QmlDesigner: Use predicate to walk nodes for merging

Task-number: QDS-3776
Change-Id: I59f647042d5975f953c4c9e2f24e60a0003b85c8
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
Vikas Pachdha
2021-02-21 23:00:25 +01:00
parent caaad2107d
commit c17458cfa9
2 changed files with 54 additions and 29 deletions

View File

@@ -28,19 +28,24 @@
#include <qmldesignercorelib_global.h> #include <qmldesignercorelib_global.h>
#include <QPointer> #include <QPointer>
#include <functional>
namespace QmlDesigner { namespace QmlDesigner {
class AbstractView; class AbstractView;
class ModelNode; class ModelNode;
using MergePredicate = std::function<bool(const ModelNode &)>;
class QMLDESIGNERCORE_EXPORT ModelMerger class QMLDESIGNERCORE_EXPORT ModelMerger
{ {
public: public:
ModelMerger(AbstractView *view) : m_view(view) {} ModelMerger(AbstractView *view) : m_view(view) {}
ModelNode insertModel(const ModelNode &modelNode); ModelNode insertModel(const ModelNode &modelNode,
void replaceModel(const ModelNode &modelNode); const MergePredicate &predicate = [](const ModelNode &) { return true; });
void replaceModel(const ModelNode &modelNode,
const MergePredicate &predicate = [](const ModelNode &) { return true; });
protected: protected:
AbstractView *view() const AbstractView *view() const

View File

@@ -43,7 +43,9 @@
namespace QmlDesigner { namespace QmlDesigner {
static ModelNode createNodeFromNode(const ModelNode &modelNode,const QHash<QString, QString> &idRenamingHash, AbstractView *view); static ModelNode createNodeFromNode(const ModelNode &modelNode,
const QHash<QString, QString> &idRenamingHash,
AbstractView *view, const MergePredicate &mergePredicate);
static QString fixExpression(const QString &expression, const QHash<QString, QString> &idRenamingHash) static QString fixExpression(const QString &expression, const QHash<QString, QString> &idRenamingHash)
{ {
@@ -130,25 +132,36 @@ static void setupIdRenamingHash(const ModelNode &modelNode, QHash<QString, QStri
} }
} }
static void syncNodeProperties(ModelNode &outputNode, const ModelNode &inputNode, const QHash<QString, QString> &idRenamingHash, AbstractView *view) static void syncNodeProperties(ModelNode &outputNode, const ModelNode &inputNode,
const QHash<QString, QString> &idRenamingHash,
AbstractView *view, const MergePredicate &mergePredicate)
{ {
foreach (const NodeProperty &nodeProperty, inputNode.nodeProperties()) { foreach (const NodeProperty &nodeProperty, inputNode.nodeProperties()) {
ModelNode newNode = createNodeFromNode(nodeProperty.modelNode(), idRenamingHash, view); ModelNode node = nodeProperty.modelNode();
if (!mergePredicate(node))
continue;
ModelNode newNode = createNodeFromNode(node, idRenamingHash, view, mergePredicate);
outputNode.nodeProperty(nodeProperty.name()).reparentHere(newNode); outputNode.nodeProperty(nodeProperty.name()).reparentHere(newNode);
} }
} }
static void syncNodeListProperties(ModelNode &outputNode, const ModelNode &inputNode, const QHash<QString, QString> &idRenamingHash, AbstractView *view) static void syncNodeListProperties(ModelNode &outputNode, const ModelNode &inputNode,
const QHash<QString, QString> &idRenamingHash,
AbstractView *view, const MergePredicate &mergePredicate)
{ {
foreach (const NodeListProperty &nodeListProperty, inputNode.nodeListProperties()) { foreach (const NodeListProperty &nodeListProperty, inputNode.nodeListProperties()) {
foreach (const ModelNode &node, nodeListProperty.toModelNodeList()) { foreach (const ModelNode &node, nodeListProperty.toModelNodeList()) {
ModelNode newNode = createNodeFromNode(node, idRenamingHash, view); if (!mergePredicate(node))
continue;
ModelNode newNode = createNodeFromNode(node, idRenamingHash, view, mergePredicate);
outputNode.nodeListProperty(nodeListProperty.name()).reparentHere(newNode); outputNode.nodeListProperty(nodeListProperty.name()).reparentHere(newNode);
} }
} }
} }
static ModelNode createNodeFromNode(const ModelNode &modelNode,const QHash<QString, QString> &idRenamingHash, AbstractView *view) static ModelNode createNodeFromNode(const ModelNode &modelNode,
const QHash<QString, QString> &idRenamingHash,
AbstractView *view, const MergePredicate &mergePredicate)
{ {
QList<QPair<PropertyName, QVariant> > propertyList; QList<QPair<PropertyName, QVariant> > propertyList;
QList<QPair<PropertyName, QVariant> > variantPropertyList; QList<QPair<PropertyName, QVariant> > variantPropertyList;
@@ -162,14 +175,17 @@ static ModelNode createNodeFromNode(const ModelNode &modelNode,const QHash<QStri
syncBindingProperties(newNode, modelNode, idRenamingHash); syncBindingProperties(newNode, modelNode, idRenamingHash);
syncSignalHandlerProperties(newNode, modelNode, idRenamingHash); syncSignalHandlerProperties(newNode, modelNode, idRenamingHash);
syncId(newNode, modelNode, idRenamingHash); syncId(newNode, modelNode, idRenamingHash);
syncNodeProperties(newNode, modelNode, idRenamingHash, view); syncNodeProperties(newNode, modelNode, idRenamingHash, view, mergePredicate);
syncNodeListProperties(newNode, modelNode, idRenamingHash, view); syncNodeListProperties(newNode, modelNode, idRenamingHash, view, mergePredicate);
return newNode; return newNode;
} }
ModelNode ModelMerger::insertModel(const ModelNode &modelNode)
ModelNode ModelMerger::insertModel(const ModelNode &modelNode, const MergePredicate &predicate)
{ {
if (!predicate(modelNode))
return {};
RewriterTransaction transaction(view()->beginRewriterTransaction(QByteArrayLiteral("ModelMerger::insertModel"))); RewriterTransaction transaction(view()->beginRewriterTransaction(QByteArrayLiteral("ModelMerger::insertModel")));
QList<Import> newImports; QList<Import> newImports;
@@ -183,32 +199,36 @@ ModelNode ModelMerger::insertModel(const ModelNode &modelNode)
QHash<QString, QString> idRenamingHash; QHash<QString, QString> idRenamingHash;
setupIdRenamingHash(modelNode, idRenamingHash, view()); setupIdRenamingHash(modelNode, idRenamingHash, view());
ModelNode newNode(createNodeFromNode(modelNode, idRenamingHash, view())); ModelNode newNode(createNodeFromNode(modelNode, idRenamingHash, view(), predicate));
return newNode; return newNode;
} }
void ModelMerger::replaceModel(const ModelNode &modelNode)
void ModelMerger::replaceModel(const ModelNode &modelNode, const MergePredicate &predicate)
{ {
view()->model()->changeImports(modelNode.model()->imports(), {}); if (!predicate(modelNode))
view()->model()->setFileUrl(modelNode.model()->fileUrl()); return;
view()->executeInTransaction("ModelMerger::replaceModel", [this, modelNode](){ view()->model()->changeImports(modelNode.model()->imports(), {});
ModelNode rootNode(view()->rootModelNode()); view()->model()->setFileUrl(modelNode.model()->fileUrl());
foreach (const PropertyName &propertyName, rootNode.propertyNames()) view()->executeInTransaction("ModelMerger::replaceModel", [this, modelNode, &predicate](){
rootNode.removeProperty(propertyName); ModelNode rootNode(view()->rootModelNode());
QHash<QString, QString> idRenamingHash; foreach (const PropertyName &propertyName, rootNode.propertyNames())
setupIdRenamingHash(modelNode, idRenamingHash, view()); rootNode.removeProperty(propertyName);
syncAuxiliaryProperties(rootNode, modelNode); QHash<QString, QString> idRenamingHash;
syncVariantProperties(rootNode, modelNode); setupIdRenamingHash(modelNode, idRenamingHash, view());
syncBindingProperties(rootNode, modelNode, idRenamingHash);
syncId(rootNode, modelNode, idRenamingHash); syncAuxiliaryProperties(rootNode, modelNode);
syncNodeProperties(rootNode, modelNode, idRenamingHash, view()); syncVariantProperties(rootNode, modelNode);
syncNodeListProperties(rootNode, modelNode, idRenamingHash, view()); syncBindingProperties(rootNode, modelNode, idRenamingHash);
m_view->changeRootNodeType(modelNode.type(), modelNode.majorVersion(), modelNode.minorVersion()); syncId(rootNode, modelNode, idRenamingHash);
}); syncNodeProperties(rootNode, modelNode, idRenamingHash, view(), predicate);
syncNodeListProperties(rootNode, modelNode, idRenamingHash, view(), predicate);
m_view->changeRootNodeType(modelNode.type(), modelNode.majorVersion(), modelNode.minorVersion());
});
} }
} //namespace QmlDesigner } //namespace QmlDesigner