diff options
author | Milian Wolff <milian.wolff@kdab.com> | 2013-01-18 16:27:42 +0100 |
---|---|---|
committer | Pierre Rossi <pierre.rossi@gmail.com> | 2013-11-01 13:57:42 +0100 |
commit | 62c243c979b172ae554f372a0d883c0273cafc53 (patch) | |
tree | 432211b3d834cf3702012afffc510c349e436e3b /examples | |
parent | b23f72024c14153d233563f600a359456649aaaf (diff) | |
download | qtwebchannel-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 'examples')
-rw-r--r-- | examples/qtobject/main.cpp | 2 | ||||
-rw-r--r-- | examples/qtobject/qml/qtobject/index.html | 36 | ||||
-rw-r--r-- | examples/qtobject/qml/qtobject/main.qml | 53 | ||||
-rw-r--r-- | examples/qtobject/qml/qtobject/qtobject.js | 118 | ||||
-rw-r--r-- | examples/qtobject/qtmetaobjectpublisher.cpp | 32 | ||||
-rw-r--r-- | examples/qtobject/qtmetaobjectpublisher.h | 34 | ||||
-rw-r--r-- | examples/qtobject/qtobject.pro | 5 | ||||
-rw-r--r-- | examples/qtobject/testobject.cpp | 2 | ||||
-rw-r--r-- | examples/qtobject/testobject.h | 2 |
9 files changed, 53 insertions, 231 deletions
diff --git a/examples/qtobject/main.cpp b/examples/qtobject/main.cpp index 6165664..fe8efff 100644 --- a/examples/qtobject/main.cpp +++ b/examples/qtobject/main.cpp @@ -3,13 +3,11 @@ #include <QtQml> #include "qtquick2applicationviewer.h" -#include "qtmetaobjectpublisher.h" #include "testobject.h" int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); - qmlRegisterType<QtMetaObjectPublisher>("Qt.labs", 1, 0, "QtMetaObjectPublisher"); qmlRegisterType<TestObject>("Qt.labs", 1, 0, "TestObject"); QtQuick2ApplicationViewer viewer; diff --git a/examples/qtobject/qml/qtobject/index.html b/examples/qtobject/qml/qtobject/index.html index d79fd7e..a24dde3 100644 --- a/examples/qtobject/qml/qtobject/index.html +++ b/examples/qtobject/qml/qtobject/index.html @@ -1,21 +1,39 @@ <html> <head> - <script> - document.write('<script src="' + (/[?&]webChannelBaseUrl=([A-Za-z0-9\-:/]+)/.exec(location.search)[1]) + '/webchannel.js/createWebChannel"><' + '/script>'); + <script type="text/javascript"> + var base = (/[?&]webChannelBaseUrl=([A-Za-z0-9\-:/]+)/.exec(location.search)[1]); + document.write('<script src="' + base + '/webchannel.js/setupWebChannel"></script>'); + document.write('<script src="' + base + '/qobject.js"><' + '/script>'); window.output = function(x) { document.querySelector("#out").innerHTML += x + "\n"; } - </script> - <script src="qtobject.js"></script> - <script> + window.onload = function() { + setupWebChannel(function(webChannel) { + setupQObjectWebChannel(webChannel); + }); + } </script> </head> <body> - <a href="#" onclick="testObject.debugMe('Debugging!', function(result) { output(result); })">invoke method</a> - <a href="#" onclick="testObject.prop1(function(value) { output(value); })">Get property</a> - <a href="#" onclick="testObject.prop1 = 'Different property'; testObject.prop1(function(value) { output(value); })">Set property</a> - <a href="#" onclick="testObject.timeout.connect(function() { output('timeout'); }); testObject.startTimer(1000);">Timer</a> + <p>TestObject 1: + <a href="#" onclick="testObject1.debugMe('Debugging!', function(result) { output(result); })">invoke method</a> + <a href="#" onclick="testObject1.prop1(function(value) { output(value); })">Get property</a> + <a href="#" onclick="testObject1.prop1 = 'Different property'; testObject1.prop1(function(value) { output(value); })">Set property</a> + <a href="#" onclick="testObject1.timeout.connect(function() { output('timeout 1'); }); testObject1.startTimer(1000);">Timer</a> + </p> + <p>TestObject 2: + <a href="#" onclick="testObject2.debugMe('Debugging!', function(result) { output(result); })">invoke method</a> + <a href="#" onclick="testObject2.prop1(function(value) { output(value); })">Get property</a> + <a href="#" onclick="testObject2.prop1 = 'Different property'; testObject2.prop1(function(value) { output(value); })">Set property</a> + <a href="#" onclick="testObject2.timeout.connect(function() { output('timeout 2'); }); testObject2.startTimer(1000);">Timer</a> + </p> + <p>TestObject 3: + <a href="#" onclick="testObject3.debugMe('Debugging!', function(result) { output(result); })">invoke method</a> + <a href="#" onclick="testObject3.prop1(function(value) { output(value); })">Get property</a> + <a href="#" onclick="testObject3.prop1 = 'Different property'; testObject3.prop1(function(value) { output(value); })">Set property</a> + <a href="#" onclick="testObject3.timeout.connect(function() { output('timeout 3'); }); testObject3.startTimer(1000);">Timer</a> + </p> <br/> <textarea id="out" style="height:80%; width: 80%"></textarea> </body> diff --git a/examples/qtobject/qml/qtobject/main.qml b/examples/qtobject/qml/qtobject/main.qml index 6ed3ad6..a4ab0c3 100644 --- a/examples/qtobject/qml/qtobject/main.qml +++ b/examples/qtobject/qml/qtobject/main.qml @@ -47,52 +47,45 @@ import QtWebKit 3.0 import QtWebKit.experimental 1.0 Rectangle { - QtMetaObjectPublisher { + MetaObjectPublisher { id: publisher } TestObject { - id: testObject + id: testObject1 + objectName: "object1" + } + + TestObject { + id: testObject2 + objectName: "object2" + } + + TestObject { + id: testObject3 + objectName: "object3" } WebChannel { id: webChannel onExecute: { var payload = JSON.parse(requestData); - var object = publisher.namedObject(payload.object); - var ret; - console.log(requestData); - 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) { - 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 objectNames = publisher.objectNames; - for (var i = 0; i < objectNames.length; ++i) { - var name = objectNames[i]; - var o = publisher.namedObject(name); - addObject(name, o); - } + var ret = publisher.handleRequest(payload, webChannel); + if (!ret) { + console.log("unhandled request: ", requestData); + } else { + response.send(JSON.stringify(ret)); } - - response.send(JSON.stringify(ret)); } - function addObject(name, object) + function registerObjects(objects) { - publisher.addObject(name, object); - var metaData = { name: name, data: publisher.classInfoForObject(object) }; - broadcast("Qt.addToWindowObject", JSON.stringify(metaData)); + for (var name in objects) { + publisher.addObject(name, objects[name]); + } } - onBaseUrlChanged: addObject("testObject", testObject) + onBaseUrlChanged: registerObjects({"testObject1": testObject1, "testObject2": testObject2, "testObject3":testObject3}) } width: 480 diff --git a/examples/qtobject/qml/qtobject/qtobject.js b/examples/qtobject/qml/qtobject/qtobject.js deleted file mode 100644 index 0553a36..0000000 --- a/examples/qtobject/qml/qtobject/qtobject.js +++ /dev/null @@ -1,118 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -window.onload = function() { - createWebChannel(function(webChannel) { - var allSignals = {}; - webChannel.subscribe( - "Qt.signal", - function(payload) { - var signalData = JSON.parse(payload); - var object = allSignals[signalData.object]; - var conns = (object ? object[signalData.signal] : []) || []; - var a = payload.args; - conns.forEach(function(callback) { - callback.call(a); - }); - } - ); - webChannel.subscribe( - "Qt.addToWindowObject", - function(payload) { - var addObjectData = JSON.parse(payload); - var objectSignals = {}; - var methodsAndSignals = []; - var object = {}; - var objectName = addObjectData.name; - var data = addObjectData.data; - for (var i in data.methods) - methodsAndSignals.push(data.methods[i]); - for (i in data.signals) - methodsAndSignals.push(data.signals[i]); - - 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: objectName, 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) { - objectSignals[signal] = objectSignals[signal] || []; - webChannel.exec(JSON.stringify({type: "Qt.connectToSignal", object: objectName, signal: signal})); - objectSignals[signal].push(callback); - }; - } - allSignals[objectName] = objectSignals; - - for (i in data.properties) { - var prop = data.properties[i]; - object.__defineSetter__(prop, function(value) { - webChannel.exec(JSON.stringify({type: "Qt.setProperty", object: objectName, property: prop, value: value })); - }); - object.__defineGetter__(prop, function() { - return (function(callback) { - webChannel.exec(JSON.stringify({type: "Qt.getProperty", object: objectName, property: prop}), function(response) { - callback(JSON.parse(response)); - }); - }); - }); - } - - window[objectName] = object; - } - ); - webChannel.exec(JSON.stringify({type:"Qt.getObjects"})); - }); -}; diff --git a/examples/qtobject/qtmetaobjectpublisher.cpp b/examples/qtobject/qtmetaobjectpublisher.cpp deleted file mode 100644 index db86145..0000000 --- a/examples/qtobject/qtmetaobjectpublisher.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#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/examples/qtobject/qtmetaobjectpublisher.h b/examples/qtobject/qtmetaobjectpublisher.h deleted file mode 100644 index 3262525..0000000 --- a/examples/qtobject/qtmetaobjectpublisher.h +++ /dev/null @@ -1,34 +0,0 @@ -#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/examples/qtobject/qtobject.pro b/examples/qtobject/qtobject.pro index 0be2129..b6ff512 100644 --- a/examples/qtobject/qtobject.pro +++ b/examples/qtobject/qtobject.pro @@ -14,12 +14,9 @@ QML_IMPORT_PATH = # The .cpp file which was generated for your project. Feel free to hack it. SOURCES += main.cpp \ - qtmetaobjectpublisher.cpp \ testobject.cpp -HEADERS += \ - qtmetaobjectpublisher.h \ - testobject.h +HEADERS += testobject.h # Please do not modify the following two lines. Required for deployment. include(qtquick2applicationviewer/qtquick2applicationviewer.pri) diff --git a/examples/qtobject/testobject.cpp b/examples/qtobject/testobject.cpp index f13c5ab..75daa8d 100644 --- a/examples/qtobject/testobject.cpp +++ b/examples/qtobject/testobject.cpp @@ -10,7 +10,7 @@ TestObject::TestObject(QObject *parent) : QString TestObject::debugMe(const QString& data) { qWarning() << data; - return "OK"; + return QString("OK from %1: %2").arg(objectName()).arg(data); } void TestObject::setProp1(const QString& s) diff --git a/examples/qtobject/testobject.h b/examples/qtobject/testobject.h index 93aa227..992247d 100644 --- a/examples/qtobject/testobject.h +++ b/examples/qtobject/testobject.h @@ -10,7 +10,7 @@ class TestObject : public QObject Q_PROPERTY(QString prop1 READ prop1 WRITE setProp1) public: explicit TestObject(QObject *parent = 0); - QString prop1() const { return p1; } + QString prop1() const { return p1 + objectName(); } void setProp1(const QString& s); signals: |