forked from qt-creator/qt-creator
QmlDesigner: Support reparenting to new nodes in transactions
When we reparent to a new node that was created during the same transaction, then this node has no position. In this case we have to delete the reparented nodes and they will be created as part of the creation of the new node, since they are children. Change-Id: Icd1d02f29f529fc0f00809f7ecebf3eabfdc9a5c Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
This commit is contained in:
@@ -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"));
|
||||
|
||||
|
@@ -56,6 +56,7 @@ void RewriteActionCompressor::operator()(QList<RewriteAction *> &actions,
|
||||
compressImports(actions);
|
||||
compressRereparentActions(actions);
|
||||
compressReparentIntoSamePropertyActions(actions);
|
||||
compressReparentIntoNewPropertyActions(actions);
|
||||
compressPropertyActions(actions);
|
||||
compressAddEditRemoveNodeActions(actions);
|
||||
compressAddEditActions(actions, tabSettings);
|
||||
@@ -152,6 +153,32 @@ void RewriteActionCompressor::compressReparentIntoSamePropertyActions(QList<Rewr
|
||||
}
|
||||
}
|
||||
|
||||
void RewriteActionCompressor::compressReparentIntoNewPropertyActions(QList<RewriteAction *> &actions) const
|
||||
{
|
||||
QList<RewriteAction *> actionsToRemove;
|
||||
|
||||
QList<RewriteAction *> 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<RewriteAction *> &actions) const
|
||||
{
|
||||
QList<RewriteAction *> actionsToRemove;
|
||||
|
@@ -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<RewriteAction *> &actions, const TextEditor::TabSettings &tabSettings) const;
|
||||
|
||||
@@ -42,6 +45,7 @@ private:
|
||||
|
||||
void compressRereparentActions(QList<RewriteAction *> &actions) const;
|
||||
void compressReparentIntoSamePropertyActions(QList<RewriteAction *> &actions) const;
|
||||
void compressReparentIntoNewPropertyActions(QList<RewriteAction *> &actions) const;
|
||||
void compressAddEditRemoveNodeActions(QList<RewriteAction *> &actions) const;
|
||||
void compressPropertyActions(QList<RewriteAction *> &actions) const;
|
||||
void compressAddEditActions(QList<RewriteAction *> &actions, const TextEditor::TabSettings &tabSettings) const;
|
||||
@@ -49,6 +53,7 @@ private:
|
||||
|
||||
private:
|
||||
PropertyNameList m_propertyOrder;
|
||||
ModelNodePositionStorage *m_positionStore;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
@@ -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(Model::create("QtQuick.Rectangle"));
|
||||
|
||||
QScopedPointer<TestRewriterView> 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<ModelNode> 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"
|
||||
|
@@ -144,6 +144,7 @@ private slots:
|
||||
void testRewriterChangeImports();
|
||||
void testRewriterUnicodeChars();
|
||||
void testRewriterTransactionAddingAfterReparenting();
|
||||
void testRewriterReparentToNewNode();
|
||||
|
||||
//
|
||||
// unit tests QmlModelNodeFacade/QmlModelState
|
||||
|
Reference in New Issue
Block a user