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) |
59 | namespace std { template<typename...> struct variant; } |
60 | #endif |
61 | |
62 | QT_BEGIN_NAMESPACE |
63 | |
64 | |
65 | class QBitArray; |
66 | class QDataStream; |
67 | class QDate; |
68 | class QDateTime; |
69 | #if QT_CONFIG(easingcurve) |
70 | class QEasingCurve; |
71 | #endif |
72 | class QLine; |
73 | class QLineF; |
74 | class QLocale; |
75 | class QMatrix; |
76 | class QTransform; |
77 | class QStringList; |
78 | class QTime; |
79 | class QPoint; |
80 | class QPointF; |
81 | class QSize; |
82 | class QSizeF; |
83 | class QRect; |
84 | class QRectF; |
85 | #ifndef QT_NO_REGEXP |
86 | class QRegExp; |
87 | #endif // QT_NO_REGEXP |
88 | #if QT_CONFIG(regularexpression) |
89 | class QRegularExpression; |
90 | #endif // QT_CONFIG(regularexpression) |
91 | class QTextFormat; |
92 | class QTextLength; |
93 | class QUrl; |
94 | class QVariant; |
95 | class QVariantComparisonHelper; |
96 | |
97 | template<typename T> |
98 | inline T qvariant_cast(const QVariant &); |
99 | |
100 | namespace 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 | |
133 | class 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 ®Exp); |
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(value1&: d, value2&: other.d); return *this; } |
280 | |
281 | inline void swap(QVariant &other) noexcept { qSwap(value1&: d, value2&: 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(other: v); } |
464 | inline bool operator!=(const QVariant &v) const |
465 | { return !cmp(other: v); } |
466 | #if QT_DEPRECATED_SINCE(5, 15) |
467 | QT_DEPRECATED inline bool operator<(const QVariant &v) const |
468 | { return compare(other: v) < 0; } |
469 | QT_DEPRECATED inline bool operator<=(const QVariant &v) const |
470 | { return compare(other: v) <= 0; } |
471 | QT_DEPRECATED inline bool operator>(const QVariant &v) const |
472 | { return compare(other: v) > 0; } |
473 | QT_DEPRECATED inline bool operator>=(const QVariant &v) const |
474 | { return compare(other: v) >= 0; } |
475 | #endif |
476 | |
477 | protected: |
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; |
487 | protected: |
488 | #else |
489 | public: |
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 | |
497 | private: |
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 |
521 | public: |
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) |
528 | template <typename T> |
529 | QT_DEPRECATED_X("Use QVariant::fromValue() instead." ) |
530 | inline QVariant qVariantFromValue(const T &t) |
531 | { |
532 | return QVariant::fromValue(t); |
533 | } |
534 | |
535 | template <typename T> |
536 | QT_DEPRECATED_X("Use QVariant::setValue() instead." ) |
537 | inline void qVariantSetValue(QVariant &v, const T &t) |
538 | { |
539 | v.setValue(t); |
540 | } |
541 | #endif |
542 | |
543 | template<> |
544 | inline QVariant QVariant::fromValue(const QVariant &value) |
545 | { |
546 | return value; |
547 | } |
548 | |
549 | #if __has_include(<variant>) && __cplusplus >= 201703L |
550 | template<> |
551 | inline QVariant QVariant::fromValue(const std::monostate &) |
552 | { |
553 | return QVariant(); |
554 | } |
555 | #endif |
556 | |
557 | inline bool QVariant::isValid() const { return d.type != Invalid; } |
558 | |
559 | template<typename T> |
560 | inline 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 | |
576 | template<> |
577 | inline void QVariant::setValue(const QVariant &avalue) |
578 | { |
579 | *this = avalue; |
580 | } |
581 | |
582 | #ifndef QT_NO_DATASTREAM |
583 | Q_CORE_EXPORT QDataStream& operator>> (QDataStream& s, QVariant& p); |
584 | Q_CORE_EXPORT QDataStream& operator<< (QDataStream& s, const QVariant& p); |
585 | Q_CORE_EXPORT QDataStream& operator>> (QDataStream& s, QVariant::Type& p); |
586 | Q_CORE_EXPORT QDataStream& operator<< (QDataStream& s, const QVariant::Type p); |
587 | #endif |
588 | |
589 | inline 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 | */ |
601 | class QVariantComparisonHelper |
602 | { |
603 | public: |
604 | inline QVariantComparisonHelper(const QVariant &var) |
605 | : v(&var) {} |
606 | private: |
607 | friend inline bool operator==(const QVariant &, const QVariantComparisonHelper &); |
608 | const QVariant *v; |
609 | }; |
610 | |
611 | inline bool operator==(const QVariant &v1, const QVariantComparisonHelper &v2) |
612 | { |
613 | return v1.cmp(other: *v2.v); |
614 | } |
615 | |
616 | inline bool operator!=(const QVariant &v1, const QVariantComparisonHelper &v2) |
617 | { |
618 | return !operator==(v1, v2); |
619 | } |
620 | #endif |
621 | Q_DECLARE_SHARED(QVariant) |
622 | |
623 | class Q_CORE_EXPORT QSequentialIterable |
624 | { |
625 | QtMetaTypePrivate::QSequentialIterableImpl m_impl; |
626 | public: |
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 | |
677 | class Q_CORE_EXPORT QAssociativeIterable |
678 | { |
679 | QtMetaTypePrivate::QAssociativeIterableImpl m_impl; |
680 | public: |
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 |
736 | namespace 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(type: 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(fromTypeId: typeId, toTypeId: qMetaTypeId<QtMetaTypePrivate::QSequentialIterableImpl>()) && !QMetaType::hasRegisteredConverterFunction(fromTypeId: typeId, toTypeId: qMetaTypeId<QVariantList>()))) { |
808 | QSequentialIterable iter = QVariantValueHelperInterface<QSequentialIterable>::invoke(v); |
809 | QVariantList l; |
810 | l.reserve(alloc: 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(a: 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(fromTypeId: typeId, toTypeId: qMetaTypeId<QtMetaTypePrivate::QAssociativeIterableImpl>())) && !QMetaType::hasRegisteredConverterFunction(fromTypeId: typeId, toTypeId: qMetaTypeId<QVariantHash>()))) { |
825 | QAssociativeIterable iter = QVariantValueHelperInterface<QAssociativeIterable>::invoke(v); |
826 | QVariantHash l; |
827 | l.reserve(asize: iter.size()); |
828 | for (QAssociativeIterable::const_iterator it = iter.begin(), end = iter.end(); it != end; ++it) |
829 | static_cast<QMultiHash<QString, QVariant> &>(l).insert(akey: it.key().toString(), avalue: it.value()); |
830 | return l; |
831 | } |
832 | return QVariantValueHelper<QVariantHash>::invoke(a: 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(fromTypeId: typeId, toTypeId: qMetaTypeId<QtMetaTypePrivate::QAssociativeIterableImpl>()) && !QMetaType::hasRegisteredConverterFunction(fromTypeId: typeId, toTypeId: 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(akey: it.key().toString(), avalue: it.value()); |
846 | return l; |
847 | } |
848 | return QVariantValueHelper<QVariantMap>::invoke(a: 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(fromTypeId: typeId, toTypeId: 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(a: v); |
873 | } |
874 | }; |
875 | } |
876 | |
877 | template<typename T> inline T qvariant_cast(const QVariant &v) |
878 | { |
879 | return QtPrivate::QVariantValueHelperInterface<T>::invoke(v); |
880 | } |
881 | |
882 | template<> 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) |
890 | template<typename T> |
891 | inline QT_DEPRECATED T qVariantValue(const QVariant &variant) |
892 | { return qvariant_cast<T>(variant); } |
893 | |
894 | template<typename T> |
895 | inline 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 |
902 | Q_CORE_EXPORT QDebug operator<<(QDebug, const QVariant &); |
903 | Q_CORE_EXPORT QDebug operator<<(QDebug, const QVariant::Type); |
904 | #endif |
905 | |
906 | QT_END_NAMESPACE |
907 | |
908 | #endif // QVARIANT_H |
909 | |