From a5f039dd6acb28a3f9e48c36ebbe7eec61e4a671 Mon Sep 17 00:00:00 2001 From: Ladislav Michl Date: Tue, 2 Sep 2025 23:17:22 +0200 Subject: [PATCH] Base: QuantityFormat: avoid storing formatting defaults User defined precision and fractional inch are stored on QuantityFormat construction making changes persistent to object life time. Change that so until not explicitely overriden, user defined values are always returned. Co-authored-by: Matthias Danner <28687794+matthiasdanner@users.noreply.github.com> --- src/Base/Quantity.cpp | 20 +++++++++++++++----- src/Base/Quantity.h | 16 ++++++++++------ src/Base/QuantityPyImp.cpp | 10 +++++----- src/Base/UnitsApiPy.cpp | 4 +--- src/Base/UnitsSchema.cpp | 3 ++- src/Gui/InputField.cpp | 4 ++-- src/Gui/QuantitySpinBox.cpp | 4 ++-- src/Mod/Sketcher/App/Constraint.cpp | 2 +- tests/src/Base/SchemaTests.cpp | 2 +- tests/src/Gui/QuantitySpinBox.cpp | 6 +++--- 10 files changed, 42 insertions(+), 29 deletions(-) diff --git a/src/Base/Quantity.cpp b/src/Base/Quantity.cpp index 478a2f7f0a..aad7638140 100644 --- a/src/Base/Quantity.cpp +++ b/src/Base/Quantity.cpp @@ -60,17 +60,27 @@ using Base::UnitsSchema; QuantityFormat::QuantityFormat() : option(OmitGroupSeparator | RejectGroupSeparator) , format(Fixed) - , precision(UnitsApi::getDecimals()) - , denominator(UnitsApi::getDenominator()) + , _precision(-1) + , _denominator(-1) {} QuantityFormat::QuantityFormat(QuantityFormat::NumberFormat format, int decimals) : option(OmitGroupSeparator | RejectGroupSeparator) , format(format) - , precision(decimals < 0 ? UnitsApi::getDecimals() : decimals) - , denominator(UnitsApi::getDenominator()) + , _precision(decimals) + , _denominator(-1) {} +int QuantityFormat::getPrecision() const +{ + return _precision < 0 ? UnitsApi::getDecimals() : _precision; +} + +int QuantityFormat::getDenominator() const +{ + return _denominator < 0 ? UnitsApi::getDenominator() : _denominator; +} + // ---------------------------------------------------------------------------- Quantity::Quantity() @@ -255,7 +265,7 @@ std::string Quantity::toNumber(const QuantityFormat& format) const default: break; } - ss << std::setprecision(format.precision) << myValue; + ss << std::setprecision(format.getPrecision()) << myValue; return ss.str(); } diff --git a/src/Base/Quantity.h b/src/Base/Quantity.h index 01f16609bc..a25616330e 100644 --- a/src/Base/Quantity.h +++ b/src/Base/Quantity.h @@ -49,18 +49,19 @@ struct BaseExport QuantityFormat using NumberOptions = int; NumberOptions option; NumberFormat format; - int precision; - int denominator; - inline int getDenominator() const + int getPrecision() const; + inline void setPrecision(int precision) { - return denominator; + _precision = precision; } - inline void setDenominator(int denom) + int getDenominator() const; + inline void setDenominator(int denominator) { - denominator = denom; + _denominator = denominator; } + QuantityFormat(); explicit QuantityFormat(NumberFormat format, int decimals = -1); inline char toFormat() const @@ -93,6 +94,9 @@ struct BaseExport QuantityFormat return Default; } } + +private: + int _precision, _denominator; }; /** diff --git a/src/Base/QuantityPyImp.cpp b/src/Base/QuantityPyImp.cpp index e8e97645b5..dc7b177b51 100644 --- a/src/Base/QuantityPyImp.cpp +++ b/src/Base/QuantityPyImp.cpp @@ -57,7 +57,7 @@ std::string QuantityPy::representation() const PyObject* QuantityPy::toStr(PyObject* args) const { - int prec = getQuantityPtr()->getFormat().precision; + int prec = getQuantityPtr()->getFormat().getPrecision(); if (!PyArg_ParseTuple(args, "|i", &prec)) { return nullptr; } @@ -669,9 +669,9 @@ Py::Dict QuantityPy::getFormat() const QuantityFormat fmt = getQuantityPtr()->getFormat(); Py::Dict dict; - dict.setItem("Precision", Py::Long(fmt.precision)); + dict.setItem("Precision", Py::Long(fmt.getPrecision())); dict.setItem("NumberFormat", Py::Char(fmt.toFormat())); - dict.setItem("Denominator", Py::Long(fmt.denominator)); + dict.setItem("Denominator", Py::Long(fmt.getDenominator())); return dict; } @@ -681,7 +681,7 @@ void QuantityPy::setFormat(Py::Dict arg) if (arg.hasKey("Precision")) { Py::Long prec(arg.getItem("Precision")); - fmt.precision = static_cast(prec); + fmt.setPrecision(static_cast(prec)); } if (arg.hasKey("NumberFormat")) { @@ -719,7 +719,7 @@ void QuantityPy::setFormat(Py::Dict arg) if (fracInch & (fracInch - 1)) { throw Py::ValueError("Denominator must be a power of two"); } - fmt.denominator = fracInch; + fmt.setDenominator(fracInch); } getQuantityPtr()->setFormat(fmt); diff --git a/src/Base/UnitsApiPy.cpp b/src/Base/UnitsApiPy.cpp index a688901aed..f6f8819892 100644 --- a/src/Base/UnitsApiPy.cpp +++ b/src/Base/UnitsApiPy.cpp @@ -208,9 +208,7 @@ PyObject* UnitsApi::sToNumber(PyObject* /*self*/, PyObject* args) } bool ok {}; - QuantityFormat qf; - qf.format = QuantityFormat::toFormat(format[0], &ok); - qf.precision = decimals; + QuantityFormat qf {QuantityFormat::toFormat(format[0], &ok), decimals}; if (!ok) { PyErr_SetString(PyExc_ValueError, "Invalid format string"); diff --git a/src/Base/UnitsSchema.cpp b/src/Base/UnitsSchema.cpp index 921d245dc5..da8d355c3d 100644 --- a/src/Base/UnitsSchema.cpp +++ b/src/Base/UnitsSchema.cpp @@ -98,7 +98,8 @@ UnitsSchema::toLocale(const Quantity& quant, const double factor, const std::str } auto valueString = - Lc.toString(quant.getValue() / factor, format.toFormat(), format.precision).toStdString(); + Lc.toString(quant.getValue() / factor, format.toFormat(), format.getPrecision()) + .toStdString(); auto notUnit = [](auto s) { return s.empty() || s == "°" || s == "″" || s == "′" || s == "\"" || s == "'"; diff --git a/src/Gui/InputField.cpp b/src/Gui/InputField.cpp index 2b977a17a6..80c125e517 100644 --- a/src/Gui/InputField.cpp +++ b/src/Gui/InputField.cpp @@ -563,13 +563,13 @@ QString InputField::getUnitText() int InputField::getPrecision() const { - return this->actQuantity.getFormat().precision; + return this->actQuantity.getFormat().getPrecision(); } void InputField::setPrecision(const int precision) { Base::QuantityFormat format = actQuantity.getFormat(); - format.precision = precision; + format.setPrecision(precision); actQuantity.setFormat(format); updateText(actQuantity); } diff --git a/src/Gui/QuantitySpinBox.cpp b/src/Gui/QuantitySpinBox.cpp index b7febd34e6..0b054fe2b9 100644 --- a/src/Gui/QuantitySpinBox.cpp +++ b/src/Gui/QuantitySpinBox.cpp @@ -743,14 +743,14 @@ bool QuantitySpinBox::isCheckedRangeInExpresion() const int QuantitySpinBox::decimals() const { Q_D(const QuantitySpinBox); - return d->quantity.getFormat().precision; + return d->quantity.getFormat().getPrecision(); } void QuantitySpinBox::setDecimals(int v) { Q_D(QuantitySpinBox); Base::QuantityFormat f = d->quantity.getFormat(); - f.precision = v; + f.setPrecision(v); d->quantity.setFormat(f); updateText(d->quantity); } diff --git a/src/Mod/Sketcher/App/Constraint.cpp b/src/Mod/Sketcher/App/Constraint.cpp index 0fc5fe0a2e..9734ac9195 100644 --- a/src/Mod/Sketcher/App/Constraint.cpp +++ b/src/Mod/Sketcher/App/Constraint.cpp @@ -136,7 +136,7 @@ Quantity Constraint::getPresentationValue() const QuantityFormat format = quantity.getFormat(); format.option = QuantityFormat::None; format.format = QuantityFormat::Default; - format.precision = 6; // QString's default + format.setPrecision(6); // QString's default quantity.setFormat(format); return quantity; } diff --git a/tests/src/Base/SchemaTests.cpp b/tests/src/Base/SchemaTests.cpp index 7ffc09be5d..bb4e5c14d0 100644 --- a/tests/src/Base/SchemaTests.cpp +++ b/tests/src/Base/SchemaTests.cpp @@ -69,7 +69,7 @@ protected: UnitsApi::setSchema(name); Quantity quantity {value, unit}; QuantityFormat format = quantity.getFormat(); - format.precision = precision; + format.setPrecision(precision); quantity.setFormat(format); return quantity.getSafeUserString(); } diff --git a/tests/src/Gui/QuantitySpinBox.cpp b/tests/src/Gui/QuantitySpinBox.cpp index 6b1fb34b2b..309c668353 100644 --- a/tests/src/Gui/QuantitySpinBox.cpp +++ b/tests/src/Gui/QuantitySpinBox.cpp @@ -51,18 +51,18 @@ private Q_SLOTS: { auto quant = qsb->value(); auto format = quant.getFormat(); - format.precision = 7; + format.setPrecision(7); quant.setFormat(format); qsb->setValue(quant); auto val1 = qsb->value(); - QCOMPARE(val1.getFormat().precision, 7); + QCOMPARE(val1.getFormat().getPrecision(), 7); // format shouldn't change after setting a double qsb->setValue(3.5); auto val2 = qsb->value(); - QCOMPARE(val2.getFormat().precision, 7); + QCOMPARE(val2.getFormat().getPrecision(), 7); } private: