1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtQml module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include "qquickvisualadaptormodel_p.h"
43 #include "qquickvisualdatamodel_p_p.h"
45 #include <private/qmetaobjectbuilder_p.h>
46 #include <private/qqmlproperty_p.h>
50 template <typename T, typename M> static void setModelDataType(QMetaObjectBuilder *builder, M *metaType)
52 builder->setFlags(QMetaObjectBuilder::DynamicMetaObject);
53 builder->setClassName(T::staticMetaObject.className());
54 builder->setSuperClass(&T::staticMetaObject);
55 metaType->propertyOffset = T::staticMetaObject.propertyCount();
56 metaType->signalOffset = T::staticMetaObject.methodCount();
59 static void addProperty(QMetaObjectBuilder *builder, int propertyId, const QByteArray &propertyName, const QByteArray &propertyType)
61 builder->addSignal("__" + QByteArray::number(propertyId) + "()");
62 QMetaPropertyBuilder property = builder->addProperty(
63 propertyName, propertyType, propertyId);
64 property.setWritable(true);
67 static v8::Handle<v8::Value> get_index(v8::Local<v8::String>, const v8::AccessorInfo &info)
69 QQuickVisualDataModelItem *data = v8_resource_cast<QQuickVisualDataModelItem>(info.This());
71 V8THROW_ERROR("Not a valid VisualData object");
73 return v8::Int32::New(data->index);
76 static v8::Local<v8::ObjectTemplate> createConstructor()
78 v8::Local<v8::ObjectTemplate> constructor = v8::ObjectTemplate::New();
79 constructor->SetHasExternalResource(true);
80 constructor->SetAccessor(v8::String::New("index"), get_index);
84 class VDMModelDelegateDataType;
86 class QQuickVDMCachedModelData : public QQuickVisualDataModelItem
89 QQuickVDMCachedModelData(
90 QQuickVisualDataModelItemMetaType *metaType,
91 VDMModelDelegateDataType *dataType,
94 int metaCall(QMetaObject::Call call, int id, void **arguments);
96 virtual QVariant value(int role) const = 0;
97 virtual void setValue(int role, const QVariant &value) = 0;
99 void setValue(const QString &role, const QVariant &value);
100 bool resolveIndex(const QQuickVisualAdaptorModel &model, int idx);
102 static v8::Handle<v8::Value> get_property(v8::Local<v8::String>, const v8::AccessorInfo &info);
103 static void set_property(
104 v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info);
106 VDMModelDelegateDataType *type;
107 QVector<QVariant> cachedData;
110 class VDMModelDelegateDataType
111 : public QQmlRefCount
112 , public QQuickVisualAdaptorModel::Accessors
113 , public QAbstractDynamicMetaObject
116 VDMModelDelegateDataType(QQuickVisualAdaptorModel *model)
122 , hasModelData(false)
126 ~VDMModelDelegateDataType()
129 propertyCache->release();
132 qPersistentDispose(constructor);
136 const QQuickVisualAdaptorModel &,
137 const QList<QQuickVisualDataModelItem *> &items,
140 const QList<int> &roles) const
142 bool changed = roles.isEmpty() && !watchedRoles.isEmpty();
143 if (!changed && !watchedRoles.isEmpty() && watchedRoleIds.isEmpty()) {
145 foreach (const QByteArray &r, watchedRoles) {
146 QHash<QByteArray, int>::const_iterator it = roleNames.find(r);
147 if (it != roleNames.end())
148 roleIds << it.value();
150 const_cast<VDMModelDelegateDataType *>(this)->watchedRoleIds = roleIds;
153 QVector<int> signalIndexes;
154 for (int i = 0; i < roles.count(); ++i) {
155 const int role = roles.at(i);
156 if (!changed && watchedRoleIds.contains(role))
159 int propertyId = propertyRoles.indexOf(role);
160 if (propertyId != -1)
161 signalIndexes.append(propertyId + signalOffset);
163 if (roles.isEmpty()) {
164 for (int propertyId = 0; propertyId < propertyRoles.count(); ++propertyId)
165 signalIndexes.append(propertyId + signalOffset);
168 for (int i = 0, c = items.count(); i < c; ++i) {
169 QQuickVisualDataModelItem *item = items.at(i);
170 const int idx = item->modelIndex();
171 if (idx >= index && idx < index + count) {
172 for (int i = 0; i < signalIndexes.count(); ++i)
173 QMetaObject::activate(item, signalIndexes.at(i), 0);
179 void replaceWatchedRoles(
180 QQuickVisualAdaptorModel &,
181 const QList<QByteArray> &oldRoles,
182 const QList<QByteArray> &newRoles) const
184 VDMModelDelegateDataType *dataType = const_cast<VDMModelDelegateDataType *>(this);
186 dataType->watchedRoleIds.clear();
187 foreach (const QByteArray &oldRole, oldRoles)
188 dataType->watchedRoles.removeOne(oldRole);
189 dataType->watchedRoles += newRoles;
192 void initializeConstructor()
194 constructor = qPersistentNew(createConstructor());
196 typedef QHash<QByteArray, int>::const_iterator iterator;
197 for (iterator it = roleNames.constBegin(), end = roleNames.constEnd(); it != end; ++it) {
198 const int propertyId = propertyRoles.indexOf(it.value());
199 const QByteArray &propertyName = it.key();
201 constructor->SetAccessor(
202 v8::String::New(propertyName.constData(), propertyName.length()),
203 QQuickVDMCachedModelData::get_property,
204 QQuickVDMCachedModelData::set_property,
205 v8::Int32::New(propertyId));
209 // QAbstractDynamicMetaObject
211 void objectDestroyed(QObject *)
216 int metaCall(QObject *object, QMetaObject::Call call, int id, void **arguments)
218 return static_cast<QQuickVDMCachedModelData *>(object)->metaCall(call, id, arguments);
221 v8::Persistent<v8::ObjectTemplate> constructor;
222 QList<int> propertyRoles;
223 QList<int> watchedRoleIds;
224 QList<QByteArray> watchedRoles;
225 QHash<QByteArray, int> roleNames;
226 QQuickVisualAdaptorModel *model;
227 QMetaObject *metaObject;
228 QQmlPropertyCache *propertyCache;
234 QQuickVDMCachedModelData::QQuickVDMCachedModelData(
235 QQuickVisualDataModelItemMetaType *metaType, VDMModelDelegateDataType *dataType, int index)
236 : QQuickVisualDataModelItem(metaType, index)
240 cachedData.resize(type->hasModelData ? 1 : type->propertyRoles.count());
242 QObjectPrivate::get(this)->metaObject = type;
246 QQmlData *qmldata = QQmlData::get(this, true);
247 qmldata->propertyCache = dataType->propertyCache;
248 qmldata->propertyCache->addref();
251 int QQuickVDMCachedModelData::metaCall(QMetaObject::Call call, int id, void **arguments)
253 if (call == QMetaObject::ReadProperty && id >= type->propertyOffset) {
254 const int propertyIndex = id - type->propertyOffset;
256 if (!cachedData.isEmpty()) {
257 *static_cast<QVariant *>(arguments[0]) = cachedData.at(
258 type->hasModelData ? 0 : propertyIndex);
260 } else if (*type->model) {
261 *static_cast<QVariant *>(arguments[0]) = value(type->propertyRoles.at(propertyIndex));
264 } else if (call == QMetaObject::WriteProperty && id >= type->propertyOffset) {
265 const int propertyIndex = id - type->propertyOffset;
267 const QMetaObject *meta = metaObject();
268 if (cachedData.count() > 1) {
269 cachedData[propertyIndex] = *static_cast<QVariant *>(arguments[0]);
270 QMetaObject::activate(this, meta, propertyIndex, 0);
271 } else if (cachedData.count() == 1) {
272 cachedData[0] = *static_cast<QVariant *>(arguments[0]);
273 QMetaObject::activate(this, meta, 0, 0);
274 QMetaObject::activate(this, meta, 1, 0);
276 } else if (*type->model) {
277 setValue(type->propertyRoles.at(propertyIndex), *static_cast<QVariant *>(arguments[0]));
281 return qt_metacall(call, id, arguments);
285 void QQuickVDMCachedModelData::setValue(const QString &role, const QVariant &value)
287 QHash<QByteArray, int>::iterator it = type->roleNames.find(role.toUtf8());
288 if (it != type->roleNames.end()) {
289 for (int i = 0; i < type->propertyRoles.count(); ++i) {
290 if (type->propertyRoles.at(i) == *it) {
291 cachedData[i] = value;
298 bool QQuickVDMCachedModelData::resolveIndex(const QQuickVisualAdaptorModel &, int idx)
304 emit modelIndexChanged();
305 const QMetaObject *meta = metaObject();
306 const int propertyCount = type->propertyRoles.count();
307 for (int i = 0; i < propertyCount; ++i)
308 QMetaObject::activate(this, meta, i, 0);
315 v8::Handle<v8::Value> QQuickVDMCachedModelData::get_property(
316 v8::Local<v8::String>, const v8::AccessorInfo &info)
318 QQuickVisualDataModelItem *data = v8_resource_cast<QQuickVisualDataModelItem>(info.This());
320 V8THROW_ERROR("Not a valid VisualData object");
322 QQuickVDMCachedModelData *modelData = static_cast<QQuickVDMCachedModelData *>(data);
323 const int propertyId = info.Data()->Int32Value();
324 if (data->index == -1) {
325 if (!modelData->cachedData.isEmpty()) {
326 return data->engine->fromVariant(
327 modelData->cachedData.at(modelData->type->hasModelData ? 0 : propertyId));
329 } else if (*modelData->type->model) {
330 return data->engine->fromVariant(
331 modelData->value(modelData->type->propertyRoles.at(propertyId)));
333 return v8::Undefined();
336 void QQuickVDMCachedModelData::set_property(
337 v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info)
339 QQuickVisualDataModelItem *data = v8_resource_cast<QQuickVisualDataModelItem>(info.This());
341 V8THROW_ERROR_SETTER("Not a valid VisualData object");
343 const int propertyId = info.Data()->Int32Value();
344 if (data->index == -1) {
345 QQuickVDMCachedModelData *modelData = static_cast<QQuickVDMCachedModelData *>(data);
346 if (!modelData->cachedData.isEmpty()) {
347 if (modelData->cachedData.count() > 1) {
348 modelData->cachedData[propertyId] = data->engine->toVariant(value, QVariant::Invalid);
349 QMetaObject::activate(data, data->metaObject(), propertyId, 0);
350 } else if (modelData->cachedData.count() == 1) {
351 modelData->cachedData[0] = data->engine->toVariant(value, QVariant::Invalid);
352 QMetaObject::activate(data, data->metaObject(), 0, 0);
353 QMetaObject::activate(data, data->metaObject(), 1, 0);
359 //-----------------------------------------------------------------
360 // QAbstractItemModel
361 //-----------------------------------------------------------------
363 class QQuickVDMAbstractItemModelData : public QQuickVDMCachedModelData
366 Q_PROPERTY(bool hasModelChildren READ hasModelChildren CONSTANT)
368 QQuickVDMAbstractItemModelData(
369 QQuickVisualDataModelItemMetaType *metaType,
370 VDMModelDelegateDataType *dataType,
372 : QQuickVDMCachedModelData(metaType, dataType, index)
376 bool hasModelChildren() const
378 if (index >= 0 && *type->model) {
379 const QAbstractItemModel * const model = type->model->aim();
380 return model->hasChildren(model->index(index, 0, type->model->rootIndex));
386 QVariant value(int role) const
388 return type->model->aim()->index(index, 0, type->model->rootIndex).data(role);
391 void setValue(int role, const QVariant &value)
393 type->model->aim()->setData(
394 type->model->aim()->index(index, 0, type->model->rootIndex), value, role);
397 v8::Handle<v8::Value> get()
399 if (type->constructor.IsEmpty()) {
400 v8::HandleScope handleScope;
401 v8::Context::Scope contextScope(engine->context());
402 type->initializeConstructor();
403 type->constructor->SetAccessor(v8::String::New("hasModelChildren"), get_hasModelChildren);
405 v8::Local<v8::Object> data = type->constructor->NewInstance();
406 data->SetExternalResource(this);
410 static v8::Handle<v8::Value> get_hasModelChildren(v8::Local<v8::String>, const v8::AccessorInfo &info)
412 QQuickVisualDataModelItem *data = v8_resource_cast<QQuickVisualDataModelItem>(info.This());
414 V8THROW_ERROR("Not a valid VisualData object");
416 const QQuickVisualAdaptorModel *const model = static_cast<QQuickVDMCachedModelData *>(data)->type->model;
417 if (data->index >= 0 && *model) {
418 const QAbstractItemModel * const aim = model->aim();
419 return v8::Boolean::New(aim->hasChildren(aim->index(data->index, 0, model->rootIndex)));
421 return v8::Boolean::New(false);
426 class VDMAbstractItemModelDataType : public VDMModelDelegateDataType
429 VDMAbstractItemModelDataType(QQuickVisualAdaptorModel *model)
430 : VDMModelDelegateDataType(model)
434 int count(const QQuickVisualAdaptorModel &model) const
436 return model.aim()->rowCount(model.rootIndex);
439 void cleanup(QQuickVisualAdaptorModel &model, QQuickVisualDataModel *vdm) const
441 QAbstractItemModel * const aim = model.aim();
443 QObject::disconnect(aim, SIGNAL(rowsInserted(QModelIndex,int,int)),
444 vdm, SLOT(_q_rowsInserted(QModelIndex,int,int)));
445 QObject::disconnect(aim, SIGNAL(rowsRemoved(QModelIndex,int,int)),
446 vdm, SLOT(_q_rowsRemoved(QModelIndex,int,int)));
447 QObject::disconnect(aim, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
448 vdm, SLOT(_q_dataChanged(QModelIndex,QModelIndex)));
449 QObject::disconnect(aim, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)),
450 vdm, SLOT(_q_rowsMoved(QModelIndex,int,int,QModelIndex,int)));
451 QObject::disconnect(aim, SIGNAL(modelReset()),
452 vdm, SLOT(_q_modelReset()));
453 QObject::disconnect(aim, SIGNAL(layoutChanged()),
454 vdm, SLOT(_q_layoutChanged()));
457 const_cast<VDMAbstractItemModelDataType *>(this)->release();
460 QString stringValue(const QQuickVisualAdaptorModel &model, int index, const QString &role) const
462 QHash<QByteArray, int>::const_iterator it = roleNames.find(role.toUtf8());
463 if (it != roleNames.end()) {
464 return model.aim()->index(index, 0, model.rootIndex).data(*it).toString();
465 } else if (role == QLatin1String("hasModelChildren")) {
466 return QVariant(model.aim()->hasChildren(model.aim()->index(index, 0, model.rootIndex))).toString();
472 QVariant parentModelIndex(const QQuickVisualAdaptorModel &model) const
475 ? QVariant::fromValue(model.aim()->parent(model.rootIndex))
479 QVariant modelIndex(const QQuickVisualAdaptorModel &model, int index) const
482 ? QVariant::fromValue(model.aim()->index(index, 0, model.rootIndex))
486 bool canFetchMore(const QQuickVisualAdaptorModel &model) const
488 return model && model.aim()->canFetchMore(model.rootIndex);
491 void fetchMore(QQuickVisualAdaptorModel &model) const
494 model.aim()->fetchMore(model.rootIndex);
497 QQuickVisualDataModelItem *createItem(
498 QQuickVisualAdaptorModel &model,
499 QQuickVisualDataModelItemMetaType *metaType,
503 VDMAbstractItemModelDataType *dataType = const_cast<VDMAbstractItemModelDataType *>(this);
505 dataType->initializeMetaType(model, engine);
506 return new QQuickVDMAbstractItemModelData(metaType, dataType, index);
509 void initializeMetaType(QQuickVisualAdaptorModel &model, QQmlEngine *engine)
511 QMetaObjectBuilder builder;
512 setModelDataType<QQuickVDMAbstractItemModelData>(&builder, this);
514 const QByteArray propertyType = QByteArrayLiteral("QVariant");
515 const QHash<int, QByteArray> names = model.aim()->roleNames();
516 for (QHash<int, QByteArray>::const_iterator it = names.begin(); it != names.end(); ++it) {
517 const int propertyId = propertyRoles.count();
518 propertyRoles.append(it.key());
519 roleNames.insert(it.value(), it.key());
520 addProperty(&builder, propertyId, it.value(), propertyType);
522 if (propertyRoles.count() == 1) {
524 const int role = names.begin().key();
525 const QByteArray propertyName = QByteArrayLiteral("modelData");
527 propertyRoles.append(role);
528 roleNames.insert(propertyName, role);
529 addProperty(&builder, 1, propertyName, propertyType);
532 metaObject = builder.toMetaObject();
533 *static_cast<QMetaObject *>(this) = *metaObject;
534 propertyCache = new QQmlPropertyCache(engine, metaObject);
538 //-----------------------------------------------------------------
539 // QListModelInterface
540 //-----------------------------------------------------------------
542 class QQuickVDMListModelInterfaceData : public QQuickVDMCachedModelData
545 QQuickVDMListModelInterfaceData(QQuickVisualDataModelItemMetaType *metaType, VDMModelDelegateDataType *dataType, int index)
546 : QQuickVDMCachedModelData(metaType, dataType, index)
550 QVariant value(int role) const
552 return type->model->lmi()->data(index, role);
555 void setValue(int, const QVariant &) {}
557 v8::Handle<v8::Value> get()
559 if (type->constructor.IsEmpty()) {
560 v8::HandleScope handleScope;
561 v8::Context::Scope contextScope(engine->context());
562 type->initializeConstructor();
564 v8::Local<v8::Object> data = type->constructor->NewInstance();
565 data->SetExternalResource(this);
570 class VDMListModelInterfaceDataType : public VDMModelDelegateDataType
573 VDMListModelInterfaceDataType(QQuickVisualAdaptorModel *model)
574 : VDMModelDelegateDataType(model)
578 int count(const QQuickVisualAdaptorModel &model) const
580 return model.lmi()->count();
583 void cleanup(QQuickVisualAdaptorModel &model, QQuickVisualDataModel *vdm) const
585 QListModelInterface *lmi = model.lmi();
587 QObject::disconnect(lmi, SIGNAL(itemsChanged(int,int,QList<int>)),
588 vdm, SLOT(_q_itemsChanged(int,int,QList<int>)));
589 QObject::disconnect(lmi, SIGNAL(itemsInserted(int,int)),
590 vdm, SLOT(_q_itemsInserted(int,int)));
591 QObject::disconnect(lmi, SIGNAL(itemsRemoved(int,int)),
592 vdm, SLOT(_q_itemsRemoved(int,int)));
593 QObject::disconnect(lmi, SIGNAL(itemsMoved(int,int,int)),
594 vdm, SLOT(_q_itemsMoved(int,int,int)));
596 const_cast<VDMListModelInterfaceDataType *>(this)->release();
599 QString stringValue(const QQuickVisualAdaptorModel &model, int index, const QString &role) const
601 QHash<QByteArray, int>::const_iterator it = roleNames.find(role.toUtf8());
602 return it != roleNames.end() && model
603 ? model.lmi()->data(index, *it).toString()
607 QQuickVisualDataModelItem *createItem(
608 QQuickVisualAdaptorModel &model,
609 QQuickVisualDataModelItemMetaType *metaType,
613 VDMListModelInterfaceDataType *dataType = const_cast<VDMListModelInterfaceDataType *>(this);
615 dataType->initializeMetaType(model, engine);
616 return new QQuickVDMListModelInterfaceData(metaType, dataType, index);
619 void initializeMetaType(QQuickVisualAdaptorModel &model, QQmlEngine *engine)
621 QMetaObjectBuilder builder;
622 setModelDataType<QQuickVDMListModelInterfaceData>(&builder, this);
624 const QByteArray propertyType = QByteArrayLiteral("QVariant");
626 const QListModelInterface * const listModelInterface = model.lmi();
627 const QList<int> roles = listModelInterface->roles();
628 for (int propertyId = 0; propertyId < roles.count(); ++propertyId) {
629 const int role = roles.at(propertyId);
630 const QString roleName = listModelInterface->toString(role);
631 const QByteArray propertyName = roleName.toUtf8();
633 propertyRoles.append(role);
634 roleNames.insert(propertyName, role);
635 addProperty(&builder, propertyId, propertyName, propertyType);
638 if (propertyRoles.count() == 1) {
640 const int role = roles.first();
641 const QByteArray propertyName = QByteArrayLiteral("modelData");
643 propertyRoles.append(role);
644 roleNames.insert(propertyName, role);
645 addProperty(&builder, 1, propertyName, propertyType);
648 metaObject = builder.toMetaObject();
649 *static_cast<QMetaObject *>(this) = *metaObject;
650 propertyCache = new QQmlPropertyCache(engine, metaObject);
654 //-----------------------------------------------------------------
655 // QQuickListAccessor
656 //-----------------------------------------------------------------
658 class QQuickVDMListAccessorData : public QQuickVisualDataModelItem
661 Q_PROPERTY(QVariant modelData READ modelData WRITE setModelData NOTIFY modelDataChanged)
663 QQuickVDMListAccessorData(QQuickVisualDataModelItemMetaType *metaType, int index, const QVariant &value)
664 : QQuickVisualDataModelItem(metaType, index)
669 QVariant modelData() const
674 void setModelData(const QVariant &data)
676 if (index == -1 && data != cachedData) {
678 emit modelDataChanged();
682 static v8::Handle<v8::Value> get_modelData(v8::Local<v8::String>, const v8::AccessorInfo &info)
684 QQuickVisualDataModelItem *data = v8_resource_cast<QQuickVisualDataModelItem>(info.This());
686 V8THROW_ERROR("Not a valid VisualData object");
688 return data->engine->fromVariant(static_cast<QQuickVDMListAccessorData *>(data)->cachedData);
691 static void set_modelData(v8::Local<v8::String>, const v8::Handle<v8::Value> &value, const v8::AccessorInfo &info)
693 QQuickVisualDataModelItem *data = v8_resource_cast<QQuickVisualDataModelItem>(info.This());
695 V8THROW_ERROR_SETTER("Not a valid VisualData object");
697 static_cast<QQuickVDMListAccessorData *>(data)->setModelData(
698 data->engine->toVariant(value, QVariant::Invalid));
701 void setValue(const QString &role, const QVariant &value)
703 if (role == QLatin1String("modelData"))
707 bool resolveIndex(const QQuickVisualAdaptorModel &model, int idx)
711 cachedData = model.list.at(idx);
712 emit modelIndexChanged();
713 emit modelDataChanged();
721 void modelDataChanged();
728 class VDMListDelegateDataType : public QQuickVisualAdaptorModel::Accessors
731 inline VDMListDelegateDataType() {}
733 int count(const QQuickVisualAdaptorModel &model) const
735 return model.list.count();
738 QString stringValue(const QQuickVisualAdaptorModel &model, int index, const QString &role) const
740 return role == QLatin1String("modelData")
741 ? model.list.at(index).toString()
745 QQuickVisualDataModelItem *createItem(
746 QQuickVisualAdaptorModel &model,
747 QQuickVisualDataModelItemMetaType *metaType,
751 return new QQuickVDMListAccessorData(
754 index >= 0 && index < model.list.count() ? model.list.at(index) : QVariant());
758 //-----------------------------------------------------------------
760 //-----------------------------------------------------------------
762 class VDMObjectDelegateDataType;
763 class QQuickVDMObjectData : public QQuickVisualDataModelItem, public QQuickVisualAdaptorModelProxyInterface
766 Q_PROPERTY(QObject *modelData READ modelData CONSTANT)
767 Q_INTERFACES(QQuickVisualAdaptorModelProxyInterface)
770 QQuickVisualDataModelItemMetaType *metaType,
771 VDMObjectDelegateDataType *dataType,
775 QObject *modelData() const { return object; }
776 QObject *proxiedObject() { return object; }
778 QQmlGuard<QObject> object;
781 class VDMObjectDelegateDataType : public QQmlRefCount, public QQuickVisualAdaptorModel::Accessors
784 QMetaObject *metaObject;
788 QMetaObjectBuilder builder;
790 VDMObjectDelegateDataType()
798 VDMObjectDelegateDataType(const VDMObjectDelegateDataType &type)
801 , propertyOffset(type.propertyOffset)
802 , signalOffset(type.signalOffset)
804 , builder(type.metaObject, QMetaObjectBuilder::Properties
805 | QMetaObjectBuilder::Signals
806 | QMetaObjectBuilder::SuperClass
807 | QMetaObjectBuilder::ClassName)
809 builder.setFlags(QMetaObjectBuilder::DynamicMetaObject);
812 ~VDMObjectDelegateDataType()
817 int count(const QQuickVisualAdaptorModel &model) const
819 return model.list.count();
822 QString stringValue(const QQuickVisualAdaptorModel &model, int index, const QString &role) const
824 if (QObject *object = model.list.at(index).value<QObject *>())
825 return object->property(role.toUtf8()).toString();
829 QQuickVisualDataModelItem *createItem(
830 QQuickVisualAdaptorModel &model,
831 QQuickVisualDataModelItemMetaType *metaType,
835 VDMObjectDelegateDataType *dataType = const_cast<VDMObjectDelegateDataType *>(this);
837 dataType->initializeMetaType(model);
838 return index >= 0 && index < model.list.count()
839 ? new QQuickVDMObjectData(metaType, dataType, index, qvariant_cast<QObject *>(model.list.at(index)))
843 void initializeMetaType(QQuickVisualAdaptorModel &)
845 setModelDataType<QQuickVDMObjectData>(&builder, this);
847 metaObject = builder.toMetaObject();
850 void cleanup(QQuickVisualAdaptorModel &, QQuickVisualDataModel *) const
852 const_cast<VDMObjectDelegateDataType *>(this)->release();
856 class QQuickVDMObjectDataMetaObject : public QAbstractDynamicMetaObject
859 QQuickVDMObjectDataMetaObject(QQuickVDMObjectData *data, VDMObjectDelegateDataType *type)
863 QObjectPrivate *op = QObjectPrivate::get(m_data);
864 *static_cast<QMetaObject *>(this) = *type->metaObject;
865 op->metaObject = this;
869 ~QQuickVDMObjectDataMetaObject()
874 int metaCall(QMetaObject::Call call, int id, void **arguments)
876 static const int objectPropertyOffset = QObject::staticMetaObject.propertyCount();
877 if (id >= m_type->propertyOffset
878 && (call == QMetaObject::ReadProperty
879 || call == QMetaObject::WriteProperty
880 || call == QMetaObject::ResetProperty)) {
882 QMetaObject::metacall(m_data->object, call, id - m_type->propertyOffset + objectPropertyOffset, arguments);
884 } else if (id >= m_type->signalOffset && call == QMetaObject::InvokeMetaMethod) {
885 QMetaObject::activate(m_data, this, id - m_type->signalOffset, 0);
888 return m_data->qt_metacall(call, id, arguments);
892 int createProperty(const char *name, const char *)
896 const QMetaObject *metaObject = m_data->object->metaObject();
897 static const int objectPropertyOffset = QObject::staticMetaObject.propertyCount();
899 const int previousPropertyCount = propertyCount() - propertyOffset();
900 int propertyIndex = metaObject->indexOfProperty(name);
901 if (propertyIndex == -1)
903 if (previousPropertyCount + objectPropertyOffset == metaObject->propertyCount())
904 return propertyIndex + m_type->propertyOffset - objectPropertyOffset;
906 if (m_type->shared) {
907 VDMObjectDelegateDataType *type = m_type;
908 m_type = new VDMObjectDelegateDataType(*m_type);
912 const int previousMethodCount = methodCount();
913 int notifierId = previousMethodCount - methodOffset();
914 for (int propertyId = previousPropertyCount; propertyId < metaObject->propertyCount() - objectPropertyOffset; ++propertyId) {
915 QMetaProperty property = metaObject->property(propertyId + objectPropertyOffset);
916 QMetaPropertyBuilder propertyBuilder;
917 if (property.hasNotifySignal()) {
918 m_type->builder.addSignal("__" + QByteArray::number(propertyId) + "()");
919 propertyBuilder = m_type->builder.addProperty(property.name(), property.typeName(), notifierId);
922 propertyBuilder = m_type->builder.addProperty(property.name(), property.typeName());
924 propertyBuilder.setWritable(property.isWritable());
925 propertyBuilder.setResettable(property.isResettable());
926 propertyBuilder.setConstant(property.isConstant());
929 if (m_type->metaObject)
930 free(m_type->metaObject);
931 m_type->metaObject = m_type->builder.toMetaObject();
932 *static_cast<QMetaObject *>(this) = *m_type->metaObject;
934 notifierId = previousMethodCount;
935 for (int i = previousPropertyCount; i < metaObject->propertyCount() - objectPropertyOffset; ++i) {
936 QMetaProperty property = metaObject->property(i + objectPropertyOffset);
937 if (property.hasNotifySignal()) {
938 QQmlPropertyPrivate::connect(
939 m_data->object, property.notifySignalIndex(), m_data, notifierId);
943 return propertyIndex + m_type->propertyOffset - objectPropertyOffset;
946 QQuickVDMObjectData *m_data;
947 VDMObjectDelegateDataType *m_type;
950 QQuickVDMObjectData::QQuickVDMObjectData(
951 QQuickVisualDataModelItemMetaType *metaType,
952 VDMObjectDelegateDataType *dataType,
955 : QQuickVisualDataModelItem(metaType, index)
958 new QQuickVDMObjectDataMetaObject(this, dataType);
961 //-----------------------------------------------------------------
962 // QQuickVisualAdaptorModel
963 //-----------------------------------------------------------------
965 static const QQuickVisualAdaptorModel::Accessors qt_vdm_null_accessors;
966 static const VDMListDelegateDataType qt_vdm_list_accessors;
968 QQuickVisualAdaptorModel::QQuickVisualAdaptorModel()
969 : accessors(&qt_vdm_null_accessors)
973 QQuickVisualAdaptorModel::~QQuickVisualAdaptorModel()
975 accessors->cleanup(*this);
978 void QQuickVisualAdaptorModel::setModel(const QVariant &variant, QQuickVisualDataModel *vdm, QQmlEngine *engine)
980 accessors->cleanup(*this, vdm);
982 list.setList(variant, engine);
984 if (QObject *object = qvariant_cast<QObject *>(variant)) {
986 if (QAbstractItemModel *model = qobject_cast<QAbstractItemModel *>(object)) {
987 accessors = new VDMAbstractItemModelDataType(this);
989 qmlobject_connect(model, QAbstractItemModel, SIGNAL(rowsInserted(QModelIndex,int,int)),
990 vdm, QQuickVisualDataModel, SLOT(_q_rowsInserted(QModelIndex,int,int)));
991 qmlobject_connect(model, QAbstractItemModel, SIGNAL(rowsRemoved(QModelIndex,int,int)),
992 vdm, QQuickVisualDataModel, SLOT(_q_rowsRemoved(QModelIndex,int,int)));
993 qmlobject_connect(model, QAbstractItemModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
994 vdm, QQuickVisualDataModel, SLOT(_q_dataChanged(QModelIndex,QModelIndex)));
995 qmlobject_connect(model, QAbstractItemModel, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)),
996 vdm, QQuickVisualDataModel, SLOT(_q_rowsMoved(QModelIndex,int,int,QModelIndex,int)));
997 qmlobject_connect(model, QAbstractItemModel, SIGNAL(modelReset()),
998 vdm, QQuickVisualDataModel, SLOT(_q_modelReset()));
999 qmlobject_connect(model, QAbstractItemModel, SIGNAL(layoutChanged()),
1000 vdm, QQuickVisualDataModel, SLOT(_q_layoutChanged()));
1001 } else if (QListModelInterface *model = qobject_cast<QListModelInterface *>(object)) {
1002 accessors = new VDMListModelInterfaceDataType(this);
1004 qmlobject_connect(model, QListModelInterface, SIGNAL(itemsChanged(int,int,QList<int>)),
1005 vdm, QQuickVisualDataModel, SLOT(_q_itemsChanged(int,int,QList<int>)));
1006 qmlobject_connect(model, QListModelInterface, SIGNAL(itemsInserted(int,int)),
1007 vdm, QQuickVisualDataModel, SLOT(_q_itemsInserted(int,int)));
1008 qmlobject_connect(model, QListModelInterface, SIGNAL(itemsRemoved(int,int)),
1009 vdm, QQuickVisualDataModel, SLOT(_q_itemsRemoved(int,int)));
1010 qmlobject_connect(model, QListModelInterface, SIGNAL(itemsMoved(int,int,int)),
1011 vdm, QQuickVisualDataModel, SLOT(_q_itemsMoved(int,int,int)));
1013 accessors = new VDMObjectDelegateDataType;
1015 } else if (list.type() == QQuickListAccessor::ListProperty) {
1016 setObject(static_cast<const QQmlListReference *>(variant.constData())->object());
1017 accessors = new VDMObjectDelegateDataType;
1018 } else if (list.type() != QQuickListAccessor::Invalid) {
1019 Q_ASSERT(list.type() != QQuickListAccessor::Instance); // Should have cast to QObject.
1021 accessors = &qt_vdm_list_accessors;
1024 accessors = &qt_vdm_null_accessors;
1028 void QQuickVisualAdaptorModel::objectDestroyed(QObject *)
1030 setModel(QVariant(), 0, 0);
1035 QML_DECLARE_TYPE(QListModelInterface)
1037 #include <qquickvisualadaptormodel.moc>