Let QMetaType know which types are Q_GADGET

This is required so we can take a QVariant and detect that it contains a
Q_GADGET and then use method like QMetaType::metaObject and QMetaProperty::write
with the QVariant::data

Change-Id: I3603692e4e84426e10bf59949e3def3ea4947bec
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
bb10
Olivier Goffart 2014-08-03 14:56:34 +02:00
parent fd05f26d80
commit 78e0e72eb5
5 changed files with 75 additions and 16 deletions

View File

@ -283,10 +283,11 @@ struct DefinedTypesFilter {
\value MovableType An instance of a type having this attribute can be safely moved by memcpy.
\omitvalue SharedPointerToQObject
\omitvalue IsEnumeration
\omitvalue PointerToQObject
\value PointerToQObject This type is a pointer to a derived of QObject
\omitvalue WeakPointerToQObject
\omitvalue TrackingPointerToQObject
\omitvalue WasDeclaredAsMetaType
\value IsGadget This type is a Q_GADGET and it's corresponding QMetaObject can be accessed with QMetaType::metaObject Since 5.5.
*/
/*!
@ -363,8 +364,19 @@ struct DefinedTypesFilter {
/*!
\fn const QMetaObject *QMetaType::metaObject() const
\since 5.0
\internal
\since 5.5
return a QMetaObject relative to this type.
If the type is a pointer type to a subclass of QObject, flags contains
QMetaType::PointerToQObject and this function returns the corresponding QMetaObject. This can
be used to in combinaison with QMetaObject::construct to create QObject of this type.
If the type is a Q_GADGET, flags contains QMetaType::IsGadget, and this function returns its
QMetaObject. This can be used to retrieve QMetaMethod and QMetaProperty and use them on a
pointer of this type. (given by QVariant::data for example)
\sa QMetaType::metaObjectForType(), QMetaType::flags()
*/
/*!
@ -2025,7 +2037,9 @@ private:
/*!
\since 5.0
Returns QMetaObject of a given \a type, if the \a type is a pointer to type derived from QObject.
returns QMetaType::metaObject for \a type
\sa metaObject()
*/
const QMetaObject *QMetaType::metaObjectForType(int type)
{

View File

@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Copyright (C) 2014 Olivier Goffart <ogoffart@woboq.com>
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtCore module of the Qt Toolkit.
@ -435,7 +436,8 @@ public:
SharedPointerToQObject = 0x20,
WeakPointerToQObject = 0x40,
TrackingPointerToQObject = 0x80,
WasDeclaredAsMetaType = 0x100
WasDeclaredAsMetaType = 0x100,
IsGadget = 0x200
};
Q_DECLARE_FLAGS(TypeFlags, TypeFlag)
@ -1335,14 +1337,27 @@ namespace QtPrivate
enum { Value = sizeof(checkType(static_cast<T*>(0))) == sizeof(yes_type) };
};
template<typename T, bool = IsPointerToTypeDerivedFromQObject<T>::Value>
template<typename T>
struct IsGadgetHelper
{
template<typename X> static typename X::QtGadgetHelper *checkType(X*);
static char checkType(void*);
enum { Value = sizeof(checkType(static_cast<T*>(0))) == sizeof(void*) };
};
template<typename T, typename Enable = void>
struct MetaObjectForType
{
static inline const QMetaObject *value() { return 0; }
};
template<typename T>
struct MetaObjectForType<T*, /* isPointerToTypeDerivedFromQObject = */ true>
struct MetaObjectForType<T*, typename QEnableIf<IsPointerToTypeDerivedFromQObject<T*>::Value>::Type>
{
static inline const QMetaObject *value() { return &T::staticMetaObject; }
};
template<typename T>
struct MetaObjectForType<T, typename QEnableIf<IsGadgetHelper<T>::Value>::Type>
{
static inline const QMetaObject *value() { return &T::staticMetaObject; }
};
@ -1553,6 +1568,7 @@ namespace QtPrivate {
| (IsWeakPointerToTypeDerivedFromQObject<T>::Value ? QMetaType::WeakPointerToQObject : 0)
| (IsTrackingPointerToTypeDerivedFromQObject<T>::Value ? QMetaType::TrackingPointerToQObject : 0)
| (Q_IS_ENUM(T) ? QMetaType::IsEnumeration : 0)
| (IsGadgetHelper<T>::Value ? QMetaType::IsGadget : 0)
};
};

View File

@ -159,6 +159,7 @@ private: \
#define Q_GADGET \
public: \
static const QMetaObject staticMetaObject; \
typedef void QtGadgetHelper; \
private: \
Q_DECL_HIDDEN_STATIC_METACALL static void qt_static_metacall(QObject *, QMetaObject::Call, int, void **);
#endif // QT_NO_META_MACROS

