Allow conversion of QVariants with real null values
Update documentation to be clearer on the special null variant state with no value as opposed to a variant with a null value, and only block conversions of the former. Change-Id: I24fd50285414e049de87de54a63700a89bd5adf1 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
bf6ae8406b
commit
bef7e4a222
@ -1459,7 +1459,11 @@ Q_CORE_EXPORT void QVariantPrivate::registerHandler(const int /* Modules::Names
|
|||||||
/*!
|
/*!
|
||||||
\fn QVariant::QVariant(Type type)
|
\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
|
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
|
done, the variant is still changed to the requested type, but is left in a cleared
|
||||||
the variant was successfully cast; otherwise returns \c false.
|
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
|
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
|
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
|
by \a targetTypeId would succeed. Note that this only works for QObject subclasses
|
||||||
which use the Q_OBJECT macro.
|
which use the Q_OBJECT macro.
|
||||||
|
|
||||||
\warning For historical reasons, converting a null QVariant results
|
\note converting QVariants that are null due to not being initialized or having
|
||||||
in a null value of the desired type (e.g., an empty string for
|
failed a previous conversion will always fail, changing the type, remaining null,
|
||||||
QString) and a result of false.
|
and returning \c false.
|
||||||
|
|
||||||
\sa canConvert(), clear()
|
\sa canConvert(), clear()
|
||||||
*/
|
*/
|
||||||
@ -3332,7 +3339,8 @@ bool QVariant::convert(int targetTypeId)
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
create(targetTypeId, 0);
|
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;
|
return false;
|
||||||
|
|
||||||
if ((QMetaType::typeFlags(oldValue.userType()) & QMetaType::PointerToQObject) && (QMetaType::typeFlags(targetTypeId) & QMetaType::PointerToQObject)) {
|
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
|
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
|
considered null if it contains no initialized value or it contains an instance
|
||||||
type instance that has an isNull method, in which case the result
|
of built-in type that has an isNull method, in which case the result would be
|
||||||
would be the same as calling isNull on the wrapped object.
|
the same as calling isNull on the wrapped object.
|
||||||
|
|
||||||
\warning The result of the function doesn't affect == operator, which means
|
\warning Null variants is not a single state and two null variants may easily
|
||||||
that two values can be equal even if one of them is null and another is not.
|
return \c false on the == operator if they do not contain similar null values.
|
||||||
|
|
||||||
|
\sa QVariant(Type), convert(int)
|
||||||
*/
|
*/
|
||||||
bool QVariant::isNull() const
|
bool QVariant::isNull() const
|
||||||
{
|
{
|
||||||
|
@ -277,6 +277,8 @@ private slots:
|
|||||||
void compareSanity();
|
void compareSanity();
|
||||||
void compareRich();
|
void compareRich();
|
||||||
|
|
||||||
|
void nullConvert();
|
||||||
|
|
||||||
void accessSequentialContainerKey();
|
void accessSequentialContainerKey();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -4861,6 +4863,33 @@ void tst_QVariant::compareRich()
|
|||||||
<< QStringLiteral("d"));
|
<< 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()
|
void tst_QVariant::accessSequentialContainerKey()
|
||||||
{
|
{
|
||||||
QString nameResult;
|
QString nameResult;
|
||||||
@ -4885,6 +4914,5 @@ void tst_QVariant::accessSequentialContainerKey()
|
|||||||
QCOMPARE(nameResult, QStringLiteral("Seven"));
|
QCOMPARE(nameResult, QStringLiteral("Seven"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
QTEST_MAIN(tst_QVariant)
|
QTEST_MAIN(tst_QVariant)
|
||||||
#include "tst_qvariant.moc"
|
#include "tst_qvariant.moc"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user