Use a shared meta-object for VisualDataModel list context objects.
authorAndrew den Exter <andrew.den-exter@nokia.com>
Mon, 21 May 2012 03:04:06 +0000 (13:04 +1000)
committerQt by Nokia <qt-info@nokia.com>
Wed, 30 May 2012 04:01:46 +0000 (06:01 +0200)
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 <martin.jones@nokia.com>

src/quick/items/qquickvisualadaptormodel.cpp
src/quick/items/qquickvisualdatamodel.cpp
src/quick/items/qquickvisualdatamodel_p_p.h

index 99c44e3..fa88932 100644 (file)
@@ -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<QVariant> 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<QQuickVDMCachedModelData *>(object)->metaCall(call, id, arguments);
+    }
+
     v8::Persistent<v8::ObjectTemplate> constructor;
     QList<int> propertyRoles;
     QList<int> 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<QMetaObject *>(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<QMetaObject *>(this) = *metaObject;
         propertyCache = new QQmlPropertyCache(engine, metaObject);
     }
 };
@@ -657,6 +646,7 @@ public:
         }
 
         metaObject = builder.toMetaObject();
+        *static_cast<QMetaObject *>(this) = *metaObject;
         propertyCache = new QQmlPropertyCache(engine, metaObject);
     }
 };
index 4d295b3..0abcf81 100644 (file)
@@ -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<QQuickPackage *>(cacheItem->object))
-            emitCreatedPackage(cacheItem, package);
-        else if (QQuickItem *item = qobject_cast<QQuickItem *>(cacheItem->object))
+        if (QQuickItem *item = qmlobject_cast<QQuickItem *>(cacheItem->object))
             emitCreatedItem(cacheItem, item);
+        else if (QQuickPackage *package = qmlobject_cast<QQuickPackage *>(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<QMetaObject *>(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<QMetaObject *>(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<QQuickVisualDataModelAttached *>(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<int *>(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<bool *>(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<bool *>(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();
 }
 
 /*!
index ad5aa5e..dc730c6 100644 (file)
@@ -66,6 +66,8 @@ QT_BEGIN_NAMESPACE
 
 typedef QQuickListCompositor Compositor;
 
+class QQuickVisualDataModelAttachedMetaObject;
+
 class QQuickVisualDataModelItemMetaType : public QQmlRefCount
 {
 public:
@@ -92,10 +94,8 @@ public:
 
     QQmlGuard<QQuickVisualDataModel> model;
     const int groupCount;
-    const int memberPropertyOffset;
-    const int indexPropertyOffset;
     QV8Engine * const v8Engine;
-    QMetaObject *metaObject;
+    QQuickVisualDataModelAttachedMetaObject *metaObject;
     const QStringList groupNames;
     v8::Persistent<v8::ObjectTemplate> constructor;
 };
@@ -151,7 +151,6 @@ public:
     QVDMIncubationTask *incubationTask;
     v8::Persistent<v8::Object> indexHandle;
     v8::Persistent<v8::Value> modelHandle;
-    QIntrusiveListNode cacheNode;
     int objectRef;
     int scriptRef;
     int groups;
@@ -389,18 +388,21 @@ public:
     QList<QQuickVisualPartsModel *> 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