Add some internal API for extracting a QSharedPointer<T> 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<T> can be inserted into a QVariant, and where T derives from QObject, a QSharedPointer<QObject> can be extracted from the QVariant, and its properties are then accessible. Change-Id: I68d6d89aceceb019267bd7301baa2047f9c09b90 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>bb10
parent
534bcc9667
commit
668efc29fd
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue