diff options
Diffstat (limited to 'src/qml')
-rw-r--r-- | src/qml/jsruntime/qv4engine.cpp | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4sequenceobject.cpp | 33 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4sequenceobject_p.h | 46 | ||||
-rw-r--r-- | src/qml/qml/qqml.cpp | 43 | ||||
-rw-r--r-- | src/qml/qml/qqml.h | 33 | ||||
-rw-r--r-- | src/qml/qml/qqmlmetatype.cpp | 6 | ||||
-rw-r--r-- | src/qml/qml/qqmlprivate.h | 46 |
7 files changed, 165 insertions, 44 deletions
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index fe34207ddc..b09f874ef3 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -709,8 +709,6 @@ ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine) static_cast<VariantPrototype *>(variantPrototype())->init(); #if QT_CONFIG(qml_sequence_object) - static const bool registered = QV4::SequencePrototype::registerDefaultTypes(); - Q_UNUSED(registered); sequencePrototype()->cast<SequencePrototype>()->init(); #endif diff --git a/src/qml/jsruntime/qv4sequenceobject.cpp b/src/qml/jsruntime/qv4sequenceobject.cpp index 5c7f8289f2..73fa2385fd 100644 --- a/src/qml/jsruntime/qv4sequenceobject.cpp +++ b/src/qml/jsruntime/qv4sequenceobject.cpp @@ -37,7 +37,6 @@ ** ****************************************************************************/ -#include <QtQml/qqml.h> #include <QtCore/qsequentialiterable.h> #include "qv4sequenceobject_p.h" @@ -51,10 +50,6 @@ #include "qv4objectiterator_p.h" #include <private/qqmlmetatype_p.h> #include <private/qqmltype_p_p.h> -#if QT_CONFIG(qml_itemmodel) -#include <private/qqmlmodelindexvaluetype_p.h> -#include <QtCore/qabstractitemmodel.h> -#endif #include <algorithm> @@ -581,34 +576,6 @@ namespace QV4 { DEFINE_OBJECT_VTABLE(QV4Sequence); } - -template<typename SequenceType> -void registerSequenceType() -{ - qRegisterMetaType<SequenceType>(); - qmlRegisterAnonymousSequentialContainer<SequenceType>("QML", 1); -} - -bool SequencePrototype::registerDefaultTypes() -{ - registerSequenceType<std::vector<int>>(); - registerSequenceType<std::vector<qreal>>(); - registerSequenceType<std::vector<bool>>(); - registerSequenceType<QList<int>>(); - registerSequenceType<QList<qreal>>(); - registerSequenceType<QList<bool>>(); - registerSequenceType<QStringList>(); - registerSequenceType<std::vector<QString>>(); - registerSequenceType<QList<QUrl>>(); - registerSequenceType<std::vector<QUrl>>(); -#if QT_CONFIG(qml_itemmodel) - registerSequenceType<QModelIndexList>(); - registerSequenceType<std::vector<QModelIndex>>(); - registerSequenceType<QItemSelection>(); -#endif - return true; -} - void SequencePrototype::init() { defineDefaultProperty(QStringLiteral("sort"), method_sort, 1); diff --git a/src/qml/jsruntime/qv4sequenceobject_p.h b/src/qml/jsruntime/qv4sequenceobject_p.h index 6229a4b5ec..9143430872 100644 --- a/src/qml/jsruntime/qv4sequenceobject_p.h +++ b/src/qml/jsruntime/qv4sequenceobject_p.h @@ -53,12 +53,18 @@ #include <QtCore/qglobal.h> #include <QtCore/qvariant.h> +#include <QtQml/qqml.h> #include "qv4value_p.h" #include "qv4object_p.h" #include "qv4context_p.h" #include "qv4string_p.h" +#if QT_CONFIG(qml_itemmodel) +#include <private/qqmlmodelindexvaluetype_p.h> +#include <QtCore/qabstractitemmodel.h> +#endif + QT_REQUIRE_CONFIG(qml_sequence_object); QT_BEGIN_NAMESPACE @@ -68,7 +74,6 @@ namespace QV4 { struct Q_QML_PRIVATE_EXPORT SequencePrototype : public QV4::Object { V4_PROTOTYPE(arrayPrototype) - static bool registerDefaultTypes(); void init(); static ReturnedValue method_valueOf(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); @@ -84,6 +89,45 @@ struct Q_QML_PRIVATE_EXPORT SequencePrototype : public QV4::Object } +#define QT_DECLARE_SEQUENTIAL_CONTAINER(LOCAL, FOREIGN, VALUE) \ + struct LOCAL \ + { \ + Q_GADGET \ + QML_ANONYMOUS \ + QML_SEQUENTIAL_CONTAINER(VALUE) \ + QML_FOREIGN(FOREIGN) \ + QML_ADDED_IN_VERSION(2, 0) \ + } + +// We use the original QT_COORD_TYPE name because that will match up with relevant other +// types in plugins.qmltypes (if you use either float or double, that is; otherwise you're +// on your own). +#ifdef QT_COORD_TYPE +QT_DECLARE_SEQUENTIAL_CONTAINER(QStdRealVectorForeign, std::vector<qreal>, QT_COORD_TYPE); +QT_DECLARE_SEQUENTIAL_CONTAINER(QRealListForeign, QList<qreal>, QT_COORD_TYPE); +#else +QT_DECLARE_SEQUENTIAL_CONTAINER(QRealStdVectorForeign, std::vector<qreal>, double); +QT_DECLARE_SEQUENTIAL_CONTAINER(QRealListForeign, QList<qreal>, double); +#endif + +QT_DECLARE_SEQUENTIAL_CONTAINER(QIntStdVectorForeign, std::vector<int>, int); +QT_DECLARE_SEQUENTIAL_CONTAINER(QBoolStdVectorForeign, std::vector<bool>, bool); +QT_DECLARE_SEQUENTIAL_CONTAINER(QStringStdVectorForeign, std::vector<QString>, QString); +QT_DECLARE_SEQUENTIAL_CONTAINER(QUrlStdVectorForeign, std::vector<QUrl>, QUrl); + +QT_DECLARE_SEQUENTIAL_CONTAINER(QIntListForeign, QList<int>, int); +QT_DECLARE_SEQUENTIAL_CONTAINER(QBoolListForeign, QList<bool>, bool); +QT_DECLARE_SEQUENTIAL_CONTAINER(QStringListForeign, QStringList, QString); +QT_DECLARE_SEQUENTIAL_CONTAINER(QUrlListForeign, QList<QUrl>, QUrl); + +#if QT_CONFIG(qml_itemmodel) +QT_DECLARE_SEQUENTIAL_CONTAINER(QModelIndexListForeign, QModelIndexList, QModelIndex); +QT_DECLARE_SEQUENTIAL_CONTAINER(QModelIndexStdVectorForeign, std::vector<QModelIndex>, QModelIndex); +QT_DECLARE_SEQUENTIAL_CONTAINER(QItemSelectionForeign, QItemSelection, QItemSelectionRange); +#endif + +#undef QT_DECLARE_SEQUENTIAL_CONTAINER + QT_END_NAMESPACE #endif // QV4SEQUENCEWRAPPER_P_H diff --git a/src/qml/qml/qqml.cpp b/src/qml/qml/qqml.cpp index 20608a60e4..40e629284b 100644 --- a/src/qml/qml/qqml.cpp +++ b/src/qml/qml/qqml.cpp @@ -421,6 +421,48 @@ int QQmlPrivate::qmlregister(RegistrationType type, void *data) } break; } + case SequentialContainerAndRevisionsRegistration: { + const RegisterSequentialContainerAndRevisions &type + = *reinterpret_cast<RegisterSequentialContainerAndRevisions *>(data); + const char *elementName = classElementName(type.classInfoMetaObject); + RegisterSequentialContainer revisionRegistration = { + 0, + type.uri, + type.version, + elementName, + type.typeId, + type.metaSequence, + QTypeRevision() + }; + + const QTypeRevision added = revisionClassInfo( + type.classInfoMetaObject, "QML.AddedInVersion", + QTypeRevision::fromMinorVersion(0)); + const QTypeRevision removed = revisionClassInfo( + type.classInfoMetaObject, "QML.RemovedInVersion"); + + QVector<QTypeRevision> revisions = { added }; + uniqueRevisions(&revisions, type.version, added); + + for (QTypeRevision revision : qAsConst(revisions)) { + if (revision < added) + continue; + if (revision.hasMajorVersion() && revision.majorVersion() > type.version.majorVersion()) + break; + + // When removed, we still add revisions, but anonymous ones + if (removed.isValid() && !(revision < removed)) + revisionRegistration.typeName = nullptr; + else + revisionRegistration.typeName = elementName; + + assignVersions(&revisionRegistration, revision, type.version); + const int id = qmlregister(SequentialContainerRegistration, &revisionRegistration); + if (type.qmlTypeIds) + type.qmlTypeIds->append(id); + } + break; + } case TypeRegistration: dtype = QQmlMetaType::registerType(*reinterpret_cast<RegisterType *>(data)); break; @@ -472,6 +514,7 @@ void QQmlPrivate::qmlunregister(RegistrationType type, quintptr data) break; case TypeAndRevisionsRegistration: case SingletonAndRevisionsRegistration: + case SequentialContainerAndRevisionsRegistration: // Currently unnecessary. We'd need a special data structure to hold // URI + majorVersion and then we'd iterate the minor versions, look up the // associated QQmlType objects by uri/elementName/major/minor and qmlunregister diff --git a/src/qml/qml/qqml.h b/src/qml/qml/qqml.h index 75f7ae5f06..7f0c81c514 100644 --- a/src/qml/qml/qqml.h +++ b/src/qml/qml/qqml.h @@ -94,6 +94,14 @@ template<typename T, typename... Args> \ friend void QML_REGISTER_TYPES_AND_REVISIONS(const char *uri, int versionMajor, QList<int> *); +#define QML_SEQUENTIAL_CONTAINER(VALUE_TYPE) \ + Q_CLASSINFO("QML.Sequence", #VALUE_TYPE) \ + using QmlSequenceValueType = VALUE_TYPE; \ + enum class QmlIsSequence {yes = true}; \ + template<typename, typename> friend struct QML_PRIVATE_NAMESPACE::QmlSequence; \ + template<typename T, typename... Args> \ + friend void QML_REGISTER_TYPES_AND_REVISIONS(const char *uri, int versionMajor, QList<int> *); + #define QML_ADDED_IN_MINOR_VERSION(VERSION) \ Q_CLASSINFO("QML.AddedInVersion", Q_REVISION(VERSION)) @@ -792,17 +800,18 @@ inline int qmlRegisterAnonymousSequentialContainer(const char *uri, int versionM QTypeRevision::fromMajorVersion(versionMajor), nullptr, QMetaType::fromType<Container>(), - QMetaSequence::fromContainer<Container>() + QMetaSequence::fromContainer<Container>(), + QTypeRevision::zero() }; return QQmlPrivate::qmlregister(QQmlPrivate::SequentialContainerRegistration, &type); } -template<class T, class Resolved, class Extended, bool Singleton, bool Interface> +template<class T, class Resolved, class Extended, bool Singleton, bool Interface, bool Sequence> struct QmlTypeAndRevisionsRegistration; template<class T, class Resolved, class Extended> -struct QmlTypeAndRevisionsRegistration<T, Resolved, Extended, false, false> { +struct QmlTypeAndRevisionsRegistration<T, Resolved, Extended, false, false, false> { static void registerTypeAndRevisions(const char *uri, int versionMajor, QList<int> *qmlTypeIds, const QMetaObject *extension) { @@ -812,8 +821,19 @@ struct QmlTypeAndRevisionsRegistration<T, Resolved, Extended, false, false> { } }; +template<class T, class Resolved> +struct QmlTypeAndRevisionsRegistration<T, Resolved, void, false, false, true> { + static void registerTypeAndRevisions(const char *uri, int versionMajor, QList<int> *qmlTypeIds, + const QMetaObject *) + { + QQmlPrivate::qmlRegisterSequenceAndRevisions<Resolved>( + uri, versionMajor, QQmlPrivate::StaticMetaObject<T>::staticMetaObject(), + qmlTypeIds); + } +}; + template<class T, class Resolved, class Extended> -struct QmlTypeAndRevisionsRegistration<T, Resolved, Extended, true, false> { +struct QmlTypeAndRevisionsRegistration<T, Resolved, Extended, true, false, false> { static void registerTypeAndRevisions(const char *uri, int versionMajor, QList<int> *qmlTypeIds, const QMetaObject *extension) { @@ -824,7 +844,7 @@ struct QmlTypeAndRevisionsRegistration<T, Resolved, Extended, true, false> { }; template<class T, class Resolved> -struct QmlTypeAndRevisionsRegistration<T, Resolved, void, false, true> { +struct QmlTypeAndRevisionsRegistration<T, Resolved, void, false, true, false> { static void registerTypeAndRevisions(const char *uri, int versionMajor, QList<int> *qmlTypeIds, const QMetaObject *) { @@ -845,7 +865,8 @@ void qmlRegisterTypesAndRevisions(const char *uri, int versionMajor, QList<int> T, typename QQmlPrivate::QmlResolved<T>::Type, typename QQmlPrivate::QmlExtended<T>::Type, QQmlPrivate::QmlSingleton<T>::Value, - QQmlPrivate::QmlInterface<T>::Value> + QQmlPrivate::QmlInterface<T>::Value, + QQmlPrivate::QmlSequence<T>::Value> ::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 e59ebc97eb..9dea173127 100644 --- a/src/qml/qml/qqmlmetatype.cpp +++ b/src/qml/qml/qqmlmetatype.cpp @@ -667,7 +667,8 @@ QQmlType QQmlMetaType::registerSequentialContainer( QQmlMetaTypeDataPtr data; - if (!checkRegistration(QQmlType::SequentialContainerType, data, container.uri, QString(), + const QString typeName = QString::fromUtf8(container.typeName); + if (!checkRegistration(QQmlType::SequentialContainerType, data, container.uri, typeName, container.version, {})) { return QQmlType(); } @@ -675,8 +676,9 @@ QQmlType QQmlMetaType::registerSequentialContainer( QQmlTypePrivate *priv = new QQmlTypePrivate(QQmlType::SequentialContainerType); data->registerType(priv); - priv->setName(QString::fromUtf8(container.uri), QString()); + priv->setName(QString::fromUtf8(container.uri), typeName); priv->version = container.version; + priv->revision = container.revision; priv->typeId = container.typeId; *priv->extraData.ld = container.metaSequence; diff --git a/src/qml/qml/qqmlprivate.h b/src/qml/qml/qqmlprivate.h index 19072f0751..feee3f8686 100644 --- a/src/qml/qml/qqmlprivate.h +++ b/src/qml/qml/qqmlprivate.h @@ -574,6 +574,19 @@ namespace QQmlPrivate const char *typeName; QMetaType typeId; QMetaSequence metaSequence; + QTypeRevision revision; + }; + + struct RegisterSequentialContainerAndRevisions { + int structVersion; + const char *uri; + QTypeRevision version; + + const QMetaObject *classInfoMetaObject; + QMetaType typeId; + QMetaSequence metaSequence; + + QVector<int> *qmlTypeIds; }; struct AOTCompiledFunction { @@ -605,6 +618,7 @@ namespace QQmlPrivate TypeAndRevisionsRegistration = 7, SingletonAndRevisionsRegistration = 8, SequentialContainerRegistration = 9, + SequentialContainerAndRevisionsRegistration = 10, }; int Q_QML_EXPORT qmlregister(RegistrationType, void *); @@ -717,6 +731,20 @@ namespace QQmlPrivate }; template<class T, class = std::void_t<>> + struct QmlSequence + { + static constexpr bool Value = false; + }; + + template<class T> + struct QmlSequence<T, std::void_t<typename T::QmlIsSequence>> + { + Q_STATIC_ASSERT((std::is_same_v<typename T::QmlSequenceValueType, + typename QmlResolved<T>::Type::value_type>)); + static constexpr bool Value = bool(T::QmlIsSequence::yes); + }; + + template<class T, class = std::void_t<>> struct QmlInterface { static constexpr bool Value = false; @@ -823,6 +851,24 @@ namespace QQmlPrivate qmlregister(TypeAndRevisionsRegistration, &type); } + template<typename T> + void qmlRegisterSequenceAndRevisions(const char *uri, int versionMajor, + const QMetaObject *classInfoMetaObject, + QVector<int> *qmlTypeIds) + { + RegisterSequentialContainerAndRevisions type = { + 0, + uri, + QTypeRevision::fromMajorVersion(versionMajor), + classInfoMetaObject, + QMetaType::fromType<T>(), + QMetaSequence::fromContainer<T>(), + qmlTypeIds + }; + + qmlregister(SequentialContainerAndRevisionsRegistration, &type); + } + template<> void Q_QML_EXPORT qmlRegisterTypeAndRevisions<QQmlTypeNotAvailable, void>( const char *uri, int versionMajor, const QMetaObject *classInfoMetaObject, |