From a735038376e1c229c293c36bd67800851323baf1 Mon Sep 17 00:00:00 2001 From: Karsten Heimrich Date: Tue, 18 Aug 2020 14:26:50 +0200 Subject: Move QStateMachine from QtCore to QtScxml Task-number: QTBUG-80316 Change-Id: I2ee74110fd55e94d86321d3b3dc5bb8297424ed4 Reviewed-by: Maurice Kalinowski --- src/corelib/statemachine/qabstractstate.cpp | 239 -- src/corelib/statemachine/qabstractstate.h | 88 - src/corelib/statemachine/qabstractstate_p.h | 99 - src/corelib/statemachine/qabstracttransition.cpp | 435 --- src/corelib/statemachine/qabstracttransition.h | 117 - src/corelib/statemachine/qabstracttransition_p.h | 94 - src/corelib/statemachine/qeventtransition.cpp | 256 -- src/corelib/statemachine/qeventtransition.h | 85 - src/corelib/statemachine/qeventtransition_p.h | 81 - src/corelib/statemachine/qfinalstate.cpp | 141 - src/corelib/statemachine/qfinalstate.h | 73 - src/corelib/statemachine/qfinalstate_p.h | 72 - src/corelib/statemachine/qhistorystate.cpp | 334 -- src/corelib/statemachine/qhistorystate.h | 95 - src/corelib/statemachine/qhistorystate_p.h | 80 - src/corelib/statemachine/qsignaleventgenerator_p.h | 78 - src/corelib/statemachine/qsignaltransition.cpp | 287 -- src/corelib/statemachine/qsignaltransition.h | 99 - src/corelib/statemachine/qsignaltransition_p.h | 83 - src/corelib/statemachine/qstate.cpp | 603 ---- src/corelib/statemachine/qstate.h | 134 - src/corelib/statemachine/qstate_p.h | 127 - src/corelib/statemachine/qstatemachine.cpp | 3208 -------------------- src/corelib/statemachine/qstatemachine.h | 199 -- src/corelib/statemachine/qstatemachine_p.h | 333 -- src/corelib/statemachine/statemachine.pri | 33 - 26 files changed, 7473 deletions(-) delete mode 100644 src/corelib/statemachine/qabstractstate.cpp delete mode 100644 src/corelib/statemachine/qabstractstate.h delete mode 100644 src/corelib/statemachine/qabstractstate_p.h delete mode 100644 src/corelib/statemachine/qabstracttransition.cpp delete mode 100644 src/corelib/statemachine/qabstracttransition.h delete mode 100644 src/corelib/statemachine/qabstracttransition_p.h delete mode 100644 src/corelib/statemachine/qeventtransition.cpp delete mode 100644 src/corelib/statemachine/qeventtransition.h delete mode 100644 src/corelib/statemachine/qeventtransition_p.h delete mode 100644 src/corelib/statemachine/qfinalstate.cpp delete mode 100644 src/corelib/statemachine/qfinalstate.h delete mode 100644 src/corelib/statemachine/qfinalstate_p.h delete mode 100644 src/corelib/statemachine/qhistorystate.cpp delete mode 100644 src/corelib/statemachine/qhistorystate.h delete mode 100644 src/corelib/statemachine/qhistorystate_p.h delete mode 100644 src/corelib/statemachine/qsignaleventgenerator_p.h delete mode 100644 src/corelib/statemachine/qsignaltransition.cpp delete mode 100644 src/corelib/statemachine/qsignaltransition.h delete mode 100644 src/corelib/statemachine/qsignaltransition_p.h delete mode 100644 src/corelib/statemachine/qstate.cpp delete mode 100644 src/corelib/statemachine/qstate.h delete mode 100644 src/corelib/statemachine/qstate_p.h delete mode 100644 src/corelib/statemachine/qstatemachine.cpp delete mode 100644 src/corelib/statemachine/qstatemachine.h delete mode 100644 src/corelib/statemachine/qstatemachine_p.h delete mode 100644 src/corelib/statemachine/statemachine.pri (limited to 'src/corelib/statemachine') diff --git a/src/corelib/statemachine/qabstractstate.cpp b/src/corelib/statemachine/qabstractstate.cpp deleted file mode 100644 index 10f54c3e18..0000000000 --- a/src/corelib/statemachine/qabstractstate.cpp +++ /dev/null @@ -1,239 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#include "qabstractstate.h" -#include "qabstractstate_p.h" -#include "qstate.h" -#include "qstate_p.h" -#include "qstatemachine.h" -#include "qstatemachine_p.h" - -QT_BEGIN_NAMESPACE - -/*! - \class QAbstractState - \inmodule QtCore - - \brief The QAbstractState class is the base class of states of a QStateMachine. - - \since 4.6 - \ingroup statemachine - - The QAbstractState class is the abstract base class of states that are part - of a QStateMachine. It defines the interface that all state objects have in - common. QAbstractState is part of \l{The State Machine Framework}. - - The entered() signal is emitted when the state has been entered. The - exited() signal is emitted when the state has been exited. - - The parentState() function returns the state's parent state. The machine() - function returns the state machine that the state is part of. - - \section1 Subclassing - - The onEntry() function is called when the state is entered; reimplement this - function to perform custom processing when the state is entered. - - The onExit() function is called when the state is exited; reimplement this - function to perform custom processing when the state is exited. -*/ - -/*! - \property QAbstractState::active - \since 5.4 - - \brief the active property of this state. A state is active between - entered() and exited() signals. -*/ - - -QAbstractStatePrivate::QAbstractStatePrivate(StateType type) - : stateType(type), isMachine(false), active(false), parentState(nullptr) -{ -} - -QStateMachine *QAbstractStatePrivate::machine() const -{ - QObject *par = parent; - while (par != nullptr) { - if (QStateMachine *mach = qobject_cast(par)) - return mach; - par = par->parent(); - } - return nullptr; -} - -void QAbstractStatePrivate::callOnEntry(QEvent *e) -{ - Q_Q(QAbstractState); - q->onEntry(e); -} - -void QAbstractStatePrivate::callOnExit(QEvent *e) -{ - Q_Q(QAbstractState); - q->onExit(e); -} - -void QAbstractStatePrivate::emitEntered() -{ - Q_Q(QAbstractState); - emit q->entered(QAbstractState::QPrivateSignal()); - if (!active) { - active = true; - emit q->activeChanged(true); - } -} - -void QAbstractStatePrivate::emitExited() -{ - Q_Q(QAbstractState); - if (active) { - active = false; - emit q->activeChanged(false); - } - emit q->exited(QAbstractState::QPrivateSignal()); -} - -/*! - Constructs a new state with the given \a parent state. -*/ -QAbstractState::QAbstractState(QState *parent) - : QObject(*new QAbstractStatePrivate(QAbstractStatePrivate::AbstractState), parent) -{ -} - -/*! - \internal -*/ -QAbstractState::QAbstractState(QAbstractStatePrivate &dd, QState *parent) - : QObject(dd, parent) -{ -} - -/*! - Destroys this state. -*/ -QAbstractState::~QAbstractState() -{ -} - -/*! - Returns this state's parent state, or \nullptr if the state has no - parent state. -*/ -QState *QAbstractState::parentState() const -{ - Q_D(const QAbstractState); - if (d->parentState != parent()) - d->parentState = qobject_cast(parent()); - return d->parentState; -} - -/*! - Returns the state machine that this state is part of, or \nullptr if - the state is not part of a state machine. -*/ -QStateMachine *QAbstractState::machine() const -{ - Q_D(const QAbstractState); - return d->machine(); -} - -/*! - Returns whether this state is active. - - \sa activeChanged(bool), entered(), exited() -*/ -bool QAbstractState::active() const -{ - Q_D(const QAbstractState); - return d->active; -} - -/*! - \fn QAbstractState::onExit(QEvent *event) - - This function is called when the state is exited. The given \a event is what - caused the state to be exited. Reimplement this function to perform custom - processing when the state is exited. -*/ - -/*! - \fn QAbstractState::onEntry(QEvent *event) - - This function is called when the state is entered. The given \a event is - what caused the state to be entered. Reimplement this function to perform - custom processing when the state is entered. -*/ - -/*! - \fn QAbstractState::entered() - - This signal is emitted when the state has been entered (after onEntry() has - been called). -*/ - -/*! - \fn QAbstractState::exited() - - This signal is emitted when the state has been exited (after onExit() has - been called). -*/ - -/*! - \fn QAbstractState::activeChanged(bool active) - \since 5.4 - - This signal is emitted when the active property is changed with \a active as argument. - - \sa QAbstractState::active, entered(), exited() -*/ - -/*! - \reimp -*/ -bool QAbstractState::event(QEvent *e) -{ - return QObject::event(e); -} - -QT_END_NAMESPACE - -#include "moc_qabstractstate.cpp" diff --git a/src/corelib/statemachine/qabstractstate.h b/src/corelib/statemachine/qabstractstate.h deleted file mode 100644 index ffc2eaae13..0000000000 --- a/src/corelib/statemachine/qabstractstate.h +++ /dev/null @@ -1,88 +0,0 @@ -/**************************************************************************** -** -** 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 QABSTRACTSTATE_H -#define QABSTRACTSTATE_H - -#include - -QT_REQUIRE_CONFIG(statemachine); - -QT_BEGIN_NAMESPACE - -class QState; -class QStateMachine; - -class QAbstractStatePrivate; -class Q_CORE_EXPORT QAbstractState : public QObject -{ - Q_OBJECT - Q_PROPERTY(bool active READ active NOTIFY activeChanged) -public: - ~QAbstractState(); - - QState *parentState() const; - QStateMachine *machine() const; - - bool active() const; - -Q_SIGNALS: - void entered(QPrivateSignal); - void exited(QPrivateSignal); - void activeChanged(bool active); - -protected: - QAbstractState(QState *parent = nullptr); - - virtual void onEntry(QEvent *event) = 0; - virtual void onExit(QEvent *event) = 0; - - bool event(QEvent *e) override; - -protected: - QAbstractState(QAbstractStatePrivate &dd, QState *parent); - -private: - Q_DISABLE_COPY(QAbstractState) - Q_DECLARE_PRIVATE(QAbstractState) -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/corelib/statemachine/qabstractstate_p.h b/src/corelib/statemachine/qabstractstate_p.h deleted file mode 100644 index 11befc187e..0000000000 --- a/src/corelib/statemachine/qabstractstate_p.h +++ /dev/null @@ -1,99 +0,0 @@ -/**************************************************************************** -** -** 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 QABSTRACTSTATE_P_H -#define QABSTRACTSTATE_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 -#include - -QT_REQUIRE_CONFIG(statemachine); - -QT_BEGIN_NAMESPACE - -class QStateMachine; - -class QState; -class QAbstractStatePrivate : public QObjectPrivate -{ - Q_DECLARE_PUBLIC(QAbstractState) - -public: - enum StateType { - AbstractState, - StandardState, - FinalState, - HistoryState - }; - - QAbstractStatePrivate(StateType type); - - static QAbstractStatePrivate *get(QAbstractState *q) - { return q->d_func(); } - static const QAbstractStatePrivate *get(const QAbstractState *q) - { return q->d_func(); } - - QStateMachine *machine() const; - - void callOnEntry(QEvent *e); - void callOnExit(QEvent *e); - - void emitEntered(); - void emitExited(); - - uint stateType:30; - uint isMachine:1; - bool active:1; - mutable QState *parentState; -}; - -QT_END_NAMESPACE - -#endif // QABSTRACTSTATE_P_H diff --git a/src/corelib/statemachine/qabstracttransition.cpp b/src/corelib/statemachine/qabstracttransition.cpp deleted file mode 100644 index b1cbc1c516..0000000000 --- a/src/corelib/statemachine/qabstracttransition.cpp +++ /dev/null @@ -1,435 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#include "qabstracttransition.h" -#include "qabstracttransition_p.h" -#include "qabstractstate.h" -#include "qhistorystate.h" -#include "qstate.h" -#include "qstatemachine.h" - -QT_BEGIN_NAMESPACE - -/*! - \class QAbstractTransition - \inmodule QtCore - - \brief The QAbstractTransition class is the base class of transitions between QAbstractState objects. - - \since 4.6 - \ingroup statemachine - - The QAbstractTransition class is the abstract base class of transitions - between states (QAbstractState objects) of a - QStateMachine. QAbstractTransition is part of \l{The State Machine - Framework}. - - The sourceState() function returns the source of the transition. The - targetStates() function returns the targets of the transition. The machine() - function returns the state machine that the transition is part of. - - The triggered() signal is emitted when the transition has been triggered. - - Transitions can cause animations to be played. Use the addAnimation() - function to add an animation to the transition. - - \section1 Subclassing - - The eventTest() function is called by the state machine to determine whether - an event should trigger the transition. In your reimplementation you - typically check the event type and cast the event object to the proper type, - and check that one or more properties of the event meet your criteria. - - The onTransition() function is called when the transition is triggered; - reimplement this function to perform custom processing for the transition. -*/ - -/*! - \property QAbstractTransition::sourceState - - \brief the source state (parent) of this transition -*/ - -/*! - \property QAbstractTransition::targetState - - \brief the target state of this transition - - If a transition has no target state, the transition may still be - triggered, but this will not cause the state machine's configuration to - change (i.e. the current state will not be exited and re-entered). -*/ - -/*! - \property QAbstractTransition::targetStates - - \brief the target states of this transition - - If multiple states are specified, all must be descendants of the same - parallel group state. -*/ - -/*! - \property QAbstractTransition::transitionType - - \brief indicates whether this transition is an internal transition, or an external transition. - - Internal and external transitions behave the same, except for the case of a transition whose - source state is a compound state and whose target(s) is a descendant of the source. In such a - case, an internal transition will not exit and re-enter its source state, while an external one - will. - - By default, the type is an external transition. -*/ - -/*! - \enum QAbstractTransition::TransitionType - - This enum specifies the kind of transition. By default, the type is an external transition. - - \value ExternalTransition Any state that is the source state of a transition (which is not a - target-less transition) is left, and re-entered when necessary. - \value InternalTransition If the target state of a transition is a sub-state of a compound state, - and that compound state is the source state, an internal transition will - not leave the source state. - - \sa QAbstractTransition::transitionType -*/ - -QAbstractTransitionPrivate::QAbstractTransitionPrivate() - : transitionType(QAbstractTransition::ExternalTransition) -{ -} - -QStateMachine *QAbstractTransitionPrivate::machine() const -{ - if (QState *source = sourceState()) - return source->machine(); - Q_Q(const QAbstractTransition); - if (QHistoryState *parent = qobject_cast(q->parent())) - return parent->machine(); - return nullptr; -} - -bool QAbstractTransitionPrivate::callEventTest(QEvent *e) -{ - Q_Q(QAbstractTransition); - return q->eventTest(e); -} - -void QAbstractTransitionPrivate::callOnTransition(QEvent *e) -{ - Q_Q(QAbstractTransition); - q->onTransition(e); -} - -QState *QAbstractTransitionPrivate::sourceState() const -{ - return qobject_cast(parent); -} - -void QAbstractTransitionPrivate::emitTriggered() -{ - Q_Q(QAbstractTransition); - emit q->triggered(QAbstractTransition::QPrivateSignal()); -} - -/*! - Constructs a new QAbstractTransition object with the given \a sourceState. -*/ -QAbstractTransition::QAbstractTransition(QState *sourceState) - : QObject(*new QAbstractTransitionPrivate, sourceState) -{ -} - -/*! - \internal -*/ -QAbstractTransition::QAbstractTransition(QAbstractTransitionPrivate &dd, - QState *parent) - : QObject(dd, parent) -{ -} - -/*! - Destroys this transition. -*/ -QAbstractTransition::~QAbstractTransition() -{ -} - -/*! - Returns the source state of this transition, or \nullptr if this - transition has no source state. -*/ -QState *QAbstractTransition::sourceState() const -{ - Q_D(const QAbstractTransition); - return d->sourceState(); -} - -/*! - Returns the target state of this transition, or \nullptr if the - transition has no target. -*/ -QAbstractState *QAbstractTransition::targetState() const -{ - Q_D(const QAbstractTransition); - if (d->targetStates.isEmpty()) - return nullptr; - return d->targetStates.first().data(); -} - -/*! - Sets the \a target state of this transition. -*/ -void QAbstractTransition::setTargetState(QAbstractState* target) -{ - Q_D(QAbstractTransition); - if ((d->targetStates.size() == 1 && target == d->targetStates.at(0).data()) || - (d->targetStates.isEmpty() && target == nullptr)) { - return; - } - if (!target) - d->targetStates.clear(); - else - setTargetStates(QList() << target); - emit targetStateChanged(QPrivateSignal()); -} - -/*! - Returns the target states of this transition, or an empty list if this - transition has no target states. -*/ -QList QAbstractTransition::targetStates() const -{ - Q_D(const QAbstractTransition); - QList result; - for (int i = 0; i < d->targetStates.size(); ++i) { - QAbstractState *target = d->targetStates.at(i).data(); - if (target) - result.append(target); - } - return result; -} - -/*! - Sets the target states of this transition to be the given \a targets. -*/ -void QAbstractTransition::setTargetStates(const QList &targets) -{ - Q_D(QAbstractTransition); - - // Verify if any of the new target states is a null-pointer: - for (int i = 0; i < targets.size(); ++i) { - if (targets.at(i) == nullptr) { - qWarning("QAbstractTransition::setTargetStates: target state(s) cannot be null"); - return; - } - } - - // First clean out any target states that got destroyed, but for which we still have a QPointer - // around. - for (int i = 0; i < d->targetStates.size(); ) { - if (d->targetStates.at(i).isNull()) { - d->targetStates.remove(i); - } else { - ++i; - } - } - - // Easy check: if both lists are empty, we're done. - if (targets.isEmpty() && d->targetStates.isEmpty()) - return; - - bool sameList = true; - - if (targets.size() != d->targetStates.size()) { - // If the sizes of the lists are different, we don't need to be smart: they're different. So - // we can just set the new list as the targetStates. - sameList = false; - } else { - QList> copy(d->targetStates); - for (int i = 0; i < targets.size(); ++i) { - sameList &= copy.removeOne(targets.at(i)); - if (!sameList) - break; // ok, we now know the lists are not the same, so stop the loop. - } - - sameList &= copy.isEmpty(); - } - - if (sameList) - return; - - d->targetStates.resize(targets.size()); - for (int i = 0; i < targets.size(); ++i) { - d->targetStates[i] = targets.at(i); - } - - emit targetStatesChanged(QPrivateSignal()); -} - -/*! - Returns the type of the transition. -*/ -QAbstractTransition::TransitionType QAbstractTransition::transitionType() const -{ - Q_D(const QAbstractTransition); - return d->transitionType; -} - -/*! - Sets the type of the transition to \a type. -*/ -void QAbstractTransition::setTransitionType(TransitionType type) -{ - Q_D(QAbstractTransition); - d->transitionType = type; -} - -/*! - Returns the state machine that this transition is part of, or - \nullptr if the transition is not part of a state machine. -*/ -QStateMachine *QAbstractTransition::machine() const -{ - Q_D(const QAbstractTransition); - return d->machine(); -} - -#if QT_CONFIG(animation) - -/*! - Adds the given \a animation to this transition. - The transition does not take ownership of the animation. - - \sa removeAnimation(), animations() -*/ -void QAbstractTransition::addAnimation(QAbstractAnimation *animation) -{ - Q_D(QAbstractTransition); - if (!animation) { - qWarning("QAbstractTransition::addAnimation: cannot add null animation"); - return; - } - d->animations.append(animation); -} - -/*! - Removes the given \a animation from this transition. - - \sa addAnimation() -*/ -void QAbstractTransition::removeAnimation(QAbstractAnimation *animation) -{ - Q_D(QAbstractTransition); - if (!animation) { - qWarning("QAbstractTransition::removeAnimation: cannot remove null animation"); - return; - } - d->animations.removeOne(animation); -} - -/*! - Returns the list of animations associated with this transition, or an empty - list if it has no animations. - - \sa addAnimation() -*/ -QList QAbstractTransition::animations() const -{ - Q_D(const QAbstractTransition); - return d->animations; -} - -#endif - -/*! - \fn QAbstractTransition::eventTest(QEvent *event) - - This function is called to determine whether the given \a event should cause - this transition to trigger. Reimplement this function and return true if the - event should trigger the transition, otherwise return false. -*/ - -/*! - \fn QAbstractTransition::onTransition(QEvent *event) - - This function is called when the transition is triggered. The given \a event - is what caused the transition to trigger. Reimplement this function to - perform custom processing when the transition is triggered. -*/ - -/*! - \fn QAbstractTransition::triggered() - - This signal is emitted when the transition has been triggered (after - onTransition() has been called). -*/ - -/*! - \fn QAbstractTransition::targetStateChanged() - \since 5.4 - - This signal is emitted when the targetState property is changed. - - \sa QAbstractTransition::targetState -*/ - -/*! - \fn QAbstractTransition::targetStatesChanged() - \since 5.4 - - This signal is emitted when the targetStates property is changed. - - \sa QAbstractTransition::targetStates -*/ - -/*! - \reimp -*/ -bool QAbstractTransition::event(QEvent *e) -{ - return QObject::event(e); -} - -QT_END_NAMESPACE - -#include "moc_qabstracttransition.cpp" diff --git a/src/corelib/statemachine/qabstracttransition.h b/src/corelib/statemachine/qabstracttransition.h deleted file mode 100644 index 357e829b6a..0000000000 --- a/src/corelib/statemachine/qabstracttransition.h +++ /dev/null @@ -1,117 +0,0 @@ -/**************************************************************************** -** -** 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 QABSTRACTTRANSITION_H -#define QABSTRACTTRANSITION_H - -#include - -#include - -QT_REQUIRE_CONFIG(statemachine); - -QT_BEGIN_NAMESPACE - -class QEvent; -class QAbstractState; -class QState; -class QStateMachine; - -#if QT_CONFIG(animation) -class QAbstractAnimation; -#endif - -class QAbstractTransitionPrivate; -class Q_CORE_EXPORT QAbstractTransition : public QObject -{ - Q_OBJECT - Q_PROPERTY(QState* sourceState READ sourceState) - Q_PROPERTY(QAbstractState* targetState READ targetState WRITE setTargetState NOTIFY targetStateChanged) - Q_PROPERTY(QList targetStates READ targetStates WRITE setTargetStates NOTIFY targetStatesChanged) - Q_PROPERTY(TransitionType transitionType READ transitionType WRITE setTransitionType REVISION(1, 1)) -public: - enum TransitionType { - ExternalTransition, - InternalTransition - }; - Q_ENUM(TransitionType) - - QAbstractTransition(QState *sourceState = nullptr); - virtual ~QAbstractTransition(); - - QState *sourceState() const; - QAbstractState *targetState() const; - void setTargetState(QAbstractState* target); - QList targetStates() const; - void setTargetStates(const QList &targets); - - TransitionType transitionType() const; - void setTransitionType(TransitionType type); - - QStateMachine *machine() const; - -#if QT_CONFIG(animation) - void addAnimation(QAbstractAnimation *animation); - void removeAnimation(QAbstractAnimation *animation); - QList animations() const; -#endif - -Q_SIGNALS: - void triggered(QPrivateSignal); - void targetStateChanged(QPrivateSignal); - void targetStatesChanged(QPrivateSignal); - -protected: - virtual bool eventTest(QEvent *event) = 0; - - virtual void onTransition(QEvent *event) = 0; - - bool event(QEvent *e) override; - -protected: - QAbstractTransition(QAbstractTransitionPrivate &dd, QState *parent); - -private: - Q_DISABLE_COPY(QAbstractTransition) - Q_DECLARE_PRIVATE(QAbstractTransition) -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/corelib/statemachine/qabstracttransition_p.h b/src/corelib/statemachine/qabstracttransition_p.h deleted file mode 100644 index 435488848f..0000000000 --- a/src/corelib/statemachine/qabstracttransition_p.h +++ /dev/null @@ -1,94 +0,0 @@ -/**************************************************************************** -** -** 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 QABSTRACTTRANSITION_P_H -#define QABSTRACTTRANSITION_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 - -#include -#include - -QT_REQUIRE_CONFIG(statemachine); - -QT_BEGIN_NAMESPACE - -class QAbstractState; -class QState; -class QStateMachine; - -class QAbstractTransition; -class Q_CORE_EXPORT QAbstractTransitionPrivate - : public QObjectPrivate -{ - Q_DECLARE_PUBLIC(QAbstractTransition) -public: - QAbstractTransitionPrivate(); - - static QAbstractTransitionPrivate *get(QAbstractTransition *q) - { return q->d_func(); } - - bool callEventTest(QEvent *e); - virtual void callOnTransition(QEvent *e); - QState *sourceState() const; - QStateMachine *machine() const; - void emitTriggered(); - - QList> targetStates; - QAbstractTransition::TransitionType transitionType; - -#if QT_CONFIG(animation) - QList animations; -#endif -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/corelib/statemachine/qeventtransition.cpp b/src/corelib/statemachine/qeventtransition.cpp deleted file mode 100644 index 5dcbcfff47..0000000000 --- a/src/corelib/statemachine/qeventtransition.cpp +++ /dev/null @@ -1,256 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#include "qeventtransition.h" -#include "qeventtransition_p.h" -#include "qstate.h" -#include "qstate_p.h" -#include "qstatemachine.h" -#include "qstatemachine_p.h" -#include - -QT_BEGIN_NAMESPACE - -/*! - \class QEventTransition - \inmodule QtCore - - \brief The QEventTransition class provides a QObject-specific transition for Qt events. - - \since 4.6 - \ingroup statemachine - - A QEventTransition object binds an event to a particular QObject. - QEventTransition is part of \l{The State Machine Framework}. - - Example: - - \code - QPushButton *button = ...; - QState *s1 = ...; - QState *s2 = ...; - // If in s1 and the button receives an Enter event, transition to s2 - QEventTransition *enterTransition = new QEventTransition(button, QEvent::Enter); - enterTransition->setTargetState(s2); - s1->addTransition(enterTransition); - // If in s2 and the button receives an Exit event, transition back to s1 - QEventTransition *leaveTransition = new QEventTransition(button, QEvent::Leave); - leaveTransition->setTargetState(s1); - s2->addTransition(leaveTransition); - \endcode - - \section1 Subclassing - - When reimplementing the eventTest() function, you should first call the base - implementation to verify that the event is a QStateMachine::WrappedEvent for - the proper object and event type. You may then cast the event to a - QStateMachine::WrappedEvent and get the original event by calling - QStateMachine::WrappedEvent::event(), and perform additional checks on that - object. - - \sa QState::addTransition() -*/ - -/*! - \property QEventTransition::eventSource - - \brief the event source that this event transition is associated with -*/ - -/*! - \property QEventTransition::eventType - - \brief the type of event that this event transition is associated with -*/ -QEventTransitionPrivate::QEventTransitionPrivate() -{ - object = nullptr; - eventType = QEvent::None; - registered = false; -} - -QEventTransitionPrivate::~QEventTransitionPrivate() -{ -} - -void QEventTransitionPrivate::unregister() -{ - Q_Q(QEventTransition); - if (!registered || !machine()) - return; - QStateMachinePrivate::get(machine())->unregisterEventTransition(q); -} - -void QEventTransitionPrivate::maybeRegister() -{ - Q_Q(QEventTransition); - if (QStateMachine *mach = machine()) - QStateMachinePrivate::get(mach)->maybeRegisterEventTransition(q); -} - -/*! - Constructs a new QEventTransition object with the given \a sourceState. -*/ -QEventTransition::QEventTransition(QState *sourceState) - : QAbstractTransition(*new QEventTransitionPrivate, sourceState) -{ -} - -/*! - Constructs a new QEventTransition object associated with events of the given - \a type for the given \a object, and with the given \a sourceState. -*/ -QEventTransition::QEventTransition(QObject *object, QEvent::Type type, - QState *sourceState) - : QAbstractTransition(*new QEventTransitionPrivate, sourceState) -{ - Q_D(QEventTransition); - d->registered = false; - d->object = object; - d->eventType = type; - d->maybeRegister(); -} - -/*! - \internal -*/ -QEventTransition::QEventTransition(QEventTransitionPrivate &dd, QState *parent) - : QAbstractTransition(dd, parent) -{ -} - -/*! - \internal -*/ -QEventTransition::QEventTransition(QEventTransitionPrivate &dd, QObject *object, - QEvent::Type type, QState *parent) - : QAbstractTransition(dd, parent) -{ - Q_D(QEventTransition); - d->registered = false; - d->object = object; - d->eventType = type; - d->maybeRegister(); -} - -/*! - Destroys this QObject event transition. -*/ -QEventTransition::~QEventTransition() -{ -} - -/*! - Returns the event type that this event transition is associated with. -*/ -QEvent::Type QEventTransition::eventType() const -{ - Q_D(const QEventTransition); - return d->eventType; -} - -/*! - Sets the event \a type that this event transition is associated with. -*/ -void QEventTransition::setEventType(QEvent::Type type) -{ - Q_D(QEventTransition); - if (d->eventType == type) - return; - d->unregister(); - d->eventType = type; - d->maybeRegister(); -} - -/*! - Returns the event source associated with this event transition. -*/ -QObject *QEventTransition::eventSource() const -{ - Q_D(const QEventTransition); - return d->object; -} - -/*! - Sets the event source associated with this event transition to be the given - \a object. -*/ -void QEventTransition::setEventSource(QObject *object) -{ - Q_D(QEventTransition); - if (d->object == object) - return; - d->unregister(); - d->object = object; - d->maybeRegister(); -} - -/*! - \reimp -*/ -bool QEventTransition::eventTest(QEvent *event) -{ - Q_D(const QEventTransition); - if (event->type() == QEvent::StateMachineWrapped) { - QStateMachine::WrappedEvent *we = static_cast(event); - return (we->object() == d->object) - && (we->event()->type() == d->eventType); - } - return false; -} - -/*! - \reimp -*/ -void QEventTransition::onTransition(QEvent *event) -{ - Q_UNUSED(event); -} - -/*! - \reimp -*/ -bool QEventTransition::event(QEvent *e) -{ - return QAbstractTransition::event(e); -} - -QT_END_NAMESPACE - -#include "moc_qeventtransition.cpp" diff --git a/src/corelib/statemachine/qeventtransition.h b/src/corelib/statemachine/qeventtransition.h deleted file mode 100644 index ff4a991162..0000000000 --- a/src/corelib/statemachine/qeventtransition.h +++ /dev/null @@ -1,85 +0,0 @@ -/**************************************************************************** -** -** 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 QEVENTTRANSITION_H -#define QEVENTTRANSITION_H - -#include -#include - -QT_REQUIRE_CONFIG(qeventtransition); - -QT_BEGIN_NAMESPACE - -class QEventTransitionPrivate; -class Q_CORE_EXPORT QEventTransition : public QAbstractTransition -{ - Q_OBJECT - Q_PROPERTY(QObject* eventSource READ eventSource WRITE setEventSource) - Q_PROPERTY(QEvent::Type eventType READ eventType WRITE setEventType) -public: - QEventTransition(QState *sourceState = nullptr); - QEventTransition(QObject *object, QEvent::Type type, QState *sourceState = nullptr); - ~QEventTransition(); - - QObject *eventSource() const; - void setEventSource(QObject *object); - - QEvent::Type eventType() const; - void setEventType(QEvent::Type type); - -protected: - bool eventTest(QEvent *event) override; - void onTransition(QEvent *event) override; - - bool event(QEvent *e) override; - -protected: - QEventTransition(QEventTransitionPrivate &dd, QState *parent); - QEventTransition(QEventTransitionPrivate &dd, QObject *object, - QEvent::Type type, QState *parent); - -private: - Q_DISABLE_COPY(QEventTransition) - Q_DECLARE_PRIVATE(QEventTransition) -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/corelib/statemachine/qeventtransition_p.h b/src/corelib/statemachine/qeventtransition_p.h deleted file mode 100644 index e30e12bc8d..0000000000 --- a/src/corelib/statemachine/qeventtransition_p.h +++ /dev/null @@ -1,81 +0,0 @@ -/**************************************************************************** -** -** 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 QEVENTTRANSITION_P_H -#define QEVENTTRANSITION_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/qabstracttransition_p.h" - -QT_REQUIRE_CONFIG(qeventtransition); - -QT_BEGIN_NAMESPACE - -class QEventTransition; -class Q_CORE_EXPORT QEventTransitionPrivate : public QAbstractTransitionPrivate -{ - Q_DECLARE_PUBLIC(QEventTransition) -public: - QEventTransitionPrivate(); - ~QEventTransitionPrivate(); - - static QEventTransitionPrivate *get(QEventTransition *q) - { return q->d_func(); } - - void unregister(); - void maybeRegister(); - - QObject *object; - bool registered; - QEvent::Type eventType; -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/corelib/statemachine/qfinalstate.cpp b/src/corelib/statemachine/qfinalstate.cpp deleted file mode 100644 index d8bfd30974..0000000000 --- a/src/corelib/statemachine/qfinalstate.cpp +++ /dev/null @@ -1,141 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#include "qfinalstate_p.h" - -QT_BEGIN_NAMESPACE - -/*! - \class QFinalState - \inmodule QtCore - - \brief The QFinalState class provides a final state. - - \since 4.6 - \ingroup statemachine - - A final state is used to communicate that (part of) a QStateMachine has - finished its work. When a final top-level state is entered, the state - machine's \l{QStateMachine::finished()}{finished}() signal is emitted. In - general, when a final substate (a child of a QState) is entered, the parent - state's \l{QState::finished()}{finished}() signal is emitted. QFinalState - is part of \l{The State Machine Framework}. - - To use a final state, you create a QFinalState object and add a transition - to it from another state. Example: - - \code - QPushButton button; - - QStateMachine machine; - QState *s1 = new QState(); - QFinalState *s2 = new QFinalState(); - s1->addTransition(&button, SIGNAL(clicked()), s2); - machine.addState(s1); - machine.addState(s2); - - QObject::connect(&machine, SIGNAL(finished()), QApplication::instance(), SLOT(quit())); - machine.setInitialState(s1); - machine.start(); - \endcode - - \sa QState::finished() -*/ - -QFinalStatePrivate::QFinalStatePrivate() - : QAbstractStatePrivate(FinalState) -{ -} - -QFinalStatePrivate::~QFinalStatePrivate() -{ - // to prevent vtables being generated in every file that includes the private header -} - -/*! - Constructs a new QFinalState object with the given \a parent state. -*/ -QFinalState::QFinalState(QState *parent) - : QAbstractState(*new QFinalStatePrivate, parent) -{ -} - -/*! - \internal - */ -QFinalState::QFinalState(QFinalStatePrivate &dd, QState *parent) - : QAbstractState(dd, parent) -{ -} - - -/*! - Destroys this final state. -*/ -QFinalState::~QFinalState() -{ -} - -/*! - \reimp -*/ -void QFinalState::onEntry(QEvent *event) -{ - Q_UNUSED(event); -} - -/*! - \reimp -*/ -void QFinalState::onExit(QEvent *event) -{ - Q_UNUSED(event); -} - -/*! - \reimp -*/ -bool QFinalState::event(QEvent *e) -{ - return QAbstractState::event(e); -} - -QT_END_NAMESPACE - -#include "moc_qfinalstate.cpp" diff --git a/src/corelib/statemachine/qfinalstate.h b/src/corelib/statemachine/qfinalstate.h deleted file mode 100644 index 1e52a0411d..0000000000 --- a/src/corelib/statemachine/qfinalstate.h +++ /dev/null @@ -1,73 +0,0 @@ -/**************************************************************************** -** -** 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 QFINALSTATE_H -#define QFINALSTATE_H - -#include - -QT_REQUIRE_CONFIG(statemachine); - -QT_BEGIN_NAMESPACE - -class QFinalStatePrivate; -class Q_CORE_EXPORT QFinalState : public QAbstractState -{ - Q_OBJECT -public: - QFinalState(QState *parent = nullptr); - ~QFinalState(); - -protected: - void onEntry(QEvent *event) override; - void onExit(QEvent *event) override; - - bool event(QEvent *e) override; - -protected: - explicit QFinalState(QFinalStatePrivate &dd, QState *parent); - -private: - Q_DISABLE_COPY(QFinalState) - Q_DECLARE_PRIVATE(QFinalState) -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/corelib/statemachine/qfinalstate_p.h b/src/corelib/statemachine/qfinalstate_p.h deleted file mode 100644 index 65598f6c19..0000000000 --- a/src/corelib/statemachine/qfinalstate_p.h +++ /dev/null @@ -1,72 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 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 QFINALSTATE_P_H -#define QFINALSTATE_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 "qfinalstate.h" -#include "private/qabstractstate_p.h" - -QT_REQUIRE_CONFIG(statemachine); - -QT_BEGIN_NAMESPACE - -class Q_CORE_EXPORT QFinalStatePrivate : public QAbstractStatePrivate -{ - Q_DECLARE_PUBLIC(QFinalState) - -public: - QFinalStatePrivate(); - ~QFinalStatePrivate(); -}; - -QT_END_NAMESPACE - -#endif // QFINALSTATE_P_H diff --git a/src/corelib/statemachine/qhistorystate.cpp b/src/corelib/statemachine/qhistorystate.cpp deleted file mode 100644 index e5b8075b96..0000000000 --- a/src/corelib/statemachine/qhistorystate.cpp +++ /dev/null @@ -1,334 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#include "qhistorystate.h" -#include "qhistorystate_p.h" - -QT_BEGIN_NAMESPACE - -/*! - \class QHistoryState - \inmodule QtCore - - \brief The QHistoryState class provides a means of returning to a previously active substate. - - \since 4.6 - \ingroup statemachine - - A history state is a pseudo-state that represents the child state that the - parent state was in the last time the parent state was exited. A transition - with a history state as its target is in fact a transition to one or more - other child states of the parent state. QHistoryState is part of \l{The - State Machine Framework}. - - Use the setDefaultState() function to set the state that should be entered - if the parent state has never been entered. Example: - - \code - QStateMachine machine; - - QState *s1 = new QState(); - QState *s11 = new QState(s1); - QState *s12 = new QState(s1); - - QHistoryState *s1h = new QHistoryState(s1); - s1h->setDefaultState(s11); - - machine.addState(s1); - - QState *s2 = new QState(); - machine.addState(s2); - - QPushButton *button = new QPushButton(); - // Clicking the button will cause the state machine to enter the child state - // that s1 was in the last time s1 was exited, or the history state's default - // state if s1 has never been entered. - s1->addTransition(button, SIGNAL(clicked()), s1h); - \endcode - - If more than one default state has to be entered, or if the transition to the default state(s) - has to be acted upon, the defaultTransition should be set instead. Note that the eventTest() - method of that transition will never be called: the selection and execution of the transition is - done automatically when entering the history state. - - By default a history state is shallow, meaning that it won't remember nested - states. This can be configured through the historyType property. -*/ - -/*! - \property QHistoryState::defaultTransition - - \brief the default transition of this history state -*/ - -/*! - \property QHistoryState::defaultState - - \brief the default state of this history state -*/ - -/*! - \property QHistoryState::historyType - - \brief the type of history that this history state records - - The default value of this property is QHistoryState::ShallowHistory. -*/ - -/*! - \enum QHistoryState::HistoryType - - This enum specifies the type of history that a QHistoryState records. - - \value ShallowHistory Only the immediate child states of the parent state - are recorded. In this case a transition with the history state as its - target will end up in the immediate child state that the parent was in the - last time it was exited. This is the default. - - \value DeepHistory Nested states are recorded. In this case a transition - with the history state as its target will end up in the most deeply nested - descendant state the parent was in the last time it was exited. -*/ - -namespace { -class DefaultStateTransition: public QAbstractTransition -{ - Q_OBJECT - -public: - DefaultStateTransition(QHistoryState *source, QAbstractState *target); - -protected: - // It doesn't matter whether this transition matches any event or not. It is always associated - // with a QHistoryState, and as soon as the state-machine detects that it enters a history - // state, it will handle this transition as a special case. The history state itself is never - // entered either: either the stored configuration will be used, or the target(s) of this - // transition are used. - bool eventTest(QEvent *event) override { Q_UNUSED(event); return false; } - void onTransition(QEvent *event) override { Q_UNUSED(event); } -}; -} - -QHistoryStatePrivate::QHistoryStatePrivate() - : QAbstractStatePrivate(HistoryState) - , defaultTransition(nullptr) - , historyType(QHistoryState::ShallowHistory) -{ -} - -DefaultStateTransition::DefaultStateTransition(QHistoryState *source, QAbstractState *target) - : QAbstractTransition() -{ - setParent(source); - setTargetState(target); -} - -/*! - Constructs a new shallow history state with the given \a parent state. -*/ -QHistoryState::QHistoryState(QState *parent) - : QAbstractState(*new QHistoryStatePrivate, parent) -{ -} -/*! - Constructs a new history state of the given \a type, with the given \a - parent state. -*/ -QHistoryState::QHistoryState(HistoryType type, QState *parent) - : QAbstractState(*new QHistoryStatePrivate, parent) -{ - Q_D(QHistoryState); - d->historyType = type; -} - -/*! - Destroys this history state. -*/ -QHistoryState::~QHistoryState() -{ -} - -/*! - Returns this history state's default transition. The default transition is - taken when the history state has never been entered before. The target states - of the default transition therefore make up the default state. - - \since 5.6 -*/ -QAbstractTransition *QHistoryState::defaultTransition() const -{ - Q_D(const QHistoryState); - return d->defaultTransition; -} - -/*! - Sets this history state's default transition to be the given \a transition. - This will set the source state of the \a transition to the history state. - - Note that the eventTest method of the \a transition will never be called. - - \since 5.6 -*/ -void QHistoryState::setDefaultTransition(QAbstractTransition *transition) -{ - Q_D(QHistoryState); - if (d->defaultTransition != transition) { - d->defaultTransition = transition; - transition->setParent(this); - emit defaultTransitionChanged(QHistoryState::QPrivateSignal()); - } -} - -/*! - Returns this history state's default state. The default state indicates the - state to transition to if the parent state has never been entered before. -*/ -QAbstractState *QHistoryState::defaultState() const -{ - Q_D(const QHistoryState); - return d->defaultTransition ? d->defaultTransition->targetState() : nullptr; -} - -static inline bool isSoleEntry(const QList &states, const QAbstractState * state) -{ - return states.size() == 1 && states.first() == state; -} - -/*! - Sets this history state's default state to be the given \a state. - \a state must be a sibling of this history state. - - Note that this function does not set \a state as the initial state - of its parent. -*/ -void QHistoryState::setDefaultState(QAbstractState *state) -{ - Q_D(QHistoryState); - if (state && state->parentState() != parentState()) { - qWarning("QHistoryState::setDefaultState: state %p does not belong " - "to this history state's group (%p)", state, parentState()); - return; - } - if (!d->defaultTransition || !isSoleEntry(d->defaultTransition->targetStates(), state)) { - if (!d->defaultTransition || !qobject_cast(d->defaultTransition)) { - d->defaultTransition = new DefaultStateTransition(this, state); - emit defaultTransitionChanged(QHistoryState::QPrivateSignal()); - } else { - d->defaultTransition->setTargetState(state); - } - emit defaultStateChanged(QHistoryState::QPrivateSignal()); - } -} - -/*! - Returns the type of history that this history state records. -*/ -QHistoryState::HistoryType QHistoryState::historyType() const -{ - Q_D(const QHistoryState); - return d->historyType; -} - -/*! - Sets the \a type of history that this history state records. -*/ -void QHistoryState::setHistoryType(HistoryType type) -{ - Q_D(QHistoryState); - if (d->historyType != type) { - d->historyType = type; - emit historyTypeChanged(QHistoryState::QPrivateSignal()); - } -} - -/*! - \reimp -*/ -void QHistoryState::onEntry(QEvent *event) -{ - Q_UNUSED(event); -} - -/*! - \reimp -*/ -void QHistoryState::onExit(QEvent *event) -{ - Q_UNUSED(event); -} - -/*! - \reimp -*/ -bool QHistoryState::event(QEvent *e) -{ - return QAbstractState::event(e); -} - -/*! - \fn QHistoryState::defaultStateChanged() - \since 5.4 - - This signal is emitted when the defaultState property is changed. - - \sa QHistoryState::defaultState -*/ - -/*! - \fn QHistoryState::historyTypeChanged() - \since 5.4 - - This signal is emitted when the historyType property is changed. - - \sa QHistoryState::historyType -*/ - -/*! - \fn QHistoryState::defaultTransitionChanged() - \since 5.6 - - This signal is emitted when the defaultTransition property is changed. - - \sa QHistoryState::defaultTransition -*/ - -QT_END_NAMESPACE - -#include "moc_qhistorystate.cpp" -#include "qhistorystate.moc" diff --git a/src/corelib/statemachine/qhistorystate.h b/src/corelib/statemachine/qhistorystate.h deleted file mode 100644 index 44f4c5d6d4..0000000000 --- a/src/corelib/statemachine/qhistorystate.h +++ /dev/null @@ -1,95 +0,0 @@ -/**************************************************************************** -** -** 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 QHISTORYSTATE_H -#define QHISTORYSTATE_H - -#include - -QT_REQUIRE_CONFIG(statemachine); - -QT_BEGIN_NAMESPACE - -class QAbstractTransition; -class QHistoryStatePrivate; -class Q_CORE_EXPORT QHistoryState : public QAbstractState -{ - Q_OBJECT - Q_PROPERTY(QAbstractState* defaultState READ defaultState WRITE setDefaultState NOTIFY defaultStateChanged) - Q_PROPERTY(QAbstractTransition* defaultTransition READ defaultTransition WRITE setDefaultTransition NOTIFY defaultTransitionChanged) - Q_PROPERTY(HistoryType historyType READ historyType WRITE setHistoryType NOTIFY historyTypeChanged) -public: - enum HistoryType { - ShallowHistory, - DeepHistory - }; - Q_ENUM(HistoryType) - - QHistoryState(QState *parent = nullptr); - QHistoryState(HistoryType type, QState *parent = nullptr); - ~QHistoryState(); - - QAbstractTransition *defaultTransition() const; - void setDefaultTransition(QAbstractTransition *transition); - - QAbstractState *defaultState() const; - void setDefaultState(QAbstractState *state); - - HistoryType historyType() const; - void setHistoryType(HistoryType type); - -Q_SIGNALS: - void defaultTransitionChanged(QPrivateSignal); - void defaultStateChanged(QPrivateSignal); - void historyTypeChanged(QPrivateSignal); - -protected: - void onEntry(QEvent *event) override; - void onExit(QEvent *event) override; - - bool event(QEvent *e) override; - -private: - Q_DISABLE_COPY(QHistoryState) - Q_DECLARE_PRIVATE(QHistoryState) -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/corelib/statemachine/qhistorystate_p.h b/src/corelib/statemachine/qhistorystate_p.h deleted file mode 100644 index 18d571feb7..0000000000 --- a/src/corelib/statemachine/qhistorystate_p.h +++ /dev/null @@ -1,80 +0,0 @@ -/**************************************************************************** -** -** 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 QHISTORYSTATE_P_H -#define QHISTORYSTATE_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/qabstractstate_p.h" -#include -#include -#include - -QT_REQUIRE_CONFIG(statemachine); - -QT_BEGIN_NAMESPACE - -class QHistoryStatePrivate : public QAbstractStatePrivate -{ - Q_DECLARE_PUBLIC(QHistoryState) - -public: - QHistoryStatePrivate(); - - static QHistoryStatePrivate *get(QHistoryState *q) - { return q->d_func(); } - - QAbstractTransition *defaultTransition; - QHistoryState::HistoryType historyType; - QList configuration; -}; - -QT_END_NAMESPACE - -#endif // QHISTORYSTATE_P_H diff --git a/src/corelib/statemachine/qsignaleventgenerator_p.h b/src/corelib/statemachine/qsignaleventgenerator_p.h deleted file mode 100644 index a9d5b96920..0000000000 --- a/src/corelib/statemachine/qsignaleventgenerator_p.h +++ /dev/null @@ -1,78 +0,0 @@ -/**************************************************************************** -** -** 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 QSIGNALEVENTGENERATOR_P_H -#define QSIGNALEVENTGENERATOR_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 -#include - -QT_REQUIRE_CONFIG(statemachine); - -QT_BEGIN_NAMESPACE - -class QStateMachine; - -class QSignalEventGenerator : public QObject -{ - Q_OBJECT -public: - QSignalEventGenerator(QStateMachine *parent); - -private Q_SLOTS: - void execute(QMethodRawArguments a); - -private: - Q_DISABLE_COPY_MOVE(QSignalEventGenerator) -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/corelib/statemachine/qsignaltransition.cpp b/src/corelib/statemachine/qsignaltransition.cpp deleted file mode 100644 index 8e57695fd7..0000000000 --- a/src/corelib/statemachine/qsignaltransition.cpp +++ /dev/null @@ -1,287 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#include "qsignaltransition.h" -#include "qsignaltransition_p.h" -#include "qstate.h" -#include "qstate_p.h" -#include "qstatemachine.h" -#include "qstatemachine_p.h" -#include - -QT_BEGIN_NAMESPACE - -/*! - \class QSignalTransition - \inmodule QtCore - - \brief The QSignalTransition class provides a transition based on a Qt signal. - - \since 4.6 - \ingroup statemachine - - Typically you would use the overload of QState::addTransition() that takes a - sender and signal as arguments, rather than creating QSignalTransition - objects directly. QSignalTransition is part of \l{The State Machine - Framework}. - - You can subclass QSignalTransition and reimplement eventTest() to make a - signal transition conditional; the event object passed to eventTest() will - be a QStateMachine::SignalEvent object. Example: - - \code - class CheckedTransition : public QSignalTransition - { - public: - CheckedTransition(QCheckBox *check) - : QSignalTransition(check, SIGNAL(stateChanged(int))) {} - protected: - bool eventTest(QEvent *e) { - if (!QSignalTransition::eventTest(e)) - return false; - QStateMachine::SignalEvent *se = static_cast(e); - return (se->arguments().at(0).toInt() == Qt::Checked); - } - }; - - ... - - QCheckBox *check = new QCheckBox(); - check->setTristate(true); - - QState *s1 = new QState(); - QState *s2 = new QState(); - CheckedTransition *t1 = new CheckedTransition(check); - t1->setTargetState(s2); - s1->addTransition(t1); - \endcode -*/ - -/*! - \property QSignalTransition::senderObject - - \brief the sender object that this signal transition is associated with -*/ - -/*! - \property QSignalTransition::signal - - \brief the signal that this signal transition is associated with -*/ - -QSignalTransitionPrivate::QSignalTransitionPrivate() -{ - sender = nullptr; - signalIndex = -1; -} - -void QSignalTransitionPrivate::unregister() -{ - Q_Q(QSignalTransition); - if ((signalIndex == -1) || !machine()) - return; - QStateMachinePrivate::get(machine())->unregisterSignalTransition(q); -} - -void QSignalTransitionPrivate::maybeRegister() -{ - Q_Q(QSignalTransition); - if (QStateMachine *mach = machine()) - QStateMachinePrivate::get(mach)->maybeRegisterSignalTransition(q); -} - -/*! - Constructs a new signal transition with the given \a sourceState. -*/ -QSignalTransition::QSignalTransition(QState *sourceState) - : QAbstractTransition(*new QSignalTransitionPrivate, sourceState) -{ -} - -/*! - Constructs a new signal transition associated with the given \a signal of - the given \a sender, and with the given \a sourceState. -*/ -QSignalTransition::QSignalTransition(const QObject *sender, const char *signal, - QState *sourceState) - : QAbstractTransition(*new QSignalTransitionPrivate, sourceState) -{ - Q_D(QSignalTransition); - d->sender = sender; - d->signal = signal; - d->maybeRegister(); -} - -/*! - \fn template QSignalTransition::QSignalTransition(const QObject *sender, PointerToMemberFunction signal, QState *sourceState) - \since 5.7 - \overload - - Constructs a new signal transition associated with the given \a signal of - the given \a sender object and with the given \a sourceState. - This constructor is enabled if the compiler supports delegating constructors, - as indicated by the presence of the macro Q_COMPILER_DELEGATING_CONSTRUCTORS. -*/ - -/*! - Destroys this signal transition. -*/ -QSignalTransition::~QSignalTransition() -{ -} - -/*! - Returns the sender object associated with this signal transition. -*/ -QObject *QSignalTransition::senderObject() const -{ - Q_D(const QSignalTransition); - return const_cast(d->sender); -} - -/*! - Sets the \a sender object associated with this signal transition. -*/ -void QSignalTransition::setSenderObject(const QObject *sender) -{ - Q_D(QSignalTransition); - if (sender == d->sender) - return; - d->unregister(); - d->sender = sender; - d->maybeRegister(); - emit senderObjectChanged(QPrivateSignal()); -} - -/*! - Returns the signal associated with this signal transition. -*/ -QByteArray QSignalTransition::signal() const -{ - Q_D(const QSignalTransition); - return d->signal; -} - -/*! - Sets the \a signal associated with this signal transition. -*/ -void QSignalTransition::setSignal(const QByteArray &signal) -{ - Q_D(QSignalTransition); - if (signal == d->signal) - return; - d->unregister(); - d->signal = signal; - d->maybeRegister(); - emit signalChanged(QPrivateSignal()); -} - -/*! - \reimp - - The default implementation returns \c true if the \a event is a - QStateMachine::SignalEvent object and the event's sender and signal index - match this transition, and returns \c false otherwise. -*/ -bool QSignalTransition::eventTest(QEvent *event) -{ - Q_D(const QSignalTransition); - if (event->type() == QEvent::StateMachineSignal) { - if (d->signalIndex == -1) - return false; - QStateMachine::SignalEvent *se = static_cast(event); - return (se->sender() == d->sender) - && (se->signalIndex() == d->signalIndex); - } - return false; -} - -/*! - \reimp -*/ -void QSignalTransition::onTransition(QEvent *event) -{ - Q_UNUSED(event); -} - -/*! - \reimp -*/ -bool QSignalTransition::event(QEvent *e) -{ - return QAbstractTransition::event(e); -} - -/*! - \fn QSignalTransition::senderObjectChanged() - \since 5.4 - - This signal is emitted when the senderObject property is changed. - - \sa QSignalTransition::senderObject -*/ - -/*! - \fn QSignalTransition::signalChanged() - \since 5.4 - - This signal is emitted when the signal property is changed. - - \sa QSignalTransition::signal -*/ - -void QSignalTransitionPrivate::callOnTransition(QEvent *e) -{ - Q_Q(QSignalTransition); - - if (e->type() == QEvent::StateMachineSignal) { - QStateMachine::SignalEvent *se = static_cast(e); - int savedSignalIndex = se->m_signalIndex; - se->m_signalIndex = originalSignalIndex; - q->onTransition(e); - se->m_signalIndex = savedSignalIndex; - } else { - q->onTransition(e); - } -} - - -QT_END_NAMESPACE - -#include "moc_qsignaltransition.cpp" diff --git a/src/corelib/statemachine/qsignaltransition.h b/src/corelib/statemachine/qsignaltransition.h deleted file mode 100644 index e785a18c73..0000000000 --- a/src/corelib/statemachine/qsignaltransition.h +++ /dev/null @@ -1,99 +0,0 @@ -/**************************************************************************** -** -** 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 QSIGNALTRANSITION_H -#define QSIGNALTRANSITION_H - -#include -#include - -QT_REQUIRE_CONFIG(statemachine); - -QT_BEGIN_NAMESPACE - -class QSignalTransitionPrivate; -class Q_CORE_EXPORT QSignalTransition : public QAbstractTransition -{ - Q_OBJECT - Q_PROPERTY(QObject* senderObject READ senderObject WRITE setSenderObject NOTIFY senderObjectChanged) - Q_PROPERTY(QByteArray signal READ signal WRITE setSignal NOTIFY signalChanged) - -public: - QSignalTransition(QState *sourceState = nullptr); - QSignalTransition(const QObject *sender, const char *signal, - QState *sourceState = nullptr); -#ifdef Q_QDOC - template - QSignalTransition(const QObject *object, PointerToMemberFunction signal, - QState *sourceState = nullptr); -#elif defined(Q_COMPILER_DELEGATING_CONSTRUCTORS) - template - QSignalTransition(const typename QtPrivate::FunctionPointer::Object *obj, - Func sig, QState *srcState = nullptr) - : QSignalTransition(obj, QMetaMethod::fromSignal(sig).methodSignature().constData(), srcState) - { - } -#endif - - ~QSignalTransition(); - - QObject *senderObject() const; - void setSenderObject(const QObject *sender); - - QByteArray signal() const; - void setSignal(const QByteArray &signal); - -protected: - bool eventTest(QEvent *event) override; - void onTransition(QEvent *event) override; - - bool event(QEvent *e) override; - -Q_SIGNALS: - void senderObjectChanged(QPrivateSignal); - void signalChanged(QPrivateSignal); - -private: - Q_DISABLE_COPY(QSignalTransition) - Q_DECLARE_PRIVATE(QSignalTransition) -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/corelib/statemachine/qsignaltransition_p.h b/src/corelib/statemachine/qsignaltransition_p.h deleted file mode 100644 index b3de334677..0000000000 --- a/src/corelib/statemachine/qsignaltransition_p.h +++ /dev/null @@ -1,83 +0,0 @@ -/**************************************************************************** -** -** 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 QSIGNALTRANSITION_P_H -#define QSIGNALTRANSITION_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/qabstracttransition_p.h" - -QT_REQUIRE_CONFIG(statemachine); - -QT_BEGIN_NAMESPACE - -class QSignalTransition; -class QSignalTransitionPrivate : public QAbstractTransitionPrivate -{ - Q_DECLARE_PUBLIC(QSignalTransition) -public: - QSignalTransitionPrivate(); - - static QSignalTransitionPrivate *get(QSignalTransition *q) - { return q->d_func(); } - - void unregister(); - void maybeRegister(); - - void callOnTransition(QEvent *e) override; - - const QObject *sender; - QByteArray signal; - int signalIndex; - int originalSignalIndex; -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/corelib/statemachine/qstate.cpp b/src/corelib/statemachine/qstate.cpp deleted file mode 100644 index dd92bfe7ba..0000000000 --- a/src/corelib/statemachine/qstate.cpp +++ /dev/null @@ -1,603 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#include "qstate_p.h" -#include "qhistorystate.h" -#include "qhistorystate_p.h" -#include "qabstracttransition.h" -#include "qabstracttransition_p.h" -#include "qsignaltransition.h" -#include "qstatemachine.h" -#include "qstatemachine_p.h" - -QT_BEGIN_NAMESPACE - -/*! - \class QState - \inmodule QtCore - - \brief The QState class provides a general-purpose state for QStateMachine. - - \since 4.6 - \ingroup statemachine - - QState objects can have child states, and can have transitions to other - states. QState is part of \l{The State Machine Framework}. - - The addTransition() function adds a transition. The removeTransition() - function removes a transition. The transitions() function returns the - state's outgoing transitions. - - The assignProperty() function is used for defining property assignments that - should be performed when a state is entered. - - Top-level states must be passed a QStateMachine object as their parent - state, or added to a state machine using QStateMachine::addState(). - - \section1 States with Child States - - The childMode property determines how child states are treated. For - non-parallel state groups, the setInitialState() function must be called to - set the initial state. The child states are mutually exclusive states, and - the state machine needs to know which child state to enter when the parent - state is the target of a transition. - - The state emits the QState::finished() signal when a final child state - (QFinalState) is entered. - - The setErrorState() sets the state's error state. The error state is the - state that the state machine will transition to if an error is detected when - attempting to enter the state (e.g. because no initial state has been set). - -*/ - -/*! - \property QState::initialState - - \brief the initial state of this state (one of its child states) -*/ - -/*! - \property QState::errorState - - \brief the error state of this state -*/ - -/*! - \property QState::childMode - - \brief the child mode of this state - - The default value of this property is QState::ExclusiveStates. -*/ - -/*! - \enum QState::ChildMode - - This enum specifies how a state's child states are treated. - - \value ExclusiveStates The child states are mutually exclusive and an - initial state must be set by calling QState::setInitialState(). - - \value ParallelStates The child states are parallel. When the parent state - is entered, all its child states are entered in parallel. -*/ - -/*! - \enum QState::RestorePolicy - - This enum specifies the restore policy type. The restore policy - takes effect when the machine enters a state which sets one or more - properties. If the restore policy is set to RestoreProperties, - the state machine will save the original value of the property before the - new value is set. - - Later, when the machine either enters a state which does not set - a value for the given property, the property will automatically be restored - to its initial value. - - Only one initial value will be saved for any given property. If a value for a property has - already been saved by the state machine, it will not be overwritten until the property has been - successfully restored. - - \value DontRestoreProperties The state machine should not save the initial values of properties - and restore them later. - \value RestoreProperties The state machine should save the initial values of properties - and restore them later. - - \sa QStateMachine::globalRestorePolicy, QState::assignProperty() -*/ - -QStatePrivate::QStatePrivate() - : QAbstractStatePrivate(StandardState), - errorState(nullptr), initialState(nullptr), childMode(QState::ExclusiveStates), - childStatesListNeedsRefresh(true), transitionsListNeedsRefresh(true) -{ -} - -QStatePrivate::~QStatePrivate() -{ -} - -void QStatePrivate::emitFinished() -{ - Q_Q(QState); - emit q->finished(QState::QPrivateSignal()); -} - -void QStatePrivate::emitPropertiesAssigned() -{ - Q_Q(QState); - emit q->propertiesAssigned(QState::QPrivateSignal()); -} - -/*! - Constructs a new state with the given \a parent state. -*/ -QState::QState(QState *parent) - : QAbstractState(*new QStatePrivate, parent) -{ -} - -/*! - Constructs a new state with the given \a childMode and the given \a parent - state. -*/ -QState::QState(ChildMode childMode, QState *parent) - : QAbstractState(*new QStatePrivate, parent) -{ - Q_D(QState); - d->childMode = childMode; -} - -/*! - \internal -*/ -QState::QState(QStatePrivate &dd, QState *parent) - : QAbstractState(dd, parent) -{ -} - -/*! - Destroys this state. -*/ -QState::~QState() -{ -} - -QList QStatePrivate::childStates() const -{ - if (childStatesListNeedsRefresh) { - childStatesList.clear(); - QList::const_iterator it; - for (it = children.constBegin(); it != children.constEnd(); ++it) { - QAbstractState *s = qobject_cast(*it); - if (!s || qobject_cast(s)) - continue; - childStatesList.append(s); - } - childStatesListNeedsRefresh = false; - } - return childStatesList; -} - -QList QStatePrivate::historyStates() const -{ - QList result; - QList::const_iterator it; - for (it = children.constBegin(); it != children.constEnd(); ++it) { - QHistoryState *h = qobject_cast(*it); - if (h) - result.append(h); - } - return result; -} - -QList QStatePrivate::transitions() const -{ - if (transitionsListNeedsRefresh) { - transitionsList.clear(); - QList::const_iterator it; - for (it = children.constBegin(); it != children.constEnd(); ++it) { - QAbstractTransition *t = qobject_cast(*it); - if (t) - transitionsList.append(t); - } - transitionsListNeedsRefresh = false; - } - return transitionsList; -} - -#ifndef QT_NO_PROPERTIES - -/*! - Instructs this state to set the property with the given \a name of the given - \a object to the given \a value when the state is entered. - - \sa propertiesAssigned() -*/ -void QState::assignProperty(QObject *object, const char *name, - const QVariant &value) -{ - Q_D(QState); - if (!object) { - qWarning("QState::assignProperty: cannot assign property '%s' of null object", name); - return; - } - for (int i = 0; i < d->propertyAssignments.size(); ++i) { - QPropertyAssignment &assn = d->propertyAssignments[i]; - if (assn.hasTarget(object, name)) { - assn.value = value; - return; - } - } - d->propertyAssignments.append(QPropertyAssignment(object, name, value)); -} - -#endif // QT_NO_PROPERTIES - -/*! - Returns this state's error state. - - \sa QStateMachine::error() -*/ -QAbstractState *QState::errorState() const -{ - Q_D(const QState); - return d->errorState; -} - -/*! - Sets this state's error state to be the given \a state. If the error state - is not set, or if it is set to \nullptr, the state will inherit its parent's error - state recursively. If no error state is set for the state itself or any of - its ancestors, an error will cause the machine to stop executing and an error - will be printed to the console. -*/ -void QState::setErrorState(QAbstractState *state) -{ - Q_D(QState); - if (state != nullptr && qobject_cast(state)) { - qWarning("QStateMachine::setErrorState: root state cannot be error state"); - return; - } - if (state != nullptr && (!state->machine() || ((state->machine() != machine()) && !qobject_cast(this)))) { - qWarning("QState::setErrorState: error state cannot belong " - "to a different state machine"); - return; - } - - if (d->errorState != state) { - d->errorState = state; - emit errorStateChanged(QState::QPrivateSignal()); - } -} - -/*! - Adds the given \a transition. The transition has this state as the source. - This state takes ownership of the transition. -*/ -void QState::addTransition(QAbstractTransition *transition) -{ - Q_D(QState); - if (!transition) { - qWarning("QState::addTransition: cannot add null transition"); - return ; - } - - transition->setParent(this); - const QList> &targets = QAbstractTransitionPrivate::get(transition)->targetStates; - for (int i = 0; i < targets.size(); ++i) { - QAbstractState *t = targets.at(i).data(); - if (!t) { - qWarning("QState::addTransition: cannot add transition to null state"); - return ; - } - if ((QAbstractStatePrivate::get(t)->machine() != d->machine()) - && QAbstractStatePrivate::get(t)->machine() && d->machine()) { - qWarning("QState::addTransition: cannot add transition " - "to a state in a different state machine"); - return ; - } - } - if (QStateMachine *mach = machine()) - QStateMachinePrivate::get(mach)->maybeRegisterTransition(transition); -} - -/*! - \fn template QState::addTransition(const QObject *sender, PointerToMemberFunction signal, QAbstractState *target); - \since 5.5 - \overload - - Adds a transition associated with the given \a signal of the given \a sender - object, and returns the new QSignalTransition object. The transition has - this state as the source, and the given \a target as the target state. -*/ - -/*! - Adds a transition associated with the given \a signal of the given \a sender - object, and returns the new QSignalTransition object. The transition has - this state as the source, and the given \a target as the target state. -*/ -QSignalTransition *QState::addTransition(const QObject *sender, const char *signal, - QAbstractState *target) -{ - if (!sender) { - qWarning("QState::addTransition: sender cannot be null"); - return nullptr; - } - if (!signal) { - qWarning("QState::addTransition: signal cannot be null"); - return nullptr; - } - if (!target) { - qWarning("QState::addTransition: cannot add transition to null state"); - return nullptr; - } - int offset = (*signal == '0'+QSIGNAL_CODE) ? 1 : 0; - const QMetaObject *meta = sender->metaObject(); - if (meta->indexOfSignal(signal+offset) == -1) { - if (meta->indexOfSignal(QMetaObject::normalizedSignature(signal+offset)) == -1) { - qWarning("QState::addTransition: no such signal %s::%s", - meta->className(), signal+offset); - return nullptr; - } - } - QSignalTransition *trans = new QSignalTransition(sender, signal); - trans->setTargetState(target); - addTransition(trans); - return trans; -} - -namespace { - -// ### Make public? -class UnconditionalTransition : public QAbstractTransition -{ -public: - UnconditionalTransition(QAbstractState *target) - : QAbstractTransition() - { setTargetState(target); } -protected: - void onTransition(QEvent *) override {} - bool eventTest(QEvent *) override { return true; } -}; - -} // namespace - -/*! - Adds an unconditional transition from this state to the given \a target - state, and returns then new transition object. -*/ -QAbstractTransition *QState::addTransition(QAbstractState *target) -{ - if (!target) { - qWarning("QState::addTransition: cannot add transition to null state"); - return nullptr; - } - UnconditionalTransition *trans = new UnconditionalTransition(target); - addTransition(trans); - return trans; -} - -/*! - Removes the given \a transition from this state. The state releases - ownership of the transition. - - \sa addTransition() -*/ -void QState::removeTransition(QAbstractTransition *transition) -{ - Q_D(QState); - if (!transition) { - qWarning("QState::removeTransition: cannot remove null transition"); - return; - } - if (transition->sourceState() != this) { - qWarning("QState::removeTransition: transition %p's source state (%p)" - " is different from this state (%p)", - transition, transition->sourceState(), this); - return; - } - QStateMachinePrivate *mach = QStateMachinePrivate::get(d->machine()); - if (mach) - mach->unregisterTransition(transition); - transition->setParent(nullptr); -} - -/*! - \since 4.7 - - Returns this state's outgoing transitions (i.e. transitions where - this state is the \l{QAbstractTransition::sourceState()}{source - state}), or an empty list if this state has no outgoing transitions. - - \sa addTransition() -*/ -QList QState::transitions() const -{ - Q_D(const QState); - return d->transitions(); -} - -/*! - \reimp -*/ -void QState::onEntry(QEvent *event) -{ - Q_UNUSED(event); -} - -/*! - \reimp -*/ -void QState::onExit(QEvent *event) -{ - Q_UNUSED(event); -} - -/*! - Returns this state's initial state, or \nullptr if the state has no - initial state. -*/ -QAbstractState *QState::initialState() const -{ - Q_D(const QState); - return d->initialState; -} - -/*! - Sets this state's initial state to be the given \a state. - \a state has to be a child of this state. -*/ -void QState::setInitialState(QAbstractState *state) -{ - Q_D(QState); - if (d->childMode == QState::ParallelStates) { - qWarning("QState::setInitialState: ignoring attempt to set initial state " - "of parallel state group %p", this); - return; - } - if (state && (state->parentState() != this)) { - qWarning("QState::setInitialState: state %p is not a child of this state (%p)", - state, this); - return; - } - if (d->initialState != state) { - d->initialState = state; - emit initialStateChanged(QState::QPrivateSignal()); - } -} - -/*! - Returns the child mode of this state. -*/ -QState::ChildMode QState::childMode() const -{ - Q_D(const QState); - return d->childMode; -} - -/*! - Sets the child \a mode of this state. -*/ -void QState::setChildMode(ChildMode mode) -{ - Q_D(QState); - - if (mode == QState::ParallelStates && d->initialState) { - qWarning("QState::setChildMode: setting the child-mode of state %p to " - "parallel removes the initial state", this); - d->initialState = nullptr; - emit initialStateChanged(QState::QPrivateSignal()); - } - - if (d->childMode != mode) { - d->childMode = mode; - emit childModeChanged(QState::QPrivateSignal()); - } -} - -/*! - \reimp -*/ -bool QState::event(QEvent *e) -{ - Q_D(QState); - if ((e->type() == QEvent::ChildAdded) || (e->type() == QEvent::ChildRemoved)) { - d->childStatesListNeedsRefresh = true; - d->transitionsListNeedsRefresh = true; - if ((e->type() == QEvent::ChildRemoved) && (static_cast(e)->child() == d->initialState)) - d->initialState = nullptr; - } - return QAbstractState::event(e); -} - -/*! - \fn QState::finished() - - This signal is emitted when a final child state of this state is entered. - - \sa QFinalState -*/ - -/*! - \fn QState::propertiesAssigned() - - This signal is emitted when all properties have been assigned their final value. If the state - assigns a value to one or more properties for which an animation exists (either set on the - transition or as a default animation on the state machine), then the signal will not be emitted - until all such animations have finished playing. - - If there are no relevant animations, or no property assignments defined for the state, then - the signal will be emitted immediately before the state is entered. - - \sa QState::assignProperty(), QAbstractTransition::addAnimation() -*/ - -/*! - \fn QState::childModeChanged() - \since 5.4 - - This signal is emitted when the childMode property is changed. - - \sa QState::childMode -*/ - -/*! - \fn QState::initialStateChanged() - \since 5.4 - - This signal is emitted when the initialState property is changed. - - \sa QState::initialState -*/ - -/*! - \fn QState::errorStateChanged() - \since 5.4 - - This signal is emitted when the errorState property is changed. - - \sa QState::errorState -*/ - -QT_END_NAMESPACE - -#include "moc_qstate.cpp" diff --git a/src/corelib/statemachine/qstate.h b/src/corelib/statemachine/qstate.h deleted file mode 100644 index 9f1f07dfcc..0000000000 --- a/src/corelib/statemachine/qstate.h +++ /dev/null @@ -1,134 +0,0 @@ -/**************************************************************************** -** -** 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 QSTATE_H -#define QSTATE_H - -#include -#include -#include - -QT_REQUIRE_CONFIG(statemachine); - -QT_BEGIN_NAMESPACE - -class QAbstractTransition; -class QSignalTransition; - -class QStatePrivate; -class Q_CORE_EXPORT QState : public QAbstractState -{ - Q_OBJECT - Q_PROPERTY(QAbstractState* initialState READ initialState WRITE setInitialState NOTIFY initialStateChanged) - Q_PROPERTY(QAbstractState* errorState READ errorState WRITE setErrorState NOTIFY errorStateChanged) - Q_PROPERTY(ChildMode childMode READ childMode WRITE setChildMode NOTIFY childModeChanged) -public: - enum ChildMode { - ExclusiveStates, - ParallelStates - }; - Q_ENUM(ChildMode) - - enum RestorePolicy { - DontRestoreProperties, - RestoreProperties - }; - Q_ENUM(RestorePolicy) - - QState(QState *parent = nullptr); - QState(ChildMode childMode, QState *parent = nullptr); - ~QState(); - - QAbstractState *errorState() const; - void setErrorState(QAbstractState *state); - - void addTransition(QAbstractTransition *transition); - QSignalTransition *addTransition(const QObject *sender, const char *signal, QAbstractState *target); -#ifdef Q_QDOC - template - QSignalTransition *addTransition(const QObject *sender, PointerToMemberFunction signal, - QAbstractState *target); -#else - template - QSignalTransition *addTransition(const typename QtPrivate::FunctionPointer::Object *obj, - Func signal, QAbstractState *target) - { - const QMetaMethod signalMetaMethod = QMetaMethod::fromSignal(signal); - return addTransition(obj, signalMetaMethod.methodSignature().constData(), target); - } -#endif // Q_QDOC - QAbstractTransition *addTransition(QAbstractState *target); - void removeTransition(QAbstractTransition *transition); - QList transitions() const; - - QAbstractState *initialState() const; - void setInitialState(QAbstractState *state); - - ChildMode childMode() const; - void setChildMode(ChildMode mode); - -#ifndef QT_NO_PROPERTIES - void assignProperty(QObject *object, const char *name, - const QVariant &value); -#endif - -Q_SIGNALS: - void finished(QPrivateSignal); - void propertiesAssigned(QPrivateSignal); - void childModeChanged(QPrivateSignal); - void initialStateChanged(QPrivateSignal); - void errorStateChanged(QPrivateSignal); - -protected: - void onEntry(QEvent *event) override; - void onExit(QEvent *event) override; - - bool event(QEvent *e) override; - -protected: - QState(QStatePrivate &dd, QState *parent); - -private: - Q_DISABLE_COPY(QState) - Q_DECLARE_PRIVATE(QState) -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/corelib/statemachine/qstate_p.h b/src/corelib/statemachine/qstate_p.h deleted file mode 100644 index 25393a04b4..0000000000 --- a/src/corelib/statemachine/qstate_p.h +++ /dev/null @@ -1,127 +0,0 @@ -/**************************************************************************** -** -** 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 QSTATE_P_H -#define QSTATE_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 "qstate.h" -#include "private/qabstractstate_p.h" - -#include -#include -#include -#include - -QT_REQUIRE_CONFIG(statemachine); - -QT_BEGIN_NAMESPACE - -#ifndef QT_NO_PROPERTIES - -struct QPropertyAssignment -{ - QPropertyAssignment() - : object(nullptr), explicitlySet(true) {} - QPropertyAssignment(QObject *o, const QByteArray &n, - const QVariant &v, bool es = true) - : object(o), propertyName(n), value(v), explicitlySet(es) - {} - - bool objectDeleted() const { return !object; } - void write() const { Q_ASSERT(object != nullptr); object->setProperty(propertyName, value); } - bool hasTarget(QObject *o, const QByteArray &pn) const - { return object == o && propertyName == pn; } - - QPointer object; - QByteArray propertyName; - QVariant value; - bool explicitlySet; // false means the property is being restored to its old value -}; -Q_DECLARE_TYPEINFO(QPropertyAssignment, Q_MOVABLE_TYPE); - -#endif // QT_NO_PROPERTIES - -class QAbstractTransition; -class QHistoryState; - -class QState; -class Q_CORE_EXPORT QStatePrivate : public QAbstractStatePrivate -{ - Q_DECLARE_PUBLIC(QState) -public: - QStatePrivate(); - ~QStatePrivate(); - - static QStatePrivate *get(QState *q) { return q ? q->d_func() : nullptr; } - static const QStatePrivate *get(const QState *q) { return q? q->d_func() : nullptr; } - - QList childStates() const; - QList historyStates() const; - QList transitions() const; - - void emitFinished(); - void emitPropertiesAssigned(); - - QAbstractState *errorState; - QAbstractState *initialState; - QState::ChildMode childMode; - mutable bool childStatesListNeedsRefresh; - mutable bool transitionsListNeedsRefresh; - mutable QList childStatesList; - mutable QList transitionsList; - -#ifndef QT_NO_PROPERTIES - QList propertyAssignments; -#endif -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp deleted file mode 100644 index 873892552f..0000000000 --- a/src/corelib/statemachine/qstatemachine.cpp +++ /dev/null @@ -1,3208 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#include "qstatemachine.h" -#include "qstate.h" -#include "qstate_p.h" -#include "qstatemachine_p.h" -#include "qabstracttransition.h" -#include "qabstracttransition_p.h" -#include "qsignaltransition.h" -#include "qsignaltransition_p.h" -#include "qsignaleventgenerator_p.h" -#include "qabstractstate.h" -#include "qabstractstate_p.h" -#include "qfinalstate.h" -#include "qhistorystate.h" -#include "qhistorystate_p.h" -#include "private/qobject_p.h" -#include "private/qthread_p.h" - -#if QT_CONFIG(qeventtransition) -#include "qeventtransition.h" -#include "qeventtransition_p.h" -#endif - -#if QT_CONFIG(animation) -#include "qpropertyanimation.h" -#include "qanimationgroup.h" -#include -#endif - -#include -#include - -#include - -QT_BEGIN_NAMESPACE - -/*! - \class QStateMachine - \inmodule QtCore - \reentrant - - \brief The QStateMachine class provides a hierarchical finite state machine. - - \since 4.6 - \ingroup statemachine - - QStateMachine is based on the concepts and notation of - \l{http://www.wisdom.weizmann.ac.il/~dharel/SCANNED.PAPERS/Statecharts.pdf}{Statecharts}. - QStateMachine is part of \l{The State Machine Framework}. - - A state machine manages a set of states (classes that inherit from - QAbstractState) and transitions (descendants of - QAbstractTransition) between those states; these states and - transitions define a state graph. Once a state graph has been - built, the state machine can execute it. QStateMachine's - execution algorithm is based on the \l{http://www.w3.org/TR/scxml/}{State Chart XML (SCXML)} - algorithm. The framework's \l{The State Machine - Framework}{overview} gives several state graphs and the code to - build them. - - Use the addState() function to add a top-level state to the state machine. - States are removed with the removeState() function. Removing states while - the machine is running is discouraged. - - Before the machine can be started, the \l{initialState}{initial - state} must be set. The initial state is the state that the - machine enters when started. You can then start() the state - machine. The started() signal is emitted when the initial state is - entered. - - The machine is event driven and keeps its own event loop. Events - are posted to the machine through postEvent(). Note that this - means that it executes asynchronously, and that it will not - progress without a running event loop. You will normally not have - to post events to the machine directly as Qt's transitions, e.g., - QEventTransition and its subclasses, handle this. But for custom - transitions triggered by events, postEvent() is useful. - - The state machine processes events and takes transitions until a - top-level final state is entered; the state machine then emits the - finished() signal. You can also stop() the state machine - explicitly. The stopped() signal is emitted in this case. - - The following snippet shows a state machine that will finish when a button - is clicked: - - \snippet code/src_corelib_statemachine_qstatemachine.cpp simple state machine - - This code example uses QState, which inherits QAbstractState. The - QState class provides a state that you can use to set properties - and invoke methods on \l{QObject}s when the state is entered or - exited. It also contains convenience functions for adding - transitions, e.g., \l{QSignalTransition}s as in this example. See - the QState class description for further details. - - If an error is encountered, the machine will look for an - \l{errorState}{error state}, and if one is available, it will - enter this state. The types of errors possible are described by the - \l{QStateMachine::}{Error} enum. After the error state is entered, - the type of the error can be retrieved with error(). The execution - of the state graph will not stop when the error state is entered. If - no error state applies to the erroneous state, the machine will stop - executing and an error message will be printed to the console. - - \note Important: setting the \l{ChildMode} of a state machine to parallel (\l{ParallelStates}) - results in an invalid state machine. It can only be set to (or kept as) - \l{ExclusiveStates}. - - \sa QAbstractState, QAbstractTransition, QState, {The State Machine Framework} -*/ - -/*! - \property QStateMachine::errorString - - \brief the error string of this state machine -*/ - -/*! - \property QStateMachine::globalRestorePolicy - - \brief the restore policy for states of this state machine. - - The default value of this property is - QState::DontRestoreProperties. -*/ - -/*! - \property QStateMachine::running - \since 5.4 - - \brief the running state of this state machine - - \sa start(), stop(), started(), stopped(), runningChanged() -*/ - -#if QT_CONFIG(animation) -/*! - \property QStateMachine::animated - - \brief whether animations are enabled - - The default value of this property is \c true. - - \sa QAbstractTransition::addAnimation() -*/ -#endif - -// #define QSTATEMACHINE_DEBUG -// #define QSTATEMACHINE_RESTORE_PROPERTIES_DEBUG - -struct CalculationCache { - struct TransitionInfo { - QList effectiveTargetStates; - QSet exitSet; - QAbstractState *transitionDomain; - - bool effectiveTargetStatesIsKnown: 1; - bool exitSetIsKnown : 1; - bool transitionDomainIsKnown : 1; - - TransitionInfo() - : transitionDomain(nullptr) - , effectiveTargetStatesIsKnown(false) - , exitSetIsKnown(false) - , transitionDomainIsKnown(false) - {} - }; - - typedef QHash TransitionInfoCache; - TransitionInfoCache cache; - - bool effectiveTargetStates(QAbstractTransition *t, QList *targets) const - { - Q_ASSERT(targets); - - TransitionInfoCache::const_iterator cacheIt = cache.find(t); - if (cacheIt == cache.end() || !cacheIt->effectiveTargetStatesIsKnown) - return false; - - *targets = cacheIt->effectiveTargetStates; - return true; - } - - void insert(QAbstractTransition *t, const QList &targets) - { - TransitionInfoCache::iterator cacheIt = cache.find(t); - TransitionInfo &ti = cacheIt == cache.end() - ? *cache.insert(t, TransitionInfo()) - : *cacheIt; - - Q_ASSERT(!ti.effectiveTargetStatesIsKnown); - ti.effectiveTargetStates = targets; - ti.effectiveTargetStatesIsKnown = true; - } - - bool exitSet(QAbstractTransition *t, QSet *exits) const - { - Q_ASSERT(exits); - - TransitionInfoCache::const_iterator cacheIt = cache.find(t); - if (cacheIt == cache.end() || !cacheIt->exitSetIsKnown) - return false; - - *exits = cacheIt->exitSet; - return true; - } - - void insert(QAbstractTransition *t, const QSet &exits) - { - TransitionInfoCache::iterator cacheIt = cache.find(t); - TransitionInfo &ti = cacheIt == cache.end() - ? *cache.insert(t, TransitionInfo()) - : *cacheIt; - - Q_ASSERT(!ti.exitSetIsKnown); - ti.exitSet = exits; - ti.exitSetIsKnown = true; - } - - bool transitionDomain(QAbstractTransition *t, QAbstractState **domain) const - { - Q_ASSERT(domain); - - TransitionInfoCache::const_iterator cacheIt = cache.find(t); - if (cacheIt == cache.end() || !cacheIt->transitionDomainIsKnown) - return false; - - *domain = cacheIt->transitionDomain; - return true; - } - - void insert(QAbstractTransition *t, QAbstractState *domain) - { - TransitionInfoCache::iterator cacheIt = cache.find(t); - TransitionInfo &ti = cacheIt == cache.end() - ? *cache.insert(t, TransitionInfo()) - : *cacheIt; - - Q_ASSERT(!ti.transitionDomainIsKnown); - ti.transitionDomain = domain; - ti.transitionDomainIsKnown = true; - } -}; - -/* The function as described in http://www.w3.org/TR/2014/WD-scxml-20140529/ : - -function isDescendant(state1, state2) - -Returns 'true' if state1 is a descendant of state2 (a child, or a child of a child, or a child of a -child of a child, etc.) Otherwise returns 'false'. -*/ -static inline bool isDescendant(const QAbstractState *state1, const QAbstractState *state2) -{ - Q_ASSERT(state1 != nullptr); - - for (QAbstractState *it = state1->parentState(); it != nullptr; it = it->parentState()) { - if (it == state2) - return true; - } - - return false; -} - -static bool containsDecendantOf(const QSet &states, const QAbstractState *node) -{ - for (QAbstractState *s : states) - if (isDescendant(s, node)) - return true; - - return false; -} - -static int descendantDepth(const QAbstractState *state, const QAbstractState *ancestor) -{ - int depth = 0; - for (const QAbstractState *it = state; it != nullptr; it = it->parentState()) { - if (it == ancestor) - break; - ++depth; - } - return depth; -} - -/* The function as described in http://www.w3.org/TR/2014/WD-scxml-20140529/ : - -function getProperAncestors(state1, state2) - -If state2 is null, returns the set of all ancestors of state1 in ancestry order (state1's parent -followed by the parent's parent, etc. up to an including the element). If state2 is -non-null, returns in ancestry order the set of all ancestors of state1, up to but not including -state2. (A "proper ancestor" of a state is its parent, or the parent's parent, or the parent's -parent's parent, etc.))If state2 is state1's parent, or equal to state1, or a descendant of state1, -this returns the empty set. -*/ -static QList getProperAncestors(const QAbstractState *state, const QAbstractState *upperBound) -{ - Q_ASSERT(state != nullptr); - QList result; - result.reserve(16); - for (QState *it = state->parentState(); it && it != upperBound; it = it->parentState()) { - result.append(it); - } - return result; -} - -/* The function as described in http://www.w3.org/TR/2014/WD-scxml-20140529/ : - -function getEffectiveTargetStates(transition) - -Returns the states that will be the target when 'transition' is taken, dereferencing any history states. - -function getEffectiveTargetStates(transition) - targets = new OrderedSet() - for s in transition.target - if isHistoryState(s): - if historyValue[s.id]: - targets.union(historyValue[s.id]) - else: - targets.union(getEffectiveTargetStates(s.transition)) - else: - targets.add(s) - return targets -*/ -static QList getEffectiveTargetStates(QAbstractTransition *transition, CalculationCache *cache) -{ - Q_ASSERT(cache); - - QList targetsList; - if (cache->effectiveTargetStates(transition, &targetsList)) - return targetsList; - - QSet targets; - const auto targetStates = transition->targetStates(); - for (QAbstractState *s : targetStates) { - if (QHistoryState *historyState = QStateMachinePrivate::toHistoryState(s)) { - QList historyConfiguration = QHistoryStatePrivate::get(historyState)->configuration; - if (!historyConfiguration.isEmpty()) { - // There is a saved history, so apply that. - targets.unite(QSet(historyConfiguration.constBegin(), historyConfiguration.constEnd())); - } else if (QAbstractTransition *defaultTransition = historyState->defaultTransition()) { - // No saved history, take all default transition targets. - const auto &targetStates = defaultTransition->targetStates(); - targets.unite(QSet(targetStates.constBegin(), targetStates.constEnd())); - } else { - // Woops, we found a history state without a default state. That's not valid! - QStateMachinePrivate *m = QStateMachinePrivate::get(historyState->machine()); - m->setError(QStateMachine::NoDefaultStateInHistoryStateError, historyState); - } - } else { - targets.insert(s); - } - } - - targetsList = targets.values(); - cache->insert(transition, targetsList); - return targetsList; -} - -QStateMachinePrivate::QStateMachinePrivate() -{ - isMachine = true; - - state = NotRunning; - processing = false; - processingScheduled = false; - stop = false; - stopProcessingReason = EventQueueEmpty; - error = QStateMachine::NoError; - globalRestorePolicy = QState::DontRestoreProperties; - signalEventGenerator = nullptr; -#if QT_CONFIG(animation) - animated = true; -#endif -} - -QStateMachinePrivate::~QStateMachinePrivate() -{ - qDeleteAll(internalEventQueue); - qDeleteAll(externalEventQueue); - - for (QHash::const_iterator it = delayedEvents.cbegin(), eit = delayedEvents.cend(); it != eit; ++it) { - delete it.value().event; - } -} - -QState *QStateMachinePrivate::rootState() const -{ - return const_cast(q_func()); -} - -static QEvent *cloneEvent(QEvent *e) -{ - switch (e->type()) { - case QEvent::None: - return new QEvent(*e); - case QEvent::Timer: - return new QTimerEvent(*static_cast(e)); - default: - Q_ASSERT_X(false, "cloneEvent()", "not implemented"); - break; - } - return nullptr; -} - -const QStateMachinePrivate::Handler qt_kernel_statemachine_handler = { - cloneEvent -}; - -const QStateMachinePrivate::Handler *QStateMachinePrivate::handler = &qt_kernel_statemachine_handler; - -Q_CORE_EXPORT const QStateMachinePrivate::Handler *qcoreStateMachineHandler() -{ - return &qt_kernel_statemachine_handler; -} - -static int indexOfDescendant(QState *s, QAbstractState *desc) -{ - QList childStates = QStatePrivate::get(s)->childStates(); - for (int i = 0; i < childStates.size(); ++i) { - QAbstractState *c = childStates.at(i); - if ((c == desc) || isDescendant(desc, c)) { - return i; - } - } - return -1; -} - -bool QStateMachinePrivate::transitionStateEntryLessThan(QAbstractTransition *t1, QAbstractTransition *t2) -{ - QState *s1 = t1->sourceState(), *s2 = t2->sourceState(); - if (s1 == s2) { - QList transitions = QStatePrivate::get(s1)->transitions(); - return transitions.indexOf(t1) < transitions.indexOf(t2); - } else if (isDescendant(s1, s2)) { - return true; - } else if (isDescendant(s2, s1)) { - return false; - } else { - Q_ASSERT(s1->machine() != nullptr); - QStateMachinePrivate *mach = QStateMachinePrivate::get(s1->machine()); - QState *lca = mach->findLCA(QList() << s1 << s2); - Q_ASSERT(lca != nullptr); - int s1Depth = descendantDepth(s1, lca); - int s2Depth = descendantDepth(s2, lca); - if (s1Depth == s2Depth) - return (indexOfDescendant(lca, s1) < indexOfDescendant(lca, s2)); - else - return s1Depth > s2Depth; - } -} - -bool QStateMachinePrivate::stateEntryLessThan(QAbstractState *s1, QAbstractState *s2) -{ - if (s1->parent() == s2->parent()) { - return s1->parent()->children().indexOf(s1) - < s2->parent()->children().indexOf(s2); - } else if (isDescendant(s1, s2)) { - return false; - } else if (isDescendant(s2, s1)) { - return true; - } else { - Q_ASSERT(s1->machine() != nullptr); - QStateMachinePrivate *mach = QStateMachinePrivate::get(s1->machine()); - QState *lca = mach->findLCA(QList() << s1 << s2); - Q_ASSERT(lca != nullptr); - return (indexOfDescendant(lca, s1) < indexOfDescendant(lca, s2)); - } -} - -bool QStateMachinePrivate::stateExitLessThan(QAbstractState *s1, QAbstractState *s2) -{ - if (s1->parent() == s2->parent()) { - return s2->parent()->children().indexOf(s2) - < s1->parent()->children().indexOf(s1); - } else if (isDescendant(s1, s2)) { - return true; - } else if (isDescendant(s2, s1)) { - return false; - } else { - Q_ASSERT(s1->machine() != nullptr); - QStateMachinePrivate *mach = QStateMachinePrivate::get(s1->machine()); - QState *lca = mach->findLCA(QList() << s1 << s2); - Q_ASSERT(lca != nullptr); - return (indexOfDescendant(lca, s2) < indexOfDescendant(lca, s1)); - } -} - -QState *QStateMachinePrivate::findLCA(const QList &states, bool onlyCompound) -{ - if (states.isEmpty()) - return nullptr; - QList ancestors = getProperAncestors(states.at(0), rootState()->parentState()); - for (int i = 0; i < ancestors.size(); ++i) { - QState *anc = ancestors.at(i); - if (onlyCompound && !isCompound(anc)) - continue; - - bool ok = true; - for (int j = states.size() - 1; (j > 0) && ok; --j) { - const QAbstractState *s = states.at(j); - if (!isDescendant(s, anc)) - ok = false; - } - if (ok) - return anc; - } - - // Oops, this should never happen! The state machine itself is a common ancestor of all states, - // no matter what. But, for the onlyCompound case: we probably have a state machine whose - // childMode is set to parallel, which is illegal. However, we're stuck with it (and with - // exposing this invalid/dangerous API to users), so recover in the least horrible way. - setError(QStateMachine::StateMachineChildModeSetToParallelError, q_func()); - return q_func(); // make the statemachine the LCA/LCCA (which it should have been anyway) -} - -QState *QStateMachinePrivate::findLCCA(const QList &states) -{ - return findLCA(states, true); -} - -QList QStateMachinePrivate::selectTransitions(QEvent *event, CalculationCache *cache) -{ - Q_ASSERT(cache); - Q_Q(const QStateMachine); - - QVarLengthArray configuration_sorted; - for (QAbstractState *s : qAsConst(configuration)) { - if (isAtomic(s)) - configuration_sorted.append(s); - } - std::sort(configuration_sorted.begin(), configuration_sorted.end(), stateEntryLessThan); - - QList enabledTransitions; - const_cast(q)->beginSelectTransitions(event); - for (QAbstractState *state : qAsConst(configuration_sorted)) { - QList lst = getProperAncestors(state, nullptr); - if (QState *grp = toStandardState(state)) - lst.prepend(grp); - bool found = false; - for (int j = 0; (j < lst.size()) && !found; ++j) { - QState *s = lst.at(j); - QList transitions = QStatePrivate::get(s)->transitions(); - for (int k = 0; k < transitions.size(); ++k) { - QAbstractTransition *t = transitions.at(k); - if (QAbstractTransitionPrivate::get(t)->callEventTest(event)) { -#ifdef QSTATEMACHINE_DEBUG - qDebug() << q << ": selecting transition" << t; -#endif - enabledTransitions.append(t); - found = true; - break; - } - } - } - } - - if (!enabledTransitions.isEmpty()) { - removeConflictingTransitions(enabledTransitions, cache); -#ifdef QSTATEMACHINE_DEBUG - qDebug() << q << ": enabled transitions after removing conflicts:" << enabledTransitions; -#endif - } - const_cast(q)->endSelectTransitions(event); - return enabledTransitions; -} - -/* The function as described in http://www.w3.org/TR/2014/WD-scxml-20140529/ : - -function removeConflictingTransitions(enabledTransitions): - filteredTransitions = new OrderedSet() - // toList sorts the transitions in the order of the states that selected them - for t1 in enabledTransitions.toList(): - t1Preempted = false; - transitionsToRemove = new OrderedSet() - for t2 in filteredTransitions.toList(): - if computeExitSet([t1]).hasIntersection(computeExitSet([t2])): - if isDescendant(t1.source, t2.source): - transitionsToRemove.add(t2) - else: - t1Preempted = true - break - if not t1Preempted: - for t3 in transitionsToRemove.toList(): - filteredTransitions.delete(t3) - filteredTransitions.add(t1) - - return filteredTransitions - -Note: the implementation below does not build the transitionsToRemove, but removes them in-place. -*/ -void QStateMachinePrivate::removeConflictingTransitions(QList &enabledTransitions, CalculationCache *cache) -{ - Q_ASSERT(cache); - - if (enabledTransitions.size() < 2) - return; // There is no transition to conflict with. - - QList filteredTransitions; - filteredTransitions.reserve(enabledTransitions.size()); - std::sort(enabledTransitions.begin(), enabledTransitions.end(), transitionStateEntryLessThan); - - for (QAbstractTransition *t1 : qAsConst(enabledTransitions)) { - bool t1Preempted = false; - const QSet exitSetT1 = computeExitSet_Unordered(t1, cache); - QList::iterator t2It = filteredTransitions.begin(); - while (t2It != filteredTransitions.end()) { - QAbstractTransition *t2 = *t2It; - if (t1 == t2) { - // Special case: someone added the same transition object to a state twice. In this - // case, t2 (which is already in the list) "preempts" t1. - t1Preempted = true; - break; - } - - QSet exitSetT2 = computeExitSet_Unordered(t2, cache); - if (!exitSetT1.intersects(exitSetT2)) { - // No conflict, no cry. Next patient please. - ++t2It; - } else { - // Houston, we have a conflict. Check which transition can be removed. - if (isDescendant(t1->sourceState(), t2->sourceState())) { - // t1 preempts t2, so we can remove t2 - t2It = filteredTransitions.erase(t2It); - } else { - // t2 preempts t1, so there's no use in looking further and we don't need to add - // t1 to the list. - t1Preempted = true; - break; - } - } - } - if (!t1Preempted) - filteredTransitions.append(t1); - } - - enabledTransitions = filteredTransitions; -} - -void QStateMachinePrivate::microstep(QEvent *event, const QList &enabledTransitions, - CalculationCache *cache) -{ - Q_ASSERT(cache); - -#ifdef QSTATEMACHINE_DEBUG - qDebug() << q_func() << ": begin microstep( enabledTransitions:" << enabledTransitions << ')'; - qDebug() << q_func() << ": configuration before exiting states:" << configuration; -#endif - QList exitedStates = computeExitSet(enabledTransitions, cache); - QHash pendingRestorables = computePendingRestorables(exitedStates); - - QSet statesForDefaultEntry; - QList enteredStates = computeEntrySet(enabledTransitions, statesForDefaultEntry, cache); - -#ifdef QSTATEMACHINE_DEBUG - qDebug() << q_func() << ": computed exit set:" << exitedStates; - qDebug() << q_func() << ": computed entry set:" << enteredStates; -#endif - - QHash> assignmentsForEnteredStates = - computePropertyAssignments(enteredStates, pendingRestorables); - if (!pendingRestorables.isEmpty()) { - // Add "implicit" assignments for restored properties to the first - // (outermost) entered state - Q_ASSERT(!enteredStates.isEmpty()); - QAbstractState *s = enteredStates.constFirst(); - assignmentsForEnteredStates[s] << restorablesToPropertyList(pendingRestorables); - } - - exitStates(event, exitedStates, assignmentsForEnteredStates); -#ifdef QSTATEMACHINE_DEBUG - qDebug() << q_func() << ": configuration after exiting states:" << configuration; -#endif - - executeTransitionContent(event, enabledTransitions); - -#if QT_CONFIG(animation) - QList selectedAnimations = selectAnimations(enabledTransitions); -#endif - - enterStates(event, exitedStates, enteredStates, statesForDefaultEntry, assignmentsForEnteredStates -#if QT_CONFIG(animation) - , selectedAnimations -#endif - ); -#ifdef QSTATEMACHINE_DEBUG - qDebug() << q_func() << ": configuration after entering states:" << configuration; - qDebug() << q_func() << ": end microstep"; -#endif -} - -/* The function as described in http://www.w3.org/TR/2014/WD-scxml-20140529/ : - -procedure computeExitSet(enabledTransitions) - -For each transition t in enabledTransitions, if t is targetless then do nothing, else compute the -transition's domain. (This will be the source state in the case of internal transitions) or the -least common compound ancestor state of the source state and target states of t (in the case of -external transitions. Add to the statesToExit set all states in the configuration that are -descendants of the domain. - -function computeExitSet(transitions) - statesToExit = new OrderedSet - for t in transitions: - if (t.target): - domain = getTransitionDomain(t) - for s in configuration: - if isDescendant(s,domain): - statesToExit.add(s) - return statesToExit -*/ -QList QStateMachinePrivate::computeExitSet(const QList &enabledTransitions, - CalculationCache *cache) -{ - Q_ASSERT(cache); - - QList statesToExit_sorted = computeExitSet_Unordered(enabledTransitions, cache).values(); - std::sort(statesToExit_sorted.begin(), statesToExit_sorted.end(), stateExitLessThan); - return statesToExit_sorted; -} - -QSet QStateMachinePrivate::computeExitSet_Unordered(const QList &enabledTransitions, - CalculationCache *cache) -{ - Q_ASSERT(cache); - - QSet statesToExit; - for (QAbstractTransition *t : enabledTransitions) - statesToExit.unite(computeExitSet_Unordered(t, cache)); - return statesToExit; -} - -QSet QStateMachinePrivate::computeExitSet_Unordered(QAbstractTransition *t, - CalculationCache *cache) -{ - Q_ASSERT(cache); - - QSet statesToExit; - if (cache->exitSet(t, &statesToExit)) - return statesToExit; - - QList effectiveTargetStates = getEffectiveTargetStates(t, cache); - QAbstractState *domain = getTransitionDomain(t, effectiveTargetStates, cache); - if (domain == nullptr && !t->targetStates().isEmpty()) { - // So we didn't find the least common ancestor for the source and target states of the - // transition. If there were not target states, that would be fine: then the transition - // will fire any events or signals, but not exit the state. - // - // However, there are target states, so it's either a node without a parent (or parent's - // parent, etc), or the state belongs to a different state machine. Either way, this - // makes the state machine invalid. - if (error == QStateMachine::NoError) - setError(QStateMachine::NoCommonAncestorForTransitionError, t->sourceState()); - QList lst = pendingErrorStates.values(); - lst.prepend(t->sourceState()); - - domain = findLCCA(lst); - Q_ASSERT(domain != nullptr); - } - - for (QAbstractState* s : qAsConst(configuration)) { - if (isDescendant(s, domain)) - statesToExit.insert(s); - } - - cache->insert(t, statesToExit); - return statesToExit; -} - -void QStateMachinePrivate::exitStates(QEvent *event, const QList &statesToExit_sorted, - const QHash> &assignmentsForEnteredStates) -{ - for (int i = 0; i < statesToExit_sorted.size(); ++i) { - QAbstractState *s = statesToExit_sorted.at(i); - if (QState *grp = toStandardState(s)) { - QList hlst = QStatePrivate::get(grp)->historyStates(); - for (int j = 0; j < hlst.size(); ++j) { - QHistoryState *h = hlst.at(j); - QHistoryStatePrivate::get(h)->configuration.clear(); - QSet::const_iterator it; - for (it = configuration.constBegin(); it != configuration.constEnd(); ++it) { - QAbstractState *s0 = *it; - if (QHistoryStatePrivate::get(h)->historyType == QHistoryState::DeepHistory) { - if (isAtomic(s0) && isDescendant(s0, s)) - QHistoryStatePrivate::get(h)->configuration.append(s0); - } else if (s0->parentState() == s) { - QHistoryStatePrivate::get(h)->configuration.append(s0); - } - } -#ifdef QSTATEMACHINE_DEBUG - qDebug() << q_func() << ": recorded" << ((QHistoryStatePrivate::get(h)->historyType == QHistoryState::DeepHistory) ? "deep" : "shallow") - << "history for" << s << "in" << h << ':' << QHistoryStatePrivate::get(h)->configuration; -#endif - } - } - } - for (int i = 0; i < statesToExit_sorted.size(); ++i) { - QAbstractState *s = statesToExit_sorted.at(i); -#ifdef QSTATEMACHINE_DEBUG - qDebug() << q_func() << ": exiting" << s; -#endif - QAbstractStatePrivate::get(s)->callOnExit(event); - -#if QT_CONFIG(animation) - terminateActiveAnimations(s, assignmentsForEnteredStates); -#else - Q_UNUSED(assignmentsForEnteredStates); -#endif - - configuration.remove(s); - QAbstractStatePrivate::get(s)->emitExited(); - } -} - -void QStateMachinePrivate::executeTransitionContent(QEvent *event, const QList &enabledTransitions) -{ - for (int i = 0; i < enabledTransitions.size(); ++i) { - QAbstractTransition *t = enabledTransitions.at(i); -#ifdef QSTATEMACHINE_DEBUG - qDebug() << q_func() << ": triggering" << t; -#endif - QAbstractTransitionPrivate::get(t)->callOnTransition(event); - QAbstractTransitionPrivate::get(t)->emitTriggered(); - } -} - -QList QStateMachinePrivate::computeEntrySet(const QList &enabledTransitions, - QSet &statesForDefaultEntry, - CalculationCache *cache) -{ - Q_ASSERT(cache); - - QSet statesToEnter; - if (pendingErrorStates.isEmpty()) { - for (QAbstractTransition *t : enabledTransitions) { - const auto targetStates = t->targetStates(); - for (QAbstractState *s : targetStates) - addDescendantStatesToEnter(s, statesToEnter, statesForDefaultEntry); - - const QList effectiveTargetStates = getEffectiveTargetStates(t, cache); - QAbstractState *ancestor = getTransitionDomain(t, effectiveTargetStates, cache); - for (QAbstractState *s : effectiveTargetStates) - addAncestorStatesToEnter(s, ancestor, statesToEnter, statesForDefaultEntry); - } - } - - // Did an error occur while selecting transitions? Then we enter the error state. - if (!pendingErrorStates.isEmpty()) { - statesToEnter.clear(); - statesToEnter = pendingErrorStates; - statesForDefaultEntry = pendingErrorStatesForDefaultEntry; - pendingErrorStates.clear(); - pendingErrorStatesForDefaultEntry.clear(); - } - - QList statesToEnter_sorted = statesToEnter.values(); - std::sort(statesToEnter_sorted.begin(), statesToEnter_sorted.end(), stateEntryLessThan); - return statesToEnter_sorted; -} - -/* The algorithm as described in http://www.w3.org/TR/2014/WD-scxml-20140529/ : - -function getTransitionDomain(transition) - -Return the compound state such that 1) all states that are exited or entered as a result of taking -'transition' are descendants of it 2) no descendant of it has this property. - -function getTransitionDomain(t) - tstates = getEffectiveTargetStates(t) - if not tstates: - return null - elif t.type == "internal" and isCompoundState(t.source) and tstates.every(lambda s: isDescendant(s,t.source)): - return t.source - else: - return findLCCA([t.source].append(tstates)) -*/ -QAbstractState *QStateMachinePrivate::getTransitionDomain(QAbstractTransition *t, - const QList &effectiveTargetStates, - CalculationCache *cache) -{ - Q_ASSERT(cache); - - if (effectiveTargetStates.isEmpty()) - return nullptr; - - QAbstractState *domain = nullptr; - if (cache->transitionDomain(t, &domain)) - return domain; - - if (t->transitionType() == QAbstractTransition::InternalTransition) { - if (QState *tSource = t->sourceState()) { - if (isCompound(tSource)) { - bool allDescendants = true; - for (QAbstractState *s : effectiveTargetStates) { - if (!isDescendant(s, tSource)) { - allDescendants = false; - break; - } - } - - if (allDescendants) - return tSource; - } - } - } - - QList states(effectiveTargetStates); - if (QAbstractState *src = t->sourceState()) - states.prepend(src); - domain = findLCCA(states); - cache->insert(t, domain); - return domain; -} - -void QStateMachinePrivate::enterStates(QEvent *event, const QList &exitedStates_sorted, - const QList &statesToEnter_sorted, - const QSet &statesForDefaultEntry, - QHash> &propertyAssignmentsForState -#if QT_CONFIG(animation) - , const QList &selectedAnimations -#endif - ) -{ -#ifdef QSTATEMACHINE_DEBUG - Q_Q(QStateMachine); -#endif - for (int i = 0; i < statesToEnter_sorted.size(); ++i) { - QAbstractState *s = statesToEnter_sorted.at(i); -#ifdef QSTATEMACHINE_DEBUG - qDebug() << q << ": entering" << s; -#endif - configuration.insert(s); - registerTransitions(s); - -#if QT_CONFIG(animation) - initializeAnimations(s, selectedAnimations, exitedStates_sorted, propertyAssignmentsForState); -#endif - - // Immediately set the properties that are not animated. - { - const auto assignments = propertyAssignmentsForState.value(s); - for (const auto &assn : assignments) { - if (globalRestorePolicy == QState::RestoreProperties) { - if (assn.explicitlySet) { - if (!hasRestorable(s, assn.object, assn.propertyName)) { - QVariant value = savedValueForRestorable(exitedStates_sorted, assn.object, assn.propertyName); - unregisterRestorables(exitedStates_sorted, assn.object, assn.propertyName); - registerRestorable(s, assn.object, assn.propertyName, value); - } - } else { - // The property is being restored, hence no need to - // save the current value. Discard any saved values in - // exited states, since those are now stale. - unregisterRestorables(exitedStates_sorted, assn.object, assn.propertyName); - } - } - assn.write(); - } - } - - QAbstractStatePrivate::get(s)->callOnEntry(event); - QAbstractStatePrivate::get(s)->emitEntered(); - - // FIXME: - // See the "initial transitions" comment in addDescendantStatesToEnter first, then implement: -// if (statesForDefaultEntry.contains(s)) { -// // ### executeContent(s.initial.transition.children()) -// } - Q_UNUSED(statesForDefaultEntry); - - if (QHistoryState *h = toHistoryState(s)) - QAbstractTransitionPrivate::get(h->defaultTransition())->callOnTransition(event); - - // Emit propertiesAssigned signal if the state has no animated properties. - { - QState *ss = toStandardState(s); - if (ss - #if QT_CONFIG(animation) - && !animationsForState.contains(s) - #endif - ) - QStatePrivate::get(ss)->emitPropertiesAssigned(); - } - - if (isFinal(s)) { - QState *parent = s->parentState(); - if (parent) { - if (parent != rootState()) { - QFinalState *finalState = qobject_cast(s); - Q_ASSERT(finalState); - emitStateFinished(parent, finalState); - } - QState *grandparent = parent->parentState(); - if (grandparent && isParallel(grandparent)) { - bool allChildStatesFinal = true; - QList childStates = QStatePrivate::get(grandparent)->childStates(); - for (int j = 0; j < childStates.size(); ++j) { - QAbstractState *cs = childStates.at(j); - if (!isInFinalState(cs)) { - allChildStatesFinal = false; - break; - } - } - if (allChildStatesFinal && (grandparent != rootState())) { - QFinalState *finalState = qobject_cast(s); - Q_ASSERT(finalState); - emitStateFinished(grandparent, finalState); - } - } - } - } - } - { - QSet::const_iterator it; - for (it = configuration.constBegin(); it != configuration.constEnd(); ++it) { - if (isFinal(*it)) { - QState *parent = (*it)->parentState(); - if (((parent == rootState()) - && (rootState()->childMode() == QState::ExclusiveStates)) - || ((parent->parentState() == rootState()) - && (rootState()->childMode() == QState::ParallelStates) - && isInFinalState(rootState()))) { - processing = false; - stopProcessingReason = Finished; - break; - } - } - } - } -// qDebug() << "configuration:" << configuration.toList(); -} - -/* The algorithm as described in http://www.w3.org/TR/2014/WD-scxml-20140529/ has a bug. See - * QTBUG-44963 for details. The algorithm here is as described in - * http://www.w3.org/Voice/2013/scxml-irp/SCXML.htm as of Friday March 13, 2015. - -procedure addDescendantStatesToEnter(state,statesToEnter,statesForDefaultEntry, defaultHistoryContent): - if isHistoryState(state): - if historyValue[state.id]: - for s in historyValue[state.id]: - addDescendantStatesToEnter(s,statesToEnter,statesForDefaultEntry, defaultHistoryContent) - for s in historyValue[state.id]: - addAncestorStatesToEnter(s, state.parent, statesToEnter, statesForDefaultEntry, defaultHistoryContent) - else: - defaultHistoryContent[state.parent.id] = state.transition.content - for s in state.transition.target: - addDescendantStatesToEnter(s,statesToEnter,statesForDefaultEntry, defaultHistoryContent) - for s in state.transition.target: - addAncestorStatesToEnter(s, state.parent, statesToEnter, statesForDefaultEntry, defaultHistoryContent) - else: - statesToEnter.add(state) - if isCompoundState(state): - statesForDefaultEntry.add(state) - for s in state.initial.transition.target: - addDescendantStatesToEnter(s,statesToEnter,statesForDefaultEntry, defaultHistoryContent) - for s in state.initial.transition.target: - addAncestorStatesToEnter(s, state, statesToEnter, statesForDefaultEntry, defaultHistoryContent) - else: - if isParallelState(state): - for child in getChildStates(state): - if not statesToEnter.some(lambda s: isDescendant(s,child)): - addDescendantStatesToEnter(child,statesToEnter,statesForDefaultEntry, defaultHistoryContent) -*/ -void QStateMachinePrivate::addDescendantStatesToEnter(QAbstractState *state, - QSet &statesToEnter, - QSet &statesForDefaultEntry) -{ - if (QHistoryState *h = toHistoryState(state)) { - const QList historyConfiguration = QHistoryStatePrivate::get(h)->configuration; - if (!historyConfiguration.isEmpty()) { - for (QAbstractState *s : historyConfiguration) - addDescendantStatesToEnter(s, statesToEnter, statesForDefaultEntry); - for (QAbstractState *s : historyConfiguration) - addAncestorStatesToEnter(s, state->parentState(), statesToEnter, statesForDefaultEntry); - -#ifdef QSTATEMACHINE_DEBUG - qDebug() << q_func() << ": restoring" - << ((QHistoryStatePrivate::get(h)->historyType == QHistoryState::DeepHistory) ? "deep" : "shallow") - << "history from" << state << ':' << historyConfiguration; -#endif - } else { - QList defaultHistoryContent; - if (QAbstractTransition *t = QHistoryStatePrivate::get(h)->defaultTransition) - defaultHistoryContent = t->targetStates(); - - if (defaultHistoryContent.isEmpty()) { - setError(QStateMachine::NoDefaultStateInHistoryStateError, h); - } else { - for (QAbstractState *s : qAsConst(defaultHistoryContent)) - addDescendantStatesToEnter(s, statesToEnter, statesForDefaultEntry); - for (QAbstractState *s : qAsConst(defaultHistoryContent)) - addAncestorStatesToEnter(s, state->parentState(), statesToEnter, statesForDefaultEntry); -#ifdef QSTATEMACHINE_DEBUG - qDebug() << q_func() << ": initial history targets for" << state << ':' << defaultHistoryContent; -#endif - } - } - } else { - if (state == rootState()) { - // Error has already been set by exitStates(). - Q_ASSERT(error != QStateMachine::NoError); - return; - } - statesToEnter.insert(state); - if (isCompound(state)) { - statesForDefaultEntry.insert(state); - if (QAbstractState *initial = toStandardState(state)->initialState()) { - Q_ASSERT(initial->machine() == q_func()); - - // FIXME: - // Qt does not support initial transitions (which is a problem for parallel states). - // The way it simulates this for other states, is by having a single initial state. - // See also the FIXME in enterStates. - statesForDefaultEntry.insert(initial); - - addDescendantStatesToEnter(initial, statesToEnter, statesForDefaultEntry); - addAncestorStatesToEnter(initial, state, statesToEnter, statesForDefaultEntry); - } else { - setError(QStateMachine::NoInitialStateError, state); - return; - } - } else if (isParallel(state)) { - QState *grp = toStandardState(state); - const auto childStates = QStatePrivate::get(grp)->childStates(); - for (QAbstractState *child : childStates) { - if (!containsDecendantOf(statesToEnter, child)) - addDescendantStatesToEnter(child, statesToEnter, statesForDefaultEntry); - } - } - } -} - - -/* The algorithm as described in http://www.w3.org/TR/2014/WD-scxml-20140529/ : - -procedure addAncestorStatesToEnter(state, ancestor, statesToEnter, statesForDefaultEntry, defaultHistoryContent) - for anc in getProperAncestors(state,ancestor): - statesToEnter.add(anc) - if isParallelState(anc): - for child in getChildStates(anc): - if not statesToEnter.some(lambda s: isDescendant(s,child)): - addDescendantStatesToEnter(child,statesToEnter,statesForDefaultEntry, defaultHistoryContent) -*/ -void QStateMachinePrivate::addAncestorStatesToEnter(QAbstractState *s, QAbstractState *ancestor, - QSet &statesToEnter, - QSet &statesForDefaultEntry) -{ - const auto properAncestors = getProperAncestors(s, ancestor); - for (QState *anc : properAncestors) { - if (!anc->parentState()) - continue; - statesToEnter.insert(anc); - if (isParallel(anc)) { - const auto childStates = QStatePrivate::get(anc)->childStates(); - for (QAbstractState *child : childStates) { - if (!containsDecendantOf(statesToEnter, child)) - addDescendantStatesToEnter(child, statesToEnter, statesForDefaultEntry); - } - } - } -} - -bool QStateMachinePrivate::isFinal(const QAbstractState *s) -{ - return s && (QAbstractStatePrivate::get(s)->stateType == QAbstractStatePrivate::FinalState); -} - -bool QStateMachinePrivate::isParallel(const QAbstractState *s) -{ - const QState *ss = toStandardState(s); - return ss && (QStatePrivate::get(ss)->childMode == QState::ParallelStates); -} - -bool QStateMachinePrivate::isCompound(const QAbstractState *s) const -{ - const QState *group = toStandardState(s); - if (!group) - return false; - bool isMachine = QStatePrivate::get(group)->isMachine; - // Don't treat the machine as compound if it's a sub-state of this machine - if (isMachine && (group != rootState())) - return false; - return (!isParallel(group) && !QStatePrivate::get(group)->childStates().isEmpty()); -} - -bool QStateMachinePrivate::isAtomic(const QAbstractState *s) const -{ - const QState *ss = toStandardState(s); - return (ss && QStatePrivate::get(ss)->childStates().isEmpty()) - || isFinal(s) - // Treat the machine as atomic if it's a sub-state of this machine - || (ss && QStatePrivate::get(ss)->isMachine && (ss != rootState())); -} - -QState *QStateMachinePrivate::toStandardState(QAbstractState *state) -{ - if (state && (QAbstractStatePrivate::get(state)->stateType == QAbstractStatePrivate::StandardState)) - return static_cast(state); - return nullptr; -} - -const QState *QStateMachinePrivate::toStandardState(const QAbstractState *state) -{ - if (state && (QAbstractStatePrivate::get(state)->stateType == QAbstractStatePrivate::StandardState)) - return static_cast(state); - return nullptr; -} - -QFinalState *QStateMachinePrivate::toFinalState(QAbstractState *state) -{ - if (state && (QAbstractStatePrivate::get(state)->stateType == QAbstractStatePrivate::FinalState)) - return static_cast(state); - return nullptr; -} - -QHistoryState *QStateMachinePrivate::toHistoryState(QAbstractState *state) -{ - if (state && (QAbstractStatePrivate::get(state)->stateType == QAbstractStatePrivate::HistoryState)) - return static_cast(state); - return nullptr; -} - -bool QStateMachinePrivate::isInFinalState(QAbstractState* s) const -{ - if (isCompound(s)) { - QState *grp = toStandardState(s); - QList lst = QStatePrivate::get(grp)->childStates(); - for (int i = 0; i < lst.size(); ++i) { - QAbstractState *cs = lst.at(i); - if (isFinal(cs) && configuration.contains(cs)) - return true; - } - return false; - } else if (isParallel(s)) { - QState *grp = toStandardState(s); - QList lst = QStatePrivate::get(grp)->childStates(); - for (int i = 0; i < lst.size(); ++i) { - QAbstractState *cs = lst.at(i); - if (!isInFinalState(cs)) - return false; - } - return true; - } - else - return false; -} - -#ifndef QT_NO_PROPERTIES - -/*! - \internal - Returns \c true if the given state has saved the value of the given property, - otherwise returns \c false. -*/ -bool QStateMachinePrivate::hasRestorable(QAbstractState *state, QObject *object, - const QByteArray &propertyName) const -{ - RestorableId id(object, propertyName); - return registeredRestorablesForState.value(state).contains(id); -} - -/*! - \internal - Returns the value to save for the property identified by \a id. - If an exited state (member of \a exitedStates_sorted) has saved a value for - the property, the saved value from the last (outermost) state that will be - exited is returned (in practice carrying the saved value on to the next - state). Otherwise, the current value of the property is returned. -*/ -QVariant QStateMachinePrivate::savedValueForRestorable(const QList &exitedStates_sorted, - QObject *object, const QByteArray &propertyName) const -{ -#ifdef QSTATEMACHINE_RESTORE_PROPERTIES_DEBUG - qDebug() << q_func() << ": savedValueForRestorable(" << exitedStates_sorted << object << propertyName << ')'; -#endif - for (int i = exitedStates_sorted.size() - 1; i >= 0; --i) { - QAbstractState *s = exitedStates_sorted.at(i); - QHash restorables = registeredRestorablesForState.value(s); - QHash::const_iterator it = restorables.constFind(RestorableId(object, propertyName)); - if (it != restorables.constEnd()) { -#ifdef QSTATEMACHINE_RESTORE_PROPERTIES_DEBUG - qDebug() << q_func() << ": using" << it.value() << "from" << s; -#endif - return it.value(); - } - } -#ifdef QSTATEMACHINE_RESTORE_PROPERTIES_DEBUG - qDebug() << q_func() << ": falling back to current value"; -#endif - return object->property(propertyName); -} - -void QStateMachinePrivate::registerRestorable(QAbstractState *state, QObject *object, const QByteArray &propertyName, - const QVariant &value) -{ -#ifdef QSTATEMACHINE_RESTORE_PROPERTIES_DEBUG - qDebug() << q_func() << ": registerRestorable(" << state << object << propertyName << value << ')'; -#endif - RestorableId id(object, propertyName); - QHash &restorables = registeredRestorablesForState[state]; - if (!restorables.contains(id)) - restorables.insert(id, value); -#ifdef QSTATEMACHINE_RESTORE_PROPERTIES_DEBUG - else - qDebug() << q_func() << ": (already registered)"; -#endif -} - -void QStateMachinePrivate::unregisterRestorables(const QList &states, QObject *object, - const QByteArray &propertyName) -{ -#ifdef QSTATEMACHINE_RESTORE_PROPERTIES_DEBUG - qDebug() << q_func() << ": unregisterRestorables(" << states << object << propertyName << ')'; -#endif - RestorableId id(object, propertyName); - for (int i = 0; i < states.size(); ++i) { - QAbstractState *s = states.at(i); - QHash >::iterator it; - it = registeredRestorablesForState.find(s); - if (it == registeredRestorablesForState.end()) - continue; - QHash &restorables = it.value(); - const auto it2 = restorables.constFind(id); - if (it2 == restorables.cend()) - continue; -#ifdef QSTATEMACHINE_RESTORE_PROPERTIES_DEBUG - qDebug() << q_func() << ": unregistered for" << s; -#endif - restorables.erase(it2); - if (restorables.isEmpty()) - registeredRestorablesForState.erase(it); - } -} - -QList QStateMachinePrivate::restorablesToPropertyList(const QHash &restorables) const -{ - QList result; - QHash::const_iterator it; - for (it = restorables.constBegin(); it != restorables.constEnd(); ++it) { - const RestorableId &id = it.key(); - if (!id.object()) { - // Property object was deleted - continue; - } -#ifdef QSTATEMACHINE_RESTORE_PROPERTIES_DEBUG - qDebug() << q_func() << ": restoring" << id.object() << id.proertyName() << "to" << it.value(); -#endif - result.append(QPropertyAssignment(id.object(), id.propertyName(), it.value(), /*explicitlySet=*/false)); - } - return result; -} - -/*! - \internal - Computes the set of properties whose values should be restored given that - the states \a statesToExit_sorted will be exited. - - If a particular (object, propertyName) pair occurs more than once (i.e., - because nested states are being exited), the value from the last (outermost) - exited state takes precedence. - - The result of this function must be filtered according to the explicit - property assignments (QState::assignProperty()) of the entered states - before the property restoration is actually performed; i.e., if an entered - state assigns to a property that would otherwise be restored, that property - should not be restored after all, but the saved value from the exited state - should be remembered by the entered state (see registerRestorable()). -*/ -QHash QStateMachinePrivate::computePendingRestorables( - const QList &statesToExit_sorted) const -{ - QHash restorables; - for (int i = statesToExit_sorted.size() - 1; i >= 0; --i) { - QAbstractState *s = statesToExit_sorted.at(i); - QHash rs = registeredRestorablesForState.value(s); - QHash::const_iterator it; - for (it = rs.constBegin(); it != rs.constEnd(); ++it) { - if (!restorables.contains(it.key())) - restorables.insert(it.key(), it.value()); - } - } - return restorables; -} - -/*! - \internal - Computes the ordered sets of property assignments for the states to be - entered, \a statesToEnter_sorted. Also filters \a pendingRestorables (removes - properties that should not be restored because they are assigned by an - entered state). -*/ -QHash> QStateMachinePrivate::computePropertyAssignments( - const QList &statesToEnter_sorted, QHash &pendingRestorables) const -{ - QHash> assignmentsForState; - for (int i = 0; i < statesToEnter_sorted.size(); ++i) { - QState *s = toStandardState(statesToEnter_sorted.at(i)); - if (!s) - continue; - - QList &assignments = QStatePrivate::get(s)->propertyAssignments; - for (int j = 0; j < assignments.size(); ++j) { - const QPropertyAssignment &assn = assignments.at(j); - if (assn.objectDeleted()) { - assignments.removeAt(j--); - } else { - pendingRestorables.remove(RestorableId(assn.object, assn.propertyName)); - assignmentsForState[s].append(assn); - } - } - } - return assignmentsForState; -} - -#endif // QT_NO_PROPERTIES - -QAbstractState *QStateMachinePrivate::findErrorState(QAbstractState *context) -{ - // Find error state recursively in parent hierarchy if not set explicitly for context state - QAbstractState *errorState = nullptr; - if (context != nullptr) { - QState *s = toStandardState(context); - if (s != nullptr) - errorState = s->errorState(); - - if (errorState == nullptr) - errorState = findErrorState(context->parentState()); - } - - return errorState; -} - -void QStateMachinePrivate::setError(QStateMachine::Error errorCode, QAbstractState *currentContext) -{ - Q_Q(QStateMachine); - - error = errorCode; - switch (errorCode) { - case QStateMachine::NoInitialStateError: - Q_ASSERT(currentContext != nullptr); - - errorString = QStateMachine::tr("Missing initial state in compound state '%1'") - .arg(currentContext->objectName()); - - break; - case QStateMachine::NoDefaultStateInHistoryStateError: - Q_ASSERT(currentContext != nullptr); - - errorString = QStateMachine::tr("Missing default state in history state '%1'") - .arg(currentContext->objectName()); - break; - - case QStateMachine::NoCommonAncestorForTransitionError: - Q_ASSERT(currentContext != nullptr); - - errorString = QStateMachine::tr("No common ancestor for targets and source of transition from state '%1'") - .arg(currentContext->objectName()); - break; - - case QStateMachine::StateMachineChildModeSetToParallelError: - Q_ASSERT(currentContext != nullptr); - - errorString = QStateMachine::tr("Child mode of state machine '%1' is not 'ExclusiveStates'.") - .arg(currentContext->objectName()); - break; - - default: - errorString = QStateMachine::tr("Unknown error"); - }; - - pendingErrorStates.clear(); - pendingErrorStatesForDefaultEntry.clear(); - - QAbstractState *currentErrorState = findErrorState(currentContext); - - // Avoid infinite loop if the error state itself has an error - if (currentContext == currentErrorState) - currentErrorState = nullptr; - - Q_ASSERT(currentErrorState != rootState()); - - if (currentErrorState != nullptr) { -#ifdef QSTATEMACHINE_DEBUG - qDebug() << q << ": entering error state" << currentErrorState << "from" << currentContext; -#endif - pendingErrorStates.insert(currentErrorState); - addDescendantStatesToEnter(currentErrorState, pendingErrorStates, pendingErrorStatesForDefaultEntry); - addAncestorStatesToEnter(currentErrorState, rootState(), pendingErrorStates, pendingErrorStatesForDefaultEntry); - pendingErrorStates -= configuration; - } else { - qWarning("Unrecoverable error detected in running state machine: %ls", - qUtf16Printable(errorString)); - q->stop(); - } -} - -#if QT_CONFIG(animation) - -QStateMachinePrivate::InitializeAnimationResult -QStateMachinePrivate::initializeAnimation(QAbstractAnimation *abstractAnimation, - const QPropertyAssignment &prop) -{ - InitializeAnimationResult result; - QAnimationGroup *group = qobject_cast(abstractAnimation); - if (group) { - for (int i = 0; i < group->animationCount(); ++i) { - QAbstractAnimation *animationChild = group->animationAt(i); - const auto ret = initializeAnimation(animationChild, prop); - result.handledAnimations << ret.handledAnimations; - result.localResetEndValues << ret.localResetEndValues; - } - } else { - QPropertyAnimation *animation = qobject_cast(abstractAnimation); - if (animation != nullptr - && prop.object == animation->targetObject() - && prop.propertyName == animation->propertyName()) { - - // Only change end value if it is undefined - if (!animation->endValue().isValid()) { - animation->setEndValue(prop.value); - result.localResetEndValues.append(animation); - } - result.handledAnimations.append(animation); - } - } - return result; -} - -void QStateMachinePrivate::_q_animationFinished() -{ - Q_Q(QStateMachine); - QAbstractAnimation *anim = qobject_cast(q->sender()); - Q_ASSERT(anim != nullptr); - QObject::disconnect(anim, SIGNAL(finished()), q, SLOT(_q_animationFinished())); - if (resetAnimationEndValues.contains(anim)) { - qobject_cast(anim)->setEndValue(QVariant()); // ### generalize - resetAnimationEndValues.remove(anim); - } - - QAbstractState *state = stateForAnimation.take(anim); - Q_ASSERT(state != nullptr); - -#ifndef QT_NO_PROPERTIES - // Set the final property value. - QPropertyAssignment assn = propertyForAnimation.take(anim); - assn.write(); - if (!assn.explicitlySet) - unregisterRestorables(QList() << state, assn.object, assn.propertyName); -#endif - - QHash >::iterator it; - it = animationsForState.find(state); - Q_ASSERT(it != animationsForState.end()); - QList &animations = it.value(); - animations.removeOne(anim); - if (animations.isEmpty()) { - animationsForState.erase(it); - QStatePrivate::get(toStandardState(state))->emitPropertiesAssigned(); - } -} - -QList QStateMachinePrivate::selectAnimations(const QList &transitionList) const -{ - QList selectedAnimations; - if (animated) { - for (int i = 0; i < transitionList.size(); ++i) { - QAbstractTransition *transition = transitionList.at(i); - - selectedAnimations << transition->animations(); - selectedAnimations << defaultAnimationsForSource.values(transition->sourceState()); - - QList targetStates = transition->targetStates(); - for (int j=0; j> &assignmentsForEnteredStates) -{ - Q_Q(QStateMachine); - QList animations = animationsForState.take(state); - for (int i = 0; i < animations.size(); ++i) { - QAbstractAnimation *anim = animations.at(i); - QObject::disconnect(anim, SIGNAL(finished()), q, SLOT(_q_animationFinished())); - stateForAnimation.remove(anim); - - // Stop the (top-level) animation. - // ### Stopping nested animation has weird behavior. - QAbstractAnimation *topLevelAnim = anim; - while (QAnimationGroup *group = topLevelAnim->group()) - topLevelAnim = group; - topLevelAnim->stop(); - - if (resetAnimationEndValues.contains(anim)) { - qobject_cast(anim)->setEndValue(QVariant()); // ### generalize - resetAnimationEndValues.remove(anim); - } - QPropertyAssignment assn = propertyForAnimation.take(anim); - Q_ASSERT(assn.object != nullptr); - // If there is no property assignment that sets this property, - // set the property to its target value. - bool found = false; - for (auto it = assignmentsForEnteredStates.constBegin(); it != assignmentsForEnteredStates.constEnd(); ++it) { - const QList &assignments = it.value(); - for (int j = 0; j < assignments.size(); ++j) { - if (assignments.at(j).hasTarget(assn.object, assn.propertyName)) { - found = true; - break; - } - } - } - if (!found) { - assn.write(); - if (!assn.explicitlySet) - unregisterRestorables(QList() << state, assn.object, assn.propertyName); - } - } -} - -void QStateMachinePrivate::initializeAnimations(QAbstractState *state, const QList &selectedAnimations, - const QList &exitedStates_sorted, - QHash> &assignmentsForEnteredStates) -{ - Q_Q(QStateMachine); - if (!assignmentsForEnteredStates.contains(state)) - return; - QList &assignments = assignmentsForEnteredStates[state]; - for (int i = 0; i < selectedAnimations.size(); ++i) { - QAbstractAnimation *anim = selectedAnimations.at(i); - for (auto it = assignments.begin(); it != assignments.end(); ) { - const QPropertyAssignment &assn = *it; - const auto ret = initializeAnimation(anim, assn); - if (!ret.handledAnimations.isEmpty()) { - for (int j = 0; j < ret.handledAnimations.size(); ++j) { - QAbstractAnimation *a = ret.handledAnimations.at(j); - propertyForAnimation.insert(a, assn); - stateForAnimation.insert(a, state); - animationsForState[state].append(a); - // ### connect to just the top-level animation? - QObject::connect(a, SIGNAL(finished()), q, SLOT(_q_animationFinished()), Qt::UniqueConnection); - } - if ((globalRestorePolicy == QState::RestoreProperties) - && !hasRestorable(state, assn.object, assn.propertyName)) { - QVariant value = savedValueForRestorable(exitedStates_sorted, assn.object, assn.propertyName); - unregisterRestorables(exitedStates_sorted, assn.object, assn.propertyName); - registerRestorable(state, assn.object, assn.propertyName, value); - } - it = assignments.erase(it); - } else { - ++it; - } - for (int j = 0; j < ret.localResetEndValues.size(); ++j) - resetAnimationEndValues.insert(ret.localResetEndValues.at(j)); - } - // We require that at least one animation is valid. - // ### generalize - QList variantAnims = anim->findChildren(); - if (QVariantAnimation *va = qobject_cast(anim)) - variantAnims.append(va); - - bool hasValidEndValue = false; - for (int j = 0; j < variantAnims.size(); ++j) { - if (variantAnims.at(j)->endValue().isValid()) { - hasValidEndValue = true; - break; - } - } - - if (hasValidEndValue) { - if (anim->state() == QAbstractAnimation::Running) { - // The animation is still running. This can happen if the - // animation is a group, and one of its children just finished, - // and that caused a state to emit its propertiesAssigned() signal, and - // that triggered a transition in the machine. - // Just stop the animation so it is correctly restarted again. - anim->stop(); - } - anim->start(); - } - - if (assignments.isEmpty()) { - assignmentsForEnteredStates.remove(state); - break; - } - } -} - -#endif // animation - -QAbstractTransition *QStateMachinePrivate::createInitialTransition() const -{ - class InitialTransition : public QAbstractTransition - { - public: - InitialTransition(const QList &targets) - : QAbstractTransition() - { setTargetStates(targets); } - protected: - bool eventTest(QEvent *) override { return true; } - void onTransition(QEvent *) override {} - }; - - QState *root = rootState(); - Q_ASSERT(root != nullptr); - QList targets; - switch (root->childMode()) { - case QState::ExclusiveStates: - targets.append(root->initialState()); - break; - case QState::ParallelStates: - targets = QStatePrivate::get(root)->childStates(); - break; - } - return new InitialTransition(targets); -} - -void QStateMachinePrivate::clearHistory() -{ - Q_Q(QStateMachine); - QList historyStates = q->findChildren(); - for (int i = 0; i < historyStates.size(); ++i) { - QHistoryState *h = historyStates.at(i); - QHistoryStatePrivate::get(h)->configuration.clear(); - } -} - -/*! - \internal - - Registers all signal transitions whose sender object lives in another thread. - - Normally, signal transitions are lazily registered (when a state becomes - active). But if the sender is in a different thread, the transition must be - registered early to keep the state machine from "dropping" signals; e.g., - a second (transition-bound) signal could be emitted on the sender thread - before the state machine gets to process the first signal. -*/ -void QStateMachinePrivate::registerMultiThreadedSignalTransitions() -{ - Q_Q(QStateMachine); - QList transitions = rootState()->findChildren(); - for (int i = 0; i < transitions.size(); ++i) { - QSignalTransition *t = transitions.at(i); - if ((t->machine() == q) && t->senderObject() && (t->senderObject()->thread() != q->thread())) - registerSignalTransition(t); - } -} - -void QStateMachinePrivate::_q_start() -{ - Q_Q(QStateMachine); - Q_ASSERT(state == Starting); - // iterate over a copy, since we emit signals which may cause - // 'configuration' to change, resulting in undefined behavior when - // iterating at the same time: - const auto config = configuration; - for (QAbstractState *state : config) { - QAbstractStatePrivate *abstractStatePrivate = QAbstractStatePrivate::get(state); - abstractStatePrivate->active = false; - emit state->activeChanged(false); - } - configuration.clear(); - qDeleteAll(internalEventQueue); - internalEventQueue.clear(); - qDeleteAll(externalEventQueue); - externalEventQueue.clear(); - clearHistory(); - - registerMultiThreadedSignalTransitions(); - - startupHook(); - -#ifdef QSTATEMACHINE_DEBUG - qDebug() << q << ": starting"; -#endif - state = Running; - processingScheduled = true; // we call _q_process() below - - QList transitions; - CalculationCache calculationCache; - QAbstractTransition *initialTransition = createInitialTransition(); - transitions.append(initialTransition); - - QEvent nullEvent(QEvent::None); - executeTransitionContent(&nullEvent, transitions); - QList exitedStates = QList(); - QSet statesForDefaultEntry; - QList enteredStates = computeEntrySet(transitions, statesForDefaultEntry, &calculationCache); - QHash pendingRestorables; - QHash> assignmentsForEnteredStates = - computePropertyAssignments(enteredStates, pendingRestorables); -#if QT_CONFIG(animation) - QList selectedAnimations = selectAnimations(transitions); -#endif - // enterStates() will set stopProcessingReason to Finished if a final - // state is entered. - stopProcessingReason = EventQueueEmpty; - enterStates(&nullEvent, exitedStates, enteredStates, statesForDefaultEntry, - assignmentsForEnteredStates -#if QT_CONFIG(animation) - , selectedAnimations -#endif - ); - delete initialTransition; - -#ifdef QSTATEMACHINE_DEBUG - qDebug() << q << ": initial configuration:" << configuration; -#endif - - emit q->started(QStateMachine::QPrivateSignal()); - emit q->runningChanged(true); - - if (stopProcessingReason == Finished) { - // The state machine immediately reached a final state. - processingScheduled = false; - state = NotRunning; - unregisterAllTransitions(); - emitFinished(); - emit q->runningChanged(false); - exitInterpreter(); - } else { - _q_process(); - } -} - -void QStateMachinePrivate::_q_process() -{ - Q_Q(QStateMachine); - Q_ASSERT(state == Running); - Q_ASSERT(!processing); - processing = true; - processingScheduled = false; - beginMacrostep(); -#ifdef QSTATEMACHINE_DEBUG - qDebug() << q << ": starting the event processing loop"; -#endif - bool didChange = false; - while (processing) { - if (stop) { - processing = false; - break; - } - QList enabledTransitions; - CalculationCache calculationCache; - - QEvent *e = new QEvent(QEvent::None); - enabledTransitions = selectTransitions(e, &calculationCache); - if (enabledTransitions.isEmpty()) { - delete e; - e = nullptr; - } - while (enabledTransitions.isEmpty() && ((e = dequeueInternalEvent()) != nullptr)) { -#ifdef QSTATEMACHINE_DEBUG - qDebug() << q << ": dequeued internal event" << e << "of type" << e->type(); -#endif - enabledTransitions = selectTransitions(e, &calculationCache); - if (enabledTransitions.isEmpty()) { - delete e; - e = nullptr; - } - } - while (enabledTransitions.isEmpty() && ((e = dequeueExternalEvent()) != nullptr)) { -#ifdef QSTATEMACHINE_DEBUG - qDebug() << q << ": dequeued external event" << e << "of type" << e->type(); -#endif - enabledTransitions = selectTransitions(e, &calculationCache); - if (enabledTransitions.isEmpty()) { - delete e; - e = nullptr; - } - } - if (enabledTransitions.isEmpty()) { - if (isInternalEventQueueEmpty()) { - processing = false; - stopProcessingReason = EventQueueEmpty; - noMicrostep(); -#ifdef QSTATEMACHINE_DEBUG - qDebug() << q << ": no transitions enabled"; -#endif - } - } else { - didChange = true; - q->beginMicrostep(e); - microstep(e, enabledTransitions, &calculationCache); - q->endMicrostep(e); - } - delete e; - } -#ifdef QSTATEMACHINE_DEBUG - qDebug() << q << ": finished the event processing loop"; -#endif - if (stop) { - stop = false; - stopProcessingReason = Stopped; - } - - switch (stopProcessingReason) { - case EventQueueEmpty: - processedPendingEvents(didChange); - break; - case Finished: - state = NotRunning; - cancelAllDelayedEvents(); - unregisterAllTransitions(); - emitFinished(); - emit q->runningChanged(false); - break; - case Stopped: - state = NotRunning; - cancelAllDelayedEvents(); - unregisterAllTransitions(); - emit q->stopped(QStateMachine::QPrivateSignal()); - emit q->runningChanged(false); - break; - } - endMacrostep(didChange); - if (stopProcessingReason == Finished) - exitInterpreter(); -} - -void QStateMachinePrivate::_q_startDelayedEventTimer(int id, int delay) -{ - Q_Q(QStateMachine); - QMutexLocker locker(&delayedEventsMutex); - QHash::iterator it = delayedEvents.find(id); - if (it != delayedEvents.end()) { - DelayedEvent &e = it.value(); - Q_ASSERT(!e.timerId); - e.timerId = q->startTimer(delay); - if (!e.timerId) { - qWarning("QStateMachine::postDelayedEvent: failed to start timer (id=%d, delay=%d)", id, delay); - delete e.event; - delayedEvents.erase(it); - delayedEventIdFreeList.release(id); - } else { - timerIdToDelayedEventId.insert(e.timerId, id); - } - } else { - // It's been cancelled already - delayedEventIdFreeList.release(id); - } -} - -void QStateMachinePrivate::_q_killDelayedEventTimer(int id, int timerId) -{ - Q_Q(QStateMachine); - q->killTimer(timerId); - QMutexLocker locker(&delayedEventsMutex); - delayedEventIdFreeList.release(id); -} - -void QStateMachinePrivate::postInternalEvent(QEvent *e) -{ - QMutexLocker locker(&internalEventMutex); - internalEventQueue.append(e); -} - -void QStateMachinePrivate::postExternalEvent(QEvent *e) -{ - QMutexLocker locker(&externalEventMutex); - externalEventQueue.append(e); -} - -QEvent *QStateMachinePrivate::dequeueInternalEvent() -{ - QMutexLocker locker(&internalEventMutex); - if (internalEventQueue.isEmpty()) - return nullptr; - return internalEventQueue.takeFirst(); -} - -QEvent *QStateMachinePrivate::dequeueExternalEvent() -{ - QMutexLocker locker(&externalEventMutex); - if (externalEventQueue.isEmpty()) - return nullptr; - return externalEventQueue.takeFirst(); -} - -bool QStateMachinePrivate::isInternalEventQueueEmpty() -{ - QMutexLocker locker(&internalEventMutex); - return internalEventQueue.isEmpty(); -} - -bool QStateMachinePrivate::isExternalEventQueueEmpty() -{ - QMutexLocker locker(&externalEventMutex); - return externalEventQueue.isEmpty(); -} - -void QStateMachinePrivate::processEvents(EventProcessingMode processingMode) -{ - Q_Q(QStateMachine); - if ((state != Running) || processing || processingScheduled) - return; - switch (processingMode) { - case DirectProcessing: - if (QThread::currentThread() == q->thread()) { - _q_process(); - break; - } - // processing must be done in the machine thread, so: - Q_FALLTHROUGH(); - case QueuedProcessing: - processingScheduled = true; - QMetaObject::invokeMethod(q, "_q_process", Qt::QueuedConnection); - break; - } -} - -void QStateMachinePrivate::cancelAllDelayedEvents() -{ - Q_Q(QStateMachine); - QMutexLocker locker(&delayedEventsMutex); - QHash::const_iterator it; - for (it = delayedEvents.constBegin(); it != delayedEvents.constEnd(); ++it) { - const DelayedEvent &e = it.value(); - if (e.timerId) { - timerIdToDelayedEventId.remove(e.timerId); - q->killTimer(e.timerId); - delayedEventIdFreeList.release(it.key()); - } else { - // Cancellation will be detected in pending _q_startDelayedEventTimer() call - } - delete e.event; - } - delayedEvents.clear(); -} - -/* - This function is called when the state machine is performing no - microstep because no transition is enabled (i.e. an event is ignored). - - The default implementation does nothing. -*/ -void QStateMachinePrivate::noMicrostep() -{ } - -/* - This function is called when the state machine has reached a stable - state (no pending events), and has not finished yet. - For each event the state machine receives it is guaranteed that - 1) beginMacrostep is called - 2) selectTransition is called at least once - 3) begin/endMicrostep is called at least once or noMicrostep is called - at least once (possibly both, but at least one) - 4) the state machine either enters an infinite loop, or stops (runningChanged(false), - and either finished or stopped are emitted), or processedPendingEvents() is called. - 5) if the machine is not in an infinite loop endMacrostep is called - 6) when the machine is finished and all processing (like signal emission) is done, - exitInterpreter() is called. (This is the same name as the SCXML specification uses.) - - didChange is set to true if at least one microstep was performed, it is possible - that the machine returned to exactly the same state as before, but some transitions - were triggered. - - The default implementation does nothing. -*/ -void QStateMachinePrivate::processedPendingEvents(bool didChange) -{ - Q_UNUSED(didChange); -} - -void QStateMachinePrivate::beginMacrostep() -{ } - -void QStateMachinePrivate::endMacrostep(bool didChange) -{ - Q_UNUSED(didChange); -} - -void QStateMachinePrivate::exitInterpreter() -{ -} - -void QStateMachinePrivate::emitStateFinished(QState *forState, QFinalState *guiltyState) -{ - Q_UNUSED(guiltyState); - Q_ASSERT(guiltyState); - -#ifdef QSTATEMACHINE_DEBUG - Q_Q(QStateMachine); - qDebug() << q << ": emitting finished signal for" << forState; -#endif - - QStatePrivate::get(forState)->emitFinished(); -} - -void QStateMachinePrivate::startupHook() -{ -} - -namespace _QStateMachine_Internal{ - -class GoToStateTransition : public QAbstractTransition -{ - Q_OBJECT -public: - GoToStateTransition(QAbstractState *target) - : QAbstractTransition() - { setTargetState(target); } -protected: - void onTransition(QEvent *) override { deleteLater(); } - bool eventTest(QEvent *) override { return true; } -}; - -} // namespace -// mingw compiler tries to export QObject::findChild(), -// which doesn't work if its in an anonymous namespace. -using namespace _QStateMachine_Internal; -/*! - \internal - - Causes this state machine to unconditionally transition to the given - \a targetState. - - Provides a backdoor for using the state machine "imperatively"; i.e. rather - than defining explicit transitions, you drive the machine's execution by - calling this function. It breaks the whole integrity of the - transition-driven model, but is provided for pragmatic reasons. -*/ -void QStateMachinePrivate::goToState(QAbstractState *targetState) -{ - if (!targetState) { - qWarning("QStateMachine::goToState(): cannot go to null state"); - return; - } - - if (configuration.contains(targetState)) - return; - - Q_ASSERT(state == Running); - QState *sourceState = nullptr; - QSet::const_iterator it; - for (it = configuration.constBegin(); it != configuration.constEnd(); ++it) { - sourceState = toStandardState(*it); - if (sourceState != nullptr) - break; - } - - Q_ASSERT(sourceState != nullptr); - // Reuse previous GoToStateTransition in case of several calls to - // goToState() in a row. - GoToStateTransition *trans = sourceState->findChild(); - if (!trans) { - trans = new GoToStateTransition(targetState); - sourceState->addTransition(trans); - } else { - trans->setTargetState(targetState); - } - - processEvents(QueuedProcessing); -} - -void QStateMachinePrivate::registerTransitions(QAbstractState *state) -{ - QState *group = toStandardState(state); - if (!group) - return; - QList transitions = QStatePrivate::get(group)->transitions(); - for (int i = 0; i < transitions.size(); ++i) { - QAbstractTransition *t = transitions.at(i); - registerTransition(t); - } -} - -void QStateMachinePrivate::maybeRegisterTransition(QAbstractTransition *transition) -{ - if (QSignalTransition *st = qobject_cast(transition)) { - maybeRegisterSignalTransition(st); - } -#if QT_CONFIG(qeventtransition) - else if (QEventTransition *et = qobject_cast(transition)) { - maybeRegisterEventTransition(et); - } -#endif -} - -void QStateMachinePrivate::registerTransition(QAbstractTransition *transition) -{ - if (QSignalTransition *st = qobject_cast(transition)) { - registerSignalTransition(st); - } -#if QT_CONFIG(qeventtransition) - else if (QEventTransition *oet = qobject_cast(transition)) { - registerEventTransition(oet); - } -#endif -} - -void QStateMachinePrivate::unregisterTransition(QAbstractTransition *transition) -{ - if (QSignalTransition *st = qobject_cast(transition)) { - unregisterSignalTransition(st); - } -#if QT_CONFIG(qeventtransition) - else if (QEventTransition *oet = qobject_cast(transition)) { - unregisterEventTransition(oet); - } -#endif -} - -void QStateMachinePrivate::maybeRegisterSignalTransition(QSignalTransition *transition) -{ - Q_Q(QStateMachine); - if ((state == Running) && (configuration.contains(transition->sourceState()) - || (transition->senderObject() && (transition->senderObject()->thread() != q->thread())))) { - registerSignalTransition(transition); - } -} - -void QStateMachinePrivate::registerSignalTransition(QSignalTransition *transition) -{ - Q_Q(QStateMachine); - if (QSignalTransitionPrivate::get(transition)->signalIndex != -1) - return; // already registered - const QObject *sender = QSignalTransitionPrivate::get(transition)->sender; - if (!sender) - return; - QByteArray signal = QSignalTransitionPrivate::get(transition)->signal; - if (signal.isEmpty()) - return; - if (signal.startsWith('0'+QSIGNAL_CODE)) - signal.remove(0, 1); - const QMetaObject *meta = sender->metaObject(); - int signalIndex = meta->indexOfSignal(signal); - int originalSignalIndex = signalIndex; - if (signalIndex == -1) { - signalIndex = meta->indexOfSignal(QMetaObject::normalizedSignature(signal)); - if (signalIndex == -1) { - qWarning("QSignalTransition: no such signal: %s::%s", - meta->className(), signal.constData()); - return; - } - originalSignalIndex = signalIndex; - } - // The signal index we actually want to connect to is the one - // that is going to be sent, i.e. the non-cloned original index. - while (meta->method(signalIndex).attributes() & QMetaMethod::Cloned) - --signalIndex; - - connectionsMutex.lock(); - QList &connectedSignalIndexes = connections[sender]; - if (connectedSignalIndexes.size() <= signalIndex) - connectedSignalIndexes.resize(signalIndex+1); - if (connectedSignalIndexes.at(signalIndex) == 0) { - if (!signalEventGenerator) - signalEventGenerator = new QSignalEventGenerator(q); - static const int generatorMethodOffset = QSignalEventGenerator::staticMetaObject.methodOffset(); - bool ok = QMetaObject::connect(sender, signalIndex, signalEventGenerator, generatorMethodOffset); - if (!ok) { -#ifdef QSTATEMACHINE_DEBUG - qDebug() << q << ": FAILED to add signal transition from" << transition->sourceState() - << ": ( sender =" << sender << ", signal =" << signal - << ", targets =" << transition->targetStates() << ')'; -#endif - return; - } - } - ++connectedSignalIndexes[signalIndex]; - connectionsMutex.unlock(); - - QSignalTransitionPrivate::get(transition)->signalIndex = signalIndex; - QSignalTransitionPrivate::get(transition)->originalSignalIndex = originalSignalIndex; -#ifdef QSTATEMACHINE_DEBUG - qDebug() << q << ": added signal transition from" << transition->sourceState() - << ": ( sender =" << sender << ", signal =" << signal - << ", targets =" << transition->targetStates() << ')'; -#endif -} - -void QStateMachinePrivate::unregisterSignalTransition(QSignalTransition *transition) -{ - int signalIndex = QSignalTransitionPrivate::get(transition)->signalIndex; - if (signalIndex == -1) - return; // not registered - const QObject *sender = QSignalTransitionPrivate::get(transition)->sender; - QSignalTransitionPrivate::get(transition)->signalIndex = -1; - - connectionsMutex.lock(); - QList &connectedSignalIndexes = connections[sender]; - Q_ASSERT(connectedSignalIndexes.size() > signalIndex); - Q_ASSERT(connectedSignalIndexes.at(signalIndex) != 0); - if (--connectedSignalIndexes[signalIndex] == 0) { - Q_ASSERT(signalEventGenerator != nullptr); - static const int generatorMethodOffset = QSignalEventGenerator::staticMetaObject.methodOffset(); - QMetaObject::disconnect(sender, signalIndex, signalEventGenerator, generatorMethodOffset); - int sum = 0; - for (int i = 0; i < connectedSignalIndexes.size(); ++i) - sum += connectedSignalIndexes.at(i); - if (sum == 0) - connections.remove(sender); - } - connectionsMutex.unlock(); -} - -void QStateMachinePrivate::unregisterAllTransitions() -{ - Q_Q(QStateMachine); - { - QList transitions = rootState()->findChildren(); - for (int i = 0; i < transitions.size(); ++i) { - QSignalTransition *t = transitions.at(i); - if (t->machine() == q) - unregisterSignalTransition(t); - } - } -#if QT_CONFIG(qeventtransition) - { - QList transitions = rootState()->findChildren(); - for (int i = 0; i < transitions.size(); ++i) { - QEventTransition *t = transitions.at(i); - if (t->machine() == q) - unregisterEventTransition(t); - } - } -#endif -} - -#if QT_CONFIG(qeventtransition) -void QStateMachinePrivate::maybeRegisterEventTransition(QEventTransition *transition) -{ - if ((state == Running) && configuration.contains(transition->sourceState())) - registerEventTransition(transition); -} - -void QStateMachinePrivate::registerEventTransition(QEventTransition *transition) -{ - Q_Q(QStateMachine); - if (QEventTransitionPrivate::get(transition)->registered) - return; - if (transition->eventType() >= QEvent::User) { - qWarning("QObject event transitions are not supported for custom types"); - return; - } - QObject *object = QEventTransitionPrivate::get(transition)->object; - if (!object) - return; - QObjectPrivate *od = QObjectPrivate::get(object); - if (!od->extraData || !od->extraData->eventFilters.contains(q)) - object->installEventFilter(q); - ++qobjectEvents[object][transition->eventType()]; - QEventTransitionPrivate::get(transition)->registered = true; -#ifdef QSTATEMACHINE_DEBUG - qDebug() << q << ": added event transition from" << transition->sourceState() - << ": ( object =" << object << ", event =" << transition->eventType() - << ", targets =" << transition->targetStates() << ')'; -#endif -} - -void QStateMachinePrivate::unregisterEventTransition(QEventTransition *transition) -{ - Q_Q(QStateMachine); - if (!QEventTransitionPrivate::get(transition)->registered) - return; - QObject *object = QEventTransitionPrivate::get(transition)->object; - QHash &events = qobjectEvents[object]; - Q_ASSERT(events.value(transition->eventType()) > 0); - if (--events[transition->eventType()] == 0) { - events.remove(transition->eventType()); - int sum = 0; - QHash::const_iterator it; - for (it = events.constBegin(); it != events.constEnd(); ++it) - sum += it.value(); - if (sum == 0) { - qobjectEvents.remove(object); - object->removeEventFilter(q); - } - } - QEventTransitionPrivate::get(transition)->registered = false; -} - -void QStateMachinePrivate::handleFilteredEvent(QObject *watched, QEvent *event) -{ - if (qobjectEvents.value(watched).contains(event->type())) { - postInternalEvent(new QStateMachine::WrappedEvent(watched, handler->cloneEvent(event))); - processEvents(DirectProcessing); - } -} -#endif - -void QStateMachinePrivate::handleTransitionSignal(QObject *sender, int signalIndex, - void **argv) -{ -#ifndef QT_NO_DEBUG - connectionsMutex.lock(); - Q_ASSERT(connections[sender].at(signalIndex) != 0); - connectionsMutex.unlock(); -#endif - const QMetaObject *meta = sender->metaObject(); - QMetaMethod method = meta->method(signalIndex); - int argc = method.parameterCount(); - QList vargs; - vargs.reserve(argc); - for (int i = 0; i < argc; ++i) { - auto type = method.parameterMetaType(i); - vargs.append(QVariant(type, argv[i+1])); - } - -#ifdef QSTATEMACHINE_DEBUG - qDebug() << q_func() << ": sending signal event ( sender =" << sender - << ", signal =" << method.methodSignature().constData() << ')'; -#endif - postInternalEvent(new QStateMachine::SignalEvent(sender, signalIndex, vargs)); - processEvents(DirectProcessing); -} - -/*! - Constructs a new state machine with the given \a parent. -*/ -QStateMachine::QStateMachine(QObject *parent) - : QState(*new QStateMachinePrivate, /*parentState=*/nullptr) -{ - // Can't pass the parent to the QState constructor, as it expects a QState - // But this works as expected regardless of whether parent is a QState or not - setParent(parent); -} - -/*! - \since 5.0 - \deprecated - - Constructs a new state machine with the given \a childMode - and \a parent. - - \warning Do not set the \a childMode to anything else than \l{ExclusiveStates}, otherwise the - state machine is invalid, and might work incorrectly. -*/ -QStateMachine::QStateMachine(QState::ChildMode childMode, QObject *parent) - : QState(*new QStateMachinePrivate, /*parentState=*/nullptr) -{ - Q_D(QStateMachine); - d->childMode = childMode; - setParent(parent); // See comment in constructor above - - if (childMode != ExclusiveStates) { - //### FIXME for Qt6: remove this constructor completely, and hide the childMode property. - // Yes, the StateMachine itself is conceptually a state, but it should only expose a limited - // number of properties. The execution algorithm (in the URL below) treats a state machine - // as a state, but from an API point of view, it's questionable if the QStateMachine should - // inherit from QState. - // - // See function findLCCA in https://www.w3.org/TR/2014/WD-scxml-20140529/#AlgorithmforSCXMLInterpretation - // to see where setting childMode to parallel will break down. - qWarning() << "Invalid childMode for QStateMachine" << this; - } -} - -/*! - \internal -*/ -QStateMachine::QStateMachine(QStateMachinePrivate &dd, QObject *parent) - : QState(dd, /*parentState=*/nullptr) -{ - setParent(parent); -} - -/*! - Destroys this state machine. -*/ -QStateMachine::~QStateMachine() -{ -} - -/*! - \enum QStateMachine::EventPriority - - This enum type specifies the priority of an event posted to the state - machine using postEvent(). - - Events of high priority are processed before events of normal priority. - - \value NormalPriority The event has normal priority. - \value HighPriority The event has high priority. -*/ - -/*! \enum QStateMachine::Error - - This enum type defines errors that can occur in the state machine at run time. When the state - machine encounters an unrecoverable error at run time, it will set the error code returned - by error(), the error message returned by errorString(), and enter an error state based on - the context of the error. - - \value NoError No error has occurred. - \value NoInitialStateError The machine has entered a QState with children which does not have an - initial state set. The context of this error is the state which is missing an initial - state. - \value NoDefaultStateInHistoryStateError The machine has entered a QHistoryState which does not have - a default state set. The context of this error is the QHistoryState which is missing a - default state. - \value NoCommonAncestorForTransitionError The machine has selected a transition whose source - and targets are not part of the same tree of states, and thus are not part of the same - state machine. Commonly, this could mean that one of the states has not been given - any parent or added to any machine. The context of this error is the source state of - the transition. - \value StateMachineChildModeSetToParallelError The machine's \l childMode - property was set to \l{QState::ParallelStates}. This is illegal. - Only states may be declared as parallel, not the state machine - itself. This enum value was added in Qt 5.14. - - \sa setErrorState() -*/ - -/*! - Returns the error code of the last error that occurred in the state machine. -*/ -QStateMachine::Error QStateMachine::error() const -{ - Q_D(const QStateMachine); - return d->error; -} - -/*! - Returns the error string of the last error that occurred in the state machine. -*/ -QString QStateMachine::errorString() const -{ - Q_D(const QStateMachine); - return d->errorString; -} - -/*! - Clears the error string and error code of the state machine. -*/ -void QStateMachine::clearError() -{ - Q_D(QStateMachine); - d->errorString.clear(); - d->error = NoError; -} - -/*! - Returns the restore policy of the state machine. - - \sa setGlobalRestorePolicy() -*/ -QState::RestorePolicy QStateMachine::globalRestorePolicy() const -{ - Q_D(const QStateMachine); - return d->globalRestorePolicy; -} - -/*! - Sets the restore policy of the state machine to \a restorePolicy. The default - restore policy is QState::DontRestoreProperties. - - \sa globalRestorePolicy() -*/ -void QStateMachine::setGlobalRestorePolicy(QState::RestorePolicy restorePolicy) -{ - Q_D(QStateMachine); - d->globalRestorePolicy = restorePolicy; -} - -/*! - Adds the given \a state to this state machine. The state becomes a top-level - state and the state machine takes ownership of the state. - - If the state is already in a different machine, it will first be removed - from its old machine, and then added to this machine. - - \sa removeState(), setInitialState() -*/ -void QStateMachine::addState(QAbstractState *state) -{ - if (!state) { - qWarning("QStateMachine::addState: cannot add null state"); - return; - } - if (QAbstractStatePrivate::get(state)->machine() == this) { - qWarning("QStateMachine::addState: state has already been added to this machine"); - return; - } - state->setParent(this); -} - -/*! - Removes the given \a state from this state machine. The state machine - releases ownership of the state. - - \sa addState() -*/ -void QStateMachine::removeState(QAbstractState *state) -{ - if (!state) { - qWarning("QStateMachine::removeState: cannot remove null state"); - return; - } - if (QAbstractStatePrivate::get(state)->machine() != this) { - qWarning("QStateMachine::removeState: state %p's machine (%p)" - " is different from this machine (%p)", - state, QAbstractStatePrivate::get(state)->machine(), this); - return; - } - state->setParent(nullptr); -} - -bool QStateMachine::isRunning() const -{ - Q_D(const QStateMachine); - return (d->state == QStateMachinePrivate::Running); -} - -/*! - Starts this state machine. The machine will reset its configuration and - transition to the initial state. When a final top-level state (QFinalState) - is entered, the machine will emit the finished() signal. - - \note A state machine will not run without a running event loop, such as - the main application event loop started with QCoreApplication::exec() or - QApplication::exec(). - - \sa started(), finished(), stop(), initialState(), setRunning() -*/ -void QStateMachine::start() -{ - Q_D(QStateMachine); - - if ((childMode() == QState::ExclusiveStates) && (initialState() == nullptr)) { - qWarning("QStateMachine::start: No initial state set for machine. Refusing to start."); - return; - } - - switch (d->state) { - case QStateMachinePrivate::NotRunning: - d->state = QStateMachinePrivate::Starting; - QMetaObject::invokeMethod(this, "_q_start", Qt::QueuedConnection); - break; - case QStateMachinePrivate::Starting: - break; - case QStateMachinePrivate::Running: - qWarning("QStateMachine::start(): already running"); - break; - } -} - -/*! - Stops this state machine. The state machine will stop processing events and - then emit the stopped() signal. - - \sa stopped(), start(), setRunning() -*/ -void QStateMachine::stop() -{ - Q_D(QStateMachine); - switch (d->state) { - case QStateMachinePrivate::NotRunning: - break; - case QStateMachinePrivate::Starting: - // the machine will exit as soon as it enters the event processing loop - d->stop = true; - break; - case QStateMachinePrivate::Running: - d->stop = true; - d->processEvents(QStateMachinePrivate::QueuedProcessing); - break; - } -} - -void QStateMachine::setRunning(bool running) -{ - if (running) - start(); - else - stop(); -} - -/*! - \threadsafe - - Posts the given \a event of the given \a priority for processing by this - state machine. - - This function returns immediately. The event is added to the state machine's - event queue. Events are processed in the order posted. The state machine - takes ownership of the event and deletes it once it has been processed. - - You can only post events when the state machine is running or when it is starting up. - - \sa postDelayedEvent() -*/ -void QStateMachine::postEvent(QEvent *event, EventPriority priority) -{ - Q_D(QStateMachine); - switch (d->state) { - case QStateMachinePrivate::Running: - case QStateMachinePrivate::Starting: - break; - default: - qWarning("QStateMachine::postEvent: cannot post event when the state machine is not running"); - return; - } - if (!event) { - qWarning("QStateMachine::postEvent: cannot post null event"); - return; - } -#ifdef QSTATEMACHINE_DEBUG - qDebug() << this << ": posting event" << event; -#endif - switch (priority) { - case NormalPriority: - d->postExternalEvent(event); - break; - case HighPriority: - d->postInternalEvent(event); - break; - } - d->processEvents(QStateMachinePrivate::QueuedProcessing); -} - -/*! - \threadsafe - - Posts the given \a event for processing by this state machine, with the - given \a delay in milliseconds. Returns an identifier associated with the - delayed event, or -1 if the event could not be posted. - - This function returns immediately. When the delay has expired, the event - will be added to the state machine's event queue for processing. The state - machine takes ownership of the event and deletes it once it has been - processed. - - You can only post events when the state machine is running. - - \sa cancelDelayedEvent(), postEvent() -*/ -int QStateMachine::postDelayedEvent(QEvent *event, int delay) -{ - Q_D(QStateMachine); - if (d->state != QStateMachinePrivate::Running) { - qWarning("QStateMachine::postDelayedEvent: cannot post event when the state machine is not running"); - return -1; - } - if (!event) { - qWarning("QStateMachine::postDelayedEvent: cannot post null event"); - return -1; - } - if (delay < 0) { - qWarning("QStateMachine::postDelayedEvent: delay cannot be negative"); - return -1; - } -#ifdef QSTATEMACHINE_DEBUG - qDebug() << this << ": posting event" << event << "with delay" << delay; -#endif - QMutexLocker locker(&d->delayedEventsMutex); - int id = d->delayedEventIdFreeList.next(); - bool inMachineThread = (QThread::currentThread() == thread()); - int timerId = inMachineThread ? startTimer(delay) : 0; - if (inMachineThread && !timerId) { - qWarning("QStateMachine::postDelayedEvent: failed to start timer with interval %d", delay); - d->delayedEventIdFreeList.release(id); - return -1; - } - QStateMachinePrivate::DelayedEvent delayedEvent(event, timerId); - d->delayedEvents.insert(id, delayedEvent); - if (timerId) { - d->timerIdToDelayedEventId.insert(timerId, id); - } else { - Q_ASSERT(!inMachineThread); - QMetaObject::invokeMethod(this, "_q_startDelayedEventTimer", - Qt::QueuedConnection, - Q_ARG(int, id), - Q_ARG(int, delay)); - } - return id; -} - -/*! - \threadsafe - - Cancels the delayed event identified by the given \a id. The id should be a - value returned by a call to postDelayedEvent(). Returns \c true if the event - was successfully cancelled, otherwise returns \c false. - - \sa postDelayedEvent() -*/ -bool QStateMachine::cancelDelayedEvent(int id) -{ - Q_D(QStateMachine); - if (d->state != QStateMachinePrivate::Running) { - qWarning("QStateMachine::cancelDelayedEvent: the machine is not running"); - return false; - } - QMutexLocker locker(&d->delayedEventsMutex); - QStateMachinePrivate::DelayedEvent e = d->delayedEvents.take(id); - if (!e.event) - return false; - if (e.timerId) { - d->timerIdToDelayedEventId.remove(e.timerId); - bool inMachineThread = (QThread::currentThread() == thread()); - if (inMachineThread) { - killTimer(e.timerId); - d->delayedEventIdFreeList.release(id); - } else { - QMetaObject::invokeMethod(this, "_q_killDelayedEventTimer", - Qt::QueuedConnection, - Q_ARG(int, id), - Q_ARG(int, e.timerId)); - } - } else { - // Cancellation will be detected in pending _q_startDelayedEventTimer() call - } - delete e.event; - return true; -} - -/*! - Returns the maximal consistent set of states (including parallel and final - states) that this state machine is currently in. If a state \c s is in the - configuration, it is always the case that the parent of \c s is also in - c. Note, however, that the machine itself is not an explicit member of the - configuration. -*/ -QSet QStateMachine::configuration() const -{ - Q_D(const QStateMachine); - return d->configuration; -} - -/*! - \fn QStateMachine::started() - - This signal is emitted when the state machine has entered its initial state - (QStateMachine::initialState). - - \sa QStateMachine::finished(), QStateMachine::start() -*/ - -/*! - \fn QStateMachine::stopped() - - This signal is emitted when the state machine has stopped. - - \sa QStateMachine::stop(), QStateMachine::finished() -*/ - -/*! - \reimp -*/ -bool QStateMachine::event(QEvent *e) -{ - Q_D(QStateMachine); - if (e->type() == QEvent::Timer) { - QTimerEvent *te = static_cast(e); - int tid = te->timerId(); - if (d->state != QStateMachinePrivate::Running) { - // This event has been cancelled already - QMutexLocker locker(&d->delayedEventsMutex); - Q_ASSERT(!d->timerIdToDelayedEventId.contains(tid)); - return true; - } - d->delayedEventsMutex.lock(); - int id = d->timerIdToDelayedEventId.take(tid); - QStateMachinePrivate::DelayedEvent ee = d->delayedEvents.take(id); - if (ee.event != nullptr) { - Q_ASSERT(ee.timerId == tid); - killTimer(tid); - d->delayedEventIdFreeList.release(id); - d->delayedEventsMutex.unlock(); - d->postExternalEvent(ee.event); - d->processEvents(QStateMachinePrivate::DirectProcessing); - return true; - } else { - d->delayedEventsMutex.unlock(); - } - } - return QState::event(e); -} - -#if QT_CONFIG(qeventtransition) -/*! - \reimp -*/ -bool QStateMachine::eventFilter(QObject *watched, QEvent *event) -{ - Q_D(QStateMachine); - d->handleFilteredEvent(watched, event); - return false; -} -#endif - -/*! - \internal - - This function is called when the state machine is about to select - transitions based on the given \a event. - - The default implementation does nothing. -*/ -void QStateMachine::beginSelectTransitions(QEvent *event) -{ - Q_UNUSED(event); -} - -/*! - \internal - - This function is called when the state machine has finished selecting - transitions based on the given \a event. - - The default implementation does nothing. -*/ -void QStateMachine::endSelectTransitions(QEvent *event) -{ - Q_UNUSED(event); -} - -/*! - \internal - - This function is called when the state machine is about to do a microstep. - - The default implementation does nothing. -*/ -void QStateMachine::beginMicrostep(QEvent *event) -{ - Q_UNUSED(event); -} - -/*! - \internal - - This function is called when the state machine has finished doing a - microstep. - - The default implementation does nothing. -*/ -void QStateMachine::endMicrostep(QEvent *event) -{ - Q_UNUSED(event); -} - -/*! - \reimp - This function will call start() to start the state machine. -*/ -void QStateMachine::onEntry(QEvent *event) -{ - start(); - QState::onEntry(event); -} - -/*! - \reimp - This function will call stop() to stop the state machine and - subsequently emit the stopped() signal. -*/ -void QStateMachine::onExit(QEvent *event) -{ - stop(); - QState::onExit(event); -} - -#if QT_CONFIG(animation) - -/*! - Returns whether animations are enabled for this state machine. -*/ -bool QStateMachine::isAnimated() const -{ - Q_D(const QStateMachine); - return d->animated; -} - -/*! - Sets whether animations are \a enabled for this state machine. -*/ -void QStateMachine::setAnimated(bool enabled) -{ - Q_D(QStateMachine); - d->animated = enabled; -} - -/*! - Adds a default \a animation to be considered for any transition. -*/ -void QStateMachine::addDefaultAnimation(QAbstractAnimation *animation) -{ - Q_D(QStateMachine); - d->defaultAnimations.append(animation); -} - -/*! - Returns the list of default animations that will be considered for any transition. -*/ -QList QStateMachine::defaultAnimations() const -{ - Q_D(const QStateMachine); - return d->defaultAnimations; -} - -/*! - Removes \a animation from the list of default animations. -*/ -void QStateMachine::removeDefaultAnimation(QAbstractAnimation *animation) -{ - Q_D(QStateMachine); - d->defaultAnimations.removeAll(animation); -} - -#endif // animation - -void QSignalEventGenerator::execute(QMethodRawArguments a) -{ - auto machinePrivate = QStateMachinePrivate::get(qobject_cast(parent())); - if (machinePrivate->state != QStateMachinePrivate::Running) - return; - int signalIndex = senderSignalIndex(); - Q_ASSERT(signalIndex != -1); - machinePrivate->handleTransitionSignal(sender(), signalIndex, a.arguments); -} - -QSignalEventGenerator::QSignalEventGenerator(QStateMachine *parent) - : QObject(parent) -{ -} - -/*! - \class QStateMachine::SignalEvent - \inmodule QtCore - - \brief The SignalEvent class represents a Qt signal event. - - \since 4.6 - \ingroup statemachine - - A signal event is generated by a QStateMachine in response to a Qt - signal. The QSignalTransition class provides a transition associated with a - signal event. QStateMachine::SignalEvent is part of \l{The State Machine Framework}. - - The sender() function returns the object that generated the signal. The - signalIndex() function returns the index of the signal. The arguments() - function returns the arguments of the signal. - - \sa QSignalTransition -*/ - -/*! - \internal - - Constructs a new SignalEvent object with the given \a sender, \a - signalIndex and \a arguments. -*/ -QStateMachine::SignalEvent::SignalEvent(QObject *sender, int signalIndex, - const QList &arguments) - : QEvent(QEvent::StateMachineSignal), m_sender(sender), - m_signalIndex(signalIndex), m_arguments(arguments) -{ -} - -/*! - Destroys this SignalEvent. -*/ -QStateMachine::SignalEvent::~SignalEvent() -{ -} - -/*! - \fn QStateMachine::SignalEvent::sender() const - - Returns the object that emitted the signal. - - \sa QObject::sender() -*/ - -/*! - \fn QStateMachine::SignalEvent::signalIndex() const - - Returns the index of the signal. - - \sa QMetaObject::indexOfSignal(), QMetaObject::method() -*/ - -/*! - \fn QStateMachine::SignalEvent::arguments() const - - Returns the arguments of the signal. -*/ - - -/*! - \class QStateMachine::WrappedEvent - \inmodule QtCore - - \brief The WrappedEvent class inherits QEvent and holds a clone of an event associated with a QObject. - - \since 4.6 - \ingroup statemachine - - A wrapped event is generated by a QStateMachine in response to a Qt - event. The QEventTransition class provides a transition associated with a - such an event. QStateMachine::WrappedEvent is part of \l{The State Machine - Framework}. - - The object() function returns the object that generated the event. The - event() function returns a clone of the original event. - - \sa QEventTransition -*/ - -/*! - \internal - - Constructs a new WrappedEvent object with the given \a object - and \a event. - - The WrappedEvent object takes ownership of \a event. -*/ -QStateMachine::WrappedEvent::WrappedEvent(QObject *object, QEvent *event) - : QEvent(QEvent::StateMachineWrapped), m_object(object), m_event(event) -{ -} - -/*! - Destroys this WrappedEvent. -*/ -QStateMachine::WrappedEvent::~WrappedEvent() -{ - delete m_event; -} - -/*! - \fn QStateMachine::WrappedEvent::object() const - - Returns the object that the event is associated with. -*/ - -/*! - \fn QStateMachine::WrappedEvent::event() const - - Returns a clone of the original event. -*/ - -/*! - \fn QStateMachine::runningChanged(bool running) - \since 5.4 - - This signal is emitted when the running property is changed with \a running as argument. - - \sa QStateMachine::running -*/ - -/*! - \fn QStateMachine::postDelayedEvent(QEvent *event, std::chrono::milliseconds delay) - \since 5.15 - \overload - \threadsafe - - Posts the given \a event for processing by this state machine, with the - given \a delay in milliseconds. Returns an identifier associated with the - delayed event, or -1 if the event could not be posted. - - This function returns immediately. When the delay has expired, the event - will be added to the state machine's event queue for processing. The state - machine takes ownership of the event and deletes it once it has been - processed. - - You can only post events when the state machine is running. - - \sa cancelDelayedEvent(), postEvent() -*/ - -QT_END_NAMESPACE - -#include "qstatemachine.moc" -#include "moc_qstatemachine.cpp" diff --git a/src/corelib/statemachine/qstatemachine.h b/src/corelib/statemachine/qstatemachine.h deleted file mode 100644 index b3c87a959b..0000000000 --- a/src/corelib/statemachine/qstatemachine.h +++ /dev/null @@ -1,199 +0,0 @@ -/**************************************************************************** -** -** 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_H -#define QSTATEMACHINE_H - -#include - -#include -#include -#include -#include -#include - -#if __has_include() -# include -#endif - -QT_REQUIRE_CONFIG(statemachine); - -QT_BEGIN_NAMESPACE - -class QStateMachinePrivate; -class QAbstractAnimation; -class Q_CORE_EXPORT QStateMachine : public QState -{ - Q_OBJECT - Q_PROPERTY(QString errorString READ errorString) - Q_PROPERTY(QState::RestorePolicy globalRestorePolicy READ globalRestorePolicy WRITE setGlobalRestorePolicy) - Q_PROPERTY(bool running READ isRunning WRITE setRunning NOTIFY runningChanged) -#if QT_CONFIG(animation) - Q_PROPERTY(bool animated READ isAnimated WRITE setAnimated) -#endif -public: - class Q_CORE_EXPORT SignalEvent : public QEvent - { - public: - SignalEvent(QObject *sender, int signalIndex, - const QList &arguments); - ~SignalEvent(); - - inline QObject *sender() const { return m_sender; } - inline int signalIndex() const { return m_signalIndex; } - inline QList arguments() const { return m_arguments; } - - private: - QObject *m_sender; - int m_signalIndex; - QList m_arguments; - - friend class QSignalTransitionPrivate; - }; - - class Q_CORE_EXPORT WrappedEvent : public QEvent - { - public: - WrappedEvent(QObject *object, QEvent *event); - ~WrappedEvent(); - - inline QObject *object() const { return m_object; } - inline QEvent *event() const { return m_event; } - - private: - QObject *m_object; - QEvent *m_event; - }; - - enum EventPriority { - NormalPriority, - HighPriority - }; - - enum Error { - NoError, - NoInitialStateError, - NoDefaultStateInHistoryStateError, - NoCommonAncestorForTransitionError, - StateMachineChildModeSetToParallelError - }; - - explicit QStateMachine(QObject *parent = nullptr); - explicit QStateMachine(QState::ChildMode childMode, QObject *parent = nullptr); - ~QStateMachine(); - - void addState(QAbstractState *state); - void removeState(QAbstractState *state); - - Error error() const; - QString errorString() const; - void clearError(); - - bool isRunning() const; - -#if QT_CONFIG(animation) - bool isAnimated() const; - void setAnimated(bool enabled); - - void addDefaultAnimation(QAbstractAnimation *animation); - QList defaultAnimations() const; - void removeDefaultAnimation(QAbstractAnimation *animation); -#endif // animation - - QState::RestorePolicy globalRestorePolicy() const; - void setGlobalRestorePolicy(QState::RestorePolicy restorePolicy); - - void postEvent(QEvent *event, EventPriority priority = NormalPriority); - int postDelayedEvent(QEvent *event, int delay); - bool cancelDelayedEvent(int id); - - QSet configuration() const; - -#if QT_CONFIG(qeventtransition) - bool eventFilter(QObject *watched, QEvent *event) override; -#endif - -#if __has_include() || defined(Q_QDOC) - int postDelayedEvent(QEvent *event, std::chrono::milliseconds delay) - { - return postDelayedEvent(event, int(delay.count())); - } -#endif - -public Q_SLOTS: - void start(); - void stop(); - void setRunning(bool running); - -Q_SIGNALS: - void started(QPrivateSignal); - void stopped(QPrivateSignal); - void runningChanged(bool running); - - -protected: - void onEntry(QEvent *event) override; - void onExit(QEvent *event) override; - - virtual void beginSelectTransitions(QEvent *event); - virtual void endSelectTransitions(QEvent *event); - - virtual void beginMicrostep(QEvent *event); - virtual void endMicrostep(QEvent *event); - - bool event(QEvent *e) override; - -protected: - QStateMachine(QStateMachinePrivate &dd, QObject *parent); - -private: - Q_DISABLE_COPY(QStateMachine) - Q_DECLARE_PRIVATE(QStateMachine) - Q_PRIVATE_SLOT(d_func(), void _q_start()) - Q_PRIVATE_SLOT(d_func(), void _q_process()) -#if QT_CONFIG(animation) - Q_PRIVATE_SLOT(d_func(), void _q_animationFinished()) -#endif - Q_PRIVATE_SLOT(d_func(), void _q_startDelayedEventTimer(int, int)) - Q_PRIVATE_SLOT(d_func(), void _q_killDelayedEventTimer(int, int)) -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/corelib/statemachine/qstatemachine_p.h b/src/corelib/statemachine/qstatemachine_p.h deleted file mode 100644 index d73313570a..0000000000 --- a/src/corelib/statemachine/qstatemachine_p.h +++ /dev/null @@ -1,333 +0,0 @@ -/**************************************************************************** -** -** 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 - -QT_REQUIRE_CONFIG(statemachine); - -QT_BEGIN_NAMESPACE - -class QEvent; -#if QT_CONFIG(qeventtransition) -class QEventTransition; -#endif -class QSignalEventGenerator; -class QSignalTransition; -class QAbstractState; -class QAbstractTransition; -class QFinalState; -class QHistoryState; -class QState; - -#if QT_CONFIG(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() : nullptr; } - - QState *findLCA(const QList &states, bool onlyCompound = false); - QState *findLCCA(const QList &states); - - 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(); -#if QT_CONFIG(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 -#if QT_CONFIG(animation) - , const QList &selectedAnimations -#endif - ); - QList computeEntrySet(const QList &enabledTransitions, - QSet &statesForDefaultEntry, CalculationCache *cache); - QAbstractState *getTransitionDomain(QAbstractTransition *t, - const QList &effectiveTargetStates, - CalculationCache *cache); - 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(); -#if QT_CONFIG(qeventtransition) - 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; - friend size_t qHash(const RestorableId &key, size_t seed) - noexcept(noexcept(qHash(std::declval()))) - { return qHash(qMakePair(key.obj, key.prop), seed); } - friend bool operator==(const RestorableId &lhs, const RestorableId &rhs) noexcept - { return lhs.obj == rhs.obj && lhs.prop == rhs.prop; } - friend bool operator!=(const RestorableId &lhs, const RestorableId &rhs) noexcept - { return !operator==(lhs, rhs); } - public: - explicit RestorableId(QObject *o, QByteArray p) noexcept : guard(o), obj(o), prop(std::move(p)) {} - QObject *object() const noexcept { return guard; } - QByteArray propertyName() const noexcept { 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); - QList 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; - -#if QT_CONFIG(animation) - bool animated; - - struct InitializeAnimationResult { - QList handledAnimations; - QList localResetEndValues; - - void swap(InitializeAnimationResult &other) noexcept - { - 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 // animation - - QSignalEventGenerator *signalEventGenerator; - - QHash> connections; - QMutex connectionsMutex; -#if QT_CONFIG(qeventtransition) - QHash > qobjectEvents; -#endif - QFreeList delayedEventIdFreeList; - struct DelayedEvent { - QEvent *event; - int timerId; - DelayedEvent(QEvent *e, int tid) - : event(e), timerId(tid) {} - DelayedEvent() - : event(nullptr), timerId(0) {} - }; - QHash delayedEvents; - QHash timerIdToDelayedEventId; - QMutex delayedEventsMutex; - - typedef QEvent* (*f_cloneEvent)(QEvent*); - struct Handler { - f_cloneEvent cloneEvent; - }; - - static const Handler *handler; -}; -#if QT_CONFIG(animation) -Q_DECLARE_SHARED(QStateMachinePrivate::InitializeAnimationResult) -#endif - -Q_CORE_EXPORT const QStateMachinePrivate::Handler *qcoreStateMachineHandler(); - -QT_END_NAMESPACE - -#endif diff --git a/src/corelib/statemachine/statemachine.pri b/src/corelib/statemachine/statemachine.pri deleted file mode 100644 index ee701ebc37..0000000000 --- a/src/corelib/statemachine/statemachine.pri +++ /dev/null @@ -1,33 +0,0 @@ -!qtConfig(statemachine): return() - -HEADERS += $$PWD/qstatemachine.h \ - $$PWD/qstatemachine_p.h \ - $$PWD/qsignaleventgenerator_p.h \ - $$PWD/qabstractstate.h \ - $$PWD/qabstractstate_p.h \ - $$PWD/qstate.h \ - $$PWD/qstate_p.h \ - $$PWD/qfinalstate.h \ - $$PWD/qfinalstate_p.h \ - $$PWD/qhistorystate.h \ - $$PWD/qhistorystate_p.h \ - $$PWD/qabstracttransition.h \ - $$PWD/qabstracttransition_p.h \ - $$PWD/qsignaltransition.h \ - $$PWD/qsignaltransition_p.h - -SOURCES += $$PWD/qstatemachine.cpp \ - $$PWD/qabstractstate.cpp \ - $$PWD/qstate.cpp \ - $$PWD/qfinalstate.cpp \ - $$PWD/qhistorystate.cpp \ - $$PWD/qabstracttransition.cpp \ - $$PWD/qsignaltransition.cpp - -qtConfig(qeventtransition) { - HEADERS += \ - $$PWD/qeventtransition.h \ - $$PWD/qeventtransition_p.h - SOURCES += \ - $$PWD/qeventtransition.cpp -} -- cgit v1.2.3