summaryrefslogtreecommitdiff
path: root/src/imports/location/location.cpp
diff options
context:
space:
mode:
authorVolker Hilsheimer <volker.hilsheimer@qt.io>2022-09-09 15:46:22 +0200
committerVolker Hilsheimer <volker.hilsheimer@qt.io>2022-09-14 13:19:44 +0200
commit734799d9f88c2383be87806d4931799b6f6a843a (patch)
tree96afab2367fd90eda01c885bf5a4f15dcf327cc6 /src/imports/location/location.cpp
parent22c3c1d155f817324ed535ba599633cad0e49b5e (diff)
downloadqtlocation-734799d9f88c2383be87806d4931799b6f6a843a.tar.gz
Implement generic conversion from QML types to gadgets
This is a temporary solution to facilitate the conversion of Places QML types into value types, allowing us to get rid of the thin and unnecessary QDeclarative* wrappers. Support both conversion from QJSValue and from QVariantMap is needed to allow value-initialization of nested types, such as QPlaceSupplier, which has a QPlaceIcon property. Once the QML engine implements property-by-property initialization, this solution can be removed again. It is either way primarily relevant for the unit tests, which need to be able to construct and initialize value types from QML and JavaScript. Change-Id: I253ce6415dd80ec6464c77bca197cff325149cf7 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'src/imports/location/location.cpp')
-rw-r--r--src/imports/location/location.cpp69
1 files changed, 69 insertions, 0 deletions
diff --git a/src/imports/location/location.cpp b/src/imports/location/location.cpp
index a12c773b..39c8046f 100644
--- a/src/imports/location/location.cpp
+++ b/src/imports/location/location.cpp
@@ -79,6 +79,75 @@
QT_BEGIN_NAMESPACE
+namespace {
+
+bool convertToGadget(const QMetaObject &metaObject, const QVariantMap &map, void *gadget)
+{
+ for (auto &&[key, value] : map.asKeyValueRange()) {
+ const int propIndex = metaObject.indexOfProperty(key.toUtf8());
+ if (propIndex == -1) {
+ qCritical("No property %s in %s", qPrintable(key), metaObject.className());
+ return false;
+ }
+ const QMetaProperty prop = metaObject.property(propIndex);
+ bool successfulWrite = false;
+ if (value.metaType() != prop.metaType()) {
+ QVariant coercedValue = value;
+ if (!coercedValue.convert(prop.metaType())) {
+ qCritical("Could not convert value from %s to %s for property %s::%s",
+ value.typeName(), prop.typeName(), metaObject.className(), qPrintable(key));
+ return false;
+ }
+ successfulWrite = prop.writeOnGadget(gadget, coercedValue);
+ } else {
+ successfulWrite = prop.writeOnGadget(gadget, value);
+ }
+ if (!successfulWrite) {
+ qCritical("Could not set property %s on %s", qPrintable(key), metaObject.className());
+ return false;
+ }
+ }
+ return true;
+}
+
+template<typename SourceType, typename GadgetType>
+bool converterToGadget(const void *src, void *gadget)
+{
+ const QMetaObject &metaObject = GadgetType::staticMetaObject;
+ QVariantMap variantMap;
+ if constexpr (std::is_same_v<SourceType, QJSValue>) {
+ const QJSValue &jsValue = *static_cast<const QJSValue *>(src);
+ const QVariant &variant = jsValue.toVariant();
+ if (variant.metaType() != QMetaType::fromType<QVariantMap>())
+ return false;
+ variantMap = variant.toMap();
+ } else {
+ static_assert(std::is_same_v<SourceType, QVariantMap>);
+ variantMap = *static_cast<const QVariantMap *>(src);
+ }
+ return convertToGadget(metaObject, variantMap, gadget);
+}
+
+template<typename GadgetType>
+bool registerConverterToGadget()
+{
+ if (!QMetaType::registerConverterFunction(converterToGadget<QJSValue, GadgetType>,
+ QMetaType::fromType<QJSValue>(), QMetaType::fromType<GadgetType>())) {
+ qCritical("Failed to register conversion function from QJSValue to %s",
+ GadgetType::staticMetaObject.className());
+ return false;
+ }
+ if (!QMetaType::registerConverterFunction(converterToGadget<QVariantMap, GadgetType>,
+ QMetaType::fromType<QVariantMap>(), QMetaType::fromType<GadgetType>())) {
+ qCritical("Failed to register conversion function from QVariantMap to %s",
+ GadgetType::staticMetaObject.className());
+ return false;
+ }
+
+ return true;
+}
+
+} // anonymous namespace
class QtLocationDeclarativeModule: public QQmlExtensionPlugin
{