1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtDBus module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include "qdbusservicewatcher.h"
43 #include "qdbusconnection.h"
44 #include "qdbus_symbols_p.h"
46 #include <QStringList>
48 #include <private/qobject_p.h>
54 Q_GLOBAL_STATIC_WITH_ARGS(QString, busService, (QLatin1String(DBUS_SERVICE_DBUS)))
55 Q_GLOBAL_STATIC_WITH_ARGS(QString, busInterface, (QLatin1String(DBUS_INTERFACE_DBUS)))
56 Q_GLOBAL_STATIC_WITH_ARGS(QString, signalName, (QLatin1String("NameOwnerChanged")))
58 class QDBusServiceWatcherPrivate: public QObjectPrivate
60 Q_DECLARE_PUBLIC(QDBusServiceWatcher)
62 QDBusServiceWatcherPrivate(const QDBusConnection &c, QDBusServiceWatcher::WatchMode wm)
63 : connection(c), watchMode(wm)
67 QStringList servicesWatched;
68 QDBusConnection connection;
69 QDBusServiceWatcher::WatchMode watchMode;
71 void _q_serviceOwnerChanged(const QString &, const QString &, const QString &);
72 void setConnection(const QStringList &services, const QDBusConnection &c, QDBusServiceWatcher::WatchMode watchMode);
74 QStringList matchArgsForService(const QString &service);
75 void addService(const QString &service);
76 void removeService(const QString &service);
79 void QDBusServiceWatcherPrivate::_q_serviceOwnerChanged(const QString &service, const QString &oldOwner, const QString &newOwner)
81 Q_Q(QDBusServiceWatcher);
82 emit q->serviceOwnerChanged(service, oldOwner, newOwner);
83 if (oldOwner.isEmpty())
84 emit q->serviceRegistered(service);
85 else if (newOwner.isEmpty())
86 emit q->serviceUnregistered(service);
89 void QDBusServiceWatcherPrivate::setConnection(const QStringList &s, const QDBusConnection &c, QDBusServiceWatcher::WatchMode wm)
91 if (connection.isConnected()) {
93 foreach (const QString &s, servicesWatched)
101 if (connection.isConnected()) {
103 foreach (const QString &s, servicesWatched)
108 QStringList QDBusServiceWatcherPrivate::matchArgsForService(const QString &service)
110 QStringList matchArgs;
111 matchArgs << service;
114 case QDBusServiceWatcher::WatchForOwnerChange:
117 case QDBusServiceWatcher::WatchForRegistration:
118 matchArgs << QString::fromLatin1("", 0);
121 case QDBusServiceWatcher::WatchForUnregistration:
122 matchArgs << QString() << QString::fromLatin1("", 0);
128 void QDBusServiceWatcherPrivate::addService(const QString &service)
130 QStringList matchArgs = matchArgsForService(service);
131 connection.connect(*busService(), QString(), *busInterface(), *signalName(),
132 matchArgs, QString(), q_func(),
133 SLOT(_q_serviceOwnerChanged(QString,QString,QString)));
136 void QDBusServiceWatcherPrivate::removeService(const QString &service)
138 QStringList matchArgs = matchArgsForService(service);
139 connection.disconnect(*busService(), QString(), *busInterface(), *signalName(),
140 matchArgs, QString(), q_func(),
141 SLOT(_q_serviceOwnerChanged(QString,QString,QString)));
145 \class QDBusServiceWatcher
149 \brief The QDBusServiceWatcher class allows the user to watch for a bus service change.
151 A QDBusServiceWatcher object can be used to notify the application about
152 an ownership change of a service name on the bus. It has three watch
156 \li Watching for service registration only.
157 \li Watching for service unregistration only.
158 \li Watching for any kind of service ownership change (the default mode).
161 Besides being created or deleted, services may change owners without a
162 unregister/register operation happening. So the serviceRegistered()
163 and serviceUnregistered() signals may not be emitted if that
166 This class is more efficient than using the
167 QDBusConnectionInterface::serviceOwnerChanged() signal because it allows
168 one to receive only the signals for which the class is interested in.
174 \enum QDBusServiceWatcher::WatchModeFlag
176 QDBusServiceWatcher supports three different watch modes, which are configured by this flag:
178 \value WatchForRegistration watch for service registration only, ignoring
179 any signals related to other service ownership change.
181 \value WatchForUnregistration watch for service unregistration only,
182 ignoring any signals related to other service ownership change.
184 \value WatchForOwnerChange watch for any kind of service ownership
189 \property QDBusServiceWatcher::watchMode
191 The \c watchMode property holds the current watch mode for this
192 QDBusServiceWatcher object. The default value for this property is
193 QDBusServiceWatcher::WatchForOwnershipChange.
197 \property QDBusServiceWatcher::watchedServices
199 The \c servicesWatched property holds the list of services watched.
201 Note that modifying this list with setServicesWatched() is an expensive
202 operation. If you can, prefer to change it by way of addWatchedService()
203 and removeWatchedService().
207 \fn void QDBusServiceWatcher::serviceRegistered(const QString &serviceName)
209 This signal is emitted whenever this object detects that the service \a
210 serviceName became available on the bus.
212 \sa serviceUnregistered(), serviceOwnerChanged()
216 \fn void QDBusServiceWatcher::serviceUnregistered(const QString &serviceName)
218 This signal is emitted whenever this object detects that the service \a
219 serviceName was unregistered from the bus and is no longer available.
221 \sa serviceRegistered(), serviceOwnerChanged()
225 \fn void QDBusServiceWatcher::serviceOwnerChanged(const QString &serviceName, const QString &oldOwner, const QString &newOwner)
227 This signal is emitted whenever this object detects that there was a
228 service ownership change relating to the \a serviceName service. The \a
229 oldOwner parameter contains the old owner name and \a newOwner is the new
230 owner. Both \a oldOwner and \a newOwner are unique connection names.
232 Note that this signal is also emitted whenever the \a serviceName service
233 was registered or unregistered. If it was registered, \a oldOwner will
234 contain an empty string, whereas if it was unregistered, \a newOwner will
235 contain an empty string.
237 If you need only to find out if the service is registered or unregistered
238 only, without being notified that the ownership changed, consider using
239 the specific modes for those operations. This class is more efficient if
240 you use the more specific modes.
242 \sa serviceRegistered(), serviceUnregistered()
246 Creates a QDBusServiceWatcher object. Note that until you set a
247 connection with setConnection(), this object will not emit any signals.
249 The \a parent parameter is passed to QObject to set the parent of this
252 QDBusServiceWatcher::QDBusServiceWatcher(QObject *parent)
253 : QObject(*new QDBusServiceWatcherPrivate(QDBusConnection(QString()), WatchForOwnerChange), parent)
258 Creates a QDBusServiceWatcher object and attaches it to the \a connection
259 connection. Also, this function immediately starts watching for \a
260 watchMode changes to service \a service.
262 The \a parent parameter is passed to QObject to set the parent of this
265 QDBusServiceWatcher::QDBusServiceWatcher(const QString &service, const QDBusConnection &connection, WatchMode watchMode, QObject *parent)
266 : QObject(*new QDBusServiceWatcherPrivate(connection, watchMode), parent)
268 d_func()->setConnection(QStringList() << service, connection, watchMode);
272 Destroys the QDBusServiceWatcher object and releases any resources
275 QDBusServiceWatcher::~QDBusServiceWatcher()
280 Returns the list of D-Bus services that are being watched.
282 \sa setWatchedServices()
284 QStringList QDBusServiceWatcher::watchedServices() const
286 return d_func()->servicesWatched;
290 Sets the list of D-Bus services being watched to be \a services.
292 Note that setting the entire list means removing all previous rules for
293 watching services and adding new ones. This is an expensive operation and
294 should be avoided, if possible. Instead, use addWatchedService() and
295 removeWatchedService() if you can to manipulate entries in the list.
297 void QDBusServiceWatcher::setWatchedServices(const QStringList &services)
299 Q_D(QDBusServiceWatcher);
300 if (services == d->servicesWatched)
302 d->setConnection(services, d->connection, d->watchMode);
306 Adds \a newService to the list of services to be watched by this object.
307 This function is more efficient than setWatchedServices() and should be
308 used whenever possible to add services.
310 void QDBusServiceWatcher::addWatchedService(const QString &newService)
312 Q_D(QDBusServiceWatcher);
313 if (d->servicesWatched.contains(newService))
315 d->addService(newService);
316 d->servicesWatched << newService;
320 Removes the \a service from the list of services being watched by this
321 object. Note that D-Bus notifications are asynchronous, so there may
322 still be signals pending delivery about \a service. Those signals will
323 still be emitted whenever the D-Bus messages are processed.
325 This function returns true if any services were removed.
327 bool QDBusServiceWatcher::removeWatchedService(const QString &service)
329 Q_D(QDBusServiceWatcher);
330 d->removeService(service);
331 return d->servicesWatched.removeOne(service);
334 QDBusServiceWatcher::WatchMode QDBusServiceWatcher::watchMode() const
336 return d_func()->watchMode;
339 void QDBusServiceWatcher::setWatchMode(WatchMode mode)
341 Q_D(QDBusServiceWatcher);
342 if (mode == d->watchMode)
344 d->setConnection(d->servicesWatched, d->connection, mode);
348 Returns the QDBusConnection that this object is attached to.
352 QDBusConnection QDBusServiceWatcher::connection() const
354 return d_func()->connection;
358 Sets the D-Bus connection that this object is attached to be \a
359 connection. All services watched will be transferred to this connection.
361 Note that QDBusConnection objects are reference counted:
362 QDBusServiceWatcher will keep a reference for this connection while it
363 exists. The connection is not closed until the reference count drops to
364 zero, so this will ensure that any notifications are received while this
365 QDBusServiceWatcher object exists.
369 void QDBusServiceWatcher::setConnection(const QDBusConnection &connection)
371 Q_D(QDBusServiceWatcher);
372 if (connection.name() == d->connection.name())
374 d->setConnection(d->servicesWatched, connection, d->watchMode);
381 #include "moc_qdbusservicewatcher.cpp"