View File

@ -113,6 +113,7 @@ private slots:
void saveAndLoadBuiltin_data();
void saveAndLoadBuiltin();
void saveAndLoadCustom();
void metaObject_data();
void metaObject();
void constexprMetaTypeIds();
void constRefs();
@ -1027,7 +1028,9 @@ void tst_QMetaType::flagsBinaryCompatibility5_0()
QFETCH(quint32, id);
QFETCH(quint32, flags);
QCOMPARE(quint32(QMetaType::typeFlags(id)), flags);
quint32 mask_5_0 = 0x1ff; // Only compare the values that were already defined in 5.0
QCOMPARE(quint32(QMetaType::typeFlags(id)) & mask_5_0, flags);
}
void tst_QMetaType::construct_data()
@ -1831,17 +1834,41 @@ void tst_QMetaType::saveAndLoadCustom()
QCOMPARE(stream.status(), QDataStream::ReadPastEnd);
}
struct MyGadget {
Q_GADGET;
};
Q_DECLARE_METATYPE(MyGadget);
Q_DECLARE_METATYPE(const QMetaObject *);
void tst_QMetaType::metaObject_data()
{
QTest::addColumn<int>("type");
QTest::addColumn<const QMetaObject*>("result");
QTest::addColumn<bool>("isGadget");
QTest::addColumn<bool>("isQObjectPtr");
QTest::newRow("QObject") << int(QMetaType::QObjectStar) << &QObject::staticMetaObject << false << true;
QTest::newRow("QFile*") << ::qMetaTypeId<QFile*>() << &QFile::staticMetaObject << false << true;
QTest::newRow("MyObject*") << ::qMetaTypeId<MyObject*>() << &MyObject::staticMetaObject << false << true;
QTest::newRow("int") << int(QMetaType::Int) << static_cast<const QMetaObject *>(0) << false << false;
QTest::newRow("QEasingCurve") << ::qMetaTypeId<QEasingCurve>() << &QEasingCurve::staticMetaObject << true << false;
QTest::newRow("MyGadget") << ::qMetaTypeId<MyGadget>() << &MyGadget::staticMetaObject << true << false;
}
void tst_QMetaType::metaObject()
{
QCOMPARE(QMetaType::metaObjectForType(QMetaType::QObjectStar), &QObject::staticMetaObject);
QCOMPARE(QMetaType::metaObjectForType(::qMetaTypeId<QFile*>()), &QFile::staticMetaObject);
QCOMPARE(QMetaType::metaObjectForType(::qMetaTypeId<MyObject*>()), &MyObject::staticMetaObject);
QCOMPARE(QMetaType::metaObjectForType(QMetaType::Int), static_cast<const QMetaObject *>(0));
QFETCH(int, type);
QFETCH(const QMetaObject *, result);
QFETCH(bool, isGadget);
QFETCH(bool, isQObjectPtr);
QCOMPARE(QMetaType(QMetaType::QObjectStar).metaObject(), &QObject::staticMetaObject);
QCOMPARE(QMetaType(::qMetaTypeId<QFile*>()).metaObject(), &QFile::staticMetaObject);
QCOMPARE(QMetaType(::qMetaTypeId<MyObject*>()).metaObject(), &MyObject::staticMetaObject);
QCOMPARE(QMetaType(QMetaType::Int).metaObject(), static_cast<const QMetaObject *>(0));
QCOMPARE(QMetaType::metaObjectForType(type), result);
QMetaType mt(type);
QCOMPARE(mt.metaObject(), result);
QCOMPARE(!!(mt.flags() & QMetaType::IsGadget), isGadget);
QCOMPARE(!!(mt.flags() & QMetaType::PointerToQObject), isQObjectPtr);
}
#define METATYPE_ID_FUNCTION(Type, MetaTypeId, Name) \

View File

@ -70,6 +70,7 @@ void tst_QWidgetMetaType::metaObject()
QCOMPARE(QMetaType::metaObjectForType(qMetaTypeId<QWidget*>()), &QWidget::staticMetaObject);
QCOMPARE(QMetaType::metaObjectForType(qMetaTypeId<QLabel*>()), &QLabel::staticMetaObject);
QCOMPARE(QMetaType::metaObjectForType(qMetaTypeId<CustomWidget*>()), &CustomWidget::staticMetaObject);
QCOMPARE(QMetaType::metaObjectForType(qMetaTypeId<QSizePolicy>()), &QSizePolicy::staticMetaObject);
}
QTEST_MAIN(tst_QWidgetMetaType)