Initial import from the monolithic Qt.
[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 ** No Commercial Usage
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 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file.  Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23 **
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27 **
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
30 **
31 **
32 **
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