Record if a metatype is a smart pointer to a QObject derived.
authorStephen Kelly <stephen.kelly@kdab.com>
Thu, 24 May 2012 12:35:45 +0000 (14:35 +0200)
committerQt by Nokia <qt-info@nokia.com>
Wed, 20 Jun 2012 13:45:07 +0000 (15:45 +0200)
This allows QVariant/QMetaType software (such as QtDeclarative) to
deal with smart pointers in a similar way to how they can deal with
naked pointers (accessing properties etc).

This also adds a requirement that T be fully defined when
QSharedPointer<T> is inserted into a QVariant.

Change-Id: I29e12b8a6aa5f4aadbd62f92b89bc238f64b5725
Reviewed-by: Jędrzej Nowacki <jedrzej.nowacki@nokia.com>
dist/changes-5.0.0
src/corelib/kernel/qmetatype.h
src/corelib/tools/qsharedpointer.cpp
tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp

index 7ddb17f..76cdd0a 100644 (file)
@@ -168,6 +168,9 @@ information about a particular change.
   * Q_DECLARE_METATYPE(Foo*) now requires that Foo is fully defined. In
     cases where a forward declared type should be used as a metatype,
     Q_DECLARE_OPAQUE_POINTER(Foo*) can be used to allow that.
+  * Similarly, Q_DECLARE_METATYPE(QSharedPointer<Foo>), and
+    Q_DECLARE_METATYPE(QWeakPointer<Foo>) require Foo to be fully defined. Again
+    though, Q_DECLARE_OPAQUE_POINTER(Foo*) can be used to allow that.
 
 - QItemEditorFactory
 
index da6d02c..1a57cac 100644 (file)
@@ -247,7 +247,10 @@ public:
         NeedsDestruction = 0x2,
         MovableType = 0x4,
         PointerToQObject = 0x8,
-        IsEnumeration = 0x10
+        IsEnumeration = 0x10,
+        SharedPointerToQObject = 0x20,
+        WeakPointerToQObject = 0x40,
+        TrackingPointerToQObject = 0x80
     };
     Q_DECLARE_FLAGS(TypeFlags, TypeFlag)
 
@@ -415,6 +418,9 @@ template <> inline void qMetaTypeLoadHelper<void>(QDataStream &, void *) {}
 
 class QObject;
 class QWidget;
+template <class T> class QSharedPointer;
+template <class T> class QWeakPointer;
+template <class T> class QPointer;
 
 namespace QtPrivate
 {
@@ -465,6 +471,40 @@ namespace QtPrivate
     {
         static inline const QMetaObject *value() { return &T::staticMetaObject; }
     };
+
+    template<typename T>
+    struct IsSharedPointerToTypeDerivedFromQObject
+    {
+        enum { Value = false };
+    };
+
+    template<typename T>
+    struct IsSharedPointerToTypeDerivedFromQObject<QSharedPointer<T> > : IsPointerToTypeDerivedFromQObject<T*>
+    {
+    };
+
+    template<typename T>
+    struct IsWeakPointerToTypeDerivedFromQObject
+    {
+        enum { Value = false };
+    };
+
+    template<typename T>
+    struct IsWeakPointerToTypeDerivedFromQObject<QWeakPointer<T> > : IsPointerToTypeDerivedFromQObject<T*>
+    {
+    };
+
+    template<typename T>
+    struct IsTrackingPointerToTypeDerivedFromQObject
+    {
+        enum { Value = false };
+    };
+
+    template<typename T>
+    struct IsTrackingPointerToTypeDerivedFromQObject<QPointer<T> >
+    {
+        enum { Value = true };
+    };
 }
 
 template <typename T, bool = QtPrivate::IsPointerToTypeDerivedFromQObject<T>::Value>
@@ -511,6 +551,9 @@ namespace QtPrivate {
                      | (QTypeInfo<T>::isComplex ? QMetaType::NeedsConstruction : 0)
                      | (QTypeInfo<T>::isComplex ? QMetaType::NeedsDestruction : 0)
                      | (IsPointerToTypeDerivedFromQObject<T>::Value ? QMetaType::PointerToQObject : 0)
+                     | (IsSharedPointerToTypeDerivedFromQObject<T>::Value ? QMetaType::SharedPointerToQObject : 0)
+                     | (IsWeakPointerToTypeDerivedFromQObject<T>::Value ? QMetaType::WeakPointerToQObject : 0)
+                     | (IsTrackingPointerToTypeDerivedFromQObject<T>::Value ? QMetaType::TrackingPointerToQObject : 0)
                      | (Q_IS_ENUM(T) ? QMetaType::IsEnumeration : 0)
              };
     };
@@ -677,9 +720,6 @@ template <class T> class QVector;
 template <class T> class QQueue;
 template <class T> class QStack;
 template <class T> class QSet;
-template <class T> class QSharedPointer;
-template <class T> class QWeakPointer;
-template <class T> class QPointer;
 template <class T1, class T2> class QMap;
 template <class T1, class T2> class QHash;
 template <class T1, class T2> struct QPair;
