Fix QVariant associative container conversion from built-in types.

Task-number: QTBUG-41403
Change-Id: I9dab0f9450cac11678eb6d20abd2dd08e86e0900
Reviewed-by: Stephen Kelly <steveire@gmail.com>
This commit is contained in:
Jędrzej Nowacki 2014-10-21 17:08:57 +02:00
parent 9c92a18b97
commit 8c4deff51c
3 changed files with 63 additions and 3 deletions

View File

@ -2109,6 +2109,21 @@ namespace QtPrivate {
}; };
} }
namespace QtMetaTypePrivate {
inline Q_DECL_CONSTEXPR bool isBuiltinSequentialType(int typeId)
{
return typeId == qMetaTypeId<QStringList>()
|| typeId == qMetaTypeId<QByteArrayList>()
|| typeId == qMetaTypeId<QVariantList>();
}
inline Q_DECL_CONSTEXPR bool isBuiltinAssociativeType(int typeId)
{
return typeId == qMetaTypeId<QVariantHash>()
|| typeId == qMetaTypeId<QVariantMap>();
}
} // QtMetaTypePrivate
QT_END_NAMESPACE QT_END_NAMESPACE
#endif // QMETATYPE_H #endif // QMETATYPE_H

View File

@ -736,7 +736,7 @@ namespace QtPrivate {
{ {
static QVariantList invoke(const QVariant &v) static QVariantList invoke(const QVariant &v)
{ {
if (v.userType() == qMetaTypeId<QStringList>() || v.userType() == qMetaTypeId<QByteArrayList>() || QMetaType::hasRegisteredConverterFunction(v.userType(), qMetaTypeId<QtMetaTypePrivate::QSequentialIterableImpl>())) { if (QtMetaTypePrivate::isBuiltinSequentialType(v.userType()) || QMetaType::hasRegisteredConverterFunction(v.userType(), qMetaTypeId<QtMetaTypePrivate::QSequentialIterableImpl>())) {
QSequentialIterable iter = QVariantValueHelperInterface<QSequentialIterable>::invoke(v); QSequentialIterable iter = QVariantValueHelperInterface<QSequentialIterable>::invoke(v);
QVariantList l; QVariantList l;
l.reserve(iter.size()); l.reserve(iter.size());
@ -752,7 +752,7 @@ namespace QtPrivate {
{ {
static QVariantHash invoke(const QVariant &v) static QVariantHash invoke(const QVariant &v)
{ {
if (QMetaType::hasRegisteredConverterFunction(v.userType(), qMetaTypeId<QtMetaTypePrivate::QAssociativeIterableImpl>())) { if (QtMetaTypePrivate::isBuiltinAssociativeType(v.userType()) || QMetaType::hasRegisteredConverterFunction(v.userType(), qMetaTypeId<QtMetaTypePrivate::QAssociativeIterableImpl>())) {
QAssociativeIterable iter = QVariantValueHelperInterface<QAssociativeIterable>::invoke(v); QAssociativeIterable iter = QVariantValueHelperInterface<QAssociativeIterable>::invoke(v);
QVariantHash l; QVariantHash l;
l.reserve(iter.size()); l.reserve(iter.size());
@ -768,7 +768,7 @@ namespace QtPrivate {
{ {
static QVariantMap invoke(const QVariant &v) static QVariantMap invoke(const QVariant &v)
{ {
if (QMetaType::hasRegisteredConverterFunction(v.userType(), qMetaTypeId<QtMetaTypePrivate::QAssociativeIterableImpl>())) { if (QtMetaTypePrivate::isBuiltinAssociativeType(v.userType()) || QMetaType::hasRegisteredConverterFunction(v.userType(), qMetaTypeId<QtMetaTypePrivate::QAssociativeIterableImpl>())) {
QAssociativeIterable iter = QVariantValueHelperInterface<QAssociativeIterable>::invoke(v); QAssociativeIterable iter = QVariantValueHelperInterface<QAssociativeIterable>::invoke(v);
QVariantMap l; QVariantMap l;
for (QAssociativeIterable::const_iterator it = iter.begin(), end = iter.end(); it != end; ++it) for (QAssociativeIterable::const_iterator it = iter.begin(), end = iter.end(); it != end; ++it)

View File

@ -35,6 +35,7 @@
#include <qvariant.h> #include <qvariant.h>
#include <qbitarray.h> #include <qbitarray.h>
#include <qbytearraylist.h>
#include <qdatetime.h> #include <qdatetime.h>
#include <qmap.h> #include <qmap.h>
#include <qiodevice.h> #include <qiodevice.h>
@ -208,6 +209,7 @@ private slots:
void convertBoolToByteArray_data() const; void convertBoolToByteArray_data() const;
void convertByteArrayToBool() const; void convertByteArrayToBool() const;
void convertByteArrayToBool_data() const; void convertByteArrayToBool_data() const;
void convertIterables() const;
void toIntFromQString() const; void toIntFromQString() const;
void toIntFromDouble() const; void toIntFromDouble() const;
void setValue(); void setValue();
@ -2838,6 +2840,49 @@ void tst_QVariant::convertByteArrayToBool_data() const
<< QByteArray("true"); << QByteArray("true");
} }
void tst_QVariant::convertIterables() const
{
{
QStringList list;
list.append("Hello");
QCOMPARE(QVariant::fromValue(list).value<QVariantList>().count(), list.count());
}
{
QByteArrayList list;
list.append("Hello");
QCOMPARE(QVariant::fromValue(list).value<QVariantList>().count(), list.count());
}
{
QVariantList list;
list.append("World");
QCOMPARE(QVariant::fromValue(list).value<QVariantList>().count(), list.count());
}
{
QMap<QString, int> map;
map.insert("3", 4);
QCOMPARE(QVariant::fromValue(map).value<QVariantHash>().count(), map.count());
QCOMPARE(QVariant::fromValue(map).value<QVariantMap>().count(), map.count());
}
{
QVariantMap map;
map.insert("3", 4);
QCOMPARE(QVariant::fromValue(map).value<QVariantHash>().count(), map.count());
QCOMPARE(QVariant::fromValue(map).value<QVariantMap>().count(), map.count());
}
{
QHash<QString, int> hash;
hash.insert("3", 4);
QCOMPARE(QVariant::fromValue(hash).value<QVariantHash>().count(), hash.count());
QCOMPARE(QVariant::fromValue(hash).value<QVariantMap>().count(), hash.count());
}
{
QVariantHash hash;
hash.insert("3", 4);
QCOMPARE(QVariant::fromValue(hash).value<QVariantHash>().count(), hash.count());
QCOMPARE(QVariant::fromValue(hash).value<QVariantMap>().count(), hash.count());
}
}
/*! /*!
We verify that: We verify that:
1. Converting the string "9.9" to int fails. This is the behavior of 1. Converting the string "9.9" to int fails. This is the behavior of