From c5b083b2a256823f4f47fcaa3140d4f79d99029f Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Fri, 4 Sep 2015 13:32:55 +0200 Subject: ListView: Set currentItem's culled state on geometry change When the viewport is moved, the ListView may cull its currentItem if it's out of the viewport bounds. However, it could be that this is only a transient state while the currentItem is being animated. Unfortunately, we don't uncull the currentItem at any moment during the animation. To solve this, we simply set the currentItem's culled state every time its geometry changes. Change-Id: I72d548f13f229029ccd8568721ea23e73f7b4392 Task-number: QTBUG-48044 Reviewed-by: J-P Nurmi --- .../auto/quick/qquicklistview/data/qtbug48044.qml | 144 +++++++++++++++++++++ .../quick/qquicklistview/tst_qquicklistview.cpp | 37 ++++++ 2 files changed, 181 insertions(+) create mode 100644 tests/auto/quick/qquicklistview/data/qtbug48044.qml (limited to 'tests') diff --git a/tests/auto/quick/qquicklistview/data/qtbug48044.qml b/tests/auto/quick/qquicklistview/data/qtbug48044.qml new file mode 100644 index 0000000000..d318643c1c --- /dev/null +++ b/tests/auto/quick/qquicklistview/data/qtbug48044.qml @@ -0,0 +1,144 @@ +import QtQuick 2.0 + +Item { + width: 200 + height: 442 + + ListModel { + id: listModel + ListElement { + name: "h1" + txt: "Header 1" + header: true + collapsed: true + } + ListElement { + name: "h2" + txt: "Header 2" + header: true + collapsed: true + } + ListElement { + name: "h3" + txt: "Header 3" + header: true + collapsed: true + } + + function indexFromName(name) { + for (var i = 0; i < count; i++) + if (get(i).name === name) + return i + + console.warn("Did not find index for name " + name) + return -1 + } + } + + function populateModel(prefix, index, n) { + for (var k = 1; k <= n; k++) { + var name = prefix + k + var data = { + "collapsed": false, + "name": name, + "txt": name, + "header": false + } + listModel.insert(index + k, data) + } + } + + function h2(open) { + var i = listModel.indexFromName("h2") + if (listModel.get(i).collapsed === !open) + return + + listModel.setProperty(i, "collapsed", !open) + + var n = 15 + if (open) { + h3(false) + populateModel("c2_", listModel.indexFromName("h2"), n) + } else { + listModel.remove(i + 1, n) + } + + } + + function h3(open) { + var i = listModel.indexFromName("h3") + if (listModel.get(i).collapsed === !open) + return + + listModel.setProperty(i, "collapsed", !open) + + var n = 6 + if (open) { + h2(false) + populateModel("c3_", listModel.indexFromName("h3"), n) + } else { + listModel.remove(i + 1, n) + } + } + + ListView { + id: listView + width: parent.width + height: parent.height + cacheBuffer: 0 + model: listModel + + property bool transitionsDone: false + property int runningTransitions: 0 + onRunningTransitionsChanged: { + if (runningTransitions === 0) + transitionsDone = true + } + + displaced: Transition { + id: dispTrans + SequentialAnimation { + ScriptAction { + script: listView.runningTransitions++ + } + NumberAnimation { + property: "y"; + duration: 250 + } + ScriptAction { + script: listView.runningTransitions-- + } + } + } + + delegate: Rectangle { + id: rect + color: header ? "yellow" : "cyan" + border.color: "black" + height: 50 + width: parent.width + + Text { + anchors.centerIn: parent + font.pixelSize: 20 + text: txt + } + + MouseArea { + anchors.fill: parent + onClicked: { + listView.currentIndex = index + var i = listModel.indexFromName("h3") + if (i === -1) + return; + var isCollapsed = listModel.get(i).collapsed + if (name === "h2") + h2(isCollapsed) + else if (name === "h3") + h3(isCollapsed) + } + } + } + } +} + diff --git a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp index 8e7f93849c..e02c053208 100644 --- a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp +++ b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp @@ -247,6 +247,8 @@ private slots: void contentHeightWithDelayRemove(); void contentHeightWithDelayRemove_data(); + void QTBUG_48044_currentItemNotVisibleAfterTransition(); + private: template void items(const QUrl &source); template void changed(const QUrl &source); @@ -8231,6 +8233,41 @@ void tst_QQuickListView::contentHeightWithDelayRemove() delete window; } +void tst_QQuickListView::QTBUG_48044_currentItemNotVisibleAfterTransition() +{ + QQuickView *window = createView(); + window->setSource(testFileUrl("qtbug48044.qml")); + window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window)); + + QQuickListView *listview = window->rootObject()->findChild(); + QTRY_VERIFY(listview != 0); + + // Expand 2nd header + listview->setProperty("transitionsDone", QVariant(false)); + QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, QPoint(window->width() / 2, 75)); + QTRY_VERIFY(listview->property("transitionsDone").toBool()); + + // Flick listview to the bottom + flick(window, QPoint(window->width() / 2, 400), QPoint(window->width() / 2, 0), 100); + QTRY_VERIFY(!listview->isMoving()); + + // Expand 3rd header + listview->setProperty("transitionsDone", QVariant(false)); + QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, QPoint(window->width() / 2, window->height() - 25)); + QTRY_VERIFY(listview->property("transitionsDone").toBool()); + + // Check current item is what we expect + QCOMPARE(listview->currentIndex(), 2); + QQuickItem *currentItem = listview->currentItem(); + QVERIFY(currentItem); + QVERIFY(currentItem->isVisible()); + + // This is the actual test + QQuickItemPrivate *currentPriv = QQuickItemPrivate::get(currentItem); + QVERIFY(!currentPriv->culled); +} + QTEST_MAIN(tst_QQuickListView) #include "tst_qquicklistview.moc" -- cgit v1.2.3