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

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

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