From ddeae91ab54bb92b813304778ab8dc4037937274 Mon Sep 17 00:00:00 2001
From: Martin Jones <martin.jones@nokia.com>
Date: Wed, 8 Dec 2010 16:22:04 +1000
Subject: ListView: Fix calculation of currentItem position when out of view.

The calculation of position of currentItem when it is out of the
visible area was bogus.

Task-number: QTBUG-15525
Reviewed-by: Bea Lam
---
 .../graphicsitems/qdeclarativelistview.cpp         | 12 ++-
 .../qdeclarativelistview/data/displaylist.qml      |  9 ++-
 .../tst_qdeclarativelistview.cpp                   | 86 ++++++++++++++++++++++
 3 files changed, 102 insertions(+), 5 deletions(-)

diff --git a/src/declarative/graphicsitems/qdeclarativelistview.cpp b/src/declarative/graphicsitems/qdeclarativelistview.cpp
index 845da79..2dfee3b 100644
--- a/src/declarative/graphicsitems/qdeclarativelistview.cpp
+++ b/src/declarative/graphicsitems/qdeclarativelistview.cpp
@@ -739,16 +739,20 @@ void QDeclarativeListViewPrivate::layout()
         return;
     }
     if (!visibleItems.isEmpty()) {
-        qreal oldEnd = visibleItems.last()->endPosition();
+        bool fixedCurrent = currentItem && visibleItems.first()->item == currentItem->item;
+        qreal sum = visibleItems.first()->size();
         qreal pos = visibleItems.first()->position() + visibleItems.first()->size() + spacing;
         for (int i=1; i < visibleItems.count(); ++i) {
             FxListItem *item = visibleItems.at(i);
             item->setPosition(pos);
             pos += item->size() + spacing;
+            sum += item->size();
+            fixedCurrent = fixedCurrent || (currentItem && item->item == currentItem->item);
         }
-        // move current item if it is after the visible items.
-        if (currentItem && currentIndex > lastVisibleIndex())
-            currentItem->setPosition(currentItem->position() + (visibleItems.last()->endPosition() - oldEnd));
+        averageSize = qRound(sum / visibleItems.count());
+        // move current item if it is not a visible item.
+        if (currentIndex >= 0 && currentItem && !fixedCurrent)
+            currentItem->setPosition(positionAt(currentIndex));
     }
     q->refill();
     minExtentDirty = true;
diff --git a/tests/auto/declarative/qdeclarativelistview/data/displaylist.qml b/tests/auto/declarative/qdeclarativelistview/data/displaylist.qml
index 487b70e..9d58530 100644
--- a/tests/auto/declarative/qdeclarativelistview/data/displaylist.qml
+++ b/tests/auto/declarative/qdeclarativelistview/data/displaylist.qml
@@ -1,6 +1,8 @@
 import QtQuick 1.0
 
 Rectangle {
+    id: root
+    property real delegateHeight: 20
     width: 240
     height: 320
     color: "#ffffff"
@@ -10,7 +12,8 @@ Rectangle {
             Rectangle {
                 id: wrapper
                 objectName: "wrapper"
-                height: 20
+                height: root.delegateHeight
+                Behavior on height { NumberAnimation {} }
                 width: 240
                 Text {
                     text: index
@@ -20,6 +23,10 @@ Rectangle {
                     objectName: "displayText"
                     text: display
                 }
+                Text {
+                    x: 200
+                    text: wrapper.y
+                }
                 color: ListView.isCurrentItem ? "lightsteelblue" : "white"
             }
         },
diff --git a/tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp b/tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp
index 759caf2..22ebb1a 100644
--- a/tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp
+++ b/tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp
@@ -103,6 +103,7 @@ private slots:
     void resizeView();
     void sizeLessThan1();
     void QTBUG_14821();
+    void resizeDelegate();
 
 private:
     template <class T> void items();
@@ -1406,6 +1407,8 @@ void tst_QDeclarativeListView::resetModel()
         QTRY_VERIFY(display != 0);
         QTRY_COMPARE(display->text(), strings.at(i));
     }
+
+    delete canvas;
 }
 
 void tst_QDeclarativeListView::propertyChanges()
