24#include "async-dbus-proxy.h"
26#include <QDBusConnection>
27#include <QDBusObjectPath>
28#include <QDBusPendingCallWatcher>
34#include "connection-manager.h"
35#include "dbusinterface.h"
37#include "libsignoncommon.h"
38#include "signond/signoncommon.h"
47 Connection(
const char *name, QObject *receiver,
const char *slot):
62PendingCall::PendingCall(
const QString &method,
63 const QList<QVariant> &args,
69 m_interfaceWasDestroyed(false)
73PendingCall::~PendingCall()
77bool PendingCall::cancel()
87void PendingCall::doCall(QDBusAbstractInterface *interface)
89 QDBusPendingCall call =
90 interface->asyncCallWithArgumentList(m_method, m_args);
91 m_watcher =
new QDBusPendingCallWatcher(call,
this);
92 QObject::connect(m_watcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
93 this, SLOT(onFinished(QDBusPendingCallWatcher*)));
95 m_interfaceWasDestroyed =
false;
96 QObject::connect(interface, SIGNAL(destroyed()),
97 this, SLOT(onInterfaceDestroyed()));
100void PendingCall::fail(
const QDBusError &err)
106void PendingCall::onFinished(QDBusPendingCallWatcher *watcher)
111 if (m_interfaceWasDestroyed && watcher->isError()) {
112 QDBusError::ErrorType type = watcher->error().type();
113 if (type == QDBusError::Disconnected ||
114 type == QDBusError::UnknownObject) {
115 TRACE() <<
"emitting retry signal";
116 Q_EMIT requeueRequested();
121 QPointer<PendingCall> thisguard(
this);
122 QPointer<QDBusPendingCallWatcher> watcherguard(watcher);
123 if (watcher->isError()) {
124 Q_EMIT error(watcher->error());
126 Q_EMIT success(watcher);
129 Q_EMIT finished(watcherguard ? watcher : 0);
133void PendingCall::onInterfaceDestroyed()
141 m_interfaceWasDestroyed =
true;
144AsyncDBusProxy::AsyncDBusProxy(
const QString &service,
145 const char *interface,
146 QObject *clientObject):
147 m_serviceName(service),
148 m_interfaceName(interface),
150 m_clientObject(clientObject),
156AsyncDBusProxy::~AsyncDBusProxy()
158 qDeleteAll(m_connectionsQueue);
159 m_connectionsQueue.clear();
164void AsyncDBusProxy::setStatus(Status status)
168 if (status == Ready) {
170 Q_FOREACH(Connection *connection, m_connectionsQueue) {
171 m_interface->connect(connection->m_name,
172 connection->m_receiver,
176 Q_FOREACH(PendingCall *call, m_operationsQueue) {
177 call->doCall(m_interface);
179 m_operationsQueue.clear();
180 }
else if (status == Invalid) {
182 Q_FOREACH(PendingCall *call, m_operationsQueue) {
183 call->fail(m_lastError);
185 m_operationsQueue.clear();
189void AsyncDBusProxy::update()
191 if (m_interface != NULL) {
196 if (m_connection == NULL || m_path.isEmpty()) {
197 setStatus(Incomplete);
201 if (!m_connection->isConnected()) {
202 setError(m_connection->lastError());
214void AsyncDBusProxy::setConnection(
const QDBusConnection &connection)
217 m_connection =
new QDBusConnection(connection);
221void AsyncDBusProxy::setDisconnected()
231void AsyncDBusProxy::setObjectPath(
const QDBusObjectPath &objectPath)
233 Q_ASSERT(m_path.isEmpty() || objectPath.path().isEmpty());
234 m_path = objectPath.path();
238void AsyncDBusProxy::setError(
const QDBusError &error)
245PendingCall *AsyncDBusProxy::queueCall(
const QString &method,
246 const QList<QVariant> &args,
247 const char *replySlot,
248 const char *errorSlot)
250 return queueCall(method, args, m_clientObject, replySlot, errorSlot);
253PendingCall *AsyncDBusProxy::queueCall(
const QString &method,
254 const QList<QVariant> &args,
256 const char *replySlot,
257 const char *errorSlot)
259 PendingCall *call =
new PendingCall(method, args,
this);
260 QObject::connect(call, SIGNAL(finished(QDBusPendingCallWatcher*)),
261 this, SLOT(onCallFinished(QDBusPendingCallWatcher*)));
262 QObject::connect(call, SIGNAL(requeueRequested()),
263 this, SLOT(onRequeueRequested()));
266 QObject::connect(call, SIGNAL(error(
const QDBusError&)),
267 receiver, errorSlot);
269 QObject::connect(call, SIGNAL(success(QDBusPendingCallWatcher*)),
270 receiver, replySlot);
272 }
else if (replySlot) {
273 QObject::connect(call, SIGNAL(finished(QDBusPendingCallWatcher*)),
274 receiver, replySlot);
277 if (m_status == Ready) {
278 call->doCall(m_interface);
279 }
else if (m_status == Incomplete) {
282 QMetaObject::invokeMethod(call,
"fail",
283 Qt::QueuedConnection,
284 Q_ARG(QDBusError, m_lastError));
289bool AsyncDBusProxy::connect(
const char *name,
295 Connection *connection =
new Connection(name, receiver, slot);
296 m_connectionsQueue.enqueue(connection);
298 if (m_status == Ready) {
299 return m_interface->connect(name, receiver, slot);
304void AsyncDBusProxy::enqueue(PendingCall *call)
306 m_operationsQueue.enqueue(call);
308 Q_EMIT connectionNeeded();
310 if (m_path.isEmpty()) {
311 Q_EMIT objectPathNeeded();
315void AsyncDBusProxy::onCallFinished(QDBusPendingCallWatcher *watcher)
318 PendingCall *call = qobject_cast<PendingCall*>(sender());
319 m_operationsQueue.removeOne(call);
323void AsyncDBusProxy::onRequeueRequested()
325 PendingCall *call = qobject_cast<PendingCall*>(sender());
329SignondAsyncDBusProxy::SignondAsyncDBusProxy(
const char *interface,
330 QObject *clientObject):
331 AsyncDBusProxy(SIGNOND_SERVICE, interface, clientObject)
336SignondAsyncDBusProxy::~SignondAsyncDBusProxy()
340void SignondAsyncDBusProxy::setupConnection()
343 QObject::connect(connManager, SIGNAL(connected(
const QDBusConnection&)),
344 this, SLOT(setConnection(
const QDBusConnection&)));
345 QObject::connect(connManager, SIGNAL(disconnected()),
346 this, SLOT(setDisconnected()));
347 QObject::connect(
this, SIGNAL(connectionNeeded()),
348 connManager, SLOT(connect()));
349 if (connManager->hasConnection()) {
350 setConnection(connManager->connection());