summaryrefslogtreecommitdiffstats
path: root/src/declarative
diff options
context:
space:
mode:
authorErik Verbruggen <erik.verbruggen@nokia.com>2009-06-25 07:33:13 (GMT)
committerErik Verbruggen <erik.verbruggen@nokia.com>2009-06-25 07:33:13 (GMT)
commit5b52c348243e6459cc7faa4ee76a23c7fadcd299 (patch)
treebe4bee855e535651b5fa22e9554ce1732f6ece70 /src/declarative
parent2020c692803a8a7839d85860d05174a193d9a848 (diff)
parent0362832c16f95c2909e2a68351e15242b7d1b795 (diff)
downloadQt-5b52c348243e6459cc7faa4ee76a23c7fadcd299.zip
Qt-5b52c348243e6459cc7faa4ee76a23c7fadcd299.tar.gz
Qt-5b52c348243e6459cc7faa4ee76a23c7fadcd299.tar.bz2
Merge branch 'kinetic-declarativeui' of git@scm.dev.nokia.troll.no:qt/kinetic into kinetic-declarativeui
Diffstat (limited to 'src/declarative')
-rw-r--r--src/declarative/canvas/qsimplecanvas.cpp6
-rw-r--r--src/declarative/extra/qmltimer.cpp150
-rw-r--r--src/declarative/extra/qmltimer.h21
-rw-r--r--src/declarative/fx/qfxflowview.cpp9
-rw-r--r--src/declarative/fx/qfxgridview.cpp4
-rw-r--r--src/declarative/fx/qfximage.cpp9
-rw-r--r--src/declarative/fx/qfxitem.cpp9
-rw-r--r--src/declarative/fx/qfxpainteditem.cpp30
-rw-r--r--src/declarative/fx/qfxpainteditem.h7
-rw-r--r--src/declarative/fx/qfxpainteditem_p.h3
-rw-r--r--src/declarative/fx/qfxwebview.cpp7
-rw-r--r--src/declarative/fx/qfxwebview.h1
-rw-r--r--src/declarative/qml/qmlbasicscript.cpp6
-rw-r--r--src/declarative/qml/qmlcompiler.cpp5
-rw-r--r--src/declarative/qml/qmlcomponent.cpp1
-rw-r--r--src/declarative/qml/qmldom.cpp10
-rw-r--r--src/declarative/qml/qmldom.h1
-rw-r--r--src/declarative/qml/qmlengine.cpp22
-rw-r--r--src/declarative/qml/qmlparser_p.h2
-rw-r--r--src/declarative/util/qmlanimation.cpp62
-rw-r--r--src/declarative/util/qmlanimation.h6
-rw-r--r--src/declarative/util/qmlanimation_p.h3
-rw-r--r--src/declarative/util/qmlfollow.cpp8
-rw-r--r--src/declarative/util/qmlstate.cpp102
-rw-r--r--src/declarative/util/qmlstate.h23
-rw-r--r--src/declarative/util/qmlstate_p.h29
26 files changed, 432 insertions, 104 deletions
diff --git a/src/declarative/canvas/qsimplecanvas.cpp b/src/declarative/canvas/qsimplecanvas.cpp
index cb46f94..a4998dc 100644
--- a/src/declarative/canvas/qsimplecanvas.cpp
+++ b/src/declarative/canvas/qsimplecanvas.cpp
@@ -883,9 +883,9 @@ QRect QSimpleCanvasPrivate::resetDirty()
dirtyItems.clear();
oldDirty = QRect();
- if (fullUpdate())
+ /*if (fullUpdate())
return QRect();
- else
+ else*/
return r;
} else {
return QRect();
@@ -934,7 +934,7 @@ bool QSimpleCanvas::event(QEvent *e)
QRect r = d->resetDirty();
#if defined(QFX_RENDER_QPAINTER)
- if (r.isEmpty() || fullUpdate())
+ if (fullUpdate())
repaint();
else
repaint(r);
diff --git a/src/declarative/extra/qmltimer.cpp b/src/declarative/extra/qmltimer.cpp
index 1e1a6de..4af83d3 100644
--- a/src/declarative/extra/qmltimer.cpp
+++ b/src/declarative/extra/qmltimer.cpp
@@ -39,6 +39,7 @@
**
****************************************************************************/
+#include "QtCore/qcoreapplication.h"
#include "QtCore/qpauseanimation.h"
#include "private/qobject_p.h"
#include "qmltimer.h"
@@ -52,27 +53,59 @@ class QmlTimerPrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QmlTimer)
public:
- QmlTimerPrivate() : interval(1000) {}
+ QmlTimerPrivate()
+ : interval(1000), running(false), repeating(false), triggeredOnStart(false)
+ , componentComplete(false) {}
int interval;
+ bool running;
+ bool repeating;
+ bool triggeredOnStart;
QPauseAnimation pause;
+ bool componentComplete;
};
+/*!
+ \qmlclass Timer QFxTimer
+ \brief The Timer item triggers a handler at a specified interval.
+
+ A timer can be used to trigger an action either once, or repeatedly
+ at a given interval.
+
+ \qml
+ Timer {
+ interval: 500; running: true; repeat: true
+ onTriggered: Time.text = Date().toString()
+ }
+ Text {
+ id: Time
+ }
+ \endqml
+
+*/
+
QmlTimer::QmlTimer(QObject *parent)
: QObject(*(new QmlTimerPrivate), parent)
{
Q_D(QmlTimer);
connect(&d->pause, SIGNAL(currentLoopChanged(int)), this, SLOT(ticked()));
- d->pause.setLoopCount(-1);
+ connect(&d->pause, SIGNAL(finished()), this, SLOT(ticked()));
+ connect(&d->pause, SIGNAL(stateChanged(QAbstractAnimation::State,QAbstractAnimation::State))
+ , this, SLOT(stateChanged(QAbstractAnimation::State,QAbstractAnimation::State)));
+ d->pause.setLoopCount(1);
d->pause.setDuration(d->interval);
}
+/*!
+ \qmlproperty int Timer::interval
+
+ Sets the \a interval in milliseconds between triggering.
+*/
void QmlTimer::setInterval(int interval)
{
Q_D(QmlTimer);
if (interval != d->interval) {
d->interval = interval;
- d->pause.setDuration(d->interval);
- d->pause.start();
+ update();
}
}
@@ -82,16 +115,119 @@ int QmlTimer::interval() const
return d->interval;
}
-void QmlTimer::componentComplete()
+/*!
+ \qmlproperty bool Timer::running
+
+ If set to true, starts the timer; otherwise stops the timer.
+ For a non-repeating timer, \a running will be set to false after the
+ timer has been triggered.
+
+ \sa repeat
+*/
+bool QmlTimer::isRunning() const
+{
+ Q_D(const QmlTimer);
+ return d->running;
+}
+
+void QmlTimer::setRunning(bool running)
+{
+ Q_D(QmlTimer);
+ if (d->running != running) {
+ d->running = running;
+ emit runningChanged();
+ update();
+ }
+}
+
+/*!
+ \qmlproperty bool Timer::repeat
+
+ If \a repeat is true the timer will be triggered repeatedly at the
+ specified interval; otherwise, the timer will trigger once at the
+ specified interval and then stop (i.e. running will be set to false).
+
+ \sa running
+*/
+bool QmlTimer::isRepeating() const
+{
+ Q_D(const QmlTimer);
+ return d->repeating;
+}
+
+void QmlTimer::setRepeating(bool repeating)
+{
+ Q_D(QmlTimer);
+ if (repeating != d->repeating) {
+ d->repeating = repeating;
+ update();
+ }
+}
+
+/*!
+ \qmlproperty bool Timer::triggeredOnStart
+
+ If \a triggeredOnStart is true, the timer will be triggered immediately
+ when started, and subsequently at the specified interval.
+
+ \sa running
+*/
+bool QmlTimer::triggeredOnStart() const
+{
+ Q_D(const QmlTimer);
+ return d->triggeredOnStart;
+}
+
+void QmlTimer::setTriggeredOnStart(bool triggeredOnStart)
+{
+ Q_D(QmlTimer);
+ if (d->triggeredOnStart != triggeredOnStart) {
+ d->triggeredOnStart = triggeredOnStart;
+ update();
+ }
+}
+
+void QmlTimer::update()
{
Q_D(QmlTimer);
- if (d->pause.state() != QAbstractAnimation::Running)
+ if (!d->componentComplete)
+ return;
+ d->pause.stop();
+ if (d->running) {
+ d->pause.setLoopCount(d->repeating ? -1 : 1);
+ d->pause.setDuration(d->interval);
d->pause.start();
+ if (d->triggeredOnStart) {
+ QCoreApplication::removePostedEvents(this, QEvent::MetaCall);
+ QMetaObject::invokeMethod(this, "ticked", Qt::QueuedConnection);
+ }
+ }
+}
+
+void QmlTimer::componentComplete()
+{
+ Q_D(QmlTimer);
+ d->componentComplete = true;
+ update();
}
+/*!
+ \qmlsignal Timer::onTriggered
+
+ This handler is called when the Timer is triggered.
+*/
void QmlTimer::ticked()
{
- emit timeout();
+ emit triggered();
+}
+
+void QmlTimer::stateChanged(QAbstractAnimation::State, QAbstractAnimation::State state)
+{
+ Q_D(QmlTimer);
+ if (d->running && state != QAbstractAnimation::Running) {
+ d->running = false;
+ emit runningChanged();
+ }
}
QT_END_NAMESPACE
diff --git a/src/declarative/extra/qmltimer.h b/src/declarative/extra/qmltimer.h
index 75603c6..8171385 100644
--- a/src/declarative/extra/qmltimer.h
+++ b/src/declarative/extra/qmltimer.h
@@ -44,6 +44,7 @@
#include <QtDeclarative/qfxglobal.h>
#include <QtCore/qobject.h>
+#include <QtCore/qabstractanimation.h>
#include <QtDeclarative/qml.h>
QT_BEGIN_HEADER
@@ -56,7 +57,11 @@ class Q_DECLARATIVE_EXPORT QmlTimer : public QObject, public QmlParserStatus
{
Q_OBJECT
Q_DECLARE_PRIVATE(QmlTimer)
+ Q_INTERFACES(QmlParserStatus)
Q_PROPERTY(int interval READ interval WRITE setInterval)
+ Q_PROPERTY(bool running READ isRunning WRITE setRunning NOTIFY runningChanged)
+ Q_PROPERTY(bool repeat READ isRepeating WRITE setRepeating)
+ Q_PROPERTY(bool triggeredOnStart READ triggeredOnStart WRITE setTriggeredOnStart)
public:
QmlTimer(QObject *parent=0);
@@ -64,14 +69,28 @@ public:
void setInterval(int interval);
int interval() const;
+ bool isRunning() const;
+ void setRunning(bool running);
+
+ bool isRepeating() const;
+ void setRepeating(bool repeating);
+
+ bool triggeredOnStart() const;
+ void setTriggeredOnStart(bool triggeredOnStart);
+
protected:
void componentComplete();
Q_SIGNALS:
- void timeout();
+ void triggered();
+ void runningChanged();
+
+private:
+ void update();
private Q_SLOTS:
void ticked();
+ void stateChanged(QAbstractAnimation::State,QAbstractAnimation::State);
};
QML_DECLARE_TYPE(QmlTimer)
diff --git a/src/declarative/fx/qfxflowview.cpp b/src/declarative/fx/qfxflowview.cpp
index e02e186..77cd6df 100644
--- a/src/declarative/fx/qfxflowview.cpp
+++ b/src/declarative/fx/qfxflowview.cpp
@@ -128,10 +128,11 @@ void QFxFlowView::refresh()
{
if (m_model && m_columns >= 1) {
for (int ii = 0; ii < m_model->count(); ++ii) {
- QFxItem *item = m_model->item(ii);
- item->setParent(this);
- item->setZ(0);
- m_items << item;
+ if (QFxItem *item = m_model->item(ii)) {
+ item->setParent(this);
+ item->setZ(0);
+ m_items << item;
+ }
}
reflow();
diff --git a/src/declarative/fx/qfxgridview.cpp b/src/declarative/fx/qfxgridview.cpp
index 0ca9393..a6ffbb9 100644
--- a/src/declarative/fx/qfxgridview.cpp
+++ b/src/declarative/fx/qfxgridview.cpp
@@ -234,6 +234,8 @@ public:
int count = columns - 1 - (modelIndex - visibleItems.last()->index - 1) % columns;
return visibleItems.last()->colPos() - count * colSize();
}
+ } else {
+ return (modelIndex % columns) * colSize();
}
return 0;
}
@@ -252,6 +254,8 @@ public:
int rows = col / (columns * colSize());
return visibleItems.last()->rowPos() + rows * rowSize();
}
+ } else {
+ return (modelIndex / columns) * rowSize();
}
return 0;
}
diff --git a/src/declarative/fx/qfximage.cpp b/src/declarative/fx/qfximage.cpp
index 40389c4..58d597a 100644
--- a/src/declarative/fx/qfximage.cpp
+++ b/src/declarative/fx/qfximage.cpp
@@ -336,7 +336,8 @@ void QFxImage::paintContents(QPainter &p)
if (d->pix.isNull())
return;
- QPainter::RenderHints oldHints = p.renderHints();
+ bool oldAA = p.testRenderHint(QPainter::Antialiasing);
+ bool oldSmooth = p.testRenderHint(QPainter::SmoothPixmapTransform);
if (d->smooth)
p.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform, d->smooth);
@@ -428,8 +429,10 @@ void QFxImage::paintContents(QPainter &p)
QRect(pix.width()-sgr, pix.height() - sgb, sgr, sgb));
}
- if (d->smooth)
- p.setRenderHints(oldHints);
+ if (d->smooth) {
+ p.setRenderHint(QPainter::Antialiasing, oldAA);
+ p.setRenderHint(QPainter::SmoothPixmapTransform, oldSmooth);
+ }
}
#elif defined(QFX_RENDER_OPENGL)
uint QFxImage::glSimpleItemData(float *vertices, float *texVertices,
diff --git a/src/declarative/fx/qfxitem.cpp b/src/declarative/fx/qfxitem.cpp
index 0c4d97b..73786a8 100644
--- a/src/declarative/fx/qfxitem.cpp
+++ b/src/declarative/fx/qfxitem.cpp
@@ -897,7 +897,16 @@ void QFxItem::qmlLoaded()
QmlContext *ctxt = new QmlContext(qmlContext(this));
ctxt->addDefaultObject(this);
+ if (!d->_qmlcomp->errors().isEmpty()) {
+ qWarning() << d->_qmlcomp->errors();
+ delete d->_qmlcomp;
+ d->_qmlcomp = 0;
+ emit qmlChanged();
+ return;
+ }
QObject *obj = d->_qmlcomp->create(ctxt);
+ if (!d->_qmlcomp->errors().isEmpty())
+ qWarning() << d->_qmlcomp->errors();
QFxItem *qmlChild = qobject_cast<QFxItem *>(obj);
if (qmlChild) {
qmlChild->setItemParent(this);
diff --git a/src/declarative/fx/qfxpainteditem.cpp b/src/declarative/fx/qfxpainteditem.cpp
index 29d11ff..65589f2 100644
--- a/src/declarative/fx/qfxpainteditem.cpp
+++ b/src/declarative/fx/qfxpainteditem.cpp
@@ -156,7 +156,6 @@ void QFxPaintedItem::setSmooth(bool smooth)
Q_D(QFxPaintedItem);
if (d->smooth == smooth) return;
d->smooth = smooth;
- clearCache();
update();
}
@@ -304,7 +303,8 @@ void QFxPaintedItem::paintGLContents(GLPainter &p)
for (int i = 0; i < rects.count(); ++i) {
const QRect &r = rects.at(i);
QPixmap img(r.size());
- img.fill(Qt::transparent);
+ if (d->fillColor.isValid())
+ img.fill(d->fillColor);
{
QPainter qp(&img);
qp.translate(-r.x(),-r.y());
@@ -384,4 +384,30 @@ void QFxPaintedItem::setCacheSize(int pixels)
d->max_imagecache_size = pixels;
}
+/*!
+ \property QFxPaintedItem::fillColor
+
+ The color to be used to fill the item prior to calling drawContents().
+ By default, this is Qt::transparent.
+
+ Performance improvements can be achieved if subclasses call this with either an
+ invalid color (QColor()), or an appropriate solid color.
+*/
+void QFxPaintedItem::setFillColor(const QColor& c)
+{
+ Q_D(QFxPaintedItem);
+ if (d->fillColor == c)
+ return;
+ d->fillColor = c;
+ emit fillColorChanged();
+ update();
+}
+
+QColor QFxPaintedItem::fillColor() const
+{
+ Q_D(const QFxPaintedItem);
+ return d->fillColor;
+}
+
+
QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfxpainteditem.h b/src/declarative/fx/qfxpainteditem.h
index b7db2d9..6cb8fe7 100644
--- a/src/declarative/fx/qfxpainteditem.h
+++ b/src/declarative/fx/qfxpainteditem.h
@@ -59,6 +59,7 @@ class Q_DECLARATIVE_EXPORT QFxPaintedItem : public QFxItem
Q_PROPERTY(QSize contentsSize READ contentsSize WRITE setContentsSize)
Q_PROPERTY(bool smooth READ isSmooth WRITE setSmooth)
+ Q_PROPERTY(QColor fillColor READ fillColor WRITE setFillColor NOTIFY fillColorChanged)
Q_PROPERTY(int cacheSize READ cacheSize WRITE setCacheSize)
public:
@@ -80,11 +81,17 @@ public:
int cacheSize() const;
void setCacheSize(int pixels);
+ QColor fillColor() const;
+ void setFillColor(const QColor&);
+
protected:
QFxPaintedItem(QFxPaintedItemPrivate &dd, QFxItem *parent);
virtual void drawContents(QPainter *p, const QRect &) = 0;
+Q_SIGNALS:
+ void fillColorChanged();
+
protected Q_SLOTS:
void dirtyCache(const QRect &);
void clearCache();
diff --git a/src/declarative/fx/qfxpainteditem_p.h b/src/declarative/fx/qfxpainteditem_p.h
index 21ac556..4e953a0 100644
--- a/src/declarative/fx/qfxpainteditem_p.h
+++ b/src/declarative/fx/qfxpainteditem_p.h
@@ -68,7 +68,7 @@ class QFxPaintedItemPrivate : public QFxItemPrivate
public:
QFxPaintedItemPrivate()
- : max_imagecache_size(100000), smooth(false)
+ : max_imagecache_size(100000), smooth(false), fillColor(Qt::transparent)
{
}
@@ -89,6 +89,7 @@ public:
int max_imagecache_size;
bool smooth;
QSize contentsSize;
+ QColor fillColor;
};
QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfxwebview.cpp b/src/declarative/fx/qfxwebview.cpp
index adb33e8..f4a06ce 100644
--- a/src/declarative/fx/qfxwebview.cpp
+++ b/src/declarative/fx/qfxwebview.cpp
@@ -428,12 +428,6 @@ void QFxWebView::setInteractive(bool i)
emit interactiveChanged();
}
-void QFxWebView::updateCacheForVisibility()
-{
- if (!isVisible())
- clearCache();
-}
-
void QFxWebView::expandToWebPage()
{
Q_D(QFxWebView);
@@ -845,7 +839,6 @@ void QFxWebView::setPage(QWebPage *page)
d->idealheight>0 ? d->idealheight : -1));
d->page->mainFrame()->setScrollBarPolicy(Qt::Horizontal,Qt::ScrollBarAlwaysOff);
d->page->mainFrame()->setScrollBarPolicy(Qt::Vertical,Qt::ScrollBarAlwaysOff);
- connect(this,SIGNAL(visibleChanged()),this,SLOT(updateCacheForVisibility()));
connect(d->page,SIGNAL(repaintRequested(QRect)),this,SLOT(paintPage(QRect)));
connect(d->page->mainFrame(),SIGNAL(urlChanged(QUrl)),this,SIGNAL(urlChanged()));
connect(d->page->mainFrame(), SIGNAL(titleChanged(QString)), this, SIGNAL(titleChanged(QString)));
diff --git a/src/declarative/fx/qfxwebview.h b/src/declarative/fx/qfxwebview.h
index c9a62cc..0ac1895 100644
--- a/src/declarative/fx/qfxwebview.h
+++ b/src/declarative/fx/qfxwebview.h
@@ -179,7 +179,6 @@ Q_SIGNALS:
void doubleClick();
private Q_SLOTS:
- void updateCacheForVisibility();
void expandToWebPage();
void paintPage(const QRect&);
void doLoadProgress(int p);
diff --git a/src/declarative/qml/qmlbasicscript.cpp b/src/declarative/qml/qmlbasicscript.cpp
index a679532..f02a176 100644
--- a/src/declarative/qml/qmlbasicscript.cpp
+++ b/src/declarative/qml/qmlbasicscript.cpp
@@ -830,7 +830,8 @@ QVariant QmlBasicScript::run(QmlContext *context, void *voidCache, CacheState *c
if (n.type == QmlBasicScriptNodeCache::Invalid || state == Reset) {
context->engine()->d_func()->loadCache(n, QLatin1String(id), static_cast<QmlContextPrivate*>(context->d_ptr));
- state = Incremental;
+ if (state != Reset)
+ state = Incremental;
}
if(!n.isValid())
@@ -855,7 +856,8 @@ QVariant QmlBasicScript::run(QmlContext *context, void *voidCache, CacheState *c
} else if (n.type == QmlBasicScriptNodeCache::Invalid || state == Reset) {
context->engine()->d_func()->fetchCache(n, QLatin1String(id), obj);
guard(n);
- state = Incremental;
+ if (state != Reset)
+ state = Incremental;
} else if (!valid(n, obj)) {
clearCache(dataCache);
*cached = Reset;
diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp
index 8297ac4..cb0c571 100644
--- a/src/declarative/qml/qmlcompiler.cpp
+++ b/src/declarative/qml/qmlcompiler.cpp
@@ -570,7 +570,10 @@ void QmlCompiler::compileTree(Object *tree)
bool QmlCompiler::compileObject(Object *obj, const BindingContext &ctxt)
{
Q_ASSERT (obj->type != -1);
- obj->metatype = output->types.at(obj->type).metaObject();
+ const QmlCompiledData::TypeReference &tr = output->types.at(obj->type);
+ obj->metatype = tr.metaObject();
+ if (tr.component)
+ obj->url = tr.component->url();
if (output->types.at(obj->type).className == "Component") {
COMPILE_CHECK(compileComponent(obj, ctxt));
diff --git a/src/declarative/qml/qmlcomponent.cpp b/src/declarative/qml/qmlcomponent.cpp
index f90af4a..3429813 100644
--- a/src/declarative/qml/qmlcomponent.cpp
+++ b/src/declarative/qml/qmlcomponent.cpp
@@ -296,6 +296,7 @@ QmlComponent::QmlComponent(QmlEngine *engine, QmlCompiledComponent *cc, int star
cc->addref();
d->start = start;
d->count = count;
+ d->url = cc->url;
}
/*!
diff --git a/src/declarative/qml/qmldom.cpp b/src/declarative/qml/qmldom.cpp
index d2608c8..42b40b6 100644
--- a/src/declarative/qml/qmldom.cpp
+++ b/src/declarative/qml/qmldom.cpp
@@ -791,6 +791,16 @@ int QmlDomObject::length() const
return 0;
}
+// Returns the URL of the type, if it is an external type, or an empty URL if
+// not
+QUrl QmlDomObject::url() const
+{
+ if (d && d->object)
+ return d->object->url;
+ else
+ return QUrl();
+}
+
QmlDomBasicValuePrivate::QmlDomBasicValuePrivate()
: value(0)
{
diff --git a/src/declarative/qml/qmldom.h b/src/declarative/qml/qmldom.h
index fde35a8..ab3e39f 100644
--- a/src/declarative/qml/qmldom.h
+++ b/src/declarative/qml/qmldom.h
@@ -143,6 +143,7 @@ public:
int position() const;
int length() const;
+ QUrl url() const;
private:
friend class QmlDomDocument;
friend class QmlDomComponent;
diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp
index 36b6424..8c926b7 100644
--- a/src/declarative/qml/qmlengine.cpp
+++ b/src/declarative/qml/qmlengine.cpp
@@ -1160,14 +1160,26 @@ QVariant QmlExpression::value()
}
rv = QVariant::fromValue(list);
}
- } else if (svalue.isObject()) {
+ } else if (svalue.isObject() &&
+ !svalue.isNumber() &&
+ !svalue.isString() &&
+ !svalue.isDate() &&
+ !svalue.isError() &&
+ !svalue.isFunction() &&
+ !svalue.isNull() &&
+ !svalue.isQMetaObject() &&
+ !svalue.isQObject() &&
+ !svalue.isRegExp()) {
QScriptValue objValue = svalue.data();
- if (objValue.isValid())
- rv = objValue.toVariant();
+ if (objValue.isValid()) {
+ QVariant var = objValue.toVariant();
+ if (var.userType() >= (int)QVariant::UserType &&
+ QmlMetaType::isObject(var.userType()))
+ rv = var;
+ }
}
- if (rv.isNull()) {
+ if (rv.isNull())
rv = svalue.toVariant();
- }
for (int i = 0; i < context()->d_func()->scopeChain.size(); ++i) {
scriptEngine->currentContext()->popScope();
diff --git a/src/declarative/qml/qmlparser_p.h b/src/declarative/qml/qmlparser_p.h
index a38ce69..78040da 100644
--- a/src/declarative/qml/qmlparser_p.h
+++ b/src/declarative/qml/qmlparser_p.h
@@ -102,6 +102,8 @@ namespace QmlParser
// QmlCompiledData::types array, or -1 if the object is a fetched
// object.
int type;
+ // The url of this object if it is an external type. Used by the DOM
+ QUrl url;
// The name of this type
QByteArray typeName;
// The id assigned to the object (if any).
diff --git a/src/declarative/util/qmlanimation.cpp b/src/declarative/util/qmlanimation.cpp
index 7df249e..2a6cad9 100644
--- a/src/declarative/util/qmlanimation.cpp
+++ b/src/declarative/util/qmlanimation.cpp
@@ -255,6 +255,44 @@ void QmlAbstractAnimation::setRunning(bool r)
emit runningChanged(d->running);
}
+/*!
+ \qmlproperty bool Animation::paused
+ This property holds whether the animation is currently paused.
+
+ The \c paused property can be set to declaratively control whether or not
+ an animation is paused.
+
+ Animations can also be paused and resumed imperatively from JavaScript
+ using the \c pause() and \c resume() methods.
+
+ By default, animations are not paused.
+*/
+bool QmlAbstractAnimation::isPaused() const
+{
+ Q_D(const QmlAbstractAnimation);
+ return d->paused;
+}
+
+void QmlAbstractAnimation::setPaused(bool p)
+{
+ Q_D(QmlAbstractAnimation);
+ if (d->paused == p)
+ return;
+
+ if (d->group) {
+ qWarning("QmlAbstractAnimation: setPaused() cannot be used on non-root animation nodes");
+ return;
+ }
+
+ d->paused = p;
+ if (d->paused)
+ qtAnimation()->pause();
+ else
+ qtAnimation()->resume();
+
+ emit pausedChanged(d->running);
+}
+
void QmlAbstractAnimation::classBegin()
{
Q_D(QmlAbstractAnimation);
@@ -430,6 +468,30 @@ void QmlAbstractAnimation::start()
}
/*!
+ \qmlmethod Animation::pause()
+ \brief Pauses the animation.
+
+ If the animation is already paused, calling this method has no effect. The
+ \c paused property will be true following a call to \c pause().
+*/
+void QmlAbstractAnimation::pause()
+{
+ setPaused(true);
+}
+
+/*!
+ \qmlmethod Animation::resume()
+ \brief Resumes a paused animation.
+
+ If the animation is not paused, calling this method has no effect. The
+ \c paused property will be false following a call to \c resume().
+*/
+void QmlAbstractAnimation::resume()
+{
+ setPaused(false);
+}
+
+/*!
\qmlmethod Animation::stop()
\brief Stops the animation.
diff --git a/src/declarative/util/qmlanimation.h b/src/declarative/util/qmlanimation.h
index 5ab9dda..0452159 100644
--- a/src/declarative/util/qmlanimation.h
+++ b/src/declarative/util/qmlanimation.h
@@ -65,6 +65,7 @@ class QmlAbstractAnimation : public QmlPropertyValueSource, public QmlParserStat
Q_INTERFACES(QmlParserStatus)
Q_PROPERTY(bool running READ isRunning WRITE setRunning NOTIFY runningChanged)
+ Q_PROPERTY(bool paused READ isPaused WRITE setPaused NOTIFY pausedChanged)
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)
@@ -78,6 +79,8 @@ public:
bool isRunning() const;
void setRunning(bool);
+ bool isPaused() const;
+ void setPaused(bool);
bool finishPlaying() const;
void setFinishPlaying(bool);
bool repeat() const;
@@ -100,6 +103,7 @@ Q_SIGNALS:
void started();
void completed();
void runningChanged(bool);
+ void pausedChanged(bool);
void repeatChanged(bool);
void targetChanged(QObject *, const QString &);
void finishPlayingChanged(bool);
@@ -107,6 +111,8 @@ Q_SIGNALS:
public Q_SLOTS:
void restart();
void start();
+ void pause();
+ void resume();
void stop();
void complete();
diff --git a/src/declarative/util/qmlanimation_p.h b/src/declarative/util/qmlanimation_p.h
index e5a7384..f09ab88 100644
--- a/src/declarative/util/qmlanimation_p.h
+++ b/src/declarative/util/qmlanimation_p.h
@@ -172,11 +172,12 @@ class QmlAbstractAnimationPrivate : public QObjectPrivate
Q_DECLARE_PUBLIC(QmlAbstractAnimation)
public:
QmlAbstractAnimationPrivate()
- : running(false), finishPlaying(false), repeat(false),
+ : running(false), paused(false), finishPlaying(false), repeat(false),
connectedTimeLine(false), componentComplete(true), startOnCompletion(false),
target(0), group(0) {}
bool running;
+ bool paused;
bool finishPlaying;
bool repeat;
bool connectedTimeLine;
diff --git a/src/declarative/util/qmlfollow.cpp b/src/declarative/util/qmlfollow.cpp
index d1ecac4..cf3d629 100644
--- a/src/declarative/util/qmlfollow.cpp
+++ b/src/declarative/util/qmlfollow.cpp
@@ -93,11 +93,11 @@ void QmlFollowPrivate::tick(int time)
if (!elapsed)
return;
if (mode == Spring) {
- if (elapsed < 10) // capped at 100fps.
+ if (elapsed < 16) // capped at 62fps.
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;
+ int count = (elapsed+8) / 16;
for (int i = 0; i < count; ++i) {
qreal diff = sourceValue - currentValue;
velocity = velocity + spring * diff - damping * velocity;
@@ -110,14 +110,14 @@ void QmlFollowPrivate::tick(int time)
else if (velocity < -maxVelocity)
velocity = -maxVelocity;
}
- currentValue += velocity * 10.0 / 1000.0;
+ currentValue += velocity * 16.0 / 1000.0;
}
if (qAbs(velocity) < epsilon && qAbs(sourceValue - currentValue) < epsilon) {
velocity = 0.0;
currentValue = sourceValue;
clock.stop();
}
- lastTime = time - (elapsed - count * 10);
+ lastTime = time - (elapsed - count * 16);
} else {
qreal moveBy = elapsed * velocityms;
qreal diff = sourceValue - currentValue;
diff --git a/src/declarative/util/qmlstate.cpp b/src/declarative/util/qmlstate.cpp
index abe8301..0574224 100644
--- a/src/declarative/util/qmlstate.cpp
+++ b/src/declarative/util/qmlstate.cpp
@@ -234,19 +234,6 @@ QmlState &QmlState::operator<<(QmlStateOperation *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::applyBindings()
{
foreach(const Action &action, bindingsList) {
@@ -282,12 +269,16 @@ void QmlStatePrivate::complete()
emit q->completed();
}
-QmlStateOperation::ActionList QmlStatePrivate::generateActionList(QmlStateGroup *group) const
+// Generate a list of actions for this state. This includes coelescing state
+// actions that this state "extends"
+QmlStateOperation::ActionList
+QmlStatePrivate::generateActionList(QmlStateGroup *group) const
{
QmlStateOperation::ActionList applyList;
if (inState)
return applyList;
+ // Prevent "extends" recursion
inState = true;
if (!extends.isEmpty()) {
@@ -336,12 +327,19 @@ void QmlState::apply(QmlStateGroup *group, QmlTransition *trans, QmlState *rever
d->reverting.clear();
d->bindingsList.clear();
- if (revert)
- d->revertList = static_cast<QmlStatePrivate*>(revert->d_ptr)->revertList;
- QmlStateOperation::RevertActionList additionalReverts;
+ if (revert) {
+ QmlStatePrivate *revertPrivate =
+ static_cast<QmlStatePrivate*>(revert->d_ptr);
+ d->revertList = revertPrivate->revertList;
+ revertPrivate->revertList.clear();
+ }
+ // List of actions caused by this state
QmlStateOperation::ActionList applyList = d->generateActionList(group);
+ // List of actions that need to be reverted to roll back (just) this state
+ QmlStatePrivate::SimpleActionList additionalReverts;
+ // First add the reverse of all the applyList actions
for (int ii = 0; ii < applyList.count(); ++ii) {
const Action &action = applyList.at(ii);
if (action.event || !action.restore)
@@ -353,10 +351,15 @@ void QmlState::apply(QmlStateGroup *group, QmlTransition *trans, QmlState *rever
found = true;
}
if (!found) {
- RevertAction r(action);
+ // Only need to revert the applyList action if the previous
+ // state doesn't have a higher priority revert already
+ SimpleAction r(action);
additionalReverts << r;
}
}
+
+ // Any reverts from a previous state that aren't carried forth
+ // into this state need to be translated into apply actions
for (int ii = 0; ii < d->revertList.count(); ++ii) {
bool found = false;
for (int jj = 0; !found && jj < applyList.count(); ++jj) {
@@ -376,26 +379,41 @@ void QmlState::apply(QmlStateGroup *group, QmlTransition *trans, QmlState *rever
a.bv = d->revertList.at(ii).bv;
}
applyList << a;
+ // Store these special reverts in the reverting list
d->reverting << d->revertList.at(ii).property;
}
}
+ // All the local reverts now become part of the ongoing revertList
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;
+ // Output for debugging
+ if (stateChangeDebug()) {
+ foreach(const Action &action, applyList) {
+ qWarning() << " Action:" << action.property.object()
+ << action.property.name() << action.toValue;
+ }
+ }
+ // Determine which actions are binding changes.
+ foreach(const Action &action, applyList) {
if (action.bv && !action.toBinding.isEmpty()) {
d->bindingsList << action;
action.bv->clearExpression();
}
}
+ // Animated transitions need both the start and the end value for
+ // each property change. In the presence of bindings, the end values
+ // are non-trivial to calculate. As a "best effort" attempt, we first
+ // apply all the property and binding changes, then read all the actual
+ // final values, then roll back the changes and proceed as normal.
+ //
+ // This doesn't catch everything, and it might be a little fragile in
+ // some cases - but whatcha going to do?
+
if (!d->bindingsList.isEmpty()) {
+
+ // Apply all the property and binding changes
foreach(const Action &action, applyList) {
if (action.bv && !action.toBinding.isEmpty()) {
action.bv->setExpression(action.toBinding);
@@ -404,6 +422,7 @@ void QmlState::apply(QmlStateGroup *group, QmlTransition *trans, QmlState *rever
}
}
+ // Read all the end values for binding changes
for (int ii = 0; ii < applyList.size(); ++ii) {
Action *action = &applyList[ii];
if (action->event)
@@ -415,6 +434,7 @@ void QmlState::apply(QmlStateGroup *group, QmlTransition *trans, QmlState *rever
}
}
+ // Revert back to the original values
foreach(const Action &action, applyList) {
if (action.event)
continue;
@@ -424,36 +444,44 @@ void QmlState::apply(QmlStateGroup *group, QmlTransition *trans, QmlState *rever
action.property.write(action.fromValue);
}
}
- ////////////////////////////////////////////////////////////////////
- QmlStateOperation::ActionList modList = applyList;
- QList<QmlMetaProperty> touched;
+
d->completeList.clear();
+
if (trans) {
+ QList<QmlMetaProperty> touched;
d->transition = trans;
- trans->prepare(modList, touched, this);
- for (int ii = 0; ii < modList.count(); ++ii) {
- const Action &action = modList.at(ii);
+ trans->prepare(applyList, touched, this);
+
+ // Modify the action list to remove actions handled in the transition
+ for (int ii = 0; ii < applyList.count(); ++ii) {
+ const Action &action = applyList.at(ii);
if (action.event) {
+
if (action.actionDone) {
- modList.removeAt(ii);
+ applyList.removeAt(ii);
--ii;
}
+
} else {
- if (action.toValue != action.fromValue) {
- d->completeList << RevertAction(action, false);
- }
if (touched.contains(action.property)) {
- modList.removeAt(ii);
+ if (action.toValue != action.fromValue)
+ d->completeList << SimpleAction(action,
+ SimpleAction::EndState);
+
+ applyList.removeAt(ii);
--ii;
}
+
}
}
}
- foreach(const Action &action, modList) {
+ // Any actions remaining have not been handled by the transition and should
+ // be applied immediately
+ foreach(const Action &action, applyList) {
if (action.event)
action.event->execute();
else
diff --git a/src/declarative/util/qmlstate.h b/src/declarative/util/qmlstate.h
index 0b8d82a..59ef812 100644
--- a/src/declarative/util/qmlstate.h
+++ b/src/declarative/util/qmlstate.h
@@ -79,28 +79,6 @@ public:
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
{
@@ -109,7 +87,6 @@ public:
QmlStateOperation(QObject *parent = 0)
: QObject(parent) {}
typedef QList<Action> ActionList;
- typedef QList<RevertAction> RevertActionList;
virtual ActionList actions();
diff --git a/src/declarative/util/qmlstate_p.h b/src/declarative/util/qmlstate_p.h
index da8fdcd..7fcbcd7 100644
--- a/src/declarative/util/qmlstate_p.h
+++ b/src/declarative/util/qmlstate_p.h
@@ -48,6 +48,29 @@
QT_BEGIN_NAMESPACE
+class SimpleAction
+{
+public:
+ enum State { StartState, EndState };
+ SimpleAction(const Action &a, State state = StartState) : bv(0)
+ {
+ property = a.property;
+ if (state == StartState) {
+ 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 QmlStatePrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QmlState)
@@ -56,13 +79,15 @@ public:
QmlStatePrivate()
: when(0), transition(0), inState(false), group(0) {}
+ typedef QList<SimpleAction> SimpleActionList;
+
QString name;
QmlBindableValue *when;
QmlConcreteList<QmlStateOperation *> operations;
QmlTransition *transition;
- QmlStateOperation::RevertActionList revertList;
+ SimpleActionList revertList;
QList<QmlMetaProperty> reverting;
- QmlStateOperation::RevertActionList completeList;
+ SimpleActionList completeList;
QmlStateOperation::ActionList bindingsList;
QString extends;
mutable bool inState;