| /**************************************************************************** |
| ** |
| ** Copyright (C) 2019 The Qt Company Ltd. |
| ** Copyright (C) 2018 Intel Corporation. |
| ** Copyright (C) 2015 Olivier Goffart <ogoffart@woboq.com> |
| ** Contact: https://www.qt.io/licensing/ |
| ** |
| ** 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 The Qt Company. For licensing terms |
| ** and conditions see https://www.qt.io/terms-conditions. For further |
| ** information use the contact form at https://www.qt.io/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 3 as published by the Free Software |
| ** Foundation and appearing in the file LICENSE.LGPL3 included in the |
| ** packaging of this file. Please review the following information to |
| ** ensure the GNU Lesser General Public License version 3 requirements |
| ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. |
| ** |
| ** GNU General Public License Usage |
| ** Alternatively, this file may be used under the terms of the GNU |
| ** General Public License version 2.0 or (at your option) the GNU General |
| ** Public license version 3 or any later version approved by the KDE Free |
| ** Qt Foundation. The licenses are as published by the Free Software |
| ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 |
| ** included in the packaging of this file. Please review the following |
| ** information to ensure the GNU General Public License requirements will |
| ** be met: https://www.gnu.org/licenses/gpl-2.0.html and |
| ** https://www.gnu.org/licenses/gpl-3.0.html. |
| ** |
| ** $QT_END_LICENSE$ |
| ** |
| ****************************************************************************/ |
| |
| #include "qvariant.h" |
| #include "qbitarray.h" |
| #include "qbytearray.h" |
| #include "qdatastream.h" |
| #include "qdebug.h" |
| #include "qmap.h" |
| #include "qdatetime.h" |
| #if QT_CONFIG(easingcurve) |
| #include "qeasingcurve.h" |
| #endif |
| #include "qlist.h" |
| #if QT_CONFIG(regularexpression) |
| #include "qregularexpression.h" |
| #endif |
| #include "qstring.h" |
| #include "qstringlist.h" |
| #include "qurl.h" |
| #include "qlocale.h" |
| #include "qregexp.h" |
| #include "quuid.h" |
| #if QT_CONFIG(itemmodel) |
| #include "qabstractitemmodel.h" |
| #endif |
| #ifndef QT_BOOTSTRAPPED |
| #include "qcborarray.h" |
| #include "qcborcommon.h" |
| #include "qcbormap.h" |
| #include "qjsonvalue.h" |
| #include "qjsonobject.h" |
| #include "qjsonarray.h" |
| #include "qjsondocument.h" |
| #include "qbytearraylist.h" |
| #endif |
| #include "private/qvariant_p.h" |
| #include "private/qlocale_p.h" |
| #include "qmetatype_p.h" |
| #include <qmetaobject.h> |
| |
| #ifndef QT_NO_GEOM_VARIANT |
| #include "qsize.h" |
| #include "qpoint.h" |
| #include "qrect.h" |
| #include "qline.h" |
| #endif |
| |
| #include <cmath> |
| #include <float.h> |
| #include <cstring> |
| |
| QT_BEGIN_NAMESPACE |
| |
| namespace { |
| class HandlersManager |
| { |
| static const QVariant::Handler *Handlers[QModulesPrivate::ModulesCount]; |
| public: |
| const QVariant::Handler *operator[] (const uint typeId) const |
| { |
| return Handlers[QModulesPrivate::moduleForType(typeId)]; |
| } |
| |
| void registerHandler(const QModulesPrivate::Names name, const QVariant::Handler *handler) |
| { |
| Handlers[name] = handler; |
| } |
| }; |
| } // namespace |
| |
| namespace { |
| struct CoreTypesFilter { |
| template<typename T> |
| struct Acceptor { |
| static const bool IsAccepted = QModulesPrivate::QTypeModuleInfo<T>::IsCore && QtMetaTypePrivate::TypeDefinition<T>::IsAvailable; |
| }; |
| }; |
| } // annonymous |
| |
| namespace { // annonymous used to hide QVariant handlers |
| |
| static void construct(QVariant::Private *x, const void *copy) |
| { |
| QVariantConstructor<CoreTypesFilter> constructor(x, copy); |
| QMetaTypeSwitcher::switcher<void>(constructor, x->type); |
| } |
| |
| static void clear(QVariant::Private *d) |
| { |
| QVariantDestructor<CoreTypesFilter> cleaner(d); |
| QMetaTypeSwitcher::switcher<void>(cleaner, d->type); |
| } |
| |
| static bool isNull(const QVariant::Private *d) |
| { |
| QVariantIsNull<CoreTypesFilter> isNull(d); |
| return QMetaTypeSwitcher::switcher<bool>(isNull, d->type); |
| } |
| |
| /*! |
| \internal |
| |
| Compares \a a to \a b. The caller guarantees that \a a and \a b |
| are of the same type. |
| */ |
| static bool compare(const QVariant::Private *a, const QVariant::Private *b) |
| { |
| QVariantComparator<CoreTypesFilter> comparator(a, b); |
| return QMetaTypeSwitcher::switcher<bool>(comparator, a->type); |
| } |
| |
| /*! |
| \internal |
| */ |
| static qlonglong qMetaTypeNumber(const QVariant::Private *d) |
| { |
| switch (d->type) { |
| case QMetaType::Int: |
| return d->data.i; |
| case QMetaType::LongLong: |
| return d->data.ll; |
| case QMetaType::Char: |
| return qlonglong(d->data.c); |
| case QMetaType::SChar: |
| return qlonglong(d->data.sc); |
| case QMetaType::Short: |
| return qlonglong(d->data.s); |
| case QMetaType::Long: |
| return qlonglong(d->data.l); |
| case QMetaType::Float: |
| return qRound64(d->data.f); |
| case QVariant::Double: |
| return qRound64(d->data.d); |
| #ifndef QT_BOOTSTRAPPED |
| case QMetaType::QJsonValue: |
| return v_cast<QJsonValue>(d)->toDouble(); |
| case QMetaType::QCborValue: |
| return v_cast<QCborValue>(d)->toInteger(); |
| #endif |
| } |
| Q_ASSERT(false); |
| return 0; |
| } |
| |
| static qulonglong qMetaTypeUNumber(const QVariant::Private *d) |
| { |
| switch (d->type) { |
| case QVariant::UInt: |
| return d->data.u; |
| case QVariant::ULongLong: |
| return d->data.ull; |
| case QMetaType::UChar: |
| return d->data.uc; |
| case QMetaType::UShort: |
| return d->data.us; |
| case QMetaType::ULong: |
| return d->data.ul; |
| } |
| Q_ASSERT(false); |
| return 0; |
| } |
| |
| static qlonglong qConvertToNumber(const QVariant::Private *d, bool *ok) |
| { |
| *ok = true; |
| |
| switch (uint(d->type)) { |
| case QVariant::String: |
| return v_cast<QString>(d)->toLongLong(ok); |
| case QVariant::Char: |
| return v_cast<QChar>(d)->unicode(); |
| case QVariant::ByteArray: |
| return v_cast<QByteArray>(d)->toLongLong(ok); |
| case QVariant::Bool: |
| return qlonglong(d->data.b); |
| #ifndef QT_BOOTSTRAPPED |
| case QMetaType::QCborValue: |
| if (!v_cast<QCborValue>(d)->isInteger() && !v_cast<QCborValue>(d)->isDouble()) |
| break; |
| return qMetaTypeNumber(d); |
| case QMetaType::QJsonValue: |
| if (!v_cast<QJsonValue>(d)->isDouble()) |
| break; |
| Q_FALLTHROUGH(); |
| #endif |
| case QVariant::Double: |
| case QVariant::Int: |
| case QMetaType::Char: |
| case QMetaType::SChar: |
| case QMetaType::Short: |
| case QMetaType::Long: |
| case QMetaType::Float: |
| case QMetaType::LongLong: |
| return qMetaTypeNumber(d); |
| case QVariant::ULongLong: |
| case QVariant::UInt: |
| case QMetaType::UChar: |
| case QMetaType::UShort: |
| case QMetaType::ULong: |
| |
| return qlonglong(qMetaTypeUNumber(d)); |
| } |
| |
| QMetaType typeInfo(d->type); |
| if (typeInfo.flags() & QMetaType::IsEnumeration || d->type == QMetaType::QCborSimpleType) { |
| switch (typeInfo.sizeOf()) { |
| case 1: |
| return d->is_shared ? *reinterpret_cast<signed char *>(d->data.shared->ptr) : d->data.sc; |
| case 2: |
| return d->is_shared ? *reinterpret_cast<qint16 *>(d->data.shared->ptr) : d->data.s; |
| case 4: |
| return d->is_shared ? *reinterpret_cast<qint32 *>(d->data.shared->ptr) : d->data.i; |
| case 8: |
| return d->is_shared ? *reinterpret_cast<qint64 *>(d->data.shared->ptr) : d->data.ll; |
| } |
| } |
| |
| *ok = false; |
| return Q_INT64_C(0); |
| } |
| |
| static qreal qConvertToRealNumber(const QVariant::Private *d, bool *ok) |
| { |
| *ok = true; |
| switch (uint(d->type)) { |
| case QVariant::Double: |
| return qreal(d->data.d); |
| case QMetaType::Float: |
| return qreal(d->data.f); |
| case QVariant::ULongLong: |
| case QVariant::UInt: |
| case QMetaType::UChar: |
| case QMetaType::UShort: |
| case QMetaType::ULong: |
| return qreal(qMetaTypeUNumber(d)); |
| #ifndef QT_BOOTSTRAPPED |
| case QMetaType::QCborValue: |
| return v_cast<QCborValue>(d)->toDouble(); |
| case QMetaType::QJsonValue: |
| return v_cast<QJsonValue>(d)->toDouble(); |
| #endif |
| default: |
| // includes enum conversion as well as invalid types |
| return qreal(qConvertToNumber(d, ok)); |
| } |
| } |
| |
| static qulonglong qConvertToUnsignedNumber(const QVariant::Private *d, bool *ok) |
| { |
| *ok = true; |
| |
| switch (uint(d->type)) { |
| case QVariant::String: |
| return v_cast<QString>(d)->toULongLong(ok); |
| case QVariant::Char: |
| return v_cast<QChar>(d)->unicode(); |
| case QVariant::ByteArray: |
| return v_cast<QByteArray>(d)->toULongLong(ok); |
| case QVariant::Bool: |
| return qulonglong(d->data.b); |
| #ifndef QT_BOOTSTRAPPED |
| case QMetaType::QCborValue: |
| if (v_cast<QCborValue>(d)->isDouble()) |
| return qulonglong(qConvertToRealNumber(d, ok)); |
| if (!v_cast<QCborValue>(d)->isInteger()) |
| return false; |
| return qulonglong(qMetaTypeNumber(d)); |
| case QMetaType::QJsonValue: |
| if (!v_cast<QJsonValue>(d)->isDouble()) |
| break; |
| Q_FALLTHROUGH(); |
| #endif |
| case QVariant::Double: |
| case QVariant::Int: |
| case QMetaType::Char: |
| case QMetaType::SChar: |
| case QMetaType::Short: |
| case QMetaType::Long: |
| case QMetaType::Float: |
| case QMetaType::LongLong: |
| return qulonglong(qMetaTypeNumber(d)); |
| case QVariant::ULongLong: |
| case QVariant::UInt: |
| case QMetaType::UChar: |
| case QMetaType::UShort: |
| case QMetaType::ULong: |
| return qMetaTypeUNumber(d); |
| } |
| |
| QMetaType typeInfo(d->type); |
| if (typeInfo.flags() & QMetaType::IsEnumeration) { |
| switch (typeInfo.sizeOf()) { |
| case 1: |
| return d->is_shared ? *reinterpret_cast<uchar *>(d->data.shared->ptr) : d->data.uc; |
| case 2: |
| return d->is_shared ? *reinterpret_cast<quint16 *>(d->data.shared->ptr) : d->data.us; |
| case 4: |
| return d->is_shared ? *reinterpret_cast<quint32 *>(d->data.shared->ptr) : d->data.u; |
| case 8: |
| return d->is_shared ? *reinterpret_cast<qint64 *>(d->data.shared->ptr) : d->data.ull; |
| } |
| } |
| |
| *ok = false; |
| return Q_UINT64_C(0); |
| } |
| |
| template<typename TInput, typename LiteralWrapper> |
| inline bool qt_convertToBool(const QVariant::Private *const d) |
| { |
| TInput str = v_cast<TInput>(d)->toLower(); |
| return !(str.isEmpty() || str == LiteralWrapper("0") || str == LiteralWrapper("false")); |
| } |
| |
| /*! |
| \internal |
| Returns the internal data pointer from \a d. |
| */ |
| |
| static const void *constData(const QVariant::Private &d) |
| { |
| return d.is_shared ? d.data.shared->ptr : reinterpret_cast<const void *>(&d.data.c); |
| } |
| |
| #ifndef QT_NO_QOBJECT |
| /*! |
| \internal |
| returns a QMetaEnum for a given meta tape type id if possible |
| */ |
| static QMetaEnum metaEnumFromType(int type) |
| { |
| QMetaType t(type); |
| if (t.flags() & QMetaType::IsEnumeration) { |
| if (const QMetaObject *metaObject = t.metaObject()) { |
| const char *enumName = QMetaType::typeName(type); |
| const char *lastColon = std::strrchr(enumName, ':'); |
| if (lastColon) |
| enumName = lastColon + 1; |
| return metaObject->enumerator(metaObject->indexOfEnumerator(enumName)); |
| } |
| } |
| return QMetaEnum(); |
| } |
| #endif |
| |
| /*! |
| \internal |
| |
| Converts \a d to type \a t, which is placed in \a result. |
| */ |
| static bool convert(const QVariant::Private *d, int t, void *result, bool *ok) |
| { |
| Q_ASSERT(d->type != uint(t)); |
| Q_ASSERT(result); |
| |
| if (d->type >= QMetaType::User || t >= QMetaType::User) { |
| const bool isOk = QMetaType::convert(constData(*d), d->type, result, t); |
| if (ok) |
| *ok = isOk; |
| if (isOk) |
| return true; |
| } |
| |
| bool dummy; |
| if (!ok) |
| ok = &dummy; |
| |
| switch (uint(t)) { |
| #ifndef QT_BOOTSTRAPPED |
| case QVariant::Url: |
| switch (d->type) { |
| case QVariant::String: |
| *static_cast<QUrl *>(result) = QUrl(*v_cast<QString>(d)); |
| break; |
| case QMetaType::QCborValue: |
| if (v_cast<QCborValue>(d)->isUrl()) { |
| *static_cast<QUrl *>(result) = v_cast<QCborValue>(d)->toUrl(); |
| break; |
| } |
| return false; |
| default: |
| return false; |
| } |
| break; |
| #endif // QT_BOOTSTRAPPED |
| #if QT_CONFIG(itemmodel) |
| case QVariant::ModelIndex: |
| switch (d->type) { |
| case QVariant::PersistentModelIndex: |
| *static_cast<QModelIndex *>(result) = QModelIndex(*v_cast<QPersistentModelIndex>(d)); |
| break; |
| default: |
| return false; |
| } |
| break; |
| case QVariant::PersistentModelIndex: |
| switch (d->type) { |
| case QVariant::ModelIndex: |
| *static_cast<QPersistentModelIndex *>(result) = QPersistentModelIndex(*v_cast<QModelIndex>(d)); |
| break; |
| default: |
| return false; |
| } |
| break; |
| #endif // QT_CONFIG(itemmodel) |
| case QVariant::String: { |
| QString *str = static_cast<QString *>(result); |
| switch (d->type) { |
| case QVariant::Char: |
| *str = *v_cast<QChar>(d); |
| break; |
| case QMetaType::Char: |
| case QMetaType::SChar: |
| case QMetaType::UChar: |
| *str = QChar::fromLatin1(d->data.c); |
| break; |
| case QMetaType::Short: |
| case QMetaType::Long: |
| case QVariant::Int: |
| case QVariant::LongLong: |
| *str = QString::number(qMetaTypeNumber(d)); |
| break; |
| case QVariant::UInt: |
| case QVariant::ULongLong: |
| case QMetaType::UShort: |
| case QMetaType::ULong: |
| *str = QString::number(qMetaTypeUNumber(d)); |
| break; |
| case QMetaType::Float: |
| *str = QString::number(d->data.f, 'g', QLocale::FloatingPointShortest); |
| break; |
| case QVariant::Double: |
| *str = QString::number(d->data.d, 'g', QLocale::FloatingPointShortest); |
| break; |
| #if QT_CONFIG(datestring) |
| case QVariant::Date: |
| *str = v_cast<QDate>(d)->toString(Qt::ISODate); |
| break; |
| case QVariant::Time: |
| *str = v_cast<QTime>(d)->toString(Qt::ISODateWithMs); |
| break; |
| case QVariant::DateTime: |
| *str = v_cast<QDateTime>(d)->toString(Qt::ISODateWithMs); |
| break; |
| #endif |
| case QVariant::Bool: |
| *str = d->data.b ? QStringLiteral("true") : QStringLiteral("false"); |
| break; |
| case QVariant::ByteArray: |
| *str = QString::fromUtf8(v_cast<QByteArray>(d)->constData()); |
| break; |
| case QVariant::StringList: |
| if (v_cast<QStringList>(d)->count() == 1) |
| *str = v_cast<QStringList>(d)->at(0); |
| break; |
| #ifndef QT_BOOTSTRAPPED |
| case QVariant::Url: |
| *str = v_cast<QUrl>(d)->toString(); |
| break; |
| case QMetaType::QJsonValue: |
| if (v_cast<QJsonValue>(d)->isString()) |
| *str = v_cast<QJsonValue>(d)->toString(); |
| else if (!v_cast<QJsonValue>(d)->isNull()) |
| return false; |
| break; |
| case QMetaType::QCborValue: |
| if (v_cast<QCborValue>(d)->isContainer() || v_cast<QCborValue>(d)->isTag()) |
| return false; |
| *str = v_cast<QCborValue>(d)->toVariant().toString(); |
| break; |
| #endif |
| case QVariant::Uuid: |
| *str = v_cast<QUuid>(d)->toString(); |
| break; |
| case QMetaType::Nullptr: |
| *str = QString(); |
| break; |
| default: |
| #ifndef QT_NO_QOBJECT |
| { |
| QMetaEnum en = metaEnumFromType(d->type); |
| if (en.isValid()) { |
| *str = QString::fromUtf8(en.valueToKey(qConvertToNumber(d, ok))); |
| return *ok; |
| } |
| } |
| #endif |
| return false; |
| } |
| break; |
| } |
| case QVariant::Char: { |
| QChar *c = static_cast<QChar *>(result); |
| switch (d->type) { |
| case QVariant::Int: |
| case QVariant::LongLong: |
| case QMetaType::Char: |
| case QMetaType::SChar: |
| case QMetaType::Short: |
| case QMetaType::Long: |
| case QMetaType::Float: |
| *c = QChar(ushort(qMetaTypeNumber(d))); |
| break; |
| case QVariant::UInt: |
| case QVariant::ULongLong: |
| case QMetaType::UChar: |
| case QMetaType::UShort: |
| case QMetaType::ULong: |
| *c = QChar(ushort(qMetaTypeUNumber(d))); |
| break; |
| default: |
| return false; |
| } |
| break; |
| } |
| #ifndef QT_NO_GEOM_VARIANT |
| case QVariant::Size: { |
| QSize *s = static_cast<QSize *>(result); |
| switch (d->type) { |
| case QVariant::SizeF: |
| *s = v_cast<QSizeF>(d)->toSize(); |
| break; |
| default: |
| return false; |
| } |
| break; |
| } |
| |
| case QVariant::SizeF: { |
| QSizeF *s = static_cast<QSizeF *>(result); |
| switch (d->type) { |
| case QVariant::Size: |
| *s = QSizeF(*(v_cast<QSize>(d))); |
| break; |
| default: |
| return false; |
| } |
| break; |
| } |
| |
| case QVariant::Line: { |
| QLine *s = static_cast<QLine *>(result); |
| switch (d->type) { |
| case QVariant::LineF: |
| *s = v_cast<QLineF>(d)->toLine(); |
| break; |
| default: |
| return false; |
| } |
| break; |
| } |
| |
| case QVariant::LineF: { |
| QLineF *s = static_cast<QLineF *>(result); |
| switch (d->type) { |
| case QVariant::Line: |
| *s = QLineF(*(v_cast<QLine>(d))); |
| break; |
| default: |
| return false; |
| } |
| break; |
| } |
| #endif |
| case QVariant::StringList: |
| if (d->type == QVariant::List) { |
| QStringList *slst = static_cast<QStringList *>(result); |
| const QVariantList *list = v_cast<QVariantList >(d); |
| const int size = list->size(); |
| slst->reserve(size); |
| for (int i = 0; i < size; ++i) |
| slst->append(list->at(i).toString()); |
| } else if (d->type == QVariant::String) { |
| QStringList *slst = static_cast<QStringList *>(result); |
| *slst = QStringList(*v_cast<QString>(d)); |
| } else { |
| return false; |
| } |
| break; |
| case QVariant::Date: { |
| QDate *dt = static_cast<QDate *>(result); |
| if (d->type == QVariant::DateTime) |
| *dt = v_cast<QDateTime>(d)->date(); |
| #if QT_CONFIG(datestring) |
| else if (d->type == QVariant::String) |
| *dt = QDate::fromString(*v_cast<QString>(d), Qt::ISODate); |
| #endif |
| else |
| return false; |
| |
| return dt->isValid(); |
| } |
| case QVariant::Time: { |
| QTime *t = static_cast<QTime *>(result); |
| switch (d->type) { |
| case QVariant::DateTime: |
| *t = v_cast<QDateTime>(d)->time(); |
| break; |
| #if QT_CONFIG(datestring) |
| case QVariant::String: |
| *t = QTime::fromString(*v_cast<QString>(d), Qt::ISODate); |
| break; |
| #endif |
| default: |
| return false; |
| } |
| return t->isValid(); |
| } |
| case QVariant::DateTime: { |
| QDateTime *dt = static_cast<QDateTime *>(result); |
| switch (d->type) { |
| #if QT_CONFIG(datestring) |
| case QVariant::String: |
| *dt = QDateTime::fromString(*v_cast<QString>(d), Qt::ISODate); |
| break; |
| # ifndef QT_BOOTSTRAPPED |
| case QMetaType::QCborValue: |
| if (v_cast<QCborValue>(d)->isDateTime()) |
| *dt = v_cast<QCborValue>(d)->toDateTime(); |
| else |
| return false; |
| break; |
| # endif |
| #endif |
| case QVariant::Date: |
| *dt = QDateTime(*v_cast<QDate>(d)); |
| break; |
| default: |
| return false; |
| } |
| return dt->isValid(); |
| } |
| case QVariant::ByteArray: { |
| QByteArray *ba = static_cast<QByteArray *>(result); |
| switch (d->type) { |
| case QVariant::String: |
| *ba = v_cast<QString>(d)->toUtf8(); |
| break; |
| case QVariant::Double: |
| *ba = QByteArray::number(d->data.d, 'g', QLocale::FloatingPointShortest); |
| break; |
| case QMetaType::Float: |
| *ba = QByteArray::number(d->data.f, 'g', QLocale::FloatingPointShortest); |
| break; |
| case QMetaType::Char: |
| case QMetaType::SChar: |
| case QMetaType::UChar: |
| *ba = QByteArray(1, d->data.c); |
| break; |
| case QVariant::Int: |
| case QVariant::LongLong: |
| case QMetaType::Short: |
| case QMetaType::Long: |
| *ba = QByteArray::number(qMetaTypeNumber(d)); |
| break; |
| case QVariant::UInt: |
| case QVariant::ULongLong: |
| case QMetaType::UShort: |
| case QMetaType::ULong: |
| *ba = QByteArray::number(qMetaTypeUNumber(d)); |
| break; |
| case QVariant::Bool: |
| *ba = QByteArray(d->data.b ? "true" : "false"); |
| break; |
| case QVariant::Uuid: |
| *ba = v_cast<QUuid>(d)->toByteArray(); |
| break; |
| case QMetaType::Nullptr: |
| *ba = QByteArray(); |
| break; |
| #ifndef QT_BOOTSTRAPPED |
| case QMetaType::QCborValue: |
| if (v_cast<QCborValue>(d)->isByteArray()) |
| *ba = v_cast<QCborValue>(d)->toByteArray(); |
| else |
| return false; |
| break; |
| #endif |
| default: |
| #ifndef QT_NO_QOBJECT |
| { |
| QMetaEnum en = metaEnumFromType(d->type); |
| if (en.isValid()) { |
| *ba = en.valueToKey(qConvertToNumber(d, ok)); |
| return *ok; |
| } |
| } |
| #endif |
| return false; |
| } |
| } |
| break; |
| case QMetaType::Short: |
| *static_cast<short *>(result) = short(qConvertToNumber(d, ok)); |
| return *ok; |
| case QMetaType::Long: |
| *static_cast<long *>(result) = long(qConvertToNumber(d, ok)); |
| return *ok; |
| case QMetaType::UShort: |
| *static_cast<ushort *>(result) = ushort(qConvertToUnsignedNumber(d, ok)); |
| return *ok; |
| case QMetaType::ULong: |
| *static_cast<ulong *>(result) = ulong(qConvertToUnsignedNumber(d, ok)); |
| return *ok; |
| case QVariant::Int: |
| *static_cast<int *>(result) = int(qConvertToNumber(d, ok)); |
| return *ok; |
| case QVariant::UInt: |
| *static_cast<uint *>(result) = uint(qConvertToUnsignedNumber(d, ok)); |
| return *ok; |
| case QVariant::LongLong: |
| *static_cast<qlonglong *>(result) = qConvertToNumber(d, ok); |
| return *ok; |
| case QVariant::ULongLong: { |
| *static_cast<qulonglong *>(result) = qConvertToUnsignedNumber(d, ok); |
| return *ok; |
| } |
| case QMetaType::SChar: { |
| signed char s = qConvertToNumber(d, ok); |
| *static_cast<signed char*>(result) = s; |
| return *ok; |
| } |
| case QMetaType::UChar: { |
| *static_cast<uchar *>(result) = qConvertToUnsignedNumber(d, ok); |
| return *ok; |
| } |
| case QVariant::Bool: { |
| bool *b = static_cast<bool *>(result); |
| switch(d->type) { |
| case QVariant::ByteArray: |
| *b = qt_convertToBool<QByteArray, const char*>(d); |
| break; |
| case QVariant::String: |
| *b = qt_convertToBool<QString, QLatin1String>(d); |
| break; |
| case QVariant::Char: |
| *b = !v_cast<QChar>(d)->isNull(); |
| break; |
| case QVariant::Double: |
| case QVariant::Int: |
| case QVariant::LongLong: |
| case QMetaType::Char: |
| case QMetaType::SChar: |
| case QMetaType::Short: |
| case QMetaType::Long: |
| case QMetaType::Float: |
| *b = qMetaTypeNumber(d) != Q_INT64_C(0); |
| break; |
| case QVariant::UInt: |
| case QVariant::ULongLong: |
| case QMetaType::UChar: |
| case QMetaType::UShort: |
| case QMetaType::ULong: |
| *b = qMetaTypeUNumber(d) != Q_UINT64_C(0); |
| break; |
| #ifndef QT_BOOTSTRAPPED |
| case QMetaType::QCborValue: |
| *b = v_cast<QCborValue>(d)->toBool(); |
| if (!v_cast<QCborValue>(d)->isBool()) |
| return false; |
| break; |
| case QMetaType::QJsonValue: |
| *b = v_cast<QJsonValue>(d)->toBool(false); |
| if (!v_cast<QJsonValue>(d)->isBool()) |
| return false; |
| break; |
| #endif |
| default: |
| *b = false; |
| return false; |
| } |
| break; |
| } |
| case QVariant::Double: { |
| double *f = static_cast<double *>(result); |
| switch (d->type) { |
| case QVariant::String: |
| *f = v_cast<QString>(d)->toDouble(ok); |
| break; |
| case QVariant::ByteArray: |
| *f = v_cast<QByteArray>(d)->toDouble(ok); |
| break; |
| case QVariant::Bool: |
| *f = double(d->data.b); |
| break; |
| case QMetaType::Float: |
| *f = double(d->data.f); |
| break; |
| case QVariant::LongLong: |
| case QVariant::Int: |
| case QMetaType::Char: |
| case QMetaType::SChar: |
| case QMetaType::Short: |
| case QMetaType::Long: |
| *f = double(qMetaTypeNumber(d)); |
| break; |
| case QVariant::UInt: |
| case QVariant::ULongLong: |
| case QMetaType::UChar: |
| case QMetaType::UShort: |
| case QMetaType::ULong: |
| *f = double(qMetaTypeUNumber(d)); |
| break; |
| #ifndef QT_BOOTSTRAPPED |
| case QMetaType::QCborValue: |
| *f = v_cast<QCborValue>(d)->toDouble(); |
| if (!v_cast<QCborValue>(d)->isDouble()) |
| return false; |
| break; |
| case QMetaType::QJsonValue: |
| *f = v_cast<QJsonValue>(d)->toDouble(0.0); |
| if (!v_cast<QJsonValue>(d)->isDouble()) |
| return false; |
| break; |
| #endif |
| default: |
| *f = 0.0; |
| return false; |
| } |
| break; |
| } |
| case QMetaType::Float: { |
| float *f = static_cast<float *>(result); |
| switch (d->type) { |
| case QVariant::String: |
| *f = v_cast<QString>(d)->toFloat(ok); |
| break; |
| case QVariant::ByteArray: |
| *f = v_cast<QByteArray>(d)->toFloat(ok); |
| break; |
| case QVariant::Bool: |
| *f = float(d->data.b); |
| break; |
| case QVariant::Double: |
| *f = float(d->data.d); |
| break; |
| case QVariant::LongLong: |
| case QVariant::Int: |
| case QMetaType::Char: |
| case QMetaType::SChar: |
| case QMetaType::Short: |
| case QMetaType::Long: |
| *f = float(qMetaTypeNumber(d)); |
| break; |
| case QVariant::UInt: |
| case QVariant::ULongLong: |
| case QMetaType::UChar: |
| case QMetaType::UShort: |
| case QMetaType::ULong: |
| *f = float(qMetaTypeUNumber(d)); |
| break; |
| #ifndef QT_BOOTSTRAPPED |
| case QMetaType::QCborValue: |
| *f = v_cast<QCborValue>(d)->toDouble(); |
| if (!v_cast<QCborValue>(d)->isDouble()) |
| return false; |
| break; |
| case QMetaType::QJsonValue: |
| *f = v_cast<QJsonValue>(d)->toDouble(0.0); |
| if (!v_cast<QJsonValue>(d)->isDouble()) |
| return false; |
| break; |
| #endif |
| default: |
| *f = 0.0f; |
| return false; |
| } |
| break; |
| } |
| case QVariant::List: |
| if (d->type == QVariant::StringList) { |
| QVariantList *lst = static_cast<QVariantList *>(result); |
| const QStringList *slist = v_cast<QStringList>(d); |
| const int size = slist->size(); |
| lst->reserve(size); |
| for (int i = 0; i < size; ++i) |
| lst->append(QVariant(slist->at(i))); |
| } else if (qstrcmp(QMetaType::typeName(d->type), "QList<QVariant>") == 0) { |
| *static_cast<QVariantList *>(result) = |
| *static_cast<QList<QVariant> *>(d->data.shared->ptr); |
| #ifndef QT_BOOTSTRAPPED |
| } else if (d->type == QMetaType::QCborValue) { |
| if (!v_cast<QCborValue>(d)->isArray()) |
| return false; |
| *static_cast<QVariantList *>(result) = v_cast<QCborValue>(d)->toArray().toVariantList(); |
| } else if (d->type == QMetaType::QCborArray) { |
| *static_cast<QVariantList *>(result) = v_cast<QCborArray>(d)->toVariantList(); |
| } else if (d->type == QMetaType::QJsonValue) { |
| if (!v_cast<QJsonValue>(d)->isArray()) |
| return false; |
| *static_cast<QVariantList *>(result) = v_cast<QJsonValue>(d)->toArray().toVariantList(); |
| } else if (d->type == QMetaType::QJsonArray) { |
| *static_cast<QVariantList *>(result) = v_cast<QJsonArray>(d)->toVariantList(); |
| #endif |
| } else { |
| return false; |
| } |
| break; |
| case QVariant::Map: |
| if (qstrcmp(QMetaType::typeName(d->type), "QMap<QString, QVariant>") == 0) { |
| *static_cast<QVariantMap *>(result) = |
| *static_cast<QMap<QString, QVariant> *>(d->data.shared->ptr); |
| } else if (d->type == QVariant::Hash) { |
| QVariantMap *map = static_cast<QVariantMap *>(result); |
| const QVariantHash *hash = v_cast<QVariantHash>(d); |
| const auto end = hash->end(); |
| for (auto it = hash->begin(); it != end; ++it) |
| map->insertMulti(it.key(), it.value()); |
| #ifndef QT_BOOTSTRAPPED |
| } else if (d->type == QMetaType::QCborValue) { |
| if (!v_cast<QCborValue>(d)->isMap()) |
| return false; |
| *static_cast<QVariantMap *>(result) = v_cast<QCborValue>(d)->toMap().toVariantMap(); |
| } else if (d->type == QMetaType::QCborMap) { |
| *static_cast<QVariantMap *>(result) = v_cast<QCborMap>(d)->toVariantMap(); |
| } else if (d->type == QMetaType::QJsonValue) { |
| if (!v_cast<QJsonValue>(d)->isObject()) |
| return false; |
| *static_cast<QVariantMap *>(result) = v_cast<QJsonValue>(d)->toObject().toVariantMap(); |
| } else if (d->type == QMetaType::QJsonObject) { |
| *static_cast<QVariantMap *>(result) = v_cast<QJsonObject>(d)->toVariantMap(); |
| #endif |
| } else { |
| return false; |
| } |
| break; |
| case QVariant::Hash: |
| if (qstrcmp(QMetaType::typeName(d->type), "QHash<QString, QVariant>") == 0) { |
| *static_cast<QVariantHash *>(result) = |
| *static_cast<QHash<QString, QVariant> *>(d->data.shared->ptr); |
| } else if (d->type == QVariant::Map) { |
| QVariantHash *hash = static_cast<QVariantHash *>(result); |
| const QVariantMap *map = v_cast<QVariantMap>(d); |
| const auto end = map->end(); |
| for (auto it = map->begin(); it != end; ++it) |
| hash->insertMulti(it.key(), it.value()); |
| #ifndef QT_BOOTSTRAPPED |
| } else if (d->type == QMetaType::QCborValue) { |
| if (!v_cast<QCborValue>(d)->isMap()) |
| return false; |
| *static_cast<QVariantHash *>(result) = v_cast<QCborValue>(d)->toMap().toVariantHash(); |
| } else if (d->type == QMetaType::QCborMap) { |
| *static_cast<QVariantHash *>(result) = v_cast<QCborMap>(d)->toVariantHash(); |
| } else if (d->type == QMetaType::QJsonValue) { |
| if (!v_cast<QJsonValue>(d)->isObject()) |
| return false; |
| *static_cast<QVariantHash *>(result) = v_cast<QJsonValue>(d)->toObject().toVariantHash(); |
| } else if (d->type == QMetaType::QJsonObject) { |
| *static_cast<QVariantHash *>(result) = v_cast<QJsonObject>(d)->toVariantHash(); |
| #endif |
| } else { |
| return false; |
| } |
| break; |
| #ifndef QT_NO_GEOM_VARIANT |
| case QVariant::Rect: |
| if (d->type == QVariant::RectF) |
| *static_cast<QRect *>(result) = (v_cast<QRectF>(d))->toRect(); |
| else |
| return false; |
| break; |
| case QVariant::RectF: |
| if (d->type == QVariant::Rect) |
| *static_cast<QRectF *>(result) = *v_cast<QRect>(d); |
| else |
| return false; |
| break; |
| case QVariant::PointF: |
| if (d->type == QVariant::Point) |
| *static_cast<QPointF *>(result) = *v_cast<QPoint>(d); |
| else |
| return false; |
| break; |
| case QVariant::Point: |
| if (d->type == QVariant::PointF) |
| *static_cast<QPoint *>(result) = (v_cast<QPointF>(d))->toPoint(); |
| else |
| return false; |
| break; |
| case QMetaType::Char: |
| { |
| *static_cast<qint8 *>(result) = qint8(qConvertToNumber(d, ok)); |
| return *ok; |
| } |
| #endif |
| case QVariant::Uuid: |
| switch (d->type) { |
| case QVariant::String: |
| *static_cast<QUuid *>(result) = QUuid(*v_cast<QString>(d)); |
| break; |
| case QVariant::ByteArray: |
| *static_cast<QUuid *>(result) = QUuid(*v_cast<QByteArray>(d)); |
| break; |
| #ifndef QT_BOOTSTRAPPED |
| case QMetaType::QCborValue: |
| if (!v_cast<QCborValue>(d)->isUuid()) |
| return false; |
| *static_cast<QUuid *>(result) = v_cast<QCborValue>(d)->toUuid(); |
| break; |
| #endif |
| default: |
| return false; |
| } |
| break; |
| case QMetaType::Nullptr: |
| *static_cast<std::nullptr_t *>(result) = nullptr; |
| if (QMetaType::typeFlags(t) & (QMetaType::PointerToGadget | QMetaType::PointerToQObject) |
| || d->type == QMetaType::VoidStar) { |
| if (v_cast<const void *>(d) == nullptr) |
| break; |
| } |
| #ifndef QT_BOOTSTRAPPED |
| if (d->type == QMetaType::QCborValue && v_cast<QCborValue>(d)->isNull()) |
| break; |
| #endif |
| return false; |
| |
| #ifndef QT_BOOTSTRAPPED |
| #if QT_CONFIG(regularexpression) |
| case QMetaType::QRegularExpression: |
| if (d->type != QMetaType::QCborValue || !v_cast<QCborValue>(d)->isRegularExpression()) |
| return false; |
| *static_cast<QRegularExpression *>(result) = v_cast<QCborValue>(d)->toRegularExpression(); |
| break; |
| #endif |
| case QMetaType::QJsonValue: |
| switch (d->type) { |
| case QMetaType::Nullptr: |
| *static_cast<QJsonValue *>(result) = QJsonValue(QJsonValue::Null); |
| break; |
| case QVariant::Bool: |
| *static_cast<QJsonValue *>(result) = QJsonValue(d->data.b); |
| break; |
| case QMetaType::Int: |
| case QMetaType::UInt: |
| case QMetaType::Double: |
| case QMetaType::Float: |
| case QMetaType::ULong: |
| case QMetaType::Long: |
| case QMetaType::LongLong: |
| case QMetaType::ULongLong: |
| case QMetaType::UShort: |
| case QMetaType::UChar: |
| case QMetaType::Char: |
| case QMetaType::SChar: |
| case QMetaType::Short: |
| *static_cast<QJsonValue *>(result) = QJsonValue(qConvertToRealNumber(d, ok)); |
| Q_ASSERT(ok); |
| break; |
| case QVariant::String: |
| *static_cast<QJsonValue *>(result) = QJsonValue(*v_cast<QString>(d)); |
| break; |
| case QVariant::StringList: |
| *static_cast<QJsonValue *>(result) = QJsonValue(QJsonArray::fromStringList(*v_cast<QStringList>(d))); |
| break; |
| case QVariant::List: |
| *static_cast<QJsonValue *>(result) = QJsonValue(QJsonArray::fromVariantList(*v_cast<QVariantList>(d))); |
| break; |
| case QVariant::Map: |
| *static_cast<QJsonValue *>(result) = QJsonValue(QJsonObject::fromVariantMap(*v_cast<QVariantMap>(d))); |
| break; |
| case QVariant::Hash: |
| *static_cast<QJsonValue *>(result) = QJsonValue(QJsonObject::fromVariantHash(*v_cast<QVariantHash>(d))); |
| break; |
| case QMetaType::QJsonObject: |
| *static_cast<QJsonValue *>(result) = *v_cast<QJsonObject>(d); |
| break; |
| case QMetaType::QJsonArray: |
| *static_cast<QJsonValue *>(result) = *v_cast<QJsonArray>(d); |
| break; |
| case QMetaType::QJsonDocument: { |
| QJsonDocument doc = *v_cast<QJsonDocument>(d); |
| *static_cast<QJsonValue *>(result) = doc.isArray() ? QJsonValue(doc.array()) : QJsonValue(doc.object()); |
| break; |
| } |
| case QMetaType::QCborValue: |
| *static_cast<QJsonValue *>(result) = v_cast<QCborValue>(d)->toJsonValue(); |
| break; |
| case QMetaType::QCborMap: |
| *static_cast<QJsonValue *>(result) = v_cast<QCborMap>(d)->toJsonObject(); |
| break; |
| case QMetaType::QCborArray: |
| *static_cast<QJsonValue *>(result) = v_cast<QCborArray>(d)->toJsonArray(); |
| break; |
| default: |
| *static_cast<QJsonValue *>(result) = QJsonValue(QJsonValue::Undefined); |
| return false; |
| } |
| break; |
| case QMetaType::QJsonArray: |
| switch (d->type) { |
| case QVariant::StringList: |
| *static_cast<QJsonArray *>(result) = QJsonArray::fromStringList(*v_cast<QStringList>(d)); |
| break; |
| case QVariant::List: |
| *static_cast<QJsonArray *>(result) = QJsonArray::fromVariantList(*v_cast<QVariantList>(d)); |
| break; |
| case QMetaType::QJsonValue: |
| if (!v_cast<QJsonValue>(d)->isArray()) |
| return false; |
| *static_cast<QJsonArray *>(result) = v_cast<QJsonValue>(d)->toArray(); |
| break; |
| case QMetaType::QJsonDocument: |
| if (!v_cast<QJsonDocument>(d)->isArray()) |
| return false; |
| *static_cast<QJsonArray *>(result) = v_cast<QJsonDocument>(d)->array(); |
| break; |
| case QMetaType::QCborValue: |
| if (!v_cast<QCborValue>(d)->isArray()) |
| return false; |
| *static_cast<QJsonArray *>(result) = v_cast<QCborValue>(d)->toArray().toJsonArray(); |
| break; |
| case QMetaType::QCborArray: |
| *static_cast<QJsonArray *>(result) = v_cast<QCborArray>(d)->toJsonArray(); |
| break; |
| default: |
| return false; |
| } |
| break; |
| case QMetaType::QJsonObject: |
| switch (d->type) { |
| case QVariant::Map: |
| *static_cast<QJsonObject *>(result) = QJsonObject::fromVariantMap(*v_cast<QVariantMap>(d)); |
| break; |
| case QVariant::Hash: |
| *static_cast<QJsonObject *>(result) = QJsonObject::fromVariantHash(*v_cast<QVariantHash>(d)); |
| break; |
| case QMetaType::QJsonValue: |
| if (!v_cast<QJsonValue>(d)->isObject()) |
| return false; |
| *static_cast<QJsonObject *>(result) = v_cast<QJsonValue>(d)->toObject(); |
| break; |
| case QMetaType::QJsonDocument: |
| if (v_cast<QJsonDocument>(d)->isArray()) |
| return false; |
| *static_cast<QJsonObject *>(result) = v_cast<QJsonDocument>(d)->object(); |
| break; |
| case QMetaType::QCborValue: |
| if (!v_cast<QCborValue>(d)->isMap()) |
| return false; |
| *static_cast<QJsonObject *>(result) = v_cast<QCborValue>(d)->toMap().toJsonObject(); |
| break; |
| case QMetaType::QCborMap: |
| *static_cast<QJsonObject *>(result) = v_cast<QCborMap>(d)->toJsonObject(); |
| break; |
| default: |
| return false; |
| } |
| break; |
| case QMetaType::QCborSimpleType: |
| if (d->type == QMetaType::QCborValue && v_cast<QCborValue>(d)->isSimpleType()) { |
| *static_cast<QCborSimpleType *>(result) = v_cast<QCborValue>(d)->toSimpleType(); |
| break; |
| } |
| return false; |
| case QMetaType::QCborValue: |
| switch (d->type) { |
| case QMetaType::Nullptr: |
| *static_cast<QCborValue *>(result) = QCborValue(QCborValue::Null); |
| break; |
| case QVariant::Bool: |
| *static_cast<QCborValue *>(result) = QCborValue(d->data.b); |
| break; |
| case QMetaType::Int: |
| case QMetaType::UInt: |
| case QMetaType::ULong: |
| case QMetaType::Long: |
| case QMetaType::LongLong: |
| case QMetaType::ULongLong: |
| case QMetaType::UShort: |
| case QMetaType::UChar: |
| case QMetaType::Char: |
| case QMetaType::SChar: |
| case QMetaType::Short: |
| *static_cast<QCborValue *>(result) = QCborValue(qConvertToNumber(d, ok)); |
| Q_ASSERT(ok); |
| break; |
| case QMetaType::Double: |
| case QMetaType::Float: |
| *static_cast<QCborValue *>(result) = QCborValue(qConvertToRealNumber(d, ok)); |
| Q_ASSERT(ok); |
| break; |
| case QVariant::String: |
| *static_cast<QCborValue *>(result) = *v_cast<QString>(d); |
| break; |
| case QVariant::StringList: |
| *static_cast<QCborValue *>(result) = QCborArray::fromStringList(*v_cast<QStringList>(d)); |
| break; |
| case QVariant::ByteArray: |
| *static_cast<QCborValue *>(result) = *v_cast<QByteArray>(d); |
| break; |
| case QVariant::Date: |
| *static_cast<QCborValue *>(result) = QCborValue(QDateTime(*v_cast<QDate>(d))); |
| break; |
| case QVariant::DateTime: |
| *static_cast<QCborValue *>(result) = QCborValue(*v_cast<QDateTime>(d)); |
| break; |
| case QVariant::Url: |
| *static_cast<QCborValue *>(result) = QCborValue(*v_cast<QUrl>(d)); |
| break; |
| #if QT_CONFIG(regularexpression) |
| case QVariant::RegularExpression: |
| *static_cast<QCborValue *>(result) = QCborValue(*v_cast<QRegularExpression>(d)); |
| break; |
| #endif |
| case QVariant::Uuid: |
| *static_cast<QCborValue *>(result) = QCborValue(*v_cast<QUuid>(d)); |
| break; |
| case QVariant::List: |
| *static_cast<QCborValue *>(result) = QCborArray::fromVariantList(*v_cast<QVariantList>(d)); |
| break; |
| case QVariant::Map: |
| *static_cast<QCborValue *>(result) = QCborMap::fromVariantMap(*v_cast<QVariantMap>(d)); |
| break; |
| case QVariant::Hash: |
| *static_cast<QCborValue *>(result) = QCborMap::fromVariantHash(*v_cast<QVariantHash>(d)); |
| break; |
| case QMetaType::QJsonValue: |
| *static_cast<QCborValue *>(result) = QCborValue::fromJsonValue(*v_cast<QJsonValue>(d)); |
| break; |
| case QMetaType::QJsonObject: |
| *static_cast<QCborValue *>(result) = QCborMap::fromJsonObject(*v_cast<QJsonObject>(d)); |
| break; |
| case QMetaType::QJsonArray: |
| *static_cast<QCborValue *>(result) = QCborArray::fromJsonArray(*v_cast<QJsonArray>(d)); |
| break; |
| case QMetaType::QJsonDocument: { |
| QJsonDocument doc = *v_cast<QJsonDocument>(d); |
| if (doc.isArray()) |
| *static_cast<QCborValue *>(result) = QCborArray::fromJsonArray(doc.array()); |
| else |
| *static_cast<QCborValue *>(result) = QCborMap::fromJsonObject(doc.object()); |
| break; |
| } |
| case QMetaType::QCborSimpleType: |
| *static_cast<QCborValue *>(result) = *v_cast<QCborSimpleType>(d); |
| break; |
| case QMetaType::QCborMap: |
| *static_cast<QCborValue *>(result) = *v_cast<QCborMap>(d); |
| break; |
| case QMetaType::QCborArray: |
| *static_cast<QCborValue *>(result) = *v_cast<QCborArray>(d); |
| break; |
| default: |
| *static_cast<QCborValue *>(result) = {}; |
| return false; |
| } |
| break; |
| case QMetaType::QCborArray: |
| switch (d->type) { |
| case QVariant::StringList: |
| *static_cast<QCborArray *>(result) = QCborArray::fromStringList(*v_cast<QStringList>(d)); |
| break; |
| case QVariant::List: |
| *static_cast<QCborArray *>(result) = QCborArray::fromVariantList(*v_cast<QVariantList>(d)); |
| break; |
| case QMetaType::QCborValue: |
| if (!v_cast<QCborValue>(d)->isArray()) |
| return false; |
| *static_cast<QCborArray *>(result) = v_cast<QCborValue>(d)->toArray(); |
| break; |
| case QMetaType::QJsonDocument: |
| if (!v_cast<QJsonDocument>(d)->isArray()) |
| return false; |
| *static_cast<QCborArray *>(result) = QCborArray::fromJsonArray(v_cast<QJsonDocument>(d)->array()); |
| break; |
| case QMetaType::QJsonValue: |
| if (!v_cast<QJsonValue>(d)->isArray()) |
| return false; |
| *static_cast<QCborArray *>(result) = QCborArray::fromJsonArray(v_cast<QJsonValue>(d)->toArray()); |
| break; |
| case QMetaType::QJsonArray: |
| *static_cast<QCborArray *>(result) = QCborArray::fromJsonArray(*v_cast<QJsonArray>(d)); |
| break; |
| default: |
| return false; |
| } |
| break; |
| case QMetaType::QCborMap: |
| switch (d->type) { |
| case QVariant::Map: |
| *static_cast<QCborMap *>(result) = QCborMap::fromVariantMap(*v_cast<QVariantMap>(d)); |
| break; |
| case QVariant::Hash: |
| *static_cast<QCborMap *>(result) = QCborMap::fromVariantHash(*v_cast<QVariantHash>(d)); |
| break; |
| case QMetaType::QCborValue: |
| if (!v_cast<QCborValue>(d)->isMap()) |
| return false; |
| *static_cast<QCborMap *>(result) = v_cast<QCborValue>(d)->toMap(); |
| break; |
| case QMetaType::QJsonDocument: |
| if (v_cast<QJsonDocument>(d)->isArray()) |
| return false; |
| *static_cast<QCborMap *>(result) = QCborMap::fromJsonObject(v_cast<QJsonDocument>(d)->object()); |
| break; |
| case QMetaType::QJsonValue: |
| if (!v_cast<QJsonValue>(d)->isObject()) |
| return false; |
| *static_cast<QCborMap *>(result) = QCborMap::fromJsonObject(v_cast<QJsonValue>(d)->toObject()); |
| break; |
| case QMetaType::QJsonObject: |
| *static_cast<QCborMap *>(result) = QCborMap::fromJsonObject(*v_cast<QJsonObject>(d)); |
| break; |
| default: |
| return false; |
| } |
| break; |
| #endif |
| |
| default: |
| #ifndef QT_NO_QOBJECT |
| if (d->type == QVariant::String || d->type == QVariant::ByteArray) { |
| QMetaEnum en = metaEnumFromType(t); |
| if (en.isValid()) { |
| QByteArray keys = (d->type == QVariant::String) ? v_cast<QString>(d)->toUtf8() : *v_cast<QByteArray>(d); |
| int value = en.keysToValue(keys.constData(), ok); |
| if (*ok) { |
| switch (QMetaType::sizeOf(t)) { |
| case 1: |
| *static_cast<signed char *>(result) = value; |
| return true; |
| case 2: |
| *static_cast<qint16 *>(result) = value; |
| return true; |
| case 4: |
| *static_cast<qint32 *>(result) = value; |
| return true; |
| case 8: |
| *static_cast<qint64 *>(result) = value; |
| return true; |
| } |
| } |
| } |
| } |
| #endif |
| if (QMetaType::typeFlags(t) & QMetaType::IsEnumeration || d->type == QMetaType::QCborSimpleType) { |
| qlonglong value = qConvertToNumber(d, ok); |
| if (*ok) { |
| switch (QMetaType::sizeOf(t)) { |
| case 1: |
| *static_cast<signed char *>(result) = value; |
| return true; |
| case 2: |
| *static_cast<qint16 *>(result) = value; |
| return true; |
| case 4: |
| *static_cast<qint32 *>(result) = value; |
| return true; |
| case 8: |
| *static_cast<qint64 *>(result) = value; |
| return true; |
| } |
| } |
| return *ok; |
| } |
| return false; |
| } |
| return true; |
| } |
| |
| #if !defined(QT_NO_DEBUG_STREAM) |
| static void streamDebug(QDebug dbg, const QVariant &v) |
| { |
| QVariant::Private *d = const_cast<QVariant::Private *>(&v.data_ptr()); |
| QVariantDebugStream<CoreTypesFilter> stream(dbg, d); |
| QMetaTypeSwitcher::switcher<void>(stream, d->type); |
| } |
| #endif |
| |
| const QVariant::Handler qt_kernel_variant_handler = { |
| construct, |
| clear, |
| isNull, |
| #ifndef QT_NO_DATASTREAM |
| nullptr, |
| nullptr, |
| #endif |
| compare, |
| convert, |
| nullptr, |
| #if !defined(QT_NO_DEBUG_STREAM) |
| streamDebug |
| #else |
| nullptr |
| #endif |
| }; |
| |
| static void dummyConstruct(QVariant::Private *, const void *) { Q_ASSERT_X(false, "QVariant", "Trying to construct an unknown type"); } |
| static void dummyClear(QVariant::Private *) { Q_ASSERT_X(false, "QVariant", "Trying to clear an unknown type"); } |
| static bool dummyIsNull(const QVariant::Private *d) { Q_ASSERT_X(false, "QVariant::isNull", "Trying to call isNull on an unknown type"); return d->is_null; } |
| static bool dummyCompare(const QVariant::Private *, const QVariant::Private *) { Q_ASSERT_X(false, "QVariant", "Trying to compare an unknown types"); return false; } |
| static bool dummyConvert(const QVariant::Private *, int, void *, bool *) { Q_ASSERT_X(false, "QVariant", "Trying to convert an unknown type"); return false; } |
| #if !defined(QT_NO_DEBUG_STREAM) |
| static void dummyStreamDebug(QDebug, const QVariant &) { Q_ASSERT_X(false, "QVariant", "Trying to convert an unknown type"); } |
| #endif |
| const QVariant::Handler qt_dummy_variant_handler = { |
| dummyConstruct, |
| dummyClear, |
| dummyIsNull, |
| #ifndef QT_NO_DATASTREAM |
| nullptr, |
| nullptr, |
| #endif |
| dummyCompare, |
| dummyConvert, |
| nullptr, |
| #if !defined(QT_NO_DEBUG_STREAM) |
| dummyStreamDebug |
| #else |
| nullptr |
| #endif |
| }; |
| |
| static void customConstruct(QVariant::Private *d, const void *copy) |
| { |
| const QMetaType type(d->type); |
| const uint size = type.sizeOf(); |
| if (!size) { |
| qWarning("Trying to construct an instance of an invalid type, type id: %i", d->type); |
| d->type = QVariant::Invalid; |
| return; |
| } |
| |
| // this logic should match with QVariantIntegrator::CanUseInternalSpace |
| if (size <= sizeof(QVariant::Private::Data) |
| && (type.flags() & (QMetaType::MovableType | QMetaType::IsEnumeration))) { |
| type.construct(&d->data.ptr, copy); |
| d->is_null = d->data.ptr == nullptr; |
| d->is_shared = false; |
| } else { |
| // Private::Data contains long long, and long double is the biggest standard type. |
| const size_t maxAlignment = |
| qMax(Q_ALIGNOF(QVariant::Private::Data), Q_ALIGNOF(long double)); |
| const size_t s = sizeof(QVariant::PrivateShared); |
| const size_t offset = s + ((s * maxAlignment - s) % maxAlignment); |
| void *data = operator new(offset + size); |
| void *ptr = static_cast<char *>(data) + offset; |
| type.construct(ptr, copy); |
| d->is_null = ptr == nullptr; |
| d->is_shared = true; |
| d->data.shared = new (data) QVariant::PrivateShared(ptr); |
| } |
| } |
| |
| static void customClear(QVariant::Private *d) |
| { |
| if (!d->is_shared) { |
| QMetaType::destruct(d->type, &d->data.ptr); |
| } else { |
| QMetaType::destruct(d->type, d->data.shared->ptr); |
| d->data.shared->~PrivateShared(); |
| operator delete(d->data.shared); |
| } |
| } |
| |
| static bool customIsNull(const QVariant::Private *d) |
| { |
| if (d->is_null) |
| return true; |
| const char *const typeName = QMetaType::typeName(d->type); |
| if (Q_UNLIKELY(!typeName) && Q_LIKELY(!QMetaType::isRegistered(d->type))) |
| qFatal("QVariant::isNull: type %d unknown to QVariant.", d->type); |
| uint typeNameLen = qstrlen(typeName); |
| if (typeNameLen > 0 && typeName[typeNameLen - 1] == '*') { |
| const void *d_ptr = d->is_shared ? d->data.shared->ptr : &(d->data.ptr); |
| return *static_cast<void *const *>(d_ptr) == nullptr; |
| } |
| return false; |
| } |
| |
| static bool customCompare(const QVariant::Private *a, const QVariant::Private *b) |
| { |
| const char *const typeName = QMetaType::typeName(a->type); |
| if (Q_UNLIKELY(!typeName) && Q_LIKELY(!QMetaType::isRegistered(a->type))) |
| qFatal("QVariant::compare: type %d unknown to QVariant.", a->type); |
| |
| const void *a_ptr = a->is_shared ? a->data.shared->ptr : &(a->data.ptr); |
| const void *b_ptr = b->is_shared ? b->data.shared->ptr : &(b->data.ptr); |
| |
| uint typeNameLen = qstrlen(typeName); |
| if (typeNameLen > 0 && typeName[typeNameLen - 1] == '*') |
| return *static_cast<void *const *>(a_ptr) == *static_cast<void *const *>(b_ptr); |
| |
| if (a->is_null && b->is_null) |
| return true; |
| |
| return !memcmp(a_ptr, b_ptr, QMetaType::sizeOf(a->type)); |
| } |
| |
| static bool customConvert(const QVariant::Private *d, int t, void *result, bool *ok) |
| { |
| if (d->type >= QMetaType::User || t >= QMetaType::User) { |
| if (QMetaType::convert(constData(*d), d->type, result, t)) { |
| if (ok) |
| *ok = true; |
| return true; |
| } |
| } |
| return convert(d, t, result, ok); |
| } |
| |
| #if !defined(QT_NO_DEBUG_STREAM) |
| static void customStreamDebug(QDebug dbg, const QVariant &variant) { |
| #ifndef QT_BOOTSTRAPPED |
| QMetaType::TypeFlags flags = QMetaType::typeFlags(variant.userType()); |
| if (flags & QMetaType::PointerToQObject) |
| dbg.nospace() << variant.value<QObject*>(); |
| #else |
| Q_UNUSED(dbg); |
| Q_UNUSED(variant); |
| #endif |
| } |
| #endif |
| |
| const QVariant::Handler qt_custom_variant_handler = { |
| customConstruct, |
| customClear, |
| customIsNull, |
| #ifndef QT_NO_DATASTREAM |
| nullptr, |
| nullptr, |
| #endif |
| customCompare, |
| customConvert, |
| nullptr, |
| #if !defined(QT_NO_DEBUG_STREAM) |
| customStreamDebug |
| #else |
| nullptr |
| #endif |
| }; |
| |
| } // annonymous used to hide QVariant handlers |
| |
| static HandlersManager handlerManager; |
| Q_STATIC_ASSERT_X(!QModulesPrivate::Core, "Initialization assumes that ModulesNames::Core is 0"); |
| const QVariant::Handler *HandlersManager::Handlers[QModulesPrivate::ModulesCount] |
| = { &qt_kernel_variant_handler, &qt_dummy_variant_handler, |
| &qt_dummy_variant_handler, &qt_custom_variant_handler }; |
| |
| Q_CORE_EXPORT const QVariant::Handler *qcoreVariantHandler() |
| { |
| return &qt_kernel_variant_handler; |
| } |
| |
| Q_CORE_EXPORT void QVariantPrivate::registerHandler(const int /* Modules::Names */name, const QVariant::Handler *handler) |
| { |
| handlerManager.registerHandler(static_cast<QModulesPrivate::Names>(name), handler); |
| } |
| |
| /*! |
| \class QVariant |
| \inmodule QtCore |
| \brief The QVariant class acts like a union for the most common Qt data types. |
| |
| \ingroup objectmodel |
| \ingroup shared |
| |
| |
| Because C++ forbids unions from including types that have |
| non-default constructors or destructors, most interesting Qt |
| classes cannot be used in unions. Without QVariant, this would be |
| a problem for QObject::property() and for database work, etc. |
| |
| A QVariant object holds a single value of a single type() at a |
| time. (Some type()s are multi-valued, for example a string list.) |
| You can find out what type, T, the variant holds, convert it to a |
| different type using convert(), get its value using one of the |
| toT() functions (e.g., toSize()) and check whether the type can |
| be converted to a particular type using canConvert(). |
| |
| The methods named toT() (e.g., toInt(), toString()) are const. If |
| you ask for the stored type, they return a copy of the stored |
| object. If you ask for a type that can be generated from the |
| stored type, toT() copies and converts and leaves the object |
| itself unchanged. If you ask for a type that cannot be generated |
| from the stored type, the result depends on the type; see the |
| function documentation for details. |
| |
| Here is some example code to demonstrate the use of QVariant: |
| |
| \snippet code/src_corelib_kernel_qvariant.cpp 0 |
| |
| You can even store QList<QVariant> and QMap<QString, QVariant> |
| values in a variant, so you can easily construct arbitrarily |
| complex data structures of arbitrary types. This is very powerful |
| and versatile, but may prove less memory and speed efficient than |
| storing specific types in standard data structures. |
| |
| QVariant also supports the notion of null values, where you can |
| have a defined type with no value set. However, note that QVariant |
| types can only be cast when they have had a value set. |
| |
| \snippet code/src_corelib_kernel_qvariant.cpp 1 |
| |
| QVariant can be extended to support other types than those |
| mentioned in the \l Type enum. See \l{Creating Custom Qt Types}{Creating Custom Qt Types} |
| for details. |
| |
| \section1 A Note on GUI Types |
| |
| Because QVariant is part of the Qt Core module, it cannot provide |
| conversion functions to data types defined in Qt GUI, such as |
| QColor, QImage, and QPixmap. In other words, there is no \c |
| toColor() function. Instead, you can use the QVariant::value() or |
| the qvariant_cast() template function. For example: |
| |
| \snippet code/src_corelib_kernel_qvariant.cpp 2 |
| |
| The inverse conversion (e.g., from QColor to QVariant) is |
| automatic for all data types supported by QVariant, including |
| GUI-related types: |
| |
| \snippet code/src_corelib_kernel_qvariant.cpp 3 |
| |
| \section1 Using canConvert() and convert() Consecutively |
| |
| When using canConvert() and convert() consecutively, it is possible for |
| canConvert() to return true, but convert() to return false. This |
| is typically because canConvert() only reports the general ability of |
| QVariant to convert between types given suitable data; it is still |
| possible to supply data which cannot actually be converted. |
| |
| For example, canConvert(Int) would return true when called on a variant |
| containing a string because, in principle, QVariant is able to convert |
| strings of numbers to integers. |
| However, if the string contains non-numeric characters, it cannot be |
| converted to an integer, and any attempt to convert it will fail. |
| Hence, it is important to have both functions return true for a |
| successful conversion. |
| |
| \sa QMetaType |
| */ |
| |
| /*! |
| \obsolete Use QMetaType::Type instead |
| \enum QVariant::Type |
| |
| This enum type defines the types of variable that a QVariant can |
| contain. |
| |
| \value Invalid no type |
| \value BitArray a QBitArray |
| \value Bitmap a QBitmap |
| \value Bool a bool |
| \value Brush a QBrush |
| \value ByteArray a QByteArray |
| \value Char a QChar |
| \value Color a QColor |
| \value Cursor a QCursor |
| \value Date a QDate |
| \value DateTime a QDateTime |
| \value Double a double |
| \value EasingCurve a QEasingCurve |
| \value Uuid a QUuid |
| \value ModelIndex a QModelIndex |
| \value PersistentModelIndex a QPersistentModelIndex (since 5.5) |
| \value Font a QFont |
| \value Hash a QVariantHash |
| \value Icon a QIcon |
| \value Image a QImage |
| \value Int an int |
| \value KeySequence a QKeySequence |
| \value Line a QLine |
| \value LineF a QLineF |
| \value List a QVariantList |
| \value Locale a QLocale |
| \value LongLong a \l qlonglong |
| \value Map a QVariantMap |
| \value Matrix a QMatrix |
| \value Transform a QTransform |
| \value Matrix4x4 a QMatrix4x4 |
| \value Palette a QPalette |
| \value Pen a QPen |
| \value Pixmap a QPixmap |
| \value Point a QPoint |
| \value PointF a QPointF |
| \value Polygon a QPolygon |
| \value PolygonF a QPolygonF |
| \value Quaternion a QQuaternion |
| \value Rect a QRect |
| \value RectF a QRectF |
| \value RegExp a QRegExp |
| \value RegularExpression a QRegularExpression |
| \value Region a QRegion |
| \value Size a QSize |
| \value SizeF a QSizeF |
| \value SizePolicy a QSizePolicy |
| \value String a QString |
| \value StringList a QStringList |
| \value TextFormat a QTextFormat |
| \value TextLength a QTextLength |
| \value Time a QTime |
| \value UInt a \l uint |
| \value ULongLong a \l qulonglong |
| \value Url a QUrl |
| \value Vector2D a QVector2D |
| \value Vector3D a QVector3D |
| \value Vector4D a QVector4D |
| |
| \value UserType Base value for user-defined types. |
| |
| \omitvalue LastGuiType |
| \omitvalue LastCoreType |
| \omitvalue LastType |
| */ |
| |
| /*! |
| \fn QVariant::QVariant(QVariant &&other) |
| |
| Move-constructs a QVariant instance, making it point at the same |
| object that \a other was pointing to. |
| |
| \since 5.2 |
| */ |
| |
| /*! |
| \fn QVariant &QVariant::operator=(QVariant &&other) |
| |
| Move-assigns \a other to this QVariant instance. |
| |
| \since 5.2 |
| */ |
| |
| /*! |
| \fn QVariant::QVariant() |
| |
| Constructs an invalid variant. |
| */ |
| |
| |
| /*! |
| \fn QVariant::QVariant(int typeId, const void *copy) |
| |
| Constructs variant of type \a typeId, and initializes with |
| \a copy if \a copy is not \nullptr. |
| |
| Note that you have to pass the address of the variable you want stored. |
| |
| Usually, you never have to use this constructor, use QVariant::fromValue() |
| instead to construct variants from the pointer types represented by |
| \c QMetaType::VoidStar, and \c QMetaType::QObjectStar. |
| |
| \sa QVariant::fromValue(), QMetaType::Type |
| */ |
| |
| /*! |
| \fn QVariant::QVariant(Type type) |
| |
| Constructs an uninitialized variant of type \a type. This will create a |
| variant in a special null state that if accessed will return a default |
| constructed value of the \a type. |
| |
| \sa isNull() |
| */ |
| |
| |
| |
| /*! |
| \fn QVariant::create(int type, const void *copy) |
| |
| \internal |
| |
| Constructs a variant private of type \a type, and initializes with \a copy if |
| \a copy is not \nullptr. |
| */ |
| |
| void QVariant::create(int type, const void *copy) |
| { |
| d.type = type; |
| handlerManager[type]->construct(&d, copy); |
| } |
| |
| /*! |
| \fn QVariant::~QVariant() |
| |
| Destroys the QVariant and the contained object. |
| |
| Note that subclasses that reimplement clear() should reimplement |
| the destructor to call clear(). This destructor calls clear(), but |
| because it is the destructor, QVariant::clear() is called rather |
| than a subclass's clear(). |
| */ |
| |
| QVariant::~QVariant() |
| { |
| if ((d.is_shared && !d.data.shared->ref.deref()) || (!d.is_shared && d.type > Char)) |
| handlerManager[d.type]->clear(&d); |
| } |
| |
| /*! |
| \fn QVariant::QVariant(const QVariant &p) |
| |
| Constructs a copy of the variant, \a p, passed as the argument to |
| this constructor. |
| */ |
| |
| QVariant::QVariant(const QVariant &p) |
| : d(p.d) |
| { |
| if (d.is_shared) { |
| d.data.shared->ref.ref(); |
| } else if (p.d.type > Char) { |
| handlerManager[d.type]->construct(&d, p.constData()); |
| d.is_null = p.d.is_null; |
| } |
| } |
| |
| #ifndef QT_NO_DATASTREAM |
| /*! |
| Reads the variant from the data stream, \a s. |
| */ |
| QVariant::QVariant(QDataStream &s) |
| { |
| d.is_null = true; |
| s >> *this; |
| } |
| #endif //QT_NO_DATASTREAM |
| |
| /*! |
| \fn QVariant::QVariant(const QString &val) |
| |
| Constructs a new variant with a string value, \a val. |
| */ |
| |
| /*! |
| \fn QVariant::QVariant(QLatin1String val) |
| |
| Constructs a new variant with a string value, \a val. |
| */ |
| |
| /*! |
| \fn QVariant::QVariant(const char *val) |
| |
| Constructs a new variant with a string value of \a val. |
| The variant creates a deep copy of \a val into a QString assuming |
| UTF-8 encoding on the input \a val. |
| |
| Note that \a val is converted to a QString for storing in the |
| variant and QVariant::userType() will return QMetaType::QString for |
| the variant. |
| |
| You can disable this operator by defining \c |
| QT_NO_CAST_FROM_ASCII when you compile your applications. |
| */ |
| |
| #ifndef QT_NO_CAST_FROM_ASCII |
| QVariant::QVariant(const char *val) |
| { |
| QString s = QString::fromUtf8(val); |
| create(String, &s); |
| } |
| #endif |
| |
| /*! |
| \fn QVariant::QVariant(const QStringList &val) |
| |
| Constructs a new variant with a string list value, \a val. |
| */ |
| |
| /*! |
| \fn QVariant::QVariant(const QMap<QString, QVariant> &val) |
| |
| Constructs a new variant with a map of \l {QVariant}s, \a val. |
| */ |
| |
| /*! |
| \fn QVariant::QVariant(const QHash<QString, QVariant> &val) |
| |
| Constructs a new variant with a hash of \l {QVariant}s, \a val. |
| */ |
| |
| /*! |
| \fn QVariant::QVariant(const QDate &val) |
| |
| Constructs a new variant with a date value, \a val. |
| */ |
| |
| /*! |
| \fn QVariant::QVariant(const QTime &val) |
| |
| Constructs a new variant with a time value, \a val. |
| */ |
| |
| /*! |
| \fn QVariant::QVariant(const QDateTime &val) |
| |
| Constructs a new variant with a date/time value, \a val. |
| */ |
| |
| /*! |
| \since 4.7 |
| \fn QVariant::QVariant(const QEasingCurve &val) |
| |
| Constructs a new variant with an easing curve value, \a val. |
| */ |
| |
| /*! |
| \since 5.0 |
| \fn QVariant::QVariant(const QUuid &val) |
| |
| Constructs a new variant with an uuid value, \a val. |
| */ |
| |
| /*! |
| \since 5.0 |
| \fn QVariant::QVariant(const QModelIndex &val) |
| |
| Constructs a new variant with a QModelIndex value, \a val. |
| */ |
| |
| /*! |
| \since 5.5 |
| \fn QVariant::QVariant(const QPersistentModelIndex &val) |
| |
| Constructs a new variant with a QPersistentModelIndex value, \a val. |
| */ |
| |
| /*! |
| \since 5.0 |
| \fn QVariant::QVariant(const QJsonValue &val) |
| |
| Constructs a new variant with a json value, \a val. |
| */ |
| |
| /*! |
| \since 5.0 |
| \fn QVariant::QVariant(const QJsonObject &val) |
| |
| Constructs a new variant with a json object value, \a val. |
| */ |
| |
| /*! |
| \since 5.0 |
| \fn QVariant::QVariant(const QJsonArray &val) |
| |
| Constructs a new variant with a json array value, \a val. |
| */ |
| |
| /*! |
| \since 5.0 |
| \fn QVariant::QVariant(const QJsonDocument &val) |
| |
| Constructs a new variant with a json document value, \a val. |
| */ |
| |
| /*! |
| \fn QVariant::QVariant(const QByteArray &val) |
| |
| Constructs a new variant with a bytearray value, \a val. |
| */ |
| |
| /*! |
| \fn QVariant::QVariant(const QBitArray &val) |
| |
| Constructs a new variant with a bitarray value, \a val. |
| */ |
| |
| /*! |
| \fn QVariant::QVariant(const QPoint &val) |
| |
| Constructs a new variant with a point value of \a val. |
| */ |
| |
| /*! |
| \fn QVariant::QVariant(const QPointF &val) |
| |
| Constructs a new variant with a point value of \a val. |
| */ |
| |
| /*! |
| \fn QVariant::QVariant(const QRectF &val) |
| |
| Constructs a new variant with a rect value of \a val. |
| */ |
| |
| /*! |
| \fn QVariant::QVariant(const QLineF &val) |
| |
| Constructs a new variant with a line value of \a val. |
| */ |
| |
| /*! |
| \fn QVariant::QVariant(const QLine &val) |
| |
| Constructs a new variant with a line value of \a val. |
| */ |
| |
| /*! |
| \fn QVariant::QVariant(const QRect &val) |
| |
| Constructs a new variant with a rect value of \a val. |
| */ |
| |
| /*! |
| \fn QVariant::QVariant(const QSize &val) |
| |
| Constructs a new variant with a size value of \a val. |
| */ |
| |
| /*! |
| \fn QVariant::QVariant(const QSizeF &val) |
| |
| Constructs a new variant with a size value of \a val. |
| */ |
| |
| /*! |
| \fn QVariant::QVariant(const QUrl &val) |
| |
| Constructs a new variant with a url value of \a val. |
| */ |
| |
| /*! |
| \fn QVariant::QVariant(int val) |
| |
| Constructs a new variant with an integer value, \a val. |
| */ |
| |
| /*! |
| \fn QVariant::QVariant(uint val) |
| |
| Constructs a new variant with an unsigned integer value, \a val. |
| */ |
| |
| /*! |
| \fn QVariant::QVariant(qlonglong val) |
| |
| Constructs a new variant with a long long integer value, \a val. |
| */ |
| |
| /*! |
| \fn QVariant::QVariant(qulonglong val) |
| |
| Constructs a new variant with an unsigned long long integer value, \a val. |
| */ |
| |
| |
| /*! |
| \fn QVariant::QVariant(bool val) |
| |
| Constructs a new variant with a boolean value, \a val. |
| */ |
| |
| /*! |
| \fn QVariant::QVariant(double val) |
| |
| Constructs a new variant with a floating point value, \a val. |
| */ |
| |
| /*! |
| \fn QVariant::QVariant(float val) |
| |
| Constructs a new variant with a floating point value, \a val. |
| \since 4.6 |
| */ |
| |
| /*! |
| \fn QVariant::QVariant(const QList<QVariant> &val) |
| |
| Constructs a new variant with a list value, \a val. |
| */ |
| |
| /*! |
| \fn QVariant::QVariant(QChar c) |
| |
| Constructs a new variant with a char value, \a c. |
| */ |
| |
| /*! |
| \fn QVariant::QVariant(const QLocale &l) |
| |
| Constructs a new variant with a locale value, \a l. |
| */ |
| |
| /*! |
| \fn QVariant::QVariant(const QRegExp ®Exp) |
| |
| Constructs a new variant with the regexp value \a regExp. |
| */ |
| |
| /*! |
| \fn QVariant::QVariant(const QRegularExpression &re) |
| |
| \since 5.0 |
| |
| Constructs a new variant with the regular expression value \a re. |
| */ |
| |
| QVariant::QVariant(Type type) |
| { create(type, nullptr); } |
| QVariant::QVariant(int typeId, const void *copy) |
| { create(typeId, copy); d.is_null = false; } |
| |
| /*! |
| \internal |
| flags is true if it is a pointer type |
| */ |
| QVariant::QVariant(int typeId, const void *copy, uint flags) |
| { |
| if (flags) { //type is a pointer type |
| d.type = typeId; |
| d.data.ptr = *reinterpret_cast<void *const*>(copy); |
| } else { |
| create(typeId, copy); |
| } |
| d.is_null = false; |
| } |
| |
| QVariant::QVariant(int val) |
| : d(Int) |
| { d.data.i = val; } |
| QVariant::QVariant(uint val) |
| : d(UInt) |
| { d.data.u = val; } |
| QVariant::QVariant(qlonglong val) |
| : d(LongLong) |
| { d.data.ll = val; } |
| QVariant::QVariant(qulonglong val) |
| : d(ULongLong) |
| { d.data.ull = val; } |
| QVariant::QVariant(bool val) |
| : d(Bool) |
| { d.data.b = val; } |
| QVariant::QVariant(double val) |
| : d(Double) |
| { d.data.d = val; } |
| QVariant::QVariant(float val) |
| : d(QMetaType::Float) |
| { d.data.f = val; } |
| |
| QVariant::QVariant(const QByteArray &val) |
| : d(ByteArray) |
| { v_construct<QByteArray>(&d, val); } |
| QVariant::QVariant(const QBitArray &val) |
| : d(BitArray) |
| { v_construct<QBitArray>(&d, val); } |
| QVariant::QVariant(const QString &val) |
| : d(String) |
| { v_construct<QString>(&d, val); } |
| QVariant::QVariant(QChar val) |
| : d(Char) |
| { v_construct<QChar>(&d, val); } |
| QVariant::QVariant(QLatin1String val) |
| : d(String) |
| { v_construct<QString>(&d, val); } |
| QVariant::QVariant(const QStringList &val) |
| : d(StringList) |
| { v_construct<QStringList>(&d, val); } |
| |
| QVariant::QVariant(const QDate &val) |
| : d(Date) |
| { v_construct<QDate>(&d, val); } |
| QVariant::QVariant(const QTime &val) |
| : d(Time) |
| { v_construct<QTime>(&d, val); } |
| QVariant::QVariant(const QDateTime &val) |
| : d(DateTime) |
| { v_construct<QDateTime>(&d, val); } |
| #if QT_CONFIG(easingcurve) |
| QVariant::QVariant(const QEasingCurve &val) |
| : d(EasingCurve) |
| { v_construct<QEasingCurve>(&d, val); } |
| #endif |
| QVariant::QVariant(const QList<QVariant> &list) |
| : d(List) |
| { v_construct<QVariantList>(&d, list); } |
| QVariant::QVariant(const QMap<QString, QVariant> &map) |
| : d(Map) |
| { v_construct<QVariantMap>(&d, map); } |
| QVariant::QVariant(const QHash<QString, QVariant> &hash) |
| : d(Hash) |
| { v_construct<QVariantHash>(&d, hash); } |
| #ifndef QT_NO_GEOM_VARIANT |
| QVariant::QVariant(const QPoint &pt) |
| : d(Point) |
| { v_construct<QPoint>(&d, pt); } |
| QVariant::QVariant(const QPointF &pt) |
| : d(PointF) |
| { v_construct<QPointF>(&d, pt); } |
| QVariant::QVariant(const QRectF &r) |
| : d(RectF) |
| { v_construct<QRectF>(&d, r); } |
| QVariant::QVariant(const QLineF &l) |
| : d(LineF) |
| { v_construct<QLineF>(&d, l); } |
| QVariant::QVariant(const QLine &l) |
| : d(Line) |
| { v_construct<QLine>(&d, l); } |
| QVariant::QVariant(const QRect &r) |
| : d(Rect) |
| { v_construct<QRect>(&d, r); } |
| QVariant::QVariant(const QSize &s) |
| : d(Size) |
| { v_construct<QSize>(&d, s); } |
| QVariant::QVariant(const QSizeF &s) |
| : d(SizeF) |
| { v_construct<QSizeF>(&d, s); } |
| #endif |
| #ifndef QT_BOOTSTRAPPED |
| QVariant::QVariant(const QUrl &u) |
| : d(Url) |
| { v_construct<QUrl>(&d, u); } |
| #endif |
| QVariant::QVariant(const QLocale &l) |
| : d(Locale) |
| { v_construct<QLocale>(&d, l); } |
| #ifndef QT_NO_REGEXP |
| QVariant::QVariant(const QRegExp ®Exp) |
| : d(RegExp) |
| { v_construct<QRegExp>(&d, regExp); } |
| #endif // QT_NO_REGEXP |
| #if QT_CONFIG(regularexpression) |
| QVariant::QVariant(const QRegularExpression &re) |
| : d(RegularExpression) |
| { v_construct<QRegularExpression>(&d, re); } |
| #endif // QT_CONFIG(regularexpression) |
| #ifndef QT_BOOTSTRAPPED |
| QVariant::QVariant(const QUuid &uuid) |
| : d(Uuid) |
| { v_construct<QUuid>(&d, uuid); } |
| QVariant::QVariant(const QJsonValue &jsonValue) |
| : d(QMetaType::QJsonValue) |
| { v_construct<QJsonValue>(&d, jsonValue); } |
| QVariant::QVariant(const QJsonObject &jsonObject) |
| : d(QMetaType::QJsonObject) |
| { v_construct<QJsonObject>(&d, jsonObject); } |
| QVariant::QVariant(const QJsonArray &jsonArray) |
| : d(QMetaType::QJsonArray) |
| { v_construct<QJsonArray>(&d, jsonArray); } |
| QVariant::QVariant(const QJsonDocument &jsonDocument) |
| : d(QMetaType::QJsonDocument) |
| { v_construct<QJsonDocument>(&d, jsonDocument); } |
| #endif // QT_BOOTSTRAPPED |
| #if QT_CONFIG(itemmodel) |
| QVariant::QVariant(const QModelIndex &modelIndex) |
| : d(ModelIndex) |
| { v_construct<QModelIndex>(&d, modelIndex); } |
| QVariant::QVariant(const QPersistentModelIndex &modelIndex) |
| : d(PersistentModelIndex) |
| { v_construct<QPersistentModelIndex>(&d, modelIndex); } |
| #endif |
| |
| /*! |
| Returns the storage type of the value stored in the variant. |
| Although this function is declared as returning QVariant::Type, |
| the return value should be interpreted as QMetaType::Type. In |
| particular, QVariant::UserType is returned here only if the value |
| is equal or greater than QMetaType::User. |
| |
| Note that return values in the ranges QVariant::Char through |
| QVariant::RegExp and QVariant::Font through QVariant::Transform |
| correspond to the values in the ranges QMetaType::QChar through |
| QMetaType::QRegExp and QMetaType::QFont through QMetaType::QQuaternion. |
| |
| Pay particular attention when working with char and QChar |
| variants. Note that there is no QVariant constructor specifically |
| for type char, but there is one for QChar. For a variant of type |
| QChar, this function returns QVariant::Char, which is the same as |
| QMetaType::QChar, but for a variant of type \c char, this function |
| returns QMetaType::Char, which is \e not the same as |
| QVariant::Char. |
| |
| Also note that the types \c void*, \c long, \c short, \c unsigned |
| \c long, \c unsigned \c short, \c unsigned \c char, \c float, \c |
| QObject*, and \c QWidget* are represented in QMetaType::Type but |
| not in QVariant::Type, and they can be returned by this function. |
| However, they are considered to be user defined types when tested |
| against QVariant::Type. |
| |
| To test whether an instance of QVariant contains a data type that |
| is compatible with the data type you are interested in, use |
| canConvert(). |
| */ |
| |
| QVariant::Type QVariant::type() const |
| { |
| return d.type >= QMetaType::User ? UserType : static_cast<Type>(d.type); |
| } |
| |
| /*! |
| Returns the storage type of the value stored in the variant. For |
| non-user types, this is the same as type(). |
| |
| \sa type() |
| */ |
| |
| int QVariant::userType() const |
| { |
| return d.type; |
| } |
| |
| /*! |
| Assigns the value of the variant \a variant to this variant. |
| */ |
| QVariant& QVariant::operator=(const QVariant &variant) |
| { |
| if (this == &variant) |
| return *this; |
| |
| clear(); |
| if (variant.d.is_shared) { |
| variant.d.data.shared->ref.ref(); |
| d = variant.d; |
| } else if (variant.d.type > Char) { |
| d.type = variant.d.type; |
| handlerManager[d.type]->construct(&d, variant.constData()); |
| d.is_null = variant.d.is_null; |
| } else { |
| d = variant.d; |
| } |
| |
| return *this; |
| } |
| |
| /*! |
| \fn void QVariant::swap(QVariant &other) |
| \since 4.8 |
| |
| Swaps variant \a other with this variant. This operation is very |
| fast and never fails. |
| */ |
| |
| /*! |
| \fn void QVariant::detach() |
| |
| \internal |
| */ |
| |
| void QVariant::detach() |
| { |
| if (!d.is_shared || d.data.shared->ref.loadRelaxed() == 1) |
| return; |
| |
| Private dd; |
| dd.type = d.type; |
| handlerManager[d.type]->construct(&dd, constData()); |
| if (!d.data.shared->ref.deref()) |
| handlerManager[d.type]->clear(&d); |
| d.data.shared = dd.data.shared; |
| } |
| |
| /*! |
| \fn bool QVariant::isDetached() const |
| |
| \internal |
| */ |
| |
| /*! |
| Returns the name of the type stored in the variant. The returned |
| strings describe the C++ datatype used to store the data: for |
| example, "QFont", "QString", or "QVariantList". An Invalid |
| variant returns 0. |
| */ |
| const char *QVariant::typeName() const |
| { |
| return QMetaType::typeName(d.type); |
| } |
| |
| /*! |
| Convert this variant to type QMetaType::UnknownType and free up any resources |
| used. |
| */ |
| void QVariant::clear() |
| { |
| if ((d.is_shared && !d.data.shared->ref.deref()) || (!d.is_shared && d.type > Char)) |
| handlerManager[d.type]->clear(&d); |
| d.type = Invalid; |
| d.is_null = true; |
| d.is_shared = false; |
| } |
| |
| /*! |
| Converts the int representation of the storage type, \a typeId, to |
| its string representation. |
| |
| Returns \nullptr if the type is QMetaType::UnknownType or doesn't exist. |
| */ |
| const char *QVariant::typeToName(int typeId) |
| { |
| return QMetaType::typeName(typeId); |
| } |
| |
| |
| /*! |
| Converts the string representation of the storage type given in \a |
| name, to its enum representation. |
| |
| If the string representation cannot be converted to any enum |
| representation, the variant is set to \c Invalid. |
| */ |
| QVariant::Type QVariant::nameToType(const char *name) |
| { |
| int metaType = QMetaType::type(name); |
| return metaType <= int(UserType) ? QVariant::Type(metaType) : UserType; |
| } |
| |
| #ifndef QT_NO_DATASTREAM |
| enum { MapFromThreeCount = 36 }; |
| static const ushort mapIdFromQt3ToCurrent[MapFromThreeCount] = |
| { |
| QVariant::Invalid, |
| QVariant::Map, |
| QVariant::List, |
| QVariant::String, |
| QVariant::StringList, |
| QVariant::Font, |
| QVariant::Pixmap, |
| QVariant::Brush, |
| QVariant::Rect, |
| QVariant::Size, |
| QVariant::Color, |
| QVariant::Palette, |
| 0, // ColorGroup |
| QVariant::Icon, |
| QVariant::Point, |
| QVariant::Image, |
| QVariant::Int, |
| QVariant::UInt, |
| QVariant::Bool, |
| QVariant::Double, |
| 0, // Buggy ByteArray, QByteArray never had id == 20 |
| QVariant::Polygon, |
| QVariant::Region, |
| QVariant::Bitmap, |
| QVariant::Cursor, |
| QVariant::SizePolicy, |
| QVariant::Date, |
| QVariant::Time, |
| QVariant::DateTime, |
| QVariant::ByteArray, |
| QVariant::BitArray, |
| QVariant::KeySequence, |
| QVariant::Pen, |
| QVariant::LongLong, |
| QVariant::ULongLong, |
| #if QT_CONFIG(easingcurve) |
| QVariant::EasingCurve |
| #endif |
| }; |
| |
| /*! |
| Internal function for loading a variant from stream \a s. Use the |
| stream operators instead. |
| |
| \internal |
| */ |
| void QVariant::load(QDataStream &s) |
| { |
| clear(); |
| |
| quint32 typeId; |
| s >> typeId; |
| if (s.version() < QDataStream::Qt_4_0) { |
| if (typeId >= MapFromThreeCount) |
| return; |
| typeId = mapIdFromQt3ToCurrent[typeId]; |
| } else if (s.version() < QDataStream::Qt_5_0) { |
| if (typeId == 127 /* QVariant::UserType */) { |
| typeId = QMetaType::User; |
| } else if (typeId >= 128 && typeId != QVariant::UserType) { |
| // In Qt4 id == 128 was FirstExtCoreType. In Qt5 ExtCoreTypes set was merged to CoreTypes |
| // by moving all ids down by 97. |
| typeId -= 97; |
| } else if (typeId == 75 /* QSizePolicy */) { |
| typeId = QMetaType::QSizePolicy; |
| } else if (typeId > 75 && typeId <= 86) { |
| // and as a result these types received lower ids too |
| // QKeySequence QPen QTextLength QTextFormat QMatrix QTransform QMatrix4x4 QVector2D QVector3D QVector4D QQuaternion |
| typeId -=1; |
| } |
| } |
| |
| qint8 is_null = false; |
| if (s.version() >= QDataStream::Qt_4_2) |
| s >> is_null; |
| if (typeId == QVariant::UserType) { |
| QByteArray name; |
| s >> name; |
| typeId = QMetaType::type(name.constData()); |
| if (typeId == QMetaType::UnknownType) { |
| s.setStatus(QDataStream::ReadCorruptData); |
| qWarning("QVariant::load: unknown user type with name %s.", name.constData()); |
| return; |
| } |
| } |
| create(typeId, 0); |
| d.is_null = is_null; |
| |
| if (!isValid()) { |
| if (s.version() < QDataStream::Qt_5_0) { |
| // Since we wrote something, we should read something |
| QString x; |
| s >> x; |
| } |
| d.is_null = true; |
| return; |
| } |
| |
| // const cast is safe since we operate on a newly constructed variant |
| if (!QMetaType::load(s, d.type, const_cast<void *>(constData()))) { |
| s.setStatus(QDataStream::ReadCorruptData); |
| qWarning("QVariant::load: unable to load type %d.", d.type); |
| } |
| } |
| |
| /*! |
| Internal function for saving a variant to the stream \a s. Use the |
| stream operators instead. |
| |
| \internal |
| */ |
| void QVariant::save(QDataStream &s) const |
| { |
| quint32 typeId = type(); |
| bool fakeUserType = false; |
| if (s.version() < QDataStream::Qt_4_0) { |
| int i; |
| for (i = 0; i <= MapFromThreeCount - 1; ++i) { |
| if (mapIdFromQt3ToCurrent[i] == typeId) { |
| typeId = i; |
| break; |
| } |
| } |
| if (i >= MapFromThreeCount) { |
| s << QVariant(); |
| return; |
| } |
| } else if (s.version() < QDataStream::Qt_5_0) { |
| if (typeId == QMetaType::User) { |
| typeId = 127; // QVariant::UserType had this value in Qt4 |
| } else if (typeId >= 128 - 97 && typeId <= LastCoreType) { |
| // In Qt4 id == 128 was FirstExtCoreType. In Qt5 ExtCoreTypes set was merged to CoreTypes |
| // by moving all ids down by 97. |
| typeId += 97; |
| } else if (typeId == QMetaType::QSizePolicy) { |
| typeId = 75; |
| } else if (typeId >= QMetaType::QKeySequence && typeId <= QMetaType::QQuaternion) { |
| // and as a result these types received lower ids too |
| typeId +=1; |
| } else if (typeId == QMetaType::QPolygonF || typeId == QMetaType::QUuid) { |
| // These existed in Qt 4 only as a custom type |
| typeId = 127; |
| fakeUserType = true; |
| } |
| } |
| s << typeId; |
| if (s.version() >= QDataStream::Qt_4_2) |
| s << qint8(d.is_null); |
| if (d.type >= QVariant::UserType || fakeUserType) { |
| s << QMetaType::typeName(userType()); |
| } |
| |
| if (!isValid()) { |
| if (s.version() < QDataStream::Qt_5_0) |
| s << QString(); |
| return; |
| } |
| |
| if (!QMetaType::save(s, d.type, constData())) { |
| qWarning("QVariant::save: unable to save type '%s' (type id: %d).\n", QMetaType::typeName(d.type), d.type); |
| Q_ASSERT_X(false, "QVariant::save", "Invalid type to save"); |
| } |
| } |
| |
| /*! |
| \since 4.4 |
| |
| Reads a variant \a p from the stream \a s. |
| |
| \sa{Serializing Qt Data Types}{Format of the QDataStream operators} |
| */ |
| QDataStream& operator>>(QDataStream &s, QVariant &p) |
| { |
| p.load(s); |
| return s; |
| } |
| |
| /*! |
| Writes a variant \a p to the stream \a s. |
| |
| \sa{Serializing Qt Data Types}{Format of the QDataStream operators} |
| */ |
| QDataStream& operator<<(QDataStream &s, const QVariant &p) |
| { |
| p.save(s); |
| return s; |
| } |
| |
| /*! |
| Reads a variant type \a p in enum representation from the stream \a s. |
| */ |
| QDataStream& operator>>(QDataStream &s, QVariant::Type &p) |
| { |
| quint32 u; |
| s >> u; |
| p = (QVariant::Type)u; |
| |
| return s; |
| } |
| |
| /*! |
| Writes a variant type \a p to the stream \a s. |
| */ |
| QDataStream& operator<<(QDataStream &s, const QVariant::Type p) |
| { |
| s << static_cast<quint32>(p); |
| |
| return s; |
| } |
| |
| #endif //QT_NO_DATASTREAM |
| |
| /*! |
| \fn bool QVariant::isValid() const |
| |
| Returns \c true if the storage type of this variant is not |
| QMetaType::UnknownType; otherwise returns \c false. |
| */ |
| |
| template <typename T> |
| inline T qVariantToHelper(const QVariant::Private &d, const HandlersManager &handlerManager) |
| { |
| const uint targetType = qMetaTypeId<T>(); |
| if (d.type == targetType) |
| return *v_cast<T>(&d); |
| |
| T ret; |
| if (d.type >= QMetaType::User || targetType >= QMetaType::User) { |
| const void * const from = constData(d); |
| if (QMetaType::convert(from, d.type, &ret, targetType)) |
| return ret; |
| } |
| |
| handlerManager[d.type]->convert(&d, targetType, &ret, nullptr); |
| return ret; |
| } |
| |
| /*! |
| \fn QStringList QVariant::toStringList() const |
| |
| Returns the variant as a QStringList if the variant has userType() |
| \l QMetaType::QStringList, \l QMetaType::QString, or |
| \l QMetaType::QVariantList of a type that can be converted to QString; |
| otherwise returns an empty list. |
| |
| \sa canConvert(int targetTypeId), convert() |
| */ |
| QStringList QVariant::toStringList() const |
| { |
| return qVariantToHelper<QStringList>(d, handlerManager); |
| } |
| |
| /*! |
| Returns the variant as a QString if the variant has a userType() |
| including, but not limited to: |
| |
| \l QMetaType::QString, \l QMetaType::Bool, \l QMetaType::QByteArray, |
| \l QMetaType::QChar, \l QMetaType::QDate, \l QMetaType::QDateTime, |
| \l QMetaType::Double, \l QMetaType::Int, \l QMetaType::LongLong, |
| \l QMetaType::QStringList, \l QMetaType::QTime, \l QMetaType::UInt, or |
| \l QMetaType::ULongLong. |
| |
| Calling QVariant::toString() on an unsupported variant returns an empty |
| string. |
| |
| \sa canConvert(int targetTypeId), convert() |
| */ |
| QString QVariant::toString() const |
| { |
| return qVariantToHelper<QString>(d, handlerManager); |
| } |
| |
| /*! |
| Returns the variant as a QMap<QString, QVariant> if the variant |
| has type() \l QMetaType::QVariantMap; otherwise returns an empty map. |
| |
| \sa canConvert(int targetTypeId), convert() |
| */ |
| QVariantMap QVariant::toMap() const |
| { |
| return qVariantToHelper<QVariantMap>(d, handlerManager); |
| } |
| |
| /*! |
| Returns the variant as a QHash<QString, QVariant> if the variant |
| has type() \l QMetaType::QVariantHash; otherwise returns an empty map. |
| |
| \sa canConvert(int targetTypeId), convert() |
| */ |
| QVariantHash QVariant::toHash() const |
| { |
| return qVariantToHelper<QVariantHash>(d, handlerManager); |
| } |
| |
| /*! |
| \fn QDate QVariant::toDate() const |
| |
| Returns the variant as a QDate if the variant has userType() |
| \l QMetaType::QDate, \l QMetaType::QDateTime, or \l QMetaType::QString; |
| otherwise returns an invalid date. |
| |
| If the type() is \l QMetaType::QString, an invalid date will be returned if |
| the string cannot be parsed as a Qt::ISODate format date. |
| |
| \sa canConvert(int targetTypeId), convert() |
| */ |
| QDate QVariant::toDate() const |
| { |
| return qVariantToHelper<QDate>(d, handlerManager); |
| } |
| |
| /*! |
| \fn QTime QVariant::toTime() const |
| |
| Returns the variant as a QTime if the variant has userType() |
| \l QMetaType::QTime, \l QMetaType::QDateTime, or \l QMetaType::QString; |
| otherwise returns an invalid time. |
| |
| If the type() is \l QMetaType::QString, an invalid time will be returned if |
| the string cannot be parsed as a Qt::ISODate format time. |
| |
| \sa canConvert(int targetTypeId), convert() |
| */ |
| QTime QVariant::toTime() const |
| { |
| return qVariantToHelper<QTime>(d, handlerManager); |
| } |
| |
| /*! |
| \fn QDateTime QVariant::toDateTime() const |
| |
| Returns the variant as a QDateTime if the variant has userType() |
| \l QMetaType::QDateTime, \l QMetaType::QDate, or \l QMetaType::QString; |
| otherwise returns an invalid date/time. |
| |
| If the type() is \l QMetaType::QString, an invalid date/time will be |
| returned if the string cannot be parsed as a Qt::ISODate format date/time. |
| |
| \sa canConvert(int targetTypeId), convert() |
| */ |
| QDateTime QVariant::toDateTime() const |
| { |
| return qVariantToHelper<QDateTime>(d, handlerManager); |
| } |
| |
| /*! |
| \since 4.7 |
| \fn QEasingCurve QVariant::toEasingCurve() const |
| |
| Returns the variant as a QEasingCurve if the variant has userType() |
| \l QMetaType::QEasingCurve; otherwise returns a default easing curve. |
| |
| \sa canConvert(int targetTypeId), convert() |
| */ |
| #if QT_CONFIG(easingcurve) |
| QEasingCurve QVariant::toEasingCurve() const |
| { |
| return qVariantToHelper<QEasingCurve>(d, handlerManager); |
| } |
| #endif |
| |
| /*! |
| \fn QByteArray QVariant::toByteArray() const |
| |
| Returns the variant as a QByteArray if the variant has userType() |
| \l QMetaType::QByteArray or \l QMetaType::QString (converted using |
| QString::fromUtf8()); otherwise returns an empty byte array. |
| |
| \sa canConvert(int targetTypeId), convert() |
| */ |
| QByteArray QVariant::toByteArray() const |
| { |
| return qVariantToHelper<QByteArray>(d, handlerManager); |
| } |
| |
| #ifndef QT_NO_GEOM_VARIANT |
| /*! |
| \fn QPoint QVariant::toPoint() const |
| |
| Returns the variant as a QPoint if the variant has userType() |
| \l QMetaType::QPoint or \l QMetaType::QPointF; otherwise returns a null |
| QPoint. |
| |
| \sa canConvert(int targetTypeId), convert() |
| */ |
| QPoint QVariant::toPoint() const |
| { |
| return qVariantToHelper<QPoint>(d, handlerManager); |
| } |
| |
| /*! |
| \fn QRect QVariant::toRect() const |
| |
| Returns the variant as a QRect if the variant has userType() |
| \l QMetaType::QRect; otherwise returns an invalid QRect. |
| |
| \sa canConvert(int targetTypeId), convert() |
| */ |
| QRect QVariant::toRect() const |
| { |
| return qVariantToHelper<QRect>(d, handlerManager); |
| } |
| |
| /*! |
| \fn QSize QVariant::toSize() const |
| |
| Returns the variant as a QSize if the variant has userType() |
| \l QMetaType::QSize; otherwise returns an invalid QSize. |
| |
| \sa canConvert(int targetTypeId), convert() |
| */ |
| QSize QVariant::toSize() const |
| { |
| return qVariantToHelper<QSize>(d, handlerManager); |
| } |
| |
| /*! |
| \fn QSizeF QVariant::toSizeF() const |
| |
| Returns the variant as a QSizeF if the variant has userType() \l |
| QMetaType::QSizeF; otherwise returns an invalid QSizeF. |
| |
| \sa canConvert(int targetTypeId), convert() |
| */ |
| QSizeF QVariant::toSizeF() const |
| { |
| return qVariantToHelper<QSizeF>(d, handlerManager); |
| } |
| |
| /*! |
| \fn QRectF QVariant::toRectF() const |
| |
| Returns the variant as a QRectF if the variant has userType() |
| \l QMetaType::QRect or \l QMetaType::QRectF; otherwise returns an invalid |
| QRectF. |
| |
| \sa canConvert(int targetTypeId), convert() |
| */ |
| QRectF QVariant::toRectF() const |
| { |
| return qVariantToHelper<QRectF>(d, handlerManager); |
| } |
| |
| /*! |
| \fn QLineF QVariant::toLineF() const |
| |
| Returns the variant as a QLineF if the variant has userType() |
| \l QMetaType::QLineF; otherwise returns an invalid QLineF. |
| |
| \sa canConvert(int targetTypeId), convert() |
| */ |
| QLineF QVariant::toLineF() const |
| { |
| return qVariantToHelper<QLineF>(d, handlerManager); |
| } |
| |
| /*! |
| \fn QLine QVariant::toLine() const |
| |
| Returns the variant as a QLine if the variant has userType() |
| \l QMetaType::QLine; otherwise returns an invalid QLine. |
| |
| \sa canConvert(int targetTypeId), convert() |
| */ |
| QLine QVariant::toLine() const |
| { |
| return qVariantToHelper<QLine>(d, handlerManager); |
| } |
| |
| /*! |
| \fn QPointF QVariant::toPointF() const |
| |
| Returns the variant as a QPointF if the variant has userType() \l |
| QMetaType::QPoint or \l QMetaType::QPointF; otherwise returns a null |
| QPointF. |
| |
| \sa canConvert(int targetTypeId), convert() |
| */ |
| QPointF QVariant::toPointF() const |
| { |
| return qVariantToHelper<QPointF>(d, handlerManager); |
| } |
| |
| #endif // QT_NO_GEOM_VARIANT |
| |
| #ifndef QT_BOOTSTRAPPED |
| /*! |
| \fn QUrl QVariant::toUrl() const |
| |
| Returns the variant as a QUrl if the variant has userType() |
| \l QMetaType::QUrl; otherwise returns an invalid QUrl. |
| |
| \sa canConvert(int targetTypeId), convert() |
| */ |
| QUrl QVariant::toUrl() const |
| { |
| return qVariantToHelper<QUrl>(d, handlerManager); |
| } |
| #endif |
| |
| /*! |
| \fn QLocale QVariant::toLocale() const |
| |
| Returns the variant as a QLocale if the variant has userType() |
| \l QMetaType::QLocale; otherwise returns an invalid QLocale. |
| |
| \sa canConvert(int targetTypeId), convert() |
| */ |
| QLocale QVariant::toLocale() const |
| { |
| return qVariantToHelper<QLocale>(d, handlerManager); |
| } |
| |
| /*! |
| \fn QRegExp QVariant::toRegExp() const |
| \since 4.1 |
| |
| Returns the variant as a QRegExp if the variant has userType() |
| \l QMetaType::QRegExp; otherwise returns an empty QRegExp. |
| |
| \sa canConvert(int targetTypeId), convert() |
| */ |
| #ifndef QT_NO_REGEXP |
| QRegExp QVariant::toRegExp() const |
| { |
| return qVariantToHelper<QRegExp>(d, handlerManager); |
| } |
| #endif |
| |
| #if QT_CONFIG(regularexpression) |
| /*! |
| \fn QRegularExpression QVariant::toRegularExpression() const |
| \since 5.0 |
| |
| Returns the variant as a QRegularExpression if the variant has userType() \l |
| QRegularExpression; otherwise returns an empty QRegularExpression. |
| |
| \sa canConvert(int targetTypeId), convert() |
| */ |
| QRegularExpression QVariant::toRegularExpression() const |
| { |
| return qVariantToHelper<QRegularExpression>(d, handlerManager); |
| } |
| #endif // QT_CONFIG(regularexpression) |
| |
| #if QT_CONFIG(itemmodel) |
| /*! |
| \since 5.0 |
| |
| Returns the variant as a QModelIndex if the variant has userType() \l |
| QModelIndex; otherwise returns a default constructed QModelIndex. |
| |
| \sa canConvert(int targetTypeId), convert(), toPersistentModelIndex() |
| */ |
| QModelIndex QVariant::toModelIndex() const |
| { |
| return qVariantToHelper<QModelIndex>(d, handlerManager); |
| } |
| |
| /*! |
| \since 5.5 |
| |
| Returns the variant as a QPersistentModelIndex if the variant has userType() \l |
| QPersistentModelIndex; otherwise returns a default constructed QPersistentModelIndex. |
| |
| \sa canConvert(int targetTypeId), convert(), toModelIndex() |
| */ |
| QPersistentModelIndex QVariant::toPersistentModelIndex() const |
| { |
| return qVariantToHelper<QPersistentModelIndex>(d, handlerManager); |
| } |
| #endif // QT_CONFIG(itemmodel) |
| |
| #ifndef QT_BOOTSTRAPPED |
| /*! |
| \since 5.0 |
| |
| Returns the variant as a QUuid if the variant has type() |
| \l QMetaType::QUuid, \l QMetaType::QByteArray or \l QMetaType::QString; |
| otherwise returns a default-constructed QUuid. |
| |
| \sa canConvert(int targetTypeId), convert() |
| */ |
| QUuid QVariant::toUuid() const |
| { |
| return qVariantToHelper<QUuid>(d, handlerManager); |
| } |
| |
| /*! |
| \since 5.0 |
| |
| Returns the variant as a QJsonValue if the variant has userType() \l |
| QJsonValue; otherwise returns a default constructed QJsonValue. |
| |
| \sa canConvert(int targetTypeId), convert() |
| */ |
| QJsonValue QVariant::toJsonValue() const |
| { |
| return qVariantToHelper<QJsonValue>(d, handlerManager); |
| } |
| |
| /*! |
| \since 5.0 |
| |
| Returns the variant as a QJsonObject if the variant has userType() \l |
| QJsonObject; otherwise returns a default constructed QJsonObject. |
| |
| \sa canConvert(int targetTypeId), convert() |
| */ |
| QJsonObject QVariant::toJsonObject() const |
| { |
| return qVariantToHelper<QJsonObject>(d, handlerManager); |
| } |
| |
| /*! |
| \since 5.0 |
| |
| Returns the variant as a QJsonArray if the variant has userType() \l |
| QJsonArray; otherwise returns a default constructed QJsonArray. |
| |
| \sa canConvert(int targetTypeId), convert() |
| */ |
| QJsonArray QVariant::toJsonArray() const |
| { |
| return qVariantToHelper<QJsonArray>(d, handlerManager); |
| } |
| |
| /*! |
| \since 5.0 |
| |
| Returns the variant as a QJsonDocument if the variant has userType() \l |
| QJsonDocument; otherwise returns a default constructed QJsonDocument. |
| |
| \sa canConvert(int targetTypeId), convert() |
| */ |
| QJsonDocument QVariant::toJsonDocument() const |
| { |
| return qVariantToHelper<QJsonDocument>(d, handlerManager); |
| } |
| #endif // QT_BOOTSTRAPPED |
| |
| /*! |
| \fn QChar QVariant::toChar() const |
| |
| Returns the variant as a QChar if the variant has userType() |
| \l QMetaType::QChar, \l QMetaType::Int, or \l QMetaType::UInt; otherwise |
| returns an invalid QChar. |
| |
| \sa canConvert(int targetTypeId), convert() |
| */ |
| QChar QVariant::toChar() const |
| { |
| return qVariantToHelper<QChar>(d, handlerManager); |
| } |
| |
| /*! |
| Returns the variant as a QBitArray if the variant has userType() |
| \l QMetaType::QBitArray; otherwise returns an empty bit array. |
| |
| \sa canConvert(int targetTypeId), convert() |
| */ |
| QBitArray QVariant::toBitArray() const |
| { |
| return qVariantToHelper<QBitArray>(d, handlerManager); |
| } |
| |
| template <typename T> |
| inline T qNumVariantToHelper(const QVariant::Private &d, |
| const HandlersManager &handlerManager, bool *ok, const T& val) |
| { |
| const uint t = qMetaTypeId<T>(); |
| if (ok) |
| *ok = true; |
| |
| if (d.type == t) |
| return val; |
| |
| T ret = 0; |
| if ((d.type >= QMetaType::User || t >= QMetaType::User) |
| && QMetaType::convert(constData(d), d.type, &ret, t)) |
| return ret; |
| |
| if (!handlerManager[d.type]->convert(&d, t, &ret, ok) && ok) |
| *ok = false; |
| return ret; |
| } |
| |
| /*! |
| Returns the variant as an int if the variant has userType() |
| \l QMetaType::Int, \l QMetaType::Bool, \l QMetaType::QByteArray, |
| \l QMetaType::QChar, \l QMetaType::Double, \l QMetaType::LongLong, |
| \l QMetaType::QString, \l QMetaType::UInt, or \l QMetaType::ULongLong; |
| otherwise returns 0. |
| |
| If \a ok is non-null: \c{*}\a{ok} is set to true if the value could be |
| converted to an int; otherwise \c{*}\a{ok} is set to false. |
| |
| \b{Warning:} If the value is convertible to a \l QMetaType::LongLong but is |
| too large to be represented in an int, the resulting arithmetic overflow |
| will not be reflected in \a ok. A simple workaround is to use |
| QString::toInt(). |
| |
| \sa canConvert(int targetTypeId), convert() |
| */ |
| int QVariant::toInt(bool *ok) const |
| { |
| return qNumVariantToHelper<int>(d, handlerManager, ok, d.data.i); |
| } |
| |
| /*! |
| Returns the variant as an unsigned int if the variant has userType() |
| \l QMetaType::UInt, \l QMetaType::Bool, \l QMetaType::QByteArray, |
| \l QMetaType::QChar, \l QMetaType::Double, \l QMetaType::Int, |
| \l QMetaType::LongLong, \l QMetaType::QString, or \l QMetaType::ULongLong; |
| otherwise returns 0. |
| |
| If \a ok is non-null: \c{*}\a{ok} is set to true if the value could be |
| converted to an unsigned int; otherwise \c{*}\a{ok} is set to false. |
| |
| \b{Warning:} If the value is convertible to a \l QMetaType::ULongLong but is |
| too large to be represented in an unsigned int, the resulting arithmetic |
| overflow will not be reflected in \a ok. A simple workaround is to use |
| QString::toUInt(). |
| |
| \sa canConvert(int targetTypeId), convert() |
| */ |
| uint QVariant::toUInt(bool *ok) const |
| { |
| return qNumVariantToHelper<uint>(d, handlerManager, ok, d.data.u); |
| } |
| |
| /*! |
| Returns the variant as a long long int if the variant has userType() |
| \l QMetaType::LongLong, \l QMetaType::Bool, \l QMetaType::QByteArray, |
| \l QMetaType::QChar, \l QMetaType::Double, \l QMetaType::Int, |
| \l QMetaType::QString, \l QMetaType::UInt, or \l QMetaType::ULongLong; |
| otherwise returns 0. |
| |
| If \a ok is non-null: \c{*}\c{ok} is set to true if the value could be |
| converted to an int; otherwise \c{*}\c{ok} is set to false. |
| |
| \sa canConvert(int targetTypeId), convert() |
| */ |
| qlonglong QVariant::toLongLong(bool *ok) const |
| { |
| return qNumVariantToHelper<qlonglong>(d, handlerManager, ok, d.data.ll); |
| } |
| |
| /*! |
| Returns the variant as an unsigned long long int if the |
| variant has type() \l QMetaType::ULongLong, \l QMetaType::Bool, |
| \l QMetaType::QByteArray, \l QMetaType::QChar, \l QMetaType::Double, |
| \l QMetaType::Int, \l QMetaType::LongLong, \l QMetaType::QString, or |
| \l QMetaType::UInt; otherwise returns 0. |
| |
| If \a ok is non-null: \c{*}\a{ok} is set to true if the value could be |
| converted to an int; otherwise \c{*}\a{ok} is set to false. |
| |
| \sa canConvert(int targetTypeId), convert() |
| */ |
| qulonglong QVariant::toULongLong(bool *ok) const |
| { |
| return qNumVariantToHelper<qulonglong>(d, handlerManager, ok, d.data.ull); |
| } |
| |
| /*! |
| Returns the variant as a bool if the variant has userType() Bool. |
| |
| Returns \c true if the variant has userType() \l QMetaType::Bool, |
| \l QMetaType::QChar, \l QMetaType::Double, \l QMetaType::Int, |
| \l QMetaType::LongLong, \l QMetaType::UInt, or \l QMetaType::ULongLong and |
| the value is non-zero, or if the variant has type \l QMetaType::QString or |
| \l QMetaType::QByteArray and its lower-case content is not one of the |
| following: empty, "0" or "false"; otherwise returns \c false. |
| |
| \sa canConvert(int targetTypeId), convert() |
| */ |
| bool QVariant::toBool() const |
| { |
| if (d.type == Bool) |
| return d.data.b; |
| |
| bool res = false; |
| handlerManager[d.type]->convert(&d, Bool, &res, nullptr); |
| |
| return res; |
| } |
| |
| /*! |
| Returns the variant as a double if the variant has userType() |
| \l QMetaType::Double, \l QMetaType::Float, \l QMetaType::Bool, |
| \l QMetaType::QByteArray, \l QMetaType::Int, \l QMetaType::LongLong, |
| \l QMetaType::QString, \l QMetaType::UInt, or \l QMetaType::ULongLong; |
| otherwise returns 0.0. |
| |
| If \a ok is non-null: \c{*}\a{ok} is set to true if the value could be |
| converted to a double; otherwise \c{*}\a{ok} is set to false. |
| |
| \sa canConvert(int targetTypeId), convert() |
| */ |
| double QVariant::toDouble(bool *ok) const |
| { |
| return qNumVariantToHelper<double>(d, handlerManager, ok, d.data.d); |
| } |
| |
| /*! |
| Returns the variant as a float if the variant has userType() |
| \l QMetaType::Double, \l QMetaType::Float, \l QMetaType::Bool, |
| \l QMetaType::QByteArray, \l QMetaType::Int, \l QMetaType::LongLong, |
| \l QMetaType::QString, \l QMetaType::UInt, or \l QMetaType::ULongLong; |
| otherwise returns 0.0. |
| |
| \since 4.6 |
| |
| If \a ok is non-null: \c{*}\a{ok} is set to true if the value could be |
| converted to a double; otherwise \c{*}\a{ok} is set to false. |
| |
| \sa canConvert(int targetTypeId), convert() |
| */ |
| float QVariant::toFloat(bool *ok) const |
| { |
| return qNumVariantToHelper<float>(d, handlerManager, ok, d.data.f); |
| } |
| |
| /*! |
| Returns the variant as a qreal if the variant has userType() |
| \l QMetaType::Double, \l QMetaType::Float, \l QMetaType::Bool, |
| \l QMetaType::QByteArray, \l QMetaType::Int, \l QMetaType::LongLong, |
| \l QMetaType::QString, \l QMetaType::UInt, or \l QMetaType::ULongLong; |
| otherwise returns 0.0. |
| |
| \since 4.6 |
| |
| If \a ok is non-null: \c{*}\a{ok} is set to true if the value could be |
| converted to a double; otherwise \c{*}\a{ok} is set to false. |
| |
| \sa canConvert(int targetTypeId), convert() |
| */ |
| qreal QVariant::toReal(bool *ok) const |
| { |
| return qNumVariantToHelper<qreal>(d, handlerManager, ok, d.data.real); |
| } |
| |
| /*! |
| Returns the variant as a QVariantList if the variant has userType() |
| \l QMetaType::QVariantList or \l QMetaType::QStringList; otherwise returns |
| an empty list. |
| |
| \sa canConvert(int targetTypeId), convert() |
| */ |
| QVariantList QVariant::toList() const |
| { |
| return qVariantToHelper<QVariantList>(d, handlerManager); |
| } |
| |
| |
| static const quint32 qCanConvertMatrix[QVariant::LastCoreType + 1] = |
| { |
| /*Invalid*/ 0, |
| |
| /*Bool*/ 1 << QVariant::Double | 1 << QVariant::Int | 1 << QVariant::UInt |
| | 1 << QVariant::LongLong | 1 << QVariant::ULongLong | 1 << QVariant::ByteArray |
| | 1 << QVariant::String | 1 << QVariant::Char, |
| |
| /*Int*/ 1 << QVariant::UInt | 1 << QVariant::String | 1 << QVariant::Double |
| | 1 << QVariant::Bool | 1 << QVariant::LongLong | 1 << QVariant::ULongLong |
| | 1 << QVariant::Char | 1 << QVariant::ByteArray | 1 << QVariant::Int, |
| |
| /*UInt*/ 1 << QVariant::Int | 1 << QVariant::String | 1 << QVariant::Double |
| | 1 << QVariant::Bool | 1 << QVariant::LongLong | 1 << QVariant::ULongLong |
| | 1 << QVariant::Char | 1 << QVariant::ByteArray, |
| |
| /*LLong*/ 1 << QVariant::Int | 1 << QVariant::String | 1 << QVariant::Double |
| | 1 << QVariant::Bool | 1 << QVariant::UInt | 1 << QVariant::ULongLong |
| | 1 << QVariant::Char | 1 << QVariant::ByteArray, |
| |
| /*ULlong*/ 1 << QVariant::Int | 1 << QVariant::String | 1 << QVariant::Double |
| | 1 << QVariant::Bool | 1 << QVariant::UInt | 1 << QVariant::LongLong |
| | 1 << QVariant::Char | 1 << QVariant::ByteArray, |
| |
| /*double*/ 1 << QVariant::Int | 1 << QVariant::String | 1 << QVariant::ULongLong |
| | 1 << QVariant::Bool | 1 << QVariant::UInt | 1 << QVariant::LongLong |
| | 1 << QVariant::ByteArray, |
| |
| /*QChar*/ 1 << QVariant::Int | 1 << QVariant::UInt | 1 << QVariant::LongLong |
| | 1 << QVariant::ULongLong, |
| |
| /*QMap*/ 0, |
| |
| /*QList*/ 1 << QVariant::StringList, |
| |
| /*QString*/ 1 << QVariant::StringList | 1 << QVariant::ByteArray | 1 << QVariant::Int |
| | 1 << QVariant::UInt | 1 << QVariant::Bool | 1 << QVariant::Double |
| | 1 << QVariant::Date | 1 << QVariant::Time | 1 << QVariant::DateTime |
| | 1 << QVariant::LongLong | 1 << QVariant::ULongLong | 1 << QVariant::Char |
| | 1 << QVariant::Url | 1 << QVariant::Uuid, |
| |
| /*QStringList*/ 1 << QVariant::List | 1 << QVariant::String, |
| |
| /*QByteArray*/ 1 << QVariant::String | 1 << QVariant::Int | 1 << QVariant::UInt | 1 << QVariant::Bool |
| | 1 << QVariant::Double | 1 << QVariant::LongLong | 1 << QVariant::ULongLong |
| | 1 << QVariant::Uuid, |
| |
| /*QBitArray*/ 0, |
| |
| /*QDate*/ 1 << QVariant::String | 1 << QVariant::DateTime, |
| |
| /*QTime*/ 1 << QVariant::String | 1 << QVariant::DateTime, |
| |
| /*QDateTime*/ 1 << QVariant::String | 1 << QVariant::Date, |
| |
| /*QUrl*/ 1 << QVariant::String, |
| |
| /*QLocale*/ 0, |
| |
| /*QRect*/ 1 << QVariant::RectF, |
| |
| /*QRectF*/ 1 << QVariant::Rect, |
| |
| /*QSize*/ 1 << QVariant::SizeF, |
| |
| /*QSizeF*/ 1 << QVariant::Size, |
| |
| /*QLine*/ 1 << QVariant::LineF, |
| |
| /*QLineF*/ 1 << QVariant::Line, |
| |
| /*QPoint*/ 1 << QVariant::PointF, |
| |
| /*QPointF*/ 1 << QVariant::Point, |
| |
| /*QRegExp*/ 0, |
| |
| /*QHash*/ 0, |
| |
| /*QEasingCurve*/ 0, |
| |
| /*QUuid*/ 1 << QVariant::String | 1 << QVariant::ByteArray, |
| }; |
| static const size_t qCanConvertMatrixMaximumTargetType = 8 * sizeof(*qCanConvertMatrix); |
| |
| #ifndef QT_BOOTSTRAPPED |
| /* |
| Returns \c true if from inherits to. |
| */ |
| static bool canConvertMetaObject(const QMetaObject *from, const QMetaObject *to) |
| { |
| if (from && to == &QObject::staticMetaObject) |
| return true; |
| |
| while (from) { |
| if (from == to) |
| return true; |
| from = from->superClass(); |
| } |
| |
| return false; |
| } |
| #endif |
| |
| static bool canConvertMetaObject(int fromId, int toId, QObject *fromObject) |
| { |
| #ifndef QT_BOOTSTRAPPED |
| QMetaType toType(toId); |
| if ((QMetaType::typeFlags(fromId) & QMetaType::PointerToQObject) && (toType.flags() & QMetaType::PointerToQObject)) { |
| if (!fromObject) |
| return true; |
| return canConvertMetaObject(fromObject->metaObject(), toType.metaObject()); |
| } |
| #else |
| Q_UNUSED(fromId); |
| Q_UNUSED(toId); |
| Q_UNUSED(fromObject); |
| #endif |
| return false; |
| } |
| |
| |
| /*! |
| Returns \c true if the variant's type can be cast to the requested |
| type, \a targetTypeId. Such casting is done automatically when calling the |
| toInt(), toBool(), ... methods. |
| |
| The following casts are done automatically: |
| |
| \table |
| \header \li Type \li Automatically Cast To |
| \row \li \l QMetaType::Bool \li \l QMetaType::QChar, \l QMetaType::Double, |
| \l QMetaType::Int, \l QMetaType::LongLong, \l QMetaType::QString, |
| \l QMetaType::UInt, \l QMetaType::ULongLong |
| \row \li \l QMetaType::QByteArray \li \l QMetaType::Double, |
| \l QMetaType::Int, \l QMetaType::LongLong, \l QMetaType::QString, |
| \l QMetaType::UInt, \l QMetaType::ULongLong, \l QMetaType::QUuid |
| \row \li \l QMetaType::QChar \li \l QMetaType::Bool, \l QMetaType::Int, |
| \l QMetaType::UInt, \l QMetaType::LongLong, \l QMetaType::ULongLong |
| \row \li \l QMetaType::QColor \li \l QMetaType::QString |
| \row \li \l QMetaType::QDate \li \l QMetaType::QDateTime, |
| \l QMetaType::QString |
| \row \li \l QMetaType::QDateTime \li \l QMetaType::QDate, |
| \l QMetaType::QString, \l QMetaType::QTime |
| \row \li \l QMetaType::Double \li \l QMetaType::Bool, \l QMetaType::Int, |
| \l QMetaType::LongLong, \l QMetaType::QString, \l QMetaType::UInt, |
| \l QMetaType::ULongLong |
| \row \li \l QMetaType::QFont \li \l QMetaType::QString |
| \row \li \l QMetaType::Int \li \l QMetaType::Bool, \l QMetaType::QChar, |
| \l QMetaType::Double, \l QMetaType::LongLong, \l QMetaType::QString, |
| \l QMetaType::UInt, \l QMetaType::ULongLong |
| \row \li \l QMetaType::QKeySequence \li \l QMetaType::Int, |
| \l QMetaType::QString |
| \row \li \l QMetaType::QVariantList \li \l QMetaType::QStringList (if the |
| list's items can be converted to QStrings) |
| \row \li \l QMetaType::LongLong \li \l QMetaType::Bool, |
| \l QMetaType::QByteArray, \l QMetaType::QChar, \l QMetaType::Double, |
| \l QMetaType::Int, \l QMetaType::QString, \l QMetaType::UInt, |
| \l QMetaType::ULongLong |
| \row \li \l QMetaType::QPoint \li QMetaType::QPointF |
| \row \li \l QMetaType::QRect \li QMetaType::QRectF |
| \row \li \l QMetaType::QString \li \l QMetaType::Bool, |
| \l QMetaType::QByteArray, \l QMetaType::QChar, \l QMetaType::QColor, |
| \l QMetaType::QDate, \l QMetaType::QDateTime, \l QMetaType::Double, |
| \l QMetaType::QFont, \l QMetaType::Int, \l QMetaType::QKeySequence, |
| \l QMetaType::LongLong, \l QMetaType::QStringList, \l QMetaType::QTime, |
| \l QMetaType::UInt, \l QMetaType::ULongLong, \l QMetaType::QUuid |
| \row \li \l QMetaType::QStringList \li \l QMetaType::QVariantList, |
| \l QMetaType::QString (if the list contains exactly one item) |
| \row \li \l QMetaType::QTime \li \l QMetaType::QString |
| \row \li \l QMetaType::UInt \li \l QMetaType::Bool, \l QMetaType::QChar, |
| \l QMetaType::Double, \l QMetaType::Int, \l QMetaType::LongLong, |
| \l QMetaType::QString, \l QMetaType::ULongLong |
| \row \li \l QMetaType::ULongLong \li \l QMetaType::Bool, |
| \l QMetaType::QChar, \l QMetaType::Double, \l QMetaType::Int, |
| \l QMetaType::LongLong, \l QMetaType::QString, \l QMetaType::UInt |
| \row \li \l QMetaType::QUuid \li \l QMetaType::QByteArray, \l QMetaType::QString |
| \endtable |
| |
| A QVariant containing a pointer to a type derived from QObject will also return true for this |
| function if a qobject_cast to the type described by \a targetTypeId would succeed. Note that |
| this only works for QObject subclasses which use the Q_OBJECT macro. |
| |
| A QVariant containing a sequential container will also return true for this |
| function if the \a targetTypeId is QVariantList. It is possible to iterate over |
| the contents of the container without extracting it as a (copied) QVariantList: |
| |
| \snippet code/src_corelib_kernel_qvariant.cpp 9 |
| |
| This requires that the value_type of the container is itself a metatype. |
| |
| Similarly, a QVariant containing a sequential container will also return true for this |
| function the \a targetTypeId is QVariantHash or QVariantMap. It is possible to iterate over |
| the contents of the container without extracting it as a (copied) QVariantHash or QVariantMap: |
| |
| \snippet code/src_corelib_kernel_qvariant.cpp 10 |
| |
| \sa convert(), QSequentialIterable, Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE(), QAssociativeIterable, |
| Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE() |
| */ |
| bool QVariant::canConvert(int targetTypeId) const |
| { |
| if (d.type == targetTypeId) |
| return true; |
| |
| #if QT_CONFIG(itemmodel) |
| if ((targetTypeId == QMetaType::QModelIndex && d.type == QMetaType::QPersistentModelIndex) |
| || (targetTypeId == QMetaType::QPersistentModelIndex && d.type == QMetaType::QModelIndex)) |
| return true; |
| #endif |
| |
| if (targetTypeId == QMetaType::QVariantList |
| && (d.type == QMetaType::QVariantList |
| || d.type == QMetaType::QStringList |
| || d.type == QMetaType::QByteArrayList |
| || QMetaType::hasRegisteredConverterFunction(d.type, |
| qMetaTypeId<QtMetaTypePrivate::QSequentialIterableImpl>()))) { |
| return true; |
| } |
| |
| if ((targetTypeId == QMetaType::QVariantHash || targetTypeId == QMetaType::QVariantMap) |
| && (d.type == QMetaType::QVariantMap |
| || d.type == QMetaType::QVariantHash |
| || QMetaType::hasRegisteredConverterFunction(d.type, |
| qMetaTypeId<QtMetaTypePrivate::QAssociativeIterableImpl>()))) { |
| return true; |
| } |
| |
| if (targetTypeId == qMetaTypeId<QPair<QVariant, QVariant> >() && |
| QMetaType::hasRegisteredConverterFunction(d.type, |
| qMetaTypeId<QtMetaTypePrivate::QPairVariantInterfaceImpl>())) { |
| return true; |
| } |
| |
| if ((d.type >= QMetaType::User || targetTypeId >= QMetaType::User) |
| && QMetaType::hasRegisteredConverterFunction(d.type, targetTypeId)) { |
| return true; |
| } |
| |
| // TODO Reimplement this function, currently it works but it is a historical mess. |
| uint currentType = d.type; |
| if (currentType == QMetaType::SChar || currentType == QMetaType::Char) |
| currentType = QMetaType::UInt; |
| if (targetTypeId == QMetaType::SChar || currentType == QMetaType::Char) |
| targetTypeId = QMetaType::UInt; |
| if (currentType == QMetaType::Short || currentType == QMetaType::UShort) |
| currentType = QMetaType::Int; |
| if (targetTypeId == QMetaType::Short || currentType == QMetaType::UShort) |
| targetTypeId = QMetaType::Int; |
| if (currentType == QMetaType::Float) |
| currentType = QMetaType::Double; |
| if (targetTypeId == QMetaType::Float) |
| targetTypeId = QMetaType::Double; |
| |
| if (currentType == uint(targetTypeId)) |
| return true; |
| |
| if (targetTypeId < 0) |
| return false; |
| if (targetTypeId >= QMetaType::User) { |
| if (QMetaType::typeFlags(targetTypeId) & QMetaType::IsEnumeration) { |
| targetTypeId = QMetaType::Int; |
| } else { |
| return canConvertMetaObject(currentType, targetTypeId, d.data.o); |
| } |
| } |
| |
| if (currentType == QMetaType::QJsonValue || targetTypeId == QMetaType::QJsonValue) { |
| switch (currentType == QMetaType::QJsonValue ? targetTypeId : currentType) { |
| case QMetaType::Nullptr: |
| case QMetaType::QString: |
| case QMetaType::Bool: |
| case QMetaType::Int: |
| case QMetaType::UInt: |
| case QMetaType::Double: |
| case QMetaType::Float: |
| case QMetaType::ULong: |
| case QMetaType::Long: |
| case QMetaType::LongLong: |
| case QMetaType::ULongLong: |
| case QMetaType::UShort: |
| case QMetaType::UChar: |
| case QMetaType::Char: |
| case QMetaType::SChar: |
| case QMetaType::Short: |
| case QMetaType::QVariantList: |
| case QMetaType::QVariantMap: |
| case QMetaType::QVariantHash: |
| case QMetaType::QCborValue: |
| case QMetaType::QCborArray: |
| case QMetaType::QCborMap: |
| return true; |
| default: |
| return false; |
| } |
| } |
| if (currentType == QMetaType::QJsonArray) |
| return targetTypeId == QMetaType::QVariantList || targetTypeId == QMetaType::QCborValue |
| || targetTypeId == QMetaType::QCborArray; |
| if (currentType == QMetaType::QJsonObject) |
| return targetTypeId == QMetaType::QVariantMap || targetTypeId == QMetaType::QVariantHash |
| || targetTypeId == QMetaType::QCborValue || targetTypeId == QMetaType::QCborMap; |
| |
| if (currentType == QMetaType::QCborValue || targetTypeId == QMetaType::QCborValue) { |
| switch (currentType == QMetaType::QCborValue ? targetTypeId : currentType) { |
| case QMetaType::UnknownType: |
| case QMetaType::Nullptr: |
| case QMetaType::Bool: |
| case QMetaType::Int: |
| case QMetaType::UInt: |
| case QMetaType::Double: |
| case QMetaType::Float: |
| case QMetaType::ULong: |
| case QMetaType::Long: |
| case QMetaType::LongLong: |
| case QMetaType::ULongLong: |
| case QMetaType::UShort: |
| case QMetaType::UChar: |
| case QMetaType::Char: |
| case QMetaType::SChar: |
| case QMetaType::Short: |
| case QMetaType::QString: |
| case QMetaType::QByteArray: |
| case QMetaType::QDateTime: |
| case QMetaType::QUrl: |
| case QMetaType::QRegularExpression: |
| case QMetaType::QUuid: |
| case QMetaType::QVariantList: |
| case QMetaType::QVariantMap: |
| case QMetaType::QVariantHash: |
| case QMetaType::QJsonValue: |
| case QMetaType::QJsonArray: |
| case QMetaType::QJsonObject: |
| case QMetaType::QJsonDocument: |
| case QMetaType::QCborArray: |
| case QMetaType::QCborMap: |
| case QMetaType::QCborSimpleType: |
| return true; |
| default: |
| return false; |
| } |
| } |
| if (currentType == QMetaType::QCborArray) |
| return targetTypeId == QMetaType::QVariantList || targetTypeId == QMetaType::QCborValue |
| || targetTypeId == QMetaType::QJsonArray; |
| if (currentType == QMetaType::QCborMap) |
| return targetTypeId == QMetaType::QVariantMap || targetTypeId == QMetaType::QVariantHash |
| || targetTypeId == QMetaType::QCborValue || targetTypeId == QMetaType::QJsonObject; |
| |
| // FIXME It should be LastCoreType intead of Uuid |
| if (currentType > int(QMetaType::QUuid) || targetTypeId > int(QMetaType::QUuid)) { |
| switch (uint(targetTypeId)) { |
| case QVariant::Int: |
| if (currentType == QVariant::KeySequence) |
| return true; |
| Q_FALLTHROUGH(); |
| case QVariant::UInt: |
| case QVariant::LongLong: |
| case QVariant::ULongLong: |
| return currentType == QMetaType::ULong |
| || currentType == QMetaType::Long |
| || currentType == QMetaType::UShort |
| || currentType == QMetaType::UChar |
| || currentType == QMetaType::Char |
| || currentType == QMetaType::SChar |
| || currentType == QMetaType::Short |
| || QMetaType::typeFlags(currentType) & QMetaType::IsEnumeration; |
| case QVariant::Image: |
| return currentType == QVariant::Pixmap || currentType == QVariant::Bitmap; |
| case QVariant::Pixmap: |
| return currentType == QVariant::Image || currentType == QVariant::Bitmap |
| || currentType == QVariant::Brush; |
| case QVariant::Bitmap: |
| return currentType == QVariant::Pixmap || currentType == QVariant::Image; |
| case QVariant::ByteArray: |
| return currentType == QVariant::Color || currentType == QMetaType::Nullptr |
| || ((QMetaType::typeFlags(currentType) & QMetaType::IsEnumeration) && QMetaType::metaObjectForType(currentType)); |
| case QVariant::String: |
| return currentType == QVariant::KeySequence || currentType == QVariant::Font |
| || currentType == QVariant::Color || currentType == QMetaType::Nullptr |
| || ((QMetaType::typeFlags(currentType) & QMetaType::IsEnumeration) && QMetaType::metaObjectForType(currentType)); |
| case QVariant::KeySequence: |
| return currentType == QVariant::String || currentType == QVariant::Int; |
| case QVariant::Font: |
| return currentType == QVariant::String; |
| case QVariant::Color: |
| return currentType == QVariant::String || currentType == QVariant::ByteArray |
| || currentType == QVariant::Brush; |
| case QVariant::Brush: |
| return currentType == QVariant::Color || currentType == QVariant::Pixmap; |
| case QMetaType::Long: |
| case QMetaType::Char: |
| case QMetaType::SChar: |
| case QMetaType::UChar: |
| case QMetaType::ULong: |
| case QMetaType::Short: |
| case QMetaType::UShort: |
| return currentType == QVariant::Int |
| || (currentType < qCanConvertMatrixMaximumTargetType |
| && qCanConvertMatrix[QVariant::Int] & (1U << currentType)) |
| || QMetaType::typeFlags(currentType) & QMetaType::IsEnumeration; |
| case QMetaType::QObjectStar: |
| return canConvertMetaObject(currentType, targetTypeId, d.data.o); |
| default: |
| return false; |
| } |
| } |
| |
| if (targetTypeId == String && currentType == StringList) |
| return v_cast<QStringList>(&d)->count() == 1; |
| return currentType < qCanConvertMatrixMaximumTargetType |
| && qCanConvertMatrix[targetTypeId] & (1U << currentType); |
| } |
| |
| /*! |
| Casts the variant to the requested type, \a targetTypeId. If the cast cannot be |
| done, the variant is still changed to the requested type, but is left in a cleared |
| null state similar to that constructed by QVariant(Type). |
| |
| Returns \c true if the current type of the variant was successfully cast; |
| otherwise returns \c false. |
| |
| A QVariant containing a pointer to a type derived from QObject will also convert |
| and return true for this function if a qobject_cast to the type described |
| by \a targetTypeId would succeed. Note that this only works for QObject subclasses |
| which use the Q_OBJECT macro. |
| |
| \note converting QVariants that are null due to not being initialized or having |
| failed a previous conversion will always fail, changing the type, remaining null, |
| and returning \c false. |
| |
| \sa canConvert(int targetTypeId), clear() |
| */ |
| |
| bool QVariant::convert(int targetTypeId) |
| { |
| if (d.type == uint(targetTypeId)) |
| return true; |
| |
| QVariant oldValue = *this; |
| |
| clear(); |
| if (!oldValue.canConvert(targetTypeId)) |
| return false; |
| |
| create(targetTypeId, nullptr); |
| // Fail if the value is not initialized or was forced null by a previous failed convert. |
| if (oldValue.d.is_null && oldValue.d.type != QMetaType::Nullptr) |
| return false; |
| |
| if ((QMetaType::typeFlags(oldValue.userType()) & QMetaType::PointerToQObject) && (QMetaType::typeFlags(targetTypeId) & QMetaType::PointerToQObject)) { |
| create(targetTypeId, &oldValue.d.data.o); |
| return true; |
| } |
| |
| bool isOk = true; |
| int converterType = std::max(oldValue.userType(), targetTypeId); |
| if (!handlerManager[converterType]->convert(&oldValue.d, targetTypeId, data(), &isOk)) |
| isOk = false; |
| d.is_null = !isOk; |
| return isOk; |
| } |
| |
| /*! |
| \fn bool QVariant::convert(const int type, void *ptr) const |
| \internal |
| Created for qvariant_cast() usage |
| */ |
| bool QVariant::convert(const int type, void *ptr) const |
| { |
| return handlerManager[type]->convert(&d, type, ptr, nullptr); |
| } |
| |
| |
| /*! |
| \fn bool operator==(const QVariant &v1, const QVariant &v2) |
| |
| \relates QVariant |
| |
| Returns \c true if \a v1 and \a v2 are equal; otherwise returns \c false. |
| |
| If \a v1 and \a v2 have the same \l{QVariant::}{type()}, the |
| type's equality operator is used for comparison. If not, it is |
| attempted to \l{QVariant::}{convert()} \a v2 to the same type as |
| \a v1. See \l{QVariant::}{canConvert()} for a list of possible |
| conversions. |
| |
| The result of the function is not affected by the result of QVariant::isNull, |
| which means that two values can be equal even if one of them is null and |
| another is not. |
| |
| \warning To make this function work with a custom type registered with |
| qRegisterMetaType(), its comparison operator must be registered using |
| QMetaType::registerComparators(). |
| */ |
| /*! |
| \fn bool operator!=(const QVariant &v1, const QVariant &v2) |
| |
| \relates QVariant |
| |
| Returns \c false if \a v1 and \a v2 are equal; otherwise returns \c true. |
| |
| \warning To make this function work with a custom type registered with |
| qRegisterMetaType(), its comparison operator must be registered using |
| QMetaType::registerComparators(). |
| */ |
| |
| /*! \fn bool QVariant::operator==(const QVariant &v) const |
| |
| Compares this QVariant with \a v and returns \c true if they are |
| equal; otherwise returns \c false. |
| |
| QVariant uses the equality operator of the type() it contains to |
| check for equality. QVariant will try to convert() \a v if its |
| type is not the same as this variant's type. See canConvert() for |
| a list of possible conversions. |
| |
| \warning To make this function work with a custom type registered with |
| qRegisterMetaType(), its comparison operator must be registered using |
| QMetaType::registerComparators(). |
| */ |
| |
| /*! |
| \fn bool QVariant::operator!=(const QVariant &v) const |
| |
| Compares this QVariant with \a v and returns \c true if they are not |
| equal; otherwise returns \c false. |
| |
| \warning To make this function work with a custom type registered with |
| qRegisterMetaType(), its comparison operator must be registered using |
| QMetaType::registerComparators(). |
| */ |
| |
| /*! |
| \fn bool QVariant::operator<(const QVariant &v) const |
| |
| Compares this QVariant with \a v and returns \c true if this is less than \a v. |
| |
| \note Comparability might not be availabe for the type stored in this QVariant |
| or in \a v. |
| |
| \warning To make this function work with a custom type registered with |
| qRegisterMetaType(), its comparison operator must be registered using |
| QMetaType::registerComparators(). |
| */ |
| |
| /*! |
| \fn bool QVariant::operator<=(const QVariant &v) const |
| |
| Compares this QVariant with \a v and returns \c true if this is less or equal than \a v. |
| |
| \note Comparability might not be available for the type stored in this QVariant |
| or in \a v. |
| |
| \warning To make this function work with a custom type registered with |
| qRegisterMetaType(), its comparison operator must be registered using |
| QMetaType::registerComparators(). |
| */ |
| |
| /*! |
| \fn bool QVariant::operator>(const QVariant &v) const |
| |
| Compares this QVariant with \a v and returns \c true if this is larger than \a v. |
| |
| \note Comparability might not be available for the type stored in this QVariant |
| or in \a v. |
| |
| \warning To make this function work with a custom type registered with |
| qRegisterMetaType(), its comparison operator must be registered using |
| QMetaType::registerComparators(). |
| */ |
| |
| /*! |
| \fn bool QVariant::operator>=(const QVariant &v) const |
| |
| Compares this QVariant with \a v and returns \c true if this is larger or equal than \a v. |
| |
| \note Comparability might not be available for the type stored in this QVariant |
| or in \a v. |
| |
| \warning To make this function work with a custom type registered with |
| qRegisterMetaType(), its comparison operator must be registered using |
| QMetaType::registerComparators(). |
| */ |
| |
| static bool qIsNumericType(uint tp) |
| { |
| static const qulonglong numericTypeBits = |
| Q_UINT64_C(1) << QMetaType::Bool | |
| Q_UINT64_C(1) << QMetaType::Double | |
| Q_UINT64_C(1) << QMetaType::Float | |
| Q_UINT64_C(1) << QMetaType::Char | |
| Q_UINT64_C(1) << QMetaType::SChar | |
| Q_UINT64_C(1) << QMetaType::UChar | |
| Q_UINT64_C(1) << QMetaType::Short | |
| Q_UINT64_C(1) << QMetaType::UShort | |
| Q_UINT64_C(1) << QMetaType::Int | |
| Q_UINT64_C(1) << QMetaType::UInt | |
| Q_UINT64_C(1) << QMetaType::Long | |
| Q_UINT64_C(1) << QMetaType::ULong | |
| Q_UINT64_C(1) << QMetaType::LongLong | |
| Q_UINT64_C(1) << QMetaType::ULongLong; |
| return tp < (CHAR_BIT * sizeof numericTypeBits) ? numericTypeBits & (Q_UINT64_C(1) << tp) : false; |
| } |
| |
| static bool qIsFloatingPoint(uint tp) |
| { |
| return tp == QVariant::Double || tp == QMetaType::Float; |
| } |
| |
| static int normalizeLowerRanks(uint tp) |
| { |
| static const qulonglong numericTypeBits = |
| Q_UINT64_C(1) << QMetaType::Bool | |
| Q_UINT64_C(1) << QMetaType::Char | |
| Q_UINT64_C(1) << QMetaType::SChar | |
| Q_UINT64_C(1) << QMetaType::UChar | |
| Q_UINT64_C(1) << QMetaType::Short | |
| Q_UINT64_C(1) << QMetaType::UShort; |
| return numericTypeBits & (Q_UINT64_C(1) << tp) ? QVariant::Int : tp; |
| } |
| |
| static int normalizeLong(uint tp) |
| { |
| const uint IntType = sizeof(long) == sizeof(int) ? QVariant::Int : QVariant::LongLong; |
| const uint UIntType = sizeof(ulong) == sizeof(uint) ? QVariant::UInt : QVariant::ULongLong; |
| return tp == QMetaType::Long ? IntType : |
| tp == QMetaType::ULong ? UIntType : tp; |
| } |
| |
| static int numericTypePromotion(uint t1, uint t2) |
| { |
| Q_ASSERT(qIsNumericType(t1)); |
| Q_ASSERT(qIsNumericType(t2)); |
| |
| // C++ integral ranks: (4.13 Integer conversion rank [conv.rank]) |
| // bool < signed char < short < int < long < long long |
| // unsigneds have the same rank as their signed counterparts |
| // C++ integral promotion rules (4.5 Integral Promotions [conv.prom]) |
| // - any type with rank less than int can be converted to int or unsigned int |
| // 5 Expressions [expr] paragraph 9: |
| // - if either operand is double, the other shall be converted to double |
| // - " " float, " " " float |
| // - if both operands have the same type, no further conversion is needed. |
| // - if both are signed or if both are unsigned, convert to the one with highest rank |
| // - if the unsigned has higher or same rank, convert the signed to the unsigned one |
| // - if the signed can represent all values of the unsigned, convert to the signed |
| // - otherwise, convert to the unsigned corresponding to the rank of the signed |
| |
| // floating point: we deviate from the C++ standard by always using qreal |
| if (qIsFloatingPoint(t1) || qIsFloatingPoint(t2)) |
| return QMetaType::QReal; |
| |
| // integral rules: |
| // for all platforms we support, int can always hold the values of lower-ranked types |
| t1 = normalizeLowerRanks(t1); |
| t2 = normalizeLowerRanks(t2); |
| |
| // normalize long / ulong: in all platforms we run, they're either the same as int or as long long |
| t1 = normalizeLong(t1); |
| t2 = normalizeLong(t2); |
| |
| // implement the other rules |
| // the four possibilities are Int, UInt, LongLong and ULongLong |
| // if any of the two is ULongLong, then it wins (highest rank, unsigned) |
| // otherwise, if one of the two is LongLong, then the other is either LongLong too or lower-ranked |
| // otherwise, if one of the two is UInt, then the other is either UInt too or Int |
| if (t1 == QVariant::ULongLong || t2 == QVariant::ULongLong) |
| return QVariant::ULongLong; |
| if (t1 == QVariant::LongLong || t2 == QVariant::LongLong) |
| return QVariant::LongLong; |
| if (t1 == QVariant::UInt || t2 == QVariant::UInt) |
| return QVariant::UInt; |
| return QVariant::Int; |
| } |
| |
| static int integralCompare(uint promotedType, const QVariant::Private *d1, const QVariant::Private *d2) |
| { |
| // use toLongLong to retrieve the data, it gets us all the bits |
| bool ok; |
| qlonglong l1 = qConvertToNumber(d1, &ok); |
| Q_ASSERT(ok); |
| |
| qlonglong l2 = qConvertToNumber(d2, &ok); |
| Q_ASSERT(ok); |
| |
| if (promotedType == QVariant::Int) |
| return int(l1) < int(l2) ? -1 : int(l1) == int(l2) ? 0 : 1; |
| if (promotedType == QVariant::UInt) |
| return uint(l1) < uint(l2) ? -1 : uint(l1) == uint(l2) ? 0 : 1; |
| if (promotedType == QVariant::LongLong) |
| return l1 < l2 ? -1 : l1 == l2 ? 0 : 1; |
| if (promotedType == QVariant::ULongLong) |
| return qulonglong(l1) < qulonglong(l2) ? -1 : qulonglong(l1) == qulonglong(l2) ? 0 : 1; |
| |
| Q_UNREACHABLE(); |
| return 0; |
| } |
| |
| static int numericCompare(const QVariant::Private *d1, const QVariant::Private *d2) |
| { |
| uint promotedType = numericTypePromotion(d1->type, d2->type); |
| if (promotedType != QMetaType::QReal) |
| return integralCompare(promotedType, d1, d2); |
| |
| // qreal comparisons |
| bool ok; |
| qreal r1 = qConvertToRealNumber(d1, &ok); |
| Q_ASSERT(ok); |
| qreal r2 = qConvertToRealNumber(d2, &ok); |
| Q_ASSERT(ok); |
| if (r1 == r2) |
| return 0; |
| |
| // only do fuzzy comparisons for finite, non-zero numbers |
| int c1 = qFpClassify(r1); |
| int c2 = qFpClassify(r2); |
| if ((c1 == FP_NORMAL || c1 == FP_SUBNORMAL) && (c2 == FP_NORMAL || c2 == FP_SUBNORMAL)) { |
| if (qFuzzyCompare(r1, r2)) |
| return 0; |
| } |
| |
| return r1 < r2 ? -1 : 1; |
| } |
| |
| /*! |
| \internal |
| */ |
| bool QVariant::cmp(const QVariant &v) const |
| { |
| auto cmp_helper = [] (const QVariant::Private &d1, const QVariant::Private &d2) |
| { |
| Q_ASSERT(d1.type == d2.type); |
| if (d1.type >= QMetaType::User) { |
| int result; |
| if (QMetaType::equals(QT_PREPEND_NAMESPACE(constData(d1)), QT_PREPEND_NAMESPACE(constData(d2)), d1.type, &result)) |
| return result == 0; |
| } |
| return handlerManager[d1.type]->compare(&d1, &d2); |
| }; |
| |
| // try numerics first, with C++ type promotion rules (no conversion) |
| if (qIsNumericType(d.type) && qIsNumericType(v.d.type)) |
| return numericCompare(&d, &v.d) == 0; |
| |
| if (d.type == v.d.type) |
| return cmp_helper(d, v.d); |
| |
| QVariant v1 = *this; |
| QVariant v2 = v; |
| if (v2.canConvert(v1.d.type)) { |
| if (!v2.convert(v1.d.type)) |
| return false; |
| } else { |
| // try the opposite conversion, it might work |
| qSwap(v1, v2); |
| if (!v2.convert(v1.d.type)) |
| return false; |
| } |
| return cmp_helper(v1.d, v2.d); |
| } |
| |
| /*! |
| \internal |
| */ |
| int QVariant::compare(const QVariant &v) const |
| { |
| // try numerics first, with C++ type promotion rules (no conversion) |
| if (qIsNumericType(d.type) && qIsNumericType(v.d.type)) |
| return numericCompare(&d, &v.d); |
| |
| // check for equality next, as more types implement operator== than operator< |
| if (cmp(v)) |
| return 0; |
| |
| const QVariant *v1 = this; |
| const QVariant *v2 = &v; |
| QVariant converted1; |
| QVariant converted2; |
| |
| if (d.type != v.d.type) { |
| // if both types differ, try to convert |
| if (v2->canConvert(v1->d.type)) { |
| converted2 = *v2; |
| if (converted2.convert(v1->d.type)) |
| v2 = &converted2; |
| } |
| if (v1->d.type != v2->d.type && v1->canConvert(v2->d.type)) { |
| converted1 = *v1; |
| if (converted1.convert(v2->d.type)) |
| v1 = &converted1; |
| } |
| if (v1->d.type != v2->d.type) { |
| // if conversion fails, default to toString |
| int r = v1->toString().compare(v2->toString(), Qt::CaseInsensitive); |
| if (r == 0) { |
| // cmp(v) returned false, so we should try to agree with it. |
| return (v1->d.type < v2->d.type) ? -1 : 1; |
| } |
| return r; |
| } |
| |
| // did we end up with two numerics? If so, restart |
| if (qIsNumericType(v1->d.type) && qIsNumericType(v2->d.type)) |
| return v1->compare(*v2); |
| } |
| if (v1->d.type >= QMetaType::User) { |
| int result; |
| if (QMetaType::compare(QT_PREPEND_NAMESPACE(constData(d)), QT_PREPEND_NAMESPACE(constData(v2->d)), d.type, &result)) |
| return result; |
| } |
| switch (v1->d.type) { |
| case QVariant::Date: |
| return v1->toDate() < v2->toDate() ? -1 : 1; |
| case QVariant::Time: |
| return v1->toTime() < v2->toTime() ? -1 : 1; |
| case QVariant::DateTime: |
| return v1->toDateTime() < v2->toDateTime() ? -1 : 1; |
| case QVariant::StringList: |
| return v1->toStringList() < v2->toStringList() ? -1 : 1; |
| } |
| int r = v1->toString().compare(v2->toString(), Qt::CaseInsensitive); |
| if (r == 0) { |
| // cmp(v) returned false, so we should try to agree with it. |
| return (d.type < v.d.type) ? -1 : 1; |
| } |
| return r; |
| } |
| |
| /*! |
| \internal |
| */ |
| |
| const void *QVariant::constData() const |
| { |
| return d.is_shared ? d.data.shared->ptr : reinterpret_cast<const void *>(&d.data.ptr); |
| } |
| |
| /*! |
| \fn const void* QVariant::data() const |
| |
| \internal |
| */ |
| |
| /*! |
| \internal |
| */ |
| void* QVariant::data() |
| { |
| detach(); |
| return const_cast<void *>(constData()); |
| } |
| |
| |
| /*! |
| Returns \c true if this is a null variant, false otherwise. A variant is |
| considered null if it contains no initialized value, or the contained value |
| is \nullptr or is an instance of a built-in type that has an isNull |
| method, in which case the result would be the same as calling isNull on the |
| wrapped object. |
| |
| \warning Null variants is not a single state and two null variants may easily |
| return \c false on the == operator if they do not contain similar null values. |
| |
| \sa convert(int) |
| */ |
| bool QVariant::isNull() const |
| { |
| return handlerManager[d.type]->isNull(&d); |
| } |
| |
| #ifndef QT_NO_DEBUG_STREAM |
| QDebug operator<<(QDebug dbg, const QVariant &v) |
| { |
| QDebugStateSaver saver(dbg); |
| const uint typeId = v.d.type; |
| dbg.nospace() << "QVariant("; |
| if (typeId != QMetaType::UnknownType) { |
| dbg << QMetaType::typeName(typeId) << ", "; |
| bool userStream = false; |
| bool canConvertToString = false; |
| if (typeId >= QMetaType::User) { |
| userStream = QMetaType::debugStream(dbg, constData(v.d), typeId); |
| canConvertToString = v.canConvert<QString>(); |
| } |
| if (!userStream && canConvertToString) |
| dbg << v.toString(); |
| else if (!userStream) |
| handlerManager[typeId]->debugStream(dbg, v); |
| } else { |
| dbg << "Invalid"; |
| } |
| dbg << ')'; |
| return dbg; |
| } |
| |
| QDebug operator<<(QDebug dbg, const QVariant::Type p) |
| { |
| QDebugStateSaver saver(dbg); |
| dbg.nospace() << "QVariant::" |
| << (int(p) != int(QMetaType::UnknownType) |
| ? QMetaType::typeName(p) |
| : "Invalid"); |
| return dbg; |
| } |
| #endif |
| |
| |
| /*! \fn template<typename T> void QVariant::setValue(const T &value) |
| |
| Stores a copy of \a value. If \c{T} is a type that QVariant |
| doesn't support, QMetaType is used to store the value. A compile |
| error will occur if QMetaType doesn't handle the type. |
| |
| Example: |
| |
| \snippet code/src_corelib_kernel_qvariant.cpp 4 |
| |
| \sa value(), fromValue(), canConvert() |
| */ |
| |
| /*! \fn template<typename T> T QVariant::value() const |
| |
| Returns the stored value converted to the template type \c{T}. |
| Call canConvert() to find out whether a type can be converted. |
| If the value cannot be converted, a \l{default-constructed value} |
| will be returned. |
| |
| If the type \c{T} is supported by QVariant, this function behaves |
| exactly as toString(), toInt() etc. |
| |
| Example: |
| |
| \snippet code/src_corelib_kernel_qvariant.cpp 5 |
| |
| If the QVariant contains a pointer to a type derived from QObject then |
| \c{T} may be any QObject type. If the pointer stored in the QVariant can be |
| qobject_cast to T, then that result is returned. Otherwise \nullptr is |
| returned. Note that this only works for QObject subclasses which use the |
| Q_OBJECT macro. |
| |
| If the QVariant contains a sequential container and \c{T} is QVariantList, the |
| elements of the container will be converted into \l {QVariant}s and returned as a QVariantList. |
| |
| \snippet code/src_corelib_kernel_qvariant.cpp 9 |
| |
| \sa setValue(), fromValue(), canConvert(), Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE() |
| */ |
| |
| /*! \fn bool QVariant::canConvert() const |
| |
| Returns \c true if the variant can be converted to the template type \c{T}, |
| otherwise false. |
| |
| Example: |
| |
| \snippet code/src_corelib_kernel_qvariant.cpp 6 |
| |
| A QVariant containing a pointer to a type derived from QObject will also return true for this |
| function if a qobject_cast to the template type \c{T} would succeed. Note that this only works |
| for QObject subclasses which use the Q_OBJECT macro. |
| |
| \sa convert() |
| */ |
| |
| /*! \fn template<typename T> static QVariant QVariant::fromValue(const T &value) |
| |
| Returns a QVariant containing a copy of \a value. Behaves |
| exactly like setValue() otherwise. |
| |
| Example: |
| |
| \snippet code/src_corelib_kernel_qvariant.cpp 7 |
| |
| \note If you are working with custom types, you should use |
| the Q_DECLARE_METATYPE() macro to register your custom type. |
| |
| \sa setValue(), value() |
| */ |
| |
| /*! \fn template<typename... Types> QVariant QVariant::fromStdVariant(const std::variant<Types...> &value) |
| \since 5.11 |
| |
| Returns a QVariant with the type and value of the active variant of \a value. If |
| the active type is std::monostate a default QVariant is returned. |
| |
| \note With this method you do not need to register the variant as a Qt metatype, |
| since the std::variant is resolved before being stored. The component types |
| should be registered however. |
| |
| \sa fromValue() |
| */ |
| |
| #if QT_DEPRECATED_SINCE(5, 14) |
| /*! |
| \fn template<typename T> QVariant qVariantFromValue(const T &value) |
| \relates QVariant |
| \obsolete |
| |
| Returns a variant containing a copy of the given \a value |
| with template type \c{T}. |
| |
| This function is equivalent to QVariant::fromValue(\a value). |
| |
| \note This function was provided as a workaround for MSVC 6 |
| which did not support member template functions. It is advised |
| to use the other form in new code. |
| |
| For example, a QObject pointer can be stored in a variant with the |
| following code: |
| |
| \snippet code/src_corelib_kernel_qvariant.cpp 8 |
| |
| \sa QVariant::fromValue() |
| */ |
| |
| /*! \fn template<typename T> void qVariantSetValue(QVariant &variant, const T &value) |
| \relates QVariant |
| \obsolete |
| |
| Sets the contents of the given \a variant to a copy of the |
| \a value with the specified template type \c{T}. |
| |
| This function is equivalent to QVariant::setValue(\a value). |
| |
| \note This function was provided as a workaround for MSVC 6 |
| which did not support member template functions. It is advised |
| to use the other form in new code. |
| |
| \sa QVariant::setValue() |
| */ |
| #endif |
| |
| /*! |
| \fn template<typename T> T qvariant_cast(const QVariant &value) |
| \relates QVariant |
| |
| Returns the given \a value converted to the template type \c{T}. |
| |
| This function is equivalent to QVariant::value(). |
| |
| \sa QVariant::value() |
| */ |
| |
| /*! \fn template<typename T> T qVariantValue(const QVariant &value) |
| \relates QVariant |
| \obsolete |
| |
| Returns the given \a value converted to the template type \c{T}. |
| |
| This function is equivalent to |
| \l{QVariant::value()}{QVariant::value}<T>(\a value). |
| |
| \note This function was provided as a workaround for MSVC 6 |
| which did not support member template functions. It is advised |
| to use the other form in new code. |
| |
| \sa QVariant::value(), qvariant_cast() |
| */ |
| |
| /*! \fn bool qVariantCanConvert(const QVariant &value) |
| \relates QVariant |
| \obsolete |
| |
| Returns \c true if the given \a value can be converted to the |
| template type specified; otherwise returns \c false. |
| |
| This function is equivalent to QVariant::canConvert(\a value). |
| |
| \note This function was provided as a workaround for MSVC 6 |
| which did not support member template functions. It is advised |
| to use the other form in new code. |
| |
| \sa QVariant::canConvert() |
| */ |
| |
| /*! |
| \typedef QVariantList |
| \relates QVariant |
| |
| Synonym for QList<QVariant>. |
| */ |
| |
| /*! |
| \typedef QVariantMap |
| \relates QVariant |
| |
| Synonym for QMap<QString, QVariant>. |
| */ |
| |
| /*! |
| \typedef QVariantHash |
| \relates QVariant |
| \since 4.5 |
| |
| Synonym for QHash<QString, QVariant>. |
| */ |
| |
| /*! |
| \typedef QVariant::DataPtr |
| \internal |
| */ |
| /*! \typedef QVariant::f_construct |
| \internal |
| */ |
| |
| /*! \typedef QVariant::f_clear |
| \internal |
| */ |
| |
| /*! \typedef QVariant::f_null |
| \internal |
| */ |
| |
| /*! \typedef QVariant::f_load |
| \internal |
| */ |
| |
| /*! \typedef QVariant::f_save |
| \internal |
| */ |
| |
| /*! \typedef QVariant::f_compare |
| \internal |
| */ |
| |
| /*! \typedef QVariant::f_convert |
| \internal |
| */ |
| |
| /*! \typedef QVariant::f_canConvert |
| \internal |
| */ |
| |
| /*! \typedef QVariant::f_debugStream |
| \internal |
| */ |
| |
| /*! |
| \fn DataPtr &QVariant::data_ptr() |
| \internal |
| */ |
| |
| /*! |
| \fn const DataPtr &QVariant::data_ptr() const |
| \internal |
| */ |
| |
| /*! |
| \class QSequentialIterable |
| \since 5.2 |
| \inmodule QtCore |
| \brief The QSequentialIterable class is an iterable interface for a container in a QVariant. |
| |
| This class allows several methods of accessing the elements of a container held within |
| a QVariant. An instance of QSequentialIterable can be extracted from a QVariant if it can |
| be converted to a QVariantList. |
| |
| \snippet code/src_corelib_kernel_qvariant.cpp 9 |
| |
| The container itself is not copied before iterating over it. |
| |
| \sa QVariant |
| */ |
| |
| /*! |
| \internal |
| */ |
| #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) |
| QSequentialIterable::QSequentialIterable(QtMetaTypePrivate::QSequentialIterableImpl impl) |
| #else |
| QSequentialIterable::QSequentialIterable(const QtMetaTypePrivate::QSequentialIterableImpl &impl) |
| #endif |
| : m_impl(impl) |
| { |
| } |
| |
| QSequentialIterable::const_iterator::const_iterator(const QSequentialIterable &iter, QAtomicInt *ref_) |
| : m_impl(iter.m_impl), ref(ref_) |
| { |
| ref->ref(); |
| } |
| |
| QSequentialIterable::const_iterator::const_iterator(const QtMetaTypePrivate::QSequentialIterableImpl &impl, QAtomicInt *ref_) |
| : m_impl(impl), ref(ref_) |
| { |
| ref->ref(); |
| } |
| |
| void QSequentialIterable::const_iterator::begin() |
| { |
| m_impl.moveToBegin(); |
| } |
| |
| void QSequentialIterable::const_iterator::end() |
| { |
| m_impl.moveToEnd(); |
| } |
| |
| /*! \fn QSequentialIterable::const_iterator QSequentialIterable::begin() const |
| |
| Returns a QSequentialIterable::const_iterator for the beginning of the container. This |
| can be used in stl-style iteration. |
| |
| \sa end() |
| */ |
| QSequentialIterable::const_iterator QSequentialIterable::begin() const |
| { |
| const_iterator it(*this, new QAtomicInt(0)); |
| it.begin(); |
| return it; |
| } |
| |
| /*! |
| Returns a QSequentialIterable::const_iterator for the end of the container. This |
| can be used in stl-style iteration. |
| |
| \sa begin() |
| */ |
| QSequentialIterable::const_iterator QSequentialIterable::end() const |
| { |
| const_iterator it(*this, new QAtomicInt(0)); |
| it.end(); |
| return it; |
| } |
| |
| static const QVariant variantFromVariantDataHelper(const QtMetaTypePrivate::VariantData &d) { |
| QVariant v; |
| if (d.metaTypeId == qMetaTypeId<QVariant>()) |
| v = *reinterpret_cast<const QVariant*>(d.data); |
| else |
| v = QVariant(d.metaTypeId, d.data, d.flags & ~QVariantConstructionFlags::ShouldDeleteVariantData); |
| if (d.flags & QVariantConstructionFlags::ShouldDeleteVariantData) |
| QMetaType::destroy(d.metaTypeId, const_cast<void *>(d.data)); |
| return v; |
| } |
| |
| /*! |
| Returns the element at position \a idx in the container. |
| */ |
| QVariant QSequentialIterable::at(int idx) const |
| { |
| const QtMetaTypePrivate::VariantData d = m_impl.at(idx); |
| return variantFromVariantDataHelper(d); |
| } |
| |
| /*! |
| Returns the number of elements in the container. |
| */ |
| int QSequentialIterable::size() const |
| { |
| return m_impl.size(); |
| } |
| |
| /*! |
| Returns whether it is possible to iterate over the container in reverse. This |
| corresponds to the std::bidirectional_iterator_tag iterator trait of the |
| const_iterator of the container. |
| */ |
| bool QSequentialIterable::canReverseIterate() const |
| { |
| return m_impl._iteratorCapabilities & QtMetaTypePrivate::BiDirectionalCapability; |
| } |
| |
| /*! |
| \class QSequentialIterable::const_iterator |
| \since 5.2 |
| \inmodule QtCore |
| \brief The QSequentialIterable::const_iterator allows iteration over a container in a QVariant. |
| |
| A QSequentialIterable::const_iterator can only be created by a QSequentialIterable instance, |
| and can be used in a way similar to other stl-style iterators. |
| |
| \snippet code/src_corelib_kernel_qvariant.cpp 9 |
| |
| \sa QSequentialIterable |
| */ |
| |
| |
| /*! |
| Destroys the QSequentialIterable::const_iterator. |
| */ |
| QSequentialIterable::const_iterator::~const_iterator() { |
| if (!ref->deref()) { |
| m_impl.destroyIter(); |
| delete ref; |
| } |
| } |
| |
| /*! |
| Creates a copy of \a other. |
| */ |
| QSequentialIterable::const_iterator::const_iterator(const const_iterator &other) |
| : m_impl(other.m_impl), ref(other.ref) |
| { |
| ref->ref(); |
| } |
| |
| /*! |
| Assigns \a other to this. |
| */ |
| QSequentialIterable::const_iterator& |
| QSequentialIterable::const_iterator::operator=(const const_iterator &other) |
| { |
| other.ref->ref(); |
| if (!ref->deref()) { |
| m_impl.destroyIter(); |
| delete ref; |
| } |
| m_impl = other.m_impl; |
| ref = other.ref; |
| return *this; |
| } |
| |
| /*! |
| Returns the current item, converted to a QVariant. |
| */ |
| const QVariant QSequentialIterable::const_iterator::operator*() const |
| { |
| const QtMetaTypePrivate::VariantData d = m_impl.getCurrent(); |
| return variantFromVariantDataHelper(d); |
| } |
| |
| /*! |
| Returns \c true if \a other points to the same item as this |
| iterator; otherwise returns \c false. |
| |
| \sa operator!=() |
| */ |
| bool QSequentialIterable::const_iterator::operator==(const const_iterator &other) const |
| { |
| return m_impl.equal(other.m_impl); |
| } |
| |
| /*! |
| Returns \c true if \a other points to a different item than this |
| iterator; otherwise returns \c false. |
| |
| \sa operator==() |
| */ |
| bool QSequentialIterable::const_iterator::operator!=(const const_iterator &other) const |
| { |
| return !m_impl.equal(other.m_impl); |
| } |
| |
| /*! |
| The prefix ++ operator (\c{++it}) advances the iterator to the |
| next item in the container and returns an iterator to the new current |
| item. |
| |
| Calling this function on QSequentialIterable::end() leads to undefined results. |
| |
| \sa operator--() |
| */ |
| QSequentialIterable::const_iterator &QSequentialIterable::const_iterator::operator++() |
| { |
| m_impl.advance(1); |
| return *this; |
| } |
| |
| /*! |
| \overload |
| |
| The postfix ++ operator (\c{it++}) advances the iterator to the |
| next item in the container and returns an iterator to the previously |
| current item. |
| */ |
| QSequentialIterable::const_iterator QSequentialIterable::const_iterator::operator++(int) |
| { |
| QtMetaTypePrivate::QSequentialIterableImpl impl; |
| impl.copy(m_impl); |
| m_impl.advance(1); |
| return const_iterator(impl, new QAtomicInt(0)); |
| } |
| |
| /*! |
| The prefix -- operator (\c{--it}) makes the preceding item |
| current and returns an iterator to the new current item. |
| |
| Calling this function on QSequentialIterable::begin() leads to undefined results. |
| |
| If the container in the QVariant does not support bi-directional iteration, calling this function |
| leads to undefined results. |
| |
| \sa operator++(), canReverseIterate() |
| */ |
| QSequentialIterable::const_iterator &QSequentialIterable::const_iterator::operator--() |
| { |
| m_impl.advance(-1); |
| return *this; |
| } |
| |
| /*! |
| \overload |
| |
| The postfix -- operator (\c{it--}) makes the preceding item |
| current and returns an iterator to the previously current item. |
| |
| If the container in the QVariant does not support bi-directional iteration, calling this function |
| leads to undefined results. |
| |
| \sa canReverseIterate() |
| */ |
| QSequentialIterable::const_iterator QSequentialIterable::const_iterator::operator--(int) |
| { |
| QtMetaTypePrivate::QSequentialIterableImpl impl; |
| impl.copy(m_impl); |
| m_impl.advance(-1); |
| return const_iterator(impl, new QAtomicInt(0)); |
| } |
| |
| /*! |
| Advances the iterator by \a j items. |
| |
| \sa operator-=(), operator+() |
| */ |
| QSequentialIterable::const_iterator &QSequentialIterable::const_iterator::operator+=(int j) |
| { |
| m_impl.advance(j); |
| return *this; |
| } |
| |
| /*! |
| Makes the iterator go back by \a j items. |
| |
| If the container in the QVariant does not support bi-directional iteration, calling this function |
| leads to undefined results. |
| |
| \sa operator+=(), operator-(), canReverseIterate() |
| */ |
| QSequentialIterable::const_iterator &QSequentialIterable::const_iterator::operator-=(int j) |
| { |
| m_impl.advance(-j); |
| return *this; |
| } |
| |
| /*! |
| Returns an iterator to the item at \a j positions forward from |
| this iterator. |
| |
| \sa operator-(), operator+=() |
| */ |
| QSequentialIterable::const_iterator QSequentialIterable::const_iterator::operator+(int j) const |
| { |
| QtMetaTypePrivate::QSequentialIterableImpl impl; |
| impl.copy(m_impl); |
| impl.advance(j); |
| return const_iterator(impl, new QAtomicInt(0)); |
| } |
| |
| /*! |
| Returns an iterator to the item at \a j positions backward from |
| this iterator. |
| |
| If the container in the QVariant does not support bi-directional iteration, calling this function |
| leads to undefined results. |
| |
| \sa operator+(), operator-=(), canReverseIterate() |
| */ |
| QSequentialIterable::const_iterator QSequentialIterable::const_iterator::operator-(int j) const |
| { |
| QtMetaTypePrivate::QSequentialIterableImpl impl; |
| impl.copy(m_impl); |
| impl.advance(-j); |
| return const_iterator(impl, new QAtomicInt(0)); |
| } |
| |
| /*! |
| \class QAssociativeIterable |
| \since 5.2 |
| \inmodule QtCore |
| \brief The QAssociativeIterable class is an iterable interface for an associative container in a QVariant. |
| |
| This class allows several methods of accessing the elements of an associative container held within |
| a QVariant. An instance of QAssociativeIterable can be extracted from a QVariant if it can |
| be converted to a QVariantHash or QVariantMap. |
| |
| \snippet code/src_corelib_kernel_qvariant.cpp 10 |
| |
| The container itself is not copied before iterating over it. |
| |
| \sa QVariant |
| */ |
| |
| /*! |
| \internal |
| */ |
| #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) |
| QAssociativeIterable::QAssociativeIterable(QtMetaTypePrivate::QAssociativeIterableImpl impl) |
| #else |
| QAssociativeIterable::QAssociativeIterable(const QtMetaTypePrivate::QAssociativeIterableImpl &impl) |
| #endif |
| : m_impl(impl) |
| { |
| } |
| |
| QAssociativeIterable::const_iterator::const_iterator(const QAssociativeIterable &iter, QAtomicInt *ref_) |
| : m_impl(iter.m_impl), ref(ref_) |
| { |
| ref->ref(); |
| } |
| |
| QAssociativeIterable::const_iterator::const_iterator(const QtMetaTypePrivate::QAssociativeIterableImpl &impl, QAtomicInt *ref_) |
| : m_impl(impl), ref(ref_) |
| { |
| ref->ref(); |
| } |
| |
| void QAssociativeIterable::const_iterator::begin() |
| { |
| m_impl.begin(); |
| } |
| |
| void QAssociativeIterable::const_iterator::end() |
| { |
| m_impl.end(); |
| } |
| |
| void QAssociativeIterable::const_iterator::find(const QVariant &key) |
| { |
| Q_ASSERT(key.userType() == m_impl._metaType_id_key); |
| const QtMetaTypePrivate::VariantData dkey(key.userType(), key.constData(), 0 /*key.flags()*/); |
| m_impl.find(dkey); |
| } |
| |
| /*! |
| Returns a QAssociativeIterable::const_iterator for the beginning of the container. This |
| can be used in stl-style iteration. |
| |
| \sa end() |
| */ |
| QAssociativeIterable::const_iterator QAssociativeIterable::begin() const |
| { |
| const_iterator it(*this, new QAtomicInt(0)); |
| it.begin(); |
| return it; |
| } |
| |
| /*! |
| Returns a QAssociativeIterable::const_iterator for the end of the container. This |
| can be used in stl-style iteration. |
| |
| \sa begin() |
| */ |
| QAssociativeIterable::const_iterator QAssociativeIterable::end() const |
| { |
| const_iterator it(*this, new QAtomicInt(0)); |
| it.end(); |
| return it; |
| } |
| |
| /*! |
| \since 5.5 |
| |
| Returns a QAssociativeIterable::const_iterator for the given key \a key |
| in the container, if the types are convertible. |
| |
| If the key is not found, returns end(). |
| |
| This can be used in stl-style iteration. |
| |
| \sa begin(), end(), value() |
| */ |
| QAssociativeIterable::const_iterator QAssociativeIterable::find(const QVariant &key) const |
| { |
| const_iterator it(*this, new QAtomicInt(0)); |
| QVariant key_ = key; |
| if (key_.canConvert(m_impl._metaType_id_key) && key_.convert(m_impl._metaType_id_key)) |
| it.find(key_); |
| else |
| it.end(); |
| return it; |
| } |
| |
| /*! |
| Returns the value for the given \a key in the container, if the types are convertible. |
| |
| \sa find() |
| */ |
| QVariant QAssociativeIterable::value(const QVariant &key) const |
| { |
| const const_iterator it = find(key); |
| if (it == end()) |
| return QVariant(); |
| return *it; |
| } |
| |
| /*! |
| Returns the number of elements in the container. |
| */ |
| int QAssociativeIterable::size() const |
| { |
| return m_impl.size(); |
| } |
| |
| /*! |
| \class QAssociativeIterable::const_iterator |
| \since 5.2 |
| \inmodule QtCore |
| \brief The QAssociativeIterable::const_iterator allows iteration over a container in a QVariant. |
| |
| A QAssociativeIterable::const_iterator can only be created by a QAssociativeIterable instance, |
| and can be used in a way similar to other stl-style iterators. |
| |
| \snippet code/src_corelib_kernel_qvariant.cpp 10 |
| |
| \sa QAssociativeIterable |
| */ |
| |
| |
| /*! |
| Destroys the QAssociativeIterable::const_iterator. |
| */ |
| QAssociativeIterable::const_iterator::~const_iterator() |
| { |
| if (!ref->deref()) { |
| m_impl.destroyIter(); |
| delete ref; |
| } |
| } |
| |
| /*! |
| Creates a copy of \a other. |
| */ |
| QAssociativeIterable::const_iterator::const_iterator(const const_iterator &other) |
| : m_impl(other.m_impl), ref(other.ref) |
| { |
| ref->ref(); |
| } |
| |
| /*! |
| Assigns \a other to this. |
| */ |
| QAssociativeIterable::const_iterator& |
| QAssociativeIterable::const_iterator::operator=(const const_iterator &other) |
| { |
| other.ref->ref(); |
| if (!ref->deref()) { |
| m_impl.destroyIter(); |
| delete ref; |
| } |
| m_impl = other.m_impl; |
| ref = other.ref; |
| return *this; |
| } |
| |
| /*! |
| Returns the current value, converted to a QVariant. |
| */ |
| const QVariant QAssociativeIterable::const_iterator::operator*() const |
| { |
| const QtMetaTypePrivate::VariantData d = m_impl.getCurrentValue(); |
| return variantFromVariantDataHelper(d); |
| } |
| |
| /*! |
| Returns the current key, converted to a QVariant. |
| */ |
| const QVariant QAssociativeIterable::const_iterator::key() const |
| { |
| const QtMetaTypePrivate::VariantData d = m_impl.getCurrentKey(); |
| return variantFromVariantDataHelper(d); |
| } |
| |
| /*! |
| Returns the current value, converted to a QVariant. |
| */ |
| const QVariant QAssociativeIterable::const_iterator::value() const |
| { |
| return operator*(); |
| } |
| |
| /*! |
| Returns \c true if \a other points to the same item as this |
| iterator; otherwise returns \c false. |
| |
| \sa operator!=() |
| */ |
| bool QAssociativeIterable::const_iterator::operator==(const const_iterator &other) const |
| { |
| return m_impl.equal(other.m_impl); |
| } |
| |
| /*! |
| Returns \c true if \a other points to a different item than this |
| iterator; otherwise returns \c false. |
| |
| \sa operator==() |
| */ |
| bool QAssociativeIterable::const_iterator::operator!=(const const_iterator &other) const |
| { |
| return !m_impl.equal(other.m_impl); |
| } |
| |
| /*! |
| The prefix ++ operator (\c{++it}) advances the iterator to the |
| next item in the container and returns an iterator to the new current |
| item. |
| |
| Calling this function on QAssociativeIterable::end() leads to undefined results. |
| |
| \sa operator--() |
| */ |
| QAssociativeIterable::const_iterator &QAssociativeIterable::const_iterator::operator++() |
| { |
| m_impl.advance(1); |
| return *this; |
| } |
| |
| /*! |
| \overload |
| |
| The postfix ++ operator (\c{it++}) advances the iterator to the |
| next item in the container and returns an iterator to the previously |
| current item. |
| */ |
| QAssociativeIterable::const_iterator QAssociativeIterable::const_iterator::operator++(int) |
| { |
| QtMetaTypePrivate::QAssociativeIterableImpl impl; |
| impl.copy(m_impl); |
| m_impl.advance(1); |
| return const_iterator(impl, new QAtomicInt(0)); |
| } |
| |
| /*! |
| The prefix -- operator (\c{--it}) makes the preceding item |
| current and returns an iterator to the new current item. |
| |
| Calling this function on QAssociativeIterable::begin() leads to undefined results. |
| |
| \sa operator++() |
| */ |
| QAssociativeIterable::const_iterator &QAssociativeIterable::const_iterator::operator--() |
| { |
| m_impl.advance(-1); |
| return *this; |
| } |
| |
| /*! |
| \overload |
| |
| The postfix -- operator (\c{it--}) makes the preceding item |
| current and returns an iterator to the previously current item. |
| */ |
| QAssociativeIterable::const_iterator QAssociativeIterable::const_iterator::operator--(int) |
| { |
| QtMetaTypePrivate::QAssociativeIterableImpl impl; |
| impl.copy(m_impl); |
| m_impl.advance(-1); |
| return const_iterator(impl, new QAtomicInt(0)); |
| } |
| |
| /*! |
| Advances the iterator by \a j items. |
| |
| \sa operator-=(), operator+() |
| */ |
| QAssociativeIterable::const_iterator &QAssociativeIterable::const_iterator::operator+=(int j) |
| { |
| m_impl.advance(j); |
| return *this; |
| } |
| |
| /*! |
| Makes the iterator go back by \a j items. |
| |
| \sa operator+=(), operator-() |
| */ |
| QAssociativeIterable::const_iterator &QAssociativeIterable::const_iterator::operator-=(int j) |
| { |
| m_impl.advance(-j); |
| return *this; |
| } |
| |
| /*! |
| Returns an iterator to the item at \a j positions forward from |
| this iterator. |
| |
| \sa operator-(), operator+=() |
| */ |
| QAssociativeIterable::const_iterator QAssociativeIterable::const_iterator::operator+(int j) const |
| { |
| QtMetaTypePrivate::QAssociativeIterableImpl impl; |
| impl.copy(m_impl); |
| impl.advance(j); |
| return const_iterator(impl, new QAtomicInt(0)); |
| } |
| |
| /*! |
| Returns an iterator to the item at \a j positions backward from |
| this iterator. |
| |
| \sa operator+(), operator-=() |
| */ |
| QAssociativeIterable::const_iterator QAssociativeIterable::const_iterator::operator-(int j) const |
| { |
| QtMetaTypePrivate::QAssociativeIterableImpl impl; |
| impl.copy(m_impl); |
| impl.advance(-j); |
| return const_iterator(impl, new QAtomicInt(0)); |
| } |
| |
| QT_END_NAMESPACE |