fw4spl
SDicomSeriesDBReader.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 "ioGdcm/SDicomSeriesDBReader.hpp"
8 
9 #include <fwCom/Signal.hxx>
10 
11 #include <fwData/mt/ObjectWriteLock.hpp>
12 
13 #include <fwGdcmIO/reader/SeriesDB.hpp>
14 
15 #include <fwGui/Cursor.hpp>
16 #include <fwGui/dialog/LocationDialog.hpp>
17 #include <fwGui/dialog/LoggerDialog.hpp>
18 #include <fwGui/dialog/MessageDialog.hpp>
19 
20 #include <fwIO/IReader.hpp>
21 
22 #include <fwJobs/IJob.hpp>
23 #include <fwJobs/Observer.hpp>
24 
25 #include <fwMedData/SeriesDB.hpp>
26 
27 #include <fwMedDataTools/helper/SeriesDB.hpp>
28 
29 #include <fwServices/macros.hpp>
30 
31 #include <fwTools/System.hpp>
32 
33 #include <string>
34 #include <vector>
35 
36 namespace ioGdcm
37 {
38 
39 fwServicesRegisterMacro( ::fwIO::IReader, ::ioGdcm::SDicomSeriesDBReader, ::fwMedData::SeriesDB );
40 
41 static const ::fwCom::Signals::SignalKeyType JOB_CREATED_SIGNAL = "jobCreated";
42 
43 //------------------------------------------------------------------------------
44 
46  m_cancelled(false),
47  m_showLogDialog(true),
48  m_dicomDirSupport(USER_SELECTION)
49 {
50  m_sigJobCreated = newSignal<JobCreatedSignal>(JOB_CREATED_SIGNAL);
51 }
52 
53 //------------------------------------------------------------------------------
54 
56 {
57 }
58 
59 //------------------------------------------------------------------------------
60 
62 {
64 
65  // Show log dialog
66  ::fwRuntime::ConfigurationElement::sptr logDialog = m_configuration->findConfigurationElement("showLogDialog");
67  if(logDialog)
68  {
69  std::string logDialogStr = logDialog->getValue();
70  SLM_ASSERT("<showLogDialog> value must be 'yes' or 'no'", logDialogStr == "yes" || logDialogStr == "no");
71  m_showLogDialog = (logDialogStr == "yes");
72  }
73 
74  // Enable dicomdir
75  ::fwRuntime::ConfigurationElement::sptr dicomDir = m_configuration->findConfigurationElement("dicomdirSupport");
76  if(dicomDir)
77  {
78  std::string dicomDirStr = dicomDir->getValue();
79  SLM_ASSERT("<dicomdirSupport> value must be 'always' or 'never' or 'user_selection'",
80  dicomDirStr == "always" || dicomDirStr == "never" || dicomDirStr == "user_selection");
81 
82  if(dicomDirStr == "always")
83  {
84  m_dicomDirSupport = ALWAYS;
85  }
86  else if(dicomDirStr == "never")
87  {
88  m_dicomDirSupport = NEVER;
89  }
90  else if(dicomDirStr == "user_selection")
91  {
92  m_dicomDirSupport = USER_SELECTION;
93  }
94  }
95 }
96 
97 //------------------------------------------------------------------------------
98 
100 {
101  static ::boost::filesystem::path _sDefaultPath;
102 
104  dialogFile.setTitle(m_windowTitle.empty() ? this->getSelectorDialogTitle() : m_windowTitle);
105  dialogFile.setDefaultLocation( ::fwData::location::Folder::New(_sDefaultPath) );
106  dialogFile.setOption(::fwGui::dialog::ILocationDialog::READ);
107  dialogFile.setType(::fwGui::dialog::LocationDialog::FOLDER);
108 
109  ::fwData::location::Folder::sptr result;
110  result = ::fwData::location::Folder::dynamicCast( dialogFile.show() );
111  if (result)
112  {
113  _sDefaultPath = result->getFolder();
114  this->setFolder( result->getFolder() );
115  dialogFile.saveDefaultLocation( ::fwData::location::Folder::New(_sDefaultPath) );
116  }
117 }
118 
119 //------------------------------------------------------------------------------
120 
122 {
123 }
124 
125 //------------------------------------------------------------------------------
126 
128 {
129 }
130 
131 //------------------------------------------------------------------------------
132 
133 void SDicomSeriesDBReader::info(std::ostream& _sstream )
134 {
135  _sstream << "SDicomSeriesDBReader::info";
136 }
137 
138 //------------------------------------------------------------------------------
139 
141 {
142  return "Choose a directory with DICOM images";
143 }
144 
145 //------------------------------------------------------------------------------
146 
147 ::fwMedData::SeriesDB::sptr SDicomSeriesDBReader::createSeriesDB(const ::boost::filesystem::path& dicomDir)
148 {
149  ::fwGdcmIO::reader::SeriesDB::sptr reader = ::fwGdcmIO::reader::SeriesDB::New();
150  ::fwMedData::SeriesDB::sptr seriesDB = ::fwMedData::SeriesDB::New();
151  reader->setObject(seriesDB);
152  reader->setFolder(dicomDir);
153 
154  auto job = reader->getJob();
155  m_sigJobCreated->emit(job);
156 
157  if(m_dicomDirSupport == USER_SELECTION && reader->isDicomDirAvailable())
158  {
160  messageBox.setTitle("Dicomdir file");
161  messageBox.setMessage( "There is a dicomdir file in the root folder. "
162  "Would you like to use it for the reading process ?" );
163  messageBox.setIcon(::fwGui::dialog::IMessageDialog::QUESTION);
164  messageBox.addButton(::fwGui::dialog::IMessageDialog::YES_NO);
165  ::fwGui::dialog::IMessageDialog::Buttons button = messageBox.show();
166 
167  reader->setDicomdirActivated(button == ::fwGui::dialog::IMessageDialog::YES);
168  }
169  else if(m_dicomDirSupport == ALWAYS)
170  {
171  reader->setDicomdirActivated(true);
172  }
173  else //m_dicomDirSupport == NEVER
174  {
175  reader->setDicomdirActivated(false);
176  }
177 
178  try
179  {
180  reader->readDicomSeries();
181 
182  // Retrieve logger
183  ::fwLog::Logger::sptr logger = reader->getLogger();
184  logger->sort();
185 
186  // Display logger dialog if enabled
187  if(m_showLogDialog && !logger->empty())
188  {
189  std::stringstream ss;
190  if(seriesDB->size() > 1)
191  {
192  ss << "The reading process is over : <b>" << seriesDB->size() << " series</b> have been found. "
193  "<br>Please verify the log report to be informed of the potential errors.";
194  }
195  else
196  {
197  ss << "The reading process is over : <b>" << seriesDB->size() << " series</b> has been found. "
198  "<br>Please verify the log report to be informed of the potential errors.";
199  }
200 
201  bool result = false;
202  if(!reader->getJob()->cancelRequested())
203  {
204  result = ::fwGui::dialog::LoggerDialog::showLoggerDialog("Reading process over", ss.str(), logger);
205  }
206 
207  // If the user cancel the reading process we delete the loaded series
208  if(!result || reader->getJob()->cancelRequested())
209  {
210  ::fwMedDataTools::helper::SeriesDB sDBhelper(seriesDB);
211  sDBhelper.clear();
212  }
213  }
214  }
215  catch (const std::exception& e)
216  {
217  std::stringstream ss;
218  ss << "Warning during loading : " << e.what();
220  "Warning", ss.str(), ::fwGui::dialog::IMessageDialog::WARNING);
221  }
222  catch( ... )
223  {
225  "Warning", "Warning during loading", ::fwGui::dialog::IMessageDialog::WARNING);
226  }
227 
228  m_cancelled = job->cancelRequested();
229 
230  return seriesDB;
231 }
232 
233 //------------------------------------------------------------------------------
234 
236 {
237  if( this->hasLocationDefined() )
238  {
239  ::fwGui::Cursor cursor;
240  cursor.setCursor(::fwGui::ICursor::BUSY);
241 
242  ::fwMedData::SeriesDB::sptr seriesDB = createSeriesDB(this->getFolder() );
243 
244  if( seriesDB->size() > 0 && !m_cancelled)
245  {
246  // Retrieve dataStruct associated with this service
247  ::fwMedData::SeriesDB::sptr associatedSeriesDB =
248  this->getInOut< ::fwMedData::SeriesDB >(::fwIO::s_DATA_KEY);
249  SLM_ASSERT("associated SeriesDB not instanced", associatedSeriesDB);
250 
251  // Clear SeriesDB and add new series
252  ::fwMedDataTools::helper::SeriesDB sDBhelper(associatedSeriesDB);
253  ::fwData::mt::ObjectWriteLock lock(associatedSeriesDB);
254  sDBhelper.clear();
255  // Notify removal.
256  sDBhelper.notify();
257  {
258  ::fwData::mt::ObjectWriteLock lock(seriesDB);
259  associatedSeriesDB->shallowCopy(seriesDB);
260  }
261 
262  ::fwMedData::SeriesDB::ContainerType addedSeries = associatedSeriesDB->getContainer();
263 
264  auto sig = associatedSeriesDB->signal< ::fwMedData::SeriesDB::AddedSeriesSignalType >(
266  sig->asyncEmit(addedSeries);
267  }
268  cursor.setDefaultCursor();
269  }
270 }
271 
272 //-----------------------------------------------------------------------------
273 
275 {
276  return ::fwIO::FOLDER;
277 }
278 
279 //------------------------------------------------------------------------------
280 
281 } // namespace ioGdcm
virtual IOGDCM_API void configuring() override
Configuring method. This method is used to configure the service.
virtual FWGUI_API void setCursor(::fwGui::ICursor::CursorType cursor) override
Set the cursor.
std::string m_windowTitle
Title of the window that will open when the configureWithIHM slot is called.
Definition: IReader.hpp:207
FWIO_API bool hasLocationDefined() const
Returns if a location has been defined ( by the configuration process or directly by user ) ...
Definition: IReader.cpp:233
virtual FWGUI_API void setMessage(const std::string &msg) override
Set the message.
virtual FWIO_API void configuring() override
This method proposes to parse xml configuration to retrieve file/files/folder paths.
Definition: IReader.cpp:144
Defines the generic message box for IHM. Use the Delegate design pattern.
static FWGUI_API IMessageDialog::Buttons showMessageDialog(const std::string &title, const std::string &message,::fwGui::dialog::IMessageDialog::Icons icon=INFO)
IOGDCM_API void updating() override
Override.
virtual IOGDCM_API std::string getSelectorDialogTitle() override
Override.
virtual IOGDCM_API void starting() override
Override.
virtual FWGUI_API void setDefaultLocation(::fwData::location::ILocation::sptr loc) override
Set the initial location for the dialog.
FWGUI_API::fwGui::dialog::ILocationDialog & setOption(::fwGui::dialog::ILocationDialog::Options option) override
allow to set option to the file dialog mode=READ/WRITE, check=FILE_MUST_EXIST
FWGUI_API::fwData::location::ILocation::sptr show() override
Display the dialog.
A helper to lock object on exclusive mode.
FWIO_APIconst::boost::filesystem::path & getFolder() const
Returns folder path set by the user or set during service configuration.
Definition: IReader.cpp:97
Defines an helper to modify an fwMedData::SeriesDB and create in parallel the message to announce thi...
virtual FWGUI_API void addButton(IMessageDialog::Buttons button) override
Add a button (OK, YES_NO, YES, NO, CANCEL)
FWMEDDATATOOLS_API void clear()
Clear all series in the SeriesDB.
virtual IOGDCM_API void stopping() override
Override.
static FWMEDDATA_APIconst::fwCom::Signals::SignalKeyType s_ADDED_SERIES_SIG
Type of signal when series are added.
virtual FWGUI_API IMessageDialog::Buttons show() override
Show the message box and return the clicked button.
IOGDCM_API void info(std::ostream &_sstream) override
Override.
Reader service API. It manages extension points definition and extension configuration.
Definition: IReader.hpp:34
IOGDCM_API::fwIO::IOPathType getIOPathType() const override
Return path type managed by the service, here FOLDER.
#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
Read DicomSeries from DICOM folder with GDCM reader.
IOGDCM_API SDicomSeriesDBReader() noexcept
constructor
::fwRuntime::ConfigurationElement::sptr m_configuration
Configuration element used to configure service internal state using a generic XML like structure TOD...
Definition: IService.hpp:670
virtual IOGDCM_API void configureWithIHM() override
Override.
virtual FWGUI_API void setIcon(IMessageDialog::Icons icon) override
Set the icon (CRITICAL, WARNING, INFO or QUESTION)
IOPathType
IOPathType defines different type of paths used by service readers/writers.
Definition: ioTypes.hpp:19
ioGdcm contains services use to deal with DICOM using the GDCM library.
FWGUI_API void setTitle(const std::string &title) override
Set the title for the dialog.
Defines the generic file/folder selector dialog for IHM.
FWMEDDATATOOLS_API void notify()
Send the signal of modification.
Defines the generic cursor for IHM. Use the Delegate design pattern.
virtual IOGDCM_API ~SDicomSeriesDBReader() noexcept override
destructor
FWIO_API void setFolder(const ::boost::filesystem::path &folder)
Sets folder path.
Definition: IReader.cpp:106
FWGUI_API void setType(::fwGui::dialog::ILocationDialog::Types type) override
Set the type of location for the dialog (SINGLE_FILE, FORLDER, MULTI_FILES)
static FWGUI_API bool showLoggerDialog(const std::string &title, const std::string &message, const ::fwLog::Logger::sptr &logger)
FWGUI_API void saveDefaultLocation(::fwData::location::ILocation::sptr loc) override
Save the specified default location for the dialog in preferences (if available)
virtual FWGUI_API void setTitle(const std::string &title) override
Set the title of the message box.
virtual FWGUI_API void setDefaultCursor() override
Set the default cursor.