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() |
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 */ |