Add automatic container access registration for built-in containers.
Change-Id: I4d590c23e072994930922ff73367600f848fbcf0 Reviewed-by: Stephen Kelly <stephen.kelly@kdab.com>
This commit is contained in:
parent
c5a6b894e7
commit
508ee5616b
@ -137,8 +137,6 @@ QVariant data = QVariant::fromValue(object);
|
||||
|
||||
//! [9]
|
||||
|
||||
qRegisterSequentialConverter<QList<int> >();
|
||||
|
||||
QList<int> intList;
|
||||
intList.push_back(7);
|
||||
intList.push_back(11);
|
||||
|
@ -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()
|
||||
*/
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user