summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOlivier Goffart <ogoffart@woboq.com>2013-11-03 14:17:15 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-11-08 16:45:26 +0100
commit34d21610ba72ea775d47619c08086f8bb0e7160b (patch)
tree4e2e0190af953324fadd01f73a6b5b4e95206a2d
parent2ee97f505b29a8539685885a239477d4417cc76a (diff)
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>
-rw-r--r--src/corelib/kernel/qvariant.cpp57
-rw-r--r--tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp84
2 files changed, 129 insertions, 12 deletions
diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp
index 21743f99d4..69cfa7888f 100644
--- a/src/corelib/kernel/qvariant.cpp
+++ b/src/corelib/kernel/qvariant.cpp
@@ -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:
diff --git a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp
index a696b0ee1e..aef79e0c2f 100644
--- a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp
+++ b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp
@@ -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"