| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084 | 
							- /*=========================================================================
 
-   Library:   CTK
 
-   Copyright (c) Kitware Inc.
 
-   Licensed under the Apache License, Version 2.0 (the "License");
 
-   you may not use this file except in compliance with the License.
 
-   You may obtain a copy of the License at
 
-       http://www.apache.org/licenses/LICENSE-2.0.txt
 
-   Unless required by applicable law or agreed to in writing, software
 
-   distributed under the License is distributed on an "AS IS" BASIS,
 
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
-   See the License for the specific language governing permissions and
 
-   limitations under the License.
 
- =========================================================================*/
 
- // std includes
 
- #include <iostream>
 
- // Qt includes
 
- #include <QAction>
 
- #include <QApplication>
 
- #include <QCoreApplication>
 
- #include <QCheckBox>
 
- #include <QDebug>
 
- #include <QFile>
 
- #include <QListView>
 
- #include <QMenu>
 
- #include <QMessageBox>
 
- #include <QProgressDialog>
 
- #include <QSettings>
 
- #include <QStringListModel>
 
- #include <QWidgetAction>
 
- // ctkWidgets includes
 
- #include "ctkDirectoryButton.h"
 
- #include "ctkFileDialog.h"
 
- #include "ctkMessageBox.h"
 
- // ctkDICOMCore includes
 
- #include "ctkDICOMDatabase.h"
 
- #include "ctkDICOMIndexer.h"
 
- // ctkDICOMWidgets includes
 
- #include "ctkDICOMBrowser.h"
 
- #include "ctkDICOMQueryResultsTabWidget.h"
 
- #include "ctkDICOMQueryRetrieveWidget.h"
 
- #include "ctkDICOMQueryWidget.h"
 
- #include "ctkDICOMTableManager.h"
 
- #include "ui_ctkDICOMBrowser.h"
 
- //logger
 
- #include <ctkLogger.h>
 
- static ctkLogger logger("org.commontk.DICOM.Widgets.ctkDICOMBrowser");
 
- //----------------------------------------------------------------------------
 
- class ctkDICOMBrowserPrivate: public Ui_ctkDICOMBrowser
 
- {
 
- public:
 
-   ctkDICOMBrowser* const q_ptr;
 
-   Q_DECLARE_PUBLIC(ctkDICOMBrowser);
 
-   ctkDICOMBrowserPrivate(ctkDICOMBrowser* );
 
-   ~ctkDICOMBrowserPrivate();
 
-   ctkFileDialog* ImportDialog;
 
-   ctkDICOMQueryRetrieveWidget* QueryRetrieveWidget;
 
-   QSharedPointer<ctkDICOMDatabase> DICOMDatabase;
 
-   QSharedPointer<ctkDICOMIndexer> DICOMIndexer;
 
-   QProgressDialog *IndexerProgress;
 
-   QProgressDialog *UpdateSchemaProgress;
 
-   QProgressDialog *ExportProgress;
 
-   void showIndexerDialog();
 
-   void showUpdateSchemaDialog();
 
-   // used when suspending the ctkDICOMModel
 
-   QSqlDatabase EmptyDatabase;
 
-   // local count variables to keep track of the number of items
 
-   // added to the database during an import operation
 
-   bool DisplayImportSummary;
 
-   int PatientsAddedDuringImport;
 
-   int StudiesAddedDuringImport;
 
-   int SeriesAddedDuringImport;
 
-   int InstancesAddedDuringImport;
 
- };
 
- //----------------------------------------------------------------------------
 
- // ctkDICOMBrowserPrivate methods
 
- ctkDICOMBrowserPrivate::ctkDICOMBrowserPrivate(ctkDICOMBrowser* parent): q_ptr(parent){
 
-   DICOMDatabase = QSharedPointer<ctkDICOMDatabase> (new ctkDICOMDatabase);
 
-   DICOMIndexer = QSharedPointer<ctkDICOMIndexer> (new ctkDICOMIndexer);
 
-   IndexerProgress = 0;
 
-   UpdateSchemaProgress = 0;
 
-   ExportProgress = 0;
 
-   DisplayImportSummary = true;
 
-   PatientsAddedDuringImport = 0;
 
-   StudiesAddedDuringImport = 0;
 
-   SeriesAddedDuringImport = 0;
 
-   InstancesAddedDuringImport = 0;
 
- }
 
- ctkDICOMBrowserPrivate::~ctkDICOMBrowserPrivate()
 
- {
 
-   if ( IndexerProgress )
 
-     {
 
-     delete IndexerProgress;
 
-     }
 
-   if ( UpdateSchemaProgress )
 
-     {
 
-     delete UpdateSchemaProgress;
 
-     }
 
-   if ( ExportProgress )
 
-     {
 
-     delete ExportProgress;
 
-     }
 
- }
 
- void ctkDICOMBrowserPrivate::showUpdateSchemaDialog()
 
