From 508ee5616b80979f6800beeb4a52fa5cc0a4ad0a Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Fri, 5 Apr 2013 13:24:54 +0200 Subject: Add automatic container access registration for built-in containers. Change-Id: I4d590c23e072994930922ff73367600f848fbcf0 Reviewed-by: Stephen Kelly --- .../snippets/code/src_corelib_kernel_qvariant.cpp | 2 - src/corelib/kernel/qmetatype.cpp | 4 ++ src/corelib/kernel/qmetatype.h | 69 +++++++++++++++++++++- src/corelib/kernel/qvariant.cpp | 10 +--- 4 files changed, 75 insertions(+), 10 deletions(-) (limited to 'src') 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 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 + struct ValueTypeIsMetaType; } class Q_CORE_EXPORT QMetaType { @@ -538,6 +541,7 @@ private: #ifndef Q_QDOC template friend bool qRegisterSequentialConverter(); + template friend struct QtPrivate::ValueTypeIsMetaType; #endif #else public: @@ -946,6 +950,63 @@ namespace QtPrivate enum { Value = true }; }; + template + struct IsSequentialContainer + { + enum { Value = false }; + }; + +#define QT_DEFINE_SEQUENTIAL_CONTAINER_TYPE(CONTAINER) \ + template \ + struct IsSequentialContainer > \ + { \ + 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::Value> + struct SequentialContainerConverterHelper + { + static bool registerConverter(int) + { + return false; + } + }; + + template::Defined> + struct ValueTypeIsMetaType + { + static bool registerConverter(int) + { + return false; + } + }; + + template + struct ValueTypeIsMetaType + { + static bool registerConverter(int id) + { + const int toId = qMetaTypeId(); + if (!QMetaType::hasRegisteredConverterFunction(id, toId)) { + QtMetaTypePrivate::QSequentialIterableConvertFunctor f; + return QMetaType::registerConverterFunction( + new QtPrivate::ConverterFunctor >(f), + id, toId); + } + return true; + } + }; + + template + struct SequentialContainerConverterHelper : ValueTypeIsMetaType + { + }; + 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::Delete, QtMetaTypePrivate::QMetaTypeFunctionHelper::Create, QtMetaTypePrivate::QMetaTypeFunctionHelper::Destruct, @@ -1043,6 +1104,12 @@ int qRegisterNormalizedMetaType(const QT_PREPEND_NAMESPACE(QByteArray) &normaliz sizeof(T), flags, QtPrivate::MetaObjectForType::value()); + + if (id > 0) { + QtPrivate::SequentialContainerConverterHelper::registerConverter(id); + } + + return id; } template 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 -- cgit v1.2.3