diff --git a/src/plugins/qmldesigner/designercore/model/modeltotextmerger.cpp b/src/plugins/qmldesigner/designercore/model/modeltotextmerger.cpp index 5a4276a416f..14badab2bf6 100644 --- a/src/plugins/qmldesigner/designercore/model/modeltotextmerger.cpp +++ b/src/plugins/qmldesigner/designercore/model/modeltotextmerger.cpp @@ -222,7 +222,7 @@ void ModelToTextMerger::applyChanges() return; dumpRewriteActions(QStringLiteral("Before compression")); - RewriteActionCompressor compress(propertyOrder()); + RewriteActionCompressor compress(propertyOrder(), m_rewriterView->positionStorage()); compress(m_rewriteActions, m_rewriterView->textModifier()->tabSettings()); dumpRewriteActions(QStringLiteral("After compression")); diff --git a/src/plugins/qmldesigner/designercore/model/rewriteactioncompressor.cpp b/src/plugins/qmldesigner/designercore/model/rewriteactioncompressor.cpp index 24342002b38..c014bcd4d78 100644 --- a/src/plugins/qmldesigner/designercore/model/rewriteactioncompressor.cpp +++ b/src/plugins/qmldesigner/designercore/model/rewriteactioncompressor.cpp @@ -56,6 +56,7 @@ void RewriteActionCompressor::operator()(QList &actions, compressImports(actions); compressRereparentActions(actions); compressReparentIntoSamePropertyActions(actions); + compressReparentIntoNewPropertyActions(actions); compressPropertyActions(actions); compressAddEditRemoveNodeActions(actions); compressAddEditActions(actions, tabSettings); @@ -152,6 +153,32 @@ void RewriteActionCompressor::compressReparentIntoSamePropertyActions(QList &actions) const +{ + QList actionsToRemove; + + QList removeActions; + + for (int i = actions.size(); --i >= 0; ) { + RewriteAction *action = actions.at(i); + + if (ReparentNodeRewriteAction *reparentAction = action->asReparentNodeRewriteAction()) { + if (m_positionStore->nodeOffset(reparentAction->targetProperty().parentModelNode()) < 0) { + actionsToRemove.append(action); + + removeActions.append(new RemoveNodeRewriteAction(reparentAction->reparentedNode())); + } + } + } + + for (RewriteAction *action : qAsConst(actionsToRemove)) { + actions.removeOne(action); + delete action; + } + + actions.append(removeActions); +} + void RewriteActionCompressor::compressAddEditRemoveNodeActions(QList &actions) const { QList actionsToRemove; diff --git a/src/plugins/qmldesigner/designercore/model/rewriteactioncompressor.h b/src/plugins/qmldesigner/designercore/model/rewriteactioncompressor.h index 57139f98115..02c1e3ad48a 100644 --- a/src/plugins/qmldesigner/designercore/model/rewriteactioncompressor.h +++ b/src/plugins/qmldesigner/designercore/model/rewriteactioncompressor.h @@ -33,7 +33,10 @@ namespace Internal { class RewriteActionCompressor { public: - RewriteActionCompressor(const PropertyNameList &propertyOrder): m_propertyOrder(propertyOrder) {} + RewriteActionCompressor(const PropertyNameList &propertyOrder, ModelNodePositionStorage *positionStore) : + m_propertyOrder(propertyOrder), + m_positionStore(positionStore) + {} void operator()(QList &actions, const TextEditor::TabSettings &tabSettings) const; @@ -42,6 +45,7 @@ private: void compressRereparentActions(QList &actions) const; void compressReparentIntoSamePropertyActions(QList &actions) const; + void compressReparentIntoNewPropertyActions(QList &actions) const; void compressAddEditRemoveNodeActions(QList &actions) const; void compressPropertyActions(QList &actions) const; void compressAddEditActions(QList &actions, const TextEditor::TabSettings &tabSettings) const; @@ -49,6 +53,7 @@ private: private: PropertyNameList m_propertyOrder; + ModelNodePositionStorage *m_positionStore; }; } // namespace Internal diff --git a/tests/auto/qml/qmldesigner/coretests/tst_testcore.cpp b/tests/auto/qml/qmldesigner/coretests/tst_testcore.cpp index 26b8ddcf8e3..f6708d2c8f3 100644 --- a/tests/auto/qml/qmldesigner/coretests/tst_testcore.cpp +++ b/tests/auto/qml/qmldesigner/coretests/tst_testcore.cpp @@ -1152,6 +1152,79 @@ void tst_TestCore::testRewriterTransactionAddingAfterReparenting() } } +void tst_TestCore::testRewriterReparentToNewNode() +{ + const QLatin1String qmlString("\n" + "import QtQuick 2.0\n" + "\n" + "Item {\n" + " Item {}\n" + " Item {}\n" + " Item {}\n" + " Item {}\n" + "}\n"); + + QPlainTextEdit textEdit; + textEdit.setPlainText(qmlString); + NotIndentingTextEditModifier modifier(&textEdit); + + QScopedPointer model(Model::create("QtQuick.Rectangle")); + + QScopedPointer testRewriterView(new TestRewriterView(0, RewriterView::Amend)); + testRewriterView->setTextModifier(&modifier); + model->attachView(testRewriterView.data()); + + QVERIFY(testRewriterView->errors().isEmpty()); + + ModelNode rootModelNode = testRewriterView->rootModelNode(); + QVERIFY(rootModelNode.isValid()); + + const QList children = rootModelNode.directSubModelNodes(); + + ModelNode rectangle = testRewriterView->createModelNode("QtQuick.Rectangle", 2, 0); + rootModelNode.nodeListProperty("data").reparentHere(rectangle); + + rectangle.setIdWithoutRefactoring("newParent"); + + QVERIFY(rectangle.isValid()); + + for (const ModelNode &child : children) + rectangle.nodeListProperty("data").reparentHere(child); + + { + RewriterTransaction transaction = testRewriterView->beginRewriterTransaction("TEST"); + ModelNode rectangle = testRewriterView->createModelNode("QtQuick.Rectangle", 2, 0); + rootModelNode.nodeListProperty("data").reparentHere(rectangle); + + rectangle.setIdWithoutRefactoring("newParent2"); + + for (const ModelNode &child : children) + rectangle.nodeListProperty("data").reparentHere(child); + } + + QCOMPARE(testRewriterView->allModelNodes().count(), 7); + + const QLatin1String expectedOutcome("\nimport QtQuick 2.0\n\n" + "Item {\n\n" + " Rectangle {\n" + " id: newParent\n" + " }\n\n" + " Rectangle {\n" + " id: newParent2\n" + " Item {\n" + " }\n\n" + " Item {\n" + " }\n\n" + " Item {\n" + " }\n\n" + " Item {\n" + " }\n" + " }\n}\n"); + + + QCOMPARE(textEdit.toPlainText(), expectedOutcome); +} + void tst_TestCore::testRewriterForGradientMagic() { const QLatin1String qmlString("\n" diff --git a/tests/auto/qml/qmldesigner/coretests/tst_testcore.h b/tests/auto/qml/qmldesigner/coretests/tst_testcore.h index 9a8aeb6450b..5248763fef9 100644 --- a/tests/auto/qml/qmldesigner/coretests/tst_testcore.h +++ b/tests/auto/qml/qmldesigner/coretests/tst_testcore.h @@ -144,6 +144,7 @@ private slots: void testRewriterChangeImports(); void testRewriterUnicodeChars(); void testRewriterTransactionAddingAfterReparenting(); + void testRewriterReparentToNewNode(); // // unit tests QmlModelNodeFacade/QmlModelState