From 66d90a7c0965c4753df66aa14554fac972c6cc50 Mon Sep 17 00:00:00 2001 From: MERLE Mathilde <“mathilde.merle@ihu-liryc.fr”> Date: Wed, 7 Dec 2022 12:26:48 +0100 Subject: [PATCH 1/3] [Tabs] handling of tabs: removal, switch --- .../gui/medTabbedViewContainers.cpp | 44 +++++++++++++++++-- .../gui/medTabbedViewContainers.h | 1 + 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/src/layers/legacy/medCoreLegacy/gui/medTabbedViewContainers.cpp b/src/layers/legacy/medCoreLegacy/gui/medTabbedViewContainers.cpp index 7c0a5fe184..3a943d4963 100644 --- a/src/layers/legacy/medCoreLegacy/gui/medTabbedViewContainers.cpp +++ b/src/layers/legacy/medCoreLegacy/gui/medTabbedViewContainers.cpp @@ -59,13 +59,12 @@ medTabbedViewContainers::medTabbedViewContainers(medAbstractWorkspaceLegacy* own d->closeShortcut = new QShortcut(this); d->closeShortcut->setKey(Qt::ControlModifier + Qt::Key_W); - // /////////////////////////////////////////////////////////////////////// - // Connect for creation and remove tab + // Connect for creation, removal and move of tabs connect(d->addTabButton, SIGNAL(clicked()), this, SLOT(addContainerInTabUnNamed())); connect(this, SIGNAL(tabCloseRequested(int)), this, SLOT(closeTab(int))); connect(d->closeShortcut, SIGNAL(activated()), this, SLOT(closeCurrentTab())); + connect(tabBar(), SIGNAL(tabMoved(int,int)), this, SLOT(movedTabs(int,int))); - // /////////////////////////////////////////////////////////////////////// // Connect group of view handling connect(medViewContainerManager::instance(), SIGNAL(containerAboutToBeDestroyed(QUuid)), this, SLOT(removeContainerFromSelection(QUuid))); connect(this, SIGNAL(containersSelectedChanged()), this, SLOT(buildTemporaryPool())); @@ -257,15 +256,36 @@ void medTabbedViewContainers::closeTab(int index) poMainSpliter->disconnect(this); } poTmp->deleteLater(); - + //Reset tab name if it follows the rule '###' is follows for (int i = 0; i < this->count(); ++i) + { if (this->tabText(i).isEmpty() || this->tabText(i).startsWith(d->owningWorkspace->name(), Qt::CaseSensitive)) + { this->setTabText(i, d->owningWorkspace->name() + " " + QString::number(i + 1)); + } + } // If medTabbedViewContainers is empty and empty is not allowed, we recreate one tab if (d->bKeepLeastOne && (this->count() < 1)) + { this->addContainerInTabUnNamed(); + } + + // Update the remaining tab indexes + d->containerSelectedForTabIndex.remove(index); + QHash > copyHash; + for(auto currentTabIndex : d->containerSelectedForTabIndex.keys()) + { + auto previousTab = d->containerSelectedForTabIndex.take(currentTabIndex); + copyHash.insert(copyHash.count(), previousTab); + } + d->containerSelectedForTabIndex.clear(); + d->containerSelectedForTabIndex = copyHash; + + // Update the current tab to the last one + setCurrentIndex(this->count()-1); + emit containersSelectedChanged(); } void medTabbedViewContainers::tabBarDoubleClickedHandler(int index) @@ -456,3 +476,19 @@ void medTabbedViewContainers::minimizeSplitterContainers(QUuid containerMaximize splitter->show(); } } + +/** + * @brief Launched when a tab from the tabs bar is moved to a new position + * + * @param from index tab before + * @param to index tab after + */ +void medTabbedViewContainers::movedTabs(int from, int to) +{ + auto previousFrom = d->containerSelectedForTabIndex.take(from); + auto previousTo = d->containerSelectedForTabIndex.take(to); + d->containerSelectedForTabIndex.insert(from, previousTo); + d->containerSelectedForTabIndex.insert(to, previousFrom); + + emit containersSelectedChanged(); +} \ No newline at end of file diff --git a/src/layers/legacy/medCoreLegacy/gui/medTabbedViewContainers.h b/src/layers/legacy/medCoreLegacy/gui/medTabbedViewContainers.h index a620a9e00a..36664ecd37 100644 --- a/src/layers/legacy/medCoreLegacy/gui/medTabbedViewContainers.h +++ b/src/layers/legacy/medCoreLegacy/gui/medTabbedViewContainers.h @@ -58,6 +58,7 @@ public slots: medViewContainer* insertNewTab(int index, const QString &name); void closeCurrentTab(); void closeTab(int index); + void movedTabs(int from, int to); private slots : void tabBarDoubleClickedHandler(int index); From e77f5ef57beb23a756dd3c34e7a98c3f53317409 Mon Sep 17 00:00:00 2001 From: MERLE Mathilde <“mathilde.merle@ihu-liryc.fr”> Date: Wed, 7 Dec 2022 12:50:30 +0100 Subject: [PATCH 2/3] [Tabs] manage the case of removing the last tab before opening new ones --- .../gui/medTabbedViewContainers.cpp | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/layers/legacy/medCoreLegacy/gui/medTabbedViewContainers.cpp b/src/layers/legacy/medCoreLegacy/gui/medTabbedViewContainers.cpp index 3a943d4963..37384d952f 100644 --- a/src/layers/legacy/medCoreLegacy/gui/medTabbedViewContainers.cpp +++ b/src/layers/legacy/medCoreLegacy/gui/medTabbedViewContainers.cpp @@ -271,21 +271,23 @@ void medTabbedViewContainers::closeTab(int index) { this->addContainerInTabUnNamed(); } - - // Update the remaining tab indexes - d->containerSelectedForTabIndex.remove(index); - QHash > copyHash; - for(auto currentTabIndex : d->containerSelectedForTabIndex.keys()) + else { - auto previousTab = d->containerSelectedForTabIndex.take(currentTabIndex); - copyHash.insert(copyHash.count(), previousTab); - } - d->containerSelectedForTabIndex.clear(); - d->containerSelectedForTabIndex = copyHash; + // Update the remaining tab indexes + d->containerSelectedForTabIndex.remove(index); + QHash > copyHash; + for(auto currentTabIndex : d->containerSelectedForTabIndex.keys()) + { + auto previousTab = d->containerSelectedForTabIndex.take(currentTabIndex); + copyHash.insert(copyHash.count(), previousTab); + } + d->containerSelectedForTabIndex.clear(); + d->containerSelectedForTabIndex = copyHash; - // Update the current tab to the last one - setCurrentIndex(this->count()-1); - emit containersSelectedChanged(); + // Update the current tab to the last one + setCurrentIndex(this->count()-1); + emit containersSelectedChanged(); + } } void medTabbedViewContainers::tabBarDoubleClickedHandler(int index) From c8eb65b26626471fa03603e955f7b42cde0229af Mon Sep 17 00:00:00 2001 From: Mathilde Merle Date: Wed, 8 Feb 2023 15:57:29 +0100 Subject: [PATCH 3/3] [3.3.2] bug fixes: dcm odd axis + tabs management --- CMakeLists.txt | 2 +- RELEASE_NOTES.txt | 3 ++ src/CMakeLists.txt | 2 +- .../legacy/medImageIO/itkDCMTKImageIO.cpp | 54 ++++++------------- .../legacy/medImageIO/itkDCMTKImageIO.h | 4 +- 5 files changed, 23 insertions(+), 42 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 58713e5d04..f4e62fe2d4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,7 +18,7 @@ if(POLICY CMP0020) endif() if(NOT DEFINED ${MEDINRIA_SUPERBUILD_VERSION}) - set(MEDINRIA_SUPERBUILD_VERSION 3.3.1) + set(MEDINRIA_SUPERBUILD_VERSION 3.3.2) endif() SET(CMAKE_CXX_STANDARD 17) diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt index 2baa9fa6e9..0b493080ec 100644 --- a/RELEASE_NOTES.txt +++ b/RELEASE_NOTES.txt @@ -9,6 +9,9 @@ medInria 3.3: - PolygonROI, solve graphical/ergonomy pb and crashes (split, clear) - Variational Segmentation: enhance GUI, solve a spacing error on output masks - BUGFIX 3.3.1: [Four-views] solve crash closing the views +- BUGFIX 3.3.2: + * Avoid corruption of exported/imported dcm with odd axis + * Fix errors with view tabs if the user switch 2 of them, or remove some of them medInria 3.2: - Add some tooltips in view navigator diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5bb8db29c4..8fdb5c94a6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -16,7 +16,7 @@ cmake_minimum_required(VERSION 3.3) if(NOT DEFINED ${medInria_VERSION}) - set(medInria_VERSION 3.3.1) + set(medInria_VERSION 3.3.2) endif() project(medInria VERSION ${medInria_VERSION}) diff --git a/src/layers/legacy/medImageIO/itkDCMTKImageIO.cpp b/src/layers/legacy/medImageIO/itkDCMTKImageIO.cpp index 9096bdf07e..2834252282 100644 --- a/src/layers/legacy/medImageIO/itkDCMTKImageIO.cpp +++ b/src/layers/legacy/medImageIO/itkDCMTKImageIO.cpp @@ -670,53 +670,29 @@ void DCMTKImageIO::DetermineOrientation() } } - double DCMTKImageIO::GetPositionOnStackingAxisForImage (int index) { - // Getting the unit vector of the closest axis - // so we know which part of the image position to use - vnl_vector closestAxis (3); - closestAxis[0] = round(m_Direction[2][0]); - closestAxis[1] = round(m_Direction[2][1]); - closestAxis[2] = round(m_Direction[2][2]); - if (fabs(closestAxis[0] + closestAxis[1] + closestAxis[2]) != 1) + // Get maximum absolute value, which is the closest to an axis + auto result = std::max_element(m_Direction[2].begin(), m_Direction[2].end(), [](double a, double b) { - itkExceptionMacro ( - << "Ambiguous slice stack direction: " - <GetMetaDataValueString("(0020,0032)", index); - std::istringstream is_stream( s_position.c_str() ); + // Index of the value in the vector + auto principalAxisIndex = std::distance(m_Direction[2].begin(), result); - double pos = 0.0; - bool foundAxis=false; + return GetPositionFromPrincipalAxisIndex(index, principalAxisIndex); +} - for (int i=0; i<3; i++) - { - if (!(is_stream >> pos) ) - { - itkWarningMacro ( << "Cannot convert string to double: " << s_position.c_str() << std::endl ); - } - else - { - if (fabs(closestAxis[i]) == 1) - { - foundAxis = true; - break; - } - } - } +double DCMTKImageIO::GetPositionFromPrincipalAxisIndex(int index, int principalAxisIndex) +{ + std::string s_position = this->GetMetaDataValueString("(0020,0032)", index); - if (!foundAxis) - { - itkWarningMacro ( <<"Could not identify position on stacking axis, returning zero." << std::endl ); - } + // Convert string metadata to vector of double + std::stringstream lineStream(s_position); + std::vector positionVector(std::istream_iterator(lineStream), {}); - return pos; + return positionVector[principalAxisIndex]; } diff --git a/src/layers/legacy/medImageIO/itkDCMTKImageIO.h b/src/layers/legacy/medImageIO/itkDCMTKImageIO.h index f4fe63a445..f8940a2797 100644 --- a/src/layers/legacy/medImageIO/itkDCMTKImageIO.h +++ b/src/layers/legacy/medImageIO/itkDCMTKImageIO.h @@ -21,6 +21,7 @@ #include +#include #include #include #include @@ -188,7 +189,8 @@ class MEDIMAGEIO_EXPORT DCMTKImageIO : public MultiThreadedImageIOBase void DetermineOrigin(); void DetermineOrientation(); - double GetPositionOnStackingAxisForImage (int); + double GetPositionOnStackingAxisForImage(int); + double GetPositionFromPrincipalAxisIndex(int, int); double GetSliceLocation(std::string); void ReadHeader( const std::string& name, const int& fileIndex, const int& fileCount );