diff --git a/src/Gui/QuantitySpinBox.cpp b/src/Gui/QuantitySpinBox.cpp index dd36f976a1..be0e7fa705 100644 --- a/src/Gui/QuantitySpinBox.cpp +++ b/src/Gui/QuantitySpinBox.cpp @@ -47,6 +47,7 @@ #include "Command.h" #include #include +#include #include #include #include @@ -64,13 +65,14 @@ namespace Gui { class QuantitySpinBoxPrivate { public: - QuantitySpinBoxPrivate() : + QuantitySpinBoxPrivate(QuantitySpinBox *q) : validInput(true), pendingEmit(false), unitValue(0), maximum(DOUBLE_MAX), minimum(-DOUBLE_MAX), - singleStep(1.0) + singleStep(1.0), + q_ptr(q) { } ~QuantitySpinBoxPrivate() @@ -89,6 +91,8 @@ public: bool validate(QString& input, Base::Quantity& result) const { + Q_Q(const QuantitySpinBox); + // Do not accept empty strings because the parser will consider // " unit" as "1 unit" which is not the desired behaviour (see #0004104) if (input.isEmpty()) @@ -96,30 +100,60 @@ public: bool success = false; QString tmp = input; - int pos = 0; - QValidator::State state; - Base::Quantity res = validateAndInterpret(tmp, pos, state); - res.setFormat(quantity.getFormat()); - if (state == QValidator::Acceptable) { - success = true; - result = res; - input = tmp; - } - else if (state == QValidator::Intermediate) { - tmp = tmp.trimmed(); - tmp += QLatin1Char(' '); - tmp += unitStr; - Base::Quantity res2 = validateAndInterpret(tmp, pos, state); - res2.setFormat(quantity.getFormat()); + + auto validateInput = [&](QString& tmp) -> QValidator::State { + int pos = 0; + QValidator::State state; + Base::Quantity res = validateAndInterpret(tmp, pos, state); + res.setFormat(quantity.getFormat()); if (state == QValidator::Acceptable) { success = true; - result = res2; + result = res; input = tmp; } + return state; + }; + + QValidator::State state = validateInput(tmp); + if (state == QValidator::Intermediate) { + if (!q->hasExpression()) { + tmp = tmp.trimmed(); + tmp += QLatin1Char(' '); + tmp += unitStr; + validateInput(tmp); + } + else { + // Accept the expression as it is but try to add the right unit string + success = true; + + Base::Quantity quantity; + double value; + if (parseString(input, quantity, value)) { + quantity.setUnit(unit); + result = quantity; + + // Now translate the text into the unit system + input = Base::UnitsApi::schemaTranslate(result); + } + } } return success; } + bool parseString(const QString& str, Base::Quantity& result, double& value) const + { + try { + QString copy = str; + copy.remove(locale.groupSeparator()); + + result = Base::Quantity::parse(copy); + value = result.getValue(); + return true; + } + catch (Base::Exception&) { + return false; + } + } Base::Quantity validateAndInterpret(QString& input, int& pos, QValidator::State& state) const { Base::Quantity res; @@ -199,24 +233,13 @@ public: } } - bool ok = false; - double value = min; - if (locale.negativeSign() != QLatin1Char('-')) copy.replace(locale.negativeSign(), QLatin1Char('-')); if (locale.positiveSign() != QLatin1Char('+')) copy.replace(locale.positiveSign(), QLatin1Char('+')); - try { - QString copy2 = copy; - copy2.remove(locale.groupSeparator()); - - res = Base::Quantity::parse(copy2); - value = res.getValue(); - ok = true; - } - catch (Base::Exception&) { - } + double value = min; + bool ok = parseString(copy, res, value); if (!ok) { // input may not be finished @@ -284,14 +307,16 @@ end: double maximum; double minimum; double singleStep; + QuantitySpinBox *q_ptr; std::unique_ptr scheme; + Q_DECLARE_PUBLIC(QuantitySpinBox) }; } QuantitySpinBox::QuantitySpinBox(QWidget *parent) : QAbstractSpinBox(parent), ExpressionSpinBox(this), - d_ptr(new QuantitySpinBoxPrivate()) + d_ptr(new QuantitySpinBoxPrivate(this)) { d_ptr->locale = locale(); this->setContextMenuPolicy(Qt::DefaultContextMenu);