Add missing QT_{BEGIN,END}_NAMESPACE
[profile/ivi/qtdeclarative.git] / src / qml / qml / qqmllist.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 "qqmllist.h"
43 #include "qqmllist_p.h"
44 #include "qqmlengine_p.h"
45 #include "qqmlproperty_p.h"
46
47 QT_BEGIN_NAMESPACE
48
49 QQmlListReferencePrivate::QQmlListReferencePrivate()
50 : propertyType(-1), refCount(1)
51 {
52 }
53
54 QQmlListReference QQmlListReferencePrivate::init(const QQmlListProperty<QObject> &prop, int propType, QQmlEngine *engine)
55 {
56     QQmlListReference rv;
57
58     if (!prop.object) return rv;
59
60     QQmlEnginePrivate *p = engine?QQmlEnginePrivate::get(engine):0;
61
62     int listType = p?p->listType(propType):QQmlMetaType::listType(propType);
63     if (listType == -1) return rv;
64
65     rv.d = new QQmlListReferencePrivate;
66     rv.d->object = prop.object;
67     rv.d->elementType = QQmlPropertyPrivate::rawMetaObjectForType(p, listType);
68     rv.d->property = prop;
69     rv.d->propertyType = propType;
70
71     return rv;
72 }
73
74 void QQmlListReferencePrivate::addref()
75 {
76     Q_ASSERT(refCount > 0);
77     ++refCount;
78 }
79
80 void QQmlListReferencePrivate::release()
81 {
82     Q_ASSERT(refCount > 0);
83     --refCount;
84     if (!refCount)
85         delete this;
86 }
87
88 /*!
89 \class QQmlListReference
90 \since 5.0
91 \inmodule QtQml
92 \brief The QQmlListReference class allows the manipulation of QQmlListProperty properties.
93
94 QQmlListReference allows C++ programs to read from, and assign values to a QML list property in a
95 simple and type safe way.  A QQmlListReference can be created by passing an object and property
96 name or through a QQmlProperty instance.  These two are equivalant:
97
98 \code
99 QQmlListReference ref1(object, "children");
100
101 QQmlProperty ref2(object, "children");
102 QQmlListReference ref2 = qvariant_cast<QQmlListReference>(ref2.read());
103 \endcode
104
105 Not all QML list properties support all operations.  A set of methods, canAppend(), canAt(), canClear() and
106 canCount() allow programs to query whether an operation is supported on a given property.
107
108 QML list properties are typesafe.  Only QObject's that derive from the correct base class can be assigned to
109 the list.  The listElementType() method can be used to query the QMetaObject of the QObject type supported.
110 Attempting to add objects of the incorrect type to a list property will fail.
111
112 Like with normal lists, when accessing a list element by index, it is the callers responsibility to ensure 
113 that it does not request an out of range element using the count() method before calling at().
114
115 The QtQuick 1 version of this class is named QDeclarativeListReference.
116 */
117
118 /*!
119 Constructs an invalid instance.
120 */
121 QQmlListReference::QQmlListReference()
122 : d(0)
123 {
124 }
125
126 /*!
127 Constructs a QQmlListReference for \a object's \a property.  If \a property is not a list
128 property, an invalid QQmlListReference is created.  If \a object is destroyed after 
129 the reference is constructed, it will automatically become invalid.  That is, it is safe to hold
130 QQmlListReference instances even after \a object is deleted.
131
132 Passing \a engine is required to access some QML created list properties.  If in doubt, and an engine
133 is available, pass it.
134 */
135 QQmlListReference::QQmlListReference(QObject *object, const char *property, QQmlEngine *engine)
136 : d(0)
137 {
138     if (!object || !property) return;
139
140     QQmlPropertyData local;
141     QQmlPropertyData *data =
142         QQmlPropertyCache::property(engine, object, QLatin1String(property), local);
143
144     if (!data || !data->isQList()) return;
145
146     QQmlEnginePrivate *p = engine?QQmlEnginePrivate::get(engine):0;
147
148     int listType = p?p->listType(data->propType):QQmlMetaType::listType(data->propType);
149     if (listType == -1) return;
150
151     d = new QQmlListReferencePrivate;
152     d->object = object;
153     d->elementType = p?p->rawMetaObjectForType(listType):QQmlMetaType::qmlType(listType)->baseMetaObject();
154     d->propertyType = data->propType;
155
156     void *args[] = { &d->property, 0 };
157     QMetaObject::metacall(object, QMetaObject::ReadProperty, data->coreIndex, args);
158 }
159
160 /*! \internal */
161 QQmlListReference::QQmlListReference(const QQmlListReference &o)
162 : d(o.d)
163 {
164     if (d) d->addref();
165 }
166
167 /*! \internal */
168 QQmlListReference &QQmlListReference::operator=(const QQmlListReference &o)
169 {
170     if (o.d) o.d->addref();
171     if (d) d->release();
172     d = o.d;
173     return *this;
174 }
175
176 /*! \internal */
177 QQmlListReference::~QQmlListReference()
178 {
179     if (d) d->release();
180 }
181
182 /*!
183 Returns true if the instance refers to a valid list property, otherwise false.
184 */
185 bool QQmlListReference::isValid() const
186 {
187     return d && d->object;
188 }
189
190 /*!
191 Returns the list property's object.  Returns 0 if the reference is invalid.
192 */
193 QObject *QQmlListReference::object() const
194 {
195     if (isValid()) return d->object;
196     else return 0;
197 }
198
199 /*!
200 Returns the QMetaObject for the elements stored in the list property.  Returns 0 if the reference
201 is invalid.
202
203 The QMetaObject can be used ahead of time to determine whether a given instance can be added
204 to a list.
205 */
206 const QMetaObject *QQmlListReference::listElementType() const
207 {
208     if (isValid()) return d->elementType.metaObject();
209     else return 0;
210 }
211
212 /*!
213 Returns true if the list property can be appended to, otherwise false.  Returns false if the
214 reference is invalid.
215
216 \sa append()
217 */
218 bool QQmlListReference::canAppend() const
219 {
220     return (isValid() && d->property.append);
221 }
222
223 /*!
224 Returns true if the list property can queried by index, otherwise false.  Returns false if the
225 reference is invalid.
226
227 \sa at()
228 */
229 bool QQmlListReference::canAt() const
230 {
231     return (isValid() && d->property.at);
232 }
233
234 /*!
235 Returns true if the list property can be cleared, otherwise false.  Returns false if the
236 reference is invalid.
237
238 \sa clear()
239 */
240 bool QQmlListReference::canClear() const
241 {
242     return (isValid() && d->property.clear);
243 }
244
245 /*!
246 Returns true if the list property can be queried for its element count, otherwise false.  
247 Returns false if the reference is invalid.
248
249 \sa count()
250 */
251 bool QQmlListReference::canCount() const
252 {
253     return (isValid() && d->property.count);
254 }
255
256 /*!
257 Appends \a object to the list.  Returns true if the operation succeeded, otherwise false.
258
259 \sa canAppend()
260 */
261 bool QQmlListReference::append(QObject *object) const
262 {
263     if (!canAppend()) return false;
264
265     if (object && !QQmlMetaObject::canConvert(object, d->elementType))
266         return false;
267
268     d->property.append(&d->property, object);
269
270     return true;
271 }
272
273 /*!
274 Returns the list element at \a index, or 0 if the operation failed.
275
276 \sa canAt()
277 */
278 QObject *QQmlListReference::at(int index) const
279 {
280     if (!canAt()) return 0;
281
282     return d->property.at(&d->property, index);
283 }
284
285 /*!
286 Clears the list.  Returns true if the operation succeeded, otherwise false.
287
288 \sa canClear()
289 */
290 bool QQmlListReference::clear() const
291 {
292     if (!canClear()) return false;
293
294     d->property.clear(&d->property);
295
296     return true;
297 }
298
299 /*!
300 Returns the number of objects in the list, or 0 if the operation failed.
301 */
302 int QQmlListReference::count() const
303 {
304     if (!canCount()) return 0;
305
306     return d->property.count(&d->property);
307 }
308
309 /*!
310 \class QQmlListProperty
311 \since 5.0
312 \inmodule QtQml
313 \brief The QQmlListProperty class allows applications to expose list-like 
314 properties to QML.
315
316 QML has many list properties, where more than one object value can be assigned.
317 The use of a list property from QML looks like this:
318
319 \code
320 FruitBasket {
321     fruit: [ 
322         Apple {},
323         Orange{},
324         Banana{}
325     ]
326 }
327 \endcode
328
329 The QQmlListProperty encapsulates a group of function pointers that represet the
330 set of actions QML can perform on the list - adding items, retrieving items and
331 clearing the list.  In the future, additional operations may be supported.  All 
332 list properties must implement the append operation, but the rest are optional.
333
334 To provide a list property, a C++ class must implement the operation callbacks, 
335 and then return an appropriate QQmlListProperty value from the property getter.
336 List properties should have no setter.  In the example above, the Q_PROPERTY()
337 declarative will look like this:
338
339 \code
340 Q_PROPERTY(QQmlListProperty<Fruit> fruit READ fruit);
341 \endcode
342
343 QML list properties are typesafe - in this case \c {Fruit} is a QObject type that 
344 \c {Apple}, \c {Orange} and \c {Banana} all derive from.
345
346 The QtQuick 1 version of this class is named QDeclarativeListProperty.
347
348 \note QQmlListProperty can only be used for lists of QObject-derived object pointers.
349 */
350
351 /*!
352 \fn QQmlListProperty::QQmlListProperty() 
353 \internal
354 */
355
356 /*!
357 \fn QQmlListProperty::QQmlListProperty(QObject *object, QList<T *> &list)
358
359 Convenience constructor for making a QQmlListProperty value from an existing
360 QList \a list.  The \a list reference must remain valid for as long as \a object
361 exists.  \a object must be provided.
362
363 Generally this constructor should not be used in production code, as a 
364 writable QList violates QML's memory management rules.  However, this constructor
365 can very useful while prototyping.
366 */
367
368 /*!
369 \fn QQmlListProperty::QQmlListProperty(QObject *object, void *data, AppendFunction append, 
370                                      CountFunction count = 0, AtFunction at = 0, 
371                                      ClearFunction clear = 0)
372
373 Construct a QQmlListProperty from a set of operation functions.  An opaque \a data handle
374 may be passed which can be accessed from within the operation functions.  The list property 
375 remains valid while \a object exists.
376
377 The \a append operation is compulsory and must be provided, while the \a count, \a at and
378 \a clear methods are optional.
379 */
380
381 /*!
382 \typedef QQmlListProperty::AppendFunction
383
384 Synonym for \c {void (*)(QQmlListProperty<T> *property, T *value)}.
385
386 Append the \a value to the list \a property.
387 */
388
389 /*!
390 \typedef QQmlListProperty::CountFunction
391
392 Synonym for \c {int (*)(QQmlListProperty<T> *property)}.
393
394 Return the number of elements in the list \a property.
395 */
396
397 /*!
398 \fn bool QQmlListProperty::operator==(const QQmlListProperty &other) const 
399
400 Returns true if this QQmlListProperty is equal to \a other, otherwise false.
401 */
402
403 /*!
404 \typedef QQmlListProperty::AtFunction
405
406 Synonym for \c {T *(*)(QQmlListProperty<T> *property, int index)}.
407
408 Return the element at position \a index in the list \a property.
409 */
410
411 /*!
412 \typedef QQmlListProperty::ClearFunction
413
414 Synonym for \c {void (*)(QQmlListProperty<T> *property)}.
415
416 Clear the list \a property.
417 */
418
419 QT_END_NAMESPACE