1/****************************************************************************
2**
3** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4** Contact: http://www.qt-project.org/legal
5**
6** This file is part of the QtDBus module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Digia. For licensing terms and
14** conditions see http://qt.digia.com/licensing. For further information
15** use the contact form at http://qt.digia.com/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 2.1 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 2.1 requirements
23** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24**
25** In addition, as a special exception, Digia gives you certain additional
26** rights. These rights are described in the Digia Qt LGPL Exception
27** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28**
29** GNU General Public License Usage
30** Alternatively, this file may be used under the terms of the GNU
31** General Public License version 3.0 as published by the Free Software
32** Foundation and appearing in the file LICENSE.GPL included in the
33** packaging of this file. Please review the following information to
34** ensure the GNU General Public License version 3.0 requirements will be
35** met: http://www.gnu.org/copyleft/gpl.html.
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
58QT_BEGIN_NAMESPACE
59
60static inline const char *data(const QByteArray &arr)
61{
62 return arr.isEmpty() ? 0 : arr.constData();
63}
64
65QDBusMessagePrivate::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
72QDBusMessagePrivate::~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*/
85QString 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*/
105DBusMessage *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/*
202struct DBusMessage
203{
204 DBusAtomic refcount;
205 DBusHeader header;
206 DBusString body;
207 char byte_order;
208 unsigned int locked : 1;
209DBUS_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*/
226QDBusMessage 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
250bool QDBusMessagePrivate::isLocal(const QDBusMessage &message)
251{
252 return message.d_ptr->localMessage;
253}
254
255QDBusMessage 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
312QDBusMessage 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 \o Method calls
335 \o Method return values
336 \o Signal emissions
337 \o 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*/
367QDBusMessage 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 QDBusObject and QDBusInterface classes provide 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*/
398QDBusMessage 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*/
415QDBusMessage 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*/
444QDBusMessage 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*/
465QDBusMessage 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*/
500QDBusMessage 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*/
513QDBusMessage::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*/
525QDBusMessage::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*/
534QDBusMessage::~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*/
547QDBusMessage &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*/
556QString 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*/
565QString 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*/
574QString 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*/
582QString 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*/
592QString 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*/
603QString 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*/
614bool 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*/
635void 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*/
645bool 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*/
670void 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*/
684bool 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*/
695void 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*/
705QList<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
715QDBusMessage &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*/
725QDBusMessage::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
753static 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
770static 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
783QDebug 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
803QT_END_NAMESPACE
804
805#endif // QT_NO_DBUS
806