From: Stephen Kelly Date: Sat, 9 Jun 2012 20:57:35 +0000 (+0200) Subject: Add some internal API for extracting a QSharedPointer from QVariant. X-Git-Tag: 071012110112~327 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=668efc29fd85bbae2395a4eca8d0ad71ad6ee3d1;p=profile%2Fivi%2Fqtbase.git Add some internal API for extracting a QSharedPointer from QVariant. The T must be derived from QObject, or it will fail to compile. This will allow scripting or other 'wrapping' and runtime environments like QtDeclarative to handle QSharedPointers to types derived from QObject properly. A QSharedPointer can be inserted into a QVariant, and where T derives from QObject, a QSharedPointer can be extracted from the QVariant, and its properties are then accessible. Change-Id: I68d6d89aceceb019267bd7301baa2047f9c09b90 Reviewed-by: Thiago Macieira --- diff --git a/src/corelib/kernel/qpointer.h b/src/corelib/kernel/qpointer.h index 88d8225..ef1d4dc 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 8ca153f..73a1e6c 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 46cd1cc..9d9698b 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 3540df1..fd20a1c 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 70caad8..6896b32 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 {