source: trunk/src/declarative/qml/qdeclarativelist.cpp

Last change on this file was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 12.5 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 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** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
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** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at qt-info@nokia.com.
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qdeclarativelist.h"
43#include "private/qdeclarativelist_p.h"
44#include "private/qdeclarativeengine_p.h"
45#include "private/qdeclarativeproperty_p.h"
46
47QT_BEGIN_NAMESPACE
48
49QDeclarativeListReferencePrivate::QDeclarativeListReferencePrivate()
50: propertyType(-1), refCount(1)
51{
52}
53
54QDeclarativeListReference 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
74void QDeclarativeListReferencePrivate::addref()
75{
76 Q_ASSERT(refCount > 0);
77 ++refCount;
78}
79
80void 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\brief The QDeclarativeListReference class allows the manipulation of QDeclarativeListProperty properties.
92
93QDeclarativeListReference allows C++ programs to read from, and assign values to a QML list property in a
94simple and type safe way. A QDeclarativeListReference can be created by passing an object and property
95name or through a QDeclarativeProperty instance. These two are equivalant:
96
97\code
98QDeclarativeListReference ref1(object, "children");
99
100QDeclarativeProperty ref2(object, "children");
101QDeclarativeListReference ref2 = qvariant_cast<QDeclarativeListReference>(ref2.read());
102\endcode
103
104Not all QML list properties support all operations. A set of methods, canAppend(), canAt(), canClear() and
105canCount() allow programs to query whether an operation is supported on a given property.
106
107QML list properties are typesafe. Only QObject's that derive from the correct base class can be assigned to
108the list. The listElementType() method can be used to query the QMetaObject of the QObject type supported.
109Attempting to add objects of the incorrect type to a list property will fail.
110
111Like with normal lists, when accessing a list element by index, it is the callers responsibility to ensure
112that it does not request an out of range element using the count() method before calling at().
113*/
114
115/*!
116Constructs an invalid instance.
117*/
118QDeclarativeListReference::QDeclarativeListReference()
119: d(0)
120{
121}
122
123/*!
124Constructs a QDeclarativeListReference for \a object's \a property. If \a property is not a list
125property, an invalid QDeclarativeListReference is created. If \a object is destroyed after
126the reference is constructed, it will automatically become invalid. That is, it is safe to hold
127QDeclarativeListReference instances even after \a object is deleted.
128
129Passing \a engine is required to access some QML created list properties. If in doubt, and an engine
130is available, pass it.
131*/
132QDeclarativeListReference::QDeclarativeListReference(QObject *object, const char *property, QDeclarativeEngine *engine)
133: d(0)
134{
135 if (!object || !property) return;
136
137 QDeclarativePropertyCache::Data local;
138 QDeclarativePropertyCache::Data *data =
139 QDeclarativePropertyCache::property(engine, object, QLatin1String(property), local);
140
141 if (!data || !(data->flags & QDeclarativePropertyCache::Data::IsQList)) return;
142
143 QDeclarativeEnginePrivate *p = engine?QDeclarativeEnginePrivate::get(engine):0;
144
145 int listType = p?p->listType(data->propType):QDeclarativeMetaType::listType(data->propType);
146 if (listType == -1) return;
147
148 d = new QDeclarativeListReferencePrivate;
149 d->object = object;
150 d->elementType = p?p->rawMetaObjectForType(listType):QDeclarativeMetaType::qmlType(listType)->baseMetaObject();
151 d->propertyType = data->propType;
152
153 void *args[] = { &d->property, 0 };
154 QMetaObject::metacall(object, QMetaObject::ReadProperty, data->coreIndex, args);
155}
156
157/*! \internal */
158QDeclarativeListReference::QDeclarativeListReference(const QDeclarativeListReference &o)
159: d(o.d)
160{
161 if (d) d->addref();
162}
163
164/*! \internal */
165QDeclarativeListReference &QDeclarativeListReference::operator=(const QDeclarativeListReference &o)
166{
167 if (o.d) o.d->addref();
168 if (d) d->release();
169 d = o.d;
170 return *this;
171}
172
173/*! \internal */
174QDeclarativeListReference::~QDeclarativeListReference()
175{
176 if (d) d->release();
177}
178
179/*!
180Returns true if the instance refers to a valid list property, otherwise false.
181*/
182bool QDeclarativeListReference::isValid() const
183{
184 return d && d->object;
185}
186
187/*!
188Returns the list property's object. Returns 0 if the reference is invalid.
189*/
190QObject *QDeclarativeListReference::object() const
191{
192 if (isValid()) return d->object;
193 else return 0;
194}
195
196/*!
197Returns the QMetaObject for the elements stored in the list property. Returns 0 if the reference
198is invalid.
199
200The QMetaObject can be used ahead of time to determine whether a given instance can be added
201to a list.
202*/
203const QMetaObject *QDeclarativeListReference::listElementType() const
204{
205 if (isValid()) return d->elementType;
206 else return 0;
207}
208
209/*!
210Returns true if the list property can be appended to, otherwise false. Returns false if the
211reference is invalid.
212
213\sa append()
214*/
215bool QDeclarativeListReference::canAppend() const
216{
217 return (isValid() && d->property.append);
218}
219
220/*!
221Returns true if the list property can queried by index, otherwise false. Returns false if the
222reference is invalid.
223
224\sa at()
225*/
226bool QDeclarativeListReference::canAt() const
227{
228 return (isValid() && d->property.at);
229}
230
231/*!
232Returns true if the list property can be cleared, otherwise false. Returns false if the
233reference is invalid.
234
235\sa clear()
236*/
237bool QDeclarativeListReference::canClear() const
238{
239 return (isValid() && d->property.clear);
240}
241
242/*!
243Returns true if the list property can be queried for its element count, otherwise false.
244Returns false if the reference is invalid.
245
246\sa count()
247*/
248bool QDeclarativeListReference::canCount() const
249{
250 return (isValid() && d->property.count);
251}
252
253/*!
254Appends \a object to the list. Returns true if the operation succeeded, otherwise false.
255
256\sa canAppend()
257*/
258bool QDeclarativeListReference::append(QObject *object) const
259{
260 if (!canAppend()) return false;
261
262 if (object && !QDeclarativePropertyPrivate::canConvert(object->metaObject(), d->elementType))
263 return false;
264
265 d->property.append(&d->property, object);
266
267 return true;
268}
269
270/*!
271Returns the list element at \a index, or 0 if the operation failed.
272
273\sa canAt()
274*/
275QObject *QDeclarativeListReference::at(int index) const
276{
277 if (!canAt()) return 0;
278
279 return d->property.at(&d->property, index);
280}
281
282/*!
283Clears the list. Returns true if the operation succeeded, otherwise false.
284
285\sa canClear()
286*/
287bool QDeclarativeListReference::clear() const
288{
289 if (!canClear()) return false;
290
291 d->property.clear(&d->property);
292
293 return true;
294}
295
296/*!
297Returns the number of objects in the list, or 0 if the operation failed.
298*/
299int QDeclarativeListReference::count() const
300{
301 if (!canCount()) return 0;
302
303 return d->property.count(&d->property);
304}
305
306/*!
307\class QDeclarativeListProperty
308\since 4.7
309\brief The QDeclarativeListProperty class allows applications to expose list-like
310properties to QML.
311
312QML has many list properties, where more than one object value can be assigned.
313The use of a list property from QML looks like this:
314
315\code
316FruitBasket {
317 fruit: [
318 Apple {},
319 Orange{},
320 Banana{}
321 ]
322}
323\endcode
324
325The QDeclarativeListProperty encapsulates a group of function pointers that represet the
326set of actions QML can perform on the list - adding items, retrieving items and
327clearing the list. In the future, additional operations may be supported. All
328list properties must implement the append operation, but the rest are optional.
329
330To provide a list property, a C++ class must implement the operation callbacks,
331and then return an appropriate QDeclarativeListProperty value from the property getter.
332List properties should have no setter. In the example above, the Q_PROPERTY()
333declarative will look like this:
334
335\code
336Q_PROPERTY(QDeclarativeListProperty<Fruit> fruit READ fruit);
337\endcode
338
339QML list properties are typesafe - in this case \c {Fruit} is a QObject type that
340\c {Apple}, \c {Orange} and \c {Banana} all derive from.
341
342\note QDeclarativeListProperty can only be used for lists of QObject-derived object pointers.
343
344\sa {Object and List Property Types}
345
346*/
347
348/*!
349\fn QDeclarativeListProperty::QDeclarativeListProperty()
350\internal
351*/
352
353/*!
354\fn QDeclarativeListProperty::QDeclarativeListProperty(QObject *object, QList<T *> &list)
355
356Convenience constructor for making a QDeclarativeListProperty value from an existing
357QList \a list. The \a list reference must remain valid for as long as \a object
358exists. \a object must be provided.
359
360Generally this constructor should not be used in production code, as a
361writable QList violates QML's memory management rules. However, this constructor
362can very useful while prototyping.
363*/
364
365/*!
366\fn QDeclarativeListProperty::QDeclarativeListProperty(QObject *object, void *data, AppendFunction append,
367 CountFunction count = 0, AtFunction at = 0,
368 ClearFunction clear = 0)
369
370Construct a QDeclarativeListProperty from a set of operation functions. An opaque \a data handle
371may be passed which can be accessed from within the operation functions. The list property
372remains valid while \a object exists.
373
374The \a append operation is compulsory and must be provided, while the \a count, \a at and
375\a clear methods are optional.
376*/
377
378/*!
379\typedef QDeclarativeListProperty::AppendFunction
380
381Synonym for \c {void (*)(QDeclarativeListProperty<T> *property, T *value)}.
382
383Append the \a value to the list \a property.
384*/
385
386/*!
387\typedef QDeclarativeListProperty::CountFunction
388
389Synonym for \c {int (*)(QDeclarativeListProperty<T> *property)}.
390
391Return the number of elements in the list \a property.
392*/
393
394/*!
395\fn bool QDeclarativeListProperty::operator==(const QDeclarativeListProperty &other) const
396
397Returns true if this QDeclarativeListProperty is equal to \a other, otherwise false.
398*/
399
400/*!
401\typedef QDeclarativeListProperty::AtFunction
402
403Synonym for \c {T *(*)(QDeclarativeListProperty<T> *property, int index)}.
404
405Return the element at position \a index in the list \a property.
406*/
407
408/*!
409\typedef QDeclarativeListProperty::ClearFunction
410
411Synonym for \c {void (*)(QDeclarativeListProperty<T> *property)}.
412
413Clear the list \a property.
414*/
415
416QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.