index 73a1e6c..673b90c 100644 (file)
@@ -1221,6 +1221,7 @@ QtSharedPointer::ExternalRefCountData *QtSharedPointer::ExternalRefCountData::ge
 */
 QSharedPointer<QObject> QtSharedPointer::sharedPointerFromVariant_internal(const QVariant &variant)
 {
+    Q_ASSERT(QMetaType::typeFlags(variant.userType()) & QMetaType::SharedPointerToQObject);
     return *reinterpret_cast<const QSharedPointer<QObject>*>(variant.constData());
 }
 
@@ -1231,6 +1232,7 @@ QSharedPointer<QObject> QtSharedPointer::sharedPointerFromVariant_internal(const
 */
 QWeakPointer<QObject> QtSharedPointer::weakPointerFromVariant_internal(const QVariant &variant)
 {
+    Q_ASSERT(QMetaType::typeFlags(variant.userType()) & QMetaType::WeakPointerToQObject || QMetaType::typeFlags(variant.userType()) & QMetaType::TrackingPointerToQObject);
     return *reinterpret_cast<const QWeakPointer<QObject>*>(variant.constData());
 }
 
index 861cedf..f1053ad 100644 (file)
@@ -1462,30 +1462,33 @@ void tst_QMetaType::automaticTemplateRegistration()
 
 #endif // Q_COMPILER_VARIADIC_MACROS
 
-#define TEST_SMARTPOINTER(SMARTPOINTER, ELEMENT_TYPE) \
+#define TEST_SMARTPOINTER(SMARTPOINTER, ELEMENT_TYPE, FLAG_TEST, FROMVARIANTFUNCTION) \
     { \
         SMARTPOINTER < ELEMENT_TYPE > sp(new ELEMENT_TYPE); \
+        sp.data()->setObjectName("Test name"); \
         QVariant v = QVariant::fromValue(sp); \
         QCOMPARE(v.typeName(), #SMARTPOINTER "<" #ELEMENT_TYPE ">"); \
+        QVERIFY(QMetaType::typeFlags(::qMetaTypeId<SMARTPOINTER < ELEMENT_TYPE > >()) & QMetaType::FLAG_TEST); \
+        SMARTPOINTER < QObject > extractedPtr = FROMVARIANTFUNCTION<QObject>(v); \
+        QCOMPARE(extractedPtr.data()->objectName(), sp.data()->objectName()); \
     }
 
-    TEST_SMARTPOINTER(QSharedPointer, QObject)
-    TEST_SMARTPOINTER(QSharedPointer, QFile)
-    TEST_SMARTPOINTER(QSharedPointer, QTemporaryFile)
-    TEST_SMARTPOINTER(QSharedPointer, MyObject)
+    TEST_SMARTPOINTER(QSharedPointer, QObject, SharedPointerToQObject, qSharedPointerFromVariant)
+    TEST_SMARTPOINTER(QSharedPointer, QFile, SharedPointerToQObject, qSharedPointerFromVariant)
+    TEST_SMARTPOINTER(QSharedPointer, QTemporaryFile, SharedPointerToQObject, qSharedPointerFromVariant)
+    TEST_SMARTPOINTER(QSharedPointer, MyObject, SharedPointerToQObject, qSharedPointerFromVariant)
 
-    TEST_SMARTPOINTER(QWeakPointer, QObject)
-    TEST_SMARTPOINTER(QWeakPointer, QFile)
-    TEST_SMARTPOINTER(QWeakPointer, QTemporaryFile)
-    TEST_SMARTPOINTER(QWeakPointer, MyObject)
+    TEST_SMARTPOINTER(QWeakPointer, QObject, WeakPointerToQObject, qWeakPointerFromVariant)
+    TEST_SMARTPOINTER(QWeakPointer, QFile, WeakPointerToQObject, qWeakPointerFromVariant)
+    TEST_SMARTPOINTER(QWeakPointer, QTemporaryFile, WeakPointerToQObject, qWeakPointerFromVariant)
+    TEST_SMARTPOINTER(QWeakPointer, MyObject, WeakPointerToQObject, qWeakPointerFromVariant)
 
-    TEST_SMARTPOINTER(QPointer, QObject)
-    TEST_SMARTPOINTER(QPointer, QFile)
-    TEST_SMARTPOINTER(QPointer, QTemporaryFile)
-    TEST_SMARTPOINTER(QPointer, MyObject)
+    TEST_SMARTPOINTER(QPointer, QObject, TrackingPointerToQObject, qPointerFromVariant)
+    TEST_SMARTPOINTER(QPointer, QFile, TrackingPointerToQObject, qPointerFromVariant)
+    TEST_SMARTPOINTER(QPointer, QTemporaryFile, TrackingPointerToQObject, qPointerFromVariant)
+    TEST_SMARTPOINTER(QPointer, MyObject, TrackingPointerToQObject, qPointerFromVariant)
 
 #undef TEST_SMARTPOINTER
-
 }
 
 template <typename T>