aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/qml/qml/qqmlproperty.cpp10
-rw-r--r--src/qml/qml/qqmlpropertycache.cpp2
-rw-r--r--src/qml/qml/v8/qv8engine.cpp2
-rw-r--r--tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp21
-rw-r--r--tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp1
-rw-r--r--tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp58
6 files changed, 87 insertions, 7 deletions
diff --git a/src/qml/qml/qqmlproperty.cpp b/src/qml/qml/qqmlproperty.cpp
index d1ecfdc52d..cf1b5ffd18 100644
--- a/src/qml/qml/qqmlproperty.cpp
+++ b/src/qml/qml/qqmlproperty.cpp
@@ -1611,10 +1611,14 @@ QQmlMetaObject QQmlPropertyPrivate::rawMetaObjectForType(QQmlEnginePrivate *engi
{
if (engine) {
return engine->rawMetaObjectForType(userType);
- } else {
- QQmlType *type = QQmlMetaType::qmlType(userType);
- return QQmlMetaObject(type?type->baseMetaObject():0);
}
+ QQmlType *type = QQmlMetaType::qmlType(userType);
+ if (type)
+ return QQmlMetaObject(type->baseMetaObject());
+ QMetaType metaType(userType);
+ if ((metaType.flags() & QMetaType::PointerToQObject) && metaType.metaObject())
+ return metaType.metaObject();
+ return QQmlMetaObject((QObject*)0);
}
/*!
diff --git a/src/qml/qml/qqmlpropertycache.cpp b/src/qml/qml/qqmlpropertycache.cpp
index 6d44b61aee..a1385e06fc 100644
--- a/src/qml/qml/qqmlpropertycache.cpp
+++ b/src/qml/qml/qqmlpropertycache.cpp
@@ -124,7 +124,7 @@ static QQmlPropertyData::Flags flagsForPropertyType(int propType, QQmlEngine *en
engine ? QQmlEnginePrivate::get(engine)->typeCategory(propType)
: QQmlMetaType::typeCategory(propType);
- if (cat == QQmlMetaType::Object)
+ if (cat == QQmlMetaType::Object || QMetaType::typeFlags(propType) & QMetaType::PointerToQObject)
flags |= QQmlPropertyData::IsQObjectDerived;
else if (cat == QQmlMetaType::List)
flags |= QQmlPropertyData::IsQList;
diff --git a/src/qml/qml/v8/qv8engine.cpp b/src/qml/qml/v8/qv8engine.cpp
index 117fea272c..6737c14b17 100644
--- a/src/qml/qml/v8/qv8engine.cpp
+++ b/src/qml/qml/v8/qv8engine.cpp
@@ -310,6 +310,8 @@ QV4::Value QV8Engine::fromVariant(const QVariant &variant)
a->arrayData[ii].value = QV4::QObjectWrapper::wrap(m_v4Engine, list.at(ii));
a->setArrayLengthUnchecked(list.count());
return QV4::Value::fromObject(a);
+ } else if (QMetaType::typeFlags(type) & QMetaType::PointerToQObject) {
+ return QV4::QObjectWrapper::wrap(m_v4Engine, *reinterpret_cast<QObject* const *>(ptr));
}
bool objOk;
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()