diff options
Diffstat (limited to 'src/qml')
-rw-r--r-- | src/qml/qml/qqml.cpp | 2 | ||||
-rw-r--r-- | src/qml/qml/qqml.h | 16 | ||||
-rw-r--r-- | src/qml/qml/qqmlengine.cpp | 3 | ||||
-rw-r--r-- | src/qml/qml/qqmlmetatype.cpp | 39 | ||||
-rw-r--r-- | src/qml/qml/qqmlprivate.h | 16 | ||||
-rw-r--r-- | src/qml/qml/qqmltype.cpp | 73 | ||||
-rw-r--r-- | src/qml/qml/qqmltype_p.h | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmltype_p_p.h | 2 |
8 files changed, 109 insertions, 44 deletions
diff --git a/src/qml/qml/qqml.cpp b/src/qml/qml/qqml.cpp index 5dd245f2a3..56a0595e0e 100644 --- a/src/qml/qml/qqml.cpp +++ b/src/qml/qml/qqml.cpp @@ -385,6 +385,8 @@ int QQmlPrivate::qmlregister(RegistrationType type, void *data) type.qObjectApi, type.instanceMetaObject, type.typeId, + type.extensionObjectCreate, + type.extensionMetaObject, QTypeRevision() }; diff --git a/src/qml/qml/qqml.h b/src/qml/qml/qqml.h index 9118b42390..75f7ae5f06 100644 --- a/src/qml/qml/qqml.h +++ b/src/qml/qml/qqml.h @@ -677,7 +677,9 @@ inline int qmlRegisterSingletonType(const char *uri, int versionMajor, int versi uri, QTypeRevision::fromVersion(versionMajor, versionMinor), typeName, callback, - nullptr, nullptr, QMetaType(), QTypeRevision::zero() + nullptr, nullptr, QMetaType(), + nullptr, nullptr, + QTypeRevision::zero() }; return QQmlPrivate::qmlregister(QQmlPrivate::SingletonRegistration, &api); @@ -697,6 +699,7 @@ inline int qmlRegisterSingletonType( callback, QQmlPrivate::StaticMetaObject<T>::staticMetaObject(), QQmlPrivate::QmlMetaType<T>::self(), + nullptr, nullptr, QTypeRevision::zero() }; @@ -722,6 +725,7 @@ inline int qmlRegisterSingletonType(const char *uri, int versionMajor, int versi callback, QQmlPrivate::StaticMetaObject<T>::staticMetaObject(), QQmlPrivate::QmlMetaType<T>::self(), + nullptr, nullptr, QTypeRevision::zero() }; @@ -808,14 +812,14 @@ struct QmlTypeAndRevisionsRegistration<T, Resolved, Extended, false, false> { } }; -template<class T, class Resolved> -struct QmlTypeAndRevisionsRegistration<T, Resolved, void, true, false> { +template<class T, class Resolved, class Extended> +struct QmlTypeAndRevisionsRegistration<T, Resolved, Extended, true, false> { static void registerTypeAndRevisions(const char *uri, int versionMajor, QList<int> *qmlTypeIds, - const QMetaObject *) + const QMetaObject *extension) { - QQmlPrivate::qmlRegisterSingletonAndRevisions<Resolved>( + QQmlPrivate::qmlRegisterSingletonAndRevisions<Resolved, Extended>( uri, versionMajor, QQmlPrivate::StaticMetaObject<T>::staticMetaObject(), - qmlTypeIds); + qmlTypeIds, extension); } }; diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index 0b4493df79..588ccea11c 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -61,6 +61,7 @@ #include <private/qqmldirparser_p.h> #include <private/qqmlboundsignal_p.h> #include <private/qqmljsdiagnosticmessage_p.h> +#include <private/qqmltype_p_p.h> #include <QtCore/qstandardpaths.h> #include <QtCore/qmetaobject.h> #include <QDebug> @@ -2398,6 +2399,8 @@ QJSValue QQmlEnginePrivate::singletonInstance<QJSValue>(const QQmlType &type) qPrintable(QString::fromUtf8(type.typeName())))); warning(error); } else { + type.createProxy(o); + // if this object can use a property cache, create it now QQmlData::ensurePropertyCache(q, o); } diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp index df5c4d89c5..e59ebc97eb 100644 --- a/src/qml/qml/qqmlmetatype.cpp +++ b/src/qml/qml/qqmlmetatype.cpp @@ -152,6 +152,8 @@ static QQmlTypePrivate *createQQmlType(QQmlMetaTypeData *data, const QString &el d->extraData.sd->singletonInstanceInfo->typeName = QString::fromUtf8(type.typeName); d->extraData.sd->singletonInstanceInfo->instanceMetaObject = type.qObjectApi ? type.instanceMetaObject : nullptr; + d->extraData.sd->extFunc = type.extensionObjectCreate; + d->extraData.sd->extMetaObject = type.extensionMetaObject; return d; } @@ -1606,23 +1608,34 @@ QList<QQmlProxyMetaObject::ProxyData> QQmlMetaType::proxyData(const QMetaObject const QQmlMetaTypeDataPtr data; + auto createProxyMetaObject = [&](const QMetaObject *superdataBaseMetaObject, + const QMetaObject *extMetaObject, + QObject *(*extFunc)(QObject *)) { + if (!extMetaObject) + return; + + QMetaObjectBuilder builder; + clone(builder, extMetaObject, superdataBaseMetaObject, baseMetaObject); + builder.setFlags(MetaObjectFlag::DynamicMetaObject); + QMetaObject *mmo = builder.toMetaObject(); + mmo->d.superdata = baseMetaObject; + if (!metaObjects.isEmpty()) + metaObjects.constLast().metaObject->d.superdata = mmo; + else if (lastMetaObject) + lastMetaObject->d.superdata = mmo; + QQmlProxyMetaObject::ProxyData data = { mmo, extFunc, 0, 0 }; + metaObjects << data; + }; + while (mo) { QQmlTypePrivate *t = data->metaObjectToType.value(mo); if (t) { if (t->regType == QQmlType::CppType) { - if (t->extraData.cd->extMetaObject) { - QMetaObjectBuilder builder; - clone(builder, t->extraData.cd->extMetaObject, t->baseMetaObject, baseMetaObject); - builder.setFlags(MetaObjectFlag::DynamicMetaObject); - QMetaObject *mmo = builder.toMetaObject(); - mmo->d.superdata = baseMetaObject; - if (!metaObjects.isEmpty()) - metaObjects.constLast().metaObject->d.superdata = mmo; - else if (lastMetaObject) - lastMetaObject->d.superdata = mmo; - QQmlProxyMetaObject::ProxyData data = { mmo, t->extraData.cd->extFunc, 0, 0 }; - metaObjects << data; - } + createProxyMetaObject(t->baseMetaObject, t->extraData.cd->extMetaObject, + t->extraData.cd->extFunc); + } else if (t->regType == QQmlType::SingletonType) { + createProxyMetaObject(t->baseMetaObject, t->extraData.sd->extMetaObject, + t->extraData.sd->extFunc); } } mo = mo->d.superdata; diff --git a/src/qml/qml/qqmlprivate.h b/src/qml/qml/qqmlprivate.h index 4fcfd65c09..19072f0751 100644 --- a/src/qml/qml/qqmlprivate.h +++ b/src/qml/qml/qqmlprivate.h @@ -526,6 +526,10 @@ namespace QQmlPrivate const QMetaObject *instanceMetaObject; QMetaType typeId; + + QObject *(*extensionObjectCreate)(QObject *); + const QMetaObject *extensionMetaObject; + QTypeRevision revision; }; @@ -540,6 +544,10 @@ namespace QQmlPrivate const QMetaObject *classInfoMetaObject; QMetaType typeId; + + QObject *(*extensionObjectCreate)(QObject *); + const QMetaObject *extensionMetaObject; + QVector<int> *qmlTypeIds; }; @@ -752,10 +760,10 @@ namespace QQmlPrivate } }; - template<typename T> + template<typename T, typename E> void qmlRegisterSingletonAndRevisions(const char *uri, int versionMajor, const QMetaObject *classInfoMetaObject, - QVector<int> *qmlTypeIds) + QVector<int> *qmlTypeIds, const QMetaObject *extension) { RegisterSingletonTypeAndRevisions api = { 0, @@ -769,6 +777,10 @@ namespace QQmlPrivate classInfoMetaObject, QmlMetaType<T>::self(), + + ExtendedType<E>::createParent, + extension ? extension : ExtendedType<E>::staticMetaObject(), + qmlTypeIds }; diff --git a/src/qml/qml/qqmltype.cpp b/src/qml/qml/qqmltype.cpp index e5b3653d2d..811ff668c6 100644 --- a/src/qml/qml/qqmltype.cpp +++ b/src/qml/qml/qqmltype.cpp @@ -78,6 +78,8 @@ QQmlTypePrivate::QQmlTypePrivate(QQmlType::RegistrationType type) case QQmlType::CompositeSingletonType: extraData.sd = new QQmlSingletonTypeData; extraData.sd->singletonInstanceInfo = nullptr; + extraData.sd->extFunc = nullptr; + extraData.sd->extMetaObject = nullptr; break; case QQmlType::InterfaceType: extraData.cd = nullptr; @@ -214,20 +216,27 @@ void QQmlTypePrivate::init() const return; } - if (regType == QQmlType::CppType) { - // Setup extended meta object + auto setupExtendedMetaObject = [&]( + const QMetaObject *extMetaObject, + QObject *(*extFunc)(QObject *)) { + + if (!extMetaObject) + return; + // XXX - very inefficient - if (extraData.cd->extMetaObject) { - QMetaObjectBuilder builder; - QQmlMetaType::clone(builder, extraData.cd->extMetaObject, extraData.cd->extMetaObject, - extraData.cd->extMetaObject); - builder.setFlags(MetaObjectFlag::DynamicMetaObject); - QMetaObject *mmo = builder.toMetaObject(); - mmo->d.superdata = mo; - QQmlProxyMetaObject::ProxyData data = { mmo, extraData.cd->extFunc, 0, 0 }; - metaObjects << data; - } - } + QMetaObjectBuilder builder; + QQmlMetaType::clone(builder, extMetaObject, extMetaObject, extMetaObject); + builder.setFlags(MetaObjectFlag::DynamicMetaObject); + QMetaObject *mmo = builder.toMetaObject(); + mmo->d.superdata = mo; + QQmlProxyMetaObject::ProxyData data = { mmo, extFunc, 0, 0 }; + metaObjects << data; + }; + + if (regType == QQmlType::SingletonType) + setupExtendedMetaObject(extraData.sd->extMetaObject, extraData.sd->extFunc); + else if (regType == QQmlType::CppType) + setupExtendedMetaObject(extraData.cd->extMetaObject, extraData.cd->extFunc); metaObjects.append(QQmlMetaType::proxyData( mo, baseMetaObject, metaObjects.isEmpty() ? nullptr @@ -477,9 +486,7 @@ QObject *QQmlType::create() const d->extraData.cd->newFunc(rv, d->extraData.cd->userdata); - if (rv && !d->metaObjects.isEmpty()) - (void)new QQmlProxyMetaObject(rv, &d->metaObjects); - + createProxy(rv); return rv; } @@ -493,9 +500,7 @@ void QQmlType::create(QObject **out, void **memory, size_t additionalMemory) con QObject *rv = (QObject *)operator new(d->extraData.cd->allocationSize + additionalMemory); d->extraData.cd->newFunc(rv, d->extraData.cd->userdata); - if (rv && !d->metaObjects.isEmpty()) - (void)new QQmlProxyMetaObject(rv, &d->metaObjects); - + createProxy(rv); *out = rv; *memory = ((char *)rv) + d->extraData.cd->allocationSize; } @@ -546,16 +551,32 @@ bool QQmlType::isCreatable() const QQmlType::ExtensionFunc QQmlType::extensionFunction() const { - if (!d || d->regType != CppType) + if (!d) + return nullptr; + + switch (d->regType) { + case CppType: + return d->extraData.cd->extFunc; + case SingletonType: + return d->extraData.sd->extFunc; + default: return nullptr; - return d->extraData.cd->extFunc; + } } const QMetaObject *QQmlType::extensionMetaObject() const { - if (!d || d->regType != CppType) + if (!d) + return nullptr; + + switch (d->regType) { + case CppType: + return d->extraData.cd->extMetaObject; + case SingletonType: + return d->extraData.sd->extMetaObject; + default: return nullptr; - return d->extraData.cd->extMetaObject; + } } bool QQmlType::isExtendedType() const @@ -976,4 +997,10 @@ QString QQmlType::pendingResolutionName() const return d->extraData.id->inlineComponentName; } +void QQmlType::createProxy(QObject *instance) const +{ + if (!d->metaObjects.isEmpty()) + (void)new QQmlProxyMetaObject(instance, &d->metaObjects); +} + QT_END_NAMESPACE diff --git a/src/qml/qml/qqmltype_p.h b/src/qml/qml/qqmltype_p.h index 0655583e1e..cbbfe955cc 100644 --- a/src/qml/qml/qqmltype_p.h +++ b/src/qml/qml/qqmltype_p.h @@ -201,6 +201,8 @@ public: void setPendingResolutionName(const QString &name); QString pendingResolutionName() const; + void createProxy(QObject *instance) const; + private: friend class QQmlTypePrivate; friend size_t qHash(const QQmlType &t, size_t seed); diff --git a/src/qml/qml/qqmltype_p_p.h b/src/qml/qml/qqmltype_p_p.h index 426b9ced37..2a375baa83 100644 --- a/src/qml/qml/qqmltype_p_p.h +++ b/src/qml/qml/qqmltype_p_p.h @@ -131,6 +131,8 @@ public: struct QQmlSingletonTypeData { QQmlType::SingletonInstanceInfo *singletonInstanceInfo; + QObject *(*extFunc)(QObject *); + const QMetaObject *extMetaObject; }; struct QQmlCompositeTypeData |