diff options
-rw-r--r-- | src/corelib/doc/snippets/code/src_corelib_kernel_qvariant.cpp | 2 | ||||
-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 | ||||
-rw-r--r-- | tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp | 19 |
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) |