- {
 
-   Q_Q(ctkDICOMBrowser);
 
-   if (UpdateSchemaProgress == 0)
 
-     {
 
-     //
 
-     // Set up the Update Schema Progress Dialog
 
-     //
 
-     UpdateSchemaProgress = new QProgressDialog(
 
-         q->tr("DICOM Schema Update"), "Cancel", 0, 100, q,
 
-          Qt::WindowTitleHint | Qt::WindowSystemMenuHint);
 
-     // We don't want the progress dialog to resize itself, so we bypass the label
 
-     // by creating our own
 
-     QLabel* progressLabel = new QLabel(q->tr("Initialization..."));
 
-     UpdateSchemaProgress->setLabel(progressLabel);
 
-     UpdateSchemaProgress->setWindowModality(Qt::ApplicationModal);
 
-     UpdateSchemaProgress->setMinimumDuration(0);
 
-     UpdateSchemaProgress->setValue(0);
 
-     q->connect(DICOMDatabase.data(), SIGNAL(schemaUpdateStarted(int)),
 
-             UpdateSchemaProgress, SLOT(setMaximum(int)));
 
-     q->connect(DICOMDatabase.data(), SIGNAL(schemaUpdateProgress(int)),
 
-             UpdateSchemaProgress, SLOT(setValue(int)));
 
-     q->connect(DICOMDatabase.data(), SIGNAL(schemaUpdateProgress(QString)),
 
-             progressLabel, SLOT(setText(QString)));
 
-     // close the dialog
 
-     q->connect(DICOMDatabase.data(), SIGNAL(schemaUpdated()),
 
-             UpdateSchemaProgress, SLOT(close()));
 
-     }
 
-   UpdateSchemaProgress->show();
 
- }
 
- void ctkDICOMBrowserPrivate::showIndexerDialog()
 
- {
 
-   Q_Q(ctkDICOMBrowser);
 
-   if (IndexerProgress == 0)
 
-     {
 
-     //
 
-     // Set up the Indexer Progress Dialog
 
-     //
 
-     IndexerProgress = new QProgressDialog( q->tr("DICOM Import"), "Cancel", 0, 100, q,
 
-          Qt::WindowTitleHint | Qt::WindowSystemMenuHint);
 
-     // We don't want the progress dialog to resize itself, so we bypass the label
 
-     // by creating our own
 
-     QLabel* progressLabel = new QLabel(q->tr("Initialization..."));
 
-     IndexerProgress->setLabel(progressLabel);
 
-     IndexerProgress->setWindowModality(Qt::ApplicationModal);
 
-     IndexerProgress->setMinimumDuration(0);
 
-     IndexerProgress->setValue(0);
 
-     q->connect(IndexerProgress, SIGNAL(canceled()), 
 
-                  DICOMIndexer.data(), SLOT(cancel()));
 
-     q->connect(DICOMIndexer.data(), SIGNAL(progress(int)),
 
-             IndexerProgress, SLOT(setValue(int)));
 
-     q->connect(DICOMIndexer.data(), SIGNAL(indexingFilePath(QString)),
 
-             progressLabel, SLOT(setText(QString)));
 
-     q->connect(DICOMIndexer.data(), SIGNAL(indexingFilePath(QString)),
 
-             q, SLOT(onFileIndexed(QString)));
 
-     // close the dialog
 
-     q->connect(DICOMIndexer.data(), SIGNAL(indexingComplete()),
 
-             IndexerProgress, SLOT(close()));
 
-     // stop indexing and reset the database if canceled
 
-     q->connect(IndexerProgress, SIGNAL(canceled()), 
 
-             DICOMIndexer.data(), SLOT(cancel()));
 
-     // allow users of this widget to know that the process has finished
 
-     q->connect(IndexerProgress, SIGNAL(canceled()), 
 
-             q, SIGNAL(directoryImported()));
 
-     q->connect(DICOMIndexer.data(), SIGNAL(indexingComplete()),
 
-             q, SIGNAL(directoryImported()));
 
-     }
 
-   IndexerProgress->show();
 
- }
 
- //----------------------------------------------------------------------------
 
- // ctkDICOMBrowser methods
 
- //----------------------------------------------------------------------------
 
- ctkDICOMBrowser::ctkDICOMBrowser(QWidget* _parent):Superclass(_parent),
 
-     d_ptr(new ctkDICOMBrowserPrivate(this))
 
- {
 
-   Q_D(ctkDICOMBrowser);
 
-   d->setupUi(this);
 
-   // signals related to tracking inserts
 
-   connect(d->DICOMDatabase.data(), SIGNAL(patientAdded(int,QString,QString,QString)), this,
 
-                               SLOT(onPatientAdded(int,QString,QString,QString)));
 
-   connect(d->DICOMDatabase.data(), SIGNAL(studyAdded(QString)), this, SLOT(onStudyAdded(QString)));
 
-   connect(d->DICOMDatabase.data(), SIGNAL(seriesAdded(QString)), this, SLOT(onSeriesAdded(QString)));
 
-   connect(d->DICOMDatabase.data(), SIGNAL(instanceAdded(QString)), this, SLOT(onInstanceAdded(QString)));
 
-   connect(d->tableDensityComboBox ,SIGNAL(currentIndexChanged (const QString&)),
 
-      this, SLOT(onTablesDensityComboBox(QString)));
 
-   //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);
 
-   d->dicomTableManager->setDICOMDatabase(d->DICOMDatabase.data());
 
-   // TableView signals
 
-   connect(d->dicomTableManager, SIGNAL(patientsSelectionChanged(const QItemSelection&, const QItemSelection&)),
 
-           this, SLOT(onModelSelected(const QItemSelection&,const QItemSelection&)));
 
-   connect(d->dicomTableManager, SIGNAL(studiesSelectionChanged(const QItemSelection&, const QItemSelection&)),
 
-           this, SLOT(onModelSelected(const QItemSelection&,const QItemSelection&)));
 
-   connect(d->dicomTableManager, SIGNAL(seriesSelectionChanged(const QItemSelection&, const QItemSelection&)),
 
-           this, SLOT(onModelSelected(const QItemSelection&,const QItemSelection&)));
 
-   // set up context menus for working on selected patients, studies, series
 
-   connect(d->dicomTableManager, SIGNAL(patientsRightClicked(const QPoint&)),
 
-           this, SLOT(onPatientsRightClicked(const QPoint&)));
 
-   connect(d->dicomTableManager, SIGNAL(studiesRightClicked(const QPoint&)),
 
-           this, SLOT(onStudiesRightClicked(const QPoint&)));
 
-   connect(d->dicomTableManager, SIGNAL(seriesRightClicked(const QPoint&)),
 
-           this, SLOT(onSeriesRightClicked(const QPoint&)));
 
-   connect(d->DirectoryButton, SIGNAL(directoryChanged(QString)), this, SLOT(setDatabaseDirectory(QString)));
 
-   //Initialize import widget
 
-   d->ImportDialog = new ctkFileDialog();
 
-   QCheckBox* importCheckbox = new QCheckBox("Copy on import", d->ImportDialog);
 
-   importCheckbox->setCheckState(Qt::Checked);
 
-   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->ImportDialog, SIGNAL(fileSelected(QString)),this,SLOT(onImportDirectory(QString)));
 
