1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtCore module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include "qmetatype.h"
43 #include "qmetatype_p.h"
44 #include "qobjectdefs.h"
45 #include "qdatetime.h"
46 #include "qbytearray.h"
47 #include "qreadwritelock.h"
49 #include "qstringlist.h"
52 #include "qeasingcurve.h"
55 #include "qmetatypeswitcher_p.h"
57 #ifdef QT_BOOTSTRAPPED
58 # ifndef QT_NO_GEOM_VARIANT
59 # define QT_NO_GEOM_VARIANT
62 # include "qbitarray.h"
64 # include "qvariant.h"
65 # include "qabstractitemmodel.h"
68 #ifndef QT_NO_GEOM_VARIANT
77 #define NS(x) QT_PREPEND_NAMESPACE(x)
82 struct TypeDefinition {
83 static const bool IsAvailable = true;
86 struct DefinedTypesFilter {
89 static const bool IsAccepted = TypeDefinition<T>::IsAvailable && QTypeModuleInfo<T>::IsCore;
93 // Ignore these types, as incomplete
94 #ifdef QT_NO_GEOM_VARIANT
95 template<> struct TypeDefinition<QRect> { static const bool IsAvailable = false; };
96 template<> struct TypeDefinition<QRectF> { static const bool IsAvailable = false; };
97 template<> struct TypeDefinition<QSize> { static const bool IsAvailable = false; };
98 template<> struct TypeDefinition<QSizeF> { static const bool IsAvailable = false; };
99 template<> struct TypeDefinition<QLine> { static const bool IsAvailable = false; };
100 template<> struct TypeDefinition<QLineF> { static const bool IsAvailable = false; };
101 template<> struct TypeDefinition<QPoint> { static const bool IsAvailable = false; };
102 template<> struct TypeDefinition<QPointF> { static const bool IsAvailable = false; };
104 #ifdef QT_BOOTSTRAPPED
105 template<> struct TypeDefinition<QVariantMap> { static const bool IsAvailable = false; };
106 template<> struct TypeDefinition<QVariantHash> { static const bool IsAvailable = false; };
107 template<> struct TypeDefinition<QVariantList> { static const bool IsAvailable = false; };
108 template<> struct TypeDefinition<QVariant> { static const bool IsAvailable = false; };
109 template<> struct TypeDefinition<QBitArray> { static const bool IsAvailable = false; };
110 template<> struct TypeDefinition<QUrl> { static const bool IsAvailable = false; };
111 template<> struct TypeDefinition<QEasingCurve> { static const bool IsAvailable = false; };
112 template<> struct TypeDefinition<QModelIndex> { static const bool IsAvailable = false; };
115 template<> struct TypeDefinition<QRegExp> { static const bool IsAvailable = false; };
120 \macro Q_DECLARE_OPAQUE_POINTER(Pointer)
123 This macro enables pointers to forward-declared types to be registered with
124 QMetaType using either Q_DECLARE_METATYPE() or qRegisterMetaType().
126 \sa Q_DECLARE_METATYPE(), qRegisterMetaType()
131 \macro Q_DECLARE_METATYPE(Type)
134 This macro makes the type \a Type known to QMetaType as long as it
135 provides a public default constructor, a public copy constructor and
137 It is needed to use the type \a Type as a custom type in QVariant.
139 This macro requires that \a Type is a fully defined type at the point where
140 it is used. For pointer types, it also requires that the pointed to type is
141 fully defined. Use in conjunction with Q_DECLARE_OPAQUE_POINTER() to
142 register pointers to forward declared types.
144 Ideally, this macro should be placed below the declaration of
145 the class or struct. If that is not possible, it can be put in
146 a private header file which has to be included every time that
147 type is used in a QVariant.
149 Adding a Q_DECLARE_METATYPE() makes the type known to all template
150 based functions, including QVariant. Note that if you intend to
151 use the type in \e queued signal and slot connections or in
152 QObject's property system, you also have to call
153 qRegisterMetaType() since the names are resolved at runtime.
155 This example shows a typical use case of Q_DECLARE_METATYPE():
157 \snippet doc/src/snippets/code/src_corelib_kernel_qmetatype.cpp 0
159 If \c MyStruct is in a namespace, the Q_DECLARE_METATYPE() macro
160 has to be outside the namespace:
162 \snippet doc/src/snippets/code/src_corelib_kernel_qmetatype.cpp 1
164 Since \c{MyStruct} is now known to QMetaType, it can be used in QVariant:
166 \snippet doc/src/snippets/code/src_corelib_kernel_qmetatype.cpp 2
168 \sa qRegisterMetaType()
172 \enum QMetaType::Type
174 These are the built-in types supported by QMetaType:
179 \value UInt \c{unsigned int}
180 \value Double \c double
182 \value QString QString
183 \value QByteArray QByteArray
185 \value VoidStar \c{void *}
187 \value LongLong LongLong
188 \value Short \c{short}
190 \value ULong \c{unsigned long}
191 \value ULongLong ULongLong
192 \value UShort \c{unsigned short}
193 \value UChar \c{unsigned char}
194 \value Float \c float
195 \value QObjectStar QObject *
196 \value QWidgetStar QWidget *
197 \value QVariant QVariant
199 \value QCursor QCursor
203 \value QVariantList QVariantList
204 \value QPolygon QPolygon
205 \value QPolygonF QPolygonF
210 \value QTextLength QTextLength
211 \value QStringList QStringList
212 \value QVariantMap QVariantMap
213 \value QVariantHash QVariantHash
217 \value QTextFormat QTextFormat
221 \value QRegExp QRegExp
222 \value QDateTime QDateTime
223 \value QPointF QPointF
224 \value QPalette QPalette
227 \value QRegion QRegion
228 \value QBitArray QBitArray
230 \value QKeySequence QKeySequence
231 \value QSizePolicy QSizePolicy
232 \value QPixmap QPixmap
233 \value QLocale QLocale
234 \value QBitmap QBitmap
235 \value QMatrix QMatrix
236 \value QTransform QTransform
237 \value QMatrix4x4 QMatrix4x4
238 \value QVector2D QVector2D
239 \value QVector3D QVector3D
240 \value QVector4D QVector4D
241 \value QQuaternion QQuaternion
242 \value QEasingCurve QEasingCurve
244 \value User Base value for user types
246 \omitvalue FirstGuiType
247 \omitvalue FirstWidgetsType
248 \omitvalue LastCoreType
249 \omitvalue LastGuiType
250 \omitvalue LastWidgetsType
252 \omitvalue HighestInternalId
254 Additional types can be registered using Q_DECLARE_METATYPE().
256 \sa type(), typeName()
260 \enum QMetaType::TypeFlags
262 The enum describes attributes of a type supported by QMetaType.
264 \value NeedsConstruction This type has non-trivial constructors. If the flag is not set instances can be safely initialized with memset to 0.
265 \value NeedsDestruction This type has a non-trivial destructor. If the flag is not set calls to the destructor are not necessary before discarding objects.
266 \value MovableType An instance of a type having this attribute can be safely moved by memcpy.
271 \brief The QMetaType class manages named types in the meta-object system.
276 The class is used as a helper to marshall types in QVariant and
277 in queued signals and slots connections. It associates a type
278 name to a type so that it can be created and destructed
279 dynamically at run-time. Declare new types with Q_DECLARE_METATYPE()
280 to make them available to QVariant and other template-based functions.
281 Call qRegisterMetaType() to make type available to non-template based
282 functions, such as the queued signal and slot connections.
284 Any class or struct that has a public default
285 constructor, a public copy constructor, and a public destructor
288 The following code allocates and destructs an instance of
291 \snippet doc/src/snippets/code/src_corelib_kernel_qmetatype.cpp 3
293 If we want the stream operators \c operator<<() and \c
294 operator>>() to work on QVariant objects that store custom types,
295 the custom type must provide \c operator<<() and \c operator>>()
298 \sa Q_DECLARE_METATYPE(), QVariant::setValue(), QVariant::value(), QVariant::fromValue()
301 #define QT_ADD_STATIC_METATYPE(MetaTypeName, MetaTypeId, RealName) \
302 { #RealName, sizeof(#RealName) - 1, MetaTypeId },
304 #define QT_ADD_STATIC_METATYPE_ALIASES_ITER(MetaTypeName, MetaTypeId, AliasingName, RealNameStr) \
305 { RealNameStr, sizeof(RealNameStr) - 1, QMetaType::MetaTypeName },
307 #define QT_ADD_STATIC_METATYPE_HACKS_ITER(MetaTypeName, TypeId, Name) \
308 QT_ADD_STATIC_METATYPE(MetaTypeName, MetaTypeName, Name)
310 static const struct { const char * typeName; int typeNameLength; int type; } types[] = {
311 QT_FOR_EACH_STATIC_TYPE(QT_ADD_STATIC_METATYPE)
312 QT_FOR_EACH_STATIC_ALIAS_TYPE(QT_ADD_STATIC_METATYPE_ALIASES_ITER)
313 QT_FOR_EACH_STATIC_HACKS_TYPE(QT_ADD_STATIC_METATYPE_HACKS_ITER)
314 {0, 0, QMetaType::Void}
317 Q_CORE_EXPORT const QMetaTypeInterface *qMetaTypeGuiHelper = 0;
318 Q_CORE_EXPORT const QMetaTypeInterface *qMetaTypeWidgetsHelper = 0;
320 class QCustomTypeInfo : public QMetaTypeInterface
326 QMetaTypeInterface empty = QT_METATYPE_INTERFACE_INIT(void);
327 *static_cast<QMetaTypeInterface*>(this) = empty;
335 union CheckThatItIsPod
336 { // This should break if QMetaTypeInterface is not a POD type
337 QMetaTypeInterface iface;
341 Q_DECLARE_TYPEINFO(QCustomTypeInfo, Q_MOVABLE_TYPE);
342 Q_GLOBAL_STATIC(QVector<QCustomTypeInfo>, customTypes)
343 Q_GLOBAL_STATIC(QReadWriteLock, customTypesLock)
345 #ifndef QT_NO_DATASTREAM
348 void QMetaType::registerStreamOperators(const char *typeName, SaveOperator saveOp,
351 int idx = type(typeName);
354 registerStreamOperators(idx, saveOp, loadOp);
359 void QMetaType::registerStreamOperators(int idx, SaveOperator saveOp,
363 return; //builtin types should not be registered;
364 QVector<QCustomTypeInfo> *ct = customTypes();
367 QWriteLocker locker(customTypesLock());
368 QCustomTypeInfo &inf = (*ct)[idx - User];
372 #endif // QT_NO_DATASTREAM
375 Returns the type name associated with the given \a type, or 0 if no
376 matching type was found. The returned pointer must not be deleted.
378 \sa type(), isRegistered(), Type
380 const char *QMetaType::typeName(int type)
382 // In theory it can be filled during compilation time, but for some reason template code
383 // that is able to do it causes GCC 4.6 to generate additional 3K of executable code. Probably
384 // it is not worth of it.
385 static const char *namesCache[QMetaType::HighestInternalId + 1];
388 if (type <= QMetaType::HighestInternalId && ((result = namesCache[type])))
391 #define QT_METATYPE_TYPEID_TYPENAME_CONVERTER(MetaTypeName, TypeId, RealName) \
392 case QMetaType::MetaTypeName: result = #RealName; break;
394 switch (QMetaType::Type(type)) {
395 QT_FOR_EACH_STATIC_TYPE(QT_METATYPE_TYPEID_TYPENAME_CONVERTER)
398 if (Q_UNLIKELY(type < QMetaType::User)) {
399 return 0; // It can happen when someone cast int to QVariant::Type, we should not crash...
401 const QVector<QCustomTypeInfo> * const ct = customTypes();
402 QReadLocker locker(customTypesLock());
403 return ct && ct->count() > type - QMetaType::User && !ct->at(type - QMetaType::User).typeName.isEmpty()
404 ? ct->at(type - QMetaType::User).typeName.constData()
409 #undef QT_METATYPE_TYPEID_TYPENAME_CONVERTER
411 Q_ASSERT(type <= QMetaType::HighestInternalId);
412 namesCache[type] = result;
417 Similar to QMetaType::type(), but only looks in the static set of types.
419 static inline int qMetaTypeStaticType(const char *typeName, int length)
422 while (types[i].typeName && ((length != types[i].typeNameLength)
423 || strcmp(typeName, types[i].typeName))) {
426 return types[i].type;
430 Similar to QMetaType::type(), but only looks in the custom set of
431 types, and doesn't lock the mutex.
433 static int qMetaTypeCustomType_unlocked(const char *typeName, int length)
435 const QVector<QCustomTypeInfo> * const ct = customTypes();
439 for (int v = 0; v < ct->count(); ++v) {
440 const QCustomTypeInfo &customInfo = ct->at(v);
441 if ((length == customInfo.typeName.size())
442 && !strcmp(typeName, customInfo.typeName.constData())) {
443 if (customInfo.alias >= 0)
444 return customInfo.alias;
445 return v + QMetaType::User;
453 This function is needed until existing code outside of qtbase
454 has been changed to call the new version of registerType().
456 int QMetaType::registerType(const char *typeName, Deleter deleter,
459 return registerType(typeName, deleter, creator, 0, 0, 0, TypeFlags());
465 Registers a user type for marshalling, with \a typeName, a \a
466 deleter, a \a creator, a \a destructor, a \a constructor, and
467 a \a size. Returns the type's handle, or -1 if the type could
470 int QMetaType::registerType(const char *typeName, Deleter deleter,
472 Destructor destructor,
473 Constructor constructor,
474 int size, TypeFlags flags)
476 QVector<QCustomTypeInfo> *ct = customTypes();
477 if (!ct || !typeName || !deleter || !creator)
481 NS(QByteArray) normalizedTypeName = typeName;
483 NS(QByteArray) normalizedTypeName = QMetaObject::normalizedType(typeName);
486 int idx = qMetaTypeStaticType(normalizedTypeName.constData(),
487 normalizedTypeName.size());
489 int previousSize = 0;
490 int previousFlags = 0;
492 QWriteLocker locker(customTypesLock());
493 idx = qMetaTypeCustomType_unlocked(normalizedTypeName.constData(),
494 normalizedTypeName.size());
497 inf.typeName = normalizedTypeName;
498 inf.creator = creator;
499 inf.deleter = deleter;
500 #ifndef QT_NO_DATASTREAM
505 inf.constructor = constructor;
506 inf.destructor = destructor;
509 idx = ct->size() + User;
515 previousSize = ct->at(idx - User).size;
516 previousFlags = ct->at(idx - User).flags;
521 previousSize = QMetaType::sizeOf(idx);
522 previousFlags = QMetaType::typeFlags(idx);
525 if (previousSize != size) {
526 qFatal("QMetaType::registerType: Binary compatibility break "
527 "-- Size mismatch for type '%s' [%i]. Previously registered "
528 "size %i, now registering size %i.",
529 normalizedTypeName.constData(), idx, previousSize, size);
531 if (previousFlags != flags) {
532 qFatal("QMetaType::registerType: Binary compatibility break "
533 "-- Type flags for type '%s' [%i] don't match. Previously "
534 "registered TypeFlags(0x%x), now registering TypeFlags(0x%x).",
535 normalizedTypeName.constData(), idx, previousFlags, int(flags));
544 Registers a user type for marshalling, as an alias of another type (typedef)
546 int QMetaType::registerTypedef(const char* typeName, int aliasId)
548 QVector<QCustomTypeInfo> *ct = customTypes();
549 if (!ct || !typeName)
553 NS(QByteArray) normalizedTypeName = typeName;
555 NS(QByteArray) normalizedTypeName = QMetaObject::normalizedType(typeName);
558 int idx = qMetaTypeStaticType(normalizedTypeName.constData(),
559 normalizedTypeName.size());
562 QWriteLocker locker(customTypesLock());
563 idx = qMetaTypeCustomType_unlocked(normalizedTypeName.constData(),
564 normalizedTypeName.size());
568 inf.typeName = normalizedTypeName;
577 if (idx != aliasId) {
578 qFatal("QMetaType::registerTypedef: Binary compatibility break "
579 "-- Type name '%s' previously registered as typedef of '%s' [%i], "
580 "now registering as typedef of '%s' [%i].",
581 normalizedTypeName.constData(), QMetaType::typeName(idx), idx,
582 QMetaType::typeName(aliasId), aliasId);
588 Returns true if the datatype with ID \a type is registered;
589 otherwise returns false.
591 \sa type(), typeName(), Type
593 bool QMetaType::isRegistered(int type)
595 if (type >= 0 && type < User) {
599 QReadLocker locker(customTypesLock());
600 const QVector<QCustomTypeInfo> * const ct = customTypes();
601 return ((type >= User) && (ct && ct->count() > type - User) && !ct->at(type - User).typeName.isEmpty());
605 Returns a handle to the type called \a typeName, or 0 if there is
608 \sa isRegistered(), typeName(), Type
610 int QMetaType::type(const char *typeName)
612 int length = qstrlen(typeName);
615 int type = qMetaTypeStaticType(typeName, length);
617 QReadLocker locker(customTypesLock());
618 type = qMetaTypeCustomType_unlocked(typeName, length);
619 #ifndef QT_NO_QOBJECT
621 const NS(QByteArray) normalizedTypeName = QMetaObject::normalizedType(typeName);
622 type = qMetaTypeStaticType(normalizedTypeName.constData(),
623 normalizedTypeName.size());
625 type = qMetaTypeCustomType_unlocked(normalizedTypeName.constData(),
626 normalizedTypeName.size());
634 #ifndef QT_NO_DATASTREAM
636 Writes the object pointed to by \a data with the ID \a type to
637 the given \a stream. Returns true if the object is saved
638 successfully; otherwise returns false.
640 The type must have been registered with qRegisterMetaType() and
641 qRegisterMetaTypeStreamOperators() beforehand.
643 Normally, you should not need to call this function directly.
644 Instead, use QVariant's \c operator<<(), which relies on save()
645 to stream custom types.
647 \sa load(), qRegisterMetaTypeStreamOperators()
649 bool QMetaType::save(QDataStream &stream, int type, const void *data)
651 if (!data || !isRegistered(type))
655 case QMetaType::Void:
656 case QMetaType::VoidStar:
657 case QMetaType::QObjectStar:
658 case QMetaType::QWidgetStar:
659 case QMetaType::QModelIndex:
661 case QMetaType::Long:
662 stream << qlonglong(*static_cast<const long *>(data));
665 stream << *static_cast<const int *>(data);
667 case QMetaType::Short:
668 stream << *static_cast<const short *>(data);
670 case QMetaType::Char:
671 // force a char to be signed
672 stream << *static_cast<const signed char *>(data);
674 case QMetaType::ULong:
675 stream << qulonglong(*static_cast<const ulong *>(data));
677 case QMetaType::UInt:
678 stream << *static_cast<const uint *>(data);
680 case QMetaType::LongLong:
681 stream << *static_cast<const qlonglong *>(data);
683 case QMetaType::ULongLong:
684 stream << *static_cast<const qulonglong *>(data);
686 case QMetaType::UShort:
687 stream << *static_cast<const ushort *>(data);
689 case QMetaType::UChar:
690 stream << *static_cast<const uchar *>(data);
692 case QMetaType::Bool:
693 stream << qint8(*static_cast<const bool *>(data));
695 case QMetaType::Float:
696 stream << *static_cast<const float *>(data);
698 case QMetaType::Double:
699 stream << *static_cast<const double *>(data);
701 case QMetaType::QChar:
702 stream << *static_cast<const NS(QChar) *>(data);
704 #ifndef QT_BOOTSTRAPPED
705 case QMetaType::QVariantMap:
706 stream << *static_cast<const NS(QVariantMap)*>(data);
708 case QMetaType::QVariantHash:
709 stream << *static_cast<const NS(QVariantHash)*>(data);
711 case QMetaType::QVariantList:
712 stream << *static_cast<const NS(QVariantList)*>(data);
714 case QMetaType::QVariant:
715 stream << *static_cast<const NS(QVariant)*>(data);
718 case QMetaType::QByteArray:
719 stream << *static_cast<const NS(QByteArray)*>(data);
721 case QMetaType::QString:
722 stream << *static_cast<const NS(QString)*>(data);
724 case QMetaType::QStringList:
725 stream << *static_cast<const NS(QStringList)*>(data);
727 #ifndef QT_BOOTSTRAPPED
728 case QMetaType::QBitArray:
729 stream << *static_cast<const NS(QBitArray)*>(data);
732 case QMetaType::QDate:
733 stream << *static_cast<const NS(QDate)*>(data);
735 case QMetaType::QTime:
736 stream << *static_cast<const NS(QTime)*>(data);
738 case QMetaType::QDateTime:
739 stream << *static_cast<const NS(QDateTime)*>(data);
741 #ifndef QT_BOOTSTRAPPED
742 case QMetaType::QUrl:
743 stream << *static_cast<const NS(QUrl)*>(data);
746 case QMetaType::QLocale:
747 stream << *static_cast<const NS(QLocale)*>(data);
749 #ifndef QT_NO_GEOM_VARIANT
750 case QMetaType::QRect:
751 stream << *static_cast<const NS(QRect)*>(data);
753 case QMetaType::QRectF:
754 stream << *static_cast<const NS(QRectF)*>(data);
756 case QMetaType::QSize:
757 stream << *static_cast<const NS(QSize)*>(data);
759 case QMetaType::QSizeF:
760 stream << *static_cast<const NS(QSizeF)*>(data);
762 case QMetaType::QLine:
763 stream << *static_cast<const NS(QLine)*>(data);
765 case QMetaType::QLineF:
766 stream << *static_cast<const NS(QLineF)*>(data);
768 case QMetaType::QPoint:
769 stream << *static_cast<const NS(QPoint)*>(data);
771 case QMetaType::QPointF:
772 stream << *static_cast<const NS(QPointF)*>(data);
776 case QMetaType::QRegExp:
777 stream << *static_cast<const NS(QRegExp)*>(data);
780 #ifndef QT_BOOTSTRAPPED
781 case QMetaType::QEasingCurve:
782 stream << *static_cast<const NS(QEasingCurve)*>(data);
785 case QMetaType::QFont:
786 case QMetaType::QPixmap:
787 case QMetaType::QBrush:
788 case QMetaType::QColor:
789 case QMetaType::QPalette:
790 case QMetaType::QImage:
791 case QMetaType::QPolygon:
792 case QMetaType::QPolygonF:
793 case QMetaType::QRegion:
794 case QMetaType::QBitmap:
795 case QMetaType::QCursor:
796 case QMetaType::QKeySequence:
797 case QMetaType::QPen:
798 case QMetaType::QTextLength:
799 case QMetaType::QTextFormat:
800 case QMetaType::QMatrix:
801 case QMetaType::QTransform:
802 case QMetaType::QMatrix4x4:
803 case QMetaType::QVector2D:
804 case QMetaType::QVector3D:
805 case QMetaType::QVector4D:
806 case QMetaType::QQuaternion:
807 if (!qMetaTypeGuiHelper)
809 qMetaTypeGuiHelper[type - FirstGuiType].saveOp(stream, data);
811 case QMetaType::QIcon:
812 case QMetaType::QSizePolicy:
813 if (!qMetaTypeWidgetsHelper)
815 qMetaTypeWidgetsHelper[type - FirstWidgetsType].saveOp(stream, data);
817 case QMetaType::QUuid:
818 stream << *static_cast<const NS(QUuid)*>(data);
821 const QVector<QCustomTypeInfo> * const ct = customTypes();
825 SaveOperator saveOp = 0;
827 QReadLocker locker(customTypesLock());
828 saveOp = ct->at(type - User).saveOp;
833 saveOp(stream, data);
841 Reads the object of the specified \a type from the given \a
842 stream into \a data. Returns true if the object is loaded
843 successfully; otherwise returns false.
845 The type must have been registered with qRegisterMetaType() and
846 qRegisterMetaTypeStreamOperators() beforehand.
848 Normally, you should not need to call this function directly.
849 Instead, use QVariant's \c operator>>(), which relies on load()
850 to stream custom types.
852 \sa save(), qRegisterMetaTypeStreamOperators()
854 bool QMetaType::load(QDataStream &stream, int type, void *data)
856 if (!data || !isRegistered(type))
860 case QMetaType::Void:
861 case QMetaType::VoidStar:
862 case QMetaType::QObjectStar:
863 case QMetaType::QWidgetStar:
864 case QMetaType::QModelIndex:
866 case QMetaType::Long: {
869 *static_cast<long *>(data) = long(l);
872 stream >> *static_cast<int *>(data);
874 case QMetaType::Short:
875 stream >> *static_cast<short *>(data);
877 case QMetaType::Char:
878 // force a char to be signed
879 stream >> *static_cast<signed char *>(data);
881 case QMetaType::ULong: {
884 *static_cast<ulong *>(data) = ulong(ul);
886 case QMetaType::UInt:
887 stream >> *static_cast<uint *>(data);
889 case QMetaType::LongLong:
890 stream >> *static_cast<qlonglong *>(data);
892 case QMetaType::ULongLong:
893 stream >> *static_cast<qulonglong *>(data);
895 case QMetaType::UShort:
896 stream >> *static_cast<ushort *>(data);
898 case QMetaType::UChar:
899 stream >> *static_cast<uchar *>(data);
901 case QMetaType::Bool: {
904 *static_cast<bool *>(data) = b;
906 case QMetaType::Float:
907 stream >> *static_cast<float *>(data);
909 case QMetaType::Double:
910 stream >> *static_cast<double *>(data);
912 case QMetaType::QChar:
913 stream >> *static_cast< NS(QChar)*>(data);
915 #ifndef QT_BOOTSTRAPPED
916 case QMetaType::QVariantMap:
917 stream >> *static_cast< NS(QVariantMap)*>(data);
919 case QMetaType::QVariantHash:
920 stream >> *static_cast< NS(QVariantHash)*>(data);
922 case QMetaType::QVariantList:
923 stream >> *static_cast< NS(QVariantList)*>(data);
925 case QMetaType::QVariant:
926 stream >> *static_cast< NS(QVariant)*>(data);
929 case QMetaType::QByteArray:
930 stream >> *static_cast< NS(QByteArray)*>(data);
932 case QMetaType::QString:
933 stream >> *static_cast< NS(QString)*>(data);
935 case QMetaType::QStringList:
936 stream >> *static_cast< NS(QStringList)*>(data);
938 #ifndef QT_BOOTSTRAPPED
939 case QMetaType::QBitArray:
940 stream >> *static_cast< NS(QBitArray)*>(data);
943 case QMetaType::QDate:
944 stream >> *static_cast< NS(QDate)*>(data);
946 case QMetaType::QTime:
947 stream >> *static_cast< NS(QTime)*>(data);
949 case QMetaType::QDateTime:
950 stream >> *static_cast< NS(QDateTime)*>(data);
952 #ifndef QT_BOOTSTRAPPED
953 case QMetaType::QUrl:
954 stream >> *static_cast< NS(QUrl)*>(data);
957 case QMetaType::QLocale:
958 stream >> *static_cast< NS(QLocale)*>(data);
960 #ifndef QT_NO_GEOM_VARIANT
961 case QMetaType::QRect:
962 stream >> *static_cast< NS(QRect)*>(data);
964 case QMetaType::QRectF:
965 stream >> *static_cast< NS(QRectF)*>(data);
967 case QMetaType::QSize:
968 stream >> *static_cast< NS(QSize)*>(data);
970 case QMetaType::QSizeF:
971 stream >> *static_cast< NS(QSizeF)*>(data);
973 case QMetaType::QLine:
974 stream >> *static_cast< NS(QLine)*>(data);
976 case QMetaType::QLineF:
977 stream >> *static_cast< NS(QLineF)*>(data);
979 case QMetaType::QPoint:
980 stream >> *static_cast< NS(QPoint)*>(data);
982 case QMetaType::QPointF:
983 stream >> *static_cast< NS(QPointF)*>(data);
987 case QMetaType::QRegExp:
988 stream >> *static_cast< NS(QRegExp)*>(data);
991 #ifndef QT_BOOTSTRAPPED
992 case QMetaType::QEasingCurve:
993 stream >> *static_cast< NS(QEasingCurve)*>(data);
996 case QMetaType::QFont:
997 case QMetaType::QPixmap:
998 case QMetaType::QBrush:
999 case QMetaType::QColor:
1000 case QMetaType::QPalette:
1001 case QMetaType::QImage:
1002 case QMetaType::QPolygon:
1003 case QMetaType::QPolygonF:
1004 case QMetaType::QRegion:
1005 case QMetaType::QBitmap:
1006 case QMetaType::QCursor:
1007 case QMetaType::QKeySequence:
1008 case QMetaType::QPen:
1009 case QMetaType::QTextLength:
1010 case QMetaType::QTextFormat:
1011 case QMetaType::QMatrix:
1012 case QMetaType::QTransform:
1013 case QMetaType::QMatrix4x4:
1014 case QMetaType::QVector2D:
1015 case QMetaType::QVector3D:
1016 case QMetaType::QVector4D:
1017 case QMetaType::QQuaternion:
1018 if (!qMetaTypeGuiHelper)
1020 qMetaTypeGuiHelper[type - FirstGuiType].loadOp(stream, data);
1022 case QMetaType::QIcon:
1023 case QMetaType::QSizePolicy:
1024 if (!qMetaTypeWidgetsHelper)
1026 qMetaTypeWidgetsHelper[type - FirstWidgetsType].loadOp(stream, data);
1028 case QMetaType::QUuid:
1029 stream >> *static_cast< NS(QUuid)*>(data);
1032 const QVector<QCustomTypeInfo> * const ct = customTypes();
1036 LoadOperator loadOp = 0;
1038 QReadLocker locker(customTypesLock());
1039 loadOp = ct->at(type - User).loadOp;
1044 loadOp(stream, data);
1049 #endif // QT_NO_DATASTREAM
1052 Returns a copy of \a copy, assuming it is of type \a type. If \a
1053 copy is zero, creates a default type.
1055 \sa destroy(), isRegistered(), Type
1057 void *QMetaType::create(int type, const void *copy)
1061 case QMetaType::VoidStar:
1062 case QMetaType::QObjectStar:
1063 case QMetaType::QWidgetStar:
1064 return new void *(*static_cast<void* const *>(copy));
1065 case QMetaType::Long:
1066 return new long(*static_cast<const long*>(copy));
1067 case QMetaType::Int:
1068 return new int(*static_cast<const int*>(copy));
1069 case QMetaType::Short:
1070 return new short(*static_cast<const short*>(copy));
1071 case QMetaType::Char:
1072 return new char(*static_cast<const char*>(copy));
1073 case QMetaType::ULong:
1074 return new ulong(*static_cast<const ulong*>(copy));
1075 case QMetaType::UInt:
1076 return new uint(*static_cast<const uint*>(copy));
1077 case QMetaType::LongLong:
1078 return new qlonglong(*static_cast<const qlonglong*>(copy));
1079 case QMetaType::ULongLong:
1080 return new qulonglong(*static_cast<const qulonglong*>(copy));
1081 case QMetaType::UShort:
1082 return new ushort(*static_cast<const ushort*>(copy));
1083 case QMetaType::UChar:
1084 return new uchar(*static_cast<const uchar*>(copy));
1085 case QMetaType::Bool:
1086 return new bool(*static_cast<const bool*>(copy));
1087 case QMetaType::Float:
1088 return new float(*static_cast<const float*>(copy));
1089 case QMetaType::Double:
1090 return new double(*static_cast<const double*>(copy));
1091 case QMetaType::QChar:
1092 return new NS(QChar)(*static_cast<const NS(QChar)*>(copy));
1093 #ifndef QT_BOOTSTRAPPED
1094 case QMetaType::QVariantMap:
1095 return new NS(QVariantMap)(*static_cast<const NS(QVariantMap)*>(copy));
1096 case QMetaType::QVariantHash:
1097 return new NS(QVariantHash)(*static_cast<const NS(QVariantHash)*>(copy));
1098 case QMetaType::QVariantList:
1099 return new NS(QVariantList)(*static_cast<const NS(QVariantList)*>(copy));
1100 case QMetaType::QVariant:
1101 return new NS(QVariant)(*static_cast<const NS(QVariant)*>(copy));
1103 case QMetaType::QByteArray:
1104 return new NS(QByteArray)(*static_cast<const NS(QByteArray)*>(copy));
1105 case QMetaType::QString:
1106 return new NS(QString)(*static_cast<const NS(QString)*>(copy));
1107 case QMetaType::QStringList:
1108 return new NS(QStringList)(*static_cast<const NS(QStringList)*>(copy));
1109 #ifndef QT_BOOTSTRAPPED
1110 case QMetaType::QBitArray:
1111 return new NS(QBitArray)(*static_cast<const NS(QBitArray)*>(copy));
1113 case QMetaType::QDate:
1114 return new NS(QDate)(*static_cast<const NS(QDate)*>(copy));
1115 case QMetaType::QTime:
1116 return new NS(QTime)(*static_cast<const NS(QTime)*>(copy));
1117 case QMetaType::QDateTime:
1118 return new NS(QDateTime)(*static_cast<const NS(QDateTime)*>(copy));
1119 #ifndef QT_BOOTSTRAPPED
1120 case QMetaType::QUrl:
1121 return new NS(QUrl)(*static_cast<const NS(QUrl)*>(copy));
1123 case QMetaType::QLocale:
1124 return new NS(QLocale)(*static_cast<const NS(QLocale)*>(copy));
1125 #ifndef QT_NO_GEOM_VARIANT
1126 case QMetaType::QRect:
1127 return new NS(QRect)(*static_cast<const NS(QRect)*>(copy));
1128 case QMetaType::QRectF:
1129 return new NS(QRectF)(*static_cast<const NS(QRectF)*>(copy));
1130 case QMetaType::QSize:
1131 return new NS(QSize)(*static_cast<const NS(QSize)*>(copy));
1132 case QMetaType::QSizeF:
1133 return new NS(QSizeF)(*static_cast<const NS(QSizeF)*>(copy));
1134 case QMetaType::QLine:
1135 return new NS(QLine)(*static_cast<const NS(QLine)*>(copy));
1136 case QMetaType::QLineF:
1137 return new NS(QLineF)(*static_cast<const NS(QLineF)*>(copy));
1138 case QMetaType::QPoint:
1139 return new NS(QPoint)(*static_cast<const NS(QPoint)*>(copy));
1140 case QMetaType::QPointF:
1141 return new NS(QPointF)(*static_cast<const NS(QPointF)*>(copy));
1143 #ifndef QT_NO_REGEXP
1144 case QMetaType::QRegExp:
1145 return new NS(QRegExp)(*static_cast<const NS(QRegExp)*>(copy));
1147 #ifndef QT_BOOTSTRAPPED
1148 case QMetaType::QEasingCurve:
1149 return new NS(QEasingCurve)(*static_cast<const NS(QEasingCurve)*>(copy));
1151 case QMetaType::QUuid:
1152 return new NS(QUuid)(*static_cast<const NS(QUuid)*>(copy));
1153 #ifndef QT_BOOTSTRAPPED
1154 case QMetaType::QModelIndex:
1155 return new NS(QModelIndex)(*static_cast<const NS(QModelIndex)*>(copy));
1157 case QMetaType::Void:
1164 case QMetaType::VoidStar:
1165 case QMetaType::QObjectStar:
1166 case QMetaType::QWidgetStar:
1168 case QMetaType::Long:
1170 case QMetaType::Int:
1172 case QMetaType::Short:
1174 case QMetaType::Char:
1176 case QMetaType::ULong:
1178 case QMetaType::UInt:
1180 case QMetaType::LongLong:
1181 return new qlonglong;
1182 case QMetaType::ULongLong:
1183 return new qulonglong;
1184 case QMetaType::UShort:
1186 case QMetaType::UChar:
1188 case QMetaType::Bool:
1190 case QMetaType::Float:
1192 case QMetaType::Double:
1194 case QMetaType::QChar:
1195 return new NS(QChar);
1196 #ifndef QT_BOOTSTRAPPED
1197 case QMetaType::QVariantMap:
1198 return new NS(QVariantMap);
1199 case QMetaType::QVariantHash:
1200 return new NS(QVariantHash);
1201 case QMetaType::QVariantList:
1202 return new NS(QVariantList);
1203 case QMetaType::QVariant:
1204 return new NS(QVariant);
1206 case QMetaType::QByteArray:
1207 return new NS(QByteArray);
1208 case QMetaType::QString:
1209 return new NS(QString);
1210 case QMetaType::QStringList:
1211 return new NS(QStringList);
1212 #ifndef QT_BOOTSTRAPPED
1213 case QMetaType::QBitArray:
1214 return new NS(QBitArray);
1216 case QMetaType::QDate:
1217 return new NS(QDate);
1218 case QMetaType::QTime:
1219 return new NS(QTime);
1220 case QMetaType::QDateTime:
1221 return new NS(QDateTime);
1222 #ifndef QT_BOOTSTRAPPED
1223 case QMetaType::QUrl:
1224 return new NS(QUrl);
1226 case QMetaType::QLocale:
1227 return new NS(QLocale);
1228 #ifndef QT_NO_GEOM_VARIANT
1229 case QMetaType::QRect:
1230 return new NS(QRect);
1231 case QMetaType::QRectF:
1232 return new NS(QRectF);
1233 case QMetaType::QSize:
1234 return new NS(QSize);
1235 case QMetaType::QSizeF:
1236 return new NS(QSizeF);
1237 case QMetaType::QLine:
1238 return new NS(QLine);
1239 case QMetaType::QLineF:
1240 return new NS(QLineF);
1241 case QMetaType::QPoint:
1242 return new NS(QPoint);
1243 case QMetaType::QPointF:
1244 return new NS(QPointF);
1246 #ifndef QT_NO_REGEXP
1247 case QMetaType::QRegExp:
1248 return new NS(QRegExp);
1250 #ifndef QT_BOOTSTRAPPED
1251 case QMetaType::QEasingCurve:
1252 return new NS(QEasingCurve);
1254 case QMetaType::QUuid:
1255 return new NS(QUuid);
1256 #ifndef QT_BOOTSTRAPPED
1257 case QMetaType::QModelIndex:
1258 return new NS(QModelIndex);
1260 case QMetaType::Void:
1267 Creator creator = 0;
1268 if (type >= FirstGuiType && type <= LastGuiType) {
1269 if (!qMetaTypeGuiHelper)
1271 creator = qMetaTypeGuiHelper[type - FirstGuiType].creator;
1272 } else if (type >= FirstWidgetsType && type <= LastWidgetsType) {
1273 if (!qMetaTypeWidgetsHelper)
1275 creator = qMetaTypeWidgetsHelper[type - FirstWidgetsType].creator;
1277 const QVector<QCustomTypeInfo> * const ct = customTypes();
1278 QReadLocker locker(customTypesLock());
1279 if (type < User || !ct || ct->count() <= type - User)
1281 if (ct->at(type - User).typeName.isEmpty())
1283 creator = ct->at(type - User).creator;
1286 return creator(copy);
1290 class TypeDestroyer {
1291 template<typename T, bool IsAcceptedType = DefinedTypesFilter::Acceptor<T>::IsAccepted>
1292 struct DestroyerImpl {
1293 static void Destroy(const int /* type */, void *where) { qMetaTypeDeleteHelper<T>(where); }
1295 template<typename T>
1296 struct DestroyerImpl<T, /* IsAcceptedType = */ false> {
1297 static void Destroy(const int type, void *where)
1299 if (QTypeModuleInfo<T>::IsGui) {
1300 if (Q_LIKELY(qMetaTypeGuiHelper))
1301 qMetaTypeGuiHelper[type - QMetaType::FirstGuiType].deleter(where);
1304 if (QTypeModuleInfo<T>::IsWidget) {
1305 if (Q_LIKELY(qMetaTypeWidgetsHelper))
1306 qMetaTypeWidgetsHelper[type - QMetaType::FirstWidgetsType].deleter(where);
1309 // This point can be reached only for known types that definition is not available, for example
1310 // in bootstrap mode. We have no other choice then ignore it.
1314 TypeDestroyer(const int type)
1318 template<typename T>
1319 void delegate(const T *where) { DestroyerImpl<T>::Destroy(m_type, const_cast<T*>(where)); }
1320 void delegate(const void *) {}
1321 void delegate(const QMetaTypeSwitcher::NotBuiltinType *where) { customTypeDestroyer(m_type, (void*)where); }
1324 static void customTypeDestroyer(const int type, void *where)
1326 QMetaType::Destructor deleter;
1327 const QVector<QCustomTypeInfo> * const ct = customTypes();
1329 QReadLocker locker(customTypesLock());
1330 if (Q_UNLIKELY(type < QMetaType::User || !ct || ct->count() <= type - QMetaType::User))
1332 deleter = ct->at(type - QMetaType::User).deleter;
1343 Destroys the \a data, assuming it is of the \a type given.
1345 \sa create(), isRegistered(), Type
1347 void QMetaType::destroy(int type, void *data)
1349 TypeDestroyer deleter(type);
1350 QMetaTypeSwitcher::switcher<void>(deleter, type, data);
1354 class TypeConstructor {
1355 template<typename T, bool IsAcceptedType = DefinedTypesFilter::Acceptor<T>::IsAccepted>
1356 struct ConstructorImpl {
1357 static void *Construct(const int /*type*/, void *where, const void *copy) { return qMetaTypeConstructHelper<T>(where, copy); }
1359 template<typename T>
1360 struct ConstructorImpl<T, /* IsAcceptedType = */ false> {
1361 static void *Construct(const int type, void *where, const void *copy)
1363 if (QTypeModuleInfo<T>::IsGui)
1364 return Q_LIKELY(qMetaTypeGuiHelper) ? qMetaTypeGuiHelper[type - QMetaType::FirstGuiType].constructor(where, copy) : 0;
1366 if (QTypeModuleInfo<T>::IsWidget)
1367 return Q_LIKELY(qMetaTypeWidgetsHelper) ? qMetaTypeWidgetsHelper[type - QMetaType::FirstWidgetsType].constructor(where, copy) : 0;
1369 // This point can be reached only for known types that definition is not available, for example
1370 // in bootstrap mode. We have no other choice then ignore it.
1375 TypeConstructor(const int type, void *where)
1380 template<typename T>
1381 void *delegate(const T *copy) { return ConstructorImpl<T>::Construct(m_type, m_where, copy); }
1382 void *delegate(const void *) { return m_where; }
1383 void *delegate(const QMetaTypeSwitcher::NotBuiltinType *copy) { return customTypeConstructor(m_type, m_where, copy); }
1386 static void *customTypeConstructor(const int type, void *where, const void *copy)
1388 QMetaType::Constructor ctor;
1389 const QVector<QCustomTypeInfo> * const ct = customTypes();
1391 QReadLocker locker(customTypesLock());
1392 if (Q_UNLIKELY(type < QMetaType::User || !ct || ct->count() <= type - QMetaType::User))
1394 ctor = ct->at(type - QMetaType::User).constructor;
1396 return ctor(where, copy);
1407 Constructs a value of the given \a type in the existing memory
1408 addressed by \a where, that is a copy of \a copy, and returns
1409 \a where. If \a copy is zero, the value is default constructed.
1411 This is a low-level function for explicitly managing the memory
1412 used to store the type. Consider calling create() if you don't
1413 need this level of control (that is, use "new" rather than
1416 You must ensure that \a where points to a location that can store
1417 a value of type \a type, and that \a where is suitably aligned.
1418 The type's size can be queried by calling sizeOf().
1420 The rule of thumb for alignment is that a type is aligned to its
1421 natural boundary, which is the smallest power of 2 that is bigger
1422 than the type, unless that alignment is larger than the maximum
1423 useful alignment for the platform. For practical purposes,
1424 alignment larger than 2 * sizeof(void*) is only necessary for
1425 special hardware instructions (e.g., aligned SSE loads and stores
1428 \sa destruct(), sizeOf()
1430 void *QMetaType::construct(int type, void *where, const void *copy)
1434 TypeConstructor constructor(type, where);
1435 return QMetaTypeSwitcher::switcher<void*>(constructor, type, copy);
1440 class TypeDestructor {
1441 template<typename T, bool IsAcceptedType = DefinedTypesFilter::Acceptor<T>::IsAccepted>
1442 struct DestructorImpl {
1443 static void Destruct(const int /* type */, void *where) { qMetaTypeDestructHelper<T>(where); }
1445 template<typename T>
1446 struct DestructorImpl<T, /* IsAcceptedType = */ false> {
1447 static void Destruct(const int type, void *where)
1449 if (QTypeModuleInfo<T>::IsGui) {
1450 if (Q_LIKELY(qMetaTypeGuiHelper))
1451 qMetaTypeGuiHelper[type - QMetaType::FirstGuiType].destructor(where);
1454 if (QTypeModuleInfo<T>::IsWidget) {
1455 if (Q_LIKELY(qMetaTypeWidgetsHelper))
1456 qMetaTypeWidgetsHelper[type - QMetaType::FirstWidgetsType].destructor(where);
1459 // This point can be reached only for known types that definition is not available, for example
1460 // in bootstrap mode. We have no other choice then ignore it.
1464 TypeDestructor(const int type)
1468 template<typename T>
1469 void delegate(const T *where) { DestructorImpl<T>::Destruct(m_type, const_cast<T*>(where)); }
1470 void delegate(const void *) {}
1471 void delegate(const QMetaTypeSwitcher::NotBuiltinType *where) { customTypeDestructor(m_type, (void*)where); }
1474 static void customTypeDestructor(const int type, void *where)
1476 QMetaType::Destructor dtor;
1477 const QVector<QCustomTypeInfo> * const ct = customTypes();
1479 QReadLocker locker(customTypesLock());
1480 if (Q_UNLIKELY(type < QMetaType::User || !ct || ct->count() <= type - QMetaType::User))
1482 dtor = ct->at(type - QMetaType::User).destructor;
1494 Destructs the value of the given \a type, located at \a where.
1496 Unlike destroy(), this function only invokes the type's
1497 destructor, it doesn't invoke the delete operator.
1501 void QMetaType::destruct(int type, void *where)
1505 TypeDestructor destructor(type);
1506 QMetaTypeSwitcher::switcher<void>(destructor, type, where);
1512 template<typename T, bool IsAcceptedType = DefinedTypesFilter::Acceptor<T>::IsAccepted>
1514 static int Size(const int) { return QTypeInfo<T>::sizeOf; }
1516 template<typename T>
1517 struct SizeOfImpl<T, /* IsAcceptedType = */ false> {
1518 static int Size(const int type)
1520 if (QTypeModuleInfo<T>::IsGui)
1521 return Q_LIKELY(qMetaTypeGuiHelper) ? qMetaTypeGuiHelper[type - QMetaType::FirstGuiType].size : 0;
1523 if (QTypeModuleInfo<T>::IsWidget)
1524 return Q_LIKELY(qMetaTypeWidgetsHelper) ? qMetaTypeWidgetsHelper[type - QMetaType::FirstWidgetsType].size : 0;
1526 // This point can be reached only for known types that definition is not available, for example
1527 // in bootstrap mode. We have no other choice then ignore it.
1537 template<typename T>
1538 int delegate(const T*) { return SizeOfImpl<T>::Size(m_type); }
1539 int delegate(const QMetaTypeSwitcher::NotBuiltinType*) { return customTypeSizeOf(m_type); }
1541 static int customTypeSizeOf(const int type)
1543 const QVector<QCustomTypeInfo> * const ct = customTypes();
1544 QReadLocker locker(customTypesLock());
1545 if (Q_UNLIKELY(type < QMetaType::User || !ct || ct->count() <= type - QMetaType::User))
1547 return ct->at(type - QMetaType::User).size;
1557 Returns the size of the given \a type in bytes (i.e., sizeof(T),
1558 where T is the actual type identified by the \a type argument).
1560 This function is typically used together with construct()
1561 to perform low-level management of the memory used by a type.
1565 int QMetaType::sizeOf(int type)
1567 SizeOf sizeOf(type);
1568 return QMetaTypeSwitcher::switcher<int>(sizeOf, type, 0);
1574 template<typename T, bool IsAcceptedType = DefinedTypesFilter::Acceptor<T>::IsAccepted>
1577 static quint32 Flags(const int type)
1579 return (!QTypeInfo<T>::isStatic * QMetaType::MovableType)
1580 | (QTypeInfo<T>::isComplex * QMetaType::NeedsConstruction)
1581 | (QTypeInfo<T>::isComplex * QMetaType::NeedsDestruction)
1582 | (type == QMetaType::QObjectStar ? QMetaType::PointerToQObject : 0)
1583 | (type == QMetaType::QWidgetStar ? QMetaType::PointerToQObject : 0);
1586 template<typename T>
1587 struct FlagsImpl<T, /* IsAcceptedType = */ false>
1589 static quint32 Flags(const int type)
1591 if (QTypeModuleInfo<T>::IsGui)
1592 return Q_LIKELY(qMetaTypeGuiHelper) ? qMetaTypeGuiHelper[type - QMetaType::FirstGuiType].flags : 0;
1594 if (QTypeModuleInfo<T>::IsWidget)
1595 return Q_LIKELY(qMetaTypeWidgetsHelper) ? qMetaTypeWidgetsHelper[type - QMetaType::FirstWidgetsType].flags : 0;
1597 // This point can be reached only for known types that definition is not available, for example
1598 // in bootstrap mode. We have no other choice then ignore it.
1603 Flags(const int type)
1606 template<typename T>
1607 quint32 delegate(const T*) { return FlagsImpl<T>::Flags(m_type); }
1608 quint32 delegate(const void*) { return 0; }
1609 quint32 delegate(const QMetaTypeSwitcher::NotBuiltinType*) { return customTypeFlags(m_type); }
1612 static quint32 customTypeFlags(const int type)
1614 const QVector<QCustomTypeInfo> * const ct = customTypes();
1615 if (Q_UNLIKELY(!ct))
1617 QReadLocker locker(customTypesLock());
1618 if (Q_UNLIKELY(ct->count() <= type - QMetaType::User))
1620 return ct->at(type - QMetaType::User).flags;
1628 Returns flags of the given \a type.
1632 QMetaType::TypeFlags QMetaType::typeFlags(int type)
1635 return static_cast<QMetaType::TypeFlags>(QMetaTypeSwitcher::switcher<quint32>(flags, type, 0));
1639 \fn int qRegisterMetaType(const char *typeName)
1643 Registers the type name \a typeName for the type \c{T}. Returns
1644 the internal ID used by QMetaType. Any class or struct that has a
1645 public default constructor, a public copy constructor and a public
1646 destructor can be registered.
1648 This function requires that \c{T} is a fully defined type at the point
1649 where the function is called. For pointer types, it also requires that the
1650 pointed to type is fully defined. Use Q_DECLARE_OPAQUE_POINTER() to be able
1651 to register pointers to forward declared types.
1653 After a type has been registered, you can create and destroy
1654 objects of that type dynamically at run-time.
1656 This example registers the class \c{MyClass}:
1658 \snippet doc/src/snippets/code/src_corelib_kernel_qmetatype.cpp 4
1660 This function is useful to register typedefs so they can be used
1661 by QMetaProperty, or in QueuedConnections
1663 \snippet doc/src/snippets/code/src_corelib_kernel_qmetatype.cpp 9
1665 \sa qRegisterMetaTypeStreamOperators(), QMetaType::isRegistered(),
1666 Q_DECLARE_METATYPE()
1670 \fn int qRegisterMetaTypeStreamOperators(const char *typeName)
1674 Registers the stream operators for the type \c{T} called \a
1677 Afterward, the type can be streamed using QMetaType::load() and
1678 QMetaType::save(). These functions are used when streaming a
1681 \snippet doc/src/snippets/code/src_corelib_kernel_qmetatype.cpp 5
1683 The stream operators should have the following signatures:
1685 \snippet doc/src/snippets/code/src_corelib_kernel_qmetatype.cpp 6
1687 \sa qRegisterMetaType(), QMetaType::isRegistered(), Q_DECLARE_METATYPE()
1690 /*! \typedef QMetaType::Deleter
1693 /*! \typedef QMetaType::Creator
1696 /*! \typedef QMetaType::SaveOperator
1699 /*! \typedef QMetaType::LoadOperator
1702 /*! \typedef QMetaType::Destructor
1705 /*! \typedef QMetaType::Constructor
1710 \fn int qRegisterMetaType()
1715 Call this function to register the type \c T. \c T must be declared with
1716 Q_DECLARE_METATYPE(). Returns the meta type Id.
1720 \snippet doc/src/snippets/code/src_corelib_kernel_qmetatype.cpp 7
1722 To use the type \c T in QVariant, using Q_DECLARE_METATYPE() is
1723 sufficient. To use the type \c T in queued signal and slot connections,
1724 \c{qRegisterMetaType<T>()} must be called before the first connection
1727 Also, to use type \c T with the QObject::property() API,
1728 \c{qRegisterMetaType<T>()} must be called before it is used, typically
1729 in the constructor of the class that uses \c T, or in the \c{main()}
1732 \sa Q_DECLARE_METATYPE()
1735 /*! \fn int qMetaTypeId()
1740 Returns the meta type id of type \c T at compile time. If the
1741 type was not declared with Q_DECLARE_METATYPE(), compilation will
1746 \snippet doc/src/snippets/code/src_corelib_kernel_qmetatype.cpp 8
1748 QMetaType::type() returns the same ID as qMetaTypeId(), but does
1749 a lookup at runtime based on the name of the type.
1750 QMetaType::type() is a bit slower, but compilation succeeds if a
1751 type is not registered.
1753 \sa Q_DECLARE_METATYPE(), QMetaType::type()
1758 template<typename T, bool IsAcceptedType = DefinedTypesFilter::Acceptor<T>::IsAccepted>
1761 TypeInfoImpl(const uint /* type */, QMetaTypeInterface &info)
1763 QMetaTypeInterface tmp = QT_METATYPE_INTERFACE_INIT_NO_DATASTREAM(T);
1768 template<typename T>
1769 struct TypeInfoImpl<T, /* IsAcceptedType = */ false>
1771 TypeInfoImpl(const uint type, QMetaTypeInterface &info)
1773 if (QTypeModuleInfo<T>::IsGui) {
1774 if (Q_LIKELY(qMetaTypeGuiHelper))
1775 info = qMetaTypeGuiHelper[type - QMetaType::FirstGuiType];
1778 if (QTypeModuleInfo<T>::IsWidget) {
1779 if (Q_LIKELY(qMetaTypeWidgetsHelper))
1780 info = qMetaTypeWidgetsHelper[type - QMetaType::FirstWidgetsType];
1786 QMetaTypeInterface info;
1787 TypeInfo(const uint type)
1790 QMetaTypeInterface tmp = QT_METATYPE_INTERFACE_INIT_EMPTY();
1793 template<typename T>
1794 void delegate(const T*) { TypeInfoImpl<T>(m_type, info); }
1795 void delegate(const void*) {}
1796 void delegate(const QMetaTypeSwitcher::NotBuiltinType*) { customTypeInfo(m_type); }
1798 void customTypeInfo(const uint type)
1800 const QVector<QCustomTypeInfo> * const ct = customTypes();
1801 if (Q_UNLIKELY(!ct))
1803 QReadLocker locker(customTypesLock());
1804 if (Q_LIKELY(uint(ct->count()) > type - QMetaType::User))
1805 info = ct->at(type - QMetaType::User);
1812 QMetaType QMetaType::typeInfo(const int type)
1814 TypeInfo typeInfo(type);
1815 QMetaTypeSwitcher::switcher<void>(typeInfo, type, 0);
1816 return typeInfo.info.creator || !type ? QMetaType(QMetaType::NoExtensionFlags
1817 , static_cast<const QMetaTypeInterface *>(0) // typeInfo::info is a temporary variable, we can't return address of it.
1818 , typeInfo.info.creator
1819 , typeInfo.info.deleter
1820 , typeInfo.info.saveOp
1821 , typeInfo.info.loadOp
1822 , typeInfo.info.constructor
1823 , typeInfo.info.destructor
1824 , typeInfo.info.size
1825 , typeInfo.info.flags
1830 QMetaType::QMetaType(const int typeId)
1833 if (Q_UNLIKELY(typeId == -1)) {
1834 // Constructs invalid QMetaType instance.
1835 m_extensionFlags = 0xffffffff;
1836 Q_ASSERT(!isValid());
1838 // TODO it can be better.
1839 *this = QMetaType::typeInfo(typeId);
1840 if (m_typeId > 0 && !m_creator) {
1841 m_extensionFlags = 0xffffffff;
1844 if (m_typeId == QMetaType::Void) {
1845 m_extensionFlags = CreateEx | DestroyEx | ConstructEx | DestructEx;
1850 QMetaType::QMetaType(const QMetaType &other)
1851 : m_creator(other.m_creator)
1852 , m_deleter(other.m_deleter)
1853 , m_saveOp(other.m_saveOp)
1854 , m_loadOp(other.m_loadOp)
1855 , m_constructor(other.m_constructor)
1856 , m_destructor(other.m_destructor)
1857 , m_extension(other.m_extension) // space reserved for future use
1858 , m_size(other.m_size)
1859 , m_typeFlags(other.m_typeFlags)
1860 , m_extensionFlags(other.m_extensionFlags)
1861 , m_typeId(other.m_typeId)
1864 QMetaType &QMetaType::operator =(const QMetaType &other)
1866 m_creator = other.m_creator;
1867 m_deleter = other.m_deleter;
1868 m_saveOp = other.m_saveOp;
1869 m_loadOp = other.m_loadOp;
1870 m_constructor = other.m_constructor;
1871 m_destructor = other.m_destructor;
1872 m_size = other.m_size;
1873 m_typeFlags = other.m_typeFlags;
1874 m_extensionFlags = other.m_extensionFlags;
1875 m_extension = other.m_extension; // space reserved for future use
1876 m_typeId = other.m_typeId;
1880 void QMetaType::ctor(const QMetaTypeInterface *info)
1882 // Special case for Void type, the type is valid but not constructible.
1883 // In future we may consider to remove this assert and extend this function to initialize
1884 // differently m_extensionFlags for different types. Currently it is not needed.
1885 Q_ASSERT(m_typeId == QMetaType::Void);
1887 m_extensionFlags = CreateEx | DestroyEx | ConstructEx | DestructEx;
1890 void QMetaType::dtor()
1893 void *QMetaType::createExtended(const void *copy) const
1899 void QMetaType::destroyExtended(void *data) const
1904 void *QMetaType::constructExtended(void *where, const void *copy) const
1911 void QMetaType::destructExtended(void *data) const
1916 uint QMetaType::sizeExtended() const
1921 QMetaType::TypeFlags QMetaType::flagsExtended() const