diff options
Diffstat (limited to 'src/qml')
-rw-r--r-- | src/qml/doc/src/cppintegration/definetypes.qdoc | 3 | ||||
-rw-r--r-- | src/qml/doc/src/qmlfunctions.qdoc | 24 | ||||
-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 |
8 files changed, 66 insertions, 21 deletions
diff --git a/src/qml/doc/src/cppintegration/definetypes.qdoc b/src/qml/doc/src/cppintegration/definetypes.qdoc index cbbbd9ba58..5098f74df8 100644 --- a/src/qml/doc/src/cppintegration/definetypes.qdoc +++ b/src/qml/doc/src/cppintegration/definetypes.qdoc @@ -310,6 +310,9 @@ QLineEdit, without modifying its source code. The QML_EXTENDED(extended) macro is for registering extended types. The argument is the name of another class to be used as extension. +You can also use QML_EXTENDED_NAMESPACE(namespace) to register a namespace, and +especially the enumerations declared within, as an extension to a type. + An extension class is a regular QObject, with a constructor that takes a QObject pointer. However, the extension class creation is delayed until the first extended property is accessed. The extension class is created and the target diff --git a/src/qml/doc/src/qmlfunctions.qdoc b/src/qml/doc/src/qmlfunctions.qdoc index c0c481b861..caca58f34a 100644 --- a/src/qml/doc/src/qmlfunctions.qdoc +++ b/src/qml/doc/src/qmlfunctions.qdoc @@ -230,10 +230,24 @@ \relates QQmlEngine Declares that the enclosing type uses \a EXTENDED_TYPE as an extension to - provide further properties and methods in QML. This takes effect if the type + provide further properties, methods, and enumerations in QML. This takes + effect if the type is exposed to QML using a \l QML_ELEMENT or + \l QML_NAMED_ELEMENT() macro. + + \sa QML_ELEMENT, QML_NAMED_ELEMENT(), QML_EXTENDED_NAMEPSACE(), + {Registering Extension Objects} +*/ + +/*! + \macro QML_EXTENDED_NAMESPACE(EXTENDED_NAMESPACE) + \relates QQmlEngine + + Declares that the enclosing type uses \a EXTENDED_NAMESPACE as an extension to + provide further enumerations in QML. This takes effect if the type is exposed to QML using a \l QML_ELEMENT or \l QML_NAMED_ELEMENT() macro. - \sa QML_ELEMENT, QML_NAMED_ELEMENT(), {Registering Extension Objects} + \sa QML_ELEMENT, QML_NAMED_ELEMENT(), QML_EXTENDED(), + {Registering Extension Objects} */ /*! @@ -243,9 +257,9 @@ Declares that any \l QML_ELEMENT, \l QML_NAMED_ELEMENT(), \l QML_ANONYMOUS, \l QML_INTERFACE, \l QML_UNCREATABLE(), \l QML_SINGLETON, \l QML_ADDED_IN_MINOR_VERSION(), \l QML_REMOVED_IN_MINOR_VERSION(), - \l QML_ATTACHED(), or \l QML_EXTENDED() macros in the enclosing C++ type do - not apply to the enclosing type but instead to \a FOREIGN_TYPE. The enclosing - type still needs to be registered with the + \l QML_ATTACHED(), \l QML_EXTENDED(), or \l QML_EXTENDED_NAMESPACE() macros + in the enclosing C++ type do not apply to the enclosing type but instead to + \a FOREIGN_TYPE. The enclosing type still needs to be registered with the \l {The Meta-Object System}{meta object system} using a \l Q_GADGET or \l Q_OBJECT macro. 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); } } |