From 4b6b6e03ab0e391ea1dff5772fc5487e64e2b09c Mon Sep 17 00:00:00 2001 From: Emmanuel Promayon Date: Mon, 19 Oct 2020 22:14:39 +0200 Subject: [PATCH 1/4] NEW asm application tests --- .../actionstatemachine/CMakeLists.txt | 28 ++++++++++++++++++- .../testdata/asmSimpleImageFilter.xml | 1 + .../testdata/asmSimpleMeshProcessing.xml | 22 +++++++++++++++ 3 files changed, 50 insertions(+), 1 deletion(-) diff --git a/sdk/applications/actionstatemachine/CMakeLists.txt b/sdk/applications/actionstatemachine/CMakeLists.txt index 11055400..e38020d3 100644 --- a/sdk/applications/actionstatemachine/CMakeLists.txt +++ b/sdk/applications/actionstatemachine/CMakeLists.txt @@ -9,4 +9,30 @@ camitk_application(NEEDS_QT_MODULES #we use QtXML # 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 "") -# TODO add two automatic test using the testdata scxml +# Automatic tests +set(TEST_BASENAME ${APPLICATION_TARGET_NAME}) +camitk_init_test(${TEST_BASENAME}) + +# should pass because invoking camitk-actionstatemachine without arguments or with help +# arg shows usage and exit success +camitk_add_test(EXECUTABLE_ARGS "--help" PROJECT_NAME ${TEST_BASENAME} TEST_SUFFIX "-") +camitk_add_test(EXECUTABLE_ARGS "-h" PROJECT_NAME ${TEST_BASENAME} TEST_SUFFIX "-") + +# should pass because invoking testcomponents with a faulty arguments results in printing +# an "Argument error" message (and exit failure) +camitk_add_test(EXECUTABLE_ARGS "-badarg" + PASS_REGULAR_EXPRESSION "unknown option '-badarg'" + PROJECT_NAME ${TEST_BASENAME} TEST_SUFFIX "-") + +# Testing using the testdata scxml +# note for the regular expression: +# as [ ] are regex wild card and " is not easy to escaped, all theses characters are replaced by . +# see https://cmake.org/cmake/help/latest/command/string.html#regex-specification +# for more information on CMake regex +camitk_add_test(EXECUTABLE_ARGS "-f ${PROJECT_SOURCE_DIR}/sdk/applications/actionstatemachine/testdata/asmSimpleImageFilter.xml -o . -a" + PASS_REGULAR_EXPRESSION ".INFO . Application .camitk-actionstatemachine. - Exiting application..." + PROJECT_NAME ${TEST_BASENAME} TEST_SUFFIX "-") + +camitk_add_test(EXECUTABLE_ARGS "-f ${PROJECT_SOURCE_DIR}/sdk/applications/actionstatemachine/testdata/asmSimpleMeshProcessing.xml -o . -a" + PASS_REGULAR_EXPRESSION ".INFO . Application .camitk-actionstatemachine. - Exiting application..." + PROJECT_NAME ${TEST_BASENAME} TEST_SUFFIX "-") diff --git a/sdk/applications/actionstatemachine/testdata/asmSimpleImageFilter.xml b/sdk/applications/actionstatemachine/testdata/asmSimpleImageFilter.xml index 83a88000..f4e73db2 100644 --- a/sdk/applications/actionstatemachine/testdata/asmSimpleImageFilter.xml +++ b/sdk/applications/actionstatemachine/testdata/asmSimpleImageFilter.xml @@ -43,6 +43,7 @@ This Action State Machine performs a very simple image processing pipeline:
+ diff --git a/sdk/applications/actionstatemachine/testdata/asmSimpleMeshProcessing.xml b/sdk/applications/actionstatemachine/testdata/asmSimpleMeshProcessing.xml index 9a5faa86..ed387f6d 100644 --- a/sdk/applications/actionstatemachine/testdata/asmSimpleMeshProcessing.xml +++ b/sdk/applications/actionstatemachine/testdata/asmSimpleMeshProcessing.xml @@ -84,6 +84,28 @@ to the testdata directory before running. + + + + + + + Save the decimated mesh + + Save + + + + + + + + + + + + + -- GitLab From 8be12adff4ac950e7361cfbde0f8c068ae7e6695 Mon Sep 17 00:00:00 2001 From: Emmanuel Promayon Date: Mon, 19 Oct 2020 22:15:35 +0200 Subject: [PATCH 2/4] FIXED crash on double delete (QTreeWidgetItem should only be deleted from children to parent) --- sdk/viewers/explorer/Explorer.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/sdk/viewers/explorer/Explorer.cpp b/sdk/viewers/explorer/Explorer.cpp index 8f4d1d43..1af8948c 100644 --- a/sdk/viewers/explorer/Explorer.cpp +++ b/sdk/viewers/explorer/Explorer.cpp @@ -53,11 +53,6 @@ Explorer::Explorer(QString name) : Viewer(name, Viewer::DOCKED) { //----------------------- destructor ------------------------ Explorer::~Explorer() { - // remove all vector actors - while (!itemComponentMap.values().empty()) { - delete itemComponentMap.values().takeFirst(); - } - delete explorerTree; explorerTree = nullptr; @@ -196,7 +191,7 @@ QTreeWidgetItem* Explorer::getItem(Component* comp) { //----------------------- getNewItem ------------------------ QTreeWidgetItem* Explorer::getNewItem(QTreeWidgetItem* parent, Component* abstractNode) { //-- create the tree widget for abstractNode - auto* tw = new QTreeWidgetItem(parent); + QTreeWidgetItem* tw = new QTreeWidgetItem(parent); // set the first column (#0) QString itemText = abstractNode->getName(); -- GitLab From 9841a9b03ebe1d38443bfbf13ca7c2c1cd7958b1 Mon Sep 17 00:00:00 2001 From: Emmanuel Promayon Date: Mon, 19 Oct 2020 22:16:39 +0200 Subject: [PATCH 3/4] NEW check input before enabling the launch --- .../actionstatemachine/ActionStateWizard.cpp | 54 ++++--- .../actionstatemachine/ActionStateWizard.h | 37 +++-- .../actionstatemachine/ActionStateWizard.ui | 146 ++++++++++-------- 3 files changed, 140 insertions(+), 97 deletions(-) diff --git a/sdk/applications/actionstatemachine/ActionStateWizard.cpp b/sdk/applications/actionstatemachine/ActionStateWizard.cpp index 56c94a68..8b90aeeb 100644 --- a/sdk/applications/actionstatemachine/ActionStateWizard.cpp +++ b/sdk/applications/actionstatemachine/ActionStateWizard.cpp @@ -28,56 +28,70 @@ // -- CamiTK Application Local stuff #include "ActionStateWizard.h" -ActionStateWizard::ActionStateWizard() { - uiasmwiz = new Ui::ActionStateWizard(); - uiasmwiz->setupUi(this); +// ---------------------- constructor ---------------------------- +ActionStateWizard::ActionStateWizard(QString inputFileName, QString outputDir) { + // init GUI + ui = new Ui::ActionStateWizard(); + ui->setupUi(this); + ui->buttonBox->button(QDialogButtonBox::Ok)->setText("Start CamiTK Action State Machine"); - connect(uiasmwiz->browseSCXML, SIGNAL(clicked()), this, SLOT(findSCXMLFileName())); - connect(uiasmwiz->browseLogDirectory, SIGNAL(clicked()), this, SLOT(findLogDirectory())); + connect(ui->browseSCXML, SIGNAL(clicked()), this, SLOT(selectSCXMLFilename())); + connect(ui->browseLogDir, SIGNAL(clicked()), this, SLOT(selectLogDirectory())); + + SCXMLFileName = inputFileName; + logDirectory = outputDir; initLogDirLabel(); initSCXMLLabel(); } -// Getter and setter for chosen file and directory +// ---------------------- getSCXMLFilename ---------------------------- QString ActionStateWizard::getSCXMLFilename() { return SCXMLFileName; } +// ---------------------- getLogDirectory ---------------------------- QString ActionStateWizard::getLogDirectory() { return logDirectory; } -void ActionStateWizard::setSCXMLFileName(QString inputFileName) { - SCXMLFileName = inputFileName; -} - -void ActionStateWizard::setLogDirectory(QString outputDir) { - logDirectory = outputDir; -} - -void ActionStateWizard::findLogDirectory() { +// ---------------------- selectLogDirectory ---------------------- +void ActionStateWizard::selectLogDirectory() { logDirectory = QFileDialog::getExistingDirectory(this, tr("Please select a directory where to save log and component files")); initLogDirLabel(); } -void ActionStateWizard::findSCXMLFileName() { +// ---------------------- selectSCXMLFilename ---------------------- +void ActionStateWizard::selectSCXMLFilename() { SCXMLFileName = QFileDialog::getOpenFileName(this, tr("Please select an xml file")); initSCXMLLabel(); } +// ---------------------- initSCXMLLabel ---------------------- void ActionStateWizard::initSCXMLLabel() { if (SCXMLFileName.isEmpty()) { - uiasmwiz->SCXMLLabel->setText("No xml file !"); + ui->SCXMLLabel->setText("No SCXML document: please select an XML file..."); + ui->browseSCXMLLabel->setText("Select SCXML document"); } else { - uiasmwiz->SCXMLLabel->setText(SCXMLFileName); + ui->SCXMLLabel->setText(SCXMLFileName); + ui->browseSCXMLLabel->setText("Modify SCXML document"); } + updateStartButtonState(); } +// ---------------------- initLogDirLabel ---------------------- void ActionStateWizard::initLogDirLabel() { if (logDirectory.isEmpty()) { - uiasmwiz->LogDirLabel->setText("No output directory !"); + ui->LogDirLabel->setText("No output directory: please select a directory"); + ui->browseLogDirLabel->setText("Secect output directory"); } else { - uiasmwiz->LogDirLabel->setText(logDirectory); + ui->LogDirLabel->setText(logDirectory); + ui->browseLogDirLabel->setText("Modify output directory"); } + updateStartButtonState(); +} + +// ---------------------- updateStartButtonState ---------------------- +void ActionStateWizard::updateStartButtonState() { + ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(!SCXMLFileName.isEmpty() && !logDirectory.isEmpty()); } \ No newline at end of file diff --git a/sdk/applications/actionstatemachine/ActionStateWizard.h b/sdk/applications/actionstatemachine/ActionStateWizard.h index e2102d03..d357e6a3 100644 --- a/sdk/applications/actionstatemachine/ActionStateWizard.h +++ b/sdk/applications/actionstatemachine/ActionStateWizard.h @@ -28,35 +28,50 @@ #include "ui_ActionStateWizard.h" +/** + * @ingroup group_sdk_application_asm + * + * @brief + * This dialog is shown only if at least one of the two required input parameters (SCXML + * and output directory) is missing when the application is started. + * + */ class ActionStateWizard : public QDialog { Q_OBJECT public: - ActionStateWizard(); + /// Constructor (initialize the application parameters) + ActionStateWizard(QString inputFileName, QString outputDir); - // Return the filename of scxml file to use as input file + /// Return the current filename of scxml file to use as input file QString getSCXMLFilename(); - // Return the directory name to use as output log directory + /// Return the current directory name to use as output log directory QString getLogDirectory(); - void setSCXMLFileName(QString inputFileName); - - void setLogDirectory(QString outputDir); - private slots: - void findLogDirectory(); + /// called when the user click on "Browse" to select an output directory + void selectLogDirectory(); - void findSCXMLFileName(); + /// called when the user click on "Browse" to select an SCXML input file + void selectSCXMLFilename(); private: - Ui::ActionStateWizard* uiasmwiz; + /// the Dialog GUI + Ui::ActionStateWizard* ui; + /// the current value of the SCXML input file QString SCXMLFileName; + /// the current value of the output directory QString logDirectory; + /// initialize the GUI to display the current value of SCXML input file + void initSCXMLLabel(); + + /// initialize the GUI to display the current value of output directory void initLogDirLabel(); - void initSCXMLLabel(); + /// enable the Start button state only if both parameters are set + void updateStartButtonState(); }; #endif // ACTIONSTATEWIZARD_H \ No newline at end of file diff --git a/sdk/applications/actionstatemachine/ActionStateWizard.ui b/sdk/applications/actionstatemachine/ActionStateWizard.ui index e975fd2a..be211556 100644 --- a/sdk/applications/actionstatemachine/ActionStateWizard.ui +++ b/sdk/applications/actionstatemachine/ActionStateWizard.ui @@ -6,8 +6,8 @@ 0 0 - 471 - 146 + 482 + 388 @@ -19,87 +19,101 @@ - CamiTK Action State Machine needs two parameters to run. + <html><head/><body><p>CamiTK Action State Machine requires two parameters to run</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">An SCXML to describe the state machine</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">An output directory to write the log</li></ul></body></html> + + + Qt::RichText - - - - - Choose a SCXML file : - - - - - - - Browse - - - - + + + SCXML + + + + + + TextLabel + + + + + + + + + Select SCXML file + + + + + + + Browse + + + + + + + - - - TextLabel + + + Output directory + + + + + TextLabel + + + + + + + + + Select output directory + + + + + + + Browse + + + + + + - + - - - Choose an output directory : + + + Qt::LeftToRight - - - - - - Browse + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + true - - - - TextLabel - - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - Qt::Vertical - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - -- GitLab From e9775788377f3723b9f672646d6860f7b6e3f2b5 Mon Sep 17 00:00:00 2001 From: Emmanuel Promayon Date: Mon, 19 Oct 2020 22:17:47 +0200 Subject: [PATCH 4/4] NEW embed xsl for modern browser support + new design of the log + xml cleanup --- .../actionstatemachine/ActionState.cpp | 26 +- .../actionstatemachine/ActionStateMachine.cpp | 466 ++++++++++++++++-- .../actionstatemachine/ActionStateMachine.h | 8 +- .../actionstatemachine/ActionTransition.cpp | 2 +- .../actionstatemachine/SaveActionState.cpp | 17 +- .../resources/camitk-actionstatemachine.qrc | 1 - .../actionstatemachine/resources/log2html.xsl | 348 ------------- 7 files changed, 452 insertions(+), 416 deletions(-) delete mode 100644 sdk/applications/actionstatemachine/resources/log2html.xsl diff --git a/sdk/applications/actionstatemachine/ActionState.cpp b/sdk/applications/actionstatemachine/ActionState.cpp index c041c3e5..7fc6382e 100644 --- a/sdk/applications/actionstatemachine/ActionState.cpp +++ b/sdk/applications/actionstatemachine/ActionState.cpp @@ -213,27 +213,29 @@ void ActionState::onEntry(QEvent* event) { } // log the parameters - (*logStream) << "\t\t\t" << myAction->getName() << "" << endl; + (*logStream) << "\t\t" << myAction->getName() << "" << endl; // Properties int nbStaticProps = myAction->metaObject()->propertyCount(); QList propertyNames = myAction->dynamicPropertyNames(); // static properties if ((nbStaticProps > 0) || (! propertyNames.isEmpty())) { - (*logStream) << "\t\t\t" << endl; + (*logStream) << "\t\t" << endl; for (int index = 0 ; index < nbStaticProps; index++) { QString staticPropName = myAction->metaObject()->property(index).name(); - (*logStream) << "\t\t\t\t" << endl; + if (staticPropName != "objectName") { + (*logStream) << "\t\t\t" << endl; + } } // dynamic properties for (QList::const_iterator it = propertyNames.begin(); it != propertyNames.end(); it++) { - (*logStream) << "\t\t\t\t" << endl; } - (*logStream) << "\t\t\t" << endl; + (*logStream) << "\t\t" << endl; } @@ -244,7 +246,7 @@ void ActionState::onEntry(QEvent* event) { // log inputs if (inputComponentNames.size() > 0) { - (*logStream) << "\t\t\t" << endl; + (*logStream) << "\t\t" << endl; } // search for proper input considering name and type @@ -260,14 +262,14 @@ void ActionState::onEntry(QEvent* event) { } if (compIt != allComps.end()) { - (*logStream) << "\t\t\t\tgetName() << "' type='" << compType << "'/>" << endl; inputComps.append((*compIt)); } } if (inputComponentNames.size() > 0) { - (*logStream) << "\t\t\t" << endl; + (*logStream) << "\t\t" << endl; } myAction->setInputComponents(inputComps); @@ -299,7 +301,7 @@ void ActionState::onExit(QEvent* event) { QTime endTime = QTime::currentTime(); (*logStream) << "\t\t" << endl; (*logStream) << "\t\t" << endTime.toString("hh:mm:ss:zzz") << "" << endl; - (*logStream) << "\t\t" << (startTime->elapsed()) << "" << endl; + (*logStream) << "\t\t" << (startTime->elapsed()) << "" << endl; (*logStream) << "\t" << endl; } } diff --git a/sdk/applications/actionstatemachine/ActionStateMachine.cpp b/sdk/applications/actionstatemachine/ActionStateMachine.cpp index 43ef997f..6e8fdf33 100644 --- a/sdk/applications/actionstatemachine/ActionStateMachine.cpp +++ b/sdk/applications/actionstatemachine/ActionStateMachine.cpp @@ -46,6 +46,7 @@ using namespace camitk; #include "ActionStateViewer.h" #include "ActionStateViewerExtension.h" #include "ActionTransition.h" +#include "ActionStateWizard.h" // ---------------------- constructor ---------------------------- ActionStateMachine::ActionStateMachine(int& argc, char** argv, QString inputFileName, QString outputDirectory) : @@ -54,20 +55,20 @@ ActionStateMachine::ActionStateMachine(int& argc, char** argv, QString inputFile setProperty("Log to File", true); setProperty("Logger Level", InterfaceLogger::TRACE); - asmwiz = new ActionStateWizard(); - - // Read parameters or ask for scxml file name and output save directory + // Read parameters or ask for scxml filename and output directory QString filename; if (inputFileName.isEmpty() || outputDirectory.isEmpty()) { - // open dialog for parameters input + // open dialog wizard for parameters input + ActionStateWizard asmwiz(inputFileName, outputDirectory); + // if OK is pressed we continue starting action state machine // otherwise we exit - if (asmwiz->exec()) { - filename = asmwiz->getSCXMLFilename(); - saveDirectory = QDir(asmwiz->getLogDirectory()); - asmwiz->done(QDialog::Accepted); + if (asmwiz.exec()) { + filename = asmwiz.getSCXMLFilename(); + saveDirectory = QDir(asmwiz.getLogDirectory()); + asmwiz.done(QDialog::Accepted); } else { - asmwiz->done(QDialog::Rejected); + asmwiz.done(QDialog::Rejected); throw AbortException("Operation aborted by user."); } } else { @@ -80,8 +81,6 @@ ActionStateMachine::ActionStateMachine(int& argc, char** argv, QString inputFile ext->initResources(); ext->init(); registerAllViewers(ext); - - statesMap = new QMap(); // Atributes initialization mainWindow = NULL; @@ -97,19 +96,17 @@ ActionStateMachine::ActionStateMachine(int& argc, char** argv, QString inputFile // NOTE on Windows ":" (colon) is reserved by the system for separating drive names, therefore hh:mm:ss cannot be used QString newDir = now.toString("yyyy-MM-dd") + "T" + now.toString("hh-mm-ss"); - if (! saveDirectory.mkdir(newDir)) { + if (!saveDirectory.mkdir(newDir)) { saveDirectory = QFileDialog::getExistingDirectory(this->mainWindow, tr("Please select a directory where to save log and component files")); saveDirectory.mkdir(newDir); } saveDirectory.cd(newDir); + CAMITK_TRACE(tr("Logging in %1").arg(saveDirectory.absolutePath())); // parse XML file and store actions and transitions in states name = this->parseSCXMLTree(); mainWindow->setWindowSubtitle(name); - // Prepare the output directory - QFile::copy(":/logXSL", saveDirectory.absolutePath() + "/log2html.xsl"); - // Starting the Machine !! //create the main timer @@ -117,16 +114,390 @@ ActionStateMachine::ActionStateMachine(int& argc, char** argv, QString inputFile startTime->start(); (*logStream) << "" << endl; - (*logStream) << "" << endl << endl; + (*logStream) << "" << endl; + (*logStream) << "" << endl; + (*logStream) << "]>" << endl; + (*logStream) << "" << endl; + // embed the XSL stylesheet directly in the XML + + (*logStream) << "" << endl; + (*logStream) << "" << endl; + (*logStream) << "" << endl; + (*logStream) << " " << endl; + (*logStream) << "" << endl; + (*logStream) << " " << endl; + (*logStream) << "" << endl; + (*logStream) << " " << endl; + (*logStream) << " " << endl; + (*logStream) << " " << endl; + (*logStream) << " Log of Application <xsl:value-of select='log:application/log:name'/>" << endl; + (*logStream) << " " << endl; + (*logStream) << " " << endl; + (*logStream) << " " << endl; + (*logStream) << "
" << endl; + (*logStream) << "
" << endl; + (*logStream) << "

" << endl; + (*logStream) << "

Log file

" << endl; + (*logStream) << "

Date:

" << endl; + (*logStream) << "

Started: - Finished:

" << endl; + (*logStream) << "

Duration: " << endl; + (*logStream) << " " << endl; + (*logStream) << " " << endl; + (*logStream) << "

" << endl; + (*logStream) << "

Input xml file name:

" << endl; + (*logStream) << "

" << endl; + (*logStream) << "
" << endl; + (*logStream) << "" << endl; + (*logStream) << "
" << endl; + (*logStream) << " " << endl; + (*logStream) << " " << endl; + (*logStream) << "" << endl; + (*logStream) << "

Total time spend within states: " << endl; + (*logStream) << " " << endl; + (*logStream) << " " << endl; + (*logStream) << " " << endl; + (*logStream) << " " << endl; + (*logStream) << " ( ms)" << endl; + (*logStream) << "

" << endl; + (*logStream) << " " << endl; + (*logStream) << "

Total time spend on action transitions: " << endl; + (*logStream) << " " << endl; + (*logStream) << " " << endl; + (*logStream) << " " << endl; + (*logStream) << " " << endl; + (*logStream) << " ( ms)" << endl; + (*logStream) << "

" << endl; + (*logStream) << " " << endl; + (*logStream) << " " << endl; + (*logStream) << " " << endl; + (*logStream) << " " << endl; + (*logStream) << " " << endl; + (*logStream) << "
State
(click on a state to show its execution details)
" << endl; + (*logStream) << "
" << endl; + (*logStream) << "
" << endl; + (*logStream) << " " << endl; + (*logStream) << " " << endl; + (*logStream) << " " << endl; + (*logStream) << "
" << endl; + (*logStream) << "" << endl; + (*logStream) << " " << endl; + (*logStream) << " " << endl; + (*logStream) << " " << endl; + (*logStream) << " " << endl; + (*logStream) << " " << endl; + (*logStream) << " " << endl; + (*logStream) << "
" << endl; + (*logStream) << " . " << endl; + (*logStream) << "
" << endl; + (*logStream) << " " << endl; + (*logStream) << " " << endl; + (*logStream) << " " << endl; + (*logStream) << " CamiTK action's name: " << endl; + (*logStream) << " " << endl; + (*logStream) << " State duration: " << endl; + (*logStream) << " " << endl; + (*logStream) << " " << endl; + (*logStream) << " " << endl; + (*logStream) << " " << endl; + (*logStream) << " " << endl; + (*logStream) << " " << endl; + (*logStream) << " " << endl; + (*logStream) << "
" << endl; + (*logStream) << " " << endl; + (*logStream) << " " << endl; + (*logStream) << " " << endl; + (*logStream) << " " << endl; + (*logStream) << " " << endl; + (*logStream) << " " << endl; + (*logStream) << " " << endl; + (*logStream) << " " << endl; + (*logStream) << " " << endl; + (*logStream) << " " << endl; + (*logStream) << " " << endl; + (*logStream) << "" << endl; + (*logStream) << " Transition duration: " << endl; + (*logStream) << " " << endl; + (*logStream) << " " << endl; + (*logStream) << " " << endl; + (*logStream) << " " << endl; + (*logStream) << " Action applied with status: " << endl; + (*logStream) << "" << endl; + (*logStream) << " " << endl; + (*logStream) << " " << endl; + (*logStream) << " Parameters: " << endl; + (*logStream) << " " << endl; + (*logStream) << " " << endl; + (*logStream) << " " << endl; + (*logStream) << " Input:" << endl; + (*logStream) << " " << endl; + (*logStream) << " " << endl; + (*logStream) << " " << endl; + (*logStream) << " Output:" << endl; + (*logStream) << " " << endl; + (*logStream) << " " << endl; + (*logStream) << "" << endl; + (*logStream) << " " << endl; + (*logStream) << " " << endl; + (*logStream) << " " << endl; + (*logStream) << " Closing:" << endl; + (*logStream) << " " << endl; + (*logStream) << " " << endl; + (*logStream) << " " << endl; + (*logStream) << " " << endl; + (*logStream) << " " << endl; + (*logStream) << "
    " << endl; + (*logStream) << " " << endl; + (*logStream) << "
" << endl; + (*logStream) << "
" << endl; + (*logStream) << "" << endl; + (*logStream) << " " << endl; + (*logStream) << "
  • :
  • " << endl; + (*logStream) << "
    " << endl; + (*logStream) << "" << endl; + (*logStream) << " " << endl; + (*logStream) << "
      " << endl; + (*logStream) << " " << endl; + (*logStream) << "
    " << endl; + (*logStream) << "
    " << endl; + (*logStream) << "" << endl; + (*logStream) << " " << endl; + (*logStream) << "
      " << endl; + (*logStream) << " " << endl; + (*logStream) << "
    " << endl; + (*logStream) << "
    " << endl; + (*logStream) << "" << endl; + (*logStream) << " " << endl; + (*logStream) << "
  • :
  • " << endl; + (*logStream) << "
    " << endl; + (*logStream) << " " << endl; + (*logStream) << " " << endl; + (*logStream) << " " << endl; + (*logStream) << " " << endl; + (*logStream) << " " << endl; + (*logStream) << " " << endl; + (*logStream) << " " << endl; + (*logStream) << " h " << endl; + (*logStream) << " min " << endl; + (*logStream) << " s " << endl; + (*logStream) << " ms" << endl; + (*logStream) << " <1 ms" << endl; + (*logStream) << " " << endl; + (*logStream) << "
    " << endl; (*logStream) << "" << endl; - (*logStream) << "\t" << name << "" << endl; + (*logStream) << "\t" << getName() << "" << endl; (*logStream) << "\t" << filename << "" << endl; (*logStream) << "\t" << now.toString("yyyy-MM-dd") << "" << endl; (*logStream) << "\t" << startTime->toString("hh:mm:ss:zzz") << "" << endl; machine.start(); - - } // ---------------------- autoNext ---------------------------- @@ -140,23 +511,43 @@ void ActionStateMachine::autoNext() { // loop until no more state is available while (currentState != nullptr && currentState->transitions().size() > 0) { // look for the "Next" or "Quit" transition + // (if there is a "Next" and a "Quit", "Next" is prioritized) auto it = currentState->transitions().begin(); bool foundNextState = false; - while (it != currentState->transitions().end() && !foundNextState) { // && nextState==nullptr) { + while (it != currentState->transitions().end() && !foundNextState) { // all transition in this state machine are ActionTransition instances... ActionTransition* currentActionTransition = qobject_cast(*it); - //... in which we can look for the "Next" or "Quit" transition - if (currentActionTransition->isNamed("Next") || currentActionTransition->isNamed("Quit")) { + //... in which we can look for the "Next" transition first + if (currentActionTransition->isNamed("Next")) { // 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; } + // if the next state is not found, look for the "Quit" state + if (!foundNextState) { + it = currentState->transitions().begin(); + while (it != currentState->transitions().end() && !foundNextState) { + // all transition in this state machine are ActionTransition instances... + ActionTransition* currentActionTransition = qobject_cast(*it); + + //... in which we can look for the "Quit" transition + if (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; + } + } // get the new current active state currentState = dynamic_cast(machine.configuration().toList().first()); } + while (currentState != nullptr); } @@ -230,6 +621,7 @@ void ActionStateMachine::checkSCXMLFile(QString filename) { // ---------------------- parseSCXMLTree ---------------------------- QString ActionStateMachine::parseSCXMLTree() { + // Get the name of the application QString applicationName = ""; QDomElement docElem = scxmlDoc.documentElement(); @@ -252,7 +644,7 @@ QString ActionStateMachine::parseSCXMLTree() { // Set the initial state (specified in the scxml element with initial attribute). QString initialStateName = scxmlDoc.documentElement().attribute("initial"); - ActionState* initialState = statesMap->find(initialStateName).value(); + ActionState* initialState = statesMap.find(initialStateName).value(); machine.setInitialState(initialState); dynamic_cast(Application::getViewer("Action State Viewer"))->setState(initialState); @@ -262,10 +654,6 @@ QString ActionStateMachine::parseSCXMLTree() { // 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; - return applicationName; } @@ -274,8 +662,9 @@ void ActionStateMachine::finished() { QTime endTime = QTime::currentTime(); (*logStream) << "\t" << endTime.toString("hh:mm:ss:zzz") << "" << endl; - (*logStream) << "\t" << (startTime->elapsed()) << "" << endl; + (*logStream) << "\t" << (startTime->elapsed()) << "" << endl; (*logStream) << "" << endl; + (*logStream) << "
    " << endl; logFile->close(); } @@ -295,20 +684,23 @@ void ActionStateMachine::createAllActionStates(QDomNodeList nodeList) { if (elementName == QString("state")) { QString stateId = element.attribute("id"); QString stateDescription = element.elementsByTagName("camitk:description").item(0).toElement().text(); - ActionState* state = new ActionState(&machine, stateId, stateDescription, logStream); - if (element.elementsByTagName("camitk:action").size() > 0) { + ActionState* state = nullptr; + if (element.elementsByTagName("camitk:action").size() > 0) { QDomElement actionElement = element.elementsByTagName("camitk:action").item(0).toElement(); // Find the name of the action QString camiTKActionName = actionElement.elementsByTagName("camitk:name").item(0).toElement().text(); if (camiTKActionName == "Save") { - delete (state); state = new SaveActionState(&machine, stateId, stateDescription, saveDirectory.absolutePath(), logStream); setCamiTKSaveAction((SaveActionState*) state, actionElement); } else { + state = new ActionState(&machine, stateId, stateDescription, logStream); setCamiTKAction(state, actionElement); } } + else { + state = new ActionState(&machine, stateId, stateDescription, logStream); + } QDomNodeList alternativeDescriptions = element.elementsByTagName("camitk:altDescription"); for (int i = 0; i < alternativeDescriptions.size(); i++) { QDomElement altDescElmt = alternativeDescriptions.item(i).toElement(); @@ -319,7 +711,7 @@ void ActionStateMachine::createAllActionStates(QDomNodeList nodeList) { state->setAlternativeDesc(altDescText, statusList); } - statesMap->insert(stateId, state); + statesMap.insert(stateId, state); } } } @@ -331,8 +723,8 @@ void ActionStateMachine::createAllActionStates(QDomNodeList nodeList) { // 1. build the map QMap inputNames; QMap outputNames; - QMap ::const_iterator it = statesMap->constBegin(); - while (it != statesMap->constEnd()) { + QMap ::const_iterator it = statesMap.constBegin(); + while (it != statesMap.constEnd()) { foreach (QString inputCompName, it.value()->getInputComponents().keys()) { if (inputNames.values().contains(inputCompName)) { CAMITK_WARNING(tr("Warning: same input \"%1\" for more than one state. It might be wrong.\n").arg(inputCompName)) @@ -376,7 +768,7 @@ void ActionStateMachine::createTransitions(QDomNodeList nodeList) { // Find its name (id attribute)... QString stateId = element.attribute("id"); // ... and get the corresponding created state in the map: - ActionState* state = (statesMap->find(stateId)).value(); + ActionState* state = (statesMap.find(stateId)).value(); // Check if this state is final bool isFinal = (element.attribute("final", "false").toLower() == QString("true")); @@ -397,8 +789,8 @@ void ActionStateMachine::createTransitions(QDomNodeList nodeList) { QVector disableConditions = stringToStatus(disableConds); // Find the corresponding target state - QMap ::iterator it = statesMap->find(targetName); - if (it == statesMap->end()) { + QMap ::iterator it = statesMap.find(targetName); + if (it == statesMap.end()) { QString msg = tr(R"(XML Parsing: %1 in state "%2": cannot find target "%3" for event "%4")") .arg(getDomNodeLocation(transitionsList.item(transNb)), state->getName(), diff --git a/sdk/applications/actionstatemachine/ActionStateMachine.h b/sdk/applications/actionstatemachine/ActionStateMachine.h index 79f40cf9..652af07e 100644 --- a/sdk/applications/actionstatemachine/ActionStateMachine.h +++ b/sdk/applications/actionstatemachine/ActionStateMachine.h @@ -46,7 +46,6 @@ // -- CamiTK Local stuff #include "ActionState.h" #include "SaveActionState.h" -#include "ActionStateWizard.h" /** * @ingroup group_sdk_application_asm @@ -109,7 +108,7 @@ protected: QDomDocument scxmlDoc; /// Map of action state to build transitions - QMap* statesMap; + QMap statesMap; /// Final State QFinalState* finalState; @@ -149,11 +148,6 @@ private: /// build a specific error message containing the line and column if available QString getDomNodeLocation(QDomNode); - - /// - /// Wizard to ask wich file and directory to use - /// - ActionStateWizard* asmwiz; }; #endif // ACTIONSTATEMACHINE_H diff --git a/sdk/applications/actionstatemachine/ActionTransition.cpp b/sdk/applications/actionstatemachine/ActionTransition.cpp index d9ae760f..1cd8d1c1 100644 --- a/sdk/applications/actionstatemachine/ActionTransition.cpp +++ b/sdk/applications/actionstatemachine/ActionTransition.cpp @@ -139,7 +139,7 @@ void ActionTransition::onTransition(QEvent* e) { QTime endTime = QTime::currentTime(); (*logStream) << "\t\t" << endTime.toString("hh:mm:ss:zzz") << "" << endl; - (*logStream) << "\t\t" << (startTime->elapsed()) << "" << endl; + (*logStream) << "\t\t" << (startTime->elapsed()) << "" << endl; (*logStream) << "\t
    " << endl; } } diff --git a/sdk/applications/actionstatemachine/SaveActionState.cpp b/sdk/applications/actionstatemachine/SaveActionState.cpp index 45a1992b..b84b402f 100644 --- a/sdk/applications/actionstatemachine/SaveActionState.cpp +++ b/sdk/applications/actionstatemachine/SaveActionState.cpp @@ -52,12 +52,11 @@ Action::ApplyStatus SaveActionState::applyAction() { Action::ApplyStatus status(Action::TRIGGERED); if (logStream != nullptr) { - (*logStream) << " " << endl; - (*logStream) << " " << myAction->getName() << "" << endl; - (*logStream) << " " << endl; + (*logStream) << "\t\t" << endl; + (*logStream) << "\t\t\t" << myAction->getName() << "" << endl; + (*logStream) << "\t\t\t" << endl; } - // set input components ComponentList allComps = Application::getAllComponents(); ComponentList::const_iterator compIt; @@ -111,13 +110,13 @@ Action::ApplyStatus SaveActionState::applyAction() { inputComps.append((*compIt)); if (logStream != NULL) { - (*logStream) << " " << endl; } } if (logStream != nullptr) { - (*logStream) << " " << endl; + (*logStream) << "\t\t\t" << endl; } @@ -134,12 +133,10 @@ Action::ApplyStatus SaveActionState::applyAction() { } if (logStream != nullptr) { - (*logStream) << " " << Action::getStatusAsString(status) << "" << endl; - (*logStream) << " " << endl; + (*logStream) << "\t\t\t" << Action::getStatusAsString(status) << "" << endl; + (*logStream) << "\t\t" << endl; } - - Application::refresh(); return status; diff --git a/sdk/applications/actionstatemachine/resources/camitk-actionstatemachine.qrc b/sdk/applications/actionstatemachine/resources/camitk-actionstatemachine.qrc index 5eb85285..864c4d39 100644 --- a/sdk/applications/actionstatemachine/resources/camitk-actionstatemachine.qrc +++ b/sdk/applications/actionstatemachine/resources/camitk-actionstatemachine.qrc @@ -1,7 +1,6 @@ - log2html.xsl camitk-actionstatemachine.xpm \ No newline at end of file diff --git a/sdk/applications/actionstatemachine/resources/log2html.xsl b/sdk/applications/actionstatemachine/resources/log2html.xsl deleted file mode 100644 index 16d6f05a..00000000 --- a/sdk/applications/actionstatemachine/resources/log2html.xsl +++ /dev/null @@ -1,348 +0,0 @@ - - - - - - - - - - - Log of Application <xsl:value-of select="/log:application/log:name"/> - - - -
    -
    -

    -

    Log file

    -

    Runned the

    -

    Start: Stop:

    -

    duration: - - -

    -

    Input xml file name:

    -
    - -
    - - - -

    Total time within states (action triggering): - - - - - (i.e., ms) -

    - -

    Total time on action application: - - - - - (i.e., ms) -

    - - - - - -

    State

    Duration

    -
    - -
    - - -
    - - - - - - - - -
    - ) -
    - - - - - - - - - -
    - - - - - - - - - Action Applied: - with status - - - - - - - - - - - - - - - -
    ParametersInputsOutputs
    - - - - - - - - - -
    - - - - - Closing: - - - - - - -
    - - - - - - - - - -
    - - - - - - - - -
    - Name - Value -
    -
    - - - - - - - - - - - - - - - - - - - -
    - Type - - Name -
    -
    - - - - - - - - -
    - Type - - Name -
    -
    - - - - - - - - - - - - - - - - - - - h - min - s - ms - -
    -- GitLab