summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMilian Wolff <milian.wolff@kdab.com>2013-01-18 16:27:42 +0100
committerPierre Rossi <pierre.rossi@gmail.com>2013-11-01 13:57:42 +0100
commit62c243c979b172ae554f372a0d883c0273cafc53 (patch)
tree432211b3d834cf3702012afffc510c349e436e3b /src
parentb23f72024c14153d233563f600a359456649aaaf (diff)
downloadqtwebchannel-62c243c979b172ae554f372a0d883c0273cafc53.tar.gz
Refactor the QObject QWebChannel and make the API reusable.
It might becme a very common use case of the QWebChannel QML plugin. Thus it should be as simple as possible for third party consumers to setup a QWebChannel for QObject publishing. The new API basically moves the QtMetaObjectPublisher along with the JavaScript marshalling to the qwebchannl/src folder. The updated qtobject example shows how this new API can be used. Furthermore note how it is now trivially possible to register multiple objects, which was not easily possible before. Some notes on the applied refactoring: - qobject.js contains the JavaScript QObject binding and was refactored to support multiple objects. - the MetaObjectPublisher contains a new handleRequest function which handles the QML-side of the QObject binding. This is implemented in QML, while the other book keeping and esp. the classInfoForObject is still handled in C++ via the QtMetaObjectPublisher class (which is registered as MetaObjectPublisherPrivate and used by MetaObjectPublisher) Change-Id: Id45121bb654447e095bf8a8062d0c8edf9dcb018 Reviewed-by: Pierre Rossi <pierre.rossi@gmail.com>
Diffstat (limited to 'src')
-rw-r--r--src/MetaObjectPublisher.qml74
-rw-r--r--src/qmldir3
-rw-r--r--src/qobject.js119
-rw-r--r--src/qtmetaobjectpublisher.cpp73
-rw-r--r--src/qtmetaobjectpublisher.h74
-rw-r--r--src/qwebchannel.cpp9
-rw-r--r--src/qwebchannel_plugin.cpp3
-rw-r--r--src/resources.qrc1
-rw-r--r--src/src.pri4
-rw-r--r--src/src.pro7
-rw-r--r--src/webchannel-iframe.html1
11 files changed, 361 insertions, 7 deletions
diff --git a/src/MetaObjectPublisher.qml b/src/MetaObjectPublisher.qml
new file mode 100644
index 0000000..e938a83
--- /dev/null
+++ b/src/MetaObjectPublisher.qml
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QWebChannel module on Qt labs.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** 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, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+import Qt.labs.WebChannel 1.0
+
+MetaObjectPublisherPrivate {
+ function handleRequest(payload, webChannel) {
+ var object = publisher.namedObject(payload.object);
+ var ret = false;
+ if (payload.type == "Qt.invokeMethod") {
+ ret = (object[payload.method])(payload.args);
+ } else if (payload.type == "Qt.connectToSignal") {
+ object[payload.signal].connect(
+ function(a,b,c,d,e,f,g,h,i,j) {
+ webChannel.broadcast("Qt.signal", JSON.stringify({object: payload.object, signal: payload.signal, args: [a,b,c,d,e,f,g,h,i,j]}));
+ });
+ } else if (payload.type == "Qt.getProperty") {
+ ret = object[payload.property];
+ } else if (payload.type == "Qt.setProperty") {
+ object[payload.property] = payload.value;
+ } else if (payload.type == "Qt.getObjects") {
+ var objects = {};
+ var objectNames = publisher.objectNames;
+ for (var i = 0; i < objectNames.length; ++i) {
+ var name = objectNames[i];
+ var object = publisher.namedObject(name);
+ objects[name] = publisher.classInfoForObject(object);
+ }
+ ret = objects;
+ }
+
+ return ret;
+ }
+} \ No newline at end of file
diff --git a/src/qmldir b/src/qmldir
index 38d107a..9ec75e6 100644
--- a/src/qmldir
+++ b/src/qmldir
@@ -1,2 +1,3 @@
+module Qt.labs.WebChannel
plugin qwebchannel
-
+MetaObjectPublisher 1.0 MetaObjectPublisher.qml \ No newline at end of file
diff --git a/src/qobject.js b/src/qobject.js
new file mode 100644
index 0000000..d5d7f42
--- /dev/null
+++ b/src/qobject.js
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QWebChannel module on Qt labs.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** 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, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+function QObject(name, data, webChannel) {
+ this.__id__ = name;
+ this.__objectSignals__ = {};
+
+ var methodsAndSignals = [];
+ for (var i in data.methods)
+ methodsAndSignals.push(data.methods[i]);
+ for (i in data.signals)
+ methodsAndSignals.push(data.signals[i]);
+
+ var object = this;
+
+ methodsAndSignals.forEach(function(method) {
+ object[method] = function() {
+ var args = [];
+ var callback;
+ for (var i = 0; i < arguments.length; ++i) {
+ if (typeof arguments[i] == "function")
+ callback = arguments[i];
+ else
+ args.push(arguments[i]);
+ }
+
+ webChannel.exec(JSON.stringify({"type": "Qt.invokeMethod", "object": object.__id__, "method": method, "args": args}), function(response) {
+ if (response.length)
+ (callback)(JSON.parse(response));
+ });
+ };
+ });
+
+ for (i in data.signals) {
+ var signal = data.signals[i];
+ object[signal].connect = function(callback) {
+ object.__objectSignals__[signal] = object.__objectSignals__[signal] || [];
+ webChannel.exec(JSON.stringify({"type": "Qt.connectToSignal", "object": object.__id__, "signal": signal}));
+ object.__objectSignals__[signal].push(callback);
+ };
+ }
+
+ for (i in data.properties) {
+ var prop = data.properties[i];
+ object.__defineSetter__(prop, function(value) {
+ webChannel.exec(JSON.stringify({"type": "Qt.setProperty", "object": object.__id__, "property": prop, "value": value }));
+ });
+ object.__defineGetter__(prop, function() {
+ return (function(callback) {
+ webChannel.exec(JSON.stringify({"type": "Qt.getProperty", "object": object.__id__, "property": prop}), function(response) {
+ callback(JSON.parse(response));
+ });
+ });
+ });
+ }
+}
+
+window.setupQObjectWebChannel = function(webChannel) {
+ webChannel.subscribe(
+ "Qt.signal",
+ function(payload) {
+ var signalData = JSON.parse(payload);
+ var object = window[signalData.object];
+ var conns = (object ? object.__objectSignals__[signalData.signal] : []) || [];
+ var a = payload.args;
+ conns.forEach(function(callback) {
+ callback.call(a);
+ });
+ }
+ );
+ webChannel.exec(JSON.stringify({type:"Qt.getObjects"}), function(response) {
+ if (response.length) {
+ var objects = JSON.parse(response);
+ for (var objectName in objects) {
+ var data = objects[objectName];
+ var object = new QObject(objectName, data, webChannel);
+ window[objectName] = object;
+ }
+ }
+ });
+};
diff --git a/src/qtmetaobjectpublisher.cpp b/src/qtmetaobjectpublisher.cpp
new file mode 100644
index 0000000..d136ce7
--- /dev/null
+++ b/src/qtmetaobjectpublisher.cpp
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QWebChannel module on Qt labs.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** 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, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtmetaobjectpublisher.h"
+#include <QVariantMap>
+#include <QStringList>
+#include <QMetaObject>
+#include <QMetaProperty>
+
+QtMetaObjectPublisher::QtMetaObjectPublisher(QObject *parent) :
+ QObject(parent)
+{
+}
+
+QVariantMap QtMetaObjectPublisher::classInfoForObject(QObject *object)
+{
+ QVariantMap data;
+ QStringList qtSignals, qtMethods, qtProperties;
+ const QMetaObject* metaObject = object->metaObject();
+ for (int i = 0; i < metaObject->propertyCount(); ++i)
+ qtProperties.append(metaObject->property(i).name());
+ for (int i = 0; i < metaObject->methodCount(); ++i) {
+ QMetaMethod method = metaObject->method(i);
+ QString signature = method.methodSignature();
+ QString name = signature.left(signature.indexOf("("));
+ if (method.access() == QMetaMethod::Public)
+ qtMethods << signature << name;
+ if (method.methodType() == QMetaMethod::Signal)
+ qtSignals << signature << name;
+ }
+ data["signals"] = qtSignals;
+ data["methods"] = qtMethods;
+ data["properties"] = qtProperties;
+ return data;
+}
diff --git a/src/qtmetaobjectpublisher.h b/src/qtmetaobjectpublisher.h
new file mode 100644
index 0000000..816338a
--- /dev/null
+++ b/src/qtmetaobjectpublisher.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QWebChannel module on Qt labs.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** 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, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTMETAOBJECTPUBLISHER_H
+#define QTMETAOBJECTPUBLISHER_H
+
+#include <QObject>
+#include <QVariantMap>
+#include <QPointer>
+#include <QStringList>
+
+class QtMetaObjectPublisher : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QStringList objectNames READ objectNames)
+public:
+ explicit QtMetaObjectPublisher(QObject *parent = 0);
+ Q_INVOKABLE QVariantMap classInfoForObject(QObject*);
+ QStringList objectNames() { return objects.keys(); }
+ Q_INVOKABLE QObject* namedObject(const QString& name) {
+ if (!objects.contains(name))
+ return 0;
+ return objects[name];
+ }
+public slots:
+ void addObject(const QString& name, QObject* object)
+ {
+ objects[name] = object;
+ }
+
+private:
+ QMap<QString, QPointer<QObject> > objects;
+
+};
+
+#endif // QTMETAOBJECTPUBLISHER_H
diff --git a/src/qwebchannel.cpp b/src/qwebchannel.cpp
index 6d7d62f..ee03cf8 100644
--- a/src/qwebchannel.cpp
+++ b/src/qwebchannel.cpp
@@ -311,6 +311,15 @@ void QWebChannelPrivate::handleHttpRequest(QTcpSocket *socket, const HttpRequest
socket->write("\n})();");
socket->close();
file.close();
+ } else if (type == "qobject.js") {
+ QFile file(":/qobject.js");
+ file.open(QIODevice::ReadOnly);
+ socket->write("HTTP/1.1 200 OK\r\n"
+ "Content-Type: text/javascript\r\n"
+ "\r\n");
+ socket->write(file.readAll());
+ socket->close();
+ file.close();
} else if (type == "iframe.html") {
QFile file(":/webchannel-iframe.html");
file.open(QIODevice::ReadOnly);
diff --git a/src/qwebchannel_plugin.cpp b/src/qwebchannel_plugin.cpp
index a0675d6..1c71463 100644
--- a/src/qwebchannel_plugin.cpp
+++ b/src/qwebchannel_plugin.cpp
@@ -42,12 +42,13 @@
#include <qqml.h>
#include "qwebchannel.h"
+#include "qtmetaobjectpublisher.h"
#include "qwebchannel_plugin.h"
void QWebChannelPlugin::registerTypes(const char *uri)
{
- Q_ASSERT(uri == QLatin1String("Qt.labs.WebChannel"));
qmlRegisterType<QWebChannel>(uri, 1, 0, "WebChannel");
+ qmlRegisterType<QtMetaObjectPublisher>(uri, 1, 0, "MetaObjectPublisherPrivate");
}
diff --git a/src/resources.qrc b/src/resources.qrc
index 6f81393..431c12b 100644
--- a/src/resources.qrc
+++ b/src/resources.qrc
@@ -1,6 +1,7 @@
<RCC>
<qresource prefix="/">
<file>webchannel.js</file>
+ <file>qobject.js</file>
<file>webchannel-iframe.html</file>
</qresource>
</RCC>
diff --git a/src/src.pri b/src/src.pri
index c64cc76..55ed7e3 100644
--- a/src/src.pri
+++ b/src/src.pri
@@ -1,3 +1,3 @@
QT += network
-SOURCES += $$PWD/qwebchannel.cpp
-HEADERS += $$PWD/qwebchannel.h
+SOURCES += $$PWD/qwebchannel.cpp $$PWD/qtmetaobjectpublisher.cpp
+HEADERS += $$PWD/qwebchannel.h $$PWD/qtmetaobjectpublisher.h
diff --git a/src/src.pro b/src/src.pro
index 1f940c6..1f5a62e 100644
--- a/src/src.pro
+++ b/src/src.pro
@@ -13,7 +13,6 @@ SOURCES += qwebchannel_plugin.cpp
HEADERS += qwebchannel_plugin.h
OTHER_FILES = qmldir \
- qwebchannel.js \
qtc_packaging/debian_harmattan/rules \
qtc_packaging/debian_harmattan/README \
qtc_packaging/debian_harmattan/copyright \
@@ -21,7 +20,9 @@ OTHER_FILES = qmldir \
qtc_packaging/debian_harmattan/compat \
qtc_packaging/debian_harmattan/changelog \
webchannel.js \
- webchannel-iframe.html
+ qobject.js \
+ webchannel-iframe.html \
+ MetaObjectPublisher.qml
!equals(_PRO_FILE_PWD_, $$OUT_PWD) {
copy_qmldir.target = $$OUT_PWD/qmldir
@@ -33,7 +34,7 @@ OTHER_FILES = qmldir \
target.path = $$[QT_INSTALL_QML]/$$TARGETPATH
-qmldir.files += $$PWD/qmldir
+qmldir.files += $$PWD/qmldir $$PWD/MetaObjectPublisher.qml
qmldir.path += $$[QT_INSTALL_QML]/$$TARGETPATH
INSTALLS += target qmldir
diff --git a/src/webchannel-iframe.html b/src/webchannel-iframe.html
index 1f93eac..bbaf7cd 100644
--- a/src/webchannel-iframe.html
+++ b/src/webchannel-iframe.html
@@ -24,6 +24,7 @@
window.addEventListener("message", function(event) {
var data = JSON.parse(event.data);
+ console.log("MESSAGE:", data);
function callback(r) { window.parent.postMessage(JSON.stringify({ type: "callback", id: data.id, payload: r }), "*"); }
if (data.type == "EXEC")
exec(data.payload, callback);