include/vcl/weld/TreeView.hxx   |   26 ++++++++++++++------------
 vcl/inc/qt5/QtTreeViewModel.hxx |   11 +++++++++++
 vcl/qt5/QtInstanceBuilder.cxx   |    1 +
 vcl/qt5/QtInstanceTreeView.cxx  |   37 ++++++++++++++++++++++++++-----------
 vcl/qt5/QtTreeViewModel.cxx     |   34 ++++++++++++++++++++++++++++++++--
 5 files changed, 84 insertions(+), 25 deletions(-)

New commits:
commit b7147efd95c075028a7a93fce8cfdb014db6773d
Author:     Michael Weghorn <[email protected]>
AuthorDate: Wed Jan 14 12:34:40 2026 +0100
Commit:     Michael Weghorn <[email protected]>
CommitDate: Thu Jan 15 01:34:39 2026 +0100

    tdf#130857 qt weld: Support "Expert Configuration" dialog
    
    This means that native Qt widgets are used for that dialog
    now when using the qt5 or qt6 VCL plugin and starting LO with
    environment variable SAL_VCL_QT_USE_WELDED_WIDGETS=1 set.
    
    The dialog can be triggered like this:
    
    * start Writer
    * "Tools" -> "Options" -> "Advanced" -> "Expert Configuration"
    
    This makes use of support for on-demand treeview children
    which was implemented in previous commit
    
        Change-Id: I269710801e54656b5891215145d7e4d3790aad18
        Author: Michael Weghorn <[email protected]>
        Date:   Wed Jan 14 12:23:16 2026 +0100
    
            tdf#130857 qt weld: Support on-demand TreeView items
    
    Change-Id: Ifcf32e08d816522366757268df9c36a6cac9a096
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/197268
    Reviewed-by: Michael Weghorn <[email protected]>
    Tested-by: Jenkins

