diff options
author | Richard Moe Gustavsen <richard.gustavsen@qt.io> | 2022-08-09 15:42:36 +0200 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2022-08-19 22:10:27 +0000 |
commit | 0981cf78544a81760d68bf44dbe1a3c1d334fd78 (patch) | |
tree | c902afe9061c5c342ac19b2869775025fb4298e0 /tests | |
parent | 55f2c0a56ff8c9f08c882642129387f4d9ef052f (diff) |
QQuickTreeViewDelegate: use pointerhandlers instead of event handlers
TreeViewDelegate was using mouse event handlers to detect clicks
on the delegate and its indicator (to e.g toggle the expanded state
of a tree node). This had the effect that any pointer handlers installed
on the TreeView itself would be blocked from working, since the
delegate would accept the mouse events, and thereby stop propagation.
Since TreeView uses drag-, and tap handlers to perform selections
(installed by SelectionRectangle), using TreeViewDelegate as
delegate would basically stop selections from working.
Therefore, this patch will switch to use pointer handlers instead.
Pointer handlers are by default non-blocking, and will naturally
work better with other pointer handlers in the application, including
of course the pointer handlers installed on the TreeView itself.
The reason QQuickTreeViewDelegate was using mouse event handlers
from the start, was because it inherits QQuickAbstractButton, which does
the same. For that reason, we still need to
override mouseButtonPressed(), and ignore the mouse events, to
make sure that the QAbstractButton implementation doesn't block.
Instead we now call the appropriate mouse handling functions in
QAbstractButton directly from the pointer handlers.
Since we don't use mouse event handlers anymore, this also has the
advantage that we no longer need to recommend users to install custom
pointer handlers on a child item of the delegate - they can now be
installed directly on the delegate. Docs that described that
work-around are therefore removed/changed.
Fixes: QTBUG-105570
Change-Id: I46d82175c577a27d083494960f1cad645f4d75a4
Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
(cherry picked from commit 32cf2b272b13b1d9781ffb2fc5c168911a42fbb0)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
Diffstat (limited to 'tests')
4 files changed, 103 insertions, 20 deletions
diff --git a/tests/auto/quickcontrols2/qquicktreeviewdelegate/BLACKLIST b/tests/auto/quickcontrols2/qquicktreeviewdelegate/BLACKLIST new file mode 100644 index 0000000000..ed6d7fd2cf --- /dev/null +++ b/tests/auto/quickcontrols2/qquicktreeviewdelegate/BLACKLIST @@ -0,0 +1,6 @@ +# perhaps related to QTBUG-103072 +[dragToSelect] +android +# perhaps related to QTBUG-103064 +[pressAndHoldToSelect] +android diff --git a/tests/auto/quickcontrols2/qquicktreeviewdelegate/data/unmodified.qml b/tests/auto/quickcontrols2/qquicktreeviewdelegate/data/unmodified.qml index 02d8b39477..c3edb37d1c 100644 --- a/tests/auto/quickcontrols2/qquicktreeviewdelegate/data/unmodified.qml +++ b/tests/auto/quickcontrols2/qquicktreeviewdelegate/data/unmodified.qml @@ -10,6 +10,7 @@ Item { height: 600 property alias treeView: treeView + property alias selectionRectangle: selectionRectangle TreeView { id: treeView @@ -21,4 +22,9 @@ Item { delegate: TreeViewDelegate {} selectionModel: ItemSelectionModel { model: treeView.model } } + + SelectionRectangle { + id: selectionRectangle + target: treeView + } } diff --git a/tests/auto/quickcontrols2/qquicktreeviewdelegate/testmodel.cpp b/tests/auto/quickcontrols2/qquicktreeviewdelegate/testmodel.cpp index 06f7c09b5e..22e45f62cb 100644 --- a/tests/auto/quickcontrols2/qquicktreeviewdelegate/testmodel.cpp +++ b/tests/auto/quickcontrols2/qquicktreeviewdelegate/testmodel.cpp @@ -87,7 +87,7 @@ QModelIndex TestModel::index(int row, int column, const QModelIndex &parent) con if (!hasIndex(row, column, parent)) return QModelIndex(); if (!parent.isValid()) - return createIndex(0, 0, m_rootItem.data()); + return createIndex(row, column, m_rootItem.data()); return createIndex(row, column, treeItem(parent)->m_childItems.at(row)); } diff --git a/tests/auto/quickcontrols2/qquicktreeviewdelegate/tst_qquicktreeviewdelegate.cpp b/tests/auto/quickcontrols2/qquicktreeviewdelegate/tst_qquicktreeviewdelegate.cpp index 79d8619567..eaa9bac2ea 100644 --- a/tests/auto/quickcontrols2/qquicktreeviewdelegate/tst_qquicktreeviewdelegate.cpp +++ b/tests/auto/quickcontrols2/qquicktreeviewdelegate/tst_qquicktreeviewdelegate.cpp @@ -58,8 +58,11 @@ private slots: void checkPropertiesRoot(); void checkPropertiesChildren(); void checkCurrentIndex(); + void checkClickedSignal_data(); void checkClickedSignal(); void clearSelectionOnClick(); + void dragToSelect(); + void pressAndHoldToSelect(); }; tst_qquicktreeviewdelegate::tst_qquicktreeviewdelegate() @@ -131,32 +134,18 @@ void tst_qquicktreeviewdelegate::expandAndCollapseClickOnIndicator() const QPoint localPos = QPoint(indicator->width() / 2, indicator->height() / 2); const QPoint pos = item->window()->contentItem()->mapFromItem(indicator, localPos).toPoint(); - // When treeview is interactive, we toggle expanded on pointer release - // to not interfere with flicking. Otherwise we expand already on press. - if (interactive) - QTest::mouseClick(item->window(), Qt::LeftButton, Qt::NoModifier, pos); - else - QTest::mousePress(item->window(), Qt::LeftButton, Qt::NoModifier, pos); + QTest::mouseClick(item->window(), Qt::LeftButton, Qt::NoModifier, pos); WAIT_UNTIL_POLISHED; // We now expect 5 rows, the root pluss it's 4 children QCOMPARE(treeViewPrivate->loadedRows.count(), 5); - if (!interactive) - QTest::mouseRelease(item->window(), Qt::LeftButton, Qt::NoModifier, pos); - // Collapse the root again - if (interactive) - QTest::mouseClick(item->window(), Qt::LeftButton, Qt::NoModifier, pos); - else - QTest::mousePress(item->window(), Qt::LeftButton, Qt::NoModifier, pos); + QTest::mouseClick(item->window(), Qt::LeftButton, Qt::NoModifier, pos); WAIT_UNTIL_POLISHED; // Check that the view only has one row loaded again (the root of the tree) QCOMPARE(treeViewPrivate->loadedRows.count(), 1); - - if (!interactive) - QTest::mouseRelease(item->window(), Qt::LeftButton, Qt::NoModifier, pos); } void tst_qquicktreeviewdelegate::pointerNavigationDisabled() @@ -281,11 +270,23 @@ void tst_qquicktreeviewdelegate::checkCurrentIndex() QVERIFY(item->selected()); } +void tst_qquicktreeviewdelegate::checkClickedSignal_data() +{ + QTest::addColumn<bool>("pointerNavigationEnabled"); + QTest::newRow("pointer navigation enabled") << true; + QTest::newRow("pointer navigation disabled") << false; +} + void tst_qquicktreeviewdelegate::checkClickedSignal() { - // Check that the delegate emits clicked when clicking on the - // label, but not when clicking on the indicator. + // Check that the delegate emits clicked when clicking on the + // label, but not when clicking on the indicator. This API is + // a part of the AbstractButton API, and should work with or + // without TableView.pointerNavigationEnabled set. + QFETCH(bool, pointerNavigationEnabled); + LOAD_TREEVIEW("unmodified.qml"); + treeView->setPointerNavigationEnabled(pointerNavigationEnabled); const auto item = treeView->itemAtCell(0, 0); QVERIFY(item); @@ -297,6 +298,7 @@ void tst_qquicktreeviewdelegate::checkClickedSignal() QPoint pos = item->window()->contentItem()->mapFromItem(item, localPos).toPoint(); QTest::mouseClick(item->window(), Qt::LeftButton, Qt::NoModifier, pos); QCOMPARE(clickedSpy.count(), 1); + clickedSpy.clear(); // Click on the indicator const auto indicator = item->property("indicator").value<QQuickItem *>(); @@ -304,7 +306,7 @@ void tst_qquicktreeviewdelegate::checkClickedSignal() localPos = QPoint(indicator->x() + indicator->width() / 2, indicator->y() + indicator->height() / 2); pos = item->window()->contentItem()->mapFromItem(item, localPos).toPoint(); QTest::mouseClick(item->window(), Qt::LeftButton, Qt::NoModifier, pos); - QCOMPARE(clickedSpy.count(), 1); + QCOMPARE(clickedSpy.count(), 0); } void tst_qquicktreeviewdelegate::clearSelectionOnClick() @@ -325,6 +327,75 @@ void tst_qquicktreeviewdelegate::clearSelectionOnClick() QCOMPARE(treeView->selectionModel()->selectedIndexes().count(), 0); } +void tst_qquicktreeviewdelegate::dragToSelect() +{ + // Check that the delegate is not blocking the user from + // being able to select cells using Drag. + LOAD_TREEVIEW("unmodified.qml"); + + // When TreeView is not interactive, SelectionRectangle + // will use Drag by default. + treeView->setInteractive(false); + treeView->expandRecursively(); + + WAIT_UNTIL_POLISHED; + + QVERIFY(!treeView->selectionModel()->hasSelection()); + QCOMPARE(treeView->selectionBehavior(), QQuickTableView::SelectRows); + + // Drag on from cell 0,0 to 0,1 + const auto item0_0 = treeView->itemAtCell(0, 0); + const auto item0_1 = treeView->itemAtCell(0, 1); + QVERIFY(item0_0); + QVERIFY(item0_1); + + QQuickWindow *window = treeView->window(); + QPoint localPos0_0 = QPoint(item0_0->width() / 2, item0_0->height() / 2); + QPoint windowPos0_0 = window->contentItem()->mapFromItem(item0_0, localPos0_0).toPoint(); + QPoint localPos0_1 = QPoint(item0_1->width() / 2, item0_1->height() / 2); + QPoint windowPos0_1 = window->contentItem()->mapFromItem(item0_1, localPos0_1).toPoint(); + + QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, windowPos0_0); + QTest::mouseMove(window, windowPos0_1); + QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, windowPos0_1); + + // Since TreeView uses TableView.SelectRows by default, we + // now expect cells from 0,0 and 1,1 to be selected. + QCOMPARE(treeView->selectionModel()->selectedIndexes().count(), 4); +} + +void tst_qquicktreeviewdelegate::pressAndHoldToSelect() +{ + // Check that the delegate is not blocking the user from + // being able to select cells using PressAndHold + LOAD_TREEVIEW("unmodified.qml"); + + // When TreeView is interactive, SelectionRectangle + // will use PressAndHold by default. + treeView->setInteractive(true); + treeView->expandRecursively(); + + WAIT_UNTIL_POLISHED; + + QVERIFY(!treeView->selectionModel()->hasSelection()); + QCOMPARE(treeView->selectionBehavior(), QQuickTableView::SelectRows); + + // PressAndHold on cell 0,0 + const auto item0_0 = treeView->itemAtCell(0, 0); + QVERIFY(item0_0); + + QQuickWindow *window = treeView->window(); + QPoint localPos0_0 = QPoint(item0_0->width() / 2, item0_0->height() / 2); + QPoint windowPos0_0 = window->contentItem()->mapFromItem(item0_0, localPos0_0).toPoint(); + + QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, windowPos0_0); + QTRY_VERIFY(treeView->selectionModel()->hasSelection()); + // Since TreeView uses TableView.SelectRows by default, we + // now expect both cell 0,0 and 1,0 to be selected. + QCOMPARE(treeView->selectionModel()->selectedIndexes().count(), 2); + QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, windowPos0_0); +} + QTEST_MAIN(tst_qquicktreeviewdelegate) #include "tst_qquicktreeviewdelegate.moc" |