-   connect(d->QueryRetrieveWidget, SIGNAL(canceled()), d->QueryRetrieveWidget, SLOT(hide()) );
 
-   connect(d->QueryRetrieveWidget, SIGNAL(canceled()), this, SLOT(onQueryRetrieveFinished()) );
 
- }
 
- //----------------------------------------------------------------------------
 
- ctkDICOMBrowser::~ctkDICOMBrowser()
 
- {
 
-   Q_D(ctkDICOMBrowser);
 
-   d->QueryRetrieveWidget->deleteLater();
 
-   d->ImportDialog->deleteLater();
 
- }
 
- //----------------------------------------------------------------------------
 
- bool ctkDICOMBrowser::displayImportSummary()
 
- {
 
-   Q_D(ctkDICOMBrowser);
 
-   return d->DisplayImportSummary;
 
- }
 
- //----------------------------------------------------------------------------
 
- void ctkDICOMBrowser::setDisplayImportSummary(bool onOff)
 
- {
 
-   Q_D(ctkDICOMBrowser);
 
-   d->DisplayImportSummary = onOff;
 
- }
 
- //----------------------------------------------------------------------------
 
- int ctkDICOMBrowser::patientsAddedDuringImport()
 
- {
 
-   Q_D(ctkDICOMBrowser);
 
-   return d->PatientsAddedDuringImport;
 
- }
 
- //----------------------------------------------------------------------------
 
- int ctkDICOMBrowser::studiesAddedDuringImport()
 
- {
 
-   Q_D(ctkDICOMBrowser);
 
-   return d->StudiesAddedDuringImport;
 
- }
 
- //----------------------------------------------------------------------------
 
- int ctkDICOMBrowser::seriesAddedDuringImport()
 
- {
 
-   Q_D(ctkDICOMBrowser);
 
-   return d->SeriesAddedDuringImport;
 
- }
 
- //----------------------------------------------------------------------------
 
- int ctkDICOMBrowser::instancesAddedDuringImport()
 
- {
 
-   Q_D(ctkDICOMBrowser);
 
-   return d->InstancesAddedDuringImport;
 
- }
 
- //----------------------------------------------------------------------------
 
- void ctkDICOMBrowser::updateDatabaseSchemaIfNeeded()
 
- {
 
-   Q_D(ctkDICOMBrowser);
 
-   d->showUpdateSchemaDialog();
 
-   d->DICOMDatabase->updateSchemaIfNeeded();
 
- }
 
- //----------------------------------------------------------------------------
 
- void ctkDICOMBrowser::setDatabaseDirectory(const QString& directory)
 
- {
 
-   Q_D(ctkDICOMBrowser);
 
-   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;
 
-     }
 
-   // update the database schema if needed and provide progress
 
-   this->updateDatabaseSchemaIfNeeded();
 
-   //pass DICOM database instance to Import widget
 
-   d->QueryRetrieveWidget->setRetrieveDatabase(d->DICOMDatabase);
 
-   // update the button and let any connected slots know about the change
 
-   d->DirectoryButton->setDirectory(directory);
 
-   d->dicomTableManager->updateTableViews();
 
-   emit databaseDirectoryChanged(directory);
 
- }
 
- //----------------------------------------------------------------------------
 
- QString ctkDICOMBrowser::databaseDirectory() const
 
- {
 
-   QSettings settings;
 
-   return settings.value("DatabaseDirectory").toString();
 
- }
 
- //------------------------------------------------------------------------------
 
- void ctkDICOMBrowser::setTagsToPrecache( const QStringList tags)
 
- {
 
-   Q_D(ctkDICOMBrowser);
 
-   d->DICOMDatabase->setTagsToPrecache(tags);
 
- }
 
- //------------------------------------------------------------------------------
 
- const QStringList ctkDICOMBrowser::tagsToPrecache()
 
- {
 
-   Q_D(ctkDICOMBrowser);
 
-   return d->DICOMDatabase->tagsToPrecache();
 
- }
 
- //----------------------------------------------------------------------------
 
- ctkDICOMDatabase* ctkDICOMBrowser::database(){
 
-   Q_D(ctkDICOMBrowser);
 
-   return d->DICOMDatabase.data();
 
- }
 
