Don't adjust the position of transitioning list items.
authorJan Arve Saether <jan-arve.saether@digia.com>
Fri, 2 May 2014 13:46:12 +0000 (15:46 +0200)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Wed, 14 May 2014 19:27:54 +0000 (21:27 +0200)
Adjusting the position of list items only makes sense for items that
belongs to the layout.

Task-number: QTBUG-38229
Change-Id: I7a05f7a3591620cce3cd9ab84cfecbe325e5e93c
Reviewed-by: Bea Lam <bea.lam@jollamobile.com>
src/quick/items/qquicklistview.cpp
tests/auto/quick/qquicklistview/data/sizeTransitions.qml [new file with mode: 0644]
tests/auto/quick/qquicklistview/tst_qquicklistview.cpp

index 8f9dbb5..e29e9d3 100644 (file)
@@ -1378,6 +1378,8 @@ void QQuickListViewPrivate::itemGeometryChanged(QQuickItem *item, const QRectF &
             // position all subsequent items
             if (visibleItems.count() && item == visibleItems.first()->item) {
                 FxListItemSG *listItem = static_cast<FxListItemSG*>(visibleItems.first());
+                if (listItem->transitionScheduledOrRunning())
+                    return;
                 if (orient == QQuickListView::Vertical) {
                     const qreal oldItemEndPosition = verticalLayoutDirection == QQuickItemView::BottomToTop ? -oldGeometry.y() : oldGeometry.y() + oldGeometry.height();
                     qreal diff = newGeometry.height() - oldGeometry.height();
diff --git a/tests/auto/quick/qquicklistview/data/sizeTransitions.qml b/tests/auto/quick/qquicklistview/data/sizeTransitions.qml
new file mode 100644 (file)
index 0000000..6dfc5ee
--- /dev/null
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+**   * Redistributions of source code must retain the above copyright
+**     notice, this list of conditions and the following disclaimer.
+**   * Redistributions in binary form must reproduce the above copyright
+**     notice, this list of conditions and the following disclaimer in
+**     the documentation and/or other materials provided with the
+**     distribution.
+**   * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
+**     of its contributors may be used to endorse or promote products derived
+**     from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.2
+import QtQuick.Window 2.1
+
+Rectangle {
+    id: root
+    width: 500
+    height: 600
+    property int animationDuration: 10
+    property int itemHeight: 40
+
+    Rectangle {
+        id: sightingsListPanel
+        border.width: 2
+        border.color: "lightgray"
+        y: 200
+        anchors.fill: parent
+        anchors.topMargin: 200
+        anchors.leftMargin: 200
+        ListView {
+            id: list
+            objectName: "list"
+            orientation: topToBottom ? ListView.Vertical : ListView.Horizontal
+            property bool transitionFinished: false
+            property bool scriptActionExecuted : false
+            anchors { fill: parent; margins: parent.border.width; }
+            model: testModel
+            delegate: listDelegate
+            // clip when we have no animation running
+            clip: false
+            add: Transition {
+                id: trans
+                onRunningChanged: {
+                    if (!running)
+                        list.transitionFinished = true;
+                }
+                SequentialAnimation {
+                    ParallelAnimation {
+                        NumberAnimation { properties: "x"; from: -100; duration: root.animationDuration }
+                        NumberAnimation { properties: "y"; from: -100; duration: root.animationDuration }
+                        NumberAnimation { properties: "width"; from: 1; to: list.width; duration: root.animationDuration;}
+                        // Commenting out the height animation and it works
+                        NumberAnimation { properties: "height"; from: 1; to: root.itemHeight; duration: root.animationDuration }
+                    }
+                    ScriptAction { script: list.scriptActionExecuted = true;}
+                }
+
+            }
+        }
+        // Delegate for defining a template for an item in the list
+        Component {
+            id: listDelegate
+            Rectangle {
+                id: background
+                width: list.width
+                height: root.itemHeight
+                border.width: 2
+                radius: 3
+            }
+        }
+    }
+}
index 29755e3..c7e821d 100644 (file)
@@ -194,6 +194,9 @@ private slots:
 
     void populateTransitions();
     void populateTransitions_data();
+    void sizeTransitions();
+    void sizeTransitions_data();
+
     void addTransitions();
     void addTransitions_data();
     void moveTransitions();
@@ -5795,6 +5798,56 @@ void tst_QQuickListView::populateTransitions_data()
     QTest::newRow("empty to start with, no populate") << false << false << false;
 }
 
+
+/*
+ * Tests if the first visible item is not repositioned if the same item
+ * resized + changes position during a transition. The test does not test the
+ * actual position while it is transitioning (since its timing sensitive), but
+ * rather tests if the transition has reached its target state properly.
+ **/
+void tst_QQuickListView::sizeTransitions()
+{
+    QFETCH(bool, topToBottom);
+    QQuickView *window = getView();
+    QQmlContext *ctxt = window->rootContext();
+    QaimModel model;
+    ctxt->setContextProperty("testModel", &model);
+    ctxt->setContextProperty("topToBottom", topToBottom);
+    TestObject *testObject = new TestObject;
+    ctxt->setContextProperty("testObject", &model);
+    window->setSource(testFileUrl("sizeTransitions.qml"));
+    window->show();
+    QVERIFY(QTest::qWaitForWindowExposed(window));
+
+    QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
+    QTRY_VERIFY(listview != 0);
+    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+
+    // the following will start the transition
+    model.addItem(QLatin1String("Test"), "");
+
+    // This ensures early failure in case of failure (in which case
+    // transitionFinished == true and scriptActionExecuted == false)
+    QTRY_COMPARE(listview->property("scriptActionExecuted").toBool() ||
+                 listview->property("transitionFinished").toBool(), true);
+    QCOMPARE(listview->property("scriptActionExecuted").toBool(), true);
+    QCOMPARE(listview->property("transitionFinished").toBool(), true);
+
+    releaseView(window);
+    delete testObject;
+}
+
+void tst_QQuickListView::sizeTransitions_data()
+{
+    QTest::addColumn<bool>("topToBottom");
+
+    QTest::newRow("TopToBottom")
+            << true;
+
+    QTest::newRow("LeftToRight")
+            << false;
+}
+
 void tst_QQuickListView::addTransitions()
 {
     QFETCH(int, initialItemCount);