From 8ab760b70e13318749bcc83e33b9a9b9a849a892 Mon Sep 17 00:00:00 2001
From: Michael Brasser <michael.brasser@nokia.com>
Date: Wed, 15 Sep 2010 10:53:29 +1000
Subject: Restore any absolute geometry changed by AnchorChanges when returning
 to the base state.

Task-number: QTBUG-11834
---
 .../util/qdeclarativestateoperations.cpp           | 54 ++++++++++++++++++++++
 .../qdeclarativestates/data/anchorRewindBug2.qml   | 25 ++++++++++
 .../qdeclarativestates/tst_qdeclarativestates.cpp  | 27 +++++++++++
 3 files changed, 106 insertions(+)
 create mode 100644 tests/auto/declarative/qdeclarativestates/data/anchorRewindBug2.qml

diff --git a/src/declarative/util/qdeclarativestateoperations.cpp b/src/declarative/util/qdeclarativestateoperations.cpp
index ccbc4cd..8cb813c 100644
--- a/src/declarative/util/qdeclarativestateoperations.cpp
+++ b/src/declarative/util/qdeclarativestateoperations.cpp
@@ -1031,6 +1031,11 @@ public:
     bool applyOrigVCenter;
     bool applyOrigBaseline;
 
+    QDeclarativeNullableValue<qreal> origWidth;
+    QDeclarativeNullableValue<qreal> origHeight;
+    qreal origX;
+    qreal origY;
+
     QList<QDeclarativeAbstractBinding*> oldBindings;
 
     QDeclarativeProperty leftProp;
@@ -1322,6 +1327,42 @@ void QDeclarativeAnchorChanges::reverse(Reason reason)
         QDeclarativePropertyPrivate::setBinding(d->vCenterProp, d->origVCenterBinding);
     if (d->origBaselineBinding)
         QDeclarativePropertyPrivate::setBinding(d->baselineProp, d->origBaselineBinding);
+
+    //restore any absolute geometry changed by the state's anchors
+    QDeclarativeAnchors::Anchors stateVAnchors = d->anchorSet->d_func()->usedAnchors & QDeclarativeAnchors::Vertical_Mask;
+    QDeclarativeAnchors::Anchors origVAnchors = targetPrivate->anchors()->usedAnchors() & QDeclarativeAnchors::Vertical_Mask;
+    QDeclarativeAnchors::Anchors stateHAnchors = d->anchorSet->d_func()->usedAnchors & QDeclarativeAnchors::Horizontal_Mask;
+    QDeclarativeAnchors::Anchors origHAnchors = targetPrivate->anchors()->usedAnchors() & QDeclarativeAnchors::Horizontal_Mask;
+
+    bool stateSetWidth = (stateHAnchors &&
+                          stateHAnchors != QDeclarativeAnchors::LeftAnchor &&
+                          stateHAnchors != QDeclarativeAnchors::RightAnchor &&
+                          stateHAnchors != QDeclarativeAnchors::HCenterAnchor);
+    bool origSetWidth = (origHAnchors &&
+                         origHAnchors != QDeclarativeAnchors::LeftAnchor &&
+                         origHAnchors != QDeclarativeAnchors::RightAnchor &&
+                         origHAnchors != QDeclarativeAnchors::HCenterAnchor);
+    if (d->origWidth.isValid() && stateSetWidth && !origSetWidth)
+        d->target->setWidth(d->origWidth.value);
+
+    bool stateSetHeight = (stateVAnchors &&
+                           stateVAnchors != QDeclarativeAnchors::TopAnchor &&
+                           stateVAnchors != QDeclarativeAnchors::BottomAnchor &&
+                           stateVAnchors != QDeclarativeAnchors::VCenterAnchor &&
+                           stateVAnchors != QDeclarativeAnchors::BaselineAnchor);
+    bool origSetHeight = (origVAnchors &&
+                          origVAnchors != QDeclarativeAnchors::TopAnchor &&
+                          origVAnchors != QDeclarativeAnchors::BottomAnchor &&
+                          origVAnchors != QDeclarativeAnchors::VCenterAnchor &&
+                          origVAnchors != QDeclarativeAnchors::BaselineAnchor);
+    if (d->origHeight.isValid() && stateSetHeight && !origSetHeight)
+        d->target->setHeight(d->origHeight.value);
+
+    if (stateHAnchors && !origHAnchors)
+        d->target->setX(d->origX);
+
+    if (stateVAnchors && !origVAnchors)
+        d->target->setY(d->origY);
 }
 
 QString QDeclarativeAnchorChanges::typeName() const
