From e997f6de135f76b71db51eef38094178a2c5523e Mon Sep 17 00:00:00 2001
From: Erik Verbruggen <erik.verbruggen@nokia.com>
Date: Tue, 25 May 2010 17:00:21 +0200
Subject: [PATCH] Fixed rewriter bug for subsequent reparent-in-out actions.

---
 .../designercore/model/modeltotextmerger.cpp  |  2 +-
 .../designercore/model/rewriteaction.h        | 51 +++++++------
 .../model/rewriteactioncompressor.cpp         | 74 ++++++++++++-------
 .../model/rewriteactioncompressor.h           |  3 +-
 .../qml/qmldesigner/coretests/testcore.cpp    | 67 +++++++++++++++++
 .../auto/qml/qmldesigner/coretests/testcore.h |  2 +-
 .../coretests/testrewriterview.cpp            | 14 ++--
 7 files changed, 153 insertions(+), 60 deletions(-)

diff --git a/src/plugins/qmldesigner/designercore/model/modeltotextmerger.cpp b/src/plugins/qmldesigner/designercore/model/modeltotextmerger.cpp
index c4e10dbce08..85922826928 100644
--- a/src/plugins/qmldesigner/designercore/model/modeltotextmerger.cpp
+++ b/src/plugins/qmldesigner/designercore/model/modeltotextmerger.cpp
@@ -149,7 +149,7 @@ void ModelToTextMerger::removeImport(const Import &import)
 void ModelToTextMerger::nodeReparented(const ModelNode &node, const NodeAbstractProperty &newPropertyParent, const NodeAbstractProperty &oldPropertyParent, AbstractView::PropertyChangeFlags propertyChange)
 {
     if (isInHierarchy(oldPropertyParent) && isInHierarchy(newPropertyParent)) { // the node is moved
-        schedule(new ReparentNodeRewriteAction(node, newPropertyParent, propertyType(newPropertyParent)));
+        schedule(new ReparentNodeRewriteAction(node, oldPropertyParent.parentModelNode(), newPropertyParent, propertyType(newPropertyParent)));
     } else if (isInHierarchy(oldPropertyParent) && !isInHierarchy(newPropertyParent)) { // the node is removed from hierarchy
         if (oldPropertyParent.isNodeProperty()) {
             // ignore, the subsequent remove property will take care of all
diff --git a/src/plugins/qmldesigner/designercore/model/rewriteaction.h b/src/plugins/qmldesigner/designercore/model/rewriteaction.h
index fe33fa8c877..28fd8af451e 100644
--- a/src/plugins/qmldesigner/designercore/model/rewriteaction.h
+++ b/src/plugins/qmldesigner/designercore/model/rewriteaction.h
@@ -55,16 +55,16 @@ public:
     virtual bool execute(QmlDesigner::QmlRefactoring &refactoring, ModelNodePositionStorage &positionStore) = 0;
     virtual QString info() const = 0;
 
-    virtual AddImportRewriteAction const *asAddImportRewriteAction() const { return 0; }
-    virtual AddPropertyRewriteAction const *asAddPropertyRewriteAction() const { return 0; }
-    virtual ChangeIdRewriteAction const *asChangeIdRewriteAction() const { return 0; }
-    virtual ChangePropertyRewriteAction const *asChangePropertyRewriteAction() const { return 0; }
-    virtual ChangeTypeRewriteAction const *asChangeTypeRewriteAction() const { return 0; }
-    virtual RemoveImportRewriteAction const * asRemoveImportRewriteAction() const { return 0; }
-    virtual RemoveNodeRewriteAction const *asRemoveNodeRewriteAction() const { return 0; }
-    virtual RemovePropertyRewriteAction const *asRemovePropertyRewriteAction() const { return 0; }
-    virtual ReparentNodeRewriteAction const *asReparentNodeRewriteAction() const { return 0; }
-    virtual MoveNodeRewriteAction const *asMoveNodeRewriteAction() const { return 0; }
+    virtual AddImportRewriteAction *asAddImportRewriteAction() { return 0; }
+    virtual AddPropertyRewriteAction *asAddPropertyRewriteAction() { return 0; }
+    virtual ChangeIdRewriteAction *asChangeIdRewriteAction() { return 0; }
+    virtual ChangePropertyRewriteAction *asChangePropertyRewriteAction() { return 0; }
+    virtual ChangeTypeRewriteAction *asChangeTypeRewriteAction() { return 0; }
+    virtual RemoveImportRewriteAction * asRemoveImportRewriteAction() { return 0; }
+    virtual RemoveNodeRewriteAction *asRemoveNodeRewriteAction() { return 0; }
+    virtual RemovePropertyRewriteAction *asRemovePropertyRewriteAction() { return 0; }
+    virtual ReparentNodeRewriteAction *asReparentNodeRewriteAction() { return 0; }
+    virtual MoveNodeRewriteAction *asMoveNodeRewriteAction() { return 0; }
 
 protected:
     RewriteAction()
@@ -85,7 +85,7 @@ public:
     virtual bool execute(QmlDesigner::QmlRefactoring &refactoring, ModelNodePositionStorage &positionStore);
     virtual QString info() const;
 
-    virtual AddPropertyRewriteAction const *asAddPropertyRewriteAction() const { return this; }
+    virtual AddPropertyRewriteAction *asAddPropertyRewriteAction() { return this; }
 
     AbstractProperty property() const
     { return m_property; }
@@ -116,7 +116,7 @@ public:
     virtual bool execute(QmlDesigner::QmlRefactoring &refactoring, ModelNodePositionStorage &positionStore);
     virtual QString info() const;
 
-    virtual ChangeIdRewriteAction const *asChangeIdRewriteAction() const { return this; }
+    virtual ChangeIdRewriteAction *asChangeIdRewriteAction() { return this; }
 
     ModelNode node() const
     { return m_node; }
@@ -137,7 +137,7 @@ public:
     virtual bool execute(QmlDesigner::QmlRefactoring &refactoring, ModelNodePositionStorage &positionStore);
     virtual QString info() const;
 
-    virtual ChangePropertyRewriteAction const *asChangePropertyRewriteAction() const { return this; }
+    virtual ChangePropertyRewriteAction *asChangePropertyRewriteAction() { return this; }
 
     AbstractProperty property() const
     { return m_property; }
@@ -168,7 +168,7 @@ public:
     virtual bool execute(QmlDesigner::QmlRefactoring &refactoring, ModelNodePositionStorage &positionStore);
     virtual QString info() const;
 
-    virtual ChangeTypeRewriteAction const *asChangeTypeRewriteAction() const { return this; }
+    virtual ChangeTypeRewriteAction *asChangeTypeRewriteAction() { return this; }
 
     ModelNode node() const
     { return m_node; }
@@ -187,7 +187,7 @@ public:
     virtual bool execute(QmlDesigner::QmlRefactoring &refactoring, ModelNodePositionStorage &positionStore);
     virtual QString info() const;
 
-    virtual RemoveNodeRewriteAction const *asRemoveNodeRewriteAction() const { return this; }
+    virtual RemoveNodeRewriteAction *asRemoveNodeRewriteAction() { return this; }
 
     ModelNode node() const
     { return m_node; }
@@ -206,7 +206,7 @@ public:
     virtual bool execute(QmlDesigner::QmlRefactoring &refactoring, ModelNodePositionStorage &positionStore);
     virtual QString info() const;
 
-    virtual RemovePropertyRewriteAction const *asRemovePropertyRewriteAction() const { return this; }
+    virtual RemovePropertyRewriteAction *asRemovePropertyRewriteAction() { return this; }
 
     AbstractProperty property() const
     { return m_property; }
@@ -218,18 +218,24 @@ private:
 class ReparentNodeRewriteAction: public RewriteAction
 {
 public:
-    ReparentNodeRewriteAction(const ModelNode &node, const AbstractProperty &targetProperty, QmlDesigner::QmlRefactoring::PropertyType propertyType):
-            m_node(node), m_targetProperty(targetProperty), m_propertyType(propertyType)
+    ReparentNodeRewriteAction(const ModelNode &node, const ModelNode &oldParent, const AbstractProperty &targetProperty, QmlDesigner::QmlRefactoring::PropertyType propertyType):
+            m_node(node), m_oldParent(oldParent), m_targetProperty(targetProperty), m_propertyType(propertyType)
     {}
 
     virtual bool execute(QmlDesigner::QmlRefactoring &refactoring, ModelNodePositionStorage &positionStore);
     virtual QString info() const;
 
-    virtual ReparentNodeRewriteAction const *asReparentNodeRewriteAction() const { return this; }
+    virtual ReparentNodeRewriteAction *asReparentNodeRewriteAction() { return this; }
 
     ModelNode reparentedNode() const
     { return m_node; }
 
+    ModelNode oldParent() const
+    { return m_oldParent; }
+
+    void setOldParent(const ModelNode &oldParent)
+    { m_oldParent = oldParent; }
+
     AbstractProperty targetProperty() const
     { return m_targetProperty; }
 
@@ -238,6 +244,7 @@ public:
 
 private:
     ModelNode m_node;
+    ModelNode m_oldParent;
     AbstractProperty m_targetProperty;
     QmlDesigner::QmlRefactoring::PropertyType m_propertyType;
 };
@@ -252,7 +259,7 @@ public:
     virtual bool execute(QmlDesigner::QmlRefactoring &refactoring, ModelNodePositionStorage &positionStore);
     virtual QString info() const;
 
-    virtual MoveNodeRewriteAction const *asMoveNodeRewriteAction() const { return this; }
+    virtual MoveNodeRewriteAction *asMoveNodeRewriteAction() { return this; }
 
 private:
     ModelNode m_movingNode;
@@ -269,7 +276,7 @@ public:
     virtual bool execute(QmlDesigner::QmlRefactoring &refactoring, ModelNodePositionStorage &positionStore);
     virtual QString info() const;
 
-    virtual AddImportRewriteAction const *asAddImportRewriteAction() const { return this; }
+    virtual AddImportRewriteAction *asAddImportRewriteAction() { return this; }
 
     Import import() const { return m_import; }
 
@@ -287,7 +294,7 @@ public:
     virtual bool execute(QmlDesigner::QmlRefactoring &refactoring, ModelNodePositionStorage &positionStore);
     virtual QString info() const;
 
-    virtual RemoveImportRewriteAction const *asRemoveImportRewriteAction() const { return this; }
+    virtual RemoveImportRewriteAction *asRemoveImportRewriteAction() { return this; }
 
     Import import() const { return m_import; }
 
diff --git a/src/plugins/qmldesigner/designercore/model/rewriteactioncompressor.cpp b/src/plugins/qmldesigner/designercore/model/rewriteactioncompressor.cpp
index 1fdcafda594..b2af209ae5a 100644
--- a/src/plugins/qmldesigner/designercore/model/rewriteactioncompressor.cpp
+++ b/src/plugins/qmldesigner/designercore/model/rewriteactioncompressor.cpp
@@ -57,7 +57,8 @@ static bool nodeOrParentInSet(const ModelNode &node, const QSet<ModelNode> &node
 void RewriteActionCompressor::operator()(QList<RewriteAction *> &actions) const
 {
     compressImports(actions);
-    compressReparentActions(actions);
+    compressRereparentActions(actions);
+    compressReparentIntoSameParentActions(actions);
     compressPropertyActions(actions);
     compressAddEditRemoveNodeActions(actions);
     compressAddEditActions(actions);
@@ -74,7 +75,7 @@ void RewriteActionCompressor::compressImports(QList<RewriteAction *> &actions) c
     while (iter.hasPrevious()) {
         RewriteAction *action = iter.previous();
 
-        if (RemoveImportRewriteAction const *removeImportAction = action->asRemoveImportRewriteAction()) {
+        if (RemoveImportRewriteAction *removeImportAction = action->asRemoveImportRewriteAction()) {
             const Import import = removeImportAction->import();
             if (removedImports.contains(import)) {
                 remove(iter);
@@ -86,7 +87,7 @@ void RewriteActionCompressor::compressImports(QList<RewriteAction *> &actions) c
             } else {
                 removedImports.insert(import, action);
             }
-        } else if (AddImportRewriteAction const *addImportAction = action->asAddImportRewriteAction()) {
+        } else if (AddImportRewriteAction *addImportAction = action->asAddImportRewriteAction()) {
             const Import import = addImportAction->import();
             if (RewriteAction *duplicateAction = addedImports.value(import, 0)) {
                 actions.removeOne(duplicateAction);
@@ -105,27 +106,44 @@ void RewriteActionCompressor::compressImports(QList<RewriteAction *> &actions) c
     }
 }
 
-void RewriteActionCompressor::compressReparentActions(QList<RewriteAction *> &actions) const
+void RewriteActionCompressor::compressRereparentActions(QList<RewriteAction *> &actions) const
 {
-    QSet<ModelNode> reparentedNodes;
+    QMap<ModelNode, ReparentNodeRewriteAction *> reparentedNodes;
 
     QMutableListIterator<RewriteAction*> iter(actions);
     iter.toBack();
     while (iter.hasPrevious()) {
         RewriteAction *action = iter.previous();
 
-        if (ReparentNodeRewriteAction const *reparentAction = action->asReparentNodeRewriteAction()) {
+        if (ReparentNodeRewriteAction *reparentAction = action->asReparentNodeRewriteAction()) {
             const ModelNode reparentedNode = reparentAction->reparentedNode();
 
-            if (reparentedNodes.contains(reparentedNode)) {
+            if (ReparentNodeRewriteAction *otherAction = reparentedNodes.value(reparentedNode, 0)) {
+                otherAction->setOldParent(reparentAction->oldParent());
                 remove(iter);
             } else {
-                reparentedNodes.insert(reparentedNode);
+                reparentedNodes.insert(reparentedNode, reparentAction);
             }
         }
     }
 }
 
+void RewriteActionCompressor::compressReparentIntoSameParentActions(QList<RewriteAction *> &actions) const
+{
+    QMutableListIterator<RewriteAction *> iter(actions);
+    iter.toBack();
+    while (iter.hasPrevious()) {
+        RewriteAction *action = iter.previous();
+
+        if (ReparentNodeRewriteAction *reparentAction = action->asReparentNodeRewriteAction()) {
+            const ModelNode targetNode = reparentAction->targetProperty().parentModelNode();
+            const ModelNode oldParent = reparentAction->oldParent();
+            if (targetNode == oldParent)
+                remove(iter);
+        }
+    }
+}
+
 void RewriteActionCompressor::compressAddEditRemoveNodeActions(QList<RewriteAction *> &actions) const
 {
     QHash<ModelNode, RewriteAction *> removedNodes;
@@ -136,7 +154,7 @@ void RewriteActionCompressor::compressAddEditRemoveNodeActions(QList<RewriteActi
     while (iter.hasPrevious()) {
         RewriteAction *action = iter.previous();
 
-        if (RemoveNodeRewriteAction const *removeNodeAction = action->asRemoveNodeRewriteAction()) {
+        if (RemoveNodeRewriteAction *removeNodeAction = action->asRemoveNodeRewriteAction()) {
             const ModelNode modelNode = removeNodeAction->node();
 
             if (removedNodes.contains(modelNode))
@@ -160,18 +178,18 @@ void RewriteActionCompressor::compressAddEditRemoveNodeActions(QList<RewriteActi
                 remove(iter);
                 removeActionsToRemove.insert(removedNodes[containedModelNode]);
             }
-        } else if (RemovePropertyRewriteAction const *removePropertyAction = action->asRemovePropertyRewriteAction()) {
+        } else if (RemovePropertyRewriteAction *removePropertyAction = action->asRemovePropertyRewriteAction()) {
             const AbstractProperty property = removePropertyAction->property();
 
             if (removedNodes.contains(property.parentModelNode()))
                 remove(iter);
-        } else if (ChangeIdRewriteAction const *changeIdAction = action->asChangeIdRewriteAction()) {
+        } else if (ChangeIdRewriteAction *changeIdAction = action->asChangeIdRewriteAction()) {
             if (removedNodes.contains(changeIdAction->node()))
                 remove(iter);
-        } else if (ChangeTypeRewriteAction const *changeTypeAction = action->asChangeTypeRewriteAction()) {
+        } else if (ChangeTypeRewriteAction *changeTypeAction = action->asChangeTypeRewriteAction()) {
             if (removedNodes.contains(changeTypeAction->node()))
                 remove(iter);
-        } else if (ReparentNodeRewriteAction const *reparentAction = action->asReparentNodeRewriteAction()) {
+        } else if (ReparentNodeRewriteAction *reparentAction = action->asReparentNodeRewriteAction()) {
             if (removedNodes.contains(reparentAction->reparentedNode()))
                 remove(iter);
         }
@@ -186,7 +204,7 @@ void RewriteActionCompressor::compressAddEditRemoveNodeActions(QList<RewriteActi
 void RewriteActionCompressor::compressPropertyActions(QList<RewriteAction *> &actions) const
 {
     QHash<AbstractProperty, RewriteAction *> removedProperties;
-    QHash<AbstractProperty, ChangePropertyRewriteAction const*> changedProperties;
+    QHash<AbstractProperty, ChangePropertyRewriteAction *> changedProperties;
     QSet<AbstractProperty> addedProperties;
 
     QMutableListIterator<RewriteAction*> iter(actions);
@@ -194,9 +212,9 @@ void RewriteActionCompressor::compressPropertyActions(QList<RewriteAction *> &ac
     while (iter.hasPrevious()) {
         RewriteAction *action = iter.previous();
 
-        if (RemovePropertyRewriteAction const *removeAction = action->asRemovePropertyRewriteAction()) {
+        if (RemovePropertyRewriteAction *removeAction = action->asRemovePropertyRewriteAction()) {
             removedProperties.insert(removeAction->property(), action);
-        } else if (ChangePropertyRewriteAction const *changeAction = action->asChangePropertyRewriteAction()) {
+        } else if (ChangePropertyRewriteAction *changeAction = action->asChangePropertyRewriteAction()) {
             const AbstractProperty property = changeAction->property();
 
             if (removedProperties.contains(property)) {
@@ -207,7 +225,7 @@ void RewriteActionCompressor::compressPropertyActions(QList<RewriteAction *> &ac
             } else {
                 changedProperties.insert(property, changeAction);
             }
-        } else if (AddPropertyRewriteAction const *addAction = action->asAddPropertyRewriteAction()) {
+        } else if (AddPropertyRewriteAction *addAction = action->asAddPropertyRewriteAction()) {
             const AbstractProperty property = addAction->property();
 
             if (RewriteAction *removeAction = removedProperties.value(property, 0)) {
@@ -238,10 +256,10 @@ void RewriteActionCompressor::compressAddEditActions(QList<RewriteAction *> &act
             AbstractProperty property;
             ModelNode containedNode;
 
-            if (AddPropertyRewriteAction const *addAction = action->asAddPropertyRewriteAction()) {
+            if (AddPropertyRewriteAction *addAction = action->asAddPropertyRewriteAction()) {
                 property = addAction->property();
                 containedNode = addAction->containedModelNode();
-            } else if (ChangePropertyRewriteAction const *changeAction = action->asChangePropertyRewriteAction()) {
+            } else if (ChangePropertyRewriteAction *changeAction = action->asChangePropertyRewriteAction()) {
                 property = changeAction->property();
                 containedNode = changeAction->containedModelNode();
             }
@@ -260,11 +278,11 @@ void RewriteActionCompressor::compressAddEditActions(QList<RewriteAction *> &act
                 addedNodes.insert(containedNode);
                 dirtyActions.insert(action);
             }
-        } else if (ChangeIdRewriteAction const *changeIdAction = action->asChangeIdRewriteAction()) {
+        } else if (ChangeIdRewriteAction *changeIdAction = action->asChangeIdRewriteAction()) {
             if (nodeOrParentInSet(changeIdAction->node(), addedNodes)) {
                 remove(iter);
             }
-        } else if (ChangeTypeRewriteAction const *changeTypeAction = action->asChangeTypeRewriteAction()) {
+        } else if (ChangeTypeRewriteAction *changeTypeAction = action->asChangeTypeRewriteAction()) {
             if (nodeOrParentInSet(changeTypeAction->node(), addedNodes)) {
                 remove(iter);
             }
@@ -274,12 +292,12 @@ void RewriteActionCompressor::compressAddEditActions(QList<RewriteAction *> &act
     QmlTextGenerator gen(m_propertyOrder);
     foreach (RewriteAction *action, dirtyActions) {
         RewriteAction *newAction = 0;
-        if (AddPropertyRewriteAction const *addAction = action->asAddPropertyRewriteAction()) {
+        if (AddPropertyRewriteAction *addAction = action->asAddPropertyRewriteAction()) {
             newAction = new AddPropertyRewriteAction(addAction->property(),
                                                      gen(addAction->containedModelNode()),
                                                      addAction->propertyType(),
                                                      addAction->containedModelNode());
-        } else if (ChangePropertyRewriteAction const *changeAction = action->asChangePropertyRewriteAction()) {
+        } else if (ChangePropertyRewriteAction *changeAction = action->asChangePropertyRewriteAction()) {
             newAction = new ChangePropertyRewriteAction(changeAction->property(),
                                                         gen(changeAction->containedModelNode()),
                                                         changeAction->propertyType(),
@@ -304,9 +322,9 @@ void RewriteActionCompressor::compressAddReparentActions(QList<RewriteAction *>
         if (action->asAddPropertyRewriteAction() || action->asChangePropertyRewriteAction()) {
             ModelNode containedNode;
 
-            if (AddPropertyRewriteAction const *addAction = action->asAddPropertyRewriteAction()) {
+            if (AddPropertyRewriteAction *addAction = action->asAddPropertyRewriteAction()) {
                 containedNode = addAction->containedModelNode();
-            } else if (ChangePropertyRewriteAction const *changeAction = action->asChangePropertyRewriteAction()) {
+            } else if (ChangePropertyRewriteAction *changeAction = action->asChangePropertyRewriteAction()) {
                 containedNode = changeAction->containedModelNode();
             }
 
@@ -314,18 +332,18 @@ void RewriteActionCompressor::compressAddReparentActions(QList<RewriteAction *>
                 continue;
 
             addedNodes.insert(containedNode, action);
-        } else if (ReparentNodeRewriteAction const *reparentAction = action->asReparentNodeRewriteAction()) {
+        } else if (ReparentNodeRewriteAction *reparentAction = action->asReparentNodeRewriteAction()) {
             if (addedNodes.contains(reparentAction->reparentedNode())) {
                 RewriteAction *previousAction = addedNodes[reparentAction->reparentedNode()];
                 actions.removeOne(previousAction);
 
                 RewriteAction *replacementAction = 0;
-                if (AddPropertyRewriteAction const *addAction = previousAction->asAddPropertyRewriteAction()) {
+                if (AddPropertyRewriteAction *addAction = previousAction->asAddPropertyRewriteAction()) {
                     replacementAction = new AddPropertyRewriteAction(reparentAction->targetProperty(),
                                                                      addAction->valueText(),
                                                                      reparentAction->propertyType(),
                                                                      addAction->containedModelNode());
-                } else if (ChangePropertyRewriteAction const *changeAction = previousAction->asChangePropertyRewriteAction()) {
+                } else if (ChangePropertyRewriteAction *changeAction = previousAction->asChangePropertyRewriteAction()) {
                     replacementAction = new AddPropertyRewriteAction(reparentAction->targetProperty(),
                                                                      changeAction->valueText(),
                                                                      reparentAction->propertyType(),
diff --git a/src/plugins/qmldesigner/designercore/model/rewriteactioncompressor.h b/src/plugins/qmldesigner/designercore/model/rewriteactioncompressor.h
index 18d99a390e7..84aaecdadb7 100644
--- a/src/plugins/qmldesigner/designercore/model/rewriteactioncompressor.h
+++ b/src/plugins/qmldesigner/designercore/model/rewriteactioncompressor.h
@@ -47,7 +47,8 @@ public:
 private:
     void compressImports(QList<RewriteAction *> &actions) const;
 
-    void compressReparentActions(QList<RewriteAction *> &actions) const;
+    void compressRereparentActions(QList<RewriteAction *> &actions) const;
+    void compressReparentIntoSameParentActions(QList<RewriteAction *> &actions) const;
     void compressAddEditRemoveNodeActions(QList<RewriteAction *> &actions) const;
     void compressPropertyActions(QList<RewriteAction *> &actions) const;
     void compressAddEditActions(QList<RewriteAction *> &actions) const;
diff --git a/tests/auto/qml/qmldesigner/coretests/testcore.cpp b/tests/auto/qml/qmldesigner/coretests/testcore.cpp
index 43521af494d..eaeeb0d2e2f 100644
--- a/tests/auto/qml/qmldesigner/coretests/testcore.cpp
+++ b/tests/auto/qml/qmldesigner/coretests/testcore.cpp
@@ -700,6 +700,73 @@ void TestCore::testRewriterPreserveOrder()
     }
 }
 
+void TestCore::testRewriterActionCompression()
+{
+    const QLatin1String qmlString("\n"
+                                  "import Qt 4.7\n"
+                                  "\n"
+                                  "Rectangle {\n"
+                                  "  id: root\n"
+                                  "  Rectangle {\n"
+                                  "    id: rect1\n"
+                                  "    x: 10\n"
+                                  "    y: 10\n"
+                                  "  }\n"
+                                  "  Rectangle {\n"
+                                  "    id: rect2\n"
+                                  "    x: 10\n"
+                                  "    y: 10\n"
+                                  "  }\n"
+                                  "}\n");
+
+    QPlainTextEdit textEdit;
+    textEdit.setPlainText(qmlString);
+    NotIndentingTextEditModifier modifier1(&textEdit);
+
+    QScopedPointer<Model> model1(Model::create("Qt/Rectangle"));
+
+    QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView());
+    testRewriterView->setTextModifier(&modifier1);
+    model1->attachView(testRewriterView.data());
+
+    QVERIFY(testRewriterView->errors().isEmpty());
+
+    ModelNode rootModelNode = testRewriterView->rootModelNode();
+    ModelNode rect1 = rootModelNode.property(QLatin1String("data")).toNodeListProperty().toModelNodeList().at(0);
+    ModelNode rect2 = rootModelNode.property(QLatin1String("data")).toNodeListProperty().toModelNodeList().at(1);
+
+    QVERIFY(rect1.isValid());
+    QVERIFY(rect2.isValid());
+
+    RewriterTransaction transaction = testRewriterView->beginRewriterTransaction();
+    rect1.nodeListProperty(QLatin1String("data")).reparentHere(rect2);
+    rect2.variantProperty(QLatin1String("x")).setValue(1.0);
+    rect2.variantProperty(QLatin1String("y")).setValue(1.0);
+
+    rootModelNode.nodeListProperty(QLatin1String("data")).reparentHere(rect2);
+    rect2.variantProperty(QLatin1String("x")).setValue(9.0);
+    rect2.variantProperty(QLatin1String("y")).setValue(9.0);
+    transaction.commit();
+
+    const QLatin1String expected("\n"
+                                 "import Qt 4.7\n"
+                                 "\n"
+                                 "Rectangle {\n"
+                                 "  id: root\n"
+                                 "  Rectangle {\n"
+                                 "    id: rect1\n"
+                                 "    x: 10\n"
+                                 "    y: 10\n"
+                                 "  }\n"
+                                 "  Rectangle {\n"
+                                 "    id: rect2\n"
+                                 "    x: 9\n"
+                                 "    y: 9\n"
+                                 "  }\n"
+                                 "}\n");
+    QCOMPARE(textEdit.toPlainText(), expected);
+}
+
 void TestCore::testRewriterForGradientMagic()
 {
     const QLatin1String qmlString("\n"
diff --git a/tests/auto/qml/qmldesigner/coretests/testcore.h b/tests/auto/qml/qmldesigner/coretests/testcore.h
index 5bfd5e9320c..f3cbc8ebe8e 100644
--- a/tests/auto/qml/qmldesigner/coretests/testcore.h
+++ b/tests/auto/qml/qmldesigner/coretests/testcore.h
@@ -127,7 +127,7 @@ private slots:
     void testRewriterDynamicProperties();
     void testRewriterGroupedProperties();
     void testRewriterPreserveOrder();
-
+    void testRewriterActionCompression();
 
     //
     // unit tests QmlModelNodeFacade/QmlModelState
diff --git a/tests/auto/qml/qmldesigner/coretests/testrewriterview.cpp b/tests/auto/qml/qmldesigner/coretests/testrewriterview.cpp
index 7b340f0e09d..b12c164a6de 100644
--- a/tests/auto/qml/qmldesigner/coretests/testrewriterview.cpp
+++ b/tests/auto/qml/qmldesigner/coretests/testrewriterview.cpp
@@ -37,8 +37,8 @@ using namespace QmlDesigner::Internal;
 
 bool TestModelToTextMerger::isNodeScheduledForRemoval(const ModelNode &node) const
 {
-    foreach (const RewriteAction *action, scheduledRewriteActions()) {
-        if (RemoveNodeRewriteAction const *removeAction = action->asRemoveNodeRewriteAction()) {
+    foreach (RewriteAction *action, scheduledRewriteActions()) {
+        if (RemoveNodeRewriteAction *removeAction = action->asRemoveNodeRewriteAction()) {
             if (removeAction->node() == node)
                 return true;
         }
@@ -49,14 +49,14 @@ bool TestModelToTextMerger::isNodeScheduledForRemoval(const ModelNode &node) con
 
 bool TestModelToTextMerger::isNodeScheduledForAddition(const ModelNode &node) const
 {
-    foreach (const RewriteAction *action, scheduledRewriteActions()) {
-        if (AddPropertyRewriteAction const *addPropertyAction = action->asAddPropertyRewriteAction()) {
+    foreach (RewriteAction *action, scheduledRewriteActions()) {
+        if (AddPropertyRewriteAction *addPropertyAction = action->asAddPropertyRewriteAction()) {
             const AbstractProperty property = addPropertyAction->property();
             if (property.isNodeProperty() && property.toNodeProperty().modelNode() == node)
                 return true;
             else if (property.isNodeListProperty() && property.toNodeListProperty().toModelNodeList().contains(node))
                 return true;
-        } else if (ChangePropertyRewriteAction const *changePropertyAction = action->asChangePropertyRewriteAction()) {
+        } else if (ChangePropertyRewriteAction *changePropertyAction = action->asChangePropertyRewriteAction()) {
             const AbstractProperty property = changePropertyAction->property();
             if (property.isNodeProperty() && property.toNodeProperty().modelNode() == node)
                 return true;
@@ -71,8 +71,8 @@ bool TestModelToTextMerger::isNodeScheduledForAddition(const ModelNode &node) co
 
 VariantProperty TestModelToTextMerger::findAddedVariantProperty(const VariantProperty &property) const
 {
-    foreach (const RewriteAction *action, scheduledRewriteActions()) {
-        if (AddPropertyRewriteAction const * addPropertyAction = action->asAddPropertyRewriteAction()) {
+    foreach (RewriteAction *action, scheduledRewriteActions()) {
+        if (AddPropertyRewriteAction *addPropertyAction = action->asAddPropertyRewriteAction()) {
             const AbstractProperty candidate = addPropertyAction->property();
 
             if (property.isVariantProperty() && property.toVariantProperty() == property)
-- 
GitLab