3 * Copyright (C) 2005 Harald Fernengel <harry@kdevelop.org>
5 * Licensed under the Academic Free License version 2.1
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include <QtCore/qdebug.h>
24 #include <QtCore/qcoreapplication.h>
26 #include "qdbusconnection.h"
27 #include "qdbusconnection_p.h"
29 QT_STATIC_CONST_IMPL char *QDBusConnection::default_connection_name = "qt_dbus_default_connection";
31 class QDBusConnectionManager
34 QDBusConnectionManager(): default_connection(0) {}
35 ~QDBusConnectionManager();
36 void bindToApplication();
37 QDBusConnectionPrivate *connection(const QString &name) const;
38 void removeConnection(const QString &name);
39 void setConnection(const QString &name, QDBusConnectionPrivate *c);
42 QDBusConnectionPrivate *default_connection;
43 QHash<QString, QDBusConnectionPrivate *> connectionHash;
46 Q_GLOBAL_STATIC(QDBusConnectionManager, manager);
48 QDBusConnectionPrivate *QDBusConnectionManager::connection(const QString &name) const
50 return name == QLatin1String(QDBusConnection::default_connection_name) ?
51 default_connection : connectionHash.value(name, 0);
54 void QDBusConnectionManager::removeConnection(const QString &name)
56 QDBusConnectionPrivate *d = 0;
57 if (name == QLatin1String(QDBusConnection::default_connection_name)) {
58 d = default_connection;
59 default_connection = 0;
61 d = connectionHash.take(name);
67 QDBusConnectionManager::~QDBusConnectionManager()
69 if (default_connection) {
70 delete default_connection;
71 default_connection = 0;
73 for (QHash<QString, QDBusConnectionPrivate *>::const_iterator it = connectionHash.constBegin();
74 it != connectionHash.constEnd(); ++it) {
77 connectionHash.clear();
80 void QDBusConnectionManager::bindToApplication()
82 if (default_connection) {
83 default_connection->bindToApplication();
85 for (QHash<QString, QDBusConnectionPrivate *>::const_iterator it = connectionHash.constBegin();
86 it != connectionHash.constEnd(); ++it) {
87 (*it)->bindToApplication();
91 void qDBusBindToApplication()
93 manager()->bindToApplication();
96 void QDBusConnectionManager::setConnection(const QString &name, QDBusConnectionPrivate *c)
98 if (name == QLatin1String(QDBusConnection::default_connection_name))
99 default_connection = c;
101 connectionHash[name] = c;
105 QDBusConnection::QDBusConnection(const QString &name)
107 d = manager()->connection(name);
112 QDBusConnection::QDBusConnection(const QDBusConnection &other)
119 QDBusConnection::~QDBusConnection()
121 if (d && !d->ref.deref())
125 QDBusConnection &QDBusConnection::operator=(const QDBusConnection &other)
129 QDBusConnectionPrivate *old = static_cast<QDBusConnectionPrivate *>(
130 q_atomic_set_ptr(&d, other.d));
131 if (old && !old->ref.deref())
137 QDBusConnection QDBusConnection::addConnection(BusType type, const QString &name)
139 // Q_ASSERT_X(QCoreApplication::instance(), "QDBusConnection::addConnection",
140 // "Cannot create connection without a Q[Core]Application instance");
142 QDBusConnectionPrivate *d = manager()->connection(name);
144 return QDBusConnection(name);
146 d = new QDBusConnectionPrivate;
147 DBusConnection *c = 0;
150 c = dbus_bus_get(DBUS_BUS_SYSTEM, &d->error);
153 c = dbus_bus_get(DBUS_BUS_SESSION, &d->error);
156 c = dbus_bus_get(DBUS_BUS_STARTER, &d->error);
159 d->setConnection(c); //setConnection does the error handling for us
161 manager()->setConnection(name, d);
163 return QDBusConnection(name);
166 QDBusConnection QDBusConnection::addConnection(const QString &address,
169 // Q_ASSERT_X(QCoreApplication::instance(), "QDBusConnection::addConnection",
170 // "Cannot create connection without a Q[Core]Application instance");
172 QDBusConnectionPrivate *d = manager()->connection(name);
174 return QDBusConnection(name);
176 d = new QDBusConnectionPrivate;
177 // setConnection does the error handling for us
178 d->setConnection(dbus_connection_open(address.toUtf8().constData(), &d->error));
180 manager()->setConnection(name, d);
182 return QDBusConnection(name);
185 void QDBusConnection::closeConnection(const QString &name)
187 manager()->removeConnection(name);
190 void QDBusConnectionPrivate::timerEvent(QTimerEvent *e)
192 DBusTimeout *timeout = timeouts.value(e->timerId(), 0);
193 dbus_timeout_handle(timeout);
196 bool QDBusConnection::send(const QDBusMessage &message) const
198 if (!d || !d->connection)
201 DBusMessage *msg = message.toDBusMessage();
205 bool isOk = dbus_connection_send(d->connection, msg, 0);
206 dbus_message_unref(msg);
210 int QDBusConnection::sendWithReplyAsync(const QDBusMessage &message, QObject *receiver,
211 const char *method) const
213 if (!d || !d->connection)
216 return d->sendWithReplyAsync(message, receiver, method);
219 QDBusMessage QDBusConnection::sendWithReply(const QDBusMessage &message) const
221 if (!d || !d->connection)
222 return QDBusMessage::fromDBusMessage(0);
224 DBusMessage *msg = message.toDBusMessage();
226 return QDBusMessage::fromDBusMessage(0);
227 DBusMessage *reply = dbus_connection_send_with_reply_and_block(d->connection, msg,
230 dbus_message_unref(msg);
232 return QDBusMessage::fromDBusMessage(reply);
235 bool QDBusConnection::connect(const QString &path, const QString &interface,
236 const QString &name, QObject *receiver, const char *slot)
238 if (!receiver || !slot || !d || !d->connection)
241 QDBusConnectionPrivate::SignalHook hook;
243 hook.interface = interface;
245 hook.obj = QPointer<QObject>(receiver);
246 if (!hook.setSlot(slot + 1))
249 d->signalHooks.insertMulti(path, hook);
250 d->connect(receiver, SIGNAL(destroyed(QObject*)), SLOT(objectDestroyed(QObject*)));
255 bool QDBusConnection::registerObject(const QString &path, const QString &interface,
258 if (!d || !d->connection || !object || path.isEmpty() || interface.isEmpty())
261 QDBusConnectionPrivate::ObjectHook hook;
262 hook.interface = interface;
265 QDBusConnectionPrivate::ObjectHookHash::iterator it = d->objectHooks.find(path);
266 while (it != d->objectHooks.end() && it.key() == path) {
267 if (it.value().interface == interface) {
268 d->objectHooks.erase(it);
274 d->objectHooks.insert(path, hook);
276 d->connect(object, SIGNAL(destroyed(QObject*)), SLOT(objectDestroyed(QObject*)));
277 qDebug("REGISTERED FOR %s", path.toLocal8Bit().constData());
279 return true; // todo - check for slots etc.
282 void QDBusConnection::unregisterObject(const QString &path)
284 if (!d || !d->connection)
287 // TODO - check interfaces
288 d->objectHooks.remove(path);
291 bool QDBusConnection::isConnected( ) const
293 return d && d->connection && dbus_connection_get_is_connected(d->connection);
296 QDBusError QDBusConnection::lastError() const
298 return d ? d->lastError : QDBusError();
301 QString QDBusConnection::baseService() const
303 return d && d->connection ?
304 QString::fromUtf8(dbus_bus_get_unique_name(d->connection))
308 bool QDBusConnection::requestName(const QString &name, NameRequestMode mode)
310 //FIXME: DBUS_NAME_FLAGS_* are bit fields not enumeration
311 static const int DBusModes[] = { 0, DBUS_NAME_FLAG_ALLOW_REPLACEMENT,
312 DBUS_NAME_FLAG_REPLACE_EXISTING };
313 Q_ASSERT(mode == 0 || mode == AllowReplace ||
314 mode == ReplaceExisting );
317 dbus_error_init (&error);
318 dbus_bus_request_name(d->connection, name.toUtf8(), DBusModes[mode], &error);
319 if (dbus_error_is_set (&error)) {
320 qDebug("Error %s\n", error.message);
321 dbus_error_free (&error);
327 #include "qdbusconnection.moc"