summaryrefslogtreecommitdiffstats
path: root/src/declarative/util
diff options
context:
space:
mode:
authorRoberto Raggi <roberto.raggi@nokia.com>2010-02-23 08:44:01 (GMT)
committerRoberto Raggi <roberto.raggi@nokia.com>2010-02-23 08:44:01 (GMT)
commitab3a625e1bc03481f740a32cdbe8c4559cf7cb1e (patch)
tree01adb2ad207b9a2980492a24cb820925f7e48635 /src/declarative/util
parent20fc9f2e264f34dd8580949ddbe5511b78ab0ac4 (diff)
parent48161233af2a6071bc0ba99e546da98f705b8281 (diff)
downloadQt-ab3a625e1bc03481f740a32cdbe8c4559cf7cb1e.zip
Qt-ab3a625e1bc03481f740a32cdbe8c4559cf7cb1e.tar.gz
Qt-ab3a625e1bc03481f740a32cdbe8c4559cf7cb1e.tar.bz2
Merge remote branch 'origin/master' into qtruntime
Diffstat (limited to 'src/declarative/util')
-rw-r--r--src/declarative/util/qmlanimation.cpp164
-rw-r--r--src/declarative/util/qmlanimation_p.h9
-rw-r--r--src/declarative/util/qmlanimation_p_p.h2
-rw-r--r--src/declarative/util/qmlpropertychanges.cpp4
-rw-r--r--src/declarative/util/qmlstate.cpp2
-rw-r--r--src/declarative/util/qmlstategroup.cpp2
-rw-r--r--src/declarative/util/qmlstateoperations.cpp1
-rw-r--r--src/declarative/util/qmltransitionmanager.cpp2
-rw-r--r--src/declarative/util/qmlview.cpp60
-rw-r--r--src/declarative/util/qmlview.h3
-rw-r--r--src/declarative/util/qmlxmllistmodel.cpp179
11 files changed, 239 insertions, 189 deletions
diff --git a/src/declarative/util/qmlanimation.cpp b/src/declarative/util/qmlanimation.cpp
index c044f97..2f24167 100644
--- a/src/declarative/util/qmlanimation.cpp
+++ b/src/declarative/util/qmlanimation.cpp
@@ -66,79 +66,6 @@
QT_BEGIN_NAMESPACE
-static QEasingCurve stringToCurve(const QString &curve, QObject *obj)
-{
- QEasingCurve easingCurve;
-
- QString normalizedCurve = curve;
- bool hasParams = curve.contains(QLatin1Char('('));
- QStringList props;
-
- if (hasParams) {
- QString easeName = curve.trimmed();
- if (!easeName.endsWith(QLatin1Char(')'))) {
- qmlInfo(obj) << QmlPropertyAnimation::tr("Unmatched parenthesis in easing function \"%1\"").arg(curve);
- return easingCurve;
- }
-
- int idx = easeName.indexOf(QLatin1Char('('));
- QString prop_str =
- easeName.mid(idx + 1, easeName.length() - 1 - idx - 1);
- normalizedCurve = easeName.left(idx);
- if (!normalizedCurve.startsWith(QLatin1String("ease"))) {
- qmlInfo(obj) << QmlPropertyAnimation::tr("Easing function \"%1\" must start with \"ease\"").arg(curve);
- return easingCurve;
- }
-
- props = prop_str.split(QLatin1Char(','));
- }
-
- if (normalizedCurve.startsWith(QLatin1String("ease")))
- normalizedCurve = normalizedCurve.mid(4);
-
- static int index = QEasingCurve::staticMetaObject.indexOfEnumerator("Type");
- static QMetaEnum me = QEasingCurve::staticMetaObject.enumerator(index);
-
- int value = me.keyToValue(normalizedCurve.toUtf8().constData());
- if (value < 0) {
- qmlInfo(obj) << QmlPropertyAnimation::tr("Unknown easing curve \"%1\"").arg(curve);
- return easingCurve;
- }
- easingCurve.setType((QEasingCurve::Type)value);
-
- if (hasParams) {
- foreach(const QString &str, props) {
- int sep = str.indexOf(QLatin1Char(':'));
-
- if (sep == -1) {
- qmlInfo(obj) << QmlPropertyAnimation::tr("Improperly specified parameter in easing function \"%1\"").arg(curve);
- continue;
- }
-
- QString propName = str.left(sep).trimmed();
- bool isOk;
- qreal propValue = str.mid(sep + 1).trimmed().toDouble(&isOk);
-
- if (propName.isEmpty() || !isOk) {
- qmlInfo(obj) << QmlPropertyAnimation::tr("Improperly specified parameter in easing function \"%1\"").arg(curve);
- continue;
- }
-
- if (propName == QLatin1String("amplitude")) {
- easingCurve.setAmplitude(propValue);
- } else if (propName == QLatin1String("period")) {
- easingCurve.setPeriod(propValue);
- } else if (propName == QLatin1String("overshoot")) {
- easingCurve.setOvershoot(propValue);
- } else {
- qmlInfo(obj) << QmlPropertyAnimation::tr("Unknown easing parameter \"%1\"").arg(propName);
- continue;
- }
- }
- }
- return easingCurve;
-}
-
QML_DEFINE_NOCREATE_TYPE(QmlAbstractAnimation)
/*!
@@ -793,7 +720,6 @@ void QmlScriptActionPrivate::execute()
const QString &str = scriptStr.script();
if (!str.isEmpty()) {
QmlExpression expr(scriptStr.context(), str, scriptStr.scopeObject());
- expr.setTrackChange(false);
expr.value();
}
}
@@ -1928,195 +1854,195 @@ void QmlPropertyAnimation::setTo(const QVariant &t)
}
/*!
- \qmlproperty string PropertyAnimation::easing
+ \qmlproperty QEasingCurve PropertyAnimation::easing
\brief the easing curve used for the transition.
Available values are:
\table
\row
- \o \c easeLinear
+ \o \c Linear
\o Easing curve for a linear (t) function: velocity is constant.
\o \inlineimage qeasingcurve-linear.png
\row
- \o \c easeInQuad
+ \o \c InQuad
\o Easing curve for a quadratic (t^2) function: accelerating from zero velocity.
\o \inlineimage qeasingcurve-inquad.png
\row
- \o \c easeOutQuad
+ \o \c OutQuad
\o Easing curve for a quadratic (t^2) function: decelerating to zero velocity.
\o \inlineimage qeasingcurve-outquad.png
\row
- \o \c easeInOutQuad
+ \o \c InOutQuad
\o Easing curve for a quadratic (t^2) function: acceleration until halfway, then deceleration.
\o \inlineimage qeasingcurve-inoutquad.png
\row
- \o \c easeOutInQuad
+ \o \c OutInQuad
\o Easing curve for a quadratic (t^2) function: deceleration until halfway, then acceleration.
\o \inlineimage qeasingcurve-outinquad.png
\row
- \o \c easeInCubic
+ \o \c InCubic
\o Easing curve for a cubic (t^3) function: accelerating from zero velocity.
\o \inlineimage qeasingcurve-incubic.png
\row
- \o \c easeOutCubic
+ \o \c OutCubic
\o Easing curve for a cubic (t^3) function: decelerating from zero velocity.
\o \inlineimage qeasingcurve-outcubic.png
\row
- \o \c easeInOutCubic
+ \o \c InOutCubic
\o Easing curve for a cubic (t^3) function: acceleration until halfway, then deceleration.
\o \inlineimage qeasingcurve-inoutcubic.png
\row
- \o \c easeOutInCubic
+ \o \c OutInCubic
\o Easing curve for a cubic (t^3) function: deceleration until halfway, then acceleration.
\o \inlineimage qeasingcurve-outincubic.png
\row
- \o \c easeInQuart
+ \o \c InQuart
\o Easing curve for a quartic (t^4) function: accelerating from zero velocity.
\o \inlineimage qeasingcurve-inquart.png
\row
- \o \c easeOutQuart
+ \o \c OutQuart
\o Easing curve for a cubic (t^4) function: decelerating from zero velocity.
\o \inlineimage qeasingcurve-outquart.png
\row
- \o \c easeInOutQuart
+ \o \c InOutQuart
\o Easing curve for a cubic (t^4) function: acceleration until halfway, then deceleration.
\o \inlineimage qeasingcurve-inoutquart.png
\row
- \o \c easeOutInQuart
+ \o \c OutInQuart
\o Easing curve for a cubic (t^4) function: deceleration until halfway, then acceleration.
\o \inlineimage qeasingcurve-outinquart.png
\row
- \o \c easeInQuint
+ \o \c InQuint
\o Easing curve for a quintic (t^5) function: accelerating from zero velocity.
\o \inlineimage qeasingcurve-inquint.png
\row
- \o \c easeOutQuint
+ \o \c OutQuint
\o Easing curve for a cubic (t^5) function: decelerating from zero velocity.
\o \inlineimage qeasingcurve-outquint.png
\row
- \o \c easeInOutQuint
+ \o \c InOutQuint
\o Easing curve for a cubic (t^5) function: acceleration until halfway, then deceleration.
\o \inlineimage qeasingcurve-inoutquint.png
\row
- \o \c easeOutInQuint
+ \o \c OutInQuint
\o Easing curve for a cubic (t^5) function: deceleration until halfway, then acceleration.
\o \inlineimage qeasingcurve-outinquint.png
\row
- \o \c easeInSine
+ \o \c InSine
\o Easing curve for a sinusoidal (sin(t)) function: accelerating from zero velocity.
\o \inlineimage qeasingcurve-insine.png
\row
- \o \c easeOutSine
+ \o \c OutSine
\o Easing curve for a sinusoidal (sin(t)) function: decelerating from zero velocity.
\o \inlineimage qeasingcurve-outsine.png
\row
- \o \c easeInOutSine
+ \o \c InOutSine
\o Easing curve for a sinusoidal (sin(t)) function: acceleration until halfway, then deceleration.
\o \inlineimage qeasingcurve-inoutsine.png
\row
- \o \c easeOutInSine
+ \o \c OutInSine
\o Easing curve for a sinusoidal (sin(t)) function: deceleration until halfway, then acceleration.
\o \inlineimage qeasingcurve-outinsine.png
\row
- \o \c easeInExpo
+ \o \c InExpo
\o Easing curve for an exponential (2^t) function: accelerating from zero velocity.
\o \inlineimage qeasingcurve-inexpo.png
\row
- \o \c easeOutExpo
+ \o \c OutExpo
\o Easing curve for an exponential (2^t) function: decelerating from zero velocity.
\o \inlineimage qeasingcurve-outexpo.png
\row
- \o \c easeInOutExpo
+ \o \c InOutExpo
\o Easing curve for an exponential (2^t) function: acceleration until halfway, then deceleration.
\o \inlineimage qeasingcurve-inoutexpo.png
\row
- \o \c easeOutInExpo
+ \o \c OutInExpo
\o Easing curve for an exponential (2^t) function: deceleration until halfway, then acceleration.
\o \inlineimage qeasingcurve-outinexpo.png
\row
- \o \c easeInCirc
+ \o \c InCirc
\o Easing curve for a circular (sqrt(1-t^2)) function: accelerating from zero velocity.
\o \inlineimage qeasingcurve-incirc.png
\row
- \o \c easeOutCirc
+ \o \c OutCirc
\o Easing curve for a circular (sqrt(1-t^2)) function: decelerating from zero velocity.
\o \inlineimage qeasingcurve-outcirc.png
\row
- \o \c easeInOutCirc
+ \o \c InOutCirc
\o Easing curve for a circular (sqrt(1-t^2)) function: acceleration until halfway, then deceleration.
\o \inlineimage qeasingcurve-inoutcirc.png
\row
- \o \c easeOutInCirc
+ \o \c OutInCirc
\o Easing curve for a circular (sqrt(1-t^2)) function: deceleration until halfway, then acceleration.
\o \inlineimage qeasingcurve-outincirc.png
\row
- \o \c easeInElastic
+ \o \c InElastic
\o Easing curve for an elastic (exponentially decaying sine wave) function: accelerating from zero velocity.
\br The peak amplitude can be set with the \e amplitude parameter, and the period of decay by the \e period parameter.
\o \inlineimage qeasingcurve-inelastic.png
\row
- \o \c easeOutElastic
+ \o \c OutElastic
\o Easing curve for an elastic (exponentially decaying sine wave) function: decelerating from zero velocity.
\br The peak amplitude can be set with the \e amplitude parameter, and the period of decay by the \e period parameter.
\o \inlineimage qeasingcurve-outelastic.png
\row
- \o \c easeInOutElastic
+ \o \c InOutElastic
\o Easing curve for an elastic (exponentially decaying sine wave) function: acceleration until halfway, then deceleration.
\o \inlineimage qeasingcurve-inoutelastic.png
\row
- \o \c easeOutInElastic
+ \o \c OutInElastic
\o Easing curve for an elastic (exponentially decaying sine wave) function: deceleration until halfway, then acceleration.
\o \inlineimage qeasingcurve-outinelastic.png
\row
- \o \c easeInBack
+ \o \c InBack
\o Easing curve for a back (overshooting cubic function: (s+1)*t^3 - s*t^2) easing in: accelerating from zero velocity.
\o \inlineimage qeasingcurve-inback.png
\row
- \o \c easeOutBack
+ \o \c OutBack
\o Easing curve for a back (overshooting cubic function: (s+1)*t^3 - s*t^2) easing out: decelerating to zero velocity.
\o \inlineimage qeasingcurve-outback.png
\row
- \o \c easeInOutBack
+ \o \c InOutBack
\o Easing curve for a back (overshooting cubic function: (s+1)*t^3 - s*t^2) easing in/out: acceleration until halfway, then deceleration.
\o \inlineimage qeasingcurve-inoutback.png
\row
- \o \c easeOutInBack
+ \o \c OutInBack
\o Easing curve for a back (overshooting cubic easing: (s+1)*t^3 - s*t^2) easing out/in: deceleration until halfway, then acceleration.
\o \inlineimage qeasingcurve-outinback.png
\row
- \o \c easeInBounce
+ \o \c InBounce
\o Easing curve for a bounce (exponentially decaying parabolic bounce) function: accelerating from zero velocity.
\o \inlineimage qeasingcurve-inbounce.png
\row
- \o \c easeOutBounce
+ \o \c OutBounce
\o Easing curve for a bounce (exponentially decaying parabolic bounce) function: decelerating from zero velocity.
\o \inlineimage qeasingcurve-outbounce.png
\row
- \o \c easeInOutBounce
+ \o \c InOutBounce
\o Easing curve for a bounce (exponentially decaying parabolic bounce) function easing in/out: acceleration until halfway, then deceleration.
\o \inlineimage qeasingcurve-inoutbounce.png
\row
- \o \c easeOutInBounce
+ \o \c OutInBounce
\o Easing curve for a bounce (exponentially decaying parabolic bounce) function easing out/in: deceleration until halfway, then acceleration.
\o \inlineimage qeasingcurve-outinbounce.png
\endtable
*/
-QString QmlPropertyAnimation::easing() const
+QEasingCurve QmlPropertyAnimation::easing() const
{
Q_D(const QmlPropertyAnimation);
return d->easing;
}
-void QmlPropertyAnimation::setEasing(const QString &e)
+void QmlPropertyAnimation::setEasing(const QEasingCurve &e)
{
Q_D(QmlPropertyAnimation);
if (d->easing == e)
return;
d->easing = e;
- d->va->setEasingCurve(stringToCurve(d->easing, this));
+ d->va->setEasingCurve(d->easing);
emit easingChanged(e);
}
diff --git a/src/declarative/util/qmlanimation_p.h b/src/declarative/util/qmlanimation_p.h
index 623ad8d..fd868bc 100644
--- a/src/declarative/util/qmlanimation_p.h
+++ b/src/declarative/util/qmlanimation_p.h
@@ -51,6 +51,7 @@
#include <qmlscriptstring.h>
#include <QtCore/qvariant.h>
+#include <QtCore/qeasingcurve.h>
#include <QtCore/QAbstractAnimation>
#include <QtGui/qcolor.h>
@@ -261,7 +262,7 @@ class Q_AUTOTEST_EXPORT QmlPropertyAnimation : public QmlAbstractAnimation
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(QEasingCurve easing READ easing WRITE setEasing NOTIFY easingChanged)
Q_PROPERTY(QObject *target READ target WRITE setTarget NOTIFY targetChanged)
Q_PROPERTY(QString property READ property WRITE setProperty NOTIFY targetChanged)
Q_PROPERTY(QString properties READ properties WRITE setProperties NOTIFY propertiesChanged)
@@ -281,8 +282,8 @@ public:
QVariant to() const;
void setTo(const QVariant &);
- QString easing() const;
- void setEasing(const QString &);
+ QEasingCurve easing() const;
+ void setEasing(const QEasingCurve &);
QObject *target() const;
void setTarget(QObject *);
@@ -307,7 +308,7 @@ Q_SIGNALS:
void durationChanged(int);
void fromChanged(QVariant);
void toChanged(QVariant);
- void easingChanged(const QString &);
+ void easingChanged(const QEasingCurve &);
void propertiesChanged(const QString &);
void targetChanged(QObject *, const QString &);
};
diff --git a/src/declarative/util/qmlanimation_p_p.h b/src/declarative/util/qmlanimation_p_p.h
index 056ce82..8c88f14 100644
--- a/src/declarative/util/qmlanimation_p_p.h
+++ b/src/declarative/util/qmlanimation_p_p.h
@@ -327,7 +327,7 @@ public:
QVariant from;
QVariant to;
- QString easing;
+ QEasingCurve easing;
QObject *target;
QString propertyName;
diff --git a/src/declarative/util/qmlpropertychanges.cpp b/src/declarative/util/qmlpropertychanges.cpp
index 068cb4d..3abbadd 100644
--- a/src/declarative/util/qmlpropertychanges.cpp
+++ b/src/declarative/util/qmlpropertychanges.cpp
@@ -47,7 +47,7 @@
#include <qmlcustomparser_p.h>
#include <qmlparser_p.h>
#include <qmlexpression.h>
-#include <qmlbinding.h>
+#include <qmlbinding_p.h>
#include <qmlcontext.h>
#include <qmlguard_p.h>
@@ -277,14 +277,12 @@ void QmlPropertyChangesPrivate::decode()
QmlMetaProperty prop = property(name); //### better way to check for signal property?
if (prop.type() & QmlMetaProperty::SignalProperty) {
QmlExpression *expression = new QmlExpression(qmlContext(q), data.toString(), object);
- expression->setTrackChange(false);
QmlReplaceSignalHandler *handler = new QmlReplaceSignalHandler;
handler->property = prop;
handler->expression = expression;
signalReplacements << handler;
} else if (isScript) {
QmlExpression *expression = new QmlExpression(qmlContext(q), data.toString(), object);
- expression->setTrackChange(false);
expressions << qMakePair(name, expression);
} else {
properties << qMakePair(name, data);
diff --git a/src/declarative/util/qmlstate.cpp b/src/declarative/util/qmlstate.cpp
index 4462b1f..ea99bd5 100644
--- a/src/declarative/util/qmlstate.cpp
+++ b/src/declarative/util/qmlstate.cpp
@@ -48,7 +48,7 @@
#include "qmlanimation_p.h"
#include "qmlanimation_p_p.h"
-#include <qmlbinding.h>
+#include <qmlbinding_p.h>
#include <qmlglobal_p.h>
#include <QtCore/qdebug.h>
diff --git a/src/declarative/util/qmlstategroup.cpp b/src/declarative/util/qmlstategroup.cpp
index 4ad77c8..7a5db1b 100644
--- a/src/declarative/util/qmlstategroup.cpp
+++ b/src/declarative/util/qmlstategroup.cpp
@@ -44,7 +44,7 @@
#include "qmltransition_p.h"
#include "qmlstate_p_p.h"
-#include <qmlbinding.h>
+#include <qmlbinding_p.h>
#include <qmlglobal_p.h>
#include <QtCore/qdebug.h>
diff --git a/src/declarative/util/qmlstateoperations.cpp b/src/declarative/util/qmlstateoperations.cpp
index bd1f5f0..fff8774 100644
--- a/src/declarative/util/qmlstateoperations.cpp
+++ b/src/declarative/util/qmlstateoperations.cpp
@@ -373,7 +373,6 @@ void QmlStateChangeScript::execute()
const QString &script = d->script.script();
if (!script.isEmpty()) {
QmlExpression expr(d->script.context(), script, d->script.scopeObject());
- expr.setTrackChange(false);
expr.value();
}
}
diff --git a/src/declarative/util/qmltransitionmanager.cpp b/src/declarative/util/qmltransitionmanager.cpp
index f2a4d64..60d9a60 100644
--- a/src/declarative/util/qmltransitionmanager.cpp
+++ b/src/declarative/util/qmltransitionmanager.cpp
@@ -43,7 +43,7 @@
#include "qmlstate_p_p.h"
-#include <qmlbinding.h>
+#include <qmlbinding_p.h>
#include <qmlglobal_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/declarative/util/qmlview.cpp b/src/declarative/util/qmlview.cpp
index 8844430..9e95b66 100644
--- a/src/declarative/util/qmlview.cpp
+++ b/src/declarative/util/qmlview.cpp
@@ -132,6 +132,8 @@ public:
QmlViewPrivate(QmlView *view)
: q(view), root(0), component(0), resizeMode(QmlView::SizeViewToRootObject) {}
+ void execute();
+
QmlView *q;
QGuard<QGraphicsObject> root;
@@ -152,6 +154,20 @@ public:
QGraphicsScene scene;
};
+void QmlViewPrivate::execute()
+{
+ delete root;
+ delete component;
+ component = new QmlComponent(&engine, source, q);
+
+ if (!component->isLoading()) {
+ q->continueExecute();
+ } else {
+ QObject::connect(component, SIGNAL(statusChanged(QmlComponent::Status)), q, SLOT(continueExecute()));
+ }
+}
+
+
/*!
\class QmlView
\brief The QmlView class provides a widget for displaying a Qt Declarative user interface.
@@ -188,9 +204,6 @@ public:
QUrl url(fileName);
view->setSource(url);
- ...
- view->execute();
- ...
view->show();
\endcode
@@ -220,6 +233,19 @@ QmlView::QmlView(QWidget *parent)
d->init();
}
+/*!
+ \fn QmlView::QmlView(const QUrl &source, QWidget *parent)
+
+ Constructs a QmlView with the given QML \a source and \a parent.
+*/
+QmlView::QmlView(const QUrl &source, QWidget *parent)
+: QGraphicsView(parent), d(new QmlViewPrivate(this))
+{
+ setSizePolicy(QSizePolicy::Preferred,QSizePolicy::Preferred);
+ d->init();
+ setSource(source);
+}
+
void QmlViewPrivate::init()
{
#ifdef Q_ENABLE_PERFORMANCE_LOG
@@ -254,15 +280,14 @@ QmlView::~QmlView()
}
/*!
- Sets the source to the \a url.
-
- Call \l execute() to load the QML and instantiate the component.
-
- \sa execute()
+ Sets the source to the \a url, loads the QML component and instantiates it.
*/
void QmlView::setSource(const QUrl& url)
{
- d->source = url;
+ if (url != d->source) {
+ d->source = url;
+ d->execute();
+ }
}
/*!
@@ -296,23 +321,6 @@ QmlContext* QmlView::rootContext()
return d->engine.rootContext();
}
-/*!
- Loads and instantiates the QML component set by the \l setSource() method.
-
- \sa setSource()
-*/
-void QmlView::execute()
-{
- delete d->root;
- delete d->component;
- d->component = new QmlComponent(&d->engine, d->source, this);
-
- if (!d->component->isLoading()) {
- continueExecute();
- } else {
- connect(d->component, SIGNAL(statusChanged(QmlComponent::Status)), this, SLOT(continueExecute()));
- }
-}
/*!
\enum QmlView::Status
diff --git a/src/declarative/util/qmlview.h b/src/declarative/util/qmlview.h
index c5e57c2..26be18f 100644
--- a/src/declarative/util/qmlview.h
+++ b/src/declarative/util/qmlview.h
@@ -67,6 +67,7 @@ class Q_DECLARATIVE_EXPORT QmlView : public QGraphicsView
public:
explicit QmlView(QWidget *parent = 0);
+ QmlView(const QUrl &source, QWidget *parent = 0);
virtual ~QmlView();
QUrl source() const;
@@ -74,7 +75,6 @@ public:
QmlEngine* engine();
QmlContext* rootContext();
- void execute();
QGraphicsObject *rootObject() const;
@@ -103,6 +103,7 @@ protected:
virtual void timerEvent(QTimerEvent*);
virtual void setRootObject(QObject *obj);
+ friend class QmlViewPrivate;
QmlViewPrivate *d;
};
diff --git a/src/declarative/util/qmlxmllistmodel.cpp b/src/declarative/util/qmlxmllistmodel.cpp
index e631cd9..6c9c03e 100644
--- a/src/declarative/util/qmlxmllistmodel.cpp
+++ b/src/declarative/util/qmlxmllistmodel.cpp
@@ -63,6 +63,8 @@ QT_BEGIN_NAMESPACE
QML_DEFINE_TYPE(Qt,4,6,XmlRole,QmlXmlListModelRole)
QML_DEFINE_TYPE(Qt,4,6,XmlListModel,QmlXmlListModel)
+typedef QPair<int, int> QmlXmlListRange;
+
/*!
\qmlclass XmlRole QmlXmlListModelRole
\brief The XmlRole element allows you to specify a role for an XmlListModel.
@@ -94,14 +96,26 @@ QML_DEFINE_TYPE(Qt,4,6,XmlListModel,QmlXmlListModel)
\endqml
*/
+/*!
+ \qmlproperty bool XmlRole::isKey
+ Defines whether this is a key role.
+
+ Key roles are used to to determine whether a set of values should
+ be updated or added to the XML list model when XmlListModel::reload()
+ is called.
+
+ \sa XmlListModel
+*/
+
class Q_DECLARATIVE_EXPORT QmlXmlListModelRole : public QObject
{
Q_OBJECT
Q_PROPERTY(QString name READ name WRITE setName)
Q_PROPERTY(QString query READ query WRITE setQuery)
+ Q_PROPERTY(bool isKey READ isKey WRITE setIsKey)
public:
- QmlXmlListModelRole() {}
+ QmlXmlListModelRole() : m_isKey(false) {}
~QmlXmlListModelRole() {}
QString name() const { return m_name; }
@@ -117,6 +131,9 @@ public:
m_query = query;
}
+ bool isKey() const { return m_isKey; }
+ void setIsKey(bool b) { m_isKey = b; }
+
bool isValid() {
return !m_name.isEmpty() && !m_query.isEmpty();
}
@@ -124,6 +141,7 @@ public:
private:
QString m_name;
QString m_query;
+ bool m_isKey;
};
QT_END_NAMESPACE
QML_DECLARE_TYPE(QmlXmlListModelRole)
@@ -153,7 +171,6 @@ public:
int doQuery(QString query, QString namespaces, QByteArray data, QList<QmlXmlListModelRole *> *roleObjects) {
QMutexLocker locker(&m_mutex);
- m_modelData.clear();
m_size = 0;
m_data = data;
m_query = QLatin1String("doc($src)") + query;
@@ -175,6 +192,16 @@ public:
return m_modelData;
}
+ QList<QmlXmlListRange> insertedItemRanges() {
+ QMutexLocker locker(&m_mutex);
+ return m_insertedItemRanges;
+ }
+
+ QList<QmlXmlListRange> removedItemRanges() {
+ QMutexLocker locker(&m_mutex);
+ return m_removedItemRanges;
+ }
+
Q_SIGNALS:
void queryCompleted(int queryId, int size);
@@ -184,13 +211,12 @@ protected:
m_mutex.lock();
int queryId = m_queryId;
doQueryJob();
- if (m_size > 0)
- doSubQueryJob();
+ doSubQueryJob();
m_data.clear(); // no longer needed
m_mutex.unlock();
m_mutex.lock();
- if (!m_abort && m_size > 0)
+ if (!m_abort)
emit queryCompleted(queryId, m_size);
if (!m_restart)
m_condition.wait(&m_mutex);
@@ -203,6 +229,8 @@ protected:
private:
void doQueryJob();
void doSubQueryJob();
+ void getValuesOfKeyRoles(QStringList *values, QXmlQuery *query) const;
+ void addIndexToRangeList(QList<QmlXmlListRange> *ranges, int index) const;
private:
QMutex m_mutex;
@@ -218,6 +246,9 @@ private:
int m_queryId;
const QList<QmlXmlListModelRole *> *m_roleObjects;
QList<QList<QVariant> > m_modelData;
+ QStringList m_keysValues;
+ QList<QmlXmlListRange> m_insertedItemRanges;
+ QList<QmlXmlListRange> m_removedItemRanges;
};
void QmlXmlQuery::doQueryJob()
@@ -262,6 +293,40 @@ void QmlXmlQuery::doQueryJob()
m_size = count;
}
+void QmlXmlQuery::getValuesOfKeyRoles(QStringList *values, QXmlQuery *query) const
+{
+ QStringList keysQueries;
+ for (int i=0; i<m_roleObjects->count(); i++) {
+ if (m_roleObjects->at(i)->isKey())
+ keysQueries << m_roleObjects->at(i)->query();
+ }
+ QString keysQuery;
+ if (keysQueries.count() == 1)
+ keysQuery = m_prefix + keysQueries[0];
+ else if (keysQueries.count() > 1)
+ keysQuery = m_prefix + QLatin1String("concat(") + keysQueries.join(QLatin1String(",")) + QLatin1String(")");
+
+ if (!keysQuery.isEmpty()) {
+ query->setQuery(keysQuery);
+ QXmlResultItems resultItems;
+ query->evaluateTo(&resultItems);
+ QXmlItem item(resultItems.next());
+ while (!item.isNull()) {
+ values->append(item.toAtomicValue().toString());
+ item = resultItems.next();
+ }
+ }
+}
+
+void QmlXmlQuery::addIndexToRangeList(QList<QmlXmlListRange> *ranges, int index) const {
+ if (ranges->isEmpty())
+ ranges->append(qMakePair(index, 1));
+ else if (ranges->last().first + ranges->last().second == index)
+ ranges->last().second += 1;
+ else
+ ranges->append(qMakePair(index, 1));
+}
+
void QmlXmlQuery::doSubQueryJob()
{
m_modelData.clear();
@@ -272,6 +337,35 @@ void QmlXmlQuery::doSubQueryJob()
QXmlQuery subquery;
subquery.bindVariable(QLatin1String("inputDocument"), &b);
+ QStringList keysValues;
+ getValuesOfKeyRoles(&keysValues, &subquery);
+
+ // See if any values of key roles have been inserted or removed.
+ m_insertedItemRanges.clear();
+ m_removedItemRanges.clear();
+ if (m_keysValues.isEmpty()) {
+ m_insertedItemRanges << qMakePair(0, m_size);
+ } else {
+ if (keysValues != m_keysValues) {
+ QStringList temp;
+ for (int i=0; i<m_keysValues.count(); i++) {
+ if (!keysValues.contains(m_keysValues[i]))
+ addIndexToRangeList(&m_removedItemRanges, i);
+ else
+ temp << m_keysValues[i];
+ }
+
+ for (int i=0; i<keysValues.count(); i++) {
+ if (temp.count() == i || keysValues[i] != temp[i]) {
+ temp.insert(i, keysValues[i]);
+ addIndexToRangeList(&m_insertedItemRanges, i);
+ }
+ }
+ }
+ }
+ m_keysValues = keysValues;
+
+ // Get the new values for each role.
//### we might be able to condense even further (query for everything in one go)
for (int i = 0; i < m_roleObjects->size(); ++i) {
QmlXmlListModelRole *role = m_roleObjects->at(i);
@@ -283,13 +377,13 @@ void QmlXmlQuery::doSubQueryJob()
continue;
}
subquery.setQuery(m_prefix + QLatin1String("(let $v := ") + role->query() + QLatin1String(" return if ($v) then ") + role->query() + QLatin1String(" else \"\")"));
- QXmlResultItems output3;
- subquery.evaluateTo(&output3);
- QXmlItem item(output3.next());
+ QXmlResultItems resultItems;
+ subquery.evaluateTo(&resultItems);
+ QXmlItem item(resultItems.next());
QList<QVariant> resultList;
while (!item.isNull()) {
resultList << item.toAtomicValue(); //### we used to trim strings
- item = output3.next();
+ item = resultItems.next();
}
//### should warn here if things have gone wrong.
while (resultList.count() < m_size)
@@ -392,25 +486,40 @@ void QmlXmlListModelPrivate::clear_role(QmlListProperty<QmlXmlListModelRole> *li
/*!
\qmlclass XmlListModel QmlXmlListModel
- \brief The XmlListModel element allows you to specify a model using XPath expressions.
+ \brief The XmlListModel element is used to specify a model using XPath expressions.
- XmlListModel allows you to construct a model from XML data that can then be used as a data source
- for the view classes (ListView, PathView, GridView) and any other classes that interact with model
- data (like Repeater).
+ XmlListModel is used to create a model from XML data that can be used as a data source
+ for the view classes (such as ListView, PathView, GridView) and other classes that interact with model
+ data (such as Repeater).
- The following is an example of a model containing news from a Yahoo RSS feed:
+ Here is an example of a model containing news from a Yahoo RSS feed:
\qml
XmlListModel {
id: feedModel
source: "http://rss.news.yahoo.com/rss/oceania"
query: "/rss/channel/item"
XmlRole { name: "title"; query: "title/string()" }
- XmlRole { name: "link"; query: "link/string()" }
+ XmlRole { name: "pubDate"; query: "pubDate/string()" }
XmlRole { name: "description"; query: "description/string()" }
}
\endqml
- \note The model is currently static, so the above is really just a snapshot of an RSS feed. To force a
- reload of the entire model, you can call the reload function.
+
+ You can also define certain roles as "keys" so that the model only adds data
+ that contains new values for these keys when reload() is called.
+
+ For example, if the roles above were defined like this:
+
+ \qml
+ XmlRole { name: "title"; query: "title/string()"; isKey: true }
+ XmlRole { name: "pubDate"; query: "pubDate/string()"; isKey: true }
+ \endqml
+
+ Then when reload() is called, the model will only add new items with a
+ "title" and "pubDate" value combination that is not already present in
+ the model.
+
+ This is useful to provide incremental updates and avoid repainting an
+ entire model in a view.
*/
QmlXmlListModel::QmlXmlListModel(QObject *parent)
@@ -526,9 +635,9 @@ void QmlXmlListModel::setXml(const QString &xml)
}
/*!
- \qmlproperty url XmlListModel::query
+ \qmlproperty string XmlListModel::query
An absolute XPath query representing the base query for the model items. The query should start with
- a '/' or '//'.
+ '/' or '//'.
*/
QString QmlXmlListModel::query() const
{
@@ -619,8 +728,13 @@ void QmlXmlListModel::componentComplete()
/*!
\qmlmethod XmlListModel::reload()
- Reloads the model. All the existing model data will be removed, and the model
- will be rebuilt from scratch.
+ Reloads the model.
+
+ If no key roles have been specified, all existing model
+ data is removed, and the model is rebuilt from scratch.
+
+ Otherwise, items are only added if the model does not already
+ contain items with matching key role values.
*/
void QmlXmlListModel::reload()
{
@@ -632,12 +746,8 @@ void QmlXmlListModel::reload()
d->qmlXmlQuery.abort();
d->queryId = -1;
- //clear existing data
- int count = d->size;
- d->size = 0;
- d->data.clear();
- if (count > 0)
- emit itemsRemoved(0, count);
+ if (d->size < 0)
+ d->size = 0;
if (d->src.isEmpty() && d->xml.isEmpty())
return;
@@ -704,12 +814,19 @@ void QmlXmlListModel::queryCompleted(int id, int size)
Q_D(QmlXmlListModel);
if (id != d->queryId)
return;
+ bool sizeChanged = size != d->size;
d->size = size;
- if (size > 0) {
- d->data = d->qmlXmlQuery.modelData();
- emit itemsInserted(0, d->size);
+ d->data = d->qmlXmlQuery.modelData();
+
+ QList<QmlXmlListRange> removed = d->qmlXmlQuery.removedItemRanges();
+ for (int i=0; i<removed.count(); i++)
+ emit itemsRemoved(removed[i].first, removed[i].second);
+ QList<QmlXmlListRange> inserted = d->qmlXmlQuery.insertedItemRanges();
+ for (int i=0; i<inserted.count(); i++)
+ emit itemsInserted(inserted[i].first, inserted[i].second);
+
+ if (sizeChanged)
emit countChanged();
- }
}
QT_END_NAMESPACE