aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml
diff options
context:
space:
mode:
authorTasuku Suzuki <stasuku@gmail.com>2012-11-25 04:36:33 +0900
committerThe Qt Project <gerrit-noreply@qt-project.org>2012-11-29 17:48:46 +0100
commite0cb13a510c0099784fee00d5b4b7c608dd42dd2 (patch)
tree8d61daaaa70df2fa7b26a0c989d748fc3718e15f /src/qml
parent55f6a109e99ea2eb3359fa941a1826d4b4e11bf8 (diff)
Move no-Gui related QML types from QtQuick into QtQml
Task-number: QTBUG-26340 Change-Id: I9049128db2598bf3c7a9d677b774eaae53b54eb5 Reviewed-by: Alan Alpert <aalpert@rim.com> Reviewed-by: Lars Knoll <lars.knoll@digia.com> Reviewed-by: Gunnar Sletta <gunnar.sletta@digia.com>
Diffstat (limited to 'src/qml')
-rw-r--r--src/qml/qml/qml.pri11
-rw-r--r--src/qml/qml/qqmlbind.cpp310
-rw-r--r--src/qml/qml/qqmlbind_p.h96
-rw-r--r--src/qml/qml/qqmlconnections.cpp321
-rw-r--r--src/qml/qml/qqmlconnections_p.h100
-rw-r--r--src/qml/qml/qqmlengine.cpp8
-rw-r--r--src/qml/qml/qqmltimer.cpp328
-rw-r--r--src/qml/qml/qqmltimer_p.h111
8 files changed, 1283 insertions, 2 deletions
diff --git a/src/qml/qml/qml.pri b/src/qml/qml/qml.pri
index e7286c25fb..20b46f0939 100644
--- a/src/qml/qml/qml.pri
+++ b/src/qml/qml/qml.pri
@@ -52,7 +52,10 @@ SOURCES += \
$$PWD/qqmlglobal.cpp \
$$PWD/qqmlfile.cpp \
$$PWD/qqmlbundle.cpp \
- $$PWD/qqmlmemoryprofiler.cpp
+ $$PWD/qqmlmemoryprofiler.cpp \
+ $$PWD/qqmlconnections.cpp \
+ $$PWD/qqmltimer.cpp \
+ $$PWD/qqmlbind.cpp
HEADERS += \
$$PWD/qqmlglobal_p.h \
@@ -125,7 +128,11 @@ HEADERS += \
$$PWD/qqmlvaluetypeproxybinding_p.h \
$$PWD/qqmlfile.h \
$$PWD/qqmlbundle_p.h \
- $$PWD/qqmlmemoryprofiler_p.h
+ $$PWD/qqmlmemoryprofiler_p.h \
+ $$PWD/qqmlconnections_p.h \
+ $$PWD/qqmltimer_p.h \
+ $$PWD/qqmlbind_p.h
+
include(parser/parser.pri)
include(rewriter/rewriter.pri)
diff --git a/src/qml/qml/qqmlbind.cpp b/src/qml/qml/qqmlbind.cpp
new file mode 100644
index 0000000000..2df9693dfa
--- /dev/null
+++ b/src/qml/qml/qqmlbind.cpp
@@ -0,0 +1,310 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qqmlbind_p.h"
+
+#include <private/qqmlnullablevalue_p_p.h>
+#include <private/qqmlproperty_p.h>
+#include <private/qqmlbinding_p.h>
+#include <private/qqmlguard_p.h>
+
+#include <qqmlengine.h>
+#include <qqmlcontext.h>
+#include <qqmlproperty.h>
+#include <qqmlinfo.h>
+
+#include <QtCore/qfile.h>
+#include <QtCore/qdebug.h>
+
+#include <private/qobject_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQmlBindPrivate : public QObjectPrivate
+{
+public:
+ QQmlBindPrivate() : componentComplete(true), obj(0), prevBind(0) {}
+ ~QQmlBindPrivate() { if (prevBind) prevBind->destroy(); }
+
+ QQmlNullableValue<bool> when;
+ bool componentComplete;
+ QQmlGuard<QObject> obj;
+ QString propName;
+ QQmlNullableValue<QVariant> value;
+ QQmlProperty prop;
+ QQmlAbstractBinding *prevBind;
+};
+
+
+/*!
+ \qmltype Binding
+ \instantiates QQmlBind
+ \inqmlmodule QtQuick 2
+ \ingroup qtquick-interceptors
+ \brief Enables the arbitrary creation of property bindings
+
+ \section1 Binding to an inaccessible property
+
+ Sometimes it is necessary to bind to a property of an object that wasn't
+ directly instantiated by QML - generally a property of a class exported
+ to QML by C++. In these cases, regular property binding doesn't work. Binding
+ allows you to bind any value to any property.
+
+ For example, imagine a C++ application that maps an "app.enteredText"
+ property into QML. You could use Binding to update the enteredText property
+ like this.
+ \code
+ TextEdit { id: myTextField; text: "Please type here..." }
+ Binding { target: app; property: "enteredText"; value: myTextField.text }
+ \endcode
+ Whenever the text in the TextEdit is updated, the C++ property will be
+ updated also.
+
+ \section1 "Single-branch" conditional binding
+
+ In some circumstances you may want to control the value of a property
+ only when a certain condition is true (and relinquish control in all
+ other circumstances). This often isn't possible to accomplish with a direct
+ binding, as you need to supply values for all possible branches.
+
+ \code
+ // produces warning: "Unable to assign [undefined] to double value"
+ value: if (mouse.pressed) mouse.mouseX
+ \endcode
+
+ The above example will produce a warning whenever we release the mouse, as the value
+ of the binding is undefined when the mouse isn't pressed. We can use the Binding
+ type to rewrite the above code and avoid the warning.
+
+ \qml
+ Binding on value {
+ when: mouse.pressed
+ value: mouse.mouseX
+ }
+ \endqml
+
+ The Binding type will also restore any previously set direct bindings on
+ the property. In that sense, it functions much like a simplified State.
+
+ \qml
+ // this is equivalent to the above Binding
+ State {
+ name: "pressed"
+ when: mouse.pressed
+ PropertyChanges {
+ target: obj
+ value: mouse.mouseX
+ }
+ }
+ \endqml
+
+ If the binding target or binding property is changed, the bound value is
+ immediately pushed onto the new target.
+
+ \sa QtQml
+*/
+QQmlBind::QQmlBind(QObject *parent)
+ : QObject(*(new QQmlBindPrivate), parent)
+{
+}
+
+QQmlBind::~QQmlBind()
+{
+}
+
+/*!
+ \qmlproperty bool QtQuick2::Binding::when
+
+ This property holds when the binding is active.
+ This should be set to an expression that evaluates to true when you want the binding to be active.
+
+ \code
+ Binding {
+ target: contactName; property: 'text'
+ value: name; when: list.ListView.isCurrentItem
+ }
+ \endcode
+
+ When the binding becomes inactive again, any direct bindings that were previously
+ set on the property will be restored.
+*/
+bool QQmlBind::when() const
+{
+ Q_D(const QQmlBind);
+ return d->when;
+}
+
+void QQmlBind::setWhen(bool v)
+{
+ Q_D(QQmlBind);
+ if (!d->when.isNull && d->when == v)
+ return;
+
+ d->when = v;
+ eval();
+}
+
+/*!
+ \qmlproperty Object QtQuick2::Binding::target
+
+ The object to be updated.
+*/
+QObject *QQmlBind::object()
+{
+ Q_D(const QQmlBind);
+ return d->obj;
+}
+
+void QQmlBind::setObject(QObject *obj)
+{
+ Q_D(QQmlBind);
+ if (d->obj && d->when.isValid() && d->when) {
+ /* if we switch the object at runtime, we need to restore the
+ previous binding on the old object before continuing */
+ d->when = false;
+ eval();
+ d->when = true;
+ }
+ d->obj = obj;
+ if (d->componentComplete)
+ d->prop = QQmlProperty(d->obj, d->propName);
+ eval();
+}
+
+/*!
+ \qmlproperty string QtQuick2::Binding::property
+
+ The property to be updated.
+*/
+QString QQmlBind::property() const
+{
+ Q_D(const QQmlBind);
+ return d->propName;
+}
+
+void QQmlBind::setProperty(const QString &p)
+{
+ Q_D(QQmlBind);
+ if (!d->propName.isEmpty() && d->when.isValid() && d->when) {
+ /* if we switch the property name at runtime, we need to restore the
+ previous binding on the old object before continuing */
+ d->when = false;
+ eval();
+ d->when = true;
+ }
+ d->propName = p;
+ if (d->componentComplete)
+ d->prop = QQmlProperty(d->obj, d->propName);
+ eval();
+}
+
+/*!
+ \qmlproperty any QtQuick2::Binding::value
+
+ The value to be set on the target object and property. This can be a
+ constant (which isn't very useful), or a bound expression.
+*/
+QVariant QQmlBind::value() const
+{
+ Q_D(const QQmlBind);
+ return d->value.value;
+}
+
+void QQmlBind::setValue(const QVariant &v)
+{
+ Q_D(QQmlBind);
+ d->value = v;
+ eval();
+}
+
+void QQmlBind::setTarget(const QQmlProperty &p)
+{
+ Q_D(QQmlBind);
+ d->prop = p;
+}
+
+void QQmlBind::classBegin()
+{
+ Q_D(QQmlBind);
+ d->componentComplete = false;
+}
+
+void QQmlBind::componentComplete()
+{
+ Q_D(QQmlBind);
+ d->componentComplete = true;
+ if (!d->prop.isValid())
+ d->prop = QQmlProperty(d->obj, d->propName);
+ eval();
+}
+
+void QQmlBind::eval()
+{
+ Q_D(QQmlBind);
+ if (!d->prop.isValid() || d->value.isNull || !d->componentComplete)
+ return;
+
+ if (d->when.isValid()) {
+ if (!d->when) {
+ //restore any previous binding
+ if (d->prevBind) {
+ QQmlAbstractBinding *tmp = d->prevBind;
+ d->prevBind = 0;
+ tmp = QQmlPropertyPrivate::setBinding(d->prop, tmp);
+ if (tmp) //should this ever be true?
+ tmp->destroy();
+ }
+ return;
+ }
+
+ //save any set binding for restoration
+ QQmlAbstractBinding *tmp;
+ tmp = QQmlPropertyPrivate::setBinding(d->prop, 0);
+ if (tmp && d->prevBind)
+ tmp->destroy();
+ else if (!d->prevBind)
+ d->prevBind = tmp;
+ }
+
+ d->prop.write(d->value.value);
+}
+
+QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlbind_p.h b/src/qml/qml/qqmlbind_p.h
new file mode 100644
index 0000000000..02e2767da9
--- /dev/null
+++ b/src/qml/qml/qqmlbind_p.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQMLBIND_H
+#define QQMLBIND_H
+
+#include <qqml.h>
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QQmlBindPrivate;
+class Q_AUTOTEST_EXPORT QQmlBind : public QObject, public QQmlPropertyValueSource, public QQmlParserStatus
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QQmlBind)
+ Q_INTERFACES(QQmlParserStatus)
+ Q_INTERFACES(QQmlPropertyValueSource)
+ Q_PROPERTY(QObject *target READ object WRITE setObject)
+ Q_PROPERTY(QString property READ property WRITE setProperty)
+ Q_PROPERTY(QVariant value READ value WRITE setValue)
+ Q_PROPERTY(bool when READ when WRITE setWhen)
+
+public:
+ QQmlBind(QObject *parent=0);
+ ~QQmlBind();
+
+ bool when() const;
+ void setWhen(bool);
+
+ QObject *object();
+ void setObject(QObject *);
+
+ QString property() const;
+ void setProperty(const QString &);
+
+ QVariant value() const;
+ void setValue(const QVariant &);
+
+protected:
+ virtual void setTarget(const QQmlProperty &);
+ virtual void classBegin();
+ virtual void componentComplete();
+
+private:
+ void eval();
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QQmlBind)
+
+QT_END_HEADER
+
+#endif
diff --git a/src/qml/qml/qqmlconnections.cpp b/src/qml/qml/qqmlconnections.cpp
new file mode 100644
index 0000000000..ab631ed3b2
--- /dev/null
+++ b/src/qml/qml/qqmlconnections.cpp
@@ -0,0 +1,321 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qqmlconnections_p.h"
+
+#include <private/qqmlexpression_p.h>
+#include <private/qqmlproperty_p.h>
+#include <private/qqmlboundsignal_p.h>
+#include <qqmlcontext.h>
+#include <private/qqmlcontext_p.h>
+#include <qqmlinfo.h>
+
+#include <QtCore/qdebug.h>
+#include <QtCore/qstringlist.h>
+
+#include <private/qobject_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQmlConnectionsPrivate : public QObjectPrivate
+{
+public:
+ QQmlConnectionsPrivate() : target(0), targetSet(false), ignoreUnknownSignals(false), componentcomplete(true) {}
+
+ QList<QQmlBoundSignal*> boundsignals;
+ QObject *target;
+
+ bool targetSet;
+ bool ignoreUnknownSignals;
+ bool componentcomplete;
+
+ QByteArray data;
+};
+
+/*!
+ \qmltype Connections
+ \instantiates QQmlConnections
+ \inqmlmodule QtQuick 2
+ \ingroup qtquick-interceptors
+ \brief Describes generalized connections to signals
+
+ A Connections object creates a connection to a QML signal.
+
+ 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(parameters) }
+ }
+ \endqml
+
+ However, it is not possible to connect to a signal in this way in some
+ cases, such as when:
+
+ \list
+ \li Multiple connections to the same signal are required
+ \li Creating connections outside the scope of the signal sender
+ \li Connecting to targets not defined in QML
+ \endlist
+
+ When any of these are needed, the Connections type can be used instead.
+
+ For example, the above code can be changed to use a Connections object,
+ like this:
+
+ \qml
+ MouseArea {
+ Connections {
+ onClicked: foo(parameters)
+ }
+ }
+ \endqml
+
+ More generally, the Connections object can be a child of some object other than
+ the sender of the signal:
+
+ \qml
+ MouseArea {
+ id: area
+ }
+ // ...
+ \endqml
+ \qml
+ Connections {
+ target: area
+ onClicked: foo(parameters)
+ }
+ \endqml
+
+ \sa QtQml
+*/
+QQmlConnections::QQmlConnections(QObject *parent) :
+ QObject(*(new QQmlConnectionsPrivate), parent)
+{
+}
+
+QQmlConnections::~QQmlConnections()
+{
+}
+
+/*!
+ \qmlproperty Object QtQuick2::Connections::target
+ This property holds the object that sends the signal.
+
+ If this property is not set, the \c target defaults to the parent of the Connection.
+
+ If set to null, no connection is made and any signal handlers are ignored
+ until the target is not null.
+*/
+QObject *QQmlConnections::target() const
+{
+ Q_D(const QQmlConnections);
+ return d->targetSet ? d->target : parent();
+}
+
+class QQmlBoundSignalDeleter : public QObject
+{
+public:
+ QQmlBoundSignalDeleter(QQmlBoundSignal *signal) : m_signal(signal) { m_signal->removeFromObject(); }
+ ~QQmlBoundSignalDeleter() { delete m_signal; }
+
+private:
+ QQmlBoundSignal *m_signal;
+};
+
+void QQmlConnections::setTarget(QObject *obj)
+{
+ Q_D(QQmlConnections);
+ d->targetSet = true; // even if setting to 0, it is *set*
+ if (d->target == obj)
+ return;
+ foreach (QQmlBoundSignal *s, d->boundsignals) {
+ // It is possible that target is being changed due to one of our signal
+ // handlers -> use deleteLater().
+ if (s->isEvaluating())
+ (new QQmlBoundSignalDeleter(s))->deleteLater();
+ else
+ delete s;
+ }
+ d->boundsignals.clear();
+ d->target = obj;
+ connectSignals();
+ emit targetChanged();
+}
+
+/*!
+ \qmlproperty bool QtQuick2::Connections::ignoreUnknownSignals
+
+ Normally, a connection to a non-existent signal produces runtime errors.
+
+ If this property is set to \c true, such errors are ignored.
+ This is useful if you intend to connect to different types of objects, handling
+ a different set of signals for each object.
+*/
+bool QQmlConnections::ignoreUnknownSignals() const
+{
+ Q_D(const QQmlConnections);
+ return d->ignoreUnknownSignals;
+}
+
+void QQmlConnections::setIgnoreUnknownSignals(bool ignore)
+{
+ Q_D(QQmlConnections);
+ d->ignoreUnknownSignals = ignore;
+}
+
+
+
+QByteArray
+QQmlConnectionsParser::compile(const QList<QQmlCustomParserProperty> &props)
+{
+ QByteArray rv;
+ QDataStream ds(&rv, QIODevice::WriteOnly);
+
+ for(int ii = 0; ii < props.count(); ++ii)
+ {
+ QString propName = props.at(ii).name();
+ int propLine = props.at(ii).location().line;
+ int propColumn = props.at(ii).location().column;
+
+ if (!propName.startsWith(QLatin1String("on")) || !propName.at(2).isUpper()) {
+ error(props.at(ii), QQmlConnections::tr("Cannot assign to non-existent property \"%1\"").arg(propName));
+ return QByteArray();
+ }
+
+ 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<QQmlCustomParserNode>()) {
+ error(props.at(ii), QQmlConnections::tr("Connections: nested objects not allowed"));
+ return QByteArray();
+ } else if (value.userType() == qMetaTypeId<QQmlCustomParserProperty>()) {
+ error(props.at(ii), QQmlConnections::tr("Connections: syntax error"));
+ return QByteArray();
+ } else {
+ QQmlScript::Variant v = qvariant_cast<QQmlScript::Variant>(value);
+ if (v.isScript()) {
+ ds << propName;
+ ds << rewriteSignalHandler(v, propName).toUtf8();
+ ds << propLine;
+ ds << propColumn;
+ } else {
+ error(props.at(ii), QQmlConnections::tr("Connections: script expected"));
+ return QByteArray();
+ }
+ }
+ }
+ }
+
+ return rv;
+}
+
+void QQmlConnectionsParser::setCustomData(QObject *object,
+ const QByteArray &data)
+{
+ QQmlConnectionsPrivate *p =
+ static_cast<QQmlConnectionsPrivate *>(QObjectPrivate::get(object));
+ p->data = data;
+}
+
+
+void QQmlConnections::connectSignals()
+{
+ Q_D(QQmlConnections);
+ if (!d->componentcomplete || (d->targetSet && !target()))
+ return;
+
+ QDataStream ds(d->data);
+ while (!ds.atEnd()) {
+ QString propName;
+ ds >> propName;
+ QByteArray script;
+ ds >> script;
+ int line;
+ ds >> line;
+ int column;
+ ds >> column;
+
+ QQmlProperty prop(target(), propName);
+ if (prop.isValid() && (prop.type() & QQmlProperty::SignalProperty)) {
+ int signalIndex = QQmlPropertyPrivate::get(prop)->signalIndex();
+ QQmlBoundSignal *signal =
+ new QQmlBoundSignal(target(), signalIndex, this, qmlEngine(this));
+
+ QString location;
+ QQmlContextData *ctxtdata = 0;
+ QQmlData *ddata = QQmlData::get(this);
+ if (ddata) {
+ ctxtdata = ddata->outerContext;
+ if (ctxtdata && !ctxtdata->url.isEmpty())
+ location = ddata->outerContext->urlString;
+ }
+
+ QQmlBoundSignalExpression *expression = ctxtdata ?
+ new QQmlBoundSignalExpression(target(), signalIndex,
+ ctxtdata, this, script,
+ true, location, line, column) : 0;
+ signal->takeExpression(expression);
+ d->boundsignals += signal;
+ } else {
+ if (!d->ignoreUnknownSignals)
+ qmlInfo(this) << tr("Cannot assign to non-existent property \"%1\"").arg(propName);
+ }
+ }
+}
+
+void QQmlConnections::classBegin()
+{
+ Q_D(QQmlConnections);
+ d->componentcomplete=false;
+}
+
+void QQmlConnections::componentComplete()
+{
+ Q_D(QQmlConnections);
+ d->componentcomplete=true;
+ connectSignals();
+}
+
+QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlconnections_p.h b/src/qml/qml/qqmlconnections_p.h
new file mode 100644
index 0000000000..5791166efe
--- /dev/null
+++ b/src/qml/qml/qqmlconnections_p.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQMLCONNECTIONS_H
+#define QQMLCONNECTIONS_H
+
+#include <qqml.h>
+#include <private/qqmlcustomparser_p.h>
+
+#include <QtCore/qobject.h>
+#include <QtCore/qstring.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QQmlBoundSignal;
+class QQmlContext;
+class QQmlConnectionsPrivate;
+class Q_AUTOTEST_EXPORT QQmlConnections : public QObject, public QQmlParserStatus
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QQmlConnections)
+
+ Q_INTERFACES(QQmlParserStatus)
+ Q_PROPERTY(QObject *target READ target WRITE setTarget NOTIFY targetChanged)
+ Q_PROPERTY(bool ignoreUnknownSignals READ ignoreUnknownSignals WRITE setIgnoreUnknownSignals)
+
+public:
+ QQmlConnections(QObject *parent=0);
+ ~QQmlConnections();
+
+ QObject *target() const;
+ void setTarget(QObject *);
+
+ bool ignoreUnknownSignals() const;
+ void setIgnoreUnknownSignals(bool ignore);
+
+Q_SIGNALS:
+ void targetChanged();
+
+private:
+ void connectSignals();
+ void classBegin();
+ void componentComplete();
+};
+
+class QQmlConnectionsParser : public QQmlCustomParser
+{
+public:
+ virtual QByteArray compile(const QList<QQmlCustomParserProperty> &);
+ virtual void setCustomData(QObject *, const QByteArray &);
+};
+
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QQmlConnections)
+
+QT_END_HEADER
+
+#endif
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp
index 1376ad7106..9db8927fd9 100644
--- a/src/qml/qml/qqmlengine.cpp
+++ b/src/qml/qml/qqmlengine.cpp
@@ -89,6 +89,10 @@
#include <private/qqmllocale_p.h>
+#include "qqmlbind_p.h"
+#include "qqmlconnections_p.h"
+#include "qqmltimer_p.h"
+
#ifdef Q_OS_WIN // for %APPDATA%
#include <qt_windows.h>
#include <qlibrary.h>
@@ -172,6 +176,10 @@ void QQmlEnginePrivate::registerBaseTypes(const char *uri, int versionMajor, int
{
qmlRegisterType<QQmlComponent>(uri,versionMajor,versionMinor,"Component");
qmlRegisterType<QObject>(uri,versionMajor,versionMinor,"QtObject");
+ qmlRegisterType<QQmlBind>(uri, versionMajor, versionMinor,"Binding");
+ qmlRegisterType<QQmlConnections>(uri, versionMajor, versionMinor,"Connections");
+ qmlRegisterType<QQmlTimer>(uri, versionMajor, versionMinor,"Timer");
+ qmlRegisterCustomType<QQmlConnections>(uri, versionMajor, versionMinor,"Connections", new QQmlConnectionsParser);
}
diff --git a/src/qml/qml/qqmltimer.cpp b/src/qml/qml/qqmltimer.cpp
new file mode 100644
index 0000000000..c07a28c506
--- /dev/null
+++ b/src/qml/qml/qqmltimer.cpp
@@ -0,0 +1,328 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qqmltimer_p.h"
+
+#include <QtCore/qcoreapplication.h>
+#include "private/qpauseanimationjob_p.h"
+#include <qdebug.h>
+
+#include <private/qobject_p.h>
+
+QT_BEGIN_NAMESPACE
+
+
+
+class QQmlTimerPrivate : public QObjectPrivate, public QAnimationJobChangeListener
+{
+ Q_DECLARE_PUBLIC(QQmlTimer)
+public:
+ QQmlTimerPrivate()
+ : interval(1000), running(false), repeating(false), triggeredOnStart(false)
+ , classBegun(false), componentComplete(false), firstTick(true) {}
+
+ virtual void animationFinished(QAbstractAnimationJob *);
+ virtual void animationCurrentLoopChanged(QAbstractAnimationJob *) { Q_Q(QQmlTimer); q->ticked(); }
+
+ int interval;
+ QPauseAnimationJob pause;
+ bool running : 1;
+ bool repeating : 1;
+ bool triggeredOnStart : 1;
+ bool classBegun : 1;
+ bool componentComplete : 1;
+ bool firstTick : 1;
+};
+
+/*!
+ \qmltype Timer
+ \instantiates QQmlTimer
+ \inqmlmodule QtQuick 2
+ \ingroup qtquick-interceptors
+ \brief Triggers a handler at a specified interval
+
+ A Timer can be used to trigger an action either once, or repeatedly
+ at a given interval.
+
+ Here is a Timer that shows the current date and time, and updates
+ the text every 500 milliseconds. It uses the JavaScript \c Date
+ object to access the current time.
+
+ \qml
+ import QtQuick 2.0
+
+ Item {
+ Timer {
+ interval: 500; running: true; repeat: true
+ onTriggered: time.text = Date().toString()
+ }
+
+ Text { id: time }
+ }
+ \endqml
+
+ The Timer type is synchronized with the animation timer. Since the animation
+ timer is usually set to 60fps, the resolution of Timer will be
+ at best 16ms.
+
+ If the Timer is running and one of its properties is changed, the
+ elapsed time will be reset. For example, if a Timer with interval of
+ 1000ms has its \e repeat property changed 500ms after starting, the
+ elapsed time will be reset to 0, and the Timer will be triggered
+ 1000ms later.
+
+ \sa {declarative/toys/clocks}{Clocks example}
+*/
+
+QQmlTimer::QQmlTimer(QObject *parent)
+ : QObject(*(new QQmlTimerPrivate), parent)
+{
+ Q_D(QQmlTimer);
+ d->pause.addAnimationChangeListener(d, QAbstractAnimationJob::Completion | QAbstractAnimationJob::CurrentLoop);
+ d->pause.setLoopCount(1);
+ d->pause.setDuration(d->interval);
+}
+
+/*!
+ \qmlproperty int QtQuick2::Timer::interval
+
+ Sets the \a interval between triggers, in milliseconds.
+
+ The default interval is 1000 milliseconds.
+*/
+void QQmlTimer::setInterval(int interval)
+{
+ Q_D(QQmlTimer);
+ if (interval != d->interval) {
+ d->interval = interval;
+ update();
+ emit intervalChanged();
+ }
+}
+
+int QQmlTimer::interval() const
+{
+ Q_D(const QQmlTimer);
+ return d->interval;
+}
+
+/*!
+ \qmlproperty bool QtQuick2::Timer::running
+
+ If set to true, starts the timer; otherwise stops the timer.
+ For a non-repeating timer, \a running is set to false after the
+ timer has been triggered.
+
+ \a running defaults to false.
+
+ \sa repeat
+*/
+bool QQmlTimer::isRunning() const
+{
+ Q_D(const QQmlTimer);
+ return d->running;
+}
+
+void QQmlTimer::setRunning(bool running)
+{
+ Q_D(QQmlTimer);
+ if (d->running != running) {
+ d->running = running;
+ d->firstTick = true;
+ emit runningChanged();
+ update();
+ }
+}
+
+/*!
+ \qmlproperty bool QtQuick2::Timer::repeat
+
+ If \a repeat is true the timer is triggered repeatedly at the
+ specified interval; otherwise, the timer will trigger once at the
+ specified interval and then stop (i.e. running will be set to false).
+
+ \a repeat defaults to false.
+
+ \sa running
+*/
+bool QQmlTimer::isRepeating() const
+{
+ Q_D(const QQmlTimer);
+ return d->repeating;
+}
+
+void QQmlTimer::setRepeating(bool repeating)
+{
+ Q_D(QQmlTimer);
+ if (repeating != d->repeating) {
+ d->repeating = repeating;
+ update();
+ emit repeatChanged();
+ }
+}
+
+/*!
+ \qmlproperty bool QtQuick2::Timer::triggeredOnStart
+
+ When a timer is started, the first trigger is usually after the specified
+ interval has elapsed. It is sometimes desirable to trigger immediately
+ when the timer is started; for example, to establish an initial
+ state.
+
+ If \a triggeredOnStart is true, the timer is triggered immediately
+ when started, and subsequently at the specified interval. Note that if
+ \e repeat is set to false, the timer is triggered twice; once on start,
+ and again at the interval.
+
+ \a triggeredOnStart defaults to false.
+
+ \sa running
+*/
+bool QQmlTimer::triggeredOnStart() const
+{
+ Q_D(const QQmlTimer);
+ return d->triggeredOnStart;
+}
+
+void QQmlTimer::setTriggeredOnStart(bool triggeredOnStart)
+{
+ Q_D(QQmlTimer);
+ if (d->triggeredOnStart != triggeredOnStart) {
+ d->triggeredOnStart = triggeredOnStart;
+ update();
+ emit triggeredOnStartChanged();
+ }
+}
+
+/*!
+ \qmlmethod QtQuick2::Timer::start()
+ \brief Starts the timer
+
+ If the timer is already running, calling this method has no effect. The
+ \c running property will be true following a call to \c start().
+*/
+void QQmlTimer::start()
+{
+ setRunning(true);
+}
+
+/*!
+ \qmlmethod QtQuick2::Timer::stop()
+ \brief Stops the timer
+
+ If the timer is not running, calling this method has no effect. The
+ \c running property will be false following a call to \c stop().
+*/
+void QQmlTimer::stop()
+{
+ setRunning(false);
+}
+
+/*!
+ \qmlmethod QtQuick2::Timer::restart()
+ \brief Restarts the timer
+
+ If the Timer is not running it will be started, otherwise it will be
+ stopped, reset to initial state and started. The \c running property
+ will be true following a call to \c restart().
+*/
+void QQmlTimer::restart()
+{
+ setRunning(false);
+ setRunning(true);
+}
+
+void QQmlTimer::update()
+{
+ Q_D(QQmlTimer);
+ if (d->classBegun && !d->componentComplete)
+ return;
+ d->pause.stop();
+ if (d->running) {
+ d->pause.setCurrentTime(0);
+ d->pause.setLoopCount(d->repeating ? -1 : 1);
+ d->pause.setDuration(d->interval);
+ d->pause.start();
+ if (d->triggeredOnStart && d->firstTick) {
+ QCoreApplication::removePostedEvents(this, QEvent::MetaCall);
+ QMetaObject::invokeMethod(this, "ticked", Qt::QueuedConnection);
+ }
+ }
+}
+
+void QQmlTimer::classBegin()
+{
+ Q_D(QQmlTimer);
+ d->classBegun = true;
+}
+
+void QQmlTimer::componentComplete()
+{
+ Q_D(QQmlTimer);
+ d->componentComplete = true;
+ update();
+}
+
+/*!
+ \qmlsignal QtQuick2::Timer::onTriggered()
+
+ This handler is called when the Timer is triggered.
+*/
+void QQmlTimer::ticked()
+{
+ Q_D(QQmlTimer);
+ if (d->running && (d->pause.currentTime() > 0 || (d->triggeredOnStart && d->firstTick)))
+ emit triggered();
+ d->firstTick = false;
+}
+
+void QQmlTimerPrivate::animationFinished(QAbstractAnimationJob *)
+{
+ Q_Q(QQmlTimer);
+ if (repeating || !running)
+ return;
+ running = false;
+ firstTick = false;
+ emit q->triggered();
+ emit q->runningChanged();
+}
+
+QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmltimer_p.h b/src/qml/qml/qqmltimer_p.h
new file mode 100644
index 0000000000..ec9046d945
--- /dev/null
+++ b/src/qml/qml/qqmltimer_p.h
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQMLTIMER_H
+#define QQMLTIMER_H
+
+#include <qqml.h>
+
+#include <QtCore/qobject.h>
+
+#include <private/qtqmlglobal_p.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QQmlTimerPrivate;
+class Q_AUTOTEST_EXPORT QQmlTimer : public QObject, public QQmlParserStatus
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QQmlTimer)
+ Q_INTERFACES(QQmlParserStatus)
+ Q_PROPERTY(int interval READ interval WRITE setInterval NOTIFY intervalChanged)
+ Q_PROPERTY(bool running READ isRunning WRITE setRunning NOTIFY runningChanged)
+ Q_PROPERTY(bool repeat READ isRepeating WRITE setRepeating NOTIFY repeatChanged)
+ Q_PROPERTY(bool triggeredOnStart READ triggeredOnStart WRITE setTriggeredOnStart NOTIFY triggeredOnStartChanged)
+ Q_PROPERTY(QObject *parent READ parent CONSTANT)
+
+public:
+ QQmlTimer(QObject *parent=0);
+
+ void setInterval(int interval);
+ int interval() const;
+
+ bool isRunning() const;
+ void setRunning(bool running);
+
+ bool isRepeating() const;
+ void setRepeating(bool repeating);
+
+ bool triggeredOnStart() const;
+ void setTriggeredOnStart(bool triggeredOnStart);
+
+protected:
+ void classBegin();
+ void componentComplete();
+
+public Q_SLOTS:
+ void start();
+ void stop();
+ void restart();
+
+Q_SIGNALS:
+ void triggered();
+ void runningChanged();
+ void intervalChanged();
+ void repeatChanged();
+ void triggeredOnStartChanged();
+
+private:
+ void update();
+
+private Q_SLOTS:
+ void ticked();
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QQmlTimer)
+
+QT_END_HEADER
+
+#endif