- //----------------------------------------------------------------------------
 
- ctkDICOMTableManager* ctkDICOMBrowser::dicomTableManager()
 
- {
 
-   Q_D(ctkDICOMBrowser);
 
-   return d->dicomTableManager;
 
- }
 
- //----------------------------------------------------------------------------
 
- void ctkDICOMBrowser::onFileIndexed(const QString& filePath)
 
- {
 
-   // Update the progress dialog when the file name changes
 
-   // - also allows for cancel button
 
-   QCoreApplication::instance()->processEvents();
 
-   qDebug() << "Indexing \n\n\n\n" << filePath <<"\n\n\n";
 
-   
 
- }
 
- //----------------------------------------------------------------------------
 
- void ctkDICOMBrowser::openImportDialog()
 
- {
 
-   Q_D(ctkDICOMBrowser);
 
-   d->ImportDialog->show();
 
-   d->ImportDialog->raise();
 
- }
 
- //----------------------------------------------------------------------------
 
- void ctkDICOMBrowser::openExportDialog()
 
- {
 
- }
 
- //----------------------------------------------------------------------------
 
- void ctkDICOMBrowser::openQueryDialog()
 
- {
 
-   Q_D(ctkDICOMBrowser);
 
-   d->QueryRetrieveWidget->show();
 
-   d->QueryRetrieveWidget->raise();
 
- }
 
- //----------------------------------------------------------------------------
 
- void ctkDICOMBrowser::onQueryRetrieveFinished()
 
- {
 
-   emit this->queryRetrieveFinished();
 
- }
 
- //----------------------------------------------------------------------------
 
- void ctkDICOMBrowser::onRemoveAction()
 
- {
 
-   Q_D(ctkDICOMBrowser);
 
-   QStringList selectedSeriesUIDs = d->dicomTableManager->currentSeriesSelection();
 
-   foreach (const QString& uid, selectedSeriesUIDs)
 
-     {
 
-       d->DICOMDatabase->removeSeries(uid);
 
-     }
 
-   QStringList selectedStudiesUIDs = d->dicomTableManager->currentStudiesSelection();
 
-   foreach (const QString& uid, selectedStudiesUIDs)
 
-     {
 
-       d->DICOMDatabase->removeStudy(uid);
 
-     }
 
-   QStringList selectedPatientUIDs = d->dicomTableManager->currentPatientsSelection();
 
-   foreach (const QString& uid, selectedPatientUIDs)
 
-     {
 
-       d->DICOMDatabase->removePatient(uid);
 
-     }
 
-   // Update the table views
 
-   d->dicomTableManager->updateTableViews();
 
- }
 
- //----------------------------------------------------------------------------
 
- void ctkDICOMBrowser::onRepairAction()
 
- {
 
-   Q_D(ctkDICOMBrowser);
 
-   QMessageBox* repairMessageBox;
 
-   repairMessageBox = new QMessageBox;
 
-   repairMessageBox->setWindowTitle("Database Repair");
 
-   QStringList allFiles(d->DICOMDatabase->allFiles());
 
-   QSet<QString> corruptedSeries;
 
-   QStringList::const_iterator it;
 
-   for (it = allFiles.constBegin(); it!= allFiles.constEnd();++it)
 
-   {
 
-     QString fileName(*it);
 
-     QFile dicomFile(fileName);
 
-     if(!dicomFile.exists())
 
-     {
 
-       QString seriesUid = d->DICOMDatabase->seriesForFile(fileName);
 
-       corruptedSeries.insert(seriesUid);
 
-     }
 
-   }
 
-   if (corruptedSeries.size() == 0)
 
-   {
 
-     repairMessageBox->setText("All the files in the local database are available.");
 
-     repairMessageBox->addButton(QMessageBox::Ok);
 
-     repairMessageBox->exec();
 
-   }
 
-   else
 
-   {
 
-     repairMessageBox->addButton(QMessageBox::Yes);
 
-     repairMessageBox->addButton(QMessageBox::No);
 
-     QSet<QString>::iterator i;
 
-     for (i = corruptedSeries.begin(); i != corruptedSeries.end(); ++i)
 
-       {
 
-       QStringList fileList (d->DICOMDatabase->filesForSeries(*i));
 
-       QString unavailableFileNames;
 
-       QStringList::const_iterator it;
 
-       for (it= fileList.constBegin(); it!= fileList.constEnd();++it)
 
-       {
 
-         unavailableFileNames.append(*it+"\n");
 
-       }
 
-       QString firstFile (*(fileList.constBegin()));
 
-       QHash<QString,QString> descriptions (d->DICOMDatabase->descriptionsForFile(firstFile));
 
-       repairMessageBox->setText("The files for the following series are not available on the disk: \nPatient Name: "
 
-         + descriptions["PatientsName"]+ "\n"+
 
-         "Study Desciption: " + descriptions["StudyDescription"]+ "\n"+
 
-         "Series Desciption: " + descriptions["SeriesDescription"]+ "\n"+
 
-         "Do you want to remove the series from the DICOM database? ");
 
-       repairMessageBox->setDetailedText(unavailableFileNames);
 
-       int selection = repairMessageBox->exec();
 
-       if (selection == QMessageBox::Yes)
 
-       {
 
-         d->DICOMDatabase->removeSeries(*i);
 
-         d->dicomTableManager->updateTableViews();
 
-       }
 
-     }
 
-   }
 
- }
 
- //----------------------------------------------------------------------------
 
