diff options
-rw-r--r-- | src/corelib/kernel/qpointer.h | 8 | ||||
-rw-r--r-- | src/corelib/tools/qsharedpointer.cpp | 20 | ||||
-rw-r--r-- | src/corelib/tools/qsharedpointer_impl.h | 20 | ||||
-rw-r--r-- | tests/auto/corelib/kernel/qpointer/tst_qpointer.cpp | 37 | ||||
-rw-r--r-- | tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp | 71 |
5 files changed, 155 insertions, 1 deletions
diff --git a/src/corelib/kernel/qpointer.h b/src/corelib/kernel/qpointer.h index 88d8225621..ef1d4dc1d5 100644 --- a/src/corelib/kernel/qpointer.h +++ b/src/corelib/kernel/qpointer.h @@ -50,6 +50,7 @@ QT_BEGIN_HEADER QT_BEGIN_NAMESPACE +class QVariant; class QPointerBase { @@ -184,6 +185,13 @@ inline bool operator!= (int i, const QPointer<T> &p) { Q_ASSERT(i == 0); return !i && !p.isNull(); } #endif +template<typename T> +QPointer<T> +qPointerFromVariant(const QVariant &variant) +{ + return QPointer<T>(qobject_cast<T*>(QtSharedPointer::weakPointerFromVariant_internal(variant).data())); +} + QT_END_NAMESPACE QT_END_HEADER diff --git a/src/corelib/tools/qsharedpointer.cpp b/src/corelib/tools/qsharedpointer.cpp index 8ca153f433..73a1e6c607 100644 --- a/src/corelib/tools/qsharedpointer.cpp +++ b/src/corelib/tools/qsharedpointer.cpp @@ -1214,6 +1214,26 @@ QtSharedPointer::ExternalRefCountData *QtSharedPointer::ExternalRefCountData::ge return x; } +/** + \internal + Returns a QSharedPointer<QObject> if the variant contains + a QSharedPointer<T> where T inherits QObject. Otherwise the behaviour is undefined. +*/ +QSharedPointer<QObject> QtSharedPointer::sharedPointerFromVariant_internal(const QVariant &variant) +{ + return *reinterpret_cast<const QSharedPointer<QObject>*>(variant.constData()); +} + +/** + \internal + Returns a QWeakPointer<QObject> if the variant contains + a QWeakPointer<T> where T inherits QObject. Otherwise the behaviour is undefined. +*/ +QWeakPointer<QObject> QtSharedPointer::weakPointerFromVariant_internal(const QVariant &variant) +{ + return *reinterpret_cast<const QWeakPointer<QObject>*>(variant.constData()); +} + QT_END_NAMESPACE #endif diff --git a/src/corelib/tools/qsharedpointer_impl.h b/src/corelib/tools/qsharedpointer_impl.h index 46cd1cc0a7..9d9698b8ca 100644 --- a/src/corelib/tools/qsharedpointer_impl.h +++ b/src/corelib/tools/qsharedpointer_impl.h @@ -87,6 +87,8 @@ template<typename T> inline void qt_sharedpointer_cast_check(T *) { } template <class T> class QWeakPointer; template <class T> class QSharedPointer; +class QVariant; + template <class X, class T> QSharedPointer<X> qSharedPointerCast(const QSharedPointer<T> &ptr); template <class X, class T> @@ -258,6 +260,9 @@ namespace QtSharedPointer { ~ExternalRefCountWithContiguousData() Q_DECL_EQ_DELETE; Q_DISABLE_COPY(ExternalRefCountWithContiguousData) }; + + Q_CORE_EXPORT QWeakPointer<QObject> weakPointerFromVariant_internal(const QVariant &variant); + Q_CORE_EXPORT QSharedPointer<QObject> sharedPointerFromVariant_internal(const QVariant &variant); } // namespace QtSharedPointer template <class T> class QSharedPointer @@ -816,8 +821,21 @@ qobject_cast(const QWeakPointer<T> &src) { return qSharedPointerObjectCast<typename QtSharedPointer::RemovePointer<X>::Type, T>(src); } -#endif +template<typename T> +QWeakPointer<typename QtPrivate::QEnableIf<QtPrivate::IsPointerToTypeDerivedFromQObject<T*>::Value, T>::Type> +qWeakPointerFromVariant(const QVariant &variant) +{ + return QWeakPointer<T>(qobject_cast<T*>(QtSharedPointer::weakPointerFromVariant_internal(variant).data())); +} +template<typename T> +QSharedPointer<typename QtPrivate::QEnableIf<QtPrivate::IsPointerToTypeDerivedFromQObject<T*>::Value, T>::Type> +qSharedPointerFromVariant(const QVariant &variant) +{ + return qSharedPointerObjectCast<T>(QtSharedPointer::sharedPointerFromVariant_internal(variant)); +} + +#endif template<typename T> Q_DECLARE_TYPEINFO_BODY(QWeakPointer<T>, Q_MOVABLE_TYPE); template<typename T> Q_DECLARE_TYPEINFO_BODY(QSharedPointer<T>, Q_MOVABLE_TYPE); diff --git a/tests/auto/corelib/kernel/qpointer/tst_qpointer.cpp b/tests/auto/corelib/kernel/qpointer/tst_qpointer.cpp index 3540df17ac..fd20a1cf5d 100644 --- a/tests/auto/corelib/kernel/qpointer/tst_qpointer.cpp +++ b/tests/auto/corelib/kernel/qpointer/tst_qpointer.cpp @@ -63,6 +63,8 @@ private slots: void disconnect(); void castDuringDestruction(); void threadSafety(); + + void qvariantCast(); }; void tst_QPointer::constructors() @@ -348,6 +350,41 @@ void tst_QPointer::threadSafety() owner.wait(); } +void tst_QPointer::qvariantCast() +{ + QPointer<QFile> tracking = new QFile; + tracking->setObjectName("A test name"); + QVariant v = QVariant::fromValue(tracking); + + { + QPointer<QObject> other = qPointerFromVariant<QObject>(v); + QCOMPARE(other->objectName(), QString::fromLatin1("A test name")); + } + { + QPointer<QIODevice> other = qPointerFromVariant<QIODevice>(v); + QCOMPARE(other->objectName(), QString::fromLatin1("A test name")); + } + { + QPointer<QFile> other = qPointerFromVariant<QFile>(v); + QCOMPARE(other->objectName(), QString::fromLatin1("A test name")); + } + { + QPointer<QThread> other = qPointerFromVariant<QThread>(v); + QVERIFY(!other); + } + { + QPointer<QFile> toBeDeleted = new QFile; + QVariant deletedVariant = QVariant::fromValue(toBeDeleted); + delete toBeDeleted; + QPointer<QObject> deleted = qPointerFromVariant<QObject>(deletedVariant); + QVERIFY(!deleted); + } + + // Intentionally does not compile. +// QPointer<int> sop = qPointerFromVariant<int>(v); +} + + QTEST_MAIN(tst_QPointer) #include "tst_qpointer.moc" diff --git a/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp b/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp index 70caad856b..6896b328d0 100644 --- a/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp +++ b/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp @@ -105,6 +105,8 @@ private slots: void invalidConstructs_data(); void invalidConstructs(); + void qvariantCast(); + public slots: void cleanup() { safetyCheck(); } @@ -1853,6 +1855,75 @@ void tst_QSharedPointer::invalidConstructs() } } +void tst_QSharedPointer::qvariantCast() +{ + QSharedPointer<QFile> sp = QSharedPointer<QFile>::create(); + sp->setObjectName("A test name"); + QVariant v = QVariant::fromValue(sp); + + { + QSharedPointer<QObject> other = qSharedPointerFromVariant<QObject>(v); + QCOMPARE(other->objectName(), QString::fromLatin1("A test name")); + } + { + QSharedPointer<QIODevice> other = qSharedPointerFromVariant<QIODevice>(v); + QCOMPARE(other->objectName(), QString::fromLatin1("A test name")); + } + { + QSharedPointer<QFile> other = qSharedPointerFromVariant<QFile>(v); + QCOMPARE(other->objectName(), QString::fromLatin1("A test name")); + } + { + QSharedPointer<QThread> other = qSharedPointerFromVariant<QThread>(v); + QVERIFY(!other); + } + // Intentionally does not compile. +// QSharedPointer<int> sop = qSharedPointerFromVariant<int>(v); + + v = QVariant::fromValue(sp.toWeakRef()); + + { + QWeakPointer<QObject> other = qWeakPointerFromVariant<QObject>(v); + QCOMPARE(other.data()->objectName(), QString::fromLatin1("A test name")); + } + { + QWeakPointer<QIODevice> other = qWeakPointerFromVariant<QIODevice>(v); + QCOMPARE(other.data()->objectName(), QString::fromLatin1("A test name")); + } + { + QWeakPointer<QFile> other = qWeakPointerFromVariant<QFile>(v); + QCOMPARE(other.data()->objectName(), QString::fromLatin1("A test name")); + } + { + QWeakPointer<QThread> other = qWeakPointerFromVariant<QThread>(v); + QVERIFY(!other); + } + + // Intentionally does not compile. +// QWeakPointer<int> sop = qWeakPointerFromVariant<int>(v); + + QWeakPointer<QFile> tracking = new QFile; + tracking.data()->setObjectName("A test name"); + v = QVariant::fromValue(tracking); + + { + QWeakPointer<QObject> other = qWeakPointerFromVariant<QObject>(v); + QCOMPARE(other.data()->objectName(), QString::fromLatin1("A test name")); + } + { + QWeakPointer<QIODevice> other = qWeakPointerFromVariant<QIODevice>(v); + QCOMPARE(other.data()->objectName(), QString::fromLatin1("A test name")); + } + { + QWeakPointer<QFile> other = qWeakPointerFromVariant<QFile>(v); + QCOMPARE(other.data()->objectName(), QString::fromLatin1("A test name")); + } + { + QWeakPointer<QThread> other = qWeakPointerFromVariant<QThread>(v); + QVERIFY(!other); + } +} + namespace ReentrancyWhileDestructing { struct IB { |