diff options
Diffstat (limited to 'src/qml')
-rw-r--r-- | src/qml/compiler/qqmlpropertycachecreator.cpp | 2 | ||||
-rw-r--r-- | src/qml/compiler/qqmlpropertyvalidator.cpp | 8 | ||||
-rw-r--r-- | src/qml/compiler/qv4compileddata.cpp | 2 | ||||
-rw-r--r-- | src/qml/jsapi/qjsengine_p.h | 12 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4qobjectwrapper.cpp | 31 | ||||
-rw-r--r-- | src/qml/qml/qqmlengine_p.h | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmlmetatype.cpp | 14 | ||||
-rw-r--r-- | src/qml/qml/qqmlmetatype_p.h | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmlpropertycache.cpp | 21 | ||||
-rw-r--r-- | src/qml/qml/qqmlpropertycache_p.h | 6 | ||||
-rw-r--r-- | src/qml/types/qqmldelegatemodel.cpp | 19 | ||||
-rw-r--r-- | src/qml/types/qqmldelegatemodel_p_p.h | 14 | ||||
-rw-r--r-- | src/qml/types/qqmltableinstancemodel.cpp | 5 | ||||
-rw-r--r-- | src/qml/types/qqmltableinstancemodel_p.h | 2 | ||||
-rw-r--r-- | src/qml/util/qqmladaptormodel.cpp | 83 | ||||
-rw-r--r-- | src/qml/util/qqmladaptormodel_p.h | 7 |
16 files changed, 146 insertions, 84 deletions
diff --git a/src/qml/compiler/qqmlpropertycachecreator.cpp b/src/qml/compiler/qqmlpropertycachecreator.cpp index fd22cd58f1..fb54da5b73 100644 --- a/src/qml/compiler/qqmlpropertycachecreator.cpp +++ b/src/qml/compiler/qqmlpropertycachecreator.cpp @@ -74,7 +74,7 @@ QQmlRefPointer<QQmlPropertyCache> QQmlBindingInstantiationContext::instantiating if (instantiatingProperty->isQObject()) { return enginePrivate->rawPropertyCacheForType(instantiatingProperty->propType(), instantiatingProperty->typeMinorVersion()); } else if (const QMetaObject *vtmo = QQmlValueTypeFactory::metaObjectForMetaType(instantiatingProperty->propType())) { - return enginePrivate->cache(vtmo); + return enginePrivate->cache(vtmo, instantiatingProperty->typeMinorVersion()); } } return QQmlRefPointer<QQmlPropertyCache>(); diff --git a/src/qml/compiler/qqmlpropertyvalidator.cpp b/src/qml/compiler/qqmlpropertyvalidator.cpp index 4e8f57c2cf..1beaac8095 100644 --- a/src/qml/compiler/qqmlpropertyvalidator.cpp +++ b/src/qml/compiler/qqmlpropertyvalidator.cpp @@ -160,10 +160,12 @@ QVector<QQmlCompileError> QQmlPropertyValidator::validateObject(int objectIndex, QQmlPropertyData *pd = nullptr; if (!name.isEmpty()) { if (binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression - || binding->flags & QV4::CompiledData::Binding::IsSignalHandlerObject) + || binding->flags & QV4::CompiledData::Binding::IsSignalHandlerObject) { pd = propertyResolver.signal(name, ¬InRevision); - else - pd = propertyResolver.property(name, ¬InRevision, isGroupProperty ? QmlIR::PropertyResolver::IgnoreRevision : QmlIR::PropertyResolver::CheckRevision); + } else { + pd = propertyResolver.property(name, ¬InRevision, + QmlIR::PropertyResolver::CheckRevision); + } if (notInRevision) { QString typeName = stringAt(obj->inheritedTypeNameIndex); diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp index c90bbf03e6..cb614f7d40 100644 --- a/src/qml/compiler/qv4compileddata.cpp +++ b/src/qml/compiler/qv4compileddata.cpp @@ -854,7 +854,7 @@ QQmlRefPointer<QQmlPropertyCache> ResolvedTypeReference::createPropertyCache(QQm if (typePropertyCache) { return typePropertyCache; } else if (type.isValid()) { - typePropertyCache = QQmlEnginePrivate::get(engine)->cache(type.metaObject()); + typePropertyCache = QQmlEnginePrivate::get(engine)->cache(type.metaObject(), minorVersion); return typePropertyCache; } else { return compilationUnit->rootPropertyCache(); diff --git a/src/qml/jsapi/qjsengine_p.h b/src/qml/jsapi/qjsengine_p.h index 360c9df075..a77d710cff 100644 --- a/src/qml/jsapi/qjsengine_p.h +++ b/src/qml/jsapi/qjsengine_p.h @@ -109,8 +109,8 @@ public: // These methods may be called from the QML loader thread - inline QQmlPropertyCache *cache(QObject *obj); - inline QQmlPropertyCache *cache(const QMetaObject *); + inline QQmlPropertyCache *cache(QObject *obj, int minorVersion = -1); + inline QQmlPropertyCache *cache(const QMetaObject *, int minorVersion = -1); }; QJSEnginePrivate::Locker::Locker(const QJSEngine *e) @@ -160,14 +160,14 @@ and deleted before the loader thread has a chance to use or reference it. This can't currently happen as the cache holds a reference to the QQmlPropertyCache until the QQmlEngine is destroyed. */ -QQmlPropertyCache *QJSEnginePrivate::cache(QObject *obj) +QQmlPropertyCache *QJSEnginePrivate::cache(QObject *obj, int minorVersion) { if (!obj || QObjectPrivate::get(obj)->metaObject || QObjectPrivate::get(obj)->wasDeleted) return nullptr; Locker locker(this); const QMetaObject *mo = obj->metaObject(); - return QQmlMetaType::propertyCache(mo); + return QQmlMetaType::propertyCache(mo, minorVersion); } /*! @@ -179,12 +179,12 @@ exist for the lifetime of the QQmlEngine. The returned cache is not referenced, so if it is to be stored, call addref(). */ -QQmlPropertyCache *QJSEnginePrivate::cache(const QMetaObject *metaObject) +QQmlPropertyCache *QJSEnginePrivate::cache(const QMetaObject *metaObject, int minorVersion) { Q_ASSERT(metaObject); Locker locker(this); - return QQmlMetaType::propertyCache(metaObject); + return QQmlMetaType::propertyCache(metaObject, minorVersion); } diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp index 6617dd5e89..40be6f41c8 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper.cpp +++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp @@ -1206,8 +1206,20 @@ static QV4::ReturnedValue CallMethod(const QQmlObjectOrGadget &object, int index args[0].initAsType(returnType); for (int ii = 0; ii < argCount; ++ii) { if (!args[ii + 1].fromValue(argTypes[ii], engine, callArgs->args[ii])) { - return engine->throwTypeError(QString::fromLatin1("Could not convert argument %1.") - .arg(ii)); + qWarning() << QString::fromLatin1("Could not convert argument %1 at").arg(ii); + const StackTrace stack = engine->stackTrace(); + for (const StackFrame &frame : stack) { + qWarning() << "\t" << frame.function + QLatin1Char('@') + frame.source + + (frame.line > 0 + ? (QLatin1Char(':') + QString::number(frame.line)) + : QString()); + + } + qWarning() << QLatin1String("Passing incompatible arguments to C++ functions from " + "JavaScript is dangerous and deprecated."); + qWarning() << QLatin1String("This will throw a JavaScript TypeError in future " + "releases of Qt!"); + } } QVarLengthArray<void *, 9> argData(args.count()); @@ -1724,6 +1736,7 @@ bool CallArgument::fromValue(int callType, QV4::ExecutionEngine *engine, const Q type = callType; } else if (callType == qMetaTypeId<QList<QObject*> >()) { qlistPtr = new (&allocData) QList<QObject *>(); + type = callType; QV4::ScopedArrayObject array(scope, value); if (array) { Scoped<QV4::QObjectWrapper> qobjectWrapper(scope); @@ -1737,14 +1750,14 @@ bool CallArgument::fromValue(int callType, QV4::ExecutionEngine *engine, const Q qlistPtr->append(o); } } else { - QObject *o = nullptr; - if (const QV4::QObjectWrapper *qobjectWrapper = value.as<QV4::QObjectWrapper>()) - o = qobjectWrapper->object(); - else if (!value.isNull() && !value.isUndefined()) - return false; - qlistPtr->append(o); + if (const QV4::QObjectWrapper *qobjectWrapper = value.as<QV4::QObjectWrapper>()) { + qlistPtr->append(qobjectWrapper->object()); + } else { + qlistPtr->append(nullptr); + if (!value.isNull() && !value.isUndefined()) + return false; + } } - type = callType; } else if (callType == qMetaTypeId<QQmlV4Handle>()) { handlePtr = new (&allocData) QQmlV4Handle(value.asReturnedValue()); type = callType; diff --git a/src/qml/qml/qqmlengine_p.h b/src/qml/qml/qqmlengine_p.h index 70e188dc1c..d05c945ae4 100644 --- a/src/qml/qml/qqmlengine_p.h +++ b/src/qml/qml/qqmlengine_p.h @@ -377,7 +377,7 @@ QQmlPropertyCache *QQmlEnginePrivate::cache(const QQmlType &type, int minorVersi Q_ASSERT(type.isValid()); if (minorVersion == -1 || !type.containsRevisionedAttributes()) - return cache(type.metaObject()); + return cache(type.metaObject(), minorVersion); Locker locker(this); return QQmlMetaType::propertyCache(type, minorVersion); diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp index 032ee7d6fc..e4fd42932f 100644 --- a/src/qml/qml/qqmlmetatype.cpp +++ b/src/qml/qml/qqmlmetatype.cpp @@ -118,7 +118,7 @@ struct QQmlMetaTypeData QHash<int, int> qmlLists; QHash<const QMetaObject *, QQmlPropertyCache *> propertyCaches; - QQmlPropertyCache *propertyCache(const QMetaObject *metaObject); + QQmlPropertyCache *propertyCache(const QMetaObject *metaObject, int minorVersion); QQmlPropertyCache *propertyCache(const QQmlType &type, int minorVersion); void startRecordingTypeRegFailures(QStringList *storage) @@ -2432,7 +2432,7 @@ QQmlType QQmlMetaType::qmlType(const QUrl &unNormalizedUrl, bool includeNonFileI return QQmlType(); } -QQmlPropertyCache *QQmlMetaTypeData::propertyCache(const QMetaObject *metaObject) +QQmlPropertyCache *QQmlMetaTypeData::propertyCache(const QMetaObject *metaObject, int minorVersion) { if (QQmlPropertyCache *rv = propertyCaches.value(metaObject)) return rv; @@ -2442,17 +2442,17 @@ QQmlPropertyCache *QQmlMetaTypeData::propertyCache(const QMetaObject *metaObject propertyCaches.insert(metaObject, rv); return rv; } - QQmlPropertyCache *super = propertyCache(metaObject->superClass()); - QQmlPropertyCache *rv = super->copyAndAppend(metaObject); + QQmlPropertyCache *super = propertyCache(metaObject->superClass(), minorVersion); + QQmlPropertyCache *rv = super->copyAndAppend(metaObject, minorVersion); propertyCaches.insert(metaObject, rv); return rv; } -QQmlPropertyCache *QQmlMetaType::propertyCache(const QMetaObject *metaObject) +QQmlPropertyCache *QQmlMetaType::propertyCache(const QMetaObject *metaObject, int minorVersion) { QMutexLocker lock(metaTypeDataLock()); QQmlMetaTypeData *data = metaTypeData(); - return data->propertyCache(metaObject); + return data->propertyCache(metaObject, minorVersion); } QQmlPropertyCache *QQmlMetaTypeData::propertyCache(const QQmlType &type, int minorVersion) @@ -2485,7 +2485,7 @@ QQmlPropertyCache *QQmlMetaTypeData::propertyCache(const QQmlType &type, int min return pc; } - QQmlPropertyCache *raw = propertyCache(type.metaObject()); + QQmlPropertyCache *raw = propertyCache(type.metaObject(), minorVersion); bool hasCopied = false; diff --git a/src/qml/qml/qqmlmetatype_p.h b/src/qml/qml/qqmlmetatype_p.h index 2a45ddb4bb..3ad2de7bb3 100644 --- a/src/qml/qml/qqmlmetatype_p.h +++ b/src/qml/qml/qqmlmetatype_p.h @@ -103,7 +103,7 @@ public: static QQmlType qmlType(int typeId, TypeIdCategory category = TypeIdCategory::MetaType); static QQmlType qmlType(const QUrl &unNormalizedUrl, bool includeNonFileImports = false); - static QQmlPropertyCache *propertyCache(const QMetaObject *metaObject); + static QQmlPropertyCache *propertyCache(const QMetaObject *metaObject, int minorVersion = -1); static QQmlPropertyCache *propertyCache(const QQmlType &type, int minorVersion); static void freeUnusedTypesAndCaches(); diff --git a/src/qml/qml/qqmlpropertycache.cpp b/src/qml/qml/qqmlpropertycache.cpp index d619730e28..73bfd7bbaa 100644 --- a/src/qml/qml/qqmlpropertycache.cpp +++ b/src/qml/qml/qqmlpropertycache.cpp @@ -252,12 +252,22 @@ QQmlPropertyCache::QQmlPropertyCache() /*! Creates a new QQmlPropertyCache of \a metaObject. */ -QQmlPropertyCache::QQmlPropertyCache(const QMetaObject *metaObject) +QQmlPropertyCache::QQmlPropertyCache(const QMetaObject *metaObject, int metaObjectRevision) : QQmlPropertyCache() { Q_ASSERT(metaObject); update(metaObject); + + if (metaObjectRevision > 0) { + // Set the revision of the meta object that this cache describes to be + // 'metaObjectRevision'. This is useful when constructing a property cache + // from a type that was created directly in C++, and not through QML. For such + // types, the revision for each recorded QMetaObject would normally be zero, which + // would exclude any revisioned properties. + for (int metaObjectOffset = 0; metaObjectOffset < allowedRevisionCache.size(); ++metaObjectOffset) + allowedRevisionCache[metaObjectOffset] = metaObjectRevision; + } } QQmlPropertyCache::~QQmlPropertyCache() @@ -454,7 +464,7 @@ QQmlPropertyCache::copyAndAppend(const QMetaObject *metaObject, QQmlPropertyCache * QQmlPropertyCache::copyAndAppend(const QMetaObject *metaObject, - int revision, + int typeMinorVersion, QQmlPropertyData::Flags propertyFlags, QQmlPropertyData::Flags methodFlags, QQmlPropertyData::Flags signalFlags) @@ -468,19 +478,17 @@ QQmlPropertyCache::copyAndAppend(const QMetaObject *metaObject, QMetaObjectPrivate::get(metaObject)->signalCount + QMetaObjectPrivate::get(metaObject)->propertyCount); - rv->append(metaObject, revision, propertyFlags, methodFlags, signalFlags); + rv->append(metaObject, typeMinorVersion, propertyFlags, methodFlags, signalFlags); return rv; } void QQmlPropertyCache::append(const QMetaObject *metaObject, - int revision, + int typeMinorVersion, QQmlPropertyData::Flags propertyFlags, QQmlPropertyData::Flags methodFlags, QQmlPropertyData::Flags signalFlags) { - Q_UNUSED(revision); - _metaObject = metaObject; bool dynamicMetaObject = isDynamicMetaObject(metaObject); @@ -630,6 +638,7 @@ void QQmlPropertyCache::append(const QMetaObject *metaObject, data->setFlags(propertyFlags); data->lazyLoad(p); + data->setTypeMinorVersion(typeMinorVersion); data->_flags.isDirect = !dynamicMetaObject; diff --git a/src/qml/qml/qqmlpropertycache_p.h b/src/qml/qml/qqmlpropertycache_p.h index 0785910cec..c3c818eb77 100644 --- a/src/qml/qml/qqmlpropertycache_p.h +++ b/src/qml/qml/qqmlpropertycache_p.h @@ -394,7 +394,7 @@ class Q_QML_PRIVATE_EXPORT QQmlPropertyCache : public QQmlRefCount { public: QQmlPropertyCache(); - QQmlPropertyCache(const QMetaObject *); + QQmlPropertyCache(const QMetaObject *, int metaObjectRevision = 0); ~QQmlPropertyCache() override; void update(const QMetaObject *); @@ -408,7 +408,7 @@ public: QQmlPropertyRawData::Flags propertyFlags = QQmlPropertyData::Flags(), QQmlPropertyRawData::Flags methodFlags = QQmlPropertyData::Flags(), QQmlPropertyRawData::Flags signalFlags = QQmlPropertyData::Flags()); - QQmlPropertyCache *copyAndAppend(const QMetaObject *, int revision, + QQmlPropertyCache *copyAndAppend(const QMetaObject *, int typeMinorVersion, QQmlPropertyRawData::Flags propertyFlags = QQmlPropertyData::Flags(), QQmlPropertyRawData::Flags methodFlags = QQmlPropertyData::Flags(), QQmlPropertyRawData::Flags signalFlags = QQmlPropertyData::Flags()); @@ -499,7 +499,7 @@ private: inline QQmlPropertyCache *copy(int reserve); - void append(const QMetaObject *, int revision, + void append(const QMetaObject *, int typeMinorVersion, QQmlPropertyRawData::Flags propertyFlags = QQmlPropertyRawData::Flags(), QQmlPropertyRawData::Flags methodFlags = QQmlPropertyData::Flags(), QQmlPropertyRawData::Flags signalFlags = QQmlPropertyData::Flags()); 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..0028849828 100644 --- a/src/qml/types/qqmldelegatemodel_p_p.h +++ b/src/qml/types/qqmldelegatemodel_p_p.h @@ -96,11 +96,13 @@ class QQmlDelegateModelItem : public QObject { Q_OBJECT Q_PROPERTY(int index READ modelIndex NOTIFY modelIndexChanged) - Q_PROPERTY(int row MEMBER row NOTIFY rowChanged) - Q_PROPERTY(int column MEMBER column NOTIFY columnChanged) + Q_PROPERTY(int row READ modelRow NOTIFY rowChanged REVISION 12) + Q_PROPERTY(int column READ modelColumn NOTIFY columnChanged REVISION 12) 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; } @@ -124,6 +126,8 @@ public: int groupIndex(Compositor::Group group); + int modelRow() const { return row; } + int modelColumn() const { return column; } int modelIndex() const { return index; } virtual void setModelIndex(int idx, int newRow, int newColumn); @@ -154,8 +158,8 @@ public: Q_SIGNALS: void modelIndexChanged(); - void rowChanged(); - void columnChanged(); + Q_REVISION(12) void rowChanged(); + Q_REVISION(12) void columnChanged(); protected: void objectDestroyed(QObject *); diff --git a/src/qml/types/qqmltableinstancemodel.cpp b/src/qml/types/qqmltableinstancemodel.cpp index 1054158dc8..2170e2daec 100644 --- a/src/qml/types/qqmltableinstancemodel.cpp +++ b/src/qml/types/qqmltableinstancemodel.cpp @@ -82,6 +82,11 @@ QQmlTableInstanceModel::QQmlTableInstanceModel(QQmlContext *qmlContext, QObject { } +void QQmlTableInstanceModel::useImportVersion(int minorVersion) +{ + m_adaptorModel.useImportVersion(minorVersion); +} + QQmlTableInstanceModel::~QQmlTableInstanceModel() { for (const auto modelItem : m_modelItems) { diff --git a/src/qml/types/qqmltableinstancemodel_p.h b/src/qml/types/qqmltableinstancemodel_p.h index 03761af326..3dd5c4e4ce 100644 --- a/src/qml/types/qqmltableinstancemodel_p.h +++ b/src/qml/types/qqmltableinstancemodel_p.h @@ -93,6 +93,8 @@ public: QQmlTableInstanceModel(QQmlContext *qmlContext, QObject *parent = nullptr); ~QQmlTableInstanceModel() override; + void useImportVersion(int minorVersion); + int count() const override { return m_adaptorModel.count(); } int rows() const { return m_adaptorModel.rowCount(); } int columns() const { return m_adaptorModel.columnCount(); } diff --git a/src/qml/util/qqmladaptormodel.cpp b/src/qml/util/qqmladaptormodel.cpp index 831663fb7b..d9cb6506b8 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; @@ -1010,6 +1008,11 @@ int QQmlAdaptorModel::indexAt(int row, int column) const return column * rowCount() + row; } +void QQmlAdaptorModel::useImportVersion(int minorVersion) +{ + modelItemRevision = minorVersion; +} + void QQmlAdaptorModel::objectDestroyed(QObject *) { setModel(QVariant(), nullptr, nullptr); diff --git a/src/qml/util/qqmladaptormodel_p.h b/src/qml/util/qqmladaptormodel_p.h index b5e0881078..8c18466ab5 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(); @@ -125,6 +130,8 @@ public: int columnAt(int index) const; int indexAt(int row, int column) const; + void useImportVersion(int minorVersion); + inline bool adaptsAim() const { return qobject_cast<QAbstractItemModel *>(object()); } inline QAbstractItemModel *aim() { return static_cast<QAbstractItemModel *>(object()); } inline const QAbstractItemModel *aim() const { return static_cast<const QAbstractItemModel *>(object()); } |