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