summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel
diff options
context:
space:
mode:
authorStephen Kelly <stephen.kelly@kdab.com>2013-04-05 13:24:54 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-05-08 12:45:59 +0200
commit508ee5616b80979f6800beeb4a52fa5cc0a4ad0a (patch)
treee093d10077f923b6c34d3e8a717433a7712da5b9 /src/corelib/kernel
parentc5a6b894e7484544c44a8a415a84e196c4b633c3 (diff)
Add automatic container access registration for built-in containers.
Change-Id: I4d590c23e072994930922ff73367600f848fbcf0 Reviewed-by: Stephen Kelly <stephen.kelly@kdab.com>
Diffstat (limited to 'src/corelib/kernel')
-rw-r--r--src/corelib/kernel/qmetatype.cpp4
-rw-r--r--src/corelib/kernel/qmetatype.h69
-rw-r--r--src/corelib/kernel/qvariant.cpp10
3 files changed, 75 insertions, 8 deletions
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