Add QDBusMessage::createTargetedSignal()

The QDBusMessage::createSignal() static method doesn't take a parameter
for specifying the destination service of the signal. While this is not
a widely used feature, it can be useful to avoid waking up all connected
clients when the service knows what are the clients which are interested
in the signal.

This commit adds a QDBusMessage::createTargetedSignal() method which
also takes the destination service as its first parameter.

Change-Id: I9fdca53673a6944c39c93c1efd69a9d02859684e
Task-number: QTBUG-44704
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Alberto Mardegan 2015-03-09 13:12:05 +02:00 committed by Alberto Mardegan
parent b873043fc4
commit 748abf9347
4 changed files with 78 additions and 2 deletions

View File

@ -1904,7 +1904,8 @@ int QDBusConnectionPrivate::send(const QDBusMessage& message)
qPrintable(message.interface()), qPrintable(message.member()),
qPrintable(error.message()));
else if (message.type() == QDBusMessage::SignalMessage)
qWarning("QDBusConnection: error: could not send signal path \"%s\" interface \"%s\" member \"%s\": %s",
qWarning("QDBusConnection: error: could not send signal to service \"%s\" path \"%s\" interface \"%s\" member \"%s\": %s",
qPrintable(message.service()),
qPrintable(message.path()), qPrintable(message.interface()),
qPrintable(message.member()),
qPrintable(error.message()));

View File

@ -153,8 +153,10 @@ DBusMessage *QDBusMessagePrivate::toDBusMessage(const QDBusMessage &message, QDB
}
break;
case QDBusMessage::SignalMessage:
// nothing can be empty here
// only the service name can be empty here
if (!d_ptr->parametersValidated) {
if (!QDBusUtil::checkBusName(d_ptr->service, QDBusUtil::EmptyAllowed, error))
return 0;
if (!QDBusUtil::checkObjectPath(d_ptr->path, QDBusUtil::EmptyNotAllowed, error))
return 0;
if (!QDBusUtil::checkInterfaceName(d_ptr->interface, QDBusUtil::EmptyAllowed, error))
@ -165,6 +167,7 @@ DBusMessage *QDBusMessagePrivate::toDBusMessage(const QDBusMessage &message, QDB
msg = q_dbus_message_new_signal(d_ptr->path.toUtf8(), d_ptr->interface.toUtf8(),
d_ptr->name.toUtf8());
q_dbus_message_set_destination(msg, data(d_ptr->service.toUtf8()));
break;
}
@ -371,6 +374,31 @@ QDBusMessage QDBusMessage::createSignal(const QString &path, const QString &inte
return message;
}
/*!
\since 5.6
Constructs a new DBus message with the given \a path, \a interface
and \a name, representing a signal emission to \a destination.
A DBus signal is emitted from one application and is received only by
the application owning the destination service name.
The QDBusMessage object that is returned can be sent using the
QDBusConnection::send() function.
*/
QDBusMessage QDBusMessage::createTargetedSignal(const QString &service, const QString &path,
const QString &interface, const QString &name)
{
QDBusMessage message;
message.d_ptr->type = SignalMessage;
message.d_ptr->service = service;
message.d_ptr->path = path;
message.d_ptr->interface = interface;
message.d_ptr->name = name;
return message;
}
/*!
Constructs a new DBus message representing a method call.
A method call always informs its destination address

View File

@ -67,6 +67,8 @@ public:
static QDBusMessage createSignal(const QString &path, const QString &interface,
const QString &name);
static QDBusMessage createTargetedSignal(const QString &service, const QString &path,
const QString &interface, const QString &name);
static QDBusMessage createMethodCall(const QString &destination, const QString &path,
const QString &interface, const QString &method);
static QDBusMessage createError(const QString &name, const QString &msg);

View File

@ -105,6 +105,8 @@ private slots:
void sendWithGui();
void sendAsync();
void sendSignal();
void sendSignalToName();
void sendSignalToOtherName();
void registerObject_data();
void registerObject();
@ -189,6 +191,49 @@ void tst_QDBusConnection::sendSignal()
QTest::qWait(1000);
}
void tst_QDBusConnection::sendSignalToName()
{
QDBusSpy spy;
QDBusConnection con = QDBusConnection::sessionBus();
con.connect(con.baseService(), "/org/kde/selftest", "org.kde.selftest", "ping", &spy,
SLOT(handlePing(QString)));
QDBusMessage msg =
QDBusMessage::createTargetedSignal(con.baseService(), "/org/kde/selftest",
"org.kde.selftest", "ping");
msg << QLatin1String("ping");
QVERIFY(con.send(msg));
QTest::qWait(1000);
QCOMPARE(spy.args.count(), 1);
QCOMPARE(spy.args.at(0).toString(), QString("ping"));
}
void tst_QDBusConnection::sendSignalToOtherName()
{
QDBusSpy spy;
QDBusConnection con = QDBusConnection::sessionBus();
con.connect(con.baseService(), "/org/kde/selftest", "org.kde.selftest", "ping", &spy,
SLOT(handlePing(QString)));
QDBusMessage msg =
QDBusMessage::createTargetedSignal("some.other.service", "/org/kde/selftest",
"org.kde.selftest", "ping");
msg << QLatin1String("ping");
QVERIFY(con.send(msg));
QTest::qWait(1000);
QCOMPARE(spy.args.count(), 0);
}
void tst_QDBusConnection::send()
{
QDBusConnection con = QDBusConnection::sessionBus();