1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the QtDeclarative module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file.  Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "private/qdeclarativestate_p_p.h"
43 #include "private/qdeclarativestate_p.h"
44 
45 #include "private/qdeclarativetransition_p.h"
46 #include "private/qdeclarativestategroup_p.h"
47 #include "private/qdeclarativestateoperations_p.h"
48 #include "private/qdeclarativeanimation_p.h"
49 #include "private/qdeclarativeanimation_p_p.h"
50 
51 #include <qdeclarativebinding_p.h>
52 #include <qdeclarativeglobal_p.h>
53 
54 #include <QtCore/qdebug.h>
55 
56 QT_BEGIN_NAMESPACE
57 
58 DEFINE_BOOL_CONFIG_OPTION(stateChangeDebug, STATECHANGE_DEBUG);
59 
QDeclarativeAction()60 QDeclarativeAction::QDeclarativeAction()
61 : restore(true), actionDone(false), reverseEvent(false), deletableToBinding(false), fromBinding(0), event(0),
62   specifiedObject(0)
63 {
64 }
65 
QDeclarativeAction(QObject * target,const QString & propertyName,const QVariant & value)66 QDeclarativeAction::QDeclarativeAction(QObject *target, const QString &propertyName,
67                const QVariant &value)
68 : restore(true), actionDone(false), reverseEvent(false), deletableToBinding(false),
69   property(target, propertyName, qmlEngine(target)), toValue(value),
70   fromBinding(0), event(0),
71   specifiedObject(target), specifiedProperty(propertyName)
72 {
73     if (property.isValid())
74         fromValue = property.read();
75 }
76 
QDeclarativeAction(QObject * target,const QString & propertyName,QDeclarativeContext * context,const QVariant & value)77 QDeclarativeAction::QDeclarativeAction(QObject *target, const QString &propertyName,
78                QDeclarativeContext *context, const QVariant &value)
79 : restore(true), actionDone(false), reverseEvent(false), deletableToBinding(false),
80   property(target, propertyName, context), toValue(value),
81   fromBinding(0), event(0),
82   specifiedObject(target), specifiedProperty(propertyName)
83 {
84     if (property.isValid())
85         fromValue = property.read();
86 }
87 
88 
~QDeclarativeActionEvent()89 QDeclarativeActionEvent::~QDeclarativeActionEvent()
90 {
91 }
92 
typeName() const93 QString QDeclarativeActionEvent::typeName() const
94 {
95     return QString();
96 }
97 
execute(Reason)98 void QDeclarativeActionEvent::execute(Reason)
99 {
100 }
101 
isReversable()102 bool QDeclarativeActionEvent::isReversable()
103 {
104     return false;
105 }
106 
reverse(Reason)107 void QDeclarativeActionEvent::reverse(Reason)
108 {
109 }
110 
changesBindings()111 bool QDeclarativeActionEvent::changesBindings()
112 {
113     return false;
114 }
115 
clearBindings()116 void QDeclarativeActionEvent::clearBindings()
117 {
118 }
119 
override(QDeclarativeActionEvent * other)120 bool QDeclarativeActionEvent::override(QDeclarativeActionEvent *other)
121 {
122     Q_UNUSED(other);
123     return false;
124 }
125 
QDeclarativeStateOperation(QObjectPrivate & dd,QObject * parent)126 QDeclarativeStateOperation::QDeclarativeStateOperation(QObjectPrivate &dd, QObject *parent)
127     : QObject(dd, parent)
128 {
129 }
130 
131 /*!
132     \qmlclass State QDeclarativeState
133     \ingroup qml-state-elements
134     \since 4.7
135     \brief The State element defines configurations of objects and properties.
136 
137     A \e state is a set of batched changes from the default configuration.
138 
139     All items have a default state that defines the default configuration of objects
140     and property values. New states can be defined by adding State items to the \l {Item::states}{states} property to
141     allow items to switch between different configurations. These configurations
142     can, for example, be used to apply different sets of property values or execute
143     different scripts.
144 
145     The following example displays a single \l Rectangle. In the default state, the rectangle
146     is colored black. In the "clicked" state, a PropertyChanges element changes the
147     rectangle's color to red. Clicking within the MouseArea toggles the rectangle's state
148     between the default state and the "clicked" state, thus toggling the color of the
149     rectangle between black and red.
150 
151     \snippet doc/src/snippets/declarative/state.qml 0
152 
153     Notice the default state is referred to using an empty string ("").
154 
155     States are commonly used together with \l{QML Animation and Transitions}{Transitions} to provide
156     animations when state changes occur.
157 
158     \note Setting the state of an object from within another state of the same object is
159     not allowed.
160 
161     \sa {declarative/animation/states}{states example}, {qmlstates}{States},
162     {QML Animation and Transitions}{Transitions}, QtDeclarative
163 */
QDeclarativeState(QObject * parent)164 QDeclarativeState::QDeclarativeState(QObject *parent)
165 : QObject(*(new QDeclarativeStatePrivate), parent)
166 {
167     Q_D(QDeclarativeState);
168     d->transitionManager.setState(this);
169 }
170 
~QDeclarativeState()171 QDeclarativeState::~QDeclarativeState()
172 {
173     Q_D(QDeclarativeState);
174     if (d->group)
175         d->group->removeState(this);
176 
177     /*
178       destroying an active state does not return us to the
179       base state, so we need to clean up our revert list to
180       prevent leaks. In the future we may want to redconsider
181       this overall architecture.
182     */
183     for (int i = 0; i < d->revertList.count(); ++i) {
184         if (d->revertList.at(i).binding()) {
185             d->revertList.at(i).binding()->destroy();
186         }
187     }
188 }
189 
190 /*!
191     \qmlproperty string State::name
192     This property holds the name of the state.
193 
194     Each state should have a unique name within its item.
195 */
name() const196 QString QDeclarativeState::name() const
197 {
198     Q_D(const QDeclarativeState);
199     return d->name;
200 }
201 
setName(const QString & n)202 void QDeclarativeState::setName(const QString &n)
203 {
204     Q_D(QDeclarativeState);
205     d->name = n;
206     d->named = true;
207 }
208 
isNamed() const209 bool QDeclarativeState::isNamed() const
210 {
211     Q_D(const QDeclarativeState);
212     return d->named;
213 }
214 
isWhenKnown() const215 bool QDeclarativeState::isWhenKnown() const
216 {
217     Q_D(const QDeclarativeState);
218     return d->when != 0;
219 }
220 
221 /*!
222     \qmlproperty bool State::when
223     This property holds when the state should be applied.
224 
225     This should be set to an expression that evaluates to \c true when you want the state to
226     be applied. For example, the following \l Rectangle changes in and out of the "hidden"
227     state when the \l MouseArea is pressed:
228 
229     \snippet doc/src/snippets/declarative/state-when.qml 0
230 
231     If multiple states in a group have \c when clauses that evaluate to \c true
232     at the same time, the first matching state will be applied. For example, in
233     the following snippet \c state1 will always be selected rather than
234     \c state2 when sharedCondition becomes \c true.
235     \qml
236     Item {
237         states: [
238             State { name: "state1"; when: sharedCondition },
239             State { name: "state2"; when: sharedCondition }
240         ]
241         // ...
242     }
243     \endqml
244 */
when() const245 QDeclarativeBinding *QDeclarativeState::when() const
246 {
247     Q_D(const QDeclarativeState);
248     return d->when;
249 }
250 
setWhen(QDeclarativeBinding * when)251 void QDeclarativeState::setWhen(QDeclarativeBinding *when)
252 {
253     Q_D(QDeclarativeState);
254     d->when = when;
255     if (d->group)
256         d->group->updateAutoState();
257 }
258 
259 /*!
260     \qmlproperty string State::extend
261     This property holds the state that this state extends.
262 
263     When a state extends another state, it inherits all the changes of that state.
264 
265     The state being extended is treated as the base state in regards to
266     the changes specified by the extending state.
267 */
extends() const268 QString QDeclarativeState::extends() const
269 {
270     Q_D(const QDeclarativeState);
271     return d->extends;
272 }
273 
setExtends(const QString & extends)274 void QDeclarativeState::setExtends(const QString &extends)
275 {
276     Q_D(QDeclarativeState);
277     d->extends = extends;
278 }
279 
280 /*!
281     \qmlproperty list<Change> State::changes
282     This property holds the changes to apply for this state
283     \default
284 
285     By default these changes are applied against the default state. If the state
286     extends another state, then the changes are applied against the state being
287     extended.
288 */
changes()289 QDeclarativeListProperty<QDeclarativeStateOperation> QDeclarativeState::changes()
290 {
291     Q_D(QDeclarativeState);
292     return QDeclarativeListProperty<QDeclarativeStateOperation>(this, &d->operations, QDeclarativeStatePrivate::operations_append,
293                                               QDeclarativeStatePrivate::operations_count, QDeclarativeStatePrivate::operations_at,
294                                               QDeclarativeStatePrivate::operations_clear);
295 }
296 
operationCount() const297 int QDeclarativeState::operationCount() const
298 {
299     Q_D(const QDeclarativeState);
300     return d->operations.count();
301 }
302 
operationAt(int index) const303 QDeclarativeStateOperation *QDeclarativeState::operationAt(int index) const
304 {
305     Q_D(const QDeclarativeState);
306     return d->operations.at(index);
307 }
308 
operator <<(QDeclarativeStateOperation * op)309 QDeclarativeState &QDeclarativeState::operator<<(QDeclarativeStateOperation *op)
310 {
311     Q_D(QDeclarativeState);
312     d->operations.append(QDeclarativeStatePrivate::OperationGuard(op, &d->operations));
313     return *this;
314 }
315 
complete()316 void QDeclarativeStatePrivate::complete()
317 {
318     Q_Q(QDeclarativeState);
319 
320     for (int ii = 0; ii < reverting.count(); ++ii) {
321         for (int jj = 0; jj < revertList.count(); ++jj) {
322             if (revertList.at(jj).property() == reverting.at(ii)) {
323                 revertList.removeAt(jj);
324                 break;
325             }
326         }
327     }
328     reverting.clear();
329 
330     emit q->completed();
331 }
332 
333 // Generate a list of actions for this state.  This includes coelescing state
334 // actions that this state "extends"
335 QDeclarativeStateOperation::ActionList
generateActionList(QDeclarativeStateGroup * group) const336 QDeclarativeStatePrivate::generateActionList(QDeclarativeStateGroup *group) const
337 {
338     QDeclarativeStateOperation::ActionList applyList;
339     if (inState)
340         return applyList;
341 
342     // Prevent "extends" recursion
343     inState = true;
344 
345     if (!extends.isEmpty()) {
346         QList<QDeclarativeState *> states = group->states();
347         for (int ii = 0; ii < states.count(); ++ii)
348             if (states.at(ii)->name() == extends) {
349                 qmlExecuteDeferred(states.at(ii));
350                 applyList = static_cast<QDeclarativeStatePrivate*>(states.at(ii)->d_func())->generateActionList(group);
351             }
352     }
353 
354     foreach(QDeclarativeStateOperation *op, operations)
355         applyList << op->actions();
356 
357     inState = false;
358     return applyList;
359 }
360 
stateGroup() const361 QDeclarativeStateGroup *QDeclarativeState::stateGroup() const
362 {
363     Q_D(const QDeclarativeState);
364     return d->group;
365 }
366 
setStateGroup(QDeclarativeStateGroup * group)367 void QDeclarativeState::setStateGroup(QDeclarativeStateGroup *group)
368 {
369     Q_D(QDeclarativeState);
370     d->group = group;
371 }
372 
cancel()373 void QDeclarativeState::cancel()
374 {
375     Q_D(QDeclarativeState);
376     d->transitionManager.cancel();
377 }
378 
deleteFromBinding()379 void QDeclarativeAction::deleteFromBinding()
380 {
381     if (fromBinding) {
382         QDeclarativePropertyPrivate::setBinding(property, 0);
383         fromBinding->destroy();
384         fromBinding = 0;
385     }
386 }
387 
containsPropertyInRevertList(QObject * target,const QString & name) const388 bool QDeclarativeState::containsPropertyInRevertList(QObject *target, const QString &name) const
389 {
390     Q_D(const QDeclarativeState);
391 
392     if (isStateActive()) {
393         QListIterator<QDeclarativeSimpleAction> revertListIterator(d->revertList);
394 
395         while (revertListIterator.hasNext()) {
396             const QDeclarativeSimpleAction &simpleAction = revertListIterator.next();
397             if (simpleAction.specifiedObject() == target && simpleAction.specifiedProperty() == name)
398                 return true;
399         }
400     }
401 
402     return false;
403 }
404 
changeValueInRevertList(QObject * target,const QString & name,const QVariant & revertValue)405 bool QDeclarativeState::changeValueInRevertList(QObject *target, const QString &name, const QVariant &revertValue)
406 {
407     Q_D(QDeclarativeState);
408 
409     if (isStateActive()) {
410         QMutableListIterator<QDeclarativeSimpleAction> revertListIterator(d->revertList);
411 
412         while (revertListIterator.hasNext()) {
413             QDeclarativeSimpleAction &simpleAction = revertListIterator.next();
414             if (simpleAction.specifiedObject() == target && simpleAction.specifiedProperty() == name) {
415                     simpleAction.setValue(revertValue);
416                     return true;
417             }
418         }
419     }
420 
421     return false;
422 }
423 
changeBindingInRevertList(QObject * target,const QString & name,QDeclarativeAbstractBinding * binding)424 bool QDeclarativeState::changeBindingInRevertList(QObject *target, const QString &name, QDeclarativeAbstractBinding *binding)
425 {
426     Q_D(QDeclarativeState);
427 
428     if (isStateActive()) {
429         QMutableListIterator<QDeclarativeSimpleAction> revertListIterator(d->revertList);
430 
431         while (revertListIterator.hasNext()) {
432             QDeclarativeSimpleAction &simpleAction = revertListIterator.next();
433             if (simpleAction.specifiedObject() == target && simpleAction.specifiedProperty() == name) {
434                 if (simpleAction.binding())
435                     simpleAction.binding()->destroy();
436 
437                 simpleAction.setBinding(binding);
438                 return true;
439             }
440         }
441     }
442 
443     return false;
444 }
445 
removeEntryFromRevertList(QObject * target,const QString & name)446 bool QDeclarativeState::removeEntryFromRevertList(QObject *target, const QString &name)
447 {
448     Q_D(QDeclarativeState);
449 
450     if (isStateActive()) {
451         QMutableListIterator<QDeclarativeSimpleAction> revertListIterator(d->revertList);
452 
453         while (revertListIterator.hasNext()) {
454             QDeclarativeSimpleAction &simpleAction = revertListIterator.next();
455             if (simpleAction.property().object() == target && simpleAction.property().name() == name) {
456                 QDeclarativeAbstractBinding *oldBinding = QDeclarativePropertyPrivate::binding(simpleAction.property());
457                 if (oldBinding) {
458                     QDeclarativePropertyPrivate::setBinding(simpleAction.property(), 0);
459                     oldBinding->destroy();
460                 }
461 
462                 simpleAction.property().write(simpleAction.value());
463                 if (simpleAction.binding())
464                     QDeclarativePropertyPrivate::setBinding(simpleAction.property(), simpleAction.binding());
465 
466                 revertListIterator.remove();
467                 return true;
468             }
469         }
470     }
471 
472     return false;
473 }
474 
addEntryToRevertList(const QDeclarativeAction & action)475 void QDeclarativeState::addEntryToRevertList(const QDeclarativeAction &action)
476 {
477     Q_D(QDeclarativeState);
478 
479     QDeclarativeSimpleAction simpleAction(action);
480 
481     d->revertList.append(simpleAction);
482 }
483 
removeAllEntriesFromRevertList(QObject * target)484 void QDeclarativeState::removeAllEntriesFromRevertList(QObject *target)
485 {
486      Q_D(QDeclarativeState);
487 
488      if (isStateActive()) {
489          QMutableListIterator<QDeclarativeSimpleAction> revertListIterator(d->revertList);
490 
491          while (revertListIterator.hasNext()) {
492              QDeclarativeSimpleAction &simpleAction = revertListIterator.next();
493              if (simpleAction.property().object() == target) {
494                  QDeclarativeAbstractBinding *oldBinding = QDeclarativePropertyPrivate::binding(simpleAction.property());
495                  if (oldBinding) {
496                      QDeclarativePropertyPrivate::setBinding(simpleAction.property(), 0);
497                      oldBinding->destroy();
498                  }
499 
500                  simpleAction.property().write(simpleAction.value());
501                  if (simpleAction.binding())
502                      QDeclarativePropertyPrivate::setBinding(simpleAction.property(), simpleAction.binding());
503 
504                  revertListIterator.remove();
505              }
506          }
507      }
508 }
509 
addEntriesToRevertList(const QList<QDeclarativeAction> & actionList)510 void QDeclarativeState::addEntriesToRevertList(const QList<QDeclarativeAction> &actionList)
511 {
512     Q_D(QDeclarativeState);
513     if (isStateActive()) {
514         QList<QDeclarativeSimpleAction> simpleActionList;
515 
516         QListIterator<QDeclarativeAction> actionListIterator(actionList);
517         while(actionListIterator.hasNext()) {
518             const QDeclarativeAction &action = actionListIterator.next();
519             QDeclarativeSimpleAction simpleAction(action);
520             action.property.write(action.toValue);
521             if (!action.toBinding.isNull()) {
522                 QDeclarativeAbstractBinding *oldBinding = QDeclarativePropertyPrivate::binding(simpleAction.property());
523                 if (oldBinding)
524                     QDeclarativePropertyPrivate::setBinding(simpleAction.property(), 0);
525                 QDeclarativePropertyPrivate::setBinding(simpleAction.property(), action.toBinding.data(), QDeclarativePropertyPrivate::DontRemoveBinding);
526             }
527 
528             simpleActionList.append(simpleAction);
529         }
530 
531         d->revertList.append(simpleActionList);
532     }
533 }
534 
valueInRevertList(QObject * target,const QString & name) const535 QVariant QDeclarativeState::valueInRevertList(QObject *target, const QString &name) const
536 {
537     Q_D(const QDeclarativeState);
538 
539     if (isStateActive()) {
540         QListIterator<QDeclarativeSimpleAction> revertListIterator(d->revertList);
541 
542         while (revertListIterator.hasNext()) {
543             const QDeclarativeSimpleAction &simpleAction = revertListIterator.next();
544             if (simpleAction.specifiedObject() == target && simpleAction.specifiedProperty() == name)
545                 return simpleAction.value();
546         }
547     }
548 
549     return QVariant();
550 }
551 
bindingInRevertList(QObject * target,const QString & name) const552 QDeclarativeAbstractBinding *QDeclarativeState::bindingInRevertList(QObject *target, const QString &name) const
553 {
554     Q_D(const QDeclarativeState);
555 
556     if (isStateActive()) {
557         QListIterator<QDeclarativeSimpleAction> revertListIterator(d->revertList);
558 
559         while (revertListIterator.hasNext()) {
560             const QDeclarativeSimpleAction &simpleAction = revertListIterator.next();
561             if (simpleAction.specifiedObject() == target && simpleAction.specifiedProperty() == name)
562                 return simpleAction.binding();
563         }
564     }
565 
566     return 0;
567 }
568 
isStateActive() const569 bool QDeclarativeState::isStateActive() const
570 {
571     return stateGroup() && stateGroup()->state() == name();
572 }
573 
apply(QDeclarativeStateGroup * group,QDeclarativeTransition * trans,QDeclarativeState * revert)574 void QDeclarativeState::apply(QDeclarativeStateGroup *group, QDeclarativeTransition *trans, QDeclarativeState *revert)
575 {
576     Q_D(QDeclarativeState);
577 
578     qmlExecuteDeferred(this);
579 
580     cancel();
581     if (revert)
582         revert->cancel();
583     d->revertList.clear();
584     d->reverting.clear();
585 
586     if (revert) {
587         QDeclarativeStatePrivate *revertPrivate =
588             static_cast<QDeclarativeStatePrivate*>(revert->d_func());
589         d->revertList = revertPrivate->revertList;
590         revertPrivate->revertList.clear();
591     }
592 
593     // List of actions caused by this state
594     QDeclarativeStateOperation::ActionList applyList = d->generateActionList(group);
595 
596     // List of actions that need to be reverted to roll back (just) this state
597     QDeclarativeStatePrivate::SimpleActionList additionalReverts;
598     // First add the reverse of all the applyList actions
599     for (int ii = 0; ii < applyList.count(); ++ii) {
600         QDeclarativeAction &action = applyList[ii];
601 
602         if (action.event) {
603             if (!action.event->isReversable())
604                 continue;
605             bool found = false;
606             for (int jj = 0; jj < d->revertList.count(); ++jj) {
607                 QDeclarativeActionEvent *event = d->revertList.at(jj).event();
608                 if (event && event->typeName() == action.event->typeName()) {
609                     if (action.event->override(event)) {
610                         found = true;
611 
612                         if (action.event != d->revertList.at(jj).event() && action.event->needsCopy()) {
613                             action.event->copyOriginals(d->revertList.at(jj).event());
614 
615                             QDeclarativeSimpleAction r(action);
616                             additionalReverts << r;
617                             d->revertList.removeAt(jj);
618                             --jj;
619                         } else if (action.event->isRewindable())    //###why needed?
620                             action.event->saveCurrentValues();
621 
622                         break;
623                     }
624                 }
625             }
626             if (!found) {
627                 action.event->saveOriginals();
628                 // Only need to revert the applyList action if the previous
629                 // state doesn't have a higher priority revert already
630                 QDeclarativeSimpleAction r(action);
631                 additionalReverts << r;
632             }
633         } else {
634             bool found = false;
635             action.fromBinding = QDeclarativePropertyPrivate::binding(action.property);
636 
637             for (int jj = 0; jj < d->revertList.count(); ++jj) {
638                 if (d->revertList.at(jj).property() == action.property) {
639                     found = true;
640                     if (d->revertList.at(jj).binding() != action.fromBinding) {
641                         action.deleteFromBinding();
642                     }
643                     break;
644                 }
645             }
646 
647             if (!found) {
648                 if (!action.restore) {
649                     action.deleteFromBinding();;
650                 } else {
651                     // Only need to revert the applyList action if the previous
652                     // state doesn't have a higher priority revert already
653                     QDeclarativeSimpleAction r(action);
654                     additionalReverts << r;
655                 }
656             }
657         }
658     }
659 
660     // Any reverts from a previous state that aren't carried forth
661     // into this state need to be translated into apply actions
662     for (int ii = 0; ii < d->revertList.count(); ++ii) {
663         bool found = false;
664         if (d->revertList.at(ii).event()) {
665             QDeclarativeActionEvent *event = d->revertList.at(ii).event();
666             if (!event->isReversable())
667                 continue;
668             for (int jj = 0; !found && jj < applyList.count(); ++jj) {
669                 const QDeclarativeAction &action = applyList.at(jj);
670                 if (action.event && action.event->typeName() == event->typeName()) {
671                     if (action.event->override(event))
672                         found = true;
673                 }
674             }
675         } else {
676             for (int jj = 0; !found && jj < applyList.count(); ++jj) {
677                 const QDeclarativeAction &action = applyList.at(jj);
678                 if (action.property == d->revertList.at(ii).property())
679                     found = true;
680             }
681         }
682         if (!found) {
683             QVariant cur = d->revertList.at(ii).property().read();
684             QDeclarativeAbstractBinding *delBinding =
685                 QDeclarativePropertyPrivate::setBinding(d->revertList.at(ii).property(), 0);
686             if (delBinding)
687                 delBinding->destroy();
688 
689             QDeclarativeAction a;
690             a.property = d->revertList.at(ii).property();
691             a.fromValue = cur;
692             a.toValue = d->revertList.at(ii).value();
693             a.toBinding = QDeclarativeAbstractBinding::getPointer(d->revertList.at(ii).binding());
694             a.specifiedObject = d->revertList.at(ii).specifiedObject();
695             a.specifiedProperty = d->revertList.at(ii).specifiedProperty();
696             a.event = d->revertList.at(ii).event();
697             a.reverseEvent = d->revertList.at(ii).reverseEvent();
698             if (a.event && a.event->isRewindable())
699                 a.event->saveCurrentValues();
700             applyList << a;
701             // Store these special reverts in the reverting list
702             d->reverting << d->revertList.at(ii).property();
703         }
704     }
705     // All the local reverts now become part of the ongoing revertList
706     d->revertList << additionalReverts;
707 
708 #ifndef QT_NO_DEBUG_STREAM
709     // Output for debugging
710     if (stateChangeDebug()) {
711         foreach(const QDeclarativeAction &action, applyList) {
712             if (action.event)
713                 qWarning() << "    QDeclarativeAction event:" << action.event->typeName();
714             else
715                 qWarning() << "    QDeclarativeAction:" << action.property.object()
716                            << action.property.name() << "From:" << action.fromValue
717                            << "To:" << action.toValue;
718         }
719     }
720 #endif
721 
722     d->transitionManager.transition(applyList, trans);
723 }
724 
actions()725 QDeclarativeStateOperation::ActionList QDeclarativeStateOperation::actions()
726 {
727     return ActionList();
728 }
729 
state() const730 QDeclarativeState *QDeclarativeStateOperation::state() const
731 {
732     Q_D(const QDeclarativeStateOperation);
733     return d->m_state;
734 }
735 
setState(QDeclarativeState * state)736 void QDeclarativeStateOperation::setState(QDeclarativeState *state)
737 {
738     Q_D(QDeclarativeStateOperation);
739     d->m_state = state;
740 }
741 
742 QT_END_NAMESPACE
743