diff --git a/src/app/container/calculator.cpp b/src/app/container/calculator.cpp index 16bdea155..350fb5b1d 100644 --- a/src/app/container/calculator.cpp +++ b/src/app/container/calculator.cpp @@ -40,20 +40,7 @@ int Calculator::iVal = -1; Calculator::Calculator(const VContainer *data) :QmuParser(), vVarVal(nullptr) { - //String with all unique symbols for supported alpabets. - // See script alphabets.py for generation and more information. - const QString symbols = QStringLiteral("ցЀĆЈVӧĎАғΕĖӅИқΝĞơРңњΥĦШҫ̆جگĮаҳѕεشԶиһνԾрυلՆӝшËՎҔPÓՖXӛӟŞӣզhëծpóӞնxßվāŁЃֆĉЋCŬđ" - "ҐГΒęҘЛΚŘġҠУGاհЫدԱҰгβطԹõлκKՁÀуςهՉÈыvیՑÐSOřӘћաőcӐթèkàѓżűðsķչøӥӔĀփїІĈЎґĐΗЖҙĘȚ" - "ΟОҡĠآΧЦتЮұİزηжԸغοоÁՀقχцÉՈيюÑՐђӋіәťӆўáŠĺѐfөըnñŰӤӨӹոľЁրăЉŭċБӸēłΔҖЙŤěΜӜDСձģΤӰ" - "ЩīņحҮбưԳصδHйԻŇμӲӴсՃمτƠщՋєLQŹՓŕÖYśÞaգĽæiŽիӓîqճöyջþĂօЄӦĊЌΑĒДҗјΙȘĚМΡéĵĢФūӚΩبĪ" - "ЬүќαذԲдҷιظԺмρՂфÇωوՊьÏՒTŚĻJբdçժlïӪղtպӫAւąЇčŃЏĕӯЗΖEțŮĝПΞأĥĹЧΦثÆӳЯIسŲԵзζԽпξكՅ" - "ÄчφNMՍӌяӢՕÔWÎŝÜџёźեägխoӒյôwĶBžսüЂĄև̈ЊČƏљΓВҕĔӮΛКĜΣТҥĤکЪƯخγвŅԴŪضλкԼĴσтÅՄنъÍՌR" - "ӕՔZÝŜbåդﻩjíլļrӵմzýռپêЅքćچЍďӱҒЕůėژșΘØҚНğńءΠFҢХħΨҪЭųįҶرҲеԷňعθҺнԿفπÂхՇψÊэšՏÒU" - "əÚѝŻşҤӑâeէŐımկòuշÕúտŔ"); - - // Defining identifier character sets - DefineNameChars(QStringLiteral("0123456789_") + symbols); - DefineOprtChars(symbols + QStringLiteral("+-*^/?<>=#!$%&|~'_")); + InitCharacterSets(); // Add variables InitVariables(data); @@ -62,8 +49,35 @@ Calculator::Calculator(const VContainer *data) DefinePostfixOprt(cm_Oprt, CmUnit); DefinePostfixOprt(mm_Oprt, MmUnit); DefinePostfixOprt(in_Oprt, InchUnit); +} +//--------------------------------------------------------------------------------------------------------------------- +Calculator::Calculator(const QString &formula, bool fromUser) + :QmuParser(), vVarVal(nullptr) +{ + InitCharacterSets(); SetVarFactory(AddVariable, this); + + // Add unary operators + if(fromUser) + { + DefinePostfixOprt(qApp->PostfixOperator(cm_Oprt), CmUnit); + DefinePostfixOprt(qApp->PostfixOperator(mm_Oprt), MmUnit); + DefinePostfixOprt(qApp->PostfixOperator(in_Oprt), InchUnit); + + QLocale loc = QLocale(); + SetDecSep(loc.decimalPoint().toLatin1()); + SetThousandsSep(loc.groupSeparator().toLatin1()); + SetArgSep(';'); + } + else + { + DefinePostfixOprt(cm_Oprt, CmUnit); + DefinePostfixOprt(mm_Oprt, MmUnit); + DefinePostfixOprt(in_Oprt, InchUnit); + } + + SetExpr(formula); } Calculator::~Calculator() @@ -210,6 +224,24 @@ void Calculator::InitVariables(const VContainer *data) } } +void Calculator::InitCharacterSets() +{ + //String with all unique symbols for supported alpabets. + // See script alphabets.py for generation and more information. + const QString symbols = QStringLiteral("ցЀĆЈVӧĎАғΕĖӅИқΝĞơРңњΥĦШҫ̆جگĮаҳѕεشԶиһνԾрυلՆӝшËՎҔPÓՖXӛӟŞӣզhëծpóӞնxßվāŁЃֆĉЋCŬđ" + "ҐГΒęҘЛΚŘġҠУGاհЫدԱҰгβطԹõлκKՁÀуςهՉÈыvیՑÐSOřӘћաőcӐթèkàѓżűðsķչøӥӔĀփїІĈЎґĐΗЖҙĘȚ" + "ΟОҡĠآΧЦتЮұİزηжԸغοоÁՀقχцÉՈيюÑՐђӋіәťӆўáŠĺѐfөըnñŰӤӨӹոľЁրăЉŭċБӸēłΔҖЙŤěΜӜDСձģΤӰ" + "ЩīņحҮбưԳصδHйԻŇμӲӴсՃمτƠщՋєLQŹՓŕÖYśÞaգĽæiŽիӓîqճöyջþĂօЄӦĊЌΑĒДҗјΙȘĚМΡéĵĢФūӚΩبĪ" + "ЬүќαذԲдҷιظԺмρՂфÇωوՊьÏՒTŚĻJբdçժlïӪղtպӫAւąЇčŃЏĕӯЗΖEțŮĝПΞأĥĹЧΦثÆӳЯIسŲԵзζԽпξكՅ" + "ÄчφNMՍӌяӢՕÔWÎŝÜџёźեägխoӒյôwĶBžսüЂĄև̈ЊČƏљΓВҕĔӮΛКĜΣТҥĤکЪƯخγвŅԴŪضλкԼĴσтÅՄنъÍՌR" + "ӕՔZÝŜbåդﻩjíլļrӵմzýռپêЅքćچЍďӱҒЕůėژșΘØҚНğńءΠFҢХħΨҪЭųįҶرҲеԷňعθҺнԿفπÂхՇψÊэšՏÒU" + "əÚѝŻşҤӑâeէŐımկòuշÕúտŔ"); + + // Defining identifier character sets + DefineNameChars(QStringLiteral("0123456789_") + symbols); + DefineOprtChars(symbols + QStringLiteral("+-*^/?<>=#!$%&|~'_")); +} + //--------------------------------------------------------------------------------------------------------------------- qreal Calculator::CmUnit(qreal val) { diff --git a/src/app/container/calculator.h b/src/app/container/calculator.h index ddea36ab2..2961f6498 100644 --- a/src/app/container/calculator.h +++ b/src/app/container/calculator.h @@ -37,7 +37,8 @@ using namespace qmu; class Calculator:public QmuParser { public: - explicit Calculator(const VContainer *data); + Calculator(const VContainer *data); + Calculator(const QString &formula, bool fromUser = true); ~Calculator(); qreal EvalFormula(const QString &formula); private: @@ -45,6 +46,7 @@ private: qreal *vVarVal; static int iVal; void InitVariables(const VContainer *data); + void InitCharacterSets(); static qreal CmUnit(qreal val); static qreal MmUnit(qreal val); static qreal InchUnit(qreal val); diff --git a/src/app/dialogs/tools/dialogalongline.cpp b/src/app/dialogs/tools/dialogalongline.cpp index c6f643d9d..3d7b1ec2b 100644 --- a/src/app/dialogs/tools/dialogalongline.cpp +++ b/src/app/dialogs/tools/dialogalongline.cpp @@ -119,7 +119,7 @@ void DialogAlongLine::setFirstPointId(const quint32 &value, const quint32 &id) //--------------------------------------------------------------------------------------------------------------------- void DialogAlongLine::setFormula(const QString &value) { - formula = value; + formula = qApp->FormulaToUser(value); ui->lineEditFormula->setText(formula); } diff --git a/src/app/dialogs/tools/dialogalongline.h b/src/app/dialogs/tools/dialogalongline.h index 947c31793..2df9c634d 100644 --- a/src/app/dialogs/tools/dialogalongline.h +++ b/src/app/dialogs/tools/dialogalongline.h @@ -157,7 +157,7 @@ inline QString DialogAlongLine::getTypeLine() const inline QString DialogAlongLine::getFormula() const { - return formula; + return qApp->FormulaFromUser(formula); } inline quint32 DialogAlongLine::getFirstPointId() const diff --git a/src/app/dialogs/tools/dialogbisector.cpp b/src/app/dialogs/tools/dialogbisector.cpp index 35050a844..70e939376 100644 --- a/src/app/dialogs/tools/dialogbisector.cpp +++ b/src/app/dialogs/tools/dialogbisector.cpp @@ -128,7 +128,7 @@ void DialogBisector::setTypeLine(const QString &value) //--------------------------------------------------------------------------------------------------------------------- void DialogBisector::setFormula(const QString &value) { - formula = value; + formula = qApp->FormulaToUser(value); ui->lineEditFormula->setText(formula); } diff --git a/src/app/dialogs/tools/dialogbisector.h b/src/app/dialogs/tools/dialogbisector.h index 89fab7a10..3ec065bf5 100644 --- a/src/app/dialogs/tools/dialogbisector.h +++ b/src/app/dialogs/tools/dialogbisector.h @@ -167,7 +167,7 @@ inline QString DialogBisector::getTypeLine() const inline QString DialogBisector::getFormula() const { - return formula; + return qApp->FormulaFromUser(formula); } inline quint32 DialogBisector::getFirstPointId() const diff --git a/src/app/dialogs/tools/dialogcutarc.cpp b/src/app/dialogs/tools/dialogcutarc.cpp index 55844e496..5ab00d16e 100644 --- a/src/app/dialogs/tools/dialogcutarc.cpp +++ b/src/app/dialogs/tools/dialogcutarc.cpp @@ -91,7 +91,7 @@ void DialogCutArc::setArcId(const quint32 &value, const quint32 &id) //--------------------------------------------------------------------------------------------------------------------- void DialogCutArc::setFormula(const QString &value) { - formula = value; + formula = qApp->FormulaToUser(value); ui->lineEditFormula->setText(formula); } diff --git a/src/app/dialogs/tools/dialogcutarc.h b/src/app/dialogs/tools/dialogcutarc.h index 8f9d93ed7..e9df0964d 100644 --- a/src/app/dialogs/tools/dialogcutarc.h +++ b/src/app/dialogs/tools/dialogcutarc.h @@ -64,7 +64,7 @@ public: * @brief getFormula return string with formula length * @return formula */ - QString getFormula() const {return formula;} + QString getFormula() const {return qApp->FormulaFromUser(formula);} /** * @brief setFormula set string with formula length * @param value string with formula diff --git a/src/app/dialogs/tools/dialogcutspline.cpp b/src/app/dialogs/tools/dialogcutspline.cpp index 1730ba10e..e51c07ff5 100644 --- a/src/app/dialogs/tools/dialogcutspline.cpp +++ b/src/app/dialogs/tools/dialogcutspline.cpp @@ -70,7 +70,7 @@ void DialogCutSpline::setPointName(const QString &value) //--------------------------------------------------------------------------------------------------------------------- void DialogCutSpline::setFormula(const QString &value) { - formula = value; + formula = qApp->FormulaToUser(value); ui->lineEditFormula->setText(formula); } diff --git a/src/app/dialogs/tools/dialogcutspline.h b/src/app/dialogs/tools/dialogcutspline.h index 35041872f..916bda69f 100644 --- a/src/app/dialogs/tools/dialogcutspline.h +++ b/src/app/dialogs/tools/dialogcutspline.h @@ -119,7 +119,7 @@ inline QString DialogCutSpline::getPointName() const inline QString DialogCutSpline::getFormula() const { - return formula; + return qApp->FormulaFromUser(formula); } inline quint32 DialogCutSpline::getSplineId() const diff --git a/src/app/dialogs/tools/dialogcutsplinepath.cpp b/src/app/dialogs/tools/dialogcutsplinepath.cpp index fee2d8f04..980c7da32 100644 --- a/src/app/dialogs/tools/dialogcutsplinepath.cpp +++ b/src/app/dialogs/tools/dialogcutsplinepath.cpp @@ -71,7 +71,7 @@ void DialogCutSplinePath::setPointName(const QString &value) //--------------------------------------------------------------------------------------------------------------------- void DialogCutSplinePath::setFormula(const QString &value) { - formula = value; + formula = qApp->FormulaToUser(value); ui->lineEditFormula->setText(formula); } diff --git a/src/app/dialogs/tools/dialogcutsplinepath.h b/src/app/dialogs/tools/dialogcutsplinepath.h index 417e85d94..70b84ae67 100644 --- a/src/app/dialogs/tools/dialogcutsplinepath.h +++ b/src/app/dialogs/tools/dialogcutsplinepath.h @@ -119,7 +119,7 @@ inline QString DialogCutSplinePath::getPointName() const inline QString DialogCutSplinePath::getFormula() const { - return formula; + return qApp->FormulaFromUser(formula); } inline quint32 DialogCutSplinePath::getSplinePathId() const diff --git a/src/app/dialogs/tools/dialogendline.cpp b/src/app/dialogs/tools/dialogendline.cpp index b9b1b4279..3095d193e 100644 --- a/src/app/dialogs/tools/dialogendline.cpp +++ b/src/app/dialogs/tools/dialogendline.cpp @@ -89,7 +89,7 @@ void DialogEndLine::setTypeLine(const QString &value) //--------------------------------------------------------------------------------------------------------------------- void DialogEndLine::setFormula(const QString &value) { - formula = value; + formula = qApp->FormulaToUser(value); ui->lineEditFormula->setText(formula); } diff --git a/src/app/dialogs/tools/dialogendline.h b/src/app/dialogs/tools/dialogendline.h index 7dfc82b03..6d1ae791a 100644 --- a/src/app/dialogs/tools/dialogendline.h +++ b/src/app/dialogs/tools/dialogendline.h @@ -152,7 +152,7 @@ inline QString DialogEndLine::getTypeLine() const inline QString DialogEndLine::getFormula() const { - return formula; + return qApp->FormulaFromUser(formula); } inline qreal DialogEndLine::getAngle() const diff --git a/src/app/dialogs/tools/dialognormal.cpp b/src/app/dialogs/tools/dialognormal.cpp index 81ebf9dd3..0c0034970 100644 --- a/src/app/dialogs/tools/dialognormal.cpp +++ b/src/app/dialogs/tools/dialognormal.cpp @@ -128,7 +128,7 @@ void DialogNormal::setAngle(const qreal &value) //--------------------------------------------------------------------------------------------------------------------- void DialogNormal::setFormula(const QString &value) { - formula = value; + formula = qApp->FormulaToUser(value); ui->lineEditFormula->setText(formula); } diff --git a/src/app/dialogs/tools/dialognormal.h b/src/app/dialogs/tools/dialognormal.h index a47aae457..7140dec48 100644 --- a/src/app/dialogs/tools/dialognormal.h +++ b/src/app/dialogs/tools/dialognormal.h @@ -171,7 +171,7 @@ inline QString DialogNormal::getTypeLine() const inline QString DialogNormal::getFormula() const { - return formula; + return qApp->FormulaFromUser(formula); } inline qreal DialogNormal::getAngle() const diff --git a/src/app/dialogs/tools/dialogshoulderpoint.cpp b/src/app/dialogs/tools/dialogshoulderpoint.cpp index 65fb7f069..0b3ee34a3 100644 --- a/src/app/dialogs/tools/dialogshoulderpoint.cpp +++ b/src/app/dialogs/tools/dialogshoulderpoint.cpp @@ -145,7 +145,7 @@ void DialogShoulderPoint::setP1Line(const quint32 &value, const quint32 &id) //--------------------------------------------------------------------------------------------------------------------- void DialogShoulderPoint::setFormula(const QString &value) { - formula = value; + formula = qApp->FormulaToUser(value); ui->lineEditFormula->setText(formula); } diff --git a/src/app/dialogs/tools/dialogshoulderpoint.h b/src/app/dialogs/tools/dialogshoulderpoint.h index 9d9130eb6..42680329f 100644 --- a/src/app/dialogs/tools/dialogshoulderpoint.h +++ b/src/app/dialogs/tools/dialogshoulderpoint.h @@ -172,7 +172,7 @@ inline QString DialogShoulderPoint::getTypeLine() const inline QString DialogShoulderPoint::getFormula() const { - return formula; + return qApp->FormulaFromUser(formula); } inline quint32 DialogShoulderPoint::getP1Line() const diff --git a/src/app/dialogs/tools/dialogtool.cpp b/src/app/dialogs/tools/dialogtool.cpp index 130a6ae4e..a2a4364e4 100644 --- a/src/app/dialogs/tools/dialogtool.cpp +++ b/src/app/dialogs/tools/dialogtool.cpp @@ -332,8 +332,9 @@ void DialogTool::Eval(QLineEdit *edit, bool &flag, QTimer *timer, QLabel *label) { try { + const QString formula = qApp->FormulaFromUser(edit->text()); Calculator cal(data); - const qreal result = cal.EvalFormula(edit->text()); + const qreal result = cal.EvalFormula(formula); label->setText(QString().setNum(result)); flag = true; @@ -345,7 +346,7 @@ void DialogTool::Eval(QLineEdit *edit, bool &flag, QTimer *timer, QLabel *label) label->setText(tr("Error")); flag = false; palette.setColor(labelEditFormula->foregroundRole(), Qt::red); - emit ToolTip(e.GetMsg()); + emit ToolTip("Parser error: "+e.GetMsg()); qDebug() << "\nMath parser error:\n" << "--------------------------------------\n" << "Message: " << e.GetMsg() << "\n" diff --git a/src/app/widgets/vapplication.cpp b/src/app/widgets/vapplication.cpp index 973cb8055..b93e6ec9a 100644 --- a/src/app/widgets/vapplication.cpp +++ b/src/app/widgets/vapplication.cpp @@ -37,6 +37,8 @@ #include #include +#include + const qreal VApplication::PrintDPI = 96.0; #define DefWidth 1.2//mm @@ -632,6 +634,7 @@ void VApplication::InitFunctions() functions.insert(avg_F, VTranslation::translate(context, avg_F, QStringLiteral("mean value of all arguments"))); } +//--------------------------------------------------------------------------------------------------------------------- void VApplication::InitPostfixOperators() { const QString context = QStringLiteral("PostfixOperators"); @@ -641,6 +644,86 @@ void VApplication::InitPostfixOperators() postfixOperators.insert(in_Oprt, VTranslation::translate(context, in_Oprt, QStringLiteral("inch"))); } +//--------------------------------------------------------------------------------------------------------------------- +bool VApplication::Measurements(QString &newFormula, int position, const QString &token) +{ + QMap::const_iterator i = measurements.constBegin(); + while (i != measurements.constEnd()) + { + if(token == i.value().translate()) + { + newFormula.replace(position, token.length(), i.key()); + return true; + } + ++i; + } + return false; +} + +//--------------------------------------------------------------------------------------------------------------------- +bool VApplication::VariablesFromUser(QString &newFormula, int position, const QString &token) +{ + QMap::const_iterator i = variables.constBegin(); + while (i != variables.constEnd()) + { + if(token.indexOf( i.value().translate() ) == 0) + { + newFormula.replace(position, i.value().translate().length(), i.key()); + return true; + } + ++i; + } + return false; +} + +//--------------------------------------------------------------------------------------------------------------------- +bool VApplication::PostfixOperators(QString &newFormula, int position, const QString &token) +{ + QMap::const_iterator i = postfixOperators.constBegin(); + while (i != postfixOperators.constEnd()) + { + if(token == i.value().translate()) + { + newFormula.replace(position, token.length(), i.key()); + return true; + } + ++i; + } + return false; +} + +//--------------------------------------------------------------------------------------------------------------------- +bool VApplication::Functions(QString &newFormula, int position, const QString &token) +{ + QMap::const_iterator i = functions.constBegin(); + while (i != functions.constEnd()) + { + if(token == i.value().translate()) + { + newFormula.replace(position, token.length(), i.key()); + return true; + } + ++i; + } + return false; +} + +//--------------------------------------------------------------------------------------------------------------------- +bool VApplication::VariablesToUser(QString &newFormula, int position, const QString &token) +{ + QMap::const_iterator i = variables.constBegin(); + while (i != variables.constEnd()) + { + if(token.indexOf( i.key() ) == 0) + { + newFormula.replace(position, variables.value(i.key()).translate().length(), i.value().translate()); + return true; + } + ++i; + } + return false; +} + //--------------------------------------------------------------------------------------------------------------------- void VApplication::setPatternUnit(const Valentina::Units &patternUnit) { @@ -677,3 +760,175 @@ QString VApplication::Function(const QString &name) const { return functions.value(name).translate(); } + +//--------------------------------------------------------------------------------------------------------------------- +QString VApplication::PostfixOperator(const QString &name) const +{ + return postfixOperators.value(name).translate(); +} + +//--------------------------------------------------------------------------------------------------------------------- +QString VApplication::FormulaFromUser(const QString &formula) +{ + QString newFormula = formula; + + QMap tokens; + QMap numbers; + try + { + Calculator cal(formula); + tokens = cal.GetTokens(); + numbers = cal.GetNumbers(); + } + catch(qmu::QmuParserError &e) + { + qDebug() << "\nMath parser error:\n" + << "--------------------------------------\n" + << "Message: " << e.GetMsg() << "\n" + << "Expression: " << e.GetExpr() << "\n" + << "--------------------------------------"; + return newFormula; + } + + QMap::const_iterator i = tokens.constBegin(); + while (i != tokens.constEnd()) + { + if(Measurements(newFormula, i.key(), i.value())) + { + ++i; + continue; + } + + if(VariablesFromUser(newFormula, i.key(), i.value())) + { + ++i; + continue; + } + + if(PostfixOperators(newFormula, i.key(), i.value())) + { + ++i; + continue; + } + + if(Functions(newFormula, i.key(), i.value())) + { + ++i; + continue; + } + ++i; + } + + QLocale loc = QLocale(); + if(loc != QLocale(QLocale::C)) + { + QMap::const_iterator i = numbers.constBegin(); + while (i != numbers.constEnd()) + { + QLocale::setDefault(QLocale::C); + bool ok = false; + qreal d = QString(i.value()).toDouble(&ok); + if(ok == false) + { + qDebug()<<"Can't convert to double token"< tokens; + QMap numbers; + try + { + Calculator cal(formula); + tokens = cal.GetTokens(); + numbers = cal.GetNumbers(); + } + catch (qmu::QmuParserError &e) + { + qDebug() << "\nMath parser error:\n" + << "--------------------------------------\n" + << "Message: " << e.GetMsg() << "\n" + << "Expression: " << e.GetExpr() << "\n" + << "--------------------------------------"; + return newFormula; + } + + QMap::const_iterator i = tokens.constBegin(); + while (i != tokens.constEnd()) + { + if (measurements.contains(i.value())) + { + newFormula.replace(i.key(), i.value().length(), measurements.value(i.value()).translate()); + ++i; + continue; + } + + if (functions.contains(i.value())) + { + newFormula.replace(i.key(), i.value().length(), functions.value(i.value()).translate()); + ++i; + continue; + } + + if (postfixOperators.contains(i.value())) + { + newFormula.replace(i.key(), i.value().length(), postfixOperators.value(i.value()).translate()); + ++i; + continue; + } + + if(VariablesToUser(newFormula, i.key(), i.value())) + { + ++i; + continue; + } + + } + + QLocale loc = QLocale(); + if(loc != QLocale::C) + { + QMap::const_iterator i = numbers.constBegin(); + while (i != numbers.constEnd()) + { + bool ok = false; + qreal d = QString(i.value()).toDouble(&ok); + if(ok == false) + { + qDebug()<<"Can't convert to double token"<