diff options
author | Milian Wolff <milian.wolff@kdab.com> | 2014-07-16 17:39:31 +0200 |
---|---|---|
committer | Sumedha Widyadharma <sumedha.widyadharma@basyskom.com> | 2014-08-01 09:16:16 +0200 |
commit | b84e46090b5230d7ebcdbdabd8c03a9ae5d2f860 (patch) | |
tree | 9687c3b47f4e77e931916a8afe1d516d3b280101 | |
parent | 5051411b92b4aca4ed5ec462e7b0e52af4d3951e (diff) | |
download | qtwebchannel-b84e46090b5230d7ebcdbdabd8c03a9ae5d2f860.tar.gz |
Add documentation for the QtWebChannel module.
Please proof-read it and tell me what needs to be improved. I assume
most people will probably not use the QWebChannel directly. Rather, they
will only consume its features indirectly through the integration in
QtWebKit/QtWebEngine. Thus the documentation here is for QWebChannel as
a library. User-end documentation should be added to QtWebKit, I think.
Change-Id: I259c204e24331271b8dc74ea11695988234a79d3
Reviewed-by: Jerome Pasion <jerome.pasion@digia.com>
25 files changed, 681 insertions, 85 deletions
@@ -1,19 +1,22 @@ ### Introduction -The `QtWebChannel` module offers Qt applications a seamless way to publish `QObjects` for interaction -from HTML/JavaScript clients. These clients can either be inside local Qt `WebView`s or any other, -potentially remote, client which supports JavaScript and WebSockets. +The Qt WebChannel module offers Qt applications a seamless way to publish `QObjects` for interaction +with HTML/JavaScript clients. These clients can either be inside local Qt `WebView`s or any other, +potentially remote, client which supports JavaScript, as long as a communication channel such +as WebSockets is available. -It uses introspection on the `QObject`s and sends this serialized data to the clients. There, with -the help of a small JavaScript library, an object is created which simulates the API of the `QObject`. -Any invokable methods, including slots, can be called as well as properties read and written. -Additionally you can connect to signals and register JavaScript callbacks as handlers. +Qt WebChannel uses introspection on the `QObject`s and sends this serialized data to the clients. +There, with the help of a small JavaScript library, an object is created which simulates the API of +the `QObject`. Any invokable methods, including slots, can be called as well as properties read and +written. Additionally you can connect to signals and register JavaScript callbacks as handlers. ### Dependencies -This module depends on `QtBase` and `QtWebSockets`. Optionally, an additional module for QtQuick is -build which makes it easy to use the `QWebChannel` from QML. Furthermore, you can decide to use the -native IPC mechanism of `QtWebKit` for efficient message passing to QtQuick `WebView`'s. +This module depends on Qt Core only. Optionally, an additional plugin for Qt Quick is build, which +makes it easy to use a `QWebChannel` from QML. Note that this module alone is not functional. It +is being used in e.g. Qt WebKit to provide a seamless integration of QML/C++ QObjects into JavaScript +clients. You can integrate it in your projects as well, by providing an implementation of the +`QWebChannelAbstractTransport` class, see the `standalone` example for how to do this. ### Building @@ -27,64 +30,29 @@ To use the Qt/C++ library, add the following to your `QMake` project: QT += webchannel -Then, in your C++ code, construct a websocket transport and webchannel, then publish your `QObject`s: +Then, in your C++ code, construct a a webchannel, then publish your `QObject`s: - QWebSocketTransport transport; QWebChannel channel; - channel.connectTo(&transport); - channel.registerObject(QStringLiteral("foo"), myFooObj); .... -On the HTML/JavaScript client side, you need to embed `src/webchannel/qwebchannel.js` and setup -the connection to the WebSocket transport. The base URL for that can be found from C++ via -`transport.baseUrl()` after the transport was initialized, and must be passed to HTML clients: - - <script type="text/javascript" src="path/to/qwebchannel.js"></script> - <script type="text/javascript"> - // note: baseUrl must be known - new QWebChannel(baseUrl, function(channel) { - foo.doStuff(); // calls doStuff slot or invokable method on myFooObj on the C++ side - }); - </script> +Additionally, you need to provide a communication channel to the HTML client. One way is to +use the Qt WebSockets module. On the HTML/JavaScript client side, you need to embed +`src/webchannel/qwebchannel.js` and setup the connection to a client-side transport. An example +which shows all this in action can be found in `examples/standalone`. -An example which shows all this can be found in `examples/standalone`. - -### Usage from QtQuick +### Usage from Qt Quick For QML applications, use the following import: import QtWebChannel 1.0 -Then setup the WebChannel and register objects to it: +Then setup the WebChannel, register objects to it and connect to transport objects: WebChannel { registeredObjects: [foo, bar, ...] - connections: WebViewTransport { - webViewExperimental: yourWebView.experimental - onMessageReceived: { - textEdit.text += "Received message: " + message + "\n"; - } - } - } - -The above uses a `WebViewTransport` for efficient message passing between the server QML application -and HTML clients in a `WebView`, which must be setup as follows: - - WebView { - id: yourWebView - experimental.preferences.navigatorQtObjectEnabled: true + transports: [yourTransport] } -The HTML client finally uses a similar setup as above, but can make use of the embedded resource -for `qwebchannel.js` and the `navigator.qt` object: - - <script type="text/javascript" src="qrc:///qwebchannel/qwebchannel.js"></script> - <script type="text/javascript"> - new QWebChannel(navigator.qt, function(channel) { - // do stuff with published objects - }); - </script> - -To see this in action, take a look at `examples/qml` and run the `example.qml` in `qmlscene`. +To see this in action, take a look at the test code in `tests/auto/qml`. diff --git a/examples/examples.pro b/examples/examples.pro index 63677f5..1cb6c9f 100644 --- a/examples/examples.pro +++ b/examples/examples.pro @@ -1,5 +1,3 @@ TEMPLATE = subdirs -qtHaveModule(widgets):qtHaveModule(websockets) { - SUBDIRS += standalone -} +SUBDIRS += qwebchannel diff --git a/examples/qwebchannel/doc/examples.qdoc b/examples/qwebchannel/doc/examples.qdoc new file mode 100644 index 0000000..613d760 --- /dev/null +++ b/examples/qwebchannel/doc/examples.qdoc @@ -0,0 +1,49 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Milian Wolff <milian.wolff@kdab.com> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWebChannel module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \title Qt WebChannel Examples + \group qtwebchannel-examples + \brief List of Qt WebChannel examples. + + The examples show how to use the QWebChannel C++ and WebChannel QML API. + +*/ diff --git a/examples/qwebchannel/doc/standalone-screenshot.png b/examples/qwebchannel/doc/standalone-screenshot.png Binary files differnew file mode 100644 index 0000000..3c55e19 --- /dev/null +++ b/examples/qwebchannel/doc/standalone-screenshot.png diff --git a/examples/qwebchannel/doc/standalone.qdoc b/examples/qwebchannel/doc/standalone.qdoc new file mode 100644 index 0000000..1d81dad --- /dev/null +++ b/examples/qwebchannel/doc/standalone.qdoc @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Milian Wolff <milian.wolff@kdab.com> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWebChannel module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \example standalone + \title Standalone Example + \ingroup qtwebchannel-examples + \image standalone-screenshot.png + \brief Shows how to use the QWebChannel C++ API to communicate with an external client. + + The standalone example is a simple chat between a pure C++/Qt application and a remote HTML + client running in your default browser. + + The C++ app sets up a QWebChannel and publishes a Dialog object over it. + For the remote client side, \c index.html is opened. Both show a dialog with the list of + received messages and an input box to send messages to the other end. + + The Dialog emits the Dialog::sendText() signal when the user sents a message. The signal + automatically gets propagated to the HTML client. When the user enters a message on the HTML + side, Dialog::receiveText() is called. + + All communication between the HTML client and the C++/Qt server is done over a WebSocket. + The C++ side instantiates a QWebSocketServer and wraps incoming QWebSocket connections + in WebSocketTransport objects, which implement QWebChannelAbstractTransport. These objects are + then connected to the QWebChannel instance. +*/ diff --git a/examples/qwebchannel/qwebchannel.pro b/examples/qwebchannel/qwebchannel.pro new file mode 100644 index 0000000..63677f5 --- /dev/null +++ b/examples/qwebchannel/qwebchannel.pro @@ -0,0 +1,5 @@ +TEMPLATE = subdirs + +qtHaveModule(widgets):qtHaveModule(websockets) { + SUBDIRS += standalone +} diff --git a/examples/standalone/dialog.ui b/examples/qwebchannel/standalone/dialog.ui index 056a3f5..056a3f5 100644 --- a/examples/standalone/dialog.ui +++ b/examples/qwebchannel/standalone/dialog.ui diff --git a/examples/standalone/index.html b/examples/qwebchannel/standalone/index.html index 3cce3ec..3cce3ec 100644 --- a/examples/standalone/index.html +++ b/examples/qwebchannel/standalone/index.html diff --git a/examples/standalone/main.cpp b/examples/qwebchannel/standalone/main.cpp index f407da6..cc22ed3 100644 --- a/examples/standalone/main.cpp +++ b/examples/qwebchannel/standalone/main.cpp @@ -55,6 +55,9 @@ #include "ui_dialog.h" +/*! + An instance of this class gets published over the WebChannel and is then accessible to HTML clients. +*/ class Dialog : public QObject { Q_OBJECT @@ -75,15 +78,24 @@ public: } signals: + /*! + This signal is emitted from the C++ side and the text displayed on the HTML client side. + */ void sendText(const QString &text); public slots: + /*! + This slot is invoked from the HTML client side and the text displayed on the server side. + */ void receiveText(const QString &text) { displayMessage(tr("Received message: %1").arg(text)); } private slots: + /*! + Note that this slot is private and thus not accessible to HTML clients. + */ void clicked() { const QString text = ui.input->text(); @@ -107,21 +119,26 @@ int main(int argc, char** argv) { QApplication app(argc, argv); - QWebChannel channel; + // setup the QWebSocketServer QWebSocketServer server(QStringLiteral("QWebChannel Standalone Example Server"), QWebSocketServer::NonSecureMode); if (!server.listen(QHostAddress::LocalHost)) { qFatal("Failed to open web socket server."); return 1; } + // wrap WebSocket clients in QWebChannelAbstractTransport objects WebSocketClientWrapper clientWrapper(&server); + + // setup the channel + QWebChannel channel; QObject::connect(&clientWrapper, &WebSocketClientWrapper::clientConnected, &channel, &QWebChannel::connectTo); + // setup the dialog and publish it to the QWebChannel Dialog dialog; - channel.registerObject(QStringLiteral("dialog"), &dialog); + // open a browser window with the client HTML page QUrl url = QUrl::fromLocalFile(SOURCE_DIR "/index.html"); url.setQuery(QStringLiteral("webChannelBaseUrl=") + server.serverUrl().toString()); QDesktopServices::openUrl(url); diff --git a/examples/standalone/standalone.pro b/examples/qwebchannel/standalone/standalone.pro index 37b6de3..37b6de3 100644 --- a/examples/standalone/standalone.pro +++ b/examples/qwebchannel/standalone/standalone.pro diff --git a/examples/standalone/websocketclientwrapper.cpp b/examples/qwebchannel/standalone/websocketclientwrapper.cpp index 219050d..0e776e1 100644 --- a/examples/standalone/websocketclientwrapper.cpp +++ b/examples/qwebchannel/standalone/websocketclientwrapper.cpp @@ -55,6 +55,12 @@ QT_BEGIN_NAMESPACE +/*! + Construct the client wrapper with the given parent. + + All clients connecting to the QWebSocketServer will be automatically wrapped + in WebSocketTransport objects. +*/ WebSocketClientWrapper::WebSocketClientWrapper(QWebSocketServer *server, QObject *parent) : QObject(parent) , m_server(server) @@ -63,6 +69,9 @@ WebSocketClientWrapper::WebSocketClientWrapper(QWebSocketServer *server, QObject this, &WebSocketClientWrapper::handleNewConnection); } +/*! + Wrap an incoming WebSocket connection in a WebSocketTransport object. +*/ void WebSocketClientWrapper::handleNewConnection() { emit clientConnected(new WebSocketTransport(m_server->nextPendingConnection())); diff --git a/examples/standalone/websocketclientwrapper.h b/examples/qwebchannel/standalone/websocketclientwrapper.h index 1f742f7..1f742f7 100644 --- a/examples/standalone/websocketclientwrapper.h +++ b/examples/qwebchannel/standalone/websocketclientwrapper.h diff --git a/examples/standalone/websockettransport.cpp b/examples/qwebchannel/standalone/websockettransport.cpp index f1ecee2..5714463 100644 --- a/examples/standalone/websockettransport.cpp +++ b/examples/qwebchannel/standalone/websockettransport.cpp @@ -57,6 +57,11 @@ QT_BEGIN_NAMESPACE +/*! + Construct the transport object and wrap the given socket. + + The socket is also set as the parent of the transport object. +*/ WebSocketTransport::WebSocketTransport(QWebSocket *socket) : QWebChannelAbstractTransport(socket) , m_socket(socket) @@ -65,17 +70,26 @@ WebSocketTransport::WebSocketTransport(QWebSocket *socket) this, &WebSocketTransport::textMessageReceived); } +/*! + Destroys the WebSocketTransport. +*/ WebSocketTransport::~WebSocketTransport() { } +/*! + Serialize the JSON message and send it as a text message via the WebSocket to the client. +*/ void WebSocketTransport::sendMessage(const QJsonObject &message) { QJsonDocument doc(message); m_socket->sendTextMessage(QString::fromUtf8(doc.toJson(QJsonDocument::Compact))); } +/*! + Deserialize the stringified JSON messageData and emit messageReceived. +*/ void WebSocketTransport::textMessageReceived(const QString &messageData) { QJsonParseError error; diff --git a/examples/standalone/websockettransport.h b/examples/qwebchannel/standalone/websockettransport.h index 828ac00..828ac00 100644 --- a/examples/standalone/websockettransport.h +++ b/examples/qwebchannel/standalone/websockettransport.h diff --git a/src/webchannel/doc/qtwebchannel.qdocconf b/src/webchannel/doc/qtwebchannel.qdocconf new file mode 100644 index 0000000..e2ed336 --- /dev/null +++ b/src/webchannel/doc/qtwebchannel.qdocconf @@ -0,0 +1,56 @@ +include($QT_INSTALL_DOCS/global/qt-module-defaults.qdocconf) + +project = QtWebChannel +description = Qt WebChannel Reference Documentation +version = $QT_VERSION + +examplesinstallpath = webchannel + +qhp.projects = QtWebChannel + +qhp.QtWebChannel.file = qtwebchannel.qhp +qhp.QtWebChannel.namespace = org.qt-project.qtwebchannel.$QT_VERSION_TAG +qhp.QtWebChannel.virtualFolder = qtwebchannel +qhp.QtWebChannel.indexTitle = Qt WebChannel +qhp.QtWebChannel.indexRoot = + +qhp.QtWebChannel.filterAttributes = qtwebchannel $QT_VERSION qtrefdoc +qhp.QtWebChannel.customFilters.Qt.name = QtWebChannel $QT_VERSION +qhp.QtWebChannel.customFilters.Qt.filterAttributes = qtwebchannel $QT_VERSION + +qhp.QtWebChannel.subprojects = classes qml examples javascript + +qhp.QtWebChannel.subprojects.classes.title = C++ Classes +qhp.QtWebChannel.subprojects.classes.indexTitle = Qt WebChannel C++ Classes +qhp.QtWebChannel.subprojects.classes.selectors = class fake:headerfile +qhp.QtWebChannel.subprojects.classes.sortPages = true + +qhp.QtWebChannel.subprojects.qml.title = QML Types +qhp.QtWebChannel.subprojects.qml.indexTitle = Qt WebChannel QML Types +qhp.QtWebChannel.subprojects.qml.selectors = qmlclass +qhp.QtWebChannel.subprojects.qml.sortPages = true + +qhp.QtWebChannel.subprojects.examples.title = Examples +qhp.QtWebChannel.subprojects.examples.indexTitle = Qt WebChannel Examples +qhp.QtWebChannel.subprojects.examples.selectors = fake:example +qhp.QtWebChannel.subprojects.examples.sortPages = true + +qhp.QtWebChannel.subprojects.javascript.title = JavaScript API +qhp.QtWebChannel.subprojects.javascript.indexTitle = Qt WebChannel JavaScript API + +tagfile = ../../../doc/qtwebchannel/qtwebchannel.tags + +depends += qtcore qtquick qtqml qmake + +headerdirs += .. \ + ../../imports + +sourcedirs += .. \ + ../../imports + + +exampledirs += ../../../examples/webchannel + +navigation.landingpage = "Qt WebChannel" +navigation.cppclassespage = "Qt WebChannel C++ Classes" +navigation.qmltypespage = "Qt WebChannel QML Types" diff --git a/src/webchannel/doc/src/index.qdoc b/src/webchannel/doc/src/index.qdoc new file mode 100644 index 0000000..635c8bd --- /dev/null +++ b/src/webchannel/doc/src/index.qdoc @@ -0,0 +1,47 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Milian Wolff <milian.wolff@kdab.com> +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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$ +** +****************************************************************************/ + +/*! + \page qtwebchannel-index.html + \since 5.4 + \title Qt WebChannel + \brief Bridges the gap between C++/QML and HTML/JavaScript. + + The Qt WebChannel module provides a library for seamless integration of C++/QML applications + with HTML/JavaScript clients. Any QObject can be published to remote clients, where its public + API becomes available. + + \section1 Related Information + + For more information on how to use this module, please refer to the following pages: + + \list + \li \l{Qt WebChannel C++ Classes} explains QWebChannel C++ API. + \li \l{Qt WebChannel QML Types} explains the WebChannel QML API. + \li The \l{Qt WebChannel Examples} show how use the API in practice. + \endlist +*/ diff --git a/src/webchannel/doc/src/javascript.qdoc b/src/webchannel/doc/src/javascript.qdoc new file mode 100644 index 0000000..36bc4ab --- /dev/null +++ b/src/webchannel/doc/src/javascript.qdoc @@ -0,0 +1,100 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Milian Wolff <milian.wolff@kdab.com> +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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$ +** +****************************************************************************/ + +/*! + \title Qt WebChannel JavaScript API + \page qtwebchannel-javascript.html + + \brief This page explains how to use the JavaScript QWebChannel API in HTML clients. + + \section1 Setup + + 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 QtWebKit, 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 + it a transport object and a callback function, which will be invoked once the + initialization of the channel finished and 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 QtWebKit navigator.qtWebChannelTransport object. Alternatively, you can also use a + WebSocket, which also implements this 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 + socket's \c onopen handler. Take a look at the \l{Standalone Example} to see how this is done. + + \section1 Interacting with QObjects + + Once the callback passed to the QWebChannel object is invoked, the channel has finished + initialization and all published objects are accessible to the HTML client via the \c channel.objects + property. Thus, assuming an object was published with the identifier "foo", then we can interact with it + as shown in the example below. Note that all communication between the HTML client and + the QML/C++ server is asynchronous. Properties are cached on the HTML side. Furthermore + keep in mind that only QML/C++ data types which can be converted to JSON will be (de-)serialized + properly and thus accessible to HTML clients. + + \code +new QWebChannel(yourTransport, function(channel) { + + // Connect to a signal: + channel.objects.foo.mySignal.connect(function() { + // This callback will be invoked whenever the signal is emitted on the C++/QML side. + console.log(arguments); + }); + + // To make the object known globally, assign it to the window object, i.e.: + window.foo = channel.objects.foo; + + // Invoke a method: + foo.myMethod(arg1, arg2, function(returnValue) { + // This callback will be invoked when myMethod has a return value. Keep in mind that + // the communication is asynchronous, hence the need for this callback. + console.log(returnValue); + }); + + // Read a property value, which is cached on the client side: + console.log(foo.myProperty); + + // Writing a property will instantly update the client side cache. + // The remote end will be notified about the change asynchronously + foo.myProperty = "Hello World!"; + + // To get notified about remote property changes, + // simply connect to the corresponding notify signal: + foo.onMyPropertyChanged.connect(function(newValue) { + console.log(newValue); + }); + + // One can also access enums that are marked with Q_ENUM: + console.log(foo.MyEnum.MyEnumerator); +}); + \endcode +*/ diff --git a/src/webchannel/doc/src/module.qdoc b/src/webchannel/doc/src/module.qdoc new file mode 100644 index 0000000..345485e --- /dev/null +++ b/src/webchannel/doc/src/module.qdoc @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Milian Wolff <milian.wolff@kdab.com> +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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$ +** +****************************************************************************/ + +/*! + \module QtWebChannel + \title Qt WebChannel C++ Classes + \ingroup modules + \qtvariable webchannel + \since 5.4 + \brief List of C++ classes that provide the QtWebChannel functionality. + + To use these classes in your application, use the following include + statement: + + \code + #include <QtWebChannel/QtWebChannel> + \endcode + + To link against the module, add this line to your \l qmake \c .pro file: + + \code + QT += webchannel + \endcode +*/ + +/*! + \qmlmodule QtWebChannel 1.0 + \title Qt WebChannel QML Types + \since 5.4 + \brief List of QML types that provide WebChannel functionality. + + The QML types are accessed by using: + \badcode + import QtWebChannel 1.0 + \endcode +*/ diff --git a/src/webchannel/qqmlwebchannel.cpp b/src/webchannel/qqmlwebchannel.cpp index ca99fe5..ad17ce7 100644 --- a/src/webchannel/qqmlwebchannel.cpp +++ b/src/webchannel/qqmlwebchannel.cpp @@ -51,6 +51,46 @@ QT_BEGIN_NAMESPACE +/*! + \qmltype WebChannel + \instantiates QQmlWebChannel + + \inqmlmodule QtWebChannel + \ingroup webchannel-qml + \brief QML interface to QWebChannel. + \since 5.4 + + The WebChannel provides a mechanism to transparently access QObject or QML objects from HTML + clients. All properties, signals and public slots can be used from the HTML clients. + + \sa QWebChannel +*/ + +/*! + \qmlproperty QQmlListProperty<QObject> WebChannel::transports + A list of transport objects, which implement QWebChannelAbstractTransport. The transports + are used to talk to the remote clients. + + \sa WebChannel::connectTo(), WebChannel::disconnectFrom() +*/ + +/*! + \qmlproperty QQmlListProperty<QObject> WebChannel::registeredObjects + + \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 + object is then known on the HTML 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. + + 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 +*/ + class QQmlWebChannelPrivate : public QWebChannelPrivate { Q_DECLARE_PUBLIC(QQmlWebChannel) @@ -60,6 +100,12 @@ public: void _q_objectIdChanged(const QString &newId); }; +/*! + \internal + + Update the name of the sender object, when its attached WebChannel.id property changed. + This is required, since during startup the property is empty and only gets set later on. +*/ void QQmlWebChannelPrivate::_q_objectIdChanged(const QString &newId) { Q_Q(QQmlWebChannel); @@ -88,6 +134,19 @@ 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. + + Once registered, all signals and property changes are automatically propagated to the clients. + Public invokable methods, including slots, are also accessible to the clients. + + 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 +*/ void QQmlWebChannel::registerObjects(const QVariantMap &objects) { Q_D(QQmlWebChannel); @@ -107,6 +166,15 @@ QQmlWebChannelAttached *QQmlWebChannel::qmlAttachedProperties(QObject *obj) return new QQmlWebChannelAttached(obj); } +/*! + \qmlmethod void WebChannel::connectTo(QWebChannelAbstractTransport transport) + + \brief Connectect to the \a transport, which represents a communication channel to a single client. + + The transport object must be an implementation of QWebChannelAbstractTransport. + + \sa WebChannel::transports, WebChannel::disconnectFrom() +*/ void QQmlWebChannel::connectTo(QObject *transport) { if (QWebChannelAbstractTransport *realTransport = qobject_cast<QWebChannelAbstractTransport*>(transport)) { @@ -116,6 +184,16 @@ void QQmlWebChannel::connectTo(QObject *transport) } } +/*! + \qmlmethod void WebChannel::disconnectFrom(QWebChannelAbstractTransport transport) + + \brief Disconnect 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. + + \sa WebChannel::connectTo() +*/ void QQmlWebChannel::disconnectFrom(QObject *transport) { if (QWebChannelAbstractTransport *realTransport = qobject_cast<QWebChannelAbstractTransport*>(transport)) { diff --git a/src/webchannel/qqmlwebchannelattached.cpp b/src/webchannel/qqmlwebchannelattached.cpp index cfe03f8..257c6a9 100644 --- a/src/webchannel/qqmlwebchannelattached.cpp +++ b/src/webchannel/qqmlwebchannelattached.cpp @@ -54,6 +54,15 @@ QQmlWebChannelAttached::~QQmlWebChannelAttached() } +/*! + \qmlattachedproperty QString WebChannel::id + + \brief The identifier under which an object, registered to a WebChannel, is known to remote clients. + + This property must be set for every object that should be published over the WebChannel. + While no restrictions are enforced on the format of the id, it is usually a good idea to + choose a string that is also a valid JavaScript identifier. +*/ QString QQmlWebChannelAttached::id() const { return m_id; diff --git a/src/webchannel/qwebchannel.cpp b/src/webchannel/qwebchannel.cpp index 3aebb14..a518d26 100644 --- a/src/webchannel/qwebchannel.cpp +++ b/src/webchannel/qwebchannel.cpp @@ -50,6 +50,37 @@ QT_BEGIN_NAMESPACE +/*! + \class QWebChannel + + \inmodule QtWebChannel + \brief Expose QObjects to remote HTML clients. + \since 5.4 + + The QWebChannel fills the gap between C++ applications and HTML/JavaScript + applications. By publishing a QObject derived object to a QWebChannel and + using \l{qtwebchannel-javascript.html}{\c qwebchannel.js} on the HTML side, one can transparently access + properties and public slots and methods of the QObject. No manual message + passing and serialization of data is required, property updates and signal emission + on the C++ side get automatically transmitted to the potentially remotely running HTML clients. + On the client side, a JavaScript object will be created for any published C++ QObject. It mirrors the + C++ object's API and thus is intuitively useable. + + The C++ QWebChannel API makes it possible to talk to any HTML client, which could run on a local + or even remote machine. The only limitation is that the HTML client supports the JavaScript + features used by \l{qtwebchannel-javascript.html}{\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. + + \sa {Standalone Example} +*/ + +/*! + \internal + + Remove a destroyed transport object from the list of known transports. +*/ void QWebChannelPrivate::_q_transportDestroyed(QObject *object) { const int idx = transports.indexOf(static_cast<QWebChannelAbstractTransport*>(object)); @@ -58,6 +89,11 @@ void QWebChannelPrivate::_q_transportDestroyed(QObject *object) } } +/*! + \internal + + Shared code to initialize the QWebChannel from both constructors. +*/ void QWebChannelPrivate::init() { Q_Q(QWebChannel); @@ -66,6 +102,13 @@ void QWebChannelPrivate::init() q, SIGNAL(blockUpdatesChanged(bool))); } +/*! + Constructs the QWebChannel object with the given \a parent. + + Note that a QWebChannel is only fully operational once you connect it to a + QWebChannelAbstractTransport. The HTML clients also need to be setup appropriately + using \l{qtwebchannel-javascript.html}{\c qwebchannel.js}. +*/ QWebChannel::QWebChannel(QObject *parent) : QObject(*(new QWebChannelPrivate), parent) { @@ -73,6 +116,13 @@ QWebChannel::QWebChannel(QObject *parent) d->init(); } +/*! + \internal + + Construct a QWebChannel from an ancestor class with the given \a parent. + + \sa QQmlWebChannel +*/ QWebChannel::QWebChannel(QWebChannelPrivate &dd, QObject *parent) : QObject(dd, parent) { @@ -80,10 +130,23 @@ QWebChannel::QWebChannel(QWebChannelPrivate &dd, QObject *parent) d->init(); } +/*! + Destroys the QWebChannel. +*/ QWebChannel::~QWebChannel() { } +/*! + Register a group of objects to the QWebChannel. + + The properties, signals and public 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. + + \note A current limitation is that objects must be registered before any client is initialized. + + \sa QWebChannel::registerObject(), QWebChannel::deregisterObject(), QWebChannel::registeredObjects() +*/ void QWebChannel::registerObjects(const QHash< QString, QObject * > &objects) { Q_D(QWebChannel); @@ -93,18 +156,40 @@ void QWebChannel::registerObjects(const QHash< QString, QObject * > &objects) } } +/*! + Returns the map of registered objects that are published to remote clients. + + \sa QWebChannel::registerObjects(), QWebChannel::registerObject(), QWebChannel::deregisterObject() +*/ QHash<QString, QObject *> QWebChannel::registeredObjects() const { Q_D(const QWebChannel); return d->publisher->registeredObjects; } +/*! + Register 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. + + \note A current limitation is that objects must be registered before any client is initialized. + + \sa QWebChannel::registerObjects(), QWebChannel::deregisterObject(), QWebChannel::registeredObjects() +*/ void QWebChannel::registerObject(const QString &id, QObject *object) { Q_D(QWebChannel); d->publisher->registerObject(id, object); } +/*! + Deregister the given \a object from the QWebChannel. + + Remote clients will receive a \c destroyed signal for the given object. + + \sa QWebChannel::registerObjects(), QWebChannel::registerObject(), QWebChannel::registeredObjects() +*/ void QWebChannel::deregisterObject(QObject *object) { Q_D(QWebChannel); @@ -112,6 +197,16 @@ void QWebChannel::deregisterObject(QObject *object) d->publisher->signalEmitted(object, s_destroyedSignalIndex, QVariantList() << QVariant::fromValue(object)); } +/*! + \property QWebChannel::blockUpdates + + \brief When set to true, updates are blocked and remote clients will not be notified about property changes. + + The changes are recorded and sent to the clients once updates become unblocked again by setting + this property to false. +*/ + + bool QWebChannel::blockUpdates() const { Q_D(const QWebChannel); @@ -124,6 +219,14 @@ void QWebChannel::setBlockUpdates(bool block) d->publisher->setBlockUpdates(block); } +/*! + Connects the QWebChannel to the given \a transport object. + + The transport object then handles the communication between the C++ application and a remote + HTML client. + + \sa QWebChannelAbstractTransport, QWebChannel::disconnectFrom() +*/ void QWebChannel::connectTo(QWebChannelAbstractTransport *transport) { Q_D(QWebChannel); @@ -138,6 +241,11 @@ void QWebChannel::connectTo(QWebChannelAbstractTransport *transport) } } +/*! + Disconnects the QWebChannel from the \a transport object. + + \sa QWebChannel::connectTo() +*/ void QWebChannel::disconnectFrom(QWebChannelAbstractTransport *transport) { Q_D(QWebChannel); diff --git a/src/webchannel/qwebchannel.h b/src/webchannel/qwebchannel.h index 46d77a3..7701751 100644 --- a/src/webchannel/qwebchannel.h +++ b/src/webchannel/qwebchannel.h @@ -62,32 +62,13 @@ public: explicit QWebChannel(QObject *parent = 0); ~QWebChannel(); - /** - * Register a map of string ID to QObject* objects. - * - * The properties, signals and public methods of the QObject are - * published to the remote client, where an object with the given identifier - * is constructed. - * - * TODO: This must be called, before clients are initialized. - */ void registerObjects(const QHash<QString, QObject*> &objects); QHash<QString, QObject*> registeredObjects() const; Q_INVOKABLE void registerObject(const QString &id, QObject *object); Q_INVOKABLE void deregisterObject(QObject *object); - /** - * @return true when property updates are blocked, false otherwise. - */ bool blockUpdates() const; - /** - * Set whether property updates should be blocked or not. - * - * When they are blocked, the remote clients will not be notified about - * property changes. The changes are recorded and sent to the clients once - * setBlockUpdates(false) is called. - */ void setBlockUpdates(bool block); Q_SIGNALS: diff --git a/src/webchannel/qwebchannelabstracttransport.cpp b/src/webchannel/qwebchannelabstracttransport.cpp index 86c3121..0d56ff6 100644 --- a/src/webchannel/qwebchannelabstracttransport.cpp +++ b/src/webchannel/qwebchannelabstracttransport.cpp @@ -43,16 +43,53 @@ QT_BEGIN_NAMESPACE +/*! + \class QWebChannelAbstractTransport + + \inmodule QtWebChannel + \brief Communication channel between the C++ QWebChannel server and a HTML/JS client. + \since 5.4 + + 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 {Standalone Example} shows how this can be done using QtWebSockets. QtWebKit implements + this interface internally and uses the native WebKit IPC mechanism to transmit messages + to HTML clients. + + \note The JSON message protocol is considered internal and might change over time. + + \sa {Standalone Example} +*/ + +/*! + \fn QWebChannelAbstractTransport::messageReceived(const QJsonObject &message, QWebChannelAbstractTransport *transport) + + This signal must be emitted when a new JSON \a message was received from the remote client. The + \a transport argument should be set to this transport object. +*/ + +/*! + \fn QWebChannelAbstractTransport::sendMessage(const QJsonObject &message) + + Send a JSON \a message to the remote client. An implementation would serialize the message and + transmit it to the remote JavaScript client. +*/ + +/*! + Constructs a transport object with the given \a parent. +*/ QWebChannelAbstractTransport::QWebChannelAbstractTransport(QObject *parent) : QObject(parent) { } +/*! + Destroys the transport object. +*/ QWebChannelAbstractTransport::~QWebChannelAbstractTransport() { } - QT_END_NAMESPACE diff --git a/src/webchannel/qwebchannelabstracttransport.h b/src/webchannel/qwebchannelabstracttransport.h index a13851c..b98ba3f 100644 --- a/src/webchannel/qwebchannelabstracttransport.h +++ b/src/webchannel/qwebchannelabstracttransport.h @@ -56,15 +56,9 @@ public: virtual ~QWebChannelAbstractTransport(); public Q_SLOTS: - /** - * Send a text @p message to the remote client. - */ virtual void sendMessage(const QJsonObject &message) = 0; Q_SIGNALS: - /** - * Emitted when a new text message was received from the remote client. - */ void messageReceived(const QJsonObject &message, QWebChannelAbstractTransport *transport); }; diff --git a/src/webchannel/webchannel.pro b/src/webchannel/webchannel.pro index d368237..024956e 100644 --- a/src/webchannel/webchannel.pro +++ b/src/webchannel/webchannel.pro @@ -4,6 +4,8 @@ CONFIG += warn_on strict_flags load(qt_module) +QMAKE_DOCS = $$PWD/doc/qtwebchannel.qdocconf + RESOURCES += \ resources.qrc |