diff options
author | Stephen Kelly <stephen.kelly@kdab.com> | 2013-09-08 08:49:29 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-09-11 12:24:42 +0200 |
commit | 546d52e605b6a74d9a5be26fb374b831a46f2550 (patch) | |
tree | c48f2e75179c44f5bee37ee2c5d8b8afcc4d072a /src/corelib | |
parent | 3256856bbea22da03109b84ef407e8dbc69930e7 (diff) |
Add a convenient way to get a type-erased smart pointer from a QVariant.
Any known smart pointer in a QVariant can be handled in this way. The
metatype system can be informed of new smart pointer types using an
existing macro which is now documented.
This is very similar to the existing infrastructure
for containers.
Change-Id: Iac4f9fabbc5a0626c04e1185d51d720b8b54603d
Reviewed-by: Olivier Goffart <ogoffart@woboq.com>
Diffstat (limited to 'src/corelib')
-rw-r--r-- | src/corelib/doc/snippets/code/src_corelib_kernel_qmetatype.cpp | 28 | ||||
-rw-r--r-- | src/corelib/kernel/qmetatype.cpp | 16 | ||||
-rw-r--r-- | src/corelib/kernel/qmetatype.h | 45 |
3 files changed, 89 insertions, 0 deletions
diff --git a/src/corelib/doc/snippets/code/src_corelib_kernel_qmetatype.cpp b/src/corelib/doc/snippets/code/src_corelib_kernel_qmetatype.cpp index cb1346f74c..0af10af36d 100644 --- a/src/corelib/doc/snippets/code/src_corelib_kernel_qmetatype.cpp +++ b/src/corelib/doc/snippets/code/src_corelib_kernel_qmetatype.cpp @@ -143,3 +143,31 @@ void someFunc() //! [11] +//! [12] +QPointer<QFile> fp(new QFile); +QVariant var = QVariant::fromValue(fp); +// ... +if (var.canConvert<QObject*>()) { + QObject *sp = var.value<QObject*>(); + qDebug() << sp->metaObject()->className(); // Prints 'QFile'. +} +//! [12] + +//! [13] + +#include <memory> + +Q_DECLARE_SMART_POINTER_METATYPE(std::shared_ptr) + +void someFunc() +{ + auto smart_ptr = std::make_shared<QFile>(); + QVariant var = QVariant::fromValue(smart_ptr); + // ... + if (var.canConvert<QObject*>()) { + QObject *sp = var.value<QObject*>(); + qDebug() << sp->metaObject()->className(); // Prints 'QFile'. + } +} + +//! [13] diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp index 2ab6681bb9..70c2e236dd 100644 --- a/src/corelib/kernel/qmetatype.cpp +++ b/src/corelib/kernel/qmetatype.cpp @@ -175,6 +175,22 @@ struct DefinedTypesFilter { */ /*! + \macro Q_DECLARE_SMART_POINTER_METATYPE(SmartPointer) + \relates QMetaType + + This macro makes the smart pointer \a SmartPointer known to QMetaType as a + smart pointer. This makes it possible to put an instance of SmartPointer<T> into + a QVariant, if T is a type which inherits QObject. + + Note that the QWeakPointer, QSharedPointer and QPointer already have built-in + support, and it is not necessary to use this macro with them. + + This example shows a typical use of Q_DECLARE_SMART_POINTER_METATYPE(): + + \snippet code/src_corelib_kernel_qmetatype.cpp 13 +*/ + +/*! \enum QMetaType::Type These are the built-in types supported by QMetaType: diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h index bd4963e4f1..2d9133dbae 100644 --- a/src/corelib/kernel/qmetatype.h +++ b/src/corelib/kernel/qmetatype.h @@ -373,6 +373,8 @@ struct ConverterFunctor : public AbstractConverterFunction struct AssociativeValueTypeIsMetaType; template<typename T, bool> struct IsMetaTypePair; + template<typename, typename> + struct MetaTypeSmartPointerHelper; } class Q_CORE_EXPORT QMetaType { @@ -656,6 +658,7 @@ private: friend bool qRegisterAssociativeConverter(); template<typename, bool> friend struct QtPrivate::AssociativeValueTypeIsMetaType; template<typename, bool> friend struct QtPrivate::IsMetaTypePair; + template<typename, typename> friend struct QtPrivate::MetaTypeSmartPointerHelper; #endif #else public: @@ -1463,6 +1466,12 @@ namespace QtPrivate template<typename T> struct MetaTypePairHelper : IsPair<T> {}; + template<typename T, typename = void> + struct MetaTypeSmartPointerHelper + { + static bool registerConverter(int) { return false; } + }; + Q_CORE_EXPORT bool isBuiltinType(const QByteArray &type); } // namespace QtPrivate @@ -1530,6 +1539,24 @@ namespace QtPrivate { { enum DefinedType { Defined = defined }; }; + + template<typename SmartPointer> + struct QSmartPointerConvertFunctor + { + QObject* operator()(const SmartPointer &p) const + { + return p.operator->(); + } + }; + + template<typename T> + struct QSmartPointerConvertFunctor<QWeakPointer<T> > + { + QObject* operator()(const QWeakPointer<T> &p) const + { + return p.data(); + } + }; } template <typename T> @@ -1565,6 +1592,7 @@ int qRegisterNormalizedMetaType(const QT_PREPEND_NAMESPACE(QByteArray) &normaliz QtPrivate::SequentialContainerConverterHelper<T>::registerConverter(id); QtPrivate::AssociativeContainerConverterHelper<T>::registerConverter(id); QtPrivate::MetaTypePairHelper<T>::registerConverter(id); + QtPrivate::MetaTypeSmartPointerHelper<T>::registerConverter(id); } return id; @@ -1828,6 +1856,23 @@ struct SharedPointerMetaTypeIdHelper<SMART_POINTER<T>, true> \ return newId; \ } \ }; \ +template<typename T> \ +struct MetaTypeSmartPointerHelper<SMART_POINTER<T> , \ + typename QEnableIf<IsPointerToTypeDerivedFromQObject<T*>::Value >::Type> \ +{ \ + static bool registerConverter(int id) \ + { \ + const int toId = QMetaType::QObjectStar; \ + if (!QMetaType::hasRegisteredConverterFunction(id, toId)) { \ + QtPrivate::QSmartPointerConvertFunctor<SMART_POINTER<T> > o; \ + static const QtPrivate::ConverterFunctor<SMART_POINTER<T>, \ + QObject*, \ + QSmartPointerConvertFunctor<SMART_POINTER<T> > > f(o); \ + return QMetaType::registerConverterFunction(&f, id, toId); \ + } \ + return true; \ + } \ +}; \ } \ template <typename T> \ struct QMetaTypeId< SMART_POINTER<T> > \ |