vcl/inc/qt5/QtInstanceMessageDialog.hxx |    5 +
 vcl/qt5/QtInstanceMessageDialog.cxx     |   83 ++++++++++++++++++++++++++++++++
 2 files changed, 88 insertions(+)

New commits:
commit bb0c0e422788b6c461387491c59911ad84c27b83
Author:     Michael Weghorn <m.wegh...@posteo.de>
AuthorDate: Tue Jan 23 13:47:21 2024 +0100
Commit:     Michael Weghorn <m.wegh...@posteo.de>
CommitDate: Wed Jan 24 17:15:07 2024 +0100

    tdf#154381 qt weld: Add button handling for message box
    
    Override the `QtInstanceDialog` methods `add_button`
    and `run` in `QtInstanceMessageDialog`, and implement
    handling for these buttons with the native
    `QMessageBox` that is used internally:
    
    Implement `QtInstanceMessageDialog::add_button` to
    make adding buttons to the welded message dialog
    work.
    Map the VCL response type to a corresponding
    `QMessageBox::ButtonRole`. Some mappings are
    straightforward, others are a bit more arbitrary,
    but the only essential thing is that the mapping
    back to the VCL response code is consistent.
    
    `QMessageBox::exec` [1] overrides `QDialog::exec` [2],
    and while the int returned by the latter corresponds
    to a `QDialog::DialogCode` code, the int returned by
    the former corresponds to a `QMessageBox::StandardButton`
    value. Since the current `QtInstanceDialog::run` implementation
    relies on the `QDialog` behaviour, override it for the
    message dialog case. Since the `QMessageBox::ButtonRole`
    is set in `QtInstanceMessageDialog::add_button`, retrieve
    the corresponding role from the clicked button instead
    of using the return value of the `QMessageBox::exec`
    to be able to get the correct VCL return code again.
    
    With this in place, the qt6 welded message dialog that
    shows up when opening a file that's already open in another
    instance of LibreOffice (s. `AlreadyOpenQueryBox::AlreadyOpenQueryBox`)
    shows buttons and clicking any of them
    behaves as expected, just as is the case for the non-welded one
    (whose use can be forced by setting env var
    `SAL_VCL_QT_NO_WELDED_WIDGETS=1`).
    
    [1] https://doc.qt.io/qt-6/qmessagebox.html#exec`
    [2] https://doc.qt.io/qt-6/qdialog.html#exec
    
    Change-Id: Ie37573951302f13eab758f889d478dc9351e9c07
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/162440
    Tested-by: Jenkins
    Reviewed-by: Omkar Acharekar  <omkarachareka...@gmail.com>
    Reviewed-by: Michael Weghorn <m.wegh...@posteo.de>

diff --git a/vcl/inc/qt5/QtInstanceMessageDialog.hxx 
b/vcl/inc/qt5/QtInstanceMessageDialog.hxx
index 68d2010cb1fa..0c585a9ed916 100644
--- a/vcl/inc/qt5/QtInstanceMessageDialog.hxx
+++ b/vcl/inc/qt5/QtInstanceMessageDialog.hxx
@@ -29,6 +29,11 @@ public:
     virtual OUString get_primary_text() const override;
 
     virtual OUString get_secondary_text() const override;
+
+    // weld::Dialog overrides
+    virtual void add_button(const OUString& rText, int nResponse,
+                            const OUString& rHelpId = {}) override;
+    virtual int run() override;
 };
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qt5/QtInstanceMessageDialog.cxx 
b/vcl/qt5/QtInstanceMessageDialog.cxx
index 2ba386ded5c5..6f252c79c816 100644
--- a/vcl/qt5/QtInstanceMessageDialog.cxx
+++ b/vcl/qt5/QtInstanceMessageDialog.cxx
@@ -9,6 +9,69 @@
 
 #include <QtInstanceMessageDialog.hxx>
 
