Sfoglia il codice sorgente

Merge branch 'refactor-dicom-database-and-model'

Marco Nolden 13 anni fa
parent
commit
5d5b6ea886

+ 2 - 0
Libs/DICOM/Core/CMakeLists.txt

@@ -19,6 +19,7 @@ set(KIT_SRCS
   ctkDICOMFilterProxyModel.h
   ctkDICOMIndexer.cpp
   ctkDICOMIndexer.h
+  ctkDICOMIndexerPrivate.h
   ctkDICOMModel.cpp
   ctkDICOMModel.h
   ctkDICOMPersonName.cpp
@@ -42,6 +43,7 @@ set(KIT_MOC_SRCS
   ctkDICOMAbstractThumbnailGenerator.h
   ctkDICOMDatabase.h
   ctkDICOMIndexer.h
+  ctkDICOMIndexerPrivate.h
   ctkDICOMFilterProxyModel.h
   ctkDICOMModel.h
   ctkDICOMQuery.h

File diff suppressed because it is too large
+ 441 - 399
Libs/DICOM/Core/ctkDICOMDatabase.cpp


+ 1 - 1
Libs/DICOM/Core/ctkDICOMDatabase.h

@@ -152,7 +152,7 @@ public:
   bool fileExistsAndUpToDate(const QString& filePath);
 
   /// remove the series from the database, including images and
-  /// thumbnails  
+  /// thumbnails
   Q_INVOKABLE bool removeSeries(const QString& seriesInstanceUID);
   Q_INVOKABLE bool removeStudy(const QString& studyInstanceUID);
   Q_INVOKABLE bool removePatient(const QString& patientID);

+ 51 - 20
Libs/DICOM/Core/ctkDICOMIndexer.cpp

@@ -18,6 +18,8 @@
 
 =========================================================================*/
 
+#include <tr1/functional>
+
 // Qt includes
 #include <QSqlQuery>
 #include <QSqlRecord>
@@ -31,11 +33,13 @@
 #include <QFileInfo>
 #include <QDebug>
 #include <QPixmap>
-
+#include <QtConcurrentRun>
 
 // ctkDICOM includes
 #include "ctkLogger.h"
 #include "ctkDICOMIndexer.h"
+#include "ctkDICOMIndexerPrivate.h"
+#include "ctkDICOMDatabase.h"
 
 // DCMTK includes
 #include <dcmtk/dcmdata/dcfilefo.h>
@@ -49,30 +53,41 @@
 #include <dcmtk/dcmimgle/dcmimage.h>  /* for class DicomImage */
 #include <dcmtk/dcmimage/diregist.h>  /* include support for color images */
 
+class AddFileFunctor
+{
+public:
+     AddFileFunctor(ctkDICOMIndexer* indexer, ctkDICOMDatabase& database,
+                    const QString& destinationDirectoryName = "")
+       : Indexer(indexer), Database(database), DestinationDirectoryName(destinationDirectoryName) { }
+
+     bool operator()(const QString &filePath)
+     {
+         Indexer->addFile(Database,filePath,DestinationDirectoryName);
+         return false; // make sure it is removed;
+     }
+
+     ctkDICOMIndexer* Indexer;
+     ctkDICOMDatabase& Database;
+     QString DestinationDirectoryName;
+
+ };
+
 
 //------------------------------------------------------------------------------
 static ctkLogger logger("org.commontk.dicom.DICOMIndexer" );
 //------------------------------------------------------------------------------
 
-//------------------------------------------------------------------------------
-class ctkDICOMIndexerPrivate
-{
-public:
-  ctkDICOMIndexerPrivate();
-  ~ctkDICOMIndexerPrivate();
-
-  ctkDICOMAbstractThumbnailGenerator* thumbnailGenerator;
-  bool                    Canceled;
-
-};
 
 //------------------------------------------------------------------------------
 // ctkDICOMIndexerPrivate methods
 
 //------------------------------------------------------------------------------
-ctkDICOMIndexerPrivate::ctkDICOMIndexerPrivate()
+ctkDICOMIndexerPrivate::ctkDICOMIndexerPrivate(ctkDICOMIndexer& o) : q_ptr(&o), Canceled(false), CurrentPercentageProgress(-1)
 {
-  this->Canceled = false;
+  Q_Q(ctkDICOMIndexer);
+  connect(&DirectoryImportWatcher,SIGNAL(progressValueChanged(int)),this,SLOT(OnProgress(int)));
+  connect(&DirectoryImportWatcher,SIGNAL(finished()),q,SIGNAL(indexingComplete()));
+  connect(&DirectoryImportWatcher,SIGNAL(canceled()),q,SIGNAL(indexingComplete()));
 }
 
 //------------------------------------------------------------------------------
@@ -80,13 +95,26 @@ ctkDICOMIndexerPrivate::~ctkDICOMIndexerPrivate()
 {
 }
 
+void ctkDICOMIndexerPrivate::OnProgress(int progress)
+{
+  Q_Q(ctkDICOMIndexer);
+
+  int newPercentageProgress = ( 100 * DirectoryImportFuture.progressValue() ) / DirectoryImportFuture.progressMaximum();
+  if (newPercentageProgress != CurrentPercentageProgress)
+    {
+      CurrentPercentageProgress = newPercentageProgress;
+      emit q->progress(newPercentageProgress);
+    }
+
+}
+
 //------------------------------------------------------------------------------
 
 //------------------------------------------------------------------------------
 // ctkDICOMIndexer methods
 
 //------------------------------------------------------------------------------
-ctkDICOMIndexer::ctkDICOMIndexer(QObject *parent):d_ptr(new ctkDICOMIndexerPrivate)
+ctkDICOMIndexer::ctkDICOMIndexer(QObject *parent):d_ptr(new ctkDICOMIndexerPrivate(*this))
 {
   Q_UNUSED(parent);
 }
@@ -97,10 +125,11 @@ ctkDICOMIndexer::~ctkDICOMIndexer()
 }
 
 //------------------------------------------------------------------------------
-void ctkDICOMIndexer::addFile(ctkDICOMDatabase& ctkDICOMDatabase, 
-                                   const QString& filePath,
+void ctkDICOMIndexer::addFile(ctkDICOMDatabase& database,
+                                   const QString filePath,
                                    const QString& destinationDirectoryName)
 {
+  std::cout << filePath.toStdString();
   if (!destinationDirectoryName.isEmpty())
   {
     logger.warn("Ignoring destinationDirectoryName parameter, just taking it as indication we should copy!");
@@ -108,7 +137,7 @@ void ctkDICOMIndexer::addFile(ctkDICOMDatabase& ctkDICOMDatabase,
 
   emit indexingFilePath(filePath);
 
-  ctkDICOMDatabase.insert(filePath, !destinationDirectoryName.isEmpty(), true);
+  database.insert(filePath, !destinationDirectoryName.isEmpty(), true);
 }
 
 //------------------------------------------------------------------------------
@@ -158,9 +187,11 @@ void ctkDICOMIndexer::addDirectory(ctkDICOMDatabase& ctkDICOMDatabase,
       emit progress( currentProgress );
     }
     QString filePath((*iter).c_str());
-    this->addFile(ctkDICOMDatabase, filePath, destinationDirectoryName);
+    d->FilesToIndex << filePath;
     ++iter;
   }
+  d->DirectoryImportFuture = QtConcurrent::filter(d->FilesToIndex,AddFileFunctor(this,ctkDICOMDatabase,destinationDirectoryName));
+  d->DirectoryImportWatcher.setFuture(d->DirectoryImportFuture);
 }
 
 //------------------------------------------------------------------------------
@@ -208,5 +239,5 @@ void ctkDICOMIndexer::refreshDatabase(ctkDICOMDatabase& dicomDatabase, const QSt
 void ctkDICOMIndexer::cancel()
 {
   Q_D(ctkDICOMIndexer);
-  d->Canceled = true;
+  d->DirectoryImportWatcher.cancel();
 }

+ 2 - 1
Libs/DICOM/Core/ctkDICOMIndexer.h

@@ -58,7 +58,7 @@ public:
   /// Scan the file using Dcmtk and populate the database with all the
   /// DICOM fields accordingly.
   ///
-  Q_INVOKABLE void addFile(ctkDICOMDatabase& database, const QString& filePath,
+  Q_INVOKABLE void addFile(ctkDICOMDatabase& database, const QString filePath,
                     const QString& destinationDirectoryName = "");
 
   Q_INVOKABLE void refreshDatabase(ctkDICOMDatabase& database, const QString& directoryName);
@@ -68,6 +68,7 @@ Q_SIGNALS:
   void indexingFileNumber(int);
   void indexingFilePath(QString);
   void progress(int);
+  void indexingComplete();
 
 public Q_SLOTS:
   void cancel();

+ 56 - 0
Libs/DICOM/Core/ctkDICOMIndexerPrivate.h

@@ -0,0 +1,56 @@
+/*=========================================================================
+
+  Library:   CTK
+
+  Copyright (c) German Cancer Research Center
+
+  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.
+
+=========================================================================*/
+
+#ifndef CTKDICOMINDEXERPRIVATE_H
+#define CTKDICOMINDEXERPRIVATE_H
+
+#include <QObject>
+
+#include "ctkDICOMIndexer.h"
+
+//------------------------------------------------------------------------------
+class ctkDICOMIndexerPrivate : public QObject
+{
+  Q_OBJECT
+
+  Q_DECLARE_PUBLIC(ctkDICOMIndexer);
+
+protected:
+  ctkDICOMIndexer* const q_ptr;
+
+public:
+  ctkDICOMIndexerPrivate(ctkDICOMIndexer&);
+  ~ctkDICOMIndexerPrivate();
+
+public Q_SLOTS:
+
+  void OnProgress(int progress);
+public:
+
+  ctkDICOMAbstractThumbnailGenerator* thumbnailGenerator;
+  bool                    Canceled;
+  QStringList FilesToIndex;
+  QFutureWatcher<void> DirectoryImportWatcher;
+  QFuture<void> DirectoryImportFuture;
+  int CurrentPercentageProgress;
+};
+
+
+#endif // CTKDICOMINDEXERPRIVATE_H

+ 12 - 9
Libs/DICOM/Widgets/ctkDICOMAppWidget.cpp

@@ -424,30 +424,33 @@ void ctkDICOMAppWidget::onImportDirectory(QString directory)
       {
       targetDirectory = d->DICOMDatabase->databaseDirectory();
       }
-    QProgressDialog progress("DICOM Import", "Cancel", 0, 100, this,
+    QProgressDialog* progress = new QProgressDialog("DICOM Import", "Cancel", 0, 100, this,
                            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(tr("Initialization..."));
-    progress.setLabel(progressLabel);
+    progress->setLabel(progressLabel);
 #ifdef Q_WS_MAC
     // BUG: avoid deadlock of dialogs on mac
-    progress.setWindowModality(Qt::NonModal);
+    progress->setWindowModality(Qt::NonModal);
 #else
-    progress.setWindowModality(Qt::ApplicationModal);
+    progress->setWindowModality(Qt::ApplicationModal);
 #endif
-    progress.setMinimumDuration(0);
-    progress.setValue(0);
-    progress.show();
+    progress->setMinimumDuration(0);
+    progress->setValue(0);
+    progress->show();
 
-    connect(&progress, SIGNAL(canceled()), d->DICOMIndexer.data(), SLOT(cancel()));
+    connect(progress, SIGNAL(canceled()), d->DICOMIndexer.data(), SLOT(cancel()));
     connect(d->DICOMIndexer.data(), SIGNAL(indexingFilePath(QString)),
             progressLabel, SLOT(setText(QString)));
     connect(d->DICOMIndexer.data(), SIGNAL(progress(int)),
-            &progress, SLOT(setValue(int)));
+            progress, SLOT(setValue(int)));
     connect(d->DICOMIndexer.data(), SIGNAL(progress(int)),
             this, SLOT(onProgress(int)));
 
+    connect(d->DICOMIndexer.data(), SIGNAL(indexingComplete()),
+            progress, SLOT(close()));
+
     d->DICOMIndexer->addDirectory(*d->DICOMDatabase,directory,targetDirectory);
 
     d->DICOMModel.reset();