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 if (id >= m_type->propertyOffset
336 && (call == QMetaObject::ReadProperty
337 || call == QMetaObject::WriteProperty
338 || call == QMetaObject::ResetProperty)) {
340 QMetaObject::metacall(m_object, call, id - m_type->propertyOffset + 1, arguments);
342 } else if (id >= m_type->signalOffset && call == QMetaObject::InvokeMetaMethod) {
343 QMetaObject::activate(m_data, this, id, 0);
346 return m_data->qt_metacall(call, id, arguments);
350 int createProperty(const char *name, const char *)
354 const QMetaObject *metaObject = m_object->metaObject();
356 const int previousPropertyCount = propertyCount() - propertyOffset();
357 int propertyIndex = metaObject->indexOfProperty(name);
358 if (propertyIndex == -1)
360 if (previousPropertyCount + 1 == metaObject->propertyCount())
361 return propertyIndex + m_type->propertyOffset - 1;
363 if (m_type->shared) {
364 VDMDelegateDataType *type = m_type;
365 m_type = new VDMDelegateDataType(*m_type);
369 const int previousMethodCount = methodCount();
370 int notifierId = previousMethodCount;
371 for (int propertyId = previousPropertyCount; propertyId < metaObject->propertyCount() - 1; ++propertyId) {
372 QMetaProperty property = metaObject->property(propertyId + 1);
373 QMetaPropertyBuilder propertyBuilder;
374 if (property.hasNotifySignal()) {
375 m_type->builder.addSignal("__" + QByteArray::number(propertyId) + "()");
376 propertyBuilder = m_type->builder.addProperty(property.name(), property.typeName(), notifierId);
379 propertyBuilder = m_type->builder.addProperty(property.name(), property.typeName());
381 propertyBuilder.setWritable(property.isWritable());
382 propertyBuilder.setResettable(property.isResettable());
383 propertyBuilder.setConstant(property.isConstant());
386 if (m_type->metaObject)
387 qFree(m_type->metaObject);
388 m_type->metaObject = m_type->builder.toMetaObject();
389 *static_cast<QMetaObject *>(this) = *m_type->metaObject;
391 notifierId = previousMethodCount;
392 for (int i = previousPropertyCount; i < metaObject->propertyCount(); ++i) {
393 QMetaProperty property = metaObject->property(i);
394 if (property.hasNotifySignal()) {
395 QDeclarativePropertyPrivate::connect(
396 m_object, property.notifySignalIndex(), m_data, notifierId);
400 return propertyIndex + m_type->propertyOffset - 1;
403 QDeclarativeGuard<QObject> m_object;
406 class QQuickVDMObjectData : public QQuickVisualAdaptorModelData, public QQuickVisualAdaptorModelProxyInterface
409 Q_PROPERTY(QObject *modelData READ modelData CONSTANT)
410 Q_INTERFACES(QQuickVisualAdaptorModelProxyInterface)
412 QObject *modelData() const { return m_metaObject->m_object; }
413 QObject *proxiedObject() { return m_metaObject->m_object; }
415 static QQuickVisualAdaptorModelData *create(int index, QQuickVisualAdaptorModel *model) {
416 return new QQuickVDMObjectData(index, model); }
419 QQuickVDMObjectData(int index, QQuickVisualAdaptorModel *model)
420 : QQuickVisualAdaptorModelData(index, model)
421 , m_metaObject(new QQuickVDMObjectDataMetaObject(this, QQuickVisualAdaptorModelPrivate::get(m_model)->m_delegateDataType))
425 QQuickVDMObjectDataMetaObject *m_metaObject;
428 void QQuickVisualAdaptorModelPrivate::addProperty(
429 int role, int propertyId, const char *propertyName, const char *propertyType, bool isModelData)
431 PropertyData propertyData;
432 propertyData.role = role;
433 propertyData.isModelData = isModelData;
434 m_delegateDataType->builder.addSignal("__" + QByteArray::number(propertyId) + "()");
435 QMetaPropertyBuilder property = m_delegateDataType->builder.addProperty(
436 propertyName, propertyType, propertyId);
437 property.setWritable(false);
439 m_propertyData.append(propertyData);
442 QQuickVisualAdaptorModelData *QQuickVisualAdaptorModelPrivate::createMetaObject(int index, QQuickVisualAdaptorModel *model)
444 Q_ASSERT(!m_delegateDataType);
446 m_objectList = false;
447 m_propertyData.clear();
449 && m_listAccessor->type() != QDeclarativeListAccessor::ListProperty
450 && m_listAccessor->type() != QDeclarativeListAccessor::Instance) {
451 createModelData = &QQuickVDMListAccessorData::create;
452 m_flags = QQuickVisualAdaptorModel::MetaObjectCacheable;
453 return QQuickVDMListAccessorData::create(index, model);
456 m_delegateDataType = new VDMDelegateDataType;
457 if (m_listModelInterface) {
458 setModelDataType<QQuickVDMListModelInterfaceData>();
459 QList<int> roles = m_listModelInterface->roles();
460 for (int propertyId = 0; propertyId < roles.count(); ++propertyId) {
461 const int role = roles.at(propertyId);
462 const QByteArray propertyName = m_listModelInterface->toString(role).toUtf8();
463 addProperty(role, propertyId, propertyName, "QVariant");
464 m_roleNames.insert(propertyName, role);
466 if (m_propertyData.count() == 1)
467 addProperty(roles.first(), 1, "modelData", "QVariant", true);
468 m_flags = QQuickVisualAdaptorModel::MetaObjectCacheable;
469 } else if (m_abstractItemModel) {
470 setModelDataType<QQuickVDMAbstractItemModelData>();
471 QHash<int, QByteArray> roleNames = m_abstractItemModel->roleNames();
472 for (QHash<int, QByteArray>::const_iterator it = roleNames.begin(); it != roleNames.end(); ++it) {
473 addProperty(it.key(), m_propertyData.count(), it.value(), "QVariant");
474 m_roleNames.insert(it.value(), it.key());
476 if (m_propertyData.count() == 1)
477 addProperty(roleNames.begin().key(), 1, "modelData", "QVariant", true);
478 m_flags = QQuickVisualAdaptorModel::MetaObjectCacheable;
479 } else if (m_listAccessor) {
480 setModelDataType<QQuickVDMObjectData>();
482 m_flags = QQuickVisualAdaptorModel::ProxiedObject;
484 Q_ASSERT(!"No model set on VisualDataModel");
487 m_delegateDataType->metaObject = m_delegateDataType->builder.toMetaObject();
489 m_delegateDataType->propertyCache = new QDeclarativePropertyCache(
490 m_engine, m_delegateDataType->metaObject);
492 return createModelData(index, model);
495 QQuickVisualAdaptorModelData::QQuickVisualAdaptorModelData(int index, QQuickVisualAdaptorModel *model)
501 QQuickVisualAdaptorModelData::~QQuickVisualAdaptorModelData()
505 int QQuickVisualAdaptorModelData::index() const
510 // This is internal only - it should not be set from qml
511 void QQuickVisualAdaptorModelData::setIndex(int index)
517 //---------------------------------------------------------------------------
519 QQuickVisualAdaptorModel::QQuickVisualAdaptorModel(QObject *parent)
520 : QObject(*(new QQuickVisualAdaptorModelPrivate), parent)
524 QQuickVisualAdaptorModel::~QQuickVisualAdaptorModel()
526 Q_D(QQuickVisualAdaptorModel);
527 if (d->m_listAccessor)
528 delete d->m_listAccessor;
529 if (d->m_delegateDataType)
530 d->m_delegateDataType->release();
533 QQuickVisualAdaptorModel::Flags QQuickVisualAdaptorModel::flags() const
535 Q_D(const QQuickVisualAdaptorModel);
539 QVariant QQuickVisualAdaptorModel::model() const
541 Q_D(const QQuickVisualAdaptorModel);
542 return d->m_modelVariant;
545 void QQuickVisualAdaptorModel::setModel(const QVariant &model, QDeclarativeEngine *engine)
547 Q_D(QQuickVisualAdaptorModel);
548 delete d->m_listAccessor;
549 d->m_engine = engine;
550 d->m_listAccessor = 0;
551 d->m_modelVariant = model;
552 if (d->m_listModelInterface) {
553 // Assume caller has released all items.
554 QObject::disconnect(d->m_listModelInterface, SIGNAL(itemsChanged(int,int,QList<int>)),
555 this, SLOT(_q_itemsChanged(int,int,QList<int>)));
556 QObject::disconnect(d->m_listModelInterface, SIGNAL(itemsInserted(int,int)),
557 this, SLOT(_q_itemsInserted(int,int)));
558 QObject::disconnect(d->m_listModelInterface, SIGNAL(itemsRemoved(int,int)),
559 this, SLOT(_q_itemsRemoved(int,int)));
560 QObject::disconnect(d->m_listModelInterface, SIGNAL(itemsMoved(int,int,int)),
561 this, SLOT(_q_itemsMoved(int,int,int)));
562 d->m_listModelInterface = 0;
563 } else if (d->m_abstractItemModel) {
564 QObject::disconnect(d->m_abstractItemModel, SIGNAL(rowsInserted(QModelIndex,int,int)),
565 this, SLOT(_q_rowsInserted(QModelIndex,int,int)));
566 QObject::disconnect(d->m_abstractItemModel, SIGNAL(rowsRemoved(QModelIndex,int,int)),
567 this, SLOT(_q_rowsRemoved(QModelIndex,int,int)));
568 QObject::disconnect(d->m_abstractItemModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
569 this, SLOT(_q_dataChanged(QModelIndex,QModelIndex)));
570 QObject::disconnect(d->m_abstractItemModel, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)),
571 this, SLOT(_q_rowsMoved(QModelIndex,int,int,QModelIndex,int)));
572 QObject::disconnect(d->m_abstractItemModel, SIGNAL(modelReset()), this, SLOT(_q_modelReset()));
573 QObject::disconnect(d->m_abstractItemModel, SIGNAL(layoutChanged()), this, SLOT(_q_layoutChanged()));
574 d->m_abstractItemModel = 0;
578 d->m_roleNames.clear();
579 d->m_flags = QQuickVisualAdaptorModel::Flags();
580 if (d->m_delegateDataType)
581 d->m_delegateDataType->release();
582 d->m_delegateDataType = 0;
583 d->createModelData = &QQuickVisualAdaptorModelPrivate::initializeModelData;
586 emit itemsRemoved(0, d->m_count);
588 QObject *object = qvariant_cast<QObject *>(model);
589 if (object && (d->m_listModelInterface = qobject_cast<QListModelInterface *>(object))) {
590 QObject::connect(d->m_listModelInterface, SIGNAL(itemsChanged(int,int,QList<int>)),
591 this, SLOT(_q_itemsChanged(int,int,QList<int>)));
592 QObject::connect(d->m_listModelInterface, SIGNAL(itemsInserted(int,int)),
593 this, SLOT(_q_itemsInserted(int,int)));
594 QObject::connect(d->m_listModelInterface, SIGNAL(itemsRemoved(int,int)),
595 this, SLOT(_q_itemsRemoved(int,int)));
596 QObject::connect(d->m_listModelInterface, SIGNAL(itemsMoved(int,int,int)),
597 this, SLOT(_q_itemsMoved(int,int,int)));
598 if ((d->m_count = d->m_listModelInterface->count()))
599 emit itemsInserted(0, d->m_count);
601 } else if (object && (d->m_abstractItemModel = qobject_cast<QAbstractItemModel *>(object))) {
602 QObject::connect(d->m_abstractItemModel, SIGNAL(rowsInserted(QModelIndex,int,int)),
603 this, SLOT(_q_rowsInserted(QModelIndex,int,int)));
604 QObject::connect(d->m_abstractItemModel, SIGNAL(rowsRemoved(QModelIndex,int,int)),
605 this, SLOT(_q_rowsRemoved(QModelIndex,int,int)));
606 QObject::connect(d->m_abstractItemModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
607 this, SLOT(_q_dataChanged(QModelIndex,QModelIndex)));
608 QObject::connect(d->m_abstractItemModel, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)),
609 this, SLOT(_q_rowsMoved(QModelIndex,int,int,QModelIndex,int)));
610 QObject::connect(d->m_abstractItemModel, SIGNAL(modelReset()), this, SLOT(_q_modelReset()));
611 QObject::connect(d->m_abstractItemModel, SIGNAL(layoutChanged()), this, SLOT(_q_layoutChanged()));
613 if ((d->m_count = d->m_abstractItemModel->rowCount(d->m_root)))
614 emit itemsInserted(0, d->m_count);
618 d->m_listAccessor = new QDeclarativeListAccessor;
619 d->m_listAccessor->setList(model, d->m_engine);
620 if ((d->m_count = d->m_listAccessor->count()))
621 emit itemsInserted(0, d->m_count);
624 QVariant QQuickVisualAdaptorModel::rootIndex() const
626 Q_D(const QQuickVisualAdaptorModel);
627 return QVariant::fromValue(d->m_root);
630 void QQuickVisualAdaptorModel::setRootIndex(const QVariant &root)
632 Q_D(QQuickVisualAdaptorModel);
633 QModelIndex modelIndex = qvariant_cast<QModelIndex>(root);
634 if (d->m_root != modelIndex) {
635 int oldCount = d->modelCount();
636 d->m_root = modelIndex;
637 if (d->m_abstractItemModel && d->m_abstractItemModel->canFetchMore(modelIndex))
638 d->m_abstractItemModel->fetchMore(modelIndex);
639 int newCount = d->modelCount();
641 emit itemsRemoved(0, oldCount);
643 emit itemsInserted(0, newCount);
644 emit rootIndexChanged();
648 QVariant QQuickVisualAdaptorModel::modelIndex(int idx) const
650 Q_D(const QQuickVisualAdaptorModel);
651 if (d->m_abstractItemModel)
652 return QVariant::fromValue(d->m_abstractItemModel->index(idx, 0, d->m_root));
653 return QVariant::fromValue(QModelIndex());
656 QVariant QQuickVisualAdaptorModel::parentModelIndex() const
658 Q_D(const QQuickVisualAdaptorModel);
659 if (d->m_abstractItemModel)
660 return QVariant::fromValue(d->m_abstractItemModel->parent(d->m_root));
661 return QVariant::fromValue(QModelIndex());
664 int QQuickVisualAdaptorModel::count() const
666 Q_D(const QQuickVisualAdaptorModel);
667 return d->modelCount();
670 QObject *QQuickVisualAdaptorModel::data(int index)
672 Q_D(QQuickVisualAdaptorModel);
673 QQuickVisualAdaptorModelData *data = d->createModelData(index, this);
674 d->m_cache.insert(data);
678 QString QQuickVisualAdaptorModel::stringValue(int index, const QString &name)
680 Q_D(QQuickVisualAdaptorModel);
681 if ((!d->m_listModelInterface || !d->m_abstractItemModel) && d->m_listAccessor) {
682 if (QObject *object = d->m_listAccessor->at(index).value<QObject*>())
683 return object->property(name.toUtf8()).toString();
687 QQuickVisualAdaptorModelData *data = d->createModelData(index, this);
689 QDeclarativeData *ddata = QDeclarativeData::get(data);
690 if (ddata && ddata->propertyCache) {
691 QDeclarativePropertyData *prop = ddata->propertyCache->property(name);
693 if (prop->propType == QVariant::String) {
694 void *args[] = { &val, 0 };
695 QMetaObject::metacall(data, QMetaObject::ReadProperty, prop->coreIndex, args);
696 } else if (prop->propType == qMetaTypeId<QVariant>()) {
698 void *args[] = { &v, 0 };
699 QMetaObject::metacall(data, QMetaObject::ReadProperty, prop->coreIndex, args);
703 val = data->property(name.toUtf8()).toString();
706 val = data->property(name.toUtf8()).toString();
714 int QQuickVisualAdaptorModel::indexOf(QObject *object) const
716 if (QQuickVisualAdaptorModelData *data = qobject_cast<QQuickVisualAdaptorModelData *>(object))
717 return data->index();
721 bool QQuickVisualAdaptorModel::canFetchMore() const
723 Q_D(const QQuickVisualAdaptorModel);
724 return d->m_abstractItemModel && d->m_abstractItemModel->canFetchMore(d->m_root);
727 void QQuickVisualAdaptorModel::fetchMore()
729 Q_D(QQuickVisualAdaptorModel);
730 if (d->m_abstractItemModel)
731 d->m_abstractItemModel->fetchMore(d->m_root);
734 void QQuickVisualAdaptorModel::replaceWatchedRoles(const QList<QByteArray> &oldRoles, const QList<QByteArray> &newRoles)
736 Q_D(QQuickVisualAdaptorModel);
737 d->watchedRoleIds.clear();
738 foreach (const QByteArray &oldRole, oldRoles)
739 d->watchedRoles.removeOne(oldRole);
740 d->watchedRoles += newRoles;
743 void QQuickVisualAdaptorModel::_q_itemsChanged(int index, int count, const QList<int> &roles)
745 Q_D(QQuickVisualAdaptorModel);
746 bool changed = roles.isEmpty();
747 if (!d->watchedRoles.isEmpty() && d->watchedRoleIds.isEmpty()) {
748 foreach (QByteArray r, d->watchedRoles) {
749 if (d->m_roleNames.contains(r))
750 d->watchedRoleIds << d->m_roleNames.value(r);
754 QVector<int> signalIndexes;
755 for (int i = 0; i < roles.count(); ++i) {
756 const int role = roles.at(i);
757 if (!changed && d->watchedRoleIds.contains(role))
759 for (int propertyId = 0; propertyId < d->m_propertyData.count(); ++propertyId) {
760 if (d->m_propertyData.at(propertyId).role == role)
761 signalIndexes.append(propertyId + d->m_delegateDataType->signalOffset);
764 if (roles.isEmpty()) {
765 for (int propertyId = 0; propertyId < d->m_propertyData.count(); ++propertyId)
766 signalIndexes.append(propertyId + d->m_delegateDataType->signalOffset);
769 typedef QQuickVisualAdaptorModelDataCache::iterator iterator;
770 for (iterator it = d->m_cache.begin(); it != d->m_cache.end(); ++it) {
771 const int idx = it->index();
772 if (idx >= index && idx < index + count) {
773 QQuickVisualAdaptorModelData *data = *it;
774 for (int i = 0; i < signalIndexes.count(); ++i)
775 QMetaObject::activate(data, signalIndexes.at(i), 0);
779 emit itemsChanged(index, count);
782 void QQuickVisualAdaptorModel::_q_itemsInserted(int index, int count)
784 Q_D(QQuickVisualAdaptorModel);
789 typedef QQuickVisualAdaptorModelDataCache::iterator iterator;
790 for (iterator it = d->m_cache.begin(); it != d->m_cache.end(); ++it) {
791 if (it->index() >= index)
792 it->setIndex(it->index() + count);
795 emit itemsInserted(index, count);
798 void QQuickVisualAdaptorModel::_q_itemsRemoved(int index, int count)
800 Q_D(QQuickVisualAdaptorModel);
805 typedef QQuickVisualAdaptorModelDataCache::iterator iterator;
806 for (iterator it = d->m_cache.begin(); it != d->m_cache.end(); ++it) {
807 if (it->index() >= index + count)
808 it->setIndex(it->index() - count);
809 else if (it->index() >= index)
813 emit itemsRemoved(index, count);
816 void QQuickVisualAdaptorModel::_q_itemsMoved(int from, int to, int count)
818 Q_D(QQuickVisualAdaptorModel);
819 const int minimum = qMin(from, to);
820 const int maximum = qMax(from, to) + count;
821 const int difference = from > to ? count : -count;
823 typedef QQuickVisualAdaptorModelDataCache::iterator iterator;
824 for (iterator it = d->m_cache.begin(); it != d->m_cache.end(); ++it) {
825 if (it->index() >= from && it->index() < from + count)
826 it->setIndex(it->index() - from + to);
827 else if (it->index() >= minimum && it->index() < maximum)
828 it->setIndex(it->index() + difference);
830 emit itemsMoved(from, to, count);
833 void QQuickVisualAdaptorModel::_q_rowsInserted(const QModelIndex &parent, int begin, int end)
835 Q_D(QQuickVisualAdaptorModel);
836 if (parent == d->m_root)
837 _q_itemsInserted(begin, end - begin + 1);
840 void QQuickVisualAdaptorModel::_q_rowsRemoved(const QModelIndex &parent, int begin, int end)
842 Q_D(QQuickVisualAdaptorModel);
843 if (parent == d->m_root)
844 _q_itemsRemoved(begin, end - begin + 1);
847 void QQuickVisualAdaptorModel::_q_rowsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationRow)
849 Q_D(QQuickVisualAdaptorModel);
850 const int count = sourceEnd - sourceStart + 1;
851 if (destinationParent == d->m_root && sourceParent == d->m_root) {
852 _q_itemsMoved(sourceStart, sourceStart > destinationRow ? destinationRow : destinationRow-count, count);
853 } else if (sourceParent == d->m_root) {
854 _q_itemsRemoved(sourceStart, count);
855 } else if (destinationParent == d->m_root) {
856 _q_itemsInserted(destinationRow, count);
860 void QQuickVisualAdaptorModel::_q_dataChanged(const QModelIndex &begin, const QModelIndex &end)
862 Q_D(QQuickVisualAdaptorModel);
863 if (begin.parent() == d->m_root)
864 _q_itemsChanged(begin.row(), end.row() - begin.row() + 1, d->m_roles);
867 void QQuickVisualAdaptorModel::_q_layoutChanged()
869 Q_D(QQuickVisualAdaptorModel);
870 _q_itemsChanged(0, count(), d->m_roles);
873 void QQuickVisualAdaptorModel::_q_modelReset()
875 Q_D(QQuickVisualAdaptorModel);
876 int oldCount = d->m_count;
877 d->m_root = QModelIndex();
878 d->m_count = d->modelCount();
879 emit modelReset(oldCount, d->m_count);
880 emit rootIndexChanged();
881 if (d->m_abstractItemModel && d->m_abstractItemModel->canFetchMore(d->m_root))
882 d->m_abstractItemModel->fetchMore(d->m_root);
887 QML_DECLARE_TYPE(QListModelInterface)
889 #include <qquickvisualadaptormodel.moc>