OSDN Git Service

b50d2914fe180ecfa572a1392f7dc90f2da92e3f
[qt-creator-jp/qt-creator-jp.git] / src / plugins / qmldesigner / designercore / model / qmltextgenerator.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/QVariant>
35 #include <QtGui/QColor>
36
37 #include "bindingproperty.h"
38 #include "nodeproperty.h"
39 #include "nodelistproperty.h"
40 #include "qmltextgenerator.h"
41 #include "variantproperty.h"
42 #include <nodemetainfo.h>
43 #include "model.h"
44
45 using namespace QmlDesigner;
46 using namespace QmlDesigner::Internal;
47
48 inline static QString properColorName(const QColor &color)
49 {
50     QString s;
51     if (color.alpha() == 255)
52         s.sprintf("#%02x%02x%02x", color.red(), color.green(), color.blue());
53     else
54         s.sprintf("#%02x%02x%02x%02x", color.alpha(), color.red(), color.green(), color.blue());
55     return s;
56 }
57
58 QmlTextGenerator::QmlTextGenerator(const QStringList &propertyOrder, int indentDepth):
59         m_propertyOrder(propertyOrder),
60         m_indentDepth(indentDepth)
61 {
62 }
63
64 QString QmlTextGenerator::toQml(const AbstractProperty &property, int indentDepth) const
65 {
66     if (property.isBindingProperty()) {
67         return property.toBindingProperty().expression();
68     } else if (property.isNodeProperty()) {
69         return toQml(property.toNodeProperty().modelNode(), indentDepth);
70     } else if (property.isNodeListProperty()) {
71         const QList<ModelNode> nodes = property.toNodeListProperty().toModelNodeList();
72         if (property.isDefaultProperty()) {
73             QString result;
74             for (int i = 0; i < nodes.length(); ++i) {
75                 if (i > 0)
76                     result += QLatin1String("\n\n");
77                 result += QString(indentDepth, QLatin1Char(' '));
78                 result += toQml(nodes.at(i), indentDepth);
79             }
80             return result;
81         } else {
82             QString result = QLatin1String("[");
83             const int arrayContentDepth = indentDepth + 4;
84             const QString arrayContentIndentation(arrayContentDepth, QLatin1Char(' '));
85             for (int i = 0; i < nodes.length(); ++i) {
86                 if (i > 0)
87                     result += QLatin1Char(',');
88                 result += QLatin1Char('\n');
89                 result += arrayContentIndentation;
90                 result += toQml(nodes.at(i), arrayContentDepth);
91             }
92             return result + QLatin1Char(']');
93         }
94     } else if (property.isVariantProperty()) {
95         const VariantProperty variantProperty = property.toVariantProperty();
96         const QVariant value = variantProperty.value();
97         const QString stringValue = value.toString();
98
99         if (property.name() == QLatin1String("id"))
100             return stringValue;
101
102           if (false) {
103           }
104         if (variantProperty.parentModelNode().metaInfo().isValid() &&
105             variantProperty.parentModelNode().metaInfo().propertyIsEnumType(variantProperty.name())) {
106             return variantProperty.parentModelNode().metaInfo().propertyEnumScope(variantProperty.name()) + '.' + stringValue;
107         } else {
108
109             switch (value.type()) {
110             case QVariant::Bool:
111                 if (value.value<bool>())
112                     return QLatin1String("true");
113                 else
114                     return QLatin1String("false");
115
116             case QVariant::Color:
117                 return QString(QLatin1String("\"%1\"")).arg(properColorName(value.value<QColor>()));
118
119             case QVariant::Double:
120             case QVariant::Int:
121             case QVariant::LongLong:
122             case QVariant::UInt:
123             case QVariant::ULongLong:
124                 return stringValue;
125
126             default:
127                 return QString(QLatin1String("\"%1\"")).arg(escape(stringValue));
128             }
129         }
130     } else {
131         Q_ASSERT("Unknown property type");
132         return QString();
133     }
134 }
135
136 QString QmlTextGenerator::toQml(const ModelNode &node, int indentDepth) const
137 {
138     QString type = node.type();
139     QString url;
140     if (type.contains('.')) {
141         QStringList nameComponents = type.split('.');
142         url = nameComponents.first();
143         type = nameComponents.last();
144     }
145
146     QString alias;
147     if (!url.isEmpty()) {
148         const QString &versionUrl = QString("%1.%2").arg(QString::number(node.majorVersion()), QString::number(node.minorVersion()));
149         foreach (const Import &import, node.model()->imports()) {
150             if (import.url() == url
151                 && import.version() == versionUrl) {
152                 alias = import.alias();
153                 break;
154             }
155         }
156     }
157
158     QString result;
159
160     if (!alias.isEmpty())
161         result = alias + '.';
162
163     result += type;
164     result += QLatin1String(" {\n");
165
166     const int propertyIndentDepth = indentDepth + 4;
167
168     const QString properties = propertiesToQml(node, propertyIndentDepth);
169
170     return result + properties + QString(indentDepth, QLatin1Char(' ')) + QLatin1Char('}');
171 }
172
173 QString QmlTextGenerator::propertiesToQml(const ModelNode &node, int indentDepth) const
174 {
175     QString topPart;
176     QString bottomPart;
177
178     QStringList nodePropertyNames = node.propertyNames();
179     bool addToTop = true;
180
181     foreach (const QString &propertyName, m_propertyOrder) {
182         if (QLatin1String("id") == propertyName) {
183             // the model handles the id property special, so:
184             if (!node.id().isEmpty()) {
185                 QString idLine(indentDepth, QLatin1Char(' '));
186                 idLine += QLatin1String("id: ");
187                 idLine += node.id();
188                 idLine += QLatin1Char('\n');
189
190                 if (addToTop)
191                     topPart.append(idLine);
192                 else
193                     bottomPart.append(idLine);
194             }
195         } else if (propertyName.isEmpty()) {
196             addToTop = false;
197         } else if (nodePropertyNames.removeAll(propertyName)) {
198             const QString newContent = propertyToQml(node.property(propertyName), indentDepth);
199
200             if (addToTop)
201                 topPart.append(newContent);
202             else
203                 bottomPart.append(newContent);
204         }
205     }
206
207     foreach (const QString &propertyName, nodePropertyNames) {
208         bottomPart.prepend(propertyToQml(node.property(propertyName), indentDepth));
209     }
210
211     return topPart + bottomPart;
212 }
213
214 QString QmlTextGenerator::propertyToQml(const AbstractProperty &property, int indentDepth) const
215 {
216     QString result;
217
218     if (property.isDefaultProperty())
219         result = toQml(property, indentDepth);
220     else
221         result = QString(indentDepth, QLatin1Char(' ')) + property.name() + QLatin1String(": ") + toQml(property, indentDepth);
222
223     result += QLatin1Char('\n');
224
225     return result;
226 }
227
228 QString QmlTextGenerator::escape(const QString &value)
229 {
230     QString result = value;
231
232     result.replace(QLatin1String("\\"), QLatin1String("\\\\"));
233     result.replace(QLatin1String("\""), QLatin1String("\\\""));
234     result.replace(QLatin1String("\t"), QLatin1String("\\\t"));
235     result.replace(QLatin1String("\r"), QLatin1String("\\\r"));
236     result.replace(QLatin1String("\n"), QLatin1String("\\\n"));
237
238     return result;
239 }