source: trunk/src/dbus/qdbusargument.cpp@ 1008

Last change on this file since 1008 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 35.5 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation (qt-info@nokia.com)
6**
7** This file is part of the QtDBus module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at qt-info@nokia.com.
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qdbusargument.h"
43
44#include <qatomic.h>
45#include <qbytearray.h>
46#include <qlist.h>
47#include <qmap.h>
48#include <qstring.h>
49#include <qstringlist.h>
50#include <qvariant.h>
51#include <qdatetime.h>
52#include <qrect.h>
53#include <qline.h>
54
55#include "qdbusargument_p.h"
56#include "qdbusmetatype_p.h"
57#include "qdbusutil_p.h"
58
59#ifndef QT_NO_DBUS
60
61QT_BEGIN_NAMESPACE
62
63QDBusArgumentPrivate::~QDBusArgumentPrivate()
64{
65 if (message)
66 q_dbus_message_unref(message);
67}
68
69QByteArray QDBusArgumentPrivate::createSignature(int id)
70{
71 if (!qdbus_loadLibDBus())
72 return "";
73
74 QByteArray signature;
75 QDBusMarshaller *marshaller = new QDBusMarshaller;
76 marshaller->ba = &signature;
77
78 // run it
79 void *null = 0;
80 QVariant v(id, null);
81 QDBusArgument arg(marshaller);
82 QDBusMetaType::marshall(arg, v.userType(), v.constData());
83 arg.d = 0;
84
85 // delete it
86 bool ok = marshaller->ok;
87 delete marshaller;
88
89 if (signature.isEmpty() || !ok || !QDBusUtil::isValidSingleSignature(QString::fromLatin1(signature))) {
90 qWarning("QDBusMarshaller: type `%s' produces invalid D-BUS signature `%s' "
91 "(Did you forget to call beginStructure() ?)",
92 QVariant::typeToName( QVariant::Type(id) ),
93 signature.isEmpty() ? "<empty>" : signature.constData());
94 return "";
95 } else if ((signature.at(0) != DBUS_TYPE_ARRAY && signature.at(0) != DBUS_STRUCT_BEGIN_CHAR) ||
96 (signature.at(0) == DBUS_TYPE_ARRAY && (signature.at(1) == DBUS_TYPE_BYTE ||
97 signature.at(1) == DBUS_TYPE_STRING))) {
98 qWarning("QDBusMarshaller: type `%s' attempts to redefine basic D-BUS type '%s' (%s) "
99 "(Did you forget to call beginStructure() ?)",
100 QVariant::typeToName( QVariant::Type(id) ),
101 signature.constData(),
102 QVariant::typeToName( QVariant::Type(QDBusMetaType::signatureToType(signature))) );
103 return "";
104 }
105 return signature;
106}
107
108bool QDBusArgumentPrivate::checkWrite(QDBusArgumentPrivate *&d)
109{
110 if (!d)
111 return false;
112 if (d->direction == Marshalling) {
113 if (!d->marshaller()->ok)
114 return false;
115
116 if (d->message && d->ref != 1) {
117 QDBusMarshaller *dd = new QDBusMarshaller;
118 dd->message = q_dbus_message_copy(d->message);
119 q_dbus_message_iter_init_append(dd->message, &dd->iterator);
120
121 if (!d->ref.deref())
122 delete d;
123 d = dd;
124 }
125 return true;
126 }
127
128#ifdef QT_DEBUG
129 qFatal("QDBusArgument: write from a read-only object");
130#else
131 qWarning("QDBusArgument: write from a read-only object");
132#endif
133 return false;
134}
135
136bool QDBusArgumentPrivate::checkRead(QDBusArgumentPrivate *d)
137{
138 if (!d)
139 return false;
140 if (d->direction == Demarshalling)
141 return true;
142
143#ifdef QT_DEBUG
144 qFatal("QDBusArgument: read from a write-only object");
145#else
146 qWarning("QDBusArgument: read from a write-only object");
147#endif
148
149 return false;
150}
151
152bool QDBusArgumentPrivate::checkReadAndDetach(QDBusArgumentPrivate *&d)
153{
154 if (!checkRead(d))
155 return false; // don't bother
156
157 if (d->ref == 1)
158 return true; // no need to detach
159
160 QDBusDemarshaller *dd = new QDBusDemarshaller;
161 dd->message = q_dbus_message_ref(d->message);
162 dd->iterator = static_cast<QDBusDemarshaller*>(d)->iterator;
163
164 if (!d->ref.deref())
165 delete d;
166 d = dd;
167 return true;
168}
169
170/*!
171 \class QDBusArgument
172 \inmodule QtDBus
173 \since 4.2
174
175 \brief The QDBusArgument class is used to marshall and demarshall D-Bus arguments.
176
177 The class is used to send arguments over D-Bus to remote
178 applications and to receive them back. D-Bus offers an extensible
179 type system, based on a few primitive types and associations of
180 them. See the \l {qdbustypesystem.html}{QtDBus type system} page
181 for more information on the type system.
182
183 QDBusArgument is the central class in the QtDBus type system,
184 providing functions to marshall and demarshall the primitive
185 types. The compound types are then created by association of one
186 or more of the primitive types in arrays, dictionaries or
187 structures.
188
189 The following example illustrates how a structure containing an
190 integer and a string can be constructed using the \l
191 {qdbustypesystem.html}{QtDBus type system}:
192
193 \snippet doc/src/snippets/code/src_qdbus_qdbusargument.cpp 0
194
195 The type has to be registered with qDBusRegisterMetaType() before
196 it can be used with QDBusArgument. Therefore, somewhere in your
197 program, you should add the following code:
198
199 \snippet doc/src/snippets/code/src_qdbus_qdbusargument.cpp 1
200
201 Once registered, a type can be used in outgoing method calls
202 (placed with QDBusAbstractInterface::call()), signal emissions
203 from registered objects or in incoming calls from remote
204 applications.
205
206 It is important to note that the \c{operator<<} and \c{operator>>}
207 streaming functions must always produce the same number of entries
208 in case of structures, both in reading and in writing (marshalling
209 and demarshalling), otherwise calls and signals may start to
210 silently fail.
211
212 The following example illustrates this wrong usage
213 in context of a class that may contain invalid data:
214
215 \badcode
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 QtDBus type system and should be avoided.
233
234 \sa QDBusAbstractInterface, {qdbustypesystem.html}{The QtDBus 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 or QVector<T>. 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 qdbus_cast(const QDBusArgument &argument)
272 \relates QDBusArgument
273 \since 4.2
274
275 Attempts to demarshall the contents of \a argument into the type
276 \c{T}. For example:
277
278 \snippet doc/src/snippets/code/src_qdbus_qdbusargument.cpp 2
279
280 Note that it is equivalent to the following:
281
282 \snippet doc/src/snippets/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 = 0;
295 return;
296 }
297
298 QDBusMarshaller *dd = new QDBusMarshaller;
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 Appends the primitive value \a arg of type \c{VARIANT} to the D-Bus stream.
491
492 A D-Bus variant type can contain any type, including other
493 variants. It is similar to the Qt QVariant type.
494*/
495QDBusArgument &QDBusArgument::operator<<(const QDBusVariant &arg)
496{
497 if (QDBusArgumentPrivate::checkWrite(d))
498 d->marshaller()->append(arg);
499 return *this;
500}
501
502/*!
503 \overload
504 Appends the QStringList given by \a arg as \c{ARRAY of STRING}
505 to the D-Bus stream.
506
507 QStringList and QByteArray are the only two non-primitive types
508 that are supported directly by QDBusArgument because of their
509 widespread usage in Qt applications.
510
511 Other arrays are supported through compound types in QtDBus.
512*/
513QDBusArgument &QDBusArgument::operator<<(const QStringList &arg)
514{
515 if (QDBusArgumentPrivate::checkWrite(d))
516 d->marshaller()->append(arg);
517 return *this;
518}
519
520/*!
521 \overload
522 Appends the QByteArray given by \a arg as \c{ARRAY of BYTE}
523 to the D-Bus stream.
524
525 QStringList and QByteArray are the only two non-primitive types
526 that are supported directly by QDBusArgument because of their
527 widespread usage in Qt applications.
528
529 Other arrays are supported through compound types in QtDBus.
530*/
531QDBusArgument &QDBusArgument::operator<<(const QByteArray &arg)
532{
533 if (QDBusArgumentPrivate::checkWrite(d))
534 d->marshaller()->append(arg);
535 return *this;
536}
537
538/*!
539 \internal
540 \since 4.5
541
542 Appends the variant \a v.
543
544 \sa asVariant()
545*/
546void QDBusArgument::appendVariant(const QVariant &v)
547{
548 if (QDBusArgumentPrivate::checkWrite(d))
549 d->marshaller()->appendVariantInternal(v);
550}
551
552/*!
553 \internal
554 Returns the type signature of the D-Bus type this QDBusArgument
555 object is currently pointing to.
556*/
557QString QDBusArgument::currentSignature() const
558{
559 if (!d)
560 return QString();
561 if (d->direction == QDBusArgumentPrivate::Demarshalling)
562 return d->demarshaller()->currentSignature();
563 else
564 return d->marshaller()->currentSignature();
565}
566
567/*!
568 \since 4.5
569 Returns the classification of the current element type. If an
570 error decoding the type occurs or if we're at the end of the
571 argument, this function returns QDBusArgument::UnknownType.
572
573 This function only makes sense when demarshalling arguments. If it
574 is used while marshalling, it will always return UnknownType.
575*/
576QDBusArgument::ElementType QDBusArgument::currentType() const
577{
578 if (!d)
579 return UnknownType;
580 if (d->direction == QDBusArgumentPrivate::Demarshalling)
581 return d->demarshaller()->currentType();
582 return UnknownType;
583}
584
585/*!
586 Extracts one D-BUS primitive argument of type \c{BYTE} from the
587 D-BUS stream and puts it into \a arg.
588*/
589const QDBusArgument &QDBusArgument::operator>>(uchar &arg) const
590{
591 if (QDBusArgumentPrivate::checkReadAndDetach(d))
592 arg = d->demarshaller()->toByte();
593 return *this;
594}
595
596/*!
597 \overload
598 Extracts one D-Bus primitive argument of type \c{BOOLEAN} from the
599 D-Bus stream.
600*/
601const QDBusArgument &QDBusArgument::operator>>(bool &arg) const
602{
603 if (QDBusArgumentPrivate::checkReadAndDetach(d))
604 arg = d->demarshaller()->toBool();
605 return *this;
606}
607
608/*!
609 \overload
610 Extracts one D-Bus primitive argument of type \c{UINT16} from the
611 D-Bus stream.
612*/
613const QDBusArgument &QDBusArgument::operator>>(ushort &arg) const
614{
615 if (QDBusArgumentPrivate::checkReadAndDetach(d))
616 arg = d->demarshaller()->toUShort();
617 return *this;
618}
619
620/*!
621 \overload
622 Extracts one D-Bus primitive argument of type \c{INT16} from the
623 D-Bus stream.
624*/
625const QDBusArgument &QDBusArgument::operator>>(short &arg) const
626{
627 if (QDBusArgumentPrivate::checkReadAndDetach(d))
628 arg = d->demarshaller()->toShort();
629 return *this;
630}
631
632/*!
633 \overload
634 Extracts one D-Bus primitive argument of type \c{INT32} from the
635 D-Bus stream.
636*/
637const QDBusArgument &QDBusArgument::operator>>(int &arg) const
638{
639 if (QDBusArgumentPrivate::checkReadAndDetach(d))
640 arg = d->demarshaller()->toInt();
641 return *this;
642}
643
644/*!
645 \overload
646 Extracts one D-Bus primitive argument of type \c{UINT32} from the
647 D-Bus stream.
648*/
649const QDBusArgument &QDBusArgument::operator>>(uint &arg) const
650{
651 if (QDBusArgumentPrivate::checkReadAndDetach(d))
652 arg = d->demarshaller()->toUInt();
653 return *this;
654}
655
656/*!
657 \overload
658 Extracts one D-Bus primitive argument of type \c{INT64} from the
659 D-Bus stream.
660*/
661const QDBusArgument &QDBusArgument::operator>>(qlonglong &arg) const
662{
663 if (QDBusArgumentPrivate::checkReadAndDetach(d))
664 arg = d->demarshaller()->toLongLong();
665 return *this;
666}
667
668/*!
669 \overload
670 Extracts one D-Bus primitive argument of type \c{UINT64} from the
671 D-Bus stream.
672*/
673const QDBusArgument &QDBusArgument::operator>>(qulonglong &arg) const
674{
675 if (QDBusArgumentPrivate::checkReadAndDetach(d))
676 arg = d->demarshaller()->toULongLong();
677 return *this;
678}
679
680/*!
681 \overload
682 Extracts one D-Bus primitive argument of type \c{DOUBLE}
683 (double-precision floating pount) from the D-Bus stream.
684*/
685const QDBusArgument &QDBusArgument::operator>>(double &arg) const
686{
687 if (QDBusArgumentPrivate::checkReadAndDetach(d))
688 arg = d->demarshaller()->toDouble();
689 return *this;
690}
691
692/*!
693 \overload
694 Extracts one D-Bus primitive argument of type \c{STRING} (Unicode
695 character string) from the D-Bus stream.
696*/
697const QDBusArgument &QDBusArgument::operator>>(QString &arg) const
698{
699 if (QDBusArgumentPrivate::checkReadAndDetach(d))
700 arg = d->demarshaller()->toString();
701 return *this;
702}
703
704/*!
705 \overload
706 \internal
707 Extracts one D-Bus primitive argument of type \c{OBJECT_PATH}
708 (D-Bus path to an object) from the D-Bus stream.
709*/
710const QDBusArgument &QDBusArgument::operator>>(QDBusObjectPath &arg) const
711{
712 if (QDBusArgumentPrivate::checkReadAndDetach(d))
713 arg = d->demarshaller()->toObjectPath();
714 return *this;
715}
716
717/*!
718 \overload
719 \internal
720 Extracts one D-Bus primitive argument of type \c{SIGNATURE} (D-Bus
721 type signature) from the D-Bus stream.
722*/
723const QDBusArgument &QDBusArgument::operator>>(QDBusSignature &arg) const
724{
725 if (QDBusArgumentPrivate::checkReadAndDetach(d))
726 arg = d->demarshaller()->toSignature();
727 return *this;
728}
729
730/*!
731 \overload
732 Extracts one D-Bus primitive argument of type \c{VARIANT} from the
733 D-Bus stream.
734
735 A D-Bus variant type can contain any type, including other
736 variants. It is similar to the Qt QVariant type.
737
738 In case the variant contains a type not directly supported by
739 QDBusArgument, the value of the returned QDBusVariant will contain
740 another QDBusArgument. It is your responsibility to further
741 demarshall it into another type.
742*/
743const QDBusArgument &QDBusArgument::operator>>(QDBusVariant &arg) const
744{
745 if (QDBusArgumentPrivate::checkReadAndDetach(d))
746 arg = d->demarshaller()->toVariant();
747 return *this;
748}
749
750/*!
751 \overload
752 Extracts an array of strings from the D-Bus stream and return it
753 as a QStringList.
754
755 QStringList and QByteArray are the only two non-primitive types
756 that are supported directly by QDBusArgument because of their
757 widespread usage in Qt applications.
758
759 Other arrays are supported through compound types in QtDBus.
760*/
761const QDBusArgument &QDBusArgument::operator>>(QStringList &arg) const
762{
763 if (QDBusArgumentPrivate::checkReadAndDetach(d))
764 arg = d->demarshaller()->toStringList();
765 return *this;
766}
767
768/*!
769 \overload
770 Extracts an array of bytes from the D-Bus stream and return it
771 as a QByteArray.
772
773 QStringList and QByteArray are the only two non-primitive types
774 that are supported directly by QDBusArgument because of their
775 widespread usage in Qt applications.
776
777 Other arrays are supported through compound types in QtDBus.
778*/
779const QDBusArgument &QDBusArgument::operator>>(QByteArray &arg) const
780{
781 if (QDBusArgumentPrivate::checkReadAndDetach(d))
782 arg = d->demarshaller()->toByteArray();
783 return *this;
784}
785
786/*!
787 Opens a new D-Bus structure suitable for appending new arguments.
788
789 This function is used usually in \c{operator<<} streaming
790 operators, as in the following example:
791
792 \snippet doc/src/snippets/code/src_qdbus_qdbusargument.cpp 4
793
794 Structures can contain other structures, so the following code is
795 also valid:
796
797 \snippet doc/src/snippets/code/src_qdbus_qdbusargument.cpp 5
798
799 \sa endStructure(), beginArray(), beginMap()
800*/
801void QDBusArgument::beginStructure()
802{
803 if (QDBusArgumentPrivate::checkWrite(d))
804 d = d->marshaller()->beginStructure();
805}
806
807/*!
808 Closes a D-Bus structure opened with beginStructure(). This function must be called
809 same number of times that beginStructure() is called.
810
811 \sa beginStructure(), endArray(), endMap()
812*/
813void QDBusArgument::endStructure()
814{
815 if (QDBusArgumentPrivate::checkWrite(d))
816 d = d->marshaller()->endStructure();
817}
818
819/*!
820 Opens a new D-Bus array suitable for appending elements of meta-type \a id.
821
822 This function is used usually in \c{operator<<} streaming
823 operators, as in the following example:
824
825 \snippet doc/src/snippets/code/src_qdbus_qdbusargument.cpp 6
826
827 If the type you want to marshall is a QList, QVector or any of the
828 Qt's \l {Container Classes} that take one template parameter,
829 you need not declare an \c{operator<<} function for it, since
830 QtDBus provides generic templates to do the job of marshalling
831 the data. The same applies for STL's sequence containers, such
832 as \c {std::list}, \c {std::vector}, etc.
833
834 \sa endArray(), beginStructure(), beginMap()
835*/
836void QDBusArgument::beginArray(int id)
837{
838 if (QDBusArgumentPrivate::checkWrite(d))
839 d = d->marshaller()->beginArray(id);
840}
841
842/*!
843 Closes a D-Bus array opened with beginArray(). This function must be called
844 same number of times that beginArray() is called.
845
846 \sa beginArray(), endStructure(), endMap()
847*/
848void QDBusArgument::endArray()
849{
850 if (QDBusArgumentPrivate::checkWrite(d))
851 d = d->marshaller()->endArray();
852}
853
854/*!
855 Opens a new D-Bus map suitable for
856 appending elements. Maps are containers that associate one entry
857 (the key) to another (the value), such as Qt's QMap or QHash. The
858 ids of the map's key and value meta types must be passed in \a kid
859 and \a vid respectively.
860
861 This function is used usually in \c{operator<<} streaming
862 operators, as in the following example:
863
864 \snippet doc/src/snippets/code/src_qdbus_qdbusargument.cpp 7
865
866 If the type you want to marshall is a QMap or QHash, you need not
867 declare an \c{operator<<} function for it, since QtDBus provides
868 generic templates to do the job of marshalling the data.
869
870 \sa endMap(), beginStructure(), beginArray(), beginMapEntry()
871*/
872void QDBusArgument::beginMap(int kid, int vid)
873{
874 if (QDBusArgumentPrivate::checkWrite(d))
875 d = d->marshaller()->beginMap(kid, vid);
876}
877
878/*!
879 Closes a D-Bus map opened with beginMap(). This function must be called
880 same number of times that beginMap() is called.
881
882 \sa beginMap(), endStructure(), endArray()
883*/
884void QDBusArgument::endMap()
885{
886 if (QDBusArgumentPrivate::checkWrite(d))
887 d = d->marshaller()->endMap();
888}
889
890/*!
891 Opens a D-Bus map entry suitable for
892 appending the key and value entries. This function is only valid
893 when a map has been opened with beginMap().
894
895 See beginMap() for an example of usage of this function.
896
897 \sa endMapEntry(), beginMap()
898*/
899void QDBusArgument::beginMapEntry()
900{
901 if (QDBusArgumentPrivate::checkWrite(d))
902 d = d->marshaller()->beginMapEntry();
903}
904
905/*!
906 Closes a D-Bus map entry opened with beginMapEntry(). This function must be called
907 same number of times that beginMapEntry() is called.
908
909 \sa beginMapEntry()
910*/
911void QDBusArgument::endMapEntry()
912{
913 if (QDBusArgumentPrivate::checkWrite(d))
914 d = d->marshaller()->endMapEntry();
915}
916
917/*!
918 Opens a D-Bus structure suitable for extracting elements.
919
920 This function is used usually in \c{operator>>} streaming
921 operators, as in the following example:
922
923 \snippet doc/src/snippets/code/src_qdbus_qdbusargument.cpp 8
924
925 \sa endStructure(), beginArray(), beginMap()
926*/
927void QDBusArgument::beginStructure() const
928{
929 if (QDBusArgumentPrivate::checkReadAndDetach(d))
930 d = d->demarshaller()->beginStructure();
931}
932
933/*!
934 Closes the D-Bus structure and allow extracting of the next element
935 after the structure.
936
937 \sa beginStructure()
938*/
939void QDBusArgument::endStructure() const
940{
941 if (QDBusArgumentPrivate::checkReadAndDetach(d))
942 d = d->demarshaller()->endStructure();
943}
944
945/*!
946 Recurses into the D-Bus array to allow extraction of
947 the array elements.
948
949 This function is used usually in \c{operator>>} streaming
950 operators, as in the following example:
951
952 \snippet doc/src/snippets/code/src_qdbus_qdbusargument.cpp 9
953
954 If the type you want to demarshall is a QList, QVector or any of the
955 Qt's \l {Container Classes} that take one template parameter, you
956 need not declare an \c{operator>>} function for it, since QtDBus
957 provides generic templates to do the job of demarshalling the data.
958 The same applies for STL's sequence containers, such as \c {std::list},
959 \c {std::vector}, etc.
960
961 \sa atEnd(), beginStructure(), beginMap()
962*/
963void QDBusArgument::beginArray() const
964{
965 if (QDBusArgumentPrivate::checkReadAndDetach(d))
966 d = d->demarshaller()->beginArray();
967}
968
969/*!
970 Closes the D-Bus array and allow extracting of the next element
971 after the array.
972
973 \sa beginArray()
974*/
975void QDBusArgument::endArray() const
976{
977 if (QDBusArgumentPrivate::checkReadAndDetach(d))
978 d = d->demarshaller()->endArray();
979}
980
981/*!
982 Recurses into the D-Bus map to allow extraction of
983 the map's elements.
984
985 This function is used usually in \c{operator>>} streaming
986 operators, as in the following example:
987
988 \snippet doc/src/snippets/code/src_qdbus_qdbusargument.cpp 10
989
990 If the type you want to demarshall is a QMap or QHash, you need not
991 declare an \c{operator>>} function for it, since QtDBus provides
992 generic templates to do the job of demarshalling the data.
993
994 \sa endMap(), beginStructure(), beginArray(), beginMapEntry()
995*/
996void QDBusArgument::beginMap() const
997{
998 if (QDBusArgumentPrivate::checkReadAndDetach(d))
999 d = d->demarshaller()->beginMap();
1000}
1001
1002/*!
1003 Closes the D-Bus map and allow extracting of the next element
1004 after the map.
1005
1006 \sa beginMap()
1007*/
1008void QDBusArgument::endMap() const
1009{
1010 if (QDBusArgumentPrivate::checkReadAndDetach(d))
1011 d = d->demarshaller()->endMap();
1012}
1013
1014/*!
1015 Recurses into the D-Bus map entry to allow extraction
1016 of the key and value pair.
1017
1018 See beginMap() for an example of how this function is usually used.
1019
1020 \sa endMapEntry(), beginMap()
1021*/
1022void QDBusArgument::beginMapEntry() const
1023{
1024 if (QDBusArgumentPrivate::checkReadAndDetach(d))
1025 d = d->demarshaller()->beginMapEntry();
1026}
1027
1028/*!
1029 Closes the D-Bus map entry and allow extracting of the next element
1030 on the map.
1031
1032 \sa beginMapEntry()
1033*/
1034void QDBusArgument::endMapEntry() const
1035{
1036 if (QDBusArgumentPrivate::checkReadAndDetach(d))
1037 d = d->demarshaller()->endMapEntry();
1038}
1039
1040/*!
1041 Returns true if there are no more elements to be extracted from
1042 this QDBusArgument. This function is usually used in QDBusArgument
1043 objects returned from beginMap() and beginArray().
1044*/
1045bool QDBusArgument::atEnd() const
1046{
1047 if (QDBusArgumentPrivate::checkRead(d))
1048 return d->demarshaller()->atEnd();
1049
1050 return true; // at least, stop reading
1051}
1052
1053/*!
1054 \since 4.5
1055
1056 Returns the current argument in the form of a QVariant. Basic
1057 types will be decoded and returned in the QVariant, but for
1058 complex types, this function will return a QDBusArgument object in
1059 the QVariant. It is the caller's responsibility to decode the
1060 argument (for example, by calling asVariant() in it).
1061
1062 For example, if the current argument is an INT32, this function
1063 will return a QVariant with an argument of type QVariant::Int. For
1064 an array of INT32, it will return a QVariant containing a
1065 QDBusArgument.
1066
1067 If an error occurs or if there are no more arguments to decode
1068 (i.e., we are at the end of the argument list), this function will
1069 return an invalid QVariant.
1070
1071 \sa atEnd()
1072*/
1073QVariant QDBusArgument::asVariant() const
1074{
1075 if (QDBusArgumentPrivate::checkRead(d))
1076 return d->demarshaller()->toVariantInternal();
1077
1078 return QVariant();
1079}
1080
1081QT_END_NAMESPACE
1082
1083// for optimization purposes, we include the marshallers here
1084#include "qdbusmarshaller.cpp"
1085#include "qdbusdemarshaller.cpp"
1086
1087QT_BEGIN_NAMESPACE
1088
1089// QDBusArgument operators
1090
1091const QDBusArgument &operator>>(const QDBusArgument &a, QVariant &v)
1092{
1093 QDBusVariant dbv;
1094 a >> dbv;
1095 v = dbv.variant();
1096 return a;
1097}
1098
1099// QVariant types
1100#ifndef QDBUS_NO_SPECIALTYPES
1101const QDBusArgument &operator>>(const QDBusArgument &a, QDate &date)
1102{
1103 int y, m, d;
1104 a.beginStructure();
1105 a >> y >> m >> d;
1106 a.endStructure();
1107
1108 if (y != 0 && m != 0 && d != 0)
1109 date.setYMD(y, m, d);
1110 else
1111 date = QDate();
1112 return a;
1113}
1114
1115QDBusArgument &operator<<(QDBusArgument &a, const QDate &date)
1116{
1117 a.beginStructure();
1118 if (date.isValid())
1119 a << date.year() << date.month() << date.day();
1120 else
1121 a << 0 << 0 << 0;
1122 a.endStructure();
1123 return a;
1124}
1125
1126const QDBusArgument &operator>>(const QDBusArgument &a, QTime &time)
1127{
1128 int h, m, s, ms;
1129 a.beginStructure();
1130 a >> h >> m >> s >> ms;
1131 a.endStructure();
1132
1133 if (h < 0)
1134 time = QTime();
1135 else
1136 time.setHMS(h, m, s, ms);
1137 return a;
1138}
1139
1140QDBusArgument &operator<<(QDBusArgument &a, const QTime &time)
1141{
1142 a.beginStructure();
1143 if (time.isValid())
1144 a << time.hour() << time.minute() << time.second() << time.msec();
1145 else
1146 a << -1 << -1 << -1 << -1;
1147 a.endStructure();
1148 return a;
1149}
1150
1151const QDBusArgument &operator>>(const QDBusArgument &a, QDateTime &dt)
1152{
1153 QDate date;
1154 QTime time;
1155 int timespec;
1156
1157 a.beginStructure();
1158 a >> date >> time >> timespec;
1159 a.endStructure();
1160
1161 dt = QDateTime(date, time, Qt::TimeSpec(timespec));
1162 return a;
1163}
1164
1165QDBusArgument &operator<<(QDBusArgument &a, const QDateTime &dt)
1166{
1167 a.beginStructure();
1168 a << dt.date() << dt.time() << int(dt.timeSpec());
1169 a.endStructure();
1170 return a;
1171}
1172
1173const QDBusArgument &operator>>(const QDBusArgument &a, QRect &rect)
1174{
1175 int x, y, width, height;
1176 a.beginStructure();
1177 a >> x >> y >> width >> height;
1178 a.endStructure();
1179
1180 rect.setRect(x, y, width, height);
1181 return a;
1182}
1183
1184QDBusArgument &operator<<(QDBusArgument &a, const QRect &rect)
1185{
1186 a.beginStructure();
1187 a << rect.x() << rect.y() << rect.width() << rect.height();
1188 a.endStructure();
1189
1190 return a;
1191}
1192
1193const QDBusArgument &operator>>(const QDBusArgument &a, QRectF &rect)
1194{
1195 double x, y, width, height;
1196 a.beginStructure();
1197 a >> x >> y >> width >> height;
1198 a.endStructure();
1199
1200 rect.setRect(qreal(x), qreal(y), qreal(width), qreal(height));
1201 return a;
1202}
1203
1204QDBusArgument &operator<<(QDBusArgument &a, const QRectF &rect)
1205{
1206 a.beginStructure();
1207 a << double(rect.x()) << double(rect.y()) << double(rect.width()) << double(rect.height());
1208 a.endStructure();
1209
1210 return a;
1211}
1212
1213const QDBusArgument &operator>>(const QDBusArgument &a, QSize &size)
1214{
1215 a.beginStructure();
1216 a >> size.rwidth() >> size.rheight();
1217 a.endStructure();
1218
1219 return a;
1220}
1221
1222QDBusArgument &operator<<(QDBusArgument &a, const QSize &size)
1223{
1224 a.beginStructure();
1225 a << size.width() << size.height();
1226 a.endStructure();
1227
1228 return a;
1229}
1230
1231const QDBusArgument &operator>>(const QDBusArgument &a, QSizeF &size)
1232{
1233 double width, height;
1234 a.beginStructure();
1235 a >> width >> height;
1236 a.endStructure();
1237
1238 size.setWidth(qreal(width));
1239 size.setHeight(qreal(height));
1240 return a;
1241}
1242
1243QDBusArgument &operator<<(QDBusArgument &a, const QSizeF &size)
1244{
1245 a.beginStructure();
1246 a << double(size.width()) << double(size.height());
1247 a.endStructure();
1248
1249 return a;
1250}
1251
1252const QDBusArgument &operator>>(const QDBusArgument &a, QPoint &pt)
1253{
1254 a.beginStructure();
1255 a >> pt.rx() >> pt.ry();
1256 a.endStructure();
1257
1258 return a;
1259}
1260
1261QDBusArgument &operator<<(QDBusArgument &a, const QPoint &pt)
1262{
1263 a.beginStructure();
1264 a << pt.x() << pt.y();
1265 a.endStructure();
1266
1267 return a;
1268}
1269
1270const QDBusArgument &operator>>(const QDBusArgument &a, QPointF &pt)
1271{
1272 double x, y;
1273 a.beginStructure();
1274 a >> x >> y;
1275 a.endStructure();
1276
1277 pt.setX(qreal(x));
1278 pt.setY(qreal(y));
1279 return a;
1280}
1281
1282QDBusArgument &operator<<(QDBusArgument &a, const QPointF &pt)
1283{
1284 a.beginStructure();
1285 a << double(pt.x()) << double(pt.y());
1286 a.endStructure();
1287
1288 return a;
1289}
1290
1291const QDBusArgument &operator>>(const QDBusArgument &a, QLine &line)
1292{
1293 QPoint p1, p2;
1294 a.beginStructure();
1295 a >> p1 >> p2;
1296 a.endStructure();
1297
1298 line = QLine(p1, p2);
1299 return a;
1300}
1301
1302QDBusArgument &operator<<(QDBusArgument &a, const QLine &line)
1303{
1304 a.beginStructure();
1305 a << line.p1() << line.p2();
1306 a.endStructure();
1307
1308 return a;
1309}
1310
1311const QDBusArgument &operator>>(const QDBusArgument &a, QLineF &line)
1312{
1313 QPointF p1, p2;
1314 a.beginStructure();
1315 a >> p1 >> p2;
1316 a.endStructure();
1317
1318 line = QLineF(p1, p2);
1319 return a;
1320}
1321
1322QDBusArgument &operator<<(QDBusArgument &a, const QLineF &line)
1323{
1324 a.beginStructure();
1325 a << line.p1() << line.p2();
1326 a.endStructure();
1327
1328 return a;
1329}
1330#endif
1331
1332QT_END_NAMESPACE
1333
1334#endif // QT_NO_DBUS
Note: See TracBrowser for help on using the repository browser.