aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Moe Gustavsen <richard.gustavsen@qt.io>2022-02-07 11:00:21 +0100
committerRichard Moe Gustavsen <richard.gustavsen@qt.io>2022-02-18 00:09:53 +0100
commitc013439598900941b860af6f525bcf96232efcc8 (patch)
tree11fd84d4c02a80b47a46a6da80b574f2f45e9983
parent7eeeb605f0d0c8c49c245e1f9d5738e4af6178cb (diff)
QQuickTreeView: add expandToIndex()
Add a function that lets you expand the tree recursively from an index in the model, and all the way up to the root. [ChangeLog][QtQuick] New function "expandToIndex()" has been added to TreeView. Change-Id: I063ef698e37f44730438e1638d3b7c1b4edaa0d0 Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
-rw-r--r--src/quick/items/qquicktreeview.cpp69
-rw-r--r--src/quick/items/qquicktreeview_p.h1
-rw-r--r--tests/auto/quick/qquicktreeview/tst_qquicktreeview.cpp40
-rw-r--r--tests/manual/treeview/sidebyside/data/treeview.qml21
4 files changed, 131 insertions, 0 deletions
diff --git a/src/quick/items/qquicktreeview.cpp b/src/quick/items/qquicktreeview.cpp
index b6547e8bcd..fc65b0f42b 100644
--- a/src/quick/items/qquicktreeview.cpp
+++ b/src/quick/items/qquicktreeview.cpp
@@ -176,6 +176,24 @@
*/
/*!
+ \qmlmethod QtQuick::TreeView::expandToIndex(QModelIndex index)
+ \since 6.4
+
+ Expands the tree from the given model \a index, and recursively all the way up
+ to the root. The result will be that the delegate item that represents \a index
+ becomes visible in the view (unless it ends up outside the viewport). To
+ ensure that the row ends up visible in the viewport, you can do:
+
+ \code
+ expandToIndex(index)
+ forceLayout()
+ positionViewAtRow(rowAtIndex(index), Qt.AlignVCenter)
+ \endcode
+
+ \sa expand(), expandRecursively()
+*/
+
+/*!
\qmlmethod QtQuick::TreeView::collapse(row)
Collapses the tree node at the given \a row in the view.
@@ -302,6 +320,8 @@
\a row and \a depth will be equal to the arguments given to the call
that caused the expansion to happen (\l expand() or \l expandRecursively()).
In case of \l expand(), \a depth will always be \c 1.
+ In case of \l expandToIndex(), \a depth will be the depth of the
+ target index.
\note when a row is expanded recursively, the expanded signal will
only be emitted for that one row, and not for its descendants.
@@ -519,6 +539,55 @@ void QQuickTreeView::expandRecursively(int row, int depth)
emit expanded(row, depth);
}
+void QQuickTreeView::expandToIndex(const QModelIndex &index)
+{
+ Q_D(QQuickTreeView);
+
+ if (!index.isValid()) {
+ qmlWarning(this) << "index is not valid: " << index;
+ return;
+ }
+
+ if (index.model() != d->m_treeModelToTableModel.model()) {
+ qmlWarning(this) << "index doesn't belong to correct model: " << index;
+ return;
+ }
+
+ if (rowAtIndex(index) != -1) {
+ // index is already visible
+ return;
+ }
+
+ int depth = 1;
+ QModelIndex parent = index.parent();
+ int row = rowAtIndex(parent);
+
+ while (parent.isValid()) {
+ if (row != -1) {
+ // The node is already visible, since it maps to a row in the table!
+ d->m_treeModelToTableModel.expandRow(row);
+
+ // Update the state of the already existing delegate item
+ for (int c = leftColumn(); c <= rightColumn(); ++c) {
+ const QPoint treeNodeCell(c, row);
+ if (const auto item = itemAtCell(treeNodeCell))
+ d->setRequiredProperty("expanded", true, d->modelIndexAtCell(treeNodeCell), item, false);
+ }
+
+ // When we hit a node that is visible, we know that all other nodes
+ // up to the parent have to be visible as well, so we can stop.
+ break;
+ } else {
+ d->m_treeModelToTableModel.expand(parent);
+ parent = parent.parent();
+ row = rowAtIndex(parent);
+ depth++;
+ }
+ }
+
+ emit expanded(row, depth);
+}
+
void QQuickTreeView::collapse(int row)
{
Q_D(QQuickTreeView);
diff --git a/src/quick/items/qquicktreeview_p.h b/src/quick/items/qquicktreeview_p.h
index 322405d463..0546dbccf4 100644
--- a/src/quick/items/qquicktreeview_p.h
+++ b/src/quick/items/qquicktreeview_p.h
@@ -77,6 +77,7 @@ public:
Q_REVISION(6, 4) Q_INVOKABLE void expandRecursively(int row = -1, int depth = -1);
Q_REVISION(6, 4) Q_INVOKABLE void collapseRecursively(int row = -1);
+ Q_REVISION(6, 4) Q_INVOKABLE void expandToIndex(const QModelIndex &index);
Q_INVOKABLE QModelIndex modelIndex(int row, int column) const;
Q_INVOKABLE QModelIndex modelIndex(const QPoint &cell) const;
diff --git a/tests/auto/quick/qquicktreeview/tst_qquicktreeview.cpp b/tests/auto/quick/qquicktreeview/tst_qquicktreeview.cpp
index c26d289fe6..712ccdc6cc 100644
--- a/tests/auto/quick/qquicktreeview/tst_qquicktreeview.cpp
+++ b/tests/auto/quick/qquicktreeview/tst_qquicktreeview.cpp
@@ -103,6 +103,7 @@ private slots:
void collapseRecursivelyRoot();
void collapseRecursivelyChild();
void collapseRecursivelyWholeTree();
+ void expandToIndex();
void requiredPropertiesRoot();
void requiredPropertiesChildren();
void emptyModel();
@@ -692,6 +693,45 @@ void tst_qquicktreeview::collapseRecursivelyWholeTree()
QCOMPARE(treeView->rows(), 1); // root
}
+void tst_qquicktreeview::expandToIndex()
+{
+ // Check that expandToIndex(index) expands the tree so
+ // that index becomes visible in the view
+ LOAD_TREEVIEW("normaltreeview.qml");
+ QSignalSpy spy(treeView, SIGNAL(expanded(int, int)));
+
+ const QModelIndex root = model->index(0, 0);
+ const QModelIndex child1 = model->index(3, 0, root);
+ const QModelIndex child2 = model->index(3, 0, child1);
+
+ QVERIFY(model->hasChildren(root));
+ QVERIFY(model->hasChildren(child1));
+ QVERIFY(model->hasChildren(child2));
+
+ QVERIFY(!treeView->isExpanded(treeView->rowAtIndex(root)));
+ QVERIFY(!treeView->isExpanded(treeView->rowAtIndex(child1)));
+ QVERIFY(!treeView->isExpanded(treeView->rowAtIndex(child2)));
+
+ const QModelIndex childToExpand = model->index(1, 0, child2);
+ treeView->expandToIndex(childToExpand);
+
+ QVERIFY(treeView->isExpanded(treeView->rowAtIndex(root)));
+ QVERIFY(treeView->isExpanded(treeView->rowAtIndex(child1)));
+ QVERIFY(treeView->isExpanded(treeView->rowAtIndex(child2)));
+
+ QCOMPARE(spy.count(), 1);
+ auto signalArgs = spy.takeFirst();
+ QVERIFY(signalArgs.at(0).toInt() == 0);
+ QVERIFY(signalArgs.at(1).toInt() == 3);
+
+ WAIT_UNTIL_POLISHED;
+
+ // The view should now have 13 rows:
+ // root + 3 expanded nodes that each have 4 children
+ QCOMPARE(treeView->rows(), 13);
+}
+
+
QTEST_MAIN(tst_qquicktreeview)
#include "tst_qquicktreeview.moc"
diff --git a/tests/manual/treeview/sidebyside/data/treeview.qml b/tests/manual/treeview/sidebyside/data/treeview.qml
index 0e97e23a96..a6fd99b076 100644
--- a/tests/manual/treeview/sidebyside/data/treeview.qml
+++ b/tests/manual/treeview/sidebyside/data/treeview.qml
@@ -48,6 +48,7 @@ ApplicationWindow {
visible: true
property alias treeView: treeView
+ property var selectedIndex: undefined
UICallback { id: callback }
@@ -92,6 +93,16 @@ ApplicationWindow {
treeView.model.removeRows(index.row, 1, index.parent);
}
}
+ Button {
+ text: "Expand to"
+ enabled: selectedIndex != undefined
+ onClicked: {
+ treeView.expandToIndex(selectedIndex);
+ treeView.forceLayout()
+ let row = treeView.rowAtIndex(selectedIndex)
+ treeView.positionViewAtRow(row, Qt.AlignVCenter)
+ }
+ }
}
TreeView {
@@ -126,6 +137,16 @@ ApplicationWindow {
treeView.expandRecursively(row)
}
}
+ TapHandler {
+ acceptedModifiers: Qt.ShiftModifier
+ onTapped: selectedIndex = treeView.modelIndex(row, 0)
+ }
+ Rectangle {
+ anchors.fill: parent
+ border.color: "red"
+ border.width: 1
+ visible: treeView.modelIndex(row, column) === selectedIndex
+ }
}
}