author | Eckhart Koeppen <eckhart.koppen@nokia.com> |
Thu, 29 Apr 2010 15:15:16 +0300 | |
branch | RCL_3 |
changeset 16 | 4b6ee5efea19 |
parent 7 | 3f74d0d4af4c |
permissions | -rw-r--r-- |
0 | 1 |
/**************************************************************************** |
2 |
** |
|
4
3b1da2848fc7
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
3
diff
changeset
|
3 |
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). |
0 | 4 |
** All rights reserved. |
5 |
** Contact: Nokia Corporation (qt-info@nokia.com) |
|
6 |
** |
|
7 |
** This file is part of the QtDBus module of the Qt Toolkit. |
|
8 |
** |
|
9 |
** $QT_BEGIN_LICENSE:LGPL$ |
|
10 |
** No Commercial Usage |
|
11 |
** This file contains pre-release code and may not be distributed. |
|
12 |
** You may use this file in accordance with the terms and conditions |
|
13 |
** contained in the Technology Preview License Agreement accompanying |
|
14 |
** this package. |
|
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 |
** If you have questions regarding the use of this file, please contact |
|
29 |
** Nokia at qt-info@nokia.com. |
|
30 |
** |
|
31 |
** |
|
32 |
** |
|
33 |
** |
|
34 |
** |
|
35 |
** |
|
36 |
** |
|
37 |
** |
|
38 |
** $QT_END_LICENSE$ |
|
39 |
** |
|
40 |
****************************************************************************/ |
|
41 |
||
42 |
#include <qdebug.h> |
|
43 |
#include <qcoreapplication.h> |
|
44 |
#include <qstringlist.h> |
|
45 |
||
46 |
#include "qdbusconnection.h" |
|
47 |
#include "qdbusconnectioninterface.h" |
|
48 |
#include "qdbuserror.h" |
|
49 |
#include "qdbusmessage.h" |
|
50 |
#include "qdbusmessage_p.h" |
|
51 |
#include "qdbusconnection_p.h" |
|
52 |
#include "qdbusinterface_p.h" |
|
53 |
#include "qdbusutil_p.h" |
|
54 |
||
55 |
#include "qdbusthreaddebug_p.h" |
|
56 |
||
57 |
QT_BEGIN_NAMESPACE |
|
58 |
||
59 |
class QDBusConnectionManager |
|
60 |
{ |
|
61 |
public: |
|
62 |
QDBusConnectionManager() {} |
|
63 |
~QDBusConnectionManager(); |
|
64 |
||
65 |
QDBusConnectionPrivate *connection(const QString &name) const; |
|
66 |
void removeConnection(const QString &name); |
|
67 |
void setConnection(const QString &name, QDBusConnectionPrivate *c); |
|
68 |
||
69 |
QDBusConnectionPrivate *sender() const; |
|
70 |
void setSender(const QDBusConnectionPrivate *s); |
|
71 |
||
72 |
mutable QMutex mutex; |
|
73 |
private: |
|
74 |
QHash<QString, QDBusConnectionPrivate *> connectionHash; |
|
75 |
||
76 |
mutable QMutex senderMutex; |
|
77 |
QString senderName; // internal; will probably change |
|
78 |
}; |
|
79 |
||
80 |
Q_GLOBAL_STATIC(QDBusConnectionManager, _q_manager) |
|
81 |
||
82 |
QDBusConnectionPrivate *QDBusConnectionManager::sender() const |
|
83 |
{ |
|
84 |
QMutexLocker locker(&senderMutex); |
|
85 |
return connection(senderName); |
|
86 |
} |
|
87 |
||
88 |
void QDBusConnectionManager::setSender(const QDBusConnectionPrivate *s) |
|
89 |
{ |
|
90 |
QMutexLocker locker(&senderMutex); |
|
91 |
senderName = (s ? s->name : QString()); |
|
92 |
} |
|
93 |
||
94 |
QDBusConnectionPrivate *QDBusConnectionManager::connection(const QString &name) const |
|
95 |
{ |
|
96 |
return connectionHash.value(name, 0); |
|
97 |
} |
|
98 |
||
99 |
void QDBusConnectionManager::removeConnection(const QString &name) |
|
100 |
{ |
|
101 |
QDBusConnectionPrivate *d = 0; |
|
102 |
d = connectionHash.take(name); |
|
103 |
if (d && !d->ref.deref()) |
|
104 |
d->deleteYourself(); |
|
105 |
||
106 |
// Static objects may be keeping the connection open. |
|
107 |
// However, it is harmless to have outstanding references to a connection that is |
|
108 |
// closing as long as those references will be soon dropped without being used. |
|
109 |
||
110 |
// ### Output a warning if connections are being used after they have been removed. |
|
111 |
} |
|
112 |
||
113 |
QDBusConnectionManager::~QDBusConnectionManager() |
|
114 |
{ |
|
115 |
for (QHash<QString, QDBusConnectionPrivate *>::const_iterator it = connectionHash.constBegin(); |
|
116 |
it != connectionHash.constEnd(); ++it) { |
|
117 |
QDBusConnectionPrivate *d = it.value(); |
|
118 |
if (!d->ref.deref()) |
|
119 |
d->deleteYourself(); |
|
120 |
else |
|
121 |
d->closeConnection(); |
|
122 |
} |
|
123 |
connectionHash.clear(); |
|
124 |
} |
|
125 |
||
126 |
QDBUS_EXPORT void qDBusBindToApplication(); |
|
127 |
void qDBusBindToApplication() |
|
128 |
{ |
|
129 |
} |
|
130 |
||
131 |
void QDBusConnectionManager::setConnection(const QString &name, QDBusConnectionPrivate *c) |
|
132 |
{ |
|
133 |
connectionHash[name] = c; |
|
134 |
c->name = name; |
|
135 |
} |
|
136 |
||
137 |
/*! |
|
138 |
\fn QDBusConnection &QDBusConnection::sessionBus() |
|
139 |
\relates QDBusConnection |
|
140 |
||
141 |
Returns a QDBusConnection object opened with the session bus. The object reference returned |
|
142 |
by this function is valid until the QCoreApplication's destructor is run, when the |
|
143 |
connection will be closed and the object, deleted. |
|
144 |
*/ |
|
145 |
/*! |
|
146 |
\fn QDBusConnection &QDBusConnection::systemBus() |
|
147 |
\relates QDBusConnection |
|
148 |
||
149 |
Returns a QDBusConnection object opened with the system bus. The object reference returned |
|
150 |
by this function is valid until the QCoreApplication's destructor is run, when the |
|
151 |
connection will be closed and the object, deleted. |
|
152 |
*/ |
|
153 |
||
154 |
/*! |
|
155 |
\class QDBusConnection |
|
156 |
\inmodule QtDBus |
|
157 |
\since 4.2 |
|
158 |
||
159 |
\brief The QDBusConnection class represents a connection to the D-Bus bus daemon. |
|
160 |
||
161 |
This class is the initial point in a D-Bus session. Using it, you |
|
162 |
can get access to remote objects, interfaces; connect remote |
|
163 |
signals to your object's slots; register objects, etc. |
|
164 |
||
165 |
D-Bus connections are created using the connectToBus() function, |
|
166 |
which opens a connection to the server daemon and does the initial |
|
167 |
handshaking, associating that connection with a name. Further |
|
168 |
attempts to connect using the same name will return the same |
|
169 |
connection. |
|
170 |
||
171 |
The connection is then torn down using the disconnectFromBus() |
|
172 |
function. |
|
173 |
||
174 |
As a convenience for the two most common connection types, the |
|
175 |
sessionBus() and systemBus() functions return open connections to |
|
176 |
the session server daemon and the system server daemon, |
|
177 |
respectively. Those connections are opened when first used and are |
|
178 |
closed when the QCoreApplication destructor is run. |
|
179 |
||
180 |
D-Bus also supports peer-to-peer connections, without the need for |
|
181 |
a bus server daemon. Using this facility, two applications can |
|
182 |
talk to each other and exchange messages. This can be achieved by |
|
183 |
passing an address to connectToBus() function, which was opened by |
|
184 |
another D-Bus application using QDBusServer. |
|
185 |
*/ |
|
186 |
||
187 |
/*! |
|
188 |
\enum QDBusConnection::BusType |
|
189 |
Specifies the type of the bus connection. The valid bus types are: |
|
190 |
||
191 |
\value SessionBus the session bus, associated with the running desktop session |
|
192 |
\value SystemBus the system bus, used to communicate with system-wide processes |
|
193 |
\value ActivationBus the activation bus, the "alias" for the bus that started the |
|
194 |
service |
|
195 |
||
196 |
On the Session Bus, one can find other applications by the same user that are sharing the same |
|
197 |
desktop session (hence the name). On the System Bus, however, processes shared for the whole |
|
198 |
system are usually found. |
|
199 |
*/ |
|
200 |
||
201 |
/*! |
|
202 |
\enum QDBusConnection::RegisterOption |
|
203 |
Specifies the options for registering objects with the connection. The possible values are: |
|
204 |
||
205 |
\value ExportAdaptors export the contents of adaptors found in this object |
|
206 |
||
207 |
\value ExportScriptableSlots export this object's scriptable slots |
|
208 |
\value ExportScriptableSignals export this object's scriptable signals |
|
209 |
\value ExportScriptableProperties export this object's scriptable properties |
|
210 |
\value ExportScriptableContents shorthand form for ExportScriptableSlots | |
|
211 |
ExportScriptableSignals | |
|
212 |
ExportScriptableProperties |
|
213 |
||
214 |
\value ExportNonScriptableSlots export this object's non-scriptable slots |
|
215 |
\value ExportNonScriptableSignals export this object's non-scriptable signals |
|
216 |
\value ExportNonScriptableProperties export this object's non-scriptable properties |
|
217 |
\value ExportNonScriptableContents shorthand form for ExportNonScriptableSlots | |
|
218 |
ExportNonScriptableSignals | |
|
219 |
ExportNonScriptableProperties |
|
220 |
||
221 |
\value ExportAllSlots export all of this object's slots |
|
222 |
\value ExportAllSignals export all of this object's signals |
|
223 |
\value ExportAllProperties export all of this object's properties |
|
224 |
\value ExportAllContents export all of this object's contents |
|
225 |
||
226 |
\value ExportChildObjects export this object's child objects |
|
227 |
||
228 |
\sa registerObject(), QDBusAbstractAdaptor, {usingadaptors.html}{Using adaptors} |
|
229 |
*/ |
|
230 |
||
231 |
/*! |
|
232 |
\enum QDBusConnection::UnregisterMode |
|
233 |
The mode for unregistering an object path: |
|
234 |
||
235 |
\value UnregisterNode unregister this node only: do not unregister child objects |
|
236 |
\value UnregisterTree unregister this node and all its sub-tree |
|
237 |
||
238 |
Note, however, if this object was registered with the ExportChildObjects option, UnregisterNode |
|
239 |
will unregister the child objects too. |
|
240 |
*/ |
|
241 |
||
242 |
/*! |
|
243 |
Creates a QDBusConnection object attached to the connection with name \a name. |
|
244 |
||
245 |
This does not open the connection. You have to call connectToBus() to open it. |
|
246 |
*/ |
|
247 |
QDBusConnection::QDBusConnection(const QString &name) |
|
248 |
{ |
|
249 |
if (name.isEmpty()) { |
|
250 |
d = 0; |
|
251 |
} else { |
|
252 |
QMutexLocker locker(&_q_manager()->mutex); |
|
253 |
d = _q_manager()->connection(name); |
|
254 |
if (d) |
|
255 |
d->ref.ref(); |
|
256 |
} |
|
257 |
} |
|
258 |
||
259 |
/*! |
|
260 |
Creates a copy of the \a other connection. |
|
261 |
*/ |
|
262 |
QDBusConnection::QDBusConnection(const QDBusConnection &other) |
|
263 |
{ |
|
264 |
d = other.d; |
|
265 |
if (d) |
|
266 |
d->ref.ref(); |
|
267 |
} |
|
268 |
||
269 |
/*! |
|
270 |
\internal |
|
271 |
Creates a connection object with the given \a dd as private object. |
|
272 |
*/ |
|
273 |
QDBusConnection::QDBusConnection(QDBusConnectionPrivate *dd) |
|
274 |
{ |
|
275 |
d = dd; |
|
276 |
if (d) |
|
277 |
d->ref.ref(); |
|
278 |
} |
|
279 |
||
280 |
/*! |
|
281 |
Disposes of this object. This does not close the connection: you |
|
282 |
have to call disconnectFromBus() to do that. |
|
283 |
*/ |
|
284 |
QDBusConnection::~QDBusConnection() |
|
285 |
{ |
|
286 |
if (d && !d->ref.deref()) |
|
287 |
d->deleteYourself(); |
|
288 |
} |
|
289 |
||
290 |
/*! |
|
291 |
Creates a copy of the connection \a other in this object. Note |
|
292 |
that the connection this object referenced before the copy, is not |
|
293 |
spontaneously disconnected. |
|
294 |
||
295 |
\sa disconnectFromBus() |
|
296 |
*/ |
|
297 |
QDBusConnection &QDBusConnection::operator=(const QDBusConnection &other) |
|
298 |
{ |
|
299 |
if (other.d) |
|
300 |
other.d->ref.ref(); |
|
301 |
if (d && !d->ref.deref()) |
|
302 |
d->deleteYourself(); |
|
303 |
d = other.d; |
|
304 |
return *this; |
|
305 |
} |
|
306 |
||
307 |
/*! |
|
308 |
Opens a connection of type \a type to one of the known busses and |
|
309 |
associate with it the connection name \a name. Returns a |
|
310 |
QDBusConnection object associated with that connection. |
|
311 |
*/ |
|
312 |
QDBusConnection QDBusConnection::connectToBus(BusType type, const QString &name) |
|
313 |
{ |
|
314 |
// Q_ASSERT_X(QCoreApplication::instance(), "QDBusConnection::addConnection", |
|
315 |
// "Cannot create connection without a Q[Core]Application instance"); |
|
316 |
if (!qdbus_loadLibDBus()) { |
|
317 |
QDBusConnectionPrivate *d = 0; |
|
318 |
return QDBusConnection(d); |
|
319 |
} |
|
320 |
||
321 |
QMutexLocker locker(&_q_manager()->mutex); |
|
322 |
||
323 |
QDBusConnectionPrivate *d = _q_manager()->connection(name); |
|
324 |
if (d || name.isEmpty()) |
|
325 |
return QDBusConnection(d); |
|
326 |
||
327 |
d = new QDBusConnectionPrivate; |
|
328 |
DBusConnection *c = 0; |
|
329 |
QDBusErrorInternal error; |
|
330 |
switch (type) { |
|
331 |
case SystemBus: |
|
332 |
c = q_dbus_bus_get_private(DBUS_BUS_SYSTEM, error); |
|
333 |
break; |
|
334 |
case SessionBus: |
|
335 |
c = q_dbus_bus_get_private(DBUS_BUS_SESSION, error); |
|
336 |
break; |
|
337 |
case ActivationBus: |
|
338 |
c = q_dbus_bus_get_private(DBUS_BUS_STARTER, error); |
|
339 |
break; |
|
340 |
} |
|
341 |
d->setConnection(c, error); //setConnection does the error handling for us |
|
342 |
||
343 |
_q_manager()->setConnection(name, d); |
|
344 |
||
345 |
QDBusConnection retval(d); |
|
346 |
||
347 |
// create the bus service |
|
348 |
// will lock in QDBusConnectionPrivate::connectRelay() |
|
349 |
d->setBusService(retval); |
|
350 |
||
351 |
return retval; |
|
352 |
} |
|
353 |
||
354 |
/*! |
|
355 |
Opens a peer-to-peer connection on address \a address and associate with it the |
|
356 |
connection name \a name. Returns a QDBusConnection object associated with that connection. |
|
357 |
*/ |
|
358 |
QDBusConnection QDBusConnection::connectToBus(const QString &address, |
|
359 |
const QString &name) |
|
360 |
{ |
|
361 |
// Q_ASSERT_X(QCoreApplication::instance(), "QDBusConnection::addConnection", |
|
362 |
// "Cannot create connection without a Q[Core]Application instance"); |
|
363 |
if (!qdbus_loadLibDBus()){ |
|
364 |
QDBusConnectionPrivate *d = 0; |
|
365 |
return QDBusConnection(d); |
|
366 |
} |
|
367 |
||
368 |
QMutexLocker locker(&_q_manager()->mutex); |
|
369 |
||
370 |
QDBusConnectionPrivate *d = _q_manager()->connection(name); |
|
371 |
if (d || name.isEmpty()) |
|
372 |
return QDBusConnection(d); |
|
373 |
||
374 |
d = new QDBusConnectionPrivate; |
|
375 |
// setConnection does the error handling for us |
|
376 |
QDBusErrorInternal error; |
|
377 |
DBusConnection *c = q_dbus_connection_open_private(address.toUtf8().constData(), error); |
|
378 |
if (c) { |
|
379 |
if (!q_dbus_bus_register(c, error)) { |
|
380 |
q_dbus_connection_unref(c); |
|
381 |
c = 0; |
|
382 |
} |
|
383 |
} |
|
384 |
d->setConnection(c, error); |
|
385 |
_q_manager()->setConnection(name, d); |
|
386 |
||
387 |
QDBusConnection retval(d); |
|
388 |
||
389 |
// create the bus service |
|
390 |
// will lock in QDBusConnectionPrivate::connectRelay() |
|
391 |
d->setBusService(retval); |
|
392 |
||
393 |
return retval; |
|
394 |
} |
|
395 |
||
396 |
/*! |
|
397 |
Closes the connection of name \a name. |
|
398 |
||
399 |
Note that if there are still QDBusConnection objects associated |
|
400 |
with the same connection, the connection will not be closed until |
|
401 |
all references are dropped. However, no further references can be |
|
402 |
created using the QDBusConnection constructor. |
|
403 |
*/ |
|
404 |
void QDBusConnection::disconnectFromBus(const QString &name) |
|
405 |
{ |
|
406 |
if (_q_manager()) { |
|
407 |
QMutexLocker locker(&_q_manager()->mutex); |
|
408 |
_q_manager()->removeConnection(name); |
|
409 |
} |
|
410 |
} |
|
411 |
||
412 |
/*! |
|
413 |
Sends the \a message over this connection, without waiting for a |
|
414 |
reply. This is suitable for errors, signals, and return values as |
|
415 |
well as calls whose return values are not necessary. |
|
416 |
||
417 |
Returns true if the message was queued successfully, false otherwise. |
|
418 |
*/ |
|
419 |
bool QDBusConnection::send(const QDBusMessage &message) const |
|
420 |
{ |
|
421 |
if (!d || !d->connection) { |
|
422 |
QDBusError err = QDBusError(QDBusError::Disconnected, |
|
423 |
QLatin1String("Not connected to D-BUS server")); |
|
424 |
if (d) |
|
425 |
d->lastError = err; |
|
426 |
return false; |
|
427 |
} |
|
428 |
return d->send(message) != 0; |
|
429 |
} |
|
430 |
||
431 |
/*! |
|
432 |
Sends the \a message over this connection and returns immediately. |
|
433 |
When the reply is received, the method \a returnMethod is called in |
|
434 |
the \a receiver object. If an error occurs, the method \a errorMethod |
|
435 |
will be called instead. |
|
436 |
||
437 |
If no reply is received within \a timeout milliseconds, an automatic |
|
438 |
error will be delivered indicating the expiration of the call. |
|
439 |
The default \a timeout is -1, which will be replaced with an |
|
440 |
implementation-defined value that is suitable for inter-process |
|
441 |
communications (generally, 25 seconds). |
|
442 |
||
443 |
This function is suitable for method calls only. It is guaranteed |
|
444 |
that the slot will be called exactly once with the reply, as long |
|
445 |
as the parameter types match and no error occurs. |
|
446 |
||
447 |
Returns true if the message was sent, or false if the message could |
|
448 |
not be sent. |
|
449 |
*/ |
|
450 |
bool QDBusConnection::callWithCallback(const QDBusMessage &message, QObject *receiver, |
|
451 |
const char *returnMethod, const char *errorMethod, |
|
452 |
int timeout) const |
|
453 |
{ |
|
454 |
if (!d || !d->connection) { |
|
455 |
QDBusError err = QDBusError(QDBusError::Disconnected, |
|
456 |
QLatin1String("Not connected to D-BUS server")); |
|
457 |
if (d) |
|
458 |
d->lastError = err; |
|
459 |
return false; |
|
460 |
} |
|
461 |
return d->sendWithReplyAsync(message, receiver, returnMethod, errorMethod, timeout) != 0; |
|
462 |
} |
|
463 |
||
464 |
/*! |
|
465 |
\overload |
|
466 |
\deprecated |
|
467 |
Sends the \a message over this connection and returns immediately. |
|
468 |
When the reply is received, the method \a returnMethod is called in |
|
469 |
the \a receiver object. |
|
470 |
||
471 |
This function is suitable for method calls only. It is guaranteed |
|
472 |
that the slot will be called exactly once with the reply, as long |
|
473 |
as the parameter types match and no error occurs. |
|
474 |
||
475 |
This function is dangerous because it cannot report errors, including |
|
476 |
the expiration of the timeout. |
|
477 |
||
478 |
Returns true if the message was sent, or false if the message could |
|
479 |
not be sent. |
|
480 |
*/ |
|
481 |
bool QDBusConnection::callWithCallback(const QDBusMessage &message, QObject *receiver, |
|
482 |
const char *returnMethod, int timeout) const |
|
483 |
{ |
|
484 |
return callWithCallback(message, receiver, returnMethod, 0, timeout); |
|
485 |
} |
|
486 |
||
487 |
/*! |
|
488 |
Sends the \a message over this connection and blocks, waiting for |
|
489 |
a reply, for at most \a timeout milliseconds. This function is |
|
490 |
suitable for method calls only. It returns the reply message as |
|
491 |
its return value, which will be either of type |
|
492 |
QDBusMessage::ReplyMessage or QDBusMessage::ErrorMessage. |
|
493 |
||
7
3f74d0d4af4c
qt:70947f0f93d948bc89b3b43d00da758a51f1ef84
Eckhart Koeppen <eckhart.koppen@nokia.com>
parents:
4
diff
changeset
|
494 |
If no reply is received within \a timeout milliseconds, an automatic |
3f74d0d4af4c
qt:70947f0f93d948bc89b3b43d00da758a51f1ef84
Eckhart Koeppen <eckhart.koppen@nokia.com>
parents:
4
diff
changeset
|
495 |
error will be delivered indicating the expiration of the call. |
3f74d0d4af4c
qt:70947f0f93d948bc89b3b43d00da758a51f1ef84
Eckhart Koeppen <eckhart.koppen@nokia.com>
parents:
4
diff
changeset
|
496 |
The default \a timeout is -1, which will be replaced with an |
3f74d0d4af4c
qt:70947f0f93d948bc89b3b43d00da758a51f1ef84
Eckhart Koeppen <eckhart.koppen@nokia.com>
parents:
4
diff
changeset
|
497 |
implementation-defined value that is suitable for inter-process |
3f74d0d4af4c
qt:70947f0f93d948bc89b3b43d00da758a51f1ef84
Eckhart Koeppen <eckhart.koppen@nokia.com>
parents:
4
diff
changeset
|
498 |
communications (generally, 25 seconds). |
3f74d0d4af4c
qt:70947f0f93d948bc89b3b43d00da758a51f1ef84
Eckhart Koeppen <eckhart.koppen@nokia.com>
parents:
4
diff
changeset
|
499 |
|
0 | 500 |
See the QDBusInterface::call() function for a more friendly way |
501 |
of placing calls. |
|
502 |
||
503 |
\warning If \a mode is QDBus::BlockWithGui, this function will |
|
504 |
reenter the Qt event loop in order to wait for the |
|
505 |
reply. During the wait, it may deliver signals and other |
|
506 |
method calls to your application. Therefore, it must be |
|
507 |
prepared to handle a reentrancy whenever a call is |
|
508 |
placed with call(). |
|
509 |
*/ |
|
510 |
QDBusMessage QDBusConnection::call(const QDBusMessage &message, QDBus::CallMode mode, int timeout) const |
|
511 |
{ |
|
512 |
if (!d || !d->connection) { |
|
513 |
QDBusError err = QDBusError(QDBusError::Disconnected, |
|
514 |
QLatin1String("Not connected to D-Bus server")); |
|
515 |
if (d) |
|
516 |
d->lastError = err; |
|
517 |
||
518 |
return QDBusMessage::createError(err); |
|
519 |
} |
|
520 |
||
521 |
if (mode != QDBus::NoBlock) |
|
522 |
return d->sendWithReply(message, mode, timeout); |
|
523 |
||
524 |
d->send(message); |
|
525 |
QDBusMessage retval; |
|
526 |
retval << QVariant(); // add one argument (to avoid .at(0) problems) |
|
527 |
return retval; |
|
528 |
} |
|
529 |
||
530 |
/*! |
|
531 |
\since 4.5 |
|
532 |
Sends the \a message over this connection and returns |
|
533 |
immediately. This function is suitable for method calls only. It |
|
534 |
returns an object of type QDBusPendingCall which can be used to |
|
7
3f74d0d4af4c
qt:70947f0f93d948bc89b3b43d00da758a51f1ef84
Eckhart Koeppen <eckhart.koppen@nokia.com>
parents:
4
diff
changeset
|
535 |
track the status of the reply. |
3f74d0d4af4c
qt:70947f0f93d948bc89b3b43d00da758a51f1ef84
Eckhart Koeppen <eckhart.koppen@nokia.com>
parents:
4
diff
changeset
|
536 |
|
3f74d0d4af4c
qt:70947f0f93d948bc89b3b43d00da758a51f1ef84
Eckhart Koeppen <eckhart.koppen@nokia.com>
parents:
4
diff
changeset
|
537 |
If no reply is received within \a timeout milliseconds, an automatic |
3f74d0d4af4c
qt:70947f0f93d948bc89b3b43d00da758a51f1ef84
Eckhart Koeppen <eckhart.koppen@nokia.com>
parents:
4
diff
changeset
|
538 |
error will be delivered indicating the expiration of the call. The |
3f74d0d4af4c
qt:70947f0f93d948bc89b3b43d00da758a51f1ef84
Eckhart Koeppen <eckhart.koppen@nokia.com>
parents:
4
diff
changeset
|
539 |
default \a timeout is -1, which will be replaced with an |
3f74d0d4af4c
qt:70947f0f93d948bc89b3b43d00da758a51f1ef84
Eckhart Koeppen <eckhart.koppen@nokia.com>
parents:
4
diff
changeset
|
540 |
implementation-defined value that is suitable for inter-process |
3f74d0d4af4c
qt:70947f0f93d948bc89b3b43d00da758a51f1ef84
Eckhart Koeppen <eckhart.koppen@nokia.com>
parents:
4
diff
changeset
|
541 |
communications (generally, 25 seconds). This timeout is also the |
3f74d0d4af4c
qt:70947f0f93d948bc89b3b43d00da758a51f1ef84
Eckhart Koeppen <eckhart.koppen@nokia.com>
parents:
4
diff
changeset
|
542 |
upper limit for waiting in QDBusPendingCall::waitForFinished(). |
0 | 543 |
|
544 |
See the QDBusInterface::asyncCall() function for a more friendly way |
|
545 |
of placing calls. |
|
546 |
*/ |
|
547 |
QDBusPendingCall QDBusConnection::asyncCall(const QDBusMessage &message, int timeout) const |
|
548 |
{ |
|
549 |
if (!d || !d->connection) { |
|
550 |
return QDBusPendingCall(0); // null pointer -> disconnected |
|
551 |
} |
|
552 |
||
553 |
QDBusPendingCallPrivate *priv = d->sendWithReplyAsync(message, timeout); |
|
554 |
return QDBusPendingCall(priv); |
|
555 |
} |
|
556 |
||
557 |
/*! |
|
558 |
Connects the signal specified by the \a service, \a path, \a interface and \a name parameters to |
|
559 |
the slot \a slot in object \a receiver. The arguments \a service and \a path can be empty, |
|
560 |
denoting a connection to any signal of the (\a interface, \a name) pair, from any remote |
|
561 |
application. |
|
562 |
||
563 |
Returns true if the connection was successful. |
|
564 |
||
565 |
\warning The signal will only be delivered to the slot if the parameters match. This verification |
|
566 |
can be done only when the signal is received, not at connection time. |
|
567 |
*/ |
|
568 |
bool QDBusConnection::connect(const QString &service, const QString &path, const QString& interface, |
|
569 |
const QString &name, QObject *receiver, const char *slot) |
|
570 |
{ |
|
3
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
571 |
return connect(service, path, interface, name, QStringList(), QString(), receiver, slot); |
0 | 572 |
} |
573 |
||
574 |
/*! |
|
575 |
\overload |
|
576 |
||
577 |
Connects the signal to the slot \a slot in object \a |
|
3
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
578 |
receiver. Unlike the previous connect() overload, this function |
0 | 579 |
allows one to specify the parameter signature to be connected |
580 |
using the \a signature variable. The function will then verify |
|
581 |
that this signature can be delivered to the slot specified by \a |
|
582 |
slot and return false otherwise. |
|
583 |
||
3
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
584 |
Returns true if the connection was successful. |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
585 |
|
0 | 586 |
\note This function verifies that the signal signature matches the |
587 |
slot's parameters, but it does not verify that the actual |
|
588 |
signal exists with the given signature in the remote |
|
589 |
service. |
|
590 |
*/ |
|
591 |
bool QDBusConnection::connect(const QString &service, const QString &path, const QString& interface, |
|
592 |
const QString &name, const QString &signature, |
|
593 |
QObject *receiver, const char *slot) |
|
594 |
{ |
|
3
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
595 |
return connect(service, path, interface, name, QStringList(), signature, receiver, slot); |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
596 |
} |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
597 |
|
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
598 |
/*! |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
599 |
\overload |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
600 |
\since 4.6 |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
601 |
|
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
602 |
Connects the signal to the slot \a slot in object \a |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
603 |
receiver. Unlike the previous connect() overload, this function |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
604 |
allows one to specify the parameter signature to be connected |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
605 |
using the \a signature variable. The function will then verify |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
606 |
that this signature can be delivered to the slot specified by \a |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
607 |
slot and return false otherwise. |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
608 |
|
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
609 |
The \a argumentMatch parameter lists the string parameters to be matched, |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
610 |
in sequential order. Note that, to match an empty string, you need to |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
611 |
pass a QString that is empty but not null (i.e., QString("")). A null |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
612 |
QString skips matching at that position. |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
613 |
|
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
614 |
Returns true if the connection was successful. |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
615 |
|
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
616 |
\note This function verifies that the signal signature matches the |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
617 |
slot's parameters, but it does not verify that the actual |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
618 |
signal exists with the given signature in the remote |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
619 |
service. |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
620 |
*/ |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
621 |
bool QDBusConnection::connect(const QString &service, const QString &path, const QString& interface, |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
622 |
const QString &name, const QStringList &argumentMatch, const QString &signature, |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
623 |
QObject *receiver, const char *slot) |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
624 |
{ |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
625 |
|
0 | 626 |
if (!receiver || !slot || !d || !d->connection) |
627 |
return false; |
|
628 |
if (!interface.isEmpty() && !QDBusUtil::isValidInterfaceName(interface)) |
|
629 |
return false; |
|
630 |
if (interface.isEmpty() && name.isEmpty()) |
|
631 |
return false; |
|
632 |
||
633 |
QDBusWriteLocker locker(ConnectAction, d); |
|
4
3b1da2848fc7
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
3
diff
changeset
|
634 |
return d->connectSignal(service, path, interface, name, argumentMatch, signature, receiver, slot); |
3
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
635 |
} |
0 | 636 |
|
3
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
637 |
/*! |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
638 |
Disconnects the signal specified by the \a service, \a path, \a interface |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
639 |
and \a name parameters from the slot \a slot in object \a receiver. The |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
640 |
arguments must be the same as passed to the connect() function. |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
641 |
|
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
642 |
Returns true if the disconnection was successful. |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
643 |
*/ |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
644 |
bool QDBusConnection::disconnect(const QString &service, const QString &path, const QString &interface, |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
645 |
const QString &name, QObject *receiver, const char *slot) |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
646 |
{ |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
647 |
return disconnect(service, path, interface, name, QStringList(), QString(), receiver, slot); |
0 | 648 |
} |
649 |
||
650 |
/*! |
|
651 |
\overload |
|
652 |
||
3
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
653 |
Disconnects the signal specified by the \a service, \a path, \a |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
654 |
interface, \a name, and \a signature parameters from the slot \a slot in |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
655 |
object \a receiver. The arguments must be the same as passed to the |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
656 |
connect() function. |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
657 |
|
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
658 |
Returns true if the disconnection was successful. |
0 | 659 |
*/ |
660 |
bool QDBusConnection::disconnect(const QString &service, const QString &path, const QString& interface, |
|
661 |
const QString &name, const QString &signature, |
|
662 |
QObject *receiver, const char *slot) |
|
663 |
{ |
|
3
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
664 |
return disconnect(service, path, interface, name, QStringList(), signature, receiver, slot); |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
665 |
} |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
666 |
|
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
667 |
/*! |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
668 |
\overload |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
669 |
\since 4.6 |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
670 |
|
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
671 |
Disconnects the signal specified by the \a service, \a path, \a |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
672 |
interface, \a name, \a argumentMatch, and \a signature parameters from |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
673 |
the slot \a slot in object \a receiver. The arguments must be the same as |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
674 |
passed to the connect() function. |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
675 |
|
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
676 |
Returns true if the disconnection was successful. |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
677 |
*/ |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
678 |
bool QDBusConnection::disconnect(const QString &service, const QString &path, const QString& interface, |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
679 |
const QString &name, const QStringList &argumentMatch, const QString &signature, |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
680 |
QObject *receiver, const char *slot) |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
681 |
{ |
0 | 682 |
if (!receiver || !slot || !d || !d->connection) |
683 |
return false; |
|
684 |
if (!interface.isEmpty() && !QDBusUtil::isValidInterfaceName(interface)) |
|
685 |
return false; |
|
686 |
if (interface.isEmpty() && name.isEmpty()) |
|
687 |
return false; |
|
688 |
||
689 |
QDBusWriteLocker locker(DisconnectAction, d); |
|
3
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
690 |
return d->disconnectSignal(service, path, interface, name, argumentMatch, signature, receiver, slot); |
0 | 691 |
} |
692 |
||
693 |
/*! |
|
694 |
Registers the object \a object at path \a path and returns true if |
|
695 |
the registration was successful. The \a options parameter |
|
696 |
specifies how much of the object \a object will be exposed through |
|
697 |
D-Bus. |
|
698 |
||
699 |
This function does not replace existing objects: if there is already an object registered at |
|
700 |
path \a path, this function will return false. Use unregisterObject() to unregister it first. |
|
701 |
||
702 |
You cannot register an object as a child object of an object that |
|
703 |
was registered with QDBusConnection::ExportChildObjects. |
|
704 |
*/ |
|
705 |
bool QDBusConnection::registerObject(const QString &path, QObject *object, RegisterOptions options) |
|
706 |
{ |
|
707 |
Q_ASSERT_X(QDBusUtil::isValidObjectPath(path), "QDBusConnection::registerObject", |
|
708 |
"Invalid object path given"); |
|
709 |
if (!d || !d->connection || !object || !options || !QDBusUtil::isValidObjectPath(path)) |
|
710 |
return false; |
|
711 |
||
712 |
QStringList pathComponents = path.split(QLatin1Char('/')); |
|
713 |
if (pathComponents.last().isEmpty()) |
|
714 |
pathComponents.removeLast(); |
|
715 |
QDBusWriteLocker locker(RegisterObjectAction, d); |
|
716 |
||
717 |
// lower-bound search for where this object should enter in the tree |
|
718 |
QDBusConnectionPrivate::ObjectTreeNode *node = &d->rootNode; |
|
719 |
int i = 1; |
|
720 |
while (node) { |
|
721 |
if (pathComponents.count() == i) { |
|
722 |
// this node exists |
|
723 |
// consider it free if there's no object here and the user is not trying to |
|
724 |
// replace the object sub-tree |
|
725 |
if ((options & ExportChildObjects && !node->children.isEmpty()) || node->obj) |
|
726 |
return false; |
|
727 |
||
728 |
// we can add the object here |
|
729 |
node->obj = object; |
|
730 |
node->flags = options; |
|
731 |
||
732 |
d->registerObject(node); |
|
733 |
//qDebug("REGISTERED FOR %s", path.toLocal8Bit().constData()); |
|
734 |
return true; |
|
735 |
} |
|
736 |
||
737 |
// find the position where we'd insert the node |
|
738 |
QDBusConnectionPrivate::ObjectTreeNode::DataList::Iterator it = |
|
739 |
qLowerBound(node->children.begin(), node->children.end(), pathComponents.at(i)); |
|
740 |
if (it != node->children.end() && it->name == pathComponents.at(i)) { |
|
741 |
// match: this node exists |
|
742 |
node = it; |
|
743 |
||
744 |
// are we allowed to go deeper? |
|
745 |
if (node->flags & ExportChildObjects) { |
|
746 |
// we're not |
|
747 |
qDebug("Cannot register object at %s because %s exports its own child objects", |
|
748 |
qPrintable(path), qPrintable(pathComponents.at(i))); |
|
749 |
return false; |
|
750 |
} |
|
751 |
} else { |
|
752 |
// add entry |
|
753 |
node = node->children.insert(it, pathComponents.at(i)); |
|
754 |
} |
|
755 |
||
756 |
// iterate |
|
757 |
++i; |
|
758 |
} |
|
759 |
||
760 |
Q_ASSERT_X(false, "QDBusConnection::registerObject", "The impossible happened"); |
|
761 |
return false; |
|
762 |
} |
|
763 |
||
764 |
/*! |
|
765 |
Unregisters an object that was registered with the registerObject() at the object path given by |
|
766 |
\a path and, if \a mode is QDBusConnection::UnregisterTree, all of its sub-objects too. |
|
767 |
||
768 |
Note that you cannot unregister objects that were not registered with registerObject(). |
|
769 |
*/ |
|
770 |
void QDBusConnection::unregisterObject(const QString &path, UnregisterMode mode) |
|
771 |
{ |
|
772 |
if (!d || !d->connection || !QDBusUtil::isValidObjectPath(path)) |
|
773 |
return; |
|
774 |
||
775 |
QStringList pathComponents = path.split(QLatin1Char('/')); |
|
776 |
QDBusWriteLocker locker(UnregisterObjectAction, d); |
|
777 |
QDBusConnectionPrivate::ObjectTreeNode *node = &d->rootNode; |
|
778 |
int i = 1; |
|
779 |
||
780 |
// find the object |
|
781 |
while (node) { |
|
782 |
if (pathComponents.count() == i) { |
|
783 |
// found it |
|
784 |
node->obj = 0; |
|
785 |
node->flags = 0; |
|
786 |
||
787 |
if (mode == UnregisterTree) { |
|
788 |
// clear the sub-tree as well |
|
789 |
node->children.clear(); // can't disconnect the objects because we really don't know if they can |
|
790 |
// be found somewhere else in the path too |
|
791 |
} |
|
792 |
||
793 |
return; |
|
794 |
} |
|
795 |
||
796 |
QDBusConnectionPrivate::ObjectTreeNode::DataList::Iterator it = |
|
797 |
qLowerBound(node->children.begin(), node->children.end(), pathComponents.at(i)); |
|
798 |
if (it == node->children.end() || it->name != pathComponents.at(i)) |
|
799 |
break; // node not found |
|
800 |
||
801 |
node = it; |
|
802 |
++i; |
|
803 |
} |
|
804 |
} |
|
805 |
||
806 |
/*! |
|
807 |
Return the object that was registered with the registerObject() at the object path given by |
|
808 |
\a path. |
|
809 |
*/ |
|
810 |
QObject *QDBusConnection::objectRegisteredAt(const QString &path) const |
|
811 |
{ |
|
812 |
Q_ASSERT_X(QDBusUtil::isValidObjectPath(path), "QDBusConnection::registeredObject", |
|
813 |
"Invalid object path given"); |
|
814 |
if (!d || !d->connection || !QDBusUtil::isValidObjectPath(path)) |
|
815 |
return false; |
|
816 |
||
817 |
QStringList pathComponents = path.split(QLatin1Char('/')); |
|
818 |
if (pathComponents.last().isEmpty()) |
|
819 |
pathComponents.removeLast(); |
|
820 |
||
821 |
// lower-bound search for where this object should enter in the tree |
|
822 |
QDBusReadLocker lock(ObjectRegisteredAtAction, d); |
|
823 |
const QDBusConnectionPrivate::ObjectTreeNode *node = &d->rootNode; |
|
824 |
||
825 |
int i = 1; |
|
826 |
while (node) { |
|
827 |
if (pathComponents.count() == i) |
|
828 |
return node->obj; |
|
829 |
||
830 |
QDBusConnectionPrivate::ObjectTreeNode::DataList::ConstIterator it = |
|
831 |
qLowerBound(node->children.constBegin(), node->children.constEnd(), pathComponents.at(i)); |
|
832 |
if (it == node->children.constEnd() || it->name != pathComponents.at(i)) |
|
833 |
break; // node not found |
|
834 |
||
835 |
node = it; |
|
836 |
++i; |
|
837 |
} |
|
838 |
return 0; |
|
839 |
} |
|
840 |
||
841 |
/*! |
|
842 |
Returns a QDBusConnectionInterface object that represents the |
|
843 |
D-Bus server interface on this connection. |
|
844 |
*/ |
|
845 |
QDBusConnectionInterface *QDBusConnection::interface() const |
|
846 |
{ |
|
847 |
if (!d) |
|
848 |
return 0; |
|
849 |
return d->busService; |
|
850 |
} |
|
851 |
||
852 |
/*! |
|
853 |
Returns true if this QDBusConnection object is connected. |
|
854 |
||
855 |
If it isn't connected, calling connectToBus() on the same |
|
856 |
connection name will not make be connected. You need to call the |
|
857 |
QDBusConnection constructor again. |
|
858 |
*/ |
|
859 |
bool QDBusConnection::isConnected() const |
|
860 |
{ |
|
861 |
return d && d->connection && q_dbus_connection_get_is_connected(d->connection); |
|
862 |
} |
|
863 |
||
864 |
/*! |
|
865 |
Returns the last error that happened in this connection. |
|
866 |
||
867 |
This function is provided for low-level code. If you're using |
|
868 |
QDBusInterface::call(), error codes are reported by its return |
|
869 |
value. |
|
870 |
||
871 |
\sa QDBusInterface, QDBusMessage |
|
872 |
*/ |
|
873 |
QDBusError QDBusConnection::lastError() const |
|
874 |
{ |
|
875 |
return d ? d->lastError : QDBusError(); |
|
876 |
} |
|
877 |
||
878 |
/*! |
|
879 |
Returns the unique connection name for this connection, if this QDBusConnection object is |
|
880 |
connected, or an empty QString otherwise. |
|
881 |
||
882 |
A Unique Connection Name is a string in the form ":x.xxx" (where x |
|
883 |
are decimal digits) that is assigned by the D-Bus server daemon |
|
884 |
upon connection. It uniquely identifies this client in the bus. |
|
885 |
||
886 |
This function returns an empty QString for peer-to-peer connections. |
|
887 |
*/ |
|
888 |
QString QDBusConnection::baseService() const |
|
889 |
{ |
|
890 |
return d ? d->baseService : QString(); |
|
891 |
} |
|
892 |
||
893 |
/*! |
|
894 |
\since 4.5 |
|
895 |
||
896 |
Returns the connection name for this connection, as given as the |
|
897 |
name parameter to connectToBus(). |
|
898 |
||
899 |
The connection name can be used to uniquely identify actual |
|
900 |
underlying connections to buses. Copies made from a single |
|
901 |
connection will always implicitly share the underlying connection, |
|
902 |
and hence will have the same connection name. |
|
903 |
||
904 |
Inversely, two connections having different connection names will |
|
905 |
always either be connected to different buses, or have a different |
|
906 |
unique name (as returned by baseService()) on that bus. |
|
907 |
||
908 |
\sa connectToBus(), disconnectFromBus() |
|
909 |
*/ |
|
910 |
QString QDBusConnection::name() const |
|
911 |
{ |
|
912 |
return d ? d->name : QString(); |
|
913 |
} |
|
914 |
||
915 |
/*! |
|
916 |
Attempts to register the \a serviceName on the D-Bus server and |
|
917 |
returns true if the registration succeded. The registration will |
|
918 |
fail if the name is already registered by another application. |
|
919 |
||
920 |
\sa unregisterService(), QDBusConnectionInterface::registerService() |
|
921 |
*/ |
|
922 |
bool QDBusConnection::registerService(const QString &serviceName) |
|
923 |
{ |
|
924 |
if (interface() && interface()->registerService(serviceName)) { |
|
925 |
if (d) d->registerService(serviceName); |
|
926 |
return true; |
|
927 |
} |
|
928 |
return false; |
|
929 |
} |
|
930 |
||
931 |
/*! |
|
932 |
Unregisters the service \a serviceName that was previously |
|
933 |
registered with registerService() and returns true if it |
|
934 |
succeeded. |
|
935 |
||
936 |
\sa registerService(), QDBusConnectionInterface::unregisterService() |
|
937 |
*/ |
|
938 |
bool QDBusConnection::unregisterService(const QString &serviceName) |
|
939 |
{ |
|
940 |
if (interface()->unregisterService(serviceName)) { |
|
941 |
if (d) d->unregisterService(serviceName); |
|
942 |
return true; |
|
943 |
} |
|
944 |
return false; |
|
945 |
} |
|
946 |
||
947 |
static const char _q_sessionBusName[] = "qt_default_session_bus"; |
|
948 |
static const char _q_systemBusName[] = "qt_default_system_bus"; |
|
949 |
||
950 |
class QDBusDefaultConnection: public QDBusConnection |
|
951 |
{ |
|
952 |
const char *ownName; |
|
953 |
public: |
|
954 |
inline QDBusDefaultConnection(BusType type, const char *name) |
|
955 |
: QDBusConnection(connectToBus(type, QString::fromLatin1(name))), ownName(name) |
|
956 |
{ } |
|
957 |
||
958 |
inline ~QDBusDefaultConnection() |
|
959 |
{ disconnectFromBus(QString::fromLatin1(ownName)); } |
|
960 |
}; |
|
961 |
||
962 |
Q_GLOBAL_STATIC_WITH_ARGS(QDBusDefaultConnection, _q_sessionBus, |
|
963 |
(QDBusConnection::SessionBus, _q_sessionBusName)) |
|
964 |
Q_GLOBAL_STATIC_WITH_ARGS(QDBusDefaultConnection, _q_systemBus, |
|
965 |
(QDBusConnection::SystemBus, _q_systemBusName)) |
|
966 |
||
967 |
QDBusConnection QDBusConnection::sessionBus() |
|
968 |
{ |
|
969 |
return *_q_sessionBus(); |
|
970 |
} |
|
971 |
||
972 |
QDBusConnection QDBusConnection::systemBus() |
|
973 |
{ |
|
974 |
return *_q_systemBus(); |
|
975 |
} |
|
976 |
||
977 |
/*! |
|
978 |
\nonreentrant |
|
979 |
||
980 |
Returns the connection that sent the signal, if called in a slot activated |
|
981 |
by QDBus; otherwise it returns 0. |
|
982 |
||
983 |
\note Please avoid this function. This function is not thread-safe, so if |
|
984 |
there's any other thread delivering a D-Bus call, this function may return |
|
985 |
the wrong connection. In new code, please use QDBusContext::connection() |
|
986 |
(see that class for a description on how to use it). |
|
987 |
*/ |
|
988 |
QDBusConnection QDBusConnection::sender() |
|
989 |
{ |
|
990 |
return QDBusConnection(_q_manager()->sender()); |
|
991 |
} |
|
992 |
||
993 |
/*! |
|
994 |
\internal |
|
995 |
*/ |
|
996 |
void QDBusConnectionPrivate::setSender(const QDBusConnectionPrivate *s) |
|
997 |
{ |
|
998 |
_q_manager()->setSender(s); |
|
999 |
} |
|
1000 |
||
1001 |
/*! |
|
1002 |
\internal |
|
1003 |
*/ |
|
1004 |
void QDBusConnectionPrivate::setConnection(const QString &name, QDBusConnectionPrivate *c) |
|
1005 |
{ |
|
1006 |
_q_manager()->setConnection(name, c); |
|
1007 |
} |
|
1008 |
||
1009 |
/*! |
|
1010 |
\internal |
|
1011 |
*/ |
|
1012 |
void QDBusConnectionPrivate::setBusService(const QDBusConnection &connection) |
|
1013 |
{ |
|
1014 |
busService = new QDBusConnectionInterface(connection, this); |
|
1015 |
ref.deref(); // busService has increased the refcounting to us |
|
1016 |
// avoid cyclic refcounting |
|
1017 |
||
1018 |
QObject::connect(this, SIGNAL(callWithCallbackFailed(QDBusError,QDBusMessage)), |
|
1019 |
busService, SIGNAL(callWithCallbackFailed(QDBusError,QDBusMessage)), |
|
1020 |
Qt::QueuedConnection); |
|
1021 |
} |
|
1022 |
||
1023 |
/*! |
|
1024 |
\namespace QDBus |
|
1025 |
\inmodule QtDBus |
|
1026 |
||
1027 |
\brief The QDBus namespace contains miscellaneous identifiers used |
|
1028 |
throughout the QtDBus library. |
|
1029 |
*/ |
|
1030 |
||
1031 |
/*! |
|
1032 |
\enum QDBus::CallMode |
|
1033 |
||
1034 |
This enum describes the various ways of placing a function call. The valid modes are: |
|
1035 |
||
1036 |
\value NoBlock Place the call but don't wait for the reply (the reply's contents |
|
1037 |
will be discarded). |
|
1038 |
\value Block Don't use an event loop to wait for a reply, but instead block on |
|
1039 |
network operations while waiting. This means the |
|
1040 |
user-interface may not be updated until the function returns. |
|
1041 |
\value BlockWithGui Use the Qt event loop to wait for a reply. This means that the |
|
1042 |
user-interface will stay responsive (processing input events), |
|
1043 |
but it also means other events may happen, like signal delivery |
|
1044 |
and other D-Bus method calls. |
|
1045 |
\value AutoDetect Automatically detect if the called function has a reply. |
|
1046 |
||
1047 |
When using BlockWithGui, applications must be prepared for reentrancy in any function. |
|
1048 |
*/ |
|
1049 |
||
1050 |
QT_END_NAMESPACE |