diff --git a/src/widgets/itemviews/qlistview.cpp b/src/widgets/itemviews/qlistview.cpp index 59ba1ec6b63..e655b639b9a 100644 --- a/src/widgets/itemviews/qlistview.cpp +++ b/src/widgets/itemviews/qlistview.cpp @@ -1234,13 +1234,25 @@ QModelIndex QListView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifie d->removeCurrentAndDisabled(&intersectVector, current); } return d->closestIndex(initialRect, intersectVector); - case MovePageUp: - // move current by (visibileRowCount - 1) items. - // rect.translate(0, -rect.height()); will happen in the switch fallthrough for MoveUp. - rect.moveTop(rect.top() - d->viewport->height() + 2 * rect.height()); - if (rect.top() < rect.height()) - rect.moveTop(rect.height()); - Q_FALLTHROUGH(); + case MovePageUp: { + rect.moveTop(rect.top() - d->viewport->height() + 1 ); + if (rect.top() < rect.height()) { + rect.setTop(0); + rect.setBottom(1); + } + QModelIndex findindex = current; + while (intersectVector.isEmpty() + || rectForIndex(findindex).top() <= (rectForIndex(current).bottom() - d->viewport->rect().height()) + || rect.top() <= 0) { + rect.translate(0, 1); + if (rect.bottom() <= 0) { + return current; + } + intersectVector = d->intersectingSet(rect); + findindex = d->closestIndex(initialRect, intersectVector); + } + return findindex; + } case MovePrevious: case MoveUp: while (intersectVector.isEmpty()) { @@ -1263,13 +1275,26 @@ QModelIndex QListView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifie d->removeCurrentAndDisabled(&intersectVector, current); } return d->closestIndex(initialRect, intersectVector); - case MovePageDown: - // move current by (visibileRowCount - 1) items. - // rect.translate(0, rect.height()); will happen in the switch fallthrough for MoveDown. - rect.moveTop(rect.top() + d->viewport->height() - 2 * rect.height()); - if (rect.bottom() > contents.height() - rect.height()) - rect.moveBottom(contents.height() - rect.height()); - Q_FALLTHROUGH(); + case MovePageDown: { + rect.moveTop(rect.top() + d->viewport->height() - 1 ); + if (rect.bottom() > contents.height() - rect.height()){ + rect.setTop(contents.height() - 1); + rect.setBottom(contents.height()); + } + QModelIndex index = current; + // index's bottom() - current's top() always <= (d->viewport->rect().height() + while (intersectVector.isEmpty() + || rectForIndex(index).bottom() >= (d->viewport->rect().height() + rectForIndex(current).top()) + || rect.bottom() > contents.height()) { + rect.translate(0, -1); + if (rect.top() >= contents.height()) { + return current; + } + intersectVector = d->intersectingSet(rect); + index = d->closestIndex(initialRect, intersectVector); + } + return index; + } case MoveNext: case MoveDown: while (intersectVector.isEmpty()) { diff --git a/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp b/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp index 3768acade70..8948f02a8b6 100644 --- a/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp +++ b/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp @@ -109,6 +109,7 @@ private slots: void moveCursor(); void moveCursor2(); void moveCursor3(); + void moveCursor4(); void indexAt(); void clicked(); void singleSelectionRemoveRow(); @@ -573,6 +574,56 @@ void tst_QListView::moveCursor3() QCOMPARE(view.selectionModel()->currentIndex(), model.index(0, 0)); } +void tst_QListView::moveCursor4() +{ + int indexCount = 100; + PublicListView listView; + QStandardItemModel model; + for (int i = 0; i < 100; i++) + { + QStandardItem* item = new QStandardItem(QString("item 0%0").arg(i)); + QFont font = item->font(); + font.setPixelSize(14); + item->setFont(font); + model.appendRow(item); + } + QFont font = model.item(0)->font(); + font.setPixelSize(50); + font.setBold(true); + model.item(0)->setFont(font); + listView.setModel(&model); + listView.setFixedSize(200, 200); + listView.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + listView.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + listView.show(); + listView.selectionModel()->setCurrentIndex(model.index(0, 0), QItemSelectionModel::SelectCurrent); + + QModelIndex idx = listView.moveCursor(PublicListView::MovePageDown, Qt::NoModifier); + + int actualIndex = 0; + int indexHeight = 0; + while (indexHeight <= listView.viewport()->height()) { + indexHeight += listView.visualRect(model.item(actualIndex)->index()).height(); + actualIndex++; + } + QTRY_COMPARE(idx, model.index(actualIndex - 2, 0)); + idx = listView.moveCursor(PublicListView::MoveUp, Qt::NoModifier); + QTRY_COMPARE(idx, model.index(0, 0)); + + listView.setCurrentIndex(model.index(indexCount - 2, 0)); + idx = listView.moveCursor(PublicListView::MovePageDown, Qt::NoModifier); + QTRY_COMPARE(idx, model.index(99, 0)); + + listView.setCurrentIndex(model.index(3, 0)); + actualIndex = 3; + indexHeight = 0; + while (indexHeight <= listView.viewport()->height()) { + indexHeight += listView.visualRect(model.item(actualIndex)->index()).height(); + actualIndex++; + } + idx = listView.moveCursor(PublicListView::MovePageDown, Qt::NoModifier); + QTRY_COMPARE(idx, model.index(actualIndex - 2, 0)); +} class QListViewShowEventListener : public QListView {