Initial import from qtquick2.
[profile/ivi/qtdeclarative.git] / src / declarative / items / qsgvisualitemmodel.cpp
1 // Commit: 45153a37e4d9e39e8c326a0f33ea17be49bb29e2
2 /****************************************************************************
3 **
4 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
5 ** All rights reserved.
6 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 **
8 ** This file is part of the QtDeclarative module of the Qt Toolkit.
9 **
10 ** $QT_BEGIN_LICENSE:LGPL$
11 ** No Commercial Usage
12 ** This file contains pre-release code and may not be distributed.
13 ** You may use this file in accordance with the terms and conditions
14 ** contained in the Technology Preview License Agreement accompanying
15 ** this package.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file.  Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Nokia gives you certain additional
26 ** rights.  These rights are described in the Nokia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** If you have questions regarding the use of this file, please contact
30 ** Nokia at qt-info@nokia.com.
31 **
32 **
33 **
34 **
35 **
36 **
37 **
38 **
39 ** $QT_END_LICENSE$
40 **
41 ****************************************************************************/
42
43 #include "qsgvisualitemmodel_p.h"
44 #include "qsgitem.h"
45
46 #include <QtDeclarative/qdeclarativecontext.h>
47 #include <QtDeclarative/qdeclarativeengine.h>
48 #include <QtDeclarative/qdeclarativeexpression.h>
49 #include <QtDeclarative/qdeclarativeinfo.h>
50
51 #include <private/qdeclarativecontext_p.h>
52 #include <private/qdeclarativepackage_p.h>
53 #include <private/qdeclarativeopenmetaobject_p.h>
54 #include <private/qdeclarativelistaccessor_p.h>
55 #include <private/qdeclarativedata_p.h>
56 #include <private/qdeclarativepropertycache_p.h>
57 #include <private/qdeclarativeguard_p.h>
58 #include <private/qdeclarativeglobal_p.h>
59 #include <private/qlistmodelinterface_p.h>
60 #include <private/qmetaobjectbuilder_p.h>
61 #include <private/qobject_p.h>
62
63 #include <QtCore/qhash.h>
64 #include <QtCore/qlist.h>
65
66 QT_BEGIN_NAMESPACE
67
68 QHash<QObject*, QSGVisualItemModelAttached*> QSGVisualItemModelAttached::attachedProperties;
69
70
71 class QSGVisualItemModelPrivate : public QObjectPrivate
72 {
73     Q_DECLARE_PUBLIC(QSGVisualItemModel)
74 public:
75     QSGVisualItemModelPrivate() : QObjectPrivate() {}
76
77     static void children_append(QDeclarativeListProperty<QSGItem> *prop, QSGItem *item) {
78         QDeclarative_setParent_noEvent(item, prop->object);
79         static_cast<QSGVisualItemModelPrivate *>(prop->data)->children.append(Item(item));
80         static_cast<QSGVisualItemModelPrivate *>(prop->data)->itemAppended();
81         static_cast<QSGVisualItemModelPrivate *>(prop->data)->emitChildrenChanged();
82     }
83
84     static int children_count(QDeclarativeListProperty<QSGItem> *prop) {
85         return static_cast<QSGVisualItemModelPrivate *>(prop->data)->children.count();
86     }
87
88     static QSGItem *children_at(QDeclarativeListProperty<QSGItem> *prop, int index) {
89         return static_cast<QSGVisualItemModelPrivate *>(prop->data)->children.at(index).item;
90     }
91
92     void itemAppended() {
93         Q_Q(QSGVisualItemModel);
94         QSGVisualItemModelAttached *attached = QSGVisualItemModelAttached::properties(children.last().item);
95         attached->setIndex(children.count()-1);
96         emit q->itemsInserted(children.count()-1, 1);
97         emit q->countChanged();
98     }
99
100     void emitChildrenChanged() {
101         Q_Q(QSGVisualItemModel);
102         emit q->childrenChanged();
103     }
104
105     int indexOf(QSGItem *item) const {
106         for (int i = 0; i < children.count(); ++i)
107             if (children.at(i).item == item)
108                 return i;
109         return -1;
110     }
111
112     class Item {
113     public:
114         Item(QSGItem *i) : item(i), ref(0) {}
115
116         void addRef() { ++ref; }
117         bool deref() { return --ref == 0; }
118
119         QSGItem *item;
120         int ref;
121     };
122
123     QList<Item> children;
124 };
125
126 QSGVisualItemModel::QSGVisualItemModel(QObject *parent)
127     : QSGVisualModel(*(new QSGVisualItemModelPrivate), parent)
128 {
129 }
130
131 QDeclarativeListProperty<QSGItem> QSGVisualItemModel::children()
132 {
133     Q_D(QSGVisualItemModel);
134     return QDeclarativeListProperty<QSGItem>(this, d, d->children_append,
135                                                       d->children_count, d->children_at);
136 }
137
138 int QSGVisualItemModel::count() const
139 {
140     Q_D(const QSGVisualItemModel);
141     return d->children.count();
142 }
143
144 bool QSGVisualItemModel::isValid() const
145 {
146     return true;
147 }
148
149 QSGItem *QSGVisualItemModel::item(int index, bool)
150 {
151     Q_D(QSGVisualItemModel);
152     QSGVisualItemModelPrivate::Item &item = d->children[index];
153     item.addRef();
154     return item.item;
155 }
156
157 QSGVisualModel::ReleaseFlags QSGVisualItemModel::release(QSGItem *item)
158 {
159     Q_D(QSGVisualItemModel);
160     int idx = d->indexOf(item);
161     if (idx >= 0) {
162         if (d->children[idx].deref()) {
163             // XXX todo - the original did item->scene()->removeItem().  Why?
164             item->setParentItem(0);
165             QDeclarative_setParent_noEvent(item, this);
166         }
167     }
168     return 0;
169 }
170
171 bool QSGVisualItemModel::completePending() const
172 {
173     return false;
174 }
175
176 void QSGVisualItemModel::completeItem()
177 {
178     // Nothing to do
179 }
180
181 QString QSGVisualItemModel::stringValue(int index, const QString &name)
182 {
183     Q_D(QSGVisualItemModel);
184     if (index < 0 || index >= d->children.count())
185         return QString();
186     return QDeclarativeEngine::contextForObject(d->children.at(index).item)->contextProperty(name).toString();
187 }
188
189 int QSGVisualItemModel::indexOf(QSGItem *item, QObject *) const
190 {
191     Q_D(const QSGVisualItemModel);
192     return d->indexOf(item);
193 }
194
195 QSGVisualItemModelAttached *QSGVisualItemModel::qmlAttachedProperties(QObject *obj)
196 {
197     return QSGVisualItemModelAttached::properties(obj);
198 }
199
200 //============================================================================
201
202 class VDMDelegateDataType : public QDeclarativeOpenMetaObjectType
203 {
204 public:
205     VDMDelegateDataType(const QMetaObject *base, QDeclarativeEngine *engine) : QDeclarativeOpenMetaObjectType(base, engine) {}
206
207     void propertyCreated(int, QMetaPropertyBuilder &prop) {
208         prop.setWritable(false);
209     }
210 };
211
212 class QSGVisualDataModelParts;
213 class QSGVisualDataModelData;
214 class QSGVisualDataModelPrivate : public QObjectPrivate
215 {
216 public:
217     QSGVisualDataModelPrivate(QDeclarativeContext *);
218
219     static QSGVisualDataModelPrivate *get(QSGVisualDataModel *m) {
220         return static_cast<QSGVisualDataModelPrivate *>(QObjectPrivate::get(m));
221     }
222
223     QDeclarativeGuard<QListModelInterface> m_listModelInterface;
224     QDeclarativeGuard<QAbstractItemModel> m_abstractItemModel;
225     QDeclarativeGuard<QSGVisualDataModel> m_visualItemModel;
226     QString m_part;
227
228     QDeclarativeComponent *m_delegate;
229     QDeclarativeGuard<QDeclarativeContext> m_context;
230     QList<int> m_roles;
231     QHash<QByteArray,int> m_roleNames;
232     void ensureRoles() {
233         if (m_roleNames.isEmpty()) {
234             if (m_listModelInterface) {
235                 m_roles = m_listModelInterface->roles();
236                 for (int ii = 0; ii < m_roles.count(); ++ii)
237                     m_roleNames.insert(m_listModelInterface->toString(m_roles.at(ii)).toUtf8(), m_roles.at(ii));
238             } else if (m_abstractItemModel) {
239                 for (QHash<int,QByteArray>::const_iterator it = m_abstractItemModel->roleNames().begin();
240                         it != m_abstractItemModel->roleNames().end(); ++it) {
241                     m_roles.append(it.key());
242                     m_roleNames.insert(*it, it.key());
243                 }
244                 if (m_roles.count())
245                     m_roleNames.insert("hasModelChildren", -1);
246             } else if (m_listAccessor) {
247                 m_roleNames.insert("modelData", 0);
248                 if (m_listAccessor->type() == QDeclarativeListAccessor::Instance) {
249                     if (QObject *object = m_listAccessor->at(0).value<QObject*>()) {
250                         int count = object->metaObject()->propertyCount();
251                         for (int ii = 1; ii < count; ++ii) {
252                             const QMetaProperty &prop = object->metaObject()->property(ii);
253                             m_roleNames.insert(prop.name(), 0);
254                         }
255                     }
256                 }
257             }
258         }
259     }
260
261     QHash<int,int> m_roleToPropId;
262     int m_modelDataPropId;
263     void createMetaData() {
264         if (!m_metaDataCreated) {
265             ensureRoles();
266             if (m_roleNames.count()) {
267                 QHash<QByteArray, int>::const_iterator it = m_roleNames.begin();
268                 while (it != m_roleNames.end()) {
269                     int propId = m_delegateDataType->createProperty(it.key()) - m_delegateDataType->propertyOffset();
270                     m_roleToPropId.insert(*it, propId);
271                     ++it;
272                 }
273                 // Add modelData property
274                 if (m_roles.count() == 1)
275                     m_modelDataPropId = m_delegateDataType->createProperty("modelData") - m_delegateDataType->propertyOffset();
276                 m_metaDataCreated = true;
277             }
278         }
279     }
280
281     struct ObjectRef {
282         ObjectRef(QObject *object=0) : obj(object), ref(1) {}
283         QObject *obj;
284         int ref;
285     };
286     class Cache : public QHash<int, ObjectRef> {
287     public:
288         QObject *getItem(int index) {
289             QObject *item = 0;
290             QHash<int,ObjectRef>::iterator it = find(index);
291             if (it != end()) {
292                 (*it).ref++;
293                 item = (*it).obj;
294             }
295             return item;
296         }
297         QObject *item(int index) {
298             QObject *item = 0;
299             QHash<int, ObjectRef>::const_iterator it = find(index);
300             if (it != end())
301                 item = (*it).obj;
302             return item;
303         }
304         void insertItem(int index, QObject *obj) {
305             insert(index, ObjectRef(obj));
306         }
307         bool releaseItem(QObject *obj) {
308             QHash<int, ObjectRef>::iterator it = begin();
309             for (; it != end(); ++it) {
310                 ObjectRef &objRef = *it;
311                 if (objRef.obj == obj) {
312                     if (--objRef.ref == 0) {
313                         erase(it);
314                         return true;
315                     }
316                     break;
317                 }
318             }
319             return false;
320         }
321     };
322
323     int modelCount() const {
324         if (m_visualItemModel)
325             return m_visualItemModel->count();
326         if (m_listModelInterface)
327             return m_listModelInterface->count();
328         if (m_abstractItemModel)
329             return m_abstractItemModel->rowCount(m_root);
330         if (m_listAccessor)
331             return m_listAccessor->count();
332         return 0;
333     }
334
335     Cache m_cache;
336     QHash<QObject *, QDeclarativePackage*> m_packaged;
337
338     QSGVisualDataModelParts *m_parts;
339     friend class QSGVisualItemParts;
340
341     VDMDelegateDataType *m_delegateDataType;
342     friend class QSGVisualDataModelData;
343     bool m_metaDataCreated : 1;
344     bool m_metaDataCacheable : 1;
345     bool m_delegateValidated : 1;
346     bool m_completePending : 1;
347
348     QSGVisualDataModelData *data(QObject *item);
349
350     QVariant m_modelVariant;
351     QDeclarativeListAccessor *m_listAccessor;
352
353     QModelIndex m_root;
354     QList<QByteArray> watchedRoles;
355     QList<int> watchedRoleIds;
356 };
357
358 class QSGVisualDataModelDataMetaObject : public QDeclarativeOpenMetaObject
359 {
360 public:
361     QSGVisualDataModelDataMetaObject(QObject *parent, QDeclarativeOpenMetaObjectType *type)
362     : QDeclarativeOpenMetaObject(parent, type) {}
363
364     virtual QVariant initialValue(int);
365     virtual int createProperty(const char *, const char *);
366
367 private:
368     friend class QSGVisualDataModelData;
369 };
370
371 class QSGVisualDataModelData : public QObject
372 {
373 Q_OBJECT
374 public:
375     QSGVisualDataModelData(int index, QSGVisualDataModel *model);
376     ~QSGVisualDataModelData();
377
378     Q_PROPERTY(int index READ index NOTIFY indexChanged)
379     int index() const;
380     void setIndex(int index);
381
382     int propForRole(int) const;
383     int modelDataPropertyId() const {
384         QSGVisualDataModelPrivate *model = QSGVisualDataModelPrivate::get(m_model);
385         return model->m_modelDataPropId;
386     }
387
388     void setValue(int, const QVariant &);
389     bool hasValue(int id) const {
390         return m_meta->hasValue(id);
391     }
392
393     void ensureProperties();
394
395 Q_SIGNALS:
396     void indexChanged();
397
398 private:
399     friend class QSGVisualDataModelDataMetaObject;
400     int m_index;
401     QDeclarativeGuard<QSGVisualDataModel> m_model;
402     QSGVisualDataModelDataMetaObject *m_meta;
403 };
404
405 int QSGVisualDataModelData::propForRole(int id) const
406 {
407     QSGVisualDataModelPrivate *model = QSGVisualDataModelPrivate::get(m_model);
408     QHash<int,int>::const_iterator it = model->m_roleToPropId.find(id);
409     if (it != model->m_roleToPropId.end())
410         return *it;
411
412     return -1;
413 }
414
415 void QSGVisualDataModelData::setValue(int id, const QVariant &val)
416 {
417     m_meta->setValue(id, val);
418 }
419
420 int QSGVisualDataModelDataMetaObject::createProperty(const char *name, const char *type)
421 {
422     QSGVisualDataModelData *data =
423         static_cast<QSGVisualDataModelData *>(object());
424
425     if (!data->m_model)
426         return -1;
427
428     QSGVisualDataModelPrivate *model = QSGVisualDataModelPrivate::get(data->m_model);
429     if (data->m_index < 0 || data->m_index >= model->modelCount())
430         return -1;
431
432     if ((!model->m_listModelInterface || !model->m_abstractItemModel) && model->m_listAccessor) {
433         if (model->m_listAccessor->type() == QDeclarativeListAccessor::ListProperty) {
434             model->ensureRoles();
435             if (qstrcmp(name,"modelData") == 0)
436                 return QDeclarativeOpenMetaObject::createProperty(name, type);
437         }
438     }
439     return -1;
440 }
441
442 QVariant QSGVisualDataModelDataMetaObject::initialValue(int propId)
443 {
444     QSGVisualDataModelData *data =
445         static_cast<QSGVisualDataModelData *>(object());
446
447     Q_ASSERT(data->m_model);
448     QSGVisualDataModelPrivate *model = QSGVisualDataModelPrivate::get(data->m_model);
449
450     QByteArray propName = name(propId);
451     if ((!model->m_listModelInterface || !model->m_abstractItemModel) && model->m_listAccessor) {
452         if (propName == "modelData") {
453             if (model->m_listAccessor->type() == QDeclarativeListAccessor::Instance) {
454                 QObject *object = model->m_listAccessor->at(0).value<QObject*>();
455                 return object->metaObject()->property(1).read(object); // the first property after objectName
456             }
457             return model->m_listAccessor->at(data->m_index);
458         } else {
459             // return any property of a single object instance.
460             QObject *object = model->m_listAccessor->at(data->m_index).value<QObject*>();
461             return object->property(propName);
462         }
463     } else if (model->m_listModelInterface) {
464         model->ensureRoles();
465         QHash<QByteArray,int>::const_iterator it = model->m_roleNames.find(propName);
466         if (it != model->m_roleNames.end()) {
467             QVariant value = model->m_listModelInterface->data(data->m_index, *it);
468             return value;
469         } else if (model->m_roles.count() == 1 && propName == "modelData") {
470             //for compatibility with other lists, assign modelData if there is only a single role
471             QVariant value = model->m_listModelInterface->data(data->m_index, model->m_roles.first());
472             return value;
473         }
474     } else if (model->m_abstractItemModel) {
475         model->ensureRoles();
476         QModelIndex index = model->m_abstractItemModel->index(data->m_index, 0, model->m_root);
477         if (propName == "hasModelChildren") {
478             return model->m_abstractItemModel->hasChildren(index);
479         } else {
480             QHash<QByteArray,int>::const_iterator it = model->m_roleNames.find(propName);
481             if (it != model->m_roleNames.end()) {
482                 return model->m_abstractItemModel->data(index, *it);
483             } else if (model->m_roles.count() == 1 && propName == "modelData") {
484                 //for compatibility with other lists, assign modelData if there is only a single role
485                 return model->m_abstractItemModel->data(index, model->m_roles.first());
486             }
487         }
488     }
489     Q_ASSERT(!"Can never be reached");
490     return QVariant();
491 }
492
493 QSGVisualDataModelData::QSGVisualDataModelData(int index,
494                                                QSGVisualDataModel *model)
495 : m_index(index), m_model(model),
496 m_meta(new QSGVisualDataModelDataMetaObject(this, QSGVisualDataModelPrivate::get(model)->m_delegateDataType))
497 {
498     ensureProperties();
499 }
500
501 QSGVisualDataModelData::~QSGVisualDataModelData()
502 {
503 }
504
505 void QSGVisualDataModelData::ensureProperties()
506 {
507     QSGVisualDataModelPrivate *modelPriv = QSGVisualDataModelPrivate::get(m_model);
508     if (modelPriv->m_metaDataCacheable) {
509         if (!modelPriv->m_metaDataCreated)
510             modelPriv->createMetaData();
511         if (modelPriv->m_metaDataCreated)
512             m_meta->setCached(true);
513     }
514 }
515
516 int QSGVisualDataModelData::index() const
517 {
518     return m_index;
519 }
520
521 // This is internal only - it should not be set from qml
522 void QSGVisualDataModelData::setIndex(int index)
523 {
524     m_index = index;
525     emit indexChanged();
526 }
527
528 //---------------------------------------------------------------------------
529
530 class QSGVisualDataModelPartsMetaObject : public QDeclarativeOpenMetaObject
531 {
532 public:
533     QSGVisualDataModelPartsMetaObject(QObject *parent)
534     : QDeclarativeOpenMetaObject(parent) {}
535
536     virtual void propertyCreated(int, QMetaPropertyBuilder &);
537     virtual QVariant initialValue(int);
538 };
539
540 class QSGVisualDataModelParts : public QObject
541 {
542 Q_OBJECT
543 public:
544     QSGVisualDataModelParts(QSGVisualDataModel *parent);
545
546 private:
547     friend class QSGVisualDataModelPartsMetaObject;
548     QSGVisualDataModel *model;
549 };
550
551 void QSGVisualDataModelPartsMetaObject::propertyCreated(int, QMetaPropertyBuilder &prop)
552 {
553     prop.setWritable(false);
554 }
555
556 QVariant QSGVisualDataModelPartsMetaObject::initialValue(int id)
557 {
558     QSGVisualDataModel *m = new QSGVisualDataModel;
559     m->setParent(object());
560     m->setPart(QString::fromUtf8(name(id)));
561     m->setModel(QVariant::fromValue(static_cast<QSGVisualDataModelParts *>(object())->model));
562
563     QVariant var = QVariant::fromValue((QObject *)m);
564     return var;
565 }
566
567 QSGVisualDataModelParts::QSGVisualDataModelParts(QSGVisualDataModel *parent)
568 : QObject(parent), model(parent)
569 {
570     new QSGVisualDataModelPartsMetaObject(this);
571 }
572
573 QSGVisualDataModelPrivate::QSGVisualDataModelPrivate(QDeclarativeContext *ctxt)
574 : m_listModelInterface(0), m_abstractItemModel(0), m_visualItemModel(0), m_delegate(0)
575 , m_context(ctxt), m_modelDataPropId(-1), m_parts(0), m_delegateDataType(0), m_metaDataCreated(false)
576 , m_metaDataCacheable(false), m_delegateValidated(false), m_completePending(false), m_listAccessor(0)
577 {
578 }
579
580 QSGVisualDataModelData *QSGVisualDataModelPrivate::data(QObject *item)
581 {
582     QSGVisualDataModelData *dataItem =
583         item->findChild<QSGVisualDataModelData *>();
584     Q_ASSERT(dataItem);
585     return dataItem;
586 }
587
588 //---------------------------------------------------------------------------
589
590 QSGVisualDataModel::QSGVisualDataModel()
591 : QSGVisualModel(*(new QSGVisualDataModelPrivate(0)))
592 {
593 }
594
595 QSGVisualDataModel::QSGVisualDataModel(QDeclarativeContext *ctxt, QObject *parent)
596 : QSGVisualModel(*(new QSGVisualDataModelPrivate(ctxt)), parent)
597 {
598 }
599
600 QSGVisualDataModel::~QSGVisualDataModel()
601 {
602     Q_D(QSGVisualDataModel);
603     if (d->m_listAccessor)
604         delete d->m_listAccessor;
605     if (d->m_delegateDataType)
606         d->m_delegateDataType->release();
607 }
608
609 QVariant QSGVisualDataModel::model() const
610 {
611     Q_D(const QSGVisualDataModel);
612     return d->m_modelVariant;
613 }
614
615 void QSGVisualDataModel::setModel(const QVariant &model)
616 {
617     Q_D(QSGVisualDataModel);
618     delete d->m_listAccessor;
619     d->m_listAccessor = 0;
620     d->m_modelVariant = model;
621     if (d->m_listModelInterface) {
622         // Assume caller has released all items.
623         QObject::disconnect(d->m_listModelInterface, SIGNAL(itemsChanged(int,int,QList<int>)),
624                 this, SLOT(_q_itemsChanged(int,int,QList<int>)));
625         QObject::disconnect(d->m_listModelInterface, SIGNAL(itemsInserted(int,int)),
626                 this, SLOT(_q_itemsInserted(int,int)));
627         QObject::disconnect(d->m_listModelInterface, SIGNAL(itemsRemoved(int,int)),
628                 this, SLOT(_q_itemsRemoved(int,int)));
629         QObject::disconnect(d->m_listModelInterface, SIGNAL(itemsMoved(int,int,int)),
630                 this, SLOT(_q_itemsMoved(int,int,int)));
631         d->m_listModelInterface = 0;
632     } else if (d->m_abstractItemModel) {
633         QObject::disconnect(d->m_abstractItemModel, SIGNAL(rowsInserted(QModelIndex,int,int)),
634                             this, SLOT(_q_rowsInserted(QModelIndex,int,int)));
635         QObject::disconnect(d->m_abstractItemModel, SIGNAL(rowsRemoved(QModelIndex,int,int)),
636                             this, SLOT(_q_rowsRemoved(QModelIndex,int,int)));
637         QObject::disconnect(d->m_abstractItemModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
638                             this, SLOT(_q_dataChanged(QModelIndex,QModelIndex)));
639         QObject::disconnect(d->m_abstractItemModel, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)),
640                             this, SLOT(_q_rowsMoved(QModelIndex,int,int,QModelIndex,int)));
641         QObject::disconnect(d->m_abstractItemModel, SIGNAL(modelReset()), this, SLOT(_q_modelReset()));
642         QObject::disconnect(d->m_abstractItemModel, SIGNAL(layoutChanged()), this, SLOT(_q_layoutChanged()));
643         d->m_abstractItemModel = 0;
644     } else if (d->m_visualItemModel) {
645         QObject::disconnect(d->m_visualItemModel, SIGNAL(itemsInserted(int,int)),
646                          this, SIGNAL(itemsInserted(int,int)));
647         QObject::disconnect(d->m_visualItemModel, SIGNAL(itemsRemoved(int,int)),
648                          this, SIGNAL(itemsRemoved(int,int)));
649         QObject::disconnect(d->m_visualItemModel, SIGNAL(itemsMoved(int,int,int)),
650                          this, SIGNAL(itemsMoved(int,int,int)));
651         QObject::disconnect(d->m_visualItemModel, SIGNAL(createdPackage(int,QDeclarativePackage*)),
652                          this, SLOT(_q_createdPackage(int,QDeclarativePackage*)));
653         QObject::disconnect(d->m_visualItemModel, SIGNAL(destroyingPackage(QDeclarativePackage*)),
654                          this, SLOT(_q_destroyingPackage(QDeclarativePackage*)));
655         d->m_visualItemModel = 0;
656     }
657
658     d->m_roles.clear();
659     d->m_roleNames.clear();
660     if (d->m_delegateDataType)
661         d->m_delegateDataType->release();
662     d->m_metaDataCreated = 0;
663     d->m_metaDataCacheable = false;
664     d->m_delegateDataType = new VDMDelegateDataType(&QSGVisualDataModelData::staticMetaObject, d->m_context?d->m_context->engine():qmlEngine(this));
665
666     QObject *object = qvariant_cast<QObject *>(model);
667     if (object && (d->m_listModelInterface = qobject_cast<QListModelInterface *>(object))) {
668         QObject::connect(d->m_listModelInterface, SIGNAL(itemsChanged(int,int,QList<int>)),
669                          this, SLOT(_q_itemsChanged(int,int,QList<int>)));
670         QObject::connect(d->m_listModelInterface, SIGNAL(itemsInserted(int,int)),
671                          this, SLOT(_q_itemsInserted(int,int)));
672         QObject::connect(d->m_listModelInterface, SIGNAL(itemsRemoved(int,int)),
673                          this, SLOT(_q_itemsRemoved(int,int)));
674         QObject::connect(d->m_listModelInterface, SIGNAL(itemsMoved(int,int,int)),
675                          this, SLOT(_q_itemsMoved(int,int,int)));
676         d->m_metaDataCacheable = true;
677         if (d->m_delegate && d->m_listModelInterface->count())
678             emit itemsInserted(0, d->m_listModelInterface->count());
679         return;
680     } else if (object && (d->m_abstractItemModel = qobject_cast<QAbstractItemModel *>(object))) {
681         QObject::connect(d->m_abstractItemModel, SIGNAL(rowsInserted(QModelIndex,int,int)),
682                             this, SLOT(_q_rowsInserted(QModelIndex,int,int)));
683         QObject::connect(d->m_abstractItemModel, SIGNAL(rowsRemoved(QModelIndex,int,int)),
684                             this, SLOT(_q_rowsRemoved(QModelIndex,int,int)));
685         QObject::connect(d->m_abstractItemModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
686                             this, SLOT(_q_dataChanged(QModelIndex,QModelIndex)));
687         QObject::connect(d->m_abstractItemModel, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)),
688                             this, SLOT(_q_rowsMoved(QModelIndex,int,int,QModelIndex,int)));
689         QObject::connect(d->m_abstractItemModel, SIGNAL(modelReset()), this, SLOT(_q_modelReset()));
690         QObject::connect(d->m_abstractItemModel, SIGNAL(layoutChanged()), this, SLOT(_q_layoutChanged()));
691         d->m_metaDataCacheable = true;
692         if (d->m_abstractItemModel->canFetchMore(d->m_root))
693             d->m_abstractItemModel->fetchMore(d->m_root);
694         return;
695     }
696     if ((d->m_visualItemModel = qvariant_cast<QSGVisualDataModel *>(model))) {
697         QObject::connect(d->m_visualItemModel, SIGNAL(itemsInserted(int,int)),
698                          this, SIGNAL(itemsInserted(int,int)));
699         QObject::connect(d->m_visualItemModel, SIGNAL(itemsRemoved(int,int)),
700                          this, SIGNAL(itemsRemoved(int,int)));
701         QObject::connect(d->m_visualItemModel, SIGNAL(itemsMoved(int,int,int)),
702                          this, SIGNAL(itemsMoved(int,int,int)));
703         QObject::connect(d->m_visualItemModel, SIGNAL(createdPackage(int,QDeclarativePackage*)),
704                          this, SLOT(_q_createdPackage(int,QDeclarativePackage*)));
705         QObject::connect(d->m_visualItemModel, SIGNAL(destroyingPackage(QDeclarativePackage*)),
706                          this, SLOT(_q_destroyingPackage(QDeclarativePackage*)));
707         return;
708     }
709     d->m_listAccessor = new QDeclarativeListAccessor;
710     d->m_listAccessor->setList(model, d->m_context?d->m_context->engine():qmlEngine(this));
711     if (d->m_listAccessor->type() != QDeclarativeListAccessor::ListProperty)
712         d->m_metaDataCacheable = true;
713     if (d->m_delegate && d->modelCount()) {
714         emit itemsInserted(0, d->modelCount());
715         emit countChanged();
716     }
717 }
718
719 QDeclarativeComponent *QSGVisualDataModel::delegate() const
720 {
721     Q_D(const QSGVisualDataModel);
722     if (d->m_visualItemModel)
723         return d->m_visualItemModel->delegate();
724     return d->m_delegate;
725 }
726
727 void QSGVisualDataModel::setDelegate(QDeclarativeComponent *delegate)
728 {
729     Q_D(QSGVisualDataModel);
730     bool wasValid = d->m_delegate != 0;
731     d->m_delegate = delegate;
732     d->m_delegateValidated = false;
733     if (!wasValid && d->modelCount() && d->m_delegate) {
734         emit itemsInserted(0, d->modelCount());
735         emit countChanged();
736     }
737     if (wasValid && !d->m_delegate && d->modelCount()) {
738         emit itemsRemoved(0, d->modelCount());
739         emit countChanged();
740     }
741 }
742
743 QVariant QSGVisualDataModel::rootIndex() const
744 {
745     Q_D(const QSGVisualDataModel);
746     return QVariant::fromValue(d->m_root);
747 }
748
749 void QSGVisualDataModel::setRootIndex(const QVariant &root)
750 {
751     Q_D(QSGVisualDataModel);
752     QModelIndex modelIndex = qvariant_cast<QModelIndex>(root);
753     if (d->m_root != modelIndex) {
754         int oldCount = d->modelCount();
755         d->m_root = modelIndex;
756         if (d->m_abstractItemModel && d->m_abstractItemModel->canFetchMore(modelIndex))
757             d->m_abstractItemModel->fetchMore(modelIndex);
758         int newCount = d->modelCount();
759         if (d->m_delegate && oldCount)
760             emit itemsRemoved(0, oldCount);
761         if (d->m_delegate && newCount)
762             emit itemsInserted(0, newCount);
763         if (newCount != oldCount)
764             emit countChanged();
765         emit rootIndexChanged();
766     }
767 }
768
769 QVariant QSGVisualDataModel::modelIndex(int idx) const
770 {
771     Q_D(const QSGVisualDataModel);
772     if (d->m_abstractItemModel)
773         return QVariant::fromValue(d->m_abstractItemModel->index(idx, 0, d->m_root));
774     return QVariant::fromValue(QModelIndex());
775 }
776
777 QVariant QSGVisualDataModel::parentModelIndex() const
778 {
779     Q_D(const QSGVisualDataModel);
780     if (d->m_abstractItemModel)
781         return QVariant::fromValue(d->m_abstractItemModel->parent(d->m_root));
782     return QVariant::fromValue(QModelIndex());
783 }
784
785 QString QSGVisualDataModel::part() const
786 {
787     Q_D(const QSGVisualDataModel);
788     return d->m_part;
789 }
790
791 void QSGVisualDataModel::setPart(const QString &part)
792 {
793     Q_D(QSGVisualDataModel);
794     d->m_part = part;
795 }
796
797 int QSGVisualDataModel::count() const
798 {
799     Q_D(const QSGVisualDataModel);
800     if (d->m_visualItemModel)
801         return d->m_visualItemModel->count();
802     if (!d->m_delegate)
803         return 0;
804     return d->modelCount();
805 }
806
807 QSGItem *QSGVisualDataModel::item(int index, bool complete)
808 {
809     Q_D(QSGVisualDataModel);
810     if (d->m_visualItemModel)
811         return d->m_visualItemModel->item(index, d->m_part.toUtf8(), complete);
812     return item(index, QByteArray(), complete);
813 }
814
815 /*
816   Returns ReleaseStatus flags.
817 */
818 QSGVisualDataModel::ReleaseFlags QSGVisualDataModel::release(QSGItem *item)
819 {
820     Q_D(QSGVisualDataModel);
821     if (d->m_visualItemModel)
822         return d->m_visualItemModel->release(item);
823
824     ReleaseFlags stat = 0;
825     QObject *obj = item;
826     bool inPackage = false;
827
828     QHash<QObject*,QDeclarativePackage*>::iterator it = d->m_packaged.find(item);
829     if (it != d->m_packaged.end()) {
830         QDeclarativePackage *package = *it;
831         d->m_packaged.erase(it);
832         if (d->m_packaged.contains(item))
833             stat |= Referenced;
834         inPackage = true;
835         obj = package; // fall through and delete
836     }
837
838     if (d->m_cache.releaseItem(obj)) {
839         // Remove any bindings to avoid warnings due to parent change.
840         QObjectPrivate *p = QObjectPrivate::get(obj);
841         Q_ASSERT(p->declarativeData);
842         QDeclarativeData *d = static_cast<QDeclarativeData*>(p->declarativeData);
843         if (d->ownContext && d->context)
844             d->context->clearContext();
845
846         if (inPackage) {
847             emit destroyingPackage(qobject_cast<QDeclarativePackage*>(obj));
848         } else {
849             // XXX todo - the original did item->scene()->removeItem().  Why?
850             item->setParentItem(0);
851         }
852         stat |= Destroyed;
853         obj->deleteLater();
854     } else if (!inPackage) {
855         stat |= Referenced;
856     }
857
858     return stat;
859 }
860
861 QObject *QSGVisualDataModel::parts()
862 {
863     Q_D(QSGVisualDataModel);
864     if (!d->m_parts)
865         d->m_parts = new QSGVisualDataModelParts(this);
866     return d->m_parts;
867 }
868
869 QSGItem *QSGVisualDataModel::item(int index, const QByteArray &viewId, bool complete)
870 {
871     Q_D(QSGVisualDataModel);
872     if (d->m_visualItemModel)
873         return d->m_visualItemModel->item(index, viewId, complete);
874
875     if (d->modelCount() <= 0 || !d->m_delegate)
876         return 0;
877     QObject *nobj = d->m_cache.getItem(index);
878     bool needComplete = false;
879     if (!nobj) {
880         QDeclarativeContext *ccontext = d->m_context;
881         if (!ccontext) ccontext = qmlContext(this);
882         QDeclarativeContext *ctxt = new QDeclarativeContext(ccontext);
883         QSGVisualDataModelData *data = new QSGVisualDataModelData(index, this);
884         if ((!d->m_listModelInterface || !d->m_abstractItemModel) && d->m_listAccessor
885             && d->m_listAccessor->type() == QDeclarativeListAccessor::ListProperty) {
886             ctxt->setContextObject(d->m_listAccessor->at(index).value<QObject*>());
887             ctxt = new QDeclarativeContext(ctxt, ctxt);
888         }
889         ctxt->setContextProperty(QLatin1String("model"), data);
890         ctxt->setContextObject(data);
891         d->m_completePending = false;
892         nobj = d->m_delegate->beginCreate(ctxt);
893         if (complete) {
894             d->m_delegate->completeCreate();
895         } else {
896             d->m_completePending = true;
897             needComplete = true;
898         }
899         if (nobj) {
900             QDeclarative_setParent_noEvent(ctxt, nobj);
901             QDeclarative_setParent_noEvent(data, nobj);
902             d->m_cache.insertItem(index, nobj);
903             if (QDeclarativePackage *package = qobject_cast<QDeclarativePackage *>(nobj))
904                 emit createdPackage(index, package);
905         } else {
906             delete data;
907             delete ctxt;
908             qmlInfo(this, d->m_delegate->errors()) << "Error creating delegate";
909         }
910     }
911     QSGItem *item = qobject_cast<QSGItem *>(nobj);
912     if (!item) {
913         QDeclarativePackage *package = qobject_cast<QDeclarativePackage *>(nobj);
914         if (package) {
915             QObject *o = package->part(QString::fromUtf8(viewId));
916             item = qobject_cast<QSGItem *>(o);
917             if (item)
918                 d->m_packaged.insertMulti(item, package);
919         }
920     }
921     if (!item) {
922         if (needComplete)
923             d->m_delegate->completeCreate();
924         d->m_cache.releaseItem(nobj);
925         if (!d->m_delegateValidated) {
926             qmlInfo(d->m_delegate) << QSGVisualDataModel::tr("Delegate component must be Item type.");
927             d->m_delegateValidated = true;
928         }
929     }
930     if (d->modelCount()-1 == index && d->m_abstractItemModel && d->m_abstractItemModel->canFetchMore(d->m_root))
931         d->m_abstractItemModel->fetchMore(d->m_root);
932
933     return item;
934 }
935
936 bool QSGVisualDataModel::completePending() const
937 {
938     Q_D(const QSGVisualDataModel);
939     if (d->m_visualItemModel)
940         return d->m_visualItemModel->completePending();
941     return d->m_completePending;
942 }
943
944 void QSGVisualDataModel::completeItem()
945 {
946     Q_D(QSGVisualDataModel);
947     if (d->m_visualItemModel) {
948         d->m_visualItemModel->completeItem();
949         return;
950     }
951
952     d->m_delegate->completeCreate();
953     d->m_completePending = false;
954 }
955
956 QString QSGVisualDataModel::stringValue(int index, const QString &name)
957 {
958     Q_D(QSGVisualDataModel);
959     if (d->m_visualItemModel)
960         return d->m_visualItemModel->stringValue(index, name);
961
962     if ((!d->m_listModelInterface || !d->m_abstractItemModel) && d->m_listAccessor) {
963         if (QObject *object = d->m_listAccessor->at(index).value<QObject*>())
964             return object->property(name.toUtf8()).toString();
965     }
966
967     if ((!d->m_listModelInterface && !d->m_abstractItemModel) || !d->m_delegate)
968         return QString();
969
970     QString val;
971     QObject *data = 0;
972     bool tempData = false;
973
974     if (QObject *nobj = d->m_cache.item(index))
975         data = d->data(nobj);
976     if (!data) {
977         data = new QSGVisualDataModelData(index, this);
978         tempData = true;
979     }
980
981     QDeclarativeData *ddata = QDeclarativeData::get(data);
982     if (ddata && ddata->propertyCache) {
983         QDeclarativePropertyCache::Data *prop = ddata->propertyCache->property(name);
984         if (prop) {
985             if (prop->propType == QVariant::String) {
986                 void *args[] = { &val, 0 };
987                 QMetaObject::metacall(data, QMetaObject::ReadProperty, prop->coreIndex, args);
988             } else if (prop->propType == qMetaTypeId<QVariant>()) {
989                 QVariant v;
990                 void *args[] = { &v, 0 };
991                 QMetaObject::metacall(data, QMetaObject::ReadProperty, prop->coreIndex, args);
992                 val = v.toString();
993             }
994         } else {
995             val = data->property(name.toUtf8()).toString();
996         }
997     } else {
998         val = data->property(name.toUtf8()).toString();
999     }
1000
1001     if (tempData)
1002         delete data;
1003
1004     return val;
1005 }
1006
1007 int QSGVisualDataModel::indexOf(QSGItem *item, QObject *) const
1008 {
1009     QVariant val = QDeclarativeEngine::contextForObject(item)->contextProperty(QLatin1String("index"));
1010         return val.toInt();
1011     return -1;
1012 }
1013
1014 void QSGVisualDataModel::setWatchedRoles(QList<QByteArray> roles)
1015 {
1016     Q_D(QSGVisualDataModel);
1017     d->watchedRoles = roles;
1018     d->watchedRoleIds.clear();
1019 }
1020
1021 void QSGVisualDataModel::_q_itemsChanged(int index, int count,
1022                                          const QList<int> &roles)
1023 {
1024     Q_D(QSGVisualDataModel);
1025     bool changed = false;
1026     if (!d->watchedRoles.isEmpty() && d->watchedRoleIds.isEmpty()) {
1027         foreach (QByteArray r, d->watchedRoles) {
1028             if (d->m_roleNames.contains(r))
1029                 d->watchedRoleIds << d->m_roleNames.value(r);
1030         }
1031     }
1032
1033     for (QHash<int,QSGVisualDataModelPrivate::ObjectRef>::ConstIterator iter = d->m_cache.begin();
1034         iter != d->m_cache.end(); ++iter) {
1035         const int idx = iter.key();
1036
1037         if (idx >= index && idx < index+count) {
1038             QSGVisualDataModelPrivate::ObjectRef objRef = *iter;
1039             QSGVisualDataModelData *data = d->data(objRef.obj);
1040             for (int roleIdx = 0; roleIdx < roles.count(); ++roleIdx) {
1041                 int role = roles.at(roleIdx);
1042                 if (!changed && !d->watchedRoleIds.isEmpty() && d->watchedRoleIds.contains(role))
1043                     changed = true;
1044                 int propId = data->propForRole(role);
1045                 if (propId != -1) {
1046                     if (data->hasValue(propId)) {
1047                         if (d->m_listModelInterface) {
1048                             data->setValue(propId, d->m_listModelInterface->data(idx, role));
1049                         } else if (d->m_abstractItemModel) {
1050                             QModelIndex index = d->m_abstractItemModel->index(idx, 0, d->m_root);
1051                             data->setValue(propId, d->m_abstractItemModel->data(index, role));
1052                         }
1053                     }
1054                 } else {
1055                     QString roleName;
1056                     if (d->m_listModelInterface)
1057                         roleName = d->m_listModelInterface->toString(role);
1058                     else if (d->m_abstractItemModel)
1059                         roleName = QString::fromUtf8(d->m_abstractItemModel->roleNames().value(role));
1060                     qmlInfo(this) << "Changing role not present in item: " << roleName;
1061                 }
1062             }
1063             if (d->m_roles.count() == 1) {
1064                 // Handle the modelData role we add if there is just one role.
1065                 int propId = data->modelDataPropertyId();
1066                 if (data->hasValue(propId)) {
1067                     int role = d->m_roles.at(0);
1068                     if (d->m_listModelInterface) {
1069                         data->setValue(propId, d->m_listModelInterface->data(idx, role));
1070                     } else if (d->m_abstractItemModel) {
1071                         QModelIndex index = d->m_abstractItemModel->index(idx, 0, d->m_root);
1072                         data->setValue(propId, d->m_abstractItemModel->data(index, role));
1073                     }
1074                 }
1075             }
1076         }
1077     }
1078     if (changed)
1079         emit itemsChanged(index, count);
1080 }
1081
1082 void QSGVisualDataModel::_q_itemsInserted(int index, int count)
1083 {
1084     Q_D(QSGVisualDataModel);
1085     if (!count)
1086         return;
1087     // XXX - highly inefficient
1088     QHash<int,QSGVisualDataModelPrivate::ObjectRef> items;
1089     for (QHash<int,QSGVisualDataModelPrivate::ObjectRef>::Iterator iter = d->m_cache.begin();
1090         iter != d->m_cache.end(); ) {
1091
1092         if (iter.key() >= index) {
1093             QSGVisualDataModelPrivate::ObjectRef objRef = *iter;
1094             int index = iter.key() + count;
1095             iter = d->m_cache.erase(iter);
1096
1097             items.insert(index, objRef);
1098
1099             QSGVisualDataModelData *data = d->data(objRef.obj);
1100             data->setIndex(index);
1101         } else {
1102             ++iter;
1103         }
1104     }
1105     d->m_cache.unite(items);
1106
1107     emit itemsInserted(index, count);
1108     emit countChanged();
1109 }
1110
1111 void QSGVisualDataModel::_q_itemsRemoved(int index, int count)
1112 {
1113     Q_D(QSGVisualDataModel);
1114     if (!count)
1115         return;
1116     // XXX - highly inefficient
1117     QHash<int, QSGVisualDataModelPrivate::ObjectRef> items;
1118     for (QHash<int, QSGVisualDataModelPrivate::ObjectRef>::Iterator iter = d->m_cache.begin();
1119         iter != d->m_cache.end(); ) {
1120         if (iter.key() >= index && iter.key() < index + count) {
1121             QSGVisualDataModelPrivate::ObjectRef objRef = *iter;
1122             iter = d->m_cache.erase(iter);
1123             items.insertMulti(-1, objRef); //XXX perhaps better to maintain separately
1124             QSGVisualDataModelData *data = d->data(objRef.obj);
1125             data->setIndex(-1);
1126         } else if (iter.key() >= index + count) {
1127             QSGVisualDataModelPrivate::ObjectRef objRef = *iter;
1128             int index = iter.key() - count;
1129             iter = d->m_cache.erase(iter);
1130             items.insert(index, objRef);
1131             QSGVisualDataModelData *data = d->data(objRef.obj);
1132             data->setIndex(index);
1133         } else {
1134             ++iter;
1135         }
1136     }
1137
1138     d->m_cache.unite(items);
1139     emit itemsRemoved(index, count);
1140     emit countChanged();
1141 }
1142
1143 void QSGVisualDataModel::_q_itemsMoved(int from, int to, int count)
1144 {
1145     Q_D(QSGVisualDataModel);
1146     // XXX - highly inefficient
1147     QHash<int,QSGVisualDataModelPrivate::ObjectRef> items;
1148     for (QHash<int,QSGVisualDataModelPrivate::ObjectRef>::Iterator iter = d->m_cache.begin();
1149         iter != d->m_cache.end(); ) {
1150
1151         if (iter.key() >= from && iter.key() < from + count) {
1152             QSGVisualDataModelPrivate::ObjectRef objRef = *iter;
1153             int index = iter.key() - from + to;
1154             iter = d->m_cache.erase(iter);
1155
1156             items.insert(index, objRef);
1157
1158             QSGVisualDataModelData *data = d->data(objRef.obj);
1159             data->setIndex(index);
1160         } else {
1161             ++iter;
1162         }
1163     }
1164     for (QHash<int,QSGVisualDataModelPrivate::ObjectRef>::Iterator iter = d->m_cache.begin();
1165         iter != d->m_cache.end(); ) {
1166
1167         int diff = from > to ? count : -count;
1168         if (iter.key() >= qMin(from,to) && iter.key() < qMax(from+count,to+count)) {
1169             QSGVisualDataModelPrivate::ObjectRef objRef = *iter;
1170             int index = iter.key() + diff;
1171             iter = d->m_cache.erase(iter);
1172
1173             items.insert(index, objRef);
1174
1175             QSGVisualDataModelData *data = d->data(objRef.obj);
1176             data->setIndex(index);
1177         } else {
1178             ++iter;
1179         }
1180     }
1181     d->m_cache.unite(items);
1182
1183     emit itemsMoved(from, to, count);
1184 }
1185
1186 void QSGVisualDataModel::_q_rowsInserted(const QModelIndex &parent, int begin, int end)
1187 {
1188     Q_D(QSGVisualDataModel);
1189     if (parent == d->m_root)
1190         _q_itemsInserted(begin, end - begin + 1);
1191 }
1192
1193 void QSGVisualDataModel::_q_rowsRemoved(const QModelIndex &parent, int begin, int end)
1194 {
1195     Q_D(QSGVisualDataModel);
1196     if (parent == d->m_root)
1197         _q_itemsRemoved(begin, end - begin + 1);
1198 }
1199
1200 void QSGVisualDataModel::_q_rowsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationRow)
1201 {
1202     Q_D(QSGVisualDataModel);
1203     const int count = sourceEnd - sourceStart + 1;
1204     if (destinationParent == d->m_root && sourceParent == d->m_root) {
1205         _q_itemsMoved(sourceStart, sourceStart > destinationRow ? destinationRow : destinationRow-1, count);
1206     } else if (sourceParent == d->m_root) {
1207         _q_itemsRemoved(sourceStart, count);
1208     } else if (destinationParent == d->m_root) {
1209         _q_itemsInserted(destinationRow, count);
1210     }
1211 }
1212
1213 void QSGVisualDataModel::_q_dataChanged(const QModelIndex &begin, const QModelIndex &end)
1214 {
1215     Q_D(QSGVisualDataModel);
1216     if (begin.parent() == d->m_root)
1217         _q_itemsChanged(begin.row(), end.row() - begin.row() + 1, d->m_roles);
1218 }
1219
1220 void QSGVisualDataModel::_q_layoutChanged()
1221 {
1222     Q_D(QSGVisualDataModel);
1223     _q_itemsChanged(0, count(), d->m_roles);
1224 }
1225
1226 void QSGVisualDataModel::_q_modelReset()
1227 {
1228     emit modelReset();
1229 }
1230
1231 void QSGVisualDataModel::_q_createdPackage(int index, QDeclarativePackage *package)
1232 {
1233     Q_D(QSGVisualDataModel);
1234     emit createdItem(index, qobject_cast<QSGItem*>(package->part(d->m_part)));
1235 }
1236
1237 void QSGVisualDataModel::_q_destroyingPackage(QDeclarativePackage *package)
1238 {
1239     Q_D(QSGVisualDataModel);
1240     emit destroyingItem(qobject_cast<QSGItem*>(package->part(d->m_part)));
1241 }
1242
1243 QT_END_NAMESPACE
1244
1245 QML_DECLARE_TYPE(QListModelInterface)
1246
1247 #include <qsgvisualitemmodel.moc>