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