include/vcl/weld.hxx                  |    2 -
 vcl/Library_vclplug_qt5.mk            |    1 
 vcl/Library_vclplug_qt6.mk            |    1 
 vcl/inc/qt5/QtInstanceBuilder.hxx     |    2 -
 vcl/inc/qt5/QtInstanceButton.hxx      |    7 +++
 vcl/inc/qt5/QtInstanceRadioButton.hxx |   36 ++++++++++++++++++++
 vcl/inc/qt6/QtInstanceRadioButton.hxx |   12 ++++++
 vcl/qt5/QtBuilder.cxx                 |   12 +++++-
 vcl/qt5/QtInstanceBuilder.cxx         |   10 +++--
 vcl/qt5/QtInstanceButton.cxx          |   21 +++++++++++
 vcl/qt5/QtInstanceDialog.cxx          |    6 +++
 vcl/qt5/QtInstanceRadioButton.cxx     |   61 ++++++++++++++++++++++++++++++++++
 vcl/qt6/QtInstanceRadioButton.cxx     |   12 ++++++
 13 files changed, 175 insertions(+), 8 deletions(-)

New commits:
commit 076deef1324b7db84f2a33ed005efe808b81a46e
Author:     Michael Weghorn <[email protected]>
AuthorDate: Fri Oct 25 13:21:55 2024 +0200
Commit:     Michael Weghorn <[email protected]>
CommitDate: Fri Oct 25 18:45:03 2024 +0200

    tdf#130857 qt weld: Add QtInstanceRadioButton
    
    Implement initial support for native radio buttons
    using QRadioButton:
    
    * Let QtBuilder create a QRadioButton widget
      when it encounters a "GtkRadioButton" object.
    * Let QtBuilder::setProperties also handle the
      QRadioButton case. Both, QRadioButton and
      QCheckBox derive from QAbstractButton, so reuse
      the existing logic for QCheckBox to set label and
      checked status.
    * Add new class QtInstanceRadioButton as a weld::RadioButton
      implementation that uses a QRadioButton widget.
    * Let QtInstanceBuilder::weld_radio_button return
      an instance of the new class.
    
    For now, ignore the GtkRadioButton "group" property [1]
    that is used to group radio buttons.
    
    QRadioButton's are automatically grouped when they
    have the same parent widget, which is sufficient
    for the case of the "Alignment" dialog in Math
    for which support will be declared in an upcoming
    commit.
    
    For more complex scenarios, the use of QButtonGroup [2]
    could be implemented in the future to explicitly group
    radio buttons, as mentioned in the QRadioButton doc [3]:
    
    > If you need multiple exclusive button groups for radio buttons that
    > belong to the same parent widget, put them into a QButtonGroup.
    
    [1] https://docs.gtk.org/gtk3/property.RadioButton.group.html
    [2] https://doc.qt.io/qt-6/qbuttongroup.html
    [3] https://doc.qt.io/qt-6/qradiobutton.html
    
    Change-Id: Iaf8b0fef00fc10268c09410080156e7913634ab7
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/175639
    Reviewed-by: Michael Weghorn <[email protected]>
    Tested-by: Jenkins

