aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml/qqmlproperty.cpp
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2022-09-08 14:41:42 +0200
committerVolker Hilsheimer <volker.hilsheimer@qt.io>2022-09-24 07:54:29 +0000
commit3195b44e1c9678584c05ed823aab2eb32518d868 (patch)
tree7c13d0ee0b6f9074841862e160d19d744daeda58 /src/qml/qml/qqmlproperty.cpp
parentb101be9be64b6cc82dc357da0faeffbaab771b8f (diff)
Allow more options for creating value types from JS objects
We allow value types to be created 1. by calling Q_INVOKABLE constructors 2. by setting their values from properties of a JS object Both have to be opted into by setting a class info. If opted into, these options override the existing methods. When a a type can be created by setting its properties, that implies you can also initialize it using an invokable constructor. However, when given a JS object, the properties method is used. We keep this internal and undocumented for now. As the last try (the create(QJSValue) methods and QJSValue ctors) was not that stellar, let's first wait a bit and see if we're getting it right this time around. Fixes: QTBUG-106480 Change-Id: I767230924afcba032d501846cc3263dad57b7bf0 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
Diffstat (limited to 'src/qml/qml/qqmlproperty.cpp')
-rw-r--r--src/qml/qml/qqmlproperty.cpp110
1 files changed, 78 insertions, 32 deletions
diff --git a/src/qml/qml/qqmlproperty.cpp b/src/qml/qml/qqmlproperty.cpp
index 402c23bb28..9f5703a3c3 100644
--- a/src/qml/qml/qqmlproperty.cpp
+++ b/src/qml/qml/qqmlproperty.cpp
@@ -1220,7 +1220,7 @@ bool QQmlPropertyPrivate::writeEnumProperty(const QMetaProperty &prop, int idx,
return false;
QVariant v = value;
- if (prop.isEnumType()) {
+ if (prop.isEnumType() && v.metaType() != prop.metaType()) {
QMetaEnum menum = prop.enumerator();
if (v.userType() == QMetaType::QString) {
bool ok;
@@ -1360,6 +1360,80 @@ private:
QUntypedPropertyBinding untypedBinding;
};
+struct ConvertAndAssignResult {
+ bool couldConvert = false;
+ bool couldWrite = false;
+
+ operator bool() const { return couldConvert; }
+};
+
+static ConvertAndAssignResult tryConvertAndAssign(
+ QObject *object, const QQmlPropertyData &property, const QVariant &value,
+ QQmlPropertyData::WriteFlags flags, QMetaType propertyMetaType, QMetaType variantMetaType,
+ bool isUrl) {
+
+ if (isUrl
+ || variantMetaType == QMetaType::fromType<QString>()
+ || propertyMetaType == QMetaType::fromType<QList<QUrl>>()
+ || property.isQList()) {
+ return {false, false};
+ }
+
+ // common cases:
+ switch (propertyMetaType.id()) {
+ case QMetaType::Bool:
+ if (value.canConvert(propertyMetaType)) {
+ bool b = value.toBool();
+ return {true, property.writeProperty(object, &b, flags)};
+ }
+ return {false, false};
+ case QMetaType::Int: {
+ bool ok = false;
+ int i = value.toInt(&ok);
+ return {ok, ok && property.writeProperty(object, &i, flags)};
+ }
+ case QMetaType::UInt: {
+ bool ok = false;
+ uint u = value.toUInt(&ok);
+ return {ok, ok && property.writeProperty(object, &u, flags)};
+ }
+ case QMetaType::Double: {
+ bool ok = false;
+ double d = value.toDouble(&ok);
+ return {ok, ok && property.writeProperty(object, &d, flags)};
+ }
+ case QMetaType::Float: {
+ bool ok = false;
+ float f = value.toFloat(&ok);
+ return {ok, ok && property.writeProperty(object, &f, flags)};
+ }
+ case QMetaType::QString:
+ if (value.canConvert(propertyMetaType)) {
+ QString s = value.toString();
+ return {true, property.writeProperty(object, &s, flags)};
+ }
+ return {false, false};
+ case QMetaType::QVariantMap:
+ if (value.canConvert(propertyMetaType)) {
+ QVariantMap m = value.toMap();
+ return {true, property.writeProperty(object, &m, flags)};
+ }
+ return {false, false};
+ default: {
+ break;
+ }
+ }
+
+ QVariant converted(propertyMetaType);
+ if (QQmlValueTypeProvider::createValueType(value, propertyMetaType, converted.data())
+ || QMetaType::convert(value.metaType(), value.constData(),
+ propertyMetaType, converted.data())) {
+ return {true, property.writeProperty(object, converted.data(), flags)};
+ }
+
+ return {false, false};
+};
+
bool QQmlPropertyPrivate::write(
QObject *object, const QQmlPropertyData &property, const QVariant &value,
const QQmlRefPointer<QQmlContextData> &context, QQmlPropertyData::WriteFlags flags)
@@ -1419,37 +1493,9 @@ bool QQmlPropertyPrivate::write(
} else {
return false;
}
- } else if (value.canConvert(propertyMetaType)
- && !isUrl && variantMetaType != QMetaType::fromType<QString>()
- && propertyMetaType != QMetaType::fromType<QList<QUrl>>() && !property.isQList()) {
- // common cases:
- switch (propertyMetaType.id()) {
- case QMetaType::Bool: {
- bool b = value.toBool();
- return property.writeProperty(object, &b, flags);
- }
- case QMetaType::Int: {
- int i = value.toInt();
- return property.writeProperty(object, &i, flags);
- }
- case QMetaType::Double: {
- double d = value.toDouble();
- return property.writeProperty(object, &d, flags);
- }
- case QMetaType::Float: {
- float f = value.toFloat();
- return property.writeProperty(object, &f, flags);
- }
- case QMetaType::QString: {
- QString s = value.toString();
- return property.writeProperty(object, &s, flags);
- }
- default: { // "fallback":
- QVariant v = value;
- v.convert(propertyMetaType);
- return property.writeProperty(object, const_cast<void *>(v.constData()), flags);
- }
- }
+ } else if (ConvertAndAssignResult result = tryConvertAndAssign(
+ object, property, value, flags, propertyMetaType, variantMetaType, isUrl)) {
+ return result.couldWrite;
} else if (propertyMetaType == QMetaType::fromType<QVariant>()) {
return property.writeProperty(object, const_cast<QVariant *>(&value), flags);
} else if (isUrl) {