src/declarative/qml/qdeclarativelist.cpp
branchGCC_SURGE
changeset 31 5daf16870df6
parent 30 5dc02b23752f
child 33 3e2da88830cd
equal deleted inserted replaced
27:93b982ccede2 31:5daf16870df6
       
     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 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    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 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    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 
       
    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 \brief The QDeclarativeListReference class allows the manipulation of QDeclarativeListProperty properties.
       
    92 
       
    93 QDeclarativeListReference allows C++ programs to read from, and assign values to a QML list property in a
       
    94 simple and type safe way.  A QDeclarativeListReference can be created by passing an object and property
       
    95 name or through a QDeclarativeProperty instance.  These two are equivalant:
       
    96 
       
    97 \code
       
    98 QDeclarativeListReference ref1(object, "children");
       
    99 
       
   100 QDeclarativeProperty ref2(object, "children");
       
   101 QDeclarativeListReference ref2 = qvariant_cast<QDeclarativeListReference>(ref2.read());
       
   102 \endcode
       
   103 
       
   104 Not all QML list properties support all operations.  A set of methods, canAppend(), canAt(), canClear() and
       
   105 canCount() allow programs to query whether an operation is supported on a given property.
       
   106 
       
   107 QML list properties are typesafe.  Only QObject's that derive from the correct base class can be assigned to
       
   108 the list.  The listElementType() method can be used to query the QMetaObject of the QObject type supported.
       
   109 Attempting to add objects of the incorrect type to a list property will fail.
       
   110 
       
   111 Like with normal lists, when accessing a list element by index, it is the callers responsibility to ensure 
       
   112 that it does not request an out of range element using the count() method before calling at().
       
   113 */
       
   114 
       
   115 /*!
       
   116 Constructs an invalid instance.
       
   117 */
       
   118 QDeclarativeListReference::QDeclarativeListReference()
       
   119 : d(0)
       
   120 {
       
   121 }
       
   122 
       
   123 /*!
       
   124 Constructs a QDeclarativeListReference for \a object's \a property.  If \a property is not a list
       
   125 property, an invalid QDeclarativeListReference is created.  If \a object is destroyed after 
       
   126 the reference is constructed, it will automatically become invalid.  That is, it is safe to hold
       
   127 QDeclarativeListReference instances even after \a object is deleted.
       
   128 
       
   129 Passing \a engine is required to access some QML created list properties.  If in doubt, and an engine
       
   130 is available, pass it.
       
   131 */
       
   132 QDeclarativeListReference::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 */
       
   158 QDeclarativeListReference::QDeclarativeListReference(const QDeclarativeListReference &o)
       
   159 : d(o.d)
       
   160 {
       
   161     if (d) d->addref();
       
   162 }
       
   163 
       
   164 /*! \internal */
       
   165 QDeclarativeListReference &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 */
       
   174 QDeclarativeListReference::~QDeclarativeListReference()
       
   175 {
       
   176     if (d) d->release();
       
   177 }
       
   178 
       
   179 /*!
       
   180 Returns true if the instance refers to a valid list property, otherwise false.
       
   181 */
       
   182 bool QDeclarativeListReference::isValid() const
       
   183 {
       
   184     return d && d->object;
       
   185 }
       
   186 
       
   187 /*!
       
   188 Returns the list property's object.  Returns 0 if the reference is invalid.
       
   189 */
       
   190 QObject *QDeclarativeListReference::object() const
       
   191 {
       
   192     if (isValid()) return d->object;
       
   193     else return 0;
       
   194 }
       
   195 
       
   196 /*!
       
   197 Returns the QMetaObject for the elements stored in the list property.  Returns 0 if the reference
       
   198 is invalid.
       
   199 
       
   200 The QMetaObject can be used ahead of time to determine whether a given instance can be added
       
   201 to a list.
       
   202 */
       
   203 const QMetaObject *QDeclarativeListReference::listElementType() const
       
   204 {
       
   205     if (isValid()) return d->elementType;
       
   206     else return 0;
       
   207 }
       
   208 
       
   209 /*!
       
   210 Returns true if the list property can be appended to, otherwise false.  Returns false if the
       
   211 reference is invalid.
       
   212 
       
   213 \sa append()
       
   214 */
       
   215 bool QDeclarativeListReference::canAppend() const
       
   216 {
       
   217     return (isValid() && d->property.append);
       
   218 }
       
   219 
       
   220 /*!
       
   221 Returns true if the list property can queried by index, otherwise false.  Returns false if the
       
   222 reference is invalid.
       
   223 
       
   224 \sa at()
       
   225 */
       
   226 bool QDeclarativeListReference::canAt() const
       
   227 {
       
   228     return (isValid() && d->property.at);
       
   229 }
       
   230 
       
   231 /*!
       
   232 Returns true if the list property can be cleared, otherwise false.  Returns false if the
       
   233 reference is invalid.
       
   234 
       
   235 \sa clear()
       
   236 */
       
   237 bool QDeclarativeListReference::canClear() const
       
   238 {
       
   239     return (isValid() && d->property.clear);
       
   240 }
       
   241 
       
   242 /*!
       
   243 Returns true if the list property can be queried for its element count, otherwise false.  
       
   244 Returns false if the reference is invalid.
       
   245 
       
   246 \sa count()
       
   247 */
       
   248 bool QDeclarativeListReference::canCount() const
       
   249 {
       
   250     return (isValid() && d->property.count);
       
   251 }
       
   252 
       
   253 /*!
       
   254 Appends \a object to the list.  Returns true if the operation succeeded, otherwise false.
       
   255 
       
   256 \sa canAppend()
       
   257 */
       
   258 bool 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 /*!
       
   271 Returns the list element at \a index, or 0 if the operation failed.
       
   272 
       
   273 \sa canAt()
       
   274 */
       
   275 QObject *QDeclarativeListReference::at(int index) const
       
   276 {
       
   277     if (!canAt()) return 0;
       
   278 
       
   279     return d->property.at(&d->property, index);
       
   280 }
       
   281 
       
   282 /*!
       
   283 Clears the list.  Returns true if the operation succeeded, otherwise false.
       
   284 
       
   285 \sa canClear()
       
   286 */
       
   287 bool QDeclarativeListReference::clear() const
       
   288 {
       
   289     if (!canClear()) return false;
       
   290 
       
   291     d->property.clear(&d->property);
       
   292 
       
   293     return true;
       
   294 }
       
   295 
       
   296 /*!
       
   297 Returns the number of objects in the list, or 0 if the operation failed.
       
   298 */
       
   299 int 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 explose list-like 
       
   310 properties to QML.
       
   311 
       
   312 QML has many list properties, where more than one object value can be assigned.
       
   313 The use of a list property from QML looks like this:
       
   314 
       
   315 \code
       
   316 FruitBasket {
       
   317     fruit: [ 
       
   318         Apple {},
       
   319         Orange{},
       
   320         Banana{}
       
   321     ]
       
   322 }
       
   323 \endcode
       
   324 
       
   325 The QDeclarativeListProperty encapsulates a group of function pointers that represet the
       
   326 set of actions QML can perform on the list - adding items, retrieving items and
       
   327 clearing the list.  In the future, additional operations may be supported.  All 
       
   328 list properties must implement the append operation, but the rest are optional.
       
   329 
       
   330 To provide a list property, a C++ class must implement the operation callbacks, 
       
   331 and then return an appropriate QDeclarativeListProperty value from the property getter.
       
   332 List properties should have no setter.  In the example above, the Q_PROPERTY()
       
   333 declarative will look like this:
       
   334 
       
   335 \code
       
   336 Q_PROPERTY(QDeclarativeListProperty<Fruit> fruit READ fruit);
       
   337 \endcode
       
   338 
       
   339 QML 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 */
       
   345 
       
   346 /*!
       
   347 \fn QDeclarativeListProperty::QDeclarativeListProperty() 
       
   348 \internal
       
   349 */
       
   350 
       
   351 /*!
       
   352 \fn QDeclarativeListProperty::QDeclarativeListProperty(QObject *object, QList<T *> &list)
       
   353 
       
   354 Convenience constructor for making a QDeclarativeListProperty value from an existing
       
   355 QList \a list.  The \a list reference must remain valid for as long as \a object
       
   356 exists.  \a object must be provided.
       
   357 
       
   358 Generally this constructor should not be used in production code, as a 
       
   359 writable QList violates QML's memory management rules.  However, this constructor
       
   360 can very useful while prototyping.
       
   361 */
       
   362 
       
   363 /*!
       
   364 \fn QDeclarativeListProperty::QDeclarativeListProperty(QObject *object, void *data, AppendFunction append, 
       
   365                                      CountFunction count = 0, AtFunction at = 0, 
       
   366                                      ClearFunction clear = 0)
       
   367 
       
   368 Construct a QDeclarativeListProperty from a set of operation functions.  An opaque \a data handle
       
   369 may be passed which can be accessed from within the operation functions.  The list property 
       
   370 remains valid while \a object exists.
       
   371 
       
   372 The \a append operation is compulsory and must be provided, while the \a count, \a at and
       
   373 \a clear methods are optional.
       
   374 */
       
   375 
       
   376 /*!
       
   377 \typedef QDeclarativeListProperty::AppendFunction
       
   378 
       
   379 Synonym for \c {void (*)(QDeclarativeListProperty<T> *property, T *value)}.
       
   380 
       
   381 Append the \a value to the list \a property.
       
   382 */
       
   383 
       
   384 /*!
       
   385 \typedef QDeclarativeListProperty::CountFunction
       
   386 
       
   387 Synonym for \c {int (*)(QDeclarativeListProperty<T> *property)}.
       
   388 
       
   389 Return the number of elements in the list \a property.
       
   390 */
       
   391 
       
   392 /*!
       
   393 \fn bool QDeclarativeListProperty::operator==(const QDeclarativeListProperty &other) const 
       
   394 
       
   395 Returns true if this QDeclarativeListProperty is equal to \a other, otherwise false.
       
   396 */
       
   397 
       
   398 /*!
       
   399 \typedef QDeclarativeListProperty::AtFunction
       
   400 
       
   401 Synonym for \c {T *(*)(QDeclarativeListProperty<T> *property, int index)}.
       
   402 
       
   403 Return the element at position \a index in the list \a property.
       
   404 */
       
   405 
       
   406 /*!
       
   407 \typedef QDeclarativeListProperty::ClearFunction
       
   408 
       
   409 Synonym for \c {void (*)(QDeclarativeListProperty<T> *property)}.
       
   410 
       
   411 Clear the list \a property.
       
   412 */
       
   413 
       
   414 QT_END_NAMESPACE