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

Last change on this file since 792 was 651, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.2 sources.

  • Property svn:eol-style set to native
File size: 12.8 KB
RevLine 
[556]1/****************************************************************************
2**
[651]3** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
[556]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
50QT_BEGIN_NAMESPACE
51
52Q_GLOBAL_STATIC_WITH_ARGS(QString, busService, (QLatin1String(DBUS_SERVICE_DBUS)))
53Q_GLOBAL_STATIC_WITH_ARGS(QString, busInterface, (QLatin1String(DBUS_INTERFACE_DBUS)))
54Q_GLOBAL_STATIC_WITH_ARGS(QString, signalName, (QLatin1String("NameOwnerChanged")))
55
56class QDBusServiceWatcherPrivate: public QObjectPrivate
57{
58 Q_DECLARE_PUBLIC(QDBusServiceWatcher)
59public:
60 QDBusServiceWatcherPrivate(const QDBusConnection &c, QDBusServiceWatcher::WatchMode wm)
61 : connection(c), watchMode(wm)
62 {
63 }
64
65 QStringList servicesWatched;
66 QDBusConnection connection;
67 QDBusServiceWatcher::WatchMode watchMode;
68
69 void _q_serviceOwnerChanged(const QString &, const QString &, const QString &);
70 void setConnection(const QStringList &services, const QDBusConnection &c, QDBusServiceWatcher::WatchMode watchMode);
71
72 QStringList matchArgsForService(const QString &service);
73 void addService(const QString &service);
74 void removeService(const QString &service);
75};
76
77void QDBusServiceWatcherPrivate::_q_serviceOwnerChanged(const QString &service, const QString &oldOwner, const QString &newOwner)
78{
79 Q_Q(QDBusServiceWatcher);
80 emit q->serviceOwnerChanged(service, oldOwner, newOwner);
81 if (oldOwner.isEmpty())
82 emit q->serviceRegistered(service);
83 else if (newOwner.isEmpty())
84 emit q->serviceUnregistered(service);
85}
86
87void QDBusServiceWatcherPrivate::setConnection(const QStringList &s, const QDBusConnection &c, QDBusServiceWatcher::WatchMode wm)
88{
89 if (connection.isConnected()) {
90 // remove older rules
91 foreach (const QString &s, servicesWatched)
92 removeService(s);
93 }
94
95 connection = c;
96 watchMode = wm;
97 servicesWatched = s;
98
99 if (connection.isConnected()) {
100 // add new rules
101 foreach (const QString &s, servicesWatched)
102 addService(s);
103 }
104}
105
106QStringList QDBusServiceWatcherPrivate::matchArgsForService(const QString &service)
107{
108 QStringList matchArgs;
109 matchArgs << service;
110
111 switch (watchMode) {
112 case QDBusServiceWatcher::WatchForOwnerChange:
113 break;
114
115 case QDBusServiceWatcher::WatchForRegistration:
116 matchArgs << QString::fromLatin1("", 0);
117 break;
118
119 case QDBusServiceWatcher::WatchForUnregistration:
120 matchArgs << QString() << QString::fromLatin1("", 0);
121 break;
122 }
123 return matchArgs;
124}
125
126void QDBusServiceWatcherPrivate::addService(const QString &service)
127{
128 QStringList matchArgs = matchArgsForService(service);
129 connection.connect(*busService(), QString(), *busInterface(), *signalName(),
130 matchArgs, QString(), q_func(),
131 SLOT(_q_serviceOwnerChanged(QString,QString,QString)));
132}
133
134void QDBusServiceWatcherPrivate::removeService(const QString &service)
135{
136 QStringList matchArgs = matchArgsForService(service);
137 connection.disconnect(*busService(), QString(), *busInterface(), *signalName(),
138 matchArgs, QString(), q_func(),
139 SLOT(_q_serviceOwnerChanged(QString,QString,QString)));
140}
141
142/*!
143 \class QDBusServiceWatcher
144 \since 4.6
145 \inmodule QtDBus
146
147 \brief The QDBusServiceWatcher class allows the user to watch for a bus service change.
148
149 A QDBusServiceWatcher object can be used to notify the application about
150 an ownership change of a service name on the bus. It has three watch
151 modes:
152
153 \list
154 \o Watching for service registration only.
155 \o Watching for service unregistration only.
156 \o Watching for any kind of service ownership change (the default mode).
157 \endlist
158
159 Besides being created or deleted, services may change owners without a
160 unregister/register operation happening. So the serviceRegistered()
161 and serviceUnregistered() signals may not be emitted if that
162 happens.
163
164 This class is more efficient than using the
165 QDBusConnectionInterface::serviceOwnerChanged() signal because it allows
166 one to receive only the signals for which the class is interested in.
167
168 \sa QDBusConnection
169*/
170
171/*!
172 \enum QDBusServiceWatcher::WatchModeFlag
173
174 QDBusServiceWatcher supports three different watch modes, which are configured by this flag:
175
176 \value WatchForRegistration watch for service registration only, ignoring
177 any signals related to other service ownership change.
178
179 \value WatchForUnregistration watch for service unregistration only,
180 ignoring any signals related to other service ownership change.
181
182 \value WatchForOwnerChange watch for any kind of service ownership
183 change.
184*/
185
186/*!
187 \property QDBusServiceWatcher::watchMode
188
189 The \c watchMode property holds the current watch mode for this
190 QDBusServiceWatcher object. The default value for this property is
191 QDBusServiceWatcher::WatchForOwnershipChange.
192*/
193
194/*!
195 \property QDBusServiceWatcher::watchedServices
196
197 The \c servicesWatched property holds the list of services watched.
198
199 Note that modifying this list with setServicesWatched() is an expensive
200 operation. If you can, prefer to change it by way of addWatchedService()
201 and removeWatchedService().
202*/
203
204/*!
205 \fn void QDBusServiceWatcher::serviceRegistered(const QString &serviceName)
206
207 This signal is emitted whenever this object detects that the service \a
208 serviceName became available on the bus.
209
210 \sa serviceUnregistered(), serviceOwnerChanged()
211*/
212
213/*!
214 \fn void QDBusServiceWatcher::serviceUnregistered(const QString &serviceName)
215
216 This signal is emitted whenever this object detects that the service \a
217 serviceName was unregistered from the bus and is no longer available.
218
219 \sa serviceRegistered(), serviceOwnerChanged()
220*/
221
222/*!
223 \fn void QDBusServiceWatcher::serviceOwnerChanged(const QString &serviceName, const QString &oldOwner, const QString &newOwner)
224
225 This signal is emitted whenever this object detects that there was a
226 service ownership change relating to the \a serviceName service. The \a
227 oldOwner parameter contains the old owner name and \a newOwner is the new
228 owner. Both \a oldOwner and \a newOwner are unique connection names.
229
230 Note that this signal is also emitted whenever the \a serviceName service
231 was registered or unregistered. If it was registered, \a oldOwner will
232 contain an empty string, whereas if it was unregistered, \a newOwner will
233 contain an empty string.
234
235 If you need only to find out if the service is registered or unregistered
236 only, without being notified that the ownership changed, consider using
237 the specific modes for those operations. This class is more efficient if
238 you use the more specific modes.
239
240 \sa serviceRegistered(), serviceUnregistered()
241*/
242
243/*!
244 Creates a QDBusServiceWatcher object. Note that until you set a
245 connection with setConnection(), this object will not emit any signals.
246
247 The \a parent parameter is passed to QObject to set the parent of this
248 object.
249*/
250QDBusServiceWatcher::QDBusServiceWatcher(QObject *parent)
251 : QObject(*new QDBusServiceWatcherPrivate(QDBusConnection(QString()), WatchForOwnerChange), parent)
252{
253}
254
255/*!
256 Creates a QDBusServiceWatcher object and attaches it to the \a connection
257 connection. Also, this function immediately starts watching for \a
258 watchMode changes to service \a service.
259
260 The \a parent parameter is passed to QObject to set the parent of this
261 object.
262*/
263QDBusServiceWatcher::QDBusServiceWatcher(const QString &service, const QDBusConnection &connection, WatchMode watchMode, QObject *parent)
264 : QObject(*new QDBusServiceWatcherPrivate(connection, watchMode), parent)
265{
266 d_func()->setConnection(QStringList() << service, connection, watchMode);
267}
268
269/*!
270 Destroys the QDBusServiceWatcher object and releases any resources
271 associated with it.
272*/
273QDBusServiceWatcher::~QDBusServiceWatcher()
274{
275}
276
277/*!
278 Returns the list of D-Bus services that are being watched.
279
280 \sa setWatchedServices()
281*/
282QStringList QDBusServiceWatcher::watchedServices() const
283{
284 return d_func()->servicesWatched;
285}
286
287/*!
288 Sets the list of D-Bus services being watched to be \a services.
289
290 Note that setting the entire list means removing all previous rules for
291 watching services and adding new ones. This is an expensive operation and
292 should be avoided, if possible. Instead, use addWatchedService() and
293 removeWatchedService() if you can to manipulate entries in the list.
294*/
295void QDBusServiceWatcher::setWatchedServices(const QStringList &services)
296{
297 Q_D(QDBusServiceWatcher);
298 if (services == d->servicesWatched)
299 return;
300 d->setConnection(services, d->connection, d->watchMode);
301}
302
303/*!
304 Adds \a newService to the list of services to be watched by this object.
305 This function is more efficient than setWatchedServices() and should be
306 used whenever possible to add services.
307*/
308void QDBusServiceWatcher::addWatchedService(const QString &newService)
309{
310 Q_D(QDBusServiceWatcher);
311 if (d->servicesWatched.contains(newService))
312 return;
313 d->addService(newService);
314 d->servicesWatched << newService;
315}
316
317/*!
318 Removes the \a service from the list of services being watched by this
319 object. Note that D-Bus notifications are asynchronous, so there may
320 still be signals pending delivery about \a service. Those signals will
321 still be emitted whenever the D-Bus messages are processed.
322
323 This function returns true if any services were removed.
324*/
325bool QDBusServiceWatcher::removeWatchedService(const QString &service)
326{
327 Q_D(QDBusServiceWatcher);
328 d->removeService(service);
329 return d->servicesWatched.removeOne(service);
330}
331
332QDBusServiceWatcher::WatchMode QDBusServiceWatcher::watchMode() const
333{
334 return d_func()->watchMode;
335}
336
337void QDBusServiceWatcher::setWatchMode(WatchMode mode)
338{
339 Q_D(QDBusServiceWatcher);
340 if (mode == d->watchMode)
341 return;
342 d->setConnection(d->servicesWatched, d->connection, mode);
343}
344
345/*!
346 Returns the QDBusConnection that this object is attached to.
347
348 \sa setConnection()
349*/
350QDBusConnection QDBusServiceWatcher::connection() const
351{
352 return d_func()->connection;
353}
354
355/*!
356 Sets the D-Bus connection that this object is attached to be \a
357 connection. All services watched will be transferred to this connection.
358
359 Note that QDBusConnection objects are reference counted:
360 QDBusServiceWatcher will keep a reference for this connection while it
361 exists. The connection is not closed until the reference count drops to
362 zero, so this will ensure that any notifications are received while this
363 QDBusServiceWatcher object exists.
364
365 \sa connection()
366*/
367void QDBusServiceWatcher::setConnection(const QDBusConnection &connection)
368{
369 Q_D(QDBusServiceWatcher);
370 if (connection.name() == d->connection.name())
371 return;
372 d->setConnection(d->servicesWatched, connection, d->watchMode);
373}
374
375QT_END_NAMESPACE
376
377#include "moc_qdbusservicewatcher.cpp"
Note: See TracBrowser for help on using the repository browser.