Remove events from the revert list.
authorMichael Brasser <michael.brasser@nokia.com>
Mon, 14 Nov 2011 03:40:03 +0000 (13:40 +1000)
committerQt by Nokia <qt-info@nokia.com>
Wed, 16 Nov 2011 02:29:39 +0000 (03:29 +0100)
State change "events" should be removed from the revert
list the same way property changes are.

Task-number: QTBUG-22583
Change-Id: Ia3f4d16ee8855d163a7f6118a0bc1f8492727940
Reviewed-by: Yunqiao Yin <charles.yin@nokia.com>

src/declarative/util/qdeclarativestate.cpp
src/declarative/util/qdeclarativestate_p_p.h
tests/auto/declarative/qdeclarativestates/data/revertListBug.qml [new file with mode: 0644]
tests/auto/declarative/qdeclarativestates/tst_qdeclarativestates.cpp

index 2c039f9..1250c0c 100644 (file)
@@ -303,7 +303,10 @@ void QDeclarativeStatePrivate::complete()
 
     for (int ii = 0; ii < reverting.count(); ++ii) {
         for (int jj = 0; jj < revertList.count(); ++jj) {
-            if (revertList.at(jj).property() == reverting.at(ii)) {
+            const QDeclarativeRevertAction &revert = reverting.at(ii);
+            const QDeclarativeSimpleAction &simple = revertList.at(jj);
+            if ((revert.event && simple.event() == revert.event) ||
+                simple.property() == revert.property) {
                 revertList.removeAt(jj);
                 break;
             }
@@ -685,7 +688,10 @@ void QDeclarativeState::apply(QDeclarativeTransition *trans, QDeclarativeState *
                 a.event->saveCurrentValues();
             applyList << a;
             // Store these special reverts in the reverting list
-            d->reverting << d->revertList.at(ii).property();
+            if (a.event)
+                d->reverting << a.event;
+            else
+                d->reverting << a.property;
         }
     }
     // All the local reverts now become part of the ongoing revertList
index a9c50f4..55aeecd 100644 (file)
@@ -177,6 +177,16 @@ private:
     bool m_reverseEvent;
 };
 
+class QDeclarativeRevertAction
+{
+public:
+    QDeclarativeRevertAction() : event(0) {}
+    QDeclarativeRevertAction(const QDeclarativeProperty &prop) : property(prop), event(0) {}
+    QDeclarativeRevertAction(QDeclarativeActionEvent *e) : event(e) {}
+    QDeclarativeProperty property;
+    QDeclarativeActionEvent *event;
+};
+
 class QDeclarativeStateOperationPrivate : public QObjectPrivate
 {
     Q_DECLARE_PUBLIC(QDeclarativeStateOperation)
@@ -240,7 +250,7 @@ public:
     QDeclarativeTransitionManager transitionManager;
 
     SimpleActionList revertList;
-    QList<QDeclarativeProperty> reverting;
+    QList<QDeclarativeRevertAction> reverting;
     QString extends;
     mutable bool inState;
     QDeclarativeStateGroup *group;
diff --git a/tests/auto/declarative/qdeclarativestates/data/revertListBug.qml b/tests/auto/declarative/qdeclarativestates/data/revertListBug.qml
new file mode 100644 (file)
index 0000000..fbc4bc5
--- /dev/null
@@ -0,0 +1,47 @@
+import QtQuick 2.0
+
+Rectangle {
+    width: 400; height: 400
+
+    property Item targetItem: rect1
+
+    function switchTargetItem() {
+        if (targetItem === rect1)
+            targetItem = rect2;
+        else
+            targetItem = rect1;
+    }
+
+    states: State {
+        name: "reparented"
+        ParentChange {
+            target: targetItem
+            parent: newParent
+            x: 0; y: 0
+        }
+    }
+
+    Item {
+        objectName: "originalParent1"
+        Rectangle {
+            id: rect1; objectName: "rect1"
+            width: 50; height: 50
+            color: "green"
+        }
+    }
+
+    Item {
+        objectName: "originalParent2"
+        Rectangle {
+            id: rect2; objectName: "rect2"
+            x: 50; y: 50
+            width: 50; height: 50
+            color: "green"
+        }
+    }
+
+    Item {
+        id: newParent; objectName: "newParent"
+        x: 200; y: 100
+    }
+}
index 5c9760a..efac99c 100644 (file)
@@ -146,6 +146,7 @@ private slots:
     void editProperties();
     void QTBUG_14830();
     void avoidFastForward();
+    void revertListBug();
 };
 
 void tst_qdeclarativestates::initTestCase()
@@ -1545,6 +1546,48 @@ void tst_qdeclarativestates::avoidFastForward()
     QCOMPARE(rect->property("updateCount").toInt(), 1);
 }
 
+//QTBUG-22583
+void tst_qdeclarativestates::revertListBug()
+{
+    QDeclarativeEngine engine;
+
+    QDeclarativeComponent c(&engine, TESTDATA("revertListBug.qml"));
+    QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+    QVERIFY(rect != 0);
+
+    QQuickRectangle *rect1 = rect->findChild<QQuickRectangle*>("rect1");
+    QQuickRectangle *rect2 = rect->findChild<QQuickRectangle*>("rect2");
+    QQuickItem *origParent1 = rect->findChild<QQuickItem*>("originalParent1");
+    QQuickItem *origParent2 = rect->findChild<QQuickItem*>("originalParent2");
+    QQuickItem *newParent = rect->findChild<QQuickItem*>("newParent");
+
+    QCOMPARE(rect1->parentItem(), origParent1);
+    QCOMPARE(rect2->parentItem(), origParent2);
+
+    QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
+    rectPrivate->setState("reparented");
+
+    QCOMPARE(rect1->parentItem(), newParent);
+    QCOMPARE(rect2->parentItem(), origParent2);
+
+    rectPrivate->setState("");
+
+    QCOMPARE(rect1->parentItem(), origParent1);
+    QCOMPARE(rect2->parentItem(), origParent2);
+
+    QMetaObject::invokeMethod(rect, "switchTargetItem");
+
+    rectPrivate->setState("reparented");
+
+    QCOMPARE(rect1->parentItem(), origParent1);
+    QCOMPARE(rect2->parentItem(), newParent);
+
+    rectPrivate->setState("");
+
+    QCOMPARE(rect1->parentItem(), origParent1);
+    QCOMPARE(rect2->parentItem(), origParent2); //QTBUG-22583 causes rect2's parent item to be origParent1
+}
+
 QTEST_MAIN(tst_qdeclarativestates)
 
 #include "tst_qdeclarativestates.moc"