瀏覽代碼

Moved a few methods from ctkDICOMIndexer to ctkDICOMDatabase

Marco Nolden 13 年之前
父節點
當前提交
21aab94b85

+ 404 - 0
Libs/DICOM/Core/ctkDICOMDatabase.cpp

@@ -73,6 +73,11 @@ public:
   void init(QString databaseFile);
   void registerCompressionLibraries();
   bool executeScript(const QString script);
+  ///
+  /// \brief runs a query and prints debug output of status
+  ///
+  bool loggedExec(QSqlQuery& query);
+  bool loggedExec(QSqlQuery& query, const QString& queryString);
 
   /// Name of the database file (i.e. for SQLITE the sqlite file)
   QString      DatabaseFileName;
@@ -81,6 +86,15 @@ public:
   QMap<QString, QString> LoadedHeader;
 
   ctkDICOMAbstractThumbnailGenerator* thumbnailGenerator;
+  
+  /// these are for optimizing the import of image sequences
+  /// since most information are identical for all slices
+  OFString lastPatientID;
+  OFString lastPatientsName;
+  OFString lastPatientsBirthDate;
+  OFString lastStudyInstanceUID;
+  OFString lastSeriesInstanceUID;
+  int lastPatientUID;
 };
 
 //------------------------------------------------------------------------------
@@ -121,6 +135,37 @@ ctkDICOMDatabasePrivate::~ctkDICOMDatabasePrivate()
 }
 
 //------------------------------------------------------------------------------
+bool ctkDICOMDatabasePrivate::loggedExec(QSqlQuery& query)
+{
+  return (loggedExec(query, QString("")));
+}
+
+//------------------------------------------------------------------------------
+bool ctkDICOMDatabasePrivate::loggedExec(QSqlQuery& query, const QString& queryString)
+{
+  bool success;
+  if (queryString.compare(""))
+    {
+    success = query.exec(queryString);
+    }
+  else
+    {
+    success = query.exec();
+    }
+  if (!success)
+    {
+    QSqlError sqlError = query.lastError();
+    logger.debug( "SQL failed\n Bad SQL: " + query.lastQuery());
+    logger.debug( "Error text: " + sqlError.text());
+    }
+  else
+    {
+  logger.debug( "SQL worked!\n SQL: " + query.lastQuery());
+    }
+  return (success);
+}
+
+//------------------------------------------------------------------------------
 void ctkDICOMDatabase::openDatabase(const QString databaseFile, const QString& connectionName )
 {
   Q_D(ctkDICOMDatabase);
@@ -618,6 +663,365 @@ void ctkDICOMDatabase::insert ( DcmDataset *dataset, bool storeFile, bool genera
     }
 }
 
