src/corelib/statemachine/qstatemachine.cpp
changeset 3 41300fa6a67c
parent 0 1918ee327afb
child 4 3b1da2848fc7
child 7 f7bc934e204c
equal deleted inserted replaced
2:56cd8111b7f7 3:41300fa6a67c
   157     \property QStateMachine::globalRestorePolicy
   157     \property QStateMachine::globalRestorePolicy
   158 
   158 
   159     \brief the restore policy for states of this state machine.
   159     \brief the restore policy for states of this state machine.
   160 
   160 
   161     The default value of this property is
   161     The default value of this property is
   162     QStateMachine::DoNotRestoreProperties.
   162     QStateMachine::DontRestoreProperties.
   163 */
   163 */
   164 
   164 
   165 #ifndef QT_NO_ANIMATION
   165 #ifndef QT_NO_ANIMATION
   166 /*!
   166 /*!
   167     \property QStateMachine::animationsEnabled
   167     \property QStateMachine::animated
   168 
   168 
   169     \brief whether animations are enabled
   169     \brief whether animations are enabled
   170 
   170 
   171     The default value of this property is true.
   171     The default value of this property is true.
   172 
   172 
   176 
   176 
   177 // #define QSTATEMACHINE_DEBUG
   177 // #define QSTATEMACHINE_DEBUG
   178 
   178 
   179 QStateMachinePrivate::QStateMachinePrivate()
   179 QStateMachinePrivate::QStateMachinePrivate()
   180 {
   180 {
       
   181     QAbstractStatePrivate::isMachine = true;
       
   182 
   181     state = NotRunning;
   183     state = NotRunning;
   182     _startState = 0;
   184     _startState = 0;
   183     processing = false;
   185     processing = false;
   184     processingScheduled = false;
   186     processingScheduled = false;
   185     stop = false;
   187     stop = false;
   186     stopProcessingReason = EventQueueEmpty;
   188     stopProcessingReason = EventQueueEmpty;
   187     error = QStateMachine::NoError;
   189     error = QStateMachine::NoError;
   188     globalRestorePolicy = QStateMachine::DoNotRestoreProperties;
   190     globalRestorePolicy = QStateMachine::DontRestoreProperties;
   189     signalEventGenerator = 0;
   191     signalEventGenerator = 0;
   190 #ifndef QT_NO_ANIMATION
   192 #ifndef QT_NO_ANIMATION
   191     animationsEnabled = true;
   193     animated = true;
   192 #endif
   194 #endif
   193 }
   195 }
   194 
   196 
   195 QStateMachinePrivate::~QStateMachinePrivate()
   197 QStateMachinePrivate::~QStateMachinePrivate()
   196 {
   198 {
   334         if (!isAtomic(state))
   336         if (!isAtomic(state))
   335             continue;
   337             continue;
   336         if (isPreempted(state, enabledTransitions))
   338         if (isPreempted(state, enabledTransitions))
   337             continue;
   339             continue;
   338         QList<QState*> lst = properAncestors(state, rootState()->parentState());
   340         QList<QState*> lst = properAncestors(state, rootState()->parentState());
   339         if (QState *grp = qobject_cast<QState*>(state))
   341         if (QState *grp = toStandardState(state))
   340             lst.prepend(grp);
   342             lst.prepend(grp);
   341         bool found = false;
   343         bool found = false;
   342         for (int j = 0; (j < lst.size()) && !found; ++j) {
   344         for (int j = 0; (j < lst.size()) && !found; ++j) {
   343             QState *s = lst.at(j);
   345             QState *s = lst.at(j);
   344             QList<QAbstractTransition*> transitions = QStatePrivate::get(s)->transitions();
   346             QList<QAbstractTransition*> transitions = QStatePrivate::get(s)->transitions();
   412     }
   414     }
   413     QList<QAbstractState*> statesToExit_sorted = statesToExit.toList();
   415     QList<QAbstractState*> statesToExit_sorted = statesToExit.toList();
   414     qSort(statesToExit_sorted.begin(), statesToExit_sorted.end(), stateExitLessThan);
   416     qSort(statesToExit_sorted.begin(), statesToExit_sorted.end(), stateExitLessThan);
   415     for (int i = 0; i < statesToExit_sorted.size(); ++i) {
   417     for (int i = 0; i < statesToExit_sorted.size(); ++i) {
   416         QAbstractState *s = statesToExit_sorted.at(i);
   418         QAbstractState *s = statesToExit_sorted.at(i);
   417         if (QState *grp = qobject_cast<QState*>(s)) {
   419         if (QState *grp = toStandardState(s)) {
   418             QList<QHistoryState*> hlst = QStatePrivate::get(grp)->historyStates();
   420             QList<QHistoryState*> hlst = QStatePrivate::get(grp)->historyStates();
   419             for (int j = 0; j < hlst.size(); ++j) {
   421             for (int j = 0; j < hlst.size(); ++j) {
   420                 QHistoryState *h = hlst.at(j);
   422                 QHistoryState *h = hlst.at(j);
   421                 QHistoryStatePrivate::get(h)->configuration.clear();
   423                 QHistoryStatePrivate::get(h)->configuration.clear();
   422                 QSet<QAbstractState*>::const_iterator it;
   424                 QSet<QAbstractState*>::const_iterator it;
   561 
   563 
   562 void QStateMachinePrivate::addStatesToEnter(QAbstractState *s, QState *root,
   564 void QStateMachinePrivate::addStatesToEnter(QAbstractState *s, QState *root,
   563                                             QSet<QAbstractState*> &statesToEnter,
   565                                             QSet<QAbstractState*> &statesToEnter,
   564                                             QSet<QAbstractState*> &statesForDefaultEntry)
   566                                             QSet<QAbstractState*> &statesForDefaultEntry)
   565 {
   567 {
   566 	if (QHistoryState *h = qobject_cast<QHistoryState*>(s)) {
   568 	if (QHistoryState *h = toHistoryState(s)) {
   567 		QList<QAbstractState*> hconf = QHistoryStatePrivate::get(h)->configuration;
   569 		QList<QAbstractState*> hconf = QHistoryStatePrivate::get(h)->configuration;
   568 		if (!hconf.isEmpty()) {
   570 		if (!hconf.isEmpty()) {
   569 			for (int k = 0; k < hconf.size(); ++k) {
   571 			for (int k = 0; k < hconf.size(); ++k) {
   570 				QAbstractState *s0 = hconf.at(k);
   572 				QAbstractState *s0 = hconf.at(k);
   571 				addStatesToEnter(s0, root, statesToEnter, statesForDefaultEntry);
   573 				addStatesToEnter(s0, root, statesToEnter, statesForDefaultEntry);
   598                 Q_ASSERT(error != QStateMachine::NoError);
   600                 Q_ASSERT(error != QStateMachine::NoError);
   599                 return;
   601                 return;
   600             }
   602             }
   601 		statesToEnter.insert(s);
   603 		statesToEnter.insert(s);
   602 		if (isParallel(s)) {
   604 		if (isParallel(s)) {
   603 			QState *grp = qobject_cast<QState*>(s);
   605 			QState *grp = toStandardState(s);
   604 			QList<QAbstractState*> lst = QStatePrivate::get(grp)->childStates();
   606 			QList<QAbstractState*> lst = QStatePrivate::get(grp)->childStates();
   605 			for (int i = 0; i < lst.size(); ++i) {
   607 			for (int i = 0; i < lst.size(); ++i) {
   606 				QAbstractState *child = lst.at(i);
   608 				QAbstractState *child = lst.at(i);
   607 				addStatesToEnter(child, grp, statesToEnter, statesForDefaultEntry);
   609 				addStatesToEnter(child, grp, statesToEnter, statesForDefaultEntry);
   608 			}
   610 			}
   609 		} else if (isCompound(s)) {
   611 		} else if (isCompound(s)) {
   610 			statesForDefaultEntry.insert(s);
   612 			statesForDefaultEntry.insert(s);
   611 			QState *grp = qobject_cast<QState*>(s);
   613 			QState *grp = toStandardState(s);
   612 			QAbstractState *initial = grp->initialState();
   614 			QAbstractState *initial = grp->initialState();
   613 			if (initial != 0) {
   615 			if (initial != 0) {
   614                             Q_ASSERT(initial->machine() == q_func());
   616                             Q_ASSERT(initial->machine() == q_func());
   615 				addStatesToEnter(initial, grp, statesToEnter, statesForDefaultEntry);
   617 				addStatesToEnter(initial, grp, statesToEnter, statesForDefaultEntry);
   616 			} else {
   618 			} else {
   658 #endif
   660 #endif
   659     // Process the property assignments of the entered states.
   661     // Process the property assignments of the entered states.
   660     QHash<QAbstractState*, QList<QPropertyAssignment> > propertyAssignmentsForState;
   662     QHash<QAbstractState*, QList<QPropertyAssignment> > propertyAssignmentsForState;
   661     QHash<RestorableId, QVariant> pendingRestorables = registeredRestorables;
   663     QHash<RestorableId, QVariant> pendingRestorables = registeredRestorables;
   662     for (int i = 0; i < enteredStates.size(); ++i) {
   664     for (int i = 0; i < enteredStates.size(); ++i) {
   663         QState *s = qobject_cast<QState*>(enteredStates.at(i));
   665         QState *s = toStandardState(enteredStates.at(i));
   664         if (!s)
   666         if (!s)
   665             continue;
   667             continue;
   666 
   668 
   667         QList<QPropertyAssignment> assignments = QStatePrivate::get(s)->propertyAssignments;
   669         QList<QPropertyAssignment> assignments = QStatePrivate::get(s)->propertyAssignments;
   668         for (int j = 0; j < assignments.size(); ++j) {
   670         for (int j = 0; j < assignments.size(); ++j) {
   740         }
   742         }
   741     }
   743     }
   742 
   744 
   743     // Find the animations to use for the state change.
   745     // Find the animations to use for the state change.
   744     QList<QAbstractAnimation*> selectedAnimations;
   746     QList<QAbstractAnimation*> selectedAnimations;
   745     if (animationsEnabled) {
   747     if (animated) {
   746         for (int i = 0; i < transitionList.size(); ++i) {
   748         for (int i = 0; i < transitionList.size(); ++i) {
   747             QAbstractTransition *transition = transitionList.at(i);
   749             QAbstractTransition *transition = transitionList.at(i);
   748 
   750 
   749             selectedAnimations << transition->animations();
   751             selectedAnimations << transition->animations();
   750             selectedAnimations << defaultAnimationsForSource.values(transition->sourceState());
   752             selectedAnimations << defaultAnimationsForSource.values(transition->sourceState());
   805 
   807 
   806         if (hasValidEndValue) {
   808         if (hasValidEndValue) {
   807             if (anim->state() == QAbstractAnimation::Running) {
   809             if (anim->state() == QAbstractAnimation::Running) {
   808                 // The animation is still running. This can happen if the
   810                 // The animation is still running. This can happen if the
   809                 // animation is a group, and one of its children just finished,
   811                 // animation is a group, and one of its children just finished,
   810                 // and that caused a state to emit its polished() signal, and
   812                 // and that caused a state to emit its propertiesAssigned() signal, and
   811                 // that triggered a transition in the machine.
   813                 // that triggered a transition in the machine.
   812                 // Just stop the animation so it is correctly restarted again.
   814                 // Just stop the animation so it is correctly restarted again.
   813                 anim->stop();
   815                 anim->stop();
   814             }
   816             }
   815             anim->start();
   817             anim->start();
   827                 assn.object->setProperty(assn.propertyName, assn.value);
   829                 assn.object->setProperty(assn.propertyName, assn.value);
   828             }
   830             }
   829         }
   831         }
   830     }
   832     }
   831 
   833 
   832     // Emit polished signal for entered states that have no animated properties.
   834     // Emit propertiesAssigned signal for entered states that have no animated properties.
   833     for (int i = 0; i < enteredStates.size(); ++i) {
   835     for (int i = 0; i < enteredStates.size(); ++i) {
   834         QState *s = qobject_cast<QState*>(enteredStates.at(i));
   836         QState *s = toStandardState(enteredStates.at(i));
   835         if (s 
   837         if (s 
   836 #ifndef QT_NO_ANIMATION
   838 #ifndef QT_NO_ANIMATION
   837             && !animationsForState.contains(s)
   839             && !animationsForState.contains(s)
   838 #endif
   840 #endif
   839             )
   841             )
   840             QStatePrivate::get(s)->emitPolished();
   842             QStatePrivate::get(s)->emitPropertiesAssigned();
   841     }
   843     }
   842 }
   844 }
   843 
   845 
   844 #endif // QT_NO_PROPERTIES
   846 #endif // QT_NO_PROPERTIES
   845 
   847 
   846 bool QStateMachinePrivate::isFinal(const QAbstractState *s)
   848 bool QStateMachinePrivate::isFinal(const QAbstractState *s)
   847 {
   849 {
   848     return qobject_cast<const QFinalState*>(s) != 0;
   850     return s && (QAbstractStatePrivate::get(s)->stateType == QAbstractStatePrivate::FinalState);
   849 }
   851 }
   850 
   852 
   851 bool QStateMachinePrivate::isParallel(const QAbstractState *s)
   853 bool QStateMachinePrivate::isParallel(const QAbstractState *s)
   852 {
   854 {
   853     const QState *ss = qobject_cast<const QState*>(s);
   855     const QState *ss = toStandardState(s);
   854     return ss && (QStatePrivate::get(ss)->childMode == QState::ParallelStates);
   856     return ss && (QStatePrivate::get(ss)->childMode == QState::ParallelStates);
   855 }
   857 }
   856 
   858 
   857 bool QStateMachinePrivate::isCompound(const QAbstractState *s) const
   859 bool QStateMachinePrivate::isCompound(const QAbstractState *s) const
   858 {
   860 {
   859     const QState *group = qobject_cast<const QState*>(s);
   861     const QState *group = toStandardState(s);
   860     if (!group)
   862     if (!group)
   861         return false;
   863         return false;
   862     bool isMachine = (qobject_cast<const QStateMachine*>(group) != 0);
   864     bool isMachine = QStatePrivate::get(group)->isMachine;
   863     // Don't treat the machine as compound if it's a sub-state of this machine
   865     // Don't treat the machine as compound if it's a sub-state of this machine
   864     if (isMachine && (group != rootState()))
   866     if (isMachine && (group != rootState()))
   865         return false;
   867         return false;
   866     return (!isParallel(group) && !QStatePrivate::get(group)->childStates().isEmpty())
   868     return (!isParallel(group) && !QStatePrivate::get(group)->childStates().isEmpty())
   867         || isMachine;
   869         || isMachine;
   868 }
   870 }
   869 
   871 
   870 bool QStateMachinePrivate::isAtomic(const QAbstractState *s) const
   872 bool QStateMachinePrivate::isAtomic(const QAbstractState *s) const
   871 {
   873 {
   872     const QState *ss = qobject_cast<const QState*>(s);
   874     const QState *ss = toStandardState(s);
   873     return (ss && QStatePrivate::get(ss)->childStates().isEmpty())
   875     return (ss && QStatePrivate::get(ss)->childStates().isEmpty())
   874         || isFinal(s)
   876         || isFinal(s)
   875         // Treat the machine as atomic if it's a sub-state of this machine
   877         // Treat the machine as atomic if it's a sub-state of this machine
   876         || (ss && (qobject_cast<const QStateMachine*>(ss) != 0) && (ss != rootState()));
   878         || (ss && QStatePrivate::get(ss)->isMachine && (ss != rootState()));
   877 }
   879 }
   878 
   880 
   879 
   881 
   880 bool QStateMachinePrivate::isDescendantOf(const QAbstractState *state, const QAbstractState *other)
   882 bool QStateMachinePrivate::isDescendantOf(const QAbstractState *state, const QAbstractState *other)
   881 {
   883 {
   895         result.append(s);
   897         result.append(s);
   896     }
   898     }
   897     return result;
   899     return result;
   898 }
   900 }
   899 
   901 
       
   902 QState *QStateMachinePrivate::toStandardState(QAbstractState *state)
       
   903 {
       
   904     if (state && (QAbstractStatePrivate::get(state)->stateType == QAbstractStatePrivate::StandardState))
       
   905         return static_cast<QState*>(state);
       
   906     return 0;
       
   907 }
       
   908 
       
   909 const QState *QStateMachinePrivate::toStandardState(const QAbstractState *state)
       
   910 {
       
   911     if (state && (QAbstractStatePrivate::get(state)->stateType == QAbstractStatePrivate::StandardState))
       
   912         return static_cast<const QState*>(state);
       
   913     return 0;
       
   914 }
       
   915 
       
   916 QFinalState *QStateMachinePrivate::toFinalState(QAbstractState *state)
       
   917 {
       
   918     if (state && (QAbstractStatePrivate::get(state)->stateType == QAbstractStatePrivate::FinalState))
       
   919         return static_cast<QFinalState*>(state);
       
   920     return 0;
       
   921 }
       
   922 
       
   923 QHistoryState *QStateMachinePrivate::toHistoryState(QAbstractState *state)
       
   924 {
       
   925     if (state && (QAbstractStatePrivate::get(state)->stateType == QAbstractStatePrivate::HistoryState))
       
   926         return static_cast<QHistoryState*>(state);
       
   927     return 0;
       
   928 }
       
   929 
   900 bool QStateMachinePrivate::isInFinalState(QAbstractState* s) const
   930 bool QStateMachinePrivate::isInFinalState(QAbstractState* s) const
   901 {
   931 {
   902     if (isCompound(s)) {
   932     if (isCompound(s)) {
   903         QState *grp = qobject_cast<QState*>(s);
   933         QState *grp = toStandardState(s);
   904         QList<QAbstractState*> lst = QStatePrivate::get(grp)->childStates();
   934         QList<QAbstractState*> lst = QStatePrivate::get(grp)->childStates();
   905         for (int i = 0; i < lst.size(); ++i) {
   935         for (int i = 0; i < lst.size(); ++i) {
   906             QAbstractState *cs = lst.at(i);
   936             QAbstractState *cs = lst.at(i);
   907             if (isFinal(cs) && configuration.contains(cs))
   937             if (isFinal(cs) && configuration.contains(cs))
   908                 return true;
   938                 return true;
   909         }
   939         }
   910         return false;
   940         return false;
   911     } else if (isParallel(s)) {
   941     } else if (isParallel(s)) {
   912         QState *grp = qobject_cast<QState*>(s);
   942         QState *grp = toStandardState(s);
   913         QList<QAbstractState*> lst = QStatePrivate::get(grp)->childStates();
   943         QList<QAbstractState*> lst = QStatePrivate::get(grp)->childStates();
   914         for (int i = 0; i < lst.size(); ++i) {
   944         for (int i = 0; i < lst.size(); ++i) {
   915             QAbstractState *cs = lst.at(i);
   945             QAbstractState *cs = lst.at(i);
   916             if (!isInFinalState(cs))
   946             if (!isInFinalState(cs))
   917                 return false;
   947                 return false;
   973 QAbstractState *QStateMachinePrivate::findErrorState(QAbstractState *context)
  1003 QAbstractState *QStateMachinePrivate::findErrorState(QAbstractState *context)
   974 {
  1004 {
   975     // Find error state recursively in parent hierarchy if not set explicitly for context state
  1005     // Find error state recursively in parent hierarchy if not set explicitly for context state
   976     QAbstractState *errorState = 0;
  1006     QAbstractState *errorState = 0;
   977     if (context != 0) {
  1007     if (context != 0) {
   978         QState *s = qobject_cast<QState*>(context);
  1008         QState *s = toStandardState(context);
   979         if (s != 0)
  1009         if (s != 0)
   980             errorState = s->errorState();
  1010             errorState = s->errorState();
   981 
  1011 
   982         if (errorState == 0)
  1012         if (errorState == 0)
   983             errorState = findErrorState(context->parentState());
  1013             errorState = findErrorState(context->parentState());
  1098     Q_ASSERT(it != animationsForState.end());
  1128     Q_ASSERT(it != animationsForState.end());
  1099     QList<QAbstractAnimation*> &animations = it.value();
  1129     QList<QAbstractAnimation*> &animations = it.value();
  1100     animations.removeOne(anim);
  1130     animations.removeOne(anim);
  1101     if (animations.isEmpty()) {
  1131     if (animations.isEmpty()) {
  1102         animationsForState.erase(it);
  1132         animationsForState.erase(it);
  1103         QStatePrivate::get(qobject_cast<QState*>(state))->emitPolished();
  1133         QStatePrivate::get(toStandardState(state))->emitPropertiesAssigned();
  1104     }
  1134     }
  1105 }
  1135 }
  1106 
  1136 
  1107 #endif // !QT_NO_ANIMATION
  1137 #endif // !QT_NO_ANIMATION
  1108 
  1138 
  1214         enabledTransitions = selectTransitions(e);
  1244         enabledTransitions = selectTransitions(e);
  1215         if (enabledTransitions.isEmpty()) {
  1245         if (enabledTransitions.isEmpty()) {
  1216             delete e;
  1246             delete e;
  1217             e = 0;
  1247             e = 0;
  1218         }
  1248         }
  1219         if (enabledTransitions.isEmpty() && !internalEventQueue.isEmpty()) {
  1249         if (enabledTransitions.isEmpty() && ((e = dequeueInternalEvent()) != 0)) {
  1220             e = internalEventQueue.takeFirst();
       
  1221 #ifdef QSTATEMACHINE_DEBUG
  1250 #ifdef QSTATEMACHINE_DEBUG
  1222             qDebug() << q << ": dequeued internal event" << e << "of type" << e->type();
  1251             qDebug() << q << ": dequeued internal event" << e << "of type" << e->type();
  1223 #endif
  1252 #endif
  1224             enabledTransitions = selectTransitions(e);
  1253             enabledTransitions = selectTransitions(e);
  1225             if (enabledTransitions.isEmpty()) {
  1254             if (enabledTransitions.isEmpty()) {
  1226                 delete e;
  1255                 delete e;
  1227                 e = 0;
  1256                 e = 0;
  1228             }
  1257             }
  1229         }
  1258         }
  1230         if (enabledTransitions.isEmpty()) {
  1259         if (enabledTransitions.isEmpty()) {
  1231             if (externalEventQueue.isEmpty()) {
  1260             if ((e = dequeueExternalEvent()) != 0) {
  1232                 if (internalEventQueue.isEmpty()) {
       
  1233                     processing = false;
       
  1234                     stopProcessingReason = EventQueueEmpty;
       
  1235                 }
       
  1236             } else {
       
  1237                 e = externalEventQueue.takeFirst();
       
  1238 #ifdef QSTATEMACHINE_DEBUG
  1261 #ifdef QSTATEMACHINE_DEBUG
  1239                 qDebug() << q << ": dequeued external event" << e << "of type" << e->type();
  1262                 qDebug() << q << ": dequeued external event" << e << "of type" << e->type();
  1240 #endif
  1263 #endif
  1241                 enabledTransitions = selectTransitions(e);
  1264                 enabledTransitions = selectTransitions(e);
  1242                 if (enabledTransitions.isEmpty()) {
  1265                 if (enabledTransitions.isEmpty()) {
  1243                     delete e;
  1266                     delete e;
  1244                     e = 0;
  1267                     e = 0;
       
  1268                 }
       
  1269             } else {
       
  1270                 if (isInternalEventQueueEmpty()) {
       
  1271                     processing = false;
       
  1272                     stopProcessingReason = EventQueueEmpty;
  1245                 }
  1273                 }
  1246             }
  1274             }
  1247         }
  1275         }
  1248         if (!enabledTransitions.isEmpty()) {
  1276         if (!enabledTransitions.isEmpty()) {
  1249             q->beginMicrostep(e);
  1277             q->beginMicrostep(e);
  1276         emit q->stopped();
  1304         emit q->stopped();
  1277         break;
  1305         break;
  1278     }
  1306     }
  1279 }
  1307 }
  1280 
  1308 
       
  1309 void QStateMachinePrivate::postInternalEvent(QEvent *e)
       
  1310 {
       
  1311     QMutexLocker locker(&internalEventMutex);
       
  1312     internalEventQueue.append(e);
       
  1313 }
       
  1314 
       
  1315 void QStateMachinePrivate::postExternalEvent(QEvent *e)
       
  1316 {
       
  1317     QMutexLocker locker(&externalEventMutex);
       
  1318     externalEventQueue.append(e);
       
  1319 }
       
  1320 
       
  1321 QEvent *QStateMachinePrivate::dequeueInternalEvent()
       
  1322 {
       
  1323     QMutexLocker locker(&internalEventMutex);
       
  1324     if (internalEventQueue.isEmpty())
       
  1325         return 0;
       
  1326     return internalEventQueue.takeFirst();
       
  1327 }
       
  1328 
       
  1329 QEvent *QStateMachinePrivate::dequeueExternalEvent()
       
  1330 {
       
  1331     QMutexLocker locker(&externalEventMutex);
       
  1332     if (externalEventQueue.isEmpty())
       
  1333         return 0;
       
  1334     return externalEventQueue.takeFirst();
       
  1335 }
       
  1336 
       
  1337 bool QStateMachinePrivate::isInternalEventQueueEmpty()
       
  1338 {
       
  1339     QMutexLocker locker(&internalEventMutex);
       
  1340     return internalEventQueue.isEmpty();
       
  1341 }
       
  1342 
       
  1343 bool QStateMachinePrivate::isExternalEventQueueEmpty()
       
  1344 {
       
  1345     QMutexLocker locker(&externalEventMutex);
       
  1346     return externalEventQueue.isEmpty();
       
  1347 }
       
  1348 
  1281 void QStateMachinePrivate::processEvents(EventProcessingMode processingMode)
  1349 void QStateMachinePrivate::processEvents(EventProcessingMode processingMode)
  1282 {
  1350 {
       
  1351     Q_Q(QStateMachine);
  1283     if ((state != Running) || processing || processingScheduled)
  1352     if ((state != Running) || processing || processingScheduled)
  1284         return;
  1353         return;
  1285     switch (processingMode) {
  1354     switch (processingMode) {
  1286     case DirectProcessing:
  1355     case DirectProcessing:
  1287         _q_process();
  1356         if (QThread::currentThread() == q->thread()) {
  1288         break;
  1357             _q_process();
       
  1358             break;
       
  1359         } // fallthrough -- processing must be done in the machine thread
  1289     case QueuedProcessing:
  1360     case QueuedProcessing:
  1290         processingScheduled = true;
  1361         processingScheduled = true;
  1291         QMetaObject::invokeMethod(q_func(), "_q_process", Qt::QueuedConnection);
  1362         QMetaObject::invokeMethod(q, "_q_process", Qt::QueuedConnection);
  1292         break;
  1363         break;
  1293     }
  1364     }
  1294 }
  1365 }
  1295 
  1366 
  1296 void QStateMachinePrivate::cancelAllDelayedEvents()
  1367 void QStateMachinePrivate::cancelAllDelayedEvents()
  1297 {
  1368 {
  1298     Q_Q(QStateMachine);
  1369     Q_Q(QStateMachine);
       
  1370     QMutexLocker locker(&delayedEventsMutex);
  1299     QHash<int, QEvent*>::const_iterator it;
  1371     QHash<int, QEvent*>::const_iterator it;
  1300     for (it = delayedEvents.constBegin(); it != delayedEvents.constEnd(); ++it) {
  1372     for (it = delayedEvents.constBegin(); it != delayedEvents.constEnd(); ++it) {
  1301         int id = it.key();
  1373         int id = it.key();
  1302         QEvent *e = it.value();
  1374         QEvent *e = it.value();
  1303         q->killTimer(id);
  1375         q->killTimer(id);
  1344 
  1416 
  1345     QState *sourceState = 0;
  1417     QState *sourceState = 0;
  1346     if (state == Running) {
  1418     if (state == Running) {
  1347         QSet<QAbstractState*>::const_iterator it;
  1419         QSet<QAbstractState*>::const_iterator it;
  1348         for (it = configuration.constBegin(); it != configuration.constEnd(); ++it) {
  1420         for (it = configuration.constBegin(); it != configuration.constEnd(); ++it) {
  1349             sourceState = qobject_cast<QState*>(*it);
  1421             sourceState = toStandardState(*it);
  1350             if (sourceState != 0)
  1422             if (sourceState != 0)
  1351                 break;
  1423                 break;
  1352         }
  1424         }
  1353     } else {
  1425     } else {
  1354         sourceState = startState();
  1426         sourceState = startState();
  1368     processEvents(QueuedProcessing);
  1440     processEvents(QueuedProcessing);
  1369 }
  1441 }
  1370 
  1442 
  1371 void QStateMachinePrivate::registerTransitions(QAbstractState *state)
  1443 void QStateMachinePrivate::registerTransitions(QAbstractState *state)
  1372 {
  1444 {
  1373     QState *group = qobject_cast<QState*>(state);
  1445     QState *group = toStandardState(state);
  1374     if (!group)
  1446     if (!group)
  1375         return;
  1447         return;
  1376     QList<QAbstractTransition*> transitions = QStatePrivate::get(group)->transitions();
  1448     QList<QAbstractTransition*> transitions = QStatePrivate::get(group)->transitions();
  1377     for (int i = 0; i < transitions.size(); ++i) {
  1449     for (int i = 0; i < transitions.size(); ++i) {
  1378         QAbstractTransition *t = transitions.at(i);
  1450         QAbstractTransition *t = transitions.at(i);
  1542     }
  1614     }
  1543     QEventTransitionPrivate::get(transition)->registered = false;
  1615     QEventTransitionPrivate::get(transition)->registered = false;
  1544 }
  1616 }
  1545 
  1617 
  1546 void QStateMachinePrivate::handleFilteredEvent(QObject *watched, QEvent *event)
  1618 void QStateMachinePrivate::handleFilteredEvent(QObject *watched, QEvent *event)
  1547 {
  1619 {    
  1548     Q_ASSERT(qobjectEvents.contains(watched));
  1620     if (qobjectEvents.value(watched).contains(event->type())) {
  1549     if (qobjectEvents[watched].contains(event->type())) {
  1621         postInternalEvent(new QStateMachine::WrappedEvent(watched, handler->cloneEvent(event)));
  1550         internalEventQueue.append(new QStateMachine::WrappedEvent(watched, handler->cloneEvent(event)));
       
  1551         processEvents(DirectProcessing);
  1622         processEvents(DirectProcessing);
  1552     }
  1623     }
  1553 }
  1624 }
  1554 #endif
  1625 #endif
  1555 
  1626 
  1569 
  1640 
  1570 #ifdef QSTATEMACHINE_DEBUG
  1641 #ifdef QSTATEMACHINE_DEBUG
  1571     qDebug() << q_func() << ": sending signal event ( sender =" << sender
  1642     qDebug() << q_func() << ": sending signal event ( sender =" << sender
  1572              << ", signal =" << sender->metaObject()->method(signalIndex).signature() << ')';
  1643              << ", signal =" << sender->metaObject()->method(signalIndex).signature() << ')';
  1573 #endif
  1644 #endif
  1574     internalEventQueue.append(new QStateMachine::SignalEvent(sender, signalIndex, vargs));
  1645     postInternalEvent(new QStateMachine::SignalEvent(sender, signalIndex, vargs));
  1575     processEvents(DirectProcessing);
  1646     processEvents(DirectProcessing);
  1576 }
  1647 }
  1577 
  1648 
  1578 /*!
  1649 /*!
  1579   Constructs a new state machine with the given \a parent.
  1650   Constructs a new state machine with the given \a parent.
  1652 
  1723 
  1653    Only one initial value will be saved for any given property. If a value for a property has 
  1724    Only one initial value will be saved for any given property. If a value for a property has 
  1654    already been saved by the state machine, it will not be overwritten until the property has been
  1725    already been saved by the state machine, it will not be overwritten until the property has been
  1655    successfully restored. 
  1726    successfully restored. 
  1656 
  1727 
  1657    \value DoNotRestoreProperties The state machine should not save the initial values of properties 
  1728    \value DontRestoreProperties The state machine should not save the initial values of properties
  1658           and restore them later.
  1729           and restore them later.
  1659    \value RestoreProperties The state machine should save the initial values of properties 
  1730    \value RestoreProperties The state machine should save the initial values of properties 
  1660           and restore them later.
  1731           and restore them later.
  1661 
  1732 
  1662    \sa QStateMachine::globalRestorePolicy QState::assignProperty()
  1733    \sa QStateMachine::globalRestorePolicy QState::assignProperty()
  1702     return d->globalRestorePolicy;
  1773     return d->globalRestorePolicy;
  1703 }
  1774 }
  1704 
  1775 
  1705 /*!
  1776 /*!
  1706    Sets the restore policy of the state machine to \a restorePolicy. The default 
  1777    Sets the restore policy of the state machine to \a restorePolicy. The default 
  1707    restore policy is QAbstractState::DoNotRestoreProperties.
  1778    restore policy is QAbstractState::DontRestoreProperties.
  1708    
  1779    
  1709    \sa globalRestorePolicy()
  1780    \sa globalRestorePolicy()
  1710 */
  1781 */
  1711 void QStateMachine::setGlobalRestorePolicy(QStateMachine::RestorePolicy restorePolicy) 
  1782 void QStateMachine::setGlobalRestorePolicy(QStateMachine::RestorePolicy restorePolicy) 
  1712 {
  1783 {
  1823         break;
  1894         break;
  1824     }
  1895     }
  1825 }
  1896 }
  1826 
  1897 
  1827 /*!
  1898 /*!
       
  1899   \threadsafe
       
  1900 
  1828   Posts the given \a event of the given \a priority for processing by this
  1901   Posts the given \a event of the given \a priority for processing by this
  1829   state machine.
  1902   state machine.
  1830 
  1903 
  1831   This function returns immediately. The event is added to the state machine's
  1904   This function returns immediately. The event is added to the state machine's
  1832   event queue. Events are processed in the order posted. The state machine
  1905   event queue. Events are processed in the order posted. The state machine
  1850 #ifdef QSTATEMACHINE_DEBUG
  1923 #ifdef QSTATEMACHINE_DEBUG
  1851     qDebug() << this << ": posting event" << event;
  1924     qDebug() << this << ": posting event" << event;
  1852 #endif
  1925 #endif
  1853     switch (priority) {
  1926     switch (priority) {
  1854     case NormalPriority:
  1927     case NormalPriority:
  1855         d->externalEventQueue.append(event);
  1928         d->postExternalEvent(event);
  1856         break;
  1929         break;
  1857     case HighPriority:
  1930     case HighPriority:
  1858         d->internalEventQueue.append(event);
  1931         d->postInternalEvent(event);
  1859         break;
  1932         break;
  1860     }
  1933     }
  1861     d->processEvents(QStateMachinePrivate::QueuedProcessing);
  1934     d->processEvents(QStateMachinePrivate::QueuedProcessing);
  1862 }
  1935 }
  1863 
  1936 
  1864 /*!
  1937 /*!
       
  1938   \threadsafe
       
  1939 
  1865   Posts the given \a event for processing by this state machine, with the
  1940   Posts the given \a event for processing by this state machine, with the
  1866   given \a delay in milliseconds. Returns an identifier associated with the
  1941   given \a delay in milliseconds. Returns an identifier associated with the
  1867   delayed event, or -1 if the event could not be posted.
  1942   delayed event, or -1 if the event could not be posted.
  1868 
  1943 
  1869   This function returns immediately. When the delay has expired, the event
  1944   This function returns immediately. When the delay has expired, the event
  1891         return -1;
  1966         return -1;
  1892     }
  1967     }
  1893 #ifdef QSTATEMACHINE_DEBUG
  1968 #ifdef QSTATEMACHINE_DEBUG
  1894     qDebug() << this << ": posting event" << event << "with delay" << delay;
  1969     qDebug() << this << ": posting event" << event << "with delay" << delay;
  1895 #endif
  1970 #endif
       
  1971     QMutexLocker locker(&d->delayedEventsMutex);
  1896     int tid = startTimer(delay);
  1972     int tid = startTimer(delay);
  1897     d->delayedEvents[tid] = event;
  1973     d->delayedEvents[tid] = event;
  1898     return tid;
  1974     return tid;
  1899 }
  1975 }
  1900 
  1976 
  1901 /*!
  1977 /*!
       
  1978   \threadsafe
       
  1979 
  1902   Cancels the delayed event identified by the given \a id. The id should be a
  1980   Cancels the delayed event identified by the given \a id. The id should be a
  1903   value returned by a call to postDelayedEvent(). Returns true if the event
  1981   value returned by a call to postDelayedEvent(). Returns true if the event
  1904   was successfully cancelled, otherwise returns false.
  1982   was successfully cancelled, otherwise returns false.
  1905 
  1983 
  1906   \sa postDelayedEvent()
  1984   \sa postDelayedEvent()
  1910     Q_D(QStateMachine);
  1988     Q_D(QStateMachine);
  1911     if (d->state != QStateMachinePrivate::Running) {
  1989     if (d->state != QStateMachinePrivate::Running) {
  1912         qWarning("QStateMachine::cancelDelayedEvent: the machine is not running");
  1990         qWarning("QStateMachine::cancelDelayedEvent: the machine is not running");
  1913         return false;
  1991         return false;
  1914     }
  1992     }
       
  1993     QMutexLocker locker(&d->delayedEventsMutex);
  1915     QEvent *e = d->delayedEvents.take(id);
  1994     QEvent *e = d->delayedEvents.take(id);
  1916     if (!e)
  1995     if (!e)
  1917         return false;
  1996         return false;
  1918     killTimer(id);
  1997     killTimer(id);
  1919     delete e;
  1998     delete e;
  1920     return true;
  1999     return true;
  1921 }
  2000 }
  1922 
  2001 
  1923 /*!
  2002 /*!
  1924   \internal
       
  1925 
       
  1926    Returns the maximal consistent set of states (including parallel and final
  2003    Returns the maximal consistent set of states (including parallel and final
  1927    states) that this state machine is currently in. If a state \c s is in the
  2004    states) that this state machine is currently in. If a state \c s is in the
  1928    configuration, it is always the case that the parent of \c s is also in
  2005    configuration, it is always the case that the parent of \c s is also in
  1929    c. Note, however, that the machine itself is not an explicit member of the
  2006    c. Note, however, that the machine itself is not an explicit member of the
  1930    configuration.
  2007    configuration.
  1961     if (e->type() == QEvent::Timer) {
  2038     if (e->type() == QEvent::Timer) {
  1962         QTimerEvent *te = static_cast<QTimerEvent*>(e);
  2039         QTimerEvent *te = static_cast<QTimerEvent*>(e);
  1963         int tid = te->timerId();
  2040         int tid = te->timerId();
  1964         if (d->state != QStateMachinePrivate::Running) {
  2041         if (d->state != QStateMachinePrivate::Running) {
  1965             // This event has been cancelled already
  2042             // This event has been cancelled already
       
  2043             QMutexLocker locker(&d->delayedEventsMutex);
  1966             Q_ASSERT(!d->delayedEvents.contains(tid));
  2044             Q_ASSERT(!d->delayedEvents.contains(tid));
  1967             return true;
  2045             return true;
  1968         }
  2046         }
       
  2047         d->delayedEventsMutex.lock();
  1969         QEvent *ee = d->delayedEvents.take(tid);
  2048         QEvent *ee = d->delayedEvents.take(tid);
  1970         if (ee != 0) {
  2049         if (ee != 0) {
  1971             killTimer(tid);
  2050             killTimer(tid);
  1972             d->externalEventQueue.append(ee);
  2051             d->delayedEventsMutex.unlock();
       
  2052             d->postExternalEvent(ee);
  1973             d->processEvents(QStateMachinePrivate::DirectProcessing);
  2053             d->processEvents(QStateMachinePrivate::DirectProcessing);
  1974             return true;
  2054             return true;
  1975         }
  2055         } else {
  1976     }
  2056             d->delayedEventsMutex.unlock();
  1977     return QObject::event(e);
  2057         }
       
  2058     }
       
  2059     return QState::event(e);
  1978 }
  2060 }
  1979 
  2061 
  1980 #ifndef QT_NO_STATEMACHINE_EVENTFILTER
  2062 #ifndef QT_NO_STATEMACHINE_EVENTFILTER
  1981 /*!
  2063 /*!
  1982   \reimp
  2064   \reimp
  2061 #ifndef QT_NO_ANIMATION
  2143 #ifndef QT_NO_ANIMATION
  2062 
  2144 
  2063 /*!
  2145 /*!
  2064   Returns whether animations are enabled for this state machine.
  2146   Returns whether animations are enabled for this state machine.
  2065 */
  2147 */
  2066 bool QStateMachine::animationsEnabled() const
  2148 bool QStateMachine::isAnimated() const
  2067 {
  2149 {
  2068     Q_D(const QStateMachine);
  2150     Q_D(const QStateMachine);
  2069     return d->animationsEnabled;
  2151     return d->animated;
  2070 }
  2152 }
  2071 
  2153 
  2072 /*!
  2154 /*!
  2073   Sets whether animations are \a enabled for this state machine.
  2155   Sets whether animations are \a enabled for this state machine.
  2074 */
  2156 */
  2075 void QStateMachine::setAnimationsEnabled(bool enabled)
  2157 void QStateMachine::setAnimated(bool enabled)
  2076 {
  2158 {
  2077     Q_D(QStateMachine);
  2159     Q_D(QStateMachine);
  2078     d->animationsEnabled = enabled;
  2160     d->animated = enabled;
  2079 }
  2161 }
  2080 
  2162 
  2081 /*!
  2163 /*!
  2082     Adds a default \a animation to be considered for any transition.
  2164     Adds a default \a animation to be considered for any transition.
  2083 */    
  2165 */