aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorRichard Moe Gustavsen <richard.gustavsen@qt.io>2018-10-31 13:02:51 +0100
committerRichard Moe Gustavsen <richard.gustavsen@qt.io>2019-02-21 10:55:03 +0000
commit99e2356a734fa3eb55ffc2e983658d17ab4c3e9f (patch)
tree6bcb7aa33c0cee20a363fb4c0378acd635cefbd2 /src
parent3b9ecd6174a7a6eacf22b5088b66b203160bfdbd (diff)
QQmlAdaptorModel::Accessors: create a propertyCache for all accessors, not just for QAIM
From before, only accessors for wrapping a QAbstractItemModel had to create a dynamic QMetaObject together with a shared QQmlPropertyCache (for enabling model roles in the delegate). Each model item in the view would get a QQmlData with the dynamic property cache assigned, which would then later be used by the v4 runtime during property lookup. But after we added the properties 'row' and 'column' to the model items, we now always need to create a property cache, regardless of the Accessor used. That way we can we specify the correct metaObject revision of the model item in the cache, which will also allow us to revision the new properties so that they will be respected by the v4 runtime. In this patch we hard-code the revision (modelItemRevision) to be 0, but this will change in a subsequent patch. This patch will move the 'metaObject' and 'propertyCache' up to the base class (Accessor), and ensure that we create a property cache for each of the non-pure-virtual sub classes. The model item wrappers will then, when creating a QQmlData, assign the shared cache from the associated Accessor. Task-number: QTBUG-70031 Change-Id: If6a67d5968d360d4a2b23d8291669c0549e8a342 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/qml/types/qqmldelegatemodel.cpp19
-rw-r--r--src/qml/types/qqmldelegatemodel_p_p.h4
-rw-r--r--src/qml/util/qqmladaptormodel.cpp78
-rw-r--r--src/qml/util/qqmladaptormodel_p.h5
4 files changed, 64 insertions, 42 deletions
diff --git a/src/qml/types/qqmldelegatemodel.cpp b/src/qml/types/qqmldelegatemodel.cpp
index 48cc77bc3d..53e3f65553 100644
--- a/src/qml/types/qqmldelegatemodel.cpp
+++ b/src/qml/types/qqmldelegatemodel.cpp
@@ -2036,7 +2036,9 @@ void QV4::Heap::QQmlDelegateModelItemObject::destroy()
}
-QQmlDelegateModelItem::QQmlDelegateModelItem(QQmlDelegateModelItemMetaType *metaType, int modelIndex, int row, int column)
+QQmlDelegateModelItem::QQmlDelegateModelItem(QQmlDelegateModelItemMetaType *metaType,
+ QQmlAdaptorModel::Accessors *accessor,
+ int modelIndex, int row, int column)
: v4(metaType->v4Engine)
, metaType(metaType)
, contextData(nullptr)
@@ -2053,6 +2055,21 @@ QQmlDelegateModelItem::QQmlDelegateModelItem(QQmlDelegateModelItemMetaType *meta
, column(column)
{
metaType->addref();
+
+ if (accessor->propertyCache) {
+ // The property cache in the accessor is common for all the model
+ // items in the model it wraps. It describes available model roles,
+ // together with revisioned properties like row, column and index, all
+ // which should be available in the delegate. We assign this cache to the
+ // model item so that the QML engine can use the revision information
+ // when resolving the properties (rather than falling back to just
+ // inspecting the QObject in the model item directly).
+ QQmlData *qmldata = QQmlData::get(this, true);
+ if (qmldata->propertyCache)
+ qmldata->propertyCache->release();
+ qmldata->propertyCache = accessor->propertyCache.data();
+ qmldata->propertyCache->addref();
+ }
}
QQmlDelegateModelItem::~QQmlDelegateModelItem()
diff --git a/src/qml/types/qqmldelegatemodel_p_p.h b/src/qml/types/qqmldelegatemodel_p_p.h
index 5e480f4df6..0cd772ede0 100644
--- a/src/qml/types/qqmldelegatemodel_p_p.h
+++ b/src/qml/types/qqmldelegatemodel_p_p.h
@@ -100,7 +100,9 @@ class QQmlDelegateModelItem : public QObject
Q_PROPERTY(int column MEMBER column NOTIFY columnChanged)
Q_PROPERTY(QObject *model READ modelObject CONSTANT)
public:
- QQmlDelegateModelItem(QQmlDelegateModelItemMetaType *metaType, int modelIndex, int row, int column);
+ QQmlDelegateModelItem(QQmlDelegateModelItemMetaType *metaType,
+ QQmlAdaptorModel::Accessors *accessor, int modelIndex,
+ int row, int column);
~QQmlDelegateModelItem();
void referenceObject() { ++objectRef; }
diff --git a/src/qml/util/qqmladaptormodel.cpp b/src/qml/util/qqmladaptormodel.cpp
index 831663fb7b..8743e9ea7c 100644
--- a/src/qml/util/qqmladaptormodel.cpp
+++ b/src/qml/util/qqmladaptormodel.cpp
@@ -121,21 +121,12 @@ class VDMModelDelegateDataType
public:
VDMModelDelegateDataType(QQmlAdaptorModel *model)
: model(model)
- , metaObject(nullptr)
- , propertyCache(nullptr)
, propertyOffset(0)
, signalOffset(0)
, hasModelData(false)
{
}
- ~VDMModelDelegateDataType()
- {
- if (propertyCache)
- propertyCache->release();
- free(metaObject);
- }
-
bool notify(
const QQmlAdaptorModel &,
const QList<QQmlDelegateModelItem *> &items,
@@ -255,15 +246,13 @@ public:
QList<QByteArray> watchedRoles;
QHash<QByteArray, int> roleNames;
QQmlAdaptorModel *model;
- QMetaObject *metaObject;
- QQmlPropertyCache *propertyCache;
int propertyOffset;
int signalOffset;
bool hasModelData;
};
QQmlDMCachedModelData::QQmlDMCachedModelData(QQmlDelegateModelItemMetaType *metaType, VDMModelDelegateDataType *dataType, int index, int row, int column)
- : QQmlDelegateModelItem(metaType, index, row, column)
+ : QQmlDelegateModelItem(metaType, dataType, index, row, column)
, type(dataType)
{
if (index == -1)
@@ -272,10 +261,6 @@ QQmlDMCachedModelData::QQmlDMCachedModelData(QQmlDelegateModelItemMetaType *meta
QObjectPrivate::get(this)->metaObject = type;
type->addref();
-
- QQmlData *qmldata = QQmlData::get(this, true);
- qmldata->propertyCache = dataType->propertyCache;
- qmldata->propertyCache->addref();
}
int QQmlDMCachedModelData::metaCall(QMetaObject::Call call, int id, void **arguments)
@@ -538,9 +523,9 @@ public:
addProperty(&builder, 1, propertyName, propertyType);
}
- metaObject = builder.toMetaObject();
+ metaObject.reset(builder.toMetaObject());
*static_cast<QMetaObject *>(this) = *metaObject;
- propertyCache = new QQmlPropertyCache(metaObject);
+ propertyCache = new QQmlPropertyCache(metaObject.data(), model.modelItemRevision);
}
};
@@ -553,8 +538,10 @@ class QQmlDMListAccessorData : public QQmlDelegateModelItem
Q_OBJECT
Q_PROPERTY(QVariant modelData READ modelData WRITE setModelData NOTIFY modelDataChanged)
public:
- QQmlDMListAccessorData(QQmlDelegateModelItemMetaType *metaType, int index, int row, int column, const QVariant &value)
- : QQmlDelegateModelItem(metaType, index, row, column)
+ QQmlDMListAccessorData(QQmlDelegateModelItemMetaType *metaType,
+ QQmlAdaptorModel::Accessors *accessor,
+ int index, int row, int column, const QVariant &value)
+ : QQmlDelegateModelItem(metaType, accessor, index, row, column)
, cachedData(value)
{
}
@@ -635,10 +622,18 @@ private:
};
-class VDMListDelegateDataType : public QQmlAdaptorModel::Accessors
+class VDMListDelegateDataType : public QQmlRefCount, public QQmlAdaptorModel::Accessors
{
public:
- inline VDMListDelegateDataType() {}
+ VDMListDelegateDataType()
+ : QQmlRefCount()
+ , QQmlAdaptorModel::Accessors()
+ {}
+
+ void cleanup(QQmlAdaptorModel &) const override
+ {
+ const_cast<VDMListDelegateDataType *>(this)->release();
+ }
int rowCount(const QQmlAdaptorModel &model) const override
{
@@ -662,8 +657,15 @@ public:
QQmlDelegateModelItemMetaType *metaType,
int index, int row, int column) const override
{
+ VDMListDelegateDataType *dataType = const_cast<VDMListDelegateDataType *>(this);
+ if (!propertyCache) {
+ dataType->propertyCache = new QQmlPropertyCache(
+ &QQmlDMListAccessorData::staticMetaObject, model.modelItemRevision);
+ }
+
return new QQmlDMListAccessorData(
metaType,
+ dataType,
index, row, column,
index >= 0 && index < model.list.count() ? model.list.at(index) : QVariant());
}
@@ -721,15 +723,13 @@ Q_SIGNALS:
class VDMObjectDelegateDataType : public QQmlRefCount, public QQmlAdaptorModel::Accessors
{
public:
- QMetaObject *metaObject;
int propertyOffset;
int signalOffset;
bool shared;
QMetaObjectBuilder builder;
VDMObjectDelegateDataType()
- : metaObject(nullptr)
- , propertyOffset(0)
+ : propertyOffset(0)
, signalOffset(0)
, shared(true)
{
@@ -738,11 +738,10 @@ public:
VDMObjectDelegateDataType(const VDMObjectDelegateDataType &type)
: QQmlRefCount()
, QQmlAdaptorModel::Accessors()
- , metaObject(nullptr)
, propertyOffset(type.propertyOffset)
, signalOffset(type.signalOffset)
, shared(false)
- , builder(type.metaObject, QMetaObjectBuilder::Properties
+ , builder(type.metaObject.data(), QMetaObjectBuilder::Properties
| QMetaObjectBuilder::Signals
| QMetaObjectBuilder::SuperClass
| QMetaObjectBuilder::ClassName)
@@ -750,11 +749,6 @@ public:
builder.setFlags(QMetaObjectBuilder::DynamicMetaObject);
}
- ~VDMObjectDelegateDataType()
- {
- free(metaObject);
- }
-
int rowCount(const QQmlAdaptorModel &model) const override
{
return model.list.count();
@@ -785,11 +779,18 @@ public:
: nullptr;
}
- void initializeMetaType(QQmlAdaptorModel &)
+ void initializeMetaType(QQmlAdaptorModel &model)
{
+ Q_UNUSED(model);
setModelDataType<QQmlDMObjectData>(&builder, this);
- metaObject = builder.toMetaObject();
+ metaObject.reset(builder.toMetaObject());
+ // Note: ATM we cannot create a shared property cache for this class, since each model
+ // object can have different properties. And to make those properties available to the
+ // delegate, QQmlDMObjectData makes use of a QAbstractDynamicMetaObject subclass
+ // (QQmlDMObjectDataMetaObject), which we cannot represent in a QQmlPropertyCache.
+ // By not having a shared property cache, revisioned properties in QQmlDelegateModelItem
+ // will always be available to the delegate, regardless of the import version.
}
void cleanup(QQmlAdaptorModel &) const override
@@ -888,9 +889,7 @@ public:
propertyBuilder.setConstant(property.isConstant());
}
- if (m_type->metaObject)
- free(m_type->metaObject);
- m_type->metaObject = m_type->builder.toMetaObject();
+ m_type->metaObject.reset(m_type->builder.toMetaObject());
*static_cast<QMetaObject *>(this) = *m_type->metaObject;
notifierId = previousMethodCount;
@@ -913,7 +912,7 @@ QQmlDMObjectData::QQmlDMObjectData(QQmlDelegateModelItemMetaType *metaType,
VDMObjectDelegateDataType *dataType,
int index, int row, int column,
QObject *object)
- : QQmlDelegateModelItem(metaType, index, row, column)
+ : QQmlDelegateModelItem(metaType, dataType, index, row, column)
, object(object)
{
new QQmlDMObjectDataMetaObject(this, dataType);
@@ -924,7 +923,6 @@ QQmlDMObjectData::QQmlDMObjectData(QQmlDelegateModelItemMetaType *metaType,
//-----------------------------------------------------------------
static const QQmlAdaptorModel::Accessors qt_vdm_null_accessors;
-static const VDMListDelegateDataType qt_vdm_list_accessors;
QQmlAdaptorModel::Accessors::~Accessors()
{
@@ -958,7 +956,7 @@ void QQmlAdaptorModel::setModel(const QVariant &variant, QObject *parent, QQmlEn
} else if (list.type() != QQmlListAccessor::Invalid
&& list.type() != QQmlListAccessor::Instance) { // Null QObject
setObject(nullptr, parent);
- accessors = &qt_vdm_list_accessors;
+ accessors = new VDMListDelegateDataType;
} else {
setObject(nullptr, parent);
accessors = &qt_vdm_null_accessors;
diff --git a/src/qml/util/qqmladaptormodel_p.h b/src/qml/util/qqmladaptormodel_p.h
index b5e0881078..4ce3b0703a 100644
--- a/src/qml/util/qqmladaptormodel_p.h
+++ b/src/qml/util/qqmladaptormodel_p.h
@@ -104,12 +104,17 @@ public:
return QVariant(); }
virtual bool canFetchMore(const QQmlAdaptorModel &) const { return false; }
virtual void fetchMore(QQmlAdaptorModel &) const {}
+
+ QScopedPointer<QMetaObject, QScopedPointerPodDeleter> metaObject;
+ QQmlRefPointer<QQmlPropertyCache> propertyCache;
};
const Accessors *accessors;
QPersistentModelIndex rootIndex;
QQmlListAccessor list;
+ int modelItemRevision = 0;
+
QQmlAdaptorModel();
~QQmlAdaptorModel();