/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QSTATEMACHINE_P_H #define QSTATEMACHINE_P_H // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists purely as an // implementation detail. This header file may change from version to // version without notice, or even be removed. // // We mean it. // #include "private/qstate_p.h" #include #include #include #include #include #include #include #include #include QT_BEGIN_NAMESPACE class QEvent; #ifndef QT_NO_STATEMACHINE_EVENTFILTER class QEventTransition; #endif class QSignalEventGenerator; class QSignalTransition; class QAbstractState; class QAbstractTransition; class QFinalState; class QHistoryState; class QState; #ifndef QT_NO_ANIMATION class QAbstractAnimation; #endif struct CalculationCache; class QStateMachine; class Q_CORE_EXPORT QStateMachinePrivate : public QStatePrivate { Q_DECLARE_PUBLIC(QStateMachine) public: enum State { NotRunning, Starting, Running }; enum EventProcessingMode { DirectProcessing, QueuedProcessing }; enum StopProcessingReason { EventQueueEmpty, Finished, Stopped }; QStateMachinePrivate(); ~QStateMachinePrivate(); static QStateMachinePrivate *get(QStateMachine *q) { return q ? q->d_func() : 0; } QState *findLCA(const QList &states, bool onlyCompound = false) const; QState *findLCCA(const QList &states) const; static bool transitionStateEntryLessThan(QAbstractTransition *t1, QAbstractTransition *t2); static bool stateEntryLessThan(QAbstractState *s1, QAbstractState *s2); static bool stateExitLessThan(QAbstractState *s1, QAbstractState *s2); QAbstractState *findErrorState(QAbstractState *context); void setError(QStateMachine::Error error, QAbstractState *currentContext); // private slots void _q_start(); void _q_process(); #ifndef QT_NO_ANIMATION void _q_animationFinished(); #endif void _q_startDelayedEventTimer(int id, int delay); void _q_killDelayedEventTimer(int id, int timerId); QState *rootState() const; void clearHistory(); QAbstractTransition *createInitialTransition() const; void removeConflictingTransitions(QList &enabledTransitions, CalculationCache *cache); void microstep(QEvent *event, const QList &transitionList, CalculationCache *cache); QList selectTransitions(QEvent *event, CalculationCache *cache); virtual void noMicrostep(); virtual void processedPendingEvents(bool didChange); virtual void beginMacrostep(); virtual void endMacrostep(bool didChange); virtual void exitInterpreter(); virtual void exitStates(QEvent *event, const QList &statesToExit_sorted, const QHash > &assignmentsForEnteredStates); QList computeExitSet(const QList &enabledTransitions, CalculationCache *cache); QSet computeExitSet_Unordered(const QList &enabledTransitions, CalculationCache *cache); QSet computeExitSet_Unordered(QAbstractTransition *t, CalculationCache *cache); void executeTransitionContent(QEvent *event, const QList &transitionList); virtual void enterStates(QEvent *event, const QList &exitedStates_sorted, const QList &statesToEnter_sorted, const QSet &statesForDefaultEntry, QHash > &propertyAssignmentsForState #ifndef QT_NO_ANIMATION , const QList &selectedAnimations #endif ); QList computeEntrySet(const QList &enabledTransitions, QSet &statesForDefaultEntry, CalculationCache *cache); QAbstractState *getTransitionDomain(QAbstractTransition *t, const QList &effectiveTargetStates, CalculationCache *cache) const; void addDescendantStatesToEnter(QAbstractState *state, QSet &statesToEnter, QSet &statesForDefaultEntry); void addAncestorStatesToEnter(QAbstractState *s, QAbstractState *ancestor, QSet &statesToEnter, QSet &statesForDefaultEntry); static QState *toStandardState(QAbstractState *state); static const QState *toStandardState(const QAbstractState *state); static QFinalState *toFinalState(QAbstractState *state); static QHistoryState *toHistoryState(QAbstractState *state); bool isInFinalState(QAbstractState *s) const; static bool isFinal(const QAbstractState *s); static bool isParallel(const QAbstractState *s); bool isCompound(const QAbstractState *s) const; bool isAtomic(const QAbstractState *s) const; void goToState(QAbstractState *targetState); void registerTransitions(QAbstractState *state); void maybeRegisterTransition(QAbstractTransition *transition); void registerTransition(QAbstractTransition *transition); void maybeRegisterSignalTransition(QSignalTransition *transition); void registerSignalTransition(QSignalTransition *transition); void unregisterSignalTransition(QSignalTransition *transition); void registerMultiThreadedSignalTransitions(); #ifndef QT_NO_STATEMACHINE_EVENTFILTER void maybeRegisterEventTransition(QEventTransition *transition); void registerEventTransition(QEventTransition *transition); void unregisterEventTransition(QEventTransition *transition); void handleFilteredEvent(QObject *watched, QEvent *event); #endif void unregisterTransition(QAbstractTransition *transition); void unregisterAllTransitions(); void handleTransitionSignal(QObject *sender, int signalIndex, void **args); void postInternalEvent(QEvent *e); void postExternalEvent(QEvent *e); QEvent *dequeueInternalEvent(); QEvent *dequeueExternalEvent(); bool isInternalEventQueueEmpty(); bool isExternalEventQueueEmpty(); void processEvents(EventProcessingMode processingMode); void cancelAllDelayedEvents(); virtual void emitStateFinished(QState *forState, QFinalState *guiltyState); virtual void startupHook(); #ifndef QT_NO_PROPERTIES class RestorableId { QPointer guard; QObject *obj; QByteArray prop; // two overloads because friends can't have default arguments friend uint qHash(const RestorableId &key, uint seed) Q_DECL_NOEXCEPT_EXPR(noexcept(qHash(std::declval()))) { return qHash(qMakePair(key.obj, key.prop), seed); } friend uint qHash(const RestorableId &key) Q_DECL_NOEXCEPT_EXPR(noexcept(qHash(key, 0U))) { return qHash(key, 0U); } friend bool operator==(const RestorableId &lhs, const RestorableId &rhs) Q_DECL_NOTHROW { return lhs.obj == rhs.obj && lhs.prop == rhs.prop; } friend bool operator!=(const RestorableId &lhs, const RestorableId &rhs) Q_DECL_NOTHROW { return !operator==(lhs, rhs); } public: explicit RestorableId(QObject *o, QByteArray p) Q_DECL_NOTHROW : guard(o), obj(o), prop(qMove(p)) {} QObject *object() const Q_DECL_NOTHROW { return guard; } QByteArray propertyName() const Q_DECL_NOTHROW { return prop; } }; QHash > registeredRestorablesForState; bool hasRestorable(QAbstractState *state, QObject *object, const QByteArray &propertyName) const; QVariant savedValueForRestorable(const QList &exitedStates_sorted, QObject *object, const QByteArray &propertyName) const; void registerRestorable(QAbstractState *state, QObject *object, const QByteArray &propertyName, const QVariant &value); void unregisterRestorables(const QList &states, QObject *object, const QByteArray &propertyName); QVector restorablesToPropertyList(const QHash &restorables) const; QHash computePendingRestorables(const QList &statesToExit_sorted) const; QHash > computePropertyAssignments( const QList &statesToEnter_sorted, QHash &pendingRestorables) const; #endif State state; bool processing; bool processingScheduled; bool stop; StopProcessingReason stopProcessingReason; QSet configuration; QList internalEventQueue; QList externalEventQueue; QMutex internalEventMutex; QMutex externalEventMutex; QStateMachine::Error error; QState::RestorePolicy globalRestorePolicy; QString errorString; QSet pendingErrorStates; QSet pendingErrorStatesForDefaultEntry; #ifndef QT_NO_ANIMATION bool animated; struct InitializeAnimationResult { QList handledAnimations; QList localResetEndValues; void swap(InitializeAnimationResult &other) Q_DECL_NOTHROW { qSwap(handledAnimations, other.handledAnimations); qSwap(localResetEndValues, other.localResetEndValues); } }; InitializeAnimationResult initializeAnimation(QAbstractAnimation *abstractAnimation, const QPropertyAssignment &prop); QHash > animationsForState; QHash propertyForAnimation; QHash stateForAnimation; QSet resetAnimationEndValues; QList defaultAnimations; QMultiHash defaultAnimationsForSource; QMultiHash defaultAnimationsForTarget; QList selectAnimations(const QList &transitionList) const; void terminateActiveAnimations(QAbstractState *state, const QHash > &assignmentsForEnteredStates); void initializeAnimations(QAbstractState *state, const QList &selectedAnimations, const QList &exitedStates_sorted, QHash > &assignmentsForEnteredStates); #endif // QT_NO_ANIMATION QSignalEventGenerator *signalEventGenerator; QHash > connections; QMutex connectionsMutex; #ifndef QT_NO_STATEMACHINE_EVENTFILTER QHash > qobjectEvents; #endif QFreeList delayedEventIdFreeList; struct DelayedEvent { QEvent *event; int timerId; DelayedEvent(QEvent *e, int tid) : event(e), timerId(tid) {} DelayedEvent() : event(0), timerId(0) {} }; QHash delayedEvents; QHash timerIdToDelayedEventId; QMutex delayedEventsMutex; typedef QEvent* (*f_cloneEvent)(QEvent*); struct Handler { f_cloneEvent cloneEvent; }; static const Handler *handler; }; Q_DECLARE_SHARED(QStateMachinePrivate::InitializeAnimationResult) Q_CORE_EXPORT const QStateMachinePrivate::Handler *qcoreStateMachineHandler(); QT_END_NAMESPACE #endif