summaryrefslogtreecommitdiffstats
path: root/src/declarative/util
diff options
context:
space:
mode:
authorWarwick Allison <warwick.allison@nokia.com>2010-02-26 07:04:38 (GMT)
committerWarwick Allison <warwick.allison@nokia.com>2010-02-26 07:04:38 (GMT)
commite1f33f2e4689a59de2814ffdea7ea246bbfe0283 (patch)
treee3a0d74f5e54f78b83d0c05d6e1588c5f1d47e37 /src/declarative/util
parent93b02976b7c9c3a36cac475c1935622ebc2f1fe1 (diff)
downloadQt-e1f33f2e4689a59de2814ffdea7ea246bbfe0283.zip
Qt-e1f33f2e4689a59de2814ffdea7ea246bbfe0283.tar.gz
Qt-e1f33f2e4689a59de2814ffdea7ea246bbfe0283.tar.bz2
Change Connection syntax as per QT-2822.
Diffstat (limited to 'src/declarative/util')
-rw-r--r--src/declarative/util/qdeclarativeconnection.cpp250
-rw-r--r--src/declarative/util/qdeclarativeconnection_p.h43
-rw-r--r--src/declarative/util/qdeclarativeutilmodule.cpp3
3 files changed, 130 insertions, 166 deletions
diff --git a/src/declarative/util/qdeclarativeconnection.cpp b/src/declarative/util/qdeclarativeconnection.cpp
index e9ae74b..a180509 100644
--- a/src/declarative/util/qdeclarativeconnection.cpp
+++ b/src/declarative/util/qdeclarativeconnection.cpp
@@ -42,8 +42,10 @@
#include "qdeclarativeconnection_p.h"
#include <qdeclarativeexpression.h>
+#include <qdeclarativeproperty_p.h>
#include <qdeclarativeboundsignal_p.h>
#include <qdeclarativecontext.h>
+#include <qdeclarativeinfo.h>
#include <QtCore/qdebug.h>
#include <QtCore/qstringlist.h>
@@ -52,236 +54,192 @@
QT_BEGIN_NAMESPACE
-class QDeclarativeConnectionPrivate : public QObjectPrivate
+class QDeclarativeConnectionsPrivate : public QObjectPrivate
{
public:
- QDeclarativeConnectionPrivate() : boundsignal(0), signalSender(0), scriptset(false), componentcomplete(false) {}
+ QDeclarativeConnectionsPrivate() : target(0), componentcomplete(false) {}
+
+ QList<QDeclarativeBoundSignal*> boundsignals;
+ QObject *target;
- QDeclarativeBoundSignal *boundsignal;
- QObject *signalSender;
- QDeclarativeScriptString script;
- bool scriptset;
- QString signal;
bool componentcomplete;
+
+ QByteArray data;
};
/*!
- \qmlclass Connection QDeclarativeConnection
+ \qmlclass Connections QDeclarativeConnections
\since 4.7
- \brief A Connection object describes generalized connections to signals.
+ \brief A Connections object describes generalized connections to signals.
When connecting to signals in QML, the usual way is to create an
"on<Signal>" handler that reacts when a signal is received, like this:
\qml
MouseArea {
- onClicked: { foo(x+123,y+456) }
+ onClicked: { foo(...) }
}
\endqml
However, in some cases, it is not possible to connect to a signal in this
- way. For example, JavaScript-in-HTML style signal properties do not allow:
+ way, such as:
\list
- \i connecting to signals with the same name but different parameters
- \i conformance checking that parameters are correctly named
\i multiple connections to the same signal
\i connections outside the scope of the signal sender
- \i signals in classes with coincidentally-named on<Signal> properties
+ \i connections to targets not defined in QML
\endlist
- When any of these are needed, the Connection object can be used instead.
+ When any of these are needed, the Connections object can be used instead.
- For example, the above code can be changed to use a Connection object,
+ For example, the above code can be changed to use a Connections object,
like this:
\qml
MouseArea {
- Connection {
- signal: "clicked(x,y)"
- script: { foo(x+123,y+456) }
+ Connections {
+ onClicked: foo(...)
}
}
\endqml
- More generally, the Connection object can be a child of some other object than
+ More generally, the Connections object can be a child of some other object than
the sender of the signal:
\qml
MouseArea {
- id: mr
+ id: area
}
...
- Connection {
- sender: mr
- signal: "clicked(x,y)"
- script: { foo(x+123,y+456) }
+ Connections {
+ target: area
+ onClicked: foo(...)
}
\endqml
*/
/*!
\internal
- \class QDeclarativeConnection
- \brief The QDeclarativeConnection class describes generalized connections to signals.
+ \class QDeclarativeConnections
+ \brief The QDeclarativeConnections class describes generalized connections to signals.
*/
-QDeclarativeConnection::QDeclarativeConnection(QObject *parent) :
- QObject(*(new QDeclarativeConnectionPrivate), parent)
+QDeclarativeConnections::QDeclarativeConnections(QObject *parent) :
+ QObject(*(new QDeclarativeConnectionsPrivate), parent)
{
}
-QDeclarativeConnection::~QDeclarativeConnection()
+QDeclarativeConnections::~QDeclarativeConnections()
{
- Q_D(QDeclarativeConnection);
- delete d->boundsignal;
}
/*!
- \qmlproperty Object Connection::sender
+ \qmlproperty Object Connections::target
This property holds the object that sends the signal.
- By default, the sender is assumed to be the parent of the Connection.
+ By default, the target is assumed to be the parent of the Connections.
*/
-QObject *QDeclarativeConnection::signalSender() const
+QObject *QDeclarativeConnections::target() const
{
- Q_D(const QDeclarativeConnection);
- return d->signalSender ? d->signalSender : parent();
+ Q_D(const QDeclarativeConnections);
+ return d->target ? d->target : parent();
}
-void QDeclarativeConnection::setSignalSender(QObject *obj)
+void QDeclarativeConnections::setTarget(QObject *obj)
{
- Q_D(QDeclarativeConnection);
- if (d->signalSender == obj)
+ Q_D(QDeclarativeConnections);
+ if (d->target == obj)
return;
- disconnectIfValid();
- d->signalSender = obj;
- connectIfValid();
+ foreach (QDeclarativeBoundSignal *s, d->boundsignals)
+ delete s;
+ d->boundsignals.clear();
+ d->target = obj;
+ connectSignals();
+ emit targetChanged();
}
-void QDeclarativeConnection::connectIfValid()
+
+QByteArray
+QDeclarativeConnectionsParser::compile(const QList<QDeclarativeCustomParserProperty> &props)
{
- Q_D(QDeclarativeConnection);
- if (!d->componentcomplete)
- return;
- // boundsignal must not exist
- if ((d->signalSender || parent()) && !d->signal.isEmpty() && d->scriptset) {
- // create
- // XXX scope?
- int sigIdx = -1;
- int lparen = d->signal.indexOf(QLatin1Char('('));
- QList<QByteArray> sigparams;
- if (lparen >= 0 && d->signal.length() > lparen+2) {
- QStringList l = d->signal.mid(lparen+1,d->signal.length()-lparen-2).split(QLatin1Char(','));
- foreach (const QString &s, l) {
- sigparams.append(s.trimmed().toUtf8());
- }
+ QByteArray rv;
+ QDataStream ds(&rv, QIODevice::WriteOnly);
+
+ for(int ii = 0; ii < props.count(); ++ii)
+ {
+ QString propName = QString::fromUtf8(props.at(ii).name());
+ if (!propName.startsWith(QLatin1String("on")) || !propName.at(2).isUpper()) {
+ error(props.at(ii), QDeclarativeConnections::tr("Cannot assign to non-existent property \"%1\"").arg(propName));
+ return QByteArray();
}
- QString signalname = d->signal.left(lparen);
- QObject *sender = d->signalSender ? d->signalSender : parent();
- const QMetaObject *mo = sender->metaObject();
- int methods = mo->methodCount();
- for (int ii = 0; ii < methods; ++ii) {
- QMetaMethod method = mo->method(ii);
- QString methodName = QString::fromUtf8(method.signature());
- int idx = methodName.indexOf(QLatin1Char('('));
- methodName = methodName.left(idx);
- if (methodName == signalname && (lparen<0 || method.parameterNames() == sigparams)) {
- sigIdx = ii;
- break;
+
+ QList<QVariant> values = props.at(ii).assignedValues();
+
+ for (int i = 0; i < values.count(); ++i) {
+ const QVariant &value = values.at(i);
+
+ if (value.userType() == qMetaTypeId<QDeclarativeCustomParserNode>()) {
+ error(props.at(ii), QDeclarativeConnections::tr("Connections: nested objects not allowed"));
+ return QByteArray();
+ } else if (value.userType() == qMetaTypeId<QDeclarativeCustomParserProperty>()) {
+ error(props.at(ii), QDeclarativeConnections::tr("Connections: syntax error"));
+ return QByteArray();
+ } else {
+ QDeclarativeParser::Variant v = qvariant_cast<QDeclarativeParser::Variant>(value);
+ if (v.isScript()) {
+ ds << propName;
+ ds << v.asScript();
+ } else {
+ error(props.at(ii), QDeclarativeConnections::tr("Connections: script expected"));
+ return QByteArray();
+ }
}
}
- if (sigIdx < 0) {
- // Cannot usefully warn, since could be in middle of
- // changing sender and signal.
- // XXX need state change transactions to do better
- return;
- }
-
- d->boundsignal = new QDeclarativeBoundSignal(qmlContext(this), d->script.script(), sender, mo->method(sigIdx), this);
}
-}
-void QDeclarativeConnection::disconnectIfValid()
-{
- Q_D(QDeclarativeConnection);
- if (!d->componentcomplete)
- return;
- if ((d->signalSender || parent()) && !d->signal.isEmpty() && d->scriptset) {
- // boundsignal must exist
- // destroy
- delete d->boundsignal;
- d->boundsignal = 0;
- }
+ return rv;
}
-void QDeclarativeConnection::componentComplete()
+void QDeclarativeConnectionsParser::setCustomData(QObject *object,
+ const QByteArray &data)
{
- Q_D(QDeclarativeConnection);
- d->componentcomplete=true;
- connectIfValid();
+ QDeclarativeConnectionsPrivate *p =
+ static_cast<QDeclarativeConnectionsPrivate *>(QObjectPrivate::get(object));
+ p->data = data;
}
-/*!
- \qmlproperty script Connection::script
- This property holds the JavaScript executed whenever the signal is sent.
-*/
-QDeclarativeScriptString QDeclarativeConnection::script() const
+void QDeclarativeConnections::connectSignals()
{
- Q_D(const QDeclarativeConnection);
- return d->script;
-}
+ Q_D(QDeclarativeConnections);
+ if (!d->componentcomplete)
+ return;
-void QDeclarativeConnection::setScript(const QDeclarativeScriptString& script)
-{
- Q_D(QDeclarativeConnection);
- if ((d->signalSender || parent()) && !d->signal.isEmpty()) {
- if (!d->scriptset) {
- // mustn't exist - create
- d->scriptset = true;
- d->script = script;
- connectIfValid();
+ QDataStream ds(d->data);
+ while (!ds.atEnd()) {
+ QString propName;
+ ds >> propName;
+ 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) {
+ QDeclarativeBoundSignal *signal =
+ new QDeclarativeBoundSignal(target(), prop.method(), this);
+ signal->setExpression(new QDeclarativeExpression(qmlContext(this), script, 0));
+ d->boundsignals += signal;
} else {
- // must exist - update
- d->script = script;
- d->boundsignal->expression()->setExpression(script.script());
+ qmlInfo(this) << tr("Cannot assign to non-existent property \"%1\"").arg(propName);
}
- } else {
- d->scriptset = true;
- d->script = script;
}
}
-/*!
- \qmlproperty string Connection::signal
- This property holds the signal from the sender to which the script is attached.
-
- The signal's formal parameter names must be given in parentheses:
-
- \qml
-Connection {
- signal: "clicked(x,y)"
- script: { ... }
-}
- \endqml
-*/
-QString QDeclarativeConnection::signal() const
-{
- Q_D(const QDeclarativeConnection);
- return d->signal;
-}
-
-void QDeclarativeConnection::setSignal(const QString& sig)
+void QDeclarativeConnections::componentComplete()
{
- Q_D(QDeclarativeConnection);
- if (d->signal == sig)
- return;
- disconnectIfValid();
- d->signal = sig;
- connectIfValid();
+ Q_D(QDeclarativeConnections);
+ d->componentcomplete=true;
+ connectSignals();
}
-
-
QT_END_NAMESPACE
diff --git a/src/declarative/util/qdeclarativeconnection_p.h b/src/declarative/util/qdeclarativeconnection_p.h
index ae2efe9..3eacf12 100644
--- a/src/declarative/util/qdeclarativeconnection_p.h
+++ b/src/declarative/util/qdeclarativeconnection_p.h
@@ -39,11 +39,12 @@
**
****************************************************************************/
-#ifndef QDECLARATIVECONNECTION_H
-#define QDECLARATIVECONNECTION_H
+#ifndef QDECLARATIVECONNECTIONS_H
+#define QDECLARATIVECONNECTIONS_H
#include <qdeclarative.h>
#include <qdeclarativescriptstring.h>
+#include <private/qdeclarativecustomparser_p.h>
#include <QtCore/qobject.h>
#include <QtCore/qstring.h>
@@ -56,37 +57,41 @@ QT_MODULE(Declarative)
class QDeclarativeBoundSignal;
class QDeclarativeContext;
-class QDeclarativeConnectionPrivate;
-class Q_DECLARATIVE_EXPORT QDeclarativeConnection : public QObject, public QDeclarativeParserStatus
+class QDeclarativeConnectionsPrivate;
+class Q_DECLARATIVE_EXPORT QDeclarativeConnections : public QObject, public QDeclarativeParserStatus
{
Q_OBJECT
- Q_DECLARE_PRIVATE(QDeclarativeConnection)
+ Q_DECLARE_PRIVATE(QDeclarativeConnections)
Q_INTERFACES(QDeclarativeParserStatus)
- Q_PROPERTY(QObject *sender READ signalSender WRITE setSignalSender)
- Q_PROPERTY(QDeclarativeScriptString script READ script WRITE setScript)
- Q_PROPERTY(QString signal READ signal WRITE setSignal)
+ Q_PROPERTY(QObject *target READ target WRITE setTarget NOTIFY targetChanged)
public:
- QDeclarativeConnection(QObject *parent=0);
- ~QDeclarativeConnection();
+ QDeclarativeConnections(QObject *parent=0);
+ ~QDeclarativeConnections();
- QObject *signalSender() const;
- void setSignalSender(QObject *);
- QDeclarativeScriptString script() const;
- void setScript(const QDeclarativeScriptString&);
- QString signal() const;
- void setSignal(const QString&);
+ QObject *target() const;
+ void setTarget(QObject *);
+
+Q_SIGNALS:
+ void targetChanged();
private:
- void disconnectIfValid();
- void connectIfValid();
+ void connectSignals();
void componentComplete();
};
+class QDeclarativeConnectionsParser : public QDeclarativeCustomParser
+{
+public:
+ virtual QByteArray compile(const QList<QDeclarativeCustomParserProperty> &);
+ virtual void setCustomData(QObject *, const QByteArray &);
+};
+
+
QT_END_NAMESPACE
-QML_DECLARE_TYPE(QDeclarativeConnection)
+QML_DECLARE_TYPE(QDeclarativeConnections)
QT_END_HEADER
diff --git a/src/declarative/util/qdeclarativeutilmodule.cpp b/src/declarative/util/qdeclarativeutilmodule.cpp
index 8d3d682..3d34e33 100644
--- a/src/declarative/util/qdeclarativeutilmodule.cpp
+++ b/src/declarative/util/qdeclarativeutilmodule.cpp
@@ -80,7 +80,7 @@ void QDeclarativeUtilModule::defineModule()
QML_REGISTER_TYPE(Qt,4,6,Behavior,QDeclarativeBehavior);
QML_REGISTER_TYPE(Qt,4,6,Binding,QDeclarativeBind);
QML_REGISTER_TYPE(Qt,4,6,ColorAnimation,QDeclarativeColorAnimation);
- QML_REGISTER_TYPE(Qt,4,6,Connection,QDeclarativeConnection);
+ QML_REGISTER_TYPE(Qt,4,6,Connections,QDeclarativeConnections);
QML_REGISTER_TYPE(Qt,4,6,DateTimeFormatter,QDeclarativeDateTimeFormatter);
QML_REGISTER_TYPE(Qt,4,6,EaseFollow,QDeclarativeEaseFollow);;
QML_REGISTER_TYPE(Qt,4,6,FontLoader,QDeclarativeFontLoader);
@@ -118,4 +118,5 @@ void QDeclarativeUtilModule::defineModule()
QML_REGISTER_CUSTOM_TYPE(Qt, 4,6, ListModel, QDeclarativeListModel, QDeclarativeListModelParser);
QML_REGISTER_CUSTOM_TYPE(Qt, 4,6, PropertyChanges, QDeclarativePropertyChanges, QDeclarativePropertyChangesParser);
+ QML_REGISTER_CUSTOM_TYPE(Qt, 4,6, Connections, QDeclarativeConnections, QDeclarativeConnectionsParser);
}