2 # ---------------------------------------------------------------------
4 # Copyright (c) CREATIS (Centre de Recherche en Acquisition et Traitement de l'Image
6 # Authors : Eduardo Davila, Frederic Cervenansky, Claire Mouton
7 # Previous Authors : Laurent Guigues, Jean-Pierre Roux
8 # CreaTools website : www.creatis.insa-lyon.fr/site/fr/creatools_accueil
10 # This software is governed by the CeCILL-B license under French law and
11 # abiding by the rules of distribution of free software. You can use,
12 # modify and/ or redistribute the software under the terms of the CeCILL-B
13 # license as circulated by CEA, CNRS and INRIA at the following URL
14 # http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
15 # or in the file LICENSE.txt.
17 # As a counterpart to the access to the source code and rights to copy,
18 # modify and redistribute granted by the license, users are provided only
19 # with a limited warranty and the software's author, the holder of the
20 # economic rights, and the successive licensors have only limited
23 # The fact that you are presently reading this means that you have had
24 # knowledge of the CeCILL-B license and that you accept its terms.
25 # ------------------------------------------------------------------------
29 #include "creaImageIOWxDescriptorPanel.h"
30 #include <creaImageIOSystem.h>
32 #include <gdcmGlobal.h>
33 #include <gdcmDictSet.h>
36 #if defined(USE_GDCM2)
37 #include <gdcmGlobal.h>
38 #include <gdcmDicts.h>
41 #include <boost/algorithm/string.hpp>
47 WxDescriptorPanel::WxDescriptorPanel(wxWindow *parent, const std::string path)
48 : wxDialog(parent, -1,_T("Descriptor Creation"), wxDefaultPosition, wxSize(550,550)) , m_path(path)
52 GimmickDebugMessage(1,"WxDescriptorPanel::WxDescriptorPanel"
56 ownatt["FullFileName"] = "Full_File_Name";
57 ownatt["FullFileDirectory"] = "Full_File_Directory";
61 wxButton *NewDescriptor = new wxButton(this, -1,_T("Create a new descriptor"), wxPoint(10,7) );
62 Connect( NewDescriptor->GetId(), wxEVT_COMMAND_BUTTON_CLICKED , (wxObjectEventFunction) &WxDescriptorPanel::OnNew );
64 wxButton *LoadDescriptor = new wxButton(this, -1,_T("Load a descriptor"), wxPoint(150,7) );
65 Connect( LoadDescriptor->GetId(), wxEVT_COMMAND_BUTTON_CLICKED , (wxObjectEventFunction) &WxDescriptorPanel::OnLoad );
67 /// \TODO fix warning: unused variable line1
68 wxStaticLine *line1 = new wxStaticLine(this, -1, wxPoint(5,40), wxSize(540,2));
71 /// \TODO fix warning: unused variable LevelText
72 wxStaticText * LevelText=new wxStaticText(this,-1,_T(" Level: "), wxPoint(5,50));
73 LevelCtrl=new wxTextCtrl(this, ID_GR_CTRL,_T("patient"), wxPoint(50,50), wxSize(50,25));
74 wxButton *addLevel = new wxButton(this, ID_LEVEL_ADD,_T("add a level"), wxPoint(150,50) );
75 Connect( addLevel->GetId(), wxEVT_COMMAND_BUTTON_CLICKED , (wxObjectEventFunction) &WxDescriptorPanel::OnAddLevel );
77 /// \TODO fix warning: unused variable line2
78 wxStaticLine *line2 = new wxStaticLine(this, -1, wxPoint(5,75), wxSize(540,2));
82 /// \TODO fix warning: unused variable GR
83 wxStaticText * GR=new wxStaticText(this,-1,_T(" DICOM Group: "), wxPoint(5,110));
84 GRCtrl=new wxTextCtrl(this, ID_GR_CTRL,_T("0x0010"), wxPoint(82,110), wxSize(50,25));
85 Connect( GRCtrl->GetId(), wxEVT_COMMAND_TEXT_UPDATED , (wxObjectEventFunction) &WxDescriptorPanel::OnDicomAttribute );
87 /// \TODO fix warning: unused variable EL
88 wxStaticText * EL=new wxStaticText(this,-1,_T(" DICOM Element: "), wxPoint(140,110));
89 ELCtrl=new wxTextCtrl(this, ID_EL_CTRL,_T("0x0010"), wxPoint(230,110), wxSize(50,25));
90 Connect( ELCtrl->GetId(), wxEVT_COMMAND_TEXT_UPDATED , (wxObjectEventFunction) &WxDescriptorPanel::OnDicomAttribute );
93 choices[0] = _T("Unknow Attribute");
94 std::map<std::string, std::string>::iterator it_att =ownatt.begin();
95 for(int i = 1; it_att != ownatt.end(); it_att++, i++)
97 choices[i] = crea::std2wx(it_att->second);
101 AttributeCombo = new wxComboBox(this, ID_ATTRIBUTE_CTRL,_T(""),wxPoint(300,110), wxSize(120,25),3,choices, wxCB_READONLY);
102 AttributeCombo->SetSelection(0);
105 wxButton *addAttribute = new wxButton(this, ID_ATTRIBUTE_ADD,_T("add an attribute"), wxPoint(440,110) );
106 Connect( addAttribute->GetId(), wxEVT_COMMAND_BUTTON_CLICKED , (wxObjectEventFunction) &WxDescriptorPanel::OnAddAttribute );
107 /// \TODO fix warning: unused variable line3
108 wxStaticLine *line3 = new wxStaticLine(this, -1, wxPoint(5,140), wxSize(540,2));
112 ResultCtrl=new wxTextCtrl(this, ID_EL_CTRL,_T(""), wxPoint(5,150), wxSize(250,310), wxTE_READONLY| wxMac | wxTE_MULTILINE | wxTE_RICH );
113 wxButton *RemoveCtrl = new wxButton(this, ID_REMOVE_ADD,_T("Remove an entry"), wxPoint(280,200) );
114 Connect( RemoveCtrl->GetId(), wxEVT_COMMAND_BUTTON_CLICKED , (wxObjectEventFunction) &WxDescriptorPanel::OnRemove );
116 /// \TODO fix warning: unused variable line4
117 wxStaticLine *line4 = new wxStaticLine(this, -1, wxPoint(5,470), wxSize(540,2));
119 wxButton *Ok = new wxButton(this, -1,_T("OK"), wxPoint(10,480) );
120 Connect( Ok->GetId(), wxEVT_COMMAND_BUTTON_CLICKED , (wxObjectEventFunction) &WxDescriptorPanel::OnOK );
122 wxButton *Apply = new wxButton(this, -1,_T("APPLY"), wxPoint(150,480) );
123 Connect( Apply->GetId(), wxEVT_COMMAND_BUTTON_CLICKED , (wxObjectEventFunction) &WxDescriptorPanel::OnApply );
125 /// \TODO fix warning: unused variable Cancel
126 wxButton *Cancel = new wxButton(this, wxID_CANCEL,_T("CANCEL"), wxPoint(250,480) );
127 // Connect( Cancel->GetId(), wxEVT_COMMAND_BUTTON_CLICKED , (wxCloseEvent) &wxWindow::Close );
134 WxDescriptorPanel::~WxDescriptorPanel()
136 GimmickDebugMessage(1,"WxCustomizeConfigPanel::~WxCustomizeConfigPanel"
140 //////////////////////////////////////////////////////////
141 // Add an attribute //
142 // @param event : Wxevent //
144 //////////////////////////////////////////////////
145 void WxDescriptorPanel::OnAddAttribute(wxCommandEvent& event)
148 std::string name_att;
149 if (AttributeCombo->GetSelection() == 0)
151 name_att = "D" + crea::wx2std(GRCtrl->GetValue()) + "_" + crea::wx2std(ELCtrl->GetValue());
155 wxString wd = AttributeCombo->GetValue();
156 std::string st = crea::wx2std(wd);
157 name_att = OwnAttribute(st);
159 onAddAttribute(crea::wx2std(AttributeCombo->GetValue()), name_att);
161 //////////////////////////////////////////////////////////
162 // add an attribute //
163 // @param att : attribute //
164 // @param name_att : 's name //
165 // @param level : level to add the attribute //
167 //////////////////////////////////////////////////
168 void WxDescriptorPanel::onAddAttribute( const std::string &att, const std::string &name_att,std::string level )
172 wxMessageBox(_T("Need a level first!"),crea::std2wx("WARNING"),wxOK,this);
178 // Find Name of level
184 if (!addAtribute(level, name_att))
186 wxMessageBox(_T("Attribute already used in this level"),crea::std2wx("WARNING"),wxOK,this);
190 ResultCtrl->SetInsertionPoint(InsertPt);
191 for (int i = 1; i<=lv;i++)
193 ResultCtrl->WriteText(_T(" "));
195 ResultCtrl->WriteText(_T("| - "));
196 ResultCtrl->WriteText(crea::std2wx(att));
197 wxTextAttr ResultAttr(ResultCtrl->GetDefaultStyle());
198 ResultAttr.SetTextColour(*wxWHITE);
199 ResultCtrl->SetDefaultStyle(ResultAttr);
200 std::string text = " ";
201 ResultCtrl->WriteText(crea::std2wx(" " + name_att));
202 ResultAttr.SetTextColour(*wxBLACK);
203 ResultCtrl->SetDefaultStyle(ResultAttr);
204 ResultCtrl->WriteText(_T("\n"));
206 InsertPt = ResultCtrl->GetInsertionPoint();
211 //////////////////////////////////////////////////////////
213 // @param event : Wxevent //
215 //////////////////////////////////////////////////
216 void WxDescriptorPanel::OnAddLevel(wxCommandEvent& event)
218 if( !LevelCtrl->GetValue().IsEmpty() )
220 onAddLevel(crea::wx2std(LevelCtrl->GetValue()));
224 //////////////////////////////////////////////////////////
226 // @param level : level's name //
228 //////////////////////////////////////////////////
229 void WxDescriptorPanel::onAddLevel(const std::string &level)
233 wxMessageBox(_T("Level already used"),crea::std2wx(("WARNING")),wxOK,this);
238 ResultCtrl->SetInsertionPoint(InsertPt);
239 for (int i = 1; i<lv;i++)
241 ResultCtrl->WriteText(_T(" "));
244 { ResultCtrl->WriteText(_T("| \n"));
245 for (int i = 1; i<lv;i++)
247 ResultCtrl->WriteText(_T(" "));
249 ResultCtrl->WriteText(_T("|_"));
252 wxTextAttr ResultAttr(ResultCtrl->GetDefaultStyle());
253 ResultAttr.SetTextColour(*wxRED);
254 ResultCtrl->SetDefaultStyle(ResultAttr);
255 ResultCtrl->WriteText(crea::std2wx(level));
256 ResultAttr.SetTextColour(*wxBLACK);
257 ResultCtrl->SetDefaultStyle(ResultAttr);
258 ResultCtrl->WriteText(_T("\n"));
259 InsertPt = ResultCtrl->GetInsertionPoint();
263 //////////////////////////////////////////////////////////
264 // Find a DICOM attribute from group and element values //
265 // @param event : Wxevent //
267 //////////////////////////////////////////////////
268 void WxDescriptorPanel::OnDicomAttribute(wxCommandEvent& event)
271 if(!GRCtrl->GetValue().IsEmpty() && !ELCtrl->GetValue().IsEmpty()
272 && GRCtrl->GetValue().Len() == 6 && ELCtrl->GetValue().Len() == 6 && AttributeCombo->GetSelection() == 0)
275 std::string gr = crea::wx2std(GRCtrl->GetValue());
276 std::string el = crea::wx2std(ELCtrl->GetValue());
277 std::stringstream val;
279 unsigned short group;
280 unsigned short element;
281 val << std::dec << gr ;
282 val >> std::hex >> group;
284 val << std::dec << el ;
285 val >> std::hex >> element;
286 #if defined(USE_GDCM)
287 // Retrieve the name from gdcm dict
288 GDCM_NAME_SPACE::DictEntry* entry = GDCM_NAME_SPACE::Global::GetDicts()->GetDefaultPubDict()->GetEntry(group, element);
289 // AttributeCombo->Clear();
292 AttributeCombo->Delete(0);
293 AttributeCombo->Insert(crea::std2wx(entry->GetName()), 0);
297 AttributeCombo->Delete(0);
298 AttributeCombo->Insert(_T("Unknown Attribute"),0);
301 AttributeCombo->SetSelection(0);
308 //////////////////////////////////////////////////////////
309 // determine values for own attributes //
310 // @param name : attribute's name //
311 // @param key : indicates key map or not //
313 //////////////////////////////////////////////////
314 std::string WxDescriptorPanel::OwnAttribute(const std::string name)
318 std::map<std::string, std::string>::iterator it_att = ownatt.begin();
319 for(; it_att != ownatt.end(); it_att++)
321 if(it_att->second == name)
323 result = it_att->first.c_str();
330 //////////////////////////////////////////////////////////
331 // Find a level in function of position in Return Ctrl //
334 //////////////////////////////////////////////////
335 std::string WxDescriptorPanel::findLevel()
340 ResultCtrl->PositionToXY( ResultCtrl->GetInsertionPoint(),&column, &line);
341 std::string tx(crea::wx2std(ResultCtrl->GetRange(0, ResultCtrl->XYToPosition(0,line+1))).c_str());
342 std::string::size_type level_pos_start = tx.rfind("|_");
343 if(level_pos_start == -1)
349 level_pos_start += 2;
352 std::string::size_type level_pos_end = tx.find_first_of("\n",level_pos_start);
353 return tx.substr(level_pos_start,level_pos_end - level_pos_start);
356 //////////////////////////////////////////////////////
358 // @param event : Wxevent //
360 //////////////////////////////////////////////////
361 void WxDescriptorPanel::OnRemove(wxCommandEvent& event)
368 pos_start = ResultCtrl->GetInsertionPoint();
369 ResultCtrl->PositionToXY( pos_start,&column, &line);
372 std::string name("root");
379 wxString text = ResultCtrl->GetLineText(line);
380 if ( text.Find(_T("|_")) == -1)
382 std::string level = findLevel();
383 // find GR and EL values to remove
384 std::string tx = crea::wx2std(text);
385 std::string::size_type EL_start_pos = tx.find_last_of(" ");
386 RemoveAttribute(level, tx.substr(EL_start_pos+1,tx.size() - EL_start_pos));
387 ResultCtrl->Remove( ResultCtrl->XYToPosition(0,line), ResultCtrl->XYToPosition(0,line+1));
391 RemoveLevel(crea::wx2std(text.AfterFirst('_')));
392 lv = text.Find(_T("|"))/3;
393 pos_start= ResultCtrl->XYToPosition(0,line-1);
394 ResultCtrl->SetInsertionPointEnd();
395 pos_end = ResultCtrl->GetInsertionPoint();
396 ResultCtrl->Remove(pos_start, pos_end);
401 //////////////////////////////////////////////
402 // create a descriptor structure //
403 // @param name : level's name to add //
404 // @return : boolean result //
405 //////////////////////////////////////////////////
406 void WxDescriptorPanel::CreateDescriptor(int type)
408 if(type == 0) // First initialization
411 outDscp += "<level>";
415 outDscp += "O Name Name 4";
422 outDscp += "O NumberOfChildren ";
423 outDscp += crea::wx2std(LevelCtrl->GetValue());
427 outDscp += "<level>";
429 outDscp += crea::wx2std(LevelCtrl->GetValue());
437 outDscp += crea::wx2std(GRCtrl->GetValue());
439 outDscp += crea::wx2std(ELCtrl->GetValue());
449 //////////////////////////////////////////////////////
451 // @param name : level's name to add //
452 // @return : boolean result //
453 //////////////////////////////////////////////////
454 bool WxDescriptorPanel::addLevel(const std::string &name)
457 std::map<std::string, std::vector <std::string> >::iterator it_tree = DscpTree.begin();
458 for (;it_tree != DscpTree.end(); it_tree++)
460 if(it_tree->first == name)
469 std::vector <std::string> branch;
470 DscpTree[name] = branch;
475 //////////////////////////////////////////////////////
477 // @param name : level's name to remove //
478 // @return : boolean result //
479 //////////////////////////////////////////////////
480 bool WxDescriptorPanel::RemoveLevel(const std::string &name)
482 bool bresult = false;
483 std::map<int, std::string>::iterator it_list= lvlist.begin();
484 for(; it_list != lvlist.end(); it_list++)
486 if(it_list->second == name)
491 std::map<int, std::string>::iterator it_list2 = it_list;
492 for(;it_list != lvlist.end(); it_list++)
494 std::map<std::string, std::vector <std::string> >::iterator it_tree = DscpTree.begin();
495 for (;it_tree != DscpTree.end(); it_tree++)
497 if(it_tree->first == name)
499 DscpTree.erase(it_tree);
504 lvlist.erase(it_list2, lvlist.end());
509 //////////////////////////////////////////////////////
510 // add an attribute in a level //
511 // @param level : level's name to add attribute //
512 // @param name : attribute's name //
513 // @return : boolean result //
514 //////////////////////////////////////////////////
515 bool WxDescriptorPanel::addAtribute(const std::string &level, const std::string &name)
518 std::map<std::string, std::vector <std::string> >::iterator it_tree = DscpTree.begin();
519 for (;it_tree != DscpTree.end(); it_tree++)
521 if (it_tree->first.c_str() == level)
523 std::vector<std::string>::iterator it_branch = it_tree->second.begin();
524 for(;it_branch != it_tree->second.end(); it_branch++)
526 if(it_branch->c_str() == name)
533 it_tree->second.push_back(name);
541 //////////////////////////////////////////////////////
542 // remove an attribute from a level //
543 // @param level : level's name to remove attribute //
544 // @param name : attribute's name //
545 // @return : boolean result //
546 //////////////////////////////////////////////////
547 bool WxDescriptorPanel::RemoveAttribute(const std::string &level, const std::string &name)
549 bool bresult = false;
550 std::map<std::string, std::vector <std::string> >::iterator it_tree = DscpTree.begin();
551 for (;it_tree != DscpTree.end(); it_tree++)
553 if(it_tree->first == level)
555 std::vector<std::string>::iterator it_branch = it_tree->second.begin();
556 cout << it_tree->second.size();
557 for(;it_branch != it_tree->second.end(); it_branch++)
559 if(it_branch->c_str() == name)
562 it_tree->second.erase(it_branch);
571 //////////////////////////////////////////////////
572 // create a new descriptor //
573 // @param event : WxEvent //
575 //////////////////////////////////////////////////
576 void WxDescriptorPanel::OnNew(wxCommandEvent &Event)
578 LevelCtrl->SetValue(_T("patient"));
584 //////////////////////////////////////////////////
585 // Load a descriptor file //
586 // @param event : WxEvent //
588 //////////////////////////////////////////////////
589 void WxDescriptorPanel::OnLoad(wxCommandEvent &Event)
591 long style = wxOPEN | wxFILE_MUST_EXIST;
592 LevelCtrl->SetValue(_T("patient"));
597 std::string wc("*.dscp");
598 wxFileDialog* FD = new wxFileDialog( 0,
600 crea::std2wx(m_path),
605 if (FD->ShowModal()==wxID_OK)
607 loadDescriptor(crea::wx2std(FD->GetPath()).c_str());
612 //////////////////////////////////////////////////
613 // Save a descriptor //
614 // @param event : WxEvent //
616 //////////////////////////////////////////////////
617 void WxDescriptorPanel::OnOK(wxCommandEvent &Event)
623 /////////////////////////////////////////////////////
624 // Save a descriptor and apply it (create a new DB//
625 // @param event : WxEvent //
627 /////////////////////////////////////////////////////
628 void WxDescriptorPanel::OnApply(wxCommandEvent &Event)
630 m_DscpFile = saveDescriptor();
632 SetReturnCode(ID_DSCP_APPLY);
635 const std::string WxDescriptorPanel::saveDescriptor()
637 std::string file = "";
639 std::string wc("*.dscp");
640 wxFileDialog* FD = new wxFileDialog( 0,
649 if (FD->ShowModal()==wxID_OK)
651 createDescriptorFile();
652 file = crea::wx2std(FD->GetPath()).c_str();
653 std::ofstream ofs(file.c_str());
661 ///////////////////////////////////////////////////////
663 // @param event : WxEvent //
665 ///////////////////////////////////////////////////////
667 void WxDescriptorPanel::OnCancel(wxCommandEvent& event)
671 ///////////////////////////////////////////////////////
672 // create a descriptor file //
675 ///////////////////////////////////////////////////////
676 void WxDescriptorPanel::createDescriptorFile()
680 outDscp += "<level>";
684 outDscp += "O Name Name 4";
686 std::map<std::string, std::vector <std::string> >::iterator it_tree = DscpTree.begin();
687 std::map<int, std::string >::iterator it_lv_nb = lvlist.begin();
688 std::map<int, std::string >::iterator it_lv = lvlist.begin();
690 for (;it_lv != lvlist.end(); it_lv++)
694 outDscp += it_lv->second.c_str();
696 if(it_lv_nb != lvlist.end())
698 outDscp += "O NumberOfChildren ";
699 outDscp += it_lv_nb->second.c_str();
704 std::vector<std::string>::iterator it_branch = DscpTree[it_lv->second.c_str()].begin();
705 for(;it_branch != DscpTree[it_lv->second.c_str()].end(); it_branch++)
707 std::string att = it_branch->c_str();
708 if(att[0] == 'D' && att[7] == '_' && att.size() == 14)
711 outDscp += att.substr(1,6) + " "; // GR
712 outDscp += att.substr(8,6) + " ";// EL
719 outDscp += it_branch->c_str();
721 outDscp += ownatt[att];
732 ///////////////////////////////////////////////////////
733 // load a descriptor //
734 // @param i_name : file name to load //
736 /////////////////////////////////////////////////////
737 void WxDescriptorPanel::loadDescriptor(const std::string i_name)
739 std::ifstream i_file(i_name.c_str());
740 std::stringstream buffer;
741 buffer << i_file.rdbuf();
745 #if defined(USE_GDCM2)
746 const gdcm::Global& g = gdcm::Global::GetInstance(); // sum of all knowledge !
747 const gdcm::Dicts &dicts = g.GetDicts();
748 const gdcm::Dict &dict = dicts.GetPublicDict(); // Part 6
756 while(std::getline(buffer, line))
759 { //increment levels.
765 // For each level, a name to describe it
775 // split line to find all tags
776 std::vector<std::string> descriptors;
777 std::string separator = " ";
778 std::string::size_type last_pos = line.find_first_not_of(separator);
779 //find first separator
780 std::string::size_type pos = line.find_first_of(separator, last_pos);
781 while(std::string::npos != pos || std::string::npos != last_pos)
783 descriptors.push_back(line.substr(last_pos, pos - last_pos));
784 last_pos = line.find_first_not_of(separator, pos);
785 pos = line.find_first_of(separator, last_pos);
788 // By default, the last tag is at zero and not recorded but if take in count
789 unsigned int flag = 0;
790 if(descriptors.size() == 4)
792 std::stringstream val;
793 val << std::dec << descriptors[3];
797 // if Dicom tag, use "group" and "element" descriptor
798 if(descriptors[0] == "D")
799 { std::stringstream val, val2;
800 unsigned short group;
801 unsigned short element;
802 val << std::dec << descriptors[1] ;
803 val >> std::hex >> group;
804 val2 << std::dec << descriptors[2];
805 val2 >> std::hex >> element;
806 std::string compose = "D";
807 compose += descriptors[1];
809 compose += descriptors[2];
810 #if defined(USE_GDCM)
811 GDCM_NAME_SPACE::DictEntry* entry = GDCM_NAME_SPACE::Global::GetDicts()->GetDefaultPubDict()->GetEntry(group, element);
814 onAddAttribute( entry->GetName(),compose, level);
818 #if defined(USE_GDCM2)
819 gdcm::DictEntry dictentry = dict.GetDictEntry(gdcm::Tag(group, element));
822 onAddAttribute( dictentry.GetName(),compose, level);
828 else if(descriptors[0].find("#") != -1)
830 // commented line continue to next line
832 else // "O" means if user's own tag.
834 boost::algorithm::replace_all(descriptors[2],"_"," ");
835 if(ilevel>0 && descriptors[1] != "NumberOfChildren" )
837 onAddAttribute( descriptors[2].c_str(),descriptors[1].c_str(), level);
844 //======================================================================
846 //======================================================================
848 } // EO namespace creaImageIO