OSDN Git Service

dcabd74ed7ca51a316384a12b0e4bb9a69b65ec9
[qt-creator-jp/qt-creator-jp.git] / src / plugins / qmldesigner / designercore / model / modelmerger.cpp
1 /**************************************************************************
2 **
3 ** This file is part of Qt Creator
4 **
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
6 **
7 ** Contact: Nokia Corporation (qt-info@nokia.com)
8 **
9 ** No Commercial Usage
10 **
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
14 ** this package.
15 **
16 ** GNU Lesser General Public License Usage
17 **
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file.  Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Nokia gives you certain additional
26 ** rights.  These rights are described in the Nokia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** If you have questions regarding the use of this file, please contact
30 ** Nokia at qt-info@nokia.com.
31 **
32 **************************************************************************/
33
34 #include "modelmerger.h"
35
36 #include "modelmerger.h"
37 #include "modelnode.h"
38 #include "abstractview.h"
39 #include "model.h"
40 #include "nodeproperty.h"
41 #include "nodelistproperty.h"
42 #include "bindingproperty.h"
43 #include "variantproperty.h"
44 #include "rewritertransaction.h"
45 #include <rewritingexception.h>
46
47 #include <QSet>
48 #include <QStringList>
49
50 #include <QtDebug>
51
52 namespace QmlDesigner {
53
54 static ModelNode createNodeFromNode(const ModelNode &modelNode,const QHash<QString, QString> &idRenamingHash, AbstractView *view);
55
56 static QString fixExpression(const QString &expression, const QHash<QString, QString> &idRenamingHash)
57 {
58     QString newExpression = expression;
59     foreach (const QString &id, idRenamingHash.keys()) {
60         if (newExpression.contains(id))
61             newExpression = newExpression.replace(id, idRenamingHash.value(id));
62     }
63     return newExpression;
64 }
65
66 static void syncVariantProperties(ModelNode &outputNode, const ModelNode &inputNode)
67 {
68     foreach (const VariantProperty &variantProperty, inputNode.variantProperties()) {
69         outputNode.variantProperty(variantProperty.name()) = variantProperty.value();
70     }
71 }
72
73 static void syncBindingProperties(ModelNode &outputNode, const ModelNode &inputNode, const QHash<QString, QString> &idRenamingHash)
74 {
75     foreach (const BindingProperty &bindingProperty, inputNode.bindingProperties()) {
76         outputNode.bindingProperty(bindingProperty.name()).setExpression(fixExpression(bindingProperty.expression(), idRenamingHash));
77     }
78 }
79
80 static void syncId(ModelNode &outputNode, const ModelNode &inputNode, const QHash<QString, QString> &idRenamingHash)
81 {
82     if (!inputNode.id().isEmpty()) {
83         outputNode.setId(idRenamingHash.value(inputNode.id()));
84     }
85 }
86
87 static void splitIdInBaseNameAndNumber(const QString &id, QString *baseId, int *number)
88 {
89
90     int counter = 0;
91     while(counter < id.count()) {
92         bool canConvertToInteger = false;
93         int newNumber = id.right(counter +1).toInt(&canConvertToInteger);
94         if (canConvertToInteger)
95             *number = newNumber;
96         else
97             break;
98
99         counter++;
100     }
101
102     *baseId = id.left(id.count() - counter);
103 }
104
105 static void setupIdRenamingHash(const ModelNode &modelNode, QHash<QString, QString> &idRenamingHash, AbstractView *view)
106 {
107     QList<ModelNode> allNodes(modelNode.allSubModelNodes());
108     allNodes.append(modelNode);
109     foreach (const ModelNode &node, allNodes) {
110         if (!node.id().isEmpty()) {
111             QString newId = node.id();
112             QString baseId;
113             int number = 1;
114             splitIdInBaseNameAndNumber(newId, &baseId, &number);
115
116             while (view->hasId(newId) || idRenamingHash.values().contains(newId)) {
117                 newId = baseId + QString::number(number);
118                 number++;
119             }
120
121             idRenamingHash.insert(node.id(), newId);
122         }
123     }
124 }
125
126 static void syncNodeProperties(ModelNode &outputNode, const ModelNode &inputNode, const QHash<QString, QString> &idRenamingHash, AbstractView *view)
127 {
128     foreach (const NodeProperty &nodeProperty, inputNode.nodeProperties()) {
129         ModelNode newNode = createNodeFromNode(nodeProperty.modelNode(), idRenamingHash, view);
130         outputNode.nodeProperty(nodeProperty.name()).reparentHere(newNode);
131     }
132 }
133
134 static void syncNodeListProperties(ModelNode &outputNode, const ModelNode &inputNode, const QHash<QString, QString> &idRenamingHash, AbstractView *view)
135 {
136     foreach (const NodeListProperty &nodeListProperty, inputNode.nodeListProperties()) {
137         foreach (const ModelNode &node, nodeListProperty.toModelNodeList()) {
138             ModelNode newNode = createNodeFromNode(node, idRenamingHash, view);
139             outputNode.nodeListProperty(nodeListProperty.name()).reparentHere(newNode);
140         }
141     }
142 }
143
144 static ModelNode createNodeFromNode(const ModelNode &modelNode,const QHash<QString, QString> &idRenamingHash, AbstractView *view)
145 {
146     QList<QPair<QString, QVariant> > propertyList;
147     foreach (const VariantProperty &variantProperty, modelNode.variantProperties()) {
148         propertyList.append(QPair<QString, QVariant>(variantProperty.name(), variantProperty.value()));
149     }
150     ModelNode newNode(view->createModelNode(modelNode.type(),modelNode.majorVersion(),modelNode.minorVersion(), propertyList));
151     syncBindingProperties(newNode, modelNode, idRenamingHash);
152     syncId(newNode, modelNode, idRenamingHash);
153     syncNodeProperties(newNode, modelNode, idRenamingHash, view);
154     syncNodeListProperties(newNode, modelNode, idRenamingHash, view);
155
156     return newNode;
157 }
158
159 ModelNode ModelMerger::insertModel(const ModelNode &modelNode)
160 {
161     RewriterTransaction transaction(view()->beginRewriterTransaction());
162
163     view()->model()->changeImports(modelNode.model()->imports(), QList<Import>());
164
165     QHash<QString, QString> idRenamingHash;
166     setupIdRenamingHash(modelNode, idRenamingHash, view());
167     qDebug() << idRenamingHash;
168     ModelNode newNode(createNodeFromNode(modelNode, idRenamingHash, view()));
169
170     return newNode;
171 }
172
173 void ModelMerger::replaceModel(const ModelNode &modelNode)
174 {
175         view()->model()->changeImports(modelNode.model()->imports(), QList<Import>());
176         view()->model()->setFileUrl(modelNode.model()->fileUrl());
177
178     try {
179         RewriterTransaction transaction(view()->beginRewriterTransaction());
180
181         ModelNode rootNode(view()->rootModelNode());
182
183         foreach (const QString &propertyName, rootNode.propertyNames())
184             rootNode.removeProperty(propertyName);
185
186         QHash<QString, QString> idRenamingHash;
187         setupIdRenamingHash(modelNode, idRenamingHash, view());
188
189         syncVariantProperties(rootNode, modelNode);
190         syncBindingProperties(rootNode, modelNode, idRenamingHash);
191         syncId(rootNode, modelNode, idRenamingHash);
192         syncNodeProperties(rootNode, modelNode, idRenamingHash, view());
193         syncNodeListProperties(rootNode, modelNode, idRenamingHash, view());
194         m_view->changeRootNodeType(modelNode.type(), modelNode.majorVersion(), modelNode.minorVersion());
195     } catch (RewritingException &e) { 
196         qWarning() << e.description(); //silent error
197     }
198 }
199
200 } //namespace QmlDesigner
201