Commit aa092313 authored by Emmanuel Promayon's avatar Emmanuel Promayon

Merge branch 'develop' into 'bug/arbitrary-slice'

FIXED merge conflicts resulting from last Slice class source code simplification/bug fix
# Conflicts:
#   sdk/libraries/core/component/InterfaceBitMap.h
#   sdk/libraries/core/component/Slice.cpp
#   sdk/libraries/core/component/Slice.h
parents 1cc978f2 8c0413db
/***************************************************************************** /*****************************************************************************
* $CAMITK_LICENCE_BEGIN$ * $CAMITK_LICENCE_BEGIN$
* *
* CamiTK - Computer Assisted Medical Intervention ToolKit * CamiTK - Computer Assisted Medical Intervention ToolKit
...@@ -59,6 +59,10 @@ DicomDialog::DicomDialog(QList<DicomDialogEntry*> elements): QDialog() { ...@@ -59,6 +59,10 @@ DicomDialog::DicomDialog(QList<DicomDialogEntry*> elements): QDialog() {
ui.tableWidget->setItem(row, column++, new QTableWidgetItem(item->getSeriesName())); ui.tableWidget->setItem(row, column++, new QTableWidgetItem(item->getSeriesName()));
row++; row++;
} }
// To get checkbox checked if there is only one study in list
if (elements.size() == 1) {
ui.tableWidget->itemAt(0, 0)->setCheckState(Qt::Checked);
}
ui.tableWidget->resizeColumnsToContents(); ui.tableWidget->resizeColumnsToContents();
......
...@@ -57,7 +57,16 @@ QWidget* QuitAction::getWidget() { ...@@ -57,7 +57,16 @@ QWidget* QuitAction::getWidget() {
// --------------- apply ------------------- // --------------- apply -------------------
Action::ApplyStatus QuitAction::apply() { Action::ApplyStatus QuitAction::apply() {
Application::getMainWindow()->close(); // close all components (and therefore ask the user to savet the modified ones)
return SUCCESS; ApplyStatus closeAllStatus = Application::getAction("Close All")->apply();
if (closeAllStatus == SUCCESS) {
// Quit the app (will call Application::quitting() and therefore unload all action extensions and delete all actions)
Application::quit();
return SUCCESS;
}
else {
// or abort the operation
return ABORTED;
}
} }
...@@ -25,14 +25,8 @@ ...@@ -25,14 +25,8 @@
#include "SaveAllAction.h" #include "SaveAllAction.h"
#include <Application.h> #include <Application.h>
#include <ImageComponent.h>
#include <ImageComponentExtension.h>
#include <MeshComponent.h>
#include <MeshComponentExtension.h>
#include <Log.h> #include <Log.h>
#include <QFileDialog>
using namespace camitk; using namespace camitk;
......
...@@ -36,11 +36,11 @@ using namespace camitk; ...@@ -36,11 +36,11 @@ using namespace camitk;
// --------------- constructor ------------------- // --------------- constructor -------------------
ImageLutAction::ImageLutAction(ActionExtension* extension) : Action(extension) { ImageLutAction::ImageLutAction(ActionExtension* extension) : Action(extension) {
setName("Lut"); setName("Image Look Up Table");
setDescription("Modify the LUT of an image components"); setDescription("Modify the LUT of an image components");
setComponent("ImageComponent"); setComponent("ImageComponent");
setFamily("ImageLut"); setFamily("Image LUT");
addTag("Lut"); addTag("LUT");
} }
// --------------- getWidget ------------------- // --------------- getWidget -------------------
......
...@@ -47,7 +47,7 @@ using namespace camitk; ...@@ -47,7 +47,7 @@ using namespace camitk;
// ---------------------- Constructor ---------------------------- // ---------------------- Constructor ----------------------------
ImageLutWidget::ImageLutWidget(QWidget* parent) : QWidget(parent) { ImageLutWidget::ImageLutWidget(QWidget* parent) : QWidget(parent) {
myComponent = NULL; myComponent = nullptr;
lutMin = 0; lutMin = 0;
lutMax = 255; lutMax = 255;
...@@ -92,7 +92,7 @@ void ImageLutWidget::updateComponent(ImageComponent* comp) { ...@@ -92,7 +92,7 @@ void ImageLutWidget::updateComponent(ImageComponent* comp) {
myComponent = comp; myComponent = comp;
// if there is no lookup table, just don't display this widget! // if there is no lookup table, just don't display this widget!
if (myComponent->getLut() == NULL) { if (myComponent->getLut() == nullptr) {
setEnabled(false); setEnabled(false);
return; return;
} }
......
...@@ -51,10 +51,8 @@ public: ...@@ -51,10 +51,8 @@ public:
/// Default Destructor /// Default Destructor
virtual ~VolumeRenderingAction() = default; virtual ~VolumeRenderingAction() = default;
void createVolumeRendering(camitk::ImageComponent* comp); void createVolumeRendering(camitk::ImageComponent* comp);
public slots: public slots:
/** this method is automatically called when the action is triggered. /** this method is automatically called when the action is triggered.
* Call getTargets() method to get the list of components to use. * Call getTargets() method to get the list of components to use.
......
...@@ -189,7 +189,7 @@ Action::ApplyStatus WarpOut::apply() { ...@@ -189,7 +189,7 @@ Action::ApplyStatus WarpOut::apply() {
for (vtkIdType i = 0; i < connectivityFilter->GetOutput()->GetNumberOfPoints(); i++) { for (vtkIdType i = 0; i < connectivityFilter->GetOutput()->GetNumberOfPoints(); i++) {
// get the id of the point in the original point set // get the id of the point in the original point set
#if VTK_MAJOR_VERSION == 8 #if VTK_MAJOR_VERSION >= 7
pointId->GetTypedTuple(i, &id); pointId->GetTypedTuple(i, &id);
#else #else
pointId->GetTupleValue(i, &id); pointId->GetTupleValue(i, &id);
......
/***************************************************************************** /*****************************************************************************
* $CAMITK_LICENCE_BEGIN$ * $CAMITK_LICENCE_BEGIN$
* *
* CamiTK - Computer Assisted Medical Intervention ToolKit * CamiTK - Computer Assisted Medical Intervention ToolKit
...@@ -61,6 +61,8 @@ ImpMainWindow::ImpMainWindow() : MainWindow("imp") { ...@@ -61,6 +61,8 @@ ImpMainWindow::ImpMainWindow() : MainWindow("imp") {
// set the specific actions state machine icon // set the specific actions state machine icon
setWindowIcon(QPixmap(":/applicationIcon")); setWindowIcon(QPixmap(":/applicationIcon"));
fileOpenDataDirectoryMenu = nullptr;
// init all other GUI // init all other GUI
initActions(); initActions();
initMenuBar(); initMenuBar();
...@@ -68,7 +70,6 @@ ImpMainWindow::ImpMainWindow() : MainWindow("imp") { ...@@ -68,7 +70,6 @@ ImpMainWindow::ImpMainWindow() : MainWindow("imp") {
// initialize architecture // initialize architecture
updateActionStates(); updateActionStates();
updateOpenDirectoryMenu();
// now add the different viewers // now add the different viewers
setCentralViewer(MedicalImageViewer::getInstance()); setCentralViewer(MedicalImageViewer::getInstance());
...@@ -111,10 +112,9 @@ void ImpMainWindow::aboutToShow() { ...@@ -111,10 +112,9 @@ void ImpMainWindow::aboutToShow() {
void ImpMainWindow::refresh() { void ImpMainWindow::refresh() {
MainWindow::refresh(); MainWindow::refresh();
// update Data directory menu
updateOpenDirectoryMenu();
// update all the action states // update all the action states
updateActionStates(); updateActionStates();
// update menu // update menu
updateRecentDocumentsMenu(); updateRecentDocumentsMenu();
} }
...@@ -229,10 +229,7 @@ void ImpMainWindow::initMenuBar() { ...@@ -229,10 +229,7 @@ void ImpMainWindow::initMenuBar() {
fileMenu = new QMenu(tr("&File")); fileMenu = new QMenu(tr("&File"));
fileMenu->addAction(fileOpen); fileMenu->addAction(fileOpen);
fileOpenDataDirectoryMenu = new QMenu(tr("Open &Data Directory...")); openDataDirectoryMenuBuilder();
fileOpenDataDirectoryMenu->setIcon(QPixmap(":/fileOpen"));
fileOpenDataDirectoryMenu->setEnabled(false);
fileMenu->addMenu(fileOpenDataDirectoryMenu);
fileMenu->addAction(fileClose); fileMenu->addAction(fileClose);
fileMenu->addAction(fileCloseAll); fileMenu->addAction(fileCloseAll);
...@@ -423,32 +420,9 @@ void ImpMainWindow::resetWindows() { ...@@ -423,32 +420,9 @@ void ImpMainWindow::resetWindows() {
move(0, 0); move(0, 0);
} }
// ------------------------ updateDataDirectoryMenu ----------------------------
void ImpMainWindow::updateOpenDirectoryMenu() {
unsigned int nrOfDataDirectoryManager = 0;
disconnect(fileOpenDataDirectoryMenu, SIGNAL(triggered(QAction*)), this, SLOT(openDirectory(QAction*)));
fileOpenDataDirectoryMenu->clear();
fileOpenDataDirectoryMenu->setEnabled(false);
foreach (QString name, ExtensionManager::getDataDirectoryExtNames()) {
nrOfDataDirectoryManager++;
QAction* openDirectory = new QAction(name, this);
openDirectory->setStatusTip(tr(QString("Opens data directory for " + name).toStdString().c_str()));
openDirectory->setWhatsThis(tr(QString("Opens data directory for " + name).toStdString().c_str()));
fileOpenDataDirectoryMenu->addAction(openDirectory);
}
if (nrOfDataDirectoryManager > 0) {
fileOpenDataDirectoryMenu->setEnabled(true);
connect(fileOpenDataDirectoryMenu, SIGNAL(triggered(QAction*)), this, SLOT(openDirectory(QAction*)));
}
}
// ------------- openDataDirectory ----------------- // ------------- openDataDirectory -----------------
void ImpMainWindow::openDirectory(QAction* emitter) { void ImpMainWindow::openDataDirectory(QString plugin) {
QString pluginName = emitter->text().replace("&", ""); QString pluginName = plugin;
statusBar()->showMessage(tr(QString("Opening " + pluginName + " directory...").toStdString().c_str())); statusBar()->showMessage(tr(QString("Opening " + pluginName + " directory...").toStdString().c_str()));
...@@ -499,7 +473,7 @@ void ImpMainWindow::updateViewMenu() { ...@@ -499,7 +473,7 @@ void ImpMainWindow::updateViewMenu() {
// change the central viewer if there is more than one viewer in the central area // change the central viewer if there is more than one viewer in the central area
if (qobject_cast<QStackedWidget*>(centralWidget())->count() > 1) { if (qobject_cast<QStackedWidget*>(centralWidget())->count() > 1) {
viewMenu->addSeparator()->setText(tr("Toggle Central Viewers")); viewMenu->addSeparator()->setText(tr("Toggle Central Viewers"));
// add a toggle action for each widget stacked inside the central widget // add a toggle action for each widget stacked inside the central widget
for (int i = 0; i < qobject_cast<QStackedWidget*>(centralWidget())->count(); i++) { for (int i = 0; i < qobject_cast<QStackedWidget*>(centralWidget())->count(); i++) {
QWidget* cWidget = qobject_cast<QStackedWidget*>(centralWidget())->widget(i); QWidget* cWidget = qobject_cast<QStackedWidget*>(centralWidget())->widget(i);
...@@ -514,15 +488,15 @@ void ImpMainWindow::updateViewMenu() { ...@@ -514,15 +488,15 @@ void ImpMainWindow::updateViewMenu() {
}); });
Viewer* cViewer = (*it); Viewer* cViewer = (*it);
// viewerAction is own by viewMenu, viewMenu->clear() will delete it // viewerAction is own by viewMenu, viewMenu->clear() will delete it
QAction *viewerAction = viewMenu->addAction(cViewer->objectName()); QAction* viewerAction = viewMenu->addAction(cViewer->objectName());
viewerAction->setCheckable(true); viewerAction->setCheckable(true);
viewerAction->setChecked(cViewer == centralViewer); viewerAction->setChecked(cViewer == centralViewer);
QString tipString = "Hide/show the " + cViewer->objectName() + " central viewer"; QString tipString = "Hide/show the " + cViewer->objectName() + " central viewer";
viewerAction->setStatusTip(tr(tipString.toStdString().c_str())); viewerAction->setStatusTip(tr(tipString.toStdString().c_str()));
viewerAction->setWhatsThis(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 // add the toggle action slot using C++11 lambda so that everything is contained inside viewMenu
connect(viewerAction, &QAction::toggled, [=](bool) { connect(viewerAction, &QAction::toggled, [ = ](bool) {
setCentralViewer(cViewer); setCentralViewer(cViewer);
}); });
} }
} }
...@@ -569,7 +543,7 @@ void ImpMainWindow::editSettings() { ...@@ -569,7 +543,7 @@ void ImpMainWindow::editSettings() {
} }
// check if there are anything to change in the data directory menu (for data directory manager) // check if there are anything to change in the data directory menu (for data directory manager)
updateOpenDirectoryMenu(); ImpMainWindow::openDataDirectoryMenuBuilder();
} }
// ------------- setApplicationConsole ----------------- // ------------- setApplicationConsole -----------------
...@@ -623,7 +597,68 @@ void ImpMainWindow::saveHistoryAsSCXML() { ...@@ -623,7 +597,68 @@ void ImpMainWindow::saveHistoryAsSCXML() {
Application::saveHistoryAsSXML(); Application::saveHistoryAsSXML();
} }
// ------------------------- openDataDirectoryMenuBuilder ---------------------------
void ImpMainWindow::openDataDirectoryMenuBuilder() {
QStringList dirExt = ExtensionManager::getDataDirectoryExtNames();
if (dirExt.size() > 1) {
if (fileOpenDataDirectoryMenu == nullptr) {
fileOpenDataDirectoryMenu = new QMenu("Open Data Directory");
fileMenu->addMenu(fileOpenDataDirectoryMenu);
}
else {
disconnect(fileOpenDataDirectoryMenu, 0, 0, 0);
fileOpenDataDirectoryMenu->clear();
}
fileOpenDataDirectoryMenu->setIcon(QPixmap(":/fileOpen"));
for (QString dirExtName : dirExt) {
QAction* openDirectory = new QAction(dirExtName, this);
openDirectory->setStatusTip(tr(QString("Opens data directory for " + dirExtName).toStdString().c_str()));
openDirectory->setWhatsThis(tr(QString("Opens data directory for " + dirExtName).toStdString().c_str()));
connect(openDirectory, &QAction::triggered, this, [ = ]() {
this->openDataDirectory(dirExtName);
});
fileOpenDataDirectoryMenu->addAction(openDirectory);
}
}
else
if (dirExt.size() == 1) {
// if it exists, remove the default directory extension menu (that has only one submenu)
// from the file "open" action list
bool updateAction = false;
QList<QAction*> menuActions = fileMenu->actions();
int indexAction = 0;
while (indexAction < menuActions.size() && !updateAction) {
if (menuActions.at(indexAction)->text().contains(" Directory")) {
menuActions.at(indexAction)->destroyed();
updateAction = true;
}
indexAction++;
}
// create the single open directory action
QString dirExtName = dirExt.at(0);
QAction* openDirectoryAction = new QAction("Open " + dirExtName + " Directory", this);
if (!updateAction) {
// there was no specific menu, just add the single "open directory" action in the file menu
fileMenu->addAction(openDirectoryAction);
}
openDirectoryAction->setStatusTip(tr(QString("Opens data directory for " + dirExtName).toStdString().c_str()));
openDirectoryAction->setWhatsThis(tr(QString("Opens data directory for " + dirExtName).toStdString().c_str()));
connect(openDirectoryAction, &QAction::triggered, this, [ = ]() {
this->openDataDirectory(dirExtName);
});
openDirectoryAction->setIcon(QPixmap(":/fileOpen"));
}
else {
fileOpenDataDirectoryMenu = new QMenu("No plugins loaded to Open Data Directory");
fileOpenDataDirectoryMenu->setIcon(QPixmap(":/fileOpen"));
fileOpenDataDirectoryMenu->setEnabled(false);
fileMenu->addMenu(fileOpenDataDirectoryMenu);
}
}
/***************************************************************************** /*****************************************************************************
* $CAMITK_LICENCE_BEGIN$ * $CAMITK_LICENCE_BEGIN$
* *
* CamiTK - Computer Assisted Medical Intervention ToolKit * CamiTK - Computer Assisted Medical Intervention ToolKit
...@@ -80,7 +80,7 @@ public slots: ...@@ -80,7 +80,7 @@ public slots:
/// @name file menu slot /// @name file menu slot
///@{ ///@{
/// open a data directory, "called" from the fileOpenDataDirectoryMenu /// open a data directory, "called" from the fileOpenDataDirectoryMenu
void openDirectory(QAction*); void openDataDirectory(QString plugin);
///@} ///@}
/// @name viewers' slot /// @name viewers' slot
...@@ -122,11 +122,15 @@ protected: ...@@ -122,11 +122,15 @@ protected:
/// update the viewer's menu /// update the viewer's menu
void updateViewMenu(); void updateViewMenu();
/// Build the open data directory menu
void openDataDirectoryMenuBuilder();
/** @name Extension and ComponentPlugin attributes */ /** @name Extension and ComponentPlugin attributes */
///@{ ///@{
/// update the data directory menu depending on registered plugins /// update the data directory menu depending on registered plugins
void updateOpenDirectoryMenu(); void updateOpenDirectoryMenu();
/// update the recent document menu /// update the recent document menu
void updateRecentDocumentsMenu(); void updateRecentDocumentsMenu();
///@} ///@}
......
...@@ -572,7 +572,7 @@ private: ...@@ -572,7 +572,7 @@ private:
} }
// -------------------- declare the interface for QPluginLoader -------------------- // -------------------- declare the interface for QPluginLoader --------------------
Q_DECLARE_INTERFACE(camitk::Action, "TIMC-IMAG.Action/2.1") //TODO use svn version? Q_DECLARE_INTERFACE(camitk::Action, "TIMC-IMAG.Action/2.1")
#endif // ACTION_H #endif // ACTION_H
......
...@@ -58,6 +58,7 @@ void ActionExtension::initResources() { ...@@ -58,6 +58,7 @@ void ActionExtension::initResources() {
// -------------------- destructor -------------------- // -------------------- destructor --------------------
ActionExtension::~ActionExtension() { ActionExtension::~ActionExtension() {
// delete all actions one by one
while (!actions.empty()) { while (!actions.empty()) {
Action* toDelete = actions.takeFirst(); Action* toDelete = actions.takeFirst();
// do not delete the "Quit" action: it is the action that triggers this delete! // do not delete the "Quit" action: it is the action that triggers this delete!
...@@ -66,7 +67,7 @@ ActionExtension::~ActionExtension() { ...@@ -66,7 +67,7 @@ ActionExtension::~ActionExtension() {
} }
} }
//delete internationalization instance // delete internationalization instance
if (translator) { if (translator) {
delete translator; delete translator;
} }
......
...@@ -108,7 +108,7 @@ private: ...@@ -108,7 +108,7 @@ private:
} }
// -------------------- declare the interface for QPluginLoader -------------------- // -------------------- declare the interface for QPluginLoader --------------------
Q_DECLARE_INTERFACE(camitk::ActionExtension, "TIMC-IMAG. Action Extension/2.1") //TODO use variable from CMake? Q_DECLARE_INTERFACE(camitk::ActionExtension, "TIMC-IMAG. Action Extension/2.1")
#endif //ACTION_EXTENSION_H #endif //ACTION_EXTENSION_H
...@@ -204,7 +204,7 @@ QString Application::getName() { ...@@ -204,7 +204,7 @@ QString Application::getName() {
// ----------------- quitting -------------------- // ----------------- quitting --------------------
void Application::quitting() { void Application::quitting() {
// this is connect to the aboutToQuit signal from QApplication // this is connected to the aboutToQuit signal from QApplication
// it should contain all the code that frees the resources // it should contain all the code that frees the resources
// delete all actions (they are instantiated when the extension is loaded) // delete all actions (they are instantiated when the extension is loaded)
......
...@@ -186,6 +186,27 @@ public: ...@@ -186,6 +186,27 @@ public:
*/ */
vtkSmartPointer<vtkActor> getActor(const RenderingModes) override; vtkSmartPointer<vtkActor> getActor(const RenderingModes) override;
/** Set a texture to this object. */
void setTexture(vtkSmartPointer<vtkTexture> texture) override;
/// a vtkPoint of the structured was picked (to be reimplemented in a Component inherited class if needed)
void pointPicked(vtkIdType, bool) {};
/// a vtkCell of the structured was picked (to be reimplemented in a Component inherited class if needed)
void cellPicked(vtkIdType, bool) {};
///@}
/// @name manage extra prop associated with a Geometry
/// @{
/// TODO
/// - put all this management into a dedicated interface
/// - remove it from InterfaceBitMap and InterfaceGeometry
/// - remove it from Slice and Geometry helper classes
/// - create a new associated helper class
/// - update Component class and all other code using it (if needed)
/// Note : beware that Geometry requires this to manage to at least "label" and "glyph" extra actors
/// Return the vtkProp (actors, volumes and annotations) corresponding to the given name /// Return the vtkProp (actors, volumes and annotations) corresponding to the given name
vtkSmartPointer<vtkProp> getProp(const QString&) override; vtkSmartPointer<vtkProp> getProp(const QString&) override;
...@@ -204,18 +225,8 @@ public: ...@@ -204,18 +225,8 @@ public:
* @return true if effictively done * @return true if effictively done
*/ */
bool removeProp(const QString&) override; bool removeProp(const QString&) override;
/// @}
/** Set a texture to this object. */
void setTexture(vtkSmartPointer<vtkTexture> texture) override;
/// a vtkPoint of the structured was picked (to be reimplemented in a Component inherited class if needed)
void pointPicked(vtkIdType, bool) {};
/// a vtkCell of the structured was picked (to be reimplemented in a Component inherited class if needed)
void cellPicked(vtkIdType, bool) {};
///@}
/// @name InterfaceGeometry Helpers inherited methods /// @name InterfaceGeometry Helpers inherited methods
/// @{ /// @{
...@@ -307,10 +318,7 @@ private: ...@@ -307,10 +318,7 @@ private:
/// the VTK mapper /// the VTK mapper
vtkSmartPointer<vtkDataSetMapper> mapper; vtkSmartPointer<vtkDataSetMapper> mapper;
/// The additional map for prop (include at least "label" and "glyph"
QMap<QString, vtkSmartPointer<vtkProp> > extraProp;
/// the mapper to create the text /// the mapper to create the text
vtkSmartPointer<vtkTextMapper> labelActorMapper; vtkSmartPointer<vtkTextMapper> labelActorMapper;
...@@ -386,8 +394,15 @@ private: ...@@ -386,8 +394,15 @@ private:
double oldAlphaPoints; double oldAlphaPoints;
double oldPointsColor[4]; double oldPointsColor[4];
///@} ///@}
protected:
vtkSmartPointer< vtkPointSet > New(); /// @name manage extra prop associated with a Geometry
/// @{
/// TODO see extra prop management method section
/// The additional map for prop (include at least "label" and "glyph")
QMap<QString, vtkSmartPointer<vtkProp> > extraProp;
///@}
}; };
......
...@@ -85,19 +85,20 @@ public: ...@@ -85,19 +85,20 @@ public:
/** Return the vtkActor used to pick pixels in the slices. */ /** Return the vtkActor used to pick pixels in the slices. */
virtual vtkSmartPointer<vtkActor> getPixelActor() = 0; virtual vtkSmartPointer<vtkActor> getPixelActor() = 0;
virtual void updateReslice() = 0; /** For an arbitrary slice: update the image depending on the current value of the reslice transform */
virtual void updateReslice() = 0;
virtual void setReslicerTransform(vtkSmartPointer<vtkTransform>) = 0;
/** Return 2D Axes at the proper slice origin */
// virtual vtkSmartPointer<vtkAxesActor> get2DAxesActor() = 0;
/** Set the pointer to the image transformation.
* this should be done once, at initialization, using the frame transformation (getTransform)
*/
virtual void setReslicerTransform(vtkSmartPointer<vtkTransform>) = 0;
/** This method is called when the associated plane has been picked in the InteractiveViewer, /** This method is called when the associated plane has been picked in the InteractiveViewer,
* the given coordinates is position where the plane was picked. * the given coordinates is position where the plane was picked.
*/ */