@@ -1613,6 +1616,8 @@ void tst_QDeclarativeListView::manualHighlight()
     QTRY_COMPARE(listview->currentIndex(), 2);
     QTRY_COMPARE(listview->currentItem(), findItem<QDeclarativeItem>(contentItem, "wrapper", 2));
     QTRY_COMPARE(listview->highlightItem()->y(), listview->currentItem()->y());
+
+    delete canvas;
 }
 
 void tst_QDeclarativeListView::QTBUG_11105()
@@ -1752,6 +1757,8 @@ void tst_QDeclarativeListView::footer()
 
     model.clear();
     QTRY_COMPARE(footer->y(), 0.0);
+
+    delete canvas;
 }
 
 void tst_QDeclarativeListView::resizeView()
@@ -1794,6 +1801,8 @@ void tst_QDeclarativeListView::resizeView()
 
     QMetaObject::invokeMethod(canvas->rootObject(), "heightRatio", Q_RETURN_ARG(QVariant, heightRatio));
     QCOMPARE(heightRatio.toReal(), 0.25);
+
+    delete canvas;
 }
 
 void tst_QDeclarativeListView::sizeLessThan1()
@@ -1849,6 +1858,83 @@ void tst_QDeclarativeListView::QTBUG_14821()
 
     listview->incrementCurrentIndex();
     QCOMPARE(listview->currentIndex(), 0);
+
+    delete canvas;
+}
+
+void tst_QDeclarativeListView::resizeDelegate()
+{
+    QDeclarativeView *canvas = createView();
+
+    QStringList strings;
+    for (int i = 0; i < 30; ++i)
+        strings << QString::number(i);
+    QStringListModel model(strings);
+
+    QDeclarativeContext *ctxt = canvas->rootContext();
+    ctxt->setContextProperty("testModel", &model);
+
+    canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/displaylist.qml"));
+    qApp->processEvents();
+
+    QDeclarativeListView *listview = findItem<QDeclarativeListView>(canvas->rootObject(), "list");
+    QTRY_VERIFY(listview != 0);
+
+    QDeclarativeItem *contentItem = listview->contentItem();
+    QTRY_VERIFY(contentItem != 0);
+
+    QTRY_COMPARE(listview->count(), model.rowCount());
+
+    listview->setCurrentIndex(25);
+    listview->setContentY(0);
+
+    for (int i = 0; i < 16; ++i) {
+        QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
+        QVERIFY(item != 0);
+        QCOMPARE(item->y(), i*20.0);
+    }
+
+    QCOMPARE(listview->currentItem()->y(), 500.0);
+    QTRY_COMPARE(listview->highlightItem()->y(), 500.0);
+
+    canvas->rootObject()->setProperty("delegateHeight", 30);
+    qApp->processEvents();
+
+    for (int i = 0; i < 11; ++i) {
+        QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
+        QVERIFY(item != 0);
+        QTRY_COMPARE(item->y(), i*30.0);
+    }
+
+    QTRY_COMPARE(listview->currentItem()->y(), 750.0);
+    QTRY_COMPARE(listview->highlightItem()->y(), 750.0);
+
+    listview->setCurrentIndex(1);
+    listview->positionViewAtIndex(25, QDeclarativeListView::Beginning);
+    listview->positionViewAtIndex(5, QDeclarativeListView::Beginning);
+
+    for (int i = 5; i < 16; ++i) {
+        QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
+        QVERIFY(item != 0);
+        QCOMPARE(item->y(), i*30.0);
+    }
+
+    QTRY_COMPARE(listview->currentItem()->y(), 30.0);
+    QTRY_COMPARE(listview->highlightItem()->y(), 30.0);
+
+    canvas->rootObject()->setProperty("delegateHeight", 20);
+    qApp->processEvents();
+
+    for (int i = 5; i < 11; ++i) {
+        QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
+        QVERIFY(item != 0);
+        QTRY_COMPARE(item->y(), 150 + (i-5)*20.0);
+    }
+
+    QTRY_COMPARE(listview->currentItem()->y(), 70.0);
+    QTRY_COMPARE(listview->highlightItem()->y(), 70.0);
+
+    delete canvas;
 }
 
 void tst_QDeclarativeListView::qListModelInterface_items()
-- 
cgit v0.12