src/corelib/statemachine/qstatemachine.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtCore module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    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"
       
    53 #include "qsignaleventgenerator_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 
       
    76 QT_BEGIN_NAMESPACE
       
    77 
       
    78 /*!
       
    79     \class QStateMachine
       
    80     \reentrant
       
    81 
       
    82     \brief The QStateMachine class provides a hierarchical finite state machine.
       
    83 
       
    84     \since 4.6
       
    85     \ingroup statemachine
       
    86 
       
    87     QStateMachine is based on the concepts and notation of
       
    88     \l{Statecharts: A visual formalism for complex
       
    89     systems}{Statecharts}. QStateMachine is part of \l{The State
       
    90     Machine Framework}.
       
    91 
       
    92     A state machine manages a set of states (classes that inherit from
       
    93     QAbstractState) and transitions (descendants of
       
    94     QAbstractTransition) between those states; these states and
       
    95     transitions define a state graph. Once a state graph has been
       
    96     built, the state machine can execute it. QStateMachine's
       
    97     execution algorithm is based on the \l{State Chart XML: State
       
    98     Machine Notation for Control Abstraction}{State Chart XML (SCXML)}
       
    99     algorithm. The framework's \l{The State Machine
       
   100     Framework}{overview} gives several state graphs and the code to
       
   101     build them.
       
   102 
       
   103     Use the addState() function to add a top-level state to the state machine.
       
   104     States are removed with the removeState() function. Removing states while
       
   105     the machine is running is discouraged.
       
   106 
       
   107     Before the machine can be started, the \l{initialState}{initial
       
   108     state} must be set. The initial state is the state that the
       
   109     machine enters when started. You can then start() the state
       
   110     machine. The started() signal is emitted when the initial state is
       
   111     entered.
       
   112 
       
   113     The machine is event driven and keeps its own event loop. Events
       
   114     are posted to the machine through postEvent(). Note that this
       
   115     means that it executes asynchronously, and that it will not
       
   116     progress without a running event loop. You will normally not have
       
   117     to post events to the machine directly as Qt's transitions, e.g.,
       
   118     QEventTransition and its subclasses, handle this. But for custom
       
   119     transitions triggered by events, postEvent() is useful.
       
   120 
       
   121     The state machine processes events and takes transitions until a
       
   122     top-level final state is entered; the state machine then emits the
       
   123     finished() signal. You can also stop() the state machine
       
   124     explicitly. The stopped() signal is emitted in this case.
       
   125 
       
   126     The following snippet shows a state machine that will finish when a button
       
   127     is clicked:
       
   128 
       
   129     \snippet doc/src/snippets/code/src_corelib_statemachine_qstatemachine.cpp simple state machine
       
   130 
       
   131     This code example uses QState, which inherits QAbstractState. The
       
   132     QState class provides a state that you can use to set properties
       
   133     and invoke methods on \l{QObject}s when the state is entered or
       
   134     exited. It also contains convenience functions for adding
       
   135     transitions, e.g., \l{QSignalTransition}s as in this example. See
       
   136     the QState class description for further details.
       
   137 
       
   138     If an error is encountered, the machine will look for an
       
   139     \l{errorState}{error state}, and if one is available, it will
       
   140     enter this state. The types of errors possible are described by the
       
   141     \l{QStateMachine::}{Error} enum. After the error state is entered,
       
   142     the type of the error can be retrieved with error(). The execution
       
   143     of the state graph will not stop when the error state is entered. If 
       
   144     no error state applies to the erroneous state, the machine will stop 
       
   145     executing and an error message will be printed to the console.
       
   146 
       
   147     \sa QAbstractState, QAbstractTransition, QState, {The State Machine Framework}
       
   148 */
       
   149 
       
   150 /*!
       
   151     \property QStateMachine::errorString
       
   152 
       
   153     \brief the error string of this state machine
       
   154 */
       
   155 
       
   156 /*!
       
   157     \property QStateMachine::globalRestorePolicy
       
   158 
       
   159     \brief the restore policy for states of this state machine.
       
   160 
       
   161     The default value of this property is
       
   162     QStateMachine::DoNotRestoreProperties.
       
   163 */
       
   164 
       
   165 #ifndef QT_NO_ANIMATION
       
   166 /*!
       
   167     \property QStateMachine::animationsEnabled
       
   168 
       
   169     \brief whether animations are enabled
       
   170 
       
   171     The default value of this property is true.
       
   172 
       
   173     \sa QAbstractTransition::addAnimation()
       
   174 */
       
   175 #endif
       
   176 
       
   177 // #define QSTATEMACHINE_DEBUG
       
   178 
       
   179 QStateMachinePrivate::QStateMachinePrivate()
       
   180 {
       
   181     state = NotRunning;
       
   182     _startState = 0;
       
   183     processing = false;
       
   184     processingScheduled = false;
       
   185     stop = false;
       
   186     stopProcessingReason = EventQueueEmpty;
       
   187     error = QStateMachine::NoError;
       
   188     globalRestorePolicy = QStateMachine::DoNotRestoreProperties;
       
   189     signalEventGenerator = 0;
       
   190 #ifndef QT_NO_ANIMATION
       
   191     animationsEnabled = true;
       
   192 #endif
       
   193 }
       
   194 
       
   195 QStateMachinePrivate::~QStateMachinePrivate()
       
   196 {
       
   197     qDeleteAll(internalEventQueue);
       
   198     qDeleteAll(externalEventQueue);
       
   199 }
       
   200 
       
   201 QStateMachinePrivate *QStateMachinePrivate::get(QStateMachine *q)
       
   202 {
       
   203     if (q)
       
   204         return q->d_func();
       
   205     return 0;
       
   206 }
       
   207 
       
   208 QState *QStateMachinePrivate::rootState() const
       
   209 {
       
   210     return const_cast<QStateMachine*>(q_func());
       
   211 }
       
   212 
       
   213 static QEvent *cloneEvent(QEvent *e)
       
   214 {
       
   215     switch (e->type()) {
       
   216     case QEvent::None:
       
   217         return new QEvent(*e);
       
   218     case QEvent::Timer:
       
   219         return new QTimerEvent(*static_cast<QTimerEvent*>(e));
       
   220     default:
       
   221         Q_ASSERT_X(false, "cloneEvent()", "not implemented");
       
   222         break;
       
   223     }
       
   224     return 0;
       
   225 }
       
   226 
       
   227 const QStateMachinePrivate::Handler qt_kernel_statemachine_handler = {
       
   228     cloneEvent
       
   229 };
       
   230 
       
   231 const QStateMachinePrivate::Handler *QStateMachinePrivate::handler = &qt_kernel_statemachine_handler;
       
   232 
       
   233 Q_CORE_EXPORT const QStateMachinePrivate::Handler *qcoreStateMachineHandler()
       
   234 {
       
   235     return &qt_kernel_statemachine_handler;
       
   236 }
       
   237 
       
   238 static int indexOfDescendant(QState *s, QAbstractState *desc)
       
   239 {
       
   240     QList<QAbstractState*> childStates = QStatePrivate::get(s)->childStates();
       
   241     for (int i = 0; i < childStates.size(); ++i) {
       
   242         QAbstractState *c = childStates.at(i);
       
   243         if ((c == desc) || QStateMachinePrivate::isDescendantOf(desc, c)) {
       
   244             return i;
       
   245         }
       
   246     }
       
   247     return -1;
       
   248 }
       
   249 
       
   250 bool QStateMachinePrivate::stateEntryLessThan(QAbstractState *s1, QAbstractState *s2)
       
   251 {
       
   252     if (s1->parent() == s2->parent()) {
       
   253         return s1->children().indexOf(s1)
       
   254             < s2->children().indexOf(s2);
       
   255     } else if (isDescendantOf(s1, s2)) {
       
   256         return false;
       
   257     } else if (isDescendantOf(s2, s1)) {
       
   258         return true;
       
   259     } else {
       
   260         Q_ASSERT(s1->machine() != 0);
       
   261         QStateMachinePrivate *mach = QStateMachinePrivate::get(s1->machine());
       
   262         QState *lca = mach->findLCA(QList<QAbstractState*>() << s1 << s2);
       
   263         Q_ASSERT(lca != 0);
       
   264         return (indexOfDescendant(lca, s1) < indexOfDescendant(lca, s2));
       
   265     }
       
   266 }
       
   267 
       
   268 bool QStateMachinePrivate::stateExitLessThan(QAbstractState *s1, QAbstractState *s2)
       
   269 {
       
   270     if (s1->parent() == s2->parent()) {
       
   271         return s1->children().indexOf(s1)
       
   272             < s2->children().indexOf(s2);
       
   273     } else if (isDescendantOf(s1, s2)) {
       
   274         return true;
       
   275     } else if (isDescendantOf(s2, s1)) {
       
   276         return false;
       
   277     } else {
       
   278         Q_ASSERT(s1->machine() != 0);
       
   279         QStateMachinePrivate *mach = QStateMachinePrivate::get(s1->machine());
       
   280         QState *lca = mach->findLCA(QList<QAbstractState*>() << s1 << s2);
       
   281         Q_ASSERT(lca != 0);
       
   282         return (indexOfDescendant(lca, s1) < indexOfDescendant(lca, s2));
       
   283     }
       
   284 }
       
   285 
       
   286 QState *QStateMachinePrivate::findLCA(const QList<QAbstractState*> &states) const
       
   287 {
       
   288     if (states.isEmpty())
       
   289         return 0;
       
   290     QList<QState*> ancestors = properAncestors(states.at(0), rootState()->parentState());
       
   291     for (int i = 0; i < ancestors.size(); ++i) {
       
   292         QState *anc = ancestors.at(i);
       
   293         bool ok = true;
       
   294         for (int j = states.size() - 1; (j > 0) && ok; --j) {
       
   295             const QAbstractState *s = states.at(j);
       
   296             if (!isDescendantOf(s, anc))
       
   297                 ok = false;
       
   298         }
       
   299         if (ok)
       
   300             return anc;
       
   301     }
       
   302     return 0;
       
   303 }
       
   304 
       
   305 bool QStateMachinePrivate::isPreempted(const QAbstractState *s, const QSet<QAbstractTransition*> &transitions) const
       
   306 {
       
   307     QSet<QAbstractTransition*>::const_iterator it;
       
   308     for (it = transitions.constBegin(); it != transitions.constEnd(); ++it) {
       
   309         QAbstractTransition *t = *it;
       
   310         QList<QAbstractState*> lst = t->targetStates();
       
   311         if (!lst.isEmpty()) {
       
   312             lst.prepend(t->sourceState());
       
   313             QAbstractState *lca = findLCA(lst);
       
   314             if (isDescendantOf(s, lca)) {
       
   315 #ifdef QSTATEMACHINE_DEBUG
       
   316                 qDebug() << q_func() << ':' << transitions << "preempts selection of a transition from"
       
   317                          << s << "because" << s << "is a descendant of" << lca;
       
   318 #endif
       
   319                 return true;
       
   320             }
       
   321         }
       
   322     }
       
   323     return false;
       
   324 }
       
   325 
       
   326 QSet<QAbstractTransition*> QStateMachinePrivate::selectTransitions(QEvent *event) const
       
   327 {
       
   328     Q_Q(const QStateMachine);
       
   329     QSet<QAbstractTransition*> enabledTransitions;
       
   330     QSet<QAbstractState*>::const_iterator it;
       
   331     const_cast<QStateMachine*>(q)->beginSelectTransitions(event);
       
   332     for (it = configuration.constBegin(); it != configuration.constEnd(); ++it) {
       
   333         QAbstractState *state = *it;
       
   334         if (!isAtomic(state))
       
   335             continue;
       
   336         if (isPreempted(state, enabledTransitions))
       
   337             continue;
       
   338         QList<QState*> lst = properAncestors(state, rootState()->parentState());
       
   339         if (QState *grp = qobject_cast<QState*>(state))
       
   340             lst.prepend(grp);
       
   341         bool found = false;
       
   342         for (int j = 0; (j < lst.size()) && !found; ++j) {
       
   343             QState *s = lst.at(j);
       
   344             QList<QAbstractTransition*> transitions = QStatePrivate::get(s)->transitions();
       
   345             for (int k = 0; k < transitions.size(); ++k) {
       
   346                 QAbstractTransition *t = transitions.at(k);
       
   347                 if (QAbstractTransitionPrivate::get(t)->callEventTest(event)) {
       
   348 #ifdef QSTATEMACHINE_DEBUG
       
   349                     qDebug() << q << ": selecting transition" << t;
       
   350 #endif
       
   351                     enabledTransitions.insert(t);
       
   352                     found = true;
       
   353                     break;
       
   354                 }
       
   355             }
       
   356         }
       
   357     }
       
   358     const_cast<QStateMachine*>(q)->endSelectTransitions(event);
       
   359     return enabledTransitions;
       
   360 }
       
   361 
       
   362 void QStateMachinePrivate::microstep(QEvent *event, const QList<QAbstractTransition*> &enabledTransitions)
       
   363 {
       
   364 #ifdef QSTATEMACHINE_DEBUG
       
   365     qDebug() << q_func() << ": begin microstep( enabledTransitions:" << enabledTransitions << ')';
       
   366     qDebug() << q_func() << ": configuration before exiting states:" << configuration;
       
   367 #endif
       
   368     QList<QAbstractState*> exitedStates = exitStates(event, enabledTransitions);
       
   369 #ifdef QSTATEMACHINE_DEBUG
       
   370     qDebug() << q_func() << ": configuration after exiting states:" << configuration;
       
   371 #endif
       
   372     executeTransitionContent(event, enabledTransitions);
       
   373     QList<QAbstractState*> enteredStates = enterStates(event, enabledTransitions);
       
   374 #ifndef QT_NO_PROPERTIES
       
   375     applyProperties(enabledTransitions, exitedStates, enteredStates);
       
   376 #endif
       
   377 #ifdef QSTATEMACHINE_DEBUG
       
   378     qDebug() << q_func() << ": configuration after entering states:" << configuration;
       
   379     qDebug() << q_func() << ": end microstep";
       
   380 #endif
       
   381 }
       
   382 
       
   383 QList<QAbstractState*> QStateMachinePrivate::exitStates(QEvent *event, const QList<QAbstractTransition*> &enabledTransitions)
       
   384 {
       
   385 //    qDebug() << "exitStates(" << enabledTransitions << ')';
       
   386     QSet<QAbstractState*> statesToExit;
       
   387 //    QSet<QAbstractState*> statesToSnapshot;
       
   388     for (int i = 0; i < enabledTransitions.size(); ++i) {
       
   389         QAbstractTransition *t = enabledTransitions.at(i);
       
   390         QList<QAbstractState*> lst = t->targetStates();
       
   391         if (lst.isEmpty())
       
   392             continue;
       
   393         lst.prepend(t->sourceState());
       
   394         QAbstractState *lca = findLCA(lst);
       
   395         if (lca == 0) {
       
   396             setError(QStateMachine::NoCommonAncestorForTransitionError, t->sourceState());
       
   397             lst = pendingErrorStates.toList();
       
   398             lst.prepend(t->sourceState());
       
   399             
       
   400             lca = findLCA(lst);
       
   401             Q_ASSERT(lca != 0);
       
   402         }
       
   403 
       
   404         {
       
   405             QSet<QAbstractState*>::const_iterator it;
       
   406             for (it = configuration.constBegin(); it != configuration.constEnd(); ++it) {
       
   407                 QAbstractState *s = *it;
       
   408                 if (isDescendantOf(s, lca))
       
   409                     statesToExit.insert(s);
       
   410             }
       
   411         }
       
   412     }
       
   413     QList<QAbstractState*> statesToExit_sorted = statesToExit.toList();
       
   414     qSort(statesToExit_sorted.begin(), statesToExit_sorted.end(), stateExitLessThan);
       
   415     for (int i = 0; i < statesToExit_sorted.size(); ++i) {
       
   416         QAbstractState *s = statesToExit_sorted.at(i);
       
   417         if (QState *grp = qobject_cast<QState*>(s)) {
       
   418             QList<QHistoryState*> hlst = QStatePrivate::get(grp)->historyStates();
       
   419             for (int j = 0; j < hlst.size(); ++j) {
       
   420                 QHistoryState *h = hlst.at(j);
       
   421                 QHistoryStatePrivate::get(h)->configuration.clear();
       
   422                 QSet<QAbstractState*>::const_iterator it;
       
   423                 for (it = configuration.constBegin(); it != configuration.constEnd(); ++it) {
       
   424                     QAbstractState *s0 = *it;
       
   425                     if (QHistoryStatePrivate::get(h)->historyType == QHistoryState::DeepHistory) {
       
   426                         if (isAtomic(s0) && isDescendantOf(s0, s))
       
   427                             QHistoryStatePrivate::get(h)->configuration.append(s0);
       
   428                     } else if (s0->parentState() == s) {
       
   429                         QHistoryStatePrivate::get(h)->configuration.append(s0);
       
   430                     }
       
   431                 }
       
   432 #ifdef QSTATEMACHINE_DEBUG
       
   433                 qDebug() << q_func() << ": recorded" << ((QHistoryStatePrivate::get(h)->historyType == QHistoryState::DeepHistory) ? "deep" : "shallow")
       
   434                          << "history for" << s << "in" << h << ':' << QHistoryStatePrivate::get(h)->configuration;
       
   435 #endif
       
   436             }
       
   437         }
       
   438     }
       
   439     for (int i = 0; i < statesToExit_sorted.size(); ++i) {
       
   440         QAbstractState *s = statesToExit_sorted.at(i);
       
   441 #ifdef QSTATEMACHINE_DEBUG
       
   442         qDebug() << q_func() << ": exiting" << s;
       
   443 #endif
       
   444         QAbstractStatePrivate::get(s)->callOnExit(event);
       
   445         configuration.remove(s);
       
   446         QAbstractStatePrivate::get(s)->emitExited();
       
   447     }
       
   448     return statesToExit_sorted;
       
   449 }
       
   450 
       
   451 void QStateMachinePrivate::executeTransitionContent(QEvent *event, const QList<QAbstractTransition*> &enabledTransitions)
       
   452 {
       
   453     for (int i = 0; i < enabledTransitions.size(); ++i) {
       
   454         QAbstractTransition *t = enabledTransitions.at(i);
       
   455 #ifdef QSTATEMACHINE_DEBUG
       
   456         qDebug() << q_func() << ": triggering" << t;
       
   457 #endif
       
   458         QAbstractTransitionPrivate::get(t)->callOnTransition(event);
       
   459         QAbstractTransitionPrivate::get(t)->emitTriggered();
       
   460     }
       
   461 }
       
   462 
       
   463 QList<QAbstractState*> QStateMachinePrivate::enterStates(QEvent *event, const QList<QAbstractTransition*> &enabledTransitions)
       
   464 {
       
   465 #ifdef QSTATEMACHINE_DEBUG
       
   466     Q_Q(QStateMachine);
       
   467 #endif
       
   468 //    qDebug() << "enterStates(" << enabledTransitions << ')';
       
   469     QSet<QAbstractState*> statesToEnter;
       
   470     QSet<QAbstractState*> statesForDefaultEntry;
       
   471 
       
   472     if (pendingErrorStates.isEmpty()) {
       
   473         for (int i = 0; i < enabledTransitions.size(); ++i) {
       
   474             QAbstractTransition *t = enabledTransitions.at(i);
       
   475             QList<QAbstractState*> lst = t->targetStates();
       
   476             if (lst.isEmpty())
       
   477                 continue;
       
   478             lst.prepend(t->sourceState());
       
   479             QState *lca = findLCA(lst);
       
   480             for (int j = 1; j < lst.size(); ++j) {
       
   481                 QAbstractState *s = lst.at(j);
       
   482 			    addStatesToEnter(s, lca, statesToEnter, statesForDefaultEntry);
       
   483                 if (isParallel(lca)) {
       
   484                     QList<QAbstractState*> lcac = QStatePrivate::get(lca)->childStates();
       
   485                     foreach (QAbstractState* child,lcac) {
       
   486                         if (!statesToEnter.contains(child))
       
   487                             addStatesToEnter(child,lca,statesToEnter,statesForDefaultEntry);                    
       
   488                     }
       
   489                 }
       
   490             }
       
   491         }
       
   492     }
       
   493 
       
   494     // Did an error occur while selecting transitions? Then we enter the error state.
       
   495     if (!pendingErrorStates.isEmpty()) {
       
   496         statesToEnter.clear();
       
   497         statesToEnter = pendingErrorStates;
       
   498         statesForDefaultEntry = pendingErrorStatesForDefaultEntry;
       
   499         pendingErrorStates.clear();
       
   500         pendingErrorStatesForDefaultEntry.clear();
       
   501     }
       
   502 
       
   503     QList<QAbstractState*> statesToEnter_sorted = statesToEnter.toList();
       
   504     qSort(statesToEnter_sorted.begin(), statesToEnter_sorted.end(), stateEntryLessThan);
       
   505 
       
   506     for (int i = 0; i < statesToEnter_sorted.size(); ++i) {
       
   507         QAbstractState *s = statesToEnter_sorted.at(i);
       
   508 #ifdef QSTATEMACHINE_DEBUG
       
   509         qDebug() << q << ": entering" << s;
       
   510 #endif
       
   511         configuration.insert(s);
       
   512         registerTransitions(s);
       
   513         QAbstractStatePrivate::get(s)->callOnEntry(event);
       
   514         QAbstractStatePrivate::get(s)->emitEntered();
       
   515         if (statesForDefaultEntry.contains(s)) {
       
   516             // ### executeContent(s.initial.transition.children())
       
   517         }
       
   518         if (isFinal(s)) {
       
   519             QState *parent = s->parentState();
       
   520             if (parent) {
       
   521                 if (parent != rootState()) {
       
   522 #ifdef QSTATEMACHINE_DEBUG
       
   523                     qDebug() << q << ": emitting finished signal for" << parent;
       
   524 #endif
       
   525                     QStatePrivate::get(parent)->emitFinished();
       
   526                 }
       
   527                 QState *grandparent = parent->parentState();
       
   528                 if (grandparent && isParallel(grandparent)) {
       
   529                     bool allChildStatesFinal = true;
       
   530                     QList<QAbstractState*> childStates = QStatePrivate::get(grandparent)->childStates();
       
   531                     for (int j = 0; j < childStates.size(); ++j) {
       
   532                         QAbstractState *cs = childStates.at(j);
       
   533                         if (!isInFinalState(cs)) {
       
   534                             allChildStatesFinal = false;
       
   535                             break;
       
   536                         }
       
   537                     }
       
   538                     if (allChildStatesFinal && (grandparent != rootState())) {
       
   539 #ifdef QSTATEMACHINE_DEBUG
       
   540                         qDebug() << q << ": emitting finished signal for" << grandparent;
       
   541 #endif
       
   542                         QStatePrivate::get(grandparent)->emitFinished();
       
   543                     }
       
   544                 }
       
   545             }
       
   546         }
       
   547     }
       
   548     {
       
   549         QSet<QAbstractState*>::const_iterator it;
       
   550         for (it = configuration.constBegin(); it != configuration.constEnd(); ++it) {
       
   551             if (isFinal(*it) && (*it)->parentState() == rootState()) {
       
   552                 processing = false;
       
   553                 stopProcessingReason = Finished;
       
   554                 break;
       
   555             }
       
   556         }
       
   557     }
       
   558 //    qDebug() << "configuration:" << configuration.toList();
       
   559     return statesToEnter_sorted;
       
   560 }
       
   561 
       
   562 void QStateMachinePrivate::addStatesToEnter(QAbstractState *s, QState *root,
       
   563                                             QSet<QAbstractState*> &statesToEnter,
       
   564                                             QSet<QAbstractState*> &statesForDefaultEntry)
       
   565 {
       
   566 	if (QHistoryState *h = qobject_cast<QHistoryState*>(s)) {
       
   567 		QList<QAbstractState*> hconf = QHistoryStatePrivate::get(h)->configuration;
       
   568 		if (!hconf.isEmpty()) {
       
   569 			for (int k = 0; k < hconf.size(); ++k) {
       
   570 				QAbstractState *s0 = hconf.at(k);
       
   571 				addStatesToEnter(s0, root, statesToEnter, statesForDefaultEntry);
       
   572 			}
       
   573 	#ifdef QSTATEMACHINE_DEBUG
       
   574 			qDebug() <<q_func() << ": restoring"
       
   575 					<< ((QHistoryStatePrivate::get(h)->historyType == QHistoryState::DeepHistory) ? "deep" : "shallow")
       
   576 					<< "history from" << s << ':' << hconf;
       
   577 	#endif
       
   578 		} else {
       
   579 			QList<QAbstractState*> hlst;
       
   580 			if (QHistoryStatePrivate::get(h)->defaultState)
       
   581 				hlst.append(QHistoryStatePrivate::get(h)->defaultState);
       
   582 
       
   583 			if (hlst.isEmpty()) {
       
   584 				setError(QStateMachine::NoDefaultStateInHistoryStateError, h);
       
   585 			} else {
       
   586 				for (int k = 0; k < hlst.size(); ++k) {
       
   587 					QAbstractState *s0 = hlst.at(k);
       
   588 					addStatesToEnter(s0, root, statesToEnter, statesForDefaultEntry);
       
   589 				}
       
   590 	#ifdef QSTATEMACHINE_DEBUG
       
   591 				qDebug() << q_func() << ": initial history targets for" << s << ':' << hlst;
       
   592 	#endif
       
   593 			}
       
   594 		}
       
   595 	} else {
       
   596             if (s == rootState()) {
       
   597                 // Error has already been set by exitStates().
       
   598                 Q_ASSERT(error != QStateMachine::NoError);
       
   599                 return;
       
   600             }
       
   601 		statesToEnter.insert(s);
       
   602 		if (isParallel(s)) {
       
   603 			QState *grp = qobject_cast<QState*>(s);
       
   604 			QList<QAbstractState*> lst = QStatePrivate::get(grp)->childStates();
       
   605 			for (int i = 0; i < lst.size(); ++i) {
       
   606 				QAbstractState *child = lst.at(i);
       
   607 				addStatesToEnter(child, grp, statesToEnter, statesForDefaultEntry);
       
   608 			}
       
   609 		} else if (isCompound(s)) {
       
   610 			statesForDefaultEntry.insert(s);
       
   611 			QState *grp = qobject_cast<QState*>(s);
       
   612 			QAbstractState *initial = grp->initialState();
       
   613 			if (initial != 0) {
       
   614                             Q_ASSERT(initial->machine() == q_func());
       
   615 				addStatesToEnter(initial, grp, statesToEnter, statesForDefaultEntry);
       
   616 			} else {
       
   617 				setError(QStateMachine::NoInitialStateError, grp);
       
   618 				return;
       
   619 			}
       
   620 		}
       
   621 		QList<QState*> ancs = properAncestors(s, root);
       
   622 		for (int i = 0; i < ancs.size(); ++i) {
       
   623 			QState *anc = ancs.at(i);
       
   624 			if (!anc->parentState())
       
   625 				continue;
       
   626 			statesToEnter.insert(anc);
       
   627 			if (isParallel(anc)) {
       
   628 				QList<QAbstractState*> lst = QStatePrivate::get(anc)->childStates();
       
   629 				for (int j = 0; j < lst.size(); ++j) {
       
   630 					QAbstractState *child = lst.at(j);
       
   631 					bool hasDescendantInList = false;
       
   632 					QSet<QAbstractState*>::const_iterator it;
       
   633 					for (it = statesToEnter.constBegin(); it != statesToEnter.constEnd(); ++it) {
       
   634 						if (isDescendantOf(*it, child)) {
       
   635 							hasDescendantInList = true;
       
   636 							break;
       
   637 						}
       
   638 					}
       
   639 					if (!hasDescendantInList)
       
   640 						addStatesToEnter(child, anc, statesToEnter, statesForDefaultEntry);
       
   641 				}
       
   642 			}
       
   643 		}
       
   644 	}
       
   645 }
       
   646 
       
   647 #ifndef QT_NO_PROPERTIES
       
   648 
       
   649 void QStateMachinePrivate::applyProperties(const QList<QAbstractTransition*> &transitionList,
       
   650                                            const QList<QAbstractState*> &exitedStates,
       
   651                                            const QList<QAbstractState*> &enteredStates)
       
   652 {
       
   653 #ifdef QT_NO_ANIMATION
       
   654     Q_UNUSED(transitionList);
       
   655     Q_UNUSED(exitedStates);
       
   656 #else
       
   657     Q_Q(QStateMachine);
       
   658 #endif
       
   659     // Process the property assignments of the entered states.
       
   660     QHash<QAbstractState*, QList<QPropertyAssignment> > propertyAssignmentsForState;
       
   661     QHash<RestorableId, QVariant> pendingRestorables = registeredRestorables;
       
   662     for (int i = 0; i < enteredStates.size(); ++i) {
       
   663         QState *s = qobject_cast<QState*>(enteredStates.at(i));
       
   664         if (!s)
       
   665             continue;
       
   666 
       
   667         QList<QPropertyAssignment> assignments = QStatePrivate::get(s)->propertyAssignments;
       
   668         for (int j = 0; j < assignments.size(); ++j) {
       
   669             const QPropertyAssignment &assn = assignments.at(j);
       
   670             if (globalRestorePolicy == QStateMachine::RestoreProperties) {
       
   671                 registerRestorable(assn.object, assn.propertyName);
       
   672             }
       
   673             pendingRestorables.remove(RestorableId(assn.object, assn.propertyName));
       
   674             propertyAssignmentsForState[s].append(assn);
       
   675         }
       
   676 
       
   677         // Remove pending restorables for all parent states to avoid restoring properties
       
   678         // before the state that assigned them is exited. If state does not explicitly 
       
   679         // assign a property which is assigned by the parent, it inherits the parent's assignment.
       
   680         QState *parentState = s;
       
   681         while ((parentState = parentState->parentState()) != 0) {
       
   682             assignments = QStatePrivate::get(parentState)->propertyAssignments;
       
   683             for (int j=0; j<assignments.size(); ++j) {
       
   684                 const QPropertyAssignment &assn = assignments.at(j);
       
   685                 int c = pendingRestorables.remove(RestorableId(assn.object, assn.propertyName));
       
   686                 if (c > 0)
       
   687                     propertyAssignmentsForState[s].append(assn);                
       
   688             }
       
   689         }
       
   690     }
       
   691     if (!pendingRestorables.isEmpty()) {
       
   692         QAbstractState *s;
       
   693         if (!enteredStates.isEmpty())
       
   694             s = enteredStates.last(); // ### handle if parallel
       
   695         else
       
   696             s = 0;
       
   697         propertyAssignmentsForState[s] << restorablesToPropertyList(pendingRestorables);
       
   698     }
       
   699 
       
   700 #ifndef QT_NO_ANIMATION
       
   701     // Gracefully terminate playing animations for states that are exited.
       
   702     for (int i = 0; i < exitedStates.size(); ++i) {
       
   703         QAbstractState *s = exitedStates.at(i);
       
   704         QList<QAbstractAnimation*> animations = animationsForState.take(s);
       
   705         for (int j = 0; j < animations.size(); ++j) {
       
   706             QAbstractAnimation *anim = animations.at(j);
       
   707             QObject::disconnect(anim, SIGNAL(finished()), q, SLOT(_q_animationFinished()));
       
   708             stateForAnimation.remove(anim);
       
   709 
       
   710             // Stop the (top-level) animation.
       
   711             // ### Stopping nested animation has weird behavior.
       
   712             QAbstractAnimation *topLevelAnim = anim;
       
   713             while (QAnimationGroup *group = topLevelAnim->group())
       
   714                 topLevelAnim = group;
       
   715             topLevelAnim->stop();
       
   716 
       
   717             if (resetAnimationEndValues.contains(anim)) {
       
   718                 qobject_cast<QVariantAnimation*>(anim)->setEndValue(QVariant()); // ### generalize
       
   719                 resetAnimationEndValues.remove(anim);
       
   720             }
       
   721             QPropertyAssignment assn = propertyForAnimation.take(anim);
       
   722             Q_ASSERT(assn.object != 0);
       
   723             // If there is no property assignment that sets this property,
       
   724             // set the property to its target value.
       
   725             bool found = false;
       
   726             QHash<QAbstractState*, QList<QPropertyAssignment> >::const_iterator it;
       
   727             for (it = propertyAssignmentsForState.constBegin(); it != propertyAssignmentsForState.constEnd(); ++it) {
       
   728                 const QList<QPropertyAssignment> &assignments = it.value();
       
   729                 for (int k = 0; k < assignments.size(); ++k) {
       
   730                     if ((assignments.at(k).object == assn.object)
       
   731                         && (assignments.at(k).propertyName == assn.propertyName)) {
       
   732                         found = true;
       
   733                         break;
       
   734                     }
       
   735                 }
       
   736             }
       
   737             if (!found) {
       
   738                 assn.object->setProperty(assn.propertyName, assn.value);
       
   739             }
       
   740         }
       
   741     }
       
   742 
       
   743     // Find the animations to use for the state change.
       
   744     QList<QAbstractAnimation*> selectedAnimations;
       
   745     if (animationsEnabled) {
       
   746         for (int i = 0; i < transitionList.size(); ++i) {
       
   747             QAbstractTransition *transition = transitionList.at(i);
       
   748 
       
   749             selectedAnimations << transition->animations();
       
   750             selectedAnimations << defaultAnimationsForSource.values(transition->sourceState());
       
   751 
       
   752             QList<QAbstractState *> targetStates = transition->targetStates();
       
   753             for (int j=0; j<targetStates.size(); ++j) 
       
   754                 selectedAnimations << defaultAnimationsForTarget.values(targetStates.at(j));
       
   755         }
       
   756         selectedAnimations << defaultAnimations;
       
   757     }
       
   758 
       
   759     // Initialize animations from property assignments.
       
   760     for (int i = 0; i < selectedAnimations.size(); ++i) {
       
   761         QAbstractAnimation *anim = selectedAnimations.at(i);
       
   762         QHash<QAbstractState*, QList<QPropertyAssignment> >::iterator it;
       
   763         for (it = propertyAssignmentsForState.begin(); it != propertyAssignmentsForState.end(); ) {
       
   764             QList<QPropertyAssignment>::iterator it2;
       
   765             QAbstractState *s = it.key();
       
   766             QList<QPropertyAssignment> &assignments = it.value();
       
   767             for (it2 = assignments.begin(); it2 != assignments.end(); ) {
       
   768                 QPair<QList<QAbstractAnimation*>, QList<QAbstractAnimation*> > ret;
       
   769                 ret = initializeAnimation(anim, *it2);
       
   770                 QList<QAbstractAnimation*> handlers = ret.first;
       
   771                 if (!handlers.isEmpty()) {
       
   772                     for (int j = 0; j < handlers.size(); ++j) {
       
   773                         QAbstractAnimation *a = handlers.at(j);
       
   774                         propertyForAnimation.insert(a, *it2);
       
   775                         stateForAnimation.insert(a, s);
       
   776                         animationsForState[s].append(a);
       
   777                         // ### connect to just the top-level animation?
       
   778                         QObject::connect(a, SIGNAL(finished()), q, SLOT(_q_animationFinished()), Qt::UniqueConnection);
       
   779                     }
       
   780                     it2 = assignments.erase(it2);
       
   781                 } else {
       
   782                     ++it2;
       
   783                 }
       
   784                 for (int j = 0; j < ret.second.size(); ++j)
       
   785                     resetAnimationEndValues.insert(ret.second.at(j));
       
   786             }
       
   787             if (assignments.isEmpty())
       
   788                 it = propertyAssignmentsForState.erase(it);
       
   789             else
       
   790                 ++it;
       
   791         }
       
   792         // We require that at least one animation is valid.
       
   793         // ### generalize
       
   794         QList<QVariantAnimation*> variantAnims = qFindChildren<QVariantAnimation*>(anim);
       
   795         if (QVariantAnimation *va = qobject_cast<QVariantAnimation*>(anim))
       
   796             variantAnims.append(va);
       
   797         
       
   798         bool hasValidEndValue = false;
       
   799         for (int j = 0; j < variantAnims.size(); ++j) {
       
   800             if (variantAnims.at(j)->endValue().isValid()) {
       
   801                 hasValidEndValue = true;
       
   802                 break;
       
   803             }
       
   804         }
       
   805 
       
   806         if (hasValidEndValue) {
       
   807             if (anim->state() == QAbstractAnimation::Running) {
       
   808                 // The animation is still running. This can happen if the
       
   809                 // animation is a group, and one of its children just finished,
       
   810                 // and that caused a state to emit its polished() signal, and
       
   811                 // that triggered a transition in the machine.
       
   812                 // Just stop the animation so it is correctly restarted again.
       
   813                 anim->stop();
       
   814             }
       
   815             anim->start();
       
   816         }
       
   817     }
       
   818 #endif // !QT_NO_ANIMATION
       
   819 
       
   820     // Immediately set the properties that are not animated.
       
   821     {
       
   822         QHash<QAbstractState*, QList<QPropertyAssignment> >::const_iterator it;
       
   823         for (it = propertyAssignmentsForState.constBegin(); it != propertyAssignmentsForState.constEnd(); ++it) {
       
   824             const QList<QPropertyAssignment> &assignments = it.value();
       
   825             for (int i = 0; i < assignments.size(); ++i) {
       
   826                 const QPropertyAssignment &assn = assignments.at(i);
       
   827                 assn.object->setProperty(assn.propertyName, assn.value);
       
   828             }
       
   829         }
       
   830     }
       
   831 
       
   832     // Emit polished signal for entered states that have no animated properties.
       
   833     for (int i = 0; i < enteredStates.size(); ++i) {
       
   834         QState *s = qobject_cast<QState*>(enteredStates.at(i));
       
   835         if (s 
       
   836 #ifndef QT_NO_ANIMATION
       
   837             && !animationsForState.contains(s)
       
   838 #endif
       
   839             )
       
   840             QStatePrivate::get(s)->emitPolished();
       
   841     }
       
   842 }
       
   843 
       
   844 #endif // QT_NO_PROPERTIES
       
   845 
       
   846 bool QStateMachinePrivate::isFinal(const QAbstractState *s)
       
   847 {
       
   848     return qobject_cast<const QFinalState*>(s) != 0;
       
   849 }
       
   850 
       
   851 bool QStateMachinePrivate::isParallel(const QAbstractState *s)
       
   852 {
       
   853     const QState *ss = qobject_cast<const QState*>(s);
       
   854     return ss && (QStatePrivate::get(ss)->childMode == QState::ParallelStates);
       
   855 }
       
   856 
       
   857 bool QStateMachinePrivate::isCompound(const QAbstractState *s) const
       
   858 {
       
   859     const QState *group = qobject_cast<const QState*>(s);
       
   860     if (!group)
       
   861         return false;
       
   862     bool isMachine = (qobject_cast<const QStateMachine*>(group) != 0);
       
   863     // Don't treat the machine as compound if it's a sub-state of this machine
       
   864     if (isMachine && (group != rootState()))
       
   865         return false;
       
   866     return (!isParallel(group) && !QStatePrivate::get(group)->childStates().isEmpty())
       
   867         || isMachine;
       
   868 }
       
   869 
       
   870 bool QStateMachinePrivate::isAtomic(const QAbstractState *s) const
       
   871 {
       
   872     const QState *ss = qobject_cast<const QState*>(s);
       
   873     return (ss && QStatePrivate::get(ss)->childStates().isEmpty())
       
   874         || isFinal(s)
       
   875         // Treat the machine as atomic if it's a sub-state of this machine
       
   876         || (ss && (qobject_cast<const QStateMachine*>(ss) != 0) && (ss != rootState()));
       
   877 }
       
   878 
       
   879 
       
   880 bool QStateMachinePrivate::isDescendantOf(const QAbstractState *state, const QAbstractState *other)
       
   881 {
       
   882     Q_ASSERT(state != 0);
       
   883     for (QAbstractState *s = state->parentState(); s != 0; s = s->parentState()) {
       
   884         if (s == other)
       
   885             return true;
       
   886     }
       
   887     return false;
       
   888 }
       
   889 
       
   890 QList<QState*> QStateMachinePrivate::properAncestors(const QAbstractState *state, const QState *upperBound)
       
   891 {
       
   892     Q_ASSERT(state != 0);
       
   893     QList<QState*> result;
       
   894     for (QState *s = state->parentState(); s && s != upperBound; s = s->parentState()) {
       
   895         result.append(s);
       
   896     }
       
   897     return result;
       
   898 }
       
   899 
       
   900 bool QStateMachinePrivate::isInFinalState(QAbstractState* s) const
       
   901 {
       
   902     if (isCompound(s)) {
       
   903         QState *grp = qobject_cast<QState*>(s);
       
   904         QList<QAbstractState*> lst = QStatePrivate::get(grp)->childStates();
       
   905         for (int i = 0; i < lst.size(); ++i) {
       
   906             QAbstractState *cs = lst.at(i);
       
   907             if (isFinal(cs) && configuration.contains(cs))
       
   908                 return true;
       
   909         }
       
   910         return false;
       
   911     } else if (isParallel(s)) {
       
   912         QState *grp = qobject_cast<QState*>(s);
       
   913         QList<QAbstractState*> lst = QStatePrivate::get(grp)->childStates();
       
   914         for (int i = 0; i < lst.size(); ++i) {
       
   915             QAbstractState *cs = lst.at(i);
       
   916             if (!isInFinalState(cs))
       
   917                 return false;
       
   918         }
       
   919         return true;
       
   920     }
       
   921     else
       
   922         return false;
       
   923 }
       
   924 
       
   925 #ifndef QT_NO_PROPERTIES
       
   926 
       
   927 void QStateMachinePrivate::registerRestorable(QObject *object, const QByteArray &propertyName)
       
   928 {
       
   929     RestorableId id(object, propertyName);
       
   930     if (!registeredRestorables.contains(id))
       
   931         registeredRestorables.insert(id, object->property(propertyName));
       
   932 }
       
   933 
       
   934 QList<QPropertyAssignment> QStateMachinePrivate::restorablesToPropertyList(const QHash<RestorableId, QVariant> &restorables) const
       
   935 {
       
   936     QList<QPropertyAssignment> result;
       
   937     QHash<RestorableId, QVariant>::const_iterator it;
       
   938     for (it = restorables.constBegin(); it != restorables.constEnd(); ++it) {
       
   939 //        qDebug() << "restorable:" << it.key().first << it.key().second << it.value();
       
   940         result.append(QPropertyAssignment(it.key().first, it.key().second, it.value(), /*explicitlySet=*/false));
       
   941     }
       
   942     return result;
       
   943 }
       
   944 
       
   945 /*! 
       
   946    \internal
       
   947    Returns true if the variable with the given \a id has been registered for restoration.
       
   948 */
       
   949 bool QStateMachinePrivate::hasRestorable(QObject *object, const QByteArray &propertyName) const
       
   950 {
       
   951     return registeredRestorables.contains(RestorableId(object, propertyName));
       
   952 }
       
   953 
       
   954 QVariant QStateMachinePrivate::restorableValue(QObject *object, const QByteArray &propertyName) const
       
   955 {
       
   956     return registeredRestorables.value(RestorableId(object, propertyName), QVariant());
       
   957 }
       
   958 
       
   959 
       
   960 /*!
       
   961    \internal
       
   962     Unregisters the variable identified by \a id
       
   963 */
       
   964 void QStateMachinePrivate::unregisterRestorable(QObject *object, const QByteArray &propertyName)
       
   965 {
       
   966 //    qDebug() << "unregisterRestorable(" << object << propertyName << ')';
       
   967     RestorableId id(object, propertyName);
       
   968     registeredRestorables.remove(id);
       
   969 }
       
   970 
       
   971 #endif // QT_NO_PROPERTIES
       
   972 
       
   973 QAbstractState *QStateMachinePrivate::findErrorState(QAbstractState *context)
       
   974 {
       
   975     // Find error state recursively in parent hierarchy if not set explicitly for context state
       
   976     QAbstractState *errorState = 0;
       
   977     if (context != 0) {
       
   978         QState *s = qobject_cast<QState*>(context);
       
   979         if (s != 0)
       
   980             errorState = s->errorState();
       
   981 
       
   982         if (errorState == 0)
       
   983             errorState = findErrorState(context->parentState());
       
   984     }
       
   985     
       
   986     return errorState;   
       
   987 }
       
   988 
       
   989 void QStateMachinePrivate::setError(QStateMachine::Error errorCode, QAbstractState *currentContext)
       
   990 {
       
   991     Q_Q(QStateMachine);
       
   992     
       
   993     error = errorCode;
       
   994     switch (errorCode) {
       
   995     case QStateMachine::NoInitialStateError:        
       
   996         Q_ASSERT(currentContext != 0);
       
   997 
       
   998         errorString = QStateMachine::tr("Missing initial state in compound state '%1'")
       
   999                         .arg(currentContext->objectName());
       
  1000 
       
  1001         break;
       
  1002     case QStateMachine::NoDefaultStateInHistoryStateError:
       
  1003         Q_ASSERT(currentContext != 0);
       
  1004 
       
  1005         errorString = QStateMachine::tr("Missing default state in history state '%1'")
       
  1006                         .arg(currentContext->objectName());
       
  1007         break;
       
  1008 
       
  1009     case QStateMachine::NoCommonAncestorForTransitionError:
       
  1010         Q_ASSERT(currentContext != 0);
       
  1011 
       
  1012         errorString = QStateMachine::tr("No common ancestor for targets and source of transition from state '%1'")
       
  1013                         .arg(currentContext->objectName());
       
  1014         break;
       
  1015     default:
       
  1016         errorString = QStateMachine::tr("Unknown error");
       
  1017     };
       
  1018 
       
  1019     pendingErrorStates.clear(); 
       
  1020     pendingErrorStatesForDefaultEntry.clear();
       
  1021 
       
  1022     QAbstractState *currentErrorState = findErrorState(currentContext);
       
  1023 
       
  1024     // Avoid infinite loop if the error state itself has an error
       
  1025     if (currentContext == currentErrorState)
       
  1026         currentErrorState = 0;    
       
  1027 
       
  1028     Q_ASSERT(currentErrorState != rootState());
       
  1029 
       
  1030     if (currentErrorState != 0) {    
       
  1031         QState *lca = findLCA(QList<QAbstractState*>() << currentErrorState << currentContext);
       
  1032         addStatesToEnter(currentErrorState, lca, pendingErrorStates, pendingErrorStatesForDefaultEntry);
       
  1033     } else {
       
  1034         qWarning("Unrecoverable error detected in running state machine: %s", 
       
  1035                  qPrintable(errorString));
       
  1036         q->stop();
       
  1037     }
       
  1038 }
       
  1039 
       
  1040 #ifndef QT_NO_ANIMATION
       
  1041 
       
  1042 QPair<QList<QAbstractAnimation*>, QList<QAbstractAnimation*> >
       
  1043 QStateMachinePrivate::initializeAnimation(QAbstractAnimation *abstractAnimation, 
       
  1044                                           const QPropertyAssignment &prop)
       
  1045 {
       
  1046     QList<QAbstractAnimation*> handledAnimations;
       
  1047     QList<QAbstractAnimation*> localResetEndValues;
       
  1048     QAnimationGroup *group = qobject_cast<QAnimationGroup*>(abstractAnimation);
       
  1049     if (group) {
       
  1050         for (int i = 0; i < group->animationCount(); ++i) {
       
  1051             QAbstractAnimation *animationChild = group->animationAt(i);
       
  1052             QPair<QList<QAbstractAnimation*>, QList<QAbstractAnimation*> > ret;
       
  1053             ret = initializeAnimation(animationChild, prop);
       
  1054             handledAnimations << ret.first;
       
  1055             localResetEndValues << ret.second;
       
  1056         }
       
  1057     } else { 
       
  1058         QPropertyAnimation *animation = qobject_cast<QPropertyAnimation *>(abstractAnimation);
       
  1059         if (animation != 0 
       
  1060             && prop.object == animation->targetObject()
       
  1061             && prop.propertyName == animation->propertyName()) {
       
  1062 
       
  1063             // Only change end value if it is undefined
       
  1064             if (!animation->endValue().isValid()) {
       
  1065                 animation->setEndValue(prop.value);
       
  1066                 localResetEndValues.append(animation);
       
  1067             }
       
  1068             handledAnimations.append(animation);
       
  1069         }
       
  1070     }
       
  1071     return qMakePair(handledAnimations, localResetEndValues);
       
  1072 }
       
  1073 
       
  1074 void QStateMachinePrivate::_q_animationFinished()
       
  1075 {
       
  1076     Q_Q(QStateMachine);
       
  1077     QAbstractAnimation *anim = qobject_cast<QAbstractAnimation*>(q->sender());
       
  1078     Q_ASSERT(anim != 0);
       
  1079     QObject::disconnect(anim, SIGNAL(finished()), q, SLOT(_q_animationFinished()));
       
  1080     if (resetAnimationEndValues.contains(anim)) {
       
  1081         qobject_cast<QVariantAnimation*>(anim)->setEndValue(QVariant()); // ### generalize
       
  1082         resetAnimationEndValues.remove(anim);
       
  1083     }
       
  1084 
       
  1085 #ifndef QT_NO_PROPERTIES
       
  1086     // Set the final property value.
       
  1087     QPropertyAssignment assn = propertyForAnimation.take(anim);
       
  1088     Q_ASSERT(assn.object != 0);
       
  1089     assn.object->setProperty(assn.propertyName, assn.value);
       
  1090     if (!assn.explicitlySet)
       
  1091         unregisterRestorable(assn.object, assn.propertyName);
       
  1092 #endif
       
  1093 
       
  1094     QAbstractState *state = stateForAnimation.take(anim);
       
  1095     Q_ASSERT(state != 0);
       
  1096     QHash<QAbstractState*, QList<QAbstractAnimation*> >::iterator it;
       
  1097     it = animationsForState.find(state);
       
  1098     Q_ASSERT(it != animationsForState.end());
       
  1099     QList<QAbstractAnimation*> &animations = it.value();
       
  1100     animations.removeOne(anim);
       
  1101     if (animations.isEmpty()) {
       
  1102         animationsForState.erase(it);
       
  1103         QStatePrivate::get(qobject_cast<QState*>(state))->emitPolished();
       
  1104     }
       
  1105 }
       
  1106 
       
  1107 #endif // !QT_NO_ANIMATION
       
  1108 
       
  1109 namespace {
       
  1110 
       
  1111 class StartState : public QState
       
  1112 {
       
  1113 public:
       
  1114     StartState(QState *parent)
       
  1115         : QState(parent) {}
       
  1116 protected:
       
  1117     void onEntry(QEvent *) {}
       
  1118     void onExit(QEvent *) {}
       
  1119 };
       
  1120 
       
  1121 class InitialTransition : public QAbstractTransition
       
  1122 {
       
  1123 public:
       
  1124     InitialTransition(QAbstractState *target)
       
  1125         : QAbstractTransition()
       
  1126     { setTargetState(target); }
       
  1127 protected:
       
  1128     virtual bool eventTest(QEvent *) { return true; }
       
  1129     virtual void onTransition(QEvent *) {}
       
  1130 };
       
  1131 
       
  1132 } // namespace
       
  1133 
       
  1134 QState *QStateMachinePrivate::startState()
       
  1135 {
       
  1136     Q_Q(QStateMachine);
       
  1137     if (_startState == 0)
       
  1138         _startState = new StartState(q);
       
  1139     return _startState;
       
  1140 }
       
  1141 
       
  1142 void QStateMachinePrivate::removeStartState()
       
  1143 {
       
  1144     delete _startState;
       
  1145     _startState = 0;
       
  1146 }
       
  1147 
       
  1148 void QStateMachinePrivate::_q_start()
       
  1149 {
       
  1150     Q_Q(QStateMachine);
       
  1151     Q_ASSERT(state == Starting);
       
  1152     Q_ASSERT(rootState() != 0);
       
  1153     QAbstractState *initial = rootState()->initialState();
       
  1154     configuration.clear();
       
  1155     qDeleteAll(internalEventQueue);
       
  1156     internalEventQueue.clear();
       
  1157     qDeleteAll(externalEventQueue);
       
  1158     externalEventQueue.clear();
       
  1159 
       
  1160 #ifdef QSTATEMACHINE_DEBUG
       
  1161     qDebug() << q << ": starting";
       
  1162 #endif
       
  1163     state = Running;
       
  1164     processingScheduled = true; // we call _q_process() below
       
  1165     emit q->started();
       
  1166 
       
  1167     QState *start = startState();
       
  1168     Q_ASSERT(start != 0);
       
  1169 
       
  1170     QList<QAbstractTransition*> transitions = QStatePrivate::get(start)->transitions();
       
  1171 
       
  1172     // If a transition has already been added, then we skip this step, as the
       
  1173     // initial transition in that case has been overridden.
       
  1174     if (transitions.isEmpty()) {
       
  1175         QAbstractTransition *initialTransition = new InitialTransition(initial);
       
  1176         start->addTransition(initialTransition);
       
  1177         transitions.append(initialTransition);
       
  1178     }
       
  1179 
       
  1180     QEvent nullEvent(QEvent::None);
       
  1181     executeTransitionContent(&nullEvent, transitions);
       
  1182     QList<QAbstractState*> enteredStates = enterStates(&nullEvent, transitions);
       
  1183 #ifndef QT_NO_PROPERTIES
       
  1184     applyProperties(transitions, QList<QAbstractState*>() << start,
       
  1185                     enteredStates);
       
  1186 #endif
       
  1187     removeStartState();
       
  1188 
       
  1189 #ifdef QSTATEMACHINE_DEBUG
       
  1190     qDebug() << q << ": initial configuration:" << configuration;
       
  1191 #endif
       
  1192     _q_process();
       
  1193 }
       
  1194 
       
  1195 void QStateMachinePrivate::_q_process()
       
  1196 {
       
  1197     Q_Q(QStateMachine);
       
  1198     Q_ASSERT(state == Running);
       
  1199     Q_ASSERT(!processing);
       
  1200     processing = true;
       
  1201     processingScheduled = false;
       
  1202 #ifdef QSTATEMACHINE_DEBUG
       
  1203     qDebug() << q << ": starting the event processing loop";
       
  1204 #endif
       
  1205     while (processing) {
       
  1206         if (stop) {
       
  1207             stop = false;
       
  1208             processing = false;
       
  1209             stopProcessingReason = Stopped;
       
  1210             break;
       
  1211         }
       
  1212         QSet<QAbstractTransition*> enabledTransitions;
       
  1213         QEvent *e = new QEvent(QEvent::None);
       
  1214         enabledTransitions = selectTransitions(e);
       
  1215         if (enabledTransitions.isEmpty()) {
       
  1216             delete e;
       
  1217             e = 0;
       
  1218         }
       
  1219         if (enabledTransitions.isEmpty() && !internalEventQueue.isEmpty()) {
       
  1220             e = internalEventQueue.takeFirst();
       
  1221 #ifdef QSTATEMACHINE_DEBUG
       
  1222             qDebug() << q << ": dequeued internal event" << e << "of type" << e->type();
       
  1223 #endif
       
  1224             enabledTransitions = selectTransitions(e);
       
  1225             if (enabledTransitions.isEmpty()) {
       
  1226                 delete e;
       
  1227                 e = 0;
       
  1228             }
       
  1229         }
       
  1230         if (enabledTransitions.isEmpty()) {
       
  1231             if (externalEventQueue.isEmpty()) {
       
  1232                 if (internalEventQueue.isEmpty()) {
       
  1233                     processing = false;
       
  1234                     stopProcessingReason = EventQueueEmpty;
       
  1235                 }
       
  1236             } else {
       
  1237                 e = externalEventQueue.takeFirst();
       
  1238 #ifdef QSTATEMACHINE_DEBUG
       
  1239                 qDebug() << q << ": dequeued external event" << e << "of type" << e->type();
       
  1240 #endif
       
  1241                 enabledTransitions = selectTransitions(e);
       
  1242                 if (enabledTransitions.isEmpty()) {
       
  1243                     delete e;
       
  1244                     e = 0;
       
  1245                 }
       
  1246             }
       
  1247         }
       
  1248         if (!enabledTransitions.isEmpty()) {
       
  1249             q->beginMicrostep(e);
       
  1250             microstep(e, enabledTransitions.toList());
       
  1251             q->endMicrostep(e);
       
  1252         }
       
  1253 #ifdef QSTATEMACHINE_DEBUG
       
  1254         else {
       
  1255             qDebug() << q << ": no transitions enabled";
       
  1256         }
       
  1257 #endif
       
  1258         delete e;
       
  1259     }
       
  1260 #ifdef QSTATEMACHINE_DEBUG
       
  1261     qDebug() << q << ": finished the event processing loop";
       
  1262 #endif
       
  1263     switch (stopProcessingReason) {
       
  1264     case EventQueueEmpty:
       
  1265         break;
       
  1266     case Finished:
       
  1267         state = NotRunning;
       
  1268         cancelAllDelayedEvents();
       
  1269         unregisterAllTransitions();
       
  1270         emit q->finished();
       
  1271         break;
       
  1272     case Stopped:
       
  1273         state = NotRunning;
       
  1274         cancelAllDelayedEvents();
       
  1275         unregisterAllTransitions();
       
  1276         emit q->stopped();
       
  1277         break;
       
  1278     }
       
  1279 }
       
  1280 
       
  1281 void QStateMachinePrivate::processEvents(EventProcessingMode processingMode)
       
  1282 {
       
  1283     if ((state != Running) || processing || processingScheduled)
       
  1284         return;
       
  1285     switch (processingMode) {
       
  1286     case DirectProcessing:
       
  1287         _q_process();
       
  1288         break;
       
  1289     case QueuedProcessing:
       
  1290         processingScheduled = true;
       
  1291         QMetaObject::invokeMethod(q_func(), "_q_process", Qt::QueuedConnection);
       
  1292         break;
       
  1293     }
       
  1294 }
       
  1295 
       
  1296 void QStateMachinePrivate::cancelAllDelayedEvents()
       
  1297 {
       
  1298     Q_Q(QStateMachine);
       
  1299     QHash<int, QEvent*>::const_iterator it;
       
  1300     for (it = delayedEvents.constBegin(); it != delayedEvents.constEnd(); ++it) {
       
  1301         int id = it.key();
       
  1302         QEvent *e = it.value();
       
  1303         q->killTimer(id);
       
  1304         delete e;
       
  1305     }
       
  1306     delayedEvents.clear();
       
  1307 }
       
  1308 
       
  1309 namespace {
       
  1310 
       
  1311 class GoToStateTransition : public QAbstractTransition
       
  1312 {
       
  1313 public:
       
  1314     GoToStateTransition(QAbstractState *target)
       
  1315         : QAbstractTransition()
       
  1316     { setTargetState(target); }
       
  1317 protected:
       
  1318     void onTransition(QEvent *) { deleteLater(); }
       
  1319     bool eventTest(QEvent *) { return true; }
       
  1320 };
       
  1321 
       
  1322 } // namespace
       
  1323 
       
  1324 /*!
       
  1325   \internal
       
  1326 
       
  1327   Causes this state machine to unconditionally transition to the given
       
  1328   \a targetState.
       
  1329 
       
  1330   Provides a backdoor for using the state machine "imperatively"; i.e.  rather
       
  1331   than defining explicit transitions, you drive the machine's execution by
       
  1332   calling this function. It breaks the whole integrity of the
       
  1333   transition-driven model, but is provided for pragmatic reasons.
       
  1334 */
       
  1335 void QStateMachinePrivate::goToState(QAbstractState *targetState)
       
  1336 {
       
  1337     if (!targetState) {
       
  1338         qWarning("QStateMachine::goToState(): cannot go to null state");
       
  1339         return;
       
  1340     }
       
  1341 
       
  1342     if (configuration.contains(targetState))
       
  1343         return;
       
  1344 
       
  1345     QState *sourceState = 0;
       
  1346     if (state == Running) {
       
  1347         QSet<QAbstractState*>::const_iterator it;
       
  1348         for (it = configuration.constBegin(); it != configuration.constEnd(); ++it) {
       
  1349             sourceState = qobject_cast<QState*>(*it);
       
  1350             if (sourceState != 0)
       
  1351                 break;
       
  1352         }
       
  1353     } else {
       
  1354         sourceState = startState();
       
  1355     }    
       
  1356 
       
  1357     Q_ASSERT(sourceState != 0);
       
  1358     // Reuse previous GoToStateTransition in case of several calls to
       
  1359     // goToState() in a row.
       
  1360     GoToStateTransition *trans = qFindChild<GoToStateTransition*>(sourceState);
       
  1361     if (!trans) {
       
  1362         trans = new GoToStateTransition(targetState);
       
  1363         sourceState->addTransition(trans);
       
  1364     } else {
       
  1365         trans->setTargetState(targetState);
       
  1366     }
       
  1367 
       
  1368     processEvents(QueuedProcessing);
       
  1369 }
       
  1370 
       
  1371 void QStateMachinePrivate::registerTransitions(QAbstractState *state)
       
  1372 {
       
  1373     QState *group = qobject_cast<QState*>(state);
       
  1374     if (!group)
       
  1375         return;
       
  1376     QList<QAbstractTransition*> transitions = QStatePrivate::get(group)->transitions();
       
  1377     for (int i = 0; i < transitions.size(); ++i) {
       
  1378         QAbstractTransition *t = transitions.at(i);
       
  1379         if (QSignalTransition *st = qobject_cast<QSignalTransition*>(t)) {
       
  1380             registerSignalTransition(st);
       
  1381         }
       
  1382 #ifndef QT_NO_STATEMACHINE_EVENTFILTER
       
  1383         else if (QEventTransition *oet = qobject_cast<QEventTransition*>(t)) {
       
  1384             registerEventTransition(oet);
       
  1385         }
       
  1386 #endif
       
  1387     }
       
  1388 }
       
  1389 
       
  1390 void QStateMachinePrivate::unregisterTransition(QAbstractTransition *transition)
       
  1391 {
       
  1392     if (QSignalTransition *st = qobject_cast<QSignalTransition*>(transition)) {
       
  1393         unregisterSignalTransition(st);
       
  1394     }
       
  1395 #ifndef QT_NO_STATEMACHINE_EVENTFILTER
       
  1396     else if (QEventTransition *oet = qobject_cast<QEventTransition*>(transition)) {
       
  1397         unregisterEventTransition(oet);
       
  1398     }
       
  1399 #endif
       
  1400 }
       
  1401 
       
  1402 void QStateMachinePrivate::registerSignalTransition(QSignalTransition *transition)
       
  1403 {
       
  1404     Q_Q(QStateMachine);
       
  1405     if (QSignalTransitionPrivate::get(transition)->signalIndex != -1)
       
  1406         return; // already registered
       
  1407     QObject *sender = QSignalTransitionPrivate::get(transition)->sender;
       
  1408     if (!sender)
       
  1409         return;
       
  1410     QByteArray signal = QSignalTransitionPrivate::get(transition)->signal;
       
  1411     if (signal.startsWith('0'+QSIGNAL_CODE))
       
  1412         signal.remove(0, 1);
       
  1413     const QMetaObject *meta = sender->metaObject();
       
  1414     int signalIndex = meta->indexOfSignal(signal);
       
  1415     int originalSignalIndex = signalIndex;
       
  1416     if (signalIndex == -1) {
       
  1417         signalIndex = meta->indexOfSignal(QMetaObject::normalizedSignature(signal));
       
  1418         if (signalIndex == -1) {
       
  1419             qWarning("QSignalTransition: no such signal: %s::%s",
       
  1420                      meta->className(), signal.constData());
       
  1421             return;
       
  1422         }
       
  1423     }
       
  1424     // The signal index we actually want to connect to is the one
       
  1425     // that is going to be sent, i.e. the non-cloned original index.
       
  1426     while (meta->method(signalIndex).attributes() & QMetaMethod::Cloned)
       
  1427         --signalIndex;
       
  1428 
       
  1429     QVector<int> &connectedSignalIndexes = connections[sender];
       
  1430     if (connectedSignalIndexes.size() <= signalIndex)
       
  1431         connectedSignalIndexes.resize(signalIndex+1);
       
  1432     if (connectedSignalIndexes.at(signalIndex) == 0) {
       
  1433         if (!signalEventGenerator)
       
  1434             signalEventGenerator = new QSignalEventGenerator(q);
       
  1435         bool ok = QMetaObject::connect(sender, signalIndex, signalEventGenerator,
       
  1436                                        signalEventGenerator->metaObject()->methodOffset());
       
  1437         if (!ok) {
       
  1438 #ifdef QSTATEMACHINE_DEBUG
       
  1439             qDebug() << q << ": FAILED to add signal transition from" << transition->sourceState()
       
  1440                      << ": ( sender =" << sender << ", signal =" << signal
       
  1441                      << ", targets =" << transition->targetStates() << ')';
       
  1442 #endif
       
  1443             return;
       
  1444         }
       
  1445     }
       
  1446     ++connectedSignalIndexes[signalIndex];
       
  1447     QSignalTransitionPrivate::get(transition)->signalIndex = signalIndex;
       
  1448     QSignalTransitionPrivate::get(transition)->originalSignalIndex = originalSignalIndex;
       
  1449 #ifdef QSTATEMACHINE_DEBUG
       
  1450     qDebug() << q << ": added signal transition from" << transition->sourceState()
       
  1451              << ": ( sender =" << sender << ", signal =" << signal
       
  1452              << ", targets =" << transition->targetStates() << ')';
       
  1453 #endif
       
  1454 }
       
  1455 
       
  1456 void QStateMachinePrivate::unregisterSignalTransition(QSignalTransition *transition)
       
  1457 {
       
  1458     int signalIndex = QSignalTransitionPrivate::get(transition)->signalIndex;
       
  1459     if (signalIndex == -1)
       
  1460         return; // not registered
       
  1461     QSignalTransitionPrivate::get(transition)->signalIndex = -1;
       
  1462     const QObject *sender = QSignalTransitionPrivate::get(transition)->sender;
       
  1463     QVector<int> &connectedSignalIndexes = connections[sender];
       
  1464     Q_ASSERT(connectedSignalIndexes.size() > signalIndex);
       
  1465     Q_ASSERT(connectedSignalIndexes.at(signalIndex) != 0);
       
  1466     if (--connectedSignalIndexes[signalIndex] == 0) {
       
  1467         Q_ASSERT(signalEventGenerator != 0);
       
  1468         QMetaObject::disconnect(sender, signalIndex, signalEventGenerator,
       
  1469                                 signalEventGenerator->metaObject()->methodOffset());
       
  1470         int sum = 0;
       
  1471         for (int i = 0; i < connectedSignalIndexes.size(); ++i)
       
  1472             sum += connectedSignalIndexes.at(i);
       
  1473         if (sum == 0)
       
  1474             connections.remove(sender);
       
  1475     }
       
  1476 }
       
  1477 
       
  1478 void QStateMachinePrivate::unregisterAllTransitions()
       
  1479 {
       
  1480     Q_Q(QStateMachine);
       
  1481     {
       
  1482         QList<QSignalTransition*> transitions = qFindChildren<QSignalTransition*>(rootState());
       
  1483         for (int i = 0; i < transitions.size(); ++i) {
       
  1484             QSignalTransition *t = transitions.at(i);
       
  1485             if (t->machine() == q)
       
  1486                 unregisterSignalTransition(t);
       
  1487         }
       
  1488     }
       
  1489     {
       
  1490         QList<QEventTransition*> transitions = qFindChildren<QEventTransition*>(rootState());
       
  1491         for (int i = 0; i < transitions.size(); ++i) {
       
  1492             QEventTransition *t = transitions.at(i);
       
  1493             if (t->machine() == q)
       
  1494                 unregisterEventTransition(t);
       
  1495         }
       
  1496     }
       
  1497 }
       
  1498 
       
  1499 #ifndef QT_NO_STATEMACHINE_EVENTFILTER
       
  1500 void QStateMachinePrivate::registerEventTransition(QEventTransition *transition)
       
  1501 {
       
  1502     Q_Q(QStateMachine);
       
  1503     if (QEventTransitionPrivate::get(transition)->registered)
       
  1504         return;
       
  1505     if (transition->eventType() >= QEvent::User) {
       
  1506         qWarning("QObject event transitions are not supported for custom types");
       
  1507         return;
       
  1508     }
       
  1509     QObject *object = QEventTransitionPrivate::get(transition)->object;
       
  1510     if (!object)
       
  1511         return;
       
  1512     QObjectPrivate *od = QObjectPrivate::get(object);
       
  1513     if (!od->eventFilters.contains(q))
       
  1514         object->installEventFilter(q);
       
  1515     ++qobjectEvents[object][transition->eventType()];
       
  1516     QEventTransitionPrivate::get(transition)->registered = true;
       
  1517 #ifdef QSTATEMACHINE_DEBUG
       
  1518     qDebug() << q << ": added event transition from" << transition->sourceState()
       
  1519              << ": ( object =" << object << ", event =" << transition->eventType()
       
  1520              << ", targets =" << transition->targetStates() << ')';
       
  1521 #endif
       
  1522 }
       
  1523 
       
  1524 void QStateMachinePrivate::unregisterEventTransition(QEventTransition *transition)
       
  1525 {
       
  1526     Q_Q(QStateMachine);
       
  1527     if (!QEventTransitionPrivate::get(transition)->registered)
       
  1528         return;
       
  1529     QObject *object = QEventTransitionPrivate::get(transition)->object;
       
  1530     QHash<QEvent::Type, int> &events = qobjectEvents[object];
       
  1531     Q_ASSERT(events.value(transition->eventType()) > 0);
       
  1532     if (--events[transition->eventType()] == 0) {
       
  1533         events.remove(transition->eventType());
       
  1534         int sum = 0;
       
  1535         QHash<QEvent::Type, int>::const_iterator it;
       
  1536         for (it = events.constBegin(); it != events.constEnd(); ++it)
       
  1537             sum += it.value();
       
  1538         if (sum == 0) {
       
  1539             qobjectEvents.remove(object);
       
  1540             object->removeEventFilter(q);
       
  1541         }
       
  1542     }
       
  1543     QEventTransitionPrivate::get(transition)->registered = false;
       
  1544 }
       
  1545 
       
  1546 void QStateMachinePrivate::handleFilteredEvent(QObject *watched, QEvent *event)
       
  1547 {
       
  1548     Q_ASSERT(qobjectEvents.contains(watched));
       
  1549     if (qobjectEvents[watched].contains(event->type())) {
       
  1550         internalEventQueue.append(new QStateMachine::WrappedEvent(watched, handler->cloneEvent(event)));
       
  1551         processEvents(DirectProcessing);
       
  1552     }
       
  1553 }
       
  1554 #endif
       
  1555 
       
  1556 void QStateMachinePrivate::handleTransitionSignal(QObject *sender, int signalIndex,
       
  1557                                                   void **argv)
       
  1558 {
       
  1559     Q_ASSERT(connections[sender].at(signalIndex) != 0);
       
  1560     const QMetaObject *meta = sender->metaObject();
       
  1561     QMetaMethod method = meta->method(signalIndex);
       
  1562     QList<QByteArray> parameterTypes = method.parameterTypes();
       
  1563     int argc = parameterTypes.count();
       
  1564     QList<QVariant> vargs;
       
  1565     for (int i = 0; i < argc; ++i) {
       
  1566         int type = QMetaType::type(parameterTypes.at(i));
       
  1567         vargs.append(QVariant(type, argv[i+1]));
       
  1568     }
       
  1569 
       
  1570 #ifdef QSTATEMACHINE_DEBUG
       
  1571     qDebug() << q_func() << ": sending signal event ( sender =" << sender
       
  1572              << ", signal =" << sender->metaObject()->method(signalIndex).signature() << ')';
       
  1573 #endif
       
  1574     internalEventQueue.append(new QStateMachine::SignalEvent(sender, signalIndex, vargs));
       
  1575     processEvents(DirectProcessing);
       
  1576 }
       
  1577 
       
  1578 /*!
       
  1579   Constructs a new state machine with the given \a parent.
       
  1580 */
       
  1581 QStateMachine::QStateMachine(QObject *parent)
       
  1582     : QState(*new QStateMachinePrivate, /*parentState=*/0)
       
  1583 {
       
  1584     // Can't pass the parent to the QState constructor, as it expects a QState
       
  1585     // But this works as expected regardless of whether parent is a QState or not
       
  1586     setParent(parent);
       
  1587 }
       
  1588 
       
  1589 /*!
       
  1590   \internal
       
  1591 */
       
  1592 QStateMachine::QStateMachine(QStateMachinePrivate &dd, QObject *parent)
       
  1593     : QState(dd, /*parentState=*/0)
       
  1594 {
       
  1595     setParent(parent);
       
  1596 }
       
  1597 
       
  1598 /*!
       
  1599   Destroys this state machine.
       
  1600 */
       
  1601 QStateMachine::~QStateMachine()
       
  1602 {
       
  1603 }
       
  1604 
       
  1605 /*!
       
  1606   \enum QStateMachine::EventPriority
       
  1607 
       
  1608   This enum type specifies the priority of an event posted to the state
       
  1609   machine using postEvent().
       
  1610 
       
  1611   Events of high priority are processed before events of normal priority.
       
  1612 
       
  1613   \value NormalPriority The event has normal priority.
       
  1614   \value HighPriority The event has high priority.
       
  1615 */
       
  1616 
       
  1617 /*! \enum QStateMachine::Error 
       
  1618 
       
  1619     This enum type defines errors that can occur in the state machine at run time. When the state
       
  1620     machine encounters an unrecoverable error at run time, it will set the error code returned 
       
  1621     by error(), the error message returned by errorString(), and enter an error state based on 
       
  1622     the context of the error.
       
  1623 
       
  1624     \value NoError No error has occurred.
       
  1625     \value NoInitialStateError The machine has entered a QState with children which does not have an
       
  1626            initial state set. The context of this error is the state which is missing an initial
       
  1627            state.
       
  1628     \value NoDefaultStateInHistoryStateError The machine has entered a QHistoryState which does not have 
       
  1629            a default state set. The context of this error is the QHistoryState which is missing a
       
  1630            default state.
       
  1631     \value NoCommonAncestorForTransitionError The machine has selected a transition whose source 
       
  1632            and targets are not part of the same tree of states, and thus are not part of the same 
       
  1633            state machine. Commonly, this could mean that one of the states has not been given 
       
  1634            any parent or added to any machine. The context of this error is the source state of 
       
  1635            the transition.
       
  1636 
       
  1637     \sa setErrorState()
       
  1638 */
       
  1639 
       
  1640 /*!
       
  1641    \enum QStateMachine::RestorePolicy
       
  1642 
       
  1643    This enum specifies the restore policy type. The restore policy
       
  1644    takes effect when the machine enters a state which sets one or more
       
  1645    properties. If the restore policy is set to RestoreProperties,
       
  1646    the state machine will save the original value of the property before the
       
  1647    new value is set.
       
  1648 
       
  1649    Later, when the machine either enters a state which does not set
       
  1650    a value for the given property, the property will automatically be restored
       
  1651    to its initial value.
       
  1652 
       
  1653    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
       
  1655    successfully restored. 
       
  1656 
       
  1657    \value DoNotRestoreProperties The state machine should not save the initial values of properties 
       
  1658           and restore them later.
       
  1659    \value RestoreProperties The state machine should save the initial values of properties 
       
  1660           and restore them later.
       
  1661 
       
  1662    \sa QStateMachine::globalRestorePolicy QState::assignProperty()
       
  1663 */
       
  1664 
       
  1665 
       
  1666 /*!
       
  1667   Returns the error code of the last error that occurred in the state machine.
       
  1668 */
       
  1669 QStateMachine::Error QStateMachine::error() const
       
  1670 {
       
  1671     Q_D(const QStateMachine);
       
  1672     return d->error;
       
  1673 }
       
  1674 
       
  1675 /*!
       
  1676   Returns the error string of the last error that occurred in the state machine.
       
  1677 */
       
  1678 QString QStateMachine::errorString() const
       
  1679 {
       
  1680     Q_D(const QStateMachine);
       
  1681     return d->errorString;
       
  1682 }
       
  1683 
       
  1684 /*!
       
  1685   Clears the error string and error code of the state machine.
       
  1686 */
       
  1687 void QStateMachine::clearError()
       
  1688 {
       
  1689     Q_D(QStateMachine);
       
  1690     d->errorString.clear();
       
  1691     d->error = NoError;
       
  1692 }
       
  1693 
       
  1694 /*!
       
  1695    Returns the restore policy of the state machine.
       
  1696 
       
  1697    \sa setGlobalRestorePolicy()
       
  1698 */
       
  1699 QStateMachine::RestorePolicy QStateMachine::globalRestorePolicy() const
       
  1700 {
       
  1701     Q_D(const QStateMachine);
       
  1702     return d->globalRestorePolicy;
       
  1703 }
       
  1704 
       
  1705 /*!
       
  1706    Sets the restore policy of the state machine to \a restorePolicy. The default 
       
  1707    restore policy is QAbstractState::DoNotRestoreProperties.
       
  1708    
       
  1709    \sa globalRestorePolicy()
       
  1710 */
       
  1711 void QStateMachine::setGlobalRestorePolicy(QStateMachine::RestorePolicy restorePolicy) 
       
  1712 {
       
  1713     Q_D(QStateMachine);
       
  1714     d->globalRestorePolicy = restorePolicy;
       
  1715 }
       
  1716 
       
  1717 /*!
       
  1718   Adds the given \a state to this state machine. The state becomes a top-level
       
  1719   state.
       
  1720 
       
  1721   If the state is already in a different machine, it will first be removed
       
  1722   from its old machine, and then added to this machine.
       
  1723 
       
  1724   \sa removeState(), setInitialState()
       
  1725 */
       
  1726 void QStateMachine::addState(QAbstractState *state)
       
  1727 {
       
  1728     if (!state) {
       
  1729         qWarning("QStateMachine::addState: cannot add null state");
       
  1730         return;
       
  1731     }
       
  1732     if (QAbstractStatePrivate::get(state)->machine() == this) {
       
  1733         qWarning("QStateMachine::addState: state has already been added to this machine");
       
  1734         return;
       
  1735     }
       
  1736     state->setParent(this);
       
  1737 }
       
  1738 
       
  1739 /*!
       
  1740   Removes the given \a state from this state machine.  The state machine
       
  1741   releases ownership of the state.
       
  1742 
       
  1743   \sa addState()
       
  1744 */
       
  1745 void QStateMachine::removeState(QAbstractState *state)
       
  1746 {
       
  1747     if (!state) {
       
  1748         qWarning("QStateMachine::removeState: cannot remove null state");
       
  1749         return;
       
  1750     }
       
  1751     if (QAbstractStatePrivate::get(state)->machine() != this) {
       
  1752         qWarning("QStateMachine::removeState: state %p's machine (%p)"
       
  1753                  " is different from this machine (%p)",
       
  1754                  state, QAbstractStatePrivate::get(state)->machine(), this);
       
  1755         return;
       
  1756     }
       
  1757     state->setParent(0);
       
  1758 }
       
  1759 
       
  1760 /*!
       
  1761   Returns whether this state machine is running.
       
  1762 
       
  1763   start(), stop()
       
  1764 */
       
  1765 bool QStateMachine::isRunning() const
       
  1766 {
       
  1767     Q_D(const QStateMachine);
       
  1768     return (d->state == QStateMachinePrivate::Running);
       
  1769 }
       
  1770 
       
  1771 /*!
       
  1772   Starts this state machine.  The machine will reset its configuration and
       
  1773   transition to the initial state.  When a final top-level state (QFinalState)
       
  1774   is entered, the machine will emit the finished() signal.
       
  1775 
       
  1776   \note A state machine will not run without a running event loop, such as
       
  1777   the main application event loop started with QCoreApplication::exec() or
       
  1778   QApplication::exec().
       
  1779 
       
  1780   \sa started(), finished(), stop(), initialState()
       
  1781 */
       
  1782 void QStateMachine::start()
       
  1783 {
       
  1784     Q_D(QStateMachine);
       
  1785 
       
  1786     if (initialState() == 0) {
       
  1787         qWarning("QStateMachine::start: No initial state set for machine. Refusing to start.");
       
  1788         return;
       
  1789     }
       
  1790 
       
  1791     switch (d->state) {
       
  1792     case QStateMachinePrivate::NotRunning:
       
  1793         d->state = QStateMachinePrivate::Starting;
       
  1794         QMetaObject::invokeMethod(this, "_q_start", Qt::QueuedConnection);
       
  1795         break;
       
  1796     case QStateMachinePrivate::Starting:
       
  1797         break;
       
  1798     case QStateMachinePrivate::Running:
       
  1799         qWarning("QStateMachine::start(): already running");
       
  1800         break;
       
  1801     }
       
  1802 }
       
  1803 
       
  1804 /*!
       
  1805   Stops this state machine. The state machine will stop processing events and
       
  1806   then emit the stopped() signal.
       
  1807 
       
  1808   \sa stopped(), start()
       
  1809 */
       
  1810 void QStateMachine::stop()
       
  1811 {
       
  1812     Q_D(QStateMachine);
       
  1813     switch (d->state) {
       
  1814     case QStateMachinePrivate::NotRunning:
       
  1815         break;
       
  1816     case QStateMachinePrivate::Starting:
       
  1817         // the machine will exit as soon as it enters the event processing loop
       
  1818         d->stop = true;
       
  1819         break;
       
  1820     case QStateMachinePrivate::Running:
       
  1821         d->stop = true;
       
  1822         d->processEvents(QStateMachinePrivate::QueuedProcessing);
       
  1823         break;
       
  1824     }
       
  1825 }
       
  1826 
       
  1827 /*!
       
  1828   Posts the given \a event of the given \a priority for processing by this
       
  1829   state machine.
       
  1830 
       
  1831   This function returns immediately. The event is added to the state machine's
       
  1832   event queue. Events are processed in the order posted. The state machine
       
  1833   takes ownership of the event and deletes it once it has been processed.
       
  1834 
       
  1835   You can only post events when the state machine is running.
       
  1836 
       
  1837   \sa postDelayedEvent()
       
  1838 */
       
  1839 void QStateMachine::postEvent(QEvent *event, EventPriority priority)
       
  1840 {
       
  1841     Q_D(QStateMachine);
       
  1842     if (d->state != QStateMachinePrivate::Running) {
       
  1843         qWarning("QStateMachine::postEvent: cannot post event when the state machine is not running");
       
  1844         return;
       
  1845     }
       
  1846     if (!event) {
       
  1847         qWarning("QStateMachine::postEvent: cannot post null event");
       
  1848         return;
       
  1849     }
       
  1850 #ifdef QSTATEMACHINE_DEBUG
       
  1851     qDebug() << this << ": posting event" << event;
       
  1852 #endif
       
  1853     switch (priority) {
       
  1854     case NormalPriority:
       
  1855         d->externalEventQueue.append(event);
       
  1856         break;
       
  1857     case HighPriority:
       
  1858         d->internalEventQueue.append(event);
       
  1859         break;
       
  1860     }
       
  1861     d->processEvents(QStateMachinePrivate::QueuedProcessing);
       
  1862 }
       
  1863 
       
  1864 /*!
       
  1865   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
       
  1867   delayed event, or -1 if the event could not be posted.
       
  1868 
       
  1869   This function returns immediately. When the delay has expired, the event
       
  1870   will be added to the state machine's event queue for processing. The state
       
  1871   machine takes ownership of the event and deletes it once it has been
       
  1872   processed.
       
  1873 
       
  1874   You can only post events when the state machine is running.
       
  1875 
       
  1876   \sa cancelDelayedEvent(), postEvent()
       
  1877 */
       
  1878 int QStateMachine::postDelayedEvent(QEvent *event, int delay)
       
  1879 {
       
  1880     Q_D(QStateMachine);
       
  1881     if (d->state != QStateMachinePrivate::Running) {
       
  1882         qWarning("QStateMachine::postDelayedEvent: cannot post event when the state machine is not running");
       
  1883         return -1;
       
  1884     }
       
  1885     if (!event) {
       
  1886         qWarning("QStateMachine::postDelayedEvent: cannot post null event");
       
  1887         return -1;
       
  1888     }
       
  1889     if (delay < 0) {
       
  1890         qWarning("QStateMachine::postDelayedEvent: delay cannot be negative");
       
  1891         return -1;
       
  1892     }
       
  1893 #ifdef QSTATEMACHINE_DEBUG
       
  1894     qDebug() << this << ": posting event" << event << "with delay" << delay;
       
  1895 #endif
       
  1896     int tid = startTimer(delay);
       
  1897     d->delayedEvents[tid] = event;
       
  1898     return tid;
       
  1899 }
       
  1900 
       
  1901 /*!
       
  1902   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
       
  1904   was successfully cancelled, otherwise returns false.
       
  1905 
       
  1906   \sa postDelayedEvent()
       
  1907 */
       
  1908 bool QStateMachine::cancelDelayedEvent(int id)
       
  1909 {
       
  1910     Q_D(QStateMachine);
       
  1911     if (d->state != QStateMachinePrivate::Running) {
       
  1912         qWarning("QStateMachine::cancelDelayedEvent: the machine is not running");
       
  1913         return false;
       
  1914     }
       
  1915     QEvent *e = d->delayedEvents.take(id);
       
  1916     if (!e)
       
  1917         return false;
       
  1918     killTimer(id);
       
  1919     delete e;
       
  1920     return true;
       
  1921 }
       
  1922 
       
  1923 /*!
       
  1924   \internal
       
  1925 
       
  1926    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
       
  1928    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
       
  1930    configuration.
       
  1931 */
       
  1932 QSet<QAbstractState*> QStateMachine::configuration() const
       
  1933 {
       
  1934     Q_D(const QStateMachine);
       
  1935     return d->configuration;
       
  1936 }
       
  1937 
       
  1938 /*!
       
  1939   \fn QStateMachine::started()
       
  1940 
       
  1941   This signal is emitted when the state machine has entered its initial state
       
  1942   (QStateMachine::initialState).
       
  1943 
       
  1944   \sa QStateMachine::finished(), QStateMachine::start()
       
  1945 */
       
  1946 
       
  1947 /*!
       
  1948   \fn QStateMachine::stopped()
       
  1949 
       
  1950   This signal is emitted when the state machine has stopped.
       
  1951 
       
  1952   \sa QStateMachine::stop(), QStateMachine::finished()
       
  1953 */
       
  1954 
       
  1955 /*!
       
  1956   \reimp
       
  1957 */
       
  1958 bool QStateMachine::event(QEvent *e)
       
  1959 {
       
  1960     Q_D(QStateMachine);
       
  1961     if (e->type() == QEvent::Timer) {
       
  1962         QTimerEvent *te = static_cast<QTimerEvent*>(e);
       
  1963         int tid = te->timerId();
       
  1964         if (d->state != QStateMachinePrivate::Running) {
       
  1965             // This event has been cancelled already
       
  1966             Q_ASSERT(!d->delayedEvents.contains(tid));
       
  1967             return true;
       
  1968         }
       
  1969         QEvent *ee = d->delayedEvents.take(tid);
       
  1970         if (ee != 0) {
       
  1971             killTimer(tid);
       
  1972             d->externalEventQueue.append(ee);
       
  1973             d->processEvents(QStateMachinePrivate::DirectProcessing);
       
  1974             return true;
       
  1975         }
       
  1976     }
       
  1977     return QObject::event(e);
       
  1978 }
       
  1979 
       
  1980 #ifndef QT_NO_STATEMACHINE_EVENTFILTER
       
  1981 /*!
       
  1982   \reimp
       
  1983 */
       
  1984 bool QStateMachine::eventFilter(QObject *watched, QEvent *event)
       
  1985 {
       
  1986     Q_D(QStateMachine);
       
  1987     d->handleFilteredEvent(watched, event);
       
  1988     return false;
       
  1989 }
       
  1990 #endif
       
  1991 
       
  1992 /*!
       
  1993   \internal
       
  1994 
       
  1995   This function is called when the state machine is about to select
       
  1996   transitions based on the given \a event.
       
  1997 
       
  1998   The default implementation does nothing.
       
  1999 */
       
  2000 void QStateMachine::beginSelectTransitions(QEvent *event)
       
  2001 {
       
  2002     Q_UNUSED(event);
       
  2003 }
       
  2004 
       
  2005 /*!
       
  2006   \internal
       
  2007 
       
  2008   This function is called when the state machine has finished selecting
       
  2009   transitions based on the given \a event.
       
  2010 
       
  2011   The default implementation does nothing.
       
  2012 */
       
  2013 void QStateMachine::endSelectTransitions(QEvent *event)
       
  2014 {
       
  2015     Q_UNUSED(event);
       
  2016 }
       
  2017 
       
  2018 /*!
       
  2019   \internal
       
  2020 
       
  2021   This function is called when the state machine is about to do a microstep.
       
  2022 
       
  2023   The default implementation does nothing.
       
  2024 */
       
  2025 void QStateMachine::beginMicrostep(QEvent *event)
       
  2026 {
       
  2027     Q_UNUSED(event);
       
  2028 }
       
  2029 
       
  2030 /*!
       
  2031   \internal
       
  2032 
       
  2033   This function is called when the state machine has finished doing a
       
  2034   microstep.
       
  2035 
       
  2036   The default implementation does nothing.
       
  2037 */
       
  2038 void QStateMachine::endMicrostep(QEvent *event)
       
  2039 {
       
  2040     Q_UNUSED(event);
       
  2041 }
       
  2042 
       
  2043 /*!
       
  2044   \reimp
       
  2045 */
       
  2046 void QStateMachine::onEntry(QEvent *event)
       
  2047 {
       
  2048     start();
       
  2049     QState::onEntry(event);
       
  2050 }
       
  2051 
       
  2052 /*!
       
  2053   \reimp
       
  2054 */
       
  2055 void QStateMachine::onExit(QEvent *event)
       
  2056 {
       
  2057     stop();
       
  2058     QState::onExit(event);
       
  2059 }
       
  2060 
       
  2061 #ifndef QT_NO_ANIMATION
       
  2062 
       
  2063 /*!
       
  2064   Returns whether animations are enabled for this state machine.
       
  2065 */
       
  2066 bool QStateMachine::animationsEnabled() const
       
  2067 {
       
  2068     Q_D(const QStateMachine);
       
  2069     return d->animationsEnabled;
       
  2070 }
       
  2071 
       
  2072 /*!
       
  2073   Sets whether animations are \a enabled for this state machine.
       
  2074 */
       
  2075 void QStateMachine::setAnimationsEnabled(bool enabled)
       
  2076 {
       
  2077     Q_D(QStateMachine);
       
  2078     d->animationsEnabled = enabled;
       
  2079 }
       
  2080 
       
  2081 /*!
       
  2082     Adds a default \a animation to be considered for any transition.
       
  2083 */    
       
  2084 void QStateMachine::addDefaultAnimation(QAbstractAnimation *animation)
       
  2085 {
       
  2086     Q_D(QStateMachine);
       
  2087     d->defaultAnimations.append(animation);
       
  2088 }
       
  2089 
       
  2090 /*!
       
  2091     Returns the list of default animations that will be considered for any transition.
       
  2092 */
       
  2093 QList<QAbstractAnimation*> QStateMachine::defaultAnimations() const
       
  2094 {    
       
  2095     Q_D(const QStateMachine);
       
  2096     return d->defaultAnimations;
       
  2097 }
       
  2098 
       
  2099 /*!
       
  2100     Removes \a animation from the list of default animations. 
       
  2101 */
       
  2102 void QStateMachine::removeDefaultAnimation(QAbstractAnimation *animation)
       
  2103 {
       
  2104     Q_D(QStateMachine);
       
  2105     d->defaultAnimations.removeAll(animation);
       
  2106 }
       
  2107 
       
  2108 #endif // QT_NO_ANIMATION
       
  2109 
       
  2110 
       
  2111 static const uint qt_meta_data_QSignalEventGenerator[] = {
       
  2112 
       
  2113  // content:
       
  2114        2,       // revision
       
  2115        0,       // classname
       
  2116        0,    0, // classinfo
       
  2117        1,   12, // methods
       
  2118        0,    0, // properties
       
  2119        0,    0, // enums/sets
       
  2120        0,    0, // constructors
       
  2121 
       
  2122  // slots: signature, parameters, type, tag, flags
       
  2123       23,   22,   22,   22, 0x0a,
       
  2124 
       
  2125        0        // eod
       
  2126 };
       
  2127 
       
  2128 static const char qt_meta_stringdata_QSignalEventGenerator[] = {
       
  2129     "QSignalEventGenerator\0\0execute()\0"
       
  2130 };
       
  2131 
       
  2132 const QMetaObject QSignalEventGenerator::staticMetaObject = {
       
  2133     { &QObject::staticMetaObject, qt_meta_stringdata_QSignalEventGenerator,
       
  2134       qt_meta_data_QSignalEventGenerator, 0 }
       
  2135 };
       
  2136 
       
  2137 const QMetaObject *QSignalEventGenerator::metaObject() const
       
  2138 {
       
  2139     return &staticMetaObject;
       
  2140 }
       
  2141 
       
  2142 void *QSignalEventGenerator::qt_metacast(const char *_clname)
       
  2143 {
       
  2144     if (!_clname) return 0;
       
  2145     if (!strcmp(_clname, qt_meta_stringdata_QSignalEventGenerator))
       
  2146         return static_cast<void*>(const_cast< QSignalEventGenerator*>(this));
       
  2147     return QObject::qt_metacast(_clname);
       
  2148 }
       
  2149 
       
  2150 int QSignalEventGenerator::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
       
  2151 {
       
  2152     _id = QObject::qt_metacall(_c, _id, _a);
       
  2153     if (_id < 0)
       
  2154         return _id;
       
  2155     if (_c == QMetaObject::InvokeMetaMethod) {
       
  2156         switch (_id) {
       
  2157         case 0: {
       
  2158 // ### in Qt 4.6 we can use QObject::senderSignalIndex()
       
  2159             QObjectPrivate *d = static_cast<QObjectPrivate *>(d_ptr.data());
       
  2160             int signalIndex = -1;
       
  2161             QObject *sender = this->sender();
       
  2162             if (sender && d->currentSender)
       
  2163                 signalIndex = d->currentSender->signal;
       
  2164 
       
  2165             Q_ASSERT(signalIndex != -1);
       
  2166             QStateMachine *machine = qobject_cast<QStateMachine*>(parent());
       
  2167             QStateMachinePrivate::get(machine)->handleTransitionSignal(sender, signalIndex, _a);
       
  2168             break;
       
  2169         }
       
  2170         default: ;
       
  2171         }
       
  2172         _id -= 1;
       
  2173     }
       
  2174     return _id;
       
  2175 }
       
  2176 
       
  2177 QSignalEventGenerator::QSignalEventGenerator(QStateMachine *parent)
       
  2178     : QObject(parent)
       
  2179 {
       
  2180 }
       
  2181 
       
  2182 /*!
       
  2183   \class QStateMachine::SignalEvent
       
  2184 
       
  2185   \brief The SignalEvent class represents a Qt signal event.
       
  2186 
       
  2187   \since 4.6
       
  2188   \ingroup statemachine
       
  2189 
       
  2190   A signal event is generated by a QStateMachine in response to a Qt
       
  2191   signal. The QSignalTransition class provides a transition associated with a
       
  2192   signal event. QStateMachine::SignalEvent is part of \l{The State Machine Framework}.
       
  2193 
       
  2194   The sender() function returns the object that generated the signal. The
       
  2195   signalIndex() function returns the index of the signal. The arguments()
       
  2196   function returns the arguments of the signal.
       
  2197 
       
  2198   \sa QSignalTransition
       
  2199 */
       
  2200 
       
  2201 /*!
       
  2202   \internal
       
  2203 
       
  2204   Constructs a new SignalEvent object with the given \a sender, \a
       
  2205   signalIndex and \a arguments.
       
  2206 */
       
  2207 QStateMachine::SignalEvent::SignalEvent(QObject *sender, int signalIndex,
       
  2208                                         const QList<QVariant> &arguments)
       
  2209     : QEvent(QEvent::StateMachineSignal), m_sender(sender),
       
  2210       m_signalIndex(signalIndex), m_arguments(arguments)
       
  2211 {
       
  2212 }
       
  2213 
       
  2214 /*!
       
  2215   Destroys this SignalEvent.
       
  2216 */
       
  2217 QStateMachine::SignalEvent::~SignalEvent()
       
  2218 {
       
  2219 }
       
  2220 
       
  2221 /*!
       
  2222   \fn QStateMachine::SignalEvent::sender() const
       
  2223 
       
  2224   Returns the object that emitted the signal.
       
  2225 
       
  2226   \sa QObject::sender()
       
  2227 */
       
  2228 
       
  2229 /*!
       
  2230   \fn QStateMachine::SignalEvent::signalIndex() const
       
  2231 
       
  2232   Returns the index of the signal.
       
  2233 
       
  2234   \sa QMetaObject::indexOfSignal(), QMetaObject::method()
       
  2235 */
       
  2236 
       
  2237 /*!
       
  2238   \fn QStateMachine::SignalEvent::arguments() const
       
  2239 
       
  2240   Returns the arguments of the signal.
       
  2241 */
       
  2242 
       
  2243 
       
  2244 /*!
       
  2245   \class QStateMachine::WrappedEvent
       
  2246 
       
  2247   \brief The WrappedEvent class holds a clone of an event associated with a QObject.
       
  2248 
       
  2249   \since 4.6
       
  2250   \ingroup statemachine
       
  2251 
       
  2252   A wrapped event is generated by a QStateMachine in response to a Qt
       
  2253   event. The QEventTransition class provides a transition associated with a
       
  2254   such an event. QStateMachine::WrappedEvent is part of \l{The State Machine
       
  2255   Framework}.
       
  2256 
       
  2257   The object() function returns the object that generated the event. The
       
  2258   event() function returns a clone of the original event.
       
  2259 
       
  2260   \sa QEventTransition
       
  2261 */
       
  2262 
       
  2263 /*!
       
  2264   \internal
       
  2265 
       
  2266   Constructs a new WrappedEvent object with the given \a object
       
  2267   and \a event.
       
  2268 
       
  2269   The WrappedEvent object takes ownership of \a event.
       
  2270 */
       
  2271 QStateMachine::WrappedEvent::WrappedEvent(QObject *object, QEvent *event)
       
  2272     : QEvent(QEvent::StateMachineWrapped), m_object(object), m_event(event)
       
  2273 {
       
  2274 }
       
  2275 
       
  2276 /*!
       
  2277   Destroys this WrappedEvent.
       
  2278 */
       
  2279 QStateMachine::WrappedEvent::~WrappedEvent()
       
  2280 {
       
  2281     delete m_event;
       
  2282 }
       
  2283 
       
  2284 /*!
       
  2285   \fn QStateMachine::WrappedEvent::object() const
       
  2286 
       
  2287   Returns the object that the event is associated with.
       
  2288 */
       
  2289 
       
  2290 /*!
       
  2291   \fn QStateMachine::WrappedEvent::event() const
       
  2292 
       
  2293   Returns a clone of the original event.
       
  2294 */
       
  2295 
       
  2296 QT_END_NAMESPACE
       
  2297 
       
  2298 #include "moc_qstatemachine.cpp"
       
  2299 
       
  2300 #endif //QT_NO_STATEMACHINE