+//------------------------------------------------------------------------------
+void ctkDICOMDatabase::insert ( const QString& filePath, bool storeFile, bool generateThumbnail, bool createHierarchy, const QString& destinationDirectoryName)
+{
+  Q_D(ctkDICOMDatabase);
+  
+  /// first we check if the file is already in the database
+  if (fileExistsAndUpToDate(filePath))
+  {
+    logger.debug( "File " + filePath + " already added.");
+    return;
+  }
+
+  logger.debug( "Processing " + filePath ); 
+
+  std::string filename = filePath.toStdString();
+
+  DcmFileFormat fileformat;
+  DcmDataset *dataset;
+
+  OFCondition status = fileformat.loadFile(filename.c_str());
+
+  dataset = fileformat.getDataset();
+
+  if (!status.good())
+  {
+    logger.error( "Could not load " + filePath );
+    logger.error( "DCMTK says: " + QString(status.text()) );
+    return;
+  }
+  
+  // ok, we have loaded a dataset
+
+
+  OFString patientsName, patientID, patientsBirthDate, patientsBirthTime, patientsSex,
+    patientComments, patientsAge;
+
+  OFString studyInstanceUID, studyID, studyDate, studyTime,
+    accessionNumber, modalitiesInStudy, institutionName, performingPhysiciansName, referringPhysician, studyDescription;
+
+  OFString seriesInstanceUID, seriesDate, seriesTime,
+    seriesDescription, bodyPartExamined, frameOfReferenceUID,
+    contrastAgent, scanningSequence;
+  OFString instanceNumber, sopInstanceUID ;
+
+  Sint32 seriesNumber = 0, acquisitionNumber = 0, echoNumber = 0, temporalPosition = 0;
+
+  //The patient UID is a unique number within the database, generated by the sqlite autoincrement
+  //Thus, this is _not_ the DICOM Patient ID.
+  int patientUID = -1;
+
+  //If the following fields can not be evaluated, cancel evaluation of the DICOM file
+  if (!dataset->findAndGetOFString(DCM_PatientName, patientsName).good())
+  {
+    logger.error( "Could not read DCM_PatientName from " + filePath );
+    return;
+  }
+
+  if (!dataset->findAndGetOFString(DCM_StudyInstanceUID, studyInstanceUID).good())
+  {
+    logger.error( "Could not read DCM_StudyInstanceUID from " + filePath );
+    return;
+  }
+
+  if (!dataset->findAndGetOFString(DCM_SeriesInstanceUID, seriesInstanceUID).good())
+  {
+    logger.error( "Could not read DCM_SeriesInstanceUID from " + filePath );
+    return;
+  }
+
+  if (!dataset->findAndGetOFString(DCM_SOPInstanceUID, sopInstanceUID).good())
+  {
+    logger.error( "Could not read DCM_SOPInstanceUID from " + filePath );
+    return;
+  }
+  if (!dataset->findAndGetOFString(DCM_InstanceNumber, instanceNumber).good())
+  {
+    logger.error( "Could not read DCM_InstanceNumber from " + filePath );
+    return;
+  }
+
+
+  dataset->findAndGetOFString(DCM_PatientID, patientID);
+  dataset->findAndGetOFString(DCM_PatientBirthDate, patientsBirthDate);
+  dataset->findAndGetOFString(DCM_PatientBirthTime, patientsBirthTime);
+  dataset->findAndGetOFString(DCM_PatientSex, patientsSex);
+  dataset->findAndGetOFString(DCM_PatientAge, patientsAge);
+  dataset->findAndGetOFString(DCM_PatientComments, patientComments);
+  dataset->findAndGetOFString(DCM_StudyID, studyID);
+  dataset->findAndGetOFString(DCM_StudyDate, studyDate);
+  dataset->findAndGetOFString(DCM_StudyTime, studyTime);
+  dataset->findAndGetOFString(DCM_AccessionNumber, accessionNumber);
+  dataset->findAndGetOFString(DCM_ModalitiesInStudy, modalitiesInStudy);
+  dataset->findAndGetOFString(DCM_InstitutionName, institutionName);
+  dataset->findAndGetOFString(DCM_PerformingPhysicianName, performingPhysiciansName);
+  dataset->findAndGetOFString(DCM_ReferringPhysicianName, referringPhysician);
+  dataset->findAndGetOFString(DCM_StudyDescription, studyDescription);
+
+  dataset->findAndGetOFString(DCM_SeriesDate, seriesDate);
+  dataset->findAndGetOFString(DCM_SeriesTime, seriesTime);
+  dataset->findAndGetOFString(DCM_SeriesDescription, seriesDescription);
+  dataset->findAndGetOFString(DCM_BodyPartExamined, bodyPartExamined);
+  dataset->findAndGetOFString(DCM_FrameOfReferenceUID, frameOfReferenceUID);
+  dataset->findAndGetOFString(DCM_ContrastBolusAgent, contrastAgent);
+  dataset->findAndGetOFString(DCM_ScanningSequence, scanningSequence);
+
+  dataset->findAndGetSint32(DCM_SeriesNumber, seriesNumber);
+  dataset->findAndGetSint32(DCM_AcquisitionNumber, acquisitionNumber);
+  dataset->findAndGetSint32(DCM_EchoNumbers, echoNumber);
+  dataset->findAndGetSint32(DCM_TemporalPositionIdentifier, temporalPosition);
+
+  logger.debug( "Adding new items to database:" );
+  logger.debug( "studyID: " + QString(studyID.c_str()) );
+  logger.debug( "seriesInstanceUID: " + QString(seriesInstanceUID.c_str()) );
+  logger.debug( "Patient's Name: " + QString(patientsName.c_str()) );
+
+  //-----------------------
+  //Add Patient to Database
+  //-----------------------
+
+  //Speed up: Check if patient is the same as in last file; very probable, as all images belonging to a study have the same patient
+  bool patientExists = false;
+  if(d->lastPatientID.compare(patientID) || d->lastPatientsBirthDate.compare(patientsBirthDate) || d->lastPatientsName.compare(patientsName))
+  {
+    //Check if patient is already present in the db
+    QSqlQuery check_exists_query(database());
+    std::stringstream check_exists_query_string;
+    check_exists_query_string << "SELECT * FROM Patients WHERE PatientID = '" << patientID << "'";
+    d->loggedExec(check_exists_query, check_exists_query_string.str().c_str());
+
+    /// we check only patients with the same PatientID
+    /// PatientID is not unique in DICOM, so we also compare Name and BirthDate
+    /// and assume this is sufficient
+    while (check_exists_query.next())
+    {
+      if (
+          check_exists_query.record().value("PatientsName").toString() == patientsName.c_str() &&
+          check_exists_query.record().value("PatientsBirthDate").toString() == patientsBirthDate.c_str()
+         )
+      {
+        /// found it
+        patientUID = check_exists_query.value(check_exists_query.record().indexOf("UID")).toInt();
+        patientExists = true;
+        break;
+      }
+    }
+    check_exists_query.finish();
+
+    if(!patientExists)
+    {
+
+      QSqlQuery insert_patient_query(database());
+
+      std::stringstream query_string;
+
+      query_string << "INSERT INTO Patients VALUES( NULL,'"
+      << patientsName << "','"
+      << patientID << "','"
+      << patientsBirthDate << "','"
+      << patientsBirthTime << "','"
+      << patientsSex << "','"
+      << patientsAge << "','"
+      << patientComments << "')";
+
+      d->loggedExec(insert_patient_query, query_string.str().c_str());
+
+      patientUID = insert_patient_query.lastInsertId().toInt();
+      insert_patient_query.finish();
+      QString patientUIDQString;
+      patientUIDQString.setNum(patientUID);
+      logger.debug( "New patient inserted: " + patientUIDQString );
+    }
+  }
+  else
+    {
+    patientUID = d->lastPatientUID;
+    }
+
+  /// keep this for the next image
+  d->lastPatientUID = patientUID;
+  d->lastPatientID = patientID;
+  d->lastPatientsBirthDate = patientsBirthDate;
+  d->lastPatientsName = patientsName;
+
+  //---------------------
+  //Add Study to Database
+  //---------------------
+
+  if(d->lastStudyInstanceUID.compare(studyInstanceUID))
+  {
+    QSqlQuery check_exists_query(database());
+    std::stringstream check_exists_query_string;
+    check_exists_query_string << "SELECT * FROM Studies WHERE StudyInstanceUID = '" << studyInstanceUID << "'";
+    d->loggedExec(check_exists_query, check_exists_query_string.str().c_str());
+
+    logger.debug( "Checking for study: " + QString(studyInstanceUID.c_str()) );
+
+    if(!check_exists_query.next())
+    {
+
+      QSqlQuery insert_query(database());
+      std::stringstream query_string;
+
+      // TODO: all INSERTS should be changed to use the prepare/bindValue methods
+      // to avoid quoting issues
+      insert_query.prepare("INSERT INTO Studies (StudyInstanceUID, PatientsUID, StudyID, StudyDate, StudyTime, AccessionNumber, ModalitiesInStudy, InstitutionName, ReferringPhysician, PerformingPhysiciansName, StudyDescription) VALUES (:StudyInstanceUID, :PatientsUID, :StudyID, :StudyDate, :StudyTime, :AccessionNumber, :ModalitiesInStudy, :InstitutionName, :ReferringPhysician, :PerformingPhysiciansName, :StudyDescription)");
+
+      insert_query.bindValue(":StudyInstanceUID", QString(studyInstanceUID.c_str()));
+      insert_query.bindValue(":PatientsUID", patientUID);
+      insert_query.bindValue(":StudyID", QString(studyID.c_str()));
+      insert_query.bindValue(":StudyDate", QDate::fromString(studyDate.c_str(), "yyyyMMdd").toString("yyyy-MM-dd"));
+      insert_query.bindValue(":StudyTime", QString(studyTime.c_str()));
+      insert_query.bindValue(":AccessionNumber", QString(accessionNumber.c_str()));
+      insert_query.bindValue(":ModalitiesInStudy", QString(modalitiesInStudy.c_str()));
+      insert_query.bindValue(":InstitutionName", QString(institutionName.c_str()));
+      insert_query.bindValue(":ReferringPhysician", QString(referringPhysician.c_str()));
+      insert_query.bindValue(":PerformingPhysiciansName", QString(performingPhysiciansName.c_str()));
+      insert_query.bindValue(":StudyDescription", QString(studyDescription.c_str()));
+
+      d->loggedExec(insert_query);
+      logger.debug( "Inserted study: " + QString(studyInstanceUID.c_str()) );
+    }
+  }
+
+  d->lastStudyInstanceUID = studyInstanceUID;
+
+  //----------------------
+  //Add Series to Database
+  //----------------------
+
+  if(d->lastSeriesInstanceUID.compare(seriesInstanceUID))
+  {
+
+    QSqlQuery check_exists_query(database());
+    std::stringstream check_exists_query_string;
+    check_exists_query_string << "SELECT * FROM Series WHERE SeriesInstanceUID = '" << seriesInstanceUID << "'";
+    d->loggedExec(check_exists_query, check_exists_query_string.str().c_str());
+
+    logger.debug( "Checking series: " + QString(seriesInstanceUID.c_str()) );
+
+    if(!check_exists_query.next())
+    {
+
+      QSqlQuery insert_query(database());
+      std::stringstream query_string;
+
+      query_string << "INSERT INTO Series VALUES('"
+        << seriesInstanceUID << "','"
+        << studyInstanceUID << "','"
+        << static_cast<int>(seriesNumber) << "','"
+        << QDate::fromString(seriesDate.c_str(), "yyyyMMdd").toString("yyyy-MM-dd").toStdString() << "','"
+        << seriesTime << "','"
+        << seriesDescription << "','"
+        << bodyPartExamined << "','"
+        << frameOfReferenceUID << "','"
+        << static_cast<int>(acquisitionNumber) << "','"
+        << contrastAgent << "','"
+        << scanningSequence << "','"
+        << static_cast<int>(echoNumber) << "','"
+        << static_cast<int>(temporalPosition) << "')";
+
+      d->loggedExec(insert_query, query_string.str().c_str());
+      logger.debug( "Inserted series: " + QString(seriesInstanceUID.c_str()) );
+    }
+  }
+
+  d->lastSeriesInstanceUID = seriesInstanceUID;
+
+  QString studySeriesDirectory = QString(studyInstanceUID.c_str()) + "/" + seriesInstanceUID.c_str();
+
+  //----------------------------------
+  //Move file to destination directory
+  //----------------------------------
+
+  QString finalFilePath(filePath);
+  if (!destinationDirectoryName.isEmpty())
+  {
+    QFile currentFile( filePath );
+    QDir destinationDir(destinationDirectoryName + "/dicom");
+    finalFilePath = sopInstanceUID.c_str();
+    if (createHierarchy)
+    {
+      destinationDir.mkpath(studySeriesDirectory);
+      finalFilePath.prepend( destinationDir.absolutePath() + "/"  + studySeriesDirectory + "/" );
+    }
+    currentFile.copy(finalFilePath);
+    logger.debug( "Copy file from: " + filePath );
+    logger.debug( "Copy file to  : " + finalFilePath );
+  }
+  logger.debug(QString("finalFilePath: ") + finalFilePath);
+
+  if (generateThumbnail)
+  {
+    if(d->thumbnailGenerator)
+    {
+      QString thumbnailBaseDir =  databaseDirectory() + "/thumbs/";
+      QString thumbnailFilename = thumbnailBaseDir + "/" + pathForDataset(dataset) + ".png";
+      QFileInfo thumbnailInfo(thumbnailFilename);
+      if ( ! ( thumbnailInfo.exists() && thumbnailInfo.lastModified() < QFileInfo(finalFilePath).lastModified() ) )
+      {
+        QDir(thumbnailBaseDir).mkpath(studySeriesDirectory);
+        DicomImage dcmtkImage(QDir::toNativeSeparators(finalFilePath).toStdString().c_str());
+        d->thumbnailGenerator->generateThumbnail(&dcmtkImage, thumbnailFilename);
+      }
+    }
+  }
+
+  //------------------------
+  //Add Filename to Database
+  //------------------------
+
+//    std::stringstream relativeFilePath;
+//    relativeFilePath << seriesInstanceUID.c_str() << "/" << currentFilePath.getFileName();
+
+  logger.debug(QString("Adding file path to dabase: ") + finalFilePath);
+
+  QSqlQuery check_exists_query(database());
+  std::stringstream check_exists_query_string;
+//    check_exists_query_string << "SELECT * FROM Images WHERE Filename = '" << relativeFilePath.str() << "'";
+  check_exists_query_string << "SELECT * FROM Images WHERE SOPInstanceUID = '" << sopInstanceUID << "'";
+  d->loggedExec(check_exists_query, check_exists_query_string.str().c_str());
+
+  if(!check_exists_query.next())
+  {
+    QSqlQuery insert_query(database());
+    std::stringstream query_string;
+
+    //To save absolute path: destDirectoryPath.str()
+    query_string << "INSERT INTO Images VALUES('"
+      << sopInstanceUID << "','" << finalFilePath.toStdString() << "','" << seriesInstanceUID << "','" << QDateTime::currentDateTime().toString(Qt::ISODate).toStdString() << "')";
+
+    d->loggedExec(insert_query, query_string.str().c_str());
+    logger.debug(QString("added file path to dabase: ") + query_string.str().c_str());
+  }
+
+
+
+}
+
+bool ctkDICOMDatabase::fileExistsAndUpToDate(const QString& filePath)
+{
+  Q_D(ctkDICOMDatabase);
+  bool result(false);
+
+  QSqlQuery check_filename_query(database());
+  check_filename_query.prepare("SELECT InsertTimestamp FROM Images WHERE Filename == ?");
+  check_filename_query.bindValue(0,filePath);
+  d->loggedExec(check_filename_query);
+  if (
+    check_filename_query.next() &&
+    QFileInfo(filePath).lastModified() < QDateTime::fromString(check_filename_query.value(0).toString(),Qt::ISODate)
+    )
+  {
+    result = true;
+  }
+  check_filename_query.finish();
+  return result; 
+}
+
+
 bool ctkDICOMDatabase::isOpen() const
 {
   Q_D(const ctkDICOMDatabase);

+ 6 - 0
Libs/DICOM/Core/ctkDICOMDatabase.h

@@ -48,6 +48,7 @@ class ctkDICOMAbstractThumbnailGenerator;
 /// parallel to "dicom" directory called "thumbs".
 class CTK_DICOM_CORE_EXPORT ctkDICOMDatabase : public QObject
 {
+
   Q_OBJECT
   Q_PROPERTY(bool isOpen READ isOpen)
   Q_PROPERTY(QString lastError READ lastError)
@@ -137,10 +138,15 @@ public:
   /// @param @generateThumbnail If true, a thumbnail is generated.
   ///
   void insert ( DcmDataset *dataset, bool storeFile = true, bool generateThumbnail = true);
+  void insert ( const QString& filePath, bool storeFile = true, bool generateThumbnail = true, bool createHierarchy = true, const QString& destinationDirectoryName = QString() );
   ///
   /// Helper method: get the path that should be used to store this image.
   ///
   QString pathForDataset( DcmDataset *dataset);
+  
+  /// Check if file is already in database and up-to-date
+  bool fileExistsAndUpToDate(const QString& filePath);
+
 
 signals:
   void databaseChanged();

+ 17 - 371
Libs/DICOM/Core/ctkDICOMIndexer.cpp

@@ -64,14 +64,6 @@ public:
 
   ctkDICOMAbstractThumbnailGenerator* thumbnailGenerator;
 
-  /// these are for optimizing the import of image sequences
-  /// since most information are identical for all slices
-  OFString lastPatientID;
-  OFString lastPatientsName;
-  OFString lastPatientsBirthDate;
-  OFString lastStudyInstanceUID;
-  OFString lastSeriesInstanceUID;
-  int lastPatientUID;
 };
 
 //------------------------------------------------------------------------------
@@ -82,12 +74,17 @@ ctkDICOMIndexerPrivate::ctkDICOMIndexerPrivate()
 {
     this->thumbnailGenerator = NULL;
 
+    /*
+     * moved to database
+     *
+     * 
     this->lastPatientID = "";
     this->lastPatientsName = "";
     this->lastPatientsBirthDate = "";
     this->lastStudyInstanceUID = "";
     this->lastSeriesInstanceUID = "";
     this->lastPatientUID = -1;
+    */
 }
 
 //------------------------------------------------------------------------------
@@ -112,382 +109,23 @@ ctkDICOMIndexer::~ctkDICOMIndexer()
 }
 
 //------------------------------------------------------------------------------
