include/vcl/builder.hxx       |    6 ++
 include/vcl/widgetbuilder.hxx |   83 +++++++++++++++++++++++++++++++++---
 vcl/inc/qt5/QtBuilder.hxx     |    6 ++
 vcl/qt5/QtBuilder.cxx         |   19 ++++++++
 vcl/source/window/builder.cxx |   96 +++++++-----------------------------------
 5 files changed, 125 insertions(+), 85 deletions(-)

New commits:
commit 7270c44e43a1c681dc55ce25f114b402bd8cf935
Author:     Michael Weghorn <m.wegh...@posteo.de>
AuthorDate: Sat Nov 9 21:23:04 2024 +0100
Commit:     Michael Weghorn <m.wegh...@posteo.de>
CommitDate: Sun Nov 10 12:28:38 2024 +0100

    tdf#130857 VclBuilder: Split XML parsing + applying tab child props
    
    Split the existing VclBuilder::handleTabChild into two
    methods and make the logic not specific to vcl::Window
    available to other subclasses as well, to make it
    available for reuse by QtBuilder in the future.
    
    In order to do that, move the existing XML parsing logic
    from the beginning of VclBuilder::handleTabChild to the base
    class into WidgetBuilder::handleTabChild.
    
    Add a new purely virtual method `applyTabChildProperties`
    to WidgetBuilder and move the corresponding logic for
    vcl::Window to the new VclBuilder override of this method.
    
    Call that method at the end of WidgetBuilder::handleTabChild.
    
    For QtBuilder, just add a dummy implementation that
    triggers an assert initially, which matches what
    would have happened right at the beginning
    of the previous WidgetBuilder::handleTabChild
    implementation without this commit in place.
    
    Change-Id: Ie5664bd341182fa51035b547accf9393d65a0702
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/176320
    Tested-by: Jenkins
    Reviewed-by: Michael Weghorn <m.wegh...@posteo.de>

diff --git a/include/vcl/builder.hxx b/include/vcl/builder.hxx
index 1db211394cf3..90b297ddb43b 100644
--- a/include/vcl/builder.hxx
+++ b/include/vcl/builder.hxx
@@ -274,6 +274,9 @@ private:
 
     void applyPackingProperties(vcl::Window* pCurrent, vcl::Window* pParent,
                                 const stringmap& rPackingProperties) override;
+    virtual void applyTabChildProperties(vcl::Window* pParent, const 
std::vector<OUString>& rIDs,
+                                         
std::vector<vcl::EnumContext::Context>& rContext, stringmap& rProperties,
+                                         stringmap& rAtkProperties) override;
 
     void        insertMenuObject(
                    Menu *pParent,
@@ -287,7 +290,6 @@ private:
     void        handleMenuChild(Menu *pParent, xmlreader::XmlReader &reader);
     void        handleMenuObject(Menu *pParent, xmlreader::XmlReader &reader);
 
-    void        handleTabChild(vcl::Window *pParent, xmlreader::XmlReader 
&reader) override;
     void handleMenu(xmlreader::XmlReader& reader, vcl::Window* pParent, const 
OUString& rID,
                     bool bMenuBar) override;
 
diff --git a/include/vcl/widgetbuilder.hxx b/include/vcl/widgetbuilder.hxx
index d12d68ad1cf7..1a7e6e608f7f 100644
--- a/include/vcl/widgetbuilder.hxx
+++ b/include/vcl/widgetbuilder.hxx
@@ -275,12 +275,86 @@ protected:
         return pCurrentChild;
     }
 
