8863766f404d2d87d31a4c1fbeefa891786bcd8d
[profile/ivi/qtbase.git] / src / dbus / qdbusmessage.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtDBus module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qdbusmessage.h"
43
44 #include <qdebug.h>
45 #include <qstringlist.h>
46
47 #include "qdbus_symbols_p.h"
48
49 #include "qdbusargument_p.h"
50 #include "qdbuserror.h"
51 #include "qdbusmessage_p.h"
52 #include "qdbusmetatype.h"
53 #include "qdbusconnection_p.h"
54 #include "qdbusutil_p.h"
55
56 #ifndef QT_NO_DBUS
57
58 QT_BEGIN_NAMESPACE
59
60 static inline const char *data(const QByteArray &arr)
61 {
62     return arr.isEmpty() ? 0 : arr.constData();
63 }
64
65 QDBusMessagePrivate::QDBusMessagePrivate()
66     : msg(0), reply(0), type(DBUS_MESSAGE_TYPE_INVALID),
67       timeout(-1), localReply(0), ref(1), delayedReply(false), localMessage(false),
68       parametersValidated(false), autoStartService(true)
69 {
70 }
71
72 QDBusMessagePrivate::~QDBusMessagePrivate()
73 {
74     if (msg)
75         q_dbus_message_unref(msg);
76     if (reply)
77         q_dbus_message_unref(reply);
78     delete localReply;
79 }
80
81 /*!
82     \since 4.3
83      Returns the human-readable message associated with the error that was received.
84 */
85 QString QDBusMessage::errorMessage() const
86 {
87     if (d_ptr->type == ErrorMessage) {
88         if (!d_ptr->message.isEmpty())
89            return d_ptr->message;
90         if (!d_ptr->arguments.isEmpty())
91             return d_ptr->arguments.at(0).toString();
92     }
93     return QString();
94 }
95
96 /*!
97     \internal
98     Constructs a DBusMessage object from \a message. The returned value must be de-referenced
99     with q_dbus_message_unref. The \a capabilities flags indicates which capabilities to use.
100
101     The \a error object is set to indicate the error if anything went wrong with the
102     marshalling. Usually, this error message will be placed in the reply, as if the call failed.
103     The \a error pointer must not be null.
104 */
105 DBusMessage *QDBusMessagePrivate::toDBusMessage(const QDBusMessage &message, QDBusConnection::ConnectionCapabilities capabilities,
106                                                 QDBusError *error)
107 {
108     if (!qdbus_loadLibDBus()) {
109         *error = QDBusError(QDBusError::Failed, QLatin1String("Could not open lidbus-1 library"));
110         return 0;
111     }
112
113     DBusMessage *msg = 0;
114     const QDBusMessagePrivate *d_ptr = message.d_ptr;
115
116     switch (d_ptr->type) {
117     case DBUS_MESSAGE_TYPE_INVALID:
118         //qDebug() << "QDBusMessagePrivate::toDBusMessage" <<  "message is invalid";
119         break;
120     case DBUS_MESSAGE_TYPE_METHOD_CALL:
121         // only service and interface can be empty -> path and name must not be empty
122         if (!d_ptr->parametersValidated) {
123             if (!QDBusUtil::checkBusName(d_ptr->service, QDBusUtil::EmptyAllowed, error))
124                 return 0;
125             if (!QDBusUtil::checkObjectPath(d_ptr->path, QDBusUtil::EmptyNotAllowed, error))
126                 return 0;
127             if (!QDBusUtil::checkInterfaceName(d_ptr->interface, QDBusUtil::EmptyAllowed, error))
128                 return 0;
129             if (!QDBusUtil::checkMemberName(d_ptr->name, QDBusUtil::EmptyNotAllowed, error, "method"))
130                 return 0;
131         }
132
133         msg = q_dbus_message_new_method_call(data(d_ptr->service.toUtf8()), d_ptr->path.toUtf8(),
134                                              data(d_ptr->interface.toUtf8()), d_ptr->name.toUtf8());
135         q_dbus_message_set_auto_start( msg, d_ptr->autoStartService );
136         break;
137     case DBUS_MESSAGE_TYPE_METHOD_RETURN:
138         msg = q_dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_RETURN);
139         if (!d_ptr->localMessage) {
140             q_dbus_message_set_destination(msg, q_dbus_message_get_sender(d_ptr->reply));
141             q_dbus_message_set_reply_serial(msg, q_dbus_message_get_serial(d_ptr->reply));
142         }
143         break;
144     case DBUS_MESSAGE_TYPE_ERROR:
145         // error name can't be empty
146         if (!d_ptr->parametersValidated
147             && !QDBusUtil::checkErrorName(d_ptr->name, QDBusUtil::EmptyNotAllowed, error))
148             return 0;
149
150         msg = q_dbus_message_new(DBUS_MESSAGE_TYPE_ERROR);
151         q_dbus_message_set_error_name(msg, d_ptr->name.toUtf8());
152         if (!d_ptr->localMessage) {
153             q_dbus_message_set_destination(msg, q_dbus_message_get_sender(d_ptr->reply));
154             q_dbus_message_set_reply_serial(msg, q_dbus_message_get_serial(d_ptr->reply));
155         }
156         break;
157     case DBUS_MESSAGE_TYPE_SIGNAL:
158         // nothing can be empty here
159         if (!d_ptr->parametersValidated) {
160             if (!QDBusUtil::checkObjectPath(d_ptr->path, QDBusUtil::EmptyNotAllowed, error))
161                 return 0;
162             if (!QDBusUtil::checkInterfaceName(d_ptr->interface, QDBusUtil::EmptyAllowed, error))
163                 return 0;
164             if (!QDBusUtil::checkMemberName(d_ptr->name, QDBusUtil::EmptyNotAllowed, error, "method"))
165                 return 0;
166         }
167
168         msg = q_dbus_message_new_signal(d_ptr->path.toUtf8(), d_ptr->interface.toUtf8(),
169                                         d_ptr->name.toUtf8());
170         break;
171     default:
172         Q_ASSERT(false);
173         break;
174     }
175
176     // if we got here, the parameters validated
177     // and since the message parameters cannot be changed once the message is created
178     // we can record this fact
179     d_ptr->parametersValidated = true;
180
181     QDBusMarshaller marshaller(capabilities);
182     QVariantList::ConstIterator it =  d_ptr->arguments.constBegin();
183     QVariantList::ConstIterator cend = d_ptr->arguments.constEnd();
184     q_dbus_message_iter_init_append(msg, &marshaller.iterator);
185     if (!d_ptr->message.isEmpty())
186         // prepend the error message
187         marshaller.append(d_ptr->message);
188     for ( ; it != cend; ++it)
189         marshaller.appendVariantInternal(*it);
190
191     // check if everything is ok
192     if (marshaller.ok)
193         return msg;
194
195     // not ok;
196     q_dbus_message_unref(msg);
197     *error = QDBusError(QDBusError::Failed, QLatin1String("Marshalling failed: ") + marshaller.errorString);
198     return 0;
199 }
200
201 /*
202 struct DBusMessage
203 {
204     DBusAtomic refcount;
205     DBusHeader header;
206     DBusString body;
207     char byte_order;
208     unsigned int locked : 1;
209 DBUS_DISABLE_CHECKS
210     unsigned int in_cache : 1;
211 #endif
212     DBusList *size_counters;
213     long size_counter_delta;
214     dbus_uint32_t changed_stamp : CHANGED_STAMP_BITS;
215     DBusDataSlotList slot_list;
216 #ifndef DBUS_DISABLE_CHECKS
217     int generation;
218 #endif
219 };
220 */
221
222 /*!
223     \internal
224     Constructs a QDBusMessage by parsing the given DBusMessage object.
225 */
226 QDBusMessage QDBusMessagePrivate::fromDBusMessage(DBusMessage *dmsg, QDBusConnection::ConnectionCapabilities capabilities)
227 {
228     QDBusMessage message;
229     if (!dmsg)
230         return message;
231
232     message.d_ptr->type = q_dbus_message_get_type(dmsg);
233     message.d_ptr->path = QString::fromUtf8(q_dbus_message_get_path(dmsg));
234     message.d_ptr->interface = QString::fromUtf8(q_dbus_message_get_interface(dmsg));
235     message.d_ptr->name = message.d_ptr->type == DBUS_MESSAGE_TYPE_ERROR ?
236                       QString::fromUtf8(q_dbus_message_get_error_name(dmsg)) :
237                       QString::fromUtf8(q_dbus_message_get_member(dmsg));
238     message.d_ptr->service = QString::fromUtf8(q_dbus_message_get_sender(dmsg));
239     message.d_ptr->signature = QString::fromUtf8(q_dbus_message_get_signature(dmsg));
240     message.d_ptr->msg = q_dbus_message_ref(dmsg);
241
242     QDBusDemarshaller demarshaller(capabilities);
243     demarshaller.message = q_dbus_message_ref(dmsg);
244     if (q_dbus_message_iter_init(demarshaller.message, &demarshaller.iterator))
245         while (!demarshaller.atEnd())
246             message << demarshaller.toVariantInternal();
247     return message;
248 }
249
250 bool QDBusMessagePrivate::isLocal(const QDBusMessage &message)
251 {
252     return message.d_ptr->localMessage;
253 }
254
255 QDBusMessage QDBusMessagePrivate::makeLocal(const QDBusConnectionPrivate &conn,
256                                             const QDBusMessage &asSent)
257 {
258     // simulate the message being sent to the bus and then received back
259     // the only field that the bus sets when delivering the message
260     // (as opposed to the message as we send it), is the sender
261     // so we simply set the sender to our unique name
262
263     // determine if we are carrying any complex types
264     QString computedSignature;
265     QVariantList::ConstIterator it = asSent.d_ptr->arguments.constBegin();
266     QVariantList::ConstIterator end = asSent.d_ptr->arguments.constEnd();
267     for ( ; it != end; ++it) {
268         int id = it->userType();
269         const char *signature = QDBusMetaType::typeToSignature(id);
270         if ((id != QVariant::StringList && id != QVariant::ByteArray &&
271              qstrlen(signature) != 1) || id == qMetaTypeId<QDBusVariant>()) {
272             // yes, we are
273             // we must marshall and demarshall again so as to create QDBusArgument
274             // entries for the complex types
275             QDBusError error;
276             DBusMessage *message = toDBusMessage(asSent, conn.capabilities, &error);
277             if (!message) {
278                 // failed to marshall, so it's a call error
279                 return QDBusMessage::createError(error);
280             }
281
282             q_dbus_message_set_sender(message, conn.baseService.toUtf8());
283
284             QDBusMessage retval = fromDBusMessage(message, conn.capabilities);
285             retval.d_ptr->localMessage = true;
286             q_dbus_message_unref(message);
287             if (retval.d_ptr->service.isEmpty())
288                 retval.d_ptr->service = conn.baseService;
289             return retval;
290         } else {
291             computedSignature += QLatin1String(signature);
292         }
293     }
294
295     // no complex types seen
296     // optimize by using the variant list itself
297     QDBusMessage retval;
298     QDBusMessagePrivate *d = retval.d_ptr;
299     d->arguments = asSent.d_ptr->arguments;
300     d->path = asSent.d_ptr->path;
301     d->interface = asSent.d_ptr->interface;
302     d->name = asSent.d_ptr->name;
303     d->message = asSent.d_ptr->message;
304     d->type = asSent.d_ptr->type;
305
306     d->service = conn.baseService;
307     d->signature = computedSignature;
308     d->localMessage = true;
309     return retval;
310 }
311
312 QDBusMessage QDBusMessagePrivate::makeLocalReply(const QDBusConnectionPrivate &conn,
313                                                  const QDBusMessage &callMsg)
314 {
315     // simulate the reply (return or error) message being sent to the bus and
316     // then received back.
317     if (callMsg.d_ptr->localReply)
318         return makeLocal(conn, *callMsg.d_ptr->localReply);
319     return QDBusMessage();      // failed
320 }
321
322 /*!
323     \class QDBusMessage
324     \inmodule QtDBus
325     \since 4.2
326
327     \brief The QDBusMessage class represents one message sent or
328     received over the D-Bus bus.
329
330     This object can represent any of the four different types of
331     messages (MessageType) that can occur on the bus:
332
333     \list
334       \li Method calls
335       \li Method return values
336       \li Signal emissions
337       \li Error codes
338     \endlist
339
340     Objects of this type are created with the static createError(),
341     createMethodCall() and createSignal() functions. Use the
342     QDBusConnection::send() function to send the messages.
343 */
344
345 /*!
346     \enum QDBusMessage::MessageType
347     The possible message types:
348
349     \value MethodCallMessage    a message representing an outgoing or incoming method call
350     \value SignalMessage        a message representing an outgoing or incoming signal emission
351     \value ReplyMessage         a message representing the return values of a method call
352     \value ErrorMessage         a message representing an error condition in response to a method call
353     \value InvalidMessage       an invalid message: this is never set on messages received from D-Bus
354 */
355
356 /*!
357     Constructs a new DBus message with the given \a path, \a interface
358     and \a name, representing a signal emission.
359
360     A DBus signal is emitted from one application and is received by
361     all applications that are listening for that signal from that
362     interface.
363
364     The QDBusMessage object that is returned can be sent using the
365     QDBusConnection::send() function.
366 */
367 QDBusMessage QDBusMessage::createSignal(const QString &path, const QString &interface,
368                                         const QString &name)
369 {
370     QDBusMessage message;
371     message.d_ptr->type = DBUS_MESSAGE_TYPE_SIGNAL;
372     message.d_ptr->path = path;
373     message.d_ptr->interface = interface;
374     message.d_ptr->name = name;
375
376     return message;
377 }
378
379 /*!
380     Constructs a new DBus message representing a method call.
381     A method call always informs its destination address
382     (\a service, \a path, \a interface and \a method).
383
384     The DBus bus allows calling a method on a given remote object without specifying the
385     destination interface, if the method name is unique. However, if two interfaces on the
386     remote object export the same method name, the result is undefined (one of the two may be
387     called or an error may be returned).
388
389     When using DBus in a peer-to-peer context (i.e., not on a bus), the \a service parameter is
390     optional.
391
392     The QDBusInterface class provides a simpler abstraction to synchronous
393     method calling.
394
395     This function returns a QDBusMessage object that can be sent with
396     QDBusConnection::call().
397 */
398 QDBusMessage QDBusMessage::createMethodCall(const QString &service, const QString &path,
399                                             const QString &interface, const QString &method)
400 {
401     QDBusMessage message;
402     message.d_ptr->type = DBUS_MESSAGE_TYPE_METHOD_CALL;
403     message.d_ptr->service = service;
404     message.d_ptr->path = path;
405     message.d_ptr->interface = interface;
406     message.d_ptr->name = method;
407
408     return message;
409 }
410
411 /*!
412     Constructs a new DBus message representing an error,
413     with the given \a name and \a msg.
414 */
415 QDBusMessage QDBusMessage::createError(const QString &name, const QString &msg)
416 {
417     QDBusMessage error;
418     error.d_ptr->type = DBUS_MESSAGE_TYPE_ERROR;
419     error.d_ptr->name = name;
420     error.d_ptr->message = msg;
421
422     return error;
423 }
424
425 /*!
426     \fn QDBusMessage QDBusMessage::createError(const QDBusError &error)
427
428     Constructs a new DBus message representing the given \a error.
429 */
430
431 /*!
432   \fn QDBusMessage QDBusMessage::createError(QDBusError::ErrorType type, const QString &msg)
433
434   Constructs a new DBus message for the error type \a type using
435   the message \a msg. Returns the DBus message.
436 */
437
438 /*!
439     \fn QDBusMessage QDBusMessage::createReply(const QList<QVariant> &arguments) const
440
441     Constructs a new DBus message representing a reply, with the given
442     \a arguments.
443 */
444 QDBusMessage QDBusMessage::createReply(const QVariantList &arguments) const
445 {
446     QDBusMessage reply;
447     reply.setArguments(arguments);
448     reply.d_ptr->type = DBUS_MESSAGE_TYPE_METHOD_RETURN;
449     if (d_ptr->msg)
450         reply.d_ptr->reply = q_dbus_message_ref(d_ptr->msg);
451     if (d_ptr->localMessage) {
452         reply.d_ptr->localMessage = true;
453         d_ptr->localReply = new QDBusMessage(reply); // keep an internal copy
454     }
455
456     // the reply must have a msg or be a local-loop optimization
457     Q_ASSERT(reply.d_ptr->reply || reply.d_ptr->localMessage);
458     return reply;
459 }
460
461 /*!
462     Constructs a new DBus message representing an error reply message,
463     with the given \a name and \a msg.
464 */
465 QDBusMessage QDBusMessage::createErrorReply(const QString name, const QString &msg) const
466 {
467     QDBusMessage reply = QDBusMessage::createError(name, msg);
468     if (d_ptr->msg)
469         reply.d_ptr->reply = q_dbus_message_ref(d_ptr->msg);
470     if (d_ptr->localMessage) {
471         reply.d_ptr->localMessage = true;
472         d_ptr->localReply = new QDBusMessage(reply); // keep an internal copy
473     }
474
475     // the reply must have a msg or be a local-loop optimization
476     Q_ASSERT(reply.d_ptr->reply || reply.d_ptr->localMessage);
477     return reply;
478 }
479
480 /*!
481    \fn QDBusMessage QDBusMessage::createReply(const QVariant &argument) const
482
483     Constructs a new DBus message representing a reply, with the
484     given \a argument.
485 */
486
487 /*!
488     \fn QDBusMessage QDBusMessage::createErrorReply(const QDBusError &error) const
489
490     Constructs a new DBus message representing an error reply message,
491     from the given \a error object.
492 */
493
494 /*!
495   \fn QDBusMessage QDBusMessage::createErrorReply(QDBusError::ErrorType type, const QString &msg) const
496
497   Constructs a new DBus reply message for the error type \a type using
498   the message \a msg. Returns the DBus message.
499 */
500 QDBusMessage QDBusMessage::createErrorReply(QDBusError::ErrorType atype, const QString &amsg) const
501 {
502     QDBusMessage msg = createErrorReply(QDBusError::errorString(atype), amsg);
503     msg.d_ptr->parametersValidated = true;
504     return msg;
505 }
506
507
508 /*!
509     Constructs an empty, invalid QDBusMessage object.
510
511     \sa createError(), createMethodCall(), createSignal()
512 */
513 QDBusMessage::QDBusMessage()
514 {
515     d_ptr = new QDBusMessagePrivate;
516 }
517
518 /*!
519     Constructs a copy of the object given by \a other.
520
521     Note: QDBusMessage objects are shared. Modifications made to the
522     copy will affect the original one as well. See setDelayedReply()
523     for more information.
524 */
525 QDBusMessage::QDBusMessage(const QDBusMessage &other)
526 {
527     d_ptr = other.d_ptr;
528     d_ptr->ref.ref();
529 }
530
531 /*!
532     Disposes of the object and frees any resources that were being held.
533 */
534 QDBusMessage::~QDBusMessage()
535 {
536     if (!d_ptr->ref.deref())
537         delete d_ptr;
538 }
539
540 /*!
541     Copies the contents of the object given by \a other.
542
543     Note: QDBusMessage objects are shared. Modifications made to the
544     copy will affect the original one as well. See setDelayedReply()
545     for more information.
546 */
547 QDBusMessage &QDBusMessage::operator=(const QDBusMessage &other)
548 {
549     qAtomicAssign(d_ptr, other.d_ptr);
550     return *this;
551 }
552
553 /*!
554     Returns the name of the service or the bus address of the remote method call.
555 */
556 QString QDBusMessage::service() const
557 {
558     return d_ptr->service;
559 }
560
561 /*!
562     Returns the path of the object that this message is being sent to (in the case of a
563     method call) or being received from (for a signal).
564 */
565 QString QDBusMessage::path() const
566 {
567     return d_ptr->path;
568 }
569
570 /*!
571     Returns the interface of the method being called (in the case of a method call) or of
572     the signal being received from.
573 */
574 QString QDBusMessage::interface() const
575 {
576     return d_ptr->interface;
577 }
578
579 /*!
580     Returns the name of the signal that was emitted or the name of the method that was called.
581 */
582 QString QDBusMessage::member() const
583 {
584     if (d_ptr->type != ErrorMessage)
585         return d_ptr->name;
586     return QString();
587 }
588
589 /*!
590     Returns the name of the error that was received.
591 */
592 QString QDBusMessage::errorName() const
593 {
594     if (d_ptr->type == ErrorMessage)
595         return d_ptr->name;
596     return QString();
597 }
598
599 /*!
600     Returns the signature of the signal that was received or for the output arguments
601     of a method call.
602 */
603 QString QDBusMessage::signature() const
604 {
605     return d_ptr->signature;
606 }
607
608 /*!
609     Returns the flag that indicates if this message should see a reply
610     or not. This is only meaningful for \l {MethodCallMessage}{method
611     call messages}: any other kind of message cannot have replies and
612     this function will always return false for them.
613 */
614 bool QDBusMessage::isReplyRequired() const
615 {
616     if (!d_ptr->msg)
617         return d_ptr->localMessage; // if it's a local message, reply is required
618     return !q_dbus_message_get_no_reply(d_ptr->msg);
619 }
620
621 /*!
622     Sets whether the message will be replied later (if \a enable is
623     true) or if an automatic reply should be generated by QtDBus
624     (if \a enable is false).
625
626     In D-Bus, all method calls must generate a reply to the caller, unless the
627     caller explicitly indicates otherwise (see isReplyRequired()). QtDBus
628     automatically generates such replies for any slots being called, but it
629     also allows slots to indicate whether they will take responsibility
630     of sending the reply at a later time, after the function has finished
631     processing.
632
633     \sa {Delayed Replies}
634 */
635 void QDBusMessage::setDelayedReply(bool enable) const
636 {
637     d_ptr->delayedReply = enable;
638 }
639
640 /*!
641     Returns the delayed reply flag, as set by setDelayedReply(). By default, this
642     flag is false, which means QtDBus will generate automatic replies
643     when necessary.
644 */
645 bool QDBusMessage::isDelayedReply() const
646 {
647     return d_ptr->delayedReply;
648 }
649
650 /*!
651     Sets the auto start flag to \a enable. This flag only makes sense
652     for method call messages, where it tells the D-Bus server to
653     either auto start the service responsible for the service name, or
654     not to auto start it.
655
656     By default this flag is true, i.e. a service is autostarted.
657     This means:
658
659     When the service that this method call is sent to is already
660     running, the method call is sent to it. If the service is not
661     running yet, the D-Bus daemon is requested to autostart the
662     service that is assigned to this service name. This is
663     handled by .service files that are placed in a directory known
664     to the D-Bus server. These files then each contain a service
665     name and the path to a program that should be executed when
666     this service name is requested.
667
668     \since 4.7
669 */
670 void QDBusMessage::setAutoStartService(bool enable)
671 {
672     d_ptr->autoStartService = enable;
673 }
674
675 /*!
676     Returns the auto start flag, as set by setAutoStartService(). By default, this
677     flag is true, which means QtDBus will auto start a service, if it is
678     not running already.
679
680     \sa setAutoStartService()
681
682     \since 4.7
683 */
684 bool QDBusMessage::autoStartService() const
685 {
686     return d_ptr->autoStartService;
687 }
688
689 /*!
690     Sets the arguments that are going to be sent over D-Bus to \a arguments. Those
691     will be the arguments to a method call or the parameters in the signal.
692
693     \sa arguments()
694 */
695 void QDBusMessage::setArguments(const QList<QVariant> &arguments)
696 {
697     // FIXME: should we detach?
698     d_ptr->arguments = arguments;
699 }
700
701 /*!
702     Returns the list of arguments that are going to be sent or were received from
703     D-Bus.
704 */
705 QList<QVariant> QDBusMessage::arguments() const
706 {
707     return d_ptr->arguments;
708 }
709
710 /*!
711     Appends the argument \a arg to the list of arguments to be sent over D-Bus in
712     a method call or signal emission.
713 */
714
715 QDBusMessage &QDBusMessage::operator<<(const QVariant &arg)
716 {
717     // FIXME: should we detach?
718     d_ptr->arguments.append(arg);
719     return *this;
720 }
721
722 /*!
723     Returns the message type.
724 */
725 QDBusMessage::MessageType QDBusMessage::type() const
726 {
727     switch (d_ptr->type) {
728     case DBUS_MESSAGE_TYPE_METHOD_CALL:
729         return MethodCallMessage;
730     case DBUS_MESSAGE_TYPE_METHOD_RETURN:
731         return ReplyMessage;
732     case DBUS_MESSAGE_TYPE_ERROR:
733         return ErrorMessage;
734     case DBUS_MESSAGE_TYPE_SIGNAL:
735         return SignalMessage;
736     default:
737         break;
738     }
739     return InvalidMessage;
740 }
741
742 /*!
743     Sends the message without waiting for a reply. This is suitable
744     for errors, signals, and return values as well as calls whose
745     return values are not necessary.
746
747     Returns true if the message was queued successfully;
748     otherwise returns false.
749
750     \sa QDBusConnection::send()
751 */
752 #ifndef QT_NO_DEBUG_STREAM
753 static QDebug operator<<(QDebug dbg, QDBusMessage::MessageType t)
754 {
755     switch (t)
756     {
757     case QDBusMessage::MethodCallMessage:
758         return dbg << "MethodCall";
759     case QDBusMessage::ReplyMessage:
760         return dbg << "MethodReturn";
761     case QDBusMessage::SignalMessage:
762         return dbg << "Signal";
763     case QDBusMessage::ErrorMessage:
764         return dbg << "Error";
765     default:
766         return dbg << "Invalid";
767     }
768 }
769
770 static void debugVariantList(QDebug dbg, const QVariantList &list)
771 {
772     bool first = true;
773     QVariantList::ConstIterator it = list.constBegin();
774     QVariantList::ConstIterator end = list.constEnd();
775     for ( ; it != end; ++it) {
776         if (!first)
777             dbg.nospace() << ", ";
778         dbg.nospace() << qPrintable(QDBusUtil::argumentToString(*it));
779         first = false;
780     }
781 }
782
783 QDebug operator<<(QDebug dbg, const QDBusMessage &msg)
784 {
785     dbg.nospace() << "QDBusMessage(type=" << msg.type()
786                   << ", service=" << msg.service();
787     if (msg.type() == QDBusMessage::MethodCallMessage ||
788         msg.type() == QDBusMessage::SignalMessage)
789         dbg.nospace() << ", path=" << msg.path()
790                       << ", interface=" << msg.interface()
791                       << ", member=" << msg.member();
792     if (msg.type() == QDBusMessage::ErrorMessage)
793         dbg.nospace() << ", error name=" << msg.errorName()
794                       << ", error message=" << msg.errorMessage();
795     dbg.nospace() << ", signature=" << msg.signature()
796                   << ", contents=(";
797     debugVariantList(dbg, msg.arguments());
798     dbg.nospace() << ") )";
799     return dbg.space();
800 }
801 #endif
802
803 QT_END_NAMESPACE
804
805 #endif // QT_NO_DBUS