Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qmetatype.cpp
Go to the documentation of this file.
1// Copyright (C) 2021 The Qt Company Ltd.
2// Copyright (C) 2021 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
3// Copyright (C) 2021 Intel Corporation.
4// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
5
6#include "qmetatype.h"
7#include "qmetatype_p.h"
8#include "qobject.h"
9#include "qobjectdefs.h"
10#include "qdatetime.h"
11#include "qbytearray.h"
12#include "qreadwritelock.h"
13#include "qhash.h"
14#include "qmap.h"
15#include "qstring.h"
16#include "qstringlist.h"
17#include "qlist.h"
18#include "qlocale.h"
19#include "qdebug.h"
20#if QT_CONFIG(easingcurve)
21#include "qeasingcurve.h"
22#endif
23#include "quuid.h"
24#include "qvariant.h"
25#include "qdatastream.h"
26
27#if QT_CONFIG(regularexpression)
28# include "qregularexpression.h"
29#endif
30
31#ifndef QT_BOOTSTRAPPED
32# include "qbitarray.h"
33# include "qurl.h"
34# include "qvariant.h"
35# include "qjsonvalue.h"
36# include "qjsonobject.h"
37# include "qjsonarray.h"
38# include "qjsondocument.h"
39# include "qcborvalue.h"
40# include "qcborarray.h"
41# include "qcbormap.h"
42# include "qbytearraylist.h"
43# include "qmetaobject.h"
44# include "qsequentialiterable.h"
45# include "qassociativeiterable.h"
46#endif
47
48#if QT_CONFIG(itemmodel)
49# include "qabstractitemmodel.h"
50#endif
51
52#ifndef QT_NO_GEOM_VARIANT
53# include "qsize.h"
54# include "qpoint.h"
55# include "qrect.h"
56# include "qline.h"
57#endif
58
59#include <bitset>
60#include <new>
61#include <cstring>
62
64
65#define NS(x) QT_PREPEND_NAMESPACE(x)
66
68
70
71namespace {
72struct QMetaTypeDeleter
73{
75 void operator()(void *data)
76 {
77 if (iface->alignment > __STDCPP_DEFAULT_NEW_ALIGNMENT__) {
78 operator delete(data, std::align_val_t(iface->alignment));
79 } else {
80 operator delete(data);
81 }
82 }
83};
84
85struct QMetaTypeCustomRegistry
86{
87
88#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
89 QMetaTypeCustomRegistry()
90 {
91 /* qfloat16 was neither a builtin, nor unconditionally registered
92 in QtCore in Qt <= 6.2.
93 Inserting it as an alias ensures that a QMetaType::id call
94 will get the correct built-in type-id (the interface pointers
95 might still not match, but we already deal with that case.
96 */
97 aliases.insert("qfloat16", QtPrivate::qMetaTypeInterfaceForType<qfloat16>());
98 }
99#endif
100
104 // index of first empty (unregistered) type in registry, if any.
105 int firstEmpty = 0;
106
107 int registerCustomType(const QtPrivate::QMetaTypeInterface *cti)
108 {
109 // we got here because cti->typeId is 0, so this is a custom meta type
110 // (not read-only)
111 auto ti = const_cast<QtPrivate::QMetaTypeInterface *>(cti);
112 {
113 QWriteLocker l(&lock);
114 if (int id = ti->typeId.loadRelaxed())
115 return id;
117#ifndef QT_NO_QOBJECT
119#endif
120 (ti->name);
121 if (auto ti2 = aliases.value(name)) {
122 const auto id = ti2->typeId.loadRelaxed();
123 ti->typeId.storeRelaxed(id);
124 return id;
125 }
126 aliases[name] = ti;
127 int size = registry.size();
128 while (firstEmpty < size && registry[firstEmpty])
129 ++firstEmpty;
130 if (firstEmpty < size) {
131 registry[firstEmpty] = ti;
132 ++firstEmpty;
133 } else {
134 registry.append(ti);
135 firstEmpty = registry.size();
136 }
137 ti->typeId.storeRelaxed(firstEmpty + QMetaType::User);
138 }
139 if (ti->legacyRegisterOp)
140 ti->legacyRegisterOp();
141 return ti->typeId.loadRelaxed();
142 };
143
144 void unregisterDynamicType(int id)
145 {
146 if (!id)
147 return;
149 QWriteLocker l(&lock);
150 int idx = id - QMetaType::User - 1;
151 auto &ti = registry[idx];
152
153 // We must unregister all names.
154 auto it = aliases.begin();
155 while (it != aliases.end()) {
156 if (it.value() == ti)
157 it = aliases.erase(it);
158 else
159 ++it;
160 }
161
162 ti = nullptr;
163
164 firstEmpty = std::min(firstEmpty, idx);
165 }
166
167 const QtPrivate::QMetaTypeInterface *getCustomType(int id)
168 {
169 QReadLocker l(&lock);
170 return registry.value(id - QMetaType::User - 1);
171 }
172};
173
174Q_GLOBAL_STATIC(QMetaTypeCustomRegistry, customTypeRegistry)
175
176} // namespace
177
178// used by QVariant::save(): returns the name used in the Q_DECLARE_METATYPE
179// macro (one of them, indetermine which one)
181{
182 const char *name = nullptr;
183 if (!customTypeRegistry.exists())
184 return name;
185 QMetaTypeCustomRegistry *r = &*customTypeRegistry;
186
187 QByteArrayView officialName(type_d->name);
188 QReadLocker l(&r->lock);
189 auto it = r->aliases.constBegin();
190 auto end = r->aliases.constEnd();
191 for ( ; it != end; ++it) {
192 if (it.value() != type_d)
193 continue;
194 if (it.key() == officialName)
195 continue; // skip the official name
196 name = it.key().constData();
197 ++it;
198 break;
199 }
200
201#ifndef QT_NO_DEBUG
202 QByteArrayList otherNames;
203 for ( ; it != end; ++it) {
204 if (it.value() == type_d && it.key() != officialName)
205 otherNames << it.key();
206 }
207 l.unlock();
208 if (!otherNames.isEmpty())
209 qWarning("QMetaType: type %s has more than one typedef alias: %s, %s",
210 type_d->name, name, otherNames.join(", ").constData());
211#endif
212
213 return name;
214}
215
522{
523 return d_ptr;
524}
525
537{
538 return d_ptr && d_ptr->typeId.loadRelaxed();
539}
540
561int QMetaType::registerHelper(const QtPrivate::QMetaTypeInterface *iface)
562{
564 auto reg = customTypeRegistry();
565 if (reg) {
566 return reg->registerCustomType(iface);
567 }
568 return 0;
569}
570
646void *QMetaType::create(const void *copy) const
647{
649 return nullptr;
650
651 std::unique_ptr<void, QMetaTypeDeleter> where(nullptr, {d_ptr});
652 if (d_ptr->alignment > __STDCPP_DEFAULT_NEW_ALIGNMENT__)
653 where.reset(operator new(d_ptr->size, std::align_val_t(d_ptr->alignment)));
654 else
655 where.reset(operator new(d_ptr->size));
656
657 QtMetaTypePrivate::construct(d_ptr, where.get(), copy);
658 return where.release();
659}
660
670void QMetaType::destroy(void *data) const
671{
672 if (data && isDestructible()) {
674 QMetaTypeDeleter{d_ptr}(data);
675 }
676}
677
704void *QMetaType::construct(void *where, const void *copy) const
705{
706 if (!where)
707 return nullptr;
709 return nullptr;
710
711 QtMetaTypePrivate::construct(d_ptr, where, copy);
712 return where;
713}
714
726void QMetaType::destruct(void *data) const
727{
728 if (data && isDestructible())
730}
731
732static QPartialOrdering threeWayCompare(const void *ptr1, const void *ptr2)
733{
734 std::less<const void *> less;
735 if (less(ptr1, ptr2))
737 if (less(ptr2, ptr1))
740}
741
768QPartialOrdering QMetaType::compare(const void *lhs, const void *rhs) const
769{
770 if (!lhs || !rhs)
772 if (d_ptr && d_ptr->flags & QMetaType::IsPointer)
773 return threeWayCompare(*reinterpret_cast<const void * const *>(lhs),
774 *reinterpret_cast<const void * const *>(rhs));
775 if (d_ptr && d_ptr->lessThan) {
776 if (d_ptr->equals && d_ptr->equals(d_ptr, lhs, rhs))
778 if (d_ptr->lessThan(d_ptr, lhs, rhs))
780 if (d_ptr->lessThan(d_ptr, rhs, lhs))
782 if (!d_ptr->equals)
784 }
786}
787
804bool QMetaType::equals(const void *lhs, const void *rhs) const
805{
806 if (!lhs || !rhs)
807 return false;
808 if (d_ptr) {
809 if (d_ptr->flags & QMetaType::IsPointer)
810 return *reinterpret_cast<const void * const *>(lhs) == *reinterpret_cast<const void * const *>(rhs);
811
812 if (d_ptr->equals)
813 return d_ptr->equals(d_ptr, lhs, rhs);
814 if (d_ptr->lessThan && !d_ptr->lessThan(d_ptr, lhs, rhs) && !d_ptr->lessThan(d_ptr, rhs, lhs))
815 return true;
816 }
817 return false;
818}
819
863{
864 return !isInterfaceFor<void>(iface) && QtMetaTypePrivate::isDefaultConstructible(iface);
865}
866
868{
869 return !isInterfaceFor<void>(iface) && QtMetaTypePrivate::isCopyConstructible(iface);
870}
871
873{
874 return !isInterfaceFor<void>(iface) && QtMetaTypePrivate::isMoveConstructible(iface);
875}
876
878{
879 return !isInterfaceFor<void>(iface) && QtMetaTypePrivate::isDestructible(iface);
880}
881
889{
890 return d_ptr && (d_ptr->flags & QMetaType::IsPointer || d_ptr->equals != nullptr || d_ptr->lessThan != nullptr);
891}
892
900{
901 return d_ptr && (d_ptr->flags & QMetaType::IsPointer || d_ptr->lessThan != nullptr);
902}
903
904
909{
910 if (type.d_ptr && type.d_ptr->typeId.loadRelaxed() >= QMetaType::User) {
911 // this is a custom meta type (not read-only)
912 auto d = const_cast<QtPrivate::QMetaTypeInterface *>(type.d_ptr);
913 if (auto reg = customTypeRegistry())
914 reg->unregisterDynamicType(d->typeId.loadRelaxed());
915 d->typeId.storeRelease(0);
916 }
917}
918
942#define QT_ADD_STATIC_METATYPE(MetaTypeName, MetaTypeId, RealName) \
943 { #RealName, sizeof(#RealName) - 1, MetaTypeId },
944
945#define QT_ADD_STATIC_METATYPE_ALIASES_ITER(MetaTypeName, MetaTypeId, AliasingName, RealNameStr) \
946 { RealNameStr, sizeof(RealNameStr) - 1, QMetaType::MetaTypeName },
947
948
949
950static const struct { const char * typeName; int typeNameLength; int type; } types[] = {
954 {nullptr, 0, QMetaType::UnknownType}
956
957static const struct : QMetaTypeModuleHelper
958{
959 template<typename T, typename LiteralWrapper =
960 std::conditional_t<std::is_same_v<T, QString>, QLatin1StringView, const char *>>
961 static inline bool convertToBool(const T &source)
962 {
963 T str = source.toLower();
964 return !(str.isEmpty() || str == LiteralWrapper("0") || str == LiteralWrapper("false"));
965 }
966
967 const QtPrivate::QMetaTypeInterface *interfaceForType(int type) const override {
968 switch (type) {
974 default:
975 return nullptr;
976 }
977 }
978
979 bool convert(const void *from, int fromTypeId, void *to, int toTypeId) const override
980 {
981 Q_ASSERT(fromTypeId != toTypeId);
982
983 // canConvert calls with two nullptr
984 bool onlyCheck = (from == nullptr && to == nullptr);
985
986 // other callers must provide two valid pointers
987 Q_ASSERT(onlyCheck || (bool(from) && bool(to)));
988
989 using Char = char;
990 using SChar = signed char;
991 using UChar = unsigned char;
992 using Short = short;
993 using UShort = unsigned short;
994 using Int = int;
995 using UInt = unsigned int;
996 using Long = long;
997 using LongLong = qlonglong;
998 using ULong = unsigned long;
999 using ULongLong = qulonglong;
1000 using Float = float;
1001 using Double = double;
1002 using Bool = bool;
1003 using Nullptr = std::nullptr_t;
1004
1005#define QMETATYPE_CONVERTER_ASSIGN_DOUBLE(To, From) \
1006 QMETATYPE_CONVERTER(To, From, result = double(source); return true;)
1007#define QMETATYPE_CONVERTER_ASSIGN_NUMBER(To, From) \
1008 QMETATYPE_CONVERTER(To, From, result = To::number(source); return true;)
1009#ifndef QT_BOOTSTRAPPED
1010#define CONVERT_CBOR_AND_JSON(To) \
1011 QMETATYPE_CONVERTER(To, QCborValue, \
1012 if constexpr(std::is_same_v<To, Bool>) { \
1013 if (!source.isBool()) \
1014 return false; \
1015 result = source.toBool(); \
1016 } else { \
1017 if (!source.isInteger() && !source.isDouble()) \
1018 return false; \
1019 if constexpr(std::is_integral_v<To>) \
1020 result = source.toInteger(); \
1021 else \
1022 result = source.toDouble(); \
1023 } \
1024 return true; \
1025 ); \
1026 QMETATYPE_CONVERTER(To, QJsonValue, \
1027 if constexpr(std::is_same_v<To, Bool>) { \
1028 if (!source.isBool()) \
1029 return false; \
1030 result = source.toBool(); \
1031 } else { \
1032 if (!source.isDouble()) \
1033 return false; \
1034 if constexpr(std::is_integral_v<To>) \
1035 result = source.toInteger(); \
1036 else \
1037 result = source.toDouble(); \
1038 } \
1039 return true; \
1040 )
1041#else
1042#define CONVERT_CBOR_AND_JSON(To)
1043#endif
1044
1045#define INTEGRAL_CONVERTER(To) \
1046 QMETATYPE_CONVERTER_ASSIGN(To, Bool); \
1047 QMETATYPE_CONVERTER_ASSIGN(To, Char); \
1048 QMETATYPE_CONVERTER_ASSIGN(To, UChar); \
1049 QMETATYPE_CONVERTER_ASSIGN(To, SChar); \
1050 QMETATYPE_CONVERTER_ASSIGN(To, Short); \
1051 QMETATYPE_CONVERTER_ASSIGN(To, UShort); \
1052 QMETATYPE_CONVERTER_ASSIGN(To, Int); \
1053 QMETATYPE_CONVERTER_ASSIGN(To, UInt); \
1054 QMETATYPE_CONVERTER_ASSIGN(To, Long); \
1055 QMETATYPE_CONVERTER_ASSIGN(To, ULong); \
1056 QMETATYPE_CONVERTER_ASSIGN(To, LongLong); \
1057 QMETATYPE_CONVERTER_ASSIGN(To, ULongLong); \
1058 QMETATYPE_CONVERTER(To, Float, result = qRound64(source); return true;); \
1059 QMETATYPE_CONVERTER(To, Double, result = qRound64(source); return true;); \
1060 QMETATYPE_CONVERTER(To, QChar, result = source.unicode(); return true;); \
1061 QMETATYPE_CONVERTER(To, QString, \
1062 bool ok = false; \
1063 if constexpr(std::is_same_v<To, bool>) \
1064 result = (ok = true, convertToBool(source)); \
1065 else if constexpr(std::is_signed_v<To>) \
1066 result = To(source.toLongLong(&ok)); \
1067 else \
1068 result = To(source.toULongLong(&ok)); \
1069 return ok; \
1070 ); \
1071 QMETATYPE_CONVERTER(To, QByteArray, \
1072 bool ok = false; \
1073 if constexpr(std::is_same_v<To, bool>) \
1074 result = (ok = true, convertToBool(source)); \
1075 else if constexpr(std::is_signed_v<To>) \
1076 result = To(source.toLongLong(&ok)); \
1077 else \
1078 result = To(source.toULongLong(&ok)); \
1079 return ok; \
1080 ); \
1081 CONVERT_CBOR_AND_JSON(To)
1082
1083#define FLOAT_CONVERTER(To) \
1084 QMETATYPE_CONVERTER_ASSIGN(To, Bool); \
1085 QMETATYPE_CONVERTER_ASSIGN(To, Char); \
1086 QMETATYPE_CONVERTER_ASSIGN(To, UChar); \
1087 QMETATYPE_CONVERTER_ASSIGN(To, SChar); \
1088 QMETATYPE_CONVERTER_ASSIGN(To, Short); \
1089 QMETATYPE_CONVERTER_ASSIGN(To, UShort); \
1090 QMETATYPE_CONVERTER_ASSIGN(To, Int); \
1091 QMETATYPE_CONVERTER_ASSIGN(To, UInt); \
1092 QMETATYPE_CONVERTER_ASSIGN(To, Long); \
1093 QMETATYPE_CONVERTER_ASSIGN(To, ULong); \
1094 QMETATYPE_CONVERTER_ASSIGN(To, LongLong); \
1095 QMETATYPE_CONVERTER_ASSIGN(To, ULongLong); \
1096 QMETATYPE_CONVERTER_ASSIGN(To, Float); \
1097 QMETATYPE_CONVERTER_ASSIGN(To, Double); \
1098 QMETATYPE_CONVERTER(To, QString, \
1099 bool ok = false; \
1100 result = source.toDouble(&ok); \
1101 return ok; \
1102 ); \
1103 QMETATYPE_CONVERTER(To, QByteArray, \
1104 bool ok = false; \
1105 result = source.toDouble(&ok); \
1106 return ok; \
1107 ); \
1108 CONVERT_CBOR_AND_JSON(To)
1109
1110 switch (makePair(toTypeId, fromTypeId)) {
1111
1112 // integral conversions
1113 INTEGRAL_CONVERTER(Bool);
1115 INTEGRAL_CONVERTER(UChar);
1116 INTEGRAL_CONVERTER(SChar);
1117 INTEGRAL_CONVERTER(Short);
1118 INTEGRAL_CONVERTER(UShort);
1120 INTEGRAL_CONVERTER(UInt);
1122 INTEGRAL_CONVERTER(ULong);
1123 INTEGRAL_CONVERTER(LongLong);
1124 INTEGRAL_CONVERTER(ULongLong);
1127
1128#ifndef QT_BOOTSTRAPPED
1131 if (source.isUrl()) {
1132 result = source.toUrl();
1133 return true;
1134 }
1135 return false;
1136 );
1137#endif
1138#if QT_CONFIG(itemmodel)
1141#endif // QT_CONFIG(itemmodel)
1142
1143 // QChar methods
1144#define QMETATYPE_CONVERTER_ASSIGN_QCHAR(From) \
1145 QMETATYPE_CONVERTER(QChar, From, result = QChar::fromUcs2(source); return true;)
1158
1159 // conversions to QString
1162 result = source ? QStringLiteral("true") : QStringLiteral("false");
1163 return true;
1164 );
1175 return true;
1176 );
1179 return true;
1180 );
1183 return true;
1184 );
1186 char s = source;
1188 return true;
1189 );
1191 char s = source;
1193 return true;
1194 );
1195#if QT_CONFIG(datestring)
1196 QMETATYPE_CONVERTER(QString, QDate, result = source.toString(Qt::ISODate); return true;);
1197 QMETATYPE_CONVERTER(QString, QTime, result = source.toString(Qt::ISODateWithMs); return true;);
1199#endif
1202 return (source.size() == 1) ? (result = source.at(0), true) : false;
1203 );
1204#ifndef QT_BOOTSTRAPPED
1207 if (source.isString() || source.isNull()) {
1208 result = source.toString();
1209 return true;
1210 }
1211 return false;
1212 );
1213#endif
1214 QMETATYPE_CONVERTER(QString, Nullptr, Q_UNUSED(source); result = QString(); return true;);
1215
1216 // QByteArray
1219 result = source ? "true" : "false";
1220 return true;
1221 );
1223 QMETATYPE_CONVERTER(QByteArray, SChar, result = QByteArray(source, 1); return true;);
1224 QMETATYPE_CONVERTER(QByteArray, UChar, result = QByteArray(source, 1); return true;);
1235 return true;
1236 );
1239 return true;
1240 );
1241 QMETATYPE_CONVERTER(QByteArray, Nullptr, Q_UNUSED(source); result = QByteArray(); return true;);
1242
1244 QMETATYPE_CONVERTER(QUuid, QString, result = QUuid(source); return true;);
1247
1248#ifndef QT_NO_GEOM_VARIANT
1249 QMETATYPE_CONVERTER(QSize, QSizeF, result = source.toSize(); return true;);
1251 QMETATYPE_CONVERTER(QLine, QLineF, result = source.toLine(); return true;);
1253 QMETATYPE_CONVERTER(QRect, QRectF, result = source.toRect(); return true;);
1257 #endif
1258
1260 result.reserve(source.size());
1261 for (const auto &v: source)
1263 return true;
1264 );
1266 result.reserve(source.size());
1267 for (const auto &v: source)
1269 return true;
1270 );
1271
1273 result.reserve(source.size());
1274 for (const auto &v: source)
1276 return true;
1277 );
1279 result.reserve(source.size());
1280 for (const auto &v: source)
1282 return true;
1283 );
1285
1287 for (auto it = source.begin(); it != source.end(); ++it)
1288 result.insert(it.key(), it.value());
1289 return true;
1290 );
1292 for (auto it = source.begin(); it != source.end(); ++it)
1293 result.insert(it.key(), it.value());
1294 return true;
1295 );
1296
1297#ifndef QT_BOOTSTRAPPED
1300 if (source.isContainer() || source.isTag())
1301 return false;
1302 result = source.toVariant().toString();
1303 return true;
1304 );
1307 if (source.isByteArray()) {
1308 result = source.toByteArray();
1309 return true;
1310 }
1311 return false;
1312 );
1315 if (!source.isUuid())
1316 return false;
1317 result = source.toUuid();
1318 return true;
1319 );
1322 if (!source.isArray())
1323 return false;
1324 result = source.toArray().toVariantList();
1325 return true;
1326 );
1329 if (!source.isMap())
1330 return false;
1331 result = source.toMap().toVariantMap();
1332 return true;
1333 );
1336 if (!source.isMap())
1337 return false;
1338 result = source.toMap().toVariantHash();
1339 return true;
1340 );
1341#if QT_CONFIG(regularexpression)
1344 if (!source.isRegularExpression())
1345 return false;
1346 result = source.toRegularExpression();
1347 return true;
1348 );
1349#endif
1350
1354 return true;
1355 );
1357 result = nullptr;
1358 return source.isNull();
1359 );
1363 QMETATYPE_CONVERTER(QCborValue, ULong, result = qlonglong(source); return true;);
1366 QMETATYPE_CONVERTER(QCborValue, ULongLong, result = qlonglong(source); return true;);
1376 return true;
1377 );
1379 result = QCborValue(source.startOfDay());
1380 return true;
1381 );
1385 return true;
1386 );
1389 return true;
1390 );
1393 return true;
1394 );
1396 QJsonDocument doc = source;
1397 if (doc.isArray())
1398 result = QCborArray::fromJsonArray(doc.array());
1399 else
1400 result = QCborMap::fromJsonObject(doc.object());
1401 return true;
1402 );
1405
1408 if (source.isDateTime()) {
1409 result = source.toDateTime();
1410 return true;
1411 }
1412 return false;
1413 );
1414
1417 if (source.isSimpleType()) {
1418 result = source.toSimpleType();
1419 return true;
1420 }
1421 return false;
1422 );
1423
1431
1433 if (!source.isArray())
1434 return false;
1435 result = source.toArray();
1436 return true;
1437 );
1439 if (!source.isArray())
1440 return false;
1442 return true;
1443 );
1445 if (!source.isArray())
1446 return false;
1448 return true;
1449 );
1452 return true;
1453 );
1455 if (!source.isMap())
1456 return false;
1457 result = source.toMap();
1458 return true;
1459 );
1461 if (source.isArray())
1462 return false;
1464 return true;
1465 );
1467 if (!source.isObject())
1468 return false;
1470 return true;
1471 );
1474 return true;
1475 );
1476
1477
1479 if (!source.isArray())
1480 return false;
1481 result = source.toArray().toVariantList();
1482 return true;
1483 );
1486 if (!source.isObject())
1487 return false;
1488 result = source.toObject().toVariantMap();
1489 return true;
1490 );
1493 if (!source.isObject())
1494 return false;
1495 result = source.toObject().toVariantHash();
1496 return true;
1497 );
1499
1500
1504 if (!source.isArray())
1505 return false;
1506 result = source.toArray();
1507 return true;
1508 );
1510 if (!source.isArray())
1511 return false;
1512 result = source.array();
1513 return true;
1514 );
1516 if (!source.isArray())
1517 return false;
1518 result = source.toArray().toJsonArray();
1519 return true;
1520 );
1525 if (!source.isObject())
1526 return false;
1527 result = source.toObject();
1528 return true;
1529 );
1531 if (source.isArray())
1532 return false;
1533 result = source.object();
1534 return true;
1535 );
1537 if (!source.isMap())
1538 return false;
1539 result = source.toMap().toJsonObject();
1540 return true;
1541 );
1543
1547 return true;
1548 );
1550 result = nullptr;
1551 return source.isNull();
1552 );
1555 return true;);
1572 return true;
1573 );
1576 return true;
1577 );
1580 return true;
1581 );
1584 return true;
1585 );
1587 result = source;
1588 return true;
1589 );
1591 result = source;
1592 return true;
1593 );
1595 QJsonDocument doc = source;
1596 result = doc.isArray() ? QJsonValue(doc.array()) : QJsonValue(doc.object());
1597 return true;
1598 );
1601 return true;
1602 );
1605 return true;
1606 );
1609 return true;
1610 );
1611
1612#endif
1613
1614 QMETATYPE_CONVERTER(QDate, QDateTime, result = source.date(); return true;);
1615 QMETATYPE_CONVERTER(QTime, QDateTime, result = source.time(); return true;);
1617#if QT_CONFIG(datestring)
1619 result = QDate::fromString(source, Qt::ISODate);
1620 return result.isValid();
1621 );
1623 result = QTime::fromString(source, Qt::ISODate);
1624 return result.isValid();
1625 );
1627 result = QDateTime::fromString(source, Qt::ISODate);
1628 return result.isValid();
1629 );
1630#endif
1631
1632 }
1633 return false;
1634 }
1636
1637Q_CONSTINIT Q_CORE_EXPORT const QMetaTypeModuleHelper *qMetaTypeGuiHelper = nullptr;
1638Q_CONSTINIT Q_CORE_EXPORT const QMetaTypeModuleHelper *qMetaTypeWidgetsHelper = nullptr;
1639
1641{
1643 return &metatypeHelper;
1645 return qMetaTypeGuiHelper;
1648 return nullptr;
1649}
1650
1651template<typename T, typename Key>
1653{
1654public:
1656 {
1657 const QWriteLocker locker(&lock);
1658 map.clear();
1659 }
1660
1661 bool contains(Key k) const
1662 {
1663 const QReadLocker locker(&lock);
1664 return map.contains(k);
1665 }
1666
1667 bool insertIfNotContains(Key k, const T &f)
1668 {
1669 const QWriteLocker locker(&lock);
1670 const qsizetype oldSize = map.size();
1671 auto &e = map[k];
1672 if (map.size() == oldSize) // already present
1673 return false;
1674 e = f;
1675 return true;
1676 }
1677
1678 const T *function(Key k) const
1679 {
1680 const QReadLocker locker(&lock);
1681 auto it = map.find(k);
1682 return it == map.end() ? nullptr : std::addressof(*it);
1683 }
1684
1685 void remove(int from, int to)
1686 {
1687 const Key k(from, to);
1688 const QWriteLocker locker(&lock);
1689 map.remove(k);
1690 }
1691private:
1692 mutable QReadWriteLock lock;
1693 QHash<Key, T> map;
1694};
1695
1698
1699Q_GLOBAL_STATIC(QMetaTypeConverterRegistry, customTypesConversionRegistry)
1700
1702 = QMetaTypeFunctionRegistry<QMetaType::MutableViewFunction, QPair<int,int>>;
1703Q_GLOBAL_STATIC(QMetaTypeMutableViewRegistry, customTypesMutableViewRegistry)
1704
1756bool QMetaType::registerConverterFunction(const ConverterFunction &f, QMetaType from, QMetaType to)
1757{
1758 if (!customTypesConversionRegistry()->insertIfNotContains(qMakePair(from.id(), to.id()), f)) {
1759 qWarning("Type conversion already registered from type %s to type %s",
1760 from.name(), to.name());
1761 return false;
1762 }
1763 return true;
1764}
1765
1790{
1791 if (!customTypesMutableViewRegistry()->insertIfNotContains(qMakePair(from.id(), to.id()), f)) {
1792 qWarning("Mutable view on type already registered from type %s to type %s",
1793 from.name(), to.name());
1794 return false;
1795 }
1796 return true;
1797}
1798
1803{
1804 if (customTypesMutableViewRegistry.isDestroyed())
1805 return;
1806 customTypesMutableViewRegistry()->remove(from.id(), to.id());
1807}
1808
1815{
1816 if (customTypesConversionRegistry.isDestroyed())
1817 return;
1818 customTypesConversionRegistry()->remove(from.id(), to.id());
1819}
1820
1821#ifndef QT_NO_DEBUG_STREAM
1822
1829{
1830 const QDebugStateSaver saver(d);
1831 return d.nospace() << "QMetaType(" << m.name() << ")";
1832}
1833
1839bool QMetaType::debugStream(QDebug& dbg, const void *rhs)
1840{
1841 if (d_ptr && d_ptr->flags & QMetaType::IsPointer) {
1842 dbg << *reinterpret_cast<const void * const *>(rhs);
1843 return true;
1844 }
1845 if (d_ptr && d_ptr->debugStream) {
1846 d_ptr->debugStream(d_ptr, dbg, rhs);
1847 return true;
1848 }
1849 return false;
1850}
1851
1882{
1883 return d_ptr && d_ptr->debugStream != nullptr;
1884}
1885#endif
1886
1887#ifndef QT_NO_QOBJECT
1893{
1894 if (t.flags() & QMetaType::IsEnumeration) {
1895 if (const QMetaObject *metaObject = t.metaObject()) {
1896 QByteArrayView qflagsNamePrefix = "QFlags<";
1897 QByteArray enumName = t.name();
1898 if (enumName.endsWith('>') && enumName.startsWith(qflagsNamePrefix)) {
1899 // extract the template argument
1900 enumName.chop(1);
1901 enumName = enumName.sliced(qflagsNamePrefix.size());
1902 }
1903 if (qsizetype lastColon = enumName.lastIndexOf(':'); lastColon != -1)
1904 enumName = enumName.sliced(lastColon + 1);
1905 return metaObject->enumerator(metaObject->indexOfEnumerator(enumName));
1906 }
1907 }
1908 return QMetaEnum();
1909}
1910#endif
1911
1912static bool convertFromEnum(QMetaType fromType, const void *from, QMetaType toType, void *to)
1913{
1914 qlonglong ll;
1915 if (fromType.flags() & QMetaType::IsUnsignedEnumeration) {
1916 qulonglong ull;
1917 switch (fromType.sizeOf()) {
1918 case 1:
1919 ull = *static_cast<const unsigned char *>(from);
1920 break;
1921 case 2:
1922 ull = *static_cast<const unsigned short *>(from);
1923 break;
1924 case 4:
1925 ull = *static_cast<const unsigned int *>(from);
1926 break;
1927 case 8:
1928 ull = *static_cast<const quint64 *>(from);
1929 break;
1930 default:
1931 Q_UNREACHABLE();
1932 }
1933 if (toType.id() == QMetaType::ULongLong) {
1934 *static_cast<qulonglong *>(to) = ull;
1935 return true;
1936 }
1937 if (toType.id() != QMetaType::QString && toType.id() != QMetaType::QByteArray)
1938 return QMetaType::convert(QMetaType::fromType<qulonglong>(), &ull, toType, to);
1939 ll = qlonglong(ull);
1940 } else {
1941 switch (fromType.sizeOf()) {
1942 case 1:
1943 ll = *static_cast<const signed char *>(from);
1944 break;
1945 case 2:
1946 ll = *static_cast<const short *>(from);
1947 break;
1948 case 4:
1949 ll = *static_cast<const int *>(from);
1950 break;
1951 case 8:
1952 ll = *static_cast<const qint64 *>(from);
1953 break;
1954 default:
1955 Q_UNREACHABLE();
1956 }
1957 if (toType.id() == QMetaType::LongLong) {
1958 *static_cast<qlonglong *>(to) = ll;
1959 return true;
1960 }
1961 if (toType.id() != QMetaType::QString && toType.id() != QMetaType::QByteArray)
1962 return QMetaType::convert(QMetaType::fromType<qlonglong>(), &ll, toType, to);
1963 }
1964#ifndef QT_NO_QOBJECT
1965 QMetaEnum en = metaEnumFromType(fromType);
1966 if (en.isValid()) {
1967 if (en.isFlag()) {
1968 const QByteArray keys = en.valueToKeys(static_cast<int>(ll));
1969 if (toType.id() == QMetaType::QString)
1970 *static_cast<QString *>(to) = QString::fromUtf8(keys);
1971 else
1972 *static_cast<QByteArray *>(to) = keys;
1973 } else {
1974 const char *key = en.valueToKey(static_cast<int>(ll));
1975 if (toType.id() == QMetaType::QString)
1976 *static_cast<QString *>(to) = QString::fromUtf8(key);
1977 else
1978 *static_cast<QByteArray *>(to) = key;
1979 }
1980 return true;
1981 }
1982#endif
1983 if (toType.id() == QMetaType::QString || toType.id() == QMetaType::QByteArray)
1984 return QMetaType::convert(QMetaType::fromType<qlonglong>(), &ll, toType, to);
1985 return false;
1986}
1987
1988static bool convertToEnum(QMetaType fromType, const void *from, QMetaType toType, void *to)
1989{
1990 int fromTypeId = fromType.id();
1991 qlonglong value = -1;
1992 bool ok = false;
1993#ifndef QT_NO_QOBJECT
1994 if (fromTypeId == QMetaType::QString || fromTypeId == QMetaType::QByteArray) {
1995 QMetaEnum en = metaEnumFromType(toType);
1996 if (en.isValid()) {
1997 QByteArray keys = (fromTypeId == QMetaType::QString)
1998 ? static_cast<const QString *>(from)->toUtf8()
1999 : *static_cast<const QByteArray *>(from);
2000 value = en.keysToValue(keys.constData(), &ok);
2001 }
2002 }
2003#endif
2004 if (!ok) {
2005 if (fromTypeId == QMetaType::LongLong) {
2006 value = *static_cast<const qlonglong *>(from);
2007 ok = true;
2008 } else {
2009 ok = QMetaType::convert(fromType, from, QMetaType::fromType<qlonglong>(), &value);
2010 }
2011 }
2012
2013 if (!ok)
2014 return false;
2015
2016 switch (toType.sizeOf()) {
2017 case 1:
2018 *static_cast<signed char *>(to) = value;
2019 return true;
2020 case 2:
2021 *static_cast<qint16 *>(to) = value;
2022 return true;
2023 case 4:
2024 *static_cast<qint32 *>(to) = value;
2025 return true;
2026 case 8:
2027 *static_cast<qint64 *>(to) = value;
2028 return true;
2029 default:
2030 Q_UNREACHABLE_RETURN(false);
2031 }
2032}
2033
2034#ifndef QT_BOOTSTRAPPED
2035static bool convertIterableToVariantList(QMetaType fromType, const void *from, void *to)
2036{
2038 if (!QMetaType::convert(fromType, from, QMetaType::fromType<QSequentialIterable>(), &list))
2039 return false;
2040
2041 QVariantList &l = *static_cast<QVariantList *>(to);
2042 l.clear();
2043 l.reserve(list.size());
2044 auto end = list.end();
2045 for (auto it = list.begin(); it != end; ++it)
2046 l << *it;
2047 return true;
2048}
2049
2050static bool convertIterableToVariantMap(QMetaType fromType, const void *from, void *to)
2051{
2053 if (!QMetaType::convert(fromType, from, QMetaType::fromType<QAssociativeIterable>(), &map))
2054 return false;
2055
2056 QVariantMap &h = *static_cast<QVariantMap *>(to);
2057 h.clear();
2058 auto end = map.end();
2059 for (auto it = map.begin(); it != end; ++it)
2060 h.insert(it.key().toString(), it.value());
2061 return true;
2062}
2063
2064static bool convertIterableToVariantHash(QMetaType fromType, const void *from, void *to)
2065{
2067 if (!QMetaType::convert(fromType, from, QMetaType::fromType<QAssociativeIterable>(), &map))
2068 return false;
2069
2070 QVariantHash &h = *static_cast<QVariantHash *>(to);
2071 h.clear();
2072 h.reserve(map.size());
2073 auto end = map.end();
2074 for (auto it = map.begin(); it != end; ++it)
2075 h.insert(it.key().toString(), it.value());
2076 return true;
2077}
2078#endif
2079
2080static bool convertIterableToVariantPair(QMetaType fromType, const void *from, void *to)
2081{
2082 const QMetaType::ConverterFunction * const f =
2083 customTypesConversionRegistry()->function(qMakePair(fromType.id(),
2084 qMetaTypeId<QtMetaTypePrivate::QPairVariantInterfaceImpl>()));
2085 if (!f)
2086 return false;
2087
2089 (*f)(from, &pi);
2090
2091 QVariant v1(pi._metaType_first);
2092 void *dataPtr;
2093 if (pi._metaType_first == QMetaType::fromType<QVariant>())
2094 dataPtr = &v1;
2095 else
2096 dataPtr = v1.data();
2097 pi.first(dataPtr);
2098
2099 QVariant v2(pi._metaType_second);
2100 if (pi._metaType_second == QMetaType::fromType<QVariant>())
2101 dataPtr = &v2;
2102 else
2103 dataPtr = v2.data();
2104 pi.second(dataPtr);
2105
2106 *static_cast<QVariantPair *>(to) = QVariantPair(v1, v2);
2107 return true;
2108}
2109
2110#ifndef QT_BOOTSTRAPPED
2111static bool convertToSequentialIterable(QMetaType fromType, const void *from, void *to)
2112{
2113 using namespace QtMetaTypePrivate;
2114 const int fromTypeId = fromType.id();
2115
2116 QSequentialIterable &i = *static_cast<QSequentialIterable *>(to);
2117 switch (fromTypeId) {
2118 case QMetaType::QVariantList:
2119 i = QSequentialIterable(reinterpret_cast<const QVariantList *>(from));
2120 return true;
2121 case QMetaType::QStringList:
2122 i = QSequentialIterable(reinterpret_cast<const QStringList *>(from));
2123 return true;
2124 case QMetaType::QByteArrayList:
2125 i = QSequentialIterable(reinterpret_cast<const QByteArrayList *>(from));
2126 return true;
2127 case QMetaType::QString:
2128 i = QSequentialIterable(reinterpret_cast<const QString *>(from));
2129 return true;
2130 case QMetaType::QByteArray:
2131 i = QSequentialIterable(reinterpret_cast<const QByteArray *>(from));
2132 return true;
2133 default: {
2136 fromType, from, QMetaType::fromType<QIterable<QMetaSequence>>(), &impl)) {
2137 i = std::move(impl);
2138 return true;
2139 }
2140 }
2141 }
2142
2143 return false;
2144}
2145
2147{
2148 switch (fromType.id()) {
2149 case QMetaType::QVariantList:
2150 case QMetaType::QStringList:
2151 case QMetaType::QByteArrayList:
2152 case QMetaType::QString:
2153 case QMetaType::QByteArray:
2154 return true;
2155 default:
2157 }
2158}
2159
2161{
2162 switch (fromType.id()) {
2163 case QMetaType::QVariantList:
2164 case QMetaType::QStringList:
2165 case QMetaType::QByteArrayList:
2166 case QMetaType::QString:
2167 case QMetaType::QByteArray:
2168 return true;
2169 default:
2170 return QMetaType::canView(
2172 }
2173}
2174
2175static bool viewAsSequentialIterable(QMetaType fromType, void *from, void *to)
2176{
2177 using namespace QtMetaTypePrivate;
2178 const int fromTypeId = fromType.id();
2179
2180 QSequentialIterable &i = *static_cast<QSequentialIterable *>(to);
2181 switch (fromTypeId) {
2182 case QMetaType::QVariantList:
2183 i = QSequentialIterable(reinterpret_cast<QVariantList *>(from));
2184 return true;
2185 case QMetaType::QStringList:
2186 i = QSequentialIterable(reinterpret_cast<QStringList *>(from));
2187 return true;
2188 case QMetaType::QByteArrayList:
2189 i = QSequentialIterable(reinterpret_cast<QByteArrayList *>(from));
2190 return true;
2191 case QMetaType::QString:
2192 i = QSequentialIterable(reinterpret_cast<QString *>(from));
2193 return true;
2194 case QMetaType::QByteArray:
2195 i = QSequentialIterable(reinterpret_cast<QByteArray *>(from));
2196 return true;
2197 default: {
2199 if (QMetaType::view(
2200 fromType, from, QMetaType::fromType<QIterable<QMetaSequence>>(), &j)) {
2201 i = std::move(j);
2202 return true;
2203 }
2204 }
2205 }
2206
2207 return false;
2208}
2209
2210static bool convertToAssociativeIterable(QMetaType fromType, const void *from, void *to)
2211{
2212 using namespace QtMetaTypePrivate;
2213
2214 QAssociativeIterable &i = *static_cast<QAssociativeIterable *>(to);
2215 if (fromType.id() == QMetaType::QVariantMap) {
2216 i = QAssociativeIterable(reinterpret_cast<const QVariantMap *>(from));
2217 return true;
2218 }
2219 if (fromType.id() == QMetaType::QVariantHash) {
2220 i = QAssociativeIterable(reinterpret_cast<const QVariantHash *>(from));
2221 return true;
2222 }
2223
2226 fromType, from, QMetaType::fromType<QIterable<QMetaAssociation>>(), &impl)) {
2227 i = std::move(impl);
2228 return true;
2229 }
2230
2231 return false;
2232}
2233
2234static bool canConvertMetaObject(QMetaType fromType, QMetaType toType)
2235{
2236 if ((fromType.flags() & QMetaType::IsPointer) != (toType.flags() & QMetaType::IsPointer))
2237 return false; // Can not convert between pointer and value
2238
2239 const QMetaObject *f = fromType.metaObject();
2240 const QMetaObject *t = toType.metaObject();
2241 if (f && t) {
2242 return f->inherits(t) || (t->inherits(f));
2243 }
2244 return false;
2245}
2246
2248{
2249 switch (fromType.id()) {
2250 case QMetaType::QVariantMap:
2251 case QMetaType::QVariantHash:
2252 return true;
2253 default:
2255 }
2256}
2257
2259{
2260 switch (fromType.id()) {
2261 case QMetaType::QVariantMap:
2262 case QMetaType::QVariantHash:
2263 return true;
2264 default:
2265 return QMetaType::canView(
2267 }
2268}
2269
2270static bool viewAsAssociativeIterable(QMetaType fromType, void *from, void *to)
2271{
2272 using namespace QtMetaTypePrivate;
2273 int fromTypeId = fromType.id();
2274
2275 QAssociativeIterable &i = *static_cast<QAssociativeIterable *>(to);
2276 if (fromTypeId == QMetaType::QVariantMap) {
2277 i = QAssociativeIterable(reinterpret_cast<QVariantMap *>(from));
2278 return true;
2279 }
2280 if (fromTypeId == QMetaType::QVariantHash) {
2281 i = QAssociativeIterable(reinterpret_cast<QVariantHash *>(from));
2282 return true;
2283 }
2284
2286 if (QMetaType::view(
2287 fromType, from, QMetaType::fromType<QIterable<QMetaAssociation>>(), &j)) {
2288 i = std::move(j);
2289 return true;
2290 }
2291
2292 return false;
2293}
2294
2295static bool convertMetaObject(QMetaType fromType, const void *from, QMetaType toType, void *to)
2296{
2297 // handle QObject conversion
2298 if ((fromType.flags() & QMetaType::PointerToQObject) && (toType.flags() & QMetaType::PointerToQObject)) {
2299 QObject *fromObject = *static_cast<QObject * const *>(from);
2300 // use dynamic metatype of from if possible
2301 if (fromObject && fromObject->metaObject()->inherits(toType.metaObject())) {
2302 *static_cast<QObject **>(to) = toType.metaObject()->cast(fromObject);
2303 return true;
2304 } else if (!fromObject && fromType.metaObject()) {
2305 // if fromObject is null, use static fromType to check if conversion works
2306 *static_cast<void **>(to) = nullptr;
2307 return fromType.metaObject()->inherits(toType.metaObject());
2308 }
2309 } else if ((fromType.flags() & QMetaType::IsPointer) == (toType.flags() & QMetaType::IsPointer)) {
2310 // fromType and toType are of same 'pointedness'
2311 const QMetaObject *f = fromType.metaObject();
2312 const QMetaObject *t = toType.metaObject();
2313 if (f && t && f->inherits(t)) {
2314 toType.destruct(to);
2315 toType.construct(to, from);
2316 return true;
2317 }
2318 }
2319 return false;
2320}
2321#endif
2322
2343bool QMetaType::convert(QMetaType fromType, const void *from, QMetaType toType, void *to)
2344{
2345 if (!fromType.isValid() || !toType.isValid())
2346 return false;
2347
2348 if (fromType == toType) {
2349 // just make a copy
2350 fromType.destruct(to);
2351 fromType.construct(to, from);
2352 return true;
2353 }
2354
2355 int fromTypeId = fromType.id();
2356 int toTypeId = toType.id();
2357
2358 if (auto moduleHelper = qModuleHelperForType(qMax(fromTypeId, toTypeId))) {
2359 if (moduleHelper->convert(from, fromTypeId, to, toTypeId))
2360 return true;
2361 }
2362 const QMetaType::ConverterFunction * const f =
2363 customTypesConversionRegistry()->function(qMakePair(fromTypeId, toTypeId));
2364 if (f)
2365 return (*f)(from, to);
2366
2368 return convertFromEnum(fromType, from, toType, to);
2369 if (toType.flags() & QMetaType::IsEnumeration)
2370 return convertToEnum(fromType, from, toType, to);
2371 if (toTypeId == Nullptr) {
2372 *static_cast<std::nullptr_t *>(to) = nullptr;
2374 if (*static_cast<const void * const *>(from) == nullptr)
2375 return true;
2376 }
2377 }
2378
2379 if (toTypeId == QVariantPair && convertIterableToVariantPair(fromType, from, to))
2380 return true;
2381
2382#ifndef QT_BOOTSTRAPPED
2383 // handle iterables
2384 if (toTypeId == QVariantList && convertIterableToVariantList(fromType, from, to))
2385 return true;
2386
2387 if (toTypeId == QVariantMap && convertIterableToVariantMap(fromType, from, to))
2388 return true;
2389
2390 if (toTypeId == QVariantHash && convertIterableToVariantHash(fromType, from, to))
2391 return true;
2392
2393 if (toTypeId == qMetaTypeId<QSequentialIterable>())
2394 return convertToSequentialIterable(fromType, from, to);
2395
2396 if (toTypeId == qMetaTypeId<QAssociativeIterable>())
2397 return convertToAssociativeIterable(fromType, from, to);
2398
2399 return convertMetaObject(fromType, from, toType, to);
2400#else
2401 return false;
2402#endif
2403}
2404
2410bool QMetaType::view(QMetaType fromType, void *from, QMetaType toType, void *to)
2411{
2412 if (!fromType.isValid() || !toType.isValid())
2413 return false;
2414
2415 int fromTypeId = fromType.id();
2416 int toTypeId = toType.id();
2417
2418 const QMetaType::MutableViewFunction * const f =
2419 customTypesMutableViewRegistry()->function(qMakePair(fromTypeId, toTypeId));
2420 if (f)
2421 return (*f)(from, to);
2422
2423#ifndef QT_BOOTSTRAPPED
2424 if (toTypeId == qMetaTypeId<QSequentialIterable>())
2425 return viewAsSequentialIterable(fromType, from, to);
2426
2427 if (toTypeId == qMetaTypeId<QAssociativeIterable>())
2428 return viewAsAssociativeIterable(fromType, from, to);
2429
2430 return convertMetaObject(fromType, from, toType, to);
2431#else
2432 return false;
2433#endif
2434}
2435
2454{
2455 int fromTypeId = fromType.id();
2456 int toTypeId = toType.id();
2457
2458 if (fromTypeId == UnknownType || toTypeId == UnknownType)
2459 return false;
2460
2461 const MutableViewFunction * const f =
2462 customTypesMutableViewRegistry()->function(qMakePair(fromTypeId, toTypeId));
2463 if (f)
2464 return true;
2465
2466#ifndef QT_BOOTSTRAPPED
2467 if (toTypeId == qMetaTypeId<QSequentialIterable>())
2469
2470 if (toTypeId == qMetaTypeId<QAssociativeIterable>())
2472
2473 if (canConvertMetaObject(fromType, toType))
2474 return true;
2475#endif
2476
2477 return false;
2478}
2479
2552{
2553 int fromTypeId = fromType.id();
2554 int toTypeId = toType.id();
2555
2556 if (fromTypeId == UnknownType || toTypeId == UnknownType)
2557 return false;
2558
2559 if (fromTypeId == toTypeId)
2560 return true;
2561
2562 if (auto moduleHelper = qModuleHelperForType(qMax(fromTypeId, toTypeId))) {
2563 if (moduleHelper->convert(nullptr, fromTypeId, nullptr, toTypeId))
2564 return true;
2565 }
2566 const ConverterFunction * const f =
2567 customTypesConversionRegistry()->function(std::make_pair(fromTypeId, toTypeId));
2568 if (f)
2569 return true;
2570
2571#ifndef QT_BOOTSTRAPPED
2572 if (toTypeId == qMetaTypeId<QSequentialIterable>())
2574
2575 if (toTypeId == qMetaTypeId<QAssociativeIterable>())
2577
2578 if (toTypeId == QVariantList
2579 && canConvert(fromType, QMetaType::fromType<QSequentialIterable>())) {
2580 return true;
2581 }
2582
2583 if ((toTypeId == QVariantHash || toTypeId == QVariantMap)
2584 && canConvert(fromType, QMetaType::fromType<QAssociativeIterable>())) {
2585 return true;
2586 }
2587#endif
2588
2590 fromType, QMetaType::fromType<QtMetaTypePrivate::QPairVariantInterfaceImpl>()))
2591 return true;
2592
2593 if (fromType.flags() & IsEnumeration) {
2594 if (toTypeId == QString || toTypeId == QByteArray)
2595 return true;
2596 return canConvert(QMetaType(LongLong), toType);
2597 }
2598 if (toType.flags() & IsEnumeration) {
2599 if (fromTypeId == QString || fromTypeId == QByteArray)
2600 return true;
2601 return canConvert(fromType, QMetaType(LongLong));
2602 }
2603 if (toTypeId == Nullptr && fromType.flags() & IsPointer)
2604 return true;
2605#ifndef QT_BOOTSTRAPPED
2606 if (canConvertMetaObject(fromType, toType))
2607 return true;
2608#endif
2609
2610 return false;
2611}
2612
2635{
2636 return customTypesConversionRegistry()->contains(qMakePair(fromType.id(), toType.id()));
2637}
2638
2652{
2653 return customTypesMutableViewRegistry()->contains(qMakePair(fromType.id(), toType.id()));
2654}
2655
2678/*
2679 Similar to QMetaType::type(), but only looks in the static set of types.
2680*/
2681static inline int qMetaTypeStaticType(const char *typeName, int length)
2682{
2683 int i = 0;
2684 while (types[i].typeName && ((length != types[i].typeNameLength)
2685 || memcmp(typeName, types[i].typeName, length))) {
2686 ++i;
2687 }
2688 return types[i].type;
2689}
2690
2691/*
2692 Similar to QMetaType::type(), but only looks in the custom set of
2693 types, and doesn't lock the mutex.
2694
2695*/
2697{
2698 if (customTypeRegistry.exists()) {
2699 auto reg = &*customTypeRegistry;
2700#if QT_CONFIG(thread)
2701 Q_ASSERT(!reg->lock.tryLockForWrite());
2702#endif
2703 if (auto ti = reg->aliases.value(QByteArray::fromRawData(typeName, length), nullptr)) {
2704 return ti->typeId.loadRelaxed();
2705 }
2706 }
2708}
2709
2717void QMetaType::registerNormalizedTypedef(const NS(QByteArray) & normalizedTypeName,
2718 QMetaType metaType)
2719{
2720 if (!metaType.isValid())
2721 return;
2722 if (auto reg = customTypeRegistry()) {
2723 QWriteLocker lock(&reg->lock);
2724 auto &al = reg->aliases[normalizedTypeName];
2725 if (al)
2726 return;
2727 al = metaType.d_ptr;
2728 }
2729}
2730
2731
2733{
2734 const QtPrivate::QMetaTypeInterface *iface = nullptr;
2735 if (typeId >= QMetaType::User) {
2736 if (customTypeRegistry.exists())
2737 iface = customTypeRegistry->getCustomType(typeId);
2738 } else {
2739 if (auto moduleHelper = qModuleHelperForType(typeId))
2740 iface = moduleHelper->interfaceForType(typeId);
2741 }
2742 return iface;
2743}
2744
2752{
2753 return interfaceForTypeNoWarning(type) != nullptr;
2754}
2755
2756template <bool tryNormalizedType>
2757static inline int qMetaTypeTypeImpl(const char *typeName, int length)
2758{
2759 if (!length)
2763 QReadLocker locker(&customTypeRegistry()->lock);
2765#ifndef QT_NO_QOBJECT
2766 if ((type == QMetaType::UnknownType) && tryNormalizedType) {
2767 const NS(QByteArray) normalizedTypeName = QMetaObject::normalizedType(typeName);
2768 type = qMetaTypeStaticType(normalizedTypeName.constData(),
2769 normalizedTypeName.size());
2771 type = qMetaTypeCustomType_unlocked(normalizedTypeName.constData(),
2772 normalizedTypeName.size());
2773 }
2774 }
2775#endif
2776 }
2777 return type;
2778}
2779
2797Q_CORE_EXPORT int qMetaTypeTypeInternal(const char *typeName)
2798{
2799 return qMetaTypeTypeImpl</*tryNormalizedType=*/false>(typeName, int(qstrlen(typeName)));
2800}
2801
2815#ifndef QT_NO_DATASTREAM
2827bool QMetaType::save(QDataStream &stream, const void *data) const
2828{
2829 if (!data || !isValid())
2830 return false;
2831
2832 // keep compatibility for long/ulong
2833 if (id() == QMetaType::Long) {
2834 stream << qlonglong(*(long *)data);
2835 return true;
2836 } else if (id() == QMetaType::ULong) {
2837 stream << qlonglong(*(unsigned long *)data);
2838 return true;
2839 }
2840
2841 if (!d_ptr->dataStreamOut)
2842 return false;
2843
2844 d_ptr->dataStreamOut(d_ptr, stream, data);
2845 return true;
2846}
2847
2866{
2867 if (!data || !isValid())
2868 return false;
2869
2870 // keep compatibility for long/ulong
2871 if (id() == QMetaType::Long) {
2872 qlonglong ll;
2873 stream >> ll;
2874 *(long *)data = long(ll);
2875 return true;
2876 } else if (id() == QMetaType::ULong) {
2877 qulonglong ull;
2878 stream >> ull;
2879 *(unsigned long *)data = (unsigned long)(ull);
2880 return true;
2881 }
2882 if (!d_ptr->dataStreamIn)
2883 return false;
2884
2885 d_ptr->dataStreamIn(d_ptr, stream, data);
2886 return true;
2887}
2888
2896{
2897 int type = id();
2898 if (type == QMetaType::Long || type == QMetaType::ULong)
2899 return true;
2900 return d_ptr && d_ptr->dataStreamIn != nullptr && d_ptr->dataStreamOut != nullptr;
2901}
2902
2913{
2914 if (!d_ptr || !(flags() & IsEnumeration))
2915 return {};
2916 /* QFlags has enumeration set so that's handled here (qint32
2917 case), as QFlags uses int as the underlying type
2918 Note that we do some approximation here, as we cannot
2919 differentiate between different underlying types of the
2920 same size and signedness (consider char <-> (un)signed char,
2921 int <-> long <-> long long).
2922
2923 ### TODO PENDING: QTBUG-111926 - QFlags supporting >32 bit int
2924 */
2925 if (flags() & IsUnsignedEnumeration) {
2926 switch (sizeOf()) {
2927 case 1:
2928 return QMetaType::fromType<quint8>();
2929 case 2:
2930 return QMetaType::fromType<quint16>();
2931 case 4:
2932 return QMetaType::fromType<quint32>();
2933 case 8:
2934 return QMetaType::fromType<quint64>();
2935 default:
2936 break;
2937 }
2938 } else {
2939 switch (sizeOf()) {
2940 case 1:
2941 return QMetaType::fromType<qint8>();
2942 case 2:
2943 return QMetaType::fromType<qint16>();
2944 case 4:
2945 return QMetaType::fromType<qint32>();
2946 case 8:
2947 return QMetaType::fromType<qint64>();
2948 default:
2949 break;
2950 }
2951 }
2952 // int128 can be handled above once we have qint128
2953 return QMetaType();
2954}
2955
2961#endif // QT_NO_DATASTREAM
2962
2968{
2969 return QMetaType(qMetaTypeTypeImpl</*tryNormalizedType=*/true>(typeName.data(), typeName.size()));
2970}
2971
3180{
3182 if (!iface && typeId != QMetaType::UnknownType)
3183 qWarning("Trying to construct an instance of an invalid type, type id: %i", typeId);
3184
3185 return iface;
3186}
3187
3202
3203
3211namespace QtPrivate {
3212#if !defined(QT_BOOTSTRAPPED) && !defined(Q_CC_MSVC) && !defined(Q_OS_INTEGRITY)
3213
3214// Explicit instantiation definition
3215#define QT_METATYPE_DECLARE_TEMPLATE_ITER(TypeName, Id, Name) \
3216 template class QMetaTypeForType<Name>; \
3217 template struct QMetaTypeInterfaceWrapper<Name>;
3223
3224#undef QT_METATYPE_DECLARE_TEMPLATE_ITER
3225#endif
3226}
3227
The QAssociativeIterable class is an iterable interface for an associative container in a QVariant.
T loadRelaxed() const noexcept
\inmodule QtCore
constexpr qsizetype size() const noexcept
\inmodule QtCore
Definition qbytearray.h:57
bool endsWith(char c) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qbytearray.h:174
void chop(qsizetype n)
Removes n bytes from the end of the byte array.
bool startsWith(QByteArrayView bv) const
Definition qbytearray.h:170
static QByteArray number(int, int base=10)
Returns a byte-array representing the whole number n as text.
QByteArray sliced(qsizetype pos) const
Definition qbytearray.h:163
qsizetype lastIndexOf(char c, qsizetype from=-1) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
static QByteArray fromRawData(const char *data, qsizetype size)
Constructs a QByteArray that uses the first size bytes of the data array.
Definition qbytearray.h:394
\inmodule QtCore\reentrant
Definition qcborarray.h:20
QVariantList toVariantList() const
Recursively converts each \l QCborValue in this array using QCborValue::toVariant() and returns the Q...
static QCborArray fromJsonArray(const QJsonArray &array)
Converts all JSON items found in the array array to CBOR using QCborValue::fromJson(),...
QJsonArray toJsonArray() const
Recursively converts every \l QCborValue element in this array to JSON using QCborValue::toJsonValue(...
static QCborArray fromStringList(const QStringList &list)
Returns a QCborArray containing all the strings found in the list list.
static QCborArray fromVariantList(const QVariantList &list)
Converts all the items in the list to CBOR using QCborValue::fromVariant() and returns the array comp...
\inmodule QtCore\reentrant
Definition qcbormap.h:21
QVariantMap toVariantMap() const
Converts the CBOR values to QVariant using QCborValue::toVariant() and "stringifies" all the CBOR key...
QVariantHash toVariantHash() const
Converts the CBOR values to QVariant using QCborValue::toVariant() and "stringifies" all the CBOR key...
QJsonObject toJsonObject() const
Recursively converts every \l QCborValue value in this map to JSON using QCborValue::toJsonValue() an...
static QCborMap fromJsonObject(const QJsonObject &o)
Converts all JSON items found in the obj object to CBOR using QCborValue::fromJson(),...
static QCborMap fromVariantMap(const QVariantMap &map)
Converts all the items in map to CBOR using QCborValue::fromVariant() and returns the map composed of...
static QCborMap fromVariantHash(const QVariantHash &hash)
Converts all the items in hash to CBOR using QCborValue::fromVariant() and returns the map composed o...
\inmodule QtCore\reentrant
Definition qcborvalue.h:50
bool isNull() const
Returns true if this QCborValue is of the null type.
Definition qcborvalue.h:167
QJsonValue toJsonValue() const
Converts this QCborValue object to an equivalent representation in JSON and returns it as a QJsonValu...
static QCborValue fromJsonValue(const QJsonValue &v)
Converts the JSON value contained in v into its corresponding CBOR value and returns it.
\inmodule QtCore
Definition qchar.h:48
\inmodule QtCore\reentrant
Definition qdatastream.h:30
\inmodule QtCore\reentrant
Definition qdatetime.h:257
QTime time() const
Returns the time part of the datetime.
QDate date() const
Returns the date part of the datetime.
\inmodule QtCore \reentrant
Definition qdatetime.h:27
QDateTime startOfDay(const QTimeZone &zone) const
\inmodule QtCore
\inmodule QtCore
\inmodule QtCore
Definition qhash.h:818
iterator begin()
Returns an \l{STL-style iterators}{STL-style iterator} pointing to the first item in the hash.
Definition qhash.h:1202
iterator erase(const_iterator it)
Definition qhash.h:1223
T value(const Key &key) const noexcept
Definition qhash.h:1044
iterator end() noexcept
Returns an \l{STL-style iterators}{STL-style iterator} pointing to the imaginary item after the last ...
Definition qhash.h:1206
void clear() noexcept(std::is_nothrow_destructible< Node >::value)
Removes all items from the hash and frees up all memory used by it.
Definition qhash.h:949
iterator insert(const Key &key, const T &value)
Inserts a new item with the key and a value of value.
Definition qhash.h:1283
\inmodule QtCore
Definition qiterable.h:408
\inmodule QtCore\reentrant
Definition qjsonarray.h:18
static QJsonArray fromStringList(const QStringList &list)
Converts the string list list to a QJsonArray.
static QJsonArray fromVariantList(const QVariantList &list)
Converts the variant list list to a QJsonArray.
QVariantList toVariantList() const
Converts this object to a QVariantList.
\inmodule QtCore\reentrant
bool isArray() const
Returns true if the document contains an array.
\inmodule QtCore\reentrant
Definition qjsonobject.h:20
QVariantMap toVariantMap() const
Converts this object to a QVariantMap.
static QJsonObject fromVariantMap(const QVariantMap &map)
Converts the variant map map to a QJsonObject.
QVariantHash toVariantHash() const
Converts this object to a QVariantHash.
static QJsonObject fromVariantHash(const QVariantHash &map)
Converts the variant hash hash to a QJsonObject.
\inmodule QtCore\reentrant
Definition qjsonvalue.h:24
bool isNull() const
Returns true if the value is null.
Definition qjsonvalue.h:71
\inmodule QtCore
Definition qline.h:182
constexpr QLine toLine() const
Returns an integer-based copy of this line.
Definition qline.h:358
\inmodule QtCore
Definition qline.h:18
Definition qlist.h:74
qsizetype size() const noexcept
Definition qlist.h:386
iterator end()
Definition qlist.h:609
T value(qsizetype i) const
Definition qlist.h:661
iterator begin()
Definition qlist.h:608
void reserve(qsizetype size)
Definition qlist.h:746
void append(parameter_type t)
Definition qlist.h:441
void clear()
Definition qlist.h:417
@ FloatingPointShortest
Definition qlocale.h:880
iterator insert(const Key &key, const T &value)
Definition qmap.h:687
void clear()
Definition qmap.h:288
iterator begin()
Definition qmap.h:597
iterator end()
Definition qmap.h:601
size_type size() const
Definition qmap.h:266
\inmodule QtCore
const char * valueToKey(int value) const
Returns the string that is used as the name of the given enumeration value, or \nullptr if value is n...
bool isFlag() const
Returns true if this enumerator is used as a flag; otherwise returns false.
int keysToValue(const char *keys, bool *ok=nullptr) const
Returns the value derived from combining together the values of the keys using the OR operator,...
QByteArray valueToKeys(int value) const
Returns a byte array of '|'-separated keys that represents the given value.
bool isValid() const
Returns true if this enum is valid (has a name); otherwise returns false.
\inmodule QtCore
void remove(int from, int to)
bool insertIfNotContains(Key k, const T &f)
bool contains(Key k) const
const T * function(Key k) const
\inmodule QtCore
Definition qmetatype.h:320
bool isRegistered() const
static constexpr QMetaType fromType()
Definition qmetatype.h:2612
void destruct(void *data) const
static bool canConvert(QMetaType fromType, QMetaType toType)
Returns true if QMetaType::convert can convert from fromType to toType.
constexpr TypeFlags flags() const
Definition qmetatype.h:2628
static bool hasRegisteredConverterFunction()
Returns true, if the meta type system has a registered conversion from type From to type To.
Definition qmetatype.h:716
static bool canView(QMetaType fromType, QMetaType toType)
Returns true if QMetaType::view can create a mutable view of type toType on type fromType.
const QtPrivate::QMetaTypeInterface * iface() const
Definition qmetatype.h:750
constexpr qsizetype sizeOf() const
Definition qmetatype.h:2618
bool isEqualityComparable() const
Returns true if a less than or equality operator for the type described by this metatype was visible ...
static bool view(QMetaType fromType, void *from, QMetaType toType, void *to)
Creates a mutable view on the object at from of fromType in the preallocated space at to typed toType...
bool debugStream(QDebug &dbg, const void *rhs)
Streams the object at rhs to the debug stream dbg.
QMetaType underlyingType() const
bool hasRegisteredDataStreamOperators() const
static QMetaType fromName(QByteArrayView name)
Returns a QMetaType matching typeName.
static bool hasRegisteredMutableViewFunction()
Returns true, if the meta type system has a registered mutable view on type From of type To.
Definition qmetatype.h:725
bool isMoveConstructible() const noexcept
Definition qmetatype.h:475
bool isValid() const
bool equals(const void *lhs, const void *rhs) const
Compares the objects at lhs and rhs for equality.
void destroy(void *data) const
int id(int=0) const
Definition qmetatype.h:454
static void registerNormalizedTypedef(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName, QMetaType type)
std::function< bool(void *src, void *target)> MutableViewFunction
Definition qmetatype.h:539
@ IsUnsignedEnumeration
Definition qmetatype.h:390
@ PointerToQObject
Definition qmetatype.h:385
@ IsEnumeration
Definition qmetatype.h:386
@ LastWidgetsType
Definition qmetatype.h:333
@ FirstWidgetsType
Definition qmetatype.h:332
void * create(const void *copy=nullptr) const
std::function< bool(const void *src, void *target)> ConverterFunction
Definition qmetatype.h:536
constexpr const QMetaObject * metaObject() const
Definition qmetatype.h:2633
bool isCopyConstructible() const noexcept
Definition qmetatype.h:474
bool isDefaultConstructible() const noexcept
Definition qmetatype.h:473
constexpr const char * name() const
Definition qmetatype.h:2650
constexpr QMetaType()=default
static bool registerMutableViewFunction(const MutableViewFunction &f, QMetaType from, QMetaType to)
Registers function f as mutable view of type id to on type id from.
static void unregisterMetaType(QMetaType type)
void * construct(void *where, const void *copy=nullptr) const
static void unregisterMutableViewFunction(QMetaType from, QMetaType to)
bool isOrdered() const
Returns true if a less than operator for the type described by this metatype was visible to the metat...
bool load(QDataStream &stream, void *data) const
Reads the object of this type from the given stream into data.
bool save(QDataStream &stream, const void *data) const
Writes the object pointed to by data to the given stream.
QPartialOrdering compare(const void *lhs, const void *rhs) const
Compares the objects at lhs and rhs for ordering.
static bool convert(QMetaType fromType, const void *from, QMetaType toType, void *to)
Converts the object at from from fromType to the preallocated space at to typed toType.
bool hasRegisteredDebugStreamOperator() const
bool isDestructible() const noexcept
Definition qmetatype.h:476
static void unregisterConverterFunction(QMetaType from, QMetaType to)
\inmodule QtCore
\inmodule QtCore
Definition qobject.h:90
bool inherits(const char *classname) const
Returns true if this object is an instance of a class that inherits className or a QObject subclass t...
Definition qobject.h:313
static const QPartialOrdering Less
Definition qcompare.h:39
static const QPartialOrdering Greater
Definition qcompare.h:41
static const QPartialOrdering Equivalent
Definition qcompare.h:40
static const QPartialOrdering Unordered
Definition qcompare.h:42
\inmodule QtCore\reentrant
Definition qpoint.h:214
constexpr QPoint toPoint() const
Rounds the coordinates of this point to the nearest integer, and returns a QPoint object with the rou...
Definition qpoint.h:394
\inmodule QtCore\reentrant
Definition qpoint.h:23
\inmodule QtCore
\inmodule QtCore
\inmodule QtCore\reentrant
Definition qrect.h:483
constexpr QRect toRect() const noexcept
Returns a QRect based on the values of this rectangle.
Definition qrect.h:845
\inmodule QtCore\reentrant
Definition qrect.h:30
\inmodule QtCore \reentrant
The QSequentialIterable class is an iterable interface for a container in a QVariant.
iterator begin()
Definition qset.h:136
iterator end()
Definition qset.h:140
const_iterator constBegin() const noexcept
Definition qset.h:139
\inmodule QtCore
Definition qsize.h:207
constexpr QSize toSize() const noexcept
Returns an integer based copy of this size.
Definition qsize.h:390
\inmodule QtCore
Definition qsize.h:25
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5710
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5857
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:1083
QString toLower() const &
Definition qstring.h:368
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:7822
QByteArray toUtf8() const &
Definition qstring.h:563
\inmodule QtCore \reentrant
Definition qdatetime.h:189
\inmodule QtCore
Definition qurl.h:94
QString toString(FormattingOptions options=FormattingOptions(PrettyDecoded)) const
Returns a string representation of the URL.
Definition qurl.cpp:2828
\inmodule QtCore
Definition quuid.h:31
QString toString(StringFormat mode=WithBraces) const
Definition quuid.cpp:602
QByteArray toByteArray(StringFormat mode=WithBraces) const
Definition quuid.cpp:643
\inmodule QtCore
Definition qvariant.h:64
\inmodule QtCore
DataStreamOutFn dataStreamOut
Definition qmetatype.h:282
QMTI_MUTABLE QBasicAtomicInt typeId
Definition qmetatype.h:260
QString str
[2]
QMap< QString, QString > map
[6]
double pi
[0]
list append(new Employee("Blackpool", "Stephen"))
double e
QSet< QString >::iterator it
Combined button and popup list for selecting options.
uint Bool
bool isDestructible(const QtPrivate::QMetaTypeInterface *iface) noexcept
bool isMoveConstructible(const QtPrivate::QMetaTypeInterface *iface) noexcept
bool isDefaultConstructible(const QtPrivate::QMetaTypeInterface *iface) noexcept
bool isCopyConstructible(const QtPrivate::QMetaTypeInterface *iface) noexcept
bool isInterfaceFor(const QtPrivate::QMetaTypeInterface *iface)
void destruct(const QtPrivate::QMetaTypeInterface *iface, void *where)
void construct(const QtPrivate::QMetaTypeInterface *iface, void *where, const void *copy)
const char * typedefNameForType(const QtPrivate::QMetaTypeInterface *type_d)
\macro QT_NAMESPACE
@ ISODate
@ ISODateWithMs
void toByteArray(QByteArray &)
Definition qctf_p.h:78
static jboolean copy(JNIEnv *, jobject)
size_t qstrlen(const char *str)
QCborSimpleType
Definition qcborcommon.h:23
std::pair< T1, T2 > QPair
QPair< QVariant, QVariant > QVariantPair
EGLStreamKHR stream
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
#define Q_GLOBAL_STATIC(TYPE, NAME,...)
#define qWarning
Definition qlogging.h:162
static bool canConvertToSequentialIterable(QMetaType fromType)
static bool convertIterableToVariantHash(QMetaType fromType, const void *from, void *to)
static bool convertMetaObject(QMetaType fromType, const void *from, QMetaType toType, void *to)
static bool canConvertToAssociativeIterable(QMetaType fromType)
static bool canConvertMetaObject(QMetaType fromType, QMetaType toType)
static QPartialOrdering threeWayCompare(const void *ptr1, const void *ptr2)
static QMetaEnum metaEnumFromType(QMetaType t)
#define NS(x)
Definition qmetatype.cpp:65
static const QMetaTypeModuleHelper * qModuleHelperForType(int type)
static bool convertIterableToVariantMap(QMetaType fromType, const void *from, void *to)
QDebug operator<<(QDebug d, QMetaType m)
Q_CONSTINIT Q_CORE_EXPORT const QMetaTypeModuleHelper * qMetaTypeWidgetsHelper
static bool canImplicitlyViewAsAssociativeIterable(QMetaType fromType)
#define QMETATYPE_CONVERTER_ASSIGN_QCHAR(From)
static int qMetaTypeStaticType(const char *typeName, int length)
QMetaTypeFunctionRegistry< QMetaType::ConverterFunction, QPair< int, int > > QMetaTypeConverterRegistry
static bool convertToEnum(QMetaType fromType, const void *from, QMetaType toType, void *to)
static const QtPrivate::QMetaTypeInterface * interfaceForTypeNoWarning(int typeId)
static bool convertToSequentialIterable(QMetaType fromType, const void *from, void *to)
#define QMETATYPE_CONVERTER_ASSIGN_DOUBLE(To, From)
static bool viewAsSequentialIterable(QMetaType fromType, void *from, void *to)
#define INTEGRAL_CONVERTER(To)
static bool convertIterableToVariantList(QMetaType fromType, const void *from, void *to)
static bool convertToAssociativeIterable(QMetaType fromType, const void *from, void *to)
static int qMetaTypeTypeImpl(const char *typeName, int length)
static bool viewAsAssociativeIterable(QMetaType fromType, void *from, void *to)
#define QT_ADD_STATIC_METATYPE(MetaTypeName, MetaTypeId, RealName)
Q_CONSTINIT Q_CORE_EXPORT const QMetaTypeModuleHelper * qMetaTypeGuiHelper
const char * typeName
#define QMETATYPE_CONVERTER_ASSIGN_NUMBER(To, From)
#define QT_METATYPE_DECLARE_TEMPLATE_ITER(TypeName, Id, Name)
static const QtPrivate::QMetaTypeInterface * interfaceForType(int typeId)
static bool canImplicitlyViewAsSequentialIterable(QMetaType fromType)
int typeNameLength
int type
static bool convertIterableToVariantPair(QMetaType fromType, const void *from, void *to)
static int qMetaTypeCustomType_unlocked(const char *typeName, int length)
metatypeHelper
Q_CORE_EXPORT int qMetaTypeTypeInternal(const char *typeName)
#define QT_ADD_STATIC_METATYPE_ALIASES_ITER(MetaTypeName, MetaTypeId, AliasingName, RealNameStr)
static bool convertFromEnum(QMetaType fromType, const void *from, QMetaType toType, void *to)
#define FLOAT_CONVERTER(To)
#define QT_FOR_EACH_STATIC_CORE_POINTER(F)
Definition qmetatype.h:128
#define QT_FOR_EACH_STATIC_PRIMITIVE_TYPE(F)
Definition qmetatype.h:67
#define QT_FOR_EACH_STATIC_PRIMITIVE_NON_VOID_TYPE(F)
Definition qmetatype.h:47
#define QT_FOR_EACH_STATIC_CORE_TEMPLATE(F)
Definition qmetatype.h:131
#define QT_FOR_EACH_STATIC_PRIMITIVE_POINTER(F)
Definition qmetatype.h:71
#define QT_IMPL_METATYPE_EXTERN_TAGGED(TYPE, TAG)
Definition qmetatype.h:1363
#define QT_FOR_EACH_STATIC_CORE_CLASS(F)
Definition qmetatype.h:96
#define QT_FOR_EACH_STATIC_ALIAS_TYPE(F)
Definition qmetatype.h:176
#define QT_FOR_EACH_STATIC_TYPE(F)
Definition qmetatype.h:198
#define QT_METATYPE_CONVERT_ID_TO_TYPE(MetaTypeName, MetaTypeId, RealName)
#define QMETATYPE_CONVERTER(To, From, assign_and_return)
Definition qmetatype_p.h:23
#define QMETATYPE_CONVERTER_ASSIGN(To, From)
Definition qmetatype_p.h:32
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
GLint GLfloat GLfloat GLfloat v2
GLsizei const GLfloat * v
[13]
const GLfloat * m
GLuint64 key
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLboolean r
[2]
GLuint GLuint end
GLsizei GLenum GLenum * types
GLenum GLuint GLenum GLsizei length
GLenum GLuint id
[7]
GLuint object
[3]
GLfloat GLfloat f
GLenum type
GLint GLfloat GLfloat v1
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLuint name
GLfloat GLfloat GLfloat GLfloat h
GLsizei GLsizei GLchar * source
GLdouble GLdouble t
Definition qopenglext.h:243
GLuint64EXT * result
[6]
GLdouble s
[6]
Definition qopenglext.h:235
constexpr decltype(auto) qMakePair(T1 &&value1, T2 &&value2) noexcept(noexcept(std::make_pair(std::forward< T1 >(value1), std::forward< T2 >(value2))))
Definition qpair.h:19
static constexpr To convert(const std::array< Mapping, N > &mapping, From Mapping::*from, To Mapping::*to, From value, To defaultValue)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define QStringLiteral(str)
#define v1
char Char
#define Q_UNUSED(x)
short qint16
Definition qtypes.h:42
int qint32
Definition qtypes.h:44
quint64 qulonglong
Definition qtypes.h:59
unsigned long long quint64
Definition qtypes.h:56
ptrdiff_t qsizetype
Definition qtypes.h:70
long long qint64
Definition qtypes.h:55
double qreal
Definition qtypes.h:92
qint64 qlonglong
Definition qtypes.h:58
QList< int > list
[14]
QStringList keys
obj metaObject() -> className()
QObject::connect nullptr
QReadWriteLock lock
[0]
char * toString(const MyType &t)
[31]
\inmodule QtCore
QObject * cast(QObject *obj) const
bool inherits(const QMetaObject *metaObject) const noexcept
Returns true if the class described by this QMetaObject inherits the type described by metaObject; ot...
static QByteArray normalizedType(const char *type)