diff options
author | Richard Moe Gustavsen <richard.gustavsen@qt.io> | 2022-05-06 15:05:59 +0200 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2022-05-10 16:41:00 +0000 |
commit | c8ec32c64c6867826d4555ed1f561ae52a574322 (patch) | |
tree | 50dfaa4e781045f6a74664645bd38b15a4c9c92b /src/quick/items/qquickgridview.cpp | |
parent | a46d508ef00180244ce1f4d9364217336f8b8326 (diff) |
QQuickGridView: return accurate row position when no rows are available
QQuickGridViewPrivate::rowPosAt() returns the position of a
row for a given index. At start-up, when no rows are yet
loaded, a plain "(modelIndex / columns) * rowSize()" fallback
calculation is sufficient.
But as the user flicks around, and new rows are moving into the
viewport, the current logic shifts to rely on the position of an
already visible row to calculate the position of a new one.
This is because the fallback calculation above will assume
that row 0 always starts at contentY == 0, which is not always
true for GridView - sometimes it will place rows outside the
content item to make room for rows that were added after start-up.
Likewise, if the cellWidth/Height changes, it might force existing
rows to be placed outside the content item. So using an already
loaded row as a reference becomes more accurate, especially when
flicking slowly.
The problem is that the fallback calculation is not only used
at start-up. It's also used when e.g moving the content item a
long distance in one go by e.g setting contentY directly, call
positionViewAtBeginning(), or scroll using a ScrollBar. In that
case, there will be no existing rows to rely on, since
they have all been moved out of the viewport. Instead the
error prone fallback calculation will be used.
This patch will therefore adjust the fallback calculation to
take all the necessary information into account, so that
rowAtPos() returns the right position of a row, even when no
rows are available as a reference. This will fix at least
two bugs that happen because row 0 actually starts at a
negative contentY, rather than at contentY == 0.
Fixes: QTBUG-91461
Fixes: QTBUG-92868
Change-Id: I21be6846809ddedf3dba0c3212693e8063411166
Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
(cherry picked from commit d0d6f70c91b1463e9f5b7a25d4e391cffb4fa5af)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
Diffstat (limited to 'src/quick/items/qquickgridview.cpp')
-rw-r--r-- | src/quick/items/qquickgridview.cpp | 22 |
1 files changed, 20 insertions, 2 deletions
diff --git a/src/quick/items/qquickgridview.cpp b/src/quick/items/qquickgridview.cpp index 7be2a7cb1f..5c4e4d7018 100644 --- a/src/quick/items/qquickgridview.cpp +++ b/src/quick/items/qquickgridview.cpp @@ -349,9 +349,27 @@ qreal QQuickGridViewPrivate::rowPosAt(int modelIndex) const return lastItem->rowPos() + rows * rowSize(); } } - return (modelIndex / columns) * rowSize(); -} + qreal rowPos = ((modelIndex / columns) * rowSize()); + + if (flow == QQuickGridView::FlowLeftToRight && verticalLayoutDirection == QQuickItemView::TopToBottom) { + // Add the effective startpos of row 0. Start by subtracting minExtent, which will contain the + // height of the rows outside the beginning of the content item. (Rows can end up outside if + // e.g flicking the viewport a long way down, changing cellSize, and then flick back). + // NOTE: It's not clearly understood why the flow == QQuickGridView::FlowLeftToRight guard is + // needed, since the flow shouldn't normally affect the y postition of an index. But without + // it, several auto tests start failing, so we keep it until this part is better understood. + rowPos -= minExtent; + // minExtent will also contain the size of the topMargin (vData.startMargin), the header, and + // the highlightRangeStart. Those should be added before the start of row 0. So we need to subtract + // them from the rowPos. But only the largest of topMargin and highlightRangeStart will need + // to be taken into account, since having a topMargin will also ensure that currentItem ends + // up within the requested highlight range when view is positioned at the beginning. + rowPos += qMax(vData.startMargin, highlightRangeStart) + headerSize(); + } + + return rowPos; +} qreal QQuickGridViewPrivate::snapPosAt(qreal pos) const { |