3 * Copyright (C) 2005 Harald Fernengel <harry@kdevelop.org>
4 * Copyright (C) 2006 Trolltech AS. All rights reserved.
5 * Author: Thiago Macieira <thiago.macieira@trolltech.com>
7 * Licensed under the Academic Free License version 2.1
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software Foundation
21 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25 #include "qdbusmessage.h"
28 #include <qstringlist.h>
30 #include <dbus/dbus.h>
32 #include "qdbuserror.h"
33 #include "qdbusmarshall_p.h"
34 #include "qdbusmessage_p.h"
35 #include "qdbustypehelper_p.h"
37 QDBusMessagePrivate::QDBusMessagePrivate()
38 : connection(QString()), msg(0), reply(0), type(DBUS_MESSAGE_TYPE_INVALID),
39 timeout(-1), ref(1), repliedTo(false)
43 QDBusMessagePrivate::~QDBusMessagePrivate()
46 dbus_message_unref(msg);
48 dbus_message_unref(reply);
54 \brief Represents one message sent or received over the DBus bus.
56 This object can represent any of four different types of messages possible on the bus
60 \o Method return values
65 Objects of this type are created with the four static functions signal, methodCall,
66 methodReply and error.
70 \enum QDBusMessage::MessageType
71 The possible message types:
73 \value MethodCallMessage a message representing an outgoing or incoming method call
74 \value SignalMessage a message representing an outgoing or incoming signal emission
75 \value ReplyMessage a message representing the return values of a method call
76 \value ErrorMessage a message representing an error condition in response to a method call
77 \value InvalidMessage an invalid message: this is never set on messages received from D-Bus
81 Constructs a new DBus message representing a signal emission. A DBus signal is emitted
82 from one application and is received by all applications that are listening for that signal
85 The signal will be constructed to represent a signal coming from the path \a path, interface \a
86 interface and signal name \a name.
88 The QDBusMessage object that is returned can be sent with QDBusConnection::send().
90 QDBusMessage QDBusMessage::signal(const QString &path, const QString &interface,
94 message.d_ptr->type = DBUS_MESSAGE_TYPE_SIGNAL;
95 message.d_ptr->path = path;
96 message.d_ptr->interface = interface;
97 message.d_ptr->name = name;
103 Constructs a new DBus message representing a method call. A method call always informs
104 its destination address (\a service, \a path, \a interface and \a method).
106 The DBus bus allows calling a method on a given remote object without specifying the
107 destination interface, if the method name is unique. However, if two interfaces on the
108 remote object export the same method name, the result is undefined (one of the two may be
109 called or an error may be returned).
111 When using DBus in a peer-to-peer context (i.e., not on a bus), the \a service parameter is
114 The QDBusObject and QDBusInterface classes provide a simpler abstraction to synchronous
117 This function returns a QDBusMessage object that can be sent with QDBusConnection::send(),
118 QDBusConnection::sendWithReply(), or QDBusConnection::sendWithReplyAsync().
120 QDBusMessage QDBusMessage::methodCall(const QString &service, const QString &path,
121 const QString &interface, const QString &method)
123 QDBusMessage message;
124 message.d_ptr->type = DBUS_MESSAGE_TYPE_METHOD_CALL;
125 message.d_ptr->service = service;
126 message.d_ptr->path = path;
127 message.d_ptr->interface = interface;
128 message.d_ptr->name = method;
134 Constructs a new DBus message representing the return values from a called method. The \a other
135 variable represents the method call that the reply will be for.
137 This function returns a QDBusMessage object that can be sent with QDBusConnection::send().
139 QDBusMessage QDBusMessage::methodReply(const QDBusMessage &other)
141 Q_ASSERT(other.d_ptr->msg);
143 QDBusMessage message;
144 message.d_ptr->connection = other.d_ptr->connection;
145 message.d_ptr->type = DBUS_MESSAGE_TYPE_METHOD_RETURN;
146 message.d_ptr->reply = dbus_message_ref(other.d_ptr->msg);
147 other.d_ptr->repliedTo = true;
153 Constructs a DBus message representing an error condition described by the \a name
154 parameter. The \a msg parameter is optional and may contain a human-readable description of the
155 error. The \a other variable represents the method call that this error relates to.
157 This function returns a QDBusMessage object that can be sent with QDBusMessage::send().
159 QDBusMessage QDBusMessage::error(const QDBusMessage &other, const QString &name,
162 Q_ASSERT(other.d_ptr->msg);
164 QDBusMessage message;
165 message.d_ptr->connection = other.d_ptr->connection;
166 message.d_ptr->type = DBUS_MESSAGE_TYPE_ERROR;
167 message.d_ptr->name = name;
168 message.d_ptr->message = msg;
169 message.d_ptr->reply = dbus_message_ref(other.d_ptr->msg);
170 other.d_ptr->repliedTo = true;
177 Constructs a DBus message representing an error, where \a other is the method call that
178 generated this error and \a error is the error code.
180 QDBusMessage QDBusMessage::error(const QDBusMessage &other, const QDBusError &error)
182 Q_ASSERT(other.d_ptr->msg);
184 QDBusMessage message;
185 message.d_ptr->connection = other.d_ptr->connection;
186 message.d_ptr->type = DBUS_MESSAGE_TYPE_ERROR;
187 message.d_ptr->name = error.name();
188 message.d_ptr->message = error.message();
189 message.d_ptr->reply = dbus_message_ref(other.d_ptr->msg);
190 other.d_ptr->repliedTo = true;
196 Constructs an empty, invalid QDBusMessage object.
198 \sa methodCall(), methodReply(), signal(), error()
200 QDBusMessage::QDBusMessage()
202 d_ptr = new QDBusMessagePrivate;
206 Constructs a copy of the object given by \a other.
208 QDBusMessage::QDBusMessage(const QDBusMessage &other)
209 : QList<QVariant>(other)
216 Disposes of the object and frees any resources that were being held.
218 QDBusMessage::~QDBusMessage()
220 if (!d_ptr->ref.deref())
225 Copies the contents of the object given by \a other.
227 QDBusMessage &QDBusMessage::operator=(const QDBusMessage &other)
229 QList<QVariant>::operator=(other);
230 qAtomicAssign(d_ptr, other.d_ptr);
234 static inline const char *data(const QByteArray &arr)
236 return arr.isEmpty() ? 0 : arr.constData();
241 Constructs a DBusMessage object from this object. The returned value must be de-referenced
242 with dbus_message_unref.
244 DBusMessage *QDBusMessage::toDBusMessage() const
246 DBusMessage *msg = 0;
248 switch (d_ptr->type) {
249 case DBUS_MESSAGE_TYPE_METHOD_CALL:
250 msg = dbus_message_new_method_call(data(d_ptr->service.toUtf8()), data(d_ptr->path.toUtf8()),
251 data(d_ptr->interface.toUtf8()), data(d_ptr->name.toUtf8()));
253 case DBUS_MESSAGE_TYPE_SIGNAL:
254 msg = dbus_message_new_signal(data(d_ptr->path.toUtf8()), data(d_ptr->interface.toUtf8()),
255 data(d_ptr->name.toUtf8()));
257 case DBUS_MESSAGE_TYPE_METHOD_RETURN:
258 msg = dbus_message_new_method_return(d_ptr->reply);
260 case DBUS_MESSAGE_TYPE_ERROR:
261 msg = dbus_message_new_error(d_ptr->reply, data(d_ptr->name.toUtf8()), data(d_ptr->message.toUtf8()));
267 QDBusMarshall::listToMessage(*this, msg, d_ptr->signature);
273 Constructs a QDBusMessage by parsing the given DBusMessage object.
275 QDBusMessage QDBusMessage::fromDBusMessage(DBusMessage *dmsg, const QDBusConnection &connection)
277 QDBusMessage message;
281 message.d_ptr->connection = connection;
282 message.d_ptr->type = dbus_message_get_type(dmsg);
283 message.d_ptr->path = QString::fromUtf8(dbus_message_get_path(dmsg));
284 message.d_ptr->interface = QString::fromUtf8(dbus_message_get_interface(dmsg));
285 message.d_ptr->name = message.d_ptr->type == DBUS_MESSAGE_TYPE_ERROR ?
286 QString::fromUtf8(dbus_message_get_error_name(dmsg)) :
287 QString::fromUtf8(dbus_message_get_member(dmsg));
288 message.d_ptr->service = QString::fromUtf8(dbus_message_get_sender(dmsg));
289 message.d_ptr->signature = QString::fromUtf8(dbus_message_get_signature(dmsg));
290 message.d_ptr->msg = dbus_message_ref(dmsg);
292 QDBusMarshall::messageToList(message, dmsg);
297 Creates a QDBusMessage that represents the same error as the QDBusError object.
299 QDBusMessage QDBusMessage::fromError(const QDBusError &error)
301 QDBusMessage message;
302 message.d_ptr->type = DBUS_MESSAGE_TYPE_ERROR;
303 message.d_ptr->name = error.name();
304 message << error.message();
309 Returns the path of the object that this message is being sent to (in the case of a
310 method call) or being received from (for a signal).
312 QString QDBusMessage::path() const
318 Returns the interface of the method being called (in the case of a method call) or of
319 the signal being received from.
321 QString QDBusMessage::interface() const
323 return d_ptr->interface;
327 Returns the name of the signal that was emitted or the name of the error that was
331 QString QDBusMessage::name() const
337 \fn QDBusMessage::member() const
338 Returns the name of the method being called.
342 \fn QDBusMessage::method() const
344 Returns the name of the method being called.
348 Returns the name of the service or the bus address of the remote method call.
350 QString QDBusMessage::service() const
352 return d_ptr->service;
356 \fn QDBusMessage::sender() const
357 Returns the unique name of the remote sender.
361 Returns the timeout (in milliseconds) for this message to be processed.
363 int QDBusMessage::timeout() const
365 return d_ptr->timeout;
369 Sets the timeout for this message to be processed, given by \a ms, in milliseconds.
371 void QDBusMessage::setTimeout(int ms)
373 qAtomicDetach(d_ptr);
378 Returns the flag that indicates if this message should see a reply or not. This is only
379 meaningful for MethodCall messages: any other kind of message cannot have replies and this
380 function will always return false for them.
382 bool QDBusMessage::noReply() const
386 return dbus_message_get_no_reply(d_ptr->msg);
390 Returns the unique serial number assigned to this message
391 or 0 if the message was not sent yet.
393 int QDBusMessage::serialNumber() const
397 return dbus_message_get_serial(d_ptr->msg);
401 Returns the unique serial number assigned to the message
402 that triggered this reply message.
404 If this message is not a reply to another message, 0
408 int QDBusMessage::replySerialNumber() const
412 return dbus_message_get_reply_serial(d_ptr->msg);
416 Returns true if this is a MethodCall message and a reply for it has been generated using
417 QDBusMessage::methodReply or QDBusMessage::error.
419 bool QDBusMessage::wasRepliedTo() const
421 return d_ptr->repliedTo;
425 Returns the signature of the signal that was received or for the output arguments
428 QString QDBusMessage::signature() const
430 return d_ptr->signature;
434 Sets the signature for the output arguments of this method call to be the value of \a
435 signature. This function has no meaning in other types of messages or when dealing with received
438 A message's signature indicate the type of the parameters to
439 be marshalled over the bus. If there are more arguments than entries in the signature, the
440 tailing arguments will be silently dropped and not sent. If there are less arguments,
441 default values will be inserted (default values are those created by QVariant::convert
442 when a variant of type QVariant::Invalid is converted to the type).
445 void QDBusMessage::setSignature(const QString &signature)
447 qAtomicDetach(d_ptr);
448 d_ptr->signature = signature;
452 Returns the connection this message was received on or an unconnected QDBusConnection object if
453 this isn't a message that has been received.
455 QDBusConnection QDBusMessage::connection() const
457 return d_ptr->connection;
461 Returns the message type.
463 QDBusMessage::MessageType QDBusMessage::type() const
465 switch (d_ptr->type) {
466 case DBUS_MESSAGE_TYPE_METHOD_CALL:
467 return MethodCallMessage;
468 case DBUS_MESSAGE_TYPE_METHOD_RETURN:
470 case DBUS_MESSAGE_TYPE_ERROR:
472 case DBUS_MESSAGE_TYPE_SIGNAL:
473 return SignalMessage;
475 return InvalidMessage;
479 // Document QDBusReply here
482 \brief The reply for a method call to a remote object.
484 A QDBusReply object is a subset of the QDBusMessage object that represents a method call's
485 reply. It contains only the first output argument or the error code and is used by
486 QDBusInterface-derived classes to allow returning the error code as the function's return
489 It can be used in the following manner:
491 QDBusReply<QString> reply = interface->call("RemoteMethod");
492 if (reply.isSuccess())
493 // use the returned value
494 useValue(reply.value());
496 // call failed. Show an error condition.
497 showError(reply.error());
500 If the remote method call cannot fail, you can skip the error checking:
502 QString reply = interface->call("RemoteMethod");
505 However, if it does fail under those conditions, the value returned by QDBusReply::value() is
506 undefined. It may be undistinguishable from a valid return value.
508 QDBusReply objects are used for remote calls that have no output arguments or return values
509 (i.e., they have a "void" return type). In this case, you can only test if the reply succeeded
510 or not, by calling isError() and isSuccess(), and inspecting the error condition by calling
511 error(). You cannot call value().
513 \sa QDBusMessage, QDBusInterface
517 \fn QDBusReply::QDBusReply(const QDBusMessage &reply)
518 Automatically construct a QDBusReply object from the reply message \a reply, extracting the
519 first return value from it if it is a success reply.
523 \fn QDBusReply::QDBusReply(const QDBusError &error)
524 Constructs an error reply from the D-Bus error code given by \a error.
528 \fn QDBusReply::isError() const
529 Returns true if this reply is an error reply. You can extract the error contents using the
534 \fn QDBusReply::isSuccess() const
535 Returns true if this reply is a normal error reply (not an error). You can extract the returned
540 \fn QDBusReply::error()
541 Returns the error code that was returned from the remote function call. If the remote call did
542 not return an error (i.e., if it succeeded), then the QDBusError object that is returned will
543 not be a valid error code (QDBusError::isValid() will return false).
547 \fn QDBusReply::value()
548 Returns the remote function's calls return value. If the remote call returned with an error,
549 the return value of this function is undefined and may be undistinguishable from a valid return
552 This function is not available if the remote call returns \c void.
556 \fn QDBusReply::operator Type()
557 Returns the same as value().
559 This function is not available if the remote call returns \c void.
564 \fn QDBusReply::fromVariant(const QDBusReply<QVariant> &variantReply)
565 Converts the QDBusReply<QVariant> object to this type by converting the variant contained in
566 \a variantReply to the template's type and copying the error condition.
568 If the QVariant in variantReply is not convertible to this type, it will assume an undefined
573 QDebug operator<<(QDebug dbg, QDBusMessage::MessageType t)
577 case QDBusMessage::MethodCallMessage:
578 return dbg << "MethodCall";
579 case QDBusMessage::ReplyMessage:
580 return dbg << "MethodReturn";
581 case QDBusMessage::SignalMessage:
582 return dbg << "Signal";
583 case QDBusMessage::ErrorMessage:
584 return dbg << "Error";
586 return dbg << "Invalid";
590 static void debugVariantList(QDebug dbg, const QVariantList &list);
591 static void debugVariantMap(QDebug dbg, const QVariantMap &map);
593 static void debugVariant(QDebug dbg, const QVariant &v)
595 dbg.nospace() << v.typeName() << "(";
596 switch (v.userType())
599 dbg.nospace() << v.toBool();
601 case QMetaType::UChar:
602 dbg.nospace() << qvariant_cast<uchar>(v);
604 case QMetaType::Short:
605 dbg.nospace() << qvariant_cast<short>(v);
607 case QMetaType::UShort:
608 dbg.nospace() << qvariant_cast<ushort>(v);
611 dbg.nospace() << v.toInt();
614 dbg.nospace() << v.toUInt();
616 case QVariant::LongLong:
617 dbg.nospace() << v.toLongLong();
619 case QVariant::ULongLong:
620 dbg.nospace() << v.toULongLong();
622 case QVariant::Double:
623 dbg.nospace() << v.toDouble();
625 case QVariant::String:
626 dbg.nospace() << v.toString();
628 case QVariant::ByteArray:
629 dbg.nospace() << v.toByteArray();
631 case QVariant::StringList:
632 dbg.nospace() << v.toStringList();
635 debugVariantList(dbg, v.toList());
638 debugVariantMap(dbg, v.toMap());
642 int id = v.userType();
643 if (id == QDBusTypeHelper<QVariant>::id())
644 debugVariant(dbg, QDBusTypeHelper<QVariant>::fromVariant(v));
645 else if (id == QDBusTypeHelper<bool>::listId())
646 dbg.nospace() << QDBusTypeHelper<QList<bool> >::fromVariant(v);
647 else if (id == QDBusTypeHelper<short>::listId())
648 dbg.nospace() << QDBusTypeHelper<QList<short> >::fromVariant(v);
649 else if (id == QDBusTypeHelper<ushort>::listId())
650 dbg.nospace() << QDBusTypeHelper<QList<ushort> >::fromVariant(v);
651 else if (id == QDBusTypeHelper<int>::listId())
652 dbg.nospace() << QDBusTypeHelper<QList<int> >::fromVariant(v);
653 else if (id == QDBusTypeHelper<uint>::listId())
654 dbg.nospace() << QDBusTypeHelper<QList<uint> >::fromVariant(v);
655 else if (id == QDBusTypeHelper<qlonglong>::listId())
656 dbg.nospace() << QDBusTypeHelper<QList<qlonglong> >::fromVariant(v);
657 else if (id == QDBusTypeHelper<qulonglong>::listId())
658 dbg.nospace() << QDBusTypeHelper<QList<qulonglong> >::fromVariant(v);
659 else if (id == QDBusTypeHelper<double>::listId())
660 dbg.nospace() << QDBusTypeHelper<QList<double> >::fromVariant(v);
662 dbg.nospace() << "unknown";
665 dbg.nospace() << ")";
668 static void debugVariantList(QDebug dbg, const QVariantList &list)
671 QVariantList::ConstIterator it = list.constBegin();
672 QVariantList::ConstIterator end = list.constEnd();
673 for ( ; it != end; ++it) {
675 dbg.nospace() << ", ";
676 debugVariant(dbg, *it);
681 static void debugVariantMap(QDebug dbg, const QVariantMap &map)
683 QVariantMap::ConstIterator it = map.constBegin();
684 QVariantMap::ConstIterator end = map.constEnd();
685 for ( ; it != end; ++it) {
686 dbg << "(" << it.key() << ", ";
687 debugVariant(dbg, it.value());
692 QDebug operator<<(QDebug dbg, const QDBusMessage &msg)
694 dbg.nospace() << "QDBusMessage(type=" << msg.type()
695 << ", service=" << msg.service()
696 << ", path=" << msg.path()
697 << ", interface=" << msg.interface()
698 << ", name=" << msg.name()
699 << ", signature=" << msg.signature()
701 debugVariantList(dbg, msg);
702 dbg.nospace() << " ) )";