diff options
author | Stephen Kelly <stephen.kelly@kdab.com> | 2012-01-12 20:01:15 +0100 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-09-10 11:17:46 +0200 |
commit | 59ed8c355b99df0b949003a438ab850274261aa0 (patch) | |
tree | 7f019270e9e8457d385d94c6e8a9b1679b396fb2 /tests | |
parent | f20d726766bf5e875f96fc5ce8885afe5c3fae4a (diff) |
Make it possible to handle pointers to QObject derived in QML.
This way, properties of QObject derived types can be read in QML
code for example:
Q_PROPERTY(MyObject* obj READ obj CONSTANT)
Previously, only QObject* types could be read by QML:
Q_PROPERTY(QObject* obj READ obj CONSTANT)
This meant that multiple properties and methods had to be created
for classes which were relevant to both QML and non-QML code.
This patch lifts that restriction.
As a consequence, we can also remove a Q_EXPECT_FAIL from
the qqmllanguage unit test. That test was introduced in
commit 92562eacbc3c (Allow signal parameters which are custom QML
object-types, 2012-07-13) to document knowledge of the limitation
while fixing it as much as possible.
Task-number: QTBUG-26662
Change-Id: Ic85fa73c6f3655189438ec509765bae2eab9993a
Reviewed-by: Alan Alpert (Personal) <416365416c@gmail.com>
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
Diffstat (limited to 'tests')
-rw-r--r-- | tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp | 21 | ||||
-rw-r--r-- | tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp | 1 | ||||
-rw-r--r-- | tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp | 58 |
3 files changed, 77 insertions, 3 deletions
diff --git a/tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp b/tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp index e0c20307a8..4f21231184 100644 --- a/tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp +++ b/tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp @@ -72,6 +72,7 @@ private slots: void qtbug_22535(); void evalAfterInvalidate(); + void qobjectDerived(); private: QQmlEngine engine; @@ -659,6 +660,26 @@ void tst_qqmlcontext::evalAfterInvalidate() QCoreApplication::processEvents(); } +void tst_qqmlcontext::qobjectDerived() +{ + QQmlEngine engine; + QQmlComponent component(&engine, testFileUrl("refreshExpressions.qml")); + + CountCommand command; + // This test is similar to refreshExpressions, but with the key difference that + // we use the QVariant overload of setContextProperty. That way, we test that + // QVariant knowledge that it contains a QObject derived pointer is used. + engine.rootContext()->setContextProperty("countCommand", QVariant::fromValue(&command)); + + // We use a fresh context here to bypass any root-context optimizations in + // the engine + QQmlContext context(engine.rootContext()); + + QObject *o1 = component.create(&context); + + QCOMPARE(command.count, 2); +} + QTEST_MAIN(tst_qqmlcontext) #include "tst_qqmlcontext.moc" diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp index 3e2493effe..acb623989a 100644 --- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp +++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp @@ -3016,7 +3016,6 @@ void tst_qqmllanguage::signalParameterTypes() QQmlComponent component(&engine, testFileUrl("signalParameterTypes.2.qml")); QObject *obj = component.create(); QVERIFY(obj != 0); - QEXPECT_FAIL("", "Dynamic connections don't enforce type safety - QTBUG-26662", Abort); QVERIFY(obj->property("success").toBool()); delete obj; } diff --git a/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp b/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp index 418e2edf27..27c3fd985e 100644 --- a/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp +++ b/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp @@ -57,11 +57,24 @@ class MyQmlObject : public QObject { Q_OBJECT public: - MyQmlObject() {} + MyQmlObject(QObject *parent = 0) : QObject(parent) {} }; QML_DECLARE_TYPE(MyQmlObject); +class MyQObject : public QObject +{ + Q_OBJECT +public: + MyQObject(QObject *parent = 0) : QObject(parent), m_i(0) {} + + int inc() { return ++m_i; } + +private: + int m_i; +}; + + class MyAttached : public QObject { Q_OBJECT @@ -316,10 +329,11 @@ class PropertyObject : public QObject Q_PROPERTY(int resettableProperty READ resettableProperty WRITE setResettableProperty RESET resetProperty) Q_PROPERTY(int propertyWithNotify READ propertyWithNotify WRITE setPropertyWithNotify NOTIFY oddlyNamedNotifySignal) Q_PROPERTY(MyQmlObject *qmlObject READ qmlObject) + Q_PROPERTY(MyQObject *qObject READ qObject WRITE setQObject NOTIFY qObjectChanged) Q_CLASSINFO("DefaultProperty", "defaultProperty") public: - PropertyObject() : m_resetProperty(9) {} + PropertyObject() : m_resetProperty(9), m_qObject(0) {} int defaultProperty() { return 10; } QRect rectProperty() { return QRect(10, 10, 1, 209); } @@ -342,9 +356,19 @@ public: MyQmlObject *qmlObject() { return &m_qmlObject; } + MyQObject *qObject() { return m_qObject; } + void setQObject(MyQObject *object) + { + if (m_qObject != object) { + m_qObject = object; + emit qObjectChanged(); + } + } + signals: void clicked(); void oddlyNamedNotifySignal(); + void qObjectChanged(); private: int m_resetProperty; @@ -353,6 +377,7 @@ private: QVariantMap m_variantMap; int m_propertyWithNotify; MyQmlObject m_qmlObject; + MyQObject *m_qObject; }; QML_DECLARE_TYPE(PropertyObject); @@ -1130,6 +1155,18 @@ void tst_qqmlproperty::read() QCOMPARE(p.read(), QVariant()); } + // Object property registered with Qt, but not registered with QML. + { + PropertyObject o; + QQmlProperty p(&o, "qObject"); + QCOMPARE(p.propertyTypeCategory(), QQmlProperty::Object); + + QCOMPARE(p.propertyType(), qMetaTypeId<MyQObject*>()); + QVariant v = p.read(); + QVERIFY(v.canConvert(QMetaType::QObjectStar)); + QVERIFY(qvariant_cast<QObject *>(v) == o.qObject()); + } + // Object property { PropertyObject o; @@ -1387,6 +1424,23 @@ void tst_qqmlproperty::write() QCOMPARE(p.read(), QVariant(99)); delete object; } + // Writable pointer to QObject derived + { + PropertyObject o; + QQmlProperty p(&o, QString("qObject")); + QCOMPARE(o.qObject(), (QObject*)0); + QObject *newObject = new MyQObject(this); + QCOMPARE(p.write(QVariant::fromValue(newObject)), true); + QCOMPARE(o.qObject(), newObject); + QVariant data = p.read(); + QCOMPARE(data.value<QObject*>(), newObject); + QCOMPARE(data.value<MyQObject*>(), newObject); + // Incompatible types can not be written. + QCOMPARE(p.write(QVariant::fromValue(new MyQmlObject(this))), false); + QVariant newData = p.read(); + QCOMPARE(newData.value<QObject*>(), newObject); + QCOMPARE(newData.value<MyQObject*>(), newObject); + } } void tst_qqmlproperty::reset() |