From 7e25a27a0cb1f68f382aadf355209b7c2c4d75e5 Mon Sep 17 00:00:00 2001 From: Roman Telezhynskyi Date: Fri, 24 Jul 2015 13:06:39 +0300 Subject: [PATCH] Block wrong formula and don't write to file. --HG-- branch : feature --- src/app/tape/tmainwindow.cpp | 174 ++++++++++++++++-- src/app/tape/tmainwindow.h | 4 +- .../valentina/xml/vindividualmeasurements.cpp | 2 +- .../valentina/xml/vstandardmeasurements.cpp | 2 +- src/libs/vformat/vmeasurements.cpp | 72 ++++++++ src/libs/vformat/vmeasurements.h | 4 + .../vpatterndb/variables/vmeasurement.cpp | 22 ++- src/libs/vpatterndb/variables/vmeasurement.h | 9 +- .../vpatterndb/variables/vmeasurement_p.h | 14 +- 9 files changed, 275 insertions(+), 28 deletions(-) diff --git a/src/app/tape/tmainwindow.cpp b/src/app/tape/tmainwindow.cpp index 3b5d946ad..46376feb8 100644 --- a/src/app/tape/tmainwindow.cpp +++ b/src/app/tape/tmainwindow.cpp @@ -1,4 +1,4 @@ -/************************************************************************ +/************************************************************************ ** ** @file tmainwindow.cpp ** @author Roman Telezhynskyi @@ -444,11 +444,11 @@ void TMainWindow::AddCustom() VMeasurement *meash; if (mType == MeasurementsType::Standard) { - meash = new VMeasurement(name, 0, 0, 0); + meash = new VMeasurement(currentRow, name, 0, 0, 0); } else { - meash = new VMeasurement(data, currentRow, name, 0, "0"); + meash = new VMeasurement(data, currentRow, name, 0, "0", true); } data->AddVariable(name, meash); @@ -507,7 +507,11 @@ void TMainWindow::ShowMData() QTableWidgetItem *nameField = ui->tableWidget->item(ui->tableWidget->currentRow(), 0); QSharedPointer meash = data->GetVariable(nameField->text()); + ui->lineEditName->blockSignals(true); ui->lineEditName->setText(ClearCustomName(meash->GetName())); + ui->lineEditName->blockSignals(false); + + ui->plainTextEditDescription->blockSignals(true); if (meash->IsCustom()) { ui->plainTextEditDescription->setPlainText(meash->GetDescription()); @@ -517,19 +521,44 @@ void TMainWindow::ShowMData() //Show from known description ui->plainTextEditDescription->setPlainText(""); } + ui->plainTextEditDescription->blockSignals(false); if (mType == MeasurementsType::Standard) { + ui->labelCalculatedValue->blockSignals(true); + ui->spinBoxBaseValue->blockSignals(true); + ui->spinBoxInSizes->blockSignals(true); + ui->spinBoxInHeights->blockSignals(true); + ui->labelCalculatedValue->setText(QString().setNum(data->GetTableValue(nameField->text(), mType))); ui->spinBoxBaseValue->setValue(static_cast(meash->GetBase())); ui->spinBoxInSizes->setValue(static_cast(meash->GetKsize())); ui->spinBoxInHeights->setValue(static_cast(meash->GetKheight())); + + ui->labelCalculatedValue->blockSignals(false); + ui->spinBoxBaseValue->blockSignals(false); + ui->spinBoxInSizes->blockSignals(false); + ui->spinBoxInHeights->blockSignals(false); } else { - this->formulaBaseHeight = ui->plainTextEditFormula->height(); EvalFormula(meash->GetFormula(), meash->GetData(), ui->labelCalculatedValue); - ui->plainTextEditFormula->setPlainText(qApp->TrVars()->FormulaToUser(meash->GetFormula())); + + ui->plainTextEditFormula->blockSignals(true); + + QString formula; + try + { + formula = qApp->TrVars()->FormulaToUser(meash->GetFormula()); + } + catch (qmu::QmuParserError &e) + { + Q_UNUSED(e); + formula = meash->GetFormula(); + } + + ui->plainTextEditFormula->setPlainText(formula); + ui->plainTextEditFormula->blockSignals(false); } if (m->ReadOnly()) @@ -540,10 +569,15 @@ void TMainWindow::ShowMData() { MFields(true); - if (not meash->IsCustom()) + if (meash->IsCustom()) { - ui->plainTextEditDescription->setEnabled(false); - ui->lineEditName->setEnabled(false); + ui->plainTextEditDescription->setReadOnly(false); + ui->lineEditName->setReadOnly(false); + } + else + { + ui->plainTextEditDescription->setReadOnly(false); + ui->lineEditName->setReadOnly(false); } } } @@ -601,10 +635,12 @@ void TMainWindow::SaveMName() MeasurementsWasSaved(false); RefreshData(); + ui->tableWidget->blockSignals(true); ui->tableWidget->selectRow(row); ui->tableWidget->resizeColumnsToContents(); ui->tableWidget->resizeRowsToContents(); ui->tableWidget->horizontalHeader()->setStretchLastSection(true); + ui->tableWidget->blockSignals(false); } else { @@ -623,16 +659,56 @@ void TMainWindow::SaveMValue() } QTableWidgetItem *nameField = ui->tableWidget->item(ui->tableWidget->currentRow(), 0); - m->SetMValue(nameField->text(), ui->plainTextEditFormula->toPlainText()); + + // Replace line return character with spaces for calc if exist + QString text = ui->plainTextEditFormula->toPlainText(); + text.replace("\n", " "); + + QTableWidgetItem *formulaField = ui->tableWidget->item(ui->tableWidget->currentRow(), 2); + if (formulaField->text() == text) + { + return; + } + + if (text.isEmpty()) + { + const QString postfix = VDomDocument::UnitsToStr(mUnit);//Show unit in dialog lable (cm, mm or inch) + ui->labelCalculatedValue->setText(tr("Error") + " (" + postfix + "). " + tr("Empty field.")); + return; + } + + QString formula; + try + { + // Translate to internal look. + formula = qApp->TrVars()->FormulaFromUser(text, true); + QSharedPointer meash = data->GetVariable(nameField->text()); + EvalFormula(formula, meash->GetData(), ui->labelCalculatedValue); + } + catch (qmu::QmuParserError &e) + { + const QString postfix = VDomDocument::UnitsToStr(mUnit);//Show unit in dialog lable (cm, mm or inch) + ui->labelCalculatedValue->setText(tr("Error") + " (" + postfix + "). " + + tr("Parser error: %1").arg(e.GetMsg())); + return; + } + + m->SetMValue(nameField->text(), formula); MeasurementsWasSaved(false); + const QTextCursor cursor = ui->plainTextEditFormula->textCursor(); + RefreshData(); + ui->tableWidget->blockSignals(true); ui->tableWidget->selectRow(row); ui->tableWidget->resizeColumnsToContents(); ui->tableWidget->resizeRowsToContents(); ui->tableWidget->horizontalHeader()->setStretchLastSection(true); + ui->tableWidget->blockSignals(false); + + ui->plainTextEditFormula->setTextCursor(cursor); } //--------------------------------------------------------------------------------------------------------------------- @@ -719,12 +795,18 @@ void TMainWindow::SaveMDescription() MeasurementsWasSaved(false); + const QTextCursor cursor = ui->plainTextEditDescription->textCursor(); + RefreshData(); + ui->tableWidget->blockSignals(true); ui->tableWidget->selectRow(row); ui->tableWidget->resizeColumnsToContents(); ui->tableWidget->resizeRowsToContents(); ui->tableWidget->horizontalHeader()->setStretchLastSection(true); + ui->tableWidget->blockSignals(false); + + ui->plainTextEditDescription->setTextCursor(cursor); } //--------------------------------------------------------------------------------------------------------------------- @@ -863,7 +945,9 @@ void TMainWindow::InitWindow() connect(ui->plainTextEditNotes, &QPlainTextEdit::textChanged, this, &TMainWindow::SaveNotes); connect(ui->pushButtonGrow, &QPushButton::clicked, this, &TMainWindow::DeployFormula); - connect(ui->plainTextEditFormula, &QPlainTextEdit::textChanged, this, &TMainWindow::SaveMValue); + this->formulaBaseHeight = ui->plainTextEditFormula->height(); + connect(ui->plainTextEditFormula, &QPlainTextEdit::textChanged, this, &TMainWindow::SaveMValue, + Qt::UniqueConnection); } ui->actionAddCustom->setEnabled(true); @@ -995,7 +1079,7 @@ bool TMainWindow::MaybeSave() } //--------------------------------------------------------------------------------------------------------------------- -void TMainWindow::AddCell(const QString &text, int row, int column) +void TMainWindow::AddCell(const QString &text, int row, int column, bool ok) { QTableWidgetItem *item = new QTableWidgetItem(text); item->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter); @@ -1005,6 +1089,13 @@ void TMainWindow::AddCell(const QString &text, int row, int column) flags &= ~(Qt::ItemIsEditable); // reset/clear the flag item->setFlags(flags); + if (not ok) + { + QBrush brush = item->foreground(); + brush.setColor(Qt::red); + item->setForeground(brush); + } + ui->tableWidget->setItem(row, column, item); } @@ -1051,7 +1142,68 @@ void TMainWindow::SetDefaultSize(int value) //--------------------------------------------------------------------------------------------------------------------- void TMainWindow::RefreshData() { + data->ClearVariables(VarType::Measurement); + m->ReadMeasurements(); + RefreshTable(); +} + +//--------------------------------------------------------------------------------------------------------------------- +void TMainWindow::RefreshTable() +{ + ui->tableWidget->blockSignals(true); + ui->tableWidget->clearContents(); + + const QMap > table = data->DataMeasurements(); + QMap > orderedTable; + QMap >::const_iterator iterMap; + for (iterMap = table.constBegin(); iterMap != table.constEnd(); ++iterMap) + { + QSharedPointer meash = iterMap.value(); + orderedTable.insert(meash->Index(), meash); + } + + qint32 currentRow = -1; + QMap >::const_iterator iMap; + ui->tableWidget->setRowCount ( orderedTable.size() ); + for (iMap = orderedTable.constBegin(); iMap != orderedTable.constEnd(); ++iMap) + { + QSharedPointer meash = iMap.value(); + currentRow++; + + if (mType == MeasurementsType::Individual) + { + AddCell(meash->GetName(), currentRow, 0); // name + AddCell(QString().setNum(*meash->GetValue()), currentRow, 1, meash->IsFormulaOk()); // calculated value + + QString formula; + try + { + formula = qApp->TrVars()->FormulaToUser(meash->GetFormula()); + } + catch (qmu::QmuParserError &e) + { + Q_UNUSED(e); + formula = meash->GetFormula(); + } + + AddCell(formula, currentRow, 2); // formula + } + else + { + AddCell(meash->GetName(), currentRow, 0); // name + AddCell(QString().setNum(data->GetTableValue(meash->GetName(), mType)), currentRow, 1, + meash->IsFormulaOk()); // calculated value + AddCell(QString().setNum(meash->GetBase()), currentRow, 3); // base value + AddCell(QString().setNum(meash->GetKsize()), currentRow, 4); // in sizes + AddCell(QString().setNum(meash->GetKheight()), currentRow, 5); // in heights + } + } + + ui->tableWidget->resizeColumnsToContents(); + ui->tableWidget->resizeRowsToContents(); + ui->tableWidget->horizontalHeader()->setStretchLastSection(true); + ui->tableWidget->blockSignals(false); } //--------------------------------------------------------------------------------------------------------------------- diff --git a/src/app/tape/tmainwindow.h b/src/app/tape/tmainwindow.h index 75d312432..2f364b95c 100644 --- a/src/app/tape/tmainwindow.h +++ b/src/app/tape/tmainwindow.h @@ -40,6 +40,7 @@ namespace Ui } class QComboBox; +class QTableWidgetItem; class TMainWindow : public QMainWindow { @@ -117,13 +118,14 @@ private: bool MaybeSave(); - void AddCell(const QString &text, int row, int column); + void AddCell(const QString &text, int row, int column, bool ok = true); QComboBox *SetGradationList(const QString &label, const QStringList &list); void SetDefaultHeight(int value); void SetDefaultSize(int value); void RefreshData(); + void RefreshTable(); void Controls(); void MFields(bool enabled); diff --git a/src/app/valentina/xml/vindividualmeasurements.cpp b/src/app/valentina/xml/vindividualmeasurements.cpp index 829e2570d..edacbcbfa 100644 --- a/src/app/valentina/xml/vindividualmeasurements.cpp +++ b/src/app/valentina/xml/vindividualmeasurements.cpp @@ -70,7 +70,7 @@ void VIndividualMeasurements::ReadMeasurement(const QDomElement &domElement, con { qreal value = GetParametrDouble(domElement, AttrValue, "0.0"); value = UnitConvertor(value, MUnit(), qApp->patternUnit()); - data->AddVariable(tag, new VMeasurement(data, 0, tag, value, qApp->TrVars()->GuiText(tag), + data->AddVariable(tag, new VMeasurement(data, 0, tag, value, "", true, qApp->TrVars()->GuiText(tag), qApp->TrVars()->Description(tag), tag)); } diff --git a/src/app/valentina/xml/vstandardmeasurements.cpp b/src/app/valentina/xml/vstandardmeasurements.cpp index 218c55e88..b490124d5 100644 --- a/src/app/valentina/xml/vstandardmeasurements.cpp +++ b/src/app/valentina/xml/vstandardmeasurements.cpp @@ -116,7 +116,7 @@ void VStandardMeasurements::ReadMeasurement(const QDomElement &domElement, const qWarning()<<"Standard table can't use inch unit."; } - data->AddVariable(tag, new VMeasurement(tag, value, size_increase, height_increase, + data->AddVariable(tag, new VMeasurement(0, tag, value, size_increase, height_increase, qApp->TrVars()->GuiText(tag), qApp->TrVars()->Description(tag), tag)); } diff --git a/src/libs/vformat/vmeasurements.cpp b/src/libs/vformat/vmeasurements.cpp index fe4dfd311..300a6f491 100644 --- a/src/libs/vformat/vmeasurements.cpp +++ b/src/libs/vformat/vmeasurements.cpp @@ -29,6 +29,8 @@ #include "vmeasurements.h" #include "../ifc/xml/vvstconverter.h" #include "../ifc/xml/vvitconverter.h" +#include "../ifc/exception/vexceptionemptyparameter.h" +#include "../vpatterndb/calculator.h" const QString VMeasurements::TagVST = QStringLiteral("vst"); const QString VMeasurements::TagVIT = QStringLiteral("vit"); @@ -157,6 +159,46 @@ void VMeasurements::MoveDown(const QString &name) } } +//--------------------------------------------------------------------------------------------------------------------- +void VMeasurements::ReadMeasurements() const +{ + const QDomNodeList list = elementsByTagName(TagMeasurement); + for (int i=0; i < list.size(); ++i) + { + const QDomElement dom = list.at(i).toElement(); + + const QString name = GetParametrString(dom, AttrName); + + QString description; + try + { + description = GetParametrString(dom, AttrDescription); + } + catch (VExceptionEmptyParameter &e) + { + Q_UNUSED(e) + } + + VMeasurement *meash; + if (type == MeasurementsType::Standard) + { + const quint32 base = GetParametrUInt(dom, AttrBase, "0"); + const quint32 ksize = GetParametrUInt(dom, AttrSizeIncrease, "0"); + const quint32 kheight = GetParametrUInt(dom, AttrHeightIncrease, "0"); + + meash = new VMeasurement(i, name, base, ksize, kheight, "", description); + } + else + { + QString formula = GetParametrString(dom, AttrValue, "0"); + bool ok = false; + const qreal value = EvalFormula(data, formula, &ok); + meash = new VMeasurement(data, i, name, value, formula, ok, "", description); + } + data->AddVariable(name, meash); + } +} + //--------------------------------------------------------------------------------------------------------------------- MeasurementsType VMeasurements::Type() const { @@ -549,3 +591,33 @@ QDomElement VMeasurements::FindM(const QString &name) const return QDomElement(); } + +//--------------------------------------------------------------------------------------------------------------------- +qreal VMeasurements::EvalFormula(VContainer *data, const QString &formula, bool *ok) const +{ + if (formula.isEmpty()) + { + *ok = true; + return 0; + } + else + { + try + { + // Replace line return character with spaces for calc if exist + QString f = formula; + f.replace("\n", " "); + Calculator *cal = new Calculator(data, type); + const qreal result = cal->EvalFormula(f); + delete cal; + + *ok = true; + return result; + } + catch (qmu::QmuParserError &e) + { + *ok = false; + return 0; + } + } +} diff --git a/src/libs/vformat/vmeasurements.h b/src/libs/vformat/vmeasurements.h index 4d036f6c8..b185f2761 100644 --- a/src/libs/vformat/vmeasurements.h +++ b/src/libs/vformat/vmeasurements.h @@ -49,6 +49,8 @@ public: void MoveUp(const QString &name); void MoveDown(const QString &name); + void ReadMeasurements() const; + MeasurementsType Type() const; Unit MUnit() const; int BaseSize() const; @@ -126,6 +128,8 @@ private: QDomElement MakeEmpty(const QString &name); QDomElement FindM(const QString &name) const; + + qreal EvalFormula(VContainer *data, const QString &formula, bool *ok) const; }; #endif // VMEASUREMENTS_H diff --git a/src/libs/vpatterndb/variables/vmeasurement.cpp b/src/libs/vpatterndb/variables/vmeasurement.cpp index cdc015f93..9e09d30ae 100644 --- a/src/libs/vpatterndb/variables/vmeasurement.cpp +++ b/src/libs/vpatterndb/variables/vmeasurement.cpp @@ -40,10 +40,10 @@ * @param description measurement full description * @param tagName measurement's tag name in file */ -VMeasurement::VMeasurement(const QString &name, const qreal &base, const qreal &ksize, +VMeasurement::VMeasurement(quint32 index, const QString &name, const qreal &base, const qreal &ksize, const qreal &kheight, const QString &gui_text, const QString &description, const QString &tagName) - :VVariable(name, base, ksize, kheight, description), d(new VMeasurementData(gui_text, tagName)) + :VVariable(name, base, ksize, kheight, description), d(new VMeasurementData(index, gui_text, tagName)) { SetType(VarType::Measurement); } @@ -57,10 +57,10 @@ VMeasurement::VMeasurement(const QString &name, const qreal &base, const qreal & * @param description measurement full description * @param tagName measurement's tag name in file */ -VMeasurement::VMeasurement(VContainer *data, quint32 id, const QString &name, const qreal &base, - const QString &formula, const QString &gui_text, const QString &description, +VMeasurement::VMeasurement(VContainer *data, quint32 index, const QString &name, const qreal &base, + const QString &formula, bool ok, const QString &gui_text, const QString &description, const QString &tagName) - :VVariable(name, base, description), d(new VMeasurementData(data, id, formula, gui_text, tagName)) + :VVariable(name, base, description), d(new VMeasurementData(data, index, formula, ok, gui_text, tagName)) { SetType(VarType::Measurement); } @@ -228,6 +228,18 @@ bool VMeasurement::IsCustom() const } } +//--------------------------------------------------------------------------------------------------------------------- +int VMeasurement::Index() const +{ + return d->index; +} + +//--------------------------------------------------------------------------------------------------------------------- +bool VMeasurement::IsFormulaOk() const +{ + return d->formulaOk; +} + //--------------------------------------------------------------------------------------------------------------------- VContainer *VMeasurement::GetData() { diff --git a/src/libs/vpatterndb/variables/vmeasurement.h b/src/libs/vpatterndb/variables/vmeasurement.h index 052bd7879..931cc5083 100644 --- a/src/libs/vpatterndb/variables/vmeasurement.h +++ b/src/libs/vpatterndb/variables/vmeasurement.h @@ -43,11 +43,11 @@ class VContainer; class VMeasurement :public VVariable { public: - VMeasurement(const QString &name, const qreal &base, const qreal &ksize, + VMeasurement(quint32 index, const QString &name, const qreal &base, const qreal &ksize, const qreal &kheight, const QString &gui_text = QString(), const QString &description = QString(), const QString &TagName = QString()); - VMeasurement(VContainer *data, quint32 id, const QString &name, const qreal &base, const QString &formula, - const QString &gui_text = QString(), const QString &description = QString(), + VMeasurement(VContainer *data, quint32 index, const QString &name, const qreal &base, const QString &formula, + bool ok, const QString &gui_text = QString(), const QString &description = QString(), const QString &TagName = QString()); VMeasurement(const VMeasurement &m); VMeasurement &operator=(const VMeasurement &m); @@ -62,6 +62,9 @@ public: bool IsCustom() const; + int Index() const; + bool IsFormulaOk() const; + VContainer *GetData(); static QStringList ListHeights(QMap heights, Unit patternUnit); diff --git a/src/libs/vpatterndb/variables/vmeasurement_p.h b/src/libs/vpatterndb/variables/vmeasurement_p.h index bd1969f95..4905d58f5 100644 --- a/src/libs/vpatterndb/variables/vmeasurement_p.h +++ b/src/libs/vpatterndb/variables/vmeasurement_p.h @@ -42,27 +42,29 @@ class VMeasurementData : public QSharedData { public: - VMeasurementData(const QString &gui_text, const QString &tagName) - :data(VContainer(nullptr, nullptr)), id(0), gui_text(gui_text), _tagName(tagName) + VMeasurementData(quint32 index, const QString &gui_text, const QString &tagName) + :data(VContainer(nullptr, nullptr)), index(index), gui_text(gui_text), _tagName(tagName), formulaOk(true) {} - VMeasurementData(VContainer *data, quint32 id, const QString &formula, const QString &gui_text, + VMeasurementData(VContainer *data, quint32 index, const QString &formula, bool ok, const QString &gui_text, const QString &tagName) - :data(*data), id(id), formula(formula), gui_text(gui_text), _tagName(tagName) + :data(*data), index(index), formula(formula), gui_text(gui_text), _tagName(tagName), formulaOk(ok) {} VMeasurementData(const VMeasurementData &m) - :QSharedData(m), data(m.data), id(m.id), formula(m.formula), gui_text(m.gui_text), _tagName(m._tagName) + :QSharedData(m), data(m.data), index(m.index), formula(m.formula), gui_text(m.gui_text), _tagName(m._tagName), + formulaOk(m.formulaOk) {} virtual ~VMeasurementData(); /** @brief description description measurement */ VContainer data; - quint32 id; + quint32 index; QString formula; QString gui_text; QString _tagName; + bool formulaOk; }; VMeasurementData::~VMeasurementData()