From 97c876a1353f29ed0129360f013f2529bed69d98 Mon Sep 17 00:00:00 2001 From: Milian Wolff Date: Wed, 25 May 2016 16:42:01 +0200 Subject: Enable calling C++ functions taking QJson arguments via webchannel. We used to convert the QJsonValue arguments to QVariants, which then failed to call a C++ function which expected on of the three QJson data types, i.e. QJsonValue, QJsonObject or QJsonArray. Instead, we now detect these three cases and manually convert the QJsonValue as needed. [ChangeLog] C++ functions taking arguments of type QJsonValue, QJsonArray or QJsonObject can now be called via the Qt WebChannel. Change-Id: I94e0c8937ca35e2ecd3554f7ddf2d4e5a3328570 Task-number: QTBUG-48198 Reviewed-by: Simon Hausmann --- src/webchannel/qmetaobjectpublisher.cpp | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/webchannel/qmetaobjectpublisher.cpp b/src/webchannel/qmetaobjectpublisher.cpp index 324191e..e85bc76 100644 --- a/src/webchannel/qmetaobjectpublisher.cpp +++ b/src/webchannel/qmetaobjectpublisher.cpp @@ -87,6 +87,29 @@ 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) @@ -366,11 +389,7 @@ QVariant QMetaObjectPublisher::invokeMethod(QObject *const object, const int met // construct converter objects of QVariant to QGenericArgument VariantArgument arguments[10]; for (int i = 0; i < qMin(args.size(), method.parameterCount()); ++i) { - QVariant arg = args.at(i).toVariant(); - if (method.parameterType(i) != QMetaType::QVariant && !arg.convert(method.parameterType(i))) { - qWarning() << "Could not convert argument" << args.at(i) << "to target type" << method.parameterTypes().at(i) << '.'; - } - arguments[i].value = arg; + arguments[i].value = toVariant(args.at(i), method.parameterType(i)); } // construct QGenericReturnArgument -- cgit v1.2.1 From bec50124b893c4632829d9806f49f64c4debf936 Mon Sep 17 00:00:00 2001 From: Milian Wolff Date: Wed, 25 May 2016 18:20:30 +0200 Subject: Fix setting properties of QJson{Value,Array,Object} type. Similar to the previous issue, where these types were not properly converted to QVariant when invoking a method, we manually do the conversion now to get the desired behavior. The culprit is again that QJsonValue::toVariant converts an object e.g. to a QVariantMap, and not to a QVariant containing a QJsonObject. [ChangeLog] QObject properties of type QJsonValue, QJsonArray or QJsonObject can now be set via the Qt WebChannel. Task-number: QTBUG-48198 Change-Id: I5d574b1a5cffd6d6ad9b555f2a3e872b9c3425a7 Reviewed-by: Simon Hausmann --- src/webchannel/qmetaobjectpublisher.cpp | 20 ++++++++++++-------- src/webchannel/qmetaobjectpublisher_p.h | 5 +++++ 2 files changed, 17 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/webchannel/qmetaobjectpublisher.cpp b/src/webchannel/qmetaobjectpublisher.cpp index e85bc76..0fa4ae2 100644 --- a/src/webchannel/qmetaobjectpublisher.cpp +++ b/src/webchannel/qmetaobjectpublisher.cpp @@ -410,6 +410,16 @@ QVariant QMetaObjectPublisher::invokeMethod(QObject *const object, const int met return returnValue; } +void QMetaObjectPublisher::setProperty(QObject *object, const int propertyIndex, const QJsonValue &value) +{ + QMetaProperty property = object->metaObject()->property(propertyIndex); + if (!property.isValid()) { + qWarning() << "Cannot set unknown property" << propertyIndex << "of object" << object; + } else if (!property.write(object, toVariant(value, property.userType()))) { + qWarning() << "Could not write value " << value << "to property" << property.name() << "of object" << object; + } +} + void QMetaObjectPublisher::signalEmitted(const QObject *object, const int signalIndex, const QVariantList &arguments) { if (!webChannel || webChannel->d_func()->transports.isEmpty()) { @@ -607,14 +617,8 @@ void QMetaObjectPublisher::handleMessage(const QJsonObject &message, QWebChannel } else if (type == TypeDisconnectFromSignal) { signalHandler.disconnectFrom(object, message.value(KEY_SIGNAL).toInt(-1)); } else if (type == TypeSetProperty) { - const int propertyIdx = message.value(KEY_PROPERTY).toInt(-1); - QMetaProperty property = object->metaObject()->property(propertyIdx); - if (!property.isValid()) { - qWarning() << "Cannot set unknown property" << message.value(KEY_PROPERTY) << "of object" << objectName; - } else if (!object->metaObject()->property(propertyIdx).write(object, message.value(KEY_VALUE).toVariant())) { - qWarning() << "Could not write value " << message.value(KEY_VALUE) - << "to property" << property.name() << "of object" << objectName; - } + setProperty(object, message.value(KEY_PROPERTY).toInt(-1), + message.value(KEY_VALUE)); } } } diff --git a/src/webchannel/qmetaobjectpublisher_p.h b/src/webchannel/qmetaobjectpublisher_p.h index cb3350e..b0ebd84 100644 --- a/src/webchannel/qmetaobjectpublisher_p.h +++ b/src/webchannel/qmetaobjectpublisher_p.h @@ -149,6 +149,11 @@ public: */ QVariant invokeMethod(QObject *const object, const int methodIndex, const QJsonArray &args); + /** + * Set the value of property @p propertyIndex on @p object to @p value. + */ + void setProperty(QObject *object, const int propertyIndex, const QJsonValue &value); + /** * Callback of the signalHandler which forwards the signal invocation to the webchannel clients. */ -- cgit v1.2.1 From 01ea92c7c8d77d3d3c10ab1cc4bf4f214aa07126 Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Tue, 31 May 2016 15:34:32 +0200 Subject: Doc: Edit example documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add images to the examples. - Add instructions for running the examples - Edit for grammar and style - Add dependencies to Qt WebEngine and Qt WebSockets modules - Add a workaround for preventing autolinking of WebChannel, WebEngine and WebSockets to the wrong targets - Use explicit linking where necessary Change-Id: Ia4025284063fa09c9e2a0b2c347ee682bba8a615 Reviewed-by: Topi Reiniƶ --- src/webchannel/doc/qtwebchannel.qdocconf | 3 +- src/webchannel/doc/src/examples.qdoc | 3 +- src/webchannel/doc/src/external-resources.qdoc | 57 ++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 src/webchannel/doc/src/external-resources.qdoc (limited to 'src') diff --git a/src/webchannel/doc/qtwebchannel.qdocconf b/src/webchannel/doc/qtwebchannel.qdocconf index cfb47e4..4026379 100644 --- a/src/webchannel/doc/qtwebchannel.qdocconf +++ b/src/webchannel/doc/qtwebchannel.qdocconf @@ -40,7 +40,7 @@ qhp.QtWebChannel.subprojects.javascript.indexTitle = Qt WebChannel JavaScript tagfile = ../../../doc/qtwebchannel/qtwebchannel.tags -depends += qtcore qtquick qtqml qmake qtdoc +depends += qtcore qtquick qtqml qmake qtdoc qtwebengine qtwebsockets headerdirs += .. \ ../../imports @@ -48,6 +48,7 @@ headerdirs += .. \ sourcedirs += .. \ ../../imports +imagedirs += images exampledirs += ../../../examples/webchannel examples.fileextensions += "*.html *.json" diff --git a/src/webchannel/doc/src/examples.qdoc b/src/webchannel/doc/src/examples.qdoc index c47b687..34875f8 100644 --- a/src/webchannel/doc/src/examples.qdoc +++ b/src/webchannel/doc/src/examples.qdoc @@ -36,6 +36,7 @@ \group qtwebchannel-examples \brief List of Qt WebChannel examples. - The examples show how to use the QWebChannel C++ and WebChannel QML API. + The examples show how to use the QWebChannel C++ and \l [QML] WebChannel QML + API. */ diff --git a/src/webchannel/doc/src/external-resources.qdoc b/src/webchannel/doc/src/external-resources.qdoc new file mode 100644 index 0000000..0002ec1 --- /dev/null +++ b/src/webchannel/doc/src/external-resources.qdoc @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/* + The nolink entries prevent autolinking of each occurrence of 'WebChannel' + 'WebEngine' or 'WebSocket' to the QML type. + To link to the QML type, use explicit linking. For example: + \l [QML] WebChannel + \sa {QtWebChannel::}{WebChannel} +*/ +/*! + \externalpage nolink + \title WebChannel + \internal +*/ + +/*! + \externalpage nolink + \title WebEngine + \internal +*/ + +/*! + \externalpage nolink + \title WebSockets + \internal +*/ + +/*! + \externalpage nolink + \title WebSocket + \internal +*/ -- cgit v1.2.1 From 432ff4bf15e2bbafaf1d36814ef0231baaf9f4ee Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Tue, 31 May 2016 15:37:55 +0200 Subject: Doc: Edit the index page - Remove reference to Qt WebKit - Add Getting Started section - Use standard section titles for API Reference and Examples Change-Id: Ie5e3ac792a109f680132a79e86d5e1065f4c3829 Reviewed-by: Milian Wolff --- src/webchannel/doc/src/index.qdoc | 40 +++++++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/webchannel/doc/src/index.qdoc b/src/webchannel/doc/src/index.qdoc index 5f354bd..43f4e6f 100644 --- a/src/webchannel/doc/src/index.qdoc +++ b/src/webchannel/doc/src/index.qdoc @@ -31,26 +31,50 @@ \title Qt WebChannel \brief Bridges the gap between Qt applications and HTML/JavaScript. - Qt WebChannel enables peer-to-peer communication between the host - (QML/C++ application) and the client (HTML/JavaScript application). The - transport mechanism is supported out of the box by the two popular web - engines, Qt WebKit 2 and Qt WebEngine (experimental). It works on all - browsers that support Qt WebSockets, enabling Qt WebChannel applications + Qt WebChannel enables peer-to-peer communication between the server + (QML/C++ application) and the client (HTML/JavaScript or QML application). The + transport mechanism is supported out of the box by \l{Qt WebEngine}. It works on all + browsers that support \l{Qt WebSockets}, enabling Qt WebChannel applications to run in any JavaScript runtime. Additionally, a custom transport mechanism can also be implemented using Qt WebSockets to support Qt WebChannel-based communication. The module provides a JavaScript library for seamless integration of C++ - and QML applications with HTML/JavaScript clients. The client must use the + and QML applications with HTML/JavaScript and QML clients. The clients must use the JavaScript library to access the serialized QObjects published by the host applications. - \section1 Related Information + \section1 Getting Started + + To use these classes in your application, use the following include + statement: + + \code + #include + \endcode + + To link against the module, add this line to your \l qmake \c .pro file: + + \code + QT += webchannel + \endcode + + The QML types are accessed by using: + \badcode + import QtWebChannel 1.0 + \endcode + + \section1 API Reference \list \li \l{Qt WebChannel JavaScript API}{JavaScript API} \li \l{Qt WebChannel C++ Classes}{C++ API} \li \l{Qt WebChannel QML Types}{QML API} - \li \l{Qt WebChannel Examples}{Examples} - show how use the API in practice + \endlist + + \section1 Examples + + \list + \li \l{Qt WebChannel Examples}{Examples} \endlist */ -- cgit v1.2.1 From 9ebaffbd531f0db4b3f528ebb7812b281520117d Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Tue, 31 May 2016 15:56:35 +0200 Subject: Doc: Fix links to other modules -Remove references to Qt WebKit Change-Id: I0bd184021b1a87828e93f5783c38b9ba97f37763 Reviewed-by: Milian Wolff --- src/webchannel/doc/src/javascript.qdoc | 17 ++++++++--------- src/webchannel/qwebchannel.cpp | 2 +- src/webchannel/qwebchannelabstracttransport.cpp | 5 ++--- 3 files changed, 11 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/webchannel/doc/src/javascript.qdoc b/src/webchannel/doc/src/javascript.qdoc index cfb5b21..a508ff9 100644 --- a/src/webchannel/doc/src/javascript.qdoc +++ b/src/webchannel/doc/src/javascript.qdoc @@ -31,21 +31,20 @@ \brief This page explains how to use the JavaScript QWebChannel API in HTML clients. - \section1 Setup + \section1 Setting up the JavaScript API - To communicate with a QWebChannel or WebChannel, any HTML client must use and setup the - JavaScript API provided by \c qwebchannel.js. For HTML clients run inside Qt WebKit, you - can load the file via \c qrc:///qtwebchannel/qwebchannel.js. For external clients you will - need to copy the file to your webserver. Then instantiate a QWebChannel object and pass + To communicate with a QWebChannel or \l [QML] WebChannel, a client must use and set up the + JavaScript API provided by \c qwebchannel.js. For clients run inside \l{Qt WebEngine}, you + can load the file via \c qrc:///qtwebchannel/qwebchannel.js. For external clients, you + need to copy the file to your web server. Then instantiate a QWebChannel object and pass it a transport object and a callback function, which will be invoked once the - initialization of the channel finished and published objects become available. + initialization of the channel finishes and the published objects become available. The transport object implements a minimal message passing interface. It should be an object with a \c send() function, which takes a stringified JSON message and transmits it to the server-side QWebChannelAbstractTransport object. Furthermore, its \c onmessage property should - be called when a message from the server was received. This interface is implemented internally - by the Qt WebKit navigator.qtWebChannelTransport object. Alternatively, you can also use a - WebSocket, which also implements this interface. + be called when a message from the server was received. Alternatively, you can use a + \l{Qt WebSockets}{WebSocket} to implement the interface. Note that the JavaScript QWebChannel object should be constructed once the transport object is fully operational. In case of a WebSocket, that means you should create the QWebChannel in the diff --git a/src/webchannel/qwebchannel.cpp b/src/webchannel/qwebchannel.cpp index d440556..24f99a2 100644 --- a/src/webchannel/qwebchannel.cpp +++ b/src/webchannel/qwebchannel.cpp @@ -63,7 +63,7 @@ QT_BEGIN_NAMESPACE features used by \c{qwebchannel.js}. As such, one can interact with basically any modern HTML browser or standalone JavaScript runtime, such as node.js. - There also exists a declarative WebChannel API. + There also exists a declarative \l{Qt WebChannel QML Types}{WebChannel API}. \sa {Qt WebChannel Standalone Example}, {Qt WebChannel JavaScript API}{JavaScript API} */ diff --git a/src/webchannel/qwebchannelabstracttransport.cpp b/src/webchannel/qwebchannelabstracttransport.cpp index 8d91dd1..771325a 100644 --- a/src/webchannel/qwebchannelabstracttransport.cpp +++ b/src/webchannel/qwebchannelabstracttransport.cpp @@ -44,9 +44,8 @@ QT_BEGIN_NAMESPACE Users of the QWebChannel must implement this interface and connect instances of it to the QWebChannel server for every client that should be connected to the QWebChannel. - The {Qt WebChannel Standalone Example}{Standalone Example} shows how this can be done - using Qt WebSockets. Qt WebKit implements this interface internally and uses the native - WebKit IPC mechanism to transmit messages to HTML clients. + The \l{Qt WebChannel Standalone Example} shows how this can be done + using \l{Qt WebSockets}. \note The JSON message protocol is considered internal and might change over time. -- cgit v1.2.1 From d2e2afcea59ec4e9d5edc30bad0866a8c18647b8 Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Tue, 31 May 2016 16:37:14 +0200 Subject: Doc: Use standard verb form to start function docs For consistency, the first verb should be in 3rd person singular form. Change-Id: I5e24ecbbac1b1ab85e737f127b021f24a55c8dd4 Reviewed-by: Milian Wolff --- src/webchannel/qwebchannel.cpp | 8 ++++---- src/webchannel/qwebchannelabstracttransport.cpp | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/webchannel/qwebchannel.cpp b/src/webchannel/qwebchannel.cpp index 24f99a2..1e8ed8f 100644 --- a/src/webchannel/qwebchannel.cpp +++ b/src/webchannel/qwebchannel.cpp @@ -46,7 +46,7 @@ QT_BEGIN_NAMESPACE \class QWebChannel \inmodule QtWebChannel - \brief Expose QObjects to remote HTML clients. + \brief Exposes QObjects to remote HTML clients. \since 5.4 The QWebChannel fills the gap between C++ applications and HTML/JavaScript @@ -130,7 +130,7 @@ QWebChannel::~QWebChannel() } /*! - Register a group of objects to the QWebChannel. + Registers a group of objects to the QWebChannel. The properties, signals and public invokable methods of the objects are published to the remote clients. There, an object with the identifier used as key in the \a objects map is then constructed. @@ -160,7 +160,7 @@ QHash QWebChannel::registeredObjects() const } /*! - Register a single object to the QWebChannel. + Registers a single object to the QWebChannel. The properties, signals and public methods of the \a object are published to the remote clients. There, an object with the identifier \a id is then constructed. @@ -176,7 +176,7 @@ void QWebChannel::registerObject(const QString &id, QObject *object) } /*! - Deregister the given \a object from the QWebChannel. + Deregisters the given \a object from the QWebChannel. Remote clients will receive a \c destroyed signal for the given object. diff --git a/src/webchannel/qwebchannelabstracttransport.cpp b/src/webchannel/qwebchannelabstracttransport.cpp index 771325a..584342b 100644 --- a/src/webchannel/qwebchannelabstracttransport.cpp +++ b/src/webchannel/qwebchannelabstracttransport.cpp @@ -62,7 +62,7 @@ QT_BEGIN_NAMESPACE /*! \fn QWebChannelAbstractTransport::sendMessage(const QJsonObject &message) - Send a JSON \a message to the remote client. An implementation would serialize the message and + Sends a JSON \a message to the remote client. An implementation would serialize the message and transmit it to the remote JavaScript client. */ -- cgit v1.2.1 From 7774f94b5d5cf8cea863ba22258bbd4543fab5ac Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Tue, 31 May 2016 16:55:01 +0200 Subject: Doc: Use 3rd person singular verb form to begin method docs And fix a typo "connectect". Change-Id: I14c4b249af3cad142a5f6042b2059f653a9c3eae Reviewed-by: Milian Wolff --- src/webchannel/qqmlwebchannel.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/webchannel/qqmlwebchannel.cpp b/src/webchannel/qqmlwebchannel.cpp index 277cd62..c9567a3 100644 --- a/src/webchannel/qqmlwebchannel.cpp +++ b/src/webchannel/qqmlwebchannel.cpp @@ -128,8 +128,8 @@ QQmlWebChannel::~QQmlWebChannel() /*! \qmlmethod void WebChannel::registerObjects(QVariantMap objects) - Register objects to make them accessible to HTML clients. The key of the map is used as an identifier - for the object on the client side. + Registers objects to make them accessible to HTML clients. The key of the + map is used as an identifier for the object on the client side. Once registered, all signals and property changes are automatically propagated to the clients. Public invokable methods, including slots, are also accessible to the clients. @@ -161,7 +161,8 @@ QQmlWebChannelAttached *QQmlWebChannel::qmlAttachedProperties(QObject *obj) /*! \qmlmethod void WebChannel::connectTo(QWebChannelAbstractTransport transport) - \brief Connectect to the \a transport, which represents a communication channel to a single client. + \brief Connects to the \a transport, which represents a communication + channel to a single client. The transport object must be an implementation of QWebChannelAbstractTransport. @@ -179,7 +180,7 @@ void QQmlWebChannel::connectTo(QObject *transport) /*! \qmlmethod void WebChannel::disconnectFrom(QWebChannelAbstractTransport transport) - \brief Disconnect the \a transport from this WebChannel. + \brief Disconnects the \a transport from this WebChannel. The client will not be able to communicate with the WebChannel anymore, nor will it receive any signals or property updates. -- cgit v1.2.1 From 224742f0e2e882bce21047622d4c351803b9d486 Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Tue, 31 May 2016 16:33:29 +0200 Subject: Doc: Fix linking to methods and properties within the type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit You don't need the type name for linking within the type docs. Also, the convention in QML and Qt Quick is to use a period and not a double colon. Change-Id: Ic93bae51e766ef782f089ce69dc4e54a712445c6 Reviewed-by: Topi Reiniƶ --- src/webchannel/qqmlwebchannel.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/webchannel/qqmlwebchannel.cpp b/src/webchannel/qqmlwebchannel.cpp index c9567a3..4bd4413 100644 --- a/src/webchannel/qqmlwebchannel.cpp +++ b/src/webchannel/qqmlwebchannel.cpp @@ -63,7 +63,7 @@ QT_BEGIN_NAMESPACE A list of transport objects, which implement QWebChannelAbstractTransport. The transports are used to talk to the remote clients. - \sa WebChannel::connectTo(), WebChannel::disconnectFrom() + \sa connectTo(), disconnectFrom() */ /*! @@ -71,7 +71,7 @@ QT_BEGIN_NAMESPACE \brief A list of objects which should be accessible to remote clients. - The objects must have the attached WebChannel::id property set to an identifier, under which the + The objects must have the attached \l id property set to an identifier, under which the object is then known on the HTML side. Once registered, all signals and property changes are automatically propagated to the clients. @@ -80,7 +80,7 @@ QT_BEGIN_NAMESPACE If one needs to register objects which are not available when the component is created, use the imperative registerObjects method. - \sa WebChannel::registerObjects(), WebChannel::id + \sa registerObjects(), id */ class QQmlWebChannelPrivate : public QWebChannelPrivate @@ -137,7 +137,7 @@ QQmlWebChannel::~QQmlWebChannel() This imperative API can be used to register objects on the fly. For static objects, the declarative registeredObjects property should be preferred. - \sa WebChannel::registeredObjects + \sa registeredObjects */ void QQmlWebChannel::registerObjects(const QVariantMap &objects) { @@ -166,7 +166,7 @@ QQmlWebChannelAttached *QQmlWebChannel::qmlAttachedProperties(QObject *obj) The transport object must be an implementation of QWebChannelAbstractTransport. - \sa WebChannel::transports, WebChannel::disconnectFrom() + \sa transports, disconnectFrom() */ void QQmlWebChannel::connectTo(QObject *transport) { @@ -185,7 +185,7 @@ void QQmlWebChannel::connectTo(QObject *transport) The client will not be able to communicate with the WebChannel anymore, nor will it receive any signals or property updates. - \sa WebChannel::connectTo() + \sa connectTo() */ void QQmlWebChannel::disconnectFrom(QObject *transport) { -- cgit v1.2.1 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 From d3c594c382761241742cd6713f249abeb538ffaa Mon Sep 17 00:00:00 2001 From: Milian Wolff Date: Tue, 21 Jun 2016 11:30:03 +0200 Subject: Properly unwrap QObject signal parameters on the JavaScript side. This enables you to pass `QObject*` parameters via signals to the JavaScript side. The object will be serialized and then unwrapped as needed now. Task-number: QTBUG-54243 Change-Id: Ie8a6d14eb1351f14f1855d242ceb3b3f8262152d Reviewed-by: Andreas Holzammer --- src/webchannel/qwebchannel.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/webchannel/qwebchannel.js b/src/webchannel/qwebchannel.js index 148e70d..b1722df 100644 --- a/src/webchannel/qwebchannel.js +++ b/src/webchannel/qwebchannel.js @@ -313,7 +313,7 @@ function QObject(name, data, webChannel) this.signalEmitted = function(signalName, signalArgs) { - invokeSignalCallbacks(signalName, signalArgs); + invokeSignalCallbacks(signalName, this.unwrapQObject(signalArgs)); } function addMethod(methodData) -- cgit v1.2.1