Fix test fails related to QTBUG-22237
[profile/ivi/qtdeclarative.git] / src / declarative / 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         if (id >= m_type->propertyOffset
336                 && (call == QMetaObject::ReadProperty
337                 || call == QMetaObject::WriteProperty
338                 || call == QMetaObject::ResetProperty)) {
339             if (m_object)
340                 QMetaObject::metacall(m_object, call, id - m_type->propertyOffset + 1, arguments);
341             return -1;
342         } else if (id >= m_type->signalOffset && call == QMetaObject::InvokeMetaMethod) {
343             QMetaObject::activate(m_data, this, id, 0);
344             return -1;
345         } else {
346             return m_data->qt_metacall(call, id, arguments);
347         }
348     }
349
350     int createProperty(const char *name, const char *)
351     {
352         if (!m_object)
353             return -1;
354         const QMetaObject *metaObject = m_object->metaObject();
355
356         const int previousPropertyCount = propertyCount() - propertyOffset();
357         int propertyIndex = metaObject->indexOfProperty(name);
358         if (propertyIndex == -1)
359             return -1;
360         if (previousPropertyCount + 1 == metaObject->propertyCount())
361             return propertyIndex + m_type->propertyOffset - 1;
362
363         if (m_type->shared) {
364             VDMDelegateDataType *type = m_type;
365             m_type = new VDMDelegateDataType(*m_type);
366             type->release();
367         }
368
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);
377                 ++notifierId;
378             } else {
379                 propertyBuilder = m_type->builder.addProperty(property.name(), property.typeName());
380             }
381             propertyBuilder.setWritable(property.isWritable());
382             propertyBuilder.setResettable(property.isResettable());
383             propertyBuilder.setConstant(property.isConstant());
384         }
385
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;
390
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);
397                 ++notifierId;
398             }
399         }
400         return propertyIndex + m_type->propertyOffset - 1;
401     }
402
403     QDeclarativeGuard<QObject> m_object;
404 };
405
406 class QQuickVDMObjectData : public QQuickVisualAdaptorModelData, public QQuickVisualAdaptorModelProxyInterface
407 {
408     Q_OBJECT
409     Q_PROPERTY(QObject *modelData READ modelData CONSTANT)
410     Q_INTERFACES(QQuickVisualAdaptorModelProxyInterface)
411 public:
412     QObject *modelData() const { return m_metaObject->m_object; }
413     QObject *proxiedObject() { return m_metaObject->m_object; }
414
415     static QQuickVisualAdaptorModelData *create(int index, QQuickVisualAdaptorModel *model) {
416         return new QQuickVDMObjectData(index, model); }
417
418 private:
419     QQuickVDMObjectData(int index, QQuickVisualAdaptorModel *model)
420         : QQuickVisualAdaptorModelData(index, model)
421         , m_metaObject(new QQuickVDMObjectDataMetaObject(this, QQuickVisualAdaptorModelPrivate::get(m_model)->m_delegateDataType))
422     {
423     }
424
425     QQuickVDMObjectDataMetaObject *m_metaObject;
426 };
427
428 void QQuickVisualAdaptorModelPrivate::addProperty(
429         int role, int propertyId, const char *propertyName, const char *propertyType, bool isModelData)
430 {
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);
438
439     m_propertyData.append(propertyData);
440 }
441
442 QQuickVisualAdaptorModelData *QQuickVisualAdaptorModelPrivate::createMetaObject(int index, QQuickVisualAdaptorModel *model)
443 {
444     Q_ASSERT(!m_delegateDataType);
445
446     m_objectList = false;
447     m_propertyData.clear();
448     if (m_listAccessor
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);
454     }
455
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);
465         }
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());
475         }
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>();
481         m_objectList = true;
482         m_flags = QQuickVisualAdaptorModel::ProxiedObject;
483     } else {
484         Q_ASSERT(!"No model set on VisualDataModel");
485         return 0;
486     }
487     m_delegateDataType->metaObject = m_delegateDataType->builder.toMetaObject();
488     if (!m_objectList) {
489         m_delegateDataType->propertyCache = new QDeclarativePropertyCache(
490                 m_engine, m_delegateDataType->metaObject);
491     }
492     return createModelData(index, model);
493 }
494
495 QQuickVisualAdaptorModelData::QQuickVisualAdaptorModelData(int index, QQuickVisualAdaptorModel *model)
496     : m_index(index)
497     , m_model(model)
498 {
499 }
500
501 QQuickVisualAdaptorModelData::~QQuickVisualAdaptorModelData()
502 {
503 }
504
505 int QQuickVisualAdaptorModelData::index() const
506 {
507     return m_index;
508 }
509
510 // This is internal only - it should not be set from qml
511 void QQuickVisualAdaptorModelData::setIndex(int index)
512 {
513     m_index = index;
514     emit indexChanged();
515 }
516
517 //---------------------------------------------------------------------------
518
519 QQuickVisualAdaptorModel::QQuickVisualAdaptorModel(QObject *parent)
520     : QObject(*(new QQuickVisualAdaptorModelPrivate), parent)
521 {
522 }
523
524 QQuickVisualAdaptorModel::~QQuickVisualAdaptorModel()
525 {
526     Q_D(QQuickVisualAdaptorModel);
527     if (d->m_listAccessor)
528         delete d->m_listAccessor;
529     if (d->m_delegateDataType)
530         d->m_delegateDataType->release();
531 }
532
533 QQuickVisualAdaptorModel::Flags QQuickVisualAdaptorModel::flags() const
534 {
535     Q_D(const QQuickVisualAdaptorModel);
536     return d->m_flags;
537 }
538
539 QVariant QQuickVisualAdaptorModel::model() const
540 {
541     Q_D(const QQuickVisualAdaptorModel);
542     return d->m_modelVariant;
543 }
544
545 void QQuickVisualAdaptorModel::setModel(const QVariant &model, QDeclarativeEngine *engine)
546 {
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;
575     }
576
577     d->m_roles.clear();
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;
584
585     if (d->m_count)
586         emit itemsRemoved(0, d->m_count);
587
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);
600         return;
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()));
612
613         if ((d->m_count = d->m_abstractItemModel->rowCount(d->m_root)))
614             emit itemsInserted(0, d->m_count);
615         return;
616     }
617
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);
622 }
623
624 QVariant QQuickVisualAdaptorModel::rootIndex() const
625 {
626     Q_D(const QQuickVisualAdaptorModel);
627     return QVariant::fromValue(d->m_root);
628 }
629
630 void QQuickVisualAdaptorModel::setRootIndex(const QVariant &root)
631 {
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();
640         if (oldCount)
641             emit itemsRemoved(0, oldCount);
642         if (newCount)
643             emit itemsInserted(0, newCount);
644         emit rootIndexChanged();
645     }
646 }
647
648 QVariant QQuickVisualAdaptorModel::modelIndex(int idx) const
649 {
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());
654 }
655
656 QVariant QQuickVisualAdaptorModel::parentModelIndex() const
657 {
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());
662 }
663
664 int QQuickVisualAdaptorModel::count() const
665 {
666     Q_D(const QQuickVisualAdaptorModel);
667     return d->modelCount();
668 }
669
670 QObject *QQuickVisualAdaptorModel::data(int index)
671 {
672     Q_D(QQuickVisualAdaptorModel);
673     QQuickVisualAdaptorModelData *data = d->createModelData(index, this);
674     d->m_cache.insert(data);
675     return data;
676 }
677
678 QString QQuickVisualAdaptorModel::stringValue(int index, const QString &name)
679 {
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();
684     }
685
686     QString val;
687     QQuickVisualAdaptorModelData *data = d->createModelData(index, this);
688
689     QDeclarativeData *ddata = QDeclarativeData::get(data);
690     if (ddata && ddata->propertyCache) {
691         QDeclarativePropertyCache::Data *prop = ddata->propertyCache->property(name);
692         if (prop) {
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>()) {
697                 QVariant v;
698                 void *args[] = { &v, 0 };
699                 QMetaObject::metacall(data, QMetaObject::ReadProperty, prop->coreIndex, args);
700                 val = v.toString();
701             }
702         } else {
703             val = data->property(name.toUtf8()).toString();
704         }
705     } else {
706         val = data->property(name.toUtf8()).toString();
707     }
708
709     delete data;
710
711     return val;
712 }
713
714 int QQuickVisualAdaptorModel::indexOf(QObject *object) const
715 {
716     if (QQuickVisualAdaptorModelData *data = qobject_cast<QQuickVisualAdaptorModelData *>(object))
717         return data->index();
718     return -1;
719 }
720
721 bool QQuickVisualAdaptorModel::canFetchMore() const
722 {
723     Q_D(const QQuickVisualAdaptorModel);
724     return d->m_abstractItemModel && d->m_abstractItemModel->canFetchMore(d->m_root);
725 }
726
727 void QQuickVisualAdaptorModel::fetchMore()
728 {
729     Q_D(QQuickVisualAdaptorModel);
730     if (d->m_abstractItemModel)
731         d->m_abstractItemModel->fetchMore(d->m_root);
732 }
733
734 void QQuickVisualAdaptorModel::replaceWatchedRoles(const QList<QByteArray> &oldRoles, const QList<QByteArray> &newRoles)
735 {
736     Q_D(QQuickVisualAdaptorModel);
737     d->watchedRoleIds.clear();
738     foreach (const QByteArray &oldRole, oldRoles)
739         d->watchedRoles.removeOne(oldRole);
740     d->watchedRoles += newRoles;
741 }
742
743 void QQuickVisualAdaptorModel::_q_itemsChanged(int index, int count, const QList<int> &roles)
744 {
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);
751         }
752     }
753
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))
758             changed = true;
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);
762         }
763     }
764     if (roles.isEmpty()) {
765         for (int propertyId = 0; propertyId < d->m_propertyData.count(); ++propertyId)
766             signalIndexes.append(propertyId + d->m_delegateDataType->signalOffset);
767     }
768
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);
776         }
777     }
778     if (changed)
779         emit itemsChanged(index, count);
780 }
781
782 void QQuickVisualAdaptorModel::_q_itemsInserted(int index, int count)
783 {
784     Q_D(QQuickVisualAdaptorModel);
785     if (count <= 0)
786         return;
787     d->m_count += count;
788
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);
793     }
794
795     emit itemsInserted(index, count);
796 }
797
798 void QQuickVisualAdaptorModel::_q_itemsRemoved(int index, int count)
799 {
800     Q_D(QQuickVisualAdaptorModel);
801     if (count <= 0)
802         return;
803     d->m_count -= count;
804
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)
810             it->setIndex(-1);
811     }
812
813     emit itemsRemoved(index, count);
814 }
815
816 void QQuickVisualAdaptorModel::_q_itemsMoved(int from, int to, int count)
817 {
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;
822
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);
829     }
830     emit itemsMoved(from, to, count);
831 }
832
833 void QQuickVisualAdaptorModel::_q_rowsInserted(const QModelIndex &parent, int begin, int end)
834 {
835     Q_D(QQuickVisualAdaptorModel);
836     if (parent == d->m_root)
837         _q_itemsInserted(begin, end - begin + 1);
838 }
839
840 void QQuickVisualAdaptorModel::_q_rowsRemoved(const QModelIndex &parent, int begin, int end)
841 {
842     Q_D(QQuickVisualAdaptorModel);
843     if (parent == d->m_root)
844         _q_itemsRemoved(begin, end - begin + 1);
845 }
846
847 void QQuickVisualAdaptorModel::_q_rowsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationRow)
848 {
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);
857     }
858 }
859
860 void QQuickVisualAdaptorModel::_q_dataChanged(const QModelIndex &begin, const QModelIndex &end)
861 {
862     Q_D(QQuickVisualAdaptorModel);
863     if (begin.parent() == d->m_root)
864         _q_itemsChanged(begin.row(), end.row() - begin.row() + 1, d->m_roles);
865 }
866
867 void QQuickVisualAdaptorModel::_q_layoutChanged()
868 {
869     Q_D(QQuickVisualAdaptorModel);
870     _q_itemsChanged(0, count(), d->m_roles);
871 }
872
873 void QQuickVisualAdaptorModel::_q_modelReset()
874 {
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);
883 }
884
885 QT_END_NAMESPACE
886
887 QML_DECLARE_TYPE(QListModelInterface)
888
889 #include <qquickvisualadaptormodel.moc>