Improve documentation.
[profile/ivi/qtdeclarative.git] / src / qml / qml / qqmllist.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtQml module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.  For licensing terms and
14 ** conditions see http://qt.digia.com/licensing.  For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
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, Digia gives you certain additional
26 ** rights.  These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file.  Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
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), 0, 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     Return true if at(), count(), append() and clear() are implemented, so you can manipulate
258     the list.
259
260 \sa isReadable(), at(), count(), append(), clear()
261 */
262 bool QQmlListReference::isManipulable() const
263 {
264     return (isValid()
265             && d->property.append
266             && d->property.count
267             && d->property.at
268             && d->property.clear);
269 }
270
271
272 /*!
273     Return true if at() and count() are implemented, so you can access the elements.
274
275 \sa isManipulable(), at(), count()
276 */
277 bool QQmlListReference::isReadable() const
278 {
279     return (isValid() && d->property.count && d->property.at);
280 }
281
282 /*!
283 Appends \a object to the list.  Returns true if the operation succeeded, otherwise false.
284
285 \sa canAppend()
286 */
287 bool QQmlListReference::append(QObject *object) const
288 {
289     if (!canAppend()) return false;
290
291     if (object && !QQmlMetaObject::canConvert(object, d->elementType))
292         return false;
293
294     d->property.append(&d->property, object);
295
296     return true;
297 }
298
299 /*!
300 Returns the list element at \a index, or 0 if the operation failed.
301
302 \sa canAt()
303 */
304 QObject *QQmlListReference::at(int index) const
305 {
306     if (!canAt()) return 0;
307
308     return d->property.at(&d->property, index);
309 }
310
311 /*!
312 Clears the list.  Returns true if the operation succeeded, otherwise false.
313
314 \sa canClear()
315 */
316 bool QQmlListReference::clear() const
317 {
318     if (!canClear()) return false;
319
320     d->property.clear(&d->property);
321
322     return true;
323 }
324
325 /*!
326 Returns the number of objects in the list, or 0 if the operation failed.
327 */
328 int QQmlListReference::count() const
329 {
330     if (!canCount()) return 0;
331
332     return d->property.count(&d->property);
333 }
334
335 /*!
336 \class QQmlListProperty
337 \since 5.0
338 \inmodule QtQml
339 \brief The QQmlListProperty class allows applications to expose list-like 
340 properties to QML.
341
342 QML has many list properties, where more than one object value can be assigned.
343 The use of a list property from QML looks like this:
344
345 \code
346 FruitBasket {
347     fruit: [ 
348         Apple {},
349         Orange{},
350         Banana{}
351     ]
352 }
353 \endcode
354
355 The QQmlListProperty encapsulates a group of function pointers that represet the
356 set of actions QML can perform on the list - adding items, retrieving items and
357 clearing the list.  In the future, additional operations may be supported.  All 
358 list properties must implement the append operation, but the rest are optional.
359
360 To provide a list property, a C++ class must implement the operation callbacks, 
361 and then return an appropriate QQmlListProperty value from the property getter.
362 List properties should have no setter.  In the example above, the Q_PROPERTY()
363 declarative will look like this:
364
365 \code
366 Q_PROPERTY(QQmlListProperty<Fruit> fruit READ fruit);
367 \endcode
368
369 QML list properties are typesafe - in this case \c {Fruit} is a QObject type that 
370 \c {Apple}, \c {Orange} and \c {Banana} all derive from.
371
372 The QtQuick 1 version of this class is named QDeclarativeListProperty.
373
374 \note QQmlListProperty can only be used for lists of QObject-derived object pointers.
375 */
376
377 /*!
378 \fn QQmlListProperty::QQmlListProperty() 
379 \internal
380 */
381
382 /*!
383 \fn QQmlListProperty::QQmlListProperty(QObject *object, QList<T *> &list)
384
385 Convenience constructor for making a QQmlListProperty value from an existing
386 QList \a list.  The \a list reference must remain valid for as long as \a object
387 exists.  \a object must be provided.
388
389 Generally this constructor should not be used in production code, as a 
390 writable QList violates QML's memory management rules.  However, this constructor
391 can very useful while prototyping.
392 */
393
394 /*!
395 \fn QQmlListProperty::QQmlListProperty(QObject *object, void *data,
396                                     CountFunction count, AtFunction at)
397
398 Construct a readonly QQmlListProperty from a set of operation functions.  An opaque \a data handle
399 may be passed which can be accessed from within the operation functions.  The list property
400 remains valid while \a object exists.
401 */
402
403 /*!
404 \fn QQmlListProperty::QQmlListProperty(QObject *object, void *data, AppendFunction append, 
405                                      CountFunction count, AtFunction at,
406                                      ClearFunction clear)
407
408 Construct a QQmlListProperty from a set of operation functions.  An opaque \a data handle
409 may be passed which can be accessed from within the operation functions.  The list property 
410 remains valid while \a object exists.
411
412 You can pass a null pointer, but than the list will be not designable or changeable by the debugger.
413 So provide all function, except it is not possible.
414 */
415
416 /*!
417 \typedef QQmlListProperty::AppendFunction
418
419 Synonym for \c {void (*)(QQmlListProperty<T> *property, T *value)}.
420
421 Append the \a value to the list \a property.
422 */
423
424 /*!
425 \typedef QQmlListProperty::CountFunction
426
427 Synonym for \c {int (*)(QQmlListProperty<T> *property)}.
428
429 Return the number of elements in the list \a property.
430 */
431
432 /*!
433 \fn bool QQmlListProperty::operator==(const QQmlListProperty &other) const 
434
435 Returns true if this QQmlListProperty is equal to \a other, otherwise false.
436 */
437
438 /*!
439 \typedef QQmlListProperty::AtFunction
440
441 Synonym for \c {T *(*)(QQmlListProperty<T> *property, int index)}.
442
443 Return the element at position \a index in the list \a property.
444 */
445
446 /*!
447 \typedef QQmlListProperty::ClearFunction
448
449 Synonym for \c {void (*)(QQmlListProperty<T> *property)}.
450
451 Clear the list \a property.
452 */
453
454 QT_END_NAMESPACE