Commit 03800dab authored by Emmanuel Promayon's avatar Emmanuel Promayon

Merge branch 'feature/asm-for-regression-test' into 'develop'

Feature/asm for regression test

See merge request !22
parents e01b24bb cf38c82b
......@@ -15,8 +15,9 @@ camitk_extension(ACTION_EXTENSION
CEP_NAME CEP_IMAGING
DESCRIPTION "This action features basic ITK image processing filters"
DEFINES COMPILE_ITKFILTER_API
AUTO_TEST
ENABLE_AUTO_TEST
TEST_FILES bassin.msh BigEndian.hdr BigEndian.img BigEndianCompressed1.hdr BigEndianCompressed1.img biorad.pic brain.mha cthead1.lsm LittleEndian1.hdr LittleEndian1.img LittleEndianCompressed1.hdr LittleEndianCompressed1.img LittleEndianZ1.hdr mini-complex-slow1.nrrd mini-ten-nomask-slow1.nrrd mini-vector-slow1.nrrd ramp1.gipl
ENABLE_INTEGRATION_TEST
)
# Test failure due to ITK exception
......@@ -37,3 +38,9 @@ set_tests_properties("action-itkfilters-level1-8" PROPERTIES WILL_FAIL true)
# camitk-testcomponents aborted by std exception: /usr/include/ITK-4.10/itkRecursiveSeparableImageFilter.hxx:245:
# itk::ERROR: RecursiveGaussianImageFilter(0x55f942cacac0): The number of pixels along direction 2 is less than 4. This filter requires a minimum of four pixels along the dimension to be processed.
set_tests_properties("action-itkfilters-level1-14" PROPERTIES WILL_FAIL true)
# Tests fail due to OpenGL crashing when used inside a VM
# As the test can be run directly on a "real" desktop, add the test but flag it with WILL_FAIL
if(WIN32)
set_tests_properties(action-itkfilters-integration-test PROPERTIES WILL_FAIL true)
endif()
This diff is collapsed.
This diff is collapsed.
......@@ -4,6 +4,6 @@ camitk_extension( ACTION_EXTENSION
CEP_NAME CEP_IMAGING
CXX_FLAGS "-w"
DESCRIPTION "This action features basic ITK image processing segmentation algorithms"
AUTO_TEST
ENABLE_AUTO_TEST
TEST_FILES Mesh.off BigEndian.hdr BigEndian.img BigEndianCompressed1.hdr BigEndianCompressed1.img biorad.pic brain.mha cthead1.lsm LittleEndian1.hdr LittleEndian1.img LittleEndianCompressed1.hdr LittleEndianCompressed1.img LittleEndianZ1.hdr mini-complex-slow1.nrrd mini-ten-nomask-slow1.nrrd mini-vector-slow1.nrrd ramp1.gipl
)
......@@ -3,6 +3,6 @@ camitk_extension(COMPONENT_EXTENSION
CEP_NAME CEP_IMAGING
DESCRIPTION "This allows one to read a single DICOM image file (.dcm) using the library GDCM 2.2.x"
INSTALL_ALL_HEADERS
AUTO_TEST
ENABLE_AUTO_TEST
)
......@@ -5,7 +5,7 @@ camitk_extension(COMPONENT_EXTENSION
CXX_FLAGS "-w"
DEFINES _SCL_SECURE_NO_WARNINGS # to remove Windows MSVC warnings
DESCRIPTION "This component allows CamiTK to handle basic ITK format images."
AUTO_TEST
ENABLE_AUTO_TEST
)
# Test failure due to ITK exception
......
......@@ -5,7 +5,7 @@ camitk_extension(ACTION_EXTENSION
NEEDS_XSD
CEP_NAME CEP_MODELING
DESCRIPTION "Feature PML actions which aims at displaying and manipulating structural information about a PML component."
AUTO_TEST
ENABLE_AUTO_TEST
TEST_FILES
TEST_FILES Mesh.off brain.mha diaphragm.pml truthcube.pml
)
......
......@@ -5,7 +5,7 @@ camitk_extension(COMPONENT_EXTENSION
CEP_NAME CEP_MODELING
DESCRIPTION "CamiTK component to manage a physical model."
DEFINES COMPILE_PML_COMPONENT_API
AUTO_TEST
ENABLE_AUTO_TEST
TEST_FILES diaphragm.pml truthcube.pml
)
......
# Call CamiTK CMake Macro to define the action
camitk_extension(ACTION_EXTENSION
DESCRIPTION "Manipulating Frames."
AUTO_TEST
ENABLE_AUTO_TEST
TEST_FILES brain.mha structured.vtk
)
......@@ -4,7 +4,7 @@ camitk_extension(ACTION_EXTENSION
NEEDS_ACTION_EXTENSION multipicking
CEP_NAME SDK
DESCRIPTION "Helps you to crop a volume to keep only an interesting subsample"
AUTO_TEST
ENABLE_AUTO_TEST
TEST_FILES Mesh.off brain.mha sinus.mhd
)
......
......@@ -2,7 +2,7 @@ camitk_extension(ACTION_EXTENSION
DEFINES COMPILE_LUT_ACTION_API
CEP_NAME SDK
DESCRIPTION "Displays the image look-up-table (lut)"
AUTO_TEST
ENABLE_AUTO_TEST
TEST_FILES scissors.obj brain.mha sinus.mhd
)
......
......@@ -2,6 +2,6 @@
camitk_extension(ACTION_EXTENSION
CEP_NAME SDK
DESCRIPTION "Re-sample image volumes"
AUTO_TEST
ENABLE_AUTO_TEST
TEST_FILES liver-smooth.obj brain.mha sinus.mhd
)
......@@ -3,7 +3,7 @@ camitk_extension(ACTION_EXTENSION
INSTALL_ALL_HEADERS
CEP_NAME SDK
DESCRIPTION "Action-multipicking allows one to make several pixel picking on an image component (volumic image)"
AUTO_TEST
ENABLE_AUTO_TEST
TEST_FILES structured.vtk brain.mha sinus.mhd
)
......
......@@ -3,6 +3,6 @@ camitk_extension(ACTION_EXTENSION
DEFINES COMPILE_PIXELCOLORCHANGER_ACTION_API
CEP_NAME SDK
DESCRIPTION "Allows changing the color of the image pixels"
AUTO_TEST
ENABLE_AUTO_TEST
TEST_FILES mixed_3D_beam.msh brain.mha sinus.mhd
)
......@@ -2,26 +2,22 @@ camitk_extension(ACTION_EXTENSION
DEFINES COMPILE_RECONSTRUCTION_ACTION_API
CEP_NAME SDK
DESCRIPTION "Use marching cube algorithm to create a surfacic mesh from a volumic image"
AUTO_TEST
ENABLE_AUTO_TEST
TEST_FILES sinus_skin.vtk brain.mha sinus.mhd
ENABLE_INTEGRATION_TEST
)
# Recursively update the shiboken path variable containing the CamiTK SDK tree structure
set(SHIBOKEN_CAMITK_SDK_PATH ${SHIBOKEN_CAMITK_SDK_PATH}:${CMAKE_CURRENT_SOURCE_DIR} CACHE INTERNAL "")
# add a specific test to run the action, save the output and compare it to expected
camitk_add_test_actionstatemachine(NAME action-reconstruction-functional-test
CAMITK_SCXML action-reconstruction-functional-test.xml
EXPECTED_OUTPUT_FILES action-reconstruction-output-test.vtk)
# On Ubuntu 16.04 LTS, the default VTK version is 6.2 not 6.3
# VTK6.2 has a bug when it saves vtk files: it does not save the proper VTK file format version
# These tests are disabled until Ubuntu LTS 18.04 is released (LTS 18.04 contains VTK 6.3)
if("${VTK_VERSION}" VERSION_LESS 6.3)
set_tests_properties(action-reconstruction-functional-test PROPERTIES WILL_FAIL true)
set_tests_properties(action-reconstruction-integration-test PROPERTIES WILL_FAIL true)
endif()
# Tests fail due to OpenGL crashing when used inside a VM
# As the test can be run directly on a "real" desktop, add the test but flag it with WILL_FAIL
if(WIN32)
set_tests_properties(action-reconstruction-functional-test PROPERTIES WILL_FAIL true)
set_tests_properties(action-reconstruction-integration-test PROPERTIES WILL_FAIL true)
endif()
<?xml version="1.0" encoding="UTF-8"?>
<scxml xmlns="http://camitk.imag.fr/3/smallScxml" initial="Initialize" xmlns:camitk="http://camitk.imag.fr/3/asm" xsi:schemaLocation="http://camitk.imag.fr/3/smallScxml/../resources/smallScxml.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<state id="Initialize">
<onentry>
......@@ -5,9 +6,9 @@
<camitk:description><![CDATA[This pipeline will process several actions on the input component(s): <br /> <ul><li>Open File</li><li>Reconstruction</li><li>Save</li>]]></camitk:description>
</camitk:onState>
</onentry>
<transition target="Action 1" event="Next"/>
<transition target="Open Input" event="Next"/>
</state>
<state id="Action 1">
<state id="Open Input">
<onentry>
<camitk:onState>
<camitk:description>Open data (component) from a given file</camitk:description>
......@@ -19,7 +20,7 @@
<camitk:parameter name="File name" value="" type="QString"/>
This should not appear.
-->
<camitk:parameter name="File Name" value="action-reconstruction-input.mha" type="QString"/>
<camitk:parameter name="File Name" value="input-1.mha" type="QString"/>
</camitk:parameters>
<camitk:parameters/>
<camitk:outputs>
......@@ -28,10 +29,10 @@
</camitk:action>
</camitk:onState>
</onentry>
<transition target="Action 2" event="Next"/>
<transition target="Initialize" event="Back"/>
<transition target="Apply Marching Cube" event="Next"/>
</state>
<state id="Action 2">
<state id="Apply Marching Cube">
<onentry>
<camitk:onState>
<camitk:description>&lt;br /> Marching cubes is a simple algorithm for creating a triangle mesh from an implicit function (one of the form f(x, y, z) = 0).&lt;br /> It works by iterating ("marching") over a uniform grid of cubes superimposed over a region of the function. If all 8 vertices of the cube are positive, or all 8 vertices are negative, the cube is entirely above or entirely below the surface and no triangles are emitted. Otherwise, the cube straddles the function and some triangles and vertices are generated. Since each vertex can either be positive or negative, there are technically 28 possible configurations, but many of these are equivalent to one another. &lt;br/> &lt;br/>This action uses this algorithm to build a 3D surfacic mesh of the input image.</camitk:description>
......@@ -50,13 +51,13 @@
<camitk:component name="image" type="ImageComponent"/>
</camitk:inputs>
<camitk:outputs>
<camitk:component name="action-reconstruction-output-test.vtk" type="MeshComponent"/>
<camitk:component name="output-1.vtk" type="MeshComponent"/>
</camitk:outputs>
</camitk:action>
</camitk:onState>
</onentry>
<transition target="Action 3" event="Next"/>
<transition target="Action 1" event="Back">
<transition target="Open Input" event="Back">
<transition target="Save Marching Cube Result as output-1.vtk" event="Next"/>
<onTransition>
<camitk:close>
<camitk:component name="image" type="ImageComponent"/>
......@@ -64,7 +65,7 @@
</onTransition>
</transition>
</state>
<state id="Action 3">
<state id="Save Marching Cube Result as output-1.vtk">
<onentry>
<camitk:onState>
<camitk:description>Save all the top-level of the selected components</camitk:description>
......@@ -72,20 +73,38 @@
<camitk:name>Save</camitk:name>
<camitk:parameters/>
<camitk:inputs>
<camitk:component name="action-reconstruction-output-test.vtk" type="MeshComponent"/>
<camitk:component name="output-1.vtk" type="MeshComponent"/>
</camitk:inputs>
</camitk:action>
</camitk:onState>
</onentry>
<transition target="Bye" event="Next"/>
<transition target="Action 2" event="Back">
<transition target="Apply Marching Cube" event="Back">
<onTransition>
<camitk:close>
<camitk:component name="action-reconstruction-output-test.vtk" type="MeshComponent"/>
<camitk:component name="output-1.vtk" type="MeshComponent"/>
</camitk:close>
</onTransition>
</transition>
<transition target="Close output-1.vtk" event="Next"/>
</state>
<state id="Close output-1.vtk">
<onentry>
<camitk:onState>
<camitk:description>Close the currently selected components</camitk:description>
<camitk:action>
<camitk:name>Close</camitk:name>
<camitk:parameters/>
<camitk:inputs>
<camitk:component name="output-1.vtk" type="MeshComponent"/>
</camitk:inputs>
</camitk:action>
</camitk:onState>
</onentry>
<transition target="Save Marching Cube Result as output-1.vtk" event="Back"/>
<transition target="Bye" event="Next"/>
</state>
<state id="Bye" final="true">
<onentry>
<camitk:onState>
......@@ -96,7 +115,7 @@
<onTransition>
<camitk:close>
<camitk:component name="image" type="ImageComponent"/>
<camitk:component name="action-reconstruction-output-test.vtk" type="MeshComponent"/>
<camitk:component name="output-1.vtk" type="MeshComponent"/>
</camitk:close>
</onTransition>
</transition>
......
# vtk DataFile Version 4.0
action-reconstruction-output-test.vtk
output-1.vtk
ASCII
DATASET POLYDATA
POINTS 1724 float
......
......@@ -3,7 +3,7 @@ camitk_extension(ACTION_EXTENSION
NEEDS_COMPONENT_EXTENSION vtkmesh
CEP_NAME SDK
DESCRIPTION "Allows one to reorient a volumic image."
AUTO_TEST
ENABLE_AUTO_TEST
TEST_FILES skull1.stl brain.mha sinus.mhd
)
......
camitk_extension(ACTION_EXTENSION
CEP_NAME SDK
DESCRIPTION "Display in 3D the component"
AUTO_TEST
ENABLE_AUTO_TEST
TEST_FILES bassin.msh brain.mha sinus.mhd
)
......
......@@ -3,7 +3,7 @@ camitk_extension(ACTION_EXTENSION
DEFINES COMPILE_VOLUME_RENDERING_ACTION_API
CEP_NAME SDK
DESCRIPTION "Use ray tracing to produce a 3D reprensation of the image"
AUTO_TEST
ENABLE_AUTO_TEST
TEST_FILES Mesh.off brain.mha sinus.mhd
)
......
......@@ -3,7 +3,7 @@ camitk_extension(ACTION_EXTENSION
INSTALL_ALL_HEADERS
DESCRIPTION "Default actions for image acquisition components"
CEP_NAME SDK
AUTO_TEST
ENABLE_AUTO_TEST
TEST_FILES bassin.msh brain.mha # this action extensions is difficult to auto test, just check it can be loaded
)
......@@ -2,7 +2,7 @@ camitk_extension(ACTION_EXTENSION
DEFINES COMPILE_BASIC_MESH_ACTION_API
CEP_NAME SDK
DESCRIPTION "Provides basic actions on meshes"
AUTO_TEST
ENABLE_AUTO_TEST
TEST_FILES brain.mha bassin.msh liver-smooth.obj Mesh.off robot.wrl scissors.obj simple.vtk sinus_skin.vtk sinus_skull.vtk skull1.stl structured.vtk pointcloud-with-data.vtk polydata-with-data.vtk cube-with-point-and-cell-data.vtk fieldfile.vtk check-with-color-pointdata.vtk plate-with-data.vtk female.vtk brainImageSmooth.vtk structuredgrid-with-data.vtk male.vtk cube-with-tensors.vtk imageBoundingBox.vtk binary-mesh-with-pointdata.vtk unstructured_binary_with_celldata.vtk
)
......
......@@ -2,7 +2,7 @@ camitk_extension(ACTION_EXTENSION
DEFINES COMPILE_BASIC_TOPOLOGY_ACTION_API
CEP_NAME SDK
DESCRIPTION "Helps building simple 3D objects"
AUTO_TEST
ENABLE_AUTO_TEST
TEST_FILES brain.mha bassin.msh head1.STL liver-smooth.obj Mesh.off mixed_3D_beam.msh robot.wrl scissors.obj simple.vtk sinus_skin.vtk sinus_skull.vtk skull1.stl structured.vtk pointcloud-with-data.vtk polydata-with-data.vtk
)
......
......@@ -5,7 +5,7 @@ camitk_extension(ACTION_EXTENSION
DESCRIPTION "Features some nice algorithms for mesh processing"
INCLUDE_DIRECTORIES ${CAMITK_INCLUDE_DIR}/components/vtkmesh
INSTALL_ALL_HEADERS
AUTO_TEST
ENABLE_AUTO_TEST
TEST_FILES brain.mha bassin.msh head1.STL liver-smooth.obj Mesh.off robot.wrl scissors.obj simple.vtk sinus_skin.vtk sinus_skull.vtk skull1.stl structured.vtk pointcloud-with-data.vtk polydata-with-data.vtk cube-with-point-and-cell-data.vtk fieldfile.vtk check-with-color-pointdata.vtk plate-with-data.vtk female.vtk brainImageSmooth.vtk structuredgrid-with-data.vtk male.vtk cube-with-tensors.vtk imageBoundingBox.vtk binary-mesh-with-pointdata.vtk unstructured_binary_with_celldata.vtk
)
......
......@@ -32,9 +32,11 @@
// -- Qt stuff
#include <QPushButton>
#include <QMainWindow>
#include <QMetaProperty>
#include <Log.h>
using namespace camitk;
// ------------- constructor -----------------
......@@ -43,7 +45,7 @@ ActionState::ActionState(QState* parent, QString name, QString description, QTex
this->name = name;
this->description = description;
this->logStream = logStream;
this->myAction = NULL;
this->myAction = nullptr;
this->myStateWidget = new ActionStateWidget(this);
}
......@@ -76,10 +78,10 @@ ActionStateWidget* ActionState::getWidget() {
}
// ------------- addActionTransition -----------------
ActionTransition* ActionState::addActionTransition(QString buttonText, QAbstractState* nextState, bool applyAction, QVector<Action::ApplyStatus> disableConditions) {
ActionTransition* ActionState::addActionTransition(QString transitionName, QAbstractState* nextState, bool applyAction, QVector<Action::ApplyStatus> disableConditions) {
QPushButton* button = myStateWidget->addTransitionButton(buttonText);
ActionTransition* transition = new ActionTransition(button, SIGNAL(clicked()), this, buttonText, applyAction, logStream);
QPushButton* button = myStateWidget->addTransitionButton(transitionName);
ActionTransition* transition = new ActionTransition(button, SIGNAL(clicked()), this, applyAction, logStream);
transition->setTargetState(nextState);
for (QVector<Action::ApplyStatus>::const_iterator it = disableConditions.begin();
......@@ -105,6 +107,10 @@ Action::ApplyStatus ActionState::applyAction() {
Action::ApplyStatus status(Action::TRIGGERED);
if (myAction != NULL) {
if (logStream != NULL) {
(*logStream) << "\t\t<applyAction>" << endl;
}
// apply the action
status = myAction->applyInPipeline();
......@@ -182,19 +188,23 @@ void ActionState::setPreviousActionStatus(camitk::Action::ApplyStatus status) {
}
}
// ------------- autoNextEntry -----------------
void ActionState::autoNextEntry() {
onEntry(new QEvent(QEvent::ApplicationStateChange));
}
// ------------- onEntry -----------------
void ActionState::onEntry ( QEvent* event ) {
if (logStream == NULL) {
return;
}
//-- log the start
startTime = new QTime();
startTime->start();
if (logStream != NULL) {
//-- log the start
startTime = new QTime();
startTime->start();
(*logStream) << "\t<state>" << endl;
(*logStream) << "\t\t<name>" << this->name << "</name>" << endl;
(*logStream) << "\t\t<startTime>" << startTime->toString("hh:mm:ss:zzz") << "</startTime>" << endl;
(*logStream) << "\t<state>" << endl;
(*logStream) << "\t\t<name>" << this->name << "</name>" << endl;
(*logStream) << "\t\t<startTime>" << startTime->toString("hh:mm:ss:zzz") << "</startTime>" << endl;
}
//-- set the parameters default values
if (myAction != NULL) {
......@@ -203,7 +213,6 @@ void ActionState::onEntry ( QEvent* event ) {
}
// log the parameters
(*logStream) << "\t\t<applyAction>" << endl;
(*logStream) << "\t\t\t<name>" << myAction->getName() << "</name>" << endl;
// Properties
int nbStaticProps = myAction->metaObject()->propertyCount();
......@@ -279,24 +288,20 @@ void ActionState::onEntry ( QEvent* event ) {
}
}
// ------------- autoNextExit -----------------
void ActionState::autoNextExit() {
onExit(new QEvent(QEvent::ApplicationStateChange));
}
// -------------onExit -----------------
void ActionState::onExit(QEvent* event) {
if (logStream == NULL) {
return;
if (logStream != NULL) {
QTime endTime = QTime::currentTime();
(*logStream) << "\t\t<!-- exiting " << this->name << " -->" << endl;
(*logStream) << "\t\t<endTime>" << endTime.toString("hh:mm:ss:zzz") << "</endTime>" << endl;
(*logStream) << "\t\t<timeEnlapsed unit='ms'>" << (startTime->elapsed()) << "</timeEnlapsed>" << endl;
(*logStream) << "\t</state>" << endl;
}
QTime endTime = QTime::currentTime();
(*logStream) << "\t\t<endTime>" << endTime.toString("hh:mm:ss:zzz") << "</endTime>" << endl;
(*logStream) << "\t\t<timeEnlapsed unit='ms'>" << (startTime->elapsed()) << "</timeEnlapsed>" << endl;
(*logStream) << "\t</state>" << endl;
}
// ------------- trigger -----------------
void ActionState::trigger() {
onEntry(nullptr);
applyAction();
onExit(nullptr);
}
// ------------- getInputComponents -----------------
......
......@@ -43,6 +43,7 @@
* @brief
* The state (in a state machine point of view) corresponding to the current processed action.
*
* By default an ActionState is not defined as being the initial state.
*/
class ActionState : public QState {
......@@ -69,30 +70,33 @@ public:
virtual camitk::Action::ApplyStatus applyAction();
/// Adds a possible transition from this action
ActionTransition* addActionTransition(QString buttonText, QAbstractState* nextState,
ActionTransition* addActionTransition(QString transitionName, QAbstractState* nextState,
bool applyAction = true, QVector<camitk::Action::ApplyStatus> disableConditions = QVector<camitk::Action::ApplyStatus>());
// get the whole action state widget (used by the ActionStateViewer)
ActionStateWidget* getWidget();
// set the status of previous action and modify description/possible action accordingly
void setPreviousActionStatus(camitk::Action::ApplyStatus status);
void setFinal();
/// get the names and type of all input components
const QMap<QString, QString>& getInputComponents();
/// get the names and type of all output components
const QMap<QString, QString>& getOutputComponents();
/// manually trigger the state
void trigger();
/// programmatically call the onEntry() method (used during autonext)
void autoNextEntry();
/// programmatically call the onExit() method (used during autonext)
void autoNextExit();
protected:
/// Reimplemented from QState
/// @{
virtual void onEntry ( QEvent* event );
virtual void onEntry(QEvent* event);
virtual void onExit ( QEvent* event );
virtual void onExit(QEvent* event);
///@}
/// Name of the state action (may not be the same as the action's name)
......@@ -136,6 +140,5 @@ protected:
/// Keep track of time...
QTime* startTime;
};
#endif // ACTIONSTATE_H
......@@ -120,52 +120,37 @@ ActionStateMachine::ActionStateMachine(int& argc, char** argv, QString inputFile
// ---------------------- destructor ----------------------------
ActionStateMachine::~ActionStateMachine() {
QTime endTime = QTime::currentTime();
(*logStream) << "\t<endTime>" << endTime.toString("hh:mm:ss:zzz") << "</endTime>" << endl;
(*logStream) << "\t<timeEnlapsed unit='ms'>" << (startTime->elapsed()) << "</timeEnlapsed>" << endl;
(*logStream) << "</application>" << endl;
logFile->close();
}
// ---------------------- autoNext ----------------------------
void ActionStateMachine::autoNext() {
ActionState* currentState;
ActionState* nextState;
void ActionStateMachine::autoNext() {
// if autonext is called, then this is an automatic test, there won't be any user to close the dialog
setProperty("Message Box Level", InterfaceLogger::NONE);
CAMITK_INFO(tr("Starting autonext..."))
// get the first initial state (there should only be one)
currentState = dynamic_cast<ActionState*>(machine.configuration().toList().first());
// machine.configuration() returns all the current state, the first on is the active state
ActionState* currentState = dynamic_cast<ActionState*>(machine.configuration().toList().first());
// loop until no more state is available
while (currentState) {
CAMITK_INFO(tr("Entering state \"%1\"").arg(currentState->getName()))
nextState = nullptr;
// get the next state by looking for the "Next" transition
foreach (QAbstractTransition* currentStateTransition, currentState->transitions()) {
ActionTransition* currentActionTransition = dynamic_cast<ActionTransition*>(currentStateTransition);
if (currentActionTransition->getButtonText() == "Next" || currentActionTransition->getButtonText() == "Quit") {
// "Next" or "Quit" is found, activate the transition
CAMITK_INFO(tr("Activating Transition \"%1\"").arg(currentActionTransition->getButtonText()))
currentActionTransition->onTransition(nullptr);
// update the next state to enter
nextState = dynamic_cast<ActionState*>(currentActionTransition->targetState());
while (currentState!=nullptr && currentState->transitions().size()>0) {
// look for the "Next" or "Quit" transition
auto it = currentState->transitions().begin();
bool foundNextState = false;
while (it!=currentState->transitions().end() && !foundNextState) { // && nextState==nullptr) {
// all transition in this state machine are ActionTransition instances...
ActionTransition* currentActionTransition = dynamic_cast<ActionTransition*>(*it);
//... in which we can look for the "Next" or "Quit" transition
if (currentActionTransition->isNamed("Next") || currentActionTransition->isNamed("Quit")) {
// activate the transition (simulate a click on the button)
currentActionTransition->autoNext(); // activating the "Quit" transition enter the final state, which make the state machine to emit the finished() signal
foundNextState = true;
}
++it;
}
// activate currentState
if (currentState) {
CAMITK_INFO(tr("Triggering state"))
currentState->trigger();
}
// next state
currentState = nextState;
}
CAMITK_INFO(tr("Quitting autonext and application"))
quit();
// get the new current active state
currentState = dynamic_cast<ActionState*>(machine.configuration().toList().first());
} while (currentState!=nullptr);
}
// ---------------------- initMainWindow ----------------------------
......@@ -253,7 +238,10 @@ QString ActionStateMachine::parseSCXMLTree() throw(AbortException) {
// Connect the end of the machine with the end of the application
QObject::connect(&machine, SIGNAL(finished()), QApplication::instance(), SLOT(quit()));
// and connect the about to quit with some final cleanup method (recommended instead using destructor to cleanup)
QObject::connect(this, SIGNAL(aboutToQuit()), this, SLOT(finished()));
// Ok, Actions and Wizard are created. We do not need the file any more.
// Clean up:
delete statesMap;
......@@ -261,6 +249,16 @@ QString ActionStateMachine::parseSCXMLTree() throw(AbortException) {
return applicationName;
}
// ---------------------- finished ----------------------------
void ActionStateMachine::finished() {
QTime endTime = QTime::currentTime();
(*logStream) << "\t<endTime>" << endTime.toString("hh:mm:ss:zzz") << "</endTime>" << endl;
(*logStream) << "\t<timeEnlapsed unit='ms'>" << (startTime->elapsed()) << "</timeEnlapsed>" << endl;
(*logStream) << "</application>" << endl;
logFile->close();
}
// ---------------------- createAllActionStates ----------------------------
void ActionStateMachine::createAllActionStates(QDomNodeList nodeList) throw(AbortException) {