@@ -1384,6 +1425,14 @@ void QDeclarativeAnchorChanges::saveOriginals()
     d->origVCenterBinding = QDeclarativePropertyPrivate::binding(d->vCenterProp);
     d->origBaselineBinding = QDeclarativePropertyPrivate::binding(d->baselineProp);
 
+    QDeclarativeItemPrivate *targetPrivate = QDeclarativeItemPrivate::get(d->target);
+    if (targetPrivate->widthValid)
+        d->origWidth = d->target->width();
+    if (targetPrivate->heightValid)
+        d->origHeight = d->target->height();
+    d->origX = d->target->x();
+    d->origY = d->target->y();
+
     d->applyOrigLeft = d->applyOrigRight = d->applyOrigHCenter = d->applyOrigTop
       = d->applyOrigBottom = d->applyOrigVCenter = d->applyOrigBaseline = false;
 
@@ -1416,6 +1465,11 @@ void QDeclarativeAnchorChanges::copyOriginals(QDeclarativeActionEvent *other)
     d->origVCenterBinding = acp->origVCenterBinding;
     d->origBaselineBinding = acp->origBaselineBinding;
 
+    d->origWidth = acp->origWidth;
+    d->origHeight = acp->origHeight;
+    d->origX = acp->origX;
+    d->origY = acp->origY;
+
     d->oldBindings.clear();
     d->oldBindings << acp->leftBinding << acp->rightBinding << acp->hCenterBinding
                 << acp->topBinding << acp->bottomBinding << acp->baselineBinding;
diff --git a/tests/auto/declarative/qdeclarativestates/data/anchorRewindBug2.qml b/tests/auto/declarative/qdeclarativestates/data/anchorRewindBug2.qml
new file mode 100644
index 0000000..4ed2815
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativestates/data/anchorRewindBug2.qml
@@ -0,0 +1,25 @@
+import Qt 4.7
+
+Rectangle {
+    id: root
+    width:200; height:300
+
+    Rectangle {
+        id: rectangle
+        objectName: "mover"
+        color: "green"
+        width:50; height:50
+    }
+
+    states: [
+        State {
+            name: "anchored"
+            AnchorChanges {
+                target: rectangle
+                anchors.left: root.left
+                anchors.right: root.right
+                anchors.bottom: root.bottom
+            }
+        }
+    ]
+}
diff --git a/tests/auto/declarative/qdeclarativestates/tst_qdeclarativestates.cpp b/tests/auto/declarative/qdeclarativestates/tst_qdeclarativestates.cpp
index 4a0ae30..f61ecf5 100644
--- a/tests/auto/declarative/qdeclarativestates/tst_qdeclarativestates.cpp
+++ b/tests/auto/declarative/qdeclarativestates/tst_qdeclarativestates.cpp
@@ -123,6 +123,7 @@ private slots:
     void anchorChanges5();
     void anchorChangesCrash();
     void anchorRewindBug();
+    void anchorRewindBug2();
     void script();
     void restoreEntryValues();
     void explicitChanges();
@@ -860,6 +861,32 @@ void tst_qdeclarativestates::anchorRewindBug()
     delete rect;
 }
 
+// QTBUG-11834
+void tst_qdeclarativestates::anchorRewindBug2()
+{
+    QDeclarativeEngine engine;
+
+    QDeclarativeComponent rectComponent(&engine, SRCDIR "/data/anchorRewindBug2.qml");
+    QDeclarativeRectangle *rect = qobject_cast<QDeclarativeRectangle*>(rectComponent.create());
+    QVERIFY(rect != 0);
+
+    QDeclarativeRectangle *mover = rect->findChild<QDeclarativeRectangle*>("mover");
+
+    QVERIFY(mover != 0);
+    QCOMPARE(mover->y(), qreal(0.0));
+    QCOMPARE(mover->width(), qreal(50.0));
+
+    QDeclarativeItemPrivate::get(rect)->setState("anchored");
+    QCOMPARE(mover->y(), qreal(250.0));
+    QCOMPARE(mover->width(), qreal(200.0));
+
+    QDeclarativeItemPrivate::get(rect)->setState("");
+    QCOMPARE(mover->y(), qreal(0.0));
+    QCOMPARE(mover->width(), qreal(50.0));
+
+    delete rect;
+}
+
 void tst_qdeclarativestates::script()
 {
     QDeclarativeEngine engine;
-- 
cgit v0.12