OSDN Git Service

45cab4f498c7766734be2771f82234d53d98310a
[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     QHash<AbstractProperty, AddPropertyRewriteAction *> 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             const AbstractProperty property = removeAction->property();
238             if (AddPropertyRewriteAction *addAction = addedProperties.value(property, 0)) {
239             } else {
240                 removedProperties.insert(property, action);
241             }
242         } else if (ChangePropertyRewriteAction *changeAction = action->asChangePropertyRewriteAction()) {
243             const AbstractProperty property = changeAction->property();
244
245             if (removedProperties.contains(property)) {
246                 actionsToRemove.append(action);
247             } else if (changedProperties.contains(property)) {
248                 if (!property.isValid() || !property.isDefaultProperty())
249                     actionsToRemove.append(action);
250             } else {
251                 changedProperties.insert(property, changeAction);
252             }
253         } else if (AddPropertyRewriteAction *addAction = action->asAddPropertyRewriteAction()) {
254             const AbstractProperty property = addAction->property();
255
256             if (RewriteAction *removeAction = removedProperties.value(property, 0)) {
257                 actionsToRemove.append(action);
258                 actionsToRemove.append(removeAction);
259                 removedProperties.remove(property);
260             } else {
261                 if (changedProperties.contains(property))
262                     changedProperties.remove(property);
263
264                 addedProperties.insert(property, addAction);
265             }
266         }
267     }
268
269     foreach (RewriteAction *action, actionsToRemove){
270         actions.removeOne(action);
271         delete action;
272     }
273 }
274
275 void RewriteActionCompressor::compressAddEditActions(QList<RewriteAction *> &actions) const
276 {
277     QList<RewriteAction *> actionsToRemove;
278     QSet<ModelNode> addedNodes;
279     QSet<RewriteAction *> dirtyActions;
280
281     QMutableListIterator<RewriteAction*> iter(actions);
282     while (iter.hasNext()) {
283         RewriteAction *action = iter.next();
284
285         if (action->asAddPropertyRewriteAction() || action->asChangePropertyRewriteAction()) {
286             AbstractProperty property;
287             ModelNode containedNode;
288
289             if (AddPropertyRewriteAction *addAction = action->asAddPropertyRewriteAction()) {
290                 property = addAction->property();
291                 containedNode = addAction->containedModelNode();
292             } else if (ChangePropertyRewriteAction *changeAction = action->asChangePropertyRewriteAction()) {
293                 property = changeAction->property();
294                 containedNode = changeAction->containedModelNode();
295             }
296
297             if (property.isValid() && addedNodes.contains(property.parentModelNode())) {
298                 actionsToRemove.append(action);
299                 continue;
300             }
301
302             if (!containedNode.isValid())
303                 continue;
304
305             if (nodeOrParentInSet(containedNode, addedNodes)) {
306                 actionsToRemove.append(action);
307             } else {
308                 addedNodes.insert(containedNode);
309                 dirtyActions.insert(action);
310             }
311         } else if (ChangeIdRewriteAction *changeIdAction = action->asChangeIdRewriteAction()) {
312             if (nodeOrParentInSet(changeIdAction->node(), addedNodes)) {
313                 actionsToRemove.append(action);
314             }
315         } else if (ChangeTypeRewriteAction *changeTypeAction = action->asChangeTypeRewriteAction()) {
316             if (nodeOrParentInSet(changeTypeAction->node(), addedNodes)) {
317                 actionsToRemove.append(action);
318             }
319         }
320     }
321
322     foreach (RewriteAction *action, actionsToRemove){
323         actions.removeOne(action);
324         delete action;
325     }
326
327     QmlTextGenerator gen(m_propertyOrder);
328     foreach (RewriteAction *action, dirtyActions) {
329         RewriteAction *newAction = 0;
330         if (AddPropertyRewriteAction *addAction = action->asAddPropertyRewriteAction()) {
331             newAction = new AddPropertyRewriteAction(addAction->property(),
332                                                      gen(addAction->containedModelNode()),
333                                                      addAction->propertyType(),
334                                                      addAction->containedModelNode());
335         } else if (ChangePropertyRewriteAction *changeAction = action->asChangePropertyRewriteAction()) {
336             newAction = new ChangePropertyRewriteAction(changeAction->property(),
337                                                         gen(changeAction->containedModelNode()),
338                                                         changeAction->propertyType(),
339                                                         changeAction->containedModelNode());
340         }
341
342         const int idx = actions.indexOf(action);
343         if (newAction && idx >= 0) {
344             actions[idx] = newAction;
345         }
346     }
347 }
348
349 void RewriteActionCompressor::compressAddReparentActions(QList<RewriteAction *> &actions) const
350 {
351     QList<RewriteAction *> actionsToRemove;
352     QMap<ModelNode, RewriteAction*> addedNodes;
353
354     QMutableListIterator<RewriteAction*> iter(actions);
355     while (iter.hasNext()) {
356         RewriteAction *action = iter.next();
357
358         if (action->asAddPropertyRewriteAction() || action->asChangePropertyRewriteAction()) {
359             ModelNode containedNode;
360
361             if (AddPropertyRewriteAction *addAction = action->asAddPropertyRewriteAction()) {
362                 containedNode = addAction->containedModelNode();
363             } else if (ChangePropertyRewriteAction *changeAction = action->asChangePropertyRewriteAction()) {
364                 containedNode = changeAction->containedModelNode();
365             }
366
367             if (!containedNode.isValid())
368                 continue;
369
370             addedNodes.insert(containedNode, action);
371         } else if (ReparentNodeRewriteAction *reparentAction = action->asReparentNodeRewriteAction()) {
372             if (addedNodes.contains(reparentAction->reparentedNode())) {
373                 RewriteAction *previousAction = addedNodes[reparentAction->reparentedNode()];
374                 actionsToRemove.append(previousAction);
375
376                 RewriteAction *replacementAction = 0;
377                 if (AddPropertyRewriteAction *addAction = previousAction->asAddPropertyRewriteAction()) {
378                     replacementAction = new AddPropertyRewriteAction(reparentAction->targetProperty(),
379                                                                      addAction->valueText(),
380                                                                      reparentAction->propertyType(),
381                                                                      addAction->containedModelNode());
382                 } else if (ChangePropertyRewriteAction *changeAction = previousAction->asChangePropertyRewriteAction()) {
383                     replacementAction = new AddPropertyRewriteAction(reparentAction->targetProperty(),
384                                                                      changeAction->valueText(),
385                                                                      reparentAction->propertyType(),
386                                                                      changeAction->containedModelNode());
387                 }
388
389                 iter.setValue(replacementAction);
390                 delete action;
391             }
392         }
393     }
394
395     foreach (RewriteAction *action, actionsToRemove){
396         actions.removeOne(action);
397         delete action;
398     }
399 }