]> Creatis software - creaImageIO.git/blob - src2/creaImageIOWxTreeView.cpp
9b1f54eb5ae88a7aff505c0774bbba38e7d0331a
[creaImageIO.git] / src2 / creaImageIOWxTreeView.cpp
1 #include <creaImageIOWxTreeView.h>
2 #include <creaImageIOGimmickView.h>
3 #include <creaImageIOSystem.h>
4 #include <wx/splitter.h>
5 #include <wx/gdicmn.h>
6 #include <boost/date_time/gregorian/gregorian.hpp>
7 #include <creaImageIOGimmick.h>
8 #ifdef _DEBUG
9 #define new DEBUG_NEW
10 #endif
11 //=====================================================================
12 namespace creaImageIO
13 {
14
15   //=====================================================================
16 }
17 //=====================================================================
18
19 //=====================================================================
20 ///Comparing function for ordering algorithm. Takes parameters as strings.
21 int wxCALLBACK CompareFunctionStrings(long item1, long item2, long sortData)
22 {       
23   creaImageIO::ItemData* data1 = (creaImageIO::ItemData*)item1;
24   creaImageIO::ItemData* data2 = (creaImageIO::ItemData*)item2;
25
26   const std::string& s1(*(data1->attr));
27   const std::string& s2(*(data2->attr));
28   if(sortData==1)
29     {
30       // inverse the order
31       if (s1 < s2)
32         return 1;
33       if (s1 > s2)
34         return -1;
35       
36       return 0;
37     }
38   else
39     {
40       if (s1 < s2)
41         return -1;
42       if (s1 > s2)
43         return 1;
44       
45       return 0;
46       
47     }
48 }
49 //=====================================================================
50
51 //=====================================================================
52 ///Comparing function for ordering algorithm. Takes parameters as ints.
53 int wxCALLBACK CompareFunctionInts(long item1, long item2, long sortData)
54 {       
55   creaImageIO::ItemData* data1 = (creaImageIO::ItemData*)item1;
56   creaImageIO::ItemData* data2 = (creaImageIO::ItemData*)item2;
57
58   const std::string& s1(*(data1->attr));
59   const std::string& s2(*(data2->attr));
60
61   int val1=atoi(s1.c_str());
62   int val2=atoi(s2.c_str());
63
64   if(sortData==1)
65     {
66       // inverse the order
67       if (val1 < val2)
68         return 1;
69       if (val1 > val2)
70         return -1;
71       
72       return 0;
73     }
74   else
75     {
76       if (val1 < val2)
77         return -1;
78       if (val1 > val2)
79         return 1;
80
81       return 0;
82       
83     }
84   
85 }
86
87 //=====================================================================
88
89
90 //=====================================================================
91 namespace creaImageIO
92 {
93   //=====================================================================
94   // CTor
95   WxTreeView::WxTreeView(TreeHandler* handler,
96                          GimmickView* gimmick,
97                          wxWindow* parent,
98                          const wxWindowID id)
99     : wxPanel(parent,id),
100       TreeView(handler, gimmick)
101   {
102     GimmickDebugMessage(1,"WxTreeView::WxTreeView"
103                         <<std::endl);
104
105     
106     // Split part below toolbar into notebook for views and panel
107     // for preview, messages...
108     // TO DO : Splitter
109     //    mSplitter = new wxSplitterWindow( this , -1);
110
111     // Global sizer
112     msizer = new wxBoxSizer(wxHORIZONTAL);
113     
114     int ctrl_style = wxLC_REPORT | wxLC_VRULES;
115     int col_style = wxLIST_FORMAT_LEFT;
116
117     // Creating the ListCtrl for the levels > 0 (not for Root level)
118     for (int i = 0;
119          i < handler->GetTree().GetNumberOfLevels() -1;
120          ++i)
121       {
122         GimmickDebugMessage(5,"Creating view for level "<<i
123                             <<std::endl);
124         LevelType level;
125         level.SelectedUpToDate = true;
126         level.SortColumn = 0;
127
128         // If the first level : parent = this
129         wxWindow* sparent = this;
130         // else parent = last splitter
131         if (i>0) 
132                 sparent = mLevelList[i-1].wxSplitter;
133
134         level.wxSplitter = new wxSplitterWindow( sparent , -1);
135         if(i!=0)
136         {
137         level.wxSplitter->Show(false);
138         }
139         //          level.wxSplitter->SetMinimumPaneSize(100);
140         
141         wxListCtrl* ctrl = new wxListCtrl(level.wxSplitter,
142                                           i,
143                                           wxDefaultPosition, 
144                                           wxDefaultSize,
145                                           ctrl_style);
146         level.wxCtrl = ctrl;
147         level.wxSplitter->Initialize(ctrl);
148    
149         // Create the columns : one for each attribute of the level
150         int col = 0;
151         std::string title;
152
153         tree::LevelDescriptor::AttributeDescriptorListType::const_iterator a;
154         for (a  = handler->GetTree().GetAttributeDescriptorList(i+1).begin();
155              a != handler->GetTree().GetAttributeDescriptorList(i+1).end();
156              ++a)
157
158 {
159         
160             GimmickDebugMessage(5,"Creating column "<<col<<" : "
161                                 <<a->GetName()
162                                 <<std::endl);
163             
164             if(a->GetFlags()!=creaImageIO::tree::AttributeDescriptor::PRIVATE)
165               {
166                 
167                 if(a->GetName()=="UNKNOWN")
168                   {
169                     title = "#";
170                     title += handler->GetTree().GetLevelDescriptor(i+1).GetName();
171                     if (title[title.size()-1]!='s')
172                       title += "s";
173                     
174                   }
175                 else
176                   {
177                     title=a->GetName();
178                   }
179                   std::string temp = a->GetKey();
180                   if (temp.compare("ID") != 0)
181                   {
182                 
183                 ctrl->InsertColumn(col, 
184                                    crea::std2wx(title),
185                                    col_style);
186                 col++;
187                   }
188                 level.key.push_back(a->GetKey());
189               }
190                 
191           }
192           
193         mLevelList.push_back(level);
194       }
195     
196 #if wxUSE_MENUS
197
198          // Column Menu
199     menu =new wxMenu;
200         wxMenuItem* m1=menu->Append(wxID_ANY, _T("&Sort ascending"));
201         wxMenuItem* m2=menu->Append(wxID_ANY, _T("&Sort descending"));
202         wxMenuItem* m3=menu->Append(wxID_ANY, _T("&Filter"));
203         mAscendingID=m1->GetId();
204         mDescendingID=m2->GetId();
205         mFilterID=m3->GetId();
206         Connect( mAscendingID, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(WxTreeView::OnPopupSort) );
207         Connect( mDescendingID, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(WxTreeView::OnPopupSort) );
208         Connect( mFilterID, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(WxTreeView::OnPopupFilter) );
209
210
211
212         //ItemMenu
213         menuItem =new wxMenu;
214         wxMenuItem* m1Item=menuItem->Append(wxID_ANY, _T("&Anonymize"));
215         wxMenuItem* m2Item=menuItem->Append(wxID_ANY, _T("&Local Copy"));
216         wxMenuItem* m3Item=menuItem->Append(wxID_ANY, _T("&Edit Fields"));
217         wxMenuItem* m4Item=menuItem->Append(wxID_ANY, _T("&Display Dicom Tags"));
218
219         mAnonymizingID=m1Item->GetId();
220         mLocalCopyID=m2Item->GetId();
221         mEditFieldID=m3Item->GetId();
222         mDumpID=m4Item->GetId();
223         //Connect( mAnonymizingID, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(WxTreeView::OnAnonymize) );
224         Connect( mLocalCopyID, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(WxTreeView::OnLocalCopy) );
225         Connect( mEditFieldID, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(WxTreeView::OnEditField) );
226         Connect( mDumpID, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(WxTreeView::OnDumpTags) );
227         
228         
229 #endif // wxUSE_MENUS
230         /// Initialize the first level splitter
231           
232         msizer->Add( mLevelList[0].wxSplitter ,1, wxGROW  ,0);
233         //      mColumnSelected=1;
234         mLastSelected=0;
235         mLastLevel=0;
236         //      mDirection=true;
237
238         mIgnoreSelectedChanged = false;
239
240         //CreateColorPalette();
241     UpdateLevel(1);
242
243     SetSizer( msizer );     
244     SetAutoLayout(true);
245     Layout();
246
247   }
248   //=====================================================================
249
250   //=====================================================================
251   /// Destructor
252   WxTreeView::~WxTreeView()
253   {
254     GimmickDebugMessage(1,"WxTreeView::~WxTreeView"
255                         <<std::endl);
256         delete menu;
257         delete menuItem;
258
259   }
260   //=====================================================================
261   
262   
263   
264   //=====================================================================
265   const std::vector<tree::Node*>& WxTreeView::GetSelected(int level)
266   {
267           std::vector<tree::Node*>& sel = mLevelList[0].Selected;
268     //  if (GetSelectedUpToDate(level)) 
269     int l = level - 1;
270     // the selection of upper level
271         if(mLevelList.size() == level -1)
272                  sel = mLevelList.back().Selected;
273         else
274                   sel=  mLevelList[l].Selected;
275         if (sel.size() > 0)
276         {
277                 sel.clear();
278         }
279           if (level == 1) 
280       {
281         sel.push_back(GetTreeHandler()->GetTree().GetTree());
282       }
283           else if (level < mLevelList.size()+2 ) 
284     {
285                 long item = -1;
286                 for ( ;; )
287                 {
288                         item = GetCtrl(l-1)->GetNextItem(item,
289                                                                                  wxLIST_NEXT_ALL,
290                                                                                  wxLIST_STATE_SELECTED);
291                         if ( item == -1 )
292                                 break;
293                         long adr = GetCtrl(l-1)->GetItemData(item);
294                         tree::Node* n = ((ItemData*)adr)->node;
295                         if(mLastSelected==item)
296                         {
297                                 std::vector<tree::Node*>::iterator it;
298                                 it = sel.begin();
299                                 it = sel.insert ( it , n );
300                         }
301                         else
302                         {
303                                 
304                                 sel.push_back(n);
305                         }                       
306                         
307                 }
308                 /*int n = GetCtrl(l-1)->GetItemCount();
309                 for (int i = 0; i<n; i++)
310                 {
311                         std::cout<<GetCtrl(l-1)->GetItemState(i,wxLIST_STATE_SELECTED)<<std::endl;
312                         if ( GetCtrl(l-1)->GetItemState(i,wxLIST_STATE_SELECTED))
313                         {
314                                 long adr = GetCtrl(l-1)->GetItemData(i);
315                                 tree::Node* n = ((ItemData*)adr)->node;
316                                 if(mLastSelected==i)
317                                 {
318                                         std::vector<tree::Node*>::iterator it;
319                                         it = sel.begin();
320                                         it = sel.insert ( it , n );
321                                 }
322                                 else
323                                 {
324                                         
325                                         sel.push_back(n);
326                                 }
327                         }
328               }*/
329           }
330         else
331         {
332                 // NOTHING
333         }   
334          
335     //    return mLevelList[level-1].Selected;
336     return sel;
337   }
338
339   //=====================================================================
340   
341   //=====================================================================
342   ///Removes selected nodes on last selected level
343    // NOT SPECIFIC 
344   void WxTreeView::RemoveSelected(std::string &i_save)
345   {
346          bool erase=false;
347          
348          unsigned int tempLevel = mLastLevel;
349     mLastLevel+=1;
350     const std::vector<tree::Node*>& sel=GetSelected(mLastLevel+1);
351         // if no selection, no remove action.
352     if(sel.size() != 0)
353         {
354         
355             std::stringstream out;
356             std::string levelName=GetTreeHandler()->GetTree().GetLevelDescriptor(mLastLevel).GetName();
357             out<<"Delete ";
358             out<<sel.size();
359             if(sel.size()>1&&levelName.at(levelName.size()-1)!='s')
360               {
361                 out<<" "<<levelName;
362                 out<<"s?";
363               }
364             else
365               {
366                 out<<" "<<GetTreeHandler()->GetTree().GetLevelDescriptor(mLastLevel).GetName()<<"?";
367               }
368             if (wxMessageBox(crea::std2wx(out.str()),
369                              _T("Remove Files"),
370                              wxYES_NO,this ) == wxYES)
371               {
372                 erase = true;
373               }
374             if(erase)
375                   {
376             GetGimmickView()->modifyValidationSignal(false);
377                     bool needRefresh=false;
378                     std::vector<tree::Node*>::const_iterator i;
379                     for (i=sel.begin(); i!=sel.end(); ++i)
380                       {
381                         GimmickMessage(1,
382                                        "deleting '"
383                                        <<(*i)->GetLabel()
384                                        <<"'"<<mLastLevel
385                                        <<std::endl);
386                         if((*i)->GetParent()->GetNumberOfChildren()<2)
387                           {
388                             needRefresh=true;
389                           }
390                           //tree::Node* n = new (tree::Node*)(*i);
391                           GetTreeHandler()->LoadChildren((*i),4);
392                           GetGimmickView()->AddIgnoreFile(*i);
393                           GetTreeHandler()->Remove(*i);
394                       }
395                     
396                     if(needRefresh && mLastLevel>1)
397                       {
398                         UpdateLevel(mLastLevel-2);
399                       }
400                     else if(mLastLevel>1)
401                       {
402                         UpdateLevel(mLastLevel-1);
403                       }
404                     else
405                       {
406                         UpdateLevel(mLastLevel);
407                       }
408                   }
409         }
410         else
411         {
412                 // no need to incremente level
413                 mLastLevel = tempLevel;
414         }
415     
416         if (erase && mLastLevel == 1 && i_save == "0")
417         {
418         
419                 RemoveAlertDlg *dial = new RemoveAlertDlg(this,  crea::std2wx("Remove files"), wxSize(370,100));
420                 //dial->ShowModal();
421                 if (dial->ShowModal() == wxID_OK)
422                 {
423                         i_save = dial->isChecked() == false? "0" : "1";
424                 }
425                 
426         }
427   }
428   
429   
430   //=====================================================================
431   /// Updates a level of the view (adds or removes children, etc.)
432   void WxTreeView::UpdateLevel( int level )
433   {
434     GimmickDebugMessage(1,
435                         GetTreeHandler()->GetTree().GetLabel()
436                         <<"WxTreeView::UpdateLevel(level "
437                         <<level
438                         <<")"
439                         <<std::endl);
440     
441     wxBusyCursor busy;
442     RecursiveUpdateLevel(level);
443     int i;
444     for (i=0; i<level-1; i++)
445       {
446         if (!GetSplitter(i)->IsSplit()) 
447           GetSplitter(i)->SplitVertically(  GetCtrl(i), GetSplitter(i+1),
448                                             100 );
449       }
450     if (GetSplitter(i)->IsSplit()) GetSplitter(i)->Unsplit();    
451     
452   }
453   //=====================================================================
454   
455   //=====================================================================
456   /// Recursive method called upon by UpdateLevel to refresh all windows
457   void WxTreeView::RecursiveUpdateLevel( int level )
458   {
459     GimmickDebugMessage(1,
460                         GetTreeHandler()->GetTree().GetLabel()
461                         <<"WxTreeView::RecursiveUpdateLevel(level "
462                         <<level
463                         <<")"<<std::endl);
464     
465     
466     const std::vector<tree::Node*>& sel(GetSelected(level));
467     
468     int l = level - 1;
469     
470     // to speed up inserting we hide the control temporarily
471     GetCtrl(l)->Hide();
472     GetCtrl(l)->DeleteAllItems();
473     
474     std::vector<tree::Node*>::const_iterator i;
475     
476     for (i=sel.begin(); i!=sel.end(); ++i)
477       {
478         GimmickDebugMessage(1,
479                             "adding children of '"
480                             <<(*i)->GetLabel()
481                             <<"'"
482                             <<std::endl);
483         int _id=0;
484         
485         //Adds items and sets their attributes 
486         
487         GetTreeHandler()->LoadChildren(*i,1);
488         tree::Node::ChildrenListType::reverse_iterator j;
489         for (j = (*i)->GetChildrenList().rbegin(); 
490              j!= (*i)->GetChildrenList().rend(); 
491              ++j)
492           {
493             GimmickDebugMessage(1,
494                                 "adding children "
495                                 <<(*j)->GetLabel()
496                                 <<"'"
497                                 <<std::endl);
498             
499             wxListItem item;
500             item.SetMask(wxLIST_MASK_STATE | 
501                          wxLIST_MASK_TEXT |
502                          //                      wxLIST_MASK_IMAGE |
503                          wxLIST_MASK_DATA |
504                          //                      wxLIST_MASK_WIDTH |
505                          wxLIST_MASK_FORMAT
506                          );
507             
508                 ItemData* data = new ItemData();
509             data->node = *j;
510             data->id = _id;
511                 
512             item.SetId(_id);
513             item.SetData(data);
514
515             _id++;
516             GetCtrl(l)->InsertItem(item);
517             
518             //Setting attributes
519             for (int k=0; k<GetCtrl(l)->GetColumnCount(); ++k)                          
520               {
521                 std::string val;
522                 //  Temporary correction : it works but no explanation about the problem FCY
523                 
524                 if(k==0 && level <3)
525                 {
526                   val = (*j)->GetAttribute("NumberOfChildren");
527                 }
528                 else
529                   val = (*j)->GetAttribute(mLevelList[l].key[k]);
530                 if(((*j)->GetAttributeDescriptor(mLevelList[l].key[k])).isDateEntry()) // Date
531                   {
532                     //                                    std::cout << "["<<val<< "]" << std::endl;
533                     std::string valtmp(val);
534                     try
535                       {
536                         boost::gregorian::date d1(boost::gregorian::from_undelimited_string(val));                                 
537                         val = to_iso_extended_string(d1);
538                       }
539                     catch (...)
540                       {
541                         val =  valtmp;
542                       }
543                     //                                    std::cout << "["<<val<< "]" << std::endl;     
544                   }
545                 else if(((*j)->GetAttributeDescriptor(mLevelList[l].key[k])).isTimeEntry()) // Time
546                   {
547                     if ((val.size()>6) && 
548                         (val != "" || val != " "))
549                       val = val.substr(0,2) + " : " 
550                         + val.substr(2,2) + " : " 
551                         + val.substr(4,2);
552                   }
553                 else
554                   {
555                     if (val.size()==0) val = "?";
556                   }
557                 if (val.size()==0) val = "X";
558                 item.SetText( crea::std2wx(val));
559                 item.SetColumn(k);
560                   
561                   GetCtrl(l)->SetItem(item);
562                   }
563                 item.Clear();
564             
565           }
566       }
567     
568     SortLevel(l);
569     GetCtrl(l)->Show();
570   }
571   //=====================================================================
572   
573   
574   //================================================================
575   void WxTreeView::OnItemDeSelected(wxListEvent& event)
576   { 
577     GimmickDebugMessage(1,
578                         GetTreeHandler()->GetTree().GetLabel()
579                         <<" WxTreeView::OnItemDeselected"<<std::endl);
580     // retrieve the level
581     wxObject* obj = event.GetEventObject();   
582     unsigned int level = 0;
583     for (level = 0; level<mLevelList.size(); ++level)
584       {
585         if ( GetCtrl(level) == obj ) break;
586       } 
587     SetSelectedUpToDate(level,false);
588     // to allow a first selection in images TreeView
589     if (level==mLevelList.size()-1) 
590       OnItemSelected(event);
591   }
592   //================================================================
593   
594   //================================================================
595   void WxTreeView::OnItemSelected(wxListEvent& event)
596   { 
597           
598     GimmickDebugMessage(1,
599                         GetTreeHandler()->GetTree().GetLabel()
600                         <<" WxTreeView::OnItemSelected"<<std::endl);
601
602     if (mIgnoreSelectedChanged) 
603       {
604         GimmickDebugMessage(1,
605                             " mIgnoreSelectedChanged true: returning"
606                             <<std::endl);
607         return;
608       }
609     
610
611     
612     wxListItem info;
613     info.m_itemId = event.m_itemIndex;
614     mLastSelected = event.m_itemIndex;
615     // retrieve the level
616     wxObject* obj = event.GetEventObject();   
617     unsigned int level = 0;
618     for (level = 0; level<mLevelList.size(); ++level)
619       {
620         if ( GetCtrl(level) == obj ) break;
621       }
622         mLastLevel=level;
623     GimmickDebugMessage(1,
624                         " Level "<<level+1
625                         <<std::endl);
626     
627     // Update the children level (if selection not at last level)
628     if (level<mLevelList.size()-1) 
629       {
630                 
631         UpdateLevel( level + 2 ); 
632         // Reset the viewer setting the default image
633         GetGimmickView()->ClearSelection();
634       }
635     // Select all images if the selection is at series level
636     if (level==mLevelList.size()-2) 
637                 SelectAll(level+1);
638     // Validate selected images if the selection is at image level
639     if (level==(mLevelList.size()-1)) //&&mProcess) 
640       {
641         if(event.GetEventType()==wxEVT_COMMAND_LIST_ITEM_SELECTED)
642           {
643                   ValidateSelectedImages (true);
644           }
645         else
646           {
647                   ValidateSelectedImages (false);
648           }
649       }
650     
651   }
652   //================================================================
653
654   //================================================================
655   void WxTreeView::SelectAll(int level)
656   {
657     long item = -1;
658     //    int level=mLevelList.size()-1;
659     for ( ;; )
660       {
661         item = GetCtrl(level)->GetNextItem(item,
662                                            wxLIST_NEXT_ALL);
663         if ( item == -1 )
664           break;
665         
666         if(item==(GetCtrl(level)->GetItemCount()-1))
667           {
668             mIgnoreSelectedChanged = false;//mProcess=true;
669           }
670         else
671           {
672             mIgnoreSelectedChanged = true;//    mProcess=false;
673           }
674         GetCtrl(level)->SetItemState(item,wxLIST_STATE_SELECTED, wxLIST_MASK_STATE 
675                                      | wxLIST_MASK_TEXT |wxLIST_MASK_IMAGE | wxLIST_MASK_DATA | wxLIST_MASK_WIDTH | wxLIST_MASK_FORMAT);
676       }
677   }
678
679   //================================================================
680   //================================================================
681
682   void WxTreeView::OnColClick(wxListEvent& event)
683   { 
684     mColumnSelected = event.m_col;
685     wxPoint clientpt;
686     clientpt.x = wxGetMousePosition().x - this->GetScreenPosition().x;
687     clientpt.y = wxGetMousePosition().y - this->GetScreenPosition().y;
688     senderCtrl = event.GetEventObject(); 
689     unsigned int level = 0;
690     for (level = 0; level<mLevelList.size(); ++level)
691       {
692         if ( GetCtrl(level) == senderCtrl ) break;
693       }
694     PopupMenu(menu, clientpt);
695     
696   }
697
698    //================================================================
699   //================================================================
700
701   void WxTreeView::OnItemMenu(wxListEvent &event)
702   {
703          wxPoint clientpt;
704     clientpt.x = wxGetMousePosition().x - this->GetScreenPosition().x;
705     clientpt.y = wxGetMousePosition().y - this->GetScreenPosition().y;
706     senderCtrl = event.GetEventObject();
707     unsigned int level = 0;
708     for (level = 0; level<mLevelList.size(); ++level)
709       {
710                 if ( GetCtrl(level) == senderCtrl ) break;
711       }
712           long* ptr=0;
713           int flag;
714           mLastRightLevel=level;
715           mLastRightSelected=GetCtrl(level)->HitTest(wxPoint(0,clientpt.y-8),flag,ptr);
716     PopupMenu(menuItem, clientpt);
717     
718   }
719   
720   //================================================================
721   //================================================================
722
723   void WxTreeView::OnPopupFilter(wxCommandEvent& event)
724   {
725     wxBusyCursor busy;
726     GimmickDebugMessage(7,
727                         "WxTreeView::OnEndLabelEdit" 
728                         <<std::endl);
729     unsigned int level = 0;
730     for (level = 0; level<mLevelList.size(); ++level)
731       {
732         if ( GetCtrl(level) == senderCtrl ) break;
733       }
734     std::string filter = crea::wx2std(wxGetTextFromUser(_T("Enter the filter to apply"), _T("Filter On Column")));
735     
736     std::string att;
737     
738     long it = -1;
739     UpdateLevel(level+1);
740     
741     std::vector<long> items;
742     bool in=false;
743     int del=0;
744     for ( ;; )
745       {
746         it = GetCtrl(level)->GetNextItem(it,
747                                          wxLIST_NEXT_ALL);
748         if ( it == -1 )
749           break;
750         
751         long adr = GetCtrl(level)->GetItemData(it);
752         tree::Node* nod = ((ItemData*)adr)->node;
753         att=(*nod).GetAttribute(mLevelList[level].key[mColumnSelected]);
754         
755         
756         if(att.find(filter)>900)
757           {
758             
759             if(!in)
760               {
761                 in=true;
762               }
763             else
764               {
765                 del+=1;
766               }
767             
768             items.push_back(it-del);
769           }
770         
771       }
772     std::vector<long>::iterator iter;
773     for(iter=items.begin();iter!=items.end();++iter)
774       {
775         GetCtrl(level)->DeleteItem(*iter);
776       }
777     GetGimmickView()->ClearSelection();
778   }
779   //================================================================
780   
781   //================================================================
782   void WxTreeView::OnPopupSort(wxCommandEvent& event)
783   {
784     wxBusyCursor busy;
785     unsigned int level = 0;
786     for (level = 0; level<mLevelList.size(); ++level)
787       {
788         if ( GetCtrl(level) == senderCtrl ) break;
789       }
790     mLevelList[level].SortColumn = mColumnSelected;
791
792     if(event.GetId()==mAscendingID)
793       {
794         mLevelList[level].SortAscending = true;
795       }
796     else if(event.GetId()==mDescendingID)
797       {
798         mLevelList[level].SortAscending = false;
799       }
800           
801     SortLevel(level);
802   }
803   //================================================================
804
805   //================================================================
806   void WxTreeView::OnLocalCopy(wxCommandEvent& event)
807   {
808     wxBusyCursor busy;
809     
810         unsigned int tempLevel = mLastLevel;
811     mLastLevel+=1;
812     const std::vector<tree::Node*>& sel=GetSelected(mLastLevel+1);
813         
814     if(sel.size() != 0)
815         {
816             bool copy=false;
817             std::stringstream out;
818             std::string levelName=GetTreeHandler()->GetTree().GetLevelDescriptor(mLastLevel).GetName();
819             out<<"Copy ";
820             out<<sel.size();
821             if(sel.size()>1&&levelName.at(levelName.size()-1)!='s')
822               {
823                 out<<" "<<levelName;
824                 out<<"s to .gimmick?";
825               }
826             else
827               {
828                 out<<" "<<GetTreeHandler()->GetTree().GetLevelDescriptor(mLastLevel).GetName()<<" to .gimmick?";
829               }
830             if (wxMessageBox(crea::std2wx(out.str()),
831                              _T("Remove Files"),
832                              wxYES_NO,this ) == wxYES)
833               {
834                 copy = true;
835               }
836             if(copy)
837                   {
838                         std::vector<std::string> s;
839                         GetFilenamesAsString(sel,s);
840             GetGimmickView()->CopyFiles(s);
841                   }
842         }
843         else
844         {
845                 mLastLevel = tempLevel;
846         }
847     
848     
849   }
850   //================================================================
851
852    //================================================================
853   void WxTreeView::OnEditField(wxCommandEvent& event)
854   {
855         if(mLastRightSelected!=-1)
856         {
857     tree::Node* node=((ItemData*)GetCtrl(mLastRightLevel)->GetItemData(mLastRightSelected))->node;
858         tree::LevelDescriptor::AttributeDescriptorListType::const_iterator a;
859         std::vector<std::string> names;
860         std::vector<std::string> keys;
861         for (a  = GetTreeHandler()->GetTree().GetAttributeDescriptorList(mLastRightLevel+1).begin();
862              a != GetTreeHandler()->GetTree().GetAttributeDescriptorList(mLastRightLevel+1).end();
863              ++a)
864         {
865                 if(a->GetFlags()==creaImageIO::tree::AttributeDescriptor::EDITABLE)
866             {
867                         names.push_back(a->GetName());
868                         keys.push_back(a->GetKey());
869                 }
870         }
871         GetGimmickView()->CreateEditFieldsDialog(node,names,keys);
872         }
873   }
874
875   void WxTreeView::OnDumpTags(wxCommandEvent &event)
876   {
877           if(mLastRightSelected!=-1)
878         {
879     tree::Node* node=((ItemData*)GetCtrl(mLastRightLevel)->GetItemData(mLastRightSelected))->node;
880         tree::LevelDescriptor::AttributeDescriptorListType::const_iterator a;
881         std::vector<std::string> names;
882         std::vector<std::string> keys;
883         for (a  = GetTreeHandler()->GetTree().GetAttributeDescriptorList(mLastRightLevel+1).begin();
884              a != GetTreeHandler()->GetTree().GetAttributeDescriptorList(mLastRightLevel+1).end();
885              ++a)
886         {
887                 if(a->GetKey()=="FullFileName")
888             {
889                         GetGimmickView()->DumpTags(node->GetAttribute("FullFileName"));
890                         return;
891                 }
892         }
893           }
894           
895   }
896
897   //================================================================
898
899   //================================================================
900   void WxTreeView::SortLevel(int level)
901   {       
902     GimmickDebugMessage(1,
903                         "WxTreeView::SortLevel(" 
904                         <<level<<")"
905                         <<std::endl);  
906     //Obtain the column name and the level that needs to be organized
907     
908     //    int l = level - 1;
909     //Sets the data for the items to be sorted
910     //    std::string att;
911     unsigned int ty=0;
912     int nbselected = 0;
913     int n = GetCtrl(level)->GetItemCount();
914     for (int i = 0; i < n; i++)
915       {
916         
917         //Gets current item data
918         ItemData* data = (ItemData*)GetCtrl(level)->GetItemData(i);
919         
920         //Extracts the node and the type of attribute   
921         tree::Node* nod = data->node;
922         if(i==0)
923           {
924             (*nod).GetAttributeDescriptor
925               (mLevelList[level].key[mLevelList[level].SortColumn])
926               .DecodeType( ty );
927           }
928         //Obtains the organizing attribute
929         data->attr = & (*nod).GetAttribute
930           (mLevelList[level].key[mLevelList[level].SortColumn]);
931         //Selected ?
932         data->selected = false;
933         if (GetCtrl(level)->GetItemState(i,wxLIST_STATE_SELECTED)>0)
934           {
935             data->selected = true;
936             nbselected++;
937           }
938
939       } 
940     GimmickDebugMessage(1,
941                         "WxTreeView::OnSort : " 
942                         <<nbselected<<" selected before sorting"
943                         <<std::endl);  
944
945     mIgnoreSelectedChanged = true; 
946     // 
947     if (mLevelList[level].SortAscending)
948       {
949         
950         if(ty==1)
951           {
952             GetCtrl(level)->SortItems(CompareFunctionInts, 0);
953           }
954         else
955           {
956             GetCtrl(level)->SortItems(CompareFunctionStrings, 0);
957           }
958         
959       }
960     else
961       {
962         if(ty==1)
963           {
964             GetCtrl(level)->SortItems(CompareFunctionInts, 1);
965           }
966         else
967           {
968             GetCtrl(level)->SortItems(CompareFunctionStrings, 1);
969           }
970       }
971  
972
973     // Reselects the unselected 
974     n = GetCtrl(level)->GetItemCount();
975     int after = 0;
976     for (int i = 0; i < n; i++)
977       {
978         
979         //Gets current item data
980         ItemData* data = (ItemData*)GetCtrl(level)->GetItemData(i);
981   
982         //  long item = -1;
983         //    for ( ;; )
984         //      {
985         //      item = GetCtrl(level)->GetNextItem(item,wxLIST_NEXT_ALL);
986         //      if ( item == -1 ) break;
987         //Gets current item data
988         //      ItemData* data = (ItemData*)GetCtrl(level)->GetItemData(item);
989         // was selected ?
990         
991         if (data->selected)
992           {
993             nbselected--;
994             if (nbselected==0)
995               {
996                 // if it is the last one we must process the selection
997                 mIgnoreSelectedChanged = false;
998               }
999             GetCtrl(level)->SetItemState(i,
1000                                          wxLIST_STATE_SELECTED, 
1001                                          wxLIST_MASK_STATE 
1002                                          | wxLIST_MASK_TEXT 
1003                                          | wxLIST_MASK_IMAGE 
1004                                          | wxLIST_MASK_DATA 
1005                                          | wxLIST_MASK_WIDTH 
1006                                          | wxLIST_MASK_FORMAT);   
1007           }
1008         if (GetCtrl(level)->GetItemState(i,wxLIST_STATE_SELECTED)>0)
1009           {
1010             after++;
1011           }
1012
1013         
1014       }
1015     mIgnoreSelectedChanged = false; 
1016      GimmickDebugMessage(1,
1017                         "WxTreeView::SortLevel : " 
1018                         <<after<<" selected after sorting"
1019                         <<std::endl);  
1020   
1021   }
1022   //================================================================
1023
1024   
1025   //================================================================
1026   void WxTreeView::ValidateSelectedImages(bool isSelection)
1027   {
1028     GimmickDebugMessage(7,
1029                         "WxTreeView::ValidateSelectedImages" 
1030                         <<std::endl);
1031     const std::vector<tree::Node*>& sel(GetSelected(mLevelList.size()+1));
1032     GetGimmickView()->OnSelectionChange(sel,
1033                                         isSelection,(mLastSelected-1),
1034                                         !mIgnoreSelectedChanged);
1035  
1036   }
1037   //================================================================
1038
1039
1040   //================================================================
1041   void WxTreeView::GetNodes(std::vector<tree::Node*>& nodes, bool direction)
1042   {
1043         long item = mLastSelected;
1044         int level=mLevelList.size()-1;
1045         //Gets current item data
1046         long adr = GetCtrl(level)->GetItemData(item);
1047         //Extracts the node
1048         tree::Node* nod = ((ItemData*)adr)->node;
1049     for ( ;; )
1050     {
1051                 if(direction)
1052                 {
1053                         item = GetCtrl(level)->GetNextItem(item,
1054                                      wxLIST_NEXT_ABOVE);
1055                 }
1056                 else
1057                 {
1058                         item = GetCtrl(level)->GetNextItem(item,
1059                                      wxLIST_NEXT_BELOW);
1060                 }
1061         if ( item == -1 || item==0  )
1062                 {
1063             break;
1064                 }
1065                 if(GetCtrl(level)->GetItemState(item, wxLIST_STATE_SELECTED)==0 )
1066                 {
1067
1068                         adr = GetCtrl(level)->GetItemData(item);
1069                         nod = ((ItemData*)adr)->node;
1070                         nodes.push_back(nod);
1071                 }
1072     }
1073
1074   }
1075   //================================================================
1076    //=================================================
1077   void WxTreeView::OnKeyDown(wxListEvent &event)
1078   {
1079           if(event.GetKeyCode() == WXK_DELETE)
1080           {
1081                    wxBusyCursor busy;
1082                    std::string temp = "0";
1083                    RemoveSelected(temp);
1084                    GetGimmickView()->ClearSelection();
1085           }
1086                   
1087   }
1088   //================================================================
1089
1090   //================================================================
1091   // Should be in another place : not specific !
1092   void WxTreeView::GetSelectedAsString(std::vector<std::string>&s)
1093   {
1094     int level=mLevelList.size();
1095     const std::vector<tree::Node*>& sel=GetSelected(level+1);
1096     std::vector<tree::Node*>::const_iterator i;
1097     
1098     for (i=sel.begin(); i!=sel.end(); ++i)
1099       {
1100         std::string filename=(*i)->GetAttribute("FullFileName");
1101         s.push_back(filename);
1102       }
1103   }
1104
1105   //================================================================
1106   void WxTreeView::GetFilenamesAsString(const std::vector<tree::Node*>& nodes, std::vector<std::string>&s)
1107   {
1108     std::vector<tree::Node*>::const_iterator i;
1109     
1110     for (i=nodes.begin(); i!=nodes.end(); ++i)
1111       {
1112                   if((*i)->GetLevel()<mLevelList.size())
1113                   {
1114                          GetTreeHandler()->LoadChildren(*i,0);
1115                          GetFilenamesAsString((*i)->GetChildrenList(),s);
1116                   }
1117                   else
1118                   {
1119                         std::string filename=(*i)->GetAttribute("FullFileName");
1120                         s.push_back(filename);
1121                   }
1122       }
1123   }
1124
1125    //================================================================
1126
1127    //================================================================
1128   void WxTreeView::GetAttributes(std::vector<std::string>& areShown, std::vector<std::string>& notShown, int level)
1129   {
1130           areShown.clear();
1131           notShown.clear();
1132         tree::LevelDescriptor::AttributeDescriptorListType::const_iterator a;
1133         for (a  = GetTreeHandler()->GetTree().GetAttributeDescriptorList(level).begin();
1134              a != GetTreeHandler()->GetTree().GetAttributeDescriptorList(level).end();
1135              ++a)
1136         {
1137                 if(a->GetFlags()==creaImageIO::tree::AttributeDescriptor::EDITABLE && IsAttributeVisible(a->GetName(),level))
1138             {
1139                         areShown.push_back(a->GetName());
1140                 }
1141         }
1142         notShown=mLevelList[level-1].notShownAtts;
1143   }
1144
1145   //================================================================
1146   void WxTreeView::SetNonVisibleAttributes(const std::vector<std::string>& notShown, int nlevel)
1147   {
1148         mLevelList[nlevel].notShownAtts=notShown;
1149   }
1150
1151   //================================================================
1152    void WxTreeView::CreateCtrl(std::vector<std::string>& notShown, int nlevel)
1153   {
1154         int ctrl_style = wxLC_REPORT | wxLC_VRULES;
1155     int col_style = wxLIST_FORMAT_LEFT;
1156         LevelType level;
1157         mLevelList[nlevel].SelectedUpToDate = true;
1158         mLevelList[nlevel].SortColumn = 0;
1159         mLevelList[nlevel].key.clear();
1160         
1161         mLevelList[nlevel].wxCtrl = new wxListCtrl(mLevelList[nlevel].wxSplitter,
1162                                           nlevel,
1163                                           wxDefaultPosition, 
1164                                           wxDefaultSize,
1165                                           ctrl_style);
1166         wxWindow* oldWin=mLevelList[nlevel].wxSplitter->GetWindow1();
1167         mLevelList[nlevel].wxSplitter->ReplaceWindow(oldWin,mLevelList[nlevel].wxCtrl);
1168         mLevelList[nlevel].wxSplitter->Initialize(mLevelList[nlevel].wxCtrl);
1169    
1170         // Create the columns : one for each attribute of the level
1171         int col = 0;
1172         std::string title;
1173
1174         tree::LevelDescriptor::AttributeDescriptorListType::const_iterator a;
1175         for (a  = GetTreeHandler()->GetTree().GetAttributeDescriptorList(nlevel+1).begin();
1176              a != GetTreeHandler()->GetTree().GetAttributeDescriptorList(nlevel+1).end();
1177              ++a)
1178
1179         {   
1180             if(a->GetFlags()!=creaImageIO::tree::AttributeDescriptor::PRIVATE && IsAttributeVisible(a->GetName(),nlevel+1))
1181               {
1182                   title=a->GetName();
1183                   std::string temp = a->GetKey();
1184                   if (temp.compare("ID") != 0)
1185                   {
1186                         mLevelList[nlevel].wxCtrl->InsertColumn(col, 
1187                                         crea::std2wx(title),
1188                                         col_style);
1189                         col++;
1190                   }
1191                 mLevelList[nlevel].key.push_back(a->GetKey());
1192               }
1193                 
1194           }
1195         oldWin->Destroy();
1196         UpdateLevel(1);
1197         }
1198
1199    //================================================================
1200   bool WxTreeView::IsAttributeVisible(const std::string& val, int level)
1201   {
1202           std::vector<std::string> ns=mLevelList[level-1].notShownAtts;
1203           std::vector<std::string>::iterator it;
1204           bool found=false;
1205           for(it=ns.begin();it!=ns.end()&&!found;++it)
1206           {
1207                   if(val.compare(*it)==0)
1208                   {
1209                           found=true;
1210                   }
1211           }
1212
1213           return !found;
1214   }
1215  //================================================================
1216   //================================================================
1217
1218         RemoveAlertDlg::RemoveAlertDlg(wxWindow *parent, 
1219                                                wxString title,    
1220                                                    const wxSize& size)
1221  :   wxDialog( parent, 
1222                   wxID_ANY, 
1223                   title,
1224                   wxDefaultPosition,
1225                   size,
1226                   wxDEFAULT_DIALOG_STYLE)
1227         {
1228             wxBoxSizer *topsizer = new wxBoxSizer(wxVERTICAL);
1229
1230                 //std::string out("To reload deleted patient, you should synchronize your database before.");  // JPR
1231                 //wxTextCtrl *text = new wxTextCtrl(this, wxID_ANY,crea::std2wx(out),wxDefaultPosition, wxSize(500,20));
1232                 wxTextCtrl *text = new wxTextCtrl(this, wxID_ANY,
1233                                         _T("To reload deleted patient, you should synchronize your database before."),
1234                                         wxDefaultPosition, wxSize(500,20));
1235                 mcheck = new wxCheckBox(this, 5478, _T("Do not display this warning again!"));
1236                 Connect( mcheck->GetId(), wxEVT_COMMAND_CHECKBOX_CLICKED , (wxObjectEventFunction) &RemoveAlertDlg::onCheck ); 
1237                 wxSizer* buttonsSizer = this->CreateSeparatedButtonSizer(wxOK|wxCANCEL);
1238                 
1239                 topsizer->Add(text);
1240                 topsizer->Add(mcheck,0,wxGROW);
1241                 topsizer->Add(buttonsSizer,0,wxGROW);
1242                 SetSizer(topsizer, true);
1243                 mSave = false;
1244                 Layout();
1245         }
1246         RemoveAlertDlg::~RemoveAlertDlg(){};
1247         bool RemoveAlertDlg::isChecked()
1248         {
1249                 return mSave;
1250         }
1251         void RemoveAlertDlg::onCheck(wxCommandEvent &Event)
1252         {
1253                 mSave = mcheck->IsChecked();
1254         }
1255         
1256
1257   //================================================================
1258   //================================================================
1259   BEGIN_EVENT_TABLE(WxTreeView, wxPanel)   
1260   /*
1261     EVT_SIZE(MyFrame::OnSize)
1262
1263     EVT_MENU(LIST_QUIT, MyFrame::OnQuit)
1264     EVT_MENU(LIST_ABOUT, MyFrame::OnAbout)
1265     EVT_MENU(LIST_LIST_VIEW, MyFrame::OnListView)
1266     EVT_MENU(LIST_REPORT_VIEW, MyFrame::OnReportView)
1267     EVT_MENU(LIST_ICON_VIEW, MyFrame::OnIconView)
1268     EVT_MENU(LIST_ICON_TEXT_VIEW, MyFrame::OnIconTextView)
1269     EVT_MENU(LIST_SMALL_ICON_VIEW, MyFrame::OnSmallIconView)
1270     EVT_MENU(LIST_SMALL_ICON_TEXT_VIEW, MyFrame::OnSmallIconTextView)
1271     EVT_MENU(LIST_VIRTUAL_VIEW, MyFrame::OnVirtualView)
1272     EVT_MENU(LIST_SMALL_VIRTUAL_VIEW, MyFrame::OnSmallVirtualView)
1273
1274     EVT_MENU(LIST_FOCUS_LAST, MyFrame::OnFocusLast)
1275     EVT_MENU(LIST_TOGGLE_FIRST, MyFrame::OnToggleFirstSel)
1276     EVT_MENU(LIST_DESELECT_ALL, MyFrame::OnDeselectAll)
1277     EVT_MENU(LIST_SELECT_ALL, MyFrame::OnSelectAll)
1278     EVT_MENU(LIST_DELETE, MyFrame::OnDelete)
1279     EVT_MENU(LIST_ADD, MyFrame::OnAdd)
1280     EVT_MENU(LIST_EDIT, MyFrame::OnEdit)
1281     EVT_MENU(LIST_DELETE_ALL, MyFrame::OnDeleteAll)
1282     EVT_MENU(LIST_SORT, MyFrame::OnSort)
1283     EVT_MENU(LIST_SET_FG_COL, MyFrame::OnSetFgColour)
1284     EVT_MENU(LIST_SET_BG_COL, MyFrame::OnSetBgColour)
1285     EVT_MENU(LIST_TOGGLE_MULTI_SEL, MyFrame::OnToggleMultiSel)
1286     EVT_MENU(LIST_SHOW_COL_INFO, MyFrame::OnShowColInfo)
1287     EVT_MENU(LIST_SHOW_SEL_INFO, MyFrame::OnShowSelInfo)
1288     EVT_MENU(LIST_FREEZE, MyFrame::OnFreeze)
1289     EVT_MENU(LIST_THAW, MyFrame::OnThaw)
1290     EVT_MENU(LIST_TOGGLE_LINES, MyFrame::OnToggleLines)
1291     EVT_MENU(LIST_MAC_USE_GENERIC, MyFrame::OnToggleMacUseGeneric)
1292
1293     EVT_UPDATE_UI(LIST_SHOW_COL_INFO, MyFrame::OnUpdateShowColInfo)
1294     EVT_UPDATE_UI(LIST_TOGGLE_MULTI_SEL, MyFrame::OnUpdateToggleMultiSel)
1295 END_EVENT_TABLE()
1296
1297 BEGIN_EVENT_TABLE(MyListCtrl, wxListCtrl)
1298     EVT_LIST_BEGIN_DRAG(LIST_CTRL, MyListCtrl::OnBeginDrag)
1299     EVT_LIST_BEGIN_RDRAG(LIST_CTRL, MyListCtrl::OnBeginRDrag)
1300         
1301     EVT_LIST_BEGIN_LABEL_EDIT(-1, WxTreeView::OnBeginLabelEdit)
1302     EVT_LIST_END_LABEL_EDIT(-1, WxTreeView::OnEndLabelEdit)
1303         
1304     EVT_LIST_DELETE_ITEM(LIST_CTRL, MyListCtrl::OnDeleteItem)
1305     EVT_LIST_DELETE_ALL_ITEMS(LIST_CTRL, MyListCtrl::OnDeleteAllItems)
1306 #if WXWIN_COMPATIBILITY_2_4
1307     EVT_LIST_GET_INFO(LIST_CTRL, MyListCtrl::OnGetInfo)
1308     EVT_LIST_SET_INFO(LIST_CTRL, MyListCtrl::OnSetInfo)
1309 #endif
1310   */
1311     EVT_LIST_KEY_DOWN(-1, WxTreeView::OnKeyDown)
1312     EVT_LIST_ITEM_SELECTED(-1, WxTreeView::OnItemSelected)
1313         EVT_LIST_ITEM_RIGHT_CLICK(-1, WxTreeView::OnItemMenu)
1314     EVT_LIST_ITEM_DESELECTED(-1, WxTreeView::OnItemDeSelected)
1315         /*
1316     EVT_LIST_KEY_DOWN(LIST_CTRL, MyListCtrl::OnListKeyDown)
1317     EVT_LIST_ITEM_ACTIVATED(LIST_CTRL, MyListCtrl::OnActivated)
1318     EVT_LIST_ITEM_FOCUSED(LIST_CTRL, MyListCtrl::OnFocused)
1319 */
1320     EVT_LIST_COL_RIGHT_CLICK(-1, WxTreeView::OnColClick)
1321         
1322     EVT_LIST_COL_CLICK(-1, WxTreeView::OnColClick)
1323
1324         //EVT_LEFT_DOWN(WxTreeView::OnMouseClick)
1325         /*
1326     EVT_LIST_COL_BEGIN_DRAG(LIST_CTRL, MyListCtrl::OnColBeginDrag)
1327     EVT_LIST_COL_DRAGGING(LIST_CTRL, MyListCtrl::OnColDragging)
1328     EVT_LIST_COL_END_DRAG(LIST_CTRL, MyListCtrl::OnColEndDrag)
1329
1330     EVT_LIST_CACHE_HINT(LIST_CTRL, MyListCtrl::OnCacheHint)
1331
1332 #if USE_CONTEXT_MENU
1333     EVT_CONTEXT_MENU(MyListCtrl::OnContextMenu)
1334 #endif
1335     EVT_CHAR(MyListCtrl::OnChar)
1336
1337     EVT_RIGHT_DOWN(MyListCtrl::OnRightClick)
1338   */
1339 END_EVENT_TABLE()
1340   
1341 } // EO namespace creaImageIO
1342