diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2020-09-09 10:34:48 +0200 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2020-10-02 13:21:09 +0200 |
commit | d621027babff9a30d56ab6af871a465108c9eaba (patch) | |
tree | 54a5ccff0410476538929e4ab1f1400075c0df81 /src/qml/qml | |
parent | ed7719a3af58b9ba36a6fbaccd08c85b78f8a961 (diff) |
V4: Rewrite qv4sequenceobject based on QMetaSequence
This avoids the template explosion and makes the mechanism extendable.
You can now register additional anonymous sequential containers.
Fixes: QTBUG-71574
Task-number: QTBUG-82443
Change-Id: I5b9ed9af1533a3b7df8fc5bb37bbb73b8304e592
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'src/qml/qml')
-rw-r--r-- | src/qml/qml/qqml.cpp | 6 | ||||
-rw-r--r-- | src/qml/qml/qqml.h | 16 | ||||
-rw-r--r-- | src/qml/qml/qqmlengine.cpp | 4 | ||||
-rw-r--r-- | src/qml/qml/qqmlmetatype.cpp | 39 | ||||
-rw-r--r-- | src/qml/qml/qqmlmetatype_p.h | 4 | ||||
-rw-r--r-- | src/qml/qml/qqmlprivate.h | 13 | ||||
-rw-r--r-- | src/qml/qml/qqmltype.cpp | 11 | ||||
-rw-r--r-- | src/qml/qml/qqmltype_p.h | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmltype_p_p.h | 3 |
9 files changed, 96 insertions, 2 deletions
diff --git a/src/qml/qml/qqml.cpp b/src/qml/qml/qqml.cpp index 705017c6de..102bf22df5 100644 --- a/src/qml/qml/qqml.cpp +++ b/src/qml/qml/qqml.cpp @@ -433,6 +433,9 @@ int QQmlPrivate::qmlregister(RegistrationType type, void *data) case CompositeSingletonRegistration: dtype = QQmlMetaType::registerCompositeSingletonType(*reinterpret_cast<RegisterCompositeSingletonType *>(data)); break; + case SequentialContainerRegistration: + dtype = QQmlMetaType::registerSequentialContainer(*reinterpret_cast<RegisterSequentialContainer *>(data)); + break; default: return -1; } @@ -454,6 +457,9 @@ void QQmlPrivate::qmlunregister(RegistrationType type, quintptr data) QQmlMetaType::removeCachedUnitLookupFunction( reinterpret_cast<QmlUnitCacheLookupFunction>(data)); break; + case SequentialContainerRegistration: + QQmlMetaType::unregisterSequentialContainer(data); + break; case TypeRegistration: case InterfaceRegistration: case SingletonRegistration: diff --git a/src/qml/qml/qqml.h b/src/qml/qml/qqml.h index f399924447..758b0a51cf 100644 --- a/src/qml/qml/qqml.h +++ b/src/qml/qml/qqml.h @@ -45,6 +45,7 @@ #include <QtCore/qbytearray.h> #include <QtCore/qmetaobject.h> +#include <QtCore/qmetacontainer.h> #include <QtCore/qversionnumber.h> #define QML_VERSION 0x020000 @@ -758,6 +759,21 @@ inline int qmlRegisterType(const QUrl &url, const char *uri, int versionMajor, i return QQmlPrivate::qmlregister(QQmlPrivate::CompositeRegistration, &type); } +template<typename Container> +inline int qmlRegisterAnonymousSequentialContainer(const char *uri, int versionMajor) +{ + QQmlPrivate::RegisterSequentialContainer type = { + 0, + uri, + QTypeRevision::fromMajorVersion(versionMajor), + nullptr, + QMetaType::fromType<Container>(), + QMetaSequence::fromContainer<Container>() + }; + + return QQmlPrivate::qmlregister(QQmlPrivate::SequentialContainerRegistration, &type); +} + template<class T, class Resolved, class Extended, bool Singleton, bool Interface> struct QmlTypeAndRevisionsRegistration; diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index bff726cb98..f32a2901c6 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -89,6 +89,10 @@ #include <private/qqmlplatform_p.h> #include <private/qqmlloggingcategory_p.h> +#if QT_CONFIG(qml_sequence_object) +#include <private/qv4sequenceobject_p.h> +#endif + #ifdef Q_OS_WIN // for %APPDATA% # include <qt_windows.h> # include <shlobj.h> diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp index e3083ae278..6eaf2063b5 100644 --- a/src/qml/qml/qqmlmetatype.cpp +++ b/src/qml/qml/qqmlmetatype.cpp @@ -389,6 +389,8 @@ QString registrationTypeString(QQmlType::RegistrationType typeType) typeStr = QStringLiteral("singleton type"); else if (typeType == QQmlType::CompositeSingletonType) typeStr = QStringLiteral("composite singleton type"); + else if (typeType == QQmlType::SequentialContainerType) + typeStr = QStringLiteral("sequential container type"); else typeStr = QStringLiteral("type"); return typeStr; @@ -464,8 +466,10 @@ void addTypeToData(QQmlTypePrivate *type, QQmlMetaTypeData *data) if (type->typeId.isValid()) { data->idToType.insert(type->typeId.id(), type); - if (type->typeId.flags() & QMetaType::PointerToQObject) + if (type->typeId.flags() & QMetaType::PointerToQObject + && type->regType != QQmlType::RegistrationType::SequentialContainerType) { data->objects.insert(type->typeId.id()); + } } if (type->listId.isValid()) { @@ -648,6 +652,39 @@ int QQmlMetaType::registerUnitCacheHook( return 0; } +QQmlType QQmlMetaType::registerSequentialContainer( + const QQmlPrivate::RegisterSequentialContainer &container) +{ + if (container.structVersion > 0) + qFatal("qmlRegisterSequenceContainer(): Cannot mix incompatible QML versions."); + + QQmlMetaTypeDataPtr data; + + if (!checkRegistration(QQmlType::SequentialContainerType, data, container.uri, QString(), + container.version, {})) { + return QQmlType(); + } + + QQmlTypePrivate *priv = new QQmlTypePrivate(QQmlType::SequentialContainerType); + + data->registerType(priv); + priv->setName(QString::fromUtf8(container.uri), QString()); + priv->version = container.version; + priv->typeId = container.typeId; + *priv->extraData.ld = container.metaSequence; + + addTypeToData(priv, data); + if (!container.typeId.isValid()) + data->idToType.insert(priv->typeId.id(), priv); + + return QQmlType(priv); +} + +void QQmlMetaType::unregisterSequentialContainer(int id) +{ + unregisterType(id); +} + bool QQmlMetaType::protectModule(const QString &uri, QTypeRevision version, bool protectAllVersions) { QQmlMetaTypeDataPtr data; diff --git a/src/qml/qml/qqmlmetatype_p.h b/src/qml/qml/qqmlmetatype_p.h index b1fe58af6e..e9279b6d97 100644 --- a/src/qml/qml/qqmlmetatype_p.h +++ b/src/qml/qml/qqmlmetatype_p.h @@ -242,6 +242,10 @@ public: static int registerAutoParentFunction(const QQmlPrivate::RegisterAutoParent &autoparent); static void unregisterAutoParentFunction(const QQmlPrivate::AutoParentFunction &function); + static QQmlType registerSequentialContainer( + const QQmlPrivate::RegisterSequentialContainer &sequenceRegistration); + static void unregisterSequentialContainer(int id); + static int registerUnitCacheHook(const QQmlPrivate::RegisterQmlUnitCacheHook &hookRegistration); static void clearTypeRegistrations(); diff --git a/src/qml/qml/qqmlprivate.h b/src/qml/qml/qqmlprivate.h index 91b8eb5283..00d277a9f7 100644 --- a/src/qml/qml/qqmlprivate.h +++ b/src/qml/qml/qqmlprivate.h @@ -66,6 +66,7 @@ #include <QtCore/qversionnumber.h> #include <QtCore/qmetaobject.h> +#include <QtCore/qmetacontainer.h> #include <QtCore/qdebug.h> QT_BEGIN_NAMESPACE @@ -460,6 +461,15 @@ namespace QQmlPrivate const char *typeName; }; + struct RegisterSequentialContainer { + int structVersion; + const char *uri; + QTypeRevision version; + const char *typeName; + QMetaType typeId; + QMetaSequence metaSequence; + }; + struct AOTCompiledFunction { int index; QMetaType returnType; @@ -487,7 +497,8 @@ namespace QQmlPrivate CompositeSingletonRegistration = 5, QmlUnitCacheHookRegistration = 6, TypeAndRevisionsRegistration = 7, - SingletonAndRevisionsRegistration = 8 + SingletonAndRevisionsRegistration = 8, + SequentialContainerRegistration = 9, }; int Q_QML_EXPORT qmlregister(RegistrationType, void *); diff --git a/src/qml/qml/qqmltype.cpp b/src/qml/qml/qqmltype.cpp index 5a685ea646..bea69166c6 100644 --- a/src/qml/qml/qqmltype.cpp +++ b/src/qml/qml/qqmltype.cpp @@ -87,6 +87,9 @@ QQmlTypePrivate::QQmlTypePrivate(QQmlType::RegistrationType type) case QQmlType::InlineComponentType: extraData.id = new QQmlInlineTypeData; break; + case QQmlType::SequentialContainerType: + extraData.ld = new QQmlSequenceTypeData; + break; default: qFatal("QQmlTypePrivate Internal Error."); } } @@ -112,6 +115,9 @@ QQmlTypePrivate::~QQmlTypePrivate() case QQmlType::InlineComponentType: delete extraData.id; break; + case QQmlType::SequentialContainerType: + delete extraData.ld; + break; default: //Also InterfaceType, because it has no extra data break; } @@ -586,6 +592,11 @@ bool QQmlType::isQJSValueSingleton() const return d && d->regType == SingletonType && d->extraData.sd->singletonInstanceInfo->scriptCallback; } +bool QQmlType::isSequentialContainer() const +{ + return d && d->regType == SequentialContainerType; +} + QMetaType QQmlType::typeId() const { return d ? d->typeId : QMetaType{}; diff --git a/src/qml/qml/qqmltype_p.h b/src/qml/qml/qqmltype_p.h index c1964cf597..025a1e5555 100644 --- a/src/qml/qml/qqmltype_p.h +++ b/src/qml/qml/qqmltype_p.h @@ -125,6 +125,7 @@ public: bool isCompositeSingleton() const; bool isQObjectSingleton() const; bool isQJSValueSingleton() const; + bool isSequentialContainer() const; QMetaType typeId() const; QMetaType qListTypeId() const; @@ -184,6 +185,7 @@ public: CompositeType = 3, CompositeSingletonType = 4, InlineComponentType = 5, + SequentialContainerType = 6, AnyRegistrationType = 255 }; diff --git a/src/qml/qml/qqmltype_p_p.h b/src/qml/qml/qqmltype_p_p.h index a66b889214..cdd46aee7c 100644 --- a/src/qml/qml/qqmltype_p_p.h +++ b/src/qml/qml/qqmltype_p_p.h @@ -149,11 +149,14 @@ public: int objectId = -1; }; + using QQmlSequenceTypeData = QMetaSequence; + union extraData { QQmlCppTypeData* cd; QQmlSingletonTypeData* sd; QQmlCompositeTypeData* fd; QQmlInlineTypeData* id; + QQmlSequenceTypeData* ld; } extraData; const char *iid; |