QQuickTreeView: add keyboard navigation support
Override keyPressEvent in QQuickTreeView to let the left and right arrow keys expand and collapse the current row in the tree. Note that the application developer can set keyNavigationEnabled to false if this default behavior is not wanted. Change-Id: If5201dafd1d3d7e2e4a113aeb2a60f601a1a4c35 Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
This commit is contained in:
parent
eb5ff13248
commit
b23626d0b8
|
@ -571,6 +571,33 @@ QModelIndex QQuickTreeView::modelIndex(int column, int row) const
|
|||
return modelIndex({column, row});
|
||||
}
|
||||
|
||||
void QQuickTreeView::keyPressEvent(QKeyEvent *event)
|
||||
{
|
||||
event->ignore();
|
||||
|
||||
if (!keyNavigationEnabled())
|
||||
return;
|
||||
if (!selectionModel())
|
||||
return;
|
||||
|
||||
const int row = cellAtIndex(selectionModel()->currentIndex()).y();
|
||||
switch (event->key()) {
|
||||
case Qt::Key_Left:
|
||||
collapse(row);
|
||||
event->accept();
|
||||
break;
|
||||
case Qt::Key_Right:
|
||||
expand(row);
|
||||
event->accept();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!event->isAccepted())
|
||||
QQuickTableView::keyPressEvent(event);
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#include "moc_qquicktreeview_p.cpp"
|
||||
|
|
|
@ -87,6 +87,9 @@ signals:
|
|||
void expanded(int row, int depth);
|
||||
void collapsed(int row, bool recursively);
|
||||
|
||||
protected:
|
||||
void keyPressEvent(QKeyEvent *event) override;
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(QQuickTreeView)
|
||||
Q_DECLARE_PRIVATE(QQuickTreeView)
|
||||
|
|
|
@ -40,11 +40,12 @@
|
|||
import QtQuick
|
||||
import TestModel
|
||||
|
||||
Item {
|
||||
Rectangle {
|
||||
id: root
|
||||
|
||||
implicitWidth: padding + label.x + label.implicitWidth + padding
|
||||
implicitHeight: label.implicitHeight * 1.5
|
||||
color: current ? "lightgreen" : "white"
|
||||
|
||||
property alias text: label.text
|
||||
|
||||
|
@ -57,6 +58,7 @@ Item {
|
|||
required property bool expanded
|
||||
required property int hasChildren
|
||||
required property int depth
|
||||
required property bool current
|
||||
|
||||
TapHandler {
|
||||
onTapped: treeView.toggleExpanded(row)
|
||||
|
|
|
@ -51,6 +51,7 @@ Item {
|
|||
anchors.fill:parent
|
||||
anchors.margins: 10
|
||||
model: TestModel {}
|
||||
selectionModel: ItemSelectionModel {}
|
||||
clip: true
|
||||
|
||||
delegate: CustomDelegate {}
|
||||
|
|
|
@ -109,6 +109,7 @@ private slots:
|
|||
void emptyModel();
|
||||
void updatedModifiedModel();
|
||||
void insertRows();
|
||||
void toggleExpandedUsingArrowKeys();
|
||||
};
|
||||
|
||||
tst_qquicktreeview::tst_qquicktreeview()
|
||||
|
@ -731,6 +732,68 @@ void tst_qquicktreeview::expandToIndex()
|
|||
QCOMPARE(treeView->rows(), 13);
|
||||
}
|
||||
|
||||
void tst_qquicktreeview::toggleExpandedUsingArrowKeys()
|
||||
{
|
||||
// Check that you can use the left and right arrow key to
|
||||
// expand and collapse nodes in the tree.
|
||||
LOAD_TREEVIEW("normaltreeview.qml");
|
||||
|
||||
treeView->setFocus(true);
|
||||
QQuickWindow *window = treeView->window();
|
||||
|
||||
// Start by making cell 0, 0 current
|
||||
treeView->selectionModel()->setCurrentIndex(treeView->modelIndex(0, 0), QItemSelectionModel::NoUpdate);
|
||||
|
||||
// Expand row 0
|
||||
const int row0 = 0;
|
||||
QCOMPARE(treeView->rows(), 1);
|
||||
QVERIFY(!treeView->isExpanded(row0));
|
||||
QTest::keyPress(window, Qt::Key_Right);
|
||||
QVERIFY(treeView->isExpanded(row0));
|
||||
|
||||
// A polish event was scheduled, but since the call to keyPress() processes
|
||||
// events, WAIT_UNTIL_POLISHED will be unreliable. So use QTRY_COMPARE instead.
|
||||
QTRY_COMPARE(treeView->rows(), 5);
|
||||
|
||||
// Hitting Key_Right again should be a no-op
|
||||
QTest::keyPress(window, Qt::Key_Right);
|
||||
QVERIFY(treeView->isExpanded(row0));
|
||||
QCOMPARE(treeView->selectionModel()->currentIndex(), treeView->modelIndex(0, row0));
|
||||
|
||||
// Move down to row 1 and try to expand it. Since Row 1
|
||||
// doesn't have children, expanding it will be a no-op.
|
||||
// And also, it shouldn't move currentIndex to the next
|
||||
// column either, it should stay in the tree column.
|
||||
const int row1 = 1;
|
||||
QVERIFY(!treeView->isExpanded(row1));
|
||||
QTest::keyPress(window, Qt::Key_Down);
|
||||
QTest::keyPress(window, Qt::Key_Right);
|
||||
QVERIFY(!treeView->isExpanded(row1));
|
||||
QCOMPARE(treeView->selectionModel()->currentIndex(), treeView->modelIndex(0, row1));
|
||||
|
||||
// Move down to row 4 and expand it
|
||||
const int row4 = 4;
|
||||
QCOMPARE(treeView->rows(), 5);
|
||||
while (treeView->currentRow() != row4)
|
||||
QTest::keyPress(window, Qt::Key_Down);
|
||||
QVERIFY(!treeView->isExpanded(row4));
|
||||
QTest::keyPress(window, Qt::Key_Right);
|
||||
QVERIFY(treeView->isExpanded(row4));
|
||||
QCOMPARE(treeView->selectionModel()->currentIndex(), treeView->modelIndex(0, row4));
|
||||
|
||||
// Move up again to row 0 and collapse it
|
||||
while (treeView->currentRow() != row0)
|
||||
QTest::keyPress(window, Qt::Key_Up);
|
||||
QVERIFY(treeView->isExpanded(row0));
|
||||
QTest::keyPress(window, Qt::Key_Left);
|
||||
QVERIFY(!treeView->isExpanded(row0));
|
||||
QTRY_COMPARE(treeView->rows(), 1);
|
||||
|
||||
// Hitting Key_Left again should be a no-op
|
||||
QTest::keyPress(window, Qt::Key_Left);
|
||||
QVERIFY(!treeView->isExpanded(row0));
|
||||
QCOMPARE(treeView->selectionModel()->currentIndex(), treeView->modelIndex(0, row0));
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_qquicktreeview)
|
||||
|
||||
|
|
Loading…
Reference in New Issue