summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel/qvariant.h
diff options
context:
space:
mode:
authorStephen Kelly <stephen.kelly@kdab.com>2011-12-30 13:18:24 +0100
committerQt by Nokia <qt-info@nokia.com>2012-02-08 14:43:18 +0100
commitae85d7c965e7d50404c056a77c73bfe00267fa12 (patch)
tree7486ebcc5d0711cbbf2a51599cd9cd3cb0bfd33b /src/corelib/kernel/qvariant.h
parente85c0862d92c226dcf0d0dac91808c036271d39f (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/corelib/kernel/qvariant.h')
-rw-r--r--src/corelib/kernel/qvariant.h72
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)