src/declarative/graphicsitems/qdeclarativevisualitemmodel.cpp
changeset 30 5dc02b23752f
child 33 3e2da88830cd
equal deleted inserted replaced
29:b72c6db6890b 30:5dc02b23752f
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2010 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 "private/qdeclarativevisualitemmodel_p.h"
       
    43 
       
    44 #include "qdeclarativeitem.h"
       
    45 
       
    46 #include <qdeclarativecontext.h>
       
    47 #include <qdeclarativecontext_p.h>
       
    48 #include <qdeclarativeengine.h>
       
    49 #include <qdeclarativeexpression.h>
       
    50 #include <qdeclarativepackage_p.h>
       
    51 #include <qdeclarativeopenmetaobject_p.h>
       
    52 #include <qdeclarativelistaccessor_p.h>
       
    53 #include <qdeclarativeinfo.h>
       
    54 #include <qdeclarativedata_p.h>
       
    55 #include <qdeclarativepropertycache_p.h>
       
    56 #include <qdeclarativeguard_p.h>
       
    57 #include <qdeclarativeglobal_p.h>
       
    58 
       
    59 #include <qgraphicsscene.h>
       
    60 #include <qlistmodelinterface_p.h>
       
    61 #include <qhash.h>
       
    62 #include <qlist.h>
       
    63 #include <qmetaobjectbuilder_p.h>
       
    64 #include <QtCore/qdebug.h>
       
    65 
       
    66 #include <private/qobject_p.h>
       
    67 
       
    68 QT_BEGIN_NAMESPACE
       
    69 
       
    70 QHash<QObject*, QDeclarativeVisualItemModelAttached*> QDeclarativeVisualItemModelAttached::attachedProperties;
       
    71 
       
    72 
       
    73 class QDeclarativeVisualItemModelPrivate : public QObjectPrivate
       
    74 {
       
    75     Q_DECLARE_PUBLIC(QDeclarativeVisualItemModel)
       
    76 public:
       
    77     QDeclarativeVisualItemModelPrivate() : QObjectPrivate() {}
       
    78 
       
    79     static void children_append(QDeclarativeListProperty<QDeclarativeItem> *prop, QDeclarativeItem *item) {
       
    80         item->QObject::setParent(prop->object);
       
    81         static_cast<QDeclarativeVisualItemModelPrivate *>(prop->data)->children.append(item);
       
    82         static_cast<QDeclarativeVisualItemModelPrivate *>(prop->data)->itemAppended();
       
    83         static_cast<QDeclarativeVisualItemModelPrivate *>(prop->data)->emitChildrenChanged();
       
    84     }
       
    85 
       
    86     static int children_count(QDeclarativeListProperty<QDeclarativeItem> *prop) {
       
    87         return static_cast<QDeclarativeVisualItemModelPrivate *>(prop->data)->children.count();
       
    88     }
       
    89 
       
    90     static QDeclarativeItem *children_at(QDeclarativeListProperty<QDeclarativeItem> *prop, int index) {
       
    91         return static_cast<QDeclarativeVisualItemModelPrivate *>(prop->data)->children.at(index);
       
    92     }
       
    93 
       
    94     void itemAppended() {
       
    95         Q_Q(QDeclarativeVisualItemModel);
       
    96         QDeclarativeVisualItemModelAttached *attached = QDeclarativeVisualItemModelAttached::properties(children.last());
       
    97         attached->setIndex(children.count()-1);
       
    98         emit q->itemsInserted(children.count()-1, 1);
       
    99         emit q->countChanged();
       
   100     }
       
   101 
       
   102     void emitChildrenChanged() {
       
   103         Q_Q(QDeclarativeVisualItemModel);
       
   104         emit q->childrenChanged();
       
   105     }
       
   106 
       
   107     QList<QDeclarativeItem *> children;
       
   108 };
       
   109 
       
   110 
       
   111 /*!
       
   112     \qmlclass VisualItemModel QDeclarativeVisualItemModel
       
   113   \since 4.7
       
   114     \brief The VisualItemModel allows items to be provided to a view.
       
   115 
       
   116     The children of the VisualItemModel are provided in a model which
       
   117     can be used in a view.  Note that no delegate should be
       
   118     provided to a view since the VisualItemModel contains the
       
   119     visual delegate (items).
       
   120 
       
   121     An item can determine its index within the
       
   122     model via the VisualItemModel.index attached property.
       
   123 
       
   124     The example below places three colored rectangles in a ListView.
       
   125     \code
       
   126     Item {
       
   127         VisualItemModel {
       
   128             id: itemModel
       
   129             Rectangle { height: 30; width: 80; color: "red" }
       
   130             Rectangle { height: 30; width: 80; color: "green" }
       
   131             Rectangle { height: 30; width: 80; color: "blue" }
       
   132         }
       
   133 
       
   134         ListView {
       
   135             anchors.fill: parent
       
   136             model: itemModel
       
   137         }
       
   138     }
       
   139     \endcode
       
   140 */
       
   141 QDeclarativeVisualItemModel::QDeclarativeVisualItemModel(QObject *parent)
       
   142     : QDeclarativeVisualModel(*(new QDeclarativeVisualItemModelPrivate), parent)
       
   143 {
       
   144 }
       
   145 
       
   146 QDeclarativeListProperty<QDeclarativeItem> QDeclarativeVisualItemModel::children()
       
   147 {
       
   148     Q_D(QDeclarativeVisualItemModel);
       
   149     return QDeclarativeListProperty<QDeclarativeItem>(this, d, d->children_append,
       
   150                                                       d->children_count, d->children_at);
       
   151 }
       
   152 
       
   153 /*!
       
   154     \qmlproperty int VisualItemModel::count
       
   155 
       
   156     The number of items in the model.  This property is readonly.
       
   157 */
       
   158 int QDeclarativeVisualItemModel::count() const
       
   159 {
       
   160     Q_D(const QDeclarativeVisualItemModel);
       
   161     return d->children.count();
       
   162 }
       
   163 
       
   164 bool QDeclarativeVisualItemModel::isValid() const
       
   165 {
       
   166     return true;
       
   167 }
       
   168 
       
   169 QDeclarativeItem *QDeclarativeVisualItemModel::item(int index, bool)
       
   170 {
       
   171     Q_D(QDeclarativeVisualItemModel);
       
   172     return d->children.at(index);
       
   173 }
       
   174 
       
   175 QDeclarativeVisualModel::ReleaseFlags QDeclarativeVisualItemModel::release(QDeclarativeItem *)
       
   176 {
       
   177     // Nothing to do
       
   178     return 0;
       
   179 }
       
   180 
       
   181 bool QDeclarativeVisualItemModel::completePending() const
       
   182 {
       
   183     return false;
       
   184 }
       
   185 
       
   186 void QDeclarativeVisualItemModel::completeItem()
       
   187 {
       
   188     // Nothing to do
       
   189 }
       
   190 
       
   191 QString QDeclarativeVisualItemModel::stringValue(int index, const QString &name)
       
   192 {
       
   193     Q_D(QDeclarativeVisualItemModel);
       
   194     if (index < 0 || index >= d->children.count())
       
   195         return QString();
       
   196     return QDeclarativeEngine::contextForObject(d->children.at(index))->contextProperty(name).toString();
       
   197 }
       
   198 
       
   199 QVariant QDeclarativeVisualItemModel::evaluate(int index, const QString &expression, QObject *objectContext)
       
   200 {
       
   201     Q_D(QDeclarativeVisualItemModel);
       
   202     if (index < 0 || index >= d->children.count())
       
   203         return QVariant();
       
   204     QDeclarativeContext *ccontext = qmlContext(this);
       
   205     QDeclarativeContext *ctxt = new QDeclarativeContext(ccontext);
       
   206     ctxt->setContextObject(d->children.at(index));
       
   207     QDeclarativeExpression e(ctxt, objectContext, expression);
       
   208     QVariant value = e.evaluate();
       
   209     delete ctxt;
       
   210     return value;
       
   211 }
       
   212 
       
   213 int QDeclarativeVisualItemModel::indexOf(QDeclarativeItem *item, QObject *) const
       
   214 {
       
   215     Q_D(const QDeclarativeVisualItemModel);
       
   216     return d->children.indexOf(item);
       
   217 }
       
   218 
       
   219 QDeclarativeVisualItemModelAttached *QDeclarativeVisualItemModel::qmlAttachedProperties(QObject *obj)
       
   220 {
       
   221     return QDeclarativeVisualItemModelAttached::properties(obj);
       
   222 }
       
   223 
       
   224 //============================================================================
       
   225 
       
   226 class VDMDelegateDataType : public QDeclarativeOpenMetaObjectType
       
   227 {
       
   228 public:
       
   229     VDMDelegateDataType(const QMetaObject *base, QDeclarativeEngine *engine) : QDeclarativeOpenMetaObjectType(base, engine) {}
       
   230 
       
   231     void propertyCreated(int, QMetaPropertyBuilder &prop) {
       
   232         prop.setWritable(false);
       
   233     }
       
   234 };
       
   235 
       
   236 class QDeclarativeVisualDataModelParts;
       
   237 class QDeclarativeVisualDataModelData;
       
   238 class QDeclarativeVisualDataModelPrivate : public QObjectPrivate
       
   239 {
       
   240 public:
       
   241     QDeclarativeVisualDataModelPrivate(QDeclarativeContext *);
       
   242 
       
   243     static QDeclarativeVisualDataModelPrivate *get(QDeclarativeVisualDataModel *m) {
       
   244         return static_cast<QDeclarativeVisualDataModelPrivate *>(QObjectPrivate::get(m));
       
   245     }
       
   246 
       
   247     QDeclarativeGuard<QListModelInterface> m_listModelInterface;
       
   248     QDeclarativeGuard<QAbstractItemModel> m_abstractItemModel;
       
   249     QDeclarativeGuard<QDeclarativeVisualDataModel> m_visualItemModel;
       
   250     QString m_part;
       
   251 
       
   252     QDeclarativeComponent *m_delegate;
       
   253     QDeclarativeGuard<QDeclarativeContext> m_context;
       
   254     QList<int> m_roles;
       
   255     QHash<QByteArray,int> m_roleNames;
       
   256     void ensureRoles() {
       
   257         if (m_roleNames.isEmpty()) {
       
   258             if (m_listModelInterface) {
       
   259                 m_roles = m_listModelInterface->roles();
       
   260                 for (int ii = 0; ii < m_roles.count(); ++ii)
       
   261                     m_roleNames.insert(m_listModelInterface->toString(m_roles.at(ii)).toUtf8(), m_roles.at(ii));
       
   262                 if (m_roles.count() == 1)
       
   263                     m_roleNames.insert("modelData", m_roles.at(0));
       
   264             } else if (m_abstractItemModel) {
       
   265                 for (QHash<int,QByteArray>::const_iterator it = m_abstractItemModel->roleNames().begin();
       
   266                         it != m_abstractItemModel->roleNames().end(); ++it) {
       
   267                     m_roles.append(it.key());
       
   268                     m_roleNames.insert(*it, it.key());
       
   269                 }
       
   270                 if (m_roles.count() == 1)
       
   271                     m_roleNames.insert("modelData", m_roles.at(0));
       
   272                 if (m_roles.count())
       
   273                     m_roleNames.insert("hasModelChildren", 0);
       
   274             } else if (m_listAccessor) {
       
   275                 m_roleNames.insert("modelData", 0);
       
   276                 if (m_listAccessor->type() == QDeclarativeListAccessor::Instance) {
       
   277                     if (QObject *object = m_listAccessor->at(0).value<QObject*>()) {
       
   278                         int count = object->metaObject()->propertyCount();
       
   279                         for (int ii = 1; ii < count; ++ii) {
       
   280                             const QMetaProperty &prop = object->metaObject()->property(ii);
       
   281                             m_roleNames.insert(prop.name(), 0);
       
   282                         }
       
   283                     }
       
   284                 }
       
   285             }
       
   286         }
       
   287     }
       
   288 
       
   289     QHash<int,int> roleToPropId;
       
   290     void createMetaData() {
       
   291         if (!m_metaDataCreated) {
       
   292             ensureRoles();
       
   293             if (m_roleNames.count()) {
       
   294                 QHash<QByteArray, int>::const_iterator it = m_roleNames.begin();
       
   295                 while (it != m_roleNames.end()) {
       
   296                     int propId = m_delegateDataType->createProperty(it.key()) - m_delegateDataType->propertyOffset();
       
   297                     roleToPropId.insert(*it, propId);
       
   298                     ++it;
       
   299                 }
       
   300                 m_metaDataCreated = true;
       
   301             }
       
   302         }
       
   303     }
       
   304 
       
   305     struct ObjectRef {
       
   306         ObjectRef(QObject *object=0) : obj(object), ref(1) {}
       
   307         QObject *obj;
       
   308         int ref;
       
   309     };
       
   310     class Cache : public QHash<int, ObjectRef> {
       
   311     public:
       
   312         QObject *getItem(int index) {
       
   313             QObject *item = 0;
       
   314             QHash<int,ObjectRef>::iterator it = find(index);
       
   315             if (it != end()) {
       
   316                 (*it).ref++;
       
   317                 item = (*it).obj;
       
   318             }
       
   319             return item;
       
   320         }
       
   321         QObject *item(int index) {
       
   322             QObject *item = 0;
       
   323             QHash<int, ObjectRef>::const_iterator it = find(index);
       
   324             if (it != end())
       
   325                 item = (*it).obj;
       
   326             return item;
       
   327         }
       
   328         void insertItem(int index, QObject *obj) {
       
   329             insert(index, ObjectRef(obj));
       
   330         }
       
   331         bool releaseItem(QObject *obj) {
       
   332             QHash<int, ObjectRef>::iterator it = begin();
       
   333             for (; it != end(); ++it) {
       
   334                 ObjectRef &objRef = *it;
       
   335                 if (objRef.obj == obj) {
       
   336                     if (--objRef.ref == 0) {
       
   337                         erase(it);
       
   338                         return true;
       
   339                     }
       
   340                     break;
       
   341                 }
       
   342             }
       
   343             return false;
       
   344         }
       
   345     };
       
   346 
       
   347     int modelCount() const {
       
   348         if (m_visualItemModel)
       
   349             return m_visualItemModel->count();
       
   350         if (m_listModelInterface)
       
   351             return m_listModelInterface->count();
       
   352         if (m_abstractItemModel)
       
   353             return m_abstractItemModel->rowCount(m_root);
       
   354         if (m_listAccessor)
       
   355             return m_listAccessor->count();
       
   356         return 0;
       
   357     }
       
   358 
       
   359     Cache m_cache;
       
   360     QHash<QObject *, QDeclarativePackage*> m_packaged;
       
   361 
       
   362     QDeclarativeVisualDataModelParts *m_parts;
       
   363     friend class QDeclarativeVisualItemParts;
       
   364 
       
   365     VDMDelegateDataType *m_delegateDataType;
       
   366     friend class QDeclarativeVisualDataModelData;
       
   367     bool m_metaDataCreated : 1;
       
   368     bool m_metaDataCacheable : 1;
       
   369     bool m_delegateValidated : 1;
       
   370     bool m_completePending : 1;
       
   371 
       
   372     QDeclarativeVisualDataModelData *data(QObject *item);
       
   373 
       
   374     QVariant m_modelVariant;
       
   375     QDeclarativeListAccessor *m_listAccessor;
       
   376 
       
   377     QModelIndex m_root;
       
   378 };
       
   379 
       
   380 class QDeclarativeVisualDataModelDataMetaObject : public QDeclarativeOpenMetaObject
       
   381 {
       
   382 public:
       
   383     QDeclarativeVisualDataModelDataMetaObject(QObject *parent, QDeclarativeOpenMetaObjectType *type)
       
   384     : QDeclarativeOpenMetaObject(parent, type) {}
       
   385 
       
   386     virtual QVariant initialValue(int);
       
   387     virtual int createProperty(const char *, const char *);
       
   388 
       
   389 private:
       
   390     friend class QDeclarativeVisualDataModelData;
       
   391 };
       
   392 
       
   393 class QDeclarativeVisualDataModelData : public QObject
       
   394 {
       
   395 Q_OBJECT
       
   396 public:
       
   397     QDeclarativeVisualDataModelData(int index, QDeclarativeVisualDataModel *model);
       
   398     ~QDeclarativeVisualDataModelData();
       
   399 
       
   400     Q_PROPERTY(int index READ index NOTIFY indexChanged)
       
   401     int index() const;
       
   402     void setIndex(int index);
       
   403 
       
   404     int propForRole(int) const;
       
   405     void setValue(int, const QVariant &);
       
   406 
       
   407     void ensureProperties();
       
   408 
       
   409 Q_SIGNALS:
       
   410     void indexChanged();
       
   411 
       
   412 private:
       
   413     friend class QDeclarativeVisualDataModelDataMetaObject;
       
   414     int m_index;
       
   415     QDeclarativeGuard<QDeclarativeVisualDataModel> m_model;
       
   416     QDeclarativeVisualDataModelDataMetaObject *m_meta;
       
   417 };
       
   418 
       
   419 int QDeclarativeVisualDataModelData::propForRole(int id) const
       
   420 {
       
   421     QDeclarativeVisualDataModelPrivate *model = QDeclarativeVisualDataModelPrivate::get(m_model);
       
   422     QHash<int,int>::const_iterator it = model->roleToPropId.find(id);
       
   423     if (it != model->roleToPropId.end())
       
   424         return *it;
       
   425 
       
   426     return -1;
       
   427 }
       
   428 
       
   429 void QDeclarativeVisualDataModelData::setValue(int id, const QVariant &val)
       
   430 {
       
   431     m_meta->setValue(id, val);
       
   432 }
       
   433 
       
   434 int QDeclarativeVisualDataModelDataMetaObject::createProperty(const char *name, const char *type)
       
   435 {
       
   436     QDeclarativeVisualDataModelData *data =
       
   437         static_cast<QDeclarativeVisualDataModelData *>(object());
       
   438 
       
   439     if (!data->m_model)
       
   440         return -1;
       
   441 
       
   442     QDeclarativeVisualDataModelPrivate *model = QDeclarativeVisualDataModelPrivate::get(data->m_model);
       
   443     if (data->m_index < 0 || data->m_index >= model->modelCount())
       
   444         return -1;
       
   445 
       
   446     if ((!model->m_listModelInterface || !model->m_abstractItemModel) && model->m_listAccessor) {
       
   447         if (model->m_listAccessor->type() == QDeclarativeListAccessor::ListProperty) {
       
   448             model->ensureRoles();
       
   449             if (qstrcmp(name,"modelData") == 0)
       
   450                 return QDeclarativeOpenMetaObject::createProperty(name, type);
       
   451         }
       
   452     }
       
   453     return -1;
       
   454 }
       
   455 
       
   456 QVariant QDeclarativeVisualDataModelDataMetaObject::initialValue(int propId)
       
   457 {
       
   458     QDeclarativeVisualDataModelData *data =
       
   459         static_cast<QDeclarativeVisualDataModelData *>(object());
       
   460 
       
   461     Q_ASSERT(data->m_model);
       
   462     QDeclarativeVisualDataModelPrivate *model = QDeclarativeVisualDataModelPrivate::get(data->m_model);
       
   463 
       
   464     QByteArray propName = name(propId);
       
   465     if ((!model->m_listModelInterface || !model->m_abstractItemModel) && model->m_listAccessor) {
       
   466         if (propName == "modelData") {
       
   467             if (model->m_listAccessor->type() == QDeclarativeListAccessor::Instance) {
       
   468                 QObject *object = model->m_listAccessor->at(0).value<QObject*>();
       
   469                 return object->metaObject()->property(1).read(object); // the first property after objectName
       
   470             }
       
   471             return model->m_listAccessor->at(data->m_index);
       
   472         } else {
       
   473             // return any property of a single object instance.
       
   474             QObject *object = model->m_listAccessor->at(data->m_index).value<QObject*>();
       
   475             return object->property(propName);
       
   476         }
       
   477     } else if (model->m_listModelInterface) {
       
   478         model->ensureRoles();
       
   479         QHash<QByteArray,int>::const_iterator it = model->m_roleNames.find(propName);
       
   480         if (it != model->m_roleNames.end()) {
       
   481             QVariant value = model->m_listModelInterface->data(data->m_index, *it);
       
   482             return value;
       
   483         } else if (model->m_roles.count() == 1 && propName == "modelData") {
       
   484             //for compatability with other lists, assign modelData if there is only a single role
       
   485             QVariant value = model->m_listModelInterface->data(data->m_index, model->m_roles.first());
       
   486             return value;
       
   487         }
       
   488     } else if (model->m_abstractItemModel) {
       
   489         model->ensureRoles();
       
   490         if (propName == "hasModelChildren") {
       
   491             QModelIndex index = model->m_abstractItemModel->index(data->m_index, 0, model->m_root);
       
   492             return model->m_abstractItemModel->hasChildren(index);
       
   493         } else {
       
   494             QHash<QByteArray,int>::const_iterator it = model->m_roleNames.find(propName);
       
   495             if (it != model->m_roleNames.end()) {
       
   496                 QModelIndex index = model->m_abstractItemModel->index(data->m_index, 0, model->m_root);
       
   497                 return model->m_abstractItemModel->data(index, *it);
       
   498             }
       
   499         }
       
   500     }
       
   501     Q_ASSERT(!"Can never be reached");
       
   502     return QVariant();
       
   503 }
       
   504 
       
   505 QDeclarativeVisualDataModelData::QDeclarativeVisualDataModelData(int index,
       
   506                                                QDeclarativeVisualDataModel *model)
       
   507 : m_index(index), m_model(model),
       
   508 m_meta(new QDeclarativeVisualDataModelDataMetaObject(this, QDeclarativeVisualDataModelPrivate::get(model)->m_delegateDataType))
       
   509 {
       
   510     ensureProperties();
       
   511 }
       
   512 
       
   513 QDeclarativeVisualDataModelData::~QDeclarativeVisualDataModelData()
       
   514 {
       
   515 }
       
   516 
       
   517 void QDeclarativeVisualDataModelData::ensureProperties()
       
   518 {
       
   519     QDeclarativeVisualDataModelPrivate *modelPriv = QDeclarativeVisualDataModelPrivate::get(m_model);
       
   520     if (modelPriv->m_metaDataCacheable && !modelPriv->m_metaDataCreated) {
       
   521         modelPriv->createMetaData();
       
   522         if (modelPriv->m_metaDataCreated)
       
   523             m_meta->setCached(true);
       
   524     }
       
   525 }
       
   526 
       
   527 int QDeclarativeVisualDataModelData::index() const
       
   528 {
       
   529     return m_index;
       
   530 }
       
   531 
       
   532 // This is internal only - it should not be set from qml
       
   533 void QDeclarativeVisualDataModelData::setIndex(int index)
       
   534 {
       
   535     m_index = index;
       
   536     emit indexChanged();
       
   537 }
       
   538 
       
   539 //---------------------------------------------------------------------------
       
   540 
       
   541 class QDeclarativeVisualDataModelPartsMetaObject : public QDeclarativeOpenMetaObject
       
   542 {
       
   543 public:
       
   544     QDeclarativeVisualDataModelPartsMetaObject(QObject *parent)
       
   545     : QDeclarativeOpenMetaObject(parent) {}
       
   546 
       
   547     virtual void propertyCreated(int, QMetaPropertyBuilder &);
       
   548     virtual QVariant initialValue(int);
       
   549 };
       
   550 
       
   551 class QDeclarativeVisualDataModelParts : public QObject
       
   552 {
       
   553 Q_OBJECT
       
   554 public:
       
   555     QDeclarativeVisualDataModelParts(QDeclarativeVisualDataModel *parent);
       
   556 
       
   557 private:
       
   558     friend class QDeclarativeVisualDataModelPartsMetaObject;
       
   559     QDeclarativeVisualDataModel *model;
       
   560 };
       
   561 
       
   562 void QDeclarativeVisualDataModelPartsMetaObject::propertyCreated(int, QMetaPropertyBuilder &prop)
       
   563 {
       
   564     prop.setWritable(false);
       
   565 }
       
   566 
       
   567 QVariant QDeclarativeVisualDataModelPartsMetaObject::initialValue(int id)
       
   568 {
       
   569     QDeclarativeVisualDataModel *m = new QDeclarativeVisualDataModel;
       
   570     m->setParent(object());
       
   571     m->setPart(QString::fromUtf8(name(id)));
       
   572     m->setModel(QVariant::fromValue(static_cast<QDeclarativeVisualDataModelParts *>(object())->model));
       
   573 
       
   574     QVariant var = QVariant::fromValue((QObject *)m);
       
   575     return var;
       
   576 }
       
   577 
       
   578 QDeclarativeVisualDataModelParts::QDeclarativeVisualDataModelParts(QDeclarativeVisualDataModel *parent)
       
   579 : QObject(parent), model(parent)
       
   580 {
       
   581     new QDeclarativeVisualDataModelPartsMetaObject(this);
       
   582 }
       
   583 
       
   584 QDeclarativeVisualDataModelPrivate::QDeclarativeVisualDataModelPrivate(QDeclarativeContext *ctxt)
       
   585 : m_listModelInterface(0), m_abstractItemModel(0), m_visualItemModel(0), m_delegate(0)
       
   586 , m_context(ctxt), m_parts(0), m_delegateDataType(0), m_metaDataCreated(false)
       
   587 , m_metaDataCacheable(false), m_delegateValidated(false), m_completePending(false), m_listAccessor(0)
       
   588 {
       
   589 }
       
   590 
       
   591 QDeclarativeVisualDataModelData *QDeclarativeVisualDataModelPrivate::data(QObject *item)
       
   592 {
       
   593     QDeclarativeVisualDataModelData *dataItem =
       
   594         item->findChild<QDeclarativeVisualDataModelData *>();
       
   595     Q_ASSERT(dataItem);
       
   596     return dataItem;
       
   597 }
       
   598 
       
   599 //---------------------------------------------------------------------------
       
   600 
       
   601 /*!
       
   602     \qmlclass VisualDataModel QDeclarativeVisualDataModel
       
   603     \brief The VisualDataModel encapsulates a model and delegate
       
   604 
       
   605     A VisualDataModel encapsulates a model and the delegate that will
       
   606     be instantiated for items in the model.
       
   607 
       
   608     It is usually not necessary to create a VisualDataModel directly,
       
   609     since the QML views will create one internally.
       
   610 
       
   611     The example below illustrates using a VisualDataModel with a ListView.
       
   612 
       
   613     \code
       
   614     VisualDataModel {
       
   615         id: visualModel
       
   616         model: myModel
       
   617         delegate: Component {
       
   618             Rectangle {
       
   619                 height: 25
       
   620                 width: 100
       
   621                 Text { text: "Name:" + name}
       
   622             }
       
   623         }
       
   624     }
       
   625     ListView {
       
   626         width: 100
       
   627         height: 100
       
   628         anchors.fill: parent
       
   629         model: visualModel
       
   630     }
       
   631     \endcode
       
   632 */
       
   633 
       
   634 QDeclarativeVisualDataModel::QDeclarativeVisualDataModel()
       
   635 : QDeclarativeVisualModel(*(new QDeclarativeVisualDataModelPrivate(0)))
       
   636 {
       
   637 }
       
   638 
       
   639 QDeclarativeVisualDataModel::QDeclarativeVisualDataModel(QDeclarativeContext *ctxt, QObject *parent)
       
   640 : QDeclarativeVisualModel(*(new QDeclarativeVisualDataModelPrivate(ctxt)), parent)
       
   641 {
       
   642 }
       
   643 
       
   644 QDeclarativeVisualDataModel::~QDeclarativeVisualDataModel()
       
   645 {
       
   646     Q_D(QDeclarativeVisualDataModel);
       
   647     if (d->m_listAccessor)
       
   648         delete d->m_listAccessor;
       
   649     if (d->m_delegateDataType)
       
   650         d->m_delegateDataType->release();
       
   651 }
       
   652 
       
   653 /*!
       
   654     \qmlproperty model VisualDataModel::model
       
   655     This property holds the model providing data for the VisualDataModel.
       
   656 
       
   657     The model provides a set of data that is used to create the items
       
   658     for a view.  For large or dynamic datasets the model is usually
       
   659     provided by a C++ model object.  The C++ model object must be a \l
       
   660     {QAbstractItemModel} subclass or a simple list.
       
   661 
       
   662     Models can also be created directly in QML, using a \l{ListModel} or
       
   663     \l{XmlListModel}.
       
   664 
       
   665     \sa {qmlmodels}{Data Models}
       
   666 */
       
   667 QVariant QDeclarativeVisualDataModel::model() const
       
   668 {
       
   669     Q_D(const QDeclarativeVisualDataModel);
       
   670     return d->m_modelVariant;
       
   671 }
       
   672 
       
   673 void QDeclarativeVisualDataModel::setModel(const QVariant &model)
       
   674 {
       
   675     Q_D(QDeclarativeVisualDataModel);
       
   676     delete d->m_listAccessor;
       
   677     d->m_listAccessor = 0;
       
   678     d->m_modelVariant = model;
       
   679     if (d->m_listModelInterface) {
       
   680         // Assume caller has released all items.
       
   681         QObject::disconnect(d->m_listModelInterface, SIGNAL(itemsChanged(int,int,QList<int>)),
       
   682                 this, SLOT(_q_itemsChanged(int,int,QList<int>)));
       
   683         QObject::disconnect(d->m_listModelInterface, SIGNAL(itemsInserted(int,int)),
       
   684                 this, SLOT(_q_itemsInserted(int,int)));
       
   685         QObject::disconnect(d->m_listModelInterface, SIGNAL(itemsRemoved(int,int)),
       
   686                 this, SLOT(_q_itemsRemoved(int,int)));
       
   687         QObject::disconnect(d->m_listModelInterface, SIGNAL(itemsMoved(int,int,int)),
       
   688                 this, SLOT(_q_itemsMoved(int,int,int)));
       
   689         d->m_listModelInterface = 0;
       
   690     } else if (d->m_abstractItemModel) {
       
   691         QObject::disconnect(d->m_abstractItemModel, SIGNAL(rowsInserted(const QModelIndex &,int,int)),
       
   692                             this, SLOT(_q_rowsInserted(const QModelIndex &,int,int)));
       
   693         QObject::disconnect(d->m_abstractItemModel, SIGNAL(rowsRemoved(const QModelIndex &,int,int)),
       
   694                             this, SLOT(_q_rowsRemoved(const QModelIndex &,int,int)));
       
   695         QObject::disconnect(d->m_abstractItemModel, SIGNAL(dataChanged(const QModelIndex&,const QModelIndex&)),
       
   696                             this, SLOT(_q_dataChanged(const QModelIndex&,const QModelIndex&)));
       
   697         QObject::disconnect(d->m_abstractItemModel, SIGNAL(rowsMoved(const QModelIndex&,int,int,const QModelIndex&,int)),
       
   698                             this, SLOT(_q_rowsMoved(const QModelIndex&,int,int,const QModelIndex&,int)));
       
   699         QObject::disconnect(d->m_abstractItemModel, SIGNAL(modelReset()), this, SLOT(_q_modelReset()));
       
   700     } else if (d->m_visualItemModel) {
       
   701         QObject::disconnect(d->m_visualItemModel, SIGNAL(itemsInserted(int,int)),
       
   702                          this, SIGNAL(itemsInserted(int,int)));
       
   703         QObject::disconnect(d->m_visualItemModel, SIGNAL(itemsRemoved(int,int)),
       
   704                          this, SIGNAL(itemsRemoved(int,int)));
       
   705         QObject::disconnect(d->m_visualItemModel, SIGNAL(itemsMoved(int,int,int)),
       
   706                          this, SIGNAL(itemsMoved(int,int,int)));
       
   707         QObject::disconnect(d->m_visualItemModel, SIGNAL(createdPackage(int,QDeclarativePackage*)),
       
   708                          this, SLOT(_q_createdPackage(int,QDeclarativePackage*)));
       
   709         QObject::disconnect(d->m_visualItemModel, SIGNAL(destroyingPackage(QDeclarativePackage*)),
       
   710                          this, SLOT(_q_destroyingPackage(QDeclarativePackage*)));
       
   711         d->m_visualItemModel = 0;
       
   712     }
       
   713 
       
   714     d->m_roles.clear();
       
   715     d->m_roleNames.clear();
       
   716     if (d->m_delegateDataType)
       
   717         d->m_delegateDataType->release();
       
   718     d->m_metaDataCreated = 0;
       
   719     d->m_metaDataCacheable = false;
       
   720     d->m_delegateDataType = new VDMDelegateDataType(&QDeclarativeVisualDataModelData::staticMetaObject, d->m_context?d->m_context->engine():qmlEngine(this));
       
   721 
       
   722     QObject *object = qvariant_cast<QObject *>(model);
       
   723     if (object && (d->m_listModelInterface = qobject_cast<QListModelInterface *>(object))) {
       
   724         QObject::connect(d->m_listModelInterface, SIGNAL(itemsChanged(int,int,QList<int>)),
       
   725                          this, SLOT(_q_itemsChanged(int,int,QList<int>)));
       
   726         QObject::connect(d->m_listModelInterface, SIGNAL(itemsInserted(int,int)),
       
   727                          this, SLOT(_q_itemsInserted(int,int)));
       
   728         QObject::connect(d->m_listModelInterface, SIGNAL(itemsRemoved(int,int)),
       
   729                          this, SLOT(_q_itemsRemoved(int,int)));
       
   730         QObject::connect(d->m_listModelInterface, SIGNAL(itemsMoved(int,int,int)),
       
   731                          this, SLOT(_q_itemsMoved(int,int,int)));
       
   732         d->m_metaDataCacheable = true;
       
   733         if (d->m_delegate && d->m_listModelInterface->count())
       
   734             emit itemsInserted(0, d->m_listModelInterface->count());
       
   735         return;
       
   736     } else if (object && (d->m_abstractItemModel = qobject_cast<QAbstractItemModel *>(object))) {
       
   737         QObject::connect(d->m_abstractItemModel, SIGNAL(rowsInserted(const QModelIndex &,int,int)),
       
   738                             this, SLOT(_q_rowsInserted(const QModelIndex &,int,int)));
       
   739         QObject::connect(d->m_abstractItemModel, SIGNAL(rowsRemoved(const QModelIndex &,int,int)),
       
   740                             this, SLOT(_q_rowsRemoved(const QModelIndex &,int,int)));
       
   741         QObject::connect(d->m_abstractItemModel, SIGNAL(dataChanged(const QModelIndex&,const QModelIndex&)),
       
   742                             this, SLOT(_q_dataChanged(const QModelIndex&,const QModelIndex&)));
       
   743         QObject::connect(d->m_abstractItemModel, SIGNAL(rowsMoved(const QModelIndex&,int,int,const QModelIndex&,int)),
       
   744                             this, SLOT(_q_rowsMoved(const QModelIndex&,int,int,const QModelIndex&,int)));
       
   745         QObject::connect(d->m_abstractItemModel, SIGNAL(modelReset()), this, SLOT(_q_modelReset()));
       
   746         d->m_metaDataCacheable = true;
       
   747         return;
       
   748     }
       
   749     if ((d->m_visualItemModel = qvariant_cast<QDeclarativeVisualDataModel *>(model))) {
       
   750         QObject::connect(d->m_visualItemModel, SIGNAL(itemsInserted(int,int)),
       
   751                          this, SIGNAL(itemsInserted(int,int)));
       
   752         QObject::connect(d->m_visualItemModel, SIGNAL(itemsRemoved(int,int)),
       
   753                          this, SIGNAL(itemsRemoved(int,int)));
       
   754         QObject::connect(d->m_visualItemModel, SIGNAL(itemsMoved(int,int,int)),
       
   755                          this, SIGNAL(itemsMoved(int,int,int)));
       
   756         QObject::connect(d->m_visualItemModel, SIGNAL(createdPackage(int,QDeclarativePackage*)),
       
   757                          this, SLOT(_q_createdPackage(int,QDeclarativePackage*)));
       
   758         QObject::connect(d->m_visualItemModel, SIGNAL(destroyingPackage(QDeclarativePackage*)),
       
   759                          this, SLOT(_q_destroyingPackage(QDeclarativePackage*)));
       
   760         return;
       
   761     }
       
   762     d->m_listAccessor = new QDeclarativeListAccessor;
       
   763     d->m_listAccessor->setList(model, d->m_context?d->m_context->engine():qmlEngine(this));
       
   764     if (d->m_listAccessor->type() != QDeclarativeListAccessor::ListProperty)
       
   765         d->m_metaDataCacheable = true;
       
   766     if (d->m_delegate && d->modelCount()) {
       
   767         emit itemsInserted(0, d->modelCount());
       
   768         emit countChanged();
       
   769     }
       
   770 }
       
   771 
       
   772 /*!
       
   773     \qmlproperty Component VisualDataModel::delegate
       
   774 
       
   775     The delegate provides a template defining each item instantiated by a view.
       
   776     The index is exposed as an accessible \c index property.  Properties of the
       
   777     model are also available depending upon the type of \l {qmlmodels}{Data Model}.
       
   778 */
       
   779 QDeclarativeComponent *QDeclarativeVisualDataModel::delegate() const
       
   780 {
       
   781     Q_D(const QDeclarativeVisualDataModel);
       
   782     if (d->m_visualItemModel)
       
   783         return d->m_visualItemModel->delegate();
       
   784     return d->m_delegate;
       
   785 }
       
   786 
       
   787 void QDeclarativeVisualDataModel::setDelegate(QDeclarativeComponent *delegate)
       
   788 {
       
   789     Q_D(QDeclarativeVisualDataModel);
       
   790     bool wasValid = d->m_delegate != 0;
       
   791     d->m_delegate = delegate;
       
   792     d->m_delegateValidated = false;
       
   793     if (!wasValid && d->modelCount() && d->m_delegate) {
       
   794         emit itemsInserted(0, d->modelCount());
       
   795         emit countChanged();
       
   796     }
       
   797     if (wasValid && !d->m_delegate && d->modelCount()) {
       
   798         emit itemsRemoved(0, d->modelCount());
       
   799         emit countChanged();
       
   800     }
       
   801 }
       
   802 
       
   803 /*!
       
   804     \qmlproperty QModelIndex VisualDataModel::rootIndex
       
   805 
       
   806     QAbstractItemModel provides a heirachical tree of data, whereas
       
   807     QML only operates on list data.  \c rootIndex allows the children of
       
   808     any node in a QAbstractItemModel to be provided by this model.
       
   809 
       
   810     This property only affects models of type QAbstractItemModel.
       
   811 
       
   812     \code
       
   813     // main.cpp
       
   814 
       
   815     int main(int argc, char ** argv)
       
   816     {
       
   817         QApplication app(argc, argv);
       
   818 
       
   819         QDeclarativeView view;
       
   820 
       
   821         QDirModel model;
       
   822         view.rootContext()->setContextProperty("myModel", &model);
       
   823 
       
   824         view.setSource(QUrl("qrc:view.qml"));
       
   825         view.show();
       
   826 
       
   827         return app.exec();
       
   828     }
       
   829 
       
   830     #include "main.moc"
       
   831     \endcode
       
   832 
       
   833     \code
       
   834     // view.qml
       
   835     import Qt 4.7
       
   836 
       
   837     ListView {
       
   838         id: view
       
   839         width: 200
       
   840         height: 200
       
   841         model: VisualDataModel {
       
   842             model: myModel
       
   843             delegate: Component {
       
   844                 Rectangle {
       
   845                     height: 25; width: 200
       
   846                     Text { text: filePath }
       
   847                     MouseArea {
       
   848                         anchors.fill: parent;
       
   849                         onClicked: if (hasModelChildren) view.model.rootIndex = view.model.modelIndex(index)
       
   850                     }
       
   851                 }
       
   852             }
       
   853         }
       
   854     }
       
   855     \endcode
       
   856 
       
   857     \sa modelIndex(), parentModelIndex()
       
   858 */
       
   859 QVariant QDeclarativeVisualDataModel::rootIndex() const
       
   860 {
       
   861     Q_D(const QDeclarativeVisualDataModel);
       
   862     return QVariant::fromValue(d->m_root);
       
   863 }
       
   864 
       
   865 void QDeclarativeVisualDataModel::setRootIndex(const QVariant &root)
       
   866 {
       
   867     Q_D(QDeclarativeVisualDataModel);
       
   868     QModelIndex modelIndex = qvariant_cast<QModelIndex>(root);
       
   869     if (d->m_root != modelIndex) {
       
   870         int oldCount = d->modelCount();
       
   871         d->m_root = modelIndex;
       
   872         int newCount = d->modelCount();
       
   873         if (d->m_delegate && oldCount)
       
   874             emit itemsRemoved(0, oldCount);
       
   875         if (d->m_delegate && newCount)
       
   876             emit itemsInserted(0, newCount);
       
   877         if (newCount != oldCount)
       
   878             emit countChanged();
       
   879         emit rootIndexChanged();
       
   880     }
       
   881 }
       
   882 
       
   883 
       
   884 /*!
       
   885     \qmlmethod QModelIndex VisualDataModel::modelIndex(int index)
       
   886 
       
   887     QAbstractItemModel provides a heirachical tree of data, whereas
       
   888     QML only operates on list data.  This function assists in using
       
   889     tree models in QML.
       
   890 
       
   891     Returns a QModelIndex for the specified index.
       
   892     This value can be assigned to rootIndex.
       
   893 
       
   894     \sa rootIndex
       
   895 */
       
   896 QVariant QDeclarativeVisualDataModel::modelIndex(int idx) const
       
   897 {
       
   898     Q_D(const QDeclarativeVisualDataModel);
       
   899     if (d->m_abstractItemModel)
       
   900         return QVariant::fromValue(d->m_abstractItemModel->index(idx, 0, d->m_root));
       
   901     return QVariant::fromValue(QModelIndex());
       
   902 }
       
   903 
       
   904 /*!
       
   905     \qmlmethod QModelIndex VisualDataModel::parentModelIndex()
       
   906 
       
   907     QAbstractItemModel provides a heirachical tree of data, whereas
       
   908     QML only operates on list data.  This function assists in using
       
   909     tree models in QML.
       
   910 
       
   911     Returns a QModelIndex for the parent of the current rootIndex.
       
   912     This value can be assigned to rootIndex.
       
   913 
       
   914     \sa rootIndex
       
   915 */
       
   916 QVariant QDeclarativeVisualDataModel::parentModelIndex() const
       
   917 {
       
   918     Q_D(const QDeclarativeVisualDataModel);
       
   919     if (d->m_abstractItemModel)
       
   920         return QVariant::fromValue(d->m_abstractItemModel->parent(d->m_root));
       
   921     return QVariant::fromValue(QModelIndex());
       
   922 }
       
   923 
       
   924 QString QDeclarativeVisualDataModel::part() const
       
   925 {
       
   926     Q_D(const QDeclarativeVisualDataModel);
       
   927     return d->m_part;
       
   928 }
       
   929 
       
   930 void QDeclarativeVisualDataModel::setPart(const QString &part)
       
   931 {
       
   932     Q_D(QDeclarativeVisualDataModel);
       
   933     d->m_part = part;
       
   934 }
       
   935 
       
   936 int QDeclarativeVisualDataModel::count() const
       
   937 {
       
   938     Q_D(const QDeclarativeVisualDataModel);
       
   939     return d->modelCount();
       
   940 }
       
   941 
       
   942 QDeclarativeItem *QDeclarativeVisualDataModel::item(int index, bool complete)
       
   943 {
       
   944     Q_D(QDeclarativeVisualDataModel);
       
   945     if (d->m_visualItemModel)
       
   946         return d->m_visualItemModel->item(index, d->m_part.toUtf8(), complete);
       
   947     return item(index, QByteArray(), complete);
       
   948 }
       
   949 
       
   950 /*
       
   951   Returns ReleaseStatus flags.
       
   952 */
       
   953 QDeclarativeVisualDataModel::ReleaseFlags QDeclarativeVisualDataModel::release(QDeclarativeItem *item)
       
   954 {
       
   955     Q_D(QDeclarativeVisualDataModel);
       
   956     if (d->m_visualItemModel)
       
   957         return d->m_visualItemModel->release(item);
       
   958 
       
   959     ReleaseFlags stat = 0;
       
   960     QObject *obj = item;
       
   961     bool inPackage = false;
       
   962 
       
   963     QHash<QObject*,QDeclarativePackage*>::iterator it = d->m_packaged.find(item);
       
   964     if (it != d->m_packaged.end()) {
       
   965         QDeclarativePackage *package = *it;
       
   966         d->m_packaged.erase(it);
       
   967         if (d->m_packaged.contains(item))
       
   968             stat |= Referenced;
       
   969         inPackage = true;
       
   970         obj = package; // fall through and delete
       
   971     }
       
   972 
       
   973     if (d->m_cache.releaseItem(obj)) {
       
   974         // Remove any bindings to avoid warnings due to parent change.
       
   975         QObjectPrivate *p = QObjectPrivate::get(obj);
       
   976         Q_ASSERT(p->declarativeData);
       
   977         QDeclarativeData *d = static_cast<QDeclarativeData*>(p->declarativeData);
       
   978         if (d->ownContext && d->context)
       
   979             d->context->clearExpressions();
       
   980 
       
   981         if (inPackage) {
       
   982             emit destroyingPackage(qobject_cast<QDeclarativePackage*>(obj));
       
   983         } else {
       
   984             if (item->scene())
       
   985                 item->scene()->removeItem(item);
       
   986         }
       
   987         stat |= Destroyed;
       
   988         obj->deleteLater();
       
   989     } else if (!inPackage) {
       
   990         stat |= Referenced;
       
   991     }
       
   992 
       
   993     return stat;
       
   994 }
       
   995 
       
   996 /*!
       
   997     \qmlproperty object VisualDataModel::parts
       
   998 
       
   999     The \a parts property selects a VisualDataModel which creates
       
  1000     delegates from the part named.  This is used in conjunction with
       
  1001     the Package element.
       
  1002 
       
  1003     For example, the code below selects a model which creates
       
  1004     delegates named \e list from a Package:
       
  1005 
       
  1006     \code
       
  1007     VisualDataModel {
       
  1008         id: visualModel
       
  1009         delegate: Package {
       
  1010             Item { Package.name: "list" }
       
  1011         }
       
  1012         model: myModel
       
  1013     }
       
  1014 
       
  1015     ListView {
       
  1016         width: 200; height:200
       
  1017         model: visualModel.parts.list
       
  1018     }
       
  1019     \endcode
       
  1020 
       
  1021     \sa Package
       
  1022 */
       
  1023 QObject *QDeclarativeVisualDataModel::parts()
       
  1024 {
       
  1025     Q_D(QDeclarativeVisualDataModel);
       
  1026     if (!d->m_parts)
       
  1027         d->m_parts = new QDeclarativeVisualDataModelParts(this);
       
  1028     return d->m_parts;
       
  1029 }
       
  1030 
       
  1031 QDeclarativeItem *QDeclarativeVisualDataModel::item(int index, const QByteArray &viewId, bool complete)
       
  1032 {
       
  1033     Q_D(QDeclarativeVisualDataModel);
       
  1034     if (d->m_visualItemModel)
       
  1035         return d->m_visualItemModel->item(index, viewId, complete);
       
  1036 
       
  1037     if (d->modelCount() <= 0 || !d->m_delegate)
       
  1038         return 0;
       
  1039     QObject *nobj = d->m_cache.getItem(index);
       
  1040     bool needComplete = false;
       
  1041     if (!nobj) {
       
  1042         QDeclarativeContext *ccontext = d->m_context;
       
  1043         if (!ccontext) ccontext = qmlContext(this);
       
  1044         QDeclarativeContext *ctxt = new QDeclarativeContext(ccontext);
       
  1045         QDeclarativeVisualDataModelData *data = new QDeclarativeVisualDataModelData(index, this);
       
  1046         if ((!d->m_listModelInterface || !d->m_abstractItemModel) && d->m_listAccessor
       
  1047             && d->m_listAccessor->type() == QDeclarativeListAccessor::ListProperty) {
       
  1048             ctxt->setContextObject(d->m_listAccessor->at(index).value<QObject*>());
       
  1049             ctxt = new QDeclarativeContext(ctxt, ctxt);
       
  1050         }
       
  1051         ctxt->setContextProperty(QLatin1String("model"), data);
       
  1052         ctxt->setContextObject(data);
       
  1053         d->m_completePending = false;
       
  1054         nobj = d->m_delegate->beginCreate(ctxt);
       
  1055         if (complete) {
       
  1056             d->m_delegate->completeCreate();
       
  1057         } else {
       
  1058             d->m_completePending = true;
       
  1059             needComplete = true;
       
  1060         }
       
  1061         if (nobj) {
       
  1062             QDeclarative_setParent_noEvent(ctxt, nobj);
       
  1063             QDeclarative_setParent_noEvent(data, nobj);
       
  1064             d->m_cache.insertItem(index, nobj);
       
  1065             if (QDeclarativePackage *package = qobject_cast<QDeclarativePackage *>(nobj))
       
  1066                 emit createdPackage(index, package);
       
  1067         } else {
       
  1068             delete data;
       
  1069             delete ctxt;
       
  1070             qmlInfo(this, d->m_delegate->errors()) << "Error creating delgate";
       
  1071         }
       
  1072     }
       
  1073     QDeclarativeItem *item = qobject_cast<QDeclarativeItem *>(nobj);
       
  1074     if (!item) {
       
  1075         QDeclarativePackage *package = qobject_cast<QDeclarativePackage *>(nobj);
       
  1076         if (package) {
       
  1077             QObject *o = package->part(QString::fromUtf8(viewId));
       
  1078             item = qobject_cast<QDeclarativeItem *>(o);
       
  1079             if (item)
       
  1080                 d->m_packaged.insertMulti(item, package);
       
  1081         }
       
  1082     }
       
  1083     if (!item) {
       
  1084         if (needComplete)
       
  1085             d->m_delegate->completeCreate();
       
  1086         d->m_cache.releaseItem(nobj);
       
  1087         if (!d->m_delegateValidated) {
       
  1088             qmlInfo(d->m_delegate) << QDeclarativeVisualDataModel::tr("Delegate component must be Item type.");
       
  1089             d->m_delegateValidated = true;
       
  1090         }
       
  1091     }
       
  1092 
       
  1093     return item;
       
  1094 }
       
  1095 
       
  1096 bool QDeclarativeVisualDataModel::completePending() const
       
  1097 {
       
  1098     Q_D(const QDeclarativeVisualDataModel);
       
  1099     if (d->m_visualItemModel)
       
  1100         return d->m_visualItemModel->completePending();
       
  1101     return d->m_completePending;
       
  1102 }
       
  1103 
       
  1104 void QDeclarativeVisualDataModel::completeItem()
       
  1105 {
       
  1106     Q_D(QDeclarativeVisualDataModel);
       
  1107     if (d->m_visualItemModel) {
       
  1108         d->m_visualItemModel->completeItem();
       
  1109         return;
       
  1110     }
       
  1111 
       
  1112     d->m_delegate->completeCreate();
       
  1113     d->m_completePending = false;
       
  1114 }
       
  1115 
       
  1116 QString QDeclarativeVisualDataModel::stringValue(int index, const QString &name)
       
  1117 {
       
  1118     Q_D(QDeclarativeVisualDataModel);
       
  1119     if (d->m_visualItemModel)
       
  1120         return d->m_visualItemModel->stringValue(index, name);
       
  1121 
       
  1122     if ((!d->m_listModelInterface && !d->m_abstractItemModel) || !d->m_delegate)
       
  1123         return QString();
       
  1124 
       
  1125     QString val;
       
  1126     QObject *data = 0;
       
  1127     bool tempData = false;
       
  1128 
       
  1129     if (QObject *nobj = d->m_cache.item(index))
       
  1130         data = d->data(nobj);
       
  1131     if (!data) {
       
  1132         data = new QDeclarativeVisualDataModelData(index, this);
       
  1133         tempData = true;
       
  1134     }
       
  1135 
       
  1136     QDeclarativeData *ddata = QDeclarativeData::get(data);
       
  1137     if (ddata && ddata->propertyCache) {
       
  1138         QDeclarativePropertyCache::Data *prop = ddata->propertyCache->property(name);
       
  1139         if (prop) {
       
  1140             if (prop->propType == QVariant::String) {
       
  1141                 void *args[] = { &val, 0 };
       
  1142                 QMetaObject::metacall(data, QMetaObject::ReadProperty, prop->coreIndex, args);
       
  1143             } else if (prop->propType == qMetaTypeId<QVariant>()) {
       
  1144                 QVariant v;
       
  1145                 void *args[] = { &v, 0 };
       
  1146                 QMetaObject::metacall(data, QMetaObject::ReadProperty, prop->coreIndex, args);
       
  1147                 val = v.toString();
       
  1148             }
       
  1149         } else {
       
  1150             val = data->property(name.toUtf8()).toString();
       
  1151         }
       
  1152     } else {
       
  1153         val = data->property(name.toUtf8()).toString();
       
  1154     }
       
  1155 
       
  1156     if (tempData)
       
  1157         delete data;
       
  1158 
       
  1159     return val;
       
  1160 }
       
  1161 
       
  1162 QVariant QDeclarativeVisualDataModel::evaluate(int index, const QString &expression, QObject *objectContext)
       
  1163 {
       
  1164     Q_D(QDeclarativeVisualDataModel);
       
  1165     if (d->m_visualItemModel)
       
  1166         return d->m_visualItemModel->evaluate(index, expression, objectContext);
       
  1167 
       
  1168     if ((!d->m_listModelInterface && !d->m_abstractItemModel) || !d->m_delegate)
       
  1169         return QVariant();
       
  1170 
       
  1171     QVariant value;
       
  1172     QObject *nobj = d->m_cache.item(index);
       
  1173     if (nobj) {
       
  1174         QDeclarativeItem *item = qobject_cast<QDeclarativeItem *>(nobj);
       
  1175         if (item) {
       
  1176             QDeclarativeExpression e(qmlContext(item), objectContext, expression);
       
  1177             value = e.evaluate();
       
  1178         }
       
  1179     } else {
       
  1180         QDeclarativeContext *ccontext = d->m_context;
       
  1181         if (!ccontext) ccontext = qmlContext(this);
       
  1182         QDeclarativeContext *ctxt = new QDeclarativeContext(ccontext);
       
  1183         QDeclarativeVisualDataModelData *data = new QDeclarativeVisualDataModelData(index, this);
       
  1184         ctxt->setContextObject(data);
       
  1185         QDeclarativeExpression e(ctxt, objectContext, expression);
       
  1186         value = e.evaluate();
       
  1187         delete data;
       
  1188         delete ctxt;
       
  1189     }
       
  1190 
       
  1191     return value;
       
  1192 }
       
  1193 
       
  1194 int QDeclarativeVisualDataModel::indexOf(QDeclarativeItem *item, QObject *) const
       
  1195 {
       
  1196     QVariant val = QDeclarativeEngine::contextForObject(item)->contextProperty(QLatin1String("index"));
       
  1197         return val.toInt();
       
  1198     return -1;
       
  1199 }
       
  1200 
       
  1201 void QDeclarativeVisualDataModel::_q_itemsChanged(int index, int count,
       
  1202                                          const QList<int> &roles)
       
  1203 {
       
  1204     Q_D(QDeclarativeVisualDataModel);
       
  1205     for (QHash<int,QDeclarativeVisualDataModelPrivate::ObjectRef>::ConstIterator iter = d->m_cache.begin();
       
  1206         iter != d->m_cache.end(); ++iter) {
       
  1207         const int idx = iter.key();
       
  1208 
       
  1209         if (idx >= index && idx < index+count) {
       
  1210             QDeclarativeVisualDataModelPrivate::ObjectRef objRef = *iter;
       
  1211             QDeclarativeVisualDataModelData *data = d->data(objRef.obj);
       
  1212             for (int roleIdx = 0; roleIdx < roles.count(); ++roleIdx) {
       
  1213                 int role = roles.at(roleIdx);
       
  1214                 int propId = data->propForRole(role);
       
  1215                 if (propId != -1) {
       
  1216                     if (d->m_listModelInterface) {
       
  1217                         data->setValue(propId, d->m_listModelInterface->data(idx, QList<int>() << role).value(role));
       
  1218                     } else if (d->m_abstractItemModel) {
       
  1219                         QModelIndex index = d->m_abstractItemModel->index(idx, 0, d->m_root);
       
  1220                         data->setValue(propId, d->m_abstractItemModel->data(index, role));
       
  1221                     }
       
  1222                 } else {
       
  1223                     QString roleName;
       
  1224                     if (d->m_listModelInterface)
       
  1225                         roleName = d->m_listModelInterface->toString(role);
       
  1226                     else if (d->m_abstractItemModel)
       
  1227                         roleName = QString::fromUtf8(d->m_abstractItemModel->roleNames().value(role));
       
  1228                     qmlInfo(this) << "Changing role not present in item: " << roleName;
       
  1229                 }
       
  1230             }
       
  1231         }
       
  1232     }
       
  1233 }
       
  1234 
       
  1235 void QDeclarativeVisualDataModel::_q_itemsInserted(int index, int count)
       
  1236 {
       
  1237     Q_D(QDeclarativeVisualDataModel);
       
  1238     if (!count)
       
  1239         return;
       
  1240     // XXX - highly inefficient
       
  1241     QHash<int,QDeclarativeVisualDataModelPrivate::ObjectRef> items;
       
  1242     for (QHash<int,QDeclarativeVisualDataModelPrivate::ObjectRef>::Iterator iter = d->m_cache.begin();
       
  1243         iter != d->m_cache.end(); ) {
       
  1244 
       
  1245         if (iter.key() >= index) {
       
  1246             QDeclarativeVisualDataModelPrivate::ObjectRef objRef = *iter;
       
  1247             int index = iter.key() + count;
       
  1248             iter = d->m_cache.erase(iter);
       
  1249 
       
  1250             items.insert(index, objRef);
       
  1251 
       
  1252             QDeclarativeVisualDataModelData *data = d->data(objRef.obj);
       
  1253             data->setIndex(index);
       
  1254         } else {
       
  1255             ++iter;
       
  1256         }
       
  1257     }
       
  1258     d->m_cache.unite(items);
       
  1259 
       
  1260     emit itemsInserted(index, count);
       
  1261     emit countChanged();
       
  1262 }
       
  1263 
       
  1264 void QDeclarativeVisualDataModel::_q_itemsRemoved(int index, int count)
       
  1265 {
       
  1266     Q_D(QDeclarativeVisualDataModel);
       
  1267     if (!count)
       
  1268         return;
       
  1269     // XXX - highly inefficient
       
  1270     QHash<int, QDeclarativeVisualDataModelPrivate::ObjectRef> items;
       
  1271     for (QHash<int, QDeclarativeVisualDataModelPrivate::ObjectRef>::Iterator iter = d->m_cache.begin();
       
  1272         iter != d->m_cache.end(); ) {
       
  1273         if (iter.key() >= index && iter.key() < index + count) {
       
  1274             QDeclarativeVisualDataModelPrivate::ObjectRef objRef = *iter;
       
  1275             iter = d->m_cache.erase(iter);
       
  1276             items.insertMulti(-1, objRef); //XXX perhaps better to maintain separately
       
  1277             QDeclarativeVisualDataModelData *data = d->data(objRef.obj);
       
  1278             data->setIndex(-1);
       
  1279         } else if (iter.key() >= index + count) {
       
  1280             QDeclarativeVisualDataModelPrivate::ObjectRef objRef = *iter;
       
  1281             int index = iter.key() - count;
       
  1282             iter = d->m_cache.erase(iter);
       
  1283             items.insert(index, objRef);
       
  1284             QDeclarativeVisualDataModelData *data = d->data(objRef.obj);
       
  1285             data->setIndex(index);
       
  1286         } else {
       
  1287             ++iter;
       
  1288         }
       
  1289     }
       
  1290 
       
  1291     d->m_cache.unite(items);
       
  1292     emit itemsRemoved(index, count);
       
  1293     emit countChanged();
       
  1294 }
       
  1295 
       
  1296 void QDeclarativeVisualDataModel::_q_itemsMoved(int from, int to, int count)
       
  1297 {
       
  1298     Q_D(QDeclarativeVisualDataModel);
       
  1299     // XXX - highly inefficient
       
  1300     QHash<int,QDeclarativeVisualDataModelPrivate::ObjectRef> items;
       
  1301     for (QHash<int,QDeclarativeVisualDataModelPrivate::ObjectRef>::Iterator iter = d->m_cache.begin();
       
  1302         iter != d->m_cache.end(); ) {
       
  1303 
       
  1304         if (iter.key() >= from && iter.key() < from + count) {
       
  1305             QDeclarativeVisualDataModelPrivate::ObjectRef objRef = *iter;
       
  1306             int index = iter.key() - from + to;
       
  1307             iter = d->m_cache.erase(iter);
       
  1308 
       
  1309             items.insert(index, objRef);
       
  1310 
       
  1311             QDeclarativeVisualDataModelData *data = d->data(objRef.obj);
       
  1312             data->setIndex(index);
       
  1313         } else {
       
  1314             ++iter;
       
  1315         }
       
  1316     }
       
  1317     for (QHash<int,QDeclarativeVisualDataModelPrivate::ObjectRef>::Iterator iter = d->m_cache.begin();
       
  1318         iter != d->m_cache.end(); ) {
       
  1319 
       
  1320         int diff = from > to ? count : -count;
       
  1321         if (iter.key() >= qMin(from,to) && iter.key() < qMax(from+count,to+count)) {
       
  1322             QDeclarativeVisualDataModelPrivate::ObjectRef objRef = *iter;
       
  1323             int index = iter.key() + diff;
       
  1324             iter = d->m_cache.erase(iter);
       
  1325 
       
  1326             items.insert(index, objRef);
       
  1327 
       
  1328             QDeclarativeVisualDataModelData *data = d->data(objRef.obj);
       
  1329             data->setIndex(index);
       
  1330         } else {
       
  1331             ++iter;
       
  1332         }
       
  1333     }
       
  1334     d->m_cache.unite(items);
       
  1335 
       
  1336     emit itemsMoved(from, to, count);
       
  1337 }
       
  1338 
       
  1339 void QDeclarativeVisualDataModel::_q_rowsInserted(const QModelIndex &parent, int begin, int end)
       
  1340 {
       
  1341     if (!parent.isValid())
       
  1342         _q_itemsInserted(begin, end - begin + 1);
       
  1343 }
       
  1344 
       
  1345 void QDeclarativeVisualDataModel::_q_rowsRemoved(const QModelIndex &parent, int begin, int end)
       
  1346 {
       
  1347     if (!parent.isValid())
       
  1348         _q_itemsRemoved(begin, end - begin + 1);
       
  1349 }
       
  1350 
       
  1351 void QDeclarativeVisualDataModel::_q_rowsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationRow)
       
  1352 {
       
  1353     const int count = sourceEnd - sourceStart + 1;
       
  1354     if (!destinationParent.isValid() && !sourceParent.isValid()) {
       
  1355         _q_itemsMoved(sourceStart, destinationRow, count);
       
  1356     } else if (!sourceParent.isValid()) {
       
  1357         _q_itemsRemoved(sourceStart, count);
       
  1358     } else if (!destinationParent.isValid()) {
       
  1359         _q_itemsInserted(destinationRow, count);
       
  1360     }
       
  1361 }
       
  1362 
       
  1363 void QDeclarativeVisualDataModel::_q_dataChanged(const QModelIndex &begin, const QModelIndex &end)
       
  1364 {
       
  1365     Q_D(QDeclarativeVisualDataModel);
       
  1366     if (!begin.parent().isValid())
       
  1367         _q_itemsChanged(begin.row(), end.row() - begin.row() + 1, d->m_roles);
       
  1368 }
       
  1369 
       
  1370 void QDeclarativeVisualDataModel::_q_modelReset()
       
  1371 {
       
  1372     emit modelReset();
       
  1373 }
       
  1374 
       
  1375 void QDeclarativeVisualDataModel::_q_createdPackage(int index, QDeclarativePackage *package)
       
  1376 {
       
  1377     Q_D(QDeclarativeVisualDataModel);
       
  1378     emit createdItem(index, qobject_cast<QDeclarativeItem*>(package->part(d->m_part)));
       
  1379 }
       
  1380 
       
  1381 void QDeclarativeVisualDataModel::_q_destroyingPackage(QDeclarativePackage *package)
       
  1382 {
       
  1383     Q_D(QDeclarativeVisualDataModel);
       
  1384     emit destroyingItem(qobject_cast<QDeclarativeItem*>(package->part(d->m_part)));
       
  1385 }
       
  1386 
       
  1387 QT_END_NAMESPACE
       
  1388 
       
  1389 QML_DECLARE_TYPE(QListModelInterface)
       
  1390 
       
  1391 #include <qdeclarativevisualitemmodel.moc>