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 &p) { Q_ASSERT(i == 0); return !i && !p.isNull(); } #endif +template +QPointer +qPointerFromVariant(const QVariant &variant) +{ + return QPointer(qobject_cast(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 if the variant contains + a QSharedPointer where T inherits QObject. Otherwise the behaviour is undefined. +*/ +QSharedPointer QtSharedPointer::sharedPointerFromVariant_internal(const QVariant &variant) +{ + return *reinterpret_cast*>(variant.constData()); +} + +/** + \internal + Returns a QWeakPointer if the variant contains + a QWeakPointer where T inherits QObject. Otherwise the behaviour is undefined. +*/ +QWeakPointer QtSharedPointer::weakPointerFromVariant_internal(const QVariant &variant) +{ + return *reinterpret_cast*>(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 inline void qt_sharedpointer_cast_check(T *) { } template class QWeakPointer; template class QSharedPointer; +class QVariant; + template QSharedPointer qSharedPointerCast(const QSharedPointer &ptr); template @@ -258,6 +260,9 @@ namespace QtSharedPointer { ~ExternalRefCountWithContiguousData() Q_DECL_EQ_DELETE; Q_DISABLE_COPY(ExternalRefCountWithContiguousData) }; + + Q_CORE_EXPORT QWeakPointer weakPointerFromVariant_internal(const QVariant &variant); + Q_CORE_EXPORT QSharedPointer sharedPointerFromVariant_internal(const QVariant &variant); } // namespace QtSharedPointer template class QSharedPointer @@ -816,8 +821,21 @@ qobject_cast(const QWeakPointer &src) { return qSharedPointerObjectCast::Type, T>(src); } -#endif +template +QWeakPointer::Value, T>::Type> +qWeakPointerFromVariant(const QVariant &variant) +{ + return QWeakPointer(qobject_cast(QtSharedPointer::weakPointerFromVariant_internal(variant).data())); +} +template +QSharedPointer::Value, T>::Type> +qSharedPointerFromVariant(const QVariant &variant) +{ + return qSharedPointerObjectCast(QtSharedPointer::sharedPointerFromVariant_internal(variant)); +} + +#endif template Q_DECLARE_TYPEINFO_BODY(QWeakPointer, Q_MOVABLE_TYPE); template Q_DECLARE_TYPEINFO_BODY(QSharedPointer, 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 tracking = new QFile; + tracking->setObjectName("A test name"); + QVariant v = QVariant::fromValue(tracking); + + { + QPointer other = qPointerFromVariant(v); + QCOMPARE(other->objectName(), QString::fromLatin1("A test name")); + } + { + QPointer other = qPointerFromVariant(v); + QCOMPARE(other->objectName(), QString::fromLatin1("A test name")); + } + { + QPointer other = qPointerFromVariant(v); + QCOMPARE(other->objectName(), QString::fromLatin1("A test name")); + } + { + QPointer other = qPointerFromVariant(v); + QVERIFY(!other); + } + { + QPointer toBeDeleted = new QFile; + QVariant deletedVariant = QVariant::fromValue(toBeDeleted); + delete toBeDeleted; + QPointer deleted = qPointerFromVariant(deletedVariant); + QVERIFY(!deleted); + } + + // Intentionally does not compile. +// QPointer sop = qPointerFromVariant(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 sp = QSharedPointer::create(); + sp->setObjectName("A test name"); + QVariant v = QVariant::fromValue(sp); + + { + QSharedPointer other = qSharedPointerFromVariant(v); + QCOMPARE(other->objectName(), QString::fromLatin1("A test name")); + } + { + QSharedPointer other = qSharedPointerFromVariant(v); + QCOMPARE(other->objectName(), QString::fromLatin1("A test name")); + } + { + QSharedPointer other = qSharedPointerFromVariant(v); + QCOMPARE(other->objectName(), QString::fromLatin1("A test name")); + } + { + QSharedPointer other = qSharedPointerFromVariant(v); + QVERIFY(!other); + } + // Intentionally does not compile. +// QSharedPointer sop = qSharedPointerFromVariant(v); + + v = QVariant::fromValue(sp.toWeakRef()); + + { + QWeakPointer other = qWeakPointerFromVariant(v); + QCOMPARE(other.data()->objectName(), QString::fromLatin1("A test name")); + } + { + QWeakPointer other = qWeakPointerFromVariant(v); + QCOMPARE(other.data()->objectName(), QString::fromLatin1("A test name")); + } + { + QWeakPointer other = qWeakPointerFromVariant(v); + QCOMPARE(other.data()->objectName(), QString::fromLatin1("A test name")); + } + { + QWeakPointer other = qWeakPointerFromVariant(v); + QVERIFY(!other); + } + + // Intentionally does not compile. +// QWeakPointer sop = qWeakPointerFromVariant(v); + + QWeakPointer tracking = new QFile; + tracking.data()->setObjectName("A test name"); + v = QVariant::fromValue(tracking); + + { + QWeakPointer other = qWeakPointerFromVariant(v); + QCOMPARE(other.data()->objectName(), QString::fromLatin1("A test name")); + } + { + QWeakPointer other = qWeakPointerFromVariant(v); + QCOMPARE(other.data()->objectName(), QString::fromLatin1("A test name")); + } + { + QWeakPointer other = qWeakPointerFromVariant(v); + QCOMPARE(other.data()->objectName(), QString::fromLatin1("A test name")); + } + { + QWeakPointer other = qWeakPointerFromVariant(v); + QVERIFY(!other); + } +} + namespace ReentrancyWhileDestructing { struct IB {