CustusX  2023.01.05-dev+develop.0da12
An IGT application
cxDicomWidget.cpp
Go to the documentation of this file.
1 /*=========================================================================
2 This file is part of CustusX, an Image Guided Therapy Application.
3 
4 Copyright (c) SINTEF Department of Medical Technology.
5 All rights reserved.
6 
7 CustusX is released under a BSD 3-Clause license.
8 
9 See Lisence.txt (https://github.com/SINTEFMedtek/CustusX/blob/master/License.txt) for details.
10 =========================================================================*/
11 
12 #include <QApplication>
13 #include <QDesktopWidget>
14 #include <QDir>
15 #undef REGISTERED
16 #include "ctkServiceTracker.h"
17 #include "ctkDICOMBrowser.h"
18 #include "ctkDICOMAppWidget.h"
19 #include "cxDICOMAppWidget.h"
20 #include "ctkDICOMTableManager.h"
21 #include "ctkDICOMObjectListWidget.h"
22 #include "ctkPluginContext.h"
23 #include "cxDicomWidget.h"
24 #include "cxProfile.h"
25 #include "cxTypeConversions.h"
26 #include "cxDicomConverter.h"
27 #include "cxLogger.h"
28 
29 #include "cxPatientModelService.h"
30 #include "cxDicomImageReader.h"
31 #include "cxVisServices.h"
32 #include "cxViewService.h"
33 #include "cxSettings.h"
34 
35 namespace cx
36 {
37 
38 DicomWidget::DicomWidget(ctkPluginContext *context, QWidget *parent) :
39  BaseWidget(parent, "dicom_widget", "DICOM"),
40  mVerticalLayout(new QVBoxLayout(this)),
41  mBrowser(NULL),
42  mContext(context),
43  mDicomShowAdvancedSettingsString("Dicom/ShowAdvanced")
44 {
45  this->setModified();
46 
47 }
48 
50 {
51  this->deleteDICOMDB();
52 }
53 
55 {
56  if (!mBrowser)
57  {
58  this->createUI();
59  }
60 }
61 
62 void DicomWidget::createUI()
63 {
64  if (mBrowser)
65  return;
66 
67  this->setToolTip("Import DICOM data");
68 
69  mViewHeaderAction = this->createAction(this,
70  QIcon(":/icons/open_icon_library/eye.png.png"),
71  "View info", "View the header info for the first selected series",
72  SLOT(onViewHeader()));
73 
74  mImportIntoCustusXAction = this->createAction(this,
75  QIcon(":/icons/open_icon_library/arrow-right-3.png"),
76  "Import selected", "Import the selected DICOM series into the application as a volume",
77  SLOT(onImportIntoCustusXAction()));
78 
79  mDetailsAction = this->createAction(this,
80  QIcon(":/icons/open_icon_library/system-run-5.png"),
81  "Advanced", "Toggle advanced options",
82  SLOT(toggleDetailsSlot()));
83 
84  mBrowser = new DICOMAppWidget;
85  mBrowser->addActionToToolbar(mViewHeaderAction);
86  mBrowser->addActionToToolbar(mImportIntoCustusXAction);
87  mBrowser->addActionToToolbar(mDetailsAction);
88  this->showOrHideDetails();
89 
90  mVerticalLayout->setMargin(0);
91  mVerticalLayout->addWidget(mBrowser);
92 
93  this->setupDatabaseDirectory();
94 }
95 
96 void DicomWidget::toggleDetailsSlot()
97 {
98  bool newShowAdvancedValue = !settings()->value(mDicomShowAdvancedSettingsString, "true").toBool();
99  settings()->setValue(mDicomShowAdvancedSettingsString, newShowAdvancedValue);
100  this->showOrHideDetails();
101 }
102 
103 void DicomWidget::showOrHideDetails()
104 {
105  bool showAdvanced = settings()->value(mDicomShowAdvancedSettingsString).toBool();
106 
107  mViewHeaderAction->setVisible(showAdvanced);
108  foreach (QAction* action, mBrowser->getAdvancedActions())
109  {
110  action->setVisible(showAdvanced);
111  }
112 }
113 
114 
116 {
117  QString databaseDirectory = profile()->getSettingsPath() + "/DICOMDatabase";
118 
119  return databaseDirectory;
120 }
121 
122 void DicomWidget::setupDatabaseDirectory()
123 {
124  QString databaseDirectory = this->getDICOMDatabaseDirectory();
125 
126  QDir qdir(databaseDirectory);
127  if ( !qdir.exists(databaseDirectory) )
128  {
129  if ( !qdir.mkpath(databaseDirectory) )
130  {
131  CX_LOG_CHANNEL_ERROR("dicom") << "Could not create database directory \"" << databaseDirectory;
132  }
133  }
134 
135  CX_LOG_CHANNEL_INFO("dicom") << "DatabaseDirectory set to: " << databaseDirectory;
136  mBrowser->setDatabaseDirectory(databaseDirectory);
137 }
138 
139 QStringList DicomWidget::currentSeriesSelection()
140 {
141  return mBrowser->getSelectedSeries();
142 }
143 
144 void DicomWidget::onViewHeader()
145 {
146  QStringList series = this->currentSeriesSelection();
147  std::cout << series.join("\n").toStdString() << std::endl;
148 
149  QStringList files;
150  for (int i=0; i<series.size(); ++i)
151  {
152  QStringList current = this->getDatabase()->filesForSeries(series[i]);
153  files.append(current);
154  }
155  files.sort();
156 
157  ctkDICOMObjectListWidget* window = new ctkDICOMObjectListWidget;
158  window->setWindowTitle("DICOM File Header");
159  window->setFileList(files);
160 
161  QWidget* screen = qApp->desktop()->screen(qApp->desktop()->screenNumber(this));
162  QRect rect = screen->geometry();
163  rect.setWidth(rect.width()*0.66);
164  window->setGeometry(rect);
165 
166  window->show();
167 }
168 
169 void DicomWidget::onImportIntoCustusXAction()
170 {
171  QStringList series = this->currentSeriesSelection();
172 
173  if (series.empty())
174  CX_LOG_CHANNEL_WARNING("dicom") << "No DICOM series selected, import failed.";
175 
176  for (unsigned i=0; i<series.size(); ++i)
177  {
178  this->importSeries(series[i]);
179  }
180 }
181 
182 void DicomWidget::deleteDICOMDB()
183 {
184  CX_LOG_CHANNEL_INFO("dicom") << "Deleting DICOM database: " << this->getDICOMDatabaseDirectory();
185  bool autoDeleteDICOMDB = settings()->value("Automation/autoDeleteDICOMDatabase").toBool();
186  if(autoDeleteDICOMDB)
187  {
188  ctkDICOMDatabase* database = this->getDatabase();
189  if(database)
190  {
191  QStringList patients = database->patients();
192  foreach(QString patient , patients)
193  {
194  this->getDatabase()->removePatient(patient);
195  }
196  }
197  }
198 }
199 
200 void DicomWidget::importSeries(QString seriesUid)
201 {
202  cx::DicomConverter converter;
203  converter.setDicomDatabase(this->getDatabase());
204  cx::ImagePtr convertedImage = converter.convertToImage(seriesUid);
205 
206  if (!convertedImage)
207  {
208  reportError(QString("Failed to convert DICOM series %1").arg(seriesUid));
209  return;
210  }
211 
212  this->loadIntoPatientModel(convertedImage, seriesUid);
213 }
214 
215 void DicomWidget::loadIntoPatientModel(ImagePtr image, QString seriesUid)
216 {
217  VisServicesPtr services = VisServices::create(mContext);
218 
219  if (!services->patient()->isNull())
220  {
221  services->patient()->insertData(image);
222  services->view()->autoShowData(image);
223  report(QString("Loaded DICOM series %1 as %2").arg(seriesUid).arg(image->getName()));
224  }
225  else
226  {
227  reportWarning(QString("Failed to load DICOM series %1 as %2: no PatientModelService.").arg(seriesUid).arg(image->getName()));
228  }
229 }
230 
231 ctkDICOMDatabase* DicomWidget::getDatabase() const
232 {
233  if(mBrowser)
234  return mBrowser->database();
235  else
236  return NULL;
237 }
238 
239 } /* namespace cx */
#define CX_LOG_CHANNEL_INFO(channel)
Definition: cxLogger.h:108
cxResource_EXPORT ProfilePtr profile()
Definition: cxProfile.cpp:160
QStringList getSelectedSeries()
void reportError(QString msg)
Definition: cxLogger.cpp:71
boost::shared_ptr< class VisServices > VisServicesPtr
Definition: cxMainWindow.h:40
ctkDICOMDatabase * database()
virtual void prePaintEvent()
boost::shared_ptr< class Image > ImagePtr
Definition: cxDicomWidget.h:27
void setDicomDatabase(ctkDICOMDatabase *database)
static VisServicesPtr create(ctkPluginContext *context)
void addActionToToolbar(QAction *action)
#define CX_LOG_CHANNEL_WARNING(channel)
Definition: cxLogger.h:110
QVariant value(const QString &key, const QVariant &defaultValue=QVariant()) const
Definition: cxSettings.cpp:66
DicomWidget(ctkPluginContext *context, QWidget *parent=0)
QAction * createAction(QObject *parent, QIcon iconName, QString text, QString tip, T slot, QLayout *layout=NULL, QToolButton *button=new QToolButton())
Definition: cxBaseWidget.h:129
void setValue(const QString &key, const QVariant &value)
Definition: cxSettings.cpp:58
ImagePtr convertToImage(QString seriesUid)
void reportWarning(QString msg)
Definition: cxLogger.cpp:70
Settings * settings()
Shortcut for accessing the settings instance.
Definition: cxSettings.cpp:21
QString getDICOMDatabaseDirectory()
ctkDICOMDatabase * getDatabase() const
Interface for QWidget which handles widgets uniformly for the system.
Definition: cxBaseWidget.h:88
void report(QString msg)
Definition: cxLogger.cpp:69
QList< QAction * > getAdvancedActions() const
virtual ~DicomWidget()
void setDatabaseDirectory(const QString &directory)
#define CX_LOG_CHANNEL_ERROR(channel)
Definition: cxLogger.h:111
Namespace for all CustusX production code.