aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/qml/doc/src/cppintegration/definetypes.qdoc6
-rw-r--r--src/qml/qml/qqml.h16
-rw-r--r--src/qml/qml/qqmlregistration.h3
-rw-r--r--src/qmltyperegistrar/qmltyperegistrar.cpp17
-rw-r--r--tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp18
-rw-r--r--tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h29
6 files changed, 80 insertions, 9 deletions
diff --git a/src/qml/doc/src/cppintegration/definetypes.qdoc b/src/qml/doc/src/cppintegration/definetypes.qdoc
index 969bf4f7c0..f4b0f51180 100644
--- a/src/qml/doc/src/cppintegration/definetypes.qdoc
+++ b/src/qml/doc/src/cppintegration/definetypes.qdoc
@@ -345,11 +345,13 @@ merged with the original target class when used from within QML. For example:
The \c leftMargin property is a new property added to an existing C++ type, \l
QLineEdit, without modifying its source code.
-The QML_EXTENDED(extended) macro is for registering extended types. The
+The QML_EXTENDED(extension) 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.
+especially the enumerations declared within, as an extension to a type. If the
+type you are extending is itself a namespace, you need to use
+QML_NAMESPACE_EXTENDED(namespace) instead.
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
diff --git a/src/qml/qml/qqml.h b/src/qml/qml/qqml.h
index d82567d26e..b635c2289e 100644
--- a/src/qml/qml/qqml.h
+++ b/src/qml/qml/qqml.h
@@ -790,8 +790,9 @@ inline void qmlRegisterTypesAndRevisions<>(const char *, int, QList<int> *)
inline void qmlRegisterNamespaceAndRevisions(const QMetaObject *metaObject,
const char *uri, int versionMajor,
- QList<int> *qmlTypeIds = nullptr,
- const QMetaObject *classInfoMetaObject = nullptr)
+ QList<int> *qmlTypeIds,
+ const QMetaObject *classInfoMetaObject,
+ const QMetaObject *extensionMetaObject)
{
QQmlPrivate::RegisterTypeAndRevisions type = {
0,
@@ -816,7 +817,7 @@ inline void qmlRegisterNamespaceAndRevisions(const QMetaObject *metaObject,
-1,
nullptr,
- nullptr,
+ extensionMetaObject,
&qmlCreateCustomParser<void>,
qmlTypeIds
@@ -825,6 +826,15 @@ inline void qmlRegisterNamespaceAndRevisions(const QMetaObject *metaObject,
qmlregister(QQmlPrivate::TypeAndRevisionsRegistration, &type);
}
+inline void qmlRegisterNamespaceAndRevisions(const QMetaObject *metaObject,
+ const char *uri, int versionMajor,
+ QList<int> *qmlTypeIds = nullptr,
+ const QMetaObject *classInfoMetaObject = nullptr)
+{
+ qmlRegisterNamespaceAndRevisions(metaObject, uri, versionMajor, qmlTypeIds,
+ classInfoMetaObject, nullptr);
+}
+
int Q_QML_EXPORT qmlTypeId(const char *uri, int versionMajor, int versionMinor, const char *qmlName);
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlregistration.h b/src/qml/qml/qqmlregistration.h
index d2e4b17248..c07cab660a 100644
--- a/src/qml/qml/qqmlregistration.h
+++ b/src/qml/qml/qqmlregistration.h
@@ -118,6 +118,9 @@ QT_BEGIN_NAMESPACE
template<typename T, typename... Args> \
friend void QML_REGISTER_TYPES_AND_REVISIONS(const char *uri, int versionMajor, QList<int> *);
+#define QML_NAMESPACE_EXTENDED(EXTENDED_NAMESPACE) \
+ Q_CLASSINFO("QML.Extended", #EXTENDED_NAMESPACE)
+
#define QML_FOREIGN(FOREIGN_TYPE) \
Q_CLASSINFO("QML.Foreign", #FOREIGN_TYPE) \
using QmlForeignType = FOREIGN_TYPE; \
diff --git a/src/qmltyperegistrar/qmltyperegistrar.cpp b/src/qmltyperegistrar/qmltyperegistrar.cpp
index 914781e737..a74f676a0b 100644
--- a/src/qmltyperegistrar/qmltyperegistrar.cpp
+++ b/src/qmltyperegistrar/qmltyperegistrar.cpp
@@ -220,6 +220,7 @@ int main(int argc, char **argv)
const QString className = classDef[QLatin1String("qualifiedClassName")].toString();
QString targetName = className;
+ QString extendedName;
bool seenQmlElement = false;
const QJsonArray classInfos = classDef.value(QLatin1String("classInfos")).toArray();
for (const QJsonValue v : classInfos) {
@@ -228,6 +229,8 @@ int main(int argc, char **argv)
seenQmlElement = true;
else if (name == QStringLiteral("QML.Foreign"))
targetName = v[QLatin1String("value")].toString();
+ else if (name == QStringLiteral("QML.Extended"))
+ extendedName = v[QStringLiteral("value")].toString();
}
// We want all related metatypes to be registered by name, so that we can look them up
@@ -273,11 +276,17 @@ int main(int argc, char **argv)
qPrintable(targetTypeName));
}
+ auto metaObjectPointer = [](const QString &name) -> QString {
+ return u'&' + name + QStringLiteral("::staticMetaObject");
+ };
+
if (seenQmlElement) {
- fprintf(output, "\n qmlRegisterNamespaceAndRevisions(&%s::staticMetaObject, "
- "\"%s\", %s, nullptr, &%s::staticMetaObject);",
- qPrintable(targetName), qPrintable(module), qPrintable(majorVersion),
- qPrintable(className));
+ fprintf(output, "\n qmlRegisterNamespaceAndRevisions(%s, "
+ "\"%s\", %s, nullptr, %s, %s);",
+ qPrintable(metaObjectPointer(targetName)), qPrintable(module),
+ qPrintable(majorVersion), qPrintable(metaObjectPointer(className)),
+ extendedName.isEmpty() ? "nullptr"
+ : qPrintable(metaObjectPointer(extendedName)));
}
} else {
if (seenQmlElement) {
diff --git a/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp b/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp
index f11f5d6404..1271090c56 100644
--- a/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp
+++ b/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp
@@ -288,4 +288,22 @@ void tst_qmltyperegistrar::namespacesAndValueTypes()
check(QMetaType::fromName("ValueTypeWithEnum2"), QMetaType::fromType<ValueTypeWithEnum2>());
}
+void tst_qmltyperegistrar::namespaceExtendedNamespace()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine);
+ c.setData("import QtQml\n"
+ "import QmlTypeRegistrarTest\n"
+ "QtObject {\n"
+ " property int b: ForeignNamespace.B\n"
+ " property int f: ForeignNamespace.F\n"
+ "}", QUrl());
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer o(c.create());
+ QVERIFY(!o.isNull());
+
+ QCOMPARE(o->property("b").toInt(), int(ExtensionValueType::B));
+ QCOMPARE(o->property("f").toInt(), int(BaseNamespace::F));
+}
+
QTEST_MAIN(tst_qmltyperegistrar)
diff --git a/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h b/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h
index 2a8423c682..d0f3f4d27b 100644
--- a/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h
+++ b/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h
@@ -382,6 +382,34 @@ struct BValueTypeWithEnumForeign2
QML_NAMED_ELEMENT(valueTypeWithEnum2)
};
+
+namespace BaseNamespace
+{
+Q_NAMESPACE
+enum BBB {
+ D, E, F
+};
+Q_ENUM_NS(BBB)
+}
+
+struct ExtensionValueType
+{
+ Q_GADGET
+public:
+ enum EEE {
+ A, B, C
+ };
+ Q_ENUM(EEE)
+};
+
+namespace ForeignNamespace
+{
+Q_NAMESPACE
+QML_FOREIGN_NAMESPACE(BaseNamespace)
+QML_NAMESPACE_EXTENDED(ExtensionValueType)
+QML_ELEMENT
+}
+
class tst_qmltyperegistrar : public QObject
{
Q_OBJECT
@@ -411,6 +439,7 @@ private slots:
void finalProperty();
void parentProperty();
void namespacesAndValueTypes();
+ void namespaceExtendedNamespace();
private:
QByteArray qmltypesData;