From f48e8c9711fbeb350ccf70f852ce3732844d4287 Mon Sep 17 00:00:00 2001 From: Kai Dohmen Date: Mon, 11 Apr 2016 19:38:50 +0200 Subject: Make passing objects from website to server possible If you get an object from the server and want to pass it back to the server via a function the id of the object is passed instead of the whole json object. On the server side QMetaObjectPublisher::invokeMethod now looks up the object in QMetaObjectPublisher::wrappedObjects by the passed object-id. Task-number: QTBUG-50075 Change-Id: Id0df2dfaa79bcba12ca48391ae7537ac1a086898 Reviewed-by: Milian Wolff --- src/webchannel/qmetaobjectpublisher.cpp | 63 +++++++++++++++++++++------------ src/webchannel/qmetaobjectpublisher_p.h | 4 +++ src/webchannel/qwebchannel.js | 16 ++++++--- 3 files changed, 56 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/webchannel/qmetaobjectpublisher.cpp b/src/webchannel/qmetaobjectpublisher.cpp index 0fa4ae2..b3fc53d 100644 --- a/src/webchannel/qmetaobjectpublisher.cpp +++ b/src/webchannel/qmetaobjectpublisher.cpp @@ -87,29 +87,6 @@ QJsonObject createResponse(const QJsonValue &id, const QJsonValue &data) /// TODO: what is the proper value here? const int PROPERTY_UPDATE_INTERVAL = 50; - -QVariant toVariant(const QJsonValue &value, int targetType) -{ - if (targetType == QMetaType::QJsonValue) { - return QVariant::fromValue(value); - } else if (targetType == QMetaType::QJsonArray) { - if (!value.isArray()) - qWarning() << "Cannot not convert non-array argument" << value << "to QJsonArray."; - return QVariant::fromValue(value.toArray()); - } else if (targetType == QMetaType::QJsonObject) { - if (!value.isObject()) - qWarning() << "Cannot not convert non-object argument" << value << "to QJsonObject."; - return QVariant::fromValue(value.toObject()); - } - - // this converts QJsonObjects to QVariantMaps, which is not desired when - // we want to get a QJsonObject or QJsonValue (see above) - QVariant variant = value.toVariant(); - if (targetType != QMetaType::QVariant && !variant.convert(targetType)) { - qWarning() << "Could not convert argument" << value << "to target type" << QVariant::typeToName(targetType) << '.'; - } - return variant; -} } QMetaObjectPublisher::QMetaObjectPublisher(QWebChannel *webChannel) @@ -472,6 +449,46 @@ void QMetaObjectPublisher::objectDestroyed(const QObject *object) pendingPropertyUpdates.remove(object); } +QObject *QMetaObjectPublisher::unwrapObject(const QString &objectId) const +{ + if (!objectId.isEmpty()) { + ObjectInfo objectInfo = wrappedObjects.value(objectId); + if (objectInfo.object && !objectInfo.classinfo.isEmpty()) + return objectInfo.object; + } + + qWarning() << "No wrapped object" << objectId; + return Q_NULLPTR; +} + +QVariant QMetaObjectPublisher::toVariant(const QJsonValue &value, int targetType) const +{ + if (targetType == QMetaType::QJsonValue) { + return QVariant::fromValue(value); + } else if (targetType == QMetaType::QJsonArray) { + if (!value.isArray()) + qWarning() << "Cannot not convert non-array argument" << value << "to QJsonArray."; + return QVariant::fromValue(value.toArray()); + } else if (targetType == QMetaType::QJsonObject) { + if (!value.isObject()) + qWarning() << "Cannot not convert non-object argument" << value << "to QJsonObject."; + return QVariant::fromValue(value.toObject()); + } else if (QMetaType::typeFlags(targetType) & QMetaType::PointerToQObject) { + QObject *unwrappedObject = unwrapObject(value.toObject()[KEY_ID].toString()); + if (unwrappedObject == Q_NULLPTR) + qWarning() << "Cannot not convert non-object argument" << value << "to QObject*."; + return QVariant::fromValue(unwrappedObject); + } + + // this converts QJsonObjects to QVariantMaps, which is not desired when + // we want to get a QJsonObject or QJsonValue (see above) + QVariant variant = value.toVariant(); + if (targetType != QMetaType::QVariant && !variant.convert(targetType)) { + qWarning() << "Could not convert argument" << value << "to target type" << QVariant::typeToName(targetType) << '.'; + } + return variant; +} + // NOTE: transport can be a nullptr // in such a case, we need to ensure that the property is registered to // the target transports of the parentObjectId diff --git a/src/webchannel/qmetaobjectpublisher_p.h b/src/webchannel/qmetaobjectpublisher_p.h index b0ebd84..048a33c 100644 --- a/src/webchannel/qmetaobjectpublisher_p.h +++ b/src/webchannel/qmetaobjectpublisher_p.h @@ -166,6 +166,10 @@ public: */ void objectDestroyed(const QObject *object); + QObject *unwrapObject(const QString &objectId) const; + + QVariant toVariant(const QJsonValue &value, int targetType) const; + /** * Given a QVariant containing a QObject*, wrap the object and register for property updates * return the objects class information. diff --git a/src/webchannel/qwebchannel.js b/src/webchannel/qwebchannel.js index d8c28bc..148e70d 100644 --- a/src/webchannel/qwebchannel.js +++ b/src/webchannel/qwebchannel.js @@ -324,10 +324,15 @@ function QObject(name, data, webChannel) var args = []; var callback; for (var i = 0; i < arguments.length; ++i) { - if (typeof arguments[i] === "function") - callback = arguments[i]; + var argument = arguments[i]; + if (typeof argument === "function") + callback = argument; + else if (argument instanceof QObject && webChannel.objects[argument.__id__] !== undefined) + args.push({ + "id": argument.__id__ + }); else - args.push(arguments[i]); + args.push(argument); } webChannel.exec({ @@ -381,11 +386,14 @@ function QObject(name, data, webChannel) return; } object.__propertyCache__[propertyIndex] = value; + var valueToSend = value; + if (valueToSend instanceof QObject && webChannel.objects[valueToSend.__id__] !== undefined) + valueToSend = { "id": valueToSend.__id__ }; webChannel.exec({ "type": QWebChannelMessageTypes.setProperty, "object": object.__id__, "property": propertyIndex, - "value": value + "value": valueToSend }); } }); -- cgit v1.2.1