Fix ListView refill() where delegate size == 0
authorBea Lam <bea.lam@nokia.com>
Wed, 3 Aug 2011 05:40:58 +0000 (15:40 +1000)
committerQt by Nokia <qt-info@nokia.com>
Thu, 4 Aug 2011 07:31:25 +0000 (09:31 +0200)
When refilling, if a delegate item is positioned at the start of the
buffer, it should only be removed if its height is > 0. Otherwise
refill() will constantly remove it in removeNonVisibleItems() and
add it again in the next frame in addVisibleItems().

Regression from aa99d4f5cb4f1f512d1db90536752b518dbea449

Task-number: QTBUG-20712
Change-Id: I21d25fde21e0b559a378c9e202ace58947417a4d
Reviewed-on: http://codereview.qt.nokia.com/2541
Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com>
Reviewed-by: Martin Jones <martin.jones@nokia.com>
src/declarative/items/qsglistview.cpp
tests/auto/declarative/qsglistview/tst_qsglistview.cpp

index d9792d1..e162339 100644 (file)
@@ -603,6 +603,8 @@ bool QSGListViewPrivate::removeNonVisibleItems(int bufferFrom, int bufferTo)
     while (visibleItems.count() > 1 && (item = visibleItems.first()) && item->endPosition() <= bufferFrom) {
         if (item->attached->delayRemove())
             break;
+        if (item->size() == 0)
+            break;
 //            qDebug() << "refill: remove first" << visibleIndex << "top end pos" << item->endPosition();
         if (item->index != -1)
             visibleIndex++;
index f4a2384..6f19692 100644 (file)
@@ -121,6 +121,7 @@ private slots:
     void sizeLessThan1();
     void QTBUG_14821();
     void resizeDelegate();
+    void resizeFirstDelegate();
     void QTBUG_16037();
     void indexAt();
     void incrementalModel();
@@ -2717,6 +2718,60 @@ void tst_QSGListView::resizeDelegate()
     delete canvas;
 }
 
+void tst_QSGListView::resizeFirstDelegate()
+{
+    // QTBUG-20712: Content Y jumps constantly if first delegate height == 0
+    // and other delegates have height > 0
+
+    QSGView *canvas = createView();
+    canvas->show();
+
+    // bug only occurs when all items in the model are visible
+    TestModel model;
+    for (int i = 0; i < 10; i++)
+        model.addItem("Item" + QString::number(i), "");
+
+    QDeclarativeContext *ctxt = canvas->rootContext();
+    ctxt->setContextProperty("testModel", &model);
+
+    TestObject *testObject = new TestObject;
+    ctxt->setContextProperty("testObject", testObject);
+
+    canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/listviewtest.qml"));
+    qApp->processEvents();
+
+    QSGListView *listview = findItem<QSGListView>(canvas->rootObject(), "list");
+    QVERIFY(listview != 0);
+
+    QSGItem *contentItem = listview->contentItem();
+    QVERIFY(contentItem != 0);
+
+    QSGItem *item = 0;
+    for (int i = 0; i < model.count(); ++i) {
+        item = findItem<QSGItem>(contentItem, "wrapper", i);
+        QVERIFY(item != 0);
+        QCOMPARE(item->y(), i*20.0);
+    }
+
+    item = findItem<QSGItem>(contentItem, "wrapper", 0);
+    item->setHeight(0);
+
+    // check the content y has not jumped up and down
+    QCOMPARE(listview->contentY(), 0.0);
+    QSignalSpy spy(listview, SIGNAL(contentYChanged()));
+    QTest::qWait(300);
+    QCOMPARE(spy.count(), 0);
+
+    for (int i = 1; i < model.count(); ++i) {
+        item = findItem<QSGItem>(contentItem, "wrapper", i);
+        QVERIFY(item != 0);
+        QTRY_COMPARE(item->y(), (i-1)*20.0);
+    }
+
+    delete testObject;
+    delete canvas;
+}
+
 void tst_QSGListView::QTBUG_16037()
 {
     QSGView *canvas = createView();