- void ctkDICOMBrowser::onTablesDensityComboBox(QString density)
 
- {
 
-   Q_D(ctkDICOMBrowser);
 
-   if ( density == "Comfortable")
 
-   {
 
-     d->dicomTableManager->setDisplayDensity(ctkDICOMTableManager::Comfortable);
 
-   }
 
-   else if ( density == "Cozy")
 
-   {
 
-     d->dicomTableManager->setDisplayDensity(ctkDICOMTableManager::Cozy);
 
-   }
 
-   else if ( density == "Compact")
 
-   {
 
-     d->dicomTableManager->setDisplayDensity(ctkDICOMTableManager::Compact);
 
-   }
 
- }
 
- //----------------------------------------------------------------------------
 
- void ctkDICOMBrowser::onPatientAdded(int databaseID, QString patientID, QString patientName, QString patientBirthDate )
 
- {
 
-   Q_D(ctkDICOMBrowser);
 
-   Q_UNUSED(databaseID);
 
-   Q_UNUSED(patientID);
 
-   Q_UNUSED(patientName);
 
-   Q_UNUSED(patientBirthDate);
 
-   ++d->PatientsAddedDuringImport;
 
- }
 
- //----------------------------------------------------------------------------
 
- void ctkDICOMBrowser::onStudyAdded(QString studyUID)
 
- {
 
-   Q_D(ctkDICOMBrowser);
 
-   Q_UNUSED(studyUID);
 
-   ++d->StudiesAddedDuringImport;
 
- }
 
- //----------------------------------------------------------------------------
 
- void ctkDICOMBrowser::onSeriesAdded(QString seriesUID)
 
- {
 
-   Q_D(ctkDICOMBrowser);
 
-   Q_UNUSED(seriesUID);
 
-   ++d->SeriesAddedDuringImport;
 
- }
 
- //----------------------------------------------------------------------------
 
- void ctkDICOMBrowser::onInstanceAdded(QString instanceUID)
 
- {
 
-   Q_D(ctkDICOMBrowser);
 
-   Q_UNUSED(instanceUID);
 
-   ++d->InstancesAddedDuringImport;
 
- }
 
- //----------------------------------------------------------------------------
 
- void ctkDICOMBrowser::onImportDirectory(QString directory)
 
- {
 
-   Q_D(ctkDICOMBrowser);
 
-   if (QDir(directory).exists())
 
-   {
 
-     QString targetDirectory;
 
-     QCheckBox* copyOnImport = qobject_cast<QCheckBox*>(d->ImportDialog->bottomWidget());
 
-     ctkMessageBox importTypeDialog;
 
-     QString message("Do you want to copy the files to the local database directory or just add the links?");
 
-     importTypeDialog.setText(message);
 
-     importTypeDialog.setIcon(QMessageBox::Question);
 
-     importTypeDialog.addButton("Copy",QMessageBox::AcceptRole);
 
-     importTypeDialog.addButton("Add Link",QMessageBox::RejectRole);
 
-     importTypeDialog.setDontShowAgainSettingsKey( "MainWindow/DontConfirmCopyOnImport" );
 
-     int selection = importTypeDialog.exec();
 
-     if (selection== QMessageBox::AcceptRole)
 
-     {
 
-       copyOnImport->setCheckState(Qt::Checked);
 
-     }
 
-     else
 
-     {
 
-       copyOnImport->setCheckState(Qt::Unchecked);
 
-     }
 
-     // reset counts
 
-     d->PatientsAddedDuringImport = 0;
 
-     d->StudiesAddedDuringImport = 0;
 
-     d->SeriesAddedDuringImport = 0;
 
-     d->InstancesAddedDuringImport = 0;
 
-     if (copyOnImport->checkState() == Qt::Checked)
 
-     {
 
-       targetDirectory = d->DICOMDatabase->databaseDirectory();
 
-     }
 
-     // show progress dialog and perform indexing
 
-     d->showIndexerDialog();
 
-     d->DICOMIndexer->addDirectory(*d->DICOMDatabase,directory,targetDirectory);
 
-     // display summary result
 
-     if (d->DisplayImportSummary)
 
-     {
 
-       QString message = "Directory import completed.\n\n";
 
-       message += QString("%1 New Patients\n").arg(QString::number(d->PatientsAddedDuringImport));
 
-       message += QString("%1 New Studies\n").arg(QString::number(d->StudiesAddedDuringImport));
 
-       message += QString("%1 New Series\n").arg(QString::number(d->SeriesAddedDuringImport));
 
-       message += QString("%1 New Instances\n").arg(QString::number(d->InstancesAddedDuringImport));
 
-       QMessageBox::information(this,"DICOM Directory Import", message);
 
-     }
 
-   }
 
- }
 
- //----------------------------------------------------------------------------
 
- void ctkDICOMBrowser::onModelSelected(const QItemSelection &item1, const QItemSelection &item2)
 
- {
 
-   Q_UNUSED(item1);
 
-   Q_UNUSED(item2);
 
-   Q_D(ctkDICOMBrowser);
 
-   d->ActionRemove->setEnabled(true);
 
- }
 
- //----------------------------------------------------------------------------
 
- bool ctkDICOMBrowser::confirmDeleteSelectedUIDs(QStringList uids)
 
