diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2020-10-28 16:48:53 +0100 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2020-11-02 14:00:17 +0100 |
commit | 6f968781c4c8a278a7743b0904fb2bdf4c6ddf1a (patch) | |
tree | 0d5944f74c10bf3223cb374234c7f6d78706714f /src/qml/qml | |
parent | 2b99430671e37427a990973df37e62ad8cdebe8b (diff) |
QML: Allow namespaces as extensions to types
This way we can access the enums of namespaces as properties of the
primary type. This is achieved by:
1. Making enums of extended types available in the base type
2. Allowing the extension to be specified as plain metaObject rather
than as type name.
3. Refraining from creating the extension if the create function does
not exist.
The goal of this is to declare the Qt namespace in a civilized way, but
will also help with cleaning up the QtQuick value types and their enums.
Change-Id: I13399741d30ce38d1bff753cfa1b11e72ccfbf6a
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'src/qml/qml')
-rw-r--r-- | src/qml/qml/qqml.cpp | 4 | ||||
-rw-r--r-- | src/qml/qml/qqml.h | 25 | ||||
-rw-r--r-- | src/qml/qml/qqmlmetatype.cpp | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmlprivate.h | 18 | ||||
-rw-r--r-- | src/qml/qml/qqmlproxymetaobject.cpp | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmltype.cpp | 9 |
6 files changed, 44 insertions, 16 deletions
diff --git a/src/qml/qml/qqml.cpp b/src/qml/qml/qqml.cpp index e61cf417e3..5dd245f2a3 100644 --- a/src/qml/qml/qqml.cpp +++ b/src/qml/qml/qqml.cpp @@ -483,7 +483,7 @@ namespace QQmlPrivate { template<> void qmlRegisterTypeAndRevisions<QQmlTypeNotAvailable, void>( const char *uri, int versionMajor, const QMetaObject *classInfoMetaObject, - QVector<int> *qmlTypeIds) + QVector<int> *qmlTypeIds, const QMetaObject *extension) { using T = QQmlTypeNotAvailable; @@ -509,7 +509,7 @@ namespace QQmlPrivate { StaticCastSelector<T, QQmlPropertyValueSource>::cast(), StaticCastSelector<T, QQmlPropertyValueInterceptor>::cast(), - nullptr, nullptr, qmlCreateCustomParser<T>, qmlTypeIds + nullptr, extension, qmlCreateCustomParser<T>, qmlTypeIds }; qmlregister(TypeAndRevisionsRegistration, &type); diff --git a/src/qml/qml/qqml.h b/src/qml/qml/qqml.h index be482c5277..9118b42390 100644 --- a/src/qml/qml/qqml.h +++ b/src/qml/qml/qqml.h @@ -119,6 +119,13 @@ template<typename T, typename... Args> \ friend void QML_REGISTER_TYPES_AND_REVISIONS(const char *uri, int versionMajor, QList<int> *); +#define QML_EXTENDED_NAMESPACE(EXTENDED_NAMESPACE) \ + Q_CLASSINFO("QML.Extended", #EXTENDED_NAMESPACE) \ + static constexpr const QMetaObject *qmlExtendedNamespace() { return &EXTENDED_NAMESPACE::staticMetaObject; } \ + template<class, class> friend struct QML_PRIVATE_NAMESPACE::QmlExtendedNamespace; \ + template<typename T, typename... Args> \ + friend void QML_REGISTER_TYPES_AND_REVISIONS(const char *uri, int versionMajor, QList<int> *); + #define QML_FOREIGN(FOREIGN_TYPE) \ Q_CLASSINFO("QML.Foreign", #FOREIGN_TYPE) \ using QmlForeignType = FOREIGN_TYPE; \ @@ -792,25 +799,30 @@ struct QmlTypeAndRevisionsRegistration; template<class T, class Resolved, class Extended> struct QmlTypeAndRevisionsRegistration<T, Resolved, Extended, false, false> { - static void registerTypeAndRevisions(const char *uri, int versionMajor, QList<int> *qmlTypeIds) + static void registerTypeAndRevisions(const char *uri, int versionMajor, QList<int> *qmlTypeIds, + const QMetaObject *extension) { QQmlPrivate::qmlRegisterTypeAndRevisions<Resolved, Extended>( - uri, versionMajor, QQmlPrivate::StaticMetaObject<T>::staticMetaObject(), qmlTypeIds); + uri, versionMajor, QQmlPrivate::StaticMetaObject<T>::staticMetaObject(), + qmlTypeIds, extension); } }; template<class T, class Resolved> struct QmlTypeAndRevisionsRegistration<T, Resolved, void, true, false> { - static void registerTypeAndRevisions(const char *uri, int versionMajor, QList<int> *qmlTypeIds) + static void registerTypeAndRevisions(const char *uri, int versionMajor, QList<int> *qmlTypeIds, + const QMetaObject *) { QQmlPrivate::qmlRegisterSingletonAndRevisions<Resolved>( - uri, versionMajor, QQmlPrivate::StaticMetaObject<T>::staticMetaObject(), qmlTypeIds); + uri, versionMajor, QQmlPrivate::StaticMetaObject<T>::staticMetaObject(), + qmlTypeIds); } }; template<class T, class Resolved> struct QmlTypeAndRevisionsRegistration<T, Resolved, void, false, true> { - static void registerTypeAndRevisions(const char *uri, int versionMajor, QList<int> *qmlTypeIds) + static void registerTypeAndRevisions(const char *uri, int versionMajor, QList<int> *qmlTypeIds, + const QMetaObject *) { const int id = qmlRegisterInterface<Resolved>(uri, versionMajor); if (qmlTypeIds) @@ -830,7 +842,8 @@ void qmlRegisterTypesAndRevisions(const char *uri, int versionMajor, QList<int> typename QQmlPrivate::QmlExtended<T>::Type, QQmlPrivate::QmlSingleton<T>::Value, QQmlPrivate::QmlInterface<T>::Value> - ::registerTypeAndRevisions(uri, versionMajor, qmlTypeIds); + ::registerTypeAndRevisions(uri, versionMajor, qmlTypeIds, + QQmlPrivate::QmlExtendedNamespace<T>::metaObject()); qmlRegisterTypesAndRevisions<Args...>(uri, versionMajor, qmlTypeIds); } diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp index ba7ffe2a91..df5c4d89c5 100644 --- a/src/qml/qml/qqmlmetatype.cpp +++ b/src/qml/qml/qqmlmetatype.cpp @@ -1610,7 +1610,7 @@ QList<QQmlProxyMetaObject::ProxyData> QQmlMetaType::proxyData(const QMetaObject QQmlTypePrivate *t = data->metaObjectToType.value(mo); if (t) { if (t->regType == QQmlType::CppType) { - if (t->extraData.cd->extFunc) { + if (t->extraData.cd->extMetaObject) { QMetaObjectBuilder builder; clone(builder, t->extraData.cd->extMetaObject, t->baseMetaObject, baseMetaObject); builder.setFlags(MetaObjectFlag::DynamicMetaObject); diff --git a/src/qml/qml/qqmlprivate.h b/src/qml/qml/qqmlprivate.h index 6639ecbd26..2beeacd20f 100644 --- a/src/qml/qml/qqmlprivate.h +++ b/src/qml/qml/qqmlprivate.h @@ -625,6 +625,18 @@ namespace QQmlPrivate }; template<class T, class = std::void_t<>> + struct QmlExtendedNamespace + { + static constexpr const QMetaObject *metaObject() { return nullptr; } + }; + + template<class T> + struct QmlExtendedNamespace<T, std::void_t<decltype(T::qmlExtendedNamespace())>> + { + static constexpr const QMetaObject *metaObject() { return T::qmlExtendedNamespace(); } + }; + + template<class T, class = std::void_t<>> struct QmlResolved { using Type = T; @@ -718,7 +730,7 @@ namespace QQmlPrivate template<typename T, typename E> void qmlRegisterTypeAndRevisions(const char *uri, int versionMajor, const QMetaObject *classInfoMetaObject, - QVector<int> *qmlTypeIds) + QVector<int> *qmlTypeIds, const QMetaObject *extension) { RegisterTypeAndRevisions type = { 0, @@ -742,7 +754,7 @@ namespace QQmlPrivate StaticCastSelector<T, QQmlPropertyValueInterceptor>::cast(), ExtendedType<E>::createParent, - ExtendedType<E>::staticMetaObject(), + extension ? extension : ExtendedType<E>::staticMetaObject(), &qmlCreateCustomParser<T>, qmlTypeIds @@ -754,7 +766,7 @@ namespace QQmlPrivate template<> void Q_QML_EXPORT qmlRegisterTypeAndRevisions<QQmlTypeNotAvailable, void>( const char *uri, int versionMajor, const QMetaObject *classInfoMetaObject, - QVector<int> *qmlTypeIds); + QVector<int> *qmlTypeIds, const QMetaObject *); } // namespace QQmlPrivate diff --git a/src/qml/qml/qqmlproxymetaobject.cpp b/src/qml/qml/qqmlproxymetaobject.cpp index e1500f70fb..c5cb2ec059 100644 --- a/src/qml/qml/qqmlproxymetaobject.cpp +++ b/src/qml/qml/qqmlproxymetaobject.cpp @@ -83,6 +83,8 @@ int QQmlProxyMetaObject::metaCall(QObject *o, QMetaObject::Call c, int id, void } if (!proxies[ii]) { + if (!data.createFunc) + continue; QObject *proxy = data.createFunc(object); const QMetaObject *metaObject = proxy->metaObject(); proxies[ii] = proxy; diff --git a/src/qml/qml/qqmltype.cpp b/src/qml/qml/qqmltype.cpp index a4f7c3f8b5..e5b3653d2d 100644 --- a/src/qml/qml/qqmltype.cpp +++ b/src/qml/qml/qqmltype.cpp @@ -217,7 +217,7 @@ void QQmlTypePrivate::init() const if (regType == QQmlType::CppType) { // Setup extended meta object // XXX - very inefficient - if (extraData.cd->extFunc) { + if (extraData.cd->extMetaObject) { QMetaObjectBuilder builder; QQmlMetaType::clone(builder, extraData.cd->extMetaObject, extraData.cd->extMetaObject, extraData.cd->extMetaObject); @@ -269,14 +269,15 @@ void QQmlTypePrivate::initEnums(QQmlEnginePrivate *engine) const ? compositePropertyCache(engine) : nullptr; + // beware: It could be a singleton type without metaobject const QMetaObject *metaObject = !isEnumFromBaseSetup.loadAcquire() - ? baseMetaObject // beware: It could be a singleton type without metaobject + ? baseMetaObject : nullptr; if (!cache && !metaObject) return; - init(); + init(); // init() can add to the metaObjects list. Therefore, check metaObjects only below QMutexLocker lock(QQmlMetaType::typeRegistrationLock()); @@ -286,7 +287,7 @@ void QQmlTypePrivate::initEnums(QQmlEnginePrivate *engine) const } if (metaObject) { - insertEnums(metaObject); + insertEnums(metaObjects.isEmpty() ? baseMetaObject : metaObjects.constFirst().metaObject); isEnumFromBaseSetup.storeRelease(true); } } |