Cleanup usage of QVariant::Type.
[profile/ivi/qtbase.git] / tests / auto / dbus / qdbusmarshall / common.h
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the test suite of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 #include <math.h>               // isnan
42 #include <qvariant.h>
43
44 #ifdef Q_OS_UNIX
45 # include <private/qcore_unix_p.h>
46
47 static bool compareFileDescriptors(int fd1, int fd2)
48 {
49     QT_STATBUF st1, st2;
50     if (QT_FSTAT(fd1, &st1) == -1 || QT_FSTAT(fd2, &st2) == -1) {
51         perror("fstat");
52         return false;
53     }
54
55     return (st1.st_dev == st2.st_dev) && (st1.st_ino == st2.st_ino);
56 }
57 #endif
58
59 Q_DECLARE_METATYPE(QVariant)
60 Q_DECLARE_METATYPE(QList<bool>)
61 Q_DECLARE_METATYPE(QList<short>)
62 Q_DECLARE_METATYPE(QList<ushort>)
63 Q_DECLARE_METATYPE(QList<int>)
64 Q_DECLARE_METATYPE(QList<uint>)
65 Q_DECLARE_METATYPE(QList<qlonglong>)
66 Q_DECLARE_METATYPE(QList<qulonglong>)
67 Q_DECLARE_METATYPE(QList<double>)
68 Q_DECLARE_METATYPE(QList<QDBusVariant>)
69 Q_DECLARE_METATYPE(QList<QDateTime>)
70
71 Q_DECLARE_METATYPE(QList<QByteArray>)
72 Q_DECLARE_METATYPE(QList<QVariantList>)
73 Q_DECLARE_METATYPE(QList<QStringList>)
74 Q_DECLARE_METATYPE(QList<QList<bool> >)
75 Q_DECLARE_METATYPE(QList<QList<short> >)
76 Q_DECLARE_METATYPE(QList<QList<ushort> >)
77 Q_DECLARE_METATYPE(QList<QList<int> >)
78 Q_DECLARE_METATYPE(QList<QList<uint> >)
79 Q_DECLARE_METATYPE(QList<QList<qlonglong> >)
80 Q_DECLARE_METATYPE(QList<QList<qulonglong> >)
81 Q_DECLARE_METATYPE(QList<QList<double> >)
82 Q_DECLARE_METATYPE(QList<QList<QDBusObjectPath> >)
83 Q_DECLARE_METATYPE(QList<QList<QDBusSignature> >)
84
85 typedef QMap<int, QString> IntStringMap;
86 typedef QMap<QString, QString> StringStringMap;
87 typedef QMap<QDBusObjectPath, QString> ObjectPathStringMap;
88 typedef QHash<qlonglong, QDateTime> LLDateTimeMap;
89 typedef QHash<QDBusSignature, QString> SignatureStringMap;
90 Q_DECLARE_METATYPE(IntStringMap)
91 Q_DECLARE_METATYPE(StringStringMap)
92 Q_DECLARE_METATYPE(ObjectPathStringMap)
93 Q_DECLARE_METATYPE(LLDateTimeMap)
94 Q_DECLARE_METATYPE(SignatureStringMap)
95
96 static bool compare(const QDBusUnixFileDescriptor &t1, const QDBusUnixFileDescriptor &t2)
97 {
98     int fd1 = t1.fileDescriptor();
99     int fd2 = t2.fileDescriptor();
100     if ((fd1 == -1 || fd2 == -1) && fd1 != fd2) {
101         // one is valid, the other isn't
102         return false;
103     }
104
105 #ifdef Q_OS_UNIX
106     return compareFileDescriptors(fd1, fd2);
107 #else
108     return true;
109 #endif
110 }
111
112 struct MyStruct
113 {
114     int i;
115     QString s;
116
117     inline bool operator==(const MyStruct &other) const
118     { return i == other.i && s == other.s; }
119 };
120 Q_DECLARE_METATYPE(MyStruct)
121
122 QDBusArgument &operator<<(QDBusArgument &arg, const MyStruct &ms)
123 {
124     arg.beginStructure();
125     arg << ms.i << ms.s;
126     arg.endStructure();
127     return arg;
128 }
129
130 const QDBusArgument &operator>>(const QDBusArgument &arg, MyStruct &ms)
131 {
132     arg.beginStructure();
133     arg >> ms.i >> ms.s;
134     arg.endStructure();
135     return arg;
136 }
137
138 struct MyVariantMapStruct
139 {
140     QString s;
141     QVariantMap map;
142
143     inline bool operator==(const MyVariantMapStruct &other) const
144     { return s == other.s && map == other.map; }
145 };
146 Q_DECLARE_METATYPE(MyVariantMapStruct)
147 Q_DECLARE_METATYPE(QList<MyVariantMapStruct>)
148
149 QDBusArgument &operator<<(QDBusArgument &arg, const MyVariantMapStruct &ms)
150 {
151     arg.beginStructure();
152     arg << ms.s << ms.map;
153     arg.endStructure();
154     return arg;
155 }
156
157 const QDBusArgument &operator>>(const QDBusArgument &arg, MyVariantMapStruct &ms)
158 {
159     arg.beginStructure();
160     arg >> ms.s >> ms.map;
161     arg.endStructure();
162     return arg;
163 }
164
165 struct MyFileDescriptorStruct
166 {
167     QDBusUnixFileDescriptor fd;
168
169     inline bool operator==(const MyFileDescriptorStruct &other) const
170     { return compare(fd, other.fd); }
171 };
172 Q_DECLARE_METATYPE(MyFileDescriptorStruct)
173 Q_DECLARE_METATYPE(QList<MyFileDescriptorStruct>)
174
175 QDBusArgument &operator<<(QDBusArgument &arg, const MyFileDescriptorStruct &ms)
176 {
177     arg.beginStructure();
178     arg << ms.fd;
179     arg.endStructure();
180     return arg;
181 }
182
183 const QDBusArgument &operator>>(const QDBusArgument &arg, MyFileDescriptorStruct &ms)
184 {
185     arg.beginStructure();
186     arg >> ms.fd;
187     arg.endStructure();
188     return arg;
189 }
190
191
192 void commonInit()
193 {
194     qDBusRegisterMetaType<QList<QDateTime> >();
195     qDBusRegisterMetaType<QList<QStringList> >();
196     qDBusRegisterMetaType<QList<QByteArray> >();
197     qDBusRegisterMetaType<QList<QList<bool> > >();
198     qDBusRegisterMetaType<QList<QList<short> > >();
199     qDBusRegisterMetaType<QList<QList<ushort> > >();
200     qDBusRegisterMetaType<QList<QList<int> > >();
201     qDBusRegisterMetaType<QList<QList<uint> > >();
202     qDBusRegisterMetaType<QList<QList<qlonglong> > >();
203     qDBusRegisterMetaType<QList<QList<qulonglong> > >();
204     qDBusRegisterMetaType<QList<QList<double> > >();
205     qDBusRegisterMetaType<QList<QList<QDBusObjectPath> > >();
206     qDBusRegisterMetaType<QList<QList<QDBusSignature> > >();
207     qDBusRegisterMetaType<QList<QVariantList> >();
208
209     qDBusRegisterMetaType<QMap<int, QString> >();
210     qDBusRegisterMetaType<QMap<QString, QString> >();
211     qDBusRegisterMetaType<QMap<QDBusObjectPath, QString> >();
212     qDBusRegisterMetaType<QHash<qlonglong, QDateTime> >();
213     qDBusRegisterMetaType<QHash<QDBusSignature, QString> >();
214
215     qDBusRegisterMetaType<MyStruct>();
216     qDBusRegisterMetaType<MyVariantMapStruct>();
217     qDBusRegisterMetaType<QList<MyVariantMapStruct> >();
218     qDBusRegisterMetaType<MyFileDescriptorStruct>();
219     qDBusRegisterMetaType<QList<MyFileDescriptorStruct> >();
220 }
221 #ifdef USE_PRIVATE_CODE
222 #include "private/qdbusintrospection_p.h"
223
224 // just to make it easier:
225 typedef QDBusIntrospection::Interfaces InterfaceMap;
226 typedef QDBusIntrospection::Objects ObjectMap;
227 typedef QDBusIntrospection::Arguments ArgumentList;
228 typedef QDBusIntrospection::Annotations AnnotationsMap;
229 typedef QDBusIntrospection::Methods MethodMap;
230 typedef QDBusIntrospection::Signals SignalMap;
231 typedef QDBusIntrospection::Properties PropertyMap;
232
233 Q_DECLARE_METATYPE(QDBusIntrospection::Method)
234 Q_DECLARE_METATYPE(QDBusIntrospection::Signal)
235 Q_DECLARE_METATYPE(QDBusIntrospection::Property)
236 Q_DECLARE_METATYPE(MethodMap)
237 Q_DECLARE_METATYPE(SignalMap)
238 Q_DECLARE_METATYPE(PropertyMap)
239
240 inline QDBusIntrospection::Argument arg(const char* type, const char *name = 0)
241 {
242     QDBusIntrospection::Argument retval;
243     retval.type = QLatin1String(type);
244     retval.name = QLatin1String(name);
245     return retval;
246 }
247
248 template<typename T>
249 inline QMap<QString, T>& operator<<(QMap<QString, T>& map, const T& m)
250 { map.insertMulti(m.name, m); return map; }
251
252 inline const char* mapName(const MethodMap&)
253 { return "MethodMap"; }
254
255 inline const char* mapName(const SignalMap&)
256 { return "SignalMap"; }
257
258 inline const char* mapName(const PropertyMap&)
259 { return "PropertyMap"; }
260
261 QString printable(const QDBusIntrospection::Method& m)
262 {
263     QString result = "method " + m.name + "(";
264     foreach (QDBusIntrospection::Argument arg, m.inputArgs)
265         result += QString("in %1 %2, ")
266         .arg(arg.type, arg.name);
267     foreach (QDBusIntrospection::Argument arg, m.outputArgs)
268         result += QString("out %1 %2, ")
269         .arg(arg.type, arg.name);
270     AnnotationsMap::const_iterator it = m.annotations.begin();
271     for ( ; it != m.annotations.end(); ++it)
272         result += QString("%1 \"%2\", ").arg(it.key()).arg(it.value());
273
274     result += ")";
275     return result;
276 }
277
278 QString printable(const QDBusIntrospection::Signal& s)
279 {
280     QString result = "signal " + s.name + "(";
281     foreach (QDBusIntrospection::Argument arg, s.outputArgs)
282         result += QString("out %1 %2, ")
283         .arg(arg.type, arg.name);
284     AnnotationsMap::const_iterator it = s.annotations.begin();
285     for ( ; it != s.annotations.end(); ++it)
286         result += QString("%1 \"%2\", ").arg(it.key()).arg(it.value());
287
288     result += ")";
289     return result;
290 }
291
292 QString printable(const QDBusIntrospection::Property& p)
293 {
294     QString result;
295     if (p.access == QDBusIntrospection::Property::Read)
296         result = "property read %1 %2, ";
297     else if (p.access == QDBusIntrospection::Property::Write)
298         result = "property write %1 %2, ";
299     else
300         result = "property readwrite %1 %2, ";
301     result = result.arg(p.type, p.name);
302
303     AnnotationsMap::const_iterator it = p.annotations.begin();
304     for ( ; it != p.annotations.end(); ++it)
305         result += QString("%1 \"%2\", ").arg(it.key()).arg(it.value());
306
307     return result;
308 }
309
310 template<typename T>
311 char* printableMap(const QMap<QString, T>& map)
312 {
313     QString contents = "\n";
314     typename QMap<QString, T>::const_iterator it = map.begin();
315     for ( ; it != map.end(); ++it) {
316         if (it.key() != it.value().name)
317             contents += it.value().name + ":";
318         contents += printable(it.value());
319         contents += ";\n";
320     }
321
322     QString result("%1(size = %2): {%3}");
323     return qstrdup(qPrintable(result
324                               .arg(mapName(map))
325                               .arg(map.size())
326                               .arg(contents)));
327 }
328
329 QT_BEGIN_NAMESPACE
330 namespace QTest {
331     template<>
332     inline char* toString(const MethodMap& map)
333     {
334         return printableMap(map);
335     }
336
337     template<>
338     inline char* toString(const SignalMap& map)
339     {
340         return printableMap(map);
341     }
342
343     template<>
344     inline char* toString(const PropertyMap& map)
345     {
346         return printableMap(map);
347     }
348 }
349 QT_END_NAMESPACE
350
351 #endif
352
353 //bool compare(const QVariantList &l1, const QVariantList &l2);
354 //bool compare(const QVariantMap &m1, const QVariantMap &m2);
355 template<typename T>
356 bool compare(const T &t1, const T &t2)
357 { return t1 == t2; }
358
359 template<>
360 bool compare(const QVariant &v1, const QVariant &v2);
361
362 bool compare(double d1, double d2)
363 {
364     if (isnan(d1) && isnan(d2))
365         return true;
366     return d1 == d2;
367 }
368
369 template<>
370 bool compare(const QString &s1, const QString &s2)
371 {
372     if (s1.isEmpty() && s2.isEmpty())
373         return true;            // regardless of whether one of them is null
374     return s1 == s2;
375 }
376
377 template<>
378 bool compare(const QByteArray &ba1, const QByteArray &ba2)
379 {
380     if (ba1.isEmpty() && ba2.isEmpty())
381         return true;            // regardless of whether one of them is null
382     return ba1 == ba2;
383 }
384
385 template<>
386 bool compare(const QDBusVariant &s1, const QDBusVariant &s2)
387 {
388     return compare(s1.variant(), s2.variant());
389 }
390
391 template<typename T>
392 bool compare(const QList<T> &l1, const QList<T> &l2)
393 {
394     if (l1.count() != l2.count())
395         return false;
396
397     typename QList<T>::ConstIterator it1 = l1.constBegin();
398     typename QList<T>::ConstIterator it2 = l2.constBegin();
399     typename QList<T>::ConstIterator end = l1.constEnd();
400     for ( ; it1 != end; ++it1, ++it2)
401         if (!compare(*it1, *it2))
402             return false;
403     return true;
404 }
405
406 template<typename Key, typename T>
407 bool compare(const QMap<Key, T> &m1, const QMap<Key, T> &m2)
408 {
409     if (m1.count() != m2.size())
410         return false;
411     typename QMap<Key, T>::ConstIterator i1 = m1.constBegin();
412     typename QMap<Key, T>::ConstIterator end = m1.constEnd();
413     for ( ; i1 != end; ++i1) {
414         typename QMap<Key, T>::ConstIterator i2 = m2.find(i1.key());
415         if (i2 == m2.constEnd())
416             return false;
417         if (!compare(*i1, *i2))
418             return false;
419     }
420     return true;
421 }
422
423 template<typename Key, typename T>
424 bool compare(const QHash<Key, T> &m1, const QHash<Key, T> &m2)
425 {
426     if (m1.count() != m2.size())
427         return false;
428     typename QHash<Key, T>::ConstIterator i1 = m1.constBegin();
429     typename QHash<Key, T>::ConstIterator end = m1.constEnd();
430     for ( ; i1 != end; ++i1) {
431         typename QHash<Key, T>::ConstIterator i2 = m2.find(i1.key());
432         if (i2 == m2.constEnd())
433             return false;
434         if (!compare(*i1, *i2))
435             return false;
436     }
437     return true;
438 }
439
440 template<typename T>
441 inline bool compare(const QDBusArgument &arg, const QVariant &v2, T * = 0)
442 {
443     return compare(qdbus_cast<T>(arg), qvariant_cast<T>(v2));
444 }
445
446 bool compareToArgument(const QDBusArgument &arg, const QVariant &v2)
447 {
448     if (arg.currentSignature() != QDBusMetaType::typeToSignature(v2.userType()))
449         return false;
450
451     // try to demarshall the arg according to v2
452     switch (v2.userType())
453     {
454     case QVariant::Bool:
455         return compare<bool>(arg, v2);
456     case QMetaType::UChar:
457         return compare<uchar>(arg, v2);
458     case QMetaType::Short:
459         return compare<short>(arg, v2);
460     case QMetaType::UShort:
461         return compare<ushort>(arg, v2);
462     case QVariant::Int:
463         return compare<int>(arg, v2);
464     case QVariant::UInt:
465         return compare<uint>(arg, v2);
466     case QVariant::LongLong:
467         return compare<qlonglong>(arg, v2);
468     case QVariant::ULongLong:
469         return compare<qulonglong>(arg, v2);
470     case QVariant::Double:
471         return compare<double>(arg, v2);
472     case QVariant::String:
473         return compare<QString>(arg, v2);
474     case QVariant::ByteArray:
475         return compare<QByteArray>(arg, v2);
476     case QVariant::List:
477         return compare<QVariantList>(arg, v2);
478     case QVariant::Map:
479         return compare<QVariantMap>(arg, v2);
480     case QVariant::Point:
481         return compare<QPoint>(arg, v2);
482     case QVariant::PointF:
483         return compare<QPointF>(arg, v2);
484     case QVariant::Size:
485         return compare<QSize>(arg, v2);
486     case QVariant::SizeF:
487         return compare<QSizeF>(arg, v2);
488     case QVariant::Line:
489         return compare<QLine>(arg, v2);
490     case QVariant::LineF:
491         return compare<QLineF>(arg, v2);
492     case QVariant::Rect:
493         return compare<QRect>(arg, v2);
494     case QVariant::RectF:
495         return compare<QRectF>(arg, v2);
496     case QVariant::Date:
497         return compare<QDate>(arg, v2);
498     case QVariant::Time:
499         return compare<QTime>(arg, v2);
500     case QVariant::DateTime:
501         return compare<QDateTime>(arg, v2);
502     default:
503         register int id = v2.userType();
504         if (id == qMetaTypeId<QDBusObjectPath>())
505             return compare<QDBusObjectPath>(arg, v2);
506         else if (id == qMetaTypeId<QDBusSignature>())
507             return compare<QDBusSignature>(arg, v2);
508         else if (id == qMetaTypeId<QDBusVariant>())
509             return compare<QDBusVariant>(arg, v2);
510         else if (id == qMetaTypeId<QList<bool> >())
511             return compare<QList<bool> >(arg, v2);
512         else if (id == qMetaTypeId<QList<short> >())
513             return compare<QList<short> >(arg, v2);
514         else if (id == qMetaTypeId<QList<ushort> >())
515             return compare<QList<ushort> >(arg, v2);
516         else if (id == qMetaTypeId<QList<int> >())
517             return compare<QList<int> >(arg, v2);
518         else if (id == qMetaTypeId<QList<uint> >())
519             return compare<QList<uint> >(arg, v2);
520         else if (id == qMetaTypeId<QList<qlonglong> >())
521             return compare<QList<qlonglong> >(arg, v2);
522         else if (id == qMetaTypeId<QList<qulonglong> >())
523             return compare<QList<qulonglong> >(arg, v2);
524         else if (id == qMetaTypeId<QList<double> >())
525             return compare<QList<double> >(arg, v2);
526         else if (id == qMetaTypeId<QList<QDBusObjectPath> >())
527             return compare<QList<QDBusObjectPath> >(arg, v2);
528         else if (id == qMetaTypeId<QList<QDBusSignature> >())
529             return compare<QList<QDBusSignature> >(arg, v2);
530         else if (id == qMetaTypeId<QList<QDBusUnixFileDescriptor> >())
531             return compare<QList<QDBusUnixFileDescriptor> >(arg, v2);
532         else if (id == qMetaTypeId<QList<QDateTime> >())
533             return compare<QList<QDateTime> >(arg, v2);
534
535         else if (id == qMetaTypeId<QMap<int, QString> >())
536             return compare<QMap<int, QString> >(arg, v2);
537         else if (id == qMetaTypeId<QMap<QString, QString> >())
538             return compare<QMap<QString, QString> >(arg, v2);
539         else if (id == qMetaTypeId<QMap<QDBusObjectPath, QString> >())
540             return compare<QMap<QDBusObjectPath, QString> >(arg, v2);
541         else if (id == qMetaTypeId<QHash<qlonglong, QDateTime> >())
542             return compare<QHash<qlonglong, QDateTime> >(arg, v2);
543         else if (id == qMetaTypeId<QHash<QDBusSignature, QString> >())
544             return compare<QHash<QDBusSignature, QString> >(arg, v2);
545
546         else if (id == qMetaTypeId<QList<QByteArray> >())
547             return compare<QList<QByteArray> >(arg, v2);
548         else if (id == qMetaTypeId<QList<QList<bool> > >())
549             return compare<QList<QList<bool> > >(arg, v2);
550         else if (id == qMetaTypeId<QList<QList<short> > >())
551             return compare<QList<QList<short> > >(arg, v2);
552         else if (id == qMetaTypeId<QList<QList<ushort> > >())
553             return compare<QList<QList<ushort> > >(arg, v2);
554         else if (id == qMetaTypeId<QList<QList<int> > >())
555             return compare<QList<QList<int> > >(arg, v2);
556         else if (id == qMetaTypeId<QList<QList<uint> > >())
557             return compare<QList<QList<uint> > >(arg, v2);
558         else if (id == qMetaTypeId<QList<QList<qlonglong> > >())
559             return compare<QList<QList<qlonglong> > >(arg, v2);
560         else if (id == qMetaTypeId<QList<QList<qulonglong> > >())
561             return compare<QList<QList<qulonglong> > >(arg, v2);
562         else if (id == qMetaTypeId<QList<QList<double> > >())
563             return compare<QList<QList<double> > >(arg, v2);
564         else if (id == qMetaTypeId<QList<QStringList> >())
565             return compare<QList<QStringList> >(arg, v2);
566         else if (id == qMetaTypeId<QList<QVariantList> >())
567             return compare<QList<QVariantList> >(arg, v2);
568
569         else if (id == qMetaTypeId<MyStruct>())
570             return compare<MyStruct>(arg, v2);
571
572         else if (id == qMetaTypeId<MyVariantMapStruct>())
573             return compare<MyVariantMapStruct>(arg, v2);
574         else if (id == qMetaTypeId<QList<MyVariantMapStruct> >())
575             return compare<QList<MyVariantMapStruct> >(arg, v2);
576         else if (id == qMetaTypeId<MyFileDescriptorStruct>())
577             return compare<MyFileDescriptorStruct>(arg, v2);
578         else if (id == qMetaTypeId<QList<MyFileDescriptorStruct> >())
579             return compare<QList<MyFileDescriptorStruct> >(arg, v2);
580     }
581
582     qWarning() << "Unexpected QVariant type" << v2.userType()
583                << QByteArray(QDBusMetaType::typeToSignature(v2.userType()))
584                << QMetaType::typeName(v2.userType());
585     return false;
586 }
587
588 template<> bool compare(const QVariant &v1, const QVariant &v2)
589 {
590     // v1 is the one that came from the network
591     // v2 is the one that we sent
592
593     if (v1.userType() == qMetaTypeId<QDBusArgument>())
594         // this argument has been left un-demarshalled
595         return compareToArgument(qvariant_cast<QDBusArgument>(v1), v2);
596
597     if (v1.userType() != v2.userType())
598         return false;
599
600     int id = v1.userType();
601     if (id == QVariant::List)
602         return compare(v1.toList(), v2.toList());
603
604     else if (id == QVariant::Map)
605         return compare(v1.toMap(), v2.toMap());
606
607     else if (id == QVariant::String)
608         return compare(v1.toString(), v2.toString());
609
610     else if (id == QVariant::ByteArray)
611         return compare(v1.toByteArray(), v2.toByteArray());
612
613     else if (id == QMetaType::UChar)
614         return qvariant_cast<uchar>(v1) == qvariant_cast<uchar>(v2);
615
616     else if (id == QMetaType::Short)
617         return qvariant_cast<short>(v1) == qvariant_cast<short>(v2);
618
619     else if (id == QMetaType::UShort)
620         return qvariant_cast<ushort>(v1) == qvariant_cast<ushort>(v2);
621
622     else if (id == qMetaTypeId<QDBusObjectPath>())
623         return qvariant_cast<QDBusObjectPath>(v1).path() == qvariant_cast<QDBusObjectPath>(v2).path();
624
625     else if (id == qMetaTypeId<QDBusSignature>())
626         return qvariant_cast<QDBusSignature>(v1).signature() == qvariant_cast<QDBusSignature>(v2).signature();
627
628     else if (id == qMetaTypeId<QDBusUnixFileDescriptor>())
629         return compare(qvariant_cast<QDBusUnixFileDescriptor>(v1), qvariant_cast<QDBusUnixFileDescriptor>(v2));
630
631     else if (id == qMetaTypeId<QDBusVariant>())
632         return compare(qvariant_cast<QDBusVariant>(v1).variant(), qvariant_cast<QDBusVariant>(v2).variant());
633
634     else if (id == qMetaTypeId<QVariant>())
635         return compare(qvariant_cast<QVariant>(v1), qvariant_cast<QVariant>(v2));
636
637     else if (id == qMetaTypeId<QList<bool> >())
638         return qvariant_cast<QList<bool> >(v1) == qvariant_cast<QList<bool> >(v2);
639
640     else if (id == qMetaTypeId<QList<short> >())
641         return qvariant_cast<QList<short> >(v1) == qvariant_cast<QList<short> >(v2);
642
643     else if (id == qMetaTypeId<QList<ushort> >())
644         return qvariant_cast<QList<ushort> >(v1) == qvariant_cast<QList<ushort> >(v2);
645
646     else if (id == qMetaTypeId<QList<int> >())
647         return qvariant_cast<QList<int> >(v1) == qvariant_cast<QList<int> >(v2);
648
649     else if (id == qMetaTypeId<QList<uint> >())
650         return qvariant_cast<QList<uint> >(v1) == qvariant_cast<QList<uint> >(v2);
651
652     else if (id == qMetaTypeId<QList<qlonglong> >())
653         return qvariant_cast<QList<qlonglong> >(v1) == qvariant_cast<QList<qlonglong> >(v2);
654
655     else if (id == qMetaTypeId<QList<qulonglong> >())
656         return qvariant_cast<QList<qulonglong> >(v2) == qvariant_cast<QList<qulonglong> >(v2);
657
658     else if (id == qMetaTypeId<QList<double> >())
659         return compare(qvariant_cast<QList<double> >(v1), qvariant_cast<QList<double> >(v2));
660
661     else if (id == qMetaTypeId<QVariant>())
662         return compare(qvariant_cast<QVariant>(v1), qvariant_cast<QVariant>(v2));
663
664     else if (id == qMetaTypeId<QList<QList<bool> > >())
665         return qvariant_cast<QList<QList<bool> > >(v1) == qvariant_cast<QList<QList<bool> > >(v2);
666
667     else if (id == qMetaTypeId<QList<QList<short> > >())
668         return qvariant_cast<QList<QList<short> > >(v1) == qvariant_cast<QList<QList<short> > >(v2);
669
670     else if (id == qMetaTypeId<QList<QList<ushort> > >())
671         return qvariant_cast<QList<QList<ushort> > >(v1) == qvariant_cast<QList<QList<ushort> > >(v2);
672
673     else if (id == qMetaTypeId<QList<QList<int> > >())
674         return qvariant_cast<QList<QList<int> > >(v1) == qvariant_cast<QList<QList<int> > >(v2);
675
676     else if (id == qMetaTypeId<QList<QList<uint> > >())
677         return qvariant_cast<QList<QList<uint> > >(v1) == qvariant_cast<QList<QList<uint> > >(v2);
678
679     else if (id == qMetaTypeId<QList<QList<qlonglong> > >())
680         return qvariant_cast<QList<QList<qlonglong> > >(v1) == qvariant_cast<QList<QList<qlonglong> > >(v2);
681
682     else if (id == qMetaTypeId<QList<QList<qulonglong> > >())
683         return qvariant_cast<QList<QList<qulonglong> > >(v1) == qvariant_cast<QList<QList<qulonglong> > >(v2);
684
685     else if (id == qMetaTypeId<QList<QList<double> > >())
686         return compare(qvariant_cast<QList<QList<double> > >(v1), qvariant_cast<QList<QList<double> > >(v2));
687
688     else if (id == qMetaTypeId<QList<QStringList> >())
689         return qvariant_cast<QList<QStringList> >(v1) == qvariant_cast<QList<QStringList> >(v2);
690
691     else if (id == qMetaTypeId<QList<QByteArray> >())
692         return qvariant_cast<QList<QByteArray> >(v1) == qvariant_cast<QList<QByteArray> >(v2);
693
694     else if (id == qMetaTypeId<QList<QVariantList> >())
695         return compare(qvariant_cast<QList<QVariantList> >(v1), qvariant_cast<QList<QVariantList> >(v2));
696
697     else if (id == qMetaTypeId<QMap<int, QString> >())
698         return compare(qvariant_cast<QMap<int, QString> >(v1), qvariant_cast<QMap<int, QString> >(v2));
699
700     else if (id == qMetaTypeId<QMap<QString, QString> >()) // ssmap
701         return compare(qvariant_cast<QMap<QString, QString> >(v1), qvariant_cast<QMap<QString, QString> >(v2));
702
703     else if (id == qMetaTypeId<QMap<QDBusObjectPath, QString> >())
704         return compare(qvariant_cast<QMap<QDBusObjectPath, QString> >(v1), qvariant_cast<QMap<QDBusObjectPath, QString> >(v2));
705
706     else if (id == qMetaTypeId<QHash<qlonglong, QDateTime> >()) // lldtmap
707         return compare(qvariant_cast<QHash<qint64, QDateTime> >(v1), qvariant_cast<QHash<qint64, QDateTime> >(v2));
708
709     else if (id == qMetaTypeId<QHash<QDBusSignature, QString> >())
710         return compare(qvariant_cast<QHash<QDBusSignature, QString> >(v1), qvariant_cast<QHash<QDBusSignature, QString> >(v2));
711
712     else if (id == qMetaTypeId<MyStruct>()) // (is)
713             return qvariant_cast<MyStruct>(v1) == qvariant_cast<MyStruct>(v2);
714
715     else if (id < int(QVariant::UserType)) // yes, v1.type()
716         // QVariant can compare
717         return v1 == v2;
718
719     else {
720         qWarning() << "Please write a comparison case for type" << v1.typeName();
721         return false;           // unknown type
722     }
723 }