Fix QQuickVisualDataModel test failure.
[profile/ivi/qtdeclarative.git] / src / quick / items / qquickvisualadaptormodel.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** 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.
17 **
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.
21 **
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.
29 **
30 ** Other Usage
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.
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qquickvisualadaptormodel_p.h"
43 #include "qquickitem.h"
44
45 #include <QtDeclarative/qdeclarativecontext.h>
46 #include <QtDeclarative/qdeclarativeengine.h>
47 #include <QtDeclarative/qdeclarativeexpression.h>
48 #include <QtDeclarative/qdeclarativeinfo.h>
49
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>
63
64 #include <QtCore/qhash.h>
65 #include <QtCore/qlist.h>
66
67 Q_DECLARE_METATYPE(QModelIndex)
68
69 QT_BEGIN_NAMESPACE
70
71 class VDMDelegateDataType : public QDeclarativeRefCount
72 {
73 public:
74     VDMDelegateDataType()
75         : metaObject(0)
76         , propertyCache(0)
77         , propertyOffset(0)
78         , signalOffset(0)
79         , shared(true)
80     {
81     }
82
83     VDMDelegateDataType(const VDMDelegateDataType &type)
84         : metaObject(0)
85         , propertyCache(0)
86         , propertyOffset(type.propertyOffset)
87         , signalOffset(type.signalOffset)
88         , shared(false)
89         , builder(type.metaObject, QMetaObjectBuilder::Properties
90                 | QMetaObjectBuilder::Signals
91                 | QMetaObjectBuilder::SuperClass
92                 | QMetaObjectBuilder::ClassName)
93     {
94         builder.setFlags(QMetaObjectBuilder::DynamicMetaObject);
95     }
96
97     ~VDMDelegateDataType()
98     {
99         if (propertyCache)
100             propertyCache->release();
101         qFree(metaObject);
102     }
103
104     QMetaObject *metaObject;
105     QDeclarativePropertyCache *propertyCache;
106     int propertyOffset;
107     int signalOffset;
108     bool shared : 1;
109     QMetaObjectBuilder builder;
110 };
111
112 class QQuickVisualAdaptorModelData : public QObject
113 {
114     Q_OBJECT
115     Q_PROPERTY(int index READ index NOTIFY indexChanged)
116 public:
117     QQuickVisualAdaptorModelData(int index, QQuickVisualAdaptorModel *model);
118     ~QQuickVisualAdaptorModelData();
119
120     int index() const;
121     void setIndex(int index);
122
123 Q_SIGNALS:
124     void indexChanged();
125
126 public:
127     int m_index;
128     QDeclarativeGuard<QQuickVisualAdaptorModel> m_model;
129     QIntrusiveListNode m_cacheNode;
130 };
131
132 typedef QIntrusiveList<QQuickVisualAdaptorModelData, &QQuickVisualAdaptorModelData::m_cacheNode> QQuickVisualAdaptorModelDataCache;
133
134 class QQuickVisualAdaptorModelDataMetaObject;
135 class QQuickVisualAdaptorModelPrivate : public QObjectPrivate
136 {
137     Q_DECLARE_PUBLIC(QQuickVisualAdaptorModel)
138 public:
139     QQuickVisualAdaptorModelPrivate()
140         : m_engine(0)
141         , m_listAccessor(0)
142         , m_delegateDataType(0)
143         , createModelData(&initializeModelData)
144         , m_ref(0)
145         , m_count(0)
146         , m_objectList(false)
147     {
148     }
149
150
151     static QQuickVisualAdaptorModelPrivate *get(QQuickVisualAdaptorModel *m) {
152         return static_cast<QQuickVisualAdaptorModelPrivate *>(QObjectPrivate::get(m));
153     }
154
155     void addProperty(int role, int propertyId, const char *propertyName, const char *propertyType, bool isModelData = false);
156     template <typename T> void setModelDataType()
157     {
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();
164     }
165     QQuickVisualAdaptorModelData *createMetaObject(int index, QQuickVisualAdaptorModel *model);
166
167     static QQuickVisualAdaptorModelData *initializeModelData(int index, QQuickVisualAdaptorModel *model) {
168         return get(model)->createMetaObject(index, model);
169     }
170
171     typedef QQuickVisualAdaptorModelData *(*CreateModelData)(int index, QQuickVisualAdaptorModel *model);
172
173     struct PropertyData {
174         int role;
175         bool isModelData : 1;
176     };
177
178     int modelCount() const {
179         if (m_listModelInterface)
180             return m_listModelInterface->count();
181         if (m_abstractItemModel)
182             return m_abstractItemModel->rowCount(m_root);
183         if (m_listAccessor)
184             return m_listAccessor->count();
185         return 0;
186     }
187
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;
194
195     int m_ref;
196     int m_count;
197     QQuickVisualAdaptorModel::Flags m_flags;
198     bool m_objectList : 1;
199
200     QVariant m_modelVariant;
201     QModelIndex m_root;
202
203     QList<int> m_roles;
204     QList<int> watchedRoleIds;
205     QList<QByteArray> watchedRoles;
206     QHash<QByteArray,int> m_roleNames;
207     QVector<PropertyData> m_propertyData;
208     QQuickVisualAdaptorModelDataCache m_cache;
209 };
210
211 class QQuickVisualAdaptorModelDataMetaObject : public QAbstractDynamicMetaObject
212 {
213 public:
214     QQuickVisualAdaptorModelDataMetaObject(QQuickVisualAdaptorModelData *data, VDMDelegateDataType *type)
215         : m_data(data)
216         , m_type(type)
217     {
218         QObjectPrivate *op = QObjectPrivate::get(m_data);
219         *static_cast<QMetaObject *>(this) = *type->metaObject;
220         op->metaObject = this;
221         m_type->addref();
222     }
223
224     ~QQuickVisualAdaptorModelDataMetaObject() { m_type->release(); }
225
226     QQuickVisualAdaptorModelData *m_data;
227     VDMDelegateDataType *m_type;
228 };
229
230 class QQuickVDMAbstractItemModelDataMetaObject : public QQuickVisualAdaptorModelDataMetaObject
231 {
232 public:
233     QQuickVDMAbstractItemModelDataMetaObject(QQuickVisualAdaptorModelData *object, VDMDelegateDataType *type)
234         : QQuickVisualAdaptorModelDataMetaObject(object, type) {}
235
236     int metaCall(QMetaObject::Call call, int id, void **arguments)
237     {
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)
241                 return -1;
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);
244             return -1;
245         } else {
246             return m_data->qt_metacall(call, id, arguments);
247         }
248     }
249 };
250
251 class QQuickVDMAbstractItemModelData : public QQuickVisualAdaptorModelData
252 {
253     Q_OBJECT
254     Q_PROPERTY(bool hasModelChildren READ hasModelChildren CONSTANT)
255 public:
256     bool hasModelChildren() const
257     {
258         QQuickVisualAdaptorModelPrivate *model = QQuickVisualAdaptorModelPrivate::get(m_model);
259         return model->m_abstractItemModel->hasChildren(model->m_abstractItemModel->index(m_index, 0, model->m_root));
260     }
261
262     static QQuickVisualAdaptorModelData *create(int index, QQuickVisualAdaptorModel *model) {
263         return new QQuickVDMAbstractItemModelData(index, model); }
264 private:
265     QQuickVDMAbstractItemModelData(int index, QQuickVisualAdaptorModel *model)
266         : QQuickVisualAdaptorModelData(index, model)
267     {
268         new QQuickVDMAbstractItemModelDataMetaObject(
269                 this, QQuickVisualAdaptorModelPrivate::get(m_model)->m_delegateDataType);
270     }
271 };
272
273 class QQuickVDMListModelInterfaceDataMetaObject : public QQuickVisualAdaptorModelDataMetaObject
274 {
275 public:
276     QQuickVDMListModelInterfaceDataMetaObject(QQuickVisualAdaptorModelData *object, VDMDelegateDataType *type)
277         : QQuickVisualAdaptorModelDataMetaObject(object, type) {}
278
279     int metaCall(QMetaObject::Call call, int id, void **arguments)
280     {
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)
284                 return -1;
285             *static_cast<QVariant *>(arguments[0]) = model->m_listModelInterface->data(
286                     m_data->m_index, model->m_propertyData.at(id - m_type->propertyOffset).role);
287             return -1;
288         } else {
289             return m_data->qt_metacall(call, id, arguments);
290         }
291     }
292 };
293
294 class QQuickVDMListModelInterfaceData : public QQuickVisualAdaptorModelData
295 {
296 public:
297     static QQuickVisualAdaptorModelData *create(int index, QQuickVisualAdaptorModel *model) {
298         return new QQuickVDMListModelInterfaceData(index, model); }
299 private:
300     QQuickVDMListModelInterfaceData(int index, QQuickVisualAdaptorModel *model)
301         : QQuickVisualAdaptorModelData(index, model)
302     {
303         new QQuickVDMListModelInterfaceDataMetaObject(
304                 this, QQuickVisualAdaptorModelPrivate::get(m_model)->m_delegateDataType);
305     }
306 };
307
308 class QQuickVDMListAccessorData : public QQuickVisualAdaptorModelData
309 {
310     Q_OBJECT
311     Q_PROPERTY(QVariant modelData READ modelData CONSTANT)
312 public:
313     QVariant modelData() const {
314         return QQuickVisualAdaptorModelPrivate::get(m_model)->m_listAccessor->at(m_index); }
315
316     static QQuickVisualAdaptorModelData *create(int index, QQuickVisualAdaptorModel *model) {
317         return new QQuickVDMListAccessorData(index, model); }
318 private:
319     QQuickVDMListAccessorData(int index, QQuickVisualAdaptorModel *model)
320         : QQuickVisualAdaptorModelData(index, model)
321     {
322     }
323 };
324
325 class QQuickVDMObjectDataMetaObject : public QQuickVisualAdaptorModelDataMetaObject
326 {
327 public:
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 *>())
331     {}
332
333     int metaCall(QMetaObject::Call call, int id, void **arguments)
334     {
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)) {
340             if (m_object)
341                 QMetaObject::metacall(m_object, call, id - m_type->propertyOffset + objectPropertyOffset, arguments);
342             return -1;
343         } else if (id >= m_type->signalOffset && call == QMetaObject::InvokeMetaMethod) {
344             QMetaObject::activate(m_data, this, id, 0);
345             return -1;
346         } else {
347             return m_data->qt_metacall(call, id, arguments);
348         }
349     }
350
351     int createProperty(const char *name, const char *)
352     {
353         if (!m_object)
354             return -1;
355         const QMetaObject *metaObject = m_object->metaObject();
356         static const int objectPropertyOffset = QObject::staticMetaObject.propertyCount();
357
358         const int previousPropertyCount = propertyCount() - propertyOffset();
359         int propertyIndex = metaObject->indexOfProperty(name);
360         if (propertyIndex == -1)
361             return -1;
362         if (previousPropertyCount + objectPropertyOffset == metaObject->propertyCount())
363             return propertyIndex + m_type->propertyOffset - objectPropertyOffset;
364
365         if (m_type->shared) {
366             VDMDelegateDataType *type = m_type;
367             m_type = new VDMDelegateDataType(*m_type);
368             type->release();
369         }
370
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);
379                 ++notifierId;
380             } else {
381                 propertyBuilder = m_type->builder.addProperty(property.name(), property.typeName());
382             }
383             propertyBuilder.setWritable(property.isWritable());
384             propertyBuilder.setResettable(property.isResettable());
385             propertyBuilder.setConstant(property.isConstant());
386         }
387
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;
392
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);
399                 ++notifierId;
400             }
401         }
402         return propertyIndex + m_type->propertyOffset - objectPropertyOffset;
403     }
404
405     QDeclarativeGuard<QObject> m_object;
406 };
407
408 class QQuickVDMObjectData : public QQuickVisualAdaptorModelData, public QQuickVisualAdaptorModelProxyInterface
409 {
410     Q_OBJECT
411     Q_PROPERTY(QObject *modelData READ modelData CONSTANT)
412     Q_INTERFACES(QQuickVisualAdaptorModelProxyInterface)
413 public:
414     QObject *modelData() const { return m_metaObject->m_object; }
415     QObject *proxiedObject() { return m_metaObject->m_object; }
416
417     static QQuickVisualAdaptorModelData *create(int index, QQuickVisualAdaptorModel *model) {
418         return new QQuickVDMObjectData(index, model); }
419
420 private:
421     QQuickVDMObjectData(int index, QQuickVisualAdaptorModel *model)
422         : QQuickVisualAdaptorModelData(index, model)
423         , m_metaObject(new QQuickVDMObjectDataMetaObject(this, QQuickVisualAdaptorModelPrivate::get(m_model)->m_delegateDataType))
424     {
425     }
426
427     QQuickVDMObjectDataMetaObject *m_metaObject;
428 };
429
430 void QQuickVisualAdaptorModelPrivate::addProperty(
431         int role, int propertyId, const char *propertyName, const char *propertyType, bool isModelData)
432 {
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);
440
441     m_propertyData.append(propertyData);
442 }
443
444 QQuickVisualAdaptorModelData *QQuickVisualAdaptorModelPrivate::createMetaObject(int index, QQuickVisualAdaptorModel *model)
445 {
446     Q_ASSERT(!m_delegateDataType);
447
448     m_objectList = false;
449     m_propertyData.clear();
450     if (m_listAccessor
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);
456     }
457
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);
467         }
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());
477         }
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>();
483         m_objectList = true;
484         m_flags = QQuickVisualAdaptorModel::ProxiedObject;
485     } else {
486         Q_ASSERT(!"No model set on VisualDataModel");
487         return 0;
488     }
489     m_delegateDataType->metaObject = m_delegateDataType->builder.toMetaObject();
490     if (!m_objectList) {
491         m_delegateDataType->propertyCache = new QDeclarativePropertyCache(
492                 m_engine, m_delegateDataType->metaObject);
493     }
494     return createModelData(index, model);
495 }
496
497 QQuickVisualAdaptorModelData::QQuickVisualAdaptorModelData(int index, QQuickVisualAdaptorModel *model)
498     : m_index(index)
499     , m_model(model)
500 {
501 }
502
503 QQuickVisualAdaptorModelData::~QQuickVisualAdaptorModelData()
504 {
505 }
506
507 int QQuickVisualAdaptorModelData::index() const
508 {
509     return m_index;
510 }
511
512 // This is internal only - it should not be set from qml
513 void QQuickVisualAdaptorModelData::setIndex(int index)
514 {
515     m_index = index;
516     emit indexChanged();
517 }
518
519 //---------------------------------------------------------------------------
520
521 QQuickVisualAdaptorModel::QQuickVisualAdaptorModel(QObject *parent)
522     : QObject(*(new QQuickVisualAdaptorModelPrivate), parent)
523 {
524 }
525
526 QQuickVisualAdaptorModel::~QQuickVisualAdaptorModel()
527 {
528     Q_D(QQuickVisualAdaptorModel);
529     if (d->m_listAccessor)
530         delete d->m_listAccessor;
531     if (d->m_delegateDataType)
532         d->m_delegateDataType->release();
533 }
534
535 QQuickVisualAdaptorModel::Flags QQuickVisualAdaptorModel::flags() const
536 {
537     Q_D(const QQuickVisualAdaptorModel);
538     return d->m_flags;
539 }
540
541 QVariant QQuickVisualAdaptorModel::model() const
542 {
543     Q_D(const QQuickVisualAdaptorModel);
544     return d->m_modelVariant;
545 }
546
547 void QQuickVisualAdaptorModel::setModel(const QVariant &model, QDeclarativeEngine *engine)
548 {
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;
577     }
578
579     d->m_roles.clear();
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;
586
587     if (d->m_count)
588         emit itemsRemoved(0, d->m_count);
589
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);
602         return;
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()));
614
615         if ((d->m_count = d->m_abstractItemModel->rowCount(d->m_root)))
616             emit itemsInserted(0, d->m_count);
617         return;
618     }
619
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);
624 }
625
626 QVariant QQuickVisualAdaptorModel::rootIndex() const
627 {
628     Q_D(const QQuickVisualAdaptorModel);
629     return QVariant::fromValue(d->m_root);
630 }
631
632 void QQuickVisualAdaptorModel::setRootIndex(const QVariant &root)
633 {
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();
642         if (oldCount)
643             emit itemsRemoved(0, oldCount);
644         if (newCount)
645             emit itemsInserted(0, newCount);
646         emit rootIndexChanged();
647     }
648 }
649
650 QVariant QQuickVisualAdaptorModel::modelIndex(int idx) const
651 {
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());
656 }
657
658 QVariant QQuickVisualAdaptorModel::parentModelIndex() const
659 {
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());
664 }
665
666 int QQuickVisualAdaptorModel::count() const
667 {
668     Q_D(const QQuickVisualAdaptorModel);
669     return d->modelCount();
670 }
671
672 QObject *QQuickVisualAdaptorModel::data(int index)
673 {
674     Q_D(QQuickVisualAdaptorModel);
675     QQuickVisualAdaptorModelData *data = d->createModelData(index, this);
676     d->m_cache.insert(data);
677     return data;
678 }
679
680 QString QQuickVisualAdaptorModel::stringValue(int index, const QString &name)
681 {
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();
686     }
687
688     QString val;
689     QQuickVisualAdaptorModelData *data = d->createModelData(index, this);
690
691     QDeclarativeData *ddata = QDeclarativeData::get(data);
692     if (ddata && ddata->propertyCache) {
693         QDeclarativePropertyData *prop = ddata->propertyCache->property(name);
694         if (prop) {
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>()) {
699                 QVariant v;
700                 void *args[] = { &v, 0 };
701                 QMetaObject::metacall(data, QMetaObject::ReadProperty, prop->coreIndex, args);
702                 val = v.toString();
703             }
704         } else {
705             val = data->property(name.toUtf8()).toString();
706         }
707     } else {
708         val = data->property(name.toUtf8()).toString();
709     }
710
711     delete data;
712
713     return val;
714 }
715
716 int QQuickVisualAdaptorModel::indexOf(QObject *object) const
717 {
718     if (QQuickVisualAdaptorModelData *data = qobject_cast<QQuickVisualAdaptorModelData *>(object))
719         return data->index();
720     return -1;
721 }
722
723 bool QQuickVisualAdaptorModel::canFetchMore() const
724 {
725     Q_D(const QQuickVisualAdaptorModel);
726     return d->m_abstractItemModel && d->m_abstractItemModel->canFetchMore(d->m_root);
727 }
728
729 void QQuickVisualAdaptorModel::fetchMore()
730 {
731     Q_D(QQuickVisualAdaptorModel);
732     if (d->m_abstractItemModel)
733         d->m_abstractItemModel->fetchMore(d->m_root);
734 }
735
736 void QQuickVisualAdaptorModel::replaceWatchedRoles(const QList<QByteArray> &oldRoles, const QList<QByteArray> &newRoles)
737 {
738     Q_D(QQuickVisualAdaptorModel);
739     d->watchedRoleIds.clear();
740     foreach (const QByteArray &oldRole, oldRoles)
741         d->watchedRoles.removeOne(oldRole);
742     d->watchedRoles += newRoles;
743 }
744
745 void QQuickVisualAdaptorModel::_q_itemsChanged(int index, int count, const QList<int> &roles)
746 {
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);
753         }
754     }
755
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))
760             changed = true;
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);
764         }
765     }
766     if (roles.isEmpty()) {
767         for (int propertyId = 0; propertyId < d->m_propertyData.count(); ++propertyId)
768             signalIndexes.append(propertyId + d->m_delegateDataType->signalOffset);
769     }
770
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);
778         }
779     }
780     if (changed)
781         emit itemsChanged(index, count);
782 }
783
784 void QQuickVisualAdaptorModel::_q_itemsInserted(int index, int count)
785 {
786     Q_D(QQuickVisualAdaptorModel);
787     if (count <= 0)
788         return;
789     d->m_count += count;
790
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);
795     }
796
797     emit itemsInserted(index, count);
798 }
799
800 void QQuickVisualAdaptorModel::_q_itemsRemoved(int index, int count)
801 {
802     Q_D(QQuickVisualAdaptorModel);
803     if (count <= 0)
804         return;
805     d->m_count -= count;
806
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)
812             it->setIndex(-1);
813     }
814
815     emit itemsRemoved(index, count);
816 }
817
818 void QQuickVisualAdaptorModel::_q_itemsMoved(int from, int to, int count)
819 {
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;
824
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);
831     }
832     emit itemsMoved(from, to, count);
833 }
834
835 void QQuickVisualAdaptorModel::_q_rowsInserted(const QModelIndex &parent, int begin, int end)
836 {
837     Q_D(QQuickVisualAdaptorModel);
838     if (parent == d->m_root)
839         _q_itemsInserted(begin, end - begin + 1);
840 }
841
842 void QQuickVisualAdaptorModel::_q_rowsRemoved(const QModelIndex &parent, int begin, int end)
843 {
844     Q_D(QQuickVisualAdaptorModel);
845     if (parent == d->m_root)
846         _q_itemsRemoved(begin, end - begin + 1);
847 }
848
849 void QQuickVisualAdaptorModel::_q_rowsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationRow)
850 {
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);
859     }
860 }
861
862 void QQuickVisualAdaptorModel::_q_dataChanged(const QModelIndex &begin, const QModelIndex &end)
863 {
864     Q_D(QQuickVisualAdaptorModel);
865     if (begin.parent() == d->m_root)
866         _q_itemsChanged(begin.row(), end.row() - begin.row() + 1, d->m_roles);
867 }
868
869 void QQuickVisualAdaptorModel::_q_layoutChanged()
870 {
871     Q_D(QQuickVisualAdaptorModel);
872     _q_itemsChanged(0, count(), d->m_roles);
873 }
874
875 void QQuickVisualAdaptorModel::_q_modelReset()
876 {
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);
885 }
886
887 QT_END_NAMESPACE
888
889 QML_DECLARE_TYPE(QListModelInterface)
890
891 #include <qquickvisualadaptormodel.moc>