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"); }