summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBea Lam <bea.lam@nokia.com>2010-02-25 00:38:43 (GMT)
committerBea Lam <bea.lam@nokia.com>2010-02-25 00:38:43 (GMT)
commitd654f87319408e3d9754fa5a8ad376c3eaef4489 (patch)
tree7276a6edf146fb9d1426dfd39714a6b2fbc3c4cf
parentfcfb08e40264c3417da91f4e187758d85f190a4f (diff)
downloadQt-d654f87319408e3d9754fa5a8ad376c3eaef4489.zip
Qt-d654f87319408e3d9754fa5a8ad376c3eaef4489.tar.gz
Qt-d654f87319408e3d9754fa5a8ad376c3eaef4489.tar.bz2
Automatically connect to signals "onFooChanged" if property is "foo".
This follows on from a2a8cea2835ef24104fe784b6ce0f508cc5637c0 to make it work for PropertyChanges and QDeclarativeMetaProperty as well. Task-number: QT-2783
-rw-r--r--src/declarative/qml/qdeclarativecompiler.cpp16
-rw-r--r--src/declarative/qml/qdeclarativecompiler_p.h3
-rw-r--r--src/declarative/qml/qdeclarativemetaproperty.cpp20
-rw-r--r--tests/auto/declarative/qdeclarativemetaproperty/tst_qdeclarativemetaproperty.cpp149
-rw-r--r--tests/auto/declarative/qdeclarativestates/data/basicChanges4.qml19
-rw-r--r--tests/auto/declarative/qdeclarativestates/tst_qdeclarativestates.cpp67
6 files changed, 232 insertions, 42 deletions
diff --git a/src/declarative/qml/qdeclarativecompiler.cpp b/src/declarative/qml/qdeclarativecompiler.cpp
index b6ebd60..0e54d45 100644
--- a/src/declarative/qml/qdeclarativecompiler.cpp
+++ b/src/declarative/qml/qdeclarativecompiler.cpp
@@ -1314,8 +1314,9 @@ int QDeclarativeCompiler::componentTypeRef()
return output->types.count() - 1;
}
-int QDeclarativeCompiler::findSignalByName(const QMetaObject *mo, const QByteArray &name)
+QMetaMethod QDeclarativeCompiler::findSignalByName(const QMetaObject *mo, const QByteArray &name)
{
+ Q_ASSERT(mo);
int methods = mo->methodCount();
for (int ii = methods - 1; ii >= 0; --ii) {
QMetaMethod method = mo->method(ii);
@@ -1324,7 +1325,7 @@ int QDeclarativeCompiler::findSignalByName(const QMetaObject *mo, const QByteArr
methodName = methodName.left(idx);
if (methodName == name)
- return ii;
+ return method;
}
// If no signal is found, but the signal is of the form "onBlahChanged",
@@ -1332,11 +1333,14 @@ int QDeclarativeCompiler::findSignalByName(const QMetaObject *mo, const QByteArr
if (name.endsWith("Changed")) {
QByteArray propName = name.mid(0, name.length() - 7);
int propIdx = mo->indexOfProperty(propName.constData());
- if (propIdx >= 0)
- return mo->property(propIdx).notifySignalIndex();
+ if (propIdx >= 0) {
+ QMetaProperty prop = mo->property(propIdx);
+ if (prop.hasNotifySignal())
+ return prop.notifySignal();
+ }
}
- return -1;
+ return QMetaMethod();
}
bool QDeclarativeCompiler::buildSignal(QDeclarativeParser::Property *prop, QDeclarativeParser::Object *obj,
@@ -1351,7 +1355,7 @@ bool QDeclarativeCompiler::buildSignal(QDeclarativeParser::Property *prop, QDecl
if(name[0] >= 'A' && name[0] <= 'Z')
name[0] = name[0] - 'A' + 'a';
- int sigIdx = findSignalByName(obj->metaObject(), name);
+ int sigIdx = findSignalByName(obj->metaObject(), name).methodIndex();
if (sigIdx == -1) {
diff --git a/src/declarative/qml/qdeclarativecompiler_p.h b/src/declarative/qml/qdeclarativecompiler_p.h
index 627490d..2ea3366 100644
--- a/src/declarative/qml/qdeclarativecompiler_p.h
+++ b/src/declarative/qml/qdeclarativecompiler_p.h
@@ -159,6 +159,8 @@ public:
static bool isAttachedPropertyName(const QByteArray &);
static bool isSignalPropertyName(const QByteArray &);
+ static QMetaMethod findSignalByName(const QMetaObject *, const QByteArray &name);
+
private:
static void reset(QDeclarativeCompiledData *);
@@ -263,7 +265,6 @@ private:
int componentTypeRef();
- static int findSignalByName(const QMetaObject *, const QByteArray &name);
static QDeclarativeType *toQmlType(QDeclarativeParser::Object *from);
bool canCoerce(int to, QDeclarativeParser::Object *from);
bool canCoerce(int to, int from);
diff --git a/src/declarative/qml/qdeclarativemetaproperty.cpp b/src/declarative/qml/qdeclarativemetaproperty.cpp
index e94ce8c..253174d 100644
--- a/src/declarative/qml/qdeclarativemetaproperty.cpp
+++ b/src/declarative/qml/qdeclarativemetaproperty.cpp
@@ -53,6 +53,7 @@
#include "qdeclarativedeclarativedata_p.h"
#include "qdeclarativestringconverters_p.h"
#include "qdeclarativelist_p.h"
+#include "qdeclarativecompiler_p.h"
#include <QStringList>
#include <QtCore/qdebug.h>
@@ -177,7 +178,7 @@ void QDeclarativeMetaPropertyPrivate::initProperty(QObject *obj, const QString &
QString signalName = name.mid(2);
signalName[0] = signalName.at(0).toLower();
- QMetaMethod method = findSignal(obj, signalName);
+ QMetaMethod method = QDeclarativeCompiler::findSignalByName(obj->metaObject(), signalName.toLatin1().constData());
if (method.signature()) {
core.load(method);
return;
@@ -631,23 +632,6 @@ QDeclarativeExpression *QDeclarativeMetaProperty::setSignalExpression(QDeclarati
}
}
-QMetaMethod QDeclarativeMetaPropertyPrivate::findSignal(QObject *obj, const QString &name)
-{
- const QMetaObject *mo = obj->metaObject();
-
- int methods = mo->methodCount();
- for (int ii = methods - 1; ii >= 0; --ii) {
- QMetaMethod method = mo->method(ii);
- QString methodName = QString::fromUtf8(method.signature());
- int idx = methodName.indexOf(QLatin1Char('('));
- methodName = methodName.left(idx);
-
- if (methodName == name)
- return method;
- }
- return QMetaMethod();
-}
-
QObject *QDeclarativeMetaPropertyPrivate::attachedObject() const
{
if (attachedFunc == -1)
diff --git a/tests/auto/declarative/qdeclarativemetaproperty/tst_qdeclarativemetaproperty.cpp b/tests/auto/declarative/qdeclarativemetaproperty/tst_qdeclarativemetaproperty.cpp
index e19bea0..028d8c4 100644
--- a/tests/auto/declarative/qdeclarativemetaproperty/tst_qdeclarativemetaproperty.cpp
+++ b/tests/auto/declarative/qdeclarativemetaproperty/tst_qdeclarativemetaproperty.cpp
@@ -180,6 +180,7 @@ class PropertyObject : public QObject
Q_PROPERTY(QRect wrectProperty READ wrectProperty WRITE setWRectProperty);
Q_PROPERTY(QUrl url READ url WRITE setUrl);
Q_PROPERTY(int resettableProperty READ resettableProperty WRITE setResettableProperty RESET resetProperty);
+ Q_PROPERTY(int propertyWithNotify READ propertyWithNotify WRITE setPropertyWithNotify NOTIFY oddlyNamedNotifySignal)
Q_CLASSINFO("DefaultProperty", "defaultProperty");
public:
@@ -198,13 +199,18 @@ public:
void setResettableProperty(int r) { m_resetProperty = r; }
void resetProperty() { m_resetProperty = 9; }
+ int propertyWithNotify() const { return m_propertyWithNotify; }
+ void setPropertyWithNotify(int i) { m_propertyWithNotify = i; emit oddlyNamedNotifySignal(); }
+
signals:
void clicked();
+ void oddlyNamedNotifySignal();
private:
int m_resetProperty;
QRect m_rect;
QUrl m_url;
+ int m_propertyWithNotify;
};
QML_DECLARE_TYPE(PropertyObject);
@@ -457,6 +463,54 @@ void tst_qdeclarativemetaproperty::qmlmetaproperty_object_string()
delete obj;
}
+
+ {
+ QDeclarativeMetaProperty prop(&dobject, QString("onPropertyWithNotifyChanged"));
+
+ QGuard<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
+ binding->setTarget(prop);
+ QVERIFY(binding != 0);
+ QGuard<QDeclarativeExpression> expression(new QDeclarativeExpression());
+ QVERIFY(expression != 0);
+
+ QObject *obj = new QObject;
+
+ QCOMPARE(prop.name(), QString("onOddlyNamedNotifySignal"));
+ QCOMPARE(prop.read(), QVariant());
+ QCOMPARE(prop.write(QVariant("Hello")), false);
+ QCOMPARE(prop.hasChangedNotifier(), false);
+ QCOMPARE(prop.needsChangedNotifier(), false);
+ QCOMPARE(prop.connectNotifier(0, SLOT(deleteLater())), false);
+ QCOMPARE(prop.connectNotifier(obj, SLOT(deleteLater())), false);
+ QCOMPARE(prop.connectNotifier(obj, 0), false);
+ QCOMPARE(prop.connectNotifier(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
+ QCOMPARE(prop.connectNotifier(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
+ QCOMPARE(prop.connectNotifier(obj, -1), false);
+ QCOMPARE(QString(prop.method().signature()), QString("oddlyNamedNotifySignal()"));
+ QCOMPARE(prop.type(), QDeclarativeMetaProperty::SignalProperty);
+ QCOMPARE(prop.isProperty(), false);
+ QCOMPARE(prop.isDefault(), false);
+ QCOMPARE(prop.isWritable(), false);
+ QCOMPARE(prop.isDesignable(), false);
+ QCOMPARE(prop.isResettable(), false);
+ QCOMPARE(prop.isValid(), true);
+ QCOMPARE(prop.object(), &dobject);
+ QCOMPARE(prop.propertyCategory(), QDeclarativeMetaProperty::InvalidProperty);
+ QCOMPARE(prop.propertyType(), 0);
+ QCOMPARE(prop.propertyTypeName(), (const char *)0);
+ QCOMPARE(prop.property().name(), (const char *)0);
+ QVERIFY(prop.binding() == 0);
+ QVERIFY(prop.setBinding(binding) == 0);
+ QVERIFY(binding == 0);
+ QVERIFY(prop.signalExpression() == 0);
+ QVERIFY(prop.setSignalExpression(expression) == 0);
+ QVERIFY(expression != 0);
+ QVERIFY(prop.signalExpression() == expression);
+ QCOMPARE(prop.coreIndex(), dobject.metaObject()->indexOfMethod("oddlyNamedNotifySignal()"));
+ QCOMPARE(prop.valueTypeCoreIndex(), -1);
+
+ delete obj;
+ }
}
void tst_qdeclarativemetaproperty::qmlmetaproperty_object_context()
@@ -707,6 +761,54 @@ void tst_qdeclarativemetaproperty::qmlmetaproperty_object_string_context()
delete obj;
}
+
+ {
+ QDeclarativeMetaProperty prop(&dobject, QString("onPropertyWithNotifyChanged"), engine.rootContext());
+
+ QGuard<QDeclarativeBinding> binding(new QDeclarativeBinding(QLatin1String("null"), 0, engine.rootContext()));
+ binding->setTarget(prop);
+ QVERIFY(binding != 0);
+ QGuard<QDeclarativeExpression> expression(new QDeclarativeExpression());
+ QVERIFY(expression != 0);
+
+ QObject *obj = new QObject;
+
+ QCOMPARE(prop.name(), QString("onOddlyNamedNotifySignal"));
+ QCOMPARE(prop.read(), QVariant());
+ QCOMPARE(prop.write(QVariant("Hello")), false);
+ QCOMPARE(prop.hasChangedNotifier(), false);
+ QCOMPARE(prop.needsChangedNotifier(), false);
+ QCOMPARE(prop.connectNotifier(0, SLOT(deleteLater())), false);
+ QCOMPARE(prop.connectNotifier(obj, SLOT(deleteLater())), false);
+ QCOMPARE(prop.connectNotifier(obj, 0), false);
+ QCOMPARE(prop.connectNotifier(0, obj->metaObject()->indexOfMethod("deleteLater()")), false);
+ QCOMPARE(prop.connectNotifier(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false);
+ QCOMPARE(prop.connectNotifier(obj, -1), false);
+ QCOMPARE(QString(prop.method().signature()), QString("oddlyNamedNotifySignal()"));
+ QCOMPARE(prop.type(), QDeclarativeMetaProperty::SignalProperty);
+ QCOMPARE(prop.isProperty(), false);
+ QCOMPARE(prop.isDefault(), false);
+ QCOMPARE(prop.isWritable(), false);
+ QCOMPARE(prop.isDesignable(), false);
+ QCOMPARE(prop.isResettable(), false);
+ QCOMPARE(prop.isValid(), true);
+ QCOMPARE(prop.object(), &dobject);
+ QCOMPARE(prop.propertyCategory(), QDeclarativeMetaProperty::InvalidProperty);
+ QCOMPARE(prop.propertyType(), 0);
+ QCOMPARE(prop.propertyTypeName(), (const char *)0);
+ QCOMPARE(prop.property().name(), (const char *)0);
+ QVERIFY(prop.binding() == 0);
+ QVERIFY(prop.setBinding(binding) == 0);
+ QVERIFY(binding == 0);
+ QVERIFY(prop.signalExpression() == 0);
+ QVERIFY(prop.setSignalExpression(expression) == 0);
+ QVERIFY(expression != 0);
+ QVERIFY(prop.signalExpression() == expression);
+ QCOMPARE(prop.coreIndex(), dobject.metaObject()->indexOfMethod("oddlyNamedNotifySignal()"));
+ QCOMPARE(prop.valueTypeCoreIndex(), -1);
+
+ delete obj;
+ }
}
void tst_qdeclarativemetaproperty::name()
@@ -741,6 +843,18 @@ void tst_qdeclarativemetaproperty::name()
}
{
+ PropertyObject o;
+ QDeclarativeMetaProperty p(&o, "onPropertyWithNotifyChanged");
+ QCOMPARE(p.name(), QString("onOddlyNamedNotifySignal"));
+ }
+
+ {
+ QObject o;
+ QDeclarativeMetaProperty p(&o, "onPropertyWithNotifyChanged");
+ QCOMPARE(p.name(), QString());
+ }
+
+ {
QObject o;
QDeclarativeMetaProperty p(&o, "foo");
QCOMPARE(p.name(), QString());
@@ -830,6 +944,18 @@ void tst_qdeclarativemetaproperty::read()
QCOMPARE(p.read(), QVariant());
}
+ // Automatic signal property
+ {
+ PropertyObject o;
+ QDeclarativeMetaProperty p(&o, "onPropertyWithNotifyChanged");
+ QCOMPARE(p.read(), QVariant());
+
+ QVERIFY(0 == p.setSignalExpression(new QDeclarativeExpression()));
+ QVERIFY(0 != p.signalExpression());
+
+ QCOMPARE(p.read(), QVariant());
+ }
+
// Deleted object
{
PropertyObject *o = new PropertyObject;
@@ -936,6 +1062,20 @@ void tst_qdeclarativemetaproperty::write()
QVERIFY(0 != p.signalExpression());
}
+ // Automatic signal property
+ {
+ PropertyObject o;
+ QDeclarativeMetaProperty p(&o, "onPropertyWithNotifyChanged");
+ QCOMPARE(p.write(QVariant("console.log(1921)")), false);
+
+ QVERIFY(0 == p.setSignalExpression(new QDeclarativeExpression()));
+ QVERIFY(0 != p.signalExpression());
+
+ QCOMPARE(p.write(QVariant("console.log(1921)")), false);
+
+ QVERIFY(0 != p.signalExpression());
+ }
+
// Value-type property
{
PropertyObject o;
@@ -1065,6 +1205,15 @@ void tst_qdeclarativemetaproperty::reset()
QCOMPARE(p.isResettable(), false);
QCOMPARE(p.reset(), false);
}
+
+ // Automatic signal property
+ {
+ PropertyObject o;
+ QDeclarativeMetaProperty p(&o, "onPropertyWithNotifyChanged");
+
+ QCOMPARE(p.isResettable(), false);
+ QCOMPARE(p.reset(), false);
+ }
}
void tst_qdeclarativemetaproperty::writeObjectToList()
diff --git a/tests/auto/declarative/qdeclarativestates/data/basicChanges4.qml b/tests/auto/declarative/qdeclarativestates/data/basicChanges4.qml
new file mode 100644
index 0000000..a373cfc
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativestates/data/basicChanges4.qml
@@ -0,0 +1,19 @@
+import Qt.test 1.0
+import Qt 4.6
+
+MyRectangle {
+ id: rect
+ width: 100; height: 100
+ color: "red"
+
+ states: State {
+ name: "aBlueDay"
+ PropertyChanges {
+ target: rect
+ onPropertyWithNotifyChanged: { rect.color = "blue"; }
+ }
+ }
+
+ Component.onCompleted: rect.state = "aBlueDay"
+}
+
diff --git a/tests/auto/declarative/qdeclarativestates/tst_qdeclarativestates.cpp b/tests/auto/declarative/qdeclarativestates/tst_qdeclarativestates.cpp
index 44fb51f..feac9c2 100644
--- a/tests/auto/declarative/qdeclarativestates/tst_qdeclarativestates.cpp
+++ b/tests/auto/declarative/qdeclarativestates/tst_qdeclarativestates.cpp
@@ -46,6 +46,29 @@
#include <private/qdeclarativepropertychanges_p.h>
#include <private/qdeclarativestategroup_p.h>
+
+class MyRect : public QDeclarativeRectangle
+{
+ Q_OBJECT
+ Q_PROPERTY(int propertyWithNotify READ propertyWithNotify WRITE setPropertyWithNotify NOTIFY oddlyNamedNotifySignal)
+public:
+ MyRect() {}
+
+ void doSomething() { emit didSomething(); }
+
+ int propertyWithNotify() const { return m_prop; }
+ void setPropertyWithNotify(int i) { m_prop = i; emit oddlyNamedNotifySignal(); }
+Q_SIGNALS:
+ void didSomething();
+ void oddlyNamedNotifySignal();
+
+private:
+ int m_prop;
+};
+
+QML_DECLARE_TYPE(MyRect)
+
+
class tst_qdeclarativestates : public QObject
{
Q_OBJECT
@@ -83,6 +106,11 @@ private slots:
void nonExistantProperty();
};
+void tst_qdeclarativestates::initTestCase()
+{
+ QML_REGISTER_TYPE(Qt.test, 1, 0, MyRectangle,MyRect);
+}
+
QByteArray tst_qdeclarativestates::fullDataPath(const QString &path)
{
return QUrl::fromLocalFile(SRCDIR + path).toString().toUtf8();
@@ -156,6 +184,28 @@ void tst_qdeclarativestates::basicChanges()
QCOMPARE(rect->border()->width(),1);
}
+
+ {
+ // Test basicChanges4.qml can magically connect to propertyWithNotify's notify
+ // signal using 'onPropertyWithNotifyChanged' even though the signal name is
+ // actually 'oddlyNamedNotifySignal'
+
+ QDeclarativeComponent component(&engine, SRCDIR "/data/basicChanges4.qml");
+ QVERIFY(component.isReady());
+
+ MyRect *rect = qobject_cast<MyRect*>(component.create());
+ QVERIFY(rect != 0);
+
+ QMetaProperty prop = rect->metaObject()->property(rect->metaObject()->indexOfProperty("propertyWithNotify"));
+ QVERIFY(prop.hasNotifySignal());
+ QString notifySignal = QByteArray(prop.notifySignal().signature());
+ QVERIFY(!notifySignal.startsWith("propertyWithNotifyChanged("));
+
+ QCOMPARE(rect->color(), QColor(Qt::red));
+
+ rect->setPropertyWithNotify(100);
+ QCOMPARE(rect->color(), QColor(Qt::blue));
+ }
}
void tst_qdeclarativestates::basicExtension()
@@ -335,23 +385,6 @@ void tst_qdeclarativestates::basicBinding()
}
}
-class MyRect : public QDeclarativeRectangle
-{
- Q_OBJECT
-public:
- MyRect() {}
- void doSomething() { emit didSomething(); }
-Q_SIGNALS:
- void didSomething();
-};
-
-QML_DECLARE_TYPE(MyRect)
-
-void tst_qdeclarativestates::initTestCase()
-{
- QML_REGISTER_TYPE(Qt.test, 1, 0, MyRectangle,MyRect);
-}
-
void tst_qdeclarativestates::signalOverride()
{
QDeclarativeEngine engine;