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 /tests/auto/quick | |
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 'tests/auto/quick')
-rw-r--r-- | tests/auto/quick/qquickgridview/data/qtbug91461.qml | 81 | ||||
-rw-r--r-- | tests/auto/quick/qquickgridview/tst_qquickgridview.cpp | 29 |
2 files changed, 110 insertions, 0 deletions
diff --git a/tests/auto/quick/qquickgridview/data/qtbug91461.qml b/tests/auto/quick/qquickgridview/data/qtbug91461.qml new file mode 100644 index 0000000000..50ab04e828 --- /dev/null +++ b/tests/auto/quick/qquickgridview/data/qtbug91461.qml @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +import QtQuick + +Item { + width: 640 + height: 800 + + property real cellSize: 100 + + GridView { + id: grid + anchors.fill: parent + model: 1000 + cellWidth: cellSize + cellHeight: cellSize + cacheBuffer: 0 + currentIndex: 0 + + delegate: Rectangle { + implicitWidth: grid.cellWidth - 10 + implicitHeight: grid.cellHeight - 10 + color: GridView.isCurrentItem ? "green" : "lightgreen" + radius: 5 + border.width: GridView.isCurrentItem ? 3 : 1 + border.color: "black" + + Text { + anchors.centerIn: parent + text: model.index + } + } + } +} diff --git a/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp b/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp index 11840f2391..9532aa546c 100644 --- a/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp +++ b/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp @@ -212,6 +212,7 @@ private slots: void QTBUG_45640(); void QTBUG_49218(); + void positionViewAtBeginningAfterResizingCells(); void QTBUG_48870_fastModelUpdates(); void QTBUG_86255(); void resizeDynamicCellWidthRtL(); @@ -6698,6 +6699,34 @@ void tst_QQuickGridView::QTBUG_49218() delete window; } +void tst_QQuickGridView::positionViewAtBeginningAfterResizingCells() +{ + // Check that positionViewAtBeginning() ends up showing row 0, even + // if the cells are resized while the viewport is deep down in the list (QTBUG-91461). + std::unique_ptr<QQuickView> window(createView()); + window->setSource(testFileUrl("qtbug91461.qml")); + window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window.get())); + + QQuickItem *rootItem = qobject_cast<QQuickItem*>(window->rootObject()); + QQuickGridView *gridview = qobject_cast<QQuickGridView *>(rootItem->childItems().first()); + QVERIFY(gridview != nullptr); + + gridview->positionViewAtEnd(); + QVERIFY(QQuickTest::qWaitForItemPolished(gridview)); + rootItem->setProperty("cellSize", 200); + QVERIFY(QQuickTest::qWaitForItemPolished(gridview)); + gridview->positionViewAtBeginning(); + QVERIFY(QQuickTest::qWaitForItemPolished(gridview)); + + const QPointF topLeftCorner = window->contentItem()->mapToItem(gridview->contentItem(), QPointF(20, 20)); + const auto item0 = gridview->itemAt(topLeftCorner.x(), topLeftCorner.y()); + QVERIFY(item0); + + const int index = qmlContext(item0)->contextProperty("index").toInt(); + QCOMPARE(index, 0); +} + void tst_QQuickGridView::keyNavigationEnabled() { QScopedPointer<QQuickView> window(createView()); |