1 #include <creaImageIODicomDatabase.h>
3 #include "CppSQLite3.h"
7 #include <creaImageIODicomDatabaseStructure.h>
9 //#include <creaImageIOUtilities.h>
11 //#include <icons/database.xpm>
17 #include <wx/filename.h>
20 //#include <icons/close.xpm>
23 #include <creaMessageManager.h>
26 #include <boost/filesystem.hpp>
27 #include <boost/algorithm/string/replace.hpp>
33 //=============================================================
34 DicomDatabase::DicomDatabase(const std::string& location, int flags)
35 : DicomNode(DicomNode::Database,0,0),
39 mDicomDatabase = this;
40 DicomNodeTypeDescription::FieldDescriptionMapType& M =
41 mDicomNodeTypeDescription[DicomNode::Database].GetFieldDescriptionMap();
43 boost::filesystem::path full_path(location);
44 mName = full_path.leaf();
45 Field::Description fname("Name",0,0,"Name",0);
47 UnsafeSetFieldValue(fname.key,mName);
48 Field::Description flocation("File name",0,0,"File name",0);
49 M[flocation.key] = flocation;
50 UnsafeSetFieldValue(flocation.key,location);
52 // Field::Description ftype("Type",0,0,"Type",0);
53 // M[ftype.key] = ftype;
54 // UnsafeSetFieldValue(ftype.key,"Invalid location");
56 mDB = new CppSQLite3DB;
57 // std::cout << "** SQLite Version: " << mDB->SQLiteVersion() << std::endl;
61 //=============================================================
63 //=============================================================
64 DicomDatabase::~DicomDatabase()
68 Already done in DicomNode now that DicomDatabase inherits from it
69 ChildrenListType::iterator i;
70 for (i=GetChildrenList().begin(); i!=GetChildrenList().end(); i++)
76 //=============================================================
79 //=============================================================
80 void DicomDatabase::BuildDefaultDicomNodeTypeDescriptions()
82 for (int i = DicomNode::Patient;
83 i <= DicomNode::Image;
86 mDicomNodeTypeDescription[i].BuildDefault(i);
89 //=============================================================
91 //=============================================================
92 void DicomDatabase::Print() const
94 std::cout << "-> '"<<GetName()<< "' - '"
95 << GetFileName()<<"'"<<std::endl;
96 ChildrenListType::const_iterator i;
97 for (i=GetChildrenList().begin(); i!=GetChildrenList().end(); i++)
102 //=============================================================
104 //=====================================================================
105 bool DicomDatabase::LocationIsValid()
110 //=====================================================================
112 char* format_sql(const std::string& s)
114 return sqlite3_mprintf("%q",s.c_str());
116 // sqlite3_exec(db, zSQL, 0, 0, 0);
117 // sqlite3_free(zSQL);
118 // char* CHAIN = format_sql(QUER); \
119 // sqlite3_free(CHAIN); \
121 //=====================================================================
122 #define QUERYDB(QUER,RES) \
125 RES = mDB->execQuery(QUER.c_str()); \
127 catch (CppSQLite3Exception& e) \
129 std::cout << "SQLite query '"<<QUER<<"' : "<< e.errorCode() << ":" \
130 << e.errorMessage()<<std::endl; \
131 creaError("SQLite query '"<<QUER<<"' : "<< e.errorCode() << ":" \
132 << e.errorMessage() ); \
135 //=====================================================================
137 //=====================================================================
138 #define UPDATEDB(UP) \
141 mDB->execDML(UP.c_str()); \
143 catch (CppSQLite3Exception& e) \
145 std::cout << "SQLite update '"<<UP<<"' Error : "<< e.errorCode() << ":" \
146 << e.errorMessage()<<std::endl; \
147 creaError("SQLite update '"<<UP<<"' Error : "<< e.errorCode() << ":" \
148 << e.errorMessage() ); \
150 //=====================================================================
152 //=====================================================================
153 bool DicomDatabase::Open()
155 // std::cout << "***> DicomDatabase::Open('"<<GetFileName()<<"')"<<std::endl;
159 //=====================================================================
160 bool DicomDatabase::New()
162 // std::cout << "***> DicomDatabase::New('"<<GetFileName()<<"')"<<std::endl;
165 //=====================================================================
167 //=====================================================================
168 bool DicomDatabase::OpenDB()
170 // std::cout << "### Opening SQLite database '"<<GetFileName()<<std::endl;
172 if (!boost::filesystem::exists(GetFileName()))
179 mDB->open(GetFileName().c_str());
181 catch (CppSQLite3Exception& e)
183 std::cerr << "Opening '"<<GetFileName()<<"' : "
184 << e.errorCode() << ":"
185 << e.errorMessage() << std::endl;
188 // TESTING STRUCTURE VALIDITY
189 if (!DBStructureIsValid())
191 std::cerr << "Opening '"<<GetFileName()<<"' : "
192 << " invalid database structure" << std::endl;
195 // IMPORTING NODE TYPE DESCRIPTIONS
196 ImportDicomNodeTypeDescriptionsFromDB();
199 //=====================================================================
201 //=====================================================================
202 bool DicomDatabase::CreateDB()
204 // std::cout << "### Creating SQLite database '"<<GetFileName()<<std::endl;
206 if (boost::filesystem::exists(GetFileName()))
213 mDB->open(GetFileName().c_str());
215 catch (CppSQLite3Exception& e)
217 std::cerr << "Creating '"<<GetFileName()<<"' : "
218 << e.errorCode() << ":"
219 << e.errorMessage() <<std::endl;
223 // CREATING DEFAULT DB STRUCTURE
224 BuildDefaultDicomNodeTypeDescriptions();
231 // command = "create table PATIENT\n(\nID INTEGER PRIMARY KEY AUTOINCREMENT,\n";
232 // LG : AUTOINCREMENT unknown on sqlite3 for Win32 ??
233 command = "create table PATIENT\n(\nID INTEGER PRIMARY KEY,\n";
234 AppendSQLFieldsDefinition(DicomNode::Patient,command);
239 // command = "create table STUDY\n(\nID INTEGER PRIMARY KEY AUTOINCREMENT,\nPARENT_ID int not null,\n";
240 command = "create table STUDY\n(\nID INTEGER PRIMARY KEY,\nPARENT_ID int not null,\n";
241 AppendSQLFieldsDefinition(DicomNode::Study,command);
243 command +="constraint FK_PARENT foreign key (PARENT_ID) references PATIENT(ID) on delete restrict on update restrict\n)";
247 // command = "create table SERIES\n(\nID INTEGER PRIMARY KEY AUTOINCREMENT,\nPARENT_ID int not null,\n";
248 command = "create table SERIES\n(\nID INTEGER PRIMARY KEY,\nPARENT_ID int not null,\n";
249 AppendSQLFieldsDefinition(DicomNode::Series,command);
251 command += "constraint FK_PARENT foreign key (PARENT_ID) references STUDY(ID) on delete restrict on update restrict\n)";
255 // command = "create table IMAGE\n(\nID INTEGER PRIMARY KEY AUTOINCREMENT,\nPARENT_ID int not null,\n";
256 command = "create table IMAGE\n(\nID INTEGER PRIMARY KEY,\nPARENT_ID int not null,\n";
257 AppendSQLFieldsDefinition(DicomNode::Image,command);
259 command += "constraint FK_PARENT foreign key (PARENT_ID) references SERIE (ID) on delete restrict on update restrict\n)";
262 //constraint FK_DIRECTORY foreign key (DIRECTORY_ID) \
263 // references ROOTDIRECTORY (ID) \
264 // on delete restrict on update restrict,
267 // Create tables *_FIELDS
268 for (DicomNode::Type type=DicomNode::Patient;
269 type<=DicomNode::Image; type++)
271 command = "create table ";
272 command += DicomDatabaseStructure::Table(type);
273 command += "_FIELDS\n(\n";
274 command += "Key text,\n";
275 command += "DicomGroup int,\n";
276 command += "DicomElement int,\n";
277 command += "Name text,\n";
278 command += "Flags int\n";
282 // Fill the tables *_FIELDS
283 ExportDicomNodeTypeDescriptionsToDB();
286 catch (std::exception)
291 if (DBStructureIsValid())
293 // std::cout << "*** DONE ***"<<std::endl;
295 SetChildrenLoaded(true);
301 // std::cout << "*** AAAARRRRGGG ***"<<std::endl;
306 //=====================================================================
308 //=====================================================================
309 void DicomDatabase::AppendSQLFieldsDefinition(DicomNode::Type c,
312 std::vector<std::string*> keys;
313 DicomNodeTypeDescription::FieldDescriptionMapType::iterator i;
314 for (i = GetDicomNodeTypeDescription(c).GetFieldDescriptionMap().begin();
315 i != GetDicomNodeTypeDescription(c).GetFieldDescriptionMap().end();
318 if (i->second.flags==1) continue;
319 keys.push_back(&(i->second.key));
321 std::vector<std::string*>::iterator j;
322 for (j=keys.begin();j!=keys.end();)
331 //=====================================================================
333 //=====================================================================
334 void DicomDatabase::ExportDicomNodeTypeDescriptionsToDB()
336 // std::cout<<"ExportDicomNodeTypeDescriptionsToDB()"<<std::endl;
337 for (DicomNode::Type type=DicomNode::Patient;
338 type<=DicomNode::Image;
341 DicomNodeTypeDescription::FieldDescriptionMapType::iterator i;
342 for (i = GetDicomNodeTypeDescription(type).GetFieldDescriptionMap().begin();
343 i!= GetDicomNodeTypeDescription(type).GetFieldDescriptionMap().end();
347 std::stringstream insert;
348 insert << "INSERT INTO "
349 << std::string(DicomDatabaseStructure::Table(type))
350 << "_FIELDS (Key,DicomGroup,DicomElement,Name,Flags) "
352 << (*i).second.GetKey() << "',"
353 << (*i).second.GetGroup() << ","
354 << (*i).second.GetElement() << ",'"
355 << (*i).second.GetName() << "',"
356 << (*i).second.GetFlags() << ");";
358 // std::cout << "** SQL = '"<<insert.str()<<"'"<<std::endl;
360 UPDATEDB(insert.str());
364 //=====================================================================
366 //=====================================================================
367 void DicomDatabase::ImportDicomNodeTypeDescriptionsFromDB()
369 // std::cout<<"ImportDicomNodeTypeDescriptionsFromDB()"<<std::endl;
370 for (DicomNode::Type type=DicomNode::Patient;
371 type<=DicomNode::Image;
374 std::string query = "SELECT * FROM ";
375 query += DicomDatabaseStructure::Table(type);
378 // std::cout << "** SQL = '"<<query<<"'"<<std::endl;
386 Field::Description d(q.getStringField(0), // Key
387 q.getIntField(1), // Group
388 q.getIntField(2), // Element
389 q.getStringField(3), // Name
390 q.getIntField(4) // Flags
392 GetDicomNodeTypeDescription(type).GetFieldDescriptionMap()[d.key] = d;
393 // std::cout << d << std::endl;
398 //=====================================================================
400 //=====================================================================
401 bool DicomDatabase::Close()
403 // std::cout << "***> DicomDatabase::Close"<<std::endl;
405 // std::cout << "<*** DicomDatabase::Close"<<std::endl;
408 //=====================================================================
410 //=====================================================================
411 bool DicomDatabase::LoadAll()
413 DBLoadChildren(0,true);
417 //=====================================================================
419 //=====================================================================
420 bool DicomDatabase::LoadUpToSeries()
423 DBLoadChildren(0,false);
427 //=====================================================================
429 //=====================================================================
430 bool DicomDatabase::LoadSeriesImages(DicomNode* series)
434 if (!series->GetType()==DicomNode::Series)
437 creaError("DicomDatabase::LoadSeriesImages : node is not a series !");
439 DBLoadChildren(series,true);
442 //=====================================================================
445 //=====================================================================
446 void DicomDatabase::Clear()
449 //=====================================================================
452 //=====================================================================
453 int DicomDatabase::DBLoadChildren(DicomNode* parent,
454 DicomNode::Type maxlevel)
457 // std::cout << "DicomDatabase::DBLoadChildren("<<parent<<","<<maxlevel
458 // << ")"<<std::endl;
460 if (parent == this) { parent = 0; }
461 DicomNode* xparent = parent;
462 if ( xparent==0 ) xparent = this;
463 if ( xparent->ChildrenLoaded() )
465 // std::cout << "--> Children already loaded"<<std::endl;
468 if ( xparent->GetType() == DicomNode::Image )
472 if ( xparent->GetType() >= maxlevel )
477 if ( parent->ChildrenLoaded().size()>0 )
480 if (parent) n = parent;
481 // If parent already has loaded its children
482 // simply recurse to its children
483 DicomNode::ChildrenListType::iterator i;
484 for (i = n->GetChildrenList().begin();
485 i != n->GetChildrenList().end();
488 DBLoadChildren(*i,load_images);
495 DicomNode::Type type = xparent->GetType()+1;
499 std::string query = "SELECT * FROM ";
500 query += DicomDatabaseStructure::Table(type);
503 query += " WHERE PARENT_ID='" + parent->GetFieldValue("ID") + "'";
506 // std::cout << "** SQL = '"<<query<<"'"<<std::endl;
514 DicomNode* n = new DicomNode(type,
516 for (int fld = 0; fld < q.numFields(); fld++)
518 n->SetFieldValue(q.fieldName(fld),q.getStringField(fld));
523 ti.id = n->GetFieldValue("ID");
524 mTypeIdToDicomNodeMap[ti] = n;
526 if ( type < maxlevel )
529 nbloaded += DBLoadChildren(n,maxlevel);
536 xparent->SetChildrenLoaded(true);
541 //=====================================================================
545 //=====================================================================
546 bool DicomDatabase::DBStructureIsValid()
549 for (int i = DicomDatabaseStructure::TableBegin();
550 i != DicomDatabaseStructure::TableEnd();++i)
552 bool ok = mDB->tableExists(DicomDatabaseStructure::Table(i));
555 // std::cout << "** Table "<<DicomDatabaseStructure::Table(i)
556 // <<" exists"<<std::endl;
557 // TO DO : TEST MANDATORY FIELDS EXIST
561 // std::cout << "** Table "<<DicomDatabaseStructure::Table(i)
562 // <<" does *NOT* exist"<<std::endl;
568 //=====================================================================
572 //=====================================================================
573 bool DicomDatabase::DBInsert(DicomNode* alien_node,
574 UpdateSummary& summary)
576 // std::cout << "DicomDatabase::Insert('"<<alien_node->GetLabel()
577 // <<"')"<<std::endl;
579 // if (!ChildrenLoaded()) DBLoadChildren(this,DicomNode::Database);
583 std::string parent_id;
584 parent = DBGetOrCreateParent(alien_node,parent_id,summary);
587 DBRecursiveGetOrCreateDicomNode(alien_node,parent,parent_id,summary);
590 //=====================================================================
593 //=====================================================================
594 DicomNode* DicomDatabase::DBGetOrCreateParent(DicomNode* alien_node,
595 std::string& parent_id,
596 UpdateSummary& summary)
598 // std::cout << "DBGetOrCreateParent '" << alien_node->GetLabel()<<"'"
600 // Load the patients if not already done
601 DBLoadChildren(this,DicomNode::Patient);
604 DicomNode* parent = this;
606 // The chain of ancestors
607 std::deque<DicomNode*> chain;
608 DicomNode* cur = alien_node->GetParent();
609 for (int type=DicomNode::Patient;
610 type<alien_node->GetType();++type)
612 chain.push_front(cur);
613 cur = cur->GetParent();
616 // create the nodes if do not exist
617 std::deque<DicomNode*>::iterator i;
618 for (i=chain.begin();i!=chain.end();++i)
620 // std::cout << " cur = '"<<(*i)->GetLabel()<<"'"<<std::endl;
621 // std::string cur_id = DBGetDicomNodeId(*i,parent_id);
622 // if (cur_id.size()==0)
624 // Node does not exist : create it
626 parent = DBGetOrCreateDicomNode(*i,
632 DBLoadChildren(parent,parent->GetType()+1);
636 // Node exists : get it and load its children
637 parent = GetDicomNodeFromTypeId((*i)->GetType(),cur_id);
638 DBLoadChildren(parent,parent->GetType()+1);
645 //=====================================================================
649 //=====================================================================
650 void DicomDatabase::DBRecursiveGetOrCreateDicomNode(DicomNode* alien_node,
652 const std::string& parent_id,
653 UpdateSummary& summary)
655 // std::cout << "DicomDatabase::RecursiveGetOrCreateDicomNode('"
656 // <<alien_node->GetLabel()
657 // <<"','"<<parent<<"','"<<parent_id<<"')"<<std::endl;
660 // std::cout << " -- Parent = '"<<parent->GetLabel()<<"'"<<std::endl;
663 DicomNode* new_node = DBGetOrCreateDicomNode(alien_node,
668 DicomNode::ChildrenListType::iterator i;
669 for (i = alien_node->GetChildrenList().begin();
670 i != alien_node->GetChildrenList().end();
673 DBRecursiveGetOrCreateDicomNode((*i),new_node,new_id,summary);
676 //=====================================================================
679 //=====================================================================
680 DicomNode* DicomDatabase::DBGetOrCreateDicomNode(DicomNode* alien_node,
681 DicomNode* internal_parent,
682 std::string parent_id,
683 std::string& node_id,
684 UpdateSummary& summary)
686 // std::cout << "DBGetOrCreateDicomNode('"<<alien_node->GetLabel()<<"','"
687 // << internal_parent << "','"<< parent_id<<"')"<<std::endl;
688 if (internal_parent != 0)
690 // std::cout << " -- Parent = '"<<internal_parent->GetLabel()<<"'"<<std::endl;
692 // DicomNode Exists ? return it
693 // First try among children of internal parent
694 DicomNode* node = GetChildrenLike(internal_parent,alien_node);
697 node_id = node->UnsafeGetFieldValue("ID");
700 // Second : try in DB
702 node_id = DBGetDicomNodeId(alien_node,parent_id);
703 if (node_id.size()>0)
706 return GetDicomNodeFromTypeId(alien_node->GetType(),node_id);
709 // Does not exist : Create new one
710 node = new DicomNode(alien_node->GetType(),this,internal_parent);
711 node->SetChildrenLoaded(true);
712 // Copy fields values from alien
713 DicomNode::FieldValueMapType::iterator i,j;
714 for (i = node->GetFieldValueMap().begin();
715 i != node->GetFieldValueMap().end();
718 j = alien_node->GetFieldValueMap().find(i->first);
719 if (j != alien_node->GetFieldValueMap().end() )
721 i->second = j->second;
726 if (node->GetType()!=DicomNode::Patient)
727 node->SetFieldValue("PARENT_ID",parent_id);
731 BuildSQLFieldsValues(node,val);
732 std::string insert("INSERT INTO ");
733 insert += std::string(DicomDatabaseStructure::Table(node->GetType()))
735 // std::cout << "** SQL = '"<<insert<<"'"<<std::endl;
737 // std::cout << "** SQL OK"<<std::endl;
739 // Store DB id of newly created node;
740 long lastrow = mDB->lastRowId();
741 std::stringstream ri;
742 ri << mDB->lastRowId();
744 // std::cout << "LastRowId='"<<mDB->lastRowId()<<"' vs '"<<created_id<<"'"<<std::endl;
746 node->SetFieldValue("ID",node_id);
747 // Insert in TypeId map
749 ti.type = node->GetType();
751 mTypeIdToDicomNodeMap[ti] = node;
752 // std::cout << "== Insert TypeId ("<<ti.type<<","<<ti.id<<")"<<std::endl;
756 if (node->GetType()==DicomNode::Patient) summary.added_patients++;
757 if (node->GetType()==DicomNode::Study) summary.added_studies++;
758 if (node->GetType()==DicomNode::Series) summary.added_series++;
759 if (node->GetType()==DicomNode::Image) summary.added_images++;
763 //=====================================================================
765 //=====================================================================
766 DicomNode* DicomDatabase::GetChildrenLike(DicomNode* parent,
767 DicomNode* alien_node)
769 DicomNode::ChildrenListType::iterator i;
770 for (i = parent->GetChildrenList().begin();
771 i != parent->GetChildrenList().end();
774 DicomNode::Type type = alien_node->GetType();
777 j<DicomDatabaseStructure::NbQueryFields(type);
781 alien_node->GetFieldValue(DicomDatabaseStructure::
782 QueryField(type,j).key ) !=
783 (*i)->GetFieldValue(DicomDatabaseStructure::
784 QueryField(type,j).key ) )
797 //=====================================================================
799 //=====================================================================
800 std::string DicomDatabase::DBGetDicomNodeId(DicomNode* node,
801 const std::string& parent_id)
803 // std::cout << "DicomDatabase::DBGetDicomNodeId('"<<node->GetLabel()
804 // <<"','"<<parent_id<<"')"
807 int type = node->GetType();
809 std::string table = DicomDatabaseStructure::Table(type);
810 std::string where = "WHERE ";
812 if (type!=DicomNode::Patient)
814 where += "PARENT_ID='" + parent_id
815 //node->GetFieldValue("PARENT_ID")
819 for (int i=0;i<DicomDatabaseStructure::NbQueryFields(type);i++)
821 where += DicomDatabaseStructure::QueryField(type,i).key + "='"
822 + node->GetFieldValue(DicomDatabaseStructure::QueryField(type,i).key) + "' ";
823 if (i<DicomDatabaseStructure::NbQueryFields(type)-1)
827 std::string query = "SELECT ID FROM " + table + " " + where + ";";
828 // std::cout << "** SQL = '"<<query<<"'"<<std::endl;
835 // std::cout << " - DicomNode exists " << std::endl;
836 std::string id = q.getStringField(0);
837 // std::cout << " id = '"<<id<<"'"<<std::endl;
844 //=====================================================================
848 //=====================================================================
849 DicomNode* DicomDatabase::GetDicomNodeFromTypeId(DicomNode::Type type,
850 const std::string& id)
852 // std::cout << "GetDicomNodeFromTypeId("<<type<<","<<id<<")"<<std::endl;
858 TypeIdToDicomNodeMapType::iterator i = mTypeIdToDicomNodeMap.find(ti);
859 if (i == mTypeIdToDicomNodeMap.end())
863 i = mTypeIdToDicomNodeMap.find(ti);
864 if (i == mTypeIdToDicomNodeMap.end())
867 std::cout << "Internal error : mTypeIdToDicomNodeMap does not contain key"
869 creaError("Internal error : mTypeIdToDicomNodeMap does not contain key");
873 // std::cout << " ** DicomNode = "<<i->second<<std::endl;
876 //=====================================================================
878 //=====================================================================
879 bool DicomDatabase::Remove(DicomNode* node)
881 DBRecursiveRemoveDicomNode(node);
883 if (node->GetType()==DicomNode::Patient)
885 // std::cout << "IS PATIENT"<<std::endl;
886 ChildrenListType::iterator i = find(GetChildrenList().begin(),
887 GetChildrenList().end(),
889 // std::cout << "ERASE"<<std::endl;
890 GetChildrenList().erase(i);
891 // std::cout << "ERASE OK"<<std::endl;
894 // std::cout << "DELETE"<<std::endl;
895 if (node->GetParent())
897 node->GetParent()->RemoveChildrenFromList(node);
900 // std::cout << "DELETE OK"<<std::endl;
903 //========================================================================
905 //=====================================================================
906 void DicomDatabase::DBRecursiveRemoveDicomNode(DicomNode* node)
908 // std::cout << "DicomDatabase::DBRecursiveRemoveDicomNode('"
909 // <<node->GetLabel()<<"')"<<std::endl;
911 std::string query = "DELETE FROM ";
912 query += DicomDatabaseStructure::Table(node->GetType());
913 query += " WHERE ID='"+ node->GetFieldValue("ID") + "';";
917 DicomNode::ChildrenListType::iterator i;
918 for (i = node->GetChildrenList().begin();
919 i != node->GetChildrenList().end();
922 DBRecursiveRemoveDicomNode((*i));
925 //=====================================================================
927 //=====================================================================
928 int DicomDatabase::DBQueryNumberOfChildren(DicomNode* node)
930 std::string query = "SELECT COUNT (ID) FROM ";
931 query += DicomDatabaseStructure::Table(node->GetType()+1);
932 if (node->GetType() != DicomNode::Database)
934 query += " WHERE PARENT_ID='"+ node->GetFieldValue("ID")+"'";
938 // std::cout << "**SQL = "<< query << std::endl;
943 // std::cout << "**RES = "<< q.getIntField(0) <<std::endl;
945 return q.getIntField(0);
947 //=====================================================================
949 //========================================================================
950 std::string& format_sql2(std::string& str)
952 // quote must be doubled
953 // crea::Utils::Replace( str, "'", "''" );
954 boost::algorithm::replace_all(str,"'","''");
955 // Found strange strings which contained NULL char INSIDE string
956 int i,size=str.size();
961 str = str.substr(0,i);
968 //========================================================================
970 //=====================================================================
971 void DicomDatabase::BuildSQLFieldsValues(DicomNode* n,
974 // std::cout << "BuildSQLFieldsValues('"<<n->GetLabel()<<"')"<<std::endl;
977 std::string values="";
978 DicomNode::FieldValueMapType::iterator i;
979 for (i = n->GetFieldValueMap().begin();
980 i != n->GetFieldValueMap().end();
987 // std::cout << "("<<i->first<<","<<i->second<<")"<<std::endl;
988 atts += "'" + i->first + "'";
989 values += "'" + format_sql2(i->second) + "'";
993 atts[atts.size()-1]=' ';
994 values[values.size()-1]=' ';
996 str = "("+atts+") VALUES ("+values+")";
999 //=====================================================================
1001 //=====================================================================
1002 bool DicomDatabase::IsHandledFile( const std::string& filename)
1004 return (mReader.CanRead(filename,""));
1006 //=====================================================================
1008 //=====================================================================
1009 bool DicomDatabase::AddFiles( const std::vector<std::string>& filenames,
1010 wxProgressDialog* progress,
1011 UpdateSummary& summary)
1013 for (int swi=0;swi<10;swi++)
1023 summary.added_images = 0;
1024 unsigned int nbf = filenames.size();
1025 std::vector<std::string>::const_iterator i;
1026 for (i=filenames.begin();i!=filenames.end();++i)
1028 summary.scanned_files++;
1029 if (IsHandledFile(*i))
1031 summary.handled_images++;
1032 AddFile(*i,summary);
1036 std::string mess("Adding ");
1038 if (!progress->Update( (int)(summary.added_images*999./nbf),
1041 // Some file was added hence we must return true !
1042 summary.cancelled_by_user = true;
1055 summary.total_time = sw.Time();
1056 summary.file_scan_time = msw[1].Time();
1057 summary.update_database_time = msw[2].Time();
1058 summary.update_structs_time =
1059 summary.total_time -
1060 summary.parse_time -
1061 summary.file_scan_time -
1062 summary.update_database_time;
1066 //=====================================================================
1068 //=====================================================================
1069 bool DicomDatabase::AddFile( const std::string& filename,
1070 UpdateSummary& summary)
1072 // std::cout << "** DicomDatabase::AddFile '"<<filename<<"'"<<std::endl;
1073 // Create *unknown* patient / study / series
1074 DicomNode* patient = new DicomNode(DicomNode::Patient,this,0);
1075 // FillFields/*<GDCM_NAME_SPACE::DicomDir>*/(patient,0);
1076 // patient->SetData(new DirDicomNodeData());
1078 //GetChildrenList().push_back(patient);
1079 DicomNode* study = new DicomNode(DicomNode::Study,this,patient);
1080 //FillFields/*<GDCM_NAME_SPACE::DicomDir>*/(study,0);
1081 //study->SetData(new DirDicomNodeData());
1082 DicomNode* series = new DicomNode(DicomNode::Series,this,study);
1083 //FillFields/*<GDCM_NAME_SPACE::DicomDir>*/(series,0);
1084 //series->SetData(new DirDicomNodeData());
1085 DicomNode* image = new DicomNode(DicomNode::Image,this,series);
1088 mReader.ReadDicomInfo(filename,image);
1091 image->SetFieldValue("FullFileName",filename);
1093 DBInsert(patient,summary);
1097 //image->SetData(new DirDicomNodeData());
1099 //FillFields/*<GDCM_NAME_SPACE::DicomDir>*/(image,0);
1100 //std::string f(Utilities::GetFileName(*i));
1101 //image->SetFieldValue("A0004_1500",cclean(f));
1102 //image->SetFieldValue("FullFileName",cclean(*i));
1105 //=====================================================================
1107 //=====================================================================
1109 * \brief Explore a directory with possibility of recursion
1110 * return number of files read
1111 * @param dirpath directory to explore
1112 * @param recursive whether we want recursion or not
1114 void DicomDatabase::ParseDirectory( const std::string &dirpath,
1115 std::vector<std::string> &Filenames,
1117 wxProgressDialog* progress,
1118 UpdateSummary& summary)
1123 std::string mess("Parsing ");
1125 progress->Pulse(std2wx(mess));
1131 std::string fileName;
1132 std::string dirName = dirpath;
1134 summary.scanned_dirs++;
1136 wxDir dir( std2wx(dirpath) );
1138 if ( !dir.IsOpened() )
1140 // deal with the error here - wxDir would already log an error message
1141 // explaining the exact reason of the failure
1147 bool cont = dir.GetFirst(&filename, wxEmptyString, wxDIR_FILES | wxDIR_HIDDEN );
1150 if ((progress)&&( sw.Time() >= 250 ))
1152 // std::cout << "PULSE"<<std::endl;
1154 if (!progress->Pulse())
1156 summary.cancelled_by_user = true;
1161 summary.scanned_files++;
1162 wxFileName wxffn(dir.GetName(),filename);
1163 std::string ffn = wx2std(wxffn.GetFullPath());
1164 // std::cout << ffn << std::endl;
1165 if (mReader.CanRead(ffn,""))
1167 Filenames.push_back( ffn );
1168 summary.handled_images++;
1170 cont = dir.GetNext(&filename);
1173 // Recurse into subdirs
1176 cont = dir.GetFirst(&filename, wxEmptyString, wxDIR_DIRS | wxDIR_HIDDEN );
1180 wxFileName wxffn(dir.GetName(),filename);
1181 std::string ffn = wx2std(wxffn.GetFullPath());
1183 // std::cout << "dir="<< ffn<< std::endl;
1185 ParseDirectory( ffn,
1190 if (summary.cancelled_by_user) break;
1192 cont = dir.GetNext(&filename);
1197 //=======================================================================
1200 //=====================================================================
1201 bool DicomDatabase::AddDirectory( const std::string& directory,
1203 wxProgressDialog* progress,
1204 UpdateSummary& summary
1207 // std::cout << "** DicomDatabase::AddDirectory"
1208 // << " '"<<directory<<"'"<<std::endl;
1209 // std::cout << "------ Parsing directory ------"<<std::endl;
1216 for (int swi=0;swi<10;swi++)
1225 bool was_canceled_by_user(false);
1226 std::vector<std::string> filenames;
1227 ParseDirectory( directory,
1233 if ( summary.cancelled_by_user )
1238 summary.parse_time = sw.Time();
1241 summary.added_images = 0;
1242 unsigned int nbf = filenames.size(); // , nf = 0;
1243 std::vector<std::string>::iterator i;
1244 for (i=filenames.begin();i!=filenames.end();++i)
1246 AddFile(*i,summary);
1250 std::string mess("Adding ");
1252 if (!progress->Update( (int)(summary.added_images*999./nbf),
1255 // Some file was added hence we must return true !
1256 summary.cancelled_by_user = true;
1268 summary.total_time = sw.Time();
1269 summary.file_scan_time = msw[1].Time();
1270 summary.update_database_time = msw[2].Time();
1271 summary.update_structs_time =
1272 summary.total_time -
1273 summary.parse_time -
1274 summary.file_scan_time -
1275 summary.update_database_time;
1279 //=====================================================================
1287 } // namespace creaImageIO