Remove "All rights reserved" line from license headers.
[profile/ivi/qtdeclarative.git] / src / quick / items / qquickvisualadaptormodel.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtDeclarative module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qquickvisualadaptormodel_p.h"
43 #include "qquickvisualdatamodel_p_p.h"
44
45 #include <private/qdeclarativeengine_p.h>
46 #include <private/qdeclarativelistaccessor_p.h>
47 #include <private/qdeclarativepropertycache_p.h>
48 #include <private/qlistmodelinterface_p.h>
49 #include <private/qmetaobjectbuilder_p.h>
50 #include <private/qintrusivelist_p.h>
51 #include <private/qobject_p.h>
52
53 QT_BEGIN_NAMESPACE
54
55 class VDMDelegateDataType : public QDeclarativeRefCount
56 {
57 public:
58     VDMDelegateDataType()
59         : metaObject(0)
60         , propertyCache(0)
61         , propertyOffset(0)
62         , signalOffset(0)
63         , shared(true)
64     {
65     }
66
67     VDMDelegateDataType(const VDMDelegateDataType &type)
68         : metaObject(0)
69         , propertyCache(0)
70         , propertyOffset(type.propertyOffset)
71         , signalOffset(type.signalOffset)
72         , shared(false)
73         , builder(type.metaObject, QMetaObjectBuilder::Properties
74                 | QMetaObjectBuilder::Signals
75                 | QMetaObjectBuilder::SuperClass
76                 | QMetaObjectBuilder::ClassName)
77     {
78         builder.setFlags(QMetaObjectBuilder::DynamicMetaObject);
79     }
80
81     ~VDMDelegateDataType()
82     {
83         if (propertyCache)
84             propertyCache->release();
85         free(metaObject);
86     }
87
88     QMetaObject *metaObject;
89     QDeclarativePropertyCache *propertyCache;
90     int propertyOffset;
91     int signalOffset;
92     bool shared : 1;
93     QMetaObjectBuilder builder;
94 };
95
96 typedef QIntrusiveList<QQuickVisualDataModelItem, &QQuickVisualDataModelItem::cacheNode> QQuickVisualDataModelItemCache;
97
98 class QQuickVisualDataModelItemMetaObject;
99 class QQuickVisualAdaptorModelPrivate : public QObjectPrivate
100 {
101     Q_DECLARE_PUBLIC(QQuickVisualAdaptorModel)
102 public:
103     QQuickVisualAdaptorModelPrivate()
104         : m_engine(0)
105         , m_listAccessor(0)
106         , m_delegateDataType(0)
107         , createItem(&initializeModelData)
108         , stringValue(&initializeStringValue)
109         , m_ref(0)
110         , m_count(0)
111         , m_roleCount(0)
112         , m_objectList(false)
113     {
114     }
115
116     ~QQuickVisualAdaptorModelPrivate()
117     {
118         qPersistentDispose(m_constructor);
119     }
120
121     static QQuickVisualAdaptorModelPrivate *get(QQuickVisualAdaptorModel *m) {
122         return static_cast<QQuickVisualAdaptorModelPrivate *>(QObjectPrivate::get(m));
123     }
124
125     void addProperty(int role, int propertyId, const char *propertyName, const char *propertyType, bool isModelData = false);
126     template <typename T> void setModelDataType()
127     {
128         createItem = &T::create;
129         stringValue = &T::stringValue;
130         m_delegateDataType->builder.setFlags(QMetaObjectBuilder::DynamicMetaObject);
131         m_delegateDataType->builder.setClassName(T::staticMetaObject.className());
132         m_delegateDataType->builder.setSuperClass(&T::staticMetaObject);
133         m_delegateDataType->propertyOffset = T::staticMetaObject.propertyCount();
134         m_delegateDataType->signalOffset = T::staticMetaObject.methodCount();
135     }
136
137     void createMetaObject();
138
139     static QQuickVisualDataModelItem *initializeModelData(
140             QQuickVisualDataModelItemMetaType *metaType, QQuickVisualAdaptorModel *model, int index) {
141         QQuickVisualAdaptorModelPrivate *d = get(model);
142         d->createMetaObject();
143         return d->createItem(metaType, model, index);
144     }
145
146     static QString initializeStringValue(QQuickVisualAdaptorModelPrivate *model, int index, const QString &name) {
147         model->createMetaObject();
148         return model->stringValue(model, index, name);
149     }
150
151     typedef QQuickVisualDataModelItem *(*CreateModelData)(QQuickVisualDataModelItemMetaType *metaType, QQuickVisualAdaptorModel *model, int index);
152     typedef QString (*StringValue)(QQuickVisualAdaptorModelPrivate *model, int index, const QString &name);
153
154     struct PropertyData {
155         int role;
156         bool isModelData : 1;
157     };
158
159     int modelCount() const {
160         if (m_listModelInterface)
161             return m_listModelInterface->count();
162         if (m_abstractItemModel)
163             return m_abstractItemModel->rowCount(m_root);
164         if (m_listAccessor)
165             return m_listAccessor->count();
166         return 0;
167     }
168
169     QDeclarativeGuard<QDeclarativeEngine> m_engine;
170     QDeclarativeGuard<QListModelInterface> m_listModelInterface;
171     QDeclarativeGuard<QAbstractItemModel> m_abstractItemModel;
172     QDeclarativeListAccessor *m_listAccessor;
173     VDMDelegateDataType *m_delegateDataType;
174     CreateModelData createItem;
175     StringValue stringValue;
176     v8::Persistent<v8::Function> m_constructor;
177
178     int m_ref;
179     int m_count;
180     int m_roleCount;
181     QQuickVisualAdaptorModel::Flags m_flags;
182     bool m_objectList : 1;
183
184     QVariant m_modelVariant;
185     QModelIndex m_root;
186
187     QList<int> m_roles;
188     QList<int> watchedRoleIds;
189     QList<QByteArray> watchedRoles;
190     QHash<QByteArray,int> m_roleNames;
191     QVector<PropertyData> m_propertyData;
192     QQuickVisualDataModelItemCache m_cache;
193 };
194
195 class QQuickVDMCachedModelData : public QQuickVisualDataModelItem
196 {
197 public:
198     virtual QVariant value(QQuickVisualAdaptorModelPrivate *model, int role) const = 0;
199     virtual void setValue(QQuickVisualAdaptorModelPrivate *model, int role, const QVariant &value) = 0;
200
201     void setValue(const QString &role, const QVariant &value)
202     {
203         QQuickVisualAdaptorModelPrivate *d = QQuickVisualAdaptorModelPrivate::get(model);
204         QHash<QByteArray, int>::iterator it = d->m_roleNames.find(role.toUtf8());
205         if (it != d->m_roleNames.end()) {
206             for (int i = 0; i < d->m_propertyData.count(); ++i) {
207                 if (d->m_propertyData.at(i).role == *it) {
208                     cachedData[i] = value;
209                     return;
210                 }
211             }
212         }
213     }
214
215     bool resolveIndex(int idx)
216     {
217         if (index[0] == -1) {
218             Q_ASSERT(idx >= 0);
219             QQuickVisualAdaptorModelPrivate *d = QQuickVisualAdaptorModelPrivate::get(model);
220             index[0] = idx;
221             cachedData.clear();
222             emit modelIndexChanged();
223             const QMetaObject *meta = metaObject();
224             const int propertyCount = d->m_propertyData.count();
225             for (int i = 0; i < propertyCount; ++i)
226                 QMetaObject::activate(this, meta, i, 0);
227             return true;
228         } else {
229             return false;
230         }
231     }
232
233     static v8::Handle<v8::Value> get_property(v8::Local<v8::String>, const v8::AccessorInfo &info)
234     {
235         QQuickVisualDataModelItem *data = v8_resource_cast<QQuickVisualDataModelItem>(info.This());
236         if (!data)
237             V8THROW_ERROR("Not a valid VisualData object");
238
239         QQuickVisualAdaptorModelPrivate *model = QQuickVisualAdaptorModelPrivate::get(data->model);
240         QQuickVDMCachedModelData *modelData = static_cast<QQuickVDMCachedModelData *>(data);
241         const int propertyId = info.Data()->Int32Value();
242         if (data->index[0] == -1) {
243             if (!modelData->cachedData.isEmpty()) {
244                 return data->engine->fromVariant(
245                         modelData->cachedData.at(modelData->cachedData.count() > 1 ? propertyId : 0));
246             }
247         } else {
248             return data->engine->fromVariant(
249                     modelData->value(model, model->m_propertyData.at(propertyId).role));
250         }
251         return v8::Undefined();
252     }
253
254     static void set_property(
255             v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info)
256     {
257         QQuickVisualDataModelItem *data = v8_resource_cast<QQuickVisualDataModelItem>(info.This());
258         if (!data)
259             V8THROW_ERROR_SETTER("Not a valid VisualData object");
260
261         const int propertyId = info.Data()->Int32Value();
262         if (data->index[0] == -1) {
263             QQuickVDMCachedModelData *modelData = static_cast<QQuickVDMCachedModelData *>(data);
264             if (!modelData->cachedData.isEmpty()) {
265                 if (modelData->cachedData.count() > 1) {
266                     modelData->cachedData[propertyId] = data->engine->toVariant(value, QVariant::Invalid);
267                     QMetaObject::activate(data, data->metaObject(), propertyId, 0);
268                 } else if (modelData->cachedData.count() == 1) {
269                     modelData->cachedData[0] = data->engine->toVariant(value, QVariant::Invalid);
270                     QMetaObject::activate(data, data->metaObject(), 0, 0);
271                     QMetaObject::activate(data, data->metaObject(), 1, 0);
272                 }
273             }
274         }
275     }
276
277     v8::Handle<v8::Value> get()
278     {
279         QQuickVisualAdaptorModelPrivate *d = QQuickVisualAdaptorModelPrivate::get(model);
280
281         v8::Local<v8::Object> data = d->m_constructor->NewInstance();
282         data->SetExternalResource(this);
283         return data;
284     }
285
286
287     QQuickVDMCachedModelData(
288             QQuickVisualDataModelItemMetaType *metaType, QQuickVisualAdaptorModel *model, int index)
289         : QQuickVisualDataModelItem(metaType, model, index)
290     {
291         if (index == -1)
292             cachedData.resize(QQuickVisualAdaptorModelPrivate::get(model)->m_roleCount);
293     }
294
295     QVector<QVariant> cachedData;
296 };
297
298 class QQuickVisualDataModelItemMetaObject : public QAbstractDynamicMetaObject
299 {
300 public:
301     QQuickVisualDataModelItemMetaObject(QQuickVisualDataModelItem *data, VDMDelegateDataType *type)
302         : m_data(data)
303         , m_type(type)
304     {
305         QObjectPrivate *op = QObjectPrivate::get(m_data);
306         *static_cast<QMetaObject *>(this) = *type->metaObject;
307         op->metaObject = this;
308         m_type->addref();
309     }
310
311     ~QQuickVisualDataModelItemMetaObject() { m_type->release(); }
312
313     static v8::Handle<v8::Value> get_index(v8::Local<v8::String>, const v8::AccessorInfo &info)
314     {
315         QQuickVisualDataModelItem *data = v8_resource_cast<QQuickVisualDataModelItem>(info.This());
316         if (!data)
317             V8THROW_ERROR("Not a valid VisualData object");
318
319         return v8::Int32::New(data->index[0]);
320     }
321
322     QQuickVisualDataModelItem *m_data;
323     VDMDelegateDataType *m_type;
324 };
325
326 class QQuickVDMCachedModelDataMetaObject : public QQuickVisualDataModelItemMetaObject
327 {
328 public:
329     QQuickVDMCachedModelDataMetaObject(QQuickVisualDataModelItem *object, VDMDelegateDataType *type)
330         : QQuickVisualDataModelItemMetaObject(object, type) {}
331
332     int metaCall(QMetaObject::Call call, int id, void **arguments)
333     {
334         if (call == QMetaObject::ReadProperty && id >= m_type->propertyOffset) {
335             QQuickVisualAdaptorModelPrivate *model = QQuickVisualAdaptorModelPrivate::get(m_data->model);
336             const int propertyIndex = id - m_type->propertyOffset;
337             if (m_data->index[0] == -1) {
338                 QQuickVDMCachedModelData *data = static_cast<QQuickVDMCachedModelData *>(m_data);
339                 if (!data->cachedData.isEmpty()) {
340                     *static_cast<QVariant *>(arguments[0]) = data->cachedData.count() > 1
341                             ? data->cachedData.at(propertyIndex)
342                             : data->cachedData.at(0);
343                 }
344             } else {
345                 *static_cast<QVariant *>(arguments[0]) = static_cast<QQuickVDMCachedModelData *>(
346                         m_data)->value(model, model->m_propertyData.at(propertyIndex).role);
347             }
348             return -1;
349         } else if (call == QMetaObject::WriteProperty && id >= m_type->propertyOffset) {
350             QQuickVisualAdaptorModelPrivate *model = QQuickVisualAdaptorModelPrivate::get(m_data->model);
351             const int propertyIndex = id - m_type->propertyOffset;
352             if (m_data->index[0] == -1) {
353                 QQuickVDMCachedModelData *data = static_cast<QQuickVDMCachedModelData *>(m_data);
354                 if (data->cachedData.count() > 1) {
355                     data->cachedData[propertyIndex] = *static_cast<QVariant *>(arguments[0]);
356                     activate(data, this, propertyIndex, 0);
357                 } else if (data->cachedData.count() == 1) {
358                     data->cachedData[0] = *static_cast<QVariant *>(arguments[0]);
359                     activate(data, this, 0, 0);
360                     activate(data, this, 1, 0);
361                 }
362             } else {
363                 static_cast<QQuickVDMCachedModelData *>(m_data)->setValue(
364                         model,
365                         model->m_propertyData.at(propertyIndex).role,
366                         *static_cast<QVariant *>(arguments[0]));
367             }
368             return -1;
369         } else {
370             return m_data->qt_metacall(call, id, arguments);
371         }
372     }
373 };
374
375 class QQuickVDMAbstractItemModelData : public QQuickVDMCachedModelData
376 {
377     Q_OBJECT
378     Q_PROPERTY(bool hasModelChildren READ hasModelChildren CONSTANT)
379 public:
380     bool hasModelChildren() const
381     {
382         QQuickVisualAdaptorModelPrivate *d = QQuickVisualAdaptorModelPrivate::get(model);
383         return d->m_abstractItemModel->hasChildren(d->m_abstractItemModel->index(index[0], 0, d->m_root));
384     }
385
386     static QQuickVisualDataModelItem *create(
387             QQuickVisualDataModelItemMetaType *metaType, QQuickVisualAdaptorModel *model, int index) {
388         return new QQuickVDMAbstractItemModelData(metaType, model, index); }
389
390     static QString stringValue(QQuickVisualAdaptorModelPrivate *model, int index, const QString &role)
391     {
392         QHash<QByteArray, int>::const_iterator it = model->m_roleNames.find(role.toUtf8());
393         if (it != model->m_roleNames.end()) {
394             return model->m_abstractItemModel->index(index, 0, model->m_root).data(*it).toString();
395         } else if (role == QLatin1String("hasModelChildren")) {
396             return QVariant(model->m_abstractItemModel->hasChildren(
397                     model->m_abstractItemModel->index(index, 0, model->m_root))).toString();
398         } else {
399             return QString();
400         }
401     }
402
403     QVariant value(QQuickVisualAdaptorModelPrivate *model, int role) const
404     {
405         return model->m_abstractItemModel
406                 ? model->m_abstractItemModel->index(index[0], 0, model->m_root).data(role)
407                 : 0;
408     }
409
410     void setValue(QQuickVisualAdaptorModelPrivate *model, int role, const QVariant &value)
411     {
412         model->m_abstractItemModel->setData(
413                 model->m_abstractItemModel->index(index[0], 0, model->m_root), value, role);
414     }
415
416     static v8::Handle<v8::Value> get_hasModelChildren(v8::Local<v8::String>, const v8::AccessorInfo &info)
417     {
418         QQuickVisualDataModelItem *data = v8_resource_cast<QQuickVisualDataModelItem>(info.This());
419         if (!data)
420             V8THROW_ERROR("Not a valid VisualData object");
421
422         QQuickVisualAdaptorModelPrivate *model = QQuickVisualAdaptorModelPrivate::get(data->model);
423
424         return v8::Boolean::New(model->m_abstractItemModel->hasChildren(
425                 model->m_abstractItemModel->index(data->index[0], 0, model->m_root)));
426     }
427
428 private:
429     QQuickVDMAbstractItemModelData(
430             QQuickVisualDataModelItemMetaType *metaType, QQuickVisualAdaptorModel *model, int index)
431         : QQuickVDMCachedModelData(metaType, model, index)
432     {
433         new QQuickVDMCachedModelDataMetaObject(
434                 this, QQuickVisualAdaptorModelPrivate::get(model)->m_delegateDataType);
435     }
436 };
437
438 class QQuickVDMListModelInterfaceDataMetaObject : public QQuickVisualDataModelItemMetaObject
439 {
440 public:
441     QQuickVDMListModelInterfaceDataMetaObject(QQuickVisualDataModelItem *object, VDMDelegateDataType *type)
442         : QQuickVisualDataModelItemMetaObject(object, type) {}
443
444     int metaCall(QMetaObject::Call call, int id, void **arguments)
445     {
446         if (call == QMetaObject::ReadProperty && id >= m_type->propertyOffset) {
447             QQuickVisualAdaptorModelPrivate *model = QQuickVisualAdaptorModelPrivate::get(m_data->model);
448             if (m_data->index[0] == -1 || !model->m_listModelInterface)
449                 return -1;
450             *static_cast<QVariant *>(arguments[0]) = model->m_listModelInterface->data(
451                     m_data->index[0], model->m_propertyData.at(id - m_type->propertyOffset).role);
452             return -1;
453         } else {
454             return m_data->qt_metacall(call, id, arguments);
455         }
456     }
457
458 };
459
460 class QQuickVDMListModelInterfaceData : public QQuickVDMCachedModelData
461 {
462 public:
463     static QQuickVisualDataModelItem *create(
464             QQuickVisualDataModelItemMetaType *metaType, QQuickVisualAdaptorModel *model, int index) {
465         return new QQuickVDMListModelInterfaceData(metaType, model, index); }
466
467     static QString stringValue(QQuickVisualAdaptorModelPrivate *model, int index, const QString &role)
468     {
469         QHash<QByteArray, int>::const_iterator it = model->m_roleNames.find(role.toUtf8());
470         return it != model->m_roleNames.end()
471                 ? model->m_listModelInterface->data(index, *it).toString()
472                 : QString();
473     }
474
475     QVariant value(QQuickVisualAdaptorModelPrivate *model, int role) const
476     {
477         return model->m_listModelInterface
478                 ? model->m_listModelInterface->data(index[0], role)
479                 : 0;
480     }
481
482     void setValue(QQuickVisualAdaptorModelPrivate *, int, const QVariant &) {}
483
484 private:
485     QQuickVDMListModelInterfaceData(QQuickVisualDataModelItemMetaType *metaType, QQuickVisualAdaptorModel *model, int index)
486         : QQuickVDMCachedModelData(metaType, model, index)
487     {
488         new QQuickVDMCachedModelDataMetaObject(
489                 this, QQuickVisualAdaptorModelPrivate::get(model)->m_delegateDataType);
490     }
491 };
492
493 class QQuickVDMListAccessorData : public QQuickVisualDataModelItem
494 {
495     Q_OBJECT
496     Q_PROPERTY(QVariant modelData READ modelData WRITE setModelData NOTIFY modelDataChanged)
497 public:
498     QVariant modelData() const
499     {
500         QQuickVisualAdaptorModelPrivate *d = QQuickVisualAdaptorModelPrivate::get(model);
501         return index[0] != -1 && d->m_listAccessor
502                 ? d->m_listAccessor->at(index[0])
503                 : cachedData;
504     }
505
506     void setModelData(const QVariant &data)
507     {
508         if (index[0] == -1 && data != cachedData) {
509             cachedData = data;
510             emit modelDataChanged();
511         }
512     }
513
514     static QQuickVisualDataModelItem *create(
515             QQuickVisualDataModelItemMetaType *metaType, QQuickVisualAdaptorModel *model, int index) {
516         return new QQuickVDMListAccessorData(metaType, model, index); }
517
518     static QString stringValue(QQuickVisualAdaptorModelPrivate *model, int index, const QString &role)
519     {
520         return role == QLatin1String("modelData")
521                 ? model->m_listAccessor->at(index).toString()
522                 : QString();
523     }
524
525     static v8::Handle<v8::Value> get_modelData(v8::Local<v8::String>, const v8::AccessorInfo &info)
526     {
527         QQuickVisualDataModelItem *data = v8_resource_cast<QQuickVisualDataModelItem>(info.This());
528         if (!data)
529             V8THROW_ERROR("Not a valid VisualData object");
530
531         QQuickVisualAdaptorModelPrivate *d = QQuickVisualAdaptorModelPrivate::get(data->model);
532         if (data->index[0] == -1 || !d->m_listAccessor)
533             return data->engine->fromVariant(static_cast<QQuickVDMListAccessorData *>(data)->cachedData);
534
535         return data->engine->fromVariant(d->m_listAccessor->at(data->index[0]));
536     }
537
538     static void set_modelData(v8::Local<v8::String>, const v8::Handle<v8::Value> &value, const v8::AccessorInfo &info)
539     {
540         QQuickVisualDataModelItem *data = v8_resource_cast<QQuickVisualDataModelItem>(info.This());
541         if (!data)
542             V8THROW_ERROR_SETTER("Not a valid VisualData object");
543
544         if (data->index[0] == -1) {
545             static_cast<QQuickVDMListAccessorData *>(data)->setModelData(
546                     data->engine->toVariant(value, QVariant::Invalid));
547         }
548     }
549
550     void setValue(const QString &role, const QVariant &value)
551     {
552         if (role == QLatin1String("modelData"))
553             cachedData = value;
554     }
555
556     bool resolveIndex(int idx)
557     {
558         if (index[0] == -1) {
559             index[0] = idx;
560             cachedData.clear();
561             emit modelIndexChanged();
562             emit modelDataChanged();
563             return true;
564         } else {
565             return false;
566         }
567     }
568
569 Q_SIGNALS:
570     void modelDataChanged();
571
572 private:
573     QQuickVDMListAccessorData(QQuickVisualDataModelItemMetaType *metaType, QQuickVisualAdaptorModel *model, int index)
574         : QQuickVisualDataModelItem(metaType, model, index)
575     {
576     }
577
578     QVariant cachedData;
579 };
580
581 class QQuickVDMObjectDataMetaObject : public QQuickVisualDataModelItemMetaObject
582 {
583 public:
584     QQuickVDMObjectDataMetaObject(QQuickVisualDataModelItem *data, VDMDelegateDataType *type)
585         : QQuickVisualDataModelItemMetaObject(data, type)
586         , m_object(QQuickVisualAdaptorModelPrivate::get(data->model)->m_listAccessor->at(data->index[0]).value<QObject *>())
587     {}
588
589     int metaCall(QMetaObject::Call call, int id, void **arguments)
590     {
591         static const int objectPropertyOffset = QObject::staticMetaObject.propertyCount();
592         if (id >= m_type->propertyOffset
593                 && (call == QMetaObject::ReadProperty
594                 || call == QMetaObject::WriteProperty
595                 || call == QMetaObject::ResetProperty)) {
596             if (m_object)
597                 QMetaObject::metacall(m_object, call, id - m_type->propertyOffset + objectPropertyOffset, arguments);
598             return -1;
599         } else if (id >= m_type->signalOffset && call == QMetaObject::InvokeMetaMethod) {
600             QMetaObject::activate(m_data, this, id, 0);
601             return -1;
602         } else {
603             return m_data->qt_metacall(call, id, arguments);
604         }
605     }
606
607     int createProperty(const char *name, const char *)
608     {
609         if (!m_object)
610             return -1;
611         const QMetaObject *metaObject = m_object->metaObject();
612         static const int objectPropertyOffset = QObject::staticMetaObject.propertyCount();
613
614         const int previousPropertyCount = propertyCount() - propertyOffset();
615         int propertyIndex = metaObject->indexOfProperty(name);
616         if (propertyIndex == -1)
617             return -1;
618         if (previousPropertyCount + objectPropertyOffset == metaObject->propertyCount())
619             return propertyIndex + m_type->propertyOffset - objectPropertyOffset;
620
621         if (m_type->shared) {
622             VDMDelegateDataType *type = m_type;
623             m_type = new VDMDelegateDataType(*m_type);
624             type->release();
625         }
626
627         const int previousMethodCount = methodCount();
628         int notifierId = previousMethodCount;
629         for (int propertyId = previousPropertyCount; propertyId < metaObject->propertyCount() - objectPropertyOffset; ++propertyId) {
630             QMetaProperty property = metaObject->property(propertyId + objectPropertyOffset);
631             QMetaPropertyBuilder propertyBuilder;
632             if (property.hasNotifySignal()) {
633                 m_type->builder.addSignal("__" + QByteArray::number(propertyId) + "()");
634                 propertyBuilder = m_type->builder.addProperty(property.name(), property.typeName(), notifierId);
635                 ++notifierId;
636             } else {
637                 propertyBuilder = m_type->builder.addProperty(property.name(), property.typeName());
638             }
639             propertyBuilder.setWritable(property.isWritable());
640             propertyBuilder.setResettable(property.isResettable());
641             propertyBuilder.setConstant(property.isConstant());
642         }
643
644         if (m_type->metaObject)
645             free(m_type->metaObject);
646         m_type->metaObject = m_type->builder.toMetaObject();
647         *static_cast<QMetaObject *>(this) = *m_type->metaObject;
648
649         notifierId = previousMethodCount;
650         for (int i = previousPropertyCount; i < metaObject->propertyCount() - objectPropertyOffset; ++i) {
651             QMetaProperty property = metaObject->property(i + objectPropertyOffset);
652             if (property.hasNotifySignal()) {
653                 QDeclarativePropertyPrivate::connect(
654                         m_object, property.notifySignalIndex(), m_data, notifierId);
655                 ++notifierId;
656             }
657         }
658         return propertyIndex + m_type->propertyOffset - objectPropertyOffset;
659     }
660
661     QDeclarativeGuard<QObject> m_object;
662 };
663
664 class QQuickVDMObjectData : public QQuickVisualDataModelItem, public QQuickVisualAdaptorModelProxyInterface
665 {
666     Q_OBJECT
667     Q_PROPERTY(QObject *modelData READ modelData CONSTANT)
668     Q_INTERFACES(QQuickVisualAdaptorModelProxyInterface)
669 public:
670     QObject *modelData() const { return m_metaObject->m_object; }
671     QObject *proxiedObject() { return m_metaObject->m_object; }
672
673     static QQuickVisualDataModelItem *create(
674             QQuickVisualDataModelItemMetaType *metaType, QQuickVisualAdaptorModel *model, int index) {
675         return index >= 0 ? new QQuickVDMObjectData(metaType, model, index) : 0; }
676
677     static QString stringValue(QQuickVisualAdaptorModelPrivate *model, int index, const QString &name)
678     {
679         if (QObject *object = model->m_listAccessor->at(index).value<QObject *>())
680             return object->property(name.toUtf8()).toString();
681         return QString();
682     }
683
684 private:
685     QQuickVDMObjectData(QQuickVisualDataModelItemMetaType *metaType, QQuickVisualAdaptorModel *model, int index)
686         : QQuickVisualDataModelItem(metaType, model, index)
687         , m_metaObject(new QQuickVDMObjectDataMetaObject(this, QQuickVisualAdaptorModelPrivate::get(model)->m_delegateDataType))
688     {
689     }
690
691     QQuickVDMObjectDataMetaObject *m_metaObject;
692 };
693
694 void QQuickVisualAdaptorModelPrivate::addProperty(
695         int role, int propertyId, const char *propertyName, const char *propertyType, bool isModelData)
696 {
697     PropertyData propertyData;
698     propertyData.role = role;
699     propertyData.isModelData = isModelData;
700     m_delegateDataType->builder.addSignal("__" + QByteArray::number(propertyId) + "()");
701     QMetaPropertyBuilder property = m_delegateDataType->builder.addProperty(
702             propertyName, propertyType, propertyId);
703     property.setWritable(true); // No, yes, yes no?
704
705     m_propertyData.append(propertyData);
706 }
707
708 void QQuickVisualAdaptorModelPrivate::createMetaObject()
709 {
710     Q_ASSERT(!m_delegateDataType);
711
712     m_objectList = false;
713     m_propertyData.clear();
714
715     QV8Engine *v8Engine  = QDeclarativeEnginePrivate::getV8Engine(m_engine);
716
717     v8::HandleScope handleScope;
718     v8::Context::Scope contextScope(v8Engine->context());
719     v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New();
720     ft->InstanceTemplate()->SetHasExternalResource(true);
721     ft->PrototypeTemplate()->SetAccessor(
722             v8::String::New("index"), QQuickVisualDataModelItemMetaObject::get_index);
723
724     if (m_listAccessor
725             && m_listAccessor->type() != QDeclarativeListAccessor::ListProperty
726             && m_listAccessor->type() != QDeclarativeListAccessor::Instance) {
727         createItem = &QQuickVDMListAccessorData::create;
728         stringValue = &QQuickVDMListAccessorData::stringValue;
729         ft->PrototypeTemplate()->SetAccessor(
730                 v8::String::New("modelData"), QQuickVDMListAccessorData::get_modelData);
731         m_constructor = qPersistentNew<v8::Function>(ft->GetFunction());
732         return;
733     }
734
735     m_delegateDataType = new VDMDelegateDataType;
736     if (m_listModelInterface) {
737         setModelDataType<QQuickVDMListModelInterfaceData>();
738         QList<int> roles = m_listModelInterface->roles();
739         for (int propertyId = 0; propertyId < roles.count(); ++propertyId) {
740             const int role = roles.at(propertyId);
741             const QString roleName = m_listModelInterface->toString(role);
742             const QByteArray propertyName = roleName.toUtf8();
743             addProperty(role, propertyId, propertyName, "QVariant");
744             ft->PrototypeTemplate()->SetAccessor(
745                     v8Engine->toString(roleName),
746                     QQuickVDMListModelInterfaceData::get_property,
747                     QQuickVDMListModelInterfaceData::set_property,
748                     v8::Int32::New(propertyId));
749             m_roleNames.insert(propertyName, role);
750         }
751         m_roleCount = m_propertyData.count();
752         if (m_propertyData.count() == 1) {
753             addProperty(roles.first(), 1, "modelData", "QVariant", true);
754             ft->PrototypeTemplate()->SetAccessor(
755                     v8::String::New("modelData"),
756                     QQuickVDMListModelInterfaceData::get_property,
757                     QQuickVDMListModelInterfaceData::set_property,
758                     v8::Int32::New(0));
759             m_roleNames.insert("modelData", roles.first());
760         }
761     } else if (m_abstractItemModel) {
762         setModelDataType<QQuickVDMAbstractItemModelData>();
763         QHash<int, QByteArray> roleNames = m_abstractItemModel->roleNames();
764         for (QHash<int, QByteArray>::const_iterator it = roleNames.begin(); it != roleNames.end(); ++it) {
765             const int propertyId = m_propertyData.count();
766             addProperty(it.key(), propertyId, it.value(), "QVariant");
767             ft->PrototypeTemplate()->SetAccessor(
768                     v8::String::New(it.value().constData(), it.value().length()),
769                     QQuickVDMAbstractItemModelData::get_property,
770                     QQuickVDMAbstractItemModelData::set_property,
771                     v8::Int32::New(propertyId));
772             m_roleNames.insert(it.value(), it.key());
773         }
774         m_roleCount = m_propertyData.count();
775         if (m_propertyData.count() == 1) {
776             addProperty(roleNames.begin().key(), 1, "modelData", "QVariant", true);
777             ft->PrototypeTemplate()->SetAccessor(
778                     v8::String::New("modelData"),
779                     QQuickVDMAbstractItemModelData::get_property,
780                     QQuickVDMAbstractItemModelData::set_property,
781                     v8::Int32::New(0));
782             m_roleNames.insert("modelData", roleNames.begin().key());
783         }
784         ft->PrototypeTemplate()->SetAccessor(
785                 v8::String::New("hasModelChildren"),
786                 QQuickVDMAbstractItemModelData::get_hasModelChildren);
787     } else if (m_listAccessor) {
788         setModelDataType<QQuickVDMObjectData>();
789         m_objectList = true;
790         m_flags = QQuickVisualAdaptorModel::ProxiedObject;
791     } else {
792         Q_ASSERT(!"No model set on VisualDataModel");
793         return;
794     }
795     m_delegateDataType->metaObject = m_delegateDataType->builder.toMetaObject();
796     if (!m_objectList) {
797         m_delegateDataType->propertyCache = new QDeclarativePropertyCache(
798                 m_engine, m_delegateDataType->metaObject);
799         m_constructor = qPersistentNew<v8::Function>(ft->GetFunction());
800     }
801 }
802
803 //---------------------------------------------------------------------------
804
805 QQuickVisualAdaptorModel::QQuickVisualAdaptorModel(QObject *parent)
806     : QObject(*(new QQuickVisualAdaptorModelPrivate), parent)
807 {
808 }
809
810 QQuickVisualAdaptorModel::~QQuickVisualAdaptorModel()
811 {
812     Q_D(QQuickVisualAdaptorModel);
813     if (d->m_listAccessor)
814         delete d->m_listAccessor;
815     if (d->m_delegateDataType)
816         d->m_delegateDataType->release();
817 }
818
819 QQuickVisualAdaptorModel::Flags QQuickVisualAdaptorModel::flags() const
820 {
821     Q_D(const QQuickVisualAdaptorModel);
822     return d->m_flags;
823 }
824
825 QVariant QQuickVisualAdaptorModel::model() const
826 {
827     Q_D(const QQuickVisualAdaptorModel);
828     return d->m_modelVariant;
829 }
830
831 void QQuickVisualAdaptorModel::setModel(const QVariant &model, QDeclarativeEngine *engine)
832 {
833     Q_D(QQuickVisualAdaptorModel);
834     delete d->m_listAccessor;
835     d->m_engine = engine;
836     d->m_listAccessor = 0;
837     d->m_modelVariant = model;
838     if (d->m_listModelInterface) {
839         // Assume caller has released all items.
840         QObject::disconnect(d->m_listModelInterface, SIGNAL(itemsChanged(int,int,QList<int>)),
841                 this, SLOT(_q_itemsChanged(int,int,QList<int>)));
842         QObject::disconnect(d->m_listModelInterface, SIGNAL(itemsInserted(int,int)),
843                 this, SLOT(_q_itemsInserted(int,int)));
844         QObject::disconnect(d->m_listModelInterface, SIGNAL(itemsRemoved(int,int)),
845                 this, SLOT(_q_itemsRemoved(int,int)));
846         QObject::disconnect(d->m_listModelInterface, SIGNAL(itemsMoved(int,int,int)),
847                 this, SLOT(_q_itemsMoved(int,int,int)));
848         d->m_listModelInterface = 0;
849     } else if (d->m_abstractItemModel) {
850         QObject::disconnect(d->m_abstractItemModel, SIGNAL(rowsInserted(QModelIndex,int,int)),
851                             this, SLOT(_q_rowsInserted(QModelIndex,int,int)));
852         QObject::disconnect(d->m_abstractItemModel, SIGNAL(rowsRemoved(QModelIndex,int,int)),
853                             this, SLOT(_q_rowsRemoved(QModelIndex,int,int)));
854         QObject::disconnect(d->m_abstractItemModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
855                             this, SLOT(_q_dataChanged(QModelIndex,QModelIndex)));
856         QObject::disconnect(d->m_abstractItemModel, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)),
857                             this, SLOT(_q_rowsMoved(QModelIndex,int,int,QModelIndex,int)));
858         QObject::disconnect(d->m_abstractItemModel, SIGNAL(modelReset()), this, SLOT(_q_modelReset()));
859         QObject::disconnect(d->m_abstractItemModel, SIGNAL(layoutChanged()), this, SLOT(_q_layoutChanged()));
860         d->m_abstractItemModel = 0;
861     }
862
863     d->m_roles.clear();
864     d->m_roleNames.clear();
865     d->m_roleCount = 0;
866     d->m_flags = QQuickVisualAdaptorModel::Flags();
867     if (d->m_delegateDataType)
868         d->m_delegateDataType->release();
869     d->m_delegateDataType = 0;
870     d->createItem = &QQuickVisualAdaptorModelPrivate::initializeModelData;
871     d->stringValue = &QQuickVisualAdaptorModelPrivate::initializeStringValue;
872     qPersistentDispose(d->m_constructor);
873
874     if (d->m_count)
875         emit itemsRemoved(0, d->m_count);
876
877     QObject *object = qvariant_cast<QObject *>(model);
878     if (object && (d->m_listModelInterface = qobject_cast<QListModelInterface *>(object))) {
879         QObject::connect(d->m_listModelInterface, SIGNAL(itemsChanged(int,int,QList<int>)),
880                          this, SLOT(_q_itemsChanged(int,int,QList<int>)));
881         QObject::connect(d->m_listModelInterface, SIGNAL(itemsInserted(int,int)),
882                          this, SLOT(_q_itemsInserted(int,int)));
883         QObject::connect(d->m_listModelInterface, SIGNAL(itemsRemoved(int,int)),
884                          this, SLOT(_q_itemsRemoved(int,int)));
885         QObject::connect(d->m_listModelInterface, SIGNAL(itemsMoved(int,int,int)),
886                          this, SLOT(_q_itemsMoved(int,int,int)));
887         if ((d->m_count = d->m_listModelInterface->count()))
888             emit itemsInserted(0, d->m_count);
889         return;
890     } else if (object && (d->m_abstractItemModel = qobject_cast<QAbstractItemModel *>(object))) {
891         QObject::connect(d->m_abstractItemModel, SIGNAL(rowsInserted(QModelIndex,int,int)),
892                             this, SLOT(_q_rowsInserted(QModelIndex,int,int)));
893         QObject::connect(d->m_abstractItemModel, SIGNAL(rowsRemoved(QModelIndex,int,int)),
894                             this, SLOT(_q_rowsRemoved(QModelIndex,int,int)));
895         QObject::connect(d->m_abstractItemModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
896                             this, SLOT(_q_dataChanged(QModelIndex,QModelIndex)));
897         QObject::connect(d->m_abstractItemModel, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)),
898                             this, SLOT(_q_rowsMoved(QModelIndex,int,int,QModelIndex,int)));
899         QObject::connect(d->m_abstractItemModel, SIGNAL(modelReset()), this, SLOT(_q_modelReset()));
900         QObject::connect(d->m_abstractItemModel, SIGNAL(layoutChanged()), this, SLOT(_q_layoutChanged()));
901
902         if ((d->m_count = d->m_abstractItemModel->rowCount(d->m_root)))
903             emit itemsInserted(0, d->m_count);
904         return;
905     }
906
907     d->m_listAccessor = new QDeclarativeListAccessor;
908     d->m_listAccessor->setList(model, d->m_engine);
909     if ((d->m_count = d->m_listAccessor->count()))
910         emit itemsInserted(0, d->m_count);
911 }
912
913 QVariant QQuickVisualAdaptorModel::rootIndex() const
914 {
915     Q_D(const QQuickVisualAdaptorModel);
916     return QVariant::fromValue(d->m_root);
917 }
918
919 void QQuickVisualAdaptorModel::setRootIndex(const QVariant &root)
920 {
921     Q_D(QQuickVisualAdaptorModel);
922     QModelIndex modelIndex = qvariant_cast<QModelIndex>(root);
923     if (d->m_root != modelIndex) {
924         int oldCount = d->modelCount();
925         d->m_root = modelIndex;
926         if (d->m_abstractItemModel && d->m_abstractItemModel->canFetchMore(modelIndex))
927             d->m_abstractItemModel->fetchMore(modelIndex);
928         int newCount = d->modelCount();
929         if (oldCount)
930             emit itemsRemoved(0, oldCount);
931         if (newCount)
932             emit itemsInserted(0, newCount);
933         emit rootIndexChanged();
934     }
935 }
936
937 QVariant QQuickVisualAdaptorModel::modelIndex(int idx) const
938 {
939     Q_D(const QQuickVisualAdaptorModel);
940     if (d->m_abstractItemModel)
941         return QVariant::fromValue(d->m_abstractItemModel->index(idx, 0, d->m_root));
942     return QVariant::fromValue(QModelIndex());
943 }
944
945 QVariant QQuickVisualAdaptorModel::parentModelIndex() const
946 {
947     Q_D(const QQuickVisualAdaptorModel);
948     if (d->m_abstractItemModel)
949         return QVariant::fromValue(d->m_abstractItemModel->parent(d->m_root));
950     return QVariant::fromValue(QModelIndex());
951 }
952
953 int QQuickVisualAdaptorModel::count() const
954 {
955     Q_D(const QQuickVisualAdaptorModel);
956     return d->modelCount();
957 }
958
959 QQuickVisualDataModelItem *QQuickVisualAdaptorModel::createItem(QQuickVisualDataModelItemMetaType *metaType, int index)
960 {
961     Q_D(QQuickVisualAdaptorModel);
962
963     if (QQuickVisualDataModelItem *item = d->createItem(metaType, this, index)) {
964         d->m_cache.insert(item);
965
966         if (d->m_delegateDataType && d->m_delegateDataType->propertyCache) {
967             QDeclarativeData *qmldata = QDeclarativeData::get(item, true);
968             qmldata->propertyCache = d->m_delegateDataType->propertyCache;
969             qmldata->propertyCache->addref();
970         }
971         return item;
972     }
973     return 0;
974 }
975
976 QString QQuickVisualAdaptorModel::stringValue(int index, const QString &name)
977 {
978     Q_D(QQuickVisualAdaptorModel);
979     return d->stringValue(d, index, name);
980 }
981
982 bool QQuickVisualAdaptorModel::canFetchMore() const
983 {
984     Q_D(const QQuickVisualAdaptorModel);
985     return d->m_abstractItemModel && d->m_abstractItemModel->canFetchMore(d->m_root);
986 }
987
988 void QQuickVisualAdaptorModel::fetchMore()
989 {
990     Q_D(QQuickVisualAdaptorModel);
991     if (d->m_abstractItemModel)
992         d->m_abstractItemModel->fetchMore(d->m_root);
993 }
994
995 void QQuickVisualAdaptorModel::replaceWatchedRoles(const QList<QByteArray> &oldRoles, const QList<QByteArray> &newRoles)
996 {
997     Q_D(QQuickVisualAdaptorModel);
998     d->watchedRoleIds.clear();
999     foreach (const QByteArray &oldRole, oldRoles)
1000         d->watchedRoles.removeOne(oldRole);
1001     d->watchedRoles += newRoles;
1002 }
1003
1004 void QQuickVisualAdaptorModel::_q_itemsChanged(int index, int count, const QList<int> &roles)
1005 {
1006     Q_D(QQuickVisualAdaptorModel);
1007     bool changed = roles.isEmpty();
1008     if (!d->watchedRoles.isEmpty() && d->watchedRoleIds.isEmpty()) {
1009         foreach (QByteArray r, d->watchedRoles) {
1010             if (d->m_roleNames.contains(r))
1011                 d->watchedRoleIds << d->m_roleNames.value(r);
1012         }
1013     }
1014
1015     QVector<int> signalIndexes;
1016     for (int i = 0; i < roles.count(); ++i) {
1017         const int role = roles.at(i);
1018         if (!changed && d->watchedRoleIds.contains(role))
1019             changed = true;
1020         for (int propertyId = 0; propertyId < d->m_propertyData.count(); ++propertyId) {
1021             if (d->m_propertyData.at(propertyId).role == role)
1022                 signalIndexes.append(propertyId + d->m_delegateDataType->signalOffset);
1023         }
1024     }
1025     if (roles.isEmpty()) {
1026         for (int propertyId = 0; propertyId < d->m_propertyData.count(); ++propertyId)
1027             signalIndexes.append(propertyId + d->m_delegateDataType->signalOffset);
1028     }
1029
1030     typedef QQuickVisualDataModelItemCache::iterator iterator;
1031     for (iterator it = d->m_cache.begin(); it != d->m_cache.end(); ++it) {
1032         const int idx = it->modelIndex();
1033         if (idx >= index && idx < index + count) {
1034             QQuickVisualDataModelItem *data = *it;
1035             for (int i = 0; i < signalIndexes.count(); ++i)
1036                 QMetaObject::activate(data, signalIndexes.at(i), 0);
1037         }
1038     }
1039     if (changed)
1040         emit itemsChanged(index, count);
1041 }
1042
1043 void QQuickVisualAdaptorModel::_q_itemsInserted(int index, int count)
1044 {
1045     Q_D(QQuickVisualAdaptorModel);
1046     if (count <= 0)
1047         return;
1048     d->m_count += count;
1049
1050     typedef QQuickVisualDataModelItemCache::iterator iterator;
1051     for (iterator it = d->m_cache.begin(); it != d->m_cache.end(); ++it) {
1052         if (it->modelIndex() >= index)
1053             it->setModelIndex(it->modelIndex() + count);
1054     }
1055
1056     emit itemsInserted(index, count);
1057 }
1058
1059 void QQuickVisualAdaptorModel::_q_itemsRemoved(int index, int count)
1060 {
1061     Q_D(QQuickVisualAdaptorModel);
1062     if (count <= 0)
1063         return;
1064     d->m_count -= count;
1065
1066     typedef QQuickVisualDataModelItemCache::iterator iterator;
1067     for (iterator it = d->m_cache.begin(); it != d->m_cache.end(); ++it) {
1068         if (it->modelIndex() >= index + count)
1069             it->setModelIndex(it->modelIndex() - count);
1070         else  if (it->modelIndex() >= index)
1071             it->setModelIndex(-1);
1072     }
1073
1074     emit itemsRemoved(index, count);
1075 }
1076
1077 void QQuickVisualAdaptorModel::_q_itemsMoved(int from, int to, int count)
1078 {
1079     Q_D(QQuickVisualAdaptorModel);
1080     const int minimum = qMin(from, to);
1081     const int maximum = qMax(from, to) + count;
1082     const int difference = from > to ? count : -count;
1083
1084     typedef QQuickVisualDataModelItemCache::iterator iterator;
1085     for (iterator it = d->m_cache.begin(); it != d->m_cache.end(); ++it) {
1086         if (it->modelIndex() >= from && it->modelIndex() < from + count)
1087             it->setModelIndex(it->modelIndex() - from + to);
1088         else if (it->modelIndex() >= minimum && it->modelIndex() < maximum)
1089             it->setModelIndex(it->modelIndex() + difference);
1090     }
1091     emit itemsMoved(from, to, count);
1092 }
1093
1094 void QQuickVisualAdaptorModel::_q_rowsInserted(const QModelIndex &parent, int begin, int end)
1095 {
1096     Q_D(QQuickVisualAdaptorModel);
1097     if (parent == d->m_root)
1098         _q_itemsInserted(begin, end - begin + 1);
1099 }
1100
1101 void QQuickVisualAdaptorModel::_q_rowsRemoved(const QModelIndex &parent, int begin, int end)
1102 {
1103     Q_D(QQuickVisualAdaptorModel);
1104     if (parent == d->m_root)
1105         _q_itemsRemoved(begin, end - begin + 1);
1106 }
1107
1108 void QQuickVisualAdaptorModel::_q_rowsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationRow)
1109 {
1110    Q_D(QQuickVisualAdaptorModel);
1111     const int count = sourceEnd - sourceStart + 1;
1112     if (destinationParent == d->m_root && sourceParent == d->m_root) {
1113         _q_itemsMoved(sourceStart, sourceStart > destinationRow ? destinationRow : destinationRow-count, count);
1114     } else if (sourceParent == d->m_root) {
1115         _q_itemsRemoved(sourceStart, count);
1116     } else if (destinationParent == d->m_root) {
1117         _q_itemsInserted(destinationRow, count);
1118     }
1119 }
1120
1121 void QQuickVisualAdaptorModel::_q_dataChanged(const QModelIndex &begin, const QModelIndex &end)
1122 {
1123     Q_D(QQuickVisualAdaptorModel);
1124     if (begin.parent() == d->m_root)
1125         _q_itemsChanged(begin.row(), end.row() - begin.row() + 1, d->m_roles);
1126 }
1127
1128 void QQuickVisualAdaptorModel::_q_layoutChanged()
1129 {
1130     Q_D(QQuickVisualAdaptorModel);
1131     _q_itemsChanged(0, count(), d->m_roles);
1132 }
1133
1134 void QQuickVisualAdaptorModel::_q_modelReset()
1135 {
1136     Q_D(QQuickVisualAdaptorModel);
1137     int oldCount = d->m_count;
1138     d->m_root = QModelIndex();
1139     d->m_count = d->modelCount();
1140     emit modelReset(oldCount, d->m_count);
1141     emit rootIndexChanged();
1142     if (d->m_abstractItemModel && d->m_abstractItemModel->canFetchMore(d->m_root))
1143         d->m_abstractItemModel->fetchMore(d->m_root);
1144 }
1145
1146 QT_END_NAMESPACE
1147
1148 QML_DECLARE_TYPE(QListModelInterface)
1149
1150 #include <qquickvisualadaptormodel.moc>