vcl/CustomTarget_qt5_moc.mk        |    1 +
 vcl/CustomTarget_qt6_moc.mk        |    1 +
 vcl/Library_vclplug_qt5.mk         |    1 +
 vcl/Library_vclplug_qt6.mk         |    1 +
 vcl/inc/qt5/QtInstanceTreeView.hxx |    4 ++--
 vcl/inc/qt5/QtTreeViewModel.hxx    |   28 ++++++++++++++++++++++++++++
 vcl/inc/qt6/QtTreeViewModel.hxx    |   12 ++++++++++++
 vcl/qt5/QtBuilder.cxx              |    8 +++-----
 vcl/qt5/QtInstanceTreeView.cxx     |    2 +-
 vcl/qt5/QtTreeViewModel.cxx        |   27 +++++++++++++++++++++++++++
 vcl/qt6/QtTreeViewModel.cxx        |   12 ++++++++++++
 11 files changed, 89 insertions(+), 8 deletions(-)

New commits:
commit e276093f3ab2a94d9be30c3fd2d2e402f4a820c8
Author:     Michael Weghorn <[email protected]>
AuthorDate: Wed Jan 14 11:10:23 2026 +0100
Commit:     Michael Weghorn <[email protected]>
CommitDate: Thu Jan 15 01:34:16 2026 +0100

    tdf#130857 qt weld: Make TreeView columns readonly by default
    
    By default weld::TreeView (text) columns are readonly.
    weld::TreeView::set_column_editables can be used to
    make specific columns editable.
    
    So far, text columns in QtInstanceTreeView were always editable,
    as seen e.g. for this scenario:
    
    * copy text from somewhere else (e.g. browser)
    * start LO Writer with the qt6 VCL plugin and 
SAL_VCL_QT_USE_WELDED_WIDGETS=1
    * press Shift+Ctrl+V to open the "Paste Special" dialog
    * double-click on the "Unformatted text" row
    
    Without this commit, this would result in entering
    edit mode, i.e. being able to replace the
    "Unformatted text" text of the row, which doesn't make
    sense.
    
    Override QAbstractItemModel::flags in the QtTreeViewModel
    used in QtInstanceTreeView to remove the Qt::ItemIsEditable
    flag for now.
    
    For checkbox columns/items for which the Qt::ItemIsUserCheckable
    state is set, the checkboxes can still be (un)checked by the user
    (e.g. in the "Tools" -> "Spelling" -> "Options" dialog).
    
    The logic will be further adjusted in an upcoming commit
    implementing QtInstanceTreeView::set_column_editables.
    
    It is worth noting these lines in the SalInstanceTreeView ctor:
    
        // by default, 1st one is editable, others not; override with 
set_column_editables
        m_xTreeView->SetTabEditable(0, true);
    
    and comment [1] in a related Gerrit change:
    
    > perhaps ideally no column should be editable by default, but that
    > requires looking at every existing tree widget and fixing them up with
    > set_column_editables calls which sounds like lot of work...
    
    While that approach may be too risky to do for SalInstanceTreeView,
    aim to do that for QtInstanceTreeView, as it's not used by default
    anywhere yet: The idea is to add any missing
    weld::TreeView::set_column_editables calls in dialog/UI component
    implementations that depend on the first column being editable once
    support for those is declared in QtInstanceBuilder::isUIFileSupported.
    
    For the "Paste Special" dialog example mentioned above:
    Now, the text is no longer editable, and the row is activated
    and the clipboard text is inserted as expected.
    
    [1] 
https://gerrit.libreoffice.org/c/core/+/137561/comments/3990a6fa_77237ad7
    
    Change-Id: I36e188880fd5bc9eabbc9392f05b057ab3cfaea9
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/197265
    Tested-by: Jenkins
    Reviewed-by: Michael Weghorn <[email protected]>

