source: trunk/src/declarative/graphicsitems/qdeclarativevisualitemmodel.cpp@ 1125

Last change on this file since 1125 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

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