source: trunk/src/dbus/qdbusservicewatcher.cpp@ 1023

Last change on this file since 1023 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

  • Property svn:eol-style set to native
File size: 12.8 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the QtDBus module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qdbusservicewatcher.h"
43#include "qdbusconnection.h"
44#include "qdbus_symbols_p.h"
45
46#include <QStringList>
47
48#include <private/qobject_p.h>
49
50#ifndef QT_NO_DBUS
51
52QT_BEGIN_NAMESPACE
53
54Q_GLOBAL_STATIC_WITH_ARGS(QString, busService, (QLatin1String(DBUS_SERVICE_DBUS)))
55Q_GLOBAL_STATIC_WITH_ARGS(QString, busInterface, (QLatin1String(DBUS_INTERFACE_DBUS)))
56Q_GLOBAL_STATIC_WITH_ARGS(QString, signalName, (QLatin1String("NameOwnerChanged")))
57
58class QDBusServiceWatcherPrivate: public QObjectPrivate
59{
60 Q_DECLARE_PUBLIC(QDBusServiceWatcher)
61public:
62 QDBusServiceWatcherPrivate(const QDBusConnection &c, QDBusServiceWatcher::WatchMode wm)
63 : connection(c), watchMode(wm)
64 {
65 }
66
67 QStringList servicesWatched;
68 QDBusConnection connection;
69 QDBusServiceWatcher::WatchMode watchMode;
70
71 void _q_serviceOwnerChanged(const QString &, const QString &, const QString &);
72 void setConnection(const QStringList &services, const QDBusConnection &c, QDBusServiceWatcher::WatchMode watchMode);
73
74 QStringList matchArgsForService(const QString &service);
75 void addService(const QString &service);
76 void removeService(const QString &service);
77};
78
79void QDBusServiceWatcherPrivate::_q_serviceOwnerChanged(const QString &service, const QString &oldOwner, const QString &newOwner)
80{
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);
87}
88
89void QDBusServiceWatcherPrivate::setConnection(const QStringList &s, const QDBusConnection &c, QDBusServiceWatcher::WatchMode wm)
90{
91 if (connection.isConnected()) {
92 // remove older rules
93 foreach (const QString &s, servicesWatched)
94 removeService(s);
95 }
96
97 connection = c;
98 watchMode = wm;
99 servicesWatched = s;
100
101 if (connection.isConnected()) {
102 // add new rules
103 foreach (const QString &s, servicesWatched)
104 addService(s);
105 }
106}
107
108QStringList QDBusServiceWatcherPrivate::matchArgsForService(const QString &service)
109{
110 QStringList matchArgs;
111 matchArgs << service;
112
113 switch (watchMode) {
114 case QDBusServiceWatcher::WatchForOwnerChange:
115 break;
116
117 case QDBusServiceWatcher::WatchForRegistration:
118 matchArgs << QString::fromLatin1("", 0);
119 break;
120
121 case QDBusServiceWatcher::WatchForUnregistration:
122 matchArgs << QString() << QString::fromLatin1("", 0);
123 break;
124 }
125 return matchArgs;
126}
127
128void QDBusServiceWatcherPrivate::addService(const QString &service)
129{
130 QStringList matchArgs = matchArgsForService(service);
131 connection.connect(*busService(), QString(), *busInterface(), *signalName(),
132 matchArgs, QString(), q_func(),
133 SLOT(_q_serviceOwnerChanged(QString,QString,QString)));
134}
135
136void QDBusServiceWatcherPrivate::removeService(const QString &service)
137{
138 QStringList matchArgs = matchArgsForService(service);
139 connection.disconnect(*busService(), QString(), *busInterface(), *signalName(),
140 matchArgs, QString(), q_func(),
141 SLOT(_q_serviceOwnerChanged(QString,QString,QString)));
142}
143
144/*!
145 \class QDBusServiceWatcher
146 \since 4.6
147 \inmodule QtDBus
148
149 \brief The QDBusServiceWatcher class allows the user to watch for a bus service change.
150
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
153 modes:
154
155 \list
156 \o Watching for service registration only.
157 \o Watching for service unregistration only.
158 \o Watching for any kind of service ownership change (the default mode).
159 \endlist
160
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
164 happens.
165
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.
169
170 \sa QDBusConnection
171*/
172
173/*!
174 \enum QDBusServiceWatcher::WatchModeFlag
175
176 QDBusServiceWatcher supports three different watch modes, which are configured by this flag:
177
178 \value WatchForRegistration watch for service registration only, ignoring
179 any signals related to other service ownership change.
180
181 \value WatchForUnregistration watch for service unregistration only,
182 ignoring any signals related to other service ownership change.
183
184 \value WatchForOwnerChange watch for any kind of service ownership
185 change.
186*/
187
188/*!
189 \property QDBusServiceWatcher::watchMode
190
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.
194*/
195
196/*!
197 \property QDBusServiceWatcher::watchedServices
198
199 The \c servicesWatched property holds the list of services watched.
200
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().
204*/
205
206/*!
207 \fn void QDBusServiceWatcher::serviceRegistered(const QString &serviceName)
208
209 This signal is emitted whenever this object detects that the service \a
210 serviceName became available on the bus.
211
212 \sa serviceUnregistered(), serviceOwnerChanged()
213*/
214
215/*!
216 \fn void QDBusServiceWatcher::serviceUnregistered(const QString &serviceName)
217
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.
220
221 \sa serviceRegistered(), serviceOwnerChanged()
222*/
223
224/*!
225 \fn void QDBusServiceWatcher::serviceOwnerChanged(const QString &serviceName, const QString &oldOwner, const QString &newOwner)
226
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.
231
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.
236
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.
241
242 \sa serviceRegistered(), serviceUnregistered()
243*/
244
245/*!
246 Creates a QDBusServiceWatcher object. Note that until you set a
247 connection with setConnection(), this object will not emit any signals.
248
249 The \a parent parameter is passed to QObject to set the parent of this
250 object.
251*/
252QDBusServiceWatcher::QDBusServiceWatcher(QObject *parent)
253 : QObject(*new QDBusServiceWatcherPrivate(QDBusConnection(QString()), WatchForOwnerChange), parent)
254{
255}
256
257/*!
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.
261
262 The \a parent parameter is passed to QObject to set the parent of this
263 object.
264*/
265QDBusServiceWatcher::QDBusServiceWatcher(const QString &service, const QDBusConnection &connection, WatchMode watchMode, QObject *parent)
266 : QObject(*new QDBusServiceWatcherPrivate(connection, watchMode), parent)
267{
268 d_func()->setConnection(QStringList() << service, connection, watchMode);
269}
270
271/*!
272 Destroys the QDBusServiceWatcher object and releases any resources
273 associated with it.
274*/
275QDBusServiceWatcher::~QDBusServiceWatcher()
276{
277}
278
279/*!
280 Returns the list of D-Bus services that are being watched.
281
282 \sa setWatchedServices()
283*/
284QStringList QDBusServiceWatcher::watchedServices() const
285{
286 return d_func()->servicesWatched;
287}
288
289/*!
290 Sets the list of D-Bus services being watched to be \a services.
291
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.
296*/
297void QDBusServiceWatcher::setWatchedServices(const QStringList &services)
298{
299 Q_D(QDBusServiceWatcher);
300 if (services == d->servicesWatched)
301 return;
302 d->setConnection(services, d->connection, d->watchMode);
303}
304
305/*!
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.
309*/
310void QDBusServiceWatcher::addWatchedService(const QString &newService)
311{
312 Q_D(QDBusServiceWatcher);
313 if (d->servicesWatched.contains(newService))
314 return;
315 d->addService(newService);
316 d->servicesWatched << newService;
317}
318
319/*!
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.
324
325 This function returns true if any services were removed.
326*/
327bool QDBusServiceWatcher::removeWatchedService(const QString &service)
328{
329 Q_D(QDBusServiceWatcher);
330 d->removeService(service);
331 return d->servicesWatched.removeOne(service);
332}
333
334QDBusServiceWatcher::WatchMode QDBusServiceWatcher::watchMode() const
335{
336 return d_func()->watchMode;
337}
338
339void QDBusServiceWatcher::setWatchMode(WatchMode mode)
340{
341 Q_D(QDBusServiceWatcher);
342 if (mode == d->watchMode)
343 return;
344 d->setConnection(d->servicesWatched, d->connection, mode);
345}
346
347/*!
348 Returns the QDBusConnection that this object is attached to.
349
350 \sa setConnection()
351*/
352QDBusConnection QDBusServiceWatcher::connection() const
353{
354 return d_func()->connection;
355}
356
357/*!
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.
360
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.
366
367 \sa connection()
368*/
369void QDBusServiceWatcher::setConnection(const QDBusConnection &connection)
370{
371 Q_D(QDBusServiceWatcher);
372 if (connection.name() == d->connection.name())
373 return;
374 d->setConnection(d->servicesWatched, connection, d->watchMode);
375}
376
377QT_END_NAMESPACE
378
379#endif // QT_NO_DBUS
380
381#include "moc_qdbusservicewatcher.cpp"
Note: See TracBrowser for help on using the repository browser.