fw4spl
SModelSeriesList.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 "uiMedDataQt/editor/SModelSeriesList.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/Boolean.hpp>
20 #include <fwData/Float.hpp>
21 #include <fwData/Integer.hpp>
22 #include <fwData/Reconstruction.hpp>
23 #include <fwData/String.hpp>
24 
25 #include <fwDataCamp/getObject.hpp>
26 
27 #include <fwDataTools/helper/Field.hpp>
28 
29 #include <fwGuiQt/container/QtContainer.hpp>
30 
31 #include <fwMedData/ModelSeries.hpp>
32 
33 #include <fwRuntime/operations.hpp>
34 
35 #include <fwServices/IService.hpp>
36 #include <fwServices/macros.hpp>
37 #include <fwServices/op/Get.hpp>
38 
39 #include <fwTools/fwID.hpp>
40 
41 #include <boost/format.hpp>
42 
43 #include <QCheckBox>
44 #include <QGroupBox>
45 #include <QListWidgetItem>
46 #include <QString>
47 #include <QTreeWidget>
48 #include <QTreeWidgetItem>
49 #include <QVBoxLayout>
50 
51 namespace uiMedDataQt
52 {
53 namespace editor
54 {
55 
56 class ValueView
57 {
58 public:
59  //------------------------------------------------------------------------------
60 
61  virtual std::string apply(::fwData::Object::sptr obj)
62  {
63  if(obj->isA("::fwData::String"))
64  {
65  ::fwData::String::sptr fwValue = ::fwData::String::dynamicCast(obj);
66  return fwValue->getValue();
67  }
68  else if(obj->isA("::fwData::Integer"))
69  {
70  ::fwData::Integer::sptr fwValue = ::fwData::Integer::dynamicCast(obj);
71  return ::boost::lexical_cast<std::string>(fwValue->getValue());
72  }
73  else if(obj->isA("::fwData::Float"))
74  {
75  ::fwData::Float::sptr fwValue = ::fwData::Float::dynamicCast(obj);
76  return ::boost::lexical_cast<std::string>(fwValue->getValue());
77  }
78  else
79  {
80  SLM_WARN(obj->getClassname() + " is not a printable object : ");
81  return "";
82  }
83  }
84 };
85 
86 class PositiveView : public ValueView
87 {
88 
89 public:
90  //------------------------------------------------------------------------------
91 
92  virtual std::string apply(::fwData::Object::sptr obj)
93  {
94  if(obj->isA("::fwData::Integer"))
95  {
96  ::fwData::Integer::sptr fwValue = ::fwData::Integer::dynamicCast(obj);
97 
98  if(fwValue->getValue() > 0)
99  {
100  std::stringstream ss;
101  ::fwData::Float::sptr fwValue = ::fwData::Float::dynamicCast(obj);
102  ss << ::boost::format("%11.2f") % (fwValue->getValue());
103  return ss.str();
104  }
105  return "Unknown";
106  }
107  else if(obj->isA("::fwData::Float"))
108  {
109  ::fwData::Float::sptr fwValue = ::fwData::Float::dynamicCast(obj);
110  if(fwValue->getValue() > 0)
111  {
112  std::stringstream ss;
113  ::fwData::Float::sptr fwValue = ::fwData::Float::dynamicCast(obj);
114  ss << ::boost::format("%11.2f") % (fwValue->getValue());
115  return ss.str();
116  }
117  return "Unknown";
118  }
119  else
120  {
121  SLM_WARN(obj->getClassname() + " is not a printable object : ");
122  return "";
123  }
124  }
125 };
126 
128 
129 const ::fwCom::Signals::SignalKeyType SModelSeriesList::s_RECONSTRUCTION_SELECTED_SIG = "reconstructionSelected";
130 const ::fwCom::Signals::SignalKeyType SModelSeriesList::s_EMPTIED_SELECTION_SIG = "emptiedSelection";
131 const ::fwCom::Slots::SlotKeyType SModelSeriesList::s_SHOW_RECONSTRUCTIONS_SLOT = "showReconstructions";
132 
133 const ::fwServices::IService::KeyType s_MODEL_SERIES_INOUT = "modelSeries";
134 
136  m_tree(new QTreeWidget()),
137  m_enableHideAll(true)
138 {
139  m_sigReconstructionSelected = newSignal< ReconstructionSelectedSignalType >( s_RECONSTRUCTION_SELECTED_SIG );
140  m_sigEmptiedSelection = newSignal< EmptiedSelectionSignalType >( s_EMPTIED_SELECTION_SIG );
141 
142  newSlot(s_SHOW_RECONSTRUCTIONS_SLOT, &SModelSeriesList::showReconstructions, this);
143 }
144 
145 //------------------------------------------------------------------------------
146 
148 {
149  for(auto cIt : m_displayedInfo)
150  {
151  delete cIt.second;
152  }
153 }
154 
155 //------------------------------------------------------------------------------
156 
158 {
159  SLM_TRACE_FUNC();
160  this->create();
161  ::fwGuiQt::container::QtContainer::sptr qtContainer
162  = ::fwGuiQt::container::QtContainer::dynamicCast(this->getContainer());
163 
164  QVBoxLayout* layout = new QVBoxLayout;
165  QHBoxLayout* layoutButton = new QHBoxLayout;
166  layout->addLayout(layoutButton);
167 
168  if (m_enableHideAll)
169  {
170  // check box "show"
171  m_showCheckBox = new QCheckBox( tr("Hide all organs"));
172  m_showCheckBox->setToolTip(tr("Show or hide all organs"));
173  layoutButton->addWidget( m_showCheckBox, 0 );
174  QObject::connect(m_showCheckBox, SIGNAL(stateChanged(int)), this, SLOT(onShowReconstructions(int)));
175 
176  m_checkAllButton = new QPushButton(tr("Check all"));
177  layoutButton->addWidget(m_checkAllButton, 0);
178  QObject::connect( m_checkAllButton, SIGNAL(clicked()), this, SLOT(onCheckAllCheckBox()) );
179 
180  m_unCheckAllButton = new QPushButton(tr("UnCheck all"));
181  layoutButton->addWidget(m_unCheckAllButton, 0);
182  QObject::connect( m_unCheckAllButton, SIGNAL(clicked()), this, SLOT(onUnCheckAllCheckBox()) );
183  }
184 
185  layout->addWidget( m_tree, 1 );
186 
187  qtContainer->setLayout( layout );
188 
189  QObject::connect(m_tree, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)),
190  this, SLOT(onCurrentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)));
191 
192  this->updating();
193 
194  QObject::connect(m_tree, SIGNAL(itemChanged(QTreeWidgetItem*,int)),
195  this, SLOT(onCurrentItemChanged(QTreeWidgetItem*,int)));
196 }
197 
198 //------------------------------------------------------------------------------
199 
201 {
202  SLM_TRACE_FUNC();
203 
204  if(m_showCheckBox)
205  {
206  QObject::disconnect(m_showCheckBox, SIGNAL(stateChanged(int)), this, SLOT(onShowReconstructions(int)));
207  }
208 
209  QObject::disconnect(m_tree, SIGNAL(itemChanged(QTreeWidgetItem*,int)),
210  this, SLOT(onCurrentItemChanged(QTreeWidgetItem*,int)));
211  QObject::disconnect(m_tree, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)),
212  this, SLOT(onCurrentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)));
213 
214  this->destroy();
215 }
216 
217 //------------------------------------------------------------------------------
218 
220 {
221  SLM_TRACE_FUNC();
222  this->initialize();
223 
224  if( m_configuration->findConfigurationElement( "enable_hide_all" ) )
225  {
226  const std::string& hide = m_configuration->findConfigurationElement("enable_hide_all")->getValue();
227  SLM_ASSERT("'enable_hide_all' attribute value must be 'true' or 'false' (found '" + hide + "')",
228  hide == "true" || hide == "false");
229  m_enableHideAll = (hide == "true");
230  }
231 
232  const ::fwRuntime::ConfigurationElement::sptr& columns = m_configuration->findConfigurationElement( "columns" );
233  if(columns)
234  {
235  ::fwRuntime::ConfigurationElement::Container::const_iterator cIt = columns->begin();
236  m_tree->setColumnCount(static_cast<int>(columns->size()));
237  QStringList header;
238  for(; cIt != columns->end(); cIt++)
239  {
240  ValueView* view;
241  ::fwRuntime::ConfigurationElement::AttributePair configView = (*cIt)->getSafeAttributeValue("view");
242  if(!configView.first)
243  {
244  view = new ValueView();
245  }
246  else if (configView.second == ("positive"))
247  {
248  view = new PositiveView();
249  }
250 
251  m_displayedInfo.insert(DisplayedInformation::value_type((*cIt)->getValue(), view));
252  header << QString::fromStdString((*cIt)->getName());
253  }
254  m_tree->setHeaderLabels(header);
255  }
256 }
257 
258 //------------------------------------------------------------------------------
259 
261 {
262  m_tree->blockSignals(true);
263 
264  this->updateReconstructions();
265  this->refreshVisibility();
266 
267  m_tree->blockSignals(false);
268 
269 }
270 
271 //------------------------------------------------------------------------------
272 
274 {
275  this->updating();
276 }
277 
278 //------------------------------------------------------------------------------
279 
280 void SModelSeriesList::updateReconstructions()
281 {
282  ::fwGuiQt::container::QtContainer::sptr qtContainer
283  = ::fwGuiQt::container::QtContainer::dynamicCast( this->getContainer() );
284  QWidget* const container = qtContainer->getQtContainer();
285 
286  SLM_ASSERT("container not instanced", container);
287 
288  ::fwMedData::ModelSeries::sptr modelSeries = this->getInOut< ::fwMedData::ModelSeries >(s_MODEL_SERIES_INOUT);
289  if (!modelSeries)
290  {
291  FW_DEPRECATED_KEY(s_MODEL_SERIES_INOUT, "inout", "18.0");
292  modelSeries = this->getObject< ::fwMedData::ModelSeries >();
293  }
294 
295  bool hasReconstructions = !modelSeries->getReconstructionDB().empty();
296  container->setEnabled( hasReconstructions );
297 
298  if(hasReconstructions)
299  {
300  this->fillTree();
301  if(m_showCheckBox)
302  {
303  const bool showAllRec = modelSeries->getField("ShowReconstructions", ::fwData::Boolean::New(true))->value();
304  m_showCheckBox->setCheckState(showAllRec ? Qt::Unchecked : Qt::Checked );
305  }
306  }
307 }
308 
309 //------------------------------------------------------------------------------
310 
311 void SModelSeriesList::fillTree()
312 {
313  ::fwMedData::ModelSeries::sptr modelSeries = this->getInOut< ::fwMedData::ModelSeries >(s_MODEL_SERIES_INOUT);
314  if (!modelSeries)
315  {
316  FW_DEPRECATED_KEY(s_MODEL_SERIES_INOUT, "inout", "18.0");
317  modelSeries = this->getObject< ::fwMedData::ModelSeries >();
318  }
319  auto& reconstructions = modelSeries->getReconstructionDB();
320 
321  if(!m_tree->selectedItems().empty())
322  {
323  m_sigEmptiedSelection->asyncEmit();
324  }
325 
326  m_tree->clear();
327 
328  // Create items
329  for(auto const& reconstruction : reconstructions)
330  {
331  QStringList info;
332  for(auto const& cIt : m_displayedInfo)
333  {
334  ::fwData::Object::sptr obj = ::fwDataCamp::getObject(reconstruction, cIt.first);
335  OSLM_ASSERT("Invalid seshat path : '"<< cIt.first <<"'", obj);
336  info << QString::fromStdString(cIt.second->apply(obj));
337  }
338  QTreeWidgetItem* item = new QTreeWidgetItem(info);
339  item->setCheckState(0, Qt::Unchecked);
340  m_tree->addTopLevelItem(item);
341  item->setData(0, Qt::UserRole, QString::fromStdString(reconstruction->getID()));
342  }
343 
344  for(int i = 0; i < m_tree->topLevelItemCount(); i++)
345  {
346  m_tree->resizeColumnToContents(i);
347  }
348 }
349 
350 //------------------------------------------------------------------------------
351 
352 void SModelSeriesList::onCurrentItemChanged( QTreeWidgetItem* current, QTreeWidgetItem* )
353 {
354  SLM_ASSERT( "Current selected item is null", current );
355  std::string id = current->data(0, Qt::UserRole).toString().toStdString();
356 
357  ::fwData::Reconstruction::sptr rec = ::fwData::Reconstruction::dynamicCast(::fwTools::fwID::getObject(id));
358 
359  m_sigReconstructionSelected->asyncEmit(rec);
360 }
361 
362 //------------------------------------------------------------------------------
363 
364 void SModelSeriesList::onCurrentItemChanged ( QTreeWidgetItem* current, int column )
365 {
366  this->onOrganChoiceVisibility(current, column);
367 }
368 
369 //------------------------------------------------------------------------------
370 
371 void SModelSeriesList::onOrganChoiceVisibility(QTreeWidgetItem* item, int )
372 {
373  std::string id = item->data(0, Qt::UserRole).toString().toStdString();
374  ::fwData::Reconstruction::sptr rec = ::fwData::Reconstruction::dynamicCast(::fwTools::fwID::getObject(id));
375  SLM_ASSERT("rec not instanced", rec);
376 
377  const bool itemIsChecked = (item->checkState(0) == Qt::Checked);
378 
379  if (rec->getIsVisible() != itemIsChecked)
380  {
381  rec->setIsVisible(itemIsChecked);
382 
383  ::fwData::Reconstruction::VisibilityModifiedSignalType::sptr sig;
386  sig->asyncEmit(itemIsChecked);
387  }
388 }
389 
390 //------------------------------------------------------------------------------
391 
392 void SModelSeriesList::onShowReconstructions(int state )
393 {
394  const bool visible = static_cast<bool>(state);
395 
396  m_checkAllButton->setEnabled(!visible);
397  m_unCheckAllButton->setEnabled(!visible);
398  m_tree->setEnabled(!visible);
399 
400  ::fwMedData::ModelSeries::sptr modelSeries = this->getInOut< ::fwMedData::ModelSeries >(s_MODEL_SERIES_INOUT);
401  if (!modelSeries)
402  {
403  FW_DEPRECATED_KEY(s_MODEL_SERIES_INOUT, "inout", "18.0");
404  modelSeries = this->getObject< ::fwMedData::ModelSeries >();
405  }
406  {
407  ::fwDataTools::helper::Field helper( modelSeries );
408  helper.addOrSwap("ShowReconstructions", ::fwData::Boolean::New(state == Qt::Unchecked));
409  }
410 }
411 
412 //------------------------------------------------------------------------------
413 
414 void SModelSeriesList::refreshVisibility()
415 {
416  for( int i = 0; i < m_tree->topLevelItemCount(); ++i )
417  {
418  QTreeWidgetItem* item = m_tree->topLevelItem( i );
419  std::string id = item->data(0, Qt::UserRole).toString().toStdString();
420  ::fwData::Reconstruction::sptr rec = ::fwData::Reconstruction::dynamicCast(::fwTools::fwID::getObject(id));
421  item->setCheckState(0, rec->getIsVisible() ? Qt::Checked : Qt::Unchecked );
422  }
423 }
424 
425 //------------------------------------------------------------------------------
426 
427 void SModelSeriesList::showReconstructions(bool show)
428 {
429  if(m_showCheckBox)
430  {
431  m_showCheckBox->setCheckState(show ? Qt::Unchecked : Qt::Checked );
432  }
433 }
434 
435 //------------------------------------------------------------------------------
436 
438 {
439  KeyConnectionsType connections;
440  connections.push_back( std::make_pair( ::fwMedData::ModelSeries::s_MODIFIED_SIG, s_UPDATE_SLOT ) );
441  connections.push_back( std::make_pair( ::fwMedData::ModelSeries::s_RECONSTRUCTIONS_ADDED_SIG, s_UPDATE_SLOT ) );
442  connections.push_back( std::make_pair( ::fwMedData::ModelSeries::s_RECONSTRUCTIONS_REMOVED_SIG, s_UPDATE_SLOT ) );
443 
444  return connections;
445 }
446 
447 //------------------------------------------------------------------------------
448 
450 {
451  KeyConnectionsMap connections;
452 
453  // FIXME hack to support deprecated getObject() with any key
454  if (this->getInOut< ::fwMedData::ModelSeries >(s_MODEL_SERIES_INOUT))
455  {
456  connections.push(s_MODEL_SERIES_INOUT, ::fwMedData::ModelSeries::s_MODIFIED_SIG, s_UPDATE_SLOT);
457  connections.push(s_MODEL_SERIES_INOUT, ::fwMedData::ModelSeries::s_RECONSTRUCTIONS_ADDED_SIG, s_UPDATE_SLOT);
458  connections.push(s_MODEL_SERIES_INOUT, ::fwMedData::ModelSeries::s_RECONSTRUCTIONS_REMOVED_SIG, s_UPDATE_SLOT);
459  }
460 
461  return connections;
462 }
463 
464 //------------------------------------------------------------------------------
465 
466 void SModelSeriesList::onCheckAllCheckBox()
467 {
468  this->onCheckAllBoxes(true);
469 }
470 
471 //------------------------------------------------------------------------------
472 
473 void SModelSeriesList::onUnCheckAllCheckBox()
474 {
475  this->onCheckAllBoxes(false);
476 }
477 
478 //------------------------------------------------------------------------------
479 
480 void SModelSeriesList::onCheckAllBoxes( bool visible )
481 {
482  for( int i = 0; i < m_tree->topLevelItemCount(); ++i )
483  {
484  QTreeWidgetItem* item = m_tree->topLevelItem( i );
485  item->setCheckState(0, visible ? Qt::Checked : Qt::Unchecked );
486  }
487 }
488 
489 //------------------------------------------------------------------------------
490 
491 } // namespace editor
492 } // namespace uiMedDataQt
#define FW_DEPRECATED_KEY(newKey, access, version)
Use this macro when deprecating a service key to warn the developer.
Definition: spyLog.hpp:366
The namespace uiMedDataQt contains editors for medical data.
This class is a helper to define the connections of a service and its data.
Definition: IService.hpp:454
virtual void configuring() override
Configures the editor.
Defines a helper to modify field on a fwData::Object and create a message notifying this modification...
Definition: Field.hpp:22
#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
virtual UIMEDDATAQT_API KeyConnectionsMap getAutoConnections() const override
Returns proposals to connect service slots to associated object signals, this method is used for obj/...
virtual void updating() override
Perform some computations according to object (this service is attached to) attribute values and its ...
#define SLM_TRACE_FUNC()
Trace contextual function signature.
Definition: spyLog.hpp:329
Defines the service interface managing the editor service for object.
Definition: IEditor.hpp:25
FWDATATOOLS_API void addOrSwap(const ::fwData::Object::FieldNameType &_name,::fwData::Object::sptr _obj)
Add or replace a field in the object.
Definition: Field.cpp:97
virtual void swapping() override
Swap the service from associated object to another object.
virtual UIMEDDATAQT_API ~SModelSeriesList() noexcept
Destructor. Do nothing.
std::pair< bool, std::string > AttributePair
Defines the attribute pair type.
virtual void starting() override
This method launches the IEditor::starting method.
#define SLM_WARN(message)
Definition: spyLog.hpp:261
void onCurrentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous)
Slot called when new current item is setted in m_organChoice.
static FWMEDDATA_APIconst::fwCom::Signals::SignalKeyType s_RECONSTRUCTIONS_ADDED_SIG
Key in m_signals map of signal m_sigReconstructionsAdded.
virtual UIMEDDATAQT_API KeyConnectionsType getObjSrvConnections() const override
Returns proposals to connect service slots to associated object signals, this method is used for obj/...
#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
::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
static FWDATA_APIconst::fwCom::Signals::SignalKeyType s_VISIBILITY_MODIFIED_SIG
Key in m_signals map of signal m_sigVisibilityModified.
static FWDATA_APIconst::fwCom::Signals::SignalKeyType s_MODIFIED_SIG
Key in m_signals map of signal m_sigModified.
Editor displaying the list of the organs in a ModelSeries.
UIMEDDATAQT_API SModelSeriesList() noexcept
Constructor. Do nothing.
virtual void stopping() override
This method launches the IEditor::stopping method.
static FWMEDDATA_APIconst::fwCom::Signals::SignalKeyType s_RECONSTRUCTIONS_REMOVED_SIG
Key in m_signals map of signal m_sigReconstructionsRemoved.
static FWTOOLS_API std::shared_ptr< ::fwTools::Object > getObject(IDType requestID)
Retrieve the object attached to the given id. Return a null sptr if no correspondence exist...
Definition: fwID.cpp:117