+    void handleTabChild(Widget* pParent, xmlreader::XmlReader& reader)
+    {
+        std::vector<OUString> sIDs;
+
+        int nLevel = 1;
+        stringmap aProperties;
+        stringmap aAtkProperties;
+        std::vector<vcl::EnumContext::Context> context;
+
+        while (true)
+        {
+            xmlreader::Span name;
+            int nsId;
+
+            xmlreader::XmlReader::Result res
+                = reader.nextItem(xmlreader::XmlReader::Text::NONE, &name, 
&nsId);
+
+            if (res == xmlreader::XmlReader::Result::Begin)
+            {
+                ++nLevel;
+                if (name == "object")
+                {
+                    while (reader.nextAttribute(&nsId, &name))
+                    {
+                        if (name == "id")
+                        {
+                            name = reader.getAttributeValue(false);
+                            OUString sID(name.begin, name.length, 
RTL_TEXTENCODING_UTF8);
+                            sal_Int32 nDelim = sID.indexOf(':');
+                            if (nDelim != -1)
+                            {
+                                aProperties[u"customproperty"_ustr] = 
sID.copy(nDelim + 1);
+                                sID = sID.copy(0, nDelim);
+                            }
+                            sIDs.push_back(sID);
+                        }
+                    }
+                }
+                else if (name == "style")
+                {
+                    int nPriority = 0;
+                    context = handleStyle(reader, nPriority);
+                    --nLevel;
+                }
+                else if (name == "property")
+                    collectProperty(reader, aProperties);
+                else if (name == "child" && isHorizontalTabControl(pParent))
+                {
+                    // just to collect the atk properties (if any) for the 
label
+                    handleChild(nullptr, &aAtkProperties, reader);
+                    --nLevel;
+                }
+            }
+
+            if (res == xmlreader::XmlReader::Result::End)
+                --nLevel;
+
+            if (!nLevel)
+                break;
+
+            if (res == xmlreader::XmlReader::Result::Done)
+                break;
+        }
+
+        if (!pParent)
+            return;
+
+        applyTabChildProperties(pParent, sIDs, context, aProperties, 
aAtkProperties);
+    }
+
     virtual void applyAtkProperties(Widget* pWidget, const stringmap& 
rProperties,
                                     bool bToolbarItem)
         = 0;
     virtual void applyPackingProperties(Widget* pCurrentChild, Widget* pParent,
                                         const stringmap& rPackingProperties)
         = 0;
+    virtual void applyTabChildProperties(Widget* pParent, const 
std::vector<OUString>& rIDs,
+                                         
std::vector<vcl::EnumContext::Context>& rContext,
+                                         stringmap& rProperties, stringmap& 
rAtkProperties)
+        = 0;
     virtual void insertComboBoxOrListBoxItems(Widget* pWidget, stringmap& rMap,
                                               const 
std::vector<ComboBoxTextItem>& rItems)
         = 0;
@@ -313,12 +387,6 @@ protected:
     {
         assert(false && "Functionality not implemented by this subclass yet.");
     }
-
-    virtual void handleTabChild(Widget* /*pParent*/, xmlreader::XmlReader& 
/*reader*/)
-
-    {
-        assert(false && "Functionality not implemented by this subclass yet.");
-    }
 };
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/qt5/QtBuilder.hxx b/vcl/inc/qt5/QtBuilder.hxx
index 57a81c0fd8cc..2bf4b67e47ac 100644
--- a/vcl/inc/qt5/QtBuilder.hxx
+++ b/vcl/inc/qt5/QtBuilder.hxx
@@ -53,6 +53,10 @@ public:
                                     bool bToolbarItem) override;
     virtual void applyPackingProperties(QObject* pCurrentChild, QObject* 
pParent,
                                         const stringmap& rPackingProperties) 
override;
+    virtual void applyTabChildProperties(QObject* pParent, const 
std::vector<OUString>& rIDs,
+                                         
std::vector<vcl::EnumContext::Context>& rContext,
+                                         stringmap& rProperties,
+                                         stringmap& rAtkProperties) override;
     virtual void insertComboBoxOrListBoxItems(QObject* pObject, stringmap& 
rMap,
                                               const 
std::vector<ComboBoxTextItem>& rItems) override;
 
