summaryrefslogtreecommitdiff
path: root/qt/qdbusconnection.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'qt/qdbusconnection.cpp')
-rw-r--r--qt/qdbusconnection.cpp547
1 files changed, 471 insertions, 76 deletions
diff --git a/qt/qdbusconnection.cpp b/qt/qdbusconnection.cpp
index 8ac13e4..422b087 100644
--- a/qt/qdbusconnection.cpp
+++ b/qt/qdbusconnection.cpp
@@ -33,12 +33,10 @@
#include "qdbusobject_p.h"
#include "qdbusutil.h"
-QT_STATIC_CONST_IMPL char *QDBusConnection::default_connection_name = "qt_dbus_default_connection";
-
class QDBusConnectionManager
{
public:
- QDBusConnectionManager(): default_connection(0) {}
+ QDBusConnectionManager() {}
~QDBusConnectionManager();
void bindToApplication();
QDBusConnectionPrivate *connection(const QString &name) const;
@@ -46,7 +44,7 @@ public:
void setConnection(const QString &name, QDBusConnectionPrivate *c);
private:
- QDBusConnectionPrivate *default_connection;
+ mutable QMutex mutex;
QHash<QString, QDBusConnectionPrivate *> connectionHash;
};
@@ -54,29 +52,22 @@ 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);
+ QMutexLocker locker(&mutex);
+ return connectionHash.value(name, 0);
}
void QDBusConnectionManager::removeConnection(const QString &name)
{
+ QMutexLocker locker(&mutex);
+
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())
+ d = connectionHash.take(name);
+ if (d && !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();
@@ -86,9 +77,7 @@ QDBusConnectionManager::~QDBusConnectionManager()
void QDBusConnectionManager::bindToApplication()
{
- if (default_connection) {
- default_connection->bindToApplication();
- }
+ QMutexLocker locker(&mutex);
for (QHash<QString, QDBusConnectionPrivate *>::const_iterator it = connectionHash.constBegin();
it != connectionHash.constEnd(); ++it) {
(*it)->bindToApplication();
@@ -102,13 +91,117 @@ void qDBusBindToApplication()
void QDBusConnectionManager::setConnection(const QString &name, QDBusConnectionPrivate *c)
{
- if (name == QLatin1String(QDBusConnection::default_connection_name))
- default_connection = c;
- else
- connectionHash[name] = c;
+ connectionHash[name] = c;
+ c->name = name;
}
+/*!
+ \fn QDBusConnection QDBus::sessionBus()
+
+ Returns a QDBusConnection object opened with the session bus. The object reference returned
+ by this function is valid until the QCoreApplication's destructor is run, when the
+ connection will be closed and the object, deleted.
+*/
+/*!
+ \fn QDBusConnection QDBus::systemBus()
+
+ Returns a QDBusConnection object opened with the system bus. The object reference returned
+ by this function is valid until the QCoreApplication's destructor is run, when the
+ connection will be closed and the object, deleted.
+*/
+
+/*!
+ \class QDBusConnection
+ \brief A connection to the D-Bus bus daemon.
+
+ This class is the initial point in a D-Bus session. Using it, you can get access to remote
+ objects, interfaces; connect remote signals to your object's slots; register objects, etc.
+
+ D-Bus connections are created using the QDBusConnection::addConnection function, which opens a
+ connection to the server daemon and does the initial handshaking, associating that connection
+ with a name. Further attempts to connect using the same name will return the same
+ connection.
+
+ The connection is then torn down using the QDBusConnection::closeConnection function.
+
+ As a convenience for the two most common connection types, the QDBus::sessionBus and
+ QDBus::systemBus functions return open connections to the session server daemon and the system
+ server daemon, respectively. Those connections are opened when first used and are closed when
+ the QCoreApplication destructor is run.
+
+ D-Bus also supports peer-to-peer connections, without the need for a bus server daemon. Using
+ this facility, two applications can talk to each other and exchange messages. This can be
+ achieved by passing an address to QDBusConnection::addConnection(const QString &, const QString
+ &) function, which was opened by another D-Bus application using QDBusServer.
+*/
+
+/*!
+ \enum QDBusConnection::BusType
+ Specifies the type of the bus connection. The valid bus types are:
+
+ \value SessionBus the session bus, associated with the running desktop session
+ \value SystemBus the system bus, used to communicate with system-wide processes
+ \value ActivationBus the activation bus, whose purpose I have no idea...
+
+ On the Session Bus, one can find other applications by the same user that are sharing the same
+ desktop session (hence the name). On the System Bus, however, processes shared for the whole
+ system are usually found.
+
+ \todo Find out what the ActivationBus is for
+*/
+
+/*!
+ \enum QDBusConnection::NameRequestMode
+ Specifies the flags for when requesting a name in the bus.
+
+ \bug Change the enum into flags and update with the new flags from the spec.
+*/
+
+/*!
+ \enum QDBusConnection::RegisterOption
+ Specifies the options for registering objects with the connection. The possible values are:
+
+ \value ExportAdaptors export the contents of adaptors found in this object
+
+ \value ExportSlots export this object's scriptable slots
+ \value ExportSignals export this object's scriptable signals
+ \value ExportProperties export this object's scriptable properties
+ \value ExportContents shorthand form for ExportSlots | ExportSignals |
+ ExportProperties
+
+ \value ExportNonScriptableSlots export all of this object's slots, including
+ non-scriptable ones
+ \value ExportNonScriptableSignals export all of this object's signals, including
+ non-scriptable ones
+ \value ExportNonScriptableProperties export all of this object's properties, including
+ non-scriptable ones
+ \value ExportNonScriptableContents export all of this object's slots, signals and
+ properties, including non-scriptable ones
+
+ \value ExportChildObjects export this object's child objects
+ \note It is currently not possible to export signals from objects. If you pass the flag
+ ExportSignals or ExportNonScriptableSignals, the registerObject() function will print a warning.
+
+ \sa QDBusConnection::registerObject, QDBusAbstractAdaptor, \ref UsingAdaptors
+*/
+
+/*!
+ \enum QDBusConnection::UnregisterMode
+ The mode for unregistering an object path:
+
+ \value UnregisterNode unregister this node only: do not unregister child objects
+ \value UnregisterTree unregister this node and all its sub-tree
+
+ Note, however, if this object was registered with the ExportChildObjects option, UnregisterNode
+ will unregister the child objects too.
+*/
+
+/*!
+ Creates a QDBusConnection object attached to the connection with name \p name.
+
+ This does not open the connection. You have to call QDBusConnection::addConnection to open it.
+*/
QDBusConnection::QDBusConnection(const QString &name)
{
d = manager()->connection(name);
@@ -116,6 +209,9 @@ QDBusConnection::QDBusConnection(const QString &name)
d->ref.ref();
}
+/*!
+ Creates a copy of the \p other connection.
+*/
QDBusConnection::QDBusConnection(const QDBusConnection &other)
{
d = other.d;
@@ -123,12 +219,21 @@ QDBusConnection::QDBusConnection(const QDBusConnection &other)
d->ref.ref();
}
+/*!
+ Disposes of this object. This does not close the connection: you have to call
+ QDBusConnection::closeConnection to do that.
+*/
QDBusConnection::~QDBusConnection()
{
if (d && !d->ref.deref())
delete d;
}
+/*!
+ Creates a copy of the connection \p other in this object. The connection this object referenced
+ before the copy is not spontaneously disconnected. See QDBusConnection::closeConnection for more
+ information.
+*/
QDBusConnection &QDBusConnection::operator=(const QDBusConnection &other)
{
if (other.d)
@@ -141,13 +246,17 @@ QDBusConnection &QDBusConnection::operator=(const QDBusConnection &other)
return *this;
}
+/*!
+ Opens a connection of type \p type to one of the known busses and associate with it the
+ connection name \p name. Returns a QDBusConnection object associated with that connection.
+*/
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)
+ if (d || name.isEmpty())
return QDBusConnection(name);
d = new QDBusConnectionPrivate;
@@ -170,6 +279,10 @@ QDBusConnection QDBusConnection::addConnection(BusType type, const QString &name
return QDBusConnection(name);
}
+/*!
+ Opens a peer-to-peer connection on address \p address and associate with it the
+ connection name \p name. Returns a QDBusConnection object associated with that connection.
+*/
QDBusConnection QDBusConnection::addConnection(const QString &address,
const QString &name)
{
@@ -177,7 +290,7 @@ QDBusConnection QDBusConnection::addConnection(const QString &address,
// "Cannot create connection without a Q[Core]Application instance");
QDBusConnectionPrivate *d = manager()->connection(name);
- if (d)
+ if (d || name.isEmpty())
return QDBusConnection(name);
d = new QDBusConnectionPrivate;
@@ -189,6 +302,13 @@ QDBusConnection QDBusConnection::addConnection(const QString &address,
return QDBusConnection(name);
}
+/*!
+ Closes the connection of name \p name.
+
+ Note that if there are still QDBusConnection objects associated with the same connection, the
+ connection will not be closed until all references are dropped. However, no further references
+ can be created using the QDBusConnection::QDBusConnection constructor.
+*/
void QDBusConnection::closeConnection(const QString &name)
{
manager()->removeConnection(name);
@@ -200,6 +320,12 @@ void QDBusConnectionPrivate::timerEvent(QTimerEvent *e)
dbus_timeout_handle(timeout);
}
+/*!
+ Sends the message over this connection, without waiting for a reply. This is suitable for errors,
+ signals, and return values as well as calls whose return values are not necessary.
+
+ \returns true if the message was queued successfully, false otherwise
+*/
bool QDBusConnection::send(const QDBusMessage &message) const
{
if (!d || !d->connection)
@@ -207,6 +333,16 @@ bool QDBusConnection::send(const QDBusMessage &message) const
return d->send(message);
}
+/*!
+ Sends the message over this connection and returns immediately after queueing it. When the reply
+ is received, the slot \p method is called in the object \p receiver. This function is suitable
+ for method calls only.
+
+ This function guarantees that the slot will be called exactly once with the reply, as long as
+ the parameter types match. If they don't, the reply cannot be delivered.
+
+ \returns true if the message was queued successfully, false otherwise.
+*/
int QDBusConnection::sendWithReplyAsync(const QDBusMessage &message, QObject *receiver,
const char *method) const
{
@@ -216,15 +352,27 @@ int QDBusConnection::sendWithReplyAsync(const QDBusMessage &message, QObject *re
return d->sendWithReplyAsync(message, receiver, method);
}
+/*!
+ Sends the message over this connection and blocks, waiting for a reply. This function is
+ suitable for method calls only. It returns the reply message as its return value, which will be
+ either of type QDBusMessage::ReplyMessage or QDBusMessage::ErrorMessage.
+
+ See the QDBusInterface::call function for a more friendly way of placing calls.
+
+ \warning This function reenters the Qt event loop in order to wait for the reply, excluding user
+ input. During the wait, it may deliver signals and other method calls to your
+ application. Therefore, it must be prepared to handle a reentrancy whenever a call is
+ placed with sendWithReply().
+*/
QDBusMessage QDBusConnection::sendWithReply(const QDBusMessage &message) const
{
if (!d || !d->connection)
- return QDBusMessage::fromDBusMessage(0);
+ return QDBusMessage::fromDBusMessage(0, *this);
if (!QCoreApplication::instance()) {
DBusMessage *msg = message.toDBusMessage();
if (!msg)
- return QDBusMessage::fromDBusMessage(0);
+ return QDBusMessage::fromDBusMessage(0, *this);
DBusMessage *reply = dbus_connection_send_with_reply_and_block(d->connection, msg,
-1, &d->error);
@@ -234,108 +382,229 @@ QDBusMessage QDBusConnection::sendWithReply(const QDBusMessage &message) const
if (lastError().isValid())
return QDBusMessage::fromError(lastError());
- return QDBusMessage::fromDBusMessage(reply);
+ return QDBusMessage::fromDBusMessage(reply, *this);
} else {
QDBusReplyWaiter waiter;
if (d->sendWithReplyAsync(message, &waiter, SLOT(reply(const QDBusMessage&))) > 0) {
// enter the event loop and wait for a reply
waiter.exec(QEventLoop::ExcludeUserInputEvents | QEventLoop::WaitForMoreEvents);
-
+
d->lastError = waiter.replyMsg; // set or clear error
return waiter.replyMsg;
}
- return QDBusMessage::fromDBusMessage(0);
+ return QDBusMessage::fromDBusMessage(0, *this);
}
}
+/*!
+ Connects the signal to the slot \p slot in object \p receiver.
+
+ \param service the service that will emit the signal, or QString() to wait for the signal
+ coming from any remote application
+ \param path the path that will emit the signal, or QString() to wait for the signal
+ coming from any object path (usually associated with an empty \p service)
+ \param interface the name of the interface to for this signal
+ \param name the name of the signal
+ \param receiver the object to connect to
+ \param slot the slot that will be invoked when the signal is emitted
+ \returns true if the connection was successful
+
+ \note The signal will only be delivered to the slot if the parameters match. This verification
+ can be done only when the signal is received, not at connection time.
+
+ \bug does not allow an empty service
+*/
bool QDBusConnection::connect(const QString &service, const QString &path, const QString& interface,
const QString &name, QObject *receiver, const char *slot)
{
return connect(service, path, interface, name, QString(), receiver, slot);
}
+/*!
+ \overload
+ Connects the signal to the slot \p slot in object \p receiver. Unlike the other
+ QDBusConnection::connect overload, this function allows one to specify the parameter signature
+ to be connected. The function will then verify that this signature can be delivered to the slot
+ specified by \p slot and return false otherwise.
+
+ \bug does not validate signature vs slot yet
+*/
bool QDBusConnection::connect(const QString &service, const QString &path, const QString& interface,
const QString &name, const QString &signature,
QObject *receiver, const char *slot)
{
- if (!receiver || !slot || !d || !d->connection)
+ if (!receiver || !slot || !d || !d->connection || !QDBusUtil::isValidInterfaceName(interface))
return false;
- QString source = getNameOwner(service);
- if (source.isEmpty())
- return false;
+ QString source;
+ if (!service.isEmpty()) {
+ source = getNameOwner(service);
+ if (source.isEmpty())
+ return false;
+ }
source += path;
// check the slot
QDBusConnectionPrivate::SignalHook hook;
if ((hook.midx = QDBusConnectionPrivate::findSlot(receiver, slot + 1, hook.params)) == -1)
return false;
-
+
hook.interface = interface;
hook.name = name;
hook.signature = signature;
- hook.obj = QPointer<QObject>(receiver);
+ hook.obj = receiver;
+
+ // avoid duplicating:
+ QDBusConnectionPrivate::SignalHookHash::ConstIterator it = d->signalHooks.find(source);
+ for ( ; it != d->signalHooks.end() && it.key() == source; ++it) {
+ const QDBusConnectionPrivate::SignalHook &entry = it.value();
+ if (entry.interface == hook.interface &&
+ entry.name == hook.name &&
+ entry.signature == hook.signature &&
+ entry.obj == hook.obj &&
+ entry.midx == hook.midx) {
+ // no need to compare the parameters if it's the same slot
+ return true; // already there
+ }
+ }
- d->signalHooks.insertMulti(source, hook);
- d->connect(receiver, SIGNAL(destroyed(QObject*)), SLOT(objectDestroyed(QObject*)));
+ d->connectSignal(source, hook);
return true;
}
-bool QDBusConnection::registerObject(const QString &path, QObject *object, RegisterOptions options)
-{
- return registerObject(path, QString(), object, options);
-}
+/*!
+ Registers the object \p object at path \p path and returns true if the registration was
+ successful.
+
+ This function does not replace existing objects: if there is already an object registered at
+ path \p path, this function will return false. Use unregisterObject() to unregister it first.
-bool QDBusConnection::registerObject(const QString &path, const QString &interface,
- QObject *object, RegisterOptions options)
+ You cannot register an object as a child object of an object that was registered with
+ QDBusConnection::ExportChildObjects.
+*/
+bool QDBusConnection::registerObject(const QString &path, QObject *object, RegisterOptions options)
{
if (!d || !d->connection || !object || !options || !QDBusUtil::isValidObjectPath(path))
return false;
- QString iface = interface;
- if (options & ExportForAnyInterface)
- iface.clear();
-
- QDBusConnectionPrivate::ObjectDataHash& hook = d->objectHooks[path];
-
- // if we're replacing and matching any interface, then we're replacing every interface
- // this catches ExportAdaptors | Reexport too
- if (( options & ( ExportForAnyInterface | Reexport )) == ( ExportForAnyInterface | Reexport ))
- hook.clear();
-
- // we're not matching any interface, but if we're not replacing, make sure it doesn't exist yet
- else if (( options & Reexport ) == 0 && hook.find(iface) != hook.end())
+ if (options & ExportSignals) {
+ qWarning("Cannot export signals from objects. Use an adaptor for that purpose.");
return false;
+ }
- QDBusConnectionPrivate::ObjectData& data = hook[iface];
+ QStringList pathComponents = path.split(QLatin1Char('/'));
+ if (pathComponents.last().isEmpty())
+ pathComponents.removeLast();
+ QWriteLocker locker(&d->lock);
+
+ // lower-bound search for where this object should enter in the tree
+ QDBusConnectionPrivate::ObjectTreeNode *node = &d->rootNode;
+ int i = 1;
+ while (node) {
+ if (pathComponents.count() == i) {
+ // this node exists
+ // consider it free if there's no object here and the user is not trying to
+ // replace the object sub-tree
+ if ((options & ExportChildObjects && !node->children.isEmpty()) || node->obj)
+ return false;
+
+ // we can add the object here
+ node->obj = object;
+ node->flags = options;
+
+ d->registerObject(node);
+ qDebug("REGISTERED FOR %s", path.toLocal8Bit().constData());
+ return true;
+ }
- data.flags = options;
- data.obj = object;
+ // find the position where we'd insert the node
+ QVector<QDBusConnectionPrivate::ObjectTreeNode::Data>::Iterator it =
+ qLowerBound(node->children.begin(), node->children.end(), pathComponents.at(i));
+ if (it != node->children.constEnd() && it->name == pathComponents.at(i)) {
+ // match: this node exists
+ node = it->node;
+
+ // are we allowed to go deeper?
+ if (node->flags & ExportChildObjects) {
+ // we're not
+ qDebug("Cannot register object at %s because %s exports its own child objects",
+ qPrintable(path), qPrintable(pathComponents.at(i)));
+ return false;
+ }
+ } else {
+ // add entry
+ QDBusConnectionPrivate::ObjectTreeNode::Data entry;
+ entry.name = pathComponents.at(i);
+ entry.node = new QDBusConnectionPrivate::ObjectTreeNode;
+ node->children.insert(it, entry);
+
+ node = entry.node;
+ }
- d->connect(object, SIGNAL(destroyed(QObject*)), SLOT(objectDestroyed(QObject*)));
- qDebug("REGISTERED FOR %s", path.toLocal8Bit().constData());
+ // iterate
+ ++i;
+ }
- return true; // todo - check for slots etc.
+ Q_ASSERT_X(false, "QDBusConnection::registerObject", "The impossible happened");
+ return false;
}
-void QDBusConnection::unregisterObject(const QString &path)
+/*!
+ Unregisters an object that was registered with the registerObject() function and, if \p mode is
+ QDBusConnection::UnregisterTree, all of its sub-objects too.
+
+ Note that you cannot unregister objects that were not registered with registerObject().
+*/
+void QDBusConnection::unregisterObject(const QString &path, UnregisterMode mode)
{
- if (!d || !d->connection)
+ if (!d || !d->connection || !QDBusUtil::isValidObjectPath(path))
return;
- d->objectHooks.remove(path);
+ QStringList pathComponents = path.split(QLatin1Char('/'));
+ QWriteLocker locker(&d->lock);
+ QDBusConnectionPrivate::ObjectTreeNode *node = &d->rootNode;
+ int i = 1;
+
+ // find the object
+ while (node) {
+ if (pathComponents.count() == i) {
+ // found it
+ node->obj = 0;
+ node->flags = 0;
+
+ if (mode == UnregisterTree) {
+ // clear the sub-tree as well
+ node->clear(); // can't disconnect the objects because we really don't know if they can
+ // be found somewhere else in the path too
+ }
+
+ return;
+ }
+
+ QVector<QDBusConnectionPrivate::ObjectTreeNode::Data>::ConstIterator it =
+ qLowerBound(node->children.constBegin(), node->children.constEnd(), pathComponents.at(i));
+ if (it == node->children.constEnd() || it->name != pathComponents.at(i))
+ break; // node not found
+
+ node = it->node;
+ ++i;
+ }
}
+/*!
+ Returns a QDBusInterface associated with the interface \p interface on object at path \p path on
+ service \p service.
+*/
QDBusInterface QDBusConnection::findInterface(const QString& service, const QString& path,
const QString& interface)
{
// create one
- QDBusInterfacePrivate *priv = new QDBusInterfacePrivate;
- priv->conn = *this;
+ QDBusInterfacePrivate *priv = new QDBusInterfacePrivate(*this);
- if (!QDBusUtil::isValidObjectPath(path) || !QDBusUtil::isValidInterfaceName(interface))
+ if (!(interface.isEmpty() || QDBusUtil::isValidInterfaceName(interface)) ||
+ !QDBusUtil::isValidObjectPath(path))
return QDBusInterface(priv);
// check if it's there first
@@ -352,28 +621,64 @@ QDBusInterface QDBusConnection::findInterface(const QString& service, const QStr
return QDBusInterface(priv); // will increment priv's refcount
}
+/*!
+ \fn QDBusConnection::findInterface(const QString &service, const QString &path)
+ Returns an interface of type \p Interface associated with the object on path \p path at service
+ \p service.
+
+ \p Interface must be a class derived from QDBusInterface.
+*/
+
+/*!
+ Returns a QDBusObject associated with the object on path \p path at service \p service.
+*/
QDBusObject QDBusConnection::findObject(const QString& service, const QString& path)
{
QDBusObjectPrivate* priv = 0;
if (d && QDBusUtil::isValidObjectPath(path)) {
QString owner = getNameOwner(service);
-
+
if (!owner.isEmpty())
priv = new QDBusObjectPrivate(d, owner, path);
}
return QDBusObject(priv, *this);
-}
+}
+
+/*!
+ Returns true if this QDBusConnection object is connected.
+
+ \note If it isn't connected, calling QDBusConnection::addConnection on the same connection name
+ will not make be connected. You need to call the QDBusConnection constructor again.
+*/
bool QDBusConnection::isConnected( ) const
{
return d && d->connection && dbus_connection_get_is_connected(d->connection);
}
+/*!
+ Returns the last error that happened in this connection.
+
+ This function is provided for low-level code. If you're using QDBusInterface::call, error codes are
+ reported by its return value.
+
+ \sa QDBusInterface, QDBusMessage
+*/
QDBusError QDBusConnection::lastError() const
{
return d ? d->lastError : QDBusError();
}
+/*!
+ Returns the unique connection name for this connection, if this QDBusConnection object is
+ connected, or an empty QString otherwise.
+
+ A Unique Connection Name is a string in the form ":x.xxx" (where x are decimal digits) that is
+ assigned by the D-Bus server daemon upon connection. It uniquely identifies this client in the
+ bus.
+
+ This function returns an empty QString for peer-to-peer connections.
+*/
QString QDBusConnection::baseService() const
{
return d && d->connection ?
@@ -381,6 +686,25 @@ QString QDBusConnection::baseService() const
: QString();
}
+/*!
+ Sends a request to the D-Bus server daemon to request the service name \p name. The flags \p
+ mode indicate how to proceed if the name is already taken or when another D-Bus client requests
+ the same name.
+
+ Service names are used to publish well-known services on the D-Bus bus, by associating a
+ friendly name to this connection. Other D-Bus clients will then be able to contact this
+ connection and the objects registered on it by using this name instead of the unique connection
+ name (see baseService()). This also allows one application to always have the same name, while
+ its unique connection name changes.
+
+ This function has no meaning in peer-to-peer connections.
+
+ This function returns true if the name is assigned to this connection now (including the case
+ when it was already assigned).
+
+ \todo probably move to the QObject representing the bus
+ \todo update the NameRequestMode flags
+*/
bool QDBusConnection::requestName(const QString &name, NameRequestMode mode)
{
static const int DBusModes[] = { DBUS_NAME_FLAG_ALLOW_REPLACEMENT, 0,
@@ -392,6 +716,17 @@ bool QDBusConnection::requestName(const QString &name, NameRequestMode mode)
retval == DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER;
}
+/*!
+ Releases a name that had been requested using requestName(). This function returns true if the
+ name has been released, false otherwise.
+
+ This function has no meaning in peer-to-peer connections.
+
+ You cannot cause a name owned by another application to be released using releaseName(). Use
+ requestName() instead to assign it to your application.
+
+ \todo probably move to the QObject representing the bus
+*/
bool QDBusConnection::releaseName(const QString &name)
{
int retval = dbus_bus_release_name(d->connection, name.toUtf8(), &d->error);
@@ -401,15 +736,23 @@ bool QDBusConnection::releaseName(const QString &name)
return retval == DBUS_RELEASE_NAME_REPLY_RELEASED;
}
+/*!
+ Returns the unique connection name of the client that currently has the \p name
+ requested. Returns an empty QString in case there is no such name on the bus or if \p name is
+ not a well-formed bus name.
+
+ \todo probably move to the QObject representing the bus
+*/
QString QDBusConnection::getNameOwner(const QString& name)
{
if (QDBusUtil::isValidUniqueConnectionName(name))
return name;
if (!d || !QDBusUtil::isValidBusName(name))
return QString();
-
- QDBusMessage msg = QDBusMessage::methodCall(DBUS_SERVICE_DBUS, DBUS_PATH_DBUS,
- DBUS_INTERFACE_DBUS, "GetNameOwner");
+
+ QDBusMessage msg = QDBusMessage::methodCall(QLatin1String(DBUS_SERVICE_DBUS),
+ QLatin1String(DBUS_PATH_DBUS), QLatin1String(DBUS_INTERFACE_DBUS),
+ QLatin1String("GetNameOwner"));
msg << name;
QDBusMessage reply = sendWithReply(msg);
if (!lastError().isValid() && reply.type() == QDBusMessage::ReplyMessage)
@@ -417,4 +760,56 @@ QString QDBusConnection::getNameOwner(const QString& name)
return QString();
}
-#include "qdbusconnection_p.moc"
+/*!
+ \internal
+*/
+template<int type>
+struct DefaultBus
+{
+ DefaultBus()
+ {
+ QDBusConnection con = QDBusConnection::addConnection(QDBusConnection::BusType(type),
+ QLatin1String(busName));
+ bus = new QDBusConnection(con);
+ qAddPostRoutine(clear);
+ }
+
+ ~DefaultBus()
+ {
+ delete bus;
+ }
+
+ static void clear()
+ {
+ delete bus;
+ bus = 0;
+ QDBusConnection::closeConnection(QLatin1String(busName));
+ }
+
+ static QDBusConnection *bus;
+ static const char busName[];
+};
+
+Q_GLOBAL_STATIC(DefaultBus<QDBusConnection::SessionBus>, sessionBusPtr);
+Q_GLOBAL_STATIC(DefaultBus<QDBusConnection::SystemBus>, systemBusPtr);
+
+template<>
+QT_STATIC_CONST_IMPL char DefaultBus<QDBusConnection::SessionBus>::busName[] = "qt_default_session_bus";
+template<>
+QT_STATIC_CONST_IMPL char DefaultBus<QDBusConnection::SystemBus>::busName[] = "qt_default_system_bus";
+
+template<> QDBusConnection *DefaultBus<QDBusConnection::SessionBus>::bus = 0;
+template<> QDBusConnection *DefaultBus<QDBusConnection::SystemBus>::bus = 0;
+
+namespace QDBus {
+ QDBusConnection &sessionBus()
+ {
+ return *sessionBusPtr()->bus;
+ }
+
+ QDBusConnection &systemBus()
+ {
+ return *systemBusPtr()->bus;
+ }
+}
+