diff options
author | Richard Moe Gustavsen <richard.gustavsen@qt.io> | 2022-12-20 15:57:23 +0100 |
---|---|---|
committer | Richard Moe Gustavsen <richard.gustavsen@qt.io> | 2023-01-20 20:39:11 +0100 |
commit | ea5200b82f21e0f4d080d3fc256b218e0ee56f3d (patch) | |
tree | be8473c4b27dec02305d71e0e36600646004a5cb /tests/auto | |
parent | e34142e6cda177b601d8e5daba00a2ab84828db1 (diff) |
QQuickTableView: set active focus directly on the edit item
When starting to edit a cell, the current implementation
calls editItem->nextItemInFocusChain(true) to resolve the
child to get active focus. But a better way is to instead
rely on the edit item being a FocusScope. That way, we can
simply set active focus on the edit item directly, and rely
on the FocusScope forwarding active focus to the right child.
After all, that is what FocusScopes are for.
This patch will therefore change the implementation to set active
focus directly on the edit item.
But doing so turns out to cause tabbing from one cell
to the next to stop working. The reason is that QQuickItem refuses
to change setActiveFocusOnTab() on an item that has active focus.
Instead, the focus item will eat the tab event, and
use it to transfer focus to the next control in the chain.
We therefore change the implementation to use an event filter on the
focus object. That way, we're are guaranteed to always get a first
shot at handling all critical key events that are needed for editing
to work correctly. This includes tabbing, but even more
imporantant, also Qt::Key_Enter, which is needed to allow
the user to commit and close the editor.
Pick-to: 6.5
Change-Id: I215b7efc52093eb0bd7f6a4fb60a57f83101e288
Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
Diffstat (limited to 'tests/auto')
-rw-r--r-- | tests/auto/quick/qquicktableview/data/editdelegate_combobox.qml | 67 | ||||
-rw-r--r-- | tests/auto/quick/qquicktableview/tst_qquicktableview.cpp | 68 |
2 files changed, 135 insertions, 0 deletions
diff --git a/tests/auto/quick/qquicktableview/data/editdelegate_combobox.qml b/tests/auto/quick/qquicktableview/data/editdelegate_combobox.qml new file mode 100644 index 0000000000..b7de4cd406 --- /dev/null +++ b/tests/auto/quick/qquicktableview/data/editdelegate_combobox.qml @@ -0,0 +1,67 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +import QtQuick +import QtQuick.Window +import QtQuick.Controls + +Item { + width: 640 + height: 450 + + property alias tableView: tableView + + TableView { + id: tableView + anchors.fill: parent + clip: true + + property Item editItem: null + property Item focusItem: null + property var editIndex + property int commitCount: 0 + property int comboFocusCount: 0 + + selectionModel: ItemSelectionModel {} + + delegate: Rectangle { + implicitWidth: 100 + implicitHeight: 50 + + required property bool editing + + Text { + anchors.centerIn: parent + text: display + visible: !editing + } + + TableView.editDelegate: FocusScope { + id: editRoot + anchors.fill: parent + required property bool current + required property bool selected + required property bool editing + + TableView.onCommit: tableView.commitCount++; + + Component.onCompleted: { + tableView.editItem = editRoot + tableView.editIndex = tableView.modelIndex(row, column) + } + + Component.onDestruction: { + tableView.editItem = null + tableView.editIndex = tableView.modelIndex(-1, -1) + } + + ComboBox { + focus: true + model: 4 + onActiveFocusChanged: if (activeFocus) tableView.comboFocusCount++; + } + } + } + } + +} diff --git a/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp b/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp index b0134a94d4..ecea4adfd5 100644 --- a/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp +++ b/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp @@ -256,6 +256,7 @@ private slots: void editUsingEditTriggers_data(); void editUsingEditTriggers(); void editUsingTab(); + void editDelegateComboBox(); void editOnNonEditableCell_data(); void editOnNonEditableCell(); void noEditDelegate_data(); @@ -6752,6 +6753,73 @@ void tst_QQuickTableView::editUsingTab() QVERIFY(editItem3); } +void tst_QQuickTableView::editDelegateComboBox() +{ + // Using a ComboBox as an edit delegate should be a quite common + // use case. So test that it works. + LOAD_TABLEVIEW("editdelegate_combobox.qml"); + + auto model = TestModel(4, 4); + tableView->setModel(QVariant::fromValue(&model)); + tableView->forceActiveFocus(); + + const char kEditItem[] = "editItem"; + const char kEditIndex[] = "editIndex"; + const char kCommitCount[] = "commitCount"; + const char kComboFocusCount[] = "comboFocusCount"; + + WAIT_UNTIL_POLISHED; + + const QPoint cell1(1, 1); + const QPoint cell2(2, 1); + const QModelIndex index1 = tableView->modelIndex(cell1); + const QModelIndex index2 = tableView->modelIndex(cell2); + + QQuickWindow *window = tableView->window(); + + // Edit cell 1 + tableView->edit(index1); + QCOMPARE(tableView->property(kEditIndex).value<QModelIndex>(), index1); + const QQuickItem *editItem1 = tableView->property(kEditItem).value<QQuickItem *>(); + QVERIFY(editItem1); + QCOMPARE(tableView->property(kComboFocusCount).value<int>(), 1); + + // Press Tab to edit cell 2 + QTest::keyClick(window, Qt::Key_Tab); + QCOMPARE(tableView->property(kCommitCount).value<int>(), 1); + QCOMPARE(tableView->property(kEditIndex).value<QModelIndex>(), index2); + const QQuickItem *editItem2 = tableView->property(kEditItem).value<QQuickItem *>(); + QVERIFY(editItem2); + QCOMPARE(tableView->property(kComboFocusCount).value<int>(), 2); + + // Press Enter to commit + QTest::keyClick(window, Qt::Key_Enter); + QCOMPARE(tableView->property(kCommitCount).value<int>(), 2); + QCOMPARE(tableView->property(kComboFocusCount).value<int>(), 2); + QVERIFY(!tableView->property(kEditIndex).value<QModelIndex>().isValid()); + QVERIFY(!tableView->property(kEditItem).value<QQuickItem *>()); + + // Edit cell 1 + tableView->edit(index1); + // Press escape to close editor + QTest::keyClick(window, Qt::Key_Escape); + QCOMPARE(tableView->property(kCommitCount).value<int>(), 2); + QCOMPARE(tableView->property(kComboFocusCount).value<int>(), 3); + QVERIFY(!tableView->property(kEditIndex).value<QModelIndex>().isValid()); + QVERIFY(!tableView->property(kEditItem).value<QQuickItem *>()); + + // Edit cell 2 + tableView->edit(index2); + // Press space to open combo menu + QTest::keyClick(window, Qt::Key_Space); + // Press Enter to commit and close the editor + QTest::keyClick(window, Qt::Key_Enter); + QCOMPARE(tableView->property(kCommitCount).value<int>(), 3); + QCOMPARE(tableView->property(kComboFocusCount).value<int>(), 4); + QVERIFY(!tableView->property(kEditIndex).value<QModelIndex>().isValid()); + QVERIFY(!tableView->property(kEditItem).value<QQuickItem *>()); +} + void tst_QQuickTableView::editOnNonEditableCell_data() { QTest::addColumn<QQuickTableView::EditTriggers>("editTriggers"); |