summaryrefslogtreecommitdiff
path: root/examples
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 /examples
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 'examples')
-rw-r--r--examples/qtobject/main.cpp2
-rw-r--r--examples/qtobject/qml/qtobject/index.html36
-rw-r--r--examples/qtobject/qml/qtobject/main.qml53
-rw-r--r--examples/qtobject/qml/qtobject/qtobject.js118
-rw-r--r--examples/qtobject/qtmetaobjectpublisher.cpp32
-rw-r--r--examples/qtobject/qtmetaobjectpublisher.h34
-rw-r--r--examples/qtobject/qtobject.pro5
-rw-r--r--examples/qtobject/testobject.cpp2
-rw-r--r--examples/qtobject/testobject.h2
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: