1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include "qquickvisualadaptormodel_p.h"
43 #include "qquickitem.h"
45 #include <QtDeclarative/qdeclarativecontext.h>
46 #include <QtDeclarative/qdeclarativeengine.h>
47 #include <QtDeclarative/qdeclarativeexpression.h>
48 #include <QtDeclarative/qdeclarativeinfo.h>
50 #include <private/qdeclarativecontext_p.h>
51 #include <private/qdeclarativepackage_p.h>
52 #include <private/qdeclarativeopenmetaobject_p.h>
53 #include <private/qdeclarativelistaccessor_p.h>
54 #include <private/qdeclarativedata_p.h>
55 #include <private/qdeclarativepropertycache_p.h>
56 #include <private/qdeclarativeguard_p.h>
57 #include <private/qdeclarativeglobal_p.h>
58 #include <private/qlistmodelinterface_p.h>
59 #include <private/qmetaobjectbuilder_p.h>
60 #include <private/qdeclarativeproperty_p.h>
61 #include <private/qintrusivelist_p.h>
62 #include <private/qobject_p.h>
64 #include <QtCore/qhash.h>
65 #include <QtCore/qlist.h>
67 Q_DECLARE_METATYPE(QModelIndex)
71 class VDMDelegateDataType : public QDeclarativeRefCount
83 VDMDelegateDataType(const VDMDelegateDataType &type)
86 , propertyOffset(type.propertyOffset)
87 , signalOffset(type.signalOffset)
89 , builder(type.metaObject, QMetaObjectBuilder::Properties
90 | QMetaObjectBuilder::Signals
91 | QMetaObjectBuilder::SuperClass
92 | QMetaObjectBuilder::ClassName)
94 builder.setFlags(QMetaObjectBuilder::DynamicMetaObject);
97 ~VDMDelegateDataType()
100 propertyCache->release();
104 QMetaObject *metaObject;
105 QDeclarativePropertyCache *propertyCache;
109 QMetaObjectBuilder builder;
112 class QQuickVisualAdaptorModelData : public QObject
115 Q_PROPERTY(int index READ index NOTIFY indexChanged)
117 QQuickVisualAdaptorModelData(int index, QQuickVisualAdaptorModel *model);
118 ~QQuickVisualAdaptorModelData();
121 void setIndex(int index);
128 QDeclarativeGuard<QQuickVisualAdaptorModel> m_model;
129 QIntrusiveListNode m_cacheNode;
132 typedef QIntrusiveList<QQuickVisualAdaptorModelData, &QQuickVisualAdaptorModelData::m_cacheNode> QQuickVisualAdaptorModelDataCache;
134 class QQuickVisualAdaptorModelDataMetaObject;
135 class QQuickVisualAdaptorModelPrivate : public QObjectPrivate
137 Q_DECLARE_PUBLIC(QQuickVisualAdaptorModel)
139 QQuickVisualAdaptorModelPrivate()
142 , m_delegateDataType(0)
143 , createModelData(&initializeModelData)
146 , m_objectList(false)
151 static QQuickVisualAdaptorModelPrivate *get(QQuickVisualAdaptorModel *m) {
152 return static_cast<QQuickVisualAdaptorModelPrivate *>(QObjectPrivate::get(m));
155 void addProperty(int role, int propertyId, const char *propertyName, const char *propertyType, bool isModelData = false);
156 template <typename T> void setModelDataType()
158 createModelData = &T::create;
159 m_delegateDataType->builder.setFlags(QMetaObjectBuilder::DynamicMetaObject);
160 m_delegateDataType->builder.setClassName(T::staticMetaObject.className());
161 m_delegateDataType->builder.setSuperClass(&T::staticMetaObject);
162 m_delegateDataType->propertyOffset = T::staticMetaObject.propertyCount();
163 m_delegateDataType->signalOffset = T::staticMetaObject.methodCount();
165 QQuickVisualAdaptorModelData *createMetaObject(int index, QQuickVisualAdaptorModel *model);
167 static QQuickVisualAdaptorModelData *initializeModelData(int index, QQuickVisualAdaptorModel *model) {
168 return get(model)->createMetaObject(index, model);
171 typedef QQuickVisualAdaptorModelData *(*CreateModelData)(int index, QQuickVisualAdaptorModel *model);
173 struct PropertyData {
175 bool isModelData : 1;
178 int modelCount() const {
179 if (m_listModelInterface)
180 return m_listModelInterface->count();
181 if (m_abstractItemModel)
182 return m_abstractItemModel->rowCount(m_root);
184 return m_listAccessor->count();
188 QDeclarativeGuard<QDeclarativeEngine> m_engine;
189 QDeclarativeGuard<QListModelInterface> m_listModelInterface;
190 QDeclarativeGuard<QAbstractItemModel> m_abstractItemModel;
191 QDeclarativeListAccessor *m_listAccessor;
192 VDMDelegateDataType *m_delegateDataType;
193 CreateModelData createModelData;
197 QQuickVisualAdaptorModel::Flags m_flags;
198 bool m_objectList : 1;
200 QVariant m_modelVariant;
204 QList<int> watchedRoleIds;
205 QList<QByteArray> watchedRoles;
206 QHash<QByteArray,int> m_roleNames;
207 QVector<PropertyData> m_propertyData;
208 QQuickVisualAdaptorModelDataCache m_cache;
211 class QQuickVisualAdaptorModelDataMetaObject : public QAbstractDynamicMetaObject
214 QQuickVisualAdaptorModelDataMetaObject(QQuickVisualAdaptorModelData *data, VDMDelegateDataType *type)
218 QObjectPrivate *op = QObjectPrivate::get(m_data);
219 *static_cast<QMetaObject *>(this) = *type->metaObject;
220 op->metaObject = this;
224 ~QQuickVisualAdaptorModelDataMetaObject() { m_type->release(); }
226 QQuickVisualAdaptorModelData *m_data;
227 VDMDelegateDataType *m_type;
230 class QQuickVDMAbstractItemModelDataMetaObject : public QQuickVisualAdaptorModelDataMetaObject
233 QQuickVDMAbstractItemModelDataMetaObject(QQuickVisualAdaptorModelData *object, VDMDelegateDataType *type)
234 : QQuickVisualAdaptorModelDataMetaObject(object, type) {}
236 int metaCall(QMetaObject::Call call, int id, void **arguments)
238 if (call == QMetaObject::ReadProperty && id >= m_type->propertyOffset) {
239 QQuickVisualAdaptorModelPrivate *model = QQuickVisualAdaptorModelPrivate::get(m_data->m_model);
240 if (m_data->m_index == -1 || !model->m_abstractItemModel)
242 *static_cast<QVariant *>(arguments[0]) = model->m_abstractItemModel->index(
243 m_data->m_index, 0, model->m_root).data(model->m_propertyData.at(id - m_type->propertyOffset).role);
246 return m_data->qt_metacall(call, id, arguments);
251 class QQuickVDMAbstractItemModelData : public QQuickVisualAdaptorModelData
254 Q_PROPERTY(bool hasModelChildren READ hasModelChildren CONSTANT)
256 bool hasModelChildren() const
258 QQuickVisualAdaptorModelPrivate *model = QQuickVisualAdaptorModelPrivate::get(m_model);
259 return model->m_abstractItemModel->hasChildren(model->m_abstractItemModel->index(m_index, 0, model->m_root));
262 static QQuickVisualAdaptorModelData *create(int index, QQuickVisualAdaptorModel *model) {
263 return new QQuickVDMAbstractItemModelData(index, model); }
265 QQuickVDMAbstractItemModelData(int index, QQuickVisualAdaptorModel *model)
266 : QQuickVisualAdaptorModelData(index, model)
268 new QQuickVDMAbstractItemModelDataMetaObject(
269 this, QQuickVisualAdaptorModelPrivate::get(m_model)->m_delegateDataType);
273 class QQuickVDMListModelInterfaceDataMetaObject : public QQuickVisualAdaptorModelDataMetaObject
276 QQuickVDMListModelInterfaceDataMetaObject(QQuickVisualAdaptorModelData *object, VDMDelegateDataType *type)
277 : QQuickVisualAdaptorModelDataMetaObject(object, type) {}
279 int metaCall(QMetaObject::Call call, int id, void **arguments)
281 if (call == QMetaObject::ReadProperty && id >= m_type->propertyOffset) {
282 QQuickVisualAdaptorModelPrivate *model = QQuickVisualAdaptorModelPrivate::get(m_data->m_model);
283 if (m_data->m_index == -1 || !model->m_listModelInterface)
285 *static_cast<QVariant *>(arguments[0]) = model->m_listModelInterface->data(
286 m_data->m_index, model->m_propertyData.at(id - m_type->propertyOffset).role);
289 return m_data->qt_metacall(call, id, arguments);
294 class QQuickVDMListModelInterfaceData : public QQuickVisualAdaptorModelData
297 static QQuickVisualAdaptorModelData *create(int index, QQuickVisualAdaptorModel *model) {
298 return new QQuickVDMListModelInterfaceData(index, model); }
300 QQuickVDMListModelInterfaceData(int index, QQuickVisualAdaptorModel *model)
301 : QQuickVisualAdaptorModelData(index, model)
303 new QQuickVDMListModelInterfaceDataMetaObject(
304 this, QQuickVisualAdaptorModelPrivate::get(m_model)->m_delegateDataType);
308 class QQuickVDMListAccessorData : public QQuickVisualAdaptorModelData
311 Q_PROPERTY(QVariant modelData READ modelData CONSTANT)
313 QVariant modelData() const {
314 return QQuickVisualAdaptorModelPrivate::get(m_model)->m_listAccessor->at(m_index); }
316 static QQuickVisualAdaptorModelData *create(int index, QQuickVisualAdaptorModel *model) {
317 return new QQuickVDMListAccessorData(index, model); }
319 QQuickVDMListAccessorData(int index, QQuickVisualAdaptorModel *model)
320 : QQuickVisualAdaptorModelData(index, model)
325 class QQuickVDMObjectDataMetaObject : public QQuickVisualAdaptorModelDataMetaObject
328 QQuickVDMObjectDataMetaObject(QQuickVisualAdaptorModelData *data, VDMDelegateDataType *type)
329 : QQuickVisualAdaptorModelDataMetaObject(data, type)
330 , m_object(QQuickVisualAdaptorModelPrivate::get(data->m_model)->m_listAccessor->at(data->m_index).value<QObject *>())
333 int metaCall(QMetaObject::Call call, int id, void **arguments)
335 static const int objectPropertyOffset = QObject::staticMetaObject.propertyCount();
336 if (id >= m_type->propertyOffset
337 && (call == QMetaObject::ReadProperty
338 || call == QMetaObject::WriteProperty
339 || call == QMetaObject::ResetProperty)) {
341 QMetaObject::metacall(m_object, call, id - m_type->propertyOffset + objectPropertyOffset, arguments);
343 } else if (id >= m_type->signalOffset && call == QMetaObject::InvokeMetaMethod) {
344 QMetaObject::activate(m_data, this, id, 0);
347 return m_data->qt_metacall(call, id, arguments);
351 int createProperty(const char *name, const char *)
355 const QMetaObject *metaObject = m_object->metaObject();
356 static const int objectPropertyOffset = QObject::staticMetaObject.propertyCount();
358 const int previousPropertyCount = propertyCount() - propertyOffset();
359 int propertyIndex = metaObject->indexOfProperty(name);
360 if (propertyIndex == -1)
362 if (previousPropertyCount + objectPropertyOffset == metaObject->propertyCount())
363 return propertyIndex + m_type->propertyOffset - objectPropertyOffset;
365 if (m_type->shared) {
366 VDMDelegateDataType *type = m_type;
367 m_type = new VDMDelegateDataType(*m_type);
371 const int previousMethodCount = methodCount();
372 int notifierId = previousMethodCount;
373 for (int propertyId = previousPropertyCount; propertyId < metaObject->propertyCount() - objectPropertyOffset; ++propertyId) {
374 QMetaProperty property = metaObject->property(propertyId + objectPropertyOffset);
375 QMetaPropertyBuilder propertyBuilder;
376 if (property.hasNotifySignal()) {
377 m_type->builder.addSignal("__" + QByteArray::number(propertyId) + "()");
378 propertyBuilder = m_type->builder.addProperty(property.name(), property.typeName(), notifierId);
381 propertyBuilder = m_type->builder.addProperty(property.name(), property.typeName());
383 propertyBuilder.setWritable(property.isWritable());
384 propertyBuilder.setResettable(property.isResettable());
385 propertyBuilder.setConstant(property.isConstant());
388 if (m_type->metaObject)
389 qFree(m_type->metaObject);
390 m_type->metaObject = m_type->builder.toMetaObject();
391 *static_cast<QMetaObject *>(this) = *m_type->metaObject;
393 notifierId = previousMethodCount;
394 for (int i = previousPropertyCount; i < metaObject->propertyCount() - objectPropertyOffset; ++i) {
395 QMetaProperty property = metaObject->property(i + objectPropertyOffset);
396 if (property.hasNotifySignal()) {
397 QDeclarativePropertyPrivate::connect(
398 m_object, property.notifySignalIndex(), m_data, notifierId);
402 return propertyIndex + m_type->propertyOffset - objectPropertyOffset;
405 QDeclarativeGuard<QObject> m_object;
408 class QQuickVDMObjectData : public QQuickVisualAdaptorModelData, public QQuickVisualAdaptorModelProxyInterface
411 Q_PROPERTY(QObject *modelData READ modelData CONSTANT)
412 Q_INTERFACES(QQuickVisualAdaptorModelProxyInterface)
414 QObject *modelData() const { return m_metaObject->m_object; }
415 QObject *proxiedObject() { return m_metaObject->m_object; }
417 static QQuickVisualAdaptorModelData *create(int index, QQuickVisualAdaptorModel *model) {
418 return new QQuickVDMObjectData(index, model); }
421 QQuickVDMObjectData(int index, QQuickVisualAdaptorModel *model)
422 : QQuickVisualAdaptorModelData(index, model)
423 , m_metaObject(new QQuickVDMObjectDataMetaObject(this, QQuickVisualAdaptorModelPrivate::get(m_model)->m_delegateDataType))
427 QQuickVDMObjectDataMetaObject *m_metaObject;
430 void QQuickVisualAdaptorModelPrivate::addProperty(
431 int role, int propertyId, const char *propertyName, const char *propertyType, bool isModelData)
433 PropertyData propertyData;
434 propertyData.role = role;
435 propertyData.isModelData = isModelData;
436 m_delegateDataType->builder.addSignal("__" + QByteArray::number(propertyId) + "()");
437 QMetaPropertyBuilder property = m_delegateDataType->builder.addProperty(
438 propertyName, propertyType, propertyId);
439 property.setWritable(false);
441 m_propertyData.append(propertyData);
444 QQuickVisualAdaptorModelData *QQuickVisualAdaptorModelPrivate::createMetaObject(int index, QQuickVisualAdaptorModel *model)
446 Q_ASSERT(!m_delegateDataType);
448 m_objectList = false;
449 m_propertyData.clear();
451 && m_listAccessor->type() != QDeclarativeListAccessor::ListProperty
452 && m_listAccessor->type() != QDeclarativeListAccessor::Instance) {
453 createModelData = &QQuickVDMListAccessorData::create;
454 m_flags = QQuickVisualAdaptorModel::MetaObjectCacheable;
455 return QQuickVDMListAccessorData::create(index, model);
458 m_delegateDataType = new VDMDelegateDataType;
459 if (m_listModelInterface) {
460 setModelDataType<QQuickVDMListModelInterfaceData>();
461 QList<int> roles = m_listModelInterface->roles();
462 for (int propertyId = 0; propertyId < roles.count(); ++propertyId) {
463 const int role = roles.at(propertyId);
464 const QByteArray propertyName = m_listModelInterface->toString(role).toUtf8();
465 addProperty(role, propertyId, propertyName, "QVariant");
466 m_roleNames.insert(propertyName, role);
468 if (m_propertyData.count() == 1)
469 addProperty(roles.first(), 1, "modelData", "QVariant", true);
470 m_flags = QQuickVisualAdaptorModel::MetaObjectCacheable;
471 } else if (m_abstractItemModel) {
472 setModelDataType<QQuickVDMAbstractItemModelData>();
473 QHash<int, QByteArray> roleNames = m_abstractItemModel->roleNames();
474 for (QHash<int, QByteArray>::const_iterator it = roleNames.begin(); it != roleNames.end(); ++it) {
475 addProperty(it.key(), m_propertyData.count(), it.value(), "QVariant");
476 m_roleNames.insert(it.value(), it.key());
478 if (m_propertyData.count() == 1)
479 addProperty(roleNames.begin().key(), 1, "modelData", "QVariant", true);
480 m_flags = QQuickVisualAdaptorModel::MetaObjectCacheable;
481 } else if (m_listAccessor) {
482 setModelDataType<QQuickVDMObjectData>();
484 m_flags = QQuickVisualAdaptorModel::ProxiedObject;
486 Q_ASSERT(!"No model set on VisualDataModel");
489 m_delegateDataType->metaObject = m_delegateDataType->builder.toMetaObject();
491 m_delegateDataType->propertyCache = new QDeclarativePropertyCache(
492 m_engine, m_delegateDataType->metaObject);
494 return createModelData(index, model);
497 QQuickVisualAdaptorModelData::QQuickVisualAdaptorModelData(int index, QQuickVisualAdaptorModel *model)
503 QQuickVisualAdaptorModelData::~QQuickVisualAdaptorModelData()
507 int QQuickVisualAdaptorModelData::index() const
512 // This is internal only - it should not be set from qml
513 void QQuickVisualAdaptorModelData::setIndex(int index)
519 //---------------------------------------------------------------------------
521 QQuickVisualAdaptorModel::QQuickVisualAdaptorModel(QObject *parent)
522 : QObject(*(new QQuickVisualAdaptorModelPrivate), parent)
526 QQuickVisualAdaptorModel::~QQuickVisualAdaptorModel()
528 Q_D(QQuickVisualAdaptorModel);
529 if (d->m_listAccessor)
530 delete d->m_listAccessor;
531 if (d->m_delegateDataType)
532 d->m_delegateDataType->release();
535 QQuickVisualAdaptorModel::Flags QQuickVisualAdaptorModel::flags() const
537 Q_D(const QQuickVisualAdaptorModel);
541 QVariant QQuickVisualAdaptorModel::model() const
543 Q_D(const QQuickVisualAdaptorModel);
544 return d->m_modelVariant;
547 void QQuickVisualAdaptorModel::setModel(const QVariant &model, QDeclarativeEngine *engine)
549 Q_D(QQuickVisualAdaptorModel);
550 delete d->m_listAccessor;
551 d->m_engine = engine;
552 d->m_listAccessor = 0;
553 d->m_modelVariant = model;
554 if (d->m_listModelInterface) {
555 // Assume caller has released all items.
556 QObject::disconnect(d->m_listModelInterface, SIGNAL(itemsChanged(int,int,QList<int>)),
557 this, SLOT(_q_itemsChanged(int,int,QList<int>)));
558 QObject::disconnect(d->m_listModelInterface, SIGNAL(itemsInserted(int,int)),
559 this, SLOT(_q_itemsInserted(int,int)));
560 QObject::disconnect(d->m_listModelInterface, SIGNAL(itemsRemoved(int,int)),
561 this, SLOT(_q_itemsRemoved(int,int)));
562 QObject::disconnect(d->m_listModelInterface, SIGNAL(itemsMoved(int,int,int)),
563 this, SLOT(_q_itemsMoved(int,int,int)));
564 d->m_listModelInterface = 0;
565 } else if (d->m_abstractItemModel) {
566 QObject::disconnect(d->m_abstractItemModel, SIGNAL(rowsInserted(QModelIndex,int,int)),
567 this, SLOT(_q_rowsInserted(QModelIndex,int,int)));
568 QObject::disconnect(d->m_abstractItemModel, SIGNAL(rowsRemoved(QModelIndex,int,int)),
569 this, SLOT(_q_rowsRemoved(QModelIndex,int,int)));
570 QObject::disconnect(d->m_abstractItemModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
571 this, SLOT(_q_dataChanged(QModelIndex,QModelIndex)));
572 QObject::disconnect(d->m_abstractItemModel, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)),
573 this, SLOT(_q_rowsMoved(QModelIndex,int,int,QModelIndex,int)));
574 QObject::disconnect(d->m_abstractItemModel, SIGNAL(modelReset()), this, SLOT(_q_modelReset()));
575 QObject::disconnect(d->m_abstractItemModel, SIGNAL(layoutChanged()), this, SLOT(_q_layoutChanged()));
576 d->m_abstractItemModel = 0;
580 d->m_roleNames.clear();
581 d->m_flags = QQuickVisualAdaptorModel::Flags();
582 if (d->m_delegateDataType)
583 d->m_delegateDataType->release();
584 d->m_delegateDataType = 0;
585 d->createModelData = &QQuickVisualAdaptorModelPrivate::initializeModelData;
588 emit itemsRemoved(0, d->m_count);
590 QObject *object = qvariant_cast<QObject *>(model);
591 if (object && (d->m_listModelInterface = qobject_cast<QListModelInterface *>(object))) {
592 QObject::connect(d->m_listModelInterface, SIGNAL(itemsChanged(int,int,QList<int>)),
593 this, SLOT(_q_itemsChanged(int,int,QList<int>)));
594 QObject::connect(d->m_listModelInterface, SIGNAL(itemsInserted(int,int)),
595 this, SLOT(_q_itemsInserted(int,int)));
596 QObject::connect(d->m_listModelInterface, SIGNAL(itemsRemoved(int,int)),
597 this, SLOT(_q_itemsRemoved(int,int)));
598 QObject::connect(d->m_listModelInterface, SIGNAL(itemsMoved(int,int,int)),
599 this, SLOT(_q_itemsMoved(int,int,int)));
600 if ((d->m_count = d->m_listModelInterface->count()))
601 emit itemsInserted(0, d->m_count);
603 } else if (object && (d->m_abstractItemModel = qobject_cast<QAbstractItemModel *>(object))) {
604 QObject::connect(d->m_abstractItemModel, SIGNAL(rowsInserted(QModelIndex,int,int)),
605 this, SLOT(_q_rowsInserted(QModelIndex,int,int)));
606 QObject::connect(d->m_abstractItemModel, SIGNAL(rowsRemoved(QModelIndex,int,int)),
607 this, SLOT(_q_rowsRemoved(QModelIndex,int,int)));
608 QObject::connect(d->m_abstractItemModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
609 this, SLOT(_q_dataChanged(QModelIndex,QModelIndex)));
610 QObject::connect(d->m_abstractItemModel, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)),
611 this, SLOT(_q_rowsMoved(QModelIndex,int,int,QModelIndex,int)));
612 QObject::connect(d->m_abstractItemModel, SIGNAL(modelReset()), this, SLOT(_q_modelReset()));
613 QObject::connect(d->m_abstractItemModel, SIGNAL(layoutChanged()), this, SLOT(_q_layoutChanged()));
615 if ((d->m_count = d->m_abstractItemModel->rowCount(d->m_root)))
616 emit itemsInserted(0, d->m_count);
620 d->m_listAccessor = new QDeclarativeListAccessor;
621 d->m_listAccessor->setList(model, d->m_engine);
622 if ((d->m_count = d->m_listAccessor->count()))
623 emit itemsInserted(0, d->m_count);
626 QVariant QQuickVisualAdaptorModel::rootIndex() const
628 Q_D(const QQuickVisualAdaptorModel);
629 return QVariant::fromValue(d->m_root);
632 void QQuickVisualAdaptorModel::setRootIndex(const QVariant &root)
634 Q_D(QQuickVisualAdaptorModel);
635 QModelIndex modelIndex = qvariant_cast<QModelIndex>(root);
636 if (d->m_root != modelIndex) {
637 int oldCount = d->modelCount();
638 d->m_root = modelIndex;
639 if (d->m_abstractItemModel && d->m_abstractItemModel->canFetchMore(modelIndex))
640 d->m_abstractItemModel->fetchMore(modelIndex);
641 int newCount = d->modelCount();
643 emit itemsRemoved(0, oldCount);
645 emit itemsInserted(0, newCount);
646 emit rootIndexChanged();
650 QVariant QQuickVisualAdaptorModel::modelIndex(int idx) const
652 Q_D(const QQuickVisualAdaptorModel);
653 if (d->m_abstractItemModel)
654 return QVariant::fromValue(d->m_abstractItemModel->index(idx, 0, d->m_root));
655 return QVariant::fromValue(QModelIndex());
658 QVariant QQuickVisualAdaptorModel::parentModelIndex() const
660 Q_D(const QQuickVisualAdaptorModel);
661 if (d->m_abstractItemModel)
662 return QVariant::fromValue(d->m_abstractItemModel->parent(d->m_root));
663 return QVariant::fromValue(QModelIndex());
666 int QQuickVisualAdaptorModel::count() const
668 Q_D(const QQuickVisualAdaptorModel);
669 return d->modelCount();
672 QObject *QQuickVisualAdaptorModel::data(int index)
674 Q_D(QQuickVisualAdaptorModel);
675 QQuickVisualAdaptorModelData *data = d->createModelData(index, this);
676 d->m_cache.insert(data);
680 QString QQuickVisualAdaptorModel::stringValue(int index, const QString &name)
682 Q_D(QQuickVisualAdaptorModel);
683 if ((!d->m_listModelInterface || !d->m_abstractItemModel) && d->m_listAccessor) {
684 if (QObject *object = d->m_listAccessor->at(index).value<QObject*>())
685 return object->property(name.toUtf8()).toString();
689 QQuickVisualAdaptorModelData *data = d->createModelData(index, this);
691 QDeclarativeData *ddata = QDeclarativeData::get(data);
692 if (ddata && ddata->propertyCache) {
693 QDeclarativePropertyData *prop = ddata->propertyCache->property(name);
695 if (prop->propType == QVariant::String) {
696 void *args[] = { &val, 0 };
697 QMetaObject::metacall(data, QMetaObject::ReadProperty, prop->coreIndex, args);
698 } else if (prop->propType == qMetaTypeId<QVariant>()) {
700 void *args[] = { &v, 0 };
701 QMetaObject::metacall(data, QMetaObject::ReadProperty, prop->coreIndex, args);
705 val = data->property(name.toUtf8()).toString();
708 val = data->property(name.toUtf8()).toString();
716 int QQuickVisualAdaptorModel::indexOf(QObject *object) const
718 if (QQuickVisualAdaptorModelData *data = qobject_cast<QQuickVisualAdaptorModelData *>(object))
719 return data->index();
723 bool QQuickVisualAdaptorModel::canFetchMore() const
725 Q_D(const QQuickVisualAdaptorModel);
726 return d->m_abstractItemModel && d->m_abstractItemModel->canFetchMore(d->m_root);
729 void QQuickVisualAdaptorModel::fetchMore()
731 Q_D(QQuickVisualAdaptorModel);
732 if (d->m_abstractItemModel)
733 d->m_abstractItemModel->fetchMore(d->m_root);
736 void QQuickVisualAdaptorModel::replaceWatchedRoles(const QList<QByteArray> &oldRoles, const QList<QByteArray> &newRoles)
738 Q_D(QQuickVisualAdaptorModel);
739 d->watchedRoleIds.clear();
740 foreach (const QByteArray &oldRole, oldRoles)
741 d->watchedRoles.removeOne(oldRole);
742 d->watchedRoles += newRoles;
745 void QQuickVisualAdaptorModel::_q_itemsChanged(int index, int count, const QList<int> &roles)
747 Q_D(QQuickVisualAdaptorModel);
748 bool changed = roles.isEmpty();
749 if (!d->watchedRoles.isEmpty() && d->watchedRoleIds.isEmpty()) {
750 foreach (QByteArray r, d->watchedRoles) {
751 if (d->m_roleNames.contains(r))
752 d->watchedRoleIds << d->m_roleNames.value(r);
756 QVector<int> signalIndexes;
757 for (int i = 0; i < roles.count(); ++i) {
758 const int role = roles.at(i);
759 if (!changed && d->watchedRoleIds.contains(role))
761 for (int propertyId = 0; propertyId < d->m_propertyData.count(); ++propertyId) {
762 if (d->m_propertyData.at(propertyId).role == role)
763 signalIndexes.append(propertyId + d->m_delegateDataType->signalOffset);
766 if (roles.isEmpty()) {
767 for (int propertyId = 0; propertyId < d->m_propertyData.count(); ++propertyId)
768 signalIndexes.append(propertyId + d->m_delegateDataType->signalOffset);
771 typedef QQuickVisualAdaptorModelDataCache::iterator iterator;
772 for (iterator it = d->m_cache.begin(); it != d->m_cache.end(); ++it) {
773 const int idx = it->index();
774 if (idx >= index && idx < index + count) {
775 QQuickVisualAdaptorModelData *data = *it;
776 for (int i = 0; i < signalIndexes.count(); ++i)
777 QMetaObject::activate(data, signalIndexes.at(i), 0);
781 emit itemsChanged(index, count);
784 void QQuickVisualAdaptorModel::_q_itemsInserted(int index, int count)
786 Q_D(QQuickVisualAdaptorModel);
791 typedef QQuickVisualAdaptorModelDataCache::iterator iterator;
792 for (iterator it = d->m_cache.begin(); it != d->m_cache.end(); ++it) {
793 if (it->index() >= index)
794 it->setIndex(it->index() + count);
797 emit itemsInserted(index, count);
800 void QQuickVisualAdaptorModel::_q_itemsRemoved(int index, int count)
802 Q_D(QQuickVisualAdaptorModel);
807 typedef QQuickVisualAdaptorModelDataCache::iterator iterator;
808 for (iterator it = d->m_cache.begin(); it != d->m_cache.end(); ++it) {
809 if (it->index() >= index + count)
810 it->setIndex(it->index() - count);
811 else if (it->index() >= index)
815 emit itemsRemoved(index, count);
818 void QQuickVisualAdaptorModel::_q_itemsMoved(int from, int to, int count)
820 Q_D(QQuickVisualAdaptorModel);
821 const int minimum = qMin(from, to);
822 const int maximum = qMax(from, to) + count;
823 const int difference = from > to ? count : -count;
825 typedef QQuickVisualAdaptorModelDataCache::iterator iterator;
826 for (iterator it = d->m_cache.begin(); it != d->m_cache.end(); ++it) {
827 if (it->index() >= from && it->index() < from + count)
828 it->setIndex(it->index() - from + to);
829 else if (it->index() >= minimum && it->index() < maximum)
830 it->setIndex(it->index() + difference);
832 emit itemsMoved(from, to, count);
835 void QQuickVisualAdaptorModel::_q_rowsInserted(const QModelIndex &parent, int begin, int end)
837 Q_D(QQuickVisualAdaptorModel);
838 if (parent == d->m_root)
839 _q_itemsInserted(begin, end - begin + 1);
842 void QQuickVisualAdaptorModel::_q_rowsRemoved(const QModelIndex &parent, int begin, int end)
844 Q_D(QQuickVisualAdaptorModel);
845 if (parent == d->m_root)
846 _q_itemsRemoved(begin, end - begin + 1);
849 void QQuickVisualAdaptorModel::_q_rowsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationRow)
851 Q_D(QQuickVisualAdaptorModel);
852 const int count = sourceEnd - sourceStart + 1;
853 if (destinationParent == d->m_root && sourceParent == d->m_root) {
854 _q_itemsMoved(sourceStart, sourceStart > destinationRow ? destinationRow : destinationRow-count, count);
855 } else if (sourceParent == d->m_root) {
856 _q_itemsRemoved(sourceStart, count);
857 } else if (destinationParent == d->m_root) {
858 _q_itemsInserted(destinationRow, count);
862 void QQuickVisualAdaptorModel::_q_dataChanged(const QModelIndex &begin, const QModelIndex &end)
864 Q_D(QQuickVisualAdaptorModel);
865 if (begin.parent() == d->m_root)
866 _q_itemsChanged(begin.row(), end.row() - begin.row() + 1, d->m_roles);
869 void QQuickVisualAdaptorModel::_q_layoutChanged()
871 Q_D(QQuickVisualAdaptorModel);
872 _q_itemsChanged(0, count(), d->m_roles);
875 void QQuickVisualAdaptorModel::_q_modelReset()
877 Q_D(QQuickVisualAdaptorModel);
878 int oldCount = d->m_count;
879 d->m_root = QModelIndex();
880 d->m_count = d->modelCount();
881 emit modelReset(oldCount, d->m_count);
882 emit rootIndexChanged();
883 if (d->m_abstractItemModel && d->m_abstractItemModel->canFetchMore(d->m_root))
884 d->m_abstractItemModel->fetchMore(d->m_root);
889 QML_DECLARE_TYPE(QListModelInterface)
891 #include <qquickvisualadaptormodel.moc>