From e0cb13a510c0099784fee00d5b4b7c608dd42dd2 Mon Sep 17 00:00:00 2001 From: Tasuku Suzuki Date: Sun, 25 Nov 2012 04:36:33 +0900 Subject: [PATCH] Move no-Gui related QML types from QtQuick into QtQml Task-number: QTBUG-26340 Change-Id: I9049128db2598bf3c7a9d677b774eaae53b54eb5 Reviewed-by: Alan Alpert Reviewed-by: Lars Knoll Reviewed-by: Gunnar Sletta --- src/qml/qml/qml.pri | 11 +- src/qml/qml/qqmlbind.cpp | 310 +++++++++++++++ src/qml/qml/qqmlbind_p.h | 96 +++++ src/qml/qml/qqmlconnections.cpp | 321 ++++++++++++++++ src/qml/qml/qqmlconnections_p.h | 100 +++++ src/qml/qml/qqmlengine.cpp | 8 + src/qml/qml/qqmltimer.cpp | 328 ++++++++++++++++ src/qml/qml/qqmltimer_p.h | 111 ++++++ src/quick/util/qquickbind.cpp | 310 --------------- src/quick/util/qquickbind_p.h | 96 ----- src/quick/util/qquickconnections.cpp | 321 ---------------- src/quick/util/qquickconnections_p.h | 100 ----- src/quick/util/qquicktimer.cpp | 328 ---------------- src/quick/util/qquicktimer_p.h | 111 ------ src/quick/util/qquickutilmodule.cpp | 7 - src/quick/util/util.pri | 6 - tests/auto/qml/qml.pro | 7 +- tests/auto/qml/qqmlbinding/data/deletedObject.qml | 24 ++ tests/auto/qml/qqmlbinding/data/restoreBinding.qml | 26 ++ .../qqmlbinding/data/restoreBindingWithLoop.qml | 23 ++ .../data/restoreBindingWithoutCrash.qml | 28 ++ tests/auto/qml/qqmlbinding/data/test-binding.qml | 16 + tests/auto/qml/qqmlbinding/data/test-binding2.qml | 16 + tests/auto/qml/qqmlbinding/qqmlbinding.pro | 14 + tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp | 237 ++++++++++++ .../data/connection-targetchange.qml | 25 ++ .../data/connection-unknownsignals-ignored.qml | 8 + .../data/connection-unknownsignals-notarget.qml | 5 + .../data/connection-unknownsignals-parent.qml | 5 + .../data/connection-unknownsignals.qml | 7 + .../auto/qml/qqmlconnections/data/error-object.qml | 5 + .../qml/qqmlconnections/data/error-property.qml | 3 + .../qml/qqmlconnections/data/error-property2.qml | 3 + .../auto/qml/qqmlconnections/data/error-syntax.qml | 7 + .../qqmlconnections/data/rewriteError-global.qml | 8 + .../qqmlconnections/data/rewriteError-unnamed.qml | 8 + .../qqmlconnections/data/singletontype-target.qml | 22 ++ .../qml/qqmlconnections/data/test-connection.qml | 10 + .../qml/qqmlconnections/data/test-connection2.qml | 3 + .../qml/qqmlconnections/data/test-connection3.qml | 3 + tests/auto/qml/qqmlconnections/data/trimming.qml | 10 + tests/auto/qml/qqmlconnections/qqmlconnections.pro | 14 + .../qml/qqmlconnections/tst_qqmlconnections.cpp | 343 +++++++++++++++++ tests/auto/qml/qqmlengine/data/qtqmlModule.5.qml | 3 + tests/auto/qml/qqmlengine/tst_qqmlengine.cpp | 2 +- tests/auto/qml/qqmltimer/qqmltimer.pro | 9 + tests/auto/qml/qqmltimer/tst_qqmltimer.cpp | 393 ++++++++++++++++++++ .../auto/qml/qquickbinding/data/deletedObject.qml | 24 -- .../auto/qml/qquickbinding/data/restoreBinding.qml | 26 -- .../qquickbinding/data/restoreBindingWithLoop.qml | 23 -- .../data/restoreBindingWithoutCrash.qml | 28 -- tests/auto/qml/qquickbinding/data/test-binding.qml | 16 - .../auto/qml/qquickbinding/data/test-binding2.qml | 16 - tests/auto/qml/qquickbinding/qquickbinding.pro | 14 - tests/auto/qml/qquickbinding/tst_qquickbinding.cpp | 237 ------------ .../data/connection-targetchange.qml | 25 -- .../data/connection-unknownsignals-ignored.qml | 8 - .../data/connection-unknownsignals-notarget.qml | 7 - .../data/connection-unknownsignals-parent.qml | 7 - .../data/connection-unknownsignals.qml | 7 - .../qml/qquickconnection/data/error-object.qml | 7 - .../qml/qquickconnection/data/error-property.qml | 5 - .../qml/qquickconnection/data/error-property2.qml | 5 - .../qml/qquickconnection/data/error-syntax.qml | 9 - .../qquickconnection/data/rewriteError-global.qml | 8 - .../qquickconnection/data/rewriteError-unnamed.qml | 8 - .../qquickconnection/data/singletontype-target.qml | 22 -- .../qml/qquickconnection/data/test-connection.qml | 10 - .../qml/qquickconnection/data/test-connection2.qml | 3 - .../qml/qquickconnection/data/test-connection3.qml | 3 - tests/auto/qml/qquickconnection/data/trimming.qml | 10 - .../auto/qml/qquickconnection/qquickconnection.pro | 14 - .../qml/qquickconnection/tst_qquickconnection.cpp | 343 ----------------- tests/auto/quick/qquicktimer/qquicktimer.pro | 9 - tests/auto/quick/qquicktimer/tst_qquicktimer.cpp | 393 -------------------- tests/auto/quick/quick.pro | 1 - 76 files changed, 2566 insertions(+), 2573 deletions(-) create mode 100644 src/qml/qml/qqmlbind.cpp create mode 100644 src/qml/qml/qqmlbind_p.h create mode 100644 src/qml/qml/qqmlconnections.cpp create mode 100644 src/qml/qml/qqmlconnections_p.h create mode 100644 src/qml/qml/qqmltimer.cpp create mode 100644 src/qml/qml/qqmltimer_p.h delete mode 100644 src/quick/util/qquickbind.cpp delete mode 100644 src/quick/util/qquickbind_p.h delete mode 100644 src/quick/util/qquickconnections.cpp delete mode 100644 src/quick/util/qquickconnections_p.h delete mode 100644 src/quick/util/qquicktimer.cpp delete mode 100644 src/quick/util/qquicktimer_p.h create mode 100644 tests/auto/qml/qqmlbinding/data/deletedObject.qml create mode 100644 tests/auto/qml/qqmlbinding/data/restoreBinding.qml create mode 100644 tests/auto/qml/qqmlbinding/data/restoreBindingWithLoop.qml create mode 100644 tests/auto/qml/qqmlbinding/data/restoreBindingWithoutCrash.qml create mode 100644 tests/auto/qml/qqmlbinding/data/test-binding.qml create mode 100644 tests/auto/qml/qqmlbinding/data/test-binding2.qml create mode 100644 tests/auto/qml/qqmlbinding/qqmlbinding.pro create mode 100644 tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp create mode 100644 tests/auto/qml/qqmlconnections/data/connection-targetchange.qml create mode 100644 tests/auto/qml/qqmlconnections/data/connection-unknownsignals-ignored.qml create mode 100644 tests/auto/qml/qqmlconnections/data/connection-unknownsignals-notarget.qml create mode 100644 tests/auto/qml/qqmlconnections/data/connection-unknownsignals-parent.qml create mode 100644 tests/auto/qml/qqmlconnections/data/connection-unknownsignals.qml create mode 100644 tests/auto/qml/qqmlconnections/data/error-object.qml create mode 100644 tests/auto/qml/qqmlconnections/data/error-property.qml create mode 100644 tests/auto/qml/qqmlconnections/data/error-property2.qml create mode 100644 tests/auto/qml/qqmlconnections/data/error-syntax.qml create mode 100644 tests/auto/qml/qqmlconnections/data/rewriteError-global.qml create mode 100644 tests/auto/qml/qqmlconnections/data/rewriteError-unnamed.qml create mode 100644 tests/auto/qml/qqmlconnections/data/singletontype-target.qml create mode 100644 tests/auto/qml/qqmlconnections/data/test-connection.qml create mode 100644 tests/auto/qml/qqmlconnections/data/test-connection2.qml create mode 100644 tests/auto/qml/qqmlconnections/data/test-connection3.qml create mode 100644 tests/auto/qml/qqmlconnections/data/trimming.qml create mode 100644 tests/auto/qml/qqmlconnections/qqmlconnections.pro create mode 100644 tests/auto/qml/qqmlconnections/tst_qqmlconnections.cpp create mode 100644 tests/auto/qml/qqmltimer/qqmltimer.pro create mode 100644 tests/auto/qml/qqmltimer/tst_qqmltimer.cpp delete mode 100644 tests/auto/qml/qquickbinding/data/deletedObject.qml delete mode 100644 tests/auto/qml/qquickbinding/data/restoreBinding.qml delete mode 100644 tests/auto/qml/qquickbinding/data/restoreBindingWithLoop.qml delete mode 100644 tests/auto/qml/qquickbinding/data/restoreBindingWithoutCrash.qml delete mode 100644 tests/auto/qml/qquickbinding/data/test-binding.qml delete mode 100644 tests/auto/qml/qquickbinding/data/test-binding2.qml delete mode 100644 tests/auto/qml/qquickbinding/qquickbinding.pro delete mode 100644 tests/auto/qml/qquickbinding/tst_qquickbinding.cpp delete mode 100644 tests/auto/qml/qquickconnection/data/connection-targetchange.qml delete mode 100644 tests/auto/qml/qquickconnection/data/connection-unknownsignals-ignored.qml delete mode 100644 tests/auto/qml/qquickconnection/data/connection-unknownsignals-notarget.qml delete mode 100644 tests/auto/qml/qquickconnection/data/connection-unknownsignals-parent.qml delete mode 100644 tests/auto/qml/qquickconnection/data/connection-unknownsignals.qml delete mode 100644 tests/auto/qml/qquickconnection/data/error-object.qml delete mode 100644 tests/auto/qml/qquickconnection/data/error-property.qml delete mode 100644 tests/auto/qml/qquickconnection/data/error-property2.qml delete mode 100644 tests/auto/qml/qquickconnection/data/error-syntax.qml delete mode 100644 tests/auto/qml/qquickconnection/data/rewriteError-global.qml delete mode 100644 tests/auto/qml/qquickconnection/data/rewriteError-unnamed.qml delete mode 100644 tests/auto/qml/qquickconnection/data/singletontype-target.qml delete mode 100644 tests/auto/qml/qquickconnection/data/test-connection.qml delete mode 100644 tests/auto/qml/qquickconnection/data/test-connection2.qml delete mode 100644 tests/auto/qml/qquickconnection/data/test-connection3.qml delete mode 100644 tests/auto/qml/qquickconnection/data/trimming.qml delete mode 100644 tests/auto/qml/qquickconnection/qquickconnection.pro delete mode 100644 tests/auto/qml/qquickconnection/tst_qquickconnection.cpp delete mode 100644 tests/auto/quick/qquicktimer/qquicktimer.pro delete mode 100644 tests/auto/quick/qquicktimer/tst_qquicktimer.cpp diff --git a/src/qml/qml/qml.pri b/src/qml/qml/qml.pri index e7286c2..20b46f0 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 0000000..2df9693 --- /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 +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include + +QT_BEGIN_NAMESPACE + +class QQmlBindPrivate : public QObjectPrivate +{ +public: + QQmlBindPrivate() : componentComplete(true), obj(0), prevBind(0) {} + ~QQmlBindPrivate() { if (prevBind) prevBind->destroy(); } + + QQmlNullableValue when; + bool componentComplete; + QQmlGuard obj; + QString propName; + QQmlNullableValue 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 0000000..02e2767 --- /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 + +#include + +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 0000000..ab631ed --- /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 +#include +#include +#include +#include +#include + +#include +#include + +#include + +QT_BEGIN_NAMESPACE + +class QQmlConnectionsPrivate : public QObjectPrivate +{ +public: + QQmlConnectionsPrivate() : target(0), targetSet(false), ignoreUnknownSignals(false), componentcomplete(true) {} + + QList 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" 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 &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 values = props.at(ii).assignedValues(); + + for (int i = 0; i < values.count(); ++i) { + const QVariant &value = values.at(i); + + if (value.userType() == qMetaTypeId()) { + error(props.at(ii), QQmlConnections::tr("Connections: nested objects not allowed")); + return QByteArray(); + } else if (value.userType() == qMetaTypeId()) { + error(props.at(ii), QQmlConnections::tr("Connections: syntax error")); + return QByteArray(); + } else { + QQmlScript::Variant v = qvariant_cast(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(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 0000000..5791166 --- /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 +#include + +#include +#include + +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 &); + 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 1376ad7..9db8927 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -89,6 +89,10 @@ #include +#include "qqmlbind_p.h" +#include "qqmlconnections_p.h" +#include "qqmltimer_p.h" + #ifdef Q_OS_WIN // for %APPDATA% #include #include @@ -172,6 +176,10 @@ void QQmlEnginePrivate::registerBaseTypes(const char *uri, int versionMajor, int { qmlRegisterType(uri,versionMajor,versionMinor,"Component"); qmlRegisterType(uri,versionMajor,versionMinor,"QtObject"); + qmlRegisterType(uri, versionMajor, versionMinor,"Binding"); + qmlRegisterType(uri, versionMajor, versionMinor,"Connections"); + qmlRegisterType(uri, versionMajor, versionMinor,"Timer"); + qmlRegisterCustomType(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 0000000..c07a28c --- /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 +#include "private/qpauseanimationjob_p.h" +#include + +#include + +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 0000000..ec9046d --- /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 + +#include + +#include + +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 diff --git a/src/quick/util/qquickbind.cpp b/src/quick/util/qquickbind.cpp deleted file mode 100644 index 7d3bc06..0000000 --- a/src/quick/util/qquickbind.cpp +++ /dev/null @@ -1,310 +0,0 @@ -/**************************************************************************** -** -** 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 "qquickbind_p.h" - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include - -#include - -QT_BEGIN_NAMESPACE - -class QQuickBindPrivate : public QObjectPrivate -{ -public: - QQuickBindPrivate() : componentComplete(true), obj(0), prevBind(0) {} - ~QQuickBindPrivate() { if (prevBind) prevBind->destroy(); } - - QQmlNullableValue when; - bool componentComplete; - QQmlGuard obj; - QString propName; - QQmlNullableValue value; - QQmlProperty prop; - QQmlAbstractBinding *prevBind; -}; - - -/*! - \qmltype Binding - \instantiates QQuickBind - \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 -*/ -QQuickBind::QQuickBind(QObject *parent) - : QObject(*(new QQuickBindPrivate), parent) -{ -} - -QQuickBind::~QQuickBind() -{ -} - -/*! - \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 QQuickBind::when() const -{ - Q_D(const QQuickBind); - return d->when; -} - -void QQuickBind::setWhen(bool v) -{ - Q_D(QQuickBind); - if (!d->when.isNull && d->when == v) - return; - - d->when = v; - eval(); -} - -/*! - \qmlproperty Object QtQuick2::Binding::target - - The object to be updated. -*/ -QObject *QQuickBind::object() -{ - Q_D(const QQuickBind); - return d->obj; -} - -void QQuickBind::setObject(QObject *obj) -{ - Q_D(QQuickBind); - 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 QQuickBind::property() const -{ - Q_D(const QQuickBind); - return d->propName; -} - -void QQuickBind::setProperty(const QString &p) -{ - Q_D(QQuickBind); - 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 QQuickBind::value() const -{ - Q_D(const QQuickBind); - return d->value.value; -} - -void QQuickBind::setValue(const QVariant &v) -{ - Q_D(QQuickBind); - d->value = v; - eval(); -} - -void QQuickBind::setTarget(const QQmlProperty &p) -{ - Q_D(QQuickBind); - d->prop = p; -} - -void QQuickBind::classBegin() -{ - Q_D(QQuickBind); - d->componentComplete = false; -} - -void QQuickBind::componentComplete() -{ - Q_D(QQuickBind); - d->componentComplete = true; - if (!d->prop.isValid()) - d->prop = QQmlProperty(d->obj, d->propName); - eval(); -} - -void QQuickBind::eval() -{ - Q_D(QQuickBind); - 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/quick/util/qquickbind_p.h b/src/quick/util/qquickbind_p.h deleted file mode 100644 index ced8aae..0000000 --- a/src/quick/util/qquickbind_p.h +++ /dev/null @@ -1,96 +0,0 @@ -/**************************************************************************** -** -** 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 QQUICKBIND_H -#define QQUICKBIND_H - -#include - -#include - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -class QQuickBindPrivate; -class Q_AUTOTEST_EXPORT QQuickBind : public QObject, public QQmlPropertyValueSource, public QQmlParserStatus -{ - Q_OBJECT - Q_DECLARE_PRIVATE(QQuickBind) - 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: - QQuickBind(QObject *parent=0); - ~QQuickBind(); - - 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(QQuickBind) - -QT_END_HEADER - -#endif diff --git a/src/quick/util/qquickconnections.cpp b/src/quick/util/qquickconnections.cpp deleted file mode 100644 index ea3628c..0000000 --- a/src/quick/util/qquickconnections.cpp +++ /dev/null @@ -1,321 +0,0 @@ -/**************************************************************************** -** -** 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 "qquickconnections_p.h" - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -QT_BEGIN_NAMESPACE - -class QQuickConnectionsPrivate : public QObjectPrivate -{ -public: - QQuickConnectionsPrivate() : target(0), targetSet(false), ignoreUnknownSignals(false), componentcomplete(true) {} - - QList boundsignals; - QObject *target; - - bool targetSet; - bool ignoreUnknownSignals; - bool componentcomplete; - - QByteArray data; -}; - -/*! - \qmltype Connections - \instantiates QQuickConnections - \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" 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 -*/ -QQuickConnections::QQuickConnections(QObject *parent) : - QObject(*(new QQuickConnectionsPrivate), parent) -{ -} - -QQuickConnections::~QQuickConnections() -{ -} - -/*! - \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 *QQuickConnections::target() const -{ - Q_D(const QQuickConnections); - 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 QQuickConnections::setTarget(QObject *obj) -{ - Q_D(QQuickConnections); - 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 QQuickConnections::ignoreUnknownSignals() const -{ - Q_D(const QQuickConnections); - return d->ignoreUnknownSignals; -} - -void QQuickConnections::setIgnoreUnknownSignals(bool ignore) -{ - Q_D(QQuickConnections); - d->ignoreUnknownSignals = ignore; -} - - - -QByteArray -QQmlConnectionsParser::compile(const QList &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), QQuickConnections::tr("Cannot assign to non-existent property \"%1\"").arg(propName)); - return QByteArray(); - } - - QList values = props.at(ii).assignedValues(); - - for (int i = 0; i < values.count(); ++i) { - const QVariant &value = values.at(i); - - if (value.userType() == qMetaTypeId()) { - error(props.at(ii), QQuickConnections::tr("Connections: nested objects not allowed")); - return QByteArray(); - } else if (value.userType() == qMetaTypeId()) { - error(props.at(ii), QQuickConnections::tr("Connections: syntax error")); - return QByteArray(); - } else { - QQmlScript::Variant v = qvariant_cast(value); - if (v.isScript()) { - ds << propName; - ds << rewriteSignalHandler(v, propName).toUtf8(); - ds << propLine; - ds << propColumn; - } else { - error(props.at(ii), QQuickConnections::tr("Connections: script expected")); - return QByteArray(); - } - } - } - } - - return rv; -} - -void QQmlConnectionsParser::setCustomData(QObject *object, - const QByteArray &data) -{ - QQuickConnectionsPrivate *p = - static_cast(QObjectPrivate::get(object)); - p->data = data; -} - - -void QQuickConnections::connectSignals() -{ - Q_D(QQuickConnections); - 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 QQuickConnections::classBegin() -{ - Q_D(QQuickConnections); - d->componentcomplete=false; -} - -void QQuickConnections::componentComplete() -{ - Q_D(QQuickConnections); - d->componentcomplete=true; - connectSignals(); -} - -QT_END_NAMESPACE diff --git a/src/quick/util/qquickconnections_p.h b/src/quick/util/qquickconnections_p.h deleted file mode 100644 index 0a8e716..0000000 --- a/src/quick/util/qquickconnections_p.h +++ /dev/null @@ -1,100 +0,0 @@ -/**************************************************************************** -** -** 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 QQUICKCONNECTIONS_H -#define QQUICKCONNECTIONS_H - -#include -#include - -#include -#include - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -class QQmlBoundSignal; -class QQmlContext; -class QQuickConnectionsPrivate; -class Q_AUTOTEST_EXPORT QQuickConnections : public QObject, public QQmlParserStatus -{ - Q_OBJECT - Q_DECLARE_PRIVATE(QQuickConnections) - - Q_INTERFACES(QQmlParserStatus) - Q_PROPERTY(QObject *target READ target WRITE setTarget NOTIFY targetChanged) - Q_PROPERTY(bool ignoreUnknownSignals READ ignoreUnknownSignals WRITE setIgnoreUnknownSignals) - -public: - QQuickConnections(QObject *parent=0); - ~QQuickConnections(); - - 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 &); - virtual void setCustomData(QObject *, const QByteArray &); -}; - - -QT_END_NAMESPACE - -QML_DECLARE_TYPE(QQuickConnections) - -QT_END_HEADER - -#endif diff --git a/src/quick/util/qquicktimer.cpp b/src/quick/util/qquicktimer.cpp deleted file mode 100644 index c7cdc70..0000000 --- a/src/quick/util/qquicktimer.cpp +++ /dev/null @@ -1,328 +0,0 @@ -/**************************************************************************** -** -** 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 "qquicktimer_p.h" - -#include -#include "private/qpauseanimationjob_p.h" -#include - -#include - -QT_BEGIN_NAMESPACE - - - -class QQuickTimerPrivate : public QObjectPrivate, public QAnimationJobChangeListener -{ - Q_DECLARE_PUBLIC(QQuickTimer) -public: - QQuickTimerPrivate() - : interval(1000), running(false), repeating(false), triggeredOnStart(false) - , classBegun(false), componentComplete(false), firstTick(true) {} - - virtual void animationFinished(QAbstractAnimationJob *); - virtual void animationCurrentLoopChanged(QAbstractAnimationJob *) { Q_Q(QQuickTimer); 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 QQuickTimer - \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} -*/ - -QQuickTimer::QQuickTimer(QObject *parent) - : QObject(*(new QQuickTimerPrivate), parent) -{ - Q_D(QQuickTimer); - 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 QQuickTimer::setInterval(int interval) -{ - Q_D(QQuickTimer); - if (interval != d->interval) { - d->interval = interval; - update(); - emit intervalChanged(); - } -} - -int QQuickTimer::interval() const -{ - Q_D(const QQuickTimer); - 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 QQuickTimer::isRunning() const -{ - Q_D(const QQuickTimer); - return d->running; -} - -void QQuickTimer::setRunning(bool running) -{ - Q_D(QQuickTimer); - 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 QQuickTimer::isRepeating() const -{ - Q_D(const QQuickTimer); - return d->repeating; -} - -void QQuickTimer::setRepeating(bool repeating) -{ - Q_D(QQuickTimer); - 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 QQuickTimer::triggeredOnStart() const -{ - Q_D(const QQuickTimer); - return d->triggeredOnStart; -} - -void QQuickTimer::setTriggeredOnStart(bool triggeredOnStart) -{ - Q_D(QQuickTimer); - 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 QQuickTimer::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 QQuickTimer::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 QQuickTimer::restart() -{ - setRunning(false); - setRunning(true); -} - -void QQuickTimer::update() -{ - Q_D(QQuickTimer); - 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 QQuickTimer::classBegin() -{ - Q_D(QQuickTimer); - d->classBegun = true; -} - -void QQuickTimer::componentComplete() -{ - Q_D(QQuickTimer); - d->componentComplete = true; - update(); -} - -/*! - \qmlsignal QtQuick2::Timer::onTriggered() - - This handler is called when the Timer is triggered. -*/ -void QQuickTimer::ticked() -{ - Q_D(QQuickTimer); - if (d->running && (d->pause.currentTime() > 0 || (d->triggeredOnStart && d->firstTick))) - emit triggered(); - d->firstTick = false; -} - -void QQuickTimerPrivate::animationFinished(QAbstractAnimationJob *) -{ - Q_Q(QQuickTimer); - if (repeating || !running) - return; - running = false; - firstTick = false; - emit q->triggered(); - emit q->runningChanged(); -} - -QT_END_NAMESPACE diff --git a/src/quick/util/qquicktimer_p.h b/src/quick/util/qquicktimer_p.h deleted file mode 100644 index 91bac9e..0000000 --- a/src/quick/util/qquicktimer_p.h +++ /dev/null @@ -1,111 +0,0 @@ -/**************************************************************************** -** -** 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 QQUICKTIMER_H -#define QQUICKTIMER_H - -#include - -#include - -#include - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -class QQuickTimerPrivate; -class Q_AUTOTEST_EXPORT QQuickTimer : public QObject, public QQmlParserStatus -{ - Q_OBJECT - Q_DECLARE_PRIVATE(QQuickTimer) - 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: - QQuickTimer(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(QQuickTimer) - -QT_END_HEADER - -#endif diff --git a/src/quick/util/qquickutilmodule.cpp b/src/quick/util/qquickutilmodule.cpp index 7ecb792..0491e94 100644 --- a/src/quick/util/qquickutilmodule.cpp +++ b/src/quick/util/qquickutilmodule.cpp @@ -43,8 +43,6 @@ #include "qquickanimation_p.h" #include "qquickanimation_p_p.h" #include "qquickbehavior_p.h" -#include "qquickbind_p.h" -#include "qquickconnections_p.h" #include "qquicksmoothedanimation_p.h" #include "qquickfontloader_p.h" #include "qquickpackage_p.h" @@ -55,7 +53,6 @@ #include "qquickstate_p.h" #include "qquickstate_p_p.h" #include "qquicksystempalette_p.h" -#include "qquicktimer_p.h" #include "qquicktransition_p.h" #include #include @@ -72,9 +69,7 @@ void QQuickUtilModule::defineModule() qmlRegisterUncreatableType("QtQuick",2,0,"Animation",QQuickAbstractAnimation::tr("Animation is an abstract class")); qmlRegisterType("QtQuick",2,0,"Behavior"); - qmlRegisterType("QtQuick",2,0,"Binding"); qmlRegisterType("QtQuick",2,0,"ColorAnimation"); - qmlRegisterType("QtQuick",2,0,"Connections"); qmlRegisterType("QtQuick",2,0,"SmoothedAnimation"); qmlRegisterType("QtQuick",2,0,"FontLoader"); qmlRegisterType("QtQuick",2,0,"NumberAnimation"); @@ -92,12 +87,10 @@ void QQuickUtilModule::defineModule() qmlRegisterType("QtQuick",2,0,"StateGroup"); qmlRegisterType("QtQuick",2,0,"State"); qmlRegisterType("QtQuick",2,0,"SystemPalette"); - qmlRegisterType("QtQuick",2,0,"Timer"); qmlRegisterType("QtQuick",2,0,"Transition"); qmlRegisterType("QtQuick",2,0,"Vector3dAnimation"); qmlRegisterType(); qmlRegisterCustomType("QtQuick",2,0,"PropertyChanges", new QQuickPropertyChangesParser); - qmlRegisterCustomType("QtQuick",2,0,"Connections", new QQmlConnectionsParser); } diff --git a/src/quick/util/util.pri b/src/quick/util/util.pri index 3d93b9f..7a56a95 100644 --- a/src/quick/util/util.pri +++ b/src/quick/util/util.pri @@ -1,7 +1,6 @@ SOURCES += \ $$PWD/qquickapplication.cpp\ $$PWD/qquickutilmodule.cpp\ - $$PWD/qquickconnections.cpp \ $$PWD/qquickpackage.cpp \ $$PWD/qquickanimation.cpp \ $$PWD/qquicksystempalette.cpp \ @@ -16,8 +15,6 @@ SOURCES += \ $$PWD/qquicktransition.cpp \ $$PWD/qquicklistaccessor.cpp \ $$PWD/qquicktimeline.cpp \ - $$PWD/qquicktimer.cpp \ - $$PWD/qquickbind.cpp \ $$PWD/qquickpixmapcache.cpp \ $$PWD/qquickbehavior.cpp \ $$PWD/qquickfontloader.cpp \ @@ -34,7 +31,6 @@ SOURCES += \ HEADERS += \ $$PWD/qquickapplication_p.h\ $$PWD/qquickutilmodule_p.h\ - $$PWD/qquickconnections_p.h \ $$PWD/qquickpackage_p.h \ $$PWD/qquickanimation_p.h \ $$PWD/qquickanimation_p_p.h \ @@ -52,8 +48,6 @@ HEADERS += \ $$PWD/qquicktransition_p.h \ $$PWD/qquicklistaccessor_p.h \ $$PWD/qquicktimeline_p_p.h \ - $$PWD/qquicktimer_p.h \ - $$PWD/qquickbind_p.h \ $$PWD/qquickpixmapcache_p.h \ $$PWD/qquickbehavior_p.h \ $$PWD/qquickfontloader_p.h \ diff --git a/tests/auto/qml/qml.pro b/tests/auto/qml/qml.pro index a9fa764..bbef361 100644 --- a/tests/auto/qml/qml.pro +++ b/tests/auto/qml/qml.pro @@ -41,16 +41,17 @@ PRIVATETESTS += \ qqmlsqldatabase \ qqmlvaluetypes \ qqmlvaluetypeproviders \ - qquickbinding \ + qqmlbinding \ qquickchangeset \ - qquickconnection \ + qqmlconnections \ qquicklistcompositor \ qquicklistmodel \ qquicklistmodelworkerscript \ qquickworkerscript \ qqmlbundle \ qrcqml \ - v4 + v4 \ + qqmltimer !contains(QT_CONFIG, no-widgets) { PUBLICTESTS += \ diff --git a/tests/auto/qml/qqmlbinding/data/deletedObject.qml b/tests/auto/qml/qqmlbinding/data/deletedObject.qml new file mode 100644 index 0000000..f9cf869 --- /dev/null +++ b/tests/auto/qml/qqmlbinding/data/deletedObject.qml @@ -0,0 +1,24 @@ +import QtQuick 2.0 + +Rectangle { + id: wrapper + width: 400 + height: 400 + + property bool activateBinding: false + + Binding { + id: binding + target: Qt.createQmlObject('import QtQuick 2.0; Item { property real value: 10 }', wrapper) + property: "value" + when: activateBinding + value: x + y + } + + Component.onCompleted: binding.target.destroy(); + +// MouseArea { +// anchors.fill: parent +// onClicked: activateBinding = true; +// } +} diff --git a/tests/auto/qml/qqmlbinding/data/restoreBinding.qml b/tests/auto/qml/qqmlbinding/data/restoreBinding.qml new file mode 100644 index 0000000..9491c0f --- /dev/null +++ b/tests/auto/qml/qqmlbinding/data/restoreBinding.qml @@ -0,0 +1,26 @@ +import QtQuick 2.0 + +Rectangle { + width: 400 + height: 400 + + Rectangle { + id: myItem + objectName: "myItem" + width: 100 + height: 100 + color: "green" + x: 100 - myItem.y + + Binding on x { + when: myItem.y > 50 + value: myItem.y + } + + /*NumberAnimation on y { + loops: Animation.Infinite + to: 100 + duration: 1000 + }*/ + } +} diff --git a/tests/auto/qml/qqmlbinding/data/restoreBindingWithLoop.qml b/tests/auto/qml/qqmlbinding/data/restoreBindingWithLoop.qml new file mode 100644 index 0000000..ee07104 --- /dev/null +++ b/tests/auto/qml/qqmlbinding/data/restoreBindingWithLoop.qml @@ -0,0 +1,23 @@ +import QtQuick 2.0 + +Rectangle { + width: 400 + height: 400 + + property bool activateBinding: false + + Rectangle { + id: myItem + objectName: "myItem" + width: 100 + height: 100 + color: "green" + x: myItem.y + 100 + onXChanged: { if (x == 188) y = 90; } //create binding loop + + Binding on x { + when: activateBinding + value: myItem.y + } + } +} diff --git a/tests/auto/qml/qqmlbinding/data/restoreBindingWithoutCrash.qml b/tests/auto/qml/qqmlbinding/data/restoreBindingWithoutCrash.qml new file mode 100644 index 0000000..0c63a16 --- /dev/null +++ b/tests/auto/qml/qqmlbinding/data/restoreBindingWithoutCrash.qml @@ -0,0 +1,28 @@ +import QtQuick 2.0 + +Rectangle { + width: 400 + height: 400 + + states: State { + name: "state1" + PropertyChanges { + target: myItem + x: 200 - myItem.y + } + } + + Rectangle { + id: myItem + objectName: "myItem" + width: 100 + height: 100 + color: "green" + x: 100 - myItem.y + + Binding on x { + when: myItem.y > 50 + value: myItem.y + } + } +} diff --git a/tests/auto/qml/qqmlbinding/data/test-binding.qml b/tests/auto/qml/qqmlbinding/data/test-binding.qml new file mode 100644 index 0000000..87aabe9 --- /dev/null +++ b/tests/auto/qml/qqmlbinding/data/test-binding.qml @@ -0,0 +1,16 @@ +import QtQuick 2.0 + +Rectangle { + id: screen + width: 320; height: 240 + property string text + property bool changeColor: false + + Text { id: s1; text: "Hello" } + Rectangle { id: r1; width: 1; height: 1; color: "yellow" } + Rectangle { id: r2; width: 1; height: 1; color: "red" } + + Binding { target: screen; property: "text"; value: s1.text; objectName: "binding1" } + Binding { target: screen; property: "color"; value: r1.color } + Binding { target: screen; property: "color"; when: screen.changeColor == true; value: r2.color; objectName: "binding3" } +} diff --git a/tests/auto/qml/qqmlbinding/data/test-binding2.qml b/tests/auto/qml/qqmlbinding/data/test-binding2.qml new file mode 100644 index 0000000..4a08141 --- /dev/null +++ b/tests/auto/qml/qqmlbinding/data/test-binding2.qml @@ -0,0 +1,16 @@ +import QtQuick 2.0 + +Rectangle { + id: screen + width: 320; height: 240 + property string text + property bool changeColor: false + + Text { id: s1; text: "Hello" } + Rectangle { id: r1; width: 1; height: 1; color: "yellow" } + Rectangle { id: r2; width: 1; height: 1; color: "red" } + + Binding { target: screen; property: "text"; value: s1.text } + Binding { target: screen; property: "color"; value: r1.color } + Binding { target: screen; property: "color"; value: r2.color; when: screen.changeColor == true } +} diff --git a/tests/auto/qml/qqmlbinding/qqmlbinding.pro b/tests/auto/qml/qqmlbinding/qqmlbinding.pro new file mode 100644 index 0000000..35a5f1c --- /dev/null +++ b/tests/auto/qml/qqmlbinding/qqmlbinding.pro @@ -0,0 +1,14 @@ +CONFIG += testcase +TARGET = tst_qqmlbinding +macx:CONFIG -= app_bundle + +SOURCES += tst_qqmlbinding.cpp + +include (../../shared/util.pri) + +TESTDATA = data/* + +CONFIG += parallel_test + +QT += core-private gui-private qml-private quick-private testlib +DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp b/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp new file mode 100644 index 0000000..4c411fb --- /dev/null +++ b/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp @@ -0,0 +1,237 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the test suite 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 +#include +#include +#include +#include +#include "../../shared/util.h" + +class tst_qqmlbinding : public QQmlDataTest +{ + Q_OBJECT +public: + tst_qqmlbinding(); + +private slots: + void binding(); + void whenAfterValue(); + void restoreBinding(); + void restoreBindingWithLoop(); + void restoreBindingWithoutCrash(); + void deletedObject(); + +private: + QQmlEngine engine; +}; + +tst_qqmlbinding::tst_qqmlbinding() +{ +} + +void tst_qqmlbinding::binding() +{ + QQmlEngine engine; + QQmlComponent c(&engine, testFileUrl("test-binding.qml")); + QQuickRectangle *rect = qobject_cast(c.create()); + QVERIFY(rect != 0); + + QQmlBind *binding3 = qobject_cast(rect->findChild("binding3")); + QVERIFY(binding3 != 0); + + QCOMPARE(rect->color(), QColor("yellow")); + QCOMPARE(rect->property("text").toString(), QString("Hello")); + QCOMPARE(binding3->when(), false); + + rect->setProperty("changeColor", true); + QCOMPARE(rect->color(), QColor("red")); + + QCOMPARE(binding3->when(), true); + + QQmlBind *binding = qobject_cast(rect->findChild("binding1")); + QVERIFY(binding != 0); + QCOMPARE(binding->object(), qobject_cast(rect)); + QCOMPARE(binding->property(), QLatin1String("text")); + QCOMPARE(binding->value().toString(), QLatin1String("Hello")); + + delete rect; +} + +void tst_qqmlbinding::whenAfterValue() +{ + QQmlEngine engine; + QQmlComponent c(&engine, testFileUrl("test-binding2.qml")); + QQuickRectangle *rect = qobject_cast(c.create()); + + QVERIFY(rect != 0); + QCOMPARE(rect->color(), QColor("yellow")); + QCOMPARE(rect->property("text").toString(), QString("Hello")); + + rect->setProperty("changeColor", true); + QCOMPARE(rect->color(), QColor("red")); + + delete rect; +} + +void tst_qqmlbinding::restoreBinding() +{ + QQmlEngine engine; + QQmlComponent c(&engine, testFileUrl("restoreBinding.qml")); + QQuickRectangle *rect = qobject_cast(c.create()); + QVERIFY(rect != 0); + + QQuickRectangle *myItem = qobject_cast(rect->findChild("myItem")); + QVERIFY(myItem != 0); + + myItem->setY(25); + QCOMPARE(myItem->x(), qreal(100-25)); + + myItem->setY(13); + QCOMPARE(myItem->x(), qreal(100-13)); + + //Binding takes effect + myItem->setY(51); + QCOMPARE(myItem->x(), qreal(51)); + + myItem->setY(88); + QCOMPARE(myItem->x(), qreal(88)); + + //original binding restored + myItem->setY(49); + QCOMPARE(myItem->x(), qreal(100-49)); + + delete rect; +} + +void tst_qqmlbinding::restoreBindingWithLoop() +{ + QQmlEngine engine; + QQmlComponent c(&engine, testFileUrl("restoreBindingWithLoop.qml")); + QQuickRectangle *rect = qobject_cast(c.create()); + QVERIFY(rect != 0); + + QQuickRectangle *myItem = qobject_cast(rect->findChild("myItem")); + QVERIFY(myItem != 0); + + myItem->setY(25); + QCOMPARE(myItem->x(), qreal(25 + 100)); + + myItem->setY(13); + QCOMPARE(myItem->x(), qreal(13 + 100)); + + //Binding takes effect + rect->setProperty("activateBinding", true); + myItem->setY(51); + QCOMPARE(myItem->x(), qreal(51)); + + myItem->setY(88); + QCOMPARE(myItem->x(), qreal(88)); + + //original binding restored + QString warning = c.url().toString() + QLatin1String(":9:5: QML Rectangle: Binding loop detected for property \"x\""); + QTest::ignoreMessage(QtWarningMsg, qPrintable(warning)); + rect->setProperty("activateBinding", false); + QCOMPARE(myItem->x(), qreal(88 + 100)); //if loop handling changes this could be 90 + 100 + + myItem->setY(49); + QCOMPARE(myItem->x(), qreal(49 + 100)); + + delete rect; +} + +void tst_qqmlbinding::restoreBindingWithoutCrash() +{ + QQmlEngine engine; + QQmlComponent c(&engine, testFileUrl("restoreBindingWithoutCrash.qml")); + QQuickRectangle *rect = qobject_cast(c.create()); + QVERIFY(rect != 0); + + QQuickRectangle *myItem = qobject_cast(rect->findChild("myItem")); + QVERIFY(myItem != 0); + + myItem->setY(25); + QCOMPARE(myItem->x(), qreal(100-25)); + + myItem->setY(13); + QCOMPARE(myItem->x(), qreal(100-13)); + + //Binding takes effect + myItem->setY(51); + QCOMPARE(myItem->x(), qreal(51)); + + myItem->setY(88); + QCOMPARE(myItem->x(), qreal(88)); + + //state sets a new binding + rect->setState("state1"); + //this binding temporarily takes effect. We may want to change this behavior in the future + QCOMPARE(myItem->x(), qreal(112)); + + //Binding still controls this value + myItem->setY(104); + QCOMPARE(myItem->x(), qreal(104)); + + //original binding restored + myItem->setY(49); + QCOMPARE(myItem->x(), qreal(100-49)); + + delete rect; +} + +//QTBUG-20692 +void tst_qqmlbinding::deletedObject() +{ + QQmlEngine engine; + QQmlComponent c(&engine, testFileUrl("deletedObject.qml")); + QQuickRectangle *rect = qobject_cast(c.create()); + QVERIFY(rect != 0); + + QGuiApplication::sendPostedEvents(0, QEvent::DeferredDelete); + + //don't crash + rect->setProperty("activateBinding", true); + + delete rect; +} + +QTEST_MAIN(tst_qqmlbinding) + +#include "tst_qqmlbinding.moc" diff --git a/tests/auto/qml/qqmlconnections/data/connection-targetchange.qml b/tests/auto/qml/qqmlconnections/data/connection-targetchange.qml new file mode 100644 index 0000000..154c309 --- /dev/null +++ b/tests/auto/qml/qqmlconnections/data/connection-targetchange.qml @@ -0,0 +1,25 @@ +import QtQuick 2.0 + +Item { + Component { + id: item1 + Item { + objectName: "item1" + } + } + Component { + id: item2 + Item { + objectName: "item2" + } + } + Loader { + id: loader + sourceComponent: item1 + } + Connections { + objectName: "connections" + target: loader.item + onWidthChanged: loader.sourceComponent = item2 + } +} diff --git a/tests/auto/qml/qqmlconnections/data/connection-unknownsignals-ignored.qml b/tests/auto/qml/qqmlconnections/data/connection-unknownsignals-ignored.qml new file mode 100644 index 0000000..0780dd1 --- /dev/null +++ b/tests/auto/qml/qqmlconnections/data/connection-unknownsignals-ignored.qml @@ -0,0 +1,8 @@ +import QtQml 2.0 + +QtObject { + id: root + + property Connections c1: Connections { target: root; onNotFooBar1: {} ignoreUnknownSignals: true } + property Connections c2: Connections { objectName: "connections"; onNotFooBar2: {} ignoreUnknownSignals: true } +} diff --git a/tests/auto/qml/qqmlconnections/data/connection-unknownsignals-notarget.qml b/tests/auto/qml/qqmlconnections/data/connection-unknownsignals-notarget.qml new file mode 100644 index 0000000..3da3e0f --- /dev/null +++ b/tests/auto/qml/qqmlconnections/data/connection-unknownsignals-notarget.qml @@ -0,0 +1,5 @@ +import QtQml 2.0 + +QtObject { + property Connections c1: Connections { objectName: "connections"; target: null; onNotFooBar: {} } +} diff --git a/tests/auto/qml/qqmlconnections/data/connection-unknownsignals-parent.qml b/tests/auto/qml/qqmlconnections/data/connection-unknownsignals-parent.qml new file mode 100644 index 0000000..2c55215 --- /dev/null +++ b/tests/auto/qml/qqmlconnections/data/connection-unknownsignals-parent.qml @@ -0,0 +1,5 @@ +import QtQml 2.0 + +QtObject { + property Connections c1: Connections { objectName: "connections"; onFooBar: {} } +} diff --git a/tests/auto/qml/qqmlconnections/data/connection-unknownsignals.qml b/tests/auto/qml/qqmlconnections/data/connection-unknownsignals.qml new file mode 100644 index 0000000..a351016 --- /dev/null +++ b/tests/auto/qml/qqmlconnections/data/connection-unknownsignals.qml @@ -0,0 +1,7 @@ +import QtQml 2.0 + +QtObject { + id: screen + + property Connections c1: Connections { objectName: "connections"; target: screen; onFooBar: {} } +} diff --git a/tests/auto/qml/qqmlconnections/data/error-object.qml b/tests/auto/qml/qqmlconnections/data/error-object.qml new file mode 100644 index 0000000..8594811 --- /dev/null +++ b/tests/auto/qml/qqmlconnections/data/error-object.qml @@ -0,0 +1,5 @@ +import QtQml 2.0 + +Connections { + onClicked: Timer {} +} diff --git a/tests/auto/qml/qqmlconnections/data/error-property.qml b/tests/auto/qml/qqmlconnections/data/error-property.qml new file mode 100644 index 0000000..b08a4a5 --- /dev/null +++ b/tests/auto/qml/qqmlconnections/data/error-property.qml @@ -0,0 +1,3 @@ +import QtQml 2.0 + +Connections { fakeProperty: {} } diff --git a/tests/auto/qml/qqmlconnections/data/error-property2.qml b/tests/auto/qml/qqmlconnections/data/error-property2.qml new file mode 100644 index 0000000..fcfbf5b --- /dev/null +++ b/tests/auto/qml/qqmlconnections/data/error-property2.qml @@ -0,0 +1,3 @@ +import QtQml 2.0 + +Connections { onfakeProperty: {} } diff --git a/tests/auto/qml/qqmlconnections/data/error-syntax.qml b/tests/auto/qml/qqmlconnections/data/error-syntax.qml new file mode 100644 index 0000000..62c841b --- /dev/null +++ b/tests/auto/qml/qqmlconnections/data/error-syntax.qml @@ -0,0 +1,7 @@ +import QtQml 2.0 + +Connections { + onClicked { + onPressed: {} + } +} diff --git a/tests/auto/qml/qqmlconnections/data/rewriteError-global.qml b/tests/auto/qml/qqmlconnections/data/rewriteError-global.qml new file mode 100644 index 0000000..1d0b557 --- /dev/null +++ b/tests/auto/qml/qqmlconnections/data/rewriteError-global.qml @@ -0,0 +1,8 @@ +import QtQml 2.0 +import Test 1.0 + +TestObject { + property QtObject connection: Connections { + onSignalWithGlobalName: { ran = true } + } +} diff --git a/tests/auto/qml/qqmlconnections/data/rewriteError-unnamed.qml b/tests/auto/qml/qqmlconnections/data/rewriteError-unnamed.qml new file mode 100644 index 0000000..a4849e9 --- /dev/null +++ b/tests/auto/qml/qqmlconnections/data/rewriteError-unnamed.qml @@ -0,0 +1,8 @@ +import QtQuick 2.0 +import Test 1.0 + +TestObject { + property QtObject connection: Connections { + onUnnamedArgumentSignal: { ran = true } + } +} diff --git a/tests/auto/qml/qqmlconnections/data/singletontype-target.qml b/tests/auto/qml/qqmlconnections/data/singletontype-target.qml new file mode 100644 index 0000000..7de488c --- /dev/null +++ b/tests/auto/qml/qqmlconnections/data/singletontype-target.qml @@ -0,0 +1,22 @@ +import QtQml 2.0 +import MyTestSingletonType 1.0 as MyTestSingletonType + +QtObject { + id: rootObject + objectName: "rootObject" + property int newIntPropValue: 12 + + property int moduleIntPropChangedCount: 0 + property int moduleOtherSignalCount: 0 + + function setModuleIntProp() { + MyTestSingletonType.Api.intProp = newIntPropValue; + newIntPropValue = newIntPropValue + 1; + } + + property Connections c: Connections { + target: MyTestSingletonType.Api + onIntPropChanged: moduleIntPropChangedCount = moduleIntPropChangedCount + 1; + onOtherSignal: moduleOtherSignalCount = moduleOtherSignalCount + 1; + } +} diff --git a/tests/auto/qml/qqmlconnections/data/test-connection.qml b/tests/auto/qml/qqmlconnections/data/test-connection.qml new file mode 100644 index 0000000..ce851fc --- /dev/null +++ b/tests/auto/qml/qqmlconnections/data/test-connection.qml @@ -0,0 +1,10 @@ +import QtQuick 2.0 + +Item { + id: screen; width: 50 + + property bool tested: false + signal testMe + + Connections { target: screen; onWidthChanged: screen.tested = true } +} diff --git a/tests/auto/qml/qqmlconnections/data/test-connection2.qml b/tests/auto/qml/qqmlconnections/data/test-connection2.qml new file mode 100644 index 0000000..a7e264c --- /dev/null +++ b/tests/auto/qml/qqmlconnections/data/test-connection2.qml @@ -0,0 +1,3 @@ +import QtQml 2.0 + +Connections { id: connection; target: connection; onTargetChanged: 1 == 1 } diff --git a/tests/auto/qml/qqmlconnections/data/test-connection3.qml b/tests/auto/qml/qqmlconnections/data/test-connection3.qml new file mode 100644 index 0000000..9aaca22 --- /dev/null +++ b/tests/auto/qml/qqmlconnections/data/test-connection3.qml @@ -0,0 +1,3 @@ +import QtQml 2.0 + +Connections {} diff --git a/tests/auto/qml/qqmlconnections/data/trimming.qml b/tests/auto/qml/qqmlconnections/data/trimming.qml new file mode 100644 index 0000000..4c37eb2 --- /dev/null +++ b/tests/auto/qml/qqmlconnections/data/trimming.qml @@ -0,0 +1,10 @@ +import QtQml 2.0 + +QtObject { + id: root + + property string tested + signal testMe(int param1, string param2) + + property Connections c: Connections { target: root; onTestMe: root.tested = param2 + param1 } +} diff --git a/tests/auto/qml/qqmlconnections/qqmlconnections.pro b/tests/auto/qml/qqmlconnections/qqmlconnections.pro new file mode 100644 index 0000000..52f85f6 --- /dev/null +++ b/tests/auto/qml/qqmlconnections/qqmlconnections.pro @@ -0,0 +1,14 @@ +CONFIG += testcase +TARGET = tst_qqmlconnections +macx:CONFIG -= app_bundle + +SOURCES += tst_qqmlconnections.cpp + +include (../../shared/util.pri) + +TESTDATA = data/* + +CONFIG += parallel_test + +QT += core-private gui-private v8-private qml-private quick-private testlib +DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/qml/qqmlconnections/tst_qqmlconnections.cpp b/tests/auto/qml/qqmlconnections/tst_qqmlconnections.cpp new file mode 100644 index 0000000..b9e31d2 --- /dev/null +++ b/tests/auto/qml/qqmlconnections/tst_qqmlconnections.cpp @@ -0,0 +1,343 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the test suite 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 +#include +#include +#include +#include +#include "../../shared/util.h" +#include + +class tst_qqmlconnections : public QQmlDataTest +{ + Q_OBJECT +public: + tst_qqmlconnections(); + +private slots: + void defaultValues(); + void properties(); + void connection(); + void trimming(); + void targetChanged(); + void unknownSignals_data(); + void unknownSignals(); + void errors_data(); + void errors(); + void rewriteErrors(); + void singletonTypeTarget(); + +private: + QQmlEngine engine; +}; + +tst_qqmlconnections::tst_qqmlconnections() +{ +} + +void tst_qqmlconnections::defaultValues() +{ + QQmlEngine engine; + QQmlComponent c(&engine, testFileUrl("test-connection3.qml")); + QQmlConnections *item = qobject_cast(c.create()); + + QVERIFY(item != 0); + QVERIFY(item->target() == 0); + + delete item; +} + +void tst_qqmlconnections::properties() +{ + QQmlEngine engine; + QQmlComponent c(&engine, testFileUrl("test-connection2.qml")); + QQmlConnections *item = qobject_cast(c.create()); + + QVERIFY(item != 0); + + QVERIFY(item != 0); + QVERIFY(item->target() == item); + + delete item; +} + +void tst_qqmlconnections::connection() +{ + QQmlEngine engine; + QQmlComponent c(&engine, testFileUrl("test-connection.qml")); + QQuickItem *item = qobject_cast(c.create()); + + QVERIFY(item != 0); + + QCOMPARE(item->property("tested").toBool(), false); + QCOMPARE(item->width(), 50.); + emit item->setWidth(100.); + QCOMPARE(item->width(), 100.); + QCOMPARE(item->property("tested").toBool(), true); + + delete item; +} + +void tst_qqmlconnections::trimming() +{ + QQmlEngine engine; + QQmlComponent c(&engine, testFileUrl("trimming.qml")); + QObject *object = c.create(); + + QVERIFY(object != 0); + + QCOMPARE(object->property("tested").toString(), QString("")); + int index = object->metaObject()->indexOfSignal("testMe(int,QString)"); + QMetaMethod method = object->metaObject()->method(index); + method.invoke(object, + Qt::DirectConnection, + Q_ARG(int, 5), + Q_ARG(QString, "worked")); + QCOMPARE(object->property("tested").toString(), QString("worked5")); + + delete object; +} + +// Confirm that target can be changed by one of our signal handlers +void tst_qqmlconnections::targetChanged() +{ + QQmlEngine engine; + QQmlComponent c(&engine, testFileUrl("connection-targetchange.qml")); + QQuickItem *item = qobject_cast(c.create()); + QVERIFY(item != 0); + + QQmlConnections *connections = item->findChild("connections"); + QVERIFY(connections); + + QQuickItem *item1 = item->findChild("item1"); + QVERIFY(item1); + + item1->setWidth(200); + + QQuickItem *item2 = item->findChild("item2"); + QVERIFY(item2); + QVERIFY(connections->target() == item2); + + // If we don't crash then we're OK + + delete item; +} + +void tst_qqmlconnections::unknownSignals_data() +{ + QTest::addColumn("file"); + QTest::addColumn("error"); + + QTest::newRow("basic") << "connection-unknownsignals.qml" << ":6:30: QML Connections: Cannot assign to non-existent property \"onFooBar\""; + QTest::newRow("parent") << "connection-unknownsignals-parent.qml" << ":4:30: 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_qqmlconnections::unknownSignals() +{ + QFETCH(QString, file); + QFETCH(QString, error); + + QUrl url = testFileUrl(file); + if (!error.isEmpty()) { + QTest::ignoreMessage(QtWarningMsg, (url.toString() + error).toLatin1()); + } else { + // QTest has no way to insist no message (i.e. fail) + } + + QQmlEngine engine; + QQmlComponent c(&engine, url); + QObject *object = c.create(); + QVERIFY(object != 0); + + // check that connection is created (they are all runtime errors) + QQmlConnections *connections = object->findChild("connections"); + QVERIFY(connections); + + if (file == "connection-unknownsignals-ignored.qml") + QVERIFY(connections->ignoreUnknownSignals()); + + delete object; +} + +void tst_qqmlconnections::errors_data() +{ + QTest::addColumn("file"); + QTest::addColumn("error"); + + QTest::newRow("no \"on\"") << "error-property.qml" << "Cannot assign to non-existent property \"fakeProperty\""; + QTest::newRow("3rd letter lowercase") << "error-property2.qml" << "Cannot assign to non-existent property \"onfakeProperty\""; + QTest::newRow("child object") << "error-object.qml" << "Connections: nested objects not allowed"; + QTest::newRow("grouped object") << "error-syntax.qml" << "Connections: syntax error"; +} + +void tst_qqmlconnections::errors() +{ + QFETCH(QString, file); + QFETCH(QString, error); + + QUrl url = testFileUrl(file); + + QQmlEngine engine; + QQmlComponent c(&engine, url); + QVERIFY(c.isError() == true); + QList errors = c.errors(); + QVERIFY(errors.count() == 1); + QCOMPARE(errors.at(0).description(), error); +} + +class TestObject : public QObject +{ + Q_OBJECT + Q_PROPERTY(bool ran READ ran WRITE setRan) + +public: + TestObject(QObject *parent = 0) : m_ran(false) {} + ~TestObject() {} + + bool ran() const { return m_ran; } + void setRan(bool arg) { m_ran = arg; } + +signals: + void unnamedArgumentSignal(int a, qreal, QString c); + void signalWithGlobalName(int parseInt); + +private: + bool m_ran; +}; + +void tst_qqmlconnections::rewriteErrors() +{ + qmlRegisterType("Test", 1, 0, "TestObject"); + { + QQmlEngine engine; + QQmlComponent c(&engine, testFileUrl("rewriteError-unnamed.qml")); + TestObject *obj = qobject_cast(c.create()); + QVERIFY(obj != 0); + + QTest::ignoreMessage(QtWarningMsg, (c.url().toString() + ":5:35: QML Connections: Signal uses unnamed parameter followed by named parameter.").toLatin1()); + obj->unnamedArgumentSignal(1, .5, "hello"); + QCOMPARE(obj->ran(), false); + + delete obj; + } + + { + QQmlEngine engine; + QQmlComponent c(&engine, testFileUrl("rewriteError-global.qml")); + TestObject *obj = qobject_cast(c.create()); + QVERIFY(obj != 0); + + QTest::ignoreMessage(QtWarningMsg, (c.url().toString() + ":5:35: QML Connections: Signal parameter \"parseInt\" hides global variable.").toLatin1()); + obj->signalWithGlobalName(10); + QCOMPARE(obj->ran(), false); + + delete obj; + } +} + + +class MyTestSingletonType : public QObject +{ +Q_OBJECT +Q_PROPERTY(int intProp READ intProp WRITE setIntProp NOTIFY intPropChanged) + +public: + MyTestSingletonType(QObject *parent = 0) : QObject(parent), m_intProp(0), m_changeCount(0) {} + ~MyTestSingletonType() {} + + Q_INVOKABLE int otherMethod(int val) { return val + 4; } + + int intProp() const { return m_intProp; } + void setIntProp(int val) + { + if (++m_changeCount % 3 == 0) emit otherSignal(); + m_intProp = val; emit intPropChanged(); + } + +signals: + void intPropChanged(); + void otherSignal(); + +private: + int m_intProp; + int m_changeCount; +}; + +static QObject *module_api_factory(QQmlEngine *engine, QJSEngine *scriptEngine) +{ + Q_UNUSED(engine) + Q_UNUSED(scriptEngine) + MyTestSingletonType *api = new MyTestSingletonType(); + return api; +} + +// QTBUG-20937 +void tst_qqmlconnections::singletonTypeTarget() +{ + qmlRegisterSingletonType("MyTestSingletonType", 1, 0, "Api", module_api_factory); + QQmlComponent component(&engine, testFileUrl("singletontype-target.qml")); + QObject *object = component.create(); + QVERIFY(object != 0); + + QCOMPARE(object->property("moduleIntPropChangedCount").toInt(), 0); + QCOMPARE(object->property("moduleOtherSignalCount").toInt(), 0); + + QMetaObject::invokeMethod(object, "setModuleIntProp"); + QCOMPARE(object->property("moduleIntPropChangedCount").toInt(), 1); + QCOMPARE(object->property("moduleOtherSignalCount").toInt(), 0); + + QMetaObject::invokeMethod(object, "setModuleIntProp"); + QCOMPARE(object->property("moduleIntPropChangedCount").toInt(), 2); + QCOMPARE(object->property("moduleOtherSignalCount").toInt(), 0); + + // the singleton Type emits otherSignal every 3 times the int property changes. + QMetaObject::invokeMethod(object, "setModuleIntProp"); + QCOMPARE(object->property("moduleIntPropChangedCount").toInt(), 3); + QCOMPARE(object->property("moduleOtherSignalCount").toInt(), 1); + + delete object; +} + +QTEST_MAIN(tst_qqmlconnections) + +#include "tst_qqmlconnections.moc" diff --git a/tests/auto/qml/qqmlengine/data/qtqmlModule.5.qml b/tests/auto/qml/qqmlengine/data/qtqmlModule.5.qml index 7a4fe5e..26018b5 100644 --- a/tests/auto/qml/qqmlengine/data/qtqmlModule.5.qml +++ b/tests/auto/qml/qqmlengine/data/qtqmlModule.5.qml @@ -2,4 +2,7 @@ import QtQml 2.0 QtObject { property Component c + property Timer timer + property Connections connections: Connections {} + property Binding binding } diff --git a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp index 937a8b1..128294b 100644 --- a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp +++ b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp @@ -593,7 +593,7 @@ void tst_qqmlengine::qtqmlModule_data() << QString(testFileUrl("qtqmlModule.4.qml").toString() + QLatin1String(":1 module \"QtQml\" version 2.5 is not installed\n")) << QStringList(); - QTest::newRow("QtQml 2.0 module provides Component and QtObject") + QTest::newRow("QtQml 2.0 module provides Component, QtObject, Connections, Binding and Timer") << testFileUrl("qtqmlModule.5.qml") << QString() << QStringList(); diff --git a/tests/auto/qml/qqmltimer/qqmltimer.pro b/tests/auto/qml/qqmltimer/qqmltimer.pro new file mode 100644 index 0000000..28f8e69 --- /dev/null +++ b/tests/auto/qml/qqmltimer/qqmltimer.pro @@ -0,0 +1,9 @@ +CONFIG += testcase +TARGET = tst_qqmltimer +macx:CONFIG -= app_bundle + +SOURCES += tst_qqmltimer.cpp + +CONFIG += parallel_test +QT += core-private gui-private qml-private quick-private gui testlib +DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/qml/qqmltimer/tst_qqmltimer.cpp b/tests/auto/qml/qqmltimer/tst_qqmltimer.cpp new file mode 100644 index 0000000..87010c2 --- /dev/null +++ b/tests/auto/qml/qqmltimer/tst_qqmltimer.cpp @@ -0,0 +1,393 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the test suite 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 +#include +#include +#include +#include +#include +#include + +class tst_qqmltimer : public QObject +{ + Q_OBJECT +public: + tst_qqmltimer(); + +private slots: + void notRepeating(); + void notRepeatingStart(); + void repeat(); + void noTriggerIfNotRunning(); + void triggeredOnStart(); + void triggeredOnStartRepeat(); + void changeDuration(); + void restart(); + void restartFromTriggered(); + void runningFromTriggered(); + void parentProperty(); +}; + +class TimerHelper : public QObject +{ + Q_OBJECT +public: + TimerHelper() : QObject(), count(0) + { + } + + int count; + +public slots: + void timeout() { + ++count; + } +}; + +#define TIMEOUT_TIMEOUT 200 + +tst_qqmltimer::tst_qqmltimer() +{ +} + +void tst_qqmltimer::notRepeating() +{ + QQmlEngine engine; + QQmlComponent component(&engine); + component.setData(QByteArray("import QtQuick 2.0\nTimer { interval: 100; running: true }"), QUrl::fromLocalFile("")); + QQmlTimer *timer = qobject_cast(component.create()); + QVERIFY(timer != 0); + QVERIFY(timer->isRunning()); + QVERIFY(!timer->isRepeating()); + QCOMPARE(timer->interval(), 100); + + TimerHelper helper; + connect(timer, SIGNAL(triggered()), &helper, SLOT(timeout())); + + QTest::qWait(TIMEOUT_TIMEOUT); + QCOMPARE(helper.count, 1); + QTest::qWait(TIMEOUT_TIMEOUT); + QCOMPARE(helper.count, 1); + QVERIFY(timer->isRunning() == false); +} + +void tst_qqmltimer::notRepeatingStart() +{ + QQmlEngine engine; + QQmlComponent component(&engine); + component.setData(QByteArray("import QtQml 2.0\nTimer { interval: 100 }"), QUrl::fromLocalFile("")); + QQmlTimer *timer = qobject_cast(component.create()); + QVERIFY(timer != 0); + QVERIFY(!timer->isRunning()); + + TimerHelper helper; + connect(timer, SIGNAL(triggered()), &helper, SLOT(timeout())); + + QTest::qWait(TIMEOUT_TIMEOUT); + QCOMPARE(helper.count, 0); + + timer->start(); + QTest::qWait(TIMEOUT_TIMEOUT); + QCOMPARE(helper.count, 1); + QTest::qWait(TIMEOUT_TIMEOUT); + QCOMPARE(helper.count, 1); + QVERIFY(timer->isRunning() == false); + + delete timer; +} + +void tst_qqmltimer::repeat() +{ + QQmlEngine engine; + QQmlComponent component(&engine); + component.setData(QByteArray("import QtQml 2.0\nTimer { interval: 100; repeat: true; running: true }"), QUrl::fromLocalFile("")); + QQmlTimer *timer = qobject_cast(component.create()); + QVERIFY(timer != 0); + + TimerHelper helper; + connect(timer, SIGNAL(triggered()), &helper, SLOT(timeout())); + QCOMPARE(helper.count, 0); + + QTest::qWait(TIMEOUT_TIMEOUT); + QVERIFY(helper.count > 0); + int oldCount = helper.count; + + QTest::qWait(TIMEOUT_TIMEOUT); + QVERIFY(helper.count > oldCount); + QVERIFY(timer->isRunning()); + + oldCount = helper.count; + timer->stop(); + + QTest::qWait(TIMEOUT_TIMEOUT); + QVERIFY(helper.count == oldCount); + QVERIFY(timer->isRunning() == false); + + QSignalSpy spy(timer, SIGNAL(repeatChanged())); + + timer->setRepeating(false); + QVERIFY(!timer->isRepeating()); + QCOMPARE(spy.count(),1); + + timer->setRepeating(false); + QCOMPARE(spy.count(),1); + + timer->setRepeating(true); + QCOMPARE(spy.count(),2); + + delete timer; +} + +void tst_qqmltimer::triggeredOnStart() +{ + QQmlEngine engine; + QQmlComponent component(&engine); + component.setData(QByteArray("import QtQml 2.0\nTimer { interval: 100; running: true; triggeredOnStart: true }"), QUrl::fromLocalFile("")); + QQmlTimer *timer = qobject_cast(component.create()); + QVERIFY(timer != 0); + QVERIFY(timer->triggeredOnStart()); + + TimerHelper helper; + connect(timer, SIGNAL(triggered()), &helper, SLOT(timeout())); + QTest::qWait(1); + QCOMPARE(helper.count, 1); + + QTest::qWait(TIMEOUT_TIMEOUT); + QCOMPARE(helper.count, 2); + QTest::qWait(TIMEOUT_TIMEOUT); + QCOMPARE(helper.count, 2); + QVERIFY(timer->isRunning() == false); + + QSignalSpy spy(timer, SIGNAL(triggeredOnStartChanged())); + + timer->setTriggeredOnStart(false); + QVERIFY(!timer->triggeredOnStart()); + QCOMPARE(spy.count(),1); + + timer->setTriggeredOnStart(false); + QCOMPARE(spy.count(),1); + + timer->setTriggeredOnStart(true); + QCOMPARE(spy.count(),2); + + delete timer; +} + +void tst_qqmltimer::triggeredOnStartRepeat() +{ + QQmlEngine engine; + QQmlComponent component(&engine); + component.setData(QByteArray("import QtQml 2.0\nTimer { interval: 100; running: true; triggeredOnStart: true; repeat: true }"), QUrl::fromLocalFile("")); + QQmlTimer *timer = qobject_cast(component.create()); + QVERIFY(timer != 0); + + TimerHelper helper; + connect(timer, SIGNAL(triggered()), &helper, SLOT(timeout())); + QTest::qWait(1); + QCOMPARE(helper.count, 1); + + QTest::qWait(TIMEOUT_TIMEOUT); + QVERIFY(helper.count > 1); + int oldCount = helper.count; + QTest::qWait(TIMEOUT_TIMEOUT); + QVERIFY(helper.count > oldCount); + QVERIFY(timer->isRunning()); + + delete timer; +} + +void tst_qqmltimer::noTriggerIfNotRunning() +{ + QQmlEngine engine; + QQmlComponent component(&engine); + component.setData(QByteArray( + "import QtQml 2.0\n" + "QtObject { property bool ok: true\n" + "property Timer timer1: Timer { id: t1; interval: 100; repeat: true; running: true; onTriggered: if (!running) ok=false }" + "property Timer timer2: Timer { interval: 10; running: true; onTriggered: t1.running=false }" + "}" + ), QUrl::fromLocalFile("")); + QObject *item = component.create(); + QVERIFY(item != 0); + QTest::qWait(TIMEOUT_TIMEOUT); + QCOMPARE(item->property("ok").toBool(), true); + + delete item; +} + +void tst_qqmltimer::changeDuration() +{ + QQmlEngine engine; + QQmlComponent component(&engine); + component.setData(QByteArray("import QtQml 2.0\nTimer { interval: 200; repeat: true; running: true }"), QUrl::fromLocalFile("")); + QQmlTimer *timer = qobject_cast(component.create()); + QVERIFY(timer != 0); + + TimerHelper helper; + connect(timer, SIGNAL(triggered()), &helper, SLOT(timeout())); + QCOMPARE(helper.count, 0); + + QTest::qWait(500); + QCOMPARE(helper.count, 2); + + timer->setInterval(500); + + QTest::qWait(600); + QCOMPARE(helper.count, 3); + QVERIFY(timer->isRunning()); + + QSignalSpy spy(timer, SIGNAL(intervalChanged())); + + timer->setInterval(200); + QCOMPARE(timer->interval(), 200); + QCOMPARE(spy.count(),1); + + timer->setInterval(200); + QCOMPARE(spy.count(),1); + + timer->setInterval(300); + QCOMPARE(spy.count(),2); + + delete timer; +} + +void tst_qqmltimer::restart() +{ + QQmlEngine engine; + QQmlComponent component(&engine); + component.setData(QByteArray("import QtQml 2.0\nTimer { interval: 500; repeat: true; running: true }"), QUrl::fromLocalFile("")); + QQmlTimer *timer = qobject_cast(component.create()); + QVERIFY(timer != 0); + + TimerHelper helper; + connect(timer, SIGNAL(triggered()), &helper, SLOT(timeout())); + QCOMPARE(helper.count, 0); + + QTest::qWait(600); + QCOMPARE(helper.count, 1); + + QTest::qWait(300); + + timer->restart(); + + QTest::qWait(700); + + QCOMPARE(helper.count, 2); + QVERIFY(timer->isRunning()); + + delete timer; +} + +void tst_qqmltimer::restartFromTriggered() +{ + QQmlEngine engine; + QQmlComponent component(&engine); + component.setData(QByteArray("import QtQml 2.0\nTimer { " + "interval: 500; " + "repeat: false; " + "running: true; " + "onTriggered: restart()" + " }"), QUrl::fromLocalFile("")); + QScopedPointer object(component.create()); + QQmlTimer *timer = qobject_cast(object.data()); + QVERIFY(timer != 0); + + TimerHelper helper; + connect(timer, SIGNAL(triggered()), &helper, SLOT(timeout())); + QCOMPARE(helper.count, 0); + + QTest::qWait(600); + QCOMPARE(helper.count, 1); + QVERIFY(timer->isRunning()); + + QTest::qWait(600); + QCOMPARE(helper.count, 2); + QVERIFY(timer->isRunning()); +} + +void tst_qqmltimer::runningFromTriggered() +{ + QQmlEngine engine; + QQmlComponent component(&engine); + component.setData(QByteArray("import QtQml 2.0\nTimer { " + "property bool ok: false; " + "interval: 500; " + "repeat: false; " + "running: true; " + "onTriggered: { ok = !running; running = true }" + " }"), QUrl::fromLocalFile("")); + QScopedPointer object(component.create()); + QQmlTimer *timer = qobject_cast(object.data()); + QVERIFY(timer != 0); + + TimerHelper helper; + connect(timer, SIGNAL(triggered()), &helper, SLOT(timeout())); + QCOMPARE(helper.count, 0); + + QTest::qWait(600); + QCOMPARE(helper.count, 1); + QVERIFY(timer->property("ok").toBool()); + QVERIFY(timer->isRunning()); + + QTest::qWait(600); + QCOMPARE(helper.count, 2); + QVERIFY(timer->property("ok").toBool()); + QVERIFY(timer->isRunning()); +} + +void tst_qqmltimer::parentProperty() +{ + QQmlEngine engine; + QQmlComponent component(&engine); + component.setData(QByteArray("import QtQuick 2.0\nItem { Timer { objectName: \"timer\"; running: parent.visible } }"), QUrl::fromLocalFile("")); + QQuickItem *item = qobject_cast(component.create()); + QVERIFY(item != 0); + QQmlTimer *timer = item->findChild("timer"); + QVERIFY(timer != 0); + + QVERIFY(timer->isRunning()); + + delete timer; +} + +QTEST_MAIN(tst_qqmltimer) + +#include "tst_qqmltimer.moc" diff --git a/tests/auto/qml/qquickbinding/data/deletedObject.qml b/tests/auto/qml/qquickbinding/data/deletedObject.qml deleted file mode 100644 index f9cf869..0000000 --- a/tests/auto/qml/qquickbinding/data/deletedObject.qml +++ /dev/null @@ -1,24 +0,0 @@ -import QtQuick 2.0 - -Rectangle { - id: wrapper - width: 400 - height: 400 - - property bool activateBinding: false - - Binding { - id: binding - target: Qt.createQmlObject('import QtQuick 2.0; Item { property real value: 10 }', wrapper) - property: "value" - when: activateBinding - value: x + y - } - - Component.onCompleted: binding.target.destroy(); - -// MouseArea { -// anchors.fill: parent -// onClicked: activateBinding = true; -// } -} diff --git a/tests/auto/qml/qquickbinding/data/restoreBinding.qml b/tests/auto/qml/qquickbinding/data/restoreBinding.qml deleted file mode 100644 index 9491c0f..0000000 --- a/tests/auto/qml/qquickbinding/data/restoreBinding.qml +++ /dev/null @@ -1,26 +0,0 @@ -import QtQuick 2.0 - -Rectangle { - width: 400 - height: 400 - - Rectangle { - id: myItem - objectName: "myItem" - width: 100 - height: 100 - color: "green" - x: 100 - myItem.y - - Binding on x { - when: myItem.y > 50 - value: myItem.y - } - - /*NumberAnimation on y { - loops: Animation.Infinite - to: 100 - duration: 1000 - }*/ - } -} diff --git a/tests/auto/qml/qquickbinding/data/restoreBindingWithLoop.qml b/tests/auto/qml/qquickbinding/data/restoreBindingWithLoop.qml deleted file mode 100644 index ee07104..0000000 --- a/tests/auto/qml/qquickbinding/data/restoreBindingWithLoop.qml +++ /dev/null @@ -1,23 +0,0 @@ -import QtQuick 2.0 - -Rectangle { - width: 400 - height: 400 - - property bool activateBinding: false - - Rectangle { - id: myItem - objectName: "myItem" - width: 100 - height: 100 - color: "green" - x: myItem.y + 100 - onXChanged: { if (x == 188) y = 90; } //create binding loop - - Binding on x { - when: activateBinding - value: myItem.y - } - } -} diff --git a/tests/auto/qml/qquickbinding/data/restoreBindingWithoutCrash.qml b/tests/auto/qml/qquickbinding/data/restoreBindingWithoutCrash.qml deleted file mode 100644 index 0c63a16..0000000 --- a/tests/auto/qml/qquickbinding/data/restoreBindingWithoutCrash.qml +++ /dev/null @@ -1,28 +0,0 @@ -import QtQuick 2.0 - -Rectangle { - width: 400 - height: 400 - - states: State { - name: "state1" - PropertyChanges { - target: myItem - x: 200 - myItem.y - } - } - - Rectangle { - id: myItem - objectName: "myItem" - width: 100 - height: 100 - color: "green" - x: 100 - myItem.y - - Binding on x { - when: myItem.y > 50 - value: myItem.y - } - } -} diff --git a/tests/auto/qml/qquickbinding/data/test-binding.qml b/tests/auto/qml/qquickbinding/data/test-binding.qml deleted file mode 100644 index 87aabe9..0000000 --- a/tests/auto/qml/qquickbinding/data/test-binding.qml +++ /dev/null @@ -1,16 +0,0 @@ -import QtQuick 2.0 - -Rectangle { - id: screen - width: 320; height: 240 - property string text - property bool changeColor: false - - Text { id: s1; text: "Hello" } - Rectangle { id: r1; width: 1; height: 1; color: "yellow" } - Rectangle { id: r2; width: 1; height: 1; color: "red" } - - Binding { target: screen; property: "text"; value: s1.text; objectName: "binding1" } - Binding { target: screen; property: "color"; value: r1.color } - Binding { target: screen; property: "color"; when: screen.changeColor == true; value: r2.color; objectName: "binding3" } -} diff --git a/tests/auto/qml/qquickbinding/data/test-binding2.qml b/tests/auto/qml/qquickbinding/data/test-binding2.qml deleted file mode 100644 index 4a08141..0000000 --- a/tests/auto/qml/qquickbinding/data/test-binding2.qml +++ /dev/null @@ -1,16 +0,0 @@ -import QtQuick 2.0 - -Rectangle { - id: screen - width: 320; height: 240 - property string text - property bool changeColor: false - - Text { id: s1; text: "Hello" } - Rectangle { id: r1; width: 1; height: 1; color: "yellow" } - Rectangle { id: r2; width: 1; height: 1; color: "red" } - - Binding { target: screen; property: "text"; value: s1.text } - Binding { target: screen; property: "color"; value: r1.color } - Binding { target: screen; property: "color"; value: r2.color; when: screen.changeColor == true } -} diff --git a/tests/auto/qml/qquickbinding/qquickbinding.pro b/tests/auto/qml/qquickbinding/qquickbinding.pro deleted file mode 100644 index e209f81..0000000 --- a/tests/auto/qml/qquickbinding/qquickbinding.pro +++ /dev/null @@ -1,14 +0,0 @@ -CONFIG += testcase -TARGET = tst_qquickbinding -macx:CONFIG -= app_bundle - -SOURCES += tst_qquickbinding.cpp - -include (../../shared/util.pri) - -TESTDATA = data/* - -CONFIG += parallel_test - -QT += core-private gui-private qml-private quick-private testlib -DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/qml/qquickbinding/tst_qquickbinding.cpp b/tests/auto/qml/qquickbinding/tst_qquickbinding.cpp deleted file mode 100644 index 9d9b5ff..0000000 --- a/tests/auto/qml/qquickbinding/tst_qquickbinding.cpp +++ /dev/null @@ -1,237 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the test suite 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 -#include -#include -#include -#include -#include "../../shared/util.h" - -class tst_qquickbinding : public QQmlDataTest -{ - Q_OBJECT -public: - tst_qquickbinding(); - -private slots: - void binding(); - void whenAfterValue(); - void restoreBinding(); - void restoreBindingWithLoop(); - void restoreBindingWithoutCrash(); - void deletedObject(); - -private: - QQmlEngine engine; -}; - -tst_qquickbinding::tst_qquickbinding() -{ -} - -void tst_qquickbinding::binding() -{ - QQmlEngine engine; - QQmlComponent c(&engine, testFileUrl("test-binding.qml")); - QQuickRectangle *rect = qobject_cast(c.create()); - QVERIFY(rect != 0); - - QQuickBind *binding3 = qobject_cast(rect->findChild("binding3")); - QVERIFY(binding3 != 0); - - QCOMPARE(rect->color(), QColor("yellow")); - QCOMPARE(rect->property("text").toString(), QString("Hello")); - QCOMPARE(binding3->when(), false); - - rect->setProperty("changeColor", true); - QCOMPARE(rect->color(), QColor("red")); - - QCOMPARE(binding3->when(), true); - - QQuickBind *binding = qobject_cast(rect->findChild("binding1")); - QVERIFY(binding != 0); - QCOMPARE(binding->object(), qobject_cast(rect)); - QCOMPARE(binding->property(), QLatin1String("text")); - QCOMPARE(binding->value().toString(), QLatin1String("Hello")); - - delete rect; -} - -void tst_qquickbinding::whenAfterValue() -{ - QQmlEngine engine; - QQmlComponent c(&engine, testFileUrl("test-binding2.qml")); - QQuickRectangle *rect = qobject_cast(c.create()); - - QVERIFY(rect != 0); - QCOMPARE(rect->color(), QColor("yellow")); - QCOMPARE(rect->property("text").toString(), QString("Hello")); - - rect->setProperty("changeColor", true); - QCOMPARE(rect->color(), QColor("red")); - - delete rect; -} - -void tst_qquickbinding::restoreBinding() -{ - QQmlEngine engine; - QQmlComponent c(&engine, testFileUrl("restoreBinding.qml")); - QQuickRectangle *rect = qobject_cast(c.create()); - QVERIFY(rect != 0); - - QQuickRectangle *myItem = qobject_cast(rect->findChild("myItem")); - QVERIFY(myItem != 0); - - myItem->setY(25); - QCOMPARE(myItem->x(), qreal(100-25)); - - myItem->setY(13); - QCOMPARE(myItem->x(), qreal(100-13)); - - //Binding takes effect - myItem->setY(51); - QCOMPARE(myItem->x(), qreal(51)); - - myItem->setY(88); - QCOMPARE(myItem->x(), qreal(88)); - - //original binding restored - myItem->setY(49); - QCOMPARE(myItem->x(), qreal(100-49)); - - delete rect; -} - -void tst_qquickbinding::restoreBindingWithLoop() -{ - QQmlEngine engine; - QQmlComponent c(&engine, testFileUrl("restoreBindingWithLoop.qml")); - QQuickRectangle *rect = qobject_cast(c.create()); - QVERIFY(rect != 0); - - QQuickRectangle *myItem = qobject_cast(rect->findChild("myItem")); - QVERIFY(myItem != 0); - - myItem->setY(25); - QCOMPARE(myItem->x(), qreal(25 + 100)); - - myItem->setY(13); - QCOMPARE(myItem->x(), qreal(13 + 100)); - - //Binding takes effect - rect->setProperty("activateBinding", true); - myItem->setY(51); - QCOMPARE(myItem->x(), qreal(51)); - - myItem->setY(88); - QCOMPARE(myItem->x(), qreal(88)); - - //original binding restored - QString warning = c.url().toString() + QLatin1String(":9:5: QML Rectangle: Binding loop detected for property \"x\""); - QTest::ignoreMessage(QtWarningMsg, qPrintable(warning)); - rect->setProperty("activateBinding", false); - QCOMPARE(myItem->x(), qreal(88 + 100)); //if loop handling changes this could be 90 + 100 - - myItem->setY(49); - QCOMPARE(myItem->x(), qreal(49 + 100)); - - delete rect; -} - -void tst_qquickbinding::restoreBindingWithoutCrash() -{ - QQmlEngine engine; - QQmlComponent c(&engine, testFileUrl("restoreBindingWithoutCrash.qml")); - QQuickRectangle *rect = qobject_cast(c.create()); - QVERIFY(rect != 0); - - QQuickRectangle *myItem = qobject_cast(rect->findChild("myItem")); - QVERIFY(myItem != 0); - - myItem->setY(25); - QCOMPARE(myItem->x(), qreal(100-25)); - - myItem->setY(13); - QCOMPARE(myItem->x(), qreal(100-13)); - - //Binding takes effect - myItem->setY(51); - QCOMPARE(myItem->x(), qreal(51)); - - myItem->setY(88); - QCOMPARE(myItem->x(), qreal(88)); - - //state sets a new binding - rect->setState("state1"); - //this binding temporarily takes effect. We may want to change this behavior in the future - QCOMPARE(myItem->x(), qreal(112)); - - //Binding still controls this value - myItem->setY(104); - QCOMPARE(myItem->x(), qreal(104)); - - //original binding restored - myItem->setY(49); - QCOMPARE(myItem->x(), qreal(100-49)); - - delete rect; -} - -//QTBUG-20692 -void tst_qquickbinding::deletedObject() -{ - QQmlEngine engine; - QQmlComponent c(&engine, testFileUrl("deletedObject.qml")); - QQuickRectangle *rect = qobject_cast(c.create()); - QVERIFY(rect != 0); - - QGuiApplication::sendPostedEvents(0, QEvent::DeferredDelete); - - //don't crash - rect->setProperty("activateBinding", true); - - delete rect; -} - -QTEST_MAIN(tst_qquickbinding) - -#include "tst_qquickbinding.moc" diff --git a/tests/auto/qml/qquickconnection/data/connection-targetchange.qml b/tests/auto/qml/qquickconnection/data/connection-targetchange.qml deleted file mode 100644 index 154c309..0000000 --- a/tests/auto/qml/qquickconnection/data/connection-targetchange.qml +++ /dev/null @@ -1,25 +0,0 @@ -import QtQuick 2.0 - -Item { - Component { - id: item1 - Item { - objectName: "item1" - } - } - Component { - id: item2 - Item { - objectName: "item2" - } - } - Loader { - id: loader - sourceComponent: item1 - } - Connections { - objectName: "connections" - target: loader.item - onWidthChanged: loader.sourceComponent = item2 - } -} diff --git a/tests/auto/qml/qquickconnection/data/connection-unknownsignals-ignored.qml b/tests/auto/qml/qquickconnection/data/connection-unknownsignals-ignored.qml deleted file mode 100644 index 05d06bd..0000000 --- a/tests/auto/qml/qquickconnection/data/connection-unknownsignals-ignored.qml +++ /dev/null @@ -1,8 +0,0 @@ -import QtQuick 2.0 - -Item { - id: screen - - Connections { target: screen; onNotFooBar1: {} ignoreUnknownSignals: true } - Connections { objectName: "connections"; onNotFooBar2: {} ignoreUnknownSignals: true } -} diff --git a/tests/auto/qml/qquickconnection/data/connection-unknownsignals-notarget.qml b/tests/auto/qml/qquickconnection/data/connection-unknownsignals-notarget.qml deleted file mode 100644 index 9d25cba..0000000 --- a/tests/auto/qml/qquickconnection/data/connection-unknownsignals-notarget.qml +++ /dev/null @@ -1,7 +0,0 @@ -import QtQuick 2.0 - -Item { - id: screen - - Connections { objectName: "connections"; target: null; onNotFooBar: {} } -} diff --git a/tests/auto/qml/qquickconnection/data/connection-unknownsignals-parent.qml b/tests/auto/qml/qquickconnection/data/connection-unknownsignals-parent.qml deleted file mode 100644 index bcd2812..0000000 --- a/tests/auto/qml/qquickconnection/data/connection-unknownsignals-parent.qml +++ /dev/null @@ -1,7 +0,0 @@ -import QtQuick 2.0 - -Item { - id: screen - - Connections { objectName: "connections"; onFooBar: {} } -} diff --git a/tests/auto/qml/qquickconnection/data/connection-unknownsignals.qml b/tests/auto/qml/qquickconnection/data/connection-unknownsignals.qml deleted file mode 100644 index ad8d4d9..0000000 --- a/tests/auto/qml/qquickconnection/data/connection-unknownsignals.qml +++ /dev/null @@ -1,7 +0,0 @@ -import QtQuick 2.0 - -Item { - id: screen - - Connections { objectName: "connections"; target: screen; onFooBar: {} } -} diff --git a/tests/auto/qml/qquickconnection/data/error-object.qml b/tests/auto/qml/qquickconnection/data/error-object.qml deleted file mode 100644 index 256b262..0000000 --- a/tests/auto/qml/qquickconnection/data/error-object.qml +++ /dev/null @@ -1,7 +0,0 @@ -import QtQuick 2.0 - -Item { - Connections { - onClicked: Item {} - } -} diff --git a/tests/auto/qml/qquickconnection/data/error-property.qml b/tests/auto/qml/qquickconnection/data/error-property.qml deleted file mode 100644 index a602479..0000000 --- a/tests/auto/qml/qquickconnection/data/error-property.qml +++ /dev/null @@ -1,5 +0,0 @@ -import QtQuick 2.0 - -Item { - Connections { fakeProperty: {} } -} diff --git a/tests/auto/qml/qquickconnection/data/error-property2.qml b/tests/auto/qml/qquickconnection/data/error-property2.qml deleted file mode 100644 index 8123afe..0000000 --- a/tests/auto/qml/qquickconnection/data/error-property2.qml +++ /dev/null @@ -1,5 +0,0 @@ -import QtQuick 2.0 - -Item { - Connections { onfakeProperty: {} } -} diff --git a/tests/auto/qml/qquickconnection/data/error-syntax.qml b/tests/auto/qml/qquickconnection/data/error-syntax.qml deleted file mode 100644 index 16c0534..0000000 --- a/tests/auto/qml/qquickconnection/data/error-syntax.qml +++ /dev/null @@ -1,9 +0,0 @@ -import QtQuick 2.0 - -Item { - Connections { - onClicked { - onPressed: {} - } - } -} diff --git a/tests/auto/qml/qquickconnection/data/rewriteError-global.qml b/tests/auto/qml/qquickconnection/data/rewriteError-global.qml deleted file mode 100644 index bd18b9d..0000000 --- a/tests/auto/qml/qquickconnection/data/rewriteError-global.qml +++ /dev/null @@ -1,8 +0,0 @@ -import QtQuick 2.0 -import Test 1.0 - -TestObject { - property QtObject connection: Connections { - onSignalWithGlobalName: { ran = true } - } -} diff --git a/tests/auto/qml/qquickconnection/data/rewriteError-unnamed.qml b/tests/auto/qml/qquickconnection/data/rewriteError-unnamed.qml deleted file mode 100644 index a4849e9..0000000 --- a/tests/auto/qml/qquickconnection/data/rewriteError-unnamed.qml +++ /dev/null @@ -1,8 +0,0 @@ -import QtQuick 2.0 -import Test 1.0 - -TestObject { - property QtObject connection: Connections { - onUnnamedArgumentSignal: { ran = true } - } -} diff --git a/tests/auto/qml/qquickconnection/data/singletontype-target.qml b/tests/auto/qml/qquickconnection/data/singletontype-target.qml deleted file mode 100644 index df6f8a0..0000000 --- a/tests/auto/qml/qquickconnection/data/singletontype-target.qml +++ /dev/null @@ -1,22 +0,0 @@ -import QtQuick 2.0 -import MyTestSingletonType 1.0 as MyTestSingletonType - -Item { - id: rootObject - objectName: "rootObject" - property int newIntPropValue: 12 - - property int moduleIntPropChangedCount: 0 - property int moduleOtherSignalCount: 0 - - function setModuleIntProp() { - MyTestSingletonType.Api.intProp = newIntPropValue; - newIntPropValue = newIntPropValue + 1; - } - - Connections { - target: MyTestSingletonType.Api - onIntPropChanged: moduleIntPropChangedCount = moduleIntPropChangedCount + 1; - onOtherSignal: moduleOtherSignalCount = moduleOtherSignalCount + 1; - } -} diff --git a/tests/auto/qml/qquickconnection/data/test-connection.qml b/tests/auto/qml/qquickconnection/data/test-connection.qml deleted file mode 100644 index ce851fc..0000000 --- a/tests/auto/qml/qquickconnection/data/test-connection.qml +++ /dev/null @@ -1,10 +0,0 @@ -import QtQuick 2.0 - -Item { - id: screen; width: 50 - - property bool tested: false - signal testMe - - Connections { target: screen; onWidthChanged: screen.tested = true } -} diff --git a/tests/auto/qml/qquickconnection/data/test-connection2.qml b/tests/auto/qml/qquickconnection/data/test-connection2.qml deleted file mode 100644 index b23d2fc..0000000 --- a/tests/auto/qml/qquickconnection/data/test-connection2.qml +++ /dev/null @@ -1,3 +0,0 @@ -import QtQuick 2.0 - -Connections { id: connection; target: connection; onTargetChanged: 1 == 1 } diff --git a/tests/auto/qml/qquickconnection/data/test-connection3.qml b/tests/auto/qml/qquickconnection/data/test-connection3.qml deleted file mode 100644 index 9e88f0f..0000000 --- a/tests/auto/qml/qquickconnection/data/test-connection3.qml +++ /dev/null @@ -1,3 +0,0 @@ -import QtQuick 2.0 - -Connections {} diff --git a/tests/auto/qml/qquickconnection/data/trimming.qml b/tests/auto/qml/qquickconnection/data/trimming.qml deleted file mode 100644 index 6692050..0000000 --- a/tests/auto/qml/qquickconnection/data/trimming.qml +++ /dev/null @@ -1,10 +0,0 @@ -import QtQuick 2.0 - -Item { - id: screen; width: 50 - - property string tested - signal testMe(int param1, string param2) - - Connections { target: screen; onTestMe: screen.tested = param2 + param1 } -} diff --git a/tests/auto/qml/qquickconnection/qquickconnection.pro b/tests/auto/qml/qquickconnection/qquickconnection.pro deleted file mode 100644 index b00bc07..0000000 --- a/tests/auto/qml/qquickconnection/qquickconnection.pro +++ /dev/null @@ -1,14 +0,0 @@ -CONFIG += testcase -TARGET = tst_qquickconnection -macx:CONFIG -= app_bundle - -SOURCES += tst_qquickconnection.cpp - -include (../../shared/util.pri) - -TESTDATA = data/* - -CONFIG += parallel_test - -QT += core-private gui-private v8-private qml-private quick-private testlib -DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/qml/qquickconnection/tst_qquickconnection.cpp b/tests/auto/qml/qquickconnection/tst_qquickconnection.cpp deleted file mode 100644 index d54e5a9..0000000 --- a/tests/auto/qml/qquickconnection/tst_qquickconnection.cpp +++ /dev/null @@ -1,343 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the test suite 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 -#include -#include -#include -#include -#include "../../shared/util.h" -#include - -class tst_qquickconnection : public QQmlDataTest -{ - Q_OBJECT -public: - tst_qquickconnection(); - -private slots: - void defaultValues(); - void properties(); - void connection(); - void trimming(); - void targetChanged(); - void unknownSignals_data(); - void unknownSignals(); - void errors_data(); - void errors(); - void rewriteErrors(); - void singletonTypeTarget(); - -private: - QQmlEngine engine; -}; - -tst_qquickconnection::tst_qquickconnection() -{ -} - -void tst_qquickconnection::defaultValues() -{ - QQmlEngine engine; - QQmlComponent c(&engine, testFileUrl("test-connection3.qml")); - QQuickConnections *item = qobject_cast(c.create()); - - QVERIFY(item != 0); - QVERIFY(item->target() == 0); - - delete item; -} - -void tst_qquickconnection::properties() -{ - QQmlEngine engine; - QQmlComponent c(&engine, testFileUrl("test-connection2.qml")); - QQuickConnections *item = qobject_cast(c.create()); - - QVERIFY(item != 0); - - QVERIFY(item != 0); - QVERIFY(item->target() == item); - - delete item; -} - -void tst_qquickconnection::connection() -{ - QQmlEngine engine; - QQmlComponent c(&engine, testFileUrl("test-connection.qml")); - QQuickItem *item = qobject_cast(c.create()); - - QVERIFY(item != 0); - - QCOMPARE(item->property("tested").toBool(), false); - QCOMPARE(item->width(), 50.); - emit item->setWidth(100.); - QCOMPARE(item->width(), 100.); - QCOMPARE(item->property("tested").toBool(), true); - - delete item; -} - -void tst_qquickconnection::trimming() -{ - QQmlEngine engine; - QQmlComponent c(&engine, testFileUrl("trimming.qml")); - QQuickItem *item = qobject_cast(c.create()); - - QVERIFY(item != 0); - - QCOMPARE(item->property("tested").toString(), QString("")); - int index = item->metaObject()->indexOfSignal("testMe(int,QString)"); - QMetaMethod method = item->metaObject()->method(index); - method.invoke(item, - Qt::DirectConnection, - Q_ARG(int, 5), - Q_ARG(QString, "worked")); - QCOMPARE(item->property("tested").toString(), QString("worked5")); - - delete item; -} - -// Confirm that target can be changed by one of our signal handlers -void tst_qquickconnection::targetChanged() -{ - QQmlEngine engine; - QQmlComponent c(&engine, testFileUrl("connection-targetchange.qml")); - QQuickItem *item = qobject_cast(c.create()); - QVERIFY(item != 0); - - QQuickConnections *connections = item->findChild("connections"); - QVERIFY(connections); - - QQuickItem *item1 = item->findChild("item1"); - QVERIFY(item1); - - item1->setWidth(200); - - QQuickItem *item2 = item->findChild("item2"); - QVERIFY(item2); - QVERIFY(connections->target() == item2); - - // If we don't crash then we're OK - - delete item; -} - -void tst_qquickconnection::unknownSignals_data() -{ - QTest::addColumn("file"); - QTest::addColumn("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_qquickconnection::unknownSignals() -{ - QFETCH(QString, file); - QFETCH(QString, error); - - QUrl url = testFileUrl(file); - if (!error.isEmpty()) { - QTest::ignoreMessage(QtWarningMsg, (url.toString() + error).toLatin1()); - } else { - // QTest has no way to insist no message (i.e. fail) - } - - QQmlEngine engine; - QQmlComponent c(&engine, url); - QQuickItem *item = qobject_cast(c.create()); - QVERIFY(item != 0); - - // check that connection is created (they are all runtime errors) - QQuickConnections *connections = item->findChild("connections"); - QVERIFY(connections); - - if (file == "connection-unknownsignals-ignored.qml") - QVERIFY(connections->ignoreUnknownSignals()); - - delete item; -} - -void tst_qquickconnection::errors_data() -{ - QTest::addColumn("file"); - QTest::addColumn("error"); - - QTest::newRow("no \"on\"") << "error-property.qml" << "Cannot assign to non-existent property \"fakeProperty\""; - QTest::newRow("3rd letter lowercase") << "error-property2.qml" << "Cannot assign to non-existent property \"onfakeProperty\""; - QTest::newRow("child object") << "error-object.qml" << "Connections: nested objects not allowed"; - QTest::newRow("grouped object") << "error-syntax.qml" << "Connections: syntax error"; -} - -void tst_qquickconnection::errors() -{ - QFETCH(QString, file); - QFETCH(QString, error); - - QUrl url = testFileUrl(file); - - QQmlEngine engine; - QQmlComponent c(&engine, url); - QVERIFY(c.isError() == true); - QList errors = c.errors(); - QVERIFY(errors.count() == 1); - QCOMPARE(errors.at(0).description(), error); -} - -class TestObject : public QObject -{ - Q_OBJECT - Q_PROPERTY(bool ran READ ran WRITE setRan) - -public: - TestObject(QObject *parent = 0) : m_ran(false) {} - ~TestObject() {} - - bool ran() const { return m_ran; } - void setRan(bool arg) { m_ran = arg; } - -signals: - void unnamedArgumentSignal(int a, qreal, QString c); - void signalWithGlobalName(int parseInt); - -private: - bool m_ran; -}; - -void tst_qquickconnection::rewriteErrors() -{ - qmlRegisterType("Test", 1, 0, "TestObject"); - { - QQmlEngine engine; - QQmlComponent c(&engine, testFileUrl("rewriteError-unnamed.qml")); - TestObject *obj = qobject_cast(c.create()); - QVERIFY(obj != 0); - - QTest::ignoreMessage(QtWarningMsg, (c.url().toString() + ":5:35: QML Connections: Signal uses unnamed parameter followed by named parameter.").toLatin1()); - obj->unnamedArgumentSignal(1, .5, "hello"); - QCOMPARE(obj->ran(), false); - - delete obj; - } - - { - QQmlEngine engine; - QQmlComponent c(&engine, testFileUrl("rewriteError-global.qml")); - TestObject *obj = qobject_cast(c.create()); - QVERIFY(obj != 0); - - QTest::ignoreMessage(QtWarningMsg, (c.url().toString() + ":5:35: QML Connections: Signal parameter \"parseInt\" hides global variable.").toLatin1()); - obj->signalWithGlobalName(10); - QCOMPARE(obj->ran(), false); - - delete obj; - } -} - - -class MyTestSingletonType : public QObject -{ -Q_OBJECT -Q_PROPERTY(int intProp READ intProp WRITE setIntProp NOTIFY intPropChanged) - -public: - MyTestSingletonType(QObject *parent = 0) : QObject(parent), m_intProp(0), m_changeCount(0) {} - ~MyTestSingletonType() {} - - Q_INVOKABLE int otherMethod(int val) { return val + 4; } - - int intProp() const { return m_intProp; } - void setIntProp(int val) - { - if (++m_changeCount % 3 == 0) emit otherSignal(); - m_intProp = val; emit intPropChanged(); - } - -signals: - void intPropChanged(); - void otherSignal(); - -private: - int m_intProp; - int m_changeCount; -}; - -static QObject *module_api_factory(QQmlEngine *engine, QJSEngine *scriptEngine) -{ - Q_UNUSED(engine) - Q_UNUSED(scriptEngine) - MyTestSingletonType *api = new MyTestSingletonType(); - return api; -} - -// QTBUG-20937 -void tst_qquickconnection::singletonTypeTarget() -{ - qmlRegisterSingletonType("MyTestSingletonType", 1, 0, "Api", module_api_factory); - QQmlComponent component(&engine, testFileUrl("singletontype-target.qml")); - QObject *object = component.create(); - QVERIFY(object != 0); - - QCOMPARE(object->property("moduleIntPropChangedCount").toInt(), 0); - QCOMPARE(object->property("moduleOtherSignalCount").toInt(), 0); - - QMetaObject::invokeMethod(object, "setModuleIntProp"); - QCOMPARE(object->property("moduleIntPropChangedCount").toInt(), 1); - QCOMPARE(object->property("moduleOtherSignalCount").toInt(), 0); - - QMetaObject::invokeMethod(object, "setModuleIntProp"); - QCOMPARE(object->property("moduleIntPropChangedCount").toInt(), 2); - QCOMPARE(object->property("moduleOtherSignalCount").toInt(), 0); - - // the singleton Type emits otherSignal every 3 times the int property changes. - QMetaObject::invokeMethod(object, "setModuleIntProp"); - QCOMPARE(object->property("moduleIntPropChangedCount").toInt(), 3); - QCOMPARE(object->property("moduleOtherSignalCount").toInt(), 1); - - delete object; -} - -QTEST_MAIN(tst_qquickconnection) - -#include "tst_qquickconnection.moc" diff --git a/tests/auto/quick/qquicktimer/qquicktimer.pro b/tests/auto/quick/qquicktimer/qquicktimer.pro deleted file mode 100644 index 60f862a..0000000 --- a/tests/auto/quick/qquicktimer/qquicktimer.pro +++ /dev/null @@ -1,9 +0,0 @@ -CONFIG += testcase -TARGET = tst_qquicktimer -macx:CONFIG -= app_bundle - -SOURCES += tst_qquicktimer.cpp - -CONFIG += parallel_test -QT += core-private gui-private qml-private quick-private gui testlib -DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/quick/qquicktimer/tst_qquicktimer.cpp b/tests/auto/quick/qquicktimer/tst_qquicktimer.cpp deleted file mode 100644 index 8d5da84..0000000 --- a/tests/auto/quick/qquicktimer/tst_qquicktimer.cpp +++ /dev/null @@ -1,393 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the test suite 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 -#include -#include -#include -#include -#include -#include - -class tst_qquicktimer : public QObject -{ - Q_OBJECT -public: - tst_qquicktimer(); - -private slots: - void notRepeating(); - void notRepeatingStart(); - void repeat(); - void noTriggerIfNotRunning(); - void triggeredOnStart(); - void triggeredOnStartRepeat(); - void changeDuration(); - void restart(); - void restartFromTriggered(); - void runningFromTriggered(); - void parentProperty(); -}; - -class TimerHelper : public QObject -{ - Q_OBJECT -public: - TimerHelper() : QObject(), count(0) - { - } - - int count; - -public slots: - void timeout() { - ++count; - } -}; - -#define TIMEOUT_TIMEOUT 200 - -tst_qquicktimer::tst_qquicktimer() -{ -} - -void tst_qquicktimer::notRepeating() -{ - QQmlEngine engine; - QQmlComponent component(&engine); - component.setData(QByteArray("import QtQuick 2.0\nTimer { interval: 100; running: true }"), QUrl::fromLocalFile("")); - QQuickTimer *timer = qobject_cast(component.create()); - QVERIFY(timer != 0); - QVERIFY(timer->isRunning()); - QVERIFY(!timer->isRepeating()); - QCOMPARE(timer->interval(), 100); - - TimerHelper helper; - connect(timer, SIGNAL(triggered()), &helper, SLOT(timeout())); - - QTest::qWait(TIMEOUT_TIMEOUT); - QCOMPARE(helper.count, 1); - QTest::qWait(TIMEOUT_TIMEOUT); - QCOMPARE(helper.count, 1); - QVERIFY(timer->isRunning() == false); -} - -void tst_qquicktimer::notRepeatingStart() -{ - QQmlEngine engine; - QQmlComponent component(&engine); - component.setData(QByteArray("import QtQuick 2.0\nTimer { interval: 100 }"), QUrl::fromLocalFile("")); - QQuickTimer *timer = qobject_cast(component.create()); - QVERIFY(timer != 0); - QVERIFY(!timer->isRunning()); - - TimerHelper helper; - connect(timer, SIGNAL(triggered()), &helper, SLOT(timeout())); - - QTest::qWait(TIMEOUT_TIMEOUT); - QCOMPARE(helper.count, 0); - - timer->start(); - QTest::qWait(TIMEOUT_TIMEOUT); - QCOMPARE(helper.count, 1); - QTest::qWait(TIMEOUT_TIMEOUT); - QCOMPARE(helper.count, 1); - QVERIFY(timer->isRunning() == false); - - delete timer; -} - -void tst_qquicktimer::repeat() -{ - QQmlEngine engine; - QQmlComponent component(&engine); - component.setData(QByteArray("import QtQuick 2.0\nTimer { interval: 100; repeat: true; running: true }"), QUrl::fromLocalFile("")); - QQuickTimer *timer = qobject_cast(component.create()); - QVERIFY(timer != 0); - - TimerHelper helper; - connect(timer, SIGNAL(triggered()), &helper, SLOT(timeout())); - QCOMPARE(helper.count, 0); - - QTest::qWait(TIMEOUT_TIMEOUT); - QVERIFY(helper.count > 0); - int oldCount = helper.count; - - QTest::qWait(TIMEOUT_TIMEOUT); - QVERIFY(helper.count > oldCount); - QVERIFY(timer->isRunning()); - - oldCount = helper.count; - timer->stop(); - - QTest::qWait(TIMEOUT_TIMEOUT); - QVERIFY(helper.count == oldCount); - QVERIFY(timer->isRunning() == false); - - QSignalSpy spy(timer, SIGNAL(repeatChanged())); - - timer->setRepeating(false); - QVERIFY(!timer->isRepeating()); - QCOMPARE(spy.count(),1); - - timer->setRepeating(false); - QCOMPARE(spy.count(),1); - - timer->setRepeating(true); - QCOMPARE(spy.count(),2); - - delete timer; -} - -void tst_qquicktimer::triggeredOnStart() -{ - QQmlEngine engine; - QQmlComponent component(&engine); - component.setData(QByteArray("import QtQuick 2.0\nTimer { interval: 100; running: true; triggeredOnStart: true }"), QUrl::fromLocalFile("")); - QQuickTimer *timer = qobject_cast(component.create()); - QVERIFY(timer != 0); - QVERIFY(timer->triggeredOnStart()); - - TimerHelper helper; - connect(timer, SIGNAL(triggered()), &helper, SLOT(timeout())); - QTest::qWait(1); - QCOMPARE(helper.count, 1); - - QTest::qWait(TIMEOUT_TIMEOUT); - QCOMPARE(helper.count, 2); - QTest::qWait(TIMEOUT_TIMEOUT); - QCOMPARE(helper.count, 2); - QVERIFY(timer->isRunning() == false); - - QSignalSpy spy(timer, SIGNAL(triggeredOnStartChanged())); - - timer->setTriggeredOnStart(false); - QVERIFY(!timer->triggeredOnStart()); - QCOMPARE(spy.count(),1); - - timer->setTriggeredOnStart(false); - QCOMPARE(spy.count(),1); - - timer->setTriggeredOnStart(true); - QCOMPARE(spy.count(),2); - - delete timer; -} - -void tst_qquicktimer::triggeredOnStartRepeat() -{ - QQmlEngine engine; - QQmlComponent component(&engine); - component.setData(QByteArray("import QtQuick 2.0\nTimer { interval: 100; running: true; triggeredOnStart: true; repeat: true }"), QUrl::fromLocalFile("")); - QQuickTimer *timer = qobject_cast(component.create()); - QVERIFY(timer != 0); - - TimerHelper helper; - connect(timer, SIGNAL(triggered()), &helper, SLOT(timeout())); - QTest::qWait(1); - QCOMPARE(helper.count, 1); - - QTest::qWait(TIMEOUT_TIMEOUT); - QVERIFY(helper.count > 1); - int oldCount = helper.count; - QTest::qWait(TIMEOUT_TIMEOUT); - QVERIFY(helper.count > oldCount); - QVERIFY(timer->isRunning()); - - delete timer; -} - -void tst_qquicktimer::noTriggerIfNotRunning() -{ - QQmlEngine engine; - QQmlComponent component(&engine); - component.setData(QByteArray( - "import QtQuick 2.0\n" - "Item { property bool ok: true\n" - "Timer { id: t1; interval: 100; repeat: true; running: true; onTriggered: if (!running) ok=false }" - "Timer { interval: 10; running: true; onTriggered: t1.running=false }" - "}" - ), QUrl::fromLocalFile("")); - QObject *item = component.create(); - QVERIFY(item != 0); - QTest::qWait(TIMEOUT_TIMEOUT); - QCOMPARE(item->property("ok").toBool(), true); - - delete item; -} - -void tst_qquicktimer::changeDuration() -{ - QQmlEngine engine; - QQmlComponent component(&engine); - component.setData(QByteArray("import QtQuick 2.0\nTimer { interval: 200; repeat: true; running: true }"), QUrl::fromLocalFile("")); - QQuickTimer *timer = qobject_cast(component.create()); - QVERIFY(timer != 0); - - TimerHelper helper; - connect(timer, SIGNAL(triggered()), &helper, SLOT(timeout())); - QCOMPARE(helper.count, 0); - - QTest::qWait(500); - QCOMPARE(helper.count, 2); - - timer->setInterval(500); - - QTest::qWait(600); - QCOMPARE(helper.count, 3); - QVERIFY(timer->isRunning()); - - QSignalSpy spy(timer, SIGNAL(intervalChanged())); - - timer->setInterval(200); - QCOMPARE(timer->interval(), 200); - QCOMPARE(spy.count(),1); - - timer->setInterval(200); - QCOMPARE(spy.count(),1); - - timer->setInterval(300); - QCOMPARE(spy.count(),2); - - delete timer; -} - -void tst_qquicktimer::restart() -{ - QQmlEngine engine; - QQmlComponent component(&engine); - component.setData(QByteArray("import QtQuick 2.0\nTimer { interval: 500; repeat: true; running: true }"), QUrl::fromLocalFile("")); - QQuickTimer *timer = qobject_cast(component.create()); - QVERIFY(timer != 0); - - TimerHelper helper; - connect(timer, SIGNAL(triggered()), &helper, SLOT(timeout())); - QCOMPARE(helper.count, 0); - - QTest::qWait(600); - QCOMPARE(helper.count, 1); - - QTest::qWait(300); - - timer->restart(); - - QTest::qWait(700); - - QCOMPARE(helper.count, 2); - QVERIFY(timer->isRunning()); - - delete timer; -} - -void tst_qquicktimer::restartFromTriggered() -{ - QQmlEngine engine; - QQmlComponent component(&engine); - component.setData(QByteArray("import QtQuick 2.0\nTimer { " - "interval: 500; " - "repeat: false; " - "running: true; " - "onTriggered: restart()" - " }"), QUrl::fromLocalFile("")); - QScopedPointer object(component.create()); - QQuickTimer *timer = qobject_cast(object.data()); - QVERIFY(timer != 0); - - TimerHelper helper; - connect(timer, SIGNAL(triggered()), &helper, SLOT(timeout())); - QCOMPARE(helper.count, 0); - - QTest::qWait(600); - QCOMPARE(helper.count, 1); - QVERIFY(timer->isRunning()); - - QTest::qWait(600); - QCOMPARE(helper.count, 2); - QVERIFY(timer->isRunning()); -} - -void tst_qquicktimer::runningFromTriggered() -{ - QQmlEngine engine; - QQmlComponent component(&engine); - component.setData(QByteArray("import QtQuick 2.0\nTimer { " - "property bool ok: false; " - "interval: 500; " - "repeat: false; " - "running: true; " - "onTriggered: { ok = !running; running = true }" - " }"), QUrl::fromLocalFile("")); - QScopedPointer object(component.create()); - QQuickTimer *timer = qobject_cast(object.data()); - QVERIFY(timer != 0); - - TimerHelper helper; - connect(timer, SIGNAL(triggered()), &helper, SLOT(timeout())); - QCOMPARE(helper.count, 0); - - QTest::qWait(600); - QCOMPARE(helper.count, 1); - QVERIFY(timer->property("ok").toBool()); - QVERIFY(timer->isRunning()); - - QTest::qWait(600); - QCOMPARE(helper.count, 2); - QVERIFY(timer->property("ok").toBool()); - QVERIFY(timer->isRunning()); -} - -void tst_qquicktimer::parentProperty() -{ - QQmlEngine engine; - QQmlComponent component(&engine); - component.setData(QByteArray("import QtQuick 2.0\nItem { Timer { objectName: \"timer\"; running: parent.visible } }"), QUrl::fromLocalFile("")); - QQuickItem *item = qobject_cast(component.create()); - QVERIFY(item != 0); - QQuickTimer *timer = item->findChild("timer"); - QVERIFY(timer != 0); - - QVERIFY(timer->isRunning()); - - delete timer; -} - -QTEST_MAIN(tst_qquicktimer) - -#include "tst_qquicktimer.moc" diff --git a/tests/auto/quick/quick.pro b/tests/auto/quick/quick.pro index abc5e7a..5f18fc9 100644 --- a/tests/auto/quick/quick.pro +++ b/tests/auto/quick/quick.pro @@ -25,7 +25,6 @@ PRIVATETESTS += \ qquickstyledtext \ qquickstates \ qquicksystempalette \ - qquicktimer \ qquickxmllistmodel # This test requires the xmlpatterns module -- 1.7.2.5