-bool ctkDICOMIndexer::loggedExec(QSqlQuery& query)
-{
-  return (this->loggedExec(query, QString("")));
-}
-
-//------------------------------------------------------------------------------
-bool ctkDICOMIndexer::loggedExec(QSqlQuery& query, const QString& queryString)
-{
-  bool success;
-  if (queryString.compare(""))
-    {
-    success = query.exec(queryString);
-    }
-  else
-    {
-    success = query.exec();
-    }
-  if (!success)
-    {
-    QSqlError sqlError = query.lastError();
-    logger.debug( "SQL failed\n Bad SQL: " + query.lastQuery());
-    logger.debug( "Error text: " + sqlError.text());
-    }
-  else
-    {
-  logger.debug( "SQL worked!\n SQL: " + query.lastQuery());
-    }
-  return (success);
-}
-
-//------------------------------------------------------------------------------
 void ctkDICOMIndexer::addFile(ctkDICOMDatabase& ctkDICOMDatabase, 
                                    const QString& filePath,
                                    const QString& destinationDirectoryName,
                                    bool createHierarchy,
                                    bool createThumbnails)
 {
-  Q_D(ctkDICOMIndexer);
+  // Q_D(ctkDICOMIndexer);
 
   logger.setDebug();
 
-  DcmFileFormat fileformat;
-  DcmDataset *dataset;
 
 
-  std::string filename = filePath.toStdString();
 
   emit indexingFilePath(filePath);
 
-  /// first we check if the file is already in the database
-  QSqlQuery check_filename_query(ctkDICOMDatabase.database());
-  check_filename_query.prepare("SELECT InsertTimestamp FROM Images WHERE Filename == ?");
-  check_filename_query.bindValue(0,filePath);
-  this->loggedExec(check_filename_query);
-  if (
-    check_filename_query.next() &&
-    QFileInfo(filePath).lastModified() < QDateTime::fromString(check_filename_query.value(0).toString(),Qt::ISODate)
-    )
-    {
-    logger.debug( "File " + filePath + " already added.");
-    return;
-    }
-  check_filename_query.finish();
-
-  logger.debug( "Processing " + filePath ); 
-  OFCondition status = fileformat.loadFile(filename.c_str());
-
-  dataset = fileformat.getDataset();
-
-  if (!status.good())
-  {
-    logger.error( "Could not load " + filePath );
-    logger.error( "DCMTK says: " + QString(status.text()) );
-    return;
-  }
-
-  OFString patientsName, patientID, patientsBirthDate, patientsBirthTime, patientsSex,
-    patientComments, patientsAge;
-
-  OFString studyInstanceUID, studyID, studyDate, studyTime,
-    accessionNumber, modalitiesInStudy, institutionName, performingPhysiciansName, referringPhysician, studyDescription;
-
-  OFString seriesInstanceUID, seriesDate, seriesTime,
-    seriesDescription, bodyPartExamined, frameOfReferenceUID,
-    contrastAgent, scanningSequence;
-  OFString instanceNumber, sopInstanceUID ;
-
-  Sint32 seriesNumber = 0, acquisitionNumber = 0, echoNumber = 0, temporalPosition = 0;
-
-  //The patient UID is a unique number within the database, generated by the sqlite autoincrement
-  //Thus, this is _not_ the DICOM Patient ID.
-  int patientUID = -1;
-
-  //If the following fields can not be evaluated, cancel evaluation of the DICOM file
-  if (!dataset->findAndGetOFString(DCM_PatientName, patientsName).good())
-  {
-    logger.error( "Could not read DCM_PatientName from " + filePath );
-    return;
-  }
-
-  if (!dataset->findAndGetOFString(DCM_StudyInstanceUID, studyInstanceUID).good())
-  {
-    logger.error( "Could not read DCM_StudyInstanceUID from " + filePath );
-    return;
-  }
-
-  if (!dataset->findAndGetOFString(DCM_SeriesInstanceUID, seriesInstanceUID).good())
-  {
-    logger.error( "Could not read DCM_SeriesInstanceUID from " + filePath );
-    return;
-  }
-
-  if (!dataset->findAndGetOFString(DCM_SOPInstanceUID, sopInstanceUID).good())
-  {
-    logger.error( "Could not read DCM_SOPInstanceUID from " + filePath );
-    return;
-  }
-  if (!dataset->findAndGetOFString(DCM_InstanceNumber, instanceNumber).good())
-  {
-    logger.error( "Could not read DCM_InstanceNumber from " + filePath );
-    return;
-  }
-
-
-  dataset->findAndGetOFString(DCM_PatientID, patientID);
-  dataset->findAndGetOFString(DCM_PatientBirthDate, patientsBirthDate);
-  dataset->findAndGetOFString(DCM_PatientBirthTime, patientsBirthTime);
-  dataset->findAndGetOFString(DCM_PatientSex, patientsSex);
-  dataset->findAndGetOFString(DCM_PatientAge, patientsAge);
-  dataset->findAndGetOFString(DCM_PatientComments, patientComments);
-  dataset->findAndGetOFString(DCM_StudyID, studyID);
-  dataset->findAndGetOFString(DCM_StudyDate, studyDate);
-  dataset->findAndGetOFString(DCM_StudyTime, studyTime);
-  dataset->findAndGetOFString(DCM_AccessionNumber, accessionNumber);
-  dataset->findAndGetOFString(DCM_ModalitiesInStudy, modalitiesInStudy);
-  dataset->findAndGetOFString(DCM_InstitutionName, institutionName);
-  dataset->findAndGetOFString(DCM_PerformingPhysicianName, performingPhysiciansName);
-  dataset->findAndGetOFString(DCM_ReferringPhysicianName, referringPhysician);
-  dataset->findAndGetOFString(DCM_StudyDescription, studyDescription);
-
-  dataset->findAndGetOFString(DCM_SeriesDate, seriesDate);
-  dataset->findAndGetOFString(DCM_SeriesTime, seriesTime);
-  dataset->findAndGetOFString(DCM_SeriesDescription, seriesDescription);
-  dataset->findAndGetOFString(DCM_BodyPartExamined, bodyPartExamined);
-  dataset->findAndGetOFString(DCM_FrameOfReferenceUID, frameOfReferenceUID);
-  dataset->findAndGetOFString(DCM_ContrastBolusAgent, contrastAgent);
-  dataset->findAndGetOFString(DCM_ScanningSequence, scanningSequence);
-
-  dataset->findAndGetSint32(DCM_SeriesNumber, seriesNumber);
-  dataset->findAndGetSint32(DCM_AcquisitionNumber, acquisitionNumber);
-  dataset->findAndGetSint32(DCM_EchoNumbers, echoNumber);
-  dataset->findAndGetSint32(DCM_TemporalPositionIdentifier, temporalPosition);
-
-  logger.debug( "Adding new items to database:" );
-  logger.debug( "studyID: " + QString(studyID.c_str()) );
-  logger.debug( "seriesInstanceUID: " + QString(seriesInstanceUID.c_str()) );
-  logger.debug( "Patient's Name: " + QString(patientsName.c_str()) );
-
-  //-----------------------
-  //Add Patient to Database
-  //-----------------------
-
-  //Speed up: Check if patient is the same as in last file; very probable, as all images belonging to a study have the same patient
-  bool patientExists = false;
-  if(d->lastPatientID.compare(patientID) || d->lastPatientsBirthDate.compare(patientsBirthDate) || d->lastPatientsName.compare(patientsName))
-  {
-    //Check if patient is already present in the db
-    QSqlQuery check_exists_query(ctkDICOMDatabase.database());
-    std::stringstream check_exists_query_string;
-    check_exists_query_string << "SELECT * FROM Patients WHERE PatientID = '" << patientID << "'";
-    this->loggedExec(check_exists_query, check_exists_query_string.str().c_str());
-
-    /// we check only patients with the same PatientID
-    /// PatientID is not unique in DICOM, so we also compare Name and BirthDate
-    /// and assume this is sufficient
-    while (check_exists_query.next())
-    {
-      if (
-          check_exists_query.record().value("PatientsName").toString() == patientsName.c_str() &&
-          check_exists_query.record().value("PatientsBirthDate").toString() == patientsBirthDate.c_str()
-         )
-      {
-        /// found it
-        patientUID = check_exists_query.value(check_exists_query.record().indexOf("UID")).toInt();
-        patientExists = true;
-        break;
-      }
-    }
-    check_exists_query.finish();
-
-    if(!patientExists)
-    {
-
-      QSqlQuery insert_patient_query(ctkDICOMDatabase.database());
-
-      std::stringstream query_string;
-
-      query_string << "INSERT INTO Patients VALUES( NULL,'"
-      << patientsName << "','"
-      << patientID << "','"
-      << patientsBirthDate << "','"
-      << patientsBirthTime << "','"
-      << patientsSex << "','"
-      << patientsAge << "','"
-      << patientComments << "')";
-
-      this->loggedExec(insert_patient_query, query_string.str().c_str());
-
-      patientUID = insert_patient_query.lastInsertId().toInt();
-      insert_patient_query.finish();
-      QString patientUIDQString;
-      patientUIDQString.setNum(patientUID);
-      logger.debug( "New patient inserted: " + patientUIDQString );
-    }
-  }
-  else
-    {
-    patientUID = d->lastPatientUID;
-    }
-
-  /// keep this for the next image
-  d->lastPatientUID = patientUID;
-  d->lastPatientID = patientID;
-  d->lastPatientsBirthDate = patientsBirthDate;
-  d->lastPatientsName = patientsName;
-
-  //---------------------
-  //Add Study to Database
-  //---------------------
-
-  if(d->lastStudyInstanceUID.compare(studyInstanceUID))
-  {
-    QSqlQuery check_exists_query(ctkDICOMDatabase.database());
-    std::stringstream check_exists_query_string;
-    check_exists_query_string << "SELECT * FROM Studies WHERE StudyInstanceUID = '" << studyInstanceUID << "'";
-    this->loggedExec(check_exists_query, check_exists_query_string.str().c_str());
-
-    logger.debug( "Checking for study: " + QString(studyInstanceUID.c_str()) );
-
-    if(!check_exists_query.next())
-    {
-
-      QSqlQuery insert_query(ctkDICOMDatabase.database());
-      std::stringstream query_string;
-
-      // TODO: all INSERTS should be changed to use the prepare/bindValue methods
-      // to avoid quoting issues
-      insert_query.prepare("INSERT INTO Studies (StudyInstanceUID, PatientsUID, StudyID, StudyDate, StudyTime, AccessionNumber, ModalitiesInStudy, InstitutionName, ReferringPhysician, PerformingPhysiciansName, StudyDescription) VALUES (:StudyInstanceUID, :PatientsUID, :StudyID, :StudyDate, :StudyTime, :AccessionNumber, :ModalitiesInStudy, :InstitutionName, :ReferringPhysician, :PerformingPhysiciansName, :StudyDescription)");
-
-      insert_query.bindValue(":StudyInstanceUID", QString(studyInstanceUID.c_str()));
-      insert_query.bindValue(":PatientsUID", patientUID);
-      insert_query.bindValue(":StudyID", QString(studyID.c_str()));
-      insert_query.bindValue(":StudyDate", QDate::fromString(studyDate.c_str(), "yyyyMMdd").toString("yyyy-MM-dd"));
-      insert_query.bindValue(":StudyTime", QString(studyTime.c_str()));
-      insert_query.bindValue(":AccessionNumber", QString(accessionNumber.c_str()));
-      insert_query.bindValue(":ModalitiesInStudy", QString(modalitiesInStudy.c_str()));
-      insert_query.bindValue(":InstitutionName", QString(institutionName.c_str()));
-      insert_query.bindValue(":ReferringPhysician", QString(referringPhysician.c_str()));
-      insert_query.bindValue(":PerformingPhysiciansName", QString(performingPhysiciansName.c_str()));
-      insert_query.bindValue(":StudyDescription", QString(studyDescription.c_str()));
-
-      this->loggedExec(insert_query);
-      logger.debug( "Inserted study: " + QString(studyInstanceUID.c_str()) );
-    }
-  }
-
-  d->lastStudyInstanceUID = studyInstanceUID;
-
-  //----------------------
-  //Add Series to Database
-  //----------------------
-
-  if(d->lastSeriesInstanceUID.compare(seriesInstanceUID))
-  {
-
-    QSqlQuery check_exists_query(ctkDICOMDatabase.database());
-    std::stringstream check_exists_query_string;
-    check_exists_query_string << "SELECT * FROM Series WHERE SeriesInstanceUID = '" << seriesInstanceUID << "'";
-    this->loggedExec(check_exists_query, check_exists_query_string.str().c_str());
-
-    logger.debug( "Checking series: " + QString(seriesInstanceUID.c_str()) );
-
-    if(!check_exists_query.next())
-    {
-
-      QSqlQuery insert_query(ctkDICOMDatabase.database());
-      std::stringstream query_string;
-
-      query_string << "INSERT INTO Series VALUES('"
-        << seriesInstanceUID << "','"
-        << studyInstanceUID << "','"
-        << static_cast<int>(seriesNumber) << "','"
-        << QDate::fromString(seriesDate.c_str(), "yyyyMMdd").toString("yyyy-MM-dd").toStdString() << "','"
-        << seriesTime << "','"
-        << seriesDescription << "','"
-        << bodyPartExamined << "','"
-        << frameOfReferenceUID << "','"
-        << static_cast<int>(acquisitionNumber) << "','"
-        << contrastAgent << "','"
-        << scanningSequence << "','"
-        << static_cast<int>(echoNumber) << "','"
-        << static_cast<int>(temporalPosition) << "')";
-
-      this->loggedExec(insert_query, query_string.str().c_str());
-      logger.debug( "Inserted series: " + QString(seriesInstanceUID.c_str()) );
-    }
-  }
-
-  d->lastSeriesInstanceUID = seriesInstanceUID;
-
-  QString studySeriesDirectory = QString(studyInstanceUID.c_str()) + "/" + seriesInstanceUID.c_str();
-
-  //----------------------------------
-  //Move file to destination directory
-  //----------------------------------
-
-  QString finalFilePath(filePath);
-  if (!destinationDirectoryName.isEmpty())
-  {
-    QFile currentFile( filePath );
-    QDir destinationDir(destinationDirectoryName + "/dicom");
-    finalFilePath = sopInstanceUID.c_str();
-    if (createHierarchy)
-    {
-      destinationDir.mkpath(studySeriesDirectory);
-      finalFilePath.prepend( destinationDir.absolutePath() + "/"  + studySeriesDirectory + "/" );
-    }
-    currentFile.copy(finalFilePath);
-    logger.debug( "Copy file from: " + filePath );
-    logger.debug( "Copy file to  : " + finalFilePath );
-  }
-  logger.debug(QString("finalFilePath: ") + finalFilePath);
-
-  if (createThumbnails)
-  {
-    if(d->thumbnailGenerator)
-    {
-      QString thumbnailBaseDir =  ctkDICOMDatabase.databaseDirectory() + "/thumbs/";
-      QString thumbnailFilename = thumbnailBaseDir + "/" + ctkDICOMDatabase.pathForDataset(dataset) + ".png";
-      QFileInfo thumbnailInfo(thumbnailFilename);
-      if ( ! ( thumbnailInfo.exists() && thumbnailInfo.lastModified() < QFileInfo(finalFilePath).lastModified() ) )
-      {
-        QDir(thumbnailBaseDir).mkpath(studySeriesDirectory);
-        DicomImage dcmtkImage(QDir::toNativeSeparators(finalFilePath).toStdString().c_str());
-        d->thumbnailGenerator->generateThumbnail(&dcmtkImage, thumbnailFilename);
-      }
-    }
-  }
-
-  //------------------------
-  //Add Filename to Database
-  //------------------------
-
-//    std::stringstream relativeFilePath;
-//    relativeFilePath << seriesInstanceUID.c_str() << "/" << currentFilePath.getFileName();
-
-  logger.debug(QString("Adding file path to dabase: ") + finalFilePath);
-
-  QSqlQuery check_exists_query(ctkDICOMDatabase.database());
-  std::stringstream check_exists_query_string;
-//    check_exists_query_string << "SELECT * FROM Images WHERE Filename = '" << relativeFilePath.str() << "'";
-  check_exists_query_string << "SELECT * FROM Images WHERE SOPInstanceUID = '" << sopInstanceUID << "'";
-  this->loggedExec(check_exists_query, check_exists_query_string.str().c_str());
-
-  if(!check_exists_query.next())
-  {
-    QSqlQuery insert_query(ctkDICOMDatabase.database());
-    std::stringstream query_string;
-
-    //To save absolute path: destDirectoryPath.str()
-    query_string << "INSERT INTO Images VALUES('"
-      << sopInstanceUID << "','" << finalFilePath.toStdString() << "','" << seriesInstanceUID << "','" << QDateTime::currentDateTime().toString(Qt::ISODate).toStdString() << "')";
-
-    this->loggedExec(insert_query, query_string.str().c_str());
-    logger.debug(QString("added file path to dabase: ") + query_string.str().c_str());
-  }
+  
+  ctkDICOMDatabase.insert(filePath, false, true);
 
 }
 
