OSDN Git Service

It's 2011 now.
[qt-creator-jp/qt-creator-jp.git] / src / plugins / qmldesigner / designercore / model / rewriteactioncompressor.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 <QtCore/QSet>
35
36 #include "modelnode.h"
37 #include "nodelistproperty.h"
38 #include "nodeproperty.h"
39 #include "qmltextgenerator.h"
40 #include "rewriteactioncompressor.h"
41
42 using namespace QmlDesigner;
43 using namespace QmlDesigner::Internal;
44
45 static bool nodeOrParentInSet(const ModelNode &node, const QSet<ModelNode> &nodeSet)
46 {
47     ModelNode n = node;
48     while (n.isValid()) {
49         if (nodeSet.contains(n))
50             return true;
51
52         if (!n.hasParentProperty())
53             return false;
54
55         n = n.parentProperty().parentModelNode();
56     }
57
58     return false;
59 }
60
61 void RewriteActionCompressor::operator()(QList<RewriteAction *> &actions) const
62 {
63     compressImports(actions);
64     compressRereparentActions(actions);
65     compressReparentIntoSamePropertyActions(actions);
66     compressPropertyActions(actions);
67     compressAddEditRemoveNodeActions(actions);
68     compressAddEditActions(actions);
69     compressAddReparentActions(actions);
70 }
71
72 void RewriteActionCompressor::compressImports(QList<RewriteAction *> &actions) const
73 {
74     QList<RewriteAction *> actionsToRemove;
75     QHash<Import, RewriteAction *> addedImports;
76     QHash<Import, RewriteAction *> removedImports;
77
78     QMutableListIterator<RewriteAction *> iter(actions);
79     iter.toBack();
80     while (iter.hasPrevious()) {
81         RewriteAction *action = iter.previous();
82
83         if (RemoveImportRewriteAction *removeImportAction = action->asRemoveImportRewriteAction()) {
84             const Import import = removeImportAction->import();
85             if (removedImports.contains(import)) {
86                 actionsToRemove.append(action);
87             } else if (RewriteAction *addImportAction = addedImports.value(import, 0)) {
88                 actionsToRemove.append(action);
89                 actionsToRemove.append(addImportAction);
90                 addedImports.remove(import);
91                 delete addImportAction;
92             } else {
93                 removedImports.insert(import, action);
94             }
95         } else if (AddImportRewriteAction *addImportAction = action->asAddImportRewriteAction()) {
96             const Import import = addImportAction->import();
97             if (RewriteAction *duplicateAction = addedImports.value(import, 0)) {
98                 actionsToRemove.append(duplicateAction);
99                 addedImports.remove(import);
100                 delete duplicateAction;
101                 addedImports.insert(import, action);
102             } else if (RewriteAction *removeAction = removedImports.value(import, 0)) {
103                 actionsToRemove.append(action);
104                 actionsToRemove.append(removeAction);
105                 removedImports.remove(import);
106                 delete removeAction;
107             } else {
108                 addedImports.insert(import, action);
109             }
110         }
111     }
112
113     foreach (RewriteAction *action, actionsToRemove) {
114         actions.removeOne(action);
115         delete action;
116     }
117 }
118
119 void RewriteActionCompressor::compressRereparentActions(QList<RewriteAction *> &actions) const
120 {
121     QList<RewriteAction *> actionsToRemove;
122     QHash<ModelNode, ReparentNodeRewriteAction *> reparentedNodes;
123
124     QMutableListIterator<RewriteAction*> iter(actions);
125     iter.toBack();
126     while (iter.hasPrevious()) {
127         RewriteAction *action = iter.previous();
128
129         if (ReparentNodeRewriteAction *reparentAction = action->asReparentNodeRewriteAction()) {
130             const ModelNode reparentedNode = reparentAction->reparentedNode();
131
132             if (ReparentNodeRewriteAction *otherAction = reparentedNodes.value(reparentedNode, 0)) {
133                 otherAction->setOldParentProperty(reparentAction->oldParentProperty());
134                 actionsToRemove.append(action);
135             } else {
136                 reparentedNodes.insert(reparentedNode, reparentAction);
137             }
138         }
139     }
140
141     foreach (RewriteAction *action, actionsToRemove) {
142         actions.removeOne(action);
143         delete action;
144     }
145 }
146
147 void RewriteActionCompressor::compressReparentIntoSamePropertyActions(QList<RewriteAction *> &actions) const
148 {
149     QList<RewriteAction *> actionsToRemove;
150     QMutableListIterator<RewriteAction *> iter(actions);
151     iter.toBack();
152     while (iter.hasPrevious()) {
153         RewriteAction *action = iter.previous();
154
155         if (ReparentNodeRewriteAction *reparentAction = action->asReparentNodeRewriteAction()) {
156             if (reparentAction->targetProperty() == reparentAction->oldParentProperty())
157                 actionsToRemove.append(action);
158         }
159     }
160
161     foreach (RewriteAction *action, actionsToRemove) {
162         actions.removeOne(action);
163         delete action;
164     }
165 }
166
167 void RewriteActionCompressor::compressAddEditRemoveNodeActions(QList<RewriteAction *> &actions) const
168 {
169     QList<RewriteAction *> actionsToRemove;
170     QHash<ModelNode, RewriteAction *> removedNodes;
171
172     QMutableListIterator<RewriteAction*> iter(actions);
173     iter.toBack();
174     while (iter.hasPrevious()) {
175         RewriteAction *action = iter.previous();
176
177         if (RemoveNodeRewriteAction *removeNodeAction = action->asRemoveNodeRewriteAction()) {
178             const ModelNode modelNode = removeNodeAction->node();
179
180             if (removedNodes.contains(modelNode))
181                 actionsToRemove.append(action);
182             else
183                 removedNodes.insert(modelNode, action);
184         } else if (action->asAddPropertyRewriteAction() || action->asChangePropertyRewriteAction()) {
185             AbstractProperty property;
186             ModelNode containedModelNode;
187             if (action->asAddPropertyRewriteAction()) {
188                 property = action->asAddPropertyRewriteAction()->property();
189                 containedModelNode = action->asAddPropertyRewriteAction()->containedModelNode();
190             } else {
191                 property = action->asChangePropertyRewriteAction()->property();
192                 containedModelNode = action->asChangePropertyRewriteAction()->containedModelNode();
193             }
194
195             if (removedNodes.contains(property.parentModelNode())) {
196                 actionsToRemove.append(action);
197             } else if (RewriteAction *removeAction = removedNodes.value(containedModelNode, 0)) {
198                 actionsToRemove.append(action);
199                 actionsToRemove.append(removeAction);
200             }
201         } else if (RemovePropertyRewriteAction *removePropertyAction = action->asRemovePropertyRewriteAction()) {
202             const AbstractProperty property = removePropertyAction->property();
203
204             if (removedNodes.contains(property.parentModelNode()))
205                 actionsToRemove.append(action);
206         } else if (ChangeIdRewriteAction *changeIdAction = action->asChangeIdRewriteAction()) {
207             if (removedNodes.contains(changeIdAction->node()))
208                 actionsToRemove.append(action);
209         } else if (ChangeTypeRewriteAction *changeTypeAction = action->asChangeTypeRewriteAction()) {
210             if (removedNodes.contains(changeTypeAction->node()))
211                 actionsToRemove.append(action);
212         } else if (ReparentNodeRewriteAction *reparentAction = action->asReparentNodeRewriteAction()) {
213             if (removedNodes.contains(reparentAction->reparentedNode()))
214                 actionsToRemove.append(action);
215         }
216     }
217
218     foreach (RewriteAction *action, actionsToRemove) {
219         actions.removeOne(action);
220         delete action;
221     }
222 }
223
224 void RewriteActionCompressor::compressPropertyActions(QList<RewriteAction *> &actions) const
225 {
226     QList<RewriteAction *> actionsToRemove;
227     QHash<AbstractProperty, RewriteAction *> removedProperties;
228     QHash<AbstractProperty, ChangePropertyRewriteAction *> changedProperties;
229     QSet<AbstractProperty> addedProperties;
230
231     QMutableListIterator<RewriteAction*> iter(actions);
232     iter.toBack();
233     while (iter.hasPrevious()) {
234         RewriteAction *action = iter.previous();
235
236         if (RemovePropertyRewriteAction *removeAction = action->asRemovePropertyRewriteAction()) {
237             removedProperties.insert(removeAction->property(), action);
238         } else if (ChangePropertyRewriteAction *changeAction = action->asChangePropertyRewriteAction()) {
239             const AbstractProperty property = changeAction->property();
240
241             if (removedProperties.contains(property)) {
242                 actionsToRemove.append(action);
243             } else if (changedProperties.contains(property)) {
244                 if (!property.isValid() || !property.isDefaultProperty())
245                     actionsToRemove.append(action);
246             } else {
247                 changedProperties.insert(property, changeAction);
248             }
249         } else if (AddPropertyRewriteAction *addAction = action->asAddPropertyRewriteAction()) {
250             const AbstractProperty property = addAction->property();
251
252             if (RewriteAction *removeAction = removedProperties.value(property, 0)) {
253                 actionsToRemove.append(action);
254                 actionsToRemove.append(removeAction);
255                 removedProperties.remove(property);
256             } else {
257                 if (changedProperties.contains(property))
258                     changedProperties.remove(property);
259
260                 addedProperties.insert(property);
261             }
262         }
263     }
264
265     foreach (RewriteAction *action, actionsToRemove){
266         actions.removeOne(action);
267         delete action;
268     }
269 }
270
271 void RewriteActionCompressor::compressAddEditActions(QList<RewriteAction *> &actions) const
272 {
273     QList<RewriteAction *> actionsToRemove;
274     QSet<ModelNode> addedNodes;
275     QSet<RewriteAction *> dirtyActions;
276
277     QMutableListIterator<RewriteAction*> iter(actions);
278     while (iter.hasNext()) {
279         RewriteAction *action = iter.next();
280
281         if (action->asAddPropertyRewriteAction() || action->asChangePropertyRewriteAction()) {
282             AbstractProperty property;
283             ModelNode containedNode;
284
285             if (AddPropertyRewriteAction *addAction = action->asAddPropertyRewriteAction()) {
286                 property = addAction->property();
287                 containedNode = addAction->containedModelNode();
288             } else if (ChangePropertyRewriteAction *changeAction = action->asChangePropertyRewriteAction()) {
289                 property = changeAction->property();
290                 containedNode = changeAction->containedModelNode();
291             }
292
293             if (property.isValid() && addedNodes.contains(property.parentModelNode())) {
294                 actionsToRemove.append(action);
295                 continue;
296             }
297
298             if (!containedNode.isValid())
299                 continue;
300
301             if (nodeOrParentInSet(containedNode, addedNodes)) {
302                 actionsToRemove.append(action);
303             } else {
304                 addedNodes.insert(containedNode);
305                 dirtyActions.insert(action);
306             }
307         } else if (ChangeIdRewriteAction *changeIdAction = action->asChangeIdRewriteAction()) {
308             if (nodeOrParentInSet(changeIdAction->node(), addedNodes)) {
309                 actionsToRemove.append(action);
310             }
311         } else if (ChangeTypeRewriteAction *changeTypeAction = action->asChangeTypeRewriteAction()) {
312             if (nodeOrParentInSet(changeTypeAction->node(), addedNodes)) {
313                 actionsToRemove.append(action);
314             }
315         }
316     }
317
318     foreach (RewriteAction *action, actionsToRemove){
319         actions.removeOne(action);
320         delete action;
321     }
322
323     QmlTextGenerator gen(m_propertyOrder);
324     foreach (RewriteAction *action, dirtyActions) {
325         RewriteAction *newAction = 0;
326         if (AddPropertyRewriteAction *addAction = action->asAddPropertyRewriteAction()) {
327             newAction = new AddPropertyRewriteAction(addAction->property(),
328                                                      gen(addAction->containedModelNode()),
329                                                      addAction->propertyType(),
330                                                      addAction->containedModelNode());
331         } else if (ChangePropertyRewriteAction *changeAction = action->asChangePropertyRewriteAction()) {
332             newAction = new ChangePropertyRewriteAction(changeAction->property(),
333                                                         gen(changeAction->containedModelNode()),
334                                                         changeAction->propertyType(),
335                                                         changeAction->containedModelNode());
336         }
337
338         const int idx = actions.indexOf(action);
339         if (newAction && idx >= 0) {
340             actions[idx] = newAction;
341         }
342     }
343 }
344
345 void RewriteActionCompressor::compressAddReparentActions(QList<RewriteAction *> &actions) const
346 {
347     QList<RewriteAction *> actionsToRemove;
348     QMap<ModelNode, RewriteAction*> addedNodes;
349
350     QMutableListIterator<RewriteAction*> iter(actions);
351     while (iter.hasNext()) {
352         RewriteAction *action = iter.next();
353
354         if (action->asAddPropertyRewriteAction() || action->asChangePropertyRewriteAction()) {
355             ModelNode containedNode;
356
357             if (AddPropertyRewriteAction *addAction = action->asAddPropertyRewriteAction()) {
358                 containedNode = addAction->containedModelNode();
359             } else if (ChangePropertyRewriteAction *changeAction = action->asChangePropertyRewriteAction()) {
360                 containedNode = changeAction->containedModelNode();
361             }
362
363             if (!containedNode.isValid())
364                 continue;
365
366             addedNodes.insert(containedNode, action);
367         } else if (ReparentNodeRewriteAction *reparentAction = action->asReparentNodeRewriteAction()) {
368             if (addedNodes.contains(reparentAction->reparentedNode())) {
369                 RewriteAction *previousAction = addedNodes[reparentAction->reparentedNode()];
370                 actionsToRemove.append(previousAction);
371
372                 RewriteAction *replacementAction = 0;
373                 if (AddPropertyRewriteAction *addAction = previousAction->asAddPropertyRewriteAction()) {
374                     replacementAction = new AddPropertyRewriteAction(reparentAction->targetProperty(),
375                                                                      addAction->valueText(),
376                                                                      reparentAction->propertyType(),
377                                                                      addAction->containedModelNode());
378                 } else if (ChangePropertyRewriteAction *changeAction = previousAction->asChangePropertyRewriteAction()) {
379                     replacementAction = new AddPropertyRewriteAction(reparentAction->targetProperty(),
380                                                                      changeAction->valueText(),
381                                                                      reparentAction->propertyType(),
382                                                                      changeAction->containedModelNode());
383                 }
384
385                 iter.setValue(replacementAction);
386                 delete action;
387             }
388         }
389     }
390
391     foreach (RewriteAction *action, actionsToRemove){
392         actions.removeOne(action);
393         delete action;
394     }
395 }