X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fquick%2Fitems%2Fqquickvisualadaptormodel.cpp;h=f504478a3d7fe47ba4cfc03756e509f1048f0a03;hb=45b14259fc0cf704692df1c00da511527d1fba1d;hp=25baee6e29de83ab91293e72c8abb58533014a3e;hpb=6c8378eaf1edbbefe6aaa3672b0127816a004fd7;p=profile%2Fivi%2Fqtdeclarative.git diff --git a/src/quick/items/qquickvisualadaptormodel.cpp b/src/quick/items/qquickvisualadaptormodel.cpp index 25baee6..f504478 100644 --- a/src/quick/items/qquickvisualadaptormodel.cpp +++ b/src/quick/items/qquickvisualadaptormodel.cpp @@ -1,8 +1,7 @@ /**************************************************************************** ** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ ** ** This file is part of the QtDeclarative module of the Qt Toolkit. ** @@ -35,37 +34,22 @@ ** ** ** +** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qquickvisualadaptormodel_p.h" -#include "qquickitem.h" - -#include -#include -#include -#include +#include "qquickvisualdatamodel_p_p.h" -#include -#include -#include +#include #include -#include #include -#include -#include #include #include -#include #include #include -#include -#include - -Q_DECLARE_METATYPE(QModelIndex) - QT_BEGIN_NAMESPACE class VDMDelegateDataType : public QDeclarativeRefCount @@ -98,7 +82,7 @@ public: { if (propertyCache) propertyCache->release(); - qFree(metaObject); + free(metaObject); } QMetaObject *metaObject; @@ -109,29 +93,9 @@ public: QMetaObjectBuilder builder; }; -class QQuickVisualAdaptorModelData : public QObject -{ - Q_OBJECT - Q_PROPERTY(int index READ index NOTIFY indexChanged) -public: - QQuickVisualAdaptorModelData(int index, QQuickVisualAdaptorModel *model); - ~QQuickVisualAdaptorModelData(); - - int index() const; - void setIndex(int index); - -Q_SIGNALS: - void indexChanged(); - -public: - int m_index; - QDeclarativeGuard m_model; - QIntrusiveListNode m_cacheNode; -}; - -typedef QIntrusiveList QQuickVisualAdaptorModelDataCache; +typedef QIntrusiveList QQuickVisualDataModelItemCache; -class QQuickVisualAdaptorModelDataMetaObject; +class QQuickVisualDataModelItemMetaObject; class QQuickVisualAdaptorModelPrivate : public QObjectPrivate { Q_DECLARE_PUBLIC(QQuickVisualAdaptorModel) @@ -140,13 +104,19 @@ public: : m_engine(0) , m_listAccessor(0) , m_delegateDataType(0) - , createModelData(&initializeModelData) + , createItem(&initializeModelData) + , stringValue(&initializeStringValue) , m_ref(0) , m_count(0) + , m_roleCount(0) , m_objectList(false) { } + ~QQuickVisualAdaptorModelPrivate() + { + qPersistentDispose(m_constructor); + } static QQuickVisualAdaptorModelPrivate *get(QQuickVisualAdaptorModel *m) { return static_cast(QObjectPrivate::get(m)); @@ -155,20 +125,31 @@ public: void addProperty(int role, int propertyId, const char *propertyName, const char *propertyType, bool isModelData = false); template void setModelDataType() { - createModelData = &T::create; + createItem = &T::create; + stringValue = &T::stringValue; m_delegateDataType->builder.setFlags(QMetaObjectBuilder::DynamicMetaObject); m_delegateDataType->builder.setClassName(T::staticMetaObject.className()); m_delegateDataType->builder.setSuperClass(&T::staticMetaObject); m_delegateDataType->propertyOffset = T::staticMetaObject.propertyCount(); m_delegateDataType->signalOffset = T::staticMetaObject.methodCount(); } - QQuickVisualAdaptorModelData *createMetaObject(int index, QQuickVisualAdaptorModel *model); - static QQuickVisualAdaptorModelData *initializeModelData(int index, QQuickVisualAdaptorModel *model) { - return get(model)->createMetaObject(index, model); + void createMetaObject(); + + static QQuickVisualDataModelItem *initializeModelData( + QQuickVisualDataModelItemMetaType *metaType, QQuickVisualAdaptorModel *model, int index) { + QQuickVisualAdaptorModelPrivate *d = get(model); + d->createMetaObject(); + return d->createItem(metaType, model, index); } - typedef QQuickVisualAdaptorModelData *(*CreateModelData)(int index, QQuickVisualAdaptorModel *model); + static QString initializeStringValue(QQuickVisualAdaptorModelPrivate *model, int index, const QString &name) { + model->createMetaObject(); + return model->stringValue(model, index, name); + } + + typedef QQuickVisualDataModelItem *(*CreateModelData)(QQuickVisualDataModelItemMetaType *metaType, QQuickVisualAdaptorModel *model, int index); + typedef QString (*StringValue)(QQuickVisualAdaptorModelPrivate *model, int index, const QString &name); struct PropertyData { int role; @@ -190,10 +171,13 @@ public: QDeclarativeGuard m_abstractItemModel; QDeclarativeListAccessor *m_listAccessor; VDMDelegateDataType *m_delegateDataType; - CreateModelData createModelData; + CreateModelData createItem; + StringValue stringValue; + v8::Persistent m_constructor; int m_ref; int m_count; + int m_roleCount; QQuickVisualAdaptorModel::Flags m_flags; bool m_objectList : 1; @@ -205,13 +189,116 @@ public: QList watchedRoles; QHash m_roleNames; QVector m_propertyData; - QQuickVisualAdaptorModelDataCache m_cache; + QQuickVisualDataModelItemCache m_cache; }; -class QQuickVisualAdaptorModelDataMetaObject : public QAbstractDynamicMetaObject +class QQuickVDMCachedModelData : public QQuickVisualDataModelItem { public: - QQuickVisualAdaptorModelDataMetaObject(QQuickVisualAdaptorModelData *data, VDMDelegateDataType *type) + virtual QVariant value(QQuickVisualAdaptorModelPrivate *model, int role) const = 0; + virtual void setValue(QQuickVisualAdaptorModelPrivate *model, int role, const QVariant &value) = 0; + + void setValue(const QString &role, const QVariant &value) + { + QQuickVisualAdaptorModelPrivate *d = QQuickVisualAdaptorModelPrivate::get(model); + QHash::iterator it = d->m_roleNames.find(role.toUtf8()); + if (it != d->m_roleNames.end()) { + for (int i = 0; i < d->m_propertyData.count(); ++i) { + if (d->m_propertyData.at(i).role == *it) { + cachedData[i] = value; + return; + } + } + } + } + + bool resolveIndex(int idx) + { + if (index[0] == -1) { + Q_ASSERT(idx >= 0); + QQuickVisualAdaptorModelPrivate *d = QQuickVisualAdaptorModelPrivate::get(model); + index[0] = idx; + cachedData.clear(); + emit modelIndexChanged(); + const QMetaObject *meta = metaObject(); + const int propertyCount = d->m_propertyData.count(); + for (int i = 0; i < propertyCount; ++i) + QMetaObject::activate(this, meta, i, 0); + return true; + } else { + return false; + } + } + + static v8::Handle get_property(v8::Local, const v8::AccessorInfo &info) + { + QQuickVisualDataModelItem *data = v8_resource_cast(info.This()); + if (!data) + V8THROW_ERROR("Not a valid VisualData object"); + + QQuickVisualAdaptorModelPrivate *model = QQuickVisualAdaptorModelPrivate::get(data->model); + QQuickVDMCachedModelData *modelData = static_cast(data); + const int propertyId = info.Data()->Int32Value(); + if (data->index[0] == -1) { + if (!modelData->cachedData.isEmpty()) { + return data->engine->fromVariant( + modelData->cachedData.at(modelData->cachedData.count() > 1 ? propertyId : 0)); + } + } else { + return data->engine->fromVariant( + modelData->value(model, model->m_propertyData.at(propertyId).role)); + } + return v8::Undefined(); + } + + static void set_property( + v8::Local, v8::Local value, const v8::AccessorInfo &info) + { + QQuickVisualDataModelItem *data = v8_resource_cast(info.This()); + if (!data) + V8THROW_ERROR_SETTER("Not a valid VisualData object"); + + const int propertyId = info.Data()->Int32Value(); + if (data->index[0] == -1) { + QQuickVDMCachedModelData *modelData = static_cast(data); + if (!modelData->cachedData.isEmpty()) { + if (modelData->cachedData.count() > 1) { + modelData->cachedData[propertyId] = data->engine->toVariant(value, QVariant::Invalid); + QMetaObject::activate(data, data->metaObject(), propertyId, 0); + } else if (modelData->cachedData.count() == 1) { + modelData->cachedData[0] = data->engine->toVariant(value, QVariant::Invalid); + QMetaObject::activate(data, data->metaObject(), 0, 0); + QMetaObject::activate(data, data->metaObject(), 1, 0); + } + } + } + } + + v8::Handle get() + { + QQuickVisualAdaptorModelPrivate *d = QQuickVisualAdaptorModelPrivate::get(model); + + v8::Local data = d->m_constructor->NewInstance(); + data->SetExternalResource(this); + return data; + } + + + QQuickVDMCachedModelData( + QQuickVisualDataModelItemMetaType *metaType, QQuickVisualAdaptorModel *model, int index) + : QQuickVisualDataModelItem(metaType, model, index) + { + if (index == -1) + cachedData.resize(QQuickVisualAdaptorModelPrivate::get(model)->m_roleCount); + } + + QVector cachedData; +}; + +class QQuickVisualDataModelItemMetaObject : public QAbstractDynamicMetaObject +{ +public: + QQuickVisualDataModelItemMetaObject(QQuickVisualDataModelItem *data, VDMDelegateDataType *type) : m_data(data) , m_type(type) { @@ -221,26 +308,63 @@ public: m_type->addref(); } - ~QQuickVisualAdaptorModelDataMetaObject() { m_type->release(); } + ~QQuickVisualDataModelItemMetaObject() { m_type->release(); } + + static v8::Handle get_index(v8::Local, const v8::AccessorInfo &info) + { + QQuickVisualDataModelItem *data = v8_resource_cast(info.This()); + if (!data) + V8THROW_ERROR("Not a valid VisualData object"); + + return v8::Int32::New(data->index[0]); + } - QQuickVisualAdaptorModelData *m_data; + QQuickVisualDataModelItem *m_data; VDMDelegateDataType *m_type; }; -class QQuickVDMAbstractItemModelDataMetaObject : public QQuickVisualAdaptorModelDataMetaObject +class QQuickVDMCachedModelDataMetaObject : public QQuickVisualDataModelItemMetaObject { public: - QQuickVDMAbstractItemModelDataMetaObject(QQuickVisualAdaptorModelData *object, VDMDelegateDataType *type) - : QQuickVisualAdaptorModelDataMetaObject(object, type) {} + QQuickVDMCachedModelDataMetaObject(QQuickVisualDataModelItem *object, VDMDelegateDataType *type) + : QQuickVisualDataModelItemMetaObject(object, type) {} int metaCall(QMetaObject::Call call, int id, void **arguments) { if (call == QMetaObject::ReadProperty && id >= m_type->propertyOffset) { - QQuickVisualAdaptorModelPrivate *model = QQuickVisualAdaptorModelPrivate::get(m_data->m_model); - if (m_data->m_index == -1 || !model->m_abstractItemModel) - return -1; - *static_cast(arguments[0]) = model->m_abstractItemModel->index( - m_data->m_index, 0, model->m_root).data(model->m_propertyData.at(id - m_type->propertyOffset).role); + QQuickVisualAdaptorModelPrivate *model = QQuickVisualAdaptorModelPrivate::get(m_data->model); + const int propertyIndex = id - m_type->propertyOffset; + if (m_data->index[0] == -1) { + QQuickVDMCachedModelData *data = static_cast(m_data); + if (!data->cachedData.isEmpty()) { + *static_cast(arguments[0]) = data->cachedData.count() > 1 + ? data->cachedData.at(propertyIndex) + : data->cachedData.at(0); + } + } else { + *static_cast(arguments[0]) = static_cast( + m_data)->value(model, model->m_propertyData.at(propertyIndex).role); + } + return -1; + } else if (call == QMetaObject::WriteProperty && id >= m_type->propertyOffset) { + QQuickVisualAdaptorModelPrivate *model = QQuickVisualAdaptorModelPrivate::get(m_data->model); + const int propertyIndex = id - m_type->propertyOffset; + if (m_data->index[0] == -1) { + QQuickVDMCachedModelData *data = static_cast(m_data); + if (data->cachedData.count() > 1) { + data->cachedData[propertyIndex] = *static_cast(arguments[0]); + activate(data, this, propertyIndex, 0); + } else if (data->cachedData.count() == 1) { + data->cachedData[0] = *static_cast(arguments[0]); + activate(data, this, 0, 0); + activate(data, this, 1, 0); + } + } else { + static_cast(m_data)->setValue( + model, + model->m_propertyData.at(propertyIndex).role, + *static_cast(arguments[0])); + } return -1; } else { return m_data->qt_metacall(call, id, arguments); @@ -248,96 +372,229 @@ public: } }; -class QQuickVDMAbstractItemModelData : public QQuickVisualAdaptorModelData +class QQuickVDMAbstractItemModelData : public QQuickVDMCachedModelData { Q_OBJECT Q_PROPERTY(bool hasModelChildren READ hasModelChildren CONSTANT) public: bool hasModelChildren() const { - QQuickVisualAdaptorModelPrivate *model = QQuickVisualAdaptorModelPrivate::get(m_model); - return model->m_abstractItemModel->hasChildren(model->m_abstractItemModel->index(m_index, 0, model->m_root)); + QQuickVisualAdaptorModelPrivate *d = QQuickVisualAdaptorModelPrivate::get(model); + return d->m_abstractItemModel->hasChildren(d->m_abstractItemModel->index(index[0], 0, d->m_root)); + } + + static QQuickVisualDataModelItem *create( + QQuickVisualDataModelItemMetaType *metaType, QQuickVisualAdaptorModel *model, int index) { + return new QQuickVDMAbstractItemModelData(metaType, model, index); } + + static QString stringValue(QQuickVisualAdaptorModelPrivate *model, int index, const QString &role) + { + QHash::const_iterator it = model->m_roleNames.find(role.toUtf8()); + if (it != model->m_roleNames.end()) { + return model->m_abstractItemModel->index(index, 0, model->m_root).data(*it).toString(); + } else if (role == QLatin1String("hasModelChildren")) { + return QVariant(model->m_abstractItemModel->hasChildren( + model->m_abstractItemModel->index(index, 0, model->m_root))).toString(); + } else { + return QString(); + } + } + + QVariant value(QQuickVisualAdaptorModelPrivate *model, int role) const + { + return model->m_abstractItemModel + ? model->m_abstractItemModel->index(index[0], 0, model->m_root).data(role) + : 0; + } + + void setValue(QQuickVisualAdaptorModelPrivate *model, int role, const QVariant &value) + { + model->m_abstractItemModel->setData( + model->m_abstractItemModel->index(index[0], 0, model->m_root), value, role); + } + + static v8::Handle get_hasModelChildren(v8::Local, const v8::AccessorInfo &info) + { + QQuickVisualDataModelItem *data = v8_resource_cast(info.This()); + if (!data) + V8THROW_ERROR("Not a valid VisualData object"); + + QQuickVisualAdaptorModelPrivate *model = QQuickVisualAdaptorModelPrivate::get(data->model); + + return v8::Boolean::New(model->m_abstractItemModel->hasChildren( + model->m_abstractItemModel->index(data->index[0], 0, model->m_root))); } - static QQuickVisualAdaptorModelData *create(int index, QQuickVisualAdaptorModel *model) { - return new QQuickVDMAbstractItemModelData(index, model); } private: - QQuickVDMAbstractItemModelData(int index, QQuickVisualAdaptorModel *model) - : QQuickVisualAdaptorModelData(index, model) + QQuickVDMAbstractItemModelData( + QQuickVisualDataModelItemMetaType *metaType, QQuickVisualAdaptorModel *model, int index) + : QQuickVDMCachedModelData(metaType, model, index) { - new QQuickVDMAbstractItemModelDataMetaObject( - this, QQuickVisualAdaptorModelPrivate::get(m_model)->m_delegateDataType); + new QQuickVDMCachedModelDataMetaObject( + this, QQuickVisualAdaptorModelPrivate::get(model)->m_delegateDataType); } }; -class QQuickVDMListModelInterfaceDataMetaObject : public QQuickVisualAdaptorModelDataMetaObject +class QQuickVDMListModelInterfaceDataMetaObject : public QQuickVisualDataModelItemMetaObject { public: - QQuickVDMListModelInterfaceDataMetaObject(QQuickVisualAdaptorModelData *object, VDMDelegateDataType *type) - : QQuickVisualAdaptorModelDataMetaObject(object, type) {} + QQuickVDMListModelInterfaceDataMetaObject(QQuickVisualDataModelItem *object, VDMDelegateDataType *type) + : QQuickVisualDataModelItemMetaObject(object, type) {} int metaCall(QMetaObject::Call call, int id, void **arguments) { if (call == QMetaObject::ReadProperty && id >= m_type->propertyOffset) { - QQuickVisualAdaptorModelPrivate *model = QQuickVisualAdaptorModelPrivate::get(m_data->m_model); - if (m_data->m_index == -1 || !model->m_listModelInterface) + QQuickVisualAdaptorModelPrivate *model = QQuickVisualAdaptorModelPrivate::get(m_data->model); + if (m_data->index[0] == -1 || !model->m_listModelInterface) return -1; *static_cast(arguments[0]) = model->m_listModelInterface->data( - m_data->m_index, model->m_propertyData.at(id - m_type->propertyOffset).role); + m_data->index[0], model->m_propertyData.at(id - m_type->propertyOffset).role); return -1; } else { return m_data->qt_metacall(call, id, arguments); } } + }; -class QQuickVDMListModelInterfaceData : public QQuickVisualAdaptorModelData +class QQuickVDMListModelInterfaceData : public QQuickVDMCachedModelData { public: - static QQuickVisualAdaptorModelData *create(int index, QQuickVisualAdaptorModel *model) { - return new QQuickVDMListModelInterfaceData(index, model); } + static QQuickVisualDataModelItem *create( + QQuickVisualDataModelItemMetaType *metaType, QQuickVisualAdaptorModel *model, int index) { + return new QQuickVDMListModelInterfaceData(metaType, model, index); } + + static QString stringValue(QQuickVisualAdaptorModelPrivate *model, int index, const QString &role) + { + QHash::const_iterator it = model->m_roleNames.find(role.toUtf8()); + return it != model->m_roleNames.end() + ? model->m_listModelInterface->data(index, *it).toString() + : QString(); + } + + QVariant value(QQuickVisualAdaptorModelPrivate *model, int role) const + { + return model->m_listModelInterface + ? model->m_listModelInterface->data(index[0], role) + : 0; + } + + void setValue(QQuickVisualAdaptorModelPrivate *, int, const QVariant &) {} + private: - QQuickVDMListModelInterfaceData(int index, QQuickVisualAdaptorModel *model) - : QQuickVisualAdaptorModelData(index, model) + QQuickVDMListModelInterfaceData(QQuickVisualDataModelItemMetaType *metaType, QQuickVisualAdaptorModel *model, int index) + : QQuickVDMCachedModelData(metaType, model, index) { - new QQuickVDMListModelInterfaceDataMetaObject( - this, QQuickVisualAdaptorModelPrivate::get(m_model)->m_delegateDataType); + new QQuickVDMCachedModelDataMetaObject( + this, QQuickVisualAdaptorModelPrivate::get(model)->m_delegateDataType); } }; -class QQuickVDMListAccessorData : public QQuickVisualAdaptorModelData +class QQuickVDMListAccessorData : public QQuickVisualDataModelItem { Q_OBJECT - Q_PROPERTY(QVariant modelData READ modelData CONSTANT) + Q_PROPERTY(QVariant modelData READ modelData WRITE setModelData NOTIFY modelDataChanged) public: - QVariant modelData() const { - return QQuickVisualAdaptorModelPrivate::get(m_model)->m_listAccessor->at(m_index); } + QVariant modelData() const + { + QQuickVisualAdaptorModelPrivate *d = QQuickVisualAdaptorModelPrivate::get(model); + return index[0] != -1 && d->m_listAccessor + ? d->m_listAccessor->at(index[0]) + : cachedData; + } + + void setModelData(const QVariant &data) + { + if (index[0] == -1 && data != cachedData) { + cachedData = data; + emit modelDataChanged(); + } + } + + static QQuickVisualDataModelItem *create( + QQuickVisualDataModelItemMetaType *metaType, QQuickVisualAdaptorModel *model, int index) { + return new QQuickVDMListAccessorData(metaType, model, index); } + + static QString stringValue(QQuickVisualAdaptorModelPrivate *model, int index, const QString &role) + { + return role == QLatin1String("modelData") + ? model->m_listAccessor->at(index).toString() + : QString(); + } + + static v8::Handle get_modelData(v8::Local, const v8::AccessorInfo &info) + { + QQuickVisualDataModelItem *data = v8_resource_cast(info.This()); + if (!data) + V8THROW_ERROR("Not a valid VisualData object"); + + QQuickVisualAdaptorModelPrivate *d = QQuickVisualAdaptorModelPrivate::get(data->model); + if (data->index[0] == -1 || !d->m_listAccessor) + return data->engine->fromVariant(static_cast(data)->cachedData); + + return data->engine->fromVariant(d->m_listAccessor->at(data->index[0])); + } + + static void set_modelData(v8::Local, const v8::Handle &value, const v8::AccessorInfo &info) + { + QQuickVisualDataModelItem *data = v8_resource_cast(info.This()); + if (!data) + V8THROW_ERROR_SETTER("Not a valid VisualData object"); + + if (data->index[0] == -1) { + static_cast(data)->setModelData( + data->engine->toVariant(value, QVariant::Invalid)); + } + } + + void setValue(const QString &role, const QVariant &value) + { + if (role == QLatin1String("modelData")) + cachedData = value; + } + + bool resolveIndex(int idx) + { + if (index[0] == -1) { + index[0] = idx; + cachedData.clear(); + emit modelIndexChanged(); + emit modelDataChanged(); + return true; + } else { + return false; + } + } + +Q_SIGNALS: + void modelDataChanged(); - static QQuickVisualAdaptorModelData *create(int index, QQuickVisualAdaptorModel *model) { - return new QQuickVDMListAccessorData(index, model); } private: - QQuickVDMListAccessorData(int index, QQuickVisualAdaptorModel *model) - : QQuickVisualAdaptorModelData(index, model) + QQuickVDMListAccessorData(QQuickVisualDataModelItemMetaType *metaType, QQuickVisualAdaptorModel *model, int index) + : QQuickVisualDataModelItem(metaType, model, index) { } + + QVariant cachedData; }; -class QQuickVDMObjectDataMetaObject : public QQuickVisualAdaptorModelDataMetaObject +class QQuickVDMObjectDataMetaObject : public QQuickVisualDataModelItemMetaObject { public: - QQuickVDMObjectDataMetaObject(QQuickVisualAdaptorModelData *data, VDMDelegateDataType *type) - : QQuickVisualAdaptorModelDataMetaObject(data, type) - , m_object(QQuickVisualAdaptorModelPrivate::get(data->m_model)->m_listAccessor->at(data->m_index).value()) + QQuickVDMObjectDataMetaObject(QQuickVisualDataModelItem *data, VDMDelegateDataType *type) + : QQuickVisualDataModelItemMetaObject(data, type) + , m_object(QQuickVisualAdaptorModelPrivate::get(data->model)->m_listAccessor->at(data->index[0]).value()) {} int metaCall(QMetaObject::Call call, int id, void **arguments) { + static const int objectPropertyOffset = QObject::staticMetaObject.propertyCount(); if (id >= m_type->propertyOffset && (call == QMetaObject::ReadProperty || call == QMetaObject::WriteProperty || call == QMetaObject::ResetProperty)) { if (m_object) - QMetaObject::metacall(m_object, call, id - m_type->propertyOffset + 1, arguments); + QMetaObject::metacall(m_object, call, id - m_type->propertyOffset + objectPropertyOffset, arguments); return -1; } else if (id >= m_type->signalOffset && call == QMetaObject::InvokeMetaMethod) { QMetaObject::activate(m_data, this, id, 0); @@ -352,13 +609,14 @@ public: if (!m_object) return -1; const QMetaObject *metaObject = m_object->metaObject(); + static const int objectPropertyOffset = QObject::staticMetaObject.propertyCount(); const int previousPropertyCount = propertyCount() - propertyOffset(); int propertyIndex = metaObject->indexOfProperty(name); if (propertyIndex == -1) return -1; - if (previousPropertyCount + 1 == metaObject->propertyCount()) - return propertyIndex + m_type->propertyOffset - 1; + if (previousPropertyCount + objectPropertyOffset == metaObject->propertyCount()) + return propertyIndex + m_type->propertyOffset - objectPropertyOffset; if (m_type->shared) { VDMDelegateDataType *type = m_type; @@ -368,8 +626,8 @@ public: const int previousMethodCount = methodCount(); int notifierId = previousMethodCount; - for (int propertyId = previousPropertyCount; propertyId < metaObject->propertyCount() - 1; ++propertyId) { - QMetaProperty property = metaObject->property(propertyId + 1); + for (int propertyId = previousPropertyCount; propertyId < metaObject->propertyCount() - objectPropertyOffset; ++propertyId) { + QMetaProperty property = metaObject->property(propertyId + objectPropertyOffset); QMetaPropertyBuilder propertyBuilder; if (property.hasNotifySignal()) { m_type->builder.addSignal("__" + QByteArray::number(propertyId) + "()"); @@ -384,26 +642,26 @@ public: } if (m_type->metaObject) - qFree(m_type->metaObject); + free(m_type->metaObject); m_type->metaObject = m_type->builder.toMetaObject(); *static_cast(this) = *m_type->metaObject; notifierId = previousMethodCount; - for (int i = previousPropertyCount; i < metaObject->propertyCount(); ++i) { - QMetaProperty property = metaObject->property(i); + for (int i = previousPropertyCount; i < metaObject->propertyCount() - objectPropertyOffset; ++i) { + QMetaProperty property = metaObject->property(i + objectPropertyOffset); if (property.hasNotifySignal()) { QDeclarativePropertyPrivate::connect( m_object, property.notifySignalIndex(), m_data, notifierId); ++notifierId; } } - return propertyIndex + m_type->propertyOffset - 1; + return propertyIndex + m_type->propertyOffset - objectPropertyOffset; } QDeclarativeGuard m_object; }; -class QQuickVDMObjectData : public QQuickVisualAdaptorModelData, public QQuickVisualAdaptorModelProxyInterface +class QQuickVDMObjectData : public QQuickVisualDataModelItem, public QQuickVisualAdaptorModelProxyInterface { Q_OBJECT Q_PROPERTY(QObject *modelData READ modelData CONSTANT) @@ -412,13 +670,21 @@ public: QObject *modelData() const { return m_metaObject->m_object; } QObject *proxiedObject() { return m_metaObject->m_object; } - static QQuickVisualAdaptorModelData *create(int index, QQuickVisualAdaptorModel *model) { - return new QQuickVDMObjectData(index, model); } + static QQuickVisualDataModelItem *create( + QQuickVisualDataModelItemMetaType *metaType, QQuickVisualAdaptorModel *model, int index) { + return index >= 0 ? new QQuickVDMObjectData(metaType, model, index) : 0; } + + static QString stringValue(QQuickVisualAdaptorModelPrivate *model, int index, const QString &name) + { + if (QObject *object = model->m_listAccessor->at(index).value()) + return object->property(name.toUtf8()).toString(); + return QString(); + } private: - QQuickVDMObjectData(int index, QQuickVisualAdaptorModel *model) - : QQuickVisualAdaptorModelData(index, model) - , m_metaObject(new QQuickVDMObjectDataMetaObject(this, QQuickVisualAdaptorModelPrivate::get(m_model)->m_delegateDataType)) + QQuickVDMObjectData(QQuickVisualDataModelItemMetaType *metaType, QQuickVisualAdaptorModel *model, int index) + : QQuickVisualDataModelItem(metaType, model, index) + , m_metaObject(new QQuickVDMObjectDataMetaObject(this, QQuickVisualAdaptorModelPrivate::get(model)->m_delegateDataType)) { } @@ -434,23 +700,36 @@ void QQuickVisualAdaptorModelPrivate::addProperty( m_delegateDataType->builder.addSignal("__" + QByteArray::number(propertyId) + "()"); QMetaPropertyBuilder property = m_delegateDataType->builder.addProperty( propertyName, propertyType, propertyId); - property.setWritable(false); + property.setWritable(true); // No, yes, yes no? m_propertyData.append(propertyData); } -QQuickVisualAdaptorModelData *QQuickVisualAdaptorModelPrivate::createMetaObject(int index, QQuickVisualAdaptorModel *model) +void QQuickVisualAdaptorModelPrivate::createMetaObject() { Q_ASSERT(!m_delegateDataType); m_objectList = false; m_propertyData.clear(); + + QV8Engine *v8Engine = QDeclarativeEnginePrivate::getV8Engine(m_engine); + + v8::HandleScope handleScope; + v8::Context::Scope contextScope(v8Engine->context()); + v8::Local ft = v8::FunctionTemplate::New(); + ft->InstanceTemplate()->SetHasExternalResource(true); + ft->PrototypeTemplate()->SetAccessor( + v8::String::New("index"), QQuickVisualDataModelItemMetaObject::get_index); + if (m_listAccessor && m_listAccessor->type() != QDeclarativeListAccessor::ListProperty && m_listAccessor->type() != QDeclarativeListAccessor::Instance) { - createModelData = &QQuickVDMListAccessorData::create; - m_flags = QQuickVisualAdaptorModel::MetaObjectCacheable; - return QQuickVDMListAccessorData::create(index, model); + createItem = &QQuickVDMListAccessorData::create; + stringValue = &QQuickVDMListAccessorData::stringValue; + ft->PrototypeTemplate()->SetAccessor( + v8::String::New("modelData"), QQuickVDMListAccessorData::get_modelData); + m_constructor = qPersistentNew(ft->GetFunction()); + return; } m_delegateDataType = new VDMDelegateDataType; @@ -459,59 +738,66 @@ QQuickVisualAdaptorModelData *QQuickVisualAdaptorModelPrivate::createMetaObject( QList roles = m_listModelInterface->roles(); for (int propertyId = 0; propertyId < roles.count(); ++propertyId) { const int role = roles.at(propertyId); - const QByteArray propertyName = m_listModelInterface->toString(role).toUtf8(); + const QString roleName = m_listModelInterface->toString(role); + const QByteArray propertyName = roleName.toUtf8(); addProperty(role, propertyId, propertyName, "QVariant"); + ft->PrototypeTemplate()->SetAccessor( + v8Engine->toString(roleName), + QQuickVDMListModelInterfaceData::get_property, + QQuickVDMListModelInterfaceData::set_property, + v8::Int32::New(propertyId)); m_roleNames.insert(propertyName, role); } - if (m_propertyData.count() == 1) + m_roleCount = m_propertyData.count(); + if (m_propertyData.count() == 1) { addProperty(roles.first(), 1, "modelData", "QVariant", true); - m_flags = QQuickVisualAdaptorModel::MetaObjectCacheable; + ft->PrototypeTemplate()->SetAccessor( + v8::String::New("modelData"), + QQuickVDMListModelInterfaceData::get_property, + QQuickVDMListModelInterfaceData::set_property, + v8::Int32::New(0)); + m_roleNames.insert("modelData", roles.first()); + } } else if (m_abstractItemModel) { setModelDataType(); QHash roleNames = m_abstractItemModel->roleNames(); for (QHash::const_iterator it = roleNames.begin(); it != roleNames.end(); ++it) { - addProperty(it.key(), m_propertyData.count(), it.value(), "QVariant"); + const int propertyId = m_propertyData.count(); + addProperty(it.key(), propertyId, it.value(), "QVariant"); + ft->PrototypeTemplate()->SetAccessor( + v8::String::New(it.value().constData(), it.value().length()), + QQuickVDMAbstractItemModelData::get_property, + QQuickVDMAbstractItemModelData::set_property, + v8::Int32::New(propertyId)); m_roleNames.insert(it.value(), it.key()); } - if (m_propertyData.count() == 1) + m_roleCount = m_propertyData.count(); + if (m_propertyData.count() == 1) { addProperty(roleNames.begin().key(), 1, "modelData", "QVariant", true); - m_flags = QQuickVisualAdaptorModel::MetaObjectCacheable; + ft->PrototypeTemplate()->SetAccessor( + v8::String::New("modelData"), + QQuickVDMAbstractItemModelData::get_property, + QQuickVDMAbstractItemModelData::set_property, + v8::Int32::New(0)); + m_roleNames.insert("modelData", roleNames.begin().key()); + } + ft->PrototypeTemplate()->SetAccessor( + v8::String::New("hasModelChildren"), + QQuickVDMAbstractItemModelData::get_hasModelChildren); } else if (m_listAccessor) { setModelDataType(); m_objectList = true; m_flags = QQuickVisualAdaptorModel::ProxiedObject; } else { Q_ASSERT(!"No model set on VisualDataModel"); - return 0; + return; } m_delegateDataType->metaObject = m_delegateDataType->builder.toMetaObject(); if (!m_objectList) { m_delegateDataType->propertyCache = new QDeclarativePropertyCache( m_engine, m_delegateDataType->metaObject); + m_constructor = qPersistentNew(ft->GetFunction()); } - return createModelData(index, model); -} - -QQuickVisualAdaptorModelData::QQuickVisualAdaptorModelData(int index, QQuickVisualAdaptorModel *model) - : m_index(index) - , m_model(model) -{ -} - -QQuickVisualAdaptorModelData::~QQuickVisualAdaptorModelData() -{ -} - -int QQuickVisualAdaptorModelData::index() const -{ - return m_index; -} - -// This is internal only - it should not be set from qml -void QQuickVisualAdaptorModelData::setIndex(int index) -{ - m_index = index; - emit indexChanged(); } //--------------------------------------------------------------------------- @@ -576,11 +862,14 @@ void QQuickVisualAdaptorModel::setModel(const QVariant &model, QDeclarativeEngin d->m_roles.clear(); d->m_roleNames.clear(); + d->m_roleCount = 0; d->m_flags = QQuickVisualAdaptorModel::Flags(); if (d->m_delegateDataType) d->m_delegateDataType->release(); d->m_delegateDataType = 0; - d->createModelData = &QQuickVisualAdaptorModelPrivate::initializeModelData; + d->createItem = &QQuickVisualAdaptorModelPrivate::initializeModelData; + d->stringValue = &QQuickVisualAdaptorModelPrivate::initializeStringValue; + qPersistentDispose(d->m_constructor); if (d->m_count) emit itemsRemoved(0, d->m_count); @@ -667,55 +956,27 @@ int QQuickVisualAdaptorModel::count() const return d->modelCount(); } -QObject *QQuickVisualAdaptorModel::data(int index) +QQuickVisualDataModelItem *QQuickVisualAdaptorModel::createItem(QQuickVisualDataModelItemMetaType *metaType, int index) { Q_D(QQuickVisualAdaptorModel); - QQuickVisualAdaptorModelData *data = d->createModelData(index, this); - d->m_cache.insert(data); - return data; -} -QString QQuickVisualAdaptorModel::stringValue(int index, const QString &name) -{ - Q_D(QQuickVisualAdaptorModel); - if ((!d->m_listModelInterface || !d->m_abstractItemModel) && d->m_listAccessor) { - if (QObject *object = d->m_listAccessor->at(index).value()) - return object->property(name.toUtf8()).toString(); - } + if (QQuickVisualDataModelItem *item = d->createItem(metaType, this, index)) { + d->m_cache.insert(item); - QString val; - QQuickVisualAdaptorModelData *data = d->createModelData(index, this); - - QDeclarativeData *ddata = QDeclarativeData::get(data); - if (ddata && ddata->propertyCache) { - QDeclarativePropertyData *prop = ddata->propertyCache->property(name); - if (prop) { - if (prop->propType == QVariant::String) { - void *args[] = { &val, 0 }; - QMetaObject::metacall(data, QMetaObject::ReadProperty, prop->coreIndex, args); - } else if (prop->propType == qMetaTypeId()) { - QVariant v; - void *args[] = { &v, 0 }; - QMetaObject::metacall(data, QMetaObject::ReadProperty, prop->coreIndex, args); - val = v.toString(); - } - } else { - val = data->property(name.toUtf8()).toString(); + if (d->m_delegateDataType && d->m_delegateDataType->propertyCache) { + QDeclarativeData *qmldata = QDeclarativeData::get(item, true); + qmldata->propertyCache = d->m_delegateDataType->propertyCache; + qmldata->propertyCache->addref(); } - } else { - val = data->property(name.toUtf8()).toString(); + return item; } - - delete data; - - return val; + return 0; } -int QQuickVisualAdaptorModel::indexOf(QObject *object) const +QString QQuickVisualAdaptorModel::stringValue(int index, const QString &name) { - if (QQuickVisualAdaptorModelData *data = qobject_cast(object)) - return data->index(); - return -1; + Q_D(QQuickVisualAdaptorModel); + return d->stringValue(d, index, name); } bool QQuickVisualAdaptorModel::canFetchMore() const @@ -766,11 +1027,11 @@ void QQuickVisualAdaptorModel::_q_itemsChanged(int index, int count, const QList signalIndexes.append(propertyId + d->m_delegateDataType->signalOffset); } - typedef QQuickVisualAdaptorModelDataCache::iterator iterator; + typedef QQuickVisualDataModelItemCache::iterator iterator; for (iterator it = d->m_cache.begin(); it != d->m_cache.end(); ++it) { - const int idx = it->index(); + const int idx = it->modelIndex(); if (idx >= index && idx < index + count) { - QQuickVisualAdaptorModelData *data = *it; + QQuickVisualDataModelItem *data = *it; for (int i = 0; i < signalIndexes.count(); ++i) QMetaObject::activate(data, signalIndexes.at(i), 0); } @@ -786,10 +1047,10 @@ void QQuickVisualAdaptorModel::_q_itemsInserted(int index, int count) return; d->m_count += count; - typedef QQuickVisualAdaptorModelDataCache::iterator iterator; + typedef QQuickVisualDataModelItemCache::iterator iterator; for (iterator it = d->m_cache.begin(); it != d->m_cache.end(); ++it) { - if (it->index() >= index) - it->setIndex(it->index() + count); + if (it->modelIndex() >= index) + it->setModelIndex(it->modelIndex() + count); } emit itemsInserted(index, count); @@ -802,12 +1063,12 @@ void QQuickVisualAdaptorModel::_q_itemsRemoved(int index, int count) return; d->m_count -= count; - typedef QQuickVisualAdaptorModelDataCache::iterator iterator; + typedef QQuickVisualDataModelItemCache::iterator iterator; for (iterator it = d->m_cache.begin(); it != d->m_cache.end(); ++it) { - if (it->index() >= index + count) - it->setIndex(it->index() - count); - else if (it->index() >= index) - it->setIndex(-1); + if (it->modelIndex() >= index + count) + it->setModelIndex(it->modelIndex() - count); + else if (it->modelIndex() >= index) + it->setModelIndex(-1); } emit itemsRemoved(index, count); @@ -820,12 +1081,12 @@ void QQuickVisualAdaptorModel::_q_itemsMoved(int from, int to, int count) const int maximum = qMax(from, to) + count; const int difference = from > to ? count : -count; - typedef QQuickVisualAdaptorModelDataCache::iterator iterator; + typedef QQuickVisualDataModelItemCache::iterator iterator; for (iterator it = d->m_cache.begin(); it != d->m_cache.end(); ++it) { - if (it->index() >= from && it->index() < from + count) - it->setIndex(it->index() - from + to); - else if (it->index() >= minimum && it->index() < maximum) - it->setIndex(it->index() + difference); + if (it->modelIndex() >= from && it->modelIndex() < from + count) + it->setModelIndex(it->modelIndex() - from + to); + else if (it->modelIndex() >= minimum && it->modelIndex() < maximum) + it->setModelIndex(it->modelIndex() + difference); } emit itemsMoved(from, to, count); }