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 | |
60 | QT_BEGIN_NAMESPACE |
61 | |
62 | |
63 | class QBitArray; |
64 | class QDataStream; |
65 | class QDate; |
66 | class QDateTime; |
67 | class QEasingCurve; |
68 | class QLine; |
69 | class QLineF; |
70 | class QLocale; |
71 | class QMatrix; |
72 | class QTransform; |
73 | class QStringList; |
74 | class QTime; |
75 | class QPoint; |
76 | class QPointF; |
77 | class QSize; |
78 | class QSizeF; |
79 | class QRect; |
80 | class QRectF; |
81 | #ifndef QT_NO_REGEXP |
82 | class QRegExp; |
83 | #endif // QT_NO_REGEXP |
84 | #if QT_CONFIG(regularexpression) |
85 | class QRegularExpression; |
86 | #endif // QT_CONFIG(regularexpression) |
87 | class QTextFormat; |
88 | class QTextLength; |
89 | class QUrl; |
90 | class QVariant; |
91 | class QVariantComparisonHelper; |
92 | |
93 | template <typename T> |
94 | inline QVariant qVariantFromValue(const T &); |
95 | |
96 | template<typename T> |
97 | inline T qvariant_cast(const QVariant &); |
98 | |
99 | namespace 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 | |
132 | class 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 ®Exp); |
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 | |
467 | protected: |
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; |
477 | protected: |
478 | #else |
479 | public: |
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 | |
487 | private: |
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 |
511 | public: |
512 | typedef Private DataPtr; |
513 | inline DataPtr &data_ptr() { return d; } |
514 | inline const DataPtr &data_ptr() const { return d; } |
515 | }; |
516 | |
517 | template <typename T> |
518 | inline QVariant qVariantFromValue(const T &t) |
519 | { |
520 | return QVariant(qMetaTypeId<T>(), &t, QTypeInfo<T>::isPointer); |
521 | } |
522 | |
523 | template <> |
524 | inline QVariant qVariantFromValue(const QVariant &t) { return t; } |
525 | |
526 | #if QT_HAS_INCLUDE(<variant>) && __cplusplus >= 201703L |
527 | template <> |
528 | inline QVariant qVariantFromValue(const std::monostate &) { return QVariant(); } |
529 | #endif |
530 | |
531 | template <typename T> |
532 | inline 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 | |
549 | template <> |
550 | inline void qVariantSetValue<QVariant>(QVariant &v, const QVariant &t) |
551 | { |
552 | v = t; |
553 | } |
554 | |
555 | inline bool QVariant::isValid() const { return d.type != Invalid; } |
556 | |
557 | template<typename T> |
558 | inline void QVariant::setValue(const T &avalue) |
559 | { qVariantSetValue(*this, avalue); } |
560 | |
561 | #ifndef QT_NO_DATASTREAM |
562 | Q_CORE_EXPORT QDataStream& operator>> (QDataStream& s, QVariant& p); |
563 | Q_CORE_EXPORT QDataStream& operator<< (QDataStream& s, const QVariant& p); |
564 | Q_CORE_EXPORT QDataStream& operator>> (QDataStream& s, QVariant::Type& p); |
565 | Q_CORE_EXPORT QDataStream& operator<< (QDataStream& s, const QVariant::Type p); |
566 | #endif |
567 | |
568 | inline 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 | */ |
580 | class QVariantComparisonHelper |
581 | { |
582 | public: |
583 | inline QVariantComparisonHelper(const QVariant &var) |
584 | : v(&var) {} |
585 | private: |
586 | friend inline bool operator==(const QVariant &, const QVariantComparisonHelper &); |
587 | const QVariant *v; |
588 | }; |
589 | |
590 | inline bool operator==(const QVariant &v1, const QVariantComparisonHelper &v2) |
591 | { |
592 | return v1.cmp(*v2.v); |
593 | } |
594 | |
595 | inline bool operator!=(const QVariant &v1, const QVariantComparisonHelper &v2) |
596 | { |
597 | return !operator==(v1, v2); |
598 | } |
599 | #endif |
600 | Q_DECLARE_SHARED(QVariant) |
601 | |
602 | class Q_CORE_EXPORT QSequentialIterable |
603 | { |
604 | QtMetaTypePrivate::QSequentialIterableImpl m_impl; |
605 | public: |
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 | |
656 | class Q_CORE_EXPORT QAssociativeIterable |
657 | { |
658 | QtMetaTypePrivate::QAssociativeIterableImpl m_impl; |
659 | public: |
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 |
715 | namespace 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 | |
858 | template<typename T> inline T qvariant_cast(const QVariant &v) |
859 | { |
860 | return QtPrivate::QVariantValueHelperInterface<T>::invoke(v); |
861 | } |
862 | |
863 | template<> 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) |
871 | template<typename T> |
872 | inline QT_DEPRECATED T qVariantValue(const QVariant &variant) |
873 | { return qvariant_cast<T>(variant); } |
874 | |
875 | template<typename T> |
876 | inline 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 |
883 | Q_CORE_EXPORT QDebug operator<<(QDebug, const QVariant &); |
884 | Q_CORE_EXPORT QDebug operator<<(QDebug, const QVariant::Type); |
885 | #endif |
886 | |
887 | QT_END_NAMESPACE |
888 | |
889 | #endif // QVARIANT_H |
890 | |