summaryrefslogtreecommitdiffstats
path: root/qt/qdbusconnection.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'qt/qdbusconnection.cpp')
-rw-r--r--qt/qdbusconnection.cpp328
1 files changed, 328 insertions, 0 deletions
diff --git a/qt/qdbusconnection.cpp b/qt/qdbusconnection.cpp
new file mode 100644
index 00000000..6493ef2a
--- /dev/null
+++ b/qt/qdbusconnection.cpp
@@ -0,0 +1,328 @@
+/* qdbusconnection.cpp
+ *
+ * Copyright (C) 2005 Harald Fernengel <harry@kdevelop.org>
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <QtCore/qdebug.h>
+#include <QtCore/qcoreapplication.h>
+
+#include "qdbusconnection.h"
+#include "qdbuserror.h"
+#include "qdbusmessage.h"
+#include "qdbusconnection_p.h"
+
+QT_STATIC_CONST_IMPL char *QDBusConnection::default_connection_name = "qt_dbus_default_connection";
+
+class QDBusConnectionManager
+{
+public:
+ QDBusConnectionManager(): default_connection(0) {}
+ ~QDBusConnectionManager();
+ void bindToApplication();
+ QDBusConnectionPrivate *connection(const QString &name) const;
+ void removeConnection(const QString &name);
+ void setConnection(const QString &name, QDBusConnectionPrivate *c);
+
+private:
+ QDBusConnectionPrivate *default_connection;
+ QHash<QString, QDBusConnectionPrivate *> connectionHash;
+};
+
+Q_GLOBAL_STATIC(QDBusConnectionManager, manager);
+
+QDBusConnectionPrivate *QDBusConnectionManager::connection(const QString &name) const
+{
+ return name == QLatin1String(QDBusConnection::default_connection_name) ?
+ default_connection : connectionHash.value(name, 0);
+}
+
+void QDBusConnectionManager::removeConnection(const QString &name)
+{
+ QDBusConnectionPrivate *d = 0;
+ if (name == QLatin1String(QDBusConnection::default_connection_name)) {
+ d = default_connection;
+ default_connection = 0;
+ } else {
+ d = connectionHash.take(name);
+ }
+ if (!d->ref.deref())
+ delete d;
+}
+
+QDBusConnectionManager::~QDBusConnectionManager()
+{
+ if (default_connection) {
+ delete default_connection;
+ default_connection = 0;
+ }
+ for (QHash<QString, QDBusConnectionPrivate *>::const_iterator it = connectionHash.constBegin();
+ it != connectionHash.constEnd(); ++it) {
+ delete it.value();
+ }
+ connectionHash.clear();
+}
+
+void QDBusConnectionManager::bindToApplication()
+{
+ if (default_connection) {
+ default_connection->bindToApplication();
+ }
+ for (QHash<QString, QDBusConnectionPrivate *>::const_iterator it = connectionHash.constBegin();
+ it != connectionHash.constEnd(); ++it) {
+ (*it)->bindToApplication();
+ }
+}
+
+void qDBusBindToApplication()
+{
+ manager()->bindToApplication();
+}
+
+void QDBusConnectionManager::setConnection(const QString &name, QDBusConnectionPrivate *c)
+{
+ if (name == QLatin1String(QDBusConnection::default_connection_name))
+ default_connection = c;
+ else
+ connectionHash[name] = c;
+}
+
+
+QDBusConnection::QDBusConnection(const QString &name)
+{
+ d = manager()->connection(name);
+ if (d)
+ d->ref.ref();
+}
+
+QDBusConnection::QDBusConnection(const QDBusConnection &other)
+{
+ d = other.d;
+ if (d)
+ d->ref.ref();
+}
+
+QDBusConnection::~QDBusConnection()
+{
+ if (d && !d->ref.deref())
+ delete d;
+}
+
+QDBusConnection &QDBusConnection::operator=(const QDBusConnection &other)
+{
+ if (other.d)
+ other.d->ref.ref();
+ QDBusConnectionPrivate *old = static_cast<QDBusConnectionPrivate *>(
+ q_atomic_set_ptr(&d, other.d));
+ if (old && !old->ref.deref())
+ delete old;
+
+ return *this;
+}
+
+QDBusConnection QDBusConnection::addConnection(BusType type, const QString &name)
+{
+// Q_ASSERT_X(QCoreApplication::instance(), "QDBusConnection::addConnection",
+// "Cannot create connection without a Q[Core]Application instance");
+
+ QDBusConnectionPrivate *d = manager()->connection(name);
+ if (d)
+ return QDBusConnection(name);
+
+ d = new QDBusConnectionPrivate;
+ DBusConnection *c = 0;
+ switch (type) {
+ case SystemBus:
+ c = dbus_bus_get(DBUS_BUS_SYSTEM, &d->error);
+ break;
+ case SessionBus:
+ c = dbus_bus_get(DBUS_BUS_SESSION, &d->error);
+ break;
+ case ActivationBus:
+ c = dbus_bus_get(DBUS_BUS_STARTER, &d->error);
+ break;
+ }
+ d->setConnection(c); //setConnection does the error handling for us
+
+ manager()->setConnection(name, d);
+
+ return QDBusConnection(name);
+}
+
+QDBusConnection QDBusConnection::addConnection(const QString &address,
+ const QString &name)
+{
+// Q_ASSERT_X(QCoreApplication::instance(), "QDBusConnection::addConnection",
+// "Cannot create connection without a Q[Core]Application instance");
+
+ QDBusConnectionPrivate *d = manager()->connection(name);
+ if (d)
+ return QDBusConnection(name);
+
+ d = new QDBusConnectionPrivate;
+ // setConnection does the error handling for us
+ d->setConnection(dbus_connection_open(address.toUtf8().constData(), &d->error));
+
+ manager()->setConnection(name, d);
+
+ return QDBusConnection(name);
+}
+
+void QDBusConnection::closeConnection(const QString &name)
+{
+ manager()->removeConnection(name);
+}
+
+void QDBusConnectionPrivate::timerEvent(QTimerEvent *e)
+{
+ DBusTimeout *timeout = timeouts.value(e->timerId(), 0);
+ dbus_timeout_handle(timeout);
+}
+
+bool QDBusConnection::send(const QDBusMessage &message) const
+{
+ if (!d || !d->connection)
+ return false;
+
+ DBusMessage *msg = message.toDBusMessage();
+ if (!msg)
+ return false;
+
+ bool isOk = dbus_connection_send(d->connection, msg, 0);
+ dbus_message_unref(msg);
+ return isOk;
+}
+
+int QDBusConnection::sendWithReplyAsync(const QDBusMessage &message, QObject *receiver,
+ const char *method) const
+{
+ if (!d || !d->connection)
+ return 0;
+
+ return d->sendWithReplyAsync(message, receiver, method);
+}
+
+QDBusMessage QDBusConnection::sendWithReply(const QDBusMessage &message) const
+{
+ if (!d || !d->connection)
+ return QDBusMessage::fromDBusMessage(0);
+
+ DBusMessage *msg = message.toDBusMessage();
+ if (!msg)
+ return QDBusMessage::fromDBusMessage(0);
+ DBusMessage *reply = dbus_connection_send_with_reply_and_block(d->connection, msg,
+ -1, &d->error);
+ d->handleError();
+ dbus_message_unref(msg);
+
+ return QDBusMessage::fromDBusMessage(reply);
+}
+
+bool QDBusConnection::connect(const QString &path, const QString &interface,
+ const QString &name, QObject *receiver, const char *slot)
+{
+ if (!receiver || !slot || !d || !d->connection)
+ return false;
+
+ QDBusConnectionPrivate::SignalHook hook;
+
+ hook.interface = interface;
+ hook.name = name;
+ hook.obj = QPointer<QObject>(receiver);
+ if (!hook.setSlot(slot + 1))
+ return false;
+
+ d->signalHooks.insertMulti(path, hook);
+ d->connect(receiver, SIGNAL(destroyed(QObject*)), SLOT(objectDestroyed(QObject*)));
+
+ return true;
+}
+
+bool QDBusConnection::registerObject(const QString &path, const QString &interface,
+ QObject *object)
+{
+ if (!d || !d->connection || !object || path.isEmpty() || interface.isEmpty())
+ return false;
+
+ QDBusConnectionPrivate::ObjectHook hook;
+ hook.interface = interface;
+ hook.obj = object;
+
+ QDBusConnectionPrivate::ObjectHookHash::iterator it = d->objectHooks.find(path);
+ while (it != d->objectHooks.end() && it.key() == path) {
+ if (it.value().interface == interface) {
+ d->objectHooks.erase(it);
+ break;
+ }
+ ++it;
+ }
+
+ d->objectHooks.insert(path, hook);
+
+ d->connect(object, SIGNAL(destroyed(QObject*)), SLOT(objectDestroyed(QObject*)));
+ qDebug("REGISTERED FOR %s", path.toLocal8Bit().constData());
+
+ return true; // todo - check for slots etc.
+}
+
+void QDBusConnection::unregisterObject(const QString &path)
+{
+ if (!d || !d->connection)
+ return;
+
+ // TODO - check interfaces
+ d->objectHooks.remove(path);
+}
+
+bool QDBusConnection::isConnected( ) const
+{
+ return d && d->connection && dbus_connection_get_is_connected(d->connection);
+}
+
+QDBusError QDBusConnection::lastError() const
+{
+ return d ? d->lastError : QDBusError();
+}
+
+QString QDBusConnection::baseService() const
+{
+ return d && d->connection ?
+ QString::fromUtf8(dbus_bus_get_unique_name(d->connection))
+ : QString();
+}
+
+bool QDBusConnection::requestName(const QString &name, NameRequestMode mode)
+{
+ static const int DBusModes[] = { 0, DBUS_NAME_FLAG_PROHIBIT_REPLACEMENT,
+ DBUS_NAME_FLAG_REPLACE_EXISTING };
+ Q_ASSERT(mode == 0 || mode == DBUS_NAME_FLAG_PROHIBIT_REPLACEMENT ||
+ mode == DBUS_NAME_FLAG_REPLACE_EXISTING);
+
+ DBusError error;
+ dbus_error_init (&error);
+ dbus_bus_request_name(d->connection, name.toUtf8(), DBusModes[mode], &error);
+ if (dbus_error_is_set (&error)) {
+ qDebug("Error %s\n", error.message);
+ dbus_error_free (&error);
+ return false;
+ }
+ return true;
+}
+
+#include "qdbusconnection.moc"