- {
 
-   Q_D(ctkDICOMBrowser);
 
-   if (uids.isEmpty())
 
-     {
 
-     return false;
 
-     }
 
-   ctkMessageBox confirmDeleteDialog;
 
-   QString message("Do you want to delete the following selected items?");
 
-   // add the information about the selected UIDs
 
-   int numUIDs = uids.size();
 
-   for (int i = 0; i < numUIDs; ++i)
 
-     {
 
-     QString uid = uids.at(i);
 
-     // try using the given UID to find a descriptive string
 
-     QString patientName = d->DICOMDatabase->nameForPatient(uid);
 
-     QString studyDescription = d->DICOMDatabase->descriptionForStudy(uid);
 
-     QString seriesDescription = d->DICOMDatabase->descriptionForSeries(uid);
 
-     if (!patientName.isEmpty())
 
-       {
 
-       message += QString("\n") + patientName;
 
-       }
 
-     else if (!studyDescription.isEmpty())
 
-       {
 
-       message += QString("\n") + studyDescription;
 
-       }
 
-     else if (!seriesDescription.isEmpty())
 
-       {
 
-       message += QString("\n") + seriesDescription;
 
-       }
 
-     else
 
-       {
 
-       // if all other descriptors are empty, use the UID
 
-       message += QString("\n") + uid;
 
-       }
 
-     }
 
-   confirmDeleteDialog.setText(message);
 
-   confirmDeleteDialog.setIcon(QMessageBox::Question);
 
-   confirmDeleteDialog.addButton("Delete", QMessageBox::AcceptRole);
 
-   confirmDeleteDialog.addButton("Cancel", QMessageBox::RejectRole);
 
-   confirmDeleteDialog.setDontShowAgainSettingsKey( "MainWindow/DontConfirmDeleteSelected");
 
-   int response = confirmDeleteDialog.exec();
 
-   if (response == QMessageBox::AcceptRole)
 
-     {
 
-     return true;
 
-     }
 
-   else
 
-     {
 
-     return false;
 
-     }
 
- }
 
- //----------------------------------------------------------------------------
 
- void ctkDICOMBrowser::onPatientsRightClicked(const QPoint &point)
 
- {
 
-   Q_D(ctkDICOMBrowser);
 
-   // get the list of patients that are selected
 
-   QStringList selectedPatientsUIDs = d->dicomTableManager->currentPatientsSelection();
 
-   int numPatients = selectedPatientsUIDs.size();
 
-   if (numPatients == 0)
 
-     {
 
-     qDebug() << "No patients selected!";
 
-     return;
 
-     }
 
-   QMenu *patientsMenu = new QMenu(d->dicomTableManager);
 
-   QString deleteString = QString("Delete ")
 
-     + QString::number(numPatients)
 
-     + QString(" selected patients");
 
-   QAction *deleteAction = new QAction(deleteString, patientsMenu);
 
-   patientsMenu->addAction(deleteAction);
 
-   QString exportString = QString("Export ")
 
-     + QString::number(numPatients)
 
-     + QString(" selected patients to file system");
 
-   QAction *exportAction = new QAction(exportString, patientsMenu);
 
-   patientsMenu->addAction(exportAction);
 
-   // the table took care of mapping it to a global position so that the
 
-   // menu will pop up at the correct place over this table.
 
-   QAction *selectedAction = patientsMenu->exec(point);
 
-   if (selectedAction == deleteAction
 
-       && this->confirmDeleteSelectedUIDs(selectedPatientsUIDs))
 
-     {
 
-     qDebug() << "Deleting " << numPatients << " patients";
 
-     foreach (const QString& uid, selectedPatientsUIDs)
 
-       {
 
-       d->DICOMDatabase->removePatient(uid);
 
-       d->dicomTableManager->updateTableViews();
 
-       }
 
-     }
 
-   else if (selectedAction == exportAction)
 
-     {
 
-     ctkFileDialog* directoryDialog = new ctkFileDialog();
 
-     directoryDialog->setOption(QFileDialog::DontUseNativeDialog);
 
-     directoryDialog->setOption(QFileDialog::ShowDirsOnly);
 
-     directoryDialog->setFileMode(QFileDialog::DirectoryOnly);
 
-     bool res = directoryDialog->exec();
 
-     if (res)
 
-       {
 
-       QStringList dirs = directoryDialog->selectedFiles();
 
-       QString dirPath = dirs[0];
 
-       this->exportSelectedPatients(dirPath, selectedPatientsUIDs);
 
-       }
 
-     delete directoryDialog;
 
-     }
 
- }
 
- //----------------------------------------------------------------------------
 
- void ctkDICOMBrowser::onStudiesRightClicked(const QPoint &point)
 
