1 // Commit: 45153a37e4d9e39e8c326a0f33ea17be49bb29e2
2 /****************************************************************************
4 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
5 ** All rights reserved.
6 ** Contact: Nokia Corporation (qt-info@nokia.com)
8 ** This file is part of the QtDeclarative module of the Qt Toolkit.
10 ** $QT_BEGIN_LICENSE:LGPL$
11 ** No Commercial Usage
12 ** This file contains pre-release code and may not be distributed.
13 ** You may use this file in accordance with the terms and conditions
14 ** contained in the Technology Preview License Agreement accompanying
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 ** In addition, as a special exception, Nokia gives you certain additional
26 ** rights. These rights are described in the Nokia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 ** If you have questions regarding the use of this file, please contact
30 ** Nokia at qt-info@nokia.com.
41 ****************************************************************************/
43 #include "qsgvisualitemmodel_p.h"
46 #include <QtDeclarative/qdeclarativecontext.h>
47 #include <QtDeclarative/qdeclarativeengine.h>
48 #include <QtDeclarative/qdeclarativeexpression.h>
49 #include <QtDeclarative/qdeclarativeinfo.h>
51 #include <private/qdeclarativecontext_p.h>
52 #include <private/qdeclarativepackage_p.h>
53 #include <private/qdeclarativeopenmetaobject_p.h>
54 #include <private/qdeclarativelistaccessor_p.h>
55 #include <private/qdeclarativedata_p.h>
56 #include <private/qdeclarativepropertycache_p.h>
57 #include <private/qdeclarativeguard_p.h>
58 #include <private/qdeclarativeglobal_p.h>
59 #include <private/qlistmodelinterface_p.h>
60 #include <private/qmetaobjectbuilder_p.h>
61 #include <private/qobject_p.h>
63 #include <QtCore/qhash.h>
64 #include <QtCore/qlist.h>
68 QHash<QObject*, QSGVisualItemModelAttached*> QSGVisualItemModelAttached::attachedProperties;
71 class QSGVisualItemModelPrivate : public QObjectPrivate
73 Q_DECLARE_PUBLIC(QSGVisualItemModel)
75 QSGVisualItemModelPrivate() : QObjectPrivate() {}
77 static void children_append(QDeclarativeListProperty<QSGItem> *prop, QSGItem *item) {
78 QDeclarative_setParent_noEvent(item, prop->object);
79 static_cast<QSGVisualItemModelPrivate *>(prop->data)->children.append(Item(item));
80 static_cast<QSGVisualItemModelPrivate *>(prop->data)->itemAppended();
81 static_cast<QSGVisualItemModelPrivate *>(prop->data)->emitChildrenChanged();
84 static int children_count(QDeclarativeListProperty<QSGItem> *prop) {
85 return static_cast<QSGVisualItemModelPrivate *>(prop->data)->children.count();
88 static QSGItem *children_at(QDeclarativeListProperty<QSGItem> *prop, int index) {
89 return static_cast<QSGVisualItemModelPrivate *>(prop->data)->children.at(index).item;
93 Q_Q(QSGVisualItemModel);
94 QSGVisualItemModelAttached *attached = QSGVisualItemModelAttached::properties(children.last().item);
95 attached->setIndex(children.count()-1);
96 emit q->itemsInserted(children.count()-1, 1);
97 emit q->countChanged();
100 void emitChildrenChanged() {
101 Q_Q(QSGVisualItemModel);
102 emit q->childrenChanged();
105 int indexOf(QSGItem *item) const {
106 for (int i = 0; i < children.count(); ++i)
107 if (children.at(i).item == item)
114 Item(QSGItem *i) : item(i), ref(0) {}
116 void addRef() { ++ref; }
117 bool deref() { return --ref == 0; }
123 QList<Item> children;
126 QSGVisualItemModel::QSGVisualItemModel(QObject *parent)
127 : QSGVisualModel(*(new QSGVisualItemModelPrivate), parent)
131 QDeclarativeListProperty<QSGItem> QSGVisualItemModel::children()
133 Q_D(QSGVisualItemModel);
134 return QDeclarativeListProperty<QSGItem>(this, d, d->children_append,
135 d->children_count, d->children_at);
138 int QSGVisualItemModel::count() const
140 Q_D(const QSGVisualItemModel);
141 return d->children.count();
144 bool QSGVisualItemModel::isValid() const
149 QSGItem *QSGVisualItemModel::item(int index, bool)
151 Q_D(QSGVisualItemModel);
152 QSGVisualItemModelPrivate::Item &item = d->children[index];
157 QSGVisualModel::ReleaseFlags QSGVisualItemModel::release(QSGItem *item)
159 Q_D(QSGVisualItemModel);
160 int idx = d->indexOf(item);
162 if (d->children[idx].deref()) {
163 // XXX todo - the original did item->scene()->removeItem(). Why?
164 item->setParentItem(0);
165 QDeclarative_setParent_noEvent(item, this);
171 bool QSGVisualItemModel::completePending() const
176 void QSGVisualItemModel::completeItem()
181 QString QSGVisualItemModel::stringValue(int index, const QString &name)
183 Q_D(QSGVisualItemModel);
184 if (index < 0 || index >= d->children.count())
186 return QDeclarativeEngine::contextForObject(d->children.at(index).item)->contextProperty(name).toString();
189 int QSGVisualItemModel::indexOf(QSGItem *item, QObject *) const
191 Q_D(const QSGVisualItemModel);
192 return d->indexOf(item);
195 QSGVisualItemModelAttached *QSGVisualItemModel::qmlAttachedProperties(QObject *obj)
197 return QSGVisualItemModelAttached::properties(obj);
200 //============================================================================
202 class VDMDelegateDataType : public QDeclarativeOpenMetaObjectType
205 VDMDelegateDataType(const QMetaObject *base, QDeclarativeEngine *engine) : QDeclarativeOpenMetaObjectType(base, engine) {}
207 void propertyCreated(int, QMetaPropertyBuilder &prop) {
208 prop.setWritable(false);
212 class QSGVisualDataModelParts;
213 class QSGVisualDataModelData;
214 class QSGVisualDataModelPrivate : public QObjectPrivate
217 QSGVisualDataModelPrivate(QDeclarativeContext *);
219 static QSGVisualDataModelPrivate *get(QSGVisualDataModel *m) {
220 return static_cast<QSGVisualDataModelPrivate *>(QObjectPrivate::get(m));
223 QDeclarativeGuard<QListModelInterface> m_listModelInterface;
224 QDeclarativeGuard<QAbstractItemModel> m_abstractItemModel;
225 QDeclarativeGuard<QSGVisualDataModel> m_visualItemModel;
228 QDeclarativeComponent *m_delegate;
229 QDeclarativeGuard<QDeclarativeContext> m_context;
231 QHash<QByteArray,int> m_roleNames;
233 if (m_roleNames.isEmpty()) {
234 if (m_listModelInterface) {
235 m_roles = m_listModelInterface->roles();
236 for (int ii = 0; ii < m_roles.count(); ++ii)
237 m_roleNames.insert(m_listModelInterface->toString(m_roles.at(ii)).toUtf8(), m_roles.at(ii));
238 } else if (m_abstractItemModel) {
239 for (QHash<int,QByteArray>::const_iterator it = m_abstractItemModel->roleNames().begin();
240 it != m_abstractItemModel->roleNames().end(); ++it) {
241 m_roles.append(it.key());
242 m_roleNames.insert(*it, it.key());
245 m_roleNames.insert("hasModelChildren", -1);
246 } else if (m_listAccessor) {
247 m_roleNames.insert("modelData", 0);
248 if (m_listAccessor->type() == QDeclarativeListAccessor::Instance) {
249 if (QObject *object = m_listAccessor->at(0).value<QObject*>()) {
250 int count = object->metaObject()->propertyCount();
251 for (int ii = 1; ii < count; ++ii) {
252 const QMetaProperty &prop = object->metaObject()->property(ii);
253 m_roleNames.insert(prop.name(), 0);
261 QHash<int,int> m_roleToPropId;
262 int m_modelDataPropId;
263 void createMetaData() {
264 if (!m_metaDataCreated) {
266 if (m_roleNames.count()) {
267 QHash<QByteArray, int>::const_iterator it = m_roleNames.begin();
268 while (it != m_roleNames.end()) {
269 int propId = m_delegateDataType->createProperty(it.key()) - m_delegateDataType->propertyOffset();
270 m_roleToPropId.insert(*it, propId);
273 // Add modelData property
274 if (m_roles.count() == 1)
275 m_modelDataPropId = m_delegateDataType->createProperty("modelData") - m_delegateDataType->propertyOffset();
276 m_metaDataCreated = true;
282 ObjectRef(QObject *object=0) : obj(object), ref(1) {}
286 class Cache : public QHash<int, ObjectRef> {
288 QObject *getItem(int index) {
290 QHash<int,ObjectRef>::iterator it = find(index);
297 QObject *item(int index) {
299 QHash<int, ObjectRef>::const_iterator it = find(index);
304 void insertItem(int index, QObject *obj) {
305 insert(index, ObjectRef(obj));
307 bool releaseItem(QObject *obj) {
308 QHash<int, ObjectRef>::iterator it = begin();
309 for (; it != end(); ++it) {
310 ObjectRef &objRef = *it;
311 if (objRef.obj == obj) {
312 if (--objRef.ref == 0) {
323 int modelCount() const {
324 if (m_visualItemModel)
325 return m_visualItemModel->count();
326 if (m_listModelInterface)
327 return m_listModelInterface->count();
328 if (m_abstractItemModel)
329 return m_abstractItemModel->rowCount(m_root);
331 return m_listAccessor->count();
336 QHash<QObject *, QDeclarativePackage*> m_packaged;
338 QSGVisualDataModelParts *m_parts;
339 friend class QSGVisualItemParts;
341 VDMDelegateDataType *m_delegateDataType;
342 friend class QSGVisualDataModelData;
343 bool m_metaDataCreated : 1;
344 bool m_metaDataCacheable : 1;
345 bool m_delegateValidated : 1;
346 bool m_completePending : 1;
348 QSGVisualDataModelData *data(QObject *item);
350 QVariant m_modelVariant;
351 QDeclarativeListAccessor *m_listAccessor;
354 QList<QByteArray> watchedRoles;
355 QList<int> watchedRoleIds;
358 class QSGVisualDataModelDataMetaObject : public QDeclarativeOpenMetaObject
361 QSGVisualDataModelDataMetaObject(QObject *parent, QDeclarativeOpenMetaObjectType *type)
362 : QDeclarativeOpenMetaObject(parent, type) {}
364 virtual QVariant initialValue(int);
365 virtual int createProperty(const char *, const char *);
368 friend class QSGVisualDataModelData;
371 class QSGVisualDataModelData : public QObject
375 QSGVisualDataModelData(int index, QSGVisualDataModel *model);
376 ~QSGVisualDataModelData();
378 Q_PROPERTY(int index READ index NOTIFY indexChanged)
380 void setIndex(int index);
382 int propForRole(int) const;
383 int modelDataPropertyId() const {
384 QSGVisualDataModelPrivate *model = QSGVisualDataModelPrivate::get(m_model);
385 return model->m_modelDataPropId;
388 void setValue(int, const QVariant &);
389 bool hasValue(int id) const {
390 return m_meta->hasValue(id);
393 void ensureProperties();
399 friend class QSGVisualDataModelDataMetaObject;
401 QDeclarativeGuard<QSGVisualDataModel> m_model;
402 QSGVisualDataModelDataMetaObject *m_meta;
405 int QSGVisualDataModelData::propForRole(int id) const
407 QSGVisualDataModelPrivate *model = QSGVisualDataModelPrivate::get(m_model);
408 QHash<int,int>::const_iterator it = model->m_roleToPropId.find(id);
409 if (it != model->m_roleToPropId.end())
415 void QSGVisualDataModelData::setValue(int id, const QVariant &val)
417 m_meta->setValue(id, val);
420 int QSGVisualDataModelDataMetaObject::createProperty(const char *name, const char *type)
422 QSGVisualDataModelData *data =
423 static_cast<QSGVisualDataModelData *>(object());
428 QSGVisualDataModelPrivate *model = QSGVisualDataModelPrivate::get(data->m_model);
429 if (data->m_index < 0 || data->m_index >= model->modelCount())
432 if ((!model->m_listModelInterface || !model->m_abstractItemModel) && model->m_listAccessor) {
433 if (model->m_listAccessor->type() == QDeclarativeListAccessor::ListProperty) {
434 model->ensureRoles();
435 if (qstrcmp(name,"modelData") == 0)
436 return QDeclarativeOpenMetaObject::createProperty(name, type);
442 QVariant QSGVisualDataModelDataMetaObject::initialValue(int propId)
444 QSGVisualDataModelData *data =
445 static_cast<QSGVisualDataModelData *>(object());
447 Q_ASSERT(data->m_model);
448 QSGVisualDataModelPrivate *model = QSGVisualDataModelPrivate::get(data->m_model);
450 QByteArray propName = name(propId);
451 if ((!model->m_listModelInterface || !model->m_abstractItemModel) && model->m_listAccessor) {
452 if (propName == "modelData") {
453 if (model->m_listAccessor->type() == QDeclarativeListAccessor::Instance) {
454 QObject *object = model->m_listAccessor->at(0).value<QObject*>();
455 return object->metaObject()->property(1).read(object); // the first property after objectName
457 return model->m_listAccessor->at(data->m_index);
459 // return any property of a single object instance.
460 QObject *object = model->m_listAccessor->at(data->m_index).value<QObject*>();
461 return object->property(propName);
463 } else if (model->m_listModelInterface) {
464 model->ensureRoles();
465 QHash<QByteArray,int>::const_iterator it = model->m_roleNames.find(propName);
466 if (it != model->m_roleNames.end()) {
467 QVariant value = model->m_listModelInterface->data(data->m_index, *it);
469 } else if (model->m_roles.count() == 1 && propName == "modelData") {
470 //for compatibility with other lists, assign modelData if there is only a single role
471 QVariant value = model->m_listModelInterface->data(data->m_index, model->m_roles.first());
474 } else if (model->m_abstractItemModel) {
475 model->ensureRoles();
476 QModelIndex index = model->m_abstractItemModel->index(data->m_index, 0, model->m_root);
477 if (propName == "hasModelChildren") {
478 return model->m_abstractItemModel->hasChildren(index);
480 QHash<QByteArray,int>::const_iterator it = model->m_roleNames.find(propName);
481 if (it != model->m_roleNames.end()) {
482 return model->m_abstractItemModel->data(index, *it);
483 } else if (model->m_roles.count() == 1 && propName == "modelData") {
484 //for compatibility with other lists, assign modelData if there is only a single role
485 return model->m_abstractItemModel->data(index, model->m_roles.first());
489 Q_ASSERT(!"Can never be reached");
493 QSGVisualDataModelData::QSGVisualDataModelData(int index,
494 QSGVisualDataModel *model)
495 : m_index(index), m_model(model),
496 m_meta(new QSGVisualDataModelDataMetaObject(this, QSGVisualDataModelPrivate::get(model)->m_delegateDataType))
501 QSGVisualDataModelData::~QSGVisualDataModelData()
505 void QSGVisualDataModelData::ensureProperties()
507 QSGVisualDataModelPrivate *modelPriv = QSGVisualDataModelPrivate::get(m_model);
508 if (modelPriv->m_metaDataCacheable) {
509 if (!modelPriv->m_metaDataCreated)
510 modelPriv->createMetaData();
511 if (modelPriv->m_metaDataCreated)
512 m_meta->setCached(true);
516 int QSGVisualDataModelData::index() const
521 // This is internal only - it should not be set from qml
522 void QSGVisualDataModelData::setIndex(int index)
528 //---------------------------------------------------------------------------
530 class QSGVisualDataModelPartsMetaObject : public QDeclarativeOpenMetaObject
533 QSGVisualDataModelPartsMetaObject(QObject *parent)
534 : QDeclarativeOpenMetaObject(parent) {}
536 virtual void propertyCreated(int, QMetaPropertyBuilder &);
537 virtual QVariant initialValue(int);
540 class QSGVisualDataModelParts : public QObject
544 QSGVisualDataModelParts(QSGVisualDataModel *parent);
547 friend class QSGVisualDataModelPartsMetaObject;
548 QSGVisualDataModel *model;
551 void QSGVisualDataModelPartsMetaObject::propertyCreated(int, QMetaPropertyBuilder &prop)
553 prop.setWritable(false);
556 QVariant QSGVisualDataModelPartsMetaObject::initialValue(int id)
558 QSGVisualDataModel *m = new QSGVisualDataModel;
559 m->setParent(object());
560 m->setPart(QString::fromUtf8(name(id)));
561 m->setModel(QVariant::fromValue(static_cast<QSGVisualDataModelParts *>(object())->model));
563 QVariant var = QVariant::fromValue((QObject *)m);
567 QSGVisualDataModelParts::QSGVisualDataModelParts(QSGVisualDataModel *parent)
568 : QObject(parent), model(parent)
570 new QSGVisualDataModelPartsMetaObject(this);
573 QSGVisualDataModelPrivate::QSGVisualDataModelPrivate(QDeclarativeContext *ctxt)
574 : m_listModelInterface(0), m_abstractItemModel(0), m_visualItemModel(0), m_delegate(0)
575 , m_context(ctxt), m_modelDataPropId(-1), m_parts(0), m_delegateDataType(0), m_metaDataCreated(false)
576 , m_metaDataCacheable(false), m_delegateValidated(false), m_completePending(false), m_listAccessor(0)
580 QSGVisualDataModelData *QSGVisualDataModelPrivate::data(QObject *item)
582 QSGVisualDataModelData *dataItem =
583 item->findChild<QSGVisualDataModelData *>();
588 //---------------------------------------------------------------------------
590 QSGVisualDataModel::QSGVisualDataModel()
591 : QSGVisualModel(*(new QSGVisualDataModelPrivate(0)))
595 QSGVisualDataModel::QSGVisualDataModel(QDeclarativeContext *ctxt, QObject *parent)
596 : QSGVisualModel(*(new QSGVisualDataModelPrivate(ctxt)), parent)
600 QSGVisualDataModel::~QSGVisualDataModel()
602 Q_D(QSGVisualDataModel);
603 if (d->m_listAccessor)
604 delete d->m_listAccessor;
605 if (d->m_delegateDataType)
606 d->m_delegateDataType->release();
609 QVariant QSGVisualDataModel::model() const
611 Q_D(const QSGVisualDataModel);
612 return d->m_modelVariant;
615 void QSGVisualDataModel::setModel(const QVariant &model)
617 Q_D(QSGVisualDataModel);
618 delete d->m_listAccessor;
619 d->m_listAccessor = 0;
620 d->m_modelVariant = model;
621 if (d->m_listModelInterface) {
622 // Assume caller has released all items.
623 QObject::disconnect(d->m_listModelInterface, SIGNAL(itemsChanged(int,int,QList<int>)),
624 this, SLOT(_q_itemsChanged(int,int,QList<int>)));
625 QObject::disconnect(d->m_listModelInterface, SIGNAL(itemsInserted(int,int)),
626 this, SLOT(_q_itemsInserted(int,int)));
627 QObject::disconnect(d->m_listModelInterface, SIGNAL(itemsRemoved(int,int)),
628 this, SLOT(_q_itemsRemoved(int,int)));
629 QObject::disconnect(d->m_listModelInterface, SIGNAL(itemsMoved(int,int,int)),
630 this, SLOT(_q_itemsMoved(int,int,int)));
631 d->m_listModelInterface = 0;
632 } else if (d->m_abstractItemModel) {
633 QObject::disconnect(d->m_abstractItemModel, SIGNAL(rowsInserted(QModelIndex,int,int)),
634 this, SLOT(_q_rowsInserted(QModelIndex,int,int)));
635 QObject::disconnect(d->m_abstractItemModel, SIGNAL(rowsRemoved(QModelIndex,int,int)),
636 this, SLOT(_q_rowsRemoved(QModelIndex,int,int)));
637 QObject::disconnect(d->m_abstractItemModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
638 this, SLOT(_q_dataChanged(QModelIndex,QModelIndex)));
639 QObject::disconnect(d->m_abstractItemModel, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)),
640 this, SLOT(_q_rowsMoved(QModelIndex,int,int,QModelIndex,int)));
641 QObject::disconnect(d->m_abstractItemModel, SIGNAL(modelReset()), this, SLOT(_q_modelReset()));
642 QObject::disconnect(d->m_abstractItemModel, SIGNAL(layoutChanged()), this, SLOT(_q_layoutChanged()));
643 d->m_abstractItemModel = 0;
644 } else if (d->m_visualItemModel) {
645 QObject::disconnect(d->m_visualItemModel, SIGNAL(itemsInserted(int,int)),
646 this, SIGNAL(itemsInserted(int,int)));
647 QObject::disconnect(d->m_visualItemModel, SIGNAL(itemsRemoved(int,int)),
648 this, SIGNAL(itemsRemoved(int,int)));
649 QObject::disconnect(d->m_visualItemModel, SIGNAL(itemsMoved(int,int,int)),
650 this, SIGNAL(itemsMoved(int,int,int)));
651 QObject::disconnect(d->m_visualItemModel, SIGNAL(createdPackage(int,QDeclarativePackage*)),
652 this, SLOT(_q_createdPackage(int,QDeclarativePackage*)));
653 QObject::disconnect(d->m_visualItemModel, SIGNAL(destroyingPackage(QDeclarativePackage*)),
654 this, SLOT(_q_destroyingPackage(QDeclarativePackage*)));
655 d->m_visualItemModel = 0;
659 d->m_roleNames.clear();
660 if (d->m_delegateDataType)
661 d->m_delegateDataType->release();
662 d->m_metaDataCreated = 0;
663 d->m_metaDataCacheable = false;
664 d->m_delegateDataType = new VDMDelegateDataType(&QSGVisualDataModelData::staticMetaObject, d->m_context?d->m_context->engine():qmlEngine(this));
666 QObject *object = qvariant_cast<QObject *>(model);
667 if (object && (d->m_listModelInterface = qobject_cast<QListModelInterface *>(object))) {
668 QObject::connect(d->m_listModelInterface, SIGNAL(itemsChanged(int,int,QList<int>)),
669 this, SLOT(_q_itemsChanged(int,int,QList<int>)));
670 QObject::connect(d->m_listModelInterface, SIGNAL(itemsInserted(int,int)),
671 this, SLOT(_q_itemsInserted(int,int)));
672 QObject::connect(d->m_listModelInterface, SIGNAL(itemsRemoved(int,int)),
673 this, SLOT(_q_itemsRemoved(int,int)));
674 QObject::connect(d->m_listModelInterface, SIGNAL(itemsMoved(int,int,int)),
675 this, SLOT(_q_itemsMoved(int,int,int)));
676 d->m_metaDataCacheable = true;
677 if (d->m_delegate && d->m_listModelInterface->count())
678 emit itemsInserted(0, d->m_listModelInterface->count());
680 } else if (object && (d->m_abstractItemModel = qobject_cast<QAbstractItemModel *>(object))) {
681 QObject::connect(d->m_abstractItemModel, SIGNAL(rowsInserted(QModelIndex,int,int)),
682 this, SLOT(_q_rowsInserted(QModelIndex,int,int)));
683 QObject::connect(d->m_abstractItemModel, SIGNAL(rowsRemoved(QModelIndex,int,int)),
684 this, SLOT(_q_rowsRemoved(QModelIndex,int,int)));
685 QObject::connect(d->m_abstractItemModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
686 this, SLOT(_q_dataChanged(QModelIndex,QModelIndex)));
687 QObject::connect(d->m_abstractItemModel, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)),
688 this, SLOT(_q_rowsMoved(QModelIndex,int,int,QModelIndex,int)));
689 QObject::connect(d->m_abstractItemModel, SIGNAL(modelReset()), this, SLOT(_q_modelReset()));
690 QObject::connect(d->m_abstractItemModel, SIGNAL(layoutChanged()), this, SLOT(_q_layoutChanged()));
691 d->m_metaDataCacheable = true;
692 if (d->m_abstractItemModel->canFetchMore(d->m_root))
693 d->m_abstractItemModel->fetchMore(d->m_root);
696 if ((d->m_visualItemModel = qvariant_cast<QSGVisualDataModel *>(model))) {
697 QObject::connect(d->m_visualItemModel, SIGNAL(itemsInserted(int,int)),
698 this, SIGNAL(itemsInserted(int,int)));
699 QObject::connect(d->m_visualItemModel, SIGNAL(itemsRemoved(int,int)),
700 this, SIGNAL(itemsRemoved(int,int)));
701 QObject::connect(d->m_visualItemModel, SIGNAL(itemsMoved(int,int,int)),
702 this, SIGNAL(itemsMoved(int,int,int)));
703 QObject::connect(d->m_visualItemModel, SIGNAL(createdPackage(int,QDeclarativePackage*)),
704 this, SLOT(_q_createdPackage(int,QDeclarativePackage*)));
705 QObject::connect(d->m_visualItemModel, SIGNAL(destroyingPackage(QDeclarativePackage*)),
706 this, SLOT(_q_destroyingPackage(QDeclarativePackage*)));
709 d->m_listAccessor = new QDeclarativeListAccessor;
710 d->m_listAccessor->setList(model, d->m_context?d->m_context->engine():qmlEngine(this));
711 if (d->m_listAccessor->type() != QDeclarativeListAccessor::ListProperty)
712 d->m_metaDataCacheable = true;
713 if (d->m_delegate && d->modelCount()) {
714 emit itemsInserted(0, d->modelCount());
719 QDeclarativeComponent *QSGVisualDataModel::delegate() const
721 Q_D(const QSGVisualDataModel);
722 if (d->m_visualItemModel)
723 return d->m_visualItemModel->delegate();
724 return d->m_delegate;
727 void QSGVisualDataModel::setDelegate(QDeclarativeComponent *delegate)
729 Q_D(QSGVisualDataModel);
730 bool wasValid = d->m_delegate != 0;
731 d->m_delegate = delegate;
732 d->m_delegateValidated = false;
733 if (!wasValid && d->modelCount() && d->m_delegate) {
734 emit itemsInserted(0, d->modelCount());
737 if (wasValid && !d->m_delegate && d->modelCount()) {
738 emit itemsRemoved(0, d->modelCount());
743 QVariant QSGVisualDataModel::rootIndex() const
745 Q_D(const QSGVisualDataModel);
746 return QVariant::fromValue(d->m_root);
749 void QSGVisualDataModel::setRootIndex(const QVariant &root)
751 Q_D(QSGVisualDataModel);
752 QModelIndex modelIndex = qvariant_cast<QModelIndex>(root);
753 if (d->m_root != modelIndex) {
754 int oldCount = d->modelCount();
755 d->m_root = modelIndex;
756 if (d->m_abstractItemModel && d->m_abstractItemModel->canFetchMore(modelIndex))
757 d->m_abstractItemModel->fetchMore(modelIndex);
758 int newCount = d->modelCount();
759 if (d->m_delegate && oldCount)
760 emit itemsRemoved(0, oldCount);
761 if (d->m_delegate && newCount)
762 emit itemsInserted(0, newCount);
763 if (newCount != oldCount)
765 emit rootIndexChanged();
769 QVariant QSGVisualDataModel::modelIndex(int idx) const
771 Q_D(const QSGVisualDataModel);
772 if (d->m_abstractItemModel)
773 return QVariant::fromValue(d->m_abstractItemModel->index(idx, 0, d->m_root));
774 return QVariant::fromValue(QModelIndex());
777 QVariant QSGVisualDataModel::parentModelIndex() const
779 Q_D(const QSGVisualDataModel);
780 if (d->m_abstractItemModel)
781 return QVariant::fromValue(d->m_abstractItemModel->parent(d->m_root));
782 return QVariant::fromValue(QModelIndex());
785 QString QSGVisualDataModel::part() const
787 Q_D(const QSGVisualDataModel);
791 void QSGVisualDataModel::setPart(const QString &part)
793 Q_D(QSGVisualDataModel);
797 int QSGVisualDataModel::count() const
799 Q_D(const QSGVisualDataModel);
800 if (d->m_visualItemModel)
801 return d->m_visualItemModel->count();
804 return d->modelCount();
807 QSGItem *QSGVisualDataModel::item(int index, bool complete)
809 Q_D(QSGVisualDataModel);
810 if (d->m_visualItemModel)
811 return d->m_visualItemModel->item(index, d->m_part.toUtf8(), complete);
812 return item(index, QByteArray(), complete);
816 Returns ReleaseStatus flags.
818 QSGVisualDataModel::ReleaseFlags QSGVisualDataModel::release(QSGItem *item)
820 Q_D(QSGVisualDataModel);
821 if (d->m_visualItemModel)
822 return d->m_visualItemModel->release(item);
824 ReleaseFlags stat = 0;
826 bool inPackage = false;
828 QHash<QObject*,QDeclarativePackage*>::iterator it = d->m_packaged.find(item);
829 if (it != d->m_packaged.end()) {
830 QDeclarativePackage *package = *it;
831 d->m_packaged.erase(it);
832 if (d->m_packaged.contains(item))
835 obj = package; // fall through and delete
838 if (d->m_cache.releaseItem(obj)) {
839 // Remove any bindings to avoid warnings due to parent change.
840 QObjectPrivate *p = QObjectPrivate::get(obj);
841 Q_ASSERT(p->declarativeData);
842 QDeclarativeData *d = static_cast<QDeclarativeData*>(p->declarativeData);
843 if (d->ownContext && d->context)
844 d->context->clearContext();
847 emit destroyingPackage(qobject_cast<QDeclarativePackage*>(obj));
849 // XXX todo - the original did item->scene()->removeItem(). Why?
850 item->setParentItem(0);
854 } else if (!inPackage) {
861 QObject *QSGVisualDataModel::parts()
863 Q_D(QSGVisualDataModel);
865 d->m_parts = new QSGVisualDataModelParts(this);
869 QSGItem *QSGVisualDataModel::item(int index, const QByteArray &viewId, bool complete)
871 Q_D(QSGVisualDataModel);
872 if (d->m_visualItemModel)
873 return d->m_visualItemModel->item(index, viewId, complete);
875 if (d->modelCount() <= 0 || !d->m_delegate)
877 QObject *nobj = d->m_cache.getItem(index);
878 bool needComplete = false;
880 QDeclarativeContext *ccontext = d->m_context;
881 if (!ccontext) ccontext = qmlContext(this);
882 QDeclarativeContext *ctxt = new QDeclarativeContext(ccontext);
883 QSGVisualDataModelData *data = new QSGVisualDataModelData(index, this);
884 if ((!d->m_listModelInterface || !d->m_abstractItemModel) && d->m_listAccessor
885 && d->m_listAccessor->type() == QDeclarativeListAccessor::ListProperty) {
886 ctxt->setContextObject(d->m_listAccessor->at(index).value<QObject*>());
887 ctxt = new QDeclarativeContext(ctxt, ctxt);
889 ctxt->setContextProperty(QLatin1String("model"), data);
890 ctxt->setContextObject(data);
891 d->m_completePending = false;
892 nobj = d->m_delegate->beginCreate(ctxt);
894 d->m_delegate->completeCreate();
896 d->m_completePending = true;
900 QDeclarative_setParent_noEvent(ctxt, nobj);
901 QDeclarative_setParent_noEvent(data, nobj);
902 d->m_cache.insertItem(index, nobj);
903 if (QDeclarativePackage *package = qobject_cast<QDeclarativePackage *>(nobj))
904 emit createdPackage(index, package);
908 qmlInfo(this, d->m_delegate->errors()) << "Error creating delegate";
911 QSGItem *item = qobject_cast<QSGItem *>(nobj);
913 QDeclarativePackage *package = qobject_cast<QDeclarativePackage *>(nobj);
915 QObject *o = package->part(QString::fromUtf8(viewId));
916 item = qobject_cast<QSGItem *>(o);
918 d->m_packaged.insertMulti(item, package);
923 d->m_delegate->completeCreate();
924 d->m_cache.releaseItem(nobj);
925 if (!d->m_delegateValidated) {
926 qmlInfo(d->m_delegate) << QSGVisualDataModel::tr("Delegate component must be Item type.");
927 d->m_delegateValidated = true;
930 if (d->modelCount()-1 == index && d->m_abstractItemModel && d->m_abstractItemModel->canFetchMore(d->m_root))
931 d->m_abstractItemModel->fetchMore(d->m_root);
936 bool QSGVisualDataModel::completePending() const
938 Q_D(const QSGVisualDataModel);
939 if (d->m_visualItemModel)
940 return d->m_visualItemModel->completePending();
941 return d->m_completePending;
944 void QSGVisualDataModel::completeItem()
946 Q_D(QSGVisualDataModel);
947 if (d->m_visualItemModel) {
948 d->m_visualItemModel->completeItem();
952 d->m_delegate->completeCreate();
953 d->m_completePending = false;
956 QString QSGVisualDataModel::stringValue(int index, const QString &name)
958 Q_D(QSGVisualDataModel);
959 if (d->m_visualItemModel)
960 return d->m_visualItemModel->stringValue(index, name);
962 if ((!d->m_listModelInterface || !d->m_abstractItemModel) && d->m_listAccessor) {
963 if (QObject *object = d->m_listAccessor->at(index).value<QObject*>())
964 return object->property(name.toUtf8()).toString();
967 if ((!d->m_listModelInterface && !d->m_abstractItemModel) || !d->m_delegate)
972 bool tempData = false;
974 if (QObject *nobj = d->m_cache.item(index))
975 data = d->data(nobj);
977 data = new QSGVisualDataModelData(index, this);
981 QDeclarativeData *ddata = QDeclarativeData::get(data);
982 if (ddata && ddata->propertyCache) {
983 QDeclarativePropertyCache::Data *prop = ddata->propertyCache->property(name);
985 if (prop->propType == QVariant::String) {
986 void *args[] = { &val, 0 };
987 QMetaObject::metacall(data, QMetaObject::ReadProperty, prop->coreIndex, args);
988 } else if (prop->propType == qMetaTypeId<QVariant>()) {
990 void *args[] = { &v, 0 };
991 QMetaObject::metacall(data, QMetaObject::ReadProperty, prop->coreIndex, args);
995 val = data->property(name.toUtf8()).toString();
998 val = data->property(name.toUtf8()).toString();
1007 int QSGVisualDataModel::indexOf(QSGItem *item, QObject *) const
1009 QVariant val = QDeclarativeEngine::contextForObject(item)->contextProperty(QLatin1String("index"));
1014 void QSGVisualDataModel::setWatchedRoles(QList<QByteArray> roles)
1016 Q_D(QSGVisualDataModel);
1017 d->watchedRoles = roles;
1018 d->watchedRoleIds.clear();
1021 void QSGVisualDataModel::_q_itemsChanged(int index, int count,
1022 const QList<int> &roles)
1024 Q_D(QSGVisualDataModel);
1025 bool changed = false;
1026 if (!d->watchedRoles.isEmpty() && d->watchedRoleIds.isEmpty()) {
1027 foreach (QByteArray r, d->watchedRoles) {
1028 if (d->m_roleNames.contains(r))
1029 d->watchedRoleIds << d->m_roleNames.value(r);
1033 for (QHash<int,QSGVisualDataModelPrivate::ObjectRef>::ConstIterator iter = d->m_cache.begin();
1034 iter != d->m_cache.end(); ++iter) {
1035 const int idx = iter.key();
1037 if (idx >= index && idx < index+count) {
1038 QSGVisualDataModelPrivate::ObjectRef objRef = *iter;
1039 QSGVisualDataModelData *data = d->data(objRef.obj);
1040 for (int roleIdx = 0; roleIdx < roles.count(); ++roleIdx) {
1041 int role = roles.at(roleIdx);
1042 if (!changed && !d->watchedRoleIds.isEmpty() && d->watchedRoleIds.contains(role))
1044 int propId = data->propForRole(role);
1046 if (data->hasValue(propId)) {
1047 if (d->m_listModelInterface) {
1048 data->setValue(propId, d->m_listModelInterface->data(idx, role));
1049 } else if (d->m_abstractItemModel) {
1050 QModelIndex index = d->m_abstractItemModel->index(idx, 0, d->m_root);
1051 data->setValue(propId, d->m_abstractItemModel->data(index, role));
1056 if (d->m_listModelInterface)
1057 roleName = d->m_listModelInterface->toString(role);
1058 else if (d->m_abstractItemModel)
1059 roleName = QString::fromUtf8(d->m_abstractItemModel->roleNames().value(role));
1060 qmlInfo(this) << "Changing role not present in item: " << roleName;
1063 if (d->m_roles.count() == 1) {
1064 // Handle the modelData role we add if there is just one role.
1065 int propId = data->modelDataPropertyId();
1066 if (data->hasValue(propId)) {
1067 int role = d->m_roles.at(0);
1068 if (d->m_listModelInterface) {
1069 data->setValue(propId, d->m_listModelInterface->data(idx, role));
1070 } else if (d->m_abstractItemModel) {
1071 QModelIndex index = d->m_abstractItemModel->index(idx, 0, d->m_root);
1072 data->setValue(propId, d->m_abstractItemModel->data(index, role));
1079 emit itemsChanged(index, count);
1082 void QSGVisualDataModel::_q_itemsInserted(int index, int count)
1084 Q_D(QSGVisualDataModel);
1087 // XXX - highly inefficient
1088 QHash<int,QSGVisualDataModelPrivate::ObjectRef> items;
1089 for (QHash<int,QSGVisualDataModelPrivate::ObjectRef>::Iterator iter = d->m_cache.begin();
1090 iter != d->m_cache.end(); ) {
1092 if (iter.key() >= index) {
1093 QSGVisualDataModelPrivate::ObjectRef objRef = *iter;
1094 int index = iter.key() + count;
1095 iter = d->m_cache.erase(iter);
1097 items.insert(index, objRef);
1099 QSGVisualDataModelData *data = d->data(objRef.obj);
1100 data->setIndex(index);
1105 d->m_cache.unite(items);
1107 emit itemsInserted(index, count);
1108 emit countChanged();
1111 void QSGVisualDataModel::_q_itemsRemoved(int index, int count)
1113 Q_D(QSGVisualDataModel);
1116 // XXX - highly inefficient
1117 QHash<int, QSGVisualDataModelPrivate::ObjectRef> items;
1118 for (QHash<int, QSGVisualDataModelPrivate::ObjectRef>::Iterator iter = d->m_cache.begin();
1119 iter != d->m_cache.end(); ) {
1120 if (iter.key() >= index && iter.key() < index + count) {
1121 QSGVisualDataModelPrivate::ObjectRef objRef = *iter;
1122 iter = d->m_cache.erase(iter);
1123 items.insertMulti(-1, objRef); //XXX perhaps better to maintain separately
1124 QSGVisualDataModelData *data = d->data(objRef.obj);
1126 } else if (iter.key() >= index + count) {
1127 QSGVisualDataModelPrivate::ObjectRef objRef = *iter;
1128 int index = iter.key() - count;
1129 iter = d->m_cache.erase(iter);
1130 items.insert(index, objRef);
1131 QSGVisualDataModelData *data = d->data(objRef.obj);
1132 data->setIndex(index);
1138 d->m_cache.unite(items);
1139 emit itemsRemoved(index, count);
1140 emit countChanged();
1143 void QSGVisualDataModel::_q_itemsMoved(int from, int to, int count)
1145 Q_D(QSGVisualDataModel);
1146 // XXX - highly inefficient
1147 QHash<int,QSGVisualDataModelPrivate::ObjectRef> items;
1148 for (QHash<int,QSGVisualDataModelPrivate::ObjectRef>::Iterator iter = d->m_cache.begin();
1149 iter != d->m_cache.end(); ) {
1151 if (iter.key() >= from && iter.key() < from + count) {
1152 QSGVisualDataModelPrivate::ObjectRef objRef = *iter;
1153 int index = iter.key() - from + to;
1154 iter = d->m_cache.erase(iter);
1156 items.insert(index, objRef);
1158 QSGVisualDataModelData *data = d->data(objRef.obj);
1159 data->setIndex(index);
1164 for (QHash<int,QSGVisualDataModelPrivate::ObjectRef>::Iterator iter = d->m_cache.begin();
1165 iter != d->m_cache.end(); ) {
1167 int diff = from > to ? count : -count;
1168 if (iter.key() >= qMin(from,to) && iter.key() < qMax(from+count,to+count)) {
1169 QSGVisualDataModelPrivate::ObjectRef objRef = *iter;
1170 int index = iter.key() + diff;
1171 iter = d->m_cache.erase(iter);
1173 items.insert(index, objRef);
1175 QSGVisualDataModelData *data = d->data(objRef.obj);
1176 data->setIndex(index);
1181 d->m_cache.unite(items);
1183 emit itemsMoved(from, to, count);
1186 void QSGVisualDataModel::_q_rowsInserted(const QModelIndex &parent, int begin, int end)
1188 Q_D(QSGVisualDataModel);
1189 if (parent == d->m_root)
1190 _q_itemsInserted(begin, end - begin + 1);
1193 void QSGVisualDataModel::_q_rowsRemoved(const QModelIndex &parent, int begin, int end)
1195 Q_D(QSGVisualDataModel);
1196 if (parent == d->m_root)
1197 _q_itemsRemoved(begin, end - begin + 1);
1200 void QSGVisualDataModel::_q_rowsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationRow)
1202 Q_D(QSGVisualDataModel);
1203 const int count = sourceEnd - sourceStart + 1;
1204 if (destinationParent == d->m_root && sourceParent == d->m_root) {
1205 _q_itemsMoved(sourceStart, sourceStart > destinationRow ? destinationRow : destinationRow-1, count);
1206 } else if (sourceParent == d->m_root) {
1207 _q_itemsRemoved(sourceStart, count);
1208 } else if (destinationParent == d->m_root) {
1209 _q_itemsInserted(destinationRow, count);
1213 void QSGVisualDataModel::_q_dataChanged(const QModelIndex &begin, const QModelIndex &end)
1215 Q_D(QSGVisualDataModel);
1216 if (begin.parent() == d->m_root)
1217 _q_itemsChanged(begin.row(), end.row() - begin.row() + 1, d->m_roles);
1220 void QSGVisualDataModel::_q_layoutChanged()
1222 Q_D(QSGVisualDataModel);
1223 _q_itemsChanged(0, count(), d->m_roles);
1226 void QSGVisualDataModel::_q_modelReset()
1231 void QSGVisualDataModel::_q_createdPackage(int index, QDeclarativePackage *package)
1233 Q_D(QSGVisualDataModel);
1234 emit createdItem(index, qobject_cast<QSGItem*>(package->part(d->m_part)));
1237 void QSGVisualDataModel::_q_destroyingPackage(QDeclarativePackage *package)
1239 Q_D(QSGVisualDataModel);
1240 emit destroyingItem(qobject_cast<QSGItem*>(package->part(d->m_part)));
1245 QML_DECLARE_TYPE(QListModelInterface)
1247 #include <qsgvisualitemmodel.moc>