diff options
author | Warwick Allison <warwick.allison@nokia.com> | 2010-04-29 00:31:18 (GMT) |
---|---|---|
committer | Warwick Allison <warwick.allison@nokia.com> | 2010-04-29 00:31:18 (GMT) |
commit | 44708167042e95ab4b5cfef8a19a9ab4f9484a71 (patch) | |
tree | b5b710dd4c9e5ee42e90e3ab6b4a9a5ed1a6080a | |
parent | c7e48e0ff2b49856e62379845731defd21d2134c (diff) | |
download | Qt-44708167042e95ab4b5cfef8a19a9ab4f9484a71.zip Qt-44708167042e95ab4b5cfef8a19a9ab4f9484a71.tar.gz Qt-44708167042e95ab4b5cfef8a19a9ab4f9484a71.tar.bz2 |
Stricter (but controllable) error reporting on Connections signal-name error. And test.
3 files changed, 77 insertions, 8 deletions
diff --git a/src/declarative/util/qdeclarativeconnections.cpp b/src/declarative/util/qdeclarativeconnections.cpp index 20d878b..c23b623 100644 --- a/src/declarative/util/qdeclarativeconnections.cpp +++ b/src/declarative/util/qdeclarativeconnections.cpp @@ -57,11 +57,13 @@ QT_BEGIN_NAMESPACE class QDeclarativeConnectionsPrivate : public QObjectPrivate { public: - QDeclarativeConnectionsPrivate() : target(0), componentcomplete(false) {} + QDeclarativeConnectionsPrivate() : target(0), ignoreUnknownSignals(false), componentcomplete(false) {} QList<QDeclarativeBoundSignal*> boundsignals; QObject *target; + bool targetSet; + bool ignoreUnknownSignals; bool componentcomplete; QByteArray data; @@ -139,17 +141,21 @@ QDeclarativeConnections::~QDeclarativeConnections() \qmlproperty Object Connections::target This property holds the object that sends the signal. - By default, the target is assumed to be the parent of the Connections. + If not set at all, the target defaults to be the parent of the Connections. + + If set to null, no connection is made and any signal handlers are ignored + until the target is not null. */ QObject *QDeclarativeConnections::target() const { Q_D(const QDeclarativeConnections); - return d->target ? d->target : parent(); + return d->targetSet ? d->target : parent(); } void QDeclarativeConnections::setTarget(QObject *obj) { Q_D(QDeclarativeConnections); + d->targetSet = true; // even if setting to 0, it is *set* if (d->target == obj) return; foreach (QDeclarativeBoundSignal *s, d->boundsignals) { @@ -166,6 +172,29 @@ void QDeclarativeConnections::setTarget(QObject *obj) emit targetChanged(); } +/*! + \qmlproperty bool Connections::ignoreUnknownSignals + + Normally, you will get a runtime error if you try to connect + to signals on an object which the object does not have. + + By setting this flag to true, such errors are ignored. This is + useful if you intend to connect to different types of object, handling + a different set of signals for each. +*/ +bool QDeclarativeConnections::ignoreUnknownSignals() const +{ + Q_D(const QDeclarativeConnections); + return d->ignoreUnknownSignals; +} + +void QDeclarativeConnections::setIgnoreUnknownSignals(bool ignore) +{ + Q_D(QDeclarativeConnections); + d->ignoreUnknownSignals = ignore; +} + + QByteArray QDeclarativeConnectionsParser::compile(const QList<QDeclarativeCustomParserProperty> &props) @@ -220,7 +249,7 @@ void QDeclarativeConnectionsParser::setCustomData(QObject *object, void QDeclarativeConnections::connectSignals() { Q_D(QDeclarativeConnections); - if (!d->componentcomplete) + if (!d->componentcomplete || (d->targetSet && !target())) return; QDataStream ds(d->data); @@ -230,15 +259,14 @@ void QDeclarativeConnections::connectSignals() QString script; ds >> script; QDeclarativeProperty prop(target(), propName); - if (!prop.isValid()) { - qmlInfo(this) << tr("Cannot assign to non-existent property \"%1\"").arg(propName); - } else if (prop.type() & QDeclarativeProperty::SignalProperty) { + if (prop.isValid() && (prop.type() & QDeclarativeProperty::SignalProperty)) { QDeclarativeBoundSignal *signal = new QDeclarativeBoundSignal(target(), prop.method(), this); signal->setExpression(new QDeclarativeExpression(qmlContext(this), script, 0)); d->boundsignals += signal; } else { - qmlInfo(this) << tr("Cannot assign to non-existent property \"%1\"").arg(propName); + if (!d->ignoreUnknownSignals) + qmlInfo(this) << tr("Cannot assign to non-existent property \"%1\"").arg(propName); } } } diff --git a/src/declarative/util/qdeclarativeconnections_p.h b/src/declarative/util/qdeclarativeconnections_p.h index 3eacf12..b51899e 100644 --- a/src/declarative/util/qdeclarativeconnections_p.h +++ b/src/declarative/util/qdeclarativeconnections_p.h @@ -65,6 +65,7 @@ class Q_DECLARATIVE_EXPORT QDeclarativeConnections : public QObject, public QDec Q_INTERFACES(QDeclarativeParserStatus) Q_PROPERTY(QObject *target READ target WRITE setTarget NOTIFY targetChanged) + Q_PROPERTY(bool ignoreUnknownSignals READ ignoreUnknownSignals WRITE setIgnoreUnknownSignals) public: QDeclarativeConnections(QObject *parent=0); @@ -73,6 +74,9 @@ public: QObject *target() const; void setTarget(QObject *); + bool ignoreUnknownSignals() const; + void setIgnoreUnknownSignals(bool ignore); + Q_SIGNALS: void targetChanged(); diff --git a/tests/auto/declarative/qdeclarativeconnection/tst_qdeclarativeconnection.cpp b/tests/auto/declarative/qdeclarativeconnection/tst_qdeclarativeconnection.cpp index 0efae3b..00e97ca 100644 --- a/tests/auto/declarative/qdeclarativeconnection/tst_qdeclarativeconnection.cpp +++ b/tests/auto/declarative/qdeclarativeconnection/tst_qdeclarativeconnection.cpp @@ -59,6 +59,8 @@ private slots: void connection(); void trimming(); void targetChanged(); + void unknownSignals_data(); + void unknownSignals(); private: QDeclarativeEngine engine; @@ -156,6 +158,41 @@ void tst_qdeclarativeconnection::targetChanged() delete item; } +void tst_qdeclarativeconnection::unknownSignals_data() +{ + QTest::addColumn<QString>("file"); + QTest::addColumn<QString>("error"); + + QTest::newRow("basic") << "connection-unknownsignals.qml" << ":6:5: QML Connections: Cannot assign to non-existent property \"onFooBar\""; + QTest::newRow("parent") << "connection-unknownsignals-parent.qml" << ":6:5: QML Connections: Cannot assign to non-existent property \"onFooBar\""; + QTest::newRow("ignored") << "connection-unknownsignals-ignored.qml" << ""; // should be NO error + QTest::newRow("notarget") << "connection-unknownsignals-notarget.qml" << ""; // should be NO error +} + +void tst_qdeclarativeconnection::unknownSignals() +{ + QFETCH(QString, file); + QFETCH(QString, error); + + QUrl url = QUrl::fromLocalFile(SRCDIR "/data/" + file); + if (!error.isEmpty()) { + QTest::ignoreMessage(QtWarningMsg, (url.toString() + error).toLatin1()); + } else { + // QTest has no way to insist no message (i.e. fail) + } + + QDeclarativeEngine engine; + QDeclarativeComponent c(&engine, url); + QDeclarativeItem *item = qobject_cast<QDeclarativeItem*>(c.create()); + QVERIFY(item != 0); + + // check that connection is created (they are all runtime errors) + QDeclarativeConnections *connections = item->findChild<QDeclarativeConnections*>("connections"); + QVERIFY(connections); + + delete item; +} + QTEST_MAIN(tst_qdeclarativeconnection) #include "tst_qdeclarativeconnection.moc" |