- {
 
-   Q_D(ctkDICOMBrowser);
 
-   // get the list of studies that are selected
 
-   QStringList selectedStudiesUIDs = d->dicomTableManager->currentStudiesSelection();
 
-   int numStudies = selectedStudiesUIDs.size();
 
-   if (numStudies == 0)
 
-     {
 
-     qDebug() << "No studies selected!";
 
-     return;
 
-     }
 
-   QMenu *studiesMenu = new QMenu(d->dicomTableManager);
 
-   QString deleteString = QString("Delete ")
 
-     + QString::number(numStudies)
 
-     + QString(" selected studies");
 
-   QAction *deleteAction = new QAction(deleteString, studiesMenu);
 
-   studiesMenu->addAction(deleteAction);
 
-   QString exportString = QString("Export ")
 
-     + QString::number(numStudies)
 
-     + QString(" selected studies to file system");
 
-   QAction *exportAction = new QAction(exportString, studiesMenu);
 
-   studiesMenu->addAction(exportAction);
 
-   // the table took care of mapping it to a global position so that the
 
-   // menu will pop up at the correct place over this table.
 
-   QAction *selectedAction = studiesMenu->exec(point);
 
-   if (selectedAction == deleteAction
 
-       && this->confirmDeleteSelectedUIDs(selectedStudiesUIDs))
 
-     {
 
-     foreach (const QString& uid, selectedStudiesUIDs)
 
-       {
 
-       d->DICOMDatabase->removeStudy(uid);
 
-       d->dicomTableManager->updateTableViews();
 
-       }
 
-     }
 
-   else if (selectedAction == exportAction)
 
-     {
 
-     ctkFileDialog* directoryDialog = new ctkFileDialog();
 
-     directoryDialog->setOption(QFileDialog::DontUseNativeDialog);
 
-     directoryDialog->setOption(QFileDialog::ShowDirsOnly);
 
-     directoryDialog->setFileMode(QFileDialog::DirectoryOnly);
 
-     bool res = directoryDialog->exec();
 
-     if (res)
 
-       {
 
-       QStringList dirs = directoryDialog->selectedFiles();
 
-       QString dirPath = dirs[0];
 
-       this->exportSelectedStudies(dirPath, selectedStudiesUIDs);
 
-       }
 
-     delete directoryDialog;
 
-     }
 
- }
 
- //----------------------------------------------------------------------------
 
- void ctkDICOMBrowser::onSeriesRightClicked(const QPoint &point)
 
- {
 
-   Q_D(ctkDICOMBrowser);
 
-   // get the list of series that are selected
 
-   QStringList selectedSeriesUIDs = d->dicomTableManager->currentSeriesSelection();
 
-   int numSeries = selectedSeriesUIDs.size();
 
-   if (numSeries == 0)
 
-     {
 
-     qDebug() << "No series selected!";
 
-     return;
 
-     }
 
-   QMenu *seriesMenu = new QMenu(d->dicomTableManager);
 
-   QString deleteString = QString("Delete ")
 
-     + QString::number(numSeries)
 
-     + QString(" selected series");
 
-   QAction *deleteAction = new QAction(deleteString, seriesMenu);
 
-   seriesMenu->addAction(deleteAction);
 
-   QString exportString = QString("Export ")
 
-     + QString::number(numSeries)
 
-     + QString(" selected series to file system");
 
-   QAction *exportAction = new QAction(exportString, seriesMenu);
 
-   seriesMenu->addAction(exportAction);
 
-   // the table took care of mapping it to a global position so that the
 
-   // menu will pop up at the correct place over this table.
 
-   QAction *selectedAction = seriesMenu->exec(point);
 
-   if (selectedAction == deleteAction
 
-       && this->confirmDeleteSelectedUIDs(selectedSeriesUIDs))
 
-     {
 
-     foreach (const QString& uid, selectedSeriesUIDs)
 
-       {
 
-       d->DICOMDatabase->removeSeries(uid);
 
-       d->dicomTableManager->updateTableViews();
 
-       }
 
-     }
 
-   else if (selectedAction == exportAction)
 
-     {
 
-     ctkFileDialog* directoryDialog = new ctkFileDialog();
 
-     directoryDialog->setOption(QFileDialog::DontUseNativeDialog);
 
-     directoryDialog->setOption(QFileDialog::ShowDirsOnly);
 
-     directoryDialog->setFileMode(QFileDialog::DirectoryOnly);
 
-     bool res = directoryDialog->exec();
 
-     if (res)
 
-       {
 
-       QStringList dirs = directoryDialog->selectedFiles();
 
-       QString dirPath = dirs[0];
 
-       this->exportSelectedSeries(dirPath, selectedSeriesUIDs);
 
-       }
 
-     delete directoryDialog;
 
-     }
 
- }
 
- //----------------------------------------------------------------------------
 
- void ctkDICOMBrowser::exportSelectedSeries(QString dirPath, QStringList uids)
 
