fw4spl
SliceIndexPositionEditor.cpp
1 /* ***** BEGIN LICENSE BLOCK *****
2  * FW4SPL - Copyright (C) IRCAD, 2009-2018.
3  * Distributed under the terms of the GNU Lesser General Public License (LGPL) as
4  * published by the Free Software Foundation.
5  * ****** END LICENSE BLOCK ****** */
6 
7 #include "uiImageQt/SliceIndexPositionEditor.hpp"
8 
9 #include <fwCom/Signal.hpp>
10 #include <fwCom/Signal.hxx>
11 #include <fwCom/Signals.hpp>
12 #include <fwCom/Slot.hpp>
13 #include <fwCom/Slot.hxx>
14 #include <fwCom/Slots.hpp>
15 #include <fwCom/Slots.hxx>
16 
17 #include <fwCore/base.hpp>
18 
19 #include <fwData/Composite.hpp>
20 #include <fwData/Image.hpp>
21 #include <fwData/Integer.hpp>
22 
23 #include <fwDataTools/fieldHelper/Image.hpp>
24 #include <fwDataTools/fieldHelper/MedicalImageHelpers.hpp>
25 
26 #include <fwGuiQt/container/QtContainer.hpp>
27 
28 #include <fwRuntime/ConfigurationElement.hpp>
29 #include <fwRuntime/operations.hpp>
30 
31 #include <fwServices/macros.hpp>
32 
33 #include <boost/algorithm/string/case_conv.hpp>
34 #include <boost/algorithm/string/trim.hpp>
35 #include <boost/lexical_cast.hpp>
36 
37 #include <QVBoxLayout>
38 #include <QWidget>
39 
40 #include <functional>
41 
42 namespace uiImageQt
43 {
44 
46 
47 const std::string* SliceIndexPositionEditor::SLICE_INDEX_FIELDID[ 3 ] =
48 {
52 };
53 
54 static const ::fwCom::Slots::SlotKeyType s_UPDATE_SLICE_INDEX_SLOT = "updateSliceIndex";
55 static const ::fwCom::Slots::SlotKeyType s_UPDATE_SLICE_TYPE_SLOT = "updateSliceType";
56 
57 static const ::fwServices::IService::KeyType s_IMAGE_INOUT = "image";
58 
59 //------------------------------------------------------------------------------
60 
62 {
63  newSlot(s_UPDATE_SLICE_INDEX_SLOT, &SliceIndexPositionEditor::updateSliceIndex, this);
64  newSlot(s_UPDATE_SLICE_TYPE_SLOT, &SliceIndexPositionEditor::updateSliceType, this);
65 }
66 
67 //------------------------------------------------------------------------------
68 
70 {
71 }
72 
73 //------------------------------------------------------------------------------
74 
76 {
77  this->create();
78 
79  ::fwGuiQt::container::QtContainer::sptr qtContainer = ::fwGuiQt::container::QtContainer::dynamicCast(
80  this->getContainer() );
81 
82  QVBoxLayout* layout = new QVBoxLayout( );
83 
84  m_sliceSelectorPanel = new ::fwGuiQt::SliceSelector();
85  m_sliceSelectorPanel->setEnable(false);
86 
87  ::fwGuiQt::SliceSelector::ChangeIndexCallback changeIndexCallback;
88  changeIndexCallback = std::bind( &::uiImageQt::SliceIndexPositionEditor::sliceIndexNotification, this,
89  std::placeholders::_1);
90  m_sliceSelectorPanel->setChangeIndexCallback(changeIndexCallback);
91 
92  ::fwGuiQt::SliceSelector::ChangeIndexCallback changeTypeCallback;
93  changeTypeCallback = std::bind( &::uiImageQt::SliceIndexPositionEditor::sliceTypeNotification, this,
94  std::placeholders::_1);
95  m_sliceSelectorPanel->setChangeTypeCallback(changeTypeCallback);
96  layout->addWidget( m_sliceSelectorPanel );
97  layout->setContentsMargins(0, 0, 0, 0);
98 
99  ::fwData::Image::sptr image = this->getInOut< ::fwData::Image >(s_IMAGE_INOUT);
100  if (!image)
101  {
102  FW_DEPRECATED_KEY(s_IMAGE_INOUT, "inout", "18.0");
103  image = this->getObject< ::fwData::Image >();
104  }
105  this->updateImageInfos(image);
107 
108  qtContainer->setLayout( layout );
109 
110  this->updating();
111 }
112 
113 //------------------------------------------------------------------------------
114 
116 {
117  this->destroy();
118  m_sliceSelectorPanel = nullptr;
119 }
120 
121 //------------------------------------------------------------------------------
122 
124 {
125  this->initialize();
126 
127  if( this->m_configuration->size() > 0 )
128  {
129  std::vector< ::fwRuntime::ConfigurationElement::sptr > slideIndexCfg = m_configuration->find("sliceIndex");
130  SLM_ASSERT("Only one xml element \"sliceIndex\" is accepted.", slideIndexCfg.size() == 1 );
131  SLM_ASSERT("The xml element \"sliceIndex\" is empty.", !(*slideIndexCfg.begin())->getValue().empty() );
132  std::string orientation = (*slideIndexCfg.begin())->getValue();
133  ::boost::algorithm::trim(orientation);
134  ::boost::algorithm::to_lower(orientation);
135 
136  if(orientation == "axial" )
137  {
138  m_orientation = Z_AXIS;
139  }
140  else if(orientation == "frontal" )
141  {
142  m_orientation = Y_AXIS;
143  }
144  else if(orientation == "sagittal" )
145  {
146  m_orientation = X_AXIS;
147  }
148  else
149  {
150  SLM_FATAL("The value for the xml element \"sliceIndex\" can only be axial, frontal or sagittal.");
151  }
152  }
153 }
154 
155 //------------------------------------------------------------------------------
156 
158 {
159  ::fwData::Image::sptr image = this->getInOut< ::fwData::Image >(s_IMAGE_INOUT);
160  if (!image)
161  {
162  FW_DEPRECATED_KEY(s_IMAGE_INOUT, "inout", "18.0");
163  image = this->getObject< ::fwData::Image >();
164  }
166  m_sliceSelectorPanel->setEnable(imageIsValid);
167  this->updateImageInfos(image);
168  this->updateSliceIndexFromImg();
169 }
170 
171 //------------------------------------------------------------------------------
172 
174 {
175  this->updating();
176 }
177 
178 //-----------------------------------------------------------------------------
179 
180 void SliceIndexPositionEditor::updateSliceIndex(int axial, int frontal, int sagittal)
181 {
182  m_axialIndex->value() = axial;
183  m_frontalIndex->value() = frontal;
184  m_sagittalIndex->value() = sagittal;
185 
186  ::fwData::Image::sptr image = this->getInOut< ::fwData::Image >(s_IMAGE_INOUT);
187  if (!image)
188  {
189  FW_DEPRECATED_KEY(s_IMAGE_INOUT, "inout", "18.0");
190  image = this->getObject< ::fwData::Image >();
191  }
192 
193  image->setField( fwDataTools::fieldHelper::Image::m_axialSliceIndexId, m_axialIndex);
196  this->updateSliceIndexFromImg();
197 }
198 
199 //-----------------------------------------------------------------------------
200 
201 void SliceIndexPositionEditor::updateSliceType(int from, int to)
202 {
203  if( to == static_cast< int > ( m_orientation ) )
204  {
205  m_orientation = static_cast< Orientation > ( from );
206  }
207  else if(from == static_cast<int>(m_orientation))
208  {
209  m_orientation = static_cast< Orientation >( to );
210  }
212 }
213 
214 //------------------------------------------------------------------------------
215 
216 void SliceIndexPositionEditor::info( std::ostream& _sstream )
217 {
218 }
219 
220 //------------------------------------------------------------------------------
221 
223 {
224  ::fwData::Image::sptr image = this->getInOut< ::fwData::Image >(s_IMAGE_INOUT);
225  if (!image)
226  {
227  FW_DEPRECATED_KEY(s_IMAGE_INOUT, "inout", "18.0");
228  image = this->getObject< ::fwData::Image >();
229  }
230 
232  {
233  // Get Index
234  std::string fieldID = *SLICE_INDEX_FIELDID[m_orientation];
235  OSLM_ASSERT("Field "<<fieldID<<" is missing", image->getField( fieldID ) );
236  unsigned int index = image->getField< ::fwData::Integer >( fieldID )->value();
237 
238  // Update QSlider
239  int max = 0;
240  if(image->getNumberOfDimensions() > m_orientation)
241  {
242  max = static_cast<int>(image->getSize()[m_orientation]-1);
243  }
244  m_sliceSelectorPanel->setSliceRange( 0, max );
245  m_sliceSelectorPanel->setSliceValue( index );
246  }
247 }
248 
249 //------------------------------------------------------------------------------
250 
252 {
253  // Update Type Choice
254  m_sliceSelectorPanel->setTypeSelection( static_cast< int >( type ) );
255 
256  ::fwData::Image::sptr image = this->getInOut< ::fwData::Image >(s_IMAGE_INOUT);
257  if (!image)
258  {
259  FW_DEPRECATED_KEY(s_IMAGE_INOUT, "inout", "18.0");
260  image = this->getObject< ::fwData::Image >();
261  }
262  this->updateSliceIndexFromImg();
263 }
264 
265 //------------------------------------------------------------------------------
266 
268 {
269  ::fwData::Image::sptr image = this->getInOut< ::fwData::Image >(s_IMAGE_INOUT);
270  if (!image)
271  {
272  FW_DEPRECATED_KEY(s_IMAGE_INOUT, "inout", "18.0");
273  image = this->getObject< ::fwData::Image >();
274  }
275 
276  std::string fieldID = *SLICE_INDEX_FIELDID[m_orientation];
277  OSLM_ASSERT("Field "<<fieldID<<" is missing", image->getField( fieldID ));
278  image->getField< ::fwData::Integer >( fieldID )->value() = index;
279 
280  auto sig = image->signal< ::fwData::Image::SliceIndexModifiedSignalType >(
282  ::fwCom::Connection::Blocker block(sig->getConnection(this->slot(s_UPDATE_SLICE_INDEX_SLOT)));
283  sig->asyncEmit(m_axialIndex->value(), m_frontalIndex->value(), m_sagittalIndex->value());
284 }
285 
286 //------------------------------------------------------------------------------
287 
289 {
290  Orientation type = static_cast< Orientation >( _type );
291  OSLM_ASSERT("Bad slice type "<<type, type == X_AXIS ||
292  type == Y_AXIS ||
293  type == Z_AXIS );
294 
295  int oldType = static_cast< int > ( m_orientation );
296  // Change slice type
297  m_orientation = type;
298 
299  // Fire the signal
300  ::fwData::Image::sptr image = this->getInOut< ::fwData::Image >(s_IMAGE_INOUT);
301  if (!image)
302  {
303  FW_DEPRECATED_KEY(s_IMAGE_INOUT, "inout", "18.0");
304  image = this->getObject< ::fwData::Image >();
305  }
306  auto sig = image->signal< ::fwData::Image::SliceTypeModifiedSignalType >(
308  {
309  ::fwCom::Connection::Blocker block(sig->getConnection(this->slot(s_UPDATE_SLICE_TYPE_SLOT)));
310  sig->asyncEmit(oldType, _type);
311  }
312  this->updateSliceIndexFromImg();
313 }
314 
315 //------------------------------------------------------------------------------
316 
318 {
319  KeyConnectionsType connections;
320  connections.push_back( std::make_pair( ::fwData::Image::s_MODIFIED_SIG, s_UPDATE_SLOT ) );
321  connections.push_back( std::make_pair( ::fwData::Image::s_SLICE_INDEX_MODIFIED_SIG, s_UPDATE_SLICE_INDEX_SLOT ) );
322  connections.push_back( std::make_pair( ::fwData::Image::s_SLICE_TYPE_MODIFIED_SIG, s_UPDATE_SLICE_TYPE_SLOT ) );
323  connections.push_back( std::make_pair( ::fwData::Image::s_BUFFER_MODIFIED_SIG, s_UPDATE_SLOT ) );
324 
325  return connections;
326 }
327 
328 //------------------------------------------------------------------------------
329 
331 {
332  KeyConnectionsMap connections;
333 
334  //FIXME hack to support deprecated getObject()
335  if (this->getInOut< ::fwData::Image >(s_IMAGE_INOUT))
336  {
337  connections.push(s_IMAGE_INOUT, ::fwData::Image::s_MODIFIED_SIG, s_UPDATE_SLOT);
338  connections.push(s_IMAGE_INOUT, ::fwData::Image::s_SLICE_INDEX_MODIFIED_SIG, s_UPDATE_SLICE_INDEX_SLOT);
339  connections.push(s_IMAGE_INOUT, ::fwData::Image::s_SLICE_TYPE_MODIFIED_SIG, s_UPDATE_SLICE_TYPE_SLOT);
340  connections.push(s_IMAGE_INOUT, ::fwData::Image::s_BUFFER_MODIFIED_SIG, s_UPDATE_SLOT);
341  }
342 
343  return connections;
344 }
345 
346 //------------------------------------------------------------------------------
347 
348 }
#define FW_DEPRECATED_KEY(newKey, access, version)
Use this macro when deprecating a service key to warn the developer.
Definition: spyLog.hpp:366
static FWDATA_APIconst::fwCom::Signals::SignalKeyType s_SLICE_INDEX_MODIFIED_SIG
Type of signal when image&#39;s buffer is added.
UIIMAGEQT_API void updateSliceTypeFromImg(Orientation type)
Update the editor slice type choice from the image slice type.
This class is a helper to define the connections of a service and its data.
Definition: IService.hpp:454
virtual UIIMAGEQT_API KeyConnectionsType getObjSrvConnections() const override
Returns proposals to connect service slots to associated object signals, this method is used for obj/...
virtual void swapping() override
Swap of image.
virtual UIIMAGEQT_API KeyConnectionsMap getAutoConnections() const override
Returns proposals to connect service slots to associated object signals, this method is used for obj/...
#define OSLM_ASSERT(message, cond)
work like &#39;assert&#39; from &#39;cassert&#39;, with in addition a message logged by spylog (with FATAL loglevel) ...
Definition: spyLog.hpp:310
Class allowing to block a Connection.
Definition: Connection.hpp:20
This class contains an integer value. Integer object is essentially used as a field in other objects...
Definition: Integer.hpp:24
virtual void starting() override
Install the layout.
Defines the service interface managing the editor service for object.
Definition: IEditor.hpp:25
::fwData::Integer::sptr m_axialIndex
Axial slice index.
FWGUI_API void destroy()
Stops sub-views and toobar services. Destroys view, sub-views and toolbar containers.
::fwData::Integer::sptr m_sagittalIndex
Sagittal slice index.
virtual void stopping() override
Destroy the layout.
The namespace uiImageQt contains several editors on image written with Qt. This namespace is included...
Definition: ImageInfo.hpp:23
#define SLM_FATAL(message)
Definition: spyLog.hpp:283
UIIMAGEQT_API void sliceTypeNotification(int type)
This method is called when the slice type selected change. Notify the slice type is modified...
virtual void updating() override
Update editor information from the image.
Orientation m_orientation
Image orientation.
FWDATATOOLS_API void updateImageInfos(::fwData::Image::sptr image)
Update the image information (slice index, min/max,...)
virtual UIIMAGEQT_API ~SliceIndexPositionEditor() noexcept
Destructor. Do nothing.
#define SLM_ASSERT(message, cond)
work like &#39;assert&#39; from &#39;cassert&#39;, with in addition a message logged by spylog (with FATAL loglevel) ...
Definition: spyLog.hpp:308
virtual void configuring() override
Configure the editor.
::fwRuntime::ConfigurationElement::sptr m_configuration
Configuration element used to configure service internal state using a generic XML like structure TOD...
Definition: IService.hpp:670
::fwCom::helper::SigSlotConnection::KeyConnectionsType KeyConnectionsType
Returns proposals to connect service slots to associated object signals, this method is used for obj/...
Definition: IService.hpp:449
FWGUI_API void create()
Creates view, sub-views and toolbar containers. Manages sub-views and toobar services.
static FWDATA_APIconst::fwCom::Signals::SignalKeyType s_BUFFER_MODIFIED_SIG
Type of signal when image&#39;s buffer is added.
static FWDATA_APIconst::fwCom::Signals::SignalKeyType s_MODIFIED_SIG
Key in m_signals map of signal m_sigModified.
::fwData::Integer::sptr m_frontalIndex
Frontal slice index.
static FWDATATOOLS_API bool checkImageValidity(::fwData::Image::csptr _pImg)
Check if the image is valid.
SliceIndexPositionEditor service allows to change the slice index of an image.
This class defines an image.
UIIMAGEQT_API void sliceIndexNotification(unsigned int index)
This method is called when the slider is move. Notify the slice index is modified.
UIIMAGEQT_API SliceIndexPositionEditor() noexcept
Constructor. Do nothing.
static FWDATA_APIconst::fwCom::Signals::SignalKeyType s_SLICE_TYPE_MODIFIED_SIG
Type of signal when image&#39;s buffer is added.
virtual UIIMAGEQT_API void info(std::ostream &_sstream) override
Overrides.
static FWSERVICES_APIconst::fwCom::Slots::SlotKeyType s_UPDATE_SLOT
Slot to call start method.
Definition: IService.hpp:177
FWGUI_API void initialize()
Initialize managers.
UIIMAGEQT_API void updateSliceIndexFromImg()
Update the editor slider from the image slice index.