Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qvariant.cpp
Go to the documentation of this file.
1// Copyright (C) 2022 The Qt Company Ltd.
2// Copyright (C) 2021 Intel Corporation.
3// Copyright (C) 2015 Olivier Goffart <ogoffart@woboq.com>
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 "qvariant_p.h"
7#include "qbitarray.h"
8#include "qbytearray.h"
9#include "qdatastream.h"
10#include "qdebug.h"
11#include "qmap.h"
12#include "qhash.h"
13#include "qdatetime.h"
14#if QT_CONFIG(easingcurve)
15#include "qeasingcurve.h"
16#endif
17#include "qlist.h"
18#if QT_CONFIG(regularexpression)
19#include "qregularexpression.h"
20#endif
21#include "qstring.h"
22#include "qstringlist.h"
23#include "qurl.h"
24#include "qlocale.h"
25#include "quuid.h"
26#if QT_CONFIG(itemmodel)
27#include "qabstractitemmodel.h"
28#endif
29#ifndef QT_BOOTSTRAPPED
30#include "qcborarray.h"
31#include "qcborcommon.h"
32#include "qcbormap.h"
33#include "qjsonvalue.h"
34#include "qjsonobject.h"
35#include "qjsonarray.h"
36#include "qjsondocument.h"
37#include "qbytearraylist.h"
38#endif
39#include "private/qlocale_p.h"
40#include "qmetatype_p.h"
41#include <qmetaobject.h>
42
43#ifndef QT_NO_GEOM_VARIANT
44#include "qsize.h"
45#include "qpoint.h"
46#include "qrect.h"
47#include "qline.h"
48#endif
49
50#include <memory>
51
52#include <cmath>
53#include <float.h>
54#include <cstring>
55
57
58using namespace Qt::StringLiterals;
59
60namespace { // anonymous used to hide QVariant handlers
61
62static qlonglong qMetaTypeNumberBySize(const QVariant::Private *d)
63{
64 switch (d->typeInterface()->size) {
65 case 1:
66 return d->get<signed char>();
67 case 2:
68 return d->get<short>();
69 case 4:
70 return d->get<int>();
71 case 8:
72 return d->get<qlonglong>();
73 }
74 Q_UNREACHABLE_RETURN(0);
75}
76
77static qlonglong qMetaTypeNumber(const QVariant::Private *d)
78{
79 switch (d->typeInterface()->typeId) {
80 case QMetaType::Int:
81 case QMetaType::LongLong:
82 case QMetaType::Char:
83 case QMetaType::SChar:
84 case QMetaType::Short:
85 case QMetaType::Long:
86 return qMetaTypeNumberBySize(d);
87 case QMetaType::Float:
88 return qRound64(d->get<float>());
89 case QMetaType::Double:
90 return qRound64(d->get<double>());
91#ifndef QT_BOOTSTRAPPED
92 case QMetaType::QJsonValue:
93 return d->get<QJsonValue>().toDouble();
94 case QMetaType::QCborValue:
95 return d->get<QCborValue>().toInteger();
96#endif
97 }
98 Q_UNREACHABLE_RETURN(0);
99}
100
101static qulonglong qMetaTypeUNumber(const QVariant::Private *d)
102{
103 switch (d->typeInterface()->size) {
104 case 1:
105 return d->get<unsigned char>();
106 case 2:
107 return d->get<unsigned short>();
108 case 4:
109 return d->get<unsigned int>();
110 case 8:
111 return d->get<qulonglong>();
112 }
113 Q_UNREACHABLE_RETURN(0);
114}
115
116static std::optional<qlonglong> qConvertToNumber(const QVariant::Private *d, bool allowStringToBool = false)
117{
118 bool ok;
119 switch (d->typeInterface()->typeId) {
120 case QMetaType::QString: {
121 const QString &s = d->get<QString>();
122 if (qlonglong l = s.toLongLong(&ok); ok)
123 return l;
124 if (allowStringToBool) {
125 if (s == "false"_L1 || s == "0"_L1)
126 return 0;
127 if (s == "true"_L1 || s == "1"_L1)
128 return 1;
129 }
130 return std::nullopt;
131 }
132 case QMetaType::QChar:
133 return d->get<QChar>().unicode();
134 case QMetaType::QByteArray:
135 if (qlonglong l = d->get<QByteArray>().toLongLong(&ok); ok)
136 return l;
137 return std::nullopt;
138 case QMetaType::Bool:
139 return qlonglong(d->get<bool>());
140#ifndef QT_BOOTSTRAPPED
141 case QMetaType::QCborValue:
142 if (!d->get<QCborValue>().isInteger() && !d->get<QCborValue>().isDouble())
143 break;
144 return qMetaTypeNumber(d);
145 case QMetaType::QJsonValue:
146 if (!d->get<QJsonValue>().isDouble())
147 break;
149#endif
150 case QMetaType::Double:
151 case QMetaType::Int:
152 case QMetaType::Char:
153 case QMetaType::SChar:
154 case QMetaType::Short:
155 case QMetaType::Long:
156 case QMetaType::Float:
157 case QMetaType::LongLong:
158 return qMetaTypeNumber(d);
159 case QMetaType::ULongLong:
160 case QMetaType::UInt:
161 case QMetaType::UChar:
162 case QMetaType::Char16:
163 case QMetaType::Char32:
164 case QMetaType::UShort:
165 case QMetaType::ULong:
166 return qlonglong(qMetaTypeUNumber(d));
167 }
168
169 if (d->typeInterface()->flags & QMetaType::IsEnumeration
170 || d->typeInterface()->typeId == QMetaType::QCborSimpleType)
171 return qMetaTypeNumberBySize(d);
172
173 return std::nullopt;
174}
175
176static std::optional<double> qConvertToRealNumber(const QVariant::Private *d)
177{
178 bool ok;
179 switch (d->typeInterface()->typeId) {
180 case QMetaType::QString:
181 if (double r = d->get<QString>().toDouble(&ok); ok)
182 return r;
183 return std::nullopt;
184 case QMetaType::Double:
185 return d->get<double>();
186 case QMetaType::Float:
187 return double(d->get<float>());
188 case QMetaType::Float16:
189 return double(d->get<qfloat16>());
190 case QMetaType::ULongLong:
191 case QMetaType::UInt:
192 case QMetaType::UChar:
193 case QMetaType::Char16:
194 case QMetaType::Char32:
195 case QMetaType::UShort:
196 case QMetaType::ULong:
197 return double(qMetaTypeUNumber(d));
198#ifndef QT_BOOTSTRAPPED
199 case QMetaType::QCborValue:
200 return d->get<QCborValue>().toDouble();
201 case QMetaType::QJsonValue:
202 return d->get<QJsonValue>().toDouble();
203#endif
204 default:
205 // includes enum conversion as well as invalid types
206 if (std::optional<qlonglong> l = qConvertToNumber(d))
207 return double(*l);
208 return std::nullopt;
209 }
210}
211
212static bool isValidMetaTypeForVariant(const QtPrivate::QMetaTypeInterface *iface, const void *copy)
213{
214 using namespace QtMetaTypePrivate;
215 if (!iface || iface->size == 0)
216 return false;
217
218 Q_ASSERT(!isInterfaceFor<void>(iface)); // only void should have size 0
219 if (!isCopyConstructible(iface) || !isDestructible(iface)) {
220 // all meta types must be copyable (because QVariant is) and
221 // destructible (because QVariant owns it)
222 qWarning("QVariant: Provided metatype for '%s' does not support destruction and "
223 "copy construction", iface->name);
224 return false;
225 }
226 if (!copy && !isDefaultConstructible(iface)) {
227 // non-default-constructible types are acceptable, but not if you're
228 // asking us to construct from nothing
229 qWarning("QVariant: Cannot create type '%s' without a default constructor", iface->name);
230 return false;
231 }
232
233 return true;
234}
235
236enum CustomConstructMoveOptions {
237 UseCopy, // custom construct uses the copy ctor unconditionally
238 // future option: TryMove: uses move ctor if available, else copy ctor
239 ForceMove, // custom construct use the move ctor (which must exist)
240};
241
242enum CustomConstructNullabilityOption {
243 MaybeNull, // copy might be null, might be non-null
244 NonNull, // copy is guarantueed to be non-null
245 // future option: AlwaysNull?
246};
247
248
249template <typename F> static QVariant::PrivateShared *
250customConstructShared(size_t size, size_t align, F &&construct)
251{
252 struct Deleter {
253 void operator()(QVariant::PrivateShared *p) const
255 };
256
257 // this is exception-safe
258 std::unique_ptr<QVariant::PrivateShared, Deleter> ptr;
260 construct(ptr->data());
261 return ptr.release();
262}
263
264// the type of d has already been set, but other field are not set
265template <CustomConstructMoveOptions moveOption = UseCopy, CustomConstructNullabilityOption nullability = MaybeNull>
266static void customConstruct(const QtPrivate::QMetaTypeInterface *iface, QVariant::Private *d,
267 std::conditional_t<moveOption == ForceMove, void *, const void *> copy)
268{
269 using namespace QtMetaTypePrivate;
270 Q_ASSERT(iface);
271 Q_ASSERT(iface->size);
272 Q_ASSERT(!isInterfaceFor<void>(iface));
274 Q_ASSERT(isDestructible(iface));
276 if constexpr (moveOption == ForceMove)
278 if constexpr (nullability == NonNull)
279 Q_ASSUME(copy != nullptr);
280
281 // need to check for nullptr_t here, as this can get called by fromValue(nullptr). fromValue() uses
282 // std::addressof(value) which in this case returns the address of the nullptr object.
283 // ### Qt 7: remove nullptr_t special casing
284 d->is_null = !copy QT6_ONLY(|| isInterfaceFor<std::nullptr_t>(iface));
285
287 d->is_shared = false;
288 if (!copy && !iface->defaultCtr)
289 return; // trivial default constructor and it's OK to build in 0-filled storage, which we've already done
290 if constexpr (moveOption == ForceMove && nullability == NonNull)
291 moveConstruct(iface, d->data.data, copy);
292 else
293 construct(iface, d->data.data, copy);
294 } else {
295 d->data.shared = customConstructShared(iface->size, iface->alignment, [=](void *where) {
296 if constexpr (moveOption == ForceMove && nullability == NonNull)
297 moveConstruct(iface, where, copy);
298 else
299 construct(iface, where, copy);
300 });
301 d->is_shared = true;
302 }
303}
304
305static void customClear(QVariant::Private *d)
306{
307 const QtPrivate::QMetaTypeInterface *iface = d->typeInterface();
308 if (!iface)
309 return;
310 if (!d->is_shared) {
311 QtMetaTypePrivate::destruct(iface, d->data.data);
312 } else {
313 QtMetaTypePrivate::destruct(iface, d->data.shared->data());
314 QVariant::PrivateShared::free(d->data.shared);
315 }
316}
317
318static QVariant::Private clonePrivate(const QVariant::Private &other)
319{
321 if (d.is_shared) {
322 d.data.shared->ref.ref();
323 } else if (const QtPrivate::QMetaTypeInterface *iface = d.typeInterface()) {
324 Q_ASSERT(d.canUseInternalSpace(iface));
325
326 // if not trivially copyable, ask to copy
327 if (iface->copyCtr)
328 QtMetaTypePrivate::copyConstruct(iface, d.data.data, other.data.data);
329 }
330 return d;
331}
332
333} // anonymous used to hide QVariant handlers
334
521//### Qt 7: Remove in favor of QMetaType overload
522void QVariant::create(int type, const void *copy)
523{
525}
526
534{
535 *this = QVariant(type, copy);
536}
537
545{
546 if (!d.is_shared || !d.data.shared->ref.deref())
547 customClear(&d);
548}
549
558 : d(clonePrivate(p.d))
559{
560}
561
611QVariant::QVariant(std::in_place_t, QMetaType type) : d(type.iface())
612{
613 // we query the metatype instead of detecting it at compile time
614 // so that we can change relocatability of internal types
615 if (!Private::canUseInternalSpace(type.iface())) {
616 d.data.shared = PrivateShared::create(type.sizeOf(), type.alignOf());
617 d.is_shared = true;
618 }
619}
620
627void *QVariant::prepareForEmplace(QMetaType type)
628{
629 /* There are two cases where we can reuse the existing storage
630 (1) The new type fits in QVariant's SBO storage
631 (2) We are using the externally allocated storage, the variant is
632 detached, and the new type fits into the existing storage.
633 In all other cases (3), we cannot reuse the storage.
634 */
635 auto typeFits = [&] {
636 auto newIface = type.iface();
637 auto oldIface = d.typeInterface();
638 auto newSize = PrivateShared::computeAllocationSize(newIface->size, newIface->alignment);
639 auto oldSize = PrivateShared::computeAllocationSize(oldIface->size, oldIface->alignment);
640 return newSize <= oldSize;
641 };
642 if (Private::canUseInternalSpace(type.iface())) { // (1)
643 clear();
644 d.packedType = quintptr(type.iface()) >> 2;
645 return d.data.data;
646 } else if (d.is_shared && isDetached() && typeFits()) { // (2)
648 // compare QVariant::PrivateShared::create
649 const auto ps = d.data.shared;
650 const auto align = type.alignOf();
651 ps->offset = PrivateShared::computeOffset(ps, align);
652 d.packedType = quintptr(type.iface()) >> 2;
653 return ps->data();
654 }
655 // (3)
656 QVariant newVariant(std::in_place, type);
657 swap(newVariant);
658 // const cast is safe, we're in a non-const method
659 return const_cast<void *>(d.storage());
660}
661
943QVariant::QVariant(QMetaType type, const void *copy) : d(type.iface())
944{
945 type.registerType();
946 if (isValidMetaTypeForVariant(type.iface(), copy))
947 customConstruct(type.iface(), &d, copy);
948 else
949 d = {};
950}
951
952QVariant::QVariant(int val) noexcept : d(std::piecewise_construct_t{}, val) {}
953QVariant::QVariant(uint val) noexcept : d(std::piecewise_construct_t{}, val) {}
954QVariant::QVariant(qlonglong val) noexcept : d(std::piecewise_construct_t{}, val) {}
955QVariant::QVariant(qulonglong val) noexcept : d(std::piecewise_construct_t{}, val) {}
956QVariant::QVariant(bool val) noexcept : d(std::piecewise_construct_t{}, val) {}
957QVariant::QVariant(double val) noexcept : d(std::piecewise_construct_t{}, val) {}
958QVariant::QVariant(float val) noexcept : d(std::piecewise_construct_t{}, val) {}
959
960QVariant::QVariant(const QByteArray &val) noexcept : d(std::piecewise_construct_t{}, val) {}
961QVariant::QVariant(const QBitArray &val) noexcept : d(std::piecewise_construct_t{}, val) {}
962QVariant::QVariant(const QString &val) noexcept : d(std::piecewise_construct_t{}, val) {}
963QVariant::QVariant(QChar val) noexcept : d(std::piecewise_construct_t{}, val) {}
964QVariant::QVariant(const QStringList &val) noexcept : d(std::piecewise_construct_t{}, val) {}
965
966QVariant::QVariant(QDate val) noexcept : d(std::piecewise_construct_t{}, val) {}
967QVariant::QVariant(QTime val) noexcept : d(std::piecewise_construct_t{}, val) {}
968QVariant::QVariant(const QDateTime &val) noexcept : d(std::piecewise_construct_t{}, val) {}
969
970QVariant::QVariant(const QList<QVariant> &list) noexcept : d(std::piecewise_construct_t{}, list) {}
971QVariant::QVariant(const QMap<QString, QVariant> &map) noexcept : d(std::piecewise_construct_t{}, map) {}
972QVariant::QVariant(const QHash<QString, QVariant> &hash) noexcept : d(std::piecewise_construct_t{}, hash) {}
973
975
976#if QT_CONFIG(easingcurve)
977QVariant::QVariant(const QEasingCurve &val) : d(std::piecewise_construct_t{}, val) {}
978#endif
979#ifndef QT_NO_GEOM_VARIANT
981 : d(std::piecewise_construct_t{}, pt) {}
982QVariant::QVariant(QPointF pt) noexcept(Private::FitsInInternalSize<sizeof(qreal) * 2>)
983 : d(std::piecewise_construct_t{}, pt) {}
984QVariant::QVariant(QRect r) noexcept(Private::FitsInInternalSize<sizeof(int) * 4>)
985 : d(std::piecewise_construct_t{}, r) {}
986QVariant::QVariant(QRectF r) noexcept(Private::FitsInInternalSize<sizeof(qreal) * 4>)
987 : d(std::piecewise_construct_t{}, r) {}
988QVariant::QVariant(QLine l) noexcept(Private::FitsInInternalSize<sizeof(int) * 4>)
989 : d(std::piecewise_construct_t{}, l) {}
990QVariant::QVariant(QLineF l) noexcept(Private::FitsInInternalSize<sizeof(qreal) * 4>)
991 : d(std::piecewise_construct_t{}, l) {}
993 : d(std::piecewise_construct_t{}, s) {}
994QVariant::QVariant(QSizeF s) noexcept(Private::FitsInInternalSize<sizeof(qreal) * 2>)
995 : d(std::piecewise_construct_t{}, s) {}
996#endif
997#ifndef QT_BOOTSTRAPPED
998QVariant::QVariant(const QUrl &u) noexcept : d(std::piecewise_construct_t{}, u) {}
999#endif
1000QVariant::QVariant(const QLocale &l) noexcept : d(std::piecewise_construct_t{}, l) {}
1001#if QT_CONFIG(regularexpression)
1002QVariant::QVariant(const QRegularExpression &re) noexcept : d(std::piecewise_construct_t{}, re) {}
1003#endif // QT_CONFIG(regularexpression)
1004QVariant::QVariant(QUuid uuid) noexcept(Private::FitsInInternalSize<16>) : d(std::piecewise_construct_t{}, uuid) {}
1005#ifndef QT_BOOTSTRAPPED
1006QVariant::QVariant(const QJsonValue &jsonValue) noexcept(Private::FitsInInternalSize<sizeof(CborValueStandIn)>)
1007 : d(std::piecewise_construct_t{}, jsonValue)
1008{ static_assert(sizeof(CborValueStandIn) == sizeof(QJsonValue)); }
1009QVariant::QVariant(const QJsonObject &jsonObject) noexcept : d(std::piecewise_construct_t{}, jsonObject) {}
1010QVariant::QVariant(const QJsonArray &jsonArray) noexcept : d(std::piecewise_construct_t{}, jsonArray) {}
1011QVariant::QVariant(const QJsonDocument &jsonDocument) : d(std::piecewise_construct_t{}, jsonDocument) {}
1012#endif // QT_BOOTSTRAPPED
1013#if QT_CONFIG(itemmodel)
1014QVariant::QVariant(const QModelIndex &modelIndex) noexcept(Private::FitsInInternalSize<8 + 2 * sizeof(quintptr)>)
1015 : d(std::piecewise_construct_t{}, modelIndex) {}
1016QVariant::QVariant(const QPersistentModelIndex &modelIndex) : d(std::piecewise_construct_t{}, modelIndex) {}
1017#endif
1018
1070{
1071 return d.type();
1072}
1073
1078{
1079 if (this == &variant)
1080 return *this;
1081
1082 clear();
1083 d = clonePrivate(variant.d);
1084 return *this;
1085}
1086
1102{
1103 if (!d.is_shared || d.data.shared->ref.loadRelaxed() == 1)
1104 return;
1105
1106 Q_ASSERT(isValidMetaTypeForVariant(d.typeInterface(), constData()));
1107 Private dd(d.typeInterface());
1108 // null variant is never shared; anything else is NonNull
1109 customConstruct<UseCopy, NonNull>(d.typeInterface(), &dd, constData());
1110 if (!d.data.shared->ref.deref())
1111 customClear(&d);
1112 d.data.shared = dd.data.shared;
1113}
1114
1127const char *QVariant::typeName() const
1128{
1129 return d.type().name();
1130}
1131
1137{
1138 if (!d.is_shared || !d.data.shared->ref.deref())
1139 customClear(&d);
1140 d = {};
1141}
1142
1164#ifndef QT_NO_DATASTREAM
1165enum { MapFromThreeCount = 36 };
1167{
1169 QMetaType::QVariantMap,
1170 QMetaType::QVariantList,
1171 QMetaType::QString,
1172 QMetaType::QStringList,
1173 QMetaType::QFont,
1174 QMetaType::QPixmap,
1175 QMetaType::QBrush,
1176 QMetaType::QRect,
1177 QMetaType::QSize,
1178 QMetaType::QColor,
1179 QMetaType::QPalette,
1180 0, // ColorGroup
1181 QMetaType::QIcon,
1182 QMetaType::QPoint,
1183 QMetaType::QImage,
1184 QMetaType::Int,
1185 QMetaType::UInt,
1186 QMetaType::Bool,
1187 QMetaType::Double,
1188 0, // Buggy ByteArray, QByteArray never had id == 20
1189 QMetaType::QPolygon,
1190 QMetaType::QRegion,
1191 QMetaType::QBitmap,
1192 QMetaType::QCursor,
1193 QMetaType::QSizePolicy,
1194 QMetaType::QDate,
1195 QMetaType::QTime,
1196 QMetaType::QDateTime,
1197 QMetaType::QByteArray,
1198 QMetaType::QBitArray,
1199#if QT_CONFIG(shortcut)
1200 QMetaType::QKeySequence,
1201#else
1202 0, // QKeySequence
1203#endif
1204 QMetaType::QPen,
1205 QMetaType::LongLong,
1206 QMetaType::ULongLong,
1207#if QT_CONFIG(easingcurve)
1208 QMetaType::QEasingCurve
1209#endif
1210};
1211
1212// values needed to map Qt5 based type id's to Qt6 based ones
1213constexpr int Qt5UserType = 1024;
1214constexpr int Qt5LastCoreType = QMetaType::QCborMap;
1215constexpr int Qt5FirstGuiType = 64;
1216constexpr int Qt5LastGuiType = 87;
1217constexpr int Qt5SizePolicy = 121;
1218constexpr int Qt5RegExp = 27;
1219constexpr int Qt5KeySequence = 75;
1220constexpr int Qt5QQuaternion = 85;
1221
1223
1231{
1232 clear();
1233
1235 s >> typeId;
1236 if (s.version() < QDataStream::Qt_4_0) {
1237 // map to Qt 5 ids
1239 return;
1241 } else if (s.version() < QDataStream::Qt_5_0) {
1242 // map to Qt 5 type ids
1243 if (typeId == 127 /* QVariant::UserType */) {
1245 } else if (typeId >= 128 && typeId != Qt5UserType) {
1246 // In Qt4 id == 128 was FirstExtCoreType. In Qt5 ExtCoreTypes set was merged to CoreTypes
1247 // by moving all ids down by 97.
1248 typeId -= 97;
1249 } else if (typeId == 75 /* QSizePolicy */) {
1251 } else if (typeId > 75 && typeId <= 86) {
1252 // and as a result these types received lower ids too
1253 // QKeySequence QPen QTextLength QTextFormat QTransform QMatrix4x4 QVector2D QVector3D QVector4D QQuaternion
1254 typeId -=1;
1255 }
1256 }
1257 if (s.version() < QDataStream::Qt_6_0) {
1258 // map from Qt 5 to Qt 6 values
1259 if (typeId == Qt5UserType) {
1261 } else if (typeId >= Qt5FirstGuiType && typeId <= Qt5LastGuiType) {
1263 } else if (typeId == Qt5SizePolicy) {
1264 typeId = QMetaType::QSizePolicy;
1265 } else if (typeId == Qt5RegExp) {
1266 typeId = QMetaType::fromName("QRegExp").id();
1267 }
1268 }
1269
1270 qint8 is_null = false;
1271 if (s.version() >= QDataStream::Qt_4_2)
1272 s >> is_null;
1273 if (typeId == QMetaType::User) {
1275 s >> name;
1279 qWarning("QVariant::load: unknown user type with name %s.", name.constData());
1280 return;
1281 }
1282 }
1283 create(typeId, nullptr);
1284 d.is_null = is_null;
1285
1286 if (!isValid()) {
1287 if (s.version() < QDataStream::Qt_5_0) {
1288 // Since we wrote something, we should read something
1289 QString x;
1290 s >> x;
1291 }
1292 d.is_null = true;
1293 return;
1294 }
1295
1296 // const cast is safe since we operate on a newly constructed variant
1297 void *data = const_cast<void *>(constData());
1298 if (!d.type().load(s, data)) {
1300 qWarning("QVariant::load: unable to load type %d.", d.type().id());
1301 }
1302}
1303
1311{
1312 quint32 typeId = d.type().id();
1313 bool saveAsUserType = false;
1314 if (typeId >= QMetaType::User) {
1316 saveAsUserType = true;
1317 }
1318 if (s.version() < QDataStream::Qt_6_0) {
1319 // map to Qt 5 values
1320 if (typeId == QMetaType::User) {
1322 if (!strcmp(d.type().name(), "QRegExp")) {
1323 typeId = 27; // QRegExp in Qt 4/5
1324 }
1326 // the type didn't exist in Qt 5
1328 saveAsUserType = true;
1331 if (typeId > Qt5LastGuiType) {
1333 saveAsUserType = true;
1334 }
1335 } else if (typeId == QMetaType::QSizePolicy) {
1337 }
1338 }
1339 if (s.version() < QDataStream::Qt_4_0) {
1340 int i;
1341 for (i = 0; i <= MapFromThreeCount - 1; ++i) {
1342 if (mapIdFromQt3ToCurrent[i] == typeId) {
1343 typeId = i;
1344 break;
1345 }
1346 }
1347 if (i >= MapFromThreeCount) {
1348 s << QVariant();
1349 return;
1350 }
1351 } else if (s.version() < QDataStream::Qt_5_0) {
1352 if (typeId == Qt5UserType) {
1353 typeId = 127; // QVariant::UserType had this value in Qt4
1354 saveAsUserType = true;
1355 } else if (typeId >= 128 - 97 && typeId <= Qt5LastCoreType) {
1356 // In Qt4 id == 128 was FirstExtCoreType. In Qt5 ExtCoreTypes set was merged to CoreTypes
1357 // by moving all ids down by 97.
1358 typeId += 97;
1359 } else if (typeId == Qt5SizePolicy) {
1360 typeId = 75;
1361 } else if (typeId >= Qt5KeySequence && typeId <= Qt5QQuaternion) {
1362 // and as a result these types received lower ids too
1363 typeId += 1;
1364 } else if (typeId > Qt5QQuaternion || typeId == QMetaType::QUuid) {
1365 // These existed in Qt 4 only as a custom type
1366 typeId = 127;
1367 saveAsUserType = true;
1368 }
1369 }
1370 const char *typeName = nullptr;
1371 if (saveAsUserType) {
1372 if (s.version() < QDataStream::Qt_6_0)
1374 if (!typeName)
1375 typeName = d.type().name();
1376 }
1377 s << typeId;
1378 if (s.version() >= QDataStream::Qt_4_2)
1379 s << qint8(d.is_null);
1380 if (typeName)
1381 s << typeName;
1382
1383 if (!isValid()) {
1384 if (s.version() < QDataStream::Qt_5_0)
1385 s << QString();
1386 return;
1387 }
1388
1389 if (!d.type().save(s, constData())) {
1390 qWarning("QVariant::save: unable to save type '%s' (type id: %d).\n",
1391 d.type().name(), d.type().id());
1392 Q_ASSERT_X(false, "QVariant::save", "Invalid type to save");
1393 }
1394}
1395
1416{
1417 p.load(s);
1418 return s;
1419}
1420
1428{
1429 p.save(s);
1430 return s;
1431}
1432
1446#endif //QT_NO_DATASTREAM
1447
1466{
1467 return qvariant_cast<QStringList>(*this);
1468}
1469
1486{
1487 return qvariant_cast<QString>(*this);
1488}
1489
1502{
1503 return qvariant_cast<QVariantMap>(*this);
1504}
1505
1513{
1514 return qvariant_cast<QVariantHash>(*this);
1515}
1516
1530{
1531 return qvariant_cast<QDate>(*this);
1532}
1533
1547{
1548 return qvariant_cast<QTime>(*this);
1549}
1550
1564{
1565 return qvariant_cast<QDateTime>(*this);
1566}
1567
1577#if QT_CONFIG(easingcurve)
1578QEasingCurve QVariant::toEasingCurve() const
1579{
1580 return qvariant_cast<QEasingCurve>(*this);
1581}
1582#endif
1583
1594{
1595 return qvariant_cast<QByteArray>(*this);
1596}
1597
1598#ifndef QT_NO_GEOM_VARIANT
1609{
1610 return qvariant_cast<QPoint>(*this);
1611}
1612
1622{
1623 return qvariant_cast<QRect>(*this);
1624}
1625
1635{
1636 return qvariant_cast<QSize>(*this);
1637}
1638
1648{
1649 return qvariant_cast<QSizeF>(*this);
1650}
1651
1662{
1663 return qvariant_cast<QRectF>(*this);
1664}
1665
1675{
1676 return qvariant_cast<QLineF>(*this);
1677}
1678
1688{
1689 return qvariant_cast<QLine>(*this);
1690}
1691
1702{
1703 return qvariant_cast<QPointF>(*this);
1704}
1705
1706#endif // QT_NO_GEOM_VARIANT
1707
1708#ifndef QT_BOOTSTRAPPED
1718{
1719 return qvariant_cast<QUrl>(*this);
1720}
1721#endif
1722
1732{
1733 return qvariant_cast<QLocale>(*this);
1734}
1735
1736#if QT_CONFIG(regularexpression)
1746QRegularExpression QVariant::toRegularExpression() const
1747{
1748 return qvariant_cast<QRegularExpression>(*this);
1749}
1750#endif // QT_CONFIG(regularexpression)
1751
1752#if QT_CONFIG(itemmodel)
1761QModelIndex QVariant::toModelIndex() const
1762{
1763 return qvariant_cast<QModelIndex>(*this);
1764}
1765
1774QPersistentModelIndex QVariant::toPersistentModelIndex() const
1775{
1776 return qvariant_cast<QPersistentModelIndex>(*this);
1777}
1778#endif // QT_CONFIG(itemmodel)
1779
1790{
1791 return qvariant_cast<QUuid>(*this);
1792}
1793
1794#ifndef QT_BOOTSTRAPPED
1804{
1805 return qvariant_cast<QJsonValue>(*this);
1806}
1807
1817{
1818 return qvariant_cast<QJsonObject>(*this);
1819}
1820
1830{
1831 return qvariant_cast<QJsonArray>(*this);
1832}
1833
1843{
1844 return qvariant_cast<QJsonDocument>(*this);
1845}
1846#endif // QT_BOOTSTRAPPED
1847
1858{
1859 return qvariant_cast<QChar>(*this);
1860}
1861
1869{
1870 return qvariant_cast<QBitArray>(*this);
1871}
1872
1873template <typename T>
1875{
1876 QMetaType t = QMetaType::fromType<T>();
1877 if (ok)
1878 *ok = true;
1879
1880 if (d.type() == t)
1881 return d.get<T>();
1882
1883 T ret = 0;
1884 bool success = QMetaType::convert(d.type(), d.storage(), t, &ret);
1885 if (ok)
1886 *ok = success;
1887 return ret;
1888}
1889
1907int QVariant::toInt(bool *ok) const
1908{
1909 return qNumVariantToHelper<int>(d, ok);
1910}
1911
1930{
1931 return qNumVariantToHelper<uint>(d, ok);
1932}
1933
1947{
1948 return qNumVariantToHelper<qlonglong>(d, ok);
1949}
1950
1964{
1965 return qNumVariantToHelper<qulonglong>(d, ok);
1966}
1967
1981{
1982 auto boolType = QMetaType::fromType<bool>();
1983 if (d.type() == boolType)
1984 return d.get<bool>();
1985
1986 bool res = false;
1987 QMetaType::convert(d.type(), constData(), boolType, &res);
1988 return res;
1989}
1990
2003double QVariant::toDouble(bool *ok) const
2004{
2005 return qNumVariantToHelper<double>(d, ok);
2006}
2007
2022float QVariant::toFloat(bool *ok) const
2023{
2024 return qNumVariantToHelper<float>(d, ok);
2025}
2026
2042{
2043 return qNumVariantToHelper<qreal>(d, ok);
2044}
2045
2058{
2059 return qvariant_cast<QVariantList>(*this);
2060}
2061
2128{
2129 if (d.type() == targetType)
2130 return targetType.isValid();
2131
2132 QVariant oldValue = *this;
2133
2134 clear();
2135 create(targetType, nullptr);
2136 if (!oldValue.canConvert(targetType))
2137 return false;
2138
2139 // Fail if the value is not initialized or was forced null by a previous failed convert.
2140 if (oldValue.d.is_null && oldValue.d.type().id() != QMetaType::Nullptr)
2141 return false;
2142
2143 bool ok = QMetaType::convert(oldValue.d.type(), oldValue.constData(), targetType, data());
2144 d.is_null = !ok;
2145 return ok;
2146}
2147
2153bool QVariant::convert(int type, void *ptr) const
2154{
2156}
2157
2161bool QVariant::view(int type, void *ptr)
2162{
2163 return QMetaType::view(d.type(), data(), QMetaType(type), ptr);
2164}
2165
2214static bool qIsNumericType(uint tp)
2215{
2216 static const qulonglong numericTypeBits =
2217 Q_UINT64_C(1) << QMetaType::QString |
2218 Q_UINT64_C(1) << QMetaType::Bool |
2219 Q_UINT64_C(1) << QMetaType::Double |
2220 Q_UINT64_C(1) << QMetaType::Float |
2221 Q_UINT64_C(1) << QMetaType::Char |
2222 Q_UINT64_C(1) << QMetaType::Char16 |
2223 Q_UINT64_C(1) << QMetaType::Char32 |
2224 Q_UINT64_C(1) << QMetaType::SChar |
2225 Q_UINT64_C(1) << QMetaType::UChar |
2226 Q_UINT64_C(1) << QMetaType::Short |
2227 Q_UINT64_C(1) << QMetaType::UShort |
2228 Q_UINT64_C(1) << QMetaType::Int |
2229 Q_UINT64_C(1) << QMetaType::UInt |
2230 Q_UINT64_C(1) << QMetaType::Long |
2231 Q_UINT64_C(1) << QMetaType::ULong |
2232 Q_UINT64_C(1) << QMetaType::LongLong |
2233 Q_UINT64_C(1) << QMetaType::ULongLong;
2234 return tp < (CHAR_BIT * sizeof numericTypeBits) ? numericTypeBits & (Q_UINT64_C(1) << tp) : false;
2235}
2236
2237static bool qIsFloatingPoint(uint tp)
2238{
2239 return tp == QMetaType::Double || tp == QMetaType::Float || tp == QMetaType::Float16;
2240}
2241
2243 const QtPrivate::QMetaTypeInterface *iface2)
2244{
2245 if (!iface1 || !iface2)
2246 return false;
2247
2248 // We don't need QMetaType::id() here because the type Id is always stored
2249 // directly for all built-in types.
2250 bool isNumeric1 = qIsNumericType(iface1->typeId);
2251 bool isNumeric2 = qIsNumericType(iface2->typeId);
2252
2253 // if they're both numeric (or QString), then they can be compared
2254 if (isNumeric1 && isNumeric2)
2255 return true;
2256
2257 bool isEnum1 = iface1->flags & QMetaType::IsEnumeration;
2258 bool isEnum2 = iface2->flags & QMetaType::IsEnumeration;
2259
2260 // if both are enums, we can only compare if they are the same enum
2261 // (the language does allow comparing two different enum types, but that's
2262 // usually considered poor coding and produces a warning)
2263 if (isEnum1 && isEnum2)
2264 return QMetaType(iface1) == QMetaType(iface2);
2265
2266 // if one is an enum and the other is a numeric, we can compare too
2267 if (isEnum1 && isNumeric2)
2268 return true;
2269 if (isNumeric1 && isEnum2)
2270 return true;
2271
2272 // we need at least one enum and one numeric...
2273 return false;
2274}
2275
2277 const QtPrivate::QMetaTypeInterface *iface2)
2278{
2279 Q_ASSERT(canBeNumericallyCompared(iface1, iface2));
2280
2281 // We don't need QMetaType::id() here because the type Id is always stored
2282 // directly for the types we're comparing against below.
2283 uint t1 = iface1->typeId;
2284 uint t2 = iface2->typeId;
2285
2286 if ((t1 == QMetaType::Bool && t2 == QMetaType::QString) ||
2287 (t2 == QMetaType::Bool && t1 == QMetaType::QString))
2288 return QMetaType::Bool;
2289
2290 // C++ integral ranks: (4.13 Integer conversion rank [conv.rank])
2291 // bool < signed char < short < int < long < long long
2292 // unsigneds have the same rank as their signed counterparts
2293 // C++ integral promotion rules (4.5 Integral Promotions [conv.prom])
2294 // - any type with rank less than int can be converted to int or unsigned int
2295 // 5 Expressions [expr] paragraph 9:
2296 // - if either operand is double, the other shall be converted to double
2297 // - " " float, " " " float
2298 // - if both operands have the same type, no further conversion is needed.
2299 // - if both are signed or if both are unsigned, convert to the one with highest rank
2300 // - if the unsigned has higher or same rank, convert the signed to the unsigned one
2301 // - if the signed can represent all values of the unsigned, convert to the signed
2302 // - otherwise, convert to the unsigned corresponding to the rank of the signed
2303
2304 // floating point: we deviate from the C++ standard by always using qreal
2306 return QMetaType::QReal;
2307
2308 auto isUnsigned = [](uint tp) {
2309 // only types for which sizeof(T) >= sizeof(int); lesser ones promote to int
2310 return tp == QMetaType::ULongLong || tp == QMetaType::ULong ||
2311 tp == QMetaType::UInt || tp == QMetaType::Char32;
2312 };
2313 bool isUnsigned1 = isUnsigned(t1);
2314 bool isUnsigned2 = isUnsigned(t2);
2315
2316 // integral rules:
2317 // 1) if either type is a 64-bit unsigned, compare as 64-bit unsigned
2318 if (isUnsigned1 && iface1->size > sizeof(int))
2319 return QMetaType::ULongLong;
2320 if (isUnsigned2 && iface2->size > sizeof(int))
2321 return QMetaType::ULongLong;
2322
2323 // 2) if either type is 64-bit, compare as 64-bit signed
2324 if (iface1->size > sizeof(int) || iface2->size > sizeof(int))
2325 return QMetaType::LongLong;
2326
2327 // 3) if either type is 32-bit unsigned, compare as 32-bit unsigned
2328 if (isUnsigned1 || isUnsigned2)
2329 return QMetaType::UInt;
2330
2331 // 4) otherwise, just do int promotion
2332 return QMetaType::Int;
2333}
2334
2335template <typename Numeric> static QPartialOrdering spaceShip(Numeric lhs, Numeric rhs)
2336{
2337 if (lhs == rhs)
2339 if constexpr (std::numeric_limits<Numeric>::has_quiet_NaN) {
2340 if (std::isnan(lhs) || std::isnan(rhs))
2342 }
2343
2344 bool smaller;
2345 if constexpr (std::is_same_v<Numeric, QObject *>)
2346 smaller = std::less<QObject *>()(lhs, rhs); // can't use less all the time because of bool
2347 else
2348 smaller = lhs < rhs;
2350}
2351
2353{
2354 // use toLongLong to retrieve the data, it gets us all the bits
2355 std::optional<qlonglong> l1 = qConvertToNumber(d1, promotedType == QMetaType::Bool);
2356 std::optional<qlonglong> l2 = qConvertToNumber(d2, promotedType == QMetaType::Bool);
2357 if (!l1 || !l2)
2359 if (promotedType == QMetaType::UInt)
2360 return spaceShip<uint>(*l1, *l2);
2361 if (promotedType == QMetaType::LongLong)
2362 return spaceShip<qlonglong>(*l1, *l2);
2363 if (promotedType == QMetaType::ULongLong)
2364 return spaceShip<qulonglong>(*l1, *l2);
2365
2366 return spaceShip<int>(*l1, *l2);
2367}
2368
2370{
2371 uint promotedType = numericTypePromotion(d1->typeInterface(), d2->typeInterface());
2372 if (promotedType != QMetaType::QReal)
2373 return integralCompare(promotedType, d1, d2);
2374
2375 // floating point comparison
2376 const auto r1 = qConvertToRealNumber(d1);
2377 const auto r2 = qConvertToRealNumber(d2);
2378 if (!r1 || !r2)
2380 if (*r1 == *r2)
2382
2383 return spaceShip(*r1, *r2);
2384}
2385
2386#ifndef QT_BOOTSTRAPPED
2387static bool qvCanConvertMetaObject(QMetaType fromType, QMetaType toType)
2388{
2389 if ((fromType.flags() & QMetaType::PointerToQObject)
2390 && (toType.flags() & QMetaType::PointerToQObject)) {
2391 const QMetaObject *f = fromType.metaObject();
2392 const QMetaObject *t = toType.metaObject();
2393 return f && t && (f->inherits(t) || t->inherits(f));
2394 }
2395 return false;
2396}
2397
2399{
2400 return spaceShip<QObject *>(d1->get<QObject *>(), d2->get<QObject *>());
2401}
2402#endif
2403
2407bool QVariant::equals(const QVariant &v) const
2408{
2409 auto metatype = d.type();
2410
2411 if (metatype != v.metaType()) {
2412 // try numeric comparisons, with C++ type promotion rules (no conversion)
2413 if (canBeNumericallyCompared(metatype.iface(), v.d.type().iface()))
2415#ifndef QT_BOOTSTRAPPED
2416 // if both types are related pointers to QObjects, check if they point to the same object
2417 if (qvCanConvertMetaObject(metatype, v.metaType()))
2419#endif
2420 return false;
2421 }
2422
2423 // For historical reasons: QVariant() == QVariant()
2424 if (!metatype.isValid())
2425 return true;
2426
2427 return metatype.equals(d.storage(), v.d.storage());
2428}
2429
2453{
2454 QMetaType t = lhs.d.type();
2455 if (t != rhs.d.type()) {
2456 // try numeric comparisons, with C++ type promotion rules (no conversion)
2457 if (canBeNumericallyCompared(lhs.d.type().iface(), rhs.d.type().iface()))
2458 return numericCompare(&lhs.d, &rhs.d);
2459#ifndef QT_BOOTSTRAPPED
2460 if (qvCanConvertMetaObject(lhs.metaType(), rhs.metaType()))
2461 return pointerCompare(&lhs.d, &rhs.d);
2462#endif
2464 }
2465 return t.compare(lhs.constData(), rhs.constData());
2466}
2467
2488{
2489 detach();
2490 // set is_null to false, as the caller is likely to write some data into this variant
2491 d.is_null = false;
2492 return const_cast<void *>(constData());
2493}
2494
2543{
2544 if (d.is_null || !metaType().isValid())
2545 return true;
2547 return d.get<void *>() == nullptr;
2548 return false;
2549}
2550
2551#ifndef QT_NO_DEBUG_STREAM
2552QDebug QVariant::qdebugHelper(QDebug dbg) const
2553{
2554 QDebugStateSaver saver(dbg);
2555 const uint typeId = d.type().id();
2556 dbg.nospace() << "QVariant(";
2558 dbg << d.type().name() << ", ";
2559 bool streamed = d.type().debugStream(dbg, d.storage());
2560 if (!streamed && canConvert<QString>())
2561 dbg << toString();
2562 } else {
2563 dbg << "Invalid";
2564 }
2565 dbg << ')';
2566 return dbg;
2567}
2568
2569QVariant QVariant::moveConstruct(QMetaType type, void *data)
2570{
2571 QVariant var;
2572 var.d = QVariant::Private(type.d_ptr);
2573 customConstruct<ForceMove, NonNull>(type.d_ptr, &var.d, data);
2574 return var;
2575}
2576
2577QVariant QVariant::copyConstruct(QMetaType type, const void *data)
2578{
2579 QVariant var;
2580 var.d = QVariant::Private(type.d_ptr);
2581 customConstruct<UseCopy, NonNull>(type.d_ptr, &var.d, data);
2582 return var;
2583}
2584
2585#if QT_DEPRECATED_SINCE(6, 0)
2588
2589QDebug operator<<(QDebug dbg, const QVariant::Type p)
2590{
2591 QDebugStateSaver saver(dbg);
2592 dbg.nospace() << "QVariant::"
2593 << (int(p) != int(QMetaType::UnknownType)
2594 ? QMetaType(p).name()
2595 : "Invalid");
2596 return dbg;
2597}
2598
2600#endif
2601
2602#endif
2603
2849{
2850 if (type == QMetaType::fromType<QVariant>())
2851 return &value;
2852
2853 if (type == value.metaType())
2854 return value.constData();
2855
2856 if (value.canConvert(type)) {
2857 converted = value;
2858 if (converted.convert(type))
2859 return converted.constData();
2860 }
2861
2862 return nullptr;
2863}
2864
2869{
2870 if (const void *result = convert(value, type))
2871 return result;
2872
2873 converted = QVariant(type);
2874 return converted.constData();
2875}
2876
2947 : m_variant(std::move(variant))
2948{
2949}
2950
2955{
2956 return m_variant;
2957}
2958
2964{
2965 return &m_variant;
2966}
2967
\inmodule QtCore
Definition qbitarray.h:13
\inmodule QtCore
Definition qbytearray.h:57
qlonglong toLongLong(bool *ok=nullptr, int base=10) const
Returns the byte array converted to a {long long} using base base, which is ten by default.
\inmodule QtCore\reentrant
Definition qcborvalue.h:50
bool isDouble() const
Returns true if this QCborValue is of the floating-point type.
Definition qcborvalue.h:169
bool isInteger() const
Returns true if this QCborValue is of the integer type.
Definition qcborvalue.h:158
\inmodule QtCore
Definition qchar.h:48
\inmodule QtCore\reentrant
Definition qdatastream.h:30
\inmodule QtCore\reentrant
Definition qdatetime.h:257
\inmodule QtCore \reentrant
Definition qdatetime.h:27
\inmodule QtCore
\inmodule QtCore
\inmodule QtCore
\inmodule QtCore
Definition qhash.h:818
\inmodule QtCore\reentrant
Definition qjsonarray.h:18
\inmodule QtCore\reentrant
\inmodule QtCore\reentrant
Definition qjsonobject.h:20
\inmodule QtCore\reentrant
Definition qjsonvalue.h:24
bool isDouble() const
Returns true if the value contains a double.
Definition qjsonvalue.h:73
\inmodule QtCore
Definition qline.h:182
\inmodule QtCore
Definition qline.h:18
Definition qlist.h:74
Definition qmap.h:186
\inmodule QtCore
Definition qmetatype.h:320
constexpr TypeFlags flags() const
Definition qmetatype.h:2628
const QtPrivate::QMetaTypeInterface * iface() const
Definition qmetatype.h:750
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.
static QMetaType fromName(QByteArrayView name)
Returns a QMetaType matching typeName.
bool isValid() const
int id(int=0) const
Definition qmetatype.h:454
@ PointerToQObject
Definition qmetatype.h:385
@ IsEnumeration
Definition qmetatype.h:386
constexpr const QMetaObject * metaObject() const
Definition qmetatype.h:2633
constexpr const char * name() const
Definition qmetatype.h:2650
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.
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.
\inmodule QtCore
\inmodule QtCore
Definition qobject.h:90
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
\inmodule QtCore\reentrant
Definition qpoint.h:23
\inmodule QtCore\reentrant
Definition qrect.h:483
\inmodule QtCore\reentrant
Definition qrect.h:30
\inmodule QtCore \reentrant
\inmodule QtCore
Definition qsize.h:207
\inmodule QtCore
Definition qsize.h:25
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
double toDouble(bool *ok=nullptr) const
Returns the string converted to a double value.
Definition qstring.cpp:7642
\inmodule QtCore \reentrant
Definition qdatetime.h:189
\inmodule QtCore
Definition qurl.h:94
\inmodule QtCore
Definition quuid.h:31
QVariantConstPointer(QVariant variant)
Constructs a QVariantConstPointer from a variant.
const QVariant * operator->() const
Returns a const pointer to the QVariant, conforming to the conventions for operator->().
QVariant operator*() const
Dereferences the QVariantConstPointer to retrieve its internal QVariant.
\inmodule QtCore
Definition qvariant.h:64
QChar toChar() const
Returns the variant as a QChar if the variant has userType() \l QMetaType::QChar, \l QMetaType::Int,...
void * data()
Returns a pointer to the contained object as a generic void* that can be written to.
bool convert(QMetaType type)
Casts the variant to the requested type, targetType.
QVariant() noexcept
Constructs an invalid variant.
Definition qvariant.h:217
QDataStream & operator<<(QDataStream &s, const QVariant &p)
Writes a variant p to the stream s.
void clear()
Convert this variant to type QMetaType::UnknownType and free up any resources used.
QPointF toPointF() const
Returns the variant as a QPointF if the variant has userType() \l QMetaType::QPoint or \l QMetaType::...
T view()
Returns a mutable view of template type {T} on the stored value.
Definition qvariant.h:515
static QPartialOrdering compare(const QVariant &lhs, const QVariant &rhs)
Compares the objects at lhs and rhs for ordering.
bool isDetached() const
Definition qvariant.h:738
qreal toReal(bool *ok=nullptr) const
Returns the variant as a qreal if the variant has userType() \l QMetaType::Double,...
QDateTime toDateTime() const
Returns the variant as a QDateTime if the variant has userType() \l QMetaType::QDateTime,...
void swap(QVariant &other) noexcept
Definition qvariant.h:334
bool isValid() const
Returns true if the storage type of this variant is not QMetaType::UnknownType; otherwise returns fal...
Definition qvariant.h:707
QJsonValue toJsonValue() const
double toDouble(bool *ok=nullptr) const
Returns the variant as a double if the variant has userType() \l QMetaType::Double,...
QList< QVariant > toList() const
Returns the variant as a QVariantList if the variant has userType() \l QMetaType::QVariantList.
QMap< QString, QVariant > toMap() const
Returns the variant as a QVariantMap if the variant has type() \l QMetaType::QVariantMap.
qlonglong toLongLong(bool *ok=nullptr) const
Returns the variant as a long long int if the variant has userType() \l QMetaType::LongLong,...
QPoint toPoint() const
Returns the variant as a QPoint if the variant has userType() \l QMetaType::QPoint or \l QMetaType::Q...
int toInt(bool *ok=nullptr) const
Returns the variant as an int if the variant has userType() \l QMetaType::Int, \l QMetaType::Bool,...
QLocale toLocale() const
Returns the variant as a QLocale if the variant has userType() \l QMetaType::QLocale; otherwise retur...
QSize toSize() const
Returns the variant as a QSize if the variant has userType() \l QMetaType::QSize; otherwise returns a...
void save(QDataStream &ds) const
Internal function for saving a variant to the stream s.
QTime toTime() const
Returns the variant as a QTime if the variant has userType() \l QMetaType::QTime, \l QMetaType::QDate...
float toFloat(bool *ok=nullptr) const
Returns the variant as a float if the variant has userType() \l QMetaType::Double,...
uint toUInt(bool *ok=nullptr) const
Returns the variant as an unsigned int if the variant has userType() \l QMetaType::UInt,...
QString toString() const
Returns the variant as a QString if the variant has a userType() including, but not limited to:
void load(QDataStream &ds)
Internal function for loading a variant from stream s.
bool toBool() const
Returns the variant as a bool if the variant has userType() Bool.
QBitArray toBitArray() const
Returns the variant as a QBitArray if the variant has userType() \l QMetaType::QBitArray; otherwise r...
QJsonArray toJsonArray() const
QHash< QString, QVariant > toHash() const
Returns the variant as a QHash<QString, QVariant> if the variant has type() \l QMetaType::QVariantHas...
int typeId() const
Returns the storage type of the value stored in the variant.
Definition qvariant.h:337
bool isNull() const
Returns true if this is a null variant, false otherwise.
const char * typeName() const
Returns the name of the type stored in the variant.
QJsonDocument toJsonDocument() const
QRectF toRectF() const
Returns the variant as a QRectF if the variant has userType() \l QMetaType::QRect or \l QMetaType::QR...
QLineF toLineF() const
Returns the variant as a QLineF if the variant has userType() \l QMetaType::QLineF; otherwise returns...
void detach()
QVariant & operator=(const QVariant &other)
Move-assigns other to this QVariant instance.
QJsonObject toJsonObject() const
bool canConvert(QMetaType targetType) const
Definition qvariant.h:342
QRect toRect() const
Returns the variant as a QRect if the variant has userType() \l QMetaType::QRect; otherwise returns a...
QSizeF toSizeF() const
Returns the variant as a QSizeF if the variant has userType() \l QMetaType::QSizeF; otherwise returns...
QUuid toUuid() const
QDate toDate() const
Returns the variant as a QDate if the variant has userType() \l QMetaType::QDate, \l QMetaType::QDate...
QByteArray toByteArray() const
Returns the variant as a QByteArray if the variant has userType() \l QMetaType::QByteArray or \l QMet...
QLine toLine() const
Returns the variant as a QLine if the variant has userType() \l QMetaType::QLine; otherwise returns a...
Private d
Definition qvariant.h:665
~QVariant()
Destroys the QVariant and the contained object.
Definition qvariant.cpp:544
QDataStream & operator>>(QDataStream &s, QVariant &p)
void create(int type, const void *copy)
Definition qvariant.cpp:522
QMetaType metaType() const
qulonglong toULongLong(bool *ok=nullptr) const
Returns the variant as an unsigned long long int if the variant has type() \l QMetaType::ULongLong,...
const void * constData() const
Definition qvariant.h:446
QStringList toStringList() const
Returns the variant as a QStringList if the variant has userType() \l QMetaType::QStringList,...
QUrl toUrl() const
Returns the variant as a QUrl if the variant has userType() \l QMetaType::QUrl; otherwise returns an ...
bool equals(const QVariant &other) const
QMTI_MUTABLE QBasicAtomicInt typeId
Definition qmetatype.h:260
const void * coerce(const QVariant &value, const QMetaType &type)
const void * convert(const QVariant &value, const QMetaType &type)
\keyword 16-bit Floating Point Support\inmodule QtCore \inheaderfile QFloat16
Definition qfloat16.h:46
QHash< int, QWidget * > hash
[35multi]
QMap< QString, QString > map
[6]
Combined button and popup list for selecting options.
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
void copyConstruct(const QtPrivate::QMetaTypeInterface *iface, void *where, const void *copy)
void destruct(const QtPrivate::QMetaTypeInterface *iface, void *where)
void construct(const QtPrivate::QMetaTypeInterface *iface, void *where, const void *copy)
void moveConstruct(const QtPrivate::QMetaTypeInterface *iface, void *where, void *copy)
const char * typedefNameForType(const QtPrivate::QMetaTypeInterface *type_d)
constexpr QBindableInterface iface
Definition qproperty.h:664
static jboolean copy(JNIEnv *, jobject)
#define Q_FALLTHROUGH()
#define QT_WARNING_POP
#define QT_WARNING_DISABLE_DEPRECATED
#define QT_WARNING_PUSH
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
qint64 qRound64(qfloat16 d) noexcept
Definition qfloat16.h:284
#define qWarning
Definition qlogging.h:162
return ret
static ControlElement< T > * ptr(QWidget *widget)
GLsizei const GLfloat * v
[13]
GLint GLint GLint GLint GLint x
[0]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLboolean r
[2]
GLfloat GLfloat f
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat t1
[4]
GLenum type
GLbitfield flags
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLuint name
GLuint res
GLuint GLfloat * val
GLdouble GLdouble t
Definition qopenglext.h:243
GLuint64EXT * result
[6]
GLdouble s
[6]
Definition qopenglext.h:235
GLfloat GLfloat p
[1]
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 Q_ASSERT_X(cond, x, msg)
Definition qrandom.cpp:48
QT_BEGIN_NAMESPACE class QT6_ONLY(Q_CORE_EXPORT) QReadWriteLock
#define t2
constexpr std::underlying_type_t< Enum > qToUnderlying(Enum e) noexcept
#define Q_UINT64_C(c)
Definition qtypes.h:53
unsigned int quint32
Definition qtypes.h:45
size_t quintptr
Definition qtypes.h:72
quint64 qulonglong
Definition qtypes.h:59
unsigned int uint
Definition qtypes.h:29
unsigned short ushort
Definition qtypes.h:28
QT_BEGIN_NAMESPACE typedef signed char qint8
Definition qtypes.h:40
double qreal
Definition qtypes.h:92
qint64 qlonglong
Definition qtypes.h:58
static double toDouble(Value v)
constexpr int Qt6ToQt5GuiTypeDelta
static QPartialOrdering spaceShip(Numeric lhs, Numeric rhs)
static bool qIsFloatingPoint(uint tp)
static QPartialOrdering numericCompare(const QVariant::Private *d1, const QVariant::Private *d2)
constexpr int Qt5QQuaternion
static bool qIsNumericType(uint tp)
static bool canBeNumericallyCompared(const QtPrivate::QMetaTypeInterface *iface1, const QtPrivate::QMetaTypeInterface *iface2)
constexpr int Qt5KeySequence
@ MapFromThreeCount
static const ushort mapIdFromQt3ToCurrent[MapFromThreeCount]
static QPartialOrdering integralCompare(uint promotedType, const QVariant::Private *d1, const QVariant::Private *d2)
constexpr int Qt5LastCoreType
T qNumVariantToHelper(const QVariant::Private &d, bool *ok)
constexpr int Qt5FirstGuiType
static bool qvCanConvertMetaObject(QMetaType fromType, QMetaType toType)
constexpr int Qt5RegExp
constexpr int Qt5LastGuiType
static int numericTypePromotion(const QtPrivate::QMetaTypeInterface *iface1, const QtPrivate::QMetaTypeInterface *iface2)
constexpr int Qt5SizePolicy
constexpr int Qt5UserType
static QPartialOrdering pointerCompare(const QVariant::Private *d1, const QVariant::Private *d2)
static QT_BEGIN_NAMESPACE QVariant::PrivateShared * customConstructShared(size_t size, size_t align, F &&construct)
Definition qvariant_p.h:23
QList< int > list
[14]
QDataStream & operator<<(QDataStream &out, const MyClass &myObj)
[4]
QVariant variant
[1]
v canConvert< QString >()
QDate d1(1995, 5, 17)
[0]
QDate d2(1995, 5, 20)
QRect r1(100, 200, 11, 16)
[0]
QRect r2(QPoint(100, 200), QSize(11, 16))
QSharedPointer< T > other(t)
[5]
view create()
\inmodule QtCore
static void free(PrivateShared *p)
Definition qvariant_p.h:64
static PrivateShared * create(size_t size, size_t align)
Definition qvariant_p.h:55
static size_t computeAllocationSize(size_t size, size_t align)
Definition qvariant_p.h:42
static int computeOffset(PrivateShared *ps, size_t align)
Definition qvariant_p.h:37
static constexpr bool canUseInternalSpace(const QtPrivate::QMetaTypeInterface *type)
Definition qvariant.h:102
const void * storage() const
Definition qvariant.h:123
quintptr is_shared
Definition qvariant.h:115
const T & get() const
Definition qvariant.h:127
quintptr packedType
Definition qvariant.h:117
const QtPrivate::QMetaTypeInterface * typeInterface() const
Definition qvariant.h:130
quintptr is_null
Definition qvariant.h:116
uchar data[MaxInternalSize]
Definition qvariant.h:111
QMetaType type() const
Definition qvariant.h:135