summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2020-07-14 14:25:18 +0200
committerLars Knoll <lars.knoll@qt.io>2020-08-24 00:18:31 +0200
commitc7ce1bc05c1ec2f63dd2531f23a3e9f6fe866556 (patch)
tree60ef42109895d8bb8c796b58f21800f2a87b8cbe
parent9d36032370f7b81279ff8774afd7dea4ea57ee6a (diff)
Move conversions to and from *Iterables into QMetaType
Those were not yet supported by QMetaType. Change-Id: I9f85476049f200e35939ac58ef7e8b4e7cbe0b77 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Lars Knoll <lars.knoll@qt.io>
-rw-r--r--src/corelib/kernel/qmetatype.cpp198
-rw-r--r--src/corelib/kernel/qmetatype.h7
-rw-r--r--src/corelib/kernel/qvariant.cpp21
-rw-r--r--src/corelib/kernel/qvariant.h118
-rw-r--r--tests/auto/corelib/kernel/qmetatype/tst_qmetatype.h4
5 files changed, 200 insertions, 148 deletions
diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp
index e8f359a366..072b27b573 100644
--- a/src/corelib/kernel/qmetatype.cpp
+++ b/src/corelib/kernel/qmetatype.cpp
@@ -1152,6 +1152,19 @@ static const struct : QMetaTypeModuleHelper
QMETATYPE_CONVERTER_ASSIGN(QPointF, QPoint);
#endif
+ QMETATYPE_CONVERTER(QByteArrayList, QVariantList,
+ result.reserve(source.size());
+ for (auto v: source)
+ result.append(v.toByteArray());
+ return true;
+ );
+ QMETATYPE_CONVERTER(QVariantList, QByteArrayList,
+ result.reserve(source.size());
+ for (auto v: source)
+ result.append(QVariant(v));
+ return true;
+ );
+
QMETATYPE_CONVERTER(QStringList, QVariantList,
result.reserve(source.size());
for (auto v: source)
@@ -1829,6 +1842,142 @@ static bool convertToEnum(const void *from, int fromTypeId, void *to, const QMet
}
}
+static bool convertIterableToVariantList(const void *from, int fromTypeId, void *to)
+{
+ const QMetaType::ConverterFunction * const f =
+ customTypesConversionRegistry()->function(qMakePair(fromTypeId,
+ qMetaTypeId<QtMetaTypePrivate::QSequentialIterableImpl>()));
+ if (!f)
+ return false;
+
+ QtMetaTypePrivate::QSequentialIterableImpl iter;
+ (*f)(from, &iter);
+ QSequentialIterable list(iter);
+ QVariantList &l = *static_cast<QVariantList *>(to);
+ l.clear();
+ l.reserve(list.size());
+ auto end = list.end();
+ for (auto it = list.begin(); it != end; ++it)
+ l << *it;
+ return true;
+}
+
+static bool convertIterableToVariantMap(const void *from, int fromTypeId, void *to)
+{
+ const QMetaType::ConverterFunction * const f =
+ customTypesConversionRegistry()->function(qMakePair(fromTypeId,
+ qMetaTypeId<QtMetaTypePrivate::QAssociativeIterableImpl>()));
+ if (!f)
+ return false;
+
+ QtMetaTypePrivate::QAssociativeIterableImpl iter;
+ (*f)(from, &iter);
+ QAssociativeIterable map(iter);
+ QVariantMap &h = *static_cast<QVariantMap *>(to);
+ h.clear();
+ auto end = map.end();
+ for (auto it = map.begin(); it != end; ++it)
+ h.insert(it.key().toString(), it.value());
+ return true;
+}
+
+static bool convertIterableToVariantHash(const void *from, int fromTypeId, void *to)
+{
+ const QMetaType::ConverterFunction * const f =
+ customTypesConversionRegistry()->function(qMakePair(fromTypeId,
+ qMetaTypeId<QtMetaTypePrivate::QAssociativeIterableImpl>()));
+ if (!f)
+ return false;
+
+ QtMetaTypePrivate::QAssociativeIterableImpl iter;
+ (*f)(from, &iter);
+ QAssociativeIterable map(iter);
+ QVariantHash &h = *static_cast<QVariantHash *>(to);
+ h.clear();
+ h.reserve(map.size());
+ auto end = map.end();
+ for (auto it = map.begin(); it != end; ++it)
+ h.insert(it.key().toString(), it.value());
+ return true;
+}
+
+static bool convertIterableToVariantPair(const void *from, int fromTypeId, void *to)
+{
+ const QMetaType::ConverterFunction * const f =
+ customTypesConversionRegistry()->function(qMakePair(fromTypeId,
+ qMetaTypeId<QtMetaTypePrivate::QPairVariantInterfaceImpl>()));
+ if (!f)
+ return false;
+
+ QtMetaTypePrivate::QPairVariantInterfaceImpl pi;
+ (*f)(from, &pi);
+
+ QVariant v1(pi._metaType_first);
+ void *dataPtr;
+ if (pi._metaType_first == QMetaType::fromType<QVariant>())
+ dataPtr = &v1;
+ else
+ dataPtr = v1.data();
+ pi.first(dataPtr);
+
+ QVariant v2(pi._metaType_second);
+ if (pi._metaType_second == QMetaType::fromType<QVariant>())
+ dataPtr = &v2;
+ else
+ dataPtr = v2.data();
+ pi.second(dataPtr);
+
+ *static_cast<QVariantPair *>(to) = QVariantPair(v1, v2);
+ return true;
+}
+
+static bool convertToSequentialIterable(const void *from, int fromTypeId, void *to)
+{
+ using namespace QtMetaTypePrivate;
+
+ QSequentialIterable &i = *static_cast<QSequentialIterable *>(to);
+ if (fromTypeId == QMetaType::QVariantList) {
+ i = QSequentialIterable(QSequentialIterableImpl(reinterpret_cast<const QVariantList *>(from)));
+ return true;
+ }
+ if (fromTypeId == QMetaType::QStringList) {
+ i = QSequentialIterable(QSequentialIterableImpl(reinterpret_cast<const QStringList *>(from)));
+ return true;
+ }
+ else if (fromTypeId == QMetaType::QByteArrayList) {
+ i = QSequentialIterable(QSequentialIterableImpl(reinterpret_cast<const QByteArrayList *>(from)));
+ return true;
+ }
+ QSequentialIterableImpl impl;
+ if (QMetaType::convert(from, fromTypeId, &impl, qMetaTypeId<QtMetaTypePrivate::QSequentialIterableImpl>())) {
+ i = QSequentialIterable(impl);
+ return true;
+ }
+ return false;
+}
+
+static bool convertToAssociativeIterable(const void *from, int fromTypeId, void *to)
+{
+ using namespace QtMetaTypePrivate;
+
+ QAssociativeIterable &i = *static_cast<QAssociativeIterable *>(to);
+ if (fromTypeId == QMetaType::QVariantMap) {
+ i = QAssociativeIterable(QAssociativeIterableImpl(reinterpret_cast<const QVariantMap *>(from)));
+ return true;
+ }
+ if (fromTypeId == QMetaType::QVariantHash) {
+ i = QAssociativeIterable(QAssociativeIterableImpl(reinterpret_cast<const QVariantHash *>(from)));
+ return true;
+ }
+ QAssociativeIterableImpl impl;
+ if (QMetaType::convert(from, fromTypeId, &impl, qMetaTypeId<QtMetaTypePrivate::QAssociativeIterableImpl>())) {
+ i = QAssociativeIterable(impl);
+ return true;
+ }
+ return false;
+}
+
+
#ifndef QT_BOOTSTRAPPED
static bool canConvertMetaObject(const QMetaType &fromType, const QMetaType &toType)
{
@@ -1840,7 +1989,6 @@ static bool canConvertMetaObject(const QMetaType &fromType, const QMetaType &toT
}
#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.
@@ -1880,6 +2028,26 @@ bool QMetaType::convert(const void *from, int fromTypeId, void *to, int toTypeId
return true;
}
}
+
+ // handle iterables
+ if (toTypeId == QVariantList && convertIterableToVariantList(from, fromTypeId, to))
+ return true;
+
+ if (toTypeId == QVariantMap && convertIterableToVariantMap(from, fromTypeId, to))
+ return true;
+
+ if (toTypeId == QVariantHash && convertIterableToVariantHash(from, fromTypeId, to))
+ return true;
+
+ if (toTypeId == QVariantPair && convertIterableToVariantPair(from, fromTypeId, to))
+ return true;
+
+ if (toTypeId == qMetaTypeId<QSequentialIterable>())
+ return convertToSequentialIterable(from, fromTypeId, to);
+
+ if (toTypeId == qMetaTypeId<QAssociativeIterable>())
+ return convertToAssociativeIterable(from, fromTypeId, to);
+
return false;
}
@@ -1969,22 +2137,34 @@ bool QMetaType::canConvert(const QMetaType &fromType, const QMetaType &toType)
if (moduleHelper->convert(nullptr, fromTypeId, nullptr, toTypeId))
return true;
}
- const QMetaType::ConverterFunction * const f =
+ const ConverterFunction * const f =
customTypesConversionRegistry()->function(qMakePair(fromTypeId, toTypeId));
if (f)
return true;
- if (fromType.flags() & QMetaType::IsEnumeration) {
- if (toTypeId == QMetaType::QString || toTypeId == QMetaType::QByteArray)
+ if (toTypeId == QVariantList && hasRegisteredConverterFunction(
+ fromTypeId, qMetaTypeId<QtMetaTypePrivate::QSequentialIterableImpl>()))
+ return true;
+
+ if ((toTypeId == QVariantHash || toTypeId == QVariantMap) && hasRegisteredConverterFunction(
+ fromTypeId, qMetaTypeId<QtMetaTypePrivate::QAssociativeIterableImpl>()))
+ return true;
+
+ if (toTypeId == QVariantPair && hasRegisteredConverterFunction(
+ fromTypeId, qMetaTypeId<QtMetaTypePrivate::QPairVariantInterfaceImpl>()))
+ return true;
+
+ if (fromType.flags() & IsEnumeration) {
+ if (toTypeId == QString || toTypeId == QByteArray)
return true;
- return QMetaType::canConvert(QMetaType(LongLong), toType);
+ return canConvert(QMetaType(LongLong), toType);
}
- if (toType.flags() & QMetaType::IsEnumeration) {
- if (fromTypeId == QMetaType::QString || fromTypeId == QMetaType::QByteArray)
+ if (toType.flags() & IsEnumeration) {
+ if (fromTypeId == QString || fromTypeId == QByteArray)
return true;
- return QMetaType::canConvert(fromType, QMetaType(LongLong));
+ return canConvert(fromType, QMetaType(LongLong));
}
- if (toTypeId == Nullptr && fromType.flags() & QMetaType::IsPointer)
+ if (toTypeId == Nullptr && fromType.flags() & IsPointer)
return true;
#ifndef QT_BOOTSTRAPPED
if (canConvertMetaObject(fromType, toType))
diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h
index 4a3ed1affc..62d2fd82a1 100644
--- a/src/corelib/kernel/qmetatype.h
+++ b/src/corelib/kernel/qmetatype.h
@@ -162,6 +162,7 @@ inline constexpr int qMetaTypeId();
F(QVariantMap, 8, QVariantMap) \
F(QVariantList, 9, QVariantList) \
F(QVariantHash, 28, QVariantHash) \
+ F(QVariantPair, 58, QVariantPair) \
F(QByteArrayList, 49, QByteArrayList) \
#if QT_CONFIG(shortcut)
@@ -219,6 +220,7 @@ inline constexpr int qMetaTypeId();
F(QVariantList, -1, QVariantList, "QList<QVariant>") \
F(QVariantMap, -1, QVariantMap, "QMap<QString,QVariant>") \
F(QVariantHash, -1, QVariantHash, "QHash<QString,QVariant>") \
+ F(QVariantPair, -1, QVariantPair, "QPair<QVariant,QVariant>") \
F(QByteArrayList, -1, QByteArrayList, "QList<QByteArray>") \
#define QT_FOR_EACH_STATIC_TYPE(F)\
@@ -295,7 +297,7 @@ public:
QT_FOR_EACH_STATIC_TYPE(QT_DEFINE_METATYPE_ID)
FirstCoreType = Bool,
- LastCoreType = Char32,
+ LastCoreType = QVariantPair,
FirstGuiType = QFont,
LastGuiType = QColorSpace,
FirstWidgetsType = QSizePolicy,
@@ -337,7 +339,7 @@ public:
// Widget types
QSizePolicy = 121,
- LastCoreType = QCborMap,
+ LastCoreType = Char32,
LastGuiType = QColorSpace,
User = 1024
};
@@ -1704,6 +1706,7 @@ QT_FOR_EACH_STATIC_WIDGETS_CLASS(QT_FORWARD_DECLARE_STATIC_TYPES_ITER)
typedef QList<QVariant> QVariantList;
typedef QMap<QString, QVariant> QVariantMap;
typedef QHash<QString, QVariant> QVariantHash;
+typedef QPair<QVariant, QVariant> QVariantPair;
#ifdef Q_CLANG_QDOC
class QByteArrayList;
#else
diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp
index c16e4a0e06..6a046dffd3 100644
--- a/src/corelib/kernel/qvariant.cpp
+++ b/src/corelib/kernel/qvariant.cpp
@@ -1974,27 +1974,6 @@ bool QVariant::canConvert(int targetTypeId) const
if (d.typeId() == targetTypeId && targetTypeId != QMetaType::UnknownType)
return true;
- if (targetTypeId == QMetaType::QVariantList
- && (d.typeId() == QMetaType::QVariantList || d.typeId() == QMetaType::QStringList
- || d.typeId() == QMetaType::QByteArrayList
- || QMetaType::hasRegisteredConverterFunction(
- d.typeId(), qMetaTypeId<QtMetaTypePrivate::QSequentialIterableImpl>()))) {
- return true;
- }
-
- if ((targetTypeId == QMetaType::QVariantHash || targetTypeId == QMetaType::QVariantMap)
- && (d.typeId() == QMetaType::QVariantMap || d.typeId() == QMetaType::QVariantHash
- || QMetaType::hasRegisteredConverterFunction(
- d.typeId(), qMetaTypeId<QtMetaTypePrivate::QAssociativeIterableImpl>()))) {
- return true;
- }
-
- if (targetTypeId == qMetaTypeId<QPair<QVariant, QVariant>>()
- && QMetaType::hasRegisteredConverterFunction(
- d.typeId(), qMetaTypeId<QtMetaTypePrivate::QPairVariantInterfaceImpl>())) {
- return true;
- }
-
return QMetaType::canConvert(d.type(), QMetaType(targetTypeId));
}
diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h
index 258dac3bbc..218b88cb4a 100644
--- a/src/corelib/kernel/qvariant.h
+++ b/src/corelib/kernel/qvariant.h
@@ -655,6 +655,7 @@ public:
friend struct const_iterator;
explicit QSequentialIterable(const QtMetaTypePrivate::QSequentialIterableImpl &impl);
+ QSequentialIterable() {}
const_iterator begin() const;
const_iterator end() const;
@@ -709,6 +710,7 @@ public:
friend struct const_iterator;
explicit QAssociativeIterable(const QtMetaTypePrivate::QAssociativeIterableImpl &impl);
+ QAssociativeIterable() {}
const_iterator begin() const;
const_iterator end() const;
@@ -748,122 +750,6 @@ namespace QtPrivate {
struct QVariantValueHelperInterface : QVariantValueHelper<T>
{
};
-
- template<>
- struct QVariantValueHelperInterface<QSequentialIterable>
- {
- static QSequentialIterable invoke(const QVariant &v)
- {
- const int typeId = v.userType();
- if (typeId == qMetaTypeId<QVariantList>()) {
- return QSequentialIterable(QtMetaTypePrivate::QSequentialIterableImpl(reinterpret_cast<const QVariantList*>(v.constData())));
- }
- if (typeId == qMetaTypeId<QStringList>()) {
- return QSequentialIterable(QtMetaTypePrivate::QSequentialIterableImpl(reinterpret_cast<const QStringList*>(v.constData())));
- }
-#ifndef QT_BOOTSTRAPPED
- if (typeId == qMetaTypeId<QByteArrayList>()) {
- return QSequentialIterable(QtMetaTypePrivate::QSequentialIterableImpl(reinterpret_cast<const QByteArrayList*>(v.constData())));
- }
-#endif
- return QSequentialIterable(qvariant_cast<QtMetaTypePrivate::QSequentialIterableImpl>(v));
- }
- };
- template<>
- struct QVariantValueHelperInterface<QAssociativeIterable>
- {
- static QAssociativeIterable invoke(const QVariant &v)
- {
- const int typeId = v.userType();
- if (typeId == qMetaTypeId<QVariantMap>()) {
- return QAssociativeIterable(QtMetaTypePrivate::QAssociativeIterableImpl(reinterpret_cast<const QVariantMap*>(v.constData())));
- }
- if (typeId == qMetaTypeId<QVariantHash>()) {
- return QAssociativeIterable(QtMetaTypePrivate::QAssociativeIterableImpl(reinterpret_cast<const QVariantHash*>(v.constData())));
- }
- return QAssociativeIterable(qvariant_cast<QtMetaTypePrivate::QAssociativeIterableImpl>(v));
- }
- };
- template<>
- struct QVariantValueHelperInterface<QVariantList>
- {
- static QVariantList invoke(const QVariant &v)
- {
- const int typeId = v.userType();
- if (typeId == qMetaTypeId<QStringList>() || typeId == qMetaTypeId<QByteArrayList>() ||
- (QMetaType::hasRegisteredConverterFunction(typeId, qMetaTypeId<QtMetaTypePrivate::QSequentialIterableImpl>()) && !QMetaType::hasRegisteredConverterFunction(typeId, qMetaTypeId<QVariantList>()))) {
- QSequentialIterable iter = QVariantValueHelperInterface<QSequentialIterable>::invoke(v);
- QVariantList l;
- l.reserve(iter.size());
- for (QSequentialIterable::const_iterator it = iter.begin(), end = iter.end(); it != end; ++it)
- l << *it;
- return l;
- }
- return QVariantValueHelper<QVariantList>::invoke(v);
- }
- };
- template<>
- struct QVariantValueHelperInterface<QVariantHash>
- {
- static QVariantHash invoke(const QVariant &v)
- {
- const int typeId = v.userType();
- if (typeId == qMetaTypeId<QVariantMap>() || ((QMetaType::hasRegisteredConverterFunction(typeId, qMetaTypeId<QtMetaTypePrivate::QAssociativeIterableImpl>())) && !QMetaType::hasRegisteredConverterFunction(typeId, qMetaTypeId<QVariantHash>()))) {
- QAssociativeIterable iter = QVariantValueHelperInterface<QAssociativeIterable>::invoke(v);
- QVariantHash l;
- l.reserve(iter.size());
- for (QAssociativeIterable::const_iterator it = iter.begin(), end = iter.end(); it != end; ++it)
- l.insert(it.key().toString(), it.value());
- return l;
- }
- return QVariantValueHelper<QVariantHash>::invoke(v);
- }
- };
- template<>
- struct QVariantValueHelperInterface<QVariantMap>
- {
- static QVariantMap invoke(const QVariant &v)
- {
- const int typeId = v.userType();
- if (typeId == qMetaTypeId<QVariantHash>() || (QMetaType::hasRegisteredConverterFunction(typeId, qMetaTypeId<QtMetaTypePrivate::QAssociativeIterableImpl>()) && !QMetaType::hasRegisteredConverterFunction(typeId, qMetaTypeId<QVariantMap>()))) {
- QAssociativeIterable iter = QVariantValueHelperInterface<QAssociativeIterable>::invoke(v);
- QVariantMap l;
- for (QAssociativeIterable::const_iterator it = iter.begin(), end = iter.end(); it != end; ++it)
- l.insert(it.key().toString(), it.value());
- return l;
- }
- return QVariantValueHelper<QVariantMap>::invoke(v);
- }
- };
- template<>
- struct QVariantValueHelperInterface<QPair<QVariant, QVariant> >
- {
- static QPair<QVariant, QVariant> invoke(const QVariant &v)
- {
- const int typeId = v.userType();
-
- if (QMetaType::hasRegisteredConverterFunction(typeId, qMetaTypeId<QtMetaTypePrivate::QPairVariantInterfaceImpl>()) && !(typeId == qMetaTypeId<QPair<QVariant, QVariant> >())) {
- QtMetaTypePrivate::QPairVariantInterfaceImpl pi = v.value<QtMetaTypePrivate::QPairVariantInterfaceImpl>();
- QVariant v1(pi._metaType_first);
- void *dataPtr;
- if (pi._metaType_first == QMetaType::fromType<QVariant>())
- dataPtr = &v1;
- else
- dataPtr = v1.data();
- pi.first(dataPtr);
-
- QVariant v2(pi._metaType_second);
- if (pi._metaType_second == QMetaType::fromType<QVariant>())
- dataPtr = &v2;
- else
- dataPtr = v2.data();
- pi.second(dataPtr);
-
- return QPair<QVariant, QVariant>(v1, v2);
- }
- return QVariantValueHelper<QPair<QVariant, QVariant> >::invoke(v);
- }
- };
}
template<typename T> inline T qvariant_cast(const QVariant &v)
diff --git a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.h b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.h
index 3f00db5519..43a099de17 100644
--- a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.h
+++ b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.h
@@ -121,6 +121,10 @@ template<> struct TestValueFactory<QMetaType::QVariantMap> {
template<> struct TestValueFactory<QMetaType::QVariantHash> {
static QVariantHash *create() { return new QVariantHash(); }
};
+template<> struct TestValueFactory<QMetaType::QVariantPair> {
+ static QVariantPair *create() { return new QVariantPair(); }
+};
+
template<> struct TestValueFactory<QMetaType::QVariantList> {
static QVariantList *create() { return new QVariantList(QVariantList() << 123 << "Q" << "Variant" << "List"); }
};