summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/kernel/qvariant.cpp34
-rw-r--r--tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp30
2 files changed, 51 insertions, 13 deletions
diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp
index 29af0647ea..b73c83bc49 100644
--- a/src/corelib/kernel/qvariant.cpp
+++ b/src/corelib/kernel/qvariant.cpp
@@ -1459,7 +1459,11 @@ Q_CORE_EXPORT void QVariantPrivate::registerHandler(const int /* Modules::Names
/*!
\fn QVariant::QVariant(Type type)
- Constructs a null variant of type \a 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()
*/
@@ -3305,17 +3309,20 @@ bool QVariant::canConvert(int targetTypeId) const
/*!
Casts the variant to the requested type, \a targetTypeId. If the cast cannot be
- done, the variant is cleared. Returns \c true if the current type of
- the variant was successfully cast; otherwise returns \c false.
+ 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.
- \warning For historical reasons, converting a null QVariant results
- in a null value of the desired type (e.g., an empty string for
- QString) and a result of false.
+ \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(), clear()
*/
@@ -3332,7 +3339,8 @@ bool QVariant::convert(int targetTypeId)
return false;
create(targetTypeId, 0);
- if (oldValue.isNull())
+ // Fail if the value is not initialized or was forced null by a previous failed convert.
+ if (oldValue.d.is_null)
return false;
if ((QMetaType::typeFlags(oldValue.userType()) & QMetaType::PointerToQObject) && (QMetaType::typeFlags(targetTypeId) & QMetaType::PointerToQObject)) {
@@ -3732,12 +3740,14 @@ void* QVariant::data()
/*!
Returns \c true if this is a null variant, false otherwise. A variant is
- considered null if it contains a default constructed value or a built-in
- type instance that has an isNull method, in which case the result
- would be the same as calling isNull on the wrapped object.
+ considered null if it contains no initialized value or it contains an instance
+ of 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.
- \warning The result of the function doesn't affect == operator, which means
- that two values can be equal even if one of them is null and another is not.
+ \sa QVariant(Type), convert(int)
*/
bool QVariant::isNull() const
{
diff --git a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp
index bddc1cd2b2..906587248e 100644
--- a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp
+++ b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp
@@ -277,6 +277,8 @@ private slots:
void compareSanity();
void compareRich();
+ void nullConvert();
+
void accessSequentialContainerKey();
private:
@@ -4861,6 +4863,33 @@ void tst_QVariant::compareRich()
<< QStringLiteral("d"));
}
+void tst_QVariant::nullConvert()
+{
+ // Test quirks with QVariants different types of null states.
+
+ // null variant with no initialized value
+ QVariant nullVar(QVariant::String);
+ QVERIFY(nullVar.isValid());
+ QVERIFY(nullVar.isNull());
+ // We can not convert a variant with no value
+ QVERIFY(!nullVar.convert(QVariant::Url));
+ QCOMPARE(nullVar.type(), QVariant::Url);
+ QVERIFY(nullVar.isNull());
+
+ // variant initialized with null value
+ QVariant nullStr = QVariant::fromValue(QString());
+ QVERIFY(nullStr.isValid());
+ QVERIFY(nullStr.isNull());
+ // We can convert an initialized null value however
+ QVERIFY(nullStr.convert(QVariant::Url));
+ QCOMPARE(nullStr.type(), QVariant::Url);
+ QVERIFY(nullStr.isValid());
+ // QUrl does not have an isNull method
+ QVERIFY(!nullStr.isNull());
+ // The URL is not valid however
+ QVERIFY(!nullStr.toUrl().isValid());
+}
+
void tst_QVariant::accessSequentialContainerKey()
{
QString nameResult;
@@ -4885,6 +4914,5 @@ void tst_QVariant::accessSequentialContainerKey()
QCOMPARE(nameResult, QStringLiteral("Seven"));
}
-
QTEST_MAIN(tst_QVariant)
#include "tst_qvariant.moc"