From f0908255c9921371d886eff0b8ce245929b50d88 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Fri, 6 Nov 2020 15:13:27 +0100 Subject: QtQml: Integrate sequences with registration macros You get to write QML_SEQUENTIAL_CONTAINER(value_type) now, and qmltyperegistrar will generate a sensible registration call from that. A registration might look like this: struct MyStringListForeign { Q_GADGET QML_ANONYMOUS QML_SEQUENTIAL_CONTAINER(QString) QML_FOREIGN(MyStringList) QML_ADDED_IN_VERSION(3, 1) }; It's unfortunate that we need to use a metaobject to transfer all of this information, but there is no other sensible way. Transform the containers defined in qv4sequenceobject.cpp to use the new style, and move them out of the builtins, into QtQml. Recognize that only one of them was ever tested, and add tests for the rest. Task-number: QTBUG-82443 Change-Id: I3a30f9e27266bb575eea26c5daf5dad1ec461cc5 Reviewed-by: Fabian Kosmale --- src/qmltyperegistrar/metatypesjsonprocessor.cpp | 9 ++++--- src/qmltyperegistrar/qmltypesclassdescription.cpp | 29 ++++++++++++++++------- src/qmltyperegistrar/qmltypesclassdescription.h | 5 ++-- src/qmltyperegistrar/qmltypescreator.cpp | 3 +++ 4 files changed, 32 insertions(+), 14 deletions(-) (limited to 'src/qmltyperegistrar') diff --git a/src/qmltyperegistrar/metatypesjsonprocessor.cpp b/src/qmltyperegistrar/metatypesjsonprocessor.cpp index f71a94c67d..e4b9c32b8b 100644 --- a/src/qmltyperegistrar/metatypesjsonprocessor.cpp +++ b/src/qmltyperegistrar/metatypesjsonprocessor.cpp @@ -153,6 +153,7 @@ QVector MetaTypesJsonProcessor::foreignRelatedTypes() const const QLatin1String qmlNamePrefix("QML."); const QLatin1String qmlForeignName("QML.Foreign"); const QLatin1String qmlAttachedName("QML.Attached"); + const QLatin1String qmlSequenceName("QML.Sequence"); const QLatin1String valueKey("value"); const QLatin1String superClassesKey("superClasses"); const QLatin1String accessKey("access"); @@ -214,9 +215,10 @@ QVector MetaTypesJsonProcessor::foreignRelatedTypes() const const auto classInfos = classDef.value(classInfosKey).toArray(); for (const QJsonValue classInfo : classInfos) { const QJsonObject obj = classInfo.toObject(); - if (obj.value(nameKey).toString() == qmlAttachedName) { + const QString objNameValue = obj.value(nameKey).toString(); + if (objNameValue == qmlAttachedName || objNameValue == qmlSequenceName) { addType(obj.value(valueKey).toString()); - } else if (obj.value(nameKey).toString() == qmlForeignName) { + } else if (objNameValue == qmlForeignName) { const QString foreignClassName = obj.value(valueKey).toString(); if (const QJsonObject *other = QmlTypesClassDescription::findType( m_foreignTypes, foreignClassName)) { @@ -230,7 +232,8 @@ QVector MetaTypesJsonProcessor::foreignRelatedTypes() const const auto otherClassInfos = other->value(classInfosKey).toArray(); for (const QJsonValue otherClassInfo : otherClassInfos) { const QJsonObject obj = otherClassInfo.toObject(); - if (obj.value(nameKey).toString() == qmlAttachedName) { + const QString objNameValue = obj.value(nameKey).toString(); + if (objNameValue == qmlAttachedName || objNameValue == qmlSequenceName) { addType(obj.value(valueKey).toString()); break; } diff --git a/src/qmltyperegistrar/qmltypesclassdescription.cpp b/src/qmltyperegistrar/qmltypesclassdescription.cpp index 20f5d4c46a..94cfd2c2a4 100644 --- a/src/qmltyperegistrar/qmltypesclassdescription.cpp +++ b/src/qmltyperegistrar/qmltypesclassdescription.cpp @@ -99,7 +99,11 @@ void QmlTypesClassDescription::collect(const QJsonObject *classDef, } else if (name == QLatin1String("QML.Creatable")) { isCreatable = (value != QLatin1String("false")); } else if (name == QLatin1String("QML.Attached")) { - collectAttached(value, types, foreign, defaultRevision); + attachedType = value; + collectRelated(value, types, foreign, defaultRevision); + } else if (name == QLatin1String("QML.Sequence")) { + sequenceValueType = value; + collectRelated(value, types, foreign, defaultRevision); } else if (name == QLatin1String("QML.Singleton")) { if (value == QLatin1String("true")) isSingleton = true; @@ -112,10 +116,15 @@ void QmlTypesClassDescription::collect(const QJsonObject *classDef, const QJsonObject obj = classInfo.toObject(); const QString foreignName = obj[QLatin1String("name")].toString(); const QString foreignValue = obj[QLatin1String("value")].toString(); - if (defaultProp.isEmpty() && foreignName == QLatin1String("DefaultProperty")) + if (defaultProp.isEmpty() && foreignName == QLatin1String("DefaultProperty")) { defaultProp = foreignValue; - else if (foreignName == QLatin1String("QML.Attached")) - collectAttached(foreignValue, types, foreign, defaultRevision); + } else if (foreignName == QLatin1String("QML.Attached")) { + attachedType = foreignValue; + collectRelated(foreignValue, types, foreign, defaultRevision); + } else if (foreignName == QLatin1String("QML.Sequence")) { + sequenceValueType = foreignValue; + collectRelated(foreignValue, types, foreign, defaultRevision); + } } } else { // The foreign type does not have a meta object: We only override the name. @@ -176,7 +185,10 @@ void QmlTypesClassDescription::collect(const QJsonObject *classDef, if (className.isEmpty() && mode == TopLevel) className = classDef->value(QLatin1String("qualifiedClassName")).toString(); - if (classDef->value(QLatin1String("object")).toBool()) { + if (!sequenceValueType.isEmpty()) { + isCreatable = false; + accessSemantics = QLatin1String("sequence"); + } else if (classDef->value(QLatin1String("object")).toBool()) { accessSemantics = QLatin1String("reference"); } else { isCreatable = false; @@ -186,14 +198,13 @@ void QmlTypesClassDescription::collect(const QJsonObject *classDef, } } -void QmlTypesClassDescription::collectAttached(const QString &attached, +void QmlTypesClassDescription::collectRelated(const QString &related, const QVector &types, const QVector &foreign, QTypeRevision defaultRevision) { - attachedType = attached; - if (const QJsonObject *other = findType(types, attachedType)) + if (const QJsonObject *other = findType(types, related)) collect(other, types, foreign, AttachedType, defaultRevision); - else if (const QJsonObject *other = findType(foreign, attachedType)) + else if (const QJsonObject *other = findType(foreign, related)) collect(other, types, foreign, AttachedType, defaultRevision); } diff --git a/src/qmltyperegistrar/qmltypesclassdescription.h b/src/qmltyperegistrar/qmltypesclassdescription.h index 17235c58eb..7e496159ff 100644 --- a/src/qmltyperegistrar/qmltypesclassdescription.h +++ b/src/qmltyperegistrar/qmltypesclassdescription.h @@ -44,6 +44,7 @@ struct QmlTypesClassDescription QString defaultProp; QString superClass; QString attachedType; + QString sequenceValueType; QString accessSemantics; QList revisions; QTypeRevision addedInRevision; @@ -61,8 +62,8 @@ struct QmlTypesClassDescription void collect(const QJsonObject *classDef, const QVector &types, const QVector &foreign, CollectMode mode, QTypeRevision defaultRevision); - void collectAttached(const QString &attached, const QVector &types, - const QVector &foreign, QTypeRevision defaultRevision); + void collectRelated(const QString &related, const QVector &types, + const QVector &foreign, QTypeRevision defaultRevision); static const QJsonObject *findType(const QVector &types, const QString &name); }; diff --git a/src/qmltyperegistrar/qmltypescreator.cpp b/src/qmltyperegistrar/qmltypescreator.cpp index 50980685e9..9e1e757b69 100644 --- a/src/qmltyperegistrar/qmltypescreator.cpp +++ b/src/qmltyperegistrar/qmltypescreator.cpp @@ -58,6 +58,9 @@ void QmlTypesCreator::writeClassProperties(const QmlTypesClassDescription &colle if (!collector.superClass.isEmpty()) m_qml.writeScriptBinding(QLatin1String("prototype"), enquote(collector.superClass)); + if (!collector.sequenceValueType.isEmpty()) + m_qml.writeScriptBinding(QLatin1String("valueType"), enquote(collector.sequenceValueType)); + if (collector.elementName.isEmpty()) return; -- cgit v1.2.3