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;