diff --git a/vcl/qt5/QtBuilder.cxx b/vcl/qt5/QtBuilder.cxx
index 347e342fb9ed..68ecf56c4126 100644
--- a/vcl/qt5/QtBuilder.cxx
+++ b/vcl/qt5/QtBuilder.cxx
@@ -477,6 +477,13 @@ void QtBuilder::applyPackingProperties(QObject* 
pCurrentChild, QObject* pParent,
         SAL_WARN("vcl.qt", "QtBuilder::applyPackingProperties not yet 
implemented for this case");
 }
 
+void QtBuilder::applyTabChildProperties(QObject*, const std::vector<OUString>&,
+                                        
std::vector<vcl::EnumContext::Context>&, stringmap&,
+                                        stringmap&)
+{
+    assert(false && "Not implemented yet");
+}
+
 void QtBuilder::set_response(std::u16string_view sID, short nResponse)
 {
     QPushButton* pPushButton = get<QPushButton>(sID);
diff --git a/vcl/source/window/builder.cxx b/vcl/source/window/builder.cxx
index fc54ba96e6c2..103da146b585 100644
--- a/vcl/source/window/builder.cxx
+++ b/vcl/source/window/builder.cxx
@@ -2489,94 +2489,31 @@ VclPtr<vcl::Window> 
VclBuilder::insertObject(vcl::Window *pParent, const OUStrin
     return pCurrentChild;
 }
 
-void VclBuilder::handleTabChild(vcl::Window *pParent, xmlreader::XmlReader 
&reader)
+void VclBuilder::applyTabChildProperties(vcl::Window* pParent, const 
std::vector<OUString>& rIDs,
+                                         
std::vector<vcl::EnumContext::Context>& rContext, stringmap& rProperties,
+                                         stringmap& rAtkProperties)
 {
-    std::vector<OUString> sIDs;
-
-    int nLevel = 1;
-    stringmap aProperties;
-    stringmap aAtkProperties;
-    std::vector<vcl::EnumContext::Context> context;
-
-    while(true)
-    {
-        xmlreader::Span name;
-        int nsId;
-
-        xmlreader::XmlReader::Result res = reader.nextItem(
-            xmlreader::XmlReader::Text::NONE, &name, &nsId);
-
-        if (res == xmlreader::XmlReader::Result::Begin)
-        {
-            ++nLevel;
-            if (name == "object")
-            {
-                while (reader.nextAttribute(&nsId, &name))
-                {
-                    if (name == "id")
-                    {
-                        name = reader.getAttributeValue(false);
-                        OUString sID(name.begin, name.length, 
RTL_TEXTENCODING_UTF8);
-                        sal_Int32 nDelim = sID.indexOf(':');
-                        if (nDelim != -1)
-                        {
-                            aProperties[u"customproperty"_ustr] = 
sID.copy(nDelim + 1);
-                            sID = sID.copy(0, nDelim);
-                        }
-                        sIDs.push_back(sID);
-                    }
-                }
-            }
-            else if (name == "style")
-            {
-                int nPriority = 0;
-                context = handleStyle(reader, nPriority);
-                --nLevel;
-            }
-            else if (name == "property")
-                collectProperty(reader, aProperties);
-            else if (name == "child" && isHorizontalTabControl(pParent))
-            {
-                // just to collect the atk properties (if any) for the label
-                handleChild(nullptr, &aAtkProperties, reader);
-                --nLevel;
-            }
-        }
-
-        if (res == xmlreader::XmlReader::Result::End)
-            --nLevel;
-
-        if (!nLevel)
-            break;
-
-        if (res == xmlreader::XmlReader::Result::Done)
-            break;
-    }
-
-    if (!pParent)
-        return;
-
     TabControl* pTabControl = isHorizontalTabControl(pParent) ? 
static_cast<TabControl*>(pParent) : nullptr;
     VerticalTabControl *pVerticalTabControl = pParent->GetType() == 
WindowType::VERTICALTABCONTROL ?
         static_cast<VerticalTabControl*>(pParent) : nullptr;
     assert(pTabControl || pVerticalTabControl);
-    VclBuilder::stringmap::iterator aFind = aProperties.find(u"label"_ustr);
-    if (aFind != aProperties.end())
+    VclBuilder::stringmap::iterator aFind = rProperties.find(u"label"_ustr);
+    if (aFind != rProperties.end())
     {
-        OUString sTooltip(extractTooltipText(aProperties));
+        OUString sTooltip(extractTooltipText(rProperties));
         if (pTabControl)
         {
             sal_uInt16 nPageId = pTabControl->GetCurPageId();
             pTabControl->SetPageText(nPageId, aFind->second);
-            pTabControl->SetPageName(nPageId, sIDs.back());
+            pTabControl->SetPageName(nPageId, rIDs.back());
             pTabControl->SetHelpText(nPageId, sTooltip);
-            if (!context.empty())
+            if (!rContext.empty())
             {
                 TabPage* pPage = pTabControl->GetTabPage(nPageId);
-                pPage->SetContext(std::move(context));
+                pPage->SetContext(std::move(rContext));
             }
 
-            for (auto const& [ rKey, rValue ] : aAtkProperties)
+            for (auto const& [ rKey, rValue ] : rAtkProperties)
             {
                 if (rKey == "AtkObject::accessible-name")
                     pTabControl->SetAccessibleName(nPageId, rValue);
@@ -2590,8 +2527,8 @@ void VclBuilder::handleTabChild(vcl::Window *pParent, 
xmlreader::XmlReader &read
         else
         {
             OUString 
sLabel(BuilderUtils::convertMnemonicMarkup(aFind->second));
-            OUString sIconName(extractIconName(aProperties));
-            pVerticalTabControl->InsertPage(sIDs.front(), sLabel, 
loadThemeImage(sIconName), sTooltip,
+            OUString sIconName(extractIconName(rProperties));
+            pVerticalTabControl->InsertPage(rIDs.front(), sLabel, 
loadThemeImage(sIconName), sTooltip,
                                             
pVerticalTabControl->GetPageParent()->GetWindow(GetWindowType::LastChild));
         }
     }
commit d18d05e2f7bfabef3d0783d4de550bf97b8937fd
Author:     Michael Weghorn <m.wegh...@posteo.de>
AuthorDate: Sat Nov 9 20:44:42 2024 +0100
Commit:     Michael Weghorn <m.wegh...@posteo.de>
CommitDate: Sun Nov 10 12:28:32 2024 +0100

    tdf#130857 VclBuilder: Abstract tab control check from VCL details
    
    In VclBuilder::handleTabChild, move casting the vcl::Window to
    TabControl further down to avoid vcl::Window specific code in
    the XML parsing logic.
    Introduce a new purely virtual helper method
    WidgetBuilder::isHorizontalTabControl,
    implement for VclBuilder and QtBuilder and
    use that in the XML parsing logic instead
    of directly checking whether the parent is
    a TabControl widget.
    
    This  gets rid of one detail specific to the VCL
    implementation in the XML parsing part and is in
    preparation of further refactoring of
    VclBuilder::handleTabChild for reuse with QtBuilder.
    
    Change-Id: I05c637f81bce4a5cdd443960a1ad096c347df560
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/176319
    Tested-by: Jenkins
    Reviewed-by: Michael Weghorn <m.wegh...@posteo.de>

diff --git a/include/vcl/builder.hxx b/include/vcl/builder.hxx
index 1ea9410fd6b6..1db211394cf3 100644
--- a/include/vcl/builder.hxx
+++ b/include/vcl/builder.hxx
@@ -300,6 +300,8 @@ private:
     void setContext(vcl::Window* pWindow,
                     std::vector<vcl::EnumContext::Context>&& aContext) 
override;
 
+    virtual bool isHorizontalTabControl(vcl::Window* pWindow) override;
+
     PackingData get_window_packing_data(const vcl::Window *pWindow) const;
     void        set_window_packing_position(const vcl::Window *pWindow, 
sal_Int32 nPosition);
 
diff --git a/include/vcl/widgetbuilder.hxx b/include/vcl/widgetbuilder.hxx
index aad9651fbaed..d12d68ad1cf7 100644
--- a/include/vcl/widgetbuilder.hxx
+++ b/include/vcl/widgetbuilder.hxx
@@ -298,6 +298,9 @@ protected:
     virtual void setPriority(Widget* pWidget, int nPriority) = 0;
     virtual void setContext(Widget* pWidget, 
std::vector<vcl::EnumContext::Context>&& aContext) = 0;
 
+    // Whether the given widget is a horizontal, i.e. non-vertical tab control
+    virtual bool isHorizontalTabControl(Widget* pWidget) = 0;
+
     // These methods are currently only implemented by VclBuilder and should be
     // refactored as described in the class documentation above (split into
     // parsing done in this class + overridable methods that don't need 
XmlReader
diff --git a/vcl/inc/qt5/QtBuilder.hxx b/vcl/inc/qt5/QtBuilder.hxx
index d77ada13bea4..57a81c0fd8cc 100644
--- a/vcl/inc/qt5/QtBuilder.hxx
+++ b/vcl/inc/qt5/QtBuilder.hxx
@@ -69,6 +69,8 @@ public:
     virtual void setContext(QObject* pObject,
                             std::vector<vcl::EnumContext::Context>&& aContext) 
override;
 
+    virtual bool isHorizontalTabControl(QObject* pObject) override;
+
     virtual void set_response(std::u16string_view sID, short nResponse) 
override;
 
 private:
diff --git a/vcl/qt5/QtBuilder.cxx b/vcl/qt5/QtBuilder.cxx
index 1249cc104536..347e342fb9ed 100644
--- a/vcl/qt5/QtBuilder.cxx
+++ b/vcl/qt5/QtBuilder.cxx
@@ -29,6 +29,7 @@
 #include <QtWidgets/QPushButton>
 #include <QtWidgets/QRadioButton>
 #include <QtWidgets/QScrollArea>
+#include <QtWidgets/QTabWidget>
 #include <QtWidgets/QTreeView>
 
 namespace
@@ -398,6 +399,17 @@ void QtBuilder::setContext(QObject*, 
std::vector<vcl::EnumContext::Context>&&)
     SAL_WARN("vcl.qt", "Ignoring context");
 }
 
+bool QtBuilder::isHorizontalTabControl(QObject* pObject)
+{
+    QTabWidget* pTabWidget = qobject_cast<QTabWidget*>(pObject);
+    if (!pTabWidget)
+        return false;
+
+    const QTabWidget::TabPosition ePosition = pTabWidget->tabPosition();
+    return ePosition == QTabWidget::TabPosition::North
+           || ePosition == QTabWidget::TabPosition::South;
+}
+
 void QtBuilder::applyAtkProperties(QObject* pObject, const stringmap& 
rProperties, bool)
 {
     if (!pObject || !pObject->isWidgetType())
diff --git a/vcl/source/window/builder.cxx b/vcl/source/window/builder.cxx
index 925d84ac43bb..fc54ba96e6c2 100644
--- a/vcl/source/window/builder.cxx
+++ b/vcl/source/window/builder.cxx
@@ -2491,9 +2491,6 @@ VclPtr<vcl::Window> VclBuilder::insertObject(vcl::Window 
*pParent, const OUStrin
 
 void VclBuilder::handleTabChild(vcl::Window *pParent, xmlreader::XmlReader 
&reader)
 {
-    TabControl *pTabControl = pParent && pParent->GetType() == 
WindowType::TABCONTROL ?
-        static_cast<TabControl*>(pParent) : nullptr;
-
     std::vector<OUString> sIDs;
 
     int nLevel = 1;
@@ -2538,7 +2535,7 @@ void VclBuilder::handleTabChild(vcl::Window *pParent, 
xmlreader::XmlReader &read
             }
             else if (name == "property")
                 collectProperty(reader, aProperties);
-            else if (pTabControl && name == "child")
+            else if (name == "child" && isHorizontalTabControl(pParent))
             {
                 // just to collect the atk properties (if any) for the label
                 handleChild(nullptr, &aAtkProperties, reader);
@@ -2559,6 +2556,7 @@ void VclBuilder::handleTabChild(vcl::Window *pParent, 
xmlreader::XmlReader &read
     if (!pParent)
         return;
 
+    TabControl* pTabControl = isHorizontalTabControl(pParent) ? 
static_cast<TabControl*>(pParent) : nullptr;
     VerticalTabControl *pVerticalTabControl = pParent->GetType() == 
WindowType::VERTICALTABCONTROL ?
         static_cast<VerticalTabControl*>(pParent) : nullptr;
     assert(pTabControl || pVerticalTabControl);
@@ -3006,6 +3004,11 @@ void VclBuilder::setContext(vcl::Window* pWindow, 
std::vector<vcl::EnumContext::
         pContextControl->SetContext(std::move(aContext));
 }
 
+bool VclBuilder::isHorizontalTabControl(vcl::Window* pWindow)
+{
+    return pWindow && pWindow->GetType() == WindowType::TABCONTROL;
+}
+
 std::vector<ComboBoxTextItem> BuilderBase::handleItems(xmlreader::XmlReader& 
reader) const
 {
     int nLevel = 1;

Reply via email to