diff --git a/vcl/Library_vclplug_qt5.mk b/vcl/Library_vclplug_qt5.mk
index 5f3ca52b6ee7..2cbd00943dc0 100644
--- a/vcl/Library_vclplug_qt5.mk
+++ b/vcl/Library_vclplug_qt5.mk
@@ -105,6 +105,7 @@ $(eval $(call gb_Library_add_exception_objects,vclplug_qt5,\
     vcl/qt5/QtInstanceFrame \
     vcl/qt5/QtInstanceMessageDialog \
     vcl/qt5/QtInstanceLabel \
+    vcl/qt5/QtInstanceRadioButton \
     vcl/qt5/QtInstanceTextView \
     vcl/qt5/QtInstanceWidget \
     vcl/qt5/QtInstanceWindow \
diff --git a/vcl/Library_vclplug_qt6.mk b/vcl/Library_vclplug_qt6.mk
index 47a11d9c09db..89f3b7eefb47 100644
--- a/vcl/Library_vclplug_qt6.mk
+++ b/vcl/Library_vclplug_qt6.mk
@@ -104,6 +104,7 @@ $(eval $(call gb_Library_add_exception_objects,vclplug_qt6,\
     vcl/qt6/QtInstanceFrame \
     vcl/qt6/QtInstanceLabel \
     vcl/qt6/QtInstanceMessageDialog \
+    vcl/qt6/QtInstanceRadioButton \
     vcl/qt6/QtInstanceTextView \
     vcl/qt6/QtInstanceWidget \
     vcl/qt6/QtInstanceWindow \
diff --git a/vcl/inc/qt5/QtInstanceBuilder.hxx 
b/vcl/inc/qt5/QtInstanceBuilder.hxx
index 2bae1fdca3b2..33e33c9f08ed 100644
--- a/vcl/inc/qt5/QtInstanceBuilder.hxx
+++ b/vcl/inc/qt5/QtInstanceBuilder.hxx
@@ -47,7 +47,7 @@ public:
     weld_menu_toggle_button(const OUString&) override;
     virtual std::unique_ptr<weld::LinkButton> weld_link_button(const 
OUString&) override;
     virtual std::unique_ptr<weld::ToggleButton> weld_toggle_button(const 
OUString&) override;
-    virtual std::unique_ptr<weld::RadioButton> weld_radio_button(const 
OUString&) override;
+    virtual std::unique_ptr<weld::RadioButton> weld_radio_button(const 
OUString& rId) override;
     virtual std::unique_ptr<weld::CheckButton> weld_check_button(const 
OUString& rId) override;
     virtual std::unique_ptr<weld::Scale> weld_scale(const OUString&) override;
     virtual std::unique_ptr<weld::ProgressBar> weld_progress_bar(const 
OUString&) override;
diff --git a/vcl/inc/qt5/QtInstanceRadioButton.hxx 
b/vcl/inc/qt5/QtInstanceRadioButton.hxx
new file mode 100644
index 000000000000..46eb098f942a
--- /dev/null
+++ b/vcl/inc/qt5/QtInstanceRadioButton.hxx
@@ -0,0 +1,36 @@
+/* -*- 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 <QtCore/QObject>
+#include <QtWidgets/QRadioButton>
+
+class QtInstanceRadioButton : public QtInstanceWidget, public virtual 
weld::RadioButton
+{
+    QRadioButton* m_pRadioButton;
+
+public:
+    QtInstanceRadioButton(QRadioButton* pRadioButton);
+
+    // weld::Toggleable methods
+    virtual void set_active(bool bActive) override;
+    virtual bool get_active() const override;
+    virtual void set_inconsistent(bool bInconsistent) override;
+    virtual bool get_inconsistent() const override;
+
+    // weld::RadioButton methods
+    virtual void set_label(const OUString& rText) override;
+    virtual OUString get_label() const override;
+    virtual void set_label_wrap(bool bWrap) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/qt6/QtInstanceRadioButton.hxx 
b/vcl/inc/qt6/QtInstanceRadioButton.hxx
new file mode 100644
index 000000000000..0207173a6ca2
--- /dev/null
+++ b/vcl/inc/qt6/QtInstanceRadioButton.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/QtInstanceRadioButton.hxx"
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qt5/QtBuilder.cxx b/vcl/qt5/QtBuilder.cxx
index cd59a1f8d3fb..8510967533d9 100644
--- a/vcl/qt5/QtBuilder.cxx
+++ b/vcl/qt5/QtBuilder.cxx
@@ -25,6 +25,7 @@
 #include <QtWidgets/QLayout>
 #include <QtWidgets/QPlainTextEdit>
 #include <QtWidgets/QPushButton>
+#include <QtWidgets/QRadioButton>
 #include <QtWidgets/QScrollArea>
 
 namespace
@@ -188,6 +189,10 @@ QObject* QtBuilder::makeObject(QObject* pParent, 
std::u16string_view sName, cons
         extractMnemonicWidget(sID, rMap);
         pObject = new QLabel(pParentWidget);
     }
+    else if (sName == u"GtkRadioButton")
+    {
+        pObject = new QRadioButton(pParentWidget);
+    }
     else if (sName == u"GtkScrolledWindow")
     {
         pObject = new QScrollArea(pParentWidget);
@@ -420,14 +425,15 @@ void QtBuilder::setProperties(QObject* pObject, 
stringmap& rProps)
             }
         }
     }
-    else if (QCheckBox* pCheckBox = qobject_cast<QCheckBox*>(pObject))
+    else if (qobject_cast<QCheckBox*>(pObject) || 
qobject_cast<QRadioButton*>(pObject))
     {
+        QAbstractButton* pButton = static_cast<QAbstractButton*>(pObject);
         for (auto const & [ rKey, rValue ] : rProps)
         {
             if (rKey == u"active")
-                pCheckBox->setChecked(toBool(rValue));
+                pButton->setChecked(toBool(rValue));
             else if (rKey == u"label")
-                pCheckBox->setText(convertAccelerator(rValue));
+                pButton->setText(convertAccelerator(rValue));
         }
     }
     else if (QDialog* pDialog = qobject_cast<QDialog*>(pObject))
diff --git a/vcl/qt5/QtInstanceBuilder.cxx b/vcl/qt5/QtInstanceBuilder.cxx
index 87e86d720de1..0fe3e95773a8 100644
--- a/vcl/qt5/QtInstanceBuilder.cxx
+++ b/vcl/qt5/QtInstanceBuilder.cxx
@@ -18,6 +18,7 @@
 #include <QtInstanceFrame.hxx>
 #include <QtInstanceLabel.hxx>
 #include <QtInstanceMessageDialog.hxx>
+#include <QtInstanceRadioButton.hxx>
 #include <QtInstanceTextView.hxx>
 
 QtInstanceBuilder::QtInstanceBuilder(QWidget* pParent, std::u16string_view 
sUIRoot,
@@ -160,10 +161,12 @@ std::unique_ptr<weld::ToggleButton> 
QtInstanceBuilder::weld_toggle_button(const
     return nullptr;
 }
 
-std::unique_ptr<weld::RadioButton> QtInstanceBuilder::weld_radio_button(const 
OUString&)
+std::unique_ptr<weld::RadioButton> QtInstanceBuilder::weld_radio_button(const 
OUString& rId)
 {
-    assert(false && "Not implemented yet");
-    return nullptr;
+    QRadioButton* pRadioButton = m_xBuilder->get<QRadioButton>(rId);
+    std::unique_ptr<weld::RadioButton> xRet(
+        pRadioButton ? std::make_unique<QtInstanceRadioButton>(pRadioButton) : 
nullptr);
+    return xRet;
 }
 
 std::unique_ptr<weld::CheckButton> QtInstanceBuilder::weld_check_button(const 
OUString& rId)
diff --git a/vcl/qt5/QtInstanceRadioButton.cxx 
b/vcl/qt5/QtInstanceRadioButton.cxx
new file mode 100644
index 000000000000..8c5124aa2661
--- /dev/null
+++ b/vcl/qt5/QtInstanceRadioButton.cxx
@@ -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/.
+ */
+
+#include <QtInstanceRadioButton.hxx>
+
+#include <vcl/qt/QtUtils.hxx>
+
+QtInstanceRadioButton::QtInstanceRadioButton(QRadioButton* pRadioButton)
+    : QtInstanceWidget(pRadioButton)
+    , m_pRadioButton(pRadioButton)
+{
+    assert(m_pRadioButton);
+}
+
+void QtInstanceRadioButton::set_active(bool bActive)
+{
+    SolarMutexGuard g;
+    GetQtInstance().RunInMainThread([&] { m_pRadioButton->setChecked(bActive); 
});
+}
+
+bool QtInstanceRadioButton::get_active() const
+{
+    SolarMutexGuard g;
+    bool bActive;
+    GetQtInstance().RunInMainThread([&] { bActive = 
m_pRadioButton->isChecked(); });
+    return bActive;
+}
+
+void QtInstanceRadioButton::set_inconsistent(bool) { assert(false && "Not 
implemented yet"); }
+
+bool QtInstanceRadioButton::get_inconsistent() const
+{
+    assert(false && "Not implemented yet");
+    return false;
+}
+
+void QtInstanceRadioButton::set_label(const OUString& rText)
+{
+    SolarMutexGuard g;
+    GetQtInstance().RunInMainThread([&] { 
m_pRadioButton->setText(toQString(rText)); });
+}
+OUString QtInstanceRadioButton::get_label() const
+{
+    SolarMutexGuard g;
+    OUString sLabel;
+    GetQtInstance().RunInMainThread([&] { sLabel = 
toOUString(m_pRadioButton->text()); });
+    return sLabel;
+}
+
+void QtInstanceRadioButton::QtInstanceRadioButton::set_label_wrap(bool 
/*bWrap*/)
+{
+    assert(false && "Not implemented yet");
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qt6/QtInstanceRadioButton.cxx 
b/vcl/qt6/QtInstanceRadioButton.cxx
new file mode 100644
index 000000000000..f4e3c36ac474
--- /dev/null
+++ b/vcl/qt6/QtInstanceRadioButton.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/QtInstanceRadioButton.cxx"
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 3e0aecad5491bedbee94b4937fe7e08edf5ae203
Author:     Michael Weghorn <[email protected]>
AuthorDate: Fri Oct 25 10:41:45 2024 +0200
Commit:     Michael Weghorn <[email protected]>
CommitDate: Fri Oct 25 18:44:56 2024 +0200

    tdf#130857 qt weld: Declare support for sw "Rename Object" dialog
    
    Add .ui file of Writer's dialog to rename objects
    to list of files supported by QtInstanceBuilder, so that native
    Qt widgets are used for that dialog now when using the qt5/qt6 VCL
    plugins, unless environment variable SAL_VCL_QT_NO_WELDED_WIDGETS=1
    is set.
    
    That dialog can be triggered e.g. as follows:
    
    * create new Writer doc
    * insert a bookmark ("Insert" -> "Bookmark")
    * in the Navigator sidebar panel, select the
      bookmark
    * righ-click, select "Edit"
    * press the "Rename" button in the "Bookmark" dialog
    
    Change-Id: I0ac8f66b977f5d999bb197cc68e8ce5533fe1ebd
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/175634
    Reviewed-by: Michael Weghorn <[email protected]>
    Tested-by: Jenkins

diff --git a/vcl/qt5/QtInstanceBuilder.cxx b/vcl/qt5/QtInstanceBuilder.cxx
index 5202760e5c68..87e86d720de1 100644
--- a/vcl/qt5/QtInstanceBuilder.cxx
+++ b/vcl/qt5/QtInstanceBuilder.cxx
@@ -42,6 +42,7 @@ bool QtInstanceBuilder::IsUIFileSupported(const OUString& 
rUIFile)
         u"modules/scalc/ui/inputstringdialog.ui"_ustr,
         u"modules/schart/ui/insertaxisdlg.ui"_ustr,
         u"modules/swriter/ui/inforeadonlydialog.ui"_ustr,
+        u"modules/swriter/ui/renameobjectdialog.ui"_ustr,
         u"modules/swriter/ui/wordcount.ui"_ustr,
         u"sfx/ui/licensedialog.ui"_ustr,
         u"sfx/ui/querysavedialog.ui"_ustr,
commit fac6d5da618f4f71e1bacc8a1dd07923407d907e
Author:     Michael Weghorn <[email protected]>
AuthorDate: Fri Oct 25 10:37:07 2024 +0200
Commit:     Michael Weghorn <[email protected]>
CommitDate: Fri Oct 25 18:44:49 2024 +0200

    tdf#130857 qt weld: Prefer custom handler for dialog buttons
    
    If a custom handler is set for a button in a dialog's
    button box, skip the default handling (to close the
    dialog with the corresponding response code, unless
    it's the help button) in QtInstanceDialog::handleButtonClick,
    so that the custom handler gets processed instead
    (see QtInstanceButton::buttonClicked).
    
    This is similar to what the VCL implementation
    (see SalInstanceButton's ClickHdl) and the
    gtk3 implementation (see
    GtkInstanceDialog::asyncresponse) do.
    
    In order to be able to determine whether
    a custom click handler is set, make
    weld::Button::connect_clicked virtual
    and override it in QtInstanceButton::connect_clicked
    to set a property on the QPushButton object
    to indicate that a handler is set.
    Introduce a static helper method
    QtInstanceButton::hasCustomClickHandler
    that evaluates this property.
    
    Without this change in place, pressing the
    "Rename" button in Writer's "Rename Object"
    dialog that will be declared as supported
    in upcoming commit
    
        Change-Id: I0ac8f66b977f5d999bb197cc68e8ce5533fe1ebd
        Author: Michael Weghorn <[email protected]>
        Date:   Fri Oct 25 10:41:45 2024 +0200
    
            tdf#130857 qt weld: Declare support for sw "Rename Object" dialog
    
    would not actually result in a bookmark getting
    renamed, only the dialog would be closed.
    
    Change-Id: If3e762100349ecd06c4e9415e9a8f9a44ec6491c
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/175633
    Tested-by: Jenkins
    Reviewed-by: Michael Weghorn <[email protected]>

diff --git a/include/vcl/weld.hxx b/include/vcl/weld.hxx
index c375a7e0c03b..cc60c8f351e7 100644
--- a/include/vcl/weld.hxx
+++ b/include/vcl/weld.hxx
@@ -1540,7 +1540,7 @@ public:
        set_accessible_name if you do. */
     virtual void set_custom_button(VirtualDevice* pDevice) = 0;
 
-    void connect_clicked(const Link<Button&, void>& rLink) { m_aClickHdl = 
rLink; }
+    virtual void connect_clicked(const Link<Button&, void>& rLink) { 
m_aClickHdl = rLink; }
 };
 
 class VCL_DLLPUBLIC Toggleable : virtual public Widget
diff --git a/vcl/inc/qt5/QtInstanceButton.hxx b/vcl/inc/qt5/QtInstanceButton.hxx
index 52f940064332..3a513512e06e 100644
--- a/vcl/inc/qt5/QtInstanceButton.hxx
+++ b/vcl/inc/qt5/QtInstanceButton.hxx
@@ -29,6 +29,13 @@ public:
     virtual void set_font(const vcl::Font& rFont) override;
     virtual void set_custom_button(VirtualDevice* pDevice) override;
 
+    virtual void connect_clicked(const Link<Button&, void>& rLink) override;
+
+    // whether a custom click handler is set for the given button
+    // (s.a. weld::Button::is_custom_handler_set which would give the
+    // same result if called on the corresponding QtInstanceButton)
+    static bool hasCustomClickHandler(QAbstractButton& rButton);
+
 private slots:
     void buttonClicked();
 };
diff --git a/vcl/qt5/QtInstanceButton.cxx b/vcl/qt5/QtInstanceButton.cxx
index d2da6d310239..6de1164e8d10 100644
--- a/vcl/qt5/QtInstanceButton.cxx
+++ b/vcl/qt5/QtInstanceButton.cxx
@@ -11,6 +11,11 @@
 
 #include <vcl/qt/QtUtils.hxx>
 
+// Name of QObject property to indicate whether a click handler
+// was set on the QPushButton: If that property is set and has a value
+// of true, then a custom click handler is set, otherwise not.
+const char* const PROPERTY_CLICK_HANDLER_SET = "click-handler-set";
+
 QtInstanceButton::QtInstanceButton(QPushButton* pButton)
     : QtInstanceWidget(pButton)
     , m_pButton(pButton)
@@ -78,6 +83,22 @@ void QtInstanceButton::set_custom_button(VirtualDevice* 
/*pDevice*/)
     assert(false && "Not implemented yet");
 }
 
+void QtInstanceButton::connect_clicked(const Link<Button&, void>& rLink)
+{
+    weld::Button::connect_clicked(rLink);
+    m_pButton->setProperty(PROPERTY_CLICK_HANDLER_SET, 
QVariant::fromValue(rLink.IsSet()));
+}
+
+bool QtInstanceButton::hasCustomClickHandler(QAbstractButton& rButton)
+{
+    QVariant aProp = rButton.property(PROPERTY_CLICK_HANDLER_SET);
+    if (!aProp.isValid())
+        return false;
+
+    assert(aProp.canConvert<bool>());
+    return aProp.toBool();
+}
+
 void QtInstanceButton::buttonClicked() { signal_clicked(); }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qt5/QtInstanceDialog.cxx b/vcl/qt5/QtInstanceDialog.cxx
index ef88d4e2e005..76efd3eca167 100644
--- a/vcl/qt5/QtInstanceDialog.cxx
+++ b/vcl/qt5/QtInstanceDialog.cxx
@@ -10,6 +10,8 @@
 #include <QtInstanceDialog.hxx>
 #include <QtInstanceDialog.moc>
 
+#include <QtInstanceButton.hxx>
+
 #include <vcl/help.hxx>
 
 const char* const QtInstanceDialog::PROPERTY_VCL_RESPONSE_CODE = 
"response-code";
@@ -174,6 +176,10 @@ void QtInstanceDialog::handleButtonClick(QDialog& rDialog, 
QAbstractButton& rBut
         return;
     }
 
+    // skip default handling if a custom click handler is set
+    if (QtInstanceButton::hasCustomClickHandler(rButton))
+        return;
+
     QVariant aResponseProperty = 
rButton.property(QtInstanceDialog::PROPERTY_VCL_RESPONSE_CODE);
     if (!aResponseProperty.isValid())
         return;

Reply via email to