1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtCore module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#ifndef QVARIANT_H
41#define QVARIANT_H
42
43#include <QtCore/qatomic.h>
44#include <QtCore/qbytearray.h>
45#include <QtCore/qlist.h>
46#include <QtCore/qmetatype.h>
47#include <QtCore/qmap.h>
48#include <QtCore/qhash.h>
49#include <QtCore/qstring.h>
50#include <QtCore/qstringlist.h>
51#include <QtCore/qobject.h>
52#ifndef QT_BOOTSTRAPPED
53#include <QtCore/qbytearraylist.h>
54#endif
55
56#if __has_include(<variant>) && __cplusplus >= 201703L
57#include <variant>
58#elif defined(Q_CLANG_QDOC)
59namespace std { template<typename...> struct variant; }
60#endif
61
62QT_BEGIN_NAMESPACE
63
64
65class QBitArray;
66class QDataStream;
67class QDate;
68class QDateTime;
69#if QT_CONFIG(easingcurve)
70class QEasingCurve;
71#endif
72class QLine;
73class QLineF;
74class QLocale;
75class QMatrix;
76class QTransform;
77class QStringList;
78class QTime;
79class QPoint;
80class QPointF;
81class QSize;
82class QSizeF;
83class QRect;
84class QRectF;
85#ifndef QT_NO_REGEXP
86class QRegExp;
87#endif // QT_NO_REGEXP
88#if QT_CONFIG(regularexpression)
89class QRegularExpression;
90#endif // QT_CONFIG(regularexpression)
91class QTextFormat;
92class QTextLength;
93class QUrl;
94class QVariant;
95class QVariantComparisonHelper;
96
97template<typename T>
98inline T qvariant_cast(const QVariant &);
99
100namespace QtPrivate {
101
102 template <typename Derived, typename Argument, typename ReturnType>
103 struct ObjectInvoker
104 {
105 static ReturnType invoke(Argument a)
106 {
107 return Derived::object(a);
108 }
109 };
110
111 template <typename Derived, typename Argument, typename ReturnType>
112 struct MetaTypeInvoker
113 {
114 static ReturnType invoke(Argument a)
115 {
116 return Derived::metaType(a);
117 }
118 };
119
120 template <typename Derived, typename T, typename Argument, typename ReturnType, bool = IsPointerToTypeDerivedFromQObject<T>::Value>
121 struct TreatAsQObjectBeforeMetaType : ObjectInvoker<Derived, Argument, ReturnType>
122 {
123 };
124
125 template <typename Derived, typename T, typename Argument, typename ReturnType>
126 struct TreatAsQObjectBeforeMetaType<Derived, T, Argument, ReturnType, false> : MetaTypeInvoker<Derived, Argument, ReturnType>
127 {
128 };
129
130 template<typename T> struct QVariantValueHelper;
131}
132
133class Q_CORE_EXPORT QVariant
134{
135 public:
136 enum Type {
137 Invalid = QMetaType::UnknownType,
138 Bool = QMetaType::Bool,
139 Int = QMetaType::Int,
140 UInt = QMetaType::UInt,
141 LongLong = QMetaType::LongLong,
142 ULongLong = QMetaType::ULongLong,
143 Double = QMetaType::Double,
144 Char = QMetaType::QChar,
145 Map = QMetaType::QVariantMap,
146 List = QMetaType::QVariantList,
147 String = QMetaType::QString,
148 StringList = QMetaType::QStringList,
149 ByteArray = QMetaType::QByteArray,
150 BitArray = QMetaType::QBitArray,
151 Date = QMetaType::QDate,
152 Time = QMetaType::QTime,
153 DateTime = QMetaType::QDateTime,
154 Url = QMetaType::QUrl,
155 Locale = QMetaType::QLocale,
156 Rect = QMetaType::QRect,
157 RectF = QMetaType::QRectF,
158 Size = QMetaType::QSize,
159 SizeF = QMetaType::QSizeF,
160 Line = QMetaType::QLine,
161 LineF = QMetaType::QLineF,
162 Point = QMetaType::QPoint,
163 PointF = QMetaType::QPointF,
164 RegExp = QMetaType::QRegExp,
165 RegularExpression = QMetaType::QRegularExpression,
166 Hash = QMetaType::QVariantHash,
167#if QT_CONFIG(easingcurve)
168 EasingCurve = QMetaType::QEasingCurve,
169#endif
170 Uuid = QMetaType::QUuid,
171#if QT_CONFIG(itemmodel)
172 ModelIndex = QMetaType::QModelIndex,
173 PersistentModelIndex = QMetaType::QPersistentModelIndex,
174#endif
175 LastCoreType = QMetaType::LastCoreType,
176
177 Font = QMetaType::QFont,
178 Pixmap = QMetaType::QPixmap,
179 Brush = QMetaType::QBrush,
180 Color = QMetaType::QColor,
181 Palette = QMetaType::QPalette,
182 Image = QMetaType::QImage,
183 Polygon = QMetaType::QPolygon,
184 Region = QMetaType::QRegion,
185 Bitmap = QMetaType::QBitmap,
186 Cursor = QMetaType::QCursor,
187 KeySequence = QMetaType::QKeySequence,
188 Pen = QMetaType::QPen,
189 TextLength = QMetaType::QTextLength,
190 TextFormat = QMetaType::QTextFormat,
191 Matrix = QMetaType::QMatrix,
192 Transform = QMetaType::QTransform,
193 Matrix4x4 = QMetaType::QMatrix4x4,
194 Vector2D = QMetaType::QVector2D,
195 Vector3D = QMetaType::QVector3D,
196 Vector4D = QMetaType::QVector4D,
197 Quaternion = QMetaType::QQuaternion,
198 PolygonF = QMetaType::QPolygonF,
199 Icon = QMetaType::QIcon,
200 LastGuiType = QMetaType::LastGuiType,
201
202 SizePolicy = QMetaType::QSizePolicy,
203
204 UserType = QMetaType::User,
205 LastType = 0xffffffff // need this so that gcc >= 3.4 allocates 32 bits for Type
206 };
207
208 QVariant() noexcept : d() {}
209 ~QVariant();
210 QVariant(Type type);
211 QVariant(int typeId, const void *copy);
212 QVariant(int typeId, const void *copy, uint flags);
213 QVariant(const QVariant &other);
214
215#ifndef QT_NO_DATASTREAM
216 QVariant(QDataStream &s);
217#endif
218
219 QVariant(int i);
220 QVariant(uint ui);
221 QVariant(qlonglong ll);
222 QVariant(qulonglong ull);
223 QVariant(bool b);
224 QVariant(double d);
225 QVariant(float f);
226#ifndef QT_NO_CAST_FROM_ASCII
227 QT_ASCII_CAST_WARN QVariant(const char *str);
228#endif
229
230 QVariant(const QByteArray &bytearray);
231 QVariant(const QBitArray &bitarray);
232 QVariant(const QString &string);
233 QVariant(QLatin1String string);
234 QVariant(const QStringList &stringlist);
235 QVariant(QChar qchar);
236 QVariant(const QDate &date);
237 QVariant(const QTime &time);
238 QVariant(const QDateTime &datetime);
239 QVariant(const QList<QVariant> &list);
240 QVariant(const QMap<QString,QVariant> &map);
241 QVariant(const QHash<QString,QVariant> &hash);
242#ifndef QT_NO_GEOM_VARIANT
243 QVariant(const QSize &size);
244 QVariant(const QSizeF &size);
245 QVariant(const QPoint &pt);
246 QVariant(const QPointF &pt);
247 QVariant(const QLine &line);
248 QVariant(const QLineF &line);
249 QVariant(const QRect &rect);
250 QVariant(const QRectF &rect);
251#endif
252 QVariant(const QLocale &locale);
253#ifndef QT_NO_REGEXP
254 QVariant(const QRegExp &regExp);
255#endif // QT_NO_REGEXP
256#if QT_CONFIG(regularexpression)
257 QVariant(const QRegularExpression &re);
258#endif // QT_CONFIG(regularexpression)
259#if QT_CONFIG(easingcurve)
260 QVariant(const QEasingCurve &easing);
261#endif
262 QVariant(const QUuid &uuid);
263#ifndef QT_BOOTSTRAPPED
264 QVariant(const QUrl &url);
265 QVariant(const QJsonValue &jsonValue);
266 QVariant(const QJsonObject &jsonObject);
267 QVariant(const QJsonArray &jsonArray);
268 QVariant(const QJsonDocument &jsonDocument);
269#endif // QT_BOOTSTRAPPED
270#if QT_CONFIG(itemmodel)
271 QVariant(const QModelIndex &modelIndex);
272 QVariant(const QPersistentModelIndex &modelIndex);
273#endif
274
275 QVariant& operator=(const QVariant &other);
276 inline QVariant(QVariant &&other) noexcept : d(other.d)
277 { other.d = Private(); }
278 inline QVariant &operator=(QVariant &&other) noexcept
279 { qSwap(d, other.d); return *this; }
280
281 inline void swap(QVariant &other) noexcept { qSwap(d, other.d); }
282
283 Type type() const;
284 int userType() const;
285 const char *typeName() const;
286
287 bool canConvert(int targetTypeId) const;
288 bool convert(int targetTypeId);
289
290 inline bool isValid() const;
291 bool isNull() const;
292
293 void clear();
294
295 void detach();
296 inline bool isDetached() const;
297
298 int toInt(bool *ok = nullptr) const;
299 uint toUInt(bool *ok = nullptr) const;
300 qlonglong toLongLong(bool *ok = nullptr) const;
301 qulonglong toULongLong(bool *ok = nullptr) const;
302 bool toBool() const;
303 double toDouble(bool *ok = nullptr) const;
304 float toFloat(bool *ok = nullptr) const;
305 qreal toReal(bool *ok = nullptr) const;
306 QByteArray toByteArray() const;
307 QBitArray toBitArray() const;
308 QString toString() const;
309 QStringList toStringList() const;
310 QChar toChar() const;
311 QDate toDate() const;
312 QTime toTime() const;
313 QDateTime toDateTime() const;
314 QList<QVariant> toList() const;
315 QMap<QString, QVariant> toMap() const;
316 QHash<QString, QVariant> toHash() const;
317
318#ifndef QT_NO_GEOM_VARIANT
319 QPoint toPoint() const;
320 QPointF toPointF() const;
321 QRect toRect() const;
322 QSize toSize() const;
323 QSizeF toSizeF() const;
324 QLine toLine() const;
325 QLineF toLineF() const;
326 QRectF toRectF() const;
327#endif
328 QLocale toLocale() const;
329#ifndef QT_NO_REGEXP
330 QRegExp toRegExp() const;
331#endif // QT_NO_REGEXP
332#if QT_CONFIG(regularexpression)
333 QRegularExpression toRegularExpression() const;
334#endif // QT_CONFIG(regularexpression)
335#if QT_CONFIG(easingcurve)
336 QEasingCurve toEasingCurve() const;
337#endif
338 QUuid toUuid() const;
339#ifndef QT_BOOTSTRAPPED
340 QUrl toUrl() const;
341 QJsonValue toJsonValue() const;
342 QJsonObject toJsonObject() const;
343 QJsonArray toJsonArray() const;
344 QJsonDocument toJsonDocument() const;
345#endif // QT_BOOTSTRAPPED
346#if QT_CONFIG(itemmodel)
347 QModelIndex toModelIndex() const;
348 QPersistentModelIndex toPersistentModelIndex() const;
349#endif
350
351#ifndef QT_NO_DATASTREAM
352 void load(QDataStream &ds);
353 void save(QDataStream &ds) const;
354#endif
355 static const char *typeToName(int typeId);
356 static Type nameToType(const char *name);
357
358 void *data();
359 const void *constData() const;
360 inline const void *data() const { return constData(); }
361
362 template<typename T>
363 inline void setValue(const T &value);
364
365 template<typename T>
366 inline T value() const
367 { return qvariant_cast<T>(*this); }
368
369 template<typename T>
370 static inline QVariant fromValue(const T &value)
371 { return QVariant(qMetaTypeId<T>(), &value, QTypeInfo<T>::isPointer); }
372
373#if (__has_include(<variant>) && __cplusplus >= 201703L) || defined(Q_CLANG_QDOC)
374 template<typename... Types>
375 static inline QVariant fromStdVariant(const std::variant<Types...> &value)
376 {
377 if (value.valueless_by_exception())
378 return QVariant();
379 return std::visit([](const auto &arg) { return fromValue(arg); }, value);
380 }
381#endif
382
383 template<typename T>
384 bool canConvert() const
385 { return canConvert(qMetaTypeId<T>()); }
386
387 public:
388 struct PrivateShared
389 {
390 inline PrivateShared(void *v) : ptr(v), ref(1) { }
391 void *ptr;
392 QAtomicInt ref;
393 };
394 struct Private
395 {
396 inline Private() noexcept : type(Invalid), is_shared(false), is_null(true)
397 { data.ptr = nullptr; }
398
399 // Internal constructor for initialized variants.
400 explicit inline Private(uint variantType) noexcept
401 : type(variantType), is_shared(false), is_null(false)
402 {}
403
404#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
405 Private(const Private &other) noexcept
406 : data(other.data), type(other.type),
407 is_shared(other.is_shared), is_null(other.is_null)
408 {}
409 Private &operator=(const Private &other) noexcept = default;
410#endif
411 union Data
412 {
413 char c;
414 uchar uc;
415 short s;
416 signed char sc;
417 ushort us;
418 int i;
419 uint u;
420 long l;
421 ulong ul;
422 bool b;
423 double d;
424 float f;
425 qreal real;
426 qlonglong ll;
427 qulonglong ull;
428 QObject *o;
429 void *ptr;
430 PrivateShared *shared;
431 } data;
432 uint type : 30;
433 uint is_shared : 1;
434 uint is_null : 1;
435 };
436 public:
437 typedef void (*f_construct)(Private *, const void *);
438 typedef void (*f_clear)(Private *);
439 typedef bool (*f_null)(const Private *);
440#ifndef QT_NO_DATASTREAM
441 typedef void (*f_load)(Private *, QDataStream &);
442 typedef void (*f_save)(const Private *, QDataStream &);
443#endif
444 typedef bool (*f_compare)(const Private *, const Private *);
445 typedef bool (*f_convert)(const QVariant::Private *d, int t, void *, bool *);
446 typedef bool (*f_canConvert)(const QVariant::Private *d, int t);
447 typedef void (*f_debugStream)(QDebug, const QVariant &);
448 struct Handler {
449 f_construct construct;
450 f_clear clear;
451 f_null isNull;
452#ifndef QT_NO_DATASTREAM
453 f_load load;
454 f_save save;
455#endif
456 f_compare compare;
457 f_convert convert;
458 f_canConvert canConvert;
459 f_debugStream debugStream;
460 };
461
462 inline bool operator==(const QVariant &v) const
463 { return cmp(v); }
464 inline bool operator!=(const QVariant &v) const
465 { return !cmp(v); }
466#if QT_DEPRECATED_SINCE(5, 15)
467 QT_DEPRECATED inline bool operator<(const QVariant &v) const
468 { return compare(v) < 0; }
469 QT_DEPRECATED inline bool operator<=(const QVariant &v) const
470 { return compare(v) <= 0; }
471 QT_DEPRECATED inline bool operator>(const QVariant &v) const
472 { return compare(v) > 0; }
473 QT_DEPRECATED inline bool operator>=(const QVariant &v) const
474 { return compare(v) >= 0; }
475#endif
476
477protected:
478 friend inline bool operator==(const QVariant &, const QVariantComparisonHelper &);
479#ifndef QT_NO_DEBUG_STREAM
480 friend Q_CORE_EXPORT QDebug operator<<(QDebug, const QVariant &);
481#endif
482// ### Qt6: FIXME: Remove the special Q_CC_MSVC handling, it was introduced to maintain BC for QTBUG-41810 .
483#if !defined(Q_NO_TEMPLATE_FRIENDS) && !defined(Q_CC_MSVC)
484 template<typename T>
485 friend inline T qvariant_cast(const QVariant &);
486 template<typename T> friend struct QtPrivate::QVariantValueHelper;
487protected:
488#else
489public:
490#endif
491 Private d;
492 void create(int type, const void *copy);
493 bool cmp(const QVariant &other) const;
494 int compare(const QVariant &other) const;
495 bool convert(const int t, void *ptr) const; // ### Qt6: drop const
496
497private:
498 // force compile error, prevent QVariant(bool) to be called
499 inline QVariant(void *) = delete;
500 // QVariant::Type is marked as \obsolete, but we don't want to
501 // provide a constructor from its intended replacement,
502 // QMetaType::Type, instead, because the idea behind these
503 // constructors is flawed in the first place. But we also don't
504 // want QVariant(QMetaType::String) to compile and falsely be an
505 // int variant, so delete this constructor:
506 QVariant(QMetaType::Type) = delete;
507
508 // These constructors don't create QVariants of the type associcated
509 // with the enum, as expected, but they would create a QVariant of
510 // type int with the value of the enum value.
511 // Use QVariant v = QColor(Qt::red) instead of QVariant v = Qt::red for
512 // example.
513 QVariant(Qt::GlobalColor) = delete;
514 QVariant(Qt::BrushStyle) = delete;
515 QVariant(Qt::PenStyle) = delete;
516 QVariant(Qt::CursorShape) = delete;
517#ifdef QT_NO_CAST_FROM_ASCII
518 // force compile error when implicit conversion is not wanted
519 inline QVariant(const char *) = delete;
520#endif
521public:
522 typedef Private DataPtr;
523 inline DataPtr &data_ptr() { return d; }
524 inline const DataPtr &data_ptr() const { return d; }
525};
526
527#if QT_DEPRECATED_SINCE(5, 14)
528template <typename T>
529QT_DEPRECATED_X("Use QVariant::fromValue() instead.")
530inline QVariant qVariantFromValue(const T &t)
531{
532 return QVariant::fromValue(t);
533}
534
535template <typename T>
536QT_DEPRECATED_X("Use QVariant::setValue() instead.")
537inline void qVariantSetValue(QVariant &v, const T &t)
538{
539 v.setValue(t);
540}
541#endif
542
543template<>
544inline QVariant QVariant::fromValue(const QVariant &value)
545{
546 return value;
547}
548
549#if __has_include(<variant>) && __cplusplus >= 201703L
550template<>
551inline QVariant QVariant::fromValue(const std::monostate &)
552{
553 return QVariant();
554}
555#endif
556
557inline bool QVariant::isValid() const { return d.type != Invalid; }
558
559template<typename T>
560inline void QVariant::setValue(const T &avalue)
561{
562 // If possible we reuse the current QVariant private.
563 const uint type = qMetaTypeId<T>();
564 if (isDetached() && (type == d.type || (type <= uint(QVariant::Char) && d.type <= uint(QVariant::Char)))) {
565 d.type = type;
566 d.is_null = false;
567 T *old = reinterpret_cast<T*>(d.is_shared ? d.data.shared->ptr : &d.data.ptr);
568 if (QTypeInfo<T>::isComplex)
569 old->~T();
570 new (old) T(avalue); // call the copy constructor
571 } else {
572 *this = QVariant(type, &avalue, QTypeInfo<T>::isPointer);
573 }
574}
575
576template<>
577inline void QVariant::setValue(const QVariant &avalue)
578{
579 *this = avalue;
580}
581
582#ifndef QT_NO_DATASTREAM
583Q_CORE_EXPORT QDataStream& operator>> (QDataStream& s, QVariant& p);
584Q_CORE_EXPORT QDataStream& operator<< (QDataStream& s, const QVariant& p);
585Q_CORE_EXPORT QDataStream& operator>> (QDataStream& s, QVariant::Type& p);
586Q_CORE_EXPORT QDataStream& operator<< (QDataStream& s, const QVariant::Type p);
587#endif
588
589inline bool QVariant::isDetached() const
590{ return !d.is_shared || d.data.shared->ref.loadRelaxed() == 1; }
591
592
593#ifdef Q_QDOC
594 inline bool operator==(const QVariant &v1, const QVariant &v2);
595 inline bool operator!=(const QVariant &v1, const QVariant &v2);
596#else
597
598/* Helper class to add one more level of indirection to prevent
599 implicit casts.
600*/
601class QVariantComparisonHelper
602{
603public:
604 inline QVariantComparisonHelper(const QVariant &var)
605 : v(&var) {}
606private:
607 friend inline bool operator==(const QVariant &, const QVariantComparisonHelper &);
608 const QVariant *v;
609};
610
611inline bool operator==(const QVariant &v1, const QVariantComparisonHelper &v2)
612{
613 return v1.cmp(*v2.v);
614}
615
616inline bool operator!=(const QVariant &v1, const QVariantComparisonHelper &v2)
617{
618 return !operator==(v1, v2);
619}
620#endif
621Q_DECLARE_SHARED(QVariant)
622
623class Q_CORE_EXPORT QSequentialIterable
624{
625 QtMetaTypePrivate::QSequentialIterableImpl m_impl;
626public:
627 struct Q_CORE_EXPORT const_iterator
628 {
629 private:
630 QtMetaTypePrivate::QSequentialIterableImpl m_impl;
631 QAtomicInt *ref;
632 friend class QSequentialIterable;
633 explicit const_iterator(const QSequentialIterable &iter, QAtomicInt *ref_);
634
635 explicit const_iterator(const QtMetaTypePrivate::QSequentialIterableImpl &impl, QAtomicInt *ref_);
636
637 void begin();
638 void end();
639 public:
640 ~const_iterator();
641
642 const_iterator(const const_iterator &other);
643
644 const_iterator& operator=(const const_iterator &other);
645
646 const QVariant operator*() const;
647 bool operator==(const const_iterator &o) const;
648 bool operator!=(const const_iterator &o) const;
649 const_iterator &operator++();
650 const_iterator operator++(int);
651 const_iterator &operator--();
652 const_iterator operator--(int);
653 const_iterator &operator+=(int j);
654 const_iterator &operator-=(int j);
655 const_iterator operator+(int j) const;
656 const_iterator operator-(int j) const;
657 friend inline const_iterator operator+(int j, const_iterator k) { return k + j; }
658 };
659
660 friend struct const_iterator;
661
662#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
663 explicit QSequentialIterable(QtMetaTypePrivate::QSequentialIterableImpl impl);
664#else
665 explicit QSequentialIterable(const QtMetaTypePrivate::QSequentialIterableImpl &impl);
666#endif
667
668 const_iterator begin() const;
669 const_iterator end() const;
670
671 QVariant at(int idx) const;
672 int size() const;
673
674 bool canReverseIterate() const;
675};
676
677class Q_CORE_EXPORT QAssociativeIterable
678{
679 QtMetaTypePrivate::QAssociativeIterableImpl m_impl;
680public:
681 struct Q_CORE_EXPORT const_iterator
682 {
683 private:
684 QtMetaTypePrivate::QAssociativeIterableImpl m_impl;
685 QAtomicInt *ref;
686 friend class QAssociativeIterable;
687 explicit const_iterator(const QAssociativeIterable &iter, QAtomicInt *ref_);
688
689 explicit const_iterator(const QtMetaTypePrivate::QAssociativeIterableImpl &impl, QAtomicInt *ref_);
690
691 void begin();
692 void end();
693 void find(const QVariant &key);
694 public:
695 ~const_iterator();
696 const_iterator(const const_iterator &other);
697
698 const_iterator& operator=(const const_iterator &other);
699
700 const QVariant key() const;
701
702 const QVariant value() const;
703
704 const QVariant operator*() const;
705 bool operator==(const const_iterator &o) const;
706 bool operator!=(const const_iterator &o) const;
707 const_iterator &operator++();
708 const_iterator operator++(int);
709 const_iterator &operator--();
710 const_iterator operator--(int);
711 const_iterator &operator+=(int j);
712 const_iterator &operator-=(int j);
713 const_iterator operator+(int j) const;
714 const_iterator operator-(int j) const;
715 friend inline const_iterator operator+(int j, const_iterator k) { return k + j; }
716 };
717
718 friend struct const_iterator;
719
720#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
721 explicit QAssociativeIterable(QtMetaTypePrivate::QAssociativeIterableImpl impl);
722#else
723 explicit QAssociativeIterable(const QtMetaTypePrivate::QAssociativeIterableImpl &impl);
724#endif
725
726 const_iterator begin() const;
727 const_iterator end() const;
728 const_iterator find(const QVariant &key) const;
729
730 QVariant value(const QVariant &key) const;
731
732 int size() const;
733};
734
735#ifndef QT_MOC
736namespace QtPrivate {
737 template<typename T>
738 struct QVariantValueHelper : TreatAsQObjectBeforeMetaType<QVariantValueHelper<T>, T, const QVariant &, T>
739 {
740 static T metaType(const QVariant &v)
741 {
742 const int vid = qMetaTypeId<T>();
743 if (vid == v.userType())
744 return *reinterpret_cast<const T *>(v.constData());
745 T t;
746 if (v.convert(vid, &t))
747 return t;
748 return T();
749 }
750#ifndef QT_NO_QOBJECT
751 static T object(const QVariant &v)
752 {
753 return qobject_cast<T>(QMetaType::typeFlags(v.userType()) & QMetaType::PointerToQObject
754 ? v.d.data.o
755 : QVariantValueHelper::metaType(v));
756 }
757#endif
758 };
759
760 template<typename T>
761 struct QVariantValueHelperInterface : QVariantValueHelper<T>
762 {
763 };
764
765 template<>
766 struct QVariantValueHelperInterface<QSequentialIterable>
767 {
768 static QSequentialIterable invoke(const QVariant &v)
769 {
770 const int typeId = v.userType();
771 if (typeId == qMetaTypeId<QVariantList>()) {
772 return QSequentialIterable(QtMetaTypePrivate::QSequentialIterableImpl(reinterpret_cast<const QVariantList*>(v.constData())));
773 }
774 if (typeId == qMetaTypeId<QStringList>()) {
775 return QSequentialIterable(QtMetaTypePrivate::QSequentialIterableImpl(reinterpret_cast<const QStringList*>(v.constData())));
776 }
777#ifndef QT_BOOTSTRAPPED
778 if (typeId == qMetaTypeId<QByteArrayList>()) {
779 return QSequentialIterable(QtMetaTypePrivate::QSequentialIterableImpl(reinterpret_cast<const QByteArrayList*>(v.constData())));
780 }
781#endif
782 return QSequentialIterable(qvariant_cast<QtMetaTypePrivate::QSequentialIterableImpl>(v));
783 }
784 };
785 template<>
786 struct QVariantValueHelperInterface<QAssociativeIterable>
787 {
788 static QAssociativeIterable invoke(const QVariant &v)
789 {
790 const int typeId = v.userType();
791 if (typeId == qMetaTypeId<QVariantMap>()) {
792 return QAssociativeIterable(QtMetaTypePrivate::QAssociativeIterableImpl(reinterpret_cast<const QVariantMap*>(v.constData())));
793 }
794 if (typeId == qMetaTypeId<QVariantHash>()) {
795 return QAssociativeIterable(QtMetaTypePrivate::QAssociativeIterableImpl(reinterpret_cast<const QVariantHash*>(v.constData())));
796 }
797 return QAssociativeIterable(qvariant_cast<QtMetaTypePrivate::QAssociativeIterableImpl>(v));
798 }
799 };
800 template<>
801 struct QVariantValueHelperInterface<QVariantList>
802 {
803 static QVariantList invoke(const QVariant &v)
804 {
805 const int typeId = v.userType();
806 if (typeId == qMetaTypeId<QStringList>() || typeId == qMetaTypeId<QByteArrayList>() ||
807 (QMetaType::hasRegisteredConverterFunction(typeId, qMetaTypeId<QtMetaTypePrivate::QSequentialIterableImpl>()) && !QMetaType::hasRegisteredConverterFunction(typeId, qMetaTypeId<QVariantList>()))) {
808 QSequentialIterable iter = QVariantValueHelperInterface<QSequentialIterable>::invoke(v);
809 QVariantList l;
810 l.reserve(iter.size());
811 for (QSequentialIterable::const_iterator it = iter.begin(), end = iter.end(); it != end; ++it)
812 l << *it;
813 return l;
814 }
815 return QVariantValueHelper<QVariantList>::invoke(v);
816 }
817 };
818 template<>
819 struct QVariantValueHelperInterface<QVariantHash>
820 {
821 static QVariantHash invoke(const QVariant &v)
822 {
823 const int typeId = v.userType();
824 if (typeId == qMetaTypeId<QVariantMap>() || ((QMetaType::hasRegisteredConverterFunction(typeId, qMetaTypeId<QtMetaTypePrivate::QAssociativeIterableImpl>())) && !QMetaType::hasRegisteredConverterFunction(typeId, qMetaTypeId<QVariantHash>()))) {
825 QAssociativeIterable iter = QVariantValueHelperInterface<QAssociativeIterable>::invoke(v);
826 QVariantHash l;
827 l.reserve(iter.size());
828 for (QAssociativeIterable::const_iterator it = iter.begin(), end = iter.end(); it != end; ++it)
829 static_cast<QMultiHash<QString, QVariant> &>(l).insert(it.key().toString(), it.value());
830 return l;
831 }
832 return QVariantValueHelper<QVariantHash>::invoke(v);
833 }
834 };
835 template<>
836 struct QVariantValueHelperInterface<QVariantMap>
837 {
838 static QVariantMap invoke(const QVariant &v)
839 {
840 const int typeId = v.userType();
841 if (typeId == qMetaTypeId<QVariantHash>() || (QMetaType::hasRegisteredConverterFunction(typeId, qMetaTypeId<QtMetaTypePrivate::QAssociativeIterableImpl>()) && !QMetaType::hasRegisteredConverterFunction(typeId, qMetaTypeId<QVariantMap>()))) {
842 QAssociativeIterable iter = QVariantValueHelperInterface<QAssociativeIterable>::invoke(v);
843 QVariantMap l;
844 for (QAssociativeIterable::const_iterator it = iter.begin(), end = iter.end(); it != end; ++it)
845 static_cast<QMultiMap<QString, QVariant> &>(l).insert(it.key().toString(), it.value());
846 return l;
847 }
848 return QVariantValueHelper<QVariantMap>::invoke(v);
849 }
850 };
851 template<>
852 struct QVariantValueHelperInterface<QPair<QVariant, QVariant> >
853 {
854 static QPair<QVariant, QVariant> invoke(const QVariant &v)
855 {
856 const int typeId = v.userType();
857
858 if (QMetaType::hasRegisteredConverterFunction(typeId, qMetaTypeId<QtMetaTypePrivate::QPairVariantInterfaceImpl>()) && !(typeId == qMetaTypeId<QPair<QVariant, QVariant> >())) {
859 QtMetaTypePrivate::QPairVariantInterfaceImpl pi = v.value<QtMetaTypePrivate::QPairVariantInterfaceImpl>();
860 const QtMetaTypePrivate::VariantData d1 = pi.first();
861 QVariant v1(d1.metaTypeId, d1.data, d1.flags);
862 if (d1.metaTypeId == qMetaTypeId<QVariant>())
863 v1 = *reinterpret_cast<const QVariant*>(d1.data);
864
865 const QtMetaTypePrivate::VariantData d2 = pi.second();
866 QVariant v2(d2.metaTypeId, d2.data, d2.flags);
867 if (d2.metaTypeId == qMetaTypeId<QVariant>())
868 v2 = *reinterpret_cast<const QVariant*>(d2.data);
869
870 return QPair<QVariant, QVariant>(v1, v2);
871 }
872 return QVariantValueHelper<QPair<QVariant, QVariant> >::invoke(v);
873 }
874 };
875}
876
877template<typename T> inline T qvariant_cast(const QVariant &v)
878{
879 return QtPrivate::QVariantValueHelperInterface<T>::invoke(v);
880}
881
882template<> inline QVariant qvariant_cast<QVariant>(const QVariant &v)
883{
884 if (v.userType() == QMetaType::QVariant)
885 return *reinterpret_cast<const QVariant *>(v.constData());
886 return v;
887}
888
889#if QT_DEPRECATED_SINCE(5, 0)
890template<typename T>
891inline QT_DEPRECATED T qVariantValue(const QVariant &variant)
892{ return qvariant_cast<T>(variant); }
893
894template<typename T>
895inline QT_DEPRECATED bool qVariantCanConvert(const QVariant &variant)
896{ return variant.template canConvert<T>(); }
897#endif
898
899#endif
900
901#ifndef QT_NO_DEBUG_STREAM
902Q_CORE_EXPORT QDebug operator<<(QDebug, const QVariant &);
903Q_CORE_EXPORT QDebug operator<<(QDebug, const QVariant::Type);
904#endif
905
906QT_END_NAMESPACE
907
908#endif // QVARIANT_H
909