Record if a metatype is a smart pointer to a QObject derived.

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>
This commit is contained in:
Stephen Kelly 2012-05-24 14:35:45 +02:00 committed by Qt by Nokia
parent 668efc29fd
commit 579ea489a4
4 changed files with 66 additions and 18 deletions

3
dist/changes-5.0.0 vendored
View File

@ -168,6 +168,9 @@ information about a particular change.
* Q_DECLARE_METATYPE(Foo*) now requires that Foo is fully defined. In * Q_DECLARE_METATYPE(Foo*) now requires that Foo is fully defined. In
cases where a forward declared type should be used as a metatype, cases where a forward declared type should be used as a metatype,
Q_DECLARE_OPAQUE_POINTER(Foo*) can be used to allow that. 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 - QItemEditorFactory

View File

@ -247,7 +247,10 @@ public:
NeedsDestruction = 0x2, NeedsDestruction = 0x2,
MovableType = 0x4, MovableType = 0x4,
PointerToQObject = 0x8, PointerToQObject = 0x8,
IsEnumeration = 0x10 IsEnumeration = 0x10,
SharedPointerToQObject = 0x20,
WeakPointerToQObject = 0x40,
TrackingPointerToQObject = 0x80
}; };
Q_DECLARE_FLAGS(TypeFlags, TypeFlag) Q_DECLARE_FLAGS(TypeFlags, TypeFlag)
@ -415,6 +418,9 @@ template <> inline void qMetaTypeLoadHelper<void>(QDataStream &, void *) {}
class QObject; class QObject;
class QWidget; class QWidget;
template <class T> class QSharedPointer;
template <class T> class QWeakPointer;
template <class T> class QPointer;
namespace QtPrivate namespace QtPrivate
{ {
@ -465,6 +471,40 @@ namespace QtPrivate
{ {
static inline const QMetaObject *value() { return &T::staticMetaObject; } 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> template <typename T, bool = QtPrivate::IsPointerToTypeDerivedFromQObject<T>::Value>
@ -511,6 +551,9 @@ namespace QtPrivate {
| (QTypeInfo<T>::isComplex ? QMetaType::NeedsConstruction : 0) | (QTypeInfo<T>::isComplex ? QMetaType::NeedsConstruction : 0)
| (QTypeInfo<T>::isComplex ? QMetaType::NeedsDestruction : 0) | (QTypeInfo<T>::isComplex ? QMetaType::NeedsDestruction : 0)
| (IsPointerToTypeDerivedFromQObject<T>::Value ? QMetaType::PointerToQObject : 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) | (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 QQueue;
template <class T> class QStack; template <class T> class QStack;
template <class T> class QSet; 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 QMap;
template <class T1, class T2> class QHash; template <class T1, class T2> class QHash;
template <class T1, class T2> struct QPair; template <class T1, class T2> struct QPair;

View File

@ -1221,6 +1221,7 @@ QtSharedPointer::ExternalRefCountData *QtSharedPointer::ExternalRefCountData::ge
*/ */
QSharedPointer<QObject> QtSharedPointer::sharedPointerFromVariant_internal(const QVariant &variant) QSharedPointer<QObject> QtSharedPointer::sharedPointerFromVariant_internal(const QVariant &variant)
{ {
Q_ASSERT(QMetaType::typeFlags(variant.userType()) & QMetaType::SharedPointerToQObject);
return *reinterpret_cast<const QSharedPointer<QObject>*>(variant.constData()); 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) 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()); return *reinterpret_cast<const QWeakPointer<QObject>*>(variant.constData());
} }

View File

@ -1462,30 +1462,33 @@ void tst_QMetaType::automaticTemplateRegistration()
#endif // Q_COMPILER_VARIADIC_MACROS #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); \ SMARTPOINTER < ELEMENT_TYPE > sp(new ELEMENT_TYPE); \
sp.data()->setObjectName("Test name"); \
QVariant v = QVariant::fromValue(sp); \ QVariant v = QVariant::fromValue(sp); \
QCOMPARE(v.typeName(), #SMARTPOINTER "<" #ELEMENT_TYPE ">"); \ 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, QObject, SharedPointerToQObject, qSharedPointerFromVariant)
TEST_SMARTPOINTER(QSharedPointer, QFile) TEST_SMARTPOINTER(QSharedPointer, QFile, SharedPointerToQObject, qSharedPointerFromVariant)
TEST_SMARTPOINTER(QSharedPointer, QTemporaryFile) TEST_SMARTPOINTER(QSharedPointer, QTemporaryFile, SharedPointerToQObject, qSharedPointerFromVariant)
TEST_SMARTPOINTER(QSharedPointer, MyObject) TEST_SMARTPOINTER(QSharedPointer, MyObject, SharedPointerToQObject, qSharedPointerFromVariant)
TEST_SMARTPOINTER(QWeakPointer, QObject) TEST_SMARTPOINTER(QWeakPointer, QObject, WeakPointerToQObject, qWeakPointerFromVariant)
TEST_SMARTPOINTER(QWeakPointer, QFile) TEST_SMARTPOINTER(QWeakPointer, QFile, WeakPointerToQObject, qWeakPointerFromVariant)
TEST_SMARTPOINTER(QWeakPointer, QTemporaryFile) TEST_SMARTPOINTER(QWeakPointer, QTemporaryFile, WeakPointerToQObject, qWeakPointerFromVariant)
TEST_SMARTPOINTER(QWeakPointer, MyObject) TEST_SMARTPOINTER(QWeakPointer, MyObject, WeakPointerToQObject, qWeakPointerFromVariant)
TEST_SMARTPOINTER(QPointer, QObject) TEST_SMARTPOINTER(QPointer, QObject, TrackingPointerToQObject, qPointerFromVariant)
TEST_SMARTPOINTER(QPointer, QFile) TEST_SMARTPOINTER(QPointer, QFile, TrackingPointerToQObject, qPointerFromVariant)
TEST_SMARTPOINTER(QPointer, QTemporaryFile) TEST_SMARTPOINTER(QPointer, QTemporaryFile, TrackingPointerToQObject, qPointerFromVariant)
TEST_SMARTPOINTER(QPointer, MyObject) TEST_SMARTPOINTER(QPointer, MyObject, TrackingPointerToQObject, qPointerFromVariant)
#undef TEST_SMARTPOINTER #undef TEST_SMARTPOINTER
} }
template <typename T> template <typename T>