From 6d1317e11a8a85f23190df02ae0c69f9e4420b0e Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Tue, 30 May 2023 10:25:31 +0200 Subject: [PATCH] Allow anonymous value types to be constructed Only anonymous object types are necessarily uncreatable. You don't need a name in order to construct or populate a value type. Since we can now construct QSize, QRect, and QPoint, the engine will try to construct them from the 'F' variants where applicable. Allow this. Pick-to: 6.5 6.6 Change-Id: I568b93c58d3184d9ac37bf0a542c0e50dd37d8de Reviewed-by: Fabian Kosmale --- src/qml/qml/qqml.cpp | 5 +- src/qml/qml/qqmlvaluetype_p.h | 6 +++ .../data/structuredValueTypes.qml | 3 ++ .../qml/qqmlvaluetypeproviders/testtypes.cpp | 1 + .../qml/qqmlvaluetypeproviders/testtypes.h | 46 +++++++++++++++++++ .../tst_qqmlvaluetypeproviders.cpp | 7 +++ 6 files changed, 66 insertions(+), 2 deletions(-) diff --git a/src/qml/qml/qqml.cpp b/src/qml/qml/qqml.cpp index ca9c1d8e52..bb740962f6 100644 --- a/src/qml/qml/qqml.cpp +++ b/src/qml/qml/qqml.cpp @@ -494,7 +494,8 @@ int QQmlPrivate::qmlregister(RegistrationType type, void *data) const char *elementName = (type.structVersion > 1 && type.forceAnonymous) ? nullptr : classElementName(type.classInfoMetaObject); - const bool creatable = (elementName != nullptr) + const bool isValueType = !(type.typeId.flags() & QMetaType::PointerToQObject); + const bool creatable = (elementName != nullptr || isValueType) && boolClassInfo(type.classInfoMetaObject, "QML.Creatable", true); QString noCreateReason; @@ -505,7 +506,7 @@ int QQmlPrivate::qmlregister(RegistrationType type, void *data) classInfo(type.classInfoMetaObject, "QML.UncreatableReason")); if (noCreateReason.isEmpty()) noCreateReason = QLatin1String("Type cannot be created in QML."); - } else if (!(type.typeId.flags() & QMetaType::PointerToQObject)) { + } else if (isValueType) { const char *method = classInfo(type.classInfoMetaObject, "QML.CreationMethod"); if (qstrcmp(method, "structured") == 0) creationMethod = ValueTypeCreationMethod::Structured; diff --git a/src/qml/qml/qqmlvaluetype_p.h b/src/qml/qml/qqmlvaluetype_p.h index ff82e11003..a2071fa7fc 100644 --- a/src/qml/qml/qqmlvaluetype_p.h +++ b/src/qml/qml/qqmlvaluetype_p.h @@ -140,6 +140,8 @@ struct Q_QML_PRIVATE_EXPORT QQmlPointValueType QML_STRUCTURED_VALUE public: + QQmlPointValueType() = default; + Q_INVOKABLE QQmlPointValueType(const QPointF &point) : v(point.toPoint()) {} Q_INVOKABLE QString toString() const; int x() const; int y() const; @@ -186,6 +188,8 @@ struct Q_QML_PRIVATE_EXPORT QQmlSizeValueType QML_STRUCTURED_VALUE public: + QQmlSizeValueType() = default; + Q_INVOKABLE QQmlSizeValueType(const QSizeF &size) : v(size.toSize()) {} Q_INVOKABLE QString toString() const; int width() const; int height() const; @@ -254,6 +258,8 @@ struct Q_QML_PRIVATE_EXPORT QQmlRectValueType QML_STRUCTURED_VALUE public: + QQmlRectValueType() = default; + Q_INVOKABLE QQmlRectValueType(const QRectF &rect) : v(rect.toRect()) {} Q_INVOKABLE QString toString() const; int x() const; int y() const; diff --git a/tests/auto/qml/qqmlvaluetypeproviders/data/structuredValueTypes.qml b/tests/auto/qml/qqmlvaluetypeproviders/data/structuredValueTypes.qml index 6a42a4f1a8..9dbe5c8f0b 100644 --- a/tests/auto/qml/qqmlvaluetypeproviders/data/structuredValueTypes.qml +++ b/tests/auto/qml/qqmlvaluetypeproviders/data/structuredValueTypes.qml @@ -43,4 +43,7 @@ MyTypeObject { c4 = {foo: 11}; } + + barren: ({i: 17}) + function changeBarren() { barren = "foos" } } diff --git a/tests/auto/qml/qqmlvaluetypeproviders/testtypes.cpp b/tests/auto/qml/qqmlvaluetypeproviders/testtypes.cpp index 7569556121..d65e2a87b2 100644 --- a/tests/auto/qml/qqmlvaluetypeproviders/testtypes.cpp +++ b/tests/auto/qml/qqmlvaluetypeproviders/testtypes.cpp @@ -10,6 +10,7 @@ void registerTypes() qmlRegisterTypesAndRevisions("Test", 1); qmlRegisterTypesAndRevisions("Test", 1); qmlRegisterTypesAndRevisions("Test", 1); + qmlRegisterTypesAndRevisions("Test", 1); qmlRegisterTypesAndRevisions("Test", 1); qmlRegisterTypesAndRevisions("Test", 1); } diff --git a/tests/auto/qml/qqmlvaluetypeproviders/testtypes.h b/tests/auto/qml/qqmlvaluetypeproviders/testtypes.h index fa8eaaf202..b3aa35dd71 100644 --- a/tests/auto/qml/qqmlvaluetypeproviders/testtypes.h +++ b/tests/auto/qml/qqmlvaluetypeproviders/testtypes.h @@ -109,6 +109,35 @@ private: QList m_sizes = { QSizeF(1, 1), QSizeF(2, 2) }; }; +struct BarrenValueType +{ + Q_GADGET + Q_PROPERTY(int i READ i WRITE setI) + +public: + BarrenValueType() = default; + Q_INVOKABLE BarrenValueType(const QString &) : m_i(25) {} + + int i() const { return m_i; } + void setI(int newI) { m_i = newI; } + +private: + friend bool operator==(const BarrenValueType &a, const BarrenValueType &b) + { + return a.m_i == b.m_i; + } + + int m_i = 0; +}; + +struct ForeignAnonymousStructuredValueType +{ + Q_GADGET + QML_ANONYMOUS + QML_FOREIGN(BarrenValueType) + QML_STRUCTURED_VALUE +}; + class MyTypeObject : public QObject { Q_OBJECT @@ -133,6 +162,7 @@ class MyTypeObject : public QObject Q_PROPERTY(QVariant variant READ variant NOTIFY changed) Q_PROPERTY(ConstructibleValueType constructible READ constructible WRITE setConstructible NOTIFY constructibleChanged) Q_PROPERTY(StructuredValueType structured READ structured WRITE setStructured NOTIFY structuredChanged) + Q_PROPERTY(BarrenValueType barren READ barren WRITE setBarren NOTIFY barrenChanged) Q_PROPERTY(QDateTime aDateTime READ aDateTime WRITE setADateTime NOTIFY aDateTimeChanged) Q_PROPERTY(QDate aDate READ aDate WRITE setADate NOTIFY aDateChanged) @@ -307,6 +337,19 @@ public: emit aVariantChanged(); } + BarrenValueType barren() const + { + return m_barren; + } + + void setBarren(const BarrenValueType &newBarren) + { + if (m_barren == newBarren) + return; + m_barren = newBarren; + emit barrenChanged(); + } + signals: void changed(); void runScript(); @@ -319,6 +362,8 @@ signals: void aTimeChanged(); void aVariantChanged(); + void barrenChanged(); + public slots: QSize method() { return QSize(13, 14); } private: @@ -329,6 +374,7 @@ private: QDate m_aDate; QTime m_aTime; QVariant m_aVariant; + BarrenValueType m_barren; }; class Padding diff --git a/tests/auto/qml/qqmlvaluetypeproviders/tst_qqmlvaluetypeproviders.cpp b/tests/auto/qml/qqmlvaluetypeproviders/tst_qqmlvaluetypeproviders.cpp index 5dd7759509..e4794a3806 100644 --- a/tests/auto/qml/qqmlvaluetypeproviders/tst_qqmlvaluetypeproviders.cpp +++ b/tests/auto/qml/qqmlvaluetypeproviders/tst_qqmlvaluetypeproviders.cpp @@ -351,6 +351,13 @@ void tst_qqmlvaluetypeproviders::structured() ConstructibleFromQReal(-112.5)); QCOMPARE(o->property("cr7").value(), ConstructibleFromQReal(50)); + + BarrenValueType barren; + barren.setI(17); + QCOMPARE(o->property("barren").value(), barren); + + QMetaObject::invokeMethod(o.data(), "changeBarren"); + QCOMPARE(o->property("barren").value(), BarrenValueType(QString())); } void tst_qqmlvaluetypeproviders::recursive()