aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2020-09-09 10:34:48 +0200
committerUlf Hermann <ulf.hermann@qt.io>2020-10-02 13:21:09 +0200
commitd621027babff9a30d56ab6af871a465108c9eaba (patch)
tree54a5ccff0410476538929e4ab1f1400075c0df81 /src/qml/qml
parented7719a3af58b9ba36a6fbaccd08c85b78f8a961 (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.cpp6
-rw-r--r--src/qml/qml/qqml.h16
-rw-r--r--src/qml/qml/qqmlengine.cpp4
-rw-r--r--src/qml/qml/qqmlmetatype.cpp39
-rw-r--r--src/qml/qml/qqmlmetatype_p.h4
-rw-r--r--src/qml/qml/qqmlprivate.h13
-rw-r--r--src/qml/qml/qqmltype.cpp11
-rw-r--r--src/qml/qml/qqmltype_p.h2
-rw-r--r--src/qml/qml/qqmltype_p_p.h3
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;