diff --git a/.gitlab/issue_templates/Bug.md b/.gitlab/issue_templates/Bug.md
index b8256025acdccdee69f110624af6c9075baf9811..1eed1dbfa07bea0c3fcb4edf303ce25b0383474e 100644
--- a/.gitlab/issue_templates/Bug.md
+++ b/.gitlab/issue_templates/Bug.md
@@ -1,28 +1,28 @@
-## About you:
+## About you
[Present yourself and your project you're working on with CamiTK]
-## Overview:
+## Overview
[Rewrite here a larger and more detailed restatement of your summary]
-## Steps to Reproduce:
+## Steps to Reproduce
[Write here the step - by - step process to reproduce the bug, including file to test (you can attach file on gitlab issue report system)]
-## Actual VS Expected Result:
+## Actual VS Expected Result
[Write here the result of the step - by - step process and explain why it is not what you expected]
-## Relevant logs and/or screenshots:
+## Relevant logs and/or screenshots
[Paste any relevant logs - please use code blocks (```) to format console output, logs, and code as it's very hard to read otherwise.]
-## Interpretation & Possible fixes:
+## Interpretation & Possible fixes
[Write here your interpretation of this bug (If you can, link to the line of code that might be responsible for the problem)]
-## CamiTK Version:
+## CamiTK Version
[Copy/Paste the output of `camitk-config -b` CamiTK Version part ]
diff --git a/.gitlab/issue_templates/Feature.md b/.gitlab/issue_templates/Feature.md
index e23401c5a0310ffb528501bfc4cc05eb4b903d52..45c593abec8e30d087ef5479dfa6d186ffdb0bc6 100644
--- a/.gitlab/issue_templates/Feature.md
+++ b/.gitlab/issue_templates/Feature.md
@@ -1,16 +1,16 @@
-## About you:
+## About you
[Present yourself and your project you're working on with CamiTK]
-## Product:
+## Product
[Specify which part of framework is concerned]
-## Overview:
+## Overview
[Rewrite here a larger and more detailed restatement of your summary]
-## Relevant logs and/or screenshots:
+## Relevant logs and/or screenshots
[Paste any relevant logs - please use code blocks (```) to format console output,
logs, and code as it's very hard to read otherwise.]
diff --git a/.gitlab/issue_templates/Technical Feature.md b/.gitlab/issue_templates/Technical Feature.md
index d13b5ccbff1bbde1b1c77c13062216603819f181..dd42cb1ef72fd754df2d1e1235356db6d70835e1 100644
--- a/.gitlab/issue_templates/Technical Feature.md
+++ b/.gitlab/issue_templates/Technical Feature.md
@@ -26,8 +26,15 @@
## Track
+One (or two) of:
/label ~"Track None"
-
+/label ~"Track Code Maintainability"
+/label ~"Track Continuous Integration"
+/label ~"Track Debugging"
+/label ~"Track Knowledge Management"
+/label ~"Track Prototyping Experience"
+/label ~"Track Technology Integration"
+/label ~"Track User Support"
[or if known, add the corresponding track label]
## Misc
diff --git a/imaging/actions/itkfilters/SobelEdgeDetection.cpp b/imaging/actions/itkfilters/SobelEdgeDetection.cpp
index a5baae4fd0607455d9dd34ad0f7f1f4a987af9e7..b3c34d93166e694838c83d02a92ca77442c790dc 100644
--- a/imaging/actions/itkfilters/SobelEdgeDetection.cpp
+++ b/imaging/actions/itkfilters/SobelEdgeDetection.cpp
@@ -43,9 +43,9 @@ using namespace camitk;
// --------------- constructor -------------------
SobelEdgeDetection::SobelEdgeDetection(ActionExtension* extension) : Action(extension) {
// Setting name, description and input component
- setName("Sobel Edge Detecton");
+ setName("Sobel Edge Detection");
setDescription("
A 2D or 3D edge detection using the Sobel operator.
\
- This filter uses the Sobel operator to calculate the image gradient and then finds the magnitude of this gradient vector. The Sobel gradient magnitude (square-root sum of squares) is an indication of edge strength..
");
+ This filter uses the Sobel operator to calculate the image gradient and then finds the magnitude of this gradient vector. The Sobel gradient magnitude (square-root sum of squares) is an indication of edge strength..
");
setComponent("ImageComponent");
// Setting classification family and tags
@@ -64,8 +64,8 @@ SobelEdgeDetection::~SobelEdgeDetection() {
// --------------- apply -------------------
Action::ApplyStatus SobelEdgeDetection::apply() {
- foreach (Component * comp, getTargets()) {
- ImageComponent* input = dynamic_cast ( comp );
+ foreach (Component* comp, getTargets()) {
+ ImageComponent* input = dynamic_cast(comp);
process(input);
}
return SUCCESS;
@@ -75,7 +75,7 @@ void SobelEdgeDetection::process(ImageComponent* comp) {
this->keepOrgVoxelType = property("Keep original voxel type?").toBool();
// ITK filter implementation using templates
vtkSmartPointer inputImage = comp->getImageData();
- vtkSmartPointer outputImage = implementProcess (inputImage);
+ vtkSmartPointer outputImage = implementProcess(inputImage);
ImageComponent* outputComp = new ImageComponent(outputImage, comp->getName() + "_edges");
// consider frame policy on new image created
@@ -134,14 +134,14 @@ vtkSmartPointer SobelEdgeDetection::itkProcess(vtkSmartPointerSetInput(vtkToItkFilter->GetOutput());
- castFilterIn->AddObserver(itk::ProgressEvent(), observer );
+ castFilterIn->AddObserver(itk::ProgressEvent(), observer);
castFilterIn->Update();
observer->Reset();
// Apply Sobel Edge Detection Filter
sobelFilter->SetInput(castFilterIn->GetOutput());
- sobelFilter->AddObserver(itk::ProgressEvent(), observer );
+ sobelFilter->AddObserver(itk::ProgressEvent(), observer);
sobelFilter->Update();
observer->Reset();
@@ -152,7 +152,7 @@ vtkSmartPointer SobelEdgeDetection::itkProcess(vtkSmartPointerUpdate();
observer->Reset();
itkToVtkFilter2->SetInput(castFilterOut->GetOutput());
- itkToVtkFilter2->AddObserver(itk::ProgressEvent(), observer );
+ itkToVtkFilter2->AddObserver(itk::ProgressEvent(), observer);
// --------------------- Actually execute all filters parts --------------------
itkToVtkFilter2->Update();
observer->Reset();
@@ -162,7 +162,7 @@ vtkSmartPointer SobelEdgeDetection::itkProcess(vtkSmartPointerSetInput(sobelFilter->GetOutput());
- itkToVtkFilter->AddObserver(itk::ProgressEvent(), observer );
+ itkToVtkFilter->AddObserver(itk::ProgressEvent(), observer);
// --------------------- Actually execute all filters parts --------------------
itkToVtkFilter->Update();
observer->Reset();
diff --git a/imaging/actions/itkfilters/integration-testdata/asm-input.scxml b/imaging/actions/itkfilters/integration-testdata/asm-input.scxml
index ec09a2978cdb00c5f10b96eb685d6e3f355a74c3..847cad965984eb725864ac6bc05df7bba8853d54 100644
--- a/imaging/actions/itkfilters/integration-testdata/asm-input.scxml
+++ b/imaging/actions/itkfilters/integration-testdata/asm-input.scxml
@@ -16,7 +16,6 @@
-
@@ -37,7 +36,6 @@
-
@@ -89,7 +87,6 @@
-
@@ -176,7 +173,6 @@
-
@@ -222,7 +218,6 @@
-
@@ -268,7 +263,6 @@
-
@@ -413,7 +407,6 @@
-
@@ -458,7 +451,6 @@
-
diff --git a/imaging/actions/itksegmentation/OtsuFilter.cpp b/imaging/actions/itksegmentation/OtsuFilter.cpp
index 4ef02fdb1da16e6b85dac6450be9e218a197a1a5..15b4e54bc2ca51185e672b7c6b9349babbc1e396 100644
--- a/imaging/actions/itksegmentation/OtsuFilter.cpp
+++ b/imaging/actions/itksegmentation/OtsuFilter.cpp
@@ -52,7 +52,6 @@ OtsuFilter::OtsuFilter(ActionExtension* extension) : Action(extension) {
this->addTag("Threshold");
this->addTag("Automatic");
this->addTag("Otsu");
- this->addTag("Region Growing");
this->computedThresholdProperty = new Property(tr("Computed threshold:"), tr("?"), tr("The computed threshold found by the Otsu filter. \nThis property is read only and only updated after applying the action on a component."), "");
computedThresholdProperty->setReadOnly(true);
diff --git a/imaging/actions/itksegmentation/RegionGrowing.cpp b/imaging/actions/itksegmentation/RegionGrowing.cpp
index 5ee6e8e7e92f3883f32d1e733f236a8b19b5d7ee..ff7373d1c1d8e9f71684a7698443c15381bea894 100644
--- a/imaging/actions/itksegmentation/RegionGrowing.cpp
+++ b/imaging/actions/itksegmentation/RegionGrowing.cpp
@@ -58,7 +58,8 @@ RegionGrowing::RegionGrowing(ActionExtension* extension) : Action(extension) {
this->addTag("Classification");
this->addTag("Growing Region");
this->addTag("Seed Point");
-
+ this->addTag("Region Growing");
+
// Setting the widget containing the parameters
theWidget = NULL;
diff --git a/imaging/actions/itksegmentation/RegionGrowing.impl b/imaging/actions/itksegmentation/RegionGrowing.impl
index d362d5e03ffcc12964e6c18f6e77c16132ca97aa..2d6cc65e8ba88bf61342aaa427ff75125516becb 100644
--- a/imaging/actions/itksegmentation/RegionGrowing.impl
+++ b/imaging/actions/itksegmentation/RegionGrowing.impl
@@ -23,103 +23,103 @@
* $CAMITK_LICENCE_END$
****************************************************************************/
-vtkSmartPointer RegionGrowing::implementProcess(vtkSmartPointer img)
-{
- vtkSmartPointer result = NULL;
- if (img == NULL)
- return result;
-
- int * dims = img->GetDimensions();
- int dim = 0;
- if (dims[2] == 0)
- dim = 2;
- else
- dim = 3;
-
- int scalarType = img->GetScalarType();
-
- switch (scalarType)
- {
- case VTK_CHAR :
- if (dim == 2)
- result = itkProcess(img);
- else // if dim == 3
- result = itkProcess(img);
- break;
-
- case VTK_UNSIGNED_CHAR :
- if (dim == 2)
- result = itkProcess(img);
- else // if dim == 3
- result = itkProcess(img);
- break;
-
- case VTK_SIGNED_CHAR :
- if (dim == 2)
- result = itkProcess(img);
- else // if dim == 3
- result = itkProcess(img);
- break;
-
- case VTK_SHORT :
- if (dim == 2)
- result = itkProcess(img);
- else // if dim == 3
- result = itkProcess(img);
- break;
-
- case VTK_UNSIGNED_SHORT :
- if (dim == 2)
- result = itkProcess(img);
- else // if dim == 3
- result = itkProcess(img);
- break;
-
- case VTK_INT :
- if (dim == 2)
- result = itkProcess(img);
- else // if dim == 3
- result = itkProcess(img);
- break;
-
- case VTK_UNSIGNED_INT :
- if (dim == 2)
- result = itkProcess(img);
- else // if dim == 3
- result = itkProcess(img);
- break;
-
- case VTK_LONG :
- if (dim == 2)
- result = itkProcess(img);
- else // if dim == 3
- result = itkProcess(img);
- break;
-
- case VTK_UNSIGNED_LONG :
- if (dim == 2)
- result = itkProcess(img);
- else // if dim == 3
- result = itkProcess(img);
- break;
-
- case VTK_FLOAT :
- if (dim == 2)
- result = itkProcess(img);
- else // if dim == 3
- result = itkProcess(img);
- break;
-
- case VTK_DOUBLE :
- if (dim == 2)
- result = itkProcess(img);
- else // if dim == 3
- result = itkProcess(img);
- break;
-
- default :
- break;
- }
-
- return result;
-}
+vtkSmartPointer RegionGrowing::implementProcess(vtkSmartPointer img) {
+ vtkSmartPointer result = NULL;
+ if (img == NULL)
+ return result;
+
+ int* dims = img->GetDimensions();
+ int dim = 0;
+ if (dims[2] == 0)
+ dim = 2;
+ else
+ dim = 3;
+
+ int scalarType = img->GetScalarType();
+
+ switch (scalarType) {
+ case VTK_CHAR :
+ if (dim == 2)
+ result = itkProcess(img);
+ else // if dim == 3
+ result = itkProcess(img);
+ break;
+
+ case VTK_UNSIGNED_CHAR :
+ if (dim == 2)
+ result = itkProcess(img);
+ else // if dim == 3
+ result = itkProcess(img);
+ break;
+
+ case VTK_SIGNED_CHAR :
+ if (dim == 2)
+ result = itkProcess(img);
+ else // if dim == 3
+ result = itkProcess(img);
+ break;
+
+ case VTK_SHORT :
+ if (dim == 2)
+ result = itkProcess(img);
+ else // if dim == 3
+ result = itkProcess(img);
+ break;
+
+ case VTK_UNSIGNED_SHORT :
+ if (dim == 2)
+ result = itkProcess(img);
+ else // if dim == 3
+ result = itkProcess(img);
+ break;
+
+ case VTK_INT :
+ if (dim == 2)
+ result = itkProcess(img);
+ else // if dim == 3
+ result = itkProcess(img);
+ break;
+
+ case VTK_UNSIGNED_INT :
+ if (dim == 2)
+ result = itkProcess(img);
+ else // if dim == 3
+ result = itkProcess(img);
+ break;
+
+ case VTK_LONG :
+ if (dim == 2)
+ result = itkProcess(img);
+ else // if dim == 3
+ result = itkProcess(img);
+ break;
+
+ case VTK_UNSIGNED_LONG :
+ if (dim == 2)
+ result = itkProcess(img);
+ else // if dim == 3
+ result = itkProcess(img);
+ break;
+
+ case VTK_FLOAT :
+ if (dim == 2)
+ result = itkProcess(img);
+ else // if dim == 3
+ result = itkProcess(img);
+ break;
+
+ case VTK_DOUBLE :
+ if (dim == 2)
+ result = itkProcess(img);
+ else // if dim == 3
+ result = itkProcess(img);
+ break;
+
+ default :
+ break;
+ }
+
+ return result;
+}
+
+
diff --git a/sdk/actions/application/OpenFile.cpp b/sdk/actions/application/OpenFile.cpp
index 20b05267b9a91f16f845f6ddee8892f1740161b8..55461ebea5ba38cac69feb3d4e86e67b0a235a02 100644
--- a/sdk/actions/application/OpenFile.cpp
+++ b/sdk/actions/application/OpenFile.cpp
@@ -59,7 +59,7 @@ OpenFile::OpenFile (ActionExtension* extension) : Action (extension) {
getQAction()->setShortcutContext(Qt::ApplicationShortcut);
// the unique property is the filename
- Property* fileNameProperty = new Property(tr("File name"), "", tr("The name of the file to open."), "");
+ Property* fileNameProperty = new Property(tr("File Name"), "", tr("The name of the file to open."), "");
addParameter(fileNameProperty);
// lazy instanciation
diff --git a/sdk/actions/frame/editframes/FrameEditor.cpp b/sdk/actions/frame/editframes/FrameEditor.cpp
index 240a8385fb576268820ed20ef1ae12d3b0c2eb6c..9b710f69a29e9e462c54e6f6c4f5a0892dd36709 100644
--- a/sdk/actions/frame/editframes/FrameEditor.cpp
+++ b/sdk/actions/frame/editframes/FrameEditor.cpp
@@ -119,7 +119,6 @@ void FrameEditor::init() {
connect(ui.translatePushButton, SIGNAL(clicked()), this, SLOT(translate()));
connect(ui.setTranslationPushButton, SIGNAL(clicked()), this, SLOT(setTranslation()));
-// connect(ui.transformationTableWidget, SIGNAL(cellChanged(int, int)), this, SLOT(transformationChanged()));
for (int j = 0; j < 4; j++) {
for (int i = 0; i < 4; i++) {
connect(transfromMatrixElements[j][i], SIGNAL(returnPressed()), this, SLOT(transformationChanged()));
@@ -159,7 +158,12 @@ QWidget* FrameEditor::getWidget() {
// --------------- initializeDialogWithCurrentComponent -------------------
void FrameEditor::initializeDialogWithCurrentComponent() {
-// ui.displayFrameCheckBox->setChecked(false);
+ // update checkbox
+ ui.displayFrameCheckBox->blockSignals(true);
+ bool isFrameDisplayed = currentComponent->getFrameVisibility(InteractiveViewer::get3DViewer());
+ ui.displayFrameCheckBox->setChecked(isFrameDisplayed);
+ ui.displayFrameCheckBox->blockSignals(false);
+
// Update the Parent Frame
bool parentFrameSignalState = ui.parentFrameComboBox->blockSignals(true);
ui.parentFrameComboBox->clear();
diff --git a/sdk/actions/image/reconstruction/integration-testdata/asm-input.scxml b/sdk/actions/image/reconstruction/integration-testdata/asm-input.scxml
index 8caf73fa0459ade2a04fec550bab4e489217e195..79de170e93d3d8b51f208ccb0bf2ba11be186168 100644
--- a/sdk/actions/image/reconstruction/integration-testdata/asm-input.scxml
+++ b/sdk/actions/image/reconstruction/integration-testdata/asm-input.scxml
@@ -15,14 +15,8 @@
Open File
-
-
@@ -46,7 +40,6 @@
-
diff --git a/sdk/applications/actionstatemachine/ActionState.h b/sdk/applications/actionstatemachine/ActionState.h
index 8e60468178039a123d77e646af669a8f28465b51..d671003a291613a19c70e23d4b8a5c8667da1067 100644
--- a/sdk/applications/actionstatemachine/ActionState.h
+++ b/sdk/applications/actionstatemachine/ActionState.h
@@ -47,6 +47,8 @@
*/
class ActionState : public QState {
+ Q_OBJECT
+
public:
/**
*/
diff --git a/sdk/applications/actionstatemachine/ActionStateMachine.cpp b/sdk/applications/actionstatemachine/ActionStateMachine.cpp
index e24588363c8e9f0179cf0340fd8bfaf4f1286e9e..ef6f446373bd5d0f3b2e4c5b8239c61a2e5162f7 100644
--- a/sdk/applications/actionstatemachine/ActionStateMachine.cpp
+++ b/sdk/applications/actionstatemachine/ActionStateMachine.cpp
@@ -129,7 +129,7 @@ void ActionStateMachine::autoNext() {
setProperty("Message Box Level", InterfaceLogger::NONE);
// machine.configuration() returns all the current state, the first on is the active state
- ActionState* currentState = dynamic_cast(machine.configuration().toList().first());
+ ActionState* currentState = qobject_cast(machine.configuration().toList().first());
// loop until no more state is available
while (currentState!=nullptr && currentState->transitions().size()>0) {
@@ -138,7 +138,8 @@ void ActionStateMachine::autoNext() {
bool foundNextState = false;
while (it!=currentState->transitions().end() && !foundNextState) { // && nextState==nullptr) {
// all transition in this state machine are ActionTransition instances...
- ActionTransition* currentActionTransition = dynamic_cast(*it);
+ ActionTransition* currentActionTransition = qobject_cast(*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)
diff --git a/sdk/applications/actionstatemachine/ActionTransition.h b/sdk/applications/actionstatemachine/ActionTransition.h
index 944a2e4eb04ccec5214d43beaa3f4885385bccc1..295a212683ae09cad3d409be3d4e5398f7fd3fc4 100644
--- a/sdk/applications/actionstatemachine/ActionTransition.h
+++ b/sdk/applications/actionstatemachine/ActionTransition.h
@@ -57,6 +57,7 @@ class ActionState;
*
*/
class ActionTransition : public QSignalTransition {
+ Q_OBJECT
public:
diff --git a/sdk/applications/imp/ImpMainWindow.cpp b/sdk/applications/imp/ImpMainWindow.cpp
index 176ef0617e11f82a42ea066fd2d349900df60eb3..0d6d7e9cd9151dbc0d043ec04e678852f206905f 100644
--- a/sdk/applications/imp/ImpMainWindow.cpp
+++ b/sdk/applications/imp/ImpMainWindow.cpp
@@ -180,7 +180,7 @@ void ImpMainWindow::initActions() {
connect(editApplicationSettings, SIGNAL(triggered()), this, SLOT(editSettings()));
// save history as SCXML
- saveHistory = new QAction(tr("&Save history"), this);
+ saveHistory = new QAction(tr("&Save History"), this);
saveHistory->setStatusTip(tr("Save the history of actions processed as an SCXML file."));
saveHistory->setWhatsThis(tr("Save the history of actions processed as an SCXML file."));
connect(saveHistory, SIGNAL(triggered()), this, SLOT(saveHistoryAsSCXML()));
diff --git a/sdk/applications/testactions/main.cpp b/sdk/applications/testactions/main.cpp
index be65b6b81e867bf93df96411d09626df9893a0f5..f9889cec66cb3adff948ea8b3be8ff21370cb5f9 100644
--- a/sdk/applications/testactions/main.cpp
+++ b/sdk/applications/testactions/main.cpp
@@ -130,6 +130,7 @@ int main(int argc, char* argv[]) {
if (loadAdditionnalComponentExtension) {
std::cout << "- additional component extension: \"" << o.component() << "\"" << std::endl;
}
+ std::cout << "Working directory: " << QDir::currentPath().toStdString() << std::endl;
testInit("Starting the camitk default application...");
diff --git a/sdk/cmake/ctest/ci-setup.cmake b/sdk/cmake/ctest/ci-setup.cmake
index 8db312941be9d640f7c6e0021c6b0c449da14ff7..9b48f2d5dc1eaff1500dafc9f9875878b15c5783 100644
--- a/sdk/cmake/ctest/ci-setup.cmake
+++ b/sdk/cmake/ctest/ci-setup.cmake
@@ -115,7 +115,9 @@ endif()
# parallelize ci scripts if possible
include(ProcessorCount)
ProcessorCount(NUMBER_OF_PROC)
-if(NOT NUMBER_OF_PROC EQUAL 0)
+# remove some to avoid processor overload
+MATH(EXPR NUMBER_OF_PROC "${NUMBER_OF_PROC}-2")
+if(NUMBER_OF_PROC GREATER 0)
if(COMPILER MATCHES "GCC" OR COMPILER MATCHES "Ninja")
set(CTEST_BUILD_FLAGS -j${NUMBER_OF_PROC})
elseif(COMPILER MATCHES "MSVC.*")
diff --git a/sdk/cmake/ctest/ci-test.cmake b/sdk/cmake/ctest/ci-test.cmake
index 7e24e8d3a311df8a2e214941dbd092764e0807de..2cf32d50b1fcaa3a0303739c614a9ba4e3a45791 100644
--- a/sdk/cmake/ctest/ci-test.cmake
+++ b/sdk/cmake/ctest/ci-test.cmake
@@ -42,8 +42,8 @@ ci_start_log(FILENAME "${CI_PROJECT_LOG_DIRECTORY}/ci-test.log")
# ------------------------ STEP 2: test ------------------------
ci_log("Step 2. Test all CAMITK_TARGETs... Using ${NUMBER_OF_PROC} tests in parallel")
-# set extra time for test (default is 600 s)
-set(CTEST_TEST_TIMEOUT 1500)
+# set extra time for test to 30 min = 1800 s (default is 10 min = 600 s)
+set(CTEST_TEST_TIMEOUT 1800)
# Get the CAMITK_TARGETs listing (automatically created at configuration step)
include("${CTEST_BINARY_DIRECTORY}/Subprojects.cmake")
diff --git a/sdk/cmake/modules/macros/camitk/test/CamiTKAddTest.cmake b/sdk/cmake/modules/macros/camitk/test/CamiTKAddTest.cmake
index 3d91977418b4ee7bbecc418bbb381e01033256a9..37474e0d70f151ea54545cf6216c3c5c810a5970 100644
--- a/sdk/cmake/modules/macros/camitk/test/CamiTKAddTest.cmake
+++ b/sdk/cmake/modules/macros/camitk/test/CamiTKAddTest.cmake
@@ -12,7 +12,7 @@
#! Usage:
#! \code
#! camitk_add_test(EXECUTABLE_ARGS "arg1 arg2 arg3"
-#! PASS_FILE pristineOutput
+#! PASS_FILE_OUTPUT pristineOutput
#! PASS_REGULAR_EXPRESSION regexp
#! FAIL_REGULAR_EXPRESSION regexp
#! PROJECT_NAME name
@@ -21,7 +21,7 @@
#! \endcode
#!
#! \param EXECUTABLE_ARGS (optional) The executable arguments (all in double quotes), typically each test will have different arguments. Can be empty
-#! \param PASS_FILE (optional) If specified the test to perform is to compare the output of the command to this file. It the output is the same, then the test is passed, otherwise it is failed.
+#! \param PASS_FILE_OUTPUT (optional) If specified the test to perform is to compare the output of the command to this file. It the output is the same, then the test is passed, otherwise it is failed.
#! \param PASS_REGULAR_EXPRESSION (optional) This is equivalent to "PASS_REGULAR_EXPRESSION regexp" property for the test, see http://www.cmake.org/Wiki/CTest:FAQ#My_test_does_not_return_non-zero_on_failure._What_can_I_do.3F
#! \param FAIL_REGULAR_EXPRESSION This is equivalent to "FAIL_REGULAR_EXPRESSION regexp" property for the test, see http://www.cmake.org/Wiki/CTest:FAQ#My_test_does_not_return_non-zero_on_failure._What_can_I_do.3F
#! \param PROJECT_NAME Base name for the test, can be used for ctest -S
diff --git a/sdk/libraries/core/action/Action.cpp b/sdk/libraries/core/action/Action.cpp
index 084a74c0f2cbeab6ee7cc4c95be3ed6f784b36e4..26c8124fa41a59dd0d73cb213c9748176d1b145b 100644
--- a/sdk/libraries/core/action/Action.cpp
+++ b/sdk/libraries/core/action/Action.cpp
@@ -186,7 +186,7 @@ Action::ApplyStatus Action::trigger(QWidget* parent) {
if (targetComponents.size() > 0 || getComponent().isEmpty()) {
if (isEmbedded) {
// if there are no parents to use use the action viewer
- if (!parent) {
+ if (parent == nullptr) {
ActionViewer::getInstance()->embedActionWidget(this);
}
else {
diff --git a/sdk/libraries/core/action/Action.h b/sdk/libraries/core/action/Action.h
index 6206db097e047ad9989dea277af1a2db8ae1d12e..bc3b28d986de2e635836401f6216b904abcf646d 100644
--- a/sdk/libraries/core/action/Action.h
+++ b/sdk/libraries/core/action/Action.h
@@ -241,7 +241,7 @@ public slots:
* The parent widget is used if the action is embedded, see class description for more information about the algorithm.
* This method cannot be redefined in inherited class.
*/
- ApplyStatus trigger(QWidget* parent = NULL);
+ ApplyStatus trigger(QWidget* parent = nullptr);
/**
* This method is called when the action has to be applied on the target list (get the target lists using getTargets())
diff --git a/sdk/libraries/core/application/Application.cpp b/sdk/libraries/core/application/Application.cpp
index c23f3f89d4cac7f05dd34b8b943a87e99c56899e..76187e0244eac69815826b1ad45447917fe75a91 100644
--- a/sdk/libraries/core/application/Application.cpp
+++ b/sdk/libraries/core/application/Application.cpp
@@ -41,6 +41,7 @@
#include
#include
#include
+#include
// -- VTK stuff (only for updating progress bar via vtk filters)
#include
@@ -214,6 +215,32 @@ void Application::quitting() {
}
}
+// ----------------- notify --------------------
+bool Application::notify(QObject* receiver, QEvent* event) {
+ bool done = true;
+ std::exception_ptr otherException;
+ try {
+ done = QApplication::notify(receiver, event);
+ }
+ catch (const std::exception& e) {
+ CAMITK_ERROR(tr("Caught a std exception: %1").arg(e.what()))
+ }
+ catch (...) {
+ CAMITK_ERROR(tr("Caught an unknown exception"))
+ otherException = std::current_exception();
+ try {
+ if (otherException) {
+ std::rethrow_exception(otherException);
+ }
+ }
+ catch (const std::exception& e) {
+ CAMITK_ERROR(tr("Exception: %1").arg(e.what()))
+ }
+ }
+
+ return done;
+}
+
// ----------------- setMainWindow --------------------
void Application::setMainWindow(MainWindow* mw) {
if (mw == NULL) {
@@ -429,10 +456,10 @@ Component* Application::open(const QString& fileName) {
resetProgressBar();
CAMITK_ERROR_ALT(tr("ComponentExtension Opening Error: cannot find the appropriate component plugin for opening:\n\"%1\" (extension \"%2\" or \"%3\")\nTo solve this problem, make sure that:\n - A corresponding valid plugin is present in one of the following directories: \"%4\"\n - Your application loaded the the appropriate extension before trying to open a file")
- .arg(fileName,
- fileInfo.suffix(),
- fileInfo.completeSuffix(),
- Core::getComponentDirectories().join(", ")))
+ .arg(fileName,
+ fileInfo.suffix(),
+ fileInfo.completeSuffix(),
+ Core::getComponentDirectories().join(", ")))
}
else {
std::exception_ptr otherException;
@@ -558,10 +585,10 @@ Component* Application::openDirectory(const QString& dirName, const QString& plu
restoreOverrideCursor();
resetProgressBar();
CAMITK_ERROR_ALT(tr("Opening Error: Cannot find the appropriate component plugin for opening directory:\n%1\n"
- "To solve this problem, make sure that:\n"
- " - A corresponding valid plugin is present in one of the component directories: \"%2\"\n"
- " - And either your application is initialized with the autoloadExtensions option\n"
- " - Or your correctly registered your component in the CamiTK settings").arg(dirName, Core::getComponentDirectories().join(", ")))
+ "To solve this problem, make sure that:\n"
+ " - A corresponding valid plugin is present in one of the component directories: \"%2\"\n"
+ " - And either your application is initialized with the autoloadExtensions option\n"
+ " - Or your correctly registered your component in the CamiTK settings").arg(dirName, Core::getComponentDirectories().join(", ")))
}
// restore the normal cursor/progress bar
@@ -634,17 +661,17 @@ bool Application::save(Component* component) {
// -- check the validity of the plugin
if (!componentExtension) {
CAMITK_ERROR_ALT(tr("Saving Error: cannot find the appropriate component plugin for saving component:\n"
- "\"%1\"\n"
- "In file:\n"
- "\"%1\" (extension \"%2\" or \"%3\")\n"
- "To solve this problem, make sure that:\n"
- " - A corresponding valid plugin is present in one of the component directories: \"%4\"\n"
- " - And either your application is initialized with the autoloadExtensions option\n"
- " - Or your correctly registered your component in the CamiTK settings")
- .arg(component->getName(),
- fileInfo.suffix(),
- fileInfo.completeSuffix(),
- Core::getComponentDirectories().join(", ")))
+ "\"%1\"\n"
+ "In file:\n"
+ "\"%1\" (extension \"%2\" or \"%3\")\n"
+ "To solve this problem, make sure that:\n"
+ " - A corresponding valid plugin is present in one of the component directories: \"%4\"\n"
+ " - And either your application is initialized with the autoloadExtensions option\n"
+ " - Or your correctly registered your component in the CamiTK settings")
+ .arg(component->getName(),
+ fileInfo.suffix(),
+ fileInfo.completeSuffix(),
+ Core::getComponentDirectories().join(", ")))
return false;
}
else {
@@ -688,12 +715,12 @@ int Application::registerAllActions(ActionExtension* ext) {
// check if an action with same name was not already registered
if (getActionMap().contains(action->getName())) {
CAMITK_ERROR_ALT(tr("Cannot register action: %1 (extension: %2, family: %3, description: \"%4\")\n"
- "extension of same name already registered by extension \"%5\"")
- .arg(action->getName(),
- action->getExtensionName(),
- action->getFamily(),
- action->getDescription(),
- getAction(action->getName())->getExtensionName()))
+ "extension of same name already registered by extension \"%5\"")
+ .arg(action->getName(),
+ action->getExtensionName(),
+ action->getFamily(),
+ action->getDescription(),
+ getAction(action->getName())->getExtensionName()))
}
else {
getActionMap().insert(action->getName(), action);
@@ -916,36 +943,38 @@ void Application::saveHistoryAsSXML() {
}
// Create the XML document
- QDomDocument* doc = new QDomDocument();
+ QDomDocument doc;
+ QDomNode xmlProlog = doc.createProcessingInstruction("xml","version=\"1.0\" encoding=\"UTF-8\"");
+ doc.appendChild(xmlProlog);
// root element
- QDomElement root = doc->createElement("scxml");
+ QDomElement root = doc.createElement("scxml");
root.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
root.setAttribute("xmlns", "http://camitk.imag.fr/3/smallScxml");
root.setAttribute("xmlns:camitk", "http://camitk.imag.fr/3/asm");
root.setAttribute("xsi:schemaLocation", "http://camitk.imag.fr/3/smallScxml/../resources/smallScxml.xsd");
root.setAttribute("initial", "Initialize");
- doc->appendChild(root);
+ doc.appendChild(root);
// SXML always contains an Initialize element which describe the pipeline
- QDomElement initializeElt = doc->createElement("state");
+ QDomElement initializeElt = doc.createElement("state");
root.appendChild(initializeElt);
initializeElt.setAttribute("id", "Initialize");
- QDomElement initializeElt_onEntry = doc->createElement("onentry");
+ QDomElement initializeElt_onEntry = doc.createElement("onentry");
initializeElt.appendChild(initializeElt_onEntry);
- QDomElement initializeElt_onState = doc->createElement("camitk:onState");
+ QDomElement initializeElt_onState = doc.createElement("camitk:onState");
initializeElt_onEntry.appendChild(initializeElt_onState);
// Description of the pipeline
- QDomElement initializeElt_desc = doc->createElement("camitk:description");
+ QDomElement initializeElt_desc = doc.createElement("camitk:description");
initializeElt_onState.appendChild(initializeElt_desc);
// create the pipeline description that will be filled whilel processing the history items.
QString pipelineDescription = "This pipeline will process several actions on the input component(s):
";
// Transition
- QDomElement initializeElt_transition = doc->createElement("transition");
+ QDomElement initializeElt_transition = doc.createElement("transition");
initializeElt_transition.setAttribute("event", "Next");
initializeElt_transition.setAttribute("target", "Action 1");
initializeElt.appendChild(initializeElt_transition);
- QDomElement initializeElt_transition2 = doc->createElement("transition");
+ QDomElement initializeElt_transition2 = doc.createElement("transition");
// Create a list of all components created during the pipeline, to know which ones to delete once pipeline is reset
// by the action state machine
@@ -957,55 +986,52 @@ void Application::saveHistoryAsSXML() {
HistoryItem historyItem = Application::getHistory().at(i);
Action* action = Application::getAction(historyItem.getName());
// state
- QDomElement stateElement = doc->createElement("state");
+ QDomElement stateElement = doc.createElement("state");
root.appendChild(stateElement);
stateElement.setAttribute("id", "Action " + QString::number(i + 1));
// onEntry
- QDomElement onentryElement = doc->createElement("onentry");
+ QDomElement onentryElement = doc.createElement("onentry");
stateElement.appendChild(onentryElement);
- QDomElement onStateElement = doc->createElement("camitk:onState");
+ QDomElement onStateElement = doc.createElement("camitk:onState");
onentryElement.appendChild(onStateElement);
// action description
- QDomElement descriptionElement = doc->createElement("camitk:description");
- QDomText descriptionText = doc->createTextNode(action->getDescription());
+ QDomElement descriptionElement = doc.createElement("camitk:description");
+ QDomText descriptionText = doc.createTextNode(action->getDescription());
descriptionElement.appendChild(descriptionText);
onStateElement.appendChild(descriptionElement);
// action name & parameters
- QDomElement actionElement = doc->createElement("camitk:action");
+ QDomElement actionElement = doc.createElement("camitk:action");
onStateElement.appendChild(actionElement);
// action name
- QDomElement actionElementName = doc->createElement("camitk:name");
+ QDomElement actionElementName = doc.createElement("camitk:name");
actionElement.appendChild(actionElementName);
pipelineDescription.append("- " + action->getName() + "
");
- QDomText actionElementNameText = doc->createTextNode(action->getName());
+ QDomText actionElementNameText = doc.createTextNode(action->getName());
actionElementName.appendChild(actionElementNameText);
// action parameters
+ QDomElement parametersElement = doc.createElement("camitk:parameters");
+ actionElement.appendChild(parametersElement);
if (!action->dynamicPropertyNames().isEmpty()) {
- QDomElement parametersElement = doc->createElement("camitk:parameters");
- actionElement.appendChild(parametersElement);
foreach (QByteArray actionParameter, action->dynamicPropertyNames()) {
- QDomElement parameterElement = doc->createElement("camitk:parameter");
- parametersElement.appendChild(parameterElement);
+ QDomElement parameterElement = doc.createElement("camitk:parameter");
parameterElement.setAttribute("name", QString(actionParameter));
parameterElement.setAttribute("type", QVariant::typeToName(action->property(actionParameter).type()));
parameterElement.setAttribute("value", action->property(actionParameter.data()).toString());
+ parametersElement.appendChild(parameterElement);
}
}
- QDomElement actionElementParam = doc->createElement("camitk:parameters");
- actionElement.appendChild(actionElementParam);
-
// action input components
if (!historyItem.getInputHistoryComponents().isEmpty()) {
- QDomElement actionElementInputComp = doc->createElement("camitk:inputs");
+ QDomElement actionElementInputComp = doc.createElement("camitk:inputs");
actionElement.appendChild(actionElementInputComp);
for (int j = 0; j < historyItem.getInputHistoryComponents().size(); j++) {
- QDomElement componentElement = doc->createElement("camitk:component");
+ QDomElement componentElement = doc.createElement("camitk:component");
// determine the type of each input component (image, meshes or other)
HistoryComponent inputHistoryComponents = historyItem.getInputHistoryComponents().at(j);
@@ -1034,11 +1060,11 @@ void Application::saveHistoryAsSXML() {
// action output components
if (!historyItem.getOutputHistoryComponents().isEmpty()) {
- QDomElement outputsElement = doc->createElement("camitk:outputs");
+ QDomElement outputsElement = doc.createElement("camitk:outputs");
actionElement.appendChild(outputsElement);
for (int j = 0; j < historyItem.getOutputHistoryComponents().size(); j++) {
- QDomElement componentElement = doc->createElement("camitk:component");
+ QDomElement componentElement = doc.createElement("camitk:component");
// determine the type of each input component (image, meshes or other)
HistoryComponent outputHistoryComponents = historyItem.getOutputHistoryComponents().at(j);
allCreatedComponents.append(outputHistoryComponents); // note the component created
@@ -1069,7 +1095,7 @@ void Application::saveHistoryAsSXML() {
// Transitions
if (Application::getHistory().size() >= 1) { // else, no transition at all
// Next transition
- QDomElement nextTransitionElement = doc->createElement("transition");
+ QDomElement nextTransitionElement = doc.createElement("transition");
if (i == Application::getHistory().size() - 1) { // Last action element => next element = Bye element.
nextTransitionElement.setAttribute("target", "Bye");
@@ -1081,7 +1107,7 @@ void Application::saveHistoryAsSXML() {
nextTransitionElement.setAttribute("event", "Next");
// Back transition
- QDomElement backTransitionElement = doc->createElement("transition");
+ QDomElement backTransitionElement = doc.createElement("transition");
backTransitionElement.setAttribute("event", "Back");
if (i == 0) { // Back to Initialize state
@@ -1094,13 +1120,13 @@ void Application::saveHistoryAsSXML() {
if (!previousItem.getOutputHistoryComponents().isEmpty()) {
// Ask for deletion of each component created at the previous element
- QDomElement onTransitionElement = doc->createElement("onTransition");
+ QDomElement onTransitionElement = doc.createElement("onTransition");
backTransitionElement.appendChild(onTransitionElement);
- QDomElement closeElement = doc->createElement("camitk:close");
+ QDomElement closeElement = doc.createElement("camitk:close");
onTransitionElement.appendChild(closeElement);
foreach (HistoryComponent outputHistoryComponent, previousItem.getOutputHistoryComponents()) {
- QDomElement backTransitionComponentElement = doc->createElement("camitk:component");
+ QDomElement backTransitionComponentElement = doc.createElement("camitk:component");
closeElement.appendChild(backTransitionComponentElement);
switch (outputHistoryComponent.getType()) {
@@ -1127,42 +1153,42 @@ void Application::saveHistoryAsSXML() {
stateElement.appendChild(backTransitionElement);
// and "Next" appears on the right
stateElement.appendChild(nextTransitionElement);
-
+
} // End transitions
}
// Update description of the pipeline, now that we have filled the it!
- initializeElt_desc.appendChild(doc->createCDATASection(pipelineDescription));
+ initializeElt_desc.appendChild(doc.createCDATASection(pipelineDescription));
// Last element : Bye
- QDomElement finalElt = doc->createElement("state");
+ QDomElement finalElt = doc.createElement("state");
root.appendChild(finalElt);
finalElt.setAttribute("id", "Bye");
finalElt.setAttribute("final", "true");
- QDomElement finalElt_onEntry = doc->createElement("onentry");
+ QDomElement finalElt_onEntry = doc.createElement("onentry");
finalElt.appendChild(finalElt_onEntry);
- QDomElement finalElt_onState = doc->createElement("camitk:onState");
+ QDomElement finalElt_onState = doc.createElement("camitk:onState");
finalElt_onEntry.appendChild(finalElt_onState);
// Thanks !
- QDomElement finalElt_desc = doc->createElement("camitk:description");
+ QDomElement finalElt_desc = doc.createElement("camitk:description");
finalElt_onState.appendChild(finalElt_desc);
QDomCDATASection finalEltDesc;
- finalElt_desc.appendChild(doc->createCDATASection("Thanks you for using the CamiTK Action State Machine !"));
+ finalElt_desc.appendChild(doc.createCDATASection("Thanks you for using the CamiTK Action State Machine !"));
// Transition
- QDomElement finalElt_transition = doc->createElement("transition");
+ QDomElement finalElt_transition = doc.createElement("transition");
finalElt_transition.setAttribute("event", "Back to the beginning");
finalElt_transition.setAttribute("target", "Initialize");
finalElt.appendChild(finalElt_transition);
// Ask for deletion of all components created in the pipeline
if (!allCreatedComponents.isEmpty()) {
- QDomElement finalEltTransition_onTransition = doc->createElement("onTransition");
+ QDomElement finalEltTransition_onTransition = doc.createElement("onTransition");
finalElt_transition.appendChild(finalEltTransition_onTransition);
- QDomElement finalEltTransition_close = doc->createElement("camitk:close");
+ QDomElement finalEltTransition_close = doc.createElement("camitk:close");
finalEltTransition_onTransition.appendChild(finalEltTransition_close);
foreach (HistoryComponent createdComponent, allCreatedComponents) {
- QDomElement finalEltTransition_comp = doc->createElement("camitk:component");
+ QDomElement finalEltTransition_comp = doc.createElement("camitk:component");
finalEltTransition_close.appendChild(finalEltTransition_comp);
switch (createdComponent.getType()) {
@@ -1184,20 +1210,17 @@ void Application::saveHistoryAsSXML() {
}
}
- // note, final element will automatically have a "Quit" transition, added by the action state machine.
-
-
- // Get the xml of the tree node
- QString xml = doc->toString();
+ // note: final element will automatically have a "Quit" transition, added by the action state machine.
// Write the xml to a file
- QString outputFileName = QFileDialog::getSaveFileName(NULL, tr("Save history of actions ..."), Core::getCurrentWorkingDir() + "/actions_history.xml", tr("XML Files (*.xml)"));
+ QString outputFileName = QFileDialog::getSaveFileName(NULL, tr("Save history of actions ..."), Core::getCurrentWorkingDir() + "/camitk-history-" + QDateTime::currentDateTime().toString("yyyyMMdd-HHmmss") + ".scxml", tr("SCXML Files (*.scxml)"));
- QFile* outputFile = new QFile(outputFileName);
+ QFile outputFile(outputFileName);
- if (outputFile->open(QFile::WriteOnly)) {
- QTextStream out(outputFile);
- out << xml;
+ if (outputFile.open(QFile::WriteOnly | QFile::Text)) {
+ QTextStream out(&outputFile);
+ // automatically indent XML output
+ doc.save(out, 4);
}
else {
CAMITK_ERROR_ALT(tr("Cannot open file \"%1\" for writing. No history saved.").arg(outputFileName))
diff --git a/sdk/libraries/core/application/Application.h b/sdk/libraries/core/application/Application.h
index dd35020bec6b284f0748b62e1de89c1afca41da0..2ad5e6b740f6432abcf7c592959f595a88f2a5e1 100644
--- a/sdk/libraries/core/application/Application.h
+++ b/sdk/libraries/core/application/Application.h
@@ -103,6 +103,9 @@ public:
*/
/// @{
+ /// reimplemented from QApplication to catch all exception from external libs used in CEP (e.g. from ITK) and avoid crashes...
+ bool notify(QObject* , QEvent* );
+
/// get the application name
static QString getName();
diff --git a/sdk/libraries/core/viewer/ActionViewer.cpp b/sdk/libraries/core/viewer/ActionViewer.cpp
index f7789d5adba5052e82c0104286bba87f327c31bc..9a396727ce1c2a4716e6c4ef0a3a6939a06c8938 100644
--- a/sdk/libraries/core/viewer/ActionViewer.cpp
+++ b/sdk/libraries/core/viewer/ActionViewer.cpp
@@ -231,7 +231,7 @@ void ActionViewer::updateActionViewer(UpdateReason reason) {
ActionList actionset = Application::getActions(Application::getSelectedComponents(), tagLineEdit->text());
if (!actionset.isEmpty()) {
- if (1 == actionset.size()) {
+ if (actionset.size() == 1) {
action = *(actionset.begin());
nameComboBox->setCurrentIndex(nameComboBox->findText(action->getName()));
updateActionViewer(ActionNameChanged);
diff --git a/tutorials/actions/sleepingwhileworking/CMakeLists.txt b/tutorials/actions/sleepingwhileworking/CMakeLists.txt
index 0c71c8f9180709615cc55b941c129ba5934cbe20..ee4a067f79f5d981e155bfc099bbb8c623216eb9 100644
--- a/tutorials/actions/sleepingwhileworking/CMakeLists.txt
+++ b/tutorials/actions/sleepingwhileworking/CMakeLists.txt
@@ -3,24 +3,3 @@ camitk_extension(ACTION_EXTENSION
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
)
-
-# Tests fail due to OpenGL crashing when accessed inside a VM
-if(WIN32)
- set_tests_properties(action-sleepingwhileworking-level1-2
- action-sleepingwhileworking-level1-3
- action-sleepingwhileworking-level1-4
- action-sleepingwhileworking-level1-5
- action-sleepingwhileworking-level1-6
- action-sleepingwhileworking-level1-7
- action-sleepingwhileworking-level1-8
- action-sleepingwhileworking-level1-9
- action-sleepingwhileworking-level1-10
- action-sleepingwhileworking-level1-11
- action-sleepingwhileworking-level1-12
- action-sleepingwhileworking-level1-13
- action-sleepingwhileworking-level1-14
- action-sleepingwhileworking-level1-15
- action-sleepingwhileworking-level1-16
- action-sleepingwhileworking-level1-17
- PROPERTIES WILL_FAIL true)
-endif()
diff --git a/tutorials/actions/sleepingwhileworking/WorkingWhenSleepingLinear.cpp b/tutorials/actions/sleepingwhileworking/WorkingWhenSleepingLinear.cpp
index 0e6e310dc3e6ff1ff5d0a1367a615012bc4fe062..5257ad7287164b7558ea52aa010f415fa43054ac 100644
--- a/tutorials/actions/sleepingwhileworking/WorkingWhenSleepingLinear.cpp
+++ b/tutorials/actions/sleepingwhileworking/WorkingWhenSleepingLinear.cpp
@@ -177,8 +177,14 @@ void WorkingWhenSleepingLinear::process(ImageComponent* comp) {
camitk::Application::setProgressBarValue(100 * n / numberOfWindows);
myMedicalImageViewer->refresh();
- Application::refresh();
- Application::processEvents();
+ // In order to see the change in the viewers, the initial idea was to call
+ // Application::processEvents();
+ // but, as explained in the Qt documentation:
+ // > In the event that you are running a local loop which calls this function continuously,
+ // > without an event loop, the DeferredDelete events will not be processed. This can affect
+ // > the behaviour of widgets, e.g. QToolTip, that rely on DeferredDelete events to function
+ // > properly. An alternative would be to call sendPostedEvents() from within that local loop.
+ Application::sendPostedEvents();
}
// set normal zoom
diff --git a/tutorials/actions/sleepingwhileworking/WorkingWhenSleepingRandom.cpp b/tutorials/actions/sleepingwhileworking/WorkingWhenSleepingRandom.cpp
index 5188342e4be523d691dbfc7f80398c7a59c44d1a..7477e0080be8429c4d8d363924c5dd43965bcc47 100644
--- a/tutorials/actions/sleepingwhileworking/WorkingWhenSleepingRandom.cpp
+++ b/tutorials/actions/sleepingwhileworking/WorkingWhenSleepingRandom.cpp
@@ -108,9 +108,14 @@ void WorkingWhenSleepingRandom::process(ImageComponent* comp) {
// Refresh the Viewers ....
myMedicalImageViewer->refresh();
- Application::refresh();
- Application::processEvents();
- }
+ // In order to see the change in the viewers, the initial idea was to call
+ // Application::processEvents();
+ // but, as explained in the Qt documentation:
+ // > In the event that you are running a local loop which calls this function continuously,
+ // > without an event loop, the DeferredDelete events will not be processed. This can affect
+ // > the behaviour of widgets, e.g. QToolTip, that rely on DeferredDelete events to function
+ // > properly. An alternative would be to call sendPostedEvents() from within that local loop.
+ Application::sendPostedEvents(); }
}