1 /*=========================================================================
2 
3   Library:   CTK
4 
5   Copyright (c) Kitware Inc.
6 
7   Licensed under the Apache License, Version 2.0 (the "License");
8   you may not use this file except in compliance with the License.
9   You may obtain a copy of the License at
10 
11       http://www.apache.org/licenses/LICENSE-2.0.txt
12 
13   Unless required by applicable law or agreed to in writing, software
14   distributed under the License is distributed on an "AS IS" BASIS,
15   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   See the License for the specific language governing permissions and
17   limitations under the License.
18 
19 =========================================================================*/
20 
21 #ifndef __ctkDICOMIndexer_h
22 #define __ctkDICOMIndexer_h
23 
24 // Qt includes
25 #include <QObject>
26 #include <QSqlDatabase>
27 
28 #include "ctkDICOMCoreExport.h"
29 #include "ctkDICOMDatabase.h"
30 
31 class ctkDICOMIndexerPrivate;
32 
33 /// \ingroup DICOM_Core
34 ///
35 /// \brief Indexes DICOM images located in local directory into an Sql database
36 ///
37 class CTK_DICOM_CORE_EXPORT ctkDICOMIndexer : public QObject
38 {
39   Q_OBJECT
40 public:
41   explicit ctkDICOMIndexer(QObject *parent = 0);
42   virtual ~ctkDICOMIndexer();
43 
44   ///
45   /// \brief Adds directory to database and optionally copies files to
46   /// destinationDirectory.
47   ///
48   /// Scan the directory using Dcmtk and populate the database with all the
49   /// DICOM images accordingly.
50   ///
51   /// If includeHidden is set to false then hidden files and folders are not added.
52   /// DICOM folders may be created based on series or study name, which sometimes start
53   /// with a . character, therefore it is advisable to include hidden files and folders.
54   ///
55   Q_INVOKABLE void addDirectory(ctkDICOMDatabase& database, const QString& directoryName,
56                     const QString& destinationDirectoryName = "", bool includeHidden = true);
57 
58   ///
59   /// \brief Adds directory to database by using DICOMDIR and optionally copies files to
60   /// destinationDirectory.
61   /// Scan the directory using Dcmtk and populate the database with all the
62   /// DICOM images accordingly.
63   /// \return Returns false if there was an error while processing the DICOMDIR file.
64   ///
65   Q_INVOKABLE bool addDicomdir(ctkDICOMDatabase& database, const QString& directoryName,
66                     const QString& destinationDirectoryName = "");
67 
68   ///
69   /// \brief Adds a QStringList containing the file path to database and optionally copies files to
70   /// destinationDirectory.
71   ///
72   /// Scan the directory using Dcmtk and populate the database with all the
73   /// DICOM images accordingly.
74   ///
75   Q_INVOKABLE void addListOfFiles(ctkDICOMDatabase& database, const QStringList& listOfFiles,
76                     const QString& destinationDirectoryName = "");
77 
78   ///
79   /// \brief Adds a file to database and optionally copies the file to
80   /// destinationDirectory.
81   ///
82   /// Scan the file using Dcmtk and populate the database with all the
83   /// DICOM fields accordingly.
84   ///
85   Q_INVOKABLE void addFile(ctkDICOMDatabase& database, const QString filePath,
86                     const QString& destinationDirectoryName = "");
87 
88   Q_INVOKABLE void refreshDatabase(ctkDICOMDatabase& database, const QString& directoryName);
89 
90   ///
91   /// \brief Deprecated - no op.
92   /// \deprecated
93   /// Previously ensured that the QFuture threads have all finished indexing
94   /// before returning control.
95   ///
96   Q_INVOKABLE void waitForImportFinished();
97 
98   /// Call this before performing multiple add...() calls in one batch
99   /// to slightly increase indexing performance and to make only a single
100   /// indexingComplete() signal emitted for multiple add...() operations.
101   ///
102   /// If startIndexing() is called before a batch of insertions, then
103   /// endIndexing() method must be called after the insertions are completed.
104   ///
105   /// It is recommended to use ScopedIndexing helper class to call startIndexing
106   /// and endIndexing automatically.
107   Q_INVOKABLE void startIndexing(ctkDICOMDatabase& database);
108 
109   /// Call this method after batch insertion is completed, and only if startIndexing()
110   /// was called before batch insertion was started.
111   Q_INVOKABLE void endIndexing();
112 
113   /// Helper class to automatically call startIndexing and endIndexing.
114   /// Its constructor calls startIndexing and its destructor calls endIndexing.
115   ///
116   /// Example:
117   ///   ...
118   ///   {
119   ///     ctkDICOMIndexer::ScopedIndexing indexingBatch(indexer, database); // this calls startIndexing
120   ///     indexer.addDirectory(database, dir1);
121   ///     indexer.addDirectory(database, dir2);
122   ///     indexer.addDirectory(database, dir3);
123   ///   } // endIndexing is called when indexingBatch goes out of scope
124   ///
125   class ScopedIndexing
126   {
127     public:
ScopedIndexing(ctkDICOMIndexer & indexer,ctkDICOMDatabase & database)128     ScopedIndexing(ctkDICOMIndexer& indexer, ctkDICOMDatabase& database)
129     {
130       this->Indexer = &indexer;
131       this->Indexer->startIndexing(database);
132     }
~ScopedIndexing()133     ~ScopedIndexing()
134     {
135       this->Indexer->endIndexing();
136     }
137     private:
138     ctkDICOMIndexer* Indexer;
139   };
140 
141 Q_SIGNALS:
142   void foundFilesToIndex(int);
143   void indexingFileNumber(int);
144   void indexingFilePath(QString);
145   void progress(int);
146   void indexingComplete();
147 
148 public Q_SLOTS:
149   void cancel();
150 
151 protected:
152   QScopedPointer<ctkDICOMIndexerPrivate> d_ptr;
153 
154 private:
155   Q_DECLARE_PRIVATE(ctkDICOMIndexer);
156   Q_DISABLE_COPY(ctkDICOMIndexer);
157 
158 };
159 
160 #endif
161