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     |    3 ++
 vcl/inc/qt5/QtTreeViewItemDelegate.hxx |   36 +++++++++++++++++++++++++
 vcl/inc/qt6/QtTreeViewItemDelegate.hxx |   12 ++++++++
 vcl/qt5/QtInstanceBuilder.cxx          |    1 
 vcl/qt5/QtInstanceTreeView.cxx         |   40 +++++++++++++++++++++++++++-
 vcl/qt5/QtTreeViewItemDelegate.cxx     |   46 +++++++++++++++++++++++++++++++++
 vcl/qt6/QtTreeViewItemDelegate.cxx     |   12 ++++++++
 11 files changed, 153 insertions(+), 1 deletion(-)

New commits:
commit 19a44ab0e4e8158c81c216840c958cefa56ce898
Author:     Michael Weghorn <[email protected]>
AuthorDate: Fri Jan 23 01:24:32 2026 +0100
Commit:     Michael Weghorn <[email protected]>
CommitDate: Fri Jan 23 10:41:37 2026 +0100

    tdf#130857 qt weld: Implement QtInstanceTreeView::do_remove_selection
    
    Sort the indices of the selected rows before removal
    and remove from the last selected row to the first one,
    to avoid that removing an earlier row invalidates the
    index of a later one.
    
    The method gets used e.g. for the following case
    with SAL_VCL_QT_USE_WELDED_WIDGETS=1:
    
    * start Writer
    * type "Hello world"
    * select the text
    * "Insert -> Bookmark"
    * confirm bookmark creation with "Insert"
    * "Insert" -> "Bookmark"
    * select the treeview entry
    * press the "Delete" button
    
    Change-Id: I37978356912139b38dca7e58c2e0723ead7acd01
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/197892
    Reviewed-by: Michael Weghorn <[email protected]>
    Tested-by: Jenkins

diff --git a/vcl/qt5/QtInstanceTreeView.cxx b/vcl/qt5/QtInstanceTreeView.cxx
index 9eacc117b17d..b21fa119c4ef 100644
--- a/vcl/qt5/QtInstanceTreeView.cxx
+++ b/vcl/qt5/QtInstanceTreeView.cxx
@@ -745,7 +745,23 @@ void QtInstanceTreeView::set_selection_mode(SelectionMode 
eMode)
 
 int QtInstanceTreeView::count_selected_rows() const { return 
get_selected_rows().size(); }
 
