From 3358f9dbc79370fbc1f6a34f00c1e36813625a72 Mon Sep 17 00:00:00 2001 From: Roman Telezhynskyi Date: Thu, 15 Oct 2015 15:37:10 +0300 Subject: [PATCH] Resolved issue #382. Add 'Create from existing file' option in Tape, Create/Edit. --HG-- branch : develop --- src/app/tape/tmainwindow.cpp | 149 ++++++++++++++++++ src/app/tape/tmainwindow.h | 3 + src/app/tape/tmainwindow.ui | 12 ++ src/libs/qmuparser/qmuparser.pro | 2 +- src/libs/qmuparser/qmutokenparser.cpp | 18 ++- src/libs/vformat/vmeasurements.cpp | 19 +++ src/libs/vformat/vmeasurements.h | 1 + src/test/ValentinaTest/tst_qmutokenparser.cpp | 3 + 8 files changed, 203 insertions(+), 4 deletions(-) diff --git a/src/app/tape/tmainwindow.cpp b/src/app/tape/tmainwindow.cpp index 7c4e21fa3..9e2c9b86b 100644 --- a/src/app/tape/tmainwindow.cpp +++ b/src/app/tape/tmainwindow.cpp @@ -385,6 +385,28 @@ void TMainWindow::OpenTemplate() } } +//--------------------------------------------------------------------------------------------------------------------- +void TMainWindow::CreateFromExisting() +{ + if (m == nullptr) + { + const QString filter = tr("Individual measurements (*.vit)"); + //Use standard path to standard measurements + const QString pathTo = qApp->TapeSettings()->GetPathIndividualMeasurements(); + const QString mPath = QFileDialog::getOpenFileName(this, tr("Select file"), pathTo, filter); + + if (not mPath.isEmpty()) + { + LoadFromExistingFile(mPath); + } + } + else + { + qApp->NewMainWindow(); + qApp->MainWindow()->CreateFromExisting(); + } +} + //--------------------------------------------------------------------------------------------------------------------- void TMainWindow::Find(const QString &term) { @@ -1557,6 +1579,7 @@ void TMainWindow::SetupMenu() connect(ui->actionOpenIndividual, &QAction::triggered, this, &TMainWindow::OpenIndividual); connect(ui->actionOpenStandard, &QAction::triggered, this, &TMainWindow::OpenStandard); connect(ui->actionOpenTemplate, &QAction::triggered, this, &TMainWindow::OpenTemplate); + connect(ui->actionCreateFromExisting, &QAction::triggered, this, &TMainWindow::CreateFromExisting); connect(ui->actionSave, &QAction::triggered, this, &TMainWindow::FileSave); ui->actionSave->setShortcuts(QKeySequence::Save); @@ -2344,6 +2367,132 @@ void TMainWindow::UpdatePatternUnit() ui->tableWidget->selectRow(row); } +//--------------------------------------------------------------------------------------------------------------------- +bool TMainWindow::LoadFromExistingFile(const QString &path) +{ + if (m == nullptr) + { + if (not QFileInfo(path).exists()) + { + qCCritical(tMainWindow, "%s", qUtf8Printable(tr("File '%1' doesn't exist!").arg(path))); + if (qApp->IsTestMode()) + { + qApp->exit(V_EX_NOINPUT); + } + return false; + } + + // Check if file already opened + QListlist = qApp->MainWindows(); + for (int i = 0; i < list.size(); ++i) + { + if (list.at(i)->CurrentFile() == path) + { + list.at(i)->activateWindow(); + close(); + return false; + } + } + + VlpCreateLock(lock, QFileInfo(path).fileName()+".lock"); + + if (not lock->IsLocked()) + { + qCCritical(tMainWindow, "%s", qUtf8Printable(tr("This file already opened in another window."))); + if (qApp->IsTestMode()) + { + qApp->exit(V_EX_NOINPUT); + } + return false; + } + + try + { + data = new VContainer(qApp->TrVars(), &mUnit); + + m = new VMeasurements(data); + m->setXMLContent(path); + + mType = m->Type(); + + if (mType == MeasurementsType::Unknown) + { + VException e(tr("File has unknown format.")); + throw e; + } + + if (mType == MeasurementsType::Standard) + { + VException e(tr("Export standard measurements not supported.")); + throw e; + } + else + { + VVITConverter converter(path); + converter.Convert(); + + VDomDocument::ValidateXML(VVITConverter::CurrentSchema, path); + } + + m->setXMLContent(path);// Read again after conversion + + if (not m->IsDefinedKnownNamesValid()) + { + VException e(tr("File contains invalid known measurement(s).")); + throw e; + } + + mUnit = m->MUnit(); + pUnit = mUnit; + + data->SetHeight(m->BaseHeight()); + data->SetSize(m->BaseSize()); + + ui->labelToolTip->setVisible(false); + ui->tabWidget->setVisible(true); + + InitWindow(); + + m->ClearForExport(); + RefreshData(); + + if (ui->tableWidget->rowCount() > 0) + { + ui->tableWidget->selectRow(0); + } + + lock.reset();// Now we can unlock the file + + GUIReadOnly(m->ReadOnly()); // Keep last + } + catch (VException &e) + { + qCCritical(tMainWindow, "%s\n\n%s\n\n%s", qUtf8Printable(tr("File error.")), + qUtf8Printable(e.ErrorMessage()), qUtf8Printable(e.DetailedInformation())); + ui->labelToolTip->setVisible(true); + ui->tabWidget->setVisible(false); + delete m; + m = nullptr; + delete data; + data = nullptr; + lock.reset(); + + if (qApp->IsTestMode()) + { + qApp->exit(V_EX_NOINPUT); + } + return false; + } + } + else + { + qApp->NewMainWindow(); + return qApp->MainWindow()->LoadFile(path); + } + + return true; +} + //--------------------------------------------------------------------------------------------------------------------- void TMainWindow::SetDecimals() { diff --git a/src/app/tape/tmainwindow.h b/src/app/tape/tmainwindow.h index 59a03904e..34ab5f677 100644 --- a/src/app/tape/tmainwindow.h +++ b/src/app/tape/tmainwindow.h @@ -68,6 +68,7 @@ public slots: void OpenIndividual(); void OpenStandard(); void OpenTemplate(); + void CreateFromExisting(); protected: virtual void closeEvent(QCloseEvent *event) Q_DECL_OVERRIDE; @@ -178,6 +179,8 @@ private: QStringList FilterMeasurements(const QStringList &mNew, const QStringList &mFilter); void UpdatePatternUnit(); + + bool LoadFromExistingFile(const QString &path); }; #endif // TMAINWINDOW_H diff --git a/src/app/tape/tmainwindow.ui b/src/app/tape/tmainwindow.ui index 1260c79d9..114476d16 100644 --- a/src/app/tape/tmainwindow.ui +++ b/src/app/tape/tmainwindow.ui @@ -724,6 +724,7 @@ + @@ -958,6 +959,17 @@ Import from a pattern + + + Create from existing ... + + + Create from existing file + + + + + diff --git a/src/libs/qmuparser/qmuparser.pro b/src/libs/qmuparser/qmuparser.pro index f2f5ca062..1c0195286 100644 --- a/src/libs/qmuparser/qmuparser.pro +++ b/src/libs/qmuparser/qmuparser.pro @@ -39,7 +39,7 @@ OBJECTS_DIR = obj include(qmuparser.pri) -VERSION = 2.3.0 +VERSION = 2.4.0 # Set "make install" command for Unix-like systems. unix:!macx{ diff --git a/src/libs/qmuparser/qmutokenparser.cpp b/src/libs/qmuparser/qmutokenparser.cpp index cb513e206..85fa0fb79 100644 --- a/src/libs/qmuparser/qmutokenparser.cpp +++ b/src/libs/qmuparser/qmutokenparser.cpp @@ -73,10 +73,14 @@ QmuTokenParser::~QmuTokenParser() * Work only with expressions in internal (C) locale. * @param formula expression for test * @return true if fomula has single number - * @throw qmu::QmuParserError if expression is incorrect. Has bad separator. */ bool QmuTokenParser::IsSingle(const QString &formula) { + if (formula.isEmpty()) + { + return false;// if don't know say no + } + QmuTokenParser *cal = new QmuTokenParser(); // Parser doesn't know any variable on this stage. So, we just use variable factory that for each unknown @@ -84,8 +88,16 @@ bool QmuTokenParser::IsSingle(const QString &formula) cal->SetVarFactory(AddVariable, cal); cal->SetSepForEval();//Reset separators options - cal->SetExpr(formula); - cal->Eval();// We don't need save result, only parse formula + try + { + cal->SetExpr(formula); + cal->Eval();// We don't need save result, only parse formula + } + catch (const qmu::QmuParserError &e) + { + Q_UNUSED(e) + return false;// something wrong with formula, say no + } QMap tokens = cal->GetTokens();// Tokens (variables, measurements) const QMap numbers = cal->GetNumbers();// All numbers in expression diff --git a/src/libs/vformat/vmeasurements.cpp b/src/libs/vformat/vmeasurements.cpp index efe575e4b..91eed876e 100644 --- a/src/libs/vformat/vmeasurements.cpp +++ b/src/libs/vformat/vmeasurements.cpp @@ -31,6 +31,7 @@ #include "../ifc/xml/vvitconverter.h" #include "../ifc/exception/vexceptionemptyparameter.h" #include "../vpatterndb/calculator.h" +#include "../qmuparser/qmutokenparser.h" const QString VMeasurements::TagVST = QStringLiteral("vst"); const QString VMeasurements::TagVIT = QStringLiteral("vit"); @@ -278,6 +279,24 @@ void VMeasurements::ReadMeasurements() const delete tempData; } +//--------------------------------------------------------------------------------------------------------------------- +void VMeasurements::ClearForExport() +{ + const QDomNodeList list = elementsByTagName(TagMeasurement); + + for (int i=0; i < list.size(); ++i) + { + QDomElement domElement = list.at(i).toElement(); + if (domElement.isNull() == false) + { + if (qmu::QmuTokenParser::IsSingle(domElement.attribute(AttrValue))) + { + SetAttribute(domElement, AttrValue, QString("0")); + } + } + } +} + //--------------------------------------------------------------------------------------------------------------------- MeasurementsType VMeasurements::Type() const { diff --git a/src/libs/vformat/vmeasurements.h b/src/libs/vformat/vmeasurements.h index c4205e400..0e7bd148c 100644 --- a/src/libs/vformat/vmeasurements.h +++ b/src/libs/vformat/vmeasurements.h @@ -54,6 +54,7 @@ public: void MoveBottom(const QString &name); void ReadMeasurements() const; + void ClearForExport(); MeasurementsType Type() const; Unit MUnit() const; diff --git a/src/test/ValentinaTest/tst_qmutokenparser.cpp b/src/test/ValentinaTest/tst_qmutokenparser.cpp index ed4076296..0ad1f84ec 100644 --- a/src/test/ValentinaTest/tst_qmutokenparser.cpp +++ b/src/test/ValentinaTest/tst_qmutokenparser.cpp @@ -49,6 +49,9 @@ void TST_QmuTokenParser::IsSingle_data() QTest::newRow("Digit and variable") << "2+a" << false; QTest::newRow("One variable twice") << "a+a" << false; QTest::newRow("Two variables") << "a+b" << false; + QTest::newRow("Empty string") << "" << false; + QTest::newRow("Several spaces") << " " << false; + QTest::newRow("Invalid formula") << "2*)))" << false; } //---------------------------------------------------------------------------------------------------------------------