1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtCore module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
45 #include <QtCore/qatomic.h>
46 #include <QtCore/qbytearray.h>
47 #include <QtCore/qlist.h>
48 #include <QtCore/qmetatype.h>
49 #include <QtCore/qmap.h>
50 #include <QtCore/qhash.h>
51 #include <QtCore/qstring.h>
52 #include <QtCore/qobject.h>
84 class QVariantComparisonHelper;
87 inline QVariant qVariantFromValue(const T &);
90 inline T qvariant_cast(const QVariant &);
94 template <typename Derived, typename Argument, typename ReturnType>
97 static ReturnType invoke(Argument a)
99 return Derived::object(a);
103 template <typename Derived, typename Argument, typename ReturnType>
104 struct MetaTypeInvoker
106 static ReturnType invoke(Argument a)
108 return Derived::metaType(a);
112 template <typename Derived, typename T, typename Argument, typename ReturnType, bool = IsPointerToTypeDerivedFromQObject<T>::Value>
113 struct TreatAsQObjectBeforeMetaType : ObjectInvoker<Derived, Argument, ReturnType>
117 template <typename Derived, typename T, typename Argument, typename ReturnType>
118 struct TreatAsQObjectBeforeMetaType<Derived, T, Argument, ReturnType, false> : MetaTypeInvoker<Derived, Argument, ReturnType>
122 template<typename T> struct QVariantValueHelper;
125 class Q_CORE_EXPORT QVariant
129 Invalid = QMetaType::Void,
130 Bool = QMetaType::Bool,
131 Int = QMetaType::Int,
132 UInt = QMetaType::UInt,
133 LongLong = QMetaType::LongLong,
134 ULongLong = QMetaType::ULongLong,
135 Double = QMetaType::Double,
136 Char = QMetaType::QChar,
137 Map = QMetaType::QVariantMap,
138 List = QMetaType::QVariantList,
139 String = QMetaType::QString,
140 StringList = QMetaType::QStringList,
141 ByteArray = QMetaType::QByteArray,
142 BitArray = QMetaType::QBitArray,
143 Date = QMetaType::QDate,
144 Time = QMetaType::QTime,
145 DateTime = QMetaType::QDateTime,
146 Url = QMetaType::QUrl,
147 Locale = QMetaType::QLocale,
148 Rect = QMetaType::QRect,
149 RectF = QMetaType::QRectF,
150 Size = QMetaType::QSize,
151 SizeF = QMetaType::QSizeF,
152 Line = QMetaType::QLine,
153 LineF = QMetaType::QLineF,
154 Point = QMetaType::QPoint,
155 PointF = QMetaType::QPointF,
156 RegExp = QMetaType::QRegExp,
157 Hash = QMetaType::QVariantHash,
158 EasingCurve = QMetaType::QEasingCurve,
159 Uuid = QMetaType::QUuid,
160 ModelIndex = QMetaType::QModelIndex,
161 LastCoreType = QMetaType::LastCoreType,
163 Font = QMetaType::QFont,
164 Pixmap = QMetaType::QPixmap,
165 Brush = QMetaType::QBrush,
166 Color = QMetaType::QColor,
167 Palette = QMetaType::QPalette,
168 Image = QMetaType::QImage,
169 Polygon = QMetaType::QPolygon,
170 Region = QMetaType::QRegion,
171 Bitmap = QMetaType::QBitmap,
172 Cursor = QMetaType::QCursor,
173 KeySequence = QMetaType::QKeySequence,
174 Pen = QMetaType::QPen,
175 TextLength = QMetaType::QTextLength,
176 TextFormat = QMetaType::QTextFormat,
177 Matrix = QMetaType::QMatrix,
178 Transform = QMetaType::QTransform,
179 Matrix4x4 = QMetaType::QMatrix4x4,
180 Vector2D = QMetaType::QVector2D,
181 Vector3D = QMetaType::QVector3D,
182 Vector4D = QMetaType::QVector4D,
183 Quaternion = QMetaType::QQuaternion,
184 PolygonF = QMetaType::QPolygonF,
185 LastGuiType = QMetaType::LastGuiType,
187 Icon = QMetaType::QIcon,
188 SizePolicy = QMetaType::QSizePolicy,
190 UserType = QMetaType::User,
191 LastType = 0xffffffff // need this so that gcc >= 3.4 allocates 32 bits for Type
197 QVariant(int typeId, const void *copy);
198 QVariant(int typeId, const void *copy, uint flags);
199 QVariant(const QVariant &other);
201 #ifndef QT_NO_DATASTREAM
202 QVariant(QDataStream &s);
207 QVariant(qlonglong ll);
208 QVariant(qulonglong ull);
211 QVariant(float f) { d.is_null = false; d.type = QMetaType::Float; d.data.f = f; }
212 #ifndef QT_NO_CAST_FROM_ASCII
213 QT_ASCII_CAST_WARN QVariant(const char *str);
216 QVariant(const QByteArray &bytearray);
217 QVariant(const QBitArray &bitarray);
218 QVariant(const QString &string);
219 QVariant(const QLatin1String &string);
220 QVariant(const QStringList &stringlist);
221 QVariant(QChar qchar);
222 QVariant(const QDate &date);
223 QVariant(const QTime &time);
224 QVariant(const QDateTime &datetime);
225 QVariant(const QList<QVariant> &list);
226 QVariant(const QMap<QString,QVariant> &map);
227 QVariant(const QHash<QString,QVariant> &hash);
228 #ifndef QT_NO_GEOM_VARIANT
229 QVariant(const QSize &size);
230 QVariant(const QSizeF &size);
231 QVariant(const QPoint &pt);
232 QVariant(const QPointF &pt);
233 QVariant(const QLine &line);
234 QVariant(const QLineF &line);
235 QVariant(const QRect &rect);
236 QVariant(const QRectF &rect);
238 QVariant(const QUrl &url);
239 QVariant(const QLocale &locale);
241 QVariant(const QRegExp ®Exp);
243 #ifndef QT_BOOTSTRAPPED
244 QVariant(const QEasingCurve &easing);
246 QVariant(Qt::GlobalColor color);
248 QVariant& operator=(const QVariant &other);
249 #ifdef Q_COMPILER_RVALUE_REFS
250 inline QVariant &operator=(QVariant &&other)
251 { qSwap(d, other.d); return *this; }
254 inline void swap(QVariant &other) { qSwap(d, other.d); }
257 int userType() const;
258 const char *typeName() const;
260 bool canConvert(int targetTypeId) const;
261 bool convert(int targetTypeId);
263 inline bool isValid() const;
269 inline bool isDetached() const;
271 int toInt(bool *ok = 0) const;
272 uint toUInt(bool *ok = 0) const;
273 qlonglong toLongLong(bool *ok = 0) const;
274 qulonglong toULongLong(bool *ok = 0) const;
276 double toDouble(bool *ok = 0) const;
277 float toFloat(bool *ok = 0) const;
278 qreal toReal(bool *ok = 0) const;
279 QByteArray toByteArray() const;
280 QBitArray toBitArray() const;
281 QString toString() const;
282 QStringList toStringList() const;
283 QChar toChar() const;
284 QDate toDate() const;
285 QTime toTime() const;
286 QDateTime toDateTime() const;
287 QList<QVariant> toList() const;
288 QMap<QString, QVariant> toMap() const;
289 QHash<QString, QVariant> toHash() const;
291 #ifndef QT_NO_GEOM_VARIANT
292 QPoint toPoint() const;
293 QPointF toPointF() const;
294 QRect toRect() const;
295 QSize toSize() const;
296 QSizeF toSizeF() const;
297 QLine toLine() const;
298 QLineF toLineF() const;
299 QRectF toRectF() const;
302 QLocale toLocale() const;
304 QRegExp toRegExp() const;
306 #ifndef QT_BOOTSTRAPPED
307 QEasingCurve toEasingCurve() const;
310 #ifndef QT_NO_DATASTREAM
311 void load(QDataStream &ds);
312 void save(QDataStream &ds) const;
314 static const char *typeToName(int typeId);
315 static Type nameToType(const char *name);
318 const void *constData() const;
319 inline const void *data() const { return constData(); }
322 inline void setValue(const T &value);
325 inline T value() const
326 { return qvariant_cast<T>(*this); }
329 static inline QVariant fromValue(const T &value)
330 { return qVariantFromValue(value); }
333 bool canConvert() const
334 { return canConvert(qMetaTypeId<T>()); }
340 inline PrivateShared(void *v) : ptr(v), ref(1) { }
346 inline Private(): type(Invalid), is_shared(false), is_null(true) { data.ptr = 0; }
347 inline Private(const Private &other)
348 : data(other.data), type(other.type),
349 is_shared(other.is_shared), is_null(other.is_null)
369 PrivateShared *shared;
376 typedef void (*f_construct)(Private *, const void *);
377 typedef void (*f_clear)(Private *);
378 typedef bool (*f_null)(const Private *);
379 #ifndef QT_NO_DATASTREAM
380 typedef void (*f_load)(Private *, QDataStream &);
381 typedef void (*f_save)(const Private *, QDataStream &);
383 typedef bool (*f_compare)(const Private *, const Private *);
384 typedef bool (*f_convert)(const QVariant::Private *d, int t, void *, bool *);
385 typedef bool (*f_canConvert)(const QVariant::Private *d, int t);
386 typedef void (*f_debugStream)(QDebug, const QVariant &);
388 f_construct construct;
391 #ifndef QT_NO_DATASTREAM
397 f_canConvert canConvert;
398 f_debugStream debugStream;
402 inline bool operator==(const QVariant &v) const
404 inline bool operator!=(const QVariant &v) const
408 friend inline bool operator==(const QVariant &, const QVariantComparisonHelper &);
409 #ifndef QT_NO_DEBUG_STREAM
410 friend Q_CORE_EXPORT QDebug operator<<(QDebug, const QVariant &);
412 #ifndef Q_NO_TEMPLATE_FRIENDS
414 friend inline T qvariant_cast(const QVariant &);
415 template<typename T> friend struct QtPrivate::QVariantValueHelper;
421 void create(int type, const void *copy);
422 bool cmp(const QVariant &other) const;
423 bool convert(const int t, void *ptr) const;
426 // force compile error, prevent QVariant(bool) to be called
427 inline QVariant(void *) Q_DECL_EQ_DELETE;
428 #ifdef QT_NO_CAST_FROM_ASCII
429 // force compile error when implicit conversion is not wanted
430 inline QVariant(const char *) Q_DECL_EQ_DELETE;
433 typedef Private DataPtr;
434 inline DataPtr &data_ptr() { return d; }
435 inline const DataPtr &data_ptr() const { return d; }
438 template <typename T>
439 inline QVariant qVariantFromValue(const T &t)
441 return QVariant(qMetaTypeId<T>(reinterpret_cast<T *>(0)), &t, QTypeInfo<T>::isPointer);
445 inline QVariant qVariantFromValue(const QVariant &t) { return t; }
447 template <typename T>
448 inline void qVariantSetValue(QVariant &v, const T &t)
450 //if possible we reuse the current QVariant private
451 const uint type = qMetaTypeId<T>(reinterpret_cast<T *>(0));
452 QVariant::Private &d = v.data_ptr();
453 if (v.isDetached() && (type == d.type || (type <= uint(QVariant::Char) && d.type <= uint(QVariant::Char)))) {
456 T *old = reinterpret_cast<T*>(d.is_shared ? d.data.shared->ptr : &d.data.ptr);
457 if (QTypeInfo<T>::isComplex)
459 new (old) T(t); //call the copy constructor
461 v = QVariant(type, &t, QTypeInfo<T>::isPointer);
466 inline void qVariantSetValue<QVariant>(QVariant &v, const QVariant &t)
472 inline QVariant::QVariant() {}
473 inline bool QVariant::isValid() const { return d.type != Invalid; }
476 inline void QVariant::setValue(const T &avalue)
477 { qVariantSetValue(*this, avalue); }
479 #ifndef QT_NO_DATASTREAM
480 Q_CORE_EXPORT QDataStream& operator>> (QDataStream& s, QVariant& p);
481 Q_CORE_EXPORT QDataStream& operator<< (QDataStream& s, const QVariant& p);
482 Q_CORE_EXPORT QDataStream& operator>> (QDataStream& s, QVariant::Type& p);
483 Q_CORE_EXPORT QDataStream& operator<< (QDataStream& s, const QVariant::Type p);
486 inline bool QVariant::isDetached() const
487 { return !d.is_shared || d.data.shared->ref.load() == 1; }
491 inline bool operator==(const QVariant &v1, const QVariant &v2);
492 inline bool operator!=(const QVariant &v1, const QVariant &v2);
495 /* Helper class to add one more level of indirection to prevent
498 class QVariantComparisonHelper
501 inline QVariantComparisonHelper(const QVariant &var)
504 friend inline bool operator==(const QVariant &, const QVariantComparisonHelper &);
508 inline bool operator==(const QVariant &v1, const QVariantComparisonHelper &v2)
510 return v1.cmp(*v2.v);
513 inline bool operator!=(const QVariant &v1, const QVariantComparisonHelper &v2)
515 return !operator==(v1, v2);
519 namespace QtPrivate {
521 struct QVariantValueHelper : TreatAsQObjectBeforeMetaType<QVariantValueHelper<T>, T, const QVariant &, T>
523 static T metaType(const QVariant &v)
525 const int vid = qMetaTypeId<T>(static_cast<T *>(0));
526 if (vid == v.userType())
527 return *reinterpret_cast<const T *>(v.constData());
528 if (vid < int(QMetaType::User)) {
530 if (v.convert(vid, &t))
535 #ifndef QT_NO_QOBJECT
536 static T object(const QVariant &v)
538 return qobject_cast<T>(QMetaType::typeFlags(v.userType()) & QMetaType::PointerToQObject ? v.d.data.o : 0);
545 template<typename T> inline T qvariant_cast(const QVariant &v)
547 return QtPrivate::QVariantValueHelper<T>::invoke(v);
550 template<> inline QVariant qvariant_cast<QVariant>(const QVariant &v)
552 if (v.userType() == QMetaType::QVariant)
553 return *reinterpret_cast<const QVariant *>(v.constData());
557 #if QT_DEPRECATED_SINCE(5, 0)
559 inline QT_DEPRECATED T qVariantValue(const QVariant &variant)
560 { return qvariant_cast<T>(variant); }
563 inline QT_DEPRECATED bool qVariantCanConvert(const QVariant &variant)
564 { return variant.template canConvert<T>(); }
568 Q_DECLARE_SHARED(QVariant)
569 Q_DECLARE_TYPEINFO(QVariant, Q_MOVABLE_TYPE);
571 #ifndef QT_NO_DEBUG_STREAM
572 Q_CORE_EXPORT QDebug operator<<(QDebug, const QVariant &);
573 Q_CORE_EXPORT QDebug operator<<(QDebug, const QVariant::Type);