/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtCore module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. For licensing terms and ** conditions see http://qt.digia.com/licensing. For further information ** use the contact form at http://qt.digia.com/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Digia gives you certain additional ** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QVARIANT_H #define QVARIANT_H #include #include #include #include #include #include #include #include #include QT_BEGIN_NAMESPACE class QBitArray; class QDataStream; class QDate; class QDateTime; class QEasingCurve; class QLine; class QLineF; class QLocale; class QMatrix; class QTransform; class QStringList; class QTime; class QPoint; class QPointF; class QSize; class QSizeF; class QRect; class QRectF; #ifndef QT_NO_REGEXP class QRegExp; #endif // QT_NO_REGEXP #ifndef QT_NO_REGULAREXPRESSION class QRegularExpression; #endif // QT_NO_REGULAREXPRESSION class QTextFormat; class QTextLength; class QUrl; class QVariant; class QVariantComparisonHelper; template inline QVariant qVariantFromValue(const T &); template inline T qvariant_cast(const QVariant &); namespace QtPrivate { template struct ObjectInvoker { static ReturnType invoke(Argument a) { return Derived::object(a); } }; template struct MetaTypeInvoker { static ReturnType invoke(Argument a) { return Derived::metaType(a); } }; template ::Value> struct TreatAsQObjectBeforeMetaType : ObjectInvoker { }; template struct TreatAsQObjectBeforeMetaType : MetaTypeInvoker { }; template struct QVariantValueHelper; } class Q_CORE_EXPORT QVariant { public: enum Type { Invalid = QMetaType::UnknownType, Bool = QMetaType::Bool, Int = QMetaType::Int, UInt = QMetaType::UInt, LongLong = QMetaType::LongLong, ULongLong = QMetaType::ULongLong, Double = QMetaType::Double, Char = QMetaType::QChar, Map = QMetaType::QVariantMap, List = QMetaType::QVariantList, String = QMetaType::QString, StringList = QMetaType::QStringList, ByteArray = QMetaType::QByteArray, BitArray = QMetaType::QBitArray, Date = QMetaType::QDate, Time = QMetaType::QTime, DateTime = QMetaType::QDateTime, Url = QMetaType::QUrl, Locale = QMetaType::QLocale, Rect = QMetaType::QRect, RectF = QMetaType::QRectF, Size = QMetaType::QSize, SizeF = QMetaType::QSizeF, Line = QMetaType::QLine, LineF = QMetaType::QLineF, Point = QMetaType::QPoint, PointF = QMetaType::QPointF, RegExp = QMetaType::QRegExp, RegularExpression = QMetaType::QRegularExpression, Hash = QMetaType::QVariantHash, EasingCurve = QMetaType::QEasingCurve, Uuid = QMetaType::QUuid, ModelIndex = QMetaType::QModelIndex, LastCoreType = QMetaType::LastCoreType, Font = QMetaType::QFont, Pixmap = QMetaType::QPixmap, Brush = QMetaType::QBrush, Color = QMetaType::QColor, Palette = QMetaType::QPalette, Image = QMetaType::QImage, Polygon = QMetaType::QPolygon, Region = QMetaType::QRegion, Bitmap = QMetaType::QBitmap, Cursor = QMetaType::QCursor, KeySequence = QMetaType::QKeySequence, Pen = QMetaType::QPen, TextLength = QMetaType::QTextLength, TextFormat = QMetaType::QTextFormat, Matrix = QMetaType::QMatrix, Transform = QMetaType::QTransform, Matrix4x4 = QMetaType::QMatrix4x4, Vector2D = QMetaType::QVector2D, Vector3D = QMetaType::QVector3D, Vector4D = QMetaType::QVector4D, Quaternion = QMetaType::QQuaternion, PolygonF = QMetaType::QPolygonF, Icon = QMetaType::QIcon, LastGuiType = QMetaType::LastGuiType, SizePolicy = QMetaType::QSizePolicy, UserType = QMetaType::User, LastType = 0xffffffff // need this so that gcc >= 3.4 allocates 32 bits for Type }; inline QVariant(); ~QVariant(); QVariant(Type type); QVariant(int typeId, const void *copy); QVariant(int typeId, const void *copy, uint flags); QVariant(const QVariant &other); #ifndef QT_NO_DATASTREAM QVariant(QDataStream &s); #endif QVariant(int i); QVariant(uint ui); QVariant(qlonglong ll); QVariant(qulonglong ull); QVariant(bool b); QVariant(double d); QVariant(float f); #ifndef QT_NO_CAST_FROM_ASCII QT_ASCII_CAST_WARN QVariant(const char *str); #endif QVariant(const QByteArray &bytearray); QVariant(const QBitArray &bitarray); QVariant(const QString &string); QVariant(QLatin1String string); QVariant(const QStringList &stringlist); QVariant(QChar qchar); QVariant(const QDate &date); QVariant(const QTime &time); QVariant(const QDateTime &datetime); QVariant(const QList &list); QVariant(const QMap &map); QVariant(const QHash &hash); #ifndef QT_NO_GEOM_VARIANT QVariant(const QSize &size); QVariant(const QSizeF &size); QVariant(const QPoint &pt); QVariant(const QPointF &pt); QVariant(const QLine &line); QVariant(const QLineF &line); QVariant(const QRect &rect); QVariant(const QRectF &rect); #endif QVariant(const QLocale &locale); #ifndef QT_NO_REGEXP QVariant(const QRegExp ®Exp); #endif // QT_NO_REGEXP #ifndef QT_BOOTSTRAPPED #ifndef QT_NO_REGULAREXPRESSION QVariant(const QRegularExpression &re); #endif // QT_NO_REGULAREXPRESSION QVariant(const QUrl &url); QVariant(const QEasingCurve &easing); QVariant(const QUuid &uuid); QVariant(const QModelIndex &modelIndex); QVariant(const QJsonValue &jsonValue); QVariant(const QJsonObject &jsonObject); QVariant(const QJsonArray &jsonArray); QVariant(const QJsonDocument &jsonDocument); #endif // QT_BOOTSTRAPPED QVariant& operator=(const QVariant &other); #ifdef Q_COMPILER_RVALUE_REFS inline QVariant(QVariant &&other) : d(other.d) { other.d = Private(); } inline QVariant &operator=(QVariant &&other) { qSwap(d, other.d); return *this; } #endif inline void swap(QVariant &other) { qSwap(d, other.d); } Type type() const; int userType() const; const char *typeName() const; bool canConvert(int targetTypeId) const; bool convert(int targetTypeId); inline bool isValid() const; bool isNull() const; void clear(); void detach(); inline bool isDetached() const; int toInt(bool *ok = 0) const; uint toUInt(bool *ok = 0) const; qlonglong toLongLong(bool *ok = 0) const; qulonglong toULongLong(bool *ok = 0) const; bool toBool() const; double toDouble(bool *ok = 0) const; float toFloat(bool *ok = 0) const; qreal toReal(bool *ok = 0) const; QByteArray toByteArray() const; QBitArray toBitArray() const; QString toString() const; QStringList toStringList() const; QChar toChar() const; QDate toDate() const; QTime toTime() const; QDateTime toDateTime() const; QList toList() const; QMap toMap() const; QHash toHash() const; #ifndef QT_NO_GEOM_VARIANT QPoint toPoint() const; QPointF toPointF() const; QRect toRect() const; QSize toSize() const; QSizeF toSizeF() const; QLine toLine() const; QLineF toLineF() const; QRectF toRectF() const; #endif QLocale toLocale() const; #ifndef QT_NO_REGEXP QRegExp toRegExp() const; #endif // QT_NO_REGEXP #ifndef QT_BOOTSTRAPPED #ifndef QT_NO_REGULAREXPRESSION QRegularExpression toRegularExpression() const; #endif // QT_NO_REGULAREXPRESSION QUrl toUrl() const; QEasingCurve toEasingCurve() const; QUuid toUuid() const; QModelIndex toModelIndex() const; QJsonValue toJsonValue() const; QJsonObject toJsonObject() const; QJsonArray toJsonArray() const; QJsonDocument toJsonDocument() const; #endif // QT_BOOTSTRAPPED #ifndef QT_NO_DATASTREAM void load(QDataStream &ds); void save(QDataStream &ds) const; #endif static const char *typeToName(int typeId); static Type nameToType(const char *name); void *data(); const void *constData() const; inline const void *data() const { return constData(); } template inline void setValue(const T &value); template inline T value() const { return qvariant_cast(*this); } template static inline QVariant fromValue(const T &value) { return qVariantFromValue(value); } template bool canConvert() const { return canConvert(qMetaTypeId()); } public: #ifndef Q_QDOC struct PrivateShared { inline PrivateShared(void *v) : ptr(v), ref(1) { } void *ptr; QAtomicInt ref; }; struct Private { inline Private(): type(Invalid), is_shared(false), is_null(true) { data.ptr = 0; } // Internal constructor for initialized variants. explicit inline Private(uint variantType) : type(variantType), is_shared(false), is_null(false) {} inline Private(const Private &other) : data(other.data), type(other.type), is_shared(other.is_shared), is_null(other.is_null) {} union Data { char c; uchar uc; short s; signed char sc; ushort us; int i; uint u; long l; ulong ul; bool b; double d; float f; qreal real; qlonglong ll; qulonglong ull; QObject *o; void *ptr; PrivateShared *shared; } data; uint type : 30; uint is_shared : 1; uint is_null : 1; }; public: typedef void (*f_construct)(Private *, const void *); typedef void (*f_clear)(Private *); typedef bool (*f_null)(const Private *); #ifndef QT_NO_DATASTREAM typedef void (*f_load)(Private *, QDataStream &); typedef void (*f_save)(const Private *, QDataStream &); #endif typedef bool (*f_compare)(const Private *, const Private *); typedef bool (*f_convert)(const QVariant::Private *d, int t, void *, bool *); typedef bool (*f_canConvert)(const QVariant::Private *d, int t); typedef void (*f_debugStream)(QDebug, const QVariant &); struct Handler { f_construct construct; f_clear clear; f_null isNull; #ifndef QT_NO_DATASTREAM f_load load; f_save save; #endif f_compare compare; f_convert convert; f_canConvert canConvert; f_debugStream debugStream; }; #endif inline bool operator==(const QVariant &v) const { return cmp(v); } inline bool operator!=(const QVariant &v) const { return !cmp(v); } inline bool operator<(const QVariant &v) const { return compare(v) < 0; } inline bool operator<=(const QVariant &v) const { return compare(v) <= 0; } inline bool operator>(const QVariant &v) const { return compare(v) > 0; } inline bool operator>=(const QVariant &v) const { return compare(v) >= 0; } protected: friend inline bool operator==(const QVariant &, const QVariantComparisonHelper &); #ifndef QT_NO_DEBUG_STREAM friend Q_CORE_EXPORT QDebug operator<<(QDebug, const QVariant &); #endif #ifndef Q_NO_TEMPLATE_FRIENDS template friend inline T qvariant_cast(const QVariant &); template friend struct QtPrivate::QVariantValueHelper; protected: #else public: #endif Private d; void create(int type, const void *copy); bool cmp(const QVariant &other) const; int compare(const QVariant &other) const; bool convert(const int t, void *ptr) const; private: // force compile error, prevent QVariant(bool) to be called inline QVariant(void *) Q_DECL_EQ_DELETE; // QVariant::Type is marked as \obsolete, but we don't want to // provide a constructor from its intended replacement, // QMetaType::Type, instead, because the idea behind these // constructors is flawed in the first place. But we also don't // want QVariant(QMetaType::String) to compile and falsely be an // int variant, so delete this constructor: QVariant(QMetaType::Type) Q_DECL_EQ_DELETE; // These constructors don't create QVariants of the type associcated // with the enum, as expected, but they would create a QVariant of // type int with the value of the enum value. // Use QVariant v = QColor(Qt::red) instead of QVariant v = Qt::red for // example. QVariant(Qt::GlobalColor) Q_DECL_EQ_DELETE; QVariant(Qt::BrushStyle) Q_DECL_EQ_DELETE; QVariant(Qt::PenStyle) Q_DECL_EQ_DELETE; QVariant(Qt::CursorShape) Q_DECL_EQ_DELETE; #ifdef QT_NO_CAST_FROM_ASCII // force compile error when implicit conversion is not wanted inline QVariant(const char *) Q_DECL_EQ_DELETE; #endif public: typedef Private DataPtr; inline DataPtr &data_ptr() { return d; } inline const DataPtr &data_ptr() const { return d; } }; template inline QVariant qVariantFromValue(const T &t) { return QVariant(qMetaTypeId(), &t, QTypeInfo::isPointer); } template <> inline QVariant qVariantFromValue(const QVariant &t) { return t; } template inline void qVariantSetValue(QVariant &v, const T &t) { //if possible we reuse the current QVariant private const uint type = qMetaTypeId(); QVariant::Private &d = v.data_ptr(); if (v.isDetached() && (type == d.type || (type <= uint(QVariant::Char) && d.type <= uint(QVariant::Char)))) { d.type = type; d.is_null = false; T *old = reinterpret_cast(d.is_shared ? d.data.shared->ptr : &d.data.ptr); if (QTypeInfo::isComplex) old->~T(); new (old) T(t); //call the copy constructor } else { v = QVariant(type, &t, QTypeInfo::isPointer); } } template <> inline void qVariantSetValue(QVariant &v, const QVariant &t) { v = t; } inline QVariant::QVariant() {} inline bool QVariant::isValid() const { return d.type != Invalid; } template inline void QVariant::setValue(const T &avalue) { qVariantSetValue(*this, avalue); } #ifndef QT_NO_DATASTREAM Q_CORE_EXPORT QDataStream& operator>> (QDataStream& s, QVariant& p); Q_CORE_EXPORT QDataStream& operator<< (QDataStream& s, const QVariant& p); Q_CORE_EXPORT QDataStream& operator>> (QDataStream& s, QVariant::Type& p); Q_CORE_EXPORT QDataStream& operator<< (QDataStream& s, const QVariant::Type p); #endif inline bool QVariant::isDetached() const { return !d.is_shared || d.data.shared->ref.load() == 1; } #ifdef Q_QDOC inline bool operator==(const QVariant &v1, const QVariant &v2); inline bool operator!=(const QVariant &v1, const QVariant &v2); #else /* Helper class to add one more level of indirection to prevent implicit casts. */ class QVariantComparisonHelper { public: inline QVariantComparisonHelper(const QVariant &var) : v(&var) {} private: friend inline bool operator==(const QVariant &, const QVariantComparisonHelper &); const QVariant *v; }; inline bool operator==(const QVariant &v1, const QVariantComparisonHelper &v2) { return v1.cmp(*v2.v); } inline bool operator!=(const QVariant &v1, const QVariantComparisonHelper &v2) { return !operator==(v1, v2); } #endif class QSequentialIterable { QtMetaTypePrivate::QSequentialIterableImpl m_impl; public: struct const_iterator { private: QtMetaTypePrivate::QSequentialIterableImpl m_impl; QAtomicInt *ref; friend class QSequentialIterable; inline explicit const_iterator(const QSequentialIterable &iter, QAtomicInt *ref_) : m_impl(iter.m_impl), ref(ref_) { ref->ref(); } inline explicit const_iterator(const QtMetaTypePrivate::QSequentialIterableImpl &impl, QAtomicInt *ref_) : m_impl(impl), ref(ref_) { ref->ref(); } inline void begin() { m_impl.moveToBegin(); } inline void end() { m_impl.moveToEnd(); } public: inline ~const_iterator() { if (!ref->deref()) { m_impl.destroyIter(); } } inline const_iterator(const const_iterator &other) : m_impl(other.m_impl), ref(other.ref) { ref->ref(); } inline const QVariant operator*() const { const QtMetaTypePrivate::VariantData d = m_impl.getCurrent(); if (d.metaTypeId == qMetaTypeId()) return *reinterpret_cast(d.data); return QVariant(d.metaTypeId, d.data, d.flags); } inline bool operator==(const const_iterator &o) const { return m_impl.equal(o.m_impl); } inline bool operator!=(const const_iterator &o) const { return !m_impl.equal(o.m_impl); } inline const_iterator &operator++() { m_impl.advance(1); return *this; } inline const_iterator operator++(int) { QtMetaTypePrivate::QSequentialIterableImpl impl = m_impl; m_impl.advance(1); return const_iterator(impl, this->ref); } inline const_iterator &operator--() { m_impl.advance(-1); return *this; } inline const_iterator operator--(int) { QtMetaTypePrivate::QSequentialIterableImpl impl = m_impl; m_impl.advance(-1); return const_iterator(impl, this->ref); } inline const_iterator &operator+=(int j) { m_impl.advance(j); return *this; } inline const_iterator &operator-=(int j) { m_impl.advance(-j); return *this; } inline const_iterator operator+(int j) const { QtMetaTypePrivate::QSequentialIterableImpl impl = m_impl; impl.advance(j); return const_iterator(impl, this->ref); } inline const_iterator operator-(int j) const { QtMetaTypePrivate::QSequentialIterableImpl impl = m_impl; impl.advance(-j); return const_iterator(impl, this->ref); } }; friend struct const_iterator; explicit QSequentialIterable(QtMetaTypePrivate::QSequentialIterableImpl impl) : m_impl(impl) { } const_iterator begin() const { const_iterator it(*this, new QAtomicInt(0)); it.begin(); return it; } const_iterator end() const { const_iterator it(*this, new QAtomicInt(0)); it.end(); return it; } QVariant at(int idx) const { const QtMetaTypePrivate::VariantData d = m_impl.at(idx); if (d.metaTypeId == qMetaTypeId()) return *reinterpret_cast(d.data); return QVariant(d.metaTypeId, d.data, d.flags); } int size() const { return m_impl.size(); } bool canReverseIterate() const { return m_impl._iteratorCapabilities & QtMetaTypePrivate::BiDirectionalCapability; } }; class QAssociativeIterable { QtMetaTypePrivate::QAssociativeIterableImpl m_impl; public: struct const_iterator { private: QtMetaTypePrivate::QAssociativeIterableImpl m_impl; QAtomicInt *ref; friend class QAssociativeIterable; inline explicit const_iterator(const QAssociativeIterable &iter, QAtomicInt *ref_) : m_impl(iter.m_impl), ref(ref_) { ref->ref(); } inline explicit const_iterator(const QtMetaTypePrivate::QAssociativeIterableImpl &impl, QAtomicInt *ref_) : m_impl(impl), ref(ref_) { ref->ref(); } inline void begin() { m_impl.begin(); } inline void end() { m_impl.end(); } public: inline ~const_iterator() { if (!ref->deref()) { m_impl.destroyIter(); } } inline const_iterator(const const_iterator &other) : m_impl(other.m_impl), ref(other.ref) { ref->ref(); } inline const QVariant key() const { const QtMetaTypePrivate::VariantData d = m_impl.getCurrentKey(); QVariant v(d.metaTypeId, d.data, d.flags); if (d.metaTypeId == qMetaTypeId()) return *reinterpret_cast(d.data); return v; } inline const QVariant value() const { const QtMetaTypePrivate::VariantData d = m_impl.getCurrentValue(); QVariant v(d.metaTypeId, d.data, d.flags); if (d.metaTypeId == qMetaTypeId()) return *reinterpret_cast(d.data); return v; } inline const QVariant operator*() const { const QtMetaTypePrivate::VariantData d = m_impl.getCurrentValue(); QVariant v(d.metaTypeId, d.data, d.flags); if (d.metaTypeId == qMetaTypeId()) return *reinterpret_cast(d.data); return v; } inline bool operator==(const const_iterator &o) const { return m_impl.equal(o.m_impl); } inline bool operator!=(const const_iterator &o) const { return !m_impl.equal(o.m_impl); } inline const_iterator &operator++() { m_impl.advance(1); return *this; } inline const_iterator operator++(int) { QtMetaTypePrivate::QAssociativeIterableImpl impl = m_impl; m_impl.advance(1); return const_iterator(impl, this->ref); } inline const_iterator &operator--() { m_impl.advance(-1); return *this; } inline const_iterator operator--(int) { QtMetaTypePrivate::QAssociativeIterableImpl impl = m_impl; m_impl.advance(-1); return const_iterator(impl, this->ref); } inline const_iterator &operator+=(int j) { m_impl.advance(j); return *this; } inline const_iterator &operator-=(int j) { m_impl.advance(-j); return *this; } inline const_iterator operator+(int j) const { QtMetaTypePrivate::QAssociativeIterableImpl impl = m_impl; impl.advance(j); return const_iterator(impl, this->ref); } inline const_iterator operator-(int j) const { QtMetaTypePrivate::QAssociativeIterableImpl impl = m_impl; impl.advance(-j); return const_iterator(impl, this->ref); } }; friend struct const_iterator; explicit QAssociativeIterable(QtMetaTypePrivate::QAssociativeIterableImpl impl) : m_impl(impl) { } const_iterator begin() const { const_iterator it(*this, new QAtomicInt(0)); it.begin(); return it; } const_iterator end() const { const_iterator it(*this, new QAtomicInt(0)); it.end(); return it; } QVariant value(const QVariant &key) const { QVariant key_ = key; if (!key_.canConvert(m_impl._metaType_id_key)) return QVariant(); if (!key_.convert(m_impl._metaType_id_key)) return QVariant(); const QtMetaTypePrivate::VariantData dkey(key_.userType(), key_.constData(), 0 /*key.flags()*/); QtMetaTypePrivate::QAssociativeIterableImpl impl = m_impl; impl.find(dkey); QtMetaTypePrivate::QAssociativeIterableImpl endIt = m_impl; endIt.end(); if (impl.equal(endIt)) return QVariant(); const QtMetaTypePrivate::VariantData d = impl.getCurrentValue(); QVariant v(d.metaTypeId, d.data, d.flags); if (d.metaTypeId == qMetaTypeId()) return *reinterpret_cast(d.data); return v; } int size() const { return m_impl.size(); } }; #ifndef QT_MOC namespace QtPrivate { template struct QVariantValueHelper : TreatAsQObjectBeforeMetaType, T, const QVariant &, T> { static T metaType(const QVariant &v) { const int vid = qMetaTypeId(); if (vid == v.userType()) return *reinterpret_cast(v.constData()); T t; if (v.convert(vid, &t)) return t; return T(); } #ifndef QT_NO_QOBJECT static T object(const QVariant &v) { return qobject_cast(QMetaType::typeFlags(v.userType()) & QMetaType::PointerToQObject ? v.d.data.o : QVariantValueHelper::metaType(v)); } #endif }; template struct QVariantValueHelperInterface : QVariantValueHelper { }; template<> struct QVariantValueHelperInterface { static QSequentialIterable invoke(const QVariant &v) { if (v.userType() == qMetaTypeId()) { return QSequentialIterable(QtMetaTypePrivate::QSequentialIterableImpl(reinterpret_cast(v.constData()))); } if (v.userType() == qMetaTypeId()) { return QSequentialIterable(QtMetaTypePrivate::QSequentialIterableImpl(reinterpret_cast(v.constData()))); } return QSequentialIterable(v.value()); } }; template<> struct QVariantValueHelperInterface { static QAssociativeIterable invoke(const QVariant &v) { if (v.userType() == qMetaTypeId()) { return QAssociativeIterable(QtMetaTypePrivate::QAssociativeIterableImpl(reinterpret_cast(v.constData()))); } if (v.userType() == qMetaTypeId()) { return QAssociativeIterable(QtMetaTypePrivate::QAssociativeIterableImpl(reinterpret_cast(v.constData()))); } return QAssociativeIterable(v.value()); } }; template<> struct QVariantValueHelperInterface { static QVariantList invoke(const QVariant &v) { if (v.userType() == qMetaTypeId() || QMetaType::hasRegisteredConverterFunction(v.userType(), qMetaTypeId())) { QSequentialIterable iter = QVariantValueHelperInterface::invoke(v); QVariantList l; l.reserve(iter.size()); for (QSequentialIterable::const_iterator it = iter.begin(), end = iter.end(); it != end; ++it) l << *it; return l; } return QVariantValueHelper::invoke(v); } }; template<> struct QVariantValueHelperInterface { static QVariantHash invoke(const QVariant &v) { if (QMetaType::hasRegisteredConverterFunction(v.userType(), qMetaTypeId())) { QAssociativeIterable iter = QVariantValueHelperInterface::invoke(v); QVariantHash l; l.reserve(iter.size()); for (QAssociativeIterable::const_iterator it = iter.begin(), end = iter.end(); it != end; ++it) l.insert(it.key().toString(), it.value()); return l; } return QVariantValueHelper::invoke(v); } }; template<> struct QVariantValueHelperInterface { static QVariantMap invoke(const QVariant &v) { if (QMetaType::hasRegisteredConverterFunction(v.userType(), qMetaTypeId())) { QAssociativeIterable iter = QVariantValueHelperInterface::invoke(v); QVariantMap l; for (QAssociativeIterable::const_iterator it = iter.begin(), end = iter.end(); it != end; ++it) l.insert(it.key().toString(), it.value()); return l; } return QVariantValueHelper::invoke(v); } }; template<> struct QVariantValueHelperInterface > { static QPair invoke(const QVariant &v) { if (v.userType() == qMetaTypeId >()) return QVariantValueHelper >::invoke(v); if (QMetaType::hasRegisteredConverterFunction(v.userType(), qMetaTypeId())) { QtMetaTypePrivate::QPairVariantInterfaceImpl pi = v.value(); const QtMetaTypePrivate::VariantData d1 = pi.first(); QVariant v1(d1.metaTypeId, d1.data, d1.flags); if (d1.metaTypeId == qMetaTypeId()) v1 = *reinterpret_cast(d1.data); const QtMetaTypePrivate::VariantData d2 = pi.second(); QVariant v2(d2.metaTypeId, d2.data, d2.flags); if (d2.metaTypeId == qMetaTypeId()) v2 = *reinterpret_cast(d2.data); return QPair(v1, v2); } return QVariantValueHelper >::invoke(v); } }; } template inline T qvariant_cast(const QVariant &v) { return QtPrivate::QVariantValueHelperInterface::invoke(v); } template<> inline QVariant qvariant_cast(const QVariant &v) { if (v.userType() == QMetaType::QVariant) return *reinterpret_cast(v.constData()); return v; } #if QT_DEPRECATED_SINCE(5, 0) template inline QT_DEPRECATED T qVariantValue(const QVariant &variant) { return qvariant_cast(variant); } template inline QT_DEPRECATED bool qVariantCanConvert(const QVariant &variant) { return variant.template canConvert(); } #endif #endif Q_DECLARE_SHARED(QVariant) #ifndef QT_NO_DEBUG_STREAM Q_CORE_EXPORT QDebug operator<<(QDebug, const QVariant &); Q_CORE_EXPORT QDebug operator<<(QDebug, const QVariant::Type); #endif QT_END_NAMESPACE #endif // QVARIANT_H