vcl/inc/qt5/QtInstanceNotebook.hxx | 8 ++ vcl/qt5/QtBuilder.cxx | 27 ++++++- vcl/qt5/QtInstanceNotebook.cxx | 141 +++++++++++++++++++++++++++++-------- 3 files changed, 145 insertions(+), 31 deletions(-)
New commits: commit 2f942db0c17512158747175ceee8cd2ed97cadee Author: Michael Weghorn <m.wegh...@posteo.de> AuthorDate: Sun Nov 10 18:54:28 2024 +0100 Commit: Michael Weghorn <m.wegh...@posteo.de> CommitDate: Mon Nov 11 01:48:36 2024 +0100 tdf#130857 tdf#142608 qt weld: Implement QtInstanceNotebook logic Implement all of the QtInstanceNotebook methods, see also GtkInstanceNotebook and SalInstanceNotebook for the gtk3 and VCL implementations for comparison. Unlike weld::Notebook, QTabWidget doesn't have the concept of IDs for tabs in addition to indices. Introduce a PROPERTY_TAB_PAGE_ID property that gets set on the widget of the corresponding tabs and holds the tab identifier in order to support that. Implement QtBuilder::applyTabChildProperties to set the tab label and ID property by using the newly introduced QtInstanceNotebook::setTabIdAndLabel, so only QtInstanceNotebook needs to handle that property. The weld::Container* returned by QtInstanceNotebook::get_page is owned by QtInstanceNotebook, so keep create one on demand and keep a mapping between tab pages and the corresponding weld::Container. In QtInstanceNotebook::insert_page, create a new widget and set a QVBoxLayout for now. That could be changed to use a different QLayout class in the future if that turns out to be more useful. In QtBuilder::makeObject, as the tab pages are children of the "GtkNotebook" in the .ui file, they are initially created as child widgets of the QTabWidget. However, they need to be set via QTabWidget::setTab instead, so add special handling for that case towards the end and unset the parent relationship and call that method. Change-Id: I52e11ecf053a48940b88b7e6d1e6f9ba8778d9bb Reviewed-on: https://gerrit.libreoffice.org/c/core/+/176353 Tested-by: Jenkins Reviewed-by: Michael Weghorn <m.wegh...@posteo.de> diff --git a/vcl/inc/qt5/QtInstanceNotebook.hxx b/vcl/inc/qt5/QtInstanceNotebook.hxx index d8e83fe90ac3..f55c9c60d9d6 100644 --- a/vcl/inc/qt5/QtInstanceNotebook.hxx +++ b/vcl/inc/qt5/QtInstanceNotebook.hxx @@ -9,16 +9,21 @@ #pragma once +#include "QtInstanceContainer.hxx" #include "QtInstanceWidget.hxx" #include <QtWidgets/QTabWidget> +#include <map> + class QtInstanceNotebook : public QObject, public QtInstanceWidget, public virtual weld::Notebook { Q_OBJECT QTabWidget* m_pTabWidget; + mutable std::map<QWidget*, std::unique_ptr<QtInstanceContainer>> m_aPageContainerInstances; + public: QtInstanceNotebook(QTabWidget* pTabWidget); @@ -35,6 +40,9 @@ public: virtual void set_show_tabs(bool bShow) override; virtual int get_n_pages() const override; virtual weld::Container* get_page(const OUString& rIdent) const override; + + static void setTabIdAndLabel(QTabWidget& rTabWidget, int nPage, const OUString& rIdent, + const OUString& rLabel); }; /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/qt5/QtBuilder.cxx b/vcl/qt5/QtBuilder.cxx index 38c6ad278c34..002a88fbbf55 100644 --- a/vcl/qt5/QtBuilder.cxx +++ b/vcl/qt5/QtBuilder.cxx @@ -11,6 +11,7 @@ #include <QtInstanceLinkButton.hxx> #include <QtInstanceMessageDialog.hxx> +#include <QtInstanceNotebook.hxx> #include <QtTools.hxx> #include <rtl/ustrbuf.hxx> @@ -289,6 +290,18 @@ QObject* QtBuilder::makeObject(QObject* pParent, std::u16string_view sName, cons if (!pWidget) pWidget = pLayoutParentWidget; + QTabWidget* pParentTabWidget = qobject_cast<QTabWidget*>(pParentWidget); + if (pParentTabWidget) + { + // remove QTabWidget child widget, set via QTabWidget::addTab instead + assert(pWidget); + pWidget->setParent(nullptr); + // initially, add tab with empty label, QtBuilder::applyTabChildProperties will evaluate actual one + pParentTabWidget->addTab(pWidget, QStringLiteral()); + // unset pParentWidget to not not create a layout below + pParentWidget = nullptr; + } + if (pWidget) { if (!pParentLayout && pParentWidget) @@ -481,11 +494,17 @@ 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&) +void QtBuilder::applyTabChildProperties(QObject* pParent, const std::vector<OUString>& rIDs, + std::vector<vcl::EnumContext::Context>&, + stringmap& rProperties, stringmap&) { - assert(false && "Not implemented yet"); + QTabWidget* pTabWidget = qobject_cast<QTabWidget*>(pParent); + assert(pTabWidget && "parent must be a QTabWidget"); + + // set ID and label for the last inserted tab + assert(rProperties.contains(u"label"_ustr) && "Tab has no label"); + QtInstanceNotebook::setTabIdAndLabel(*pTabWidget, pTabWidget->count() - 1, rIDs.front(), + rProperties.at(u"label"_ustr)); } void QtBuilder::set_response(std::u16string_view sID, short nResponse) diff --git a/vcl/qt5/QtInstanceNotebook.cxx b/vcl/qt5/QtInstanceNotebook.cxx index b6487fe79582..bb26817c3196 100644 --- a/vcl/qt5/QtInstanceNotebook.cxx +++ b/vcl/qt5/QtInstanceNotebook.cxx @@ -10,6 +10,15 @@ #include <QtInstanceNotebook.hxx> #include <QtInstanceNotebook.moc> +#include <vcl/qt/QtUtils.hxx> + +#include <QtWidgets/QTabBar> +#include <QtWidgets/QVBoxLayout> +#include <QtWidgets/QWidget> + +// property on each tab's widget holding the accessible identifier of that tab +const char* const PROPERTY_TAB_PAGE_ID = "tab-page-id"; + QtInstanceNotebook::QtInstanceNotebook(QTabWidget* pTabWidget) : QtInstanceWidget(pTabWidget) , m_pTabWidget(pTabWidget) @@ -19,65 +28,143 @@ QtInstanceNotebook::QtInstanceNotebook(QTabWidget* pTabWidget) int QtInstanceNotebook::get_current_page() const { - assert(false && "Not implemented yet"); - return -1; + SolarMutexGuard g; + int nCurrentIndex = 0; + GetQtInstance().RunInMainThread([&] { nCurrentIndex = m_pTabWidget->currentIndex(); }); + return nCurrentIndex; } -int QtInstanceNotebook::get_page_index(const OUString&) const +int QtInstanceNotebook::get_page_index(const OUString& rIdent) const { - assert(false && "Not implemented yet"); - return -1; + SolarMutexGuard g; + + const QString sId = toQString(rIdent); + int nIndex = -1; + GetQtInstance().RunInMainThread([&] { + for (int i = 0; i < m_pTabWidget->count(); ++i) + { + if (get_page_ident(i) == rIdent) + { + nIndex = i; + return; + } + } + }); + return nIndex; } -OUString QtInstanceNotebook::get_page_ident(int) const +OUString QtInstanceNotebook::get_page_ident(int nPage) const { - assert(false && "Not implemented yet"); - return OUString(); + SolarMutexGuard g; + + OUString sIdent; + GetQtInstance().RunInMainThread([&] { + QWidget* pPage = m_pTabWidget->widget(nPage); + assert(pPage); + QVariant aIdVariant = pPage->property(PROPERTY_TAB_PAGE_ID); + if (aIdVariant.canConvert<QString>()) + sIdent = toOUString(aIdVariant.toString()); + }); + return sIdent; } OUString QtInstanceNotebook::get_current_page_ident() const { - assert(false && "Not implemented yet"); - return OUString(); + SolarMutexGuard g; + + OUString sIdent; + GetQtInstance().RunInMainThread([&] { sIdent = get_page_ident(m_pTabWidget->currentIndex()); }); + return sIdent; } -void QtInstanceNotebook::set_current_page(int) { assert(false && "Not implemented yet"); } +void QtInstanceNotebook::set_current_page(int nPage) +{ + SolarMutexGuard g; + GetQtInstance().RunInMainThread([&] { m_pTabWidget->setCurrentIndex(nPage); }); +} -void QtInstanceNotebook::set_current_page(const OUString&) +void QtInstanceNotebook::set_current_page(const OUString& rIdent) { - assert(false && "Not implemented yet"); + set_current_page(get_page_index(rIdent)); } -void QtInstanceNotebook::remove_page(const OUString&) { assert(false && "Not implemented yet"); } +void QtInstanceNotebook::remove_page(const OUString& rIdent) +{ + SolarMutexGuard g; + GetQtInstance().RunInMainThread([&] { m_pTabWidget->removeTab(get_page_index(rIdent)); }); +} -void QtInstanceNotebook::insert_page(const OUString&, const OUString&, int) +void QtInstanceNotebook::insert_page(const OUString& rIdent, const OUString& rLabel, int nPos) { - assert(false && "Not implemented yet"); + SolarMutexGuard g; + GetQtInstance().RunInMainThread([&] { + QWidget* pPage = new QWidget; + pPage->setLayout(new QVBoxLayout); + pPage->setProperty(PROPERTY_TAB_PAGE_ID, toQString(rIdent)); + m_pTabWidget->insertTab(nPos, pPage, toQString(rLabel)); + }); } -void QtInstanceNotebook::set_tab_label_text(const OUString&, const OUString&) +void QtInstanceNotebook::set_tab_label_text(const OUString& rIdent, const OUString& rLabel) { - assert(false && "Not implemented yet"); + SolarMutexGuard g; + GetQtInstance().RunInMainThread([&] { + const int nIndex = get_page_index(rIdent); + m_pTabWidget->setTabText(nIndex, toQString(rLabel)); + }); } -OUString QtInstanceNotebook::get_tab_label_text(const OUString&) const +OUString QtInstanceNotebook::get_tab_label_text(const OUString& rIdent) const { - assert(false && "Not implemented yet"); - return OUString(); + SolarMutexGuard g; + OUString sText; + GetQtInstance().RunInMainThread([&] { + const int nIndex = get_page_index(rIdent); + sText = toOUString(m_pTabWidget->tabText(nIndex)); + }); + return sText; } -void QtInstanceNotebook::set_show_tabs(bool) { assert(false && "Not implemented yet"); } +void QtInstanceNotebook::set_show_tabs(bool bShow) +{ + SolarMutexGuard g; + GetQtInstance().RunInMainThread([&] { m_pTabWidget->tabBar()->setVisible(bShow); }); +} int QtInstanceNotebook::get_n_pages() const { - assert(false && "Not implemented yet"); - return 0; + SolarMutexGuard g; + int nCount = 0; + GetQtInstance().RunInMainThread([&] { nCount = m_pTabWidget->count(); }); + return nCount; +} + +weld::Container* QtInstanceNotebook::get_page(const OUString& rIdent) const +{ + SolarMutexGuard g; + + QWidget* pWidget = nullptr; + GetQtInstance().RunInMainThread([&] { + const int nIndex = get_page_index(rIdent); + pWidget = m_pTabWidget->widget(nIndex); + }); + + if (!m_aPageContainerInstances.contains(pWidget)) + m_aPageContainerInstances.emplace(pWidget, std::make_unique<QtInstanceContainer>(pWidget)); + + return m_aPageContainerInstances.at(pWidget).get(); } -weld::Container* QtInstanceNotebook::get_page(const OUString&) const +void QtInstanceNotebook::setTabIdAndLabel(QTabWidget& rTabWidget, int nPage, const OUString& rIdent, + const OUString& rLabel) { - assert(false && "Not implemented yet"); - return nullptr; + SolarMutexGuard g; + GetQtInstance().RunInMainThread([&] { + QWidget* pPage = rTabWidget.widget(nPage); + assert(pPage); + pPage->setProperty(PROPERTY_TAB_PAGE_ID, toQString(rIdent)); + rTabWidget.setTabText(nPage, toQString(rLabel)); + }); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */