/* # --------------------------------------------------------------------- # # Copyright (c) CREATIS (Centre de Recherche en Acquisition et Traitement de l'Image # pour la Santé) # Authors : Eduardo Davila, Frederic Cervenansky, Claire Mouton # Previous Authors : Laurent Guigues, Jean-Pierre Roux # CreaTools website : www.creatis.insa-lyon.fr/site/fr/creatools_accueil # # This software is governed by the CeCILL-B license under French law and # abiding by the rules of distribution of free software. You can use, # modify and/ or redistribute the software under the terms of the CeCILL-B # license as circulated by CEA, CNRS and INRIA at the following URL # http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html # or in the file LICENSE.txt. # # As a counterpart to the access to the source code and rights to copy, # modify and redistribute granted by the license, users are provided only # with a limited warranty and the software's author, the holder of the # economic rights, and the successive licensors have only limited # liability. # # The fact that you are presently reading this means that you have had # knowledge of the CeCILL-B license and that you accept its terms. # ------------------------------------------------------------------------ */ #include "creaImageIOWxDescriptorPanel.h" #include #if defined(USE_GDCM) #include #include #endif #if defined(USE_GDCM2) #include #include #include #endif #include namespace creaImageIO { // CTor WxDescriptorPanel::WxDescriptorPanel(wxWindow *parent, const std::string path) : wxDialog(parent, -1,_T("Descriptor Creation"), wxDefaultPosition, wxSize(550,550)) , m_path(path) { GimmickDebugMessage(1,"WxDescriptorPanel::WxDescriptorPanel" <GetId(), wxEVT_COMMAND_BUTTON_CLICKED , (wxObjectEventFunction) &WxDescriptorPanel::OnNew ); wxButton *LoadDescriptor = new wxButton(this, -1,_T("Load a descriptor"), wxPoint(150,7) ); Connect( LoadDescriptor->GetId(), wxEVT_COMMAND_BUTTON_CLICKED , (wxObjectEventFunction) &WxDescriptorPanel::OnLoad ); /// \TODO fix warning: unused variable line1 wxStaticLine *line1 = new wxStaticLine(this, -1, wxPoint(5,40), wxSize(540,2)); // LEVEL /// \TODO fix warning: unused variable LevelText wxStaticText * LevelText=new wxStaticText(this,-1,_T(" Level: "), wxPoint(5,50)); LevelCtrl=new wxTextCtrl(this, ID_GR_CTRL,_T("patient"), wxPoint(50,50), wxSize(50,25)); wxButton *addLevel = new wxButton(this, ID_LEVEL_ADD,_T("add a level"), wxPoint(150,50) ); Connect( addLevel->GetId(), wxEVT_COMMAND_BUTTON_CLICKED , (wxObjectEventFunction) &WxDescriptorPanel::OnAddLevel ); /// \TODO fix warning: unused variable line2 wxStaticLine *line2 = new wxStaticLine(this, -1, wxPoint(5,75), wxSize(540,2)); // ATTRIBUTES /// \TODO fix warning: unused variable GR wxStaticText * GR=new wxStaticText(this,-1,_T(" DICOM Group: "), wxPoint(5,110)); GRCtrl=new wxTextCtrl(this, ID_GR_CTRL,_T("0x0010"), wxPoint(82,110), wxSize(50,25)); Connect( GRCtrl->GetId(), wxEVT_COMMAND_TEXT_UPDATED , (wxObjectEventFunction) &WxDescriptorPanel::OnDicomAttribute ); /// \TODO fix warning: unused variable EL wxStaticText * EL=new wxStaticText(this,-1,_T(" DICOM Element: "), wxPoint(140,110)); ELCtrl=new wxTextCtrl(this, ID_EL_CTRL,_T("0x0010"), wxPoint(230,110), wxSize(50,25)); Connect( ELCtrl->GetId(), wxEVT_COMMAND_TEXT_UPDATED , (wxObjectEventFunction) &WxDescriptorPanel::OnDicomAttribute ); wxString choices[3]; choices[0] = _T("Unknow Attribute"); std::map::iterator it_att =ownatt.begin(); for(int i = 1; it_att != ownatt.end(); it_att++, i++) { choices[i] = crea::std2wx(it_att->second); } AttributeCombo = new wxComboBox(this, ID_ATTRIBUTE_CTRL,_T(""),wxPoint(300,110), wxSize(120,25),3,choices, wxCB_READONLY); AttributeCombo->SetSelection(0); wxButton *addAttribute = new wxButton(this, ID_ATTRIBUTE_ADD,_T("add an attribute"), wxPoint(440,110) ); Connect( addAttribute->GetId(), wxEVT_COMMAND_BUTTON_CLICKED , (wxObjectEventFunction) &WxDescriptorPanel::OnAddAttribute ); /// \TODO fix warning: unused variable line3 wxStaticLine *line3 = new wxStaticLine(this, -1, wxPoint(5,140), wxSize(540,2)); // RESULT ResultCtrl=new wxTextCtrl(this, ID_EL_CTRL,_T(""), wxPoint(5,150), wxSize(250,310), wxTE_READONLY| wxMac | wxTE_MULTILINE | wxTE_RICH ); wxButton *RemoveCtrl = new wxButton(this, ID_REMOVE_ADD,_T("Remove an entry"), wxPoint(280,200) ); Connect( RemoveCtrl->GetId(), wxEVT_COMMAND_BUTTON_CLICKED , (wxObjectEventFunction) &WxDescriptorPanel::OnRemove ); /// \TODO fix warning: unused variable line4 wxStaticLine *line4 = new wxStaticLine(this, -1, wxPoint(5,470), wxSize(540,2)); // VALIDATION BUTTON wxButton *Ok = new wxButton(this, -1,_T("OK"), wxPoint(10,480) ); Connect( Ok->GetId(), wxEVT_COMMAND_BUTTON_CLICKED , (wxObjectEventFunction) &WxDescriptorPanel::OnOK ); wxButton *Apply = new wxButton(this, -1,_T("APPLY"), wxPoint(150,480) ); Connect( Apply->GetId(), wxEVT_COMMAND_BUTTON_CLICKED , (wxObjectEventFunction) &WxDescriptorPanel::OnApply ); /// \TODO fix warning: unused variable Cancel wxButton *Cancel = new wxButton(this, wxID_CANCEL,_T("CANCEL"), wxPoint(250,480) ); // Connect( Cancel->GetId(), wxEVT_COMMAND_BUTTON_CLICKED , (wxCloseEvent) &wxWindow::Close ); Layout(); CreateDescriptor(0); } /// Destructor WxDescriptorPanel::~WxDescriptorPanel() { GimmickDebugMessage(1,"WxCustomizeConfigPanel::~WxCustomizeConfigPanel" <GetSelection() == 0) { name_att = "D" + crea::wx2std(GRCtrl->GetValue()) + "_" + crea::wx2std(ELCtrl->GetValue()); } else { wxString wd = AttributeCombo->GetValue(); std::string st = crea::wx2std(wd); name_att = OwnAttribute(st); } onAddAttribute(crea::wx2std(AttributeCombo->GetValue()), name_att); } ////////////////////////////////////////////////////////// // add an attribute // // @param att : attribute // // @param name_att : 's name // // @param level : level to add the attribute // // @return : - // ////////////////////////////////////////////////// void WxDescriptorPanel::onAddAttribute( const std::string &att, const std::string &name_att,std::string level ) { if(lv == 0) { wxMessageBox(_T("Need a level first!"),crea::std2wx("WARNING"),wxOK,this); } else { if( !att.empty() ) { // Find Name of level if(level.empty()) { level = findLevel(); } if (!addAtribute(level, name_att)) { wxMessageBox(_T("Attribute already used in this level"),crea::std2wx("WARNING"),wxOK,this); } else { ResultCtrl->SetInsertionPoint(InsertPt); for (int i = 1; i<=lv;i++) { ResultCtrl->WriteText(_T(" ")); } ResultCtrl->WriteText(_T("| - ")); ResultCtrl->WriteText(crea::std2wx(att)); wxTextAttr ResultAttr(ResultCtrl->GetDefaultStyle()); ResultAttr.SetTextColour(*wxWHITE); ResultCtrl->SetDefaultStyle(ResultAttr); std::string text = " "; ResultCtrl->WriteText(crea::std2wx(" " + name_att)); ResultAttr.SetTextColour(*wxBLACK); ResultCtrl->SetDefaultStyle(ResultAttr); ResultCtrl->WriteText(_T("\n")); } InsertPt = ResultCtrl->GetInsertionPoint(); } } } ////////////////////////////////////////////////////////// // add a level // // @param event : Wxevent // // @return : - // ////////////////////////////////////////////////// void WxDescriptorPanel::OnAddLevel(wxCommandEvent& event) { if( !LevelCtrl->GetValue().IsEmpty() ) { onAddLevel(crea::wx2std(LevelCtrl->GetValue())); } } ////////////////////////////////////////////////////////// // add a level // // @param level : level's name // // @return : - // ////////////////////////////////////////////////// void WxDescriptorPanel::onAddLevel(const std::string &level) { if(addLevel(level)) { wxMessageBox(_T("Level already used"),crea::std2wx(("WARNING")),wxOK,this); return; } lv++; ResultCtrl->SetInsertionPoint(InsertPt); for (int i = 1; iWriteText(_T(" ")); } if(lv>1) { ResultCtrl->WriteText(_T("| \n")); for (int i = 1; iWriteText(_T(" ")); } ResultCtrl->WriteText(_T("|_")); } wxTextAttr ResultAttr(ResultCtrl->GetDefaultStyle()); ResultAttr.SetTextColour(*wxRED); ResultCtrl->SetDefaultStyle(ResultAttr); ResultCtrl->WriteText(crea::std2wx(level)); ResultAttr.SetTextColour(*wxBLACK); ResultCtrl->SetDefaultStyle(ResultAttr); ResultCtrl->WriteText(_T("\n")); InsertPt = ResultCtrl->GetInsertionPoint(); } ////////////////////////////////////////////////////////// // Find a DICOM attribute from group and element values // // @param event : Wxevent // // @return : - // ////////////////////////////////////////////////// void WxDescriptorPanel::OnDicomAttribute(wxCommandEvent& event) { //int i = 0; if(!GRCtrl->GetValue().IsEmpty() && !ELCtrl->GetValue().IsEmpty() && GRCtrl->GetValue().Len() == 6 && ELCtrl->GetValue().Len() == 6 && AttributeCombo->GetSelection() == 0) { std::string gr = crea::wx2std(GRCtrl->GetValue()); std::string el = crea::wx2std(ELCtrl->GetValue()); std::stringstream val; unsigned short group; unsigned short element; val << std::dec << gr ; val >> std::hex >> group; val.clear(); val << std::dec << el ; val >> std::hex >> element; #if defined(USE_GDCM) // Retrieve the name from gdcm dict GDCM_NAME_SPACE::DictEntry* entry = GDCM_NAME_SPACE::Global::GetDicts()->GetDefaultPubDict()->GetEntry(group, element); // AttributeCombo->Clear(); if(entry) { AttributeCombo->Delete(0); AttributeCombo->Insert(crea::std2wx(entry->GetName()), 0); } else { AttributeCombo->Delete(0); AttributeCombo->Insert(_T("Unknown Attribute"),0); } #endif AttributeCombo->SetSelection(0); } } ////////////////////////////////////////////////////////// // determine values for own attributes // // @param name : attribute's name // // @param key : indicates key map or not // // @return : - // ////////////////////////////////////////////////// std::string WxDescriptorPanel::OwnAttribute(const std::string name) { std::string result; std::map::iterator it_att = ownatt.begin(); for(; it_att != ownatt.end(); it_att++) { if(it_att->second == name) { result = it_att->first.c_str(); break; } } return result; } ////////////////////////////////////////////////////////// // Find a level in function of position in Return Ctrl // // @param - : // // @return : - // ////////////////////////////////////////////////// std::string WxDescriptorPanel::findLevel() { long column; long line; ResultCtrl->PositionToXY( ResultCtrl->GetInsertionPoint(),&column, &line); std::string tx(crea::wx2std(ResultCtrl->GetRange(0, ResultCtrl->XYToPosition(0,line+1))).c_str()); std::string::size_type level_pos_start = tx.rfind("|_"); if(level_pos_start == -1) { level_pos_start = 0; } else { level_pos_start += 2; } std::string::size_type level_pos_end = tx.find_first_of("\n",level_pos_start); return tx.substr(level_pos_start,level_pos_end - level_pos_start); } ////////////////////////////////////////////////////// // Remove an item // // @param event : Wxevent // // @return : - // ////////////////////////////////////////////////// void WxDescriptorPanel::OnRemove(wxCommandEvent& event) { long line; long column; long pos_start; long pos_end; pos_start = ResultCtrl->GetInsertionPoint(); ResultCtrl->PositionToXY( pos_start,&column, &line); if (line == 0) { std::string name("root"); RemoveLevel(name); ResultCtrl->Clear(); lv = 0; } else { wxString text = ResultCtrl->GetLineText(line); if ( text.Find(_T("|_")) == -1) { std::string level = findLevel(); // find GR and EL values to remove std::string tx = crea::wx2std(text); std::string::size_type EL_start_pos = tx.find_last_of(" "); RemoveAttribute(level, tx.substr(EL_start_pos+1,tx.size() - EL_start_pos)); ResultCtrl->Remove( ResultCtrl->XYToPosition(0,line), ResultCtrl->XYToPosition(0,line+1)); } else { RemoveLevel(crea::wx2std(text.AfterFirst('_'))); lv = text.Find(_T("|"))/3; pos_start= ResultCtrl->XYToPosition(0,line-1); ResultCtrl->SetInsertionPointEnd(); pos_end = ResultCtrl->GetInsertionPoint(); ResultCtrl->Remove(pos_start, pos_end); } } } ////////////////////////////////////////////// // create a descriptor structure // // @param name : level's name to add // // @return : boolean result // ////////////////////////////////////////////////// void WxDescriptorPanel::CreateDescriptor(int type) { if(type == 0) // First initialization { outDscp.clear(); outDscp += ""; outDscp += "\n"; outDscp += "root"; outDscp += "\n"; outDscp += "O Name Name 4"; outDscp += "\n"; } if(type == 1) { if(lv > 1) { outDscp += "O NumberOfChildren "; outDscp += crea::wx2std(LevelCtrl->GetValue()); outDscp += "s"; outDscp += "\n"; } outDscp += ""; outDscp += "\n"; outDscp += crea::wx2std(LevelCtrl->GetValue()); outDscp += "\n"; } if(type == 2) { outDscp += "D"; outDscp += " "; outDscp += crea::wx2std(GRCtrl->GetValue()); outDscp += " "; outDscp += crea::wx2std(ELCtrl->GetValue()); outDscp += " "; outDscp += "3"; outDscp += "\n"; } } ////////////////////////////////////////////////////// // add a level // // @param name : level's name to add // // @return : boolean result // ////////////////////////////////////////////////// bool WxDescriptorPanel::addLevel(const std::string &name) { bool bfound = false; std::map >::iterator it_tree = DscpTree.begin(); for (;it_tree != DscpTree.end(); it_tree++) { if(it_tree->first == name) { bfound = true; break; } } if(!bfound) { lvlist[lv] = name; std::vector branch; DscpTree[name] = branch; } return bfound; } ////////////////////////////////////////////////////// // remove a level // // @param name : level's name to remove // // @return : boolean result // ////////////////////////////////////////////////// bool WxDescriptorPanel::RemoveLevel(const std::string &name) { bool bresult = false; std::map::iterator it_list= lvlist.begin(); for(; it_list != lvlist.end(); it_list++) { if(it_list->second == name) { break; } } std::map::iterator it_list2 = it_list; for(;it_list != lvlist.end(); it_list++) { std::map >::iterator it_tree = DscpTree.begin(); for (;it_tree != DscpTree.end(); it_tree++) { if(it_tree->first == name) { DscpTree.erase(it_tree); break; } } } lvlist.erase(it_list2, lvlist.end()); return bresult; } ////////////////////////////////////////////////////// // add an attribute in a level // // @param level : level's name to add attribute // // @param name : attribute's name // // @return : boolean result // ////////////////////////////////////////////////// bool WxDescriptorPanel::addAtribute(const std::string &level, const std::string &name) { bool bresult = true; std::map >::iterator it_tree = DscpTree.begin(); for (;it_tree != DscpTree.end(); it_tree++) { if (it_tree->first.c_str() == level) { std::vector::iterator it_branch = it_tree->second.begin(); for(;it_branch != it_tree->second.end(); it_branch++) { if(it_branch->c_str() == name) { bresult = false; } } if(bresult) { it_tree->second.push_back(name); break; } } } return bresult; } ////////////////////////////////////////////////////// // remove an attribute from a level // // @param level : level's name to remove attribute // // @param name : attribute's name // // @return : boolean result // ////////////////////////////////////////////////// bool WxDescriptorPanel::RemoveAttribute(const std::string &level, const std::string &name) { bool bresult = false; std::map >::iterator it_tree = DscpTree.begin(); for (;it_tree != DscpTree.end(); it_tree++) { if(it_tree->first == level) { std::vector::iterator it_branch = it_tree->second.begin(); cout << it_tree->second.size(); for(;it_branch != it_tree->second.end(); it_branch++) { if(it_branch->c_str() == name) { bresult = true; it_tree->second.erase(it_branch); break; } } } } return bresult; } ////////////////////////////////////////////////// // create a new descriptor // // @param event : WxEvent // // @return : - // ////////////////////////////////////////////////// void WxDescriptorPanel::OnNew(wxCommandEvent &Event) { LevelCtrl->SetValue(_T("patient")); ResultCtrl->Clear(); DscpTree.clear(); lv = 0; } ////////////////////////////////////////////////// // Load a descriptor file // // @param event : WxEvent // // @return : - // ////////////////////////////////////////////////// void WxDescriptorPanel::OnLoad(wxCommandEvent &Event) { long style = wxOPEN | wxFILE_MUST_EXIST; LevelCtrl->SetValue(_T("patient")); ResultCtrl->Clear(); DscpTree.clear(); lv = 0; std::string wc("*.dscp"); wxFileDialog* FD = new wxFileDialog( 0, _T("Select file"), crea::std2wx(m_path), _T(""), crea::std2wx(wc), style, wxDefaultPosition); if (FD->ShowModal()==wxID_OK) { loadDescriptor(crea::wx2std(FD->GetPath()).c_str()); } } ////////////////////////////////////////////////// // Save a descriptor // // @param event : WxEvent // // @return : - // ////////////////////////////////////////////////// void WxDescriptorPanel::OnOK(wxCommandEvent &Event) { saveDescriptor(); wxWindow::Close(); } ///////////////////////////////////////////////////// // Save a descriptor and apply it (create a new DB// // @param event : WxEvent // // @return : - // ///////////////////////////////////////////////////// void WxDescriptorPanel::OnApply(wxCommandEvent &Event) { m_DscpFile = saveDescriptor(); wxWindow::Close(); SetReturnCode(ID_DSCP_APPLY); } const std::string WxDescriptorPanel::saveDescriptor() { std::string file = ""; long style = wxSAVE; std::string wc("*.dscp"); wxFileDialog* FD = new wxFileDialog( 0, _T("Select file"), _T(""), _T(""), crea::std2wx(wc), style, wxDefaultPosition); if (FD->ShowModal()==wxID_OK) { createDescriptorFile(); file = crea::wx2std(FD->GetPath()).c_str(); std::ofstream ofs(file.c_str()); ofs.clear(); ofs << outDscp; ofs.close(); } return file.c_str(); } /////////////////////////////////////////////////////// // Cancel action // // @param event : WxEvent // // @return : - // /////////////////////////////////////////////////////// void WxDescriptorPanel::OnCancel(wxCommandEvent& event) { } /////////////////////////////////////////////////////// // create a descriptor file // // @param - : // // @return : - // /////////////////////////////////////////////////////// void WxDescriptorPanel::createDescriptorFile() { outDscp.clear(); outDscp += ""; outDscp += "\n"; outDscp += "Root"; outDscp += "\n"; outDscp += "O Name Name 4"; outDscp += "\n"; std::map >::iterator it_tree = DscpTree.begin(); std::map::iterator it_lv_nb = lvlist.begin(); std::map::iterator it_lv = lvlist.begin(); it_lv_nb++; for (;it_lv != lvlist.end(); it_lv++) { outDscp +=""; outDscp += "\n"; outDscp += it_lv->second.c_str(); outDscp += "\n"; if(it_lv_nb != lvlist.end()) { outDscp += "O NumberOfChildren "; outDscp += it_lv_nb->second.c_str(); outDscp += "s"; outDscp += "\n"; it_lv_nb++; } std::vector::iterator it_branch = DscpTree[it_lv->second.c_str()].begin(); for(;it_branch != DscpTree[it_lv->second.c_str()].end(); it_branch++) { std::string att = it_branch->c_str(); if(att[0] == 'D' && att[7] == '_' && att.size() == 14) { outDscp += "D "; outDscp += att.substr(1,6) + " "; // GR outDscp += att.substr(8,6) + " ";// EL outDscp += "3"; outDscp += "\n"; } else { outDscp += "O "; outDscp += it_branch->c_str(); outDscp += " "; outDscp += ownatt[att]; outDscp += " "; outDscp += "2"; outDscp += "\n"; } } } } /////////////////////////////////////////////////////// // load a descriptor // // @param i_name : file name to load // // @return : - // ///////////////////////////////////////////////////// void WxDescriptorPanel::loadDescriptor(const std::string i_name) { std::ifstream i_file(i_name.c_str()); std::stringstream buffer; buffer << i_file.rdbuf(); std::string line; std::string level; #if defined(USE_GDCM2) const gdcm::Global& g = gdcm::Global::GetInstance(); // sum of all knowledge ! const gdcm::Dicts &dicts = g.GetDicts(); const gdcm::Dict &dict = dicts.GetPublicDict(); // Part 6 #endif bool bname; int ilevel = -1; while(std::getline(buffer, line)) { if(line =="") { //increment levels. ilevel++; bname = true; } else if(bname) { // For each level, a name to describe it level = line; if(ilevel>0) { onAddLevel(level); } bname = false; } else { // split line to find all tags std::vector descriptors; std::string separator = " "; std::string::size_type last_pos = line.find_first_not_of(separator); //find first separator std::string::size_type pos = line.find_first_of(separator, last_pos); while(std::string::npos != pos || std::string::npos != last_pos) { descriptors.push_back(line.substr(last_pos, pos - last_pos)); last_pos = line.find_first_not_of(separator, pos); pos = line.find_first_of(separator, last_pos); } // By default, the last tag is at zero and not recorded but if take in count unsigned int flag = 0; if(descriptors.size() == 4) { std::stringstream val; val << std::dec << descriptors[3]; val>> flag; } // if Dicom tag, use "group" and "element" descriptor if(descriptors[0] == "D") { std::stringstream val, val2; unsigned short group; unsigned short element; val << std::dec << descriptors[1] ; val >> std::hex >> group; val2 << std::dec << descriptors[2]; val2 >> std::hex >> element; std::string compose = "D"; compose += descriptors[1]; compose += "_"; compose += descriptors[2]; #if defined(USE_GDCM) GDCM_NAME_SPACE::DictEntry* entry = GDCM_NAME_SPACE::Global::GetDicts()->GetDefaultPubDict()->GetEntry(group, element); if(ilevel>0) { onAddAttribute( entry->GetName(),compose, level); } #endif #if defined(USE_GDCM2) gdcm::DictEntry dictentry = dict.GetDictEntry(gdcm::Tag(group, element)); if(ilevel>0) { onAddAttribute( dictentry.GetName(),compose, level); } #endif } else if(descriptors[0].find("#") != -1) { // commented line continue to next line } else // "O" means if user's own tag. { boost::algorithm::replace_all(descriptors[2],"_"," "); if(ilevel>0 && descriptors[1] != "NumberOfChildren" ) { onAddAttribute( descriptors[2].c_str(),descriptors[1].c_str(), level); } } } } } //====================================================================== //====================================================================== } // EO namespace creaImageIO