aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/items/qquickgridview.cpp
diff options
context:
space:
mode:
authorRichard Moe Gustavsen <richard.gustavsen@qt.io>2022-05-06 15:05:59 +0200
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2022-05-10 16:41:00 +0000
commitc8ec32c64c6867826d4555ed1f561ae52a574322 (patch)
tree50dfaa4e781045f6a74664645bd38b15a4c9c92b /src/quick/items/qquickgridview.cpp
parenta46d508ef00180244ce1f4d9364217336f8b8326 (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.cpp22
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
{