QVariant: Convert automatically from enum types to integral types.
[ChangeLog][QtCore][QVariant] Variant containing enum types can now be converted to integer Change-Id: Ibbbc9ae29ab45d67c582fa2d406afc19c5dc41ce Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> Reviewed-by: Jędrzej Nowacki <jedrzej.nowacki@digia.com>bb10
parent
2ee97f505b
commit
34d21610ba
|
|
@ -1,6 +1,7 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** Copyright (C) 2013 Olivier Goffart <ogoffart@woboq.com>
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of the QtCore module of the Qt Toolkit.
|
||||
|
|
@ -221,6 +222,19 @@ static qlonglong qConvertToNumber(const QVariant::Private *d, bool *ok)
|
|||
return qlonglong(qMetaTypeUNumber(d));
|
||||
}
|
||||
|
||||
if (QMetaType::typeFlags(d->type) & QMetaType::IsEnumeration) {
|
||||
switch (QMetaType::sizeOf(d->type)) {
|
||||
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);
|
||||
}
|
||||
|
|
@ -256,6 +270,19 @@ static qulonglong qConvertToUnsignedNumber(const QVariant::Private *d, bool *ok)
|
|||
return qMetaTypeUNumber(d);
|
||||
}
|
||||
|
||||
if (QMetaType::typeFlags(d->type) & QMetaType::IsEnumeration) {
|
||||
switch (QMetaType::sizeOf(d->type)) {
|
||||
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);
|
||||
}
|
||||
|
|
@ -888,15 +915,13 @@ static bool customCompare(const QVariant::Private *a, const QVariant::Private *b
|
|||
static bool customConvert(const QVariant::Private *d, int t, void *result, bool *ok)
|
||||
{
|
||||
if (d->type >= QMetaType::User || t >= QMetaType::User) {
|
||||
const bool isOk = QMetaType::convert(constData(*d), d->type, result, t);
|
||||
if (ok)
|
||||
*ok = isOk;
|
||||
return isOk;
|
||||
if (QMetaType::convert(constData(*d), d->type, result, t)) {
|
||||
if (ok)
|
||||
*ok = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (ok)
|
||||
*ok = false;
|
||||
return false;
|
||||
return convert(d, t, result, ok);
|
||||
}
|
||||
|
||||
#if !defined(QT_NO_DEBUG_STREAM)
|
||||
|
|
@ -2854,8 +2879,13 @@ bool QVariant::canConvert(int targetTypeId) const
|
|||
|
||||
if (targetTypeId < 0)
|
||||
return false;
|
||||
if (targetTypeId >= QMetaType::User)
|
||||
return canConvertMetaObject(currentType, targetTypeId, d.data.o);
|
||||
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) {
|
||||
switch (targetTypeId) {
|
||||
|
|
@ -2896,7 +2926,8 @@ bool QVariant::canConvert(int targetTypeId) const
|
|||
|| currentType == QMetaType::UChar
|
||||
|| currentType == QMetaType::Char
|
||||
|| currentType == QMetaType::SChar
|
||||
|| currentType == QMetaType::Short;
|
||||
|| currentType == QMetaType::Short
|
||||
|| QMetaType::typeFlags(currentType) & QMetaType::IsEnumeration;
|
||||
case QVariant::Image:
|
||||
return currentType == QVariant::Pixmap || currentType == QVariant::Bitmap;
|
||||
case QVariant::Pixmap:
|
||||
|
|
@ -2925,7 +2956,9 @@ bool QVariant::canConvert(int targetTypeId) const
|
|||
case QMetaType::ULong:
|
||||
case QMetaType::Short:
|
||||
case QMetaType::UShort:
|
||||
return qCanConvertMatrix[QVariant::Int] & (1 << currentType) || currentType == QVariant::Int;
|
||||
return qCanConvertMatrix[QVariant::Int] & (1 << currentType)
|
||||
|| currentType == QVariant::Int
|
||||
|| QMetaType::typeFlags(currentType) & QMetaType::IsEnumeration;
|
||||
case QMetaType::QObjectStar:
|
||||
return canConvertMetaObject(currentType, targetTypeId, d.data.o);
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -247,6 +247,8 @@ private slots:
|
|||
|
||||
void iterateContainerElements();
|
||||
void pairElements();
|
||||
|
||||
void enums();
|
||||
private:
|
||||
void dataStream_data(QDataStream::Version version);
|
||||
void loadQVariantFromDataStream(QDataStream::Version version);
|
||||
|
|
@ -3953,5 +3955,87 @@ void tst_QVariant::pairElements()
|
|||
TEST_PAIR_ELEMENT_ACCESS(std::pair, int, QVariant, 44, 15)
|
||||
}
|
||||
|
||||
enum EnumTest_Enum0 { EnumTest_Enum0_value = 42, ensureSignedEnum0 = -1 };
|
||||
Q_DECLARE_METATYPE(EnumTest_Enum0)
|
||||
enum EnumTest_Enum1 { EnumTest_Enum1_value = 42, EnumTest_Enum1_bigValue = (Q_INT64_C(1) << 33) + 50 };
|
||||
Q_DECLARE_METATYPE(EnumTest_Enum1)
|
||||
|
||||
#if defined(Q_COMPILER_CLASS_ENUM)
|
||||
enum EnumTest_Enum3 : qint64 { EnumTest_Enum3_value = -47, EnumTest_Enum3_bigValue = (Q_INT64_C(1) << 56) + 5 };
|
||||
Q_DECLARE_METATYPE(EnumTest_Enum3)
|
||||
enum EnumTest_Enum4 : quint64 { EnumTest_Enum4_value = 47, EnumTest_Enum4_bigValue = (Q_INT64_C(1) << 52) + 45 };
|
||||
Q_DECLARE_METATYPE(EnumTest_Enum4)
|
||||
enum EnumTest_Enum5 : uint { EnumTest_Enum5_value = 47 };
|
||||
Q_DECLARE_METATYPE(EnumTest_Enum5)
|
||||
enum EnumTest_Enum6 : uchar { EnumTest_Enum6_value = 47 };
|
||||
Q_DECLARE_METATYPE(EnumTest_Enum6)
|
||||
enum class EnumTest_Enum7 { EnumTest_Enum7_value = 47, ensureSignedEnum7 = -1 };
|
||||
Q_DECLARE_METATYPE(EnumTest_Enum7)
|
||||
enum EnumTest_Enum8 : short { EnumTest_Enum8_value = 47 };
|
||||
Q_DECLARE_METATYPE(EnumTest_Enum8)
|
||||
#endif
|
||||
|
||||
template<typename Enum> void testVariant(Enum value, bool *ok)
|
||||
{
|
||||
*ok = false;
|
||||
QVariant var = QVariant::fromValue(value);
|
||||
|
||||
QCOMPARE(var.userType(), qMetaTypeId<Enum>());
|
||||
|
||||
QVERIFY(var.canConvert<Enum>());
|
||||
QVERIFY(var.canConvert<int>());
|
||||
QVERIFY(var.canConvert<unsigned int>());
|
||||
QVERIFY(var.canConvert<short>());
|
||||
QVERIFY(var.canConvert<unsigned short>());
|
||||
QVERIFY(var.canConvert<qint64>());
|
||||
QVERIFY(var.canConvert<quint64>());
|
||||
|
||||
|
||||
QCOMPARE(var.value<Enum>(), value);
|
||||
QCOMPARE(var.value<int>(), static_cast<int>(value));
|
||||
QCOMPARE(var.value<uint>(), static_cast<uint>(value));
|
||||
QCOMPARE(var.value<short>(), static_cast<short>(value));
|
||||
QCOMPARE(var.value<unsigned short>(), static_cast<unsigned short>(value));
|
||||
QCOMPARE(var.value<qint64>(), static_cast<qint64>(value));
|
||||
QCOMPARE(var.value<quint64>(), static_cast<quint64>(value));
|
||||
|
||||
QVariant var2 = var;
|
||||
QVERIFY(var2.convert(QMetaType::Int));
|
||||
QCOMPARE(var2.value<int>(), static_cast<int>(value));
|
||||
|
||||
*ok = true;
|
||||
}
|
||||
|
||||
void tst_QVariant::enums()
|
||||
{
|
||||
bool ok = false;
|
||||
testVariant(EnumTest_Enum0_value, &ok);
|
||||
QVERIFY(ok);
|
||||
testVariant(EnumTest_Enum1_value, &ok);
|
||||
QVERIFY(ok);
|
||||
testVariant(EnumTest_Enum1_bigValue, &ok);
|
||||
QVERIFY(ok);
|
||||
#if defined(Q_COMPILER_CLASS_ENUM)
|
||||
testVariant(EnumTest_Enum3::EnumTest_Enum3_value, &ok);
|
||||
QVERIFY(ok);
|
||||
testVariant(EnumTest_Enum3::EnumTest_Enum3_bigValue, &ok);
|
||||
QVERIFY(ok);
|
||||
testVariant(EnumTest_Enum4::EnumTest_Enum4_value, &ok);
|
||||
QVERIFY(ok);
|
||||
testVariant(EnumTest_Enum4::EnumTest_Enum4_bigValue, &ok);
|
||||
QVERIFY(ok);
|
||||
testVariant(EnumTest_Enum5::EnumTest_Enum5_value, &ok);
|
||||
QVERIFY(ok);
|
||||
testVariant(EnumTest_Enum6::EnumTest_Enum6_value, &ok);
|
||||
QVERIFY(ok);
|
||||
testVariant(EnumTest_Enum7::EnumTest_Enum7_value, &ok);
|
||||
QVERIFY(ok);
|
||||
testVariant(EnumTest_Enum8::EnumTest_Enum8_value, &ok);
|
||||
QVERIFY(ok);
|
||||
testVariant(EnumTest_Enum3::EnumTest_Enum3_value, &ok);
|
||||
QVERIFY(ok);
|
||||
#endif
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_QVariant)
|
||||
#include "tst_qvariant.moc"
|
||||
|
|
|
|||
Loading…
Reference in New Issue