Add missing QT_{BEGIN,END}_NAMESPACE
[profile/ivi/qtdeclarative.git] / src / qml / qml / qqmlcustomparser.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtQml module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qqmlcustomparser_p.h"
43 #include "qqmlcustomparser_p_p.h"
44
45 #include "qqmlcompiler_p.h"
46
47 #include <QtCore/qdebug.h>
48
49 QT_BEGIN_NAMESPACE
50
51 using namespace QQmlScript;
52
53 /*!
54     \class QQmlCustomParser
55     \brief The QQmlCustomParser class allows you to add new arbitrary types to QML.
56     \internal
57
58     By subclassing QQmlCustomParser, you can add a parser for
59     building a particular type.
60
61     The subclass must implement compile() and setCustomData(), and register
62     itself in the meta type system by calling the macro:
63
64     \code
65     QML_REGISTER_CUSTOM_TYPE(Module, MajorVersion, MinorVersion, Name, TypeClass, ParserClass)
66     \endcode
67 */
68
69 /*
70     \fn QByteArray QQmlCustomParser::compile(const QList<QQmlCustomParserProperty> & properties)
71
72     The custom parser processes \a properties, and returns
73     a QByteArray containing data meaningful only to the
74     custom parser; the type engine will pass this same data to
75     setCustomData() when making an instance of the data.
76
77     Errors must be reported via the error() functions.
78
79     The QByteArray may be cached between executions of the system, so
80     it must contain correctly-serialized data (not, for example,
81     pointers to stack objects).
82 */
83
84 /*
85     \fn void QQmlCustomParser::setCustomData(QObject *object, const QByteArray &data)
86
87     This function sets \a object to have the properties defined
88     by \a data, which is a block of data previously returned by a call
89     to compile().
90
91     Errors should be reported using qmlInfo(object).
92
93     The \a object will be an instance of the TypeClass specified by QML_REGISTER_CUSTOM_TYPE.
94 */
95
96 QQmlCustomParserNode 
97 QQmlCustomParserNodePrivate::fromObject(QQmlScript::Object *root)
98 {
99     QQmlCustomParserNode rootNode;
100     if (root->typeReference)
101         rootNode.d->name = root->typeReference->name;
102     rootNode.d->location = root->location.start;
103
104     for (Property *p = root->properties.first(); p; p = root->properties.next(p)) {
105         rootNode.d->properties << fromProperty(p);
106     }
107
108     if (root->defaultProperty)
109         rootNode.d->properties << fromProperty(root->defaultProperty);
110
111     return rootNode;
112 }
113
114 QQmlCustomParserProperty 
115 QQmlCustomParserNodePrivate::fromProperty(QQmlScript::Property *p)
116 {
117     QQmlCustomParserProperty prop;
118     prop.d->name = p->name().toString();
119     prop.d->isList = p->values.isMany();
120     prop.d->location = p->location.start;
121
122     if (p->value) {
123         QQmlCustomParserNode node = fromObject(p->value);
124         QList<QQmlCustomParserProperty> props = node.properties();
125         for (int ii = 0; ii < props.count(); ++ii)
126             prop.d->values << QVariant::fromValue(props.at(ii));
127     } else {
128         for (QQmlScript::Value *v = p->values.first(); v; v = p->values.next(v)) {
129             v->type = QQmlScript::Value::Literal;
130
131             if(v->object) {
132                 QQmlCustomParserNode node = fromObject(v->object);
133                 prop.d->values << QVariant::fromValue(node);
134             } else {
135                 prop.d->values << QVariant::fromValue(v->value);
136             }
137
138         }
139     }
140
141     return prop;
142 }
143
144 QQmlCustomParserNode::QQmlCustomParserNode()
145 : d(new QQmlCustomParserNodePrivate)
146 {
147 }
148
149 QQmlCustomParserNode::QQmlCustomParserNode(const QQmlCustomParserNode &other)
150 : d(new QQmlCustomParserNodePrivate)
151 {
152     *this = other;
153 }
154
155 QQmlCustomParserNode &QQmlCustomParserNode::operator=(const QQmlCustomParserNode &other)
156 {
157     d->name = other.d->name;
158     d->properties = other.d->properties;
159     d->location = other.d->location;
160     return *this;
161 }
162
163 QQmlCustomParserNode::~QQmlCustomParserNode()
164 {
165     delete d; d = 0;
166 }
167
168 QString QQmlCustomParserNode::name() const
169 {
170     return d->name;
171 }
172
173 QList<QQmlCustomParserProperty> QQmlCustomParserNode::properties() const
174 {
175     return d->properties;
176 }
177
178 QQmlScript::Location QQmlCustomParserNode::location() const
179 {
180     return d->location;
181 }
182
183 QQmlCustomParserProperty::QQmlCustomParserProperty()
184 : d(new QQmlCustomParserPropertyPrivate)
185 {
186 }
187
188 QQmlCustomParserProperty::QQmlCustomParserProperty(const QQmlCustomParserProperty &other)
189 : d(new QQmlCustomParserPropertyPrivate)
190 {
191     *this = other;
192 }
193
194 QQmlCustomParserProperty &QQmlCustomParserProperty::operator=(const QQmlCustomParserProperty &other)
195 {
196     d->name = other.d->name;
197     d->isList = other.d->isList;
198     d->values = other.d->values;
199     d->location = other.d->location;
200     return *this;
201 }
202
203 QQmlCustomParserProperty::~QQmlCustomParserProperty()
204 {
205     delete d; d = 0;
206 }
207
208 QString QQmlCustomParserProperty::name() const
209 {
210     return d->name;
211 }
212
213 bool QQmlCustomParserProperty::isList() const
214 {
215     return d->isList;
216 }
217
218 QQmlScript::Location QQmlCustomParserProperty::location() const
219 {
220     return d->location;
221 }
222
223 QList<QVariant> QQmlCustomParserProperty::assignedValues() const
224 {
225     return d->values;
226 }
227
228 void QQmlCustomParser::clearErrors()
229 {
230     exceptions.clear();
231 }
232
233 /*!
234     Reports an error with the given \a description.
235
236     This can only be used during the compile() step. For errors during setCustomData(), use qmlInfo().
237
238     An error is generated referring to the position of the element in the source file.
239 */
240 void QQmlCustomParser::error(const QString& description)
241 {
242     Q_ASSERT(object);
243     QQmlError error;
244     QString exceptionDescription;
245     error.setLine(object->location.start.line);
246     error.setColumn(object->location.start.column);
247     error.setDescription(description);
248     exceptions << error;
249 }
250
251 /*!
252     Reports an error in parsing \a prop, with the given \a description.
253
254     An error is generated referring to the position of \a node in the source file.
255 */
256 void QQmlCustomParser::error(const QQmlCustomParserProperty& prop, const QString& description)
257 {
258     QQmlError error;
259     QString exceptionDescription;
260     error.setLine(prop.location().line);
261     error.setColumn(prop.location().column);
262     error.setDescription(description);
263     exceptions << error;
264 }
265
266 /*!
267     Reports an error in parsing \a node, with the given \a description.
268
269     An error is generated referring to the position of \a node in the source file.
270 */
271 void QQmlCustomParser::error(const QQmlCustomParserNode& node, const QString& description)
272 {
273     QQmlError error;
274     QString exceptionDescription;
275     error.setLine(node.location().line);
276     error.setColumn(node.location().column);
277     error.setDescription(description);
278     exceptions << error;
279 }
280
281 /*!
282     If \a script is a simple enumeration expression (eg. Text.AlignLeft),
283     returns the integer equivalent (eg. 1), and sets \a ok to true.
284
285     Otherwise sets \a ok to false.
286
287     A valid \a ok must be provided, or the function will assert.
288 */
289 int QQmlCustomParser::evaluateEnum(const QByteArray& script, bool *ok) const
290 {
291     Q_ASSERT_X(ok, "QQmlCustomParser::evaluateEnum", "ok must not be a null pointer");
292     *ok = false;
293     int dot = script.indexOf('.');
294     if (dot == -1)
295         return -1;
296
297     return compiler->evaluateEnum(QString::fromUtf8(script.left(dot)), script.mid(dot+1), ok);
298 }
299
300 /*!
301     Resolves \a name to a type, or 0 if it is not a type. This can be used
302     to type-check object nodes.
303 */
304 const QMetaObject *QQmlCustomParser::resolveType(const QString& name) const
305 {
306     return compiler->resolveType(name);
307 }
308
309 /*!
310     Rewrites \a value and returns an identifier that can be
311     used to construct the binding later. \a name
312     is used as the name of the rewritten function.
313 */
314 QQmlBinding::Identifier QQmlCustomParser::rewriteBinding(const QQmlScript::Variant &value, const QString& name)
315 {
316     return compiler->rewriteBinding(value, name);
317 }
318
319 /*!
320     Returns a rewritten \a handler. \a name
321     is used as the name of the rewritten function.
322 */
323 QString QQmlCustomParser::rewriteSignalHandler(const QQmlScript::Variant &value, const QString &name)
324 {
325     return compiler->rewriteSignalHandler(value , name);
326 }
327
328 QT_END_NAMESPACE