aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Moe Gustavsen <richard.gustavsen@qt.io>2022-11-30 14:36:43 +0100
committerRichard Moe Gustavsen <richard.gustavsen@qt.io>2022-12-08 23:33:42 +0100
commit21bf976a411a65a1c945aae994afbcb8590e50e4 (patch)
tree28394b9dc650e9aec042b1967b05c732103f32ca
parent52cbcd947db2219aecb2f6cb59bc6676a7c61e48 (diff)
QQuickTreeViewDelegate: implement edit delegates
This patch will implement a default edit delegate for the TreeViewDelegates, for all our styles. [ChangeLog][Controls] TreeViewDelegate got support for editing nodes in the tree. Change-Id: Iec5936e4439770586837daa3b8045482b75a15f2 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
-rw-r--r--src/qmlmodels/qqmltreemodeltotablemodel.cpp5
-rw-r--r--src/qmlmodels/qqmltreemodeltotablemodel_p_p.h1
-rw-r--r--src/quickcontrols/basic/TreeViewDelegate.qml35
-rw-r--r--src/quickcontrols/fusion/TreeViewDelegate.qml35
-rw-r--r--src/quickcontrols/ios/TreeViewDelegate.qml35
-rw-r--r--src/quickcontrols/material/TreeViewDelegate.qml35
-rw-r--r--src/quicknativestyle/controls/DefaultTreeViewDelegate.qml35
-rw-r--r--src/quicktemplates/qquicktreeviewdelegate.cpp24
-rw-r--r--src/quicktemplates/qquicktreeviewdelegate_p.h5
-rw-r--r--tests/auto/quickcontrols/qquicktreeviewdelegate/tst_qquicktreeviewdelegate.cpp4
-rw-r--r--tests/manual/treeview/sidebyside/data/treeview.qml2
-rw-r--r--tests/manual/treeview/sidebyside/testmodel.cpp5
-rw-r--r--tests/manual/treeview/sidebyside/testmodel.h2
13 files changed, 223 insertions, 0 deletions
diff --git a/src/qmlmodels/qqmltreemodeltotablemodel.cpp b/src/qmlmodels/qqmltreemodeltotablemodel.cpp
index 1fdcc1f95b..d300ff2d1a 100644
--- a/src/qmlmodels/qqmltreemodeltotablemodel.cpp
+++ b/src/qmlmodels/qqmltreemodeltotablemodel.cpp
@@ -164,6 +164,11 @@ QVariant QQmlTreeModelToTableModel::headerData(int section, Qt::Orientation orie
return m_model->headerData(section, orientation, role);
}
+Qt::ItemFlags QQmlTreeModelToTableModel::flags(const QModelIndex &index) const
+{
+ return m_model->flags(mapToModel(index));
+}
+
int QQmlTreeModelToTableModel::depthAtRow(int row) const
{
if (row < 0 || row >= m_items.size())
diff --git a/src/qmlmodels/qqmltreemodeltotablemodel_p_p.h b/src/qmlmodels/qqmltreemodeltotablemodel_p_p.h
index 55ef45912a..1c503ca37c 100644
--- a/src/qmlmodels/qqmltreemodeltotablemodel_p_p.h
+++ b/src/qmlmodels/qqmltreemodeltotablemodel_p_p.h
@@ -60,6 +60,7 @@ public:
QVariant data(const QModelIndex &, int role) const override;
bool setData(const QModelIndex &index, const QVariant &value, int role) override;
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
+ Qt::ItemFlags flags(const QModelIndex &index) const override;
void clearModelData();
diff --git a/src/quickcontrols/basic/TreeViewDelegate.qml b/src/quickcontrols/basic/TreeViewDelegate.qml
index fc9a072c43..2248d23e25 100644
--- a/src/quickcontrols/basic/TreeViewDelegate.qml
+++ b/src/quickcontrols/basic/TreeViewDelegate.qml
@@ -59,5 +59,40 @@ T.TreeViewDelegate {
text: control.model.display
elide: Text.ElideRight
color: control.highlighted ? control.palette.highlightedText : control.palette.buttonText
+ visible: !control.editing
}
+
+ // The edit delegate is a separate component, and doesn't need
+ // to follow the same strict rules that are applied to a control.
+ // qmllint disable attached-property-reuse
+ // qmllint disable controls-sanity
+ TableView.editDelegate: FocusScope {
+ width: parent.width
+ height: parent.height
+
+ readonly property int __role: {
+ let model = control.treeView.model
+ let index = control.treeView.modelIndex(column, row)
+ let editText = model.data(index, Qt.EditRole)
+ return editText !== undefined ? Qt.EditRole : Qt.DisplayRole
+ }
+
+ TextField {
+ id: textField
+ x: control.contentItem.x
+ y: (parent.height - height) / 2
+ width: control.contentItem.width
+ text: control.treeView.model.data(control.treeView.modelIndex(column, row), __role)
+ focus: true
+ }
+
+ TableView.onCommit: {
+ let index = TableView.view.modelIndex(column, row)
+ TableView.view.model.setData(index, textField.text, __role)
+ }
+
+ Component.onCompleted: textField.selectAll()
+ }
+ // qmllint enable attached-property-reuse
+ // qmllint enable controls-sanity
}
diff --git a/src/quickcontrols/fusion/TreeViewDelegate.qml b/src/quickcontrols/fusion/TreeViewDelegate.qml
index 5223361872..f8bbfb24b8 100644
--- a/src/quickcontrols/fusion/TreeViewDelegate.qml
+++ b/src/quickcontrols/fusion/TreeViewDelegate.qml
@@ -58,5 +58,40 @@ T.TreeViewDelegate {
contentItem: Label {
text: control.model.display
elide: Text.ElideRight
+ visible: !control.editing
}
+
+ // The edit delegate is a separate component, and doesn't need
+ // to follow the same strict rules that are applied to a control.
+ // qmllint disable attached-property-reuse
+ // qmllint disable controls-sanity
+ TableView.editDelegate: FocusScope {
+ width: parent.width
+ height: parent.height
+
+ readonly property int __role: {
+ let model = control.treeView.model
+ let index = control.treeView.modelIndex(column, row)
+ let editText = model.data(index, Qt.EditRole)
+ return editText !== undefined ? Qt.EditRole : Qt.DisplayRole
+ }
+
+ TextField {
+ id: textField
+ x: control.contentItem.x
+ y: (parent.height - height) / 2
+ width: control.contentItem.width
+ text: control.treeView.model.data(control.treeView.modelIndex(column, row), __role)
+ focus: true
+ }
+
+ TableView.onCommit: {
+ let index = TableView.view.modelIndex(column, row)
+ TableView.view.model.setData(index, textField.text, __role)
+ }
+
+ Component.onCompleted: textField.selectAll()
+ }
+ // qmllint enable attached-property-reuse
+ // qmllint enable controls-sanity
}
diff --git a/src/quickcontrols/ios/TreeViewDelegate.qml b/src/quickcontrols/ios/TreeViewDelegate.qml
index 4dcfcbf39d..89577e297b 100644
--- a/src/quickcontrols/ios/TreeViewDelegate.qml
+++ b/src/quickcontrols/ios/TreeViewDelegate.qml
@@ -73,5 +73,40 @@ T.TreeViewDelegate {
clip: false
text: control.model.display
elide: Text.ElideRight
+ visible: !control.editing
}
+
+ // The edit delegate is a separate component, and doesn't need
+ // to follow the same strict rules that are applied to a control.
+ // qmllint disable attached-property-reuse
+ // qmllint disable controls-sanity
+ TableView.editDelegate: FocusScope {
+ width: parent.width
+ height: parent.height
+
+ readonly property int __role: {
+ let model = control.treeView.model
+ let index = control.treeView.modelIndex(column, row)
+ let editText = model.data(index, Qt.EditRole)
+ return editText !== undefined ? Qt.EditRole : Qt.DisplayRole
+ }
+
+ TextField {
+ id: textField
+ x: control.contentItem.x
+ y: (parent.height - height) / 2
+ width: control.contentItem.width
+ text: control.treeView.model.data(control.treeView.modelIndex(column, row), __role)
+ focus: true
+ }
+
+ TableView.onCommit: {
+ let index = TableView.view.modelIndex(column, row)
+ TableView.view.model.setData(index, textField.text, __role)
+ }
+
+ Component.onCompleted: textField.selectAll()
+ }
+ // qmllint enable attached-property-reuse
+ // qmllint enable controls-sanity
}
diff --git a/src/quickcontrols/material/TreeViewDelegate.qml b/src/quickcontrols/material/TreeViewDelegate.qml
index a7be36a555..1a6e35dadc 100644
--- a/src/quickcontrols/material/TreeViewDelegate.qml
+++ b/src/quickcontrols/material/TreeViewDelegate.qml
@@ -58,5 +58,40 @@ T.TreeViewDelegate {
contentItem: Label {
text: control.model.display
elide: Text.ElideRight
+ visible: !control.editing
}
+
+ // The edit delegate is a separate component, and doesn't need
+ // to follow the same strict rules that are applied to a control.
+ // qmllint disable attached-property-reuse
+ // qmllint disable controls-sanity
+ TableView.editDelegate: FocusScope {
+ width: parent.width
+ height: parent.height
+
+ readonly property int __role: {
+ let model = control.treeView.model
+ let index = control.treeView.modelIndex(column, row)
+ let editText = model.data(index, Qt.EditRole)
+ return editText !== undefined ? Qt.EditRole : Qt.DisplayRole
+ }
+
+ TextField {
+ id: textField
+ x: control.contentItem.x
+ y: (parent.height - height) / 2
+ width: control.contentItem.width
+ text: control.treeView.model.data(control.treeView.modelIndex(column, row), __role)
+ focus: true
+ }
+
+ TableView.onCommit: {
+ let index = TableView.view.modelIndex(column, row)
+ TableView.view.model.setData(index, textField.text, __role)
+ }
+
+ Component.onCompleted: textField.selectAll()
+ }
+ // qmllint enable attached-property-reuse
+ // qmllint enable controls-sanity
}
diff --git a/src/quicknativestyle/controls/DefaultTreeViewDelegate.qml b/src/quicknativestyle/controls/DefaultTreeViewDelegate.qml
index a5f0496909..6a9963cc6a 100644
--- a/src/quicknativestyle/controls/DefaultTreeViewDelegate.qml
+++ b/src/quicknativestyle/controls/DefaultTreeViewDelegate.qml
@@ -57,5 +57,40 @@ T.TreeViewDelegate {
text: control.model.display
elide: Text.ElideRight
color: control.highlighted ? control.palette.highlightedText : control.palette.buttonText
+ visible: !control.editing
}
+
+ // The edit delegate is a separate component, and doesn't need
+ // to follow the same strict rules that are applied to a control.
+ // qmllint disable attached-property-reuse
+ // qmllint disable controls-sanity
+ TableView.editDelegate: FocusScope {
+ width: parent.width
+ height: parent.height
+
+ readonly property int __role: {
+ let model = control.treeView.model
+ let index = control.treeView.modelIndex(column, row)
+ let editText = model.data(index, Qt.EditRole)
+ return editText !== undefined ? Qt.EditRole : Qt.DisplayRole
+ }
+
+ TextField {
+ id: textField
+ x: control.contentItem.x
+ y: (parent.height - height) / 2
+ width: control.contentItem.width
+ text: control.treeView.model.data(control.treeView.modelIndex(column, row), __role)
+ focus: true
+ }
+
+ TableView.onCommit: {
+ let index = TableView.view.modelIndex(column, row)
+ TableView.view.model.setData(index, textField.text, __role)
+ }
+
+ Component.onCompleted: textField.selectAll()
+ }
+ // qmllint enable attached-property-reuse
+ // qmllint enable controls-sanity
}
diff --git a/src/quicktemplates/qquicktreeviewdelegate.cpp b/src/quicktemplates/qquicktreeviewdelegate.cpp
index 1f4b8e38fe..01558a20db 100644
--- a/src/quicktemplates/qquicktreeviewdelegate.cpp
+++ b/src/quicktemplates/qquicktreeviewdelegate.cpp
@@ -162,6 +162,14 @@ QT_BEGIN_NAMESPACE
*/
/*!
+ \qmlproperty bool QtQuick.Controls::TreeViewDelegate::editing
+ \since 6.5
+
+ This property holds if the delegate is being
+ \l {Editing cells}{edited.}
+*/
+
+/*!
\qmlproperty real QtQuick.Controls::TreeViewDelegate::indentation
This property holds the space a child is indented horizontally
@@ -210,6 +218,7 @@ public:
bool m_expanded = false;
bool m_current = false;
bool m_selected = false;
+ bool m_editing = false;
bool m_hasChildren = false;
bool m_pressOnTopOfIndicator = false;
int m_depth = 0;
@@ -417,6 +426,21 @@ void QQuickTreeViewDelegate::setSelected(bool selected)
emit selectedChanged();
}
+bool QQuickTreeViewDelegate::editing() const
+{
+ return d_func()->m_editing;
+}
+
+void QQuickTreeViewDelegate::setEditing(bool editing)
+{
+ Q_D(QQuickTreeViewDelegate);
+ if (d->m_editing == editing)
+ return;
+
+ d->m_editing = editing;
+ emit editingChanged();
+}
+
int QQuickTreeViewDelegate::depth() const
{
return d_func()->m_depth;
diff --git a/src/quicktemplates/qquicktreeviewdelegate_p.h b/src/quicktemplates/qquicktreeviewdelegate_p.h
index de85f7c2cd..aa39b17c10 100644
--- a/src/quicktemplates/qquicktreeviewdelegate_p.h
+++ b/src/quicktemplates/qquicktreeviewdelegate_p.h
@@ -39,6 +39,7 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickTreeViewDelegate : public QQuickIte
Q_PROPERTY(int depth READ depth WRITE setDepth NOTIFY depthChanged REQUIRED FINAL)
Q_PROPERTY(bool current READ current WRITE setCurrent NOTIFY currentChanged REQUIRED FINAL REVISION(6, 4))
Q_PROPERTY(bool selected READ selected WRITE setSelected NOTIFY selectedChanged REQUIRED FINAL REVISION(6, 4))
+ Q_PROPERTY(bool editing READ editing WRITE setEditing NOTIFY editingChanged REQUIRED FINAL REVISION(6, 5))
QML_NAMED_ELEMENT(TreeViewDelegate)
QML_ADDED_IN_VERSION(6, 3)
@@ -64,6 +65,9 @@ public:
bool selected() const;
void setSelected(bool selected);
+ bool editing() const;
+ void setEditing(bool editing);
+
int depth() const;
void setDepth(int depth);
@@ -88,6 +92,7 @@ Q_SIGNALS:
void rightMarginChanged();
Q_REVISION(6, 4) void currentChanged();
Q_REVISION(6, 4) void selectedChanged();
+ Q_REVISION(6, 5) void editingChanged();
protected:
QFont defaultFont() const override;
diff --git a/tests/auto/quickcontrols/qquicktreeviewdelegate/tst_qquicktreeviewdelegate.cpp b/tests/auto/quickcontrols/qquicktreeviewdelegate/tst_qquicktreeviewdelegate.cpp
index 834729e133..8471a31408 100644
--- a/tests/auto/quickcontrols/qquicktreeviewdelegate/tst_qquicktreeviewdelegate.cpp
+++ b/tests/auto/quickcontrols/qquicktreeviewdelegate/tst_qquicktreeviewdelegate.cpp
@@ -237,6 +237,7 @@ void tst_qquicktreeviewdelegate::checkPropertiesChildren()
QCOMPARE(childItem->depth(), row <= 4 ? 1 : 2);
QCOMPARE(childItem->current(), false);
QCOMPARE(childItem->selected(), false);
+ QCOMPARE(childItem->editing(), false);
QCOMPARE(childItem->leftPadding(), childItem->leftMargin() + (childItem->depth() * childItem->indentation()) + childItem->indicator()->width() + childItem->spacing());
QCOMPARE(childItem->indicator()->x(), childItem->leftMargin() + (childItem->depth() * childItem->indentation()));
}
@@ -254,6 +255,7 @@ void tst_qquicktreeviewdelegate::checkCurrentIndex()
QVERIFY(item);
QVERIFY(!item->current());
QVERIFY(!item->selected());
+ QVERIFY(!item->editing());
QVERIFY(!treeView->hasActiveFocus());
// Click on the label
@@ -262,12 +264,14 @@ void tst_qquicktreeviewdelegate::checkCurrentIndex()
QTest::mouseClick(item->window(), Qt::LeftButton, Qt::NoModifier, pos);
QVERIFY(item->current());
QVERIFY(!item->selected());
+ QVERIFY(!item->editing());
QVERIFY(treeView->hasActiveFocus());
// Select the cell
treeView->selectionModel()->setCurrentIndex(treeView->modelIndex(cell), QItemSelectionModel::Select);
QVERIFY(item->current());
QVERIFY(item->selected());
+ QVERIFY(!item->editing());
}
void tst_qquicktreeviewdelegate::checkClickedSignal_data()
diff --git a/tests/manual/treeview/sidebyside/data/treeview.qml b/tests/manual/treeview/sidebyside/data/treeview.qml
index fc5d102b2e..6c51b7c413 100644
--- a/tests/manual/treeview/sidebyside/data/treeview.qml
+++ b/tests/manual/treeview/sidebyside/data/treeview.qml
@@ -80,6 +80,8 @@ ApplicationWindow {
anchors.topMargin: 100
clip: true
+ selectionModel: ItemSelectionModel {}
+
model: useFileSystemModel.checked ? fileSystemModel : testModel
delegate: useCustomDelegate.checked ? customDelegate : treeViewDelegate
}
diff --git a/tests/manual/treeview/sidebyside/testmodel.cpp b/tests/manual/treeview/sidebyside/testmodel.cpp
index f5c4f2ab04..3b70ea7ab5 100644
--- a/tests/manual/treeview/sidebyside/testmodel.cpp
+++ b/tests/manual/treeview/sidebyside/testmodel.cpp
@@ -162,3 +162,8 @@ bool TestModel::removeRows(int position, int count, const QModelIndex &parent)
return true;
}
+Qt::ItemFlags TestModel::flags(const QModelIndex &index) const
+{
+ Q_UNUSED(index)
+ return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable;
+}
diff --git a/tests/manual/treeview/sidebyside/testmodel.h b/tests/manual/treeview/sidebyside/testmodel.h
index 8dd7c81231..86007f0d7f 100644
--- a/tests/manual/treeview/sidebyside/testmodel.h
+++ b/tests/manual/treeview/sidebyside/testmodel.h
@@ -43,6 +43,8 @@ public:
Q_INVOKABLE bool insertRows(int position, int count, const QModelIndex &parent) override;
Q_INVOKABLE bool removeRows(int position, int count, const QModelIndex &parent) override;
+ Qt::ItemFlags flags(const QModelIndex &index) const override;
+
private:
QVector<TreeItem *> m_rootItems;
int m_columnCount = 2;