diff --git a/vcl/qt5/QtInstanceBuilder.cxx b/vcl/qt5/QtInstanceBuilder.cxx
index 577d9923d267..496412bcc589 100644
--- a/vcl/qt5/QtInstanceBuilder.cxx
+++ b/vcl/qt5/QtInstanceBuilder.cxx
@@ -67,6 +67,7 @@ bool QtInstanceBuilder::IsUIFileSupported(const OUString& 
rUIFile, const weld::W
     // what is relevant for that particular one, without having to implement 
the full
     // weld API at once.
     static std::unordered_set<OUString> aSupportedUIFiles = {
+        u"cui/ui/aboutconfigdialog.ui"_ustr,
         u"cui/ui/aboutdialog.ui"_ustr,
         u"cui/ui/additionsdialog.ui"_ustr,
         u"cui/ui/breaknumberoption.ui"_ustr,
commit f53088eb09021ce6daa60fa37997bb2007d5c535
Author:     Michael Weghorn <[email protected]>
AuthorDate: Wed Jan 14 12:23:16 2026 +0100
Commit:     Michael Weghorn <[email protected]>
CommitDate: Thu Jan 15 01:34:32 2026 +0100

    tdf#130857 qt weld: Support on-demand TreeView items
    
    Implement support for on-demand child entries in
    QtInstanceTreeView.
    
    The documentation in the "expanding on-demand node details"
    section in include/vcl/weld/TreeView.hxx contains more details.
    
    So far, it was documenting that on-demand children are
    implemented by temporarily inserting a dummy child.
    
    For Qt, implement it a different way: Override
    QAbstractItemView::hasChildren in the QtTreeViewModel
    used in QtInstanceTreeView to always return true if
    on-demand children are enabled for an entry/item.
    
    If on-demand children are enabled, indicate that
    by setting a true boolean value for the new custom
    ROLE_CHILDREN_ON_DEMAND role in the item.
    
    Update the documentation in include/vcl/weld/TreeView.hxx
    to make clear that the use of dummy children is
    just one possible way of implementing support
    for on-demand children.
    
    On-demand children are used e.g. in the "Tools"
    -> "Options" -> "Advanced" -> "Expert Configuration"
    dialog that is not supported yet, but will be declared
    as supported in an upcoming commit, now that the
    required logic has been implemented.
    
    Change-Id: I269710801e54656b5891215145d7e4d3790aad18
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/197267
    Tested-by: Jenkins
    Reviewed-by: Michael Weghorn <[email protected]>

diff --git a/include/vcl/weld/TreeView.hxx b/include/vcl/weld/TreeView.hxx
index 194f770c89de..2456eba9f1c1 100644
--- a/include/vcl/weld/TreeView.hxx
+++ b/include/vcl/weld/TreeView.hxx
@@ -377,24 +377,26 @@ public:
     /* expanding on-demand node details
 
     When a node is added with children-on-demand (typically via 'insert' with
-    bChildrenOnDemand of true), then initially in reality the
-    children-on-demand node is given a 'placeholder' child entry to indicate
-    the load-on-demand state.
-
-    The 'placeholder' needs to be there for the expander indicator to be
-    drawn/shown even when there are no "real" entries yet. This child doesn't
-    exist for the purposes of any of the iterator methods, e.g. iter_has_child
-    on an on-demand node which hasn't been expanded yet is false. Likewise the
-    rest of the iterator methods skip over or otherwise ignore that node.
+    bChildrenOnDemand of true), then it shows an expander indicator even if
+    it doesn't have any "real" child entries (yet).
+
+    (Depending on the underlying toolkit, implementations may in reality give
+    the children-on-demand node a 'placeholder' child entry to indicate the
+    load-on-demand state and ensure the treeview draws/shows the expander
+    indicator even when there are no "real" entries yet. In that case, this
+    child doesn't exist for the purposes of any of the iterator methods,
+    e.g. iter_has_child on an on-demand node which hasn't been expanded yet
+    is false. Likewise the rest of the iterator methods skip over or otherwise
+    ignore that node.)
 
     Normal usage is the user clicks on the expander, the expansion mechanism
-    removes the 'placeholder' entry (set_children_on_demand(false)) and calls
+    disables on-demand nodes (set_children_on_demand(false)) and calls
     any installed expanding-callback (installable via connect_expanding) which
     has the opportunity to populate the node with children.
 
     If you decide to directly populate the children of an on-demand node
-    outside of the expanding-callback then you also need to explicitly remove
-    the 'placeholder' with set_children_on_demand(false) otherwise the treeview
+    outside of the expanding-callback then you also need to explicitly disable
+    on-demand mode with set_children_on_demand(false); otherwise the treeview
     is in an inconsistent state.  */
 
     virtual bool get_row_expanded(const TreeIter& rIter) const = 0;
diff --git a/vcl/inc/qt5/QtTreeViewModel.hxx b/vcl/inc/qt5/QtTreeViewModel.hxx
index 22e2c4010545..f485cd174187 100644
--- a/vcl/inc/qt5/QtTreeViewModel.hxx
+++ b/vcl/inc/qt5/QtTreeViewModel.hxx
@@ -28,7 +28,12 @@ public:
 
     virtual Qt::ItemFlags flags(const QModelIndex& rIndex) const override;
 
+    virtual bool hasChildren(const QModelIndex& rIndex = QModelIndex()) const 
override;
+
     void setEditableColumns(const std::unordered_set<int>& rEditableColumns);
+
+    bool getChildrenOnDemand(const QModelIndex& rIndex) const;
+    void setChildrenOnDemand(const QModelIndex& rIndex, bool 
bOnDemandChildren);
 };
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s 
cinkeys+=0=break: */
diff --git a/vcl/qt5/QtInstanceTreeView.cxx b/vcl/qt5/QtInstanceTreeView.cxx
index 02b2df1e0420..a0d07d45019c 100644
--- a/vcl/qt5/QtInstanceTreeView.cxx
+++ b/vcl/qt5/QtInstanceTreeView.cxx
@@ -53,10 +53,6 @@ void QtInstanceTreeView::do_insert(const weld::TreeIter* 
pParent, int nPos, cons
                                    VirtualDevice* pImageSurface, bool 
bChildrenOnDemand,
                                    weld::TreeIter* pRet)
 {
-    assert(!bChildrenOnDemand && "Not implemented yet");
-    // avoid -Werror=unused-parameter for release build
-    (void)bChildrenOnDemand;
-
     SolarMutexGuard g;
     GetQtInstance().RunInMainThread([&] {
         const QModelIndex aParentIndex
@@ -90,6 +86,9 @@ void QtInstanceTreeView::do_insert(const weld::TreeIter* 
pParent, int nPos, cons
             
itemFromIndex(toggleButtonModelIndex(QtInstanceTreeIter(aIndex)))->setCheckable(true);
         }
 
+        if (bChildrenOnDemand)
+            m_pModel->setChildrenOnDemand(aIndex, true);
+
         if (pRet)
             static_cast<QtInstanceTreeIter*>(pRet)->setModelIndex(aIndex);
     });
@@ -534,15 +533,24 @@ void QtInstanceTreeView::collapse_row(const 
weld::TreeIter& rIter)
     GetQtInstance().RunInMainThread([&] { 
m_pTreeView->collapse(modelIndex(rIter)); });
 }
 
-void QtInstanceTreeView::do_set_children_on_demand(const weld::TreeIter&, bool)
+void QtInstanceTreeView::do_set_children_on_demand(const weld::TreeIter& rIter,
+                                                   bool bChildrenOnDemand)
 {
-    assert(false && "Not implemented yet");
+    SolarMutexGuard g;
+
+    GetQtInstance().RunInMainThread(
+        [&] { m_pModel->setChildrenOnDemand(modelIndex(rIter), 
bChildrenOnDemand); });
 }
 
-bool QtInstanceTreeView::get_children_on_demand(const weld::TreeIter&) const
+bool QtInstanceTreeView::get_children_on_demand(const weld::TreeIter& rIter) 
const
 {
-    assert(false && "Not implemented yet");
-    return false;
+    SolarMutexGuard g;
+
+    bool bChildrenOnDemand = false;
+    GetQtInstance().RunInMainThread(
+        [&] { bChildrenOnDemand = 
m_pModel->getChildrenOnDemand(modelIndex(rIter)); });
+
+    return bChildrenOnDemand;
 }
 
 void QtInstanceTreeView::set_show_expanders(bool) { assert(false && "Not 
implemented yet"); }
diff --git a/vcl/qt5/QtTreeViewModel.cxx b/vcl/qt5/QtTreeViewModel.cxx
index 67e3d7ddfca4..4c41a175d3f5 100644
--- a/vcl/qt5/QtTreeViewModel.cxx
+++ b/vcl/qt5/QtTreeViewModel.cxx
@@ -12,6 +12,9 @@
 
 #include <QtGui/QStandardItemModel>
 
+// role used to indicate whether an item has on-demand children
+constexpr int ROLE_CHILDREN_ON_DEMAND = Qt::UserRole + 2000;
+
 QtTreeViewModel::QtTreeViewModel(QWidget* pParent)
     : QSortFilterProxyModel(pParent)
 {
@@ -28,9 +31,27 @@ Qt::ItemFlags QtTreeViewModel::flags(const QModelIndex& 
rIndex) const
     return eFlags;
 }
 
+bool QtTreeViewModel::hasChildren(const QModelIndex& rIndex) const
+{
+    if (getChildrenOnDemand(rIndex))
+        return true;
+
+    return QSortFilterProxyModel::hasChildren(rIndex);
+}
+
 void QtTreeViewModel::setEditableColumns(const std::unordered_set<int>& 
rEditableColumns)
 {
     m_aEditableColumns = rEditableColumns;
 }
 
+bool QtTreeViewModel::getChildrenOnDemand(const QModelIndex& rIndex) const
+{
+    return data(rIndex, ROLE_CHILDREN_ON_DEMAND).toBool();
+}
+
+void QtTreeViewModel::setChildrenOnDemand(const QModelIndex& rIndex, bool 
bOnDemandChildren)
+{
+    setData(rIndex, QVariant(bOnDemandChildren), ROLE_CHILDREN_ON_DEMAND);
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s 
cinkeys+=0=break: */
commit bb101bff7eab618dc2682fe7d91a8b04398b952a
Author:     Michael Weghorn <[email protected]>
AuthorDate: Wed Jan 14 11:34:48 2026 +0100
Commit:     Michael Weghorn <[email protected]>
CommitDate: Thu Jan 15 01:34:24 2026 +0100

    tdf#130857 qt weld: Implement TreeView::set_column_editables
    
    Extend the approach implemented in previous commit
    
        Change-Id: I36e188880fd5bc9eabbc9392f05b057ab3cfaea9
        Author: Michael Weghorn <[email protected]>
        Date:   Wed Jan 14 11:10:23 2026 +0100
    
            tdf#130857 qt weld: Make TreeView columns readonly by default
    
    to keep track of columns set as editable via
    QtInstanceTreeView::set_column_editables: Only
    clear the editable flag for items in columns that
    haven't explicitly been set to be editable.
    
    See the above-mentioned commit for more details/background.
    
    The implementation is still untested in practice
    as no dialog using weld::TreeView::set_column_editables
    method is supported yet with SAL_VCL_QT_USE_WELDED_WIDGETS=1.
    
    Change-Id: I77fa14ce15c6a04f36ee2b259078e18f4b4f350f
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/197266
    Tested-by: Jenkins
    Reviewed-by: Michael Weghorn <[email protected]>

diff --git a/vcl/inc/qt5/QtTreeViewModel.hxx b/vcl/inc/qt5/QtTreeViewModel.hxx
index 06af92c9c2cf..22e2c4010545 100644
--- a/vcl/inc/qt5/QtTreeViewModel.hxx
+++ b/vcl/inc/qt5/QtTreeViewModel.hxx
@@ -14,15 +14,21 @@
 #include <QtCore/QSortFilterProxyModel>
 #include <QtWidgets/QWidget>
 
+#include <unordered_set>
+
 /** Item model for QtInstanceTreeView. */
 class QtTreeViewModel : public QSortFilterProxyModel
 {
     Q_OBJECT
 
+    std::unordered_set<int> m_aEditableColumns;
+
 public:
     QtTreeViewModel(QWidget* pParent);
 
     virtual Qt::ItemFlags flags(const QModelIndex& rIndex) const override;
+
+    void setEditableColumns(const std::unordered_set<int>& rEditableColumns);
 };
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s 
cinkeys+=0=break: */
diff --git a/vcl/qt5/QtInstanceTreeView.cxx b/vcl/qt5/QtInstanceTreeView.cxx
index 7bdc24839267..02b2df1e0420 100644
--- a/vcl/qt5/QtInstanceTreeView.cxx
+++ b/vcl/qt5/QtInstanceTreeView.cxx
@@ -669,9 +669,16 @@ void QtInstanceTreeView::set_column_fixed_widths(const 
std::vector<int>& rWidths
     });
 }
 
-void QtInstanceTreeView::set_column_editables(const std::vector<bool>&)
+void QtInstanceTreeView::set_column_editables(const std::vector<bool>& 
rEditables)
 {
-    assert(false && "Not implemented yet");
+    std::unordered_set<int> aEditableColumns;
+    for (size_t i = 0; i < rEditables.size(); i++)
+    {
+        if (rEditables.at(i))
+            aEditableColumns.insert(i);
+    }
+
+    m_pModel->setEditableColumns(aEditableColumns);
 }
 
 int QtInstanceTreeView::get_column_width(int nCol) const
diff --git a/vcl/qt5/QtTreeViewModel.cxx b/vcl/qt5/QtTreeViewModel.cxx
index 20531e45c328..67e3d7ddfca4 100644
--- a/vcl/qt5/QtTreeViewModel.cxx
+++ b/vcl/qt5/QtTreeViewModel.cxx
@@ -20,8 +20,17 @@ QtTreeViewModel::QtTreeViewModel(QWidget* pParent)
 
 Qt::ItemFlags QtTreeViewModel::flags(const QModelIndex& rIndex) const
 {
-    // weld::TreeView columns are not editable by default
-    return QSortFilterProxyModel::flags(rIndex) & ~Qt::ItemIsEditable;
+    Qt::ItemFlags eFlags = QSortFilterProxyModel::flags(rIndex);
+
+    if (!m_aEditableColumns.contains(rIndex.column()))
+        eFlags &= ~Qt::ItemIsEditable;
+
+    return eFlags;
+}
+
+void QtTreeViewModel::setEditableColumns(const std::unordered_set<int>& 
rEditableColumns)
+{
+    m_aEditableColumns = rEditableColumns;
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s 
cinkeys+=0=break: */

Reply via email to