diff options
author | Stephen Kelly <stephen.kelly@kdab.com> | 2011-12-30 13:18:24 +0100 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2012-02-08 14:43:18 +0100 |
commit | ae85d7c965e7d50404c056a77c73bfe00267fa12 (patch) | |
tree | 7486ebcc5d0711cbbf2a51599cd9cd3cb0bfd33b /src | |
parent | e85c0862d92c226dcf0d0dac91808c036271d39f (diff) |
Treat pointers to QObject derived types in QVariant specially.
It is possible to do this for example:
QVariant v = QVariant::fromValue<MyCustomQObject*>();
QObject *object = v.value<QObject*>();
This means that if a QVariant contains a pointer to a QObject
derived type, third parties can extract a QObject* and use its
properties without knowing the concrete type.
This is a source compatible change.
Change-Id: Iee9a9437e99cc2f40d1a4bfea47275482ef7161f
Reviewed-by: Jędrzej Nowacki <jedrzej.nowacki@nokia.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/corelib/kernel/qvariant.h | 72 |
1 files changed, 62 insertions, 10 deletions
diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h index b61b0cc33c..089d0d643b 100644 --- a/src/corelib/kernel/qvariant.h +++ b/src/corelib/kernel/qvariant.h @@ -49,6 +49,7 @@ #include <QtCore/qmap.h> #include <QtCore/qhash.h> #include <QtCore/qstring.h> +#include <QtCore/qobject.h> QT_BEGIN_HEADER @@ -88,6 +89,39 @@ inline QVariant qVariantFromValue(const T &); template<typename T> inline T qvariant_cast(const QVariant &); +namespace QtPrivate { + + template <typename Derived, typename Argument, typename ReturnType> + struct ObjectInvoker + { + static ReturnType invoke(Argument a) + { + return Derived::object(a); + } + }; + + template <typename Derived, typename Argument, typename ReturnType> + struct MetaTypeInvoker + { + static ReturnType invoke(Argument a) + { + return Derived::metaType(a); + } + }; + + template <typename Derived, typename T, typename Argument, typename ReturnType, bool = IsPointerToTypeDerivedFromQObject<T>::Value> + struct TreatAsQObjectBeforeMetaType : ObjectInvoker<Derived, Argument, ReturnType> + { + }; + + template <typename Derived, typename T, typename Argument, typename ReturnType> + struct TreatAsQObjectBeforeMetaType<Derived, T, Argument, ReturnType, false> : MetaTypeInvoker<Derived, Argument, ReturnType> + { + }; + + template<typename T> struct QVariantValueHelper; +} + class Q_CORE_EXPORT QVariant { public: @@ -375,14 +409,15 @@ protected: #ifndef QT_NO_DEBUG_STREAM friend Q_CORE_EXPORT QDebug operator<<(QDebug, const QVariant &); #endif - Private d; #ifndef Q_NO_TEMPLATE_FRIENDS template<typename T> friend inline T qvariant_cast(const QVariant &); + template<typename T> friend struct QtPrivate::QVariantValueHelper; protected: #else public: #endif + Private d; void create(int type, const void *copy); bool cmp(const QVariant &other) const; bool convert(const int t, void *ptr) const; @@ -481,18 +516,35 @@ inline bool operator!=(const QVariant &v1, const QVariantComparisonHelper &v2) } #endif +namespace QtPrivate { + template<typename T> + struct QVariantValueHelper : TreatAsQObjectBeforeMetaType<QVariantValueHelper<T>, T, const QVariant &, T> + { + static T metaType(const QVariant &v) + { + const int vid = qMetaTypeId<T>(static_cast<T *>(0)); + if (vid == v.userType()) + return *reinterpret_cast<const T *>(v.constData()); + if (vid < int(QMetaType::User)) { + T t; + if (v.convert(QVariant::Type(vid), &t)) + return t; + } + return T(); + } +#ifndef QT_NO_QOBJECT + static T object(const QVariant &v) + { + return qobject_cast<T>(QMetaType::typeFlags(v.userType()) & QMetaType::PointerToQObject ? v.d.data.o : 0); + } +#endif + }; +} + #ifndef QT_MOC template<typename T> inline T qvariant_cast(const QVariant &v) { - const int vid = qMetaTypeId<T>(static_cast<T *>(0)); - if (vid == v.userType()) - return *reinterpret_cast<const T *>(v.constData()); - if (vid < int(QMetaType::User)) { - T t; - if (v.convert(vid, &t)) - return t; - } - return T(); + return QtPrivate::QVariantValueHelper<T>::invoke(v); } template<> inline QVariant qvariant_cast<QVariant>(const QVariant &v) |