diff --git a/vcl/inc/qt5/QtTreeViewModel.hxx b/vcl/inc/qt5/QtTreeViewModel.hxx
index ed7b4d7d0eab..06af92c9c2cf 100644
--- a/vcl/inc/qt5/QtTreeViewModel.hxx
+++ b/vcl/inc/qt5/QtTreeViewModel.hxx
@@ -21,6 +21,8 @@ class QtTreeViewModel : public QSortFilterProxyModel
 
 public:
     QtTreeViewModel(QWidget* pParent);
+
+    virtual Qt::ItemFlags flags(const QModelIndex& rIndex) const override;
 };
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s 
cinkeys+=0=break: */
diff --git a/vcl/qt5/QtTreeViewModel.cxx b/vcl/qt5/QtTreeViewModel.cxx
index a2dd6fc8524c..20531e45c328 100644
--- a/vcl/qt5/QtTreeViewModel.cxx
+++ b/vcl/qt5/QtTreeViewModel.cxx
@@ -18,4 +18,10 @@ QtTreeViewModel::QtTreeViewModel(QWidget* pParent)
     setSourceModel(new QStandardItemModel(pParent));
 }
 
+Qt::ItemFlags QtTreeViewModel::flags(const QModelIndex& rIndex) const
+{
+    // weld::TreeView columns are not editable by default
+    return QSortFilterProxyModel::flags(rIndex) & ~Qt::ItemIsEditable;
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s 
cinkeys+=0=break: */
commit c1fbad547771c64d164b8d89a3f50fdf1d15da2d
Author:     Michael Weghorn <[email protected]>
AuthorDate: Wed Jan 14 10:57:00 2026 +0100
Commit:     Michael Weghorn <[email protected]>
CommitDate: Thu Jan 15 01:34:08 2026 +0100

    tdf#130857 qt weld: Add custom class for QtInstanceTreeView model
    
    Instead of using Qt's QSortFilterProxyModel directly
    for the model of the QTreeView used in QtInstanceTreeView,
    introduce a new subclass QtTreeViewModel that will be used
    to customize behavior to account for the weld::TreeView
    requirements.
    
    Initially, only move the logic to set the
    underlying QStandardItemModel into the new
    class.
    No change in behavior intended yet.
    
    Further changes will follow in upcoming commits,
    in order to implement support for on-demand children
    and distinguising between readonly and editable columns
    (see the currently still unimplemented methods
    QtInstanceTreeView::do_set_children_on_demand and
    QtInstanceTreeView::set_column_editables).
    
    Change-Id: Ic5165e99b9fa3e3c51ade7863f979e2067496f9e
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/197264
    Tested-by: Jenkins
    Reviewed-by: Michael Weghorn <[email protected]>

diff --git a/vcl/CustomTarget_qt5_moc.mk b/vcl/CustomTarget_qt5_moc.mk
index ba043a0e036e..f8f2a5819eaa 100644
--- a/vcl/CustomTarget_qt5_moc.mk
+++ b/vcl/CustomTarget_qt5_moc.mk
@@ -62,6 +62,7 @@ $(call gb_CustomTarget_get_target,vcl/qt5) : \
        $(gb_CustomTarget_workdir)/vcl/qt5/QtMainWindow.moc \
        $(gb_CustomTarget_workdir)/vcl/qt5/QtMenu.moc \
        $(gb_CustomTarget_workdir)/vcl/qt5/QtTransferable.moc \
+       $(gb_CustomTarget_workdir)/vcl/qt5/QtTreeViewModel.moc \
        $(gb_CustomTarget_workdir)/vcl/qt5/QtObject.moc \
        $(gb_CustomTarget_workdir)/vcl/qt5/QtTimer.moc \
        $(gb_CustomTarget_workdir)/vcl/qt5/QtWidget.moc \
diff --git a/vcl/CustomTarget_qt6_moc.mk b/vcl/CustomTarget_qt6_moc.mk
index be3f11dad86d..f545b285150e 100644
--- a/vcl/CustomTarget_qt6_moc.mk
+++ b/vcl/CustomTarget_qt6_moc.mk
@@ -62,6 +62,7 @@ $(call gb_CustomTarget_get_target,vcl/qt6) : \
        $(gb_CustomTarget_workdir)/vcl/qt6/QtMainWindow.moc \
        $(gb_CustomTarget_workdir)/vcl/qt6/QtMenu.moc \
        $(gb_CustomTarget_workdir)/vcl/qt6/QtTransferable.moc \
+       $(gb_CustomTarget_workdir)/vcl/qt6/QtTreeViewModel.moc \
        $(gb_CustomTarget_workdir)/vcl/qt6/QtObject.moc \
        $(gb_CustomTarget_workdir)/vcl/qt6/QtTimer.moc \
        $(gb_CustomTarget_workdir)/vcl/qt6/QtWidget.moc \
diff --git a/vcl/Library_vclplug_qt5.mk b/vcl/Library_vclplug_qt5.mk
index 61eb1f2683e5..90826dcd06ae 100644
--- a/vcl/Library_vclplug_qt5.mk
+++ b/vcl/Library_vclplug_qt5.mk
@@ -155,6 +155,7 @@ $(eval $(call gb_Library_add_exception_objects,vclplug_qt5,\
     vcl/qt5/QtTimer \
     vcl/qt5/QtTools \
     vcl/qt5/QtTransferable \
+    vcl/qt5/QtTreeViewModel \
     vcl/qt5/QtVirtualDevice \
     vcl/qt5/QtWidget \
     vcl/qt5/QtXAccessible \
diff --git a/vcl/Library_vclplug_qt6.mk b/vcl/Library_vclplug_qt6.mk
index b1aa8edcace3..83cf22d38888 100644
--- a/vcl/Library_vclplug_qt6.mk
+++ b/vcl/Library_vclplug_qt6.mk
@@ -154,6 +154,7 @@ $(eval $(call gb_Library_add_exception_objects,vclplug_qt6,\
     vcl/qt6/QtTimer \
     vcl/qt6/QtTools \
     vcl/qt6/QtTransferable \
+    vcl/qt6/QtTreeViewModel \
     vcl/qt6/QtVirtualDevice \
     vcl/qt6/QtWidget \
     vcl/qt6/QtXAccessible \
diff --git a/vcl/inc/qt5/QtInstanceTreeView.hxx 
b/vcl/inc/qt5/QtInstanceTreeView.hxx
index f8e0dbc7ff90..b1606d884126 100644
--- a/vcl/inc/qt5/QtInstanceTreeView.hxx
+++ b/vcl/inc/qt5/QtInstanceTreeView.hxx
@@ -11,10 +11,10 @@
 
 #include "QtInstanceTreeIter.hxx"
 #include "QtInstanceItemView.hxx"
+#include "QtTreeViewModel.hxx"
 
 #include <vcl/weld/TreeView.hxx>
 
-#include <QtCore/QSortFilterProxyModel>
 #include <QtGui/QStandardItemModel>
 #include <QtWidgets/QTreeView>
 
@@ -26,7 +26,7 @@ class QtInstanceTreeView : public QtInstanceItemView, public 
virtual weld::TreeV
 
     /** The model displayed in the tree view. The proxy model takes care of 
sorting
      *  if sorting is enabled. */
-    QSortFilterProxyModel* m_pModel;
+    QtTreeViewModel* m_pModel;
 
     /** The QStandardItemModel used as the source model for `m_pModel`. */
     QStandardItemModel* m_pSourceModel;
diff --git a/vcl/inc/qt5/QtTreeViewModel.hxx b/vcl/inc/qt5/QtTreeViewModel.hxx
new file mode 100644
index 000000000000..ed7b4d7d0eab
--- /dev/null
+++ b/vcl/inc/qt5/QtTreeViewModel.hxx
@@ -0,0 +1,26 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; 
fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <vcl/weld/TreeView.hxx>
+
+#include <QtCore/QSortFilterProxyModel>
+#include <QtWidgets/QWidget>
+
+/** Item model for QtInstanceTreeView. */
+class QtTreeViewModel : public QSortFilterProxyModel
+{
+    Q_OBJECT
+
+public:
+    QtTreeViewModel(QWidget* pParent);
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s 
cinkeys+=0=break: */
diff --git a/vcl/inc/qt6/QtTreeViewModel.hxx b/vcl/inc/qt6/QtTreeViewModel.hxx
new file mode 100644
index 000000000000..a1219ed58596
--- /dev/null
+++ b/vcl/inc/qt6/QtTreeViewModel.hxx
@@ -0,0 +1,12 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; 
fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "../qt5/QtTreeViewModel.hxx"
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s 
cinkeys+=0=break: */
diff --git a/vcl/qt5/QtBuilder.cxx b/vcl/qt5/QtBuilder.cxx
index 098cd9af2701..1e943ac18e6c 100644
--- a/vcl/qt5/QtBuilder.cxx
+++ b/vcl/qt5/QtBuilder.cxx
@@ -16,10 +16,10 @@
 #include <QtInstanceNotebook.hxx>
 #include <QtInstanceTreeView.hxx>
 #include <QtHyperlinkLabel.hxx>
+#include <QtTreeViewModel.hxx>
 
 #include <vcl/qt/QtUtils.hxx>
 
-#include <QtCore/QSortFilterProxyModel>
 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
 #include <QtGui/QActionGroup>
 #endif
@@ -420,10 +420,8 @@ QObject* QtBuilder::makeObject(QObject* pParent, 
std::u16string_view sName, std:
     else if (sName == u"GtkTreeView")
     {
         QTreeView* pTreeView = new QTreeView(pParentWidget);
-        QStandardItemModel* pItemModel = new QStandardItemModel(pTreeView);
-        QSortFilterProxyModel* pProxyModel = new 
QSortFilterProxyModel(pTreeView);
-        pProxyModel->setSourceModel(pItemModel);
-        pTreeView->setModel(pProxyModel);
+        QtTreeViewModel* pTreeViewModel = new QtTreeViewModel(pTreeView);
+        pTreeView->setModel(pTreeViewModel);
         pTreeView->setHeaderHidden(!extractHeadersVisible(rMap));
         pTreeView->setRootIsDecorated(extractShowExpanders(rMap));
         setItemViewProperties(*pTreeView, rMap);
diff --git a/vcl/qt5/QtInstanceTreeView.cxx b/vcl/qt5/QtInstanceTreeView.cxx
index a53012aa76a4..7bdc24839267 100644
--- a/vcl/qt5/QtInstanceTreeView.cxx
+++ b/vcl/qt5/QtInstanceTreeView.cxx
@@ -24,7 +24,7 @@ QtInstanceTreeView::QtInstanceTreeView(QTreeView* pTreeView)
 {
     assert(m_pTreeView);
 
-    m_pModel = qobject_cast<QSortFilterProxyModel*>(m_pTreeView->model());
+    m_pModel = qobject_cast<QtTreeViewModel*>(m_pTreeView->model());
     assert(m_pModel && "tree view doesn't have expected QSortFilterProxyModel 
set");
 
     m_pSourceModel = 
qobject_cast<QStandardItemModel*>(m_pModel->sourceModel());
diff --git a/vcl/qt5/QtTreeViewModel.cxx b/vcl/qt5/QtTreeViewModel.cxx
new file mode 100644
index 000000000000..a2dd6fc8524c
--- /dev/null
+++ b/vcl/qt5/QtTreeViewModel.cxx
@@ -0,0 +1,21 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; 
fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <QtTreeViewModel.hxx>
+#include <QtTreeViewModel.moc>
+
+#include <QtGui/QStandardItemModel>
+
+QtTreeViewModel::QtTreeViewModel(QWidget* pParent)
+    : QSortFilterProxyModel(pParent)
+{
+    setSourceModel(new QStandardItemModel(pParent));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s 
cinkeys+=0=break: */
diff --git a/vcl/qt6/QtTreeViewModel.cxx b/vcl/qt6/QtTreeViewModel.cxx
new file mode 100644
index 000000000000..6ec096b8b8d9
--- /dev/null
+++ b/vcl/qt6/QtTreeViewModel.cxx
@@ -0,0 +1,12 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; 
fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "../qt5/QtTreeViewModel.cxx"
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s 
cinkeys+=0=break: */

Reply via email to