diff options
author | Stephen Kelly <stephen.kelly@kdab.com> | 2013-04-05 13:24:54 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-05-08 12:45:59 +0200 |
commit | 508ee5616b80979f6800beeb4a52fa5cc0a4ad0a (patch) | |
tree | e093d10077f923b6c34d3e8a717433a7712da5b9 /src/corelib/kernel | |
parent | c5a6b894e7484544c44a8a415a84e196c4b633c3 (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.cpp | 4 | ||||
-rw-r--r-- | src/corelib/kernel/qmetatype.h | 69 | ||||
-rw-r--r-- | src/corelib/kernel/qvariant.cpp | 10 |
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 |