Fix PageDown behavior and PageUP

When the PageDown is pressed, the current's rect cannot be
used to match the item, because we don't know the size of
the rect. Move the rect by the height of the viewport, and
then move the rect upwards until it matches the
button <= viewport's bottom of the item

Fixes: QTBUG-92583
Change-Id: I210edc0e8b942984f3fc20e7752c6e1315152ea1
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
(cherry picked from commit c77840d734883c91079c942e052cbdc0994c2f01)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Tang Haixiang 2021-04-27 17:39:48 +08:00 committed by Qt Cherry-pick Bot
parent 1a081042ab
commit bd73184395
2 changed files with 90 additions and 14 deletions

View File

@ -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()) {

View File

@ -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
{