diff --git a/modeling/components/pmlcomponent/PMLComponent.cpp b/modeling/components/pmlcomponent/PMLComponent.cpp index a0b9536b57065a6fccf52d886b8d1c866c2f1282..eb61174331edc3c40eb8ea4d5a88ef419d610d62 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/modeling/libraries/mml/monitoringgui/MonitoringDialog.cpp b/modeling/libraries/mml/monitoringgui/MonitoringDialog.cpp index 631e367b4f3df8ddaa75575942c8d7d73bf976e4..b4e1376b92e31991baf0798c3cce62d1a88aab15 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/CMakeLists.txt b/sdk/CMakeLists.txt index db305b7e5ace28f02b577dfdbcc8599f3a974dfc..4e4bd7f79e2f66cac72134ae4d6d4f466a3c9b87 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 288e7689e2c54fb97a4474196d3cc59b57525cff..894ed42ef9b2f190f5c9982e446b5f6848c55352 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 d091c88b00de390c334bb211a7d0bdcc762dfabd..074e67d5c6f1ca356c3a04dc871dcfd9eb9ca7c8 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 7b687a2ec965434067b899b3bd4f528ff5b9d0fc..840a2dce9ea68b5c3ff346597e7a15938ef34704 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 39094316b66441c248f698d57876bf1464907add..9830da2467b3bd2de552502555536b142b8e9f7b 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 c9ddb37c53cf3b519c58afec44724b8b6d625dc4..b69b774f88da4fa6f93e7b360d6c82c1d33b0ba4 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 19beb6fcccda2b6ddb824adba92afdbe0d5730a9..8c713db317c56489b18f123a62f7930492294872 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 6ec9e733edf4bf04f55f06d0265c73719d0ccde0..80005ec07de8e381c9f307ccc7fd6ebe30ecdaf4 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 c6b9de37382ac09303190897b8c1bfb7afea073c..961d3f2828267df6fd63fd6757852dc2153727e5 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 f260b7e8e776314eb77cbe791bc47c0a87c979ef..a0c29d855aa10e7dab729174255eab2f9f427f17 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/arbitraryslice/AnglesAndTranslationAction.cpp b/sdk/actions/image/arbitraryslice/AnglesAndTranslationAction.cpp index c60a65bf17a25fbdd7f027799c882b62a762abc9..a20381bc388ade28f81c320131ef0a2475ab425f 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/AnglesAndTranslationAction.h b/sdk/actions/image/arbitraryslice/AnglesAndTranslationAction.h index b2a45024d8da3ebaa6f3d098735bf79d1bc955bc..4fe6b39b4d4cafbabb13f5c190920bbd2d55a973 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: diff --git a/sdk/actions/image/arbitraryslice/AnglesAndTranslationWidget.cpp b/sdk/actions/image/arbitraryslice/AnglesAndTranslationWidget.cpp index 12e4829f11c65d946fa76150e9ecbe6d5fb239ab..0869daaa8ac707e19de9d4780d24f53c052d54bf 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/actions/image/arbitraryslice/CMakeLists.txt b/sdk/actions/image/arbitraryslice/CMakeLists.txt index dbb2d8432a172faf1b114d862e05674f056728ef..1095912879ee8532bde002a895843f140e724843 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/pixelcolorchanger/PixelColorChanger.cpp b/sdk/actions/image/pixelcolorchanger/PixelColorChanger.cpp index eb88db782f09067bfe8ef03e8b9ec4eb8ff0bd1c..042091edf8456c270acc2a18c55b49d9eee99f23 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 f1a4a9ed500c537912a19ea5340b7c245356ccd3..8f92a7eeeb2d0444ccb1e64f808e65134c947930 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 5bddcd30dcf1ad359200ce6f98133eb0529d42d3..0d3f588ae5c1106744927782389ac1f3fe332a7c 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 e795439d494090133eecc5ca6aa077309757ea35..08804a51b5bdbc3d8c670a5888caefd1769e0f3a 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 9ce4b3c20c689205cc24dfb6630b7ea268218b3e..c334f157d990972afef1bb12228bafa8e49b2916 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; @@ -105,11 +106,8 @@ private: camitk::Geometry* maleModel; camitk::Geometry* femaleModel; - 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 4371a993b9aac374d40032c92296f540a340a7be..b5c087d70735bdbe926ef7e9a39d61da3d82ebbf 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 fc4ca1ef144eb6cc5a08e06e7f1852333e3466f3..277c0c5f960c64a8ccef7f748cbbb16cd8777fb2 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 8cc958f535dfa5a8d445cc1c77701299444bb60c..80c5091d6179bdb79e4b62d2feb267fc03d18c0d 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 e70b8bee8c4591eb6dc43a6aa5cd632a94026756..c648c67755d71f17876e1102d57c3b139ac165fb 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 2f72b4891d2fcc6ef52d60fd3c9443f178f5a3a5..0d51ff5b44cda579d091f239460f0d4fe2d87727 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 9d7c26b06987fee8c8676d5068a2ba2b6e8df591..9cab56d46ec99e965fe9328ac7464dfa42034e84 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 972c90462d8401a3d4401fddea936f8f79ee1914..561088f1765e25037435cb6340c76d11864a9cd4 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 e83cd1a64f72c77445952fa0ceaac16ce34a4860..21df0ba57dfc687eea09ecf63290a8dc3f2034e0 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 773a4ce4b7cde679727a67e7e40dc3a2cceb9632..ee8baf5a115f8704a7ab73f99857f738a88b6050 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 09d3357f9054c85c4ae59ddaafa3c5734291c9b4..8156aee6d31027437229f71ea5940c704560cb06 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 6d4dedf1da5b28383df524e223bca9fc9b2ae70d..c041c3e5b4d0ffab443f0490ad91bd6ca26ee8b7 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 0009fdcb80679ac9ec4d21e56c8aa9cd2fb00317..a35029e6219447a89c9b2b75527e78f221db2d23 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 57a5b671e21c1dc9f99739a80bf43bbcecf150a8..dbceb697406dd5b2072dadd3d52e1c36b6e34016 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 9635bdf64ddad84354425b9b0707b9c89eea1729..3e6a6095bce0653488ac586f772ae0f8fd62a4aa 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,30 +46,24 @@ 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); - - /// returns the number of Component that are displayed by this viewer - virtual unsigned int numberOfViewedComponent() { - return 0; - }; + /// get the viewer widget. + virtual QWidget* getWidget(); /// 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 0000000000000000000000000000000000000000..19632d93f159f338ddec9c74dcd130fe5c55b3ba --- /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/tutorials/actions/bitmapviewer/ShowBitmapViewerExtension.h b/sdk/applications/actionstatemachine/ActionStateViewerExtension.h similarity index 58% rename from tutorials/actions/bitmapviewer/ShowBitmapViewerExtension.h rename to sdk/applications/actionstatemachine/ActionStateViewerExtension.h index 24800fd820796ee1cbcee1e463d8bfc2b87eb4cb..ce85ad031b18cd366f18f23f4c7258a838b9b370 100644 --- a/tutorials/actions/bitmapviewer/ShowBitmapViewerExtension.h +++ b/sdk/applications/actionstatemachine/ActionStateViewerExtension.h @@ -24,39 +24,38 @@ ****************************************************************************/ -#ifndef SHOW_BITMAP_VIEWER_EXTENSION_H -#define SHOW_BITMAP_VIEWER_EXTENSION_H +#ifndef ACTION_STATE_VIEWER_EXTENSION_H +#define ACTION_STATE_VIEWER_EXTENSION_H -#include -#include -#include +#include -/// shows the bitmap viewer in the central viewer -class ShowBitmapViewerExtension : public camitk::ActionExtension { +class ActionStateViewerExtension : public camitk::ViewerExtension { Q_OBJECT - Q_INTERFACES(camitk::ActionExtension) - Q_PLUGIN_METADATA(IID "fr.imag.camitk.tutorials.action.showbitmapviewer") + Q_INTERFACES(camitk::ViewerExtension); + Q_PLUGIN_METADATA(IID "fr.imag.camitk.actionstatemachine.viewer.actionstateviewerextension") public: - /// the constructor - ShowBitmapViewerExtension() : ActionExtension() {}; + /// Constructor + ActionStateViewerExtension() : ViewerExtension() {}; - /// the destructor - virtual ~ShowBitmapViewerExtension() = default; + /// Destructor + virtual ~ActionStateViewerExtension() = default; - /// initialize all the actions - virtual void init(); - - /// Method that return the action extension name + /// Method returning the action extension name virtual QString getName() { - return "Show Bitmap Viewer"; + return "Action State Viewer Extension"; }; - /// Method that return the action extension descrption + /// Method returning 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."; + return "This extension provides Action State Viewer"; }; + /// initialize all the actions + virtual void init(); + }; -#endif // SHOW_BITMAP_VIEWER_EXTENSION_H +#endif // ACTION_STATE_VIEWER_EXTENSION_H + + diff --git a/sdk/applications/actionstatemachine/ActionStateWidget.cpp b/sdk/applications/actionstatemachine/ActionStateWidget.cpp index 50f2155a504a8c42af0401e521907cd350235e31..aa8e03835f0f57ac7cb7a175f1d785f510808abc 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 f9f61b7d8d1493c0e62c9faf38a699178449faea..e6240caeaec1a4376eab2c375f4f57b5d54988b0 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 23268722d5dfe1355e74f257ea978da64bd862b2..8de42b800a2fc36326d1cc25f3a8418fd5555af4 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 bfca68fb00d66be36297d410c79a4d8845d47d87..83a88000d6832e05386fb38531bb253c4ab9d7b4 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 51941959f251f5f3f6f81570319f8f49cd3fb45c..9a5faa861b54b57023e9a78cb80c3b04aba243c6 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/config/testing/config-test.sh b/sdk/applications/config/testing/config-test.sh index e8de3869b7db3bae3a31e4d8ad31587ef904f850..4ec58e152a2d654f5483c431726f3aebd7e0b480 100644 --- a/sdk/applications/config/testing/config-test.sh +++ b/sdk/applications/config/testing/config-test.sh @@ -22,11 +22,13 @@ 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]=29 [4.1]=27 [4.0]=27 ) + 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]=13 ) # fill release date releaseDate=( [4.2]="not yet released, current development version" \ @@ -48,8 +50,10 @@ declareTestData() { declare -Ag extensionCount declare -Ag componentExtensionCount declare -Ag actionExtensionCount + declare -Ag viewerExtensionCount declare -Ag fileExtensionCount declare -Ag actionCount + declare -Ag viewerCount declare -Ag releaseDate } @@ -171,16 +175,22 @@ 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]} - ;; + ;; + "Number of Viewers") + echo ${viewerCount[$shortVersion]} + ;; esac } @@ -284,7 +294,9 @@ 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" +checkValue "Number of Viewers" exit $exitStatus diff --git a/sdk/applications/imp/CMakeLists.txt b/sdk/applications/imp/CMakeLists.txt index ee84d18b952a877cd10086b1f9210c2cd52dec57..8dc0fcb781f3e4f9bb578e0aef32460e9b770e77 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 b6d489f4048b4fb5f79571fc7fe4573e4d732a3c..8d646d4c3f42c3022acd132fd213169c7c15e713 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,14 +223,13 @@ void ImpMainWindow::initActions() { } -//************************************************************************** - +// ------------- initMenuBar ----------------- void ImpMainWindow::initMenuBar() { // -- file fileMenu = new QMenu(tr("&File")); fileMenu->addAction(fileOpen); - openDataDirectoryMenuBuilder(); + updateOpenDirectoryMenu(); fileMenu->addAction(fileClose); fileMenu->addAction(fileCloseAll); @@ -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,50 +472,65 @@ 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; + 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 = 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 + connect(viewerAction, &QAction::toggled, [ = ](bool) { + setCentralViewer(viewer); }); - Viewer* cViewer = (*it); + } + } + + 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 = viewMenu->addAction(cViewer->objectName()); + QAction* viewerAction = toggleCentralWidgetMenu->addAction(viewer->getName()); 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->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(cViewer); + setCentralViewer(viewer); }); } } // 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 ------------------------------- @@ -543,7 +560,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 ----------------- @@ -598,7 +615,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 aeabf143cc4ce4d0bd5f6edb272478e918d26eb0..caca9dbf56bfe3cfb1cccbb89e3268ef37d55d4d 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(); @@ -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 8da9c0a27e39f464b3ff6c679596949a5bbc53f7..975c94e4211ffa2767eb98381bc76235b7ea3537 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/CMakeLists.txt b/sdk/applications/wizard/CMakeLists.txt index 3aec6ed582ea0aeb196e2351d93978a0a1705f99..d4fa21b89a2ad41b9e174de2b3370769a8bb01ab 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/applications/wizard/WizardMainWindow.cpp b/sdk/applications/wizard/WizardMainWindow.cpp index 087b09980a7e97a14c1e200558c3e43d1006e7dd..1e30560c4b8a46629fab61fbf9d2bd692c78dbd0 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 fd81a7e60631df88182c224e3c83b814585e31bf..df2210accf917e59cdecb9642e9ded0fe2e0ff80 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 3c352bc11ee8e48373c92ad43c899417ea43d0ab..6eb70c249bf72da599811f078e0032af2ee1aa2a 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 fc2460bbd0c08650b84a19ee7a9d5d66536eb74e..51e6725a19e1f4808b01d2ce324fd238e21eed36 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/CamiTKApplication.cmake b/sdk/cmake/modules/macros/camitk/CamiTKApplication.cmake index 73c250abff577d62bcf745d9aa5f3e03d5db9289..774ef84e351cae11a3ad40ff4dd8c77e84bd115e 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 # @@ -475,9 +508,9 @@ 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}) + - ######################################################################### # # @@ -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 1273052d56583ad2ae3bc0ce4e1bb5c33e81256c..f946f7e7b88b136eb301332c1a7d3e5c7cff4dbe 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}/../..) @@ -360,32 +368,31 @@ 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() - # 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/cmake/modules/macros/camitk/CamiTKInstallAllHeaders.cmake b/sdk/cmake/modules/macros/camitk/CamiTKInstallAllHeaders.cmake index 3d3f8bd11b99afe1691c27ec4b22dddbdd2b4236..c99c52a7fc6f18ecc9c82da7e7b616ed2e5a9cff 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 cefb5aa233789d84d724931305ed380586df7a6e..6f7d76454d251cb88069601f04dd0329fe35c7a7 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 7bcf222c164915ca9134d5eab3882daa19207841..138538fd384a06b25ec18eec1260e2cffc523d1c 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 d337ccd203f7c295b29d7824a9cc17a601722728..42e57a72dbd4d63bffa7ab4e578478972f17777e 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 044e9d4c316189e2da6e0232bcfdf6c52b078e60..404f0af23ebd693a5e5f5556f018f719aa501000 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/components/msh/MshComponent.cpp b/sdk/components/msh/MshComponent.cpp index 6dbbf7eeb1ed551a9140649bee64237d3be6e637..266917ae59e57bb059d49769efeca019058131cd 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 a9a52fee4480bf7215a469d2209af6b764254445..0b4467955b6deb242fa8bc11d9d7c33b77288312 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 8c87b66376228540dea218dcfa4f6052b5f30372..76dba43cad845ffd2b0528fdddb3e4db7f3ab36b 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; @@ -42,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 ------------------- @@ -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/doc/groups.h b/sdk/doc/groups.h index c83402bffae449daf7cf02593ae839805e1027fe..692f5c1008844fea0d2e9c1fdc22af7b49d4022a 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 15cb304334b0c15abaa4e6a435edfa6e20a64b9a..8b9bfdfc941bdf05784150561fca7c0ec20dfaca 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 c0dc41fdc52bfab7c8e8c757f10d9fb5a2b81923..d2673e6613230936f8d93de8debe74ad859efcc6 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 1f88b1bbabb64dd722101a486cb8f2517ae2a9e1..f324454d3ae40e182b5ed1aa9f39963056a349b5 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 9bc1e48088e9b588126b363aec7149d441b614f3..28abef73aaf946911b1cfccc6cc93e57539ea14c 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/CMakeLists.txt b/sdk/libraries/core/CMakeLists.txt index 998afd67b4de9e2b35d4890d97c38d39cedcff20..a318dbadd81bb0968824f92852d7dc4fa4029e48 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 df65239042178c00c10082fd320c84e6c3b1be94..849b135dbfaff31f275acfb6774d976f594fd289 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; @@ -91,7 +92,13 @@ using ComponentList = QList; /// A set of Action using ActionSet = QSet; +/// A set of Viewer +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 5be7431f2f01b94a15c736358306ac02a7a3f4b1..5252a5ced3d19b1dcef40b683e16bc5a86d1d118 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 17f054c5a0ab87c3e074dac52f06978315f087a0..f2eb6265ef54ecd87ca0d4fa48fc02f1c66614d6 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.cpp b/sdk/libraries/core/ExtensionManager.cpp index f76067df2105f4a911601159217361eb06f69e17..36ca3cb30fc461194635de83887b4ab1a7ab193b 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/ExtensionManager.h b/sdk/libraries/core/ExtensionManager.h index f2893f23de87b384ebb2913c82c292ea5e668383..4dd3d29dfc800b9f56feaf8fff61dcbb8fff07ee 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/action/Action.cpp b/sdk/libraries/core/action/Action.cpp index a3a5bc4ead718a7b40cb8c7670f9d798f10332e2..c26f26163933d60461f5e2807da9adae8bf853f2 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 54d0b1492fb3d85c2301c5b98bf07b6013774fc7..1875c6d4c64e3fb51ce5f4fe70b4e853f7b6d82f 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 63fec35aff75c3e79af51a3008262127aa50329e..8c4adc64cf604568a8d81c05a75f5245cd76b554 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 1d8aa5cdf42bb50f590e61b855b0970a4e392889..4c576075840b89816e1d05aefd9d82a28f32eab8 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 f051c48040d835225a0c49d3af5078a8bf508362..c98ae1ce195c6ce04457d0a2464728c3fd8f3995 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 fc0bf12b5e9fb7b91357cf97e07fd590b47f6653..8c7847f11d38861805e8980a8b994b528e4eeb5b 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 ae70e8882ac5325d85449aa3fc9b470f428d3b3c..a58ae44cce06b382bb861cb3160698d48e101dc0 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 44faba92a5634bac0292db301833bd4b9ab05711..4cb36636eac33c2dc0c389373eaed00855326667 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,8 +106,15 @@ Component::~Component() { foreach (Property* prop, propertyMap.values()) { delete prop; } + propertyMap.clear(); + if (actionsMenu != nullptr) { + actionsMenu->clear(); + delete actionsMenu; + actionsMenu = nullptr; + } + CAMITK_TRACE(tr("Deleted")) } @@ -120,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(); @@ -151,12 +163,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; } @@ -251,19 +266,24 @@ 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); - } - else { - it.value() = b; + // 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; + } } } // -------------------- getVisibility -------------------- bool Component::getVisibility(Viewer* v) const { QMap::const_iterator it = myViewers.constFind(v); + if (it == myViewers.end()) { return false; } @@ -295,6 +315,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 +330,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 +358,7 @@ Component::Representation Component::getRepresentation() const { } } } + return myService; } @@ -348,12 +374,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 +391,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()); } @@ -373,12 +404,40 @@ 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; actionsMenu = nullptr; } } + + //-- 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; } @@ -401,9 +460,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 +483,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 +504,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 +536,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 +584,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 +604,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 +644,7 @@ void Component::deleteChildren() { delete childComp; } } + childrenComponent.clear(); } @@ -627,6 +699,7 @@ const QVector& Component::getChildrenFrame() const { CAMITK_ERROR(tr("myFrame is not instantiated.")) // error / undefined behaviour } + return myFrame->getChildrenFrame(); } @@ -636,6 +709,7 @@ const vtkSmartPointer Component::getTransformFromWorld() const { CAMITK_ERROR(tr("myFrame is not instantiated.")) return nullptr; } + return myFrame->getTransformFromWorld(); } @@ -645,6 +719,7 @@ const vtkSmartPointer Component::getTransform() const { CAMITK_ERROR(tr("myFrame is not instantiated.")) return nullptr; } + return myFrame->getTransform(); } @@ -654,6 +729,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/Component.h b/sdk/libraries/core/component/Component.h index 3f00bb84a80cd7e48f294f4b611197a255fc391d..f8fc9b4538696efab53c59bcd7e68299079bd414 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 5b837173cabf518e835499b02282f9f8cdc0ec3c..ef9c8a121846750ce5f482c1d5c497acc08413cc 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 3a0fb255b75d0f7d98285065975c48263ebc267b..ef5f38605ddd73fa556363521a51041307875e3f 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 112bf64af78ef86c1984341805e9429e31063257..25c9017fa9e7afaa6c2aee22c24227e3b8abe8cf 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,11 +32,10 @@ #include "ImageOrientationHelper.h" // -- Core stuff -#include "InteractiveViewer.h" -#include "PropertyExplorer.h" #include "MeshComponent.h" #include "Property.h" #include "Frame.h" +#include "Viewer.h" // -- vtk stuff #include @@ -86,6 +86,7 @@ ImageComponent::~ImageComponent() { if (model != nullptr) { delete model; } + if (selectionView != nullptr) { delete selectionView; } @@ -157,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(); @@ -201,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 -------------------- @@ -276,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); @@ -502,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); @@ -524,7 +545,7 @@ void ImageComponent::update3DViewer() { } if (volumeRenderingChild != nullptr) { - volumeRenderingChild->setVisibility(InteractiveViewer::get3DViewer(), viewIn3D); + volumeRenderingChild->setVisibility(Application::getViewer("3DViewer"), viewIn3D); } } @@ -789,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 3eb8050689637bbef2786dc495255cac438a1bab..a9e33aeaa5251f794c99d730c0f564d1acaa2e00 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/component/image/SingleImageComponent.cpp b/sdk/libraries/core/component/image/SingleImageComponent.cpp index 90e1c96389718a2e8eb76df0192e3aa972b5e986..7a551aaa6e5476c5d3f9e6383859528e3d758e36 100644 --- a/sdk/libraries/core/component/image/SingleImageComponent.cpp +++ b/sdk/libraries/core/component/image/SingleImageComponent.cpp @@ -28,10 +28,8 @@ #include "ImageComponent.h" // -- Core stuff -#include "InteractiveViewer.h" #include "Frame.h" - -#include "Log.h" +#include "Application.h" // -- VTK stuff #include @@ -80,7 +78,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 +92,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 9377deb09ad16436d462c116b684a5e57f25a74c..ba95661969beb8e8bc65adda045cc395f9055d68 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 261c0e6953e9181e6cc0a7348739b538e53db40d..e9dc330f738e31727713f0e5ae2e9fcc7ec7c1e3 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 70cadacb8bd236df1c7003d67f8ce678d71664b9..99bb85d8bd6cde4e2b4b945ff4552df8ce8837d9 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 57f89a0971853c45fb22d006e1901515f37ccbad..f20bd46b8c1d879c71be0d79b53d2208942e46ac 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/utils/Log.h b/sdk/libraries/core/utils/Log.h index 3d91607817d59923a73f7232537cbc6c2008e1a8..4e4a192084f8caf84904d0e50528f24661642613 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/libraries/core/viewer/InteractiveViewer.cpp b/sdk/libraries/core/viewer/InteractiveViewer.cpp index db5c825f62fca77a543cd7e2e88dfb3ec26ce645..1f4e60af133e0af14f36c2fb7b997c870542aae7 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; } @@ -496,11 +391,6 @@ QString InteractiveViewer::getName() const { return objectName(); } -// ---------------- numberOfViewedComponent ---------------- -unsigned int InteractiveViewer::numberOfViewedComponent() { - return actorMap.size(); -} - // ---------------------- refresh ---------------------------- void InteractiveViewer::refresh(Viewer* v) { @@ -513,6 +403,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 +417,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 +431,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 +455,7 @@ void InteractiveViewer::refresh(Viewer* v) { } } } + if (comp->getFrameVisibility(this)) { addActor(comp, comp->getFrameAxisActor()); } @@ -573,6 +467,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 +543,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 +569,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 +598,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 +676,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 +693,7 @@ QToolBar* InteractiveViewer::getToolBar() { viewerToolbar->addAction(scalarDataColorAction); } + /* if (myType == SLICE_VIEWER) { viewerToolBar->addAction(toggleOrientationDecorationsAction); } @@ -1086,6 +989,7 @@ void InteractiveViewer::keyPressEvent(QKeyEvent* e) { break; case Qt::Key_C: + // addWhatsThisItem("C", "Toggle color scale"); if (e->modifiers() == Qt::NoModifier) { @@ -1096,6 +1000,7 @@ void InteractiveViewer::keyPressEvent(QKeyEvent* e) { break; case Qt::Key_F: + // addWhatsThisItem("F", "Toggle backface culling"); if (e->modifiers() == Qt::NoModifier) { @@ -1105,6 +1010,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 +1029,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 +1047,7 @@ void InteractiveViewer::keyPressEvent(QKeyEvent* e) { break; case Qt::Key_P: + // addWhatsThisItem("Alt+P", "Toggle point rendering"); if (e->modifiers() == Qt::AltModifier) { @@ -1198,6 +1106,7 @@ void InteractiveViewer::keyPressEvent(QKeyEvent* e) { break; case Qt::Key_W: + // addWhatsThisItem("Alt+W", "Toggle wireframe rendering"); if (e->modifiers() == Qt::AltModifier) { @@ -1295,6 +1204,7 @@ void InteractiveViewer::keyPressEvent(QKeyEvent* e) { break; case Qt::Key_Plus: + // addWhatsThisItem("+", "Move slider a step above"); if (myType == SLICE_VIEWER) { @@ -1384,6 +1294,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 +1302,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 +1323,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 +1343,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 +1367,7 @@ void InteractiveViewer::keyPressEvent(QKeyEvent* e) { } } + debugStream << "=== (end of debug information) ===" << endl; CAMITK_INFO(tr("InteractiveViewer Debug Information: ").arg(debugString)) } @@ -1740,6 +1660,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 +1668,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 +1676,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 +1803,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 +2039,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 +2083,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 +2129,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 +2150,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 +2185,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 +2197,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 +2207,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 +2220,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 +2230,12 @@ void InteractiveViewer::picked() { } } break; + case NO_PICKING : default : break; } + isPicking = false; comp = nullptr; } @@ -2431,8 +2375,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 c13ff617d60482fe350619d8dc960bdba3b6d9e5..266623a31bf9814a922a25f87cf5eff44ded546d 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; @@ -208,14 +186,11 @@ 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; /// 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 +235,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 +266,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 +303,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 +320,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 +370,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 985c58272ecf7fa9a8389424ff92d3b0042b190f..5dd6da460ca69033fbffe3aa1b31598ee3f19c18 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 7e9a0908a8449fa7816b357b30be3cfe5eecbae9..6a394bcb71a262eaf0cd721f6bda6db437fdee60 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 6f8714df74603edd2efda0d13000f9720e3d8366..b6116969b7dfece2c7e46db35d7516eb33f6e213 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,74 @@ 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) { + // 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) { + embeddedLayout->addWidget(getWidget()); + // 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 d32c10f7555789438a7c0755521b5b305fdf73b9..260bfaa119d9c497417bde1d9aa715bbcc1a55bc 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,17 +73,44 @@ public: Viewer(QString name); /// default destructor - ~Viewer() override = default; + virtual ~Viewer() override; - /// returns the number of Component that are displayed by this viewer - virtual unsigned int numberOfViewedComponent() = 0; + /// \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 + void stackIn(QStackedWidget*); + + /// Add the viewer widget in the given layout + void embedIn(QLayout*); /// 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 +126,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 +154,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 +172,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 0000000000000000000000000000000000000000..a55435ff66c1ef33cd71c2c4a8b2a7cbf11c9eeb --- /dev/null +++ b/sdk/libraries/core/viewer/ViewerExtension.cpp @@ -0,0 +1,157 @@ +/***************************************************************************** +* $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())); + } + + 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 0000000000000000000000000000000000000000..e7b7c616477c4f6b55916dde9b94ae6bec6d7357 --- /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 ab47557c69735f3e57e8b3ad505818b76d162563..d3ff2ece64db72499bdb668dd83130f693fe0968 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 5b92c59749b3970d4435790f2765745506948848..e564b05d5fb22d02c21926f86944cdaeaedb0b4f 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 0000000000000000000000000000000000000000..6c796fb5431b97bb12af50bdd64845cb1a3d925a --- /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 35df1bb4fde73d227b485cc7a2870daf8872096a..8e800ce50368e3a8e24dc671118056a67db3abd1 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 79% rename from sdk/libraries/core/viewer/ActionViewer.h rename to sdk/viewers/actionviewer/ActionViewer.h index 24f42d47a0887f9c2853e8871ca55c83547fc95a..e8c640b02c684e83aa078661aff6bda6fb8a7cc3 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,36 +63,22 @@ 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 //@{ - /// 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) - void refresh(Viewer* whoIsAsking = nullptr) override; + virtual 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 + virtual QWidget* getWidget() override; //@} - /// @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 +95,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 +113,7 @@ private: QComboBox* nameComboBox; /// Current action - Action* action; + camitk::Action* action; /// action tags line edit QLineEdit* tagLineEdit; @@ -136,11 +128,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 0000000000000000000000000000000000000000..392290011d4401bbd00b75df768b66b2aa4cdb31 --- /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 0000000000000000000000000000000000000000..f3ca8f37d2d552062efdc22dfb4d93b46490cb64 --- /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 0000000000000000000000000000000000000000..c8561c9c8352e94653d48b1b0272717e2ea2ea9e --- /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 0000000000000000000000000000000000000000..5e9869de4ae3352d772c6b9ddca077565cc67205 --- /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 81% rename from tutorials/actions/bitmapviewer/BitmapViewer.cpp rename to sdk/viewers/bitmap/BitmapViewer.cpp index 0000490ce94f7acaa63a8befce1bb07eb0e7cd5c..8b9badbea533f4498d38f528aabbf663cdb759ab 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,9 @@ BitmapViewer::BitmapViewer() : InteractiveViewer(BitmapViewerName, InteractiveVi // parallel projection getRendererWidget()->getActiveCamera()->ParallelProjectionOn(); + // can only display 2D bitmap = SingleImageComponent + setComponents(QStringList() << "SingleImageComponent"); + myToolbar = nullptr; } @@ -74,8 +63,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(); @@ -97,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) { - Application::getMainWindow()->setCentralViewer(MedicalImageViewer::getInstance()); + connect(hideViewerAction, &QAction::triggered, [ = ](bool) { + Application::getMainWindow()->setCentralViewer(Application::getViewer("MedicalImageViewer")); }); } + return myToolbar; } @@ -111,7 +101,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 b7cb7a59acce80b907c377f625f6010030ccbd2f..33f67971a24e87cf20aaabb387ef6d0e37f59603 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 0000000000000000000000000000000000000000..7f7859e047a02698369a321b3bc6ea4b905903b0 --- /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 0000000000000000000000000000000000000000..01a3369affc004dddc70dce52e6e08b586ef5262 --- /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 0000000000000000000000000000000000000000..7f2bfd3e9ef9702927edea157ec0956addef8604 --- /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 0000000000000000000000000000000000000000..58c4805abae5afe775ad7cff6a15e8f5f6d7e858 --- /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 0000000000000000000000000000000000000000..2bcb223c92cba69b21f54743b1887d6dcf04e594 --- /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 94% rename from sdk/libraries/core/viewer/Explorer.cpp rename to sdk/viewers/explorer/Explorer.cpp index 2a3e8c739dc14a1f758ab3661591994122ee790c..d13c7c540bb32087afd76699d0e652406f58bf4c 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 @@ -124,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... @@ -409,6 +395,3 @@ void Explorer::renameItem() { } } - -} - diff --git a/sdk/libraries/core/viewer/Explorer.h b/sdk/viewers/explorer/Explorer.h similarity index 81% rename from sdk/libraries/core/viewer/Explorer.h rename to sdk/viewers/explorer/Explorer.h index fcb73c34ec92f05cb26d3f30122626c2bdccec60..df34fa092291309e0e045d50435cb48f70a38722 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,26 +65,19 @@ public: */ ///@{ /** Construtor */ - Explorer(); + Q_INVOKABLE Explorer(QString); /** Destructor */ ~Explorer() override; - /// returns the unique instance of ActionViewer - static Explorer* 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) - 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 +92,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 +116,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 +144,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 +161,4 @@ private: ///@} }; -} - - #endif diff --git a/sdk/viewers/explorer/ExplorerAPI.h b/sdk/viewers/explorer/ExplorerAPI.h new file mode 100644 index 0000000000000000000000000000000000000000..b8ead55cfe4b0fa14fa6e9e443cb34633ad9b6c0 --- /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/tutorials/actions/bitmapviewer/ShowBitmapViewer.h b/sdk/viewers/explorer/ExplorerExtension.cpp similarity index 61% rename from tutorials/actions/bitmapviewer/ShowBitmapViewer.h rename to sdk/viewers/explorer/ExplorerExtension.cpp index fc56562e4afc031ce027c4d3303c2da848702723..53d8105853041c1bf23632889343a37fe2c69bb6 100644 --- a/tutorials/actions/bitmapviewer/ShowBitmapViewer.h +++ b/sdk/viewers/explorer/ExplorerExtension.cpp @@ -23,36 +23,20 @@ * $CAMITK_LICENCE_END$ ****************************************************************************/ -#ifndef SHOW_BITMAP_VIEWER_H -#define SHOW_BITMAP_VIEWER_H -#include +#include "ExplorerExtension.h" -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; +// include generated actions headers +#include "Explorer.h" - /// 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(); +// --------------- constructor ------------------- +ExplorerExtension::ExplorerExtension() : ViewerExtension() { + // initialize the icon resources + Q_INIT_RESOURCE(ExplorerExtensionIcons); +} - bool firstCall; -}; +// --------------- getViewers ------------------- +void ExplorerExtension::init() { + registerDefaultViewer(Explorer); +} -#endif // SHOW_BITMAP_VIEWER_H diff --git a/sdk/viewers/explorer/ExplorerExtension.h b/sdk/viewers/explorer/ExplorerExtension.h new file mode 100644 index 0000000000000000000000000000000000000000..175837ba7b70a05cc979fd835669fef411d783f6 --- /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 0000000000000000000000000000000000000000..926bcbe0f8ea754ed97c0f5a1c991b006583280c --- /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 Binary files /dev/null and b/sdk/viewers/explorer/resources/folder-orange.png differ diff --git a/sdk/viewers/frameexplorer/CMakeLists.txt b/sdk/viewers/frameexplorer/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..bf48a08a63070a8d465fed454718117150c18a48 --- /dev/null +++ b/sdk/viewers/frameexplorer/CMakeLists.txt @@ -0,0 +1,8 @@ +# Call CamiTK CMake Macro to define the action +camitk_extension(VIEWER_EXTENSION + CEP_NAME SDK + DEFINES COMPILE_FRAMEEXPLORER_API + DESCRIPTION "An extension for the viewer that display GUI action" + INSTALL_ALL_HEADERS +) + diff --git a/sdk/libraries/core/viewer/FrameExplorer.cpp b/sdk/viewers/frameexplorer/FrameExplorer.cpp similarity index 88% rename from sdk/libraries/core/viewer/FrameExplorer.cpp rename to sdk/viewers/frameexplorer/FrameExplorer.cpp index 7548555db82de3f8f871108ed5d040a02a090c7d..62c68bbe68b70c3ba0258d3f1f222dffddf9f186 100644 --- a/sdk/libraries/core/viewer/FrameExplorer.cpp +++ b/sdk/viewers/frameexplorer/FrameExplorer.cpp @@ -23,36 +23,28 @@ * $CAMITK_LICENCE_END$ ****************************************************************************/ -//-- camiTK stuff #include "FrameExplorer.h" -#include "Component.h" -#include "Application.h" + +//-- CamiTK stuff +#include +#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 @@ -79,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... @@ -175,6 +162,3 @@ void FrameExplorer::selectionChanged() { // refresh! refresh(this); } - -} - diff --git a/sdk/libraries/core/viewer/FrameExplorer.h b/sdk/viewers/frameexplorer/FrameExplorer.h similarity index 62% rename from sdk/libraries/core/viewer/FrameExplorer.h rename to sdk/viewers/frameexplorer/FrameExplorer.h index 48b9154f506e31d07ec7ac069ca92872476c6ce8..03257b8021ec089a47f1d57b036255dda20b9bbd 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,23 @@ 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 +84,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 +104,4 @@ private: }; -} - - #endif diff --git a/sdk/viewers/frameexplorer/FrameExplorerAPI.h b/sdk/viewers/frameexplorer/FrameExplorerAPI.h new file mode 100644 index 0000000000000000000000000000000000000000..1c53bd304aa9c2a4b11e804f9d87d70554beb900 --- /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 0000000000000000000000000000000000000000..6865b7aa386ae47bb897e393202a0fc1f34a3085 --- /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 0000000000000000000000000000000000000000..b66ea917137e37d10bab49ff865d9ac4f29f1d55 --- /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 0000000000000000000000000000000000000000..79072986807227ebe293b7020bb4d6a161177b94 --- /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 0000000000000000000000000000000000000000..d3770aedc4fcfc6150d049b0e27f7275f1f6d6d2 --- /dev/null +++ b/sdk/viewers/interactivegeometryviewer/InteractiveGeometryViewer.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 "InteractiveGeometryViewer.h" + +using namespace camitk; + +// -------------------- Constructor -------------------- +InteractiveGeometryViewer::InteractiveGeometryViewer(QString name) : InteractiveViewer(name, InteractiveViewer::GEOMETRY_VIEWER) { + if (name == "3DViewer") { + // the default 3D Viewer is embedded + setLayout(Viewer::EMBEDDED); + } +} diff --git a/sdk/viewers/interactivegeometryviewer/InteractiveGeometryViewer.h b/sdk/viewers/interactivegeometryviewer/InteractiveGeometryViewer.h new file mode 100644 index 0000000000000000000000000000000000000000..0f434b71b93329224fce375192dda0efaf93aeda --- /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 0000000000000000000000000000000000000000..dfbfe45039b1a3c223af6a572cdf989a42aa0ac2 --- /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 0000000000000000000000000000000000000000..5b295e4955f4d9364acf635ba23232cd809b9dd2 --- /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 0000000000000000000000000000000000000000..b189ace789b32db03df8090a107a8fd49ac1b80b --- /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 0000000000000000000000000000000000000000..39328f7aed940a0968f0acc26a4611360a72ee7c --- /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 0000000000000000000000000000000000000000..d0ed035dafbb8b6f6efd9d5152f1bf71ab354a01 --- /dev/null +++ b/sdk/viewers/interactivesliceviewer/InteractiveSliceViewer.cpp @@ -0,0 +1,79 @@ +/***************************************************************************** + * $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 "InteractiveSliceViewer.h" + +#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); + 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 0000000000000000000000000000000000000000..bf0a5625e8adeca10d0fbac4d07a4d90b46c6307 --- /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 0000000000000000000000000000000000000000..55ac68ab5139f84b7fedf329439bc55a9814e043 --- /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 0000000000000000000000000000000000000000..a750eb01a4fa08c282974c10d0c3f86b3830c836 --- /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 0000000000000000000000000000000000000000..f08f5667e1010199ae723a6dc69d4ca737d613c7 --- /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 0000000000000000000000000000000000000000..eb96dc84ea6075a623a6e515aca7282564a15896 --- /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 70% rename from sdk/libraries/core/viewer/MedicalImageViewer.cpp rename to sdk/viewers/medicalimageviewer/MedicalImageViewer.cpp index 466a3280fc4bfb323438764d7ce11df188544aed..287a702f6a3a5479d2ea1b9590794b9cdb498791 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,26 +51,15 @@ MedicalImageViewer::MedicalImageViewer() : Viewer("Medical Image Viewer") { displayedTopLevelComponents = 0; autoUpdateToolbarVisibility = true; + } // -------------------- Destructor -------------------- MedicalImageViewer::~MedicalImageViewer() { - if (frame) { - delete frame; - } -} - - -// -------------------- 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 -------------------- @@ -91,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 (InteractiveViewer::getAxialViewer()->numberOfViewedComponent() > 0 - && InteractiveViewer::getCoronalViewer()->numberOfViewedComponent() > 0 - && InteractiveViewer::getSagittalViewer()->numberOfViewedComponent() > 0) { + // Check if there is ImageComponent, if yes show all viewers + int i = 0; + while (iisInstanceOf("ImageComponent")) { + i++; + } + if (isetObjectName("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); @@ -129,19 +106,26 @@ 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_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 + 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) { @@ -154,12 +138,19 @@ QWidget* MedicalImageViewer::getWidget(QWidget* parent) { 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; } // ---------------------- getPropertyObject ---------------------------- QObject* MedicalImageViewer::getPropertyObject() { - return InteractiveViewer::get3DViewer()->getPropertyObject(); + return Application::getViewer("3DViewer")->getPropertyObject(); } // -------------------- getMenu -------------------- @@ -211,7 +202,7 @@ void MedicalImageViewer::setVisibleViewer(LayoutVisibility visibleViewer) { updateLayout(); } -// -------------------- setVisibleViewer -------------------- +// -------------------- getVisibleViewer -------------------- MedicalImageViewer::LayoutVisibility MedicalImageViewer::getVisibleViewer() const { return visibleLayout; } @@ -224,18 +215,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 +260,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 84% rename from sdk/libraries/core/viewer/MedicalImageViewer.h rename to sdk/viewers/medicalimageviewer/MedicalImageViewer.h index 71c540bc325c5b1c8d55803fa3d44e22b1c146e5..bbc300847f20a13dbe0f13d14f4c97a174e1279c 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; @@ -80,14 +76,11 @@ public: /** @name Viewer inherited */ /// @{ - /// returns the number of Component that are displayed by this viewer - unsigned int numberOfViewedComponent() override; - /// 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 +111,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 +118,12 @@ private: /// The main layout QGridLayout* frameLayout; - /// the layout for the arbitrary/axial at the top left position of frameLayout - QVBoxLayout* topLeftLayout; - + /// The four corners of the main layout + QVBoxLayout* northWestLayout; + QVBoxLayout* southWestLayout; + QVBoxLayout* northEastLayout; + QVBoxLayout* southEastLayout; + /// the main widget QFrame* frame; @@ -151,15 +142,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 0000000000000000000000000000000000000000..04f23d26d7f6f66f581b3da4b01b1000836f4d0d --- /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 0000000000000000000000000000000000000000..2be66e4511780ba5b032c45c2c125616624bb406 --- /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 0000000000000000000000000000000000000000..5cb0a9e55b8ed93ff8dc64661e0d10bb2b5f49c9 --- /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 0000000000000000000000000000000000000000..144235566f394a7afb8829420c5623b0de3d583f --- /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 87% rename from sdk/libraries/core/viewer/PropertyExplorer.cpp rename to sdk/viewers/propertyexplorer/PropertyExplorer.cpp index fa27382a25f44ca7922680cacdd3a2bbcb904248..0b5f14a758f09e4b1ba21bb7b37dd44e32595b85 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,32 +53,9 @@ 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(); - } - - return propExplorer; -} - -// ---------------- numberOfViewedComponent ---------------- -unsigned int PropertyExplorer::numberOfViewedComponent() { - if (currentComponent) { - return 1; - } - else { - return 0; + if (propertyObject != nullptr) { + delete propertyObject; // this will also delete viewModeProperty } } @@ -93,13 +72,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 +106,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 +128,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 +167,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 +185,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 +259,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 87% rename from sdk/libraries/core/viewer/PropertyExplorer.h rename to sdk/viewers/propertyexplorer/PropertyExplorer.h index 2d7f3ad67ed0bb6eaeba59cc641f18dee2269ca6..195e8080080afee86c159e6267416d0a3814439d 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,26 +89,19 @@ 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 */ ///@{ - /// returns the number of Component that are displayed by this viewer - 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 +126,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 +141,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 +180,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 0000000000000000000000000000000000000000..dfbce44103a4d2ab45df46ac8f6d3a2e21558690 --- /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 0000000000000000000000000000000000000000..bed2a8ca3d1fef23ac5004c24048a031e111a3f0 --- /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 0000000000000000000000000000000000000000..8cead860c30adae7abd2864a7ec68cc2664a8fa4 --- /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/CMakeLists.txt b/tutorials/actions/CMakeLists.txt index 91cf4b550f3d75d2cef653726000ac5a3c740ff9..dbdc33b5ac7403bd370e9bf762d5a26482dd6b8e 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/actions/basicpicking/ImagePicking.cpp b/tutorials/actions/basicpicking/ImagePicking.cpp index 78cffce7cb639700e0d317249799526546daba6a..75d558bf1cf99e18855a873ac596300b87870c19 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/CMakeLists.txt b/tutorials/actions/bitmapviewer/CMakeLists.txt deleted file mode 100644 index 9cc3535dcf7afae05c4b361e09cf6302b159b3d9..0000000000000000000000000000000000000000 --- 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 9d92d29cba8b2c8647c46a086269eecc3cdda3a4..0000000000000000000000000000000000000000 --- 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(BitmapViewer::getInstance()); - 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/meshpointdata/CMakeLists.txt b/tutorials/actions/meshpointdata/CMakeLists.txt index 474cc940cb61deb059fe72d565ee9ee575eb12db..5b32c7ad0f1b2c0f2160bbccd31ed00a0cdecff2 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/sleepingwhileworking/CMakeLists.txt b/tutorials/actions/sleepingwhileworking/CMakeLists.txt index ee4a067f79f5d981e155bfc099bbb8c623216eb9..d2b142d4d8eb5ea04dd1ed42c8572b25a8813a62 100644 --- a/tutorials/actions/sleepingwhileworking/CMakeLists.txt +++ b/tutorials/actions/sleepingwhileworking/CMakeLists.txt @@ -1,5 +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 +# 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/actions/sleepingwhileworking/WorkingWhenSleepingLinear.cpp b/tutorials/actions/sleepingwhileworking/WorkingWhenSleepingLinear.cpp index 1859ec9a6b214e7337ef032fb27f3bb0777dc136..57077dee00ba7514c5985c20b495125616114a31 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 e44c33f55e03f5c025dca2300014f5492101a00b..b4ce003c5103e3df94c49b6cae141353fe7890b6 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 e52703e6720a408c603682ec4ab9572092c1ac0b..2fe5156b0bd2f1c20fd2289ffa439ac0bc217db1 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 836c31acd19a9cb3bd008ac866cc3e0f21cd6eb3..9874b77d9910505f59d75ba8caef9ea185369b00 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 01abf83c66654ccac4f6b8cb69975e66087f0a0a..6fe2056a4c4ea5b0a0eeb5b6dd194dfe40cf2e66 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 d209cae3e76c4add2f401e173060c2703ec90543..6333cb1c5658b150b91e36721708ee01ed444d96 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 306ee0ba9b897d0e094a03a6b5cfea57aeecf73a..edcaad46edfdb769ed0cd844119a72315bd3c2ac 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 4e47bc1e4f41f873c58b665227dff8a35d1e1602..73711e87b1b57ae3be576958a5b75db9198d77e3 100644 --- a/tutorials/applications/fancy/FancyMainWindow.cpp +++ b/tutorials/applications/fancy/FancyMainWindow.cpp @@ -28,9 +28,10 @@ #include "FancyMainWindow.h" #include -#include +#include #include #include +#include // -- Qt stuff #include @@ -39,6 +40,8 @@ #include #include +using namespace camitk; + // ------------- constructor ----------------- FancyMainWindow::FancyMainWindow() : MainWindow("Fancy") { mainWidget = new QWidget; @@ -51,24 +54,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()); @@ -79,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(); @@ -99,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(); } @@ -116,14 +139,19 @@ 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(); + } // -------------------- updateDialSlider -------------------- @@ -131,31 +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 = NULL; - - 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; + } } @@ -184,51 +215,89 @@ 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; + 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); + 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) { - InteractiveViewer::getArbitraryViewer()->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) { - InteractiveViewer::getArbitraryViewer()->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 -------------------- @@ -236,19 +305,22 @@ void FancyMainWindow::refresh() { getVisibleViewer()->refresh(); // force visualization of arbitrary slice in 3D - if (Application::getTopLevelComponents().size() > 0) { - ImageComponent* comp = dynamic_cast(Application::getTopLevelComponents().last()); - - if (comp != nullptr && comp->getAxialSlices() != nullptr) { + // 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 (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); } } @@ -258,21 +330,26 @@ void FancyMainWindow::refresh() { } // -------------------- getVisibleViewer -------------------- -InteractiveViewer* FancyMainWindow::getVisibleViewer() { - InteractiveViewer* visibleViewer = NULL; +InteractiveSliceViewer* FancyMainWindow::getVisibleViewer() { + InteractiveSliceViewer* visibleViewer = nullptr; + 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 eec0f5d32564e5470820361b70f1b774484f6283..875b667b3020a6f0511dd1a4d9a523e27e23b28a 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,18 @@ // -- Core stuff #include -#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: @@ -55,7 +52,7 @@ public: /// destructor ~FancyMainWindow(); - + public slots: /// inherited from QWidget, just to refresh all viewers @@ -94,10 +91,16 @@ private: QWidget* mainWidget; /// get the currently visible viewer (axial, sagittal, coronal or arbitrary) - InteractiveViewer* getVisibleViewer(); + InteractiveSliceViewer* getVisibleViewer(); + + /// update the comp + void updateComponent(); /// specific 3D viewer for fancy - InteractiveViewer* viewer3D; + InteractiveGeometryViewer* viewer3D; + + /// current visible component + camitk::ImageComponent* comp; }; #endif // FANCYAPP_H diff --git a/tutorials/applications/menubar/MyAppMainWindow.cpp b/tutorials/applications/menubar/MyAppMainWindow.cpp index 7e00baa9be1ad00779547f582470f8e1dd71bf80..1062832fa0d62211623c3a057993818f49c40642 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 @@ -37,6 +36,8 @@ // -- Qt Stuff #include +using namespace camitk; + // ------------- constructor ----------------- MyAppMainWindow::MyAppMainWindow() : MainWindow("MyApp - " + tr(Core::version)) { @@ -69,8 +70,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/menubar/MyAppMainWindow.h b/tutorials/applications/menubar/MyAppMainWindow.h index 0334d988bbfbc9e30c449d599cfba78d7ce20e69..4f5e87adbbb856ddc7cf916994a4a239b4d96b18 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. @@ -41,7 +40,7 @@ using namespace camitk; * 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: diff --git a/tutorials/applications/simple/SimpleMainWindow.cpp b/tutorials/applications/simple/SimpleMainWindow.cpp index 64b3df8d73fc57918bb7242f50b39bb243d1eca0..6f12934e9f2ef22d0be66086107251e9b44dbe63 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 a604d4d004a60e12857b6733910d49ee9f649d1a..7979ed0731c1aadb06ccedb25b1fb08ec1d9265c 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/testlogger/log-default-linux.log b/tutorials/applications/testlogger/log-default-linux.log index 4d609493456159ee5d7347070022badc4ad08d41..843246727245c60e848f10c5f6b990beb2746a42 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 8b58414014119b0631c488ddeb0228acae4ffebe..350215d46c4ae0e3007342a89f03ce74416ed8b0 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: diff --git a/tutorials/applications/textviewer/CMakeLists.txt b/tutorials/applications/textviewer/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..63d671caa7612e9a6c1b14482ee2d596ad72fcb8 --- /dev/null +++ b/tutorials/applications/textviewer/CMakeLists.txt @@ -0,0 +1,3 @@ +camitk_application( + NEEDS_VIEWER_EXTENSION textviewer +) diff --git a/tutorials/viewers/main.cpp b/tutorials/applications/textviewer/main.cpp similarity index 88% rename from tutorials/viewers/main.cpp rename to tutorials/applications/textviewer/main.cpp index a6bc35d14b3c8d4039f4a27da44783b9eae349b8..6dde8ce4573f906a24f37d530d3379a7911537d4 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 - auto* myViewer = new MyViewer(); + // 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/components/CMakeLists.txt b/tutorials/components/CMakeLists.txt index fe490f3f028800451a4f3b24876ec13f63b6ce8b..cfe910073a5b02cfb1e96776903f9c924c6467be 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/components/mixed/MixedComponent.cpp b/tutorials/components/mixed/MixedComponent.cpp index 465bedf59d88bbc48a889a1204c963a43d08000b..1d462f6f76d32683be6e819f254d934bb7bc4f06 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/CMakeLists.txt b/tutorials/viewers/CMakeLists.txt index 221b8c39f684756716623661cac82211e53e4f16..696df4d31b9d376b6ea889783b3aa18bd56e6db2 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 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 + +# 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/mixedviewer/CMakeLists.txt b/tutorials/viewers/mixedviewer/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..69498ee5843419b2b871c75ca70bad5a77664571 --- /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 0000000000000000000000000000000000000000..8d786d39c1d022a7f717645fc94398fc60605c9c --- /dev/null +++ b/tutorials/viewers/mixedviewer/MixedViewer.cpp @@ -0,0 +1,75 @@ +/***************************************************************************** + * $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; +} + +// -------------------- 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 0000000000000000000000000000000000000000..1d0263959c8820d50d844c5e7f06e736b342655f --- /dev/null +++ b/tutorials/viewers/mixedviewer/MixedViewer.h @@ -0,0 +1,88 @@ +/***************************************************************************** + * $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. + * + * 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 + +public: + + /** @name Constructors/Destructors + */ + /// @{ + /** construtor. */ + Q_INVOKABLE MixedViewer(QString name); + + /** destructor */ + virtual ~MixedViewer(); + /// @} + + /** @name Viewer inherited + */ + /// @{ + /// 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 panels inside 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 0000000000000000000000000000000000000000..e2b068531005076d5a613c781e4a1b4afd3b4234 --- /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 0000000000000000000000000000000000000000..f077a7ef9c1d02b74f03b04213e49461cc8033f3 --- /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 0000000000000000000000000000000000000000..2dad138361b55977aadd034dae947f128bf16c2d --- /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 + + diff --git a/tutorials/viewers/textviewer/CMakeLists.txt b/tutorials/viewers/textviewer/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..c47130cca2960736dcd26feadbb22f14e5ef66a0 --- /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 83% rename from tutorials/viewers/MyViewer.cpp rename to tutorials/viewers/textviewer/TextViewer.cpp index 38b87309fd9527da7bbcca5fb47b983155d66414..16b1006b5a22458bc30384c8d3e0956b6819734b 100644 --- a/tutorials/viewers/MyViewer.cpp +++ b/tutorials/viewers/textviewer/TextViewer.cpp @@ -23,42 +23,35 @@ * $CAMITK_LICENCE_END$ ****************************************************************************/ -#include "MyViewer.h" +#include "TextViewer.h" // -- Core stuff #include #include +#include //-- Qt stuff #include #include +#include +using namespace camitk; // -------------------- Constructor -------------------- -MyViewer::MyViewer() : Viewer("My Simple Viewer") { +TextViewer::TextViewer(QString name) : Viewer(name) { inverse = nullptr; myMenu = nullptr; myWidget = nullptr; displayedTopLevelComponents = 0; } - // -------------------- Destructor -------------------- -MyViewer::~MyViewer() { +TextViewer::~TextViewer() { delete myWidget; - myWidget = nullptr; - delete myMenu; - myMenu = nullptr; -} - - -// -------------------- numberOfViewedComponentgetWidget -------------------- -unsigned int MyViewer::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, @@ -74,16 +67,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); @@ -97,13 +90,13 @@ QWidget* MyViewer::getWidget(QWidget* parent) { } // ---------------------- 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()); @@ -120,7 +113,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()); @@ -136,7 +129,7 @@ void MyViewer::inverseColors(bool state) { } // -------------------- updateColors -------------------- -void MyViewer::updateColors() { +void TextViewer::updateColors() { output->setTextColor(textColor); output->setTextBackgroundColor(bgColor); output->append("Colors updated"); @@ -144,29 +137,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 85% rename from tutorials/viewers/MyViewer.h rename to tutorials/viewers/textviewer/TextViewer.h index aaffcc1b5e111a03dfca32e9ce3d1fe74e4719d0..273985dde3667918f3c2c893300d51075d279de3 100644 --- a/tutorials/viewers/MyViewer.h +++ b/tutorials/viewers/textviewer/TextViewer.h @@ -24,25 +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 @@ -57,23 +59,20 @@ public: */ /// @{ /** construtor. */ - MyViewer(); + Q_INVOKABLE TextViewer(QString name); /** destructor */ - virtual ~MyViewer(); + virtual ~TextViewer(); /// @} /** @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); - /// 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(); @@ -118,12 +117,11 @@ private: /// colors QColor textColor; QColor bgColor; + + /// color management void updateColors(); }; - - - -#endif +#endif // TEXT_VIEWER_H diff --git a/tutorials/viewers/textviewer/TextViewerAPI.h b/tutorials/viewers/textviewer/TextViewerAPI.h new file mode 100644 index 0000000000000000000000000000000000000000..fe5bef84e2a35f24b955c9c0d7fb896a80298c05 --- /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/actions/bitmapviewer/ShowBitmapViewerExtension.cpp b/tutorials/viewers/textviewer/TextViewerExtension.cpp similarity index 82% rename from tutorials/actions/bitmapviewer/ShowBitmapViewerExtension.cpp rename to tutorials/viewers/textviewer/TextViewerExtension.cpp index ec10627b34786a3568a663fabdc22b7ef442bc8d..52d8dd52ca4037b623f0bf9d32d9ac387195104d 100644 --- a/tutorials/actions/bitmapviewer/ShowBitmapViewerExtension.cpp +++ b/tutorials/viewers/textviewer/TextViewerExtension.cpp @@ -22,11 +22,15 @@ * * $CAMITK_LICENCE_END$ ****************************************************************************/ -#include "ShowBitmapViewerExtension.h" -#include "ShowBitmapViewer.h" -// -------------------- init -------------------- -void ShowBitmapViewerExtension::init() { - registerNewAction(ShowBitmapViewer); + +#include "TextViewerExtension.h" + +// include generated actions headers +#include "TextViewer.h" + +// --------------- getActions ------------------- +void TextViewerExtension::init() { + registerDefaultViewer(TextViewer); } diff --git a/tutorials/viewers/textviewer/TextViewerExtension.h b/tutorials/viewers/textviewer/TextViewerExtension.h new file mode 100644 index 0000000000000000000000000000000000000000..8b613f40b9c6f000e714396e37d83ca3060d9358 --- /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 + +