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: */

Reply via email to