Question
I am currently working on a application using Qt state machine framework, my objective is to associate a single transition with multiple source states. The rationale for doing it is the signal causing the transition is independent of the source state, hence instead of multiple transitions (one for each source state) I thought it would be better to have one. I am facing issues in acheiving the above mentioned through Qt.Details are demonstrated below with a test state machine. (Below mentioned is an hypothetical state machine but I can aslo give some real world examples for such a use case). Please suggest some effective ways for acheiving the mentioned objective.
Code snippet where the problem lies
m_s1.addTransition(&m_Trans); // Adding transition to state S1
m_s2.addTransition(&m_Trans); // Adding the same transition to state S2
// As per Qt docs, it seems the ownership of thr transition will be transferred to s2 which is what is causing the problem.
CState.hpp
class CState: public QState
{
public:
/** Constructor */
CState(std::string a_pStateName)
:QState(nullptr),
m_pStateName(a_pStateName)
{
}
/** Overriding on entry */
virtual void onEntry(QEvent *a_pEvent) Q_DECL_OVERRIDE
{
(void) a_pEvent;
printf("State entry %s\n",m_pStateName.c_str());
}
~CState() {}
CState() {}
private:
std::string m_pStateName;
};
CTestMachine.hpp
class CTestStateMachine: public QObject
{
Q_OBJECT
public:
CTestStateMachine();
~CTestStateMachine() {};
private:
QSignalTransition m_Trans;
CState m_s1;
CState m_s2;
CState m_s3;
QStateMachine m_TestMachine;
QTimer m_Timer;
signals:
void SourceIndependentSignal();
public slots:
void TimetoInvokeTrans();
};
CTestMachine.cpp
#include <stdio.h>
#include <iostream>
#include <string>
using namespace std;
#include <QObject>
#include <QCoreApplication>
#include <QStateMachine>
#include <QState>
#include <QSignalTransition>
#include <QTimer>
#include "CState.hpp"
#include "CTestStateMachine.hpp"
void CTestStateMachine::TimetoInvokeTrans()
{
printf("Emitting source independent signal\n");
emit SourceIndependentSignal();
}
CTestStateMachine::CTestStateMachine():
m_Trans(this, SIGNAL(SourceIndependentSignal())),
m_s1("s1"),
m_s2("s2"),
m_s3("s3")
{
/* Setup state machine */
m_Trans.setTargetState(&m_s3);
m_s1.addTransition(&m_Trans);
m_s2.addTransition(&m_Trans);
m_TestMachine.addState(&m_s1);
m_TestMachine.addState(&m_s2);
m_TestMachine.addState(&m_s3);
m_TestMachine.setInitialState(&m_s1);
m_TestMachine.start();
printf("Started state machine\n");
/* Trigger timer to make transitions */
connect(&m_Timer, SIGNAL(timeout()), this, SLOT(TimetoInvokeTrans()));
m_Timer.start(1000);
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
CTestStateMachine TestMachine;
return a.exec();
}