- {
 
-   Q_D(ctkDICOMBrowser);
 
-   foreach (const QString& uid, uids)
 
-     {
 
-     QStringList filesForSeries = d->DICOMDatabase->filesForSeries(uid);
 
-     // Use the first file to get the overall series information
 
-     QString firstFilePath = filesForSeries[0];
 
-     QHash<QString,QString> descriptions (d->DICOMDatabase->descriptionsForFile(firstFilePath));
 
-     QString patientName = descriptions["PatientsName"];
 
-     QString patientIDTag = QString("0010,0020");
 
-     QString patientID = d->DICOMDatabase->fileValue(firstFilePath, patientIDTag);
 
-     QString studyDescription = descriptions["StudyDescription"];
 
-     QString seriesDescription = descriptions["SeriesDescription"];
 
-     QString studyDateTag = QString("0008,0020");
 
-     QString studyDate = d->DICOMDatabase->fileValue(firstFilePath,studyDateTag);
 
-     QString seriesNumberTag = QString("0020,0011");
 
-     QString seriesNumber = d->DICOMDatabase->fileValue(firstFilePath,seriesNumberTag);
 
-     QString sep = "/";
 
-     QString nameSep = "-";
 
-     QString destinationDir = dirPath + sep + patientID;
 
-     if (!patientName.isEmpty())
 
-       {
 
-       destinationDir += nameSep + patientName;
 
-       }
 
-     destinationDir += sep + studyDate;
 
-     if (!studyDescription.isEmpty())
 
-       {
 
-       destinationDir += nameSep + studyDescription;
 
-       }
 
-     destinationDir += sep + seriesNumber;
 
-     if (!seriesDescription.isEmpty())
 
-       {
 
-       destinationDir += nameSep + seriesDescription;
 
-       }
 
-     destinationDir += sep;
 
-     // make sure only ascii characters are in the directory path
 
-     destinationDir = destinationDir.toLatin1();
 
-     // replace any question marks that were used as replacements for non ascii
 
-     // characters with underscore
 
-     destinationDir.replace("?", "_");
 
-     // create the destination directory if necessary
 
-     if (!QDir().exists(destinationDir))
 
-       {
 
-       if (!QDir().mkpath(destinationDir))
 
-         {
 
-         QString errorString =
 
-           QString("Unable to create export destination directory:\n\n")
 
-           + destinationDir
 
-           + QString("\n\nHalting export.");
 
-         ctkMessageBox createDirectoryErrorMessageBox;
 
-         createDirectoryErrorMessageBox.setText(errorString);
 
-         createDirectoryErrorMessageBox.setIcon(QMessageBox::Warning);
 
-         createDirectoryErrorMessageBox.exec();
 
-         return;
 
-         }
 
-       }
 
-     // show progress
 
-     if (d->ExportProgress == 0)
 
-       {
 
-       d->ExportProgress = new QProgressDialog(this->tr("DICOM Export"), "Close", 0, 100, this, Qt::WindowTitleHint | Qt::WindowSystemMenuHint);
 
-       d->ExportProgress->setWindowModality(Qt::ApplicationModal);
 
-       d->ExportProgress->setMinimumDuration(0);
 
-       }
 
-     QLabel *exportLabel = new QLabel(this->tr("Exporting series ") + seriesNumber);
 
-     d->ExportProgress->setLabel(exportLabel);
 
-     d->ExportProgress->setValue(0);
 
-     int fileNumber = 0;
 
-     int numFiles = filesForSeries.size();
 
-     d->ExportProgress->setMaximum(numFiles);
 
-     foreach (const QString& filePath, filesForSeries)
 
-       {
 
-       QString destinationFileName = destinationDir;
 
-       QString fileNumberString;
 
-       // sequentially number the files
 
-       fileNumberString.sprintf("%06d", fileNumber);
 
-       destinationFileName += fileNumberString + QString(".dcm");
 
-       // replace non ASCII characters
 
-       destinationFileName = destinationFileName.toLatin1();
 
-       // replace any question marks that were used as replacements for non ascii
 
-       // characters with underscore
 
-       destinationFileName.replace("?", "_");
 
-       if (!QFile::exists(filePath))
 
-         {
 
-         d->ExportProgress->setValue(numFiles);
 
-         QString errorString = QString("Export source file not found:\n\n")
 
-           + filePath
 
-           + QString("\n\nHalting export.\n\nError may be fixed via Repair.");
 
-         ctkMessageBox copyErrorMessageBox;
 
-         copyErrorMessageBox.setText(errorString);
 
-         copyErrorMessageBox.setIcon(QMessageBox::Warning);
 
-         copyErrorMessageBox.exec();
 
-         return;
 
-       }
 
-       if (QFile::exists(destinationFileName))
 
-         {
 
-         d->ExportProgress->setValue(numFiles);
 
-         QString errorString = QString("Export destination file already exists:\n\n")
 
-           + destinationFileName
 
-           + QString("\n\nHalting export.");
 
-         ctkMessageBox copyErrorMessageBox;
 
-         copyErrorMessageBox.setText(errorString);
 
-         copyErrorMessageBox.setIcon(QMessageBox::Warning);
 
-         copyErrorMessageBox.exec();
 
-         return;
 
-         }
 
-       bool copyResult = QFile::copy(filePath, destinationFileName);
 
-       if (!copyResult)
 
-         {
 
-         d->ExportProgress->setValue(numFiles);
 
-         QString errorString = QString("Failed to copy\n\n")
 
-           + filePath
 
-           + QString("\n\nto\n\n")
 
-           + destinationFileName
 
-           + QString("\n\nHalting export.");
 
-         ctkMessageBox copyErrorMessageBox;
 
-         copyErrorMessageBox.setText(errorString);
 
-         copyErrorMessageBox.setIcon(QMessageBox::Warning);
 
-         copyErrorMessageBox.exec();
 
-         return;
 
-         }
 
-       fileNumber++;
 
-       d->ExportProgress->setValue(fileNumber);
 
-       }
 
-     d->ExportProgress->setValue(numFiles);
 
-     }
 
- }
 
- //----------------------------------------------------------------------------
 
- void ctkDICOMBrowser::exportSelectedStudies(QString dirPath, QStringList uids)
 
- {
 
-   Q_D(ctkDICOMBrowser);
 
-   foreach (const QString& uid, uids)
 
-     {
 
-     QStringList seriesUIDs = d->DICOMDatabase->seriesForStudy(uid);
 
-     this->exportSelectedSeries(dirPath, seriesUIDs);
 
-     }
 
- }
 
- //----------------------------------------------------------------------------
 
- void ctkDICOMBrowser::exportSelectedPatients(QString dirPath, QStringList uids)
 
- {
 
-   Q_D(ctkDICOMBrowser);
 
-   foreach (const QString& uid, uids)
 
-     {
 
-     QStringList studiesUIDs = d->DICOMDatabase->studiesForPatient(uid);
 
-     this->exportSelectedStudies(dirPath, studiesUIDs);
 
-     }
 
- }
 
 
  |