Qt 4.8
qstatemachine.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtCore 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 Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/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 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "qstatemachine.h"
43 
44 #ifndef QT_NO_STATEMACHINE
45 
46 #include "qstate.h"
47 #include "qstate_p.h"
48 #include "qstatemachine_p.h"
49 #include "qabstracttransition.h"
50 #include "qabstracttransition_p.h"
51 #include "qsignaltransition.h"
52 #include "qsignaltransition_p.h"
54 #include "qabstractstate.h"
55 #include "qabstractstate_p.h"
56 #include "qfinalstate.h"
57 #include "qhistorystate.h"
58 #include "qhistorystate_p.h"
59 #include "private/qobject_p.h"
60 #include "private/qthread_p.h"
61 
62 #ifndef QT_NO_STATEMACHINE_EVENTFILTER
63 #include "qeventtransition.h"
64 #include "qeventtransition_p.h"
65 #endif
66 
67 #ifndef QT_NO_ANIMATION
68 #include "qpropertyanimation.h"
69 #include "qanimationgroup.h"
70 #include <private/qvariantanimation_p.h>
71 #endif
72 
73 #include <QtCore/qmetaobject.h>
74 #include <qdebug.h>
75 
77 
173 #ifndef QT_NO_ANIMATION
174 
186 #endif
187 
188 // #define QSTATEMACHINE_DEBUG
189 
191 {
192  isMachine = true;
193 
194  state = NotRunning;
195  _startState = 0;
196  processing = false;
197  processingScheduled = false;
198  stop = false;
203 #ifndef QT_NO_ANIMATION
204  animated = true;
205 #endif
206 }
207 
209 {
212 }
213 
215 {
216  if (q)
217  return q->d_func();
218  return 0;
219 }
220 
222 {
223  return const_cast<QStateMachine*>(q_func());
224 }
225 
227 {
228  switch (e->type()) {
229  case QEvent::None:
230  return new QEvent(*e);
231  case QEvent::Timer:
232  return new QTimerEvent(*static_cast<QTimerEvent*>(e));
233  default:
234  Q_ASSERT_X(false, "cloneEvent()", "not implemented");
235  break;
236  }
237  return 0;
238 }
239 
241  cloneEvent
242 };
243 
245 
247 {
249 }
250 
252 {
254  for (int i = 0; i < childStates.size(); ++i) {
255  QAbstractState *c = childStates.at(i);
256  if ((c == desc) || QStateMachinePrivate::isDescendantOf(desc, c)) {
257  return i;
258  }
259  }
260  return -1;
261 }
262 
264 {
265  if (s1->parent() == s2->parent()) {
266  return s1->children().indexOf(s1)
267  < s2->children().indexOf(s2);
268  } else if (isDescendantOf(s1, s2)) {
269  return false;
270  } else if (isDescendantOf(s2, s1)) {
271  return true;
272  } else {
273  Q_ASSERT(s1->machine() != 0);
275  QState *lca = mach->findLCA(QList<QAbstractState*>() << s1 << s2);
276  Q_ASSERT(lca != 0);
277  return (indexOfDescendant(lca, s1) < indexOfDescendant(lca, s2));
278  }
279 }
280 
282 {
283  if (s1->parent() == s2->parent()) {
284  return s1->children().indexOf(s1)
285  < s2->children().indexOf(s2);
286  } else if (isDescendantOf(s1, s2)) {
287  return true;
288  } else if (isDescendantOf(s2, s1)) {
289  return false;
290  } else {
291  Q_ASSERT(s1->machine() != 0);
293  QState *lca = mach->findLCA(QList<QAbstractState*>() << s1 << s2);
294  Q_ASSERT(lca != 0);
295  return (indexOfDescendant(lca, s1) < indexOfDescendant(lca, s2));
296  }
297 }
298 
300 {
301  if (states.isEmpty())
302  return 0;
303  QList<QState*> ancestors = properAncestors(states.at(0), rootState()->parentState());
304  for (int i = 0; i < ancestors.size(); ++i) {
305  QState *anc = ancestors.at(i);
306  bool ok = true;
307  for (int j = states.size() - 1; (j > 0) && ok; --j) {
308  const QAbstractState *s = states.at(j);
309  if (!isDescendantOf(s, anc))
310  ok = false;
311  }
312  if (ok)
313  return anc;
314  }
315  return 0;
316 }
317 
319 {
321  for (it = transitions.constBegin(); it != transitions.constEnd(); ++it) {
322  QAbstractTransition *t = *it;
324  if (!lst.isEmpty()) {
325  lst.prepend(t->sourceState());
326  QAbstractState *lca = findLCA(lst);
327  if (isDescendantOf(s, lca)) {
328 #ifdef QSTATEMACHINE_DEBUG
329  qDebug() << q_func() << ':' << transitions << "preempts selection of a transition from"
330  << s << "because" << s << "is a descendant of" << lca;
331 #endif
332  return true;
333  }
334  }
335  }
336  return false;
337 }
338 
340 {
341  Q_Q(const QStateMachine);
342  QSet<QAbstractTransition*> enabledTransitions;
344  const_cast<QStateMachine*>(q)->beginSelectTransitions(event);
345  for (it = configuration.constBegin(); it != configuration.constEnd(); ++it) {
346  QAbstractState *state = *it;
347  if (!isAtomic(state))
348  continue;
349  if (isPreempted(state, enabledTransitions))
350  continue;
352  if (QState *grp = toStandardState(state))
353  lst.prepend(grp);
354  bool found = false;
355  for (int j = 0; (j < lst.size()) && !found; ++j) {
356  QState *s = lst.at(j);
358  for (int k = 0; k < transitions.size(); ++k) {
359  QAbstractTransition *t = transitions.at(k);
360  if (QAbstractTransitionPrivate::get(t)->callEventTest(event)) {
361 #ifdef QSTATEMACHINE_DEBUG
362  qDebug() << q << ": selecting transition" << t;
363 #endif
364  enabledTransitions.insert(t);
365  found = true;
366  break;
367  }
368  }
369  }
370  }
371  const_cast<QStateMachine*>(q)->endSelectTransitions(event);
372  return enabledTransitions;
373 }
374 
376 {
377 #ifdef QSTATEMACHINE_DEBUG
378  qDebug() << q_func() << ": begin microstep( enabledTransitions:" << enabledTransitions << ')';
379  qDebug() << q_func() << ": configuration before exiting states:" << configuration;
380 #endif
381  QList<QAbstractState*> exitedStates = exitStates(event, enabledTransitions);
382 #ifdef QSTATEMACHINE_DEBUG
383  qDebug() << q_func() << ": configuration after exiting states:" << configuration;
384 #endif
385  executeTransitionContent(event, enabledTransitions);
386  QList<QAbstractState*> enteredStates = enterStates(event, enabledTransitions);
387 #ifndef QT_NO_PROPERTIES
388  applyProperties(enabledTransitions, exitedStates, enteredStates);
389 #endif
390 #ifdef QSTATEMACHINE_DEBUG
391  qDebug() << q_func() << ": configuration after entering states:" << configuration;
392  qDebug() << q_func() << ": end microstep";
393 #endif
394 }
395 
397 {
398 // qDebug() << "exitStates(" << enabledTransitions << ')';
399  QSet<QAbstractState*> statesToExit;
400 // QSet<QAbstractState*> statesToSnapshot;
401  for (int i = 0; i < enabledTransitions.size(); ++i) {
402  QAbstractTransition *t = enabledTransitions.at(i);
404  if (lst.isEmpty())
405  continue;
406  lst.prepend(t->sourceState());
407  QAbstractState *lca = findLCA(lst);
408  if (lca == 0) {
410  lst = pendingErrorStates.toList();
411  lst.prepend(t->sourceState());
412 
413  lca = findLCA(lst);
414  Q_ASSERT(lca != 0);
415  }
416 
417  {
419  for (it = configuration.constBegin(); it != configuration.constEnd(); ++it) {
420  QAbstractState *s = *it;
421  if (isDescendantOf(s, lca))
422  statesToExit.insert(s);
423  }
424  }
425  }
426  QList<QAbstractState*> statesToExit_sorted = statesToExit.toList();
427  qSort(statesToExit_sorted.begin(), statesToExit_sorted.end(), stateExitLessThan);
428  for (int i = 0; i < statesToExit_sorted.size(); ++i) {
429  QAbstractState *s = statesToExit_sorted.at(i);
430  if (QState *grp = toStandardState(s)) {
432  for (int j = 0; j < hlst.size(); ++j) {
433  QHistoryState *h = hlst.at(j);
436  for (it = configuration.constBegin(); it != configuration.constEnd(); ++it) {
437  QAbstractState *s0 = *it;
439  if (isAtomic(s0) && isDescendantOf(s0, s))
441  } else if (s0->parentState() == s) {
443  }
444  }
445 #ifdef QSTATEMACHINE_DEBUG
446  qDebug() << q_func() << ": recorded" << ((QHistoryStatePrivate::get(h)->historyType == QHistoryState::DeepHistory) ? "deep" : "shallow")
447  << "history for" << s << "in" << h << ':' << QHistoryStatePrivate::get(h)->configuration;
448 #endif
449  }
450  }
451  }
452  for (int i = 0; i < statesToExit_sorted.size(); ++i) {
453  QAbstractState *s = statesToExit_sorted.at(i);
454 #ifdef QSTATEMACHINE_DEBUG
455  qDebug() << q_func() << ": exiting" << s;
456 #endif
460  }
461  return statesToExit_sorted;
462 }
463 
465 {
466  for (int i = 0; i < enabledTransitions.size(); ++i) {
467  QAbstractTransition *t = enabledTransitions.at(i);
468 #ifdef QSTATEMACHINE_DEBUG
469  qDebug() << q_func() << ": triggering" << t;
470 #endif
473  }
474 }
475 
477 {
478 #ifdef QSTATEMACHINE_DEBUG
480 #endif
481 // qDebug() << "enterStates(" << enabledTransitions << ')';
482  QSet<QAbstractState*> statesToEnter;
483  QSet<QAbstractState*> statesForDefaultEntry;
484 
485  if (pendingErrorStates.isEmpty()) {
486  for (int i = 0; i < enabledTransitions.size(); ++i) {
487  QAbstractTransition *t = enabledTransitions.at(i);
489  if (lst.isEmpty())
490  continue;
491  lst.prepend(t->sourceState());
492  QState *lca = findLCA(lst);
493  for (int j = 1; j < lst.size(); ++j) {
494  QAbstractState *s = lst.at(j);
495  addStatesToEnter(s, lca, statesToEnter, statesForDefaultEntry);
496  if (isParallel(lca)) {
498  foreach (QAbstractState* child,lcac) {
499  if (!statesToEnter.contains(child))
500  addStatesToEnter(child,lca,statesToEnter,statesForDefaultEntry);
501  }
502  }
503  }
504  }
505  }
506 
507  // Did an error occur while selecting transitions? Then we enter the error state.
508  if (!pendingErrorStates.isEmpty()) {
509  statesToEnter.clear();
510  statesToEnter = pendingErrorStates;
511  statesForDefaultEntry = pendingErrorStatesForDefaultEntry;
514  }
515 
516  QList<QAbstractState*> statesToEnter_sorted = statesToEnter.toList();
517  qSort(statesToEnter_sorted.begin(), statesToEnter_sorted.end(), stateEntryLessThan);
518 
519  for (int i = 0; i < statesToEnter_sorted.size(); ++i) {
520  QAbstractState *s = statesToEnter_sorted.at(i);
521 #ifdef QSTATEMACHINE_DEBUG
522  qDebug() << q << ": entering" << s;
523 #endif
528  if (statesForDefaultEntry.contains(s)) {
529  // ### executeContent(s.initial.transition.children())
530  }
531  if (isFinal(s)) {
532  QState *parent = s->parentState();
533  if (parent) {
534  if (parent != rootState()) {
535 #ifdef QSTATEMACHINE_DEBUG
536  qDebug() << q << ": emitting finished signal for" << parent;
537 #endif
538  QStatePrivate::get(parent)->emitFinished();
539  }
540  QState *grandparent = parent->parentState();
541  if (grandparent && isParallel(grandparent)) {
542  bool allChildStatesFinal = true;
544  for (int j = 0; j < childStates.size(); ++j) {
545  QAbstractState *cs = childStates.at(j);
546  if (!isInFinalState(cs)) {
547  allChildStatesFinal = false;
548  break;
549  }
550  }
551  if (allChildStatesFinal && (grandparent != rootState())) {
552 #ifdef QSTATEMACHINE_DEBUG
553  qDebug() << q << ": emitting finished signal for" << grandparent;
554 #endif
555  QStatePrivate::get(grandparent)->emitFinished();
556  }
557  }
558  }
559  }
560  }
561  {
563  for (it = configuration.constBegin(); it != configuration.constEnd(); ++it) {
564  if (isFinal(*it) && (*it)->parentState() == rootState()) {
565  processing = false;
567  break;
568  }
569  }
570  }
571 // qDebug() << "configuration:" << configuration.toList();
572  return statesToEnter_sorted;
573 }
574 
576  QSet<QAbstractState*> &statesToEnter,
577  QSet<QAbstractState*> &statesForDefaultEntry)
578 {
579  if (QHistoryState *h = toHistoryState(s)) {
581  if (!hconf.isEmpty()) {
582  for (int k = 0; k < hconf.size(); ++k) {
583  QAbstractState *s0 = hconf.at(k);
584  addStatesToEnter(s0, root, statesToEnter, statesForDefaultEntry);
585  }
586  #ifdef QSTATEMACHINE_DEBUG
587  qDebug() <<q_func() << ": restoring"
588  << ((QHistoryStatePrivate::get(h)->historyType == QHistoryState::DeepHistory) ? "deep" : "shallow")
589  << "history from" << s << ':' << hconf;
590  #endif
591  } else {
595 
596  if (hlst.isEmpty()) {
598  } else {
599  for (int k = 0; k < hlst.size(); ++k) {
600  QAbstractState *s0 = hlst.at(k);
601  addStatesToEnter(s0, root, statesToEnter, statesForDefaultEntry);
602  }
603  #ifdef QSTATEMACHINE_DEBUG
604  qDebug() << q_func() << ": initial history targets for" << s << ':' << hlst;
605  #endif
606  }
607  }
608  } else {
609  if (s == rootState()) {
610  // Error has already been set by exitStates().
612  return;
613  }
614  statesToEnter.insert(s);
615  if (isParallel(s)) {
616  QState *grp = toStandardState(s);
618  for (int i = 0; i < lst.size(); ++i) {
619  QAbstractState *child = lst.at(i);
620  addStatesToEnter(child, grp, statesToEnter, statesForDefaultEntry);
621  }
622  } else if (isCompound(s)) {
623  statesForDefaultEntry.insert(s);
624  QState *grp = toStandardState(s);
625  QAbstractState *initial = grp->initialState();
626  if (initial != 0) {
627  Q_ASSERT(initial->machine() == q_func());
628  addStatesToEnter(initial, grp, statesToEnter, statesForDefaultEntry);
629  } else {
631  return;
632  }
633  }
634  QList<QState*> ancs = properAncestors(s, root);
635  for (int i = 0; i < ancs.size(); ++i) {
636  QState *anc = ancs.at(i);
637  if (!anc->parentState())
638  continue;
639  statesToEnter.insert(anc);
640  if (isParallel(anc)) {
642  for (int j = 0; j < lst.size(); ++j) {
643  QAbstractState *child = lst.at(j);
644  bool hasDescendantInList = false;
646  for (it = statesToEnter.constBegin(); it != statesToEnter.constEnd(); ++it) {
647  if (isDescendantOf(*it, child)) {
648  hasDescendantInList = true;
649  break;
650  }
651  }
652  if (!hasDescendantInList)
653  addStatesToEnter(child, anc, statesToEnter, statesForDefaultEntry);
654  }
655  }
656  }
657  }
658 }
659 
660 #ifndef QT_NO_PROPERTIES
661 
663  const QList<QAbstractState*> &exitedStates,
664  const QList<QAbstractState*> &enteredStates)
665 {
666 #ifdef QT_NO_ANIMATION
667  Q_UNUSED(transitionList);
668  Q_UNUSED(exitedStates);
669 #else
671 #endif
672  // Process the property assignments of the entered states.
673  QHash<QAbstractState*, QList<QPropertyAssignment> > propertyAssignmentsForState;
675  for (int i = 0; i < enteredStates.size(); ++i) {
676  QState *s = toStandardState(enteredStates.at(i));
677  if (!s)
678  continue;
679 
681  for (int j = 0; j < assignments.size(); ++j) {
682  const QPropertyAssignment &assn = assignments.at(j);
685  }
686  pendingRestorables.remove(RestorableId(assn.object, assn.propertyName));
687  propertyAssignmentsForState[s].append(assn);
688  }
689 
690  // Remove pending restorables for all parent states to avoid restoring properties
691  // before the state that assigned them is exited. If state does not explicitly
692  // assign a property which is assigned by the parent, it inherits the parent's assignment.
693  QState *parentState = s;
694  while ((parentState = parentState->parentState()) != 0) {
695  assignments = QStatePrivate::get(parentState)->propertyAssignments;
696  for (int j=0; j<assignments.size(); ++j) {
697  const QPropertyAssignment &assn = assignments.at(j);
698  int c = pendingRestorables.remove(RestorableId(assn.object, assn.propertyName));
699  if (c > 0)
700  propertyAssignmentsForState[s].append(assn);
701  }
702  }
703  }
704  if (!pendingRestorables.isEmpty()) {
705  QAbstractState *s;
706  if (!enteredStates.isEmpty())
707  s = enteredStates.last(); // ### handle if parallel
708  else
709  s = 0;
710  propertyAssignmentsForState[s] << restorablesToPropertyList(pendingRestorables);
711  }
712 
713 #ifndef QT_NO_ANIMATION
714  // Gracefully terminate playing animations for states that are exited.
715  for (int i = 0; i < exitedStates.size(); ++i) {
716  QAbstractState *s = exitedStates.at(i);
718  for (int j = 0; j < animations.size(); ++j) {
719  QAbstractAnimation *anim = animations.at(j);
720  QObject::disconnect(anim, SIGNAL(finished()), q, SLOT(_q_animationFinished()));
722 
723  // Stop the (top-level) animation.
724  // ### Stopping nested animation has weird behavior.
725  QAbstractAnimation *topLevelAnim = anim;
726  while (QAnimationGroup *group = topLevelAnim->group())
727  topLevelAnim = group;
728  topLevelAnim->stop();
729 
730  if (resetAnimationEndValues.contains(anim)) {
731  qobject_cast<QVariantAnimation*>(anim)->setEndValue(QVariant()); // ### generalize
733  }
735  Q_ASSERT(assn.object != 0);
736  // If there is no property assignment that sets this property,
737  // set the property to its target value.
738  bool found = false;
740  for (it = propertyAssignmentsForState.constBegin(); it != propertyAssignmentsForState.constEnd(); ++it) {
741  const QList<QPropertyAssignment> &assignments = it.value();
742  for (int k = 0; k < assignments.size(); ++k) {
743  if ((assignments.at(k).object == assn.object)
744  && (assignments.at(k).propertyName == assn.propertyName)) {
745  found = true;
746  break;
747  }
748  }
749  }
750  if (!found) {
751  assn.object->setProperty(assn.propertyName, assn.value);
752  }
753  }
754  }
755 
756  // Find the animations to use for the state change.
757  QList<QAbstractAnimation*> selectedAnimations;
758  if (animated) {
759  for (int i = 0; i < transitionList.size(); ++i) {
760  QAbstractTransition *transition = transitionList.at(i);
761 
762  selectedAnimations << transition->animations();
763  selectedAnimations << defaultAnimationsForSource.values(transition->sourceState());
764 
765  QList<QAbstractState *> targetStates = transition->targetStates();
766  for (int j=0; j<targetStates.size(); ++j)
767  selectedAnimations << defaultAnimationsForTarget.values(targetStates.at(j));
768  }
769  selectedAnimations << defaultAnimations;
770  }
771 
772  // Initialize animations from property assignments.
773  for (int i = 0; i < selectedAnimations.size(); ++i) {
774  QAbstractAnimation *anim = selectedAnimations.at(i);
776  for (it = propertyAssignmentsForState.begin(); it != propertyAssignmentsForState.end(); ) {
778  QAbstractState *s = it.key();
779  QList<QPropertyAssignment> &assignments = it.value();
780  for (it2 = assignments.begin(); it2 != assignments.end(); ) {
782  ret = initializeAnimation(anim, *it2);
783  QList<QAbstractAnimation*> handlers = ret.first;
784  if (!handlers.isEmpty()) {
785  for (int j = 0; j < handlers.size(); ++j) {
786  QAbstractAnimation *a = handlers.at(j);
787  propertyForAnimation.insert(a, *it2);
789  animationsForState[s].append(a);
790  // ### connect to just the top-level animation?
792  }
793  it2 = assignments.erase(it2);
794  } else {
795  ++it2;
796  }
797  for (int j = 0; j < ret.second.size(); ++j)
799  }
800  if (assignments.isEmpty())
801  it = propertyAssignmentsForState.erase(it);
802  else
803  ++it;
804  }
805  // We require that at least one animation is valid.
806  // ### generalize
808  if (QVariantAnimation *va = qobject_cast<QVariantAnimation*>(anim))
809  variantAnims.append(va);
810 
811  bool hasValidEndValue = false;
812  for (int j = 0; j < variantAnims.size(); ++j) {
813  if (variantAnims.at(j)->endValue().isValid()) {
814  hasValidEndValue = true;
815  break;
816  }
817  }
818 
819  if (hasValidEndValue) {
820  if (anim->state() == QAbstractAnimation::Running) {
821  // The animation is still running. This can happen if the
822  // animation is a group, and one of its children just finished,
823  // and that caused a state to emit its propertiesAssigned() signal, and
824  // that triggered a transition in the machine.
825  // Just stop the animation so it is correctly restarted again.
826  anim->stop();
827  }
828  anim->start();
829  }
830  }
831 #endif // !QT_NO_ANIMATION
832 
833  // Immediately set the properties that are not animated.
834  {
836  for (it = propertyAssignmentsForState.constBegin(); it != propertyAssignmentsForState.constEnd(); ++it) {
837  const QList<QPropertyAssignment> &assignments = it.value();
838  for (int i = 0; i < assignments.size(); ++i) {
839  const QPropertyAssignment &assn = assignments.at(i);
840  assn.object->setProperty(assn.propertyName, assn.value);
841  }
842  }
843  }
844 
845  // Emit propertiesAssigned signal for entered states that have no animated properties.
846  for (int i = 0; i < enteredStates.size(); ++i) {
847  QState *s = toStandardState(enteredStates.at(i));
848  if (s
849 #ifndef QT_NO_ANIMATION
851 #endif
852  )
854  }
855 }
856 
857 #endif // QT_NO_PROPERTIES
858 
860 {
862 }
863 
865 {
866  const QState *ss = toStandardState(s);
867  return ss && (QStatePrivate::get(ss)->childMode == QState::ParallelStates);
868 }
869 
871 {
872  const QState *group = toStandardState(s);
873  if (!group)
874  return false;
875  bool isMachine = QStatePrivate::get(group)->isMachine;
876  // Don't treat the machine as compound if it's a sub-state of this machine
877  if (isMachine && (group != rootState()))
878  return false;
879  return (!isParallel(group) && !QStatePrivate::get(group)->childStates().isEmpty())
880  || isMachine;
881 }
882 
884 {
885  const QState *ss = toStandardState(s);
886  return (ss && QStatePrivate::get(ss)->childStates().isEmpty())
887  || isFinal(s)
888  // Treat the machine as atomic if it's a sub-state of this machine
889  || (ss && QStatePrivate::get(ss)->isMachine && (ss != rootState()));
890 }
891 
892 
894 {
895  Q_ASSERT(state != 0);
896  for (QAbstractState *s = state->parentState(); s != 0; s = s->parentState()) {
897  if (s == other)
898  return true;
899  }
900  return false;
901 }
902 
904 {
905  Q_ASSERT(state != 0);
906  QList<QState*> result;
907  for (QState *s = state->parentState(); s && s != upperBound; s = s->parentState()) {
908  result.append(s);
909  }
910  return result;
911 }
912 
914 {
916  return static_cast<QState*>(state);
917  return 0;
918 }
919 
921 {
923  return static_cast<const QState*>(state);
924  return 0;
925 }
926 
928 {
930  return static_cast<QFinalState*>(state);
931  return 0;
932 }
933 
935 {
937  return static_cast<QHistoryState*>(state);
938  return 0;
939 }
940 
942 {
943  if (isCompound(s)) {
944  QState *grp = toStandardState(s);
946  for (int i = 0; i < lst.size(); ++i) {
947  QAbstractState *cs = lst.at(i);
948  if (isFinal(cs) && configuration.contains(cs))
949  return true;
950  }
951  return false;
952  } else if (isParallel(s)) {
953  QState *grp = toStandardState(s);
955  for (int i = 0; i < lst.size(); ++i) {
956  QAbstractState *cs = lst.at(i);
957  if (!isInFinalState(cs))
958  return false;
959  }
960  return true;
961  }
962  else
963  return false;
964 }
965 
966 #ifndef QT_NO_PROPERTIES
967 
969 {
970  RestorableId id(object, propertyName);
971  if (!registeredRestorables.contains(id))
972  registeredRestorables.insert(id, object->property(propertyName));
973 }
974 
976 {
979  for (it = restorables.constBegin(); it != restorables.constEnd(); ++it) {
980 // qDebug() << "restorable:" << it.key().first << it.key().second << it.value();
981  result.append(QPropertyAssignment(it.key().first, it.key().second, it.value(), /*explicitlySet=*/false));
982  }
983  return result;
984 }
985 
993 bool QStateMachinePrivate::hasRestorable(QObject *object, const QByteArray &propertyName) const
994 {
995  return registeredRestorables.contains(RestorableId(object, propertyName));
996 }
997 
999 {
1000  return registeredRestorables.value(RestorableId(object, propertyName), QVariant());
1001 }
1002 
1003 
1009 {
1010 // qDebug() << "unregisterRestorable(" << object << propertyName << ')';
1011  RestorableId id(object, propertyName);
1012  registeredRestorables.remove(id);
1013 }
1014 
1015 #endif // QT_NO_PROPERTIES
1016 
1018 {
1019  // Find error state recursively in parent hierarchy if not set explicitly for context state
1021  if (context != 0) {
1022  QState *s = toStandardState(context);
1023  if (s != 0)
1024  errorState = s->errorState();
1025 
1026  if (errorState == 0)
1027  errorState = findErrorState(context->parentState());
1028  }
1029 
1030  return errorState;
1031 }
1032 
1034 {
1035  Q_Q(QStateMachine);
1036 
1037  error = errorCode;
1038  switch (errorCode) {
1040  Q_ASSERT(currentContext != 0);
1041 
1042  errorString = QStateMachine::tr("Missing initial state in compound state '%1'")
1043  .arg(currentContext->objectName());
1044 
1045  break;
1047  Q_ASSERT(currentContext != 0);
1048 
1049  errorString = QStateMachine::tr("Missing default state in history state '%1'")
1050  .arg(currentContext->objectName());
1051  break;
1052 
1054  Q_ASSERT(currentContext != 0);
1055 
1056  errorString = QStateMachine::tr("No common ancestor for targets and source of transition from state '%1'")
1057  .arg(currentContext->objectName());
1058  break;
1059  default:
1060  errorString = QStateMachine::tr("Unknown error");
1061  };
1062 
1065 
1066  QAbstractState *currentErrorState = findErrorState(currentContext);
1067 
1068  // Avoid infinite loop if the error state itself has an error
1069  if (currentContext == currentErrorState)
1070  currentErrorState = 0;
1071 
1072  Q_ASSERT(currentErrorState != rootState());
1073 
1074  if (currentErrorState != 0) {
1075  QState *lca = findLCA(QList<QAbstractState*>() << currentErrorState << currentContext);
1077  } else {
1078  qWarning("Unrecoverable error detected in running state machine: %s",
1080  q->stop();
1081  }
1082 }
1083 
1084 #ifndef QT_NO_ANIMATION
1085 
1088  const QPropertyAssignment &prop)
1089 {
1090  QList<QAbstractAnimation*> handledAnimations;
1091  QList<QAbstractAnimation*> localResetEndValues;
1092  QAnimationGroup *group = qobject_cast<QAnimationGroup*>(abstractAnimation);
1093  if (group) {
1094  for (int i = 0; i < group->animationCount(); ++i) {
1095  QAbstractAnimation *animationChild = group->animationAt(i);
1097  ret = initializeAnimation(animationChild, prop);
1098  handledAnimations << ret.first;
1099  localResetEndValues << ret.second;
1100  }
1101  } else {
1102  QPropertyAnimation *animation = qobject_cast<QPropertyAnimation *>(abstractAnimation);
1103  if (animation != 0
1104  && prop.object == animation->targetObject()
1105  && prop.propertyName == animation->propertyName()) {
1106 
1107  // Only change end value if it is undefined
1108  if (!animation->endValue().isValid()) {
1109  animation->setEndValue(prop.value);
1110  localResetEndValues.append(animation);
1111  }
1112  handledAnimations.append(animation);
1113  }
1114  }
1115  return qMakePair(handledAnimations, localResetEndValues);
1116 }
1117 
1119 {
1120  Q_Q(QStateMachine);
1121  QAbstractAnimation *anim = qobject_cast<QAbstractAnimation*>(q->sender());
1122  Q_ASSERT(anim != 0);
1123  QObject::disconnect(anim, SIGNAL(finished()), q, SLOT(_q_animationFinished()));
1124  if (resetAnimationEndValues.contains(anim)) {
1125  qobject_cast<QVariantAnimation*>(anim)->setEndValue(QVariant()); // ### generalize
1127  }
1128 
1129 #ifndef QT_NO_PROPERTIES
1130  // Set the final property value.
1132  Q_ASSERT(assn.object != 0);
1133  assn.object->setProperty(assn.propertyName, assn.value);
1134  if (!assn.explicitlySet)
1136 #endif
1137 
1139  Q_ASSERT(state != 0);
1141  it = animationsForState.find(state);
1142  Q_ASSERT(it != animationsForState.end());
1143  QList<QAbstractAnimation*> &animations = it.value();
1144  animations.removeOne(anim);
1145  if (animations.isEmpty()) {
1148  }
1149 }
1150 
1151 #endif // !QT_NO_ANIMATION
1152 
1153 namespace {
1154 
1155 class StartState : public QState
1156 {
1157 public:
1158  StartState(QState *parent)
1159  : QState(parent) {}
1160 protected:
1161  void onEntry(QEvent *) {}
1162  void onExit(QEvent *) {}
1163 };
1164 
1165 class InitialTransition : public QAbstractTransition
1166 {
1167 public:
1168  InitialTransition(QAbstractState *target)
1170  { setTargetState(target); }
1171 protected:
1172  virtual bool eventTest(QEvent *) { return true; }
1173  virtual void onTransition(QEvent *) {}
1174 };
1175 
1176 } // namespace
1177 
1179 {
1180  Q_Q(QStateMachine);
1181  if (_startState == 0)
1182  _startState = new StartState(q);
1183  return _startState;
1184 }
1185 
1187 {
1188  delete _startState;
1189  _startState = 0;
1190 }
1191 
1193 {
1194  Q_Q(QStateMachine);
1195  QList<QHistoryState*> historyStates = q->findChildren<QHistoryState*>();
1196  for (int i = 0; i < historyStates.size(); ++i) {
1197  QHistoryState *h = historyStates.at(i);
1199  }
1200 }
1201 
1203 {
1204  Q_Q(QStateMachine);
1205  Q_ASSERT(state == Starting);
1206  Q_ASSERT(rootState() != 0);
1207  QAbstractState *initial = rootState()->initialState();
1208  configuration.clear();
1213  clearHistory();
1214 
1215 #ifdef QSTATEMACHINE_DEBUG
1216  qDebug() << q << ": starting";
1217 #endif
1218  state = Running;
1219  processingScheduled = true; // we call _q_process() below
1220  emit q->started();
1221 
1222  QState *start = startState();
1223  Q_ASSERT(start != 0);
1224 
1226 
1227  // If a transition has already been added, then we skip this step, as the
1228  // initial transition in that case has been overridden.
1229  if (transitions.isEmpty()) {
1230  QAbstractTransition *initialTransition = new InitialTransition(initial);
1231  start->addTransition(initialTransition);
1232  transitions.append(initialTransition);
1233  }
1234 
1235  QEvent nullEvent(QEvent::None);
1236  executeTransitionContent(&nullEvent, transitions);
1237  QList<QAbstractState*> enteredStates = enterStates(&nullEvent, transitions);
1238 #ifndef QT_NO_PROPERTIES
1239  applyProperties(transitions, QList<QAbstractState*>() << start,
1240  enteredStates);
1241 #endif
1242  removeStartState();
1243 
1244 #ifdef QSTATEMACHINE_DEBUG
1245  qDebug() << q << ": initial configuration:" << configuration;
1246 #endif
1247  _q_process();
1248 }
1249 
1251 {
1252  Q_Q(QStateMachine);
1253  Q_ASSERT(state == Running);
1254  Q_ASSERT(!processing);
1255  processing = true;
1256  processingScheduled = false;
1257 #ifdef QSTATEMACHINE_DEBUG
1258  qDebug() << q << ": starting the event processing loop";
1259 #endif
1260  while (processing) {
1261  if (stop) {
1262  processing = false;
1263  break;
1264  }
1265  QSet<QAbstractTransition*> enabledTransitions;
1266  QEvent *e = new QEvent(QEvent::None);
1267  enabledTransitions = selectTransitions(e);
1268  if (enabledTransitions.isEmpty()) {
1269  delete e;
1270  e = 0;
1271  }
1272  if (enabledTransitions.isEmpty() && ((e = dequeueInternalEvent()) != 0)) {
1273 #ifdef QSTATEMACHINE_DEBUG
1274  qDebug() << q << ": dequeued internal event" << e << "of type" << e->type();
1275 #endif
1276  enabledTransitions = selectTransitions(e);
1277  if (enabledTransitions.isEmpty()) {
1278  delete e;
1279  e = 0;
1280  }
1281  }
1282  if (enabledTransitions.isEmpty()) {
1283  if ((e = dequeueExternalEvent()) != 0) {
1284 #ifdef QSTATEMACHINE_DEBUG
1285  qDebug() << q << ": dequeued external event" << e << "of type" << e->type();
1286 #endif
1287  enabledTransitions = selectTransitions(e);
1288  if (enabledTransitions.isEmpty()) {
1289  delete e;
1290  e = 0;
1291  }
1292  } else {
1293  if (isInternalEventQueueEmpty()) {
1294  processing = false;
1296  }
1297  }
1298  }
1299  if (!enabledTransitions.isEmpty()) {
1300  q->beginMicrostep(e);
1301  microstep(e, enabledTransitions.toList());
1302  q->endMicrostep(e);
1303  }
1304 #ifdef QSTATEMACHINE_DEBUG
1305  else {
1306  qDebug() << q << ": no transitions enabled";
1307  }
1308 #endif
1309  delete e;
1310  }
1311 #ifdef QSTATEMACHINE_DEBUG
1312  qDebug() << q << ": finished the event processing loop";
1313 #endif
1314  if (stop) {
1315  stop = false;
1317  }
1318 
1319  switch (stopProcessingReason) {
1320  case EventQueueEmpty:
1321  break;
1322  case Finished:
1323  state = NotRunning;
1326  emit q->finished();
1327  break;
1328  case Stopped:
1329  state = NotRunning;
1332  emit q->stopped();
1333  break;
1334  }
1335 }
1336 
1338 {
1341 }
1342 
1344 {
1347 }
1348 
1350 {
1353  return 0;
1354  return internalEventQueue.takeFirst();
1355 }
1356 
1358 {
1361  return 0;
1362  return externalEventQueue.takeFirst();
1363 }
1364 
1366 {
1368  return internalEventQueue.isEmpty();
1369 }
1370 
1372 {
1374  return externalEventQueue.isEmpty();
1375 }
1376 
1378 {
1379  Q_Q(QStateMachine);
1381  return;
1382  switch (processingMode) {
1383  case DirectProcessing:
1384  if (QThread::currentThread() == q->thread()) {
1385  _q_process();
1386  break;
1387  } // fallthrough -- processing must be done in the machine thread
1388  case QueuedProcessing:
1389  processingScheduled = true;
1391  break;
1392  }
1393 }
1394 
1396 {
1397  Q_Q(QStateMachine);
1400  for (it = delayedEvents.constBegin(); it != delayedEvents.constEnd(); ++it) {
1401  int id = it.key();
1402  QEvent *e = it.value();
1403  q->killTimer(id);
1404  delete e;
1405  }
1406  delayedEvents.clear();
1407 }
1408 
1410 
1412 {
1413 public:
1416  { setTargetState(target); }
1417 protected:
1418  void onTransition(QEvent *) { deleteLater(); }
1419  bool eventTest(QEvent *) { return true; }
1420 };
1421 
1422 } // namespace
1423 // mingw compiler tries to export QObject::findChild<GoToStateTransition>(),
1424 // which doesn't work if its in an anonymous namespace.
1425 using namespace _QStateMachine_Internal;
1441 {
1442  if (!targetState) {
1443  qWarning("QStateMachine::goToState(): cannot go to null state");
1444  return;
1445  }
1446 
1447  if (configuration.contains(targetState))
1448  return;
1449 
1450  QState *sourceState = 0;
1451  if (state == Running) {
1453  for (it = configuration.constBegin(); it != configuration.constEnd(); ++it) {
1454  sourceState = toStandardState(*it);
1455  if (sourceState != 0)
1456  break;
1457  }
1458  } else {
1459  sourceState = startState();
1460  }
1461 
1462  Q_ASSERT(sourceState != 0);
1463  // Reuse previous GoToStateTransition in case of several calls to
1464  // goToState() in a row.
1465  GoToStateTransition *trans = sourceState->findChild<GoToStateTransition*>();
1466  if (!trans) {
1467  trans = new GoToStateTransition(targetState);
1468  sourceState->addTransition(trans);
1469  } else {
1470  trans->setTargetState(targetState);
1471  }
1472 
1474 }
1475 
1477 {
1478  QState *group = toStandardState(state);
1479  if (!group)
1480  return;
1482  for (int i = 0; i < transitions.size(); ++i) {
1483  QAbstractTransition *t = transitions.at(i);
1484  if (QSignalTransition *st = qobject_cast<QSignalTransition*>(t)) {
1486  }
1487 #ifndef QT_NO_STATEMACHINE_EVENTFILTER
1488  else if (QEventTransition *oet = qobject_cast<QEventTransition*>(t)) {
1490  }
1491 #endif
1492  }
1493 }
1494 
1496 {
1497  if (QSignalTransition *st = qobject_cast<QSignalTransition*>(transition)) {
1499  }
1500 #ifndef QT_NO_STATEMACHINE_EVENTFILTER
1501  else if (QEventTransition *oet = qobject_cast<QEventTransition*>(transition)) {
1503  }
1504 #endif
1505 }
1506 
1508 {
1509  Q_Q(QStateMachine);
1510  if (QSignalTransitionPrivate::get(transition)->signalIndex != -1)
1511  return; // already registered
1512  QObject *sender = QSignalTransitionPrivate::get(transition)->sender;
1513  if (!sender)
1514  return;
1515  QByteArray signal = QSignalTransitionPrivate::get(transition)->signal;
1516  if (signal.startsWith('0'+QSIGNAL_CODE))
1517  signal.remove(0, 1);
1518  const QMetaObject *meta = sender->metaObject();
1519  int signalIndex = meta->indexOfSignal(signal);
1520  int originalSignalIndex = signalIndex;
1521  if (signalIndex == -1) {
1522  signalIndex = meta->indexOfSignal(QMetaObject::normalizedSignature(signal));
1523  if (signalIndex == -1) {
1524  qWarning("QSignalTransition: no such signal: %s::%s",
1525  meta->className(), signal.constData());
1526  return;
1527  }
1528  }
1529  // The signal index we actually want to connect to is the one
1530  // that is going to be sent, i.e. the non-cloned original index.
1531  while (meta->method(signalIndex).attributes() & QMetaMethod::Cloned)
1532  --signalIndex;
1533 
1534  QVector<int> &connectedSignalIndexes = connections[sender];
1535  if (connectedSignalIndexes.size() <= signalIndex)
1536  connectedSignalIndexes.resize(signalIndex+1);
1537  if (connectedSignalIndexes.at(signalIndex) == 0) {
1538  if (!signalEventGenerator)
1540  bool ok = QMetaObject::connect(sender, signalIndex, signalEventGenerator,
1542  if (!ok) {
1543 #ifdef QSTATEMACHINE_DEBUG
1544  qDebug() << q << ": FAILED to add signal transition from" << transition->sourceState()
1545  << ": ( sender =" << sender << ", signal =" << signal
1546  << ", targets =" << transition->targetStates() << ')';
1547 #endif
1548  return;
1549  }
1550  }
1551  ++connectedSignalIndexes[signalIndex];
1553  QSignalTransitionPrivate::get(transition)->originalSignalIndex = originalSignalIndex;
1554 #ifdef QSTATEMACHINE_DEBUG
1555  qDebug() << q << ": added signal transition from" << transition->sourceState()
1556  << ": ( sender =" << sender << ", signal =" << signal
1557  << ", targets =" << transition->targetStates() << ')';
1558 #endif
1559 }
1560 
1562 {
1564  if (signalIndex == -1)
1565  return; // not registered
1566  QSignalTransitionPrivate::get(transition)->signalIndex = -1;
1567  const QObject *sender = QSignalTransitionPrivate::get(transition)->sender;
1568  QVector<int> &connectedSignalIndexes = connections[sender];
1569  Q_ASSERT(connectedSignalIndexes.size() > signalIndex);
1570  Q_ASSERT(connectedSignalIndexes.at(signalIndex) != 0);
1571  if (--connectedSignalIndexes[signalIndex] == 0) {
1573  QMetaObject::disconnect(sender, signalIndex, signalEventGenerator,
1575  int sum = 0;
1576  for (int i = 0; i < connectedSignalIndexes.size(); ++i)
1577  sum += connectedSignalIndexes.at(i);
1578  if (sum == 0)
1579  connections.remove(sender);
1580  }
1581 }
1582 
1584 {
1585  Q_Q(QStateMachine);
1586  {
1588  for (int i = 0; i < transitions.size(); ++i) {
1589  QSignalTransition *t = transitions.at(i);
1590  if (t->machine() == q)
1592  }
1593  }
1594  {
1596  for (int i = 0; i < transitions.size(); ++i) {
1597  QEventTransition *t = transitions.at(i);
1598  if (t->machine() == q)
1600  }
1601  }
1602 }
1603 
1604 #ifndef QT_NO_STATEMACHINE_EVENTFILTER
1606 {
1607  Q_Q(QStateMachine);
1608  if (QEventTransitionPrivate::get(transition)->registered)
1609  return;
1610  if (transition->eventType() >= QEvent::User) {
1611  qWarning("QObject event transitions are not supported for custom types");
1612  return;
1613  }
1614  QObject *object = QEventTransitionPrivate::get(transition)->object;
1615  if (!object)
1616  return;
1617  QObjectPrivate *od = QObjectPrivate::get(object);
1618  if (!od->eventFilters.contains(q))
1619  object->installEventFilter(q);
1620  ++qobjectEvents[object][transition->eventType()];
1621  QEventTransitionPrivate::get(transition)->registered = true;
1622 #ifdef QSTATEMACHINE_DEBUG
1623  qDebug() << q << ": added event transition from" << transition->sourceState()
1624  << ": ( object =" << object << ", event =" << transition->eventType()
1625  << ", targets =" << transition->targetStates() << ')';
1626 #endif
1627 }
1628 
1630 {
1631  Q_Q(QStateMachine);
1632  if (!QEventTransitionPrivate::get(transition)->registered)
1633  return;
1634  QObject *object = QEventTransitionPrivate::get(transition)->object;
1635  QHash<QEvent::Type, int> &events = qobjectEvents[object];
1636  Q_ASSERT(events.value(transition->eventType()) > 0);
1637  if (--events[transition->eventType()] == 0) {
1638  events.remove(transition->eventType());
1639  int sum = 0;
1641  for (it = events.constBegin(); it != events.constEnd(); ++it)
1642  sum += it.value();
1643  if (sum == 0) {
1644  qobjectEvents.remove(object);
1645  object->removeEventFilter(q);
1646  }
1647  }
1648  QEventTransitionPrivate::get(transition)->registered = false;
1649 }
1650 
1652 {
1653  if (qobjectEvents.value(watched).contains(event->type())) {
1656  }
1657 }
1658 #endif
1659 
1661  void **argv)
1662 {
1663  Q_ASSERT(connections[sender].at(signalIndex) != 0);
1664  const QMetaObject *meta = sender->metaObject();
1665  QMetaMethod method = meta->method(signalIndex);
1666  QList<QByteArray> parameterTypes = method.parameterTypes();
1667  int argc = parameterTypes.count();
1668  QList<QVariant> vargs;
1669  for (int i = 0; i < argc; ++i) {
1670  int type = QMetaType::type(parameterTypes.at(i));
1671  vargs.append(QVariant(type, argv[i+1]));
1672  }
1673 
1674 #ifdef QSTATEMACHINE_DEBUG
1675  qDebug() << q_func() << ": sending signal event ( sender =" << sender
1676  << ", signal =" << sender->metaObject()->method(signalIndex).signature() << ')';
1677 #endif
1678  postInternalEvent(new QStateMachine::SignalEvent(sender, signalIndex, vargs));
1680 }
1681 
1686  : QState(*new QStateMachinePrivate, /*parentState=*/0)
1687 {
1688  // Can't pass the parent to the QState constructor, as it expects a QState
1689  // But this works as expected regardless of whether parent is a QState or not
1690  setParent(parent);
1691 }
1692 
1697  : QState(dd, /*parentState=*/0)
1698 {
1699  setParent(parent);
1700 }
1701 
1706 {
1707 }
1708 
1783 {
1784  Q_D(const QStateMachine);
1785  return d->error;
1786 }
1787 
1792 {
1793  Q_D(const QStateMachine);
1794  return d->errorString;
1795 }
1796 
1801 {
1802  Q_D(QStateMachine);
1803  d->errorString.clear();
1804  d->error = NoError;
1805 }
1806 
1813 {
1814  Q_D(const QStateMachine);
1815  return d->globalRestorePolicy;
1816 }
1817 
1825 {
1826  Q_D(QStateMachine);
1827  d->globalRestorePolicy = restorePolicy;
1828 }
1829 
1840 {
1841  if (!state) {
1842  qWarning("QStateMachine::addState: cannot add null state");
1843  return;
1844  }
1845  if (QAbstractStatePrivate::get(state)->machine() == this) {
1846  qWarning("QStateMachine::addState: state has already been added to this machine");
1847  return;
1848  }
1849  state->setParent(this);
1850 }
1851 
1859 {
1860  if (!state) {
1861  qWarning("QStateMachine::removeState: cannot remove null state");
1862  return;
1863  }
1864  if (QAbstractStatePrivate::get(state)->machine() != this) {
1865  qWarning("QStateMachine::removeState: state %p's machine (%p)"
1866  " is different from this machine (%p)",
1867  state, QAbstractStatePrivate::get(state)->machine(), this);
1868  return;
1869  }
1870  state->setParent(0);
1871 }
1872 
1879 {
1880  Q_D(const QStateMachine);
1881  return (d->state == QStateMachinePrivate::Running);
1882 }
1883 
1896 {
1897  Q_D(QStateMachine);
1898 
1899  if (initialState() == 0) {
1900  qWarning("QStateMachine::start: No initial state set for machine. Refusing to start.");
1901  return;
1902  }
1903 
1904  switch (d->state) {
1908  break;
1910  break;
1912  qWarning("QStateMachine::start(): already running");
1913  break;
1914  }
1915 }
1916 
1924 {
1925  Q_D(QStateMachine);
1926  switch (d->state) {
1928  break;
1930  // the machine will exit as soon as it enters the event processing loop
1931  d->stop = true;
1932  break;
1934  d->stop = true;
1935  d->processEvents(QStateMachinePrivate::QueuedProcessing);
1936  break;
1937  }
1938 }
1939 
1958 {
1959  Q_D(QStateMachine);
1960  if (d->state != QStateMachinePrivate::Running) {
1961  qWarning("QStateMachine::postEvent: cannot post event when the state machine is not running");
1962  return;
1963  }
1964  if (!event) {
1965  qWarning("QStateMachine::postEvent: cannot post null event");
1966  return;
1967  }
1968 #ifdef QSTATEMACHINE_DEBUG
1969  qDebug() << this << ": posting event" << event;
1970 #endif
1971  switch (priority) {
1972  case NormalPriority:
1973  d->postExternalEvent(event);
1974  break;
1975  case HighPriority:
1976  d->postInternalEvent(event);
1977  break;
1978  }
1979  d->processEvents(QStateMachinePrivate::QueuedProcessing);
1980 }
1981 
2002 {
2003  Q_D(QStateMachine);
2004  if (d->state != QStateMachinePrivate::Running) {
2005  qWarning("QStateMachine::postDelayedEvent: cannot post event when the state machine is not running");
2006  return -1;
2007  }
2008  if (!event) {
2009  qWarning("QStateMachine::postDelayedEvent: cannot post null event");
2010  return -1;
2011  }
2012  if (delay < 0) {
2013  qWarning("QStateMachine::postDelayedEvent: delay cannot be negative");
2014  return -1;
2015  }
2016 #ifdef QSTATEMACHINE_DEBUG
2017  qDebug() << this << ": posting event" << event << "with delay" << delay;
2018 #endif
2019  QMutexLocker locker(&d->delayedEventsMutex);
2020  int tid = startTimer(delay);
2021  d->delayedEvents[tid] = event;
2022  return tid;
2023 }
2024 
2038 {
2039  Q_D(QStateMachine);
2040  if (d->state != QStateMachinePrivate::Running) {
2041  qWarning("QStateMachine::cancelDelayedEvent: the machine is not running");
2042  return false;
2043  }
2044  QMutexLocker locker(&d->delayedEventsMutex);
2045  QEvent *e = d->delayedEvents.take(id);
2046  if (!e)
2047  return false;
2048  killTimer(id);
2049  delete e;
2050  return true;
2051 }
2052 
2061 {
2062  Q_D(const QStateMachine);
2063  return d->configuration;
2064 }
2065 
2093 {
2094  Q_D(QStateMachine);
2095  if (e->type() == QEvent::Timer) {
2096  QTimerEvent *te = static_cast<QTimerEvent*>(e);
2097  int tid = te->timerId();
2098  if (d->state != QStateMachinePrivate::Running) {
2099  // This event has been cancelled already
2100  QMutexLocker locker(&d->delayedEventsMutex);
2101  Q_ASSERT(!d->delayedEvents.contains(tid));
2102  return true;
2103  }
2104  d->delayedEventsMutex.lock();
2105  QEvent *ee = d->delayedEvents.take(tid);
2106  if (ee != 0) {
2107  killTimer(tid);
2108  d->delayedEventsMutex.unlock();
2109  d->postExternalEvent(ee);
2110  d->processEvents(QStateMachinePrivate::DirectProcessing);
2111  return true;
2112  } else {
2113  d->delayedEventsMutex.unlock();
2114  }
2115  }
2116  return QState::event(e);
2117 }
2118 
2119 #ifndef QT_NO_STATEMACHINE_EVENTFILTER
2120 
2124 {
2125  Q_D(QStateMachine);
2126  d->handleFilteredEvent(watched, event);
2127  return false;
2128 }
2129 #endif
2130 
2143 {
2144  Q_UNUSED(event);
2145 }
2146 
2159 {
2160  Q_UNUSED(event);
2161 }
2162 
2174 {
2175  Q_UNUSED(event);
2176 }
2177 
2190 {
2191  Q_UNUSED(event);
2192 }
2193 
2202 {
2203  start();
2204  QState::onEntry(event);
2205 }
2206 
2216 {
2217  stop();
2218  QState::onExit(event);
2219 }
2220 
2221 #ifndef QT_NO_ANIMATION
2222 
2227 {
2228  Q_D(const QStateMachine);
2229  return d->animated;
2230 }
2231 
2236 {
2237  Q_D(QStateMachine);
2238  d->animated = enabled;
2239 }
2240 
2245 {
2246  Q_D(QStateMachine);
2247  d->defaultAnimations.append(animation);
2248 }
2249 
2254 {
2255  Q_D(const QStateMachine);
2256  return d->defaultAnimations;
2257 }
2258 
2263 {
2264  Q_D(QStateMachine);
2265  d->defaultAnimations.removeAll(animation);
2266 }
2267 
2268 #endif // QT_NO_ANIMATION
2269 
2270 
2272 
2273  // content:
2274  2, // revision
2275  0, // classname
2276  0, 0, // classinfo
2277  1, 12, // methods
2278  0, 0, // properties
2279  0, 0, // enums/sets
2280  0, 0, // constructors
2281 
2282  // slots: signature, parameters, type, tag, flags
2283  23, 22, 22, 22, 0x0a,
2284 
2285  0 // eod
2286 };
2287 
2289  "QSignalEventGenerator\0\0execute()\0"
2290 };
2291 
2295 };
2296 
2298 {
2299  return &staticMetaObject;
2300 }
2301 
2302 void *QSignalEventGenerator::qt_metacast(const char *_clname)
2303 {
2304  if (!_clname) return 0;
2305  if (!strcmp(_clname, qt_meta_stringdata_QSignalEventGenerator))
2306  return static_cast<void*>(const_cast< QSignalEventGenerator*>(this));
2307  return QObject::qt_metacast(_clname);
2308 }
2309 
2311 {
2312  _id = QObject::qt_metacall(_c, _id, _a);
2313  if (_id < 0)
2314  return _id;
2315  if (_c == QMetaObject::InvokeMetaMethod) {
2316  switch (_id) {
2317  case 0: {
2318 // ### in Qt 4.6 we can use QObject::senderSignalIndex()
2319  QObjectPrivate *d = static_cast<QObjectPrivate *>(d_ptr.data());
2320  int signalIndex = -1;
2321  QObject *sender = this->sender();
2322  if (sender && d->currentSender)
2323  signalIndex = d->currentSender->signal;
2324 
2325  Q_ASSERT(signalIndex != -1);
2327  QStateMachinePrivate::get(machine)->handleTransitionSignal(sender, signalIndex, _a);
2328  break;
2329  }
2330  default: ;
2331  }
2332  _id -= 1;
2333  }
2334  return _id;
2335 }
2336 
2338  : QObject(parent)
2339 {
2340 }
2341 
2374  const QList<QVariant> &arguments)
2375  : QEvent(QEvent::StateMachineSignal), m_sender(sender),
2376  m_signalIndex(signalIndex), m_arguments(arguments)
2377 {
2378 }
2379 
2384 {
2385 }
2386 
2453  : QEvent(QEvent::StateMachineWrapped), m_object(object), m_event(event)
2454 {
2455 }
2456 
2461 {
2462  delete m_event;
2463 }
2464 
2484 
2485 #include "moc_qstatemachine.cpp"
2486 
2487 #endif //QT_NO_STATEMACHINE
The QVariant class acts like a union for the most common Qt data types.
Definition: qvariant.h:92
T qobject_cast(QObject *object)
Definition: qobject.h:375
int startTimer(int interval)
Starts a timer and returns a timer identifier, or returns zero if it could not start a timer...
Definition: qobject.cpp:1623
void removeState(QAbstractState *state)
Removes the given state from this state machine.
void callOnEntry(QEvent *e)
QAbstractState * findErrorState(QAbstractState *context)
double d
Definition: qnumeric_p.h:62
The QMetaObject class contains meta-information about Qt objects.
Definition: qobjectdefs.h:304
QVariant endValue
the end value of the animation
QSignalEventGenerator(QStateMachine *parent)
QStateMachine::RestorePolicy globalRestorePolicy
The QHash::const_iterator class provides an STL-style const iterator for QHash and QMultiHash...
Definition: qhash.h:395
static QEventTransitionPrivate * get(QEventTransition *q)
The QPropertyAnimation class animates Qt properties.
QAbstractAnimation * animationAt(int index) const
Returns a pointer to the animation at index in this group.
int type
Definition: qmetatype.cpp:239
void onEntry(QEvent *event)
Reimplemented Function
Definition: qstate.cpp:446
The WrappedEvent class inherits QEvent and holds a clone of an event associated with a QObject...
Definition: qstatemachine.h:92
unsigned char c[8]
Definition: qnumeric_p.h:62
static bool connect(const QObject *sender, int signal_index, const QObject *receiver, int method_index, int type=0, int *types=0)
Definition: qobject.cpp:3194
QStateMachine::Error error
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
QState * parentState() const
Returns this state&#39;s parent state, or 0 if the state has no parent state.
static const QMetaObject staticMetaObject
EventRef event
static QByteArray normalizedSignature(const char *method)
Normalizes the signature of the given method.
QPair< QList< QAbstractAnimation * >, QList< QAbstractAnimation * > > initializeAnimation(QAbstractAnimation *abstractAnimation, const QPropertyAssignment &prop)
QStateMachine * machine() const
Returns the state machine that this state is part of, or 0 if the state is not part of a state machin...
void clear()
Removes all items from the hash.
Definition: qhash.h:574
int remove(const Key &key)
Removes all the items that have the key from the hash.
Definition: qhash.h:784
The QAbstractTransition class is the base class of transitions between QAbstractState objects...
virtual int qt_metacall(QMetaObject::Call, int, void **argv)
T * data() const
Returns the value of the pointer referenced by this object.
QList< QAbstractState * > targetStates
the target states of this transition
The QStateMachine class provides a hierarchical finite state machine.
Definition: qstatemachine.h:63
#define it(className, varName)
static bool stateEntryLessThan(QAbstractState *s1, QAbstractState *s2)
static const char qt_meta_stringdata_QSignalEventGenerator[]
void unregisterSignalTransition(QSignalTransition *transition)
void removeDefaultAnimation(QAbstractAnimation *animation)
Removes animation from the list of default animations.
void postInternalEvent(QEvent *e)
#define at(className, varName)
bool remove(const T &value)
Definition: qset.h:89
const_iterator constEnd() const
Definition: qset.h:171
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:135
bool isEmpty() const
Definition: qset.h:77
#define SLOT(a)
Definition: qobjectdefs.h:226
T1 first
Definition: qpair.h:65
void setGlobalRestorePolicy(QStateMachine::RestorePolicy restorePolicy)
Sets the restore policy of the state machine to restorePolicy.
bool setProperty(const char *name, const QVariant &value)
Sets the value of the object&#39;s name property to value.
Definition: qobject.cpp:3755
static bool isDescendantOf(const QAbstractState *s, const QAbstractState *other)
T2 second
Definition: qpair.h:66
iterator begin()
Returns an STL-style iterator pointing to the first item in the list.
Definition: qlist.h:267
QPair< QObject *, QByteArray > RestorableId
int animationCount() const
Returns the number of animations managed by this group.
void postExternalEvent(QEvent *e)
int postDelayedEvent(QEvent *event, int delay)
Posts the given event for processing by this state machine, with the given delay in milliseconds...
StopProcessingReason stopProcessingReason
QVariant endValue() const
bool hasRestorable(QObject *object, const QByteArray &propertyName) const
Returns true if the variable with the given id has been registered for restoration.
static const QMetaObject staticMetaObject
This variable stores the meta-object for the class.
Definition: qobject.h:128
QVariant value
Definition: qstate_p.h:74
void start(QAbstractAnimation::DeletionPolicy policy=KeepWhenStopped)
Starts the animation.
QMultiHash< QAbstractState *, QAbstractAnimation * > defaultAnimationsForTarget
static QString tr(const char *sourceText, const char *comment=0, int n=-1)
QState::ChildMode childMode
Definition: qstate_p.h:101
long ASN1_INTEGER_get ASN1_INTEGER * a
int count(const T &t) const
Returns the number of occurrences of value in the list.
Definition: qlist.h:891
QHistoryState::HistoryType historyType
QSet< QAbstractState * > configuration
The QString class provides a Unicode character string.
Definition: qstring.h:83
T * qobject_cast(QObject *object)
Definition: qobject.h:375
void setEndValue(const QVariant &value)
T take(const Key &key)
Removes the item with the key from the hash and returns the value associated with it...
Definition: qhash.h:807
The QHash class is a template class that provides a hash-table-based dictionary.
Definition: qdatastream.h:66
void onTransition(QEvent *)
This function is called when the transition is triggered.
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
The QObject class is the base class of all Qt objects.
Definition: qobject.h:111
bool startsWith(const QByteArray &a) const
Returns true if this byte array starts with byte array ba; otherwise returns false.
Sender * currentSender
Definition: qobject_p.h:200
void start()
Starts this state machine.
QEvent::Type eventType
the type of event that this event transition is associated with
static const uint qt_meta_data_QSignalEventGenerator[]
#define Q_D(Class)
Definition: qglobal.h:2482
~QStateMachine()
Destroys this state machine.
QObject * object
Definition: qstate_p.h:72
void handleTransitionSignal(QObject *sender, int signalIndex, void **args)
QObject * targetObject
the target QObject for this animation.
void clearError()
Clears the error string and error code of the state machine.
void addStatesToEnter(QAbstractState *s, QState *root, QSet< QAbstractState *> &statesToEnter, QSet< QAbstractState *> &statesForDefaultEntry)
bool contains(const Key &key) const
Returns true if the hash contains an item with the key; otherwise returns false.
Definition: qhash.h:872
State state
state of the animation.
static QObjectPrivate * get(QObject *o)
Definition: qobject_p.h:177
static QEvent * cloneEvent(QEvent *e)
const T value(const Key &key) const
Returns the value associated with the key.
Definition: qhash.h:606
The QState class provides a general-purpose state for QStateMachine.
Definition: qstate.h:61
void stop()
Stops the animation.
void registerTransitions(QAbstractState *state)
void addState(QAbstractState *state)
Adds the given state to this state machine.
bool isEmpty() const
Returns true if the list contains no items; otherwise returns false.
Definition: qlist.h:152
void resize(int size)
Sets the size of the vector to size.
Definition: qvector.h:342
iterator insert(const Key &key, const T &value)
Inserts a new item with the key and a value of value.
Definition: qhash.h:753
void setParent(QObject *)
Makes the object a child of parent.
Definition: qobject.cpp:1950
QObject * sender() const
Returns a pointer to the object that sent the signal, if called in a slot activated by a signal; othe...
Definition: qobject.cpp:2327
void processEvents(EventProcessingMode processingMode)
QHash< QObject *, QHash< QEvent::Type, int > > qobjectEvents
#define Q_Q(Class)
Definition: qglobal.h:2483
QList< QAbstractState * > targetStates() const
const QStateMachinePrivate::Handler qt_kernel_statemachine_handler
const Key & key() const
Returns the current item&#39;s key.
Definition: qhash.h:419
QList< QAbstractAnimation * > animations() const
Returns the list of animations associated with this transition, or an empty list if it has no animati...
QList< QPointer< QObject > > eventFilters
Definition: qobject_p.h:211
QAnimationGroup * group() const
If this animation is part of a QAnimationGroup, this function returns a pointer to the group; otherwi...
Q_CORE_EXPORT void qDebug(const char *,...)
virtual const QMetaObject * metaObject() const
Returns a pointer to the meta-object of this object.
void unregisterEventTransition(QEventTransition *transition)
QList< QAbstractState * > configuration
#define SIGNAL(a)
Definition: qobjectdefs.h:227
void goToState(QAbstractState *targetState)
Causes this state machine to unconditionally transition to the given targetState. ...
QAbstractState * defaultState
static QThread * currentThread()
Returns a pointer to a QThread which manages the currently executing thread.
Definition: qthread.cpp:419
void append(const T &t)
Inserts value at the end of the list.
Definition: qlist.h:507
void registerSignalTransition(QSignalTransition *transition)
static QHistoryStatePrivate * get(QHistoryState *q)
RestorePolicy
This enum specifies the restore policy type.
Error error() const
Returns the error code of the last error that occurred in the state machine.
bool eventFilter(QObject *watched, QEvent *event)
Reimplemented Function
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
static QStateMachinePrivate * get(QStateMachine *q)
void setError(QStateMachine::Error error, QAbstractState *currentContext)
QBool contains(const T &t) const
Returns true if the list contains an occurrence of value; otherwise returns false.
Definition: qlist.h:880
static bool isEmpty(const char *str)
The QEventTransition class provides a QObject-specific transition for Qt events.
virtual void beginSelectTransitions(QEvent *event)
This function is called when the state machine is about to select transitions based on the given even...
QHash< QAbstractAnimation *, QPropertyAssignment > propertyForAnimation
int methodOffset() const
Returns the method offset for this class; i.e.
QSet< QAbstractState * > pendingErrorStates
The QAbstractState class is the base class of states of a QStateMachine.
The QSignalTransition class provides a transition based on a Qt signal.
bool contains(const T &value) const
Definition: qset.h:91
T takeFirst()
Removes the first item in the list and returns it.
Definition: qlist.h:489
The QVariantAnimation class provides an abstract base class for animations.
QList< T > toList() const
Definition: qset.h:296
void addDefaultAnimation(QAbstractAnimation *animation)
Adds a default animation to be considered for any transition.
static bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
Creates a connection of the given type from the signal in the sender object to the method in the rece...
Definition: qobject.cpp:2580
static QAbstractTransitionPrivate * get(QAbstractTransition *q)
The QFinalState class provides a final state.
Definition: qfinalstate.h:56
bool eventTest(QEvent *)
This function is called to determine whether the given event should cause this transition to trigger...
QSet< QAbstractTransition * > selectTransitions(QEvent *event) const
virtual void endSelectTransitions(QEvent *event)
This function is called when the state machine has finished selecting transitions based on the given ...
iterator end()
Returns an STL-style iterator pointing to the imaginary item after the last item in the list...
Definition: qlist.h:270
void onEntry(QEvent *event)
This function will call start() to start the state machine.
void prepend(const T &t)
Inserts value at the beginning of the list.
Definition: qlist.h:541
const T & at(int i) const
Returns the item at index position i in the list.
Definition: qlist.h:468
#define emit
Definition: qobjectdefs.h:76
QHash< int, QEvent * > delayedEvents
bool isEmpty() const
Returns true if the hash contains no items; otherwise returns false.
Definition: qhash.h:297
const T & value() const
Returns the current item&#39;s value.
Definition: qhash.h:420
Q_CORE_EXPORT void qWarning(const char *,...)
bool isCompound(const QAbstractState *s) const
const_iterator insert(const T &value)
Definition: qset.h:179
int timerId() const
Returns the unique timer identifier, which is the same identifier as returned from QObject::startTime...
Definition: qcoreevent.h:346
unsigned int uint
Definition: qglobal.h:996
T findChild(const QString &aName=QString()) const
Returns the child of this object that can be cast into type T and that is called name, or 0 if there is no such object.
Definition: qobject.h:158
void clear()
Definition: qset.h:87
~WrappedEvent()
Destroys this WrappedEvent.
static bool disconnect(const QObject *sender, int signal_index, const QObject *receiver, int method_index)
Definition: qobject.cpp:3276
QList< QAbstractTransition * > transitions() const
Definition: qstate.cpp:227
QAbstractState * initialState
the initial state of this state (one of its child states)
Definition: qstate.h:64
QState * rootState() const
int indexOfSignal(const char *signal) const
Finds signal and returns its index; otherwise returns -1.
QSignalEventGenerator * signalEventGenerator
void applyProperties(const QList< QAbstractTransition *> &transitionList, const QList< QAbstractState *> &exitedStates, const QList< QAbstractState *> &enteredStates)
QList< QEvent * > externalEventQueue
QState * sourceState() const
void onExit(QEvent *event)
Reimplemented Function
Definition: qstate.cpp:454
void clear()
Removes all items from the list.
Definition: qlist.h:764
static int type(const char *typeName)
Returns a handle to the type called typeName, or 0 if there is no such type.
Definition: qmetatype.cpp:607
static QHistoryState * toHistoryState(QAbstractState *state)
The QAbstractAnimation class is the base of all animations.
void handleFilteredEvent(QObject *watched, QEvent *event)
void registerEventTransition(QEventTransition *transition)
void setTargetState(QAbstractState *target)
Sets the target state of this transition.
void stop()
Stops this state machine.
static QStatePrivate * get(QState *q)
Definition: qstate_p.h:89
void qSort(RandomAccessIterator start, RandomAccessIterator end)
Definition: qalgorithms.h:177
const T & at(int i) const
Returns the item at index position i in the vector.
Definition: qvector.h:350
virtual void callOnTransition(QEvent *e)
static QAbstractStatePrivate * get(QAbstractState *q)
Q_CORE_EXPORT const QStateMachinePrivate::Handler * qcoreStateMachineHandler()
bool isPreempted(const QAbstractState *s, const QSet< QAbstractTransition *> &transitions) const
void unregisterRestorable(QObject *object, const QByteArray &propertyName)
void callOnExit(QEvent *e)
const char * constData() const
Returns a pointer to the data stored in the byte array.
Definition: qbytearray.h:433
QList< QAbstractAnimation * > defaultAnimations
QVariant restorableValue(QObject *object, const QByteArray &propertyName) const
static bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *member)
Disconnects signal in object sender from method in object receiver.
Definition: qobject.cpp:2895
The QHistoryState class provides a means of returning to a previously active substate.
Definition: qhistorystate.h:56
const_iterator constBegin() const
Returns a const STL-style iterator pointing to the first item in the hash.
Definition: qhash.h:466
QHash< const QObject *, QVector< int > > connections
QState * sourceState
the source state (parent) of this transition
#define QSIGNAL_CODE
Definition: qobjectdefs.h:244
void onExit(QEvent *event)
This function will call stop() to stop the state machine and subsequently emit the stopped() signal...
const_iterator constEnd() const
Returns a const STL-style iterator pointing to the imaginary item after the last item in the hash...
Definition: qhash.h:469
QStateMachine(QObject *parent=0)
Constructs a new state machine with the given parent.
QSet< QAbstractState * > configuration() const
Returns the maximal consistent set of states (including parallel and final states) that this state ma...
Error
This enum type defines errors that can occur in the state machine at run time.
bool event(QEvent *e)
Reimplemented Function
QList< QByteArray > parameterTypes() const
Returns a list of parameter types.
#define Q_ASSERT_X(cond, where, what)
Definition: qglobal.h:1837
QHash< RestorableId, QVariant > registeredRestorables
iterator erase(iterator pos)
Removes the item associated with the iterator pos from the list, and returns an iterator to the next ...
Definition: qlist.h:464
The QMutexLocker class is a convenience class that simplifies locking and unlocking mutexes...
Definition: qmutex.h:101
QString arg(qlonglong a, int fieldwidth=0, int base=10, const QChar &fillChar=QLatin1Char(' ')) const Q_REQUIRED_RESULT
Definition: qstring.cpp:7186
QList< QEvent * > internalEventQueue
int indexOf(const T &t, int from=0) const
Returns the index position of the first occurrence of value in the list, searching forward from index...
Definition: qlist.h:847
void executeTransitionContent(QEvent *event, const QList< QAbstractTransition *> &transitionList)
#define Q_CORE_EXPORT
Definition: qglobal.h:1449
iterator end()
Returns an STL-style iterator pointing to the imaginary item after the last item in the hash...
Definition: qhash.h:467
The QTimerEvent class contains parameters that describe a timer event.
Definition: qcoreevent.h:341
QList< QHistoryState * > historyStates() const
Definition: qstate.cpp:215
EventPriority
This enum type specifies the priority of an event posted to the state machine using postEvent()...
static bool isFinal(const QAbstractState *s)
QEvent * dequeueInternalEvent()
void unregisterTransition(QAbstractTransition *transition)
static bool stateExitLessThan(QAbstractState *s1, QAbstractState *s2)
QState * findLCA(const QList< QAbstractState *> &states) const
const Key key(const T &value) const
Returns the first key mapped to value.
Definition: qhash.h:674
QList< T > values() const
Returns a list containing all the values in the hash, in an arbitrary order.
Definition: qhash.h:693
QList< QAbstractState * > childStates() const
Definition: qstate.cpp:199
QObject * parent() const
Returns a pointer to the parent object.
Definition: qobject.h:273
Q_OUTOFLINE_TEMPLATE QPair< T1, T2 > qMakePair(const T1 &x, const T2 &y)
Definition: qpair.h:102
#define st(var, type, card)
static QSignalTransitionPrivate * get(QSignalTransition *q)
void installEventFilter(QObject *)
Installs an event filter filterObj on this object.
Definition: qobject.cpp:2070
T & last()
Returns a reference to the last item in the list.
Definition: qlist.h:284
int size() const
Returns the number of items in the list.
Definition: qlist.h:137
bool event(QEvent *e)
Reimplemented Function
Definition: qstate.cpp:509
QByteArray propertyName
Definition: qstate_p.h:73
const char * className() const
Returns the class name.
Definition: qobjectdefs.h:491
QList< QPropertyAssignment > restorablesToPropertyList(const QHash< RestorableId, QVariant > &restorables) const
QString objectName() const
iterator begin()
Returns an STL-style iterator pointing to the first item in the hash.
Definition: qhash.h:464
bool isRunning() const
Returns whether this state machine is running.
const_iterator constBegin() const
Definition: qset.h:168
QList< QAbstractState * > enterStates(QEvent *event, const QList< QAbstractTransition *> &enabledTransitions)
const QObjectList & children() const
Returns a list of child objects.
Definition: qobject.h:197
QHash< QAbstractAnimation *, QAbstractState * > stateForAnimation
int attributes() const
QEvent * dequeueExternalEvent()
QVariant property(const char *name) const
Returns the value of the object&#39;s name property.
Definition: qobject.cpp:3807
QObject * parent
Definition: qobject.h:92
void setAnimated(bool enabled)
Sets whether animations are enabled for this state machine.
WrappedEvent(QObject *object, QEvent *event)
Constructs a new WrappedEvent object with the given object and event.
SignalEvent(QObject *sender, int signalIndex, const QList< QVariant > &arguments)
Constructs a new SignalEvent object with the given sender, signalIndex and arguments.
QScopedPointer< QObjectData > d_ptr
Definition: qobject.h:320
static bool invokeMethod(QObject *obj, const char *member, Qt::ConnectionType, QGenericReturnArgument ret, QGenericArgument val0=QGenericArgument(0), QGenericArgument val1=QGenericArgument(), QGenericArgument val2=QGenericArgument(), QGenericArgument val3=QGenericArgument(), QGenericArgument val4=QGenericArgument(), QGenericArgument val5=QGenericArgument(), QGenericArgument val6=QGenericArgument(), QGenericArgument val7=QGenericArgument(), QGenericArgument val8=QGenericArgument(), QGenericArgument val9=QGenericArgument())
Invokes the member (a signal or a slot name) on the object obj.
void emitPropertiesAssigned()
Definition: qstate.cpp:159
void microstep(QEvent *event, const QList< QAbstractTransition *> &transitionList)
void postEvent(QEvent *event, EventPriority priority=NormalPriority)
Posts the given event of the given priority for processing by this state machine. ...
QMetaMethod method(int index) const
Returns the meta-data for the method with the given index.
QByteArray propertyName
the target property name for this animation
bool cancelDelayedEvent(int id)
Cancels the delayed event identified by the given id.
QStateMachine::RestorePolicy globalRestorePolicy() const
const char * signature() const
Returns the signature of this method (e.g., setValue(double)).
iterator find(const Key &key)
Returns an iterator pointing to the item with the key in the hash.
Definition: qhash.h:865
QThread * thread() const
Returns the thread in which the object lives.
Definition: qobject.cpp:1419
QSet< QAbstractAnimation * > resetAnimationEndValues
bool isInFinalState(QAbstractState *s) const
QAbstractState * initialState() const
The QAnimationGroup class is an abstract base class for groups of animations.
static QList< QState * > properAncestors(const QAbstractState *s, const QState *upperBound)
virtual void endMicrostep(QEvent *event)
This function is called when the state machine has finished doing a microstep.
bool isValid() const
Returns true if the storage type of this variant is not QVariant::Invalid; otherwise returns false...
Definition: qvariant.h:485
~SignalEvent()
Destroys this SignalEvent.
static QState * toStandardState(QAbstractState *state)
QStateMachine * machine() const
Returns the state machine that this transition is part of, or 0 if the transition is not part of a st...
void addTransition(QAbstractTransition *transition)
Adds the given transition.
Definition: qstate.cpp:308
static bool isParallel(const QAbstractState *s)
QMultiHash< QAbstractState *, QAbstractAnimation * > defaultAnimationsForSource
bool isAtomic(const QAbstractState *s) const
The QEvent class is the base class of all event classes.
Definition: qcoreevent.h:56
#define qPrintable(string)
Definition: qglobal.h:1750
Type type() const
Returns the event type.
Definition: qcoreevent.h:303
#define Q_UNUSED(x)
Indicates to the compiler that the parameter with the specified name is not used in the body of a fun...
Definition: qglobal.h:1729
Q_OUTOFLINE_TEMPLATE void qDeleteAll(ForwardIterator begin, ForwardIterator end)
Definition: qalgorithms.h:319
QList< QPropertyAssignment > propertyAssignments
Definition: qstate_p.h:107
int size() const
Returns the number of items in the vector.
Definition: qvector.h:137
QSet< QAbstractState * > pendingErrorStatesForDefaultEntry
QList< QAbstractAnimation * > defaultAnimations() const
Returns the list of default animations that will be considered for any transition.
QList< T > findChildren(const QString &aName=QString()) const
Returns all children of this object with the given name that can be cast to type T, or an empty list if there are no such objects.
Definition: qobject.h:162
iterator erase(iterator it)
Removes the (key, value) pair associated with the iterator pos from the hash, and returns an iterator...
Definition: qhash.h:827
QList< QAbstractState * > exitStates(QEvent *event, const QList< QAbstractTransition *> &transitionList)
virtual void * qt_metacast(const char *)
bool isAnimated() const
Returns whether animations are enabled for this state machine.
The QMetaMethod class provides meta-data about a member function.
Definition: qmetaobject.h:56
The SignalEvent class represents a Qt signal event.
Definition: qstatemachine.h:73
#define enabled
QString errorString() const
QByteArray & remove(int index, int len)
Removes len bytes from the array, starting at index position pos, and returns a reference to the arra...
void emitFinished()
Definition: qstate.cpp:153
void registerRestorable(QObject *object, const QByteArray &propertyName)
virtual const QMetaObject * metaObject() const
Returns a pointer to the meta-object of this object.
virtual void beginMicrostep(QEvent *event)
This function is called when the state machine is about to do a microstep.
static int indexOfDescendant(QState *s, QAbstractState *desc)
QAbstractState * errorState
Definition: qstate_p.h:99
static const Handler * handler
static QFinalState * toFinalState(QAbstractState *state)
The QList class is a template class that provides lists.
Definition: qdatastream.h:62
int signalIndex(const char *signalName) const
Returns the signal index used in the internal connectionLists vector.
Definition: qobject.cpp:3719
void killTimer(int id)
Kills the timer with timer identifier, id.
Definition: qobject.cpp:1650
QHash< QAbstractState *, QList< QAbstractAnimation * > > animationsForState
QAbstractState * errorState
the error state of this state
Definition: qstate.h:65