1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
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 The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/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 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "qdbusargument.h"
41#include "qdbusargument_p.h"
42
43#include <qatomic.h>
44#include <qbytearray.h>
45#include <qlist.h>
46#include <qmap.h>
47#include <qstring.h>
48#include <qstringlist.h>
49#include <qvariant.h>
50#include <qdatetime.h>
51#include <qrect.h>
52#include <qline.h>
53
54#include "qdbusmetatype_p.h"
55#include "qdbusutil_p.h"
56
57#ifndef QT_NO_DBUS
58
59QT_BEGIN_NAMESPACE
60
61QDBusArgumentPrivate::~QDBusArgumentPrivate()
62{
63 if (message)
64 q_dbus_message_unref(message);
65}
66
67QByteArray QDBusArgumentPrivate::createSignature(int id)
68{
69 if (!qdbus_loadLibDBus())
70 return "";
71
72 QByteArray signature;
73 QDBusMarshaller *marshaller = new QDBusMarshaller(0);
74 marshaller->ba = &signature;
75
76 // run it
77 QVariant v{QMetaType(id)};
78 QDBusArgument arg(marshaller);
79 QDBusMetaType::marshall(arg, v.metaType(), v.constData());
80 arg.d = nullptr;
81
82 // delete it
83 bool ok = marshaller->ok;
84 delete marshaller;
85
86 if (signature.isEmpty() || !ok || !QDBusUtil::isValidSingleSignature(QString::fromLatin1(signature))) {
87 qWarning("QDBusMarshaller: type `%s' produces invalid D-BUS signature `%s' "
88 "(Did you forget to call beginStructure() ?)",
89 QMetaType(id).name(),
90 signature.isEmpty() ? "<empty>" : signature.constData());
91 return "";
92 } else if ((signature.at(0) != DBUS_TYPE_ARRAY && signature.at(0) != DBUS_STRUCT_BEGIN_CHAR) ||
93 (signature.at(0) == DBUS_TYPE_ARRAY && (signature.at(1) == DBUS_TYPE_BYTE ||
94 signature.at(1) == DBUS_TYPE_STRING))) {
95 qWarning("QDBusMarshaller: type `%s' attempts to redefine basic D-BUS type '%s' (%s) "
96 "(Did you forget to call beginStructure() ?)",
97 QMetaType(id).name(),
98 signature.constData(),
99 QDBusMetaType::signatureToMetaType(signature).name());
100 return "";
101 }
102 return signature;
103}
104
105bool QDBusArgumentPrivate::checkWrite(QDBusArgumentPrivate *&d)
106{
107 if (!d)
108 return false;
109 if (d->direction == Marshalling) {
110 if (!d->marshaller()->ok)
111 return false;
112
113 if (d->message && d->ref.loadRelaxed() != 1) {
114 QDBusMarshaller *dd = new QDBusMarshaller(d->capabilities);
115 dd->message = q_dbus_message_copy(d->message);
116 q_dbus_message_iter_init_append(dd->message, &dd->iterator);
117
118 if (!d->ref.deref())
119 delete d;
120 d = dd;
121 }
122 return true;
123 }
124
125#ifdef QT_DEBUG
126 qFatal("QDBusArgument: write from a read-only object");
127#else
128 qWarning("QDBusArgument: write from a read-only object");
129#endif
130 return false;
131}
132
133bool QDBusArgumentPrivate::checkRead(QDBusArgumentPrivate *d)
134{
135 if (!d)
136 return false;
137 if (d->direction == Demarshalling)
138 return true;
139
140#ifdef QT_DEBUG
141 qFatal("QDBusArgument: read from a write-only object");
142#else
143 qWarning("QDBusArgument: read from a write-only object");
144#endif
145
146 return false;
147}
148
149bool QDBusArgumentPrivate::checkReadAndDetach(QDBusArgumentPrivate *&d)
150{
151 if (!checkRead(d))
152 return false; // don't bother
153
154 if (d->ref.loadRelaxed() == 1)
155 return true; // no need to detach
156
157 QDBusDemarshaller *dd = new QDBusDemarshaller(d->capabilities);
158 dd->message = q_dbus_message_ref(d->message);
159 dd->iterator = static_cast<QDBusDemarshaller*>(d)->iterator;
160
161 if (!d->ref.deref())
162 delete d;
163 d = dd;
164 return true;
165}
166
167/*!
168 \class QDBusArgument
169 \inmodule QtDBus
170 \since 4.2
171
172 \brief The QDBusArgument class is used to marshall and demarshall D-Bus arguments.
173
174 The class is used to send arguments over D-Bus to remote
175 applications and to receive them back. D-Bus offers an extensible
176 type system, based on a few primitive types and associations of
177 them. See the \l {qdbustypesystem.html}{Qt D-Bus Type System} page
178 for more information on the type system.
179
180 QDBusArgument is the central class in the Qt D-Bus type system,
181 providing functions to marshall and demarshall the primitive
182 types. The compound types are then created by association of one
183 or more of the primitive types in arrays, dictionaries or
184 structures.
185
186 The following example illustrates how a structure containing an
187 integer and a string can be constructed using the \l
188 {qdbustypesystem.html}{Qt D-Bus type system}:
189
190 \snippet code/src_qdbus_qdbusargument.cpp 0-0
191 \codeline
192 \snippet code/src_qdbus_qdbusargument.cpp 0-1
193
194 The type has to be registered with qDBusRegisterMetaType() before
195 it can be used with QDBusArgument. Therefore, somewhere in your
196 program, you should add the following code:
197
198 \snippet code/src_qdbus_qdbusargument.cpp 1
199
200 Once registered, a type can be used in outgoing method calls
201 (placed with QDBusAbstractInterface::call()), signal emissions
202 from registered objects or in incoming calls from remote
203 applications.
204
205 It is important to note that the \c{operator<<} and \c{operator>>}
206 streaming functions must always produce the same number of entries
207 in case of structures, both in reading and in writing (marshalling
208 and demarshalling), otherwise calls and signals may start to
209 silently fail.
210
211 The following example illustrates this wrong usage
212 in context of a class that may contain invalid data:
213
214 \code
215 //bad code
216 // Wrongly marshall the MyTime data into a D-Bus argument
217 QDBusArgument &operator<<(QDBusArgument &argument, const MyTime &mytime)
218 {
219 argument.beginStructure();
220 if (mytime.isValid)
221 argument << true << mytime.hour
222 << mytime.minute << mytime.second;
223 else
224 argument << false;
225 argument.endStructure();
226 return argument;
227 }
228 \endcode
229
230 In this example, both the \c{operator<<} and the \c{operator>>}
231 functions may produce a different number of reads/writes. This can
232 confuse the Qt D-Bus type system and should be avoided.
233
234 \sa QDBusAbstractInterface, {qdbustypesystem.html}{The Qt D-Bus type
235 system}, {usingadaptors.html}{Using Adaptors}, qdbus_cast()
236*/
237
238/*!
239 \enum QDBusArgument::ElementType
240 \since 4.5
241
242 This enum describes the type of element held by the argument.
243
244 \value BasicType A basic element, which is understood by
245 QVariant. The following types are considered basic: bool,
246 byte, short, ushort, int, uint, qint64, quint64, double,
247 QString, QByteArray, QDBusObjectPath, QDBusSignature
248
249 \value VariantType The variant element (QDBusVariant)
250
251 \value ArrayType An array element, usually represented by QList<T>.
252 Note: QByteArray and associative maps are not
253 considered arrays, even if the D-Bus protocol transports them as such.
254
255 \value StructureType A custom type represented by a structure,
256 like QDateTime, QPoint, etc.
257
258 \value MapType An associative container, like QMap<Key, Value> or
259 QHash<Key, Value>
260
261 \value MapEntryType One entry in an associative container: both
262 the key and the value form one map-entry type.
263
264 \value UnknownType The type is unknown or we have reached the end
265 of the list.
266
267 \sa currentType()
268*/
269
270/*!
271 \fn template<typename T> T qdbus_cast(const QDBusArgument &arg)
272 \relates QDBusArgument
273 \since 4.2
274
275 Attempts to demarshall the contents of \a arg into the type
276 \c{T}. For example:
277
278 \snippet code/src_qdbus_qdbusargument.cpp 2
279
280 Note that it is equivalent to the following:
281
282 \snippet code/src_qdbus_qdbusargument.cpp 3
283*/
284
285/*!
286 Constructs an empty QDBusArgument argument.
287
288 An empty QDBusArgument object does not allow either reading or
289 writing to be performed.
290*/
291QDBusArgument::QDBusArgument()
292{
293 if (!qdbus_loadLibDBus()) {
294 d = nullptr;
295 return;
296 }
297
298 QDBusMarshaller *dd = new QDBusMarshaller(0);
299 d = dd;
300
301 // create a new message with any type, we won't sent it anyways
302 dd->message = q_dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_CALL);
303 q_dbus_message_iter_init_append(dd->message, &dd->iterator);
304}
305
306/*!
307 Constructs a copy of the \a other QDBusArgument object.
308
309 Both objects will therefore contain the same state from this point
310 forward. QDBusArguments are explicitly shared and, therefore, any
311 modification to either copy will affect the other one too.
312*/
313QDBusArgument::QDBusArgument(const QDBusArgument &other)
314 : d(other.d)
315{
316 if (d)
317 d->ref.ref();
318}
319
320/*!
321 \internal
322*/
323QDBusArgument::QDBusArgument(QDBusArgumentPrivate *dd)
324 : d(dd)
325{
326}
327
328/*!
329 Copies the \a other QDBusArgument object into this one.
330
331 Both objects will therefore contain the same state from this point
332 forward. QDBusArguments are explicitly shared and, therefore, any
333 modification to either copy will affect the other one too.
334*/
335QDBusArgument &QDBusArgument::operator=(const QDBusArgument &other)
336{
337 qAtomicAssign(d, other.d);
338 return *this;
339}
340
341/*!
342 Disposes of the resources associated with this QDBusArgument
343 object.
344*/
345QDBusArgument::~QDBusArgument()
346{
347 if (d && !d->ref.deref())
348 delete d;
349}
350
351/*!
352 Appends the primitive value \a arg of type \c{BYTE} to the D-Bus stream.
353*/
354QDBusArgument &QDBusArgument::operator<<(uchar arg)
355{
356 if (QDBusArgumentPrivate::checkWrite(d))
357 d->marshaller()->append(arg);
358 return *this;
359}
360
361/*!
362 \overload
363 Appends the primitive value \a arg of type \c{BOOLEAN} to the D-Bus stream.
364*/
365QDBusArgument &QDBusArgument::operator<<(bool arg)
366{
367 if (QDBusArgumentPrivate::checkWrite(d))
368 d->marshaller()->append(arg);
369 return *this;
370}
371
372/*!
373 \overload
374 Appends the primitive value \a arg of type \c{INT16} to the D-Bus stream.
375*/
376QDBusArgument &QDBusArgument::operator<<(short arg)
377{
378 if (QDBusArgumentPrivate::checkWrite(d))
379 d->marshaller()->append(arg);
380 return *this;
381}
382
383/*!
384 \overload
385 Appends the primitive value \a arg of type \c{UINT16} to the D-Bus stream.
386*/
387QDBusArgument &QDBusArgument::operator<<(ushort arg)
388{
389 if (QDBusArgumentPrivate::checkWrite(d))
390 d->marshaller()->append(arg);
391 return *this;
392}
393
394/*!
395 \overload
396 Appends the primitive value \a arg of type \c{INT32} to the D-Bus stream.
397*/
398QDBusArgument &QDBusArgument::operator<<(int arg)
399{
400 if (QDBusArgumentPrivate::checkWrite(d))
401 d->marshaller()->append(arg);
402 return *this;
403}
404
405/*!
406 \overload
407 Appends the primitive value \a arg of type \c{UINT32} to the D-Bus stream.
408*/
409QDBusArgument &QDBusArgument::operator<<(uint arg)
410{
411 if (QDBusArgumentPrivate::checkWrite(d))
412 d->marshaller()->append(arg);
413 return *this;
414}
415
416/*!
417 \overload
418 Appends the primitive value \a arg of type \c{INT64} to the D-Bus stream.
419*/
420QDBusArgument &QDBusArgument::operator<<(qlonglong arg)
421{
422 if (QDBusArgumentPrivate::checkWrite(d))
423 d->marshaller()->append(arg);
424 return *this;
425}
426
427/*!
428 \overload
429 Appends the primitive value \a arg of type \c{UINT64} to the D-Bus stream.
430*/
431QDBusArgument &QDBusArgument::operator<<(qulonglong arg)
432{
433 if (QDBusArgumentPrivate::checkWrite(d))
434 d->marshaller()->append(arg);
435 return *this;
436}
437
438/*!
439 \overload
440 Appends the primitive value \a arg of type \c{DOUBLE} (double-precision
441 floating-point) to the D-Bus stream.
442*/
443QDBusArgument &QDBusArgument::operator<<(double arg)
444{
445 if (QDBusArgumentPrivate::checkWrite(d))
446 d->marshaller()->append(arg);
447 return *this;
448}
449
450/*!
451 \overload
452 Appends the primitive value \a arg of type \c{STRING} (Unicode character
453 string) to the D-Bus stream.
454*/
455QDBusArgument &QDBusArgument::operator<<(const QString &arg)
456{
457 if (QDBusArgumentPrivate::checkWrite(d))
458 d->marshaller()->append(arg);
459 return *this;
460}
461
462/*!
463 \overload
464 \internal
465 Appends the primitive value \a arg of type \c{OBJECT_PATH} (path to a D-Bus
466 object) to the D-Bus stream.
467*/
468QDBusArgument &QDBusArgument::operator<<(const QDBusObjectPath &arg)
469{
470 if (QDBusArgumentPrivate::checkWrite(d))
471 d->marshaller()->append(arg);
472 return *this;
473}
474
475/*!
476 \overload
477 \internal
478 Appends the primitive value \a arg of type \c{SIGNATURE} (D-Bus type
479 signature) to the D-Bus stream.
480*/
481QDBusArgument &QDBusArgument::operator<<(const QDBusSignature &arg)
482{
483 if (QDBusArgumentPrivate::checkWrite(d))
484 d->marshaller()->append(arg);
485 return *this;
486}
487
488/*!
489 \overload
490 \since 4.8
491 \internal
492 Appends the primitive value \a arg of type \c{UNIX_FILE_DESCRIPTOR} (Unix
493 File Descriptor) to the D-Bus stream.
494*/
495QDBusArgument &QDBusArgument::operator<<(const QDBusUnixFileDescriptor &arg)
496{
497 if (QDBusArgumentPrivate::checkWrite(d))
498 d->marshaller()->append(arg);
499 return *this;
500}
501
502/*!
503 \overload
504 Appends the primitive value \a arg of type \c{VARIANT} to the D-Bus stream.
505
506 A D-Bus variant type can contain any type, including other
507 variants. It is similar to the Qt QVariant type.
508*/
509QDBusArgument &QDBusArgument::operator<<(const QDBusVariant &arg)
510{
511 if (QDBusArgumentPrivate::checkWrite(d))
512 d->marshaller()->append(arg);
513 return *this;
514}
515
516/*!
517 \overload
518 Appends the QStringList given by \a arg as \c{ARRAY of STRING}
519 to the D-Bus stream.
520
521 QStringList and QByteArray are the only two non-primitive types
522 that are supported directly by QDBusArgument because of their
523 widespread usage in Qt applications.
524
525 Other arrays are supported through compound types in Qt D-Bus.
526*/
527QDBusArgument &QDBusArgument::operator<<(const QStringList &arg)
528{
529 if (QDBusArgumentPrivate::checkWrite(d))
530 d->marshaller()->append(arg);
531 return *this;
532}
533
534/*!
535 \overload
536 Appends the QByteArray given by \a arg as \c{ARRAY of BYTE}
537 to the D-Bus stream.
538
539 QStringList and QByteArray are the only two non-primitive types
540 that are supported directly by QDBusArgument because of their
541 widespread usage in Qt applications.
542
543 Other arrays are supported through compound types in Qt D-Bus.
544*/
545QDBusArgument &QDBusArgument::operator<<(const QByteArray &arg)
546{
547 if (QDBusArgumentPrivate::checkWrite(d))
548 d->marshaller()->append(arg);
549 return *this;
550}
551
552/*!
553 \internal
554 \since 4.5
555
556 Appends the variant \a v.
557
558 \sa asVariant()
559*/
560void QDBusArgument::appendVariant(const QVariant &v)
561{
562 if (QDBusArgumentPrivate::checkWrite(d))
563 d->marshaller()->appendVariantInternal(v);
564}
565
566/*!
567 \internal
568 Returns the type signature of the D-Bus type this QDBusArgument
569 object is currently pointing to.
570*/
571QString QDBusArgument::currentSignature() const
572{
573 if (!d)
574 return QString();
575 if (d->direction == QDBusArgumentPrivate::Demarshalling)
576 return d->demarshaller()->currentSignature();
577 else
578 return d->marshaller()->currentSignature();
579}
580
581/*!
582 \since 4.5
583 Returns the classification of the current element type. If an
584 error decoding the type occurs or if we're at the end of the
585 argument, this function returns QDBusArgument::UnknownType.
586
587 This function only makes sense when demarshalling arguments. If it
588 is used while marshalling, it will always return UnknownType.
589*/
590QDBusArgument::ElementType QDBusArgument::currentType() const
591{
592 if (!d)
593 return UnknownType;
594 if (d->direction == QDBusArgumentPrivate::Demarshalling)
595 return d->demarshaller()->currentType();
596 return UnknownType;
597}
598
599/*!
600 Extracts one D-BUS primitive argument of type \c{BYTE} from the
601 D-BUS stream and puts it into \a arg.
602*/
603const QDBusArgument &QDBusArgument::operator>>(uchar &arg) const
604{
605 if (QDBusArgumentPrivate::checkReadAndDetach(d))
606 arg = d->demarshaller()->toByte();
607 else
608 arg = 0;
609 return *this;
610}
611
612/*!
613 \overload
614 Extracts one D-Bus primitive argument of type \c{BOOLEAN} from the
615 D-Bus stream.
616*/
617const QDBusArgument &QDBusArgument::operator>>(bool &arg) const
618{
619 if (QDBusArgumentPrivate::checkReadAndDetach(d))
620 arg = d->demarshaller()->toBool();
621 else
622 arg = false;
623 return *this;
624}
625
626/*!
627 \overload
628 Extracts one D-Bus primitive argument of type \c{UINT16} from the
629 D-Bus stream.
630*/
631const QDBusArgument &QDBusArgument::operator>>(ushort &arg) const
632{
633 if (QDBusArgumentPrivate::checkReadAndDetach(d))
634 arg = d->demarshaller()->toUShort();
635 else
636 arg = 0;
637 return *this;
638}
639
640/*!
641 \overload
642 Extracts one D-Bus primitive argument of type \c{INT16} from the
643 D-Bus stream.
644*/
645const QDBusArgument &QDBusArgument::operator>>(short &arg) const
646{
647 if (QDBusArgumentPrivate::checkReadAndDetach(d))
648 arg = d->demarshaller()->toShort();
649 else
650 arg = 0;
651 return *this;
652}
653
654/*!
655 \overload
656 Extracts one D-Bus primitive argument of type \c{INT32} from the
657 D-Bus stream.
658*/
659const QDBusArgument &QDBusArgument::operator>>(int &arg) const
660{
661 if (QDBusArgumentPrivate::checkReadAndDetach(d))
662 arg = d->demarshaller()->toInt();
663 else
664 arg = 0;
665 return *this;
666}
667
668/*!
669 \overload
670 Extracts one D-Bus primitive argument of type \c{UINT32} from the
671 D-Bus stream.
672*/
673const QDBusArgument &QDBusArgument::operator>>(uint &arg) const
674{
675 if (QDBusArgumentPrivate::checkReadAndDetach(d))
676 arg = d->demarshaller()->toUInt();
677 else
678 arg = 0;
679 return *this;
680}
681
682/*!
683 \overload
684 Extracts one D-Bus primitive argument of type \c{INT64} from the
685 D-Bus stream.
686*/
687const QDBusArgument &QDBusArgument::operator>>(qlonglong &arg) const
688{
689 if (QDBusArgumentPrivate::checkReadAndDetach(d))
690 arg = d->demarshaller()->toLongLong();
691 else
692 arg = 0;
693 return *this;
694}
695
696/*!
697 \overload
698 Extracts one D-Bus primitive argument of type \c{UINT64} from the
699 D-Bus stream.
700*/
701const QDBusArgument &QDBusArgument::operator>>(qulonglong &arg) const
702{
703 if (QDBusArgumentPrivate::checkReadAndDetach(d))
704 arg = d->demarshaller()->toULongLong();
705 else
706 arg = 0;
707 return *this;
708}
709
710/*!
711 \overload
712 Extracts one D-Bus primitive argument of type \c{DOUBLE}
713 (double-precision floating pount) from the D-Bus stream.
714*/
715const QDBusArgument &QDBusArgument::operator>>(double &arg) const
716{
717 if (QDBusArgumentPrivate::checkReadAndDetach(d))
718 arg = d->demarshaller()->toDouble();
719 else
720 arg = 0;
721 return *this;
722}
723
724/*!
725 \overload
726 Extracts one D-Bus primitive argument of type \c{STRING} (Unicode
727 character string) from the D-Bus stream.
728*/
729const QDBusArgument &QDBusArgument::operator>>(QString &arg) const
730{
731 if (QDBusArgumentPrivate::checkReadAndDetach(d))
732 arg = d->demarshaller()->toString();
733 return *this;
734}
735
736/*!
737 \overload
738 \internal
739 Extracts one D-Bus primitive argument of type \c{OBJECT_PATH}
740 (D-Bus path to an object) from the D-Bus stream.
741*/
742const QDBusArgument &QDBusArgument::operator>>(QDBusObjectPath &arg) const
743{
744 if (QDBusArgumentPrivate::checkReadAndDetach(d))
745 arg = d->demarshaller()->toObjectPath();
746 return *this;
747}
748
749/*!
750 \overload
751 \internal
752 Extracts one D-Bus primitive argument of type \c{SIGNATURE} (D-Bus
753 type signature) from the D-Bus stream.
754*/
755const QDBusArgument &QDBusArgument::operator>>(QDBusSignature &arg) const
756{
757 if (QDBusArgumentPrivate::checkReadAndDetach(d))
758 arg = d->demarshaller()->toSignature();
759 return *this;
760}
761
762/*!
763 \overload
764 \since 4.8
765 \internal
766 Extracts one D-Bus primitive argument of type \c{UNIX_FILE_DESCRIPTOR}
767 (Unix file descriptor) from the D-Bus stream.
768*/
769const QDBusArgument &QDBusArgument::operator>>(QDBusUnixFileDescriptor &arg) const
770{
771 if (QDBusArgumentPrivate::checkReadAndDetach(d))
772 arg = d->demarshaller()->toUnixFileDescriptor();
773 return *this;
774}
775
776/*!
777 \overload
778 Extracts one D-Bus primitive argument of type \c{VARIANT} from the
779 D-Bus stream.
780
781 A D-Bus variant type can contain any type, including other
782 variants. It is similar to the Qt QVariant type.
783
784 In case the variant contains a type not directly supported by
785 QDBusArgument, the value of the returned QDBusVariant will contain
786 another QDBusArgument. It is your responsibility to further
787 demarshall it into another type.
788*/
789const QDBusArgument &QDBusArgument::operator>>(QDBusVariant &arg) const
790{
791 if (QDBusArgumentPrivate::checkReadAndDetach(d))
792 arg = d->demarshaller()->toVariant();
793 return *this;
794}
795
796/*!
797 \overload
798 Extracts an array of strings from the D-Bus stream and return it
799 as a QStringList.
800
801 QStringList and QByteArray are the only two non-primitive types
802 that are supported directly by QDBusArgument because of their
803 widespread usage in Qt applications.
804
805 Other arrays are supported through compound types in Qt D-Bus.
806*/
807const QDBusArgument &QDBusArgument::operator>>(QStringList &arg) const
808{
809 if (QDBusArgumentPrivate::checkReadAndDetach(d))
810 arg = d->demarshaller()->toStringList();
811 return *this;
812}
813
814/*!
815 \overload
816 Extracts an array of bytes from the D-Bus stream and return it
817 as a QByteArray.
818
819 QStringList and QByteArray are the only two non-primitive types
820 that are supported directly by QDBusArgument because of their
821 widespread usage in Qt applications.
822
823 Other arrays are supported through compound types in Qt D-Bus.
824*/
825const QDBusArgument &QDBusArgument::operator>>(QByteArray &arg) const
826{
827 if (QDBusArgumentPrivate::checkReadAndDetach(d))
828 arg = d->demarshaller()->toByteArray();
829 return *this;
830}
831
832/*!
833 Opens a new D-Bus structure suitable for appending new arguments.
834
835 This function is used usually in \c{operator<<} streaming
836 operators, as in the following example:
837
838 \snippet code/src_qdbus_qdbusargument.cpp 4
839
840 Structures can contain other structures, so the following code is
841 also valid:
842
843 \snippet code/src_qdbus_qdbusargument.cpp 5
844
845 \sa endStructure(), beginArray(), beginMap()
846*/
847void QDBusArgument::beginStructure()
848{
849 if (QDBusArgumentPrivate::checkWrite(d))
850 d = d->marshaller()->beginStructure();
851}
852
853/*!
854 Closes a D-Bus structure opened with beginStructure(). This function must be called
855 same number of times that beginStructure() is called.
856
857 \sa beginStructure(), endArray(), endMap()
858*/
859void QDBusArgument::endStructure()
860{
861 if (QDBusArgumentPrivate::checkWrite(d))
862 d = d->marshaller()->endStructure();
863}
864
865/*!
866 Opens a new D-Bus array suitable for appending elements of meta-type \a id.
867
868 This function is used usually in \c{operator<<} streaming
869 operators, as in the following example:
870
871 \snippet code/src_qdbus_qdbusargument.cpp 6
872
873 If the type you want to marshall is a QList or any of the
874 Qt's \l {Container Classes} that take one template parameter,
875 you need not declare an \c{operator<<} function for it, since
876 Qt D-Bus provides generic templates to do the job of marshalling
877 the data. The same applies for STL's sequence containers, such
878 as \c {std::list}, \c {std::vector}, etc.
879
880 \sa endArray(), beginStructure(), beginMap()
881*/
882void QDBusArgument::beginArray(QMetaType id)
883{
884 if (QDBusArgumentPrivate::checkWrite(d))
885 d = d->marshaller()->beginArray(id);
886}
887
888/*!
889 Closes a D-Bus array opened with beginArray(). This function must be called
890 same number of times that beginArray() is called.
891
892 \sa beginArray(), endStructure(), endMap()
893*/
894void QDBusArgument::endArray()
895{
896 if (QDBusArgumentPrivate::checkWrite(d))
897 d = d->marshaller()->endArray();
898}
899
900/*!
901 Opens a new D-Bus map suitable for
902 appending elements. Maps are containers that associate one entry
903 (the key) to another (the value), such as Qt's QMap or QHash. The
904 ids of the map's key and value meta types must be passed in \a keyMetaType
905 and \a valueMetaType respectively.
906
907 This function is used usually in \c{operator<<} streaming
908 operators, as in the following example:
909
910 \snippet code/src_qdbus_qdbusargument.cpp 7
911
912 You usually don't need to provide an \c{operator<<} or \c{operator>>}
913 function for associative containers such as QHash or std::map,
914 since Qt D-Bus provides generic templates to do the job of marshalling
915 the data.
916
917 \sa endMap(), beginStructure(), beginArray(), beginMapEntry()
918*/
919void QDBusArgument::beginMap(QMetaType keyMetaType, QMetaType valueMetaType)
920{
921 if (QDBusArgumentPrivate::checkWrite(d))
922 d = d->marshaller()->beginMap(keyMetaType, valueMetaType);
923}
924
925/*!
926 Closes a D-Bus map opened with beginMap(). This function must be called
927 same number of times that beginMap() is called.
928
929 \sa beginMap(), endStructure(), endArray()
930*/
931void QDBusArgument::endMap()
932{
933 if (QDBusArgumentPrivate::checkWrite(d))
934 d = d->marshaller()->endMap();
935}
936
937/*!
938 Opens a D-Bus map entry suitable for
939 appending the key and value entries. This function is only valid
940 when a map has been opened with beginMap().
941
942 See beginMap() for an example of usage of this function.
943
944 \sa endMapEntry(), beginMap()
945*/
946void QDBusArgument::beginMapEntry()
947{
948 if (QDBusArgumentPrivate::checkWrite(d))
949 d = d->marshaller()->beginMapEntry();
950}
951
952/*!
953 Closes a D-Bus map entry opened with beginMapEntry(). This function must be called
954 same number of times that beginMapEntry() is called.
955
956 \sa beginMapEntry()
957*/
958void QDBusArgument::endMapEntry()
959{
960 if (QDBusArgumentPrivate::checkWrite(d))
961 d = d->marshaller()->endMapEntry();
962}
963
964/*!
965 Opens a D-Bus structure suitable for extracting elements.
966
967 This function is used usually in \c{operator>>} streaming
968 operators, as in the following example:
969
970 \snippet code/src_qdbus_qdbusargument.cpp 8
971
972 \sa endStructure(), beginArray(), beginMap()
973*/
974void QDBusArgument::beginStructure() const
975{
976 if (QDBusArgumentPrivate::checkReadAndDetach(d))
977 d = d->demarshaller()->beginStructure();
978}
979
980/*!
981 Closes the D-Bus structure and allow extracting of the next element
982 after the structure.
983
984 \sa beginStructure()
985*/
986void QDBusArgument::endStructure() const
987{
988 if (QDBusArgumentPrivate::checkReadAndDetach(d))
989 d = d->demarshaller()->endStructure();
990}
991
992/*!
993 Recurses into the D-Bus array to allow extraction of
994 the array elements.
995
996 This function is used usually in \c{operator>>} streaming
997 operators, as in the following example:
998
999 \snippet code/src_qdbus_qdbusargument.cpp 9
1000
1001 If the type you want to demarshall is a QList or any of the
1002 Qt's \l {Container Classes} that take one template parameter, you
1003 need not declare an \c{operator>>} function for it, since Qt D-Bus
1004 provides generic templates to do the job of demarshalling the data.
1005 The same applies for STL's sequence containers, such as \c {std::list},
1006 \c {std::vector}, etc.
1007
1008 \sa atEnd(), beginStructure(), beginMap()
1009*/
1010void QDBusArgument::beginArray() const
1011{
1012 if (QDBusArgumentPrivate::checkReadAndDetach(d))
1013 d = d->demarshaller()->beginArray();
1014}
1015
1016/*!
1017 Closes the D-Bus array and allow extracting of the next element
1018 after the array.
1019
1020 \sa beginArray()
1021*/
1022void QDBusArgument::endArray() const
1023{
1024 if (QDBusArgumentPrivate::checkReadAndDetach(d))
1025 d = d->demarshaller()->endArray();
1026}
1027
1028/*!
1029 Recurses into the D-Bus map to allow extraction of
1030 the map's elements.
1031
1032 This function is used usually in \c{operator>>} streaming
1033 operators, as in the following example:
1034
1035 \snippet code/src_qdbus_qdbusargument.cpp 10
1036
1037 If the type you want to demarshall is a QMap or QHash, you need not
1038 declare an \c{operator>>} function for it, since Qt D-Bus provides
1039 generic templates to do the job of demarshalling the data.
1040
1041 \sa endMap(), beginStructure(), beginArray(), beginMapEntry()
1042*/
1043void QDBusArgument::beginMap() const
1044{
1045 if (QDBusArgumentPrivate::checkReadAndDetach(d))
1046 d = d->demarshaller()->beginMap();
1047}
1048
1049/*!
1050 Closes the D-Bus map and allow extracting of the next element
1051 after the map.
1052
1053 \sa beginMap()
1054*/
1055void QDBusArgument::endMap() const
1056{
1057 if (QDBusArgumentPrivate::checkReadAndDetach(d))
1058 d = d->demarshaller()->endMap();
1059}
1060
1061/*!
1062 Recurses into the D-Bus map entry to allow extraction
1063 of the key and value pair.
1064
1065 See beginMap() for an example of how this function is usually used.
1066
1067 \sa endMapEntry(), beginMap()
1068*/
1069void QDBusArgument::beginMapEntry() const
1070{
1071 if (QDBusArgumentPrivate::checkReadAndDetach(d))
1072 d = d->demarshaller()->beginMapEntry();
1073}
1074
1075/*!
1076 Closes the D-Bus map entry and allow extracting of the next element
1077 on the map.
1078
1079 \sa beginMapEntry()
1080*/
1081void QDBusArgument::endMapEntry() const
1082{
1083 if (QDBusArgumentPrivate::checkReadAndDetach(d))
1084 d = d->demarshaller()->endMapEntry();
1085}
1086
1087/*!
1088 Returns \c true if there are no more elements to be extracted from
1089 this QDBusArgument. This function is usually used in QDBusArgument
1090 objects returned from beginMap() and beginArray().
1091*/
1092bool QDBusArgument::atEnd() const
1093{
1094 if (QDBusArgumentPrivate::checkRead(d))
1095 return d->demarshaller()->atEnd();
1096
1097 return true; // at least, stop reading
1098}
1099
1100/*!
1101 \since 4.5
1102
1103 Returns the current argument in the form of a QVariant. Basic
1104 types will be decoded and returned in the QVariant, but for
1105 complex types, this function will return a QDBusArgument object in
1106 the QVariant. It is the caller's responsibility to decode the
1107 argument (for example, by calling asVariant() in it).
1108
1109 For example, if the current argument is an INT32, this function
1110 will return a QVariant with an argument of type QMetaType::Int. For
1111 an array of INT32, it will return a QVariant containing a
1112 QDBusArgument.
1113
1114 If an error occurs or if there are no more arguments to decode
1115 (i.e., we are at the end of the argument list), this function will
1116 return an invalid QVariant.
1117
1118 \sa atEnd()
1119*/
1120QVariant QDBusArgument::asVariant() const
1121{
1122 if (QDBusArgumentPrivate::checkRead(d))
1123 return d->demarshaller()->toVariantInternal();
1124
1125 return QVariant();
1126}
1127
1128QT_END_NAMESPACE
1129
1130// for optimization purposes, we include the marshallers here
1131#include "qdbusmarshaller.cpp"
1132#include "qdbusdemarshaller.cpp"
1133
1134QT_BEGIN_NAMESPACE
1135
1136// QDBusArgument operators
1137
1138const QDBusArgument &operator>>(const QDBusArgument &a, QVariant &v)
1139{
1140 QDBusVariant dbv;
1141 a >> dbv;
1142 v = dbv.variant();
1143 return a;
1144}
1145
1146// QVariant types
1147#ifndef QDBUS_NO_SPECIALTYPES
1148const QDBusArgument &operator>>(const QDBusArgument &a, QDate &date)
1149{
1150 int y, m, d;
1151 a.beginStructure();
1152 a >> y >> m >> d;
1153 a.endStructure();
1154
1155 if (y != 0 && m != 0 && d != 0)
1156 date.setDate(y, m, d);
1157 else
1158 date = QDate();
1159 return a;
1160}
1161
1162QDBusArgument &operator<<(QDBusArgument &a, const QDate &date)
1163{
1164 a.beginStructure();
1165 if (date.isValid())
1166 a << date.year() << date.month() << date.day();
1167 else
1168 a << 0 << 0 << 0;
1169 a.endStructure();
1170 return a;
1171}
1172
1173const QDBusArgument &operator>>(const QDBusArgument &a, QTime &time)
1174{
1175 int h, m, s, ms;
1176 a.beginStructure();
1177 a >> h >> m >> s >> ms;
1178 a.endStructure();
1179
1180 if (h < 0)
1181 time = QTime();
1182 else
1183 time.setHMS(h, m, s, ms);
1184 return a;
1185}
1186
1187QDBusArgument &operator<<(QDBusArgument &a, const QTime &time)
1188{
1189 a.beginStructure();
1190 if (time.isValid())
1191 a << time.hour() << time.minute() << time.second() << time.msec();
1192 else
1193 a << -1 << -1 << -1 << -1;
1194 a.endStructure();
1195 return a;
1196}
1197
1198const QDBusArgument &operator>>(const QDBusArgument &a, QDateTime &dt)
1199{
1200 QDate date;
1201 QTime time;
1202 int timespec;
1203
1204 a.beginStructure();
1205 a >> date >> time >> timespec;
1206 a.endStructure();
1207
1208 dt = QDateTime(date, time, Qt::TimeSpec(timespec));
1209 return a;
1210}
1211
1212QDBusArgument &operator<<(QDBusArgument &a, const QDateTime &dt)
1213{
1214 a.beginStructure();
1215 a << dt.date() << dt.time() << int(dt.timeSpec());
1216 a.endStructure();
1217 return a;
1218}
1219
1220const QDBusArgument &operator>>(const QDBusArgument &a, QRect &rect)
1221{
1222 int x, y, width, height;
1223 a.beginStructure();
1224 a >> x >> y >> width >> height;
1225 a.endStructure();
1226
1227 rect.setRect(x, y, width, height);
1228 return a;
1229}
1230
1231QDBusArgument &operator<<(QDBusArgument &a, const QRect &rect)
1232{
1233 a.beginStructure();
1234 a << rect.x() << rect.y() << rect.width() << rect.height();
1235 a.endStructure();
1236
1237 return a;
1238}
1239
1240const QDBusArgument &operator>>(const QDBusArgument &a, QRectF &rect)
1241{
1242 double x, y, width, height;
1243 a.beginStructure();
1244 a >> x >> y >> width >> height;
1245 a.endStructure();
1246
1247 rect.setRect(qreal(x), qreal(y), qreal(width), qreal(height));
1248 return a;
1249}
1250
1251QDBusArgument &operator<<(QDBusArgument &a, const QRectF &rect)
1252{
1253 a.beginStructure();
1254 a << double(rect.x()) << double(rect.y()) << double(rect.width()) << double(rect.height());
1255 a.endStructure();
1256
1257 return a;
1258}
1259
1260const QDBusArgument &operator>>(const QDBusArgument &a, QSize &size)
1261{
1262 a.beginStructure();
1263 a >> size.rwidth() >> size.rheight();
1264 a.endStructure();
1265
1266 return a;
1267}
1268
1269QDBusArgument &operator<<(QDBusArgument &a, const QSize &size)
1270{
1271 a.beginStructure();
1272 a << size.width() << size.height();
1273 a.endStructure();
1274
1275 return a;
1276}
1277
1278const QDBusArgument &operator>>(const QDBusArgument &a, QSizeF &size)
1279{
1280 double width, height;
1281 a.beginStructure();
1282 a >> width >> height;
1283 a.endStructure();
1284
1285 size.setWidth(qreal(width));
1286 size.setHeight(qreal(height));
1287 return a;
1288}
1289
1290QDBusArgument &operator<<(QDBusArgument &a, const QSizeF &size)
1291{
1292 a.beginStructure();
1293 a << double(size.width()) << double(size.height());
1294 a.endStructure();
1295
1296 return a;
1297}
1298
1299const QDBusArgument &operator>>(const QDBusArgument &a, QPoint &pt)
1300{
1301 a.beginStructure();
1302 a >> pt.rx() >> pt.ry();
1303 a.endStructure();
1304
1305 return a;
1306}
1307
1308QDBusArgument &operator<<(QDBusArgument &a, const QPoint &pt)
1309{
1310 a.beginStructure();
1311 a << pt.x() << pt.y();
1312 a.endStructure();
1313
1314 return a;
1315}
1316
1317const QDBusArgument &operator>>(const QDBusArgument &a, QPointF &pt)
1318{
1319 double x, y;
1320 a.beginStructure();
1321 a >> x >> y;
1322 a.endStructure();
1323
1324 pt.setX(qreal(x));
1325 pt.setY(qreal(y));
1326 return a;
1327}
1328
1329QDBusArgument &operator<<(QDBusArgument &a, const QPointF &pt)
1330{
1331 a.beginStructure();
1332 a << double(pt.x()) << double(pt.y());
1333 a.endStructure();
1334
1335 return a;
1336}
1337
1338const QDBusArgument &operator>>(const QDBusArgument &a, QLine &line)
1339{
1340 QPoint p1, p2;
1341 a.beginStructure();
1342 a >> p1 >> p2;
1343 a.endStructure();
1344
1345 line = QLine(p1, p2);
1346 return a;
1347}
1348
1349QDBusArgument &operator<<(QDBusArgument &a, const QLine &line)
1350{
1351 a.beginStructure();
1352 a << line.p1() << line.p2();
1353 a.endStructure();
1354
1355 return a;
1356}
1357
1358const QDBusArgument &operator>>(const QDBusArgument &a, QLineF &line)
1359{
1360 QPointF p1, p2;
1361 a.beginStructure();
1362 a >> p1 >> p2;
1363 a.endStructure();
1364
1365 line = QLineF(p1, p2);
1366 return a;
1367}
1368
1369QDBusArgument &operator<<(QDBusArgument &a, const QLineF &line)
1370{
1371 a.beginStructure();
1372 a << line.p1() << line.p2();
1373 a.endStructure();
1374
1375 return a;
1376}
1377#endif
1378
1379/*!
1380 \fn void QDBusArgument::swap(QDBusArgument &other)
1381
1382 Swaps this QDBusArgument instance with \a other.
1383*/
1384
1385QT_END_NAMESPACE
1386
1387#endif // QT_NO_DBUS
1388