ctkDICOMAppWidget.cpp 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. // std includes
  2. #include <iostream>
  3. #include <dcmimage.h>
  4. // Qt includes
  5. #include <QDebug>
  6. #include <QTreeView>
  7. #include <QTabBar>
  8. #include <QSettings>
  9. #include <QAction>
  10. #include <QModelIndex>
  11. #include <QCheckBox>
  12. // ctkDICOMCore includes
  13. #include "ctkDICOMDatabase.h"
  14. #include "ctkDICOMIndexer.h"
  15. // ctkDICOMWidgets includes
  16. #include "ctkDICOMImage.h"
  17. #include "ctkDICOMModel.h"
  18. #include "ctkDICOMAppWidget.h"
  19. #include "ctkDICOMQueryResultsTabWidget.h"
  20. #include "ui_ctkDICOMAppWidget.h"
  21. #include "ctkDirectoryButton.h"
  22. #include "ctkFileDialog.h"
  23. #include "ctkDICOMQueryRetrieveWidget.h"
  24. #include "ctkDICOMImportWidget.h"
  25. //logger
  26. #include <ctkLogger.h>
  27. static ctkLogger logger("org.commontk.DICOM.Widgets.ctkDICOMAppWidget");
  28. //----------------------------------------------------------------------------
  29. class ctkDICOMAppWidgetPrivate: public Ui_ctkDICOMAppWidget
  30. {
  31. public:
  32. ctkDICOMAppWidgetPrivate();
  33. ctkFileDialog* ImportDialog;
  34. ctkDICOMQueryRetrieveWidget* QueryRetrieveWidget;
  35. QSharedPointer<ctkDICOMDatabase> DICOMDatabase;
  36. ctkDICOMModel DICOMModel;
  37. QSharedPointer<ctkDICOMIndexer> DICOMIndexer;
  38. };
  39. //----------------------------------------------------------------------------
  40. // ctkDICOMAppWidgetPrivate methods
  41. ctkDICOMAppWidgetPrivate::ctkDICOMAppWidgetPrivate(){
  42. DICOMDatabase = QSharedPointer<ctkDICOMDatabase> (new ctkDICOMDatabase);
  43. DICOMIndexer = QSharedPointer<ctkDICOMIndexer> (new ctkDICOMIndexer);
  44. }
  45. //----------------------------------------------------------------------------
  46. // ctkDICOMAppWidget methods
  47. //----------------------------------------------------------------------------
  48. ctkDICOMAppWidget::ctkDICOMAppWidget(QWidget* _parent):Superclass(_parent),
  49. d_ptr(new ctkDICOMAppWidgetPrivate)
  50. {
  51. Q_D(ctkDICOMAppWidget);
  52. d->setupUi(this);
  53. //Enable sorting in tree view
  54. d->treeView->setSortingEnabled(true);
  55. //Set toolbar button style
  56. d->toolBar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
  57. //Initialize Q/R widget
  58. d->QueryRetrieveWidget = new ctkDICOMQueryRetrieveWidget();
  59. d->QueryRetrieveWidget->setWindowModality ( Qt::ApplicationModal );
  60. //initialize directory from settings, then listen for changes
  61. QSettings settings;
  62. if ( settings.value("DatabaseDirectory", "") == "" )
  63. {
  64. QString directory = QString("./ctkDICOM-Database");
  65. settings.setValue("DatabaseDirectory", directory);
  66. settings.sync();
  67. }
  68. QString databaseDirectory = settings.value("DatabaseDirectory").toString();
  69. this->setDatabaseDirectory(databaseDirectory);
  70. d->directoryButton->setDirectory(databaseDirectory);
  71. connect(d->directoryButton, SIGNAL(directoryChanged(const QString&)), this, SLOT(setDatabaseDirectory(const QString&)));
  72. //Initialize import widget
  73. d->ImportDialog = new ctkFileDialog();
  74. QCheckBox* importCheckbox = new QCheckBox("Copy on import", d->ImportDialog);
  75. d->ImportDialog->setBottomWidget(importCheckbox);
  76. d->ImportDialog->setFileMode(QFileDialog::Directory);
  77. d->ImportDialog->setLabelText(QFileDialog::Accept,"Import");
  78. d->ImportDialog->setWindowTitle("Import DICOM files from directory ...");
  79. d->ImportDialog->setWindowModality(Qt::ApplicationModal);
  80. //Set thumbnails width in thumbnail widget
  81. //d->thumbnailsWidget->setThumbnailWidth(128);
  82. //Test add thumbnails
  83. //d->thumbnailsWidget->addTestThumbnail();
  84. //connect signal and slots
  85. connect(d->treeView, SIGNAL(clicked(const QModelIndex&)), this, SLOT(onDICOMModelSelected(const QModelIndex &)));
  86. connect(d->thumbnailsWidget, SIGNAL(selected(const ctkDICOMThumbnailWidget&)), this, SLOT(onThumbnailSelected(const ctkDICOMThumbnailWidget&)));
  87. connect(d->ImportDialog, SIGNAL(fileSelected(QString)),this,SLOT(onImportDirectory(QString)));
  88. connect(d->DICOMDatabase.data(), SIGNAL( databaseChanged() ), &(d->DICOMModel), SLOT( reset() ) );
  89. connect(d->QueryRetrieveWidget, SIGNAL( canceled() ), d->QueryRetrieveWidget, SLOT( hide() ) );
  90. }
  91. //----------------------------------------------------------------------------
  92. ctkDICOMAppWidget::~ctkDICOMAppWidget()
  93. {
  94. Q_D(ctkDICOMAppWidget);
  95. d->QueryRetrieveWidget->deleteLater();
  96. d->ImportDialog->deleteLater();
  97. }
  98. //----------------------------------------------------------------------------
  99. void ctkDICOMAppWidget::setDatabaseDirectory(const QString& directory)
  100. {
  101. Q_D(ctkDICOMAppWidget);
  102. QSettings settings;
  103. settings.setValue("DatabaseDirectory", directory);
  104. settings.sync();
  105. //close the active DICOM database
  106. d->DICOMDatabase->closeDatabase();
  107. //open DICOM database on the directory
  108. QString databaseFileName = directory + QString("/ctkDICOM.sql");
  109. try { d->DICOMDatabase->openDatabase( databaseFileName ); }
  110. catch (std::exception e)
  111. {
  112. std::cerr << "Database error: " << qPrintable(d->DICOMDatabase->lastError()) << "\n";
  113. d->DICOMDatabase->closeDatabase();
  114. return;
  115. }
  116. d->DICOMModel.setDatabase(d->DICOMDatabase->database());
  117. d->treeView->setModel(&d->DICOMModel);
  118. //pass DICOM database instance to Import widget
  119. // d->ImportDialog->setDICOMDatabase(d->DICOMDatabase);
  120. d->QueryRetrieveWidget->setRetrieveDatabase(d->DICOMDatabase);
  121. }
  122. //----------------------------------------------------------------------------
  123. QString ctkDICOMAppWidget::databaseDirectory() const
  124. {
  125. QSettings settings;
  126. return settings.value("DatabaseDirectory").toString();
  127. }
  128. void ctkDICOMAppWidget::onAddToDatabase()
  129. {
  130. //Q_D(ctkDICOMAppWidget);
  131. //d->
  132. }
  133. //----------------------------------------------------------------------------
  134. void ctkDICOMAppWidget::openImportDialog()
  135. {
  136. Q_D(ctkDICOMAppWidget);
  137. d->ImportDialog->show();
  138. d->ImportDialog->raise();
  139. }
  140. //----------------------------------------------------------------------------
  141. void ctkDICOMAppWidget::openExportDialog()
  142. {
  143. }
  144. //----------------------------------------------------------------------------
  145. void ctkDICOMAppWidget::openQueryDialog()
  146. {
  147. Q_D(ctkDICOMAppWidget);
  148. d->QueryRetrieveWidget->show();
  149. d->QueryRetrieveWidget->raise();
  150. }
  151. //----------------------------------------------------------------------------
  152. void ctkDICOMAppWidget::onDICOMModelSelected(const QModelIndex& index)
  153. {
  154. Q_D(ctkDICOMAppWidget);
  155. QModelIndex index0 = index.sibling(index.row(), 0);
  156. if ( d->DICOMModel.data(index0,ctkDICOMModel::TypeRole) == ctkDICOMModel::SeriesType )
  157. {
  158. qDebug() << "Clicked on series";
  159. QStringList thumbnails;
  160. QString thumbnailPath = d->DICOMDatabase->databaseDirectory() +
  161. "/thumbs/" + d->DICOMModel.data(index0.parent() ,ctkDICOMModel::UIDRole).toString() + "/" +
  162. d->DICOMModel.data(index0 ,ctkDICOMModel::UIDRole).toString() + "/";
  163. QModelIndex studyIndex = index0.parent();
  164. QModelIndex seriesIndex = index0;
  165. d->DICOMModel.fetchMore(index0);
  166. int imageCount = d->DICOMModel.rowCount(index0);
  167. logger.debug(QString("Thumbs: %1").arg(imageCount));
  168. for (int i = 0 ; i < imageCount ; i++ )
  169. {
  170. QModelIndex imageIndex = index0.child(i,0);
  171. QString thumbnail = thumbnailPath + d->DICOMModel.data(imageIndex, ctkDICOMModel::UIDRole).toString() + ".png";
  172. qDebug() << "Thumb: " << thumbnail;
  173. if (QFile(thumbnail).exists())
  174. {
  175. thumbnails << thumbnail;
  176. }
  177. else
  178. {
  179. logger.error("No thumbnail file " + thumbnail);
  180. }
  181. }
  182. d->thumbnailsWidget->setThumbnailFiles(thumbnails);
  183. // thumbnailPath.append("/thumbs/").append(d->DICOMModel.data( studyIndex,ctkDICOMModel::UIDRole).toString() );
  184. // thumbnailPath.append(d->DICOMModel.data( seriesIndex,ctkDICOMModel::UIDRole).toString() );
  185. }
  186. // TODO: this could check the type of the model entries
  187. QString thumbnailPath = d->DICOMDatabase->databaseDirectory();
  188. thumbnailPath.append("/dicom/").append(d->DICOMModel.data(index0.parent().parent() ,ctkDICOMModel::UIDRole).toString());
  189. thumbnailPath.append("/").append(d->DICOMModel.data(index0.parent() ,ctkDICOMModel::UIDRole).toString());
  190. thumbnailPath.append("/").append(d->DICOMModel.data(index0 ,ctkDICOMModel::UIDRole).toString());
  191. //thumbnailPath.append(".png");
  192. if (QFile(thumbnailPath).exists())
  193. {
  194. DicomImage dcmImage( thumbnailPath.toStdString().c_str() );
  195. ctkDICOMImage ctkImage( & dcmImage );
  196. d->imagePreview->clearImages();
  197. d->imagePreview->addImage( ctkImage );
  198. }
  199. else
  200. {
  201. d->imagePreview->clearImages();
  202. }
  203. }
  204. //----------------------------------------------------------------------------
  205. void ctkDICOMAppWidget::onThumbnailSelected(const ctkDICOMThumbnailWidget& widget)
  206. {
  207. //TODO: update previewer
  208. }
  209. //----------------------------------------------------------------------------
  210. void ctkDICOMAppWidget::onImportDirectory(QString directory)
  211. {
  212. Q_D(ctkDICOMAppWidget);
  213. if (QDir(directory).exists())
  214. {
  215. QCheckBox* copyOnImport = qobject_cast<QCheckBox*>(d->ImportDialog->bottomWidget());
  216. QString targetDirectory;
  217. if (copyOnImport->isEnabled())
  218. {
  219. targetDirectory = d->DICOMDatabase->databaseDirectory();
  220. }
  221. d->DICOMIndexer->addDirectory(*d->DICOMDatabase,directory,targetDirectory);
  222. d->DICOMModel.reset();
  223. }
  224. }