diff options
author | Richard Moe Gustavsen <richard.gustavsen@qt.io> | 2022-02-07 11:00:21 +0100 |
---|---|---|
committer | Richard Moe Gustavsen <richard.gustavsen@qt.io> | 2022-02-18 00:09:53 +0100 |
commit | c013439598900941b860af6f525bcf96232efcc8 (patch) | |
tree | 11fd84d4c02a80b47a46a6da80b574f2f45e9983 | |
parent | 7eeeb605f0d0c8c49c245e1f9d5738e4af6178cb (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.cpp | 69 | ||||
-rw-r--r-- | src/quick/items/qquicktreeview_p.h | 1 | ||||
-rw-r--r-- | tests/auto/quick/qquicktreeview/tst_qquicktreeview.cpp | 40 | ||||
-rw-r--r-- | tests/manual/treeview/sidebyside/data/treeview.qml | 21 |
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 + } } } |