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
56QT_BEGIN_NAMESPACE
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(f: d->get<float>());
89 case QMetaType::Double:
90 return qRound64(d: 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); 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); 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;
148 Q_FALLTHROUGH();
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); 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(msg: "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(msg: "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// the type of d has already been set, but other field are not set
249template <CustomConstructMoveOptions moveOption = UseCopy, CustomConstructNullabilityOption nullability = MaybeNull>
250static void customConstruct(const QtPrivate::QMetaTypeInterface *iface, QVariant::Private *d,
251 std::conditional_t<moveOption == ForceMove, void *, const void *> copy)
252{
253 using namespace QtMetaTypePrivate;
254 Q_ASSERT(iface);
255 Q_ASSERT(iface->size);
256 Q_ASSERT(!isInterfaceFor<void>(iface));
257 Q_ASSERT(isCopyConstructible(iface));
258 Q_ASSERT(isDestructible(iface));
259 Q_ASSERT(copy || isDefaultConstructible(iface));
260 if constexpr (moveOption == ForceMove)
261 Q_ASSERT(isMoveConstructible(iface));
262 if constexpr (nullability == NonNull)
263 Q_ASSERT(copy != nullptr);
264
265 // need to check for nullptr_t here, as this can get called by fromValue(nullptr). fromValue() uses
266 // std::addressof(value) which in this case returns the address of the nullptr object.
267 // ### Qt 7: remove nullptr_t special casing
268 d->is_null = !copy QT6_ONLY(|| isInterfaceFor<std::nullptr_t>(iface));
269
270 if (QVariant::Private::canUseInternalSpace(type: iface)) {
271 d->is_shared = false;
272 if (!copy && !iface->defaultCtr)
273 return; // trivial default constructor and it's OK to build in 0-filled storage, which we've already done
274 if constexpr (moveOption == ForceMove && nullability == NonNull)
275 moveConstruct(iface, d->data.data, copy);
276 else
277 construct(iface, d->data.data, copy);
278 } else {
279 d->data.shared = customConstructShared(iface->size, iface->alignment, [=](void *where) {
280 if constexpr (moveOption == ForceMove && nullability == NonNull)
281 moveConstruct(iface, where, copy);
282 else
283 construct(iface, where, copy);
284 });
285 d->is_shared = true;
286 }
287}
288
289static void customClear(QVariant::Private *d)
290{
291 const QtPrivate::QMetaTypeInterface *iface = d->typeInterface();
292 if (!iface)
293 return;
294 if (!d->is_shared) {
295 QtMetaTypePrivate::destruct(iface, where: d->data.data);
296 } else {
297 QtMetaTypePrivate::destruct(iface, where: d->data.shared->data());
298 QVariant::PrivateShared::free(p: d->data.shared);
299 }
300}
301
302static QVariant::Private clonePrivate(const QVariant::Private &other)
303{
304 QVariant::Private d = other;
305 if (d.is_shared) {
306 d.data.shared->ref.ref();
307 } else if (const QtPrivate::QMetaTypeInterface *iface = d.typeInterface()) {
308 Q_ASSERT(d.canUseInternalSpace(iface));
309
310 // if not trivially copyable, ask to copy
311 if (iface->copyCtr)
312 QtMetaTypePrivate::copyConstruct(iface, where: d.data.data, copy: other.data.data);
313 }
314 return d;
315}
316
317} // anonymous used to hide QVariant handlers
318
319/*!
320 \class QVariant
321 \inmodule QtCore
322 \brief The QVariant class acts like a union for the most common Qt data types.
323
324 \ingroup objectmodel
325 \ingroup shared
326
327 \compares equality
328
329 Because C++ forbids unions from including types that have
330 non-default constructors or destructors, most interesting Qt
331 classes cannot be used in unions. Without QVariant, this would be
332 a problem for QObject::property() and for database work, etc.
333
334 A QVariant object holds a single value of a single typeId() at a
335 time. (Some types are multi-valued, for example a string list.)
336 You can find out what type, T, the variant holds, convert it to a
337 different type using convert(), get its value using one of the
338 toT() functions (e.g., toSize()), and check whether the type can
339 be converted to a particular type using canConvert().
340
341 The methods named toT() (e.g., toInt(), toString()) are const. If
342 you ask for the stored type, they return a copy of the stored
343 object. If you ask for a type that can be generated from the
344 stored type, toT() copies and converts and leaves the object
345 itself unchanged. If you ask for a type that cannot be generated
346 from the stored type, the result depends on the type; see the
347 function documentation for details.
348
349 Here is some example code to demonstrate the use of QVariant:
350
351 \snippet code/src_corelib_kernel_qvariant.cpp 0
352
353 You can even store QList<QVariant> and QMap<QString, QVariant>
354 values in a variant, so you can easily construct arbitrarily
355 complex data structures of arbitrary types. This is very powerful
356 and versatile, but may prove less memory and speed efficient than
357 storing specific types in standard data structures.
358
359 QVariant also supports the notion of null values. A variant is null
360 if the variant contains no initialized value, or contains a null pointer.
361
362 \snippet code/src_corelib_kernel_qvariant.cpp 1
363
364 QVariant can be extended to support other types than those
365 mentioned in the \l QMetaType::Type enum.
366 See \l{Creating Custom Qt Types}{Creating Custom Qt Types} for details.
367
368 \section1 A Note on GUI Types
369
370 Because QVariant is part of the Qt Core module, it cannot provide
371 conversion functions to data types defined in Qt GUI, such as
372 QColor, QImage, and QPixmap. In other words, there is no \c
373 toColor() function. Instead, you can use the QVariant::value() or
374 the qvariant_cast() template function. For example:
375
376 \snippet code/src_corelib_kernel_qvariant.cpp 2
377
378 The inverse conversion (e.g., from QColor to QVariant) is
379 automatic for all data types supported by QVariant, including
380 GUI-related types:
381
382 \snippet code/src_corelib_kernel_qvariant.cpp 3
383
384 \section1 Using canConvert() and convert() Consecutively
385
386 When using canConvert() and convert() consecutively, it is possible for
387 canConvert() to return true, but convert() to return false. This
388 is typically because canConvert() only reports the general ability of
389 QVariant to convert between types given suitable data; it is still
390 possible to supply data which cannot actually be converted.
391
392 For example, \c{canConvert(QMetaType::fromType<int>())} would return true
393 when called on a variant containing a string because, in principle,
394 QVariant is able to convert strings of numbers to integers.
395 However, if the string contains non-numeric characters, it cannot be
396 converted to an integer, and any attempt to convert it will fail.
397 Hence, it is important to have both functions return true for a
398 successful conversion.
399
400 \sa QMetaType
401*/
402
403/*!
404 \deprecated Use \l QMetaType::Type instead.
405 \enum QVariant::Type
406
407 This enum type defines the types of variable that a QVariant can
408 contain.
409
410 \value Invalid no type
411 \value BitArray a QBitArray
412 \value Bitmap a QBitmap
413 \value Bool a bool
414 \value Brush a QBrush
415 \value ByteArray a QByteArray
416 \value Char a QChar
417 \value Color a QColor
418 \value Cursor a QCursor
419 \value Date a QDate
420 \value DateTime a QDateTime
421 \value Double a double
422 \value EasingCurve a QEasingCurve
423 \value Uuid a QUuid
424 \value ModelIndex a QModelIndex
425 \value [since 5.5] PersistentModelIndex a QPersistentModelIndex
426 \value Font a QFont
427 \value Hash a QVariantHash
428 \value Icon a QIcon
429 \value Image a QImage
430 \value Int an int
431 \value KeySequence a QKeySequence
432 \value Line a QLine
433 \value LineF a QLineF
434 \value List a QVariantList
435 \value Locale a QLocale
436 \value LongLong a \l qlonglong
437 \value Map a QVariantMap
438 \value Transform a QTransform
439 \value Matrix4x4 a QMatrix4x4
440 \value Palette a QPalette
441 \value Pen a QPen
442 \value Pixmap a QPixmap
443 \value Point a QPoint
444 \value PointF a QPointF
445 \value Polygon a QPolygon
446 \value PolygonF a QPolygonF
447 \value Quaternion a QQuaternion
448 \value Rect a QRect
449 \value RectF a QRectF
450 \value RegularExpression a QRegularExpression
451 \value Region a QRegion
452 \value Size a QSize
453 \value SizeF a QSizeF
454 \value SizePolicy a QSizePolicy
455 \value String a QString
456 \value StringList a QStringList
457 \value TextFormat a QTextFormat
458 \value TextLength a QTextLength
459 \value Time a QTime
460 \value UInt a \l uint
461 \value ULongLong a \l qulonglong
462 \value Url a QUrl
463 \value Vector2D a QVector2D
464 \value Vector3D a QVector3D
465 \value Vector4D a QVector4D
466
467 \value UserType Base value for user-defined types.
468
469 \omitvalue LastGuiType
470 \omitvalue LastCoreType
471 \omitvalue LastType
472*/
473
474/*!
475 \fn QVariant::QVariant(QVariant &&other)
476
477 Move-constructs a QVariant instance, making it point at the same
478 object that \a other was pointing to.
479
480 \since 5.2
481*/
482
483/*!
484 \fn QVariant &QVariant::operator=(QVariant &&other)
485
486 Move-assigns \a other to this QVariant instance.
487
488 \since 5.2
489*/
490
491/*!
492 \fn QVariant::QVariant()
493
494 Constructs an invalid variant.
495*/
496
497/*!
498 \fn QVariant::create(int type, const void *copy)
499
500 \internal
501
502 Constructs a variant private of type \a type, and initializes with \a copy if
503 \a copy is not \nullptr.
504
505*/
506//### Qt 7: Remove in favor of QMetaType overload
507void QVariant::create(int type, const void *copy)
508{
509 create(type: QMetaType(type), copy);
510}
511
512/*!
513 \fn QVariant::create(int type, const void *copy)
514
515 \internal
516 \overload
517*/
518void QVariant::create(QMetaType type, const void *copy)
519{
520 *this = QVariant::fromMetaType(type, copy);
521}
522
523/*!
524 \fn QVariant::~QVariant()
525
526 Destroys the QVariant and the contained object.
527*/
528
529QVariant::~QVariant()
530{
531 if (!d.is_shared || !d.data.shared->ref.deref())
532 customClear(d: &d);
533}
534
535/*!
536 \fn QVariant::QVariant(const QVariant &p)
537
538 Constructs a copy of the variant, \a p, passed as the argument to
539 this constructor.
540*/
541
542QVariant::QVariant(const QVariant &p)
543 : d(clonePrivate(other: p.d))
544{
545}
546
547/*!
548 \fn template <typename T, typename... Args, QVariant::if_constructible<T, Args...> = true> QVariant::QVariant(std::in_place_type_t<T>, Args&&... args) noexcept(is_noexcept_constructible<q20::remove_cvref_t<T>, Args...>::value)
549
550 \since 6.6
551 Constructs a new variant containing a value of type \c T. The contained
552 value is is initialized with the arguments
553 \c{std::forward<Args>(args)...}.
554
555 This overload only participates in overload resolution if \c T can be
556 constructed from \a args.
557
558 This constructor is provided for STL/std::any compatibility.
559
560 \overload
561 */
562
563/*!
564
565 \fn template <typename T, typename U, typename... Args, QVariant::if_constructible<T, std::initializer_list<U> &, Args...> = true> explicit QVariant::QVariant(std::in_place_type_t<T>, std::initializer_list<U> il, Args&&... args) noexcept(is_noexcept_constructible<q20::remove_cvref_t<T>, std::initializer_list<U> &, Args... >::value)
566
567 \since 6.6
568 \overload
569 This overload exists to support types with constructors taking an
570 \c initializer_list. It behaves otherwise equivalent to the
571 non-initializer list \c{in_place_type_t} overload.
572*/
573
574
575/*!
576 \fn template <typename T, typename... Args, QVariant::if_constructible<T, Args...> = true> QVariant::emplace(Args&&... args)
577
578 \since 6.6
579 Replaces the object currently held in \c{*this} with an object of
580 type \c{T}, constructed from \a{args}\c{...}. If \c{*this} was non-null,
581 the previously held object is destroyed first.
582 If possible, this method will reuse memory allocated by the QVariant.
583 Returns a reference to the newly-created object.
584 */
585
586/*!
587 \fn template <typename T, typename U, typename... Args, QVariant::if_constructible<T, std::initializer_list<U> &, Args...> = true> QVariant::emplace(std::initializer_list<U> list, Args&&... args)
588
589 \since 6.6
590 \overload
591 This overload exists to support types with constructors taking an
592 \c initializer_list. It behaves otherwise equivalent to the
593 non-initializer list overload.
594*/
595
596QVariant::QVariant(std::in_place_t, QMetaType type) : d(type.iface())
597{
598 // we query the metatype instead of detecting it at compile time
599 // so that we can change relocatability of internal types
600 if (!Private::canUseInternalSpace(type: type.iface())) {
601 d.data.shared = PrivateShared::create(size: type.sizeOf(), align: type.alignOf());
602 d.is_shared = true;
603 }
604}
605
606/*!
607 \internal
608 Returns a pointer to data suitable for placement new
609 of an object of type \a type
610 Changes the variant's metatype to \a type
611 */
612void *QVariant::prepareForEmplace(QMetaType type)
613{
614 /* There are two cases where we can reuse the existing storage
615 (1) The new type fits in QVariant's SBO storage
616 (2) We are using the externally allocated storage, the variant is
617 detached, and the new type fits into the existing storage.
618 In all other cases (3), we cannot reuse the storage.
619 */
620 auto typeFits = [&] {
621 auto newIface = type.iface();
622 auto oldIface = d.typeInterface();
623 auto newSize = PrivateShared::computeAllocationSize(size: newIface->size, align: newIface->alignment);
624 auto oldSize = PrivateShared::computeAllocationSize(size: oldIface->size, align: oldIface->alignment);
625 return newSize <= oldSize;
626 };
627 if (Private::canUseInternalSpace(type: type.iface())) { // (1)
628 clear();
629 d.packedType = quintptr(type.iface()) >> 2;
630 return d.data.data;
631 } else if (d.is_shared && isDetached() && typeFits()) { // (2)
632 QtMetaTypePrivate::destruct(iface: d.typeInterface(), where: d.data.shared->data());
633 // compare QVariant::PrivateShared::create
634 const auto ps = d.data.shared;
635 const auto align = type.alignOf();
636 ps->offset = PrivateShared::computeOffset(ps, align);
637 d.packedType = quintptr(type.iface()) >> 2;
638 return ps->data();
639 }
640 // (3)
641 QVariant newVariant(std::in_place, type);
642 swap(other&: newVariant);
643 // const cast is safe, we're in a non-const method
644 return const_cast<void *>(d.storage());
645}
646
647/*!
648 \fn QVariant::QVariant(const QString &val) noexcept
649
650 Constructs a new variant with a string value, \a val.
651*/
652
653/*!
654 \fn QVariant::QVariant(QLatin1StringView val)
655
656 Constructs a new variant with a QString value from the Latin-1
657 string viewed by \a val.
658*/
659
660/*!
661 \fn QVariant::QVariant(const char *val)
662
663 Constructs a new variant with a string value of \a val.
664 The variant creates a deep copy of \a val into a QString assuming
665 UTF-8 encoding on the input \a val.
666
667 Note that \a val is converted to a QString for storing in the
668 variant and QVariant::userType() will return QMetaType::QString for
669 the variant.
670
671 You can disable this operator by defining \c
672 QT_NO_CAST_FROM_ASCII when you compile your applications.
673*/
674
675/*!
676 \fn QVariant::QVariant(const QStringList &val) noexcept
677
678 Constructs a new variant with a string list value, \a val.
679*/
680
681/*!
682 \fn QVariant::QVariant(const QMap<QString, QVariant> &val) noexcept
683
684 Constructs a new variant with a map of \l {QVariant}s, \a val.
685*/
686
687/*!
688 \fn QVariant::QVariant(const QHash<QString, QVariant> &val) noexcept
689
690 Constructs a new variant with a hash of \l {QVariant}s, \a val.
691*/
692
693/*!
694 \fn QVariant::QVariant(QDate val) noexcept
695
696 Constructs a new variant with a date value, \a val.
697*/
698
699/*!
700 \fn QVariant::QVariant(QTime val) noexcept
701
702 Constructs a new variant with a time value, \a val.
703*/
704
705/*!
706 \fn QVariant::QVariant(const QDateTime &val) noexcept
707
708 Constructs a new variant with a date/time value, \a val.
709*/
710
711/*!
712 \since 4.7
713 \fn QVariant::QVariant(const QEasingCurve &val)
714
715 Constructs a new variant with an easing curve value, \a val.
716*/
717
718/*!
719 \since 5.0
720 \fn QVariant::QVariant(QUuid val) noexcept
721
722 Constructs a new variant with an uuid value, \a val.
723*/
724
725/*!
726 \since 5.0
727 \fn QVariant::QVariant(const QModelIndex &val) noexcept
728
729 Constructs a new variant with a QModelIndex value, \a val.
730*/
731
732/*!
733 \since 5.5
734 \fn QVariant::QVariant(const QPersistentModelIndex &val)
735
736 Constructs a new variant with a QPersistentModelIndex value, \a val.
737*/
738
739/*!
740 \since 5.0
741 \fn QVariant::QVariant(const QJsonValue &val)
742
743 Constructs a new variant with a json value, \a val.
744*/
745
746/*!
747 \since 5.0
748 \fn QVariant::QVariant(const QJsonObject &val)
749
750 Constructs a new variant with a json object value, \a val.
751*/
752
753/*!
754 \since 5.0
755 \fn QVariant::QVariant(const QJsonArray &val)
756
757 Constructs a new variant with a json array value, \a val.
758*/
759
760/*!
761 \since 5.0
762 \fn QVariant::QVariant(const QJsonDocument &val)
763
764 Constructs a new variant with a json document value, \a val.
765*/
766
767/*!
768 \fn QVariant::QVariant(const QByteArray &val) noexcept
769
770 Constructs a new variant with a bytearray value, \a val.
771*/
772
773/*!
774 \fn QVariant::QVariant(const QBitArray &val) noexcept
775
776 Constructs a new variant with a bitarray value, \a val.
777*/
778
779/*!
780 \fn QVariant::QVariant(QPoint val) noexcept
781
782 Constructs a new variant with a point value of \a val.
783 */
784
785/*!
786 \fn QVariant::QVariant(QPointF val) noexcept
787
788 Constructs a new variant with a point value of \a val.
789 */
790
791/*!
792 \fn QVariant::QVariant(QRectF val)
793
794 Constructs a new variant with a rect value of \a val.
795 */
796
797/*!
798 \fn QVariant::QVariant(QLineF val) noexcept
799
800 Constructs a new variant with a line value of \a val.
801 */
802
803/*!
804 \fn QVariant::QVariant(QLine val) noexcept
805
806 Constructs a new variant with a line value of \a val.
807 */
808
809/*!
810 \fn QVariant::QVariant(QRect val) noexcept
811
812 Constructs a new variant with a rect value of \a val.
813 */
814
815/*!
816 \fn QVariant::QVariant(QSize val) noexcept
817
818 Constructs a new variant with a size value of \a val.
819 */
820
821/*!
822 \fn QVariant::QVariant(QSizeF val) noexcept
823
824 Constructs a new variant with a size value of \a val.
825 */
826
827/*!
828 \fn QVariant::QVariant(const QUrl &val) noexcept
829
830 Constructs a new variant with a url value of \a val.
831 */
832
833/*!
834 \fn QVariant::QVariant(int val) noexcept
835
836 Constructs a new variant with an integer value, \a val.
837*/
838
839/*!
840 \fn QVariant::QVariant(uint val) noexcept
841
842 Constructs a new variant with an unsigned integer value, \a val.
843*/
844
845/*!
846 \fn QVariant::QVariant(qlonglong val) noexcept
847
848 Constructs a new variant with a long long integer value, \a val.
849*/
850
851/*!
852 \fn QVariant::QVariant(qulonglong val) noexcept
853
854 Constructs a new variant with an unsigned long long integer value, \a val.
855*/
856
857
858/*!
859 \fn QVariant::QVariant(bool val) noexcept
860
861 Constructs a new variant with a boolean value, \a val.
862*/
863
864/*!
865 \fn QVariant::QVariant(double val) noexcept
866
867 Constructs a new variant with a floating point value, \a val.
868*/
869
870/*!
871 \fn QVariant::QVariant(float val) noexcept
872
873 Constructs a new variant with a floating point value, \a val.
874 \since 4.6
875*/
876
877/*!
878 \fn QVariant::QVariant(const QList<QVariant> &val) noexcept
879
880 Constructs a new variant with a list value, \a val.
881*/
882
883/*!
884 \fn QVariant::QVariant(QChar c) noexcept
885
886 Constructs a new variant with a char value, \a c.
887*/
888
889/*!
890 \fn QVariant::QVariant(const QLocale &l) noexcept
891
892 Constructs a new variant with a locale value, \a l.
893*/
894
895/*!
896 \fn QVariant::QVariant(const QRegularExpression &re) noexcept
897
898 \since 5.0
899
900 Constructs a new variant with the regular expression value \a re.
901*/
902
903/*! \fn QVariant::QVariant(Type type)
904 \deprecated [6.0] Use the constructor taking a QMetaType instead.
905
906 Constructs an uninitialized variant of type \a type. This will create a
907 variant in a special null state that if accessed will return a default
908 constructed value of the \a type.
909
910 \sa isNull()
911*/
912
913/*!
914 Constructs a variant of type \a type, and initializes it with
915 a copy of \c{*copy} if \a copy is not \nullptr (in which case, \a copy
916 must point to an object of type \a type).
917
918 Note that you have to pass the address of the object you want stored.
919
920 Usually, you never have to use this constructor, use QVariant::fromValue()
921 instead to construct variants from the pointer types represented by
922 \c QMetaType::VoidStar, and \c QMetaType::QObjectStar.
923
924 If \a type does not support copy construction and \a copy is not \nullptr,
925 the variant will be invalid. Similarly, if \a copy is \nullptr and
926 \a type does not support default construction, the variant will be
927 invalid.
928
929 \sa QVariant::fromMetaType, QVariant::fromValue(), QMetaType::Type
930*/
931QVariant::QVariant(QMetaType type, const void *copy)
932 : d()
933{
934 *this = fromMetaType(type, copy);
935}
936
937QVariant::QVariant(int val) noexcept : d(std::piecewise_construct_t{}, val) {}
938QVariant::QVariant(uint val) noexcept : d(std::piecewise_construct_t{}, val) {}
939QVariant::QVariant(qlonglong val) noexcept : d(std::piecewise_construct_t{}, val) {}
940QVariant::QVariant(qulonglong val) noexcept : d(std::piecewise_construct_t{}, val) {}
941QVariant::QVariant(bool val) noexcept : d(std::piecewise_construct_t{}, val) {}
942QVariant::QVariant(double val) noexcept : d(std::piecewise_construct_t{}, val) {}
943QVariant::QVariant(float val) noexcept : d(std::piecewise_construct_t{}, val) {}
944
945QVariant::QVariant(const QByteArray &val) noexcept : d(std::piecewise_construct_t{}, val) {}
946#ifndef QT_BOOTSTRAPPED
947QVariant::QVariant(const QBitArray &val) noexcept : d(std::piecewise_construct_t{}, val) {}
948#endif
949QVariant::QVariant(const QString &val) noexcept : d(std::piecewise_construct_t{}, val) {}
950QVariant::QVariant(QChar val) noexcept : d(std::piecewise_construct_t{}, val) {}
951QVariant::QVariant(const QStringList &val) noexcept : d(std::piecewise_construct_t{}, val) {}
952
953QVariant::QVariant(QDate val) noexcept : d(std::piecewise_construct_t{}, val) {}
954QVariant::QVariant(QTime val) noexcept : d(std::piecewise_construct_t{}, val) {}
955QVariant::QVariant(const QDateTime &val) noexcept : d(std::piecewise_construct_t{}, val) {}
956
957QVariant::QVariant(const QList<QVariant> &list) noexcept : d(std::piecewise_construct_t{}, list) {}
958QVariant::QVariant(const QMap<QString, QVariant> &map) noexcept : d(std::piecewise_construct_t{}, map) {}
959QVariant::QVariant(const QHash<QString, QVariant> &hash) noexcept : d(std::piecewise_construct_t{}, hash) {}
960
961QVariant::QVariant(QLatin1StringView val) : QVariant(QString(val)) {}
962
963#if QT_CONFIG(easingcurve)
964QVariant::QVariant(const QEasingCurve &val) : d(std::piecewise_construct_t{}, val) {}
965#endif
966#ifndef QT_NO_GEOM_VARIANT
967QVariant::QVariant(QPoint pt) noexcept
968 : d(std::piecewise_construct_t{}, pt) {}
969QVariant::QVariant(QPointF pt) noexcept(Private::FitsInInternalSize<sizeof(qreal) * 2>)
970 : d(std::piecewise_construct_t{}, pt) {}
971QVariant::QVariant(QRect r) noexcept(Private::FitsInInternalSize<sizeof(int) * 4>)
972 : d(std::piecewise_construct_t{}, r) {}
973QVariant::QVariant(QRectF r) noexcept(Private::FitsInInternalSize<sizeof(qreal) * 4>)
974 : d(std::piecewise_construct_t{}, r) {}
975QVariant::QVariant(QLine l) noexcept(Private::FitsInInternalSize<sizeof(int) * 4>)
976 : d(std::piecewise_construct_t{}, l) {}
977QVariant::QVariant(QLineF l) noexcept(Private::FitsInInternalSize<sizeof(qreal) * 4>)
978 : d(std::piecewise_construct_t{}, l) {}
979QVariant::QVariant(QSize s) noexcept
980 : d(std::piecewise_construct_t{}, s) {}
981QVariant::QVariant(QSizeF s) noexcept(Private::FitsInInternalSize<sizeof(qreal) * 2>)
982 : d(std::piecewise_construct_t{}, s) {}
983#endif
984#ifndef QT_BOOTSTRAPPED
985QVariant::QVariant(const QUrl &u) noexcept : d(std::piecewise_construct_t{}, u) {}
986#endif
987QVariant::QVariant(const QLocale &l) noexcept : d(std::piecewise_construct_t{}, l) {}
988#if QT_CONFIG(regularexpression)
989QVariant::QVariant(const QRegularExpression &re) noexcept : d(std::piecewise_construct_t{}, re) {}
990#endif // QT_CONFIG(regularexpression)
991QVariant::QVariant(QUuid uuid) noexcept(Private::FitsInInternalSize<16>) : d(std::piecewise_construct_t{}, uuid) {}
992#ifndef QT_BOOTSTRAPPED
993QVariant::QVariant(const QJsonValue &jsonValue) noexcept(Private::FitsInInternalSize<sizeof(CborValueStandIn)>)
994 : d(std::piecewise_construct_t{}, jsonValue)
995{ static_assert(sizeof(CborValueStandIn) == sizeof(QJsonValue)); }
996QVariant::QVariant(const QJsonObject &jsonObject) noexcept : d(std::piecewise_construct_t{}, jsonObject) {}
997QVariant::QVariant(const QJsonArray &jsonArray) noexcept : d(std::piecewise_construct_t{}, jsonArray) {}
998QVariant::QVariant(const QJsonDocument &jsonDocument) : d(std::piecewise_construct_t{}, jsonDocument) {}
999#endif // QT_BOOTSTRAPPED
1000#if QT_CONFIG(itemmodel)
1001QVariant::QVariant(const QModelIndex &modelIndex) noexcept(Private::FitsInInternalSize<8 + 2 * sizeof(quintptr)>)
1002 : d(std::piecewise_construct_t{}, modelIndex) {}
1003QVariant::QVariant(const QPersistentModelIndex &modelIndex) : d(std::piecewise_construct_t{}, modelIndex) {}
1004#endif
1005
1006/*! \fn QVariant::Type QVariant::type() const
1007 \deprecated [6.0] Use typeId() or metaType() instead.
1008
1009 Returns the storage type of the value stored in the variant.
1010 Although this function is declared as returning QVariant::Type,
1011 the return value should be interpreted as QMetaType::Type. In
1012 particular, QVariant::UserType is returned here only if the value
1013 is equal or greater than QMetaType::User.
1014
1015 Note that return values in the ranges QVariant::Char through
1016 QVariant::RegExp and QVariant::Font through QVariant::Transform
1017 correspond to the values in the ranges QMetaType::QChar through
1018 QMetaType::QRegularExpression and QMetaType::QFont through QMetaType::QQuaternion.
1019
1020 Pay particular attention when working with char and QChar
1021 variants. Note that there is no QVariant constructor specifically
1022 for type char, but there is one for QChar. For a variant of type
1023 QChar, this function returns QVariant::Char, which is the same as
1024 QMetaType::QChar, but for a variant of type \c char, this function
1025 returns QMetaType::Char, which is \e not the same as
1026 QVariant::Char.
1027
1028 Also note that the types \c void*, \c long, \c short, \c unsigned
1029 \c long, \c unsigned \c short, \c unsigned \c char, \c float, \c
1030 QObject*, and \c QWidget* are represented in QMetaType::Type but
1031 not in QVariant::Type, and they can be returned by this function.
1032 However, they are considered to be user defined types when tested
1033 against QVariant::Type.
1034
1035 To test whether an instance of QVariant contains a data type that
1036 is compatible with the data type you are interested in, use
1037 canConvert().
1038
1039 \sa userType(), metaType()
1040*/
1041
1042/*! \fn int QVariant::userType() const
1043 \fn int QVariant::typeId() const
1044
1045 Returns the storage type of the value stored in the variant. This is
1046 the same as metaType().id().
1047
1048 \sa metaType()
1049*/
1050
1051/*!
1052 \since 6.0
1053
1054 Returns the QMetaType of the value stored in the variant.
1055*/
1056QMetaType QVariant::metaType() const
1057{
1058 return d.type();
1059}
1060
1061/*!
1062 Assigns the value of the variant \a variant to this variant.
1063*/
1064QVariant &QVariant::operator=(const QVariant &variant)
1065{
1066 if (this == &variant)
1067 return *this;
1068
1069 clear();
1070 d = clonePrivate(other: variant.d);
1071 return *this;
1072}
1073
1074/*!
1075 \fn void QVariant::swap(QVariant &other)
1076 \since 4.8
1077
1078 Swaps variant \a other with this variant. This operation is very
1079 fast and never fails.
1080*/
1081
1082/*!
1083 \fn void QVariant::detach()
1084
1085 \internal
1086*/
1087
1088void QVariant::detach()
1089{
1090 if (!d.is_shared || d.data.shared->ref.loadRelaxed() == 1)
1091 return;
1092
1093 Q_ASSERT(isValidMetaTypeForVariant(d.typeInterface(), constData()));
1094 Private dd(d.typeInterface());
1095 // null variant is never shared; anything else is NonNull
1096 customConstruct<UseCopy, NonNull>(iface: d.typeInterface(), d: &dd, copy: constData());
1097 if (!d.data.shared->ref.deref())
1098 customClear(d: &d);
1099 d.data.shared = dd.data.shared;
1100}
1101
1102/*!
1103 \fn bool QVariant::isDetached() const
1104
1105 \internal
1106*/
1107
1108/*!
1109 Returns the name of the type stored in the variant. The returned
1110 strings describe the C++ datatype used to store the data: for
1111 example, "QFont", "QString", or "QVariantList". An Invalid
1112 variant returns 0.
1113*/
1114const char *QVariant::typeName() const
1115{
1116 return d.type().name();
1117}
1118
1119/*!
1120 Convert this variant to type QMetaType::UnknownType and free up any resources
1121 used.
1122*/
1123void QVariant::clear()
1124{
1125 if (!d.is_shared || !d.data.shared->ref.deref())
1126 customClear(d: &d);
1127 d = {};
1128}
1129
1130/*!
1131 \fn const char *QVariant::typeToName(int typeId)
1132 \deprecated [6.0] Use \c QMetaType(typeId).name() instead.
1133
1134 Converts the int representation of the storage type, \a typeId, to
1135 its string representation.
1136
1137 Returns \nullptr if the type is QMetaType::UnknownType or doesn't exist.
1138*/
1139
1140/*!
1141 \fn QVariant::Type QVariant::nameToType(const char *name)
1142 \deprecated [6.0] Use \c QMetaType::fromName(name).id() instead
1143
1144 Converts the string representation of the storage type given in \a
1145 name, to its enum representation.
1146
1147 If the string representation cannot be converted to any enum
1148 representation, the variant is set to \c Invalid.
1149*/
1150
1151#ifndef QT_NO_DATASTREAM
1152enum { MapFromThreeCount = 36 };
1153static const ushort mapIdFromQt3ToCurrent[MapFromThreeCount] =
1154{
1155 QMetaType::UnknownType,
1156 QMetaType::QVariantMap,
1157 QMetaType::QVariantList,
1158 QMetaType::QString,
1159 QMetaType::QStringList,
1160 QMetaType::QFont,
1161 QMetaType::QPixmap,
1162 QMetaType::QBrush,
1163 QMetaType::QRect,
1164 QMetaType::QSize,
1165 QMetaType::QColor,
1166 QMetaType::QPalette,
1167 0, // ColorGroup
1168 QMetaType::QIcon,
1169 QMetaType::QPoint,
1170 QMetaType::QImage,
1171 QMetaType::Int,
1172 QMetaType::UInt,
1173 QMetaType::Bool,
1174 QMetaType::Double,
1175 0, // Buggy ByteArray, QByteArray never had id == 20
1176 QMetaType::QPolygon,
1177 QMetaType::QRegion,
1178 QMetaType::QBitmap,
1179 QMetaType::QCursor,
1180 QMetaType::QSizePolicy,
1181 QMetaType::QDate,
1182 QMetaType::QTime,
1183 QMetaType::QDateTime,
1184 QMetaType::QByteArray,
1185 QMetaType::QBitArray,
1186#if QT_CONFIG(shortcut)
1187 QMetaType::QKeySequence,
1188#else
1189 0, // QKeySequence
1190#endif
1191 QMetaType::QPen,
1192 QMetaType::LongLong,
1193 QMetaType::ULongLong,
1194#if QT_CONFIG(easingcurve)
1195 QMetaType::QEasingCurve
1196#endif
1197};
1198
1199// values needed to map Qt5 based type id's to Qt6 based ones
1200constexpr int Qt5UserType = 1024;
1201constexpr int Qt5LastCoreType = QMetaType::QCborMap;
1202constexpr int Qt5FirstGuiType = 64;
1203constexpr int Qt5LastGuiType = 87;
1204constexpr int Qt5SizePolicy = 121;
1205constexpr int Qt5RegExp = 27;
1206constexpr int Qt5KeySequence = 75;
1207constexpr int Qt5QQuaternion = 85;
1208
1209constexpr int Qt6ToQt5GuiTypeDelta = qToUnderlying(e: QMetaType::FirstGuiType) - Qt5FirstGuiType;
1210
1211/*!
1212 Internal function for loading a variant from stream \a s. Use the
1213 stream operators instead.
1214
1215 \internal
1216*/
1217void QVariant::load(QDataStream &s)
1218{
1219 clear();
1220
1221 quint32 typeId;
1222 s >> typeId;
1223 if (s.version() < QDataStream::Qt_4_0) {
1224 // map to Qt 5 ids
1225 if (typeId >= MapFromThreeCount)
1226 return;
1227 typeId = mapIdFromQt3ToCurrent[typeId];
1228 } else if (s.version() < QDataStream::Qt_5_0) {
1229 // map to Qt 5 type ids
1230 if (typeId == 127 /* QVariant::UserType */) {
1231 typeId = Qt5UserType;
1232 } else if (typeId >= 128 && typeId != Qt5UserType) {
1233 // In Qt4 id == 128 was FirstExtCoreType. In Qt5 ExtCoreTypes set was merged to CoreTypes
1234 // by moving all ids down by 97.
1235 typeId -= 97;
1236 } else if (typeId == 75 /* QSizePolicy */) {
1237 typeId = Qt5SizePolicy;
1238 } else if (typeId > 75 && typeId <= 86) {
1239 // and as a result these types received lower ids too
1240 // QKeySequence QPen QTextLength QTextFormat QTransform QMatrix4x4 QVector2D QVector3D QVector4D QQuaternion
1241 typeId -=1;
1242 }
1243 }
1244 if (s.version() < QDataStream::Qt_6_0) {
1245 // map from Qt 5 to Qt 6 values
1246 if (typeId == Qt5UserType) {
1247 typeId = QMetaType::User;
1248 } else if (typeId >= Qt5FirstGuiType && typeId <= Qt5LastGuiType) {
1249 typeId += Qt6ToQt5GuiTypeDelta;
1250 } else if (typeId == Qt5SizePolicy) {
1251 typeId = QMetaType::QSizePolicy;
1252 } else if (typeId == Qt5RegExp) {
1253 typeId = QMetaType::fromName(name: "QRegExp").id();
1254 }
1255 }
1256
1257 qint8 is_null = false;
1258 if (s.version() >= QDataStream::Qt_4_2)
1259 s >> is_null;
1260 if (typeId == QMetaType::User) {
1261 QByteArray name;
1262 s >> name;
1263 typeId = QMetaType::fromName(name).id();
1264 if (typeId == QMetaType::UnknownType) {
1265 s.setStatus(QDataStream::ReadCorruptData);
1266 qWarning(msg: "QVariant::load: unknown user type with name %s.", name.constData());
1267 return;
1268 }
1269 }
1270 create(type: typeId, copy: nullptr);
1271 d.is_null = is_null;
1272
1273 if (!isValid()) {
1274 if (s.version() < QDataStream::Qt_5_0) {
1275 // Since we wrote something, we should read something
1276 QString x;
1277 s >> x;
1278 }
1279 d.is_null = true;
1280 return;
1281 }
1282
1283 // const cast is safe since we operate on a newly constructed variant
1284 void *data = const_cast<void *>(constData());
1285 if (!d.type().load(stream&: s, data)) {
1286 s.setStatus(QDataStream::ReadCorruptData);
1287 qWarning(msg: "QVariant::load: unable to load type %d.", d.type().id());
1288 }
1289}
1290
1291/*!
1292 Internal function for saving a variant to the stream \a s. Use the
1293 stream operators instead.
1294
1295 \internal
1296*/
1297void QVariant::save(QDataStream &s) const
1298{
1299 quint32 typeId = d.type().id();
1300 bool saveAsUserType = false;
1301 if (typeId >= QMetaType::User) {
1302 typeId = QMetaType::User;
1303 saveAsUserType = true;
1304 }
1305 if (s.version() < QDataStream::Qt_6_0) {
1306 // map to Qt 5 values
1307 if (typeId == QMetaType::User) {
1308 typeId = Qt5UserType;
1309 if (!strcmp(s1: d.type().name(), s2: "QRegExp")) {
1310 typeId = 27; // QRegExp in Qt 4/5
1311 }
1312 } else if (typeId > Qt5LastCoreType && typeId <= QMetaType::LastCoreType) {
1313 // the type didn't exist in Qt 5
1314 typeId = Qt5UserType;
1315 saveAsUserType = true;
1316 } else if (typeId >= QMetaType::FirstGuiType && typeId <= QMetaType::LastGuiType) {
1317 typeId -= Qt6ToQt5GuiTypeDelta;
1318 if (typeId > Qt5LastGuiType) {
1319 typeId = Qt5UserType;
1320 saveAsUserType = true;
1321 }
1322 } else if (typeId == QMetaType::QSizePolicy) {
1323 typeId = Qt5SizePolicy;
1324 }
1325 }
1326 if (s.version() < QDataStream::Qt_4_0) {
1327 int i;
1328 for (i = 0; i <= MapFromThreeCount - 1; ++i) {
1329 if (mapIdFromQt3ToCurrent[i] == typeId) {
1330 typeId = i;
1331 break;
1332 }
1333 }
1334 if (i >= MapFromThreeCount) {
1335 s << QVariant();
1336 return;
1337 }
1338 } else if (s.version() < QDataStream::Qt_5_0) {
1339 if (typeId == Qt5UserType) {
1340 typeId = 127; // QVariant::UserType had this value in Qt4
1341 saveAsUserType = true;
1342 } else if (typeId >= 128 - 97 && typeId <= Qt5LastCoreType) {
1343 // In Qt4 id == 128 was FirstExtCoreType. In Qt5 ExtCoreTypes set was merged to CoreTypes
1344 // by moving all ids down by 97.
1345 typeId += 97;
1346 } else if (typeId == Qt5SizePolicy) {
1347 typeId = 75;
1348 } else if (typeId >= Qt5KeySequence && typeId <= Qt5QQuaternion) {
1349 // and as a result these types received lower ids too
1350 typeId += 1;
1351 } else if (typeId > Qt5QQuaternion || typeId == QMetaType::QUuid) {
1352 // These existed in Qt 4 only as a custom type
1353 typeId = 127;
1354 saveAsUserType = true;
1355 }
1356 }
1357 const char *typeName = nullptr;
1358 if (saveAsUserType) {
1359 if (s.version() < QDataStream::Qt_6_0)
1360 typeName = QtMetaTypePrivate::typedefNameForType(type_d: d.type().d_ptr);
1361 if (!typeName)
1362 typeName = d.type().name();
1363 }
1364 s << typeId;
1365 if (s.version() >= QDataStream::Qt_4_2)
1366 s << qint8(d.is_null);
1367 if (typeName)
1368 s << typeName;
1369
1370 if (!isValid()) {
1371 if (s.version() < QDataStream::Qt_5_0)
1372 s << QString();
1373 return;
1374 }
1375
1376 if (!d.type().save(stream&: s, data: constData())) {
1377 qWarning(msg: "QVariant::save: unable to save type '%s' (type id: %d).\n",
1378 d.type().name(), d.type().id());
1379 Q_ASSERT_X(false, "QVariant::save", "Invalid type to save");
1380 }
1381}
1382
1383/*!
1384 \since 4.4
1385 \relates QVariant
1386
1387 Reads a variant \a p from the stream \a s.
1388
1389 \note If the stream contains types that aren't the built-in ones (see \l
1390 QMetaType::Type), those types must be registered using qRegisterMetaType()
1391 or QMetaType::registerType() before the variant can be properly loaded. If
1392 an unregistered type is found, QVariant will set the corrupt flag in the
1393 stream, stop processing and print a warning. For example, for QList<int>
1394 it would print the following:
1395
1396 \quotation
1397 QVariant::load: unknown user type with name QList<int>
1398 \endquotation
1399
1400 \sa{Serializing Qt Data Types}{Format of the QDataStream operators}
1401*/
1402QDataStream &operator>>(QDataStream &s, QVariant &p)
1403{
1404 p.load(s);
1405 return s;
1406}
1407
1408/*!
1409 Writes a variant \a p to the stream \a s.
1410 \relates QVariant
1411
1412 \sa{Serializing Qt Data Types}{Format of the QDataStream operators}
1413*/
1414QDataStream &operator<<(QDataStream &s, const QVariant &p)
1415{
1416 p.save(s);
1417 return s;
1418}
1419
1420/*! \fn QDataStream& operator>>(QDataStream &s, QVariant::Type &p)
1421 \relates QVariant
1422 \deprecated [6.0] Stream QMetaType::Type instead.
1423
1424 Reads a variant type \a p in enum representation from the stream \a s.
1425*/
1426
1427/*! \fn QDataStream& operator<<(QDataStream &s, const QVariant::Type p)
1428 \relates QVariant
1429 \deprecated [6.0] Stream QMetaType::Type instead.
1430
1431 Writes a variant type \a p to the stream \a s.
1432*/
1433#endif //QT_NO_DATASTREAM
1434
1435/*!
1436 \fn bool QVariant::isValid() const
1437
1438 Returns \c true if the storage type of this variant is not
1439 QMetaType::UnknownType; otherwise returns \c false.
1440*/
1441
1442/*!
1443 \fn QStringList QVariant::toStringList() const
1444
1445 Returns the variant as a QStringList if the variant has userType()
1446 \l QMetaType::QStringList, \l QMetaType::QString, or
1447 \l QMetaType::QVariantList of a type that can be converted to QString;
1448 otherwise returns an empty list.
1449
1450 \sa canConvert(), convert()
1451*/
1452QStringList QVariant::toStringList() const
1453{
1454 return qvariant_cast<QStringList>(v: *this);
1455}
1456
1457/*!
1458 Returns the variant as a QString if the variant has a userType()
1459 including, but not limited to:
1460
1461 \l QMetaType::QString, \l QMetaType::Bool, \l QMetaType::QByteArray,
1462 \l QMetaType::QChar, \l QMetaType::QDate, \l QMetaType::QDateTime,
1463 \l QMetaType::Double, \l QMetaType::Int, \l QMetaType::LongLong,
1464 \l QMetaType::QStringList, \l QMetaType::QTime, \l QMetaType::UInt, or
1465 \l QMetaType::ULongLong.
1466
1467 Calling QVariant::toString() on an unsupported variant returns an empty
1468 string.
1469
1470 \sa canConvert(), convert()
1471*/
1472QString QVariant::toString() const
1473{
1474 return qvariant_cast<QString>(v: *this);
1475}
1476
1477/*!
1478 Returns the variant as a QVariantMap if the variant has type() \l
1479 QMetaType::QVariantMap. If it doesn't, QVariant will attempt to
1480 convert the type to a map and then return it. This will succeed for
1481 any type that has registered a converter to QVariantMap or which was
1482 declared as a associative container using
1483 \l{Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE}. If none of those
1484 conditions are true, this function will return an empty map.
1485
1486 \sa canConvert(), convert()
1487*/
1488QVariantMap QVariant::toMap() const
1489{
1490 return qvariant_cast<QVariantMap>(v: *this);
1491}
1492
1493/*!
1494 Returns the variant as a QHash<QString, QVariant> if the variant
1495 has type() \l QMetaType::QVariantHash; otherwise returns an empty map.
1496
1497 \sa canConvert(), convert()
1498*/
1499QVariantHash QVariant::toHash() const
1500{
1501 return qvariant_cast<QVariantHash>(v: *this);
1502}
1503
1504/*!
1505 \fn QDate QVariant::toDate() const
1506
1507 Returns the variant as a QDate if the variant has userType()
1508 \l QMetaType::QDate, \l QMetaType::QDateTime, or \l QMetaType::QString;
1509 otherwise returns an invalid date.
1510
1511 If the type() is \l QMetaType::QString, an invalid date will be returned if
1512 the string cannot be parsed as a Qt::ISODate format date.
1513
1514 \sa canConvert(), convert()
1515*/
1516QDate QVariant::toDate() const
1517{
1518 return qvariant_cast<QDate>(v: *this);
1519}
1520
1521/*!
1522 \fn QTime QVariant::toTime() const
1523
1524 Returns the variant as a QTime if the variant has userType()
1525 \l QMetaType::QTime, \l QMetaType::QDateTime, or \l QMetaType::QString;
1526 otherwise returns an invalid time.
1527
1528 If the type() is \l QMetaType::QString, an invalid time will be returned if
1529 the string cannot be parsed as a Qt::ISODate format time.
1530
1531 \sa canConvert(), convert()
1532*/
1533QTime QVariant::toTime() const
1534{
1535 return qvariant_cast<QTime>(v: *this);
1536}
1537
1538/*!
1539 \fn QDateTime QVariant::toDateTime() const
1540
1541 Returns the variant as a QDateTime if the variant has userType()
1542 \l QMetaType::QDateTime, \l QMetaType::QDate, or \l QMetaType::QString;
1543 otherwise returns an invalid date/time.
1544
1545 If the type() is \l QMetaType::QString, an invalid date/time will be
1546 returned if the string cannot be parsed as a Qt::ISODate format date/time.
1547
1548 \sa canConvert(), convert()
1549*/
1550QDateTime QVariant::toDateTime() const
1551{
1552 return qvariant_cast<QDateTime>(v: *this);
1553}
1554
1555/*!
1556 \since 4.7
1557 \fn QEasingCurve QVariant::toEasingCurve() const
1558
1559 Returns the variant as a QEasingCurve if the variant has userType()
1560 \l QMetaType::QEasingCurve; otherwise returns a default easing curve.
1561
1562 \sa canConvert(), convert()
1563*/
1564#if QT_CONFIG(easingcurve)
1565QEasingCurve QVariant::toEasingCurve() const
1566{
1567 return qvariant_cast<QEasingCurve>(v: *this);
1568}
1569#endif
1570
1571/*!
1572 \fn QByteArray QVariant::toByteArray() const
1573
1574 Returns the variant as a QByteArray if the variant has userType()
1575 \l QMetaType::QByteArray or \l QMetaType::QString (converted using
1576 QString::fromUtf8()); otherwise returns an empty byte array.
1577
1578 \sa canConvert(), convert()
1579*/
1580QByteArray QVariant::toByteArray() const
1581{
1582 return qvariant_cast<QByteArray>(v: *this);
1583}
1584
1585#ifndef QT_NO_GEOM_VARIANT
1586/*!
1587 \fn QPoint QVariant::toPoint() const
1588
1589 Returns the variant as a QPoint if the variant has userType()
1590 \l QMetaType::QPoint or \l QMetaType::QPointF; otherwise returns a null
1591 QPoint.
1592
1593 \sa canConvert(), convert()
1594*/
1595QPoint QVariant::toPoint() const
1596{
1597 return qvariant_cast<QPoint>(v: *this);
1598}
1599
1600/*!
1601 \fn QRect QVariant::toRect() const
1602
1603 Returns the variant as a QRect if the variant has userType()
1604 \l QMetaType::QRect; otherwise returns an invalid QRect.
1605
1606 \sa canConvert(), convert()
1607*/
1608QRect QVariant::toRect() const
1609{
1610 return qvariant_cast<QRect>(v: *this);
1611}
1612
1613/*!
1614 \fn QSize QVariant::toSize() const
1615
1616 Returns the variant as a QSize if the variant has userType()
1617 \l QMetaType::QSize; otherwise returns an invalid QSize.
1618
1619 \sa canConvert(), convert()
1620*/
1621QSize QVariant::toSize() const
1622{
1623 return qvariant_cast<QSize>(v: *this);
1624}
1625
1626/*!
1627 \fn QSizeF QVariant::toSizeF() const
1628
1629 Returns the variant as a QSizeF if the variant has userType() \l
1630 QMetaType::QSizeF; otherwise returns an invalid QSizeF.
1631
1632 \sa canConvert(), convert()
1633*/
1634QSizeF QVariant::toSizeF() const
1635{
1636 return qvariant_cast<QSizeF>(v: *this);
1637}
1638
1639/*!
1640 \fn QRectF QVariant::toRectF() const
1641
1642 Returns the variant as a QRectF if the variant has userType()
1643 \l QMetaType::QRect or \l QMetaType::QRectF; otherwise returns an invalid
1644 QRectF.
1645
1646 \sa canConvert(), convert()
1647*/
1648QRectF QVariant::toRectF() const
1649{
1650 return qvariant_cast<QRectF>(v: *this);
1651}
1652
1653/*!
1654 \fn QLineF QVariant::toLineF() const
1655
1656 Returns the variant as a QLineF if the variant has userType()
1657 \l QMetaType::QLineF; otherwise returns an invalid QLineF.
1658
1659 \sa canConvert(), convert()
1660*/
1661QLineF QVariant::toLineF() const
1662{
1663 return qvariant_cast<QLineF>(v: *this);
1664}
1665
1666/*!
1667 \fn QLine QVariant::toLine() const
1668
1669 Returns the variant as a QLine if the variant has userType()
1670 \l QMetaType::QLine; otherwise returns an invalid QLine.
1671
1672 \sa canConvert(), convert()
1673*/
1674QLine QVariant::toLine() const
1675{
1676 return qvariant_cast<QLine>(v: *this);
1677}
1678
1679/*!
1680 \fn QPointF QVariant::toPointF() const
1681
1682 Returns the variant as a QPointF if the variant has userType() \l
1683 QMetaType::QPoint or \l QMetaType::QPointF; otherwise returns a null
1684 QPointF.
1685
1686 \sa canConvert(), convert()
1687*/
1688QPointF QVariant::toPointF() const
1689{
1690 return qvariant_cast<QPointF>(v: *this);
1691}
1692
1693#endif // QT_NO_GEOM_VARIANT
1694
1695#ifndef QT_BOOTSTRAPPED
1696/*!
1697 \fn QUrl QVariant::toUrl() const
1698
1699 Returns the variant as a QUrl if the variant has userType()
1700 \l QMetaType::QUrl; otherwise returns an invalid QUrl.
1701
1702 \sa canConvert(), convert()
1703*/
1704QUrl QVariant::toUrl() const
1705{
1706 return qvariant_cast<QUrl>(v: *this);
1707}
1708#endif
1709
1710/*!
1711 \fn QLocale QVariant::toLocale() const
1712
1713 Returns the variant as a QLocale if the variant has userType()
1714 \l QMetaType::QLocale; otherwise returns an invalid QLocale.
1715
1716 \sa canConvert(), convert()
1717*/
1718QLocale QVariant::toLocale() const
1719{
1720 return qvariant_cast<QLocale>(v: *this);
1721}
1722
1723#if QT_CONFIG(regularexpression)
1724/*!
1725 \fn QRegularExpression QVariant::toRegularExpression() const
1726 \since 5.0
1727
1728 Returns the variant as a QRegularExpression if the variant has userType() \l
1729 QRegularExpression; otherwise returns an empty QRegularExpression.
1730
1731 \sa canConvert(), convert()
1732*/
1733QRegularExpression QVariant::toRegularExpression() const
1734{
1735 return qvariant_cast<QRegularExpression>(v: *this);
1736}
1737#endif // QT_CONFIG(regularexpression)
1738
1739#if QT_CONFIG(itemmodel)
1740/*!
1741 \since 5.0
1742
1743 Returns the variant as a QModelIndex if the variant has userType() \l
1744 QModelIndex; otherwise returns a default constructed QModelIndex.
1745
1746 \sa canConvert(), convert(), toPersistentModelIndex()
1747*/
1748QModelIndex QVariant::toModelIndex() const
1749{
1750 return qvariant_cast<QModelIndex>(v: *this);
1751}
1752
1753/*!
1754 \since 5.5
1755
1756 Returns the variant as a QPersistentModelIndex if the variant has userType() \l
1757 QPersistentModelIndex; otherwise returns a default constructed QPersistentModelIndex.
1758
1759 \sa canConvert(), convert(), toModelIndex()
1760*/
1761QPersistentModelIndex QVariant::toPersistentModelIndex() const
1762{
1763 return qvariant_cast<QPersistentModelIndex>(v: *this);
1764}
1765#endif // QT_CONFIG(itemmodel)
1766
1767/*!
1768 \since 5.0
1769
1770 Returns the variant as a QUuid if the variant has type()
1771 \l QMetaType::QUuid, \l QMetaType::QByteArray or \l QMetaType::QString;
1772 otherwise returns a default-constructed QUuid.
1773
1774 \sa canConvert(), convert()
1775*/
1776QUuid QVariant::toUuid() const
1777{
1778 return qvariant_cast<QUuid>(v: *this);
1779}
1780
1781#ifndef QT_BOOTSTRAPPED
1782/*!
1783 \since 5.0
1784
1785 Returns the variant as a QJsonValue if the variant has userType() \l
1786 QJsonValue; otherwise returns a default constructed QJsonValue.
1787
1788 \sa canConvert(), convert()
1789*/
1790QJsonValue QVariant::toJsonValue() const
1791{
1792 return qvariant_cast<QJsonValue>(v: *this);
1793}
1794
1795/*!
1796 \since 5.0
1797
1798 Returns the variant as a QJsonObject if the variant has userType() \l
1799 QJsonObject; otherwise returns a default constructed QJsonObject.
1800
1801 \sa canConvert(), convert()
1802*/
1803QJsonObject QVariant::toJsonObject() const
1804{
1805 return qvariant_cast<QJsonObject>(v: *this);
1806}
1807
1808/*!
1809 \since 5.0
1810
1811 Returns the variant as a QJsonArray if the variant has userType() \l
1812 QJsonArray; otherwise returns a default constructed QJsonArray.
1813
1814 \sa canConvert(), convert()
1815*/
1816QJsonArray QVariant::toJsonArray() const
1817{
1818 return qvariant_cast<QJsonArray>(v: *this);
1819}
1820
1821/*!
1822 \since 5.0
1823
1824 Returns the variant as a QJsonDocument if the variant has userType() \l
1825 QJsonDocument; otherwise returns a default constructed QJsonDocument.
1826
1827 \sa canConvert(), convert()
1828*/
1829QJsonDocument QVariant::toJsonDocument() const
1830{
1831 return qvariant_cast<QJsonDocument>(v: *this);
1832}
1833#endif // QT_BOOTSTRAPPED
1834
1835/*!
1836 \fn QChar QVariant::toChar() const
1837
1838 Returns the variant as a QChar if the variant has userType()
1839 \l QMetaType::QChar, \l QMetaType::Int, or \l QMetaType::UInt; otherwise
1840 returns an invalid QChar.
1841
1842 \sa canConvert(), convert()
1843*/
1844QChar QVariant::toChar() const
1845{
1846 return qvariant_cast<QChar>(v: *this);
1847}
1848
1849#ifndef QT_BOOTSTRAPPED
1850/*!
1851 Returns the variant as a QBitArray if the variant has userType()
1852 \l QMetaType::QBitArray; otherwise returns an empty bit array.
1853
1854 \sa canConvert(), convert()
1855*/
1856QBitArray QVariant::toBitArray() const
1857{
1858 return qvariant_cast<QBitArray>(v: *this);
1859}
1860#endif // QT_BOOTSTRAPPED
1861
1862template <typename T>
1863inline T qNumVariantToHelper(const QVariant::Private &d, bool *ok)
1864{
1865 QMetaType t = QMetaType::fromType<T>();
1866 if (ok)
1867 *ok = true;
1868
1869 if (d.type() == t)
1870 return d.get<T>();
1871
1872 T ret = 0;
1873 bool success = QMetaType::convert(d.type(), d.storage(), t, &ret);
1874 if (ok)
1875 *ok = success;
1876 return ret;
1877}
1878
1879/*!
1880 Returns the variant as an int if the variant has userType()
1881 \l QMetaType::Int, \l QMetaType::Bool, \l QMetaType::QByteArray,
1882 \l QMetaType::QChar, \l QMetaType::Double, \l QMetaType::LongLong,
1883 \l QMetaType::QString, \l QMetaType::UInt, or \l QMetaType::ULongLong;
1884 otherwise returns 0.
1885
1886 If \a ok is non-null: \c{*}\a{ok} is set to true if the value could be
1887 converted to an int; otherwise \c{*}\a{ok} is set to false.
1888
1889 \b{Warning:} If the value is convertible to a \l QMetaType::LongLong but is
1890 too large to be represented in an int, the resulting arithmetic overflow
1891 will not be reflected in \a ok. A simple workaround is to use
1892 QString::toInt().
1893
1894 \sa canConvert(), convert()
1895*/
1896int QVariant::toInt(bool *ok) const
1897{
1898 return qNumVariantToHelper<int>(d, ok);
1899}
1900
1901/*!
1902 Returns the variant as an unsigned int if the variant has userType()
1903 \l QMetaType::UInt, \l QMetaType::Bool, \l QMetaType::QByteArray,
1904 \l QMetaType::QChar, \l QMetaType::Double, \l QMetaType::Int,
1905 \l QMetaType::LongLong, \l QMetaType::QString, or \l QMetaType::ULongLong;
1906 otherwise returns 0.
1907
1908 If \a ok is non-null: \c{*}\a{ok} is set to true if the value could be
1909 converted to an unsigned int; otherwise \c{*}\a{ok} is set to false.
1910
1911 \b{Warning:} If the value is convertible to a \l QMetaType::ULongLong but is
1912 too large to be represented in an unsigned int, the resulting arithmetic
1913 overflow will not be reflected in \a ok. A simple workaround is to use
1914 QString::toUInt().
1915
1916 \sa canConvert(), convert()
1917*/
1918uint QVariant::toUInt(bool *ok) const
1919{
1920 return qNumVariantToHelper<uint>(d, ok);
1921}
1922
1923/*!
1924 Returns the variant as a long long int if the variant has userType()
1925 \l QMetaType::LongLong, \l QMetaType::Bool, \l QMetaType::QByteArray,
1926 \l QMetaType::QChar, \l QMetaType::Double, \l QMetaType::Int,
1927 \l QMetaType::QString, \l QMetaType::UInt, or \l QMetaType::ULongLong;
1928 otherwise returns 0.
1929
1930 If \a ok is non-null: \c{*}\c{ok} is set to true if the value could be
1931 converted to an int; otherwise \c{*}\c{ok} is set to false.
1932
1933 \sa canConvert(), convert()
1934*/
1935qlonglong QVariant::toLongLong(bool *ok) const
1936{
1937 return qNumVariantToHelper<qlonglong>(d, ok);
1938}
1939
1940/*!
1941 Returns the variant as an unsigned long long int if the
1942 variant has type() \l QMetaType::ULongLong, \l QMetaType::Bool,
1943 \l QMetaType::QByteArray, \l QMetaType::QChar, \l QMetaType::Double,
1944 \l QMetaType::Int, \l QMetaType::LongLong, \l QMetaType::QString, or
1945 \l QMetaType::UInt; otherwise returns 0.
1946
1947 If \a ok is non-null: \c{*}\a{ok} is set to true if the value could be
1948 converted to an int; otherwise \c{*}\a{ok} is set to false.
1949
1950 \sa canConvert(), convert()
1951*/
1952qulonglong QVariant::toULongLong(bool *ok) const
1953{
1954 return qNumVariantToHelper<qulonglong>(d, ok);
1955}
1956
1957/*!
1958 Returns the variant as a bool if the variant has userType() Bool.
1959
1960 Returns \c true if the variant has userType() \l QMetaType::Bool,
1961 \l QMetaType::QChar, \l QMetaType::Double, \l QMetaType::Int,
1962 \l QMetaType::LongLong, \l QMetaType::UInt, or \l QMetaType::ULongLong and
1963 the value is non-zero, or if the variant has type \l QMetaType::QString or
1964 \l QMetaType::QByteArray and its lower-case content is not one of the
1965 following: empty, "0" or "false"; otherwise returns \c false.
1966
1967 \sa canConvert(), convert()
1968*/
1969bool QVariant::toBool() const
1970{
1971 auto boolType = QMetaType::fromType<bool>();
1972 if (d.type() == boolType)
1973 return d.get<bool>();
1974
1975 bool res = false;
1976 QMetaType::convert(fromType: d.type(), from: constData(), toType: boolType, to: &res);
1977 return res;
1978}
1979
1980/*!
1981 Returns the variant as a double if the variant has userType()
1982 \l QMetaType::Double, \l QMetaType::Float, \l QMetaType::Bool,
1983 \l QMetaType::QByteArray, \l QMetaType::Int, \l QMetaType::LongLong,
1984 \l QMetaType::QString, \l QMetaType::UInt, or \l QMetaType::ULongLong;
1985 otherwise returns 0.0.
1986
1987 If \a ok is non-null: \c{*}\a{ok} is set to true if the value could be
1988 converted to a double; otherwise \c{*}\a{ok} is set to false.
1989
1990 \sa canConvert(), convert()
1991*/
1992double QVariant::toDouble(bool *ok) const
1993{
1994 return qNumVariantToHelper<double>(d, ok);
1995}
1996
1997/*!
1998 Returns the variant as a float if the variant has userType()
1999 \l QMetaType::Double, \l QMetaType::Float, \l QMetaType::Bool,
2000 \l QMetaType::QByteArray, \l QMetaType::Int, \l QMetaType::LongLong,
2001 \l QMetaType::QString, \l QMetaType::UInt, or \l QMetaType::ULongLong;
2002 otherwise returns 0.0.
2003
2004 \since 4.6
2005
2006 If \a ok is non-null: \c{*}\a{ok} is set to true if the value could be
2007 converted to a double; otherwise \c{*}\a{ok} is set to false.
2008
2009 \sa canConvert(), convert()
2010*/
2011float QVariant::toFloat(bool *ok) const
2012{
2013 return qNumVariantToHelper<float>(d, ok);
2014}
2015
2016/*!
2017 Returns the variant as a qreal if the variant has userType()
2018 \l QMetaType::Double, \l QMetaType::Float, \l QMetaType::Bool,
2019 \l QMetaType::QByteArray, \l QMetaType::Int, \l QMetaType::LongLong,
2020 \l QMetaType::QString, \l QMetaType::UInt, or \l QMetaType::ULongLong;
2021 otherwise returns 0.0.
2022
2023 \since 4.6
2024
2025 If \a ok is non-null: \c{*}\a{ok} is set to true if the value could be
2026 converted to a double; otherwise \c{*}\a{ok} is set to false.
2027
2028 \sa canConvert(), convert()
2029*/
2030qreal QVariant::toReal(bool *ok) const
2031{
2032 return qNumVariantToHelper<qreal>(d, ok);
2033}
2034
2035/*!
2036 Returns the variant as a QVariantList if the variant has userType() \l
2037 QMetaType::QVariantList. If it doesn't, QVariant will attempt to convert
2038 the type to a list and then return it. This will succeed for any type that
2039 has registered a converter to QVariantList or which was declared as a
2040 sequential container using \l{Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE}. If
2041 none of those conditions are true, this function will return an empty
2042 list.
2043
2044 \sa canConvert(), convert()
2045*/
2046QVariantList QVariant::toList() const
2047{
2048 return qvariant_cast<QVariantList>(v: *this);
2049}
2050
2051/*!
2052 \fn bool QVariant::canConvert(int targetTypeId) const
2053 \overload
2054 \deprecated [6.0] Use \c canConvert(QMetaType(targetTypeId)) instead.
2055
2056 \sa QMetaType::canConvert()
2057*/
2058
2059/*!
2060 \fn bool QVariant::canConvert(QMetaType type) const
2061 \since 6.0
2062
2063 Returns \c true if the variant's type can be cast to the requested
2064 type, \a type. Such casting is done automatically when calling the
2065 toInt(), toBool(), ... methods.
2066
2067 \sa QMetaType::canConvert()
2068*/
2069
2070
2071/*!
2072 \fn bool QVariant::convert(int targetTypeId)
2073 \deprecated [6.0] Use \c convert(QMetaType(targetTypeId)) instead.
2074
2075 Casts the variant to the requested type, \a targetTypeId. If the cast cannot be
2076 done, the variant is still changed to the requested type, but is left in a cleared
2077 null state similar to that constructed by QVariant(Type).
2078
2079 Returns \c true if the current type of the variant was successfully cast;
2080 otherwise returns \c false.
2081
2082 A QVariant containing a pointer to a type derived from QObject will also convert
2083 and return true for this function if a qobject_cast to the type described
2084 by \a targetTypeId would succeed. Note that this only works for QObject subclasses
2085 which use the Q_OBJECT macro.
2086
2087 \note converting QVariants that are null due to not being initialized or having
2088 failed a previous conversion will always fail, changing the type, remaining null,
2089 and returning \c false.
2090
2091 \sa canConvert(), clear()
2092*/
2093
2094/*!
2095 Casts the variant to the requested type, \a targetType. If the cast cannot be
2096 done, the variant is still changed to the requested type, but is left in a cleared
2097 null state similar to that constructed by QVariant(Type).
2098
2099 Returns \c true if the current type of the variant was successfully cast;
2100 otherwise returns \c false.
2101
2102 A QVariant containing a pointer to a type derived from QObject will also convert
2103 and return true for this function if a qobject_cast to the type described
2104 by \a targetType would succeed. Note that this only works for QObject subclasses
2105 which use the Q_OBJECT macro.
2106
2107 \note converting QVariants that are null due to not being initialized or having
2108 failed a previous conversion will always fail, changing the type, remaining null,
2109 and returning \c false.
2110
2111 \since 6.0
2112
2113 \sa canConvert(), clear()
2114*/
2115
2116bool QVariant::convert(QMetaType targetType)
2117{
2118 if (d.type() == targetType)
2119 return targetType.isValid();
2120
2121 QVariant oldValue = *this;
2122
2123 clear();
2124 create(type: targetType, copy: nullptr);
2125 if (!oldValue.canConvert(targetType))
2126 return false;
2127
2128 // Fail if the value is not initialized or was forced null by a previous failed convert.
2129 if (oldValue.d.is_null && oldValue.d.type().id() != QMetaType::Nullptr)
2130 return false;
2131
2132 bool ok = QMetaType::convert(fromType: oldValue.d.type(), from: oldValue.constData(), toType: targetType, to: data());
2133 d.is_null = !ok;
2134 return ok;
2135}
2136
2137/*!
2138 \fn bool QVariant::convert(int type, void *ptr) const
2139 \internal
2140 Created for qvariant_cast() usage
2141*/
2142bool QVariant::convert(int type, void *ptr) const
2143{
2144 return QMetaType::convert(fromType: d.type(), from: constData(), toType: QMetaType(type), to: ptr);
2145}
2146
2147/*!
2148 \internal
2149*/
2150bool QVariant::view(int type, void *ptr)
2151{
2152 return QMetaType::view(fromType: d.type(), from: data(), toType: QMetaType(type), to: ptr);
2153}
2154
2155/*!
2156 \fn bool QVariant::operator==(const QVariant &lhs, const QVariant &rhs)
2157
2158 Returns \c true if \a lhs and \a rhs are equal; otherwise returns \c false.
2159
2160 QVariant uses the equality operator of the type() contained to check for
2161 equality.
2162
2163 Variants of different types will always compare as not equal with a few
2164 exceptions:
2165
2166 \list
2167 \li If both types are numeric types (integers and floatins point numbers)
2168 Qt will compare those types using standard C++ type promotion rules.
2169 \li If one type is numeric and the other one a QString, Qt will try to
2170 convert the QString to a matching numeric type and if successful compare
2171 those.
2172 \li If both variants contain pointers to QObject derived types, QVariant
2173 will check whether the types are related and point to the same object.
2174 \endlist
2175
2176 The result of the function is not affected by the result of QVariant::isNull,
2177 which means that two values can be equal even if one of them is null and
2178 another is not.
2179*/
2180
2181/*!
2182 \fn bool QVariant::operator!=(const QVariant &lhs, const QVariant &rhs)
2183
2184 Returns \c false if \a lhs and \a rhs are equal; otherwise returns \c true.
2185
2186 QVariant uses the equality operator of the type() contained to check for
2187 equality.
2188
2189 Variants of different types will always compare as not equal with a few
2190 exceptions:
2191
2192 \list
2193 \li If both types are numeric types (integers and floatins point numbers)
2194 Qt will compare those types using standard C++ type promotion rules.
2195 \li If one type is numeric and the other one a QString, Qt will try to
2196 convert the QString to a matching numeric type and if successful compare
2197 those.
2198 \li If both variants contain pointers to QObject derived types, QVariant
2199 will check whether the types are related and point to the same object.
2200 \endlist
2201*/
2202
2203static bool qIsNumericType(uint tp)
2204{
2205 static const qulonglong numericTypeBits =
2206 Q_UINT64_C(1) << QMetaType::QString |
2207 Q_UINT64_C(1) << QMetaType::Bool |
2208 Q_UINT64_C(1) << QMetaType::Double |
2209 Q_UINT64_C(1) << QMetaType::Float |
2210 Q_UINT64_C(1) << QMetaType::Char |
2211 Q_UINT64_C(1) << QMetaType::Char16 |
2212 Q_UINT64_C(1) << QMetaType::Char32 |
2213 Q_UINT64_C(1) << QMetaType::SChar |
2214 Q_UINT64_C(1) << QMetaType::UChar |
2215 Q_UINT64_C(1) << QMetaType::Short |
2216 Q_UINT64_C(1) << QMetaType::UShort |
2217 Q_UINT64_C(1) << QMetaType::Int |
2218 Q_UINT64_C(1) << QMetaType::UInt |
2219 Q_UINT64_C(1) << QMetaType::Long |
2220 Q_UINT64_C(1) << QMetaType::ULong |
2221 Q_UINT64_C(1) << QMetaType::LongLong |
2222 Q_UINT64_C(1) << QMetaType::ULongLong;
2223 return tp < (CHAR_BIT * sizeof numericTypeBits) ? numericTypeBits & (Q_UINT64_C(1) << tp) : false;
2224}
2225
2226static bool qIsFloatingPoint(uint tp)
2227{
2228 return tp == QMetaType::Double || tp == QMetaType::Float || tp == QMetaType::Float16;
2229}
2230
2231static bool canBeNumericallyCompared(const QtPrivate::QMetaTypeInterface *iface1,
2232 const QtPrivate::QMetaTypeInterface *iface2)
2233{
2234 if (!iface1 || !iface2)
2235 return false;
2236
2237 // We don't need QMetaType::id() here because the type Id is always stored
2238 // directly for all built-in types.
2239 bool isNumeric1 = qIsNumericType(tp: iface1->typeId);
2240 bool isNumeric2 = qIsNumericType(tp: iface2->typeId);
2241
2242 // if they're both numeric (or QString), then they can be compared
2243 if (isNumeric1 && isNumeric2)
2244 return true;
2245
2246 bool isEnum1 = iface1->flags & QMetaType::IsEnumeration;
2247 bool isEnum2 = iface2->flags & QMetaType::IsEnumeration;
2248
2249 // if both are enums, we can only compare if they are the same enum
2250 // (the language does allow comparing two different enum types, but that's
2251 // usually considered poor coding and produces a warning)
2252 if (isEnum1 && isEnum2)
2253 return QMetaType(iface1) == QMetaType(iface2);
2254
2255 // if one is an enum and the other is a numeric, we can compare too
2256 if (isEnum1 && isNumeric2)
2257 return true;
2258 if (isNumeric1 && isEnum2)
2259 return true;
2260
2261 // we need at least one enum and one numeric...
2262 return false;
2263}
2264
2265static int numericTypePromotion(const QtPrivate::QMetaTypeInterface *iface1,
2266 const QtPrivate::QMetaTypeInterface *iface2)
2267{
2268 Q_ASSERT(canBeNumericallyCompared(iface1, iface2));
2269
2270 // We don't need QMetaType::id() here because the type Id is always stored
2271 // directly for the types we're comparing against below.
2272 uint t1 = iface1->typeId;
2273 uint t2 = iface2->typeId;
2274
2275 if ((t1 == QMetaType::Bool && t2 == QMetaType::QString) ||
2276 (t2 == QMetaType::Bool && t1 == QMetaType::QString))
2277 return QMetaType::Bool;
2278
2279 // C++ integral ranks: (4.13 Integer conversion rank [conv.rank])
2280 // bool < signed char < short < int < long < long long
2281 // unsigneds have the same rank as their signed counterparts
2282 // C++ integral promotion rules (4.5 Integral Promotions [conv.prom])
2283 // - any type with rank less than int can be converted to int or unsigned int
2284 // 5 Expressions [expr] paragraph 9:
2285 // - if either operand is double, the other shall be converted to double
2286 // - " " float, " " " float
2287 // - if both operands have the same type, no further conversion is needed.
2288 // - if both are signed or if both are unsigned, convert to the one with highest rank
2289 // - if the unsigned has higher or same rank, convert the signed to the unsigned one
2290 // - if the signed can represent all values of the unsigned, convert to the signed
2291 // - otherwise, convert to the unsigned corresponding to the rank of the signed
2292
2293 // floating point: we deviate from the C++ standard by always using qreal
2294 if (qIsFloatingPoint(tp: t1) || qIsFloatingPoint(tp: t2))
2295 return QMetaType::QReal;
2296
2297 auto isUnsigned = [](uint tp) {
2298 // only types for which sizeof(T) >= sizeof(int); lesser ones promote to int
2299 return tp == QMetaType::ULongLong || tp == QMetaType::ULong ||
2300 tp == QMetaType::UInt || tp == QMetaType::Char32;
2301 };
2302 bool isUnsigned1 = isUnsigned(t1);
2303 bool isUnsigned2 = isUnsigned(t2);
2304
2305 // integral rules:
2306 // 1) if either type is a 64-bit unsigned, compare as 64-bit unsigned
2307 if (isUnsigned1 && iface1->size > sizeof(int))
2308 return QMetaType::ULongLong;
2309 if (isUnsigned2 && iface2->size > sizeof(int))
2310 return QMetaType::ULongLong;
2311
2312 // 2) if either type is 64-bit, compare as 64-bit signed
2313 if (iface1->size > sizeof(int) || iface2->size > sizeof(int))
2314 return QMetaType::LongLong;
2315
2316 // 3) if either type is 32-bit unsigned, compare as 32-bit unsigned
2317 if (isUnsigned1 || isUnsigned2)
2318 return QMetaType::UInt;
2319
2320 // 4) otherwise, just do int promotion
2321 return QMetaType::Int;
2322}
2323
2324template <typename Numeric> static QPartialOrdering spaceShip(Numeric lhs, Numeric rhs)
2325{
2326 if (lhs == rhs)
2327 return QPartialOrdering::Equivalent;
2328 if constexpr (std::numeric_limits<Numeric>::has_quiet_NaN) {
2329 if (std::isnan(lhs) || std::isnan(rhs))
2330 return QPartialOrdering::Unordered;
2331 }
2332
2333 bool smaller;
2334 if constexpr (std::is_same_v<Numeric, QObject *>)
2335 smaller = std::less<QObject *>()(lhs, rhs); // can't use less all the time because of bool
2336 else
2337 smaller = lhs < rhs;
2338 return smaller ? QPartialOrdering::Less : QPartialOrdering::Greater;
2339}
2340
2341static QPartialOrdering integralCompare(uint promotedType, const QVariant::Private *d1, const QVariant::Private *d2)
2342{
2343 // use toLongLong to retrieve the data, it gets us all the bits
2344 std::optional<qlonglong> l1 = qConvertToNumber(d: d1, allowStringToBool: promotedType == QMetaType::Bool);
2345 std::optional<qlonglong> l2 = qConvertToNumber(d: d2, allowStringToBool: promotedType == QMetaType::Bool);
2346 if (!l1 || !l2)
2347 return QPartialOrdering::Unordered;
2348 if (promotedType == QMetaType::UInt)
2349 return spaceShip<uint>(lhs: *l1, rhs: *l2);
2350 if (promotedType == QMetaType::LongLong)
2351 return spaceShip<qlonglong>(lhs: *l1, rhs: *l2);
2352 if (promotedType == QMetaType::ULongLong)
2353 return spaceShip<qulonglong>(lhs: *l1, rhs: *l2);
2354
2355 return spaceShip<int>(lhs: *l1, rhs: *l2);
2356}
2357
2358static QPartialOrdering numericCompare(const QVariant::Private *d1, const QVariant::Private *d2)
2359{
2360 uint promotedType = numericTypePromotion(iface1: d1->typeInterface(), iface2: d2->typeInterface());
2361 if (promotedType != QMetaType::QReal)
2362 return integralCompare(promotedType, d1, d2);
2363
2364 // floating point comparison
2365 const auto r1 = qConvertToRealNumber(d: d1);
2366 const auto r2 = qConvertToRealNumber(d: d2);
2367 if (!r1 || !r2)
2368 return QPartialOrdering::Unordered;
2369 if (*r1 == *r2)
2370 return QPartialOrdering::Equivalent;
2371
2372 return spaceShip(lhs: *r1, rhs: *r2);
2373}
2374
2375#ifndef QT_BOOTSTRAPPED
2376static bool qvCanConvertMetaObject(QMetaType fromType, QMetaType toType)
2377{
2378 if ((fromType.flags() & QMetaType::PointerToQObject)
2379 && (toType.flags() & QMetaType::PointerToQObject)) {
2380 const QMetaObject *f = fromType.metaObject();
2381 const QMetaObject *t = toType.metaObject();
2382 return f && t && (f->inherits(metaObject: t) || t->inherits(metaObject: f));
2383 }
2384 return false;
2385}
2386
2387static QPartialOrdering pointerCompare(const QVariant::Private *d1, const QVariant::Private *d2)
2388{
2389 return spaceShip<QObject *>(lhs: d1->get<QObject *>(), rhs: d2->get<QObject *>());
2390}
2391#endif
2392
2393/*!
2394 \internal
2395 */
2396bool QVariant::equals(const QVariant &v) const
2397{
2398 auto metatype = d.type();
2399
2400 if (metatype != v.metaType()) {
2401 // try numeric comparisons, with C++ type promotion rules (no conversion)
2402 if (canBeNumericallyCompared(iface1: metatype.iface(), iface2: v.d.type().iface()))
2403 return numericCompare(d1: &d, d2: &v.d) == QPartialOrdering::Equivalent;
2404#ifndef QT_BOOTSTRAPPED
2405 // if both types are related pointers to QObjects, check if they point to the same object
2406 if (qvCanConvertMetaObject(fromType: metatype, toType: v.metaType()))
2407 return pointerCompare(d1: &d, d2: &v.d) == QPartialOrdering::Equivalent;
2408#endif
2409 return false;
2410 }
2411
2412 // For historical reasons: QVariant() == QVariant()
2413 if (!metatype.isValid())
2414 return true;
2415
2416 return metatype.equals(lhs: d.storage(), rhs: v.d.storage());
2417}
2418
2419/*!
2420 Compares the objects at \a lhs and \a rhs for ordering.
2421
2422 Returns QPartialOrdering::Unordered if comparison is not supported
2423 or the values are unordered. Otherwise, returns
2424 QPartialOrdering::Less, QPartialOrdering::Equivalent or
2425 QPartialOrdering::Greater if \a lhs is less than, equivalent
2426 to or greater than \a rhs, respectively.
2427
2428 If the variants contain data with a different metatype, the values are considered
2429 unordered unless they are both of numeric or pointer types, where regular numeric or
2430 pointer comparison rules will be used.
2431 \note: If a numeric comparison is done and at least one value is NaN, QPartialOrdering::Unordered
2432 is returned.
2433
2434 If both variants contain data of the same metatype, the method will use the
2435 QMetaType::compare method to determine the ordering of the two variants, which can
2436 also indicate that it can't establish an ordering between the two values.
2437
2438 \since 6.0
2439 \sa QMetaType::compare(), QMetaType::isOrdered()
2440*/
2441QPartialOrdering QVariant::compare(const QVariant &lhs, const QVariant &rhs)
2442{
2443 QMetaType t = lhs.d.type();
2444 if (t != rhs.d.type()) {
2445 // try numeric comparisons, with C++ type promotion rules (no conversion)
2446 if (canBeNumericallyCompared(iface1: lhs.d.type().iface(), iface2: rhs.d.type().iface()))
2447 return numericCompare(d1: &lhs.d, d2: &rhs.d);
2448#ifndef QT_BOOTSTRAPPED
2449 if (qvCanConvertMetaObject(fromType: lhs.metaType(), toType: rhs.metaType()))
2450 return pointerCompare(d1: &lhs.d, d2: &rhs.d);
2451#endif
2452 return QPartialOrdering::Unordered;
2453 }
2454 return t.compare(lhs: lhs.constData(), rhs: rhs.constData());
2455}
2456
2457/*!
2458 \fn const void *QVariant::constData() const
2459 \fn const void* QVariant::data() const
2460
2461 Returns a pointer to the contained object as a generic void* that cannot be
2462 written to.
2463
2464 \sa get_if(), QMetaType
2465 */
2466
2467/*!
2468 Returns a pointer to the contained object as a generic void* that can be
2469 written to.
2470
2471 This function detaches the QVariant. When called on a \l{isNull}{null-QVariant},
2472 the QVariant will not be null after the call.
2473
2474 \sa get_if(), QMetaType
2475*/
2476void *QVariant::data()
2477{
2478 detach();
2479 // set is_null to false, as the caller is likely to write some data into this variant
2480 d.is_null = false;
2481 return const_cast<void *>(constData());
2482}
2483
2484/*!
2485 \since 6.6
2486 \fn template <typename T> const T* QVariant::get_if(const QVariant *v)
2487 \fn template <typename T> T* QVariant::get_if(QVariant *v)
2488
2489 If \a v contains an object of type \c T, returns a pointer to the contained
2490 object, otherwise returns \nullptr.
2491
2492 The overload taking a mutable \a v detaches \a v: When called on a
2493 \l{isNull()}{null} \a v with matching type \c T, \a v will not be null
2494 after the call.
2495
2496 These functions are provided for compatibility with \c{std::variant}.
2497
2498 \sa data()
2499*/
2500
2501/*!
2502 \since 6.6
2503 \fn template <typename T> T &QVariant::get(QVariant &v)
2504 \fn template <typename T> const T &QVariant::get(const QVariant &v)
2505 \fn template <typename T> T &&QVariant::get(QVariant &&v)
2506 \fn template <typename T> const T &&QVariant::get(const QVariant &&v)
2507
2508 If \a v contains an object of type \c T, returns a reference to the contained
2509 object, otherwise the call has undefined behavior.
2510
2511 The overloads taking a mutable \a v detach \a v: When called on a
2512 \l{isNull()}{null} \a v with matching type \c T, \a v will not be null
2513 after the call.
2514
2515 These functions are provided for compatibility with \c{std::variant}.
2516
2517 \sa get_if(), data()
2518*/
2519
2520/*!
2521 Returns \c true if this is a null variant, false otherwise.
2522
2523 A variant is considered null if it contains no initialized value or a null pointer.
2524
2525 \note This behavior has been changed from Qt 5, where isNull() would also
2526 return true if the variant contained an object of a builtin type with an isNull()
2527 method that returned true for that object.
2528
2529 \sa convert()
2530*/
2531bool QVariant::isNull() const
2532{
2533 if (d.is_null || !metaType().isValid())
2534 return true;
2535 if (metaType().flags() & QMetaType::IsPointer)
2536 return d.get<void *>() == nullptr;
2537 return false;
2538}
2539
2540#ifndef QT_NO_DEBUG_STREAM
2541QDebug QVariant::qdebugHelper(QDebug dbg) const
2542{
2543 QDebugStateSaver saver(dbg);
2544 const uint typeId = d.type().id();
2545 dbg.nospace() << "QVariant(";
2546 if (typeId != QMetaType::UnknownType) {
2547 dbg << d.type().name() << ", ";
2548 bool streamed = d.type().debugStream(dbg, rhs: d.storage());
2549 if (!streamed && canConvert<QString>())
2550 dbg << toString();
2551 } else {
2552 dbg << "Invalid";
2553 }
2554 dbg << ')';
2555 return dbg;
2556}
2557
2558QVariant QVariant::moveConstruct(QMetaType type, void *data)
2559{
2560 QVariant var;
2561 var.d = QVariant::Private(type.d_ptr);
2562 customConstruct<ForceMove, NonNull>(iface: type.d_ptr, d: &var.d, copy: data);
2563 return var;
2564}
2565
2566QVariant QVariant::copyConstruct(QMetaType type, const void *data)
2567{
2568 QVariant var;
2569 var.d = QVariant::Private(type.d_ptr);
2570 customConstruct<UseCopy, NonNull>(iface: type.d_ptr, d: &var.d, copy: data);
2571 return var;
2572}
2573
2574#if QT_DEPRECATED_SINCE(6, 0)
2575QT_WARNING_PUSH
2576QT_WARNING_DISABLE_DEPRECATED
2577
2578QDebug operator<<(QDebug dbg, const QVariant::Type p)
2579{
2580 QDebugStateSaver saver(dbg);
2581 dbg.nospace() << "QVariant::"
2582 << (int(p) != int(QMetaType::UnknownType)
2583 ? QMetaType(p).name()
2584 : "Invalid");
2585 return dbg;
2586}
2587
2588QT_WARNING_POP
2589#endif
2590
2591#endif
2592
2593/*! \fn template<typename T, typename = std::enable_if_t<!std::is_same_v<std::decay_t<T>, QVariant>>> void QVariant::setValue(T &&value)
2594
2595 Stores a copy of \a value. If \c{T} is a type that QVariant
2596 doesn't support, QMetaType is used to store the value. A compile
2597 error will occur if QMetaType doesn't handle the type.
2598
2599 Example:
2600
2601 \snippet code/src_corelib_kernel_qvariant.cpp 4
2602
2603 \sa value(), fromValue(), canConvert()
2604 */
2605
2606/*! \fn void QVariant::setValue(const QVariant &value)
2607
2608 Copies \a value over this QVariant. It is equivalent to simply
2609 assigning \a value to this QVariant.
2610*/
2611
2612/*! \fn void QVariant::setValue(QVariant &&value)
2613
2614 Moves \a value over this QVariant. It is equivalent to simply
2615 move assigning \a value to this QVariant.
2616*/
2617
2618/*! \fn template<typename T> T QVariant::value() const &
2619
2620 Returns the stored value converted to the template type \c{T}.
2621 Call canConvert() to find out whether a type can be converted.
2622 If the value cannot be converted, a \l{default-constructed value}
2623 will be returned.
2624
2625 If the type \c{T} is supported by QVariant, this function behaves
2626 exactly as toString(), toInt() etc.
2627
2628 Example:
2629
2630 \snippet code/src_corelib_kernel_qvariant.cpp 5
2631
2632 If the QVariant contains a pointer to a type derived from QObject then
2633 \c{T} may be any QObject type. If the pointer stored in the QVariant can be
2634 qobject_cast to T, then that result is returned. Otherwise \nullptr is
2635 returned. Note that this only works for QObject subclasses which use
2636 the Q_OBJECT macro.
2637
2638 If the QVariant contains a sequential container and \c{T} is QVariantList, the
2639 elements of the container will be converted into \l {QVariant}s and returned as a QVariantList.
2640
2641 \snippet code/src_corelib_kernel_qvariant.cpp 9
2642
2643 \sa setValue(), fromValue(), canConvert(), Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE()
2644*/
2645
2646/*! \fn template<typename T> T QVariant::view()
2647
2648 Returns a mutable view of template type \c{T} on the stored value.
2649 Call canView() to find out whether such a view is supported.
2650 If no such view can be created, returns the stored value converted to the
2651 template type \c{T}. Call canConvert() to find out whether a type can be
2652 converted. If the value can neither be viewed nor converted, a
2653 \l{default-constructed value} will be returned.
2654
2655 \sa canView(), Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE()
2656*/
2657
2658/*! \fn template<typename T> bool QVariant::canConvert() const
2659
2660 Returns \c true if the variant can be converted to the template type \c{T},
2661 otherwise false.
2662
2663 Example:
2664
2665 \snippet code/src_corelib_kernel_qvariant.cpp 6
2666
2667 A QVariant containing a pointer to a type derived from QObject will also return true for this
2668 function if a qobject_cast to the template type \c{T} would succeed. Note that this only works
2669 for QObject subclasses which use the Q_OBJECT macro.
2670
2671 \sa convert()
2672*/
2673
2674/*! \fn template<typename T> bool QVariant::canView() const
2675
2676 Returns \c true if a mutable view of the template type \c{T} can be created on this variant,
2677 otherwise \c false.
2678
2679 \sa value()
2680*/
2681
2682/*! \fn template<typename T> static QVariant QVariant::fromValue(const T &value)
2683
2684 Returns a QVariant containing a copy of \a value. Behaves
2685 exactly like setValue() otherwise.
2686
2687 Example:
2688
2689 \snippet code/src_corelib_kernel_qvariant.cpp 7
2690
2691 \sa setValue(), value()
2692*/
2693
2694/*! \fn template<typename T, QVariant::if_rvalue<T> = true> static QVariant QVariant::fromValue(T &&value)
2695
2696 \since 6.6
2697 \overload
2698*/
2699
2700/*! \fn template<typename... Types> QVariant QVariant::fromStdVariant(const std::variant<Types...> &value)
2701 \since 5.11
2702
2703 Returns a QVariant with the type and value of the active variant of \a value. If
2704 the active type is std::monostate a default QVariant is returned.
2705
2706 \note With this method you do not need to register the variant as a Qt metatype,
2707 since the std::variant is resolved before being stored. The component types
2708 should be registered however.
2709
2710 \sa fromValue()
2711*/
2712
2713/*!
2714 \fn template<typename... Types> QVariant QVariant::fromStdVariant(std::variant<Types...> &&value)
2715 \since 6.6
2716 \overload
2717*/
2718
2719
2720/*!
2721 \since 6.7
2722
2723 Creates a variant of type \a type, and initializes it with
2724 a copy of \c{*copy} if \a copy is not \nullptr (in which case, \a copy
2725 must point to an object of type \a type).
2726
2727 Note that you have to pass the address of the object you want stored.
2728
2729 Usually, you never have to use this constructor, use QVariant::fromValue()
2730 instead to construct variants from the pointer types represented by
2731 \c QMetaType::VoidStar, and \c QMetaType::QObjectStar.
2732
2733 If \a type does not support copy construction and \a copy is not \nullptr,
2734 the variant will be invalid. Similarly, if \a copy is \nullptr and
2735 \a type does not support default construction, the variant will be
2736 invalid.
2737
2738 Returns the QVariant created as described above.
2739
2740 \sa QVariant::fromValue(), QMetaType::Type
2741*/
2742QVariant QVariant::fromMetaType(QMetaType type, const void *copy)
2743{
2744 QVariant result;
2745 type.registerType();
2746 const auto iface = type.iface();
2747 if (isValidMetaTypeForVariant(iface, copy)) {
2748 result.d = Private(iface);
2749 customConstruct(iface, d: &result.d, copy);
2750 }
2751 return result;
2752}
2753
2754/*!
2755 \fn template<typename T> T qvariant_cast(const QVariant &value)
2756 \relates QVariant
2757
2758 Returns the given \a value converted to the template type \c{T}.
2759
2760 This function is equivalent to QVariant::value().
2761
2762 \sa QVariant::value()
2763*/
2764
2765/*!
2766 \fn template<typename T> T QVariant::qvariant_cast(QVariant &&value)
2767 \overload
2768 \since 6.7
2769
2770 Returns the given \a value converted to the template type \c{T}.
2771*/
2772
2773/*! \fn template<typename T> T qVariantValue(const QVariant &value)
2774 \relates QVariant
2775 \deprecated
2776
2777 Returns the given \a value converted to the template type \c{T}.
2778
2779 This function is equivalent to
2780 \l{QVariant::value()}{QVariant::value}<T>(\a value).
2781
2782 \note This function was provided as a workaround for MSVC 6
2783 which did not support member template functions. It is advised
2784 to use the other form in new code.
2785
2786 \sa QVariant::value(), qvariant_cast()
2787*/
2788
2789/*! \fn bool qVariantCanConvert(const QVariant &value)
2790 \relates QVariant
2791 \deprecated
2792
2793 Returns \c true if the given \a value can be converted to the
2794 template type specified; otherwise returns \c false.
2795
2796 This function is equivalent to QVariant::canConvert(\a value).
2797
2798 \note This function was provided as a workaround for MSVC 6
2799 which did not support member template functions. It is advised
2800 to use the other form in new code.
2801
2802 \sa QVariant::canConvert()
2803*/
2804
2805/*!
2806 \typedef QVariantList
2807 \relates QVariant
2808
2809 Synonym for QList<QVariant>.
2810*/
2811
2812/*!
2813 \typedef QVariantMap
2814 \relates QVariant
2815
2816 Synonym for QMap<QString, QVariant>.
2817*/
2818
2819/*!
2820 \typedef QVariantHash
2821 \relates QVariant
2822 \since 4.5
2823
2824 Synonym for QHash<QString, QVariant>.
2825*/
2826
2827/*!
2828 \typedef QVariant::DataPtr
2829 \internal
2830*/
2831/*! \typedef QVariant::f_construct
2832 \internal
2833*/
2834
2835/*! \typedef QVariant::f_clear
2836 \internal
2837*/
2838
2839/*! \typedef QVariant::f_null
2840 \internal
2841*/
2842
2843/*! \typedef QVariant::f_load
2844 \internal
2845*/
2846
2847/*! \typedef QVariant::f_save
2848 \internal
2849*/
2850
2851/*! \typedef QVariant::f_compare
2852 \internal
2853*/
2854
2855/*! \typedef QVariant::f_convert
2856 \internal
2857*/
2858
2859/*! \typedef QVariant::f_canConvert
2860 \internal
2861*/
2862
2863/*! \typedef QVariant::f_debugStream
2864 \internal
2865*/
2866
2867/*!
2868 \fn DataPtr &QVariant::data_ptr()
2869 \internal
2870*/
2871
2872/*!
2873 \fn const DataPtr &QVariant::data_ptr() const
2874 \internal
2875*/
2876
2877/*!
2878 \internal
2879 */
2880const void *QtPrivate::QVariantTypeCoercer::convert(const QVariant &value, const QMetaType &type)
2881{
2882 if (type == QMetaType::fromType<QVariant>())
2883 return &value;
2884
2885 if (type == value.metaType())
2886 return value.constData();
2887
2888 if (value.canConvert(targetType: type)) {
2889 converted = value;
2890 if (converted.convert(targetType: type))
2891 return converted.constData();
2892 }
2893
2894 return nullptr;
2895}
2896
2897/*!
2898 \internal
2899 */
2900const void *QtPrivate::QVariantTypeCoercer::coerce(const QVariant &value, const QMetaType &type)
2901{
2902 if (const void *result = convert(value, type))
2903 return result;
2904
2905 converted = QVariant(type);
2906 return converted.constData();
2907}
2908
2909/*!
2910 \class QVariantRef
2911 \since 6.0
2912 \inmodule QtCore
2913 \brief The QVariantRef acts as a non-const reference to a QVariant.
2914
2915 As the generic iterators don't actually instantiate a QVariant on each
2916 step, they cannot return a reference to one from operator*(). QVariantRef
2917 provides the same functionality as an actual reference to a QVariant would,
2918 but is backed by a pointer given as template parameter. The template is
2919 implemented for pointers of type QSequentialIterator and
2920 QAssociativeIterator.
2921*/
2922
2923/*!
2924 \fn template<typename Pointer> QVariantRef<Pointer>::QVariantRef(const Pointer *pointer)
2925
2926 Creates a QVariantRef from an \a pointer.
2927 */
2928
2929/*!
2930 \fn template<typename Pointer> QVariantRef<Pointer> &QVariantRef<Pointer>::operator=(const QVariant &value)
2931
2932 Assigns a new \a value to the value pointed to by the pointer this
2933 QVariantRef refers to.
2934 */
2935
2936/*!
2937 \fn template<typename Pointer> QVariantRef<Pointer> &QVariantRef<Pointer>::operator=(const QVariantRef &value)
2938
2939 Assigns a new \a value to the value pointed to by the pointer this
2940 QVariantRef refers to.
2941 */
2942
2943/*!
2944 \fn template<typename Pointer> QVariantRef<Pointer> &QVariantRef<Pointer>::operator=(QVariantRef &&value)
2945
2946 Assigns a new \a value to the value pointed to by the pointer this
2947 QVariantRef refers to.
2948*/
2949
2950/*!
2951 \fn template<typename Pointer> QVariantRef<Pointer>::operator QVariant() const
2952
2953 Resolves the QVariantRef to an actual QVariant.
2954*/
2955
2956/*!
2957 \fn template<typename Pointer> void swap(QVariantRef<Pointer> a, QVariantRef<Pointer> b)
2958
2959 Swaps the values pointed to by the pointers the QVariantRefs
2960 \a a and \a b refer to.
2961*/
2962
2963/*!
2964 \class QVariantConstPointer
2965 \since 6.0
2966 \inmodule QtCore
2967 \brief Emulated const pointer to QVariant based on a pointer.
2968
2969 QVariantConstPointer wraps a QVariant and returns it from its operator*().
2970 This makes it suitable as replacement for an actual const pointer. We cannot
2971 return an actual const pointer from generic iterators as the iterators don't
2972 hold an actual QVariant.
2973*/
2974
2975/*!
2976 Constructs a QVariantConstPointer from a \a variant.
2977 */
2978QVariantConstPointer::QVariantConstPointer(QVariant variant)
2979 : m_variant(std::move(variant))
2980{
2981}
2982
2983/*!
2984 Dereferences the QVariantConstPointer to retrieve its internal QVariant.
2985 */
2986QVariant QVariantConstPointer::operator*() const
2987{
2988 return m_variant;
2989}
2990
2991/*!
2992 Returns a const pointer to the QVariant, conforming to the
2993 conventions for operator->().
2994 */
2995const QVariant *QVariantConstPointer::operator->() const
2996{
2997 return &m_variant;
2998}
2999
3000/*!
3001 \class QVariantPointer
3002 \since 6.0
3003 \inmodule QtCore
3004 \brief QVariantPointer is a template class that emulates a pointer to QVariant based on a pointer.
3005
3006 QVariantConstPointer wraps a pointer and returns QVariantRef to it from its
3007 operator*(). This makes it suitable as replacement for an actual pointer. We
3008 cannot return an actual pointer from generic iterators as the iterators don't
3009 hold an actual QVariant.
3010*/
3011
3012/*!
3013 \fn template<typename Pointer> QVariantPointer<Pointer>::QVariantPointer(const Pointer *pointer)
3014
3015 Constructs a QVariantPointer from the given \a pointer.
3016 */
3017
3018/*!
3019 \fn template<typename Pointer> QVariantRef<Pointer> QVariantPointer<Pointer>::operator*() const
3020
3021 Dereferences the QVariantPointer to a QVariantRef.
3022 */
3023
3024/*!
3025 \fn template<typename Pointer> Pointer QVariantPointer<Pointer>::operator->() const
3026
3027 Dereferences and returns the pointer. The pointer is expected to also
3028 implement operator->().
3029 */
3030
3031QT_END_NAMESPACE
3032

Provided by KDAB

Privacy Policy
Learn Advanced QML with KDAB
Find out more

source code of qtbase/src/corelib/kernel/qvariant.cpp