-void QtInstanceTreeView::do_remove_selection() { assert(false && "Not 
implemented yet"); }
+void QtInstanceTreeView::do_remove_selection()
+{
+    SolarMutexGuard g;
+
+    GetQtInstance().RunInMainThread([&] {
+        // remove from last to first selected row to ensure indexes remain 
valid
+        QModelIndexList aSelectedIndexes = m_pSelectionModel->selectedRows();
+        std::sort(aSelectedIndexes.begin(), aSelectedIndexes.end(),
+                  [this](const QModelIndex& rFirst, const QModelIndex& 
rSecond) {
+                      return iter_compare(QtInstanceTreeIter(rFirst), 
QtInstanceTreeIter(rSecond))
+                             == -1;
+                  });
+
+        for (auto aIt = aSelectedIndexes.rbegin(); aIt != 
aSelectedIndexes.rend(); aIt++)
+            m_pModel->removeRow(aIt->row(), aIt->parent());
+    });
+}
 
 bool QtInstanceTreeView::changed_by_hover() const
 {
commit 96e2a24ef1c9f6a773dd218d80046a68b8c433b1
Author:     Michael Weghorn <[email protected]>
AuthorDate: Fri Jan 23 00:57:19 2026 +0100
Commit:     Michael Weghorn <[email protected]>
CommitDate: Fri Jan 23 10:41:30 2026 +0100

    tdf#130857 qt weld: Support Writer "Insert Bookmark" 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.
    
    See commit message of previous commit
    
        Change-Id: I98ea4e9237ac3174c6049075cf0ecb04b2448167
        Author: Michael Weghorn <[email protected]>
        Date:   Fri Jan 23 00:49:08 2026 +0100
    
            tdf#130857 qt weld: Call TreeView signal hdls when editing 
starts/ends
    
    for sample steps to trigger and test this newly supported
    dialog.
    
    QtInstanceTreeView::do_remove_selection, required to
    remove selected entries in the dialog when pressing
    the "Delete" button, will be implemented in an upcoming
    commit.
    
    Change-Id: Ic5508d3c5df83d9136af4a336bf14b6566c07b17
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/197891
    Reviewed-by: Michael Weghorn <[email protected]>
    Tested-by: Jenkins

diff --git a/vcl/qt5/QtInstanceBuilder.cxx b/vcl/qt5/QtInstanceBuilder.cxx
index 3b2604461d9a..a0df2c03b33e 100644
--- a/vcl/qt5/QtInstanceBuilder.cxx
+++ b/vcl/qt5/QtInstanceBuilder.cxx
@@ -194,6 +194,7 @@ bool QtInstanceBuilder::IsUIFileSupported(const OUString& 
rUIFile, const weld::W
         u"modules/swriter/ui/footendnotedialog.ui"_ustr,
         u"modules/swriter/ui/footnotepage.ui"_ustr,
         u"modules/swriter/ui/inforeadonlydialog.ui"_ustr,
+        u"modules/swriter/ui/insertbookmark.ui"_ustr,
         u"modules/swriter/ui/insertbreak.ui"_ustr,
         u"modules/swriter/ui/insertcaption.ui"_ustr,
         u"modules/swriter/ui/inserttable.ui"_ustr,
commit a7a8c98858bfdde442bac443a24c8e8f0cd54176
Author:     Michael Weghorn <[email protected]>
AuthorDate: Fri Jan 23 00:49:08 2026 +0100
Commit:     Michael Weghorn <[email protected]>
CommitDate: Fri Jan 23 10:41:23 2026 +0100

    tdf#130857 qt weld: Call TreeView signal hdls when editing starts/ends
    
    weld::TreeView has signal_editing_started
    and signal_editing_done methods that are supposed
    to be called by the toolkit-specific weld::TreeView
    implementations when editing is about to start
    and when it is about to end.
    
    weld::TreeView::signal_editing_started returns a
    bool indicating whether or not editing should
    actually start for the given index/entry.
    
    weld::TreeView::signal_editing_done returns a
    bool indicating whether the entry should actually
    be updated with the newly typed text.
    
    In addition, the handlers connected to those signals
    may do additional work.
    
    For the Qt-based implementation, introduce a custom
    item delegate called QtTreeViewItemDelegate
    that subclasses QStyledItemDelegate. As [1] says:
    
    > QStyledItemDelegate is the default delegate for all Qt item views, and
    > is installed upon them when they are created.
    
    In the new QtTreeViewItemDelegate class,
    override the methods that get called when the editor
    gets created and when the model data is supposed to get
    updated. Call the weld::TreeView signal handlers and return
    early in case they return false.
    
    In QtTreeViewItemDelegate::setModelData, only handle the
    case where the editor is a QLineEdit, which is used
    for editing (single-line) strings, as that is what
    weld::TreeView::signal_editing_done also expects.
    
    The newly introduced logic will e.g. be used by Writer's
    "Insert" -> "Bookmark" dialog once it is declared as supported
    by QtInstanceBuilder, which will happen in an upcoming commit.
    
    Sample scenario:
    
    * start Writer
    * type "Hello world"
    * select the text
    * "Insert -> Bookmark"
    * confirm bookmark creation with "Insert"
    * "Insert" -> "Bookmark"
    * select the treeview entry
    * press the "Edit Text" button
    * type new text "Something else" and press Enter to confirm
    
    -> The text in the document is changed to "Something else"
    by the handler called by the call to
    weld::TreeView::signal_editing_done.
    
    [1] https://doc.qt.io/qt-6/qstyleditemdelegate.html#details
    
    Change-Id: I98ea4e9237ac3174c6049075cf0ecb04b2448167
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/197890
    Reviewed-by: Michael Weghorn <[email protected]>
    Tested-by: Jenkins

diff --git a/vcl/CustomTarget_qt5_moc.mk b/vcl/CustomTarget_qt5_moc.mk
index f8f2a5819eaa..9068019700aa 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/QtTreeViewItemDelegate.moc \
        $(gb_CustomTarget_workdir)/vcl/qt5/QtTreeViewModel.moc \
        $(gb_CustomTarget_workdir)/vcl/qt5/QtObject.moc \
        $(gb_CustomTarget_workdir)/vcl/qt5/QtTimer.moc \
diff --git a/vcl/CustomTarget_qt6_moc.mk b/vcl/CustomTarget_qt6_moc.mk
index f545b285150e..1797ba66cf21 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/QtTreeViewItemDelegate.moc \
        $(gb_CustomTarget_workdir)/vcl/qt6/QtTreeViewModel.moc \
        $(gb_CustomTarget_workdir)/vcl/qt6/QtObject.moc \
        $(gb_CustomTarget_workdir)/vcl/qt6/QtTimer.moc \
diff --git a/vcl/Library_vclplug_qt5.mk b/vcl/Library_vclplug_qt5.mk
index 90826dcd06ae..3352bbb7432d 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/QtTreeViewItemDelegate \
     vcl/qt5/QtTreeViewModel \
     vcl/qt5/QtVirtualDevice \
     vcl/qt5/QtWidget \
diff --git a/vcl/Library_vclplug_qt6.mk b/vcl/Library_vclplug_qt6.mk
index 83cf22d38888..7894b0f8900e 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/QtTreeViewItemDelegate \
     vcl/qt6/QtTreeViewModel \
     vcl/qt6/QtVirtualDevice \
     vcl/qt6/QtWidget \
diff --git a/vcl/inc/qt5/QtInstanceTreeView.hxx 
b/vcl/inc/qt5/QtInstanceTreeView.hxx
index be22c9096286..fc83fbcd97ba 100644
--- a/vcl/inc/qt5/QtInstanceTreeView.hxx
+++ b/vcl/inc/qt5/QtInstanceTreeView.hxx
@@ -158,6 +158,9 @@ public:
     using QtInstanceWidget::set_sensitive;
     using QtInstanceWidget::get_sensitive;
 
+    bool signalEditingStarted(const QModelIndex& rIndex);
+    bool signalEditingDone(const QModelIndex& rIndex, const QString& rNewText);
+
     // methods to get/set which roles are supported by the individual columns
     // based on the underlying GtkTreeViewColumns and their GtkCellRenderers
     static QList<QList<Qt::ItemDataRole>> columnRoles(QTreeView& rTreeView);
diff --git a/vcl/inc/qt5/QtTreeViewItemDelegate.hxx 
b/vcl/inc/qt5/QtTreeViewItemDelegate.hxx
new file mode 100644
index 000000000000..60672cca7371
--- /dev/null
+++ b/vcl/inc/qt5/QtTreeViewItemDelegate.hxx
@@ -0,0 +1,36 @@
+/* -*- 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 <QtWidgets/QStyledItemDelegate>
+#include <QtWidgets/QWidget>
+
+/** Item delegate for QtInstanceTreeView. */
+class QtTreeViewItemDelegate : public QStyledItemDelegate
+{
+    Q_OBJECT
+
+    std::function<bool(const QModelIndex& rIndex)> m_aStartEditingFunction;
+    std::function<bool(const QModelIndex& rIndex, const QString& rNewText)>
+        m_aFinishEditingFunction;
+
+public:
+    QtTreeViewItemDelegate(QObject* pParent,
+                           std::function<bool(const QModelIndex& rIndex)> 
aStartEditingFunction,
+                           std::function<bool(const QModelIndex& rIndex, const 
QString& rNewText)>
+                               aEndEditingFunction);
+
+    virtual QWidget* createEditor(QWidget* pParent, const 
QStyleOptionViewItem& rOption,
+                                  const QModelIndex& rIndex) const override;
+    virtual void setModelData(QWidget* pEditor, QAbstractItemModel* pModel,
+                              const QModelIndex& rIndex) const override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s 
cinkeys+=0=break: */
diff --git a/vcl/inc/qt6/QtTreeViewItemDelegate.hxx 
b/vcl/inc/qt6/QtTreeViewItemDelegate.hxx
new file mode 100644
index 000000000000..2469d54a45a7
--- /dev/null
+++ b/vcl/inc/qt6/QtTreeViewItemDelegate.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/QtTreeViewItemDelegate.hxx"
+
+/* 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 5f5e5238cfc4..9eacc117b17d 100644
--- a/vcl/qt5/QtInstanceTreeView.cxx
+++ b/vcl/qt5/QtInstanceTreeView.cxx
@@ -9,6 +9,7 @@
 
 #include <QtInstanceTreeView.hxx>
 #include <QtInstanceTreeView.moc>
+#include <QtTreeViewItemDelegate.hxx>
 
 #include <vcl/qt/QtUtils.hxx>
 
@@ -46,6 +47,13 @@ QtInstanceTreeView::QtInstanceTreeView(QTreeView* pTreeView)
 
     assert(m_pTreeView->viewport());
     m_pTreeView->viewport()->installEventFilter(this);
+
+    QtTreeViewItemDelegate* pDelegate = new QtTreeViewItemDelegate(
+        m_pTreeView, [this](const QModelIndex& rIndex) { return 
signalEditingStarted(rIndex); },
+        [this](const QModelIndex& rIndex, const QString& rNewText) {
+            return signalEditingDone(rIndex, rNewText);
+        });
+    m_pTreeView->setItemDelegate(pDelegate);
 }
 
 void QtInstanceTreeView::do_insert(const weld::TreeIter* pParent, int nPos, 
const OUString* pStr,
@@ -810,6 +818,20 @@ QAbstractItemView::SelectionMode 
QtInstanceTreeView::mapSelectionMode(SelectionM
     }
 }
 
+bool QtInstanceTreeView::signalEditingStarted(const QModelIndex& rIndex)
+{
+    SolarMutexGuard g;
+
+    return signal_editing_started(QtInstanceTreeIter(rIndex));
+}
+
+bool QtInstanceTreeView::signalEditingDone(const QModelIndex& rIndex, const 
QString& rNewText)
+{
+    SolarMutexGuard g;
+
+    return signal_editing_done({ QtInstanceTreeIter(rIndex), 
toOUString(rNewText) });
+}
+
 QList<QList<Qt::ItemDataRole>> QtInstanceTreeView::columnRoles(QTreeView& 
rTreeView)
 {
     QVariant aVariant = rTreeView.property(PROPERTY_COLUMN_ROLES);
diff --git a/vcl/qt5/QtTreeViewItemDelegate.cxx 
b/vcl/qt5/QtTreeViewItemDelegate.cxx
new file mode 100644
index 000000000000..e80944ee9aae
--- /dev/null
+++ b/vcl/qt5/QtTreeViewItemDelegate.cxx
@@ -0,0 +1,46 @@
+/* -*- 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 <QtTreeViewItemDelegate.hxx>
+#include <QtTreeViewItemDelegate.moc>
+
+#include <QtWidgets/QLineEdit>
+
+QtTreeViewItemDelegate::QtTreeViewItemDelegate(
+    QObject* pParent, std::function<bool(const QModelIndex& rIndex)> 
aStartEditingFunction,
+    std::function<bool(const QModelIndex& rIndex, const QString& rNewText)> 
aFinishEditingFunction)
+    : QStyledItemDelegate(pParent)
+    , m_aStartEditingFunction(aStartEditingFunction)
+    , m_aFinishEditingFunction(aFinishEditingFunction)
+{
+}
+
+QWidget* QtTreeViewItemDelegate::createEditor(QWidget* pParent, const 
QStyleOptionViewItem& rOption,
+                                              const QModelIndex& rIndex) const
+{
+    if (!m_aStartEditingFunction(rIndex))
+        return nullptr;
+
+    return QStyledItemDelegate::createEditor(pParent, rOption, rIndex);
+}
+
+void QtTreeViewItemDelegate::setModelData(QWidget* pEditor, 
QAbstractItemModel* pModel,
+                                          const QModelIndex& rIndex) const
+{
+    // check whether new string is accepted
+    if (QLineEdit* pLineEdit = qobject_cast<QLineEdit*>(pEditor))
+    {
+        if (!m_aFinishEditingFunction(rIndex, pLineEdit->text()))
+            return;
+    }
+
+    QStyledItemDelegate::setModelData(pEditor, pModel, rIndex);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s 
cinkeys+=0=break: */
diff --git a/vcl/qt6/QtTreeViewItemDelegate.cxx 
b/vcl/qt6/QtTreeViewItemDelegate.cxx
new file mode 100644
index 000000000000..5b4b27a1a26b
--- /dev/null
+++ b/vcl/qt6/QtTreeViewItemDelegate.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/QtTreeViewItemDelegate.cxx"
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s 
cinkeys+=0=break: */

Reply via email to