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
Olivier Goffart 2013-11-03 14:17:15 +01:00 committed by The Qt Project
parent 2ee97f505b
commit 34d21610ba
2 changed files with 129 additions and 12 deletions

View File

@ -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:

View File

@ -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"