summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/dbus/qdbusconnection.h3
-rw-r--r--src/dbus/qdbusintegrator.cpp22
-rw-r--r--src/dbus/qdbusinterface.cpp2
-rw-r--r--src/dbus/qdbusxmlgenerator.cpp8
-rw-r--r--tests/auto/qdbusinterface/tst_qdbusinterface.cpp138
5 files changed, 153 insertions, 20 deletions
diff --git a/src/dbus/qdbusconnection.h b/src/dbus/qdbusconnection.h
index 0f365ec..eedda16 100644
--- a/src/dbus/qdbusconnection.h
+++ b/src/dbus/qdbusconnection.h
@@ -85,16 +85,19 @@ public:
ExportScriptableSlots = 0x10,
ExportScriptableSignals = 0x20,
ExportScriptableProperties = 0x40,
+ ExportScriptableInvokables = 0x80,
ExportScriptableContents = 0xf0,
ExportNonScriptableSlots = 0x100,
ExportNonScriptableSignals = 0x200,
ExportNonScriptableProperties = 0x400,
+ ExportNonScriptableInvokables = 0x800,
ExportNonScriptableContents = 0xf00,
ExportAllSlots = ExportScriptableSlots|ExportNonScriptableSlots,
ExportAllSignals = ExportScriptableSignals|ExportNonScriptableSignals,
ExportAllProperties = ExportScriptableProperties|ExportNonScriptableProperties,
+ ExportAllInvokables = ExportScriptableInvokables|ExportNonScriptableInvokables,
ExportAllContents = ExportScriptableContents|ExportNonScriptableContents,
#ifndef Q_QDOC
diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp
index 1f44bd2..e1b90b8 100644
--- a/src/dbus/qdbusintegrator.cpp
+++ b/src/dbus/qdbusintegrator.cpp
@@ -508,7 +508,7 @@ static bool shouldWatchService(const QString &service)
return !service.isEmpty() && !service.startsWith(QLatin1Char(':'));
}
-extern Q_DBUS_EXPORT void qDBusAddSpyHook(QDBusSpyHook);
+extern QDBUS_EXPORT void qDBusAddSpyHook(QDBusSpyHook);
void qDBusAddSpyHook(QDBusSpyHook hook)
{
qDBusSpyHookList()->append(hook);
@@ -618,7 +618,7 @@ static int findSlot(const QMetaObject *mo, const QByteArray &name, int flags,
continue;
// check type:
- if (mm.methodType() != QMetaMethod::Slot)
+ if (mm.methodType() != QMetaMethod::Slot && mm.methodType() != QMetaMethod::Method)
continue;
// check name:
@@ -682,10 +682,17 @@ static int findSlot(const QMetaObject *mo, const QByteArray &name, int flags,
if (isAsync && metaTypes.count() > i + 1)
continue;
- if (isScriptable && (flags & QDBusConnection::ExportScriptableSlots) == 0)
- continue; // not exported
- if (!isScriptable && (flags & QDBusConnection::ExportNonScriptableSlots) == 0)
- continue; // not exported
+ if (mm.methodType() == QMetaMethod::Slot) {
+ if (isScriptable && (flags & QDBusConnection::ExportScriptableSlots) == 0)
+ continue; // scriptable slots not exported
+ if (!isScriptable && (flags & QDBusConnection::ExportNonScriptableSlots) == 0)
+ continue; // non-scriptable slots not exported
+ } else {
+ if (isScriptable && (flags & QDBusConnection::ExportScriptableInvokables) == 0)
+ continue; // scriptable invokables not exported
+ if (!isScriptable && (flags & QDBusConnection::ExportNonScriptableInvokables) == 0)
+ continue; // non-scriptable invokables not exported
+ }
// if we got here, this slot matched
return idx;
@@ -1379,7 +1386,8 @@ void QDBusConnectionPrivate::activateObject(ObjectTreeNode &node, const QDBusMes
return; // internal filters have already run or an error has been sent
// try the object itself:
- if (node.flags & (QDBusConnection::ExportScriptableSlots|QDBusConnection::ExportNonScriptableSlots)) {
+ if (node.flags & (QDBusConnection::ExportScriptableSlots|QDBusConnection::ExportNonScriptableSlots) ||
+ node.flags & (QDBusConnection::ExportScriptableInvokables|QDBusConnection::ExportNonScriptableInvokables)) {
bool interfaceFound = true;
if (!msg.interface().isEmpty())
interfaceFound = qDBusInterfaceInObject(node.obj, msg.interface());
diff --git a/src/dbus/qdbusinterface.cpp b/src/dbus/qdbusinterface.cpp
index b989cab..248bf65 100644
--- a/src/dbus/qdbusinterface.cpp
+++ b/src/dbus/qdbusinterface.cpp
@@ -277,7 +277,7 @@ int QDBusInterfacePrivate::metacall(QMetaObject::Call c, int id, void **argv)
// signal relay from D-Bus world to Qt world
QMetaObject::activate(q, metaObject, id, argv);
- } else if (mm.methodType() == QMetaMethod::Slot) {
+ } else if (mm.methodType() == QMetaMethod::Slot || mm.methodType() == QMetaMethod::Method) {
// method call relay from Qt world to D-Bus world
// get D-Bus equivalent signature
QString methodName = QLatin1String(metaObject->dbusNameForMethod(id));
diff --git a/src/dbus/qdbusxmlgenerator.cpp b/src/dbus/qdbusxmlgenerator.cpp
index 7cc5acb..1222ac7 100644
--- a/src/dbus/qdbusxmlgenerator.cpp
+++ b/src/dbus/qdbusxmlgenerator.cpp
@@ -133,7 +133,7 @@ static QString generateInterfaceXml(const QMetaObject *mo, int flags, int method
if (mm.methodType() == QMetaMethod::Signal)
// adding a signal
isSignal = true;
- else if (mm.methodType() == QMetaMethod::Slot && mm.access() == QMetaMethod::Public)
+ else if (mm.access() == QMetaMethod::Public && (mm.methodType() == QMetaMethod::Slot || mm.methodType() == QMetaMethod::Method))
isSignal = false;
else
continue; // neither signal nor public slot
@@ -141,9 +141,9 @@ static QString generateInterfaceXml(const QMetaObject *mo, int flags, int method
if (isSignal && !(flags & (QDBusConnection::ExportScriptableSignals |
QDBusConnection::ExportNonScriptableSignals)))
continue; // we're not exporting any signals
- if (!isSignal && !(flags & (QDBusConnection::ExportScriptableSlots |
- QDBusConnection::ExportNonScriptableSlots)))
- continue; // we're not exporting any slots
+ if (!isSignal && (!(flags & (QDBusConnection::ExportScriptableSlots | QDBusConnection::ExportNonScriptableSlots)) &&
+ !(flags & (QDBusConnection::ExportScriptableInvokables | QDBusConnection::ExportNonScriptableInvokables))))
+ continue; // we're not exporting any slots or invokables
QString xml = QString::fromLatin1(" <%1 name=\"%2\">\n")
.arg(isSignal ? QLatin1String("signal") : QLatin1String("method"))
diff --git a/tests/auto/qdbusinterface/tst_qdbusinterface.cpp b/tests/auto/qdbusinterface/tst_qdbusinterface.cpp
index d8ff2d3..a870e47 100644
--- a/tests/auto/qdbusinterface/tst_qdbusinterface.cpp
+++ b/tests/auto/qdbusinterface/tst_qdbusinterface.cpp
@@ -70,18 +70,34 @@ class MyObject: public QObject
" <arg direction=\"in\" type=\"v\" name=\"ping\" />\n"
" <arg direction=\"out\" type=\"v\" name=\"ping\" />\n"
" </method>\n"
+" <method name=\"ping_invokable\" >\n"
+" <arg direction=\"in\" type=\"v\" name=\"ping_invokable\" />\n"
+" <arg direction=\"out\" type=\"v\" name=\"ping_invokable\" />\n"
+" </method>\n"
" <method name=\"ping\" >\n"
" <arg direction=\"in\" type=\"v\" name=\"ping1\" />\n"
" <arg direction=\"in\" type=\"v\" name=\"ping2\" />\n"
" <arg direction=\"out\" type=\"v\" name=\"pong1\" />\n"
" <arg direction=\"out\" type=\"v\" name=\"pong2\" />\n"
" </method>\n"
+" <method name=\"ping_invokable\" >\n"
+" <arg direction=\"in\" type=\"v\" name=\"ping1_invokable\" />\n"
+" <arg direction=\"in\" type=\"v\" name=\"ping2_invokable\" />\n"
+" <arg direction=\"out\" type=\"v\" name=\"pong1_invokable\" />\n"
+" <arg direction=\"out\" type=\"v\" name=\"pong2_invokable\" />\n"
+" </method>\n"
" <method name=\"ping\" >\n"
" <arg direction=\"in\" type=\"ai\" name=\"ping\" />\n"
" <arg direction=\"out\" type=\"ai\" name=\"ping\" />\n"
" <annotation name=\"com.trolltech.QtDBus.QtTypeName.In0\" value=\"QList&lt;int&gt;\"/>\n"
" <annotation name=\"com.trolltech.QtDBus.QtTypeName.Out0\" value=\"QList&lt;int&gt;\"/>\n"
" </method>\n"
+" <method name=\"ping_invokable\" >\n"
+" <arg direction=\"in\" type=\"ai\" name=\"ping_invokable\" />\n"
+" <arg direction=\"out\" type=\"ai\" name=\"ping_invokable\" />\n"
+" <annotation name=\"com.trolltech.QtDBus.QtTypeName.In0\" value=\"QList&lt;int&gt;\"/>\n"
+" <annotation name=\"com.trolltech.QtDBus.QtTypeName.Out0\" value=\"QList&lt;int&gt;\"/>\n"
+" </method>\n"
" </interface>\n"
"")
Q_PROPERTY(int prop1 READ prop1 WRITE setProp1)
@@ -120,6 +136,20 @@ public:
m_complexProp = value;
}
+ Q_INVOKABLE void ping_invokable(QDBusMessage msg)
+ {
+ QDBusConnection sender = QDBusConnection::sender();
+ if (!sender.isConnected())
+ exit(1);
+
+ ++callCount;
+ callArgs = msg.arguments();
+
+ msg.setDelayedReply(true);
+ if (!sender.send(msg.createReply(callArgs)))
+ exit(1);
+ }
+
public slots:
void ping(QDBusMessage msg)
@@ -220,6 +250,7 @@ void tst_QDBusInterface::initTestCase()
con.registerObject("/", &obj, QDBusConnection::ExportAllProperties
| QDBusConnection::ExportAllSlots
+ | QDBusConnection::ExportAllInvokables
| QDBusConnection::ExportChildObjects);
}
@@ -283,7 +314,7 @@ void tst_QDBusInterface::introspect()
const QMetaObject *mo = iface.metaObject();
- QCOMPARE(mo->methodCount() - mo->methodOffset(), 4);
+ QCOMPARE(mo->methodCount() - mo->methodOffset(), 7);
QVERIFY(mo->indexOfSignal(TEST_SIGNAL_NAME "(QString)") != -1);
QCOMPARE(mo->propertyCount() - mo->propertyOffset(), 2);
@@ -298,6 +329,8 @@ void tst_QDBusInterface::callMethod()
TEST_INTERFACE_NAME);
MyObject::callCount = 0;
+
+ // call a SLOT method
QDBusMessage reply = iface.call("ping", qVariantFromValue(QDBusVariant("foo")));
QCOMPARE(MyObject::callCount, 1);
QCOMPARE(reply.type(), QDBusMessage::ReplyMessage);
@@ -315,6 +348,25 @@ void tst_QDBusInterface::callMethod()
dv = qdbus_cast<QDBusVariant>(v);
QCOMPARE(dv.variant().type(), QVariant::String);
QCOMPARE(dv.variant().toString(), QString("foo"));
+
+ // call an INVOKABLE method
+ reply = iface.call("ping_invokable", qVariantFromValue(QDBusVariant("bar")));
+ QCOMPARE(MyObject::callCount, 2);
+ QCOMPARE(reply.type(), QDBusMessage::ReplyMessage);
+
+ // verify what the callee received
+ QCOMPARE(MyObject::callArgs.count(), 1);
+ v = MyObject::callArgs.at(0);
+ dv = qdbus_cast<QDBusVariant>(v);
+ QCOMPARE(dv.variant().type(), QVariant::String);
+ QCOMPARE(dv.variant().toString(), QString("bar"));
+
+ // verify reply
+ QCOMPARE(reply.arguments().count(), 1);
+ v = reply.arguments().at(0);
+ dv = qdbus_cast<QDBusVariant>(v);
+ QCOMPARE(dv.variant().type(), QVariant::String);
+ QCOMPARE(dv.variant().toString(), QString("bar"));
}
void tst_QDBusInterface::invokeMethod()
@@ -323,8 +375,9 @@ void tst_QDBusInterface::invokeMethod()
QDBusInterface iface(QDBusConnection::sessionBus().baseService(), QLatin1String("/"),
TEST_INTERFACE_NAME);
- // make the call without a return type
MyObject::callCount = 0;
+
+ // make the SLOT call without a return type
QDBusVariant arg("foo");
QVERIFY(QMetaObject::invokeMethod(&iface, "ping", Q_ARG(QDBusVariant, arg)));
QCOMPARE(MyObject::callCount, 1);
@@ -335,6 +388,18 @@ void tst_QDBusInterface::invokeMethod()
QDBusVariant dv = qdbus_cast<QDBusVariant>(v);
QCOMPARE(dv.variant().type(), QVariant::String);
QCOMPARE(dv.variant().toString(), QString("foo"));
+
+ // make the INVOKABLE call without a return type
+ QDBusVariant arg2("bar");
+ QVERIFY(QMetaObject::invokeMethod(&iface, "ping_invokable", Q_ARG(QDBusVariant, arg2)));
+ QCOMPARE(MyObject::callCount, 2);
+
+ // verify what the callee received
+ QCOMPARE(MyObject::callArgs.count(), 1);
+ v = MyObject::callArgs.at(0);
+ dv = qdbus_cast<QDBusVariant>(v);
+ QCOMPARE(dv.variant().type(), QVariant::String);
+ QCOMPARE(dv.variant().toString(), QString("bar"));
}
void tst_QDBusInterface::invokeMethodWithReturn()
@@ -343,10 +408,11 @@ void tst_QDBusInterface::invokeMethodWithReturn()
QDBusInterface iface(QDBusConnection::sessionBus().baseService(), QLatin1String("/"),
TEST_INTERFACE_NAME);
- // make the call without a return type
MyObject::callCount = 0;
- QDBusVariant arg("foo");
QDBusVariant retArg;
+
+ // make the SLOT call without a return type
+ QDBusVariant arg("foo");
QVERIFY(QMetaObject::invokeMethod(&iface, "ping", Q_RETURN_ARG(QDBusVariant, retArg), Q_ARG(QDBusVariant, arg)));
QCOMPARE(MyObject::callCount, 1);
@@ -359,6 +425,21 @@ void tst_QDBusInterface::invokeMethodWithReturn()
// verify that we got the reply as expected
QCOMPARE(retArg.variant(), arg.variant());
+
+ // make the INVOKABLE call without a return type
+ QDBusVariant arg2("bar");
+ QVERIFY(QMetaObject::invokeMethod(&iface, "ping_invokable", Q_RETURN_ARG(QDBusVariant, retArg), Q_ARG(QDBusVariant, arg2)));
+ QCOMPARE(MyObject::callCount, 2);
+
+ // verify what the callee received
+ QCOMPARE(MyObject::callArgs.count(), 1);
+ v = MyObject::callArgs.at(0);
+ dv = qdbus_cast<QDBusVariant>(v);
+ QCOMPARE(dv.variant().type(), QVariant::String);
+ QCOMPARE(dv.variant().toString(), arg2.variant().toString());
+
+ // verify that we got the reply as expected
+ QCOMPARE(retArg.variant(), arg2.variant());
}
void tst_QDBusInterface::invokeMethodWithMultiReturn()
@@ -367,10 +448,11 @@ void tst_QDBusInterface::invokeMethodWithMultiReturn()
QDBusInterface iface(QDBusConnection::sessionBus().baseService(), QLatin1String("/"),
TEST_INTERFACE_NAME);
- // make the call without a return type
MyObject::callCount = 0;
- QDBusVariant arg("foo"), arg2("bar");
QDBusVariant retArg, retArg2;
+
+ // make the SLOT call without a return type
+ QDBusVariant arg("foo"), arg2("bar");
QVERIFY(QMetaObject::invokeMethod(&iface, "ping",
Q_RETURN_ARG(QDBusVariant, retArg),
Q_ARG(QDBusVariant, arg),
@@ -393,6 +475,31 @@ void tst_QDBusInterface::invokeMethodWithMultiReturn()
// verify that we got the replies as expected
QCOMPARE(retArg.variant(), arg.variant());
QCOMPARE(retArg2.variant(), arg2.variant());
+
+ // make the INVOKABLE call without a return type
+ QDBusVariant arg3("hello"), arg4("world");
+ QVERIFY(QMetaObject::invokeMethod(&iface, "ping_invokable",
+ Q_RETURN_ARG(QDBusVariant, retArg),
+ Q_ARG(QDBusVariant, arg3),
+ Q_ARG(QDBusVariant, arg4),
+ Q_ARG(QDBusVariant&, retArg2)));
+ QCOMPARE(MyObject::callCount, 2);
+
+ // verify what the callee received
+ QCOMPARE(MyObject::callArgs.count(), 2);
+ v = MyObject::callArgs.at(0);
+ dv = qdbus_cast<QDBusVariant>(v);
+ QCOMPARE(dv.variant().type(), QVariant::String);
+ QCOMPARE(dv.variant().toString(), arg3.variant().toString());
+
+ v = MyObject::callArgs.at(1);
+ dv = qdbus_cast<QDBusVariant>(v);
+ QCOMPARE(dv.variant().type(), QVariant::String);
+ QCOMPARE(dv.variant().toString(), arg4.variant().toString());
+
+ // verify that we got the replies as expected
+ QCOMPARE(retArg.variant(), arg3.variant());
+ QCOMPARE(retArg2.variant(), arg4.variant());
}
void tst_QDBusInterface::invokeMethodWithComplexReturn()
@@ -401,10 +508,11 @@ void tst_QDBusInterface::invokeMethodWithComplexReturn()
QDBusInterface iface(QDBusConnection::sessionBus().baseService(), QLatin1String("/"),
TEST_INTERFACE_NAME);
- // make the call without a return type
MyObject::callCount = 0;
- QList<int> arg = QList<int>() << 42 << -47;
QList<int> retArg;
+
+ // make the SLOT call without a return type
+ QList<int> arg = QList<int>() << 42 << -47;
QVERIFY(QMetaObject::invokeMethod(&iface, "ping", Q_RETURN_ARG(QList<int>, retArg), Q_ARG(QList<int>, arg)));
QCOMPARE(MyObject::callCount, 1);
@@ -416,6 +524,20 @@ void tst_QDBusInterface::invokeMethodWithComplexReturn()
// verify that we got the reply as expected
QCOMPARE(retArg, arg);
+
+ // make the INVOKABLE call without a return type
+ QList<int> arg2 = QList<int>() << 24 << -74;
+ QVERIFY(QMetaObject::invokeMethod(&iface, "ping", Q_RETURN_ARG(QList<int>, retArg), Q_ARG(QList<int>, arg2)));
+ QCOMPARE(MyObject::callCount, 2);
+
+ // verify what the callee received
+ QCOMPARE(MyObject::callArgs.count(), 1);
+ v = MyObject::callArgs.at(0);
+ QCOMPARE(v.userType(), qMetaTypeId<QDBusArgument>());
+ QCOMPARE(qdbus_cast<QList<int> >(v), arg2);
+
+ // verify that we got the reply as expected
+ QCOMPARE(retArg, arg2);
}
void tst_QDBusInterface::signal()