Introduce QMetaType::UnknownType.
[profile/ivi/qtbase.git] / src / corelib / kernel / qvariant.cpp
index 76957f1..ae51764 100644 (file)
@@ -1,8 +1,7 @@
 /****************************************************************************
 **
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
 **
 ** This file is part of the QtCore module of the Qt Toolkit.
 **
@@ -35,6 +34,7 @@
 **
 **
 **
+**
 ** $QT_END_LICENSE$
 **
 ****************************************************************************/
 #include "qstringlist.h"
 #include "qurl.h"
 #include "qlocale.h"
+#include "quuid.h"
+#ifndef QT_BOOTSTRAPPED
+#include "qabstractitemmodel.h"
+#endif
 #include "private/qvariant_p.h"
+#include "qmetatype_p.h"
 
 #ifndef QT_NO_GEOM_VARIANT
 #include "qsize.h"
@@ -72,299 +77,73 @@ QT_BEGIN_NAMESPACE
 #  define FLT_DIG 6
 #endif
 
-static void construct(QVariant::Private *x, const void *copy)
+namespace {
+class HandlersManager
 {
-    x->is_shared = false;
+    static const QVariant::Handler *Handlers[QModulesPrivate::ModulesCount];
+public:
+    const QVariant::Handler *operator[] (const int typeId) const
+    {
+        return Handlers[QModulesPrivate::moduleForType(typeId)];
+    }
 
-    switch (x->type) {
-    case QVariant::String:
-        v_construct<QString>(x, copy);
-        break;
-    case QVariant::Char:
-        v_construct<QChar>(x, copy);
-        break;
-    case QVariant::StringList:
-        v_construct<QStringList>(x, copy);
-        break;
-    case QVariant::Map:
-        v_construct<QVariantMap>(x, copy);
-        break;
-    case QVariant::Hash:
-        v_construct<QVariantHash>(x, copy);
-        break;
-    case QVariant::List:
-        v_construct<QVariantList>(x, copy);
-        break;
-    case QVariant::Date:
-        v_construct<QDate>(x, copy);
-        break;
-    case QVariant::Time:
-        v_construct<QTime>(x, copy);
-        break;
-    case QVariant::DateTime:
-        v_construct<QDateTime>(x, copy);
-        break;
-    case QVariant::ByteArray:
-        v_construct<QByteArray>(x, copy);
-        break;
-    case QVariant::BitArray:
-        v_construct<QBitArray>(x, copy);
-        break;
-#ifndef QT_NO_GEOM_VARIANT
-    case QVariant::Size:
-        v_construct<QSize>(x, copy);
-        break;
-    case QVariant::SizeF:
-        v_construct<QSizeF>(x, copy);
-        break;
-    case QVariant::Rect:
-        v_construct<QRect>(x, copy);
-        break;
-    case QVariant::LineF:
-        v_construct<QLineF>(x, copy);
-        break;
-    case QVariant::Line:
-        v_construct<QLine>(x, copy);
-        break;
-    case QVariant::RectF:
-        v_construct<QRectF>(x, copy);
-        break;
-    case QVariant::Point:
-        v_construct<QPoint>(x, copy);
-        break;
-    case QVariant::PointF:
-        v_construct<QPointF>(x, copy);
-        break;
-#endif
-    case QVariant::Url:
-        v_construct<QUrl>(x, copy);
-        break;
-    case QVariant::Locale:
-        v_construct<QLocale>(x, copy);
-        break;
-#ifndef QT_NO_REGEXP
-    case QVariant::RegExp:
-        v_construct<QRegExp>(x, copy);
-        break;
-#endif
-#ifndef QT_BOOTSTRAPPED
-    case QVariant::EasingCurve:
-        v_construct<QEasingCurve>(x, copy);
-        break;
-#endif
-    case QVariant::Int:
-        x->data.i = copy ? *static_cast<const int *>(copy) : 0;
-        break;
-    case QVariant::UInt:
-        x->data.u = copy ? *static_cast<const uint *>(copy) : 0u;
-        break;
-    case QVariant::Bool:
-        x->data.b = copy ? *static_cast<const bool *>(copy) : false;
-        break;
-    case QVariant::Double:
-        x->data.d = copy ? *static_cast<const double*>(copy) : 0.0;
-        break;
-    case QMetaType::Float:
-        x->data.f = copy ? *static_cast<const float*>(copy) : 0.0f;
-        break;
-    case QMetaType::QObjectStar:
-        x->data.o = copy ? *static_cast<QObject *const*>(copy) : 0;
-        break;
-    case QVariant::LongLong:
-        x->data.ll = copy ? *static_cast<const qlonglong *>(copy) : Q_INT64_C(0);
-        break;
-    case QVariant::ULongLong:
-        x->data.ull = copy ? *static_cast<const qulonglong *>(copy) : Q_UINT64_C(0);
-        break;
-    case QVariant::Invalid:
-    case QVariant::UserType:
-        break;
-    default:
-        void *ptr = QMetaType::create(x->type, copy);
-        if (!ptr) {
-            x->type = QVariant::Invalid;
-        } else {
-            x->is_shared = true;
-            x->data.shared = new QVariant::PrivateShared(ptr);
-        }
-        break;
+    void registerHandler(const QModulesPrivate::Names name, const QVariant::Handler *handler)
+    {
+        Handlers[name] = handler;
     }
-    x->is_null = !copy;
-}
 
-static void clear(QVariant::Private *d)
-{
-    switch (d->type) {
-    case QVariant::String:
-        v_clear<QString>(d);
-        break;
-    case QVariant::Char:
-        v_clear<QChar>(d);
-        break;
-    case QVariant::StringList:
-        v_clear<QStringList>(d);
-        break;
-    case QVariant::Map:
-        v_clear<QVariantMap>(d);
-        break;
-    case QVariant::Hash:
-        v_clear<QVariantHash>(d);
-        break;
-    case QVariant::List:
-        v_clear<QVariantList>(d);
-        break;
-    case QVariant::Date:
-        v_clear<QDate>(d);
-        break;
-    case QVariant::Time:
-        v_clear<QTime>(d);
-        break;
-    case QVariant::DateTime:
-        v_clear<QDateTime>(d);
-        break;
-    case QVariant::ByteArray:
-        v_clear<QByteArray>(d);
-        break;
-    case QVariant::BitArray:
-        v_clear<QBitArray>(d);
-        break;
-#ifndef QT_NO_GEOM_VARIANT
-    case QVariant::Point:
-        v_clear<QPoint>(d);
-        break;
-    case QVariant::PointF:
-        v_clear<QPointF>(d);
-        break;
-    case QVariant::Size:
-        v_clear<QSize>(d);
-        break;
-    case QVariant::SizeF:
-        v_clear<QSizeF>(d);
-        break;
-    case QVariant::Rect:
-        v_clear<QRect>(d);
-        break;
-    case QVariant::LineF:
-        v_clear<QLineF>(d);
-        break;
-    case QVariant::Line:
-        v_clear<QLine>(d);
-        break;
-    case QVariant::RectF:
-        v_clear<QRectF>(d);
-        break;
-#endif
-    case QVariant::Url:
-        v_clear<QUrl>(d);
-        break;
-    case QVariant::Locale:
-        v_clear<QLocale>(d);
-        break;
-#ifndef QT_NO_REGEXP
-    case QVariant::RegExp:
-        v_clear<QRegExp>(d);
-        break;
+    inline void unregisterHandler(const QModulesPrivate::Names name);
+};
+}  // namespace
+
+namespace {
+template<typename T>
+struct TypeDefinition {
+    static const bool IsAvailable = true;
+};
+
+// Ignore these types, as incomplete
+#ifdef QT_BOOTSTRAPPED
+template<> struct TypeDefinition<QEasingCurve> { static const bool IsAvailable = false; };
+template<> struct TypeDefinition<QModelIndex> { static const bool IsAvailable = false; };
 #endif
-#ifndef QT_BOOTSTRAPPED
-    case QVariant::EasingCurve:
-        v_clear<QEasingCurve>(d);
-        break;
+#ifdef QT_NO_GEOM_VARIANT
+template<> struct TypeDefinition<QRect> { static const bool IsAvailable = false; };
+template<> struct TypeDefinition<QRectF> { static const bool IsAvailable = false; };
+template<> struct TypeDefinition<QSize> { static const bool IsAvailable = false; };
+template<> struct TypeDefinition<QSizeF> { static const bool IsAvailable = false; };
+template<> struct TypeDefinition<QLine> { static const bool IsAvailable = false; };
+template<> struct TypeDefinition<QLineF> { static const bool IsAvailable = false; };
+template<> struct TypeDefinition<QPoint> { static const bool IsAvailable = false; };
+template<> struct TypeDefinition<QPointF> { static const bool IsAvailable = false; };
 #endif
-    case QVariant::LongLong:
-    case QVariant::ULongLong:
-    case QVariant::Double:
-    case QMetaType::Float:
-    case QMetaType::QObjectStar:
-        break;
-    case QVariant::Invalid:
-    case QVariant::UserType:
-    case QVariant::Int:
-    case QVariant::UInt:
-    case QVariant::Bool:
-        break;
-    default:
-        QMetaType::destroy(d->type, d->data.shared->ptr);
-        delete d->data.shared;
-        break;
-    }
 
-    d->type = QVariant::Invalid;
-    d->is_null = true;
-    d->is_shared = false;
-}
+struct CoreTypesFilter {
+    template<typename T>
+    struct Acceptor {
+        static const bool IsAccepted = QTypeModuleInfo<T>::IsCore && TypeDefinition<T>::IsAvailable;
+    };
+};
+} // annonymous used to hide TypeDefinition
 
