Bläddra i källkod

Merge remote-tracking branch 'origin/200-database-schema-update' into rt104-dicomModel

Conflicts:
	Libs/DICOM/Core/Testing/Cpp/ctkDICOMDatabaseTest2.cpp
	Libs/DICOM/Core/ctkDICOMDatabase.cpp
Steve Pieper 13 år sedan
förälder
incheckning
39dca8f1dd

+ 20 - 1
Libs/DICOM/Core/Testing/Cpp/ctkDICOMDatabaseTest2.cpp

@@ -132,7 +132,6 @@ int ctkDICOMDatabaseTest2( int argc, char * argv [] )
     }
 
 
-
   //
   // Test the tag cache
   //
@@ -185,6 +184,26 @@ int ctkDICOMDatabaseTest2( int argc, char * argv [] )
     return EXIT_FAILURE;
     }
 
+  // now update the database
+  database.updateSchema();
+
+  // and repeat the above checks
+  foundFile = database.fileForInstance(instanceUID);
+
+  if (foundFile != dicomFilePath)
+    {
+    std::cerr << "ctkDICOMDatabase: didn't get back the original file path" << std::endl;
+    return EXIT_FAILURE;
+    }
+
+  foundSeriesDescription = database.instanceValue(instanceUID, tag);
+
+  if (foundSeriesDescription != knownSeriesDescription)
+    {
+    std::cerr << "ctkDICOMDatabase: invalid element value returned" << std::endl;
+    return EXIT_FAILURE;
+    }
+
   database.closeDatabase();
   database.initializeDatabase();
 

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

@@ -86,6 +86,20 @@ public:
   // filePath has to be set if this is an import of an actual file
   void insert ( const ctkDICOMDataset& ctkDataset, const QString& filePath, bool storeFile = true, bool generateThumbnail = true);
 
+  ///
+  /// copy the complete list of files to an extra table
+  ///
+  void createBackupFileList();
+
+  ///
+  /// remove the extra table containing the backup
+  ///
+  void removeBackupFileList();
+
+
+  ///
+  /// get all Filename values from table
+  QStringList filenames(QString table);
 
   /// Name of the database file (i.e. for SQLITE the sqlite file)
   QString      DatabaseFileName;
@@ -196,6 +210,23 @@ bool ctkDICOMDatabasePrivate::loggedExec(QSqlQuery& query, const QString& queryS
 }
 
 //------------------------------------------------------------------------------
+void ctkDICOMDatabasePrivate::createBackupFileList()
+{
+  QSqlQuery query(this->Database);
+  loggedExec(query, "CREATE TABLE IF NOT EXISTS main.Filenames_backup (Filename TEXT PRIMARY KEY NOT NULL )" );
+  loggedExec(query, "INSERT INTO Filenames_backup SELECT Filename FROM Images;" );
+}
+
+//------------------------------------------------------------------------------
+void ctkDICOMDatabasePrivate::removeBackupFileList()
+{
+  QSqlQuery query(this->Database);
+  loggedExec(query, "DROP TABLE main.Filenames_backup; " );
+}
+
+
+
+//------------------------------------------------------------------------------
 void ctkDICOMDatabase::openDatabase(const QString databaseFile, const QString& connectionName )
 {
   Q_D(ctkDICOMDatabase);
@@ -333,6 +364,21 @@ bool ctkDICOMDatabasePrivate::executeScript(const QString script) {
 }
 
 //------------------------------------------------------------------------------
+QStringList ctkDICOMDatabasePrivate::filenames(QString table)
+{
+  /// get all filenames from the database
+  QSqlQuery allFilesQuery(this->Database);
+  QStringList allFileNames;
+  loggedExec(allFilesQuery,QString("SELECT Filename from %1 ;").arg(table) );
+
+  while (allFilesQuery.next())
+  {
+    allFileNames << allFilesQuery.value(0).toString();
+  }
+  return allFileNames;
+}
+
+//------------------------------------------------------------------------------
 bool ctkDICOMDatabase::initializeDatabase(const char* sqlFileName)
 {
   Q_D(ctkDICOMDatabase);
@@ -340,6 +386,31 @@ bool ctkDICOMDatabase::initializeDatabase(const char* sqlFileName)
 }
 
 //------------------------------------------------------------------------------
+bool ctkDICOMDatabase::updateSchema(const char* schemaFile)
+{
+  // backup filelist
+  // reinit with the new schema
+  // reinsert everything
+ 
+  Q_D(ctkDICOMDatabase);
+  d->createBackupFileList();
+ 
+  this->initializeDatabase(schemaFile);
+
+  QStringList allFiles = d->filenames("Filenames_backup");
+  foreach(QString file, allFiles)
+  {
+    // TODO: use QFuture
+    this->insert(file,false,false,true);
+  }
+  // TODO: check better that everything is ok
+  d->removeBackupFileList();
+  return true;
+
+}
+
+
+//------------------------------------------------------------------------------
 void ctkDICOMDatabase::closeDatabase()
 {
   Q_D(ctkDICOMDatabase);
@@ -451,6 +522,13 @@ QString ctkDICOMDatabase::instanceForFile(QString fileName)
 //
 
 //------------------------------------------------------------------------------
+QStringList ctkDICOMDatabase::allFiles()
+{
+  Q_D(ctkDICOMDatabase);
+  return d->filenames("Images");
+}
+
+//------------------------------------------------------------------------------
 void ctkDICOMDatabase::loadInstanceHeader (QString sopInstanceUID)
 {
   Q_D(ctkDICOMDatabase);

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

@@ -107,9 +107,12 @@ public:
   /// close the database. It must not be used afterwards.
   Q_INVOKABLE void closeDatabase();
   ///
-  /// delete all data and reinitialize the database.
+  /// delete all data and (re-)initialize the database.
   Q_INVOKABLE bool initializeDatabase(const char* schemaFile = ":/dicom/dicom-schema.sql");
 
+  /// updates the database schema and reinserts all existing files
+  Q_INVOKABLE bool updateSchema(const char* schemaFile = ":/dicom/dicom-schema.sql");
+
   ///
   /// \brief database accessors
   Q_INVOKABLE QStringList patients ();
@@ -119,6 +122,7 @@ public:
   Q_INVOKABLE QString fileForInstance (const QString sopInstanceUID);
   Q_INVOKABLE QString instanceForFile (const QString fileName);
 
+  Q_INVOKABLE QStringList allFiles ();
   ///
   /// \brief load the header from a file and allow access to elements
   /// @param sopInstanceUID A string with the uid for a given instance
@@ -148,7 +152,7 @@ public:
   Q_INVOKABLE void insert( const ctkDICOMDataset& ctkDataset, bool storeFile, bool generateThumbnail);
   void insert ( DcmDataset *dataset, bool storeFile = true, bool generateThumbnail = true);
   Q_INVOKABLE void insert ( const QString& filePath, bool storeFile = true, bool generateThumbnail = true, bool createHierarchy = true, const QString& destinationDirectoryName = QString() );
-  
+
   /// Check if file is already in database and up-to-date
   bool fileExistsAndUpToDate(const QString& filePath);
 

+ 1 - 1
Libs/DICOM/Core/ctkDICOMIndexer.cpp

@@ -96,7 +96,7 @@ ctkDICOMIndexerPrivate::~ctkDICOMIndexerPrivate()
 
 }
 
-void ctkDICOMIndexerPrivate::OnProgress(int progress)
+void ctkDICOMIndexerPrivate::OnProgress(int)
 {
   Q_Q(ctkDICOMIndexer);