From eee97f8c66a60e2faf7485d6d59a6dc425a2eca5 Mon Sep 17 00:00:00 2001 From: Michael Weghorn Date: Wed, 19 Feb 2025 17:50:39 +0100 Subject: [PATCH] tdf#130857 Formatter: Pass string to convert to double Instead of letting the implementations set for Formatter::m_aInputHdl via Formatter::SetInputHdl always retrieve the current text and parse that one, pass the text to convert as a parameter instead. Introduce a new struct Formatter::ParseResult so that both, the state (which describes whether parsing was successful and/or a handler was set) and the value can still be returned at the same time. (Link/The handlers only supports a single param. So far, the state was returned by the function result and the value was returned via an out param, but the single param is now used for an input param to pass the text.) Make it the responsibility of Formatter::ImplGetValue to pass the current text instead of having the handlers read it themselves. Rename the members accordingly: * Formatter::m_aInputHdl -> Formatter:m_aParseTextHdl * Formatter::SetInputHdl -> Formatter::SetParseTextHdl This is similar to Change-Id: I6b3fbccc89b89446a1ea367a80aeed3a7b583298 Author: Michael Weghorn Date: Tue Feb 18 20:29:20 2025 +0100 tdf#130857 Let Formatter:m_aOutputHdl convert double to text (but for the conversion the other way around) and commit 15ad64a412d80fdf05ee1783bcc277753eaa34bc Author: Michael Weghorn Date: Sat Feb 15 11:22:54 2025 +0100 tdf#130857 weld: Let SpinButton input hdl only parse value from string (which is a similar change, but in weld::SpinButton). No change in behavior is intended by this change by itself. The primary motivation is to allow reusing the logic to convert a string to a value in order to implement QtDoubleSpinBox::valueFromText for QtInstanceFormattedSpinButton. Change-Id: If6837409aadbe9cc37fdbb4c0650f5e1305229f7 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/181942 Tested-by: Jenkins Reviewed-by: Michael Weghorn --- .../uielement/spinfieldtoolbarcontroller.cxx | 10 +++---- include/vcl/formatter.hxx | 26 +++++++++++++++++-- include/vcl/weldutils.hxx | 6 ++--- vcl/inc/salvtables.hxx | 2 +- vcl/source/app/salvtables.cxx | 15 +++++------ vcl/source/app/weldutils.cxx | 6 ++--- vcl/source/control/field2.cxx | 21 ++++++++------- vcl/source/control/fmtfield.cxx | 11 ++++---- vcl/source/control/longcurr.cxx | 9 ++++--- 9 files changed, 65 insertions(+), 41 deletions(-) diff --git a/framework/source/uielement/spinfieldtoolbarcontroller.cxx b/framework/source/uielement/spinfieldtoolbarcontroller.cxx index 13ffcdc0cb44..ef180bd5d51d 100644 --- a/framework/source/uielement/spinfieldtoolbarcontroller.cxx +++ b/framework/source/uielement/spinfieldtoolbarcontroller.cxx @@ -62,7 +62,7 @@ public: DECL_LINK(ValueChangedHdl, weld::FormattedSpinButton&, void); DECL_LINK(FormatOutputHdl, double, std::optional); - DECL_LINK(ParseInputHdl, double*, TriState); + DECL_STATIC_LINK(SpinfieldControl, ParseInputHdl, const OUString&, Formatter::ParseResult); DECL_LINK(ModifyHdl, weld::Entry&, void); DECL_LINK(ActivateHdl, weld::Entry&, bool); DECL_LINK(FocusInHdl, weld::Widget&, void); @@ -85,7 +85,7 @@ SpinfieldControl::SpinfieldControl(vcl::Window* pParent, SpinfieldToolbarControl m_xWidget->connect_focus_out(LINK(this, SpinfieldControl, FocusOutHdl)); Formatter& rFormatter = m_xWidget->GetFormatter(); rFormatter.SetFormatValueHdl(LINK(this, SpinfieldControl, FormatOutputHdl)); - rFormatter.SetInputHdl(LINK(this, SpinfieldControl, ParseInputHdl)); + rFormatter.SetParseTextHdl(LINK(this, SpinfieldControl, ParseInputHdl)); m_xWidget->connect_value_changed(LINK(this, SpinfieldControl, ValueChangedHdl)); m_xWidget->connect_changed(LINK(this, SpinfieldControl, ModifyHdl)); m_xWidget->connect_activate(LINK(this, SpinfieldControl, ActivateHdl)); @@ -103,10 +103,10 @@ IMPL_LINK(SpinfieldControl, KeyInputHdl, const ::KeyEvent&, rKEvt, bool) return ChildKeyInput(rKEvt); } -IMPL_LINK(SpinfieldControl, ParseInputHdl, double*, result, TriState) +IMPL_STATIC_LINK(SpinfieldControl, ParseInputHdl, const OUString&, rText, Formatter::ParseResult) { - *result = m_xWidget->get_text().toDouble(); - return TRISTATE_TRUE; + const double fValue = rText.toDouble(); + return Formatter::ParseResult(TRISTATE_TRUE, fValue); } SpinfieldControl::~SpinfieldControl() diff --git a/include/vcl/formatter.hxx b/include/vcl/formatter.hxx index 889c20a879f8..c09d0e133cc4 100644 --- a/include/vcl/formatter.hxx +++ b/include/vcl/formatter.hxx @@ -99,6 +99,28 @@ public: UNLESS_MERGELIBS(VCL_DLLPUBLIC) static SvNumberFormatter* GetFormatter(); }; + /** + * This struct gets returned by the handlers that can be set via Formatter::SetParseTextHdl + * and describes the result of trying to convert text to a double value. + */ + struct ParseResult + { + ParseResult() + : ParseResult(TRISTATE_INDET, 0.0) + { + } + + ParseResult(TriState eState, double fValue) + : m_eState(eState) + , m_fValue(fValue) + { + } + + TriState m_eState; + // if m_eState is TRISTATE_TRUE, this contains the value + double m_fValue; + }; + protected: OUString m_sLastValidText; // Has nothing to do with the current value. It is the last text, which was valid at input (checked by CheckText, @@ -143,7 +165,7 @@ protected: bool m_bUseInputStringForFormatting; - Link m_aInputHdl; + Link m_aParseTextHdl; Link> m_aFormatValueHdl; public: @@ -242,7 +264,7 @@ public: bool TreatingAsNumber() const { return m_bTreatAsNumber; } void TreatAsNumber(bool bDoSo) { m_bTreatAsNumber = bDoSo; } - void SetInputHdl(const Link& rLink) { m_aInputHdl = rLink; } + void SetParseTextHdl(const Link& rLink) { m_aParseTextHdl = rLink; } void SetFormatValueHdl(const Link>& rLink) { m_aFormatValueHdl = rLink; } OUString FormatValue(double fValue); diff --git a/include/vcl/weldutils.hxx b/include/vcl/weldutils.hxx index 05a8ba2b22bd..8a3291c42345 100644 --- a/include/vcl/weldutils.hxx +++ b/include/vcl/weldutils.hxx @@ -285,7 +285,7 @@ public: private: DECL_DLLPRIVATE_LINK(FormatOutputHdl, double, std::optional); - DECL_DLLPRIVATE_LINK(ParseInputHdl, double*, TriState); + DECL_DLLPRIVATE_LINK(ParseInputHdl, const OUString&, Formatter::ParseResult); SAL_DLLPRIVATE void Init(); @@ -313,7 +313,7 @@ public: private: DECL_DLLPRIVATE_LINK(FormatOutputHdl, double, std::optional); - DECL_DLLPRIVATE_LINK(ParseInputHdl, double*, TriState); + DECL_DLLPRIVATE_LINK(ParseInputHdl, const OUString&, Formatter::ParseResult); DECL_DLLPRIVATE_LINK(CursorChangedHdl, weld::Entry&, void); SAL_DLLPRIVATE void Init(); @@ -346,7 +346,7 @@ public: private: DECL_DLLPRIVATE_LINK(FormatOutputHdl, double, std::optional); - DECL_DLLPRIVATE_LINK(ParseInputHdl, double*, TriState); + DECL_DLLPRIVATE_LINK(ParseInputHdl, const OUString&, Formatter::ParseResult); DECL_DLLPRIVATE_LINK(CursorChangedHdl, weld::Entry&, void); SAL_DLLPRIVATE void Init(); diff --git a/vcl/inc/salvtables.hxx b/vcl/inc/salvtables.hxx index 5be5314157c9..f9793e2d6771 100644 --- a/vcl/inc/salvtables.hxx +++ b/vcl/inc/salvtables.hxx @@ -681,7 +681,7 @@ private: DECL_LINK(UpDownHdl, SpinField&, void); DECL_LINK(LoseFocusHdl, Control&, void); DECL_LINK(OutputHdl, double, std::optional); - DECL_LINK(InputHdl, double*, TriState); + DECL_LINK(InputHdl, const OUString&, Formatter::ParseResult); DECL_LINK(ActivateHdl, Edit&, bool); public: diff --git a/vcl/source/app/salvtables.cxx b/vcl/source/app/salvtables.cxx index 89c024ab220d..172f889ccfec 100644 --- a/vcl/source/app/salvtables.cxx +++ b/vcl/source/app/salvtables.cxx @@ -5856,7 +5856,7 @@ SalInstanceSpinButton::SalInstanceSpinButton(FormattedField* pButton, SalInstanc m_xButton->SetDownHdl(LINK(this, SalInstanceSpinButton, UpDownHdl)); m_xButton->SetLoseFocusHdl(LINK(this, SalInstanceSpinButton, LoseFocusHdl)); m_rFormatter.SetFormatValueHdl(LINK(this, SalInstanceSpinButton, OutputHdl)); - m_rFormatter.SetInputHdl(LINK(this, SalInstanceSpinButton, InputHdl)); + m_rFormatter.SetParseTextHdl(LINK(this, SalInstanceSpinButton, InputHdl)); if (Edit* pEdit = m_xButton->GetSubEdit()) pEdit->SetActivateHdl(LINK(this, SalInstanceSpinButton, ActivateHdl)); else @@ -5913,7 +5913,7 @@ SalInstanceSpinButton::~SalInstanceSpinButton() pEdit->SetActivateHdl(Link()); else m_xButton->SetActivateHdl(Link()); - m_rFormatter.SetInputHdl(Link()); + m_rFormatter.SetParseTextHdl(Link()); m_rFormatter.SetFormatValueHdl(Link>()); m_xButton->SetLoseFocusHdl(Link()); m_xButton->SetDownHdl(Link()); @@ -5936,13 +5936,12 @@ IMPL_LINK(SalInstanceSpinButton, OutputHdl, double, fValue, std::optional(FormatNumber(fValue)); } - IMPL_LINK(DateFormatter, ParseInputHdl, double*, result, TriState) + IMPL_LINK(DateFormatter, ParseInputHdl, const OUString&, rText, Formatter::ParseResult) { const LocaleDataWrapper& rLocaleDataWrapper = Application::GetSettings().GetLocaleDataWrapper(); Date aResult(Date::EMPTY); - bool bRet = ::DateFormatter::TextToDate(GetEntryText(), aResult, ResolveSystemFormat(m_eFormat, rLocaleDataWrapper), + bool bRet = ::DateFormatter::TextToDate(rText, aResult, ResolveSystemFormat(m_eFormat, rLocaleDataWrapper), rLocaleDataWrapper, GetCalendarWrapper()); - if (bRet) - *result = aResult.GetDate(); - return bRet ? TRISTATE_TRUE : TRISTATE_FALSE; + double fValue = 0; + if (bRet) + fValue = aResult.GetDate(); + + return Formatter::ParseResult(bRet ? TRISTATE_TRUE : TRISTATE_FALSE, fValue); } } @@ -3148,16 +3150,17 @@ namespace weld return std::optional(FormatNumber(fValue)); } - IMPL_LINK(TimeFormatter, ParseInputHdl, double*, result, TriState) + IMPL_LINK(TimeFormatter, ParseInputHdl, const OUString&, rText, Formatter::ParseResult) { const LocaleDataWrapper& rLocaleDataWrapper = Application::GetSettings().GetLocaleDataWrapper(); + double fValue = 0.0; tools::Time aResult(tools::Time::EMPTY); - bool bRet = ::TimeFormatter::TextToTime(GetEntryText(), aResult, m_eFormat, m_bDuration, rLocaleDataWrapper); + bool bRet = ::TimeFormatter::TextToTime(rText, aResult, m_eFormat, m_bDuration, rLocaleDataWrapper); if (bRet) - *result = ConvertValue(aResult); + fValue = ConvertValue(aResult); - return bRet ? TRISTATE_TRUE : TRISTATE_FALSE; + return Formatter::ParseResult(bRet ? TRISTATE_TRUE : TRISTATE_FALSE, fValue); } IMPL_LINK(TimeFormatter, CursorChangedHdl, weld::Entry&, rEntry, void) diff --git a/vcl/source/control/fmtfield.cxx b/vcl/source/control/fmtfield.cxx index 8dc97702e533..e3cad69651e0 100644 --- a/vcl/source/control/fmtfield.cxx +++ b/vcl/source/control/fmtfield.cxx @@ -800,15 +800,14 @@ bool Formatter::ImplGetValue(double& dNewVal) return true; bool bUseExternalFormatterValue = false; - if (m_aInputHdl.IsSet()) + if (m_aParseTextHdl.IsSet()) { - double fResult; - auto eState = m_aInputHdl.Call(&fResult); - bUseExternalFormatterValue = eState != TRISTATE_INDET; + ParseResult aResult = m_aParseTextHdl.Call(sText); + bUseExternalFormatterValue = aResult.m_eState != TRISTATE_INDET; if (bUseExternalFormatterValue) { - if (eState == TRISTATE_TRUE) - dNewVal = fResult; + if (aResult.m_eState == TRISTATE_TRUE) + dNewVal = aResult.m_fValue; else dNewVal = m_dCurrentValue; } diff --git a/vcl/source/control/longcurr.cxx b/vcl/source/control/longcurr.cxx index a1698afb1f90..475f80939abb 100644 --- a/vcl/source/control/longcurr.cxx +++ b/vcl/source/control/longcurr.cxx @@ -225,17 +225,18 @@ namespace weld return std::optional(aText); } - IMPL_LINK(LongCurrencyFormatter, ParseInputHdl, double*, result, TriState) + IMPL_LINK(LongCurrencyFormatter, ParseInputHdl, const OUString&, rText, Formatter::ParseResult) { const LocaleDataWrapper& rLocaleDataWrapper = Application::GetSettings().GetLocaleDataWrapper(); BigInt value; - bool bRet = ImplCurrencyGetValue(GetEntryText(), value, GetDecimalDigits(), rLocaleDataWrapper); + bool bRet = ImplCurrencyGetValue(rText, value, GetDecimalDigits(), rLocaleDataWrapper); + double fValue = 0; if (bRet) - *result = double(value) / weld::SpinButton::Power10(GetDecimalDigits()); + fValue = double(value) / weld::SpinButton::Power10(GetDecimalDigits()); - return bRet ? TRISTATE_TRUE : TRISTATE_FALSE; + return Formatter::ParseResult(bRet ? TRISTATE_TRUE : TRISTATE_FALSE, fValue); } }