diff options
Diffstat (limited to 'src/declarative/util')
34 files changed, 1735 insertions, 1897 deletions
diff --git a/src/declarative/util/qdeclarativeanimation.cpp b/src/declarative/util/qdeclarativeanimation.cpp index d47dcc5..ba1444e 100644 --- a/src/declarative/util/qdeclarativeanimation.cpp +++ b/src/declarative/util/qdeclarativeanimation.cpp @@ -190,9 +190,13 @@ void QDeclarativeAbstractAnimation::setRunning(bool r) d->running = r; if (d->running) { - if (d->alwaysRunToEnd && d->repeat + if (d->alwaysRunToEnd && d->loopCount != 1 && qtAnimation()->state() == QAbstractAnimation::Running) { - qtAnimation()->setLoopCount(-1); + //we've restarted before the final loop finished; restore proper loop count + if (d->loopCount == -1) + qtAnimation()->setLoopCount(d->loopCount); + else + qtAnimation()->setLoopCount(qtAnimation()->currentLoop() + d->loopCount); } if (!d->connectedTimeLine) { @@ -204,8 +208,8 @@ void QDeclarativeAbstractAnimation::setRunning(bool r) emit started(); } else { if (d->alwaysRunToEnd) { - if (d->repeat) - qtAnimation()->setLoopCount(qtAnimation()->currentLoop()+1); + if (d->loopCount != 1) + qtAnimation()->setLoopCount(qtAnimation()->currentLoop()+1); //finish the current loop } else qtAnimation()->stop(); @@ -300,10 +304,12 @@ void QDeclarativeAbstractAnimation::setAlwaysRunToEnd(bool f) } /*! - \qmlproperty bool Animation::repeat - This property holds whether the animation should repeat. + \qmlproperty int Animation::loops + This property holds the number of times the animation should play. + + By default, \c loops is 1: the animation will play through once and then stop. - If set, the animation will continuously repeat until it is explicitly + If set to Animation.Infinite, 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. @@ -311,28 +317,36 @@ void QDeclarativeAbstractAnimation::setAlwaysRunToEnd(bool f) \code Rectangle { - NumberAnimation on rotation { running: true; repeat: true; from: 0 to: 360 } + width: 100; height: 100; color: "green" + RotationAnimation on rotation { + loops: Animation.Infinite + from: 0 + to: 360 + } } \endcode */ -bool QDeclarativeAbstractAnimation::repeat() const +int QDeclarativeAbstractAnimation::loops() const { Q_D(const QDeclarativeAbstractAnimation); - return d->repeat; + return d->loopCount; } -void QDeclarativeAbstractAnimation::setRepeat(bool r) +void QDeclarativeAbstractAnimation::setLoops(int loops) { Q_D(QDeclarativeAbstractAnimation); - if (r == d->repeat) + if (loops < 0) + loops = -1; + + if (loops == d->loopCount) return; - d->repeat = r; - int lc = r ? -1 : 1; - qtAnimation()->setLoopCount(lc); - emit repeatChanged(r); + d->loopCount = loops; + qtAnimation()->setLoopCount(loops); + emit loopCountChanged(loops); } + int QDeclarativeAbstractAnimation::currentTime() { return qtAnimation()->currentLoopTime(); @@ -509,8 +523,9 @@ void QDeclarativeAbstractAnimation::timelineComplete() { Q_D(QDeclarativeAbstractAnimation); setRunning(false); - if (d->alwaysRunToEnd && d->repeat) { - qtAnimation()->setLoopCount(-1); + if (d->alwaysRunToEnd && d->loopCount != 1) { + //restore the proper loopCount for the next run + qtAnimation()->setLoopCount(d->loopCount); } } @@ -658,6 +673,37 @@ void QDeclarativeColorAnimation::setTo(const QColor &t) \inherits Animation \brief The ScriptAction element allows scripts to be run during an animation. + ScriptAction can be used to run script at a specific point in an animation. + + \qml + SequentialAnimation { + NumberAnimation { ... } + ScriptAction { script: doSomething(); } + NumberAnimation { ... } + } + \endqml + + When used as part of a Transition, you can also target a specific + StateChangeScript to run using the \c scriptName property. + + \qml + State { + StateChangeScript { + name: "myScript" + script: doStateStuff(); + } + } + ... + Transition { + SequentialAnimation { + NumberAnimation { ... } + ScriptAction { scriptName: "myScript" } + NumberAnimation { ... } + } + } + \endqml + + \sa StateChangeScript */ /*! \internal @@ -698,11 +744,14 @@ void QDeclarativeScriptAction::setScript(const QDeclarativeScriptString &script) } /*! - \qmlproperty QString ScriptAction::stateChangeScriptName + \qmlproperty QString ScriptAction::scriptName This property holds the the name of the StateChangeScript to run. This property is only valid when ScriptAction is used as part of a transition. - If both script and stateChangeScriptName are set, stateChangeScriptName will be used. + If both script and scriptName are set, scriptName will be used. + + \note When using scriptName in a reversible transition, the script will only + be run when the transition is being run forwards. */ QString QDeclarativeScriptAction::stateChangeScriptName() const { @@ -718,6 +767,9 @@ void QDeclarativeScriptAction::setStateChangeScriptName(const QString &name) void QDeclarativeScriptActionPrivate::execute() { + if (hasRunScriptScript && reversing) + return; + QDeclarativeScriptString scriptStr = hasRunScriptScript ? runScriptScript : script; const QString &str = scriptStr.script(); @@ -733,19 +785,18 @@ void QDeclarativeScriptAction::transition(QDeclarativeStateActions &actions, { Q_D(QDeclarativeScriptAction); Q_UNUSED(modified); - Q_UNUSED(direction); d->hasRunScriptScript = false; + d->reversing = (direction == Backward); for (int ii = 0; ii < actions.count(); ++ii) { QDeclarativeAction &action = actions[ii]; if (action.event && action.event->typeName() == QLatin1String("StateChangeScript") && static_cast<QDeclarativeStateChangeScript*>(action.event)->name() == d->name) { - //### how should we handle reverse direction? d->runScriptScript = static_cast<QDeclarativeStateChangeScript*>(action.event)->script(); d->hasRunScriptScript = true; action.actionDone = true; - break; //assumes names are unique + break; //only match one (names should be unique) } } } @@ -1006,212 +1057,6 @@ void QDeclarativePropertyAction::transition(QDeclarativeStateActions &actions, } } - - -/*! - \qmlclass ParentAction QDeclarativeParentAction - \since 4.7 - \inherits Animation - \brief The ParentAction element allows parent changes during animation. - - ParentAction provides a way to specify at what point in a Transition a ParentChange should - occur. - \qml - State { - ParentChange { - target: myItem - parent: newParent - } - } - Transition { - SequentialAnimation { - PropertyAnimation { ... } - ParentAction {} //reparent myItem now - PropertyAnimation { ... } - } - } - \endqml - - It also provides a way to explicitly reparent an item during an animation. - \qml - SequentialAnimation { - ParentAction { target: myItem; parent: newParent } - PropertyAnimation {} - } - \endqml - - The ParentAction is immediate - it is not animated in any way. -*/ - -QDeclarativeParentAction::QDeclarativeParentAction(QObject *parent) -: QDeclarativeAbstractAnimation(*(new QDeclarativeParentActionPrivate), parent) -{ - Q_D(QDeclarativeParentAction); - d->init(); -} - -QDeclarativeParentAction::~QDeclarativeParentAction() -{ -} - -void QDeclarativeParentActionPrivate::init() -{ - Q_Q(QDeclarativeParentAction); - cpa = new QActionAnimation; - QDeclarative_setParent_noEvent(cpa, q); -} - -/*! - \qmlproperty Item ParentAction::target - - This property holds a target item to reparent. - - In the following example, \c myItem will be reparented by the ParentAction, while - \c myOtherItem will not. - \qml - State { - ParentChange { - target: myItem - parent: newParent - } - ParentChange { - target: myOtherItem - parent: otherNewParent - } - } - Transition { - SequentialAnimation { - PropertyAnimation { ... } - ParentAction { target: myItem } - PropertyAnimation { ... } - } - } - \endqml - - */ -QDeclarativeItem *QDeclarativeParentAction::object() const -{ - Q_D(const QDeclarativeParentAction); - return d->pcTarget; -} - -void QDeclarativeParentAction::setObject(QDeclarativeItem *target) -{ - Q_D(QDeclarativeParentAction); - d->pcTarget = target; -} - -/*! - \qmlproperty Item ParentAction::parent - - The item to reparent to (i.e. the new parent). - */ -QDeclarativeItem *QDeclarativeParentAction::parent() const -{ - Q_D(const QDeclarativeParentAction); - return d->pcParent; -} - -void QDeclarativeParentAction::setParent(QDeclarativeItem *parent) -{ - Q_D(QDeclarativeParentAction); - d->pcParent = parent; -} - -void QDeclarativeParentActionPrivate::doAction() -{ - QDeclarativeParentChange pc; - pc.setObject(pcTarget); - pc.setParent(pcParent); - pc.execute(); -} - -QAbstractAnimation *QDeclarativeParentAction::qtAnimation() -{ - Q_D(QDeclarativeParentAction); - return d->cpa; -} - -void QDeclarativeParentAction::transition(QDeclarativeStateActions &actions, - QDeclarativeProperties &modified, - TransitionDirection direction) -{ - Q_D(QDeclarativeParentAction); - Q_UNUSED(modified); - Q_UNUSED(direction); - - struct QDeclarativeParentActionData : public QAbstractAnimationAction - { - QDeclarativeParentActionData(): pc(0) {} - ~QDeclarativeParentActionData() { delete pc; } - - QDeclarativeStateActions actions; - bool reverse; - QDeclarativeParentChange *pc; - virtual void doAction() - { - for (int ii = 0; ii < actions.count(); ++ii) { - const QDeclarativeAction &action = actions.at(ii); - if (reverse) - action.event->reverse(); - else - action.event->execute(); - } - } - }; - - QDeclarativeParentActionData *data = new QDeclarativeParentActionData; - - //### need to correctly handle modified/done - - bool hasExplicit = false; - if (d->pcTarget && d->pcParent) { - data->reverse = false; - QDeclarativeAction myAction; - QDeclarativeParentChange *pc = new QDeclarativeParentChange; - pc->setObject(d->pcTarget); - pc->setParent(d->pcParent); - myAction.event = pc; - data->pc = pc; - data->actions << myAction; - hasExplicit = true; - } - - if (!hasExplicit) - for (int ii = 0; ii < actions.count(); ++ii) { - QDeclarativeAction &action = actions[ii]; - - if (action.event && action.event->typeName() == QLatin1String("ParentChange") - && (!d->pcTarget || static_cast<QDeclarativeParentChange*>(action.event)->object() == d->pcTarget)) { - QDeclarativeAction myAction = action; - data->reverse = action.reverseEvent; - //### this logic differs from PropertyAnimation - // (probably a result of modified vs. done) - if (d->pcParent) { - //### should we disallow this case? - QDeclarativeParentChange *pc = new QDeclarativeParentChange; - pc->setObject(d->pcTarget); - pc->setParent(static_cast<QDeclarativeParentChange*>(action.event)->parent()); - myAction.event = pc; - data->pc = pc; - data->actions << myAction; - break; //only match one - } else { - action.actionDone = true; - data->actions << myAction; - } - } - } - - if (data->actions.count()) { - d->cpa->setAnimAction(data, QAbstractAnimation::DeleteWhenStopped); - } else { - delete data; - } -} - - - /*! \qmlclass NumberAnimation QDeclarativeNumberAnimation \since 4.7 @@ -1233,15 +1078,26 @@ void QDeclarativeParentAction::transition(QDeclarativeStateActions &actions, QDeclarativeNumberAnimation::QDeclarativeNumberAnimation(QObject *parent) : QDeclarativePropertyAnimation(parent) { - Q_D(QDeclarativePropertyAnimation); - d->interpolatorType = QMetaType::QReal; - d->interpolator = QVariantAnimationPrivate::getInterpolator(d->interpolatorType); + init(); +} + +QDeclarativeNumberAnimation::QDeclarativeNumberAnimation(QDeclarativePropertyAnimationPrivate &dd, QObject *parent) +: QDeclarativePropertyAnimation(dd, parent) +{ + init(); } QDeclarativeNumberAnimation::~QDeclarativeNumberAnimation() { } +void QDeclarativeNumberAnimation::init() +{ + Q_D(QDeclarativePropertyAnimation); + d->interpolatorType = QMetaType::QReal; + d->interpolator = QVariantAnimationPrivate::getInterpolator(d->interpolatorType); +} + /*! \qmlproperty real NumberAnimation::from This property holds the starting value. @@ -1342,9 +1198,10 @@ void QDeclarativeVector3dAnimation::setTo(QVector3D t) \brief The RotationAnimation element allows you to animate rotations. RotationAnimation is a specialized PropertyAnimation that gives control - over the direction of rotation. By default, it will rotate - via the shortest path; for example, a rotation from 20 to 340 degrees will - rotation 40 degrees counterclockwise. + over the direction of rotation. By default, it will rotate in the direction + of the numerical change; a rotation from 0 to 240 will rotate 220 degrees + clockwise, while a rotation from 240 to 0 will rotate 220 degrees + counterclockwise. When used in a transition RotationAnimation will rotate all properties named "rotation" or "angle". You can override this by providing @@ -1359,7 +1216,7 @@ void QDeclarativeVector3dAnimation::setTo(QVector3D t) State { name: "-90"; PropertyChanges { target: myItem; rotation: -90 } } } transition: Transition { - RotationAnimation { } + RotationAnimation { direction: RotationAnimation.Shortest } } \endqml */ @@ -1411,7 +1268,7 @@ QDeclarativeRotationAnimation::QDeclarativeRotationAnimation(QObject *parent) { Q_D(QDeclarativeRotationAnimation); d->interpolatorType = QMetaType::QReal; - d->interpolator = reinterpret_cast<QVariantAnimation::Interpolator>(&_q_interpolateShortestRotation); + d->interpolator = QVariantAnimationPrivate::getInterpolator(d->interpolatorType); d->defaultProperties = QLatin1String("rotation,angle"); } @@ -1474,7 +1331,7 @@ void QDeclarativeRotationAnimation::setTo(qreal t) A rotation from 10 to 350 will rotate 20 degrees counterclockwise. \endtable - The default direction is Shortest. + The default direction is Numerical. */ QDeclarativeRotationAnimation::RotationDirection QDeclarativeRotationAnimation::direction() const { @@ -1523,8 +1380,8 @@ void QDeclarativeAnimationGroupPrivate::append_animation(QDeclarativeListPropert { QDeclarativeAnimationGroup *q = qobject_cast<QDeclarativeAnimationGroup *>(list->object); if (q) { - q->d_func()->animations.append(a); a->setGroup(q); + QDeclarative_setParent_noEvent(a->qtAnimation(), q->d_func()->ag); q->d_func()->ag->addAnimation(a->qtAnimation()); } } @@ -1755,7 +1612,7 @@ void QDeclarativePropertyAnimationPrivate::convertVariant(QVariant &variant, int \qml Rectangle { SequentialAnimation on x { - repeat: true + loops: Animation.Infinite PropertyAnimation { to: 50 } PropertyAnimation { to: 0 } } @@ -2164,7 +2021,7 @@ void QDeclarativePropertyAnimation::setProperties(const QString &prop) id: theRect width: 100; height: 100 color: Qt.rgba(0,0,1) - NumberAnimation on x { to: 500; repeat: true } //animate theRect's x property + NumberAnimation on x { to: 500; loops: Animation.Infinite } //animate theRect's x property Behavior on y { NumberAnimation {} } //animate theRect's y property } \endqml @@ -2391,8 +2248,10 @@ void QDeclarativePropertyAnimation::transition(QDeclarativeStateActions &actions } d->va->setAnimValue(data, QAbstractAnimation::DeleteWhenStopped); d->va->setFromSourcedValue(&data->fromSourced); + d->actions = &data->actions; } else { delete data; + d->actions = 0; } } @@ -2483,7 +2342,11 @@ QDeclarativeItem *QDeclarativeParentAnimation::target() const void QDeclarativeParentAnimation::setTarget(QDeclarativeItem *target) { Q_D(QDeclarativeParentAnimation); + if (target == d->target) + return; + d->target = target; + emit targetChanged(); } /*! @@ -2501,7 +2364,11 @@ QDeclarativeItem *QDeclarativeParentAnimation::newParent() const void QDeclarativeParentAnimation::setNewParent(QDeclarativeItem *newParent) { Q_D(QDeclarativeParentAnimation); + if (newParent == d->newParent) + return; + d->newParent = newParent; + emit newParentChanged(); } /*! @@ -2526,7 +2393,11 @@ QDeclarativeItem *QDeclarativeParentAnimation::via() const void QDeclarativeParentAnimation::setVia(QDeclarativeItem *via) { Q_D(QDeclarativeParentAnimation); + if (via == d->via) + return; + d->via = via; + emit viaChanged(); } //### mirrors same-named function in QDeclarativeItem @@ -2561,10 +2432,10 @@ void QDeclarativeParentAnimation::transition(QDeclarativeStateActions &actions, { Q_D(QDeclarativeParentAnimation); - struct QDeclarativeParentActionData : public QAbstractAnimationAction + struct QDeclarativeParentAnimationData : public QAbstractAnimationAction { - QDeclarativeParentActionData() {} - ~QDeclarativeParentActionData() { qDeleteAll(pc); } + QDeclarativeParentAnimationData() {} + ~QDeclarativeParentAnimationData() { qDeleteAll(pc); } QDeclarativeStateActions actions; //### reverse should probably apply on a per-action basis @@ -2582,8 +2453,8 @@ void QDeclarativeParentAnimation::transition(QDeclarativeStateActions &actions, } }; - QDeclarativeParentActionData *data = new QDeclarativeParentActionData; - QDeclarativeParentActionData *viaData = new QDeclarativeParentActionData; + QDeclarativeParentAnimationData *data = new QDeclarativeParentAnimationData; + QDeclarativeParentAnimationData *viaData = new QDeclarativeParentAnimationData; bool hasExplicit = false; if (d->target && d->newParent) { diff --git a/src/declarative/util/qdeclarativeanimation_p.h b/src/declarative/util/qdeclarativeanimation_p.h index eb339f6..f620786 100644 --- a/src/declarative/util/qdeclarativeanimation_p.h +++ b/src/declarative/util/qdeclarativeanimation_p.h @@ -70,24 +70,28 @@ class Q_AUTOTEST_EXPORT QDeclarativeAbstractAnimation : public QObject, public Q Q_INTERFACES(QDeclarativeParserStatus) Q_INTERFACES(QDeclarativePropertyValueSource) + Q_ENUMS(Loops) Q_PROPERTY(bool running READ isRunning WRITE setRunning NOTIFY runningChanged) Q_PROPERTY(bool paused READ isPaused WRITE setPaused NOTIFY pausedChanged) - Q_PROPERTY(bool alwaysRunToEnd READ alwaysRunToEnd WRITE setAlwaysRunToEnd NOTIFY alwaysRunToEndChanged()) - Q_PROPERTY(bool repeat READ repeat WRITE setRepeat NOTIFY repeatChanged) + Q_PROPERTY(bool alwaysRunToEnd READ alwaysRunToEnd WRITE setAlwaysRunToEnd NOTIFY alwaysRunToEndChanged) + Q_PROPERTY(int loops READ loops WRITE setLoops NOTIFY loopsChanged) Q_CLASSINFO("DefaultMethod", "start()") public: QDeclarativeAbstractAnimation(QObject *parent=0); virtual ~QDeclarativeAbstractAnimation(); + enum Loops { Infinite = -2 }; + bool isRunning() const; void setRunning(bool); bool isPaused() const; void setPaused(bool); bool alwaysRunToEnd() const; void setAlwaysRunToEnd(bool); - bool repeat() const; - void setRepeat(bool); + + int loops() const; + void setLoops(int); int currentTime(); void setCurrentTime(int); @@ -106,8 +110,8 @@ Q_SIGNALS: void completed(); void runningChanged(bool); void pausedChanged(bool); - void repeatChanged(bool); void alwaysRunToEndChanged(bool); + void loopCountChanged(int); public Q_SLOTS: void restart(); @@ -163,7 +167,7 @@ class QDeclarativeScriptAction : public QDeclarativeAbstractAnimation Q_DECLARE_PRIVATE(QDeclarativeScriptAction) Q_PROPERTY(QDeclarativeScriptString script READ script WRITE setScript) - Q_PROPERTY(QString stateChangeScriptName READ stateChangeScriptName WRITE setStateChangeScriptName) + Q_PROPERTY(QString scriptName READ stateChangeScriptName WRITE setStateChangeScriptName) public: QDeclarativeScriptAction(QObject *parent=0); @@ -227,32 +231,6 @@ protected: }; class QDeclarativeItem; -class QDeclarativeParentActionPrivate; -class QDeclarativeParentAction : public QDeclarativeAbstractAnimation -{ - Q_OBJECT - Q_DECLARE_PRIVATE(QDeclarativeParentAction) - - Q_PROPERTY(QDeclarativeItem *target READ object WRITE setObject) - Q_PROPERTY(QDeclarativeItem *parent READ parent WRITE setParent) //### newParent - -public: - QDeclarativeParentAction(QObject *parent=0); - virtual ~QDeclarativeParentAction(); - - QDeclarativeItem *object() const; - void setObject(QDeclarativeItem *); - - QDeclarativeItem *parent() const; - void setParent(QDeclarativeItem *); - -protected: - virtual void transition(QDeclarativeStateActions &actions, - QDeclarativeProperties &modified, - TransitionDirection direction); - virtual QAbstractAnimation *qtAnimation(); -}; - class QDeclarativePropertyAnimationPrivate; class Q_AUTOTEST_EXPORT QDeclarativePropertyAnimation : public QDeclarativeAbstractAnimation { @@ -273,8 +251,8 @@ public: QDeclarativePropertyAnimation(QObject *parent=0); virtual ~QDeclarativePropertyAnimation(); - int duration() const; - void setDuration(int); + virtual int duration() const; + virtual void setDuration(int); QVariant from() const; void setFrom(const QVariant &); @@ -348,6 +326,12 @@ public: qreal to() const; void setTo(qreal); + +protected: + QDeclarativeNumberAnimation(QDeclarativePropertyAnimationPrivate &dd, QObject *parent); + +private: + void init(); }; class Q_AUTOTEST_EXPORT QDeclarativeVector3dAnimation : public QDeclarativePropertyAnimation @@ -456,9 +440,9 @@ class QDeclarativeParentAnimation : public QDeclarativeAnimationGroup Q_OBJECT Q_DECLARE_PRIVATE(QDeclarativeParentAnimation) - Q_PROPERTY(QDeclarativeItem *target READ target WRITE setTarget) - Q_PROPERTY(QDeclarativeItem *newParent READ newParent WRITE setNewParent) - Q_PROPERTY(QDeclarativeItem *via READ via WRITE setVia) + Q_PROPERTY(QDeclarativeItem *target READ target WRITE setTarget NOTIFY targetChanged) + Q_PROPERTY(QDeclarativeItem *newParent READ newParent WRITE setNewParent NOTIFY newParentChanged) + Q_PROPERTY(QDeclarativeItem *via READ via WRITE setVia NOTIFY viaChanged) public: QDeclarativeParentAnimation(QObject *parent=0); @@ -473,6 +457,11 @@ public: QDeclarativeItem *via() const; void setVia(QDeclarativeItem *); +Q_SIGNALS: + void targetChanged(); + void newParentChanged(); + void viaChanged(); + protected: virtual void transition(QDeclarativeStateActions &actions, QDeclarativeProperties &modified, @@ -506,7 +495,6 @@ QML_DECLARE_TYPE(QDeclarativeAbstractAnimation) QML_DECLARE_TYPE(QDeclarativePauseAnimation) QML_DECLARE_TYPE(QDeclarativeScriptAction) QML_DECLARE_TYPE(QDeclarativePropertyAction) -QML_DECLARE_TYPE(QDeclarativeParentAction) QML_DECLARE_TYPE(QDeclarativePropertyAnimation) QML_DECLARE_TYPE(QDeclarativeColorAnimation) QML_DECLARE_TYPE(QDeclarativeNumberAnimation) diff --git a/src/declarative/util/qdeclarativeanimation_p_p.h b/src/declarative/util/qdeclarativeanimation_p_p.h index 0460312..8bcbeff 100644 --- a/src/declarative/util/qdeclarativeanimation_p_p.h +++ b/src/declarative/util/qdeclarativeanimation_p_p.h @@ -100,17 +100,11 @@ class QActionAnimation : public QAbstractAnimation { Q_OBJECT public: - QActionAnimation(QObject *parent = 0) : QAbstractAnimation(parent), animAction(0), policy(KeepWhenStopped), running(false) {} + QActionAnimation(QObject *parent = 0) : QAbstractAnimation(parent), animAction(0), policy(KeepWhenStopped) {} QActionAnimation(QAbstractAnimationAction *action, QObject *parent = 0) - : QAbstractAnimation(parent), animAction(action), policy(KeepWhenStopped), running(false) {} + : QAbstractAnimation(parent), animAction(action), policy(KeepWhenStopped) {} ~QActionAnimation() { if (policy == DeleteWhenStopped) { delete animAction; animAction = 0; } } virtual int duration() const { return 0; } - void clearAnimAction() - { - if (policy == DeleteWhenStopped) - delete animAction; - animAction = 0; - } void setAnimAction(QAbstractAnimationAction *action, DeletionPolicy p) { if (state() == Running) @@ -127,26 +121,18 @@ protected: { if (newState == Running) { if (animAction) { - running = true; animAction->doAction(); - running = false; if (state() == Stopped && policy == DeleteWhenStopped) { delete animAction; animAction = 0; } } - } /*else if (newState == Stopped && policy == DeleteWhenStopped) { - if (!running) { - delete animAction; - animAction = 0; - } - }*/ + } } private: QAbstractAnimationAction *animAction; DeletionPolicy policy; - bool running; }; class QDeclarativeBulkValueUpdater @@ -192,11 +178,7 @@ protected: //check for new from every loop if (fromSourced) *fromSourced = false; - } /*else if (newState == Stopped && policy == DeleteWhenStopped) { - delete animValue; - animValue = 0; - }*/ //### we get a stop each loop if we are in a group - //### top-level animation is the only reliable one for this + } } private: @@ -225,19 +207,21 @@ class QDeclarativeAbstractAnimationPrivate : public QObjectPrivate Q_DECLARE_PUBLIC(QDeclarativeAbstractAnimation) public: QDeclarativeAbstractAnimationPrivate() - : running(false), paused(false), alwaysRunToEnd(false), repeat(false), + : running(false), paused(false), alwaysRunToEnd(false), connectedTimeLine(false), componentComplete(true), - avoidPropertyValueSourceStart(false), disableUserControl(false), group(0) {} + avoidPropertyValueSourceStart(false), disableUserControl(false), + loopCount(1), group(0) {} bool running:1; bool paused:1; bool alwaysRunToEnd:1; - bool repeat:1; bool connectedTimeLine:1; bool componentComplete:1; bool avoidPropertyValueSourceStart:1; bool disableUserControl:1; + int loopCount; + void commence(); QDeclarativeProperty defaultProperty; @@ -264,7 +248,7 @@ class QDeclarativeScriptActionPrivate : public QDeclarativeAbstractAnimationPriv Q_DECLARE_PUBLIC(QDeclarativeScriptAction) public: QDeclarativeScriptActionPrivate() - : QDeclarativeAbstractAnimationPrivate(), hasRunScriptScript(false), proxy(this), rsa(0) {} + : QDeclarativeAbstractAnimationPrivate(), hasRunScriptScript(false), reversing(false), proxy(this), rsa(0) {} void init(); @@ -272,6 +256,7 @@ public: QString name; QDeclarativeScriptString runScriptScript; bool hasRunScriptScript; + bool reversing; void execute(); @@ -300,22 +285,6 @@ public: QActionAnimation *spa; }; -class QDeclarativeParentActionPrivate : public QDeclarativeAbstractAnimationPrivate -{ - Q_DECLARE_PUBLIC(QDeclarativeParentAction) -public: - QDeclarativeParentActionPrivate() - : QDeclarativeAbstractAnimationPrivate(), pcTarget(0), pcParent(0) {} - - void init(); - - QDeclarativeItem *pcTarget; - QDeclarativeItem *pcParent; - - void doAction(); - QActionAnimation *cpa; -}; - class QDeclarativeAnimationGroupPrivate : public QDeclarativeAbstractAnimationPrivate { Q_DECLARE_PUBLIC(QDeclarativeAnimationGroup) @@ -335,7 +304,7 @@ class QDeclarativePropertyAnimationPrivate : public QDeclarativeAbstractAnimatio public: QDeclarativePropertyAnimationPrivate() : QDeclarativeAbstractAnimationPrivate(), target(0), fromSourced(false), fromIsDefined(false), toIsDefined(false), - rangeIsSet(false), defaultToInterpolatorType(0), interpolatorType(0), interpolator(0), va(0) {} + rangeIsSet(false), defaultToInterpolatorType(0), interpolatorType(0), interpolator(0), va(0), actions(0) {} void init(); @@ -361,6 +330,9 @@ public: QDeclarativeBulkValueAnimator *va; + // for animations that dont use the QDeclarativeBulkValueAnimator + QDeclarativeStateActions *actions; + static QVariant interpolateVariant(const QVariant &from, const QVariant &to, qreal progress); static void convertVariant(QVariant &variant, int type); }; @@ -369,7 +341,7 @@ class QDeclarativeRotationAnimationPrivate : public QDeclarativePropertyAnimatio { Q_DECLARE_PUBLIC(QDeclarativeRotationAnimation) public: - QDeclarativeRotationAnimationPrivate() : direction(QDeclarativeRotationAnimation::Shortest) {} + QDeclarativeRotationAnimationPrivate() : direction(QDeclarativeRotationAnimation::Numerical) {} QDeclarativeRotationAnimation::RotationDirection direction; }; diff --git a/src/declarative/util/qdeclarativebehavior.cpp b/src/declarative/util/qdeclarativebehavior.cpp index d90ca33..87d6836 100644 --- a/src/declarative/util/qdeclarativebehavior.cpp +++ b/src/declarative/util/qdeclarativebehavior.cpp @@ -47,15 +47,12 @@ #include <qdeclarativecontext.h> #include <qdeclarativeinfo.h> #include <qdeclarativeproperty_p.h> - -#include <QtCore/qparallelanimationgroup.h> +#include <qdeclarativeguard_p.h> #include <private/qobject_p.h> QT_BEGIN_NAMESPACE - - class QDeclarativeBehaviorPrivate : public QObjectPrivate { Q_DECLARE_PUBLIC(QDeclarativeBehavior) @@ -64,7 +61,7 @@ public: QDeclarativeProperty property; QVariant currentValue; - QDeclarativeAbstractAnimation *animation; + QDeclarativeGuard<QDeclarativeAbstractAnimation> animation; bool enabled; }; @@ -83,7 +80,8 @@ public: y: 200 // initial value Behavior on y { NumberAnimation { - easing: "easeOutBounce(amplitude:100)" + easing.type: "OutBounce" + easing.amplitude: 100 duration: 200 } } @@ -165,7 +163,8 @@ void QDeclarativeBehavior::write(const QVariant &value) d->currentValue = d->property.read(); - d->animation->qtAnimation()->stop(); + if (d->animation->qtAnimation()->duration() != -1) + d->animation->qtAnimation()->stop(); QDeclarativeStateOperation::ActionList actions; QDeclarativeAction action; @@ -175,11 +174,10 @@ void QDeclarativeBehavior::write(const QVariant &value) actions << action; QList<QDeclarativeProperty> after; - if (d->animation) - d->animation->transition(actions, after, QDeclarativeAbstractAnimation::Forward); + d->animation->transition(actions, after, QDeclarativeAbstractAnimation::Forward); d->animation->qtAnimation()->start(); if (!after.contains(d->property)) - QDeclarativePropertyPrivate::write(d->property, value, QDeclarativePropertyPrivate::BypassInterceptor | QDeclarativePropertyPrivate::DontRemoveBinding); + QDeclarativePropertyPrivate::write(d->property, value, QDeclarativePropertyPrivate::BypassInterceptor | QDeclarativePropertyPrivate::DontRemoveBinding); } void QDeclarativeBehavior::setTarget(const QDeclarativeProperty &property) diff --git a/src/declarative/util/qdeclarativeeasefollow.cpp b/src/declarative/util/qdeclarativeeasefollow.cpp deleted file mode 100644 index ee181dd..0000000 --- a/src/declarative/util/qdeclarativeeasefollow.cpp +++ /dev/null @@ -1,537 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (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 Technology Preview License Agreement accompanying -** this package. -** -** 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.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qdeclarativeeasefollow_p.h" - -#include "qdeclarativeanimation_p_p.h" - -#include <qdeclarativeproperty.h> - -#include <QtCore/qdebug.h> - -#include <math.h> - -QT_BEGIN_NAMESPACE - - - -class QDeclarativeEaseFollowPrivate : public QObjectPrivate -{ - Q_DECLARE_PUBLIC(QDeclarativeEaseFollow) -public: - QDeclarativeEaseFollowPrivate() - : source(0), velocity(200), duration(-1), maximumEasingTime(-1), - reversingMode(QDeclarativeEaseFollow::Eased), initialVelocity(0), - initialValue(0), invert(false), enabled(true), trackVelocity(0), clockOffset(0), - lastTick(0), clock(this) - {} - - qreal source; - qreal velocity; - qreal duration; - qreal maximumEasingTime; - QDeclarativeEaseFollow::ReversingMode reversingMode; - - qreal initialVelocity; - qreal initialValue; - bool invert; - bool enabled; - - qreal trackVelocity; - - QDeclarativeProperty target; - - int clockOffset; - int lastTick; - void tick(int); - void clockStart(); - void clockStop(); - QTickAnimationProxy<QDeclarativeEaseFollowPrivate, &QDeclarativeEaseFollowPrivate::tick> clock; - - void restart(); - - // Parameters for use in tick() - qreal a; // Acceleration - qreal d; // Deceleration - qreal tf; // Total time - qreal tp; // Time at which peak velocity occurs - qreal td; // Time at which decelleration begins - qreal vp; // Velocity at tp - qreal sp; // Displacement at tp - qreal sd; // Displacement at td - qreal vi; // "Normalized" initialvelocity - bool recalc(); -}; - -bool QDeclarativeEaseFollowPrivate::recalc() -{ - qreal s = source - initialValue; - vi = initialVelocity; - - s = (invert?-1.0:1.0) * s; - vi = (invert?-1.0:1.0) * vi; - - if (duration > 0 && velocity > 0) { - tf = s / velocity; - if (tf > (duration / 1000.)) tf = (duration / 1000.); - } else if (duration > 0) { - tf = duration / 1000.; - } else if (velocity > 0) { - tf = s / velocity; - } else { - return false; - } - - if (maximumEasingTime == 0) { - a = 0; - d = 0; - tp = 0; - td = tf; - vp = velocity; - sp = 0; - sd = s; - } else if (maximumEasingTime != -1 && tf > (maximumEasingTime / 1000.)) { - - qreal met = maximumEasingTime / 1000.; - td = tf - met; - - qreal c1 = td; - qreal c2 = (tf - td) * vi - tf * velocity; - qreal c3 = -0.5 * (tf - td) * vi * vi; - - qreal vp1 = (-c2 + sqrt(c2 * c2 - 4 * c1 * c3)) / (2. * c1); - // qreal vp2 = (-c2 - sqrt(c2 * c2 - 4 * c1 * c3)) / (2. * c1); - - vp = vp1; - a = vp / met; - d = a; - tp = (vp - vi) / a; - sp = vi * tp + 0.5 * a * tp * tp; - sd = sp + (td - tp) * vp; - } else { - - qreal c1 = 0.25 * tf * tf; - qreal c2 = 0.5 * vi * tf - s; - qreal c3 = -0.25 * vi * vi; - - qreal a1 = (-c2 + sqrt(c2 * c2 - 4 * c1 * c3)) / (2. * c1); - //qreal a2 = (-c2 - sqrt(c2 * c2 - 4 * c1 * c3)) / (2. * c1); - - qreal tp1 = 0.5 * tf - 0.5 * vi / a1; - //qreal tp2 = 0.5 * tf - 0.5 * vi / a2; - qreal vp1 = a1 * tp1 + vi; - //qreal vp2 = a2 * tp2 + vi; - - qreal sp1 = 0.5 * a1 * tp1 * tp1 + vi * tp1; - //qreal sp2 = 0.5 * a2 * tp2 * tp2 + vi * tp2; - - a = a1; - d = a1; - tp = tp1; - td = tp1; - vp = vp1; - sp = sp1; - sd = sp1; - } - - /* - qWarning() << "a:" << a << "tf:" << tf << "tp:" << tp << "vp:" - << vp << "sp:" << sp << "vi:" << vi << "invert:" << invert; - */ - return true; -} - -void QDeclarativeEaseFollowPrivate::clockStart() -{ - if (clock.state() == QAbstractAnimation::Running) { - clockOffset = lastTick; - return; - } else { - clockOffset = 0; - lastTick = 0; - clock.start(); - } -} - -void QDeclarativeEaseFollowPrivate::clockStop() -{ - clockOffset = 0; - lastTick = 0; - clock.stop(); -} - -void QDeclarativeEaseFollowPrivate::tick(int t) -{ - lastTick = t; - t -= clockOffset; - - qreal time_seconds = qreal(t) / 1000.; - - qreal out = 0; - if (time_seconds < tp) { - - trackVelocity = vi + time_seconds * a; - trackVelocity = (invert?-1.0:1.0) * trackVelocity; - - qreal value = 0.5 * a * time_seconds * time_seconds + vi * time_seconds; - value = (invert?-1.0:1.0) * value; - target.write(initialValue + value); - out = initialValue + value; - } else if (time_seconds < td) { - - time_seconds -= tp; - trackVelocity = (invert?-1.0:1.0) * vp; - qreal value = sp + time_seconds * vp; - value = (invert?-1.0:1.0) * value; - - target.write(initialValue + value); - - out = initialValue + value; - } else if (time_seconds < tf) { - - time_seconds -= td; - - trackVelocity = vp - time_seconds * a; - trackVelocity = (invert?-1.0:1.0) * trackVelocity; - - qreal value = sd - 0.5 * d * time_seconds * time_seconds + vp * time_seconds; - value = (invert?-1.0:1.0) * value; - - target.write(initialValue + value); - - out = initialValue + value; - } else { - - clock.stop(); - - trackVelocity = 0; - target.write(source); - } - - //qWarning() << out << trackVelocity << t << a; -} - -/*! - \qmlclass EaseFollow QDeclarativeEaseFollow - \since 4.7 - \brief The EaseFollow element allows a property to smoothly track a value. - - The EaseFollow smoothly animates a property's value to a set target value - using an ease in/out quad easing curve. If the target value changes while - the animation is in progress, the easing curves used to animate to the old - and the new target values are spliced together to avoid any obvious visual - glitches. - - The property animation is configured by setting the velocity at which the - animation should occur, or the duration that the animation should take. - If both a velocity and a duration are specified, the one that results in - the quickest animation is chosen for each change in the target value. - - For example, animating from 0 to 800 will take 4 seconds if a velocity - of 200 is set, will take 8 seconds with a duration of 8000 set, and will - take 4 seconds with both a velocity of 200 and a duration of 8000 set. - Animating from 0 to 20000 will take 10 seconds if a velocity of 200 is set, - will take 8 seconds with a duration of 8000 set, and will take 8 seconds - with both a velocity of 200 and a duration of 8000 set. - - The follow example shows one rectangle tracking the position of another. -\code -import Qt 4.6 - -Rectangle { - width: 800; height: 600; color: "blue" - - Rectangle { - color: "green" - width: 60; height: 60; - x: -5; y: -5; - EaseFollow on x { source: rect1.x - 5; velocity: 200 } - EaseFollow on y { source: rect1.y - 5; velocity: 200 } - } - - Rectangle { - id: rect1 - color: "red" - width: 50; height: 50; - } - - focus: true - Keys.onRightPressed: rect1.x = rect1.x + 100 - Keys.onLeftPressed: rect1.x = rect1.x - 100 - Keys.onUpPressed: rect1.y = rect1.y - 100 - Keys.onDownPressed: rect1.y = rect1.y + 100 -} -\endcode - - The default velocity of EaseFollow is 200 units/second. Note that if the range of the - value being animated is small, then the velocity will need to be adjusted - appropriately. For example, the opacity of an item ranges from 0 - 1.0. - To enable a smooth animation in this range the velocity will need to be - set to a value such as 0.5 units/second. Animating from 0 to 1.0 with a velocity - of 0.5 will take 2000 ms to complete. - - \sa SpringFollow -*/ - -QDeclarativeEaseFollow::QDeclarativeEaseFollow(QObject *parent) -: QObject(*(new QDeclarativeEaseFollowPrivate), parent) -{ -} - -QDeclarativeEaseFollow::~QDeclarativeEaseFollow() -{ -} - -/*! - \qmlproperty qreal EaseFollow::source - This property holds the source value which will be tracked. - - Bind to a property in order to track its changes. -*/ -qreal QDeclarativeEaseFollow::sourceValue() const -{ - Q_D(const QDeclarativeEaseFollow); - return d->source; -} - -/*! - \qmlproperty enumeration EaseFollow::reversingMode - - Sets how the EaseFollow behaves if an animation direction is reversed. - - If reversing mode is \c Eased, the animation will smoothly decelerate, and - then reverse direction. If the reversing mode is \c Immediate, the - animation will immediately begin accelerating in the reverse direction, - begining with a velocity of 0. If the reversing mode is \c Sync, the - property is immediately set to the target value. -*/ -QDeclarativeEaseFollow::ReversingMode QDeclarativeEaseFollow::reversingMode() const -{ - Q_D(const QDeclarativeEaseFollow); - return d->reversingMode; -} - -void QDeclarativeEaseFollow::setReversingMode(ReversingMode m) -{ - Q_D(QDeclarativeEaseFollow); - if (d->reversingMode == m) - return; - - d->reversingMode = m; - emit reversingModeChanged(); -} - -void QDeclarativeEaseFollowPrivate::restart() -{ - if (!enabled || velocity == 0) { - clockStop(); - return; - } - - initialValue = target.read().toReal(); - - if (source == initialValue) { - clockStop(); - return; - } - - bool hasReversed = trackVelocity != 0. && - ((trackVelocity > 0) == ((initialValue - source) > 0)); - - if (hasReversed) { - switch (reversingMode) { - default: - case QDeclarativeEaseFollow::Eased: - break; - case QDeclarativeEaseFollow::Sync: - target.write(source); - return; - case QDeclarativeEaseFollow::Immediate: - initialVelocity = 0; - clockStop(); - break; - } - } - - trackVelocity = initialVelocity; - - invert = (source < initialValue); - - if (!recalc()) { - target.write(source); - clockStop(); - return; - } - - clockStart(); -} - -void QDeclarativeEaseFollow::setSourceValue(qreal s) -{ - Q_D(QDeclarativeEaseFollow); - - if (d->clock.state() == QAbstractAnimation::Running && d->source == s) - return; - - d->source = s; - d->initialVelocity = d->trackVelocity; - d->restart(); - - emit sourceChanged(); -} - -/*! - \qmlproperty qreal EaseFollow::duration - - This property holds the animation duration used when tracking the source. - - Setting this to -1 (the default) disables the duration value. -*/ -qreal QDeclarativeEaseFollow::duration() const -{ - Q_D(const QDeclarativeEaseFollow); - return d->duration; -} - -void QDeclarativeEaseFollow::setDuration(qreal v) -{ - Q_D(QDeclarativeEaseFollow); - if (d->duration == v) - return; - - d->duration = v; - d->trackVelocity = 0; - - if (d->clock.state() == QAbstractAnimation::Running) - d->restart(); - - emit durationChanged(); -} - -qreal QDeclarativeEaseFollow::velocity() const -{ - Q_D(const QDeclarativeEaseFollow); - return d->velocity; -} - -/*! - \qmlproperty qreal EaseFollow::velocity - - This property holds the average velocity allowed when tracking the source. - - The default velocity of EaseFollow is 200 units/second. - - Setting this to -1 disables the velocity value. -*/ -void QDeclarativeEaseFollow::setVelocity(qreal v) -{ - Q_D(QDeclarativeEaseFollow); - if (d->velocity == v) - return; - - d->velocity = v; - d->trackVelocity = 0; - - if (d->clock.state() == QAbstractAnimation::Running) - d->restart(); - - emit velocityChanged(); -} - -/*! - \qmlproperty bool EaseFollow::enabled - This property holds whether the target will track the source. -*/ -bool QDeclarativeEaseFollow::enabled() const -{ - Q_D(const QDeclarativeEaseFollow); - return d->enabled; -} - -void QDeclarativeEaseFollow::setEnabled(bool enabled) -{ - Q_D(QDeclarativeEaseFollow); - if (d->enabled == enabled) - return; - - d->enabled = enabled; - if (enabled) - d->restart(); - else - d->clockStop(); - - emit enabledChanged(); -} - -void QDeclarativeEaseFollow::setTarget(const QDeclarativeProperty &t) -{ - Q_D(QDeclarativeEaseFollow); - d->target = t; -} - -/*! -\qmlproperty qreal EaseFollow::maximumEasingTime - -This property specifies the maximum time an "eases" during the follow should take. -Setting this property causes the velocity to "level out" after at a time. Setting -a negative value reverts to the normal mode of easing over the entire animation -duration. - -The default value is -1. -*/ -qreal QDeclarativeEaseFollow::maximumEasingTime() const -{ - Q_D(const QDeclarativeEaseFollow); - return d->maximumEasingTime; -} - -void QDeclarativeEaseFollow::setMaximumEasingTime(qreal v) -{ - Q_D(QDeclarativeEaseFollow); - d->maximumEasingTime = v; - - if (d->clock.state() == QAbstractAnimation::Running) - d->restart(); - - emit maximumEasingTimeChanged(); -} - -QT_END_NAMESPACE diff --git a/src/declarative/util/qdeclarativelistmodel.cpp b/src/declarative/util/qdeclarativelistmodel.cpp index 340e9ac..1a28176 100644 --- a/src/declarative/util/qdeclarativelistmodel.cpp +++ b/src/declarative/util/qdeclarativelistmodel.cpp @@ -365,7 +365,7 @@ void QDeclarativeListModel::clear() if (!m_isWorkerCopy) { emit itemsRemoved(0, cleared); - emit countChanged(0); + emit countChanged(); } } @@ -390,7 +390,7 @@ void QDeclarativeListModel::remove(int index) if (!m_isWorkerCopy) { emit itemsRemoved(index, 1); - emit countChanged(this->count()); + emit countChanged(); } } @@ -401,7 +401,7 @@ void QDeclarativeListModel::remove(int index) values in \a dict. \code - FruitModel.insert(2, {"cost": 5.95, "name":"Pizza"}) + fruitModel.insert(2, {"cost": 5.95, "name":"Pizza"}) \endcode The \a index must be to an existing item in the list, or one past @@ -424,7 +424,7 @@ void QDeclarativeListModel::insert(int index, const QScriptValue& valuemap) bool ok = m_flat ? m_flat->insert(index, valuemap) : m_nested->insert(index, valuemap); if (ok && !m_isWorkerCopy) { emit itemsInserted(index, 1); - emit countChanged(this->count()); + emit countChanged(); } } @@ -437,7 +437,7 @@ void QDeclarativeListModel::insert(int index, const QScriptValue& valuemap) to the end of the list: \code - FruitModel.move(0,FruitModel.count-3,3) + fruitModel.move(0,fruitModel.count-3,3) \endcode \sa append() @@ -479,7 +479,7 @@ void QDeclarativeListModel::move(int from, int to, int n) values in \a dict. \code - FruitModel.append({"cost": 5.95, "name":"Pizza"}) + fruitModel.append({"cost": 5.95, "name":"Pizza"}) \endcode \sa set() remove() @@ -500,8 +500,8 @@ void QDeclarativeListModel::append(const QScriptValue& valuemap) Returns the item at \a index in the list model. \code - FruitModel.append({"cost": 5.95, "name":"Jackfruit"}) - FruitModel.get(0).cost + fruitModel.append({"cost": 5.95, "name":"Jackfruit"}) + fruitModel.get(0).cost \endcode The \a index must be an element in the list. @@ -510,10 +510,10 @@ void QDeclarativeListModel::append(const QScriptValue& valuemap) will also be models, and this get() method is used to access elements: \code - FruitModel.append(..., "attributes": + fruitModel.append(..., "attributes": [{"name":"spikes","value":"7mm"}, {"name":"color","value":"green"}]); - FruitModel.get(0).attributes.get(1).value; // == "green" + fruitModel.get(0).attributes.get(1).value; // == "green" \endcode \sa append() @@ -536,7 +536,7 @@ QScriptValue QDeclarativeListModel::get(int index) const are left unchanged. \code - FruitModel.set(3, {"cost": 5.95, "name":"Pizza"}) + fruitModel.set(3, {"cost": 5.95, "name":"Pizza"}) \endcode The \a index must be an element in the list. @@ -574,7 +574,7 @@ void QDeclarativeListModel::set(int index, const QScriptValue& valuemap) Changes the \a property of the item at \a index in the list model to \a value. \code - FruitModel.set(3, "cost", 5.95) + fruitModel.set(3, "cost", 5.95) \endcode The \a index must be an element in the list. @@ -1250,14 +1250,9 @@ ModelNode::ModelNode() ModelNode::~ModelNode() { - ModelNode *node; - - QList<ModelNode *> nodeValues = properties.values(); - for (int ii = 0; ii < nodeValues.count(); ++ii) { - node = nodeValues[ii]; - if (node) { delete node; node = 0; } - } + qDeleteAll(properties.values()); + ModelNode *node; for (int ii = 0; ii < values.count(); ++ii) { node = qvariant_cast<ModelNode *>(values.at(ii)); if (node) { delete node; node = 0; } @@ -1279,7 +1274,9 @@ void ModelNode::setObjectValue(const QScriptValue& valuemap) { } else { value->values << v.toVariant(); } - properties.insert(it.name(),value); + if (properties.contains(it.name())) + delete properties[it.name()]; + properties.insert(it.name(), value); } } diff --git a/src/declarative/util/qdeclarativelistmodel_p.h b/src/declarative/util/qdeclarativelistmodel_p.h index 6a0426b..d09062e 100644 --- a/src/declarative/util/qdeclarativelistmodel_p.h +++ b/src/declarative/util/qdeclarativelistmodel_p.h @@ -91,7 +91,7 @@ public: QDeclarativeListModelWorkerAgent *agent(); Q_SIGNALS: - void countChanged(int); + void countChanged(); private: friend class QDeclarativeListModelParser; diff --git a/src/declarative/util/qdeclarativelistmodelworkeragent.cpp b/src/declarative/util/qdeclarativelistmodelworkeragent.cpp index 2951262..0e38632 100644 --- a/src/declarative/util/qdeclarativelistmodelworkeragent.cpp +++ b/src/declarative/util/qdeclarativelistmodelworkeragent.cpp @@ -229,7 +229,7 @@ bool QDeclarativeListModelWorkerAgent::event(QEvent *e) } if (cc) - emit m_orig->countChanged(m_copy->count()); + emit m_orig->countChanged(); } } diff --git a/src/declarative/util/qdeclarativeopenmetaobject.cpp b/src/declarative/util/qdeclarativeopenmetaobject.cpp index 8c23354..6611885 100644 --- a/src/declarative/util/qdeclarativeopenmetaobject.cpp +++ b/src/declarative/util/qdeclarativeopenmetaobject.cpp @@ -222,9 +222,10 @@ int QDeclarativeOpenMetaObject::metaCall(QMetaObject::Call c, int id, void **a) propertyRead(propId); *reinterpret_cast<QVariant *>(a[0]) = d->getData(propId); } else if (c == QMetaObject::WriteProperty) { - if (d->data[propId].first != *reinterpret_cast<QVariant *>(a[0])) { + if (propId <= d->data.count() || d->data[propId].first != *reinterpret_cast<QVariant *>(a[0])) { propertyWrite(propId); d->writeData(propId, *reinterpret_cast<QVariant *>(a[0])); + propertyWritten(propId); activate(d->object, d->type->d->signalOffset + propId, 0); } } @@ -270,6 +271,11 @@ QVariant &QDeclarativeOpenMetaObject::operator[](const QByteArray &name) return d->getData(*iter); } +QVariant &QDeclarativeOpenMetaObject::operator[](int id) +{ + return d->getData(id); +} + void QDeclarativeOpenMetaObject::setValue(const QByteArray &name, const QVariant &val) { QHash<QByteArray, int>::ConstIterator iter = d->type->d->names.find(name); @@ -326,6 +332,10 @@ void QDeclarativeOpenMetaObject::propertyWrite(int) { } +void QDeclarativeOpenMetaObject::propertyWritten(int) +{ +} + void QDeclarativeOpenMetaObject::propertyCreated(int, QMetaPropertyBuilder &) { } diff --git a/src/declarative/util/qdeclarativeopenmetaobject_p.h b/src/declarative/util/qdeclarativeopenmetaobject_p.h index ec5ac17..9bb4c34 100644 --- a/src/declarative/util/qdeclarativeopenmetaobject_p.h +++ b/src/declarative/util/qdeclarativeopenmetaobject_p.h @@ -90,6 +90,7 @@ public: QVariant value(int) const; void setValue(int, const QVariant &); QVariant &operator[](const QByteArray &); + QVariant &operator[](int); int count() const; QByteArray name(int) const; @@ -109,6 +110,7 @@ protected: virtual void propertyRead(int); virtual void propertyWrite(int); + virtual void propertyWritten(int); virtual void propertyCreated(int, QMetaPropertyBuilder &); QAbstractDynamicMetaObject *parent() const; diff --git a/src/declarative/util/qdeclarativepixmapcache.cpp b/src/declarative/util/qdeclarativepixmapcache.cpp index 942d5f6..1da929e 100644 --- a/src/declarative/util/qdeclarativepixmapcache.cpp +++ b/src/declarative/util/qdeclarativepixmapcache.cpp @@ -43,8 +43,6 @@ #include "qdeclarativenetworkaccessmanagerfactory.h" #include "qdeclarativeimageprovider.h" -#include "qfxperf_p_p.h" - #include <qdeclarativeengine.h> #include <private/qdeclarativeglobal_p.h> #include <private/qdeclarativeengine_p.h> @@ -62,11 +60,6 @@ #include <private/qobject_p.h> #include <QSslError> -#ifdef Q_OS_LINUX -#include <pthread.h> -#include <linux/sched.h> -#endif - // Maximum number of simultaneous image requests to send. static const int maxImageRequestCount = 8; @@ -108,7 +101,7 @@ public: QDeclarativeImageReader(QDeclarativeEngine *eng); ~QDeclarativeImageReader(); - QDeclarativePixmapReply *getImage(const QUrl &url); + QDeclarativePixmapReply *getImage(const QUrl &url, int req_width, int req_height); void cancel(QDeclarativePixmapReply *rep); static QDeclarativeImageReader *instance(QDeclarativeEngine *engine); @@ -121,6 +114,7 @@ private: QList<QDeclarativePixmapReply*> cancelled; QDeclarativeEngine *engine; QDeclarativeImageRequestHandler *handler; + QObject *eventLoopQuitHack; QMutex mutex; static QHash<QDeclarativeEngine *,QDeclarativeImageReader*> readers; @@ -142,7 +136,7 @@ public: QCoreApplication::postEvent(this, new QEvent(QEvent::User)); } - QDeclarativePixmapReply *getImage(const QUrl &url); + QDeclarativePixmapReply *getImage(const QUrl &url, int req_width, int req_height); void cancel(QDeclarativePixmapReply *reply); protected: @@ -172,11 +166,58 @@ private: //=========================================================================== +static bool readImage(const QUrl& url, QIODevice *dev, QImage *image, QString *errorString, QSize *impsize, int req_width, int req_height) +{ + QImageReader imgio(dev); + + bool force_scale = false; + if (url.path().endsWith(QLatin1String(".svg"),Qt::CaseInsensitive)) { + imgio.setFormat("svg"); // QSvgPlugin::capabilities bug QTBUG-9053 + force_scale = true; + } + + bool scaled = false; + if (req_width > 0 || req_height > 0) { + QSize s = imgio.size(); + if (req_width && (force_scale || req_width < s.width())) { + if (req_height <= 0) + s.setHeight(s.height()*req_width/s.width()); + s.setWidth(req_width); scaled = true; + } + if (req_height && (force_scale || req_height < s.height())) { + if (req_width <= 0) + s.setWidth(s.width()*req_height/s.height()); + s.setHeight(req_height); scaled = true; + } + if (scaled) { imgio.setScaledSize(s); } + } + + if (impsize) + *impsize = imgio.size(); + + if (imgio.read(image)) { + if (impsize && impsize->width() < 0) + *impsize = image->size(); + return true; + } else { + if (errorString) + *errorString = QLatin1String("Error decoding: ") + url.toString() + + QLatin1String(" \"") + imgio.errorString() + QLatin1String("\""); + return false; + } +} + + +//=========================================================================== + int QDeclarativeImageRequestHandler::replyDownloadProgress = -1; int QDeclarativeImageRequestHandler::replyFinished = -1; int QDeclarativeImageRequestHandler::downloadProgress = -1; int QDeclarativeImageRequestHandler::thisNetworkRequestDone = -1; +typedef QHash<QUrl, QSize> QDeclarativePixmapSizeHash; +Q_GLOBAL_STATIC(QDeclarativePixmapSizeHash, qmlOriginalSizes); + bool QDeclarativeImageRequestHandler::event(QEvent *event) { if (event->type() == QEvent::User) { @@ -223,7 +264,9 @@ bool QDeclarativeImageRequestHandler::event(QEvent *event) // fetch if (url.scheme() == QLatin1String("image")) { // Use QmlImageProvider - QImage image = QDeclarativeEnginePrivate::get(engine)->getImageFromProvider(url); + QSize read_impsize; + QImage image = QDeclarativeEnginePrivate::get(engine)->getImageFromProvider(url, &read_impsize, QSize(runningJob->forcedWidth(),runningJob->forcedHeight())); + qmlOriginalSizes()->insert(url, read_impsize); QDeclarativeImageReaderEvent::ReadError errorCode = QDeclarativeImageReaderEvent::NoError; QString errorStr; if (image.isNull()) { @@ -240,10 +283,10 @@ bool QDeclarativeImageRequestHandler::event(QEvent *event) QString errorStr; QFile f(lf); if (f.open(QIODevice::ReadOnly)) { - QImageReader imgio(&f); - if (!imgio.read(&image)) { - errorStr = QLatin1String("Error decoding: ") + url.toString() - + QLatin1String(" \"") + imgio.errorString() + QLatin1String("\""); + QSize read_impsize; + if (readImage(url, &f, &image, &errorStr, &read_impsize, runningJob->forcedWidth(),runningJob->forcedHeight())) { + qmlOriginalSizes()->insert(url, read_impsize); + } else { errorCode = QDeclarativeImageReaderEvent::Loading; } } else { @@ -305,12 +348,11 @@ void QDeclarativeImageRequestHandler::networkRequestDone() error = QDeclarativeImageReaderEvent::Loading; errorString = reply->errorString(); } else { - QImageReader imgio(reply); - if (imgio.read(&image)) { + QSize read_impsize; + if (readImage(reply->url(), reply, &image, &errorString, &read_impsize, job->forcedWidth(), job->forcedHeight())) { + qmlOriginalSizes()->insert(reply->url(), read_impsize); error = QDeclarativeImageReaderEvent::NoError; } else { - errorString = QLatin1String("Error decoding: ") + reply->url().toString() - + QLatin1String(" \"") + imgio.errorString() + QLatin1String("\""); error = QDeclarativeImageReaderEvent::Decoding; } } @@ -328,7 +370,10 @@ void QDeclarativeImageRequestHandler::networkRequestDone() QDeclarativeImageReader::QDeclarativeImageReader(QDeclarativeEngine *eng) : QThread(eng), engine(eng), handler(0) { - start(QThread::LowPriority); + eventLoopQuitHack = new QObject; + eventLoopQuitHack->moveToThread(this); + connect(eventLoopQuitHack, SIGNAL(destroyed(QObject*)), SLOT(quit()), Qt::DirectConnection); + start(QThread::IdlePriority); } QDeclarativeImageReader::~QDeclarativeImageReader() @@ -337,7 +382,7 @@ QDeclarativeImageReader::~QDeclarativeImageReader() readers.remove(engine); readerMutex.unlock(); - quit(); + eventLoopQuitHack->deleteLater(); wait(); } @@ -354,10 +399,10 @@ QDeclarativeImageReader *QDeclarativeImageReader::instance(QDeclarativeEngine *e return reader; } -QDeclarativePixmapReply *QDeclarativeImageReader::getImage(const QUrl &url) +QDeclarativePixmapReply *QDeclarativeImageReader::getImage(const QUrl &url, int req_width, int req_height) { mutex.lock(); - QDeclarativePixmapReply *reply = new QDeclarativePixmapReply(this, url); + QDeclarativePixmapReply *reply = new QDeclarativePixmapReply(this, url, req_width, req_height); reply->addRef(); reply->setLoading(); jobs.append(reply); @@ -381,15 +426,9 @@ void QDeclarativeImageReader::cancel(QDeclarativePixmapReply *reply) void QDeclarativeImageReader::run() { -#if defined(Q_OS_LINUX) && defined(SCHED_IDLE) - struct sched_param param; - int policy; - - pthread_getschedparam(pthread_self(), &policy, ¶m); - pthread_setschedparam(pthread_self(), SCHED_IDLE, ¶m); -#endif - + readerMutex.lock(); handler = new QDeclarativeImageRequestHandler(this, engine); + readerMutex.unlock(); exec(); @@ -399,40 +438,6 @@ void QDeclarativeImageReader::run() //=========================================================================== -static bool readImage(QIODevice *dev, QPixmap *pixmap, QString &errorString) -{ - QImageReader imgio(dev); - -//#define QT_TEST_SCALED_SIZE -#ifdef QT_TEST_SCALED_SIZE - /* - Some mechanism is needed for loading images at a limited size, especially - for remote images. Loading only thumbnails of remote progressive JPEG - images can be efficient. (Qt jpeg handler does not do so currently) - */ - - QSize limit(60,60); - QSize sz = imgio.size(); - if (sz.width() > limit.width() || sz.height() > limit.height()) { - sz.scale(limit,Qt::KeepAspectRatio); - imgio.setScaledSize(sz); - } -#endif - - QImage img; - if (imgio.read(&img)) { -#ifdef QT_TEST_SCALED_SIZE - if (!sz.isValid()) - img = img.scaled(limit,Qt::KeepAspectRatio); -#endif - *pixmap = QPixmap::fromImage(img); - return true; - } else { - errorString = imgio.errorString(); - return false; - } -} - /*! \internal \class QDeclarativePixmapCache @@ -449,8 +454,10 @@ class QDeclarativePixmapReplyPrivate : public QObjectPrivate Q_DECLARE_PUBLIC(QDeclarativePixmapReply) public: - QDeclarativePixmapReplyPrivate(QDeclarativeImageReader *r, const QUrl &u) - : QObjectPrivate(), refCount(1), url(u), status(QDeclarativePixmapReply::Loading), loading(false), reader(r) { + QDeclarativePixmapReplyPrivate(QDeclarativeImageReader *r, const QUrl &u, int req_width, int req_height) + : QObjectPrivate(), refCount(1), url(u), status(QDeclarativePixmapReply::Loading), loading(false), reader(r), + forced_width(req_width), forced_height(req_height) + { } int refCount; @@ -459,11 +466,12 @@ public: QDeclarativePixmapReply::Status status; bool loading; QDeclarativeImageReader *reader; + int forced_width, forced_height; }; -QDeclarativePixmapReply::QDeclarativePixmapReply(QDeclarativeImageReader *reader, const QUrl &url) - : QObject(*new QDeclarativePixmapReplyPrivate(reader, url), 0) +QDeclarativePixmapReply::QDeclarativePixmapReply(QDeclarativeImageReader *reader, const QUrl &url, int req_width, int req_height) + : QObject(*new QDeclarativePixmapReplyPrivate(reader, url, req_width, req_height), 0) { } @@ -477,6 +485,28 @@ const QUrl &QDeclarativePixmapReply::url() const return d->url; } +int QDeclarativePixmapReply::forcedWidth() const +{ + Q_D(const QDeclarativePixmapReply); + return d->forced_width; +} + +int QDeclarativePixmapReply::forcedHeight() const +{ + Q_D(const QDeclarativePixmapReply); + return d->forced_height; +} + +QSize QDeclarativePixmapReply::implicitSize() const +{ + Q_D(const QDeclarativePixmapReply); + QDeclarativePixmapSizeHash::Iterator iter = qmlOriginalSizes()->find(d->url); + if (iter != qmlOriginalSizes()->end()) + return *iter; + else + return QSize(); +} + bool QDeclarativePixmapReply::event(QEvent *event) { Q_D(QDeclarativePixmapReply); @@ -556,13 +586,25 @@ bool QDeclarativePixmapReply::release(bool defer) If \a async is false the image will be loaded and decoded immediately; otherwise the image will be loaded and decoded in a separate thread. + If \a req_width and \a req_height are non-zero, they are used for + the size of the rendered pixmap rather than the intrinsic size of the image. + Different request sizes add different cache items. + Note that images sourced from the network will always be loaded and decoded asynchonously. */ -QDeclarativePixmapReply::Status QDeclarativePixmapCache::get(const QUrl& url, QPixmap *pixmap, bool async) +QDeclarativePixmapReply::Status QDeclarativePixmapCache::get(const QUrl& url, QPixmap *pixmap, QSize *impsize, bool async, int req_width, int req_height) { QDeclarativePixmapReply::Status status = QDeclarativePixmapReply::Unrequested; QByteArray key = url.toEncoded(QUrl::FormattingOption(0x100)); + + if (req_width > 0 || req_height > 0) { + key += ':'; + key += QByteArray::number(req_width); + key += 'x'; + key += QByteArray::number(req_height); + } + QString strKey = QString::fromLatin1(key.constData(), key.count()); #ifndef QT_NO_LOCALFILE_OPTIMIZED_QML @@ -572,11 +614,13 @@ QDeclarativePixmapReply::Status QDeclarativePixmapCache::get(const QUrl& url, QP status = QDeclarativePixmapReply::Ready; if (!QPixmapCache::find(strKey,pixmap)) { QFile f(lf); + QSize read_impsize; if (f.open(QIODevice::ReadOnly)) { QString errorString; - if (!readImage(&f, pixmap, errorString)) { - errorString = QLatin1String("Error decoding: ") + url.toString() - + QLatin1String(" \"") + errorString + QLatin1String("\""); + QImage image; + if (readImage(url, &f, &image, &errorString, &read_impsize, req_width, req_height)) { + *pixmap = QPixmap::fromImage(image); + } else { qWarning() << errorString; *pixmap = QPixmap(); status = QDeclarativePixmapReply::Error; @@ -586,8 +630,18 @@ QDeclarativePixmapReply::Status QDeclarativePixmapCache::get(const QUrl& url, QP *pixmap = QPixmap(); status = QDeclarativePixmapReply::Error; } - if (status == QDeclarativePixmapReply::Ready) + if (status == QDeclarativePixmapReply::Ready) { QPixmapCache::insert(strKey, *pixmap); + qmlOriginalSizes()->insert(url, read_impsize); + } + if (impsize) + *impsize = read_impsize; + } else { + if (impsize) { + QDeclarativePixmapSizeHash::Iterator iter = qmlOriginalSizes()->find(url); + if (iter != qmlOriginalSizes()->end()) + *impsize = *iter; + } } return status; } @@ -610,6 +664,11 @@ QDeclarativePixmapReply::Status QDeclarativePixmapCache::get(const QUrl& url, QP } else if (iter != qmlActivePixmapReplies()->end()) { status = QDeclarativePixmapReply::Loading; } + if (impsize) { + QDeclarativePixmapSizeHash::Iterator iter = qmlOriginalSizes()->find(url); + if (iter != qmlOriginalSizes()->end()) + *impsize = *iter; + } return status; } @@ -623,12 +682,12 @@ QDeclarativePixmapReply::Status QDeclarativePixmapCache::get(const QUrl& url, QP The returned QDeclarativePixmapReply will be deleted when all request() calls are matched by a corresponding get() call. */ -QDeclarativePixmapReply *QDeclarativePixmapCache::request(QDeclarativeEngine *engine, const QUrl &url) +QDeclarativePixmapReply *QDeclarativePixmapCache::request(QDeclarativeEngine *engine, const QUrl &url, int req_width, int req_height) { QDeclarativePixmapReplyHash::Iterator iter = qmlActivePixmapReplies()->find(url); if (iter == qmlActivePixmapReplies()->end()) { QDeclarativeImageReader *reader = QDeclarativeImageReader::instance(engine); - QDeclarativePixmapReply *item = reader->getImage(url); + QDeclarativePixmapReply *item = reader->getImage(url, req_width, req_height); iter = qmlActivePixmapReplies()->insert(url, item); } else { (*iter)->addRef(); diff --git a/src/declarative/util/qdeclarativepixmapcache_p.h b/src/declarative/util/qdeclarativepixmapcache_p.h index b8949db..df71d65 100644 --- a/src/declarative/util/qdeclarativepixmapcache_p.h +++ b/src/declarative/util/qdeclarativepixmapcache_p.h @@ -66,6 +66,9 @@ public: Status status() const; const QUrl &url() const; + int forcedWidth() const; + int forcedHeight() const; + QSize implicitSize() const; Q_SIGNALS: void finished(); @@ -81,7 +84,7 @@ private: void setLoading(); private: - QDeclarativePixmapReply(QDeclarativeImageReader *reader, const QUrl &url); + QDeclarativePixmapReply(QDeclarativeImageReader *reader, const QUrl &url, int req_width, int req_height); Q_DISABLE_COPY(QDeclarativePixmapReply) Q_DECLARE_PRIVATE(QDeclarativePixmapReply) friend class QDeclarativeImageRequestHandler; @@ -92,8 +95,8 @@ private: class Q_DECLARATIVE_EXPORT QDeclarativePixmapCache { public: - static QDeclarativePixmapReply::Status get(const QUrl& url, QPixmap *pixmap, bool async=false); - static QDeclarativePixmapReply *request(QDeclarativeEngine *, const QUrl& url); + static QDeclarativePixmapReply::Status get(const QUrl& url, QPixmap *pixmap, QSize *impsize=0, bool async=false, int req_width=0, int req_height=0); + static QDeclarativePixmapReply *request(QDeclarativeEngine *, const QUrl& url, int req_width=0, int req_height=0); static void cancel(const QUrl& url, QObject *obj); static int pendingRequests(); }; diff --git a/src/declarative/util/qdeclarativepropertychanges.cpp b/src/declarative/util/qdeclarativepropertychanges.cpp index 8865e04..6ceec5d 100644 --- a/src/declarative/util/qdeclarativepropertychanges.cpp +++ b/src/declarative/util/qdeclarativepropertychanges.cpp @@ -227,6 +227,8 @@ QDeclarativePropertyChangesParser::compileList(QList<QPair<QByteArray, QVariant> const QVariant &value = values.at(ii); if (value.userType() == qMetaTypeId<QDeclarativeCustomParserNode>()) { + error(qvariant_cast<QDeclarativeCustomParserNode>(value), + QDeclarativePropertyChanges::tr("PropertyChanges does not support creating state-specific objects.")); continue; } else if(value.userType() == qMetaTypeId<QDeclarativeCustomParserProperty>()) { diff --git a/src/declarative/util/qdeclarativepropertymap.cpp b/src/declarative/util/qdeclarativepropertymap.cpp index fcea515..0bdd91b 100644 --- a/src/declarative/util/qdeclarativepropertymap.cpp +++ b/src/declarative/util/qdeclarativepropertymap.cpp @@ -41,6 +41,7 @@ #include "qdeclarativepropertymap.h" +#include <private/qmetaobjectbuilder_p.h> #include "qdeclarativeopenmetaobject_p.h" #include <QDebug> @@ -55,7 +56,8 @@ public: QDeclarativePropertyMapMetaObject(QDeclarativePropertyMap *obj, QDeclarativePropertyMapPrivate *objPriv); protected: - virtual void propertyWrite(int index); + virtual void propertyWritten(int index); + virtual void propertyCreated(int, QMetaPropertyBuilder &); private: QDeclarativePropertyMap *map; @@ -68,13 +70,13 @@ class QDeclarativePropertyMapPrivate : public QObjectPrivate public: QDeclarativePropertyMapMetaObject *mo; QStringList keys; - void emitChanged(const QString &key); + void emitChanged(const QString &key, const QVariant &value); }; -void QDeclarativePropertyMapPrivate::emitChanged(const QString &key) +void QDeclarativePropertyMapPrivate::emitChanged(const QString &key, const QVariant &value) { Q_Q(QDeclarativePropertyMap); - emit q->valueChanged(key); + emit q->valueChanged(key, value); } QDeclarativePropertyMapMetaObject::QDeclarativePropertyMapMetaObject(QDeclarativePropertyMap *obj, QDeclarativePropertyMapPrivate *objPriv) : QDeclarativeOpenMetaObject(obj) @@ -83,14 +85,19 @@ QDeclarativePropertyMapMetaObject::QDeclarativePropertyMapMetaObject(QDeclarativ priv = objPriv; } -void QDeclarativePropertyMapMetaObject::propertyWrite(int index) +void QDeclarativePropertyMapMetaObject::propertyWritten(int index) { - priv->emitChanged(QString::fromUtf8(name(index))); + priv->emitChanged(QString::fromUtf8(name(index)), operator[](index)); +} + +void QDeclarativePropertyMapMetaObject::propertyCreated(int, QMetaPropertyBuilder &b) +{ + priv->keys.append(QString::fromUtf8(b.name())); } /*! \class QDeclarativePropertyMap - \since 4.7 + \since 4.7 \brief The QDeclarativePropertyMap class allows you to set key-value pairs that can be used in bindings. QDeclarativePropertyMap provides a convenient way to expose domain data to the UI layer. @@ -172,8 +179,6 @@ QVariant QDeclarativePropertyMap::value(const QString &key) const void QDeclarativePropertyMap::insert(const QString &key, const QVariant &value) { Q_D(QDeclarativePropertyMap); - if (!d->keys.contains(key)) - d->keys.append(key); d->mo->setValue(key.toUtf8(), value); } @@ -249,10 +254,8 @@ QVariant &QDeclarativePropertyMap::operator[](const QString &key) //### optimize Q_D(QDeclarativePropertyMap); QByteArray utf8key = key.toUtf8(); - if (!d->keys.contains(key)) { - d->keys.append(key); + if (!d->keys.contains(key)) d->mo->setValue(utf8key, QVariant()); //force creation -- needed below - } return (*(d->mo))[utf8key]; } @@ -268,9 +271,9 @@ const QVariant QDeclarativePropertyMap::operator[](const QString &key) const } /*! - \fn void QDeclarativePropertyMap::valueChanged(const QString &key) + \fn void QDeclarativePropertyMap::valueChanged(const QString &key, const QVariant &value) 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. + is the key corresponding to the \a value that was changed. \note valueChanged() is \bold NOT emitted when changes are made by calling insert() or clear() - it is only emitted when a value is updated from QML. diff --git a/src/declarative/util/qdeclarativepropertymap.h b/src/declarative/util/qdeclarativepropertymap.h index 513089f..e0b7ce3 100644 --- a/src/declarative/util/qdeclarativepropertymap.h +++ b/src/declarative/util/qdeclarativepropertymap.h @@ -76,7 +76,7 @@ public: const QVariant operator[](const QString &key) const; Q_SIGNALS: - void valueChanged(const QString &key); + void valueChanged(const QString &key, const QVariant &value); private: Q_DECLARE_PRIVATE(QDeclarativePropertyMap) diff --git a/src/declarative/util/qdeclarativesmoothedanimation.cpp b/src/declarative/util/qdeclarativesmoothedanimation.cpp new file mode 100644 index 0000000..b3a9b9a --- /dev/null +++ b/src/declarative/util/qdeclarativesmoothedanimation.cpp @@ -0,0 +1,483 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (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 Technology Preview License Agreement accompanying +** this package. +** +** 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.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdeclarativesmoothedanimation_p.h" +#include "qdeclarativesmoothedanimation_p_p.h" + +#include "qdeclarativeanimation_p_p.h" + +#include <qdeclarativeproperty.h> +#include "qdeclarativeproperty_p.h" + +#include "qdeclarativeglobal_p.h" + +#include <QtCore/qdebug.h> + +#include <math.h> + +#define DELAY_STOP_TIMER_INTERVAL 32 + +QT_BEGIN_NAMESPACE + +QSmoothedAnimation::QSmoothedAnimation(QObject *parent) + : QAbstractAnimation(parent), to(0), velocity(200), userDuration(-1), maximumEasingTime(-1), + reversingMode(QDeclarativeSmoothedAnimation::Eased), initialVelocity(0), + trackVelocity(0), initialValue(0), invert(false), finalDuration(-1), lastTime(0) +{ + delayedStopTimer.setInterval(DELAY_STOP_TIMER_INTERVAL); + delayedStopTimer.setSingleShot(true); + connect(&delayedStopTimer, SIGNAL(timeout()), this, SLOT(stop())); +} + +void QSmoothedAnimation::restart() +{ + if (state() != QAbstractAnimation::Running) + start(); + else + init(); +} + +void QSmoothedAnimation::updateState(QAbstractAnimation::State newState, QAbstractAnimation::State /*oldState*/) +{ + if (newState == QAbstractAnimation::Running) + init(); +} + +void QSmoothedAnimation::delayedStop() +{ + if (!delayedStopTimer.isActive()) + delayedStopTimer.start(); +} + +int QSmoothedAnimation::duration() const +{ + return -1; +} + +bool QSmoothedAnimation::recalc() +{ + s = to - initialValue; + vi = initialVelocity; + + s = (invert? -1.0: 1.0) * s; + + if (userDuration > 0 && velocity > 0) { + tf = s / velocity; + if (tf > (userDuration / 1000.)) tf = (userDuration / 1000.); + } else if (userDuration > 0) { + tf = userDuration / 1000.; + } else if (velocity > 0) { + tf = s / velocity; + } else { + return false; + } + + finalDuration = ceil(tf * 1000.0); + + if (maximumEasingTime == 0) { + a = 0; + d = 0; + tp = 0; + td = tf; + vp = velocity; + sp = 0; + sd = s; + } else if (maximumEasingTime != -1 && tf > (maximumEasingTime / 1000.)) { + qreal met = maximumEasingTime / 1000.; + td = tf - met; + + qreal c1 = td; + qreal c2 = (tf - td) * vi - tf * velocity; + qreal c3 = -0.5 * (tf - td) * vi * vi; + + qreal vp1 = (-c2 + sqrt(c2 * c2 - 4 * c1 * c3)) / (2. * c1); + + vp = vp1; + a = vp / met; + d = a; + tp = (vp - vi) / a; + sp = vi * tp + 0.5 * a * tp * tp; + sd = sp + (td - tp) * vp; + } else { + qreal c1 = 0.25 * tf * tf; + qreal c2 = 0.5 * vi * tf - s; + qreal c3 = -0.25 * vi * vi; + + qreal a1 = (-c2 + sqrt(c2 * c2 - 4 * c1 * c3)) / (2. * c1); + + qreal tp1 = 0.5 * tf - 0.5 * vi / a1; + qreal vp1 = a1 * tp1 + vi; + + qreal sp1 = 0.5 * a1 * tp1 * tp1 + vi * tp1; + + a = a1; + d = a1; + tp = tp1; + td = tp1; + vp = vp1; + sp = sp1; + sd = sp1; + } + return true; +} + +qreal QSmoothedAnimation::easeFollow(qreal time_seconds) +{ + qreal value; + if (time_seconds < tp) { + trackVelocity = vi + time_seconds * a; + value = 0.5 * a * time_seconds * time_seconds + vi * time_seconds; + } else if (time_seconds < td) { + time_seconds -= tp; + trackVelocity = vp; + value = sp + time_seconds * vp; + } else if (time_seconds < tf) { + time_seconds -= td; + trackVelocity = vp - time_seconds * a; + value = sd - 0.5 * d * time_seconds * time_seconds + vp * time_seconds; + } else { + trackVelocity = 0; + value = s; + delayedStop(); + } + + // to normalize 's' between [0..1], divide 'value' by 's' + return value; +} + +void QSmoothedAnimation::updateCurrentTime(int t) +{ + qreal time_seconds = qreal(t - lastTime) / 1000.; + + qreal value = easeFollow(time_seconds); + value *= (invert? -1.0: 1.0); + QDeclarativePropertyPrivate::write(target, initialValue + value, + QDeclarativePropertyPrivate::BypassInterceptor + | QDeclarativePropertyPrivate::DontRemoveBinding); +} + +void QSmoothedAnimation::init() +{ + if (velocity == 0) { + stop(); + return; + } + + if (delayedStopTimer.isActive()) + delayedStopTimer.stop(); + + initialValue = target.read().toReal(); + lastTime = this->currentTime(); + + if (to == initialValue) { + stop(); + return; + } + + bool hasReversed = trackVelocity != 0. && + ((trackVelocity > 0) == ((initialValue - to) > 0)); + + if (hasReversed) { + switch (reversingMode) { + default: + case QDeclarativeSmoothedAnimation::Eased: + break; + case QDeclarativeSmoothedAnimation::Sync: + QDeclarativePropertyPrivate::write(target, to, + QDeclarativePropertyPrivate::BypassInterceptor + | QDeclarativePropertyPrivate::DontRemoveBinding); + return; + case QDeclarativeSmoothedAnimation::Immediate: + initialVelocity = 0; + delayedStop(); + break; + } + } + + trackVelocity = initialVelocity; + + invert = (to < initialValue); + + if (!recalc()) { + QDeclarativePropertyPrivate::write(target, to, + QDeclarativePropertyPrivate::BypassInterceptor + | QDeclarativePropertyPrivate::DontRemoveBinding); + stop(); + return; + } +} + +/*! + \qmlclass SmoothedAnimation QDeclarativeSmoothedAnimation + \since 4.7 + \brief The SmoothedAnimation element allows a property to smoothly track a value. + + The SmoothedAnimation smoothly animates a property's value to a set target value + using an ease in/out quad easing curve. If the animation is restarted + with a different target value, the easing curves used to animate to the old + and the new target values are spliced together to avoid any obvious visual + glitches. + + The property animation is configured by setting the velocity at which the + animation should occur, or the duration that the animation should take. + If both a velocity and a duration are specified, the one that results in + the quickest animation is chosen for each change in the target value. + + For example, animating from 0 to 800 will take 4 seconds if a velocity + of 200 is set, will take 8 seconds with a duration of 8000 set, and will + take 4 seconds with both a velocity of 200 and a duration of 8000 set. + Animating from 0 to 20000 will take 10 seconds if a velocity of 200 is set, + will take 8 seconds with a duration of 8000 set, and will take 8 seconds + with both a velocity of 200 and a duration of 8000 set. + + The follow example shows one rectangle tracking the position of another. +\code +import Qt 4.6 + +Rectangle { + width: 800; height: 600; color: "blue" + + Rectangle { + color: "green" + width: 60; height: 60; + x: rect1.x - 5; y: rect1.y - 5; + Behavior on x { SmoothedAnimation { velocity: 200 } } + Behavior on y { SmoothedAnimation { velocity: 200 } } + } + + Rectangle { + id: rect1 + color: "red" + width: 50; height: 50; + } + + focus: true + Keys.onRightPressed: rect1.x = rect1.x + 100 + Keys.onLeftPressed: rect1.x = rect1.x - 100 + Keys.onUpPressed: rect1.y = rect1.y - 100 + Keys.onDownPressed: rect1.y = rect1.y + 100 +} +\endcode + + The default velocity of SmoothedAnimation is 200 units/second. Note that if the range of the + value being animated is small, then the velocity will need to be adjusted + appropriately. For example, the opacity of an item ranges from 0 - 1.0. + To enable a smooth animation in this range the velocity will need to be + set to a value such as 0.5 units/second. Animating from 0 to 1.0 with a velocity + of 0.5 will take 2000 ms to complete. + + \sa SpringFollow +*/ + +QDeclarativeSmoothedAnimation::QDeclarativeSmoothedAnimation(QObject *parent) +: QDeclarativeNumberAnimation(*(new QDeclarativeSmoothedAnimationPrivate), parent) +{ +} + +QDeclarativeSmoothedAnimation::~QDeclarativeSmoothedAnimation() +{ +} + +QDeclarativeSmoothedAnimationPrivate::QDeclarativeSmoothedAnimationPrivate() + : wrapperGroup(new QParallelAnimationGroup), anim(new QSmoothedAnimation) +{ + Q_Q(QDeclarativeSmoothedAnimation); + QDeclarative_setParent_noEvent(wrapperGroup, q); + QDeclarative_setParent_noEvent(anim, q); +} + +QAbstractAnimation* QDeclarativeSmoothedAnimation::qtAnimation() +{ + Q_D(QDeclarativeSmoothedAnimation); + return d->wrapperGroup; +} + +void QDeclarativeSmoothedAnimation::transition(QDeclarativeStateActions &actions, + QDeclarativeProperties &modified, + TransitionDirection direction) +{ + Q_D(QDeclarativeSmoothedAnimation); + QDeclarativeNumberAnimation::transition(actions, modified, direction); + + if (!d->actions) + return; + + QSet<QAbstractAnimation*> anims; + for (int i = 0; i < d->actions->size(); i++) { + QSmoothedAnimation *ease; + qreal trackVelocity; + bool needsRestart; + if (!d->activeAnimations.contains((*d->actions)[i].property)) { + ease = new QSmoothedAnimation(); + d->wrapperGroup->addAnimation(ease); + d->activeAnimations.insert((*d->actions)[i].property, ease); + trackVelocity = 0.0; + needsRestart = false; + } else { + ease = d->activeAnimations.value((*d->actions)[i].property); + trackVelocity = ease->trackVelocity; + needsRestart = true; + } + + ease->target = (*d->actions)[i].property; + ease->to = (*d->actions)[i].toValue.toReal(); + + // copying public members from main value holder animation + ease->maximumEasingTime = d->anim->maximumEasingTime; + ease->reversingMode = d->anim->reversingMode; + ease->velocity = d->anim->velocity; + ease->userDuration = d->anim->userDuration; + + ease->trackVelocity = trackVelocity; + ease->initialVelocity = trackVelocity; + + if (needsRestart) + ease->init(); + anims.insert(ease); + } + + for (int i = d->wrapperGroup->animationCount() - 1; i >= 0 ; --i) { + if (!anims.contains(d->wrapperGroup->animationAt(i))) { + QSmoothedAnimation *ease = static_cast<QSmoothedAnimation*>(d->wrapperGroup->animationAt(i)); + d->activeAnimations.remove(ease->target); + d->wrapperGroup->takeAnimation(i); + delete ease; + } + } +} + +/*! + \qmlproperty enumeration SmoothedAnimation::reversingMode + + Sets how the SmoothedAnimation behaves if an animation direction is reversed. + + If reversing mode is \c Eased, the animation will smoothly decelerate, and + then reverse direction. If the reversing mode is \c Immediate, the + animation will immediately begin accelerating in the reverse direction, + begining with a velocity of 0. If the reversing mode is \c Sync, the + property is immediately set to the target value. +*/ +QDeclarativeSmoothedAnimation::ReversingMode QDeclarativeSmoothedAnimation::reversingMode() const +{ + Q_D(const QDeclarativeSmoothedAnimation); + return (QDeclarativeSmoothedAnimation::ReversingMode) d->anim->reversingMode; +} + +void QDeclarativeSmoothedAnimation::setReversingMode(ReversingMode m) +{ + Q_D(QDeclarativeSmoothedAnimation); + if (d->anim->reversingMode == m) + return; + + d->anim->reversingMode = m; + emit reversingModeChanged(); +} + +/*! + \qmlproperty int SmoothedAnimation::duration + + This property holds the animation duration, in msecs, used when tracking the source. + + Setting this to -1 (the default) disables the duration value. +*/ +int QDeclarativeSmoothedAnimation::duration() const +{ + Q_D(const QDeclarativeSmoothedAnimation); + return d->anim->userDuration; +} + +void QDeclarativeSmoothedAnimation::setDuration(int duration) +{ + Q_D(QDeclarativeSmoothedAnimation); + if (duration != -1) + QDeclarativeNumberAnimation::setDuration(duration); + d->anim->userDuration = duration; +} + +qreal QDeclarativeSmoothedAnimation::velocity() const +{ + Q_D(const QDeclarativeSmoothedAnimation); + return d->anim->velocity; +} + +/*! + \qmlproperty qreal SmoothedAnimation::velocity + + This property holds the average velocity allowed when tracking the 'to' value. + + The default velocity of SmoothedAnimation is 200 units/second. + + Setting this to -1 disables the velocity value. +*/ +void QDeclarativeSmoothedAnimation::setVelocity(qreal v) +{ + Q_D(QDeclarativeSmoothedAnimation); + if (d->anim->velocity == v) + return; + + d->anim->velocity = v; + emit velocityChanged(); +} + +/*! +\qmlproperty qreal SmoothedAnimation::maximumEasingTime + +This property specifies the maximum time, in msecs, an "eases" during the follow should take. +Setting this property causes the velocity to "level out" after at a time. Setting +a negative value reverts to the normal mode of easing over the entire animation +duration. + +The default value is -1. +*/ +int QDeclarativeSmoothedAnimation::maximumEasingTime() const +{ + Q_D(const QDeclarativeSmoothedAnimation); + return d->anim->maximumEasingTime; +} + +void QDeclarativeSmoothedAnimation::setMaximumEasingTime(int v) +{ + Q_D(QDeclarativeSmoothedAnimation); + d->anim->maximumEasingTime = v; + emit maximumEasingTimeChanged(); +} + +QT_END_NAMESPACE diff --git a/src/declarative/util/qdeclarativeeasefollow_p.h b/src/declarative/util/qdeclarativesmoothedanimation_p.h index 83d1eff..50ed00c 100644 --- a/src/declarative/util/qdeclarativeeasefollow_p.h +++ b/src/declarative/util/qdeclarativesmoothedanimation_p.h @@ -39,11 +39,11 @@ ** ****************************************************************************/ -#ifndef QDECLARATIVEEASEFOLLOW_H -#define QDECLARATIVEEASEFOLLOW_H +#ifndef QDECLARATIVESMOOTHEDANIMATION_H +#define QDECLARATIVESMOOTHEDANIMATION_H #include <qdeclarative.h> -#include <qdeclarativepropertyvaluesource.h> +#include "qdeclarativeanimation_p.h" #include <QtCore/qobject.h> @@ -54,61 +54,51 @@ QT_BEGIN_NAMESPACE QT_MODULE(Declarative) class QDeclarativeProperty; -class QDeclarativeEaseFollowPrivate; -class Q_DECLARATIVE_EXPORT QDeclarativeEaseFollow : public QObject, - public QDeclarativePropertyValueSource +class QDeclarativeSmoothedAnimationPrivate; +class Q_DECLARATIVE_EXPORT QDeclarativeSmoothedAnimation : public QDeclarativeNumberAnimation { Q_OBJECT - Q_DECLARE_PRIVATE(QDeclarativeEaseFollow) - Q_INTERFACES(QDeclarativePropertyValueSource) + Q_DECLARE_PRIVATE(QDeclarativeSmoothedAnimation) Q_ENUMS(ReversingMode) - Q_PROPERTY(qreal source READ sourceValue WRITE setSourceValue NOTIFY sourceChanged) Q_PROPERTY(qreal velocity READ velocity WRITE setVelocity NOTIFY velocityChanged) - Q_PROPERTY(qreal duration READ duration WRITE setDuration NOTIFY durationChanged) Q_PROPERTY(ReversingMode reversingMode READ reversingMode WRITE setReversingMode NOTIFY reversingModeChanged) - Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged) Q_PROPERTY(qreal maximumEasingTime READ maximumEasingTime WRITE setMaximumEasingTime NOTIFY maximumEasingTimeChanged) public: enum ReversingMode { Eased, Immediate, Sync }; - QDeclarativeEaseFollow(QObject *parent = 0); - ~QDeclarativeEaseFollow(); + QDeclarativeSmoothedAnimation(QObject *parent = 0); + ~QDeclarativeSmoothedAnimation(); ReversingMode reversingMode() const; void setReversingMode(ReversingMode); - qreal sourceValue() const; - void setSourceValue(qreal); + virtual int duration() const; + virtual void setDuration(int); qreal velocity() const; void setVelocity(qreal); - qreal duration() const; - void setDuration(qreal); + int maximumEasingTime() const; + void setMaximumEasingTime(int); - bool enabled() const; - void setEnabled(bool enabled); - - qreal maximumEasingTime() const; - void setMaximumEasingTime(qreal); - - virtual void setTarget(const QDeclarativeProperty &); +public: + virtual void transition(QDeclarativeStateActions &actions, + QDeclarativeProperties &modified, + TransitionDirection direction); + QAbstractAnimation* qtAnimation(); Q_SIGNALS: - void sourceChanged(); void velocityChanged(); - void durationChanged(); void reversingModeChanged(); - void enabledChanged(); void maximumEasingTimeChanged(); }; QT_END_NAMESPACE -QML_DECLARE_TYPE(QDeclarativeEaseFollow); +QML_DECLARE_TYPE(QDeclarativeSmoothedAnimation); QT_END_HEADER -#endif // QDECLARATIVEEASEFOLLOW_H +#endif // QDECLARATIVESMOOTHEDANIMATION_H diff --git a/src/declarative/util/qdeclarativesmoothedanimation_p_p.h b/src/declarative/util/qdeclarativesmoothedanimation_p_p.h new file mode 100644 index 0000000..bdceeb3 --- /dev/null +++ b/src/declarative/util/qdeclarativesmoothedanimation_p_p.h @@ -0,0 +1,134 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (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 Technology Preview License Agreement accompanying +** this package. +** +** 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.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVESMOOTHEDANIMATION_P_H +#define QDECLARATIVESMOOTHEDANIMATION_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qdeclarativesmoothedanimation_p.h" +#include "qdeclarativeanimation_p.h" + +#include "qdeclarativeanimation_p_p.h" + +#include <qparallelanimationgroup.h> + +#include <private/qobject_p.h> +#include <QTimer> + +QT_BEGIN_NAMESPACE + +class QSmoothedAnimation : public QAbstractAnimation +{ +public: + QSmoothedAnimation(QObject *parent=0); + + qreal to; + qreal velocity; + int userDuration; + + int maximumEasingTime; + QDeclarativeSmoothedAnimation::ReversingMode reversingMode; + + qreal initialVelocity; + qreal trackVelocity; + + QDeclarativeProperty target; + + int duration() const; + void restart(); + void init(); + +protected: + virtual void updateCurrentTime(int); + virtual void updateState(QAbstractAnimation::State, QAbstractAnimation::State); + +private: + qreal easeFollow(qreal); + qreal initialValue; + + bool invert; + + int finalDuration; + + // Parameters for use in updateCurrentTime() + qreal a; // Acceleration + qreal d; // Deceleration + qreal tf; // Total time + qreal tp; // Time at which peak velocity occurs + qreal td; // Time at which decelleration begins + qreal vp; // Velocity at tp + qreal sp; // Displacement at tp + qreal sd; // Displacement at td + qreal vi; // "Normalized" initialvelocity + qreal s; // Total s + + int lastTime; + + bool recalc(); + void delayedStop(); + + QTimer delayedStopTimer; +}; + +class QDeclarativeSmoothedAnimationPrivate : public QDeclarativePropertyAnimationPrivate +{ + Q_DECLARE_PUBLIC(QDeclarativeSmoothedAnimation) +public: + QDeclarativeSmoothedAnimationPrivate(); + + QParallelAnimationGroup *wrapperGroup; + QSmoothedAnimation *anim; + QHash<QDeclarativeProperty, QSmoothedAnimation*> activeAnimations; +}; + +QT_END_NAMESPACE + +#endif // QDECLARATIVESMOOTHEDANIMATION_P_H diff --git a/src/declarative/util/qdeclarativespringfollow.cpp b/src/declarative/util/qdeclarativespringfollow.cpp index 1d69dd3..063c3df 100644 --- a/src/declarative/util/qdeclarativespringfollow.cpp +++ b/src/declarative/util/qdeclarativespringfollow.cpp @@ -224,11 +224,11 @@ void QDeclarativeSpringFollowPrivate::stop() color: "#00ff00" y: 200 // initial value SequentialAnimation on y { - running: true - repeat: true + loops: Animation.Infinite NumberAnimation { to: 200 - easing: "easeOutBounce(amplitude:100)" + easing.type: "OutBounce" + easing.amplitude: 100 duration: 2000 } PauseAnimation { duration: 1000 } @@ -242,8 +242,6 @@ void QDeclarativeSpringFollowPrivate::stop() SpringFollow on y { source: rect1.y; velocity: 200 } } \endcode - - \sa EaseFollow */ QDeclarativeSpringFollow::QDeclarativeSpringFollow(QObject *parent) diff --git a/src/declarative/util/qdeclarativestate_p_p.h b/src/declarative/util/qdeclarativestate_p_p.h index 6f52219..558c99b 100644 --- a/src/declarative/util/qdeclarativestate_p_p.h +++ b/src/declarative/util/qdeclarativestate_p_p.h @@ -58,8 +58,8 @@ #include "qdeclarativeanimation_p_p.h" #include "qdeclarativetransitionmanager_p_p.h" -#include <qdeclarativeproperty_p.h> -#include <qdeclarativeguard_p.h> +#include <private/qdeclarativeproperty_p.h> +#include <private/qdeclarativeguard_p.h> #include <private/qobject_p.h> diff --git a/src/declarative/util/qdeclarativestategroup.cpp b/src/declarative/util/qdeclarativestategroup.cpp index 083e87d..258a9e9 100644 --- a/src/declarative/util/qdeclarativestategroup.cpp +++ b/src/declarative/util/qdeclarativestategroup.cpp @@ -69,6 +69,7 @@ public: static void append_state(QDeclarativeListProperty<QDeclarativeState> *list, QDeclarativeState *state); static int count_state(QDeclarativeListProperty<QDeclarativeState> *list); static QDeclarativeState *at_state(QDeclarativeListProperty<QDeclarativeState> *list, int index); + static void clear_states(QDeclarativeListProperty<QDeclarativeState> *list); QList<QDeclarativeState *> states; QList<QDeclarativeTransition *> transitions; @@ -150,7 +151,8 @@ QDeclarativeListProperty<QDeclarativeState> QDeclarativeStateGroup::statesProper Q_D(QDeclarativeStateGroup); return QDeclarativeListProperty<QDeclarativeState>(this, &d->states, &QDeclarativeStateGroupPrivate::append_state, &QDeclarativeStateGroupPrivate::count_state, - &QDeclarativeStateGroupPrivate::at_state); + &QDeclarativeStateGroupPrivate::at_state, + &QDeclarativeStateGroupPrivate::clear_states); } void QDeclarativeStateGroupPrivate::append_state(QDeclarativeListProperty<QDeclarativeState> *list, QDeclarativeState *state) @@ -175,6 +177,16 @@ QDeclarativeState *QDeclarativeStateGroupPrivate::at_state(QDeclarativeListPrope return _this->d_func()->states.at(index); } +void QDeclarativeStateGroupPrivate::clear_states(QDeclarativeListProperty<QDeclarativeState> *list) +{ + QDeclarativeStateGroup *_this = static_cast<QDeclarativeStateGroup *>(list->object); + _this->d_func()->setCurrentStateInternal(QString(), true); + for (int i = 0; i < _this->d_func()->states.count(); ++i) { + _this->d_func()->states.at(i)->setStateGroup(0); + } + _this->d_func()->states.clear(); +} + /*! \qmlproperty list<Transition> StateGroup::transitions This property holds a list of transitions defined by the state group. @@ -206,13 +218,11 @@ QDeclarativeListProperty<QDeclarativeTransition> QDeclarativeStateGroup::transit example: \qml - Script { - function toggle() { - if (button.state == 'On') - button.state = 'Off'; - else - button.state = 'On'; - } + function toggle() { + if (button.state == 'On') + button.state = 'Off'; + else + button.state = 'On'; } \endqml diff --git a/src/declarative/util/qdeclarativestateoperations.cpp b/src/declarative/util/qdeclarativestateoperations.cpp index 6f5bb66..3469136 100644 --- a/src/declarative/util/qdeclarativestateoperations.cpp +++ b/src/declarative/util/qdeclarativestateoperations.cpp @@ -168,7 +168,7 @@ void QDeclarativeParentChangePrivate::doChange(QDeclarativeItem *targetParent, Q for the original and new parent). You can specify at which point in a transition you want a ParentChange to occur by - using a ParentAnimation or ParentAction. + using a ParentAnimation. */ @@ -456,11 +456,10 @@ void QDeclarativeParentChange::saveCurrentValues() } d->rewindParent = d->target->parentItem(); + d->rewindStackBefore = 0; - if (!d->rewindParent) { - d->rewindStackBefore = 0; + if (!d->rewindParent) return; - } //try to determine the item's original stack position so we can restore it int siblingIndex = ((AccessibleFxItem*)d->target)->siblingIndex() + 1; @@ -495,9 +494,31 @@ public: \qmlclass StateChangeScript QDeclarativeStateChangeScript \brief The StateChangeScript element allows you to run a script in a state. - The script specified will be run immediately when the state is made current. - Alternatively you can use a ScriptAction to specify at which point in the transition + StateChangeScripts are run when entering the state. You can use + ScriptAction to specify at which point in the transition you want the StateChangeScript to be run. + + \qml + State { + name "state1" + StateChangeScript { + name: "myScript" + script: doStateStuff(); + } + ... + } + ... + Transition { + to: "state1" + SequentialAnimation { + NumberAnimation { ... } + ScriptAction { scriptName: "myScript" } + NumberAnimation { ... } + } + } + \endqml + + \sa ScriptAction */ QDeclarativeStateChangeScript::QDeclarativeStateChangeScript(QObject *parent) @@ -588,209 +609,343 @@ QString QDeclarativeStateChangeScript::typeName() const For more information on anchors see \l {anchor-layout}{Anchor Layouts}. */ - - -class QDeclarativeAnchorChangesPrivate : public QObjectPrivate +class QDeclarativeAnchorSetPrivate : public QObjectPrivate { + Q_DECLARE_PUBLIC(QDeclarativeAnchorSet) public: - QDeclarativeAnchorChangesPrivate() : target(0) {} + QDeclarativeAnchorSetPrivate() + : usedAnchors(0), fill(0), + centerIn(0)/*, leftMargin(0), rightMargin(0), topMargin(0), bottomMargin(0), + margins(0), vCenterOffset(0), hCenterOffset(0), baselineOffset(0)*/ + { + } - QDeclarativeItem *target; - QString resetString; + QDeclarativeAnchors::UsedAnchors usedAnchors; + //### change to QDeclarativeAnchors::UsedAnchors resetAnchors QStringList resetList; + QDeclarativeItem *fill; + QDeclarativeItem *centerIn; + QDeclarativeAnchorLine left; QDeclarativeAnchorLine right; - QDeclarativeAnchorLine horizontalCenter; QDeclarativeAnchorLine top; QDeclarativeAnchorLine bottom; - QDeclarativeAnchorLine verticalCenter; + QDeclarativeAnchorLine vCenter; + QDeclarativeAnchorLine hCenter; QDeclarativeAnchorLine baseline; - QDeclarativeAnchorLine origLeft; - QDeclarativeAnchorLine origRight; - QDeclarativeAnchorLine origHCenter; - QDeclarativeAnchorLine origTop; - QDeclarativeAnchorLine origBottom; - QDeclarativeAnchorLine origVCenter; - QDeclarativeAnchorLine origBaseline; - - QDeclarativeAnchorLine rewindLeft; - QDeclarativeAnchorLine rewindRight; - QDeclarativeAnchorLine rewindHCenter; - QDeclarativeAnchorLine rewindTop; - QDeclarativeAnchorLine rewindBottom; - QDeclarativeAnchorLine rewindVCenter; - QDeclarativeAnchorLine rewindBaseline; + /*qreal leftMargin; + qreal rightMargin; + qreal topMargin; + qreal bottomMargin; + qreal margins; + qreal vCenterOffset; + qreal hCenterOffset; + qreal baselineOffset;*/ +}; - qreal fromX; - qreal fromY; - qreal fromWidth; - qreal fromHeight; +QDeclarativeAnchorSet::QDeclarativeAnchorSet(QObject *parent) + : QObject(*new QDeclarativeAnchorSetPrivate, parent) +{ +} - qreal toX; - qreal toY; - qreal toWidth; - qreal toHeight; +QDeclarativeAnchorSet::~QDeclarativeAnchorSet() +{ +} - qreal rewindX; - qreal rewindY; - qreal rewindWidth; - qreal rewindHeight; +QDeclarativeAnchorLine QDeclarativeAnchorSet::top() const +{ + Q_D(const QDeclarativeAnchorSet); + return d->top; +} - bool applyOrigLeft; - bool applyOrigRight; - bool applyOrigHCenter; - bool applyOrigTop; - bool applyOrigBottom; - bool applyOrigVCenter; - bool applyOrigBaseline; -}; +void QDeclarativeAnchorSet::setTop(const QDeclarativeAnchorLine &edge) +{ + Q_D(QDeclarativeAnchorSet); + d->usedAnchors |= QDeclarativeAnchors::HasTopAnchor; + d->top = edge; +} -/*! - \qmlproperty Item AnchorChanges::target - This property holds the Item whose anchors will change -*/ +void QDeclarativeAnchorSet::resetTop() +{ + Q_D(QDeclarativeAnchorSet); + d->usedAnchors &= ~QDeclarativeAnchors::HasTopAnchor; + d->top = QDeclarativeAnchorLine(); + d->resetList << QLatin1String("top"); +} -QDeclarativeAnchorChanges::QDeclarativeAnchorChanges(QObject *parent) - : QDeclarativeStateOperation(*(new QDeclarativeAnchorChangesPrivate), parent) +QDeclarativeAnchorLine QDeclarativeAnchorSet::bottom() const { + Q_D(const QDeclarativeAnchorSet); + return d->bottom; } -QDeclarativeAnchorChanges::~QDeclarativeAnchorChanges() +void QDeclarativeAnchorSet::setBottom(const QDeclarativeAnchorLine &edge) { + Q_D(QDeclarativeAnchorSet); + d->usedAnchors |= QDeclarativeAnchors::HasBottomAnchor; + d->bottom = edge; } -QDeclarativeAnchorChanges::ActionList QDeclarativeAnchorChanges::actions() +void QDeclarativeAnchorSet::resetBottom() { - QDeclarativeAction a; - a.event = this; - return ActionList() << a; + Q_D(QDeclarativeAnchorSet); + d->usedAnchors &= ~QDeclarativeAnchors::HasBottomAnchor; + d->bottom = QDeclarativeAnchorLine(); + d->resetList << QLatin1String("bottom"); } -QDeclarativeItem *QDeclarativeAnchorChanges::object() const +QDeclarativeAnchorLine QDeclarativeAnchorSet::verticalCenter() const { - Q_D(const QDeclarativeAnchorChanges); - return d->target; + Q_D(const QDeclarativeAnchorSet); + return d->vCenter; } -void QDeclarativeAnchorChanges::setObject(QDeclarativeItem *target) +void QDeclarativeAnchorSet::setVerticalCenter(const QDeclarativeAnchorLine &edge) { - Q_D(QDeclarativeAnchorChanges); - d->target = target; + Q_D(QDeclarativeAnchorSet); + d->usedAnchors |= QDeclarativeAnchors::HasVCenterAnchor; + d->vCenter = edge; } -QString QDeclarativeAnchorChanges::reset() const +void QDeclarativeAnchorSet::resetVerticalCenter() { - Q_D(const QDeclarativeAnchorChanges); - return d->resetString; + Q_D(QDeclarativeAnchorSet); + d->usedAnchors &= ~QDeclarativeAnchors::HasVCenterAnchor; + d->vCenter = QDeclarativeAnchorLine(); + d->resetList << QLatin1String("verticalCenter"); } -void QDeclarativeAnchorChanges::setReset(const QString &reset) +QDeclarativeAnchorLine QDeclarativeAnchorSet::baseline() const { - Q_D(QDeclarativeAnchorChanges); - d->resetString = reset; - d->resetList = d->resetString.split(QLatin1Char(',')); - for (int i = 0; i < d->resetList.count(); ++i) - d->resetList[i] = d->resetList.at(i).trimmed(); + Q_D(const QDeclarativeAnchorSet); + return d->baseline; } -/*! - \qmlproperty AnchorLine AnchorChanges::left - \qmlproperty AnchorLine AnchorChanges::right - \qmlproperty AnchorLine AnchorChanges::horizontalCenter - \qmlproperty AnchorLine AnchorChanges::top - \qmlproperty AnchorLine AnchorChanges::bottom - \qmlproperty AnchorLine AnchorChanges::verticalCenter - \qmlproperty AnchorLine AnchorChanges::baseline +void QDeclarativeAnchorSet::setBaseline(const QDeclarativeAnchorLine &edge) +{ + Q_D(QDeclarativeAnchorSet); + d->usedAnchors |= QDeclarativeAnchors::HasBaselineAnchor; + d->baseline = edge; +} - These properties change the respective anchors of the item. -*/ +void QDeclarativeAnchorSet::resetBaseline() +{ + Q_D(QDeclarativeAnchorSet); + d->usedAnchors &= ~QDeclarativeAnchors::HasBaselineAnchor; + d->baseline = QDeclarativeAnchorLine(); + d->resetList << QLatin1String("baseline"); +} -QDeclarativeAnchorLine QDeclarativeAnchorChanges::left() const +QDeclarativeAnchorLine QDeclarativeAnchorSet::left() const { - Q_D(const QDeclarativeAnchorChanges); + Q_D(const QDeclarativeAnchorSet); return d->left; } -void QDeclarativeAnchorChanges::setLeft(const QDeclarativeAnchorLine &edge) +void QDeclarativeAnchorSet::setLeft(const QDeclarativeAnchorLine &edge) { - Q_D(QDeclarativeAnchorChanges); + Q_D(QDeclarativeAnchorSet); + d->usedAnchors |= QDeclarativeAnchors::HasLeftAnchor; d->left = edge; } -QDeclarativeAnchorLine QDeclarativeAnchorChanges::right() const +void QDeclarativeAnchorSet::resetLeft() { - Q_D(const QDeclarativeAnchorChanges); + Q_D(QDeclarativeAnchorSet); + d->usedAnchors &= ~QDeclarativeAnchors::HasLeftAnchor; + d->left = QDeclarativeAnchorLine(); + d->resetList << QLatin1String("left"); +} + +QDeclarativeAnchorLine QDeclarativeAnchorSet::right() const +{ + Q_D(const QDeclarativeAnchorSet); return d->right; } -void QDeclarativeAnchorChanges::setRight(const QDeclarativeAnchorLine &edge) +void QDeclarativeAnchorSet::setRight(const QDeclarativeAnchorLine &edge) { - Q_D(QDeclarativeAnchorChanges); + Q_D(QDeclarativeAnchorSet); + d->usedAnchors |= QDeclarativeAnchors::HasRightAnchor; d->right = edge; } -QDeclarativeAnchorLine QDeclarativeAnchorChanges::horizontalCenter() const +void QDeclarativeAnchorSet::resetRight() { - Q_D(const QDeclarativeAnchorChanges); - return d->horizontalCenter; + Q_D(QDeclarativeAnchorSet); + d->usedAnchors &= ~QDeclarativeAnchors::HasRightAnchor; + d->right = QDeclarativeAnchorLine(); + d->resetList << QLatin1String("right"); } -void QDeclarativeAnchorChanges::setHorizontalCenter(const QDeclarativeAnchorLine &edge) +QDeclarativeAnchorLine QDeclarativeAnchorSet::horizontalCenter() const { - Q_D(QDeclarativeAnchorChanges); - d->horizontalCenter = edge; + Q_D(const QDeclarativeAnchorSet); + return d->hCenter; } -QDeclarativeAnchorLine QDeclarativeAnchorChanges::top() const +void QDeclarativeAnchorSet::setHorizontalCenter(const QDeclarativeAnchorLine &edge) { - Q_D(const QDeclarativeAnchorChanges); - return d->top; + Q_D(QDeclarativeAnchorSet); + d->usedAnchors |= QDeclarativeAnchors::HasHCenterAnchor; + d->hCenter = edge; } -void QDeclarativeAnchorChanges::setTop(const QDeclarativeAnchorLine &edge) +void QDeclarativeAnchorSet::resetHorizontalCenter() { - Q_D(QDeclarativeAnchorChanges); - d->top = edge; + Q_D(QDeclarativeAnchorSet); + d->usedAnchors &= ~QDeclarativeAnchors::HasHCenterAnchor; + d->hCenter = QDeclarativeAnchorLine(); + d->resetList << QLatin1String("horizontalCenter"); } -QDeclarativeAnchorLine QDeclarativeAnchorChanges::bottom() const +QDeclarativeItem *QDeclarativeAnchorSet::fill() const { - Q_D(const QDeclarativeAnchorChanges); - return d->bottom; + Q_D(const QDeclarativeAnchorSet); + return d->fill; } -void QDeclarativeAnchorChanges::setBottom(const QDeclarativeAnchorLine &edge) +void QDeclarativeAnchorSet::setFill(QDeclarativeItem *f) { - Q_D(QDeclarativeAnchorChanges); - d->bottom = edge; + Q_D(QDeclarativeAnchorSet); + d->fill = f; } -QDeclarativeAnchorLine QDeclarativeAnchorChanges::verticalCenter() const +void QDeclarativeAnchorSet::resetFill() +{ + setFill(0); +} + +QDeclarativeItem *QDeclarativeAnchorSet::centerIn() const +{ + Q_D(const QDeclarativeAnchorSet); + return d->centerIn; +} + +void QDeclarativeAnchorSet::setCenterIn(QDeclarativeItem* c) +{ + Q_D(QDeclarativeAnchorSet); + d->centerIn = c; +} + +void QDeclarativeAnchorSet::resetCenterIn() +{ + setCenterIn(0); +} + + +class QDeclarativeAnchorChangesPrivate : public QObjectPrivate +{ +public: + QDeclarativeAnchorChangesPrivate() + : target(0), anchorSet(new QDeclarativeAnchorSet) {} + ~QDeclarativeAnchorChangesPrivate() { delete anchorSet; } + + QDeclarativeItem *target; + QDeclarativeAnchorSet *anchorSet; + + QDeclarativeAnchorLine origLeft; + QDeclarativeAnchorLine origRight; + QDeclarativeAnchorLine origHCenter; + QDeclarativeAnchorLine origTop; + QDeclarativeAnchorLine origBottom; + QDeclarativeAnchorLine origVCenter; + QDeclarativeAnchorLine origBaseline; + + QDeclarativeAnchorLine rewindLeft; + QDeclarativeAnchorLine rewindRight; + QDeclarativeAnchorLine rewindHCenter; + QDeclarativeAnchorLine rewindTop; + QDeclarativeAnchorLine rewindBottom; + QDeclarativeAnchorLine rewindVCenter; + QDeclarativeAnchorLine rewindBaseline; + + qreal fromX; + qreal fromY; + qreal fromWidth; + qreal fromHeight; + + qreal toX; + qreal toY; + qreal toWidth; + qreal toHeight; + + qreal rewindX; + qreal rewindY; + qreal rewindWidth; + qreal rewindHeight; + + bool applyOrigLeft; + bool applyOrigRight; + bool applyOrigHCenter; + bool applyOrigTop; + bool applyOrigBottom; + bool applyOrigVCenter; + bool applyOrigBaseline; +}; + +/*! + \qmlproperty Item AnchorChanges::target + This property holds the Item whose anchors will change +*/ + +QDeclarativeAnchorChanges::QDeclarativeAnchorChanges(QObject *parent) + : QDeclarativeStateOperation(*(new QDeclarativeAnchorChangesPrivate), parent) { - Q_D(const QDeclarativeAnchorChanges); - return d->verticalCenter; } -void QDeclarativeAnchorChanges::setVerticalCenter(const QDeclarativeAnchorLine &edge) +QDeclarativeAnchorChanges::~QDeclarativeAnchorChanges() +{ +} + +QDeclarativeAnchorChanges::ActionList QDeclarativeAnchorChanges::actions() +{ + QDeclarativeAction a; + a.event = this; + return ActionList() << a; +} + +QDeclarativeAnchorSet *QDeclarativeAnchorChanges::anchors() { Q_D(QDeclarativeAnchorChanges); - d->verticalCenter = edge; + return d->anchorSet; } -QDeclarativeAnchorLine QDeclarativeAnchorChanges::baseline() const +QDeclarativeItem *QDeclarativeAnchorChanges::object() const { Q_D(const QDeclarativeAnchorChanges); - return d->baseline; + return d->target; } -void QDeclarativeAnchorChanges::setBaseline(const QDeclarativeAnchorLine &edge) +void QDeclarativeAnchorChanges::setObject(QDeclarativeItem *target) { Q_D(QDeclarativeAnchorChanges); - d->baseline = edge; + d->target = target; } +/*! + \qmlproperty AnchorLine AnchorChanges::anchors.left + \qmlproperty AnchorLine AnchorChanges::anchors.right + \qmlproperty AnchorLine AnchorChanges::anchors.horizontalCenter + \qmlproperty AnchorLine AnchorChanges::anchors.top + \qmlproperty AnchorLine AnchorChanges::anchors.bottom + \qmlproperty AnchorLine AnchorChanges::anchors.verticalCenter + \qmlproperty AnchorLine AnchorChanges::anchors.baseline + + These properties change the respective anchors of the item. + + To reset an anchor you can assign \c undefined: + \qml + AnchorChanges { + target: myItem + left: undefined //remove myItem's left anchor + right: otherItem.right + } + \endqml +*/ + void QDeclarativeAnchorChanges::execute() { Q_D(QDeclarativeAnchorChanges); @@ -814,36 +969,36 @@ void QDeclarativeAnchorChanges::execute() d->target->anchors()->setBaseline(d->origBaseline); //reset any anchors that have been specified - if (d->resetList.contains(QLatin1String("left"))) + if (d->anchorSet->d_func()->resetList .contains(QLatin1String("left"))) d->target->anchors()->resetLeft(); - if (d->resetList.contains(QLatin1String("right"))) + if (d->anchorSet->d_func()->resetList .contains(QLatin1String("right"))) d->target->anchors()->resetRight(); - if (d->resetList.contains(QLatin1String("horizontalCenter"))) + if (d->anchorSet->d_func()->resetList .contains(QLatin1String("horizontalCenter"))) d->target->anchors()->resetHorizontalCenter(); - if (d->resetList.contains(QLatin1String("top"))) + if (d->anchorSet->d_func()->resetList .contains(QLatin1String("top"))) d->target->anchors()->resetTop(); - if (d->resetList.contains(QLatin1String("bottom"))) + if (d->anchorSet->d_func()->resetList .contains(QLatin1String("bottom"))) d->target->anchors()->resetBottom(); - if (d->resetList.contains(QLatin1String("verticalCenter"))) + if (d->anchorSet->d_func()->resetList .contains(QLatin1String("verticalCenter"))) d->target->anchors()->resetVerticalCenter(); - if (d->resetList.contains(QLatin1String("baseline"))) + if (d->anchorSet->d_func()->resetList .contains(QLatin1String("baseline"))) d->target->anchors()->resetBaseline(); //set any anchors that have been specified - if (d->left.anchorLine != QDeclarativeAnchorLine::Invalid) - d->target->anchors()->setLeft(d->left); - if (d->right.anchorLine != QDeclarativeAnchorLine::Invalid) - d->target->anchors()->setRight(d->right); - if (d->horizontalCenter.anchorLine != QDeclarativeAnchorLine::Invalid) - d->target->anchors()->setHorizontalCenter(d->horizontalCenter); - if (d->top.anchorLine != QDeclarativeAnchorLine::Invalid) - d->target->anchors()->setTop(d->top); - if (d->bottom.anchorLine != QDeclarativeAnchorLine::Invalid) - d->target->anchors()->setBottom(d->bottom); - if (d->verticalCenter.anchorLine != QDeclarativeAnchorLine::Invalid) - d->target->anchors()->setVerticalCenter(d->verticalCenter); - if (d->baseline.anchorLine != QDeclarativeAnchorLine::Invalid) - d->target->anchors()->setBaseline(d->baseline); + if (d->anchorSet->d_func()->left.anchorLine != QDeclarativeAnchorLine::Invalid) + d->target->anchors()->setLeft(d->anchorSet->d_func()->left); + if (d->anchorSet->d_func()->right.anchorLine != QDeclarativeAnchorLine::Invalid) + d->target->anchors()->setRight(d->anchorSet->d_func()->right); + if (d->anchorSet->d_func()->hCenter.anchorLine != QDeclarativeAnchorLine::Invalid) + d->target->anchors()->setHorizontalCenter(d->anchorSet->d_func()->hCenter); + if (d->anchorSet->d_func()->top.anchorLine != QDeclarativeAnchorLine::Invalid) + d->target->anchors()->setTop(d->anchorSet->d_func()->top); + if (d->anchorSet->d_func()->bottom.anchorLine != QDeclarativeAnchorLine::Invalid) + d->target->anchors()->setBottom(d->anchorSet->d_func()->bottom); + if (d->anchorSet->d_func()->vCenter.anchorLine != QDeclarativeAnchorLine::Invalid) + d->target->anchors()->setVerticalCenter(d->anchorSet->d_func()->vCenter); + if (d->anchorSet->d_func()->baseline.anchorLine != QDeclarativeAnchorLine::Invalid) + d->target->anchors()->setBaseline(d->anchorSet->d_func()->baseline); } bool QDeclarativeAnchorChanges::isReversable() @@ -858,19 +1013,19 @@ void QDeclarativeAnchorChanges::reverse() return; //reset any anchors set by the state - if (d->left.anchorLine != QDeclarativeAnchorLine::Invalid) + if (d->anchorSet->d_func()->left.anchorLine != QDeclarativeAnchorLine::Invalid) d->target->anchors()->resetLeft(); - if (d->right.anchorLine != QDeclarativeAnchorLine::Invalid) + if (d->anchorSet->d_func()->right.anchorLine != QDeclarativeAnchorLine::Invalid) d->target->anchors()->resetRight(); - if (d->horizontalCenter.anchorLine != QDeclarativeAnchorLine::Invalid) + if (d->anchorSet->d_func()->hCenter.anchorLine != QDeclarativeAnchorLine::Invalid) d->target->anchors()->resetHorizontalCenter(); - if (d->top.anchorLine != QDeclarativeAnchorLine::Invalid) + if (d->anchorSet->d_func()->top.anchorLine != QDeclarativeAnchorLine::Invalid) d->target->anchors()->resetTop(); - if (d->bottom.anchorLine != QDeclarativeAnchorLine::Invalid) + if (d->anchorSet->d_func()->bottom.anchorLine != QDeclarativeAnchorLine::Invalid) d->target->anchors()->resetBottom(); - if (d->verticalCenter.anchorLine != QDeclarativeAnchorLine::Invalid) + if (d->anchorSet->d_func()->vCenter.anchorLine != QDeclarativeAnchorLine::Invalid) d->target->anchors()->resetVerticalCenter(); - if (d->baseline.anchorLine != QDeclarativeAnchorLine::Invalid) + if (d->anchorSet->d_func()->baseline.anchorLine != QDeclarativeAnchorLine::Invalid) d->target->anchors()->resetBaseline(); //restore previous anchors @@ -944,7 +1099,7 @@ void QDeclarativeAnchorChanges::saveOriginals() d->origBaseline = d->target->anchors()->baseline(); d->applyOrigLeft = d->applyOrigRight = d->applyOrigHCenter = d->applyOrigTop - = d->applyOrigBottom = d->applyOrigHCenter = d->applyOrigBaseline = false; + = d->applyOrigBottom = d->applyOrigVCenter = d->applyOrigBaseline = false; saveCurrentValues(); } @@ -956,26 +1111,26 @@ void QDeclarativeAnchorChanges::copyOriginals(QDeclarativeActionEvent *other) QDeclarativeAnchorChangesPrivate *acp = ac->d_func(); //probably also need to revert some things - d->applyOrigLeft = (acp->left.anchorLine != QDeclarativeAnchorLine::Invalid || - acp->resetList.contains(QLatin1String("left"))); + d->applyOrigLeft = (acp->anchorSet->d_func()->left.anchorLine != QDeclarativeAnchorLine::Invalid || + acp->anchorSet->d_func()->resetList.contains(QLatin1String("left"))); - d->applyOrigRight = (acp->right.anchorLine != QDeclarativeAnchorLine::Invalid || - acp->resetList.contains(QLatin1String("right"))); + d->applyOrigRight = (acp->anchorSet->d_func()->right.anchorLine != QDeclarativeAnchorLine::Invalid || + acp->anchorSet->d_func()->resetList.contains(QLatin1String("right"))); - d->applyOrigHCenter = (acp->horizontalCenter.anchorLine != QDeclarativeAnchorLine::Invalid || - acp->resetList.contains(QLatin1String("horizontalCenter"))); + d->applyOrigHCenter = (acp->anchorSet->d_func()->hCenter.anchorLine != QDeclarativeAnchorLine::Invalid || + acp->anchorSet->d_func()->resetList.contains(QLatin1String("horizontalCenter"))); - d->applyOrigTop = (acp->top.anchorLine != QDeclarativeAnchorLine::Invalid || - acp->resetList.contains(QLatin1String("top"))); + d->applyOrigTop = (acp->anchorSet->d_func()->top.anchorLine != QDeclarativeAnchorLine::Invalid || + acp->anchorSet->d_func()->resetList.contains(QLatin1String("top"))); - d->applyOrigBottom = (acp->bottom.anchorLine != QDeclarativeAnchorLine::Invalid || - acp->resetList.contains(QLatin1String("bottom"))); + d->applyOrigBottom = (acp->anchorSet->d_func()->bottom.anchorLine != QDeclarativeAnchorLine::Invalid || + acp->anchorSet->d_func()->resetList.contains(QLatin1String("bottom"))); - d->applyOrigVCenter = (acp->verticalCenter.anchorLine != QDeclarativeAnchorLine::Invalid || - acp->resetList.contains(QLatin1String("verticalCenter"))); + d->applyOrigVCenter = (acp->anchorSet->d_func()->vCenter.anchorLine != QDeclarativeAnchorLine::Invalid || + acp->anchorSet->d_func()->resetList.contains(QLatin1String("verticalCenter"))); - d->applyOrigBaseline = (acp->baseline.anchorLine != QDeclarativeAnchorLine::Invalid || - acp->resetList.contains(QLatin1String("baseline"))); + d->applyOrigBaseline = (acp->anchorSet->d_func()->baseline.anchorLine != QDeclarativeAnchorLine::Invalid || + acp->anchorSet->d_func()->resetList.contains(QLatin1String("baseline"))); d->origLeft = ac->d_func()->origLeft; d->origRight = ac->d_func()->origRight; @@ -1013,35 +1168,35 @@ void QDeclarativeAnchorChanges::clearBindings() d->target->anchors()->resetBaseline(); //reset any anchors that have been specified - if (d->resetList.contains(QLatin1String("left"))) + if (d->anchorSet->d_func()->resetList .contains(QLatin1String("left"))) d->target->anchors()->resetLeft(); - if (d->resetList.contains(QLatin1String("right"))) + if (d->anchorSet->d_func()->resetList .contains(QLatin1String("right"))) d->target->anchors()->resetRight(); - if (d->resetList.contains(QLatin1String("horizontalCenter"))) + if (d->anchorSet->d_func()->resetList .contains(QLatin1String("horizontalCenter"))) d->target->anchors()->resetHorizontalCenter(); - if (d->resetList.contains(QLatin1String("top"))) + if (d->anchorSet->d_func()->resetList .contains(QLatin1String("top"))) d->target->anchors()->resetTop(); - if (d->resetList.contains(QLatin1String("bottom"))) + if (d->anchorSet->d_func()->resetList .contains(QLatin1String("bottom"))) d->target->anchors()->resetBottom(); - if (d->resetList.contains(QLatin1String("verticalCenter"))) + if (d->anchorSet->d_func()->resetList .contains(QLatin1String("verticalCenter"))) d->target->anchors()->resetVerticalCenter(); - if (d->resetList.contains(QLatin1String("baseline"))) + if (d->anchorSet->d_func()->resetList .contains(QLatin1String("baseline"))) d->target->anchors()->resetBaseline(); //reset any anchors that we'll be setting in the state - if (d->left.anchorLine != QDeclarativeAnchorLine::Invalid) + if (d->anchorSet->d_func()->left.anchorLine != QDeclarativeAnchorLine::Invalid) d->target->anchors()->resetLeft(); - if (d->right.anchorLine != QDeclarativeAnchorLine::Invalid) + if (d->anchorSet->d_func()->right.anchorLine != QDeclarativeAnchorLine::Invalid) d->target->anchors()->resetRight(); - if (d->horizontalCenter.anchorLine != QDeclarativeAnchorLine::Invalid) + if (d->anchorSet->d_func()->hCenter.anchorLine != QDeclarativeAnchorLine::Invalid) d->target->anchors()->resetHorizontalCenter(); - if (d->top.anchorLine != QDeclarativeAnchorLine::Invalid) + if (d->anchorSet->d_func()->top.anchorLine != QDeclarativeAnchorLine::Invalid) d->target->anchors()->resetTop(); - if (d->bottom.anchorLine != QDeclarativeAnchorLine::Invalid) + if (d->anchorSet->d_func()->bottom.anchorLine != QDeclarativeAnchorLine::Invalid) d->target->anchors()->resetBottom(); - if (d->verticalCenter.anchorLine != QDeclarativeAnchorLine::Invalid) + if (d->anchorSet->d_func()->vCenter.anchorLine != QDeclarativeAnchorLine::Invalid) d->target->anchors()->resetVerticalCenter(); - if (d->baseline.anchorLine != QDeclarativeAnchorLine::Invalid) + if (d->anchorSet->d_func()->baseline.anchorLine != QDeclarativeAnchorLine::Invalid) d->target->anchors()->resetBaseline(); } diff --git a/src/declarative/util/qdeclarativestateoperations_p.h b/src/declarative/util/qdeclarativestateoperations_p.h index 66a8717..c97b2da 100644 --- a/src/declarative/util/qdeclarativestateoperations_p.h +++ b/src/declarative/util/qdeclarativestateoperations_p.h @@ -143,54 +143,132 @@ public: virtual void execute(); }; -class QDeclarativeAnchorChangesPrivate; -class Q_DECLARATIVE_EXPORT QDeclarativeAnchorChanges : public QDeclarativeStateOperation, public QDeclarativeActionEvent +class QDeclarativeAnchorChanges; +class QDeclarativeAnchorSetPrivate; +class Q_AUTOTEST_EXPORT QDeclarativeAnchorSet : public QObject { Q_OBJECT - Q_DECLARE_PRIVATE(QDeclarativeAnchorChanges) - Q_PROPERTY(QDeclarativeItem *target READ object WRITE setObject) - Q_PROPERTY(QString reset READ reset WRITE setReset) - Q_PROPERTY(QDeclarativeAnchorLine left READ left WRITE setLeft) - Q_PROPERTY(QDeclarativeAnchorLine right READ right WRITE setRight) - Q_PROPERTY(QDeclarativeAnchorLine horizontalCenter READ horizontalCenter WRITE setHorizontalCenter) - Q_PROPERTY(QDeclarativeAnchorLine top READ top WRITE setTop) - Q_PROPERTY(QDeclarativeAnchorLine bottom READ bottom WRITE setBottom) - Q_PROPERTY(QDeclarativeAnchorLine verticalCenter READ verticalCenter WRITE setVerticalCenter) - Q_PROPERTY(QDeclarativeAnchorLine baseline READ baseline WRITE setBaseline) + Q_PROPERTY(QDeclarativeAnchorLine left READ left WRITE setLeft RESET resetLeft) + Q_PROPERTY(QDeclarativeAnchorLine right READ right WRITE setRight RESET resetRight) + Q_PROPERTY(QDeclarativeAnchorLine horizontalCenter READ horizontalCenter WRITE setHorizontalCenter RESET resetHorizontalCenter) + Q_PROPERTY(QDeclarativeAnchorLine top READ top WRITE setTop RESET resetTop) + Q_PROPERTY(QDeclarativeAnchorLine bottom READ bottom WRITE setBottom RESET resetBottom) + Q_PROPERTY(QDeclarativeAnchorLine verticalCenter READ verticalCenter WRITE setVerticalCenter RESET resetVerticalCenter) + Q_PROPERTY(QDeclarativeAnchorLine baseline READ baseline WRITE setBaseline RESET resetBaseline) + //Q_PROPERTY(QDeclarativeItem *fill READ fill WRITE setFill RESET resetFill) + //Q_PROPERTY(QDeclarativeItem *centerIn READ centerIn WRITE setCenterIn RESET resetCenterIn) + + /*Q_PROPERTY(qreal margins READ margins WRITE setMargins NOTIFY marginsChanged) + Q_PROPERTY(qreal leftMargin READ leftMargin WRITE setLeftMargin NOTIFY leftMarginChanged) + Q_PROPERTY(qreal rightMargin READ rightMargin WRITE setRightMargin NOTIFY rightMarginChanged) + Q_PROPERTY(qreal horizontalCenterOffset READ horizontalCenterOffset WRITE setHorizontalCenterOffset NOTIFY horizontalCenterOffsetChanged()) + Q_PROPERTY(qreal topMargin READ topMargin WRITE setTopMargin NOTIFY topMarginChanged) + Q_PROPERTY(qreal bottomMargin READ bottomMargin WRITE setBottomMargin NOTIFY bottomMarginChanged) + Q_PROPERTY(qreal verticalCenterOffset READ verticalCenterOffset WRITE setVerticalCenterOffset NOTIFY verticalCenterOffsetChanged()) + Q_PROPERTY(qreal baselineOffset READ baselineOffset WRITE setBaselineOffset NOTIFY baselineOffsetChanged())*/ public: - QDeclarativeAnchorChanges(QObject *parent=0); - ~QDeclarativeAnchorChanges(); - - virtual ActionList actions(); - - QDeclarativeItem *object() const; - void setObject(QDeclarativeItem *); - - QString reset() const; - void setReset(const QString &); + QDeclarativeAnchorSet(QObject *parent=0); + virtual ~QDeclarativeAnchorSet(); QDeclarativeAnchorLine left() const; void setLeft(const QDeclarativeAnchorLine &edge); + void resetLeft(); QDeclarativeAnchorLine right() const; void setRight(const QDeclarativeAnchorLine &edge); + void resetRight(); QDeclarativeAnchorLine horizontalCenter() const; void setHorizontalCenter(const QDeclarativeAnchorLine &edge); + void resetHorizontalCenter(); QDeclarativeAnchorLine top() const; void setTop(const QDeclarativeAnchorLine &edge); + void resetTop(); QDeclarativeAnchorLine bottom() const; void setBottom(const QDeclarativeAnchorLine &edge); + void resetBottom(); QDeclarativeAnchorLine verticalCenter() const; void setVerticalCenter(const QDeclarativeAnchorLine &edge); + void resetVerticalCenter(); QDeclarativeAnchorLine baseline() const; void setBaseline(const QDeclarativeAnchorLine &edge); + void resetBaseline(); + + QDeclarativeItem *fill() const; + void setFill(QDeclarativeItem *); + void resetFill(); + + QDeclarativeItem *centerIn() const; + void setCenterIn(QDeclarativeItem *); + void resetCenterIn(); + + /*qreal leftMargin() const; + void setLeftMargin(qreal); + + qreal rightMargin() const; + void setRightMargin(qreal); + + qreal horizontalCenterOffset() const; + void setHorizontalCenterOffset(qreal); + + qreal topMargin() const; + void setTopMargin(qreal); + + qreal bottomMargin() const; + void setBottomMargin(qreal); + + qreal margins() const; + void setMargins(qreal); + + qreal verticalCenterOffset() const; + void setVerticalCenterOffset(qreal); + + qreal baselineOffset() const; + void setBaselineOffset(qreal);*/ + + QDeclarativeAnchors::UsedAnchors usedAnchors() const; + +/*Q_SIGNALS: + void leftMarginChanged(); + void rightMarginChanged(); + void topMarginChanged(); + void bottomMarginChanged(); + void marginsChanged(); + void verticalCenterOffsetChanged(); + void horizontalCenterOffsetChanged(); + void baselineOffsetChanged();*/ + +private: + friend class QDeclarativeAnchorChanges; + Q_DISABLE_COPY(QDeclarativeAnchorSet) + Q_DECLARE_PRIVATE(QDeclarativeAnchorSet) +}; + +class QDeclarativeAnchorChangesPrivate; +class Q_DECLARATIVE_EXPORT QDeclarativeAnchorChanges : public QDeclarativeStateOperation, public QDeclarativeActionEvent +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QDeclarativeAnchorChanges) + + Q_PROPERTY(QDeclarativeItem *target READ object WRITE setObject) + Q_PROPERTY(QDeclarativeAnchorSet *anchors READ anchors CONSTANT) + +public: + QDeclarativeAnchorChanges(QObject *parent=0); + ~QDeclarativeAnchorChanges(); + + virtual ActionList actions(); + + QDeclarativeAnchorSet *anchors(); + + QDeclarativeItem *object() const; + void setObject(QDeclarativeItem *); virtual void execute(); virtual bool isReversable(); @@ -212,6 +290,7 @@ QT_END_NAMESPACE QML_DECLARE_TYPE(QDeclarativeParentChange) QML_DECLARE_TYPE(QDeclarativeStateChangeScript) +QML_DECLARE_TYPE(QDeclarativeAnchorSet) QML_DECLARE_TYPE(QDeclarativeAnchorChanges) QT_END_HEADER diff --git a/src/declarative/util/qdeclarativetransition.cpp b/src/declarative/util/qdeclarativetransition.cpp index ac07b10..1e8be7f 100644 --- a/src/declarative/util/qdeclarativetransition.cpp +++ b/src/declarative/util/qdeclarativetransition.cpp @@ -67,7 +67,7 @@ QT_BEGIN_NAMESPACE \ingroup group_states */ -//ParallelAnimationWrapperallows us to do a "callback" when the animation finishes, rather than connecting +//ParallelAnimationWrapper allows us to do a "callback" when the animation finishes, rather than connecting //and disconnecting signals and slots frequently class ParallelAnimationWrapper : public QParallelAnimationGroup { @@ -116,9 +116,9 @@ void QDeclarativeTransitionPrivate::append_animation(QDeclarativeListProperty<QD void ParallelAnimationWrapper::updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState) { QParallelAnimationGroup::updateState(newState, oldState); - if (newState == Stopped && - ((direction() == QAbstractAnimation::Forward && currentLoopTime() == duration()) || - (direction() == QAbstractAnimation::Backward && currentLoopTime() == 0))) + if (newState == Stopped && (duration() == -1 + || (direction() == QAbstractAnimation::Forward && currentLoopTime() == duration()) + || (direction() == QAbstractAnimation::Backward && currentLoopTime() == 0))) { trans->complete(); } @@ -195,7 +195,11 @@ QString QDeclarativeTransition::fromState() const void QDeclarativeTransition::setFromState(const QString &f) { Q_D(QDeclarativeTransition); + if (f == d->fromState) + return; + d->fromState = f; + emit fromChanged(); } /*! @@ -213,7 +217,11 @@ bool QDeclarativeTransition::reversible() const void QDeclarativeTransition::setReversible(bool r) { Q_D(QDeclarativeTransition); + if (r == d->reversible) + return; + d->reversible = r; + emit reversibleChanged(); } QString QDeclarativeTransition::toState() const @@ -225,7 +233,11 @@ QString QDeclarativeTransition::toState() const void QDeclarativeTransition::setToState(const QString &t) { Q_D(QDeclarativeTransition); + if (t == d->toState) + return; + d->toState = t; + emit toChanged(); } /*! diff --git a/src/declarative/util/qdeclarativetransition_p.h b/src/declarative/util/qdeclarativetransition_p.h index 861111a..2f9e7b5 100644 --- a/src/declarative/util/qdeclarativetransition_p.h +++ b/src/declarative/util/qdeclarativetransition_p.h @@ -62,9 +62,9 @@ class Q_DECLARATIVE_EXPORT QDeclarativeTransition : public QObject Q_OBJECT Q_DECLARE_PRIVATE(QDeclarativeTransition) - Q_PROPERTY(QString from READ fromState WRITE setFromState) - Q_PROPERTY(QString to READ toState WRITE setToState) - Q_PROPERTY(bool reversible READ reversible WRITE setReversible) + Q_PROPERTY(QString from READ fromState WRITE setFromState NOTIFY fromChanged) + Q_PROPERTY(QString to READ toState WRITE setToState NOTIFY toChanged) + Q_PROPERTY(bool reversible READ reversible WRITE setReversible NOTIFY reversibleChanged) Q_PROPERTY(QDeclarativeListProperty<QDeclarativeAbstractAnimation> animations READ animations) Q_CLASSINFO("DefaultProperty", "animations") Q_CLASSINFO("DeferredPropertyNames", "animations") @@ -90,6 +90,11 @@ public: void setReversed(bool r); void stop(); + +Q_SIGNALS: + void fromChanged(); + void toChanged(); + void reversibleChanged(); }; QT_END_NAMESPACE diff --git a/src/declarative/util/qdeclarativeutilmodule.cpp b/src/declarative/util/qdeclarativeutilmodule.cpp index 4d4678a..7f2f64a 100644 --- a/src/declarative/util/qdeclarativeutilmodule.cpp +++ b/src/declarative/util/qdeclarativeutilmodule.cpp @@ -40,13 +40,12 @@ ****************************************************************************/ #include "qdeclarativeutilmodule_p.h" -#include "qfxperf_p_p.h" #include "qdeclarativeanimation_p.h" #include "qdeclarativeanimation_p_p.h" #include "qdeclarativebehavior_p.h" #include "qdeclarativebind_p.h" #include "qdeclarativeconnections_p.h" -#include "qdeclarativeeasefollow_p.h" +#include "qdeclarativesmoothedanimation_p.h" #include "qdeclarativefontloader_p.h" #include "qdeclarativelistaccessor_p.h" #include "qdeclarativelistmodel_p.h" @@ -71,7 +70,38 @@ #ifndef QT_NO_XMLPATTERNS #include "qdeclarativexmllistmodel_p.h" #endif -#include "qperformancelog_p_p.h" + +template<typename T> +int qmlRegisterTypeEnums(const char *qmlName) +{ + QByteArray name(T::staticMetaObject.className()); + + QByteArray pointerName(name + '*'); + QByteArray listName("QDeclarativeListProperty<" + name + ">"); + + QDeclarativePrivate::RegisterType type = { + 0, + + qRegisterMetaType<T *>(pointerName.constData()), + qRegisterMetaType<QDeclarativeListProperty<T> >(listName.constData()), + 0, 0, + + "Qt", 4, 6, qmlName, &T::staticMetaObject, + + QDeclarativePrivate::attachedPropertiesFunc<T>(), + QDeclarativePrivate::attachedPropertiesMetaObject<T>(), + + QDeclarativePrivate::StaticCastSelector<T,QDeclarativeParserStatus>::cast(), + QDeclarativePrivate::StaticCastSelector<T,QDeclarativePropertyValueSource>::cast(), + QDeclarativePrivate::StaticCastSelector<T,QDeclarativePropertyValueInterceptor>::cast(), + + 0, 0, + + 0 + }; + + return QDeclarativePrivate::registerType(type); +} void QDeclarativeUtilModule::defineModule() { @@ -81,13 +111,12 @@ void QDeclarativeUtilModule::defineModule() qmlRegisterType<QDeclarativeBind>("Qt",4,6,"Binding"); qmlRegisterType<QDeclarativeColorAnimation>("Qt",4,6,"ColorAnimation"); qmlRegisterType<QDeclarativeConnections>("Qt",4,6,"Connections"); - qmlRegisterType<QDeclarativeEaseFollow>("Qt",4,6,"EaseFollow"); + qmlRegisterType<QDeclarativeSmoothedAnimation>("Qt",4,6,"SmoothedAnimation"); qmlRegisterType<QDeclarativeFontLoader>("Qt",4,6,"FontLoader"); qmlRegisterType<QDeclarativeListElement>("Qt",4,6,"ListElement"); qmlRegisterType<QDeclarativeNumberAnimation>("Qt",4,6,"NumberAnimation"); qmlRegisterType<QDeclarativePackage>("Qt",4,6,"Package"); qmlRegisterType<QDeclarativeParallelAnimation>("Qt",4,6,"ParallelAnimation"); - qmlRegisterType<QDeclarativeParentAction>("Qt",4,6,"ParentAction"); qmlRegisterType<QDeclarativeParentAnimation>("Qt",4,6,"ParentAnimation"); qmlRegisterType<QDeclarativeParentChange>("Qt",4,6,"ParentChange"); qmlRegisterType<QDeclarativePauseAnimation>("Qt",4,6,"PauseAnimation"); @@ -110,8 +139,10 @@ void QDeclarativeUtilModule::defineModule() #endif qmlRegisterType<QDeclarativeAnchors>(); - qmlRegisterType<QDeclarativeAbstractAnimation>(); qmlRegisterType<QDeclarativeStateOperation>(); + qmlRegisterType<QDeclarativeAnchorSet>(); + + qmlRegisterTypeEnums<QDeclarativeAbstractAnimation>("Animation"); qmlRegisterCustomType<QDeclarativeListModel>("Qt", 4,6, "ListModel", "QDeclarativeListModel", new QDeclarativeListModelParser); diff --git a/src/declarative/util/qdeclarativeview.cpp b/src/declarative/util/qdeclarativeview.cpp index 59a062a..22a7873 100644 --- a/src/declarative/util/qdeclarativeview.cpp +++ b/src/declarative/util/qdeclarativeview.cpp @@ -41,9 +41,6 @@ #include "qdeclarativeview.h" -#include "qperformancelog_p_p.h" -#include "qfxperf_p_p.h" - #include <qdeclarative.h> #include <qdeclarativeitem.h> #include <qdeclarativeengine.h> @@ -132,6 +129,7 @@ class QDeclarativeViewPrivate public: QDeclarativeViewPrivate(QDeclarativeView *view) : q(view), root(0), component(0), resizeMode(QDeclarativeView::SizeViewToRootObject) {} + ~QDeclarativeViewPrivate() { delete root; } void execute(); @@ -159,6 +157,7 @@ void QDeclarativeViewPrivate::execute() { delete root; delete component; + initialSize = QSize(); component = new QDeclarativeComponent(&engine, source, q); if (!component->isLoading()) { @@ -251,13 +250,6 @@ QDeclarativeView::QDeclarativeView(const QUrl &source, QWidget *parent) void QDeclarativeViewPrivate::init() { -#ifdef Q_ENABLE_PERFORMANCE_LOG - { - QDeclarativePerfTimer<QDeclarativePerf::FontDatabase> perf; - QFontDatabase database; - } -#endif - q->setScene(&scene); q->setOptimizationFlags(QGraphicsView::DontSavePainterState); @@ -280,7 +272,7 @@ void QDeclarativeViewPrivate::init() */ QDeclarativeView::~QDeclarativeView() { - delete d->root; + delete d; } /*! \property QDeclarativeView::source @@ -298,7 +290,6 @@ QDeclarativeView::~QDeclarativeView() void QDeclarativeView::setSource(const QUrl& url) { d->source = url; - d->engine.setBaseUrl(url); d->execute(); } @@ -455,12 +446,10 @@ void QDeclarativeView::setRootObject(QObject *obj) if (QDeclarativeItem *item = qobject_cast<QDeclarativeItem *>(obj)) { d->scene.addItem(item); - QPerformanceLog::displayData(); - QPerformanceLog::clear(); d->root = item; d->qmlRoot = item; - connect(item, SIGNAL(widthChanged(qreal)), this, SLOT(sizeChanged())); - connect(item, SIGNAL(heightChanged(qreal)), this, SLOT(sizeChanged())); + connect(item, SIGNAL(widthChanged()), this, SLOT(sizeChanged())); + connect(item, SIGNAL(heightChanged()), this, SLOT(sizeChanged())); if (d->initialSize.height() <= 0 && d->qmlRoot->width() > 0) d->initialSize.setWidth(d->qmlRoot->width()); if (d->initialSize.height() <= 0 && d->qmlRoot->height() > 0) diff --git a/src/declarative/util/qdeclarativexmllistmodel.cpp b/src/declarative/util/qdeclarativexmllistmodel.cpp index 01ae2ed..efc614b 100644 --- a/src/declarative/util/qdeclarativexmllistmodel.cpp +++ b/src/declarative/util/qdeclarativexmllistmodel.cpp @@ -46,6 +46,7 @@ #include <QDebug> #include <QStringList> +#include <QQueue> #include <QApplication> #include <QThread> #include <QMutex> @@ -56,16 +57,19 @@ #include <QBuffer> #include <QNetworkRequest> #include <QNetworkReply> +#include <QTimer> #include <private/qobject_p.h> -QT_BEGIN_NAMESPACE - +Q_DECLARE_METATYPE(QDeclarativeXmlQueryResult) +QT_BEGIN_NAMESPACE typedef QPair<int, int> QDeclarativeXmlListRange; +#define XMLLISTMODEL_CLEAR_ID 0 + /*! \qmlclass XmlRole QDeclarativeXmlListModelRole \since 4.7 @@ -109,14 +113,27 @@ typedef QPair<int, int> QDeclarativeXmlListRange; \sa XmlListModel */ +struct XmlQueryJob +{ + int queryId; + QByteArray data; + QString query; + QString namespaces; + QStringList roleQueries; + QStringList keyRoleQueries; + QStringList keyRoleResultsCache; +}; + class QDeclarativeXmlQuery : public QThread { Q_OBJECT public: QDeclarativeXmlQuery(QObject *parent=0) - : QThread(parent), m_quit(false), m_restart(false), m_abort(false), m_queryId(0) { + : QThread(parent), m_quit(false), m_abortQueryId(-1), m_queryIds(XMLLISTMODEL_CLEAR_ID + 1) { + qRegisterMetaType<QDeclarativeXmlQueryResult>("QDeclarativeXmlQueryResult"); } + ~QDeclarativeXmlQuery() { m_mutex.lock(); m_quit = true; @@ -126,64 +143,66 @@ public: wait(); } - void abort() { - QMutexLocker locker(&m_mutex); - m_abort = true; - } - - int doQuery(QString query, QString namespaces, QByteArray data, QList<QDeclarativeXmlListModelRole *> *roleObjects) { + void abort(int id) { QMutexLocker locker(&m_mutex); - m_size = 0; - m_data = data; - m_query = QLatin1String("doc($src)") + query; - m_namespaces = namespaces; - m_roleObjects = roleObjects; - if (!isRunning()) { - m_abort = false; - start(); - } else { - m_restart = true; - m_condition.wakeOne(); - } - m_queryId++; - return m_queryId; + m_abortQueryId = id; } - QList<QList<QVariant> > modelData() { + int doQuery(QString query, QString namespaces, QByteArray data, QList<QDeclarativeXmlListModelRole *> *roleObjects, QStringList keyRoleResultsCache) { QMutexLocker locker(&m_mutex); - return m_modelData; - } - QList<QDeclarativeXmlListRange> insertedItemRanges() { - QMutexLocker locker(&m_mutex); - return m_insertedItemRanges; - } + XmlQueryJob job; + job.queryId = m_queryIds; + job.data = data; + job.query = QLatin1String("doc($src)") + query; + job.namespaces = namespaces; + job.keyRoleResultsCache = keyRoleResultsCache; + + for (int i=0; i<roleObjects->count(); i++) { + if (!roleObjects->at(i)->isValid()) { + job.roleQueries << ""; + continue; + } + job.roleQueries << roleObjects->at(i)->query(); + if (roleObjects->at(i)->isKey()) + job.keyRoleQueries << job.roleQueries.last(); + } + m_jobs.enqueue(job); + m_queryIds++; - QList<QDeclarativeXmlListRange> removedItemRanges() { - QMutexLocker locker(&m_mutex); - return m_removedItemRanges; + if (!isRunning()) + start(); + else + m_condition.wakeOne(); + return job.queryId; } Q_SIGNALS: - void queryCompleted(int queryId, int size); + void queryCompleted(const QDeclarativeXmlQueryResult &); protected: void run() { while (!m_quit) { m_mutex.lock(); - int queryId = m_queryId; doQueryJob(); doSubQueryJob(); - m_data.clear(); // no longer needed m_mutex.unlock(); m_mutex.lock(); - if (!m_abort) - emit queryCompleted(queryId, m_size); - if (!m_restart) + const XmlQueryJob &job = m_jobs.dequeue(); + if (m_abortQueryId != job.queryId) { + QDeclarativeXmlQueryResult r; + r.queryId = job.queryId; + r.size = m_size; + r.data = m_modelData; + r.inserted = m_insertedItemRanges; + r.removed = m_removedItemRanges; + r.keyRoleResultsCache = job.keyRoleResultsCache; + emit queryCompleted(r); + } + if (m_jobs.isEmpty()) m_condition.wait(&m_mutex); - m_abort = false; - m_restart = false; + m_abortQueryId = -1; m_mutex.unlock(); } } @@ -197,43 +216,40 @@ private: private: QMutex m_mutex; QWaitCondition m_condition; + QQueue<XmlQueryJob> m_jobs; bool m_quit; - bool m_restart; - bool m_abort; - QByteArray m_data; - QString m_query; - QString m_namespaces; + int m_abortQueryId; QString m_prefix; int m_size; - int m_queryId; - const QList<QDeclarativeXmlListModelRole *> *m_roleObjects; + int m_queryIds; QList<QList<QVariant> > m_modelData; - QStringList m_keysValues; QList<QDeclarativeXmlListRange> m_insertedItemRanges; QList<QDeclarativeXmlListRange> m_removedItemRanges; }; +Q_GLOBAL_STATIC(QDeclarativeXmlQuery, globalXmlQuery) + void QDeclarativeXmlQuery::doQueryJob() { + Q_ASSERT(!m_jobs.isEmpty()); + XmlQueryJob &job = m_jobs.head(); + QString r; QXmlQuery query; - QBuffer buffer(&m_data); + QBuffer buffer(&job.data); buffer.open(QIODevice::ReadOnly); query.bindVariable(QLatin1String("src"), &buffer); - query.setQuery(m_namespaces + m_query); + query.setQuery(job.namespaces + job.query); query.evaluateTo(&r); - //qDebug() << r; - //always need a single root element QByteArray xml = "<dummy:items xmlns:dummy=\"http://qtsotware.com/dummy\">\n" + r.toUtf8() + "</dummy:items>"; QBuffer b(&xml); b.open(QIODevice::ReadOnly); - //qDebug() << xml; - QString namespaces = QLatin1String("declare namespace dummy=\"http://qtsotware.com/dummy\";\n") + m_namespaces; + QString namespaces = QLatin1String("declare namespace dummy=\"http://qtsotware.com/dummy\";\n") + job.namespaces; QString prefix = QLatin1String("doc($inputDocument)/dummy:items") + - m_query.mid(m_query.lastIndexOf(QLatin1Char('/'))); + job.query.mid(job.query.lastIndexOf(QLatin1Char('/'))); //figure out how many items we are dealing with int count = -1; @@ -247,21 +263,19 @@ void QDeclarativeXmlQuery::doQueryJob() if (item.isAtomicValue()) count = item.toAtomicValue().toInt(); } - //qDebug() << count; + job.data = xml; m_prefix = namespaces + prefix + QLatin1Char('/'); - m_data = xml; + m_size = 0; if (count > 0) m_size = count; } void QDeclarativeXmlQuery::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(); - } + Q_ASSERT(!m_jobs.isEmpty()); + + const QStringList &keysQueries = m_jobs.head().keyRoleQueries; QString keysQuery; if (keysQueries.count() == 1) keysQuery = m_prefix + keysQueries[0]; @@ -291,54 +305,58 @@ void QDeclarativeXmlQuery::addIndexToRangeList(QList<QDeclarativeXmlListRange> * void QDeclarativeXmlQuery::doSubQueryJob() { + Q_ASSERT(!m_jobs.isEmpty()); + XmlQueryJob &job = m_jobs.head(); m_modelData.clear(); - QBuffer b(&m_data); + QBuffer b(&job.data); b.open(QIODevice::ReadOnly); QXmlQuery subquery; subquery.bindVariable(QLatin1String("inputDocument"), &b); - QStringList keysValues; - getValuesOfKeyRoles(&keysValues, &subquery); + QStringList keyRoleResults; + getValuesOfKeyRoles(&keyRoleResults, &subquery); // See if any values of key roles have been inserted or removed. + m_insertedItemRanges.clear(); m_removedItemRanges.clear(); - if (m_keysValues.isEmpty()) { + if (job.keyRoleResultsCache.isEmpty()) { m_insertedItemRanges << qMakePair(0, m_size); } else { - if (keysValues != m_keysValues) { + if (keyRoleResults != job.keyRoleResultsCache) { QStringList temp; - for (int i=0; i<m_keysValues.count(); i++) { - if (!keysValues.contains(m_keysValues[i])) + for (int i=0; i<job.keyRoleResultsCache.count(); i++) { + if (!keyRoleResults.contains(job.keyRoleResultsCache[i])) addIndexToRangeList(&m_removedItemRanges, i); else - temp << m_keysValues[i]; + temp << job.keyRoleResultsCache[i]; } - for (int i=0; i<keysValues.count(); i++) { - if (temp.count() == i || keysValues[i] != temp[i]) { - temp.insert(i, keysValues[i]); + for (int i=0; i<keyRoleResults.count(); i++) { + if (temp.count() == i || keyRoleResults[i] != temp[i]) { + temp.insert(i, keyRoleResults[i]); addIndexToRangeList(&m_insertedItemRanges, i); } } } } - m_keysValues = keysValues; + job.keyRoleResultsCache = keyRoleResults; + // 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) { - QDeclarativeXmlListModelRole *role = m_roleObjects->at(i); - if (!role->isValid()) { + const QStringList &queries = job.roleQueries; + for (int i = 0; i < queries.size(); ++i) { + if (queries[i].isEmpty()) { QList<QVariant> resultList; for (int j = 0; j < m_size; ++j) resultList << QVariant(); m_modelData << resultList; continue; } - subquery.setQuery(m_prefix + QLatin1String("(let $v := ") + role->query() + QLatin1String(" return if ($v) then ") + role->query() + QLatin1String(" else \"\")")); + subquery.setQuery(m_prefix + QLatin1String("(let $v := ") + queries[i] + QLatin1String(" return if ($v) then ") + queries[i] + QLatin1String(" else \"\")")); QXmlResultItems resultItems; subquery.evaluateTo(&resultItems); QXmlItem item(resultItems.next()); @@ -404,8 +422,8 @@ public: QNetworkReply *reply; QDeclarativeXmlListModel::Status status; qreal progress; - QDeclarativeXmlQuery qmlXmlQuery; int queryId; + QStringList keyRoleResultsCache; QList<QDeclarativeXmlListModelRole *> roleObjects; static void append_role(QDeclarativeListProperty<QDeclarativeXmlListModelRole> *list, QDeclarativeXmlListModelRole *role); static void clear_role(QDeclarativeListProperty<QDeclarativeXmlListModelRole> *list); @@ -489,9 +507,8 @@ void QDeclarativeXmlListModelPrivate::clear_role(QDeclarativeListProperty<QDecla QDeclarativeXmlListModel::QDeclarativeXmlListModel(QObject *parent) : QListModelInterface(*(new QDeclarativeXmlListModelPrivate), parent) { - Q_D(QDeclarativeXmlListModel); - connect(&d->qmlXmlQuery, SIGNAL(queryCompleted(int,int)), - this, SLOT(queryCompleted(int,int))); + connect(globalXmlQuery(), SIGNAL(queryCompleted(QDeclarativeXmlQueryResult)), + this, SLOT(queryCompleted(QDeclarativeXmlQueryResult))); } QDeclarativeXmlListModel::~QDeclarativeXmlListModel() @@ -519,7 +536,7 @@ QHash<int,QVariant> QDeclarativeXmlListModel::data(int index, const QList<int> & for (int i = 0; i < roles.size(); ++i) { int role = roles.at(i); int roleIndex = d->roles.indexOf(role); - rv.insert(role, roleIndex == -1 ? QVariant() : d->data.at(roleIndex).at(index)); + rv.insert(role, roleIndex == -1 ? QVariant() : d->data.value(roleIndex).value(index)); } return rv; } @@ -528,7 +545,7 @@ QVariant QDeclarativeXmlListModel::data(int index, int role) const { Q_D(const QDeclarativeXmlListModel); int roleIndex = d->roles.indexOf(role); - return (roleIndex == -1) ? QVariant() : d->data.at(roleIndex).at(index); + return (roleIndex == -1) ? QVariant() : d->data.value(roleIndex).value(index); } /*! @@ -573,7 +590,8 @@ void QDeclarativeXmlListModel::setSource(const QUrl &src) Q_D(QDeclarativeXmlListModel); if (d->src != src) { d->src = src; - reload(); + if (d->xml.isEmpty()) // src is only used if d->xml is not set + reload(); emit sourceChanged(); } } @@ -650,23 +668,13 @@ void QDeclarativeXmlListModel::setNamespaceDeclarations(const QString &declarati /*! \qmlproperty enum XmlListModel::status + Specifies the model loading status, which can be one of the following: - This property holds the status of data source loading. It can be one of: - \list - \o Null - no data source has been set - \o Ready - the data source has been loaded - \o Loading - the data source is currently being loaded - \o Error - an error occurred while loading the data source - \endlist - - Note that a change in the status property does not cause anything to happen - (although it reflects what has happened to the XmlListModel internally). If you wish - to react to the change in status you need to do it yourself, for example in one - of the following ways: \list - \o Create a state, so that a state change occurs, e.g. State{name: 'loaded'; when: xmlListModel.status = XmlListModel.Ready;} - \o Do something inside the onStatusChanged signal handler, e.g. XmlListModel{id: xmlListModel; onStatusChanged: if(xmlListModel.status == XmlListModel.Ready) console.log('Loaded');} - \o Bind to the status variable somewhere, e.g. Text{text: if(xmlListModel.status!=XmlListModel.Ready){'Not Loaded';}else{'Loaded';}} + \o Null - No XML data has been set for this model. + \o Ready - The XML data has been loaded into the model. + \o Loading - The model is in the process of reading and loading XML data. + \o Error - An error occurred while the model was loading. \endlist \sa progress @@ -681,10 +689,17 @@ QDeclarativeXmlListModel::Status QDeclarativeXmlListModel::status() const /*! \qmlproperty real XmlListModel::progress - This property holds the progress of data source loading, from 0.0 (nothing loaded) - to 1.0 (finished). + This indicates the current progress of the downloading of the XML data + source. This value ranges from 0.0 (no data downloaded) to + 1.0 (all data downloaded). If the XML data is not from a remote source, + the progress becomes 1.0 as soon as the data is read. - \sa status + Note that when the progress is 1.0, the XML data has been downloaded, but + it is yet to be loaded into the model at this point. Use the status + property to find out when the XML data has been read and loaded into + the model. + + \sa status, source */ qreal QDeclarativeXmlListModel::progress() const { @@ -715,6 +730,8 @@ void QDeclarativeXmlListModel::componentComplete() Otherwise, items are only added if the model does not already contain items with matching key role values. + + \sa XmlRole::isKey */ void QDeclarativeXmlListModel::reload() { @@ -723,30 +740,11 @@ void QDeclarativeXmlListModel::reload() if (!d->isComponentComplete) return; - d->qmlXmlQuery.abort(); + globalXmlQuery()->abort(d->queryId); d->queryId = -1; - int count = d->size; - if (count < 0) - d->size = 0; - bool hasKeys = false; - for (int i=0; i<d->roleObjects.count(); i++) { - if (d->roleObjects[i]->isKey()) { - hasKeys = true; - break; - } - } - if (!hasKeys) { - d->data.clear(); + if (d->size < 0) d->size = 0; - if (count > 0) { - emit itemsRemoved(0, count); - emit countChanged(); - } - } - - if (d->src.isEmpty() && d->xml.isEmpty()) - return; if (d->reply) { d->reply->abort(); @@ -755,11 +753,21 @@ void QDeclarativeXmlListModel::reload() } if (!d->xml.isEmpty()) { - d->queryId = d->qmlXmlQuery.doQuery(d->query, d->namespaces, d->xml.toUtf8(), &d->roleObjects); + d->queryId = globalXmlQuery()->doQuery(d->query, d->namespaces, d->xml.toUtf8(), &d->roleObjects, d->keyRoleResultsCache); + d->progress = 1.0; + d->status = Loading; + emit progressChanged(d->progress); + emit statusChanged(d->status); + return; + } + + if (d->src.isEmpty()) { + d->queryId = XMLLISTMODEL_CLEAR_ID; d->progress = 1.0; - d->status = Ready; + d->status = Loading; emit progressChanged(d->progress); emit statusChanged(d->status); + QTimer::singleShot(0, this, SLOT(dataCleared())); return; } @@ -798,18 +806,33 @@ void QDeclarativeXmlListModel::requestFinished() disconnect(d->reply, 0, this, 0); d->reply->deleteLater(); d->reply = 0; + + int count = this->count(); + d->data.clear(); + d->size = 0; + if (count > 0) { + emit itemsRemoved(0, count); + emit countChanged(); + } + d->status = Error; + d->queryId = -1; + emit statusChanged(d->status); } else { - d->status = Ready; QByteArray data = d->reply->readAll(); - d->queryId = d->qmlXmlQuery.doQuery(d->query, d->namespaces, data, &d->roleObjects); + if (data.isEmpty()) { + d->queryId = XMLLISTMODEL_CLEAR_ID; + QTimer::singleShot(0, this, SLOT(dataCleared())); + } else { + d->queryId = globalXmlQuery()->doQuery(d->query, d->namespaces, data, &d->roleObjects, d->keyRoleResultsCache); + } disconnect(d->reply, 0, this, 0); d->reply->deleteLater(); d->reply = 0; + + d->progress = 1.0; + emit progressChanged(d->progress); } - d->progress = 1.0; - emit progressChanged(d->progress); - emit statusChanged(d->status); } void QDeclarativeXmlListModel::requestProgress(qint64 received, qint64 total) @@ -821,25 +844,58 @@ void QDeclarativeXmlListModel::requestProgress(qint64 received, qint64 total) } } -void QDeclarativeXmlListModel::queryCompleted(int id, int size) +void QDeclarativeXmlListModel::dataCleared() +{ + Q_D(QDeclarativeXmlListModel); + QDeclarativeXmlQueryResult r; + r.queryId = XMLLISTMODEL_CLEAR_ID; + r.size = 0; + r.removed << qMakePair(0, count()); + r.keyRoleResultsCache = d->keyRoleResultsCache; + queryCompleted(r); +} + +void QDeclarativeXmlListModel::queryCompleted(const QDeclarativeXmlQueryResult &result) { Q_D(QDeclarativeXmlListModel); - if (id != d->queryId) + if (result.queryId != d->queryId) return; - bool sizeChanged = size != d->size; - d->size = size; - d->data = d->qmlXmlQuery.modelData(); - QList<QDeclarativeXmlListRange> removed = d->qmlXmlQuery.removedItemRanges(); - QList<QDeclarativeXmlListRange> inserted = d->qmlXmlQuery.insertedItemRanges(); + int origCount = d->size; + bool sizeChanged = result.size != d->size; + + d->size = result.size; + d->data = result.data; + d->keyRoleResultsCache = result.keyRoleResultsCache; + d->status = Ready; + d->queryId = -1; + + bool hasKeys = false; + for (int i=0; i<d->roleObjects.count(); i++) { + if (d->roleObjects[i]->isKey()) { + hasKeys = true; + break; + } + } + if (!hasKeys) { + if (!(origCount == 0 && d->size == 0)) { + emit itemsRemoved(0, origCount); + emit itemsInserted(0, d->size); + emit countChanged(); + } + + } else { + + for (int i=0; i<result.removed.count(); i++) + emit itemsRemoved(result.removed[i].first, result.removed[i].second); + for (int i=0; i<result.inserted.count(); i++) + emit itemsInserted(result.inserted[i].first, result.inserted[i].second); - for (int i=0; i<removed.count(); i++) - emit itemsRemoved(removed[i].first, removed[i].second); - for (int i=0; i<inserted.count(); i++) - emit itemsInserted(inserted[i].first, inserted[i].second); + if (sizeChanged) + emit countChanged(); + } - if (sizeChanged) - emit countChanged(); + emit statusChanged(d->status); } QT_END_NAMESPACE diff --git a/src/declarative/util/qdeclarativexmllistmodel_p.h b/src/declarative/util/qdeclarativexmllistmodel_p.h index 23ff7ce..7b85476 100644 --- a/src/declarative/util/qdeclarativexmllistmodel_p.h +++ b/src/declarative/util/qdeclarativexmllistmodel_p.h @@ -46,6 +46,7 @@ #include <qdeclarativeinfo.h> #include <QtCore/qurl.h> +#include <QtCore/qstringlist.h> #include <private/qlistmodelinterface_p.h> @@ -56,10 +57,18 @@ QT_BEGIN_NAMESPACE QT_MODULE(Declarative) class QDeclarativeContext; - class QDeclarativeXmlListModelRole; - class QDeclarativeXmlListModelPrivate; + +struct QDeclarativeXmlQueryResult { + int queryId; + int size; + QList<QList<QVariant> > data; + QList<QPair<int, int> > inserted; + QList<QPair<int, int> > removed; + QStringList keyRoleResultsCache; +}; + class Q_DECLARATIVE_EXPORT QDeclarativeXmlListModel : public QListModelInterface, public QDeclarativeParserStatus { Q_OBJECT @@ -108,7 +117,7 @@ public: virtual void componentComplete(); Q_SIGNALS: - void statusChanged(Status); + void statusChanged(QDeclarativeXmlListModel::Status); void progressChanged(qreal progress); void countChanged(); void sourceChanged(); @@ -126,7 +135,8 @@ public Q_SLOTS: private Q_SLOTS: void requestFinished(); void requestProgress(qint64,qint64); - void queryCompleted(int,int); + void dataCleared(); + void queryCompleted(const QDeclarativeXmlQueryResult &); private: Q_DECLARE_PRIVATE(QDeclarativeXmlListModel) diff --git a/src/declarative/util/qfxperf.cpp b/src/declarative/util/qfxperf.cpp deleted file mode 100644 index 5611c49..0000000 --- a/src/declarative/util/qfxperf.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (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 Technology Preview License Agreement accompanying -** this package. -** -** 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.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qfxperf_p_p.h" - -QT_BEGIN_NAMESPACE - -Q_DEFINE_PERFORMANCE_LOG(QDeclarativePerf, "QDeclarativeGraphics") { - Q_DEFINE_PERFORMANCE_METRIC(QDeclarativeParsing, "Compilation: QML Parsing") - Q_DEFINE_PERFORMANCE_METRIC(Compilation, " QML Compilation") - Q_DEFINE_PERFORMANCE_METRIC(VMEExecution, "Execution: QML VME Execution") - Q_DEFINE_PERFORMANCE_METRIC(BindInit, "BindValue Initialization") - 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, "QDeclarativeBinding::update") - Q_DEFINE_PERFORMANCE_METRIC(PixmapLoad, "Pixmap loading") - Q_DEFINE_PERFORMANCE_METRIC(FontDatabase, "Font database creation") - Q_DEFINE_PERFORMANCE_METRIC(QDeclarativePathViewPathCache, "FX Items: QDeclarativePathView: Path cache") - Q_DEFINE_PERFORMANCE_METRIC(CreateParticle, " QDeclarativeParticles: Particle creation") - Q_DEFINE_PERFORMANCE_METRIC(ItemComponentComplete, " QDeclarativeItem::componentComplete") - Q_DEFINE_PERFORMANCE_METRIC(ImageComponentComplete, " QDeclarativeImage::componentComplete") - Q_DEFINE_PERFORMANCE_METRIC(BaseLayoutComponentComplete, " QDeclarativeBasePositioner::componentComplete") - Q_DEFINE_PERFORMANCE_METRIC(TextComponentComplete, " QDeclarativeText::componentComplete") - Q_DEFINE_PERFORMANCE_METRIC(QDeclarativeText_setText, " QDeclarativeText::setText") - Q_DEFINE_PERFORMANCE_METRIC(AddScript, "QDeclarativeScript::addScriptToEngine") -} - -QT_END_NAMESPACE diff --git a/src/declarative/util/qfxperf_p_p.h b/src/declarative/util/qfxperf_p_p.h deleted file mode 100644 index 8b65821..0000000 --- a/src/declarative/util/qfxperf_p_p.h +++ /dev/null @@ -1,90 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (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 Technology Preview License Agreement accompanying -** this package. -** -** 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.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -#ifndef QFXPERF_H -#define QFXPERF_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "qperformancelog_p_p.h" - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -QT_MODULE(Declarative) - -Q_DECLARE_PERFORMANCE_LOG(QDeclarativePerf) { - Q_DECLARE_PERFORMANCE_METRIC(QDeclarativeParsing) - - Q_DECLARE_PERFORMANCE_METRIC(Compilation) - Q_DECLARE_PERFORMANCE_METRIC(VMEExecution) - - Q_DECLARE_PERFORMANCE_METRIC(BindInit) - 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(FontDatabase) - Q_DECLARE_PERFORMANCE_METRIC(QDeclarativePathViewPathCache) - Q_DECLARE_PERFORMANCE_METRIC(CreateParticle) - Q_DECLARE_PERFORMANCE_METRIC(ItemComponentComplete) - Q_DECLARE_PERFORMANCE_METRIC(ImageComponentComplete) - Q_DECLARE_PERFORMANCE_METRIC(BaseLayoutComponentComplete) - Q_DECLARE_PERFORMANCE_METRIC(TextComponentComplete) - Q_DECLARE_PERFORMANCE_METRIC(QDeclarativeText_setText) - Q_DECLARE_PERFORMANCE_METRIC(AddScript) -} - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif // QFXPERF_H diff --git a/src/declarative/util/qperformancelog.cpp b/src/declarative/util/qperformancelog.cpp deleted file mode 100644 index 83cc919..0000000 --- a/src/declarative/util/qperformancelog.cpp +++ /dev/null @@ -1,181 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (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 Technology Preview License Agreement accompanying -** this package. -** -** 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.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qperformancelog_p_p.h" - -#include <QHash> -#include <QDebug> - -QT_BEGIN_NAMESPACE - -#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 - -QT_END_NAMESPACE diff --git a/src/declarative/util/qperformancelog_p_p.h b/src/declarative/util/qperformancelog_p_p.h deleted file mode 100644 index a212f28..0000000 --- a/src/declarative/util/qperformancelog_p_p.h +++ /dev/null @@ -1,141 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (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 Technology Preview License Agreement accompanying -** this package. -** -** 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.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QPERFORMANCELOG_H -#define QPERFORMANCELOG_H - -#include <QtCore/qdatetime.h> - -QT_BEGIN_NAMESPACE - -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) -#define Q_DECLARE_PERFORMANCE_LOG(name) namespace name -#define Q_DEFINE_PERFORMANCE_LOG(name, desc) namespace name -#define Q_DEFINE_PERFORMANCE_METRIC(name, desc) - -#endif // Q_ENABLE_PERFORMANCE_LOG - -QT_END_NAMESPACE - -#endif // QPERFORMANCELOG_H diff --git a/src/declarative/util/util.pri b/src/declarative/util/util.pri index f455870..4163596 100644 --- a/src/declarative/util/util.pri +++ b/src/declarative/util/util.pri @@ -3,14 +3,12 @@ INCLUDEPATH += $$PWD SOURCES += \ $$PWD/qdeclarativeutilmodule.cpp\ $$PWD/qdeclarativeview.cpp \ - $$PWD/qfxperf.cpp \ - $$PWD/qperformancelog.cpp \ $$PWD/qdeclarativeconnections.cpp \ $$PWD/qdeclarativepackage.cpp \ $$PWD/qdeclarativeanimation.cpp \ $$PWD/qdeclarativesystempalette.cpp \ $$PWD/qdeclarativespringfollow.cpp \ - $$PWD/qdeclarativeeasefollow.cpp \ + $$PWD/qdeclarativesmoothedanimation.cpp \ $$PWD/qdeclarativestate.cpp\ $$PWD/qdeclarativetransitionmanager.cpp \ $$PWD/qdeclarativestateoperations.cpp \ @@ -33,15 +31,14 @@ SOURCES += \ HEADERS += \ $$PWD/qdeclarativeutilmodule_p.h\ $$PWD/qdeclarativeview.h \ - $$PWD/qfxperf_p_p.h \ - $$PWD/qperformancelog_p_p.h \ $$PWD/qdeclarativeconnections_p.h \ $$PWD/qdeclarativepackage_p.h \ $$PWD/qdeclarativeanimation_p.h \ $$PWD/qdeclarativeanimation_p_p.h \ $$PWD/qdeclarativesystempalette_p.h \ $$PWD/qdeclarativespringfollow_p.h \ - $$PWD/qdeclarativeeasefollow_p.h \ + $$PWD/qdeclarativesmoothedanimation_p.h \ + $$PWD/qdeclarativesmoothedanimation_p_p.h \ $$PWD/qdeclarativestate_p.h\ $$PWD/qdeclarativestateoperations_p.h \ $$PWD/qdeclarativepropertychanges_p.h \ |