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