diff options
Diffstat (limited to 'src/qml/qml/qqmllist.cpp')
-rw-r--r-- | src/qml/qml/qqmllist.cpp | 417 |
1 files changed, 417 insertions, 0 deletions
diff --git a/src/qml/qml/qqmllist.cpp b/src/qml/qml/qqmllist.cpp new file mode 100644 index 0000000000..00fd805ee0 --- /dev/null +++ b/src/qml/qml/qqmllist.cpp @@ -0,0 +1,417 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qqmllist.h" +#include "qqmllist_p.h" +#include "qqmlengine_p.h" +#include "qqmlproperty_p.h" + +QT_BEGIN_NAMESPACE + +QQmlListReferencePrivate::QQmlListReferencePrivate() +: propertyType(-1), refCount(1) +{ +} + +QQmlListReference QQmlListReferencePrivate::init(const QQmlListProperty<QObject> &prop, int propType, QQmlEngine *engine) +{ + QQmlListReference rv; + + if (!prop.object) return rv; + + QQmlEnginePrivate *p = engine?QQmlEnginePrivate::get(engine):0; + + int listType = p?p->listType(propType):QQmlMetaType::listType(propType); + if (listType == -1) return rv; + + rv.d = new QQmlListReferencePrivate; + rv.d->object = prop.object; + rv.d->elementType = p?p->rawMetaObjectForType(listType):QQmlMetaType::qmlType(listType)->baseMetaObject(); + rv.d->property = prop; + rv.d->propertyType = propType; + + return rv; +} + +void QQmlListReferencePrivate::addref() +{ + Q_ASSERT(refCount > 0); + ++refCount; +} + +void QQmlListReferencePrivate::release() +{ + Q_ASSERT(refCount > 0); + --refCount; + if (!refCount) + delete this; +} + +/*! +\class QQmlListReference +\since 4.7 +\module QtQml +\brief The QQmlListReference class allows the manipulation of QQmlListProperty properties. + +QQmlListReference allows C++ programs to read from, and assign values to a QML list property in a +simple and type safe way. A QQmlListReference can be created by passing an object and property +name or through a QQmlProperty instance. These two are equivalant: + +\code +QQmlListReference ref1(object, "children"); + +QQmlProperty ref2(object, "children"); +QQmlListReference ref2 = qvariant_cast<QQmlListReference>(ref2.read()); +\endcode + +Not all QML list properties support all operations. A set of methods, canAppend(), canAt(), canClear() and +canCount() allow programs to query whether an operation is supported on a given property. + +QML list properties are typesafe. Only QObject's that derive from the correct base class can be assigned to +the list. The listElementType() method can be used to query the QMetaObject of the QObject type supported. +Attempting to add objects of the incorrect type to a list property will fail. + +Like with normal lists, when accessing a list element by index, it is the callers responsibility to ensure +that it does not request an out of range element using the count() method before calling at(). +*/ + +/*! +Constructs an invalid instance. +*/ +QQmlListReference::QQmlListReference() +: d(0) +{ +} + +/*! +Constructs a QQmlListReference for \a object's \a property. If \a property is not a list +property, an invalid QQmlListReference is created. If \a object is destroyed after +the reference is constructed, it will automatically become invalid. That is, it is safe to hold +QQmlListReference instances even after \a object is deleted. + +Passing \a engine is required to access some QML created list properties. If in doubt, and an engine +is available, pass it. +*/ +QQmlListReference::QQmlListReference(QObject *object, const char *property, QQmlEngine *engine) +: d(0) +{ + if (!object || !property) return; + + QQmlPropertyData local; + QQmlPropertyData *data = + QQmlPropertyCache::property(engine, object, QLatin1String(property), local); + + if (!data || !data->isQList()) return; + + QQmlEnginePrivate *p = engine?QQmlEnginePrivate::get(engine):0; + + int listType = p?p->listType(data->propType):QQmlMetaType::listType(data->propType); + if (listType == -1) return; + + d = new QQmlListReferencePrivate; + d->object = object; + d->elementType = p?p->rawMetaObjectForType(listType):QQmlMetaType::qmlType(listType)->baseMetaObject(); + d->propertyType = data->propType; + + void *args[] = { &d->property, 0 }; + QMetaObject::metacall(object, QMetaObject::ReadProperty, data->coreIndex, args); +} + +/*! \internal */ +QQmlListReference::QQmlListReference(const QQmlListReference &o) +: d(o.d) +{ + if (d) d->addref(); +} + +/*! \internal */ +QQmlListReference &QQmlListReference::operator=(const QQmlListReference &o) +{ + if (o.d) o.d->addref(); + if (d) d->release(); + d = o.d; + return *this; +} + +/*! \internal */ +QQmlListReference::~QQmlListReference() +{ + if (d) d->release(); +} + +/*! +Returns true if the instance refers to a valid list property, otherwise false. +*/ +bool QQmlListReference::isValid() const +{ + return d && d->object; +} + +/*! +Returns the list property's object. Returns 0 if the reference is invalid. +*/ +QObject *QQmlListReference::object() const +{ + if (isValid()) return d->object; + else return 0; +} + +/*! +Returns the QMetaObject for the elements stored in the list property. Returns 0 if the reference +is invalid. + +The QMetaObject can be used ahead of time to determine whether a given instance can be added +to a list. +*/ +const QMetaObject *QQmlListReference::listElementType() const +{ + if (isValid()) return d->elementType; + else return 0; +} + +/*! +Returns true if the list property can be appended to, otherwise false. Returns false if the +reference is invalid. + +\sa append() +*/ +bool QQmlListReference::canAppend() const +{ + return (isValid() && d->property.append); +} + +/*! +Returns true if the list property can queried by index, otherwise false. Returns false if the +reference is invalid. + +\sa at() +*/ +bool QQmlListReference::canAt() const +{ + return (isValid() && d->property.at); +} + +/*! +Returns true if the list property can be cleared, otherwise false. Returns false if the +reference is invalid. + +\sa clear() +*/ +bool QQmlListReference::canClear() const +{ + return (isValid() && d->property.clear); +} + +/*! +Returns true if the list property can be queried for its element count, otherwise false. +Returns false if the reference is invalid. + +\sa count() +*/ +bool QQmlListReference::canCount() const +{ + return (isValid() && d->property.count); +} + +/*! +Appends \a object to the list. Returns true if the operation succeeded, otherwise false. + +\sa canAppend() +*/ +bool QQmlListReference::append(QObject *object) const +{ + if (!canAppend()) return false; + + if (object && !QQmlPropertyPrivate::canConvert(object->metaObject(), d->elementType)) + return false; + + d->property.append(&d->property, object); + + return true; +} + +/*! +Returns the list element at \a index, or 0 if the operation failed. + +\sa canAt() +*/ +QObject *QQmlListReference::at(int index) const +{ + if (!canAt()) return 0; + + return d->property.at(&d->property, index); +} + +/*! +Clears the list. Returns true if the operation succeeded, otherwise false. + +\sa canClear() +*/ +bool QQmlListReference::clear() const +{ + if (!canClear()) return false; + + d->property.clear(&d->property); + + return true; +} + +/*! +Returns the number of objects in the list, or 0 if the operation failed. +*/ +int QQmlListReference::count() const +{ + if (!canCount()) return 0; + + return d->property.count(&d->property); +} + +/*! +\class QQmlListProperty +\since 4.7 +\brief The QQmlListProperty class allows applications to expose list-like +properties to QML. + +QML has many list properties, where more than one object value can be assigned. +The use of a list property from QML looks like this: + +\code +FruitBasket { + fruit: [ + Apple {}, + Orange{}, + Banana{} + ] +} +\endcode + +The QQmlListProperty encapsulates a group of function pointers that represet the +set of actions QML can perform on the list - adding items, retrieving items and +clearing the list. In the future, additional operations may be supported. All +list properties must implement the append operation, but the rest are optional. + +To provide a list property, a C++ class must implement the operation callbacks, +and then return an appropriate QQmlListProperty value from the property getter. +List properties should have no setter. In the example above, the Q_PROPERTY() +declarative will look like this: + +\code +Q_PROPERTY(QQmlListProperty<Fruit> fruit READ fruit); +\endcode + +QML list properties are typesafe - in this case \c {Fruit} is a QObject type that +\c {Apple}, \c {Orange} and \c {Banana} all derive from. + +\note QQmlListProperty can only be used for lists of QObject-derived object pointers. + +\sa {Object and List Property Types} + +*/ + +/*! +\fn QQmlListProperty::QQmlListProperty() +\internal +*/ + +/*! +\fn QQmlListProperty::QQmlListProperty(QObject *object, QList<T *> &list) + +Convenience constructor for making a QQmlListProperty value from an existing +QList \a list. The \a list reference must remain valid for as long as \a object +exists. \a object must be provided. + +Generally this constructor should not be used in production code, as a +writable QList violates QML's memory management rules. However, this constructor +can very useful while prototyping. +*/ + +/*! +\fn QQmlListProperty::QQmlListProperty(QObject *object, void *data, AppendFunction append, + CountFunction count = 0, AtFunction at = 0, + ClearFunction clear = 0) + +Construct a QQmlListProperty from a set of operation functions. An opaque \a data handle +may be passed which can be accessed from within the operation functions. The list property +remains valid while \a object exists. + +The \a append operation is compulsory and must be provided, while the \a count, \a at and +\a clear methods are optional. +*/ + +/*! +\typedef QQmlListProperty::AppendFunction + +Synonym for \c {void (*)(QQmlListProperty<T> *property, T *value)}. + +Append the \a value to the list \a property. +*/ + +/*! +\typedef QQmlListProperty::CountFunction + +Synonym for \c {int (*)(QQmlListProperty<T> *property)}. + +Return the number of elements in the list \a property. +*/ + +/*! +\fn bool QQmlListProperty::operator==(const QQmlListProperty &other) const + +Returns true if this QQmlListProperty is equal to \a other, otherwise false. +*/ + +/*! +\typedef QQmlListProperty::AtFunction + +Synonym for \c {T *(*)(QQmlListProperty<T> *property, int index)}. + +Return the element at position \a index in the list \a property. +*/ + +/*! +\typedef QQmlListProperty::ClearFunction + +Synonym for \c {void (*)(QQmlListProperty<T> *property)}. + +Clear the list \a property. +*/ + +QT_END_NAMESPACE |