diff options
author | Mårten Nordheim <marten.nordheim@qt.io> | 2023-06-27 18:29:38 +0200 |
---|---|---|
committer | Mårten Nordheim <marten.nordheim@qt.io> | 2023-08-24 07:45:04 +0200 |
commit | a7d2855b3c7716467c827f27359259afb5c4cbea (patch) | |
tree | b3130eeed1d0af9ac371715f7c35215472ec1346 /tests/auto/corelib/kernel/qmetaobject | |
parent | 777a1ed19185c594d7f43296e0044e3e354690ca (diff) |
invokeMethod: enable passing parameters to overload taking functors
This was missing for a while, and there is nothing fundamentally
missing for it to work.
With the more recent work around slot objects and invokeMethod in
general, it is a good time to add support for this.
In this patch, when connecting to a functor, it automatically deduces
the overload to call based on the arguments passed to invokeMethod.
Sharing code with QObject::connect could be done, but they have a
key difference that makes it harder:
With signal emissions we throw away trailing arguments that are not
used: i.e. `signal(int, int)` can be connected to `slot(int)` or
`slot()`. With invokeMethod that's not a thing. So we will need a way
to toggle that behavior during resolution.
[ChangeLog][QtCore][QMetaObject] Added support for passing parameters
to the overload of QMetaObject::invokeMethod that takes a functor. These
new overloads must have the return-value passed through qReturnArg().
Change-Id: If4fcbb75515b19e72fab80115c109efa37e6626e
Reviewed-by: Ievgenii Meshcheriakov <ievgenii.meshcheriakov@qt.io>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'tests/auto/corelib/kernel/qmetaobject')
-rw-r--r-- | tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp b/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp index 926f3d1d60..8ccb5929a1 100644 --- a/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp +++ b/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp @@ -31,6 +31,8 @@ Q_DECLARE_METATYPE(const QMetaObject *) # define Q_NO_ARG #endif +using namespace Qt::StringLiterals; + struct MyStruct { int i; @@ -1081,6 +1083,98 @@ void tst_QMetaObject::invokePointer() QCOMPARE(obj.slotResult, QString("sl1:1")); } QCOMPARE(countedStructObjectsCount, 0); + + // Invoking with parameters + QString result; + QVERIFY(QMetaObject::invokeMethod(&obj, &QtTestObject::sl1, qReturnArg(result), u"bubu"_s)); + QCOMPARE(obj.slotResult, u"sl1:bubu"); + QCOMPARE(result, u"yessir"); + + // without taking return value + QVERIFY(QMetaObject::invokeMethod(&obj, &QtTestObject::sl1, u"bubu"_s)); + QCOMPARE(obj.slotResult, u"sl1:bubu"); + + QVERIFY(QMetaObject::invokeMethod(&obj, &QtTestObject::sl1, Qt::DirectConnection, qReturnArg(result), + u"byebye"_s)); + QCOMPARE(obj.slotResult, u"sl1:byebye"); + QCOMPARE(result, u"yessir"); + + QVERIFY(QMetaObject::invokeMethod(&obj, qOverload<int, int>(&QtTestObject::overloadedSlot), 1, 2)); + QCOMPARE(obj.slotResult, u"overloadedSlot:1,2"); + + // non-const ref parameter + QString original = u"bubu"_s; + QString &ref = original; + QVERIFY(QMetaObject::invokeMethod(&obj, &QtTestObject::sl1, qReturnArg(result), ref)); + QCOMPARE(obj.slotResult, u"sl1:bubu"); + QCOMPARE(result, u"yessir"); + + struct R { + bool operator()(int) { return true; } + int operator()(char) { return 15; } + int operator()(QString = {}, int = {}, int = {}) { return 242; } + } r; + + // Test figuring out which operator() to call: + { + bool res = false; + QVERIFY(QMetaObject::invokeMethod(&obj, r, qReturnArg(res), 1)); + QCOMPARE(res, true); + } + { + int res; + QVERIFY(QMetaObject::invokeMethod(&obj, r, qReturnArg(res), 'c')); + QCOMPARE(res, 15); + } + { + int res; + QVERIFY(QMetaObject::invokeMethod(&obj, r, qReturnArg(res))); + QCOMPARE(res, 242); + res = 0; + QVERIFY(QMetaObject::invokeMethod(&obj, r, qReturnArg(res), u"bu"_s)); + QCOMPARE(res, 242); + res = 0; + QVERIFY(QMetaObject::invokeMethod(&obj, r, qReturnArg(res), u"bu"_s, 1)); + QCOMPARE(res, 242); + res = 0; + QVERIFY(QMetaObject::invokeMethod(&obj, r, qReturnArg(res), u"bu"_s, 1, 2)); + QCOMPARE(res, 242); + } + + { + auto lambda = [](const QString &s) { return s + s; }; + QVERIFY(QMetaObject::invokeMethod(&obj, lambda, qReturnArg(result), u"bu"_s)); + QCOMPARE(result, u"bubu"); + } + + { + auto lambda = [](const QString &s = u"bu"_s) { return s + s; }; + QVERIFY(QMetaObject::invokeMethod(&obj, lambda, qReturnArg(result))); + QCOMPARE(result, u"bubu"); + + QVERIFY(QMetaObject::invokeMethod(&obj, lambda, qReturnArg(result), u"bye"_s)); + QCOMPARE(result, u"byebye"); + } + + { + auto lambda = [](const QString &s, qint64 a, qint16 b, qint8 c) { + return s + QString::number(a) + QString::number(b) + QString::number(c); + }; + // Testing mismatching argument (int for qint64). The other arguments + // would static_assert for potential truncation if they were ints. + QVERIFY(QMetaObject::invokeMethod(&obj, lambda, qReturnArg(result), u"bu"_s, 1, qint16(2), qint8(3))); + QCOMPARE(result, u"bu123"); + } + { + // Testing deduction + auto lambda = [](const QString &s, auto a) { return s + a; }; + QVERIFY(QMetaObject::invokeMethod(&obj, lambda, qReturnArg(result), u"bu"_s, "bu"_L1)); + QCOMPARE(result, u"bubu"); + + auto variadic = [](const QString &s, auto... a) { return s + (QString::number(a) + ...); }; + QVERIFY(QMetaObject::invokeMethod(&obj, variadic, qReturnArg(result), u"bu"_s, 1, 2, 3, 4, 5, 6)); + QCOMPARE(result, u"bu123456"); + } } void tst_QMetaObject::invokeQueuedMetaMember() @@ -1345,6 +1439,12 @@ void tst_QMetaObject::invokeQueuedPointer() QCOMPARE(var, 0); } QCOMPARE(countedStructObjectsCount, 0); + + // Invoking with parameters + using namespace Qt::StringLiterals; + QVERIFY(QMetaObject::invokeMethod(&obj, &QtTestObject::sl1, Qt::QueuedConnection, u"bubu"_s)); + qApp->processEvents(QEventLoop::AllEvents); + QCOMPARE(obj.slotResult, u"sl1:bubu"); } // this test is duplicated below @@ -1764,6 +1864,18 @@ void tst_QMetaObject::invokeBlockingQueuedPointer() Qt::BlockingQueuedConnection)); QCOMPARE(obj.slotResult, QString("sl1:hehe")); } + + // Test with parameters + QString result; + QVERIFY(QMetaObject::invokeMethod(&obj, &QtTestObject::sl1, Qt::BlockingQueuedConnection, + qReturnArg(result), u"bubu"_s)); + QCOMPARE(result, u"yessir"); + QCOMPARE(obj.slotResult, u"sl1:bubu"); + + QVERIFY(QMetaObject::invokeMethod(&obj, &QtTestObject::sl2, Qt::BlockingQueuedConnection, + u"bubu"_s, u"baba"_s)); + QCOMPARE(obj.slotResult, u"sl2:bububaba"); + QVERIFY(QMetaObject::invokeMethod(&obj, [&](){obj.moveToThread(QThread::currentThread());}, Qt::BlockingQueuedConnection)); t.quit(); QVERIFY(t.wait()); |