@@ -511,6 +149,7 @@ void ctkDICOMIndexer::addDirectory(ctkDICOMDatabase& ctkDICOMDatabase,
   }
 
   OFListIterator(OFString) iter = dcmtkFileNames.begin();
+
   OFListIterator(OFString) last = dcmtkFileNames.end();
 
   if(iter == last) return;
@@ -531,6 +170,12 @@ void ctkDICOMIndexer::addDirectory(ctkDICOMDatabase& ctkDICOMDatabase,
 //------------------------------------------------------------------------------
 void ctkDICOMIndexer::refreshDatabase(ctkDICOMDatabase& ctkDICOMDatabase, const QString& directoryName)
 {
+  /*
+   * Probably this should go to the database class as well
+   * Or we have to extend the interface to make possible what we do here
+   * without using SQL directly
+   
+
   /// get all filenames from the database
   QSqlQuery allFilesQuery(ctkDICOMDatabase.database());
   QStringList databaseFileNames;
@@ -558,7 +203,8 @@ void ctkDICOMIndexer::refreshDatabase(ctkDICOMDatabase& ctkDICOMDatabase, const
   // 
   // I guess the next step is to remove all filesToRemove from the database
   // and also to add filesystemFiles into the database tables
-}
+  */ 
+  }
 
 //------------------------------------------------------------------------------
 void ctkDICOMIndexer::setThumbnailGenerator(ctkDICOMAbstractThumbnailGenerator *generator){

+ 0 - 8
Libs/DICOM/Core/ctkDICOMIndexer.h

@@ -66,14 +66,6 @@ public:
   Q_INVOKABLE void refreshDatabase(ctkDICOMDatabase& database, const QString& directoryName);
 
   ///
-  /// \brief runs a query and prints debug output of status
-  ///
-  ///
-  bool loggedExec(QSqlQuery& query);
-  bool loggedExec(QSqlQuery& query, const QString& queryString);
-
-
-  ///
   /// set thumbnail generator object
   void setThumbnailGenerator(ctkDICOMAbstractThumbnailGenerator* generator);
   ///