18#include <config-kdsme.h>
20#include "rep_debuginterface_source.h"
26#include <QAbstractTransition>
28#include <QHistoryState>
29#include <QSignalTransition>
30#include <QStateMachine>
33using namespace DebugInterface;
38StateId makeStateId(QAbstractState *state)
40 return StateId {
reinterpret_cast<quint64
>(state) };
42TransitionId makeTransitionId(QAbstractTransition *transition)
44 return TransitionId {
reinterpret_cast<quint64
>(transition) };
47QString labelForTransition(QAbstractTransition *transition)
49 const QString objectName = transition->objectName();
50 if (!objectName.isEmpty()) {
55 QSignalTransition *signalTransition = qobject_cast<QSignalTransition *>(transition);
56 if (signalTransition) {
57 return QString::fromLatin1(
"%1::%2").arg(
ObjectHelper::displayString(signalTransition->senderObject())).arg(QString::fromLatin1(signalTransition->signal().mid(1)));
65class QsmDebugInterfaceSource::Private :
public DebugInterfaceSource
70 explicit Private(QObject *parent =
nullptr);
72 void addState(QAbstractState *state);
73 void addTransition(QAbstractTransition *transition);
75 QStateMachine *qStateMachine()
const;
76 void setQStateMachine(QStateMachine *machine);
79 void stateEntered(QAbstractState *state);
80 void stateExited(QAbstractState *state);
81 void handleStateConfigurationChanged();
82 void handleTransitionTriggered(QAbstractTransition *);
84 void updateStartStop();
87 void repopulateGraph()
override;
90 void updateStateItems();
92 bool mayAddState(QAbstractState *state);
95 QSet<QAbstractState *> m_recursionGuard;
96 QSet<QAbstractState *> m_lastStateConfig;
110 return d->qStateMachine();
115 d->setQStateMachine(machine);
123QsmDebugInterfaceSource::Private::Private(QObject *parent)
124 : DebugInterfaceSource(parent)
129 connect(m_stateMachineWatcher, SIGNAL(stateEntered(QAbstractState *)),
130 SLOT(stateEntered(QAbstractState *)));
131 connect(m_stateMachineWatcher, SIGNAL(stateExited(QAbstractState *)),
132 SLOT(stateExited(QAbstractState *)));
133 connect(m_stateMachineWatcher, SIGNAL(transitionTriggered(QAbstractTransition *)),
134 SLOT(handleTransitionTriggered(QAbstractTransition *)));
139void QsmDebugInterfaceSource::Private::repopulateGraph()
141 Q_EMIT aboutToRepopulateGraph();
145 addState(qStateMachine());
146 m_recursionGuard.clear();
148 Q_EMIT graphRepopulated();
151 handleStateConfigurationChanged();
154QStateMachine *QsmDebugInterfaceSource::Private::qStateMachine()
const
156 return m_stateMachineWatcher->watchedStateMachine();
159bool QsmDebugInterfaceSource::Private::mayAddState(QAbstractState *state)
165 if (m_recursionGuard.contains(state)) {
171void QsmDebugInterfaceSource::Private::setQStateMachine(QStateMachine *machine)
173 QStateMachine *oldMachine = qStateMachine();
175 disconnect(oldMachine, SIGNAL(started()),
this, SLOT(updateStartStop()));
176 disconnect(oldMachine, SIGNAL(stopped()),
this, SLOT(updateStartStop()));
177 disconnect(oldMachine, SIGNAL(finished()),
this, SLOT(updateStartStop()));
181 handleStateConfigurationChanged();
183 m_stateMachineWatcher->setWatchedStateMachine(machine);
187 connect(machine, SIGNAL(started()),
this, SLOT(updateStartStop()));
188 connect(machine, SIGNAL(stopped()),
this, SLOT(updateStartStop()));
189 connect(machine, SIGNAL(finished()),
this, SLOT(updateStartStop()));
194void QsmDebugInterfaceSource::Private::handleTransitionTriggered(QAbstractTransition *transition)
199void QsmDebugInterfaceSource::Private::stateEntered(QAbstractState *state)
202 handleStateConfigurationChanged();
205void QsmDebugInterfaceSource::Private::stateExited(QAbstractState *state)
208 handleStateConfigurationChanged();
211void QsmDebugInterfaceSource::Private::handleStateConfigurationChanged()
213 QSet<QAbstractState *> newConfig;
214 if (qStateMachine()) {
215 newConfig = qStateMachine()->configuration();
218 if (newConfig == m_lastStateConfig) {
221 m_lastStateConfig = newConfig;
224 config.reserve(newConfig.size());
225 for (QAbstractState *state : qAsConst(newConfig)) {
226 config << makeStateId(state);
229 Q_EMIT stateConfigurationChanged(config);
232void QsmDebugInterfaceSource::Private::addState(QAbstractState *state)
237 if (!mayAddState(state)) {
241 Q_ASSERT(!m_recursionGuard.contains(state));
242 m_recursionGuard.insert(state);
244 QState *parentState = state->parentState();
246 addState(parentState);
249 const bool hasChildren = state->findChild<QAbstractState *>();
253 const bool connectToInitial = parentState && parentState->initialState() == state;
255 if (qobject_cast<QFinalState *>(state)) {
257 }
else if (
auto historyState = qobject_cast<QHistoryState *>(state)) {
259 }
else if (qobject_cast<QStateMachine *>(state)) {
263 Q_EMIT stateAdded(makeStateId(state), makeStateId(parentState),
264 hasChildren, label, type, connectToInitial);
267 Q_FOREACH (
auto transition, state->findChildren<QAbstractTransition *>(QString(), Qt::FindDirectChildrenOnly)) {
268 addTransition(transition);
272 Q_FOREACH (
auto child, state->findChildren<QAbstractState *>(QString(), Qt::FindDirectChildrenOnly)) {
277void QsmDebugInterfaceSource::Private::addTransition(QAbstractTransition *transition)
279 QState *sourceState = transition->sourceState();
280 QAbstractState *targetState = transition->targetState();
281 addState(sourceState);
282 addState(targetState);
284 const QString label = labelForTransition(transition);
285 Q_EMIT transitionAdded(makeTransitionId(transition), makeStateId(sourceState),
286 makeStateId(targetState), label);
289void QsmDebugInterfaceSource::Private::updateStartStop()
291 Q_EMIT statusChanged(qStateMachine() !=
nullptr, qStateMachine() && qStateMachine()->isRunning());
294void QsmDebugInterfaceSource::Private::toggleRunning()
296 if (!qStateMachine()) {
300 if (qStateMachine()->isRunning()) {
301 qStateMachine()->stop();
303 qStateMachine()->start();
307#include "qsmdebuginterfacesource.moc"
void setQStateMachine(QStateMachine *machine)
QObject * remoteObjectSource() const
virtual ~QsmDebugInterfaceSource()
QsmDebugInterfaceSource()
QStateMachine * qStateMachine() const
QList< StateId > StateMachineConfiguration
KDSME_CORE_EXPORT QString displayString(const QObject *object, DisplayOption option=NoStrip)