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