Fix section delegates not updating when changed.
authorAndrew den Exter <andrew.den-exter@nokia.com>
Tue, 26 Jun 2012 03:13:11 +0000 (13:13 +1000)
committerQt by Nokia <qt-info@nokia.com>
Tue, 26 Jun 2012 06:08:33 +0000 (08:08 +0200)
Delete all allocated section items before doing an update when the
section delegate is changed.

Task-number: QTBUG-24899
Change-Id: I09dc7a1c602a49ad7bb37512a7e5116392259457
Reviewed-by: Martin Jones <martin.jones@nokia.com>
src/quick/items/qquicklistview.cpp
tests/auto/quick/qquicklistview/data/sectiondelegatechange.qml [new file with mode: 0644]
tests/auto/quick/qquicklistview/tst_qquicklistview.cpp

index 062cd58..d67e02e 100644 (file)
@@ -113,6 +113,7 @@ public:
     virtual void updateSections();
     QQuickItem *getSectionItem(const QString &section);
     void releaseSectionItem(QQuickItem *item);
+    void releaseSectionItems();
     void updateInlineSection(FxListItemSG *);
     void updateCurrentSection();
     void updateStickySections();
@@ -209,6 +210,8 @@ void QQuickViewSection::setCriteria(QQuickViewSection::SectionCriteria criteria)
 void QQuickViewSection::setDelegate(QQmlComponent *delegate)
 {
     if (delegate != m_delegate) {
+        if (m_delegate)
+            m_view->releaseSectionItems();
         m_delegate = delegate;
         emit delegateChanged();
         m_view->updateSections();
@@ -980,6 +983,24 @@ void QQuickListViewPrivate::releaseSectionItem(QQuickItem *item)
     delete item;
 }
 
+
+void QQuickListViewPrivate::releaseSectionItems()
+{
+    for (int i = 0; i < visibleItems.count(); ++i) {
+        FxListItemSG *listItem = static_cast<FxListItemSG *>(visibleItems.at(i));
+        if (listItem->section()) {
+            qreal pos = listItem->position();
+            releaseSectionItem(listItem->section());
+            listItem->setSection(0);
+            listItem->setPosition(pos);
+        }
+    }
+    for (int i = 0; i < sectionCacheSize; ++i) {
+        delete sectionCache[i];
+        sectionCache[i] = 0;
+    }
+}
+
 void QQuickListViewPrivate::updateInlineSection(FxListItemSG *listItem)
 {
     if (!sectionCriteria || !sectionCriteria->delegate())
diff --git a/tests/auto/quick/qquicklistview/data/sectiondelegatechange.qml b/tests/auto/quick/qquicklistview/data/sectiondelegatechange.qml
new file mode 100644 (file)
index 0000000..eee15ed
--- /dev/null
@@ -0,0 +1,61 @@
+import QtQuick 2.0
+
+ListView {
+    width: 240
+    height: 320
+
+    function switchDelegates() {
+        section.delegate = section.delegate === delegate1
+                ? delegate2
+                : delegate1
+    }
+
+    Component {
+        id: delegate1
+
+        Rectangle {
+            objectName: "section1"
+            color: "lightsteelblue"
+            border.width: 1;
+            width: 240
+            height: 25
+
+            Text {
+                anchors.centerIn: parent
+                text: section
+            }
+        }
+    }
+    Component {
+        id: delegate2
+
+        Rectangle {
+            objectName: "section2"
+            color: "yellow"
+            border.width: 1;
+            width: 240
+            height: 50
+
+            Text {
+                anchors.centerIn: parent
+                text: section
+            }
+        }
+    }
+
+    section.property: "modelData"
+    section.delegate: delegate1
+
+    model: 20
+    delegate: Rectangle {
+        objectName: "item"
+        border.width: 1
+        width: 240
+        height: 25
+
+        Text {
+            anchors.centerIn: parent
+            text: modelData
+        }
+    }
+}
index c6a7230..848ffb1 100644 (file)
@@ -146,6 +146,7 @@ private slots:
     void sectionsDragOutsideBounds();
     void sectionsDelegate_headerVisibility();
     void sectionPropertyChange();
+    void sectionDelegateChange();
     void cacheBuffer();
     void positionViewAtIndex();
     void resetModel();
@@ -2431,6 +2432,46 @@ void tst_QQuickListView::sectionPropertyChange()
     delete canvas;
 }
 
+void tst_QQuickListView::sectionDelegateChange()
+{
+    QQuickView *canvas = createView();
+
+    canvas->setSource(testFileUrl("sectiondelegatechange.qml"));
+    canvas->show();
+    qApp->processEvents();
+
+    QQuickListView *listview = qobject_cast<QQuickListView *>(canvas->rootObject());
+    QVERIFY(listview != 0);
+
+    QQuickItem *contentItem = listview->contentItem();
+    QVERIFY(contentItem != 0);
+
+    QQUICK_VERIFY_POLISH(listview);
+
+    QVERIFY(findItems<QQuickItem>(contentItem, "section1").count() > 0);
+    QCOMPARE(findItems<QQuickItem>(contentItem, "section2").count(), 0);
+
+    for (int i = 0; i < 3; ++i) {
+        QQuickItem *item = findItem<QQuickItem>(contentItem, "item", i);
+        QTRY_VERIFY(item);
+        QTRY_COMPARE(item->y(), qreal(25. + i*50.));
+    }
+
+    QMetaObject::invokeMethod(canvas->rootObject(), "switchDelegates");
+    QQUICK_VERIFY_POLISH(listview);
+
+    QCOMPARE(findItems<QQuickItem>(contentItem, "section1").count(), 0);
+    QVERIFY(findItems<QQuickItem>(contentItem, "section2").count() > 0);
+
+    for (int i = 0; i < 3; ++i) {
+        QQuickItem *item = findItem<QQuickItem>(contentItem, "item", i);
+        QVERIFY(item);
+        QTRY_COMPARE(item->y(), qreal(50. + i*75.));
+    }
+
+    delete canvas;
+}
+
 void tst_QQuickListView::currentIndex_delayedItemCreation()
 {
     QFETCH(bool, setCurrentToZero);