| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484 | // std includes#include <iostream>#include <dcmimage.h>// Qt includes#include <QDebug>#include <QTreeView>#include <QTabBar>#include <QSettings>#include <QAction>#include <QModelIndex>#include <QCheckBox>// ctkDICOMCore includes#include "ctkDICOMDatabase.h"#include "ctkDICOMIndexer.h"// ctkDICOMWidgets includes#include "ctkDICOMModel.h"#include "ctkDICOMAppWidget.h"#include "ctkDICOMQueryResultsTabWidget.h"#include "ui_ctkDICOMAppWidget.h"#include "ctkDirectoryButton.h"#include "ctkFileDialog.h"#include "ctkDICOMQueryRetrieveWidget.h"#include "ctkDICOMImportWidget.h"#include "ctkDICOMThumbnailWidget.h"#include "ctkDICOMThumbnailGenerator.h"//logger#include <ctkLogger.h>static ctkLogger logger("org.commontk.DICOM.Widgets.ctkDICOMAppWidget");//----------------------------------------------------------------------------class ctkDICOMAppWidgetPrivate: public Ui_ctkDICOMAppWidget{public:  ctkDICOMAppWidgetPrivate();  ctkFileDialog* ImportDialog;  ctkDICOMQueryRetrieveWidget* QueryRetrieveWidget;  QSharedPointer<ctkDICOMDatabase> DICOMDatabase;  QSharedPointer<ctkDICOMThumbnailGenerator> thumbnailGenerator;  ctkDICOMModel DICOMModel;  QSharedPointer<ctkDICOMIndexer> DICOMIndexer;};//----------------------------------------------------------------------------// ctkDICOMAppWidgetPrivate methodsctkDICOMAppWidgetPrivate::ctkDICOMAppWidgetPrivate(){  DICOMDatabase = QSharedPointer<ctkDICOMDatabase> (new ctkDICOMDatabase);  thumbnailGenerator = QSharedPointer <ctkDICOMThumbnailGenerator> (new ctkDICOMThumbnailGenerator);  DICOMDatabase->setThumbnailGenerator(thumbnailGenerator.data());  DICOMIndexer = QSharedPointer<ctkDICOMIndexer> (new ctkDICOMIndexer);  DICOMIndexer->setThumbnailGenerator(thumbnailGenerator.data());}//----------------------------------------------------------------------------// ctkDICOMAppWidget methods//----------------------------------------------------------------------------ctkDICOMAppWidget::ctkDICOMAppWidget(QWidget* _parent):Superclass(_parent),   d_ptr(new ctkDICOMAppWidgetPrivate){  Q_D(ctkDICOMAppWidget);    d->setupUi(this);  //Hide image previewer buttons  d->nextImageButton->hide();  d->prevImageButton->hide();  d->nextSeriesButton->hide();  d->prevSeriesButton->hide();  d->nextStudyButton->hide();  d->prevStudyButton->hide();  //Enable sorting in tree view  d->treeView->setSortingEnabled(true);  d->treeView->setSelectionBehavior(QAbstractItemView::SelectRows);  connect(d->treeView, SIGNAL(collapsed(QModelIndex)), this, SLOT(onTreeCollapsed(QModelIndex)));  connect(d->treeView, SIGNAL(expanded(QModelIndex)), this, SLOT(onTreeExpanded(QModelIndex)));  //Set toolbar button style  d->toolBar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);  //Initialize Q/R widget  d->QueryRetrieveWidget = new ctkDICOMQueryRetrieveWidget();  d->QueryRetrieveWidget->setWindowModality ( Qt::ApplicationModal );  //initialize directory from settings, then listen for changes  QSettings settings;  if ( settings.value("DatabaseDirectory", "") == "" )    {    QString directory = QString("./ctkDICOM-Database");    settings.setValue("DatabaseDirectory", directory);    settings.sync();    }  QString databaseDirectory = settings.value("DatabaseDirectory").toString();  this->setDatabaseDirectory(databaseDirectory);  d->directoryButton->setDirectory(databaseDirectory);  connect(d->directoryButton, SIGNAL(directoryChanged(const QString&)), this, SLOT(setDatabaseDirectory(const QString&)));  //Initialize import widget  d->ImportDialog = new ctkFileDialog();  QCheckBox* importCheckbox = new QCheckBox("Copy on import", d->ImportDialog);  d->ImportDialog->setBottomWidget(importCheckbox);  d->ImportDialog->setFileMode(QFileDialog::Directory);  d->ImportDialog->setLabelText(QFileDialog::Accept,"Import");  d->ImportDialog->setWindowTitle("Import DICOM files from directory ...");  d->ImportDialog->setWindowModality(Qt::ApplicationModal);  //connect signal and slots  connect(d->treeView, SIGNAL(clicked(const QModelIndex&)), d->thumbnailsWidget, SLOT(onModelSelected(const QModelIndex &)));  connect(d->treeView, SIGNAL(clicked(const QModelIndex&)), d->imagePreview, SLOT(onModelSelected(const QModelIndex &)));  connect(d->treeView, SIGNAL(clicked(const QModelIndex&)), this, SLOT(onModelSelected(const QModelIndex &)));  connect(d->thumbnailsWidget, SIGNAL(selected(const ctkDICOMThumbnailWidget&)), this, SLOT(onThumbnailSelected(const ctkDICOMThumbnailWidget&)));  connect(d->thumbnailsWidget, SIGNAL(doubleClicked(const ctkDICOMThumbnailWidget&)), this, SLOT(onThumbnailDoubleClicked(const ctkDICOMThumbnailWidget&)));  connect(d->ImportDialog, SIGNAL(fileSelected(QString)),this,SLOT(onImportDirectory(QString)));  connect(d->DICOMDatabase.data(), SIGNAL( databaseChanged() ), &(d->DICOMModel), SLOT( reset() ) );  connect(d->QueryRetrieveWidget, SIGNAL( canceled() ), d->QueryRetrieveWidget, SLOT( hide() ) );  connect(d->imagePreview, SIGNAL(requestNextImage()), this, SLOT(onNextImage()));  connect(d->imagePreview, SIGNAL(requestPreviousImage()), this, SLOT(onPreviousImage()));}//----------------------------------------------------------------------------ctkDICOMAppWidget::~ctkDICOMAppWidget(){  Q_D(ctkDICOMAppWidget);    d->QueryRetrieveWidget->deleteLater();  d->ImportDialog->deleteLater();}//----------------------------------------------------------------------------void ctkDICOMAppWidget::setDatabaseDirectory(const QString& directory){  Q_D(ctkDICOMAppWidget);    QSettings settings;  settings.setValue("DatabaseDirectory", directory);  settings.sync();  //close the active DICOM database  d->DICOMDatabase->closeDatabase();    //open DICOM database on the directory  QString databaseFileName = directory + QString("/ctkDICOM.sql");  try { d->DICOMDatabase->openDatabase( databaseFileName ); }  catch (std::exception e)  {    std::cerr << "Database error: " << qPrintable(d->DICOMDatabase->lastError()) << "\n";    d->DICOMDatabase->closeDatabase();    return;  }    d->DICOMModel.setDatabase(d->DICOMDatabase->database());  d->DICOMModel.setDisplayLevel(ctkDICOMModel::SeriesType);  d->treeView->setModel(&d->DICOMModel);  d->treeView->resizeColumnToContents(0);  //pass DICOM database instance to Import widget  // d->ImportDialog->setDICOMDatabase(d->DICOMDatabase);  d->QueryRetrieveWidget->setRetrieveDatabase(d->DICOMDatabase);  // update the button and let any connected slots know about the change  d->directoryButton->setDirectory(directory);  d->thumbnailsWidget->setDatabaseDirectory(directory);  d->imagePreview->setDatabaseDirectory(directory);  emit databaseDirectoryChanged(directory);}//----------------------------------------------------------------------------QString ctkDICOMAppWidget::databaseDirectory() const{  QSettings settings;  return settings.value("DatabaseDirectory").toString();}void ctkDICOMAppWidget::onAddToDatabase(){  //Q_D(ctkDICOMAppWidget);  //d->}//----------------------------------------------------------------------------void ctkDICOMAppWidget::openImportDialog(){  Q_D(ctkDICOMAppWidget);    d->ImportDialog->show();  d->ImportDialog->raise();}//----------------------------------------------------------------------------void ctkDICOMAppWidget::openExportDialog(){}//----------------------------------------------------------------------------void ctkDICOMAppWidget::openQueryDialog(){  Q_D(ctkDICOMAppWidget);  d->QueryRetrieveWidget->show();  d->QueryRetrieveWidget->raise();}//----------------------------------------------------------------------------void ctkDICOMAppWidget::onThumbnailSelected(const ctkDICOMThumbnailWidget& widget){    Q_D(ctkDICOMAppWidget);    d->imagePreview->onModelSelected(widget.sourceIndex());}//----------------------------------------------------------------------------void ctkDICOMAppWidget::onThumbnailDoubleClicked(const ctkDICOMThumbnailWidget& widget){    Q_D(ctkDICOMAppWidget);    logger.debug("double clicked");    QModelIndex index = widget.sourceIndex();    ctkDICOMModel* model = const_cast<ctkDICOMModel*>(qobject_cast<const ctkDICOMModel*>(index.model()));    QModelIndex index0 = index.sibling(index.row(), 0);    if(model && (model->data(index0,ctkDICOMModel::TypeRole) != ctkDICOMModel::ImageType)){        this->onModelSelected(index0);        d->treeView->setCurrentIndex(index0);        d->thumbnailsWidget->onModelSelected(index0);        d->imagePreview->onModelSelected(index0);    }}//----------------------------------------------------------------------------void ctkDICOMAppWidget::onImportDirectory(QString directory){  Q_D(ctkDICOMAppWidget);  if (QDir(directory).exists())  {    QCheckBox* copyOnImport = qobject_cast<QCheckBox*>(d->ImportDialog->bottomWidget());    QString targetDirectory;    if (copyOnImport->isEnabled())    {       targetDirectory = d->DICOMDatabase->databaseDirectory();    }    d->DICOMIndexer->addDirectory(*d->DICOMDatabase,directory,targetDirectory);    d->DICOMModel.reset();  }}//----------------------------------------------------------------------------void ctkDICOMAppWidget::onModelSelected(const QModelIndex &index){     Q_D(ctkDICOMAppWidget);    ctkDICOMModel* model = const_cast<ctkDICOMModel*>(qobject_cast<const ctkDICOMModel*>(index.model()));    if(model){        QModelIndex index0 = index.sibling(index.row(), 0);        if ( model->data(index0,ctkDICOMModel::TypeRole) == ctkDICOMModel::PatientType ){            d->nextImageButton->show();            d->prevImageButton->show();            d->nextSeriesButton->show();            d->prevSeriesButton->show();            d->nextStudyButton->show();            d->prevStudyButton->show();        }else if ( model->data(index0,ctkDICOMModel::TypeRole) == ctkDICOMModel::StudyType ){            d->nextImageButton->show();            d->prevImageButton->show();            d->nextSeriesButton->show();            d->prevSeriesButton->show();            d->nextStudyButton->hide();            d->prevStudyButton->hide();        }else if ( model->data(index0,ctkDICOMModel::TypeRole) == ctkDICOMModel::SeriesType ){            d->nextImageButton->show();            d->prevImageButton->show();            d->nextSeriesButton->hide();            d->prevSeriesButton->hide();            d->nextStudyButton->hide();            d->prevStudyButton->hide();        }else{            d->nextImageButton->hide();            d->prevImageButton->hide();            d->nextSeriesButton->hide();            d->prevSeriesButton->hide();            d->nextStudyButton->hide();            d->prevStudyButton->hide();        }    }else{        d->nextImageButton->hide();        d->prevImageButton->hide();        d->nextSeriesButton->hide();        d->prevSeriesButton->hide();        d->nextStudyButton->hide();        d->prevStudyButton->hide();    }}//----------------------------------------------------------------------------void ctkDICOMAppWidget::onNextImage(){    Q_D(ctkDICOMAppWidget);    QModelIndex currentIndex = d->imagePreview->currentImageIndex();    if(currentIndex.isValid()){        ctkDICOMModel* model = const_cast<ctkDICOMModel*>(qobject_cast<const ctkDICOMModel*>(currentIndex.model()));        if(model){            QModelIndex seriesIndex = currentIndex.parent();            int imageCount = model->rowCount(seriesIndex);            int imageID = currentIndex.row();            imageID = (imageID+1)%imageCount;            QModelIndex nextIndex = currentIndex.sibling(imageID, 0);            d->imagePreview->onModelSelected(nextIndex);            d->thumbnailsWidget->selectThumbnail(nextIndex);        }    }}//----------------------------------------------------------------------------void ctkDICOMAppWidget::onPreviousImage(){    Q_D(ctkDICOMAppWidget);    QModelIndex currentIndex = d->imagePreview->currentImageIndex();    if(currentIndex.isValid()){        ctkDICOMModel* model = const_cast<ctkDICOMModel*>(qobject_cast<const ctkDICOMModel*>(currentIndex.model()));        if(model){            QModelIndex seriesIndex = currentIndex.parent();            int imageCount = model->rowCount(seriesIndex);            int imageID = currentIndex.row();            imageID--;            if(imageID < 0) imageID += imageCount;            QModelIndex prevIndex = currentIndex.sibling(imageID, 0);            d->imagePreview->onModelSelected(prevIndex);            d->thumbnailsWidget->selectThumbnail(prevIndex);        }    }}//----------------------------------------------------------------------------void ctkDICOMAppWidget::onNextSeries(){    Q_D(ctkDICOMAppWidget);    QModelIndex currentIndex = d->imagePreview->currentImageIndex();    if(currentIndex.isValid()){        ctkDICOMModel* model = const_cast<ctkDICOMModel*>(qobject_cast<const ctkDICOMModel*>(currentIndex.model()));        if(model){            QModelIndex seriesIndex = currentIndex.parent();            QModelIndex studyIndex = seriesIndex.parent();            int seriesCount = model->rowCount(studyIndex);            int seriesID = seriesIndex.row();            seriesID = (seriesID + 1)%seriesCount;            QModelIndex nextIndex = seriesIndex.sibling(seriesID, 0);            d->imagePreview->onModelSelected(nextIndex);            d->thumbnailsWidget->selectThumbnail(nextIndex);        }    }}//----------------------------------------------------------------------------void ctkDICOMAppWidget::onPreviousSeries(){    Q_D(ctkDICOMAppWidget);    QModelIndex currentIndex = d->imagePreview->currentImageIndex();    if(currentIndex.isValid()){        ctkDICOMModel* model = const_cast<ctkDICOMModel*>(qobject_cast<const ctkDICOMModel*>(currentIndex.model()));        if(model){            QModelIndex seriesIndex = currentIndex.parent();            QModelIndex studyIndex = seriesIndex.parent();            int seriesCount = model->rowCount(studyIndex);            int seriesID = seriesIndex.row();            seriesID--;            if(seriesID < 0) seriesID += seriesCount;            QModelIndex prevIndex = seriesIndex.sibling(seriesID, 0);            d->imagePreview->onModelSelected(prevIndex);            d->thumbnailsWidget->selectThumbnail(prevIndex);        }    }}//----------------------------------------------------------------------------void ctkDICOMAppWidget::onNextStudy(){    Q_D(ctkDICOMAppWidget);    QModelIndex currentIndex = d->imagePreview->currentImageIndex();    if(currentIndex.isValid()){        ctkDICOMModel* model = const_cast<ctkDICOMModel*>(qobject_cast<const ctkDICOMModel*>(currentIndex.model()));        if(model){            QModelIndex seriesIndex = currentIndex.parent();            QModelIndex studyIndex = seriesIndex.parent();            QModelIndex patientIndex = studyIndex.parent();            int studyCount = model->rowCount(patientIndex);            int studyID = studyIndex.row();            studyID = (studyID + 1)%studyCount;            QModelIndex nextIndex = studyIndex.sibling(studyID, 0);            d->imagePreview->onModelSelected(nextIndex);            d->thumbnailsWidget->selectThumbnail(nextIndex);        }    }}//----------------------------------------------------------------------------void ctkDICOMAppWidget::onPreviousStudy(){    Q_D(ctkDICOMAppWidget);    QModelIndex currentIndex = d->imagePreview->currentImageIndex();    if(currentIndex.isValid()){        ctkDICOMModel* model = const_cast<ctkDICOMModel*>(qobject_cast<const ctkDICOMModel*>(currentIndex.model()));        if(model){            QModelIndex seriesIndex = currentIndex.parent();            QModelIndex studyIndex = seriesIndex.parent();            QModelIndex patientIndex = studyIndex.parent();            int studyCount = model->rowCount(patientIndex);            int studyID = studyIndex.row();            studyID--;            if(studyID < 0) studyID += studyCount;            QModelIndex prevIndex = studyIndex.sibling(studyID, 0);            d->imagePreview->onModelSelected(prevIndex);            d->thumbnailsWidget->selectThumbnail(prevIndex);        }    }}//----------------------------------------------------------------------------void ctkDICOMAppWidget::onTreeCollapsed(const QModelIndex &index){    Q_D(ctkDICOMAppWidget);    d->treeView->resizeColumnToContents(0);}//----------------------------------------------------------------------------void ctkDICOMAppWidget::onTreeExpanded(const QModelIndex &index){    Q_D(ctkDICOMAppWidget);    d->treeView->resizeColumnToContents(0);}
 |