From 2c80968d21ff15f574cbbfd93ce4409cda7eeebf Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Wed, 23 Jul 2014 19:39:26 -0500 Subject: [PATCH] Improve programmatic flicking of ListView (and Flickable). Fix bug when programmatically flicking ListView after a real flick in the opposite direction. Also ensure a programmatic flick can flick past bounds when situated at the bounds and DragAndOvershootBounds is set. Task-number: QTBUG-38209 Change-Id: If4a2f65d0e7cb620b9af21f8a25a8a8797976125 Reviewed-by: Martin Jones --- src/quick/items/qquickflickable.cpp | 6 ++- .../quick/qquicklistview/data/simplelistview.qml | 11 +++++ .../quick/qquicklistview/tst_qquicklistview.cpp | 55 ++++++++++++++++++++++ 3 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 tests/auto/quick/qquicklistview/data/simplelistview.qml diff --git a/src/quick/items/qquickflickable.cpp b/src/quick/items/qquickflickable.cpp index 45566f2..ee71ea8 100644 --- a/src/quick/items/qquickflickable.cpp +++ b/src/quick/items/qquickflickable.cpp @@ -327,7 +327,7 @@ bool QQuickFlickablePrivate::flick(AxisData &data, qreal minExtent, qreal maxExt maxDistance = qAbs(maxExtent - data.move.value()); data.flickTarget = maxExtent; } - if (maxDistance > 0) { + if (maxDistance > 0 || boundsBehavior == QQuickFlickable::DragAndOvershootBounds) { qreal v = velocity; if (maxVelocity != -1 && maxVelocity < qAbs(v)) { if (v < 0) @@ -1541,6 +1541,10 @@ void QQuickFlickable::geometryChanged(const QRectF &newGeometry, void QQuickFlickable::flick(qreal xVelocity, qreal yVelocity) { Q_D(QQuickFlickable); + d->hData.reset(); + d->vData.reset(); + d->hData.velocity = xVelocity; + d->vData.velocity = yVelocity; bool flickedX = d->flickX(xVelocity); bool flickedY = d->flickY(yVelocity); d->flickingStarted(flickedX, flickedY); diff --git a/tests/auto/quick/qquicklistview/data/simplelistview.qml b/tests/auto/quick/qquicklistview/data/simplelistview.qml new file mode 100644 index 0000000..56a9615 --- /dev/null +++ b/tests/auto/quick/qquicklistview/data/simplelistview.qml @@ -0,0 +1,11 @@ +import QtQuick 2.0 + +ListView { + width: 400 + height: 400 + model: 100 + delegate: Rectangle { + height: 40; width: 400 + color: index % 2 ? "lightsteelblue" : "lightgray" + } +} diff --git a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp index 2093265..14e26b7 100644 --- a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp +++ b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp @@ -228,6 +228,9 @@ private slots: void roundingErrors(); void roundingErrors_data(); + void QTBUG_38209(); + void programmaticFlickAtBounds(); + private: template void items(const QUrl &source); template void changed(const QUrl &source); @@ -7309,6 +7312,58 @@ void tst_QQuickListView::roundingErrors_data() QTest::newRow("pixelAligned=false") << false; } +void tst_QQuickListView::QTBUG_38209() +{ + QScopedPointer window(createView()); + window->setSource(testFileUrl("simplelistview.qml")); + window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window.data())); + + QQuickListView *listview = qobject_cast(window->rootObject()); + QVERIFY(listview); + + // simulate mouse flick + flick(window.data(), QPoint(200, 200), QPoint(200, 50), 100); + QTRY_VERIFY(listview->isMoving() == false); + qreal contentY = listview->contentY(); + + // flick down + listview->flick(0, 1000); + + // ensure we move more than just a couple pixels + QTRY_VERIFY(contentY - listview->contentY() > qreal(100.0)); +} + +void tst_QQuickListView::programmaticFlickAtBounds() +{ + QScopedPointer window(createView()); + window->setSource(testFileUrl("simplelistview.qml")); + window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window.data())); + + QQuickListView *listview = qobject_cast(window->rootObject()); + QVERIFY(listview); + QSignalSpy spy(listview, SIGNAL(contentYChanged())); + + // flick down + listview->flick(0, 1000); + + // verify that there is movement beyond bounds + QVERIFY(spy.wait(100)); + + // reset, and test with StopAtBounds + listview->cancelFlick(); + listview->returnToBounds(); + QTRY_COMPARE(listview->contentY(), qreal(0.0)); + listview->setBoundsBehavior(QQuickFlickable::StopAtBounds); + + // flick down + listview->flick(0, 1000); + + // verify that there is no movement beyond bounds + QVERIFY(!spy.wait(100)); +} + QTEST_MAIN(tst_QQuickListView) #include "tst_qquicklistview.moc" -- 2.7.4