diff options
author | Milian Wolff <milian.wolff@kdab.com> | 2019-03-22 11:03:43 +0100 |
---|---|---|
committer | Milian Wolff <milian.wolff@kdab.com> | 2019-03-25 14:07:36 +0000 |
commit | 7a673eb1a6902ef6f2eb03d6beab139282b1e4a5 (patch) | |
tree | aaa3e1c31152327b9662bee7a00c0249b916eb66 /tests/auto/qml | |
parent | 857cfc1adecd72750cea26d4c91371f4aaf9a68f (diff) | |
download | qtwebchannel-7a673eb1a6902ef6f2eb03d6beab139282b1e4a5.tar.gz |
Publish overloaded methods and signals to JavaScript
Previously, we only published the first method or signal of any given
name. We keep this behavior for the nice JavaScript notation that looks
like a normal JavaScript method call `foo.bar(...)`. When you need to
call a different overloaded method, this patch offers you to specify
the explicit signature on the JavaScript side. I.e. when we have an
object with `foo(int i)` and `foo(const QString &str, int i)`, then
on the JavaScript a call to `obj.foo(...)` will always call the first
method like before. But now you can specify the full QMetaMethod
signature and call matching methods explicitly via `obj["foo(int)"]`
or `obj["foo(QString,int)"]`.
Automatic overload resolution on the C++ side for the nice notation
cannot easily be implemented: We need to know the return value of
the called function, otherwise we cannot construct a valid
QGenericReturnArgument. Furthermore, we wouldn't be able to
differentiate between e.g. any numeric types on the C++ side, since
JavaScript only has a single `double` type internally.
[ChangeLog][QWebChannel][General] It is now possible to explicitly
call overloaded methods or connect to overloaded signals by specifying
the full method or signal signature in string form on the JavaScript
side.
Fixes: QTBUG-73010
Change-Id: I4645edee97af56fd8d126e77d70dc33ed3513deb
Reviewed-by: Arno Rehn <a.rehn@menlosystems.com>
Reviewed-by: Frederik Gladhorn <frederik.gladhorn@qt.io>
Reviewed-by: Milian Wolff <milian.wolff@kdab.com>
Diffstat (limited to 'tests/auto/qml')
-rw-r--r-- | tests/auto/qml/testobject.cpp | 18 | ||||
-rw-r--r-- | tests/auto/qml/testobject.h | 8 | ||||
-rw-r--r-- | tests/auto/qml/tst_webchannel.qml | 60 |
3 files changed, 86 insertions, 0 deletions
diff --git a/tests/auto/qml/testobject.cpp b/tests/auto/qml/testobject.cpp index 4968bf4..ad302e7 100644 --- a/tests/auto/qml/testobject.cpp +++ b/tests/auto/qml/testobject.cpp @@ -59,4 +59,22 @@ void TestObject::triggerSignals() emit testSignalInt(0); } +int TestObject::testOverload(int i) +{ + emit testOverloadSignal(i); + return i + 1; +} + +QString TestObject::testOverload(const QString &str) +{ + emit testOverloadSignal(str); + return str.toUpper(); +} + +QString TestObject::testOverload(const QString &str, int i) +{ + emit testOverloadSignal(str, i); + return str.toUpper() + QString::number(i + 1); +} + QT_END_NAMESPACE diff --git a/tests/auto/qml/testobject.h b/tests/auto/qml/testobject.h index 5813dae..b9c5ecc 100644 --- a/tests/auto/qml/testobject.h +++ b/tests/auto/qml/testobject.h @@ -48,10 +48,18 @@ public: public slots: void triggerSignals(); + int testOverload(int i); + QString testOverload(const QString &str); + QString testOverload(const QString &str, int i); + signals: void testSignalBool(bool testBool); void testSignalInt(int testInt); + void testOverloadSignal(int i); + void testOverloadSignal(const QString &str); + void testOverloadSignal(const QString &str, int i); + private: QObject *embeddedObject; }; diff --git a/tests/auto/qml/tst_webchannel.qml b/tests/auto/qml/tst_webchannel.qml index 0069261..87ce84b 100644 --- a/tests/auto/qml/tst_webchannel.qml +++ b/tests/auto/qml/tst_webchannel.qml @@ -476,4 +476,64 @@ TestCase { compare(signalArgs, [42, 42, 1, 1, 0, 0]); } + + function test_overloading() + { + var signalArgs_implicit = []; + var signalArgs_explicit1 = []; + var signalArgs_explicit2 = []; + var signalArgs_explicit3 = []; + function logSignalArgs(container) { + return function(...args) { + container.push(args); + }; + } + var returnValues = []; + function logReturnValue(value) { + returnValues.push(value); + } + var channel = client.createChannel(function(channel) { + var testObject = channel.objects.testObject; + testObject.testOverloadSignal.connect(logSignalArgs(signalArgs_implicit)); + testObject["testOverloadSignal(int)"].connect(logSignalArgs(signalArgs_explicit1)); + testObject["testOverloadSignal(QString)"].connect(logSignalArgs(signalArgs_explicit2)); + testObject["testOverloadSignal(QString,int)"].connect(logSignalArgs(signalArgs_explicit3)); + testObject.testOverload(99, logReturnValue); + testObject["testOverload(int)"](41, logReturnValue); + testObject["testOverload(QString)"]("hello world", logReturnValue); + testObject["testOverload(QString,int)"]("the answer is ", 41, logReturnValue); + }); + client.awaitInit(); + + function awaitMessage(type) + { + var msg = client.awaitMessage(); + compare(msg.type, type); + compare(msg.object, "testObject"); + } + + console.log("sig1"); + awaitMessage(JSClient.QWebChannelMessageTypes.connectToSignal); + console.log("sig2"); + awaitMessage(JSClient.QWebChannelMessageTypes.connectToSignal); + console.log("sig3"); + awaitMessage(JSClient.QWebChannelMessageTypes.connectToSignal); + + console.log("method1"); + awaitMessage(JSClient.QWebChannelMessageTypes.invokeMethod); + console.log("method2"); + awaitMessage(JSClient.QWebChannelMessageTypes.invokeMethod); + console.log("method3"); + awaitMessage(JSClient.QWebChannelMessageTypes.invokeMethod); + console.log("method4"); + awaitMessage(JSClient.QWebChannelMessageTypes.invokeMethod); + + client.awaitIdle(); + + compare(signalArgs_implicit, [[99], [41]]); + compare(signalArgs_explicit1, signalArgs_implicit); + compare(signalArgs_explicit2, [["hello world"]]); + compare(signalArgs_explicit3, [["the answer is ", 41]]); + compare(returnValues, [100, 42, "HELLO WORLD", "THE ANSWER IS 42"]); + } } |