vcl/inc/qt5/QtBuilder.hxx |    2 -
 vcl/qt5/QtBuilder.cxx     |   66 +++++++++++++++++++++++++++++++++-------------
 2 files changed, 49 insertions(+), 19 deletions(-)

New commits:
commit bf42162fc50d0c6f8e567d8765f8b14b96d7cc50
Author:     Michael Weghorn <m.wegh...@posteo.de>
AuthorDate: Mon Nov 4 19:06:15 2024 +0100
Commit:     Michael Weghorn <m.wegh...@posteo.de>
CommitDate: Tue Nov 5 08:21:22 2024 +0100

    tdf#130857 qt weld: Add extra QWidget parents for layouts
    
    For "GtkBox" and "GtkGrid" objects in .ui files,
    don't just create the corresponding QLayout objects,
    but create an extra QWidget object and set the
    layout for that widget, i.e. use that QWidget as
    the parent.
    
    While this generally wouldn't be needed to properly
    layout/handle things in Qt, having an associated
    QWidget for the "GtkBox" and "GtkGrid" children
    is needed in order to be able to create a
    corresponding weld::Container (QtInstanceContainer)
    for these, which derives from weld::Widget.
    QLayout itself doesn't have the methods required to
    implement weld::Widget, e.g. can't be hidden or shown.
    
    Therefore, create a QWidget for these in addition,
    except for special cases like the top-level layout
    in a dialog or the dialog's button box.
    
    For QGroupBox (created for "GtkFrame" objects),
    this now means that the direct child is no more
    necessarily a layout. Just setting a QWidget
    as a child wouldn't suffice for proper layouting.
    Therefore, explicitly create a layout for parent
    widgets that don't have a layout set yet.
    
    Adjust QtBuilder::applyPackingProperties
    accordingly as well. Now, there's no more
    use case to call QtBuilder::applyGridPackingProperties
    with a QLayout for the current child. Get the
    corresponding QWidget parent (if there is one)
    before calling the method instead, and switch the
    param from QObject* to QWidget* to simplify the
    method.
    
    Having an extra widget might have the side-effect
    that extra spacing/margins might be used. If that
    turns out to be a problem, these can presumably
    explicitly be reduced (e.g. set to 0 for the relevant
    objects) as needed later.
    
    At least the 19 dialogs currently listed as supported in
    QtInstanceBuilder::IsUIFileSupported still look OK to
    me in a quick test with this commit in place.
    
    Actually making use of the newly added widgets
    to implement more of the QtInstanceContainer logic
    will be done in separate commits.
    
    Change-Id: I3d3600ddfc7883239177aafed57629c107cbdf5d
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/176033
    Tested-by: Jenkins
    Reviewed-by: Michael Weghorn <m.wegh...@posteo.de>

diff --git a/vcl/inc/qt5/QtBuilder.hxx b/vcl/inc/qt5/QtBuilder.hxx
index ccc199ec4c16..f3945cdc5dff 100644
--- a/vcl/inc/qt5/QtBuilder.hxx
+++ b/vcl/inc/qt5/QtBuilder.hxx
@@ -75,7 +75,7 @@ private:
     static QWidget* windowForObject(QObject* pObject);
     static QDialogButtonBox* findButtonBox(QDialog* pDialog);
 
-    static void applyGridPackingProperties(QObject* pCurrentChild, 
QGridLayout& rGrid,
+    static void applyGridPackingProperties(QWidget* pCurrentChild, 
QGridLayout& rGrid,
                                            const stringmap& 
rPackingProperties);
 };
 
diff --git a/vcl/qt5/QtBuilder.cxx b/vcl/qt5/QtBuilder.cxx
index 330774715bbb..91cd1839d055 100644
--- a/vcl/qt5/QtBuilder.cxx
+++ b/vcl/qt5/QtBuilder.cxx
@@ -105,6 +105,9 @@ QObject* QtBuilder::makeObject(QObject* pParent, 
std::u16string_view sName, cons
     QLayout* pParentLayout = qobject_cast<QLayout*>(pParent);
 
     QObject* pObject = nullptr;
+    // in case a QLayout is created, an additional QWidget parent
+    // will also be created because that is needed for QtInstanceContainer
+    QWidget* pLayoutParentWidget = nullptr;
 
     if (sName == u"GtkMessageDialog")
     {
@@ -120,11 +123,20 @@ QObject* QtBuilder::makeObject(QObject* pParent, 
std::u16string_view sName, cons
         }
         else
         {
+            QWidget* pBoxParentWidget = pParentWidget;
+            // Unless this is the direct GtkBox child of a GtkDialog, create a 
parent widget
+            // that can be used to create a QtInstanceContainer for this box
+            if (!qobject_cast<QDialog*>(pParentWidget))
+            {
+                pLayoutParentWidget = new QWidget(pParentWidget);
+                pBoxParentWidget = pLayoutParentWidget;
+            }
+
             const bool bVertical = hasOrientationVertical(rMap);
             if (bVertical)
-                pObject = new QVBoxLayout(pParentWidget);
+                pObject = new QVBoxLayout(pBoxParentWidget);
             else
-                pObject = new QHBoxLayout(pParentWidget);
+                pObject = new QHBoxLayout(pBoxParentWidget);
         }
     }
     else if (sName == u"GtkButtonBox")
@@ -189,7 +201,8 @@ QObject* QtBuilder::makeObject(QObject* pParent, 
std::u16string_view sName, cons
     }
     else if (sName == u"GtkGrid")
     {
-        pObject = new QGridLayout(pParentWidget);
+        pLayoutParentWidget = new QWidget(pParentWidget);
+        pObject = new QGridLayout(pLayoutParentWidget);
     }
     else if (sName == u"GtkImage")
     {
@@ -243,8 +256,20 @@ QObject* QtBuilder::makeObject(QObject* pParent, 
std::u16string_view sName, cons
         assert(false && "Widget type not supported yet");
     }
 
-    if (QWidget* pWidget = qobject_cast<QWidget*>(pObject))
+    QWidget* pWidget = qobject_cast<QWidget*>(pObject);
+    if (!pWidget)
+        pWidget = pLayoutParentWidget;
+
+    if (pWidget)
     {
+        if (!pParentLayout && pParentWidget)
+        {
+            // if the parent is a widget, use the widget's layout, and ensure 
it has one set
+            pParentLayout = pParentWidget->layout();
+            if (!pParentLayout)
+                pParentLayout = new QVBoxLayout(pParentWidget);
+        }
+
         // add widget to parent layout
         if (pParentLayout)
             pParentLayout->addWidget(pWidget);
@@ -365,7 +390,7 @@ void QtBuilder::applyAtkProperties(QObject* pObject, const 
stringmap& rPropertie
     }
 }
 
-void QtBuilder::applyGridPackingProperties(QObject* pCurrentChild, 
QGridLayout& rGrid,
+void QtBuilder::applyGridPackingProperties(QWidget* pCurrentChild, 
QGridLayout& rGrid,
                                            const stringmap& rPackingProperties)
 {
     assert(pCurrentChild);
@@ -385,18 +410,8 @@ void QtBuilder::applyGridPackingProperties(QObject* 
pCurrentChild, QGridLayout&
     auto aHeightIt = rPackingProperties.find(u"height"_ustr);
     sal_Int32 nRowSpan = (aHeightIt == rPackingProperties.end()) ? 1 : 
aHeightIt->second.toInt32();
 
-    if (pCurrentChild->isWidgetType())
-    {
-        QWidget* pWidget = static_cast<QWidget*>(pCurrentChild);
-        rGrid.removeWidget(pWidget);
-        rGrid.addWidget(pWidget, nRow, nColumn, nRowSpan, nColumnSpan);
-        return;
-    }
-
-    // if it's not a QWidget, it must be a QLayout
-    QLayout* pLayout = static_cast<QLayout*>(pCurrentChild);
-    rGrid.removeItem(pLayout);
-    rGrid.addLayout(pLayout, nRow, nColumn, nRowSpan, nColumnSpan);
+    rGrid.removeWidget(pCurrentChild);
+    rGrid.addWidget(pCurrentChild, nRow, nColumn, nRowSpan, nColumnSpan);
 }
 
 void QtBuilder::applyPackingProperties(QObject* pCurrentChild, QObject* 
pParent,
@@ -405,8 +420,23 @@ void QtBuilder::applyPackingProperties(QObject* 
pCurrentChild, QObject* pParent,
     if (!pCurrentChild)
         return;
 
+    QWidget* pWidget = nullptr;
+    if (pCurrentChild->isWidgetType())
+        pWidget = static_cast<QWidget*>(pCurrentChild);
+    else
+    {
+        QObject* pParentObject = pCurrentChild->parent();
+        assert(pParent && "Non-widget (i.e. layout) has no parent");
+        if (pParentObject->isWidgetType())
+            pWidget = static_cast<QWidget*>(pParentObject);
+    }
+
+    if (!pWidget)
+        return;
+
+    // check parent's parent, due to extra QWidget parents for layouts
     if (QGridLayout* pGrid = qobject_cast<QGridLayout*>(pParent))
-        applyGridPackingProperties(pCurrentChild, *pGrid, rPackingProperties);
+        applyGridPackingProperties(pWidget, *pGrid, rPackingProperties);
     else
         SAL_WARN("vcl.qt", "QtBuilder::applyPackingProperties not yet 
implemented for this case");
 }

Reply via email to