fw4spl
ioPacs/src/ioPacs/SQueryEditor.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 "ioPacs/SQueryEditor.hpp"
8 
9 #include <fwGui/dialog/MessageDialog.hpp>
10 
11 #include <fwGuiQt/container/QtContainer.hpp>
12 
13 #include <fwMedData/DicomSeries.hpp>
14 
15 #include <fwMedDataTools/helper/SeriesDB.hpp>
16 
17 #include <fwPacsIO/exceptions/Base.hpp>
18 #include <fwPacsIO/helper/Series.hpp>
19 
20 #include <fwServices/macros.hpp>
21 
22 #include <boost/filesystem/operations.hpp>
23 #include <boost/foreach.hpp>
24 
25 #include <dcmtk/dcmnet/scu.h>
26 
27 #include <QGridLayout>
28 #include <QHBoxLayout>
29 #include <QLabel>
30 
31 namespace ioPacs
32 {
33 
34 fwServicesRegisterMacro( ::fwGui::editor::IEditor, ::ioPacs::SQueryEditor, ::fwMedData::SeriesDB );
35 
36 //------------------------------------------------------------------------------
37 
39 {
40 }
41 //------------------------------------------------------------------------------
42 
44 {
45 }
46 
47 //------------------------------------------------------------------------------
48 
49 void SQueryEditor::info(std::ostream& _sstream )
50 {
51  _sstream << "SQueryEditor::info";
52 }
53 
54 //------------------------------------------------------------------------------
55 
57 {
59 }
60 
61 //------------------------------------------------------------------------------
62 
64 {
67  ::fwGuiQt::container::QtContainer::sptr qtContainer = fwGuiQt::container::QtContainer::dynamicCast(getContainer());
68 
69  // Main Widget
70  QGridLayout* layout = new QGridLayout();
71 
72  m_patientNameLineEdit = new QLineEdit();
73  m_patientNameQueryButton = new QPushButton("Send");
74  layout->addWidget(new QLabel("Patient name:"), 0, 0);
75  layout->addWidget(m_patientNameLineEdit, 0, 1);
76  layout->addWidget(m_patientNameQueryButton, 0, 2);
77 
78  m_beginStudyDateEdit = new QDateEdit();
79  m_beginStudyDateEdit->setDate(QDate::currentDate());
80  m_beginStudyDateEdit->setDisplayFormat("dd.MM.yyyy");
81  m_endStudyDateEdit = new QDateEdit();
82  m_endStudyDateEdit->setDate(QDate::currentDate());
83  m_endStudyDateEdit->setDisplayFormat("dd.MM.yyyy");
84  m_studyDateQueryButton = new QPushButton("Send");
85  QHBoxLayout* dateLayout = new QHBoxLayout();
86  layout->addWidget(new QLabel("Study date:"), 1, 0);
87  layout->addLayout(dateLayout, 1, 1);
88  layout->addWidget(m_studyDateQueryButton, 1, 2);
89  dateLayout->addWidget(m_beginStudyDateEdit);
90  dateLayout->addWidget(m_endStudyDateEdit);
91 
92  //Set layout
93  qtContainer->setLayout(layout);
94 
95  // Connect the signals
96  QObject::connect(m_patientNameLineEdit, SIGNAL(returnPressed()), this, SLOT(queryPatientName()));
97  QObject::connect(m_patientNameQueryButton, SIGNAL(clicked()), this, SLOT(queryPatientName()));
98  QObject::connect(m_studyDateQueryButton, SIGNAL(clicked()), this, SLOT(queryStudyDate()));
99  QObject::connect(m_beginStudyDateEdit, SIGNAL(dateChanged(QDate)), this, SLOT(queryStudyDate()));
100  QObject::connect(m_endStudyDateEdit, SIGNAL(dateChanged(QDate)), this, SLOT(queryStudyDate()));
101 
102  // Create enquirer
103  m_seriesEnquirer = ::fwPacsIO::SeriesEnquirer::New();
104 
105  // Get pacs configuration
106  m_pacsConfiguration = this->getInput< ::fwPacsIO::data::PacsConfiguration>("pacsConfig");
107  SLM_ASSERT("The pacs configuration object sould not be null.", m_pacsConfiguration);
108 }
109 
110 //------------------------------------------------------------------------------
111 
113 {
114  SLM_TRACE_FUNC();
115 
116  // Disconnect the signals
117  QObject::disconnect(m_patientNameLineEdit, SIGNAL(returnPressed()), this, SLOT(queryPatientName()));
118  QObject::disconnect(m_patientNameQueryButton, SIGNAL(clicked()), this, SLOT(queryPatientName()));
119  QObject::disconnect(m_studyDateQueryButton, SIGNAL(clicked()), this, SLOT(queryStudyDate()));
120  QObject::disconnect(m_beginStudyDateEdit, SIGNAL(dateChanged(QDate)), this, SLOT(queryStudyDate()));
121  QObject::disconnect(m_endStudyDateEdit, SIGNAL(dateChanged(QDate)), this, SLOT(queryStudyDate()));
122 
123  this->destroy();
124 }
125 
126 //------------------------------------------------------------------------------
127 
129 {
130  SLM_TRACE_FUNC();
131 }
132 
133 //------------------------------------------------------------------------------
134 
135 void SQueryEditor::queryPatientName()
136 {
137  try
138  {
139  // Initialize connection
140  m_seriesEnquirer->initialize(
141  m_pacsConfiguration->getLocalApplicationTitle(),
142  m_pacsConfiguration->getPacsHostName(),
143  m_pacsConfiguration->getPacsApplicationPort(),
144  m_pacsConfiguration->getPacsApplicationTitle());
145  m_seriesEnquirer->connect();
146  OFList< QRResponse* > responses;
147 
148  // Find series according to patient's name
149  responses = m_seriesEnquirer->findSeriesByPatientName(m_patientNameLineEdit->text().toStdString());
150 
151  // Convert response to DicomSeries
152  ::fwMedData::SeriesDB::ContainerType series =
155 
156  // Check whether the instance number start at 1 or 0
157  for(::fwMedData::Series::sptr s: series)
158  {
159  ::fwMedData::DicomSeries::sptr dicomSeries = ::fwMedData::DicomSeries::dynamicCast(s);
160  SLM_ASSERT("The PACS response should contain only DicomSeries", dicomSeries);
161  const std::string instanceUID = m_seriesEnquirer->findSOPInstanceUID(dicomSeries->getInstanceUID(), 0);
162  dicomSeries->setFirstInstanceNumber((instanceUID.empty() ? 1 : 0));
163  }
164 
165  m_seriesEnquirer->disconnect();
166 
167  this->updateSeriesDB(series);
168  }
169  catch (::fwPacsIO::exceptions::Base& exception)
170  {
171  this->displayErrorMessage(exception.what());
172  }
173 
174 }
175 
176 //------------------------------------------------------------------------------
177 
178 void SQueryEditor::queryStudyDate()
179 {
180  try
181  {
182  m_seriesEnquirer->initialize(
183  m_pacsConfiguration->getLocalApplicationTitle(),
184  m_pacsConfiguration->getPacsHostName(),
185  m_pacsConfiguration->getPacsApplicationPort(),
186  m_pacsConfiguration->getPacsApplicationTitle());
187  m_seriesEnquirer->connect();
188  OFList< QRResponse* > responses;
189 
190  // Find series according to study's date
191  responses = m_seriesEnquirer->findSeriesByDate(
192  m_beginStudyDateEdit->date().toString("yyyyMMdd").toStdString(),
193  m_endStudyDateEdit->date().toString("yyyyMMdd").toStdString());
194 
195  // Convert response to DicomSeries
196  ::fwMedData::SeriesDB::ContainerType series =
199 
200  // Check whether the instance number start at 1 or 0
201  for(::fwMedData::Series::sptr s: series)
202  {
203  ::fwMedData::DicomSeries::sptr dicomSeries = ::fwMedData::DicomSeries::dynamicCast(s);
204  SLM_ASSERT("The PACS response should contain only DicomSeries", dicomSeries);
205  const std::string instanceUID = m_seriesEnquirer->findSOPInstanceUID(dicomSeries->getInstanceUID(), 0);
206  dicomSeries->setFirstInstanceNumber((instanceUID.empty() ? 1 : 0));
207  }
208 
209  m_seriesEnquirer->disconnect();
210 
211  this->updateSeriesDB(series);
212  }
213  catch (::fwPacsIO::exceptions::Base& exception)
214  {
215  this->displayErrorMessage(exception.what());
216  }
217 }
218 
219 //------------------------------------------------------------------------------
220 
221 void SQueryEditor::updateSeriesDB(::fwMedData::SeriesDB::ContainerType series)
222 {
223  ::fwMedData::SeriesDB::sptr seriesDB = this->getInOut< ::fwMedData::SeriesDB >("seriesDB");
224  ::fwMedDataTools::helper::SeriesDB seriesDBHelper(seriesDB);
225 
226  // Delete old series from the SeriesDB
227  seriesDBHelper.clear();
228 
229  // Push new series in the SeriesDB
230  for(const ::fwMedData::Series::sptr& s: series)
231  {
232  ::fwMedData::DicomSeries::sptr dicomSeries = ::fwMedData::DicomSeries::dynamicCast(s);
233  seriesDBHelper.add(dicomSeries);
234  }
235 
236  // Notify th SeriesDB
237  seriesDBHelper.notify();
238 
239 }
240 
241 //------------------------------------------------------------------------------
242 
243 void SQueryEditor::displayErrorMessage(const std::string& message) const
244 {
245  std::stringstream ss;
246  ss << "Unable to connect to the pacs. Please check your configuration: \n"
247  << "Pacs host name: " << m_pacsConfiguration->getPacsHostName() << "\n"
248  << "Pacs application title: " << m_pacsConfiguration->getPacsApplicationTitle() << "\n"
249  << "Pacs port: " << m_pacsConfiguration->getPacsApplicationPort() << "\n";
250 
251  SLM_WARN("Error: " + message);
253  messageBox.setTitle("Error");
254  messageBox.setMessage( ss.str() );
255  messageBox.setIcon(::fwGui::dialog::IMessageDialog::CRITICAL);
256  messageBox.addButton(::fwGui::dialog::IMessageDialog::OK);
257  messageBox.show();
258 }
259 
260 //------------------------------------------------------------------------------
261 
262 } // namespace ioPacs
virtual IOPACS_API void starting() override
Override.
QPointer< QPushButton > m_patientNameQueryButton
Patient Name Query Button.
static FWPACSIO_API DicomSeriesContainer toFwMedData(OFList< QRResponse * > responses)
Convert DCMTK series to fwMedData::DicomSeries.
::fwPacsIO::SeriesEnquirer::sptr m_seriesEnquirer
Series enquirer.
ioPacs contains services use to deal with PACS using DCMTK library.
#define SLM_TRACE_FUNC()
Trace contextual function signature.
Definition: spyLog.hpp:329
virtual FWGUI_API void setMessage(const std::string &msg) override
Set the message.
Defines the service interface managing the editor service for object.
Definition: IEditor.hpp:25
Defines the generic message box for IHM. Use the Delegate design pattern.
FWGUI_API void destroy()
Stops sub-views and toobar services. Destroys view, sub-views and toolbar containers.
::fwPacsIO::data::PacsConfiguration::csptr m_pacsConfiguration
Pacs Configuration object.
QPointer< QDateEdit > m_endStudyDateEdit
End study date widget.
IOPACS_API SQueryEditor() noexcept
Constructor.
Defines an helper to modify an fwMedData::SeriesDB and create in parallel the message to announce thi...
#define SLM_WARN(message)
Definition: spyLog.hpp:261
virtual IOPACS_API void stopping() override
Override.
virtual FWGUI_API void addButton(IMessageDialog::Buttons button) override
Add a button (OK, YES_NO, YES, NO, CANCEL)
This editor service is used to perform a IOPACS query on a pacs.
virtual FWGUI_API IMessageDialog::Buttons show() override
Show the message box and return the clicked button.
virtual IOPACS_API ~SQueryEditor() noexcept
Destructor.
#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
IOPACS_API void displayErrorMessage(const std::string &message) const
Display an error message.
FWGUI_API void create()
Creates view, sub-views and toolbar containers. Manages sub-views and toobar services.
virtual FWGUI_API void setIcon(IMessageDialog::Icons icon) override
Set the icon (CRITICAL, WARNING, INFO or QUESTION)
QPointer< QLineEdit > m_patientNameLineEdit
Patient Name Field.
QPointer< QPushButton > m_studyDateQueryButton
Study Date Query Button.
IOPACS_API void updating() override
Override.
virtual IOPACS_API void configuring() override
Configuring method. This method is used to configure the service.
IOPACS_API void info(std::ostream &_sstream) override
Override.
QPointer< QDateEdit > m_beginStudyDateEdit
Begin study date widget.
virtual FWGUI_API void setTitle(const std::string &title) override
Set the title of the message box.
FWGUI_API void initialize()
Initialize managers.
static FWPACSIO_API void releaseResponses(OFList< QRResponse * > responses)
Release the responses.