From 52187b084491641ef80536c743c2261af8bfe11c Mon Sep 17 00:00:00 2001
From: Martin Jones <martin.jones@nokia.com>
Date: Wed, 13 Apr 2011 16:34:06 +1000
Subject: Moving contentY by large values in List/GridView is slow

We needed to create/destroy every delegate between the current position
and the new position.  Now we estimate element at the new position and
just create the elements from that item.

Change-Id: I9da1354cbadb4e44fafc1a0bee619d058d1e06a2
Task-number: QTBUG-14974
Reviewed-by: Bea Lam
---
 .../graphicsitems/qdeclarativegridview.cpp         | 20 ++++++++
 .../graphicsitems/qdeclarativelistview.cpp         | 22 +++++++++
 .../tst_qdeclarativegridview.cpp                   | 51 ++++++++++++++++++++
 .../tst_qdeclarativelistview.cpp                   | 56 ++++++++++++++++++++++
 4 files changed, 149 insertions(+)

diff --git a/src/declarative/graphicsitems/qdeclarativegridview.cpp b/src/declarative/graphicsitems/qdeclarativegridview.cpp
index 3ec29c1..21bfc59 100644
--- a/src/declarative/graphicsitems/qdeclarativegridview.cpp
+++ b/src/declarative/graphicsitems/qdeclarativegridview.cpp
@@ -584,6 +584,26 @@ void QDeclarativeGridViewPrivate::refill(qreal from, qreal to, bool doBuffer)
             --i;
         modelIndex = visibleItems.at(i)->index + 1;
     }
+
+    if (visibleItems.count() && (fillFrom > rowPos + rowSize()*2
+        || fillTo < rowPosAt(visibleIndex) - rowSize())) {
+        // We've jumped more than a page.  Estimate which items are now
+        // visible and fill from there.
+        int count = (fillFrom - (rowPos + rowSize())) / (rowSize()) * columns;
+        for (int i = 0; i < visibleItems.count(); ++i)
+            releaseItem(visibleItems.at(i));
+        visibleItems.clear();
+        modelIndex += count;
+        if (modelIndex >= model->count())
+            modelIndex = model->count() - 1;
+        else if (modelIndex < 0)
+            modelIndex = 0;
+        modelIndex = modelIndex / columns * columns;
+        visibleIndex = modelIndex;
+        colPos = colPosAt(visibleIndex);
+        rowPos = rowPosAt(visibleIndex);
+    }
+
     int colNum = colPos / colSize();
 
     FxGridItem *item = 0;
diff --git a/src/declarative/graphicsitems/qdeclarativelistview.cpp b/src/declarative/graphicsitems/qdeclarativelistview.cpp
index cb751f6..7c01293 100644
--- a/src/declarative/graphicsitems/qdeclarativelistview.cpp
+++ b/src/declarative/graphicsitems/qdeclarativelistview.cpp
@@ -744,6 +744,28 @@ void QDeclarativeListViewPrivate::refill(qreal from, qreal to, bool doBuffer)
         if (visibleItems.at(i)->index != -1)
             modelIndex = visibleItems.at(i)->index + 1;
     }
+
+    if (visibleItems.count() && (fillFrom > itemEnd+averageSize+spacing
+        || fillTo < visiblePos - averageSize - spacing)) {
+        // We've jumped more than a page.  Estimate which items are now
+        // visible and fill from there.
+        int count = (fillFrom - itemEnd) / (averageSize + spacing);
+        for (int i = 0; i < visibleItems.count(); ++i)
+            releaseItem(visibleItems.at(i));
+        visibleItems.clear();
+        modelIndex += count;
+        if (modelIndex >= model->count()) {
+            count -= modelIndex - model->count() + 1;
+            modelIndex = model->count() - 1;
+        } else if (modelIndex < 0) {
+            count -= modelIndex;
+            modelIndex = 0;
+        }
+        visibleIndex = modelIndex;
+        visiblePos = itemEnd + count * (averageSize + spacing) + 1;
+        itemEnd = visiblePos-1;
+    }
+
     bool changed = false;
     FxListItem *item = 0;
     qreal pos = itemEnd + 1;
diff --git a/tests/auto/declarative/qdeclarativegridview/tst_qdeclarativegridview.cpp b/tests/auto/declarative/qdeclarativegridview/tst_qdeclarativegridview.cpp
index c183934..c8e7817 100644
--- a/tests/auto/declarative/qdeclarativegridview/tst_qdeclarativegridview.cpp
+++ b/tests/auto/declarative/qdeclarativegridview/tst_qdeclarativegridview.cpp
@@ -97,6 +97,7 @@ private slots:
     void onRemove_data();
     void testQtQuick11Attributes();
     void testQtQuick11Attributes_data();
+    void contentPosJump();
 
 private:
     QDeclarativeView *createView();
@@ -2077,6 +2078,56 @@ void tst_QDeclarativeGridView::testQtQuick11Attributes_data()
         << "";
 }
 
