summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_kernel_qvariant.cpp2
-rw-r--r--src/corelib/kernel/qmetatype.cpp4
-rw-r--r--src/corelib/kernel/qmetatype.h69
-rw-r--r--src/corelib/kernel/qvariant.cpp10
-rw-r--r--tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp19
5 files changed, 75 insertions, 29 deletions
diff --git a/src/corelib/doc/snippets/code/src_corelib_kernel_qvariant.cpp b/src/corelib/doc/snippets/code/src_corelib_kernel_qvariant.cpp
index 27971d6f60..779c35d879 100644
--- a/src/corelib/doc/snippets/code/src_corelib_kernel_qvariant.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_kernel_qvariant.cpp
@@ -137,8 +137,6 @@ QVariant data = QVariant::fromValue(object);
//! [9]
-qRegisterSequentialConverter<QList<int> >();
-
QList<int> intList;
intList.push_back(7);
intList.push_back(11);
diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp
index 37ff858530..fe7cc53181 100644
--- a/src/corelib/kernel/qmetatype.cpp
+++ b/src/corelib/kernel/qmetatype.cpp
@@ -1971,6 +1971,10 @@ const QMetaObject *QMetaType::metaObjectForType(int type)
a QVariantList. If compilation fails, then you probably forgot to
Q_DECLARE_METATYPE the value type.
+ Note that it is not necessary to call this method for Qt containers (QList,
+ QVector etc) or for std::vector or std::list. Such containers are automatically
+ registered by Qt.
+
\sa QVariant::canConvert()
*/
diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h
index 3eb89caea8..0104f0ea56 100644
--- a/src/corelib/kernel/qmetatype.h
+++ b/src/corelib/kernel/qmetatype.h
@@ -307,6 +307,9 @@ struct ConverterFunctor : public AbstractConverterFunction
UnaryFunction m_function;
};
+
+ template<typename T, bool>
+ struct ValueTypeIsMetaType;
}
class Q_CORE_EXPORT QMetaType {
@@ -538,6 +541,7 @@ private:
#ifndef Q_QDOC
template<typename T>
friend bool qRegisterSequentialConverter();
+ template<typename, bool> friend struct QtPrivate::ValueTypeIsMetaType;
#endif
#else
public:
@@ -946,6 +950,63 @@ namespace QtPrivate
enum { Value = true };
};
+ template<typename T>
+ struct IsSequentialContainer
+ {
+ enum { Value = false };
+ };
+
+#define QT_DEFINE_SEQUENTIAL_CONTAINER_TYPE(CONTAINER) \
+ template<typename T> \
+ struct IsSequentialContainer<CONTAINER<T> > \
+ { \
+ enum { Value = true }; \
+ };
+ QT_FOR_EACH_AUTOMATIC_TEMPLATE_1ARG(QT_DEFINE_SEQUENTIAL_CONTAINER_TYPE)
+ QT_DEFINE_SEQUENTIAL_CONTAINER_TYPE(std::vector)
+ QT_DEFINE_SEQUENTIAL_CONTAINER_TYPE(std::list)
+
+ template<typename T, bool = QtPrivate::IsSequentialContainer<T>::Value>
+ struct SequentialContainerConverterHelper
+ {
+ static bool registerConverter(int)
+ {
+ return false;
+ }
+ };
+
+ template<typename T, bool = QMetaTypeId2<typename T::value_type>::Defined>
+ struct ValueTypeIsMetaType
+ {
+ static bool registerConverter(int)
+ {
+ return false;
+ }
+ };
+
+ template<typename T>
+ struct ValueTypeIsMetaType<T, true>
+ {
+ static bool registerConverter(int id)
+ {
+ const int toId = qMetaTypeId<QtMetaTypePrivate::QSequentialIterableImpl>();
+ if (!QMetaType::hasRegisteredConverterFunction(id, toId)) {
+ QtMetaTypePrivate::QSequentialIterableConvertFunctor<T> f;
+ return QMetaType::registerConverterFunction(
+ new QtPrivate::ConverterFunctor<T,
+ QtMetaTypePrivate::QSequentialIterableImpl,
+ QtMetaTypePrivate::QSequentialIterableConvertFunctor<T> >(f),
+ id, toId);
+ }
+ return true;
+ }
+ };
+
+ template<typename T>
+ struct SequentialContainerConverterHelper<T, true> : ValueTypeIsMetaType<T>
+ {
+ };
+
Q_CORE_EXPORT bool isBuiltinType(const QByteArray &type);
} // namespace QtPrivate
@@ -1035,7 +1096,7 @@ int qRegisterNormalizedMetaType(const QT_PREPEND_NAMESPACE(QByteArray) &normaliz
if (defined)
flags |= QMetaType::WasDeclaredAsMetaType;
- return QMetaType::registerNormalizedType(normalizedTypeName,
+ const int id = QMetaType::registerNormalizedType(normalizedTypeName,
QtMetaTypePrivate::QMetaTypeFunctionHelper<T>::Delete,
QtMetaTypePrivate::QMetaTypeFunctionHelper<T>::Create,
QtMetaTypePrivate::QMetaTypeFunctionHelper<T>::Destruct,
@@ -1043,6 +1104,12 @@ int qRegisterNormalizedMetaType(const QT_PREPEND_NAMESPACE(QByteArray) &normaliz
sizeof(T),
flags,
QtPrivate::MetaObjectForType<T>::value());
+
+ if (id > 0) {
+ QtPrivate::SequentialContainerConverterHelper<T>::registerConverter(id);
+ }
+
+ return id;
}
template <typename T>
diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp
index 985433d83a..99fdb4fa4a 100644
--- a/src/corelib/kernel/qvariant.cpp
+++ b/src/corelib/kernel/qvariant.cpp
@@ -2753,11 +2753,9 @@ static bool canConvertMetaObject(int fromId, int toId, QObject *fromObject)
\snippet code/src_corelib_kernel_qvariant.cpp 9
- This requires that the value_type of the container is itself a metatype. To make it
- possible to convert or iterate over a sequential container, the qRegisterSequentialConverter
- method must first be called for the container.
+ This requires that the value_type of the container is itself a metatype.
- \sa convert(), QSequentialIterable
+ \sa convert(), QSequentialIterable, qRegisterSequentialConverter()
*/
bool QVariant::canConvert(int targetTypeId) const
{
@@ -3090,9 +3088,7 @@ QDebug operator<<(QDebug dbg, const QVariant::Type p)
\snippet code/src_corelib_kernel_qvariant.cpp 9
- The qRegisterSequentialConverter method must first be called for the container.
-
- \sa setValue(), fromValue(), canConvert()
+ \sa setValue(), fromValue(), canConvert(), qRegisterSequentialConverter()
*/
/*! \fn bool QVariant::canConvert() const
diff --git a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp
index 3f5a05eb5d..cdc6f1f1df 100644
--- a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp
+++ b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp
@@ -3518,25 +3518,6 @@ void tst_QVariant::iterateContainerElements()
TEST_RANGE_FOR(CONTAINER, VALUE_TYPE) \
}
- qRegisterSequentialConverter<QVector<int> >();
- qRegisterSequentialConverter<QVector<QVariant> >();
- qRegisterSequentialConverter<QVector<QString> >();
- qRegisterSequentialConverter<QQueue<int> >();
- qRegisterSequentialConverter<QQueue<QVariant> >();
- qRegisterSequentialConverter<QQueue<QString> >();
- qRegisterSequentialConverter<QList<int> >();
- qRegisterSequentialConverter<QList<QVariant> >();
- qRegisterSequentialConverter<QList<QString> >();
- qRegisterSequentialConverter<QStack<int> >();
- qRegisterSequentialConverter<QStack<QVariant> >();
- qRegisterSequentialConverter<QStack<QString> >();
- qRegisterSequentialConverter<std::vector<int> >();
- qRegisterSequentialConverter<std::vector<QVariant> >();
- qRegisterSequentialConverter<std::vector<QString> >();
- qRegisterSequentialConverter<std::list<int> >();
- qRegisterSequentialConverter<std::list<QVariant> >();
- qRegisterSequentialConverter<std::list<QString> >();
-
TEST_SEQUENTIAL_ITERATION(QVector, int)
TEST_SEQUENTIAL_ITERATION(QVector, QVariant)
TEST_SEQUENTIAL_ITERATION(QVector, QString)