-static bool isNull(const QVariant::Private *d)
+namespace { // annonymous used to hide QVariant handlers
+
+static void construct(QVariant::Private *x, const void *copy)
 {
-    switch(d->type) {
-    case QVariant::String:
-        return v_cast<QString>(d)->isNull();
-    case QVariant::Char:
-        return v_cast<QChar>(d)->isNull();
-    case QVariant::Date:
-        return v_cast<QDate>(d)->isNull();
-    case QVariant::Time:
-        return v_cast<QTime>(d)->isNull();
-    case QVariant::DateTime:
-        return v_cast<QDateTime>(d)->isNull();
-    case QVariant::ByteArray:
-        return v_cast<QByteArray>(d)->isNull();
-    case QVariant::BitArray:
-        return v_cast<QBitArray>(d)->isNull();
-#ifndef QT_NO_GEOM_VARIANT
-    case QVariant::Size:
-        return v_cast<QSize>(d)->isNull();
-    case QVariant::SizeF:
-        return v_cast<QSizeF>(d)->isNull();
-    case QVariant::Rect:
-        return v_cast<QRect>(d)->isNull();
-    case QVariant::Line:
-        return v_cast<QLine>(d)->isNull();
-    case QVariant::LineF:
-        return v_cast<QLineF>(d)->isNull();
-    case QVariant::RectF:
-        return v_cast<QRectF>(d)->isNull();
-    case QVariant::Point:
-        return v_cast<QPoint>(d)->isNull();
-    case QVariant::PointF:
-        return v_cast<QPointF>(d)->isNull();
-#endif
-#ifndef QT_BOOTSTRAPPED
-    case QVariant::EasingCurve:
-#endif
-    case QVariant::Url:
-    case QVariant::Locale:
-    case QVariant::RegExp:
-    case QVariant::StringList:
-    case QVariant::Map:
-    case QVariant::Hash:
-    case QVariant::List:
-    case QVariant::Invalid:
-    case QVariant::UserType:
-    case QVariant::Int:
-    case QVariant::UInt:
-    case QVariant::LongLong:
-    case QVariant::ULongLong:
-    case QVariant::Bool:
-    case QVariant::Double:
-    case QMetaType::Float:
-    case QMetaType::QObjectStar:
-        break;
-    }
-    return d->is_null;
+    QVariantConstructor<CoreTypesFilter> constructor(x, copy);
+    QMetaTypeSwitcher::switcher<void>(constructor, x->type, 0);
 }
 
-/*
-  \internal
-  \since 4.4
+static void clear(QVariant::Private *d)
+{
+    QVariantDestructor<CoreTypesFilter> cleaner(d);
+    QMetaTypeSwitcher::switcher<void>(cleaner, d->type, 0);
+}
 
-  We cannot use v_cast() for QMetaType's numeric types because they're smaller than QVariant::Private::Data,
-  which in turns makes v_cast() believe the value is stored in d->data.c. But
-  it's not, since we're a QMetaType type.
- */
-template<typename T>
-inline bool compareNumericMetaType(const QVariant::Private *const a, const QVariant::Private *const b)
+static bool isNull(const QVariant::Private *d)
 {
-    return *static_cast<const T *>(a->data.shared->ptr) == *static_cast<const T *>(b->data.shared->ptr);
+    QVariantIsNull<CoreTypesFilter> isNull(d);
+    return QMetaTypeSwitcher::switcher<bool>(isNull, d->type, 0);
 }
 
 /*!
@@ -375,123 +154,8 @@ inline bool compareNumericMetaType(const QVariant::Private *const a, const QVari
  */
 static bool compare(const QVariant::Private *a, const QVariant::Private *b)
 {
-    switch(a->type) {
-    case QVariant::List:
-        return *v_cast<QVariantList>(a) == *v_cast<QVariantList>(b);
-    case QVariant::Map: {
-        const QVariantMap *m1 = v_cast<QVariantMap>(a);
-        const QVariantMap *m2 = v_cast<QVariantMap>(b);
-        if (m1->count() != m2->count())
-            return false;
-        QVariantMap::ConstIterator it = m1->constBegin();
-        QVariantMap::ConstIterator it2 = m2->constBegin();
-        while (it != m1->constEnd()) {
-            if (*it != *it2 || it.key() != it2.key())
-                return false;
-            ++it;
-            ++it2;
-        }
-        return true;
-    }
-    case QVariant::Hash:
-        return *v_cast<QVariantHash>(a) == *v_cast<QVariantHash>(b);
-    case QVariant::String:
-        return *v_cast<QString>(a) == *v_cast<QString>(b);
-    case QVariant::Char:
-        return *v_cast<QChar>(a) == *v_cast<QChar>(b);
-    case QVariant::StringList:
-        return *v_cast<QStringList>(a) == *v_cast<QStringList>(b);
-#ifndef QT_NO_GEOM_VARIANT
-    case QVariant::Size:
-        return *v_cast<QSize>(a) == *v_cast<QSize>(b);
-    case QVariant::SizeF:
-        return *v_cast<QSizeF>(a) == *v_cast<QSizeF>(b);
-    case QVariant::Rect:
-        return *v_cast<QRect>(a) == *v_cast<QRect>(b);
-    case QVariant::Line:
-        return *v_cast<QLine>(a) == *v_cast<QLine>(b);
-    case QVariant::LineF:
-        return *v_cast<QLineF>(a) == *v_cast<QLineF>(b);
-    case QVariant::RectF:
-        return *v_cast<QRectF>(a) == *v_cast<QRectF>(b);
-    case QVariant::Point:
-        return *v_cast<QPoint>(a) == *v_cast<QPoint>(b);
-    case QVariant::PointF:
-        return *v_cast<QPointF>(a) == *v_cast<QPointF>(b);
-#endif
-    case QVariant::Url:
-        return *v_cast<QUrl>(a) == *v_cast<QUrl>(b);
-    case QVariant::Locale:
-        return *v_cast<QLocale>(a) == *v_cast<QLocale>(b);
-#ifndef QT_NO_REGEXP
-    case QVariant::RegExp:
-        return *v_cast<QRegExp>(a) == *v_cast<QRegExp>(b);
-#endif
-    case QVariant::Int:
-        return a->data.i == b->data.i;
-    case QVariant::UInt:
-        return a->data.u == b->data.u;
-    case QVariant::LongLong:
-        return a->data.ll == b->data.ll;
-    case QVariant::ULongLong:
-        return a->data.ull == b->data.ull;
-    case QVariant::Bool:
-        return a->data.b == b->data.b;
-    case QVariant::Double:
-        return a->data.d == b->data.d;
-    case QMetaType::Float:
-        return a->data.f == b->data.f;
-    case QMetaType::QObjectStar:
-        return a->data.o == b->data.o;
-    case QVariant::Date:
-        return *v_cast<QDate>(a) == *v_cast<QDate>(b);
-    case QVariant::Time:
-        return *v_cast<QTime>(a) == *v_cast<QTime>(b);
-    case QVariant::DateTime:
-        return *v_cast<QDateTime>(a) == *v_cast<QDateTime>(b);
-#ifndef QT_BOOTSTRAPPED
-    case QVariant::EasingCurve:
-        return *v_cast<QEasingCurve>(a) == *v_cast<QEasingCurve>(b);
-#endif
-    case QVariant::ByteArray:
-        return *v_cast<QByteArray>(a) == *v_cast<QByteArray>(b);
-    case QVariant::BitArray:
-        return *v_cast<QBitArray>(a) == *v_cast<QBitArray>(b);
-    case QVariant::Invalid:
-        return true;
-    case QMetaType::Long:
-        return compareNumericMetaType<long>(a, b);
-    case QMetaType::ULong:
-        return compareNumericMetaType<ulong>(a, b);
-    case QMetaType::Short:
-        return compareNumericMetaType<short>(a, b);
-    case QMetaType::UShort:
-        return compareNumericMetaType<ushort>(a, b);
-    case QMetaType::UChar:
-        return compareNumericMetaType<uchar>(a, b);
-    case QMetaType::Char:
-        return compareNumericMetaType<char>(a, b);
-    default:
-        break;
-    }
-    if (!QMetaType::isRegistered(a->type))
-        qFatal("QVariant::compare: type %d unknown to QVariant.", a->type);
-
-    const void *a_ptr = a->is_shared ? a->data.shared->ptr : &(a->data.ptr);
-    const void *b_ptr = b->is_shared ? b->data.shared->ptr : &(b->data.ptr);
-
-    /* The reason we cannot place this test in a case branch above for the types
-     * QMetaType::VoidStar, QMetaType::QObjectStar and so forth, is that it wouldn't include
-     * user defined pointer types. */
-    const char *const typeName = QMetaType::typeName(a->type);
-    uint typeNameLen = qstrlen(typeName);
-    if (typeNameLen > 0 && typeName[typeNameLen - 1] == '*')
-        return *static_cast<void *const *>(a_ptr) == *static_cast<void *const *>(b_ptr);
-
-    if (a->is_null && b->is_null)
-        return true;
-
-    return a_ptr == b_ptr;
+    QVariantComparator<CoreTypesFilter> comparator(a, b);
+    return QMetaTypeSwitcher::switcher<bool>(comparator, a->type, 0);
 }
 
 /*!
@@ -505,11 +169,11 @@ static qlonglong qMetaTypeNumber(const QVariant::Private *d)
     case QMetaType::LongLong:
         return d->data.ll;
     case QMetaType::Char:
-        return qlonglong(*static_cast<signed char *>(d->data.shared->ptr));
+        return qlonglong(d->data.c);
     case QMetaType::Short:
-        return qlonglong(*static_cast<short *>(d->data.shared->ptr));
+        return qlonglong(d->data.s);
     case QMetaType::Long:
-        return qlonglong(*static_cast<long *>(d->data.shared->ptr));
+        return qlonglong(d->data.l);
     case QMetaType::Float:
         return qRound64(d->data.f);
     case QVariant::Double:
@@ -527,11 +191,11 @@ static qulonglong qMetaTypeUNumber(const QVariant::Private *d)
     case QVariant::ULongLong:
         return d->data.ull;
     case QMetaType::UChar:
-        return qulonglong(*static_cast<unsigned char *>(d->data.shared->ptr));
+        return d->data.uc;
     case QMetaType::UShort:
-        return qulonglong(*static_cast<ushort *>(d->data.shared->ptr));
+        return d->data.us;
     case QMetaType::ULong:
-        return qulonglong(*static_cast<ulong *>(d->data.shared->ptr));
+        return d->data.ul;
     }
     Q_ASSERT(false);
     return 0;
@@ -615,7 +279,7 @@ inline bool qt_convertToBool(const QVariant::Private *const d)
 
  Converts \a d to type \a t, which is placed in \a result.
  */
-static bool convert(const QVariant::Private *d, QVariant::Type t, void *result, bool *ok)
+static bool convert(const QVariant::Private *d, int t, void *result, bool *ok)
 {
     Q_ASSERT(d->type != uint(t));
     Q_ASSERT(result);
@@ -642,7 +306,7 @@ static bool convert(const QVariant::Private *d, QVariant::Type t, void *result,
             break;
         case QMetaType::Char:
         case QMetaType::UChar:
-            *str = QChar::fromAscii(*static_cast<char *>(d->data.shared->ptr));
+            *str = QChar::fromAscii(d->data.c);
             break;
         case QMetaType::Short:
         case QMetaType::Long:
@@ -686,6 +350,9 @@ static bool convert(const QVariant::Private *d, QVariant::Type t, void *result,
         case QVariant::Url:
             *str = v_cast<QUrl>(d)->toString();
             break;
+        case QVariant::Uuid:
+            *str = v_cast<QUuid>(d)->toString();
+            break;
         default:
             return false;
         }
@@ -835,7 +502,7 @@ static bool convert(const QVariant::Private *d, QVariant::Type t, void *result,
             break;
         case QMetaType::Char:
         case QMetaType::UChar:
-            *ba = QByteArray(1, *static_cast<char *>(d->data.shared->ptr));
+            *ba = QByteArray(1, d->data.c);
             break;
         case QVariant::Int:
         case QVariant::LongLong:
@@ -1050,110 +717,27 @@ static bool convert(const QVariant::Private *d, QVariant::Type t, void *result,
         return *ok;
     }
 #endif
+    case QVariant::Uuid:
+        switch (d->type) {
+        case QVariant::String:
+            *static_cast<QUuid *>(result) = QUuid(*v_cast<QString>(d));
+            break;
+        default:
+            return false;
+        }
+        break;
     default:
         return false;
     }
     return true;
 }
 
-#if !defined(QT_NO_DEBUG_STREAM) && !defined(Q_BROKEN_DEBUG_STREAM)
+#if !defined(QT_NO_DEBUG_STREAM)
 static void streamDebug(QDebug dbg, const QVariant &v)
 {
-    switch (v.userType()) {
-    case QVariant::Int:
-        dbg.nospace() << v.toInt();
-        break;
-    case QVariant::UInt:
-        dbg.nospace() << v.toUInt();
-        break;
-    case QVariant::LongLong:
-        dbg.nospace() << v.toLongLong();
-        break;
-    case QVariant::ULongLong:
-        dbg.nospace() << v.toULongLong();
-        break;
-    case QMetaType::Float:
-        dbg.nospace() << v.toFloat();
-        break;
-    case QMetaType::QObjectStar:
-        dbg.nospace() << qvariant_cast<QObject *>(v);
-        break;
-    case QVariant::Double:
-        dbg.nospace() << v.toDouble();
-        break;
-    case QVariant::Bool:
-        dbg.nospace() << v.toBool();
-        break;
-    case QVariant::String:
-        dbg.nospace() << v.toString();
-        break;
-    case QVariant::Char:
-        dbg.nospace() << v.toChar();
-        break;
-    case QVariant::StringList:
-        dbg.nospace() << v.toStringList();
-        break;
-    case QVariant::Map:
-        dbg.nospace() << v.toMap();
-        break;
-    case QVariant::Hash:
-        dbg.nospace() << v.toHash();
-        break;
-    case QVariant::List:
-        dbg.nospace() << v.toList();
-        break;
-    case QVariant::Date:
-        dbg.nospace() << v.toDate();
-        break;
-    case QVariant::Time:
-        dbg.nospace() << v.toTime();
-        break;
-    case QVariant::DateTime:
-        dbg.nospace() << v.toDateTime();
-        break;
-#ifndef QT_BOOTSTRAPPED
-    case QVariant::EasingCurve:
-        dbg.nospace() << v.toEasingCurve();
-        break;
-#endif
-    case QVariant::ByteArray:
-        dbg.nospace() << v.toByteArray();
-        break;
-    case QVariant::Url:
-        dbg.nospace() << v.toUrl();
-        break;
-#ifndef QT_NO_GEOM_VARIANT
-    case QVariant::Point:
-        dbg.nospace() << v.toPoint();
-        break;
-    case QVariant::PointF:
-        dbg.nospace() << v.toPointF();
-        break;
-    case QVariant::Rect:
-        dbg.nospace() << v.toRect();
-        break;
-    case QVariant::Size:
-        dbg.nospace() << v.toSize();
-        break;
-    case QVariant::SizeF:
-        dbg.nospace() << v.toSizeF();
-        break;
-    case QVariant::Line:
-        dbg.nospace() << v.toLine();
-        break;
-    case QVariant::LineF:
-        dbg.nospace() << v.toLineF();
-        break;
-    case QVariant::RectF:
-        dbg.nospace() << v.toRectF();
-        break;
-#endif
-    case QVariant::BitArray:
-        //dbg.nospace() << v.toBitArray();
-        break;
-    default:
-        break;
-    }
+    QVariant::Private *d = const_cast<QVariant::Private *>(&v.data_ptr());
+    QVariantDebugStream<CoreTypesFilter> stream(dbg, d);
+    QMetaTypeSwitcher::switcher<void>(stream, d->type, 0);
 }
 #endif
 
@@ -1168,20 +752,150 @@ const QVariant::Handler qt_kernel_variant_handler = {
     compare,
     convert,
     0,
-#if !defined(QT_NO_DEBUG_STREAM) && !defined(Q_BROKEN_DEBUG_STREAM)
+#if !defined(QT_NO_DEBUG_STREAM)
     streamDebug
 #else
     0
 #endif
 };
 
+static void dummyConstruct(QVariant::Private *, const void *) { Q_ASSERT_X(false, "QVariant", "Trying to construct an unknown type"); }
+static void dummyClear(QVariant::Private *) { Q_ASSERT_X(false, "QVariant", "Trying to clear an unknown type"); }
+static bool dummyIsNull(const QVariant::Private *d) { Q_ASSERT_X(false, "QVariant::isNull", "Trying to call isNull on an unknown type"); return d->is_null; }
+static bool dummyCompare(const QVariant::Private *, const QVariant::Private *) { Q_ASSERT_X(false, "QVariant", "Trying to compare an unknown types"); return false; }
+static bool dummyConvert(const QVariant::Private *, int, void *, bool *) { Q_ASSERT_X(false, "QVariant", "Trying to convert an unknown type"); return false; }
+#if !defined(QT_NO_DEBUG_STREAM)
+static void dummyStreamDebug(QDebug, const QVariant &) { Q_ASSERT_X(false, "QVariant", "Trying to convert an unknown type"); }
+#endif
+const QVariant::Handler qt_dummy_variant_handler = {
+    dummyConstruct,
+    dummyClear,
+    dummyIsNull,
+#ifndef QT_NO_DATASTREAM
+    0,
+    0,
+#endif
+    dummyCompare,
+    dummyConvert,
+    0,
+#if !defined(QT_NO_DEBUG_STREAM)
+    dummyStreamDebug
+#else
+    0
+#endif
+};
+
+static void customConstruct(QVariant::Private *d, const void *copy)
+{
+    const QMetaType type(d->type);
+    const uint size = type.sizeOf();
+    if (!size) {
+        d->type = QVariant::Invalid;
+        return;
+    }
+
+    // this logic should match with QVariantIntegrator::CanUseInternalSpace
+    if (size <= sizeof(QVariant::Private::Data)
+            && (type.flags() & QMetaType::MovableType)) {
+        type.construct(&d->data.ptr, copy);
+        d->is_shared = false;
+    } else {
+        void *ptr = type.create(copy);
+        d->is_shared = true;
+        d->data.shared = new QVariant::PrivateShared(ptr);
+    }
+}
+
+static void customClear(QVariant::Private *d)
+{
+    if (!d->is_shared) {
+        QMetaType::destruct(d->type, &d->data.ptr);
+    } else {
+        QMetaType::destroy(d->type, d->data.shared->ptr);
+        delete d->data.shared;
+    }
+}
+
+static bool customIsNull(const QVariant::Private *d)
+{
+    return d->is_null;
+}
+
+static bool customCompare(const QVariant::Private *a, const QVariant::Private *b)
+{
+    const char *const typeName = QMetaType::typeName(a->type);
+    if (Q_UNLIKELY(!typeName) && Q_LIKELY(!QMetaType::isRegistered(a->type)))
+        qFatal("QVariant::compare: type %d unknown to QVariant.", a->type);
+
+    const void *a_ptr = a->is_shared ? a->data.shared->ptr : &(a->data.ptr);
+    const void *b_ptr = b->is_shared ? b->data.shared->ptr : &(b->data.ptr);
+
+    uint typeNameLen = qstrlen(typeName);
+    if (typeNameLen > 0 && typeName[typeNameLen - 1] == '*')
+        return *static_cast<void *const *>(a_ptr) == *static_cast<void *const *>(b_ptr);
+
+    if (a->is_null && b->is_null)
+        return true;
+
+    return !memcmp(a_ptr, b_ptr, QMetaType::sizeOf(a->type));
+}
+
+static bool customConvert(const QVariant::Private *, int, void *, bool *ok)
+{
+    if (ok)
+        *ok = false;
+    return false;
+}
+
+#if !defined(QT_NO_DEBUG_STREAM)
+static void customStreamDebug(QDebug, const QVariant &) {}
+#endif
+
+const QVariant::Handler qt_custom_variant_handler = {
+    customConstruct,
+    customClear,
+    customIsNull,
+#ifndef QT_NO_DATASTREAM
+    0,
+    0,
+#endif
+    customCompare,
+    customConvert,
+    0,
+#if !defined(QT_NO_DEBUG_STREAM)
+    customStreamDebug
+#else
+    0
+#endif
+};
+
+} // annonymous used to hide QVariant handlers
+
+static HandlersManager handlerManager;
+Q_STATIC_ASSERT_X(!QModulesPrivate::Core, "Initialization assumes that ModulesNames::Core is 0");
+const QVariant::Handler *HandlersManager::Handlers[QModulesPrivate::ModulesCount]
+                                        = { &qt_kernel_variant_handler, &qt_dummy_variant_handler,
+                                            &qt_dummy_variant_handler, &qt_custom_variant_handler };
+
 Q_CORE_EXPORT const QVariant::Handler *qcoreVariantHandler()
 {
     return &qt_kernel_variant_handler;
 }
 
+inline void HandlersManager::unregisterHandler(const QModulesPrivate::Names name)
+{
+    Handlers[name] = &qt_dummy_variant_handler;
+}
 
-const QVariant::Handler *QVariant::handler = &qt_kernel_variant_handler;
+Q_CORE_EXPORT void QVariantPrivate::registerHandler(const int /* Modules::Names */name, const QVariant::Handler *handler)
+{
+    handlerManager.registerHandler(static_cast<QModulesPrivate::Names>(name), handler);
+}
+
+Q_CORE_EXPORT void QVariantPrivate::unregisterHandler(const int /* Modules::Names */ name)
+{
+    handlerManager.unregisterHandler(static_cast<QModulesPrivate::Names>(name));
+}
 
 /*!
     \class QVariant
@@ -1267,6 +981,7 @@ const QVariant::Handler *QVariant::handler = &qt_kernel_variant_handler;
 */
 
 /*!
+    \obsolete Use QMetaType::Type instead
     \enum QVariant::Type
 
     This enum type defines the types of variable that a QVariant can
@@ -1285,6 +1000,8 @@ const QVariant::Handler *QVariant::handler = &qt_kernel_variant_handler;
     \value DateTime  a QDateTime
     \value Double  a double
     \value EasingCurve a QEasingCurve
+    \value Uuid a QUuid
+    \value ModelIndex a QModelIndex
     \value Font  a QFont
     \value Hash a QVariantHash
     \value Icon  a QIcon
@@ -1304,9 +1021,9 @@ const QVariant::Handler *QVariant::handler = &qt_kernel_variant_handler;
     \value Pen  a QPen
     \value Pixmap  a QPixmap
     \value Point  a QPoint
-    \value PointArray  a QPointArray
     \value PointF  a QPointF
     \value Polygon a QPolygon
+    \value PolygonF a QPolygonF
     \value Quaternion  a QQuaternion
     \value Rect  a QRect
     \value RectF  a QRectF
@@ -1345,9 +1062,9 @@ const QVariant::Handler *QVariant::handler = &qt_kernel_variant_handler;
 
 
 /*!
-    \fn QVariant::QVariant(int typeOrUserType, const void *copy)
+    \fn QVariant::QVariant(int typeId, const void *copy)
 
-    Constructs variant of type \a typeOrUserType, and initializes with
+    Constructs variant of type \a typeId, and initializes with
     \a copy if \a copy is not 0.
 
     Note that you have to pass the address of the variable you want stored.
@@ -1380,7 +1097,7 @@ const QVariant::Handler *QVariant::handler = &qt_kernel_variant_handler;
 void QVariant::create(int type, const void *copy)
 {
     d.type = type;
-    handler->construct(&d, copy);
+    handlerManager[type]->construct(&d, copy);
 }
 
 /*!
@@ -1396,8 +1113,8 @@ void QVariant::create(int type, const void *copy)
 
 QVariant::~QVariant()
 {
-    if ((d.is_shared && !d.data.shared->ref.deref()) || (!d.is_shared && d.type > Char && d.type < UserType))
-        handler->clear(&d);
+    if ((d.is_shared && !d.data.shared->ref.deref()) || (!d.is_shared && d.type > Char))
+        handlerManager[d.type]->clear(&d);
 }
 
 /*!
@@ -1412,8 +1129,8 @@ QVariant::QVariant(const QVariant &p)
 {
     if (d.is_shared) {
         d.data.shared->ref.ref();
-    } else if (p.d.type > Char && p.d.type < QVariant::UserType) {
-        handler->construct(&d, p.constData());
+    } else if (p.d.type > Char) {
+        handlerManager[d.type]->construct(&d, p.constData());
         d.is_null = p.d.is_null;
     }
 }
@@ -1445,17 +1162,15 @@ QVariant::QVariant(QDataStream &s)
   \fn QVariant::QVariant(const char *val)
 
     Constructs a new variant with a string value of \a val.
-    The variant creates a deep copy of \a val, using the encoding
-    set by QTextCodec::setCodecForCStrings().
+    The variant creates a deep copy of \a val into a QString assuming
+    UTF-8 encoding on the input \a val.
 
     Note that \a val is converted to a QString for storing in the
-    variant and QVariant::type() will return QMetaType::QString for
+    variant and QVariant::userType() will return QMetaType::QString for
     the variant.
 
     You can disable this operator by defining \c
     QT_NO_CAST_FROM_ASCII when you compile your applications.
-
-    \sa QTextCodec::setCodecForCStrings()
 */
 
 #ifndef QT_NO_CAST_FROM_ASCII
@@ -1626,7 +1341,7 @@ QVariant::QVariant(const char *val)
 */
 
 /*!
-  \fn QVariant::QVariant(const QChar &c)
+  \fn QVariant::QVariant(QChar c)
 
   Constructs a new variant with a char value, \a c.
 */
@@ -1658,22 +1373,21 @@ QVariant::QVariant(const char *val)
 
 QVariant::QVariant(Type type)
 { create(type, 0); }
-QVariant::QVariant(int typeOrUserType, const void *copy)
-{ create(typeOrUserType, copy); d.is_null = false; }
+QVariant::QVariant(int typeId, const void *copy)
+{ create(typeId, copy); d.is_null = false; }
 
 /*! \internal
     flags is true if it is a pointer type
  */
-QVariant::QVariant(int typeOrUserType, const void *copy, uint flags)
+QVariant::QVariant(int typeId, const void *copy, uint flags)
 {
     if (flags) { //type is a pointer type
-        d.type = typeOrUserType;
+        d.type = typeId;
         d.data.ptr = *reinterpret_cast<void *const*>(copy);
-        d.is_null = false;
     } else {
-        create(typeOrUserType, copy);
-        d.is_null = false;
+        create(typeId, copy);
     }
+    d.is_null = false;
 }
 
 QVariant::QVariant(int val)
@@ -1695,7 +1409,7 @@ QVariant::QVariant(const QBitArray &val)
 { d.is_null = false; d.type = BitArray; v_construct<QBitArray>(&d, val);  }
 QVariant::QVariant(const QString &val)
 { d.is_null = false; d.type = String; v_construct<QString>(&d, val);  }
-QVariant::QVariant(const QChar &val)
+QVariant::QVariant(QChar val)
 { d.is_null = false; d.type = Char; v_construct<QChar>(&d, val);  }
 QVariant::QVariant(const QLatin1String &val)
 { QString str(val); d.is_null = false; d.type = String; v_construct<QString>(&d, str); }
@@ -1796,9 +1510,9 @@ QVariant& QVariant::operator=(const QVariant &variant)
     if (variant.d.is_shared) {
         variant.d.data.shared->ref.ref();
         d = variant.d;
-    } else if (variant.d.type > Char && variant.d.type < UserType) {
+    } else if (variant.d.type > Char) {
         d.type = variant.d.type;
-        handler->construct(&d, variant.constData());
+        handlerManager[d.type]->construct(&d, variant.constData());
         d.is_null = variant.d.is_null;
     } else {
         d = variant.d;
@@ -1823,14 +1537,14 @@ QVariant& QVariant::operator=(const QVariant &variant)
 
 void QVariant::detach()
 {
-    if (!d.is_shared || d.data.shared->ref == 1)
+    if (!d.is_shared || d.data.shared->ref.load() == 1)
         return;
 
     Private dd;
     dd.type = d.type;
-    handler->construct(&dd, constData());
+    handlerManager[d.type]->construct(&dd, constData());
     if (!d.data.shared->ref.deref())
-        handler->clear(&d);
+        handlerManager[d.type]->clear(&d);
     d.data.shared = dd.data.shared;
 }
 
@@ -1849,7 +1563,7 @@ void QVariant::detach()
 */
 const char *QVariant::typeName() const
 {
-    return typeToName(Type(d.type));
+    return typeToName(d.type);
 }
 
 /*!
@@ -1858,27 +1572,25 @@ const char *QVariant::typeName() const
 */
 void QVariant::clear()
 {
-    if ((d.is_shared && !d.data.shared->ref.deref()) || (!d.is_shared && d.type < UserType && d.type > Char))
-        handler->clear(&d);
+    if ((d.is_shared && !d.data.shared->ref.deref()) || (!d.is_shared && d.type > Char))
+        handlerManager[d.type]->clear(&d);
     d.type = Invalid;
     d.is_null = true;
     d.is_shared = false;
 }
 
 /*!
-    Converts the enum representation of the storage type, \a typ, to
+    Converts the int representation of the storage type, \a typeId, to
     its string representation.
 
     Returns a null pointer if the type is QVariant::Invalid or doesn't exist.
 */
-const char *QVariant::typeToName(Type typ)
+const char *QVariant::typeToName(int typeId)
 {
-    if (typ == Invalid)
+    if (typeId == Invalid)
         return 0;
-    if (typ == UserType)
-        return "UserType";
 
-    return QMetaType::typeName(typ);
+    return QMetaType::typeName(typeId);
 }
 
 
@@ -1893,24 +1605,14 @@ QVariant::Type QVariant::nameToType(const char *name)
 {
     if (!name || !*name)
         return Invalid;
-    if (strcmp(name, "Q3CString") == 0)
-        return ByteArray;
-    if (strcmp(name, "Q_LLONG") == 0)
-        return LongLong;
-    if (strcmp(name, "Q_ULLONG") == 0)
-        return ULongLong;
-    if (strcmp(name, "QIconSet") == 0)
-        return Icon;
-    if (strcmp(name, "UserType") == 0)
-        return UserType;
 
     int metaType = QMetaType::type(name);
-    return metaType <= int(LastGuiType) ? QVariant::Type(metaType) : UserType;
+    return metaType <= int(UserType) ? QVariant::Type(metaType) : UserType;
 }
 
 #ifndef QT_NO_DATASTREAM
 enum { MapFromThreeCount = 36 };
-static const ushort map_from_three[MapFromThreeCount] =
+static const ushort mapIdFromQt3ToCurrent[MapFromThreeCount] =
 {
     QVariant::Invalid,
     QVariant::Map,
@@ -1924,7 +1626,7 @@ static const ushort map_from_three[MapFromThreeCount] =
     QVariant::Size,
     QVariant::Color,
     QVariant::Palette,
-    63, // ColorGroup
+    0, // ColorGroup
     QVariant::Icon,
     QVariant::Point,
     QVariant::Image,
@@ -1960,26 +1662,47 @@ void QVariant::load(QDataStream &s)
 {
     clear();
 
-    quint32 u;
-    s >> u;
+    quint32 typeId;
+    s >> typeId;
     if (s.version() < QDataStream::Qt_4_0) {
-        if (u >= MapFromThreeCount)
+        if (typeId >= MapFromThreeCount)
             return;
-        u = map_from_three[u];
+        typeId = mapIdFromQt3ToCurrent[typeId];
+    } else if (s.version() < QDataStream::Qt_5_0) {
+        if (typeId == 127 /* QVariant::UserType */) {
+            typeId = QMetaType::User;
+        } else if (typeId >= 128 && typeId != QVariant::UserType) {
+            // In Qt4 id == 128 was FirstExtCoreType. In Qt5 ExtCoreTypes set was merged to CoreTypes
+            // by moving all ids down by 97.
+            typeId -= 97;
+        } else if (typeId == 69 /* QIcon */) {
+            // In Qt5 after modularization project this types where moved to a separate module (and ids were downgraded)
+            typeId = QMetaType::QIcon;
+        } else if (typeId == 75 /* QSizePolicy */) {
+            typeId = QMetaType::QSizePolicy;
+        } else if (typeId >= 70) {
+            // and as a result this types recieved lower ids too
+            if (typeId <= 74) { // QImage QPolygon QRegion QBitmap QCursor
+                typeId -=1;
+            } else if (typeId <= 86) { // QKeySequence QPen QTextLength QTextFormat QMatrix QTransform QMatrix4x4 QVector2D QVector3D QVector4D QQuaternion
+                typeId -=2;
+            }
+        }
     }
+
     qint8 is_null = false;
     if (s.version() >= QDataStream::Qt_4_2)
         s >> is_null;
-    if (u == QVariant::UserType) {
+    if (typeId == QVariant::UserType) {
         QByteArray name;
         s >> name;
-        u = QMetaType::type(name);
-        if (!u) {
+        typeId = QMetaType::type(name);
+        if (typeId == QMetaType::UnknownType) {
             s.setStatus(QDataStream::ReadCorruptData);
             return;
         }
     }
-    create(static_cast<int>(u), 0);
+    create(static_cast<int>(typeId), 0);
     d.is_null = is_null;
 
     if (!isValid()) {
@@ -2005,12 +1728,12 @@ void QVariant::load(QDataStream &s)
 */
 void QVariant::save(QDataStream &s) const
 {
-    quint32 tp = type();
+    quint32 typeId = type();
     if (s.version() < QDataStream::Qt_4_0) {
         int i;
         for (i = MapFromThreeCount - 1; i >= 0; i--) {
-            if (map_from_three[i] == tp) {
-                tp = i;
+            if (mapIdFromQt3ToCurrent[i] == typeId) {
+                typeId = i;
                 break;
             }
         }
@@ -2018,11 +1741,31 @@ void QVariant::save(QDataStream &s) const
             s << QVariant();
             return;
         }
+    } else if (s.version() < QDataStream::Qt_5_0) {
+        if (typeId == QMetaType::User) {
+            typeId = 127; // QVariant::UserType had this value in Qt4
+        } else if (typeId >= 128 - 97 && typeId <= LastCoreType) {
+            // In Qt4 id == 128 was FirstExtCoreType. In Qt5 ExtCoreTypes set was merged to CoreTypes
+            // by moving all ids down by 97.
+            typeId += 97;
+        } else if (typeId == QMetaType::QIcon) {
+            // In Qt5 after modularization project this types where moved to a separate module (and ids were downgraded)
+            typeId = 69;
+        } else if (typeId == QMetaType::QSizePolicy) {
+            typeId = 75;
+        } else if (typeId >= QMetaType::QImage) {
+            // and as a result this types recieved lower ids too
+            if (typeId <= QMetaType::QCursor) {
+                typeId +=1;
+            } else if (typeId <= QMetaType::QQuaternion) {
+                typeId +=2;
+            }
+        }
     }
-    s << tp;
+    s << typeId;
     if (s.version() >= QDataStream::Qt_4_2)
         s << qint8(d.is_null);
-    if (tp == QVariant::UserType) {
+    if (d.type >= QVariant::UserType) {
         s << QMetaType::typeName(userType());
     }
 
@@ -2032,8 +1775,8 @@ void QVariant::save(QDataStream &s) const
     }
 
     if (!QMetaType::save(s, d.type, constData())) {
+        qWarning("QVariant::save: unable to save type '%s' (type id: %d).\n", QMetaType::typeName(d.type), d.type);
         Q_ASSERT_X(false, "QVariant::save", "Invalid type to save");
-        qWarning("QVariant::save: unable to save type %d.", d.type);
     }
 }
 
@@ -2095,14 +1838,14 @@ QDataStream& operator<<(QDataStream &s, const QVariant::Type p)
 */
 
 template <typename T>
-inline T qVariantToHelper(const QVariant::Private &d, QVariant::Type t,
-                          const QVariant::Handler *handler, T * = 0)
+inline T qVariantToHelper(const QVariant::Private &d, const HandlersManager &handlerManager)
 {
-    if (d.type == t)
+    const uint targetType = qMetaTypeId<T>();
+    if (d.type == targetType)
         return *v_cast<T>(&d);
 
     T ret;
-    handler->convert(&d, t, &ret, 0);
+    handlerManager[d.type]->convert(&d, targetType, &ret, 0);
     return ret;
 }
 
@@ -2117,7 +1860,7 @@ inline T qVariantToHelper(const QVariant::Private &d, QVariant::Type t,
 */
 QStringList QVariant::toStringList() const
 {
-    return qVariantToHelper<QStringList>(d, StringList, handler);
+    return qVariantToHelper<QStringList>(d, handlerManager);
 }
 
 /*!
@@ -2130,7 +1873,7 @@ QStringList QVariant::toStringList() const
 */
 QString QVariant::toString() const
 {
-    return qVariantToHelper<QString>(d, String, handler);
+    return qVariantToHelper<QString>(d, handlerManager);
 }
 
 /*!
@@ -2141,7 +1884,7 @@ QString QVariant::toString() const
 */
 QVariantMap QVariant::toMap() const
 {
-    return qVariantToHelper<QVariantMap>(d, Map, handler);
+    return qVariantToHelper<QVariantMap>(d, handlerManager);
 }
 
 /*!
@@ -2152,7 +1895,7 @@ QVariantMap QVariant::toMap() const
 */
 QVariantHash QVariant::toHash() const
 {
-    return qVariantToHelper<QVariantHash>(d, Hash, handler);
+    return qVariantToHelper<QVariantHash>(d, handlerManager);
 }
 
 /*!
@@ -2168,7 +1911,7 @@ QVariantHash QVariant::toHash() const
 */
 QDate QVariant::toDate() const
 {
-    return qVariantToHelper<QDate>(d, Date, handler);
+    return qVariantToHelper<QDate>(d, handlerManager);
 }
 
 /*!
@@ -2184,7 +1927,7 @@ QDate QVariant::toDate() const
 */
 QTime QVariant::toTime() const
 {
-    return qVariantToHelper<QTime>(d, Time, handler);
+    return qVariantToHelper<QTime>(d, handlerManager);
 }
 
 /*!
@@ -2201,7 +1944,7 @@ QTime QVariant::toTime() const
 */
 QDateTime QVariant::toDateTime() const
 {
-    return qVariantToHelper<QDateTime>(d, DateTime, handler);
+    return qVariantToHelper<QDateTime>(d, handlerManager);
 }
 
 /*!
@@ -2216,7 +1959,7 @@ QDateTime QVariant::toDateTime() const
 #ifndef QT_BOOTSTRAPPED
 QEasingCurve QVariant::toEasingCurve() const
 {
-    return qVariantToHelper<QEasingCurve>(d, EasingCurve, handler);
+    return qVariantToHelper<QEasingCurve>(d, handlerManager);
 }
 #endif
 
@@ -2231,7 +1974,7 @@ QEasingCurve QVariant::toEasingCurve() const
 */
 QByteArray QVariant::toByteArray() const
 {
-    return qVariantToHelper<QByteArray>(d, ByteArray, handler);
+    return qVariantToHelper<QByteArray>(d, handlerManager);
 }
 
 #ifndef QT_NO_GEOM_VARIANT
@@ -2245,7 +1988,7 @@ QByteArray QVariant::toByteArray() const
 */
 QPoint QVariant::toPoint() const
 {
-    return qVariantToHelper<QPoint>(d, Point, handler);
+    return qVariantToHelper<QPoint>(d, handlerManager);
 }
 
 /*!
@@ -2258,7 +2001,7 @@ QPoint QVariant::toPoint() const
 */
 QRect QVariant::toRect() const
 {
-    return qVariantToHelper<QRect>(d, Rect, handler);
+    return qVariantToHelper<QRect>(d, handlerManager);
 }
 
 /*!
@@ -2271,7 +2014,7 @@ QRect QVariant::toRect() const
 */
 QSize QVariant::toSize() const
 {
-    return qVariantToHelper<QSize>(d, Size, handler);
+    return qVariantToHelper<QSize>(d, handlerManager);
 }
 
 /*!
@@ -2284,7 +2027,7 @@ QSize QVariant::toSize() const
 */
 QSizeF QVariant::toSizeF() const
 {
-    return qVariantToHelper<QSizeF>(d, SizeF, handler);
+    return qVariantToHelper<QSizeF>(d, handlerManager);
 }
 
 /*!
@@ -2297,7 +2040,7 @@ QSizeF QVariant::toSizeF() const
 */
 QRectF QVariant::toRectF() const
 {
-    return qVariantToHelper<QRectF>(d, RectF, handler);
+    return qVariantToHelper<QRectF>(d, handlerManager);
 }
 
 /*!
@@ -2310,7 +2053,7 @@ QRectF QVariant::toRectF() const
 */
 QLineF QVariant::toLineF() const
 {
-    return qVariantToHelper<QLineF>(d, LineF, handler);
+    return qVariantToHelper<QLineF>(d, handlerManager);
 }
 
 /*!
@@ -2323,7 +2066,7 @@ QLineF QVariant::toLineF() const
 */
 QLine QVariant::toLine() const
 {
-    return qVariantToHelper<QLine>(d, Line, handler);
+    return qVariantToHelper<QLine>(d, handlerManager);
 }
 
 /*!
@@ -2336,7 +2079,7 @@ QLine QVariant::toLine() const
 */
 QPointF QVariant::toPointF() const
 {
-    return qVariantToHelper<QPointF>(d, PointF, handler);
+    return qVariantToHelper<QPointF>(d, handlerManager);
 }
 
 #endif // QT_NO_GEOM_VARIANT
@@ -2351,7 +2094,7 @@ QPointF QVariant::toPointF() const
 */
 QUrl QVariant::toUrl() const
 {
-    return qVariantToHelper<QUrl>(d, Url, handler);
+    return qVariantToHelper<QUrl>(d, handlerManager);
 }
 
 /*!
@@ -2364,7 +2107,7 @@ QUrl QVariant::toUrl() const
 */
 QLocale QVariant::toLocale() const
 {
-    return qVariantToHelper<QLocale>(d, Locale, handler);
+    return qVariantToHelper<QLocale>(d, handlerManager);
 }
 
 /*!
@@ -2379,7 +2122,7 @@ QLocale QVariant::toLocale() const
 #ifndef QT_NO_REGEXP
 QRegExp QVariant::toRegExp() const
 {
-    return qVariantToHelper<QRegExp>(d, RegExp, handler);
+    return qVariantToHelper<QRegExp>(d, handlerManager);
 }
 #endif
 
@@ -2393,7 +2136,7 @@ QRegExp QVariant::toRegExp() const
 */
 QChar QVariant::toChar() const
 {
-    return qVariantToHelper<QChar>(d, Char, handler);
+    return qVariantToHelper<QChar>(d, handlerManager);
 }
 
 /*!
@@ -2404,12 +2147,12 @@ QChar QVariant::toChar() const
 */
 QBitArray QVariant::toBitArray() const
 {
-    return qVariantToHelper<QBitArray>(d, BitArray, handler);
+    return qVariantToHelper<QBitArray>(d, handlerManager);
 }
 
 template <typename T>
 inline T qNumVariantToHelper(const QVariant::Private &d,
-                             const QVariant::Handler *handler, bool *ok, const T& val)
+                             const HandlersManager &handlerManager, bool *ok, const T& val)
 {
     uint t = qMetaTypeId<T>();
     if (ok)
@@ -2417,8 +2160,8 @@ inline T qNumVariantToHelper(const QVariant::Private &d,
     if (d.type == t)
         return val;
 
-    T ret;
-    if (!handler->convert(&d, QVariant::Type(t), &ret, ok) && ok)
+    T ret = 0;
+    if (!handlerManager[d.type]->convert(&d, t, &ret, ok) && ok)
         *ok = false;
     return ret;
 }
@@ -2440,7 +2183,7 @@ inline T qNumVariantToHelper(const QVariant::Private &d,
 */
 int QVariant::toInt(bool *ok) const
 {
-    return qNumVariantToHelper<int>(d, handler, ok, d.data.i);
+    return qNumVariantToHelper<int>(d, handlerManager, ok, d.data.i);
 }
 
 /*!
@@ -2460,7 +2203,7 @@ int QVariant::toInt(bool *ok) const
 */
 uint QVariant::toUInt(bool *ok) const
 {
-    return qNumVariantToHelper<uint>(d, handler, ok, d.data.u);
+    return qNumVariantToHelper<uint>(d, handlerManager, ok, d.data.u);
 }
 
 /*!
@@ -2475,7 +2218,7 @@ uint QVariant::toUInt(bool *ok) const
 */
 qlonglong QVariant::toLongLong(bool *ok) const
 {
-    return qNumVariantToHelper<qlonglong>(d, handler, ok, d.data.ll);
+    return qNumVariantToHelper<qlonglong>(d, handlerManager, ok, d.data.ll);
 }
 
 /*!
@@ -2491,7 +2234,7 @@ qlonglong QVariant::toLongLong(bool *ok) const
 */
 qulonglong QVariant::toULongLong(bool *ok) const
 {
-    return qNumVariantToHelper<qulonglong>(d, handler, ok, d.data.ull);
+    return qNumVariantToHelper<qulonglong>(d, handlerManager, ok, d.data.ull);
 }
 
 /*!
@@ -2511,7 +2254,7 @@ bool QVariant::toBool() const
         return d.data.b;
 
     bool res = false;
-    handler->convert(&d, Bool, &res, 0);
+    handlerManager[d.type]->convert(&d, Bool, &res, 0);
 
     return res;
 }
@@ -2528,7 +2271,7 @@ bool QVariant::toBool() const
 */
 double QVariant::toDouble(bool *ok) const
 {
-    return qNumVariantToHelper<double>(d, handler, ok, d.data.d);
+    return qNumVariantToHelper<double>(d, handlerManager, ok, d.data.d);
 }
 
 /*!
@@ -2545,7 +2288,7 @@ double QVariant::toDouble(bool *ok) const
 */
 float QVariant::toFloat(bool *ok) const
 {
-    return qNumVariantToHelper<float>(d, handler, ok, d.data.f);
+    return qNumVariantToHelper<float>(d, handlerManager, ok, d.data.f);
 }
 
 /*!
@@ -2562,7 +2305,7 @@ float QVariant::toFloat(bool *ok) const
 */
 qreal QVariant::toReal(bool *ok) const
 {
-    return qNumVariantToHelper<qreal>(d, handler, ok, d.data.real);
+    return qNumVariantToHelper<qreal>(d, handlerManager, ok, d.data.real);
 }
 
 /*!
@@ -2573,7 +2316,7 @@ qreal QVariant::toReal(bool *ok) const
 */
 QVariantList QVariant::toList() const
 {
-    return qVariantToHelper<QVariantList>(d, List, handler);
+    return qVariantToHelper<QVariantList>(d, handlerManager);
 }
 
 
@@ -2616,7 +2359,7 @@ static const quint32 qCanConvertMatrix[QVariant::LastCoreType + 1] =
                 | 1 << QVariant::UInt       | 1 << QVariant::Bool       | 1 << QVariant::Double
                 | 1 << QVariant::Date       | 1 << QVariant::Time       | 1 << QVariant::DateTime
                 | 1 << QVariant::LongLong   | 1 << QVariant::ULongLong  | 1 << QVariant::Char
-                | 1 << QVariant::Url,
+                | 1 << QVariant::Url        | 1 << QVariant::Uuid,
 
 /*QStringList*/   1 << QVariant::List       | 1 << QVariant::String,
 
@@ -2655,12 +2398,14 @@ static const quint32 qCanConvertMatrix[QVariant::LastCoreType + 1] =
 
 /*QHash*/         0,
 
-/*QEasingCurve*/  0
+/*QEasingCurve*/  0,
+
+/*QUuid*/         1 << QVariant::String
 };
 
 /*!
     Returns true if the variant's type can be cast to the requested
-    type, \a t. Such casting is done automatically when calling the
+    type, \a targetTypeId. Such casting is done automatically when calling the
     toInt(), toBool(), ... methods.
 
     The following casts are done automatically:
@@ -2692,20 +2437,18 @@ static const quint32 qCanConvertMatrix[QVariant::LastCoreType + 1] =
 
     \sa convert()
 */
-bool QVariant::canConvert(Type t) const
+bool QVariant::canConvert(int targetTypeId) const
 {
-    //we can treat floats as double
-    //the reason for not doing it the "proper" way is that QMetaType::Float's value is 135,
-    //which can't be handled by qCanConvertMatrix
-    //In addition QVariant::Type doesn't have a Float value, so we're using QMetaType::Float
+    // TODO Reimplement this function, currently it works but it is a historical mess.
     const uint currentType = ((d.type == QMetaType::Float) ? QVariant::Double : d.type);
-    if (uint(t) == uint(QMetaType::Float)) t = QVariant::Double;
+    if (uint(targetTypeId) == uint(QMetaType::Float)) targetTypeId = QVariant::Double;
 
-    if (currentType == uint(t))
+    if (currentType == uint(targetTypeId))
         return true;
 
-    if (currentType > QVariant::LastCoreType || t > QVariant::LastCoreType) {
-        switch (uint(t)) {
+    // FIXME It should be LastCoreType intead of Uuid
+    if (currentType > int(QMetaType::QUuid) || targetTypeId > int(QMetaType::QUuid)) {
+        switch (uint(targetTypeId)) {
         case QVariant::Int:
             return currentType == QVariant::KeySequence
                    || currentType == QMetaType::ULong
@@ -2747,14 +2490,14 @@ bool QVariant::canConvert(Type t) const
         }
     }
 
-    if(t == String && currentType == StringList)
+    if (targetTypeId == String && currentType == StringList)
         return v_cast<QStringList>(&d)->count() == 1;
     else
-        return qCanConvertMatrix[t] & (1 << currentType);
+        return qCanConvertMatrix[targetTypeId] & (1 << currentType);
 }
 
 /*!
-    Casts the variant to the requested type, \a t. If the cast cannot be
+    Casts the variant to the requested type, \a targetTypeId. If the cast cannot be
     done, the variant is cleared. Returns true if the current type of
     the variant was successfully cast; otherwise returns false.
 
@@ -2765,29 +2508,41 @@ bool QVariant::canConvert(Type t) const
     \sa canConvert(), clear()
 */
 
-bool QVariant::convert(Type t)
+bool QVariant::convert(int targetTypeId)
 {
-    if (d.type == uint(t))
+    if (d.type == uint(targetTypeId))
         return true;
 
     QVariant oldValue = *this;
 
     clear();
-    if (!oldValue.canConvert(t))
+    if (!oldValue.canConvert(targetTypeId))
         return false;
 
-    create(t, 0);
+    create(targetTypeId, 0);
     if (oldValue.isNull())
         return false;
 
     bool isOk = true;
-    if (!handler->convert(&oldValue.d, t, data(), &isOk))
+    if (!handlerManager[d.type]->convert(&oldValue.d, targetTypeId, data(), &isOk))
         isOk = false;
     d.is_null = !isOk;
     return isOk;
 }
 
 /*!
+  \fn convert(const int type, void *ptr) const
+  \internal
+  Created for qvariant_cast() usage
+*/
+bool QVariant::convert(const int type, void *ptr) const
+{
+    Q_ASSERT(type < int(QMetaType::User));
+    return handlerManager[type]->convert(&d, type, ptr, 0);
+}
+
+
+/*!
     \fn bool operator==(const QVariant &v1, const QVariant &v2)
 
     \relates QVariant
@@ -2850,10 +2605,10 @@ bool QVariant::cmp(const QVariant &v) const
             else
                 return toLongLong() == v.toLongLong();
         }
-        if (!v2.canConvert(Type(d.type)) || !v2.convert(Type(d.type)))
+        if (!v2.canConvert(d.type) || !v2.convert(d.type))
             return false;
     }
-    return handler->compare(&d, &v2.d);
+    return handlerManager[d.type]->compare(&d, &v2.d);
 }
 
 /*! \internal
@@ -2883,34 +2638,22 @@ void* QVariant::data()
 */
 bool QVariant::isNull() const
 {
-    return handler->isNull(&d);
+    return handlerManager[d.type]->isNull(&d);
 }
 
 #ifndef QT_NO_DEBUG_STREAM
 QDebug operator<<(QDebug dbg, const QVariant &v)
 {
-#ifndef Q_BROKEN_DEBUG_STREAM
-    dbg.nospace() << "QVariant(" << v.typeName() << ", ";
-    QVariant::handler->debugStream(dbg, v);
+    dbg.nospace() << "QVariant(" << QMetaType::typeName(v.userType()) << ", ";
+    handlerManager[v.d.type]->debugStream(dbg, v);
     dbg.nospace() << ')';
     return dbg.space();
-#else
-    qWarning("This compiler doesn't support streaming QVariant to QDebug");
-    return dbg;
-    Q_UNUSED(v);
-#endif
 }
 
 QDebug operator<<(QDebug dbg, const QVariant::Type p)
 {
-#ifndef Q_BROKEN_DEBUG_STREAM
-    dbg.nospace() << "QVariant::" << QVariant::typeToName(p);
+    dbg.nospace() << "QVariant::" << QMetaType::typeName(p);
     return dbg.space();
-#else
-    qWarning("This compiler doesn't support streaming QVariant::Type to QDebug");
-    return dbg;
-    Q_UNUSED(p);
-#endif
 }
 #endif