18#include <config-kdsme.h>
20#include "rep_debuginterface_source.h"
24#include <QScxmlStateMachine>
25#include <private/qscxmlstatemachineinfo_p.h>
28using namespace DebugInterface;
32StateId makeStateId(QScxmlStateMachineInfo::StateId stateId)
34 return StateId {
static_cast<quint64
>(stateId) };
36TransitionId makeTransitionId(QScxmlStateMachineInfo::TransitionId transitionId)
38 return TransitionId {
static_cast<quint64
>(transitionId) };
40StateType makeStateType(QScxmlStateMachineInfo::StateType stateType)
43 case QScxmlStateMachineInfo::InvalidState:
45 case QScxmlStateMachineInfo::NormalState:
47 case QScxmlStateMachineInfo::ParallelState:
49 case QScxmlStateMachineInfo::FinalState:
51 case QScxmlStateMachineInfo::ShallowHistoryState:
53 case QScxmlStateMachineInfo::DeepHistoryState:
62class QScxmlDebugInterfaceSource::Private :
public DebugInterfaceSource
67 explicit Private(QObject *parent =
nullptr);
69 QScxmlStateMachine *qScxmlStateMachine()
const;
70 void setQScxmlStateMachine(QScxmlStateMachine *machine);
73 void stateEntered(QScxmlStateMachineInfo::StateId state);
74 void stateExited(QScxmlStateMachineInfo::StateId state);
75 void handleStateConfigurationChanged();
76 void handleTransitionTriggered(QScxmlStateMachineInfo::TransitionId);
78 void updateStartStop();
81 void repopulateGraph()
override;
84 void addState(QScxmlStateMachineInfo::StateId state);
85 void addTransition(QScxmlStateMachineInfo::TransitionId transition);
87 QString labelForState(QScxmlStateMachineInfo::StateId state)
const
90 if (state == QScxmlStateMachineInfo::InvalidStateId) {
91 return m_info->stateMachine()->name();
94 return QStringLiteral(
"%1 (%2)").arg(m_info->stateName(state)).arg(state);
97 QString labelForTransition(QScxmlStateMachineInfo::TransitionId transition)
const
99 if (transition == QScxmlStateMachineInfo::InvalidTransitionId) {
103 auto events = m_info->transitionEvents(transition);
104 if (events.empty()) {
109 return QStringLiteral(
"%1 (%2)").arg(events.first()).arg(transition);
112 QScopedPointer<QScxmlStateMachineInfo> m_info;
113 QSet<QScxmlStateMachineInfo::StateId> m_recursionGuard;
114 QSet<QScxmlStateMachineInfo::TransitionId> m_recursionGuardForTransition;
115 QVector<QScxmlStateMachineInfo::StateId> m_lastStateConfig;
129 return d->qScxmlStateMachine();
134 d->setQScxmlStateMachine(machine);
142QScxmlDebugInterfaceSource::Private::Private(QObject *parent)
143 : DebugInterfaceSource(parent)
150void QScxmlDebugInterfaceSource::Private::repopulateGraph()
152 Q_EMIT aboutToRepopulateGraph();
158 addState(QScxmlStateMachineInfo::InvalidStateId);
160 const auto states = m_info->allStates();
161 for (
auto stateId : states) {
165 const auto transitions = m_info->allTransitions();
166 for (
auto transition : transitions) {
167 addTransition(transition);
170 m_recursionGuard.clear();
171 m_recursionGuardForTransition.clear();
174 Q_EMIT graphRepopulated();
177 handleStateConfigurationChanged();
180QScxmlStateMachine *QScxmlDebugInterfaceSource::Private::qScxmlStateMachine()
const
182 return m_info ? m_info->stateMachine() :
nullptr;
185void QScxmlDebugInterfaceSource::Private::setQScxmlStateMachine(QScxmlStateMachine *machine)
191 handleStateConfigurationChanged();
193 m_info.reset(machine ?
new QScxmlStateMachineInfo(machine) : nullptr);
197 connect(m_info.data(), &QScxmlStateMachineInfo::statesEntered,
this,
198 [
this](
const QVector<QScxmlStateMachineInfo::StateId> &states) {
200 if (!states.isEmpty()) {
201 stateEntered(states.first());
204 connect(m_info.data(), &QScxmlStateMachineInfo::statesExited,
this,
205 [
this](
const QVector<QScxmlStateMachineInfo::StateId> &states) {
207 if (!states.isEmpty()) {
208 stateExited(states.first());
211 connect(m_info.data(), &QScxmlStateMachineInfo::transitionsTriggered,
212 this, [
this](
const QVector<QScxmlStateMachineInfo::TransitionId> &transitions) {
214 if (!transitions.isEmpty()) {
215 handleTransitionTriggered(transitions.first());
223void QScxmlDebugInterfaceSource::Private::handleTransitionTriggered(QScxmlStateMachineInfo::TransitionId transition)
225 Q_EMIT transitionTriggered(makeTransitionId(transition), labelForTransition(transition));
228void QScxmlDebugInterfaceSource::Private::stateEntered(QScxmlStateMachineInfo::StateId state)
230 Q_EMIT message(tr(
"State entered: %1").arg(labelForState(state)));
231 handleStateConfigurationChanged();
234void QScxmlDebugInterfaceSource::Private::stateExited(QScxmlStateMachineInfo::StateId state)
236 Q_EMIT message(tr(
"State exited: %1").arg(labelForState(state)));
237 handleStateConfigurationChanged();
240void QScxmlDebugInterfaceSource::Private::handleStateConfigurationChanged()
242 QVector<QScxmlStateMachineInfo::StateId> newConfig;
244 newConfig = m_info->configuration();
247 if (newConfig == m_lastStateConfig) {
250 m_lastStateConfig = newConfig;
253 config.reserve(newConfig.size());
254 for (
auto state : qAsConst(newConfig)) {
255 config << makeStateId(state);
258 Q_EMIT stateConfigurationChanged(config);
261void QScxmlDebugInterfaceSource::Private::addState(QScxmlStateMachineInfo::StateId state)
263 if (m_recursionGuard.contains(state)) {
267 m_recursionGuard.insert(state);
269 auto parentState = m_info->stateParent(state);
270 addState(parentState);
272 const auto children = m_info->stateChildren(state);
273 const bool hasChildren = !children.isEmpty();
277 const auto parentInitialTransition = m_info->initialTransition(parentState);
278 if (parentInitialTransition != QScxmlStateMachineInfo::InvalidTransitionId) {
279 m_recursionGuardForTransition.insert(parentInitialTransition);
282 const auto parentInitialTransitionTargets = m_info->transitionTargets(parentInitialTransition);
283 Q_ASSERT(parentInitialTransitionTargets.size() <= 1);
284 const auto parentInitialState = parentInitialTransitionTargets.value(0);
285 const bool connectToInitial = parentInitialState == state;
286 Q_EMIT stateAdded(makeStateId(state), makeStateId(parentState),
287 hasChildren, labelForState(state),
288 makeStateType(m_info->stateType(state)), connectToInitial);
291 Q_FOREACH (
int child, m_info->stateChildren(state)) {
296void QScxmlDebugInterfaceSource::Private::addTransition(QScxmlStateMachineInfo::TransitionId transition)
298 if (m_recursionGuardForTransition.contains(transition)) {
302 m_recursionGuardForTransition.insert(transition);
304 const auto sourceState = m_info->transitionSource(transition);
305 const auto targetStates = m_info->transitionTargets(transition);
306 addState(sourceState);
307 for (
int targetState : targetStates) {
308 addState(targetState);
311 for (
int targetState : targetStates) {
312 Q_EMIT transitionAdded(makeTransitionId(transition), makeStateId(sourceState),
313 makeStateId(targetState), labelForTransition(transition));
317void QScxmlDebugInterfaceSource::Private::updateStartStop()
319 Q_EMIT statusChanged(qScxmlStateMachine() !=
nullptr, qScxmlStateMachine() && qScxmlStateMachine()->isRunning());
322void QScxmlDebugInterfaceSource::Private::toggleRunning()
324 if (!qScxmlStateMachine()) {
328 if (qScxmlStateMachine()->isRunning()) {
329 qScxmlStateMachine()->stop();
331 qScxmlStateMachine()->start();
335#include "qscxmldebuginterfacesource.moc"
virtual ~QScxmlDebugInterfaceSource()
QScxmlDebugInterfaceSource()
QObject * remoteObjectSource() const
void setQScxmlStateMachine(QScxmlStateMachine *machine)
QScxmlStateMachine * qScxmlStateMachine() const
QList< StateId > StateMachineConfiguration