diff options
author | Michael Brasser <michael.brasser@nokia.com> | 2009-04-22 04:47:24 (GMT) |
---|---|---|
committer | Michael Brasser <michael.brasser@nokia.com> | 2009-04-22 04:47:24 (GMT) |
commit | 2366667fc97eb6a56203b2dd7dac776ff4164abd (patch) | |
tree | b2acb6cc6bfe475d7e619e4788973b61fff775e0 /src/declarative/util | |
parent | 2c762f3b8b284a7c6dc0c499b7052013bad5b707 (diff) | |
download | Qt-2366667fc97eb6a56203b2dd7dac776ff4164abd.zip Qt-2366667fc97eb6a56203b2dd7dac776ff4164abd.tar.gz Qt-2366667fc97eb6a56203b2dd7dac776ff4164abd.tar.bz2 |
Initial import of kinetic-dui branch from the old kinetic
Diffstat (limited to 'src/declarative/util')
47 files changed, 11043 insertions, 0 deletions
diff --git a/src/declarative/util/qbindablemap.cpp b/src/declarative/util/qbindablemap.cpp new file mode 100644 index 0000000..aea2a2c --- /dev/null +++ b/src/declarative/util/qbindablemap.cpp @@ -0,0 +1,179 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qbindablemap.h" +#include <qmlopenmetaobject.h> +#include <QDebug> + +QT_BEGIN_NAMESPACE + +//QBindableMapMetaObject lets us listen for changes coming from QML +//so we can emit the changed signal. +class QBindableMapMetaObject : public QmlOpenMetaObject +{ +public: + QBindableMapMetaObject(QBindableMap *obj) : QmlOpenMetaObject(obj) + { + map = obj; + } + +protected: + virtual void propertyWrite(int index) + { + map->emitChanged(QLatin1String(name(index))); + } + +private: + QBindableMap *map; +}; + +/*! + \class QBindableMap + \brief The QBindableMap class allows you to set key-value pairs that can be used in bindings. + + QBindableMap provides a convenient way to expose domain data to the UI layer. + The following example shows how you might declare data in C++ and then + access it in QML. + + Setup in C++: + \code + //create our data + QBindableMap ownerData; + ownerData.setValue("name", QVariant(QString("John Smith"))); + ownerData.setValue("phone", QVariant(QString("555-5555"))); + + //expose it to the UI layer + QmlContext *ctxt = view->bindContext(); + ctxt->setProperty("owner", &data); + \endcode + + Then, in QML: + \code + <Text text="{owner.name}"/> + <Text text="{owner.phone}"/> + \endcode + + The binding is dynamic - whenever a key's value is updated, anything bound to that + key will be updated as well. + + To detect value changes made in the UI layer you can connect to the changed() signal. + However, note that changed() is \b NOT emitted when changes are made by calling setValue() + or clearValue() - it is only emitted when a value is updated from QML. +*/ + +// is there a more efficient way to store/return keys? +// (or should we just provide an iterator or something else instead?) +// can we provide a way to clear keys? +// do we want to make any claims regarding key ordering? +// should we have signals for insertion and and deletion -- becoming more model like +// should we emit change for our own changes as well? +// Bug or Feature?: values can be created in QML (owner.somethingElse = "Hello") will create somethingElse property. (need to verify if this is actually the case) +// Bug or Feature?: all values are read-write (there are no read-only values) + +/*! + Constructs a bindable map with parent object \a parent. +*/ +QBindableMap::QBindableMap(QObject *parent) +: QObject(parent) +{ + m_mo = new QBindableMapMetaObject(this); +} + +QBindableMap::~QBindableMap() +{ +} + +/*! + Clears the value (if any) associated with \a key. +*/ +void QBindableMap::clearValue(const QString &key) +{ + //m_keys.remove(); //### + m_mo->setValue(key.toLatin1(), QVariant()); + //emit changed(key); +} + +/*! + Returns the value associated with \a key. + + If no value has been set for this key (or if the value has been cleared), + an invalid QVariant is returned. +*/ +QVariant QBindableMap::value(const QString &key) const +{ + return m_mo->value(key.toLatin1()); +} + +/*! + Sets the value associated with \a key to \a value. + + If the key doesn't exist, it is automatically created. +*/ +void QBindableMap::setValue(const QString &key, QVariant value) +{ + if (!m_keys.contains(key)) + m_keys.append(key); + m_mo->setValue(key.toLatin1(), value); + //emit changed(key); +} + +/*! + Returns the list of keys. + + Keys that have been cleared will still appear in this list, even though their + associated values are invalid QVariants. +*/ +QStringList QBindableMap::keys() const +{ + return m_keys; +} + +/*! + \fn void QBindableMap::changed(const QString &key) + This signal is emitted whenever one of the values in the map is changed. \a key + is the key corresponding to the value that was changed. + */ + +void QBindableMap::emitChanged(const QString &key) +{ + emit changed(key); +} +QT_END_NAMESPACE diff --git a/src/declarative/util/qbindablemap.h b/src/declarative/util/qbindablemap.h new file mode 100644 index 0000000..d617867 --- /dev/null +++ b/src/declarative/util/qbindablemap.h @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QBINDABLEMAP_H +#define QBINDABLEMAP_H + +#include <qfxglobal.h> +#include <QObject> +#include <QHash> +#include <QStringList> +#include <QVariant> + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Declarative) + +class QBindableMapMetaObject; +class Q_DECLARATIVE_EXPORT QBindableMap : public QObject +{ + Q_OBJECT +public: + QBindableMap(QObject *parent = 0); + virtual ~QBindableMap(); + + QVariant value(const QString &key) const; + void setValue(const QString &key, QVariant value); + void clearValue(const QString &key); + + Q_INVOKABLE QStringList keys() const; + +Q_SIGNALS: + void changed(const QString &key); + +private: + Q_DISABLE_COPY(QBindableMap) + void emitChanged(const QString &key); + QBindableMapMetaObject *m_mo; + QStringList m_keys; + friend class QBindableMapMetaObject; +}; + + +QT_END_NAMESPACE + +QT_END_HEADER +#endif diff --git a/src/declarative/util/qfxglobal.h b/src/declarative/util/qfxglobal.h new file mode 100644 index 0000000..52cf021 --- /dev/null +++ b/src/declarative/util/qfxglobal.h @@ -0,0 +1,124 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QFXGLOBAL_H +#define QFXGLOBAL_H + +#include <qglobal.h> +#include <QObject> + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Declarative) +#if defined(QT_OPENGL_ES_1) +#define QFX_CONFIGURATION_OPENGL1 +#elif defined(QT_OPENGL_ES_2) +#define QFX_CONFIGURATION_OPENGL2 +#else +#define QFX_CONFIGURATION_SOFTWARE +#endif + +/* + The choices of renderer are: + QFX_RENDER_QPAINTER + QFX_RENDER_OPENGL1 + QFX_RENDER_OPENGL2 + To simplify code, if either of the OpenGL renderers are used, + QFX_RENDER_OPENGL is also defined. +*/ + +#if defined(QFX_CONFIGURATION_OPENGL2) + +#define QFX_RENDER_OPENGL +#define QFX_RENDER_OPENGL2 + +#elif defined(QFX_CONFIGURATION_OPENGL1) + +#define QFX_RENDER_OPENGL +#define QFX_RENDER_OPENGL1 + +#elif defined(QFX_CONFIGURATION_SOFTWARE) + +#define QFX_RENDER_QPAINTER + +#endif + +#define DEFINE_BOOL_CONFIG_OPTION(name, var) \ + static bool name() \ + { \ + static enum { Yes, No, Unknown } status = Unknown; \ + if(status == Unknown) { \ + QByteArray v = qgetenv(#var); \ + bool value = !v.isEmpty() && v != "0" && v != "false"; \ + if(value) status = Yes; \ + else status = No; \ + } \ + return status == Yes; \ + } + +struct QFx_DerivedObject : public QObject +{ + void setParent_noEvent(QObject *parent) { + bool sce = d_ptr->sendChildEvents; + d_ptr->sendChildEvents = false; + setParent(parent); + d_ptr->sendChildEvents = sce; + } +}; + +/*! + Makes the \a object a child of \a parent. Note that when using this method, + neither \a parent nor the object's previous parent (if it had one) will + receive ChildRemoved or ChildAdded events. +*/ +inline void QFx_setParent_noEvent(QObject *object, QObject *parent) +{ + static_cast<QFx_DerivedObject *>(object)->setParent_noEvent(parent); +} + + +QT_END_NAMESPACE + +QT_END_HEADER +#endif // QFXGLOBAL_H diff --git a/src/declarative/util/qfxperf.cpp b/src/declarative/util/qfxperf.cpp new file mode 100644 index 0000000..5ce8646 --- /dev/null +++ b/src/declarative/util/qfxperf.cpp @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qfxperf.h" + + +QT_BEGIN_NAMESPACE +Q_DEFINE_PERFORMANCE_LOG(QFxPerf, "QFx") { + Q_DEFINE_PERFORMANCE_METRIC(XmlParsing, "XML Parsing"); + Q_DEFINE_PERFORMANCE_METRIC(Compile, "XML Compilation"); + Q_DEFINE_PERFORMANCE_METRIC(CompileRun, "XML Compilation Run"); + Q_DEFINE_PERFORMANCE_METRIC(CssParsing, "CSS Parsing"); + Q_DEFINE_PERFORMANCE_METRIC(CreateComponent, "Component creation"); + Q_DEFINE_PERFORMANCE_METRIC(BindInit, "BindValue Initialization"); + Q_DEFINE_PERFORMANCE_METRIC(BindCompile, "BindValue compile"); + Q_DEFINE_PERFORMANCE_METRIC(BindValue, "BindValue execution"); + Q_DEFINE_PERFORMANCE_METRIC(BindValueSSE, "BindValue execution SSE"); + Q_DEFINE_PERFORMANCE_METRIC(BindValueQt, "BindValue execution QtScript"); + Q_DEFINE_PERFORMANCE_METRIC(BindableValueUpdate, "QmlBindableValue::update"); + Q_DEFINE_PERFORMANCE_METRIC(PixmapLoad, "Pixmap loading"); + Q_DEFINE_PERFORMANCE_METRIC(MetaProperty, "Meta property resolution"); + Q_DEFINE_PERFORMANCE_METRIC(PathCache, "Path cache"); + Q_DEFINE_PERFORMANCE_METRIC(CreateParticle, "Particle creation"); + Q_DEFINE_PERFORMANCE_METRIC(FontDatabase, "Font database creation"); + Q_DEFINE_PERFORMANCE_METRIC(ItemComponentComplete, "QFxItem::componentComplete"); + Q_DEFINE_PERFORMANCE_METRIC(ImageComponentComplete, "QFxImage::componentComplete"); + Q_DEFINE_PERFORMANCE_METRIC(ComponentInstanceComponentComplete, "QFxComponentInstance::componentComplete"); + Q_DEFINE_PERFORMANCE_METRIC(BaseLayoutComponentComplete, "QFxBaseLayout::componentComplete"); + Q_DEFINE_PERFORMANCE_METRIC(TextComponentComplete, "QFxText::componentComplete"); + Q_DEFINE_PERFORMANCE_METRIC(ContextQuery, "QtScript: Query Context"); + Q_DEFINE_PERFORMANCE_METRIC(ContextProperty, "QtScript: Context Property"); + Q_DEFINE_PERFORMANCE_METRIC(ObjectQuery, "QtScript: Query Object"); + Q_DEFINE_PERFORMANCE_METRIC(ObjectProperty, "QtScript: Object Property"); + Q_DEFINE_PERFORMANCE_METRIC(ObjectSetProperty, "QtScript: Set Object Property"); + Q_DEFINE_PERFORMANCE_METRIC(QFxText_setText, "QFxText::setText"); +} +QT_END_NAMESPACE diff --git a/src/declarative/util/qfxperf.h b/src/declarative/util/qfxperf.h new file mode 100644 index 0000000..b1f9bd0 --- /dev/null +++ b/src/declarative/util/qfxperf.h @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef _QFXPERF_H_ +#define _QFXPERF_H_ + +#include "qperformancelog.h" + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Declarative) +Q_DECLARE_PERFORMANCE_LOG(QFxPerf) { + Q_DECLARE_PERFORMANCE_METRIC(XmlParsing); + Q_DECLARE_PERFORMANCE_METRIC(Compile); + Q_DECLARE_PERFORMANCE_METRIC(CompileRun); + Q_DECLARE_PERFORMANCE_METRIC(CssParsing); + Q_DECLARE_PERFORMANCE_METRIC(CreateComponent); + Q_DECLARE_PERFORMANCE_METRIC(BindInit); + Q_DECLARE_PERFORMANCE_METRIC(BindCompile); + Q_DECLARE_PERFORMANCE_METRIC(BindValue); + Q_DECLARE_PERFORMANCE_METRIC(BindValueSSE); + Q_DECLARE_PERFORMANCE_METRIC(BindValueQt); + Q_DECLARE_PERFORMANCE_METRIC(BindableValueUpdate); + Q_DECLARE_PERFORMANCE_METRIC(PixmapLoad); + Q_DECLARE_PERFORMANCE_METRIC(MetaProperty); + Q_DECLARE_PERFORMANCE_METRIC(PathCache); + Q_DECLARE_PERFORMANCE_METRIC(CreateParticle); + Q_DECLARE_PERFORMANCE_METRIC(FontDatabase); + Q_DECLARE_PERFORMANCE_METRIC(ItemComponentComplete); + Q_DECLARE_PERFORMANCE_METRIC(ImageComponentComplete); + Q_DECLARE_PERFORMANCE_METRIC(ComponentInstanceComponentComplete); + Q_DECLARE_PERFORMANCE_METRIC(BaseLayoutComponentComplete); + Q_DECLARE_PERFORMANCE_METRIC(TextComponentComplete); + Q_DECLARE_PERFORMANCE_METRIC(ContextQuery); + Q_DECLARE_PERFORMANCE_METRIC(ContextProperty); + Q_DECLARE_PERFORMANCE_METRIC(ObjectQuery); + Q_DECLARE_PERFORMANCE_METRIC(ObjectProperty); + Q_DECLARE_PERFORMANCE_METRIC(ObjectSetProperty); + Q_DECLARE_PERFORMANCE_METRIC(QFxText_setText); +} + +#endif // _QFXPERF_H_ + + +QT_END_NAMESPACE + +QT_END_HEADER diff --git a/src/declarative/util/qfxview.cpp b/src/declarative/util/qfxview.cpp new file mode 100644 index 0000000..3fb30e9 --- /dev/null +++ b/src/declarative/util/qfxview.cpp @@ -0,0 +1,310 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qscriptvalueiterator.h" +#include "qdebug.h" +#include "qtimer.h" +#include "qevent.h" +#include "qdir.h" +#include "qcoreapplication.h" +#include "qfontdatabase.h" +#include "qicon.h" +#include "qurl.h" +#include "qboxlayout.h" + +#include "qmlbindablevalue.h" +#include "qml.h" +#include "qfxitem.h" +#include "qperformancelog.h" +#include "qfxperf.h" + +#include "qfxview.h" +#include <QtDeclarative/qmlengine.h> +#include <QtDeclarative/qmlcontext.h> + + +QT_BEGIN_NAMESPACE +DEFINE_BOOL_CONFIG_OPTION(itemTreeDump, ITEMTREE_DUMP); + +static QVariant stringToPixmap(const QString &str) +{ + //XXX need to use correct paths + return QVariant(QPixmap(str)); +} + +static QVariant stringToIcon(const QString &str) +{ + //XXX need to use correct paths + return QVariant(QIcon(str)); +} + +static QVariant stringToKeySequence(const QString &str) +{ + return QVariant::fromValue(QKeySequence(str)); +} + +static QVariant stringToUrl(const QString &str) +{ + return QVariant(QUrl(str)); +} + +class QFxViewPrivate +{ +public: + QFxViewPrivate(QFxView *w) + : q(w), root(0), component(0) {} + + QFxView *q; + QFxItem *root; + + QUrl source; + QString xml; + + QmlEngine engine; + QmlComponent *component; + void init(); +}; + +/*! + \class QFxView + \brief The QFxView class provides a widget for displaying a Qt Declarative user interface. + + QFxView currently provides a minimal interface for displaying Qml files, and + connecting between QML and C++ Qt objects. + + Typcial usage looks something like this: + \code + ... + QFxView *view = new QFxView(this); + vbox->addWidget(view); + + QFile file(fileName); + file.open(QFile::ReadOnly); + QString xml = file.readAll(); + view->setXml(xml, fileName); + + QFileInfo fi(file); + view->setPath(fi.path()); + + view->execute(); + ... + \endcode +*/ + +QFxView::QFxView(QWidget *parent) +: QSimpleCanvas(parent), d(new QFxViewPrivate(this)) +{ + d->init(); +} + +QFxView::QFxView(QSimpleCanvas::CanvasMode mode, QWidget *parent) +: QSimpleCanvas(mode, parent), d(new QFxViewPrivate(this)) +{ + d->init(); +} + +void QFxViewPrivate::init() +{ + // XXX: These need to be put in a central location for this kind of thing + qRegisterMetaType<QFxAnchorLine>("QFxAnchorLine"); + + QmlMetaType::registerCustomStringConverter(QVariant::Pixmap, &stringToPixmap); + QmlMetaType::registerCustomStringConverter(QVariant::Icon, &stringToIcon); + QmlMetaType::registerCustomStringConverter(QVariant::KeySequence, &stringToKeySequence); + QmlMetaType::registerCustomStringConverter(QVariant::Url, &stringToUrl); + +#ifdef Q_ENABLE_PERFORMANCE_LOG + QFxPerfTimer<QFxPerf::FontDatabase> perf; +#endif + QFontDatabase database; +} + +QFxView::~QFxView() +{ + clearItems(); + delete d; d = 0; +} + +void QFxView::setUrl(const QUrl& url) +{ + d->source = url; + d->xml = QString(); +} + +void QFxView::setXml(const QString &xml, const QString &filename) +{ + d->source = QUrl::fromLocalFile(filename); + d->xml = xml; +} + +QString QFxView::xml() const +{ + return d->xml; +} + +QmlEngine* QFxView::engine() +{ + return &d->engine; +} + +QmlContext* QFxView::rootContext() +{ + return d->engine.rootContext(); +} + +void QFxView::execute() +{ + rootContext()->activate(); + + if (d->xml.isEmpty()) { + d->component = new QmlComponent(&d->engine, d->source, this); + } else { + d->component = new QmlComponent(&d->engine, d->xml.toUtf8(), d->source); + } + + if(d->component->isReady()) { + continueExecute(); + } else { + connect(d->component, SIGNAL(readyChanged()), this, SLOT(continueExecute())); + } +} + +void QFxView::continueExecute() +{ + disconnect(d->component, SIGNAL(readyChanged()), this, SLOT(continueExecute())); + + if(!d->component){ + qWarning() << "Error in loading" << d->source; + return; + } + + QObject *obj = d->component->create(); + rootContext()->deactivate(); + if(obj) { + if(QFxItem *item = qobject_cast<QFxItem *>(obj)) { + item->QSimpleCanvasItem::setParent(QSimpleCanvas::root()); + + if(itemTreeDump()) + item->dump(); + + QPerformanceLog::displayData(); + QPerformanceLog::clear(); + d->root = item; + emit sceneResized(QSize(item->width(), item->height())); + } else if(QWidget *wid = qobject_cast<QWidget *>(obj)) { + window()->setAttribute(Qt::WA_OpaquePaintEvent, false); + window()->setAttribute(Qt::WA_NoSystemBackground, false); + if (!layout()) { + setLayout(new QVBoxLayout); + } else if (layout()->count()) { + // Hide the QGraphicsView in GV mode. + QLayoutItem *item = layout()->itemAt(0); + if (item->widget()) + item->widget()->hide(); + } + layout()->addWidget(wid); + emit sceneResized(wid->size()); + } + } +} + +QFxItem* QFxView::addItem(const QString &xml, QFxItem* parent) +{ + if(!d->root) + return 0; + + QmlComponent component(&d->engine, xml.toUtf8(), QUrl()); + QObject *obj = component.create(); + if(obj){ + QFxItem *item = static_cast<QFxItem *>(obj); + if(!parent) + parent = d->root; + + item->setItemParent(parent); + return item; + } + return 0; +} + +void QFxView::reset() +{ + clearItems(); + d->engine.clearComponentCache(); +} + +void QFxView::clearItems() +{ + if(!d->root) + return; + delete d->root; + d->root = 0; +} + +QFxItem *QFxView::root() const +{ + return d->root; +} + +void QFxView::resizeEvent(QResizeEvent *e) +{ + if(d->root) { + d->root->setWidth(width()); + d->root->setHeight(height()); + } + QSimpleCanvas::resizeEvent(e); +} + +void QFxView::focusInEvent(QFocusEvent *) +{ + // Do nothing (do not call QWidget::update()) +} + +void QFxView::focusOutEvent(QFocusEvent *) +{ + // Do nothing (do not call QWidget::update()) +} + + +void QFxView::dumpRoot() +{ + root()->dump(); +} +QT_END_NAMESPACE diff --git a/src/declarative/util/qfxview.h b/src/declarative/util/qfxview.h new file mode 100644 index 0000000..b5592b8 --- /dev/null +++ b/src/declarative/util/qfxview.h @@ -0,0 +1,107 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef _QFXVIEW_H_ +#define _QFXVIEW_H_ + +#include <qfxglobal.h> +#include <QtCore/qdatetime.h> +#include <QtGui/qgraphicssceneevent.h> +#include <QtGui/qwidget.h> +#include <qsimplecanvas.h> + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Declarative) +class QFxItem; +class QmlEngine; +class QmlContext; +class Canvas; + +class QFxViewPrivate; +class Q_DECLARATIVE_EXPORT QFxView : public QSimpleCanvas +{ +Q_OBJECT +public: + explicit QFxView(QWidget *parent = 0); + QFxView(QSimpleCanvas::CanvasMode mode, QWidget* parent = 0); + + virtual ~QFxView(); + + void setUrl(const QUrl&); + void setXml(const QString &xml, const QString &filename=QString()); + QString xml() const; + QmlEngine* engine(); + QmlContext* rootContext(); + virtual void execute(); + virtual void reset(); + + virtual QFxItem* addItem(const QString &xml, QFxItem* parent=0); + virtual void clearItems(); + + virtual QFxItem *root() const; + + void dumpRoot(); + +Q_SIGNALS: + void sceneResized(QSize size); + +private Q_SLOTS: + void continueExecute(); + +protected: + virtual void resizeEvent(QResizeEvent *); + void focusInEvent(QFocusEvent *); + void focusOutEvent(QFocusEvent *); + +private: + friend class QFxViewPrivate; + QFxViewPrivate *d; +}; + + +QT_END_NAMESPACE + +QT_END_HEADER +#endif // _QFXVIEW_H_ diff --git a/src/declarative/util/qmlanimation.cpp b/src/declarative/util/qmlanimation.cpp new file mode 100644 index 0000000..803f2b2 --- /dev/null +++ b/src/declarative/util/qmlanimation.cpp @@ -0,0 +1,2292 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qmlanimation.h" +#include "gfxtimeline.h" +#include "qvariant.h" +#include "qcolor.h" +#include "qfile.h" +#include "gfxeasing.h" +#include "qmlpropertyvaluesource.h" +#include "qml.h" +#include "qmlanimation_p.h" +#include "gfxtimeline.h" +#include "qmlbehaviour.h" +#include <QParallelAnimationGroup> +#include <QSequentialAnimationGroup> +#include <QtCore/qset.h> +#include <QtDeclarative/qmlexpression.h> +#include <private/qmlstringconverters_p.h> + +/* TODO: + Check for any memory leaks + easing should be a QEasingCurve-type property + All other XXXs +*/ + +QT_BEGIN_NAMESPACE + +QEasingCurve stringToCurve(const QString &curve) +{ + QEasingCurve easingCurve; + + QString normalizedCurve = curve; + bool hasParams = curve.contains(QLatin1Char('(')); + QStringList props; + + if(hasParams) { + QString easeName = curve.trimmed(); + if(!easeName.endsWith(QLatin1Char(')'))) { + qWarning("QEasingCurve: Unmatched perenthesis in easing function '%s'", + curve.toLatin1().constData()); + return easingCurve; + } + + int idx = easeName.indexOf(QLatin1Char('(')); + QString prop_str = + easeName.mid(idx + 1, easeName.length() - 1 - idx - 1); + normalizedCurve = easeName.left(idx); + + props = prop_str.split(QLatin1Char(',')); + } + + normalizedCurve = normalizedCurve.mid(4); + //XXX optimize? + int index = QEasingCurve::staticMetaObject.indexOfEnumerator("Type"); + QMetaEnum me = QEasingCurve::staticMetaObject.enumerator(index); + + int value = me.keyToValue(normalizedCurve.toLatin1().constData()); + if (value < 0) { + //XXX print line number + qWarning("QEasingCurve: Unknown easing curve '%s'", + curve.toLatin1().constData()); + value = 0; + } + easingCurve.setType((QEasingCurve::Type)value); + + if (hasParams) { + foreach(QString str, props) { + int sep = str.indexOf(QLatin1Char(':')); + + if(sep == -1) { + qWarning("QEasingCurve: Improperly specified property in easing function '%s'", + curve.toLatin1().constData()); + return easingCurve; + } + + QString propName = str.left(sep).trimmed(); + bool isOk; + qreal propValue = str.mid(sep + 1).trimmed().toDouble(&isOk); + + if(propName.isEmpty() || !isOk) { + qWarning("QEasingCurve: Improperly specified property in easing function '%s'", + curve.toLatin1().constData()); + return easingCurve; + } + + //XXX optimize + if (propName == QLatin1String("amplitude")) { + easingCurve.setAmplitude(propValue); + } else if (propName == QLatin1String("period")) { + easingCurve.setPeriod(propValue); + } else if (propName == QLatin1String("overshoot")) { + easingCurve.setOvershoot(propValue); + } + } + } + + return easingCurve; +} + +QML_DEFINE_NOCREATE_TYPE(QmlAbstractAnimation); + +/*! + \qmlclass Animation + \brief The Animation element is the base of all QML animations. + + The Animation element cannot be used directly in a QML file. It exists + to provide a set of common properties and methods, available across all the + other animation types that inherit from it. Attempting to use the Animation + element directly will result in an error. +*/ + +/*! + \class QmlAbstractAnimation + \internal +*/ + +QmlAbstractAnimation::QmlAbstractAnimation(QObject *parent) +: QmlPropertyValueSource(*(new QmlAbstractAnimationPrivate), parent) +{ +} + +QmlAbstractAnimation::~QmlAbstractAnimation() +{ +} + +QmlAbstractAnimation::QmlAbstractAnimation(QmlAbstractAnimationPrivate &dd, QObject *parent) +: QmlPropertyValueSource(dd, parent) +{ +} + +/*! + \qmlproperty bool Animation::running + This property holds whether the animation is currently running. + + The \c running property can be set to declaratively control whether or not + an animation is running. The following example will animate a rectangle + whenever the \l MouseRegion is pressed. + + \code + <Rect width="100" height="100"> + <x> + <NumericAnimation running="{MyMouse.pressed}" from="0" to="100" /> + </x> + <MouseRegion id="MyMouse" /> + </Rect> + \endcode + + Likewise, the \c running property can be read to determine if the animation + is running. In the following example the text element will indicate whether + or not the animation is running. + + \code + <NumericAnimation id="MyAnimation" /> + <Text text="{MyAnimation.running?'Animation is running':'Animation is not running'}" /> + \endcode + + Animations can also be started and stopped imperatively from JavaScript + using the \c start() and \c stop() methods. + + By default, animations are not running. +*/ +bool QmlAbstractAnimation::isRunning() const +{ + Q_D(const QmlAbstractAnimation); + return d->running; +} + +void QmlAbstractAnimationPrivate::commence() +{ + Q_Q(QmlAbstractAnimation); + + q->prepare(userProperty.value); + q->qtAnimation()->start(); + if(!q->qtAnimation()->state() == QAbstractAnimation::Running) { + running = false; + emit q->completed(); + } +} + +void QmlAbstractAnimation::setRunning(bool r) +{ + Q_D(QmlAbstractAnimation); + if(d->running == r) + return; + + if(d->group) { + qWarning("QmlAbstractAnimation: setRunning() cannot be used on non-root animation nodes"); + return; + } + + d->running = r; + if(d->running) { + if(!d->connectedTimeLine) { + QObject::connect(qtAnimation(), SIGNAL(finished()), + this, SLOT(timelineComplete())); + d->connectedTimeLine = true; + } + if (d->componentComplete) + d->commence(); + else + d->startOnCompletion = true; + emit started(); + } else { + if(!d->finishPlaying) + qtAnimation()->stop(); + emit completed(); + } + + emit runningChanged(d->running); +} + +void QmlAbstractAnimation::classBegin() +{ + Q_D(QmlAbstractAnimation); + d->componentComplete = false; +} + +void QmlAbstractAnimation::componentComplete() +{ + Q_D(QmlAbstractAnimation); + if (d->startOnCompletion) + d->commence(); + d->componentComplete = true; +} + +/*! + \qmlproperty bool Animation::finishPlaying + This property holds whether the animation should finish playing when it is stopped. + + If this true the animation will complete its current iteration when it + is stopped - either by setting the \c running property to false, or by + calling the \c stop() method. The \c complete() method is not effected + by this value. + + This behaviour is most useful when the \c repeat property is set, as the + animation will finish playing normally but not restart. + + By default, the finishPlaying property is not set. +*/ +bool QmlAbstractAnimation::finishPlaying() const +{ + Q_D(const QmlAbstractAnimation); + return d->finishPlaying; +} + +void QmlAbstractAnimation::setFinishPlaying(bool f) +{ + Q_D(QmlAbstractAnimation); + if(d->finishPlaying == f) + return; + + d->finishPlaying = f; + emit finishPlayingChanged(f); +} + +/*! + \qmlproperty bool Animation::repeat + This property holds whether the animation should repeat. + + If set, the animation will continuously repeat until it is explicitly + stopped - either by setting the \c running property to false, or by calling + the \c stop() method. + + In the following example, the rectangle will spin indefinately. + + \code + <Rect> + <rotation> + <NumericAnimation running="true" repeat="true" from="0" to="360" /> + </rotation> + </Rect> + \endcode +*/ +bool QmlAbstractAnimation::repeat() const +{ + Q_D(const QmlAbstractAnimation); + return d->repeat; +} + +void QmlAbstractAnimation::setRepeat(bool r) +{ + Q_D(QmlAbstractAnimation); + if(r == d->repeat) + return; + + d->repeat = r; + int ic = r ? -1 : 1; + qtAnimation()->setIterationCount(ic); + emit repeatChanged(r); +} + +QmlAnimationGroup *QmlAbstractAnimation::group() const +{ + Q_D(const QmlAbstractAnimation); + return d->group; +} + +void QmlAbstractAnimation::setGroup(QmlAnimationGroup *g) +{ + Q_D(QmlAbstractAnimation); + if(d->group == g) + return; + if(d->group) + static_cast<QmlAnimationGroupPrivate *>(d->group->d_ptr)->animations.removeAll(this); + + d->group = g; + + if(d->group && !static_cast<QmlAnimationGroupPrivate *>(d->group->d_ptr)->animations.contains(this)) + static_cast<QmlAnimationGroupPrivate *>(d->group->d_ptr)->animations.append(this); + + if (d->group) + ((QAnimationGroup*)d->group->qtAnimation())->addAnimation(qtAnimation()); + + //if(g) //if removed from a group, then the group should no longer be the parent + setParent(g); +} + +/*! + \qmlproperty Object Animation::target + This property holds an explicit target object to animate. + + The exact effect of the \c target property depends on how the animation + is being used. Refer to the \l animation documentation for details. +*/ +QObject *QmlAbstractAnimation::target() const +{ + Q_D(const QmlAbstractAnimation); + return d->target; +} + +void QmlAbstractAnimation::setTarget(QObject *o) +{ + Q_D(QmlAbstractAnimation); + if(d->target == o) + return; + + d->target = o; + if(d->target && !d->propertyName.isEmpty()) { + d->userProperty = QmlMetaProperty(d->target, d->propertyName); + } else { + d->userProperty.invalidate(); + } + + emit targetChanged(d->target, d->propertyName); +} + +/*! + \qmlproperty string Animation::property + This property holds an explicit property to animated. + + The exact effect of the \c property property depends on how the animation + is being used. Refer to the \l animation documentation for details. +*/ +QString QmlAbstractAnimation::property() const +{ + Q_D(const QmlAbstractAnimation); + return d->propertyName; +} + +void QmlAbstractAnimation::setProperty(const QString &n) +{ + Q_D(QmlAbstractAnimation); + if(d->propertyName == n) + return; + + d->propertyName = n; + if(d->target && !d->propertyName.isEmpty()) { + d->userProperty = QmlMetaProperty(d->target, d->propertyName); + } else { + d->userProperty.invalidate(); + } + + emit targetChanged(d->target, d->propertyName); +} + +/*! + \qmlmethod Animation::start() + \brief Starts the animation. + + If the animation is already running, calling this method has no effect. The + \c running property will be true following a call to \c start(). +*/ +void QmlAbstractAnimation::start() +{ + setRunning(true); +} + +/*! + \qmlmethod Animation::stop() + \brief Stops the animation. + + If the animation is not running, calling this method has no effect. The + \c running property will be false following a call to \c stop(). + + Normally \c stop() stops the animation immediately, and the animation has + no further influence on property values. In this example animation + \code + <Rect> + <x> + <NumericAnimation from="0" to="100" duration="500" /> + </x> + </Rect> + \endcode + was stopped at time 250ms, the \c x property will have a value of 50. + + However, if the \c finishPlaying property is set, the animation will + continue running until it completes and then stop. The \c running property + will still become false immediately. +*/ +void QmlAbstractAnimation::stop() +{ + setRunning(false); +} + +/*! + \qmlmethod Animation::restart() + \brief Restarts the animation. + + This is a convenience method, and is equivalent to calling \c stop() and + then \c start(). +*/ +void QmlAbstractAnimation::restart() +{ + stop(); + start(); +} + +/*! + \qmlmethod Animation::complete() + \brief Stops the animation, jumping to the final property values. + + If the animation is not running, calling this method has no effect. The + \c running property will be false following a call to \c complete(). + + Unlike \c stop(), \c complete() immediately fast-forwards the animation to + its end. In the following example, + \code + <Rect> + <x> + <NumericAnimation from="0" to="100" duration="500" /> + </x> + </Rect> + \endcode + calling \c stop() at time 250ms will result in the \c x property having + a value of 50, while calling \c complete() will set the \c x property to + 100, exactly as though the animation had played the whole way through. +*/ +void QmlAbstractAnimation::complete() +{ + if(isRunning()) { + qtAnimation()->setCurrentTime(qtAnimation()->duration()); + } +} + +void QmlAbstractAnimation::setTarget(const QmlMetaProperty &p) +{ + Q_D(QmlAbstractAnimation); + if(d->userProperty.isNull) + d->userProperty = p; +} + +//prepare is called before an animation begins +//(when an animation is used as a simple animation, and not as part of a transition) +void QmlAbstractAnimation::prepare(QmlMetaProperty &) +{ +} + +void QmlAbstractAnimation::transition(QmlStateActions &actions, + QmlMetaProperties &modified, + TransitionDirection direction) +{ + Q_UNUSED(actions); + Q_UNUSED(modified); + Q_UNUSED(direction); +} + +void QmlAbstractAnimation::timelineComplete() +{ + setRunning(false); +} + +/*! + \qmlclass PauseAnimation QmlPauseAnimation + \inherits Animation + \brief The PauseAnimation provides a pause for an animation. + + When used in a SequentialAnimation, PauseAnimation is a step when + nothing happens, for a specified duration. + + A 500ms animation sequence, with a 100ms pause between two animations: + \code + <SequentialAnimation> + <NumericAnimation ... duration="200"/> + <PauseAnimation duration="100"/> + <NumericAnimation ... duration="200"/> + </SequentialAnimation> + \endcode +*/ +/*! + \internal + \class QmlPauseAnimation + \ingroup animation states + \brief The QmlPauseAnimation class provides a pause for an animation. + + When used in a QmlSequentialAnimation, QmlPauseAnimation is a step when + nothing happens, for a specified duration. + + A QmlPauseAnimation object can be instantiated in Qml using the tag + \ref xmlPauseAnimation "<PauseAnimation>". +*/ + +QML_DEFINE_TYPE(QmlPauseAnimation,PauseAnimation); +QmlPauseAnimation::QmlPauseAnimation(QObject *parent) +: QmlAbstractAnimation(*(new QmlPauseAnimationPrivate), parent) +{ + Q_D(QmlPauseAnimation); + d->init(); +} + +QmlPauseAnimation::~QmlPauseAnimation() +{ +} + +void QmlPauseAnimationPrivate::init() +{ + Q_Q(QmlPauseAnimation); + pa = new QPauseAnimation(q); +} + +/*! + \qmlproperty int PauseAnimation::duration + This property holds the duration of the pause in milliseconds + + The default value is 250. +*/ +/*! + \property QmlPauseAnimation::duration + \brief the duration of the pause in milliseconds + + The default value is 250. +*/ +int QmlPauseAnimation::duration() const +{ + Q_D(const QmlPauseAnimation); + return d->pa->duration(); +} + +void QmlPauseAnimation::setDuration(int duration) +{ + if(duration < 0) { + qWarning("QmlPauseAnimation: Cannot set a duration of < 0"); + return; + } + + Q_D(QmlPauseAnimation); + if(d->pa->duration() == duration) + return; + d->pa->setDuration(duration); + emit durationChanged(duration); +} + +void QmlPauseAnimation::prepare(QmlMetaProperty &p) +{ + Q_D(QmlPauseAnimation); + if(d->userProperty.isNull) + d->property = p; + else + d->property = d->userProperty; +} + +QAbstractAnimation *QmlPauseAnimation::qtAnimation() +{ + Q_D(QmlPauseAnimation); + return d->pa; +} + +/*! + \qmlclass ColorAnimation QmlColorAnimation + \inherits Animation + \brief The ColorAnimation allows you to animate color changes. + + \code + <ColorAnimation from="white" to="#c0c0c0" duration="100"/> + \endcode + + The default property animated is \c color, but like other animations, + this can be changed by setting \c property. The \c color property will + still animate. XXX is this a bug? +*/ +/*! + \internal + \class QmlColorAnimation + \ingroup animation states + \brief The QmlColorAnimation class allows you to animate color changes. + + A QmlColorAnimation object can be instantiated in Qml using the tag + \ref xmlColorAnimation "<ColorAnimation>". +*/ + +QmlColorAnimation::QmlColorAnimation(QObject *parent) +: QmlAbstractAnimation(*(new QmlColorAnimationPrivate), parent) +{ + Q_D(QmlColorAnimation); + d->init(); +} + +QmlColorAnimation::~QmlColorAnimation() +{ +} + +void QmlColorAnimationPrivate::init() +{ + Q_Q(QmlColorAnimation); + ca = new GfxValueAnimator(q); + ca->setStartValue(QVariant(0.0f)); + ca->setEndValue(QVariant(1.0f)); +} + +/*! + \qmlproperty int ColorAnimation::duration + This property holds the duration of the color transition, in milliseconds. + + The default value is 250. +*/ +/*! + \property QmlColorAnimation::duration + \brief the duration of the transition, in milliseconds. + + The default value is 250. +*/ +int QmlColorAnimation::duration() const +{ + Q_D(const QmlColorAnimation); + return d->ca->duration(); +} + +void QmlColorAnimation::setDuration(int duration) +{ + if(duration < 0) { + qWarning("QmlColorAnimation: Cannot set a duration of < 0"); + return; + } + + Q_D(QmlColorAnimation); + if(d->ca->duration() == duration) + return; + d->ca->setDuration(duration); + emit durationChanged(duration); +} + +/*! + \qmlproperty color ColorAnimation::from + This property holds the starting color. +*/ +/*! + \property QmlColorAnimation::from + \brief the starting color. +*/ +QColor QmlColorAnimation::from() const +{ + Q_D(const QmlColorAnimation); + return d->fromValue; +} + +void QmlColorAnimation::setFrom(const QColor &f) +{ + Q_D(QmlColorAnimation); + if(d->fromValue.isValid() && f == d->fromValue) + return; + d->fromValue = f; + emit fromChanged(f); +} + +/*! + \qmlproperty color ColorAnimation::from + This property holds the ending color. +*/ +/*! + \property QmlColorAnimation::to + \brief the ending color. +*/ +QColor QmlColorAnimation::to() const +{ + Q_D(const QmlColorAnimation); + return d->toValue; +} + +void QmlColorAnimation::setTo(const QColor &t) +{ + Q_D(QmlColorAnimation); + if(d->toValue.isValid() && t == d->toValue) + return; + d->toValue = t; + emit toChanged(t); +} + +/*! + \qmlproperty string ColorAnimation::easing + This property holds the easing curve used for the transition. + + Each channel of the color is eased using the same easing curve. + See NumericAnimation::easing for a full discussion of easing, + and a list of available curves. +*/ +QString QmlColorAnimation::easing() const +{ + Q_D(const QmlColorAnimation); + return d->easing; +} + +void QmlColorAnimation::setEasing(const QString &e) +{ + Q_D(QmlColorAnimation); + if(d->easing == e) + return; + + d->easing = e; + d->ca->setEasingCurve(stringToCurve(d->easing)); + emit easingChanged(e); +} + +/*! + \qmlproperty list<Item> ColorAnimation::filter + This property holds the items selected to be affected by this animation (all if not set). + \sa exclude +*/ +QList<QObject *> *QmlColorAnimation::filter() +{ + Q_D(QmlColorAnimation); + return &d->filter; +} + +/*! + \qmlproperty list<Item> ColorAnimation::exclude + This property holds the items not to be affected by this animation. + \sa filter +*/ +QList<QObject *> *QmlColorAnimation::exclude() +{ + Q_D(QmlColorAnimation); + return &d->exclude; +} + +void QmlColorAnimation::prepare(QmlMetaProperty &p) +{ + Q_D(QmlColorAnimation); + if(d->userProperty.isNull) + d->property = p; + else + d->property = d->userProperty; + d->fromSourced = false; + d->value.GfxValue::setValue(0.); + d->ca->setAnimValue(&d->value, QAbstractAnimation::KeepWhenStopped); +} + +QAbstractAnimation *QmlColorAnimation::qtAnimation() +{ + Q_D(QmlColorAnimation); + return d->ca; +} + +void QmlColorAnimation::transition(QmlStateActions &actions, + QmlMetaProperties &modified, + TransitionDirection direction) +{ + Q_D(QmlColorAnimation); + Q_UNUSED(direction); + + struct NTransitionData : public GfxValue + { + QmlStateActions actions; + void write(QmlMetaProperty &property, const QColor &color) + { + if(property.propertyType() == qMetaTypeId<QColor>()) { + property.write(color); + } + } + + void setValue(qreal v) + { + GfxValue::setValue(v); + for(int ii = 0; ii < actions.count(); ++ii) { + Action &action = actions[ii]; + + QColor to(action.toValue.value<QColor>()); + + if(v == 1.) { + write(action.property, to); + } else { + if(action.fromValue.isNull()) { + action.fromValue = action.property.read(); + if(action.fromValue.isNull()) + action.fromValue = QVariant(QColor()); + } + + QColor from(action.fromValue.value<QColor>()); + + //XXX consolidate somewhere + uint red = uint(qreal(from.red()) + v * (qreal(to.red()) - qreal(from.red()))); + uint green = uint(qreal(from.green()) + v * (qreal(to.green()) - qreal(from.green()))); + uint blue = uint(qreal(from.blue()) + v * (qreal(to.blue()) - qreal(from.blue()))); + uint alpha = uint(qreal(from.alpha()) + v * (qreal(to.alpha()) - qreal(from.alpha()))); + + write(action.property, QColor(red, green, blue, alpha)); + } + } + } + }; + + //XXX should we get rid of this? + QStringList props; + props << QLatin1String("color"); + if(!d->propertyName.isEmpty() && !props.contains(d->propertyName)) + props.append(d->propertyName); + + NTransitionData *data = new NTransitionData; + + QSet<QObject *> objs; + for(int ii = 0; ii < actions.count(); ++ii) { + Action &action = actions[ii]; + + QObject *obj = action.property.object(); + QString propertyName = action.property.name(); + + if((d->filter.isEmpty() || d->filter.contains(obj)) && + (!d->exclude.contains(obj)) && props.contains(propertyName) && + (!target() || target() == obj)) { + objs.insert(obj); + Action myAction = action; + if(d->fromValue.isValid()) + myAction.fromValue = QVariant(d->fromValue); + if(d->toValue.isValid()) + myAction.toValue = QVariant(d->toValue); + + modified << action.property; + data->actions << myAction; + action.fromValue = myAction.toValue; + } + } + + if(d->toValue.isValid() && target() && !objs.contains(target())) { + QObject *obj = target(); + for(int jj = 0; jj < props.count(); ++jj) { + Action myAction; + myAction.property = QmlMetaProperty(obj, props.at(jj)); + + if(d->fromValue.isValid()) + myAction.fromValue = QVariant(d->fromValue); + + myAction.toValue = QVariant(d->toValue); + myAction.bv = 0; + myAction.event = 0; + data->actions << myAction; + } + } + + if(data->actions.count()) + d->ca->setAnimValue(data, QAbstractAnimation::DeleteWhenStopped); + else + delete data; +} + + +void QmlColorAnimationPrivate::valueChanged(qreal v) +{ + if(!fromSourced) { + if(!fromValue.isValid()) { + fromValue = QColor(qvariant_cast<QColor>(property.read())); + } + fromSourced = true; + } + + //XXX consolidate somewhere + uint red = uint(qreal(fromValue.red()) + v * (qreal(toValue.red()) - qreal(fromValue.red()))); + uint green = uint(qreal(fromValue.green()) + v * (qreal(toValue.green()) - qreal(fromValue.green()))); + uint blue = uint(qreal(fromValue.blue()) + v * (qreal(toValue.blue()) - qreal(fromValue.blue()))); + uint alpha = uint(qreal(fromValue.alpha()) + v * (qreal(toValue.alpha()) - qreal(fromValue.alpha()))); + + if(property.propertyType() == qMetaTypeId<QColor>()) { + property.write(QColor(red, green, blue, alpha)); + } +} +QML_DEFINE_TYPE(QmlColorAnimation,ColorAnimation); + +/*! + \qmlclass RunScriptAction QmlRunScriptAction + \inherits Animation + \brief The RunScripAction allows scripts to be run during transitions. + +*/ +/*! + \internal + \class QmlRunScriptAction + \brief The QmlRunScriptAction class allows scropts to be run during transitions + + \ref xmlRunScriptAction +*/ +QmlRunScriptAction::QmlRunScriptAction(QObject *parent) + :QmlAbstractAnimation(*(new QmlRunScriptActionPrivate), parent) +{ + Q_D(QmlRunScriptAction); + d->init(); +} + +QmlRunScriptAction::~QmlRunScriptAction() +{ +} + +void QmlRunScriptActionPrivate::init() +{ + Q_Q(QmlRunScriptAction); + rsa = new QActionAnimation(&proxy, q); +} + +/*! + \qmlproperty QString RunScript::script + This property holds the script to run. +*/ +QString QmlRunScriptAction::script() const +{ + Q_D(const QmlRunScriptAction); + return d->script; +} + +void QmlRunScriptAction::setScript(const QString &script) +{ + Q_D(QmlRunScriptAction); + if(script == d->script) + return; + d->script = script; + emit scriptChanged(script); +} + +/*! + \qmlproperty QString RunScript::script + This property holds the file containing the script to run. +*/ +QString QmlRunScriptAction::file() const +{ + Q_D(const QmlRunScriptAction); + return d->file; +} + +void QmlRunScriptAction::setFile(const QString &file) +{ + Q_D(QmlRunScriptAction); + if(file == d->file) + return; + d->file = file; + emit fileChanged(file); +} + +void QmlRunScriptActionPrivate::execute() +{ + Q_Q(QmlRunScriptAction); + QString scriptStr = script; + if(!file.isEmpty()){ + QFile scriptFile(file); + if(scriptFile.open(QIODevice::ReadOnly | QIODevice::Text)){ + scriptStr = QString::fromUtf8(scriptFile.readAll()); + } + } + + if(!scriptStr.isEmpty()) { + QmlExpression expr(ctxt, scriptStr, q); + expr.setTrackChange(false); + expr.value(); + } +} + +QAbstractAnimation *QmlRunScriptAction::qtAnimation() +{ + Q_D(QmlRunScriptAction); + return d->rsa; +} + +QML_DEFINE_TYPE(QmlRunScriptAction, RunScriptAction); + +/*! + \qmlclass SetPropertyAction QmlSetPropertyAction + \inherits Animation + \brief The SetPropertyAction allows property changes during transitions. + + Explicitly set \c theimage.smooth=true during a transition: + \code + <SetPropertyAction target="{theimage}" property="smooth" value="true"/> + \endcode + + Set \c thewebview.url to the value set for the destination state: + \code + <SetPropertyAction target="{thewebview}" property="url"/> + \endcode + + The SetPropertyAction is immediate - + the target property is not animated to the selected value in any way. +*/ +/*! + \internal + \class QmlSetPropertyAction + \brief The QmlSetPropertyAction class allows property changes during transitions. + + A QmlSetPropertyAction object can be instantiated in Qml using the tag + \ref xmlSetPropertyAction "<SetPropertyAction>". +*/ +QmlSetPropertyAction::QmlSetPropertyAction(QObject *parent) +: QmlAbstractAnimation(*(new QmlSetPropertyActionPrivate), parent) +{ + Q_D(QmlSetPropertyAction); + d->init(); +} + +QmlSetPropertyAction::~QmlSetPropertyAction() +{ +} + +void QmlSetPropertyActionPrivate::init() +{ + Q_Q(QmlSetPropertyAction); + spa = new QActionAnimation(q); +} + +/*! + \qmlproperty string SetPropertyAction::properties + This property holds the properties to be immediately set, comma-separated. +*/ +QString QmlSetPropertyAction::properties() const +{ + Q_D(const QmlSetPropertyAction); + return d->properties; +} + +void QmlSetPropertyAction::setProperties(const QString &p) +{ + Q_D(QmlSetPropertyAction); + if(d->properties == p) + return; + d->properties = p; + emit propertiesChanged(p); +} + +/*! + \qmlproperty list<Item> SetPropertyAction::filter + This property holds the items selected to be affected by this animation (all if not set). + \sa exclude +*/ +QList<QObject *> *QmlSetPropertyAction::filter() +{ + Q_D(QmlSetPropertyAction); + return &d->filter; +} + +/*! + \qmlproperty list<Item> SetPropertyAction::exclude + This property holds the items not to be affected by this animation. + \sa filter +*/ +QList<QObject *> *QmlSetPropertyAction::exclude() +{ + Q_D(QmlSetPropertyAction); + return &d->exclude; +} + +/*! + \qmlproperty any SetPropertyAction::value + This property holds the value to be set on the property. + If not set, then the value defined for the end state of the transition. +*/ +QVariant QmlSetPropertyAction::value() const +{ + Q_D(const QmlSetPropertyAction); + return d->value; +} + +void QmlSetPropertyAction::setValue(const QVariant &v) +{ + Q_D(QmlSetPropertyAction); + if(d->value.isNull || d->value != v) { + d->value = v; + emit valueChanged(v); + } +} + +void QmlSetPropertyActionPrivate::doAction() +{ + property.write(value); +} + +QAbstractAnimation *QmlSetPropertyAction::qtAnimation() +{ + Q_D(QmlSetPropertyAction); + return d->spa; +} + +void QmlSetPropertyAction::prepare(QmlMetaProperty &p) +{ + Q_D(QmlSetPropertyAction); + + if(d->userProperty.isNull) + d->property = p; + else + d->property = d->userProperty; + + d->spa->setAnimAction(&d->proxy, QAbstractAnimation::KeepWhenStopped); +} + +void QmlSetPropertyAction::transition(QmlStateActions &actions, + QmlMetaProperties &modified, + TransitionDirection direction) +{ + Q_D(QmlSetPropertyAction); + Q_UNUSED(direction); + + struct QmlSetPropertyAnimationAction : public QAbstractAnimationAction + { + QmlStateActions actions; + virtual void doAction() + { + for(int ii = 0; ii < actions.count(); ++ii) { + const Action &action = actions.at(ii); + QmlBehaviour::_ignore = true; + action.property.write(action.toValue); + QmlBehaviour::_ignore = false; + } + } + }; + + QStringList props = d->properties.split(QLatin1Char(',')); + for(int ii = 0; ii < props.count(); ++ii) + props[ii] = props.at(ii).trimmed(); + if(!d->propertyName.isEmpty() && !props.contains(d->propertyName)) + props.append(d->propertyName); + + QmlSetPropertyAnimationAction *data = new QmlSetPropertyAnimationAction; + + QSet<QObject *> objs; + for(int ii = 0; ii < actions.count(); ++ii) { + Action &action = actions[ii]; + + QObject *obj = action.property.object(); + QString propertyName = action.property.name(); + + if((d->filter.isEmpty() || d->filter.contains(obj)) && + (!d->exclude.contains(obj)) && props.contains(propertyName) && + (!target() || target() == obj)) { + objs.insert(obj); + Action myAction = action; + + if(d->value.isValid()) + myAction.toValue = d->value; + + modified << action.property; + data->actions << myAction; + action.fromValue = myAction.toValue; + } + } + + if(d->value.isValid() && target() && !objs.contains(target())) { + QObject *obj = target(); + for(int jj = 0; jj < props.count(); ++jj) { + Action myAction; + myAction.property = QmlMetaProperty(obj, props.at(jj)); + myAction.toValue = d->value; + data->actions << myAction; + } + } + + if(data->actions.count()) { + d->spa->setAnimAction(data, QAbstractAnimation::DeleteWhenStopped); + } else { + delete data; + } +} + +QML_DEFINE_TYPE(QmlSetPropertyAction,SetPropertyAction); + +/*! + \qmlclass ParentChangeAction QmlParentChangeAction + \inherits Animation + \brief The ParentChangeAction allows parent changes during transitions. + + The ParentChangeAction is immediate - it is not animated in any way. +*/ + +QmlParentChangeAction::QmlParentChangeAction(QObject *parent) +: QmlAbstractAnimation(*(new QmlParentChangeActionPrivate), parent) +{ + Q_D(QmlParentChangeAction); + d->init(); +} + +QmlParentChangeAction::~QmlParentChangeAction() +{ +} + +void QmlParentChangeActionPrivate::init() +{ + Q_Q(QmlParentChangeAction); + cpa = new QActionAnimation(q); +} + +void QmlParentChangeActionPrivate::doAction() +{ + //XXX property.write(value); +} + +void QmlParentChangeAction::prepare(QmlMetaProperty &p) +{ + Q_D(QmlParentChangeAction); + + if(d->userProperty.isNull) + d->property = p; + else + d->property = d->userProperty; + + //XXX +} + +QAbstractAnimation *QmlParentChangeAction::qtAnimation() +{ + Q_D(QmlParentChangeAction); + return d->cpa; +} + +void QmlParentChangeAction::transition(QmlStateActions &actions, + QmlMetaProperties &modified, + TransitionDirection direction) +{ + Q_D(QmlParentChangeAction); + Q_UNUSED(direction); + + struct QmlParentChangeActionData : public QAbstractAnimationAction + { + QmlStateActions actions; + virtual void doAction() + { + for(int ii = 0; ii < actions.count(); ++ii) { + const Action &action = actions.at(ii); + QmlBehaviour::_ignore = true; + action.property.write(action.toValue); + QmlBehaviour::_ignore = false; + } + } + }; + + QmlParentChangeActionData *data = new QmlParentChangeActionData; + + QSet<QObject *> objs; + for(int ii = 0; ii < actions.count(); ++ii) { + Action &action = actions[ii]; + + QObject *obj = action.property.object(); + QString propertyName = action.property.name(); + + if((!target() || target() == obj) && propertyName == QString(QLatin1String("moveToParent"))) { + objs.insert(obj); + Action myAction = action; + + /*if(d->value.isValid()) + myAction.toValue = d->value;*/ + + modified << action.property; + data->actions << myAction; + action.fromValue = myAction.toValue; + } + } + + /*if(d->value.isValid() && target() && !objs.contains(target())) { + QObject *obj = target(); + for(int jj = 0; jj < props.count(); ++jj) { + Action myAction; + myAction.property = QmlMetaProperty(obj, props.at(jj)); + myAction.toValue = d->value; + data->actions << myAction; + } + }*/ + + if(data->actions.count()) { + d->cpa->setAnimAction(data, QAbstractAnimation::DeleteWhenStopped); + } else { + delete data; + } +} + +QML_DEFINE_TYPE(QmlParentChangeAction,ParentChangeAction); + +/*! + \qmlclass NumericAnimation QmlNumericAnimation + \inherits Animation + \brief The NumericAnimation allows you to animate changes in properties of type qreal. + + Animate a set of properties over 200ms, from their values in the start state to + their values in the end state of the transition: + \code + <NumericAnimation properties="x,y,scale" duration="200"/> + \endcode +*/ + +/*! + \internal + \class QmlNumericAnimation + \ingroup animation states + \brief The QmlNumericAnimation class allows you to animate changes in properties of type qreal. + + A QmlNumericAnimation object can be instantiated in Qml using the tag + \ref xmlNumericAnimation "<NumericAnimation>". +*/ + +QmlNumericAnimation::QmlNumericAnimation(QObject *parent) +: QmlAbstractAnimation(*(new QmlNumericAnimationPrivate), parent) +{ + Q_D(QmlNumericAnimation); + d->init(); +} + +QmlNumericAnimation::~QmlNumericAnimation() +{ +} + +void QmlNumericAnimationPrivate::init() +{ + Q_Q(QmlNumericAnimation); + na = new GfxValueAnimator(q); + na->setStartValue(QVariant(0.0f)); + na->setEndValue(QVariant(1.0f)); +} + +/*! + \qmlproperty int NumericAnimation::duration + This property holds the duration of the transition, in milliseconds. + + The default value is 250. +*/ +/*! + \property QmlNumericAnimation::duration + \brief the duration of the transition, in milliseconds. + + The default value is 250. +*/ +int QmlNumericAnimation::duration() const +{ + Q_D(const QmlNumericAnimation); + return d->na->duration(); +} + +void QmlNumericAnimation::setDuration(int duration) +{ + if(duration < 0) { + qWarning("QmlNumericAnimation: Cannot set a duration of < 0"); + return; + } + + Q_D(QmlNumericAnimation); + if(d->na->duration() == duration) + return; + d->na->setDuration(duration); + emit durationChanged(duration); +} + +/*! + \qmlproperty real NumericAnimation::from + This property holds the starting value. + If not set, then the value defined in the start state of the transition. +*/ +/*! + \property QmlNumericAnimation::from + \brief the starting value. +*/ +qreal QmlNumericAnimation::from() const +{ + Q_D(const QmlNumericAnimation); + return d->from; +} + +void QmlNumericAnimation::setFrom(qreal f) +{ + Q_D(QmlNumericAnimation); + if(!d->from.isNull && f == d->from) + return; + d->from = f; + emit fromChanged(f); +} + +/*! + \qmlproperty real NumericAnimation::to + This property holds the ending value. + If not set, then the value defined in the end state of the transition. +*/ +/*! + \property QmlNumericAnimation::to + \brief the ending value. +*/ +qreal QmlNumericAnimation::to() const +{ + Q_D(const QmlNumericAnimation); + return d->to; +} + +void QmlNumericAnimation::setTo(qreal t) +{ + Q_D(QmlNumericAnimation); + if(!d->to.isNull && t == d->to) + return; + d->to = t; + emit toChanged(t); +} + +/* XML docs in GfxEasing */ +/*! + \property QmlNumericAnimation::easing + This property holds the easing curve to use. + + \sa QEasingCurve +*/ +QString QmlNumericAnimation::easing() const +{ + Q_D(const QmlNumericAnimation); + return d->easing; +} + +void QmlNumericAnimation::setEasing(const QString &e) +{ + Q_D(QmlNumericAnimation); + if(d->easing == e) + return; + + d->easing = e; + d->na->setEasingCurve(stringToCurve(d->easing)); + emit easingChanged(e); +} + +/*! + \qmlproperty string NumericAnimation::properties + This property holds the properties this animation should be applied to. + + This is a comma-separated list of properties that should use + this animation when they change. +*/ +/*! + \property QmlNumericAnimation::properties + \brief the properties this animation should be applied to. + + properties holds a comma-separated list of properties that should use + this animation when they change. +*/ +QString QmlNumericAnimation::properties() const +{ + Q_D(const QmlNumericAnimation); + return d->properties; +} + +void QmlNumericAnimation::setProperties(const QString &prop) +{ + Q_D(QmlNumericAnimation); + if(d->properties == prop) + return; + + d->properties = prop; + emit propertiesChanged(prop); +} + +/*! + \qmlproperty list<Item> NumericAnimation::filter + This property holds the items selected to be affected by this animation (all if not set). + \sa exclude +*/ +QList<QObject *> *QmlNumericAnimation::filter() +{ + Q_D(QmlNumericAnimation); + return &d->filter; +} + +/*! + \qmlproperty list<Item> NumericAnimation::exclude + This property holds the items not to be affected by this animation. + \sa filter +*/ +QList<QObject *> *QmlNumericAnimation::exclude() +{ + Q_D(QmlNumericAnimation); + return &d->exclude; +} + +void QmlNumericAnimationPrivate::valueChanged(qreal r) +{ + if(!fromSourced) { + if(from.isNull) { + fromValue = qvariant_cast<qreal>(property.read()); + } else { + fromValue = from; + } + fromSourced = true; + } + + if(r == 1.) { + property.write(to.value); + } else { + qreal val = fromValue + (to-fromValue) * r; + property.write(val); + } +} + +void QmlNumericAnimation::prepare(QmlMetaProperty &p) +{ + Q_D(QmlNumericAnimation); + if(d->userProperty.isNull) + d->property = p; + else + d->property = d->userProperty; + d->fromSourced = false; + d->value.GfxValue::setValue(0.); + d->na->setAnimValue(&d->value, QAbstractAnimation::KeepWhenStopped); +} + +QAbstractAnimation *QmlNumericAnimation::qtAnimation() +{ + Q_D(QmlNumericAnimation); + return d->na; +} + +void QmlNumericAnimation::transition(QmlStateActions &actions, + QmlMetaProperties &modified, + TransitionDirection direction) +{ + Q_D(QmlNumericAnimation); + Q_UNUSED(direction); + + struct NTransitionData : public GfxValue + { + QmlStateActions actions; + void setValue(qreal v) + { + GfxValue::setValue(v); + for(int ii = 0; ii < actions.count(); ++ii) { + Action &action = actions[ii]; + + QmlBehaviour::_ignore = true; + if(v == 1.) + action.property.write(action.toValue.toDouble()); + else { + if(action.fromValue.isNull()) { + action.fromValue = action.property.read(); + if(action.fromValue.isNull()) { + action.fromValue = QVariant(0.); + } + } + qreal start = action.fromValue.toDouble(); + qreal end = action.toValue.toDouble(); + qreal val = start + (end-start) * v; + action.property.write(val); + } + QmlBehaviour::_ignore = false; + } + } + }; + + QStringList props = d->properties.split(QLatin1Char(',')); + for(int ii = 0; ii < props.count(); ++ii) + props[ii] = props.at(ii).trimmed(); + if(!d->propertyName.isEmpty() && !props.contains(d->propertyName)) + props.append(d->propertyName); + + NTransitionData *data = new NTransitionData; + + QSet<QObject *> objs; + for(int ii = 0; ii < actions.count(); ++ii) { + Action &action = actions[ii]; + + QObject *obj = action.property.object(); + QString propertyName = action.property.name(); + + if((d->filter.isEmpty() || d->filter.contains(obj)) && + (!d->exclude.contains(obj)) && props.contains(propertyName) && + (!target() || target() == obj)) { + objs.insert(obj); + Action myAction = action; + if(d->from.isValid()) { + myAction.fromValue = QVariant(d->from); + } else { + myAction.fromValue = QVariant(); + } + if(d->to.isValid()) + myAction.toValue = QVariant(d->to); + + modified << action.property; + + data->actions << myAction; + action.fromValue = myAction.toValue; + } + } + + if(d->to.isValid() && target() && !objs.contains(target())) { + QObject *obj = target(); + for(int jj = 0; jj < props.count(); ++jj) { + Action myAction; + myAction.property = QmlMetaProperty(obj, props.at(jj)); + + if(d->from.isValid()) + myAction.fromValue = QVariant(d->from); + + myAction.toValue = QVariant(d->to); + myAction.bv = 0; + myAction.event = 0; + data->actions << myAction; + } + } + + if(data->actions.count()) { + d->na->setAnimValue(data, QAbstractAnimation::DeleteWhenStopped); + } else { + delete data; + } +} + +QML_DEFINE_TYPE(QmlNumericAnimation,NumericAnimation); + +QmlAnimationGroup::QmlAnimationGroup(QObject *parent) +: QmlAbstractAnimation(*(new QmlAnimationGroupPrivate), parent) +{ +} + +QmlAnimationGroup::~QmlAnimationGroup() +{ +} + +QmlList<QmlAbstractAnimation *> *QmlAnimationGroup::animations() +{ + Q_D(QmlAnimationGroup); + return &d->animations; +} + +/*! + \qmlclass SequentialAnimation QmlSequentialAnimation + \inherits Animation + \brief The SequentialAnimation allows you to run animations sequentially. + + Animations controlled in SequentialAnimation will be run one after the other. + + The following example chains two numeric animations together. The \c MyItem + object will animate from its current x position to 100, and then back to 0. + + \code + <SequentialAnimation> + <NumericAnimation target="{MyItem}" property="x" to="100" /> + <NumericAnimation target="{MyItem}" property="x" to="0" /> + <SequentialAnimation> + \endcode + + \sa ParallelAnimation +*/ + +QmlSequentialAnimation::QmlSequentialAnimation(QObject *parent) : + QmlAnimationGroup(parent) +{ + Q_D(QmlAnimationGroup); + d->ag = new QSequentialAnimationGroup(this); +} + +QmlSequentialAnimation::~QmlSequentialAnimation() +{ +} + +void QmlSequentialAnimation::prepare(QmlMetaProperty &p) +{ + Q_D(QmlAnimationGroup); + if(d->userProperty.isNull) + d->property = p; + else + d->property = d->userProperty; + + for (int i = 0; i < d->animations.size(); ++i) + d->animations.at(i)->prepare(d->property); +} + +QAbstractAnimation *QmlSequentialAnimation::qtAnimation() +{ + Q_D(QmlAnimationGroup); + return d->ag; +} + +void QmlSequentialAnimation::transition(QmlStateActions &actions, + QmlMetaProperties &modified, + TransitionDirection direction) +{ + Q_D(QmlAnimationGroup); + + int inc = 1; + int from = 0; + if(direction == Backward) { + inc = -1; + from = d->animations.count() - 1; + } + + //XXX removing and readding isn't ideal; we do it to get around the problem mentioned below. + for (int i = d->ag->animationCount()-1; i >= 0; --i) + d->ag->takeAnimationAt(i); + + for(int ii = from; ii < d->animations.count() && ii >= 0; ii += inc) { + d->animations.at(ii)->transition(actions, modified, direction); + d->ag->addAnimation(d->animations.at(ii)->qtAnimation()); + } + + //XXX changing direction means all the animations play in reverse, while we only want the ordering reversed. + //d->ag->setDirection(direction == Backward ? QAbstractAnimation::Backward : QAbstractAnimation::Forward); +} + +QML_DEFINE_TYPE(QmlSequentialAnimation,SequentialAnimation); + +/*! + \qmlclass ParallelAnimation QmlParallelAnimation + \inherits Animation + \brief The ParallelAnimation allows you to run animations in parallel. + + Animations contained in ParallelAnimation will be run at the same time. + + The following animation demonstrates animating the \c MyItem item + to (100,100) by animating the x and y properties in parallel. + + \code + <ParallelAnimation> + <NumericAnimation target="{MyItem}" property="x" to="100" /> + <NumericAnimation target="{MyItem}" property="y" to="100" /> + </ParallelAnimation> + \endcode + + \sa SequentialAnimation +*/ +/*! + \internal + \class QmlParallelAnimation + \ingroup animation states + \brief The QmlParallelAnimation class allows you to run animations in parallel. + + Animations controlled by QmlParallelAnimation will be run at the same time. + + \sa QmlSequentialAnimation + + A QmlParallelAnimation object can be instantiated in Qml using the tag + \ref xmlParallelAnimation "<ParallelAnimation>". +*/ + +QmlParallelAnimation::QmlParallelAnimation(QObject *parent) : + QmlAnimationGroup(parent) +{ + Q_D(QmlAnimationGroup); + d->ag = new QParallelAnimationGroup(this); +} + +QmlParallelAnimation::~QmlParallelAnimation() +{ +} + +void QmlParallelAnimation::prepare(QmlMetaProperty &p) +{ + Q_D(QmlAnimationGroup); + if(d->userProperty.isNull) + d->property = p; + else + d->property = d->userProperty; + + for (int i = 0; i < d->animations.size(); ++i) + d->animations.at(i)->prepare(d->property); +} + +QAbstractAnimation *QmlParallelAnimation::qtAnimation() +{ + Q_D(QmlAnimationGroup); + return d->ag; +} + +void QmlParallelAnimation::transition(QmlStateActions &actions, + QmlMetaProperties &modified, + TransitionDirection direction) +{ + Q_D(QmlAnimationGroup); + + for(int ii = 0; ii < d->animations.count(); ++ii) { + d->animations.at(ii)->transition(actions, modified, direction); + } +} + +QML_DEFINE_TYPE(QmlParallelAnimation,ParallelAnimation); + +//XXX it would be good to use QVariantAnimation's interpolators if possible +QVariant QmlVariantAnimationPrivate::interpolateVariant(const QVariant &from, const QVariant &to, qreal progress) +{ + if (from.userType() != to.userType()) + return QVariant(); + + QVariant res; + switch (from.userType()) { + case QVariant::Int: { + int f = from.toInt(); + int t = to.toInt(); + res = f + (t - f) * progress; + break; + } + case QVariant::Double: { + double f = from.toDouble(); + double t = to.toDouble(); + res = f + (t - f) * progress; + break; + } + case QMetaType::Float: { + float f = from.toDouble(); + float t = to.toDouble(); + res = f + (t - f) * progress; + break; + } + case QVariant::Color: { + QColor f = from.value<QColor>(); + QColor t = to.value<QColor>(); + uint red = uint(qreal(f.red()) + progress * (qreal(t.red()) - qreal(f.red()))); + uint green = uint(qreal(f.green()) + progress * (qreal(t.green()) - qreal(f.green()))); + uint blue = uint(qreal(f.blue()) + progress * (qreal(t.blue()) - qreal(f.blue()))); + res = QColor(red,green,blue); + break; + } + case QVariant::Rect: { + QRect f = from.value<QRect>(); + QRect t = to.value<QRect>(); + int x = f.x() + (t.x() - f.x()) * progress; + int y = f.y() + (t.y() - f.y()) * progress; + int w = f.width() + (t.width() - f.width()) * progress; + int h = f.height() + (t.height() - f.height()) * progress; + res = QRect(x, y, w, h); + break; + } + case QVariant::RectF: { + QRectF f = from.value<QRectF>(); + QRectF t = to.value<QRectF>(); + qreal x = f.x() + (t.x() - f.x()) * progress; + qreal y = f.y() + (t.y() - f.y()) * progress; + qreal w = f.width() + (t.width() - f.width()) * progress; + qreal h = f.height() + (t.height() - f.height()) * progress; + res = QRectF(x, y, w, h); + break; + } + case QVariant::Point: { + QPoint f = from.value<QPoint>(); + QPoint t = to.value<QPoint>(); + int x = f.x() + (t.x() - f.x()) * progress; + int y = f.y() + (t.y() - f.y()) * progress; + res = QPointF(x, y); + break; + } + case QVariant::PointF: { + QPointF f = from.value<QPointF>(); + QPointF t = to.value<QPointF>(); + qreal x = f.x() + (t.x() - f.x()) * progress; + qreal y = f.y() + (t.y() - f.y()) * progress; + res = QPointF(x, y); + break; + } + case QVariant::Size: { + QSize f = from.value<QSize>(); + QSize t = to.value<QSize>(); + int w = f.width() + (t.width() - f.width()) * progress; + int h = f.height() + (t.height() - f.height()) * progress; + res = QSize(w, h); + break; + } + case QVariant::SizeF: { + QSizeF f = from.value<QSizeF>(); + QSizeF t = to.value<QSizeF>(); + qreal w = f.width() + (t.width() - f.width()) * progress; + qreal h = f.height() + (t.height() - f.height()) * progress; + res = QSizeF(w, h); + break; + } + default: + res = to; + break; + } + + return res; +} + +//convert a variant from string type to another animatable type +void QmlVariantAnimationPrivate::convertVariant(QVariant &variant, QVariant::Type type) +{ + if (variant.type() != QVariant::String) { + variant.convert(type); + return; + } + + switch (type) { + case QVariant::Rect: { + variant.setValue(QmlStringConverters::rectFFromString(variant.toString()).toRect()); + break; + } + case QVariant::RectF: { + variant.setValue(QmlStringConverters::rectFFromString(variant.toString())); + break; + } + case QVariant::Point: { + variant.setValue(QmlStringConverters::pointFFromString(variant.toString()).toPoint()); + break; + } + case QVariant::PointF: { + variant.setValue(QmlStringConverters::pointFFromString(variant.toString())); + break; + } + case QVariant::Size: { + variant.setValue(QmlStringConverters::sizeFFromString(variant.toString()).toSize()); + break; + } + case QVariant::SizeF: { + variant.setValue(QmlStringConverters::sizeFFromString(variant.toString())); + break; + } + case QVariant::Color: { + variant.setValue(QmlStringConverters::colorFromString(variant.toString())); + break; + } + default: + variant.convert(type); + break; + } +} + +/*! + \qmlclass VariantAnimation QmlVariantAnimation + \inherits Animation + \brief The VariantAnimation allows you to animate changes in properties of type QVariant. + + Animate a size property over 200ms, from its current size to 20-by-20: + \code + <VariantAnimation property="size" to="20x20" duration="200"/> + \endcode +*/ + +QmlVariantAnimation::QmlVariantAnimation(QObject *parent) +: QmlAbstractAnimation(*(new QmlVariantAnimationPrivate), parent) +{ + Q_D(QmlVariantAnimation); + d->init(); +} + +QmlVariantAnimation::~QmlVariantAnimation() +{ +} + +void QmlVariantAnimationPrivate::init() +{ + Q_Q(QmlVariantAnimation); + va = new GfxValueAnimator(q); + va->setStartValue(QVariant(0.0f)); + va->setEndValue(QVariant(1.0f)); +} + +/*! + \qmlproperty int VariantAnimation::duration + This property holds the duration of the transition, in milliseconds. + + The default value is 250. +*/ +/*! + \property QmlVariantAnimation::duration + \brief the duration of the transition, in milliseconds. + + The default value is 250. +*/ +int QmlVariantAnimation::duration() const +{ + Q_D(const QmlVariantAnimation); + return d->va->duration(); +} + +void QmlVariantAnimation::setDuration(int duration) +{ + if(duration < 0) { + qWarning("QmlVariantAnimation: Cannot set a duration of < 0"); + return; + } + + Q_D(QmlVariantAnimation); + if(d->va->duration() == duration) + return; + d->va->setDuration(duration); + emit durationChanged(duration); +} + +/*! + \qmlproperty real VariantAnimation::from + This property holds the starting value. + If not set, then the value defined in the start state of the transition. +*/ +/*! + \property QmlVariantAnimation::from + \brief the starting value. +*/ +QVariant QmlVariantAnimation::from() const +{ + Q_D(const QmlVariantAnimation); + return d->from; +} + +void QmlVariantAnimation::setFrom(const QVariant &f) +{ + Q_D(QmlVariantAnimation); + if(!d->from.isNull && f == d->from) + return; + d->from = f; + emit fromChanged(f); +} + +/*! + \qmlproperty real VariantAnimation::to + This property holds the ending value. + If not set, then the value defined in the end state of the transition. +*/ +/*! + \property QmlVariantAnimation::to + \brief the ending value. +*/ +QVariant QmlVariantAnimation::to() const +{ + Q_D(const QmlVariantAnimation); + return d->to; +} + +void QmlVariantAnimation::setTo(const QVariant &t) +{ + Q_D(QmlVariantAnimation); + if(!d->to.isNull && t == d->to) + return; + d->to = t; + emit toChanged(t); +} + +/*! + \qmlproperty string VariantAnimation::easing + This property holds the easing curve used for the transition. + + See NumericAnimation::easing for a full discussion of easing, + and a list of available curves. +*/ + +/*! + \property QmlVariantAnimation::easing + \brief the easing curve to use. + + \sa QEasingCurve +*/ +QString QmlVariantAnimation::easing() const +{ + Q_D(const QmlVariantAnimation); + return d->easing; +} + +void QmlVariantAnimation::setEasing(const QString &e) +{ + Q_D(QmlVariantAnimation); + if(d->easing == e) + return; + + d->easing = e; + d->va->setEasingCurve(stringToCurve(d->easing)); + emit easingChanged(e); +} + +/*! + \qmlproperty string VariantAnimation::properties + This property holds the properties this animation should be applied to. + + This is a comma-separated list of properties that should use + this animation when they change. +*/ +/*! + \property QmlVariantAnimation::properties + \brief the properties this animation should be applied to + + properties holds a copy separated list of properties that should use + this animation when they change. +*/ +QString QmlVariantAnimation::properties() const +{ + Q_D(const QmlVariantAnimation); + return d->properties; +} + +void QmlVariantAnimation::setProperties(const QString &prop) +{ + Q_D(QmlVariantAnimation); + if(d->properties == prop) + return; + + d->properties = prop; + emit propertiesChanged(prop); +} + +/*! + \qmlproperty list<Item> VariantAnimation::filter + This property holds the items selected to be affected by this animation (all if not set). + \sa exclude +*/ +QList<QObject *> *QmlVariantAnimation::filter() +{ + Q_D(QmlVariantAnimation); + return &d->filter; +} + +/*! + \qmlproperty list<Item> VariantAnimation::exclude + This property holds the items not to be affected by this animation. + \sa filter +*/ +QList<QObject *> *QmlVariantAnimation::exclude() +{ + Q_D(QmlVariantAnimation); + return &d->exclude; +} + +void QmlVariantAnimationPrivate::valueChanged(qreal r) +{ + if(!fromSourced) { + if(from.isNull) { + fromValue = property.read(); + } else { + fromValue = from; + } + fromSourced = true; + } + + if(r == 1.) { + property.write(to.value); + } else { + QVariant val = interpolateVariant(fromValue, to.value, r); + property.write(val); + } +} + +QAbstractAnimation *QmlVariantAnimation::qtAnimation() +{ + Q_D(QmlVariantAnimation); + return d->va; +} + +void QmlVariantAnimation::prepare(QmlMetaProperty &p) +{ + Q_D(QmlVariantAnimation); + if(d->userProperty.isNull) + d->property = p; + else + d->property = d->userProperty; + + d->convertVariant(d->to.value, (QVariant::Type)d->property.propertyType()); + if (!d->from.isNull) + d->convertVariant(d->from.value, (QVariant::Type)d->property.propertyType()); + + d->fromSourced = false; + d->value.GfxValue::setValue(0.); + d->va->setAnimValue(&d->value, QAbstractAnimation::KeepWhenStopped); +} + +void QmlVariantAnimation::transition(QmlStateActions &actions, + QmlMetaProperties &modified, + TransitionDirection direction) +{ + Q_D(QmlVariantAnimation); + Q_UNUSED(direction); + + struct NTransitionData : public GfxValue + { + QmlStateActions actions; + void setValue(qreal v) + { + GfxValue::setValue(v); + for(int ii = 0; ii < actions.count(); ++ii) { + Action &action = actions[ii]; + + if(v == 1.) + action.property.write(action.toValue); + else { + if(action.fromValue.isNull()) { + action.fromValue = action.property.read(); + /*if(action.fromValue.isNull()) + action.fromValue = QVariant(0.);*/ //XXX can we give a default value for any type? + } + QVariant val = QmlVariantAnimationPrivate::interpolateVariant(action.fromValue, action.toValue, v); + action.property.write(val); + } + } + } + }; + + QStringList props = d->properties.split(QLatin1Char(',')); + for(int ii = 0; ii < props.count(); ++ii) + props[ii] = props.at(ii).trimmed(); + if(!d->propertyName.isEmpty() && !props.contains(d->propertyName)) + props.append(d->propertyName); + + NTransitionData *data = new NTransitionData; + + QSet<QObject *> objs; + for(int ii = 0; ii < actions.count(); ++ii) { + Action &action = actions[ii]; + + QObject *obj = action.property.object(); + QString propertyName = action.property.name(); + + if((d->filter.isEmpty() || d->filter.contains(obj)) && + (!d->exclude.contains(obj)) && props.contains(propertyName) && + (!target() || target() == obj)) { + objs.insert(obj); + Action myAction = action; + + if(d->from.isValid()) + myAction.fromValue = QVariant(d->from); + if(d->to.isValid()) + myAction.toValue = QVariant(d->to); + + d->convertVariant(myAction.fromValue, (QVariant::Type)myAction.property.propertyType()); + d->convertVariant(myAction.toValue, (QVariant::Type)myAction.property.propertyType()); + + modified << action.property; + + data->actions << myAction; + action.fromValue = myAction.toValue; + } + } + + if(d->to.isValid() && target() && !objs.contains(target())) { + QObject *obj = target(); + for(int jj = 0; jj < props.count(); ++jj) { + Action myAction; + myAction.property = QmlMetaProperty(obj, props.at(jj)); + + if(d->from.isValid()) { + d->convertVariant(d->from.value, (QVariant::Type)myAction.property.propertyType()); + myAction.fromValue = QVariant(d->from); + } + + d->convertVariant(d->to.value, (QVariant::Type)myAction.property.propertyType()); + myAction.toValue = QVariant(d->to); + myAction.bv = 0; + myAction.event = 0; + data->actions << myAction; + } + } + + if(data->actions.count()) { + d->va->setAnimValue(data, QAbstractAnimation::DeleteWhenStopped); + } else { + delete data; + } +} + +//XXX whats the best name for this? (just Animation?) +QML_DEFINE_TYPE(QmlVariantAnimation,VariantAnimation); + + +QT_END_NAMESPACE diff --git a/src/declarative/util/qmlanimation.h b/src/declarative/util/qmlanimation.h new file mode 100644 index 0000000..578631c --- /dev/null +++ b/src/declarative/util/qmlanimation.h @@ -0,0 +1,453 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMLANIMATION_H +#define QMLANIMATION_H + +#include <QtCore/qvariant.h> +#include <QtGui/qcolor.h> +#include <qmltransition.h> +#include <qmlpropertyvaluesource.h> +#include <qmlstate.h> +#include <qml.h> +#include <QAbstractAnimation> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Declarative) + +class QmlAbstractAnimationPrivate; +class QmlAnimationGroup; +class QmlAbstractAnimation : public QmlPropertyValueSource, public QmlParserStatus +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QmlAbstractAnimation) + + Q_INTERFACES(QmlParserStatus); + Q_PROPERTY(bool running READ isRunning WRITE setRunning NOTIFY runningChanged); + Q_PROPERTY(bool finishPlaying READ finishPlaying WRITE setFinishPlaying NOTIFY finishPlayingChanged()); + Q_PROPERTY(bool repeat READ repeat WRITE setRepeat NOTIFY repeatChanged); + Q_PROPERTY(QObject *target READ target WRITE setTarget NOTIFY targetChanged); + Q_PROPERTY(QString property READ property WRITE setProperty NOTIFY targetChanged); + Q_CLASSINFO("DefaultMethod", "start()"); + Q_INTERFACES(QmlParserStatus) + +public: + QmlAbstractAnimation(QObject *parent=0); + virtual ~QmlAbstractAnimation(); + + bool isRunning() const; + void setRunning(bool); + bool finishPlaying() const; + void setFinishPlaying(bool); + bool repeat() const; + void setRepeat(bool); + + QmlAnimationGroup *group() const; + void setGroup(QmlAnimationGroup *); + + QObject *target() const; + void setTarget(QObject *); + QString property() const; + void setProperty(const QString &); + + void classBegin(); + void componentComplete(); + +Q_SIGNALS: + void started(); + void completed(); + void runningChanged(bool); + void repeatChanged(bool); + void targetChanged(QObject *, const QString &); + void finishPlayingChanged(bool); + +public Q_SLOTS: + void restart(); + void start(); + void stop(); + void complete(); + +protected: + virtual void setTarget(const QmlMetaProperty &); + QmlAbstractAnimation(QmlAbstractAnimationPrivate &dd, QObject *parent); + +public: + enum TransitionDirection { Forward, Backward }; + virtual void transition(QmlStateActions &actions, + QmlMetaProperties &modified, + TransitionDirection direction); + virtual void prepare(QmlMetaProperty &); + virtual QAbstractAnimation *qtAnimation() = 0; + +private Q_SLOTS: + void timelineComplete(); +}; + +QML_DECLARE_TYPE(QmlAbstractAnimation); + +class QmlPauseAnimationPrivate; +class QmlPauseAnimation : public QmlAbstractAnimation +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QmlPauseAnimation); + + Q_PROPERTY(int duration READ duration WRITE setDuration NOTIFY durationChanged); + +public: + QmlPauseAnimation(QObject *parent=0); + virtual ~QmlPauseAnimation(); + + int duration() const; + void setDuration(int); + +Q_SIGNALS: + void durationChanged(int); + +protected: + virtual QAbstractAnimation *qtAnimation(); + virtual void prepare(QmlMetaProperty &); +}; +QML_DECLARE_TYPE(QmlPauseAnimation); + +class QmlColorAnimationPrivate; +class QmlColorAnimation : public QmlAbstractAnimation +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QmlColorAnimation); + Q_PROPERTY(int duration READ duration WRITE setDuration NOTIFY durationChanged); + Q_PROPERTY(QColor from READ from WRITE setFrom NOTIFY fromChanged); + Q_PROPERTY(QColor to READ to WRITE setTo NOTIFY toChanged); + Q_PROPERTY(QString easing READ easing WRITE setEasing NOTIFY easingChanged); + Q_PROPERTY(QList<QObject *>* filter READ filter); + Q_PROPERTY(QList<QObject *>* exclude READ exclude); + +public: + QmlColorAnimation(QObject *parent=0); + virtual ~QmlColorAnimation(); + + int duration() const; + void setDuration(int); + + QColor from() const; + void setFrom(const QColor &); + + QColor to() const; + void setTo(const QColor &); + + QString easing() const; + void setEasing(const QString &); + + QList<QObject *> *filter(); + + QList<QObject *> *exclude(); + +protected: + virtual void transition(QmlStateActions &actions, + QmlMetaProperties &modified, + TransitionDirection direction); + virtual QAbstractAnimation *qtAnimation(); + virtual void prepare(QmlMetaProperty &); + +Q_SIGNALS: + void durationChanged(int); + void fromChanged(const QColor &); + void toChanged(const QColor &); + void easingChanged(const QString &); +}; +QML_DECLARE_TYPE(QmlColorAnimation); + +class QmlRunScriptActionPrivate; +class QmlRunScriptAction : public QmlAbstractAnimation +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QmlRunScriptAction); + + Q_PROPERTY(QString script READ script WRITE setScript NOTIFY scriptChanged); + Q_PROPERTY(QString file READ file WRITE setFile NOTIFY fileChanged); + +public: + QmlRunScriptAction(QObject *parent=0); + virtual ~QmlRunScriptAction(); + + QString script() const; + void setScript(const QString &); + + QString file() const; + void setFile(const QString &); + +Q_SIGNALS: + void fileChanged(const QString &); + void scriptChanged(const QString &); + +protected: + virtual QAbstractAnimation *qtAnimation(); +}; +QML_DECLARE_TYPE(QmlRunScriptAction); + +class QmlSetPropertyActionPrivate; +class QmlSetPropertyAction : public QmlAbstractAnimation +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QmlSetPropertyAction); + + Q_PROPERTY(QString properties READ properties WRITE setProperties NOTIFY propertiesChanged); + Q_PROPERTY(QList<QObject *>* filter READ filter); + Q_PROPERTY(QList<QObject *>* exclude READ exclude); + Q_PROPERTY(QVariant value READ value WRITE setValue NOTIFY valueChanged); + +public: + QmlSetPropertyAction(QObject *parent=0); + virtual ~QmlSetPropertyAction(); + + QString properties() const; + void setProperties(const QString &); + + QList<QObject *> *filter(); + QList<QObject *> *exclude(); + + QVariant value() const; + void setValue(const QVariant &); + +Q_SIGNALS: + void valueChanged(const QVariant &); + void propertiesChanged(const QString &); + +protected: + virtual void transition(QmlStateActions &actions, + QmlMetaProperties &modified, + TransitionDirection direction); + virtual QAbstractAnimation *qtAnimation(); + virtual void prepare(QmlMetaProperty &); +}; +QML_DECLARE_TYPE(QmlSetPropertyAction); + +class QmlParentChangeActionPrivate; +class QmlParentChangeAction : public QmlAbstractAnimation +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QmlParentChangeAction); + + //XXX should have parent property as well for when it isn't part of a transition + +public: + QmlParentChangeAction(QObject *parent=0); + virtual ~QmlParentChangeAction(); + +protected: + virtual void transition(QmlStateActions &actions, + QmlMetaProperties &modified, + TransitionDirection direction); + virtual QAbstractAnimation *qtAnimation(); + virtual void prepare(QmlMetaProperty &); +}; +QML_DECLARE_TYPE(QmlParentChangeAction); + +class QmlNumericAnimationPrivate; +class QmlNumericAnimation : public QmlAbstractAnimation +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QmlNumericAnimation); + + Q_PROPERTY(int duration READ duration WRITE setDuration NOTIFY durationChanged); + Q_PROPERTY(qreal from READ from WRITE setFrom NOTIFY fromChanged); + Q_PROPERTY(qreal to READ to WRITE setTo NOTIFY toChanged); + Q_PROPERTY(QString easing READ easing WRITE setEasing NOTIFY easingChanged); + Q_PROPERTY(QString properties READ properties WRITE setProperties NOTIFY propertiesChanged); + Q_PROPERTY(QList<QObject *>* filter READ filter); + Q_PROPERTY(QList<QObject *>* exclude READ exclude); + +public: + QmlNumericAnimation(QObject *parent=0); + virtual ~QmlNumericAnimation(); + + int duration() const; + void setDuration(int); + + qreal from() const; + void setFrom(qreal); + + qreal to() const; + void setTo(qreal); + + QString easing() const; + void setEasing(const QString &); + + QString properties() const; + void setProperties(const QString &); + + QList<QObject *> *filter(); + QList<QObject *> *exclude(); + +protected: + virtual void transition(QmlStateActions &actions, + QmlMetaProperties &modified, + TransitionDirection direction); + virtual QAbstractAnimation *qtAnimation(); + virtual void prepare(QmlMetaProperty &); + +Q_SIGNALS: + void durationChanged(int); + void fromChanged(qreal); + void toChanged(qreal); + void easingChanged(const QString &); + void propertiesChanged(const QString &); +}; +QML_DECLARE_TYPE(QmlNumericAnimation); + +#if 0 +class QmlDiscreteAnimation : public QmlAbstractAnimation +{ +Q_OBJECT +}; +#endif + +class QmlAnimationGroupPrivate; +class QmlAnimationGroup : public QmlAbstractAnimation +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QmlAnimationGroup); + + Q_CLASSINFO("DefaultProperty", "animations"); + Q_PROPERTY(QmlList<QmlAbstractAnimation *> *animations READ animations); + +public: + QmlAnimationGroup(QObject *parent); + virtual ~QmlAnimationGroup(); + + QmlList<QmlAbstractAnimation *>* animations(); +}; + +class QmlSequentialAnimation : public QmlAnimationGroup +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QmlAnimationGroup); + +public: + QmlSequentialAnimation(QObject *parent=0); + virtual ~QmlSequentialAnimation(); + +protected: + virtual void transition(QmlStateActions &actions, + QmlMetaProperties &modified, + TransitionDirection direction); + virtual QAbstractAnimation *qtAnimation(); + virtual void prepare(QmlMetaProperty &); +}; +QML_DECLARE_TYPE(QmlSequentialAnimation); + +class QmlParallelAnimation : public QmlAnimationGroup +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QmlAnimationGroup); + +public: + QmlParallelAnimation(QObject *parent=0); + virtual ~QmlParallelAnimation(); + +protected: + virtual void transition(QmlStateActions &actions, + QmlMetaProperties &modified, + TransitionDirection direction); + virtual QAbstractAnimation *qtAnimation(); + virtual void prepare(QmlMetaProperty &); +}; +QML_DECLARE_TYPE(QmlParallelAnimation); + +class QmlVariantAnimationPrivate; +class QmlVariantAnimation : public QmlAbstractAnimation +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QmlVariantAnimation); + + Q_PROPERTY(int duration READ duration WRITE setDuration NOTIFY durationChanged); + Q_PROPERTY(QVariant from READ from WRITE setFrom NOTIFY fromChanged); + Q_PROPERTY(QVariant to READ to WRITE setTo NOTIFY toChanged); + Q_PROPERTY(QString easing READ easing WRITE setEasing NOTIFY easingChanged); + Q_PROPERTY(QString properties READ properties WRITE setProperties NOTIFY propertiesChanged); + Q_PROPERTY(QList<QObject *>* filter READ filter); + Q_PROPERTY(QList<QObject *>* exclude READ exclude); + +public: + QmlVariantAnimation(QObject *parent=0); + virtual ~QmlVariantAnimation(); + + int duration() const; + void setDuration(int); + + QVariant from() const; + void setFrom(const QVariant &); + + QVariant to() const; + void setTo(const QVariant &); + + QString easing() const; + void setEasing(const QString &); + + QString properties() const; + void setProperties(const QString &); + + QList<QObject *> *filter(); + QList<QObject *> *exclude(); + +protected: + virtual void transition(QmlStateActions &actions, + QmlMetaProperties &modified, + TransitionDirection direction); + virtual QAbstractAnimation *qtAnimation(); + virtual void prepare(QmlMetaProperty &); + +Q_SIGNALS: + void durationChanged(int); + void fromChanged(QVariant); + void toChanged(QVariant); + void easingChanged(const QString &); + void propertiesChanged(const QString &); +}; +QML_DECLARE_TYPE(QmlVariantAnimation); + +#endif // QMLANIMATION_H + +QT_END_NAMESPACE + +QT_END_HEADER diff --git a/src/declarative/util/qmlanimation_p.h b/src/declarative/util/qmlanimation_p.h new file mode 100644 index 0000000..db7cb18 --- /dev/null +++ b/src/declarative/util/qmlanimation_p.h @@ -0,0 +1,374 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMLANIMATION_P_H +#define QMLANIMATION_P_H + +#include <private/qobject_p.h> +#include <private/qmlnullablevalue_p.h> +#include <qmlanimation.h> +#include <qml.h> +#include <qmlcontext.h> +#include <private/qvariantanimation_p.h> +#include <QPauseAnimation> +#include <QVariantAnimation> +#include <QAnimationGroup> +#include <QColor> +#include <gfxvalueproxy.h> + +QT_BEGIN_NAMESPACE + +//interface for classes that provide animation actions for QActionAnimation +class QAbstractAnimationAction +{ +public: + virtual ~QAbstractAnimationAction() {} + virtual void doAction() = 0; +}; + +//templated animation action +//allows us to specify an action that calls a function of a class. +//(so that class doesn't have to inherit QmlAbstractAnimationAction) +template<class T, void (T::*method)()> +class QAnimationActionProxy : public QAbstractAnimationAction +{ +public: + QAnimationActionProxy(T *p) : m_p(p) {} + virtual void doAction() { (m_p->*method)(); } + +private: + T *m_p; +}; + +//performs an action of type QAbstractAnimationAction +class QActionAnimation : public QAbstractAnimation +{ +public: + QActionAnimation(QObject *parent = 0) : QAbstractAnimation(parent), animAction(0), policy(KeepWhenStopped) {} + QActionAnimation(QAbstractAnimationAction *action, QObject *parent = 0) + : QAbstractAnimation(parent), animAction(action), policy(KeepWhenStopped) {} + virtual int duration() const { return 0; } + void setAnimAction(QAbstractAnimationAction *action, DeletionPolicy p) + { + if (state() == Running) + stop(); + animAction = action; + policy = p; + } +protected: + virtual void updateCurrentTime(int) {} + + virtual void updateState(State /*oldState*/, State newState) + { + if (newState == Running) { + if (animAction) + animAction->doAction(); + } else if (newState == Stopped && policy == DeleteWhenStopped) { + delete animAction; + animAction = 0; + } + } + +private: + QAbstractAnimationAction *animAction; + DeletionPolicy policy; +}; + +//animates GfxValue (assumes start and end values will be reals or compatible) +class GfxValueAnimator : public QVariantAnimation +{ +public: + GfxValueAnimator(QObject *parent = 0) : QVariantAnimation(parent), animValue(0), policy(KeepWhenStopped) {} + GfxValueAnimator(GfxValue *value, QObject *parent = 0) : QVariantAnimation(parent), animValue(value), policy(KeepWhenStopped) {} + void setAnimValue(GfxValue *value, DeletionPolicy p) + { + if (state() == Running) + stop(); + animValue = value; + policy = p; + } +protected: + virtual void updateCurrentValue(const QVariant &value) + { + if (animValue) + animValue->setValue(value.toDouble()); + } + virtual void updateState(State oldState, State newState) + { + QVariantAnimation::updateState(oldState, newState); + if (newState == Stopped && policy == DeleteWhenStopped) { + delete animValue; + animValue = 0; + } + } + +private: + GfxValue *animValue; + DeletionPolicy policy; +}; + +//an animation that just gives a tick +template<class T, void (T::*method)(int)> +class QTickAnimationProxy : public QAbstractAnimation +{ +public: + QTickAnimationProxy(T *p, QObject *parent = 0) : QAbstractAnimation(parent), m_p(p) {} + virtual int duration() const { return -1; } +protected: + virtual void updateCurrentTime(int msec) { (m_p->*method)(msec); } + +private: + T *m_p; +}; + +class QmlAbstractAnimationPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QmlAbstractAnimation); +public: + QmlAbstractAnimationPrivate() + : running(false), finishPlaying(false), repeat(false), + connectedTimeLine(false), componentComplete(true), startOnCompletion(false), + target(0), group(0) {} + + bool running; + bool finishPlaying; + bool repeat; + bool connectedTimeLine; + + bool componentComplete; + bool startOnCompletion; + + void commence(); + + QmlNullableValue<QmlMetaProperty> userProperty; + QObject *target; + QString propertyName; + + QmlMetaProperty property; + QmlAnimationGroup *group; +}; + +class QmlPauseAnimationPrivate : public QmlAbstractAnimationPrivate +{ + Q_DECLARE_PUBLIC(QmlPauseAnimation); +public: + QmlPauseAnimationPrivate() + : QmlAbstractAnimationPrivate(), pa(0) {} + + void init(); + + QPauseAnimation *pa; +}; + +class QmlColorAnimationPrivate : public QmlAbstractAnimationPrivate +{ + Q_DECLARE_PUBLIC(QmlColorAnimation); +public: + QmlColorAnimationPrivate() + : QmlAbstractAnimationPrivate(), fromSourced(false), ca(0), value(this, &QmlColorAnimationPrivate::valueChanged) {} + + void init(); + + QString easing; + + QList<QObject *> filter; + QList<QObject *> exclude; + bool fromSourced; + QColor fromValue; + QColor toValue; + GfxValueAnimator *ca; + virtual void valueChanged(qreal); + + GfxValueProxy<QmlColorAnimationPrivate> value; +}; + +class QmlRunScriptActionPrivate : public QmlAbstractAnimationPrivate +{ + Q_DECLARE_PUBLIC(QmlRunScriptAction); +public: + QmlRunScriptActionPrivate() + : QmlAbstractAnimationPrivate(), ctxt(QmlContext::activeContext()), proxy(this), rsa(0) {} + + void init(); + + QString script; + QString file; + QmlContext* ctxt; + + void execute(); + + QAnimationActionProxy<QmlRunScriptActionPrivate, + &QmlRunScriptActionPrivate::execute> proxy; + QActionAnimation *rsa; +}; + +class QmlSetPropertyActionPrivate : public QmlAbstractAnimationPrivate +{ + Q_DECLARE_PUBLIC(QmlSetPropertyAction); +public: + QmlSetPropertyActionPrivate() + : QmlAbstractAnimationPrivate(), proxy(this), spa(0) {} + + void init(); + + QString properties; + QList<QObject *> filter; + QList<QObject *> exclude; + + QmlNullableValue<QVariant> value; + + void doAction(); + + QAnimationActionProxy<QmlSetPropertyActionPrivate, + &QmlSetPropertyActionPrivate::doAction> proxy; + QActionAnimation *spa; +}; + +class QmlParentChangeActionPrivate : public QmlAbstractAnimationPrivate +{ + Q_DECLARE_PUBLIC(QmlParentChangeAction); +public: + QmlParentChangeActionPrivate() + : QmlAbstractAnimationPrivate() {} + + void init(); + + void doAction(); + QActionAnimation *cpa; +}; + +class QmlNumericAnimationPrivate : public QmlAbstractAnimationPrivate +{ + Q_DECLARE_PUBLIC(QmlNumericAnimation); +public: + QmlNumericAnimationPrivate() + : QmlAbstractAnimationPrivate(), fromSourced(false), na(0), value(this, &QmlNumericAnimationPrivate::valueChanged) {} + + void init(); + + QmlNullableValue<qreal> from; + QmlNullableValue<qreal> to; + + QString easing; + + QString properties; + QList<QObject *> filter; + QList<QObject *> exclude; + + bool fromSourced; + qreal fromValue; + GfxValueAnimator *na; + virtual void valueChanged(qreal); + + GfxValueProxy<QmlNumericAnimationPrivate> value; +}; + +class QmlAnimationGroupPrivate : public QmlAbstractAnimationPrivate +{ + Q_DECLARE_PUBLIC(QmlAnimationGroup); +public: + QmlAnimationGroupPrivate() + : QmlAbstractAnimationPrivate(), animations(this), ag(0) {} + + struct AnimationList : public QmlConcreteList<QmlAbstractAnimation *> + { + AnimationList(QmlAnimationGroupPrivate *p) + : anim(p) {} + virtual void append(QmlAbstractAnimation *a) { + QmlConcreteList<QmlAbstractAnimation *>::append(a); + a->setGroup(anim->q_func()); + } + virtual void clear() + { + for (int i = 0; i < count(); ++i) + at(i)->setGroup(0); + QmlConcreteList<QmlAbstractAnimation *>::clear(); + } + virtual void removeAt(int i) + { + at(i)->setGroup(0); + QmlConcreteList<QmlAbstractAnimation *>::removeAt(i); + } + virtual void insert(int i, QmlAbstractAnimation *a) + { + QmlConcreteList<QmlAbstractAnimation *>::insert(i, a); + a->setGroup(anim->q_func()); + } + + QmlAnimationGroupPrivate *anim; + }; + + AnimationList animations; + QAnimationGroup *ag; +}; + +class QmlVariantAnimationPrivate : public QmlAbstractAnimationPrivate +{ + Q_DECLARE_PUBLIC(QmlVariantAnimation); +public: + QmlVariantAnimationPrivate() + : QmlAbstractAnimationPrivate(), fromSourced(false), va(0), value(this, &QmlVariantAnimationPrivate::valueChanged) {} + + void init(); + + QmlNullableValue<QVariant> from; + QmlNullableValue<QVariant> to; + + QString easing; + + QString properties; + QList<QObject *> filter; + QList<QObject *> exclude; + + bool fromSourced; + QVariant fromValue; + GfxValueAnimator *va; + virtual void valueChanged(qreal); + + GfxValueProxy<QmlVariantAnimationPrivate> value; + + static QVariant interpolateVariant(const QVariant &from, const QVariant &to, qreal progress); + static void convertVariant(QVariant &variant, QVariant::Type type); +}; + +#endif // QMLANIMATION_P_H + +QT_END_NAMESPACE diff --git a/src/declarative/util/qmlbehaviour.cpp b/src/declarative/util/qmlbehaviour.cpp new file mode 100644 index 0000000..3169f63 --- /dev/null +++ b/src/declarative/util/qmlbehaviour.cpp @@ -0,0 +1,248 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <private/qobject_p.h> +#include "qmlanimation.h" +#include "qmltransition.h" +#include "qmlbehaviour.h" +#include <QtDeclarative/qmlcontext.h> + + +QT_BEGIN_NAMESPACE +QML_DEFINE_TYPE(QmlBehaviour,Behaviour); + + +class QmlBehaviourData : public QObject +{ +Q_OBJECT +public: + QmlBehaviourData(QObject *parent) + : QObject(parent) {} + + Q_PROPERTY(QVariant endValue READ endValue NOTIFY valuesChanged); + Q_PROPERTY(QVariant startValue READ startValue NOTIFY valuesChanged); + QVariant endValue() const { return e; } + QVariant startValue() const { return s; } + + QVariant e; + QVariant s; + +Q_SIGNALS: + void valuesChanged(); + +private: + friend class QmlBehaviour; +}; + +class QmlBehaviourPrivate : public QObjectPrivate +{ +public: + QmlBehaviourPrivate() + : context(0), oldContext(0), valueData(0), operations(this) {} + QmlMetaProperty property; + QVariant currentValue; + + QVariant fromValue; + QVariant toValue; + QmlContext *context; + QmlContext *oldContext; + QmlBehaviourData *valueData; + class AnimationList : public QmlConcreteList<QmlAbstractAnimation *> + { + public: + AnimationList(QmlBehaviourPrivate *parent) : _parent(parent) {} + virtual void append(QmlAbstractAnimation *a) + { + QmlConcreteList<QmlAbstractAnimation *>::append(a); + _parent->group->addAnimation(a->qtAnimation()); + } + virtual void clear() { QmlConcreteList<QmlAbstractAnimation *>::clear(); } //### + private: + QmlBehaviourPrivate *_parent; + }; + AnimationList operations; + QSequentialAnimationGroup *group; +}; + +/*! + \qmlclass Behaviour QmlBehaviour + \brief The Behaviour element allows you to specify a default animation for a property change. + + In example below, Rect1 will use a bounce easing curve over 200 millisecond for any changes to its y property: + \code + <Rect id="Rect1" y="200" width="20" height="20" color="#00ff00"> + <y> + <Behaviour> + <NumericAnimation easing="easeOutBounce(amplitude:100)" duration="200" /> + </Behaviour> + </y> + </Rect> + \endcode +*/ + +QmlBehaviour::QmlBehaviour(QObject *parent) +: QmlPropertyValueSource(*(new QmlBehaviourPrivate), parent) +{ + Q_D(QmlBehaviour); + d->valueData = new QmlBehaviourData(this); + d->context = new QmlContext(QmlContext::activeContext(), this); + d->context->addDefaultObject(d->valueData); + d->group = new QSequentialAnimationGroup(this); +} + +/*! + \qmlproperty QVariant Behaviour::fromValue + This property holds a selector specifying a starting value for the behaviour + + If you only want the behaviour to apply when the change starts at a + specific value you can specify fromValue. This selector is used in conjunction + with the toValue selector. +*/ + +QVariant QmlBehaviour::fromValue() const +{ + Q_D(const QmlBehaviour); + return d->fromValue; +} + +void QmlBehaviour::setFromValue(const QVariant &v) +{ + Q_D(QmlBehaviour); + d->fromValue = v; +} + +/*! + \qmlproperty QVariant Behaviour::toValue + This property holds a selector specifying a ending value for the behaviour + + If you only want the behaviour to apply when the change ends at a + specific value you can specify toValue. This selector is used in conjunction + with the fromValue selector. +*/ + +QVariant QmlBehaviour::toValue() const +{ + Q_D(const QmlBehaviour); + return d->toValue; +} + +void QmlBehaviour::setToValue(const QVariant &v) +{ + Q_D(QmlBehaviour); + d->toValue = v; +} + +QmlList<QmlAbstractAnimation *>* QmlBehaviour::operations() +{ + Q_D(QmlBehaviour); + return &d->operations; +} + +QmlBehaviour::~QmlBehaviour() +{ + //### do we need any other cleanup here? +} + +bool QmlBehaviour::_ignore = false; +void QmlBehaviour::propertyValueChanged() +{ + Q_D(QmlBehaviour); + if(_ignore) + return; + + QVariant newValue = d->property.read(); + + if((!fromValue().isValid() || fromValue() == d->currentValue) && + (!toValue().isValid() || toValue() == newValue)) { + + //### does this clean up everything needed? + d->group->stop(); + + d->valueData->e = newValue; + d->valueData->s = d->currentValue; + emit d->valueData->valuesChanged(); + + QmlStateOperation::ActionList actions; + Action action; + action.property = d->property; + action.fromValue = d->currentValue; + action.toValue = newValue; + actions << action; + + _ignore = true; + d->property.write(d->currentValue); + + QList<QmlMetaProperty> after; + for(int ii = 0; ii < d->operations.count(); ++ii) { + d->operations.at(ii)->transition(actions, after, QmlAbstractAnimation::Forward); + } + d->group->start(); + if(!after.contains(d->property)) + d->property.write(newValue); + _ignore = false; + } + + d->currentValue = newValue; +} + +void QmlBehaviour::setTarget(const QmlMetaProperty &property) +{ + Q_D(QmlBehaviour); + d->property = property; + d->currentValue = property.read(); + d->property.connectNotifier(this, SLOT(propertyValueChanged())); +} + +void QmlBehaviour::classBegin() +{ + Q_D(QmlBehaviour); + d->context->activate(); +} + +void QmlBehaviour::classComplete() +{ + Q_D(QmlBehaviour); + d->context->deactivate(); +} + +#include "qmlbehaviour.moc" + +QT_END_NAMESPACE diff --git a/src/declarative/util/qmlbehaviour.h b/src/declarative/util/qmlbehaviour.h new file mode 100644 index 0000000..080423a --- /dev/null +++ b/src/declarative/util/qmlbehaviour.h @@ -0,0 +1,99 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMLBEHAVIOUR_H +#define QMLBEHAVIOUR_H + +#include <qmlpropertyvaluesource.h> +#include <qml.h> +#include <qmlstate.h> +#include <gfxtimeline.h> + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Declarative) +class QmlAbstractAnimation; +class QmlBehaviourPrivate; +class Q_DECLARATIVE_EXPORT QmlBehaviour : public QmlPropertyValueSource, + public QmlParserStatus +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QmlBehaviour) + Q_INTERFACES(QmlParserStatus) + + Q_PROPERTY(QVariant from READ fromValue WRITE setFromValue); + Q_PROPERTY(QVariant to READ toValue WRITE setToValue); + Q_CLASSINFO("DefaultProperty", "operations"); + Q_PROPERTY(QmlList<QmlAbstractAnimation *>* operations READ operations); + +public: + QmlBehaviour(QObject *parent=0); + ~QmlBehaviour(); + + QVariant fromValue() const; + void setFromValue(const QVariant &); + QVariant toValue() const; + void setToValue(const QVariant &); + virtual void setTarget(const QmlMetaProperty &); + + QmlList<QmlAbstractAnimation *>* operations(); + + static bool _ignore; + +protected: + virtual void classBegin(); + virtual void classComplete(); + +private Q_SLOTS: + void propertyValueChanged(); +}; +QML_DECLARE_TYPE(QmlBehaviour); + + +#endif // QMLBEHAVIOUR_H + + +QT_END_NAMESPACE + +QT_END_HEADER diff --git a/src/declarative/util/qmlbind.cpp b/src/declarative/util/qmlbind.cpp new file mode 100644 index 0000000..d71d711 --- /dev/null +++ b/src/declarative/util/qmlbind.cpp @@ -0,0 +1,203 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <qmlbindablevalue.h> +#include <QtDeclarative/qmlengine.h> +#include <QtDeclarative/qmlcontext.h> +#include <private/qobject_p.h> +#include <QtCore/qfile.h> +#include <QtCore/qdebug.h> +#include <QtScript/qscriptvalue.h> +#include <QtScript/qscriptcontext.h> +#include <QtScript/qscriptengine.h> +#include <private/qmlnullablevalue_p.h> +#include "qmlbind.h" + +QT_BEGIN_NAMESPACE +class QmlBindPrivate : public QObjectPrivate +{ +public: + QmlBindPrivate() : when(true), obj(0) {} + + bool when; + QObject *obj; + QString prop; + QmlNullableValue<QVariant> value; +}; + +QML_DEFINE_TYPE(QmlBind,Bind); +/*! + \qmlclass Bind QmlBind + \brief The Bind element allows arbitrary property bindings to be created. + + 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. Bind + 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 Bind to update the enteredText property + like this. + \code + <LineEdit id="myTextField" text="Please type here..." /> + <Bind target="{app}" property="enteredText" value="{myTextField.text}" /> + \endcode + Whenever the text in the LineEdit is updated, the C++ property will be + updated also. + + If the bind target or bind property is changed, the bound value is + immediately pushed onto the new target. + + \sa {qmlforcpp}{Qt Declarative Markup Language For C++ Programmers} + */ +/*! + \internal + \class QmlBind + \ingroup utility + \brief The QmlBind class allows arbitrary property bindings to be created. + + Simple bindings are usually earier to do in-place rather than creating a + QmlBind item. For that reason, QmlBind is usually used to transfer property information + from Qml to C++. + + \sa cppqml + */ +QmlBind::QmlBind(QObject *parent) + : QObject(*(new QmlBindPrivate), parent) +{ +} + +QmlBind::~QmlBind() +{ +} + +bool QmlBind::when() const +{ + Q_D(const QmlBind); + return d->when; +} + +void QmlBind::setWhen(bool v) +{ + Q_D(QmlBind); + d->when = v; + eval(); +} + +/*! + \qmlproperty Object Bind::target + + The object to be updated. + */ +/*! + \property QmlBind::target + \brief the object to be updated. +*/ +QObject *QmlBind::object() +{ + Q_D(const QmlBind); + return d->obj; +} + +void QmlBind::setObject(QObject *obj) +{ + Q_D(QmlBind); + d->obj = obj; + eval(); +} + +/*! + \qmlproperty string Bind::property + + The property to be updated. + */ +/*! + \property QmlBind::property + \brief the property of the target to be updated. +*/ +QString QmlBind::property() const +{ + Q_D(const QmlBind); + return d->prop; +} + +void QmlBind::setProperty(const QString &p) +{ + Q_D(QmlBind); + d->prop = p; + eval(); +} + +/*! + \qmlproperty any Bind::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. + */ +/*! + \property QmlBind::value + \brief the value to bind to. +*/ +QVariant QmlBind::value() const +{ + Q_D(const QmlBind); + return d->value.value; +} + +void QmlBind::setValue(const QVariant &v) +{ + Q_D(QmlBind); + d->value.value = v; + d->value.isNull = false; + eval(); +} + +void QmlBind::eval() +{ + Q_D(QmlBind); + if(!d->obj || d->value.isNull || !d->when) + return; + + QmlMetaProperty prop(d->obj, d->prop); + prop.write(d->value.value); +} + +QT_END_NAMESPACE diff --git a/src/declarative/util/qmlbind.h b/src/declarative/util/qmlbind.h new file mode 100644 index 0000000..355edfd --- /dev/null +++ b/src/declarative/util/qmlbind.h @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMLBIND_H +#define QMLBIND_H + +#include <qfxglobal.h> +#include <QtCore/qobject.h> +#include "qml.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Declarative) +class QmlBindPrivate; +class Q_DECLARATIVE_EXPORT QmlBind : public QObject +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QmlBind); + + Q_PROPERTY(QObject *target READ object WRITE setObject); + Q_PROPERTY(QString property READ property WRITE setProperty); + Q_PROPERTY(QVariant value READ value WRITE setValue); + +public: + QmlBind(QObject *parent=0); + ~QmlBind(); + + Q_PROPERTY(bool when READ when WRITE setWhen); + 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 &); + +private: + void eval(); +}; +QML_DECLARE_TYPE(QmlBind); + +QT_END_NAMESPACE + +QT_END_HEADER +#endif diff --git a/src/declarative/util/qmlconnection.cpp b/src/declarative/util/qmlconnection.cpp new file mode 100644 index 0000000..df45a31 --- /dev/null +++ b/src/declarative/util/qmlconnection.cpp @@ -0,0 +1,290 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qmlconnection.h" +#include <QtDeclarative/qmlexpression.h> +#include "private/qmlboundsignal_p.h" +#include "private/qobject_p.h" +#include <QtDeclarative/qmlcontext.h> +#include <QtCore/qdebug.h> + + +QT_BEGIN_NAMESPACE +class QmlConnectionPrivate : public QObjectPrivate +{ +public: + QmlConnectionPrivate() : ctxt(0), boundsignal(0), signalSender(0), componentcomplete(false) {} + + QmlContext *ctxt; + QmlBoundSignal *boundsignal; + QObject *signalSender; + QString script; + QString signal; + bool componentcomplete; +}; + +/*! + \qmlclass Connection QmlConnection + \brief The Connection element describes generalized connections to signals. + + JavaScript-in-HTML style \l {qmlformatsignalscpp}{signal properties} do not allow: + \list + \i connecting to signals with the same name but different parameters + \i conformance checking that parameters are correctly named + \i multiple connections to the same signal + \i connections outside the scope of the signal sender + \i signals in classes with coincidentally-named on<Signal> properties + \endlist + + When any of these is needed, the Connection element can be used instead. + Where a signal could be connected like this: + + \code + <MouseRegion onClicked="foo(x+123,y+456)" /> + \endcode + + An equivalent binding can be made with a Connection element: + + \code + <MouseRegion> + <Connection signal="clicked(x,y)" script="foo(x+123,y+456)" /> + </MouseRegion> + \endcode + + More generally, the Connection element can be a child of some other element than + the sender of the signal, and the script is the default attribute: + + \code + <MouseRegion id="mr"/> + ... + <Connection sender="{mr}" signal="clicked(x,y)"> + foo(x+123,y+456) + </Connection> + \endcode +*/ + +/*! + \internal + \class QmlConnection + \brief The QmlConnection class describes generalized connections to signals. + + QmlSetProperties is a mechanism for connecting a script to be run when + some object sends a signal. +*/ +QmlConnection::QmlConnection(QObject *parent) : + QObject(*(new QmlConnectionPrivate), parent) +{ + Q_D(QmlConnection); + d->ctxt = QmlContext::activeContext(); +} + +QmlConnection::~QmlConnection() +{ + Q_D(QmlConnection); + delete d->boundsignal; +} + +/*! + \qmlproperty Object Connection::sender + This property holds the object that sends the signal. + + By default, the sender is assumed to be the parent of the Connection. +*/ + +/*! + \property QmlConnection::sender + \brief the object that sends the signal. + + By default, the sender is assumed to be the parent of the Connection. + + Note that the set/get methods are setSignalSender() and signalSender(), + due to the pre-existence of QObject::sender(). +*/ +QObject *QmlConnection::signalSender() const +{ + Q_D(const QmlConnection); + return d->signalSender ? d->signalSender : parent(); +} + +void QmlConnection::setSignalSender(QObject *obj) +{ + Q_D(QmlConnection); + if (d->signalSender == obj) + return; + disconnectIfValid(); + d->signalSender = obj; + connectIfValid(); +} + +void QmlConnection::connectIfValid() +{ + Q_D(QmlConnection); + if (!d->componentcomplete) + return; + // boundsignal must not exist + if ((d->signalSender || parent()) && !d->signal.isEmpty() && !d->script.isEmpty()) { + // create + // XXX scope? + int sigIdx = -1; + int lparen = d->signal.indexOf(QLatin1Char('(')); + QList<QByteArray> sigparams; + if (lparen >= 0 && d->signal.length() > lparen+2) { + QStringList l = d->signal.mid(lparen+1,d->signal.length()-lparen-2).split(QLatin1Char(',')); + foreach (QString s, l) { + sigparams.append(s.toLatin1()); + } + } + QString signalname = d->signal.left(lparen); + QObject *sender = d->signalSender ? d->signalSender : parent(); + const QMetaObject *mo = sender->metaObject(); + int methods = mo->methodCount(); + for(int ii = 0; ii < methods; ++ii) { + QMetaMethod method = mo->method(ii); + QString methodName = QLatin1String(method.signature()); + int idx = methodName.indexOf(QLatin1Char('(')); + methodName = methodName.left(idx); + if(methodName == signalname && (lparen<0 || method.parameterNames() == sigparams)) { + sigIdx = ii; + break; + } + } + if (sigIdx < 0) { + qWarning() << "signal" << d->signal << "not found"; + return; + } + + if (sigparams.isEmpty()) + d->boundsignal = new QmlBoundSignal(d->ctxt, d->script, sender, sigIdx, this); + else + d->boundsignal = new QmlBoundSignalProxy(new QmlContext(d->ctxt,this), d->script, sender, sigIdx, this); + } +} + +void QmlConnection::disconnectIfValid() +{ + Q_D(QmlConnection); + if (!d->componentcomplete) + return; + if ((d->signalSender || parent()) && !d->signal.isEmpty() && !d->script.isEmpty()) { + // boundsignal must exist + // destroy + delete d->boundsignal; + d->boundsignal = 0; + } +} + +void QmlConnection::componentComplete() +{ + Q_D(QmlConnection); + d->componentcomplete=true; + connectIfValid(); +} + + +/*! + \qmlproperty string Connection::script + This property holds the JavaScript executed whenever the signal is sent. + + This is the default attribute of Connection. +*/ + +/*! + \property QmlConnection::script + \brief the JavaScript executed whenever the signal is sent. +*/ +QString QmlConnection::script() const +{ + Q_D(const QmlConnection); + return d->script; +} + +void QmlConnection::setScript(const QString& script) +{ + Q_D(QmlConnection); + if ((d->signalSender || parent()) && !d->signal.isEmpty()) { + if (d->script.isEmpty()) { + // mustn't exist - create + d->script = script; + connectIfValid(); + } else { + // must exist - update + d->script = script; + d->boundsignal->setExpression(script); + } + } else { + d->script = script; + } +} + +/*! + \qmlproperty string Connection::signal + This property holds the signal from the sender to which the script is attached. + + The signal must have its formal parameter names given in parentheses: + + \code + <Connection signal="clicked(x,y)" ... /> + \endcode +*/ + +/*! + \property QmlConnection::signal + \brief the signal from the sender to which the script is attached. +*/ +QString QmlConnection::signal() const +{ + Q_D(const QmlConnection); + return d->signal; +} + +void QmlConnection::setSignal(const QString& sig) +{ + Q_D(QmlConnection); + if (d->signal == sig) + return; + disconnectIfValid(); + d->signal = sig; + connectIfValid(); +} + +QML_DEFINE_TYPE(QmlConnection,Connection); + +QT_END_NAMESPACE diff --git a/src/declarative/util/qmlconnection.h b/src/declarative/util/qmlconnection.h new file mode 100644 index 0000000..c943092 --- /dev/null +++ b/src/declarative/util/qmlconnection.h @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMLCONNECTION_H +#define QMLCONNECTION_H + +#include <QtCore/qobject.h> +#include <QtCore/qstring.h> +#include <QtDeclarative/qml.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Declarative) +class QmlBoundSignal; +class QmlContext; +class QmlConnectionPrivate; +class Q_DECLARATIVE_EXPORT QmlConnection : public QObject, public QmlParserStatus +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QmlConnection) + + Q_INTERFACES(QmlParserStatus); + Q_CLASSINFO("DefaultProperty", "script"); + Q_PROPERTY(QObject *sender READ signalSender WRITE setSignalSender); + Q_PROPERTY(QString script READ script WRITE setScript); + Q_PROPERTY(QString signal READ signal WRITE setSignal); + +public: + QmlConnection(QObject *parent=0); + ~QmlConnection(); + + QObject *signalSender() const; + void setSignalSender(QObject *); + QString script() const; + void setScript(const QString&); + QString signal() const; + void setSignal(const QString&); + +private: + void disconnectIfValid(); + void connectIfValid(); + void componentComplete(); +}; +QML_DECLARE_TYPE(QmlConnection); + +#endif + + +QT_END_NAMESPACE + +QT_END_HEADER diff --git a/src/declarative/util/qmldatetimeformatter.cpp b/src/declarative/util/qmldatetimeformatter.cpp new file mode 100644 index 0000000..138f68b --- /dev/null +++ b/src/declarative/util/qmldatetimeformatter.cpp @@ -0,0 +1,368 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qmldatetimeformatter.h" +#include "private/qobject_p.h" +#include <QtCore/qlocale.h> + +QT_BEGIN_NAMESPACE +//TODO: may need optimisation as the QDateTime member may not be needed? +// be able to set a locale? + +class QmlDateTimeFormatterPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QmlDateTimeFormatter) +public: + QmlDateTimeFormatterPrivate() : locale(QLocale::system()), longStyle(false), classComplete(true) {} + + void updateText(); + + QDateTime dateTime; + QDate date; + QTime time; + QLocale locale; + QString dateTimeText; + QString dateText; + QString timeText; + QString dateTimeFormat; //set for convienience? + QString dateFormat; + QString timeFormat; + bool longStyle; + bool classComplete; +}; + +/*! + \qmlclass DateTimeFormatter QmlDateTimeFormatter + \brief The DateTimeFormatter allows you to control the format of a date string. + + \code + <DateTimeFormatter id="Formatter" date="{System.date}"/> + <Text text="{Formatter.dateText}"/> + \endcode + + By default, the text properties (dateText, timeText, and dateTimeText) will return the + date and time using the current system locale's format. +*/ + +/*! + \internal + \class QmlDateTimeFormatter + \ingroup utility + \brief The QmlDateTimeFormatter class allows you to format a date string. +*/ + +QmlDateTimeFormatter::QmlDateTimeFormatter(QObject *parent) +: QObject(*(new QmlDateTimeFormatterPrivate), parent) +{ +} + +QmlDateTimeFormatter::~QmlDateTimeFormatter() +{ +} + +/*! + \qmlproperty string DateTimeFormatter::dateText + \qmlproperty string DateTimeFormatter::timeText + \qmlproperty string DateTimeFormatter::dateTimeText + + Formatted text representations of the \c date, \c time, + and \c {date and time}, respectively. + + If there is no explictly specified format the DateTimeFormatter + will use the system locale's default 'short' setting. + + \code + <!-- specify source date (assuming today is February 19, 2009) --> + <DateTimeFormatter id="formatter" dateTime="{Today.date}"/> + + <!-- display the full date and time --> + <Text text="{formatter.dateText}"/> + \endcode + + Would be equivalent to the following for a US English locale: + + \code + <!-- display the date --> + <Text text="2/19/09"/> + \endcode +*/ +QString QmlDateTimeFormatter::dateTimeText() const +{ + Q_D(const QmlDateTimeFormatter); + return d->dateTimeText; +} + +QString QmlDateTimeFormatter::dateText() const +{ + Q_D(const QmlDateTimeFormatter); + return d->dateText; +} + +QString QmlDateTimeFormatter::timeText() const +{ + Q_D(const QmlDateTimeFormatter); + return d->timeText; +} + +/*! + \qmlproperty date DateTimeFormatter::date + \qmlproperty time DateTimeFormatter::time + \qmlproperty datetime DateTimeFormatter::dateTime + + The source date and time to be used by the formatter. + + \code + <!-- setting the date and time --> + <DateTimeFormatter date="{System.date}" time="{System.time}"/> + \endcode + + For convienience it is possible to set the datetime property to set both the date and the time. + \code + <!-- setting the datetime --> + <DateTimeFormatter dateTime="{System.dateTime}"/> + \endcode + + There can only be one instance of date and time per formatter; if date, time, and dateTime are all + set the actual date and time used is not guaranteed. + + \note If no date is set, dateTimeText will be just the date; + If no time is set, the dateTimeText will be just the time. + +*/ +QDate QmlDateTimeFormatter::date() const +{ + Q_D(const QmlDateTimeFormatter); + return d->date; +} + +QTime QmlDateTimeFormatter::time() const +{ + Q_D(const QmlDateTimeFormatter); + return d->time; +} + +QDateTime QmlDateTimeFormatter::dateTime() const +{ + Q_D(const QmlDateTimeFormatter); + return d->dateTime; +} + +/*! + \qmlproperty string DateTimeFormatter::dateFormat + \qmlproperty string DateTimeFormatter::timeFormat + \qmlproperty string DateTimeFormatter::dateTimeFormat + + Specifies a custom format which the DateTime Formatter can use. + + If there is no explictly specified format the DateTimeFormatter + will use the system locale's default 'short' setting. + + The text's format may be modified by setting: + \list + \i \c dateFormat + \i \c timeFormat + \i \c dateTimeFormat + \endlist + + If only the format for date is defined, the time and dateTime formats will be defined + as the system locale default and likewise for the others. + + Syntax for the format is based on the QDateTime::toString() formatting options. + + \code + <!-- Format the date such that the dateText is: '1997-12-12'> + <DateFormatter id="formatter" dateTime="{Today.dateTime}" formatDate="yyyy-MM-d"/> + \endcode + + Assigning an empty string to a particular format will reset it. +*/ +QString QmlDateTimeFormatter::dateTimeFormat() const +{ + Q_D(const QmlDateTimeFormatter); + return d->dateTimeFormat; +} + +QString QmlDateTimeFormatter::dateFormat() const +{ + Q_D(const QmlDateTimeFormatter); + return d->dateFormat; +} + +QString QmlDateTimeFormatter::timeFormat() const +{ + Q_D(const QmlDateTimeFormatter); + return d->timeFormat; +} + +/*! + \qmlproperty bool DateTimeFormatter::longStyle + + This property causes the formatter to use the system locale's long format rather than short format + by default. + + This setting is off by default. +*/ +bool QmlDateTimeFormatter::longStyle() const +{ + Q_D(const QmlDateTimeFormatter); + return d->longStyle; +} + +void QmlDateTimeFormatter::setDateTime(const QDateTime &dateTime) +{ + Q_D(QmlDateTimeFormatter); + if (d->dateTime == dateTime) + return; + d->dateTime = dateTime; + d->date = d->dateTime.date(); + d->time = d->dateTime.time(); + d->updateText(); +} + +void QmlDateTimeFormatter::setTime(const QTime &time) +{ + Q_D(QmlDateTimeFormatter); + if (d->dateTime.time() == time) + return; + d->time = time; + d->dateTime.setTime(time); + d->updateText(); +} + +void QmlDateTimeFormatter::setDate(const QDate &date) +{ + Q_D(QmlDateTimeFormatter); + if (d->dateTime.date() == date) + return; + d->date = date; + bool clearTime = d->dateTime.time().isValid() ? false : true; //because setting date generates default time + d->dateTime.setDate(date); + if (clearTime) + d->dateTime.setTime(QTime()); + d->updateText(); +} + +//DateTime formatting may be a combination of date and time? +void QmlDateTimeFormatter::setDateTimeFormat(const QString &format) +{ + Q_D(QmlDateTimeFormatter); + //no format checking + d->dateTimeFormat = format; + d->updateText(); +} + +void QmlDateTimeFormatter::setDateFormat(const QString &format) +{ + Q_D(QmlDateTimeFormatter); + //no format checking + d->dateFormat = format; + d->updateText(); +} + +void QmlDateTimeFormatter::setTimeFormat(const QString &format) +{ + Q_D(QmlDateTimeFormatter); + //no format checking + d->timeFormat = format; + d->updateText(); +} + +void QmlDateTimeFormatter::setLongStyle(bool longStyle) +{ + Q_D(QmlDateTimeFormatter); + d->longStyle = longStyle; + d->updateText(); +} + +void QmlDateTimeFormatterPrivate::updateText() +{ + Q_Q(QmlDateTimeFormatter); + if (!classComplete) + return; + + QString str; + QString str1; + QString str2; + + Qt::DateFormat defaultFormat = longStyle ? Qt::SystemLocaleLongDate : Qt::SystemLocaleShortDate; + + if (dateFormat.isEmpty()) + str1 = date.toString(defaultFormat); + else + str1 = date.toString(dateFormat); + + if (timeFormat.isEmpty()) + str2 = time.toString(defaultFormat); + else + str2 = time.toString(timeFormat); + + if (dateTimeFormat.isEmpty()) + str = dateTime.toString(defaultFormat); + //else if (!formatTime.isEmpty() && !formatDate.isEmpty()) + // str = str1 + QLatin1Char(' ') + str2; + else + str = dateTime.toString(dateTimeFormat); + + if (dateTimeText == str && dateText == str1 && timeText == str2) + return; + + dateTimeText = str; + dateText = str1; + timeText = str2; + + emit q->textChanged(); +} + +void QmlDateTimeFormatter::classBegin() +{ + Q_D(QmlDateTimeFormatter); + d->classComplete = false; +} + +void QmlDateTimeFormatter::classComplete() +{ + Q_D(QmlDateTimeFormatter); + d->classComplete = true; + d->updateText(); +} + +QML_DEFINE_TYPE(QmlDateTimeFormatter, DateTimeFormatter); +QT_END_NAMESPACE diff --git a/src/declarative/util/qmldatetimeformatter.h b/src/declarative/util/qmldatetimeformatter.h new file mode 100644 index 0000000..3421f8c --- /dev/null +++ b/src/declarative/util/qmldatetimeformatter.h @@ -0,0 +1,116 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMLDATETIMEFORMATTER_H +#define QMLDATETIMEFORMATTER_H + +#include <QtCore/qdatetime.h> +#include <QtDeclarative/qml.h> + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Declarative) +class QmlDateTimeFormatterPrivate; +class Q_DECLARATIVE_EXPORT QmlDateTimeFormatter : public QObject, public QmlParserStatus +{ + Q_OBJECT + Q_INTERFACES(QmlParserStatus) + + Q_PROPERTY(QString dateText READ dateText NOTIFY textChanged) + Q_PROPERTY(QString timeText READ timeText NOTIFY textChanged) + Q_PROPERTY(QString dateTimeText READ dateTimeText NOTIFY textChanged) + Q_PROPERTY(QDate date READ date WRITE setDate) + Q_PROPERTY(QTime time READ time WRITE setTime) + Q_PROPERTY(QDateTime dateTime READ dateTime WRITE setDateTime) + Q_PROPERTY(QString dateFormat READ dateFormat WRITE setDateFormat) + Q_PROPERTY(QString timeFormat READ timeFormat WRITE setTimeFormat) + Q_PROPERTY(QString dateTimeFormat READ dateTimeFormat WRITE setDateTimeFormat) + Q_PROPERTY(bool longStyle READ longStyle WRITE setLongStyle) +public: + QmlDateTimeFormatter(QObject *parent=0); + ~QmlDateTimeFormatter(); + + QString dateTimeText() const; + QString dateText() const; + QString timeText() const; + + QDate date() const; + void setDate(const QDate &); + + QTime time() const; + void setTime(const QTime &); + + QDateTime dateTime() const; + void setDateTime(const QDateTime &); + + QString dateTimeFormat() const; + void setDateTimeFormat(const QString &); + + QString dateFormat() const; + void setDateFormat(const QString &); + + QString timeFormat() const; + void setTimeFormat(const QString &); + + bool longStyle() const; + void setLongStyle(bool); + + virtual void classBegin(); + virtual void classComplete(); + +Q_SIGNALS: + void textChanged(); + +private: + Q_DISABLE_COPY(QmlDateTimeFormatter) + Q_DECLARE_PRIVATE(QmlDateTimeFormatter) +}; + +QML_DECLARE_TYPE(QmlDateTimeFormatter); + + +QT_END_NAMESPACE + +QT_END_HEADER +#endif diff --git a/src/declarative/util/qmlfollow.cpp b/src/declarative/util/qmlfollow.cpp new file mode 100644 index 0000000..c841b85 --- /dev/null +++ b/src/declarative/util/qmlfollow.cpp @@ -0,0 +1,309 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <limits.h> +#include <QtCore/qdebug.h> +#include <gfxtimeline.h> +#include "private/qobject_p.h" +#include "qmlfollow.h" +#include "private/qmlanimation_p.h" + + +QT_BEGIN_NAMESPACE +QML_DEFINE_TYPE(QmlFollow,Follow); + +class QmlFollowPrivate : public QObjectPrivate +{ +public: + QmlFollowPrivate() + : sourceValue(0), maxVelocity(0), lastTime(0) + , mass(1.0), spring(0.), damping(0.), velocity(0), enabled(true), mode(Track), clock(this) {} + + QmlMetaProperty property; + qreal currentValue; + qreal sourceValue; + qreal maxVelocity; + qreal velocityms; + int lastTime; + qreal mass; + qreal spring; + qreal damping; + qreal velocity; + bool enabled; + + enum Mode { + Track, + Velocity, + Spring + }; + Mode mode; + + void tick(int); + void updateMode(); + void start(); + void stop(); + + QTickAnimationProxy<QmlFollowPrivate, &QmlFollowPrivate::tick> clock; +}; + +void QmlFollowPrivate::tick(int time) +{ + int elapsed = time - lastTime; + if (!elapsed) + return; + if (mode == Spring) { + if (elapsed < 10) // capped at 100fps. + return; + // Real men solve the spring DEs using RK4. + // We'll do something much simpler which gives a result that looks fine. + int count = (elapsed+5) / 10; + for (int i = 0; i < count; ++i) { + qreal diff = sourceValue - currentValue; + velocity = velocity + spring * diff - damping * velocity; + // The following line supports mass. Not sure its worth the extra divisions. + // velocity = velocity + spring / mass * diff - damping / mass * velocity; + if (maxVelocity > 0.) { + // limit velocity + if (velocity > maxVelocity) + velocity = maxVelocity; + else if (velocity < -maxVelocity) + velocity = -maxVelocity; + } + currentValue += velocity * 10.0 / 1000.0; + } + if (qAbs(velocity) < 0.5 && qAbs(sourceValue - currentValue) < 0.5) { + velocity = 0.0; + currentValue = sourceValue; + clock.stop(); + } + lastTime = time - (elapsed - count * 10); + } else { + qreal moveBy = elapsed * velocityms; + qreal diff = sourceValue - currentValue; + if (diff > 0) { + currentValue += moveBy; + if (currentValue > sourceValue) { + currentValue = sourceValue; + clock.stop(); + } + } else { + currentValue -= moveBy; + if (currentValue < sourceValue) { + currentValue = sourceValue; + clock.stop(); + } + } + lastTime = time; + } + property.write(currentValue); +} + +void QmlFollowPrivate::updateMode() +{ + if (spring == 0. && maxVelocity == 0.) + mode = Track; + else if (spring > 0.) + mode = Spring; + else + mode = Velocity; +} + +void QmlFollowPrivate::start() +{ + if (!enabled) + return; + + if (mode == QmlFollowPrivate::Track) { + currentValue = sourceValue; + property.write(currentValue); + } else if (sourceValue != currentValue && clock.state() != QAbstractAnimation::Running) { + lastTime = 0; + clock.start(); // infinity?? + } +} + +void QmlFollowPrivate::stop() +{ + clock.stop(); +} + +/*! + \qmlclass Follow QmlFollow + \brief The Follow element allows a property to track a value. + + In example below, Rect2 will follow Rect1 moving with a velocity of up to 200: + \code + <Rect id="Rect1" y="{200}" width="20" height="20" color="#00ff00"> + <y> + <SequentialAnimation running="true" repeat="true"> + <NumericAnimation to="{200}" easing="easeOutBounce(amplitude:100)" duration="2000" /> + <PauseAnimation duration="1000" /> + </SequentialAnimation> + </y> + </Rect> + <Rect id="Rect2" x="{Rect1.width}" width="20" height="20" color="#ff0000"> + <y> + <Follow source="{Rect1.y}" velocity="200"/> + </y> + </Rect> + \endcode +*/ + +QmlFollow::QmlFollow(QObject *parent) +: QmlPropertyValueSource(*(new QmlFollowPrivate),parent) +{ +} + +QmlFollow::~QmlFollow() +{ +} + +void QmlFollow::setTarget(const QmlMetaProperty &property) +{ + Q_D(QmlFollow); + d->property = property; + d->currentValue = property.read().toDouble(); +} + +qreal QmlFollow::sourceValue() const +{ + Q_D(const QmlFollow); + return d->sourceValue; +} + +/*! + \qmlproperty qreal Follow::source + This property holds the source value which will be tracked. + + Bind to a property in order to track its changes. +*/ + +void QmlFollow::setSourceValue(qreal value) +{ + Q_D(QmlFollow); + d->sourceValue = value; + d->start(); +} + +/*! + \qmlproperty qreal Follow::velocity + This property holds the maximum velocity allowed when tracking the source. +*/ + +qreal QmlFollow::velocity() const +{ + Q_D(const QmlFollow); + return d->maxVelocity; +} + +void QmlFollow::setVelocity(qreal velocity) +{ + Q_D(QmlFollow); + d->maxVelocity = velocity; + d->velocityms = velocity / 1000.0; + d->updateMode(); +} + +/*! + \qmlproperty qreal Follow::spring + This property holds the spring constant + + The spring constant describes how strongly the target is pulled towards the + source. Setting spring to 0 turns off spring tracking. Useful values 0 - 5.0 + + When a spring constant is set and the velocity property is greater than 0, + velocity limits the maximum speed. +*/ +qreal QmlFollow::spring() const +{ + Q_D(const QmlFollow); + return d->spring; +} + +void QmlFollow::setSpring(qreal spring) +{ + Q_D(QmlFollow); + d->spring = spring; + d->updateMode(); +} + +/*! + \qmlproperty qreal Follow::damping + This property holds the spring damping constant + + The damping constant describes how quickly a sprung follower comes to rest. + Useful range is 0 - 1.0 +*/ +qreal QmlFollow::damping() const +{ + Q_D(const QmlFollow); + return d->damping; +} + +void QmlFollow::setDamping(qreal damping) +{ + Q_D(QmlFollow); + if (damping > 1.) + damping = 1.; + + d->damping = damping; +} + +/*! + \qmlproperty bool Follow::enabled + This property holds whether the target will track the source. +*/ +bool QmlFollow::enabled() const +{ + Q_D(const QmlFollow); + return d->enabled; +} + +void QmlFollow::setEnabled(bool enabled) +{ + Q_D(QmlFollow); + d->enabled = enabled; + if (enabled) + d->start(); + else + d->stop(); +} +QT_END_NAMESPACE diff --git a/src/declarative/util/qmlfollow.h b/src/declarative/util/qmlfollow.h new file mode 100644 index 0000000..a609305 --- /dev/null +++ b/src/declarative/util/qmlfollow.h @@ -0,0 +1,94 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMLFOLLOW_H +#define QMLFOLLOW_H + +#include <qmlpropertyvaluesource.h> +#include <qml.h> + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Declarative) +class QmlFollowPrivate; +class Q_DECLARATIVE_EXPORT QmlFollow : public QmlPropertyValueSource, + public QmlParserStatus +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QmlFollow) + Q_INTERFACES(QmlParserStatus) + + Q_PROPERTY(qreal source READ sourceValue WRITE setSourceValue); + Q_PROPERTY(qreal velocity READ velocity WRITE setVelocity); + Q_PROPERTY(qreal spring READ spring WRITE setSpring); + Q_PROPERTY(qreal damping READ damping WRITE setDamping); + Q_PROPERTY(bool enabled READ enabled WRITE setEnabled); + +public: + QmlFollow(QObject *parent=0); + ~QmlFollow(); + + virtual void setTarget(const QmlMetaProperty &); + + qreal sourceValue() const; + void setSourceValue(qreal value); + qreal velocity() const; + void setVelocity(qreal velocity); + qreal spring() const; + void setSpring(qreal spring); + qreal damping() const; + void setDamping(qreal damping); + bool enabled() const; + void setEnabled(bool enabled); +}; + +QML_DECLARE_TYPE(QmlFollow); + + +#endif // QFXFOLLOW_H + + +QT_END_NAMESPACE + +QT_END_HEADER diff --git a/src/declarative/util/qmlfont.cpp b/src/declarative/util/qmlfont.cpp new file mode 100644 index 0000000..ad91edd --- /dev/null +++ b/src/declarative/util/qmlfont.cpp @@ -0,0 +1,147 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "private/qobject_p.h" +#include "qfont.h" +#include "qmlfont.h" + + +QT_BEGIN_NAMESPACE +class QmlFontPrivate : public QObjectPrivate +{ +public: + QFont font; +}; + +QML_DEFINE_TYPE(QmlFont,Font); + +/*! + \internal + \class QmlFont + \ingroup utility + \brief The QmlFont class provides a font used for drawing text on a QFxView. +*/ +QmlFont::QmlFont(QObject *parent) + : QObject(*(new QmlFontPrivate), parent) +{ +} + +QmlFont::~QmlFont() +{ +} + +/*! + \property QmlFont::family + \brief the family of the font. +*/ +QString QmlFont::family() const +{ + Q_D(const QmlFont); + return d->font.family(); +} + +void QmlFont::setFamily(const QString &family) +{ + Q_D(QmlFont); + d->font.setFamily(family); + emit updated(); +} + +/*! + \property QmlFont::bold + \brief whether the font should be bold. +*/ +bool QmlFont::bold() const +{ + Q_D(const QmlFont); + return d->font.bold(); +} + +void QmlFont::setBold(bool b) +{ + Q_D(QmlFont); + d->font.setBold(b); + emit updated(); +} + +/*! + \property QmlFont::italic + \brief whether the font should be italic. +*/ +bool QmlFont::italic() const +{ + Q_D(const QmlFont); + return d->font.italic(); +} + +void QmlFont::setItalic(bool b) +{ + Q_D(QmlFont); + d->font.setItalic(b); + emit updated(); +} + +/*! + \property QmlFont::size + \brief the size of the font in points. +*/ +qreal QmlFont::size() const +{ + Q_D(const QmlFont); + return d->font.pointSizeF(); +} + +void QmlFont::setSize(qreal size) +{ + Q_D(QmlFont); + d->font.setPointSizeF(size); + emit updated(); +} + +/*! + \brief Returns a QFont representation of the font. +*/ +QFont QmlFont::font() const +{ + Q_D(const QmlFont); + return d->font; +} +QT_END_NAMESPACE diff --git a/src/declarative/util/qmlfont.h b/src/declarative/util/qmlfont.h new file mode 100644 index 0000000..b6bce7c --- /dev/null +++ b/src/declarative/util/qmlfont.h @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMLFONT_H +#define QMLFONT_H + +#include <QtCore/qobject.h> +#include <qml.h> + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Declarative) +class QmlFontPrivate; +class Q_DECLARATIVE_EXPORT QmlFont : public QObject +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QmlFont) + + Q_PROPERTY(QString family READ family WRITE setFamily) + Q_PROPERTY(bool bold READ bold WRITE setBold) + Q_PROPERTY(bool italic READ italic WRITE setItalic) + Q_PROPERTY(qreal size READ size WRITE setSize) + +public: + QmlFont(QObject *parent=0); + ~QmlFont(); + + QString family() const; + void setFamily(const QString &); + + bool bold() const; + void setBold(bool b); + + bool italic() const; + void setItalic(bool b); + + qreal size() const; + void setSize(qreal size); + + QFont font() const; + +Q_SIGNALS: + void updated(); +}; +QML_DECLARE_TYPE(QmlFont); + + +QT_END_NAMESPACE + +QT_END_HEADER +#endif // QMLFONT_H diff --git a/src/declarative/util/qmllistaccessor.cpp b/src/declarative/util/qmllistaccessor.cpp new file mode 100644 index 0000000..9387bbc --- /dev/null +++ b/src/declarative/util/qmllistaccessor.cpp @@ -0,0 +1,243 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qmllistaccessor.h" +#include <QStringList> +#include <qmlmetatype.h> +#include <QtCore/qdebug.h> + +QT_BEGIN_NAMESPACE + +QmlListAccessor::QmlListAccessor() +: type(Invalid) +{ +} + +QmlListAccessor::~QmlListAccessor() +{ +} + +QVariant QmlListAccessor::list() const +{ + return d; +} + +void QmlListAccessor::setList(const QVariant &v) +{ + d = v; + + if(!d.isValid()) { + type = Invalid; + } else if(d.type() == QVariant::StringList) { + type = StringList; + } else if(d.type() != QVariant::UserType) { + type = Instance; + } else if(QmlMetaType::isObject(d.userType())) { + QObject *data = 0; + data = *(QObject **)v.constData(); + d = QVariant::fromValue(data); + type = Instance; + } else if(QmlMetaType::isQmlList(d.userType())) { + type = QmlList; + } else if(QmlMetaType::isList(d.userType())) { + type = QList; + } else { + type = Invalid; + d = QVariant(); + } +} + +int QmlListAccessor::count() const +{ + switch(type) { + case Invalid: + return 0; + case StringList: + return qvariant_cast<QStringList>(d).count(); + case QmlList: + { + QmlPrivate::ListInterface *li = *(QmlPrivate::ListInterface **)d.constData(); + return li->count(); + } + case QList: + return QmlMetaType::listCount(d); + case Instance: + return 1; + } + + return 0; +} + +QVariant QmlListAccessor::at(int idx) const +{ + Q_ASSERT(idx >= 0 && idx < count()); + switch(type) { + case Invalid: + return QVariant(); + case StringList: + return QVariant::fromValue(qvariant_cast<QStringList>(d).at(idx)); + case QmlList: + { + QmlPrivate::ListInterface *li = *(QmlPrivate::ListInterface **)d.constData(); + void *ptr[1]; + li->at(idx, ptr); + return QmlMetaType::fromObject((QObject*)ptr[0], li->type()); //XXX only handles QObject-derived types + } + case QList: + return QmlMetaType::listAt(d, idx); + case Instance: + return d; + } + + return QVariant(); +} + +void QmlListAccessor::append(const QVariant &value) +{ + switch(type) { + case Invalid: + break; + case StringList: + { + const QString &str = value.toString(); + qvariant_cast<QStringList>(d).append(str); + break; + } + case QmlList: + { + QmlPrivate::ListInterface *li = *(QmlPrivate::ListInterface **)d.constData(); + li->append(const_cast<void *>(value.constData())); //XXX + break; + } + case QList: + QmlMetaType::append(d, value); + break; + case Instance: + //do nothing + break; + } +} + +void QmlListAccessor::insert(int index, const QVariant &value) +{ + switch(type) { + case Invalid: + break; + case StringList: + { + const QString &str = value.toString(); + qvariant_cast<QStringList>(d).insert(index, str); + break; + } + case QmlList: + { + QmlPrivate::ListInterface *li = *(QmlPrivate::ListInterface **)d.constData(); + li->insert(index, const_cast<void *>(value.constData())); //XXX + break; + } + case QList: + //XXX needs implementation + qWarning() << "insert function not yet implemented for QLists"; + break; + case Instance: + //XXX do nothing? + if (index == 0) + setList(value); + break; + } +} + +void QmlListAccessor::removeAt(int index) +{ + switch(type) { + case Invalid: + break; + case StringList: + qvariant_cast<QStringList>(d).removeAt(index); + break; + case QmlList: + { + QmlPrivate::ListInterface *li = *(QmlPrivate::ListInterface **)d.constData(); + li->removeAt(index); + break; + } + case QList: + //XXX needs implementation + qWarning() << "removeAt function not yet implemented for QLists"; + break; + case Instance: + //XXX do nothing? + if (index == 0) + setList(QVariant()); + break; + } +} + +void QmlListAccessor::clear() +{ + switch(type) { + case Invalid: + break; + case StringList: + qvariant_cast<QStringList>(d).clear(); + break; + case QmlList: + { + QmlPrivate::ListInterface *li = *(QmlPrivate::ListInterface **)d.constData(); + li->clear(); + break; + } + case QList: + QmlMetaType::clear(d); + break; + case Instance: + //XXX what should we do here? + setList(QVariant()); + break; + } +} + +bool QmlListAccessor::isValid() const +{ + return type != Invalid; +} + +QT_END_NAMESPACE diff --git a/src/declarative/util/qmllistaccessor.h b/src/declarative/util/qmllistaccessor.h new file mode 100644 index 0000000..29f910d --- /dev/null +++ b/src/declarative/util/qmllistaccessor.h @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMLLISTACCESSOR_H +#define QMLLISTACCESSOR_H + +#include <QVariant> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Declarative) + +class Q_DECLARATIVE_EXPORT QmlListAccessor +{ +public: + QmlListAccessor(); + virtual ~QmlListAccessor(); + + QVariant list() const; + void setList(const QVariant &); + + bool isValid() const; + + int count() const; + QVariant at(int) const; + + virtual void append(const QVariant &); + virtual void insert(int, const QVariant &); + virtual void removeAt(int); + virtual void clear(); + +private: + enum Type { Invalid, StringList, QmlList, QList, Instance }; + Type type; + QVariant d; +}; + +#endif // QMLLISTACCESSOR_H + +QT_END_NAMESPACE + +QT_END_HEADER diff --git a/src/declarative/util/qmllistmodel.cpp b/src/declarative/util/qmllistmodel.cpp new file mode 100644 index 0000000..992185a --- /dev/null +++ b/src/declarative/util/qmllistmodel.cpp @@ -0,0 +1,721 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtCore/qdebug.h> +#include <QtCore/qstack.h> +#include <QXmlStreamReader> +#include "qmlcustomparser.h" +#include "qmlopenmetaobject.h" +#include <qmlcontext.h> +#include <qmlbindablevalue.h> +#include "qmllistmodel.h" + +QT_BEGIN_NAMESPACE + +#define DATA_ROLE_ID 1 +#define DATA_ROLE_NAME "data" + +Q_DECLARE_METATYPE(QListModelInterface *); +class QmlListModelPrivate +{ +public: + QmlListModelPrivate(QmlListModel *m) + : q(m), + type(QmlListModel::Invalid), + listModelInterface(0), + singleObject(0), + roleCacheValid(false) + { + } + + void clear() + { + type = QmlListModel::Invalid; + model = QVariant(); + if(listModelInterface) + listModelInterface->disconnect(q); + listModelInterface = 0; + singleObject = 0; + roleCacheValid = false; + roleCache.clear(); + } + + void updateRoleCache() + { + if(roleCacheValid) + return; + + roleCacheValid = true; + if(type == QmlListModel::SingleObject) + roleCache = QmlMetaProperty::properties(singleObject); + } + + QmlListModel *q; + + QmlListModel::ModelType type; + + QVariant model; + QListModelInterface *listModelInterface; + QObject *singleObject; + + bool roleCacheValid; + QStringList roleCache; +}; + +/*! + \qmlclass ListModel QmlListModel + \brief The ListModel element defines a free-form list data source. + + The ListModel is a simple XML heirarchy of items containing data roles. + For example: + + \code + <ListModel id="FruitModel"> + <Fruit> + <name>Apple</name> + <cost>2.45</cost> + <Fruit> + <Fruit> + <name>Orange</name> + <cost>3.25</cost> + </Fruit> + <Fruit> + <name>Banana</name> + <cost>1.95</cost> + </Fruit> + </ListModel> + \endcode + + Elements beginning with a capital are items. Elements beginning + with lower-case are the data roles. The above example defines a + ListModel containing three items, with the roles "name" and "cost". + + The defined model can be used in views such as ListView: + \code + <Component id="FruitDelegate"> + <Item width="200" height="50"> + <Text text="{name}"/> + <Text text="{'$'+cost}" anchors.right="{parent.right}"/> + </Item> + </Component> + + <ListView model="{FruitModel}" delegate="{FruitDelegate}" anchors.fill="{parent}"/> + \endcode +*/ +/*! + \internal + \class QmlListModel +*/ +QmlListModel::QmlListModel(QObject *parent) +: QListModelInterface(parent), d(new QmlListModelPrivate(this)) +{ +} + +QmlListModel::~QmlListModel() +{ + delete d; d = 0; +} + +QmlListModel::ModelType QmlListModel::modelType() const +{ + return d->type; +} + +bool QmlListModel::setModel(const QVariant &model) +{ + d->clear(); + + QListModelInterface *iface = qvariant_cast<QListModelInterface *>(model); + if(iface) { + QObject::connect(iface, SIGNAL(itemsInserted(int,int)), + this, SIGNAL(itemsInserted(int,int))); + QObject::connect(iface, SIGNAL(itemsRemoved(int,int)), + this, SIGNAL(itemsRemoved(int,int))); + QObject::connect(iface, SIGNAL(itemsMoved(int,int,int)), + this, SIGNAL(itemsMoved(int,int,int))); + QObject::connect(iface, SIGNAL(itemsChanged(int,int,QList<int>)), + this, SIGNAL(itemsChanged(int,int,QList<int>))); + d->listModelInterface = iface; + d->type = ListInterface; + d->model = model; + return true; + } + + QObject *object = qvariant_cast<QObject *>(model); + if(object) { + d->singleObject = object; + d->type = SingleObject; + d->model = model; + return true; + } + + if(QmlMetaType::isList(model)) { + d->type = SimpleList; + d->model = model; + return true; + } + + return false; +} + +QVariant QmlListModel::model() const +{ + return d->model; +} + +QList<int> QmlListModel::roles() const +{ + d->updateRoleCache(); + switch(modelType()) { + case Invalid: + return QList<int>(); + case SimpleList: + return QList<int>() << DATA_ROLE_ID; + case ListInterface: + return d->listModelInterface->roles(); + case SingleObject: + { + QList<int> rv; + for(int ii = 0; ii < d->roleCache.count(); ++ii) + rv << ii; + return rv; + } + break; + }; + return QList<int>(); +} + +QString QmlListModel::toString(int role) const +{ + d->updateRoleCache(); + switch(modelType()) { + case Invalid: + return QString(); + case SimpleList: + if(role == DATA_ROLE_ID) + return QLatin1String(DATA_ROLE_NAME); + else + return QString(); + case ListInterface: + return d->listModelInterface->toString(role); + case SingleObject: + if(role >= d->roleCache.count()) + return QString(); + else + return d->roleCache.at(role); + }; + return QString(); +} + +/*! + \qmlproperty int ListModel::count + This property holds the number of items in the list. +*/ +int QmlListModel::count() const +{ + switch(modelType()) { + case Invalid: + return 0; + case SimpleList: + return QmlMetaType::listCount(model()); + case ListInterface: + return d->listModelInterface->count(); + case SingleObject: + return 1; + } + return 0; +} + +QHash<int,QVariant> QmlListModel::data(int index, const QList<int> &roles) const +{ + d->updateRoleCache(); + QHash<int, QVariant> rv; + switch(modelType()) { + case Invalid: + break; + case SimpleList: + if(roles.contains(DATA_ROLE_ID)) + rv.insert(DATA_ROLE_ID, QmlMetaType::listAt(d->model, index)); + break; + case ListInterface: + return d->listModelInterface->data(index, roles); + case SingleObject: + { + for(int ii = 0; ii < roles.count(); ++ii) { + QmlMetaProperty prop(d->singleObject, toString(roles.at(ii))); + rv.insert(roles.at(ii), prop.read()); + } + } + break; + }; + + return rv; +} + + + +struct ModelNode; +class ListModel : public QListModelInterface +{ + Q_OBJECT +public: + ListModel(QObject *parent=0); + + virtual QList<int> roles() const; + virtual QString toString(int role) const; + Q_PROPERTY(int count READ count); + virtual int count() const; + virtual QHash<int,QVariant> data(int index, const QList<int> &roles = (QList<int>())) const; + +private: + QVariant valueForNode(ModelNode *) const; + mutable QStringList roleStrings; + friend class ListModelParser; + friend struct ModelNode; + + void checkRoles() const; + void addRole(const QString &) const; + mutable bool _rolesOk; + ModelNode *_root; +}; + +class ModelObject : public QObject +{ + Q_OBJECT +public: + ModelObject(ModelNode *); + + void setValue(const QByteArray &name, const QVariant &val) + { + _mo->setValue(name, val); + } + +private: + ModelNode *_node; + bool _haveProperties; + QmlOpenMetaObject *_mo; +}; + +struct ModelNode +{ + ModelNode(); + ~ModelNode(); + QString className; + + QList<QVariant> values; + QHash<QString, ModelNode *> properties; + + ListModel *model() { + if(!modelCache) { + modelCache = new ListModel; + modelCache->_root = this; + } + return modelCache; + } + + ModelObject *object() { + if(!objectCache) { + objectCache = new ModelObject(this); + QHash<QString, ModelNode *>::iterator it; + for (it = properties.begin(); it != properties.end(); ++it) { + if (!(*it)->values.isEmpty()) + objectCache->setValue(it.key().toLatin1(), (*it)->values.first()); + } + } + return objectCache; + } + + ListModel *modelCache; + ModelObject *objectCache; +}; +Q_DECLARE_METATYPE(ModelNode *); + +ModelObject::ModelObject(ModelNode *node) +: _node(node), _haveProperties(false), _mo(new QmlOpenMetaObject(this)) +{ +} + +QML_DECLARE_TYPE(ListModel); +QML_DEFINE_TYPE(ListModel,ListModel); +ListModel::ListModel(QObject *parent) +: QListModelInterface(parent), _rolesOk(false), _root(0) +{ +} + +void ListModel::checkRoles() const +{ + if(_rolesOk) + return; + + for(int ii = 0; ii < _root->values.count(); ++ii) { + ModelNode *node = qvariant_cast<ModelNode *>(_root->values.at(ii)); + if(node) { + foreach(QString role, node->properties.keys()) + addRole(role); + } + } + + _rolesOk = true; +} + +void ListModel::addRole(const QString &role) const +{ + if(!roleStrings.contains(role)) + roleStrings << role; +} + +QList<int> ListModel::roles() const +{ + checkRoles(); + QList<int> rv; + for(int ii = 0; ii < roleStrings.count(); ++ii) + rv << ii; + return rv; +} + +QString ListModel::toString(int role) const +{ + checkRoles(); + if(role < roleStrings.count()) + return roleStrings.at(role); + else + return QString(); +} + +QVariant ListModel::valueForNode(ModelNode *node) const +{ + QObject *rv = 0; + + if(!node->properties.isEmpty()) { + // Object + rv = node->object(); + } else if(node->values.count() == 0) { + // Invalid + return QVariant(); + } else if(node->values.count() == 1) { + // Value + QVariant &var = node->values[0]; + ModelNode *valueNode = qvariant_cast<ModelNode *>(var); + if(valueNode) { + if(!valueNode->properties.isEmpty()) + rv = valueNode->object(); + else + rv = valueNode->model(); + } else { + return var; + } + } else if(node->values.count() > 1) { + // List + rv = node->model(); + } + + if(rv) + return QVariant::fromValue(rv); + else + return QVariant(); +} + +QHash<int,QVariant> ListModel::data(int index, const QList<int> &roles) const +{ + checkRoles(); + QHash<int, QVariant> rv; + if(index >= count()) + return rv; + + ModelNode *node = qvariant_cast<ModelNode *>(_root->values.at(index)); + if(!node) + return rv; + + for(int ii = 0; ii < roles.count(); ++ii) { + const QString &roleString = roleStrings.at(roles.at(ii)); + + QHash<QString, ModelNode *>::ConstIterator iter = + node->properties.find(roleString); + if(iter != node->properties.end()) { + ModelNode *row = *iter; + rv.insert(roles.at(ii), valueForNode(row)); + } + } + + return rv; +} + +int ListModel::count() const +{ + if(!_root) return 0; + return _root->values.count(); +} + +struct ListInstruction +{ + enum { Push, Pop, Value, Set } type; + int dataIdx; +}; + +class ListModelParser : public QmlCustomParser +{ +public: + virtual QByteArray compile(QXmlStreamReader& reader, bool *); + virtual QVariant create(const QByteArray &); +}; +QML_DEFINE_CUSTOM_PARSER(ListModel, ListModelParser); + +static void dump(ModelNode *node, int ind) +{ + QByteArray indentBa(ind * 4, ' '); + const char *indent = indentBa.constData(); + + for(int ii = 0; ii < node->values.count(); ++ii) { + ModelNode *subNode = qvariant_cast<ModelNode *>(node->values.at(ii)); + if(subNode) { + qWarning().nospace() << indent << "Sub-node " << ii << ": class " << subNode->className; + dump(subNode, ind + 1); + } else { + qWarning().nospace() << indent << "Sub-node " << ii << ": " << node->values.at(ii).toString(); + } + } + + for(QHash<QString, ModelNode *>::ConstIterator iter = node->properties.begin(); iter != node->properties.end(); ++iter) { + qWarning().nospace() << indent << "Property " << iter.key() << ":"; + dump(iter.value(), ind + 1); + } +} + +ModelNode::ModelNode() +: modelCache(0), objectCache(0) +{ +} + +ModelNode::~ModelNode() +{ + qDeleteAll(properties); + for(int ii = 0; ii < values.count(); ++ii) { + ModelNode *node = qvariant_cast<ModelNode *>(values.at(ii)); + if(node) { delete node; node = 0; } + } + if(modelCache) { delete modelCache; modelCache = 0; } +} + +struct ListModelData +{ + int dataOffset; + int id; + int instrCount; + ListInstruction *instructions() const { return (ListInstruction *)((char *)this + sizeof(ListModelData)); } +}; + +QByteArray ListModelParser::compile(QXmlStreamReader& reader, bool *ok) +{ + *ok = true; + + QByteArray id; + QByteArray data; + QList<ListInstruction> instr; + int depth=0; + + while(!reader.atEnd() && depth >= 0) { + switch(reader.readNext()) { + case QXmlStreamReader::StartElement: + { + QStringRef name = reader.name(); + bool isType = name.at(0).isUpper(); + + if (isType) { + ListInstruction li; + li.type = ListInstruction::Push; + li.dataIdx = -1; + instr << li; + + for (int i = 0; i < reader.attributes().count(); ++i) { + const QXmlStreamAttribute &attr = reader.attributes().at(i); + QStringRef attrName = attr.name(); + QStringRef attrValue = attr.value(); + + ListInstruction li; + int ref = data.count(); + data.append(attrName.toString().toLatin1()); + data.append('\0'); + li.type = ListInstruction::Set; + li.dataIdx = ref; + instr << li; + + ref = data.count(); + data.append(attrValue.toString().toLatin1()); + data.append('\0'); + li.type = ListInstruction::Value; + li.dataIdx = ref; + instr << li; + + li.type = ListInstruction::Pop; + li.dataIdx = -1; + instr << li; + } + } else { + ListInstruction li; + int ref = data.count(); + data.append(name.toString().toLatin1()); + data.append('\0'); + li.type = ListInstruction::Set; + li.dataIdx = ref; + instr << li; + } + } + ++depth; + break; + case QXmlStreamReader::EndElement: + { + ListInstruction li; + li.type = ListInstruction::Pop; + li.dataIdx = -1; + instr << li; + --depth; + } + break; + case QXmlStreamReader::Characters: + if (!reader.isWhitespace()) { + int ref = data.count(); + QByteArray d = reader.text().toString().toLatin1(); + d.append('\0'); + data.append(d); + + ListInstruction li; + li.type = ListInstruction::Value; + li.dataIdx = ref; + instr << li; + } + break; + + case QXmlStreamReader::Invalid: + case QXmlStreamReader::NoToken: + case QXmlStreamReader::StartDocument: + case QXmlStreamReader::EndDocument: + case QXmlStreamReader::Comment: + case QXmlStreamReader::DTD: + case QXmlStreamReader::EntityReference: + case QXmlStreamReader::ProcessingInstruction: + break; + } + } + + if (reader.hasError()) + *ok = true; + + if (!*ok) + return QByteArray(); + + int size = sizeof(ListModelData) + + instr.count() * sizeof(ListInstruction) + + data.count(); + + QByteArray rv; + rv.resize(size); + + ListModelData *lmd = (ListModelData *)rv.data(); + if(id.count()) + lmd->id = 0; + else + lmd->id = -1; + lmd->dataOffset = sizeof(ListModelData) + + instr.count() * sizeof(ListInstruction); + lmd->instrCount = instr.count(); + for(int ii = 0; ii < instr.count(); ++ii) + lmd->instructions()[ii] = instr.at(ii); + ::memcpy(rv.data() + lmd->dataOffset, data.constData(), data.count()); + + return rv; +} + +QVariant ListModelParser::create(const QByteArray &d) +{ + ListModel *rv = new ListModel; + ModelNode *root = new ModelNode; + rv->_root = root; + QStack<ModelNode *> nodes; + nodes << root; + + const ListModelData *lmd = (const ListModelData *)d.constData(); + const char *data = ((const char *)lmd) + lmd->dataOffset; + + for(int ii = 0; ii < lmd->instrCount; ++ii) { + const ListInstruction &instr = lmd->instructions()[ii]; + + switch(instr.type) { + case ListInstruction::Push: + { + ModelNode *n = nodes.top(); + ModelNode *n2 = new ModelNode; + n->values << qVariantFromValue(n2); + nodes.push(n2); + } + break; + + case ListInstruction::Pop: + nodes.pop(); + break; + + case ListInstruction::Value: + { + ModelNode *n = nodes.top(); + n->values.append(QByteArray(data + instr.dataIdx)); + } + break; + + case ListInstruction::Set: + { + ModelNode *n = nodes.top(); + ModelNode *n2 = new ModelNode; + n->properties.insert(QLatin1String(data + instr.dataIdx), n2); + nodes.push(n2); + } + break; + } + } + + if(lmd->id != -1) { + QmlContext *ctxt = QmlContext::activeContext(); + ctxt->setContextProperty(QLatin1String(data + lmd->id), rv); + } + + return QVariant::fromValue(rv); +} + +QT_END_NAMESPACE +#include "qmllistmodel.moc" diff --git a/src/declarative/util/qmllistmodel.h b/src/declarative/util/qmllistmodel.h new file mode 100644 index 0000000..3dcac4f --- /dev/null +++ b/src/declarative/util/qmllistmodel.h @@ -0,0 +1,96 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMLLISTMODEL_H +#define QMLLISTMODEL_H + +#include <QObject> +#include <qfxglobal.h> +#include <QStringList> +#include <QHash> +#include <QList> +#include <QVariant> +#include <qml.h> +#include <qlistmodelinterface.h> + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Declarative) +class QmlListModelPrivate; +class Q_DECLARATIVE_EXPORT QmlListModel : public QListModelInterface +{ +Q_OBJECT +public: + QmlListModel(QObject *parent = 0); + virtual ~QmlListModel(); + + enum ModelType { + Invalid, + SimpleList, + ListInterface, + SingleObject + }; + + ModelType modelType() const; + bool setModel(const QVariant &); + QVariant model() const; + + virtual QList<int> roles() const; + virtual QString toString(int role) const; + + Q_PROPERTY(int count READ count); + virtual int count() const; + virtual QHash<int,QVariant> + data(int index, const QList<int> &roles = (QList<int>())) const; +private: + QmlListModelPrivate *d; +}; +QML_DECLARE_TYPE(QmlListModel); + +#endif // QMLLISTMODEL_H + + +QT_END_NAMESPACE + +QT_END_HEADER diff --git a/src/declarative/util/qmlnullablevalue_p.h b/src/declarative/util/qmlnullablevalue_p.h new file mode 100644 index 0000000..f16ddd6 --- /dev/null +++ b/src/declarative/util/qmlnullablevalue_p.h @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMLNULLABLEVALUE_P_H +#define QMLNULLABLEVALUE_P_H + +template<typename T> +struct QmlNullableValue +{ + QmlNullableValue() + : isNull(true), value(T()) {} + QmlNullableValue(const QmlNullableValue<T> &o) + : isNull(o.isNull), value(o.value) {} + QmlNullableValue(const T &t) + : isNull(false), value(t) {} + QmlNullableValue<T> &operator=(const T &t) + { isNull = false; value = t; return *this; } + QmlNullableValue<T> &operator=(const QmlNullableValue<T> &o) + { isNull = o.isNull; value = o.value; return *this; } + operator T() const { return value; } + + void invalidate() { isNull = true; } + bool isValid() const { return !isNull; } + bool isNull; + T value; +}; + +#endif // QMLNULLABLEVALUE_P_H + diff --git a/src/declarative/util/qmlopenmetaobject.cpp b/src/declarative/util/qmlopenmetaobject.cpp new file mode 100644 index 0000000..09d71bd --- /dev/null +++ b/src/declarative/util/qmlopenmetaobject.cpp @@ -0,0 +1,188 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qmlopenmetaobject.h" +#include <QDebug> + + +QT_BEGIN_NAMESPACE +QmlOpenMetaObject::QmlOpenMetaObject(QObject *obj, bool automatic) +: autoCreate(automatic), parent(0), mem(0), _object(obj) +{ + mob.setSuperClass(obj->metaObject()); + mob.setFlags(QMetaObjectBuilder::DynamicMetaObject); + + QObjectPrivate *op = QObjectPrivate::get(obj); + if(op->metaObject) + mob.setSuperClass(op->metaObject); + + mem = mob.toMetaObject(); + *static_cast<QMetaObject *>(this) = *mem; + op->metaObject = this; + _propertyOffset = propertyOffset(); + _signalOffset = methodOffset(); +} + +QmlOpenMetaObject::~QmlOpenMetaObject() +{ + if(parent) + delete parent; + qFree(mem); +} + +int QmlOpenMetaObject::metaCall(QMetaObject::Call c, int id, void **a) +{ + if(( c == QMetaObject::ReadProperty || c == QMetaObject::WriteProperty) + && id >= _propertyOffset) { + int propId = id - _propertyOffset; + if(c == QMetaObject::ReadProperty) { + propertyRead(propId); + *reinterpret_cast<QVariant *>(a[0]) = data[propId]; + } else if(c == QMetaObject::WriteProperty) { + if(data[propId] != *reinterpret_cast<QVariant *>(a[0])) { + propertyWrite(propId); + data[propId] = *reinterpret_cast<QVariant *>(a[0]); + activate(_object, _signalOffset + propId, 0); + } + } + return -1; + } else { + if(parent) + return parent->metaCall(c, id, a); + else + return _object->qt_metacall(c, id, a); + } +} + +QVariant QmlOpenMetaObject::value(int id) const +{ + Q_ASSERT(id >= 0 && id < data.count()); + return data.at(id); +} + +void QmlOpenMetaObject::setValue(int id, const QVariant &value) +{ + Q_ASSERT(id >= 0 && id < data.count()); + data[id] = value; + activate(_object, id + _signalOffset, 0); +} + +QVariant QmlOpenMetaObject::value(const QByteArray &name) const +{ + QHash<QByteArray, int>::ConstIterator iter = names.find(name); + if(iter == names.end()) + return QVariant(); + + return data.at(*iter); +} + +void QmlOpenMetaObject::setValue(const QByteArray &name, const QVariant &val) +{ + QHash<QByteArray, int>::ConstIterator iter = names.find(name); + + int id = -1; + if(iter == names.end()) { + id = doCreateProperty(name.constData()) - _propertyOffset; + } else { + id = *iter; + } + + if(data[id] == val) + return; + + data[id] = val; + activate(_object, id + _signalOffset, 0); +} + +int QmlOpenMetaObject::createProperty(const char *name, const char *) +{ + if(autoCreate) + return doCreateProperty(name); + else + return -1; +} + +int QmlOpenMetaObject::doCreateProperty(const char *name) +{ + int id = mob.propertyCount(); + mob.addSignal("__" + QByteArray::number(id) + "()"); + QMetaPropertyBuilder build = mob.addProperty(name, "QVariant", id); + build.setDynamic(true); + data << propertyCreated(id, build); + qFree(mem); + mem = mob.toMetaObject(); + *static_cast<QMetaObject *>(this) = *mem; + names.insert(name, id); + + return _propertyOffset + id; +} + +void QmlOpenMetaObject::propertyRead(int) +{ +} + +void QmlOpenMetaObject::propertyWrite(int) +{ +} + +QVariant QmlOpenMetaObject::propertyCreated(int, QMetaPropertyBuilder &) +{ + return QVariant(); +} + +int QmlOpenMetaObject::count() const +{ + return data.count(); +} + +QByteArray QmlOpenMetaObject::name(int idx) const +{ + Q_ASSERT(idx >= 0 && idx < data.count()); + + return mob.property(idx).name(); +} + +QObject *QmlOpenMetaObject::object() const +{ + return _object; +} + +QT_END_NAMESPACE diff --git a/src/declarative/util/qmlopenmetaobject.h b/src/declarative/util/qmlopenmetaobject.h new file mode 100644 index 0000000..17cecd87 --- /dev/null +++ b/src/declarative/util/qmlopenmetaobject.h @@ -0,0 +1,96 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMLOPENMETAOBJECT_H +#define QMLOPENMETAOBJECT_H + +#include <QMetaObject> +#include "private/qmetaobjectbuilder_p.h" +#include <private/qobject_p.h> +#include <QObject> + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Declarative) +class Q_DECLARATIVE_EXPORT QmlOpenMetaObject : public QAbstractDynamicMetaObject +{ +public: + QmlOpenMetaObject(QObject *, bool = true); + ~QmlOpenMetaObject(); + + QVariant value(const QByteArray &) const; + void setValue(const QByteArray &, const QVariant &); + QVariant value(int) const; + void setValue(int, const QVariant &); + + int count() const; + QByteArray name(int) const; + + QObject *object() const; +protected: + virtual int metaCall(QMetaObject::Call _c, int _id, void **_a); + virtual int createProperty(const char *, const char *); + + virtual void propertyRead(int); + virtual void propertyWrite(int); + virtual QVariant propertyCreated(int, QMetaPropertyBuilder &); + +private: + int doCreateProperty(const char *); + bool autoCreate; + QAbstractDynamicMetaObject *parent; + int _propertyOffset; + int _signalOffset; + QList<QVariant> data; + QHash<QByteArray, int> names; + QMetaObjectBuilder mob; + QMetaObject *mem; + QObject *_object; +}; + + +QT_END_NAMESPACE + +QT_END_HEADER +#endif // QMLOPENMETAOBJECT_H diff --git a/src/declarative/util/qmlpackage.cpp b/src/declarative/util/qmlpackage.cpp new file mode 100644 index 0000000..264d186 --- /dev/null +++ b/src/declarative/util/qmlpackage.cpp @@ -0,0 +1,148 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "private/qobject_p.h" +#include "qmlpackage.h" + + +QT_BEGIN_NAMESPACE +class QmlPackagePrivate : public QObjectPrivate +{ +public: + QmlPackagePrivate() {} + + QmlConcreteList<QObject *> dataList; +}; + +class QmlPackageAttached : public QObject +{ +Q_OBJECT +public: + QmlPackageAttached(QObject *parent); + virtual ~QmlPackageAttached(); + + Q_PROPERTY(QString name READ name WRITE setName); + QString name() const; + void setName(const QString &n); + + static QHash<QObject *, QmlPackageAttached *> attached; +private: + QString _name; +}; + +QHash<QObject *, QmlPackageAttached *> QmlPackageAttached::attached; + +QmlPackageAttached::QmlPackageAttached(QObject *parent) +: QObject(parent) +{ + attached.insert(parent, this); +} + +QmlPackageAttached::~QmlPackageAttached() +{ + attached.remove(parent()); +} + +QString QmlPackageAttached::name() const +{ + return _name; +} + +void QmlPackageAttached::setName(const QString &n) +{ + _name = n; +} + +QmlPackage::QmlPackage(QObject *parent) + : QObject(*(new QmlPackagePrivate), parent) +{ +} + +QmlPackage::~QmlPackage() +{ +} + +QmlList<QObject *> *QmlPackage::data() +{ + Q_D(QmlPackage); + return &d->dataList; +} + +bool QmlPackage::hasPart(const QString &name) +{ + Q_D(QmlPackage); + for(int ii = 0; ii < d->dataList.count(); ++ii) { + QObject *obj = d->dataList.at(ii); + QmlPackageAttached *a = QmlPackageAttached::attached.value(obj); + if(a && a->name() == name) + return true; + } + return false; +} + +QObject *QmlPackage::part(const QString &name) +{ + Q_D(QmlPackage); + if(name.isEmpty() && !d->dataList.isEmpty()) + return d->dataList.at(0); + + for(int ii = 0; ii < d->dataList.count(); ++ii) { + QObject *obj = d->dataList.at(ii); + QmlPackageAttached *a = QmlPackageAttached::attached.value(obj); + if(a && a->name() == name) + return obj; + } + + if(name == QLatin1String("default") && !d->dataList.isEmpty()) + return d->dataList.at(0); + + return 0; +} + +QObject *QmlPackage::qmlAttachedProperties(QObject *o) +{ + return new QmlPackageAttached(o); +} + +QML_DEFINE_TYPE(QmlPackage, Package); + +QT_END_NAMESPACE +#include "qmlpackage.moc" diff --git a/src/declarative/util/qmlpackage.h b/src/declarative/util/qmlpackage.h new file mode 100644 index 0000000..6652b98 --- /dev/null +++ b/src/declarative/util/qmlpackage.h @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMLPACKAGE_H +#define QMLPACKAGE_H + +#include <qml.h> + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Declarative) +/***************************************************************************** + ***************************************************************************** + XXX Experimental + ***************************************************************************** +*****************************************************************************/ + +class QmlPackagePrivate; +class QmlPackage : public QObject +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QmlPackage) + + Q_CLASSINFO("DefaultProperty", "data"); + Q_PROPERTY(QmlList<QObject *> *data READ data SCRIPTABLE false); + +public: + QmlPackage(QObject *parent=0); + virtual ~QmlPackage(); + + QmlList<QObject *> *data(); + + QObject *part(const QString & = QString()); + bool hasPart(const QString &); + + static QObject *qmlAttachedProperties(QObject *); +}; +QML_DECLARE_TYPE(QmlPackage); + +#endif // QMLPACKAGE_H + + +QT_END_NAMESPACE + +QT_END_HEADER diff --git a/src/declarative/util/qmlscript.cpp b/src/declarative/util/qmlscript.cpp new file mode 100644 index 0000000..a24c427 --- /dev/null +++ b/src/declarative/util/qmlscript.cpp @@ -0,0 +1,219 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <qmlbindablevalue.h> +#include <QtDeclarative/qmlengine.h> +#include <QtDeclarative/qmlcontext.h> +#include <private/qobject_p.h> +#include <QtCore/qfile.h> +#include <QtCore/qdebug.h> +#include <QtScript/qscriptvalue.h> +#include <QtScript/qscriptcontext.h> +#include <QtScript/qscriptengine.h> +#include <private/qmlnullablevalue_p.h> +#include <private/qmlengine_p.h> +#include <private/qmlcontext_p.h> +#include "qmlscript.h" +#include <QNetworkReply> +#include <QNetworkRequest> +#include <QtDeclarative/qmlinfo.h> + +QT_BEGIN_NAMESPACE + + + +class QmlScriptPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QmlScript); + +public: + QmlScriptPrivate() : reply(0), ctxt(0) {} + + void addScriptToEngine(const QString &, const QString &fileName=QString()); + + QString script; + QString source; + QNetworkReply *reply; + QUrl url; + QmlContext *ctxt; +}; + +/*! + \qmlclass Script QmlScript + \brief The Script element adds JavaScript snippets. + \ingroup utility + + QmlScript is used to add convenient JavaScript "glue" methods to + your Qt Declarative application or component. While you can have any JavaScript code + within a QmlScript, it is best to limit yourself to defining functions. + + \qml + <Script> + function debugMyComponent() { + print(text.text); + print(otherinterestingitem.property); + } + </Script> + <MouseRegion onClicked="debugMyComponent()" /> + \endqml + + \note QmlScript executes JavaScript as soon as it is specified. + When defining a component, this may be before the execution context is + fully specified. As a result some properties or items may not be + accessible. By limiting your JavaScript to defining functions that are + only executed later once the context is fully defined, this problem is + avoided. +*/ + +QML_DEFINE_TYPE(QmlScript,Script); +QmlScript::QmlScript(QObject *parent) : QObject(*(new QmlScriptPrivate), parent) +{ + Q_D(QmlScript); + d->ctxt = QmlContext::activeContext(); +} + +/*! + \qmlproperty string Script::script + \default + JavaScript code to execute. +*/ +/*! + \property QmlScript::script + \brief a script snippet. +*/ +QString QmlScript::script() const +{ + Q_D(const QmlScript); + return d->script; +} + +void QmlScript::setScript(const QString &script) +{ + Q_D(QmlScript); + d->script = script; + d->addScriptToEngine(d->script); +} + +/*! + \qmlproperty string Script::source + + Setting this property causes the Script element to read JavaScript code from + the file specified. + */ +/*! + \property QmlScript::source + \brief the path to a script file. +*/ +QString QmlScript::source() const +{ + Q_D(const QmlScript); + return d->source; +} + +void QmlScript::setSource(const QString &source) +{ + Q_D(QmlScript); + if (d->source == source) + return; + d->source = source; + d->url = d->ctxt->resolvedUrl(source); + QNetworkRequest req(d->url); + req.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache); + d->reply = d->ctxt->engine()->networkAccessManager()->get(req); + QObject::connect(d->reply, SIGNAL(finished()), + this, SLOT(replyFinished())); +} + +void QmlScript::replyFinished() +{ + Q_D(QmlScript); + if (!d->reply->error()) { + QByteArray ba = d->reply->readAll(); + d->addScriptToEngine(QString::fromUtf8(ba), d->source); + } + d->reply->deleteLater(); + d->reply = 0; +} + +void QmlScriptPrivate::addScriptToEngine(const QString &script, const QString &fileName) +{ + Q_Q(QmlScript); + QmlEngine *engine = ctxt->engine(); + QScriptEngine *scriptEngine = engine->scriptEngine(); + + QScriptContext *currentContext = engine->scriptEngine()->currentContext(); + QScriptValueList oldScopeChain = currentContext->scopeChain(); + QScriptValue oldact = currentContext->activationObject(); + + for (int i = 0; i < oldScopeChain.size(); ++i) { + currentContext->popScope(); + } + for (int i = ctxt->d_func()->scopeChain.size() - 1; i > -1; --i) { + currentContext->pushScope(ctxt->d_func()->scopeChain.at(i)); + } + + currentContext->setActivationObject(ctxt->d_func()->scopeChain.at(0)); + + QScriptValue val = scriptEngine->evaluate(script, fileName); + if (scriptEngine->hasUncaughtException()) { + if (scriptEngine->uncaughtException().isError()){ + QScriptValue exception = scriptEngine->uncaughtException(); + if(!exception.property(QLatin1String("fileName")).toString().isEmpty()){ + qWarning() << exception.property(QLatin1String("fileName")).toString() + << scriptEngine->uncaughtExceptionLineNumber() + << exception.toString(); + + } else { + qmlInfo(q) << exception.toString(); + } + } + } + + currentContext->setActivationObject(oldact); + + for (int i = 0; i < ctxt->d_func()->scopeChain.size(); ++i) + currentContext->popScope(); + + for (int i = oldScopeChain.size() - 1; i > -1; --i) + currentContext->pushScope(oldScopeChain.at(i)); +} + +QT_END_NAMESPACE diff --git a/src/declarative/util/qmlscript.h b/src/declarative/util/qmlscript.h new file mode 100644 index 0000000..fc038b4 --- /dev/null +++ b/src/declarative/util/qmlscript.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMLSCRIPT_H +#define QMLSCRIPT_H + +#include <qfxglobal.h> +#include <QtCore/qobject.h> +#include "qml.h" + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +QT_MODULE(Declarative) + +class QmlScriptPrivate; +class Q_DECLARATIVE_EXPORT QmlScript : public QObject +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QmlScript); + + Q_PROPERTY(QString script READ script WRITE setScript); + Q_PROPERTY(QString src READ source WRITE setSource); + Q_CLASSINFO("DefaultProperty", "script"); + +public: + QmlScript(QObject *parent=0); + + QString script() const; + void setScript(const QString &); + + QString source() const; + void setSource(const QString &); + +private Q_SLOTS: + void replyFinished(); +}; +QML_DECLARE_TYPE(QmlScript); + +QT_END_NAMESPACE +QT_END_HEADER +#endif diff --git a/src/declarative/util/qmlsetproperties.cpp b/src/declarative/util/qmlsetproperties.cpp new file mode 100644 index 0000000..f385391 --- /dev/null +++ b/src/declarative/util/qmlsetproperties.cpp @@ -0,0 +1,247 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "private/qobject_p.h" +#include "qmlopenmetaobject.h" +#include "qmlsetproperties.h" +#include <QtCore/qdebug.h> +#include <QtDeclarative/qmlinfo.h> + + +QT_BEGIN_NAMESPACE +class QmlSetPropertiesMetaObject : public QmlOpenMetaObject +{ +public: + QmlSetPropertiesMetaObject(QObject *); + +protected: + virtual void propertyRead(int); + virtual void propertyWrite(int); +}; + +class QmlSetPropertiesProxyObject : public QObject +{ +Q_OBJECT +public: + QmlSetPropertiesProxyObject(QObject *); + + QmlSetPropertiesMetaObject *fxMetaObject() const { return _mo; } +private: + QmlSetPropertiesMetaObject *_mo; +}; + +QmlSetPropertiesProxyObject::QmlSetPropertiesProxyObject(QObject *parent) +: QObject(parent), _mo(new QmlSetPropertiesMetaObject(this)) +{ +} + +QmlSetPropertiesMetaObject::QmlSetPropertiesMetaObject(QObject *obj) +: QmlOpenMetaObject(obj) +{ +} + +void QmlSetPropertiesMetaObject::propertyRead(int id) +{ + if(!value(id).isValid()) + setValue(id, QVariant::fromValue((QObject *)new QmlSetPropertiesProxyObject(object()))); + + QmlOpenMetaObject::propertyRead(id); +} + +void QmlSetPropertiesMetaObject::propertyWrite(int id) +{ + if(value(id).userType() == qMetaTypeId<QObject *>()) { + QObject *val = qvariant_cast<QObject *>(value(id)); + QmlSetPropertiesProxyObject *proxy = qobject_cast<QmlSetPropertiesProxyObject *>(val); + if(proxy) { + setValue(id, QVariant()); + delete proxy; + } + } + QmlOpenMetaObject::propertyWrite(id); +} + +/*! + \qmlclass SetProperties QmlSetProperties + \brief The SetProperties element describes new property values for a state. + + SetProperties is a convenience element for changing many properties on a single + object. It allows you to specify the property names and values similar to how + you normally would specify them for the actual item: + + \code + <SetProperties target="{myRect}" x="52" y="300" width="48"/> + \endcode + + \c target is a property of \c SetProperties, so if the property you want to change + is named \e target you will have to use \l SetProperty instead. You should also + use \l SetProperty if you want to update the binding for a property, + as SetProperties does not support this. +*/ + +/*! + \internal + \class QmlSetProperties + \brief The QmlSetProperties class describes new property values for a state. + + \ingroup states + + QmlSetProperties is a convenience class for changing many properties on a single + object. It allows you to specify the property names and values similar to how + you normally would specify them for the actual item: + + \code + <SetProperties target="{myRect}" x="52" y="300" width="48"/> + \endcode + + \c target is a property of \c SetProperties, so if the property you want to change + is named \e target you will have to use QmlSetProperty instead. You should also use QmlSetProperty + if you want to update the binding for a property, as QmlSetProperties does not support this. + + \sa QmlSetProperty +*/ + +class QmlSetPropertiesPrivate : public QObjectPrivate +{ +public: + QmlSetPropertiesPrivate() : obj(0), mo(0) {} + + QObject *obj; + QmlSetPropertiesMetaObject *mo; +}; + +QML_DEFINE_TYPE(QmlSetProperties,SetProperties); +QmlSetProperties::QmlSetProperties() + : QmlStateOperation(*(new QmlSetPropertiesPrivate)) +{ + Q_D(QmlSetProperties); + d->mo = new QmlSetPropertiesMetaObject(this); +} + +QmlSetProperties::QmlSetProperties(QObject *parent) + : QmlStateOperation(*(new QmlSetPropertiesPrivate), parent) +{ + Q_D(QmlSetProperties); + d->mo = new QmlSetPropertiesMetaObject(this); +} + +QmlSetProperties::~QmlSetProperties() +{ +} + +/*! + \qmlproperty Object SetProperties::target + This property holds the object that the properties to change belong to +*/ + +/*! + \property QmlSetProperties::target + \brief the object that the properties to change belong to +*/ +QObject *QmlSetProperties::object() +{ + Q_D(QmlSetProperties); + return d->obj; +} + +void QmlSetProperties::setObject(QObject *o) +{ + Q_D(QmlSetProperties); + d->obj = o; +} + +QmlSetProperties::ActionList +QmlSetProperties::doAction(QmlSetPropertiesMetaObject *metaObject, + QObject *object) +{ + ActionList list; + + for (int ii = 0; ii < metaObject->count(); ++ii) { + + QByteArray name = metaObject->name(ii); + QVariant value = metaObject->value(ii); + + QmlSetPropertiesProxyObject *po = qobject_cast<QmlSetPropertiesProxyObject *>(qvariant_cast<QObject *>(value)); + + QmlMetaProperty prop(object, QLatin1String(name)); + + if(po) { + QObject *objVal = QmlMetaType::toQObject(prop.read()); + if(!objVal) { + qmlInfo(this) << object->metaObject()->className() + << "has no object property named" << name; + continue; + } + + list << doAction(po->fxMetaObject(), objVal); + } else if (!prop.isValid()) { + qmlInfo(this) << object->metaObject()->className() + << "has no property named" << name; + continue; + } else if (!prop.isWritable()) { + qmlInfo(this) << object->metaObject()->className() + << name << "is not writable, and cannot be set."; + continue; + } else { + //append action + Action a; + a.property = prop; + a.fromValue = prop.read(); + a.toValue = value; + + list << a; + } + } + + return list; +} + +QmlSetProperties::ActionList QmlSetProperties::actions() +{ + Q_D(QmlSetProperties); + if (!d->obj) + return ActionList(); + + return doAction(d->mo, d->obj); +} + +QT_END_NAMESPACE +#include "qmlsetproperties.moc" diff --git a/src/declarative/util/qmlsetproperties.h b/src/declarative/util/qmlsetproperties.h new file mode 100644 index 0000000..456b672 --- /dev/null +++ b/src/declarative/util/qmlsetproperties.h @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMLSETPROPERTIES_H +#define QMLSETPROPERTIES_H + +#include <qmlstateoperations.h> + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Declarative) +class QmlSetPropertiesMetaObject; +class QmlSetPropertiesPrivate; +class Q_DECLARATIVE_EXPORT QmlSetProperties : public QmlStateOperation +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QmlSetProperties); + + Q_PROPERTY(QObject *target READ object WRITE setObject); + +public: + QmlSetProperties(); + QmlSetProperties(QObject *parent); + ~QmlSetProperties(); + + QObject *object(); + void setObject(QObject *); + + virtual ActionList actions(); + +private: + ActionList doAction(QmlSetPropertiesMetaObject *, QObject *); + //QmlSetProperties::ActionList appendDotActions(const QVariant &, const QVariant &); +}; +QML_DECLARE_TYPE(QmlSetProperties); + +#endif // QMLSETPROPERTIES_H + + +QT_END_NAMESPACE + +QT_END_HEADER diff --git a/src/declarative/util/qmlstate.cpp b/src/declarative/util/qmlstate.cpp new file mode 100644 index 0000000..50ae6b5 --- /dev/null +++ b/src/declarative/util/qmlstate.cpp @@ -0,0 +1,469 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <gfxeasing.h> +#include "qmltransition.h" +#include "qmlstategroup.h" +#include "qmlstate_p.h" +#include "qmlbindablevalue.h" +#include "qmlstateoperations.h" +#include "qmlanimation.h" +#include "qmlanimation_p.h" +#include "qmlstate.h" +#include <QtCore/qdebug.h> + +QT_BEGIN_NAMESPACE + +DEFINE_BOOL_CONFIG_OPTION(stateChangeDebug, STATECHANGE_DEBUG); + +Action::Action() : bv(0), event(0), actionDone(false) +{ +} + +ActionEvent::~ActionEvent() +{ +} + +QString ActionEvent::name() const +{ + return QString(); +} + +void ActionEvent::execute() +{ +} + +/*! + \internal +*/ +QmlStateOperation::QmlStateOperation(QObjectPrivate &dd, QObject *parent) + : QObject(dd, parent) +{ +} + +/*! + \qmlclass State + \brief The State element defines configurations of objects and properties. + + A state is specified as a set of batched changes from the default configuration. + + Note that setting the state of an object from within another state of the same object is + inadvisible. Not only would this have the same effect as going directly to the second state + it may cause the program to crash. + + \sa {states-transitions}{States and Transitions} +*/ + +/*! + \internal + \class QmlState + \brief The QmlState class allows you to define configurations of objects and properties. + + \ingroup states + + QmlState allows you to specify a state as a set of batched changes from the default + configuration. + + \sa {states-transitions}{States and Transitions} +*/ + +QML_DEFINE_TYPE(QmlState,State); +QmlState::QmlState(QObject *parent) +: QObject(*(new QmlStatePrivate), parent) +{ +} + +QmlState::~QmlState() +{ +} + +/*! + \qmlproperty string State::name + This property holds the name of the state + + Each state should have a unique name. +*/ + +/*! + \property QmlState::name + \brief the name of the state + + Each state should have a unique name. +*/ +QString QmlState::name() const +{ + Q_D(const QmlState); + return d->name; +} + +void QmlState::setName(const QString &n) +{ + Q_D(QmlState); + d->name = n; +} + +bool QmlState::isWhenKnown() const +{ + Q_D(const QmlState); + return d->when != 0; +} + +/*! + \qmlproperty bool State::when + This property holds when the state should be applied + + This should be set to an expression that evaluates to true when you want the state to + be applied. +*/ + +/*! + \property QmlState::when + \brief when the state should be applied + + This should be set to an expression that evaluates to true when you want the state to + be applied. +*/ +QmlBindableValue *QmlState::when() const +{ + Q_D(const QmlState); + return d->when; +} + +void QmlState::setWhen(QmlBindableValue *when) +{ + Q_D(QmlState); + d->when = when; + if(d->group) + d->group->updateAutoState(); +} + +/*! + \advanced + \qmlproperty string State::extends + This property holds the state that this state extends + + The state being extended is treated as the base state in regards to + the changes specified by the extending state. +*/ + +/*! + \property QmlState::extends + \brief the state that this state extends + + The state being extended is treated as the base state in regards to + the changes specified by the extending state. + + \sa operations +*/ +QString QmlState::extends() const +{ + Q_D(const QmlState); + return d->extends; +} + +void QmlState::setExtends(const QString &extends) +{ + Q_D(QmlState); + d->extends = extends; +} + +/*! + \qmlproperty list<StateOperation> State::operations + This property holds the changes to apply for this state + \default + + By default these changes are applied against the default state. If the state + extends another state, then the changes are applied against the state being + extended. +*/ + +/*! + \property QmlState::operations + \brief the changes to apply for this state + + By default these changes are applied against the default state. If the state + extends another state, then the changes are applied against the state being + extended. +*/ +QmlList<QmlStateOperation *> *QmlState::operations() +{ + Q_D(QmlState); + return &d->operations; +} + +QmlState &QmlState::operator<<(QmlStateOperation *op) +{ + Q_D(QmlState); + d->operations.append(op); + return *this; +} + +#if 0 +static void dump(const QmlStateOperation::ActionList &list) +{ + if(!QString(getenv("STATE_DEBUG")).isEmpty()) + return; + + for(int ii = 0; ii < list.count(); ++ii) { + const Action &action = list.at(ii); + qWarning() << action.property.object << action.property.name << action.toValue; + } +} +#endif + +void QmlStatePrivate::complete() +{ + Q_Q(QmlState); + //apply bindings (now that all transitions are complete) + ////////////////////////////////////////////////////////// + foreach(const Action &action, bindingsList) { + if (action.bv && !action.toBinding.isEmpty()) { + action.bv->setExpression(action.toBinding); + } + } + ////////////////////////////////////////////////////////// + + for(int ii = 0; ii < reverting.count(); ++ii) { + for(int jj = 0; jj < revertList.count(); ++jj) { + if(revertList.at(jj).property == reverting.at(ii)) { + revertList.removeAt(jj); + break; + } + } + } + reverting.clear(); + + for(int ii = 0; ii < completeList.count(); ++ii) { + const QmlMetaProperty &prop = completeList.at(ii).property; + prop.write(completeList.at(ii).value); + } + + completeList.clear(); + transition = 0; + emit q->completed(); +} + +QmlStateOperation::ActionList QmlStatePrivate::generateActionList(QmlStateGroup *group) const +{ + QmlStateOperation::ActionList applyList; + if(inState) + return applyList; + + inState = true; + + if(!extends.isEmpty()) { + QList<QmlState *> states = group->states(); + for(int ii = 0; ii < states.count(); ++ii) + if(states.at(ii)->name() == extends) + applyList = static_cast<QmlStatePrivate*>(states.at(ii)->d_ptr)->generateActionList(group); + } + + foreach(QmlStateOperation *op, operations) + applyList << op->actions(); + + inState = false; + return applyList; +} + +QmlStateGroup *QmlState::stateGroup() const +{ + Q_D(const QmlState); + return d->group; +} + +void QmlState::setStateGroup(QmlStateGroup *group) +{ + Q_D(QmlState); + d->group = group; +} + +void QmlState::cancel() +{ + Q_D(QmlState); + if (d->transition) { + d->transition->stop(); //XXX this could potentially trigger a complete in rare circumstances + d->transition = 0; + } +} + +void QmlState::apply(QmlStateGroup *group, QmlTransition *trans, QmlState *revert) +{ + Q_D(QmlState); + + cancel(); + if(revert) + revert->cancel(); + d->revertList.clear(); + d->reverting.clear(); + d->bindingsList.clear(); + + if(revert) + d->revertList = static_cast<QmlStatePrivate*>(revert->d_ptr)->revertList; + QmlStateOperation::RevertActionList additionalReverts; + + QmlStateOperation::ActionList applyList = d->generateActionList(group); + + for(int ii = 0; ii < applyList.count(); ++ii) { + const Action &action = applyList.at(ii); + if(action.event) + continue; + + bool found = false; + for(int jj = 0; !found && jj < d->revertList.count(); ++jj) { + if(d->revertList.at(jj).property == action.property) + found = true; + } + if(!found) { + RevertAction r(action); + additionalReverts << r; + } + } + for(int ii = 0; ii < d->revertList.count(); ++ii) { + bool found = false; + for(int jj = 0; !found && jj < applyList.count(); ++jj) { + const Action &action = applyList.at(jj); + if(action.property == d->revertList.at(ii).property) + found = true; + } + if(!found) { + QVariant cur = d->revertList.at(ii).property.read(); + Action a; + a.property = d->revertList.at(ii).property; + a.fromValue = cur; + a.toValue = d->revertList.at(ii).value; + a.toBinding = d->revertList.at(ii).binding; + if (!a.toBinding.isEmpty()) { + a.fromBinding = d->revertList.at(ii).bv->expression(); //### relies on clearExpression not clearing string + a.bv = d->revertList.at(ii).bv; + } + applyList << a; + d->reverting << d->revertList.at(ii).property; + } + } + d->revertList << additionalReverts; + + //apply all changes, and work out any ending positions for bindings + //then rewind all changes and proceed as normal + //### 4 foreach loops! + //////////////////////////////////////////////////////////////////// + foreach(const Action &action, applyList) { + if(stateChangeDebug()) + qWarning() << " Action:" << action.property.object() << action.property.name() << action.toValue; + + if (action.bv && !action.toBinding.isEmpty()) { + d->bindingsList << action; + action.bv->clearExpression(); + } + } + + if (!d->bindingsList.isEmpty()) { + foreach(const Action &action, applyList) { + if (action.bv && !action.toBinding.isEmpty()) { + action.bv->setExpression(action.toBinding); + } else if(!action.event) { + action.property.write(action.toValue); + } + } + + for (int ii = 0; ii < applyList.size(); ++ii) { + Action *action = &applyList[ii]; + if(action->event) + continue; + + const QmlMetaProperty &prop = action->property; + if (action->bv && !action->toBinding.isEmpty()) { + action->toValue = prop.read(); + } + } + + foreach(const Action &action, applyList) { + if(action.event) + continue; + + if (action.bv && !action.toBinding.isEmpty()) + action.bv->clearExpression(); + action.property.write(action.fromValue); + } + } + //////////////////////////////////////////////////////////////////// + + QmlStateOperation::ActionList modList = applyList; + QList<QmlMetaProperty> touched; + d->completeList.clear(); + if(trans) { + d->transition = trans; + trans->prepare(modList, touched, this); + for(int ii = 0; ii < modList.count(); ++ii) { + const Action &action = modList.at(ii); + + if(action.event) { + if(action.actionDone) { + modList.removeAt(ii); + --ii; + } + } else { + if(action.toValue != action.fromValue) { + d->completeList << RevertAction(action, false); + } + + if(touched.contains(action.property)) { + modList.removeAt(ii); + --ii; + } + } + } + } + + foreach(const Action &action, modList) { + if(action.event) + action.event->execute(); + else + action.property.write(action.toValue); + } +} + +QML_DEFINE_TYPE(QmlStateOperation,StateOperation); +QmlStateOperation::ActionList QmlStateOperation::actions() +{ + return ActionList(); +} + +QT_END_NAMESPACE diff --git a/src/declarative/util/qmlstate.h b/src/declarative/util/qmlstate.h new file mode 100644 index 0000000..3e6727d --- /dev/null +++ b/src/declarative/util/qmlstate.h @@ -0,0 +1,175 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMLSTATE_H +#define QMLSTATE_H + +#include <QtCore/qobject.h> +#include <qfxglobal.h> +#include <gfxtimeline.h> +#include <qml.h> +#include <QSequentialAnimationGroup> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Declarative) + +class ActionEvent; +class QmlBindableValue; +class Action +{ +public: + Action(); + + QmlMetaProperty property; + QVariant fromValue; + QVariant toValue; + QString fromBinding; + QString toBinding; + QmlBindableValue *bv; + ActionEvent *event; + bool actionDone; +}; + +class ActionEvent +{ +public: + virtual ~ActionEvent(); + virtual QString name() const; + virtual void execute(); +}; + +class RevertAction +{ +public: + RevertAction(const Action &a, bool from = true) : bv(0) + { + property = a.property; + if (from) { + value = a.fromValue; + binding = a.fromBinding; + } else { + value = a.toValue; + binding = a.toBinding; + } + bv = a.bv; + } + + QmlMetaProperty property; + QVariant value; + QString binding; + QmlBindableValue *bv; +}; + +class QmlStateGroup; +class Q_DECLARATIVE_EXPORT QmlStateOperation : public QObject +{ + Q_OBJECT +public: + QmlStateOperation(QObject *parent = 0) + : QObject(parent) {} + typedef QList<Action> ActionList; + typedef QList<RevertAction> RevertActionList; + + virtual ActionList actions(); + +protected: + QmlStateOperation(QObjectPrivate &dd, QObject *parent = 0); +}; +QML_DECLARE_TYPE(QmlStateOperation); + +typedef QmlStateOperation::ActionList QmlStateActions; + +class QmlTransition; +class QmlTransitionPrivate; +class QmlStatePrivate; +class Q_DECLARATIVE_EXPORT QmlState : public QObject +{ + Q_OBJECT + + Q_PROPERTY(QString name READ name WRITE setName); + Q_PROPERTY(QmlBindableValue *when READ when WRITE setWhen); + Q_PROPERTY(QString extends READ extends WRITE setExtends); + Q_PROPERTY(QmlList<QmlStateOperation *>* operations READ operations); + Q_CLASSINFO("DefaultProperty", "operations"); + +public: + QmlState(QObject *parent=0); + virtual ~QmlState(); + + QString name() const; + void setName(const QString &); + + /*'when' is a QmlBindableValue to limit state changes oscillation + due to the unpredictable order of evaluation of bound expressions*/ + bool isWhenKnown() const; + QmlBindableValue *when() const; + void setWhen(QmlBindableValue *); + + QString extends() const; + void setExtends(const QString &); + + QmlList<QmlStateOperation *> *operations(); + QmlState &operator<<(QmlStateOperation *); + + void apply(QmlStateGroup *, QmlTransition *, QmlState *revert); + void cancel(); + + QmlStateGroup *stateGroup() const; + void setStateGroup(QmlStateGroup *); + +Q_SIGNALS: + void completed(); + +private: + Q_DECLARE_PRIVATE(QmlState) + Q_DISABLE_COPY(QmlState) + friend class QmlTransitionPrivate; +}; +QML_DECLARE_TYPE(QmlState); + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QMLSTATE_H diff --git a/src/declarative/util/qmlstate_p.h b/src/declarative/util/qmlstate_p.h new file mode 100644 index 0000000..20d1c1a --- /dev/null +++ b/src/declarative/util/qmlstate_p.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMLSTATE_P_H +#define QMLSTATE_P_H + +#include <qmlstate.h> +#include "private/qobject_p.h" +#include "private/qmlanimation_p.h" + +QT_BEGIN_NAMESPACE + +class QmlStatePrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QmlState); + +public: + QmlStatePrivate() + : when(0), transition(0), inState(false), group(0) {} + + QString name; + QmlBindableValue *when; + QmlConcreteList<QmlStateOperation *> operations; + QmlTransition *transition; + QmlStateOperation::RevertActionList revertList; + QList<QmlMetaProperty> reverting; + QmlStateOperation::RevertActionList completeList; + QmlStateOperation::ActionList bindingsList; + QString extends; + mutable bool inState; + QmlStateGroup *group; + + QmlStateOperation::ActionList generateActionList(QmlStateGroup *) const; + void complete(); +}; + +QT_END_NAMESPACE + +#endif // QMLSTATE_P_H diff --git a/src/declarative/util/qmlstategroup.cpp b/src/declarative/util/qmlstategroup.cpp new file mode 100644 index 0000000..36fea4e --- /dev/null +++ b/src/declarative/util/qmlstategroup.cpp @@ -0,0 +1,306 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "private/qobject_p.h" +#include "qmlbindablevalue.h" +#include "qmlstategroup.h" +#include "qmltransition.h" +#include <QtCore/qdebug.h> + + +QT_BEGIN_NAMESPACE +DEFINE_BOOL_CONFIG_OPTION(stateChangeDebug, STATECHANGE_DEBUG); + +QML_DEFINE_TYPE(QmlStateGroup,StateGroup); + +class QmlStateGroupPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QmlStateGroup) +public: + QmlStateGroupPrivate(QmlStateGroup *p) + : nullState(0), states(p), classComplete(true), + componentComplete(true), ignoreTrans(false) {} + + QString currentState; + QmlState *nullState; + + struct StateList : public QmlConcreteList<QmlState *> + { + StateList(QmlStateGroup *g) + :group(g) {} + void append(QmlState *s) { + QmlConcreteList<QmlState *>::append(s); + if(s) s->setStateGroup(group); + } + private: + QmlStateGroup *group; + }; + StateList states; + + QmlConcreteList<QmlTransition *> transitions; + bool classComplete; + bool componentComplete; + bool ignoreTrans; + + QmlTransition *findTransition(const QString &from, const QString &to); + void setCurrentStateInternal(const QString &state, bool = false); + void updateAutoState(); +}; + +QmlStateGroup::QmlStateGroup(QObject *parent) + : QObject(*(new QmlStateGroupPrivate(this)), parent) +{ +} + +QmlStateGroup::~QmlStateGroup() +{ +} + +QList<QmlState *> QmlStateGroup::states() const +{ + Q_D(const QmlStateGroup); + return d->states; +} + +QmlList<QmlState *>* QmlStateGroup::statesProperty() +{ + Q_D(QmlStateGroup); + return &(d->states); +} + +QmlList<QmlTransition *>* QmlStateGroup::transitionsProperty() +{ + Q_D(QmlStateGroup); + return &(d->transitions); +} + +QString QmlStateGroup::state() const +{ + Q_D(const QmlStateGroup); + return d->currentState; +} + +void QmlStateGroup::setState(const QString &state) +{ + Q_D(QmlStateGroup); + if(d->currentState == state) + return; + + d->setCurrentStateInternal(state); + + d->currentState = state; + emit stateChanged(d->currentState); +} + +void QmlStateGroup::classBegin() +{ + Q_D(QmlStateGroup); + d->classComplete = false; + d->componentComplete = false; +} + +void QmlStateGroup::classComplete() +{ + Q_D(QmlStateGroup); + d->classComplete = true; +} + +void QmlStateGroup::updateAutoState() +{ + Q_D(QmlStateGroup); + d->updateAutoState(); +} + +void QmlStateGroupPrivate::updateAutoState() +{ + Q_Q(QmlStateGroup); + if(!classComplete) + return; + + bool revert = false; + for(int ii = 0; ii < states.count(); ++ii) { + QmlState *state = states.at(ii); + if(state->isWhenKnown()) { + if(!state->name().isEmpty()) { + if(state->when() && state->when()->value().toBool()) { + if(stateChangeDebug()) + qWarning() << "Setting auto state due to:" + << state->when()->expression(); + q->setState(state->name()); + return; + } else if(state->name() == currentState) { + revert = true; + } + } + } + } + if(revert) + q->setState(QString()); +} + +QmlTransition *QmlStateGroupPrivate::findTransition(const QString &from, const QString &to) +{ + QmlTransition *highest = 0; + int score = 0; + bool reversed = false; + bool done = false; + + for(int ii = 0; !done && ii < transitions.count(); ++ii) { + QmlTransition *t = transitions.at(ii); + for(int ii = 0; ii < 2; ++ii) + { + if(ii && (!t->reversible() || + (t->fromState() == QLatin1String("*") && + t->toState() == QLatin1String("*")))) + break; + QStringList fromState; + QStringList toState; + + fromState = t->fromState().split(QLatin1Char(',')); + toState = t->toState().split(QLatin1Char(',')); + if(ii == 1) + qSwap(fromState, toState); + int tScore = 0; + if(fromState.contains(from)) + tScore += 2; + else if(fromState.contains(QLatin1String("*"))) + tScore += 1; + else + continue; + + if(toState.contains(to)) + tScore += 2; + else if(toState.contains(QLatin1String("*"))) + tScore += 1; + else + continue; + + if(ii == 1) + reversed = true; + else + reversed = false; + + if(tScore == 4) { + highest = t; + done = true; + break; + } else if(tScore > score) { + score = tScore; + highest = t; + } + } + } + + if(highest) + highest->setReversed(reversed); + + return highest; +} + +void QmlStateGroupPrivate::setCurrentStateInternal(const QString &state, + bool ignoreTrans) +{ + Q_Q(QmlStateGroup); + if(!componentComplete) + return; + + QmlTransition *transition = (ignoreTrans || ignoreTrans) ? 0 : findTransition(currentState, state); + if(stateChangeDebug()) { + qWarning() << this << "Changing state. From" << currentState << ". To" << state; + if(transition) + qWarning() << " using transition" << transition->fromState() + << transition->toState(); + } + + QmlState *oldState = 0; + if(!currentState.isEmpty()) { + for(int ii = 0; ii < states.count(); ++ii) { + if(states.at(ii)->name() == currentState) { + oldState = states.at(ii); + break; + } + } + } + + currentState = state; + + QmlState *newState = 0; + for(int ii = 0; ii < states.count(); ++ii) { + if(states.at(ii)->name() == currentState) { + newState = states.at(ii); + break; + } + } + + if(oldState == 0 || newState == 0) { + if(!nullState) { nullState = new QmlState(q); } + if(!oldState) oldState = nullState; + if(!newState) newState = nullState; + } + + newState->apply(q, transition, oldState); +} + +void QmlStateGroup::componentComplete() +{ + Q_D(QmlStateGroup); + d->updateAutoState(); + d->componentComplete = true; + if(!d->currentState.isEmpty()) { + QString cs = d->currentState; + d->currentState = QString(); + d->setCurrentStateInternal(cs, true); + } +} + +QmlState *QmlStateGroup::findState(const QString &name) const +{ + Q_D(const QmlStateGroup); + for (int i = 0; i < d->states.count(); ++i) { + QmlState *state = d->states.at(i); + if (state->name() == name) + return state; + } + + return 0; +} + +QT_END_NAMESPACE diff --git a/src/declarative/util/qmlstategroup.h b/src/declarative/util/qmlstategroup.h new file mode 100644 index 0000000..55b84eb --- /dev/null +++ b/src/declarative/util/qmlstategroup.h @@ -0,0 +1,95 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMLSTATEGROUP_H +#define QMLSTATEGROUP_H + +#include <qmlstate.h> + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Declarative) +class QmlStateGroupPrivate; +class QmlStateGroup : public QObject, public QmlParserStatus +{ + Q_OBJECT + Q_INTERFACES(QmlParserStatus) + Q_DECLARE_PRIVATE(QmlStateGroup); + + Q_PROPERTY(QString state READ state WRITE setState NOTIFY stateChanged); + Q_PROPERTY(QmlList<QmlState *>* states READ statesProperty DESIGNABLE false); + Q_PROPERTY(QmlList<QmlTransition *>* transitions READ transitionsProperty DESIGNABLE false); + +public: + QmlStateGroup(QObject * = 0); + virtual ~QmlStateGroup(); + + QString state() const; + void setState(const QString &); + + QmlList<QmlState *>* statesProperty(); + QList<QmlState *> states() const; + + QmlList<QmlTransition *>* transitionsProperty(); + + QmlState *findState(const QString &name) const; + + virtual void classBegin(); + virtual void classComplete(); + virtual void componentComplete(); +Q_SIGNALS: + void stateChanged(const QString &); + +private: + friend class QmlState; + void updateAutoState(); +}; +QML_DECLARE_TYPE(QmlStateGroup); + +#endif // QMLSTATEGROUP_H + + +QT_END_NAMESPACE + +QT_END_HEADER diff --git a/src/declarative/util/qmlstateoperations.cpp b/src/declarative/util/qmlstateoperations.cpp new file mode 100644 index 0000000..c2ba4b8 --- /dev/null +++ b/src/declarative/util/qmlstateoperations.cpp @@ -0,0 +1,416 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <private/qobject_p.h> +#include <gfxeasing.h> +#include <qml.h> +#include <QtDeclarative/qmlcontext.h> +#include "qmlbindablevalue.h" +#include "qmlstateoperations.h" +#include <QtCore/qdebug.h> +#include <QtDeclarative/qmlinfo.h> + +QT_BEGIN_NAMESPACE + +class QmlParentChangePrivate : public QObjectPrivate +{ +public: + QmlParentChangePrivate() : target(0), parent(0) {} + + QObject *target; + QObject *parent; +}; + +/*! + \qmlclass ParentChange + \brief The ParentChange element allows you to reparent an object in a state. +*/ + +QML_DEFINE_TYPE(QmlParentChange,ParentChange); +QmlParentChange::QmlParentChange(QObject *parent) + : QmlStateOperation(*(new QmlParentChangePrivate), parent) +{ +} + +QmlParentChange::~QmlParentChange() +{ +} + +/*! + \qmlproperty Object ParentChange::target + This property holds the object to be reparented +*/ + +QObject *QmlParentChange::object() const +{ + Q_D(const QmlParentChange); + return d->target; +} +void QmlParentChange::setObject(QObject *target) +{ + Q_D(QmlParentChange); + d->target = target; +} + +/*! + \qmlproperty Object ParentChange::parent + This property holds the parent for the object in this state +*/ + +QObject *QmlParentChange::parent() const +{ + Q_D(const QmlParentChange); + return d->parent; +} + +void QmlParentChange::setParent(QObject *parent) +{ + Q_D(QmlParentChange); + d->parent = parent; +} + +QmlStateOperation::ActionList QmlParentChange::actions() +{ + Q_D(QmlParentChange); + if(!d->target || !d->parent) + return ActionList(); + + QString propName(QLatin1String("moveToParent")); + QmlMetaProperty prop(d->target, propName); + if (!prop.isValid()) { + qmlInfo(this) << d->target->metaObject()->className() + << "has no property named" << propName; + return ActionList(); + }else if(!prop.isWritable()){ + qmlInfo(this) << d->target->metaObject()->className() << propName + << "is not a writable property and cannot be set."; + return ActionList(); + } + QVariant cur = prop.read(); + + Action a; + a.property = prop; + a.fromValue = cur; + a.toValue = qVariantFromValue(d->parent); + + return ActionList() << a; +} + +class QmlRunScriptPrivate : public QObjectPrivate +{ +public: + QmlRunScriptPrivate() : ctxt(0) {} + + QmlContext *ctxt; + QString script; + QString name; +}; + +/*! + \qmlclass RunScript QmlRunScript + \brief The RunScript element allows you to run a script in a state. +*/ +QML_DEFINE_TYPE(QmlRunScript,RunScript); +QmlRunScript::QmlRunScript(QObject *parent) +: QmlStateOperation(*(new QmlRunScriptPrivate), parent) +{ + Q_D(QmlRunScript); + d->ctxt = QmlContext::activeContext(); +} + +QmlRunScript::~QmlRunScript() +{ +} + +/*! + \qmlproperty string RunScript::script + This property holds the script to run when the state is current. +*/ +QString QmlRunScript::script() const +{ + Q_D(const QmlRunScript); + return d->script; +} + +void QmlRunScript::setScript(const QString &s) +{ + Q_D(QmlRunScript); + d->script = s; +} + +QString QmlRunScript::name() const +{ + Q_D(const QmlRunScript); + return d->name; +} + +void QmlRunScript::setName(const QString &n) +{ + Q_D(QmlRunScript); + d->name = n; +} + +void QmlRunScript::execute() +{ + Q_D(QmlRunScript); + if(!d->script.isEmpty()) { + QmlExpression expr(d->ctxt, d->script, this); + expr.setTrackChange(false); + expr.value(); + } +} + +QmlRunScript::ActionList QmlRunScript::actions() +{ + ActionList rv; + Action a; + a.event = this; + rv << a; + return rv; +} + +/*! + \qmlclass SetProperty QmlSetProperty + \brief The SetProperty element describes a new property value or binding for a state. + + The code below changes the position of the Rect depending upon + the current state: + + \code + <Rect id="myrect" width="50" height="50" color="red"/> + + <states> + <State name="Position1"> + <SetProperty target="{myrect}" property="x" value="150"/> + <SetProperty target="{myrect}" property="y" value="50"/> + </State> + <State name="Position2"> + <SetProperty target="{myrect}" property="y" value="200"/> + </State> + </states> + \endcode + + \sa SetProperties +*/ + +/*! + \internal + \class QmlSetProperty + \brief The QmlSetProperty class describes a new property value or binding for a state. + + \ingroup states + + \sa QmlSetProperties +*/ + +class QmlSetPropertyPrivate : public QObjectPrivate +{ +public: + QmlSetPropertyPrivate() : obj(0) {} + + QObject *obj; + QString prop; + QVariant value; + QString binding; +}; + +QML_DEFINE_TYPE(QmlSetProperty,SetProperty); + +QmlSetProperty::QmlSetProperty(QObject *parent) + : QmlStateOperation(*(new QmlSetPropertyPrivate), parent) +{ +} + +QmlSetProperty::~QmlSetProperty() +{ +} + +/*! + \qmlproperty Object SetProperty::target + This property holds the object the property to change belongs to +*/ + +/*! + \property QmlSetProperty::target + \brief the object the property to change belongs to +*/ +QObject *QmlSetProperty::object() +{ + Q_D(QmlSetProperty); + return d->obj; +} + +void QmlSetProperty::setObject(QObject *o) +{ + Q_D(QmlSetProperty); + d->obj = o; +} + +/*! + \qmlproperty string SetProperty::property + This property holds the name of the property to change +*/ + +/*! + \property QmlSetProperty::property + \brief the name of the property to change +*/ +QString QmlSetProperty::property() const +{ + Q_D(const QmlSetProperty); + return d->prop; +} + +void QmlSetProperty::setProperty(const QString &p) +{ + Q_D(QmlSetProperty); + d->prop = p; +} + +/*! + \qmlproperty variant SetProperty::value + This property holds the value to assign to the property + + You should set either a \c value or a \c binding, but not both. +*/ + +/*! + \property QmlSetProperty::value + \brief the value to assign to the property + + You should set either a value or a binding, not both. +*/ +QVariant QmlSetProperty::value() const +{ + Q_D(const QmlSetProperty); + return d->value; +} + +void QmlSetProperty::setValue(const QVariant &v) +{ + Q_D(QmlSetProperty); + d->value = v; +} + +/*! + \qmlproperty string SetProperty::binding + This property holds the binding to assign to the property + + You should set either a \c value or a \c binding, but not both. +*/ + +/*! + \property QmlSetProperty::binding + \brief the binding to assign to the property + + You should set either a value or a binding, not both. +*/ +QString QmlSetProperty::binding() const +{ + Q_D(const QmlSetProperty); + return d->binding; +} + +void QmlSetProperty::setBinding(const QString &binding) +{ + Q_D(QmlSetProperty); + d->binding = binding; +} + +QmlSetProperty::ActionList QmlSetProperty::actions() +{ + Q_D(QmlSetProperty); + if(!d->obj) + return ActionList(); + + QObject *obj = d->obj; + QString propName = d->prop; + + if (d->prop.contains(QLatin1Char('.'))) { //handle dot properties + QStringList str = d->prop.split(QLatin1Char('.')); + for(int ii = 0; ii < str.count()-1; ++ii) { + const QString &s = str.at(ii); + QmlMetaProperty prop(obj, s); + if(!prop.isValid()) { + qmlInfo(this) << obj->metaObject()->className() + << "has no property named" << s; + return ActionList(); + } + QVariant v = prop.read(); + obj = QmlMetaType::toQObject(v); + if (!obj) { + qmlInfo(this) << "Unable to coerce value property" + << s << "into a QObject"; + return ActionList(); + } + } + propName = str.last(); + } + + QmlMetaProperty prop(obj, propName); + if (!prop.isValid()) { + qmlInfo(this) << obj->metaObject()->className() + << "has no property named" << propName; + return ActionList(); + }else if(!prop.isWritable()){ + qmlInfo(this) << obj->metaObject()->className() << propName + << "is not a writable property and cannot be set."; + return ActionList(); + } + QVariant cur = prop.read(); + + Action a; + a.property = prop; + a.fromValue = cur; + a.toValue = d->value; + if (!d->binding.isEmpty()) { + QmlBindableValue *bv = prop.binding(); + if(bv) { + a.fromBinding = bv->expression(); + a.bv = bv; + } + } + a.toBinding = d->binding; + + return ActionList() << a; +} + +QT_END_NAMESPACE diff --git a/src/declarative/util/qmlstateoperations.h b/src/declarative/util/qmlstateoperations.h new file mode 100644 index 0000000..8ecdcd2 --- /dev/null +++ b/src/declarative/util/qmlstateoperations.h @@ -0,0 +1,132 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMLSTATEOPERATIONS_H +#define QMLSTATEOPERATIONS_H + +#include <qmlstate.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Declarative) + +class QmlParentChangePrivate; +class Q_DECLARATIVE_EXPORT QmlParentChange : public QmlStateOperation +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QmlParentChange); + + Q_PROPERTY(QObject *target READ object WRITE setObject) + Q_PROPERTY(QObject *parent READ parent WRITE setParent) +public: + QmlParentChange(QObject *parent=0); + ~QmlParentChange(); + + QObject *object() const; + void setObject(QObject *); + + QObject *parent() const; + void setParent(QObject *); + + virtual ActionList actions(); +}; +QML_DECLARE_TYPE(QmlParentChange); + +class QmlRunScriptPrivate; +class Q_DECLARATIVE_EXPORT QmlRunScript : public QmlStateOperation, public ActionEvent +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QmlRunScript) + + Q_PROPERTY(QString script READ script WRITE setScript); + Q_PROPERTY(QString name READ name WRITE setName); + +public: + QmlRunScript(QObject *parent=0); + ~QmlRunScript(); + + virtual ActionList actions(); + + QString script() const; + void setScript(const QString &); + + virtual QString name() const; + void setName(const QString &); + + virtual void execute(); +}; +QML_DECLARE_TYPE(QmlRunScript); + +class QmlSetPropertyPrivate; +class Q_DECLARATIVE_EXPORT QmlSetProperty : public QmlStateOperation +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QmlSetProperty); + + 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(QString binding READ binding WRITE setBinding); + +public: + QmlSetProperty(QObject *parent=0); + ~QmlSetProperty(); + + QObject *object(); + void setObject(QObject *); + QString property() const; + void setProperty(const QString &); + QVariant value() const; + void setValue(const QVariant &); + QString binding() const; + void setBinding(const QString&); + + virtual ActionList actions(); +}; +QML_DECLARE_TYPE(QmlSetProperty); + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QMLSTATEOPERATIONS_H diff --git a/src/declarative/util/qmltransition.cpp b/src/declarative/util/qmltransition.cpp new file mode 100644 index 0000000..fb09e32 --- /dev/null +++ b/src/declarative/util/qmltransition.cpp @@ -0,0 +1,283 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qmlstate.h" +#include "qmlstategroup.h" +#include "qmlstate_p.h" +#include "qmlbindablevalue.h" +#include "qmlstateoperations.h" +#include "qmlanimation.h" +#include "qmlanimation_p.h" +#include <QParallelAnimationGroup> + +QT_BEGIN_NAMESPACE + +/*! + \qmlclass Transition QmlTransition + \brief The Transition element defines animated transitions that occur on state changes. + + \sa {states-transitions}{States and Transitions} +*/ + +/*! + \internal + \class QmlTransition + \brief The QmlTransition class allows you to define animated transitions that occur on state changes. + + \ingroup states +*/ + +//ParallelAnimationWrapperallows us to do a "callback" when the animation finishes, rather than connecting +//and disconnecting signals and slots frequently +class ParallelAnimationWrapper : public QParallelAnimationGroup +{ + Q_OBJECT +public: + ParallelAnimationWrapper(QObject *parent) : QParallelAnimationGroup(parent) {} + QmlTransitionPrivate *trans; +protected: + virtual void updateState(QAbstractAnimation::State oldState, QAbstractAnimation::State newState); +}; + +class QmlTransitionPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QmlTransition) +public: + QmlTransitionPrivate() : fromState(QLatin1String("*")), toState(QLatin1String("*")) + , reversed(false), reversible(false), group(0), endState(0) + { + operations.parent = this; + } + + QString fromState; + QString toState; + bool reversed; + bool reversible; + ParallelAnimationWrapper *group; + QmlState *endState; + + void init() + { + Q_Q(QmlTransition); + group = new ParallelAnimationWrapper(q); + group->trans = this; + } + + void complete() + { + endState->d_func()->complete(); + } + + class AnimationList : public QmlConcreteList<QmlAbstractAnimation *> + { + public: + AnimationList() : parent(0) {} + virtual void append(QmlAbstractAnimation *a); + virtual void clear() { QmlConcreteList<QmlAbstractAnimation *>::clear(); } //XXX + + QmlTransitionPrivate *parent; + }; + AnimationList operations; +}; + +void QmlTransitionPrivate::AnimationList::append(QmlAbstractAnimation *a) +{ + QmlConcreteList<QmlAbstractAnimation *>::append(a); + parent->group->addAnimation(a->qtAnimation()); +} + +void ParallelAnimationWrapper::updateState(QAbstractAnimation::State oldState, QAbstractAnimation::State newState) +{ + QParallelAnimationGroup::updateState(oldState, newState); + //XXX not 100% guaranteed to be at end (if there are many zero duration animations at the end)? + if (newState == Stopped && currentTime() == duration()) + { + trans->complete(); + } +} + + +QML_DEFINE_TYPE(QmlTransition,Transition); +QmlTransition::QmlTransition(QObject *parent) + : QObject(*(new QmlTransitionPrivate), parent) +{ + Q_D(QmlTransition); + d->init(); +} + +QmlTransition::~QmlTransition() +{ +} + +void QmlTransition::stop() +{ + Q_D(QmlTransition); + d->group->stop(); +} + +void QmlTransition::setReversed(bool r) +{ + Q_D(QmlTransition); + d->reversed = r; +} + +void QmlTransition::prepare(QmlStateOperation::ActionList &actions, + QList<QmlMetaProperty> &after, + QmlState *endState) +{ + Q_D(QmlTransition); + + if(d->reversed) { + for(int ii = d->operations.count() - 1; ii >= 0; --ii) { + d->operations.at(ii)->transition(actions, after, QmlAbstractAnimation::Backward); + } + } else { + for(int ii = 0; ii < d->operations.count(); ++ii) { + d->operations.at(ii)->transition(actions, after, QmlAbstractAnimation::Forward); + } + } + + d->endState = endState; + d->group->start(); +} + +/*! + \qmlproperty string Transition::fromState + \qmlproperty string Transition::toState + These properties are selectors indicating which state changes should trigger the transition. + + fromState is used in conjunction with toState to determine when a transition should + be applied. By default fromState and toState are both "*" (any state). In the following example, + the transition is applied when changing from state1 to state2. + \code + <Transition fromState="state1" toState="state2"> + ... + </Transition> + \endcode +*/ + +/*! + \property QmlTransition::fromState + \brief a selector indicating which states, when left, should trigger the transition. + + fromState is used in conjunction with toState to determine when a transition should + be applied. The default value is "*" (any state). +*/ +QString QmlTransition::fromState() const +{ + Q_D(const QmlTransition); + return d->fromState; +} + +void QmlTransition::setFromState(const QString &f) +{ + Q_D(QmlTransition); + d->fromState = f; +} + +/*! + \qmlproperty bool Transition::reversible + This property holds whether the transition should be automatically reversed when the conditions that triggered this transition are reversed. + + The default value is false. +*/ + + +/*! + \property QmlTransition::reversible + \brief whether the transition should be automatically reversed when the conditions that triggered this transition are reversed. + + The default value is false. +*/ +bool QmlTransition::reversible() const +{ + Q_D(const QmlTransition); + return d->reversible; +} + +void QmlTransition::setReversible(bool r) +{ + Q_D(QmlTransition); + d->reversible = r; +} + +/*! + \property QmlTransition::toState + \brief a selector indicating which states, when entered, should trigger the transition. + + toState is used in conjunction with fromState to determine when a transition should + be applied. The default value is "*" (any state). +*/ +QString QmlTransition::toState() const +{ + Q_D(const QmlTransition); + return d->toState; +} + +void QmlTransition::setToState(const QString &t) +{ + Q_D(QmlTransition); + d->toState = t; +} + +/*! + \qmlproperty list<Animation> Transition::operations + This property holds a list of the animations to be run for this transition. + + The top-level animations in operations are run in parallel. + To run them sequentially, you can create a single <SequentialAnimation> + which contains all the animations, and assign that to operations. + \default +*/ + +/*! + \property QmlTransition::operations + \brief a list of the transition animations to be run. +*/ +QmlList<QmlAbstractAnimation *>* QmlTransition::operations() +{ + Q_D(QmlTransition); + return &d->operations; +} + +QT_END_NAMESPACE + +#include "qmltransition.moc" diff --git a/src/declarative/util/qmltransition.h b/src/declarative/util/qmltransition.h new file mode 100644 index 0000000..0d86b7d --- /dev/null +++ b/src/declarative/util/qmltransition.h @@ -0,0 +1,98 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMLTRANSITION_H +#define QMLTRANSITION_H + +#include <QtCore/qobject.h> +#include <qfxglobal.h> +#include <gfxtimeline.h> +#include <qmlstate.h> +#include <qml.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Declarative) + +class QmlAbstractAnimation; +class QmlTransitionPrivate; +class Q_DECLARATIVE_EXPORT QmlTransition : public QObject +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QmlTransition) + + Q_PROPERTY(QString fromState READ fromState WRITE setFromState) + Q_PROPERTY(QString toState READ toState WRITE setToState) + Q_PROPERTY(bool reversible READ reversible WRITE setReversible) + Q_PROPERTY(QmlList<QmlAbstractAnimation *>* operations READ operations) + Q_CLASSINFO("DefaultProperty", "operations") + +public: + QmlTransition(QObject *parent=0); + ~QmlTransition(); + + QString fromState() const; + void setFromState(const QString &); + + QString toState() const; + void setToState(const QString &); + + bool reversible() const; + void setReversible(bool); + + QmlList<QmlAbstractAnimation *>* operations(); + + void prepare(QmlStateOperation::ActionList &actions, + QList<QmlMetaProperty> &after, + QmlState *endState); + + void setReversed(bool r); + void stop(); +}; +QML_DECLARE_TYPE(QmlTransition); + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QMLTRANSITION_H diff --git a/src/declarative/util/qperformancelog.cpp b/src/declarative/util/qperformancelog.cpp new file mode 100644 index 0000000..52ccc0d --- /dev/null +++ b/src/declarative/util/qperformancelog.cpp @@ -0,0 +1,177 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qperformancelog.h" +#include <QHash> +#include <QDebug> + + +#ifdef Q_ENABLE_PERFORMANCE_LOG + +struct QPerformanceLogData +{ + struct Log + { + Log() + : logDescription(0), maxId(-1) {} + + QHash<int, const char *> descriptions; + const char *logDescription; + int maxId; + }; + + typedef QHash<QPerformanceLog::LogData *, Log> Logs; + Logs logs; +}; +Q_GLOBAL_STATIC(QPerformanceLogData, performanceLogData); + +QPerformanceLog::LogData::LogData(const char *desc) +: sumTime(0), data(0) +{ + QPerformanceLogData *logData = performanceLogData(); + + QPerformanceLogData::Log log; + log.logDescription = desc; + logData->logs.insert(this, log); + + timer.start(); +} + +QPerformanceLog::LogMetric::LogMetric(LogData *l, int id, const char *desc) +{ + if(id < 0) + qFatal("QPerformanceLog: Invalid log id %d ('%s')", id, desc); + + QPerformanceLogData *logData = performanceLogData(); + + QPerformanceLogData::Logs::Iterator logIter = logData->logs.find(l); + if(logIter == logData->logs.end()) + qFatal("QPerformanceLog: Unable to locate log for metric '%s'", desc); + QPerformanceLogData::Log &log = *logIter; + if(log.descriptions.contains(id)) + qFatal("QPerformanceLog: Duplicate log metric %d ('%s')", id, desc); + log.descriptions.insert(id, desc); + + if(log.maxId < id) { + log.maxId = id; + if(l->data) delete [] l->data; + l->data = new unsigned int[2 * (log.maxId + 1)]; + ::memset(l->data, 0, 2 * (log.maxId + 1) * sizeof(unsigned int)); + } +} + +static void QPerformanceLog_clear(QPerformanceLog::LogData *l, const QPerformanceLogData::Log *pl) +{ + ::memset(l->data, 0, 2 * (pl->maxId + 1) * sizeof(unsigned int)); +} + +static void QPerformanceLog_displayData(const QPerformanceLog::LogData *l, const QPerformanceLogData::Log *pl) +{ + qWarning() << pl->logDescription << "performance data"; + unsigned int total = 0; + for(QHash<int, const char *>::ConstIterator iter = pl->descriptions.begin(); + iter != pl->descriptions.end(); + ++iter) { + + int id = iter.key(); + unsigned int ms = l->data[id * 2]; + total += ms; + unsigned int inst = l->data[id * 2 + 1]; + float pi = float(ms) / float(inst); + qWarning().nospace() << " " << *iter << ": " << ms << " ms over " + << inst << " instances (" << pi << " ms/instance)"; + } + qWarning().nospace() << " TOTAL: " << total; +} + +void QPerformanceLog::displayData() +{ + QPerformanceLogData *logData = performanceLogData(); + + for(QPerformanceLogData::Logs::ConstIterator iter = logData->logs.begin(); + iter != logData->logs.end(); + ++iter) { + QPerformanceLog_displayData(iter.key(), &(*iter)); + } +} + +void QPerformanceLog::clear() +{ + QPerformanceLogData *logData = performanceLogData(); + + for(QPerformanceLogData::Logs::ConstIterator iter = logData->logs.begin(); + iter != logData->logs.end(); + ++iter) { + QPerformanceLog_clear(iter.key(), &(*iter)); + } +} + +void QPerformanceLog::displayData(LogData *l) +{ + QPerformanceLogData *logData = performanceLogData(); + QPerformanceLogData::Logs::ConstIterator iter = logData->logs.find(l); + if(iter == logData->logs.end()) + qFatal("QPerformanceLog: Internal corruption - unable to locate log"); + + QPerformanceLog_displayData(iter.key(), &(*iter)); +} + +void QPerformanceLog::clear(LogData *l) +{ + QPerformanceLogData *logData = performanceLogData(); + QPerformanceLogData::Logs::ConstIterator iter = logData->logs.find(l); + if(iter == logData->logs.end()) + qFatal("QPerformanceLog: Internal corruption - unable to locate log"); + + QPerformanceLog_clear(iter.key(), &(*iter)); +} + +#else // Q_ENABLE_PERFORMANCE_LOG + +void QPerformanceLog::displayData() +{ +} + +void QPerformanceLog::clear() +{ +} + +#endif // Q_ENABLE_PERFORMANCE_LOG diff --git a/src/declarative/util/qperformancelog.h b/src/declarative/util/qperformancelog.h new file mode 100644 index 0000000..9d19bbd --- /dev/null +++ b/src/declarative/util/qperformancelog.h @@ -0,0 +1,176 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPERFORMANCELOG_H +#define QPERFORMANCELOG_H + +#include <QtCore/qdatetime.h> +namespace QPerformanceLog +{ + Q_DECLARATIVE_EXPORT void displayData(); + Q_DECLARATIVE_EXPORT void clear(); + +#ifdef Q_ENABLE_PERFORMANCE_LOG + struct LogData { + LogData(const char *); + QTime timer; + int sumTime; + unsigned int *data; + }; + + struct LogMetric { + LogMetric(LogData *, int, const char *); + }; + + // Internal + void displayData(LogData *); + void clear(LogData *); +#endif +}; + +#ifdef Q_ENABLE_PERFORMANCE_LOG + +#define Q_DECLARE_PERFORMANCE_METRIC(name) \ + enum { name = ValueChoice<0, ValueTracker<0, __LINE__>::value, __LINE__>::value }; \ + template<int L> \ + struct ValueTracker<name, L> \ + { \ + enum { value = name }; \ + }; \ + extern QPerformanceLog::LogMetric metric ## name; + +#define Q_DECLARE_PERFORMANCE_LOG(name) \ + namespace name { \ + extern QPerformanceLog::LogData log; \ + inline void displayData() { QPerformanceLog::displayData(&log); } \ + inline void clear() { QPerformanceLog::clear(&log); } \ + } \ + template<int N> \ + class name ## Timer { \ + public: \ + name ## Timer() { \ + lastSum = name::log.sumTime + name::log.timer.restart(); \ + name::log.sumTime = 0; \ + } \ + ~ name ## Timer() { \ + name::log.data[2 * N] += name::log.sumTime + name::log.timer.restart(); \ + ++name::log.data[2 * N + 1]; \ + name::log.sumTime = lastSum; \ + } \ + private: \ + int lastSum; \ + }; \ + namespace name { \ + template<int N, int L> \ + struct ValueTracker \ + { \ + enum { value = -1 }; \ + }; \ + template<int DefNextValue, int NextValue, int L> \ + struct ValueChoice \ + { \ + enum { value = ValueChoice<DefNextValue + 1, ValueTracker<DefNextValue + 1, L>::value, L>::value }; \ + }; \ + template<int DefNextValue, int L> \ + struct ValueChoice<DefNextValue, -1, L> \ + { \ + enum { value = DefNextValue }; \ + }; \ + } \ + namespace name + +#define Q_DEFINE_PERFORMANCE_LOG(name, desc) \ + QPerformanceLog::LogData name::log(desc); \ + namespace name + +#define Q_DEFINE_PERFORMANCE_METRIC(name, desc) \ + QPerformanceLog::LogMetric metrix ## name(&log, name, desc); + +#else // Q_ENABLE_PERFORMANCE_LOG + +#define Q_DECLARE_PERFORMANCE_METRIC(name) \ + enum { name = ValueChoice<0, ValueTracker<0, __LINE__>::value, __LINE__>::value }; \ + template<int L> \ + struct ValueTracker<name, L> \ + { \ + enum { value = name }; \ + }; \ + +#define Q_DECLARE_PERFORMANCE_LOG(name) \ + namespace name { \ + inline void displayData() { }; \ + inline void clear() { }; \ + } \ + template<int N> \ + class name ## Timer { \ + public: \ + name ## Timer() { \ + } \ + ~ name ## Timer() { \ + } \ + }; \ + namespace name { \ + template<int N, int L> \ + struct ValueTracker \ + { \ + enum { value = -1 }; \ + }; \ + template<int DefNextValue, int NextValue, int L> \ + struct ValueChoice \ + { \ + enum { value = ValueChoice<DefNextValue + 1, ValueTracker<DefNextValue + 1, L>::value, L>::value }; \ + }; \ + template<int DefNextValue, int L> \ + struct ValueChoice<DefNextValue, -1, L> \ + { \ + enum { value = DefNextValue }; \ + }; \ + } \ + namespace name + +#define Q_DEFINE_PERFORMANCE_LOG(name, desc) \ + namespace name + +#define Q_DEFINE_PERFORMANCE_METRIC(name, desc) + +#endif // Q_ENABLE_PERFORMANCE_LOG + +#endif // QPERFORMANCELOG_H diff --git a/src/declarative/util/util.pri b/src/declarative/util/util.pri new file mode 100644 index 0000000..030a44e --- /dev/null +++ b/src/declarative/util/util.pri @@ -0,0 +1,49 @@ +SOURCES += \ + util/qfxview.cpp \ + util/qfxperf.cpp \ + util/qperformancelog.cpp \ + util/qmlconnection.cpp \ + util/qmlpackage.cpp \ + util/qmlscript.cpp \ + util/qmlanimation.cpp \ + util/qmlbehaviour.cpp \ + util/qmlfont.cpp \ + util/qmlfollow.cpp \ + util/qmlstate.cpp\ + util/qmlstateoperations.cpp \ + util/qmlsetproperties.cpp \ + util/qmlstategroup.cpp \ + util/qmltransition.cpp \ + util/qbindablemap.cpp \ + util/qmldatetimeformatter.cpp \ + util/qmllistmodel.cpp\ + util/qmllistaccessor.cpp \ + util/qmlopenmetaobject.cpp \ + util/qmlbind.cpp + +HEADERS += \ + util/qfxview.h \ + util/qfxperf.h \ + util/qfxglobal.h \ + util/qperformancelog.h \ + util/qmlconnection.h \ + util/qmlpackage.h \ + util/qmlscript.h \ + util/qmlanimation.h \ + util/qmlanimation_p.h \ + util/qmlbehaviour.h \ + util/qmlfont.h \ + util/qmlfollow.h \ + util/qmlstate.h\ + util/qmlstateoperations.h \ + util/qmlsetproperties.h \ + util/qmlstate_p.h\ + util/qmlstategroup.h \ + util/qmltransition.h \ + util/qbindablemap.h \ + util/qmldatetimeformatter.h \ + util/qmllistmodel.h\ + util/qmllistaccessor.h \ + util/qmlopenmetaobject.h \ + util/qmlnullablevalue_p.h \ + util/qmlbind.h |