Improve keyboard navigation in QListView when isWrapping is enabled

Search the previous item or the next item in a model instead
of searching them on visual layout. This way the cursor will
not stop at the beginning or at the end of a row or a column.

Fixes: QTBUG-14444
Change-Id: I0ef203a4dcd876e4c50559fb87e61585f07434d1
Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
This commit is contained in:
Alexander Volkov 2019-02-01 15:34:49 +03:00
parent 670b843369
commit f6edb0ef72
2 changed files with 51 additions and 8 deletions

View File

@ -1100,19 +1100,45 @@ QModelIndex QListView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifie
Q_D(QListView); Q_D(QListView);
Q_UNUSED(modifiers); Q_UNUSED(modifiers);
QModelIndex current = currentIndex(); auto findAvailableRowBackward = [d](int row) {
if (!current.isValid()) { while (row >= 0 && d->isHiddenOrDisabled(row))
--row;
return row;
};
auto findAvailableRowForward = [d](int row) {
int rowCount = d->model->rowCount(d->root); int rowCount = d->model->rowCount(d->root);
if (!rowCount) if (!rowCount)
return QModelIndex(); return -1;
int row = 0;
while (row < rowCount && d->isHiddenOrDisabled(row)) while (row < rowCount && d->isHiddenOrDisabled(row))
++row; ++row;
if (row >= rowCount) if (row >= rowCount)
return -1;
return row;
};
QModelIndex current = currentIndex();
if (!current.isValid()) {
int row = findAvailableRowForward(0);
if (row == -1)
return QModelIndex(); return QModelIndex();
return d->model->index(row, d->column, d->root); return d->model->index(row, d->column, d->root);
} }
if ((d->flow == LeftToRight && cursorAction == MoveLeft) ||
(d->flow == TopToBottom && (cursorAction == MoveUp || cursorAction == MovePrevious))) {
const int row = findAvailableRowBackward(current.row() - 1);
if (row == -1)
return current;
return d->model->index(row, d->column, d->root);
} else if ((d->flow == LeftToRight && cursorAction == MoveRight) ||
(d->flow == TopToBottom && (cursorAction == MoveDown || cursorAction == MoveNext))) {
const int row = findAvailableRowForward(current.row() + 1);
if (row == -1)
return current;
return d->model->index(row, d->column, d->root);
}
const QRect initialRect = rectForIndex(current); const QRect initialRect = rectForIndex(current);
QRect rect = initialRect; QRect rect = initialRect;
if (rect.isEmpty()) { if (rect.isEmpty()) {

View File

@ -380,8 +380,11 @@ void tst_QListView::cursorMove()
<< Qt::Key_Up << Qt::Key_Up << Qt::Key_Up << Qt::Key_Up << Qt::Key_Up << Qt::Key_Up << Qt::Key_Up << Qt::Key_Up << Qt::Key_Up << Qt::Key_Up
<< Qt::Key_Left << Qt::Key_Left << Qt::Key_Up << Qt::Key_Down; << Qt::Key_Left << Qt::Key_Left << Qt::Key_Up << Qt::Key_Down;
int displayRow = rows / displayColumns - 1; int lastRow = rows / displayColumns - 1;
int displayColumn = displayColumns - (rows % displayColumns) - 1; int lastColumn = displayColumns - 1;
int displayRow = lastRow;
int displayColumn = lastColumn - (rows % displayColumns);
QApplication::instance()->processEvents(); QApplication::instance()->processEvents();
for (int i = 0; i < keymoves.size(); ++i) { for (int i = 0; i < keymoves.size(); ++i) {
@ -395,10 +398,24 @@ void tst_QListView::cursorMove()
displayRow = qMin(rows / displayColumns - 1, displayRow + 1); displayRow = qMin(rows / displayColumns - 1, displayRow + 1);
break; break;
case Qt::Key_Left: case Qt::Key_Left:
displayColumn = qMax(0, displayColumn - 1); if (displayColumn > 0) {
displayColumn--;
} else {
if (displayRow > 0) {
displayRow--;
displayColumn = lastColumn;
}
}
break; break;
case Qt::Key_Right: case Qt::Key_Right:
displayColumn = qMin(displayColumns-1, displayColumn + 1); if (displayColumn < lastColumn) {
displayColumn++;
} else {
if (displayRow < lastRow) {
displayRow++;
displayColumn = 0;
}
}
break; break;
default: default:
QVERIFY(false); QVERIFY(false);