Start from the first visible item when doing a search

Since the first item in a treeview might be hidden, start from the
first visible item in the view when starting or wrapping round
during a keyboard search.

Task-number: QTBUG-63869
Change-Id: I202bea567c6d4484c3ffaf8a5f9af8ea2e13708d
Reviewed-by: Thorbjørn Lund Martsum <tmartsum@gmail.com>
bb10
Andy Shaw 2017-11-01 12:11:33 +01:00
parent 048c380629
commit 53f48fceee
2 changed files with 110 additions and 5 deletions

View File

@ -1014,11 +1014,16 @@ void QTreeView::keyboardSearch(const QString &search)
if (!d->model->rowCount(d->root) || !d->model->columnCount(d->root))
return;
// Do a relayout nows, so that we can utilize viewItems
d->executePostedLayout();
if (d->viewItems.isEmpty())
return;
QModelIndex start;
if (currentIndex().isValid())
start = currentIndex();
else
start = d->model->index(0, 0, d->root);
start = d->viewItems.at(0).index;
bool skipRow = false;
bool keyboardTimeWasValid = d->keyboardInputTime.isValid();
@ -1046,13 +1051,16 @@ void QTreeView::keyboardSearch(const QString &search)
// skip if we are searching for the same key or a new search started
if (skipRow) {
if (indexBelow(start).isValid())
if (indexBelow(start).isValid()) {
start = indexBelow(start);
else
start = d->model->index(0, start.column(), d->root);
} else {
const int origCol = start.column();
start = d->viewItems.at(0).index;
if (origCol != start.column())
start = start.sibling(start.row(), origCol);
}
}
d->executePostedLayout();
int startIndex = d->viewIndex(start);
if (startIndex <= -1)
return;

View File

@ -1067,6 +1067,103 @@ void tst_QTreeView::keyboardSearch()
// The item that starts with B is selected.
view.keyboardSearch(QLatin1String("B"));
QVERIFY(view.selectionModel()->isSelected(model.index(1, 0)));
// Test that it wraps round
model.appendRow(new QStandardItem("Andy"));
QTest::qWait(QApplication::keyboardInputInterval() * 2);
view.keyboardSearch(QLatin1String("A"));
QVERIFY(view.selectionModel()->isSelected(model.index(3, 0)));
QTest::qWait(QApplication::keyboardInputInterval() * 2);
view.keyboardSearch(QLatin1String("A"));
QVERIFY(view.selectionModel()->isSelected(model.index(0, 0)));
QTest::qWait(QApplication::keyboardInputInterval() * 2);
view.keyboardSearch(QLatin1String("A"));
QVERIFY(view.selectionModel()->isSelected(model.index(3, 0)));
// Test that it handles the case where the first item is hidden correctly
model.insertRow(0, new QStandardItem("Hidden item"));
view.setRowHidden(0, QModelIndex(), true);
QTest::qWait(QApplication::keyboardInputInterval() * 2);
view.keyboardSearch(QLatin1String("A"));
QVERIFY(view.selectionModel()->isSelected(model.index(1, 0)));
QTest::qWait(QApplication::keyboardInputInterval() * 2);
view.keyboardSearch(QLatin1String("A"));
QVERIFY(view.selectionModel()->isSelected(model.index(4, 0)));
QTest::qWait(QApplication::keyboardInputInterval() * 2);
view.keyboardSearch(QLatin1String("A"));
QVERIFY(view.selectionModel()->isSelected(model.index(1, 0)));
QTest::qWait(QApplication::keyboardInputInterval() * 2);
model.clear();
view.setCurrentIndex(QModelIndex());
QList<QStandardItem *> items = { new QStandardItem("Andreas"), new QStandardItem("Alicia") };
model.appendRow(items);
items = { new QStandardItem("Baldrian"), new QStandardItem("Belinda") };
model.appendRow(items);
items = { new QStandardItem("Cecilie"), new QStandardItem("Claire") };
model.appendRow(items);
QVERIFY(!view.selectionModel()->hasSelection());
QVERIFY(!view.selectionModel()->isSelected(model.index(0, 0)));
// We want to search on the 2nd column so we have to force it to have
// an index in that column as a starting point
view.setCurrentIndex(QModelIndex(model.index(0, 1)));
// Second item in first row is selected
view.keyboardSearch(QLatin1String("A"));
QTRY_VERIFY(view.selectionModel()->isSelected(model.index(0, 1)));
QVERIFY(view.currentIndex() == model.index(0, 1));
// Second item in first row is still selected
view.keyboardSearch(QLatin1String("l"));
QVERIFY(view.selectionModel()->isSelected(model.index(0, 1)));
QCOMPARE(view.currentIndex(), model.index(0, 1));
// No "AnB" item - keep the same selection.
view.keyboardSearch(QLatin1String("B"));
QVERIFY(view.selectionModel()->isSelected(model.index(0, 1)));
QCOMPARE(view.currentIndex(), model.index(0, 1));
// Wait a bit.
QTest::qWait(QApplication::keyboardInputInterval() * 2);
// The item that starts with B is selected.
view.keyboardSearch(QLatin1String("B"));
QVERIFY(view.selectionModel()->isSelected(model.index(1, 1)));
QCOMPARE(view.currentIndex(), model.index(1, 1));
// Test that it wraps round
items = { new QStandardItem("Andy"), new QStandardItem("Adele") };
model.appendRow(items);
QTest::qWait(QApplication::keyboardInputInterval() * 2);
view.keyboardSearch(QLatin1String("A"));
QVERIFY(view.selectionModel()->isSelected(model.index(3, 1)));
QCOMPARE(view.currentIndex(), model.index(3, 1));
QTest::qWait(QApplication::keyboardInputInterval() * 2);
view.keyboardSearch(QLatin1String("A"));
QVERIFY(view.selectionModel()->isSelected(model.index(0, 1)));
QCOMPARE(view.currentIndex(), model.index(0, 1));
QTest::qWait(QApplication::keyboardInputInterval() * 2);
view.keyboardSearch(QLatin1String("A"));
QVERIFY(view.selectionModel()->isSelected(model.index(3, 1)));
QCOMPARE(view.currentIndex(), model.index(3, 1));
// Test that it handles the case where the first item is hidden correctly
model.insertRow(0, new QStandardItem("Hidden item"));
view.setRowHidden(0, QModelIndex(), true);
QTest::qWait(QApplication::keyboardInputInterval() * 2);
view.keyboardSearch(QLatin1String("A"));
QVERIFY(view.selectionModel()->isSelected(model.index(1, 1)));
QCOMPARE(view.currentIndex(), model.index(1, 1));
QTest::qWait(QApplication::keyboardInputInterval() * 2);
view.keyboardSearch(QLatin1String("A"));
QVERIFY(view.selectionModel()->isSelected(model.index(4, 1)));
QCOMPARE(view.currentIndex(), model.index(4, 1));
QTest::qWait(QApplication::keyboardInputInterval() * 2);
view.keyboardSearch(QLatin1String("A"));
QVERIFY(view.selectionModel()->isSelected(model.index(1, 1)));
QCOMPARE(view.currentIndex(), model.index(1, 1));
}
void tst_QTreeView::keyboardSearchMultiColumn()