summaryrefslogtreecommitdiffstats
path: root/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.h
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/corelib/kernel/qmetatype/tst_qmetatype.h')
-rw-r--r--tests/auto/corelib/kernel/qmetatype/tst_qmetatype.h566
1 files changed, 299 insertions, 267 deletions
diff --git a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.h b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.h
index 3f00db5519..1694e49491 100644
--- a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.h
+++ b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.h
@@ -1,294 +1,326 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the test suite of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-// Used by both tst_qmetatype and tst_qsettings
-
-#ifndef TST_QMETATYPE_H
-#define TST_QMETATYPE_H
-
-#include <qmetatype.h>
-#include <float.h>
-
-#define FOR_EACH_PRIMITIVE_METATYPE(F) \
- QT_FOR_EACH_STATIC_PRIMITIVE_TYPE(F) \
- QT_FOR_EACH_STATIC_CORE_POINTER(F) \
-
-#define FOR_EACH_COMPLEX_CORE_METATYPE(F) \
- QT_FOR_EACH_STATIC_CORE_CLASS(F) \
- QT_FOR_EACH_STATIC_CORE_TEMPLATE(F)
-
-#define FOR_EACH_CORE_METATYPE(F) \
- FOR_EACH_PRIMITIVE_METATYPE(F) \
- FOR_EACH_COMPLEX_CORE_METATYPE(F) \
-
-template <int ID>
-struct MetaEnumToType {};
-
-#define DEFINE_META_ENUM_TO_TYPE(MetaTypeName, MetaTypeId, RealType) \
-template<> \
-struct MetaEnumToType<QMetaType::MetaTypeName> { \
- typedef RealType Type; \
-};
-FOR_EACH_CORE_METATYPE(DEFINE_META_ENUM_TO_TYPE)
-#undef DEFINE_META_ENUM_TO_TYPE
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include <QTest>
+#include "tst_qmetatype_common.h"
+#include "tst_qvariant_common.h"
-template <int ID>
-struct DefaultValueFactory
+struct Derived : QObject
{
- typedef typename MetaEnumToType<ID>::Type Type;
- static Type *create() { return new Type; }
+ Q_OBJECT
};
-template <>
-struct DefaultValueFactory<QMetaType::Void>
+struct MessageHandlerCustom : public MessageHandler
{
- typedef MetaEnumToType<QMetaType::Void>::Type Type;
- static Type *create() { return 0; }
+ MessageHandlerCustom(const int typeId)
+ : MessageHandler(typeId, handler)
+ {}
+ static void handler(QtMsgType, const QMessageLogContext &, const QString &msg)
+ {
+ QCOMPARE(msg.trimmed(), expectedMessage.trimmed());
+ }
+ inline static QString expectedMessage;
};
-template <int ID>
-struct DefaultValueTraits
+class tst_QMetaType: public QObject
{
- // By default we assume that a default-constructed value (new T) is
- // initialized; e.g. QCOMPARE(*(new T), *(new T)) should succeed
- enum { IsInitialized = true };
-};
+ Q_OBJECT
+ Q_PROPERTY(QList<QVariant> prop READ prop WRITE setProp)
-#define DEFINE_NON_INITIALIZED_DEFAULT_VALUE_TRAITS(MetaTypeName, MetaTypeId, RealType) \
-template<> struct DefaultValueTraits<QMetaType::MetaTypeName> { \
- enum { IsInitialized = false }; \
-};
-// Primitive types (int et al) aren't initialized
-FOR_EACH_PRIMITIVE_METATYPE(DEFINE_NON_INITIALIZED_DEFAULT_VALUE_TRAITS)
-#undef DEFINE_NON_INITIALIZED_DEFAULT_VALUE_TRAITS
+public:
+ struct GadgetPropertyType {
+ QByteArray type;
+ QByteArray name;
+ QVariant testData;
+ };
-template <int ID>
-struct TestValueFactory {};
+ tst_QMetaType() { propList << 42 << "Hello"; }
-template<> struct TestValueFactory<QMetaType::Void> {
- static void *create() { return 0; }
-};
+ QList<QVariant> prop() const { return propList; }
+ void setProp(const QList<QVariant> &list) { propList = list; }
-template<> struct TestValueFactory<QMetaType::QString> {
- static QString *create() { return new QString(QString::fromLatin1("QString")); }
-};
-template<> struct TestValueFactory<QMetaType::Int> {
- static int *create() { return new int(INT_MIN); }
-};
-template<> struct TestValueFactory<QMetaType::UInt> {
- static uint *create() { return new uint(UINT_MAX); }
-};
-template<> struct TestValueFactory<QMetaType::Bool> {
- static bool *create() { return new bool(true); }
-};
-template<> struct TestValueFactory<QMetaType::Double> {
- static double *create() { return new double(DBL_MIN); }
-};
-template<> struct TestValueFactory<QMetaType::QByteArray> {
- static QByteArray *create() { return new QByteArray(QByteArray("QByteArray")); }
-};
-template<> struct TestValueFactory<QMetaType::QByteArrayList> {
- static QByteArrayList *create() { return new QByteArrayList(QByteArrayList() << "Q" << "Byte" << "Array" << "List"); }
-};
-template<> struct TestValueFactory<QMetaType::QVariantMap> {
- static QVariantMap *create() { return new QVariantMap(); }
-};
-template<> struct TestValueFactory<QMetaType::QVariantHash> {
- static QVariantHash *create() { return new QVariantHash(); }
-};
-template<> struct TestValueFactory<QMetaType::QVariantList> {
- static QVariantList *create() { return new QVariantList(QVariantList() << 123 << "Q" << "Variant" << "List"); }
-};
-template<> struct TestValueFactory<QMetaType::QChar> {
- static QChar *create() { return new QChar(QChar('q')); }
-};
-template<> struct TestValueFactory<QMetaType::Long> {
- static long *create() { return new long(LONG_MIN); }
-};
-template<> struct TestValueFactory<QMetaType::Short> {
- static short *create() { return new short(SHRT_MIN); }
-};
-template<> struct TestValueFactory<QMetaType::Char> {
- static char *create() { return new char('c'); }
-};
-template<> struct TestValueFactory<QMetaType::Char16> {
- static char16_t *create() { return new char16_t('c'); }
-};
-template<> struct TestValueFactory<QMetaType::Char32> {
- static char32_t *create() { return new char32_t('c'); }
-};
-template<> struct TestValueFactory<QMetaType::ULong> {
- static ulong *create() { return new ulong(ULONG_MAX); }
-};
-template<> struct TestValueFactory<QMetaType::UShort> {
- static ushort *create() { return new ushort(USHRT_MAX); }
-};
-template<> struct TestValueFactory<QMetaType::SChar> {
- static signed char *create() { return new signed char(CHAR_MIN); }
-};
-template<> struct TestValueFactory<QMetaType::UChar> {
- static uchar *create() { return new uchar(UCHAR_MAX); }
-};
-template<> struct TestValueFactory<QMetaType::Float> {
- static float *create() { return new float(FLT_MIN); }
-};
-template<> struct TestValueFactory<QMetaType::QObjectStar> {
- static QObject * *create() { return new QObject *(0); }
-};
-template<> struct TestValueFactory<QMetaType::VoidStar> {
- static void * *create() { return new void *(0); }
-};
-template<> struct TestValueFactory<QMetaType::LongLong> {
- static qlonglong *create() { return new qlonglong(LLONG_MIN); }
-};
-template<> struct TestValueFactory<QMetaType::ULongLong> {
- static qulonglong *create() { return new qulonglong(ULLONG_MAX); }
-};
-template<> struct TestValueFactory<QMetaType::QStringList> {
- static QStringList *create() { return new QStringList(QStringList() << "Q" << "t"); }
-};
-template<> struct TestValueFactory<QMetaType::QBitArray> {
- static QBitArray *create() { return new QBitArray(QBitArray(256, true)); }
-};
-template<> struct TestValueFactory<QMetaType::QDate> {
- static QDate *create() { return new QDate(QDate::currentDate()); }
-};
-template<> struct TestValueFactory<QMetaType::QTime> {
- static QTime *create() { return new QTime(QTime::currentTime()); }
-};
-template<> struct TestValueFactory<QMetaType::QDateTime> {
- static QDateTime *create() { return new QDateTime(QDateTime::currentDateTime()); }
-};
-template<> struct TestValueFactory<QMetaType::QUrl> {
- static QUrl *create() { return new QUrl("http://www.example.org"); }
-};
-template<> struct TestValueFactory<QMetaType::QLocale> {
- static QLocale *create() { return new QLocale(QLocale::c()); }
-};
-template<> struct TestValueFactory<QMetaType::QRect> {
- static QRect *create() { return new QRect(10, 20, 30, 40); }
-};
-template<> struct TestValueFactory<QMetaType::QRectF> {
- static QRectF *create() { return new QRectF(10, 20, 30, 40); }
-};
-template<> struct TestValueFactory<QMetaType::QSize> {
- static QSize *create() { return new QSize(10, 20); }
-};
-template<> struct TestValueFactory<QMetaType::QSizeF> {
- static QSizeF *create() { return new QSizeF(10, 20); }
-};
-template<> struct TestValueFactory<QMetaType::QLine> {
- static QLine *create() { return new QLine(10, 20, 30, 40); }
-};
-template<> struct TestValueFactory<QMetaType::QLineF> {
- static QLineF *create() { return new QLineF(10, 20, 30, 40); }
-};
-template<> struct TestValueFactory<QMetaType::QPoint> {
- static QPoint *create() { return new QPoint(10, 20); }
-};
-template<> struct TestValueFactory<QMetaType::QPointF> {
- static QPointF *create() { return new QPointF(10, 20); }
-};
-template<> struct TestValueFactory<QMetaType::QEasingCurve> {
- static QEasingCurve *create() { return new QEasingCurve(QEasingCurve::InOutElastic); }
-};
-template<> struct TestValueFactory<QMetaType::QUuid> {
- static QUuid *create() { return new QUuid(); }
-};
-template<> struct TestValueFactory<QMetaType::QModelIndex> {
- static QModelIndex *create() { return new QModelIndex(); }
-};
-template<> struct TestValueFactory<QMetaType::QPersistentModelIndex> {
- static QPersistentModelIndex *create() { return new QPersistentModelIndex(); }
-};
-template<> struct TestValueFactory<QMetaType::Nullptr> {
- static std::nullptr_t *create() { return new std::nullptr_t; }
+private:
+ void registerGadget(const char * name, const QList<GadgetPropertyType> &gadgetProperties);
+ QList<QVariant> propList;
+
+private slots:
+ void defined();
+#if QT_CONFIG(thread)
+ void threadSafety();
+#endif
+ void namespaces();
+ void id();
+ void qMetaTypeId();
+ void properties();
+ void normalizedTypes();
+ void typeName_data();
+ void typeName();
+ void type_data();
+ void type();
+ void type_fromSubString_data();
+ void type_fromSubString();
+ void create_data();
+ void create();
+ void createCopy_data();
+ void createCopy();
+ void sizeOf_data();
+ void sizeOf();
+ void sizeOfStaticLess_data();
+ void sizeOfStaticLess();
+ void alignOf_data();
+ void alignOf();
+ void flags_data();
+ void flags();
+ void flags2_data();
+ void flags2();
+ void flagsBinaryCompatibility6_0_data();
+ void flagsBinaryCompatibility6_0();
+ void construct_data();
+ void construct();
+ void defaultConstructTrivial_QTBUG_109594();
+ void typedConstruct();
+ void constructCopy_data();
+ void constructCopy();
+ void selfCompare_data();
+ void selfCompare();
+ void typedefs();
+ void registerType();
+ void isRegistered_data();
+ void isRegistered();
+ void isRegisteredStaticLess_data();
+ void isRegisteredStaticLess();
+ void isNotRegistered();
+ void isEnum();
+ void underlyingType_data();
+ void underlyingType();
+ void automaticTemplateRegistration_1();
+ void automaticTemplateRegistration_2(); // defined in tst_qmetatype3.cpp
+ void saveAndLoadBuiltin_data();
+ void saveAndLoadBuiltin();
+ void saveAndLoadCustom();
+ void metaObject_data();
+ void metaObject();
+ void constexprMetaTypeIds();
+
+ // tst_qmetatype2.cpp
+ void constRefs();
+ void convertCustomType_data();
+ void convertCustomType();
+ void convertConstNonConst();
+ void compareCustomEqualOnlyType();
+ void customDebugStream();
+ void unknownType();
+ void fromType();
+ void operatorEq_data();
+ void operatorEq();
+ void operatorEq2_data();
+ void operatorEq2();
+ void operatorEqAcrossLibs_data();
+ void operatorEqAcrossLibs();
+ void typesWithInaccessibleDTors();
+ void voidIsNotUnknown();
+ void typeNameNormalization();
+ void typeNameInQtPrivate();
+
+ // Tests for deprecated APIs
+#if QT_DEPRECATED_SINCE(6, 0)
+ void testDeprecatedGetters_data() { type_data(); }
+ void testDeprecatedGetters();
+ void testDeprecatedLoadSave_data() { saveAndLoadBuiltin_data(); }
+ void testDeprecatedLoadSave();
+#endif
};
-template<> struct TestValueFactory<QMetaType::QRegularExpression> {
- static QRegularExpression *create()
- {
-#if QT_CONFIG(regularexpression)
- return new QRegularExpression("abc.*def");
-#else
- return 0;
+
+template <typename T>
+struct Whity { T t; Whity() {} };
+
+Q_DECLARE_METATYPE(Whity<int>)
+Q_DECLARE_METATYPE(Whity<double>)
+
+#if !defined(Q_CC_CLANG) && defined(Q_CC_GNU) && Q_CC_GNU < 501
+QT_BEGIN_NAMESPACE
+Q_DECLARE_TYPEINFO(Whity<double>, Q_RELOCATABLE_TYPE);
+QT_END_NAMESPACE
#endif
- }
+
+struct CustomConvertibleType
+{
+ explicit CustomConvertibleType(const QVariant &foo = QVariant()) : m_foo(foo) {}
+ virtual ~CustomConvertibleType() {}
+ QString toString() const { return m_foo.toString(); }
+ operator QPoint() const { return QPoint(12, 34); }
+ template<typename To>
+ To convert() const { return s_value.value<To>();}
+ template<typename To>
+ To convertOk(bool *ok) const { *ok = s_ok; return s_value.value<To>();}
+
+ QVariant m_foo;
+ inline static QVariant s_value;
+ inline static bool s_ok = true;
+
+ friend bool operator<(const CustomConvertibleType &lhs, const CustomConvertibleType &rhs)
+ { return lhs.m_foo.toString() < rhs.m_foo.toString(); }
+ friend bool operator==(const CustomConvertibleType &lhs, const CustomConvertibleType &rhs)
+ { return lhs.m_foo == rhs.m_foo; }
+ friend bool operator!=(const CustomConvertibleType &lhs, const CustomConvertibleType &rhs)
+ { return !operator==(lhs, rhs); }
};
-template<> struct TestValueFactory<QMetaType::QJsonValue> {
- static QJsonValue *create() { return new QJsonValue(123.); }
+
+struct CustomConvertibleType2
+{
+ // implicit
+ CustomConvertibleType2(const CustomConvertibleType &t = CustomConvertibleType())
+ : m_foo(t.m_foo) {}
+ virtual ~CustomConvertibleType2() {}
+
+ QVariant m_foo;
+
+ friend bool operator==(const CustomConvertibleType2 &lhs, const CustomConvertibleType2 &rhs)
+ { return lhs.m_foo == rhs.m_foo; }
+ friend bool operator!=(const CustomConvertibleType2 &lhs, const CustomConvertibleType2 &rhs)
+ { return !operator==(lhs, rhs); }
};
-template<> struct TestValueFactory<QMetaType::QJsonObject> {
- static QJsonObject *create() {
- QJsonObject *o = new QJsonObject();
- o->insert("a", 123.);
- o->insert("b", true);
- o->insert("c", QJsonValue::Null);
- o->insert("d", QLatin1String("ciao"));
- return o;
+
+struct CustomDebugStreamableType
+{
+ QString toString() const { return "test"; }
+
+ friend QDebug operator<<(QDebug dbg, const CustomDebugStreamableType&)
+ {
+ return dbg << "string-content";
}
};
-template<> struct TestValueFactory<QMetaType::QJsonArray> {
- static QJsonArray *create() {
- QJsonArray *a = new QJsonArray();
- a->append(123.);
- a->append(true);
- a->append(QJsonValue::Null);
- a->append(QLatin1String("ciao"));
- return a;
- }
+
+struct CustomDebugStreamableType2
+{
+ QString toString() const { return "test"; }
};
-template<> struct TestValueFactory<QMetaType::QJsonDocument> {
- static QJsonDocument *create() {
- return new QJsonDocument(
- QJsonDocument::fromJson("{ 'foo': 123, 'bar': [true, null, 'ciao'] }")
- );
- }
+
+struct CustomEqualsOnlyType
+{
+ explicit CustomEqualsOnlyType(int value = 0) : val(value) {}
+ virtual ~CustomEqualsOnlyType() {}
+
+ int val;
+
+ friend bool operator==(const CustomEqualsOnlyType &lhs, const CustomEqualsOnlyType &rhs)
+ { return lhs.val == rhs.val;}
+ friend bool operator!=(const CustomEqualsOnlyType &lhs, const CustomEqualsOnlyType &rhs)
+ { return !operator==(lhs, rhs); }
};
-template<> struct TestValueFactory<QMetaType::QCborSimpleType> {
- static QCborSimpleType *create() { return new QCborSimpleType(QCborSimpleType::True); }
+static_assert(QTypeTraits::has_operator_equal_v<CustomEqualsOnlyType>);
+static_assert(!QTypeTraits::has_operator_less_than_v<CustomEqualsOnlyType>);
+
+struct BaseGadgetType
+{
+ Q_GADGET
+public:
+ explicit BaseGadgetType(QVariant foo = QVariant()) : m_foo(std::move(foo)) {}
+ QVariant m_foo;
};
-template<> struct TestValueFactory<QMetaType::QCborValue> {
- static QCborValue *create() { return new QCborValue(123.); }
+
+struct DerivedGadgetType : public BaseGadgetType
+{
+ Q_GADGET
+public:
+ explicit DerivedGadgetType(QVariant foo = QVariant()) : BaseGadgetType(std::move(foo)) {}
+ int bar = 25;
};
-template<> struct TestValueFactory<QMetaType::QCborMap> {
- static QCborMap *create() {
- return new QCborMap{{0, 0}, {"Hello", 1}, {1, nullptr}};
- }
+
+Q_DECLARE_METATYPE(CustomConvertibleType);
+Q_DECLARE_METATYPE(CustomConvertibleType2);
+Q_DECLARE_METATYPE(CustomDebugStreamableType);
+Q_DECLARE_METATYPE(CustomEqualsOnlyType);
+
+struct CustomMovable {
+ CustomMovable() {}
+
+ friend bool operator==(const CustomMovable &, const CustomMovable &) { return true; }
+ // needed for QSet<CustomMovable>. We actually check that it makes sense.
+ friend qsizetype qHash(const CustomMovable &, qsizetype seed = 0) { return seed; }
};
-template<> struct TestValueFactory<QMetaType::QCborArray> {
- static QCborArray *create() {
- return new QCborArray{0, 1, -2, 2.5, false, nullptr, "Hello", QByteArray("World") };
+
+#if !defined(Q_CC_CLANG) && defined(Q_CC_GNU) && Q_CC_GNU < 501
+QT_BEGIN_NAMESPACE
+Q_DECLARE_TYPEINFO(CustomMovable, Q_RELOCATABLE_TYPE);
+QT_END_NAMESPACE
+#endif
+
+Q_DECLARE_METATYPE(CustomMovable);
+
+#define FOR_EACH_STATIC_PRIMITIVE_TYPE(F) \
+ F(bool) \
+ F(int) \
+ F(qulonglong) \
+ F(double) \
+ F(short) \
+ F(char) \
+ F(ulong) \
+ F(uchar) \
+ F(float) \
+ F(QObject*) \
+ F(QString) \
+ F(CustomMovable)
+
+#define FOR_EACH_STATIC_PRIMITIVE_TYPE2(F, SecondaryRealName) \
+ F(uint, SecondaryRealName) \
+ F(qlonglong, SecondaryRealName) \
+ F(char, SecondaryRealName) \
+ F(uchar, SecondaryRealName) \
+ F(QObject*, SecondaryRealName)
+
+#define CREATE_AND_VERIFY_CONTAINER(CONTAINER, ...) \
+ { \
+ CONTAINER< __VA_ARGS__ > t; \
+ const QVariant v = QVariant::fromValue(t); \
+ QByteArray tn = createTypeName(#CONTAINER "<", #__VA_ARGS__); \
+ const int expectedType = ::qMetaTypeId<CONTAINER< __VA_ARGS__ > >(); \
+ const int type = QMetaType::fromName(tn).id(); \
+ QCOMPARE(type, expectedType); \
+ QCOMPARE((QMetaType::fromType<CONTAINER< __VA_ARGS__ >>().id()), expectedType); \
}
-};
-template<> struct TestValueFactory<QMetaType::QVariant> {
- static QVariant *create() { return new QVariant(QStringList(QStringList() << "Q" << "t")); }
-};
+#define FOR_EACH_1ARG_TEMPLATE_TYPE(F, TYPE) \
+ F(QList, TYPE) \
+ F(QQueue, TYPE) \
+ F(QStack, TYPE) \
+ F(QSet, TYPE)
+
+#define PRINT_1ARG_TEMPLATE(RealName) \
+ FOR_EACH_1ARG_TEMPLATE_TYPE(CREATE_AND_VERIFY_CONTAINER, RealName)
+
+#define FOR_EACH_2ARG_TEMPLATE_TYPE(F, RealName1, RealName2) \
+ F(QHash, RealName1, RealName2) \
+ F(QMap, RealName1, RealName2) \
+ F(std::pair, RealName1, RealName2)
+
+#define PRINT_2ARG_TEMPLATE_INTERNAL(RealName1, RealName2) \
+ FOR_EACH_2ARG_TEMPLATE_TYPE(CREATE_AND_VERIFY_CONTAINER, RealName1, RealName2)
+
+#define PRINT_2ARG_TEMPLATE(RealName) \
+ FOR_EACH_STATIC_PRIMITIVE_TYPE2(PRINT_2ARG_TEMPLATE_INTERNAL, RealName)
+
+#define REGISTER_TYPEDEF(TYPE, ARG1, ARG2) \
+ qRegisterMetaType<TYPE <ARG1, ARG2>>(#TYPE "<" #ARG1 "," #ARG2 ">");
+
+static inline QByteArray createTypeName(const char *begin, const char *va)
+{
+ QByteArray tn(begin);
+ const QList<QByteArray> args = QByteArray(va).split(',');
+ tn += args.first().trimmed();
+ if (args.size() > 1) {
+ QList<QByteArray>::const_iterator it = args.constBegin() + 1;
+ const QList<QByteArray>::const_iterator end = args.constEnd();
+ for (; it != end; ++it) {
+ tn += ",";
+ tn += it->trimmed();
+ }
+ }
+ if (tn.endsWith('>'))
+ tn += ' ';
+ tn += '>';
+ return tn;
+}
-#endif // TST_QMETATYPE_H
+Q_DECLARE_METATYPE(const void*)