aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml/qqmlvmemetaobject.cpp
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2022-01-07 20:19:20 +0100
committerUlf Hermann <ulf.hermann@qt.io>2022-01-25 23:55:27 +0100
commit5a908de8b7e772e78adb30cc3205c7cf5bd622f5 (patch)
tree0a803fb250a3b89133935ba1e75d2e0eac2f7c23 /src/qml/qml/qqmlvmemetaobject.cpp
parent17dcba699566bfe052bf2c320e07c2c7cc53094b (diff)
Allow custom named value types in QML
You can now add your own, lower-case named, value types to your own module, and use them in QML. Previously the names had been ignored, but now you can actually declare properties using the value types. The QtQuick value types are now handled exactly this way, and their special casing at compile time is removed. [ChangeLog][QML][Important Behavior Changes] You can now add your own value types to QML modules. This works exactly like the registration of object types, just with Q_GADGET instead of QObject/Q_OBJECT. In turn, the QtQuick value types are only available from QtQuick now. Previously you could declare unusable properties of QtQuick value types when only importing QtQml. This is not possible anymore. Task-number: QTBUG-82443 Change-Id: I5b2e867141244531cb13d789678fb7e06a6e41e7 Reviewed-by: Andrei Golubev <andrei.golubev@qt.io> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Konstantin Shegunov <kshegunov@gmail.com> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Diffstat (limited to 'src/qml/qml/qqmlvmemetaobject.cpp')
-rw-r--r--src/qml/qml/qqmlvmemetaobject.cpp118
1 files changed, 76 insertions, 42 deletions
diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp
index 8c61e03595..70c6b2e45e 100644
--- a/src/qml/qml/qqmlvmemetaobject.cpp
+++ b/src/qml/qml/qqmlvmemetaobject.cpp
@@ -582,7 +582,21 @@ QDate QQmlVMEMetaObject::readPropertyAsDate(int id) const
return v->d()->data().value<QDate>();
}
-QDateTime QQmlVMEMetaObject::readPropertyAsDateTime(int id)
+QTime QQmlVMEMetaObject::readPropertyAsTime(int id) const
+{
+ QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
+ if (!md)
+ return QTime();
+
+ QV4::Scope scope(engine);
+ QV4::ScopedValue sv(scope, *(md->data() + id));
+ const QV4::VariantObject *v = sv->as<QV4::VariantObject>();
+ if (!v || v->d()->data().userType() != QMetaType::QTime)
+ return QTime();
+ return v->d()->data().value<QTime>();
+}
+
+QDateTime QQmlVMEMetaObject::readPropertyAsDateTime(int id) const
{
QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
if (!md)
@@ -698,9 +712,6 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void *
? nullptr
: QQmlEnginePrivate::get(ctxt->engine());
- const QMetaType fallbackMetaType
- = QQmlPropertyCacheCreatorBase::metaTypeForPropertyType(t);
-
if (c == QMetaObject::ReadProperty) {
switch (t) {
case QV4::CompiledData::BuiltinType::Int:
@@ -733,22 +744,8 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void *
case QV4::CompiledData::BuiltinType::Point:
*reinterpret_cast<QPointF *>(a[0]) = readPropertyAsPointF(id);
break;
- case QV4::CompiledData::BuiltinType::Font:
case QV4::CompiledData::BuiltinType::Time:
- case QV4::CompiledData::BuiltinType::Color:
- case QV4::CompiledData::BuiltinType::Vector2D:
- case QV4::CompiledData::BuiltinType::Vector3D:
- case QV4::CompiledData::BuiltinType::Vector4D:
- case QV4::CompiledData::BuiltinType::Matrix4x4:
- case QV4::CompiledData::BuiltinType::Quaternion:
- Q_ASSERT(fallbackMetaType.isValid());
- if (QV4::MemberData *md = propertyAndMethodStorageAsMemberData()) {
- QVariant propertyAsVariant;
- if (const QV4::VariantObject *v = (md->data() + id)->as<QV4::VariantObject>())
- propertyAsVariant = v->d()->data();
- QQml_valueTypeProvider()->readValueType(
- fallbackMetaType, propertyAsVariant, a[0]);
- }
+ *reinterpret_cast<QTime *>(a[0]) = readPropertyAsTime(id);
break;
case QV4::CompiledData::BuiltinType::Var:
if (ep) {
@@ -785,15 +782,37 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void *
}
quintptr encodedIndex = (inheritanceDepth << (usableBits/2)) + id;
-
readPropertyAsList(id); // Initializes if necessary
*static_cast<QQmlListProperty<QObject> *>(a[0])
= QQmlListProperty<QObject>(
object, reinterpret_cast<void *>(quintptr(encodedIndex)),
list_append, list_count, list_at,
list_clear, list_replace, list_removeLast);
+ } else if (QV4::MemberData *md = propertyAndMethodStorageAsMemberData()) {
+ QV4::Scope scope(engine);
+ QV4::ScopedValue sv(scope, *(md->data() + id));
+
+ // _id because this is an absolute property ID.
+ const QQmlPropertyData *propertyData = cache->property(_id);
+
+ if (propertyData->isQObject()) {
+ if (const auto *wrap = sv->as<QV4::QObjectWrapper>())
+ *reinterpret_cast<QObject **>(a[0]) = wrap->object();
+ else
+ *reinterpret_cast<QObject **>(a[0]) = nullptr;
+ } else {
+ const QMetaType propType = propertyData->propType();
+ const void *data = nullptr;
+ if (const QV4::VariantObject *v = sv->as<QV4::VariantObject>()) {
+ const QVariant &variant = v->d()->data();
+ if (variant.metaType() == propType)
+ data = variant.constData();
+ }
+ propType.destruct(a[0]);
+ propType.construct(a[0], data);
+ }
} else {
- *reinterpret_cast<QObject **>(a[0]) = readPropertyAsQObject(id);
+ qmlWarning(object) << "Cannot find member data";
}
}
@@ -840,25 +859,9 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void *
needActivate = *reinterpret_cast<QPointF *>(a[0]) != readPropertyAsPointF(id);
writeProperty(id, *reinterpret_cast<QPointF *>(a[0]));
break;
- case QV4::CompiledData::BuiltinType::Font:
case QV4::CompiledData::BuiltinType::Time:
- case QV4::CompiledData::BuiltinType::Color:
- case QV4::CompiledData::BuiltinType::Vector2D:
- case QV4::CompiledData::BuiltinType::Vector3D:
- case QV4::CompiledData::BuiltinType::Vector4D:
- case QV4::CompiledData::BuiltinType::Matrix4x4:
- case QV4::CompiledData::BuiltinType::Quaternion:
- Q_ASSERT(fallbackMetaType.isValid());
- if (QV4::MemberData *md = propertyAndMethodStorageAsMemberData()) {
- const QV4::VariantObject *v = (md->data() + id)->as<QV4::VariantObject>();
- if (!v) {
- md->set(engine, id, engine->newVariantObject(QVariant()));
- v = (md->data() + id)->as<QV4::VariantObject>();
- QQml_valueTypeProvider()->initValueType(fallbackMetaType, v->d()->data());
- }
- needActivate = !QQml_valueTypeProvider()->equalValueType(fallbackMetaType, a[0], v->d()->data());
- QQml_valueTypeProvider()->writeValueType(fallbackMetaType, a[0], v->d()->data());
- }
+ needActivate = *reinterpret_cast<QTime *>(a[0]) != readPropertyAsTime(id);
+ writeProperty(id, *reinterpret_cast<QTime *>(a[0]));
break;
case QV4::CompiledData::BuiltinType::Var:
if (ep)
@@ -868,11 +871,42 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void *
if (property.isList) {
// Writing such a property is not supported. Content is added through the list property
// methods.
+ } else if (QV4::MemberData *md = propertyAndMethodStorageAsMemberData()) {
+ QV4::Scope scope(engine);
+ QV4::ScopedValue sv(scope, *(md->data() + id));
+
+ // _id because this is an absolute property ID.
+ const QQmlPropertyData *propertyData = cache->property(_id);
+
+ if (propertyData->isQObject()) {
+ QObject *arg = *reinterpret_cast<QObject **>(a[0]);
+ if (const QV4::QObjectWrapper *wrap = sv->as<QV4::QObjectWrapper>())
+ needActivate = wrap->object() != arg;
+ else
+ needActivate = true;
+ if (needActivate)
+ writeProperty(id, arg);
+ } else {
+ const QMetaType propType = propertyData->propType();
+ if (const QV4::VariantObject *v = sv->as<QV4::VariantObject>()) {
+ QVariant &variant = v->d()->data();
+ if (variant.metaType() != propType) {
+ needActivate = true;
+ variant = QVariant(propType, a[0]);
+ } else if (!propType.equals(variant.constData(), a[0])) {
+ needActivate = true;
+ propType.destruct(variant.data());
+ propType.construct(variant.data(), a[0]);
+ }
+ } else {
+ needActivate = true;
+ md->set(engine, id, engine->newVariantObject(
+ QVariant(propType, a[0])));
+ }
+ }
} else {
- needActivate = *reinterpret_cast<QObject **>(a[0]) != readPropertyAsQObject(id);
- writeProperty(id, *reinterpret_cast<QObject **>(a[0]));
+ qmlWarning(object) << "Cannot find member data";
}
-
}
if (needActivate)