summaryrefslogtreecommitdiffstats
path: root/qt/src/qdbusmessage.cpp
diff options
context:
space:
mode:
authorThiago Macieira <thiago@kde.org>2006-06-04 15:52:05 +0000
committerThiago Macieira <thiago@kde.org>2006-06-04 15:52:05 +0000
commitedbf2bfc109ce94b2604ea20328fda25542e4383 (patch)
tree3281d191fa9dde9f1f26b947b145d02373f031b0 /qt/src/qdbusmessage.cpp
parent435c7af9b605c3ffc8641142b6d7add18bf7080b (diff)
* qt/: Update to Subversion r548032.
This includes a big reorganisation of the files inside the subdir. We really need a version control system that supports moving of files. I'm not bothering with history anyways anymore, since the bindings will be moved out to git. The history should be restored from Subversion when that happens.
Diffstat (limited to 'qt/src/qdbusmessage.cpp')
-rw-r--r--qt/src/qdbusmessage.cpp706
1 files changed, 706 insertions, 0 deletions
diff --git a/qt/src/qdbusmessage.cpp b/qt/src/qdbusmessage.cpp
new file mode 100644
index 00000000..d0a0f1e5
--- /dev/null
+++ b/qt/src/qdbusmessage.cpp
@@ -0,0 +1,706 @@
+/* qdbusmessage.cpp
+ *
+ * Copyright (C) 2005 Harald Fernengel <harry@kdevelop.org>
+ * Copyright (C) 2006 Trolltech AS. All rights reserved.
+ * Author: Thiago Macieira <thiago.macieira@trolltech.com>
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "qdbusmessage.h"
+
+#include <qdebug.h>
+#include <qstringlist.h>
+
+#include <dbus/dbus.h>
+
+#include "qdbuserror.h"
+#include "qdbusmarshall_p.h"
+#include "qdbusmessage_p.h"
+#include "qdbustypehelper_p.h"
+
+QDBusMessagePrivate::QDBusMessagePrivate()
+ : connection(QString()), msg(0), reply(0), type(DBUS_MESSAGE_TYPE_INVALID),
+ timeout(-1), ref(1), repliedTo(false)
+{
+}
+
+QDBusMessagePrivate::~QDBusMessagePrivate()
+{
+ if (msg)
+ dbus_message_unref(msg);
+ if (reply)
+ dbus_message_unref(reply);
+}
+
+///////////////
+/*!
+ \class QDBusMessage
+ \brief Represents one message sent or received over the DBus bus.
+
+ This object can represent any of four different types of messages possible on the bus
+ (see MessageType)
+ \list
+ \o Method calls
+ \o Method return values
+ \o Signal emissions
+ \o Error codes
+ \endlist
+
+ Objects of this type are created with the four static functions signal, methodCall,
+ methodReply and error.
+*/
+
+/*!
+ \enum QDBusMessage::MessageType
+ The possible message types:
+
+ \value MethodCallMessage a message representing an outgoing or incoming method call
+ \value SignalMessage a message representing an outgoing or incoming signal emission
+ \value ReplyMessage a message representing the return values of a method call
+ \value ErrorMessage a message representing an error condition in response to a method call
+ \value InvalidMessage an invalid message: this is never set on messages received from D-Bus
+*/
+
+/*!
+ Constructs a new DBus message representing a signal emission. A DBus signal is emitted
+ from one application and is received by all applications that are listening for that signal
+ from that interface.
+
+ The signal will be constructed to represent a signal coming from the path \a path, interface \a
+ interface and signal name \a name.
+
+ The QDBusMessage object that is returned can be sent with QDBusConnection::send().
+*/
+QDBusMessage QDBusMessage::signal(const QString &path, const QString &interface,
+ const QString &name)
+{
+ QDBusMessage message;
+ message.d_ptr->type = DBUS_MESSAGE_TYPE_SIGNAL;
+ message.d_ptr->path = path;
+ message.d_ptr->interface = interface;
+ message.d_ptr->name = name;
+
+ return message;
+}
+
+/*!
+ Constructs a new DBus message representing a method call. A method call always informs
+ its destination address (\a service, \a path, \a interface and \a method).
+
+ The DBus bus allows calling a method on a given remote object without specifying the
+ destination interface, if the method name is unique. However, if two interfaces on the
+ remote object export the same method name, the result is undefined (one of the two may be
+ called or an error may be returned).
+
+ When using DBus in a peer-to-peer context (i.e., not on a bus), the \a service parameter is
+ optional.
+
+ The QDBusObject and QDBusInterface classes provide a simpler abstraction to synchronous
+ method calling.
+
+ This function returns a QDBusMessage object that can be sent with QDBusConnection::send(),
+ QDBusConnection::sendWithReply(), or QDBusConnection::sendWithReplyAsync().
+*/
+QDBusMessage QDBusMessage::methodCall(const QString &service, const QString &path,
+ const QString &interface, const QString &method)
+{
+ QDBusMessage message;
+ message.d_ptr->type = DBUS_MESSAGE_TYPE_METHOD_CALL;
+ message.d_ptr->service = service;
+ message.d_ptr->path = path;
+ message.d_ptr->interface = interface;
+ message.d_ptr->name = method;
+
+ return message;
+}
+
+/*!
+ Constructs a new DBus message representing the return values from a called method. The \a other
+ variable represents the method call that the reply will be for.
+
+ This function returns a QDBusMessage object that can be sent with QDBusConnection::send().
+*/
+QDBusMessage QDBusMessage::methodReply(const QDBusMessage &other)
+{
+ Q_ASSERT(other.d_ptr->msg);
+
+ QDBusMessage message;
+ message.d_ptr->connection = other.d_ptr->connection;
+ message.d_ptr->type = DBUS_MESSAGE_TYPE_METHOD_RETURN;
+ message.d_ptr->reply = dbus_message_ref(other.d_ptr->msg);
+ other.d_ptr->repliedTo = true;
+
+ return message;
+}
+
+/*!
+ Constructs a DBus message representing an error condition described by the \a name
+ parameter. The \a msg parameter is optional and may contain a human-readable description of the
+ error. The \a other variable represents the method call that this error relates to.
+
+ This function returns a QDBusMessage object that can be sent with QDBusMessage::send().
+*/
+QDBusMessage QDBusMessage::error(const QDBusMessage &other, const QString &name,
+ const QString &msg)
+{
+ Q_ASSERT(other.d_ptr->msg);
+
+ QDBusMessage message;
+ message.d_ptr->connection = other.d_ptr->connection;
+ message.d_ptr->type = DBUS_MESSAGE_TYPE_ERROR;
+ message.d_ptr->name = name;
+ message.d_ptr->message = msg;
+ message.d_ptr->reply = dbus_message_ref(other.d_ptr->msg);
+ other.d_ptr->repliedTo = true;
+
+ return message;
+}
+
+/*!
+ \overload
+ Constructs a DBus message representing an error, where \a other is the method call that
+ generated this error and \a error is the error code.
+*/
+QDBusMessage QDBusMessage::error(const QDBusMessage &other, const QDBusError &error)
+{
+ Q_ASSERT(other.d_ptr->msg);
+
+ QDBusMessage message;
+ message.d_ptr->connection = other.d_ptr->connection;
+ message.d_ptr->type = DBUS_MESSAGE_TYPE_ERROR;
+ message.d_ptr->name = error.name();
+ message.d_ptr->message = error.message();
+ message.d_ptr->reply = dbus_message_ref(other.d_ptr->msg);
+ other.d_ptr->repliedTo = true;
+
+ return message;
+}
+
+/*!
+ Constructs an empty, invalid QDBusMessage object.
+
+ \sa methodCall(), methodReply(), signal(), error()
+*/
+QDBusMessage::QDBusMessage()
+{
+ d_ptr = new QDBusMessagePrivate;
+}
+
+/*!
+ Constructs a copy of the object given by \a other.
+*/
+QDBusMessage::QDBusMessage(const QDBusMessage &other)
+ : QList<QVariant>(other)
+{
+ d_ptr = other.d_ptr;
+ d_ptr->ref.ref();
+}
+
+/*!
+ Disposes of the object and frees any resources that were being held.
+*/
+QDBusMessage::~QDBusMessage()
+{
+ if (!d_ptr->ref.deref())
+ delete d_ptr;
+}
+
+/*!
+ Copies the contents of the object given by \a other.
+*/
+QDBusMessage &QDBusMessage::operator=(const QDBusMessage &other)
+{
+ QList<QVariant>::operator=(other);
+ qAtomicAssign(d_ptr, other.d_ptr);
+ return *this;
+}
+
+static inline const char *data(const QByteArray &arr)
+{
+ return arr.isEmpty() ? 0 : arr.constData();
+}
+
+/*!
+ \internal
+ Constructs a DBusMessage object from this object. The returned value must be de-referenced
+ with dbus_message_unref.
+*/
+DBusMessage *QDBusMessage::toDBusMessage() const
+{
+ DBusMessage *msg = 0;
+
+ switch (d_ptr->type) {
+ case DBUS_MESSAGE_TYPE_METHOD_CALL:
+ msg = dbus_message_new_method_call(data(d_ptr->service.toUtf8()), data(d_ptr->path.toUtf8()),
+ data(d_ptr->interface.toUtf8()), data(d_ptr->name.toUtf8()));
+ break;
+ case DBUS_MESSAGE_TYPE_SIGNAL:
+ msg = dbus_message_new_signal(data(d_ptr->path.toUtf8()), data(d_ptr->interface.toUtf8()),
+ data(d_ptr->name.toUtf8()));
+ break;
+ case DBUS_MESSAGE_TYPE_METHOD_RETURN:
+ msg = dbus_message_new_method_return(d_ptr->reply);
+ break;
+ case DBUS_MESSAGE_TYPE_ERROR:
+ msg = dbus_message_new_error(d_ptr->reply, data(d_ptr->name.toUtf8()), data(d_ptr->message.toUtf8()));
+ break;
+ }
+ if (!msg)
+ return 0;
+
+ QDBusMarshall::listToMessage(*this, msg, d_ptr->signature);
+ return msg;
+}
+
+/*!
+ \internal
+ Constructs a QDBusMessage by parsing the given DBusMessage object.
+*/
+QDBusMessage QDBusMessage::fromDBusMessage(DBusMessage *dmsg, const QDBusConnection &connection)
+{
+ QDBusMessage message;
+ if (!dmsg)
+ return message;
+
+ message.d_ptr->connection = connection;
+ message.d_ptr->type = dbus_message_get_type(dmsg);
+ message.d_ptr->path = QString::fromUtf8(dbus_message_get_path(dmsg));
+ message.d_ptr->interface = QString::fromUtf8(dbus_message_get_interface(dmsg));
+ message.d_ptr->name = message.d_ptr->type == DBUS_MESSAGE_TYPE_ERROR ?
+ QString::fromUtf8(dbus_message_get_error_name(dmsg)) :
+ QString::fromUtf8(dbus_message_get_member(dmsg));
+ message.d_ptr->service = QString::fromUtf8(dbus_message_get_sender(dmsg));
+ message.d_ptr->signature = QString::fromUtf8(dbus_message_get_signature(dmsg));
+ message.d_ptr->msg = dbus_message_ref(dmsg);
+
+ QDBusMarshall::messageToList(message, dmsg);
+ return message;
+}
+
+/*!
+ Creates a QDBusMessage that represents the same error as the QDBusError object.
+*/
+QDBusMessage QDBusMessage::fromError(const QDBusError &error)
+{
+ QDBusMessage message;
+ message.d_ptr->type = DBUS_MESSAGE_TYPE_ERROR;
+ message.d_ptr->name = error.name();
+ message << error.message();
+ return message;
+}
+
+/*!
+ Returns the path of the object that this message is being sent to (in the case of a
+ method call) or being received from (for a signal).
+*/
+QString QDBusMessage::path() const
+{
+ return d_ptr->path;
+}
+
+/*!
+ Returns the interface of the method being called (in the case of a method call) or of
+ the signal being received from.
+*/
+QString QDBusMessage::interface() const
+{
+ return d_ptr->interface;
+}
+
+/*!
+ Returns the name of the signal that was emitted or the name of the error that was
+ received.
+ \sa member()
+*/
+QString QDBusMessage::name() const
+{
+ return d_ptr->name;
+}
+
+/*!
+ \fn QDBusMessage::member() const
+ Returns the name of the method being called.
+*/
+
+/*!
+ \fn QDBusMessage::method() const
+ \overload
+ Returns the name of the method being called.
+*/
+
+/*!
+ Returns the name of the service or the bus address of the remote method call.
+*/
+QString QDBusMessage::service() const
+{
+ return d_ptr->service;
+}
+
+/*!
+ \fn QDBusMessage::sender() const
+ Returns the unique name of the remote sender.
+*/
+
+/*!
+ Returns the timeout (in milliseconds) for this message to be processed.
+*/
+int QDBusMessage::timeout() const
+{
+ return d_ptr->timeout;
+}
+
+/*!
+ Sets the timeout for this message to be processed, given by \a ms, in milliseconds.
+*/
+void QDBusMessage::setTimeout(int ms)
+{
+ qAtomicDetach(d_ptr);
+ d_ptr->timeout = ms;
+}
+
+/*!
+ Returns the flag that indicates if this message should see a reply or not. This is only
+ meaningful for MethodCall messages: any other kind of message cannot have replies and this
+ function will always return false for them.
+*/
+bool QDBusMessage::noReply() const
+{
+ if (!d_ptr->msg)
+ return false;
+ return dbus_message_get_no_reply(d_ptr->msg);
+}
+
+/*!
+ Returns the unique serial number assigned to this message
+ or 0 if the message was not sent yet.
+ */
+int QDBusMessage::serialNumber() const
+{
+ if (!d_ptr->msg)
+ return 0;
+ return dbus_message_get_serial(d_ptr->msg);
+}
+
+/*!
+ Returns the unique serial number assigned to the message
+ that triggered this reply message.
+
+ If this message is not a reply to another message, 0
+ is returned.
+
+ */
+int QDBusMessage::replySerialNumber() const
+{
+ if (!d_ptr->msg)
+ return 0;
+ return dbus_message_get_reply_serial(d_ptr->msg);
+}
+
+/*!
+ Returns true if this is a MethodCall message and a reply for it has been generated using
+ QDBusMessage::methodReply or QDBusMessage::error.
+*/
+bool QDBusMessage::wasRepliedTo() const
+{
+ return d_ptr->repliedTo;
+}
+
+/*!
+ Returns the signature of the signal that was received or for the output arguments
+ of a method call.
+*/
+QString QDBusMessage::signature() const
+{
+ return d_ptr->signature;
+}
+
+/*!
+ Sets the signature for the output arguments of this method call to be the value of \a
+ signature. This function has no meaning in other types of messages or when dealing with received
+ method calls.
+
+ A message's signature indicate the type of the parameters to
+ be marshalled over the bus. If there are more arguments than entries in the signature, the
+ tailing arguments will be silently dropped and not sent. If there are less arguments,
+ default values will be inserted (default values are those created by QVariant::convert
+ when a variant of type QVariant::Invalid is converted to the type).
+
+*/
+void QDBusMessage::setSignature(const QString &signature)
+{
+ qAtomicDetach(d_ptr);
+ d_ptr->signature = signature;
+}
+
+/*!
+ Returns the connection this message was received on or an unconnected QDBusConnection object if
+ this isn't a message that has been received.
+*/
+QDBusConnection QDBusMessage::connection() const
+{
+ return d_ptr->connection;
+}
+
+/*!
+ Returns the message type.
+*/
+QDBusMessage::MessageType QDBusMessage::type() const
+{
+ switch (d_ptr->type) {
+ case DBUS_MESSAGE_TYPE_METHOD_CALL:
+ return MethodCallMessage;
+ case DBUS_MESSAGE_TYPE_METHOD_RETURN:
+ return ReplyMessage;
+ case DBUS_MESSAGE_TYPE_ERROR:
+ return ErrorMessage;
+ case DBUS_MESSAGE_TYPE_SIGNAL:
+ return SignalMessage;
+ default:
+ return InvalidMessage;
+ }
+}
+
+// Document QDBusReply here
+/*!
+ \class QDBusReply
+ \brief The reply for a method call to a remote object.
+
+ A QDBusReply object is a subset of the QDBusMessage object that represents a method call's
+ reply. It contains only the first output argument or the error code and is used by
+ QDBusInterface-derived classes to allow returning the error code as the function's return
+ argument.
+
+ It can be used in the following manner:
+ \code
+ QDBusReply<QString> reply = interface->call("RemoteMethod");
+ if (reply.isSuccess())
+ // use the returned value
+ useValue(reply.value());
+ else
+ // call failed. Show an error condition.
+ showError(reply.error());
+ \endcode
+
+ If the remote method call cannot fail, you can skip the error checking:
+ \code
+ QString reply = interface->call("RemoteMethod");
+ \endcode
+
+ However, if it does fail under those conditions, the value returned by QDBusReply::value() is
+ undefined. It may be undistinguishable from a valid return value.
+
+ QDBusReply objects are used for remote calls that have no output arguments or return values
+ (i.e., they have a "void" return type). In this case, you can only test if the reply succeeded
+ or not, by calling isError() and isSuccess(), and inspecting the error condition by calling
+ error(). You cannot call value().
+
+ \sa QDBusMessage, QDBusInterface
+*/
+
+/*!
+ \fn QDBusReply::QDBusReply(const QDBusMessage &reply)
+ Automatically construct a QDBusReply object from the reply message \a reply, extracting the
+ first return value from it if it is a success reply.
+*/
+
+/*!
+ \fn QDBusReply::QDBusReply(const QDBusError &error)
+ Constructs an error reply from the D-Bus error code given by \a error.
+*/
+
+/*!
+ \fn QDBusReply::isError() const
+ Returns true if this reply is an error reply. You can extract the error contents using the
+ error() function.
+*/
+
+/*!
+ \fn QDBusReply::isSuccess() const
+ Returns true if this reply is a normal error reply (not an error). You can extract the returned
+ value with value()
+*/
+
+/*!
+ \fn QDBusReply::error()
+ Returns the error code that was returned from the remote function call. If the remote call did
+ not return an error (i.e., if it succeeded), then the QDBusError object that is returned will
+ not be a valid error code (QDBusError::isValid() will return false).
+*/
+
+/*!
+ \fn QDBusReply::value()
+ Returns the remote function's calls return value. If the remote call returned with an error,
+ the return value of this function is undefined and may be undistinguishable from a valid return
+ value.
+
+ This function is not available if the remote call returns \c void.
+*/
+
+/*!
+ \fn QDBusReply::operator Type()
+ Returns the same as value().
+
+ This function is not available if the remote call returns \c void.
+*/
+
+/*!
+ \internal
+ \fn QDBusReply::fromVariant(const QDBusReply<QVariant> &variantReply)
+ Converts the QDBusReply<QVariant> object to this type by converting the variant contained in
+ \a variantReply to the template's type and copying the error condition.
+
+ If the QVariant in variantReply is not convertible to this type, it will assume an undefined
+ value.
+*/
+
+#ifndef QT_NO_DEBUG
+QDebug operator<<(QDebug dbg, QDBusMessage::MessageType t)
+{
+ switch (t)
+ {
+ case QDBusMessage::MethodCallMessage:
+ return dbg << "MethodCall";
+ case QDBusMessage::ReplyMessage:
+ return dbg << "MethodReturn";
+ case QDBusMessage::SignalMessage:
+ return dbg << "Signal";
+ case QDBusMessage::ErrorMessage:
+ return dbg << "Error";
+ default:
+ return dbg << "Invalid";
+ }
+}
+
+static void debugVariantList(QDebug dbg, const QVariantList &list);
+static void debugVariantMap(QDebug dbg, const QVariantMap &map);
+
+static void debugVariant(QDebug dbg, const QVariant &v)
+{
+ dbg.nospace() << v.typeName() << "(";
+ switch (v.userType())
+ {
+ case QVariant::Bool:
+ dbg.nospace() << v.toBool();
+ break;
+ case QMetaType::UChar:
+ dbg.nospace() << qvariant_cast<uchar>(v);
+ break;
+ case QMetaType::Short:
+ dbg.nospace() << qvariant_cast<short>(v);
+ break;
+ case QMetaType::UShort:
+ dbg.nospace() << qvariant_cast<ushort>(v);
+ break;
+ case QVariant::Int:
+ dbg.nospace() << v.toInt();
+ break;
+ case QVariant::UInt:
+ dbg.nospace() << v.toUInt();
+ break;
+ case QVariant::LongLong:
+ dbg.nospace() << v.toLongLong();
+ break;
+ case QVariant::ULongLong:
+ dbg.nospace() << v.toULongLong();
+ break;
+ case QVariant::Double:
+ dbg.nospace() << v.toDouble();
+ break;
+ case QVariant::String:
+ dbg.nospace() << v.toString();
+ break;
+ case QVariant::ByteArray:
+ dbg.nospace() << v.toByteArray();
+ break;
+ case QVariant::StringList:
+ dbg.nospace() << v.toStringList();
+ break;
+ case QVariant::List:
+ debugVariantList(dbg, v.toList());
+ break;
+ case QVariant::Map:
+ debugVariantMap(dbg, v.toMap());
+ break;
+
+ default: {
+ int id = v.userType();
+ if (id == QDBusTypeHelper<QVariant>::id())
+ debugVariant(dbg, QDBusTypeHelper<QVariant>::fromVariant(v));
+ else if (id == QDBusTypeHelper<bool>::listId())
+ dbg.nospace() << QDBusTypeHelper<QList<bool> >::fromVariant(v);
+ else if (id == QDBusTypeHelper<short>::listId())
+ dbg.nospace() << QDBusTypeHelper<QList<short> >::fromVariant(v);
+ else if (id == QDBusTypeHelper<ushort>::listId())
+ dbg.nospace() << QDBusTypeHelper<QList<ushort> >::fromVariant(v);
+ else if (id == QDBusTypeHelper<int>::listId())
+ dbg.nospace() << QDBusTypeHelper<QList<int> >::fromVariant(v);
+ else if (id == QDBusTypeHelper<uint>::listId())
+ dbg.nospace() << QDBusTypeHelper<QList<uint> >::fromVariant(v);
+ else if (id == QDBusTypeHelper<qlonglong>::listId())
+ dbg.nospace() << QDBusTypeHelper<QList<qlonglong> >::fromVariant(v);
+ else if (id == QDBusTypeHelper<qulonglong>::listId())
+ dbg.nospace() << QDBusTypeHelper<QList<qulonglong> >::fromVariant(v);
+ else if (id == QDBusTypeHelper<double>::listId())
+ dbg.nospace() << QDBusTypeHelper<QList<double> >::fromVariant(v);
+ else
+ dbg.nospace() << "unknown";
+ }
+ }
+ dbg.nospace() << ")";
+}
+
+static void debugVariantList(QDebug dbg, const QVariantList &list)
+{
+ bool first = true;
+ QVariantList::ConstIterator it = list.constBegin();
+ QVariantList::ConstIterator end = list.constEnd();
+ for ( ; it != end; ++it) {
+ if (!first)
+ dbg.nospace() << ", ";
+ debugVariant(dbg, *it);
+ first = false;
+ }
+}
+
+static void debugVariantMap(QDebug dbg, const QVariantMap &map)
+{
+ QVariantMap::ConstIterator it = map.constBegin();
+ QVariantMap::ConstIterator end = map.constEnd();
+ for ( ; it != end; ++it) {
+ dbg << "(" << it.key() << ", ";
+ debugVariant(dbg, it.value());
+ dbg << ") ";
+ }
+}
+
+QDebug operator<<(QDebug dbg, const QDBusMessage &msg)
+{
+ dbg.nospace() << "QDBusMessage(type=" << msg.type()
+ << ", service=" << msg.service()
+ << ", path=" << msg.path()
+ << ", interface=" << msg.interface()
+ << ", name=" << msg.name()
+ << ", signature=" << msg.signature()
+ << ", contents=(";
+ debugVariantList(dbg, msg);
+ dbg.nospace() << " ) )";
+ return dbg.space();
+}
+#endif
+