diff options
author | Andrew den Exter <andrew.den-exter@nokia.com> | 2012-06-14 15:11:54 +1000 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2012-06-22 12:47:31 +0200 |
commit | 530b773dfcd2dddeb824cb2a2c7fe1778e5c7985 (patch) | |
tree | 6f129e793fb1faa095d19812eff9f2a3834a69c3 /tests/auto/quick/qquicklistview/tst_qquicklistview.cpp | |
parent | 9e686c502be0b68f39836f29027a58466cb517b7 (diff) |
Fix crash when dragging items outside visible area.
If asynchronous item creation finishes while the content area of a
ListView has been dragged full outside the visible area a full refill
is triggered which can overwrite the requested index and potentially
result in a single delegate item being assigned to multiple view items
and later being doubly released. Only create the view item object in
the createItem function to prevent this from happening.
Secondly only reset the visible items if jumping outside the buffer
range rather than just the fill range to prevent churn when the list
only contains buffered items.
Task-number: QTBUG-26232
Change-Id: I5bce845898ef5f699f34afc268594ef38e01d6a3
Reviewed-by: Martin Jones <martin.jones@nokia.com>
Diffstat (limited to 'tests/auto/quick/qquicklistview/tst_qquicklistview.cpp')
-rw-r--r-- | tests/auto/quick/qquicklistview/tst_qquicklistview.cpp | 76 |
1 files changed, 58 insertions, 18 deletions
diff --git a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp index ca2fcf2972..92526a0c40 100644 --- a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp +++ b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp @@ -141,6 +141,8 @@ private slots: void qAbstractItemModel_sections(); void sectionsPositioning(); void sectionsDelegate(); + void sectionsDragOutsideBounds_data(); + void sectionsDragOutsideBounds(); void sectionPropertyChange(); void cacheBuffer(); void positionViewAtIndex(); @@ -1939,7 +1941,7 @@ void tst_QQuickListView::sections(const QUrl &source) int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count(); for (int i = 0; i < model.count() && i < itemCount; ++i) { QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i); - QTRY_VERIFY(item); + QVERIFY(item); QTRY_COMPARE(item->y(), qreal(i*20 + ((i+4)/5) * 20)); QQuickText *next = findItem<QQuickText>(item, "nextSection"); QCOMPARE(next->text().toInt(), (i+1)/5); @@ -2109,29 +2111,67 @@ void tst_QQuickListView::sectionsDelegate() QTRY_COMPARE(item->y(), qreal(i*20*4)); } + delete canvas; +} + +void tst_QQuickListView::sectionsDragOutsideBounds_data() +{ + QTest::addColumn<int>("distance"); + QTest::addColumn<int>("cacheBuffer"); + + QTest::newRow("500, no cache buffer") << 500 << 0; + QTest::newRow("1000, no cache buffer") << 1000 << 0; + QTest::newRow("500, cache buffer") << 500 << 320; + QTest::newRow("1000, cache buffer") << 1000 << 320; +} + +void tst_QQuickListView::sectionsDragOutsideBounds() +{ + QFETCH(int, distance); + QFETCH(int, cacheBuffer); + + QQuickView *canvas = getView(); + + QmlListModel model; + for (int i = 0; i < 10; i++) + model.addItem("Item" + QString::number(i), QString::number(i/5)); + + QQmlContext *ctxt = canvas->rootContext(); + ctxt->setContextProperty("testModel", &model); + + canvas->setSource(testFileUrl("listview-sections_delegate.qml")); + canvas->show(); + qApp->processEvents(); + + QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list"); + QTRY_VERIFY(listview != 0); + listview->setCacheBuffer(cacheBuffer); + + QQuickItem *contentItem = listview->contentItem(); + QTRY_VERIFY(contentItem != 0); + + QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false); + // QTBUG-17769 - model.removeItems(10, 20); - // ensure view has settled. - QTRY_COMPARE(findItems<QQuickItem>(contentItem, "wrapper").count(), 10); // Drag view up beyond bounds QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(20,20)); - { - QMouseEvent mv(QEvent::MouseMove, QPoint(20,0), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); - QGuiApplication::sendEvent(canvas, &mv); - } - { - QMouseEvent mv(QEvent::MouseMove, QPoint(20,-50), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); - QGuiApplication::sendEvent(canvas, &mv); - } - { - QMouseEvent mv(QEvent::MouseMove, QPoint(20,-200), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); - QGuiApplication::sendEvent(canvas, &mv); - } - QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(20,-200)); + QTest::mouseMove(canvas, QPoint(20,0)); + QTest::mouseMove(canvas, QPoint(20,-50)); + QTest::mouseMove(canvas, QPoint(20,-distance)); + QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(20,-distance)); // view should settle back at 0 QTRY_COMPARE(listview->contentY(), 0.0); - delete canvas; + QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(20,0)); + QTest::mouseMove(canvas, QPoint(20,20)); + QTest::mouseMove(canvas, QPoint(20,70)); + QTest::mouseMove(canvas, QPoint(20,distance)); + + QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(20,distance)); + // view should settle back at 0 + QTRY_COMPARE(listview->contentY(), 0.0); + + releaseView(canvas); } void tst_QQuickListView::sectionsPositioning() |