aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml')
-rw-r--r--src/qml/doc/src/cppintegration/definetypes.qdoc3
-rw-r--r--src/qml/doc/src/qmlfunctions.qdoc24
-rw-r--r--src/qml/qml/qqml.cpp4
-rw-r--r--src/qml/qml/qqml.h25
-rw-r--r--src/qml/qml/qqmlmetatype.cpp2
-rw-r--r--src/qml/qml/qqmlprivate.h18
-rw-r--r--src/qml/qml/qqmlproxymetaobject.cpp2
-rw-r--r--src/qml/qml/qqmltype.cpp9
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);
}
}