+namespace
+{
+QMessageBox::ButtonRole lcl_vclResponseTypeToQtMessageBoxButtonRole(int 
nResponseType)
+{
+    // RET_CANCEL, RET_HELP, RET_YES, RET_NO and RET_OK have a matching 
equivalent
+    // in Qt, the others are a bit more arbitrary; what really matters about 
these
+    // is only that the mapping here and the other way around
+    // (in lcl_qtMessageBoxButtonRoleToVclResponseType) is consistent
+    switch (nResponseType)
+    {
+        case RET_CANCEL:
+            return QMessageBox::ButtonRole::RejectRole;
+        case RET_HELP:
+            return QMessageBox::ButtonRole::HelpRole;
+        case RET_YES:
+            return QMessageBox::ButtonRole::YesRole;
+        case RET_NO:
+            return QMessageBox::ButtonRole::NoRole;
+        case RET_OK:
+            return QMessageBox::ButtonRole::AcceptRole;
+        case RET_RETRY:
+            return QMessageBox::ButtonRole::ResetRole;
+        case RET_IGNORE:
+            return QMessageBox::ButtonRole::ActionRole;
+        case RET_CLOSE:
+            return QMessageBox::ButtonRole::DestructiveRole;
+        default:
+            assert(false && "Unhandled vcl response type");
+            return QMessageBox::InvalidRole;
+    }
+}
+
+VclResponseType lcl_qtMessageBoxButtonRoleToVclResponseType(int nRet)
+{
+    // AcceptRole, HelpRole, NoRole, RejectRole and YesRole have a matching 
equivalent
+    // in VCL, the others are a bit more arbitrary; what really matters about 
these
+    // is only that the mapping here and the other way around
+    // (in lcl_vclResponseTypeToQtMessageBoxButtonRole) is consistent
+    switch (nRet)
+    {
+        case QMessageBox::ButtonRole::AcceptRole:
+            return RET_OK;
+        case QMessageBox::ButtonRole::HelpRole:
+            return RET_HELP;
+        case QMessageBox::ButtonRole::NoRole:
+            return RET_NO;
+        case QMessageBox::ButtonRole::RejectRole:
+            return RET_CANCEL;
+        case QMessageBox::ButtonRole::YesRole:
+            return RET_YES;
+        case QMessageBox::ButtonRole::ResetRole:
+            return RET_RETRY;
+        case QMessageBox::ButtonRole::ActionRole:
+            return RET_IGNORE;
+        case QMessageBox::ButtonRole::DestructiveRole:
+            return RET_CLOSE;
+        default:
+            assert(false && "Unhandled QMessageBox::ButtonRole");
+            return RET_CANCEL;
+    }
+}
+}
+
 QtInstanceMessageDialog::QtInstanceMessageDialog(QMessageBox* pMessageDialog)
     : QtInstanceDialog(pMessageDialog)
     , m_pMessageDialog(pMessageDialog)
@@ -39,4 +102,24 @@ OUString QtInstanceMessageDialog::get_secondary_text() const
     return toOUString(m_pMessageDialog->informativeText());
 }
 
+void QtInstanceMessageDialog::add_button(const OUString& rText, int nResponse, 
const OUString&)
+{
+    assert(m_pMessageDialog);
+    m_pMessageDialog->addButton(vclToQtStringWithAccelerator(rText),
+                                
lcl_vclResponseTypeToQtMessageBoxButtonRole(nResponse));
+}
+
+int QtInstanceMessageDialog::run()
+{
+    // cannot use the QMessageBox::exec() return value right away, because it 
returns the
+    // QMessageBox::StandardButton value or an opaque value, so use the clicked
+    // button to retrieve its role instead and map that to the VCL response
+    m_pMessageDialog->exec();
+    QAbstractButton* pClickedButton = m_pMessageDialog->clickedButton();
+    if (!pClickedButton)
+        return RET_CLOSE;
+    return lcl_qtMessageBoxButtonRoleToVclResponseType(
+        m_pMessageDialog->buttonRole(pClickedButton));
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Reply via email to