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