From 8e3e04d1112beec00be676602f3a45c517d91225 Mon Sep 17 00:00:00 2001 From: Emmanuel Promayon Date: Wed, 29 Jan 2020 17:34:32 +0100 Subject: [PATCH 01/15] FIXED comment --- sdk/actions/image/arbitraryslice/AnglesAndTranslationAction.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/actions/image/arbitraryslice/AnglesAndTranslationAction.h b/sdk/actions/image/arbitraryslice/AnglesAndTranslationAction.h index b2a45024..4fe6b39b 100644 --- a/sdk/actions/image/arbitraryslice/AnglesAndTranslationAction.h +++ b/sdk/actions/image/arbitraryslice/AnglesAndTranslationAction.h @@ -57,7 +57,7 @@ public: /// manage change in the action parameters (angles and slice number) virtual bool event(QEvent* e); - // reset transform to identity + /// reset transform to identity void resetTransform(); public slots: -- GitLab From 31b3c1760dde6ac20d1ece2e3e3c983a7bf8279a Mon Sep 17 00:00:00 2001 From: Emmanuel Promayon Date: Wed, 5 Feb 2020 11:08:56 +0100 Subject: [PATCH 02/15] MERGED current develop with viewer-extension-instance-extension --- .../components/pmlcomponent/PMLComponent.cpp | 4 +- sdk/CMakeLists.txt | 2 +- sdk/actions/application/CMakeLists.txt | 1 + sdk/actions/application/Show3DViewer.cpp | 3 +- sdk/actions/application/ShowAllViewers.cpp | 2 +- .../application/ShowArbitraryViewer.cpp | 2 +- sdk/actions/application/ShowAxialViewer.cpp | 2 +- sdk/actions/application/ShowCoronalViewer.cpp | 2 +- .../application/ShowSagittalViewer.cpp | 2 +- sdk/actions/frame/editframes/FrameEditor.cpp | 24 +-- sdk/actions/frame/editframes/FrameEditor.h | 1 + .../pixelcolorchanger/PixelColorChanger.cpp | 12 +- .../ImageReconstructionAction.cpp | 7 +- .../image/reorientimage/CMakeLists.txt | 1 + .../image/reorientimage/ReorientImage.cpp | 17 +- .../image/reorientimage/ReorientImage.h | 9 +- .../image/reorientimage/ReorientImage.ui | 12 +- .../volumerendering/VolumeRenderingAction.cpp | 15 +- .../volumerendering/VolumeRenderingAction.h | 1 + sdk/actions/mesh/basicmesh/CenterMesh.h | 2 +- sdk/actions/mesh/basicmesh/ChangeColor.cpp | 2 +- sdk/actions/mesh/basicmesh/MeshPicking.cpp | 2 +- sdk/actions/mesh/basicmesh/RigidTransform.cpp | 8 +- sdk/actions/mesh/basicmesh/RigidTransform.h | 4 +- .../mesh/meshprocessing/MeshClipping.cpp | 6 +- .../MeshProcessingExtension.cpp | 3 +- .../actionstatemachine/ActionState.cpp | 2 +- .../actionstatemachine/ActionStateMachine.cpp | 17 +- .../actionstatemachine/ActionStateViewer.cpp | 32 +-- .../actionstatemachine/ActionStateViewer.h | 19 +- .../ActionStateViewerExtension.cpp | 36 ++++ .../ActionStateViewerExtension.h | 61 ++++++ .../actionstatemachine/ActionStateWidget.cpp | 16 +- .../actionstatemachine/ActionTransition.cpp | 2 +- .../actionstatemachine/CMakeLists.txt | 3 +- .../testdata/asmSimpleImageFilter.xml | 58 ++--- .../testdata/asmSimpleMeshProcessing.xml | 22 +- sdk/applications/imp/CMakeLists.txt | 5 +- sdk/applications/imp/ImpMainWindow.cpp | 136 ++++++------ sdk/applications/imp/ImpMainWindow.h | 2 +- sdk/applications/wizard/CMakeLists.txt | 1 + .../macros/camitk/CamiTKApplication.cmake | 2 +- sdk/components/msh/MshComponent.cpp | 5 +- sdk/components/off/OffComponent.cpp | 3 +- .../vrml/VRMLComponentExtension.cpp | 3 +- sdk/libraries/core/CMakeLists.txt | 2 +- sdk/libraries/core/CamiTKAPI.h | 3 + sdk/libraries/core/ExtensionManager.cpp | 156 +++++++++++++- sdk/libraries/core/action/Action.cpp | 36 +++- sdk/libraries/core/action/ActionExtension.cpp | 50 +++-- sdk/libraries/core/action/ActionExtension.h | 12 +- .../core/application/Application.cpp | 183 +++++++++++++++- sdk/libraries/core/application/Application.h | 80 ++++++- sdk/libraries/core/application/MainWindow.cpp | 100 +++++---- sdk/libraries/core/application/MainWindow.h | 7 +- sdk/libraries/core/component/Component.cpp | 39 ++++ .../core/component/image/ImageComponent.cpp | 5 +- .../component/image/SingleImageComponent.cpp | 11 +- .../core/component/mesh/MeshComponent.cpp | 14 +- .../core/component/mesh/MeshDataModel.cpp | 1 - .../core/component/mesh/MeshDataModel.h | 4 +- sdk/libraries/core/utils/CamiTKLogger.cpp | 7 + .../core/viewer/InteractiveViewer.cpp | 200 +++++++----------- sdk/libraries/core/viewer/InteractiveViewer.h | 75 ++----- sdk/libraries/core/viewer/RendererWidget.cpp | 2 +- sdk/libraries/core/viewer/RendererWidget.h | 7 +- sdk/libraries/core/viewer/Viewer.cpp | 113 ++++++++++ sdk/libraries/core/viewer/Viewer.h | 108 +++++++++- sdk/libraries/core/viewer/ViewerExtension.cpp | 187 ++++++++++++++++ sdk/libraries/core/viewer/ViewerExtension.h | 133 ++++++++++++ .../core/viewer/vtkInteractorStylePick.cpp | 4 +- .../core/viewer/vtkInteractorStylePick.h | 5 +- sdk/viewers/CMakeLists.txt | 18 ++ .../actionviewer}/ActionViewer.cpp | 144 +++++++------ .../actionviewer}/ActionViewer.h | 49 ++--- sdk/viewers/actionviewer/ActionViewerAPI.h | 74 +++++++ .../actionviewer/ActionViewerExtension.cpp | 36 ++++ .../actionviewer/ActionViewerExtension.h | 64 ++++++ sdk/viewers/actionviewer/CMakeLists.txt | 8 + .../viewers/bitmap}/BitmapViewer.cpp | 28 +-- .../viewers/bitmap}/BitmapViewer.h | 18 +- sdk/viewers/bitmap/BitmapViewerAPI.h | 67 ++++++ sdk/viewers/bitmap/BitmapViewerExtension.cpp | 36 ++++ sdk/viewers/bitmap/BitmapViewerExtension.h | 62 ++++++ sdk/viewers/bitmap/CMakeLists.txt | 8 + sdk/viewers/explorer/CMakeLists.txt | 8 + .../viewer => viewers/explorer}/Explorer.cpp | 34 +-- .../viewer => viewers/explorer}/Explorer.h | 47 ++-- sdk/viewers/explorer/ExplorerAPI.h | 59 ++++++ sdk/viewers/explorer/ExplorerExtension.cpp | 42 ++++ sdk/viewers/explorer/ExplorerExtension.h | 64 ++++++ .../explorer/ExplorerExtensionIcons.qrc | 5 + .../explorer/resources/folder-orange.png | Bin 0 -> 5026 bytes sdk/viewers/frameexplorer/CMakeLists.txt | 8 + .../frameexplorer}/FrameExplorer.cpp | 31 +-- .../frameexplorer}/FrameExplorer.h | 46 ++-- sdk/viewers/frameexplorer/FrameExplorerAPI.h | 59 ++++++ .../frameexplorer/FrameExplorerExtension.cpp | 36 ++++ .../frameexplorer/FrameExplorerExtension.h | 64 ++++++ .../interactivegeometryviewer/CMakeLists.txt | 8 + .../InteractiveGeometryViewer.cpp | 42 ++++ .../InteractiveGeometryViewer.h | 65 ++++++ .../InteractiveGeometryViewerAPI.h | 59 ++++++ .../InteractiveGeometryViewerExtension.cpp | 36 ++++ .../InteractiveGeometryViewerExtension.h | 64 ++++++ .../interactivesliceviewer/CMakeLists.txt | 8 + .../InteractiveSliceViewer.cpp | 78 +++++++ .../InteractiveSliceViewer.h | 71 +++++++ .../InteractiveSliceViewerAPI.h | 59 ++++++ .../InteractiveSliceViewerExtension.cpp | 39 ++++ .../InteractiveSliceViewerExtension.h | 64 ++++++ sdk/viewers/medicalimageviewer/CMakeLists.txt | 9 + .../MedicalImageViewer.cpp | 89 ++++---- .../medicalimageviewer}/MedicalImageViewer.h | 31 +-- .../MedicalImageViewerAPI.h | 59 ++++++ .../MedicalImageViewerExtension.cpp | 36 ++++ .../MedicalImageViewerExtension.h | 64 ++++++ sdk/viewers/propertyexplorer/CMakeLists.txt | 8 + .../propertyexplorer}/PropertyExplorer.cpp | 60 +++--- .../propertyexplorer}/PropertyExplorer.h | 36 ++-- .../propertyexplorer/PropertyExplorerAPI.h | 59 ++++++ .../PropertyExplorerExtension.cpp | 36 ++++ .../PropertyExplorerExtension.h | 64 ++++++ .../actions/basicpicking/ImagePicking.cpp | 12 +- .../actions/bitmapviewer/ShowBitmapViewer.cpp | 2 +- .../actions/meshpointdata/CMakeLists.txt | 2 +- .../actions/showtextviewer/ShowTextViewer.cpp | 68 ++++++ .../sleepingwhileworking/CMakeLists.txt | 1 + .../WorkingWhenSleepingLinear.cpp | 4 +- .../WorkingWhenSleepingRandom.cpp | 4 +- tutorials/actions/vtkwidget/BoxWidget.cpp | 4 +- tutorials/actions/vtkwidget/CMakeLists.txt | 1 + tutorials/actions/vtkwidget/ContourWidget.cpp | 7 +- tutorials/applications/basic/main.cpp | 11 +- tutorials/applications/fancy/CMakeLists.txt | 4 +- .../applications/fancy/FancyMainWindow.cpp | 125 ++++++----- .../applications/fancy/FancyMainWindow.h | 14 +- .../applications/menubar/MyAppMainWindow.cpp | 9 +- .../applications/simple/SimpleMainWindow.cpp | 24 +-- tutorials/applications/simple/main.cpp | 2 +- .../applications/textviewer/CMakeLists.txt | 3 + tutorials/viewers/MyViewer.cpp | 11 +- tutorials/viewers/MyViewer.h | 7 +- tutorials/viewers/main.cpp | 2 +- .../textviewer/TextViewerExtension.cpp | 36 ++++ 145 files changed, 3702 insertions(+), 1025 deletions(-) create mode 100644 sdk/applications/actionstatemachine/ActionStateViewerExtension.cpp create mode 100644 sdk/applications/actionstatemachine/ActionStateViewerExtension.h create mode 100644 sdk/libraries/core/viewer/ViewerExtension.cpp create mode 100644 sdk/libraries/core/viewer/ViewerExtension.h create mode 100644 sdk/viewers/CMakeLists.txt rename sdk/{libraries/core/viewer => viewers/actionviewer}/ActionViewer.cpp (75%) rename sdk/{libraries/core/viewer => viewers/actionviewer}/ActionViewer.h (82%) create mode 100644 sdk/viewers/actionviewer/ActionViewerAPI.h create mode 100644 sdk/viewers/actionviewer/ActionViewerExtension.cpp create mode 100644 sdk/viewers/actionviewer/ActionViewerExtension.h create mode 100644 sdk/viewers/actionviewer/CMakeLists.txt rename {tutorials/actions/bitmapviewer => sdk/viewers/bitmap}/BitmapViewer.cpp (83%) rename {tutorials/actions/bitmapviewer => sdk/viewers/bitmap}/BitmapViewer.h (85%) create mode 100644 sdk/viewers/bitmap/BitmapViewerAPI.h create mode 100644 sdk/viewers/bitmap/BitmapViewerExtension.cpp create mode 100644 sdk/viewers/bitmap/BitmapViewerExtension.h create mode 100644 sdk/viewers/bitmap/CMakeLists.txt create mode 100644 sdk/viewers/explorer/CMakeLists.txt rename sdk/{libraries/core/viewer => viewers/explorer}/Explorer.cpp (95%) rename sdk/{libraries/core/viewer => viewers/explorer}/Explorer.h (83%) create mode 100644 sdk/viewers/explorer/ExplorerAPI.h create mode 100644 sdk/viewers/explorer/ExplorerExtension.cpp create mode 100644 sdk/viewers/explorer/ExplorerExtension.h create mode 100644 sdk/viewers/explorer/ExplorerExtensionIcons.qrc create mode 100644 sdk/viewers/explorer/resources/folder-orange.png create mode 100644 sdk/viewers/frameexplorer/CMakeLists.txt rename sdk/{libraries/core/viewer => viewers/frameexplorer}/FrameExplorer.cpp (90%) rename sdk/{libraries/core/viewer => viewers/frameexplorer}/FrameExplorer.h (66%) create mode 100644 sdk/viewers/frameexplorer/FrameExplorerAPI.h create mode 100644 sdk/viewers/frameexplorer/FrameExplorerExtension.cpp create mode 100644 sdk/viewers/frameexplorer/FrameExplorerExtension.h create mode 100644 sdk/viewers/interactivegeometryviewer/CMakeLists.txt create mode 100644 sdk/viewers/interactivegeometryviewer/InteractiveGeometryViewer.cpp create mode 100644 sdk/viewers/interactivegeometryviewer/InteractiveGeometryViewer.h create mode 100644 sdk/viewers/interactivegeometryviewer/InteractiveGeometryViewerAPI.h create mode 100644 sdk/viewers/interactivegeometryviewer/InteractiveGeometryViewerExtension.cpp create mode 100644 sdk/viewers/interactivegeometryviewer/InteractiveGeometryViewerExtension.h create mode 100644 sdk/viewers/interactivesliceviewer/CMakeLists.txt create mode 100644 sdk/viewers/interactivesliceviewer/InteractiveSliceViewer.cpp create mode 100644 sdk/viewers/interactivesliceviewer/InteractiveSliceViewer.h create mode 100644 sdk/viewers/interactivesliceviewer/InteractiveSliceViewerAPI.h create mode 100644 sdk/viewers/interactivesliceviewer/InteractiveSliceViewerExtension.cpp create mode 100644 sdk/viewers/interactivesliceviewer/InteractiveSliceViewerExtension.h create mode 100644 sdk/viewers/medicalimageviewer/CMakeLists.txt rename sdk/{libraries/core/viewer => viewers/medicalimageviewer}/MedicalImageViewer.cpp (75%) rename sdk/{libraries/core/viewer => viewers/medicalimageviewer}/MedicalImageViewer.h (87%) create mode 100644 sdk/viewers/medicalimageviewer/MedicalImageViewerAPI.h create mode 100644 sdk/viewers/medicalimageviewer/MedicalImageViewerExtension.cpp create mode 100644 sdk/viewers/medicalimageviewer/MedicalImageViewerExtension.h create mode 100644 sdk/viewers/propertyexplorer/CMakeLists.txt rename sdk/{libraries/core/viewer => viewers/propertyexplorer}/PropertyExplorer.cpp (89%) rename sdk/{libraries/core/viewer => viewers/propertyexplorer}/PropertyExplorer.h (89%) create mode 100644 sdk/viewers/propertyexplorer/PropertyExplorerAPI.h create mode 100644 sdk/viewers/propertyexplorer/PropertyExplorerExtension.cpp create mode 100644 sdk/viewers/propertyexplorer/PropertyExplorerExtension.h create mode 100644 tutorials/actions/showtextviewer/ShowTextViewer.cpp create mode 100644 tutorials/applications/textviewer/CMakeLists.txt create mode 100644 tutorials/viewers/textviewer/TextViewerExtension.cpp diff --git a/modeling/components/pmlcomponent/PMLComponent.cpp b/modeling/components/pmlcomponent/PMLComponent.cpp index a0b9536b..eb611743 100644 --- a/modeling/components/pmlcomponent/PMLComponent.cpp +++ b/modeling/components/pmlcomponent/PMLComponent.cpp @@ -224,7 +224,7 @@ void PMLComponent::create3DStructure() { initRepresentation(mainGrid); // Tell this component is visible in the 3D viewer, otherwise we won't see it! - setVisibility(InteractiveViewer::get3DViewer(), true); + setVisibility(Application::getViewer("3DViewer"), true); } //-------------------- parseMultiComponent ------------------- @@ -343,7 +343,7 @@ void PMLComponent::refreshDisplay() { // for instance in a MML monitor) in order to obtain a real refresh getPointSet()->Modified(); // This is a forced/active refresh (breaking CamiTK programming guidelines) - InteractiveViewer::get3DViewer()->refresh(); + Application::getViewer("3DViewer")->refresh(); // shade the current selected component in order to see the selected item (SC, MC, Atoms or Cells) myGeometry->setEnhancedModes(InterfaceGeometry::Shaded); } diff --git a/sdk/CMakeLists.txt b/sdk/CMakeLists.txt index db305b7e..4e4bd7f7 100644 --- a/sdk/CMakeLists.txt +++ b/sdk/CMakeLists.txt @@ -109,8 +109,8 @@ camitk_parse_test_init() camitk_add_subdirectory(libraries) camitk_add_subdirectory(testapplications) camitk_add_subdirectory(components) -camitk_add_subdirectory(actions) camitk_add_subdirectory(viewers) +camitk_add_subdirectory(actions) camitk_add_subdirectory(applications) camitk_add_subdirectory(cmake) # for cmake module installation diff --git a/sdk/actions/application/CMakeLists.txt b/sdk/actions/application/CMakeLists.txt index 288e7689..894ed42e 100644 --- a/sdk/actions/application/CMakeLists.txt +++ b/sdk/actions/application/CMakeLists.txt @@ -1,6 +1,7 @@ camitk_extension(ACTION_EXTENSION DEFINES COMPILE_APPLICATION_ACTION_API CEP_NAME SDK + NEEDS_VIEWER_EXTENSION medicalimageviewer DESCRIPTION "Features actions used at aplication level (these actions are mandatory for any CamiTK appliction to work)" ) diff --git a/sdk/actions/application/Show3DViewer.cpp b/sdk/actions/application/Show3DViewer.cpp index d091c88b..074e67d5 100644 --- a/sdk/actions/application/Show3DViewer.cpp +++ b/sdk/actions/application/Show3DViewer.cpp @@ -25,6 +25,7 @@ #include "Show3DViewer.h" #include + using namespace camitk; // --------------- constructor ------------------- @@ -60,7 +61,7 @@ QWidget* Show3DViewer::getWidget() { // --------------- apply ------------------- Action::ApplyStatus Show3DViewer::apply() { - MedicalImageViewer::getInstance()->setVisibleViewer(MedicalImageViewer::VIEWER_3D); + dynamic_cast(Application::getViewer("MedicalImageViewer"))->setVisibleViewer(MedicalImageViewer::VIEWER_3D); Application::refresh(); return SUCCESS; } diff --git a/sdk/actions/application/ShowAllViewers.cpp b/sdk/actions/application/ShowAllViewers.cpp index 7b687a2e..840a2dce 100644 --- a/sdk/actions/application/ShowAllViewers.cpp +++ b/sdk/actions/application/ShowAllViewers.cpp @@ -60,7 +60,7 @@ QWidget* ShowAllViewers::getWidget() { // --------------- apply ------------------- Action::ApplyStatus ShowAllViewers::apply() { - MedicalImageViewer::getInstance()->setVisibleViewer(MedicalImageViewer::VIEWER_ALL); + dynamic_cast(Application::getViewer("MedicalImageViewer"))->setVisibleViewer(MedicalImageViewer::VIEWER_ALL); Application::refresh(); return SUCCESS; } diff --git a/sdk/actions/application/ShowArbitraryViewer.cpp b/sdk/actions/application/ShowArbitraryViewer.cpp index 39094316..9830da24 100644 --- a/sdk/actions/application/ShowArbitraryViewer.cpp +++ b/sdk/actions/application/ShowArbitraryViewer.cpp @@ -60,7 +60,7 @@ QWidget* ShowArbitraryViewer::getWidget() { // --------------- apply ------------------- Action::ApplyStatus ShowArbitraryViewer::apply() { - MedicalImageViewer::getInstance()->setVisibleViewer(MedicalImageViewer::VIEWER_ARBITRARY); + dynamic_cast(Application::getViewer("MedicalImageViewer"))->setVisibleViewer(MedicalImageViewer::VIEWER_ARBITRARY); Application::refresh(); return SUCCESS; } diff --git a/sdk/actions/application/ShowAxialViewer.cpp b/sdk/actions/application/ShowAxialViewer.cpp index c9ddb37c..b69b774f 100644 --- a/sdk/actions/application/ShowAxialViewer.cpp +++ b/sdk/actions/application/ShowAxialViewer.cpp @@ -60,7 +60,7 @@ QWidget* ShowAxialViewer::getWidget() { // --------------- apply ------------------- Action::ApplyStatus ShowAxialViewer::apply() { - MedicalImageViewer::getInstance()->setVisibleViewer(MedicalImageViewer::VIEWER_AXIAL); + dynamic_cast(Application::getViewer("MedicalImageViewer"))->setVisibleViewer(MedicalImageViewer::VIEWER_AXIAL); Application::refresh(); return SUCCESS; } diff --git a/sdk/actions/application/ShowCoronalViewer.cpp b/sdk/actions/application/ShowCoronalViewer.cpp index 19beb6fc..8c713db3 100644 --- a/sdk/actions/application/ShowCoronalViewer.cpp +++ b/sdk/actions/application/ShowCoronalViewer.cpp @@ -60,7 +60,7 @@ QWidget* ShowCoronalViewer::getWidget() { // --------------- apply ------------------- Action::ApplyStatus ShowCoronalViewer::apply() { - MedicalImageViewer::getInstance()->setVisibleViewer(MedicalImageViewer::VIEWER_CORONAL); + dynamic_cast(Application::getViewer("MedicalImageViewer"))->setVisibleViewer(MedicalImageViewer::VIEWER_CORONAL); Application::refresh(); return SUCCESS; } diff --git a/sdk/actions/application/ShowSagittalViewer.cpp b/sdk/actions/application/ShowSagittalViewer.cpp index 6ec9e733..80005ec0 100644 --- a/sdk/actions/application/ShowSagittalViewer.cpp +++ b/sdk/actions/application/ShowSagittalViewer.cpp @@ -60,7 +60,7 @@ QWidget* ShowSagittalViewer::getWidget() { // --------------- apply ------------------- Action::ApplyStatus ShowSagittalViewer::apply() { - MedicalImageViewer::getInstance()->setVisibleViewer(MedicalImageViewer::VIEWER_SAGITTAL); + dynamic_cast(Application::getViewer("MedicalImageViewer"))->setVisibleViewer(MedicalImageViewer::VIEWER_SAGITTAL); Application::refresh(); return SUCCESS; } diff --git a/sdk/actions/frame/editframes/FrameEditor.cpp b/sdk/actions/frame/editframes/FrameEditor.cpp index c6b9de37..961d3f28 100644 --- a/sdk/actions/frame/editframes/FrameEditor.cpp +++ b/sdk/actions/frame/editframes/FrameEditor.cpp @@ -27,7 +27,6 @@ #include "FrameEditor.h" // CamiTK -#include #include using namespace camitk; @@ -160,7 +159,7 @@ QWidget* FrameEditor::getWidget() { void FrameEditor::initializeDialogWithCurrentComponent() { // update checkbox ui.displayFrameCheckBox->blockSignals(true); - bool isFrameDisplayed = currentComponent->getFrameVisibility(InteractiveViewer::get3DViewer()); + bool isFrameDisplayed = currentComponent->getFrameVisibility(Application::getViewer("3DViewer")); ui.displayFrameCheckBox->setChecked(isFrameDisplayed); ui.displayFrameCheckBox->blockSignals(false); @@ -218,19 +217,18 @@ void FrameEditor::initializeDialogWithCurrentComponent() { void FrameEditor::displayFrameToggled(bool display) { int frameSize = ui.frameSizeSpinBox->value(); currentComponent->getFrameAxisActor()->SetTotalLength(frameSize, frameSize, frameSize); - currentComponent->setFrameVisibility(InteractiveViewer::get3DViewer(), display); - - InteractiveViewer::get3DViewer()->refresh(); + currentComponent->setFrameVisibility(Application::getViewer("3DViewer"), display); + Application::getViewer("3DViewer")->refresh(); } // --------------- frameSizeChanged ------------------- void FrameEditor::frameSizeChanged(int val) { bool display = ui.displayFrameCheckBox->isChecked(); currentComponent->getFrameAxisActor()->SetTotalLength(val, val, val); - currentComponent->setFrameVisibility(InteractiveViewer::get3DViewer(), display); + currentComponent->setFrameVisibility(Application::getViewer("3DViewer"), display); - InteractiveViewer::get3DViewer()->refresh(); + Application::getViewer("3DViewer")->refresh(); } // --------------- setParentFrame ------------------- @@ -251,7 +249,7 @@ void FrameEditor::setParentFrame() { } currentComponent->setParentFrame(parentFrame, keepTransform); - InteractiveViewer::get3DViewer()->refresh(); + Application::getViewer("3DViewer")->refresh(); initializeDialogWithCurrentComponent(); } @@ -300,7 +298,7 @@ void FrameEditor::setTransformation() { matrixTransform->SetMatrix(matrix); currentComponent->setTransform(matrixTransform); - InteractiveViewer::get3DViewer()->refresh(); + Application::getViewer("3DViewer")->refresh(); initializeDialogWithCurrentComponent(); } @@ -315,7 +313,7 @@ void FrameEditor::translate() { ui.yTranslationLineEdit->text().toDouble(), ui.zTranslationLineEdit->text().toDouble()); - InteractiveViewer::get3DViewer()->refresh(); + Application::getViewer("3DViewer")->refresh(); initializeDialogWithCurrentComponent(); } @@ -325,7 +323,7 @@ void FrameEditor::setTranslation() { ui.yTranslationLineEdit->text().toDouble(), ui.zTranslationLineEdit->text().toDouble()); - InteractiveViewer::get3DViewer()->refresh(); + Application::getViewer("3DViewer")->refresh(); initializeDialogWithCurrentComponent(); } @@ -348,7 +346,7 @@ void FrameEditor::rotate() { ui.zRotationLineEdit->text().toDouble()); } - InteractiveViewer::get3DViewer()->refresh(); + Application::getViewer("3DViewer")->refresh(); initializeDialogWithCurrentComponent(); } @@ -365,7 +363,7 @@ void FrameEditor::setRotation() { ui.zRotationLineEdit->text().toDouble()); } - InteractiveViewer::get3DViewer()->refresh(); + Application::getViewer("3DViewer")->refresh(); initializeDialogWithCurrentComponent(); } diff --git a/sdk/actions/frame/editframes/FrameEditor.h b/sdk/actions/frame/editframes/FrameEditor.h index f260b7e8..a0c29d85 100644 --- a/sdk/actions/frame/editframes/FrameEditor.h +++ b/sdk/actions/frame/editframes/FrameEditor.h @@ -28,6 +28,7 @@ #include "Action.h" #include "Component.h" +#include "Viewer.h" #include #include diff --git a/sdk/actions/image/pixelcolorchanger/PixelColorChanger.cpp b/sdk/actions/image/pixelcolorchanger/PixelColorChanger.cpp index eb88db78..042091ed 100644 --- a/sdk/actions/image/pixelcolorchanger/PixelColorChanger.cpp +++ b/sdk/actions/image/pixelcolorchanger/PixelColorChanger.cpp @@ -79,9 +79,9 @@ QWidget* PixelColorChanger::getWidget() { if (!isConnected) { //-- run the action every time a picking is done in the axial/sagittal or coronal planes - QObject::connect(InteractiveViewer::getAxialViewer(), SIGNAL(selectionChanged()), this, SLOT(apply())); - QObject::connect(InteractiveViewer::getCoronalViewer(), SIGNAL(selectionChanged()), this, SLOT(apply())); - QObject::connect(InteractiveViewer::getSagittalViewer(), SIGNAL(selectionChanged()), this, SLOT(apply())); + QObject::connect(Application::getViewer("axialViewer"), SIGNAL(selectionChanged()), this, SLOT(apply())); + QObject::connect(Application::getViewer("coronalViewer"), SIGNAL(selectionChanged()), this, SLOT(apply())); + QObject::connect(Application::getViewer("sagittalViewer"), SIGNAL(selectionChanged()), this, SLOT(apply())); isConnected = true; } return Action::getWidget(); @@ -219,9 +219,9 @@ Action::ApplyStatus PixelColorChanger::apply() { } else { // disconnect - QObject::disconnect(InteractiveViewer::getAxialViewer(), SIGNAL(selectionChanged()), this, SLOT(apply())); - QObject::disconnect(InteractiveViewer::getCoronalViewer(), SIGNAL(selectionChanged()), this, SLOT(apply())); - QObject::disconnect(InteractiveViewer::getSagittalViewer(), SIGNAL(selectionChanged()), this, SLOT(apply())); + QObject::disconnect(Application::getViewer("axialViewer"), SIGNAL(selectionChanged()), this, SLOT(apply())); + QObject::disconnect(Application::getViewer("coronalViewer"), SIGNAL(selectionChanged()), this, SLOT(apply())); + QObject::disconnect(Application::getViewer("sagittalViewer"), SIGNAL(selectionChanged()), this, SLOT(apply())); isConnected = false; } return SUCCESS; diff --git a/sdk/actions/image/reconstruction/ImageReconstructionAction.cpp b/sdk/actions/image/reconstruction/ImageReconstructionAction.cpp index f1a4a9ed..8f92a7ee 100644 --- a/sdk/actions/image/reconstruction/ImageReconstructionAction.cpp +++ b/sdk/actions/image/reconstruction/ImageReconstructionAction.cpp @@ -23,18 +23,13 @@ * $CAMITK_LICENCE_END$ ****************************************************************************/ -// -- Core image component stuff classes #include "ImageReconstructionAction.h" -#include "ImageComponent.h" -#include "MeshComponent.h" // -- Core stuff classes #include #include #include - -// -- stl stuff -#include +#include // -- vtk filters stuff #include diff --git a/sdk/actions/image/reorientimage/CMakeLists.txt b/sdk/actions/image/reorientimage/CMakeLists.txt index 5bddcd30..00a9b67e 100644 --- a/sdk/actions/image/reorientimage/CMakeLists.txt +++ b/sdk/actions/image/reorientimage/CMakeLists.txt @@ -1,6 +1,7 @@ # Call CamiTK CMake Macro to define the action camitk_extension(ACTION_EXTENSION NEEDS_COMPONENT_EXTENSION vtkmesh + NEEDS_VIEWER_EXTENSION interactivegeometryviewer CEP_NAME SDK DESCRIPTION "Allows one to reorient a volumic image." ENABLE_AUTO_TEST diff --git a/sdk/actions/image/reorientimage/ReorientImage.cpp b/sdk/actions/image/reorientimage/ReorientImage.cpp index e795439d..a2fb0b30 100644 --- a/sdk/actions/image/reorientimage/ReorientImage.cpp +++ b/sdk/actions/image/reorientimage/ReorientImage.cpp @@ -28,7 +28,7 @@ // CamiTK #include -#include +#include #include #include #include @@ -125,20 +125,18 @@ ReorientImage::~ReorientImage() { femaleModel = NULL; delete maleModel; maleModel = NULL; - delete dialog; - dialog = NULL; } // --------------- initDialog ------------------- void ReorientImage::initDialog() { - dialog = new QDialog(); + dialog = new QFrame(); //-- init user interface ui.setupUi(dialog); //-- add the internal viewer initInternalViewer(); - ui.illustrationLayout->addWidget(internalViewer->getWidget(dialog)); + internalViewer->embedIn(ui.illustrationLayout); ui.xDirection->setTextFormat(Qt::RichText); ui.yDirection->setTextFormat(Qt::RichText); @@ -192,7 +190,8 @@ void ReorientImage::initInternalViewer() { buildGeometries(); // Set up the 3D viewer to visualize actual origin/orientation locations - internalViewer = InteractiveViewer::getNewViewer("Image Orientation Viewer", InteractiveViewer::GEOMETRY_VIEWER); + internalViewer = dynamic_cast(Application::getNewViewer("Image Orientation Viewer", "InteractiveGeometryViewer")); + internalViewer->setLayout(Viewer::EMBEDDED); internalViewer->setHighlightMode(InteractiveViewer::OFF); internalViewer->toggleCopyright(false); internalViewer->getRendererWidget()->setCameraOrientation(RendererWidget::RIGHT_DOWN); @@ -333,7 +332,7 @@ Action::ApplyStatus ReorientImage::process(ImageComponent* image) { updatedTransform->SetMatrix(updatedMatrix); image->setTransform(updatedTransform); - image->setFrameVisibility(InteractiveViewer::get3DViewer(), true); + image->setFrameVisibility(Application::getViewer("3DViewer"), true); } else { @@ -357,9 +356,9 @@ Action::ApplyStatus ReorientImage::process(ImageComponent* image) { updatedTransform->SetMatrix(updatedMatrix); result->setTransform(updatedTransform); - result->setFrameVisibility(InteractiveViewer::get3DViewer(), true); + result->setFrameVisibility(Application::getViewer("3DViewer"), true); } - InteractiveViewer::get3DViewer()->refresh(); + Application::getViewer("3DViewer")->refresh(); Application::refresh(); diff --git a/sdk/actions/image/reorientimage/ReorientImage.h b/sdk/actions/image/reorientimage/ReorientImage.h index 9ce4b3c2..dcd9de1e 100644 --- a/sdk/actions/image/reorientimage/ReorientImage.h +++ b/sdk/actions/image/reorientimage/ReorientImage.h @@ -31,12 +31,13 @@ // Include ui_ReorientImage.h to be able to declare an instance of Ui::ReorientImage #include "ui_ReorientImage.h" +#include + class vtkTransform; class vtkAnnotatedCubeActor; namespace camitk { class Geometry; class ImageComponent; -class InteractiveViewer; } class ReorientImage : public camitk::Action { @@ -77,7 +78,7 @@ private: void setAxesOrientation(const QString orientation); - camitk::InteractiveViewer* internalViewer; + InteractiveGeometryViewer* internalViewer; /// Actually perform the image transformation ApplyStatus process(camitk::ImageComponent* image); @@ -86,7 +87,7 @@ private: Ui::ReorientImage ui; /// the dialog - QDialog* dialog; + QFrame* dialog; /// axes actor vtkSmartPointer axes; @@ -108,8 +109,6 @@ private: QMap lettersMeaning; -// camitk::ImageComponent * img; - }; #endif // REORIENTIMAGE_H diff --git a/sdk/actions/image/reorientimage/ReorientImage.ui b/sdk/actions/image/reorientimage/ReorientImage.ui index 4371a993..b5c087d7 100644 --- a/sdk/actions/image/reorientimage/ReorientImage.ui +++ b/sdk/actions/image/reorientimage/ReorientImage.ui @@ -1,7 +1,7 @@ ReorientImage - + true @@ -9,7 +9,7 @@ 0 0 - 530 + 584 458 @@ -25,7 +25,7 @@ TransformDialog - + true @@ -86,7 +86,7 @@ - How was your image acquired ? + How was your image acquired? @@ -177,7 +177,7 @@ - Male + Ma&le @@ -196,7 +196,7 @@ - Reset Image Origin + Rese&t Image Origin diff --git a/sdk/actions/image/volumerendering/VolumeRenderingAction.cpp b/sdk/actions/image/volumerendering/VolumeRenderingAction.cpp index fc4ca1ef..277c0c5f 100644 --- a/sdk/actions/image/volumerendering/VolumeRenderingAction.cpp +++ b/sdk/actions/image/volumerendering/VolumeRenderingAction.cpp @@ -52,7 +52,6 @@ // -- Application -- #include #include -#include #include #include @@ -98,18 +97,18 @@ Action::ApplyStatus VolumeRenderingAction::apply() { // --------------- process --------------- void VolumeRenderingAction::process(ImageComponent* comp) { - bool isVisible = comp->getVolumeRenderingChild()->getVisibility(InteractiveViewer::get3DViewer()); + bool isVisible = comp->getVolumeRenderingChild()->getVisibility(Application::getViewer("3DViewer")); bool existVR = (comp->getVolumeRenderingChild()->getProp(volumeName) != NULL); if (existVR) { if (isVisible) { - comp->getVolumeRenderingChild()->setVisibility(InteractiveViewer::get3DViewer(), false); + comp->getVolumeRenderingChild()->setVisibility(Application::getViewer("3DViewer"), false); if (myWidget) { myWidget->close(); } Application::refresh(); } else { - comp->getVolumeRenderingChild()->setVisibility(InteractiveViewer::get3DViewer(), true); + comp->getVolumeRenderingChild()->setVisibility(Application::getViewer("3DViewer"), true); if (myWidget != nullptr) { myWidget->show(); Application::refresh(); @@ -253,16 +252,16 @@ void VolumeRenderingAction::createVolumeRendering(ImageComponent* comp) { if (oldVolume) { comp->getVolumeRenderingChild()->removeProp(volumeName); - //InteractiveViewer::get3DViewer()->getRendererWidget()->removeProp(oldVolume); + //Application::getViewer("3DViewer")->getRendererWidget()->removeProp(oldVolume); } // Add the new computed volume to the component and display it in the 3D viewer comp->getVolumeRenderingChild()->addProp(volumeName, volume); comp->getVolumeRenderingChild()->getProp(volumeName)->SetVisibility(true); - //InteractiveViewer::get3DViewer()->getRendererWidget()->addProp(volume); - comp->getVolumeRenderingChild()->setVisibility(InteractiveViewer::get3DViewer(), true); - InteractiveViewer::get3DViewer()->refresh(); + //Application::getViewer("3DViewer")->getRendererWidget()->addProp(volume); + comp->getVolumeRenderingChild()->setVisibility(Application::getViewer("3DViewer"), true); + Application::getViewer("3DViewer")->refresh(); } diff --git a/sdk/actions/image/volumerendering/VolumeRenderingAction.h b/sdk/actions/image/volumerendering/VolumeRenderingAction.h index 8cc958f5..80c5091d 100644 --- a/sdk/actions/image/volumerendering/VolumeRenderingAction.h +++ b/sdk/actions/image/volumerendering/VolumeRenderingAction.h @@ -27,6 +27,7 @@ #include #include +#include #include diff --git a/sdk/actions/mesh/basicmesh/CenterMesh.h b/sdk/actions/mesh/basicmesh/CenterMesh.h index e70b8bee..c648c677 100644 --- a/sdk/actions/mesh/basicmesh/CenterMesh.h +++ b/sdk/actions/mesh/basicmesh/CenterMesh.h @@ -26,7 +26,7 @@ #ifndef CENTERMESH_H #define CENTERMESH_H -#include "Action.h" +#include /** * @ingroup group_sdk_actions_mesh_basicmesh diff --git a/sdk/actions/mesh/basicmesh/ChangeColor.cpp b/sdk/actions/mesh/basicmesh/ChangeColor.cpp index 2f72b489..0d51ff5b 100644 --- a/sdk/actions/mesh/basicmesh/ChangeColor.cpp +++ b/sdk/actions/mesh/basicmesh/ChangeColor.cpp @@ -52,7 +52,7 @@ Action::ApplyStatus ChangeColor::apply() { QColor currentColor; currentColor.setRgbF(actorColor[0], actorColor[1], actorColor[2], actorColor[3]); - QColor newColor = QColorDialog::getColor(currentColor, NULL, QString("Change color of ") + getTargets().size() + QString(" components"), QColorDialog::ShowAlphaChannel); + QColor newColor = QColorDialog::getColor(currentColor, nullptr, QString("Change color of ") + getTargets().size() + QString(" components"), QColorDialog::ShowAlphaChannel); if (newColor.isValid()) { actorColor[0] = newColor.redF(); diff --git a/sdk/actions/mesh/basicmesh/MeshPicking.cpp b/sdk/actions/mesh/basicmesh/MeshPicking.cpp index 9d7c26b0..9cab56d4 100644 --- a/sdk/actions/mesh/basicmesh/MeshPicking.cpp +++ b/sdk/actions/mesh/basicmesh/MeshPicking.cpp @@ -61,7 +61,7 @@ QWidget* MeshPicking::getWidget() { informationLabel = new QLabel(); //-- run the action every time a picking is done in the axial/sagittal or coronal planes - QObject::connect(InteractiveViewer::get3DViewer(), SIGNAL(selectionChanged()), this, SLOT(apply())); + QObject::connect(Application::getViewer("3DViewer"), SIGNAL(selectionChanged()), this, SLOT(apply())); //-- the vertical layout, put every GUI elements in it auto* informationFrameLayout = new QVBoxLayout(); diff --git a/sdk/actions/mesh/basicmesh/RigidTransform.cpp b/sdk/actions/mesh/basicmesh/RigidTransform.cpp index 972c9046..561088f1 100644 --- a/sdk/actions/mesh/basicmesh/RigidTransform.cpp +++ b/sdk/actions/mesh/basicmesh/RigidTransform.cpp @@ -51,7 +51,7 @@ RigidTransform::RigidTransform(ActionExtension* extension) : Action(extension) { addTag("Rotate"); addTag("Scale"); - dialog = NULL; + dialog = nullptr; } @@ -131,7 +131,7 @@ void RigidTransform::reset() { //-- init values double bounds[6]; - InteractiveViewer::get3DViewer()->getBounds(bounds); + dynamic_cast(Application::getViewer("3DViewer"))->getBounds(bounds); double xLength = bounds[1] - bounds[0]; double yLength = bounds[3] - bounds[2]; double zLength = bounds[5] - bounds[4]; @@ -184,7 +184,7 @@ void RigidTransform::update(bool forceUpdate) { transformation->Scale(sx, sy, sz); // Refresh all the used viewers - InteractiveViewer::get3DViewer()->refresh(); + Application::getViewer("3DViewer")->refresh(); } } @@ -217,7 +217,7 @@ Action::ApplyStatus RigidTransform::apply() { void RigidTransform::close() { //--disconnect the selected Component foreach (Component* comp, getTargets()) { - comp->setDataConnection(NULL); + comp->setDataConnection(nullptr); } // hide the dialog dialog->hide(); diff --git a/sdk/actions/mesh/basicmesh/RigidTransform.h b/sdk/actions/mesh/basicmesh/RigidTransform.h index e83cd1a6..21df0ba5 100644 --- a/sdk/actions/mesh/basicmesh/RigidTransform.h +++ b/sdk/actions/mesh/basicmesh/RigidTransform.h @@ -26,8 +26,8 @@ #ifndef RIGID_TRANSFORM_H #define RIGID_TRANSFORM_H -#include "Action.h" -#include "Component.h" +#include +#include #include #include diff --git a/sdk/actions/mesh/meshprocessing/MeshClipping.cpp b/sdk/actions/mesh/meshprocessing/MeshClipping.cpp index 773a4ce4..ee8baf5a 100644 --- a/sdk/actions/mesh/meshprocessing/MeshClipping.cpp +++ b/sdk/actions/mesh/meshprocessing/MeshClipping.cpp @@ -85,8 +85,8 @@ QWidget* MeshClipping::getWidget() { //-- Creating the clipping plane widget (the first time getWidget() is called) if (!widget->planeWidget) { vtkRenderWindowInteractor* iren = - InteractiveViewer::get3DViewer()-> - getRendererWidget()->GetRenderWindow()->GetInteractor(); + dynamic_cast(Application::getViewer("3DViewer")) + ->getRendererWidget()->GetRenderWindow()->GetInteractor(); //-- Configure the plane widget including callbacks widget->planeWidget = @@ -96,7 +96,7 @@ QWidget* MeshClipping::getWidget() { //-- Bounding box definition and placement widget->planeWidget->SetPlaceFactor(1.5); - InteractiveViewer::get3DViewer()->getBounds(limBounds); + dynamic_cast(Application::getViewer("3DViewer"))->getBounds(limBounds); widget->planeWidget->PlaceWidget(limBounds); QVector3D origin((limBounds[1] + limBounds[0]) / 2, (limBounds[3] + limBounds[2]) / 2, diff --git a/sdk/actions/mesh/meshprocessing/MeshProcessingExtension.cpp b/sdk/actions/mesh/meshprocessing/MeshProcessingExtension.cpp index 09d3357f..8156aee6 100644 --- a/sdk/actions/mesh/meshprocessing/MeshProcessingExtension.cpp +++ b/sdk/actions/mesh/meshprocessing/MeshProcessingExtension.cpp @@ -22,6 +22,7 @@ * * $CAMITK_LICENCE_END$ ****************************************************************************/ + #include "MeshProcessingExtension.h" #include "Decimation.h" #include "CleanPolyData.h" @@ -41,8 +42,6 @@ #include "SaveDisplacementFromTransformation.h" #include "AppendMeshes.h" -#include "Application.h" - // -------------------- init -------------------- void MeshProcessingExtension::init() { registerNewAction(Decimation); diff --git a/sdk/applications/actionstatemachine/ActionState.cpp b/sdk/applications/actionstatemachine/ActionState.cpp index 6d4dedf1..c041c3e5 100644 --- a/sdk/applications/actionstatemachine/ActionState.cpp +++ b/sdk/applications/actionstatemachine/ActionState.cpp @@ -22,8 +22,8 @@ * * $CAMITK_LICENCE_END$ ****************************************************************************/ + #include "ActionState.h" -//FIXME #include "ActionStateViewer.h" // -- CamiTK Core stuff #include diff --git a/sdk/applications/actionstatemachine/ActionStateMachine.cpp b/sdk/applications/actionstatemachine/ActionStateMachine.cpp index 0009fdcb..a35029e6 100644 --- a/sdk/applications/actionstatemachine/ActionStateMachine.cpp +++ b/sdk/applications/actionstatemachine/ActionStateMachine.cpp @@ -44,6 +44,7 @@ using namespace camitk; // -- CamiTK Application Local stuff #include "ActionStateMachine.h" #include "ActionStateViewer.h" +#include "ActionStateViewerExtension.h" #include "ActionTransition.h" // ---------------------- constructor ---------------------------- @@ -53,6 +54,12 @@ ActionStateMachine::ActionStateMachine(int& argc, char** argv, QString inputFile setProperty("Log to File", true); setProperty("Logger Level", InterfaceLogger::TRACE); + // load the specific viewer extension + ActionStateViewerExtension* ext = new ActionStateViewerExtension(); + ext->initResources(); + ext->init(); + registerAllViewers(ext); + statesMap = new QMap(); // Atributes initialization @@ -154,12 +161,12 @@ void ActionStateMachine::autoNext() { void ActionStateMachine::initMainWindow() { mainWindow = new MainWindow(name); - mainWindow->setCentralViewer(MedicalImageViewer::getInstance()); - mainWindow->addDockViewer(Qt::RightDockWidgetArea, ActionStateViewer::getActionStateViewer()); - mainWindow->addDockViewer(Qt::LeftDockWidgetArea, Explorer::getInstance()); + mainWindow->setCentralViewer(Application::getViewer("MedicalImageViewer")); + mainWindow->addDockViewer(Qt::RightDockWidgetArea, Application::getViewer("ActionStateViewer")); + mainWindow->addDockViewer(Qt::LeftDockWidgetArea, Application::getViewer("Explorer")); // never show the toolbar - MedicalImageViewer::getInstance()->setToolbarAutoVisibility(false); + dynamic_cast(Application::getViewer("MedicalImageViewer"))->setToolbarAutoVisibility(false); mainWindow->showStatusBar(true); this->setMainWindow(mainWindow); @@ -231,7 +238,7 @@ QString ActionStateMachine::parseSCXMLTree() { QString initialStateName = scxmlDoc.documentElement().attribute("initial"); ActionState* initialState = statesMap->find(initialStateName).value(); machine.setInitialState(initialState); - ActionStateViewer::getActionStateViewer()->setState(initialState); + dynamic_cast(Application::getViewer("ActionStateViewer"))->setState(initialState); // Connect the end of the machine with the end of the application QObject::connect(&machine, SIGNAL(finished()), QApplication::instance(), SLOT(quit())); diff --git a/sdk/applications/actionstatemachine/ActionStateViewer.cpp b/sdk/applications/actionstatemachine/ActionStateViewer.cpp index 57a5b671..dbceb697 100644 --- a/sdk/applications/actionstatemachine/ActionStateViewer.cpp +++ b/sdk/applications/actionstatemachine/ActionStateViewer.cpp @@ -33,38 +33,18 @@ // Local includes #include "ActionStateViewer.h" -// ---------------------- singleton ---------------------------- -/// the register containing all the viewers (static instantiation, global variable, but global only for this file) -ActionStateViewer* ActionStateViewer::actionStateViewer; - -// ---------------- getActionStateViewer ---------------- -ActionStateViewer* ActionStateViewer::getActionStateViewer() { - if (!actionStateViewer) { - actionStateViewer = new ActionStateViewer(); - } - - return actionStateViewer; -} - // ---------------- constructor ---------------- -ActionStateViewer::ActionStateViewer() : Viewer("Current State") { +ActionStateViewer::ActionStateViewer(QString name) : Viewer(name) { + setLayout(Viewer::DOCKED); myWidget = nullptr; - + // empty the list as this is a state viewer, it has nothing to do with Components + setComponents(QStringList()); } // ---------------- getWidget ---------------- -QWidget* ActionStateViewer::getWidget(QWidget* parent) { +QWidget* ActionStateViewer::getWidget() { if (myWidget == nullptr) { - // if no parent then put this in a dialog - if (!parent) { - // put it in a dialog, this is the case for default MainWindow, who does not add the ActionViewer in a dock - QDialog* myWidgetIsADialog = new QDialog(nullptr); - myWidgetIsADialog->setWindowTitle(objectName()); - myWidget = myWidgetIsADialog; - } - else { - myWidget = new QWidget(); - } + myWidget = new QWidget(); auto* actionStateWidgetLayout = new QVBoxLayout(); diff --git a/sdk/applications/actionstatemachine/ActionStateViewer.h b/sdk/applications/actionstatemachine/ActionStateViewer.h index 9635bdf6..6842232d 100644 --- a/sdk/applications/actionstatemachine/ActionStateViewer.h +++ b/sdk/applications/actionstatemachine/ActionStateViewer.h @@ -30,7 +30,7 @@ #include // CamiTK stuff -#include "Viewer.h" +#include // Local includes #include "ActionState.h" @@ -46,11 +46,11 @@ class ActionStateViewer : public camitk::Viewer { Q_OBJECT public: - /// returns the unique instance oh ActionStateViewer - static ActionStateViewer* getActionStateViewer(); + + Q_INVOKABLE ActionStateViewer(QString name); - /// get the viewer widget. @param parent the parent widget for the viewer widget - virtual QWidget* getWidget(QWidget* parent = nullptr); + /// get the viewer widget. + virtual QWidget* getWidget(); /// returns the number of Component that are displayed by this viewer virtual unsigned int numberOfViewedComponent() { @@ -60,16 +60,15 @@ public: /// refresh the view (can be interesting to know which other viewer is calling this) virtual void refresh(Viewer* whoIsAsking = nullptr) {}; - + /// set the current state void setState(ActionState* actionState); private: - ActionStateViewer(); - - /// the singleton ActionStateViewer instance - static ActionStateViewer* actionStateViewer; + /// the viewer's widget QWidget* myWidget; + + /// the viewer's name QString name; /// actions stacked widget of the viewer diff --git a/sdk/applications/actionstatemachine/ActionStateViewerExtension.cpp b/sdk/applications/actionstatemachine/ActionStateViewerExtension.cpp new file mode 100644 index 00000000..19632d93 --- /dev/null +++ b/sdk/applications/actionstatemachine/ActionStateViewerExtension.cpp @@ -0,0 +1,36 @@ +/***************************************************************************** + * $CAMITK_LICENCE_BEGIN$ + * + * CamiTK - Computer Assisted Medical Intervention ToolKit + * (c) 2001-2018 Univ. Grenoble Alpes, CNRS, TIMC-IMAG UMR 5525 (GMCAO) + * + * Visit http://camitk.imag.fr for more information + * + * This file is part of CamiTK. + * + * CamiTK is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * CamiTK is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with CamiTK. If not, see . + * + * $CAMITK_LICENCE_END$ + ****************************************************************************/ + + +#include "ActionStateViewerExtension.h" + +// include generated actions headers +#include "ActionStateViewer.h" + +// --------------- getActions ------------------- +void ActionStateViewerExtension::init() { + registerDefaultViewer(ActionStateViewer); +} + diff --git a/sdk/applications/actionstatemachine/ActionStateViewerExtension.h b/sdk/applications/actionstatemachine/ActionStateViewerExtension.h new file mode 100644 index 00000000..ce85ad03 --- /dev/null +++ b/sdk/applications/actionstatemachine/ActionStateViewerExtension.h @@ -0,0 +1,61 @@ +/***************************************************************************** + * $CAMITK_LICENCE_BEGIN$ + * + * CamiTK - Computer Assisted Medical Intervention ToolKit + * (c) 2001-2018 Univ. Grenoble Alpes, CNRS, TIMC-IMAG UMR 5525 (GMCAO) + * + * Visit http://camitk.imag.fr for more information + * + * This file is part of CamiTK. + * + * CamiTK is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * CamiTK is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with CamiTK. If not, see . + * + * $CAMITK_LICENCE_END$ + ****************************************************************************/ + + +#ifndef ACTION_STATE_VIEWER_EXTENSION_H +#define ACTION_STATE_VIEWER_EXTENSION_H + +#include + +class ActionStateViewerExtension : public camitk::ViewerExtension { + Q_OBJECT + Q_INTERFACES(camitk::ViewerExtension); + Q_PLUGIN_METADATA(IID "fr.imag.camitk.actionstatemachine.viewer.actionstateviewerextension") + +public: + /// Constructor + ActionStateViewerExtension() : ViewerExtension() {}; + + /// Destructor + virtual ~ActionStateViewerExtension() = default; + + /// Method returning the action extension name + virtual QString getName() { + return "Action State Viewer Extension"; + }; + + /// Method returning the action extension descrption + virtual QString getDescription() { + return "This extension provides Action State Viewer"; + }; + + /// initialize all the actions + virtual void init(); + +}; + +#endif // ACTION_STATE_VIEWER_EXTENSION_H + + diff --git a/sdk/applications/actionstatemachine/ActionStateWidget.cpp b/sdk/applications/actionstatemachine/ActionStateWidget.cpp index 50f2155a..aa8e0383 100644 --- a/sdk/applications/actionstatemachine/ActionStateWidget.cpp +++ b/sdk/applications/actionstatemachine/ActionStateWidget.cpp @@ -23,9 +23,10 @@ * $CAMITK_LICENCE_END$ ****************************************************************************/ #include "ActionStateWidget.h" -#include "Action.h" #include "ActionState.h" +#include + ActionStateWidget::ActionStateWidget(ActionState* actionState) { ui.setupUi(this); myActionState = actionState; @@ -51,16 +52,3 @@ void ActionStateWidget::setActionWidget(QWidget* widget) { void ActionStateWidget::setDescription(QString description) { ui.stateDescriptionLabel->setText(description); } - - -//QPushButton * ActionStateWidget::setFinal() { -// const QPalette pal(Qt::red); // enumeration is Qt::GlobalColor -// QPushButton * button = new QPushButton("Quit", this); -// button->setAutoFillBackground(true); //this must be set for palette to work -// button->setPalette(pal); // assign color palette to button -// -// ui.buttonsLayout->addWidget(button); -// -// return button; -// -//} \ No newline at end of file diff --git a/sdk/applications/actionstatemachine/ActionTransition.cpp b/sdk/applications/actionstatemachine/ActionTransition.cpp index f9f61b7d..e6240cae 100644 --- a/sdk/applications/actionstatemachine/ActionTransition.cpp +++ b/sdk/applications/actionstatemachine/ActionTransition.cpp @@ -132,7 +132,7 @@ void ActionTransition::onTransition(QEvent* e) { if (nextActionState) { nextActionState->setPreviousActionStatus(status); - ActionStateViewer::getActionStateViewer()->setState(nextActionState); + dynamic_cast(Application::getViewer("ActionStateViewer"))->setState(nextActionState); } if (logStream != nullptr) { diff --git a/sdk/applications/actionstatemachine/CMakeLists.txt b/sdk/applications/actionstatemachine/CMakeLists.txt index 23268722..8de42b80 100644 --- a/sdk/applications/actionstatemachine/CMakeLists.txt +++ b/sdk/applications/actionstatemachine/CMakeLists.txt @@ -2,10 +2,11 @@ camitk_application(NEEDS_QT_MODULES #we use QtXML ADDITIONAL_SOURCES CommandLineOptions.cxx CommandLineOptions.hxx CommandLineOptions.ixx CEP_NAME SDK + NEEDS_VIEWER_EXTENSION explorer medicalimageviewer DESCRIPTION "Simple action state machine to pipeline actions from an XML file" ) # 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 diff --git a/sdk/applications/actionstatemachine/testdata/asmSimpleImageFilter.xml b/sdk/applications/actionstatemachine/testdata/asmSimpleImageFilter.xml index bfca68fb..83a88000 100644 --- a/sdk/applications/actionstatemachine/testdata/asmSimpleImageFilter.xml +++ b/sdk/applications/actionstatemachine/testdata/asmSimpleImageFilter.xml @@ -1,14 +1,14 @@
  • with low threshold to arbitrary set to 58
  • with high threshold arbitrary set to 153
  • -
  • Name the output image thresholdImage
  • +
  • Name the output image resampledImage
  • Save this output image in the same directory as the input image.
  • Quit the application
  • ]]> + + Set Path To Test Data + - + Open a new volume image and display it. - Open + Open File + + + @@ -53,7 +59,7 @@ This Action State Machine performs a very simple image processing pipeline:
    - +
    @@ -74,31 +80,33 @@ Please check that this image is the right image. - + - + - + - Image Processing Step + Resample Image - Manual Threshold Filter + Resample - - + + + + - + @@ -114,15 +122,15 @@ Please check that this image is the right image. Save - + - + - + @@ -145,7 +153,7 @@ to re-run the application from the beginning. - + diff --git a/sdk/applications/actionstatemachine/testdata/asmSimpleMeshProcessing.xml b/sdk/applications/actionstatemachine/testdata/asmSimpleMeshProcessing.xml index 51941959..9a5faa86 100644 --- a/sdk/applications/actionstatemachine/testdata/asmSimpleMeshProcessing.xml +++ b/sdk/applications/actionstatemachine/testdata/asmSimpleMeshProcessing.xml @@ -1,14 +1,14 @@ - + @@ -84,7 +84,7 @@ to the testdata directory before running.
    - + diff --git a/sdk/applications/imp/CMakeLists.txt b/sdk/applications/imp/CMakeLists.txt index ee84d18b..8dc0fcb7 100644 --- a/sdk/applications/imp/CMakeLists.txt +++ b/sdk/applications/imp/CMakeLists.txt @@ -1,7 +1,8 @@ camitk_application( ADDITIONAL_SOURCES CommandLineOptions.cxx CommandLineOptions.hxx CommandLineOptions.ixx CEP_NAME SDK - DESCRIPTION "All-in-one application to load actions and component and interact with them" + NEEDS_VIEWER_EXTENSION actionviewer medicalimageviewer explorer frameexplorer propertyexplorer + DESCRIPTION "All-in-one application to load actions and components and interact with them" ) # 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 "") \ No newline at end of file +set(SHIBOKEN_CAMITK_SDK_PATH ${SHIBOKEN_CAMITK_SDK_PATH}:${CMAKE_CURRENT_SOURCE_DIR} CACHE INTERNAL "") diff --git a/sdk/applications/imp/ImpMainWindow.cpp b/sdk/applications/imp/ImpMainWindow.cpp index b6d489f4..a0f66def 100644 --- a/sdk/applications/imp/ImpMainWindow.cpp +++ b/sdk/applications/imp/ImpMainWindow.cpp @@ -29,15 +29,12 @@ // -- Core stuff #include #include -#include -#include #include #include +#include #include +#include #include // for getActionDirectories() -#include -#include -#include #include #include #include @@ -54,6 +51,7 @@ using namespace camitk; #include #include #include +#include #include // ------------- constructor ----------------- @@ -72,22 +70,24 @@ ImpMainWindow::ImpMainWindow() : MainWindow("imp") { updateActionStates(); // now add the different viewers - setCentralViewer(MedicalImageViewer::getInstance()); - addDockViewer(Qt::LeftDockWidgetArea, Explorer::getInstance()); - addDockViewer(Qt::LeftDockWidgetArea, FrameExplorer::getInstance()); - addDockViewer(Qt::LeftDockWidgetArea, PropertyExplorer::getInstance()); - addDockViewer(Qt::RightDockWidgetArea, ActionViewer::getInstance()); + setCentralViewer(Application::getViewer("BitmapViewer")); + setCentralViewer(Application::getViewer("MedicalImageViewer")); + addDockViewer(Qt::LeftDockWidgetArea, Application::getViewer("Explorer")); + addDockViewer(Qt::LeftDockWidgetArea, Application::getViewer("FrameExplorer")); + addDockViewer(Qt::LeftDockWidgetArea, Application::getViewer("PropertyExplorer")); + addDockViewer(Qt::RightDockWidgetArea, Application::getViewer("ActionViewer")); //Merge Explorer and FrameExplorer viewers in one layout - QDockWidget* dockWidgetExplorer = dockWidgetMap.value(Explorer::getInstance(), NULL); - QDockWidget* dockWidgetFrameExplorer = dockWidgetMap.value(FrameExplorer::getInstance(), NULL); - if (dockWidgetExplorer && dockWidgetFrameExplorer) { + QDockWidget* dockWidgetExplorer = dockWidgetMap.value(Application::getViewer("Explorer"), nullptr); + QDockWidget* dockWidgetFrameExplorer = dockWidgetMap.value(Application::getViewer("FrameExplorer"), nullptr); + + if (dockWidgetExplorer != nullptr && dockWidgetFrameExplorer != nullptr) { tabifyDockWidget(dockWidgetExplorer, dockWidgetFrameExplorer); dockWidgetExplorer->raise(); } - showDockViewer(ActionViewer::getInstance(), false); - ActionViewer::getInstance()->setSearchPanelVisible(true); + showDockViewer(Application::getViewer("ActionViewer"), false); + dynamic_cast(Application::getViewer("ActionViewer"))->setSearchPanelVisible(true); showStatusBar(true); } @@ -140,6 +140,7 @@ void ImpMainWindow::initActions() { QListIterator it(ExtensionManager::getActionExtensionsList()); while (it.hasNext() && applicationActionExtension == nullptr) { ActionExtension* current = it.next(); + if (current->getName() == "Application Level Actions") { applicationActionExtension = current; } @@ -195,7 +196,7 @@ void ImpMainWindow::initActions() { // global shortcut, NOTE: the action should also be added as an ImpMainWindow action, otherwise the shortcut will not work when // the menu bar is hidden! (see initMenuBar() method) viewMenuBar->setShortcutContext(Qt::ApplicationShortcut); - connect(viewMenuBar, SIGNAL(triggered(bool)), this, SLOT(showMenuBar(bool))); + connect(viewMenuBar, SIGNAL(triggered()), this, SLOT(toggleMenuBar())); // NOTE: viewMenuBar can be used to hide the menu bar, if the menu bar is not visible, // since Qt4, it does not receive any event (and thus there is no way to set the menu // visible again! Which is quite annoying). @@ -222,8 +223,7 @@ void ImpMainWindow::initActions() { } -//************************************************************************** - +// ------------- initMenuBar ----------------- void ImpMainWindow::initMenuBar() { // -- file fileMenu = new QMenu(tr("&File")); @@ -333,6 +333,7 @@ void ImpMainWindow::updateActionStates() { else { // add all generic actions ActionList allActions = Application::getActions(NULL); + foreach (Action* action, allActions) { actionMenu->addAction(action->getQAction()); actionMenu->setEnabled(true); @@ -353,22 +354,19 @@ void ImpMainWindow::showToolbar(bool b) { mainToolbar->setVisible(b); } -// ------------- showMenuBar ----------------- -void ImpMainWindow::showMenuBar(bool b) { - if (!b) { +// ------------- toggleMenuBar ----------------- +void ImpMainWindow::toggleMenuBar() { + bool menuBarVisible = menuBar()->isVisible(); + + if (menuBarVisible) { // warn the user first CAMITK_WARNING(tr("Hide menu: the menu is going to be hidden. There is only one way to make it reappear: you need to press CTRL+M again.")) - viewMenuBar->blockSignals(true); - viewMenuBar->setChecked(true); - viewMenuBar->blockSignals(false); - } - else { - menuBar()->setVisible(b); - viewMenuBar->blockSignals(true); - viewMenuBar->setChecked(b); - viewMenuBar->blockSignals(false); - showStatusBar(b); } + + menuBar()->setVisible(!menuBarVisible); + viewMenuBar->blockSignals(true); + viewMenuBar->setChecked(!menuBarVisible); + viewMenuBar->blockSignals(false); } // ------------- showStatusBar ----------------- @@ -379,40 +377,45 @@ void ImpMainWindow::showStatusBar(bool b) { // ------------------------ resetWindows ---------------------------- void ImpMainWindow::resetWindows() { for (QMap::iterator it = dockWidgetMap.begin(); it != dockWidgetMap.end(); it++) { - if (it.value()->widget() == Explorer::getInstance()->getWidget(NULL)) { + if (it.key()->getName() == "Explorer") { removeDockWidget(it.value()); addDockWidget(Qt::LeftDockWidgetArea, it.value()); it.value()->show(); } - else - if (it.value()->widget() == FrameExplorer::getInstance()->getWidget(NULL)) { + else { + if (it.key()->getName() == "FrameExplorer") { removeDockWidget(it.value()); addDockWidget(Qt::LeftDockWidgetArea, it.value()); it.value()->show(); } - else - if (it.value()->widget() == PropertyExplorer::getInstance()->getWidget()) { + else { + if (it.key()->getName() == "PropertyExplorer") { removeDockWidget(it.value()); addDockWidget(Qt::LeftDockWidgetArea, it.value()); it.value()->show(); } - else - if (it.value()->widget() == ActionViewer::getInstance()->getWidget()) { + else { + if (it.key()->getName() == "ActionViewer") { removeDockWidget(it.value()); addDockWidget(Qt::RightDockWidgetArea, it.value()); it.value()->show(); } + } + } + } } - //Merge Explorer and FrameExplorer viewers in one layout - QDockWidget* dockWidgetExplorer = dockWidgetMap.value(Explorer::getInstance(), NULL); - QDockWidget* dockWidgetFrameExplorer = dockWidgetMap.value(FrameExplorer::getInstance(), NULL); + + // Merge Explorer and FrameExplorer viewers in one layout + QDockWidget* dockWidgetExplorer = dockWidgetMap.value(Application::getViewer("Explorer"), NULL); + QDockWidget* dockWidgetFrameExplorer = dockWidgetMap.value(Application::getViewer("FrameExplorer"), NULL); + if (dockWidgetExplorer && dockWidgetFrameExplorer) { tabifyDockWidget(dockWidgetExplorer, dockWidgetFrameExplorer); dockWidgetExplorer->raise(); } showStatusBar(true); - showMenuBar(true); + menuBar()->setVisible(true); showToolbar(true); // reset geometry to default @@ -457,8 +460,7 @@ void ImpMainWindow::openDataDirectory(QString plugin) { void ImpMainWindow::updateViewMenu() { // From Qt documentation: // "Removes all the menu's actions. Actions owned by the menu and not shown in any other widget are deleted" - // I.e., the central viewer toggle action are own by viewMenu (they are created and used here), they will - // therefore be no memory leak + // this will therefore automatically delete the toggle central viewer's action viewMenu->clear(); // insert viewers menu @@ -470,28 +472,20 @@ void ImpMainWindow::updateViewMenu() { } } - // change the central viewer if there is more than one viewer in the central area - if (qobject_cast(centralWidget())->count() > 1) { - viewMenu->addSeparator()->setText(tr("Toggle Central Viewers")); - - // add a toggle action for each widget stacked inside the central widget - for (int i = 0; i < qobject_cast(centralWidget())->count(); i++) { - QWidget* cWidget = qobject_cast(centralWidget())->widget(i); - // Get the viewer associated with the widget in the central area - // As there is no map from widget to viewer, we need to find the viewer that - // has the given corresponding widget. - // Beware that getWidget(..) requires a parent and as the widget was setup inside centralWidget() - // it was reparented to centralWidget() → use getWidget(centralWidget()) and not getWidget(this) - // in order not to modify the central widget parenting - auto it = std::find_if(viewers.begin(), viewers.end(), [&](Viewer * v) { - return v->getWidget(centralWidget()) == cWidget; - }); - Viewer* cViewer = (*it); + viewMenu->addSeparator(); + + QMenu* toggleCentralWidgetMenu = viewMenu->addMenu(tr("Toggle Central Viewer")); + + // add an action for each viewer of layout "stacked" + foreach (Viewer* viewer, viewers) { + // only add viewer that are not docked + if (viewer->getLayout() == Viewer::STACKED) { // viewerAction is own by viewMenu, viewMenu->clear() will delete it QAction* viewerAction = viewMenu->addAction(cViewer->objectName()); viewerAction->setCheckable(true); - viewerAction->setChecked(cViewer == centralViewer); - QString tipString = "Hide/show the " + cViewer->objectName() + " central viewer"; + viewerAction->setChecked(viewer == centralViewer); + viewerAction->setIcon(viewer->getIcon()); + QString tipString = "Hide/show the " + viewer->objectName() + " in the central viewer"; viewerAction->setStatusTip(tr(tipString.toStdString().c_str())); viewerAction->setWhatsThis(tr(tipString.toStdString().c_str())); // add the toggle action slot using C++11 lambda so that everything is contained inside viewMenu @@ -502,18 +496,20 @@ void ImpMainWindow::updateViewMenu() { } // insert viewers on/off actions - viewMenu->addSeparator()->setText(tr("Toggle Viewers")); - viewMenu->addAction(viewResetWindows); + QMenu* toggleDockedMenu = viewMenu->addMenu(tr("Toggle Docked Viewers")); + + toggleDockedMenu->addAction(viewResetWindows); for (QMap::iterator it = dockWidgetMap.begin(); it != dockWidgetMap.end(); it++) { - viewMenu->addAction(it.value()->toggleViewAction()); + it.value()->toggleViewAction()->setIcon(it.key()->getIcon()); + toggleDockedMenu->addAction(it.value()->toggleViewAction()); } // insert generic on/off actions - viewMenu->addSeparator()->setText(tr("Other Toggle")); - viewMenu->addAction(viewMenuBar); - viewMenu->addAction(viewStatusBar); - viewMenu->addAction(mainToolbar->toggleViewAction()); + QMenu* otherToggleMenu = viewMenu->addMenu(tr("Other Toggle")); + otherToggleMenu->addAction(viewMenuBar); + otherToggleMenu->addAction(viewStatusBar); + otherToggleMenu->addAction(mainToolbar->toggleViewAction()); } // ------------------------------ slotEditSettings ------------------------------- diff --git a/sdk/applications/imp/ImpMainWindow.h b/sdk/applications/imp/ImpMainWindow.h index aeabf143..d6f0de20 100644 --- a/sdk/applications/imp/ImpMainWindow.h +++ b/sdk/applications/imp/ImpMainWindow.h @@ -98,7 +98,7 @@ public slots: void showToolbar(bool); /// show or hide the menu bar - void showMenuBar(bool); + void toggleMenuBar(); /// reset all windows in their initial state void resetWindows(); diff --git a/sdk/applications/wizard/CMakeLists.txt b/sdk/applications/wizard/CMakeLists.txt index 3aec6ed5..d4fa21b8 100644 --- a/sdk/applications/wizard/CMakeLists.txt +++ b/sdk/applications/wizard/CMakeLists.txt @@ -1,6 +1,7 @@ camitk_application(NEEDS_XSD NEEDS_XERCESC NEEDS_CEP_LIBRARIES cepgenerator cepcoreschema + NEEDS_VIEWER_EXTENSION explorer CEP_NAME SDK ADDITIONAL_SOURCES CommandLineOptions.cxx CommandLineOptions.hxx CommandLineOptions.ixx DESCRIPTION "Create CEP and file skeletons from GUI" diff --git a/sdk/cmake/modules/macros/camitk/CamiTKApplication.cmake b/sdk/cmake/modules/macros/camitk/CamiTKApplication.cmake index 73c250ab..a939bb67 100644 --- a/sdk/cmake/modules/macros/camitk/CamiTKApplication.cmake +++ b/sdk/cmake/modules/macros/camitk/CamiTKApplication.cmake @@ -475,7 +475,7 @@ macro(camitk_application) # # ######################################################################### # LINKING LIBRARIES - target_link_libraries(${APPLICATION_TARGET_NAME} ${CAMITK_CORE_LIBRARIES} ${CAMITK_LIBRARIES} ${COMPONENT_EXTENSION_LIBRARIES} ${ACTION_EXTENSION_LIBRARIES} ${CEP_LIBRARIES} ${XERCESC_LIBRARY} ${CAMITK_ITK_LIBRARIES} ${PYTHON_LIBRARIES} ${EXTERNAL_LIBRARIES}) + target_link_libraries(${APPLICATION_TARGET_NAME} ${CAMITK_CORE_LIBRARIES} ${CAMITK_LIBRARIES} ${COMPONENT_EXTENSION_LIBRARIES} ${ACTION_EXTENSION_LIBRARIES} ${VIEWER_EXTENSION_LIBRARIES} ${CEP_LIBRARIES} ${XERCESC_LIBRARY} ${CAMITK_ITK_LIBRARIES} ${PYTHON_LIBRARIES} ${EXTERNAL_LIBRARIES}) diff --git a/sdk/components/msh/MshComponent.cpp b/sdk/components/msh/MshComponent.cpp index 6dbbf7ee..266917ae 100644 --- a/sdk/components/msh/MshComponent.cpp +++ b/sdk/components/msh/MshComponent.cpp @@ -28,6 +28,7 @@ #include +#include #include #include @@ -165,7 +166,7 @@ void MshComponent::readLegacyFormat(std::ifstream& fileStream) { initRepresentation(mesh); // add the represention in the 3D viewer - setVisibility(InteractiveViewer::get3DViewer(), true); + setVisibility(Application::getViewer("3DViewer"), true); } void MshComponent::readV2Format(std::ifstream& fileStream) { @@ -322,5 +323,5 @@ void MshComponent::readV2Format(std::ifstream& fileStream) { initRepresentation(mesh); // add the represention in the 3D viewer - setVisibility(InteractiveViewer::get3DViewer(), true); + setVisibility(Application::getViewer("3DViewer"), true); } diff --git a/sdk/components/off/OffComponent.cpp b/sdk/components/off/OffComponent.cpp index a9a52fee..0b446795 100644 --- a/sdk/components/off/OffComponent.cpp +++ b/sdk/components/off/OffComponent.cpp @@ -27,6 +27,7 @@ #include +#include #include #include @@ -116,7 +117,7 @@ OffComponent::OffComponent(const QString& file) : MeshComponent(file) { initRepresentation(offMesh); // add the represention in the 3D viewer - setVisibility(InteractiveViewer::get3DViewer(), true); + setVisibility(Application::getViewer("3DViewer"), true); // initialize the dynamic properties //initDynamicProperties(); diff --git a/sdk/components/vrml/VRMLComponentExtension.cpp b/sdk/components/vrml/VRMLComponentExtension.cpp index 8c87b663..2115e1cf 100644 --- a/sdk/components/vrml/VRMLComponentExtension.cpp +++ b/sdk/components/vrml/VRMLComponentExtension.cpp @@ -28,6 +28,7 @@ #include "VRMLComponent.h" //-- CamiTK stuff +#include #include #include using namespace camitk; @@ -69,7 +70,7 @@ bool VRMLComponentExtension::save(Component* component) const { } else if (mesh->getPointSet()) { vtkSmartPointer exporter = vtkSmartPointer::New(); - exporter->SetInput(InteractiveViewer::get3DViewer()->getRendererWidget()->GetRenderWindow()); + exporter->SetInput(dynamic_cast(Application::getViewer("3DViewer"))->getRendererWidget()->GetRenderWindow()); exporter->SetFileName(mesh->getFileName().toStdString().c_str()); exporter->Write(); return true; diff --git a/sdk/libraries/core/CMakeLists.txt b/sdk/libraries/core/CMakeLists.txt index 998afd67..a318dbad 100644 --- a/sdk/libraries/core/CMakeLists.txt +++ b/sdk/libraries/core/CMakeLists.txt @@ -152,4 +152,4 @@ set(SHIBOKEN_CAMITK_SDK_PATH ${SHIBOKEN_CAMITK_SDK_PATH}:${CMAKE_CURRENT_SOURCE_ set(SHIBOKEN_CAMITK_SDK_PATH ${SHIBOKEN_CAMITK_SDK_PATH}:${CMAKE_CURRENT_SOURCE_DIR}/component/image CACHE INTERNAL "") set(SHIBOKEN_CAMITK_SDK_PATH ${SHIBOKEN_CAMITK_SDK_PATH}:${CMAKE_CURRENT_SOURCE_DIR}/component/mesh CACHE INTERNAL "") set(SHIBOKEN_CAMITK_SDK_PATH ${SHIBOKEN_CAMITK_SDK_PATH}:${CMAKE_CURRENT_SOURCE_DIR}/utils CACHE INTERNAL "") -set(SHIBOKEN_CAMITK_SDK_PATH ${SHIBOKEN_CAMITK_SDK_PATH}:${CMAKE_CURRENT_SOURCE_DIR}/viewer CACHE INTERNAL "") +set(SHIBOKEN_CAMITK_SDK_PATH ${SHIBOKEN_CAMITK_SDK_PATH}:${CMAKE_CURRENT_SOURCE_DIR}/viewer CACHE INTERNAL "") \ No newline at end of file diff --git a/sdk/libraries/core/CamiTKAPI.h b/sdk/libraries/core/CamiTKAPI.h index df652390..f937408d 100644 --- a/sdk/libraries/core/CamiTKAPI.h +++ b/sdk/libraries/core/CamiTKAPI.h @@ -91,6 +91,9 @@ using ComponentList = QList; /// A set of Action using ActionSet = QSet; +/// A set of Viewer +using ViewerSet = QSet; + /// A list of Action using ActionList = QList; } diff --git a/sdk/libraries/core/ExtensionManager.cpp b/sdk/libraries/core/ExtensionManager.cpp index f76067df..36ca3cb3 100644 --- a/sdk/libraries/core/ExtensionManager.cpp +++ b/sdk/libraries/core/ExtensionManager.cpp @@ -28,6 +28,7 @@ #include "Core.h" #include "Application.h" #include "Action.h" +#include "Viewer.h" // -- QT stuff #include @@ -44,19 +45,27 @@ namespace camitk { void ExtensionManager::autoload() { autoload(COMPONENT); autoload(ACTION); + autoload(VIEWER); } void ExtensionManager::autoload(ExtensionManager::ExtensionType type) { QStringList extensionDir; + switch (type) { case ACTION: extensionDir = Core::getActionDirectories(); break; + case COMPONENT: extensionDir = Core::getComponentDirectories(); break; + + case VIEWER: + extensionDir = Core::getViewerDirectories(); + break; + default: - CAMITK_TRACE_ALT(tr("autoload of unknown type: type should be either ACTION or COMPONENT, other extensions are not implemented yet")) + CAMITK_TRACE_ALT(tr("autoload of unknown type: type should be either ACTION or COMPONENT or VIEWER, other extensions are not implemented yet")) break; } @@ -64,11 +73,14 @@ void ExtensionManager::autoload(ExtensionManager::ExtensionType type) { QStringList extensionFileNames; QStringList extensionAbsoluteFileNames; QMap extensionUniqueDir; + foreach (QString dirName, extensionDir) { QDir dir(dirName); QStringList pluginFileNames = getPluginFileNames(dir); + foreach (QString pluginFile, pluginFileNames) { QString pluginAbsoluteFileName = dir.absoluteFilePath(pluginFile); + if (!extensionFileNames.contains(pluginFile)) { extensionFileNames.append(pluginFile); extensionUniqueDir.insert(pluginFile, dir); @@ -110,6 +122,7 @@ void ExtensionManager::autoload(ExtensionManager::ExtensionType type) { if (extensionAbsoluteFileNames.size() > 0) { // get the messages from Qt QStringList errorStrings; + foreach (QString fileName, extensionAbsoluteFileNames) { QPluginLoader pluginLoader(fileName); QObject* plugin = pluginLoader.instance(); @@ -141,16 +154,24 @@ void ExtensionManager::autoload(ExtensionManager::ExtensionType type) { QSettings& settings = Application::getSettings(); settings.beginGroup("UserExtensions"); QStringList userRegisteredExtensions; + switch (type) { case ACTION: userRegisteredExtensions = settings.value("actions", QVariant(QStringList())).toStringList(); break; + case COMPONENT: userRegisteredExtensions = settings.value("components", QVariant(QStringList())).toStringList(); break; + + case VIEWER: + userRegisteredExtensions = settings.value("viewers", QVariant(QStringList())).toStringList(); + break; + default: break; } + settings.endGroup(); foreach (QString userRegisteredExtensionFile, userRegisteredExtensions) { @@ -188,6 +209,41 @@ bool ExtensionManager::loadExtension(ExtensionManager::ExtensionType type, QStri } break; + case VIEWER: { + ViewerExtension* ext = qobject_cast (extension); + + if (ext) { + ext->setLocation(fileName); + ext->initResources(); + // initialize all viewers + ext->init(); + + int i = 0; + + while (i < getViewerExtensionMap().size() && getViewerExtensionsList().at(i)->getViewerClassName() != ext->getViewerClassName()) { + i++; + } + + if (returnValue = (i >= getViewerExtensionMap().size())) { + //-- register the filename + getViewerExtensionMap().insert(fileName, ext); + //-- register all viewers + Application::registerAllViewers(ext); + } + else { + CAMITK_INFO_ALT(tr("Extension Manager: duplicate extension management: viewer extension \"%1\" (in file \"%2\") declares management of \"%3\" while \"%4\" extension (loaded from file \"%5\") is already managing \"%6\".\nUsing extension in \"%7\" instead (higher priority) as only one viewer extension can manage an instance of viewer.") + .arg(ext->getName(), + fileName, + ext->getViewerClassName(), + getViewerExtensionsList().at(i)->getName(), + getViewerExtensionsList().at(i)->getLocation(), + ext->getViewerClassName(), + getViewerExtensionsList().at(i)->getLocation())) + } + } + } + break; + case COMPONENT: { ComponentExtension* cp = qobject_cast (extension); @@ -207,6 +263,7 @@ bool ExtensionManager::loadExtension(ExtensionManager::ExtensionType type, QStri // (cannot do that in the constructor because the virtual symbol table seems to be confused!) foreach (QString ext, cp->getFileExtensions()) { ComponentExtension* existingComponentExtension = getComponentExtensionMap().value(ext); + if (existingComponentExtension != nullptr) { CAMITK_INFO_ALT(tr("Extension Manager: duplicate extension management: component extension \"%1\" (in file \"%2\") declares management of \"%3\" file extension while \"%4\" extension (loaded from file \"%5\") is already managing \"%6\".\nUsing extension in \"%7\" instead (higher priority) as only one component extension can manage a give file extension.") .arg(cp->getName(), @@ -244,6 +301,7 @@ bool ExtensionManager::loadExtension(ExtensionManager::ExtensionType type, QStri // try to load the missing shared object directly from private dir (give absolute path) QRegExp libname("\\((lib.*): cannot open shared object file"); + if (libname.indexIn(pluginLoader.errorString(), 0) != -1) { QString privateLibToLoad = Core::getGlobalInstallDir() + "/lib/" + QString(Core::shortVersion) + "/" + libname.cap(1); QLibrary privateLib(privateLibToLoad); @@ -266,18 +324,22 @@ QString ExtensionManager::getInstallationString(QString file, const QString& glo dir.cdUp(); QString absolutePath = dir.absolutePath(); + if (absolutePath == currentWorkingDir) { whichInstallDir = "[W]"; } - else if (absolutePath == userInstallDir) { - whichInstallDir = "[L]"; - } - else if (absolutePath == globalInstallDir) { - whichInstallDir = "[G]"; - } - else { - whichInstallDir = "[U]"; - } + else + if (absolutePath == userInstallDir) { + whichInstallDir = "[L]"; + } + else + if (absolutePath == globalInstallDir) { + whichInstallDir = "[G]"; + } + else { + whichInstallDir = "[U]"; + } + return whichInstallDir; } @@ -380,6 +442,56 @@ void ExtensionManager::unloadAllActionExtensions() { } } +// -------------------- getViewerExtensionMap -------------------- +QMap& camitk::ExtensionManager::getViewerExtensionMap() { + static QMap viewerExtensionMap; + + return viewerExtensionMap; +} + +// -------------------- unloadAllViewerExtensions -------------------- +void camitk::ExtensionManager::unloadAllViewerExtensions() { + QList allExtensions = getViewerExtensionMap().keys(); + + while (!allExtensions.isEmpty()) { + unloadViewerExtension(allExtensions.takeFirst()); + } +} + +const QList camitk::ExtensionManager::getViewerExtensionsList() { + QList< ViewerExtension* > sortedList = getViewerExtensionMap().values().toSet().toList(); // to remove duplicates + qSort(sortedList.begin(), sortedList.end(), ExtensionManager::viewerExtensionLessThan); + + return sortedList; +} + +ViewerExtension* camitk::ExtensionManager::getViewerExtension(QString file) { + return getViewerExtensionMap().value(file); +} + +// -------------------- unloadViewerExtension -------------------- +bool ExtensionManager::unloadViewerExtension(QString fileName) { + if (getViewerExtensionMap().contains(fileName)) { + ViewerExtension* ext = getViewerExtensionMap().value(fileName); + + //-- unregister all actions + foreach (Viewer* viewer, ext->getViewers()) { + getViewerExtensionMap().remove(viewer->getName()); + } + + //-- unregister extension + getViewerExtensionMap().remove(fileName); + // -- unregister actions from application + Application::unregisterAllViewers(ext); + //-- delete extensions (and all its actions) + delete ext; + return true; + } + else { + return false; + } +} + // -------------------- registerFileExtension -------------------- void ExtensionManager::registerFileExtension(QString fileExtension) { // we get the application name and its binary path for the association @@ -416,12 +528,14 @@ QStringList ExtensionManager::getExtensionFilter() { QStringList pluginFilter; // linux: .so, windows: .dll, macOs: .dylib pluginFilter << "*.so." + QString(Core::soVersion) << "*." + QString(Core::soVersion) + ".dylib"; + if (Core::isDebugBuild()) { pluginFilter << "*" + QString(Core::debugPostfix) + ".dll"; } else { pluginFilter << "*.dll"; } + return pluginFilter; } @@ -443,8 +557,10 @@ QStringList ExtensionManager::getPluginFileNames(QDir extensionsDir) { foreach (QString debugDLL, pluginFileNamesDebugMSVC) { pluginFileNames.removeAll(debugDLL); } + return pluginFileNames; } + #endif return pluginFileNames; @@ -455,10 +571,12 @@ QStringList ExtensionManager::getPluginFileNames(QDir extensionsDir) { bool ExtensionManager::unloadActionExtension(QString fileName) { if (getActionExtensionMap().contains(fileName)) { ActionExtension* ext = getActionExtensionMap().value(fileName); + //-- unregister all actions foreach (Action* action, ext->getActions()) { getActionExtensionMap().remove(action->getName()); } + //-- unregister extension getActionExtensionMap().remove(fileName); // -- unregister actions from application @@ -535,6 +653,7 @@ void ExtensionManager::initPrivateLibDirs() { if (!alreadyInitialized) { // Build directory QDir privateBuildLibDir(Core::getCurrentWorkingDir()); + if (privateBuildLibDir.cd("lib/" + QString(Core::shortVersion))) { QByteArray privateBuildLibDirPath = privateBuildLibDir.canonicalPath().toUtf8(); #ifdef WIN32 // for Windows @@ -545,16 +664,20 @@ void ExtensionManager::initPrivateLibDirs() { path.append(privateBuildLibDirPath + "/actions"); path.append(";"); path.append(privateBuildLibDirPath + "/components"); + path.append(";"); + path.append(privateBuildLibDirPath + "/viewers"); qputenv("PATH", path); #endif // update the application / qt plugins library path Application::instance()->addLibraryPath(privateBuildLibDirPath); Application::instance()->addLibraryPath(privateBuildLibDirPath + "/actions"); Application::instance()->addLibraryPath(privateBuildLibDirPath + "/components"); + Application::instance()->addLibraryPath(privateBuildLibDirPath + "/viewers"); } // Local install directory QDir privateLocalLibDir(Core::getUserInstallDir()); + if (privateLocalLibDir.cd("lib/" + QString(Core::shortVersion))) { QByteArray privateLocalLibDirPath = privateLocalLibDir.canonicalPath().toUtf8(); #ifdef WIN32 // for Windows @@ -565,16 +688,20 @@ void ExtensionManager::initPrivateLibDirs() { path.append(privateLocalLibDirPath + "/actions"); path.append(";"); path.append(privateLocalLibDirPath + "/components"); + path.append(";"); + path.append(privateLocalLibDirPath + "/viewers"); qputenv("PATH", path); #endif // update the application / qt plugins library path Application::instance()->addLibraryPath(privateLocalLibDirPath); Application::instance()->addLibraryPath(privateLocalLibDirPath + "/actions"); Application::instance()->addLibraryPath(privateLocalLibDirPath + "/components"); + Application::instance()->addLibraryPath(privateLocalLibDirPath + "/viewers"); } // Global install directory QDir privateGlobalLibDir(Core::getGlobalInstallDir()); + if (privateGlobalLibDir.cd("lib/" + QString(Core::shortVersion))) { QByteArray privateGlobalLibDirPath = privateGlobalLibDir.canonicalPath().toUtf8(); #ifdef WIN32 // for Windows @@ -585,13 +712,17 @@ void ExtensionManager::initPrivateLibDirs() { path.append(privateGlobalLibDirPath + "/actions"); path.append(";"); path.append(privateGlobalLibDirPath + "/components"); + path.append(";"); + path.append(privateGlobalLibDirPath + "/viewers"); qputenv("PATH", path); #endif // update the application / qt plugins library path Application::instance()->addLibraryPath(privateGlobalLibDirPath); Application::instance()->addLibraryPath(privateGlobalLibDirPath + "/actions"); Application::instance()->addLibraryPath(privateGlobalLibDirPath + "/components"); + Application::instance()->addLibraryPath(privateGlobalLibDirPath + "/viewers"); } + alreadyInitialized = true; } } @@ -606,6 +737,11 @@ bool ExtensionManager::actionExtensionLessThan(ActionExtension* left, ActionExte return left->getName() < right->getName(); } +// -------------------- viewerExtensionLessThan -------------------- +bool ExtensionManager::viewerExtensionLessThan(ViewerExtension* left, ViewerExtension* right) { + return left->getName() < right->getName(); +} + } diff --git a/sdk/libraries/core/action/Action.cpp b/sdk/libraries/core/action/Action.cpp index a3a5bc4e..c26f2616 100644 --- a/sdk/libraries/core/action/Action.cpp +++ b/sdk/libraries/core/action/Action.cpp @@ -24,8 +24,9 @@ ****************************************************************************/ #include "Action.h" +#include "Viewer.h" #include "ActionExtension.h" -#include "ActionViewer.h" +//#include "ActionViewer.h" #include "Application.h" #include "Component.h" #include "ActionWidget.h" @@ -52,6 +53,7 @@ Action::~Action() { foreach (Property* prop, parameterMap.values()) { delete prop; } + parameterMap.clear(); //delete History item @@ -63,26 +65,33 @@ Action::~Action() { // -------------------- getStatusAsString -------------------- QString Action::getStatusAsString(ApplyStatus status) { QString statusStr; + switch (status) { case Action::ABORTED: statusStr = "ABORTED"; break; + case Action::ERROR: statusStr = "ERROR"; break; + case Action::SUCCESS: statusStr = "SUCCESS"; break; + case Action::TRIGGERED: statusStr = "TRIGGERED"; break; + case Action::WARNING: statusStr = "WARNING"; break; + default: statusStr = "UNKNOWN"; break; } + return statusStr; } @@ -186,11 +195,8 @@ Action::ApplyStatus Action::trigger(QWidget* parent) { //-- if there are some valid targets or if the action is generic if (targetComponents.size() > 0 || getComponent().isEmpty()) { if (isEmbedded) { - // if there are no parents to use use the action viewer - if (parent == nullptr) { - ActionViewer::getInstance()->embedActionWidget(this); - } - else { + if (parent != nullptr) { + // set the widget in the given parent getWidget()->setParent(parent); getWidget()->show(); } @@ -208,6 +214,15 @@ Action::ApplyStatus Action::trigger(QWidget* parent) { } } + // tell the application this action is ready to show its widget + Application::setTriggeredAction(this); + // make sure that any viewer that wants to show something about it is refreshed + Application::refresh(); + // now that everyone that wanted to be notified about this change of action selection, + // there is no need to do more, just empty the current selection + Application::setTriggeredAction(nullptr); + + return TRIGGERED; } else { @@ -266,6 +281,7 @@ Action::ApplyStatus Action::applyInPipeline() { void Action::setInputComponents(ComponentList inputs) { //-- build the list of valid targets targetComponents.clear(); + foreach (Component* comp, inputs) { // check compatibility if (comp->isInstanceOf(this->getComponent())) { @@ -314,6 +330,7 @@ void Action::preProcess() { // We will select the one selected as input of the current action this->topLevelSelectedComponents.clear(); QList topLevelSelectedHistoryComponents; + foreach (Component* comp, this->aliveBeforeComponents) { if (comp->isSelected()) { this->topLevelSelectedComponents.append(comp); @@ -340,6 +357,7 @@ void Action::postProcess() { ComponentList topLevelComponentCreated; QList topLevelHistoryComponentCreated; topLevelHistoryComponentCreated.clear(); + foreach (Component* comp, Application::getTopLevelComponents()) { if (!this->aliveBeforeComponents.contains(comp)) { topLevelComponentCreated.append(comp); @@ -365,6 +383,7 @@ void Action::postProcess() { void Action::postProcessInPipeline() { outputComponents.clear(); ComponentList allComp = Application::getAllComponents(); + foreach (Component* comp, allComp) { if (!aliveBeforeComponents.contains(comp) || comp->getModified()) { outputComponents.append(comp); @@ -380,6 +399,7 @@ bool Action::getAutoUpdateProperties() const { // -------------------- setAutoUpdateProperties -------------------- void Action::setAutoUpdateProperties(bool autoUpdateProperties) { this->autoUpdateProperties = autoUpdateProperties; + if (actionWidget) { dynamic_cast(actionWidget)->setAutoUpdateProperty(autoUpdateProperties); } @@ -411,10 +431,12 @@ void Action::applyTargetPosition(Component* input, Component* target, Applicatio case Application::NO_TRANSFORMATION: target->setParentFrame(nullptr); break; + case Application::SUBFRAME: target->setParentFrame(nullptr); // reset the frame transform to Identity target->setParentFrame(input); break; + case Application::SAME_TRANSFORMATION: default: target->setParentFrame(nullptr); @@ -438,3 +460,5 @@ void Action::applyTargetPosition(Component* input, Component* target, Applicatio + + diff --git a/sdk/libraries/core/action/ActionExtension.cpp b/sdk/libraries/core/action/ActionExtension.cpp index 54d0b149..1875c6d4 100644 --- a/sdk/libraries/core/action/ActionExtension.cpp +++ b/sdk/libraries/core/action/ActionExtension.cpp @@ -35,6 +35,38 @@ namespace camitk { +// -------------------- constructor -------------------- +ActionExtension::ActionExtension() { + translator = nullptr; +} + +// -------------------- destructor -------------------- +ActionExtension::~ActionExtension() { + while (!actions.empty()) { + Action* toDelete = actions.takeFirst(); + + // do not delete the "Quit" action: it is the action that triggers this delete! + if (toDelete->getName() != "Quit") { + delete toDelete; + } + } + + //delete internationalization instance + if (translator) { + delete translator; + } +} + +// -------------------- setLocation -------------------- +void ActionExtension::setLocation(const QString loc) { + dynamicLibraryFileName = loc; +} + +// -------------------- getLocation -------------------- +QString ActionExtension::getLocation() const { + return dynamicLibraryFileName; +} + // -------------------- initResources -------------------- void ActionExtension::initResources() { // Get the selected language @@ -47,6 +79,7 @@ void ActionExtension::initResources() { actionExtensionDirName.remove("-debug.dll").remove(".so").remove(".dylib"); QString languageFile = ":/translate_" + actionExtensionDirName + "/translate/translate_" + selectedLanguage + ".qm"; translator = new QTranslator(); + if (translator->load(languageFile)) { QCoreApplication::installTranslator(translator); } @@ -56,23 +89,6 @@ void ActionExtension::initResources() { } } -// -------------------- destructor -------------------- -ActionExtension::~ActionExtension() { - // delete all actions one by one - while (!actions.empty()) { - Action* toDelete = actions.takeFirst(); - // do not delete the "Quit" action: it is the action that triggers this delete! - if (toDelete->getName() != "Quit") { - delete toDelete; - } - } - - // delete internationalization instance - if (translator) { - delete translator; - } -} - // -------------------- registerAction -------------------- void ActionExtension::registerAction(Action* action) { // simply add the action in the list diff --git a/sdk/libraries/core/action/ActionExtension.h b/sdk/libraries/core/action/ActionExtension.h index 63fec35a..8c4adc64 100644 --- a/sdk/libraries/core/action/ActionExtension.h +++ b/sdk/libraries/core/action/ActionExtension.h @@ -60,7 +60,7 @@ class CAMITK_API ActionExtension : public QObject { protected : /// constructor - ActionExtension() {}; + ActionExtension(); public : /// destructor @@ -79,14 +79,10 @@ public : const ActionList& getActions(); /// set the file path (once loaded as a dynamic library) - void setLocation(const QString loc) { - dynamicLibraryFileName = loc; - } + void setLocation(const QString loc); /// get the file path (location of the .dll/.so/.dylib) of this plugin - QString getLocation() const { - return dynamicLibraryFileName; - } + QString getLocation() const; /// Load, for the selected langage (asked to the Application), the associated .qm file void initResources(); @@ -103,7 +99,7 @@ private: QString dynamicLibraryFileName; /// Provide internationalization support for text output. - QTranslator* translator{nullptr}; + QTranslator* translator; }; } diff --git a/sdk/libraries/core/application/Application.cpp b/sdk/libraries/core/application/Application.cpp index 1d8aa5cd..4c576075 100644 --- a/sdk/libraries/core/application/Application.cpp +++ b/sdk/libraries/core/application/Application.cpp @@ -29,6 +29,7 @@ #include "MainWindow.h" #include "ExtensionManager.h" #include "Action.h" +#include "Viewer.h" #include "HistoryComponent.h" #include "ImageComponent.h" #include "Property.h" @@ -66,6 +67,7 @@ int Application::argc = 0; char** Application::argv = nullptr; QTranslator* Application::translator = nullptr; PropertyObject* Application::propertyObject = nullptr; +Action* Application::currentAction = nullptr; // ----------------- constructor -------------------- Application::Application(QString name, int& theArgc, char** theArgv, bool autoloadExtensions, bool registerFileExtension) : QApplication(theArgc, theArgv) { @@ -209,6 +211,7 @@ void Application::quitting() { // delete all actions (they are instantiated when the extension is loaded) ExtensionManager::unloadAllActionExtensions(); + ExtensionManager::unloadAllViewerExtensions(); if (translator) { delete translator; //delete instance of internationalization support @@ -219,6 +222,7 @@ void Application::quitting() { bool Application::notify(QObject* receiver, QEvent* event) { bool done = true; std::exception_ptr otherException; + try { done = QApplication::notify(receiver, event); } @@ -228,6 +232,7 @@ bool Application::notify(QObject* receiver, QEvent* event) { catch (...) { CAMITK_ERROR(tr("Caught an unknown exception")) otherException = std::current_exception(); + try { if (otherException) { std::rethrow_exception(otherException); @@ -289,8 +294,11 @@ void Application::setMainWindow(MainWindow* mw) { // ----------------- getMainWindow -------------------- MainWindow* Application::getMainWindow() { - if (!mainWindow) { + if (mainWindow == nullptr) { + // this is the first time getMainWindow() is called and no MainWindow were created + // In this case, force the creation of a default MainWindow by sending nullptr dynamic_cast(qApp)->setMainWindow(nullptr); + // and then returns it } return mainWindow; @@ -509,6 +517,7 @@ Component* Application::open(const QString& fileName) { // try harder otherException = std::current_exception(); + try { if (otherException) { std::rethrow_exception(otherException); @@ -538,6 +547,7 @@ Component* Application::openDirectory(const QString& dirName, const QString& plu if (cp != nullptr) { std::exception_ptr otherException; + // Ask the plugin instance to create the Component instance try { comp = cp->open(QDir(dirName).absolutePath()); @@ -570,6 +580,7 @@ Component* Application::openDirectory(const QString& dirName, const QString& plu // try harder otherException = std::current_exception(); + try { if (otherException) { std::rethrow_exception(otherException); @@ -749,6 +760,13 @@ bool actionLessThan(const camitk::Action* a1, const camitk::Action* a2) { return a1->getName() < a2->getName(); } +// ---------------- viewerLessThan ---------------- +bool viewerLessThan(const camitk::Viewer* v1, const camitk::Viewer* v2) { + // This method is needed by qsort in the sort method to sort viewer by name + return v1->getName() < v2->getName(); +} + + // ---------------- sort ---------------- ActionList Application::sort(ActionSet actionSet) { // sort actions by name @@ -758,6 +776,15 @@ ActionList Application::sort(ActionSet actionSet) { return actionList; } +ViewerList Application::sort(ViewerSet viewerSet) { + // sort actions by name + ViewerList viewerList = viewerSet.toList(); + qSort(viewerList.begin(), viewerList.end(), viewerLessThan); + + return viewerList; +} + + // ---------------- getAction ---------------- Action* Application::getAction(QString name) { return getActionMap().value(name); @@ -824,6 +851,144 @@ ActionList Application::getActions(ComponentList selComp, QString tag) { } +// -------------------- getViewerMap -------------------- +QMap& Application::getViewerMap() { + static QMap viewerMap; + + return viewerMap; +} + +// -------------------- getViewer -------------------- +Viewer* Application::getViewer(QString name) { + return getViewerMap().value(name); +} + +// -------------------- registerAllViewers -------------------- +int Application::registerAllViewers(ViewerExtension* ext) { + int registered = 0; + + // register all the viewer instances in this extension + for (Viewer* viewer : ext->getViewers()) { + // first check if a viewer with the same name is not already registered + if (getViewerMap().contains(viewer->getName())) { + // if it is register, find out more information about the viewer extension + // that manages the already registered viewer + QString extensionName = ""; + ViewerExtension* extension = getViewerExtension(viewer); + + if (extension != nullptr) { + extensionName = extension->getName(); + CAMITK_ERROR_ALT(tr("Cannot register viewer: %1 (description: \"%2\")\n" + "viewer of same name already registered in extension %3") + .arg(viewer->getName(), viewer->getDescription(), extensionName)) + } + else { + // should never happen + CAMITK_ERROR_ALT(tr("Cannot register viewer: %1 (description: \"%2\")\n" + "viewer of same name already registered in an unknown extension...") + .arg(viewer->getName(), viewer->getDescription())) + } + } + else { + // everythis is alright register the viewer + getViewerMap().insert(viewer->getName(), viewer); + registered++; + } + } + + return registered; +} + +// -------------------- getViewers -------------------- +ViewerList Application::getViewers(Component* component) { + ViewerSet viewers; + + if (component) { + QStringList componentHierarchy = component->getHierarchy(); + + foreach (Viewer* currentViewer, Application::getViewers()) { + foreach (QString compType, currentViewer->getComponents()) { + if (componentHierarchy.contains(compType)) { + viewers.insert(currentViewer); + } + } + } + } + else { + foreach (Viewer* currentViewer, Application::getViewers()) { + foreach (QString compType, currentViewer->getComponents()) { + if (compType.isEmpty()) { + viewers.insert(currentViewer); + } + } + } + } + + return sort(viewers); +} + +// -------------------- getNewViewer -------------------- +Viewer* Application::getNewViewer(QString name, QString className) { + + int i = 0; + QList vl = ExtensionManager::getViewerExtensionsList(); + + while (i < vl.size() && vl.at(i)->getViewerClassName() != className) { + i++; + } + + if (i < vl.size()) { + ViewerExtension* ve = vl.at(i); + return ve->getNewInstance(name); + } + else { + CAMITK_ERROR_ALT(tr("No extension manage viewer manages the viewers of type \"%1\"\n").arg(className)) + return nullptr; + } +} + +// -------------------- getViewers -------------------- +const ViewerList Application::getViewers() { + return getViewerMap().values(); +} + +// -------------------- unregisterAllViewers -------------------- +int Application::unregisterAllViewers(ViewerExtension* ext) { + int unregistered = 0; + + foreach (Viewer* viewer, ext->getViewers()) { + getViewerMap().remove(viewer->getName()); + unregistered++; + } + + return unregistered; +} + +// -------------------- getViewerExtension -------------------- +ViewerExtension* Application::getViewerExtension(Viewer* viewer) { + + int i = 0; + bool found = false; + ViewerExtension* extension = nullptr; + + while (i < ExtensionManager::getViewerExtensionsList().size() && !found) { + int j = 0; + + while (j < ExtensionManager::getViewerExtensionsList().at(i)->getViewers().size() && !found) { + found = (ExtensionManager::getViewerExtensionsList().at(i)->getViewers().at(j)->getName() == viewer->getName()); + j++; + } + + i++; + } + + if (found) { + extension = ExtensionManager::getViewerExtensionsList().at(i - 1); + } + + return extension; +} + // ---------- isAlive ---------- bool Application::isAlive(Component* comp) { return getAllComponents().contains(comp); @@ -917,6 +1082,16 @@ void Application::clearSelectedComponents() { getSelectedComponentList().clear(); } +// -------------------- setSelectedAction -------------------- +void Application::setTriggeredAction(Action* action) { + currentAction = action; +} + +// -------------------- getSelectedAction -------------------- +Action* Application::getTriggeredAction() { + return currentAction; +} + // -------------------- getHistory -------------------- QStack& Application::getHistory() { // static singleton declaration @@ -1014,6 +1189,7 @@ void Application::saveHistoryAsSXML() { // action parameters QDomElement parametersElement = doc.createElement("camitk:parameters"); actionElement.appendChild(parametersElement); + if (!action->dynamicPropertyNames().isEmpty()) { foreach (QByteArray actionParameter, action->dynamicPropertyNames()) { @@ -1288,9 +1464,10 @@ void Application::createProperties() { property->setEnumTypeName("LogLevel"); // Set a custom list of GUI names QStringList enumGuiText; + for (const InterfaceLogger::LogLevel l : { - InterfaceLogger::NONE, InterfaceLogger::ERROR, InterfaceLogger::WARNING, InterfaceLogger::INFO, InterfaceLogger::TRACE -}) { + InterfaceLogger::NONE, InterfaceLogger::ERROR, InterfaceLogger::WARNING, InterfaceLogger::INFO, InterfaceLogger::TRACE + }) { enumGuiText << Log::getLevelAsString(l); } property->setAttribute("enumNames", enumGuiText); diff --git a/sdk/libraries/core/application/Application.h b/sdk/libraries/core/application/Application.h index f051c480..c98ae1ce 100644 --- a/sdk/libraries/core/application/Application.h +++ b/sdk/libraries/core/application/Application.h @@ -43,7 +43,9 @@ class vtkObject; namespace camitk { class MainWindow; class ActionExtension; +class ViewerExtension; class Action; +class Viewer; class HistoryItem; class ComponentExtension; class Property; @@ -225,7 +227,6 @@ public: * all the previously selected components and clear the list. */ static void clearSelectedComponents(); - ///@} /// @name Action instances management @@ -255,6 +256,36 @@ public: * @return the number of actions effectively unregistered */ static int unregisterAllActions(ActionExtension*); + + /// set the currently triggered action + /// This is used by Action::trigger(..) to refresh all the viewer (the viewers + /// interested by the fact an action was triggered can then update what they need to) + static void setTriggeredAction(Action* action); + + /// get the currently triggered action + static Action* getTriggeredAction(); + ///@} + + /// get a registered viewer given its name + static Viewer* getViewer(QString name); + + static Viewer* getNewViewer(QString name, QString className); + + /// get all the viewers registered in the application (note: the returned ViewerList is garanteed to be sorted by viewer name and to not contain any duplicate) + static const ViewerList getViewers(); + + /// get all the actions that can be applied on a given component (note: the returned ActionList is garanteed to be sorted by action name and to contain no duplicates) + static ViewerList getViewers(Component*); + + /** register all viewers from the given ViewerExtension + * @return the number of viewers effectively registered (in case a viewer's name is already registered by another viewer extension, it won't be registered a second time) + */ + static int registerAllViewers(ViewerExtension*); + + /** unregister all viewers from the given ViewerExtension + * @return the number of viewer effectively unregistered + */ + static int unregisterAllViewers(ViewerExtension*); ///@} /** @name Main Window management @@ -274,6 +305,9 @@ public: void setMainWindow(MainWindow* mw); /// get the main window + /// \note if there is no MainWindow when this method is first called, + /// then this method makes sure there is a MainWindow by and force the creation of + /// a default MainWindow (direct instance of the MainWindow class) static MainWindow* getMainWindow(); /// refresh the main window (this will call the refresh method of all viewers) @@ -371,6 +405,8 @@ private: /// argv given from command line static char** argv; + static Action* currentAction; + /// @name Recent document management ///@{ /// list of all the remembered recent documents (last opened is last inserted!) @@ -459,9 +495,11 @@ private: ///@name Actions pipeline history ///@{ - /// get the history of actions stored. - /// * This method follows the "construct on first use" idiom/design-pattern. - /** get the singleton stack of actions stored in a pipeline + /** get the history of actions stored. + * + * This methods returns the singleton stack of actions stored in a pipeline as + * their are applied during the execution of the application. + * * This is the private (intern) method. * This history is updated (push(), pop()) by addHistoryItem() and removeHistoryItem() * This method follows the "construct on first use" idiom/design-pattern. @@ -474,9 +512,12 @@ private: /// @name Actions management ///@{ - /** all the registered actions, this is a QMap as actions are mainly sort/compared/process by name (key). + /** As actions are mainly sort/compared/process by name, an internal QMap + * associates all the contains all the registered actions with their name (key) * This is the private (intern) method. - * The component extension map is updated by loadExtension, unloadExtension and autoloadExtensions. + * + * The action extension map is updated by loadExtension, unloadExtension and autoloadExtensions. + * * This method follows the "construct on first use" idiom/design-pattern. * It therefore avoids the infamous "static initialization order fiasco", * see http://www.parashift.com/c++-faq/ctors.html @@ -487,9 +528,29 @@ private: static ActionList sort(ActionSet); ///@} - /// Init the application resources by loading the language associated .qm file - static void initResources(); + /// sort an ViewerSet by viewer's name + static ViewerList sort(ViewerSet); + ///@} + /// @name viewer management + ///@{ + /** As viewers are mainly sort/compared/process by name, an internal QMap + * associates all the registered viewers with their name (key). + * This is the private (intern) method. + * + * This is the private (intern) method. + * + * The viewer extension map is updated by loadExtension, unloadExtension and autoloadExtensions. + * + * This method follows the "construct on first use" idiom/design-pattern. + * It therefore avoids the infamous "static initialization order fiasco", + * see http://www.parashift.com/c++-faq/ctors.html + */ + static QMap& getViewerMap(); + + static ViewerExtension* getViewerExtension(Viewer* viewer); + + ///@} /// @name Property management ///@{ @@ -510,6 +571,9 @@ private: static PropertyObject* propertyObject; ///@} + /// Init the application resources by loading the language associated .qml file + static void initResources(); + protected: /** * Event filter of this class instance to watch its properties instances. diff --git a/sdk/libraries/core/application/MainWindow.cpp b/sdk/libraries/core/application/MainWindow.cpp index fc0bf12b..8c7847f1 100644 --- a/sdk/libraries/core/application/MainWindow.cpp +++ b/sdk/libraries/core/application/MainWindow.cpp @@ -57,7 +57,6 @@ MainWindow::MainWindow(QString title) { setWindowIcon(QIcon(":/camiTKIcon")); // prepare GUI - centralViewer = nullptr; showStatusBar(false); // add permanent widget to the status bar (toggle console and progress bar) @@ -67,6 +66,7 @@ MainWindow::MainWindow(QString title) { // if actions are available, add a toggle console Action* toggleAction = Application::getAction("Toggle Log Console"); + if (toggleAction) { auto* toggleConsole = new QToolBar(); @@ -88,23 +88,29 @@ MainWindow::MainWindow(QString title) { Ui::ui_Console ui; ui.setupUi(consoleWindow); + switch (Log::getLogger()->getLogLevel()) { case InterfaceLogger::ERROR: ui.errorLogLevelButton->setChecked(true); break; + case InterfaceLogger::WARNING: ui.warningLogLevelButton->setChecked(true); break; + case InterfaceLogger::INFO: ui.infoLogLevelButton->setChecked(true); break; + case InterfaceLogger::TRACE: ui.traceLogLevelButton->setChecked(true); break; + default: ui.noneLogLevelButton->setChecked(true); break; } + ui.toggleDebug->setChecked(Log::getLogger()->getDebugInformation()); ui.toggleTimestamp->setChecked(Log::getLogger()->getTimeStampInformation()); @@ -155,6 +161,12 @@ MainWindow::MainWindow(QString title) { consoleWindow->hide(); addDockWidget(Qt::BottomDockWidgetArea, consoleWindow); + // create the default (empty) central widget inside which the central viewers can be added + centralWidget = new QStackedWidget(this); + centralWidget->setObjectName("MainWindow Central Widget"); + setCentralWidget(centralWidget); + centralViewer = nullptr; + // accept drag and drop events setAcceptDrops(true); @@ -164,11 +176,6 @@ MainWindow::MainWindow(QString title) { // ------------- destructor ----------------- MainWindow::~MainWindow() { - // delete all the viewers - while (!viewers.isEmpty()) { - delete viewers.takeFirst(); - } - delete consoleWindow; consoleWindow = nullptr; } @@ -221,8 +228,9 @@ void MainWindow::showViewer(Viewer* theViewer, bool visible) { void MainWindow::showViewerToolbar(Viewer* theViewer, bool visible) { if (theViewer == nullptr) return; - + QToolBar* viewerToolBar = theViewer->getToolBar(); + if (viewerToolBar != nullptr) { if (visible && theViewer->getToolBarVisibility()) { addToolBar(viewerToolBar); @@ -240,6 +248,7 @@ void MainWindow::refreshViewers() { foreach (Viewer* v, viewers) { v->refresh(); } + // update the central viewer toolbar visibility showViewerToolbar(centralViewer, true); } @@ -248,19 +257,18 @@ void MainWindow::refreshViewers() { void MainWindow::addDockViewer(Qt::DockWidgetArea dockingArea, Viewer* theViewer) { if (addViewer(theViewer)) { // create the dock widget and insert it only if the viewer has a widget - QWidget* viewerWidget = theViewer->getWidget(this); - if (viewerWidget) { - // add the widget - QDockWidget* viewerDock = new QDockWidget(theViewer->objectName(), this); - viewerDock->setObjectName(theViewer->objectName()); - viewerDock->setWidget(viewerWidget); + QDockWidget* viewerDock = theViewer->dockIn(); + + if (viewerDock) { + // add the dock addDockWidget(dockingArea, viewerDock); - + // update the map dockWidgetMap.insert(theViewer, viewerDock); } } + // show the viewer anyway showDockViewer(theViewer, true); } @@ -268,44 +276,48 @@ void MainWindow::addDockViewer(Qt::DockWidgetArea dockingArea, Viewer* theViewer // ------------- setCentralViewer ----------------- void MainWindow::setCentralViewer(Viewer* theViewer) { - // get the viewer widget (must have something to show as it is a viewer after all!) - QWidget* viewerWidget = theViewer->getWidget(this); - if (viewerWidget != nullptr) { - // add the viewer to the list (if not already in the list) - addViewer(theViewer); - - // if needed, create the default (empty) central widget inside which the central viewers can be added - if (centralWidget() == 0) { - setCentralWidget(new QStackedWidget(this)); - } - else { - // there is already a central viewer, just hide its toolbar - showViewerToolbar(centralViewer, false); - } - - // add the viewer's widget - qobject_cast(centralWidget())->addWidget(viewerWidget); - qobject_cast(centralWidget())->setCurrentWidget(viewerWidget); - centralViewer = theViewer; - - // show its toolbar - showViewerToolbar(centralViewer, true); + addViewer(theViewer); + + // unstack the previous widget + if (centralViewer != nullptr) { + // hide the previous toolbar + showViewerToolbar(centralViewer, false); + } + + // update the pointer + centralViewer = theViewer; + + // stack the viewer inside the central viewer + centralViewer->stackIn(centralWidget); + + // show its toolbar + showViewerToolbar(centralViewer, true); + + // save current central viewer in the settings (only if the central widget is visible + if (centralWidget->isVisible()) { + QSettings& settings = Application::getSettings(); + settings.beginGroup(Application::getName() + ".MainWindow"); + settings.setValue("centralViewer", centralViewer->getName()); + settings.endGroup(); } + } // ------------- getCentralViewer ----------------- -const Viewer& MainWindow::getCentralViewer() const { - return *centralViewer; +Viewer* MainWindow::getCentralViewer() const { + return centralViewer; } // ------------- refresh ----------------- void MainWindow::refresh() { Viewer* whoIsAsking = qobject_cast (sender()); + foreach (Viewer* v, viewers) { if (v != whoIsAsking) { v->refresh(); } } + // update the central viewer toolbar visibility showViewerToolbar(centralViewer, true); } @@ -359,6 +371,7 @@ void MainWindow::show() { // update the log console toggle state (if actions are available) Action* toggleAction = Application::getAction("Toggle Log Console"); + if (toggleAction) { toggleAction->getQAction()->setChecked(consoleWindow->isVisible()); } @@ -375,14 +388,25 @@ void MainWindow::initSettings() { settings.beginGroup(Application::getName() + ".MainWindow"); restoreState(settings.value("windowState").toByteArray()); QRect geom = settings.value("geometry", QRect(8, 30, 1024, 768)).toRect(); + // ensure ok size for non-compliant window managers if (geom.width() <= 0) { geom.setWidth(1024); } + if (geom.height() <= 0) { geom.setHeight(768); } + setGeometry(geom); + + // get central viewer + QString centralViewerName = settings.value("centralViewer", "").toString(); + // if no specific name is found, just do nothing will use the one alread set in the central viewer by default + if (centralViewerName != "") { + setCentralViewer(Application::getViewer(centralViewerName)); + } + settings.endGroup(); } diff --git a/sdk/libraries/core/application/MainWindow.h b/sdk/libraries/core/application/MainWindow.h index ae70e888..a58ae44c 100644 --- a/sdk/libraries/core/application/MainWindow.h +++ b/sdk/libraries/core/application/MainWindow.h @@ -38,7 +38,7 @@ #include #include #include - +#include namespace camitk { @@ -167,7 +167,7 @@ public: /** * @return the current central viewer. */ - virtual const Viewer& getCentralViewer() const; + virtual Viewer* getCentralViewer() const; /** Set the visibility of a viewer's toolbar. * This method respect the toolbar visibility property of the viewer. @@ -268,6 +268,9 @@ private: /// the main part of the title QString mainTitle; + /// the central widget is a QStackedWidget + QStackedWidget* centralWidget; + }; } diff --git a/sdk/libraries/core/component/Component.cpp b/sdk/libraries/core/component/Component.cpp index 44faba92..87d4b25f 100644 --- a/sdk/libraries/core/component/Component.cpp +++ b/sdk/libraries/core/component/Component.cpp @@ -54,6 +54,7 @@ Component::Component(Component* parentComponent, const QString& n, Representatio if (myParentNode == nullptr) { throw AbortException(tr("Inconsistency: cannot instantiate a sub component with a null parent, please use the parent component pointer as the first parameter of the constructor or use the top-level Component constructor.").toStdString()); } + init(); myFileName = n; // register as a parent child @@ -80,17 +81,20 @@ Component::~Component() { if (myGeometry) { delete myGeometry; } + myGeometry = nullptr; if (mySlice) { delete mySlice; } + mySlice = nullptr; // delete Frame if (myFrame) { delete myFrame; } + myFrame = nullptr; // remove from selection @@ -102,6 +106,7 @@ Component::~Component() { foreach (Property* prop, propertyMap.values()) { delete prop; } + propertyMap.clear(); CAMITK_TRACE(tr("Deleted")) @@ -151,12 +156,15 @@ bool Component::isInstanceOf(QString className) const { QStringList Component::getHierarchy() const { const QMetaObject* qmetaObject = metaObject(); QStringList classnameList; + while (qmetaObject && !QString(qmetaObject->className()).contains("InterfaceProperty")) { classnameList.append(QString(qmetaObject->className()).remove(0, QString(qmetaObject->className()).lastIndexOf(':') + 1)); + if (qmetaObject->superClass()) { qmetaObject = qmetaObject->superClass(); } } + return classnameList; } @@ -252,6 +260,7 @@ Component* Component::getTopLevelComponent() { // -------------------- setVisibility -------------------- void Component::setVisibility(Viewer* v, bool b) { QMap::iterator it = myViewers.find(v); + if (it == myViewers.end()) { // insert the new viewer with the corresponding boolean myViewers.insert(v, b); @@ -264,6 +273,7 @@ void Component::setVisibility(Viewer* v, bool b) { // -------------------- getVisibility -------------------- bool Component::getVisibility(Viewer* v) const { QMap::const_iterator it = myViewers.constFind(v); + if (it == myViewers.end()) { return false; } @@ -295,6 +305,7 @@ void Component::refreshInterfaceNode() { // -------------------- getService -------------------- Component::Representation Component::getRepresentation() const { static bool checked = false; // only check once for each Component + if (!checked) { checked = true; QString representationString; @@ -309,19 +320,23 @@ Component::Representation Component::getRepresentation() const { shouldInstantiateMember = "myGeometry"; instantiationError = (myGeometry == nullptr); break; + case SLICE: representationString = "SLICE"; shouldInstantiateMember = "mySlice"; instantiationError = (mySlice == nullptr); break; + case NO_REPRESENTATION: instantiatedMember = (myGeometry != nullptr) ? "myGeometry" : (mySlice != nullptr) ? "mySlice" : "<>"; instantiationError = (mySlice != nullptr || myGeometry != nullptr); break; } + if (instantiationError) { const QMetaObject* qmetaObject = metaObject(); QString classname = qmetaObject->className(); + if (myService != NO_REPRESENTATION) { // the Component has to instantiate CAMITK_ERROR(tr("Component class \"%1\" implements service %2 but does not instantiate it!\n" @@ -333,6 +348,7 @@ Component::Representation Component::getRepresentation() const { } } } + return myService; } @@ -348,12 +364,15 @@ QMenu* Component::getActionMenu() { //-- add all actions sorted by family ActionList allActions = Application::getActions(this); QMap familyMap; + foreach (Action* action, allActions) { ActionSet* familySet = familyMap.value(action->getFamily().toLower()); + if (!familySet) { familySet = new ActionSet; familyMap.insert(action->getFamily().toLower(), familySet); } + familySet->insert(action); } @@ -362,8 +381,10 @@ QMenu* Component::getActionMenu() { // sort actions by name ActionList familyList = familySet->toList(); qSort(familyList.begin(), familyList.end(), actionLessThan); + if (familyList.size() >= 1) { QMenu* familyMenu = actionsMenu->addMenu(familyList.first()->getFamily()); + foreach (Action* action, familyList) { familyMenu->addAction(action->getQAction()); } @@ -379,6 +400,7 @@ QMenu* Component::getActionMenu() { actionsMenu = nullptr; } } + return actionsMenu; } @@ -401,9 +423,11 @@ const InterfaceGeometry::RenderingModes Component::getRenderingModes() const { // else return the added rendering mode of all children if (childrenComponent.size() > 0) { InterfaceGeometry::RenderingModes m = InterfaceGeometry::None; + foreach (Component* childComponent, childrenComponent) { m |= childComponent->getRenderingModes(); } + return m; } } @@ -422,11 +446,13 @@ void Component::getActorColor(InterfaceGeometry::RenderingModes m, double d[4]) // return the firts existing Color in my children int i = 0; bool found = false; + while (i < childrenComponent.size() && !found) { childrenComponent[i]->getActorColor(m, d); found = (d[0] != 0.0 || d[1] != 0.0 || d[2] != 0.0 || d[3] != 0.0); i++; } + if (!found) { for (unsigned int j = 0; j < 4; j++) { d[j] = 0.0; @@ -441,17 +467,20 @@ void Component::getBounds(double* bounds) { else { bounds[0] = bounds[2] = bounds[4] = 0.0; bounds[1] = bounds[3] = bounds[5] = 1.0; + // compute bounds using the children's foreach (Component* childComponent, childrenComponent) { double childBounds[6]; //xmin,xmax, ymin,ymax, zmin,zmax // get child bounds childComponent->getBounds(childBounds); + // check compared to global bound for (int i = 0; i < 3; i++) { // compare min if (bounds[i * 2] > childBounds[i * 2]) { bounds[i * 2] = childBounds[i * 2]; } + // compare max if (bounds[i * 2 + 1] < childBounds[i * 2 + 1]) { bounds[i * 2 + 1] = childBounds[i * 2 + 1]; @@ -470,12 +499,15 @@ double Component::getBoundingRadius() { else { // compute bounding radius using the children's double radius = 0.0; + foreach (Component* childComponent, childrenComponent) { double childRadius = childComponent->getBoundingRadius(); + if (childRadius > radius) { radius = childRadius; } } + return radius; } } @@ -515,6 +547,7 @@ int Component::getSlice() const { // -------------------- attachChild -------------------- void Component::attachChild(InterfaceNode* childNode) { auto* comp = dynamic_cast(childNode); + if (comp != nullptr) { // add a sub item if (!childrenComponent.contains(comp)) { @@ -534,6 +567,7 @@ void Component::addChild(InterfaceNode* childNode) { // -------------------- setSelected -------------------- void Component::setSelected(const bool b, const bool recursive) { isSelectedFlag = b; + // maintain the children selection state as well if (recursive) { foreach (Component* child, childrenComponent) { @@ -573,6 +607,7 @@ void Component::deleteChildren() { delete childComp; } } + childrenComponent.clear(); } @@ -627,6 +662,7 @@ const QVector& Component::getChildrenFrame() const { CAMITK_ERROR(tr("myFrame is not instantiated.")) // error / undefined behaviour } + return myFrame->getChildrenFrame(); } @@ -636,6 +672,7 @@ const vtkSmartPointer Component::getTransformFromWorld() const { CAMITK_ERROR(tr("myFrame is not instantiated.")) return nullptr; } + return myFrame->getTransformFromWorld(); } @@ -645,6 +682,7 @@ const vtkSmartPointer Component::getTransform() const { CAMITK_ERROR(tr("myFrame is not instantiated.")) return nullptr; } + return myFrame->getTransform(); } @@ -654,6 +692,7 @@ const vtkSmartPointer Component::getTransformFromFrame(InterfaceFr CAMITK_ERROR(tr("myFrame is not instantiated.")) return nullptr; } + return myFrame->getTransformFromFrame(frame); } diff --git a/sdk/libraries/core/component/image/ImageComponent.cpp b/sdk/libraries/core/component/image/ImageComponent.cpp index 112bf64a..fd474828 100644 --- a/sdk/libraries/core/component/image/ImageComponent.cpp +++ b/sdk/libraries/core/component/image/ImageComponent.cpp @@ -24,6 +24,7 @@ ****************************************************************************/ // -- Core image component stuff +#include "Application.h" #include "ImageComponent.h" #include "ImageComponentExtension.h" #include "SingleImageComponent.h" @@ -31,8 +32,6 @@ #include "ImageOrientationHelper.h" // -- Core stuff -#include "InteractiveViewer.h" -#include "PropertyExplorer.h" #include "MeshComponent.h" #include "Property.h" #include "Frame.h" @@ -524,7 +523,7 @@ void ImageComponent::update3DViewer() { } if (volumeRenderingChild != nullptr) { - volumeRenderingChild->setVisibility(InteractiveViewer::get3DViewer(), viewIn3D); + volumeRenderingChild->setVisibility(Application::getViewer("3DViewer"), viewIn3D); } } diff --git a/sdk/libraries/core/component/image/SingleImageComponent.cpp b/sdk/libraries/core/component/image/SingleImageComponent.cpp index 90e1c963..d899b4f2 100644 --- a/sdk/libraries/core/component/image/SingleImageComponent.cpp +++ b/sdk/libraries/core/component/image/SingleImageComponent.cpp @@ -28,7 +28,6 @@ #include "ImageComponent.h" // -- Core stuff -#include "InteractiveViewer.h" #include "Frame.h" #include "Log.h" @@ -80,7 +79,7 @@ bool SingleImageComponent::getViewSliceIn3D() const { // -------------------- setViewSliceIn3D -------------------- void SingleImageComponent::setViewSliceIn3D(bool toggle) { this->viewSliceIn3D = toggle; - this->setVisibility(InteractiveViewer::get3DViewer(), viewSliceIn3D); + this->setVisibility(Application::getViewer("3DViewer"), viewSliceIn3D); } // -------------------- initRepresentation -------------------- @@ -94,16 +93,16 @@ void SingleImageComponent::initRepresentation() { switch (sliceOrientation) { case Slice::AXIAL: case Slice::AXIAL_NEURO: - setVisibility(InteractiveViewer::getAxialViewer(), true); + setVisibility(Application::getViewer("axialViewer"), true); break; case Slice::CORONAL: - setVisibility(InteractiveViewer::getCoronalViewer(), true); + setVisibility(Application::getViewer("coronalViewer"), true); break; case Slice::SAGITTAL: - setVisibility(InteractiveViewer::getSagittalViewer(), true); + setVisibility(Application::getViewer("sagittalViewer"), true); break; case Slice::ARBITRARY: - setVisibility(InteractiveViewer::getArbitraryViewer(), true); + setVisibility(Application::getViewer("arbitraryViewer"), true); break; } } diff --git a/sdk/libraries/core/component/mesh/MeshComponent.cpp b/sdk/libraries/core/component/mesh/MeshComponent.cpp index 9377deb0..ba956619 100644 --- a/sdk/libraries/core/component/mesh/MeshComponent.cpp +++ b/sdk/libraries/core/component/mesh/MeshComponent.cpp @@ -25,7 +25,6 @@ #include "MeshComponent.h" #include "Geometry.h" -#include "InteractiveViewer.h" #include "Property.h" #include "Application.h" #include "MeshDataModel.h" @@ -36,6 +35,7 @@ //-- Qt stuff #include #include +#include //-- vtk stuff #include @@ -229,7 +229,7 @@ void MeshComponent::initRepresentation(vtkSmartPointer originalPoin myGeometry->setMeshWorldTransform(getTransformFromWorld()); // add it in the InteractiveViewer (automatically) - setVisibility(InteractiveViewer::get3DViewer(), true); + setVisibility(Application::getViewer("3DViewer"), true); // initialize selection initSelection(); @@ -808,8 +808,8 @@ void MeshComponent::setDataRepresentationOff(int dataType) { pointDataSet->SetActiveScalars(nullptr); cellDataSet->SetActiveScalars(nullptr); // remove all color bar - InteractiveViewer::get3DViewer()->setColorScaleTitle(""); - InteractiveViewer::get3DViewer()->setColorScale(false); + //Application::getViewer("3DViewer")->setColorScaleTitle(""); + //Application::getViewer("3DViewer")->setColorScale(false); } if (dataType & VECTORS) { @@ -855,9 +855,9 @@ void MeshComponent::setScalarDataRepresentationOn(vtkSmartPointer setMapperScalarRange(range[0], range[1]); //-- show the color scale in 3D - InteractiveViewer::get3DViewer()->setColorScale(true); - InteractiveViewer::get3DViewer()->setColorScaleTitle(dataArray->GetName()); - InteractiveViewer::get3DViewer()->setColorScaleMinMax(range[0], range[1]); + /*Application::getViewer("3DViewer")->setColorScale(true); + Application::getViewer("3DViewer")->setColorScaleTitle(dataArray->GetName()); + Application::getViewer("3DViewer")->setColorScaleMinMax(range[0], range[1]);*/ } // -------------------- setDataRepresentationVisibility -------------------- diff --git a/sdk/libraries/core/component/mesh/MeshDataModel.cpp b/sdk/libraries/core/component/mesh/MeshDataModel.cpp index 261c0e69..e9dc330f 100644 --- a/sdk/libraries/core/component/mesh/MeshDataModel.cpp +++ b/sdk/libraries/core/component/mesh/MeshDataModel.cpp @@ -25,7 +25,6 @@ #include "MeshComponent.h" #include "MeshDataModel.h" -#include "InteractiveViewer.h" #include #include diff --git a/sdk/libraries/core/component/mesh/MeshDataModel.h b/sdk/libraries/core/component/mesh/MeshDataModel.h index 70cadacb..99bb85d8 100644 --- a/sdk/libraries/core/component/mesh/MeshDataModel.h +++ b/sdk/libraries/core/component/mesh/MeshDataModel.h @@ -42,7 +42,7 @@ namespace camitk { * * CamiTK intern class to represent mesh data. */ -class MeshDataModel : public QAbstractTableModel { +class CAMITK_API MeshDataModel : public QAbstractTableModel { Q_OBJECT @@ -105,7 +105,7 @@ private : * * For example: this is used in the InteractiveViewer to show a combobox of all the point and cell scalar data. */ -class MeshDataFilterModel : public QSortFilterProxyModel { +class CAMITK_API MeshDataFilterModel : public QSortFilterProxyModel { Q_OBJECT diff --git a/sdk/libraries/core/utils/CamiTKLogger.cpp b/sdk/libraries/core/utils/CamiTKLogger.cpp index 57f89a09..f20bd46b 100644 --- a/sdk/libraries/core/utils/CamiTKLogger.cpp +++ b/sdk/libraries/core/utils/CamiTKLogger.cpp @@ -32,6 +32,7 @@ #include "MainWindow.h" #include "ActionExtension.h" #include "ComponentExtension.h" +#include "ViewerExtension.h" #include "Log.h" #include @@ -346,6 +347,12 @@ QString CamiTKLogger::getCamiTKAPIInformation(const QObject* sender) { return QString("Component Extension \"") + camitkComponentExt->getName() + "\" - "; } + // sender is a ComponentExtension + auto* camitkViewerExt = dynamic_cast(nonConstSender); + if (camitkViewerExt != nullptr) { + return QString("Viewer Extension \"") + camitkViewerExt->getName() + "\" - "; + } + // sender is an application const auto* camitkApplication = dynamic_cast(sender); if (camitkApplication != nullptr) { diff --git a/sdk/libraries/core/viewer/InteractiveViewer.cpp b/sdk/libraries/core/viewer/InteractiveViewer.cpp index db5c825f..36d2ef4c 100644 --- a/sdk/libraries/core/viewer/InteractiveViewer.cpp +++ b/sdk/libraries/core/viewer/InteractiveViewer.cpp @@ -80,110 +80,29 @@ #include namespace camitk { -// ---------------------- singleton ---------------------------- -/// the register containing all the viewers (static instantiation, global variable, but global only for this file) -QMap InteractiveViewer::viewers; -QString InteractiveViewer::defaultNames[5] = {QString("3DViewer"), QString("axialViewer"), QString("coronalViewer"), QString("sagittalViewer"), QString("arbitraryViewer") }; -InteractiveViewer* InteractiveViewer::getNewViewer(QString name, ViewerType type) { - if (!viewers.contains(name)) { - //-- Congratulation, you got yourself a new InteractiveViewer! (but are you really sure you need it?) - viewers[name] = new InteractiveViewer(name, type); - } - - return viewers.value(name); -} - -InteractiveViewer* InteractiveViewer::getViewer(QString name) { - const std::string nameChar = name.toStdString(); - - if (viewers.contains(name)) { - return viewers.value(name); - } - else { - //-- if this is a default scene, get a new one if it does not exists - // perform the singleton instantiation here! - unsigned int i = 0; - // special case, the first viewer is a 3D viewer - - if (name == defaultNames[i]) { - return getNewViewer(defaultNames[i], GEOMETRY_VIEWER); - } - - InteractiveViewer* singletonInstance = nullptr; - - i++; - - while (i < 6 && !singletonInstance) { - if (name == defaultNames[i]) { - singletonInstance = getNewViewer(defaultNames[i], SLICE_VIEWER); - } - - i++; - } - - // default orientation for axial, sagittal and coronal is not the same - // See Image Reorientation Action Documentation... - if (name == defaultNames[1]) { // Axial Viewer - singletonInstance->getRendererWidget()->setCameraOrientation(RendererWidget::RIGHT_DOWN); - QString letters[4] = {QString("R"), QString("L"), QString("A"), QString("P") }; - singletonInstance->getRendererWidget()->setOrientationDecorationsLetters(letters); - singletonInstance->toggleOrientationDecorations(true); - singletonInstance->getRendererWidget()->getActiveCamera()->ParallelProjectionOn(); - } - else - if (name == defaultNames[2]) { // Coronal Viewer - singletonInstance->getRendererWidget()->setCameraOrientation(RendererWidget::LEFT_BACK); - QString letters[4] = {QString("R"), QString("L"), QString("S"), QString("I") }; - singletonInstance->getRendererWidget()->setOrientationDecorationsLetters(letters); - singletonInstance->toggleOrientationDecorations(true); - singletonInstance->getRendererWidget()->getActiveCamera()->ParallelProjectionOn(); - } - else - if (name == defaultNames[3]) { // Sagittal Viewer - singletonInstance->getRendererWidget()->setCameraOrientation(RendererWidget::BACK_DOWN); - QString letters[4] = {QString("A"), QString("P"), QString("S"), QString("I") }; - singletonInstance->getRendererWidget()->setOrientationDecorationsLetters(letters); - singletonInstance->toggleOrientationDecorations(true); - singletonInstance->getRendererWidget()->getActiveCamera()->ParallelProjectionOn(); - } - else - if (name == defaultNames[4]) { // Arbitrary Viewer - singletonInstance->getRendererWidget()->setCameraOrientation(RendererWidget::RIGHT_DOWN); - singletonInstance->toggleOrientationDecorations(false); - singletonInstance->getRendererWidget()->getActiveCamera()->ParallelProjectionOn(); - } - - - return singletonInstance; - } -} - -InteractiveViewer* InteractiveViewer::get3DViewer() { - return getViewer(defaultNames[0]); +// ---------------------- constructor ---------------------------- +InteractiveViewer::InteractiveViewer(QString& name, ViewerType type) : Viewer(name) { + myType = type; + init(); } -InteractiveViewer* InteractiveViewer::getAxialViewer() { - return getViewer(defaultNames[1]); -} +// ---------------------- destructor ---------------------------- +InteractiveViewer::~InteractiveViewer() { -InteractiveViewer* InteractiveViewer::getCoronalViewer() { - return getViewer(defaultNames[2]); -} + delete viewerMenu; + viewerMenu = nullptr; -InteractiveViewer* InteractiveViewer::getSagittalViewer() { - return getViewer(defaultNames[3]); -} + delete viewerToolbar; + viewerToolbar = nullptr; -InteractiveViewer* InteractiveViewer::getArbitraryViewer() { - return getViewer(defaultNames[4]); + if (frame != nullptr) + delete frame; + frame = nullptr; } -// ---------------------- constructor ---------------------------- -InteractiveViewer::InteractiveViewer(QString& name, ViewerType type) : Viewer(name) { - - myType = type; - +// ---------------------- init ---------------------------- +void InteractiveViewer::init() { // frame is NULL, but the rendererWidget and sliceSlider have to be instantiated // (even if the InteractiveViewer is not visible yet, it can still do some actions) frame = nullptr; @@ -234,20 +153,7 @@ InteractiveViewer::InteractiveViewer(QString& name, ViewerType type) : Viewer(na // init from settings initSettings(); -} - -// ---------------------- destructor ---------------------------- -InteractiveViewer::~InteractiveViewer() { - viewers.remove(this->getName()); - delete viewerMenu; - viewerMenu = nullptr; - - delete viewerToolbar; - viewerToolbar = nullptr; - - delete frame; - frame = nullptr; } // ---------------------- initSettings ---------------------------- @@ -257,6 +163,7 @@ void InteractiveViewer::initSettings() { // the background color QColor bg; + if (myType == GEOMETRY_VIEWER) { // default is white bg.setNamedColor(settings.value("backgroundColor", QColor::fromRgbF(1.0, 1.0, 1.0)).toString()); @@ -343,14 +250,14 @@ void InteractiveViewer::initSettings() { } // ---------------------- getWidget ---------------------------- -QWidget* InteractiveViewer::getWidget(QWidget* parent) { +QWidget* InteractiveViewer::getWidget() { if (!frame) { //-- create the actions initActions(); //-- build the frame - frame = new InteractiveViewerFrame(parent, this); + frame = new InteractiveViewerFrame(nullptr, this); frame->setFrameStyle(QFrame::StyledPanel | QFrame::Plain); //-- handle layout @@ -398,11 +305,6 @@ QWidget* InteractiveViewer::getWidget(QWidget* parent) { sideFrame->setMaximumWidth(60); horizontalSplitter->addWidget(sideFrame); - - if (getName() == defaultNames[4]) { // arbitrary viewer - // no side frame as their is no slice index per se in arbitrary slice - sideFrame->hide(); - } } else { sideFrame = nullptr; @@ -470,13 +372,6 @@ QWidget* InteractiveViewer::getWidget(QWidget* parent) { // add the text as whatsThis frame->setWhatsThis(whatsThis); } - else { - if (frame->parentWidget() != parent) { - bool isVisible = frame->isVisible(); - frame->setParent(parent); - frame->setVisible(isVisible); - } - } return frame; } @@ -513,6 +408,7 @@ void InteractiveViewer::refresh(Viewer* v) { if (v != this) { //-- check all present QList compRendered = actorMap.keys(); + foreach (Component* comp, compRendered) { if (!Application::isAlive(comp)) { // remove from the renderer and map @@ -526,6 +422,7 @@ void InteractiveViewer::refresh(Viewer* v) { switch (myType) { case GEOMETRY_VIEWER: + // check all Components foreach (Component* comp, allComponents) { // remove from the renderer and map @@ -539,6 +436,7 @@ void InteractiveViewer::refresh(Viewer* v) { //-- check the line as tube representation bool linesAsTubes = propertyObject->property(linesAsTubesProperty->getName().toStdString().c_str()).toBool(); + if (linesAsTubes) { comp->setLinesAsTubes(linesAsTubes); } @@ -562,6 +460,7 @@ void InteractiveViewer::refresh(Viewer* v) { } } } + if (comp->getFrameVisibility(this)) { addActor(comp, comp->getFrameAxisActor()); } @@ -573,6 +472,7 @@ void InteractiveViewer::refresh(Viewer* v) { case SLICE_VIEWER: // remove all from the renderer and map QList compRendered = actorMap.keys(); + foreach (Component* comp, compRendered) { removeAllActors(comp); } @@ -648,9 +548,11 @@ void InteractiveViewer::refresh(Viewer* v) { { rendererWidget->resetClippingPlanes(); } + // TODO add a boolean "Reset camera when picking" that can be set on or off // and saved as a setting } + rendererWidget->refresh(); } else { @@ -672,9 +574,11 @@ void InteractiveViewer::refreshRenderer() { // ---------------------- removeAllActors ---------------------------- void InteractiveViewer::removeAllActors(Component* comp) { QList > actorRendered = actorMap.values(comp); + foreach (vtkSmartPointer a, actorRendered) { rendererWidget->removeProp(a); } + // remove from the list actorMap.remove(comp); } @@ -699,6 +603,7 @@ QMenu* InteractiveViewer::getMenu() { options->addAction(backgroundColorAction); options->addAction(toggleCopyrightAction); options->addAction(toggleAxesAction); + if (myType == SLICE_VIEWER) { options->addAction(toggleOrientationDecorationsAction); options->addAction(toggleScreenshotAction); @@ -776,9 +681,11 @@ QToolBar* InteractiveViewer::getToolBar() { viewerToolbar->addAction(surfaceAction); viewerToolbar->addAction(wireframeAction); viewerToolbar->addAction(pointsAction); + if (colorAction) { viewerToolbar->addAction(colorAction); } + viewerToolbar->addAction(glyphAction); viewerToolbar->addAction(toggleLabelAction); @@ -791,6 +698,7 @@ QToolBar* InteractiveViewer::getToolBar() { viewerToolbar->addAction(scalarDataColorAction); } + /* if (myType == SLICE_VIEWER) { viewerToolBar->addAction(toggleOrientationDecorationsAction); } @@ -1086,6 +994,7 @@ void InteractiveViewer::keyPressEvent(QKeyEvent* e) { break; case Qt::Key_C: + // addWhatsThisItem("C", "Toggle color scale"); if (e->modifiers() == Qt::NoModifier) { @@ -1096,6 +1005,7 @@ void InteractiveViewer::keyPressEvent(QKeyEvent* e) { break; case Qt::Key_F: + // addWhatsThisItem("F", "Toggle backface culling"); if (e->modifiers() == Qt::NoModifier) { @@ -1105,6 +1015,7 @@ void InteractiveViewer::keyPressEvent(QKeyEvent* e) { break; case Qt::Key_I: + // addWhatsThisItem("I", "Toggle image interpolation on slices"); if (e->modifiers() == Qt::NoModifier) { @@ -1123,6 +1034,7 @@ void InteractiveViewer::keyPressEvent(QKeyEvent* e) { break; case Qt::Key_L: + // addWhatsThisItem("L", "Toggle view labels"); if (e->modifiers() == Qt::NoModifier && myType == GEOMETRY_VIEWER) { @@ -1140,6 +1052,7 @@ void InteractiveViewer::keyPressEvent(QKeyEvent* e) { break; case Qt::Key_P: + // addWhatsThisItem("Alt+P", "Toggle point rendering"); if (e->modifiers() == Qt::AltModifier) { @@ -1198,6 +1111,7 @@ void InteractiveViewer::keyPressEvent(QKeyEvent* e) { break; case Qt::Key_W: + // addWhatsThisItem("Alt+W", "Toggle wireframe rendering"); if (e->modifiers() == Qt::AltModifier) { @@ -1295,6 +1209,7 @@ void InteractiveViewer::keyPressEvent(QKeyEvent* e) { break; case Qt::Key_Plus: + // addWhatsThisItem("+", "Move slider a step above"); if (myType == SLICE_VIEWER) { @@ -1384,6 +1299,7 @@ void InteractiveViewer::keyPressEvent(QKeyEvent* e) { debugStream << endl; debugStream << "== Component vtkProp ==" << endl; + foreach (Component* c, actorMap.keys().toSet()) { debugStream << "- Component: \"" << c->getName() << "\" of type \"" << c->metaObject()->className() @@ -1391,9 +1307,11 @@ void InteractiveViewer::keyPressEvent(QKeyEvent* e) { std::list > allActors = actorMap.values(c).toStdList(); allActors.sort(); allActors.unique(); + foreach (vtkSmartPointer p, allActors) { // get more information by comparing with the getActor/getProp method of c bool found = false; + switch (myType) { case GEOMETRY_VIEWER: if (c->getActor(InterfaceGeometry::Surface) == p) { @@ -1410,7 +1328,9 @@ void InteractiveViewer::keyPressEvent(QKeyEvent* e) { found = true; debugStream << "\t- Points Actor" << endl; } + break; + case SLICE_VIEWER: if (c->getPixelActor() == p) { found = true; @@ -1428,16 +1348,20 @@ void InteractiveViewer::keyPressEvent(QKeyEvent* e) { } break; + default: // no other thing is possible break; } + // check additional prop if (!found) { unsigned int i = 0; + while (i < c->getNumberOfProp() && c->getProp(i) != p) { i++; } + if (i == c->getNumberOfProp()) { debugStream << "\t- Unknown Prop" << endl; } @@ -1448,6 +1372,7 @@ void InteractiveViewer::keyPressEvent(QKeyEvent* e) { } } + debugStream << "=== (end of debug information) ===" << endl; CAMITK_INFO(tr("InteractiveViewer Debug Information: ").arg(debugString)) } @@ -1740,6 +1665,7 @@ void InteractiveViewer::initPicking(PickingMode pickingMode) { rendererWidget->setPicker(picker); break; } + case POINT_PICKING: { vtkSmartPointer< vtkPointPicker > picker = vtkSmartPointer< vtkPointPicker >::New(); picker->SetTolerance(0.01); @@ -1747,6 +1673,7 @@ void InteractiveViewer::initPicking(PickingMode pickingMode) { this->rendererWidget->setAreaPicking(false); break; } + case CELL_PICKING: { vtkSmartPointer< vtkCellPicker > picker = vtkSmartPointer< vtkCellPicker >::New(); picker->SetTolerance(0.0001); @@ -1754,18 +1681,21 @@ void InteractiveViewer::initPicking(PickingMode pickingMode) { this->rendererWidget->setAreaPicking(false); break; } + case AREA_CELL_PICKING: { vtkSmartPointer< vtkRenderedAreaPicker > picker = vtkSmartPointer< vtkRenderedAreaPicker >::New(); this->rendererWidget->setPicker(picker); this->rendererWidget->setAreaPicking(true); break; } + case AREA_POINT_PICKING: { vtkSmartPointer< vtkRenderedAreaPicker > picker = vtkSmartPointer< vtkRenderedAreaPicker >::New(); this->rendererWidget->setPicker(picker); this->rendererWidget->setAreaPicking(true); break; } + default: case NO_PICKING: rendererWidget->setPicker(nullptr); @@ -1878,6 +1808,7 @@ void InteractiveViewer::updateActions() { toggleLabelAction->setChecked(Application::getSelectedComponents().first()->getProp("label")->GetVisibility()); auto* mesh = dynamic_cast< MeshComponent* >(first); + if (mesh) { // active scalar data colors and populate combobox with scalar data from the component scalarDataColorAction->setEnabled(true); @@ -2113,6 +2044,7 @@ void InteractiveViewer::setBackfaceCulling(bool b) { // -------------- setScreenshotAction -------------- void InteractiveViewer::setScreenshotAction(bool b) { propertyObject->setProperty(screenshotActionProperty->getName().toStdString().c_str(), b); + if (screenshotActionMenu) { screenshotActionMenu->setVisible(b); } @@ -2156,6 +2088,7 @@ void InteractiveViewer::picked() { } vtkSmartPointer itemPicker; + if (!pickingEffectUpdated && (itemPicker = vtkPicker::SafeDownCast(picker))) { pickingEffectUpdated = true; // decide of the state: if one of the possible picked is selected, then try unselect @@ -2201,10 +2134,13 @@ void InteractiveViewer::picked() { } } break; + case POINT_PICKING: { vtkSmartPointer pointPicker = vtkPointPicker::SafeDownCast(picker); + if (pointPicker) { vtkIdType currentId = pointPicker->GetPointId(); + if (currentId != -1) { vtkSmartPointer ids = vtkSmartPointer::New(); ids->InsertNextValue(currentId); @@ -2219,20 +2155,25 @@ void InteractiveViewer::picked() { // pointPicked can have changed something auto* mesh = dynamic_cast(comp); + if (mesh) { mesh->addToSelectedSelection(vtkSelectionNode::POINT, vtkSelectionNode::INDICES, ids); } + refresh(this); emit selectionChanged(); } } } break; + case CELL_PICKING : { vtkSmartPointer cellPicker = vtkCellPicker::SafeDownCast(this->rendererWidget->GetInteractor()->GetPicker()); auto* mesh = dynamic_cast(comp); + if (cellPicker && mesh) { vtkIdType currentId = cellPicker->GetCellId(); + if (currentId != -1) { vtkSmartPointer ids = vtkSmartPointer::New(); ids->InsertNextValue(currentId); @@ -2249,9 +2190,11 @@ void InteractiveViewer::picked() { } } break; + case AREA_CELL_PICKING : { vtkSmartPointer areaPicker = vtkRenderedAreaPicker::SafeDownCast(this->rendererWidget->GetInteractor()->GetPicker()); auto* mesh = dynamic_cast(comp); + if (areaPicker && mesh) { vtkSmartPointer extractor = vtkSmartPointer::New(); extractor->SetInputData(mesh->getPointSet()); @@ -2259,6 +2202,7 @@ void InteractiveViewer::picked() { extractor->SetFrustum(areaPicker->GetFrustum()); extractor->Update(); vtkDataSet* dataSet = vtkDataSet::SafeDownCast(extractor->GetOutput()); + if (dataSet) { Application::showStatusBarMessage("Picked : " + comp->getName() + " (" + QString::number(dataSet->GetCellData()->GetArray(0)->GetNumberOfTuples()) + " cells )"); mesh->addToSelectedSelection(vtkSelectionNode::CELL, vtkSelectionNode::INDICES, dataSet->GetCellData()->GetArray(0)); @@ -2268,9 +2212,11 @@ void InteractiveViewer::picked() { } } break; + case AREA_POINT_PICKING : { vtkSmartPointer areaPicker = vtkRenderedAreaPicker::SafeDownCast(this->rendererWidget->GetInteractor()->GetPicker()); auto* mesh = dynamic_cast(comp); + if (areaPicker && mesh) { vtkSmartPointer extractor = vtkSmartPointer::New(); extractor->SetInputData(mesh->getPointSet()); @@ -2279,6 +2225,7 @@ void InteractiveViewer::picked() { extractor->SetFieldType(vtkSelection::POINT); extractor->Update(); vtkDataSet* dataSet = vtkDataSet::SafeDownCast(extractor->GetOutput()); + if (dataSet) { Application::showStatusBarMessage("Picked : " + comp->getName() + " (" + QString::number(dataSet->GetPointData()->GetArray(0)->GetNumberOfTuples()) + " points )"); mesh->addToSelectedSelection(vtkSelectionNode::POINT, vtkSelectionNode::INDICES, dataSet->GetPointData()->GetArray(0)); @@ -2288,10 +2235,12 @@ void InteractiveViewer::picked() { } } break; + case NO_PICKING : default : break; } + isPicking = false; comp = nullptr; } @@ -2431,8 +2380,3 @@ void InteractiveViewerFrame::keyPressEvent(QKeyEvent* e) { #include "moc_InteractiveViewer.cpp" } - - - - - diff --git a/sdk/libraries/core/viewer/InteractiveViewer.h b/sdk/libraries/core/viewer/InteractiveViewer.h index c13ff617..31ba7bca 100644 --- a/sdk/libraries/core/viewer/InteractiveViewer.h +++ b/sdk/libraries/core/viewer/InteractiveViewer.h @@ -169,37 +169,15 @@ public: SELECTION_ONLY ///< the selected Components are in default mode, the non-selected are hidden }; - /** @name General/Singleton - * There is no public constructor for this class, but 5 default instances. - */ /// @{ - /** Use this method to create a new custom instance of this class. - * Of course you can create as many InteractiveViewer instance as you like, but if you try to create - * a InteractiveViewer with a name that match one of the default InteractiveViewer name, getNewViewer(..) automatically - * will return the corresponding default InteractiveViewer instance. - */ - static InteractiveViewer* getNewViewer(QString, ViewerType type); - - /// get a viewer by its name (return NULL if no instance has the given name, use getNewViewer to create one viewer) - static InteractiveViewer* getViewer(QString); - - /// get the 3D viewer default InteractiveViewer (provided for convenience, equivalent to getViewer("3DViewer") - static InteractiveViewer* get3DViewer(); - - /// get the axial default InteractiveViewer (provided for convenience, equivalent to getViewer("axialViewer") - static InteractiveViewer* getAxialViewer(); - - /// get the coronal default InteractiveViewer (provided for convenience, equivalent to getViewer("coronalViewer") - static InteractiveViewer* getCoronalViewer(); - - /// get the sagittal default InteractiveViewer (provided for convenience, equivalent to getViewer("sagittalViewer") - static InteractiveViewer* getSagittalViewer(); - - /// get the arbitrary default InteractiveViewer (provided for convenience, equivalent to getViewer("arbitraryViewer") - static InteractiveViewer* getArbitraryViewer(); - + /** Construtor. + * @param name the name of the viewer is mandatory, it is used as an identifier (e.g. in MedicalImageViewer) + * @param type type of the InteractiveViewer, depending on which it will behave as slice viewer, i.e. with no rotation interactions are possible, or 3D viewer + */ + Q_INVOKABLE InteractiveViewer(QString& name, ViewerType type); + /** Destructor */ - ~InteractiveViewer() override; + virtual ~InteractiveViewer() override; /// get the scene name QString getName() const; @@ -215,7 +193,7 @@ public: void refresh(Viewer* whoIsAsking = nullptr) override; /// get the InteractiveViewer widget (QTreeWidget). @param parent the parent widget for the viewer widget - QWidget* getWidget(QWidget* parent) override; + QWidget* getWidget() override; /// get the InteractiveViewer propertyObject (only non-null for GEOMETRY_VIEWER) QObject* getPropertyObject() override; @@ -260,21 +238,16 @@ public: /// set background color virtual void setBackgroundColor(QColor); +public slots: /** @name Viewing/Interaction Property */ ///@{ -public slots: /// set the backface culling mode (default is true). void setBackfaceCulling(bool); /// visibility of the screenshot in slice viewers void setScreenshotAction(bool); -public: - /// get the backface current culling mode. - // bool getBackfaceCulling() const; - -public slots: /** Update the visualization of lines (for all the InterfaceGeometry of the scene). * * \note it is only possible to transform lines to tubes if @@ -296,11 +269,9 @@ public: return rendererWidget; } - ///@} - /** @name Misc - */ + /// @name Misc /// @{ /// set the color scale in the viewport, use setColorScaleMinMax / setColorScaleTitle to change the displayed values. void setColorScale(bool); @@ -335,6 +306,8 @@ public: public slots: + /// @name public slots + /// @{ /** Slot called when the InteractiveViewer slider has been changed. If there is a InterfaceBitMap in the scene, * set the slice index with the new slider value. */ void sliderChanged(int); @@ -350,26 +323,13 @@ public slots: /// show/hide the copyright in 3D void toggleCopyright(bool); - -protected: - /** @name General/Singleton - */ - /// @{ - /** Construtor. - * @param name the name of the scene is mandatory, it is used as an identifier (e.g. in MedicalImageViewer) - * @param type type of the InteractiveViewer, depending on which it will behave as slice viewer, i.e. with no rotation interactions are possible, or 3D viewer - */ - InteractiveViewer(QString& name, ViewerType type); - - /// the map containing all the InteractiveViewer instances - static QMap viewers; - - /// the QString array containing all InteractiveViewer instance default names - static QString defaultNames[5]; - /// @} +protected: + /// used by both constructors + void init(); + /** @name Display properties * * Properties that can be managed without the knowledge/intervention of the InterfaceGeometry: @@ -413,8 +373,7 @@ protected: QMap cameraMap; ///@} - /** @name Widget/Action management - */ + /// @name Widget/Action management /// @{ /// The 3D scene itself, wrapping VTK render window, renderer and interactor in a single Qt widget RendererWidget* rendererWidget; diff --git a/sdk/libraries/core/viewer/RendererWidget.cpp b/sdk/libraries/core/viewer/RendererWidget.cpp index 985c5827..5dd6da46 100644 --- a/sdk/libraries/core/viewer/RendererWidget.cpp +++ b/sdk/libraries/core/viewer/RendererWidget.cpp @@ -1475,4 +1475,4 @@ void RendererWidget::setPicker(vtkSmartPointer woodyWood) } -} +} \ No newline at end of file diff --git a/sdk/libraries/core/viewer/RendererWidget.h b/sdk/libraries/core/viewer/RendererWidget.h index 7e9a0908..6a394bcb 100644 --- a/sdk/libraries/core/viewer/RendererWidget.h +++ b/sdk/libraries/core/viewer/RendererWidget.h @@ -73,7 +73,6 @@ class vtkScalarBarWidget; class vtkTextMapper; class vtkAbstractPropPicker; - namespace camitk { class vtkInteractorStylePick; @@ -100,10 +99,10 @@ class vtkInteractorStylePick; class CAMITK_API RendererWidget : public QVTKWidget2 { #elif VTK_MAJOR_VERSION == 7 -class CAMITK_API RendererWidget : public QVTKWidget { +class INTERACTIVEVIEWER_API RendererWidget : public QVTKWidget { #elif VTK_MAJOR_VERSION == 8 -class CAMITK_API RendererWidget : public QVTKOpenGLWidget { +class INTERACTIVEVIEWER_API RendererWidget : public QVTKOpenGLWidget { #else #error "Invalid VTK version: not (yet) supported." @@ -480,7 +479,7 @@ protected : bool pickingDiverter; /// picking interactor - vtkSmartPointer pickInteractorStyle; + vtkSmartPointer pickInteractorStyle; ///@} diff --git a/sdk/libraries/core/viewer/Viewer.cpp b/sdk/libraries/core/viewer/Viewer.cpp index 6f8714df..c4fae204 100644 --- a/sdk/libraries/core/viewer/Viewer.cpp +++ b/sdk/libraries/core/viewer/Viewer.cpp @@ -26,13 +26,54 @@ #include "Viewer.h" #include "Component.h" #include "Application.h" +#include "MainWindow.h" + +#include "Log.h" + +#include +#include +#include namespace camitk { //---------------------- constructor ------------------------ Viewer::Viewer(QString name): QObject() { + this->name = name; setObjectName(name); + + layout = STACKED; + dockedWidget = nullptr; + stackedWidget = nullptr; + embeddedLayout = nullptr; + toolbarVisibility = true; + + components << "Component"; +} + +//---------------------- destructor ------------------------ +Viewer::~Viewer() { + delete dockedWidget; +} + +// -------------------- setIcon -------------------- +void Viewer::setIcon(QPixmap icon) { + this->icon = icon; +} + +// -------------------- getIcon -------------------- +QPixmap Viewer::getIcon() { + return icon; +} + +// -------------------- setComponents -------------------- +void Viewer::setComponents(QStringList components) { + this->components = components; +} + +// -------------------- getComponents -------------------- +QStringList Viewer::getComponents() { + return components; } //---------------------- selectionChanged ------------------------ @@ -40,6 +81,7 @@ void Viewer::selectionChanged(camitk::ComponentList& compSet) { foreach (Component* comp, compSet) { comp->setSelected(true); } + emit selectionChanged(); } @@ -65,4 +107,75 @@ bool Viewer::getToolBarVisibility() { return toolbarVisibility; } +// -------------------- getLayout -------------------- +Viewer::ViewerLayout Viewer::getLayout() { + return layout; +} + +// -------------------- setLayout -------------------- +void Viewer::setLayout(Viewer::ViewerLayout layout) { + this->layout = layout; +} + +// -------------------- dockIn -------------------- +QDockWidget* Viewer::dockIn() { + if (layout != DOCKED) { + CAMITK_ERROR(tr("Cannot dock \"%1\": it does not have a DOCKED layout").arg(name)) + return nullptr; + } + + // create the dock widget and insert it only if the viewer has a widget + if (getWidget() != nullptr && dockedWidget == nullptr) { + // create the dock + dockedWidget = new QDockWidget(name); + dockedWidget->setObjectName(name); + // add the widget + dockedWidget->setWidget(getWidget()); + } + + return dockedWidget; +} + +// -------------------- stackIn -------------------- +void Viewer::stackIn(QStackedWidget* stackedWidget) { + if (layout != STACKED) { + CAMITK_ERROR(tr("Cannot stack \"%1\": it does not have a STACKED layout").arg(name)) + return; + } + + // check all conditions are met + if (getWidget() != nullptr && this->stackedWidget == nullptr) { + // add the viewer's widget inside the stack + stackedWidget->addWidget(getWidget()); + // keep the pointer + this->stackedWidget = stackedWidget; + } + + // refresh the widget + if (this->stackedWidget != nullptr) { + this->stackedWidget->setCurrentWidget(getWidget()); + } +} + +// -------------------- embedIn -------------------- +void Viewer::embedIn(QLayout* embeddedLayout) { + if (layout != EMBEDDED) { + CAMITK_ERROR(tr("Cannot embed \"%1\": it does not have a EMBEDDED layout").arg(name)) + return; + } + + // check all conditions are met + if (getWidget() != nullptr && this->embeddedLayout == nullptr) { + embeddedLayout->addWidget(getWidget()); + //getWidget()->setParent(embeddedLayout->parentWidget()); + // keep the pointer + this->embeddedLayout = embeddedLayout; + } +} + +// -------------------- setVisible -------------------- +void Viewer::setVisible(bool visible) { + getWidget()->setVisible(visible); +} + } diff --git a/sdk/libraries/core/viewer/Viewer.h b/sdk/libraries/core/viewer/Viewer.h index d32c10f7..5eeb70a4 100644 --- a/sdk/libraries/core/viewer/Viewer.h +++ b/sdk/libraries/core/viewer/Viewer.h @@ -31,13 +31,21 @@ // -- QT stuff #include +#include // -- QT stuff classes class QToolBar; class QMenu; +class QPixMap; +class QWidget; +class QDockWidget; +class QStackedWidget; +class QLayout; namespace camitk { class Component; +class ViewerExtension; +class Property; /** * @ingroup group_sdk_libraries_core_viewer @@ -49,7 +57,12 @@ class Component; * A viewer can be added to MainWindow, MainWindow will include its menu in the "View" menu and its toolbar in * the application toolbar. * - * Use QObject method getObjectName to get the viewer's name. + * The default viewed component are set so that the viewer is updated every time the current component selection + * is modified. + * If your viewer does not view components (for instance, in the very rare/special case it views actions) + * then you need to call the setComponents(...) method with an empty list. + * An empty list means that this viewer is going to be notified/refreshed for every changes in the + * current action selection as well (i.e., anytime an action is triggered) */ class CAMITK_API Viewer : public QObject { @@ -60,7 +73,40 @@ public: Viewer(QString name); /// default destructor - ~Viewer() override = default; + virtual ~Viewer() override; + + /// \enum ViewerLayout describes where this viewer should appear + enum ViewerLayout { + DOCKED, ///< this viewer is meant to be docked, use dockIn() to get the dock widget + STACKED, ///< this viewer is meant to be inside a stacked widget (for instance the central viewer), use stackIn() to set the stacked widget it is in + EMBEDDED, ///< this viewer is meant to be embedded inside a layout (of another viewer or widget), use embedIn(..) to set the layout it is embedded in + }; + + /// get the name of the viewer + QString getName() const { + return name; + }; + + /// get the name of the viewer + QString getDescription() const { + return description; + }; + + /// set the viewer layout + void setLayout(ViewerLayout); + + /// get the viewer layout + ViewerLayout getLayout(); + + /// Create the dock widget and dock the viewer widget in it (return nullptr if this viewer has not a DOCKED layout) + QDockWidget* dockIn(); + + /// show the viewer's widget in the stack + /// If it is the first call, add the viewer widget in the given stack (once done, it cannot change stack) + void stackIn(QStackedWidget*); + + /// Add the viewer widget in the given layout (once done, the layout cannot be changed) + void embedIn(QLayout*); /// returns the number of Component that are displayed by this viewer virtual unsigned int numberOfViewedComponent() = 0; @@ -68,9 +114,6 @@ public: /// refresh the view (can be interesting to know which other viewer is calling this) virtual void refresh(Viewer* whoIsAsking = nullptr) = 0; - /// get the viewer widget. @param parent the parent widget for the viewer widget - virtual QWidget* getWidget(QWidget* parent = nullptr) = 0; - /// get the viewer property object (returns NULL by default, i.e. there are no property to edit) virtual QObject* getPropertyObject() { return nullptr; @@ -86,17 +129,27 @@ public: return nullptr; }; + /// set the visibility of the viewer (show or hide its widget) + void setVisible(bool); + /** set the visibility of the toolbar in the main window (true by default). - * If the visibility is set to false, the next call to setCentralViewer(..) or addDockViwer(...) will remove it + * If the visibility is set to false, the next call to setCentralViewer(..) or addDockViwer(...) will remove it */ void setToolBarVisibility(bool); - + /// get the current value of the toolbar visibility bool getToolBarVisibility(); - + + /// get the viewer icon + virtual QPixmap getIcon(); + /// Update the whole tree of the representation of the Component. /// Is actually useful (and defined) in Explorer. - virtual void refreshInterfaceNode(Component* comp) {}; + virtual void refreshInterfaceNode(Component*) {}; + + /// get the list of Component class manages by this viewer + /// (default is set to "Component", i.e. all type of Component) + QStringList getComponents(); signals: @@ -104,6 +157,11 @@ signals: void selectionChanged(); protected: + /// get the viewer widget. + /// this method is protected and to be redefined in the inheriting class. + /// \note to show the viewer's widget in the GUI, use dockIn(), stackIn(..) or embedIn(...) + /// to set where the viewer is displayed + virtual QWidget* getWidget() = 0; /** The selection has changed to the given ComponentList. * This method updates the Component::selection and emit the modified signal. @@ -117,9 +175,41 @@ protected: /// clear the selection void clearSelection(); + /// set the default icon for the viewer extension + void setIcon(QPixmap icon); + + /// set the list of component class names managed by this viewer + /// \note Default is set to "Component" (all type of components) + void setComponents(QStringList); + private: + /// current viewer's name + QString name; + + /// description of the viewer + QString description; + /// the current toolbar visibility bool toolbarVisibility; + + /// the Viewer pixmap icon + QPixmap icon; + + /// list of Component class name managed by this viewer + QStringList components; + + /// this viewer's layout + ViewerLayout layout; + + /// if layout is DOCKED, then this is the dock widget + QDockWidget* dockedWidget; + + /// if layout is embedded, then this is the QLayout it is embedded in + QLayout* embeddedLayout; + + /// the QAction that will allow it to be set as the central viewer + QStackedWidget* stackedWidget; + }; } diff --git a/sdk/libraries/core/viewer/ViewerExtension.cpp b/sdk/libraries/core/viewer/ViewerExtension.cpp new file mode 100644 index 00000000..f1b11da2 --- /dev/null +++ b/sdk/libraries/core/viewer/ViewerExtension.cpp @@ -0,0 +1,187 @@ +/***************************************************************************** +* $CAMITK_LICENCE_BEGIN$ +* +* CamiTK - Computer Assisted Medical Intervention ToolKit +* (c) 2001-2018 Univ. Grenoble Alpes, CNRS, TIMC-IMAG UMR 5525 (GMCAO) +* +* Visit http://camitk.imag.fr for more information +* +* This file is part of CamiTK. +* +* CamiTK is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License version 3 +* only, as published by the Free Software Foundation. +* +* CamiTK is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Lesser General Public License version 3 for more details. +* +* You should have received a copy of the GNU Lesser General Public License +* version 3 along with CamiTK. If not, see . +* +* $CAMITK_LICENCE_END$ +****************************************************************************/ + +#include "ViewerExtension.h" +#include "Viewer.h" +#include "Application.h" +#include "Core.h" +#include "Log.h" + +#include +#include +#include + +namespace camitk { + +// -------------------- constructor -------------------- +ViewerExtension::ViewerExtension() { + managedMetaObject = nullptr; + translator = nullptr; +} + +// -------------------- destructor -------------------- +ViewerExtension::~ViewerExtension() { + while (!viewers.empty()) { + Viewer* toDelete = viewers.takeFirst(); + delete toDelete; + } + + // delete internationalization instance + if (translator) { + delete translator; + } +} + +// -------------------- initResources -------------------- +void ViewerExtension::initResources() { + // Get the selected language + QString selectedLanguage = Application::getSelectedLanguage(); + + // if a language is defined, then try to load the translation file + if (!selectedLanguage.isEmpty()) { + QString viewerExtensionDirName = QDir(this->getLocation()).dirName(); + // remove any occurence of "-debug.dll" or ".so" or ".dylib" on the extension file name + viewerExtensionDirName.remove("-debug.dll").remove(".so").remove(".dylib"); + QString languageFile = ":/translate_" + viewerExtensionDirName + "/translate/translate_" + selectedLanguage + ".qm"; + translator = new QTranslator(); + + if (translator->load(languageFile)) { + QCoreApplication::installTranslator(translator); + } + else { + CAMITK_INFO(tr("Cannot load resource file: %1").arg(languageFile)) + } + } +} + +// -------------------- setLocation -------------------- +void ViewerExtension::setLocation(const QString loc) { + dynamicLibraryFileName = loc; +} + +// -------------------- getLocation -------------------- +QString ViewerExtension::getLocation() const { + return dynamicLibraryFileName; +} + +// -------------------- getViewerClassName -------------------- +QString ViewerExtension::getViewerClassName() { + if (managedMetaObject == nullptr) { + return ""; + } + else { + return managedMetaObject->className(); + } +} + +// -------------------- setManagedMetaObject -------------------- +void ViewerExtension::setManagedMetaObject(const QMetaObject* metaObject) { + // first call, set the viewer class meta object + if (managedMetaObject == nullptr) { + managedMetaObject = metaObject; + } +} + +// -------------------- registerViewer -------------------- +bool ViewerExtension::registerViewer(Viewer* viewer) { + // only one type of viewer is managed by a viewer extension + if (getViewerClassName() != viewer->metaObject()->className()) { + CAMITK_ERROR(tr("Cannot register viewer \"%1\" as it is an instance of \"%2\" (extension \"%3\" only manages the \"%4\" viewer class)").arg(viewer->getName()).arg(viewer->metaObject()->className()).arg(getName()).arg(getViewerClassName())) + return false; + } + + // simply add the viewer in the list + viewers.append(viewer); + + // all OK + return true; +} + +// -------------------- getNewInstance -------------------- +Viewer* ViewerExtension::getNewInstance(QString name) { + // check if a viewer of the same name exists + int i = 0; + + while (i < viewers.size() && viewers.at(i)->getName() != name) { + i++; + } + + if (i != viewers.size()) { + CAMITK_INFO(tr("No new instance created, returning already instanciated and registered \"%1\" viewer.\nViewer instance names should be unique.\n").arg(name)) + return viewers.at(i); + } + + // if the viewer does not already exist, instanciate it + QObject *instance = managedMetaObject->newInstance(Q_ARG(QString, name)); // add constructor arguments as needed + Viewer* viewerInstance = qobject_cast(instance); + + if (viewerInstance != nullptr) { + // register it in the list + registerViewer(viewerInstance); + } + else { + CAMITK_ERROR(tr("Cannot instanciate %1 from static meta object").arg(getViewerClassName())); + } +/*CLEANUP + int typeId = QMetaType::type(viewerClassName.toStdString().c_str()); + + if (typeId != QMetaType::UnknownType) { + // get the pointer to the viewer's class meta object + const QMetaObject* metaObject = QMetaType::metaObjectForType(typeId); + + if (metaObject == nullptr) { + // If not working try the meta type create method + void* instance = QMetaType::create(typeId); + // this pointer is bad and uninitialized + viewer = static_cast(instance); + + if (viewer == nullptr) { + CAMITK_ERROR(tr("Cannot get %1 metaObject nor use the QMetaType create method").arg(viewerClassName)); + } + } + else { + // instanciate a new viewer of the managed class + QObject* o = metaObject->newInstance(Q_ARG(QString, name)); + viewer = qobject_cast(o); + + // register it in the list + registerViewer(viewer); + } + } + else { + CAMITK_ERROR(tr("Cannot create new instance of %1: type not registered by Qt").arg(viewerClassName)); + } +*/ + + return viewerInstance; +} + +// -------------------- getViewers -------------------- +const ViewerList& ViewerExtension::getViewers() { + return viewers; +} + + +} diff --git a/sdk/libraries/core/viewer/ViewerExtension.h b/sdk/libraries/core/viewer/ViewerExtension.h new file mode 100644 index 00000000..e7b7c616 --- /dev/null +++ b/sdk/libraries/core/viewer/ViewerExtension.h @@ -0,0 +1,133 @@ +/***************************************************************************** +* $CAMITK_LICENCE_BEGIN$ +* +* CamiTK - Computer Assisted Medical Intervention ToolKit +* (c) 2001-2018 Univ. Grenoble Alpes, CNRS, TIMC-IMAG UMR 5525 (GMCAO) +* +* Visit http://camitk.imag.fr for more information +* +* This file is part of CamiTK. +* +* CamiTK is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License version 3 +* only, as published by the Free Software Foundation. +* +* CamiTK is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Lesser General Public License version 3 for more details. +* +* You should have received a copy of the GNU Lesser General Public License +* version 3 along with CamiTK. If not, see . +* +* $CAMITK_LICENCE_END$ +****************************************************************************/ + +#ifndef VIEWER_EXTENSION_H +#define VIEWER_EXTENSION_H + +#include "CamiTKAPI.h" + +// -- QT stuff +#include +#include +#include +#include + +namespace camitk { +class Viewer; + +/// ViewerExtension implements a specific Factory pattern (@see getNewInstance) +/// Each time a viewer is registered, call setManagedMetaObject (the fist registered viewer will +/// register the managed class meta object that can be reused later on to instanciate new viewer) +/// register default viewer will use the class name to create a new viewer of the same name +/// \note #className surrounds macro argument with double quotes converting it to string +#define registerDefaultViewer(className) setManagedMetaObject(&className::staticMetaObject); \ + registerViewer(new className(QString(#className))) + +/// register a new viewer, instance of X, its name is Y +#define registerNewViewer(className, instanceName) setManagedMetaObject(&className::staticMetaObject); \ + registerViewer(new className(QString(instanceName))) + +/** +* @ingroup group_sdk_libraries_core_action +* +* @brief +* This class describes what is a generic Action extension. +* To add a ActionExtension to CamiTK core, write a new class that inherits from this class. +* +* The following methods HAVE to be redefined in your subclass: +* - getName: return the name of your extension +* - getDescription: return a small description +* - init: a simple enough method, just call registerNewAction(MyAction) for any +* MyAction class inheriting from camitk::Action +* +* @see BasicMeshExtension For an example of an extension registering more than one actions +*/ +class CAMITK_API ViewerExtension : public QObject { + +protected: + /// constructor + ViewerExtension(); + +public: + /// destructor + ~ViewerExtension() override; + + /// returns the viewer extension name (to be overriden in the derived class) + virtual QString getName() = 0; + + /// returns the viewer extension small description (to be overriden in the derived class) + virtual QString getDescription() = 0; + + /// this method should just call registerNewViewer(MyViewer) for any MyViewer class you need to register by this extension + virtual void init() = 0; + + /// get the list of viewer instances registered by this extension + const ViewerList& getViewers(); + + /// set the file path (once loaded as a dynamic library) = where this extension was loaded + void setLocation(const QString loc); + + /// get the file path (location of the .dll/.so/.dylib) of this plugin + QString getLocation() const; + + /// Load, for the selected langage (asked to the Application), the associated .qm file + void initResources(); + + /// get the class name of the viewer managed by this extension + QString getViewerClassName(); + + /// factory: create a new viewer instance and register it + /// @return a new instance of the given name, or the previously registered instance if it already exist + Viewer* getNewInstance(QString name); + +protected: + /// register an viewer instance + /// The first call will also register the managed viewer class name in viewerClassName + /// and its static meta object in + bool registerViewer(Viewer*); + + /// the list of viewers + ViewerList viewers; + + /// The first time this method is called, it sets the static meta object + void setManagedMetaObject(const QMetaObject*); + +private: + /// the shared lib (.so, .dll or .dylib) used to instantiate the ComponentExtension subclass instance + QString dynamicLibraryFileName; + + /// Provide internationalization support for text output. + QTranslator* translator; + + /// static meta object of the viewer class managed by this extension + const QMetaObject* managedMetaObject; +}; + +} +// -------------------- declare the interface for QPluginLoader -------------------- +Q_DECLARE_INTERFACE(camitk::ViewerExtension, "TIMC-IMAG. Viewer Extension/2.1") //TODO use variable from CMake? + +#endif //VIEWER_EXTENSION_H + diff --git a/sdk/libraries/core/viewer/vtkInteractorStylePick.cpp b/sdk/libraries/core/viewer/vtkInteractorStylePick.cpp index ab47557c..d3ff2ece 100644 --- a/sdk/libraries/core/viewer/vtkInteractorStylePick.cpp +++ b/sdk/libraries/core/viewer/vtkInteractorStylePick.cpp @@ -35,7 +35,6 @@ #include #include - namespace camitk { //----------------------- Picking Interactor ----------------------- @@ -305,4 +304,5 @@ void vtkInteractorStylePick::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); } -} + +} \ No newline at end of file diff --git a/sdk/libraries/core/viewer/vtkInteractorStylePick.h b/sdk/libraries/core/viewer/vtkInteractorStylePick.h index 5b92c597..e564b05d 100644 --- a/sdk/libraries/core/viewer/vtkInteractorStylePick.h +++ b/sdk/libraries/core/viewer/vtkInteractorStylePick.h @@ -27,6 +27,7 @@ #ifndef VTKINTERACTORSTYLEPICK_H #define VTKINTERACTORSTYLEPICK_H +#include "CamiTKAPI.h" #include #include @@ -34,10 +35,11 @@ class vtkUnsignedCharArray; namespace camitk { + /// Specific backward compatible interactor for CamiTK RendererWidget /// Interactor used when we are in picking mode /// -class vtkInteractorStylePick : public vtkInteractorStyle { +class CAMITK_API vtkInteractorStylePick : public vtkInteractorStyle { public: @@ -74,4 +76,5 @@ protected: }; } + #endif //VTKINTERACTORSTYLEPICK_H diff --git a/sdk/viewers/CMakeLists.txt b/sdk/viewers/CMakeLists.txt new file mode 100644 index 00000000..6c796fb5 --- /dev/null +++ b/sdk/viewers/CMakeLists.txt @@ -0,0 +1,18 @@ +# +# DO NOT EDIT THIS FILE (unless you REALLY know what you are doing) +# +# To add a component, just add a subdirectory (the component name is the +# directory name). Add all your code there and a text file called +# CMakeLists.txt +# In your CMakeLists.txt, use the camitk_extension(ACTION_EXTENSION ...) macro appropriately + +# find components +get_subdirectories(VIEWERS_LIST) + +# 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 subdirectories in CMake project +foreach(VIEWER_NAME ${VIEWERS_LIST}) + camitk_add_subdirectory(${VIEWER_NAME}) +endforeach() diff --git a/sdk/libraries/core/viewer/ActionViewer.cpp b/sdk/viewers/actionviewer/ActionViewer.cpp similarity index 75% rename from sdk/libraries/core/viewer/ActionViewer.cpp rename to sdk/viewers/actionviewer/ActionViewer.cpp index 35df1bb4..8e800ce5 100644 --- a/sdk/libraries/core/viewer/ActionViewer.cpp +++ b/sdk/viewers/actionviewer/ActionViewer.cpp @@ -25,9 +25,10 @@ #include "ActionViewer.h" -#include "Application.h" -#include "Component.h" -#include "Action.h" +//-- Core +#include +#include +#include #include #include @@ -35,49 +36,38 @@ #include #include #include -// Deprecated. Use Application.h to handle logger interface -//#include "Log.h" +#include + +using namespace camitk; -namespace camitk { // ---------------- constructor ---------------- -ActionViewer::ActionViewer() : Viewer("Action Viewer") { +ActionViewer::ActionViewer(QString name) : Viewer(name) { + setLayout(Viewer::DOCKED); myWidget = nullptr; familyComboBox = nullptr; nameComboBox = nullptr; actionWidgetStack = nullptr; searchFramePanel = nullptr; -} -// ---------------- getInstance ---------------- -ActionViewer* ActionViewer::getInstance() { - //static instantiation, static method variable - static ActionViewer* actionViewer = nullptr; - if (!actionViewer) { - actionViewer = new ActionViewer(); - } + // empty the list as this is an action viewer, it has nothing to do with Components + setComponents(QStringList()); +} - return actionViewer; +// ---------------- destructor ---------------- +ActionViewer::~ActionViewer() { } // -------------------- refresh -------------------- -void ActionViewer::refresh(Viewer* whoIsAsking) { - updateActionViewer(ViewerRefresh); +void ActionViewer::refresh(Viewer*) { + updateActionWidget(Application::getTriggeredAction()); + updateSearchPanel(ViewerRefresh); } // -------------------- getWidget -------------------- -QWidget* ActionViewer::getWidget(QWidget* parent) { +QWidget* ActionViewer::getWidget() { // lazy instantiation if (!myWidget) { - // if no parent then put this in a dialog - if (!parent) { - // put it in a dialog, this is the case for default MainWindow, who does not add the ActionViewer in a dock - QDialog* myWidgetIsADialog = new QDialog(nullptr); - myWidgetIsADialog->setWindowTitle(objectName()); - myWidget = myWidgetIsADialog; - } - else { - myWidget = new QWidget(); - } + myWidget = new QWidget(); auto* actionWidgetLayout = new QVBoxLayout(); @@ -111,7 +101,7 @@ QWidget* ActionViewer::getWidget(QWidget* parent) { emptyActionWidgetIndex = actionWidgetStack->addWidget(new QWidget()); // init history insert new index in history for empty selection ComponentList emptySelection; - widgetHistory.insert(emptySelection, NULL); + widgetHistory.insert(emptySelection, nullptr); actionWidgetLayout->addWidget(actionWidgetStack); // set the action widget layout @@ -146,17 +136,17 @@ void ActionViewer::setSearchPanelVisible(bool visibility) { // -------------------- changeActionNameComboBox -------------------- void ActionViewer::changeName() { action = Application::getAction(nameComboBox->currentText()); - updateActionViewer(ActionNameChanged); + updateSearchPanel(ActionNameChanged); } // -------------------- changeTag -------------------- void ActionViewer::changeTag() { - updateActionViewer(ActionTagChanged); + updateSearchPanel(ActionTagChanged); } // -------------------- changeFamilyComboBox -------------------- void ActionViewer::changeFamily() { - updateActionViewer(ActionFamilyChanged); + updateSearchPanel(ActionFamilyChanged); } // ---------------- componentListLessThan ---------------- @@ -181,8 +171,8 @@ bool operator<(const ComponentList& l1, const ComponentList& l2) { } } -// -------------------- updateActionViewer -------------------- -void ActionViewer::updateActionViewer(UpdateReason reason) { +// -------------------- updateSearchPanel -------------------- +void ActionViewer::updateSearchPanel(UpdateReason reason) { familyComboBox->blockSignals(true); nameComboBox->blockSignals(true); tagLineEdit->blockSignals(true); @@ -198,9 +188,8 @@ void ActionViewer::updateActionViewer(UpdateReason reason) { if (Application::getSelectedComponents().size() > 0) { possibleActions = Application::getActions(Application::getSelectedComponents()); } - else + else { // no selection => select only empty component actions - { possibleActions = Application::getActions(nullptr); } @@ -209,6 +198,7 @@ void ActionViewer::updateActionViewer(UpdateReason reason) { nameComboBox->addItem(action->getName()); } } + nameComboBox->model()->sort(0); break; @@ -230,11 +220,12 @@ void ActionViewer::updateActionViewer(UpdateReason reason) { if (actionset.size() == 1) { action = *(actionset.begin()); nameComboBox->setCurrentIndex(nameComboBox->findText(action->getName())); - updateActionViewer(ActionNameChanged); + updateSearchPanel(ActionNameChanged); } else { nameComboBox->clear(); nameComboBox->addItem("-- Select Action --"); + foreach (Action* action, actionset) { nameComboBox->addItem(action->getName()); } @@ -244,13 +235,13 @@ void ActionViewer::updateActionViewer(UpdateReason reason) { } } break; - case ViewerRefresh: default: { //-- selection was changed, update combo boxes and tag list, and then check history // copy selected component list (so that references are not used for comparison) ComponentList selected(Application::getSelectedComponents()); + // if selection did not change between two updates, no need to refresh the widget if (currentlySelected != selected) { currentlySelected = selected; @@ -260,25 +251,30 @@ void ActionViewer::updateActionViewer(UpdateReason reason) { QStringList wordList; familyComboBox->addItem("-- Select Family --"); nameComboBox->addItem("-- Select Action --"); + if (selected.size() > 0) { possibleActions = Application::getActions(selected.last()); } else { // no selection => select only empty component actions possibleActions = Application::getActions(nullptr); } // Complete family and action lists depending of the last selected component + foreach (Action* action, possibleActions) { if (familyComboBox->findText(action->getFamily()) == -1) { familyComboBox->addItem(action->getFamily()); } + if (nameComboBox->findText(action->getName()) == -1) { nameComboBox->addItem(action->getName()); } + foreach (QString tag, action->getTag()) { if (!wordList.contains(tag)) { wordList.append(tag); } } } + nameComboBox->model()->sort(0); familyComboBox->model()->sort(0); auto* completer = new QCompleter(wordList, myWidget); @@ -288,23 +284,23 @@ void ActionViewer::updateActionViewer(UpdateReason reason) { //-- check history // check if the same list of Component* was already used QMap::const_iterator it = widgetHistory.find(selected); + if (it != widgetHistory.end()) { // show the previously used widget - if (it.value() == NULL) { + if (it.value() == nullptr) { actionWidgetStack->setCurrentIndex(emptyActionWidgetIndex); } - else { // update search panel - familyComboBox->setCurrentIndex(familyComboBox->findText(it.value()->getFamily())); - nameComboBox->setCurrentIndex(nameComboBox->findText(it.value()->getName())); - it.value()->trigger(); + else { + updateActionWidget(it.value()); } } else { - // insert new index in history (NULL action, with empty widget) - widgetHistory.insert(selected, NULL); + // insert new index in history (nullptr action, with empty widget) + widgetHistory.insert(selected, nullptr); actionWidgetStack->setCurrentIndex(emptyActionWidgetIndex); } } + } } @@ -313,35 +309,37 @@ void ActionViewer::updateActionViewer(UpdateReason reason) { tagLineEdit->blockSignals(false); } -// -------------------- embedActionWidget -------------------- -void ActionViewer::embedActionWidget(Action* action) { - // make sure the action viewer is visible (even if in a dockwidget) - if (getWidget()->parentWidget()) { - getWidget()->parentWidget()->setVisible(true); - getWidget()->setVisible(true); - } +// -------------------- updateActionWidget -------------------- +void ActionViewer::updateActionWidget(Action* action) { + // no need to update if there is no currently selected action or the current action is not to embed + if (action != nullptr && action->getEmbedded()) { - //-- check history - QWidget* actionWidget = action->getWidget(); - int actionWidgetIndex = actionWidgetStack->indexOf(actionWidget); + // make sure the action viewer is visible (even if in a dockwidget) + if (getWidget()->parentWidget()) { + getWidget()->parentWidget()->setVisible(true); + getWidget()->setVisible(true); + } - if (actionWidgetIndex == -1 && actionWidget) { - // add the widget (beware that actionWidgetStack then takes ownership of the widget!) - actionWidgetIndex = actionWidgetStack->addWidget(actionWidget); - } + //-- check history + QWidget* actionWidget = action->getWidget(); + int actionWidgetIndex = actionWidgetStack->indexOf(actionWidget); - // insert new index in history - ComponentList selected(Application::getSelectedComponents()); - widgetHistory.insert(selected, action); - actionWidgetStack->setCurrentIndex(actionWidgetIndex); - actionWidgetStack->update(); - // ignore size policy of widget so that it can be resized - actionWidgetStack->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored); - - // update search panel - familyComboBox->setCurrentIndex(familyComboBox->findText(action->getFamily())); - updateActionViewer(ActionFamilyChanged); // to have only the actions of the same family - nameComboBox->setCurrentIndex(nameComboBox->findText(action->getName())); -} + if (actionWidgetIndex == -1 && actionWidget) { + // add the widget (beware that actionWidgetStack then takes ownership of the widget!) + actionWidgetIndex = actionWidgetStack->addWidget(actionWidget); + } + // insert new index in history + ComponentList selected(Application::getSelectedComponents()); + widgetHistory.insert(selected, action); + actionWidgetStack->setCurrentIndex(actionWidgetIndex); + actionWidgetStack->update(); + // ignore size policy of widget so that it can be resized + actionWidgetStack->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored); + + // update search panel + familyComboBox->setCurrentIndex(familyComboBox->findText(action->getFamily())); + updateSearchPanel(ActionFamilyChanged); // to have only the actions of the same family + nameComboBox->setCurrentIndex(nameComboBox->findText(action->getName())); + } } diff --git a/sdk/libraries/core/viewer/ActionViewer.h b/sdk/viewers/actionviewer/ActionViewer.h similarity index 82% rename from sdk/libraries/core/viewer/ActionViewer.h rename to sdk/viewers/actionviewer/ActionViewer.h index 24f42d47..5483b384 100644 --- a/sdk/libraries/core/viewer/ActionViewer.h +++ b/sdk/viewers/actionviewer/ActionViewer.h @@ -26,6 +26,12 @@ #ifndef ACTIONVIEWER_H #define ACTIONVIEWER_H +#include "ActionViewerAPI.h" + +#include +#include +#include + #include #include #include @@ -35,11 +41,6 @@ #include #include -#include "Viewer.h" -#include "Action.h" -#include "Component.h" - -namespace camitk { /** * @ingroup group_sdk_libraries_core_viewer * @@ -54,7 +55,7 @@ namespace camitk { * You do not have to use it, but it is convienent (and sometimes preferable) to use this instance * instead of creating your own one. */ -class CAMITK_API ActionViewer : public Viewer { +class ACTIONVIEWER_API ActionViewer : public camitk::Viewer { Q_OBJECT public: @@ -62,14 +63,10 @@ public: */ ///@{ /// constructor - ActionViewer(); + Q_INVOKABLE ActionViewer(QString name); /// destructor - ~ActionViewer() override = default; - - /// returns the unique instance of ActionViewer - static ActionViewer* getInstance(); - //@} + virtual ~ActionViewer(); /// @name Inherited from Viewer //@{ @@ -79,19 +76,14 @@ public: }; /// refresh the view (can be interesting to know which other viewer is calling this) - void refresh(Viewer* whoIsAsking = nullptr) override; + virtual void refresh(Viewer* whoIsAsking = nullptr); - /// get the viewer widget. @param parent the parent widget for the viewer widget - QWidget* getWidget(QWidget* parent = nullptr) override; + /// get the viewer widget + virtual QWidget* getWidget(); //@} - /// @name Specific to the Action viewer - //@{ - /// embed an action widget in the stacked widget - void embedActionWidget(Action*); - /// show/hide the search panel (hidden by default) - void setSearchPanelVisible(bool); + virtual void setSearchPanelVisible(bool); //@} protected slots : @@ -108,8 +100,13 @@ private: /// Enum the different fields of the action viewwer enum UpdateReason {ActionFamilyChanged, ActionNameChanged, ActionTagChanged, ViewerRefresh}; + /// @name Specific to the Action viewer + //@{ + /// embed an action widget in the stacked widget if needed + virtual void updateActionWidget(camitk::Action*); + /// method used to update the viewer for a given update field - void updateActionViewer(UpdateReason); + void updateSearchPanel(UpdateReason); /// Main action widget of the viewer QWidget* myWidget; @@ -121,7 +118,7 @@ private: QComboBox* nameComboBox; /// Current action - Action* action; + camitk::Action* action; /// action tags line edit QLineEdit* tagLineEdit; @@ -136,11 +133,11 @@ private: int emptyActionWidgetIndex; /// this map stores the list of selected component and the corresponding stack index of their embedded action - QMap widgetHistory; + QMap widgetHistory; /// Used to evaluate modification of the list while execution - ComponentList currentlySelected; + camitk::ComponentList currentlySelected; }; -} + #endif // ACTIONVIEWER_H diff --git a/sdk/viewers/actionviewer/ActionViewerAPI.h b/sdk/viewers/actionviewer/ActionViewerAPI.h new file mode 100644 index 00000000..39229001 --- /dev/null +++ b/sdk/viewers/actionviewer/ActionViewerAPI.h @@ -0,0 +1,74 @@ +/***************************************************************************** +* $CAMITK_LICENCE_BEGIN$ +* +* CamiTK - Computer Assisted Medical Intervention ToolKit +* (c) 2001-2018 Univ. Grenoble Alpes, CNRS, TIMC-IMAG UMR 5525 (GMCAO) +* +* Visit http://camitk.imag.fr for more information +* +* This file is part of CamiTK. +* +* CamiTK is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License version 3 +* only, as published by the Free Software Foundation. +* +* CamiTK is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Lesser General Public License version 3 for more details. +* +* You should have received a copy of the GNU Lesser General Public License +* version 3 along with CamiTK. If not, see . +* +* $CAMITK_LICENCE_END$ +****************************************************************************/ + +// ----- ACTIONVIEWER_API_H.h +#ifndef ACTIONVIEWER_API_H +#define ACTIONVIEWER_API_H + +// ----------------------------------------------------------------------- +// +// ACTIONVIEWER_API +// +// ----------------------------------------------------------------------- + +// The following ifdef block is the standard way of creating macros which make exporting +// from a DLL simpler. All files within this DLL are compiled with the COMPILE_ACTIONVIEWER_API +// flag defined on the command line. this symbol should not be defined on any project +// that uses this DLL. This way any other project whose source files include this file see +// ACTIONVIEWER_API functions as being imported from a DLL, wheras this DLL sees symbols +// defined with this macro as being exported. + +#if defined(_WIN32) // MSVC and mingw + +#ifdef COMPILE_ACTIONVIEWER_API +#define ACTIONVIEWER_API __declspec(dllexport) +#else +#define ACTIONVIEWER_API __declspec(dllimport) +#endif // COMPILE_ACTIONVIEWER_API + +#else // for all other platforms ACTIONVIEWER_API is defined to be "nothing" + +#ifndef ACTIONVIEWER_API +#define ACTIONVIEWER_API +#endif // ACTIONVIEWER_API + +#endif // MSVC and mingw + +// ----------------------------------------------------------------------- +// It seems that MSVC does not understand exception specification +// If I understand it well, when _declspec() is used, there is a default +// nothrow attribute. +// I did not find the throw attribute. It seems that msvc is therefore ignoring the +// specification of the type of the exception. +// The compiler therefore issues a warning. +// The following line is to avoid this particular warning. +// The best would be to ask msvc not only to take the exception into account, but also +// its type. Anyway, I did not find how to do that anywhere, and I am not sure this is +// possible... +#if defined(_WIN32) && !defined(__MINGW32__) // MSVC only +#pragma warning( disable : 4290 ) +#endif // MSVC only + +#endif // ACTIONVIEWER_API_H \ No newline at end of file diff --git a/sdk/viewers/actionviewer/ActionViewerExtension.cpp b/sdk/viewers/actionviewer/ActionViewerExtension.cpp new file mode 100644 index 00000000..f3ca8f37 --- /dev/null +++ b/sdk/viewers/actionviewer/ActionViewerExtension.cpp @@ -0,0 +1,36 @@ +/***************************************************************************** + * $CAMITK_LICENCE_BEGIN$ + * + * CamiTK - Computer Assisted Medical Intervention ToolKit + * (c) 2001-2018 Univ. Grenoble Alpes, CNRS, TIMC-IMAG UMR 5525 (GMCAO) + * + * Visit http://camitk.imag.fr for more information + * + * This file is part of CamiTK. + * + * CamiTK is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * CamiTK is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with CamiTK. If not, see . + * + * $CAMITK_LICENCE_END$ + ****************************************************************************/ + + +#include "ActionViewerExtension.h" + +// include generated actions headers +#include "ActionViewer.h" + +// --------------- getViewers ------------------- +void ActionViewerExtension::init() { + registerDefaultViewer(ActionViewer); +} + diff --git a/sdk/viewers/actionviewer/ActionViewerExtension.h b/sdk/viewers/actionviewer/ActionViewerExtension.h new file mode 100644 index 00000000..c8561c9c --- /dev/null +++ b/sdk/viewers/actionviewer/ActionViewerExtension.h @@ -0,0 +1,64 @@ +/***************************************************************************** + * $CAMITK_LICENCE_BEGIN$ + * + * CamiTK - Computer Assisted Medical Intervention ToolKit + * (c) 2001-2018 Univ. Grenoble Alpes, CNRS, TIMC-IMAG UMR 5525 (GMCAO) + * + * Visit http://camitk.imag.fr for more information + * + * This file is part of CamiTK. + * + * CamiTK is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * CamiTK is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with CamiTK. If not, see . + * + * $CAMITK_LICENCE_END$ + ****************************************************************************/ + + +#ifndef ACTIONVIEWEREXTENSION_H +#define ACTIONVIEWEREXTENSION_H + +#include "ActionViewerAPI.h" + +//-- from CamiTK Core +#include + +class ACTIONVIEWER_API ActionViewerExtension : public camitk::ViewerExtension { + Q_OBJECT + Q_INTERFACES(camitk::ViewerExtension); + Q_PLUGIN_METADATA(IID "fr.imag.camitk.actionviewerextension.viewer.actionviewerextension") + +public: + /// Constructor + ActionViewerExtension() : ViewerExtension() {}; + + /// Destructor + virtual ~ActionViewerExtension() = default; + + /// Method returning the action extension name + virtual QString getName() { + return "Action Viewer Extension"; + }; + + /// Method returning the action extension descrption + virtual QString getDescription() { + return "actionViewer displays the currently selected action's GUI as well as a action selector"; + }; + + /// initialize all the actions + virtual void init(); + +}; + +#endif // ACTIONVIEWEREXTENSION_H + + diff --git a/sdk/viewers/actionviewer/CMakeLists.txt b/sdk/viewers/actionviewer/CMakeLists.txt new file mode 100644 index 00000000..5e9869de --- /dev/null +++ b/sdk/viewers/actionviewer/CMakeLists.txt @@ -0,0 +1,8 @@ +# Call CamiTK CMake Macro to define the action +camitk_extension(VIEWER_EXTENSION + CEP_NAME SDK + DEFINES COMPILE_ACTIONVIEWER_API + DESCRIPTION "A viewer to display the currently selected action's GUI as well as a action selector" + INSTALL_ALL_HEADERS +) + diff --git a/tutorials/actions/bitmapviewer/BitmapViewer.cpp b/sdk/viewers/bitmap/BitmapViewer.cpp similarity index 83% rename from tutorials/actions/bitmapviewer/BitmapViewer.cpp rename to sdk/viewers/bitmap/BitmapViewer.cpp index 0000490c..aaab0207 100644 --- a/tutorials/actions/bitmapviewer/BitmapViewer.cpp +++ b/sdk/viewers/bitmap/BitmapViewer.cpp @@ -27,7 +27,6 @@ #include #include -#include #include #include @@ -36,23 +35,10 @@ using namespace camitk; -// initialize static variables -QString BitmapViewer::BitmapViewerName = "2D Bitmap Viewer"; // required due to QString ref needed by InteractiveViewer cstr -BitmapViewer* BitmapViewer::singleton = nullptr; - -BitmapViewer* BitmapViewer::getInstance() { - if (!singleton) { - singleton = new BitmapViewer(); - } - - return singleton; -} - - // -------------------- Constructor -------------------- -BitmapViewer::BitmapViewer() : InteractiveViewer(BitmapViewerName, InteractiveViewer::SLICE_VIEWER) { +BitmapViewer::BitmapViewer(QString name) : InteractiveViewer(name, InteractiveViewer::SLICE_VIEWER) { // 2D images need x right, y up, z front - getRendererWidget()->setCameraOrientation(RendererWidget::RIGHT_UP); + getRendererWidget()->setCameraOrientation(RendererWidget::RIGHT_DOWN); // no decoration and grey background getRendererWidget()->toggleOrientationDecorations(false); getRendererWidget()->setGradientBackground(false); @@ -60,6 +46,8 @@ BitmapViewer::BitmapViewer() : InteractiveViewer(BitmapViewerName, InteractiveVi // parallel projection getRendererWidget()->getActiveCamera()->ParallelProjectionOn(); + setComponents(QStringList() << "ImageComponent"); + myToolbar = nullptr; } @@ -74,8 +62,8 @@ void BitmapViewer::refresh(Viewer* whoIsAsking) { } // -------------------- getWidget -------------------- -QWidget* BitmapViewer::getWidget(QWidget* parent) { - QWidget* myWidget = InteractiveViewer::getWidget(parent); +QWidget* BitmapViewer::getWidget() { + QWidget* myWidget = InteractiveViewer::getWidget(); // hide slice slider sideFrame->hide(); updateVisibility(); @@ -98,7 +86,7 @@ QToolBar* BitmapViewer::getToolBar() { hideViewerAction->setStatusTip(tr("Switch back to the medical image viewer")); hideViewerAction->setWhatsThis(tr("Switch back the ventral viewer to normal (i.e., show the Medical Image Viewer)")); connect(hideViewerAction, &QAction::triggered, [=](bool) { - Application::getMainWindow()->setCentralViewer(MedicalImageViewer::getInstance()); + Application::getMainWindow()->setCentralViewer(Application::getViewer("MedicalImageViewer")); }); } return myToolbar; @@ -111,7 +99,7 @@ void BitmapViewer::updateVisibility() { // tell all the components that are already visible in the axial slices to be also // visible in my2DBitmapViewer for (Component* comp : Application::getAllComponents()) { - if (comp->getVisibility(InteractiveViewer::getAxialViewer())) { + if (comp->getVisibility(Application::getViewer("axialViewer"))) { comp->setVisibility(this, true); } } diff --git a/tutorials/actions/bitmapviewer/BitmapViewer.h b/sdk/viewers/bitmap/BitmapViewer.h similarity index 85% rename from tutorials/actions/bitmapviewer/BitmapViewer.h rename to sdk/viewers/bitmap/BitmapViewer.h index b7cb7a59..33f67971 100644 --- a/tutorials/actions/bitmapviewer/BitmapViewer.h +++ b/sdk/viewers/bitmap/BitmapViewer.h @@ -27,6 +27,9 @@ #ifndef BITMAPVIEWER_H #define BITMAPVIEWER_H +#include "BitmapViewerAPI.h" + +//-- Core #include class QToolBar; @@ -35,30 +38,21 @@ class QToolBar; * @brief * InteractiveViewer specialized in 2D bitmap (images in jpeg, png...) */ -class BitmapViewer : public camitk::InteractiveViewer { +class BITMAP_VIEWER_API BitmapViewer : public camitk::InteractiveViewer { Q_OBJECT public: - - static BitmapViewer* getInstance(); + Q_INVOKABLE BitmapViewer(QString name); virtual ~BitmapViewer() override; void refresh(camitk::Viewer* whoIsAsking = nullptr) override; - QWidget* getWidget(QWidget* parent = nullptr) override; + QWidget* getWidget() override; QToolBar* getToolBar() override; - -protected: - - BitmapViewer(); private: - - static BitmapViewer* singleton; - - static QString BitmapViewerName; QToolBar* myToolbar; diff --git a/sdk/viewers/bitmap/BitmapViewerAPI.h b/sdk/viewers/bitmap/BitmapViewerAPI.h new file mode 100644 index 00000000..7f7859e0 --- /dev/null +++ b/sdk/viewers/bitmap/BitmapViewerAPI.h @@ -0,0 +1,67 @@ +/***************************************************************************** + * $CAMITK_LICENCE_BEGIN$ + * + * CamiTK - Computer Assisted Medical Intervention ToolKit + * (c) 2001-2014 UJF-Grenoble 1, CNRS, TIMC-IMAG UMR 5525 (GMCAO) + * + * Visit http://camitk.imag.fr for more information + * + * + * CamiTK is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * CamiTK is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with CamiTK. If not, see . + * + * $CAMITK_LICENCE_END$ + ****************************************************************************/ + +#ifndef BITMAP_VIEWER_API_H +#define BITMAP_VIEWER_API_H + +// ----------------------------------------------------------------------- +// +// BITMAP_VIEWER_API +// +// ----------------------------------------------------------------------- +// The following ifdef block is the standfard way of creating macros which make exporting +// from a DLL simpler. All files within this DLL are compiled with the COMPILE_BITMAP_VIEWER_API +// flag defined on the command line. this symbol should not be defined on any project +// that uses this DLL. This way any other project whose source files include this file see +// BITMAP_VIEWER_API functions as being imported from a DLL, whereas this DLL sees symbols +// defined with this macro as being exported. +#if defined(_WIN32) // MSVC and mingw +#ifdef COMPILE_BITMAP_VIEWER_API +#define BITMAP_VIEWER_API __declspec(dllexport) +#else +#define BITMAP_VIEWER_API __declspec(dllimport) +#endif +#else +// for all other platforms BITMAP_VIEWER_API is defined to be "nothing" +#ifndef BITMAP_VIEWER_API +#define BITMAP_VIEWER_API +#endif +#endif // MSVC and mingw + +// ----------------------------------------------------------------------- +// It seems that MSVC does not understand exception specification +// If I understand it well, when _declspec() is used, there is a default +// nothrow attribute. +// I did not find the throw attribute. It seems that msvc is therefore ignoring the +// specification of the type of the exception. +// The compiler therefore issues a warning. +// The following line is to avoid this particular warning. +// The best would be to ask msvc not only to take the exception into account, but also +// its type. Anyway, I did not find how to do that anywhere, and I am not sure this is +// possible... +#if defined(_WIN32) && !defined(__MINGW32__) // MSVC only +#pragma warning( disable : 4290 ) +#endif // MSVC only + +#endif // BITMAP_VIEWER_API_H diff --git a/sdk/viewers/bitmap/BitmapViewerExtension.cpp b/sdk/viewers/bitmap/BitmapViewerExtension.cpp new file mode 100644 index 00000000..01a3369a --- /dev/null +++ b/sdk/viewers/bitmap/BitmapViewerExtension.cpp @@ -0,0 +1,36 @@ +/***************************************************************************** + * $CAMITK_LICENCE_BEGIN$ + * + * CamiTK - Computer Assisted Medical Intervention ToolKit + * (c) 2001-2018 Univ. Grenoble Alpes, CNRS, TIMC-IMAG UMR 5525 (GMCAO) + * + * Visit http://camitk.imag.fr for more information + * + * This file is part of CamiTK. + * + * CamiTK is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * CamiTK is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with CamiTK. If not, see . + * + * $CAMITK_LICENCE_END$ + ****************************************************************************/ + + +#include "BitmapViewerExtension.h" + +// include generated actions headers +#include "BitmapViewer.h" + +// --------------- getActions ------------------- +void BitmapViewerExtension::init() { + registerDefaultViewer(BitmapViewer); +} + diff --git a/sdk/viewers/bitmap/BitmapViewerExtension.h b/sdk/viewers/bitmap/BitmapViewerExtension.h new file mode 100644 index 00000000..7f2bfd3e --- /dev/null +++ b/sdk/viewers/bitmap/BitmapViewerExtension.h @@ -0,0 +1,62 @@ +/***************************************************************************** + * $CAMITK_LICENCE_BEGIN$ + * + * CamiTK - Computer Assisted Medical Intervention ToolKit + * (c) 2001-2018 Univ. Grenoble Alpes, CNRS, TIMC-IMAG UMR 5525 (GMCAO) + * + * Visit http://camitk.imag.fr for more information + * + * This file is part of CamiTK. + * + * CamiTK is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * CamiTK is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with CamiTK. If not, see . + * + * $CAMITK_LICENCE_END$ + ****************************************************************************/ + + +#ifndef BITMAP_VIEWER_EXTENSION_H +#define BITMAP_VIEWER_EXTENSION_H + +//-- Core +#include + +class BitmapViewerExtension : public camitk::ViewerExtension { + Q_OBJECT + Q_INTERFACES(camitk::ViewerExtension); + Q_PLUGIN_METADATA(IID "fr.imag.camitk.tutorials.viewer.bitmapviewerextension") + +public: + /// Constructor + BitmapViewerExtension() : ViewerExtension() {}; + + /// Destructor + virtual ~BitmapViewerExtension() = default; + + /// Method returning the action extension name + virtual QString getName() { + return "BitmapViewer Extension"; + }; + + /// Method returning the action extension descrption + virtual QString getDescription() { + return "This extension provides BitmapViewer, a simple 2D image viewer"; + }; + + /// initialize all the actions + virtual void init(); + +}; + +#endif // BITMAP_VIEWER_EXTENSION_H + + diff --git a/sdk/viewers/bitmap/CMakeLists.txt b/sdk/viewers/bitmap/CMakeLists.txt new file mode 100644 index 00000000..58c4805a --- /dev/null +++ b/sdk/viewers/bitmap/CMakeLists.txt @@ -0,0 +1,8 @@ +# Call CamiTK CMake Macro to define the action +camitk_extension(VIEWER_EXTENSION + DEFAULT + DEFINES COMPILE_BITMAP_VIEWER_API + DESCRIPTION "This extension provides a simple 2D image viewer" + INSTALL_ALL_HEADERS +) + diff --git a/sdk/viewers/explorer/CMakeLists.txt b/sdk/viewers/explorer/CMakeLists.txt new file mode 100644 index 00000000..2bcb223c --- /dev/null +++ b/sdk/viewers/explorer/CMakeLists.txt @@ -0,0 +1,8 @@ +# Call CamiTK CMake Macro to define the action +camitk_extension(VIEWER_EXTENSION + CEP_NAME SDK + DEFINES COMPILE_EXPLORER_API + DESCRIPTION "An extension for the viewer that display GUI action" + INSTALL_ALL_HEADERS +) + diff --git a/sdk/libraries/core/viewer/Explorer.cpp b/sdk/viewers/explorer/Explorer.cpp similarity index 95% rename from sdk/libraries/core/viewer/Explorer.cpp rename to sdk/viewers/explorer/Explorer.cpp index 2a3e8c73..a6cb347c 100644 --- a/sdk/libraries/core/viewer/Explorer.cpp +++ b/sdk/viewers/explorer/Explorer.cpp @@ -23,27 +23,29 @@ * $CAMITK_LICENCE_END$ ****************************************************************************/ -//-- camiTK stuff #include "Explorer.h" -#include "Application.h" -#include "Component.h" -#include "Log.h" +//-- CamiTK Core stuff +#include +#include +#include //-- Qt stuff #include #include -//-- to stretch th first column to entirely show the names +//-- to stretch the first column to entirely show the names #include //-- stl stuff #include +using namespace camitk; -namespace camitk { //----------------------- constructor ------------------------ -Explorer::Explorer() : Viewer("Explorer") { +Explorer::Explorer(QString name) : Viewer(name) { + setLayout(Viewer::DOCKED); + setIcon(QPixmap(":/explorer")); explorerTree = nullptr; explorerMenu = nullptr; } @@ -57,22 +59,11 @@ Explorer::~Explorer() { explorerMenu = nullptr; } -//----------------------- getInstance ------------------------ -Explorer* Explorer::getInstance() { - // static instanciation, static method variable - static Explorer* explorer = nullptr; - if (!explorer) { - explorer = new Explorer(); - } - - return explorer; -} - //----------------------- getWidget ------------------------ -QWidget* Explorer::getWidget(QWidget* parent) { +QWidget* Explorer::getWidget() { if (explorerTree == nullptr) { //-- create the explorer tree - explorerTree = new QTreeWidget(parent); + explorerTree = new QTreeWidget(); // For explorerTree to emit the customMenu.. signal explorerTree->setContextMenuPolicy(Qt::CustomContextMenu); // headers @@ -409,6 +400,3 @@ void Explorer::renameItem() { } } - -} - diff --git a/sdk/libraries/core/viewer/Explorer.h b/sdk/viewers/explorer/Explorer.h similarity index 83% rename from sdk/libraries/core/viewer/Explorer.h rename to sdk/viewers/explorer/Explorer.h index fcb73c34..a337bac0 100644 --- a/sdk/libraries/core/viewer/Explorer.h +++ b/sdk/viewers/explorer/Explorer.h @@ -27,19 +27,21 @@ #ifndef EXPLORER_H #define EXPLORER_H +#include "ExplorerAPI.h" + // -- Core stuff -#include "Viewer.h" +#include // -- QT stuff #include #include namespace camitk { -// -- Core stuff classes -class InterfaceNode; -class Component; -class ExplorerItem; -class Explorer; + // -- Core stuff classes + class InterfaceNode; + class Component; + class ExplorerItem; +} /** * @ingroup group_sdk_libraries_core_viewer @@ -55,7 +57,7 @@ class Explorer; * You do not have to use it, but it is convienent (and sometimes preferable) to use this instance * instead of creating your own one. */ -class CAMITK_API Explorer : public Viewer { +class EXPLORER_API Explorer : public camitk::Viewer { Q_OBJECT public: @@ -63,15 +65,11 @@ public: */ ///@{ /** Construtor */ - Explorer(); + Q_INVOKABLE Explorer(QString); /** Destructor */ ~Explorer() override; - /// returns the unique instance of ActionViewer - static Explorer* getInstance(); - /// @} - /** @name Inherited from Viewer */ ///@{ @@ -79,10 +77,10 @@ public: unsigned int numberOfViewedComponent() override; /// refresh the explorer (can be interesting to know which other viewer is calling this) - void refresh(Viewer* whoIsAsking = nullptr) override; + void refresh(camitk::Viewer* whoIsAsking = nullptr) override; - /// get the explorer widget (QTreeWidget). @param parent the parent widget for the viewer widget - QWidget* getWidget(QWidget* parent) override; + /// get the explorer widget (QTreeWidget) + QWidget* getWidget() override; /// get the explorer menu QMenu* getMenu() override; @@ -97,7 +95,7 @@ public: * If the component was not displayed in the explorer, this method does nothing. * @param comp The InterfaceNode provider to update list. */ - void refreshInterfaceNode(Component* comp) override; + void refreshInterfaceNode(camitk::Component* comp) override; ///@} public slots : @@ -121,27 +119,27 @@ private: /// @name QTreeWidgetItem/InterfaceNode map ///@{ /// the map to get the Component* from the QTreeWidgetItem* - QMap itemComponentMap; + QMap itemComponentMap; /// the map to get the QTreeWidgetItem corresponding to a parentComp - QMap topLevelCompItemMap; + QMap topLevelCompItemMap; /// Return the QTreeWidgetItem of a given Component (return NULL if not found) - QTreeWidgetItem* getItem(Component*); + QTreeWidgetItem* getItem(camitk::Component*); ///@} /// @name QTreeWidget and QTreeWidgetItem management ///@{ /// instanciate a new QTreeWidgetItem using names and properties from the InterfaceNode, and using parent - QTreeWidgetItem* getNewItem(QTreeWidgetItem* parent, Component*); + QTreeWidgetItem* getNewItem(QTreeWidgetItem* parent, camitk::Component*); /// recursively add the Component in the tree explorer and return the QTreeWidgetItem of the InterfaceNode - QTreeWidgetItem* add(QTreeWidgetItem*, Component*); + QTreeWidgetItem* add(QTreeWidgetItem*, camitk::Component*); /** Add the given Component to the explorer (at top level) and automatically create children Component items. * @param comp The Component to add in the tree view. */ - void addTopLevel(Component* comp, int index = -1); + void addTopLevel(camitk::Component* comp, int index = -1); /// remove a given item from the explorer (return its index in the parent item list) void remove(QTreeWidgetItem*); @@ -149,7 +147,7 @@ private: /** Remove the Component (its Component and its sub-item) from the explorer list (if present). * The Component itself is of course not deleted here. */ - void removeTopLevel(Component* comp); + void removeTopLevel(camitk::Component* comp); /// the list view @@ -166,7 +164,4 @@ private: ///@} }; -} - - #endif diff --git a/sdk/viewers/explorer/ExplorerAPI.h b/sdk/viewers/explorer/ExplorerAPI.h new file mode 100644 index 00000000..b8ead55c --- /dev/null +++ b/sdk/viewers/explorer/ExplorerAPI.h @@ -0,0 +1,59 @@ +/***************************************************************************** +* $CAMITK_LICENCE_BEGIN$ +* +* CamiTK - Computer Assisted Medical Intervention ToolKit +* (c) 2001-2018 Univ. Grenoble Alpes, CNRS, TIMC-IMAG UMR 5525 (GMCAO) +* +* Visit http://camitk.imag.fr for more information +* +* This file is part of CamiTK. +* +* CamiTK is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License version 3 +* only, as published by the Free Software Foundation. +* +* CamiTK is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Lesser General Public License version 3 for more details. +* +* You should have received a copy of the GNU Lesser General Public License +* version 3 along with CamiTK. If not, see . +* +* $CAMITK_LICENCE_END$ +****************************************************************************/ + +// ----- EXPLORER_API_H.h +#ifndef EXPLORER_API_H +#define EXPLORER_API_H + +// ----------------------------------------------------------------------- +// +// EXPLORER_API +// +// ----------------------------------------------------------------------- + +// The following ifdef block is the standard way of creating macros which make exporting +// from a DLL simpler. All files within this DLL are compiled with the COMPILE_EXPLORER_API +// flag defined on the command line. this symbol should not be defined on any project +// that uses this DLL. This way any other project whose source files include this file see +// EXPLORER_API functions as being imported from a DLL, wheras this DLL sees symbols +// defined with this macro as being exported. + +#if defined(_WIN32) // MSVC and mingw + +#ifdef COMPILE_EXPLORER_API +#define EXPLORER_API __declspec(dllexport) +#else +#define EXPLORER_API __declspec(dllimport) +#endif // COMPILE_EXPLORER_API + +#else // for all other platforms EXPLORER_API is defined to be "nothing" + +#ifndef EXPLORER_API +#define EXPLORER_API +#endif // EXPLORER_API + +#endif // MSVC and mingw + +#endif // EXPLORER_API_H \ No newline at end of file diff --git a/sdk/viewers/explorer/ExplorerExtension.cpp b/sdk/viewers/explorer/ExplorerExtension.cpp new file mode 100644 index 00000000..ad55d2ab --- /dev/null +++ b/sdk/viewers/explorer/ExplorerExtension.cpp @@ -0,0 +1,42 @@ +/***************************************************************************** + * $CAMITK_LICENCE_BEGIN$ + * + * CamiTK - Computer Assisted Medical Intervention ToolKit + * (c) 2001-2018 Univ. Grenoble Alpes, CNRS, TIMC-IMAG UMR 5525 (GMCAO) + * + * Visit http://camitk.imag.fr for more information + * + * This file is part of CamiTK. + * + * CamiTK is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * CamiTK is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with CamiTK. If not, see . + * + * $CAMITK_LICENCE_END$ + ****************************************************************************/ + + +#include "ExplorerExtension.h" + +// include generated actions headers +#include "Explorer.h" + +// --------------- constructor ------------------- +ExplorerExtension::ExplorerExtension() : ViewerExtension() { + // initialize the icon resources + Q_INIT_RESOURCE(ExplorerExtensionIcons); +} + +// --------------- getViewers ------------------- +void ExplorerExtension::init() { + registerDefaultViewer(Explorer); +} + diff --git a/sdk/viewers/explorer/ExplorerExtension.h b/sdk/viewers/explorer/ExplorerExtension.h new file mode 100644 index 00000000..175837ba --- /dev/null +++ b/sdk/viewers/explorer/ExplorerExtension.h @@ -0,0 +1,64 @@ +/***************************************************************************** + * $CAMITK_LICENCE_BEGIN$ + * + * CamiTK - Computer Assisted Medical Intervention ToolKit + * (c) 2001-2018 Univ. Grenoble Alpes, CNRS, TIMC-IMAG UMR 5525 (GMCAO) + * + * Visit http://camitk.imag.fr for more information + * + * This file is part of CamiTK. + * + * CamiTK is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * CamiTK is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with CamiTK. If not, see . + * + * $CAMITK_LICENCE_END$ + ****************************************************************************/ + + +#ifndef EXPLOREREXTENSION_H +#define EXPLOREREXTENSION_H + +#include "ExplorerAPI.h" + +//-- from CamiTK Core +#include + +class EXPLORER_API ExplorerExtension : public camitk::ViewerExtension { + Q_OBJECT + Q_INTERFACES(camitk::ViewerExtension); + Q_PLUGIN_METADATA(IID "fr.imag.camitk.explorerextension.viewer.explorerextension") + +public: + /// Constructor + ExplorerExtension(); + + /// Destructor + virtual ~ExplorerExtension() = default; + + /// Method returning the action extension name + virtual QString getName() { + return "Explorer Extension"; + }; + + /// Method returning the action extension descrption + virtual QString getDescription() { + return "An extension for the explorer"; + }; + + /// initialize all the actions + virtual void init(); + +}; + +#endif // EXPLOREREXTENSION_H + + diff --git a/sdk/viewers/explorer/ExplorerExtensionIcons.qrc b/sdk/viewers/explorer/ExplorerExtensionIcons.qrc new file mode 100644 index 00000000..926bcbe0 --- /dev/null +++ b/sdk/viewers/explorer/ExplorerExtensionIcons.qrc @@ -0,0 +1,5 @@ + + + resources/folder-orange.png + + diff --git a/sdk/viewers/explorer/resources/folder-orange.png b/sdk/viewers/explorer/resources/folder-orange.png new file mode 100644 index 0000000000000000000000000000000000000000..f0e2b7a83fa5e209ea3dcbe73e474fbd310c2df3 GIT binary patch literal 5026 zcmWkydpr~B8}EGT*EnN}+FU1vaop1}nUQ-4rA{b!D~e-oP3E$b%Vf)4;$ZGMMcAT{ zal~RJb19j-O>DWfHrFM`-skf?f4uMWJn!>7@Ava&Ty}Mk{#EhULx&DYJ6^PP z7xN4Mk;GB)`utAhteE{0?e1WGsBuV{D;6XpE_y{DIuzdVAN?{uONNM*fEY&?JHXTt zNwC4M+FD(cS6J(D`RA1=3A)G@`hB5}V`rCV z5O*wYOcjm0x8hIK{FVx8;5Kky`<^h@br6GuDN3CcYZPtmmkJ=9=`@LbvWMdbcQB1jOwIi}cAq38FDe z;qt+vCBH6V=gonfWMTGEHKk`07n=v{+YcL z^+l9hE~Gc4O&>?+m8E&BYe49lRwiM2c|bMhz-gsI^{_V*%z->z$}ycDd$5&>>f^#J zl3SO#fu#U=(2Luh6AHR_p5O*!*Sc8u_eKXlmwHgfnb3_ig=h7*%Ok zZ^MV#uDVhLIhp%gBlt>~0)=^frcqV6hfWytSnCR$3m;;q6w}Pd@+xB&?QOvPM=J0m zZ?-;>hKxz&yFYsK`}=$OtwZ^*KE=`;QltT3Xk=jjDXm6%)z1#RDX@kALLZ)o45hu| zZEo|NyLT4rF@EH;S?mZXjF6_{CZ7rp&@t8upEPBRZNAzS5=+pDE6ms3qSc$-ydM7V zlgF(bkEu$7ootR0K{`^`i}IvlJ`HDm3y#$K7U-(}L35g!K__vxr*|z6ntJQ^N4w8h z?nC-Kgph+J%gJ&f+wz;KD9O~q3&~3D)i%kaY55hfWO0H8{HdIsg%);9!IK!ylL zW)0HtC2JCyL*KdpU&_7LuY5#0G}xk9zX5P(z`7WL#!?LZoK%Y#kpY!Tn9`WeI|Gh3 z@0Aykd|Q)LtdTr@$eW9YX*QH;gM9`U+CJCM5XILUI`aX08lsDxC+RH$xM!GL`}bRa z(Yi+D?3lB;Y5BV7r>J95409F;-U)+iN`!l&M)F3jxbLw3P_OM6jxmP9NrTQVWEfU@*y%eB7YWZ1Dce&Nh;-?NZJ? zgF-2*q2sw0M7RGb1k#m9uimc7HcJY za_yXn^B@niQOeq&BecjtdE#QRl73sj@s|4)051U^xXH>&%1Ap*Jbzhg`SEJ0$B9}v znpGX%mKTo=!n~qA^7ue((ZbxIjPagwRQL)|j+M-GwcvQqX+&@cClg-)y~NE*3k*sg zhOG)}e2>(sHV0HAUUD2E(Xs~C=m~OAr-Hyf#SkDTTTtq|HhXRDsfX@fY9{u|cpCE| zM2+Zu9zO2su!TU9=qh@R6UAy9MFw!i?nQ?sud`?CCInkbflt~A zHXRuy1%jMSUs<}o{f*Bf?U2N5#%a%;5EOJz9vSSuVSR+(iYv*0Z zVuub++IelP2GL5tG`mHhj#z#yDNU^gG-^p-Ra{aC=#)T4vaE@fDfxjQ!Wfa38ut{i zlEtopFF6qr?})>}lq)Bqhbv(wH*R-MQnk!}m$qwc<3B}Qy@G`Fc+-bUDOGG*6`cGj zl*>&RG?-~S;J9&27H#&o#)?-wEN3!J!y!C%>y<&sh9J$RdCTd}#?()@=XOQu&! z^U8c{5g7ve@H`*q>Au5M?8(}bFt**D@0T_tmK^_NeSZp$Xh3{Zzud}$UC@f$ zQjPDY`mcX*Uj=A&7-z>UC)_5*SmXdP;_#Pjy-jG0?#&8uo96g?2K;FTqfMLI$cXLv zd_-n2he%RwDT3*G(_xc3pfFTRFLu7uh|w02P|>@qVq$=wU6~$uYCJhs|J6l7b+d2Y z+QtdPoHfcG%rrOj_;D)kQ|A+1Bu>t`GstxusrNFbF;AKp7Sl=3a#=!=BI}l|FkVW9 z9e0R?c(cW~aRe8J1I2Trh^MLKb*V_ngxunpG9%u)2-Y#?RuqhF21omwHpP&^d<`VW zuw+oq-u%9?hZO%&3WdInkVbS@LRBUVf)u=0gM0H4NoTf~vjZ=D<#O#QUwAY|9803yk&xyaWM4&)9 znc<#hzEZAe+0I}PD;s1A=dM@^hOH3d3s7nE~H;e28rgz?%<8oFFQo zJBnbpbAd>OyCIQoPLLTRK?Onu9n~MlQ6Q|FiX~zdOs-6>x1*Yq0pzFlq#Y$r8)?0O zAdq*OLyGgS$N$5-8~2BSxFgqQH=HFZC@%Hcqgz`3cADiXUn(xsj;`KrDP^Fl5z#EK zYf8$4Rj?G&xt6=?v8BDKcs!rrX6iN+995|lO?zfMY6$NzW?bT0ZCs|Ojn{vTSEO*P z=0^NIfozxFj-YUPZWF;v3-G#8Bki)I{+?H0D{@gZ z`*M2PJvX$VLJ31oh-n@sDvrYh#p`Aa6#wq_^INVT)A0V`Z9zUo3{KjbT$aQ5;pj6S ztEF{tzAc8ZIw(h_%;x5drhul>W{dLjJA**ub_}&!_}Sd6KUJa}oULV+-eVoWDtoE1 zH8DjgtEd)u$ASXH%y-SVq1Af}kR_wu;1)uE`XX#2!XdpimzH`j8z}nAB^rjDpte;A zBXS_ld~H}VF2+Pt(Q6*;a2E+%Wshs_fBRW7`B)-8+sZqvQpyW^L3M3 zSEs0nQ{qzI`Fim4i||W1t~XAqeOO6y(+2@!*>!SHX*mt&1gd=^=7;?Q*OS}~3=o1O z^$4;C1ZlgFhY;9|BsS-(OD>QqtNOco%Q$#$FVlcJNxi?lf7SAbO{A3BA{CyfiSRL{ zJI02Yb~-l4jpY}d?h37j@v6ioUue!x0qI*PvS?K{7%a^d5AyO9oC1n*qaKrUIDCSR zPkA?4xLhaBhR@F-VqIoC3)1X_{BX0BMN7gh43F z?TO+1Dr#Uj&5Cmp2=h9jopP^M33yfZ28HuL1%^@XBS!hs1H-k>b57fFjhUU?oJ^3H z;9q|mI=*K|%hQw_P!d_fySvSj5#{3g%6BqUF^C-Cc?AQfDh<#_YTJm59`DjR$Hj)= zEi5E0+CxkzhB3zt8U?;8fiT$2r;D9h)MxSZ2l3O*V=!68RdxA}0cj$st^cuij4OR& z-GbMBAe`%AOi_1OO5Llw+jHKGvbfteR0;e&hPm_lXX%m#8wSFgZujG##0rgAfwQhu zoP*4gzuu8s_{4nZB+#pkJ}J;;a$bhL8JZ_SO%)n?4mVz6nha40IVv6@cp`_0IOkDSoY|a(WCZJgWJ(kLI;Rk{5H zYFZ->*K+`y##y_$m^`wsE=YlEQ|Iy0#MY6X!-UM!h}XfZW{ipAkyL$(5i#jOrUeTb z-HcI8J|CH$pI~iW{~DG+2o6^rpzd8zmB1PTW_Xw8a#?S!JDJoF%bo?;PtK87nd_it{!QY1y5#BJG zDc#?^UaV$0u=_|(X{MPy@4ZNBH$trZg5VEsX)gyW!?yrOLyc@8q02iLOx%|$HawN0 z+1_Crrd?^WQoF z#VnYT1HLS9??;W7%n(uhUG@k$?omQg9ZGIU7y=HvN)B*9;w#t(F@P#J4w-24vGQPr}Rq?_Wim-;CY(7@5DO z!hqXK^8#PKh^3Y-S3}-FaBOrUe@TT#OJQ`IiaZWJzz+g{s_|H=!k@T#88p4z=jQ%}JnGup=c(b7 zE#T3IH(s2QNFM%#&VXO()<{aXr#|l^-qo;5JYk?nd;Z&1NxJQCf4>^FKbjv>eA#`( z(DaGW>D6ZWeiLp*35Ph?aT8W_@AK!jR7D?f!u5ll)|Icjx@FVh!Huu!Yx4a}<^IJY zdgQoKe(`PlNwdkp9@J?5-z`;_O2!YIY1@4pCt9z6tG- +#include //-- to stretch th first column to entirely show the names #include -namespace camitk { +using namespace camitk; + //----------------------- constructor ------------------------ -FrameExplorer::FrameExplorer() : Viewer("Frame Explorer") { +FrameExplorer::FrameExplorer(QString name) : Viewer( name) { + setLayout(Viewer::DOCKED); explorerTree = nullptr; } -//----------------------- getInstance ------------------------ -FrameExplorer* FrameExplorer::getInstance() { - // static instantiation, static method variable - static FrameExplorer* frameExplorer = nullptr; - if (!frameExplorer) { - frameExplorer = new FrameExplorer(); - } - - return frameExplorer; -} - //----------------------- getWidget ------------------------ -QWidget* FrameExplorer::getWidget(QWidget* parent) { +QWidget* FrameExplorer::getWidget() { if (explorerTree == nullptr) { //-- create the explorer tree - explorerTree = new QTreeWidget(parent); + explorerTree = new QTreeWidget(); // For explorerTree to emit the customMenu.. signal explorerTree->setContextMenuPolicy(Qt::CustomContextMenu); // headers @@ -175,6 +167,3 @@ void FrameExplorer::selectionChanged() { // refresh! refresh(this); } - -} - diff --git a/sdk/libraries/core/viewer/FrameExplorer.h b/sdk/viewers/frameexplorer/FrameExplorer.h similarity index 66% rename from sdk/libraries/core/viewer/FrameExplorer.h rename to sdk/viewers/frameexplorer/FrameExplorer.h index 48b9154f..f0e292b2 100644 --- a/sdk/libraries/core/viewer/FrameExplorer.h +++ b/sdk/viewers/frameexplorer/FrameExplorer.h @@ -27,32 +27,29 @@ #ifndef FRAMEEXPLORER_H #define FRAMEEXPLORER_H +#include "FrameExplorerAPI.h" + // -- Core stuff -#include "Viewer.h" +#include // -- QT stuff #include #include namespace camitk { -// -- Core stuff classes -class InterfaceFrame; + // -- Core stuff classes + class InterfaceFrame; +} /** * @ingroup group_sdk_libraries_core_viewer * * @brief - * Explorer window, display the list of all data currently opened in the application. - * All objects are displayed in a QListView widget and can be selected + * Frame Explorer window, display the hierachy of the frames of all the data currently opened in the application. + * All frames are displayed in a QListView widget and can be selected * (single/multiple selection is available). - * - * \image html libraries/explorer.png "The component explorer viewer." - * - * This viewer also manages a singleton (THE CamiTK explorer). See getInstance() for more information. - * You do not have to use it, but it is convienent (and sometimes preferable) to use this instance - * instead of creating your own one. */ -class CAMITK_API FrameExplorer : public Viewer { +class FRAMEEXPLORER_API FrameExplorer : public camitk::Viewer { Q_OBJECT public: @@ -60,32 +57,26 @@ public: */ ///@{ /** Construtor */ - FrameExplorer(); + Q_INVOKABLE FrameExplorer(QString); /** Destructor */ ~FrameExplorer() override = default; - /// returns the unique instance of ActionViewer - static FrameExplorer* getInstance(); - /// @} - /** @name Inherited from Viewer */ ///@{ /// returns the number of Component that are displayed by this viewer unsigned int numberOfViewedComponent() override; - /// refresh the explorer (can be interesting to know which other viewer is calling this) + /// refresh the frame explorer (can be interesting to know which other viewer is calling this) void refresh(Viewer* whoIsAsking = nullptr) override; - /// get the explorer widget (QTreeWidget). @param parent the parent widget for the viewer widget - QWidget* getWidget(QWidget* parent) override; + /// get the frame explorer widget (QTreeWidget) + QWidget* getWidget() override; - /// get the explorer preference widget (widget where all preferences can be modified). @param parent the parent widget for the preference widget + /// get the frame explorer preference widget (widget where all preferences can be modified). @param parent the parent widget for the preference widget virtual QWidget* getPreferenceWidget(QWidget* parent); -public slots : - private slots : /// slot called whenever the selection changed in the explorer @@ -96,15 +87,15 @@ private: /// @name QTreeWidget and QTreeWidgetItem management ///@{ /// instantiate a new QTreeWidgetItem using names and properties from the InterfaceNode, and using parent - QTreeWidgetItem* getNewItem(QTreeWidgetItem* parent, Component*); + QTreeWidgetItem* getNewItem(QTreeWidgetItem* parent, camitk::Component*); /// recursively add the Component in the tree explorer and return the QTreeWidgetItem of the InterfaceNode - QTreeWidgetItem* add(QTreeWidgetItem*, Component*); + QTreeWidgetItem* add(QTreeWidgetItem*, camitk::Component*); /** Add the given Component to the explorer (at top level) and automatically create children Component items. * @param comp The Component to add in the tree view. */ - void add(Component* comp); + void add(camitk::Component* comp); /// clear the tree explorer void remove(); @@ -116,7 +107,4 @@ private: }; -} - - #endif diff --git a/sdk/viewers/frameexplorer/FrameExplorerAPI.h b/sdk/viewers/frameexplorer/FrameExplorerAPI.h new file mode 100644 index 00000000..1c53bd30 --- /dev/null +++ b/sdk/viewers/frameexplorer/FrameExplorerAPI.h @@ -0,0 +1,59 @@ +/***************************************************************************** +* $CAMITK_LICENCE_BEGIN$ +* +* CamiTK - Computer Assisted Medical Intervention ToolKit +* (c) 2001-2018 Univ. Grenoble Alpes, CNRS, TIMC-IMAG UMR 5525 (GMCAO) +* +* Visit http://camitk.imag.fr for more information +* +* This file is part of CamiTK. +* +* CamiTK is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License version 3 +* only, as published by the Free Software Foundation. +* +* CamiTK is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Lesser General Public License version 3 for more details. +* +* You should have received a copy of the GNU Lesser General Public License +* version 3 along with CamiTK. If not, see . +* +* $CAMITK_LICENCE_END$ +****************************************************************************/ + +// ----- FRAMEEXPLORER_API_H.h +#ifndef FRAMEEXPLORER_API_H +#define FRAMEEXPLORER_API_H + +// ----------------------------------------------------------------------- +// +// FRAMEEXPLORER_API +// +// ----------------------------------------------------------------------- + +// The following ifdef block is the standard way of creating macros which make exporting +// from a DLL simpler. All files within this DLL are compiled with the COMPILE_FRAMEEXPLORER_API +// flag defined on the command line. this symbol should not be defined on any project +// that uses this DLL. This way any other project whose source files include this file see +// FRAMEEXPLORER_API functions as being imported from a DLL, wheras this DLL sees symbols +// defined with this macro as being exported. + +#if defined(_WIN32) // MSVC and mingw + +#ifdef COMPILE_FRAMEEXPLORER_API +#define FRAMEEXPLORER_API __declspec(dllexport) +#else +#define FRAMEEXPLORER_API __declspec(dllimport) +#endif // COMPILE_FRAMEEXPLORER_API + +#else // for all other platforms FRAMEEXPLORER_API is defined to be "nothing" + +#ifndef FRAMEEXPLORER_API +#define FRAMEEXPLORER_API +#endif // FRAMEEXPLORER_API + +#endif // MSVC and mingw + +#endif // FRAMEEXPLORER_API_H \ No newline at end of file diff --git a/sdk/viewers/frameexplorer/FrameExplorerExtension.cpp b/sdk/viewers/frameexplorer/FrameExplorerExtension.cpp new file mode 100644 index 00000000..6865b7aa --- /dev/null +++ b/sdk/viewers/frameexplorer/FrameExplorerExtension.cpp @@ -0,0 +1,36 @@ +/***************************************************************************** + * $CAMITK_LICENCE_BEGIN$ + * + * CamiTK - Computer Assisted Medical Intervention ToolKit + * (c) 2001-2018 Univ. Grenoble Alpes, CNRS, TIMC-IMAG UMR 5525 (GMCAO) + * + * Visit http://camitk.imag.fr for more information + * + * This file is part of CamiTK. + * + * CamiTK is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * CamiTK is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with CamiTK. If not, see . + * + * $CAMITK_LICENCE_END$ + ****************************************************************************/ + + +#include "FrameExplorerExtension.h" + +// include generated actions headers +#include "FrameExplorer.h" + +// --------------- getViewers ------------------- +void FrameExplorerExtension::init() { + registerDefaultViewer(FrameExplorer); +} + diff --git a/sdk/viewers/frameexplorer/FrameExplorerExtension.h b/sdk/viewers/frameexplorer/FrameExplorerExtension.h new file mode 100644 index 00000000..2462ced5 --- /dev/null +++ b/sdk/viewers/frameexplorer/FrameExplorerExtension.h @@ -0,0 +1,64 @@ +/***************************************************************************** + * $CAMITK_LICENCE_BEGIN$ + * + * CamiTK - Computer Assisted Medical Intervention ToolKit + * (c) 2001-2018 Univ. Grenoble Alpes, CNRS, TIMC-IMAG UMR 5525 (GMCAO) + * + * Visit http://camitk.imag.fr for more information + * + * This file is part of CamiTK. + * + * CamiTK is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * CamiTK is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with CamiTK. If not, see . + * + * $CAMITK_LICENCE_END$ + ****************************************************************************/ + + +#ifndef FRAMEEXPLOREREXTENSION_H +#define FRAMEEXPLOREREXTENSION_H + +#include "FrameExplorerAPI.h" + +//-- from CamiTK Core +#include + +class FRAMEEXPLORER_API FrameExplorerExtension : public camitk::ViewerExtension { + Q_OBJECT + Q_INTERFACES(camitk::ViewerExtension); + Q_PLUGIN_METADATA(IID "fr.imag.camitk.frameexplorerextension.viewer.frameexplorerextension") + +public: + /// Constructor + FrameExplorerExtension() : ViewerExtension() {}; + + /// Destructor + virtual ~FrameExplorerExtension() = default; + + /// Method returning the action extension name + virtual QString getName() { + return "Frame Explorer Extension"; + }; + + /// Method returning the action extension descrption + virtual QString getDescription() { + return "An extension for the frame explorer"; + }; + + /// initialize all the actions + virtual void init(); + +}; + +#endif // FRAMEEXPLOREREXTENSION_H + + diff --git a/sdk/viewers/interactivegeometryviewer/CMakeLists.txt b/sdk/viewers/interactivegeometryviewer/CMakeLists.txt new file mode 100644 index 00000000..79072986 --- /dev/null +++ b/sdk/viewers/interactivegeometryviewer/CMakeLists.txt @@ -0,0 +1,8 @@ +# Call CamiTK CMake Macro to define the action +camitk_extension(VIEWER_EXTENSION + CEP_NAME SDK + DEFINES COMPILE_INTERACTIVEGEOMETRYVIEWER_API + DESCRIPTION "An extension for the viewer that display GUI action" + INSTALL_ALL_HEADERS +) + diff --git a/sdk/viewers/interactivegeometryviewer/InteractiveGeometryViewer.cpp b/sdk/viewers/interactivegeometryviewer/InteractiveGeometryViewer.cpp new file mode 100644 index 00000000..314a6f56 --- /dev/null +++ b/sdk/viewers/interactivegeometryviewer/InteractiveGeometryViewer.cpp @@ -0,0 +1,42 @@ +/***************************************************************************** + * $CAMITK_LICENCE_BEGIN$ + * + * CamiTK - Computer Assisted Medical Intervention ToolKit + * (c) 2001-2018 Univ. Grenoble Alpes, CNRS, TIMC-IMAG UMR 5525 (GMCAO) + * + * Visit http://camitk.imag.fr for more information + * + * This file is part of CamiTK. + * + * CamiTK is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * CamiTK is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with CamiTK. If not, see . + * + * $CAMITK_LICENCE_END$ + ****************************************************************************/ + +// -- Core stuff +#include "InteractiveGeometryViewer.h" + +using namespace camitk; + +// -------------------- Constructor -------------------- +InteractiveGeometryViewer::InteractiveGeometryViewer(QString name) : InteractiveViewer(name, InteractiveViewer::GEOMETRY_VIEWER) { + if (name == "3DViewer") { + // Axial Viewer + setLayout(Viewer::EMBEDDED); + } +} +/* CLEANUP + +// -------------------- Destructor -------------------- +InteractiveGeometryViewer::~InteractiveGeometryViewer() { +}*/ diff --git a/sdk/viewers/interactivegeometryviewer/InteractiveGeometryViewer.h b/sdk/viewers/interactivegeometryviewer/InteractiveGeometryViewer.h new file mode 100644 index 00000000..0f434b71 --- /dev/null +++ b/sdk/viewers/interactivegeometryviewer/InteractiveGeometryViewer.h @@ -0,0 +1,65 @@ +/***************************************************************************** + * $CAMITK_LICENCE_BEGIN$ + * + * CamiTK - Computer Assisted Medical Intervention ToolKit + * (c) 2001-2018 Univ. Grenoble Alpes, CNRS, TIMC-IMAG UMR 5525 (GMCAO) + * + * Visit http://camitk.imag.fr for more information + * + * This file is part of CamiTK. + * + * CamiTK is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * CamiTK is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with CamiTK. If not, see . + * + * $CAMITK_LICENCE_END$ + ****************************************************************************/ + + +#ifndef INTERACTIVEGEOMETRYVIEWER_H +#define INTERACTIVEGEOMETRYVIEWER_H + +#include "InteractiveGeometryViewerAPI.h" + +// -- Core stuff +#include + +/** + * @ingroup group_sdk_libraries_core_viewer + * + * @brief + * The views manager. + * + * MedicalImageViewer is a viewer that can display from 1 to 4 InteractiveViewer that represents + * the axial, coronal, sagittal and 3D view of the same medical image. + * The views used the default InteractiveViewers singletons. + * + * This class follow the "singleton" design pattern, see getInstance(). + * Singleton is enforced/recommanded so that actions can directly use the show*Viewer() methods + * + * \image html libraries/medicalimageviewer.png "The medical image viewer" + * + */ +class INTERACTIVEGEOMETRYVIEWER_API InteractiveGeometryViewer : public camitk::InteractiveViewer { + Q_OBJECT + +public: + + Q_INVOKABLE InteractiveGeometryViewer(QString name); + + /** destructor */ + ~InteractiveGeometryViewer() = default; + +}; + + +#endif // INTERACTIVEGEOMETRYVIEWER_H + diff --git a/sdk/viewers/interactivegeometryviewer/InteractiveGeometryViewerAPI.h b/sdk/viewers/interactivegeometryviewer/InteractiveGeometryViewerAPI.h new file mode 100644 index 00000000..dfbfe450 --- /dev/null +++ b/sdk/viewers/interactivegeometryviewer/InteractiveGeometryViewerAPI.h @@ -0,0 +1,59 @@ +/***************************************************************************** +* $CAMITK_LICENCE_BEGIN$ +* +* CamiTK - Computer Assisted Medical Intervention ToolKit +* (c) 2001-2018 Univ. Grenoble Alpes, CNRS, TIMC-IMAG UMR 5525 (GMCAO) +* +* Visit http://camitk.imag.fr for more information +* +* This file is part of CamiTK. +* +* CamiTK is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License version 3 +* only, as published by the Free Software Foundation. +* +* CamiTK is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Lesser General Public License version 3 for more details. +* +* You should have received a copy of the GNU Lesser General Public License +* version 3 along with CamiTK. If not, see . +* +* $CAMITK_LICENCE_END$ +****************************************************************************/ + +// ----- INTERACTIVEGEOMETRYVIEWER_API_H +#ifndef INTERACTIVEGEOMETRYVIEWER_API_H +#define INTERACTIVEGEOMETRYVIEWER_API_H + +// ----------------------------------------------------------------------- +// +// INTERACTIVEGEOMETRYVIEWER_API +// +// ----------------------------------------------------------------------- + +// The following ifdef block is the standard way of creating macros which make exporting +// from a DLL simpler. All files within this DLL are compiled with the COMPILE_INTERACTIVEGEOMETRYVIEWER_API +// flag defined on the command line. this symbol should not be defined on any project +// that uses this DLL. This way any other project whose source files include this file see +// INTERACTIVEGEOMETRYVIEWER_API functions as being imported from a DLL, wheras this DLL sees symbols +// defined with this macro as being exported. + +#if defined(_WIN32) // MSVC and mingw + +#ifdef COMPILE_INTERACTIVEGEOMETRYVIEWER_API +#define INTERACTIVEGEOMETRYVIEWER_API __declspec(dllexport) +#else +#define INTERACTIVEGEOMETRYVIEWER_API __declspec(dllimport) +#endif // COMPILE_INTERACTIVEGEOMETRYVIEWER_API + +#else // for all other platforms INTERACTIVEGEOMETRYVIEWER_API is defined to be "nothing" + +#ifndef INTERACTIVEGEOMETRYVIEWER_API +#define INTERACTIVEGEOMETRYVIEWER_API +#endif // INTERACTIVEGEOMETRYVIEWER_API + +#endif // MSVC and mingw + +#endif // INTERACTIVEGEOMETRYVIEWER_API_H diff --git a/sdk/viewers/interactivegeometryviewer/InteractiveGeometryViewerExtension.cpp b/sdk/viewers/interactivegeometryviewer/InteractiveGeometryViewerExtension.cpp new file mode 100644 index 00000000..5b295e49 --- /dev/null +++ b/sdk/viewers/interactivegeometryviewer/InteractiveGeometryViewerExtension.cpp @@ -0,0 +1,36 @@ +/***************************************************************************** + * $CAMITK_LICENCE_BEGIN$ + * + * CamiTK - Computer Assisted Medical Intervention ToolKit + * (c) 2001-2018 Univ. Grenoble Alpes, CNRS, TIMC-IMAG UMR 5525 (GMCAO) + * + * Visit http://camitk.imag.fr for more information + * + * This file is part of CamiTK. + * + * CamiTK is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * CamiTK is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with CamiTK. If not, see . + * + * $CAMITK_LICENCE_END$ + ****************************************************************************/ + + +#include "InteractiveGeometryViewerExtension.h" + +// include generated actions headers +#include "InteractiveGeometryViewer.h" + +// --------------- getViewers ------------------- +void InteractiveGeometryViewerExtension::init() { + registerNewViewer(InteractiveGeometryViewer, "3DViewer"); +} + diff --git a/sdk/viewers/interactivegeometryviewer/InteractiveGeometryViewerExtension.h b/sdk/viewers/interactivegeometryviewer/InteractiveGeometryViewerExtension.h new file mode 100644 index 00000000..b189ace7 --- /dev/null +++ b/sdk/viewers/interactivegeometryviewer/InteractiveGeometryViewerExtension.h @@ -0,0 +1,64 @@ +/***************************************************************************** + * $CAMITK_LICENCE_BEGIN$ + * + * CamiTK - Computer Assisted Medical Intervention ToolKit + * (c) 2001-2018 Univ. Grenoble Alpes, CNRS, TIMC-IMAG UMR 5525 (GMCAO) + * + * Visit http://camitk.imag.fr for more information + * + * This file is part of CamiTK. + * + * CamiTK is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * CamiTK is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with CamiTK. If not, see . + * + * $CAMITK_LICENCE_END$ + ****************************************************************************/ + + +#ifndef INTERACTIVEGEOMETRYVIEWEREXTENSION_H +#define INTERACTIVEGEOMETRYVIEWEREXTENSION_H + +#include "InteractiveGeometryViewerAPI.h" + +//-- from CamiTK Core +#include + +class INTERACTIVEGEOMETRYVIEWER_API InteractiveGeometryViewerExtension : public camitk::ViewerExtension { + Q_OBJECT + Q_INTERFACES(camitk::ViewerExtension); + Q_PLUGIN_METADATA(IID "fr.imag.camitk.interactivegeometryviewerextension.viewer.interactivegeometryviewerextension") + +public: + /// Constructor + InteractiveGeometryViewerExtension() : camitk::ViewerExtension() {}; + + /// Destructor + virtual ~InteractiveGeometryViewerExtension() = default; + + /// Method returning the action extension name + virtual QString getName() { + return "Interactive Geometry Viewer Extension"; + }; + + /// Method returning the action extension descrption + virtual QString getDescription() { + return "An extension for the interactive geometry viewer"; + }; + + /// initialize all the actions + virtual void init(); + +}; + +#endif // INTERACTIVEGEOMETRYVIEWEREXTENSION_H + + diff --git a/sdk/viewers/interactivesliceviewer/CMakeLists.txt b/sdk/viewers/interactivesliceviewer/CMakeLists.txt new file mode 100644 index 00000000..39328f7a --- /dev/null +++ b/sdk/viewers/interactivesliceviewer/CMakeLists.txt @@ -0,0 +1,8 @@ +# Call CamiTK CMake Macro to define the action +camitk_extension(VIEWER_EXTENSION + CEP_NAME SDK + DEFINES COMPILE_INTERACTIVESLICEVIEWER_API + DESCRIPTION "An extension for the viewer that display GUI action" + INSTALL_ALL_HEADERS +) + diff --git a/sdk/viewers/interactivesliceviewer/InteractiveSliceViewer.cpp b/sdk/viewers/interactivesliceviewer/InteractiveSliceViewer.cpp new file mode 100644 index 00000000..f3c0115b --- /dev/null +++ b/sdk/viewers/interactivesliceviewer/InteractiveSliceViewer.cpp @@ -0,0 +1,78 @@ +/***************************************************************************** + * $CAMITK_LICENCE_BEGIN$ + * + * CamiTK - Computer Assisted Medical Intervention ToolKit + * (c) 2001-2018 Univ. Grenoble Alpes, CNRS, TIMC-IMAG UMR 5525 (GMCAO) + * + * Visit http://camitk.imag.fr for more information + * + * This file is part of CamiTK. + * + * CamiTK is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * CamiTK is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with CamiTK. If not, see . + * + * $CAMITK_LICENCE_END$ + ****************************************************************************/ + +// -- Core stuff +#include "InteractiveSliceViewer.h" +#include +#include + +using namespace camitk; + +// -------------------- Constructor -------------------- +InteractiveSliceViewer::InteractiveSliceViewer(QString name) : InteractiveViewer(name, InteractiveViewer::SLICE_VIEWER) { + if (name == "axialViewer") { + // Axial Viewer + setLayout(Viewer::EMBEDDED); + getRendererWidget()->setCameraOrientation(RendererWidget::RIGHT_DOWN); + QString letters[4] = { QString("R"), QString("L"), QString("A"), QString("P") }; + getRendererWidget()->setOrientationDecorationsLetters(letters); + toggleOrientationDecorations(true); + getRendererWidget()->getActiveCamera()->ParallelProjectionOn(); + } + else { + if (name == "coronalViewer") { + // Coronal Viewer + setLayout(Viewer::EMBEDDED); + getRendererWidget()->setCameraOrientation(RendererWidget::LEFT_BACK); + QString letters[4] = { QString("R"), QString("L"), QString("S"), QString("I") }; + getRendererWidget()->setOrientationDecorationsLetters(letters); + toggleOrientationDecorations(true); + getRendererWidget()->getActiveCamera()->ParallelProjectionOn(); + } + else { + if (name == "sagittalViewer") { + // Sagittal Viewer + setLayout(Viewer::EMBEDDED); + getRendererWidget()->setCameraOrientation(RendererWidget::BACK_DOWN); + QString letters[4] = { QString("A"), QString("P"), QString("S"), QString("I") }; + getRendererWidget()->setOrientationDecorationsLetters(letters); + toggleOrientationDecorations(true); + getRendererWidget()->getActiveCamera()->ParallelProjectionOn(); + } + else { + if (name == "arbitraryViewer") { + // Arbitrary Viewer + setLayout(Viewer::EMBEDDED); + toggleOrientationDecorations(false); + } + } + } + } +} + + +// -------------------- Destructor -------------------- +InteractiveSliceViewer::~InteractiveSliceViewer() { +} diff --git a/sdk/viewers/interactivesliceviewer/InteractiveSliceViewer.h b/sdk/viewers/interactivesliceviewer/InteractiveSliceViewer.h new file mode 100644 index 00000000..bf0a5625 --- /dev/null +++ b/sdk/viewers/interactivesliceviewer/InteractiveSliceViewer.h @@ -0,0 +1,71 @@ +/***************************************************************************** + * $CAMITK_LICENCE_BEGIN$ + * + * CamiTK - Computer Assisted Medical Intervention ToolKit + * (c) 2001-2018 Univ. Grenoble Alpes, CNRS, TIMC-IMAG UMR 5525 (GMCAO) + * + * Visit http://camitk.imag.fr for more information + * + * This file is part of CamiTK. + * + * CamiTK is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * CamiTK is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with CamiTK. If not, see . + * + * $CAMITK_LICENCE_END$ + ****************************************************************************/ + + +#ifndef INTERACTIVESLICEVIEWER_H +#define INTERACTIVESLICEVIEWER_H + +#include "InteractiveSliceViewerAPI.h" + +// -- Core stuff +#include + +// -- QT stuff +#include +#include +#include +#include + +/** + * @ingroup group_sdk_libraries_core_viewer + * + * @brief + * The views manager. + * + * MedicalImageViewer is a viewer that can display from 1 to 4 InteractiveViewer that represents + * the axial, coronal, sagittal and 3D view of the same medical image. + * The views used the default InteractiveViewers singletons. + * + * This class follow the "singleton" design pattern, see getInstance(). + * Singleton is enforced/recommanded so that actions can directly use the show*Viewer() methods + * + * \image html libraries/medicalimageviewer.png "The medical image viewer" + * + */ +class INTERACTIVESLICEVIEWER_API InteractiveSliceViewer : public camitk::InteractiveViewer { + Q_OBJECT + +public: + + Q_INVOKABLE InteractiveSliceViewer(QString); + + /** destructor */ + ~InteractiveSliceViewer() override; + +}; + + +#endif // INTERACTIVESLICEVIEWER_H + diff --git a/sdk/viewers/interactivesliceviewer/InteractiveSliceViewerAPI.h b/sdk/viewers/interactivesliceviewer/InteractiveSliceViewerAPI.h new file mode 100644 index 00000000..55ac68ab --- /dev/null +++ b/sdk/viewers/interactivesliceviewer/InteractiveSliceViewerAPI.h @@ -0,0 +1,59 @@ +/***************************************************************************** +* $CAMITK_LICENCE_BEGIN$ +* +* CamiTK - Computer Assisted Medical Intervention ToolKit +* (c) 2001-2018 Univ. Grenoble Alpes, CNRS, TIMC-IMAG UMR 5525 (GMCAO) +* +* Visit http://camitk.imag.fr for more information +* +* This file is part of CamiTK. +* +* CamiTK is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License version 3 +* only, as published by the Free Software Foundation. +* +* CamiTK is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Lesser General Public License version 3 for more details. +* +* You should have received a copy of the GNU Lesser General Public License +* version 3 along with CamiTK. If not, see . +* +* $CAMITK_LICENCE_END$ +****************************************************************************/ + +// ----- MEDICALIMAGEVIEWER_API_H.h +#ifndef INTERACTIVESLICEVIEWER_API_H +#define INTERACTIVESLICEVIEWER_API_H + +// ----------------------------------------------------------------------- +// +// INTERACTIVESLICEVIEWER_API_API +// +// ----------------------------------------------------------------------- + +// The following ifdef block is the standard way of creating macros which make exporting +// from a DLL simpler. All files within this DLL are compiled with the COMPILE_INTERACTIVESLICEVIEWER_API +// flag defined on the command line. this symbol should not be defined on any project +// that uses this DLL. This way any other project whose source files include this file see +// INTERACTIVESLICEVIEWER_API functions as being imported from a DLL, wheras this DLL sees symbols +// defined with this macro as being exported. + +#if defined(_WIN32) // MSVC and mingw + +#ifdef COMPILE_INTERACTIVESLICEVIEWER_API +#define INTERACTIVESLICEVIEWER_API __declspec(dllexport) +#else +#define INTERACTIVESLICEVIEWER_API __declspec(dllimport) +#endif // COMPILE_INTERACTIVESLICEVIEWER_API + +#else // for all other platforms INTERACTIVESLICEVIEWER_API is defined to be "nothing" + +#ifndef INTERACTIVESLICEVIEWER_API +#define INTERACTIVESLICEVIEWER_API +#endif // INTERACTIVESLICEVIEWER_API + +#endif // MSVC and mingw + +#endif // INTERACTIVESLICEVIEWER_API_H diff --git a/sdk/viewers/interactivesliceviewer/InteractiveSliceViewerExtension.cpp b/sdk/viewers/interactivesliceviewer/InteractiveSliceViewerExtension.cpp new file mode 100644 index 00000000..d09f8da7 --- /dev/null +++ b/sdk/viewers/interactivesliceviewer/InteractiveSliceViewerExtension.cpp @@ -0,0 +1,39 @@ +/***************************************************************************** + * $CAMITK_LICENCE_BEGIN$ + * + * CamiTK - Computer Assisted Medical Intervention ToolKit + * (c) 2001-2018 Univ. Grenoble Alpes, CNRS, TIMC-IMAG UMR 5525 (GMCAO) + * + * Visit http://camitk.imag.fr for more information + * + * This file is part of CamiTK. + * + * CamiTK is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * CamiTK is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with CamiTK. If not, see . + * + * $CAMITK_LICENCE_END$ + ****************************************************************************/ + + +#include "InteractiveSliceViewerExtension.h" + +// include generated actions headers +#include "InteractiveSliceViewer.h" + +// --------------- getViewers ------------------- +void InteractiveSliceViewerExtension::init() { + registerNewViewer(InteractiveSliceViewer, "axialViewer"); + registerNewViewer(InteractiveSliceViewer, "coronalViewer"); + registerNewViewer(InteractiveSliceViewer, "sagittalViewer"); + registerNewViewer(InteractiveSliceViewer, "arbitraryViewer"); +} + diff --git a/sdk/viewers/interactivesliceviewer/InteractiveSliceViewerExtension.h b/sdk/viewers/interactivesliceviewer/InteractiveSliceViewerExtension.h new file mode 100644 index 00000000..f08f5667 --- /dev/null +++ b/sdk/viewers/interactivesliceviewer/InteractiveSliceViewerExtension.h @@ -0,0 +1,64 @@ +/***************************************************************************** + * $CAMITK_LICENCE_BEGIN$ + * + * CamiTK - Computer Assisted Medical Intervention ToolKit + * (c) 2001-2018 Univ. Grenoble Alpes, CNRS, TIMC-IMAG UMR 5525 (GMCAO) + * + * Visit http://camitk.imag.fr for more information + * + * This file is part of CamiTK. + * + * CamiTK is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * CamiTK is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with CamiTK. If not, see . + * + * $CAMITK_LICENCE_END$ + ****************************************************************************/ + + +#ifndef INTERACTIVESLICEVIEWEREXTENSION_H +#define INTERACTIVESLICEVIEWEREXTENSION_H + +#include "InteractiveSliceViewerAPI.h" + +//-- from CamiTK Core +#include + +class INTERACTIVESLICEVIEWER_API InteractiveSliceViewerExtension : public camitk::ViewerExtension { + Q_OBJECT + Q_INTERFACES(camitk::ViewerExtension); + Q_PLUGIN_METADATA(IID "fr.imag.camitk.interactivesliceviewerextension.viewer.interactivesliceviewerextension") + +public: + /// Constructor + InteractiveSliceViewerExtension() : ViewerExtension() {}; + + /// Destructor + virtual ~InteractiveSliceViewerExtension() = default; + + /// Method returning the action extension name + virtual QString getName() { + return "Interactive Slice Viewer Extension"; + }; + + /// Method returning the action extension descrption + virtual QString getDescription() { + return "An extension for the interactive slice viewer"; + }; + + /// initialize all the actions + virtual void init(); + +}; + +#endif // INTERACTIVESLICEVIEWEREXTENSION_H + + diff --git a/sdk/viewers/medicalimageviewer/CMakeLists.txt b/sdk/viewers/medicalimageviewer/CMakeLists.txt new file mode 100644 index 00000000..eb96dc84 --- /dev/null +++ b/sdk/viewers/medicalimageviewer/CMakeLists.txt @@ -0,0 +1,9 @@ +# Call CamiTK CMake Macro to define the action +camitk_extension(VIEWER_EXTENSION + CEP_NAME SDK + DEFINES COMPILE_MEDICALIMAGEVIEWER_API + NEEDS_VIEWER_EXTENSION interactivesliceviewer interactivegeometryviewer + DESCRIPTION "An extension for the viewer that display GUI action" + INSTALL_ALL_HEADERS +) + diff --git a/sdk/libraries/core/viewer/MedicalImageViewer.cpp b/sdk/viewers/medicalimageviewer/MedicalImageViewer.cpp similarity index 75% rename from sdk/libraries/core/viewer/MedicalImageViewer.cpp rename to sdk/viewers/medicalimageviewer/MedicalImageViewer.cpp index 466a3280..76b46a00 100644 --- a/sdk/libraries/core/viewer/MedicalImageViewer.cpp +++ b/sdk/viewers/medicalimageviewer/MedicalImageViewer.cpp @@ -24,10 +24,10 @@ ****************************************************************************/ // -- Core stuff -#include "Action.h" #include "MedicalImageViewer.h" -#include "InteractiveViewer.h" -#include "Application.h" +#include +#include +#include //-- Qt stuff #include @@ -35,20 +35,11 @@ #include #include -namespace camitk { -MedicalImageViewer* MedicalImageViewer::singleton = nullptr; - -MedicalImageViewer* MedicalImageViewer::getInstance() { - if (!singleton) { - singleton = new MedicalImageViewer(); - } - - return singleton; -} +using namespace camitk; // -------------------- Constructor -------------------- -MedicalImageViewer::MedicalImageViewer() : Viewer("Medical Image Viewer") { +MedicalImageViewer::MedicalImageViewer(QString name) : Viewer(name) { // init view members frame = nullptr; frameLayout = nullptr; @@ -60,14 +51,15 @@ MedicalImageViewer::MedicalImageViewer() : Viewer("Medical Image Viewer") { displayedTopLevelComponents = 0; autoUpdateToolbarVisibility = true; + + /* + setComponents(QStringList() << "ImageComponent" << "MeshComponent"); + */ } // -------------------- Destructor -------------------- MedicalImageViewer::~MedicalImageViewer() { - if (frame) { - delete frame; - } } @@ -93,9 +85,9 @@ void MedicalImageViewer::refresh(Viewer* whoIsAsking) { if (displayedTopLevelComponents != (unsigned) Application::getTopLevelComponents().size()) { // if there the nr of Component changed since last refresh, // and if there is something displayed in the slices viewer, show all view - if (InteractiveViewer::getAxialViewer()->numberOfViewedComponent() > 0 - && InteractiveViewer::getCoronalViewer()->numberOfViewedComponent() > 0 - && InteractiveViewer::getSagittalViewer()->numberOfViewedComponent() > 0) { + if (Application::getViewer("axialViewer")->numberOfViewedComponent() > 0 + && Application::getViewer("coronalViewer")->numberOfViewedComponent() > 0 + && Application::getViewer("sagittalViewer")->numberOfViewedComponent() > 0) { visibleLayout = VIEWER_ALL; } else { @@ -110,9 +102,10 @@ void MedicalImageViewer::refresh(Viewer* whoIsAsking) { } // -------------------- getWidget -------------------- -QWidget* MedicalImageViewer::getWidget(QWidget* parent) { +QWidget* MedicalImageViewer::getWidget() { if (!frame) { - frame = new QFrame(parent); + frame = new QFrame(); + frame->setObjectName("MedicalImageViewer Frame"); frame->setFrameStyle(QFrame::StyledPanel | QFrame::Plain); //-- init layout @@ -129,19 +122,25 @@ QWidget* MedicalImageViewer::getWidget(QWidget* parent) { viewerVisibility.append(VIEWER_ALL); // ALL has to be the end of visible viewers // list of viewer name - viewers.insert(VIEWER_3D, InteractiveViewer::get3DViewer()); - viewers.insert(VIEWER_ARBITRARY, InteractiveViewer::getArbitraryViewer()); - viewers.insert(VIEWER_AXIAL, InteractiveViewer::getAxialViewer()); - viewers.insert(VIEWER_CORONAL, InteractiveViewer::getCoronalViewer()); - viewers.insert(VIEWER_SAGITTAL, InteractiveViewer::getSagittalViewer()); - - topLeftLayout = new QVBoxLayout(); - frameLayout->addLayout(topLeftLayout, 0, 0); - topLeftLayout->addWidget(InteractiveViewer::getAxialViewer()->getWidget(frame)); // equivalent of addWidget(InteractiveViewer::getAxialViewer()->getWidget(frame), 0, 0) = north-west - topLeftLayout->addWidget(InteractiveViewer::getArbitraryViewer()->getWidget(frame)); - frameLayout->addWidget(InteractiveViewer::getCoronalViewer()->getWidget(frame), 1, 0); // north-east - frameLayout->addWidget(InteractiveViewer::getSagittalViewer()->getWidget(frame), 1, 1); // south-west - frameLayout->addWidget(InteractiveViewer::get3DViewer()->getWidget(frame), 0, 1); // south-east + viewers.insert(VIEWER_3D, Application::getViewer("3DViewer")); + viewers.insert(VIEWER_ARBITRARY, Application::getViewer("arbitraryViewer")); + viewers.insert(VIEWER_AXIAL, Application::getViewer("axialViewer")); + viewers.insert(VIEWER_CORONAL, Application::getViewer("coronalViewer")); + viewers.insert(VIEWER_SAGITTAL, Application::getViewer("sagittalViewer")); + + /// the layout for the arbitrary/axial at the top left position of frameLayout + QVBoxLayout* innerLayout = new QVBoxLayout(); + frameLayout->addLayout(innerLayout, 0, 0); // north-west + Application::getViewer("axialViewer")->embedIn(innerLayout); + innerLayout = new QVBoxLayout(); + frameLayout->addLayout(innerLayout, 1, 0); // south-west + Application::getViewer("coronalViewer")->embedIn(innerLayout); + innerLayout = new QVBoxLayout(); + frameLayout->addLayout(innerLayout, 1, 1); // south-east + Application::getViewer("sagittalViewer")->embedIn(innerLayout); + innerLayout = new QVBoxLayout(); + frameLayout->addLayout(innerLayout, 0, 1); // north-east + Application::getViewer("3DViewer")->embedIn(innerLayout); //-- connect foreach (LayoutVisibility v, viewerVisibility) { @@ -159,7 +158,7 @@ QWidget* MedicalImageViewer::getWidget(QWidget* parent) { // ---------------------- getPropertyObject ---------------------------- QObject* MedicalImageViewer::getPropertyObject() { - return InteractiveViewer::get3DViewer()->getPropertyObject(); + return Application::getViewer("3DViewer")->getPropertyObject(); } // -------------------- getMenu -------------------- @@ -211,7 +210,7 @@ void MedicalImageViewer::setVisibleViewer(LayoutVisibility visibleViewer) { updateLayout(); } -// -------------------- setVisibleViewer -------------------- +// -------------------- getVisibleViewer -------------------- MedicalImageViewer::LayoutVisibility MedicalImageViewer::getVisibleViewer() const { return visibleLayout; } @@ -224,18 +223,18 @@ void MedicalImageViewer::updateLayout() { } if (visibleLayout == VIEWER_ALL) { - viewers.value(VIEWER_3D)->getWidget(frame)->show(); - viewers.value(VIEWER_AXIAL)->getWidget(frame)->show(); - viewers.value(VIEWER_CORONAL)->getWidget(frame)->show(); - viewers.value(VIEWER_SAGITTAL)->getWidget(frame)->show(); - viewers.value(VIEWER_ARBITRARY)->getWidget(frame)->hide(); + viewers.value(VIEWER_3D)->setVisible(true); + viewers.value(VIEWER_AXIAL)->setVisible(true); + viewers.value(VIEWER_CORONAL)->setVisible(true); + viewers.value(VIEWER_SAGITTAL)->setVisible(true); + viewers.value(VIEWER_ARBITRARY)->setVisible(false); } else { for (unsigned int i = 0; viewerVisibility[i] != VIEWER_ALL; i++) { - viewers.value(viewerVisibility[i])->getWidget(frame)->hide(); + viewers.value(viewerVisibility[i])->setVisible(false); } - viewers.value(visibleLayout)->getWidget(frame)->show(); + viewers.value(visibleLayout)->setVisible(true); } if (autoUpdateToolbarVisibility) { @@ -269,5 +268,3 @@ void MedicalImageViewer::setToolbarAutoVisibility(bool toolbarAutoVisibility) { setToolBarVisibility(false); } -} - diff --git a/sdk/libraries/core/viewer/MedicalImageViewer.h b/sdk/viewers/medicalimageviewer/MedicalImageViewer.h similarity index 87% rename from sdk/libraries/core/viewer/MedicalImageViewer.h rename to sdk/viewers/medicalimageviewer/MedicalImageViewer.h index 71c540bc..30c02e67 100644 --- a/sdk/libraries/core/viewer/MedicalImageViewer.h +++ b/sdk/viewers/medicalimageviewer/MedicalImageViewer.h @@ -27,9 +27,10 @@ #ifndef MEDICAL_IMAGE_VIEWER_H #define MEDICAL_IMAGE_VIEWER_H +#include "MedicalImageViewerAPI.h" + // -- Core stuff -#include "CamiTKAPI.h" -#include "Viewer.h" +#include // -- QT stuff #include @@ -37,10 +38,6 @@ #include #include -namespace camitk { -// -- Core stuff classes -class InteractiveViewer; - /** * @ingroup group_sdk_libraries_core_viewer * @@ -57,7 +54,7 @@ class InteractiveViewer; * \image html libraries/medicalimageviewer.png "The medical image viewer" * */ -class CAMITK_API MedicalImageViewer : public Viewer { +class MEDICALIMAGEVIEWER_API MedicalImageViewer : public camitk::Viewer { Q_OBJECT public: @@ -71,8 +68,7 @@ public: VIEWER_ARBITRARY ///< Only the arbitrary InteractiveViewer are visible }; - /// get singleton instance - static MedicalImageViewer* getInstance(); + Q_INVOKABLE MedicalImageViewer(QString); /** destructor */ ~MedicalImageViewer() override; @@ -86,8 +82,8 @@ public: /// refresh the view (can be interesting to know which other viewer is calling this) void refresh(Viewer* whoIsAsking = nullptr) override; - /// get the viewer widget. @param parent the parent widget for the viewer widget - QWidget* getWidget(QWidget* parent = nullptr) override; + /// get the viewer widget. + QWidget* getWidget() override; /// get the propertyObject (only the 3D Scene one) QObject* getPropertyObject() override; @@ -118,11 +114,6 @@ public slots: /// called when an internal InteractiveViewers has emitted a selectionChanged signal void synchronizeSelection(); -protected: - - /// Protected construtor (singleton) - MedicalImageViewer(); - private: /// set the current visibility of the different viewer void updateLayout(); @@ -130,9 +121,6 @@ private: /// The main layout QGridLayout* frameLayout; - /// the layout for the arbitrary/axial at the top left position of frameLayout - QVBoxLayout* topLeftLayout; - /// the main widget QFrame* frame; @@ -151,15 +139,10 @@ private: /// number of top-level component that are currently displayed unsigned int displayedTopLevelComponents; - /// the default instance (singleton) - static MedicalImageViewer* singleton; - /// if true, the toolbar automatically updated bool autoUpdateToolbarVisibility; }; -} - #endif diff --git a/sdk/viewers/medicalimageviewer/MedicalImageViewerAPI.h b/sdk/viewers/medicalimageviewer/MedicalImageViewerAPI.h new file mode 100644 index 00000000..04f23d26 --- /dev/null +++ b/sdk/viewers/medicalimageviewer/MedicalImageViewerAPI.h @@ -0,0 +1,59 @@ +/***************************************************************************** +* $CAMITK_LICENCE_BEGIN$ +* +* CamiTK - Computer Assisted Medical Intervention ToolKit +* (c) 2001-2018 Univ. Grenoble Alpes, CNRS, TIMC-IMAG UMR 5525 (GMCAO) +* +* Visit http://camitk.imag.fr for more information +* +* This file is part of CamiTK. +* +* CamiTK is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License version 3 +* only, as published by the Free Software Foundation. +* +* CamiTK is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Lesser General Public License version 3 for more details. +* +* You should have received a copy of the GNU Lesser General Public License +* version 3 along with CamiTK. If not, see . +* +* $CAMITK_LICENCE_END$ +****************************************************************************/ + +// ----- MEDICALIMAGEVIEWER_API_H.h +#ifndef MEDICALIMAGEVIEWER_API_H +#define MEDICALIMAGEVIEWER_API_H + +// ----------------------------------------------------------------------- +// +// MEDICALIMAGEVIEWER_API +// +// ----------------------------------------------------------------------- + +// The following ifdef block is the standard way of creating macros which make exporting +// from a DLL simpler. All files within this DLL are compiled with the COMPILE_MEDICALIMAGEVIEWER_API +// flag defined on the command line. this symbol should not be defined on any project +// that uses this DLL. This way any other project whose source files include this file see +// MEDICALIMAGEVIEWER_API functions as being imported from a DLL, wheras this DLL sees symbols +// defined with this macro as being exported. + +#if defined(_WIN32) // MSVC and mingw + +#ifdef COMPILE_MEDICALIMAGEVIEWER_API +#define MEDICALIMAGEVIEWER_API __declspec(dllexport) +#else +#define MEDICALIMAGEVIEWER_API __declspec(dllimport) +#endif // COMPILE_MEDICALIMAGEVIEWER_API + +#else // for all other platforms MEDICALIMAGEVIEWER_API is defined to be "nothing" + +#ifndef MEDICALIMAGEVIEWER_API +#define MEDICALIMAGEVIEWER_API +#endif // MEDICALIMAGEVIEWER_API + +#endif // MSVC and mingw + +#endif // MEDICALIMAGEVIEWER_API_H \ No newline at end of file diff --git a/sdk/viewers/medicalimageviewer/MedicalImageViewerExtension.cpp b/sdk/viewers/medicalimageviewer/MedicalImageViewerExtension.cpp new file mode 100644 index 00000000..2be66e45 --- /dev/null +++ b/sdk/viewers/medicalimageviewer/MedicalImageViewerExtension.cpp @@ -0,0 +1,36 @@ +/***************************************************************************** + * $CAMITK_LICENCE_BEGIN$ + * + * CamiTK - Computer Assisted Medical Intervention ToolKit + * (c) 2001-2018 Univ. Grenoble Alpes, CNRS, TIMC-IMAG UMR 5525 (GMCAO) + * + * Visit http://camitk.imag.fr for more information + * + * This file is part of CamiTK. + * + * CamiTK is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * CamiTK is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with CamiTK. If not, see . + * + * $CAMITK_LICENCE_END$ + ****************************************************************************/ + + +#include "MedicalImageViewerExtension.h" + +// include generated actions headers +#include "MedicalImageViewer.h" + +// --------------- getViewers ------------------- +void MedicalImageViewerExtension::init() { + registerDefaultViewer(MedicalImageViewer); +} + diff --git a/sdk/viewers/medicalimageviewer/MedicalImageViewerExtension.h b/sdk/viewers/medicalimageviewer/MedicalImageViewerExtension.h new file mode 100644 index 00000000..5cb0a9e5 --- /dev/null +++ b/sdk/viewers/medicalimageviewer/MedicalImageViewerExtension.h @@ -0,0 +1,64 @@ +/***************************************************************************** + * $CAMITK_LICENCE_BEGIN$ + * + * CamiTK - Computer Assisted Medical Intervention ToolKit + * (c) 2001-2018 Univ. Grenoble Alpes, CNRS, TIMC-IMAG UMR 5525 (GMCAO) + * + * Visit http://camitk.imag.fr for more information + * + * This file is part of CamiTK. + * + * CamiTK is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * CamiTK is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with CamiTK. If not, see . + * + * $CAMITK_LICENCE_END$ + ****************************************************************************/ + + +#ifndef MEDICALIMAGEVIEWEREXTENSION_H +#define MEDICALIMAGEVIEWEREXTENSION_H + +#include "MedicalImageViewerAPI.h" + +// -- from CamiTK Core +#include + +class MEDICALIMAGEVIEWER_API MedicalImageViewerExtension : public camitk::ViewerExtension { + Q_OBJECT + Q_INTERFACES(camitk::ViewerExtension); + Q_PLUGIN_METADATA(IID "fr.imag.camitk.medicalimageviewerextension.viewer.medicalimageviewerextension") + +public: + /// Constructor + MedicalImageViewerExtension() : ViewerExtension() {}; + + /// Destructor + virtual ~MedicalImageViewerExtension() = default; + + /// Method returning the action extension name + virtual QString getName() { + return "Medical Image Viewer Extension"; + }; + + /// Method returning the action extension descrption + virtual QString getDescription() { + return "An extension for the Medical Image Viewer"; + }; + + /// initialize all the actions + virtual void init(); + +}; + +#endif // MEDICALIMAGEVIEWEREXTENSION_H + + diff --git a/sdk/viewers/propertyexplorer/CMakeLists.txt b/sdk/viewers/propertyexplorer/CMakeLists.txt new file mode 100644 index 00000000..14423556 --- /dev/null +++ b/sdk/viewers/propertyexplorer/CMakeLists.txt @@ -0,0 +1,8 @@ +# Call CamiTK CMake Macro to define the action +camitk_extension(VIEWER_EXTENSION + CEP_NAME SDK + DEFINES COMPILE_PROPERTYEXPLORER_API + DESCRIPTION "An extension for the viewer that display GUI action" + INSTALL_ALL_HEADERS +) + diff --git a/sdk/libraries/core/viewer/PropertyExplorer.cpp b/sdk/viewers/propertyexplorer/PropertyExplorer.cpp similarity index 89% rename from sdk/libraries/core/viewer/PropertyExplorer.cpp rename to sdk/viewers/propertyexplorer/PropertyExplorer.cpp index fa27382a..76960efd 100644 --- a/sdk/libraries/core/viewer/PropertyExplorer.cpp +++ b/sdk/viewers/propertyexplorer/PropertyExplorer.cpp @@ -23,10 +23,11 @@ * $CAMITK_LICENCE_END$ ****************************************************************************/ -// -- Core stuff -#include "Application.h" #include "PropertyExplorer.h" -#include "Component.h" + +// -- Core stuff +#include +#include // -- QT stuff #include @@ -35,10 +36,11 @@ #include #include -namespace camitk { +using namespace camitk; // ---------------- constructor ---------------- -PropertyExplorer::PropertyExplorer() : Viewer("Property Explorer") { +PropertyExplorer::PropertyExplorer(QString name) : Viewer(name) { + setLayout(Viewer::DOCKED); theController = nullptr; tabWidget = nullptr; revertButton = nullptr; @@ -51,23 +53,10 @@ PropertyExplorer::PropertyExplorer() : Viewer("Property Explorer") { // ---------------- destructor ---------------- PropertyExplorer::~PropertyExplorer() { clear(); - if (propertyObject) { - delete propertyObject; - } - if (viewModeProperty) { - delete viewModeProperty; - } -} -//----------------------- getInstance ------------------------ -PropertyExplorer* PropertyExplorer::getInstance() { - // static instantiation, static method variable - static PropertyExplorer* propExplorer = nullptr; - if (!propExplorer) { - propExplorer = new PropertyExplorer(); + if (propertyObject != nullptr) { + delete propertyObject; // this will also delete viewModeProperty } - - return propExplorer; } // ---------------- numberOfViewedComponent ---------------- @@ -93,13 +82,16 @@ void PropertyExplorer::refresh(Viewer* whoIsAsking) { currentComponent->setVisibility(this, true); //-- get the property widgets QWidget* customWidget; + for (unsigned int i = 0; i < currentComponent->getNumberOfPropertyWidget(); i++) { customWidget = currentComponent->getPropertyWidgetAt(i); + if (customWidget) { tabWidget->addTab(customWidget, customWidget->objectName()); } } } + //-- update the property editor // first clear all (otherwise if a new dynamic properties was added, it won't show) theController->setObject(nullptr); @@ -124,13 +116,13 @@ void PropertyExplorer::refresh(Viewer* whoIsAsking) { } // ---------------- getWidget ---------------- -QWidget* PropertyExplorer::getWidget(QWidget* parent) { +QWidget* PropertyExplorer::getWidget() { if (tabWidget == nullptr) { - tabWidget = new QTabWidget(parent); + tabWidget = new QTabWidget(); tabWidget->setWindowTitle(tr("Property Tabs")); // create the property editor tab itself - auto* propertyFrame = new QFrame; + auto* propertyFrame = new QFrame(); auto* propertyTabLayout = new QVBoxLayout; propertyTabLayout->setSpacing(2); propertyTabLayout->setMargin(2); @@ -146,8 +138,8 @@ QWidget* PropertyExplorer::getWidget(QWidget* parent) { propertyTabLayout->addWidget(theController); // then the buttons - auto* buttonFrame = new QFrame(parent); - auto* buttonLayout = new QHBoxLayout; + auto* buttonFrame = new QFrame(); + auto* buttonLayout = new QHBoxLayout(); applyButton = new QPushButton("Apply"); buttonLayout->addWidget(applyButton); @@ -185,14 +177,17 @@ QObject* PropertyExplorer::getPropertyObject() { // ---------------- clear ---------------- void PropertyExplorer::clear() { - // page #0 is the property widget (not be counted) - for (int i = tabWidget->count() - 1; i > 0; i--) { - tabWidget->removeTab(i); + if (tabWidget != nullptr) { + // page #0 is the property widget (not to be counted) + for (int i = tabWidget->count() - 1; i > 0; i--) { + tabWidget->removeTab(i); + } } - - if (currentComponent && Application::isAlive(currentComponent)) { + + if (currentComponent != nullptr && Application::isAlive(currentComponent)) { currentComponent->setVisibility(this, false); } + currentComponent = nullptr; } @@ -200,8 +195,10 @@ void PropertyExplorer::clear() { void PropertyExplorer::selectWidget(QWidget* widget) { // get the last component tab widgets QWidget* customWidget; + for (int i = 0; i < this->tabWidget->count(); i++) { customWidget = this->tabWidget->widget(i); + if (customWidget && (customWidget == widget)) { this->tabWidget->setCurrentWidget(widget); return; @@ -272,6 +269,3 @@ void PropertyExplorer::createProperties() { void PropertyExplorer::refreshAll() { Application::refresh(); } - - -} diff --git a/sdk/libraries/core/viewer/PropertyExplorer.h b/sdk/viewers/propertyexplorer/PropertyExplorer.h similarity index 89% rename from sdk/libraries/core/viewer/PropertyExplorer.h rename to sdk/viewers/propertyexplorer/PropertyExplorer.h index 2d7f3ad6..73a18394 100644 --- a/sdk/libraries/core/viewer/PropertyExplorer.h +++ b/sdk/viewers/propertyexplorer/PropertyExplorer.h @@ -25,13 +25,14 @@ #ifndef PROPERTYEXPLORER_H #define PROPERTYEXPLORER_H +#include "PropertyExplorerAPI.h" + // -- Core stuff -#include "Viewer.h" -#include "ObjectController.h" -#include "PropertyObject.h" +#include +#include +#include // -- QT stuff -#include #include #include #include @@ -42,9 +43,8 @@ class QPushButton; class QWidget; namespace camitk { - - class ObjectController; +} /** * @ingroup group_sdk_libraries_core_viewer @@ -80,7 +80,7 @@ class ObjectController; * * @see ObjectController */ -class CAMITK_API PropertyExplorer : public Viewer { +class PROPERTYEXPLORER_API PropertyExplorer : public camitk::Viewer { Q_OBJECT Q_ENUMS(camitk::ObjectController::ViewMode) // so that it can be used in property editor @@ -89,15 +89,11 @@ public: */ ///@{ /// constructor - PropertyExplorer(); + Q_INVOKABLE PropertyExplorer(QString name); /// destructor ~PropertyExplorer() override; - /// returns the unique instance of the PropertyExplorer - static PropertyExplorer* getInstance(); - ///@} - /** @name Inherited from Viewer */ ///@{ @@ -105,10 +101,10 @@ public: unsigned int numberOfViewedComponent() override; /// refresh the property editor - void refresh(Viewer* whoIsAsking = nullptr) override; + void refresh(camitk::Viewer* whoIsAsking = nullptr) override; - /// get the viewer widget. @param parent the parent widget for the viewer widget - QWidget* getWidget(QWidget* parent = nullptr) override; + /// get the viewer widget. + QWidget* getWidget() override; /// add a property to change the ObjectController representation at run-time (user choice) QObject* getPropertyObject() override; @@ -133,13 +129,13 @@ public: private: /// the widgets - ObjectController* theController; + camitk::ObjectController* theController; QTabWidget* tabWidget; QPushButton* revertButton; QPushButton* applyButton; /// the viewed Component - Component* currentComponent; + camitk::Component* currentComponent; /** * @name CamiTK Properties of this viewer @@ -148,12 +144,12 @@ private: /** * The property object that holds the properties of this viewer */ - PropertyObject* propertyObject; + camitk::PropertyObject* propertyObject; /** * The CamiTK property that stands for the ObjectController view mode. */ - Property* viewModeProperty; + camitk::Property* viewModeProperty; /** * Event filter of this class instance to watch its properties instances. @@ -187,5 +183,5 @@ private slots: /// in component or action codes. void refreshAll(); }; -} + #endif diff --git a/sdk/viewers/propertyexplorer/PropertyExplorerAPI.h b/sdk/viewers/propertyexplorer/PropertyExplorerAPI.h new file mode 100644 index 00000000..dfbce441 --- /dev/null +++ b/sdk/viewers/propertyexplorer/PropertyExplorerAPI.h @@ -0,0 +1,59 @@ +/***************************************************************************** +* $CAMITK_LICENCE_BEGIN$ +* +* CamiTK - Computer Assisted Medical Intervention ToolKit +* (c) 2001-2018 Univ. Grenoble Alpes, CNRS, TIMC-IMAG UMR 5525 (GMCAO) +* +* Visit http://camitk.imag.fr for more information +* +* This file is part of CamiTK. +* +* CamiTK is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License version 3 +* only, as published by the Free Software Foundation. +* +* CamiTK is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Lesser General Public License version 3 for more details. +* +* You should have received a copy of the GNU Lesser General Public License +* version 3 along with CamiTK. If not, see . +* +* $CAMITK_LICENCE_END$ +****************************************************************************/ + +// ----- PROPERTYEXPLORER_API_H.h +#ifndef PROPERTYEXPLORER_API_H +#define PROPERTYEXPLORER_API_H + +// ----------------------------------------------------------------------- +// +// PROPERTYEXPLORER_API +// +// ----------------------------------------------------------------------- + +// The following ifdef block is the standard way of creating macros which make exporting +// from a DLL simpler. All files within this DLL are compiled with the COMPILE_PROPERTYEXPLORER_API +// flag defined on the command line. this symbol should not be defined on any project +// that uses this DLL. This way any other project whose source files include this file see +// PROPERTYEXPLORER_API functions as being imported from a DLL, wheras this DLL sees symbols +// defined with this macro as being exported. + +#if defined(_WIN32) // MSVC and mingw + +#ifdef COMPILE_PROPERTYEXPLORER_API +#define PROPERTYEXPLORER_API __declspec(dllexport) +#else +#define PROPERTYEXPLORER_API __declspec(dllimport) +#endif // COMPILE_PROPERTYEXPLORER_API + +#else // for all other platforms PROPERTYEXPLORER_API is defined to be "nothing" + +#ifndef PROPERTYEXPLORER_API +#define PROPERTYEXPLORER_API +#endif // PROPERTYEXPLORER_API + +#endif // MSVC and mingw + +#endif // PROPERTYEXPLORER_API_H \ No newline at end of file diff --git a/sdk/viewers/propertyexplorer/PropertyExplorerExtension.cpp b/sdk/viewers/propertyexplorer/PropertyExplorerExtension.cpp new file mode 100644 index 00000000..bed2a8ca --- /dev/null +++ b/sdk/viewers/propertyexplorer/PropertyExplorerExtension.cpp @@ -0,0 +1,36 @@ +/***************************************************************************** + * $CAMITK_LICENCE_BEGIN$ + * + * CamiTK - Computer Assisted Medical Intervention ToolKit + * (c) 2001-2018 Univ. Grenoble Alpes, CNRS, TIMC-IMAG UMR 5525 (GMCAO) + * + * Visit http://camitk.imag.fr for more information + * + * This file is part of CamiTK. + * + * CamiTK is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * CamiTK is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with CamiTK. If not, see . + * + * $CAMITK_LICENCE_END$ + ****************************************************************************/ + + +#include "PropertyExplorerExtension.h" + +// include generated actions headers +#include "PropertyExplorer.h" + +// --------------- getViewers ------------------- +void PropertyExplorerExtension::init() { + registerDefaultViewer(PropertyExplorer); +} + diff --git a/sdk/viewers/propertyexplorer/PropertyExplorerExtension.h b/sdk/viewers/propertyexplorer/PropertyExplorerExtension.h new file mode 100644 index 00000000..d69aa3bd --- /dev/null +++ b/sdk/viewers/propertyexplorer/PropertyExplorerExtension.h @@ -0,0 +1,64 @@ +/***************************************************************************** + * $CAMITK_LICENCE_BEGIN$ + * + * CamiTK - Computer Assisted Medical Intervention ToolKit + * (c) 2001-2018 Univ. Grenoble Alpes, CNRS, TIMC-IMAG UMR 5525 (GMCAO) + * + * Visit http://camitk.imag.fr for more information + * + * This file is part of CamiTK. + * + * CamiTK is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * CamiTK is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with CamiTK. If not, see . + * + * $CAMITK_LICENCE_END$ + ****************************************************************************/ + + +#ifndef PROPERTYEXPLOREREXTENSION_H +#define PROPERTYEXPLOREREXTENSION_H + +#include "PropertyExplorerAPI.h" + +//-- Core +#include + +class PROPERTYEXPLORER_API PropertyExplorerExtension : public camitk::ViewerExtension { + Q_OBJECT + Q_INTERFACES(camitk::ViewerExtension); + Q_PLUGIN_METADATA(IID "fr.imag.camitk.propertyexplorerextension.viewer.propertyexplorerextension") + +public: + /// Constructor + PropertyExplorerExtension() : ViewerExtension() {}; + + /// Destructor + virtual ~PropertyExplorerExtension() = default; + + /// Method returning the action extension name + virtual QString getName() { + return "Property Explorer Extension"; + }; + + /// Method returning the action extension descrption + virtual QString getDescription() { + return "An extension for the property explorer"; + }; + + /// initialize all the actions + virtual void init(); + +}; + +#endif // PROPERTYEXPLOREREXTENSION_H + + diff --git a/tutorials/actions/basicpicking/ImagePicking.cpp b/tutorials/actions/basicpicking/ImagePicking.cpp index 78cffce7..75d558bf 100644 --- a/tutorials/actions/basicpicking/ImagePicking.cpp +++ b/tutorials/actions/basicpicking/ImagePicking.cpp @@ -72,9 +72,9 @@ QWidget* ImagePicking::getWidget() { if (!isConnected) { //-- run the action every time a picking is done in the axial/sagittal or coronal planes - QObject::connect(InteractiveViewer::getAxialViewer(), SIGNAL(selectionChanged()), this, SLOT(apply())); - QObject::connect(InteractiveViewer::getCoronalViewer(), SIGNAL(selectionChanged()), this, SLOT(apply())); - QObject::connect(InteractiveViewer::getSagittalViewer(), SIGNAL(selectionChanged()), this, SLOT(apply())); + QObject::connect(Application::getViewer("axialViewer"), SIGNAL(selectionChanged()), this, SLOT(apply())); + QObject::connect(Application::getViewer("coronalViewer"), SIGNAL(selectionChanged()), this, SLOT(apply())); + QObject::connect(Application::getViewer("sagittalViewer"), SIGNAL(selectionChanged()), this, SLOT(apply())); isConnected = true; } @@ -132,9 +132,9 @@ Action::ApplyStatus ImagePicking::apply() { else { // disconnect //-- run the action every time a picking is done in the axial/sagittal or coronal planes - QObject::disconnect(InteractiveViewer::getAxialViewer(), SIGNAL(selectionChanged()), this, SLOT(apply())); - QObject::disconnect(InteractiveViewer::getCoronalViewer(), SIGNAL(selectionChanged()), this, SLOT(apply())); - QObject::disconnect(InteractiveViewer::getSagittalViewer(), SIGNAL(selectionChanged()), this, SLOT(apply())); + QObject::disconnect(Application::getViewer("axialViewer"), SIGNAL(selectionChanged()), this, SLOT(apply())); + QObject::disconnect(Application::getViewer("coronalViewer"), SIGNAL(selectionChanged()), this, SLOT(apply())); + QObject::disconnect(Application::getViewer("sagittalViewer"), SIGNAL(selectionChanged()), this, SLOT(apply())); isConnected = false; } } diff --git a/tutorials/actions/bitmapviewer/ShowBitmapViewer.cpp b/tutorials/actions/bitmapviewer/ShowBitmapViewer.cpp index 9d92d29c..c784fc1a 100644 --- a/tutorials/actions/bitmapviewer/ShowBitmapViewer.cpp +++ b/tutorials/actions/bitmapviewer/ShowBitmapViewer.cpp @@ -58,7 +58,7 @@ QWidget* ShowBitmapViewer::getWidget() { // --------------- apply ------------------- Action::ApplyStatus ShowBitmapViewer::apply() { // just add the BitMap viewer in the central viewer - Application::getMainWindow()->setCentralViewer(BitmapViewer::getInstance()); + Application::getMainWindow()->setCentralViewer(Application::getViewer("BitmapViewer")); Application::refresh(); if (firstCall) { CAMITK_INFO("TIP: switch central wiewers from the menu: do you know that you can use the \"View Menu\" item \"Toggle Central Viewers\" to switch the central viewer from/to the Medical Image Viewer"); diff --git a/tutorials/actions/meshpointdata/CMakeLists.txt b/tutorials/actions/meshpointdata/CMakeLists.txt index 474cc940..5b32c7ad 100644 --- a/tutorials/actions/meshpointdata/CMakeLists.txt +++ b/tutorials/actions/meshpointdata/CMakeLists.txt @@ -1,7 +1,7 @@ # Call CamiTK CMake Macro to define the action camitk_extension(ACTION_EXTENSION DESCRIPTION "This extension shows how to show/hide mesh point data using a color scale" - ENABLE_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 ) diff --git a/tutorials/actions/showtextviewer/ShowTextViewer.cpp b/tutorials/actions/showtextviewer/ShowTextViewer.cpp new file mode 100644 index 00000000..31db1b7b --- /dev/null +++ b/tutorials/actions/showtextviewer/ShowTextViewer.cpp @@ -0,0 +1,68 @@ +/***************************************************************************** + * $CAMITK_LICENCE_BEGIN$ + * + * CamiTK - Computer Assisted Medical Intervention ToolKit + * (c) 2001-2018 Univ. Grenoble Alpes, CNRS, TIMC-IMAG UMR 5525 (GMCAO) + * + * Visit http://camitk.imag.fr for more information + * + * This file is part of CamiTK. + * + * CamiTK is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * CamiTK is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with CamiTK. If not, see . + * + * $CAMITK_LICENCE_END$ + ****************************************************************************/ + +#include "ShowTextViewer.h" + +// CamiTK includes +#include +#include +#include + +// from tutorial viewer extensions +#include + +using namespace camitk; + +// --------------- Constructor ------------------- +ShowTextViewer::ShowTextViewer(ActionExtension* extension) : Action(extension) { + // Setting name, description and input component + setName("Show TextViewer"); + setDescription("Set TextViewer (from tutorial) as central viewer of the application's main window."); + setComponent(""); + setEmbedded(false); // not embedded (as getWidget returns nullptr, apply is called as soon as the action is triggered) + + setFamily("Tutorial"); + addTag("Viewer"); + addTag("TextViewer"); + addTag("MainWindow"); +} + +// --------------- getWidget ------------------- +QWidget* ShowTextViewer::getWidget() { + CAMITK_INFO(" !!!") + return nullptr; +} + +// --------------- apply ------------------- +Action::ApplyStatus ShowTextViewer::apply() { + CAMITK_INFO(" TextViewer = " + Application::getViewer("TextViewer")->getName()) + + // just add the TextViewer in the central viewer + Application::getMainWindow()->setCentralViewer(Application::getViewer("TextViewer")); + Application::refresh(); + return SUCCESS; +} + + diff --git a/tutorials/actions/sleepingwhileworking/CMakeLists.txt b/tutorials/actions/sleepingwhileworking/CMakeLists.txt index ee4a067f..e306a7a9 100644 --- a/tutorials/actions/sleepingwhileworking/CMakeLists.txt +++ b/tutorials/actions/sleepingwhileworking/CMakeLists.txt @@ -2,4 +2,5 @@ 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 + NEEDS_VIEWER_EXTENSION medicalimageviewer ) diff --git a/tutorials/actions/sleepingwhileworking/WorkingWhenSleepingLinear.cpp b/tutorials/actions/sleepingwhileworking/WorkingWhenSleepingLinear.cpp index 1859ec9a..57077dee 100644 --- a/tutorials/actions/sleepingwhileworking/WorkingWhenSleepingLinear.cpp +++ b/tutorials/actions/sleepingwhileworking/WorkingWhenSleepingLinear.cpp @@ -80,11 +80,11 @@ void WorkingWhenSleepingLinear::process(ImageComponent* comp) { inputImage->GetDimensions(dims); // Getting the Viewer - MedicalImageViewer* myMedicalImageViewer = camitk::MedicalImageViewer::getInstance(); + MedicalImageViewer* myMedicalImageViewer = dynamic_cast(Application::getViewer("MedicalImageViewer")); myMedicalImageViewer->setVisibleViewer(MedicalImageViewer::VIEWER_ALL); // Getting the Camera of the 3DViewer - RendererWidget* myRendererWidget = InteractiveViewer::get3DViewer()->getRendererWidget(); + RendererWidget* myRendererWidget = dynamic_cast(Application::getViewer("3DViewer"))->getRendererWidget(); vtkCamera* myCamera = myRendererWidget->getActiveCamera(); // Getting the three images slices diff --git a/tutorials/actions/sleepingwhileworking/WorkingWhenSleepingRandom.cpp b/tutorials/actions/sleepingwhileworking/WorkingWhenSleepingRandom.cpp index e44c33f5..b4ce003c 100644 --- a/tutorials/actions/sleepingwhileworking/WorkingWhenSleepingRandom.cpp +++ b/tutorials/actions/sleepingwhileworking/WorkingWhenSleepingRandom.cpp @@ -79,11 +79,11 @@ void WorkingWhenSleepingRandom::process(ImageComponent* comp) { inputImage->GetDimensions(dims); // Getting the Viewer - MedicalImageViewer* myMedicalImageViewer = camitk::MedicalImageViewer::getInstance(); + MedicalImageViewer* myMedicalImageViewer = dynamic_cast(Application::getViewer("MedicalImageViewer")); myMedicalImageViewer->setVisibleViewer(MedicalImageViewer::VIEWER_ALL); // Getting the Camera of the 3DViewer - RendererWidget* myRendererWidget = InteractiveViewer::get3DViewer()->getRendererWidget(); + RendererWidget* myRendererWidget = dynamic_cast(Application::getViewer("3DViewer"))->getRendererWidget(); vtkCamera* myCamera = myRendererWidget->getActiveCamera(); // Getting the three images slices diff --git a/tutorials/actions/vtkwidget/BoxWidget.cpp b/tutorials/actions/vtkwidget/BoxWidget.cpp index e52703e6..2fe5156b 100644 --- a/tutorials/actions/vtkwidget/BoxWidget.cpp +++ b/tutorials/actions/vtkwidget/BoxWidget.cpp @@ -74,7 +74,7 @@ BoxWidget::~BoxWidget() { QWidget* BoxWidget::getWidget() { if (boxWidget == nullptr) { - vtkRenderWindowInteractor* iren = InteractiveViewer::get3DViewer()->getRendererWidget()->GetRenderWindow()->GetInteractor(); + vtkRenderWindowInteractor* iren = dynamic_cast(Application::getViewer("3DViewer"))->getRendererWidget()->GetRenderWindow()->GetInteractor(); // Configure the box widget including callbacks boxWidget = vtkSmartPointer::New(); @@ -84,7 +84,7 @@ QWidget* BoxWidget::getWidget() { // Initialize the dimension using the current bounding box double bounds[6]; - InteractiveViewer::get3DViewer()->getBounds(bounds); + dynamic_cast(Application::getViewer("3DViewer"))->getBounds(bounds); boxWidget->PlaceWidget(bounds); // Set box possible interactions diff --git a/tutorials/actions/vtkwidget/CMakeLists.txt b/tutorials/actions/vtkwidget/CMakeLists.txt index 836c31ac..9874b77d 100644 --- a/tutorials/actions/vtkwidget/CMakeLists.txt +++ b/tutorials/actions/vtkwidget/CMakeLists.txt @@ -1,4 +1,5 @@ camitk_extension(ACTION_EXTENSION ENABLE_AUTO_TEST TEST_FILES bassin.msh brain.mha sinus.mhd 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 + NEEDS_VIEWER_EXTENSION medicalimageviewer ) diff --git a/tutorials/actions/vtkwidget/ContourWidget.cpp b/tutorials/actions/vtkwidget/ContourWidget.cpp index 01abf83c..6fe2056a 100644 --- a/tutorials/actions/vtkwidget/ContourWidget.cpp +++ b/tutorials/actions/vtkwidget/ContourWidget.cpp @@ -52,7 +52,6 @@ #include #include #include -#include #include using namespace camitk; @@ -215,16 +214,16 @@ void ContourWidget::initContour() { if (currentImage != nullptr) { if (viewer == Coronal) { - interactor = InteractiveViewer::getCoronalViewer()->getRendererWidget()->GetRenderWindow()->GetInteractor(); + interactor = dynamic_cast(Application::getViewer("coronalViewer"))->getRendererWidget()->GetRenderWindow()->GetInteractor(); viewedSIC = currentImage->getCoronalSlices(); } else { if (viewer == Sagittal) { - interactor = InteractiveViewer::getSagittalViewer()->getRendererWidget()->GetRenderWindow()->GetInteractor(); + interactor = dynamic_cast(Application::getViewer("sagittalViewer"))->getRendererWidget()->GetRenderWindow()->GetInteractor(); viewedSIC = currentImage->getSagittalSlices(); } else { - interactor = InteractiveViewer::getAxialViewer()->getRendererWidget()->GetRenderWindow()->GetInteractor(); + interactor = dynamic_cast(Application::getViewer("axialViewer"))->getRendererWidget()->GetRenderWindow()->GetInteractor(); viewedSIC = currentImage->getAxialSlices(); } } diff --git a/tutorials/applications/basic/main.cpp b/tutorials/applications/basic/main.cpp index d209cae3..6333cb1c 100644 --- a/tutorials/applications/basic/main.cpp +++ b/tutorials/applications/basic/main.cpp @@ -24,10 +24,10 @@ ****************************************************************************/ // -- Core stuff +#include #include #include -#include -#include +#include using namespace camitk; @@ -35,8 +35,11 @@ int main(int argc, char* argv[]) { // create a camitk application Application a("basic", argc, argv); - // add an axial viewer to the default main window - a.getMainWindow()->setCentralViewer(InteractiveViewer::getAxialViewer()); + // add an axial viewer to the default main window + // in order to add it to the main window, we need to extract it first from the medical viewer + // (that's what setLayout is doing) + Application::getViewer("axialViewer")->setLayout(Viewer::STACKED); + a.getMainWindow()->setCentralViewer(Application::getViewer("axialViewer")); // open an image volume Application::open(Core::getTestDataDir() + "/brain.mha"); diff --git a/tutorials/applications/fancy/CMakeLists.txt b/tutorials/applications/fancy/CMakeLists.txt index 306ee0ba..edcaad46 100644 --- a/tutorials/applications/fancy/CMakeLists.txt +++ b/tutorials/applications/fancy/CMakeLists.txt @@ -1 +1,3 @@ -camitk_application() +camitk_application( + NEEDS_VIEWER_EXTENSION interactivegeometryviewer interactivesliceviewer medicalimageviewer +) diff --git a/tutorials/applications/fancy/FancyMainWindow.cpp b/tutorials/applications/fancy/FancyMainWindow.cpp index 4e47bc1e..029e18fa 100644 --- a/tutorials/applications/fancy/FancyMainWindow.cpp +++ b/tutorials/applications/fancy/FancyMainWindow.cpp @@ -51,24 +51,30 @@ FancyMainWindow::FancyMainWindow() : MainWindow("Fancy") { // add the medical image viewer visibility = MedicalImageViewer::VIEWER_AXIAL; - ui.viewer->addWidget(MedicalImageViewer::getInstance()->getWidget(this)); + // for this application, force the medical image viewer to be embedded + Application::getViewer("MedicalImageViewer")->setLayout(Viewer::EMBEDDED); + Application::getViewer("MedicalImageViewer")->embedIn(ui.viewer); + // hide slide bar and modify the color and background - InteractiveViewer::getAxialViewer()->setSideFrameVisible(false); - InteractiveViewer::getAxialViewer()->setGradientBackground(false); - InteractiveViewer::getAxialViewer()->setBackgroundColor(ui.dial->palette().background().color()); - InteractiveViewer::getSagittalViewer()->setSideFrameVisible(false); - InteractiveViewer::getSagittalViewer()->setGradientBackground(false); - InteractiveViewer::getSagittalViewer()->setBackgroundColor(ui.dial->palette().background().color()); - InteractiveViewer::getCoronalViewer()->setSideFrameVisible(false); - InteractiveViewer::getCoronalViewer()->setGradientBackground(false); - InteractiveViewer::getCoronalViewer()->setBackgroundColor(ui.dial->palette().background().color()); - InteractiveViewer::getArbitraryViewer()->setSideFrameVisible(false); - InteractiveViewer::getArbitraryViewer()->setGradientBackground(false); - InteractiveViewer::getArbitraryViewer()->setBackgroundColor(ui.dial->palette().background().color()); - - // add the 3D small little viewer - viewer3D = InteractiveViewer::getNewViewer("Fancy 3D Viewer", camitk::InteractiveViewer::GEOMETRY_VIEWER); - ui.viewer3DLayout->addWidget(viewer3D->getWidget(this)); + dynamic_cast(Application::getViewer("axialViewer"))->setSideFrameVisible(false); + dynamic_cast(Application::getViewer("axialViewer"))->setGradientBackground(false); + dynamic_cast(Application::getViewer("axialViewer"))->setBackgroundColor(ui.dial->palette().background().color()); + dynamic_cast(Application::getViewer("sagittalViewer"))->setSideFrameVisible(false); + dynamic_cast(Application::getViewer("sagittalViewer"))->setGradientBackground(false); + dynamic_cast(Application::getViewer("sagittalViewer"))->setBackgroundColor(ui.dial->palette().background().color()); + dynamic_cast(Application::getViewer("coronalViewer"))->setSideFrameVisible(false); + dynamic_cast(Application::getViewer("coronalViewer"))->setGradientBackground(false); + dynamic_cast(Application::getViewer("coronalViewer"))->setBackgroundColor(ui.dial->palette().background().color()); + dynamic_cast(Application::getViewer("arbitraryViewer"))->setSideFrameVisible(false); + dynamic_cast(Application::getViewer("arbitraryViewer"))->setGradientBackground(false); + dynamic_cast(Application::getViewer("arbitraryViewer"))->setBackgroundColor(ui.dial->palette().background().color()); + + // add a 3D small little viewer (note that we need to set the visibility of this viewer + // to true during refresh, as by default, the component does not know about it + // and its visibility is false) + viewer3D = dynamic_cast(Application::getNewViewer("small3DViewer", "InteractiveGeometryViewer")); + viewer3D->setLayout(Viewer::EMBEDDED); + viewer3D->embedIn(ui.viewer3DLayout); viewer3D->setSideFrameVisible(false); viewer3D->setGradientBackground(false); viewer3D->setBackgroundColor(ui.dial->palette().background().color()); @@ -116,12 +122,14 @@ void FancyMainWindow::updateAngleSlider(QDial* dial, QLabel* label) { if (label == ui.xAngleValue) { label->setText("X : " + QString("%1").arg(dial->value(), 3) + "" + 0x00B0); } - else if (label == ui.yAngleValue) { - label->setText("Y : " + QString("%1").arg(dial->value(), 3) + "" + 0x00B0); - } - else if (label == ui.zAngleValue) { - label->setText("Z : " + QString("%1").arg(dial->value(), 3) + "" + 0x00B0); - } + else + if (label == ui.yAngleValue) { + label->setText("Y : " + QString("%1").arg(dial->value(), 3) + "" + 0x00B0); + } + else + if (label == ui.zAngleValue) { + label->setText("Z : " + QString("%1").arg(dial->value(), 3) + "" + 0x00B0); + } label->update(); } @@ -137,7 +145,7 @@ void FancyMainWindow::updateDialSlider() { maxSliceId = 360; } else { - Component* comp = NULL; + Component* comp = nullptr; if (Application::getTopLevelComponents().size() > 0) { ImageComponent* comp = dynamic_cast(Application::getTopLevelComponents().last()); @@ -147,14 +155,15 @@ void FancyMainWindow::updateDialSlider() { currentSliceId = comp->getAxialSlices()->getSlice(); maxSliceId = comp->getAxialSlices()->getNumberOfSlices(); } - else if (visibility == MedicalImageViewer::VIEWER_CORONAL) { - currentSliceId = comp->getCoronalSlices()->getSlice(); - maxSliceId = comp->getCoronalSlices()->getNumberOfSlices(); - } - else { - currentSliceId = comp->getSagittalSlices()->getSlice(); - maxSliceId = comp->getSagittalSlices()->getNumberOfSlices(); - } + else + if (visibility == MedicalImageViewer::VIEWER_CORONAL) { + currentSliceId = comp->getCoronalSlices()->getSlice(); + maxSliceId = comp->getCoronalSlices()->getNumberOfSlices(); + } + else { + currentSliceId = comp->getSagittalSlices()->getSlice(); + maxSliceId = comp->getSagittalSlices()->getNumberOfSlices(); + } } } } @@ -184,42 +193,46 @@ void FancyMainWindow::layoutChanged() { if (ui.axial->isChecked()) { visibility = MedicalImageViewer::VIEWER_AXIAL; } - else if (ui.saggital->isChecked()) { - visibility = MedicalImageViewer::VIEWER_SAGITTAL; - } - else if (ui.coronal->isChecked()) { - visibility = MedicalImageViewer::VIEWER_CORONAL; - } - else { - visibility = MedicalImageViewer::VIEWER_ARBITRARY; - } + else + if (ui.saggital->isChecked()) { + visibility = MedicalImageViewer::VIEWER_SAGITTAL; + } + else + if (ui.coronal->isChecked()) { + visibility = MedicalImageViewer::VIEWER_CORONAL; + } + else { + visibility = MedicalImageViewer::VIEWER_ARBITRARY; + } - MedicalImageViewer::getInstance()->setVisibleViewer(visibility); + dynamic_cast(Application::getViewer("MedicalImageViewer"))->setVisibleViewer(visibility); ui.dial->show(); + ui.slideValue->show(); showAngleDials(visibility == MedicalImageViewer::VIEWER_ARBITRARY); + refresh(); } // -------------------- xAngleDialValueChanged -------------------- void FancyMainWindow::xAngleDialValueChanged(int value) { - InteractiveViewer::getArbitraryViewer()->xAngleChanged(value); + dynamic_cast(Application::getViewer("arbitraryViewer"))->xAngleChanged(value); updateAngleSlider(ui.xAngledial, ui.xAngleValue); refresh(); } // -------------------- yAngleDialValueChanged -------------------- void FancyMainWindow::yAngleDialValueChanged(int value) { - InteractiveViewer::getArbitraryViewer()->yAngleChanged(value); + dynamic_cast(Application::getViewer("arbitraryViewer"))->yAngleChanged(value); updateAngleSlider(ui.yAngledial, ui.yAngleValue); refresh(); } // -------------------- zAngleDialValueChanged -------------------- void FancyMainWindow::zAngleDialValueChanged(int value) { - InteractiveViewer::getArbitraryViewer()->zAngleChanged(value); + dynamic_cast(Application::getViewer("arbitraryViewer"))->zAngleChanged(value); updateAngleSlider(ui.zAngledial, ui.zAngleValue); refresh(); } @@ -236,18 +249,23 @@ void FancyMainWindow::refresh() { getVisibleViewer()->refresh(); // force visualization of arbitrary slice in 3D + // We need to set the visibility of this viewer to true during as by default + // the component does not know about it and the visibility in viewer3D is false if (Application::getTopLevelComponents().size() > 0) { ImageComponent* comp = dynamic_cast(Application::getTopLevelComponents().last()); if (comp != nullptr && comp->getAxialSlices() != nullptr) { comp->getAxialSlices()->setVisibility(viewer3D, true); } + if (comp != nullptr && comp->getSagittalSlices() != nullptr) { comp->getSagittalSlices()->setVisibility(viewer3D, true); } + if (comp != nullptr && comp->getCoronalSlices() != nullptr) { comp->getCoronalSlices()->setVisibility(viewer3D, true); } + if (comp != nullptr && comp->getArbitrarySlices() != nullptr) { comp->getArbitrarySlices()->setVisibility(viewer3D, true); } @@ -258,21 +276,26 @@ void FancyMainWindow::refresh() { } // -------------------- getVisibleViewer -------------------- -InteractiveViewer* FancyMainWindow::getVisibleViewer() { - InteractiveViewer* visibleViewer = NULL; +InteractiveSliceViewer* FancyMainWindow::getVisibleViewer() { + InteractiveSliceViewer* visibleViewer = NULL; + switch (visibility) { case MedicalImageViewer::VIEWER_AXIAL: - visibleViewer = InteractiveViewer::getAxialViewer(); + visibleViewer = dynamic_cast(Application::getViewer("axialViewer")); break; + case MedicalImageViewer::VIEWER_CORONAL: - visibleViewer = InteractiveViewer::getCoronalViewer(); + visibleViewer = dynamic_cast(Application::getViewer("coronalViewer")); break; + case MedicalImageViewer::VIEWER_SAGITTAL: - visibleViewer = InteractiveViewer::getSagittalViewer(); + visibleViewer = dynamic_cast(Application::getViewer("sagittalViewer")); break; + default: // arbitrary (and... 3D!) - visibleViewer = InteractiveViewer::getArbitraryViewer(); + visibleViewer = dynamic_cast(Application::getViewer("arbitraryViewer")); break; } + return visibleViewer; } diff --git a/tutorials/applications/fancy/FancyMainWindow.h b/tutorials/applications/fancy/FancyMainWindow.h index eec0f5d3..c4e32a10 100644 --- a/tutorials/applications/fancy/FancyMainWindow.h +++ b/tutorials/applications/fancy/FancyMainWindow.h @@ -23,9 +23,6 @@ * $CAMITK_LICENCE_END$ ****************************************************************************/ - - - #ifndef FANCYAPP_H #define FANCYAPP_H @@ -34,18 +31,17 @@ // -- Core stuff #include -#include #include -#include +#include +#include -using namespace camitk; /** * This Class describes the fancy bare application. It sets up the main * window and providing few buttons to demonstrates that CamiTK can * be very fancy! * */ -class FancyMainWindow : public MainWindow { +class FancyMainWindow : public camitk::MainWindow { Q_OBJECT public: @@ -94,10 +90,10 @@ private: QWidget* mainWidget; /// get the currently visible viewer (axial, sagittal, coronal or arbitrary) - InteractiveViewer* getVisibleViewer(); + InteractiveSliceViewer* getVisibleViewer(); /// specific 3D viewer for fancy - InteractiveViewer* viewer3D; + InteractiveGeometryViewer* viewer3D; }; #endif // FANCYAPP_H diff --git a/tutorials/applications/menubar/MyAppMainWindow.cpp b/tutorials/applications/menubar/MyAppMainWindow.cpp index 7e00baa9..314f9670 100644 --- a/tutorials/applications/menubar/MyAppMainWindow.cpp +++ b/tutorials/applications/menubar/MyAppMainWindow.cpp @@ -29,7 +29,6 @@ // -- CamiTK Core stuff #include #include -#include #include #include #include @@ -69,8 +68,12 @@ MyAppMainWindow::MyAppMainWindow() : MainWindow("MyApp - " + tr(Core::version)) updateActionStates(); // now add the different viewers - addDockViewer(Qt::LeftDockWidgetArea, new Explorer()); - addDockViewer(Qt::RightDockWidgetArea, InteractiveViewer::get3DViewer()); + addDockViewer(Qt::LeftDockWidgetArea, Application::getViewer("Explorer")); + // get the default 3D viewer out of the MedicalImageViewer and put it directly in the central viewer + Application::getViewer("3DViewer")->setLayout(Viewer::STACKED); + setCentralViewer(Application::getViewer("3DViewer")); + addDockViewer(Qt::RightDockWidgetArea, Application::getViewer("ActionViewer")); + showDockViewer(Application::getViewer("ActionViewer"), false); showStatusBar(true); } diff --git a/tutorials/applications/simple/SimpleMainWindow.cpp b/tutorials/applications/simple/SimpleMainWindow.cpp index 64b3df8d..6f12934e 100644 --- a/tutorials/applications/simple/SimpleMainWindow.cpp +++ b/tutorials/applications/simple/SimpleMainWindow.cpp @@ -27,7 +27,7 @@ #include "SimpleMainWindow.h" // -- Core stuff -#include +#include #include #include @@ -39,24 +39,24 @@ SimpleMainWindow::SimpleMainWindow() : MainWindow("Simple Demo") { // only add a main viewers - setCentralViewer(MedicalImageViewer::getInstance()); + setCentralViewer(Application::getViewer("MedicalImageViewer")); // all black like if they were old-school OpenGL - InteractiveViewer::get3DViewer()->keyPressEvent(new QKeyEvent(QEvent::KeyPress, Qt::Key_A, Qt::NoModifier)); // simulate "a" stroke - InteractiveViewer::get3DViewer()->setBackgroundColor(Qt::black); - InteractiveViewer::get3DViewer()->setGradientBackground(false); - InteractiveViewer::getAxialViewer()->setBackgroundColor(Qt::black); - InteractiveViewer::getAxialViewer()->setGradientBackground(false); - InteractiveViewer::getSagittalViewer()->setBackgroundColor(Qt::black); - InteractiveViewer::getSagittalViewer()->setGradientBackground(false); - InteractiveViewer::getCoronalViewer()->setBackgroundColor(Qt::black); - InteractiveViewer::getCoronalViewer()->setGradientBackground(false); + dynamic_cast(Application::getViewer("3DViewer"))->keyPressEvent(new QKeyEvent(QEvent::KeyPress, Qt::Key_A, Qt::NoModifier)); // simulate "a" stroke + dynamic_cast(Application::getViewer("3DViewer"))->setBackgroundColor(Qt::black); + dynamic_cast(Application::getViewer("3DViewer"))->setGradientBackground(false); + dynamic_cast(Application::getViewer("axialViewer"))->setBackgroundColor(Qt::black); + dynamic_cast(Application::getViewer("axialViewer"))->setGradientBackground(false); + dynamic_cast(Application::getViewer("sagittalViewer"))->setBackgroundColor(Qt::black); + dynamic_cast(Application::getViewer("sagittalViewer"))->setGradientBackground(false); + dynamic_cast(Application::getViewer("coronalViewer"))->setBackgroundColor(Qt::black); + dynamic_cast(Application::getViewer("coronalViewer"))->setGradientBackground(false); } // ------------- aboutToShow ----------------- void SimpleMainWindow::aboutToShow() { // remove all but the main viewer - InteractiveViewer::get3DViewer()->getToolBar()->hide(); + dynamic_cast(Application::getViewer("3DViewer"))->getToolBar()->hide(); camitk::MainWindow::aboutToShow(); } diff --git a/tutorials/applications/simple/main.cpp b/tutorials/applications/simple/main.cpp index a604d4d0..7979ed07 100644 --- a/tutorials/applications/simple/main.cpp +++ b/tutorials/applications/simple/main.cpp @@ -32,7 +32,7 @@ int main(int argc, char* argv[]) { Application a("simple", argc, argv); - + a.setMainWindow(new SimpleMainWindow()); Application::open(Core::getTestDataDir() + "/brain.mha"); diff --git a/tutorials/applications/textviewer/CMakeLists.txt b/tutorials/applications/textviewer/CMakeLists.txt new file mode 100644 index 00000000..ce1997f1 --- /dev/null +++ b/tutorials/applications/textviewer/CMakeLists.txt @@ -0,0 +1,3 @@ +camitk_application( + NEEDS_VIEWER_EXTENSION textviewer explorer + ) diff --git a/tutorials/viewers/MyViewer.cpp b/tutorials/viewers/MyViewer.cpp index 38b87309..ddb56694 100644 --- a/tutorials/viewers/MyViewer.cpp +++ b/tutorials/viewers/MyViewer.cpp @@ -35,14 +35,13 @@ // -------------------- Constructor -------------------- -MyViewer::MyViewer() : Viewer("My Simple Viewer") { +TextViewer::TextViewer(QString name) : Viewer(name) { inverse = nullptr; myMenu = nullptr; myWidget = nullptr; displayedTopLevelComponents = 0; } - // -------------------- Destructor -------------------- MyViewer::~MyViewer() { delete myWidget; @@ -74,16 +73,16 @@ void MyViewer::refresh(Viewer* whoIsAsking) { } // -------------------- getWidget -------------------- -QWidget* MyViewer::getWidget(QWidget* parent) { +QWidget* TextViewer::getWidget() { if (!myWidget) { - myWidget = new QWidget(parent); - output = new QTextEdit; + myWidget = new QWidget(); + output = new QTextEdit(); textColor = Qt::blue; bgColor = Qt::white; updateColors(); //-- init layout - auto* myWidgetLayout = new QHBoxLayout; + auto* myWidgetLayout = new QHBoxLayout(); myWidgetLayout->setSpacing(0); myWidgetLayout->setMargin(0); diff --git a/tutorials/viewers/MyViewer.h b/tutorials/viewers/MyViewer.h index aaffcc1b..c31c4b0f 100644 --- a/tutorials/viewers/MyViewer.h +++ b/tutorials/viewers/MyViewer.h @@ -28,6 +28,7 @@ #define MY_VIEWER_H // -- Core stuff +#include #include using namespace camitk; @@ -57,7 +58,7 @@ public: */ /// @{ /** construtor. */ - MyViewer(); + Q_INVOKABLE TextViewer(QString name); /** destructor */ virtual ~MyViewer(); @@ -72,8 +73,8 @@ public: /// refresh the view (can be interesting to know which other viewer is calling this) virtual void refresh(Viewer* whoIsAsking = nullptr); - /// get the viewer widget. @param parent the parent widget for the viewer widget - virtual QWidget* getWidget(QWidget* parent = nullptr); + /// get the viewer widget. + virtual QWidget* getWidget(); /// get the propertyObject (only the 3D Scene one) virtual QObject* getPropertyObject(); diff --git a/tutorials/viewers/main.cpp b/tutorials/viewers/main.cpp index a6bc35d1..19b08e05 100644 --- a/tutorials/viewers/main.cpp +++ b/tutorials/viewers/main.cpp @@ -51,7 +51,7 @@ int main(int argc, char* argv[]) { Application a("viewer-tutorial", argc, argv); // create a myViewer instance - auto* myViewer = new MyViewer(); + Viewer* textViewer = Application::getViewer("TextViewer"); // add myViewer to the main window a.getMainWindow()->setCentralViewer(myViewer); diff --git a/tutorials/viewers/textviewer/TextViewerExtension.cpp b/tutorials/viewers/textviewer/TextViewerExtension.cpp new file mode 100644 index 00000000..7572ce49 --- /dev/null +++ b/tutorials/viewers/textviewer/TextViewerExtension.cpp @@ -0,0 +1,36 @@ +/***************************************************************************** + * $CAMITK_LICENCE_BEGIN$ + * + * CamiTK - Computer Assisted Medical Intervention ToolKit + * (c) 2001-2018 Univ. Grenoble Alpes, CNRS, TIMC-IMAG UMR 5525 (GMCAO) + * + * Visit http://camitk.imag.fr for more information + * + * This file is part of CamiTK. + * + * CamiTK is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * CamiTK is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with CamiTK. If not, see . + * + * $CAMITK_LICENCE_END$ + ****************************************************************************/ + + +#include "TextViewerExtension.h" + +// include generated actions headers +#include "TextViewer.h" + +// --------------- getActions ------------------- +void TextViewerExtension::init() { + registerDefaultViewer(TextViewer); +} + -- GitLab From 869ded0da1af6cccb1618c5c30f4b3d49865182d Mon Sep 17 00:00:00 2001 From: Emmanuel Promayon Date: Wed, 5 Feb 2020 11:23:43 +0100 Subject: [PATCH 03/15] FIXED merge issues --- .../applications/textviewer/CMakeLists.txt | 4 +- .../textviewer}/main.cpp | 12 ++-- tutorials/viewers/CMakeLists.txt | 22 ++++-- tutorials/viewers/textviewer/CMakeLists.txt | 8 +++ .../TextViewer.cpp} | 34 +++++----- .../{MyViewer.h => textviewer/TextViewer.h} | 27 +++++--- tutorials/viewers/textviewer/TextViewerAPI.h | 67 +++++++++++++++++++ .../viewers/textviewer/TextViewerExtension.h | 61 +++++++++++++++++ 8 files changed, 194 insertions(+), 41 deletions(-) rename tutorials/{viewers => applications/textviewer}/main.cpp (90%) create mode 100644 tutorials/viewers/textviewer/CMakeLists.txt rename tutorials/viewers/{MyViewer.cpp => textviewer/TextViewer.cpp} (88%) rename tutorials/viewers/{MyViewer.h => textviewer/TextViewer.h} (88%) create mode 100644 tutorials/viewers/textviewer/TextViewerAPI.h create mode 100644 tutorials/viewers/textviewer/TextViewerExtension.h diff --git a/tutorials/applications/textviewer/CMakeLists.txt b/tutorials/applications/textviewer/CMakeLists.txt index ce1997f1..63d671ca 100644 --- a/tutorials/applications/textviewer/CMakeLists.txt +++ b/tutorials/applications/textviewer/CMakeLists.txt @@ -1,3 +1,3 @@ camitk_application( - NEEDS_VIEWER_EXTENSION textviewer explorer - ) + NEEDS_VIEWER_EXTENSION textviewer +) diff --git a/tutorials/viewers/main.cpp b/tutorials/applications/textviewer/main.cpp similarity index 90% rename from tutorials/viewers/main.cpp rename to tutorials/applications/textviewer/main.cpp index 19b08e05..6dde8ce4 100644 --- a/tutorials/viewers/main.cpp +++ b/tutorials/applications/textviewer/main.cpp @@ -31,7 +31,7 @@ using namespace camitk; -#include "MyViewer.h" +#include #include /** This program demonstrates how to build a CamiTK Application with only @@ -48,25 +48,25 @@ using namespace camitk; int main(int argc, char* argv[]) { // create a camitk application - Application a("viewer-tutorial", argc, argv); + Application a("textviewer-tutorial", argc, argv); - // create a myViewer instance + // create a textViewer instance Viewer* textViewer = Application::getViewer("TextViewer"); // add myViewer to the main window - a.getMainWindow()->setCentralViewer(myViewer); + a.getMainWindow()->setCentralViewer(textViewer); // get the open action QAction* fileOpen = Application::getAction("Open")->getQAction(); // get the edit preferences action QAction* editPreference = new QAction("&Edit Preferences...", a.getMainWindow()); - a.getMainWindow()->connect(editPreference, SIGNAL(triggered()), myViewer, SLOT(editPreference())); + a.getMainWindow()->connect(editPreference, SIGNAL(triggered()), textViewer, SLOT(editPreference())); // create menu QMenu* simpleMenu = new QMenu("&Simple Menu"); simpleMenu->addAction(fileOpen); simpleMenu->addAction(editPreference); - simpleMenu->addMenu(myViewer->getMenu()); // add the viewer menu + simpleMenu->addMenu(textViewer->getMenu()); // add the viewer menu a.getMainWindow()->menuBar()->addMenu(simpleMenu); // open an image volume diff --git a/tutorials/viewers/CMakeLists.txt b/tutorials/viewers/CMakeLists.txt index 221b8c39..635c9799 100644 --- a/tutorials/viewers/CMakeLists.txt +++ b/tutorials/viewers/CMakeLists.txt @@ -1,8 +1,18 @@ # -# A simple text viewer... -# It just send a text message everytime a component is read/close and gives information -# about current number of components. -# -# the main.cpp just add this viewer to the default main window so it can be tested. +# DO NOT EDIT THIS FILE (unless you REALLY know what you are doing) # -camitk_application() +# To add a component, just add a subdirectory (the component name is the +# directory name). Add all your code there and a text file called +# CMakeLists.txt +# In your CMakeLists.txt, use the camitk_extension(VIEWER_EXTENSION ...) macro appropriately + +# find components +get_subdirectories(VIEWERS_LIST) + +# 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 subdirectories in CMake project +foreach(VIEWER_NAME ${VIEWERS_LIST}) + camitk_add_subdirectory(${VIEWER_NAME}) +endforeach() diff --git a/tutorials/viewers/textviewer/CMakeLists.txt b/tutorials/viewers/textviewer/CMakeLists.txt new file mode 100644 index 00000000..c47130cc --- /dev/null +++ b/tutorials/viewers/textviewer/CMakeLists.txt @@ -0,0 +1,8 @@ +# Call CamiTK CMake Macro to define the action +camitk_extension(VIEWER_EXTENSION + DEFAULT + DEFINES COMPILE_TEXT_VIEWER_API + DESCRIPTION "An extension to add TextViewer (a pure simple text viewer)" + INSTALL_ALL_HEADERS +) + diff --git a/tutorials/viewers/MyViewer.cpp b/tutorials/viewers/textviewer/TextViewer.cpp similarity index 88% rename from tutorials/viewers/MyViewer.cpp rename to tutorials/viewers/textviewer/TextViewer.cpp index ddb56694..c149fafe 100644 --- a/tutorials/viewers/MyViewer.cpp +++ b/tutorials/viewers/textviewer/TextViewer.cpp @@ -23,41 +23,41 @@ * $CAMITK_LICENCE_END$ ****************************************************************************/ -#include "MyViewer.h" +#include "TextViewer.h" // -- Core stuff #include #include +#include //-- Qt stuff #include #include +#include +using namespace camitk; // -------------------- Constructor -------------------- TextViewer::TextViewer(QString name) : Viewer(name) { inverse = nullptr; myMenu = nullptr; myWidget = nullptr; + isVisible = false; displayedTopLevelComponents = 0; } // -------------------- Destructor -------------------- -MyViewer::~MyViewer() { - delete myWidget; - myWidget = nullptr; - delete myMenu; - myMenu = nullptr; +TextViewer::~TextViewer() { } // -------------------- numberOfViewedComponentgetWidget -------------------- -unsigned int MyViewer::numberOfViewedComponent() { +unsigned int TextViewer::numberOfViewedComponent() { return displayedTopLevelComponents; } // -------------------- refresh -------------------- -void MyViewer::refresh(Viewer* whoIsAsking) { +void TextViewer::refresh(Viewer* whoIsAsking) { // view everything? if (displayedTopLevelComponents != Application::getTopLevelComponents().size()) { // if there the nr of Component changed since last refresh, @@ -96,13 +96,13 @@ QWidget* TextViewer::getWidget() { } // ---------------------- getPropertyObject ---------------------------- -QObject* MyViewer::getPropertyObject() { +QObject* TextViewer::getPropertyObject() { // (change the text/background color) return this; } // -------------------- getMenu -------------------- -QMenu* MyViewer::getMenu() { +QMenu* TextViewer::getMenu() { if (!myMenu) { //-- create the main menu myMenu = new QMenu(objectName()); @@ -119,7 +119,7 @@ QMenu* MyViewer::getMenu() { } // -------------------- inverseColors -------------------- -void MyViewer::inverseColors(bool state) { +void TextViewer::inverseColors(bool state) { if (state) { QColor background = output->textBackgroundColor(); output->setTextBackgroundColor(output->textColor()); @@ -135,7 +135,7 @@ void MyViewer::inverseColors(bool state) { } // -------------------- updateColors -------------------- -void MyViewer::updateColors() { +void TextViewer::updateColors() { output->setTextColor(textColor); output->setTextBackgroundColor(bgColor); output->append("Colors updated"); @@ -143,29 +143,29 @@ void MyViewer::updateColors() { // -------------------- getBgColor -------------------- -QColor MyViewer::getBgColor() { +QColor TextViewer::getBgColor() { return bgColor; } // -------------------- getTextColor -------------------- -QColor MyViewer::getTextColor() { +QColor TextViewer::getTextColor() { return textColor; } // -------------------- setBgColor -------------------- -void MyViewer::setBgColor(QColor c) { +void TextViewer::setBgColor(QColor c) { bgColor = c; updateColors(); } // -------------------- setTextColor -------------------- -void MyViewer::setTextColor(QColor c) { +void TextViewer::setTextColor(QColor c) { textColor = c; updateColors(); } // -------------------- slotEditPreference -------------------- -void MyViewer::editPreference() { +void TextViewer::editPreference() { SettingsDialog settingsDialog; settingsDialog.editSettings(this); settingsDialog.exec(); diff --git a/tutorials/viewers/MyViewer.h b/tutorials/viewers/textviewer/TextViewer.h similarity index 88% rename from tutorials/viewers/MyViewer.h rename to tutorials/viewers/textviewer/TextViewer.h index c31c4b0f..1b864c7b 100644 --- a/tutorials/viewers/MyViewer.h +++ b/tutorials/viewers/textviewer/TextViewer.h @@ -24,26 +24,27 @@ ****************************************************************************/ -#ifndef MY_VIEWER_H -#define MY_VIEWER_H +#ifndef TEXT_VIEWER_H +#define TEXT_VIEWER_H + +#include "TextViewerAPI.h" // -- Core stuff #include #include -using namespace camitk; // -- QT stuff -#include -#include +#include #include -#include + +class QTextEdit; /** * A simple text viewer... * It just send a text message everytime a component is read/close and gives information * about current number of components */ -class MyViewer : public Viewer { +class TEXT_VIEWER_API TextViewer : public camitk::Viewer { Q_OBJECT /// the background color for the text output @@ -61,7 +62,7 @@ public: Q_INVOKABLE TextViewer(QString name); /** destructor */ - virtual ~MyViewer(); + virtual ~TextViewer(); /// @} /** @name Viewer inherited @@ -121,10 +122,16 @@ private: QColor bgColor; void updateColors(); -}; + /// current visibility state + bool isVisible; + /// the viewer instance singleton + static TextViewer* singleton; + /// the unique instance name + static QString viewerName; +}; -#endif +#endif // TEXT_VIEWER_H diff --git a/tutorials/viewers/textviewer/TextViewerAPI.h b/tutorials/viewers/textviewer/TextViewerAPI.h new file mode 100644 index 00000000..fe5bef84 --- /dev/null +++ b/tutorials/viewers/textviewer/TextViewerAPI.h @@ -0,0 +1,67 @@ +/***************************************************************************** + * $CAMITK_LICENCE_BEGIN$ + * + * CamiTK - Computer Assisted Medical Intervention ToolKit + * (c) 2001-2014 UJF-Grenoble 1, CNRS, TIMC-IMAG UMR 5525 (GMCAO) + * + * Visit http://camitk.imag.fr for more information + * + * + * CamiTK is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * CamiTK is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with CamiTK. If not, see . + * + * $CAMITK_LICENCE_END$ + ****************************************************************************/ + +#ifndef TEXT_VIEWER_API_H +#define TEXT_VIEWER_API_H + +// ----------------------------------------------------------------------- +// +// TEXT_VIEWER_API +// +// ----------------------------------------------------------------------- +// The following ifdef block is the standfard way of creating macros which make exporting +// from a DLL simpler. All files within this DLL are compiled with the COMPILE_TEXT_VIEWER_API +// flag defined on the command line. this symbol should not be defined on any project +// that uses this DLL. This way any other project whose source files include this file see +// TEXT_VIEWER_API functions as being imported from a DLL, whereas this DLL sees symbols +// defined with this macro as being exported. +#if defined(_WIN32) // MSVC and mingw +#ifdef COMPILE_TEXT_VIEWER_API +#define TEXT_VIEWER_API __declspec(dllexport) +#else +#define TEXT_VIEWER_API __declspec(dllimport) +#endif +#else +// for all other platforms TEXT_VIEWER_API is defined to be "nothing" +#ifndef TEXT_VIEWER_API +#define TEXT_VIEWER_API +#endif +#endif // MSVC and mingw + +// ----------------------------------------------------------------------- +// It seems that MSVC does not understand exception specification +// If I understand it well, when _declspec() is used, there is a default +// nothrow attribute. +// I did not find the throw attribute. It seems that msvc is therefore ignoring the +// specification of the type of the exception. +// The compiler therefore issues a warning. +// The following line is to avoid this particular warning. +// The best would be to ask msvc not only to take the exception into account, but also +// its type. Anyway, I did not find how to do that anywhere, and I am not sure this is +// possible... +#if defined(_WIN32) && !defined(__MINGW32__) // MSVC only +#pragma warning( disable : 4290 ) +#endif // MSVC only + +#endif // TEXT_VIEWER_API_H diff --git a/tutorials/viewers/textviewer/TextViewerExtension.h b/tutorials/viewers/textviewer/TextViewerExtension.h new file mode 100644 index 00000000..8b613f40 --- /dev/null +++ b/tutorials/viewers/textviewer/TextViewerExtension.h @@ -0,0 +1,61 @@ +/***************************************************************************** + * $CAMITK_LICENCE_BEGIN$ + * + * CamiTK - Computer Assisted Medical Intervention ToolKit + * (c) 2001-2018 Univ. Grenoble Alpes, CNRS, TIMC-IMAG UMR 5525 (GMCAO) + * + * Visit http://camitk.imag.fr for more information + * + * This file is part of CamiTK. + * + * CamiTK is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * CamiTK is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with CamiTK. If not, see . + * + * $CAMITK_LICENCE_END$ + ****************************************************************************/ + + +#ifndef TEXT_VIEWER_EXTENSION_H +#define TEXT_VIEWER_EXTENSION_H + +#include + +class TextViewerExtension : public camitk::ViewerExtension { + Q_OBJECT + Q_INTERFACES(camitk::ViewerExtension); + Q_PLUGIN_METADATA(IID "fr.imag.camitk.tutorials.viewer.textviewerextension") + +public: + /// Constructor + TextViewerExtension() : ViewerExtension() {}; + + /// Destructor + virtual ~TextViewerExtension() = default; + + /// Method returning the action extension name + virtual QString getName() { + return "TextViewer Extension"; + }; + + /// Method returning the action extension descrption + virtual QString getDescription() { + return "An extension that brings a pure text viewer called... TextViewer"; + }; + + /// initialize all the actions + virtual void init(); + +}; + +#endif // TEXT_VIEWER_EXTENSION_H + + -- GitLab From 67012e689e0335bbe30dc288d1ea953463cc90c2 Mon Sep 17 00:00:00 2001 From: Emmanuel Promayon Date: Wed, 5 Feb 2020 11:39:19 +0100 Subject: [PATCH 04/15] FIXED bad merge of cmake macro --- .../image/reorientimage/CMakeLists.txt | 2 +- .../macros/camitk/CamiTKApplication.cmake | 199 +++++++++------- .../macros/camitk/CamiTKExtension.cmake | 212 +++++++++++------- sdk/libraries/core/CamiTKAPI.h | 1 + 4 files changed, 244 insertions(+), 170 deletions(-) diff --git a/sdk/actions/image/reorientimage/CMakeLists.txt b/sdk/actions/image/reorientimage/CMakeLists.txt index 00a9b67e..0d3f588a 100644 --- a/sdk/actions/image/reorientimage/CMakeLists.txt +++ b/sdk/actions/image/reorientimage/CMakeLists.txt @@ -1,7 +1,7 @@ # Call CamiTK CMake Macro to define the action camitk_extension(ACTION_EXTENSION NEEDS_COMPONENT_EXTENSION vtkmesh - NEEDS_VIEWER_EXTENSION interactivegeometryviewer + NEEDS_VIEWER_EXTENSION interactivegeometryviewer CEP_NAME SDK DESCRIPTION "Allows one to reorient a volumic image." ENABLE_AUTO_TEST diff --git a/sdk/cmake/modules/macros/camitk/CamiTKApplication.cmake b/sdk/cmake/modules/macros/camitk/CamiTKApplication.cmake index a939bb67..774ef84e 100644 --- a/sdk/cmake/modules/macros/camitk/CamiTKApplication.cmake +++ b/sdk/cmake/modules/macros/camitk/CamiTKApplication.cmake @@ -3,10 +3,10 @@ #! #! macro camitk_application simplify writing a CMakeLists.txt for CamiTK application extension #! -#! \note -#! After the execution of this macro, the variable APPLICATION_TARGET_NAME +#! \note +#! After the execution of this macro, the variable APPLICATION_TARGET_NAME #! holds the name of the CMake target produced by this macro. -#! The target name itself is equals to "camitk-", where is the name of the current +#! The target name itself is equals to "camitk-", where is the name of the current #! folder in lowercase. #! #! On Unix additional system resources can also be automatically installed or configured: man pages, @@ -22,7 +22,7 @@ #! To write a simple man page, please refer to SDK application examples. If you need to #! generate a simple manpage or analyze the command line arguments, the CamiTK team recommands #! to use Code Synthesis CLI configuration (see http://codesynthesis.com/projects/cli) -#! +#! #! usage: #! \code #! camitk_application( @@ -32,6 +32,7 @@ #! [NEEDS_CEP_LIBRARIES CEPLib1 CEPLib12 ...] #! [NEEDS_COMPONENT_EXTENSION component1 component2 ...] #! [NEEDS_ACTION_EXTENSION ation1 action2 ...] +#! [NEEDS_VIEWER_EXTENSION viewer1 viewer2 ...] #! [DEFINES flag1 flag2 ...] #! [CXX_FLAGS flag1 flag2 ...] #! [ADDITIONAL_SOURCES source.cxx source.cpp ...] @@ -45,7 +46,8 @@ #! \param NEEDS_ITK means this application requires ITK to be compiled / run. #! \param NEEDS_CEP_LIBRARIES list of needed camitk CEP libraries #! \param NEEDS_COMPONENT_EXTENSION list of needed component extensions -#! \param NEEDS_ACTION_EXTENSION list of needed component extensions +#! \param NEEDS_ACTION_EXTENSION list of needed action extensions +#! \param NEEDS_VIEWER_EXTENSION list of needed viewer extensions #! \param DEFINES list of define flags to add at compilation time #! \param CXX_FLAGS list of compiler flags to add (such as warning levels (-Wall ...)). #! \param ADDITIONAL_SOURCES list of additional sources (that cannot be automatically found by gather_headers_and_sources macro) @@ -55,11 +57,12 @@ #! \param INCLUDE_DIRECTORIES additional include directories #! \param EXTERNAL_LIBRARIES external libraries to add to the link command #! \param EXTRA_TRANSLATE_LANGUAGE Additionnal extra language to translate the application +#! macro(camitk_application) # Instruct CMake to run moc automatically when needed. set(CMAKE_AUTOMOC ON) - + ######################################################################### # # # ARGUMENTS PARSING # @@ -73,11 +76,11 @@ macro(camitk_application) set(options DISABLED NEEDS_ITK NEEDS_XSD NEEDS_XERCESC NEEDS_PYTHON) set(oneValueArgs "") - set(multiValueArgs NEEDS_CEP_LIBRARIES NEEDS_TOOL NEEDS_COMPONENT_EXTENSION NEEDS_ACTION_EXTENSION DEFINES CXX_FLAGS ADDITIONAL_SOURCES CEP_NAME DESCRIPTION EXTERNAL_LIBRARIES INCLUDE_DIRECTORIES EXTRA_TRANSLATE_LANGUAGE) + set(multiValueArgs NEEDS_CEP_LIBRARIES NEEDS_TOOL NEEDS_COMPONENT_EXTENSION NEEDS_ACTION_EXTENSION NEEDS_VIEWER_EXTENSION DEFINES CXX_FLAGS ADDITIONAL_SOURCES CEP_NAME DESCRIPTION EXTERNAL_LIBRARIES INCLUDE_DIRECTORIES EXTRA_TRANSLATE_LANGUAGE) cmake_parse_arguments(${APPLICATION_NAME_CMAKE} "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} ) - - - + + + ######################################################################### # # # CREATE CMAKE VARIABLES # @@ -87,7 +90,7 @@ macro(camitk_application) ######################################################################### # CMAKE CACHE VARIABLE - # if it is the first cmake run, create the application variable with a correct initial value + # if it is the first cmake run, create the application variable with a correct initial value if(NOT APPLICATION_${APPLICATION_NAME_CMAKE}_INTERNAL) # add option to enable/disable this extension and set it to true by default # Building the extension can be disabled by giving the argument DISABLED to the macro @@ -100,7 +103,7 @@ macro(camitk_application) set(APPLICATION_${APPLICATION_NAME_CMAKE} ${APPLICATION_${APPLICATION_NAME_CMAKE}_ENABLED} CACHE BOOL "Build application ${APPLICATION_NAME}") set(APPLICATION_${APPLICATION_NAME_CMAKE}_INTERNAL TRUE CACHE INTERNAL "Is variable APPLICATION_${APPLICATION_NAME} already created?") endif() - + # APPLICATION TARGET NAME if (PACKAGING_NSIS) # NSIS requires that cpack component names do not feature space or "-" characters @@ -108,17 +111,17 @@ macro(camitk_application) else() set(APPLICATION_TARGET_NAME application-${APPLICATION_NAME}) endif() - - - + + + # if this extension is enabled, do everything needed # otherwise... do nothing if (APPLICATION_${APPLICATION_NAME_CMAKE}) - + message(STATUS "Building application ${APPLICATION_NAME}") - - - + + + ######################################################################### # # # INCLUDE DIRECTORIES # @@ -129,15 +132,15 @@ macro(camitk_application) # # ######################################################################### # BASIC DIRECTORIES - include_directories(${CAMITK_INCLUDE_DIRECTORIES}) + include_directories(${CAMITK_INCLUDE_DIRECTORIES}) include_directories(${CMAKE_CURRENT_BINARY_DIR}) include_directories(${CMAKE_CURRENT_SOURCE_DIR}) - + # USER INPUT DIRECTORIES include_directories(${${APPLICATION_NAME_CMAKE}_INCLUDE_DIRECTORIES}) - - - + + + ######################################################################### # # # GATHER RESOURCES # @@ -145,17 +148,17 @@ macro(camitk_application) # * get all the headers (.h) and source files (.cpp) of the project # # * create the needed Qt files (using moc and uic) # # * On Windows, Visual Studio, group .moc and .ui files # - # in subdirectories # + # in subdirectories # # # ######################################################################### - + # get all headers, sources and do what is needed for Qt # one need to do this just before the add_library so that all defines, include directories and link directories # are set properly (gather_headers_and_sources include the call to Qt moc and uic) gather_headers_and_sources(${APPLICATION_NAME}) - - - + + + ######################################################################### # # # TARGET COMPILATION DEFINITION # @@ -166,7 +169,7 @@ macro(camitk_application) ######################################################################### # EXTERNAL SOURCES set(${APPLICATION_NAME}_SOURCES ${${APPLICATION_NAME}_SOURCES} ${${APPLICATION_NAME_CMAKE}_ADDITIONAL_SOURCES}) - + # APPLE BUNDLE DEFINITIONS if(APPLE) set(MACOSX_BUNDLE_INFO_STRING "${APPLICATION_TARGET_NAME} ${CAMITK_SHORT_VERSION_STRING}") @@ -182,9 +185,9 @@ macro(camitk_application) execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${MACOSX_BUNDLE_RESOURCES}) execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different ${MACOSX_BUNDLE_ICON} ${MACOSX_BUNDLE_RESOURCES}) endif() - - + + ######################################################################### # # # ADDITIONAL KNOWN LIBRARY DEPENDENCIES # @@ -195,7 +198,7 @@ macro(camitk_application) # * Backward compatibility : Warn user if using old NEEDS_TOOL syntax # # # ######################################################################### - + # Looking for ITK set(ITK_LIBRARIES "") if(${APPLICATION_NAME_CMAKE}_NEEDS_ITK) @@ -273,13 +276,13 @@ macro(camitk_application) message(FATAL_ERROR "Python (2.7 or above) is required by ${APPLICATION_NAME} : please add your python installation dir to your PATH environment variable") endif() endif() - + # EXTERNAL LIBRARIES set(EXTERNAL_LIBRARIES) if(${APPLICATION_NAME_CMAKE}_EXTERNAL_LIBRARIES) foreach(EXTERNAL_LIBRARY ${${APPLICATION_NAME_CMAKE}_EXTERNAL_LIBRARIES}) if (MSVC) # TODO We have to decide how to handle debug version of external libraries - set(EXTERNAL_LIBRARIES ${EXTERNAL_LIBRARIES} + set(EXTERNAL_LIBRARIES ${EXTERNAL_LIBRARIES} debug ${EXTERNAL_LIBRARY}${CAMITK_DEBUG_POSTFIX}.lib optimized ${EXTERNAL_LIBRARY}.lib ) @@ -289,8 +292,8 @@ macro(camitk_application) endforeach() endif() - - + + ######################################################################### # # # LINK DIRECTORIES # @@ -301,9 +304,9 @@ macro(camitk_application) ######################################################################### # CAMITK BASIC LIB DIRECTORIES link_directories(${CAMITK_LINK_DIRECTORIES}) - - - + + + ######################################################################### # # # TARGET COMPILATION DEFINITION # @@ -314,8 +317,8 @@ macro(camitk_application) ######################################################################### # CMAKE TARGET DEFINITION add_executable(${APPLICATION_TARGET_NAME} ${${APPLICATION_NAME}_SOURCES}) - - + + ######################################################################### # # @@ -325,9 +328,9 @@ macro(camitk_application) # # ######################################################################### qt5_use_modules(${APPLICATION_TARGET_NAME} ${CAMITK_QT_COMPONENTS}) - - - + + + ######################################################################### # # # CAMITK ACTION / COMPONENT / LIBRARIES DEPENDENCIES # @@ -336,20 +339,20 @@ macro(camitk_application) # * Specific actions / components / libraries are specified as option # # with the NEEDS_ACTION/COMPONENT_EXTENSION/CEP_LIBRARIES syntax # # * Add dependencies to library-camitkcore and the testing # - # action/component if test are runned on it # + # action/component if test are runned on it # # # ######################################################################### - - # 1st CAMITKCORE LIBRARY DEPENDENCY - # add the target dependency (i.e., enable proper parallelization of the build process + + # 1) CAMITKCORE LIBRARY DEPENDENCY + # add the target dependency (i.e., enable proper parallelization of the build process # only if inside the sdk build - if(CAMITK_COMMUNITY_EDITION_BUILD) + if(CAMITK_COMMUNITY_EDITION_BUILD) add_dependencies(${APPLICATION_TARGET_NAME} ${CAMITK_CORE_TARGET_LIB_NAME}) # add the dependency to the core automoc target set_property(TARGET ${APPLICATION_TARGET_NAME} APPEND PROPERTY AUTOGEN_TARGET_DEPENDS ${CAMITK_CORE_TARGET_LIB_NAME}) endif() - - # 2nd COMPONENTS DEPENDENCIES + + # 2) COMPONENTS DEPENDENCIES if(${APPLICATION_NAME_CMAKE}_NEEDS_COMPONENT_EXTENSION) set(COMPONENTS_DEPENDENCY_LIST "") #use for generating the project.xml file foreach(COMPONENT_NEEDED ${${APPLICATION_NAME_CMAKE}_NEEDS_COMPONENT_EXTENSION}) @@ -369,17 +372,17 @@ macro(camitk_application) if(PACKAGING_NSIS) add_dependencies(${APPLICATION_TARGET_NAME} component_${COMPONENT_NEEDED}) # add the dependency to the component automoc target - set_property(TARGET ${APPLICATION_TARGET_NAME} APPEND PROPERTY AUTOGEN_TARGET_DEPENDS component_${COMPONENT_NEEDED}) + set_property(TARGET ${APPLICATION_TARGET_NAME} APPEND PROPERTY AUTOGEN_TARGET_DEPENDS component_${COMPONENT_NEEDED}) else() add_dependencies(${APPLICATION_TARGET_NAME} component-${COMPONENT_NEEDED}) list(APPEND COMPONENTS_DEPENDENCY_LIST component-${COMPONENT_NEEDED}) # add the dependency to the component automoc target - set_property(TARGET ${APPLICATION_TARGET_NAME} APPEND PROPERTY AUTOGEN_TARGET_DEPENDS component-${COMPONENT_NEEDED}) + set_property(TARGET ${APPLICATION_TARGET_NAME} APPEND PROPERTY AUTOGEN_TARGET_DEPENDS component-${COMPONENT_NEEDED}) endif() endforeach() endif() - # 3rd ACTIONS DEPENDENCIES + # 3) ACTIONS DEPENDENCIES if(${APPLICATION_NAME_CMAKE}_NEEDS_ACTION_EXTENSION) set(ACTIONS_DEPENDENCY_LIST "") #use for generating the project.xml file foreach(ACTION_NEEDED ${${APPLICATION_NAME_CMAKE}_NEEDS_ACTION_EXTENSION}) @@ -399,17 +402,47 @@ macro(camitk_application) if (PACKAGING_NSIS) add_dependencies(${APPLICATION_TARGET_NAME} action_${ACTION_NEEDED}) # add the dependency to the action automoc target - set_property(TARGET ${APPLICATION_TARGET_NAME} APPEND PROPERTY AUTOGEN_TARGET_DEPENDS action_${ACTION_NEEDED}) + set_property(TARGET ${APPLICATION_TARGET_NAME} APPEND PROPERTY AUTOGEN_TARGET_DEPENDS action_${ACTION_NEEDED}) else() add_dependencies(${APPLICATION_TARGET_NAME} action-${ACTION_NEEDED}) list(APPEND ACTIONS_DEPENDENCY_LIST action-${ACTION_NEEDED}) # add the dependency to the action automoc target - set_property(TARGET ${APPLICATION_TARGET_NAME} APPEND PROPERTY AUTOGEN_TARGET_DEPENDS action-${ACTION_NEEDED}) + set_property(TARGET ${APPLICATION_TARGET_NAME} APPEND PROPERTY AUTOGEN_TARGET_DEPENDS action-${ACTION_NEEDED}) + endif() + endforeach() + endif() + + # 4) VIEWERS DEPENDENCIES + if(${APPLICATION_NAME_CMAKE}_NEEDS_VIEWER_EXTENSION) + set(VIEWERS_DEPENDENCY_LIST "") #use for generating the project.xml file + foreach(VIEWER_NEEDED ${${APPLICATION_NAME_CMAKE}_NEEDS_VIEWER_EXTENSION}) + # include directories from build, camitk (local or global install). + include_directories(${CAMITK_BUILD_INCLUDE_DIR}/viewers/${VIEWER_NEEDED}) + include_directories(${CAMITK_INCLUDE_DIR}/viewers/${VIEWER_NEEDED}) + # file dependency + if (MSVC) + list(APPEND VIEWER_EXTENSION_LIBRARIES + debug ${CAMITK_BUILD_PRIVATE_LIB_DIR}/viewers/${VIEWER_NEEDED}${CAMITK_DEBUG_POSTFIX}.lib + optimized ${VIEWER_NEEDED} + ) + else() + list(APPEND VIEWER_EXTENSION_LIBRARIES ${VIEWER_NEEDED}) + endif() + # CMake / CDash dependencies + if (PACKAGING_NSIS) + add_dependencies(${APPLICATION_TARGET_NAME} viewer_${VIEWER_NEEDED}) + # add the dependency to the viewer automoc target + set_property(TARGET ${APPLICATION_TARGET_NAME} APPEND PROPERTY AUTOGEN_TARGET_DEPENDS viewer_${VIEWER_NEEDED}) + else() + add_dependencies(${APPLICATION_TARGET_NAME} viewer-${VIEWER_NEEDED}) + list(APPEND VIEWERS_DEPENDENCY_LIST viewer-${VIEWER_NEEDED}) + # add the dependency to the viewer automoc target + set_property(TARGET ${APPLICATION_TARGET_NAME} APPEND PROPERTY AUTOGEN_TARGET_DEPENDS viewer-${VIEWER_NEEDED}) endif() endforeach() endif() - # 4th CEP LIBRARIES DEPENDENCIES + # 5) CEP LIBRARIES DEPENDENCIES if(${APPLICATION_NAME_CMAKE}_NEEDS_CEP_LIBRARIES) set(CEP_LIBRARIES_DEPENDENCY_LIST "") #use for generating the project.xml file foreach(CEP_LIBRARY_NEEDED ${${APPLICATION_NAME_CMAKE}_NEEDS_CEP_LIBRARIES}) @@ -428,17 +461,17 @@ macro(camitk_application) if (PACKAGING_NSIS) add_dependencies(${APPLICATION_TARGET_NAME} library_${CEP_LIBRARY_NEEDED}) # add the dependency to the library automoc target - set_property(TARGET ${APPLICATION_TARGET_NAME} APPEND PROPERTY AUTOGEN_TARGET_DEPENDS library_${CEP_LIBRARY_NEEDED}) + set_property(TARGET ${APPLICATION_TARGET_NAME} APPEND PROPERTY AUTOGEN_TARGET_DEPENDS library_${CEP_LIBRARY_NEEDED}) else() add_dependencies(${APPLICATION_TARGET_NAME} library-${CEP_LIBRARY_NEEDED}) list(APPEND CEP_LIBRARIES_DEPENDENCY_LIST library-${CEP_LIBRARY_NEEDED}) # add the dependency to the library automoc target - set_property(TARGET ${APPLICATION_TARGET_NAME} APPEND PROPERTY AUTOGEN_TARGET_DEPENDS library-${CEP_LIBRARY_NEEDED}) + set_property(TARGET ${APPLICATION_TARGET_NAME} APPEND PROPERTY AUTOGEN_TARGET_DEPENDS library-${CEP_LIBRARY_NEEDED}) endif() endforeach() endif() - - + + ######################################################################### # # @@ -456,16 +489,16 @@ macro(camitk_application) add_definitions(-D${FLAG}) endforeach() endif() - + # USER INPUT CUSTOM COMPILER FLAG if(${APPLICATION_NAME_CMAKE}_CXX_FLAGS) foreach (FLAG ${${APPLICATION_NAME_CMAKE}_CXX_FLAGS}) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${FLAG}") endforeach() endif() - - - + + + ######################################################################### # # # LINKING # @@ -477,7 +510,7 @@ macro(camitk_application) # LINKING LIBRARIES target_link_libraries(${APPLICATION_TARGET_NAME} ${CAMITK_CORE_LIBRARIES} ${CAMITK_LIBRARIES} ${COMPONENT_EXTENSION_LIBRARIES} ${ACTION_EXTENSION_LIBRARIES} ${VIEWER_EXTENSION_LIBRARIES} ${CEP_LIBRARIES} ${XERCESC_LIBRARY} ${CAMITK_ITK_LIBRARIES} ${PYTHON_LIBRARIES} ${EXTERNAL_LIBRARIES}) - + ######################################################################### # # @@ -488,7 +521,7 @@ macro(camitk_application) # * Add ${CAMITK_DEBUG_POSTFIX} suffix to Debug MSVC built libraries # # # ######################################################################### - + # OUTPUT NAME if (MSVC) set_target_properties(${APPLICATION_TARGET_NAME} @@ -506,8 +539,8 @@ macro(camitk_application) set_target_properties(${APPLICATION_TARGET_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CAMITK_BUILD_BIN_DIR} RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CAMITK_BUILD_BIN_DIR} RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CAMITK_BUILD_BIN_DIR} - ) - + ) + ######################################################################### # # # INSTALLATION # @@ -526,8 +559,8 @@ macro(camitk_application) COMPONENT ${APPLICATION_TARGET_NAME} ) - - + + ######################################################################### # # # CDASH SUBPROJECT DESCRIPTION # @@ -535,14 +568,14 @@ macro(camitk_application) # * Update the XML descriton of the subprojects dependenicies # # for CDash. # # # - ######################################################################### + ######################################################################### # CDASH XML SUBPROJECTS DESCRIPTION UPDATE # if(NOT ((APPLICATION_TARGET_NAME STREQUAL "application-testactions") OR (APPLICATION_TARGET_NAME STREQUAL "application-testcomponents"))) # We will add manually the CDash dependencies of the testing applications # See CamiTKCDashPublishSubProject.cmake - camitk_register_subproject(APPLICATION ${APPLICATION_TARGET_NAME} DEPENDENCIES library-camitkcore ${COMPONENTS_DEPENDENCY_LIST} ${ACTIONS_DEPENDENCY_LIST} ${CEP_LIBRARIES_DEPENDENCY_LIST}) + camitk_register_subproject(APPLICATION ${APPLICATION_TARGET_NAME} DEPENDENCIES library-camitkcore ${COMPONENTS_DEPENDENCY_LIST} ${ACTIONS_DEPENDENCY_LIST} ${VIEWERS_DEPENDENCY_LIST} ${CEP_LIBRARIES_DEPENDENCY_LIST}) # endif() - + ##################################################################################### # # # TRANSLATION # @@ -551,9 +584,9 @@ macro(camitk_application) # the QString to. # # # # * Create the translate.pro file which contains 4 sections: # - # - HEADERS: list of .h/.hpp files to look for tr("") QString # + # - HEADERS: list of .h/.hpp files to look for tr("") QString # # - SOURCES: list of .cpp files to look for tr("") QString # - # - FORMS: list of .ui files to look for tr("") QString # + # - FORMS: list of .ui files to look for tr("") QString # # - TRANSLATIONS: list of .ts files which use CAMITK_TRANSLATIONS # # to define each .ts file # # # @@ -575,8 +608,8 @@ macro(camitk_application) camitk_translate() endif() endif() - - + + ######################################################################### # # # PACKAGING CATEGORIZATION # @@ -590,7 +623,7 @@ macro(camitk_application) # of the component in this installer. # # # ######################################################################### - + # WINDOWS INSTALLER CATEGORIZATION if(${APPLICATION_NAME_CMAKE}_CEP_NAME) if (${APPLICATION_NAME_CMAKE}_CEP_NAME MATCHES "SDK") @@ -601,7 +634,7 @@ macro(camitk_application) REQUIRED GROUP SDK ) - + else() # Extension is selectable for installation in the wizard of the installer cpack_add_component(${APPLICATION_TARGET_NAME} @@ -616,7 +649,7 @@ macro(camitk_application) DISPLAY_NAME ${APPLICATION_TARGET_NAME} DESCRIPTION ${${APPLICATION_NAME_CMAKE}_DESCRIPTION} ) - + endif() # additional unix system files/resources @@ -660,7 +693,7 @@ macro(camitk_application) message(STATUS "Found pixmap for ${APPLICATION_TARGET_NAME}") install(FILES ${${APPLICATION_NAME_CMAKE}_PIXMAP} DESTINATION ${CAMITK_APPLICATION_PIXMAP_INSTALL_DIR}) endif() - + endif() endif() #APPLICATION_${APPLICATION_NAME_CMAKE} diff --git a/sdk/cmake/modules/macros/camitk/CamiTKExtension.cmake b/sdk/cmake/modules/macros/camitk/CamiTKExtension.cmake index 1273052d..0b31388a 100644 --- a/sdk/cmake/modules/macros/camitk/CamiTKExtension.cmake +++ b/sdk/cmake/modules/macros/camitk/CamiTKExtension.cmake @@ -1,17 +1,20 @@ #! #! @ingroup group_sdk_cmake_camitk #! -#! Macro camitk_extension simplifies writing a camitk extension (component, action) +#! Macro camitk_extension simplifies writing a camitk extension (component, action, viewer) #! #! The name of the extension is automatically the name of the directory from where this macro #! is called, unless it is overriden by the TARGET_NAME parameter. -#! -#! \note -#! To be more precise, after the execution of this macro, the variable _TARGET_NAME (e.g. -#! ACTION_TARGET_NAME or COMPONENT_TARGET_NAME) holds the name of the CMake target produced by this macro. -#! The target name itself is equals to either "action-" or "component-" (depending on the -#! of the extension), where is the name of the current folder in lowercase, unless TARGET_NAME +#! +#! \note +#! To be more precise, after the execution of this macro, the variable _TARGET_NAME (i.e., +#! ACTION_TARGET_NAME, COMPONENT_TARGET_NAME, or VIEWER_TARGET_NAME) holds the name +#! of the CMake target produced by this macro. +#! The target name itself is equals to either "action-", "component-" +#! or viewer- (depending on the of the extension), where is +#! the name of the current folder in lowercase, unless TARGET_NAME #! is provided +#! On windows, the "-" (dash) is replaced by "_" (underscore) #! #! usage: #! \code @@ -24,6 +27,7 @@ #! [NEEDS_XSD] #! [NEEDS_GDCM] #! [NEEDS_ACTION_EXTENSION action1 action2 ...] +#! [NEEDS_VIEWER_EXTENSION viewer1 viewer2 ...] #! [NEEDS_COMPONENT_EXTENSION component1 component2 ...] #! [NEEDS_CEP_LIBRARIES CEPLib1 CEPLib2 ...] #! [INCLUDE_DIRECTORIES dir1 dir2 ...] @@ -45,19 +49,21 @@ #! \endcode #! #! \param = REQUIRED. The selected type of extension you wish to build. -# possible values : ACTION_EXTENSION or COMPONENT_EXTENSION. +# possible values : ACTION_EXTENSION, COMPONENT_EXTENSION +#! or VIEWER_EXTENSION. #! \param DISABLED = means this is a not a default extension, it will not be compiled automatically -#! \param NEEDS_ITK = add this if your component needs ITK. +#! \param NEEDS_ITK = add this if your extension needs ITK. #! Do not forget to add the needed list of ITK libraries in the LIBRARIES parameter -#! \param NEEDS_LIBXML2 = add this if your component needs libxml2 -#! \param NEEDS_XSD = add this if your action needs Codesynthesis xsd cxx (xml schema compiler) -#! \param NEEDS_OPENCV = add this if your component needs OpenCV -#! \param NEEDS_IGSTK = add this if your component needs IgsTK -#! \param NEEDS_XERCESC = add this if your action / component needs XercesC library -#! \param NEEDS_GDCM = Add this, if your extension requires GDCM 2.x library +#! \param NEEDS_LIBXML2 = add this if your extension needs libxml2 +#! \param NEEDS_XSD = add this if your extension needs Codesynthesis xsd cxx (xml schema compiler) +#! \param NEEDS_OPENCV = add this if your extension needs OpenCV +#! \param NEEDS_IGSTK = add this if your extension needs IgsTK +#! \param NEEDS_XERCESC = add this if your extension needs XercesC library +#! \param NEEDS_GDCM = Add this if your extension requires GDCM library #! \param NEEDS_CEP_LIBRARIES = list of needed CEP libraries (not external dependencies) #! \param NEEDS_COMPONENT_EXTENSION = list of needed component extensions -#! \param NEEDS_ACTION_EXTENSION = list of needed component extensions +#! \param NEEDS_ACTION_EXTENSION = list of needed action extensions +#! \param NEEDS_VIEWER_EXTENSION = list of needed viewer extensions #! \param INCLUDE_DIRECTORIES = additional include directories #! \param DEFINES = list of define flags to add at compilation time. #! \param CXX_FLAGS = list of compiler flags to add (such as warning levels (-Wall ...)). @@ -66,43 +72,43 @@ #! Note: EXTERNAL_SOURCES are not installed #! \param EXTERNAL_LIBRARIES = external libraries to add to the link command #! \param HEADERS_TO_INSTALL = list of headers to install, if present this will automatically -#! create an "install-COMPONENT_NAMEcomponent" target, that can be used -#! anywhere else to manage dependencies to this component. -#! The headers are installed ${CAMITK_BUILD_INCLUDE_DIR}/COMPONENT_NAME -#! when the target "install-COMPONENT_NAMEcomponent" is called. +#! create an "install-EXTENSION_NAME" target, that can be used +#! anywhere else to manage dependencies to this extension. +#! The headers are installed ${CAMITK_BUILD_INCLUDE_DIR}/EXTENSION_TYPE/EXTENSION_NAME +#! when the target "install-EXTENSION_NAME" is called. #! \param INSTALL_ALL_HEADERS = install all of the headers (this is the lazy solution, please consider #! making a list and using HEADERS_TO_INSTALL parameter instead. -#! Only the files matching the regex *.h will be install. If you need to add +#! Only the files matching the regex *.h will be install. If you need to add #! other files, you need to use the HEADERS_TO_INSTALL option. -#! \param TARGET_NAME = specify a target name different than the default (default is the action/component directory name) -#! this can be very useful for example when you have action/component directory in your CEP that has -#! the same name as one in the camitk communityedition. +#! \param TARGET_NAME = specify a target name different than the default (default is the extension source code directory name) +#! this can be very useful for example when you have an extension source code directory in your CEP that has +#! the same name as one in the camitk community edition. #! \param CEP_NAME = specify the CEP_NAME, which is used to categorized the extension for packaging purpose #! No CEP_NAME provided will result in default categorization (generic extension). #! \param DESCRIPTION = Simple description of the extension. Used for packaging presentation for instance. #! \param EXTRA_TRANSLATE_LANGUAGE = Additionnal extra language to translate the application -#! \param ENABLE_AUTO_TEST = Create automatic test with either testactions or testcomponents. +#! \param ENABLE_AUTO_TEST = Create automatic test with either testactions or testcomponents. #! By default, auto test are run at the highlest level (level 3) unless AUTO_TEST_LEVEL is specified #! See also TEST_FILES and AUTO_TEST_LEVEL options #! \param TEST_FILES = List of files to use for testing. #! If provided, only the filenames are required (not the absolute paths), each of them should be #! found in the testdata build dir. #! If no test files are provided: -#! - for component extension auto test: all the files in the component +#! - for component extension auto test: all the files in the component #! testdata subdir are used by default #! - for action extension auto test: all the files available in the testdata build dir (i.e., -#! all the component testdata) are used by default (which might be too many!). +#! all the component testdata) are used by default (which might be too many!). #! \param AUTO_TEST_LEVEL i = for automatic test of component extensions: set the highest level of automatic test to perform: #! - level 1: load the component extension, open and close a testdata component file #! - level 2: same as level 1, but save the component before closing it. #! - level 3 (default): same as level 2, but also compare the saved component to the input. -#! \param ENABLE_INTEGRATION_TEST = add a specific integration test (see camitk_add_integration_test) CamiTK CMake macro. +#! \param ENABLE_INTEGRATION_TEST = add a specific integration test (see camitk_add_integration_test) CamiTK CMake macro. #! New in CamiTK 4.1 -#! It does add an integration test using the action-state-machine to process a chain -#! of actions (requires that subdirectory integration-testdata exists, and contains +#! It does add an integration test using the action-state-machine to process a chain +#! of actions (requires that subdirectory integration-testdata exists, and contains #! a file called "asm-input.scxml" and at least one file name "output-*.*") #! Check the wiki for more information about integration test -#! +#! #! #! #! @@ -111,9 +117,8 @@ macro(camitk_extension) # Instruct CMake to run moc automatically when needed. set(CMAKE_AUTOMOC ON) - - - + + ######################################################################### # # # ARGUMENTS PARSING # @@ -124,10 +129,10 @@ macro(camitk_extension) ######################################################################### get_directory_name(${CMAKE_CURRENT_SOURCE_DIR} EXTENSION_NAME) - - set(options ACTION_EXTENSION COMPONENT_EXTENSION DISABLED NEEDS_XERCESC NEEDS_ITK NEEDS_LIBXML2 NEEDS_XSD NEEDS_OPENCV NEEDS_IGSTK INSTALL_ALL_HEADERS NEEDS_GDCM ENABLE_AUTO_TEST ENABLE_INTEGRATION_TEST) + + set(options ACTION_EXTENSION COMPONENT_EXTENSION VIEWER_EXTENSION DISABLED NEEDS_XERCESC NEEDS_ITK NEEDS_LIBXML2 NEEDS_XSD NEEDS_OPENCV NEEDS_IGSTK INSTALL_ALL_HEADERS NEEDS_GDCM ENABLE_AUTO_TEST ENABLE_INTEGRATION_TEST) set(oneValueArgs TARGET_NAME CEP_NAME DESCRIPTION AUTO_TEST_LEVEL) - set(multiValueArgs NEEDS_TOOL NEEDS_CEP_LIBRARIES NEEDS_COMPONENT_EXTENSION NEEDS_ACTION_EXTENSION INCLUDE_DIRECTORIES EXTERNAL_LIBRARIES HEADERS_TO_INSTALL DEFINES CXX_FLAGS EXTERNAL_SOURCES EXTRA_TRANSLATE_LANGUAGE TEST_FILES) + set(multiValueArgs NEEDS_TOOL NEEDS_CEP_LIBRARIES NEEDS_COMPONENT_EXTENSION NEEDS_ACTION_EXTENSION NEEDS_VIEWER_EXTENSION INCLUDE_DIRECTORIES EXTERNAL_LIBRARIES HEADERS_TO_INSTALL DEFINES CXX_FLAGS EXTERNAL_SOURCES EXTRA_TRANSLATE_LANGUAGE TEST_FILES) cmake_parse_arguments(${EXTENSION_NAME_CMAKE} "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} ) @@ -139,13 +144,16 @@ macro(camitk_extension) # # ######################################################################### - # TYPE EXTENSION : ACTION or COMPONENT + # TYPE EXTENSION : ACTION or COMPONENT or VIEWER if (${EXTENSION_NAME_CMAKE}_ACTION_EXTENSION) set(TYPE_EXTENSION "action") string(TOUPPER ${TYPE_EXTENSION} TYPE_EXTENSION_CMAKE) elseif(${EXTENSION_NAME_CMAKE}_COMPONENT_EXTENSION) set(TYPE_EXTENSION "component") string(TOUPPER ${TYPE_EXTENSION} TYPE_EXTENSION_CMAKE) + elseif(${EXTENSION_NAME_CMAKE}_VIEWER_EXTENSION) + set(TYPE_EXTENSION "viewer") + string(TOUPPER ${TYPE_EXTENSION} TYPE_EXTENSION_CMAKE) endif() # CMAKE CACHE VARIABLE @@ -195,7 +203,7 @@ macro(camitk_extension) set(EXTENSION_PLUGIN_FILE ${EXTENSION_PLUGIN_FILE}/lib${${TYPE_EXTENSION_CMAKE}_OUTPUT_NAME}.dylib) else() # Must be Linux - set(EXTENSION_PLUGIN_FILE ${EXTENSION_PLUGIN_FILE}/lib${${TYPE_EXTENSION_CMAKE}_OUTPUT_NAME}.so) + set(EXTENSION_PLUGIN_FILE ${EXTENSION_PLUGIN_FILE}/lib${${TYPE_EXTENSION_CMAKE}_OUTPUT_NAME}.so) endif() ######################################################################### @@ -225,7 +233,7 @@ macro(camitk_extension) # * Get all the headers (.h) and source files (.cpp) of the project # # * Create the needed Qt files (using moc and uic) # # * On Windows, Visual Studio, group .moc and .ui files # - # in subdirectories # + # in subdirectories # # # ######################################################################### @@ -233,7 +241,7 @@ macro(camitk_extension) # one need to do this just before the add_library so that all defines, include directories and link directories # are set properly (gather_headers_and_sources include the call to Qt moc and uic) gather_headers_and_sources(${EXTENSION_NAME_CMAKE}) - + ######################################################################### @@ -256,7 +264,7 @@ macro(camitk_extension) set(ITK_VERSION ${ITK_VERSION_MAJOR}.${ITK_VERSION_MINOR}.${ITK_VERSION_PATCH}) #ITK_VERSION is not always set set(CAMITK_ITK_VERSION ${ITK_VERSION_MAJOR}.${ITK_VERSION_MINOR}) message(STATUS "${${TYPE_EXTENSION_CMAKE}_TARGET_NAME}: Found ITK version ${ITK_VERSION}") - + if ((${ITK_VERSION} VERSION_GREATER "4") AND (${ITK_VERSION} VERSION_LESS "5")) # ITK 4.9 on Windows, maybe a lesser version for Linux. if(MSVC) set(ITK_DIR ${ITK_DIR}/../..) @@ -385,7 +393,6 @@ macro(camitk_extension) endif() endif() - # EXTERNAL LIBRARIES set(EXTERNAL_LIBRARIES) if(${EXTENSION_NAME_CMAKE}_EXTERNAL_LIBRARIES) @@ -402,7 +409,7 @@ macro(camitk_extension) endif() - + ######################################################################### # # # LINK DIRECTORIES # @@ -415,7 +422,7 @@ macro(camitk_extension) # CAMITK BASIC LIB DIRECTORIES link_directories(${CAMITK_LINK_DIRECTORIES}) - + ######################################################################### @@ -432,8 +439,8 @@ macro(camitk_extension) # CMAKE TARGET DEFINITION add_library(${${TYPE_EXTENSION_CMAKE}_TARGET_NAME} SHARED ${${EXTENSION_NAME_CMAKE}_SOURCES}) - - + + ######################################################################### # # # QT LINKING LIBRARIES # @@ -442,9 +449,9 @@ macro(camitk_extension) # # ######################################################################### qt5_use_modules(${${TYPE_EXTENSION_CMAKE}_TARGET_NAME} ${CAMITK_QT_COMPONENTS}) - - - + + + ######################################################################### # # # CAMITK ACTION / COMPONENT / LIBRARIES DEPENDENCIES # @@ -466,8 +473,8 @@ macro(camitk_extension) add_dependencies(${${TYPE_EXTENSION_CMAKE}_TARGET_NAME} ${CAMITK_CORE_TARGET_LIB_NAME}) # add the dependency to the core automoc target only if inside a SDK build set_property(TARGET ${${TYPE_EXTENSION_CMAKE}_TARGET_NAME} APPEND PROPERTY AUTOGEN_TARGET_DEPENDS ${CAMITK_CORE_TARGET_LIB_NAME}) - endif() - + endif() + # 2nd COMPONENTS DEPENDENCIES if(${EXTENSION_NAME_CMAKE}_NEEDS_COMPONENT_EXTENSION) @@ -489,14 +496,14 @@ macro(camitk_extension) add_dependencies(${${TYPE_EXTENSION_CMAKE}_TARGET_NAME} component_${COMPONENT_NEEDED}) # add the dependency to the component automoc target only if compiling SDK if(CAMITK_COMMUNITY_EDITION_BUILD) - set_property(TARGET ${${TYPE_EXTENSION_CMAKE}_TARGET_NAME} APPEND PROPERTY AUTOGEN_TARGET_DEPENDS component_${COMPONENT_NEEDED}) + set_property(TARGET ${${TYPE_EXTENSION_CMAKE}_TARGET_NAME} APPEND PROPERTY AUTOGEN_TARGET_DEPENDS component_${COMPONENT_NEEDED}) endif() else() add_dependencies(${${TYPE_EXTENSION_CMAKE}_TARGET_NAME} component-${COMPONENT_NEEDED}) list(APPEND COMPONENTS_DEPENDENCY_LIST component-${COMPONENT_NEEDED}) # add the dependency to the component automoc target only if compiling SDK if(CAMITK_COMMUNITY_EDITION_BUILD) - set_property(TARGET ${${TYPE_EXTENSION_CMAKE}_TARGET_NAME} APPEND PROPERTY AUTOGEN_TARGET_DEPENDS component-${COMPONENT_NEEDED}) + set_property(TARGET ${${TYPE_EXTENSION_CMAKE}_TARGET_NAME} APPEND PROPERTY AUTOGEN_TARGET_DEPENDS component-${COMPONENT_NEEDED}) endif() endif() endforeach() @@ -522,15 +529,48 @@ macro(camitk_extension) add_dependencies(${${TYPE_EXTENSION_CMAKE}_TARGET_NAME} action_${ACTION_NEEDED}) # add the dependency to the component automoc target only if compiling SDK if(CAMITK_COMMUNITY_EDITION_BUILD) - set_property(TARGET ${${TYPE_EXTENSION_CMAKE}_TARGET_NAME} APPEND PROPERTY AUTOGEN_TARGET_DEPENDS action_${ACTION_NEEDED}) - endif() + set_property(TARGET ${${TYPE_EXTENSION_CMAKE}_TARGET_NAME} APPEND PROPERTY AUTOGEN_TARGET_DEPENDS action_${ACTION_NEEDED}) + endif() else() add_dependencies(${${TYPE_EXTENSION_CMAKE}_TARGET_NAME} action-${ACTION_NEEDED}) list(APPEND ACTIONS_DEPENDENCY_LIST action-${ACTION_NEEDED}) # add the dependency to the component automoc target only if compiling SDK if(CAMITK_COMMUNITY_EDITION_BUILD) - set_property(TARGET ${${TYPE_EXTENSION_CMAKE}_TARGET_NAME} APPEND PROPERTY AUTOGEN_TARGET_DEPENDS action-${ACTION_NEEDED}) - endif() + set_property(TARGET ${${TYPE_EXTENSION_CMAKE}_TARGET_NAME} APPEND PROPERTY AUTOGEN_TARGET_DEPENDS action-${ACTION_NEEDED}) + endif() + endif() + endforeach() + endif() + + # 3rd VIEWERS DEPENDENCIES + if(${EXTENSION_NAME_CMAKE}_NEEDS_VIEWER_EXTENSION) + set(VIEWERS_DEPENDENCY_LIST "") #use for generating the project.xml file + foreach(VIEWER_NEEDED ${${EXTENSION_NAME_CMAKE}_NEEDS_VIEWER_EXTENSION}) + # include directories from build, camitk (local or global install). + include_directories(${CAMITK_BUILD_INCLUDE_DIR}/viewers/${VIEWER_NEEDED}) + include_directories(${CAMITK_INCLUDE_DIR}/viewers/${VIEWER_NEEDED}) + # file dependency + if (MSVC) + list(APPEND VIEWER_EXTENSION_LIBRARIES debug ${CAMITK_BUILD_PRIVATE_LIB_DIR}/viewers/${VIEWER_NEEDED}${CAMITK_DEBUG_POSTFIX}.lib + optimized ${VIEWER_NEEDED} + ) + else() + list(APPEND VIEWER_EXTENSION_LIBRARIES ${VIEWER_NEEDED}) + endif() + # CMake / CDash dependencies + if (PACKAGING_NSIS) + add_dependencies(${${TYPE_EXTENSION_CMAKE}_TARGET_NAME} viewer_${VIEWER_NEEDED}) + # add the dependency to the component automoc target only if compiling SDK + if(CAMITK_COMMUNITY_EDITION_BUILD) + set_property(TARGET ${${TYPE_EXTENSION_CMAKE}_TARGET_NAME} APPEND PROPERTY AUTOGEN_TARGET_DEPENDS viewer_${VIEWER_NEEDED}) + endif() + else() + add_dependencies(${${TYPE_EXTENSION_CMAKE}_TARGET_NAME} viewer-${VIEWER_NEEDED}) + list(APPEND VIEWERS_DEPENDENCY_LIST viewer-${VIEWER_NEEDED}) + # add the dependency to the component automoc target only if compiling SDK + if(CAMITK_COMMUNITY_EDITION_BUILD) + set_property(TARGET ${${TYPE_EXTENSION_CMAKE}_TARGET_NAME} APPEND PROPERTY AUTOGEN_TARGET_DEPENDS viewer-${VIEWER_NEEDED}) + endif() endif() endforeach() endif() @@ -555,8 +595,8 @@ macro(camitk_extension) add_dependencies(${${TYPE_EXTENSION_CMAKE}_TARGET_NAME} library_${CEP_LIBRARY_NEEDED}) # add the dependency to the component automoc target only if compiling SDK if(CAMITK_COMMUNITY_EDITION_BUILD) - set_property(TARGET ${${TYPE_EXTENSION_CMAKE}_TARGET_NAME} APPEND PROPERTY AUTOGEN_TARGET_DEPENDS library_${CEP_LIBRARY_NEEDED}) - endif() + set_property(TARGET ${${TYPE_EXTENSION_CMAKE}_TARGET_NAME} APPEND PROPERTY AUTOGEN_TARGET_DEPENDS library_${CEP_LIBRARY_NEEDED}) + endif() else() add_dependencies(${${TYPE_EXTENSION_CMAKE}_TARGET_NAME} library-${CEP_LIBRARY_NEEDED}) list(APPEND CEP_LIBRARIES_DEPENDENCY_LIST ${CEP_LIBRARY_NEEDED} library-${CEP_LIBRARY_NEEDED}) @@ -614,7 +654,7 @@ macro(camitk_extension) ######################################################################### # LINKING LIBRARIES # Any component or action has to be linked with ${CAMITK_CORE_LIBRARIES} and with all its dependencies - target_link_libraries(${${TYPE_EXTENSION_CMAKE}_TARGET_NAME} ${CAMITK_CORE_LIBRARIES} ${CAMITK_LIBRARIES} ${COMPONENT_EXTENSION_LIBRARIES} ${ACTION_EXTENSION_LIBRARIES} ${CEP_LIBRARIES} ${CAMITK_ITK_LIBRARIES} ${LIBXML2_LIBRARY} ${OpenCV_LIBRARIES} ${IGSTK_LIBRARIES} ${XERCESC_LIBRARIES} ${GDCM_LIBRARIES} ${EXTERNAL_LIBRARIES}) + target_link_libraries(${${TYPE_EXTENSION_CMAKE}_TARGET_NAME} ${CAMITK_CORE_LIBRARIES} ${CAMITK_LIBRARIES} ${COMPONENT_EXTENSION_LIBRARIES} ${ACTION_EXTENSION_LIBRARIES} ${VIEWER_EXTENSION_LIBRARIES} ${CEP_LIBRARIES} ${CAMITK_ITK_LIBRARIES} ${LIBXML2_LIBRARY} ${OpenCV_LIBRARIES} ${IGSTK_LIBRARIES} ${XERCESC_LIBRARIES} ${GDCM_LIBRARIES} ${EXTERNAL_LIBRARIES}) @@ -739,7 +779,7 @@ macro(camitk_extension) # # ######################################################################### # CDASH XML SUBPROJECTS DESCRIPTION UPDATE - camitk_register_subproject(${TYPE_EXTENSION_CMAKE} ${${TYPE_EXTENSION_CMAKE}_TARGET_NAME} DEPENDENCIES library-camitkcore ${COMPONENTS_DEPENDENCY_LIST} ${ACTIONS_DEPENDENCY_LIST} ${CEP_LIBRARIES_DEPENDENCY_LIST}) + camitk_register_subproject(${TYPE_EXTENSION_CMAKE} ${${TYPE_EXTENSION_CMAKE}_TARGET_NAME} DEPENDENCIES library-camitkcore ${COMPONENTS_DEPENDENCY_LIST} ${ACTIONS_DEPENDENCY_LIST} ${VIEWERS_DEPENDENCY_LIST} ${CEP_LIBRARIES_DEPENDENCY_LIST}) @@ -793,9 +833,9 @@ macro(camitk_extension) # the QString to. # # # # * Create the translate.pro file which contains 4 sections: # - # - HEADERS: list of .h/.hpp files to look for tr("") QString # + # - HEADERS: list of .h/.hpp files to look for tr("") QString # # - SOURCES: list of .cpp files to look for tr("") QString # - # - FORMS: list of .ui files to look for tr("") QString # + # - FORMS: list of .ui files to look for tr("") QString # # - TRANSLATIONS: list of .ts files which use CAMITK_TRANSLATIONS # # to define each .ts file # # # @@ -834,12 +874,12 @@ macro(camitk_extension) # CTEST - COMPONENT TESTS DESCRIPTION # # # ######################################################################### - + # if auto test possible and required if (NOT PACKAGING_NSIS AND BUILD_TESTING AND ${EXTENSION_NAME_CMAKE}_ENABLE_AUTO_TEST) if(${EXTENSION_NAME_CMAKE}_COMPONENT_EXTENSION) camitk_init_test( camitk-testcomponents ) - + camitk_parse_test_add_separator(EXTENSION_TYPE ${TYPE_EXTENSION} EXTENSION_NAME ${EXTENSION_NAME}) # Retrieve the files in testdata directory - a test will be applied for each of these files @@ -849,7 +889,7 @@ macro(camitk_extension) set(TESTFILES) foreach(COMPONENT_TESTDATA_FILE ${${EXTENSION_NAME_CMAKE}_TEST_FILES}) list(APPEND TESTFILES ${CMAKE_CURRENT_SOURCE_DIR}/${COMPONENT_TESTDATA_FILE}) - endforeach() + endforeach() else() get_subdirectoryfiles( ${CMAKE_CURRENT_SOURCE_DIR}/testdata TESTFILES ) endif() @@ -867,21 +907,21 @@ macro(camitk_extension) set(TESTLEVEL ${${EXTENSION_NAME_CMAKE}_AUTO_TEST_LEVEL}) endif() endif() - + # Different the test level are done automatically: - # - level 1: load component extension, open & close test data - # - level 2: load component extension, open & close test data, save as - # - level 3: load component extension, open & close test data, save as and compare input with output - # disable some tests accordingly to options defined in camitk_extension macro arguments + # - level 1: load component extension, open & close test data + # - level 2: load component extension, open & close test data, save as + # - level 3: load component extension, open & close test data, save as and compare input with output + # disable some tests accordingly to options defined in camitk_extension macro arguments if(${TESTLEVEL} STREQUAL "1") set(TEST_DESCRIPTION "Test loading the extension, opening and closing the component.") elseif(${TESTLEVEL} STREQUAL "2") set(TEST_DESCRIPTION "Test loading the extension, opening the component and saving it as a file.") - else() + else() # level 3 set(TEST_DESCRIPTION "Test loading the extension, opening, saving and closing the component and comparing saved with input component.") endif() - + foreach(COMPONENT_TESTDATA_FILE ${TESTFILES}) # Give the file name (full path) get_directory_name(${COMPONENT_TESTDATA_FILE} DATA_FILE) @@ -892,24 +932,24 @@ macro(camitk_extension) camitk_add_test(EXECUTABLE_ARGS "-i ${CAMITK_BUILD_TESTDATA_DIR}/${DATA_FILE} -c ${EXTENSION_PLUGIN_FILE} -l 2" PASS_FILE_OUTPUT ${CAMITK_BUILD_TESTDATA_DIR}/${DATA_FILE} TEST_SUFFIX "-level3-" - PROJECT_NAME ${${TYPE_EXTENSION_CMAKE}_TARGET_NAME} - ) + PROJECT_NAME ${${TYPE_EXTENSION_CMAKE}_TARGET_NAME} + ) endif() - + if(${TESTLEVEL} EQUAL 2) camitk_add_test(EXECUTABLE_ARGS "-i ${CAMITK_BUILD_TESTDATA_DIR}/${DATA_FILE} -c ${EXTENSION_PLUGIN_FILE} -l 2" TEST_SUFFIX "-level2-" - PROJECT_NAME ${${TYPE_EXTENSION_CMAKE}_TARGET_NAME} + PROJECT_NAME ${${TYPE_EXTENSION_CMAKE}_TARGET_NAME} ) endif() - + if(${TESTLEVEL} EQUAL 1) camitk_add_test(EXECUTABLE_ARGS "-i ${CAMITK_BUILD_TESTDATA_DIR}/${DATA_FILE} -c ${EXTENSION_PLUGIN_FILE} -l 1" TEST_SUFFIX "-level1-" - PROJECT_NAME ${${TYPE_EXTENSION_CMAKE}_TARGET_NAME} + PROJECT_NAME ${${TYPE_EXTENSION_CMAKE}_TARGET_NAME} ) endif() - + camitk_parse_test_add(NAME ${CAMITK_TEST_NAME} LEVEL ${TESTLEVEL} DESCRIPTION ${TEST_DESCRIPTION}) endforeach() @@ -927,7 +967,7 @@ macro(camitk_extension) # get the names of actions .dlls in lib directory get_subdirectoryfiles( ${CAMITK_BUILD_PRIVATE_LIB_DIR}/actions/ ACTIONSDLLS ) - + # Retrieve the files in testdata directory - a test will be applied for each of these files # or use only the given files if (${EXTENSION_NAME_CMAKE}_TEST_FILES) @@ -942,21 +982,21 @@ macro(camitk_extension) foreach( ACTION_TESTDATA_FILE ${TESTFILES}) # Test procedure: Open a file - load an action extension - Apply an action on the component wrapping the file - camitk_add_test(EXECUTABLE_ARGS "-i ${ACTION_TESTDATA_FILE} -a ${EXTENSION_PLUGIN_FILE}" + camitk_add_test(EXECUTABLE_ARGS "-i ${ACTION_TESTDATA_FILE} -a ${EXTENSION_PLUGIN_FILE}" TEST_SUFFIX "-level1-" - PROJECT_NAME ${${TYPE_EXTENSION_CMAKE}_TARGET_NAME} + PROJECT_NAME ${${TYPE_EXTENSION_CMAKE}_TARGET_NAME} ) camitk_parse_test_add(NAME ${CAMITK_TEST_NAME} LEVEL 1 DESCRIPTION "Open a file, load the action and apply it on the component.") endforeach() endif() endif() # NOT PACKAGING_NSIS AND BUILD_TESTING AND ${EXTENSION_NAME_CMAKE}_ENABLE_AUTO_TEST) - + ######################################################################### # # # CTEST - Integration test # # # ######################################################################### - + if (NOT PACKAGING_NSIS AND BUILD_TESTING AND ${EXTENSION_NAME_CMAKE}_ENABLE_INTEGRATION_TEST) # add a specific test to run the action, save the output and compare it to expected camitk_add_integration_test() diff --git a/sdk/libraries/core/CamiTKAPI.h b/sdk/libraries/core/CamiTKAPI.h index f937408d..28647492 100644 --- a/sdk/libraries/core/CamiTKAPI.h +++ b/sdk/libraries/core/CamiTKAPI.h @@ -84,6 +84,7 @@ namespace camitk { // -- Core stuff Classes class Component; class Action; +class Viewer; /// A list of Component using ComponentList = QList; -- GitLab From c996b75e211d0d5a441bc826f94dadcccc56f49d Mon Sep 17 00:00:00 2001 From: Emmanuel Promayon Date: Wed, 5 Feb 2020 14:19:20 +0100 Subject: [PATCH 05/15] FIXED merge upstream develop --- .../mml/monitoringgui/MonitoringDialog.cpp | 1 - .../image/arbitraryslice/CMakeLists.txt | 1 + .../image/reorientimage/ReorientImage.h | 1 - sdk/applications/imp/ImpMainWindow.cpp | 10 +-- sdk/applications/imp/ImpMainWindow.h | 6 +- sdk/applications/imp/main.cpp | 2 +- sdk/applications/wizard/WizardMainWindow.cpp | 2 +- sdk/cmake/modules/CamiTKApiDoc.cmake | 22 +++-- sdk/cmake/modules/CamiTKConfig.cmake.in | 34 ++++---- sdk/cmake/modules/macros/ExportHeaders.cmake | 4 +- .../macros/camitk/CamiTKExtension.cmake | 42 +++++----- .../camitk/CamiTKInstallAllHeaders.cmake | 31 ++++--- .../camitk/manifest/CamiTKAddSubProject.cmake | 54 +++++++----- .../manifest/CamiTKInitManifestData.cmake | 31 ++++--- .../manifest/CamiTKWriteManifestData.cmake | 3 +- .../camitk/packaging/CamiTKCEPPackaging.cmake | 83 ++++++++++--------- sdk/doc/groups.h | 4 +- sdk/doc/mainpage.h | 6 +- sdk/doc/relatedpages.h | 4 +- sdk/libraries/cepgenerator/CepGenerator.h | 2 +- .../resources/actions.CMakeLists.txt.in | 2 +- sdk/libraries/core/CamiTKAPI.h | 3 + sdk/libraries/core/Core.cpp | 44 ++++++++++ sdk/libraries/core/Core.h | 8 ++ sdk/libraries/core/ExtensionManager.h | 55 +++++++++++- .../component/image/SingleImageComponent.cpp | 3 +- tutorials/actions/CMakeLists.txt | 4 +- .../applications/menubar/MyAppMainWindow.cpp | 2 + .../applications/menubar/MyAppMainWindow.h | 1 - tutorials/components/CMakeLists.txt | 2 +- tutorials/viewers/CMakeLists.txt | 2 +- 31 files changed, 303 insertions(+), 166 deletions(-) diff --git a/modeling/libraries/mml/monitoringgui/MonitoringDialog.cpp b/modeling/libraries/mml/monitoringgui/MonitoringDialog.cpp index 631e367b..b4e1376b 100644 --- a/modeling/libraries/mml/monitoringgui/MonitoringDialog.cpp +++ b/modeling/libraries/mml/monitoringgui/MonitoringDialog.cpp @@ -85,7 +85,6 @@ MonitoringDialog::MonitoringDialog(MonitoringGuiManager* guiManager, QWidget* pa MonitoringDialog::~MonitoringDialog() { // unselect and clear the monitor tab's content. // this allow not to encounter crash when closing the image - // see bug 116 : https://forge.imag.fr/tracker/index.php?func=detail&aid=116&group_id=184&atid=792 this->ui->monitorsTable->clearContents(); QWidget* simulatorWidget = ui->monitoringTabs->widget(3); if (simulatorWidget != nullptr) { diff --git a/sdk/actions/image/arbitraryslice/CMakeLists.txt b/sdk/actions/image/arbitraryslice/CMakeLists.txt index dbb2d843..10959128 100644 --- a/sdk/actions/image/arbitraryslice/CMakeLists.txt +++ b/sdk/actions/image/arbitraryslice/CMakeLists.txt @@ -2,6 +2,7 @@ camitk_extension(ACTION_EXTENSION DEFINES COMPILE_ARBITRARY_SLICE_API CEP_NAME SDK DESCRIPTION "Control of the arbitrary slice on image component" + NEEDS_VIEWER_EXTENSION medicalimageviewer ENABLE_AUTO_TEST TEST_FILES Mesh.off brain.mha sinus.mhd ) diff --git a/sdk/actions/image/reorientimage/ReorientImage.h b/sdk/actions/image/reorientimage/ReorientImage.h index dcd9de1e..c334f157 100644 --- a/sdk/actions/image/reorientimage/ReorientImage.h +++ b/sdk/actions/image/reorientimage/ReorientImage.h @@ -106,7 +106,6 @@ private: camitk::Geometry* maleModel; camitk::Geometry* femaleModel; - QMap lettersMeaning; }; diff --git a/sdk/applications/imp/ImpMainWindow.cpp b/sdk/applications/imp/ImpMainWindow.cpp index a0f66def..fe04a347 100644 --- a/sdk/applications/imp/ImpMainWindow.cpp +++ b/sdk/applications/imp/ImpMainWindow.cpp @@ -229,7 +229,7 @@ void ImpMainWindow::initMenuBar() { fileMenu = new QMenu(tr("&File")); fileMenu->addAction(fileOpen); - openDataDirectoryMenuBuilder(); + updateOpenDirectoryMenu(); fileMenu->addAction(fileClose); fileMenu->addAction(fileCloseAll); @@ -481,7 +481,7 @@ void ImpMainWindow::updateViewMenu() { // only add viewer that are not docked if (viewer->getLayout() == Viewer::STACKED) { // viewerAction is own by viewMenu, viewMenu->clear() will delete it - QAction* viewerAction = viewMenu->addAction(cViewer->objectName()); + QAction* viewerAction = toggleCentralWidgetMenu->addAction(viewer->getName()); viewerAction->setCheckable(true); viewerAction->setChecked(viewer == centralViewer); viewerAction->setIcon(viewer->getIcon()); @@ -490,7 +490,7 @@ void ImpMainWindow::updateViewMenu() { viewerAction->setWhatsThis(tr(tipString.toStdString().c_str())); // add the toggle action slot using C++11 lambda so that everything is contained inside viewMenu connect(viewerAction, &QAction::toggled, [ = ](bool) { - setCentralViewer(cViewer); + setCentralViewer(viewer); }); } } @@ -539,7 +539,7 @@ void ImpMainWindow::editSettings() { } // check if there are anything to change in the data directory menu (for data directory manager) - ImpMainWindow::openDataDirectoryMenuBuilder(); + ImpMainWindow::updateOpenDirectoryMenu(); } // ------------- setApplicationConsole ----------------- @@ -594,7 +594,7 @@ void ImpMainWindow::saveHistoryAsSCXML() { } // ------------------------- openDataDirectoryMenuBuilder --------------------------- -void ImpMainWindow::openDataDirectoryMenuBuilder() { +void ImpMainWindow::updateOpenDirectoryMenu() { QStringList dirExt = ExtensionManager::getDataDirectoryExtNames(); if (dirExt.size() > 1) { diff --git a/sdk/applications/imp/ImpMainWindow.h b/sdk/applications/imp/ImpMainWindow.h index d6f0de20..caca9dbf 100644 --- a/sdk/applications/imp/ImpMainWindow.h +++ b/sdk/applications/imp/ImpMainWindow.h @@ -122,15 +122,11 @@ protected: /// update the viewer's menu void updateViewMenu(); - /// Build the open data directory menu - void openDataDirectoryMenuBuilder(); - /** @name Extension and ComponentPlugin attributes */ ///@{ - /// update the data directory menu depending on registered plugins + /// update the ioen data directory menu depending on registered plugins void updateOpenDirectoryMenu(); - /// update the recent document menu void updateRecentDocumentsMenu(); ///@} diff --git a/sdk/applications/imp/main.cpp b/sdk/applications/imp/main.cpp index 8da9c0a2..975c94e4 100644 --- a/sdk/applications/imp/main.cpp +++ b/sdk/applications/imp/main.cpp @@ -54,7 +54,7 @@ const char* description = "Please visit http://camitk.imag.fr for more informati "formats, offers image processing and segmentation algorithms to reconstruct a\n" "mesh geometry and run a biomechanical simulation.\n\n" "For a tutorial on camitk-imp, please visit the website:\n" - "https://forge.imag.fr/plugins/mediawiki/wiki/camitk/index.php/Camitk-imp_tutorial\n\n" + "https://camitk.imag.fr\n\n" "CamiTK is highly modular and make an extensive use of extensions (plugins).\n\n" "CamiTK goals are to:\n" "- Gather knowledge & know-how from several fields\n" diff --git a/sdk/applications/wizard/WizardMainWindow.cpp b/sdk/applications/wizard/WizardMainWindow.cpp index 087b0998..1e30560c 100644 --- a/sdk/applications/wizard/WizardMainWindow.cpp +++ b/sdk/applications/wizard/WizardMainWindow.cpp @@ -62,7 +62,7 @@ WizardMainWindow::~WizardMainWindow() {} // Welcome buttons /** When button Help of WelcomeWindow interface is clicked, the wiki page "New interfaces of Wizard" opens */ void WizardMainWindow::welcomeHelp() { - QUrl helpUrl("https://forge.imag.fr/plugins/mediawiki/wiki/camitk/index.php/New_interfaces_of_Wizard"); + QUrl helpUrl("https://camitk.imag.fr"); QDesktopServices::openUrl(helpUrl); } diff --git a/sdk/cmake/modules/CamiTKApiDoc.cmake b/sdk/cmake/modules/CamiTKApiDoc.cmake index fd81a7e6..df2210ac 100644 --- a/sdk/cmake/modules/CamiTKApiDoc.cmake +++ b/sdk/cmake/modules/CamiTKApiDoc.cmake @@ -34,23 +34,29 @@ if(APIDOC_SDK) # which directories to use set(DOXYGEN_SUBDIRS) - set(DOXYGEN_SUBDIRS ${DOXYGEN_SUBDIRS} ${CMAKE_SOURCE_DIR}/sdk/doc) - set(DOXYGEN_SUBDIRS ${DOXYGEN_SUBDIRS} ${CMAKE_SOURCE_DIR}/imaging/doc) - set(DOXYGEN_SUBDIRS ${DOXYGEN_SUBDIRS} ${CMAKE_SOURCE_DIR}/modeling/doc) + set(DOXYGEN_SUBDIRS ${DOXYGEN_SUBDIRS} ${CMAKE_CURRENT_SOURCE_DIR}/doc) set(DOXYGEN_SUBDIRS ${DOXYGEN_SUBDIRS} ${CMAKE_CURRENT_SOURCE_DIR}/libraries/core) set(DOXYGEN_SUBDIRS ${DOXYGEN_SUBDIRS} ${CMAKE_CURRENT_SOURCE_DIR}/libraries/cepgenerator) set(DOXYGEN_SUBDIRS ${DOXYGEN_SUBDIRS} ${CMAKE_CURRENT_SOURCE_DIR}/libraries/qtpropertybrowser) - set(DOXYGEN_SUBDIRS ${DOXYGEN_SUBDIRS} ${CMAKE_CURRENT_SOURCE_DIR}/../modeling/libraries) + set(DOXYGEN_SUBDIRS ${DOXYGEN_SUBDIRS} ${CMAKE_CURRENT_SOURCE_DIR}/viewers) set(DOXYGEN_SUBDIRS ${DOXYGEN_SUBDIRS} ${CMAKE_CURRENT_SOURCE_DIR}/actions) - set(DOXYGEN_SUBDIRS ${DOXYGEN_SUBDIRS} ${CMAKE_CURRENT_SOURCE_DIR}/../modeling/actions) - set(DOXYGEN_SUBDIRS ${DOXYGEN_SUBDIRS} ${CMAKE_CURRENT_SOURCE_DIR}/../imaging/actions) set(DOXYGEN_SUBDIRS ${DOXYGEN_SUBDIRS} ${CMAKE_CURRENT_SOURCE_DIR}/applications) set(DOXYGEN_SUBDIRS ${DOXYGEN_SUBDIRS} ${CMAKE_CURRENT_SOURCE_DIR}/cmake) set(DOXYGEN_SUBDIRS ${DOXYGEN_SUBDIRS} ${CMAKE_CURRENT_SOURCE_DIR}/components) - set(DOXYGEN_SUBDIRS ${DOXYGEN_SUBDIRS} ${CMAKE_CURRENT_SOURCE_DIR}/../modeling/components) - set(DOXYGEN_SUBDIRS ${DOXYGEN_SUBDIRS} ${CMAKE_CURRENT_SOURCE_DIR}/../imaging/components) set(DOXYGEN_SUBDIRS ${DOXYGEN_SUBDIRS} ${CMAKE_BINARY_DIR}/doxygencmake) + set(DOXYGEN_SUBDIRS ${DOXYGEN_SUBDIRS} ${CMAKE_SOURCE_DIR}/imaging/doc) + set(DOXYGEN_SUBDIRS ${DOXYGEN_SUBDIRS} ${CMAKE_SOURCE_DIR}/viewers) + set(DOXYGEN_SUBDIRS ${DOXYGEN_SUBDIRS} ${CMAKE_SOURCE_DIR}/imaging/actions) + set(DOXYGEN_SUBDIRS ${DOXYGEN_SUBDIRS} ${CMAKE_SOURCE_DIR}/imaging/libraries) + set(DOXYGEN_SUBDIRS ${DOXYGEN_SUBDIRS} ${CMAKE_SOURCE_DIR}/imaging/components) + + set(DOXYGEN_SUBDIRS ${DOXYGEN_SUBDIRS} ${CMAKE_SOURCE_DIR}/modeling/doc) + set(DOXYGEN_SUBDIRS ${DOXYGEN_SUBDIRS} ${CMAKE_SOURCE_DIR}/modeling/libraries) + set(DOXYGEN_SUBDIRS ${DOXYGEN_SUBDIRS} ${CMAKE_SOURCE_DIR}/viewers) + set(DOXYGEN_SUBDIRS ${DOXYGEN_SUBDIRS} ${CMAKE_SOURCE_DIR}/modeling/actions) + set(DOXYGEN_SUBDIRS ${DOXYGEN_SUBDIRS} ${CMAKE_SOURCE_DIR}/modeling/components) + string(REGEX REPLACE ";" " " DOXYGEN_INPUT_LIST "${DOXYGEN_SUBDIRS}") set(PROJECT_LOGO ${CMAKE_CURRENT_SOURCE_DIR}/libraries/core/resources/camitk-small.png) diff --git a/sdk/cmake/modules/CamiTKConfig.cmake.in b/sdk/cmake/modules/CamiTKConfig.cmake.in index 3c352bc1..6eb70c24 100644 --- a/sdk/cmake/modules/CamiTKConfig.cmake.in +++ b/sdk/cmake/modules/CamiTKConfig.cmake.in @@ -14,7 +14,7 @@ set(CAMITK_VERSION_MINOR "@CAMITK_VERSION_MINOR@") # CamiTK short version name we are looking for set(CAMITK_SHORT_VERSION_STRING "camitk-${CAMITK_VERSION_MAJOR}.${CAMITK_VERSION_MINOR}") -#-- Cmake policy +#-- Cmake policy # Error on non-existent dependency in add_dependencies => old behavior (no error) # It is useful to have add_dependencies(anyextension camitkcore) for SDK/modeling/imaging dev # It shoud not generate an error or a warning for external CEP trying to compile @@ -64,7 +64,7 @@ if(WIN32) file(TO_CMAKE_PATH "${CAMITK_USER_BASE_DIR_WINDOWS}" CAMITK_USER_BASE_DIR) else() # (UNIX OR APPLE) - # $HOME/.config/MySoft/Star Runner.ini + # $HOME/.config/MySoft/Star Runner.ini set(CAMITK_USER_BASE_DIR "$ENV{HOME}/.config") endif() set(CAMITK_USER_DIR "${CAMITK_USER_BASE_DIR}/CamiTK") @@ -100,7 +100,7 @@ if(PACKAGING_NSIS) else() set(CAMITK_CORE_TARGET_LIB_NAME library-${CAMITK_CORE_LIB_NAME}) endif() - + # All the link directories set(CAMITK_LINK_DIRECTORIES # private and public libs (including bin dir for windows) @@ -116,10 +116,13 @@ set(CAMITK_LINK_DIRECTORIES # CEP extensions dependencies ${CAMITK_PRIVATE_LIB_DIR}/components ${CAMITK_PRIVATE_LIB_DIR}/actions + ${CAMITK_PRIVATE_LIB_DIR}/viewers ${CAMITK_USER_PRIVATE_LIB_DIR}/components ${CAMITK_USER_PRIVATE_LIB_DIR}/actions + ${CAMITK_USER_PRIVATE_LIB_DIR}/viewers ${CAMITK_BUILD_PRIVATE_LIB_DIR}/components - ${CAMITK_BUILD_PRIVATE_LIB_DIR}/actions + ${CAMITK_BUILD_PRIVATE_LIB_DIR}/actions + ${CAMITK_BUILD_PRIVATE_LIB_DIR}/viewers ) # List of directories where the compiler should look for CamiTK core headers as well @@ -133,7 +136,7 @@ set(CAMITK_INCLUDE_DIRECTORIES ${CAMITK_BUILD_INCLUDE_DIR} ${QT_INCLUDE_DIRS} ${VTK_INCLUDE_DIRS} - ${CAMITK_BUILD_INCLUDE_DIR}/libraries + ${CAMITK_BUILD_INCLUDE_DIR}/libraries ) # TODO: remove ${CAMITK_BUILD_INCLUDE_DIR}/libraries => find a better way to organize dependencies @@ -146,7 +149,7 @@ if(MSVC) set(CAMITK_CORE_LIBRARIES optimized ${CAMITK_CORE_LIB_NAME} debug ${CAMITK_CORE_LIB_NAME}${CAMITK_DEBUG_POSTFIX} ) - + # Construct list of VTK libraries for linking # CAMITK_VTK_LIBRARIES = VTK input libraries at linkage foreach(VTK_LIBRARY ${VTK_LIBRARIES}) @@ -168,13 +171,13 @@ if(MSVC) endif() set(CAMITK_VTK_LIBRARIES ${CAMITK_VTK_LIBRARIES} debug ${VTK_LIBRARY_DIR}/${VTK_LIBRARY}-${CAMITK_VTK_VERSION}${CAMITK_DEBUG_POSTFIX}.lib optimized ${VTK_LIBRARY_DIR}/${VTK_LIBRARY}-${CAMITK_VTK_VERSION}.lib) endforeach() - + # add missing vtkIOExport, vtkImagingStencil, vtkIOImport, vtkImagingMath library set(CAMITK_VTK_LIBRARIES ${CAMITK_VTK_LIBRARIES} debug ${VTK_LIBRARY_DIR}/vtkIOExport-${CAMITK_VTK_VERSION}${CAMITK_DEBUG_POSTFIX}.lib optimized ${VTK_LIBRARY_DIR}/vtkIOExport-${CAMITK_VTK_VERSION}.lib) set(CAMITK_VTK_LIBRARIES ${CAMITK_VTK_LIBRARIES} debug ${VTK_LIBRARY_DIR}/vtkImagingStencil-${CAMITK_VTK_VERSION}${CAMITK_DEBUG_POSTFIX}.lib optimized ${VTK_LIBRARY_DIR}/vtkImagingStencil-${CAMITK_VTK_VERSION}.lib) set(CAMITK_VTK_LIBRARIES ${CAMITK_VTK_LIBRARIES} debug ${VTK_LIBRARY_DIR}/vtkIOImport-${CAMITK_VTK_VERSION}${CAMITK_DEBUG_POSTFIX}.lib optimized ${VTK_LIBRARY_DIR}/vtkIOImport-${CAMITK_VTK_VERSION}.lib) set(CAMITK_VTK_LIBRARIES ${CAMITK_VTK_LIBRARIES} debug ${VTK_LIBRARY_DIR}/vtkImagingMath-${CAMITK_VTK_VERSION}${CAMITK_DEBUG_POSTFIX}.lib optimized ${VTK_LIBRARY_DIR}/vtkImagingMath-${CAMITK_VTK_VERSION}.lib) - + # list of all core dependencies set(CAMITK_LIBRARIES ${CAMITK_VTK_LIBRARIES} @@ -209,15 +212,15 @@ if (UNIX) OUTPUT_STRIP_TRAILING_WHITESPACE ) endif() - + # Application man pages (always in section 1, this is an application...) - set(CAMITK_APPLICATION_MAN_INSTALL_DIR "share/man/man1") + set(CAMITK_APPLICATION_MAN_INSTALL_DIR "share/man/man1") # Desktop file always in share/applications (freedesktop standard) set(CAMITK_APPLICATION_DESKTOP_INSTALL_DIR "share/applications") # icons file always in pixmaps (should be xpm or svg) set(CAMITK_APPLICATION_PIXMAP_INSTALL_DIR "share/pixmaps") endif() - + # rpath settings for linux # This settings allow running the exe from the build tree and running them from its install location # without doing anything in particular. @@ -249,7 +252,8 @@ if("${isSystemDir}" STREQUAL "-1") set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib" "${CMAKE_INSTALL_PREFIX}/lib/${CAMITK_SHORT_VERSION_STRING}" "${CMAKE_INSTALL_PREFIX}/lib/${CAMITK_SHORT_VERSION_STRING}/components" - "${CMAKE_INSTALL_PREFIX}/lib/${CAMITK_SHORT_VERSION_STRING}/actions") + "${CMAKE_INSTALL_PREFIX}/lib/${CAMITK_SHORT_VERSION_STRING}/actions" + "${CMAKE_INSTALL_PREFIX}/lib/${CAMITK_SHORT_VERSION_STRING}/viewers") endif() #-- update module path @@ -281,13 +285,13 @@ include(CamiTKMacros) include(CamiTKLog) # TODO check this -# +# # # By default, validate all projects are build in the build/bin directory (no subfolders). # # Note that, subfolders for actions / components are added later. # set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CAMITK_BIN_DIR}) # set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CAMITK_BIN_DIR}) # set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CAMITK_BIN_DIR}) -# +# # # Remove the Debug, Release subfolders in build/bin, natively created with Visual Studio # if ( ${CMAKE_GENERATOR} MATCHES "Visual Studio") # MSVC compiler # foreach( OUTPUTCONFIG ${CMAKE_CONFIGURATION_TYPES} ) @@ -297,6 +301,6 @@ include(CamiTKLog) # set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CAMITK_BIN_DIR} CACHE TYPE STRING) # endforeach( OUTPUTCONFIG CMAKE_CONFIGURATION_TYPES ) # endif(${CMAKE_GENERATOR} MATCHES "Visual Studio") -# +# # # Create the Xml data for Project.xml description, fyi store in the global variable CAMITK_SUBPROJECTS # camitk_init_manifest_data() diff --git a/sdk/cmake/modules/macros/ExportHeaders.cmake b/sdk/cmake/modules/macros/ExportHeaders.cmake index fc2460bb..51e6725a 100644 --- a/sdk/cmake/modules/macros/ExportHeaders.cmake +++ b/sdk/cmake/modules/macros/ExportHeaders.cmake @@ -44,8 +44,8 @@ macro(export_headers) set(multiValueArgs "") cmake_parse_arguments(EXPORT_HEADER "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} ) - # special case for components: remove prefix for the destination directory - string(REGEX REPLACE "^component-|^component_|^action-|^action_|^library_|^library-" "" EXPORT_HEADER_DESTINATION "${EXPORT_HEADER_COMPONENT}") + # Remove prefix for the destination directory + string(REGEX REPLACE "^component-|^component_|^action-|^action_|^viewer-|^viewer_|^library_|^library-" "" EXPORT_HEADER_DESTINATION "${EXPORT_HEADER_COMPONENT}") # # 1. Create the build-time directory tree diff --git a/sdk/cmake/modules/macros/camitk/CamiTKExtension.cmake b/sdk/cmake/modules/macros/camitk/CamiTKExtension.cmake index 0b31388a..f946f7e7 100644 --- a/sdk/cmake/modules/macros/camitk/CamiTKExtension.cmake +++ b/sdk/cmake/modules/macros/camitk/CamiTKExtension.cmake @@ -151,8 +151,8 @@ macro(camitk_extension) elseif(${EXTENSION_NAME_CMAKE}_COMPONENT_EXTENSION) set(TYPE_EXTENSION "component") string(TOUPPER ${TYPE_EXTENSION} TYPE_EXTENSION_CMAKE) - elseif(${EXTENSION_NAME_CMAKE}_VIEWER_EXTENSION) - set(TYPE_EXTENSION "viewer") + elseif(${EXTENSION_NAME_CMAKE}_VIEWER_EXTENSION) + set(TYPE_EXTENSION "viewer") string(TOUPPER ${TYPE_EXTENSION} TYPE_EXTENSION_CMAKE) endif() @@ -368,28 +368,28 @@ macro(camitk_extension) if(GDCM_FOUND) include(${GDCM_USE_FILE}) if (MSVC) - # List all available GDCM library files - file(GLOB GDCM_LIB_FILES - LIST_DIRECTORIES false - "${GDCM_DIR}/../*${CAMITK_DEBUG_POSTFIX}.lib" - - ) - unset(GDCM_LIBRARIES) - foreach(GDCM_LIB_FILE ${GDCM_LIB_FILES}) - # Get the actual name of the library - string(REGEX REPLACE "^.*/(.*)${CAMITK_DEBUG_POSTFIX}.lib" - "\\1" GDCM_LIB_FILE_OPTIMIZED - "${GDCM_LIB_FILE}") - # Add both debug and optimized version - set(GDCM_LIBRARIES ${GDCM_LIBRARIES} debug ${GDCM_LIB_FILE} - optimized ${GDCM_LIB_FILE_OPTIMIZED}) - endforeach() - + # List all available GDCM library files + file(GLOB GDCM_LIB_FILES + LIST_DIRECTORIES false + "${GDCM_DIR}/../*${CAMITK_DEBUG_POSTFIX}.lib" + + ) + unset(GDCM_LIBRARIES) + foreach(GDCM_LIB_FILE ${GDCM_LIB_FILES}) + # Get the actual name of the library + string(REGEX REPLACE "^.*/(.*)${CAMITK_DEBUG_POSTFIX}.lib" + "\\1" GDCM_LIB_FILE_OPTIMIZED + "${GDCM_LIB_FILE}") + # Add both debug and optimized version + set(GDCM_LIBRARIES ${GDCM_LIBRARIES} debug ${GDCM_LIB_FILE} + optimized ${GDCM_LIB_FILE_OPTIMIZED}) + endforeach() + else() set(GDCM_LIBRARIES gdcmCommon gdcmDICT gdcmDSED gdcmMEXD gdcmMSFF vtkgdcm) endif() else() - message(ERROR "${EXTENSION_NAME}: GDCM 2.x or above library required. Please install GDCM.") + message(ERROR "${EXTENSION_NAME}: GDCM 2.x or above library required. Please install GDCM.") endif() endif() @@ -542,7 +542,7 @@ macro(camitk_extension) endforeach() endif() - # 3rd VIEWERS DEPENDENCIES + # 3rd VIEWERS DEPENDENCIES if(${EXTENSION_NAME_CMAKE}_NEEDS_VIEWER_EXTENSION) set(VIEWERS_DEPENDENCY_LIST "") #use for generating the project.xml file foreach(VIEWER_NEEDED ${${EXTENSION_NAME_CMAKE}_NEEDS_VIEWER_EXTENSION}) diff --git a/sdk/cmake/modules/macros/camitk/CamiTKInstallAllHeaders.cmake b/sdk/cmake/modules/macros/camitk/CamiTKInstallAllHeaders.cmake index 3d3f8bd1..c99c52a7 100644 --- a/sdk/cmake/modules/macros/camitk/CamiTKInstallAllHeaders.cmake +++ b/sdk/cmake/modules/macros/camitk/CamiTKInstallAllHeaders.cmake @@ -11,7 +11,7 @@ #! #! This macro keeps header files directories tree structure at installation. In other words, if your extension #! has its header files located in subdirectories, this tree structure will be kept the same at installation. -#! +#! #! Note that only file matching regex "*.h" in the source dir and subdir are considered headers. #! If you need to add other files, you need to use the HEADERS_TO_INSTALL option. #! @@ -25,7 +25,7 @@ #! \param COMPONENT (required) Name of the component to use. This is also the include subdirectory name #! used for copying the file #! \param GROUP (optional) Name of the group this install should be using group will be -#! prepend to the component name. This is either actions, components or libraries. +#! prepend to the component name. This is either actions, components, viewers or libraries. #! #! Example invocation: #! @@ -48,17 +48,17 @@ macro(camitk_install_all_headers) set(oneValueArgs COMPONENT GROUP) set(multiValueArgs "") cmake_parse_arguments(CAMITK_INSTALL_ALL_HEADERS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} ) - + # # 1. Create the build-time directory tree # - + # The base include directories set(CAMITK_INSTALL_ALL_HEADERS_BUILD_BASE_DIR ${CMAKE_BINARY_DIR}/include/${CAMITK_SHORT_VERSION_STRING}) # Get action, component or library name without its prefix set(CAMITK_INSTALL_ALL_HEADERS_TARGET_NAME ${CAMITK_INSTALL_ALL_HEADERS_COMPONENT}) - string(REGEX REPLACE "^component-|^component_|^action-|^action_|^library_|^library-" "" CAMITK_INSTALL_ALL_HEADERS_COMPONENT "${CAMITK_INSTALL_ALL_HEADERS_COMPONENT}") + string(REGEX REPLACE "^component-|^component_|^action-|^action_|^viewer-|^viewer_|^library_|^library-" "" CAMITK_INSTALL_ALL_HEADERS_COMPONENT "${CAMITK_INSTALL_ALL_HEADERS_COMPONENT}") # Check group directory if(CAMITK_INSTALL_ALL_HEADERS_GROUP) @@ -71,7 +71,7 @@ macro(camitk_install_all_headers) VERBATIM ) endif() - # Update base dirs + # Update base dirs set(CAMITK_INSTALL_ALL_HEADERS_BUILD_BASE_DIR ${CAMITK_INSTALL_ALL_HEADERS_BUILD_BASE_DIR}/${CAMITK_INSTALL_ALL_HEADERS_GROUP}) endif() @@ -84,13 +84,13 @@ macro(camitk_install_all_headers) VERBATIM ) endif() - # Update base dirs + # Update base dirs set(CAMITK_INSTALL_ALL_HEADERS_BUILD_BASE_DIR ${CAMITK_INSTALL_ALL_HEADERS_BUILD_BASE_DIR}/${CAMITK_INSTALL_ALL_HEADERS_COMPONENT}) - - # + + # # 2. Install the file (build-time and install-time) # - + # get the list of headers file(GLOB_RECURSE HEADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/ *.h) @@ -98,7 +98,7 @@ macro(camitk_install_all_headers) foreach(HEADER ${HEADERS}) # Get the subdirectory name of the header string(REGEX MATCH ".*/" SUBDIR ${HEADER}) - + # Create subdirectory if not already existing if(NOT EXISTS "${CAMITK_INSTALL_ALL_HEADERS_BUILD_BASE_DIR}/${SUBDIR}" AND NOT CAMITK_INSTALL_ALL_HEADERS_${SUBDIR}) # Create directory at build time @@ -110,7 +110,7 @@ macro(camitk_install_all_headers) ) set(CAMITK_INSTALL_ALL_HEADERS_${SUBDIR} "CREATED") # To avoid creating the directory another time endif() - + # Install header at build time add_custom_command( TARGET ${CAMITK_INSTALL_ALL_HEADERS_TARGET_NAME} POST_BUILD @@ -119,16 +119,15 @@ macro(camitk_install_all_headers) VERBATIM ) endforeach() - + # Install time, copy all the .h directories structure foreach(HEADER ${HEADERS}) # Get the subdirectory name of the header string(REGEX MATCH ".*/" SUBDIR ${HEADER}) - + install(FILES ${HEADER} DESTINATION include/${CAMITK_SHORT_VERSION_STRING}/${CAMITK_INSTALL_ALL_HEADERS_GROUP}/${CAMITK_INSTALL_ALL_HEADERS_COMPONENT}/${SUBDIR} COMPONENT ${CAMITK_INSTALL_ALL_HEADERS_COMPONENT} - ) + ) endforeach() endmacro() - diff --git a/sdk/cmake/modules/macros/camitk/manifest/CamiTKAddSubProject.cmake b/sdk/cmake/modules/macros/camitk/manifest/CamiTKAddSubProject.cmake index cefb5aa2..6f7d7645 100644 --- a/sdk/cmake/modules/macros/camitk/manifest/CamiTKAddSubProject.cmake +++ b/sdk/cmake/modules/macros/camitk/manifest/CamiTKAddSubProject.cmake @@ -2,22 +2,23 @@ #! @ingroup group_sdk_cmake_camitk_cdash_projects #! #! macro camitk_register_subproject adds a subproject definition for the CDash report -#! +#! #! Subprojects in CDash shows configure/build/test information by subprojects. -#! In CamiTK there are 6 types of subprojects: +#! There are 7 types of subprojects: #! - the corelib (only present in the SDK) #! - the cep library (one subproject per library of the CEP) #! - the application action (only present in the SDK for application actions) #! - the component (one subproject per component extension of the CEP) #! - the action (one subproject per action extension of the CEP) +#! - the viewer (one subproject per viewer extension of the CEP) #! - the application (one subproject per application of the CEP) #! #! Note: application actions are special actions grouped into a specific action extension. #! This unique action extension is mandatory for any CamiTK application to run properly #! (they include basic actions such as "save", "open"...) -#! +#! #! macro camitk_register_subproject is called to add one subproject and define: -#! - the target +#! - the target #! - and its dependencies (if any) #! #! This macro should be called once for each corelib, cep library component, action, and application @@ -31,11 +32,12 @@ #! - CAMITK_APPLICATION_ACTION_SUBPROJECTS is the XML fragment describing the application actions (only found in the SDK) #! - CAMITK_COMPONENT_SUBPROJECTS is the XML fragment describing the component extensions created by the CEP #! - CAMITK_ACTION_SUBPROJECTS is the XML fragment describing the action extensions created by the CEP +#! - CAMITK_VIEWER_SUBPROJECTS is the XML fragment describing the viewer extensions created by the CEP #! - CAMITK_APPLICATION_SUBPROJECTS is the XML Fragment describing applications created by the CEP #! #! Usage: #! \code -#! camitk_register_subproject(CORELIB|CEP_LIBRARY|COMPONENT|ACTION|APPLICATION targetName +#! camitk_register_subproject(CORELIB|CEP_LIBRARY|COMPONENT|ACTION|VIEWER|APPLICATION targetName #! [DEPENDENCIES dep1 dep2 dep3] #! ) #! \endcode @@ -45,47 +47,54 @@ macro(camitk_register_subproject) set(options "") - set(oneValueArgs ACTION COMPONENT CEP_LIBRARY APPLICATION CORELIB) + set(oneValueArgs ACTION COMPONENT VIEWER CEP_LIBRARY APPLICATION CORELIB) set(multiValueArgs DEPENDENCIES) cmake_parse_arguments(ADD_SUB_PROJECT "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} ) - + # # 1. get the subproject name and add it to the corresponding target list # - + # CORE LIBRARIES if(ADD_SUB_PROJECT_CORELIB) set(SUB_PROJECT_NAME ${ADD_SUB_PROJECT_CORELIB}) endif() - + # LIBRARY if(ADD_SUB_PROJECT_CEP_LIBRARY) set(SUB_PROJECT_NAME ${ADD_SUB_PROJECT_CEP_LIBRARY}) # Add the project to the corresponding list set(CAMITK_CEP_LIBRARY_TARGETS ${CAMITK_CEP_LIBRARY_TARGETS} ${SUB_PROJECT_NAME} CACHE STRING "List of library targets" FORCE) endif() - + # COMPONENTS if(ADD_SUB_PROJECT_COMPONENT) set(SUB_PROJECT_NAME ${ADD_SUB_PROJECT_COMPONENT}) # Add the project to the corresponding list set(CAMITK_COMPONENT_TARGETS ${CAMITK_COMPONENT_TARGETS} ${SUB_PROJECT_NAME} CACHE STRING "List of component extension targets" FORCE) endif() - + # ACTIONS if(ADD_SUB_PROJECT_ACTION) set(SUB_PROJECT_NAME ${ADD_SUB_PROJECT_ACTION}) # Add the project to the corresponding list set(CAMITK_ACTION_TARGETS ${CAMITK_ACTION_TARGETS} ${SUB_PROJECT_NAME} CACHE STRING "List of action extension targets" FORCE) endif() - + + # VIEWERS + if(ADD_SUB_PROJECT_VIEWER) + set(SUB_PROJECT_NAME ${ADD_SUB_PROJECT_VIEWER}) + # Add the project to the corresponding list + set(CAMITK_VIEWER_TARGETS ${CAMITK_VIEWER_TARGETS} ${SUB_PROJECT_NAME} CACHE STRING "List of viewer extension targets" FORCE) + endif() + # APPLICATION if(ADD_SUB_PROJECT_APPLICATION) set(SUB_PROJECT_NAME ${ADD_SUB_PROJECT_APPLICATION}) # Add the project to the corresponding list set(CAMITK_APPLICATION_TARGETS ${CAMITK_APPLICATION_TARGETS} ${SUB_PROJECT_NAME} CACHE STRING "List of application targets" FORCE) endif() - + # # 2. Create the XML fragment (including name and dependency list # @@ -97,10 +106,10 @@ macro(camitk_register_subproject) # concatenate all dependencies foreach(DEPENDENCY ${ADD_SUB_PROJECT_DEPENDENCIES}) set(SUBPROJECT_XML_FRAGMENT ${SUBPROJECT_XML_FRAGMENT} "") - endforeach() + endforeach() endif() set(SUBPROJECT_XML_FRAGMENT ${SUBPROJECT_XML_FRAGMENT} "") - + # # 3. add the project to the list of the CEP/CEP set subprojects # @@ -114,17 +123,17 @@ macro(camitk_register_subproject) if(ADD_SUB_PROJECT_CORELIB) set(CAMITK_CORE_LIBRARY_SUBPROJECTS ${CAMITK_CORE_LIBRARY_SUBPROJECTS} ${SUBPROJECT_XML_FRAGMENT} CACHE INTERNAL "XML description of Core library subprojects") endif() - + # LIBRARY if(ADD_SUB_PROJECT_CEP_LIBRARY) set(CAMITK_CEP_LIBRARY_SUBPROJECTS ${CAMITK_CEP_LIBRARY_SUBPROJECTS} ${SUBPROJECT_XML_FRAGMENT} CACHE INTERNAL "XML description of library subprojects") endif() - + # COMPONENTS if(ADD_SUB_PROJECT_COMPONENT) set(CAMITK_COMPONENT_SUBPROJECTS ${CAMITK_COMPONENT_SUBPROJECTS} ${SUBPROJECT_XML_FRAGMENT} CACHE INTERNAL "XML description of component extension subprojects") endif() - + # ACTIONS if(ADD_SUB_PROJECT_ACTION) # Particular case of action-applications @@ -134,11 +143,16 @@ macro(camitk_register_subproject) set(CAMITK_ACTION_SUBPROJECTS ${CAMITK_ACTION_SUBPROJECTS} ${SUBPROJECT_XML_FRAGMENT} CACHE INTERNAL "XML description of action extension subprojects") endif() endif() - + + # VIEWERS + if(ADD_SUB_PROJECT_VIEWER) + set(CAMITK_VIEWER_SUBPROJECTS ${CAMITK_VIEWER_SUBPROJECTS} ${SUBPROJECT_XML_FRAGMENT} CACHE INTERNAL "XML description of viewer extension subprojects") + endif() + # APPLICATION if(ADD_SUB_PROJECT_APPLICATION) # Add the xml fragment for the current subproject set(CAMITK_APPLICATION_SUBPROJECTS ${CAMITK_APPLICATION_SUBPROJECTS} ${SUBPROJECT_XML_FRAGMENT} CACHE INTERNAL "XML description of application subprojects") endif() - + endmacro() diff --git a/sdk/cmake/modules/macros/camitk/manifest/CamiTKInitManifestData.cmake b/sdk/cmake/modules/macros/camitk/manifest/CamiTKInitManifestData.cmake index 7bcf222c..138538fd 100644 --- a/sdk/cmake/modules/macros/camitk/manifest/CamiTKInitManifestData.cmake +++ b/sdk/cmake/modules/macros/camitk/manifest/CamiTKInitManifestData.cmake @@ -2,24 +2,25 @@ #! @ingroup group_sdk_cmake_camitk_cdash_projects #! #! MACRO camitk_init_manifest_data initializes the global variables that will -#! gather all the information about all the subprojects. +#! gather all the information about all the subprojects. #! -#! In CamiTK there are 6 types of subprojects: +#! There are 7 types of subprojects: #! - the corelib (only present in the SDK) #! - the cep library (one subproject per library of the CEP) #! - the application action (only present in the SDK for application actions) #! - the component (one subproject per component extension of the CEP) #! - the action (one subproject per action extension of the CEP) +#! - the viewer (one subproject per viewer extension of the CEP) #! - the application (one subproject per application of the CEP) #! #! Note: application actions are special actions grouped into a specific action extension. #! This unique action extension is mandatory for any CamiTK application to run properly #! (they include basic actions such as "save", "open"...) -#! +#! #! macro camitk_init_manifest_data is called only once per CEP or per CEP Set and #! reset the global cache variables that are filled with XML fragment. #! -#! The CAMITK_SUBPROJECTS variable is a XML document that concatenate all +#! The CAMITK_SUBPROJECTS variable is a XML document that concatenate all #! these variable. CAMITK_SUBPROJECTS is used to produced the "Project.xml" file #! in the build directory. The "Project.xml" file is send and later parse by CDash to #! present Continuous Integration information by subproject. @@ -30,6 +31,7 @@ #! - CAMITK_APPLICATION_ACTION_SUBPROJECTS is the XML fragment describing the application actions (only found in the SDK) #! - CAMITK_COMPONENT_SUBPROJECTS is the XML fragment describing the component extensions created by the CEP #! - CAMITK_ACTION_SUBPROJECTS is the XML fragment describing the action extensions created by the CEP +#! - CAMITK_VIEWER_SUBPROJECTS is the XML fragment describing the viewer extensions created by the CEP #! - CAMITK_APPLICATION_SUBPROJECTS is the XML Fragment describing applications created by the CEP #! #! The CAMITK_TARGETS variable list all the targets. It is also used by CDash. @@ -37,10 +39,11 @@ #! #! This macro also clears all these global cache variables. #! - CAMITK_CEP_LIBRARY_TARGETS -#! - CAMITK_COMPONENT_TARGETS -#! - CAMITK_ACTION_TARGETS +#! - CAMITK_COMPONENT_TARGETS +#! - CAMITK_ACTION_TARGETS +#! - CAMITK_VIEWER_TARGETS #! - CAMITK_APPLICATION_TARGETS -#! +#! #! usage: #! \code #! camitk_init_manifest_data() @@ -49,7 +52,7 @@ macro(camitk_init_manifest_data) if(CAMITK_EXTENSION_PROJECT_SET) if(NOT CAMITK_SUBPROJECTS) - # This is a call to camitk_init_manifest_data from the first CEP of a CEP Set + # This is a call to camitk_init_manifest_data from the first CEP of a CEP Set camitk_init_manifest_data_reset_variables(${CAMITK_EXTENSION_PROJECT_SET_NAME}) endif() # else: if CAMITK_SUBPROJECTS cache variable is defined, this means the variables were already reset @@ -57,7 +60,7 @@ macro(camitk_init_manifest_data) # This is a call to camitk_init_manifest_data from a standalone CEP camitk_init_manifest_data_reset_variables(${CMAKE_PROJECT_NAME}) endif() - + endmacro() # Intern macro to simplify camitk_init_manifest_data @@ -70,17 +73,19 @@ macro(camitk_init_manifest_data_reset_variables NAME) set(CAMITK_CEP_LIBRARY_TARGETS "" CACHE STRING "List of library extension targets" FORCE) set(CAMITK_COMPONENT_TARGETS "" CACHE STRING "List of component extension targets" FORCE) set(CAMITK_ACTION_TARGETS "" CACHE STRING "List of action extension targets" FORCE) + set(CAMITK_VIEWER_TARGETS "" CACHE STRING "List of viewer extension targets" FORCE) set(CAMITK_APPLICATION_TARGETS "" CACHE STRING "List of application targets" FORCE) - + # Subproject list (XML document) - set(CAMITK_SUBPROJECTS "" CACHE INTERNAL "XML description of all subprojects") - + set(CAMITK_SUBPROJECTS "" CACHE INTERNAL "XML description of all subprojects") + # Subprojects by category (XML fragment) set(CAMITK_CORE_LIBRARY_SUBPROJECTS "" CACHE INTERNAL "XML description of core library subprojects") set(CAMITK_CEP_LIBRARY_SUBPROJECTS "" CACHE INTERNAL "XML description of library subprojects") set(CAMITK_APPLICATION_ACTION_SUBPROJECTS "" CACHE INTERNAL "XML description of application action extension subprojects") set(CAMITK_COMPONENT_SUBPROJECTS "" CACHE INTERNAL "XML description of component extension subprojects") set(CAMITK_ACTION_SUBPROJECTS "" CACHE INTERNAL "XML description of action extension subprojects") + set(CAMITK_VIEWER_SUBPROJECTS "" CACHE INTERNAL "XML description of viewer extension subprojects") set(CAMITK_APPLICATION_SUBPROJECTS "" CACHE INTERNAL "XML description of application subprojects") - + endmacro() diff --git a/sdk/cmake/modules/macros/camitk/manifest/CamiTKWriteManifestData.cmake b/sdk/cmake/modules/macros/camitk/manifest/CamiTKWriteManifestData.cmake index d337ccd2..42e57a72 100644 --- a/sdk/cmake/modules/macros/camitk/manifest/CamiTKWriteManifestData.cmake +++ b/sdk/cmake/modules/macros/camitk/manifest/CamiTKWriteManifestData.cmake @@ -44,7 +44,7 @@ macro(camitk_write_manifest_data) # set(CAMITK_SUBPROJECTS ${CAMITK_SUBPROJECTS} " ") # set(CAMITK_SUBPROJECTS ${CAMITK_SUBPROJECTS} ${CAMITK_ACTION_SUBPROJECTS}) # set(CAMITK_SUBPROJECTS ${CAMITK_SUBPROJECTS} ${CAMITK_APPLICATION_SUBPROJECTS}) -# +# # # Add packaging source, packaging and api_doc target (COMMENTED > let's be frank, those are not compiled anymore on VMs) # # set(CAMITK_SUBPROJECTS ${CAMITK_SUBPROJECTS} "\n \n ") # # set(CAMITK_SUBPROJECTS ${CAMITK_SUBPROJECTS} "\n \n ") @@ -52,6 +52,7 @@ macro(camitk_write_manifest_data) # else() # Other external CEP set(CAMITK_SUBPROJECTS ${CAMITK_SUBPROJECTS} ${CAMITK_COMPONENT_SUBPROJECTS}) set(CAMITK_SUBPROJECTS ${CAMITK_SUBPROJECTS} ${CAMITK_ACTION_SUBPROJECTS}) + set(CAMITK_SUBPROJECTS ${CAMITK_SUBPROJECTS} ${CAMITK_VIEWER_SUBPROJECTS}) set(CAMITK_SUBPROJECTS ${CAMITK_SUBPROJECTS} ${CAMITK_APPLICATION_SUBPROJECTS}) # endif() diff --git a/sdk/cmake/modules/macros/camitk/packaging/CamiTKCEPPackaging.cmake b/sdk/cmake/modules/macros/camitk/packaging/CamiTKCEPPackaging.cmake index 044e9d4c..404f0af2 100644 --- a/sdk/cmake/modules/macros/camitk/packaging/CamiTKCEPPackaging.cmake +++ b/sdk/cmake/modules/macros/camitk/packaging/CamiTKCEPPackaging.cmake @@ -30,20 +30,21 @@ macro(camitk_cep_packaging) # CEP Packaging only works for stand-alone CEP if (NOT CAMITK_EXTENSION_PROJECT_SET) - + set(options "") set(oneValueArgs NAME VENDOR CONTACT DESCRIPTION LICENSE) set(multiValueArgs "") cmake_parse_arguments(CAMITK_CEP_PACKAGING "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} ) - + # Clean list of targets by removing duplicates -# Those may appear if configuring more than once (i.e. by manually clicking more than once on the CMake configure +# Those may appear if configuring more than once (i.e. by manually clicking more than once on the CMake configure # button before generating list(REMOVE_DUPLICATES CAMITK_ACTION_TARGETS) list(REMOVE_DUPLICATES CAMITK_COMPONENT_TARGETS) list(REMOVE_DUPLICATES CAMITK_CEP_LIBRARY_TARGETS) list(REMOVE_DUPLICATES CAMITK_APPLICATION_TARGETS) +list(REMOVE_DUPLICATES CAMITK_VIEWER_TARGETS) # package named if(CAMITK_CEP_PACKAGING_NAME) @@ -194,7 +195,7 @@ if (UNIX AND NOT WIN32) set(LSB_DISTRIB "Ubuntu12.xx") set(CPACK_DEBIAN_PACKAGE_DEPENDS "libqt4-dev, libinsighttoolkit3.20, libxml2, libvtk5.8-qt4, libxerces-c3.1 ") endif() - + # TODO Debian dependencies (see CamiTKPackaging.cmake) if(NOT CPACK_DEBIAN_PACKAGE_DEPENDS) @@ -312,14 +313,14 @@ if(WIN32 AND NOT UNIX) # MSVC compiler if (MSVC) - + message(STATUS "Packaging nsis using ${MAKENSIS} with MSVC compiler") - set(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS + set(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS ##TODO use GetPrerequisites.cmake (i.e. find a better way to list dependencies) ##get_prerequisites() is not well enough documented to justify the time investement - EP May 2011 # Qt dependencies - ${QT_BINARY_DIR}/QtCore4.dll + ${QT_BINARY_DIR}/QtCore4.dll ${QT_BINARY_DIR}/QtGui4.dll ${QT_BINARY_DIR}/QtSvg4.dll ${QT_BINARY_DIR}/QtXml4.dll @@ -327,48 +328,48 @@ if(WIN32 AND NOT UNIX) ${QT_BINARY_DIR}/QtSql4.dll ${QT_BINARY_DIR}/QtWebKit4.dll # VTK dependencies - ${VTK_DIR}/../../bin/QVTK.dll - ${VTK_DIR}/../../bin/vtkCommon.dll - ${VTK_DIR}/../../bin/vtksys.dll - ${VTK_DIR}/../../bin/vtkFiltering.dll - ${VTK_DIR}/../../bin/vtkGraphics.dll - ${VTK_DIR}/../../bin/vtkHybrid.dll - ${VTK_DIR}/../../bin/vtkIO.dll + ${VTK_DIR}/../../bin/QVTK.dll + ${VTK_DIR}/../../bin/vtkCommon.dll + ${VTK_DIR}/../../bin/vtksys.dll + ${VTK_DIR}/../../bin/vtkFiltering.dll + ${VTK_DIR}/../../bin/vtkGraphics.dll + ${VTK_DIR}/../../bin/vtkHybrid.dll + ${VTK_DIR}/../../bin/vtkIO.dll ${VTK_DIR}/../../bin/vtkImaging.dll - ${VTK_DIR}/../../bin/vtkRendering.dll + ${VTK_DIR}/../../bin/vtkRendering.dll ${VTK_DIR}/../../bin/vtkVolumeRendering.dll - ${VTK_DIR}/../../bin/vtkverdict.dll - ${VTK_DIR}/../../bin/vtkDICOMParser.dll - ${VTK_DIR}/../../bin/vtkNetCDF.dll + ${VTK_DIR}/../../bin/vtkverdict.dll + ${VTK_DIR}/../../bin/vtkDICOMParser.dll + ${VTK_DIR}/../../bin/vtkNetCDF.dll ${VTK_DIR}/../../bin/vtkNetCDF_cxx.dll - ${VTK_DIR}/../../bin/vtkexpat.dll - ${VTK_DIR}/../../bin/vtkjpeg.dll - ${VTK_DIR}/../../bin/vtkmetaio.dll - ${VTK_DIR}/../../bin/vtkpng.dll - ${VTK_DIR}/../../bin/vtktiff.dll - ${VTK_DIR}/../../bin/vtkzlib.dll - ${VTK_DIR}/../../bin/vtkInfovis.dll - ${VTK_DIR}/../../bin/vtkfreetype.dll + ${VTK_DIR}/../../bin/vtkexpat.dll + ${VTK_DIR}/../../bin/vtkjpeg.dll + ${VTK_DIR}/../../bin/vtkmetaio.dll + ${VTK_DIR}/../../bin/vtkpng.dll + ${VTK_DIR}/../../bin/vtktiff.dll + ${VTK_DIR}/../../bin/vtkzlib.dll + ${VTK_DIR}/../../bin/vtkInfovis.dll + ${VTK_DIR}/../../bin/vtkfreetype.dll ${VTK_DIR}/../../bin/vtkftgl.dll - ${VTK_DIR}/../../bin/vtkalglib.dll - ${VTK_DIR}/../../bin/vtklibxml2.dll - ${VTK_DIR}/../../bin/vtkViews.dll + ${VTK_DIR}/../../bin/vtkalglib.dll + ${VTK_DIR}/../../bin/vtklibxml2.dll + ${VTK_DIR}/../../bin/vtkViews.dll ${VTK_DIR}/../../bin/vtkexoIIc.dll - ${VTK_DIR}/../../bin/vtkWidgets.dll - ${VTK_DIR}/../../bin/vtkhdf5.dll - ${VTK_DIR}/../../bin/vtkhdf5_hl.dll + ${VTK_DIR}/../../bin/vtkWidgets.dll + ${VTK_DIR}/../../bin/vtkhdf5.dll + ${VTK_DIR}/../../bin/vtkhdf5_hl.dll ${VTK_DIR}/../../bin/LSDyna.dll # Xerces-c dependency - ${XERCESC_ROOT_DIR}/bin/xerces-c_3_1.dll + ${XERCESC_ROOT_DIR}/bin/xerces-c_3_1.dll # Libxml2 dependencies ${LIBXML2_INCLUDE_DIR}/../bin/iconv.dll ${LIBXML2_INCLUDE_DIR}/../bin/libxml2.dll ${LIBXML2_INCLUDE_DIR}/../bin/zlib1.dll - # ITK dependency + # ITK dependency ${ITK_DIR}/../../bin/ITKCommon.dll ) endif() - + # Copy those dependencies DLLs if packaging on Windows. if (PACKAGING_NSIS) include(InstallRequiredSystemLibraries) @@ -435,7 +436,7 @@ add_custom_target(camitk-${CPACK_PACKAGE_NAME}-package COMMAND ${CMAKE_COMMAND} -E remove_directory "${CEP_PACKAGING_DIR}" COMMAND ${CMAKE_COMMAND} -E remove -f ${CMAKE_BINARY_DIR}/${CEP_PACKAGE_FILENAME} COMMAND ${CMAKE_COMMAND} -E make_directory "${CEP_PACKAGING_DIR}" - COMMAND ${CMAKE_COMMAND} -E make_directory "${CEP_PACKAGING_DIR}/share/${CAMITK_SHORT_VERSION_STRING}/cep" + COMMAND ${CMAKE_COMMAND} -E make_directory "${CEP_PACKAGING_DIR}/share/${CAMITK_SHORT_VERSION_STRING}/cep" # copy all cep files COMMAND ${CMAKE_COMMAND} -E copy_directory "${CMAKE_BINARY_DIR}/lib" "${CEP_PACKAGING_DIR}/lib" COMMAND ${CMAKE_COMMAND} -E copy_directory "${CMAKE_BINARY_DIR}/bin" "${CEP_PACKAGING_DIR}/bin" @@ -444,7 +445,7 @@ add_custom_target(camitk-${CPACK_PACKAGE_NAME}-package # copy cep manifest COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_BINARY_DIR}/CEPPackageManifest.xml ${CEP_PACKAGING_DIR}/share/${CAMITK_SHORT_VERSION_STRING}/cep/${CPACK_PACKAGE_NAME}.xml # compress - COMMAND ${CMAKE_COMMAND} -E tar cvj "${CMAKE_BINARY_DIR}/${CEP_PACKAGE_FILENAME}" "${CEP_PACKAGING_DIR}" + COMMAND ${CMAKE_COMMAND} -E tar cvj "${CMAKE_BINARY_DIR}/${CEP_PACKAGE_FILENAME}" "${CEP_PACKAGING_DIR}" WORKING_DIRECTORY ${CMAKE_BINARY_DIR} # configure back for normal build COMMAND ${CMAKE_COMMAND} -DPACKAGING_NSIS:BOOL=OFF ${CMAKE_BINARY_DIR} @@ -477,6 +478,12 @@ foreach(TARGET_NAME_ITERATOR ${CAMITK_ACTION_TARGETS}) set(CEP_PACKAGE_MANIFEST_XML ${CEP_PACKAGE_MANIFEST_XML} " ${TARGET_NAME}") endforeach() set(CEP_PACKAGE_MANIFEST_XML ${CEP_PACKAGE_MANIFEST_XML} " ") +set(CEP_PACKAGE_MANIFEST_XML ${CEP_PACKAGE_MANIFEST_XML} " ") +foreach(TARGET_NAME_ITERATOR ${CAMITK_VIEWER_TARGETS}) + string(REPLACE "viewer-" "" TARGET_NAME ${TARGET_NAME_ITERATOR}) + set(CEP_PACKAGE_MANIFEST_XML ${CEP_PACKAGE_MANIFEST_XML} " ${TARGET_NAME}") +endforeach() +set(CEP_PACKAGE_MANIFEST_XML ${CEP_PACKAGE_MANIFEST_XML} " ") set(CEP_PACKAGE_MANIFEST_XML ${CEP_PACKAGE_MANIFEST_XML} " ") foreach(TARGET_NAME_ITERATOR ${CAMITK_COMPONENT_TARGETS}) string(REPLACE "component-" "" TARGET_NAME ${TARGET_NAME_ITERATOR}) @@ -502,6 +509,6 @@ string (REGEX REPLACE "[\\](.)" "\\1" CEP_PACKAGE_MANIFEST_XML_TEXT "${CEP_PACKA file(WRITE ${CMAKE_BINARY_DIR}/CEPPackageManifest.xml ${CEP_PACKAGE_MANIFEST_XML_TEXT}) message(STATUS "Generated CEP manifest in CEPPackageManifest.xml") - + endif() # Standalone CEP endmacro() diff --git a/sdk/doc/groups.h b/sdk/doc/groups.h index c83402bf..692f5c10 100644 --- a/sdk/doc/groups.h +++ b/sdk/doc/groups.h @@ -134,7 +134,7 @@ * @ingroup group_sdk * The applications of the CamiTK SDK. * CamiTK applications are Qt applications. When featuring end user graphical interfaces, they are composed of several @ref camitk::Viewer. - * You may inherits the @ref camitk::MainWindow "MainWindow" class. The MainWindow class is a kind of super presenter : it instantiates and organizes all the viewers in an application GUI. Check the wiki tutorial : create a new application. + * You may inherits the @ref camitk::MainWindow "MainWindow" class. The MainWindow class is a kind of super presenter : it instantiates and organizes all the viewers in an application GUI. Check the wiki tutorial : create a new application. * * * @defgroup group_sdk_application_asm Action State Machine (ASM) @@ -437,6 +437,6 @@ * @defgroup group_sdk_cmake_camitk_test_level level * @ingroup group_sdk_cmake_camitk_test * CamiTK CMake macros used generating the mediawiki tab containing the list of all functionnal tests, classified by CamiTK extensions with their given LEVEL. - * @see https://forge.imag.fr/plugins/mediawiki/wiki/camitk/index.php/Testing_level_in_CamiTK + * @see the test framework pages on the wiki * **/ diff --git a/sdk/doc/mainpage.h b/sdk/doc/mainpage.h index 15cb3043..8b9bfdfc 100644 --- a/sdk/doc/mainpage.h +++ b/sdk/doc/mainpage.h @@ -37,13 +37,13 @@ * @section getting-started Getting started * * @subsection how-to-extend-camitk How to add a new action or component ? - * To add a new action or component to CamiTK, you will need to create a new dynamic link library that extends the framework with your desired data structure and / or algorithms. You may want to use the CamiTK wizard to automatically generate a code skeleton for your extension. Please check the wiki documentation about adding a new component / action. + * To add a new action or component to CamiTK, you will need to create a new dynamic link library that extends the framework with your desired data structure and / or algorithms. You may want to use the CamiTK wizard to automatically generate a code skeleton for your extension. Please check the wiki documentation about adding a new component / action. * * @subsection how-to-create-new-application How to create a new application ? - * You may inherits the @ref camitk::MainWindow "MainWindow" class. The MainWindow class is a kind of super presenter : it instantiates and organizes all the viewers in an application GUI. Check the wiki tutorial : create a new applicaiton. + * You may inherits the @ref camitk::MainWindow "MainWindow" class. The MainWindow class is a kind of super presenter : it instantiates and organizes all the viewers in an application GUI. Check the wiki tutorial : create a new applicaiton. * * @subsection tutorials Tutorials - * Many tutorials are proposed in the CamiTK wiki (you may want to edit it and share your knowledge). + * Many tutorials are proposed in the CamiTK wiki (you may want to edit it and share your knowledge). * * @section HomePage Home Page * The home page of the project can be found at : camitk.imag.fr diff --git a/sdk/doc/relatedpages.h b/sdk/doc/relatedpages.h index c0dc41fd..d2673e66 100644 --- a/sdk/doc/relatedpages.h +++ b/sdk/doc/relatedpages.h @@ -4,7 +4,7 @@ * The home page of the project can be found at : camitk.imag.fr * * @page wiki CamiTK wiki - * Installation instructions, many tips and tutorials are proposed in the CamiTK wiki (you may want to edit it and share your knowledge). + * Installation instructions, many tips and tutorials are proposed in the CamiTK wiki (you may want to edit it and share your knowledge). * * \namespace CMake * @@ -15,4 +15,4 @@ * * @page CamiTKBuildSystem The CamiTK Build System (based on CMake Macros) * - **/ \ No newline at end of file + **/ diff --git a/sdk/libraries/cepgenerator/CepGenerator.h b/sdk/libraries/cepgenerator/CepGenerator.h index 1f88b1bb..f324454d 100644 --- a/sdk/libraries/cepgenerator/CepGenerator.h +++ b/sdk/libraries/cepgenerator/CepGenerator.h @@ -55,7 +55,7 @@ class ExtensionGenerator; * This class contains the entry points to generate CEP. * * A CEP is generated form an XML file or from a dom xml-schema. \n - * See https://forge.imag.fr/plugins/mediawiki/wiki/camitk/index.php/CEP to understand how a CEP is buildt. \n + * See wiki to understand how a CEP is buildt. \n * Release 3.5: Suppose that the CEP does NOT already exist. * **/ diff --git a/sdk/libraries/cepgenerator/resources/actions.CMakeLists.txt.in b/sdk/libraries/cepgenerator/resources/actions.CMakeLists.txt.in index 9bc1e480..28abef73 100644 --- a/sdk/libraries/cepgenerator/resources/actions.CMakeLists.txt.in +++ b/sdk/libraries/cepgenerator/resources/actions.CMakeLists.txt.in @@ -1,7 +1,7 @@ # # DO NOT EDIT THIS FILE (unless you REALLY know what you are doing) # -# To add a component, just add a subdirectory (the component name is the +# To add a action, just add a subdirectory (the action name is the # directory name). Add all your code there and a text file called # CMakeLists.txt # In your CMakeLists.txt, use the camitk_extension(ACTION_EXTENSION ...) macro appropriately diff --git a/sdk/libraries/core/CamiTKAPI.h b/sdk/libraries/core/CamiTKAPI.h index 28647492..849b135d 100644 --- a/sdk/libraries/core/CamiTKAPI.h +++ b/sdk/libraries/core/CamiTKAPI.h @@ -97,5 +97,8 @@ using ViewerSet = QSet; /// A list of Action using ActionList = QList; + +/// A list of Viewer +using ViewerList = QList; } #endif diff --git a/sdk/libraries/core/Core.cpp b/sdk/libraries/core/Core.cpp index 5be7431f..5252a5ce 100644 --- a/sdk/libraries/core/Core.cpp +++ b/sdk/libraries/core/Core.cpp @@ -28,6 +28,7 @@ #include "CamiTKVersion.h" #include "ExtensionManager.h" #include "Action.h" +#include "Viewer.h" #include "Application.h" // -- QT stuff @@ -111,6 +112,7 @@ const QString Core::getPaths() { diagnosis << "- Test Data Directory...................... " + Core::getTestDataDir(); diagnosis << "- Component Extension Directories.......... " + Core::getComponentDirectories().join("\n "); diagnosis << "- Action Extension Directories............. " + Core::getActionDirectories().join("\n "); + diagnosis << "- Viewer Extension Directories............. " + Core::getViewerDirectories().join("\n "); return diagnosis.join("\n"); } @@ -225,6 +227,40 @@ const QString Core::getConfig() { diagnosis << "- Number of Action Extensions.............. " + QString::number(extensionCount) + " (locations: " + QString::number(globalCount) + " global, " + QString::number(localCount) + " local, " + QString::number(workingDirCount) + " in working directory, " + QString::number(userCount) + " manually installed by user)"; diagnosis << "- Number of Actions........................ " + QString::number(extensionUnitCount); + + //-- viewer extensions + extensionCount = extensionUnitCount = globalCount = localCount = workingDirCount = userCount = 0; + + QStringList viewers; + const QList< ViewerExtension* >& allViewers = ExtensionManager::getViewerExtensionsList(); + + foreach (ViewerExtension* ve, allViewers) { + QStringList viewerNames; + for (Viewer* v : ve->getViewers()) { + viewerNames << v->getName(); + } + + installationDirectory = ExtensionManager::getInstallationString(ve->getLocation(), globalDir, userDir, currentWorkingDir); + + viewers << " - " + installationDirectory + " " + ve->getName().leftJustified(35, '.') + " " + QString::number(ve->getViewers().size()) + " viewers"; // + ": " + viewerNames.join(", "); + extensionCount++; + extensionUnitCount += ve->getViewers().size(); + if (installationDirectory == "[G]") { + globalCount++; + } + else if (installationDirectory == "[L]") { + localCount++; + } + else if (installationDirectory == "[W]") { + workingDirCount++; + } + else if (installationDirectory == "[U]") { + userCount++; + } + } + + diagnosis << "- Number of Viewer Extensions.............. " + QString::number(extensionCount) + " (locations: " + QString::number(globalCount) + " global, " + QString::number(localCount) + " local, " + QString::number(workingDirCount) + " in working directory, " + QString::number(userCount) + " manually installed by user)"; + diagnosis << "- Number of Viewers........................ " + QString::number(extensionUnitCount); //-- details of the extensions diagnosis << "- Registered components:"; @@ -233,6 +269,9 @@ const QString Core::getConfig() { diagnosis << "- Registered actions:"; diagnosis += actions; + diagnosis << "- Registered viewers:"; + diagnosis += viewers; + return diagnosis.join("\n"); } @@ -271,6 +310,11 @@ const QStringList Core::getComponentDirectories() { return getInstallDirectories("lib/" + QString(Core::shortVersion) + "/components"); } +// ------------- getViewerDirectories (static) ----------------- +const QStringList Core::getViewerDirectories() { + return getInstallDirectories("lib/" + QString(Core::shortVersion) + "/viewers"); +} + // ------------- getTestDataDir (static) ----------------- const QString Core::getTestDataDir() { QStringList testDataDirectories = getInstallDirectories("share/" + QString(Core::shortVersion) + "/testdata"); diff --git a/sdk/libraries/core/Core.h b/sdk/libraries/core/Core.h index 17f054c5..f2eb6265 100644 --- a/sdk/libraries/core/Core.h +++ b/sdk/libraries/core/Core.h @@ -71,6 +71,14 @@ public: */ static const QStringList getActionDirectories(); + /** get all the viewers directories. It gets all the valid directories + * where components are installed, and insert them in this particular order: + * 1. current working directory (build install tree) + * 2. user config directory (user install tree) + * 3. CamiTK SDK installation directory (global install tree) + */ + static const QStringList getViewerDirectories(); + /** Get a valid camitk test data directory name. It returns the first valid * test data directory that is found. Checking is done in this particular order: * 1. current working directory (build install tree) diff --git a/sdk/libraries/core/ExtensionManager.h b/sdk/libraries/core/ExtensionManager.h index f2893f23..4dd3d29d 100644 --- a/sdk/libraries/core/ExtensionManager.h +++ b/sdk/libraries/core/ExtensionManager.h @@ -30,6 +30,7 @@ // -- Core stuff #include "ComponentExtension.h" #include "ActionExtension.h" +#include "ViewerExtension.h" #include "CamiTKAPI.h" #include "AbortException.h" @@ -202,6 +203,40 @@ public: static bool unloadActionExtension(QString); ///@} + /// @name Viewer extension list management + ///@{ + + /// unload all viewer extensions and delete instantiated actions + static void unloadAllViewerExtensions(); + + /** + * @brief Get the list of registered ViewerExtension. + * The list contains unique elements (no duplicates possible) and is alphabitically sorted. + * + * @note + * The list is read-only and cannot be modified. + * This list is useful to loop over the loaded ViewerExtension, especially when order counts. + * + * @return list of unique ViewerExtension loaded in the Core. + */ + static const QList getViewerExtensionsList(); + + /** + * @brief Get the Viewer Extension corresponding to the given shared library file. + * + * If the given shared library is not loaded return nullptr. The shared library file should + * be given as a complete filepath in the QString. + * + * @return nullptr if the given shared library complete path is not loaded. + */ + static ViewerExtension* getViewerExtension(QString); + + /** Unload an viewer extension using its .dll/.so/.dylib filename + * @return false if the plugin could not be unloaded - still in use somewhere + */ + static bool unloadViewerExtension(QString); + ///@} + private: /** get the singleton map of loaded component plugins for files (the key is the file extension) * This is the private (intern) method. @@ -223,13 +258,22 @@ private: /** get the singleton map of loaded action plugins (the key is the shared object/dll/dylib filename) * This is the private (intern) method. - * The component extension map is updated by loadActionExtension, unloadActionExtension and autoloadActionExtensions. + * The action extension map is updated by loadActionExtension, unloadActionExtension and autoloadActionExtensions. * This method follows the "construct on first use" idiom/design-pattern. * It therefore avoids the infamous "static initialization order fiasco", * see http://www.parashift.com/c++-faq/ctors.html */ static QMap& getActionExtensionMap(); + /** get the singleton map of loaded viewer plugins (the key is the shared object/dll/dylib filename) + * This is the private (intern) method. + * The viewer extension map is updated by loadViewerExtension, unloadViewerExtension and autoloadViewerExtensions. + * This method follows the "construct on first use" idiom/design-pattern. + * It therefore avoids the infamous "static initialization order fiasco", + * see http://www.parashift.com/c++-faq/ctors.html + */ + static QMap& getViewerExtensionMap(); + /// return the extensions file filter static QStringList getExtensionFilter(); @@ -271,9 +315,16 @@ private: * @note This method does not take const input arguments as the ActionExtension::getName() accessor * is a mutable method (not const). * This should be updated, but would change the CamiTK API - * see https://forge.imag.fr/plugins/mediawiki/wiki/camitk/index.php/Core_developper_guidelines + * check the Wiki for Code developer guidelines */ static bool actionExtensionLessThan(ActionExtension* left, ActionExtension* right); + + /** + * @brief Custom comparaison method between two ViewerExtension* + * based on the same principle as actionExtensionLessThan(..) + * @see actionExtensionLessThan(..) for more information + */ + static bool viewerExtensionLessThan(ViewerExtension* left, ViewerExtension* right); ///@} }; diff --git a/sdk/libraries/core/component/image/SingleImageComponent.cpp b/sdk/libraries/core/component/image/SingleImageComponent.cpp index d899b4f2..7a551aaa 100644 --- a/sdk/libraries/core/component/image/SingleImageComponent.cpp +++ b/sdk/libraries/core/component/image/SingleImageComponent.cpp @@ -29,8 +29,7 @@ // -- Core stuff #include "Frame.h" - -#include "Log.h" +#include "Application.h" // -- VTK stuff #include diff --git a/tutorials/actions/CMakeLists.txt b/tutorials/actions/CMakeLists.txt index 91cf4b55..dbdc33b5 100644 --- a/tutorials/actions/CMakeLists.txt +++ b/tutorials/actions/CMakeLists.txt @@ -1,10 +1,10 @@ # # DO NOT EDIT THIS FILE (unless you REALLY know what you are doing) # -# To add a component, just add a subdirectory (the component name is the +# To add an action, just add a subdirectory (the action name is the # directory name). Add all your code there and a text file called # CMakeLists.txt -# In your CMakeLists.txt, use the action_extension() macro apropriately +# In your CMakeLists.txt, use the camitk_extension(ACTION_EXTENSION ...) macro apropriately # find components get_subdirectories(ACTIONS_LIST) diff --git a/tutorials/applications/menubar/MyAppMainWindow.cpp b/tutorials/applications/menubar/MyAppMainWindow.cpp index 314f9670..1062832f 100644 --- a/tutorials/applications/menubar/MyAppMainWindow.cpp +++ b/tutorials/applications/menubar/MyAppMainWindow.cpp @@ -36,6 +36,8 @@ // -- Qt Stuff #include +using namespace camitk; + // ------------- constructor ----------------- MyAppMainWindow::MyAppMainWindow() : MainWindow("MyApp - " + tr(Core::version)) { diff --git a/tutorials/applications/menubar/MyAppMainWindow.h b/tutorials/applications/menubar/MyAppMainWindow.h index 0334d988..313b1ddb 100644 --- a/tutorials/applications/menubar/MyAppMainWindow.h +++ b/tutorials/applications/menubar/MyAppMainWindow.h @@ -29,7 +29,6 @@ // -- CamiTK Core stuff #include -using namespace camitk; /** * This Class describes a very simple application. diff --git a/tutorials/components/CMakeLists.txt b/tutorials/components/CMakeLists.txt index fe490f3f..cfe91007 100644 --- a/tutorials/components/CMakeLists.txt +++ b/tutorials/components/CMakeLists.txt @@ -4,7 +4,7 @@ # To add a component, just add a subdirectory (the component name is the # directory name). Add all your code there and a text file called # CMakeLists.txt -# In your CMakeLists.txt, use the component_extension() macro apropriately +# In your CMakeLists.txt, use the camitk_extension(COMPONENT_EXTENSION ...) macro apropriately # find components get_subdirectories(COMPONENTS_LIST) diff --git a/tutorials/viewers/CMakeLists.txt b/tutorials/viewers/CMakeLists.txt index 635c9799..696df4d3 100644 --- a/tutorials/viewers/CMakeLists.txt +++ b/tutorials/viewers/CMakeLists.txt @@ -1,7 +1,7 @@ # # DO NOT EDIT THIS FILE (unless you REALLY know what you are doing) # -# To add a component, just add a subdirectory (the component name is the +# To add a viewer, just add a subdirectory (the viewer name is the # directory name). Add all your code there and a text file called # CMakeLists.txt # In your CMakeLists.txt, use the camitk_extension(VIEWER_EXTENSION ...) macro appropriately -- GitLab From 14e44370d8f5b1741d41600ded4b3a9f560ffe02 Mon Sep 17 00:00:00 2001 From: Emmanuel Promayon Date: Wed, 5 Feb 2020 14:36:40 +0100 Subject: [PATCH 06/15] FIXED embed the arbitrary viewer in the medical image viewer --- .../AnglesAndTranslationAction.cpp | 3 ++- .../AnglesAndTranslationWidget.cpp | 6 +++--- .../medicalimageviewer/MedicalImageViewer.cpp | 16 +++++++++------- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/sdk/actions/image/arbitraryslice/AnglesAndTranslationAction.cpp b/sdk/actions/image/arbitraryslice/AnglesAndTranslationAction.cpp index c60a65bf..a20381bc 100644 --- a/sdk/actions/image/arbitraryslice/AnglesAndTranslationAction.cpp +++ b/sdk/actions/image/arbitraryslice/AnglesAndTranslationAction.cpp @@ -123,7 +123,8 @@ void AnglesAndTranslationAction::update() { // update central viewer MedicalImageViewer::LayoutVisibility visibleViewer = static_cast(property("Visible Viewer").toInt()); - MedicalImageViewer::getInstance()->setVisibleViewer(visibleViewer); + + dynamic_cast(Application::getViewer("MedicalImageViewer"))->setVisibleViewer(visibleViewer); // keep property up-to-date when the GUI will change blockEvent = false; diff --git a/sdk/actions/image/arbitraryslice/AnglesAndTranslationWidget.cpp b/sdk/actions/image/arbitraryslice/AnglesAndTranslationWidget.cpp index 12e4829f..0869daaa 100644 --- a/sdk/actions/image/arbitraryslice/AnglesAndTranslationWidget.cpp +++ b/sdk/actions/image/arbitraryslice/AnglesAndTranslationWidget.cpp @@ -84,21 +84,21 @@ void AnglesAndTranslationWidget::updateGUI() { // -------------------- showArbitraryViewer -------------------- void AnglesAndTranslationWidget::showArbitraryViewer(bool buttonState) { if (buttonState) { - myAction->setProperty("Visible Viewer", camitk::MedicalImageViewer::VIEWER_ARBITRARY); + myAction->setProperty("Visible Viewer", MedicalImageViewer::VIEWER_ARBITRARY); } } // -------------------- show3DViewer -------------------- void AnglesAndTranslationWidget::show3DViewer(bool buttonState) { if (buttonState) { - myAction->setProperty("Visible Viewer", camitk::MedicalImageViewer::VIEWER_3D); + myAction->setProperty("Visible Viewer", MedicalImageViewer::VIEWER_3D); } } // -------------------- showAllViewer -------------------- void AnglesAndTranslationWidget::showAllViewer(bool buttonState) { if (buttonState) { - myAction->setProperty("Visible Viewer", camitk::MedicalImageViewer::VIEWER_ALL); + myAction->setProperty("Visible Viewer", MedicalImageViewer::VIEWER_ALL); } } diff --git a/sdk/viewers/medicalimageviewer/MedicalImageViewer.cpp b/sdk/viewers/medicalimageviewer/MedicalImageViewer.cpp index 76b46a00..4602f614 100644 --- a/sdk/viewers/medicalimageviewer/MedicalImageViewer.cpp +++ b/sdk/viewers/medicalimageviewer/MedicalImageViewer.cpp @@ -108,11 +108,6 @@ QWidget* MedicalImageViewer::getWidget() { frame->setObjectName("MedicalImageViewer Frame"); frame->setFrameStyle(QFrame::StyledPanel | QFrame::Plain); - //-- init layout - frameLayout = new QGridLayout(frame); - frameLayout->setSpacing(0); - frameLayout->setMargin(0); - // gulp the enum viewerVisibility.append(VIEWER_3D); viewerVisibility.append(VIEWER_AXIAL); @@ -123,10 +118,15 @@ QWidget* MedicalImageViewer::getWidget() { // list of viewer name viewers.insert(VIEWER_3D, Application::getViewer("3DViewer")); - viewers.insert(VIEWER_ARBITRARY, Application::getViewer("arbitraryViewer")); viewers.insert(VIEWER_AXIAL, Application::getViewer("axialViewer")); viewers.insert(VIEWER_CORONAL, Application::getViewer("coronalViewer")); viewers.insert(VIEWER_SAGITTAL, Application::getViewer("sagittalViewer")); + viewers.insert(VIEWER_ARBITRARY, Application::getViewer("arbitraryViewer")); + + //-- init layout + frameLayout = new QGridLayout(frame); + frameLayout->setSpacing(0); + frameLayout->setMargin(0); /// the layout for the arbitrary/axial at the top left position of frameLayout QVBoxLayout* innerLayout = new QVBoxLayout(); @@ -140,8 +140,10 @@ QWidget* MedicalImageViewer::getWidget() { Application::getViewer("sagittalViewer")->embedIn(innerLayout); innerLayout = new QVBoxLayout(); frameLayout->addLayout(innerLayout, 0, 1); // north-east + Application::getViewer("3DViewer")->embedIn(innerLayout); - + Application::getViewer("arbitraryViewer")->embedIn(innerLayout); + //-- connect foreach (LayoutVisibility v, viewerVisibility) { if (viewers.value(v)) { // prevent ALL -- GitLab From dc4aba607ba515521a3a3de21f28c86d6dd0d953 Mon Sep 17 00:00:00 2001 From: Emmanuel Promayon Date: Wed, 5 Feb 2020 15:42:52 +0100 Subject: [PATCH 07/15] NEW Imp show all central viewer The show viewer actions are not needed anymore --- sdk/applications/imp/ImpMainWindow.cpp | 23 ++++++- tutorials/actions/bitmapviewer/CMakeLists.txt | 1 - .../actions/bitmapviewer/ShowBitmapViewer.cpp | 68 ------------------- .../actions/bitmapviewer/ShowBitmapViewer.h | 58 ---------------- .../ShowBitmapViewerExtension.cpp | 32 --------- .../bitmapviewer/ShowBitmapViewerExtension.h | 62 ----------------- .../actions/showtextviewer/ShowTextViewer.cpp | 68 ------------------- .../applications/fancy/FancyMainWindow.cpp | 3 + .../applications/menubar/MyAppMainWindow.h | 2 +- 9 files changed, 26 insertions(+), 291 deletions(-) delete mode 100644 tutorials/actions/bitmapviewer/CMakeLists.txt delete mode 100644 tutorials/actions/bitmapviewer/ShowBitmapViewer.cpp delete mode 100644 tutorials/actions/bitmapviewer/ShowBitmapViewer.h delete mode 100644 tutorials/actions/bitmapviewer/ShowBitmapViewerExtension.cpp delete mode 100644 tutorials/actions/bitmapviewer/ShowBitmapViewerExtension.h delete mode 100644 tutorials/actions/showtextviewer/ShowTextViewer.cpp diff --git a/sdk/applications/imp/ImpMainWindow.cpp b/sdk/applications/imp/ImpMainWindow.cpp index fe04a347..8d646d4c 100644 --- a/sdk/applications/imp/ImpMainWindow.cpp +++ b/sdk/applications/imp/ImpMainWindow.cpp @@ -485,7 +485,28 @@ void ImpMainWindow::updateViewMenu() { viewerAction->setCheckable(true); viewerAction->setChecked(viewer == centralViewer); viewerAction->setIcon(viewer->getIcon()); - QString tipString = "Hide/show the " + viewer->objectName() + " in the central viewer"; + QString tipString = "Hide/show the " + viewer->getName() + " in the central viewer"; + viewerAction->setStatusTip(tr(tipString.toStdString().c_str())); + viewerAction->setWhatsThis(tr(tipString.toStdString().c_str())); + // add the toggle action slot using C++11 lambda so that everything is contained inside viewMenu + connect(viewerAction, &QAction::toggled, [ = ](bool) { + setCentralViewer(viewer); + }); + } + } + + toggleCentralWidgetMenu-> addSeparator(); + + // add other viewers that are not initially part of imp, but that are + // added by supplementary viewer extensions + foreach (Viewer* viewer, Application::getViewers()) { + if (!viewers.contains(viewer) && viewer->getLayout() == Viewer::STACKED) { + // viewerAction is own by viewMenu, viewMenu->clear() will delete it + QAction* viewerAction = toggleCentralWidgetMenu->addAction(viewer->getName()); + viewerAction->setCheckable(true); + viewerAction->setChecked(viewer == centralViewer); + viewerAction->setIcon(viewer->getIcon()); + QString tipString = "Hide/show the " + viewer->getName() + " in the central viewer"; viewerAction->setStatusTip(tr(tipString.toStdString().c_str())); viewerAction->setWhatsThis(tr(tipString.toStdString().c_str())); // add the toggle action slot using C++11 lambda so that everything is contained inside viewMenu diff --git a/tutorials/actions/bitmapviewer/CMakeLists.txt b/tutorials/actions/bitmapviewer/CMakeLists.txt deleted file mode 100644 index 9cc3535d..00000000 --- a/tutorials/actions/bitmapviewer/CMakeLists.txt +++ /dev/null @@ -1 +0,0 @@ -camitk_extension(ACTION_EXTENSION) diff --git a/tutorials/actions/bitmapviewer/ShowBitmapViewer.cpp b/tutorials/actions/bitmapviewer/ShowBitmapViewer.cpp deleted file mode 100644 index c784fc1a..00000000 --- a/tutorials/actions/bitmapviewer/ShowBitmapViewer.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/***************************************************************************** - * $CAMITK_LICENCE_BEGIN$ - * - * CamiTK - Computer Assisted Medical Intervention ToolKit - * (c) 2001-2018 Univ. Grenoble Alpes, CNRS, TIMC-IMAG UMR 5525 (GMCAO) - * - * Visit http://camitk.imag.fr for more information - * - * This file is part of CamiTK. - * - * CamiTK is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * CamiTK is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License version 3 for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with CamiTK. If not, see . - * - * $CAMITK_LICENCE_END$ - ****************************************************************************/ - -#include "ShowBitmapViewer.h" -#include "BitmapViewer.h" - -#include -#include -#include - -#include -#include - -using namespace camitk; - -// -------------------- ShowBitmapViewer -------------------- -ShowBitmapViewer::ShowBitmapViewer(ActionExtension* extension) : Action(extension) { - setName("Show Bitmap Viewer"); - setEmbedded(false); // not embedded (and as the - setDescription("Tutorial action that set the bitmap viewer as the central viewer. Trigger this action when no component is selected"); - setComponent(""); - - setFamily("Tutorial"); - addTag("Viewer"); - addTag("BitmapViewer"); - addTag("MainWindow"); - - firstCall = true; -} - -// --------------- getWidget ------------------- -QWidget* ShowBitmapViewer::getWidget() { - return nullptr; -} - -// --------------- apply ------------------- -Action::ApplyStatus ShowBitmapViewer::apply() { - // just add the BitMap viewer in the central viewer - Application::getMainWindow()->setCentralViewer(Application::getViewer("BitmapViewer")); - Application::refresh(); - if (firstCall) { - CAMITK_INFO("TIP: switch central wiewers from the menu: do you know that you can use the \"View Menu\" item \"Toggle Central Viewers\" to switch the central viewer from/to the Medical Image Viewer"); - firstCall = false; - } - return SUCCESS; -} diff --git a/tutorials/actions/bitmapviewer/ShowBitmapViewer.h b/tutorials/actions/bitmapviewer/ShowBitmapViewer.h deleted file mode 100644 index fc56562e..00000000 --- a/tutorials/actions/bitmapviewer/ShowBitmapViewer.h +++ /dev/null @@ -1,58 +0,0 @@ -/***************************************************************************** - * $CAMITK_LICENCE_BEGIN$ - * - * CamiTK - Computer Assisted Medical Intervention ToolKit - * (c) 2001-2018 Univ. Grenoble Alpes, CNRS, TIMC-IMAG UMR 5525 (GMCAO) - * - * Visit http://camitk.imag.fr for more information - * - * This file is part of CamiTK. - * - * CamiTK is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * CamiTK is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License version 3 for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with CamiTK. If not, see . - * - * $CAMITK_LICENCE_END$ - ****************************************************************************/ - -#ifndef SHOW_BITMAP_VIEWER_H -#define SHOW_BITMAP_VIEWER_H - -#include - -namespace camitk { -class InteractiveViewer; -class Viewer; -} - -/** - * Demonstrates how to switch the central image viewer. - */ -class ShowBitmapViewer : public camitk::Action { - -public: - /// the constructor - ShowBitmapViewer(camitk::ActionExtension*); - - /// the destructor - virtual ~ShowBitmapViewer() = default; - - /// method called when the action when the action is triggered (i.e. started) - virtual QWidget* getWidget(); - -public slots: - /// method called when the action is applied - virtual ApplyStatus apply(); - - bool firstCall; -}; - -#endif // SHOW_BITMAP_VIEWER_H diff --git a/tutorials/actions/bitmapviewer/ShowBitmapViewerExtension.cpp b/tutorials/actions/bitmapviewer/ShowBitmapViewerExtension.cpp deleted file mode 100644 index ec10627b..00000000 --- a/tutorials/actions/bitmapviewer/ShowBitmapViewerExtension.cpp +++ /dev/null @@ -1,32 +0,0 @@ -/***************************************************************************** - * $CAMITK_LICENCE_BEGIN$ - * - * CamiTK - Computer Assisted Medical Intervention ToolKit - * (c) 2001-2018 Univ. Grenoble Alpes, CNRS, TIMC-IMAG UMR 5525 (GMCAO) - * - * Visit http://camitk.imag.fr for more information - * - * This file is part of CamiTK. - * - * CamiTK is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * CamiTK is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License version 3 for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with CamiTK. If not, see . - * - * $CAMITK_LICENCE_END$ - ****************************************************************************/ -#include "ShowBitmapViewerExtension.h" -#include "ShowBitmapViewer.h" - -// -------------------- init -------------------- -void ShowBitmapViewerExtension::init() { - registerNewAction(ShowBitmapViewer); -} - diff --git a/tutorials/actions/bitmapviewer/ShowBitmapViewerExtension.h b/tutorials/actions/bitmapviewer/ShowBitmapViewerExtension.h deleted file mode 100644 index 24800fd8..00000000 --- a/tutorials/actions/bitmapviewer/ShowBitmapViewerExtension.h +++ /dev/null @@ -1,62 +0,0 @@ -/***************************************************************************** - * $CAMITK_LICENCE_BEGIN$ - * - * CamiTK - Computer Assisted Medical Intervention ToolKit - * (c) 2001-2018 Univ. Grenoble Alpes, CNRS, TIMC-IMAG UMR 5525 (GMCAO) - * - * Visit http://camitk.imag.fr for more information - * - * This file is part of CamiTK. - * - * CamiTK is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * CamiTK is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License version 3 for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with CamiTK. If not, see . - * - * $CAMITK_LICENCE_END$ - ****************************************************************************/ - - -#ifndef SHOW_BITMAP_VIEWER_EXTENSION_H -#define SHOW_BITMAP_VIEWER_EXTENSION_H - -#include -#include -#include - -/// shows the bitmap viewer in the central viewer -class ShowBitmapViewerExtension : public camitk::ActionExtension { - Q_OBJECT - Q_INTERFACES(camitk::ActionExtension) - Q_PLUGIN_METADATA(IID "fr.imag.camitk.tutorials.action.showbitmapviewer") - -public: - /// the constructor - ShowBitmapViewerExtension() : ActionExtension() {}; - - /// the destructor - virtual ~ShowBitmapViewerExtension() = default; - - /// initialize all the actions - virtual void init(); - - /// Method that return the action extension name - virtual QString getName() { - return "Show Bitmap Viewer"; - }; - - /// Method that return the action extension descrption - virtual QString getDescription() { - return "This extension contains a simple 2D bitmap viewer and a simple action to show this bitmap viewer in the central viewer."; - }; - -}; - -#endif // SHOW_BITMAP_VIEWER_EXTENSION_H diff --git a/tutorials/actions/showtextviewer/ShowTextViewer.cpp b/tutorials/actions/showtextviewer/ShowTextViewer.cpp deleted file mode 100644 index 31db1b7b..00000000 --- a/tutorials/actions/showtextviewer/ShowTextViewer.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/***************************************************************************** - * $CAMITK_LICENCE_BEGIN$ - * - * CamiTK - Computer Assisted Medical Intervention ToolKit - * (c) 2001-2018 Univ. Grenoble Alpes, CNRS, TIMC-IMAG UMR 5525 (GMCAO) - * - * Visit http://camitk.imag.fr for more information - * - * This file is part of CamiTK. - * - * CamiTK is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * CamiTK is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License version 3 for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with CamiTK. If not, see . - * - * $CAMITK_LICENCE_END$ - ****************************************************************************/ - -#include "ShowTextViewer.h" - -// CamiTK includes -#include -#include -#include - -// from tutorial viewer extensions -#include - -using namespace camitk; - -// --------------- Constructor ------------------- -ShowTextViewer::ShowTextViewer(ActionExtension* extension) : Action(extension) { - // Setting name, description and input component - setName("Show TextViewer"); - setDescription("Set TextViewer (from tutorial) as central viewer of the application's main window."); - setComponent(""); - setEmbedded(false); // not embedded (as getWidget returns nullptr, apply is called as soon as the action is triggered) - - setFamily("Tutorial"); - addTag("Viewer"); - addTag("TextViewer"); - addTag("MainWindow"); -} - -// --------------- getWidget ------------------- -QWidget* ShowTextViewer::getWidget() { - CAMITK_INFO(" !!!") - return nullptr; -} - -// --------------- apply ------------------- -Action::ApplyStatus ShowTextViewer::apply() { - CAMITK_INFO(" TextViewer = " + Application::getViewer("TextViewer")->getName()) - - // just add the TextViewer in the central viewer - Application::getMainWindow()->setCentralViewer(Application::getViewer("TextViewer")); - Application::refresh(); - return SUCCESS; -} - - diff --git a/tutorials/applications/fancy/FancyMainWindow.cpp b/tutorials/applications/fancy/FancyMainWindow.cpp index 029e18fa..d2482703 100644 --- a/tutorials/applications/fancy/FancyMainWindow.cpp +++ b/tutorials/applications/fancy/FancyMainWindow.cpp @@ -31,6 +31,7 @@ #include #include #include +#include // -- Qt stuff #include @@ -39,6 +40,8 @@ #include #include +using namespace camitk; + // ------------- constructor ----------------- FancyMainWindow::FancyMainWindow() : MainWindow("Fancy") { mainWidget = new QWidget; diff --git a/tutorials/applications/menubar/MyAppMainWindow.h b/tutorials/applications/menubar/MyAppMainWindow.h index 313b1ddb..4f5e87ad 100644 --- a/tutorials/applications/menubar/MyAppMainWindow.h +++ b/tutorials/applications/menubar/MyAppMainWindow.h @@ -40,7 +40,7 @@ * The most difficult part is to manage the "Action" menu (as it depends on the * selection). */ -class MyAppMainWindow : public MainWindow { +class MyAppMainWindow : public camitk::MainWindow { Q_OBJECT public: -- GitLab From 2c27db64736a3b4602c3f13c7269eb8a3ad92655 Mon Sep 17 00:00:00 2001 From: Emmanuel Promayon Date: Wed, 5 Feb 2020 16:51:16 +0100 Subject: [PATCH 08/15] FIXED arbitrary viewer in fancy --- .../applications/fancy/FancyMainWindow.cpp | 157 ++++++++++++------ .../applications/fancy/FancyMainWindow.h | 9 +- 2 files changed, 112 insertions(+), 54 deletions(-) diff --git a/tutorials/applications/fancy/FancyMainWindow.cpp b/tutorials/applications/fancy/FancyMainWindow.cpp index d2482703..73711e87 100644 --- a/tutorials/applications/fancy/FancyMainWindow.cpp +++ b/tutorials/applications/fancy/FancyMainWindow.cpp @@ -28,10 +28,10 @@ #include "FancyMainWindow.h" #include -#include +#include #include #include -#include +#include // -- Qt stuff #include @@ -88,15 +88,15 @@ FancyMainWindow::FancyMainWindow() : MainWindow("Fancy") { updateAngleSlider(ui.zAngledial, ui.zAngleValue); showAngleDials(false); - connect(ui.openButton, SIGNAL(clicked()), this, SLOT(fancyFileOpen())); - connect(ui.axial, SIGNAL(clicked()), this, SLOT(layoutChanged())); - connect(ui.coronal, SIGNAL(clicked()), this, SLOT(layoutChanged())); - connect(ui.saggital, SIGNAL(clicked()), this, SLOT(layoutChanged())); - connect(ui.abstract, SIGNAL(clicked()), this, SLOT(layoutChanged())); + connect(ui.openButton, SIGNAL(clicked()), this, SLOT(fancyFileOpen())); + connect(ui.axial, SIGNAL(clicked()), this, SLOT(layoutChanged())); + connect(ui.coronal, SIGNAL(clicked()), this, SLOT(layoutChanged())); + connect(ui.saggital, SIGNAL(clicked()), this, SLOT(layoutChanged())); + connect(ui.abstract, SIGNAL(clicked()), this, SLOT(layoutChanged())); connect(ui.xAngledial, SIGNAL(valueChanged(int)), this, SLOT(xAngleDialValueChanged(int))); connect(ui.yAngledial, SIGNAL(valueChanged(int)), this, SLOT(yAngleDialValueChanged(int))); connect(ui.zAngledial, SIGNAL(valueChanged(int)), this, SLOT(zAngleDialValueChanged(int))); - connect(ui.dial, SIGNAL(valueChanged(int)), this, SLOT(dialValueChanged(int))); + connect(ui.dial, SIGNAL(valueChanged(int)), this, SLOT(dialValueChanged(int))); layoutChanged(); @@ -108,10 +108,24 @@ FancyMainWindow::~FancyMainWindow() { delete mainWidget; } +// ------------- updateComponent ----------------- +void FancyMainWindow::updateComponent() { + // get the current state from the current selected component top level + comp = nullptr; + + if (Application::getTopLevelComponents().size() > 0) { + comp = dynamic_cast(Application::getTopLevelComponents().last()); + } + + viewer3D->resetCamera(); +} + // ------------- fancyFileOpen ----------------- void FancyMainWindow::fancyFileOpen() { Application::getAction("Close All")->trigger(this); Application::getAction("Open")->trigger(this); + + updateComponent(); refresh(); } @@ -125,16 +139,19 @@ void FancyMainWindow::updateAngleSlider(QDial* dial, QLabel* label) { if (label == ui.xAngleValue) { label->setText("X : " + QString("%1").arg(dial->value(), 3) + "" + 0x00B0); } - else + else { if (label == ui.yAngleValue) { label->setText("Y : " + QString("%1").arg(dial->value(), 3) + "" + 0x00B0); } - else + else { if (label == ui.zAngleValue) { label->setText("Z : " + QString("%1").arg(dial->value(), 3) + "" + 0x00B0); } + } + } label->update(); + } // -------------------- updateDialSlider -------------------- @@ -142,32 +159,34 @@ void FancyMainWindow::updateDialSlider() { int currentSliceId, minSliceId, maxSliceId; currentSliceId = minSliceId = maxSliceId = 0; - if (visibility == MedicalImageViewer::VIEWER_ARBITRARY) { - currentSliceId = ui.dial->value(); - minSliceId = 0; - maxSliceId = 360; - } - else { - Component* comp = nullptr; - - if (Application::getTopLevelComponents().size() > 0) { - ImageComponent* comp = dynamic_cast(Application::getTopLevelComponents().last()); - - if (comp) { - if (visibility == MedicalImageViewer::VIEWER_AXIAL) { - currentSliceId = comp->getAxialSlices()->getSlice(); - maxSliceId = comp->getAxialSlices()->getNumberOfSlices(); - } - else - if (visibility == MedicalImageViewer::VIEWER_CORONAL) { - currentSliceId = comp->getCoronalSlices()->getSlice(); - maxSliceId = comp->getCoronalSlices()->getNumberOfSlices(); - } - else { - currentSliceId = comp->getSagittalSlices()->getSlice(); - maxSliceId = comp->getSagittalSlices()->getNumberOfSlices(); - } - } + updateComponent(); + + if (comp != nullptr) { + switch (visibility) { + case MedicalImageViewer::VIEWER_AXIAL: + currentSliceId = comp->getAxialSlices()->getSlice(); + maxSliceId = comp->getAxialSlices()->getNumberOfSlices(); + break; + + case MedicalImageViewer::VIEWER_CORONAL: + currentSliceId = comp->getCoronalSlices()->getSlice(); + maxSliceId = comp->getCoronalSlices()->getNumberOfSlices(); + break; + + case MedicalImageViewer::VIEWER_SAGITTAL: + currentSliceId = comp->getSagittalSlices()->getSlice(); + maxSliceId = comp->getSagittalSlices()->getNumberOfSlices(); + break; + + case MedicalImageViewer::VIEWER_ARBITRARY: + // this is a percentage of translation (50% = half way through the volume) + currentSliceId = comp->getArbitrarySlices()->getTranslationInVolume() * 100.0; + maxSliceId = 100; + break; + + default: + break; + } } @@ -196,17 +215,19 @@ void FancyMainWindow::layoutChanged() { if (ui.axial->isChecked()) { visibility = MedicalImageViewer::VIEWER_AXIAL; } - else + else { if (ui.saggital->isChecked()) { visibility = MedicalImageViewer::VIEWER_SAGITTAL; } - else + else { if (ui.coronal->isChecked()) { visibility = MedicalImageViewer::VIEWER_CORONAL; } else { visibility = MedicalImageViewer::VIEWER_ARBITRARY; } + } + } dynamic_cast(Application::getViewer("MedicalImageViewer"))->setVisibleViewer(visibility); @@ -221,30 +242,62 @@ void FancyMainWindow::layoutChanged() { // -------------------- xAngleDialValueChanged -------------------- void FancyMainWindow::xAngleDialValueChanged(int value) { - dynamic_cast(Application::getViewer("arbitraryViewer"))->xAngleChanged(value); + if (comp != nullptr) { + if (visibility == MedicalImageViewer::VIEWER_ARBITRARY && comp != nullptr && comp->getArbitrarySlices() != nullptr) { + comp->getArbitrarySlices()->setTransformRotation(ui.xAngledial->value(), ui.yAngledial->value(), ui.zAngledial->value()); + } + else { + dynamic_cast(Application::getViewer("arbitraryViewer"))->xAngleChanged(value); + } + } + updateAngleSlider(ui.xAngledial, ui.xAngleValue); refresh(); } // -------------------- yAngleDialValueChanged -------------------- void FancyMainWindow::yAngleDialValueChanged(int value) { - dynamic_cast(Application::getViewer("arbitraryViewer"))->yAngleChanged(value); + if (comp != nullptr) { + if (visibility == MedicalImageViewer::VIEWER_ARBITRARY && comp != nullptr && comp->getArbitrarySlices() != nullptr) { + comp->getArbitrarySlices()->setTransformRotation(ui.xAngledial->value(), ui.yAngledial->value(), ui.zAngledial->value()); + } + else { + dynamic_cast(Application::getViewer("arbitraryViewer"))->yAngleChanged(value); + } + } + updateAngleSlider(ui.yAngledial, ui.yAngleValue); refresh(); } // -------------------- zAngleDialValueChanged -------------------- void FancyMainWindow::zAngleDialValueChanged(int value) { - dynamic_cast(Application::getViewer("arbitraryViewer"))->zAngleChanged(value); + if (comp != nullptr) { + if (visibility == MedicalImageViewer::VIEWER_ARBITRARY && comp != nullptr && comp->getArbitrarySlices() != nullptr) { + comp->getArbitrarySlices()->setTransformRotation(ui.xAngledial->value(), ui.yAngledial->value(), ui.zAngledial->value()); + } + else { + dynamic_cast(Application::getViewer("arbitraryViewer"))->zAngleChanged(value); + } + } + updateAngleSlider(ui.zAngledial, ui.zAngleValue); refresh(); } // -------------------- dialValueChanged -------------------- void FancyMainWindow::dialValueChanged(int value) { - getVisibleViewer()->sliderChanged(value); - updateDialSlider(); - refresh(); + if (comp != nullptr) { + if (visibility == MedicalImageViewer::VIEWER_ARBITRARY && comp->getArbitrarySlices() != nullptr) { + comp->getArbitrarySlices()->setTransformTranslation(0.0, 0.0, ((double) value) / 100.0); + } + else { + getVisibleViewer()->sliderChanged(value); + } + + updateDialSlider(); + refresh(); + } } // -------------------- refreshView -------------------- @@ -252,24 +305,22 @@ void FancyMainWindow::refresh() { getVisibleViewer()->refresh(); // force visualization of arbitrary slice in 3D - // We need to set the visibility of this viewer to true during as by default + // We need to set the visibility of our viewer3D to true during as by default // the component does not know about it and the visibility in viewer3D is false - if (Application::getTopLevelComponents().size() > 0) { - ImageComponent* comp = dynamic_cast(Application::getTopLevelComponents().last()); - - if (comp != nullptr && comp->getAxialSlices() != nullptr) { + if (comp != nullptr) { + if (comp->getAxialSlices() != nullptr) { comp->getAxialSlices()->setVisibility(viewer3D, true); } - if (comp != nullptr && comp->getSagittalSlices() != nullptr) { + if (comp->getSagittalSlices() != nullptr) { comp->getSagittalSlices()->setVisibility(viewer3D, true); } - if (comp != nullptr && comp->getCoronalSlices() != nullptr) { + if (comp->getCoronalSlices() != nullptr) { comp->getCoronalSlices()->setVisibility(viewer3D, true); } - if (comp != nullptr && comp->getArbitrarySlices() != nullptr) { + if (comp->getArbitrarySlices() != nullptr) { comp->getArbitrarySlices()->setVisibility(viewer3D, true); } } @@ -280,7 +331,7 @@ void FancyMainWindow::refresh() { // -------------------- getVisibleViewer -------------------- InteractiveSliceViewer* FancyMainWindow::getVisibleViewer() { - InteractiveSliceViewer* visibleViewer = NULL; + InteractiveSliceViewer* visibleViewer = nullptr; switch (visibility) { case MedicalImageViewer::VIEWER_AXIAL: diff --git a/tutorials/applications/fancy/FancyMainWindow.h b/tutorials/applications/fancy/FancyMainWindow.h index c4e32a10..875b667b 100644 --- a/tutorials/applications/fancy/FancyMainWindow.h +++ b/tutorials/applications/fancy/FancyMainWindow.h @@ -34,6 +34,7 @@ #include #include #include +#include /** * This Class describes the fancy bare application. It sets up the main @@ -51,7 +52,7 @@ public: /// destructor ~FancyMainWindow(); - + public slots: /// inherited from QWidget, just to refresh all viewers @@ -92,8 +93,14 @@ private: /// get the currently visible viewer (axial, sagittal, coronal or arbitrary) InteractiveSliceViewer* getVisibleViewer(); + /// update the comp + void updateComponent(); + /// specific 3D viewer for fancy InteractiveGeometryViewer* viewer3D; + + /// current visible component + camitk::ImageComponent* comp; }; #endif // FANCYAPP_H -- GitLab From 34f6ef31f89100ff5d1e22a95b9b3a71b85d7423 Mon Sep 17 00:00:00 2001 From: Emmanuel Promayon Date: Wed, 5 Feb 2020 22:20:25 +0100 Subject: [PATCH 09/15] FIXED bug: do not record null viewer is the component viewer's list When testcomponents is ran, no viewer extensions are loaded. Application::getViewer(..) returns nullptr. As MeshComponent set its visibility in the 3DViewer, and there is no 3DViewer, nullptr was registered in the list. This caused a crash later on, when refresh() was called. --- .../image/reorientimage/ReorientImage.cpp | 2 +- .../vrml/VRMLComponentExtension.cpp | 2 +- sdk/libraries/core/component/Component.cpp | 17 ++++++---- sdk/libraries/core/utils/Log.h | 5 ++- sdk/viewers/explorer/ExplorerExtension.cpp | 2 +- .../frameexplorer/FrameExplorerExtension.h | 34 +++++++++---------- .../InteractiveSliceViewerExtension.cpp | 8 ++--- .../medicalimageviewer/MedicalImageViewer.cpp | 2 +- .../PropertyExplorerExtension.h | 34 +++++++++---------- .../textviewer/TextViewerExtension.cpp | 2 +- 10 files changed, 57 insertions(+), 51 deletions(-) diff --git a/sdk/actions/image/reorientimage/ReorientImage.cpp b/sdk/actions/image/reorientimage/ReorientImage.cpp index a2fb0b30..08804a51 100644 --- a/sdk/actions/image/reorientimage/ReorientImage.cpp +++ b/sdk/actions/image/reorientimage/ReorientImage.cpp @@ -190,7 +190,7 @@ void ReorientImage::initInternalViewer() { buildGeometries(); // Set up the 3D viewer to visualize actual origin/orientation locations - internalViewer = dynamic_cast(Application::getNewViewer("Image Orientation Viewer", "InteractiveGeometryViewer")); + internalViewer = dynamic_cast(Application::getNewViewer("Image Orientation Viewer", "InteractiveGeometryViewer")); internalViewer->setLayout(Viewer::EMBEDDED); internalViewer->setHighlightMode(InteractiveViewer::OFF); internalViewer->toggleCopyright(false); diff --git a/sdk/components/vrml/VRMLComponentExtension.cpp b/sdk/components/vrml/VRMLComponentExtension.cpp index 2115e1cf..76dba43c 100644 --- a/sdk/components/vrml/VRMLComponentExtension.cpp +++ b/sdk/components/vrml/VRMLComponentExtension.cpp @@ -43,7 +43,7 @@ QString VRMLComponentExtension::getName() const { // --------------- getDescription ------------------- QString VRMLComponentExtension::getDescription() const { - return tr("Manage VRML 2 .wrl .vrml files in CamiTK.(very few support!)"); + return tr("Basic support for VRML 2 .wrl and .vrml documents"); } // --------------- getFileExtensions ------------------- diff --git a/sdk/libraries/core/component/Component.cpp b/sdk/libraries/core/component/Component.cpp index 87d4b25f..c66bf607 100644 --- a/sdk/libraries/core/component/Component.cpp +++ b/sdk/libraries/core/component/Component.cpp @@ -259,14 +259,17 @@ Component* Component::getTopLevelComponent() { // -------------------- setVisibility -------------------- void Component::setVisibility(Viewer* v, bool b) { - QMap::iterator it = myViewers.find(v); + // only insert real non-null viewers + if (v != nullptr) { + QMap::iterator it = myViewers.find(v); - if (it == myViewers.end()) { - // insert the new viewer with the corresponding boolean - myViewers.insert(v, b); - } - else { - it.value() = b; + if (it == myViewers.end()) { + // insert the new viewer with the corresponding boolean + myViewers.insert(v, b); + } + else { + it.value() = b; + } } } diff --git a/sdk/libraries/core/utils/Log.h b/sdk/libraries/core/utils/Log.h index 3d916078..4e4a1920 100644 --- a/sdk/libraries/core/utils/Log.h +++ b/sdk/libraries/core/utils/Log.h @@ -216,7 +216,10 @@ private: static InterfaceLogger* applicationLogger; }; -// Generic log macro (it is NOT recommended to use it directly...) +/// Helper macro that produce a QString reprensenting a pointer +#define CAMITK_PRINT_POINTER(PTR) (QString(#PTR) + QString("=0x%1").arg((quintptr)PTR, QT_POINTER_SIZE * 2, 16, QChar('0'))) + +/// Generic log macro (it is NOT recommended to use it directly...) #if !defined(CAMITK_DISABLE_LOG) #define CAMITK_LOG(LEVEL,MSG,SENDER) camitk::Log::getLogger()->log(MSG, LEVEL, __FILE__, Q_FUNC_INFO, __LINE__, SENDER); #define CAMITK_LOG_ALT(LEVEL,MSG) camitk::Log::getLogger()->log(MSG, LEVEL, __FILE__, __func__, __LINE__); diff --git a/sdk/viewers/explorer/ExplorerExtension.cpp b/sdk/viewers/explorer/ExplorerExtension.cpp index ad55d2ab..53d81058 100644 --- a/sdk/viewers/explorer/ExplorerExtension.cpp +++ b/sdk/viewers/explorer/ExplorerExtension.cpp @@ -37,6 +37,6 @@ ExplorerExtension::ExplorerExtension() : ViewerExtension() { // --------------- getViewers ------------------- void ExplorerExtension::init() { - registerDefaultViewer(Explorer); + registerDefaultViewer(Explorer); } diff --git a/sdk/viewers/frameexplorer/FrameExplorerExtension.h b/sdk/viewers/frameexplorer/FrameExplorerExtension.h index 2462ced5..b66ea917 100644 --- a/sdk/viewers/frameexplorer/FrameExplorerExtension.h +++ b/sdk/viewers/frameexplorer/FrameExplorerExtension.h @@ -33,29 +33,29 @@ #include class FRAMEEXPLORER_API FrameExplorerExtension : public camitk::ViewerExtension { - Q_OBJECT - Q_INTERFACES(camitk::ViewerExtension); - Q_PLUGIN_METADATA(IID "fr.imag.camitk.frameexplorerextension.viewer.frameexplorerextension") + Q_OBJECT + Q_INTERFACES(camitk::ViewerExtension); + Q_PLUGIN_METADATA(IID "fr.imag.camitk.frameexplorerextension.viewer.frameexplorerextension") public: - /// Constructor - FrameExplorerExtension() : ViewerExtension() {}; + /// Constructor + FrameExplorerExtension() : ViewerExtension() {}; - /// Destructor - virtual ~FrameExplorerExtension() = default; + /// Destructor + virtual ~FrameExplorerExtension() = default; - /// Method returning the action extension name - virtual QString getName() { - return "Frame Explorer Extension"; - }; + /// Method returning the action extension name + virtual QString getName() { + return "Frame Explorer Extension"; + }; - /// Method returning the action extension descrption - virtual QString getDescription() { - return "An extension for the frame explorer"; - }; + /// Method returning the action extension descrption + virtual QString getDescription() { + return "An extension for the frame explorer"; + }; - /// initialize all the actions - virtual void init(); + /// initialize all the actions + virtual void init(); }; diff --git a/sdk/viewers/interactivesliceviewer/InteractiveSliceViewerExtension.cpp b/sdk/viewers/interactivesliceviewer/InteractiveSliceViewerExtension.cpp index d09f8da7..a750eb01 100644 --- a/sdk/viewers/interactivesliceviewer/InteractiveSliceViewerExtension.cpp +++ b/sdk/viewers/interactivesliceviewer/InteractiveSliceViewerExtension.cpp @@ -31,9 +31,9 @@ // --------------- getViewers ------------------- void InteractiveSliceViewerExtension::init() { - registerNewViewer(InteractiveSliceViewer, "axialViewer"); - registerNewViewer(InteractiveSliceViewer, "coronalViewer"); - registerNewViewer(InteractiveSliceViewer, "sagittalViewer"); - registerNewViewer(InteractiveSliceViewer, "arbitraryViewer"); + registerNewViewer(InteractiveSliceViewer, "axialViewer"); + registerNewViewer(InteractiveSliceViewer, "coronalViewer"); + registerNewViewer(InteractiveSliceViewer, "sagittalViewer"); + registerNewViewer(InteractiveSliceViewer, "arbitraryViewer"); } diff --git a/sdk/viewers/medicalimageviewer/MedicalImageViewer.cpp b/sdk/viewers/medicalimageviewer/MedicalImageViewer.cpp index 4602f614..92d082fc 100644 --- a/sdk/viewers/medicalimageviewer/MedicalImageViewer.cpp +++ b/sdk/viewers/medicalimageviewer/MedicalImageViewer.cpp @@ -140,7 +140,7 @@ QWidget* MedicalImageViewer::getWidget() { Application::getViewer("sagittalViewer")->embedIn(innerLayout); innerLayout = new QVBoxLayout(); frameLayout->addLayout(innerLayout, 0, 1); // north-east - + Application::getViewer("3DViewer")->embedIn(innerLayout); Application::getViewer("arbitraryViewer")->embedIn(innerLayout); diff --git a/sdk/viewers/propertyexplorer/PropertyExplorerExtension.h b/sdk/viewers/propertyexplorer/PropertyExplorerExtension.h index d69aa3bd..8cead860 100644 --- a/sdk/viewers/propertyexplorer/PropertyExplorerExtension.h +++ b/sdk/viewers/propertyexplorer/PropertyExplorerExtension.h @@ -33,29 +33,29 @@ #include class PROPERTYEXPLORER_API PropertyExplorerExtension : public camitk::ViewerExtension { - Q_OBJECT - Q_INTERFACES(camitk::ViewerExtension); - Q_PLUGIN_METADATA(IID "fr.imag.camitk.propertyexplorerextension.viewer.propertyexplorerextension") + Q_OBJECT + Q_INTERFACES(camitk::ViewerExtension); + Q_PLUGIN_METADATA(IID "fr.imag.camitk.propertyexplorerextension.viewer.propertyexplorerextension") public: - /// Constructor - PropertyExplorerExtension() : ViewerExtension() {}; + /// Constructor + PropertyExplorerExtension() : ViewerExtension() {}; - /// Destructor - virtual ~PropertyExplorerExtension() = default; + /// Destructor + virtual ~PropertyExplorerExtension() = default; - /// Method returning the action extension name - virtual QString getName() { - return "Property Explorer Extension"; - }; + /// Method returning the action extension name + virtual QString getName() { + return "Property Explorer Extension"; + }; - /// Method returning the action extension descrption - virtual QString getDescription() { - return "An extension for the property explorer"; - }; + /// Method returning the action extension descrption + virtual QString getDescription() { + return "An extension for the property explorer"; + }; - /// initialize all the actions - virtual void init(); + /// initialize all the actions + virtual void init(); }; diff --git a/tutorials/viewers/textviewer/TextViewerExtension.cpp b/tutorials/viewers/textviewer/TextViewerExtension.cpp index 7572ce49..52d8dd52 100644 --- a/tutorials/viewers/textviewer/TextViewerExtension.cpp +++ b/tutorials/viewers/textviewer/TextViewerExtension.cpp @@ -31,6 +31,6 @@ // --------------- getActions ------------------- void TextViewerExtension::init() { - registerDefaultViewer(TextViewer); + registerDefaultViewer(TextViewer); } -- GitLab From 0418bf236e0b2c1d466cd617eabae431e58e35c3 Mon Sep 17 00:00:00 2001 From: Emmanuel Promayon Date: Wed, 5 Feb 2020 22:48:49 +0100 Subject: [PATCH 10/15] FIXED broken tests Note that the sleepingwhileworking automatic test are now disabled until it is possible to specify a dependency of the action with one ore more viewer extensions --- .../config/testing/config-test.sh | 24 ++++++++++++------- .../sleepingwhileworking/CMakeLists.txt | 10 +++++--- .../testlogger/log-default-linux.log | 2 +- .../testlogger/log-default-win.log | 2 +- 4 files changed, 24 insertions(+), 14 deletions(-) diff --git a/sdk/applications/config/testing/config-test.sh b/sdk/applications/config/testing/config-test.sh index e8de3869..8228274c 100644 --- a/sdk/applications/config/testing/config-test.sh +++ b/sdk/applications/config/testing/config-test.sh @@ -22,11 +22,12 @@ set -e # values to check initTestData() { # fill test data - extensionCount=( [4.2]=44 [4.1]=41 [4.0]=31 ) - componentExtensionCount=( [4.2]=14 [4.1]=14 [4.0]=14 ) - actionExtensionCount=( [4.2]=30 [4.1]=27 [4.0]=27 ) - fileExtensionCount=( [4.2]=37 [4.1]=37 [4.0]=37 ) - actionCount=( [4.2]=109 [4.1]=105 [4.0]=105 ) + extensionCount=( [4.2]=53 [4.1]=41 [4.0]=31 ) + componentExtensionCount=( [4.2]=14 [4.1]=14 [4.0]=14 ) + actionExtensionCount=( [4.2]=30 [4.1]=27 [4.0]=27 ) + viewerExtensionCount=( [4.2]=9 ) + fileExtensionCount=( [4.2]=37 [4.1]=37 [4.0]=37 ) + actionCount=( [4.2]=109 [4.1]=105 [4.0]=105 ) # fill release date releaseDate=( [4.2]="not yet released, current development version" \ @@ -48,6 +49,7 @@ declareTestData() { declare -Ag extensionCount declare -Ag componentExtensionCount declare -Ag actionExtensionCount + declare -Ag viewerExtensionCount declare -Ag fileExtensionCount declare -Ag actionCount declare -Ag releaseDate @@ -171,16 +173,19 @@ getExpectedValue() { ;; "Number of Component Extensions") echo ${componentExtensionCount[$shortVersion]} - ;; + ;; "Number of Action Extensions") echo ${actionExtensionCount[$shortVersion]} - ;; + ;; + "Number of Viewer Extensions") + echo ${viewerExtensionCount[$shortVersion]} + ;; "Number of File Extensions Supported") echo ${fileExtensionCount[$shortVersion]} - ;; + ;; "Number of Actions") echo ${actionCount[$shortVersion]} - ;; + ;; esac } @@ -284,6 +289,7 @@ else fi checkValue "Number of Component Extensions" checkValue "Number of Action Extensions" +checkValue "Number of Viewer Extensions" checkValue "Number of File Extensions Supported" checkValue "Number of Actions" diff --git a/tutorials/actions/sleepingwhileworking/CMakeLists.txt b/tutorials/actions/sleepingwhileworking/CMakeLists.txt index e306a7a9..d2b142d4 100644 --- a/tutorials/actions/sleepingwhileworking/CMakeLists.txt +++ b/tutorials/actions/sleepingwhileworking/CMakeLists.txt @@ -1,6 +1,10 @@ # Call CamiTK CMake Macro to define the action 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 - NEEDS_VIEWER_EXTENSION medicalimageviewer + NEEDS_VIEWER_EXTENSION medicalimageviewer +# Automatic test are disable for this extension because these actions directly manipulates the camera of the 3D +# viewer. During automatic test no viewers are loaded, therefore resulting in a crash. +# TODO Create a specific "TEST_REQUIRES_VIEWER_EXTENSIONS viewer1 viewer2..." option +# that will instructs camitk-testaction to load the specified viewer extensions before applying the actions +# 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 ) diff --git a/tutorials/applications/testlogger/log-default-linux.log b/tutorials/applications/testlogger/log-default-linux.log index 4d609493..84324672 100644 --- a/tutorials/applications/testlogger/log-default-linux.log +++ b/tutorials/applications/testlogger/log-default-linux.log @@ -139,7 +139,7 @@ Log level "INFO": end test. Log level "TRACE": begin test... [TRACE ] Log level changed to: TRACE With debug information: -[TRACE ] [virtual void camitk::CamiTKLogger::setDebugInformation(bool)@CamiTKLogger.cpp:223] Logging debug information: true +[TRACE ] [virtual void camitk::CamiTKLogger::setDebugInformation(bool)@CamiTKLogger.cpp:224] Logging debug information: true TRACE message: [TRACE ] [printLog@main.cpp:43] Test Log: TRACE TRACE_IF(true) message: diff --git a/tutorials/applications/testlogger/log-default-win.log b/tutorials/applications/testlogger/log-default-win.log index 8b584140..350215d4 100644 --- a/tutorials/applications/testlogger/log-default-win.log +++ b/tutorials/applications/testlogger/log-default-win.log @@ -139,7 +139,7 @@ Log level "INFO": end test. Log level "TRACE": begin test... [TRACE ] Log level changed to: TRACE With debug information: -[TRACE ] [void __cdecl camitk::CamiTKLogger::setDebugInformation(bool)@CamiTKLogger.cpp:223] Logging debug information: true +[TRACE ] [void __cdecl camitk::CamiTKLogger::setDebugInformation(bool)@CamiTKLogger.cpp:224] Logging debug information: true TRACE message: [TRACE ] [printLog@main.cpp:43] Test Log: TRACE TRACE_IF(true) message: -- GitLab From 8d1a98c86998a34ac4452bcb2d18f0aa0f6b1ff5 Mon Sep 17 00:00:00 2001 From: Emmanuel Promayon Date: Thu, 6 Feb 2020 07:07:49 +0100 Subject: [PATCH 11/15] FIXED add viwer count test + fix numbers of actions and extensions --- sdk/applications/config/testing/config-test.sh | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/sdk/applications/config/testing/config-test.sh b/sdk/applications/config/testing/config-test.sh index 8228274c..02a1f9a4 100644 --- a/sdk/applications/config/testing/config-test.sh +++ b/sdk/applications/config/testing/config-test.sh @@ -22,12 +22,13 @@ set -e # values to check initTestData() { # fill test data - extensionCount=( [4.2]=53 [4.1]=41 [4.0]=31 ) + extensionCount=( [4.2]=52 [4.1]=41 [4.0]=31 ) componentExtensionCount=( [4.2]=14 [4.1]=14 [4.0]=14 ) - actionExtensionCount=( [4.2]=30 [4.1]=27 [4.0]=27 ) + actionExtensionCount=( [4.2]=29 [4.1]=27 [4.0]=27 ) viewerExtensionCount=( [4.2]=9 ) fileExtensionCount=( [4.2]=37 [4.1]=37 [4.0]=37 ) - actionCount=( [4.2]=109 [4.1]=105 [4.0]=105 ) + actionCount=( [4.2]=108 [4.1]=105 [4.0]=105 ) + viewerCount=( [4.2]=12 ) # fill release date releaseDate=( [4.2]="not yet released, current development version" \ @@ -52,6 +53,7 @@ declareTestData() { declare -Ag viewerExtensionCount declare -Ag fileExtensionCount declare -Ag actionCount + declare -Ag viewerCount declare -Ag releaseDate } @@ -186,6 +188,9 @@ getExpectedValue() { "Number of Actions") echo ${actionCount[$shortVersion]} ;; + "Number of Viewers") + echo ${viewerCount[$shortVersion]} + ;; esac } @@ -292,5 +297,6 @@ checkValue "Number of Action Extensions" checkValue "Number of Viewer Extensions" checkValue "Number of File Extensions Supported" checkValue "Number of Actions" +checkValue "Number of Viewers" exit $exitStatus -- GitLab From a26da3c6ddbbcf08cbfb848143053e75595510c0 Mon Sep 17 00:00:00 2001 From: Emmanuel Promayon Date: Thu, 6 Feb 2020 10:29:38 +0100 Subject: [PATCH 12/15] NEW Visibility menu to set the visibility of a component in a viewer + FIXED BitmapViewer and InteractiveSliceViewer can only see SingleImageComponent + FIXED image component management of visibility in 3D viewer and some override warnings Thanks to Maxime that prepared most of then visibility menu code --- sdk/libraries/core/component/Component.cpp | 34 ++++++ sdk/libraries/core/component/Component.h | 105 ++++++++++-------- sdk/libraries/core/component/Geometry.h | 18 +-- .../core/component/SimplisticComponent.h | 2 +- .../core/component/image/ImageComponent.cpp | 49 +++++--- .../core/component/image/ImageComponent.h | 7 +- sdk/libraries/core/viewer/ViewerExtension.cpp | 30 ----- sdk/viewers/bitmap/BitmapViewer.cpp | 6 +- .../InteractiveGeometryViewer.cpp | 8 +- .../InteractiveSliceViewer.cpp | 5 +- .../medicalimageviewer/MedicalImageViewer.cpp | 3 - 11 files changed, 151 insertions(+), 116 deletions(-) diff --git a/sdk/libraries/core/component/Component.cpp b/sdk/libraries/core/component/Component.cpp index c66bf607..4cb36636 100644 --- a/sdk/libraries/core/component/Component.cpp +++ b/sdk/libraries/core/component/Component.cpp @@ -109,6 +109,12 @@ Component::~Component() { propertyMap.clear(); + if (actionsMenu != nullptr) { + actionsMenu->clear(); + delete actionsMenu; + actionsMenu = nullptr; + } + CAMITK_TRACE(tr("Deleted")) } @@ -125,6 +131,7 @@ void Component::init() { mySlice = nullptr; myFrame = nullptr; actionsMenu = nullptr; + visibilityMenu = nullptr; // create the Frame (does not depend on any representation, should be created for any Component) myFrame = new Frame(); @@ -397,6 +404,9 @@ QMenu* Component::getActionMenu() { } } + //-- create the visibility menu when first call + visibilityMenu = actionsMenu->addMenu("Visibility"); + // no menu if no action if (actionsMenu->actions().size() == 0) { delete actionsMenu; @@ -404,6 +414,30 @@ QMenu* Component::getActionMenu() { } } + //-- update viewer visibility + visibilityMenu->clear(); + ViewerList allViewers = Application::getViewers(this); + + for (Viewer* viewer : allViewers) { + // show only embedded or stacked viewers + if (viewer->getLayout() != Viewer::DOCKED) { + // viewerAction is own by visibilityMenu, visibilityMenu.clear() will delete it + QAction* visibilityAction = visibilityMenu->addAction(viewer->getName()); + visibilityAction->setCheckable(true); + visibilityAction->setChecked(getVisibility(viewer)); + visibilityAction->setIcon(viewer->getIcon()); + QString tipString = "Set the visibility of this component in the \"" + viewer->getName() + "\" viewer\n(note that it might not have effect depending on the viewer)"; + visibilityAction->setStatusTip(tr(tipString.toStdString().c_str())); + visibilityAction->setWhatsThis(tr(tipString.toStdString().c_str())); + // add the toggle action slot using C++11 lambda so that everything is contained inside viewMenu + connect(visibilityAction, &QAction::toggled, [ = ](bool visible) { + setVisibility(viewer, visible); + Application::refresh(); + }); + } + } + + return actionsMenu; } diff --git a/sdk/libraries/core/component/Component.h b/sdk/libraries/core/component/Component.h index 3f00bb84..f8fc9b45 100644 --- a/sdk/libraries/core/component/Component.h +++ b/sdk/libraries/core/component/Component.h @@ -148,27 +148,27 @@ foreach (Component *child, childrenComponent) { \ * is always checked before actually calling METHOD. */ #define delegate0(HANDLER,METHOD) \ -virtual void METHOD() { \ +virtual void METHOD() override { \ invoke0(HANDLER,METHOD) \ } #define delegate1(HANDLER,METHOD,PARAM_TYPE) \ -virtual void METHOD(PARAM_TYPE param) { \ +virtual void METHOD(PARAM_TYPE param) override { \ invoke1(HANDLER,METHOD,param) \ } #define delegate2(HANDLER,METHOD,PARAM_TYPE1,PARAM_TYPE2) \ -virtual void METHOD(PARAM_TYPE1 param1, PARAM_TYPE2 param2) { \ +virtual void METHOD(PARAM_TYPE1 param1, PARAM_TYPE2 param2) override { \ invoke2(HANDLER,METHOD,param1,param2) \ } #define delegate3(HANDLER,METHOD,PARAM_TYPE1,PARAM_TYPE2,PARAM_TYPE3) \ -virtual void METHOD(PARAM_TYPE1 param1, PARAM_TYPE2 param2, PARAM_TYPE3 param3) { \ +virtual void METHOD(PARAM_TYPE1 param1, PARAM_TYPE2 param2, PARAM_TYPE3 param3) override { \ invoke3(HANDLER,METHOD,param1,param2,param3) \ } #define delegate4(HANDLER,METHOD,PARAM_TYPE1,PARAM_TYPE2,PARAM_TYPE3, PARAM_TYPE4) \ -virtual void METHOD(PARAM_TYPE1 param1, PARAM_TYPE2 param2, PARAM_TYPE3 param3, PARAM_TYPE4 param4) { \ +virtual void METHOD(PARAM_TYPE1 param1, PARAM_TYPE2 param2, PARAM_TYPE3 param3, PARAM_TYPE4 param4) override { \ invoke4(HANDLER,METHOD,param1,param2,param3,param4) \ } @@ -179,21 +179,21 @@ virtual void METHOD(PARAM_TYPE1 param1, PARAM_TYPE2 param2, PARAM_TYPE3 param3, * (which should automatically be converted to false for bool, NULL for pointers...) */ #define delegateGet0(HANDLER,METHOD,TYPE) \ -virtual TYPE METHOD() { \ +virtual TYPE METHOD() override { \ invokeGet0(HANDLER,METHOD) \ else \ return 0; \ } #define delegateGet1(HANDLER,METHOD,TYPE,PARAM_TYPE) \ -virtual TYPE METHOD(PARAM_TYPE param) { \ +virtual TYPE METHOD(PARAM_TYPE param) override { \ invokeGet1(HANDLER,METHOD,param) \ else \ return 0; \ } #define delegateGet2(HANDLER,METHOD,TYPE,PARAM1_TYPE,PARAM2_TYPE) \ -virtual TYPE METHOD(PARAM1_TYPE param1, PARAM2_TYPE param2) { \ +virtual TYPE METHOD(PARAM1_TYPE param1, PARAM2_TYPE param2) override { \ invokeGet2(HANDLER,METHOD,param1,param2) \ else \ return 0; \ @@ -202,14 +202,14 @@ virtual TYPE METHOD(PARAM1_TYPE param1, PARAM2_TYPE param2) { \ * Same as delegateGet but for const METHOD */ #define delegateConstGet0(HANDLER,METHOD,TYPE) \ -virtual TYPE METHOD() const { \ +virtual TYPE METHOD() const override { \ invokeGet0(HANDLER,METHOD) \ else \ return 0; \ } #define delegateConstGet1(HANDLER,METHOD,TYPE,PARAM_TYPE) \ -virtual TYPE METHOD(PARAM_TYPE param) const { \ +virtual TYPE METHOD(PARAM_TYPE param) const override { \ invokeGet1(HANDLER,METHOD,param) \ else \ return 0; \ @@ -220,31 +220,31 @@ virtual TYPE METHOD(PARAM_TYPE param) const { \ * First uses the corresponding invoke macro, then the corresponding invokeChildren macro. */ #define delegateAndInvokeChildren1(HANDLER,METHOD,PARAM_TYPE) \ -virtual void METHOD(PARAM_TYPE param) { \ +virtual void METHOD(PARAM_TYPE param) override { \ invoke1(HANDLER,METHOD,param) \ invokeChildren1(METHOD,param) \ } #define delegateAndInvokeChildren2(HANDLER,METHOD,PARAM_TYPE1,PARAM_TYPE2) \ -virtual void METHOD(PARAM_TYPE1 param1, PARAM_TYPE2 param2) { \ +virtual void METHOD(PARAM_TYPE1 param1, PARAM_TYPE2 param2) override { \ invoke2(HANDLER,METHOD,param1,param2) \ invokeChildren2(METHOD,param1,param2) \ } #define delegateAndInvokeChildren1Array(HANDLER,METHOD,PARAM_TYPE1,PARAM_TYPE2,DIM) \ -virtual void METHOD(PARAM_TYPE1 param1, PARAM_TYPE2 param2[DIM]) { \ +virtual void METHOD(PARAM_TYPE1 param1, PARAM_TYPE2 param2[DIM]) override { \ invoke2(HANDLER,METHOD,param1,param2) \ invokeChildren2(METHOD,param1,param2) \ } #define delegateAndInvokeChildren3(HANDLER,METHOD,PARAM_TYPE1,PARAM_TYPE2,PARAM_TYPE3) \ -virtual void METHOD(PARAM_TYPE1 param1, PARAM_TYPE2 param2, PARAM_TYPE3 param3) { \ +virtual void METHOD(PARAM_TYPE1 param1, PARAM_TYPE2 param2, PARAM_TYPE3 param3) override { \ invoke3(HANDLER,METHOD,param1,param2,param3) \ invokeChildren3(METHOD,param1,param2,param3) \ } #define delegateAndInvokeChildren4(HANDLER,METHOD,PARAM_TYPE1,PARAM_TYPE2,PARAM_TYPE3,PARAM_TYPE4) \ -virtual void METHOD(PARAM_TYPE1 param1, PARAM_TYPE2 param2, PARAM_TYPE3 param3,PARAM_TYPE4 param4) { \ +virtual void METHOD(PARAM_TYPE1 param1, PARAM_TYPE2 param2, PARAM_TYPE3 param3,PARAM_TYPE4 param4) override { \ invoke4(HANDLER,METHOD,param1,param2,param3,param4) \ invokeChildren4(METHOD,param1,param2,param3,param4) \ } @@ -420,7 +420,7 @@ public: * get the number of alternative property widgets * @see PropertyExplorer */ - unsigned int getNumberOfPropertyWidget() { + unsigned int getNumberOfPropertyWidget() override { return 0; } @@ -428,7 +428,7 @@ public: * Get the ith alternative property widget * @see PropertyExplorer */ - QWidget* getPropertyWidgetAt(unsigned int i) { + QWidget* getPropertyWidgetAt(unsigned int) override { return nullptr; } @@ -440,7 +440,7 @@ public: * @see PropertyExplorer * @see ObjectController */ - QObject* getPropertyObject() { + QObject* getPropertyObject() override { return this; } @@ -459,7 +459,7 @@ public: * @param index the index to select in the tab of the ProperlyExplorer. * @see PropertyExplorer **/ - inline void setIndexOfPropertyExplorerTab(unsigned int index) { + inline void setIndexOfPropertyExplorerTab(unsigned int index) override { this->indexOfPropertyExplorerTab = index; } @@ -470,7 +470,7 @@ public: * @return the index to select in the tab of the ProperlyExplorer. * @see PropertyExplorer **/ - inline unsigned int getIndexOfPropertyExplorerTab() { + inline unsigned int getIndexOfPropertyExplorerTab() override { return this->indexOfPropertyExplorerTab; } @@ -524,7 +524,7 @@ public: bool inItalic() const override; /// get the popup menu to display (always return NULL, overwrite this method if you want to give here you own popup) - QMenu* getPopupMenu(QWidget* parent = nullptr) { + QMenu* getPopupMenu(QWidget* parent = nullptr) override { return nullptr; } /// @} @@ -554,54 +554,64 @@ public: // TODO : uses an object myRepresentation (which is a Geometry or a Slice) // to use a single delegate macro - vtkSmartPointer getProp(const QString& param) { + vtkSmartPointer getProp(const QString& param) override { if (myGeometry) { return myGeometry->getProp(param); } - else if (mySlice) { - return mySlice->getProp(param); - } + else + if (mySlice) { + return mySlice->getProp(param); + } + return nullptr; } - unsigned int getNumberOfProp() const { + unsigned int getNumberOfProp() const override { if (myGeometry) { return myGeometry->getNumberOfProp(); } - else if (mySlice) { - return mySlice->getNumberOfProp(); - } + else + if (mySlice) { + return mySlice->getNumberOfProp(); + } + return 0; } - vtkSmartPointer getProp(unsigned int index) { + vtkSmartPointer getProp(unsigned int index) override { if (myGeometry) { return myGeometry->getProp(index); } - else if (mySlice) { - return mySlice->getProp(index); - } + else + if (mySlice) { + return mySlice->getProp(index); + } + return nullptr; } - bool addProp(const QString& name, vtkSmartPointer prop) { + bool addProp(const QString& name, vtkSmartPointer prop) override { if (myGeometry) { return myGeometry->addProp(name, prop); } - else if (mySlice) { - return mySlice->addProp(name, prop); - } + else + if (mySlice) { + return mySlice->addProp(name, prop); + } + return false; } - bool removeProp(const QString& name) { + bool removeProp(const QString& name) override { if (myGeometry) { return myGeometry->removeProp(name); } - else if (mySlice) { - return mySlice->removeProp(name); - } + else + if (mySlice) { + return mySlice->removeProp(name); + } + return false; } // END TODO @@ -610,12 +620,12 @@ public: /** an inherited class can redefine this method something specific. * Default behaviour: do nothing. */ - void pointPicked(vtkIdType, bool) {} + void pointPicked(vtkIdType, bool) override {} /** an inherited class can redefine this method something specific. * Default behaviour: do nothing. */ - void cellPicked(vtkIdType, bool) {} + void cellPicked(vtkIdType, bool) override {} // -- @@ -684,8 +694,6 @@ public: delegateGet0(mySlice, getPixelActor, vtkSmartPointer) -// delegateGet0(mySlice, get2DAxesActor, vtkSmartPointer) - delegate3(mySlice, pixelPicked, double, double, double) delegate0(mySlice, updatePickPlane) @@ -700,8 +708,7 @@ public: delegate1(mySlice, setImageWorldTransform, vtkSmartPointer) - delegate1(mySlice, setArbitraryTransform, vtkSmartPointer) - + delegate1(mySlice, setArbitraryTransform, vtkSmartPointer) /// see Component.cpp int getNumberOfSlices() const override; @@ -817,6 +824,9 @@ private: /// the action menu for this component QMenu* actionsMenu; + /// the sub menu that shows the visibility of this component in the viewers + QMenu* visibilityMenu; + /// list of CamiTK property decorating the dynamic properties QMap propertyMap; ///@} @@ -876,6 +886,7 @@ inline bool Component::inItalic() const { // -------------------- setName -------------------- inline void Component::setName(const QString& n) { myName = n; + if (myGeometry) { myGeometry->setLabel(n); } diff --git a/sdk/libraries/core/component/Geometry.h b/sdk/libraries/core/component/Geometry.h index 5b837173..ef9c8a12 100644 --- a/sdk/libraries/core/component/Geometry.h +++ b/sdk/libraries/core/component/Geometry.h @@ -143,12 +143,12 @@ public: ~Geometry() override; /// get the label of this Geometry instance - const QString getLabel() const { + const QString getLabel() const override { return label; } /// set the label of this Geometry instance - void setLabel(QString newName) { + void setLabel(QString newName) override { label = newName; updateLabel(); } @@ -159,7 +159,7 @@ public: */ ///@{ /// Return the dataset associated to this object. - vtkSmartPointer getPointSet() { + vtkSmartPointer getPointSet() override { return pointSet; } @@ -170,7 +170,7 @@ public: void setMeshWorldTransform(vtkSmartPointer) override; /// get the custom algorithm pipeline input. - vtkSmartPointer getDataPort() const { + vtkSmartPointer getDataPort() const override { return dataOutput; } @@ -190,10 +190,10 @@ public: void setTexture(vtkSmartPointer texture) override; /// a vtkPoint of the structured was picked (to be reimplemented in a Component inherited class if needed) - void pointPicked(vtkIdType, bool) {}; + void pointPicked(vtkIdType, bool) override {}; /// a vtkCell of the structured was picked (to be reimplemented in a Component inherited class if needed) - void cellPicked(vtkIdType, bool) {}; + void cellPicked(vtkIdType, bool) override {}; ///@} @@ -246,12 +246,12 @@ public: /// @{ /// Set the actor associated to a rendering mode visible or not. - void setRenderingModes(const RenderingModes rMode) { + void setRenderingModes(const RenderingModes rMode) override { renderingModes = rMode; } /// Return if the actor associated to a rendering mode is currently visible or not. - const RenderingModes getRenderingModes() const { + const RenderingModes getRenderingModes() const override { return renderingModes; } @@ -259,7 +259,7 @@ public: void setEnhancedModes(const EnhancedModes) override; /// get the current enhanced mode - const EnhancedModes getEnhancedModes() const { + const EnhancedModes getEnhancedModes() const override { return enhancedModes; } diff --git a/sdk/libraries/core/component/SimplisticComponent.h b/sdk/libraries/core/component/SimplisticComponent.h index 3a0fb255..ef5f3860 100644 --- a/sdk/libraries/core/component/SimplisticComponent.h +++ b/sdk/libraries/core/component/SimplisticComponent.h @@ -53,7 +53,7 @@ public: static SimplisticComponent* createInstance(QString name); /// this component has no representation - void initRepresentation() {} + void initRepresentation() override {} /// This simplistic component cannot have properties /// If you need properties, it means that you need a diff --git a/sdk/libraries/core/component/image/ImageComponent.cpp b/sdk/libraries/core/component/image/ImageComponent.cpp index fd474828..25c9017f 100644 --- a/sdk/libraries/core/component/image/ImageComponent.cpp +++ b/sdk/libraries/core/component/image/ImageComponent.cpp @@ -35,6 +35,7 @@ #include "MeshComponent.h" #include "Property.h" #include "Frame.h" +#include "Viewer.h" // -- vtk stuff #include @@ -85,6 +86,7 @@ ImageComponent::~ImageComponent() { if (model != nullptr) { delete model; } + if (selectionView != nullptr) { delete selectionView; } @@ -156,6 +158,7 @@ void ImageComponent::initImageProperties() { // from QObject documentation, section "Detailed Description": // "To avoid never ending notification loops you can temporarily block signals with blockSignals()." setProperty("Image Name", QVariant(getName())); + if (originalImageData != nullptr) { int* imgDims = originalImageData->GetDimensions(); @@ -200,19 +203,21 @@ void ImageComponent::updateProperty(QString name, QVariant value) { if (name == "Display Image in 3D Viewer") { update3DViewer(); } - else if (name == "Image Name") { - setName(value.toString()); - refreshInterfaceNode(); - } - // bypass read-only properties - // (other specific properties are read only and should not be sent up to Component::updateProperty) - else if (name != "Image Dimensions" - && name != "Image Size" - && name != "Voxel Size" - && name != "Voxel Data Type" - && name != "Initial Image Orientation") { - Component::updateProperty(name, value); - } + else + if (name == "Image Name") { + setName(value.toString()); + refreshInterfaceNode(); + } + // bypass read-only properties + // (other specific properties are read only and should not be sent up to Component::updateProperty) + else + if (name != "Image Dimensions" + && name != "Image Size" + && name != "Voxel Size" + && name != "Voxel Data Type" + && name != "Initial Image Orientation") { + Component::updateProperty(name, value); + } } // -------------------- setImageData -------------------- @@ -275,10 +280,12 @@ void ImageComponent::setImageData(vtkSmartPointer anImageData, initialFrameTransform = vtkSmartPointer::New(); vtkSmartPointer initialFrameMatrix = vtkSmartPointer::New(); rotationMatrix = initialRotationMatrix; + if (!rotationMatrix) { rotationMatrix = vtkSmartPointer::New(); rotationMatrix->Identity(); } + vtkMatrix4x4::Multiply4x4(rotationMatrix, initialTranslation->GetMatrix(), initialFrameMatrix); vtkMatrix4x4::Multiply4x4(initialFrameMatrix, orientationToRAIMatrix, initialFrameMatrix); initialFrameTransform->SetMatrix(initialFrameMatrix); @@ -501,9 +508,24 @@ QString ImageComponent::getImageName() const { return getName(); } +// -------------------- setVisibility -------------------- +void ImageComponent::setVisibility(Viewer* v, bool b) { + if (v != nullptr) { + if (v->getName() == "3DViewer") { + // if setVisibility was called and the current state is different, update it + if (property("Display Image in 3D Viewer").toBool() != b) { + setProperty("Display Image in 3D Viewer", b); + } + } + } + + Component::setVisibility(v, b); +} + // -------------------- update3DViewer -------------------- void ImageComponent::update3DViewer() { bool viewIn3D = property("Display Image in 3D Viewer").toBool(); + setVisibility(Application::getViewer("3DViewer"), viewIn3D); if (axialSlices != nullptr) { axialSlices->setViewSliceIn3D(viewIn3D); @@ -788,6 +810,7 @@ QWidget* ImageComponent::getPropertyWidgetAt(unsigned int i) { case 0: return selectionView; break; + default: return nullptr; } diff --git a/sdk/libraries/core/component/image/ImageComponent.h b/sdk/libraries/core/component/image/ImageComponent.h index 3eb80506..a9e33aea 100644 --- a/sdk/libraries/core/component/image/ImageComponent.h +++ b/sdk/libraries/core/component/image/ImageComponent.h @@ -100,12 +100,15 @@ public: /// set selected will select all the Image components (axial, sagittal and coronal). void setSelected(const bool b, const bool recursive = false) override; + /// set the visibility for a viewer (override required to manage the specific case of the 3D viewer) + virtual void setVisibility(Viewer*, bool) override; + /// getter/setter for the property QString getImageName() const; void setImageName(const QString&); /// get the image volume managed by this Component - vtkSmartPointer getImageData() const { + vtkSmartPointer getImageData() const override { return originalImageData; } @@ -253,7 +256,7 @@ private: virtual void initImageProperties(); /// the concrete building of the 3D objects (Slice/Geometry): none in this case! - void initRepresentation() {} + void initRepresentation() override {} // builds default lookup table void initLookupTable(); diff --git a/sdk/libraries/core/viewer/ViewerExtension.cpp b/sdk/libraries/core/viewer/ViewerExtension.cpp index f1b11da2..a55435ff 100644 --- a/sdk/libraries/core/viewer/ViewerExtension.cpp +++ b/sdk/libraries/core/viewer/ViewerExtension.cpp @@ -144,36 +144,6 @@ Viewer* ViewerExtension::getNewInstance(QString name) { else { CAMITK_ERROR(tr("Cannot instanciate %1 from static meta object").arg(getViewerClassName())); } -/*CLEANUP - int typeId = QMetaType::type(viewerClassName.toStdString().c_str()); - - if (typeId != QMetaType::UnknownType) { - // get the pointer to the viewer's class meta object - const QMetaObject* metaObject = QMetaType::metaObjectForType(typeId); - - if (metaObject == nullptr) { - // If not working try the meta type create method - void* instance = QMetaType::create(typeId); - // this pointer is bad and uninitialized - viewer = static_cast(instance); - - if (viewer == nullptr) { - CAMITK_ERROR(tr("Cannot get %1 metaObject nor use the QMetaType create method").arg(viewerClassName)); - } - } - else { - // instanciate a new viewer of the managed class - QObject* o = metaObject->newInstance(Q_ARG(QString, name)); - viewer = qobject_cast(o); - - // register it in the list - registerViewer(viewer); - } - } - else { - CAMITK_ERROR(tr("Cannot create new instance of %1: type not registered by Qt").arg(viewerClassName)); - } -*/ return viewerInstance; } diff --git a/sdk/viewers/bitmap/BitmapViewer.cpp b/sdk/viewers/bitmap/BitmapViewer.cpp index aaab0207..8b9badbe 100644 --- a/sdk/viewers/bitmap/BitmapViewer.cpp +++ b/sdk/viewers/bitmap/BitmapViewer.cpp @@ -46,7 +46,8 @@ BitmapViewer::BitmapViewer(QString name) : InteractiveViewer(name, InteractiveVi // parallel projection getRendererWidget()->getActiveCamera()->ParallelProjectionOn(); - setComponents(QStringList() << "ImageComponent"); + // can only display 2D bitmap = SingleImageComponent + setComponents(QStringList() << "SingleImageComponent"); myToolbar = nullptr; } @@ -85,10 +86,11 @@ QToolBar* BitmapViewer::getToolBar() { hideViewerAction->setIcon(QPixmap(":/fileClose")); hideViewerAction->setStatusTip(tr("Switch back to the medical image viewer")); hideViewerAction->setWhatsThis(tr("Switch back the ventral viewer to normal (i.e., show the Medical Image Viewer)")); - connect(hideViewerAction, &QAction::triggered, [=](bool) { + connect(hideViewerAction, &QAction::triggered, [ = ](bool) { Application::getMainWindow()->setCentralViewer(Application::getViewer("MedicalImageViewer")); }); } + return myToolbar; } diff --git a/sdk/viewers/interactivegeometryviewer/InteractiveGeometryViewer.cpp b/sdk/viewers/interactivegeometryviewer/InteractiveGeometryViewer.cpp index 314a6f56..d3770aed 100644 --- a/sdk/viewers/interactivegeometryviewer/InteractiveGeometryViewer.cpp +++ b/sdk/viewers/interactivegeometryviewer/InteractiveGeometryViewer.cpp @@ -23,7 +23,6 @@ * $CAMITK_LICENCE_END$ ****************************************************************************/ -// -- Core stuff #include "InteractiveGeometryViewer.h" using namespace camitk; @@ -31,12 +30,7 @@ using namespace camitk; // -------------------- Constructor -------------------- InteractiveGeometryViewer::InteractiveGeometryViewer(QString name) : InteractiveViewer(name, InteractiveViewer::GEOMETRY_VIEWER) { if (name == "3DViewer") { - // Axial Viewer + // the default 3D Viewer is embedded setLayout(Viewer::EMBEDDED); } } -/* CLEANUP - -// -------------------- Destructor -------------------- -InteractiveGeometryViewer::~InteractiveGeometryViewer() { -}*/ diff --git a/sdk/viewers/interactivesliceviewer/InteractiveSliceViewer.cpp b/sdk/viewers/interactivesliceviewer/InteractiveSliceViewer.cpp index f3c0115b..d0ed035d 100644 --- a/sdk/viewers/interactivesliceviewer/InteractiveSliceViewer.cpp +++ b/sdk/viewers/interactivesliceviewer/InteractiveSliceViewer.cpp @@ -23,15 +23,16 @@ * $CAMITK_LICENCE_END$ ****************************************************************************/ -// -- Core stuff #include "InteractiveSliceViewer.h" -#include + #include using namespace camitk; // -------------------- Constructor -------------------- InteractiveSliceViewer::InteractiveSliceViewer(QString name) : InteractiveViewer(name, InteractiveViewer::SLICE_VIEWER) { + setComponents(QStringList() << "SingleImageComponent" ); + if (name == "axialViewer") { // Axial Viewer setLayout(Viewer::EMBEDDED); diff --git a/sdk/viewers/medicalimageviewer/MedicalImageViewer.cpp b/sdk/viewers/medicalimageviewer/MedicalImageViewer.cpp index 92d082fc..ac9c3c3b 100644 --- a/sdk/viewers/medicalimageviewer/MedicalImageViewer.cpp +++ b/sdk/viewers/medicalimageviewer/MedicalImageViewer.cpp @@ -52,9 +52,6 @@ MedicalImageViewer::MedicalImageViewer(QString name) : Viewer(name) { autoUpdateToolbarVisibility = true; - /* - setComponents(QStringList() << "ImageComponent" << "MeshComponent"); - */ } -- GitLab From 23e4cfbefab80db3a31f99ccd5e78b01b1a73d8b Mon Sep 17 00:00:00 2001 From: Emmanuel Promayon Date: Thu, 6 Feb 2020 11:35:24 +0100 Subject: [PATCH 13/15] NEW mixed viewer example Shows how to simply re-use the default axial and 3D viewer in a dual panel viewer... --- .../config/testing/config-test.sh | 6 ++-- sdk/libraries/core/viewer/Viewer.cpp | 5 ++- sdk/libraries/core/viewer/Viewer.h | 4 +-- .../medicalimageviewer/MedicalImageViewer.cpp | 31 ++++++++++--------- .../medicalimageviewer/MedicalImageViewer.h | 6 ++++ tutorials/components/mixed/MixedComponent.cpp | 3 +- tutorials/viewers/textviewer/TextViewer.cpp | 2 +- tutorials/viewers/textviewer/TextViewer.h | 11 ++----- 8 files changed, 34 insertions(+), 34 deletions(-) diff --git a/sdk/applications/config/testing/config-test.sh b/sdk/applications/config/testing/config-test.sh index 02a1f9a4..4ec58e15 100644 --- a/sdk/applications/config/testing/config-test.sh +++ b/sdk/applications/config/testing/config-test.sh @@ -22,13 +22,13 @@ set -e # values to check initTestData() { # fill test data - extensionCount=( [4.2]=52 [4.1]=41 [4.0]=31 ) + extensionCount=( [4.2]=53 [4.1]=41 [4.0]=31 ) componentExtensionCount=( [4.2]=14 [4.1]=14 [4.0]=14 ) actionExtensionCount=( [4.2]=29 [4.1]=27 [4.0]=27 ) - viewerExtensionCount=( [4.2]=9 ) + viewerExtensionCount=( [4.2]=10 ) fileExtensionCount=( [4.2]=37 [4.1]=37 [4.0]=37 ) actionCount=( [4.2]=108 [4.1]=105 [4.0]=105 ) - viewerCount=( [4.2]=12 ) + viewerCount=( [4.2]=13 ) # fill release date releaseDate=( [4.2]="not yet released, current development version" \ diff --git a/sdk/libraries/core/viewer/Viewer.cpp b/sdk/libraries/core/viewer/Viewer.cpp index c4fae204..b6116969 100644 --- a/sdk/libraries/core/viewer/Viewer.cpp +++ b/sdk/libraries/core/viewer/Viewer.cpp @@ -144,7 +144,7 @@ void Viewer::stackIn(QStackedWidget* stackedWidget) { } // check all conditions are met - if (getWidget() != nullptr && this->stackedWidget == nullptr) { + if (getWidget() != nullptr) { // add the viewer's widget inside the stack stackedWidget->addWidget(getWidget()); // keep the pointer @@ -165,9 +165,8 @@ void Viewer::embedIn(QLayout* embeddedLayout) { } // check all conditions are met - if (getWidget() != nullptr && this->embeddedLayout == nullptr) { + if (getWidget() != nullptr) { embeddedLayout->addWidget(getWidget()); - //getWidget()->setParent(embeddedLayout->parentWidget()); // keep the pointer this->embeddedLayout = embeddedLayout; } diff --git a/sdk/libraries/core/viewer/Viewer.h b/sdk/libraries/core/viewer/Viewer.h index 5eeb70a4..47e54918 100644 --- a/sdk/libraries/core/viewer/Viewer.h +++ b/sdk/libraries/core/viewer/Viewer.h @@ -102,10 +102,10 @@ public: QDockWidget* dockIn(); /// show the viewer's widget in the stack - /// If it is the first call, add the viewer widget in the given stack (once done, it cannot change stack) + /// If it is the first call, add the viewer widget in the given stack void stackIn(QStackedWidget*); - /// Add the viewer widget in the given layout (once done, the layout cannot be changed) + /// Add the viewer widget in the given layout void embedIn(QLayout*); /// returns the number of Component that are displayed by this viewer diff --git a/sdk/viewers/medicalimageviewer/MedicalImageViewer.cpp b/sdk/viewers/medicalimageviewer/MedicalImageViewer.cpp index ac9c3c3b..5c892200 100644 --- a/sdk/viewers/medicalimageviewer/MedicalImageViewer.cpp +++ b/sdk/viewers/medicalimageviewer/MedicalImageViewer.cpp @@ -126,21 +126,15 @@ QWidget* MedicalImageViewer::getWidget() { frameLayout->setMargin(0); /// the layout for the arbitrary/axial at the top left position of frameLayout - QVBoxLayout* innerLayout = new QVBoxLayout(); - frameLayout->addLayout(innerLayout, 0, 0); // north-west - Application::getViewer("axialViewer")->embedIn(innerLayout); - innerLayout = new QVBoxLayout(); - frameLayout->addLayout(innerLayout, 1, 0); // south-west - Application::getViewer("coronalViewer")->embedIn(innerLayout); - innerLayout = new QVBoxLayout(); - frameLayout->addLayout(innerLayout, 1, 1); // south-east - Application::getViewer("sagittalViewer")->embedIn(innerLayout); - innerLayout = new QVBoxLayout(); - frameLayout->addLayout(innerLayout, 0, 1); // north-east - - Application::getViewer("3DViewer")->embedIn(innerLayout); - Application::getViewer("arbitraryViewer")->embedIn(innerLayout); - + northWestLayout = new QVBoxLayout(); + frameLayout->addLayout(northWestLayout, 0, 0); // north-west + southWestLayout = new QVBoxLayout(); + frameLayout->addLayout(southWestLayout, 1, 0); // south-west + southEastLayout = new QVBoxLayout(); + frameLayout->addLayout(southEastLayout, 1, 1); // south-east + northEastLayout = new QVBoxLayout(); + frameLayout->addLayout(northEastLayout, 0, 1); // north-east + //-- connect foreach (LayoutVisibility v, viewerVisibility) { if (viewers.value(v)) { // prevent ALL @@ -152,6 +146,13 @@ QWidget* MedicalImageViewer::getWidget() { updateLayout(); } + // always re-embed the viewers (in case another viewer embeded them somewhere else in the meanwhile) + Application::getViewer("axialViewer")->embedIn(northWestLayout); + Application::getViewer("coronalViewer")->embedIn(southWestLayout); + Application::getViewer("sagittalViewer")->embedIn(southEastLayout); + Application::getViewer("3DViewer")->embedIn(northEastLayout); + Application::getViewer("arbitraryViewer")->embedIn(northEastLayout); + return frame; } diff --git a/sdk/viewers/medicalimageviewer/MedicalImageViewer.h b/sdk/viewers/medicalimageviewer/MedicalImageViewer.h index 30c02e67..302c1f0d 100644 --- a/sdk/viewers/medicalimageviewer/MedicalImageViewer.h +++ b/sdk/viewers/medicalimageviewer/MedicalImageViewer.h @@ -121,6 +121,12 @@ private: /// The main layout QGridLayout* frameLayout; + /// The four corners of the main layout + QVBoxLayout* northWestLayout; + QVBoxLayout* southWestLayout; + QVBoxLayout* northEastLayout; + QVBoxLayout* southEastLayout; + /// the main widget QFrame* frame; diff --git a/tutorials/components/mixed/MixedComponent.cpp b/tutorials/components/mixed/MixedComponent.cpp index 465bedf5..1d462f6f 100644 --- a/tutorials/components/mixed/MixedComponent.cpp +++ b/tutorials/components/mixed/MixedComponent.cpp @@ -49,5 +49,6 @@ MixedComponent::MixedComponent(const QString& file) : Component(file, QFileInfo( // Create vtk component and connect it as a sub-component VtkMeshComponent* meshCpt = new VtkMeshComponent(vtkFile); addChild(meshCpt); - + // show only wireframe + meshCpt->setRenderingModes(InterfaceGeometry::Wireframe); } diff --git a/tutorials/viewers/textviewer/TextViewer.cpp b/tutorials/viewers/textviewer/TextViewer.cpp index c149fafe..6b1e7d95 100644 --- a/tutorials/viewers/textviewer/TextViewer.cpp +++ b/tutorials/viewers/textviewer/TextViewer.cpp @@ -42,12 +42,12 @@ TextViewer::TextViewer(QString name) : Viewer(name) { inverse = nullptr; myMenu = nullptr; myWidget = nullptr; - isVisible = false; displayedTopLevelComponents = 0; } // -------------------- Destructor -------------------- TextViewer::~TextViewer() { + delete myWidget; } diff --git a/tutorials/viewers/textviewer/TextViewer.h b/tutorials/viewers/textviewer/TextViewer.h index 1b864c7b..ffce5e85 100644 --- a/tutorials/viewers/textviewer/TextViewer.h +++ b/tutorials/viewers/textviewer/TextViewer.h @@ -120,17 +120,10 @@ private: /// colors QColor textColor; QColor bgColor; + + /// color management void updateColors(); - /// current visibility state - bool isVisible; - - /// the viewer instance singleton - static TextViewer* singleton; - - /// the unique instance name - static QString viewerName; - }; #endif // TEXT_VIEWER_H -- GitLab From 8ddaa17f38f1cc32b656516c1e2737df7998e497 Mon Sep 17 00:00:00 2001 From: Emmanuel Promayon Date: Thu, 6 Feb 2020 11:43:10 +0100 Subject: [PATCH 14/15] NEW introducing the dual panel viewer Very simple viewer that relies on MedicalImageViewer to do the heavy work (for instance the synchronization between the viewers is already taken into account by what the MedicalImageViewer set in place). --- tutorials/viewers/mixedviewer/CMakeLists.txt | 9 ++ tutorials/viewers/mixedviewer/MixedViewer.cpp | 81 ++++++++++++++++++ tutorials/viewers/mixedviewer/MixedViewer.h | 83 +++++++++++++++++++ .../viewers/mixedviewer/MixedViewerAPI.h | 67 +++++++++++++++ .../mixedviewer/MixedViewerExtension.cpp | 36 ++++++++ .../mixedviewer/MixedViewerExtension.h | 61 ++++++++++++++ 6 files changed, 337 insertions(+) create mode 100644 tutorials/viewers/mixedviewer/CMakeLists.txt create mode 100644 tutorials/viewers/mixedviewer/MixedViewer.cpp create mode 100644 tutorials/viewers/mixedviewer/MixedViewer.h create mode 100644 tutorials/viewers/mixedviewer/MixedViewerAPI.h create mode 100644 tutorials/viewers/mixedviewer/MixedViewerExtension.cpp create mode 100644 tutorials/viewers/mixedviewer/MixedViewerExtension.h diff --git a/tutorials/viewers/mixedviewer/CMakeLists.txt b/tutorials/viewers/mixedviewer/CMakeLists.txt new file mode 100644 index 00000000..69498ee5 --- /dev/null +++ b/tutorials/viewers/mixedviewer/CMakeLists.txt @@ -0,0 +1,9 @@ +# Call CamiTK CMake Macro to define the action +camitk_extension(VIEWER_EXTENSION + DEFAULT + DEFINES COMPILE_MIXED_VIEWER_API + NEEDS_COMPONENT_EXTENSION mixed + DESCRIPTION "An extension to demonstrate a dual viewer (only for ImageComponent and MixedComponent)" + INSTALL_ALL_HEADERS +) + diff --git a/tutorials/viewers/mixedviewer/MixedViewer.cpp b/tutorials/viewers/mixedviewer/MixedViewer.cpp new file mode 100644 index 00000000..2c120224 --- /dev/null +++ b/tutorials/viewers/mixedviewer/MixedViewer.cpp @@ -0,0 +1,81 @@ +/***************************************************************************** + * $CAMITK_LICENCE_BEGIN$ + * + * CamiTK - Computer Assisted Medical Intervention ToolKit + * (c) 2001-2018 Univ. Grenoble Alpes, CNRS, TIMC-IMAG UMR 5525 (GMCAO) + * + * Visit http://camitk.imag.fr for more information + * + * This file is part of CamiTK. + * + * CamiTK is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * CamiTK is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with CamiTK. If not, see . + * + * $CAMITK_LICENCE_END$ + ****************************************************************************/ + +#include "MixedViewer.h" + +// -- Core stuff +#include +#include + +//-- Qt stuff +#include + +using namespace camitk; + +// -------------------- Constructor -------------------- +MixedViewer::MixedViewer(QString name) : Viewer(name) { + myWidget = nullptr; + setComponents(QStringList() << "ImageComponent" << "MixedComponent"); +} + +// -------------------- Destructor -------------------- +MixedViewer::~MixedViewer() { + delete myWidget; +} + + +// -------------------- numberOfViewedComponentgetWidget -------------------- +unsigned int MixedViewer::numberOfViewedComponent() { + return Application::getViewer("MedicalImageViewer")->numberOfViewedComponent(); +} + +// -------------------- refresh -------------------- +void MixedViewer::refresh(Viewer*) { + // nothing to do as everything is already done by the MedicalImageViewer! +} + +// -------------------- getWidget -------------------- +QWidget* MixedViewer::getWidget() { + if (!myWidget) { + myWidget = new QWidget(); + + //-- init layout + auto* myWidgetLayout = new QGridLayout(); + myWidgetLayout->setSpacing(0); + myWidgetLayout->setMargin(0); + leftLayout = new QVBoxLayout(); + myWidgetLayout->addLayout(leftLayout, 0, 0); + rightLayout = new QVBoxLayout(); + myWidgetLayout->addLayout(rightLayout, 0, 1); + myWidget->setLayout(myWidgetLayout); + } + + // always re-embed the viewers (in case another viewer embeded them somewhere else in the meanwhile) + Application::getViewer("axialViewer")->embedIn(leftLayout); + Application::getViewer("3DViewer")->embedIn(rightLayout); + + return myWidget; +} + diff --git a/tutorials/viewers/mixedviewer/MixedViewer.h b/tutorials/viewers/mixedviewer/MixedViewer.h new file mode 100644 index 00000000..1675a610 --- /dev/null +++ b/tutorials/viewers/mixedviewer/MixedViewer.h @@ -0,0 +1,83 @@ +/***************************************************************************** + * $CAMITK_LICENCE_BEGIN$ + * + * CamiTK - Computer Assisted Medical Intervention ToolKit + * (c) 2001-2018 Univ. Grenoble Alpes, CNRS, TIMC-IMAG UMR 5525 (GMCAO) + * + * Visit http://camitk.imag.fr for more information + * + * This file is part of CamiTK. + * + * CamiTK is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * CamiTK is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with CamiTK. If not, see . + * + * $CAMITK_LICENCE_END$ + ****************************************************************************/ + + +#ifndef MIXED_VIEWER_H +#define MIXED_VIEWER_H + +#include "MixedViewerAPI.h" + +// -- Core stuff +#include +#include + +// -- QT stuff +#include + +/** + * A dual panel viewer... + * It just send reused the axial and 3D viewer to display two views of the same thing. + */ +class MIXED_VIEWER_API MixedViewer : public camitk::Viewer { + Q_OBJECT + +public: + + /** @name Constructors/Destructors + */ + /// @{ + /** construtor. */ + Q_INVOKABLE MixedViewer(QString name); + + /** destructor */ + virtual ~MixedViewer(); + /// @} + + /** @name Viewer inherited + */ + /// @{ + /// returns the number of Component that are displayed by this viewer + virtual unsigned int numberOfViewedComponent() override; + + /// refresh the view (can be interesting to know which other viewer is calling this) + virtual void refresh(Viewer* whoIsAsking = nullptr) override; + + /// get the viewer widget. + virtual QWidget* getWidget() override; + /// @} + +private: + + /// The viewer's widget + QWidget* myWidget; + + /// The two panel of the main layout + QVBoxLayout* leftLayout; + QVBoxLayout* rightLayout; + +}; + +#endif // MIXED_VIEWER_H + diff --git a/tutorials/viewers/mixedviewer/MixedViewerAPI.h b/tutorials/viewers/mixedviewer/MixedViewerAPI.h new file mode 100644 index 00000000..e2b06853 --- /dev/null +++ b/tutorials/viewers/mixedviewer/MixedViewerAPI.h @@ -0,0 +1,67 @@ +/***************************************************************************** + * $CAMITK_LICENCE_BEGIN$ + * + * CamiTK - Computer Assisted Medical Intervention ToolKit + * (c) 2001-2014 UJF-Grenoble 1, CNRS, TIMC-IMAG UMR 5525 (GMCAO) + * + * Visit http://camitk.imag.fr for more information + * + * + * CamiTK is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * CamiTK is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with CamiTK. If not, see . + * + * $CAMITK_LICENCE_END$ + ****************************************************************************/ + +#ifndef MIXED_VIEWER_API_H +#define MIXED_VIEWER_API_H + +// ----------------------------------------------------------------------- +// +// MIXED_VIEWER_API +// +// ----------------------------------------------------------------------- +// The following ifdef block is the standard way of creating macros which make exporting +// from a DLL simpler. All files within this DLL are compiled with the COMPILE_MIXED_VIEWER_API +// flag defined on the command line. this symbol should not be defined on any project +// that uses this DLL. This way any other project whose source files include this file see +// MIXED_VIEWER_API functions as being imported from a DLL, whereas this DLL sees symbols +// defined with this macro as being exported. +#if defined(_WIN32) // MSVC and mingw +#ifdef COMPILE_MIXED_VIEWER_API +#define MIXED_VIEWER_API __declspec(dllexport) +#else +#define MIXED_VIEWER_API __declspec(dllimport) +#endif +#else +// for all other platforms MIXED_VIEWER_API is defined to be "nothing" +#ifndef MIXED_VIEWER_API +#define MIXED_VIEWER_API +#endif +#endif // MSVC and mingw + +// ----------------------------------------------------------------------- +// It seems that MSVC does not understand exception specification +// If I understand it well, when _declspec() is used, there is a default +// nothrow attribute. +// I did not find the throw attribute. It seems that msvc is therefore ignoring the +// specification of the type of the exception. +// The compiler therefore issues a warning. +// The following line is to avoid this particular warning. +// The best would be to ask msvc not only to take the exception into account, but also +// its type. Anyway, I did not find how to do that anywhere, and I am not sure this is +// possible... +#if defined(_WIN32) && !defined(__MINGW32__) // MSVC only +#pragma warning( disable : 4290 ) +#endif // MSVC only + +#endif // MIXED_VIEWER_API_H diff --git a/tutorials/viewers/mixedviewer/MixedViewerExtension.cpp b/tutorials/viewers/mixedviewer/MixedViewerExtension.cpp new file mode 100644 index 00000000..f077a7ef --- /dev/null +++ b/tutorials/viewers/mixedviewer/MixedViewerExtension.cpp @@ -0,0 +1,36 @@ +/***************************************************************************** + * $CAMITK_LICENCE_BEGIN$ + * + * CamiTK - Computer Assisted Medical Intervention ToolKit + * (c) 2001-2018 Univ. Grenoble Alpes, CNRS, TIMC-IMAG UMR 5525 (GMCAO) + * + * Visit http://camitk.imag.fr for more information + * + * This file is part of CamiTK. + * + * CamiTK is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * CamiTK is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with CamiTK. If not, see . + * + * $CAMITK_LICENCE_END$ + ****************************************************************************/ + + +#include "MixedViewerExtension.h" + +// include generated actions headers +#include "MixedViewer.h" + +// --------------- getActions ------------------- +void MixedViewerExtension::init() { + registerDefaultViewer(MixedViewer); +} + diff --git a/tutorials/viewers/mixedviewer/MixedViewerExtension.h b/tutorials/viewers/mixedviewer/MixedViewerExtension.h new file mode 100644 index 00000000..2dad1383 --- /dev/null +++ b/tutorials/viewers/mixedviewer/MixedViewerExtension.h @@ -0,0 +1,61 @@ +/***************************************************************************** + * $CAMITK_LICENCE_BEGIN$ + * + * CamiTK - Computer Assisted Medical Intervention ToolKit + * (c) 2001-2018 Univ. Grenoble Alpes, CNRS, TIMC-IMAG UMR 5525 (GMCAO) + * + * Visit http://camitk.imag.fr for more information + * + * This file is part of CamiTK. + * + * CamiTK is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * CamiTK is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with CamiTK. If not, see . + * + * $CAMITK_LICENCE_END$ + ****************************************************************************/ + + +#ifndef MIXED_VIEWER_EXTENSION_H +#define MIXED_VIEWER_EXTENSION_H + +#include + +class MixedViewerExtension : public camitk::ViewerExtension { + Q_OBJECT + Q_INTERFACES(camitk::ViewerExtension); + Q_PLUGIN_METADATA(IID "fr.imag.camitk.tutorials.viewer.mixedviewerextension") + +public: + /// Constructor + MixedViewerExtension() : ViewerExtension() {}; + + /// Destructor + virtual ~MixedViewerExtension() = default; + + /// Method returning the action extension name + virtual QString getName() { + return "MixedViewer Extension"; + }; + + /// Method returning the action extension descrption + virtual QString getDescription() { + return "An extension that brings a pure text viewer called... MixedViewer"; + }; + + /// initialize all the actions + virtual void init(); + +}; + +#endif // MIXED_VIEWER_EXTENSION_H + + -- GitLab From 1b47380a35992b455bf0674e0d69c8b9523875e8 Mon Sep 17 00:00:00 2001 From: Emmanuel Promayon Date: Thu, 6 Feb 2020 14:12:20 +0100 Subject: [PATCH 15/15] FIXED simplified Viewer API No need for the numberOfViewedComponent method --- .../actionstatemachine/ActionStateViewer.h | 5 ---- .../core/viewer/InteractiveViewer.cpp | 5 ---- sdk/libraries/core/viewer/InteractiveViewer.h | 3 --- sdk/libraries/core/viewer/Viewer.h | 3 --- sdk/viewers/actionviewer/ActionViewer.h | 9 ++----- sdk/viewers/explorer/Explorer.cpp | 5 ---- sdk/viewers/explorer/Explorer.h | 11 +++----- sdk/viewers/frameexplorer/FrameExplorer.cpp | 5 ---- sdk/viewers/frameexplorer/FrameExplorer.h | 3 --- .../medicalimageviewer/MedicalImageViewer.cpp | 26 +++++++------------ .../medicalimageviewer/MedicalImageViewer.h | 3 --- .../propertyexplorer/PropertyExplorer.cpp | 10 ------- .../propertyexplorer/PropertyExplorer.h | 3 --- tutorials/viewers/mixedviewer/MixedViewer.cpp | 6 ----- tutorials/viewers/mixedviewer/MixedViewer.h | 13 +++++++--- tutorials/viewers/textviewer/TextViewer.cpp | 6 ----- tutorials/viewers/textviewer/TextViewer.h | 3 --- 17 files changed, 24 insertions(+), 95 deletions(-) diff --git a/sdk/applications/actionstatemachine/ActionStateViewer.h b/sdk/applications/actionstatemachine/ActionStateViewer.h index 6842232d..3e6a6095 100644 --- a/sdk/applications/actionstatemachine/ActionStateViewer.h +++ b/sdk/applications/actionstatemachine/ActionStateViewer.h @@ -52,11 +52,6 @@ public: /// get the viewer widget. virtual QWidget* getWidget(); - /// returns the number of Component that are displayed by this viewer - virtual unsigned int numberOfViewedComponent() { - return 0; - }; - /// refresh the view (can be interesting to know which other viewer is calling this) virtual void refresh(Viewer* whoIsAsking = nullptr) {}; diff --git a/sdk/libraries/core/viewer/InteractiveViewer.cpp b/sdk/libraries/core/viewer/InteractiveViewer.cpp index 36d2ef4c..1f4e60af 100644 --- a/sdk/libraries/core/viewer/InteractiveViewer.cpp +++ b/sdk/libraries/core/viewer/InteractiveViewer.cpp @@ -391,11 +391,6 @@ QString InteractiveViewer::getName() const { return objectName(); } -// ---------------- numberOfViewedComponent ---------------- -unsigned int InteractiveViewer::numberOfViewedComponent() { - return actorMap.size(); -} - // ---------------------- refresh ---------------------------- void InteractiveViewer::refresh(Viewer* v) { diff --git a/sdk/libraries/core/viewer/InteractiveViewer.h b/sdk/libraries/core/viewer/InteractiveViewer.h index 31ba7bca..266623a3 100644 --- a/sdk/libraries/core/viewer/InteractiveViewer.h +++ b/sdk/libraries/core/viewer/InteractiveViewer.h @@ -186,9 +186,6 @@ public: /** @name Inherited from Viewer */ ///@{ - /// returns the number of Component that are displayed by this viewer - unsigned int numberOfViewedComponent() override; - /// Refresh the display. void refresh(Viewer* whoIsAsking = nullptr) override; diff --git a/sdk/libraries/core/viewer/Viewer.h b/sdk/libraries/core/viewer/Viewer.h index 47e54918..260bfaa1 100644 --- a/sdk/libraries/core/viewer/Viewer.h +++ b/sdk/libraries/core/viewer/Viewer.h @@ -108,9 +108,6 @@ public: /// Add the viewer widget in the given layout void embedIn(QLayout*); - /// returns the number of Component that are displayed by this viewer - virtual unsigned int numberOfViewedComponent() = 0; - /// refresh the view (can be interesting to know which other viewer is calling this) virtual void refresh(Viewer* whoIsAsking = nullptr) = 0; diff --git a/sdk/viewers/actionviewer/ActionViewer.h b/sdk/viewers/actionviewer/ActionViewer.h index 5483b384..e8c640b0 100644 --- a/sdk/viewers/actionviewer/ActionViewer.h +++ b/sdk/viewers/actionviewer/ActionViewer.h @@ -70,16 +70,11 @@ public: /// @name Inherited from Viewer //@{ - /// returns the number of Component that are displayed by this viewer - unsigned int numberOfViewedComponent() { - return 0; - }; - /// refresh the view (can be interesting to know which other viewer is calling this) - virtual void refresh(Viewer* whoIsAsking = nullptr); + virtual void refresh(Viewer* whoIsAsking = nullptr) override; /// get the viewer widget - virtual QWidget* getWidget(); + virtual QWidget* getWidget() override; //@} /// show/hide the search panel (hidden by default) diff --git a/sdk/viewers/explorer/Explorer.cpp b/sdk/viewers/explorer/Explorer.cpp index a6cb347c..d13c7c54 100644 --- a/sdk/viewers/explorer/Explorer.cpp +++ b/sdk/viewers/explorer/Explorer.cpp @@ -115,11 +115,6 @@ QWidget* Explorer::getPreferenceWidget(QWidget* parent) { return nullptr; } -// ---------------- numberOfViewedComponent ---------------- -unsigned int Explorer::numberOfViewedComponent() { - return itemComponentMap.size(); -} - //----------------------- refresh ------------------------ void Explorer::refresh(Viewer* whoIsAsking) { // if it is this instance who is asking the refresh, then only the Component names need to be checked... diff --git a/sdk/viewers/explorer/Explorer.h b/sdk/viewers/explorer/Explorer.h index a337bac0..df34fa09 100644 --- a/sdk/viewers/explorer/Explorer.h +++ b/sdk/viewers/explorer/Explorer.h @@ -37,10 +37,10 @@ #include namespace camitk { - // -- Core stuff classes - class InterfaceNode; - class Component; - class ExplorerItem; + // -- Core stuff classes + class InterfaceNode; + class Component; + class ExplorerItem; } /** @@ -73,9 +73,6 @@ public: /** @name Inherited from Viewer */ ///@{ - /// returns the number of Component that are displayed by this viewer - unsigned int numberOfViewedComponent() override; - /// refresh the explorer (can be interesting to know which other viewer is calling this) void refresh(camitk::Viewer* whoIsAsking = nullptr) override; diff --git a/sdk/viewers/frameexplorer/FrameExplorer.cpp b/sdk/viewers/frameexplorer/FrameExplorer.cpp index 3a481b19..62c68bbe 100644 --- a/sdk/viewers/frameexplorer/FrameExplorer.cpp +++ b/sdk/viewers/frameexplorer/FrameExplorer.cpp @@ -71,11 +71,6 @@ QWidget* FrameExplorer::getPreferenceWidget(QWidget* parent) { return nullptr; } -// ---------------- numberOfViewedComponent ---------------- -unsigned int FrameExplorer::numberOfViewedComponent() { - return 0; -} - //----------------------- refresh ------------------------ void FrameExplorer::refresh(Viewer* whoIsAsking) { // if it is this instance who is asking the refresh, then only the Component names need to be checked... diff --git a/sdk/viewers/frameexplorer/FrameExplorer.h b/sdk/viewers/frameexplorer/FrameExplorer.h index f0e292b2..03257b80 100644 --- a/sdk/viewers/frameexplorer/FrameExplorer.h +++ b/sdk/viewers/frameexplorer/FrameExplorer.h @@ -65,9 +65,6 @@ public: /** @name Inherited from Viewer */ ///@{ - /// returns the number of Component that are displayed by this viewer - unsigned int numberOfViewedComponent() override; - /// refresh the frame explorer (can be interesting to know which other viewer is calling this) void refresh(Viewer* whoIsAsking = nullptr) override; diff --git a/sdk/viewers/medicalimageviewer/MedicalImageViewer.cpp b/sdk/viewers/medicalimageviewer/MedicalImageViewer.cpp index 5c892200..287a702f 100644 --- a/sdk/viewers/medicalimageviewer/MedicalImageViewer.cpp +++ b/sdk/viewers/medicalimageviewer/MedicalImageViewer.cpp @@ -57,18 +57,9 @@ MedicalImageViewer::MedicalImageViewer(QString name) : Viewer(name) { // -------------------- Destructor -------------------- MedicalImageViewer::~MedicalImageViewer() { -} - - -// -------------------- numberOfViewedComponentgetWidget -------------------- -unsigned int MedicalImageViewer::numberOfViewedComponent() { - unsigned int count = 0; - - for (unsigned int i = 0; viewerVisibility[i] != VIEWER_ALL; i++) { - count += viewers.value(viewerVisibility[i])->numberOfViewedComponent(); - } - - return count; + viewerMenu->clear(); + delete viewerMenu; + delete frame; } // -------------------- refresh -------------------- @@ -80,11 +71,12 @@ void MedicalImageViewer::refresh(Viewer* whoIsAsking) { // view everything? if (displayedTopLevelComponents != (unsigned) Application::getTopLevelComponents().size()) { - // if there the nr of Component changed since last refresh, - // and if there is something displayed in the slices viewer, show all view - if (Application::getViewer("axialViewer")->numberOfViewedComponent() > 0 - && Application::getViewer("coronalViewer")->numberOfViewedComponent() > 0 - && Application::getViewer("sagittalViewer")->numberOfViewedComponent() > 0) { + // Check if there is ImageComponent, if yes show all viewers + int i = 0; + while (iisInstanceOf("ImageComponent")) { + i++; + } + if (inumberOfViewedComponent(); -} - // -------------------- refresh -------------------- void MixedViewer::refresh(Viewer*) { // nothing to do as everything is already done by the MedicalImageViewer! diff --git a/tutorials/viewers/mixedviewer/MixedViewer.h b/tutorials/viewers/mixedviewer/MixedViewer.h index 1675a610..1d026395 100644 --- a/tutorials/viewers/mixedviewer/MixedViewer.h +++ b/tutorials/viewers/mixedviewer/MixedViewer.h @@ -39,6 +39,14 @@ /** * A dual panel viewer... * It just send reused the axial and 3D viewer to display two views of the same thing. + * + * All the heavy work is already done by the MedicalImageViewer: + * - view synchronization + * - update and refresh of the viewer + * - management of viewed components + * + * This viewer is therefore very simple. In the end it is just building a specific widget + * that presents the axial and 3D viewer side by side using a grid layout. */ class MIXED_VIEWER_API MixedViewer : public camitk::Viewer { Q_OBJECT @@ -58,9 +66,6 @@ public: /** @name Viewer inherited */ /// @{ - /// returns the number of Component that are displayed by this viewer - virtual unsigned int numberOfViewedComponent() override; - /// refresh the view (can be interesting to know which other viewer is calling this) virtual void refresh(Viewer* whoIsAsking = nullptr) override; @@ -73,7 +78,7 @@ private: /// The viewer's widget QWidget* myWidget; - /// The two panel of the main layout + /// The two panels inside the main layout QVBoxLayout* leftLayout; QVBoxLayout* rightLayout; diff --git a/tutorials/viewers/textviewer/TextViewer.cpp b/tutorials/viewers/textviewer/TextViewer.cpp index 6b1e7d95..16b1006b 100644 --- a/tutorials/viewers/textviewer/TextViewer.cpp +++ b/tutorials/viewers/textviewer/TextViewer.cpp @@ -50,12 +50,6 @@ TextViewer::~TextViewer() { delete myWidget; } - -// -------------------- numberOfViewedComponentgetWidget -------------------- -unsigned int TextViewer::numberOfViewedComponent() { - return displayedTopLevelComponents; -} - // -------------------- refresh -------------------- void TextViewer::refresh(Viewer* whoIsAsking) { // view everything? diff --git a/tutorials/viewers/textviewer/TextViewer.h b/tutorials/viewers/textviewer/TextViewer.h index ffce5e85..273985dd 100644 --- a/tutorials/viewers/textviewer/TextViewer.h +++ b/tutorials/viewers/textviewer/TextViewer.h @@ -68,9 +68,6 @@ public: /** @name Viewer inherited */ /// @{ - /// returns the number of Component that are displayed by this viewer - virtual unsigned int numberOfViewedComponent(); - /// refresh the view (can be interesting to know which other viewer is calling this) virtual void refresh(Viewer* whoIsAsking = nullptr); -- GitLab