summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_kernel_qmetatype.cpp28
-rw-r--r--src/corelib/kernel/qmetatype.cpp16
-rw-r--r--src/corelib/kernel/qmetatype.h45
-rw-r--r--tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp53
4 files changed, 142 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> > \
diff --git a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp
index 502e2504c9..c59e87cf13 100644
--- a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp
+++ b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp
@@ -2300,6 +2300,8 @@ Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE(MyNS::AssociativeContainer)
// Test that explicit declaration does not degrade features.
Q_DECLARE_METATYPE(MyNS::SmartPointer<int>)
+Q_DECLARE_METATYPE(MyNS::SmartPointer<QIODevice>)
+Q_DECLARE_METATYPE(QSharedPointer<QIODevice>)
void tst_QVariant::qvariant_cast_QObject_wrapper()
{
@@ -2319,6 +2321,57 @@ void tst_QVariant::qvariant_cast_QObject_wrapper()
QVariant::fromValue(sc);
QVariant::fromValue(ac);
+ {
+ QFile *f = new QFile(this);
+ MyNS::SmartPointer<QFile> sp(f);
+ QVariant spVar = QVariant::fromValue(sp);
+ QVERIFY(spVar.canConvert<QObject*>());
+ QCOMPARE(f, spVar.value<QObject*>());
+ }
+ {
+ QFile *f = new QFile(this);
+ QPointer<QFile> sp(f);
+ QVariant spVar = QVariant::fromValue(sp);
+ QVERIFY(spVar.canConvert<QObject*>());
+ QCOMPARE(f, spVar.value<QObject*>());
+ }
+ {
+ QFile *f = new QFile(this);
+ QWeakPointer<QFile> sp(f);
+ QVariant spVar = QVariant::fromValue(sp);
+ QVERIFY(spVar.canConvert<QObject*>());
+ QCOMPARE(f, spVar.value<QObject*>());
+ }
+ {
+ QFile *f = new QFile(this);
+ QSharedPointer<QFile> sp(f);
+ QWeakPointer<QFile> wp = sp.toWeakRef();
+ QVariant wpVar = QVariant::fromValue(wp);
+ QVERIFY(wpVar.canConvert<QObject*>());
+ QCOMPARE(f, wpVar.value<QObject*>());
+ }
+ {
+ QFile *f = new QFile(this);
+ QSharedPointer<QFile> sp(f);
+ QVariant spVar = QVariant::fromValue(sp);
+ QVERIFY(spVar.canConvert<QObject*>());
+ QCOMPARE(f, spVar.value<QObject*>());
+ }
+ {
+ QIODevice *f = new QFile(this);
+ MyNS::SmartPointer<QIODevice> sp(f);
+ QVariant spVar = QVariant::fromValue(sp);
+ QVERIFY(spVar.canConvert<QObject*>());
+ QCOMPARE(f, spVar.value<QObject*>());
+ }
+ {
+ QIODevice *f = new QFile(this);
+ QSharedPointer<QIODevice> sp(f);
+ QVariant spVar = QVariant::fromValue(sp);
+ QVERIFY(spVar.canConvert<QObject*>());
+ QCOMPARE(f, spVar.value<QObject*>());
+ }
+
// Compile tests:
qRegisterMetaType<MyNS::SmartPointer<int> >();
// Not declared as a metatype: