CustusX  16.5.0-rc9
An IGT application
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
cxDICOMAppWidget.cpp
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Library: CTK
4 
5  Copyright (c) Kitware Inc.
6 
7  Licensed under the Apache License, Version 2.0 (the "License");
8  you may not use this file except in compliance with the License.
9  You may obtain a copy of the License at
10 
11  http://www.apache.org/licenses/LICENSE-2.0.txt
12 
13  Unless required by applicable law or agreed to in writing, software
14  distributed under the License is distributed on an "AS IS" BASIS,
15  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  See the License for the specific language governing permissions and
17  limitations under the License.
18 
19 =========================================================================*/
20 
21 // std includes
22 #include <iostream>
23 
24 #include <dcmimage.h>
25 
26 // Qt includes
27 #include <QAction>
28 #include <QCoreApplication>
29 #include <QCheckBox>
30 #include <QDebug>
31 #include <QMessageBox>
32 #include <QMetaType>
33 #include <QModelIndex>
34 #include <QPersistentModelIndex>
35 #include <QProgressDialog>
36 #include <QSettings>
37 #include <QSlider>
38 #include <QTabBar>
39 #include <QTimer>
40 #include <QTreeView>
41 #include <QLabel>
42 #include <QHBoxLayout>
43 #include <QSplitter>
44 
45 // ctkWidgets includes
46 #include "ctkDirectoryButton.h"
47 #include "ctkFileDialog.h"
48 
49 // ctkDICOMCore includes
50 #include "ctkDICOMDatabase.h"
51 #include "ctkDICOMFilterProxyModel.h"
52 #include "ctkDICOMIndexer.h"
53 #include "cxDICOMModel.h"
54 
55 // ctkDICOMWidgets includes
56 #include "cxDICOMAppWidget.h"
58 #include "ctkThumbnailLabel.h"
59 #include "ctkDICOMQueryResultsTabWidget.h"
60 #include "ctkDICOMQueryRetrieveWidget.h"
61 #include "ctkDICOMQueryWidget.h"
62 #include <QToolBar>
63 //#include "ctkDICOMThumbnailListWidget.h"
65 
66 
67 #include "cxDicomImporter.h"
68 #include "cxLogger.h"
69 
70 //#include "ui_DICOMAppWidget.h"
71 
72 //logger
73 #include <ctkLogger.h>
74 static ctkLogger logger("org.commontk.DICOM.Widgets.DICOMAppWidget");
75 
76 Q_DECLARE_METATYPE(QPersistentModelIndex);
77 
78 
79 namespace cx
80 {
82 
83 //----------------------------------------------------------------------------
84 class DICOMAppWidgetPrivate: public QWidget
85 {
86 public:
89 
92  void setupUi(DICOMAppWidget* parent);
93 
94  QVBoxLayout* TopLayout;
95  QTreeView* TreeView;
96  QToolBar* ToolBar;
97 // ctkDICOMThumbnailListWidget* ThumbnailsWidget;
100  QAction* ActionImport;
101  QAction* ActionQuery;
102  QAction* ActionRemove;
104 
105  ctkDICOMQueryRetrieveWidget* QueryRetrieveWidget;
106  ctkDICOMQueryRetrieveWidget* getQueryRetrieveWidget();
107 
108  QSharedPointer<ctkDICOMDatabase> DICOMDatabase;
109  QSharedPointer<ctkDICOMThumbnailGenerator> ThumbnailGenerator;
111  ctkDICOMFilterProxyModel DICOMProxyModel;
112  QProgressDialog *UpdateSchemaProgress;
113 
114  void showUpdateSchemaDialog();
115  std::map<ctkDICOMModel::IndexType, QStringList> getSelection() const;
116 
117  void removeSelection();
118 };
119 
120 //----------------------------------------------------------------------------
121 // DICOMAppWidgetPrivate methods
122 
124  q_ptr(parent),
125  TopLayout(NULL),
126  TreeView(NULL),
127  ToolBar(NULL),
128  ThumbnailsWidget(NULL),
129  ThumbnailWidthSlider(NULL),
130  ActionImport(NULL),
131  ActionQuery(NULL),
132  ActionRemove(NULL),
133  QueryRetrieveWidget(NULL)
134 {
135  DICOMDatabase = QSharedPointer<ctkDICOMDatabase> (new ctkDICOMDatabase);
136  ThumbnailGenerator = QSharedPointer <ctkDICOMThumbnailGenerator> (new ctkDICOMThumbnailGenerator);
137  DICOMDatabase->setThumbnailGenerator(ThumbnailGenerator.data());
139 }
140 
142 {
143  if ( UpdateSchemaProgress )
144  {
145  delete UpdateSchemaProgress;
146  }
147 
149  QueryRetrieveWidget->deleteLater();
150 }
151 
153 {
154  Q_Q(DICOMAppWidget);
155 
156  TopLayout = new QVBoxLayout(parent);
157  TopLayout->setMargin(0);
158 
159  ToolBar = new QToolBar;
160  TopLayout->addWidget(ToolBar);
161 
162  ActionImport = new QAction("Open", this);
163  ActionImport->setToolTip("Open and load a DICOM file or folder");
164  q->connect(ActionImport, SIGNAL(triggered()), &Importer, SLOT(openImportDialog()));
165  ToolBar->addAction(ActionImport);
166 
167  ActionQuery = new QAction("Query", this);
168  ActionQuery->setToolTip("Query and Retrieve DICOM studies from a DICOM node");
169  q->connect(ActionQuery, SIGNAL(triggered()), q, SLOT(openQueryDialog()));
170  ToolBar->addAction(ActionQuery);
171 
172  ActionRemove = new QAction("Remove", this);
173  ActionRemove->setToolTip("Remove selection from database");
174  q->connect(ActionRemove, SIGNAL(triggered()), q, SLOT(onRemoveAction()));
175  ToolBar->addAction(ActionRemove);
176 
177  QSplitter* splitter = new QSplitter;
178  splitter->setOrientation(Qt::Vertical);
179  TopLayout->addWidget(splitter);
180 
181  TreeView = new QTreeView;
182  TreeView->setAlternatingRowColors(true);
183  splitter->addWidget(TreeView);
184 
185  QWidget* ThumbnailsFullWidget = new QWidget;
186  splitter->addWidget(ThumbnailsFullWidget);
187  QVBoxLayout* ThumbnailsFullWidgetLayout = new QVBoxLayout(ThumbnailsFullWidget);
188  ThumbnailsFullWidgetLayout->setMargin(0);
189 
191  ThumbnailsWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
192  ThumbnailsWidget->setMinimumSize(QSize(0,200));
193  ThumbnailsFullWidgetLayout->addWidget(ThumbnailsWidget);
194 
195  ThumbnailWidthSlider = new QSlider;
196  ThumbnailWidthSlider->setMinimum(64);
197  ThumbnailWidthSlider->setMaximum(256);
198  ThumbnailWidthSlider->setValue(64);
199  ThumbnailWidthSlider->setOrientation(Qt::Horizontal);
200  connect(ThumbnailWidthSlider, SIGNAL(valueChanged(int)), q, SLOT(onThumbnailWidthSliderValueChanged(int)));
201  ThumbnailsFullWidgetLayout->addWidget(ThumbnailWidthSlider);
202 }
203 
205 {
206  Q_Q(DICOMAppWidget);
207 
208  ctkDICOMDatabase* db = DICOMDatabase.data();
209  q->connect(db, SIGNAL(schemaUpdateStarted(int)), q, SLOT(schemaUpdateStarted(int)));
210  q->connect(db, SIGNAL(schemaUpdateProgress(int)), q, SLOT(schemaUpdateProgress(int)));
211  q->connect(db, SIGNAL(schemaUpdateProgress(QString)), q, SLOT(schemaUpdateProgress(QString)));
212  q->connect(db, SIGNAL(schemaUpdated()), q, SLOT(schemaUpdated()));
213 
214 // if (UpdateSchemaProgress == 0)
215 // {
216 // //
217 // // Set up the Update Schema Progress Dialog
218 // //
219 // UpdateSchemaProgress = new QProgressDialog(
220 // q->tr("DICOM Schema Update"), "Cancel", 0, 100, q,
221 // Qt::WindowTitleHint | Qt::WindowSystemMenuHint);
222 
223 // // We don't want the progress dialog to resize itself, so we bypass the label
224 // // by creating our own
225 // QLabel* progressLabel = new QLabel(q->tr("Initialization..."));
226 // UpdateSchemaProgress->setLabel(progressLabel);
227 // UpdateSchemaProgress->setWindowModality(Qt::ApplicationModal);
228 // UpdateSchemaProgress->setMinimumDuration(0);
229 // UpdateSchemaProgress->setValue(0);
230 
231 // //q->connect(UpdateSchemaProgress, SIGNAL(canceled()),
232 // // DICOMIndexer.data(), SLOT(cancel()));
233 // ctkDICOMDatabase* db = DICOMDatabase.data();
234 
235 // q->connect(db, SIGNAL(schemaUpdateStarted(int)), UpdateSchemaProgress, SLOT(setMaximum(int)));
236 // q->connect(db, SIGNAL(schemaUpdateProgress(int)), UpdateSchemaProgress, SLOT(setValue(int)));
237 // q->connect(db, SIGNAL(schemaUpdateProgress(QString)), progressLabel, SLOT(setText(QString)));
238 // // close the dialog
240 // // reset the database to show new data
241 // q->connect(db, SIGNAL(schemaUpdated()), &mDICOMModel, SLOT(reset()));
242 // // reset the database if canceled
243 // q->connect(UpdateSchemaProgress, SIGNAL(canceled()), &mDICOMModel, SLOT(reset()));
244 
245 
246 // q->connect(db, SIGNAL(schemaUpdateStarted(int)), q, SLOT(schemaUpdateStarted(int)));
247 // q->connect(db, SIGNAL(schemaUpdateProgress(int)), q, SLOT(schemaUpdateProgress(int)));
248 // q->connect(db, SIGNAL(schemaUpdateProgress(QString)), q, SLOT(schemaUpdateProgress(QString)));
249 // q->connect(db, SIGNAL(schemaUpdated()), q, SLOT(schemaUpdated()));
250 // }
251 // UpdateSchemaProgress->show();
252 }
253 
254 void DICOMAppWidget::schemaUpdateStarted(int)
255 {
256 // report("DICOM schema update started...");
257 }
258 void DICOMAppWidget::schemaUpdateProgress(QString val)
259 {
260 }
261 void DICOMAppWidget::schemaUpdateProgress(int val)
262 {
263 }
264 void DICOMAppWidget::schemaUpdated()
265 {
266 // report("DICOM schema updated");
267 }
268 
270 {
271  QModelIndexList selection = TreeView->selectionModel()->selectedIndexes();
272  QModelIndex index;
273 
274  foreach(index,selection)
275  {
276  if (index.column()!=0)
277  continue;
278  mDICOMModel.removeRows(index.row(), 1, index.parent());
279 // this->remove(index);
280  }
281 }
282 
283 std::map<ctkDICOMModel::IndexType, QStringList> DICOMAppWidgetPrivate::getSelection() const
284 {
285 // Q_Q(DICOMAppWidget);
286  std::map<ctkDICOMModel::IndexType, QStringList> retval;
287  QModelIndexList selection = TreeView->selectionModel()->selectedIndexes();
288  QModelIndex index;
289 
290  foreach(index,selection)
291  {
292  QModelIndex index0 = index.sibling(index.row(), 0);
294  QString uid = mDICOMModel.data(index0,ctkDICOMModel::UIDRole).toString();
295 
296  retval[type] << uid;
297  retval[type].removeDuplicates();
298  }
299 
300  return retval;
301 }
302 
303 //----------------------------------------------------------------------------
304 ctkDICOMQueryRetrieveWidget* DICOMAppWidgetPrivate::getQueryRetrieveWidget()
305 {
306  if (!QueryRetrieveWidget)
307  {
308  Q_Q(DICOMAppWidget);
309  //Initialize Q/R widget
310  QueryRetrieveWidget = new ctkDICOMQueryRetrieveWidget();
311  QueryRetrieveWidget->setWindowModality(Qt::ApplicationModal);
312 
313  connect(QueryRetrieveWidget, SIGNAL(canceled()), QueryRetrieveWidget, SLOT(hide()) );
314  connect(QueryRetrieveWidget, SIGNAL(canceled()), q, SLOT(onQueryRetrieveFinished()) );
315 
316  QueryRetrieveWidget->setRetrieveDatabase(DICOMDatabase);
317  }
318 
319  return QueryRetrieveWidget;
320 }
321 
322 //----------------------------------------------------------------------------
323 // DICOMAppWidget methods
324 
325 //----------------------------------------------------------------------------
326 DICOMAppWidget::DICOMAppWidget(QWidget* _parent):Superclass(_parent),
327  d_ptr(new DICOMAppWidgetPrivate(this))
328 {
329  Q_D(DICOMAppWidget);
330 
331  d->setupUi(this);
332 
333  connect(&d->Importer, SIGNAL(indexingCompleted()),
334  &d->mDICOMModel, SLOT(reset()));
335  connect(&d->Importer, SIGNAL(directoryImported()),
336  this, SIGNAL(directoryImported()));
337 
338  //Enable sorting in tree view
339  d->TreeView->setSortingEnabled(true);
340  d->TreeView->setSelectionBehavior(QAbstractItemView::SelectRows);
341  d->TreeView->setSelectionMode(QAbstractItemView::ExtendedSelection);
342  d->DICOMProxyModel.setSourceModel(&d->mDICOMModel);
343  d->TreeView->setModel(&d->mDICOMModel);
344 
345  d->ThumbnailsWidget->setThumbnailSize(
346  QSize(d->ThumbnailWidthSlider->value(), d->ThumbnailWidthSlider->value()));
347 
348  // Treeview signals
349  connect(d->TreeView, SIGNAL(collapsed(QModelIndex)), this, SLOT(onTreeCollapsed(QModelIndex)));
350  connect(d->TreeView, SIGNAL(expanded(QModelIndex)), this, SLOT(onTreeExpanded(QModelIndex)));
351 
352  //Set ToolBar button style
353  d->ToolBar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
354 
355 // //Initialize Q/R widget
356 // d->QueryRetrieveWidget = new ctkDICOMQueryRetrieveWidget();
357 // d->QueryRetrieveWidget->setWindowModality ( Qt::ApplicationModal );
358 
359  connect(d->TreeView->selectionModel(),
360  &QItemSelectionModel::selectionChanged,
361  this,
363  connect(d->TreeView->selectionModel(),
364  &QItemSelectionModel::currentChanged,
365  this,
367 
368  //connect signal and slots
369  connect(d->TreeView, SIGNAL(clicked(QModelIndex)), this, SLOT(onModelSelected(QModelIndex)));
370 
371 // connect(d->QueryRetrieveWidget, SIGNAL(canceled()), d->QueryRetrieveWidget, SLOT(hide()) );
372 // connect(d->QueryRetrieveWidget, SIGNAL(canceled()), this, SLOT(onQueryRetrieveFinished()) );
373 }
374 
375 //----------------------------------------------------------------------------
377 {
378  Q_D(DICOMAppWidget);
379 
380 // d->QueryRetrieveWidget->deleteLater();
381 }
382 
383 //----------------------------------------------------------------------------
385 {
386  Q_D(DICOMAppWidget);
387  return d->Importer.displayImportSummary();
388 }
389 
390 //----------------------------------------------------------------------------
392 {
393  Q_D(DICOMAppWidget);
394  return d->Importer.setDisplayImportSummary(onOff);
395 }
396 
397 //----------------------------------------------------------------------------
399 {
400  Q_D(DICOMAppWidget);
401  return d->Importer.patientsAddedDuringImport();
402 }
403 
404 //----------------------------------------------------------------------------
406 {
407  Q_D(DICOMAppWidget);
408  return d->Importer.studiesAddedDuringImport();
409 }
410 
411 //----------------------------------------------------------------------------
413 {
414  Q_D(DICOMAppWidget);
415  return d->Importer.seriesAddedDuringImport();
416 }
417 
418 //----------------------------------------------------------------------------
420 {
421  Q_D(DICOMAppWidget);
422  return d->Importer.instancesAddedDuringImport();
423 }
424 
425 //----------------------------------------------------------------------------
427 {
428  Q_D(DICOMAppWidget);
429 
430  d->showUpdateSchemaDialog();
431  d->DICOMDatabase->updateSchemaIfNeeded();
432 }
433 
434 //----------------------------------------------------------------------------
435 void DICOMAppWidget::setDatabaseDirectory(const QString& directory)
436 {
437  Q_D(DICOMAppWidget);
438 
439  QSettings settings;
440  settings.setValue("DatabaseDirectory", directory);
441  settings.sync();
442 
443  //close the active DICOM database
444  d->DICOMDatabase->closeDatabase();
445 
446  //open DICOM database on the directory
447  QString databaseFileName = directory + QString("/ctkDICOM.sql");
448  try
449  {
450  d->DICOMDatabase->openDatabase( databaseFileName );
451 
452  CX_LOG_CHANNEL_INFO("dicom") << "Open Database " << databaseFileName.toStdString() << ", open= " << d->DICOMDatabase->isOpen();
453 // std::cout << "open database " << databaseFileName.toStdString() << ", open= " << d->DICOMDatabase->isOpen() << std::endl;
454  }
455  catch (std::exception& e)
456  {
457  CX_LOG_CHANNEL_ERROR("dicom") << "Database error: " << qPrintable(d->DICOMDatabase->lastError());
458 // std::cerr << "Database error: " << qPrintable(d->DICOMDatabase->lastError()) << "\n";
459  d->DICOMDatabase->closeDatabase();
460  return;
461  }
462 
463  // update the database schema if needed and provide progress
465 
466  d->mDICOMModel.setDatabase(d->DICOMDatabase);
467  d->mDICOMModel.setEndLevel(ctkDICOMModel::SeriesType);
468  d->TreeView->resizeColumnToContents(0);
469  d->Importer.setDatabase(d->DICOMDatabase);
470 
471 // d->getQueryRetrieveWidget()->setRetrieveDatabase(d->DICOMDatabase);
472  d->ThumbnailsWidget->setDatabaseDirectory(directory);
473  d->ThumbnailsWidget->setDatabase(d->DICOMDatabase);
474  emit databaseDirectoryChanged(directory);
475 }
476 
477 //----------------------------------------------------------------------------
479 {
480  QSettings settings;
481  return settings.value("DatabaseDirectory").toString();
482 }
483 
484 //------------------------------------------------------------------------------
485 void DICOMAppWidget::setTagsToPrecache( const QStringList tags)
486 {
487  Q_D(DICOMAppWidget);
488  d->DICOMDatabase->setTagsToPrecache(tags);
489 }
490 
491 //------------------------------------------------------------------------------
493 {
494  Q_D(DICOMAppWidget);
495  return d->DICOMDatabase->tagsToPrecache();
496 }
497 
498 //----------------------------------------------------------------------------
499 ctkDICOMDatabase* DICOMAppWidget::database(){
500  Q_D(DICOMAppWidget);
501  return d->DICOMDatabase.data();
502 }
503 
504 //----------------------------------------------------------------------------
506 {
507  Q_D(DICOMAppWidget);
508 
509  d->getQueryRetrieveWidget()->show();
510  d->getQueryRetrieveWidget()->raise();
511 
512 }
513 
514 //----------------------------------------------------------------------------
516 {
517  Q_D(DICOMAppWidget);
518  d->mDICOMModel.reset();
519  emit this->queryRetrieveFinished();
520 }
521 
523 {
524  Q_D(DICOMAppWidget);
525  return d->getSelection()[ctkDICOMModel::PatientType];
526 }
528 {
529  Q_D(DICOMAppWidget);
530  return d->getSelection()[ctkDICOMModel::StudyType];
531 }
533 {
534  Q_D(DICOMAppWidget);
535  return d->getSelection()[ctkDICOMModel::SeriesType];
536 }
537 
538 //----------------------------------------------------------------------------
540 {
541  Q_D(DICOMAppWidget);
542  d->removeSelection();
543 }
544 
545 //----------------------------------------------------------------------------
547 {
548  Q_D(DICOMAppWidget);
549  d->mDICOMModel.setDatabase(d->DICOMDatabase);
550 }
551 
552 //----------------------------------------------------------------------------
554 {
555  Q_D(DICOMAppWidget);
556  d->mDICOMModel.reset();
557 }
558 
560 void DICOMAppWidget::onImportDirectory(QString directory)
561 {
562  Q_D(DICOMAppWidget);
563  d->Importer.onImportDirectory(directory);
564 }
565 
566 void DICOMAppWidget::onSelectionChanged(const QItemSelection&, const QItemSelection&)
567 {
568 }
569 
570 void DICOMAppWidget::onCurrentChanged(const QModelIndex& next, const QModelIndex& last)
571 {
572  Q_D(DICOMAppWidget);
573  d->ThumbnailsWidget->addThumbnails(next);
574 }
575 
576 void DICOMAppWidget::onModelSelected(const QModelIndex &index)
577 {
578  Q_D(DICOMAppWidget);
579 
580  ctkDICOMModel* model = const_cast<ctkDICOMModel*>(qobject_cast<const ctkDICOMModel*>(index.model()));
581 
582  if(model)
583  {
584  QModelIndex index0 = index.sibling(index.row(), 0);
585 
586  d->ActionRemove->setEnabled(
587  model->data(index0,ctkDICOMModel::TypeRole) == static_cast<int>(ctkDICOMModel::SeriesType) ||
588  model->data(index0,ctkDICOMModel::TypeRole) == static_cast<int>(ctkDICOMModel::StudyType) ||
589  model->data(index0,ctkDICOMModel::TypeRole) == static_cast<int>(ctkDICOMModel::PatientType) );
590  }
591  else
592  {
593  d->ActionRemove->setEnabled(false);
594  }
595 }
596 
597 //----------------------------------------------------------------------------
598 void DICOMAppWidget::onTreeCollapsed(const QModelIndex &index){
599  Q_UNUSED(index);
600  Q_D(DICOMAppWidget);
601  d->TreeView->resizeColumnToContents(0);
602 }
603 
604 //----------------------------------------------------------------------------
605 void DICOMAppWidget::onTreeExpanded(const QModelIndex &index){
606  Q_UNUSED(index);
607  Q_D(DICOMAppWidget);
608  d->TreeView->resizeColumnToContents(0);
609  d->TreeView->resizeColumnToContents(1);
610 }
611 
612 //----------------------------------------------------------------------------
614 {
615  Q_D(DICOMAppWidget);
616  d->ThumbnailsWidget->setThumbnailSize(QSize(val, val));
617 }
618 
620 {
621  Q_D(DICOMAppWidget);
622  d->ToolBar->addAction(action);
623 }
624 
625 
626 
627 } // namespace cx
#define CX_LOG_CHANNEL_INFO(channel)
Definition: cxLogger.h:123
void onTreeCollapsed(const QModelIndex &index)
ctkDICOMQueryRetrieveWidget * getQueryRetrieveWidget()
QStringList getSelectedSeries()
ctkDICOMQueryRetrieveWidget * QueryRetrieveWidget
Q_DECLARE_PUBLIC(DICOMAppWidget)
void onTreeExpanded(const QModelIndex &index)
virtual bool removeRows(int row, int count, const QModelIndex &parent=QModelIndex())
DICOMAppWidgetPrivate(DICOMAppWidget *)
ctkDICOMDatabase * database()
ctkDICOMFilterProxyModel DICOMProxyModel
std::map< ctkDICOMModel::IndexType, QStringList > getSelection() const
void addActionToToolbar(QAction *action)
void setDisplayImportSummary(bool)
virtual QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const
void onSelectionChanged(const QItemSelection &, const QItemSelection &)
QVariant value(const QString &key, const QVariant &defaultValue=QVariant()) const
Definition: cxSettings.cpp:87
QSharedPointer< ctkDICOMDatabase > DICOMDatabase
QSharedPointer< ctkDICOMThumbnailGenerator > ThumbnailGenerator
void onImportDirectory(QString directory)
void setTagsToPrecache(const QStringList tags)
DICOMModel ctkDICOMModel
void setValue(const QString &key, const QVariant &value)
Definition: cxSettings.cpp:79
QStringList getSelectedPatients()
QStringList getSelectedStudies()
void onCurrentChanged(const QModelIndex &, const QModelIndex &)
void databaseDirectoryChanged(const QString &)
QProgressDialog * UpdateSchemaProgress
QString databaseDirectory() const
Directory being used to store the dicom database.
Settings * settings()
Shortcut for accessing the settings instance.
Definition: cxSettings.cpp:42
DICOMAppWidget(QWidget *parent=0)
void queryRetrieveFinished()
void onThumbnailWidthSliderValueChanged(int val)
void setupUi(DICOMAppWidget *parent)
const QStringList tagsToPrecache()
void onModelSelected(const QModelIndex &index)
DICOMAppWidget *const q_ptr
void setDatabaseDirectory(const QString &directory)
Q_DECLARE_METATYPE(QPersistentModelIndex)
int patientsAddedDuringImport()
Accessors to status of last directory import operation.
#define CX_LOG_CHANNEL_ERROR(channel)
Definition: cxLogger.h:126
DICOMThumbnailListWidget * ThumbnailsWidget