From 486ec88d2b88378768487a12dcbf6493c33d5699 Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Mon, 21 May 2012 13:04:06 +1000 Subject: [PATCH] Use a shared meta-object for VisualDataModel list context objects. The objectDestroyed() function on QAbstractDynamicMetaObject makes it possible to reference count dynamic meta objects so there is no longer a need to construct an instance per item. Change-Id: I6f32b803b97db015212284718239dc3062dcefe7 Reviewed-by: Martin Jones --- src/quick/items/qquickvisualadaptormodel.cpp | 48 ++++++++------------ src/quick/items/qquickvisualdatamodel.cpp | 66 ++++++++++++++++------------ src/quick/items/qquickvisualdatamodel_p_p.h | 20 +++++---- 3 files changed, 67 insertions(+), 67 deletions(-) diff --git a/src/quick/items/qquickvisualadaptormodel.cpp b/src/quick/items/qquickvisualadaptormodel.cpp index 99c44e3..fa88932 100644 --- a/src/quick/items/qquickvisualadaptormodel.cpp +++ b/src/quick/items/qquickvisualadaptormodel.cpp @@ -90,7 +90,6 @@ public: QQuickVisualDataModelItemMetaType *metaType, VDMModelDelegateDataType *dataType, int index); - ~QQuickVDMCachedModelData(); int metaCall(QMetaObject::Call call, int id, void **arguments); @@ -108,7 +107,10 @@ public: QVector cachedData; }; -class VDMModelDelegateDataType : public QQmlRefCount, public QQuickVisualAdaptorModel::Accessors +class VDMModelDelegateDataType + : public QQmlRefCount + , public QQuickVisualAdaptorModel::Accessors + , public QAbstractDynamicMetaObject { public: VDMModelDelegateDataType(QQuickVisualAdaptorModel *model) @@ -204,6 +206,18 @@ public: } } + // QAbstractDynamicMetaObject + + void objectDestroyed(QObject *) + { + release(); + } + + int metaCall(QObject *object, QMetaObject::Call call, int id, void **arguments) + { + return static_cast(object)->metaCall(call, id, arguments); + } + v8::Persistent constructor; QList propertyRoles; QList watchedRoleIds; @@ -217,23 +231,6 @@ public: bool hasModelData; }; - -class QQuickVDMCachedModelDataMetaObject : public QAbstractDynamicMetaObject -{ -public: - QQuickVDMCachedModelDataMetaObject(QQuickVDMCachedModelData *data) - : m_data(data) - { - } - - int metaCall(QMetaObject::Call call, int id, void **arguments) - { - return m_data->metaCall(call, id, arguments); - } - - QQuickVDMCachedModelData *m_data; -}; - QQuickVDMCachedModelData::QQuickVDMCachedModelData( QQuickVisualDataModelItemMetaType *metaType, VDMModelDelegateDataType *dataType, int index) : QQuickVisualDataModelItem(metaType, index) @@ -242,11 +239,7 @@ QQuickVDMCachedModelData::QQuickVDMCachedModelData( if (index == -1) cachedData.resize(type->hasModelData ? 1 : type->propertyRoles.count()); - QQuickVDMCachedModelDataMetaObject *metaObject = new QQuickVDMCachedModelDataMetaObject(this); - - QObjectPrivate *op = QObjectPrivate::get(this); - *static_cast(metaObject) = *type->metaObject; - op->metaObject = metaObject; + QObjectPrivate::get(this)->metaObject = type; type->addref(); @@ -255,11 +248,6 @@ QQuickVDMCachedModelData::QQuickVDMCachedModelData( qmldata->propertyCache->addref(); } -QQuickVDMCachedModelData::~QQuickVDMCachedModelData() -{ - type->release(); -} - int QQuickVDMCachedModelData::metaCall(QMetaObject::Call call, int id, void **arguments) { if (call == QMetaObject::ReadProperty && id >= type->propertyOffset) { @@ -542,6 +530,7 @@ public: } metaObject = builder.toMetaObject(); + *static_cast(this) = *metaObject; propertyCache = new QQmlPropertyCache(engine, metaObject); } }; @@ -657,6 +646,7 @@ public: } metaObject = builder.toMetaObject(); + *static_cast(this) = *metaObject; propertyCache = new QQmlPropertyCache(engine, metaObject); } }; diff --git a/src/quick/items/qquickvisualdatamodel.cpp b/src/quick/items/qquickvisualdatamodel.cpp index 4d295b3..0abcf81 100644 --- a/src/quick/items/qquickvisualdatamodel.cpp +++ b/src/quick/items/qquickvisualdatamodel.cpp @@ -162,6 +162,9 @@ QQuickVisualDataModelPrivate::QQuickVisualDataModelPrivate(QQmlContext *ctxt) QQuickVisualDataModelPrivate::~QQuickVisualDataModelPrivate() { qDeleteAll(m_finishedIncubating); + + if (m_cacheMetaType) + m_cacheMetaType->release(); } void QQuickVisualDataModelPrivate::init() @@ -207,9 +210,6 @@ QQuickVisualDataModel::~QQuickVisualDataModel() if (!cacheItem->isReferenced()) delete cacheItem; } - - if (d->m_cacheMetaType) - d->m_cacheMetaType->release(); } @@ -782,10 +782,10 @@ void QQuickVisualDataModelPrivate::incubatorStatusChanged(QVDMIncubationTask *in if (status == QQmlIncubator::Ready) { incubationTask->incubating = 0; releaseIncubator(incubationTask); - if (QQuickPackage *package = qmlobject_cast(cacheItem->object)) - emitCreatedPackage(cacheItem, package); - else if (QQuickItem *item = qobject_cast(cacheItem->object)) + if (QQuickItem *item = qmlobject_cast(cacheItem->object)) emitCreatedItem(cacheItem, item); + else if (QQuickPackage *package = qmlobject_cast(cacheItem->object)) + emitCreatedPackage(cacheItem, package); } else if (status == QQmlIncubator::Error) { cacheItem->scriptRef -= 1; cacheItem->contextData->destroy(); @@ -1446,18 +1446,16 @@ QQuickVisualDataModelItemMetaType::QQuickVisualDataModelItemMetaType( QV8Engine *engine, QQuickVisualDataModel *model, const QStringList &groupNames) : model(model) , groupCount(groupNames.count() + 1) - , memberPropertyOffset(QQuickVisualDataModelAttached::staticMetaObject.propertyCount()) - , indexPropertyOffset(QQuickVisualDataModelAttached::staticMetaObject.propertyCount() + groupNames.count()) , v8Engine(engine) , metaObject(0) , groupNames(groupNames) { - initializeMetaObject(); } QQuickVisualDataModelItemMetaType::~QQuickVisualDataModelItemMetaType() { - free(metaObject); + if (metaObject) + metaObject->release(); qPersistentDispose(constructor); } @@ -1485,7 +1483,7 @@ void QQuickVisualDataModelItemMetaType::initializeMetaObject() propertyBuilder.setWritable(true); } - metaObject = builder.toMetaObject(); + metaObject = new QQuickVisualDataModelAttachedMetaObject(this, builder.toMetaObject()); } void QQuickVisualDataModelItemMetaType::initializeConstructor() @@ -1785,41 +1783,47 @@ QQuickVisualDataModelItem *QQuickVisualDataModelItem::dataForObject(QObject *obj //--------------------------------------------------------------------------- QQuickVisualDataModelAttachedMetaObject::QQuickVisualDataModelAttachedMetaObject( - QQuickVisualDataModelAttached *attached, QQuickVisualDataModelItemMetaType *metaType) - : attached(attached) - , metaType(metaType) + QQuickVisualDataModelItemMetaType *metaType, QMetaObject *metaObject) + : metaType(metaType) + , metaObject(metaObject) + , memberPropertyOffset(QQuickVisualDataModelAttached::staticMetaObject.propertyCount()) + , indexPropertyOffset(QQuickVisualDataModelAttached::staticMetaObject.propertyCount() + metaType->groupNames.count()) { - if (!metaType->metaObject) - metaType->initializeMetaObject(); - - metaType->addref(); - *static_cast(this) = *metaType->metaObject; - QObjectPrivate::get(attached)->metaObject = this; + // Don't reference count the meta-type here as that would create a circular reference. + // Instead we rely the fact that the meta-type's reference count can't reach 0 without first + // destroying all delegates with attached objects. + *static_cast(this) = *metaObject; } QQuickVisualDataModelAttachedMetaObject::~QQuickVisualDataModelAttachedMetaObject() { - metaType->release(); + ::free(metaObject); } -int QQuickVisualDataModelAttachedMetaObject::metaCall(QMetaObject::Call call, int _id, void **arguments) +void QQuickVisualDataModelAttachedMetaObject::objectDestroyed(QObject *) { + release(); +} + +int QQuickVisualDataModelAttachedMetaObject::metaCall(QObject *object, QMetaObject::Call call, int _id, void **arguments) +{ + QQuickVisualDataModelAttached *attached = static_cast(object); if (call == QMetaObject::ReadProperty) { - if (_id >= metaType->indexPropertyOffset) { - Compositor::Group group = Compositor::Group(_id - metaType->indexPropertyOffset + 1); + if (_id >= indexPropertyOffset) { + Compositor::Group group = Compositor::Group(_id - indexPropertyOffset + 1); *static_cast(arguments[0]) = attached->m_cacheItem->index[group]; return -1; - } else if (_id >= metaType->memberPropertyOffset) { - Compositor::Group group = Compositor::Group(_id - metaType->memberPropertyOffset + 1); + } else if (_id >= memberPropertyOffset) { + Compositor::Group group = Compositor::Group(_id - memberPropertyOffset + 1); *static_cast(arguments[0]) = attached->m_cacheItem->groups & (1 << group); return -1; } } else if (call == QMetaObject::WriteProperty) { - if (_id >= metaType->memberPropertyOffset) { + if (_id >= memberPropertyOffset) { if (!metaType->model) return -1; QQuickVisualDataModelPrivate *model = QQuickVisualDataModelPrivate::get(metaType->model); - Compositor::Group group = Compositor::Group(_id - metaType->memberPropertyOffset + 1); + Compositor::Group group = Compositor::Group(_id - memberPropertyOffset + 1); const int groupFlag = 1 << group; const bool member = attached->m_cacheItem->groups & groupFlag; if (member && !*static_cast(arguments[0])) { @@ -1860,7 +1864,11 @@ QQuickVisualDataModelAttached::QQuickVisualDataModelAttached( for (int i = 1; i < m_cacheItem->metaType->groupCount; ++i) m_previousIndex[i] = m_cacheItem->index[i]; - new QQuickVisualDataModelAttachedMetaObject(this, cacheItem->metaType); + if (!cacheItem->metaType->metaObject) + cacheItem->metaType->initializeMetaObject(); + + QObjectPrivate::get(this)->metaObject = cacheItem->metaType->metaObject; + cacheItem->metaType->metaObject->addref(); } /*! diff --git a/src/quick/items/qquickvisualdatamodel_p_p.h b/src/quick/items/qquickvisualdatamodel_p_p.h index ad5aa5e..dc730c6 100644 --- a/src/quick/items/qquickvisualdatamodel_p_p.h +++ b/src/quick/items/qquickvisualdatamodel_p_p.h @@ -66,6 +66,8 @@ QT_BEGIN_NAMESPACE typedef QQuickListCompositor Compositor; +class QQuickVisualDataModelAttachedMetaObject; + class QQuickVisualDataModelItemMetaType : public QQmlRefCount { public: @@ -92,10 +94,8 @@ public: QQmlGuard model; const int groupCount; - const int memberPropertyOffset; - const int indexPropertyOffset; QV8Engine * const v8Engine; - QMetaObject *metaObject; + QQuickVisualDataModelAttachedMetaObject *metaObject; const QStringList groupNames; v8::Persistent constructor; }; @@ -151,7 +151,6 @@ public: QVDMIncubationTask *incubationTask; v8::Persistent indexHandle; v8::Persistent modelHandle; - QIntrusiveListNode cacheNode; int objectRef; int scriptRef; int groups; @@ -389,18 +388,21 @@ public: QList models; }; -class QQuickVisualDataModelAttachedMetaObject : public QAbstractDynamicMetaObject +class QQuickVisualDataModelAttachedMetaObject : public QAbstractDynamicMetaObject, public QQmlRefCount { public: QQuickVisualDataModelAttachedMetaObject( - QQuickVisualDataModelAttached *attached, QQuickVisualDataModelItemMetaType *metaType); + QQuickVisualDataModelItemMetaType *metaType, QMetaObject *metaObject); ~QQuickVisualDataModelAttachedMetaObject(); - int metaCall(QMetaObject::Call, int _id, void **); + void objectDestroyed(QObject *); + int metaCall(QObject *, QMetaObject::Call, int _id, void **); private: - QQuickVisualDataModelAttached *attached; - QQuickVisualDataModelItemMetaType *metaType; + QQuickVisualDataModelItemMetaType * const metaType; + QMetaObject * const metaObject; + const int memberPropertyOffset; + const int indexPropertyOffset; }; QT_END_NAMESPACE -- 2.7.4