summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2020-07-14 12:26:16 +0200
committerLars Knoll <lars.knoll@qt.io>2020-08-24 00:18:24 +0200
commit9d36032370f7b81279ff8774afd7dea4ea57ee6a (patch)
treed750ccd6cd317f056d13495a03fde5881134ec89
parent2d3b31171d8fce2ab364ca2ceea4e75020933334 (diff)
Implement QMetaType::canConvert() and use it in QVariant
Use the fact that we return the conversion function as a lambda to find out reliably whether a conversion between two types can be done. This requires some minor adjustments to our tests: * Nothing can convert to an unknown type and vice versa * Adjust results to the fact that we don't convert from char to QString anymore (where the old method was incorrect) * QStringList->QString requires some adjustments, as we only convert if the string list has exactly one element. For now we return true in canConvert(), but the conversion behavior in this case is something we should rethink, as it is very surprising. Change-Id: I3f5f87ee9cb99d690f5a7d13b13d6a6313d8038e Reviewed-by: Maurice Kalinowski <maurice.kalinowski@qt.io>
-rw-r--r--src/corelib/kernel/qmetatype.cpp142
-rw-r--r--src/corelib/kernel/qmetatype.h1
-rw-r--r--src/corelib/kernel/qvariant.cpp396
-rw-r--r--tests/auto/corelib/io/qsettings/tst_qsettings.cpp3
-rw-r--r--tests/auto/corelib/kernel/qvariant/CMakeLists.txt1
-rw-r--r--tests/auto/corelib/kernel/qvariant/qvariant.pro2
-rw-r--r--tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp16
7 files changed, 159 insertions, 402 deletions
diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp
index 446511c14d..e8f359a366 100644
--- a/src/corelib/kernel/qmetatype.cpp
+++ b/src/corelib/kernel/qmetatype.cpp
@@ -1829,6 +1829,18 @@ static bool convertToEnum(const void *from, int fromTypeId, void *to, const QMet
}
}
+#ifndef QT_BOOTSTRAPPED
+static bool canConvertMetaObject(const QMetaType &fromType, const QMetaType &toType)
+{
+ if ((fromType.flags() & QMetaType::PointerToQObject) && (toType.flags() & QMetaType::PointerToQObject)) {
+ return fromType.metaObject()->inherits(toType.metaObject()) ||
+ toType.metaObject()->inherits(fromType.metaObject());
+ }
+ return false;
+}
+#endif
+
+
/*!
Converts the object at \a from from \a fromTypeId to the preallocated space at \a to
typed \a toTypeId. Returns \c true, if the conversion succeeded, otherwise false.
@@ -1836,6 +1848,16 @@ static bool convertToEnum(const void *from, int fromTypeId, void *to, const QMet
*/
bool QMetaType::convert(const void *from, int fromTypeId, void *to, int toTypeId)
{
+ if (fromTypeId == UnknownType || toTypeId == UnknownType)
+ return false;
+
+ if (fromTypeId == toTypeId) {
+ // just make a copy
+ QMetaType(fromTypeId).destruct(to);
+ QMetaType(fromTypeId).construct(to, from);
+ return true;
+ }
+
if (auto moduleHelper = qModuleHelperForType(qMax(fromTypeId, toTypeId))) {
if (moduleHelper->convert(from, fromTypeId, to, toTypeId))
return true;
@@ -1862,6 +1884,126 @@ bool QMetaType::convert(const void *from, int fromTypeId, void *to, int toTypeId
}
/*!
+ Returns \c true if QMetaType::convert can convert from \a fromType to
+ \a toType.
+
+ The following conversions are supported by Qt:
+
+ \table
+ \header \li Type \li Automatically Cast To
+ \row \li \l QMetaType::Bool \li \l QMetaType::QChar, \l QMetaType::Double,
+ \l QMetaType::Int, \l QMetaType::LongLong, \l QMetaType::QString,
+ \l QMetaType::UInt, \l QMetaType::ULongLong
+ \row \li \l QMetaType::QByteArray \li \l QMetaType::Double,
+ \l QMetaType::Int, \l QMetaType::LongLong, \l QMetaType::QString,
+ \l QMetaType::UInt, \l QMetaType::ULongLong, \l QMetaType::QUuid
+ \row \li \l QMetaType::QChar \li \l QMetaType::Bool, \l QMetaType::Int,
+ \l QMetaType::UInt, \l QMetaType::LongLong, \l QMetaType::ULongLong
+ \row \li \l QMetaType::QColor \li \l QMetaType::QString
+ \row \li \l QMetaType::QDate \li \l QMetaType::QDateTime,
+ \l QMetaType::QString
+ \row \li \l QMetaType::QDateTime \li \l QMetaType::QDate,
+ \l QMetaType::QString, \l QMetaType::QTime
+ \row \li \l QMetaType::Double \li \l QMetaType::Bool, \l QMetaType::Int,
+ \l QMetaType::LongLong, \l QMetaType::QString, \l QMetaType::UInt,
+ \l QMetaType::ULongLong
+ \row \li \l QMetaType::QFont \li \l QMetaType::QString
+ \row \li \l QMetaType::Int \li \l QMetaType::Bool, \l QMetaType::QChar,
+ \l QMetaType::Double, \l QMetaType::LongLong, \l QMetaType::QString,
+ \l QMetaType::UInt, \l QMetaType::ULongLong
+ \row \li \l QMetaType::QKeySequence \li \l QMetaType::Int,
+ \l QMetaType::QString
+ \row \li \l QMetaType::QVariantList \li \l QMetaType::QStringList (if the
+ list's items can be converted to QStrings)
+ \row \li \l QMetaType::LongLong \li \l QMetaType::Bool,
+ \l QMetaType::QByteArray, \l QMetaType::QChar, \l QMetaType::Double,
+ \l QMetaType::Int, \l QMetaType::QString, \l QMetaType::UInt,
+ \l QMetaType::ULongLong
+ \row \li \l QMetaType::QPoint \li QMetaType::QPointF
+ \row \li \l QMetaType::QRect \li QMetaType::QRectF
+ \row \li \l QMetaType::QString \li \l QMetaType::Bool,
+ \l QMetaType::QByteArray, \l QMetaType::QChar, \l QMetaType::QColor,
+ \l QMetaType::QDate, \l QMetaType::QDateTime, \l QMetaType::Double,
+ \l QMetaType::QFont, \l QMetaType::Int, \l QMetaType::QKeySequence,
+ \l QMetaType::LongLong, \l QMetaType::QStringList, \l QMetaType::QTime,
+ \l QMetaType::UInt, \l QMetaType::ULongLong, \l QMetaType::QUuid
+ \row \li \l QMetaType::QStringList \li \l QMetaType::QVariantList,
+ \l QMetaType::QString (if the list contains exactly one item)
+ \row \li \l QMetaType::QTime \li \l QMetaType::QString
+ \row \li \l QMetaType::UInt \li \l QMetaType::Bool, \l QMetaType::QChar,
+ \l QMetaType::Double, \l QMetaType::Int, \l QMetaType::LongLong,
+ \l QMetaType::QString, \l QMetaType::ULongLong
+ \row \li \l QMetaType::ULongLong \li \l QMetaType::Bool,
+ \l QMetaType::QChar, \l QMetaType::Double, \l QMetaType::Int,
+ \l QMetaType::LongLong, \l QMetaType::QString, \l QMetaType::UInt
+ \row \li \l QMetaType::QUuid \li \l QMetaType::QByteArray, \l QMetaType::QString
+ \endtable
+
+ Casting between primitive type (int, float, bool etc.) is supported.
+
+ Converting between pointers of types derived from QObject will also return true for this
+ function if a qobject_cast from the type described by \a fromType to the type described
+ by \a toType would succeed.
+
+ A cast from a sequential container will also return true for this
+ function if the \a toType is QVariantList.
+
+ Similarly, a cast from an associative container will also return true for this
+ function the \a toType is QVariantHash or QVariantMap.
+
+ \sa convert(), QSequentialIterable, Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE(), QAssociativeIterable,
+ Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE()
+*/
+bool QMetaType::canConvert(const QMetaType &fromType, const QMetaType &toType)
+{
+ int fromTypeId = fromType.id();
+ int toTypeId = toType.id();
+
+ if (fromTypeId == UnknownType || toTypeId == UnknownType)
+ return false;
+
+ if (fromTypeId == toTypeId)
+ return true;
+
+ if (auto moduleHelper = qModuleHelperForType(qMax(fromTypeId, toTypeId))) {
+ if (moduleHelper->convert(nullptr, fromTypeId, nullptr, toTypeId))
+ return true;
+ }
+ const QMetaType::ConverterFunction * const f =
+ customTypesConversionRegistry()->function(qMakePair(fromTypeId, toTypeId));
+ if (f)
+ return true;
+
+ if (fromType.flags() & QMetaType::IsEnumeration) {
+ if (toTypeId == QMetaType::QString || toTypeId == QMetaType::QByteArray)
+ return true;
+ return QMetaType::canConvert(QMetaType(LongLong), toType);
+ }
+ if (toType.flags() & QMetaType::IsEnumeration) {
+ if (fromTypeId == QMetaType::QString || fromTypeId == QMetaType::QByteArray)
+ return true;
+ return QMetaType::canConvert(fromType, QMetaType(LongLong));
+ }
+ if (toTypeId == Nullptr && fromType.flags() & QMetaType::IsPointer)
+ return true;
+#ifndef QT_BOOTSTRAPPED
+ if (canConvertMetaObject(fromType, toType))
+ return true;
+#endif
+
+ return false;
+}
+
+/*!
+ bool QMetaType::compare(const void *lhs, const void *rhs, int typeId, int* result)
+ \deprecated Use the non-static compare method instead
+
+ Compares the objects at \a lhs and \a rhs. Both objects need to be of type \a typeId.
+ \a result is set to less than, equal to or greater than zero, if \a lhs is less than, equal to
+ or greater than \a rhs. Returns \c true, if the comparison succeeded, otherwise \c false.
+*/
+
+/*!
\fn bool QMetaType::hasRegisteredConverterFunction()
Returns \c true, if the meta type system has a registered conversion from type From to type To.
\since 5.2
diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h
index b4217bc3a1..4a3ed1affc 100644
--- a/src/corelib/kernel/qmetatype.h
+++ b/src/corelib/kernel/qmetatype.h
@@ -524,6 +524,7 @@ public:
#endif
static bool convert(const void *from, int fromTypeId, void *to, int toTypeId);
+ static bool canConvert(const QMetaType &fromType, const QMetaType &toType);
#if QT_DEPRECATED_SINCE(6, 0)
QT_DEPRECATED_VERSION_6_0
static bool compare(const void *lhs, const void *rhs, int typeId, int *result)
diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp
index 4f0664dc28..c16e4a0e06 100644
--- a/src/corelib/kernel/qvariant.cpp
+++ b/src/corelib/kernel/qvariant.cpp
@@ -1962,219 +1962,17 @@ QVariantList QVariant::toList() const
return qVariantToHelper<QVariantList>(d);
}
-
-static const quint32 qCanConvertMatrix[QMetaType::LastCoreType + 1] =
-{
-/*Invalid*/ 0,
-
-/*Bool*/ 1 << QMetaType::Double | 1 << QMetaType::Int | 1 << QMetaType::UInt
- | 1 << QMetaType::LongLong | 1 << QMetaType::ULongLong | 1 << QMetaType::QByteArray
- | 1 << QMetaType::QString | 1 << QMetaType::QChar,
-
-/*Int*/ 1 << QMetaType::UInt | 1 << QMetaType::QString | 1 << QMetaType::Double
- | 1 << QMetaType::Bool | 1 << QMetaType::LongLong | 1 << QMetaType::ULongLong
- | 1 << QMetaType::QChar | 1 << QMetaType::QByteArray | 1 << QMetaType::Int,
-
-/*UInt*/ 1 << QMetaType::Int | 1 << QMetaType::QString | 1 << QMetaType::Double
- | 1 << QMetaType::Bool | 1 << QMetaType::LongLong | 1 << QMetaType::ULongLong
- | 1 << QMetaType::QChar | 1 << QMetaType::QByteArray,
-
-/*LLong*/ 1 << QMetaType::Int | 1 << QMetaType::QString | 1 << QMetaType::Double
- | 1 << QMetaType::Bool | 1 << QMetaType::UInt | 1 << QMetaType::ULongLong
- | 1 << QMetaType::QChar | 1 << QMetaType::QByteArray,
-
-/*ULlong*/ 1 << QMetaType::Int | 1 << QMetaType::QString | 1 << QMetaType::Double
- | 1 << QMetaType::Bool | 1 << QMetaType::UInt | 1 << QMetaType::LongLong
- | 1 << QMetaType::QChar | 1 << QMetaType::QByteArray,
-
-/*double*/ 1 << QMetaType::Int | 1 << QMetaType::QString | 1 << QMetaType::ULongLong
- | 1 << QMetaType::Bool | 1 << QMetaType::UInt | 1 << QMetaType::LongLong
- | 1 << QMetaType::QByteArray,
-
-/*QChar*/ 1 << QMetaType::Int | 1 << QMetaType::UInt | 1 << QMetaType::LongLong
- | 1 << QMetaType::ULongLong,
-
-/*QMap*/ 0,
-
-/*QList*/ 1 << QMetaType::QStringList,
-
-/*QString*/ 1 << QMetaType::QStringList | 1 << QMetaType::QByteArray | 1 << QMetaType::Int
- | 1 << QMetaType::UInt | 1 << QMetaType::Bool | 1 << QMetaType::Double
- | 1 << QMetaType::QDate | 1 << QMetaType::QTime | 1 << QMetaType::QDateTime
- | 1 << QMetaType::LongLong | 1 << QMetaType::ULongLong | 1 << QMetaType::QChar
- | 1 << QMetaType::QUrl | 1 << QMetaType::QUuid,
-
-/*QStringList*/ 1 << QMetaType::QVariantList | 1 << QMetaType::QString,
-
-/*QByteArray*/ 1 << QMetaType::QString | 1 << QMetaType::Int | 1 << QMetaType::UInt | 1 << QMetaType::Bool
- | 1 << QMetaType::Double | 1 << QMetaType::LongLong | 1 << QMetaType::ULongLong
- | 1 << QMetaType::QUuid,
-
-/*QBitArray*/ 0,
-
-/*QDate*/ 1 << QMetaType::QString | 1 << QMetaType::QDateTime,
-
-/*QTime*/ 1 << QMetaType::QString | 1 << QMetaType::QDateTime,
-
-/*QDateTime*/ 1 << QMetaType::QString | 1 << QMetaType::QDate,
-
-/*QUrl*/ 1 << QMetaType::QString,
-
-/*QLocale*/ 0,
-
-/*QRect*/ 1 << QMetaType::QRectF,
-
-/*QRectF*/ 1 << QMetaType::QRect,
-
-/*QSize*/ 1 << QMetaType::QSizeF,
-
-/*QSizeF*/ 1 << QMetaType::QSize,
-
-/*QLine*/ 1 << QMetaType::QLineF,
-
-/*QLineF*/ 1 << QMetaType::QLine,
-
-/*QPoint*/ 1 << QMetaType::QPointF,
-
-/*QPointF*/ 1 << QMetaType::QPoint,
-
-/*unused, was: QRegExp*/ 0,
-
-/*QHash*/ 0,
-
-/*QEasingCurve*/ 0,
-
-/*QUuid*/ 1 << QMetaType::QString | 1 << QMetaType::QByteArray,
-};
-static const size_t qCanConvertMatrixMaximumTargetType = 8 * sizeof(*qCanConvertMatrix);
-
-#ifndef QT_BOOTSTRAPPED
-/*
- Returns \c true if from inherits to.
-*/
-static bool canConvertMetaObject(const QMetaObject *from, const QMetaObject *to)
-{
- if (from && to == &QObject::staticMetaObject)
- return true;
-
- while (from) {
- if (from == to)
- return true;
- from = from->superClass();
- }
-
- return false;
-}
-#endif
-
-static bool canConvertMetaObject(int fromId, int toId, QObject *fromObject)
-{
-#ifndef QT_BOOTSTRAPPED
- QMetaType toType(toId);
- if ((QMetaType::typeFlags(fromId) & QMetaType::PointerToQObject) && (toType.flags() & QMetaType::PointerToQObject)) {
- if (!fromObject)
- return true;
- return canConvertMetaObject(fromObject->metaObject(), toType.metaObject());
- }
-#else
- Q_UNUSED(fromId);
- Q_UNUSED(toId);
- Q_UNUSED(fromObject);
-#endif
- return false;
-}
-
-
/*!
Returns \c true if the variant's type can be cast to the requested
type, \a targetTypeId. Such casting is done automatically when calling the
toInt(), toBool(), ... methods.
- The following casts are done automatically:
-
- \table
- \header \li Type \li Automatically Cast To
- \row \li \l QMetaType::Bool \li \l QMetaType::QChar, \l QMetaType::Double,
- \l QMetaType::Int, \l QMetaType::LongLong, \l QMetaType::QString,
- \l QMetaType::UInt, \l QMetaType::ULongLong
- \row \li \l QMetaType::QByteArray \li \l QMetaType::Double,
- \l QMetaType::Int, \l QMetaType::LongLong, \l QMetaType::QString,
- \l QMetaType::UInt, \l QMetaType::ULongLong, \l QMetaType::QUuid
- \row \li \l QMetaType::QChar \li \l QMetaType::Bool, \l QMetaType::Int,
- \l QMetaType::UInt, \l QMetaType::LongLong, \l QMetaType::ULongLong
- \row \li \l QMetaType::QColor \li \l QMetaType::QString
- \row \li \l QMetaType::QDate \li \l QMetaType::QDateTime,
- \l QMetaType::QString
- \row \li \l QMetaType::QDateTime \li \l QMetaType::QDate,
- \l QMetaType::QString, \l QMetaType::QTime
- \row \li \l QMetaType::Double \li \l QMetaType::Bool, \l QMetaType::Int,
- \l QMetaType::LongLong, \l QMetaType::QString, \l QMetaType::UInt,
- \l QMetaType::ULongLong
- \row \li \l QMetaType::QFont \li \l QMetaType::QString
- \row \li \l QMetaType::Int \li \l QMetaType::Bool, \l QMetaType::QChar,
- \l QMetaType::Double, \l QMetaType::LongLong, \l QMetaType::QString,
- \l QMetaType::UInt, \l QMetaType::ULongLong
- \row \li \l QMetaType::QKeySequence \li \l QMetaType::Int,
- \l QMetaType::QString
- \row \li \l QMetaType::QVariantList \li \l QMetaType::QStringList (if the
- list's items can be converted to QStrings)
- \row \li \l QMetaType::LongLong \li \l QMetaType::Bool,
- \l QMetaType::QByteArray, \l QMetaType::QChar, \l QMetaType::Double,
- \l QMetaType::Int, \l QMetaType::QString, \l QMetaType::UInt,
- \l QMetaType::ULongLong
- \row \li \l QMetaType::QPoint \li QMetaType::QPointF
- \row \li \l QMetaType::QRect \li QMetaType::QRectF
- \row \li \l QMetaType::QString \li \l QMetaType::Bool,
- \l QMetaType::QByteArray, \l QMetaType::QChar, \l QMetaType::QColor,
- \l QMetaType::QDate, \l QMetaType::QDateTime, \l QMetaType::Double,
- \l QMetaType::QFont, \l QMetaType::Int, \l QMetaType::QKeySequence,
- \l QMetaType::LongLong, \l QMetaType::QStringList, \l QMetaType::QTime,
- \l QMetaType::UInt, \l QMetaType::ULongLong, \l QMetaType::QUuid
- \row \li \l QMetaType::QStringList \li \l QMetaType::QVariantList,
- \l QMetaType::QString (if the list contains exactly one item)
- \row \li \l QMetaType::QTime \li \l QMetaType::QString
- \row \li \l QMetaType::UInt \li \l QMetaType::Bool, \l QMetaType::QChar,
- \l QMetaType::Double, \l QMetaType::Int, \l QMetaType::LongLong,
- \l QMetaType::QString, \l QMetaType::ULongLong
- \row \li \l QMetaType::ULongLong \li \l QMetaType::Bool,
- \l QMetaType::QChar, \l QMetaType::Double, \l QMetaType::Int,
- \l QMetaType::LongLong, \l QMetaType::QString, \l QMetaType::UInt
- \row \li \l QMetaType::QUuid \li \l QMetaType::QByteArray, \l QMetaType::QString
- \endtable
-
- A QVariant containing a pointer to a type derived from QObject will also 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.
-
- A QVariant containing a sequential container will also return true for this
- function if the \a targetTypeId is QVariantList. It is possible to iterate over
- the contents of the container without extracting it as a (copied) QVariantList:
-
- \snippet code/src_corelib_kernel_qvariant.cpp 9
-
- This requires that the value_type of the container is itself a metatype.
-
- Similarly, a QVariant containing a sequential container will also return true for this
- function the \a targetTypeId is QVariantHash or QVariantMap. It is possible to iterate over
- the contents of the container without extracting it as a (copied) QVariantHash or QVariantMap:
-
- \snippet code/src_corelib_kernel_qvariant.cpp 10
-
- \sa convert(), QSequentialIterable, Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE(), QAssociativeIterable,
- Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE()
+ \sa QMetaType::canConvert()
*/
bool QVariant::canConvert(int targetTypeId) const
{
- if (d.typeId() == targetTypeId)
- return true;
-
-#if QT_CONFIG(itemmodel)
- if ((targetTypeId == QMetaType::QModelIndex
- && d.typeId() == QMetaType::QPersistentModelIndex)
- || (targetTypeId == QMetaType::QPersistentModelIndex
- && d.typeId() == QMetaType::QModelIndex))
+ if (d.typeId() == targetTypeId && targetTypeId != QMetaType::UnknownType)
return true;
-#endif
if (targetTypeId == QMetaType::QVariantList
&& (d.typeId() == QMetaType::QVariantList || d.typeId() == QMetaType::QStringList
@@ -2197,193 +1995,7 @@ bool QVariant::canConvert(int targetTypeId) const
return true;
}
- if ((d.typeId() >= QMetaType::LastCoreType|| targetTypeId >= QMetaType::LastCoreType)
- && QMetaType::hasRegisteredConverterFunction(d.typeId(), targetTypeId)) {
- return true;
- }
-
- // TODO Reimplement this function, currently it works but it is a historical mess.
- uint currentType = d.typeId();
- if (currentType == QMetaType::SChar || currentType == QMetaType::Char)
- currentType = QMetaType::UInt;
- if (targetTypeId == QMetaType::SChar || currentType == QMetaType::Char)
- targetTypeId = QMetaType::UInt;
- if (currentType == QMetaType::Short || currentType == QMetaType::UShort)
- currentType = QMetaType::Int;
- if (targetTypeId == QMetaType::Short || currentType == QMetaType::UShort)
- targetTypeId = QMetaType::Int;
- if (currentType == QMetaType::Float)
- currentType = QMetaType::Double;
- if (targetTypeId == QMetaType::Float)
- targetTypeId = QMetaType::Double;
-
- if (currentType == uint(targetTypeId))
- return true;
-
- if (targetTypeId < 0)
- return false;
- if (targetTypeId >= QMetaType::User) {
- if (QMetaType::typeFlags(targetTypeId) & QMetaType::IsEnumeration) {
- targetTypeId = QMetaType::Int;
- } else {
- return canConvertMetaObject(currentType, targetTypeId, d.get<QObject *>());
- }
- }
-
- if (currentType == QMetaType::QJsonValue || targetTypeId == QMetaType::QJsonValue) {
- switch (currentType == QMetaType::QJsonValue ? targetTypeId : currentType) {
- case QMetaType::Nullptr:
- case QMetaType::QString:
- case QMetaType::Bool:
- case QMetaType::Int:
- case QMetaType::UInt:
- case QMetaType::Double:
- case QMetaType::Float:
- case QMetaType::ULong:
- case QMetaType::Long:
- case QMetaType::LongLong:
- case QMetaType::ULongLong:
- case QMetaType::UShort:
- case QMetaType::UChar:
- case QMetaType::Char:
- case QMetaType::SChar:
- case QMetaType::Short:
- case QMetaType::QVariantList:
- case QMetaType::QVariantMap:
- case QMetaType::QVariantHash:
- case QMetaType::QCborValue:
- case QMetaType::QCborArray:
- case QMetaType::QCborMap:
- return true;
- default:
- return false;
- }
- }
- if (currentType == QMetaType::QJsonArray)
- return targetTypeId == QMetaType::QVariantList || targetTypeId == QMetaType::QCborValue
- || targetTypeId == QMetaType::QCborArray;
- if (currentType == QMetaType::QJsonObject)
- return targetTypeId == QMetaType::QVariantMap || targetTypeId == QMetaType::QVariantHash
- || targetTypeId == QMetaType::QCborValue || targetTypeId == QMetaType::QCborMap;
-
- if (currentType == QMetaType::QCborValue || targetTypeId == QMetaType::QCborValue) {
- switch (currentType == QMetaType::QCborValue ? targetTypeId : currentType) {
- case QMetaType::UnknownType:
- case QMetaType::Nullptr:
- case QMetaType::Bool:
- case QMetaType::Int:
- case QMetaType::UInt:
- case QMetaType::Double:
- case QMetaType::Float:
- case QMetaType::ULong:
- case QMetaType::Long:
- case QMetaType::LongLong:
- case QMetaType::ULongLong:
- case QMetaType::UShort:
- case QMetaType::UChar:
- case QMetaType::Char:
- case QMetaType::SChar:
- case QMetaType::Short:
- case QMetaType::QString:
- case QMetaType::QByteArray:
- case QMetaType::QDateTime:
- case QMetaType::QUrl:
-#if QT_CONFIG(regularexpression)
- case QMetaType::QRegularExpression:
-#endif
- case QMetaType::QUuid:
- case QMetaType::QVariantList:
- case QMetaType::QVariantMap:
- case QMetaType::QVariantHash:
- case QMetaType::QJsonValue:
- case QMetaType::QJsonArray:
- case QMetaType::QJsonObject:
- case QMetaType::QJsonDocument:
- case QMetaType::QCborArray:
- case QMetaType::QCborMap:
- case QMetaType::QCborSimpleType:
- return true;
- default:
- return false;
- }
- }
- if (currentType == QMetaType::QCborArray)
- return targetTypeId == QMetaType::QVariantList || targetTypeId == QMetaType::QCborValue
- || targetTypeId == QMetaType::QJsonArray;
- if (currentType == QMetaType::QCborMap)
- return targetTypeId == QMetaType::QVariantMap || targetTypeId == QMetaType::QVariantHash
- || targetTypeId == QMetaType::QCborValue || targetTypeId == QMetaType::QJsonObject;
-
- // FIXME It should be LastCoreType intead of Uuid
- if (currentType > int(QMetaType::QUuid) || targetTypeId > int(QMetaType::QUuid)) {
- switch (uint(targetTypeId)) {
- case QVariant::Int:
-#if QT_CONFIG(shortcut)
- if (currentType == QVariant::KeySequence)
- return true;
- Q_FALLTHROUGH();
-#endif
- case QVariant::UInt:
- case QVariant::LongLong:
- case QVariant::ULongLong:
- return currentType == QMetaType::ULong
- || currentType == QMetaType::Long
- || currentType == QMetaType::UShort
- || currentType == QMetaType::UChar
- || currentType == QMetaType::Char
- || currentType == QMetaType::SChar
- || currentType == QMetaType::Short
- || QMetaType::typeFlags(currentType) & QMetaType::IsEnumeration;
- case QVariant::Image:
- return currentType == QVariant::Pixmap || currentType == QVariant::Bitmap;
- case QVariant::Pixmap:
- return currentType == QVariant::Image || currentType == QVariant::Bitmap
- || currentType == QVariant::Brush;
- case QVariant::Bitmap:
- return currentType == QVariant::Pixmap || currentType == QVariant::Image;
- case QVariant::ByteArray:
- return currentType == QVariant::Color || currentType == QMetaType::Nullptr
- || ((QMetaType::typeFlags(currentType) & QMetaType::IsEnumeration) && QMetaType::metaObjectForType(currentType));
- case QVariant::String:
- return currentType == QVariant::Font
- || currentType == QVariant::Color || currentType == QMetaType::Nullptr
-#if QT_CONFIG(shortcut)
- || currentType == QVariant::KeySequence
-#endif
- || ((QMetaType::typeFlags(currentType) & QMetaType::IsEnumeration) && QMetaType::metaObjectForType(currentType));
-#if QT_CONFIG(shortcut)
- case QVariant::KeySequence:
- return currentType == QVariant::String || currentType == QVariant::Int;
-#endif
- case QVariant::Font:
- return currentType == QVariant::String;
- case QVariant::Color:
- return currentType == QVariant::String || currentType == QVariant::ByteArray
- || currentType == QVariant::Brush;
- case QVariant::Brush:
- return currentType == QVariant::Color || currentType == QVariant::Pixmap;
- case QMetaType::Long:
- case QMetaType::Char:
- case QMetaType::SChar:
- case QMetaType::UChar:
- case QMetaType::ULong:
- case QMetaType::Short:
- case QMetaType::UShort:
- return currentType == QVariant::Int
- || (currentType < qCanConvertMatrixMaximumTargetType
- && qCanConvertMatrix[QVariant::Int] & (1U << currentType))
- || QMetaType::typeFlags(currentType) & QMetaType::IsEnumeration;
- case QMetaType::QObjectStar:
- return canConvertMetaObject(currentType, targetTypeId, d.get<QObject *>());
- default:
- return false;
- }
- }
-
- if (targetTypeId == String && currentType == StringList)
- return d.get<QStringList>().count() == 1;
- return currentType < qCanConvertMatrixMaximumTargetType
- && qCanConvertMatrix[targetTypeId] & (1U << currentType);
+ return QMetaType::canConvert(d.type(), QMetaType(targetTypeId));
}
/*!
@@ -2409,7 +2021,7 @@ bool QVariant::canConvert(int targetTypeId) const
bool QVariant::convert(int targetTypeId)
{
if (d.typeId() == targetTypeId)
- return true;
+ return (targetTypeId != QMetaType::UnknownType);
QVariant oldValue = *this;
diff --git a/tests/auto/corelib/io/qsettings/tst_qsettings.cpp b/tests/auto/corelib/io/qsettings/tst_qsettings.cpp
index aa893309e8..a84825d1e6 100644
--- a/tests/auto/corelib/io/qsettings/tst_qsettings.cpp
+++ b/tests/auto/corelib/io/qsettings/tst_qsettings.cpp
@@ -929,7 +929,8 @@ void tst_QSettings::testIniParsing()
if ( settings.status() == QSettings::NoError ) { // else no point proceeding
QVariant v = settings.value(key);
- QVERIFY(v.canConvert(expect.type()));
+ if (expect.isValid())
+ QVERIFY(v.canConvert(expect.type()));
// check some types so as to give prettier error messages
if ( v.type() == QVariant::String ) {
QCOMPARE(v.toString(), expect.toString());
diff --git a/tests/auto/corelib/kernel/qvariant/CMakeLists.txt b/tests/auto/corelib/kernel/qvariant/CMakeLists.txt
index f1baaefe43..8b122a48e2 100644
--- a/tests/auto/corelib/kernel/qvariant/CMakeLists.txt
+++ b/tests/auto/corelib/kernel/qvariant/CMakeLists.txt
@@ -13,6 +13,7 @@ qt_add_test(tst_qvariant
../../../other/qvariant_common
PUBLIC_LIBRARIES
Qt::CorePrivate
+ Qt::Gui
)
# Resources:
diff --git a/tests/auto/corelib/kernel/qvariant/qvariant.pro b/tests/auto/corelib/kernel/qvariant/qvariant.pro
index a620be0091..7416023808 100644
--- a/tests/auto/corelib/kernel/qvariant/qvariant.pro
+++ b/tests/auto/corelib/kernel/qvariant/qvariant.pro
@@ -1,6 +1,6 @@
CONFIG += testcase
TARGET = tst_qvariant
-QT = core-private testlib
+QT = core-private gui testlib
INCLUDEPATH += $$PWD/../../../other/qvariant_common
SOURCES = tst_qvariant.cpp
RESOURCES += qvariant.qrc
diff --git a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp
index a722e53f48..d4af02baf1 100644
--- a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp
+++ b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp
@@ -477,7 +477,7 @@ void tst_QVariant::canConvert_data()
<< var << N << N << Y << N << Y << N << N << N << N << Y << N << N << Y << N << Y << N << Y << N << N << N << N << N << N << N << N << N << Y << N << N << Y << Y;
var = QVariant();
QTest::newRow("Invalid")
- << var << N << N << N << N << N << N << N << N << N << N << N << N << N << Y << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N;
+ << var << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N;
var = QVariant(QList<QVariant>());
QTest::newRow("List")
<< var << N << N << N << N << N << N << N << N << N << N << N << N << N << N << N << Y << N << N << N << N << N << N << N << N << N << N << N << Y << N << N << N;
@@ -520,12 +520,12 @@ void tst_QVariant::canConvert_data()
var = QVariant::fromValue<signed char>(-1);
QTest::newRow("SChar")
<< var << N << N << Y << N << Y << N << N << N << N << Y << N << N << Y << N << N << N << Y << N << N << N << N << N << N << N << N << N << Y << N << N << Y << Y;
- var = QVariant((short)-3);
+ var = QVariant::fromValue((short)-3);
QTest::newRow("Short")
- << var << N << N << Y << N << Y << N << N << N << N << Y << N << N << Y << N << Y << N << Y << N << N << N << N << N << N << N << N << N << Y << N << N << Y << Y;
- var = QVariant((ushort)7);
+ << var << N << N << Y << N << Y << N << N << N << N << Y << N << N << Y << N << N << N << Y << N << N << N << N << N << N << N << N << N << Y << N << N << Y << Y;
+ var = QVariant::fromValue((ushort)7);
QTest::newRow("UShort")
- << var << N << N << Y << N << Y << N << N << N << N << Y << N << N << Y << N << Y << N << Y << N << N << N << N << N << N << N << N << N << Y << N << N << Y << Y;
+ << var << N << N << Y << N << Y << N << N << N << N << Y << N << N << Y << N << N << N << Y << N << N << N << N << N << N << N << N << N << Y << N << N << Y << Y;
var = QVariant::fromValue<QJsonValue>(QJsonValue(QStringLiteral("hello")));
QTest::newRow("JsonValue")
<< var << N << N << Y << N << N << N << N << N << N << Y << N << N << Y << N << N << Y << Y << Y << N << N << N << N << N << N << N << N << Y << N << N << Y << Y;
@@ -2705,17 +2705,17 @@ void tst_QVariant::canConvertQStringList_data() const
QTest::addColumn<QStringList>("input");
QTest::addColumn<QString>("result");
- QTest::newRow("An empty list") << false << QStringList() << QString();
+ QTest::newRow("An empty list") << true << QStringList() << QString();
QTest::newRow("A single item") << true << QStringList(QLatin1String("foo")) << QString::fromLatin1("foo");
QTest::newRow("A single, but empty item") << true << QStringList(QString()) << QString();
QStringList l;
l << "a" << "b";
- QTest::newRow("Two items") << false << l << QString();
+ QTest::newRow("Two items") << true << l << QString();
l << "c";
- QTest::newRow("Three items") << false << l << QString();
+ QTest::newRow("Three items") << true << l << QString();
}
template<typename T> void convertMetaType()