diff options
-rw-r--r-- | src/qml/types/qqmldelegatemodel.cpp | 19 | ||||
-rw-r--r-- | src/qml/types/qqmldelegatemodel_p_p.h | 4 | ||||
-rw-r--r-- | src/qml/util/qqmladaptormodel.cpp | 78 | ||||
-rw-r--r-- | src/qml/util/qqmladaptormodel_p.h | 5 |
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(); |