+void tst_QDeclarativeGridView::contentPosJump()
+{
+    QDeclarativeView *canvas = createView();
+
+    TestModel model;
+    for (int i = 0; i < 100; i++)
+        model.addItem("Item" + QString::number(i), "");
+
+    QDeclarativeContext *ctxt = canvas->rootContext();
+    ctxt->setContextProperty("testModel", &model);
+    ctxt->setContextProperty("testRightToLeft", QVariant(false));
+    ctxt->setContextProperty("testTopToBottom", QVariant(false));
+
+    canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/gridview1.qml"));
+    qApp->processEvents();
+
+    QDeclarativeGridView *gridview = findItem<QDeclarativeGridView>(canvas->rootObject(), "grid");
+    QVERIFY(gridview != 0);
+
+    QDeclarativeItem *contentItem = gridview->contentItem();
+    QVERIFY(contentItem != 0);
+
+    // Test jumping more than a page of items.
+    gridview->setContentY(500);
+
+    // Confirm items positioned correctly
+    int itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
+    for (int i = 24; i < model.count() && i < itemCount; ++i) {
+        QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
+        if (!item) qWarning() << "Item" << i << "not found";
+        QVERIFY(item);
+        QVERIFY(item->x() == (i%3)*80);
+        QVERIFY(item->y() == (i/3)*60);
+    }
+
+    gridview->setContentY(-100);
+    itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
+    QVERIFY(itemCount < 15);
+    // Confirm items positioned correctly
+    for (int i = 0; i < model.count() && i < itemCount; ++i) {
+        QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
+        if (!item) qWarning() << "Item" << i << "not found";
+        QVERIFY(item);
+        QVERIFY(item->x() == (i%3)*80);
+        QVERIFY(item->y() == (i/3)*60);
+    }
+
+    delete canvas;
+}
+
 QDeclarativeView *tst_QDeclarativeGridView::createView()
 {
     QDeclarativeView *canvas = new QDeclarativeView(0);
diff --git a/tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp b/tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp
index ec60e8a..0c96587 100644
--- a/tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp
+++ b/tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp
@@ -120,6 +120,7 @@ private slots:
     void rightToLeft();
     void test_mirroring();
     void orientationChange();
+    void contentPosJump();
 
 private:
     template <class T> void items();
@@ -2630,6 +2631,61 @@ void tst_QDeclarativeListView::orientationChange()
     delete canvas;
 }
 
+void tst_QDeclarativeListView::contentPosJump()
+{
+    QDeclarativeView *canvas = createView();
+
+    TestModel model;
+    for (int i = 0; i < 50; 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();
+
+    QDeclarativeListView *listview = findItem<QDeclarativeListView>(canvas->rootObject(), "list");
+    QTRY_VERIFY(listview != 0);
+
+    QDeclarativeItem *contentItem = listview->contentItem();
+    QTRY_VERIFY(contentItem != 0);
+
+    // Confirm items positioned correctly
+    int itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
+    for (int i = 0; i < model.count() && i < itemCount; ++i) {
+        QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
+        if (!item) qWarning() << "Item" << i << "not found";
+        QTRY_VERIFY(item);
+        QTRY_VERIFY(item->y() == i*20);
+    }
+
+    // Test jumping more than a page of items.
+    listview->setContentY(500);
+    itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
+    for (int i = 25; i < model.count() && i < itemCount; ++i) {
+        QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
+        if (!item) qWarning() << "Item" << i << "not found";
+        QTRY_VERIFY(item);
+        QTRY_VERIFY(item->y() == i*20);
+    }
+
+    listview->setContentY(-100);
+    itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
+    QVERIFY(itemCount < 20);
+    for (int i = 0; i < model.count() && i < itemCount; ++i) {
+        QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
+        if (!item) qWarning() << "Item" << i << "not found";
+        QTRY_VERIFY(item);
+        QTRY_VERIFY(item->y() == i*20);
+    }
+
+    delete canvas;
+}
+
 void tst_QDeclarativeListView::qListModelInterface_items()
 {
     items<TestModel>();
-- 
cgit v0.12


From f6505f9f2eb4c594d3a249655879117e2a136468 Mon Sep 17 00:00:00 2001
From: Martin Jones <martin.jones@nokia.com>
Date: Thu, 14 Apr 2011 11:06:39 +1000
Subject: Add pincharea.qmlproject file for PinchArea example.

Change-Id: I9d3129be4d03904805e53489c1117104e08ce860
---
 .../touchinteraction/pincharea/pincharea.qmlproject    | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)
 create mode 100644 examples/declarative/touchinteraction/pincharea/pincharea.qmlproject

diff --git a/examples/declarative/touchinteraction/pincharea/pincharea.qmlproject b/examples/declarative/touchinteraction/pincharea/pincharea.qmlproject
new file mode 100644
index 0000000..e526217
--- /dev/null
+++ b/examples/declarative/touchinteraction/pincharea/pincharea.qmlproject
@@ -0,0 +1,18 @@
+/* File generated by QtCreator */
+
+import QmlProject 1.0
+
+Project {
+    /* Include .qml, .js, and image files from current directory and subdirectories */
+    QmlFiles {
+        directory: "."
+    }
+    JavaScriptFiles {
+        directory: "."
+    }
+    ImageFiles {
+        directory: "."
+    }
+    /* List of plugin directories passed to QML runtime */
+    // importPaths: [ " ../exampleplugin " ]
+}
-- 
cgit v0.12