1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
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.
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.
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.
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.
40 ****************************************************************************/
42 #include "qdeclarativelist.h"
43 #include "qdeclarativelist_p.h"
44 #include "qdeclarativeengine_p.h"
45 #include "qdeclarativeproperty_p.h"
49 QDeclarativeListReferencePrivate::QDeclarativeListReferencePrivate()
50 : propertyType(-1), refCount(1)
54 QDeclarativeListReference QDeclarativeListReferencePrivate::init(const QDeclarativeListProperty<QObject> &prop, int propType, QDeclarativeEngine *engine)
56 QDeclarativeListReference rv;
58 if (!prop.object) return rv;
60 QDeclarativeEnginePrivate *p = engine?QDeclarativeEnginePrivate::get(engine):0;
62 int listType = p?p->listType(propType):QDeclarativeMetaType::listType(propType);
63 if (listType == -1) return rv;
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;
74 void QDeclarativeListReferencePrivate::addref()
76 Q_ASSERT(refCount > 0);
80 void QDeclarativeListReferencePrivate::release()
82 Q_ASSERT(refCount > 0);
89 \class QDeclarativeListReference
92 \brief The QDeclarativeListReference class allows the manipulation of QDeclarativeListProperty properties.
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:
99 QDeclarativeListReference ref1(object, "children");
101 QDeclarativeProperty ref2(object, "children");
102 QDeclarativeListReference ref2 = qvariant_cast<QDeclarativeListReference>(ref2.read());
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.
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.
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().
117 Constructs an invalid instance.
119 QDeclarativeListReference::QDeclarativeListReference()
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.
130 Passing \a engine is required to access some QML created list properties. If in doubt, and an engine
131 is available, pass it.
133 QDeclarativeListReference::QDeclarativeListReference(QObject *object, const char *property, QDeclarativeEngine *engine)
136 if (!object || !property) return;
138 QDeclarativePropertyData local;
139 QDeclarativePropertyData *data =
140 QDeclarativePropertyCache::property(engine, object, QLatin1String(property), local);
142 if (!data || !data->isQList()) return;
144 QDeclarativeEnginePrivate *p = engine?QDeclarativeEnginePrivate::get(engine):0;
146 int listType = p?p->listType(data->propType):QDeclarativeMetaType::listType(data->propType);
147 if (listType == -1) return;
149 d = new QDeclarativeListReferencePrivate;
151 d->elementType = p?p->rawMetaObjectForType(listType):QDeclarativeMetaType::qmlType(listType)->baseMetaObject();
152 d->propertyType = data->propType;
154 void *args[] = { &d->property, 0 };
155 QMetaObject::metacall(object, QMetaObject::ReadProperty, data->coreIndex, args);
159 QDeclarativeListReference::QDeclarativeListReference(const QDeclarativeListReference &o)
166 QDeclarativeListReference &QDeclarativeListReference::operator=(const QDeclarativeListReference &o)
168 if (o.d) o.d->addref();
175 QDeclarativeListReference::~QDeclarativeListReference()
181 Returns true if the instance refers to a valid list property, otherwise false.
183 bool QDeclarativeListReference::isValid() const
185 return d && d->object;
189 Returns the list property's object. Returns 0 if the reference is invalid.
191 QObject *QDeclarativeListReference::object() const
193 if (isValid()) return d->object;
198 Returns the QMetaObject for the elements stored in the list property. Returns 0 if the reference
201 The QMetaObject can be used ahead of time to determine whether a given instance can be added
204 const QMetaObject *QDeclarativeListReference::listElementType() const
206 if (isValid()) return d->elementType;
211 Returns true if the list property can be appended to, otherwise false. Returns false if the
212 reference is invalid.
216 bool QDeclarativeListReference::canAppend() const
218 return (isValid() && d->property.append);
222 Returns true if the list property can queried by index, otherwise false. Returns false if the
223 reference is invalid.
227 bool QDeclarativeListReference::canAt() const
229 return (isValid() && d->property.at);
233 Returns true if the list property can be cleared, otherwise false. Returns false if the
234 reference is invalid.
238 bool QDeclarativeListReference::canClear() const
240 return (isValid() && d->property.clear);
244 Returns true if the list property can be queried for its element count, otherwise false.
245 Returns false if the reference is invalid.
249 bool QDeclarativeListReference::canCount() const
251 return (isValid() && d->property.count);
255 Appends \a object to the list. Returns true if the operation succeeded, otherwise false.
259 bool QDeclarativeListReference::append(QObject *object) const
261 if (!canAppend()) return false;
263 if (object && !QDeclarativePropertyPrivate::canConvert(object->metaObject(), d->elementType))
266 d->property.append(&d->property, object);
272 Returns the list element at \a index, or 0 if the operation failed.
276 QObject *QDeclarativeListReference::at(int index) const
278 if (!canAt()) return 0;
280 return d->property.at(&d->property, index);
284 Clears the list. Returns true if the operation succeeded, otherwise false.
288 bool QDeclarativeListReference::clear() const
290 if (!canClear()) return false;
292 d->property.clear(&d->property);
298 Returns the number of objects in the list, or 0 if the operation failed.
300 int QDeclarativeListReference::count() const
302 if (!canCount()) return 0;
304 return d->property.count(&d->property);
308 \class QDeclarativeListProperty
310 \brief The QDeclarativeListProperty class allows applications to expose list-like
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:
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.
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:
337 Q_PROPERTY(QDeclarativeListProperty<Fruit> fruit READ fruit);
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.
343 \note QDeclarativeListProperty can only be used for lists of QObject-derived object pointers.
345 \sa {Object and List Property Types}
350 \fn QDeclarativeListProperty::QDeclarativeListProperty()
355 \fn QDeclarativeListProperty::QDeclarativeListProperty(QObject *object, QList<T *> &list)
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.
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.
367 \fn QDeclarativeListProperty::QDeclarativeListProperty(QObject *object, void *data, AppendFunction append,
368 CountFunction count = 0, AtFunction at = 0,
369 ClearFunction clear = 0)
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.
375 The \a append operation is compulsory and must be provided, while the \a count, \a at and
376 \a clear methods are optional.
380 \typedef QDeclarativeListProperty::AppendFunction
382 Synonym for \c {void (*)(QDeclarativeListProperty<T> *property, T *value)}.
384 Append the \a value to the list \a property.
388 \typedef QDeclarativeListProperty::CountFunction
390 Synonym for \c {int (*)(QDeclarativeListProperty<T> *property)}.
392 Return the number of elements in the list \a property.
396 \fn bool QDeclarativeListProperty::operator==(const QDeclarativeListProperty &other) const
398 Returns true if this QDeclarativeListProperty is equal to \a other, otherwise false.
402 \typedef QDeclarativeListProperty::AtFunction
404 Synonym for \c {T *(*)(QDeclarativeListProperty<T> *property, int index)}.
406 Return the element at position \a index in the list \a property.
410 \typedef QDeclarativeListProperty::ClearFunction
412 Synonym for \c {void (*)(QDeclarativeListProperty<T> *property)}.
414 Clear the list \a property.