#include #include #include #include //#define ENABLE_WORKOROUND #define VERBOSE if(1) qDebug() << #if QT_VERSION == 0x050000 #include "5.0.0/QtCore/private/qsignaltransition_p.h" #include "5.0.0/QtCore/private/qstatemachine_p.h" #else #include "private/qsignaltransition_p.h" #include "private/qstatemachine_p.h" #endif //--------------------------------------------------------- struct ms : QThread { static void sleep(int milliSec) { QThread::msleep(milliSec); } }; //--------------------------------------------------------- class Writer : public QObject { Q_OBJECT public: Writer(int ms) : duration(ms), aborted(false) {} void write() { VERBOSE "writing ..."; ms::sleep(duration); VERBOSE "writing done"; emit done(); } int duration; bool aborted; public slots: void abort() { VERBOSE "Writer abort()"; aborted = true; emit done(); } signals: void done(); }; //--------------------------------------------------------- class WriteTransition : public QSignalTransition { public: WriteTransition(QObject* sender, const char* signal, Writer* w) : QSignalTransition(sender, signal), writer(w) {} void onTransition(QEvent*) { writer->write(); } Writer* writer; }; //--------------------------------------------------------- class WritingDoneTransition : public QSignalTransition { public: WritingDoneTransition(QObject* sender, const char* signal) : QSignalTransition(sender, signal) { } bool eventTest(QEvent* event) { if (event->type() == QEvent::StateMachineSignal) { bool ok = QSignalTransition::eventTest(event); VERBOSE "eventTest returns: " << (ok ? "true" : "false"); return ok; } return QSignalTransition::eventTest(event); } }; //------------------------------------------------------------------------------------------------- class TransitionSignalTest: public QObject { Q_OBJECT public: TransitionSignalTest() : writer(200) {} void initialize() { QState* parent = &stateMachine; // states QState* state_started = new QState(parent); QState* state_writing = new QState(parent); QFinalState* state_done = new QFinalState(parent); // transitions WriteTransition* transition_write = new WriteTransition(state_started, SIGNAL(entered()), &writer); WritingDoneTransition* transition_done = new WritingDoneTransition(&writer, SIGNAL(done())); // chart stateMachine.setInitialState(state_started); state_started->addTransition(transition_write); transition_write->setTargetState(state_writing); state_writing->addTransition(transition_done); transition_done->setTargetState(state_done); // don't hang QTimer::singleShot(2000, &writer, SLOT(abort())); #ifdef ENABLE_WORKOROUND QStateMachinePrivate::get(&stateMachine)->registerSignalTransition(transition_done); #endif stateMachine.moveToThread(&stateMachineThread); stateMachineThread.start(); connect(state_started, SIGNAL(entered()), this, SLOT(stateStarted())); connect(state_writing, SIGNAL(entered()), this, SLOT(stateWriting())); connect(state_done, SIGNAL(entered()), this, SLOT(stateDone())); stateMachine.start(); } public slots: void stateStarted() { VERBOSE "-- State: Started"; } void stateWriting() { VERBOSE "-- State: Writing"; } void stateDone() { VERBOSE "-- State: Done"; } private slots: void writeTest() { initialize(); QEventLoop loop; QObject::connect(&stateMachine, SIGNAL(finished()), &loop, SLOT(quit())); loop.exec(); QVERIFY(!writer.aborted); } void cleanupTestCase() { stateMachineThread.quit(); stateMachineThread.wait(); } private: Writer writer; QThread stateMachineThread; QStateMachine stateMachine; }; //--------------------------------------------------------- QTEST_MAIN(TransitionSignalTest) #include "TransitionSignal.moc"