From ea790b37d991b6db818ff75f9d28ad10ef865810 Mon Sep 17 00:00:00 2001 From: Michael Weghorn Date: Thu, 7 Nov 2024 22:04:07 +0100 Subject: [PATCH] tdf#130857 qt weld: Add initial SpinButton support Add new class QtInstanceSpinButton that is the weld::SpinButton implementation using native widgets. Initially, implement the actual logic of only some methods, and let the others trigger an assert for now. (These can be implemented once needed to support more dialogs.) Initially, assume that the value is an integer (which is the case for the "Table" -> "Insert" -> "Rows" dialog in Writer, for which support will be declared in an upcoming commit). However, already use a QDoubleSpinBox that supports floating point values instead of QSpinBox (that can only handle integer values) to prepare for extending the implementation accordingly later. In QtBuilder, handle "GtkSpinButton" objects, create a QDoubleSpinBox for them and evaluate the "digits" and "adjustment" properties to set the corresponding values for the QDoubleSpinBox. Let QtInstanceBuilder::weld_spin_button return an instance of the newly added class. Change-Id: I0808589a3e6bece749c0ae4541f2419410ea99bb Reviewed-on: https://gerrit.libreoffice.org/c/core/+/176248 Tested-by: Jenkins Reviewed-by: Michael Weghorn --- vcl/Library_vclplug_qt5.mk | 1 + vcl/Library_vclplug_qt6.mk | 1 + vcl/inc/qt5/QtBuilder.hxx | 2 + vcl/inc/qt5/QtInstanceBuilder.hxx | 2 +- vcl/inc/qt5/QtInstanceSpinButton.hxx | 61 ++++++++++ vcl/inc/qt6/QtInstanceSpinButton.hxx | 12 ++ vcl/qt5/QtBuilder.cxx | 31 +++++ vcl/qt5/QtInstanceBuilder.cxx | 9 +- vcl/qt5/QtInstanceSpinButton.cxx | 164 +++++++++++++++++++++++++++ vcl/qt6/QtInstanceSpinButton.cxx | 12 ++ 10 files changed, 291 insertions(+), 4 deletions(-) create mode 100644 vcl/inc/qt5/QtInstanceSpinButton.hxx create mode 100644 vcl/inc/qt6/QtInstanceSpinButton.hxx create mode 100644 vcl/qt5/QtInstanceSpinButton.cxx create mode 100644 vcl/qt6/QtInstanceSpinButton.cxx diff --git a/vcl/Library_vclplug_qt5.mk b/vcl/Library_vclplug_qt5.mk index 678f69a92088..8923204fed94 100644 --- a/vcl/Library_vclplug_qt5.mk +++ b/vcl/Library_vclplug_qt5.mk @@ -113,6 +113,7 @@ $(eval $(call gb_Library_add_exception_objects,vclplug_qt5,\ vcl/qt5/QtInstanceMessageDialog \ vcl/qt5/QtInstanceProgressBar \ vcl/qt5/QtInstanceRadioButton \ + vcl/qt5/QtInstanceSpinButton \ vcl/qt5/QtInstanceTextView \ vcl/qt5/QtInstanceWidget \ vcl/qt5/QtInstanceWindow \ diff --git a/vcl/Library_vclplug_qt6.mk b/vcl/Library_vclplug_qt6.mk index f57bcc307157..e6ec9491c5e5 100644 --- a/vcl/Library_vclplug_qt6.mk +++ b/vcl/Library_vclplug_qt6.mk @@ -112,6 +112,7 @@ $(eval $(call gb_Library_add_exception_objects,vclplug_qt6,\ vcl/qt6/QtInstanceMessageDialog \ vcl/qt6/QtInstanceProgressBar \ vcl/qt6/QtInstanceRadioButton \ + vcl/qt6/QtInstanceSpinButton \ vcl/qt6/QtInstanceTextView \ vcl/qt6/QtInstanceWidget \ vcl/qt6/QtInstanceWindow \ diff --git a/vcl/inc/qt5/QtBuilder.hxx b/vcl/inc/qt5/QtBuilder.hxx index f3945cdc5dff..a3faaa84a0ab 100644 --- a/vcl/inc/qt5/QtBuilder.hxx +++ b/vcl/inc/qt5/QtBuilder.hxx @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -72,6 +73,7 @@ public: private: void setProperties(QObject* obj, stringmap& rProps); + void setSpinButtonProperties(QDoubleSpinBox& rSpinBox, stringmap& rProps); static QWidget* windowForObject(QObject* pObject); static QDialogButtonBox* findButtonBox(QDialog* pDialog); diff --git a/vcl/inc/qt5/QtInstanceBuilder.hxx b/vcl/inc/qt5/QtInstanceBuilder.hxx index 120c6f9abbb8..70b072dbd4da 100644 --- a/vcl/inc/qt5/QtInstanceBuilder.hxx +++ b/vcl/inc/qt5/QtInstanceBuilder.hxx @@ -56,7 +56,7 @@ public: virtual std::unique_ptr weld_image(const OUString& rId) override; virtual std::unique_ptr weld_calendar(const OUString&) override; virtual std::unique_ptr weld_entry(const OUString& rId) override; - virtual std::unique_ptr weld_spin_button(const OUString&) override; + virtual std::unique_ptr weld_spin_button(const OUString& rId) override; virtual std::unique_ptr weld_metric_spin_button(const OUString&, FieldUnit) override; virtual std::unique_ptr diff --git a/vcl/inc/qt5/QtInstanceSpinButton.hxx b/vcl/inc/qt5/QtInstanceSpinButton.hxx new file mode 100644 index 000000000000..0ca3d67ede56 --- /dev/null +++ b/vcl/inc/qt5/QtInstanceSpinButton.hxx @@ -0,0 +1,61 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include "QtInstanceWidget.hxx" + +#include + +class QtInstanceSpinButton : public QtInstanceWidget, public virtual weld::SpinButton +{ + QDoubleSpinBox* m_pSpinBox; + +public: + QtInstanceSpinButton(QDoubleSpinBox* pSpinBox); + + virtual void set_text(const OUString& rText) override; + virtual OUString get_text() const override; + virtual void set_width_chars(int nChars) override; + virtual int get_width_chars() const override; + virtual void set_max_length(int nChars) override; + virtual void select_region(int nStartPos, int nEndPos) override; + virtual bool get_selection_bounds(int& rStartPos, int& rEndPos) override; + virtual void replace_selection(const OUString& rText) override; + virtual void set_position(int nCursorPos) override; + virtual int get_position() const override; + virtual void set_editable(bool bEditable) override; + virtual bool get_editable() const override; + virtual void set_message_type(weld::EntryMessageType eType) override; + virtual void set_placeholder_text(const OUString& rText) override; + + virtual void set_overwrite_mode(bool bOn) override; + virtual bool get_overwrite_mode() const override; + + virtual void set_font(const vcl::Font& rFont) override; + virtual void set_font_color(const Color& rColor) override; + + virtual void cut_clipboard() override; + virtual void copy_clipboard() override; + virtual void paste_clipboard() override; + + virtual void set_alignment(TxtAlign eXAlign) override; + + virtual void set_value(sal_Int64 nValue) override; + virtual sal_Int64 get_value() const override; + virtual void set_range(sal_Int64 nMin, sal_Int64 nMax) override; + virtual void get_range(sal_Int64& rMin, sal_Int64& rMax) const override; + + virtual void set_increments(sal_Int64 nStep, sal_Int64 nPage) override; + virtual void get_increments(sal_Int64& rStep, sal_Int64& rPage) const override; + virtual void set_digits(unsigned int nDigits) override; + virtual unsigned int get_digits() const override; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/qt6/QtInstanceSpinButton.hxx b/vcl/inc/qt6/QtInstanceSpinButton.hxx new file mode 100644 index 000000000000..137bf956be7f --- /dev/null +++ b/vcl/inc/qt6/QtInstanceSpinButton.hxx @@ -0,0 +1,12 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "../qt5/QtInstanceSpinButton.hxx" + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/qt5/QtBuilder.cxx b/vcl/qt5/QtBuilder.cxx index 73ad72ec424b..1b219567c199 100644 --- a/vcl/qt5/QtBuilder.cxx +++ b/vcl/qt5/QtBuilder.cxx @@ -256,6 +256,12 @@ QObject* QtBuilder::makeObject(QObject* pParent, std::u16string_view sName, cons pFrame->setFrameShape(bVertical ? QFrame::VLine : QFrame::HLine); pObject = pFrame; } + else if (sName == u"GtkSpinButton") + { + QDoubleSpinBox* pSpinBox = new QDoubleSpinBox(pParentWidget); + setSpinButtonProperties(*pSpinBox, rMap); + pObject = pSpinBox; + } else if (sName == u"GtkTextView") { pObject = new QPlainTextEdit(pParentWidget); @@ -557,6 +563,31 @@ void QtBuilder::setProperties(QObject* pObject, stringmap& rProps) } } +void QtBuilder::setSpinButtonProperties(QDoubleSpinBox& rSpinBox, stringmap& rProps) +{ + auto aDigitsIt = rProps.find(u"digits"_ustr); + sal_Int32 nDigits = (aDigitsIt != rProps.end()) ? aDigitsIt->second.toInt32() : 0; + rSpinBox.setDecimals(nDigits); + + auto aAdjustmentIt = rProps.find("adjustment"); + if (aAdjustmentIt != rProps.end()) + { + const Adjustment* pAdjustment = get_adjustment_by_name(aAdjustmentIt->second); + assert(pAdjustment && "referenced adjustment doesn't exist"); + for (auto const & [ rKey, rValue ] : *pAdjustment) + { + if (rKey == u"upper") + rSpinBox.setMaximum(rValue.toDouble()); + else if (rKey == u"lower") + rSpinBox.setMinimum(rValue.toDouble()); + else if (rKey == "value") + rSpinBox.setValue(rValue.toDouble()); + else if (rKey == "step-increment") + rSpinBox.setSingleStep(rValue.toDouble()); + } + } +} + QWidget* QtBuilder::windowForObject(QObject* pObject) { if (QWidget* pWidget = qobject_cast(pObject)) diff --git a/vcl/qt5/QtInstanceBuilder.cxx b/vcl/qt5/QtInstanceBuilder.cxx index 53144d4adc18..4531a614a66b 100644 --- a/vcl/qt5/QtInstanceBuilder.cxx +++ b/vcl/qt5/QtInstanceBuilder.cxx @@ -24,6 +24,7 @@ #include #include #include +#include #include QtInstanceBuilder::QtInstanceBuilder(QWidget* pParent, std::u16string_view sUIRoot, @@ -250,10 +251,12 @@ std::unique_ptr QtInstanceBuilder::weld_entry(const OUString& rId) return xRet; } -std::unique_ptr QtInstanceBuilder::weld_spin_button(const OUString&) +std::unique_ptr QtInstanceBuilder::weld_spin_button(const OUString& rId) { - assert(false && "Not implemented yet"); - return nullptr; + QDoubleSpinBox* pSpinBox = m_xBuilder->get(rId); + std::unique_ptr xRet( + pSpinBox ? std::make_unique(pSpinBox) : nullptr); + return xRet; } std::unique_ptr QtInstanceBuilder::weld_metric_spin_button(const OUString&, diff --git a/vcl/qt5/QtInstanceSpinButton.cxx b/vcl/qt5/QtInstanceSpinButton.cxx new file mode 100644 index 000000000000..749e1e8eed35 --- /dev/null +++ b/vcl/qt5/QtInstanceSpinButton.cxx @@ -0,0 +1,164 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include + +QtInstanceSpinButton::QtInstanceSpinButton(QDoubleSpinBox* pSpinBox) + : QtInstanceWidget(pSpinBox) + , m_pSpinBox(pSpinBox) +{ + assert(pSpinBox); +} + +void QtInstanceSpinButton::set_text(const OUString&) { assert(false && "Not implemented yet"); } + +OUString QtInstanceSpinButton::get_text() const +{ + SolarMutexGuard g; + OUString sText; + GetQtInstance().RunInMainThread([&] { sText = toOUString(m_pSpinBox->text()); }); + return sText; +} + +void QtInstanceSpinButton::set_width_chars(int) { assert(false && "Not implemented yet"); } + +int QtInstanceSpinButton::get_width_chars() const +{ + assert(false && "Not implemented yet"); + return -1; +} + +void QtInstanceSpinButton::set_max_length(int) { assert(false && "Not implemented yet"); } + +void QtInstanceSpinButton::select_region(int, int) { assert(false && "Not implemented yet"); } + +bool QtInstanceSpinButton::get_selection_bounds(int&, int&) +{ + assert(false && "Not implemented yet"); + return false; +} + +void QtInstanceSpinButton::replace_selection(const OUString&) +{ + assert(false && "Not implemented yet"); +} + +void QtInstanceSpinButton::set_position(int) { assert(false && "Not implemented yet"); } + +int QtInstanceSpinButton::get_position() const +{ + assert(false && "Not implemented yet"); + return -1; +} + +void QtInstanceSpinButton::set_editable(bool) { assert(false && "Not implemented yet"); } + +bool QtInstanceSpinButton::get_editable() const +{ + assert(false && "Not implemented yet"); + return false; +} + +void QtInstanceSpinButton::set_message_type(weld::EntryMessageType) +{ + assert(false && "Not implemented yet"); +} + +void QtInstanceSpinButton::set_placeholder_text(const OUString&) +{ + assert(false && "Not implemented yet"); +} + +void QtInstanceSpinButton::set_overwrite_mode(bool) { assert(false && "Not implemented yet"); } + +bool QtInstanceSpinButton::get_overwrite_mode() const +{ + assert(false && "Not implemented yet"); + return false; +} + +void QtInstanceSpinButton::set_font(const vcl::Font&) { assert(false && "Not implemented yet"); } + +void QtInstanceSpinButton::set_font_color(const Color&) { assert(false && "Not implemented yet"); } + +void QtInstanceSpinButton::cut_clipboard() { assert(false && "Not implemented yet"); } + +void QtInstanceSpinButton::copy_clipboard() { assert(false && "Not implemented yet"); } + +void QtInstanceSpinButton::paste_clipboard() { assert(false && "Not implemented yet"); } + +void QtInstanceSpinButton::set_alignment(TxtAlign) { assert(false && "Not implemented yet"); } + +void QtInstanceSpinButton::set_value(sal_Int64 nValue) +{ + SolarMutexGuard g; + GetQtInstance().RunInMainThread([&] { (m_pSpinBox->setValue(nValue)); }); +} + +sal_Int64 QtInstanceSpinButton::get_value() const +{ + SolarMutexGuard g; + + sal_Int64 nValue; + GetQtInstance().RunInMainThread([&] { nValue = std::round(m_pSpinBox->value()); }); + return nValue; +} + +void QtInstanceSpinButton::set_range(sal_Int64 nMin, sal_Int64 nMax) +{ + SolarMutexGuard g; + GetQtInstance().RunInMainThread([&] { (m_pSpinBox->setRange(nMin, nMax)); }); +} + +void QtInstanceSpinButton::get_range(sal_Int64& rMin, sal_Int64& rMax) const +{ + SolarMutexGuard g; + + GetQtInstance().RunInMainThread([&] { + rMin = std::round(m_pSpinBox->minimum()); + rMax = std::round(m_pSpinBox->maximum()); + }); +} + +void QtInstanceSpinButton::set_increments(sal_Int64 nStep, sal_Int64) +{ + SolarMutexGuard g; + + GetQtInstance().RunInMainThread([&] { m_pSpinBox->setSingleStep(nStep); }); +} + +void QtInstanceSpinButton::get_increments(sal_Int64& rStep, sal_Int64& rPage) const +{ + SolarMutexGuard g; + + GetQtInstance().RunInMainThread([&] { + rStep = std::round(m_pSpinBox->singleStep()); + rPage = rStep; + }); +} + +void QtInstanceSpinButton::set_digits(unsigned int nDigits) +{ + SolarMutexGuard g; + + GetQtInstance().RunInMainThread([&] { m_pSpinBox->setDecimals(nDigits); }); +} + +unsigned int QtInstanceSpinButton::get_digits() const +{ + SolarMutexGuard g; + + unsigned int nDigits = 0; + GetQtInstance().RunInMainThread([&] { nDigits = o3tl::make_unsigned(m_pSpinBox->decimals()); }); + return nDigits; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/qt6/QtInstanceSpinButton.cxx b/vcl/qt6/QtInstanceSpinButton.cxx new file mode 100644 index 000000000000..cc7291c63971 --- /dev/null +++ b/vcl/qt6/QtInstanceSpinButton.cxx @@ -0,0 +1,12 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "../qt5/QtInstanceSpinButton.cxx" + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */