]> Creatis software - creaImageIO.git/blob - src2/creaImageIOWxGimmickView.cpp
*** empty log message ***
[creaImageIO.git] / src2 / creaImageIOWxGimmickView.cpp
1 #include <creaImageIOWxGimmickView.h>
2 #include <creaImageIOWxTreeView.h>
3 #include <creaImageIOSystem.h>
4 using namespace crea;
5 // Icons
6 #include "icons/accept.xpm"
7 #include "icons/add.xpm"
8 #include "icons/folder-down.xpm"
9 #include "icons/page-down.xpm"
10 #include "icons/remove.xpm"
11 #include "icons/database-add.xpm"
12 #include "icons/help.xpm"
13
14 #include <wx/imaglist.h>
15
16 namespace creaImageIO
17 {
18   //======================================================================
19   // The ids of the different tools
20   enum
21     {
22       TOOL_ADDFILES_ID = 1,
23       TOOL_ADDDIR_ID = 2,
24       TOOL_REMOVE_ID = 3,
25       TOOL_ADDDATABASE_ID = 4,
26       TOOL_HELP_ID = 5
27     };
28   //======================================================================
29
30   //================================================================
31   // 
32   const int icon_number = 7;
33   // Icon ids
34   typedef enum
35     {
36       Icon_accept,
37       Icon_add,
38       Icon_folder_down,
39       Icon_page_down,
40       Icon_remove,
41       Icon_database_add,
42       Icon_help
43     }
44     icon_id;
45   //================================================================
46
47   //================================================================
48   /*
49   const icon_id Icon[5] = { Icon_Database,  
50                             Icon_Patient,
51                             Icon_Study,
52                             Icon_Series,
53                             Icon_Image };
54   */
55   //================================================================
56
57
58   //======================================================================
59   // CTor
60   WxGimmickView::WxGimmickView(Gimmick* gimmick,
61                                wxWindow *parent, 
62                                const wxWindowID id,
63                                const wxPoint& pos, const wxSize& size,
64                                int min_dim,
65                                    int max_dim,
66                                int number_of_threads)
67     : wxPanel(parent,id,pos,size),
68       GimmickView(gimmick, number_of_threads),
69       mProgressDialog(0),
70       mConstructed(false)
71   {
72     GimmickDebugMessage(1,"WxGimmickView::WxGimmickView"
73                         <<std::endl);
74     // Sets the current directory to the home dir
75     mCurrentDirectory =  std2wx(gimmick->GetHomeDirectory());
76
77      // Connect the AddProgress callback
78     gimmick->ConnectAddProgressObserver
79       ( boost::bind( &WxGimmickView::OnAddProgress , this, _1 ) );
80
81     // Create the list of icons (mIcon)
82     CreateIconList();
83
84     // Global sizer
85     wxBoxSizer  *sizer = new wxBoxSizer(wxVERTICAL);
86
87     // Create the tool bar
88     CreateToolBar(); 
89     sizer->Add( mToolBar ,0, wxGROW  ,0);
90
91     // Split part below toolbar into notebook for views and panel
92     // for preview, messages...
93     mSplitter = new wxSplitterWindow( this , -1);
94  
95    
96     // Notebook
97     mNotebook = new wxNotebook(mSplitter,
98                                -1,wxDefaultPosition, wxDefaultSize, 0);
99
100     //Gimmick
101     mGimmick=gimmick;
102
103       
104     mSelectionMaxDimension= max_dim;
105     mSelectionMinDimension= min_dim;
106     
107     // Create the views
108     CreateTreeViews();
109
110     // Bottom panel 
111     mBottomPanel = new wxPanel(mSplitter,-1);
112     
113     wxBoxSizer  *bottom_sizer = new wxBoxSizer(wxHORIZONTAL);
114     
115     mText = new wxStaticText(mBottomPanel, wxID_ANY, wxT("Status: Welcome to Gimmick!"));
116     bottom_sizer->Add(mText,1,wxGROW,0);
117     
118     // Previewer
119     mViewer = new WxViewer(mBottomPanel, wxID_ANY, wxT("Gimmick! Viewer"),wxDefaultPosition, wxDefaultSize );
120
121     bottom_sizer->Add(mViewer,1,wxGROW,0);
122     //    mViewer->Show();
123
124     mBottomPanel->SetSizer(bottom_sizer);
125
126     // Splitting
127     int hsize = size.GetHeight();
128     int bottom_minsize = 40;
129
130     mSplitter->SetMinimumPaneSize( bottom_minsize );
131     mSplitter->SplitHorizontally( mNotebook, mBottomPanel, 
132                                    hsize - bottom_minsize);
133   
134     sizer->Add( mSplitter,1,wxGROW  ,0);
135
136
137     SetSizer( sizer );     
138     SetAutoLayout(true);
139     Layout();
140     
141     mConstructed = true;
142   }
143   //======================================================================
144
145   //======================================================================
146   /// Destructor
147   WxGimmickView::~WxGimmickView()
148   {
149     GimmickDebugMessage(1,"WxGimmickView::~WxGimmickView"
150                         <<std::endl);
151   }
152   //======================================================================
153   
154   //======================================================================
155   /// Creates the tool bar
156   void WxGimmickView::CreateToolBar()
157   {
158     long style = wxTB_HORIZONTAL | wxNO_BORDER | wxTB_TEXT;
159     mToolBar = new wxToolBar(this,-1,wxDefaultPosition,wxDefaultSize,
160                              style);
161
162     mToolAddFile = mToolBar->AddTool( TOOL_ADDFILES_ID, 
163                                       _T("Add file(s)"),
164                                       mIcon->GetBitmap(Icon_page_down),
165                                       _T("Add one or more file to database")
166                                       );
167     mToolAddDir = mToolBar->AddTool( TOOL_ADDDIR_ID, 
168                                       _T("Add folder"),
169                                       mIcon->GetBitmap(Icon_folder_down),
170                                       _T("Add the content of a folder to database")
171                                       );
172     mToolRemove = mToolBar->AddTool( TOOL_REMOVE_ID, 
173                                       _T("Remove"),
174                                       mIcon->GetBitmap(Icon_remove),
175                                       _T("Remove selected items")
176                                       );
177     mToolAddDatabase = mToolBar->AddTool( TOOL_ADDDATABASE_ID, 
178                                       _T("Open database"),
179                                       mIcon->GetBitmap(Icon_database_add),
180                                       _T("Open a local or distant database")
181                                       );
182     mToolHelp = mToolBar->AddTool( TOOL_HELP_ID, 
183                                       _T("Help"),
184                                       mIcon->GetBitmap(Icon_help),
185                                       _T("Open help window")
186                                       );
187     //const wxBitmap& bitmap1, const wxString& shortHelpString = "", wxItemKind kind = wxITEM_NORMAL)
188
189     mToolBar->Realize();
190   }
191   //======================================================================
192
193  
194   //======================================================================
195   /// Create the tree view for TreeHandler provided
196   void WxGimmickView::CreateTreeView( TreeHandler* h)
197   {
198     std::string name(h->GetTree().GetAttribute("Name"));
199     GimmickMessage(2,"Creating the tree view for '"<<
200                    name<<"'"<<std::endl);
201     // Create the WxTreeView
202     WxTreeView* view = new WxTreeView(h,this,mNotebook,-1);
203
204     // TO DO : TEST THAT A VIEW WITH SAME NAME IS NOT
205     // ALREADY IN THE MAP
206     GetTreeViewMap()[name] = view;
207
208     // Add Notebook page
209     mNotebook->AddPage( view, crea::std2wx(name) );
210
211   }
212   //======================================================================
213   /// Returns the selected Image so that it complies with the given parameter(<4D)
214   vtkImageData* WxGimmickView::GetSelectedImage(int dim)
215   {
216           return NULL;
217                   //GetTreeViewMap()["Local database"]->GetSelectedImage(dim);
218   }
219
220   //======================================================================
221   /// Returns the selected Images so that they comply with the given parameter(4D)
222   void WxGimmickView::GetSelectedImages(std::vector<vtkImageData*>& s, int dim)
223   {
224         int level=GetTreeViewMap()["Local database"]->GetNumberOfLevels();
225         std::vector<tree::Node*> im=GetTreeViewMap()["Local database"]->GetSelected(level+1);
226         ReadImagesNotThreaded(s,im,dim);
227   }
228   //======================================================================
229   /// Returns the selected Images so that they comply with the given parameter(4D)
230   void WxGimmickView::GetSelectedFiles(std::vector<std::string>& s)
231   {
232         GetTreeViewMap()["Local database"]->GetSelectedAsString(s);
233   }
234   //=================================================
235   void WxGimmickView::CreateIconList()
236   {
237     // Size of the icons;
238     int size = 24;
239
240     wxIcon icons[20];
241     // should correspond to Icon_xxx enum
242     icons[Icon_accept] = wxIcon(accept_xpm);
243     icons[Icon_add] = wxIcon(add_xpm);
244     icons[Icon_folder_down] = wxIcon(folder_down_xpm);
245     icons[Icon_page_down] = wxIcon(page_down_xpm);
246     icons[Icon_remove] = wxIcon(remove_xpm);
247     icons[Icon_database_add] = wxIcon(database_add_xpm);
248     icons[Icon_help] = wxIcon(help_xpm);
249
250     //   unsigned int NbIcons = 8;
251     // Make an image list containing small icons
252     mIcon = new wxImageList(size,size,true);
253     
254     // Make all icons the same size = size of the first one
255     int sizeOrig = icons[0].GetWidth();
256     for ( size_t i = 0; i < icon_number; i++ )
257       {
258         if ( size == sizeOrig )
259           {
260             mIcon->Add(icons[i]);
261           }
262         else
263           {
264             mIcon->Add(wxBitmap(wxBitmap(icons[i]).ConvertToImage().Rescale(size, size)));
265           }
266       }
267   }
268   //=================================================
269
270
271   //=================================================
272   void WxGimmickView::OnAddFiles(wxCommandEvent& event)
273   {
274    long style = wxOPEN | wxFILE_MUST_EXIST | wxFD_MULTIPLE;
275     std::string wc("*.*");
276     wxFileDialog* FD = new wxFileDialog( 0, 
277                                          _T("Select file"),
278                                          _T(""),
279                                          _T(""),
280                                          crea::std2wx(wc),
281                                          style,
282                                          wxDefaultPosition);
283     
284     if (FD->ShowModal()==wxID_OK)
285       {
286         wxBusyCursor busy;
287
288         wxArrayString files;
289         FD->GetPaths(files);
290         unsigned int i;
291         std::vector<std::string> filenames;
292         for (i=0;i<files.GetCount();++i)
293         {
294           filenames.push_back(wx2std(files[i]));
295           GimmickMessage(2,"Adding File "<<files[i]<<"."<<std::endl);
296         }
297
298         mProgressDialog = 
299           new wxProgressDialog(_T("Adding file(s)"),
300                                _T(""),
301                                1000,
302                                this,
303                                wxPD_ELAPSED_TIME |
304                                //                              wxPD_ESTIMATED_TIME | 
305                                //                              wxPD_REMAINING_TIME |
306                                wxPD_CAN_ABORT );
307
308         // TO DO : select the current tree handler
309         mGimmick->AddFiles("Local database",filenames);
310
311         mProgressDialog->Pulse(_T("Updating view..."));
312
313         UpdateTreeViewLevel("Local database",1);
314         delete mProgressDialog;
315         DisplayAddSummary();    
316       }
317         
318   }
319   //=================================================
320
321   //=================================================
322   void WxGimmickView::OnAddDir(wxCommandEvent& event)
323   {
324     long style = wxDD_DEFAULT_STYLE | wxDD_DIR_MUST_EXIST;
325     wxDirDialog* FD = 
326       new wxDirDialog( 0, 
327                        _T("Select directory"),
328                        mCurrentDirectory,
329                        style);
330     
331     if (FD->ShowModal()==wxID_OK)
332       {
333         
334         bool recurse = false;
335         if (wxMessageBox(_T("Recurse into sub-directories ?"),
336                          _T("Scan directory"),
337                          wxYES_NO,this ) == wxYES)
338           {
339             recurse = true;
340           }
341        
342         wxBusyCursor busy;
343         wxString title(_T("Adding directory"));
344         if (recurse) 
345           title = _T("Adding directory (recursive)");
346         mProgressDialog = 
347           new wxProgressDialog(_T("Adding directory"),
348                                _T(""),
349                                1000,
350                                this,
351                                wxPD_ELAPSED_TIME |
352                                //                              wxPD_ESTIMATED_TIME | 
353                                //                              wxPD_REMAINING_TIME |
354                                wxPD_CAN_ABORT );
355         std::string dirname = wx2std (FD->GetPath()) ;
356         mCurrentDirectory = FD->GetPath();  
357         
358         // TO DO : select the current tree handler
359         mGimmick->AddDir("Local database",dirname,recurse);
360         
361         mProgressDialog->Pulse(_T("Updating view..."));
362         
363         UpdateTreeViewLevel("Local database",1);
364         delete mProgressDialog;
365         DisplayAddSummary();
366       }
367   }
368   //=================================================
369
370   //=================================================
371   void WxGimmickView::OnSelectionChange(std::vector<tree::Node*>& sel)
372   {      
373     GimmickDebugMessage(5,
374                         "WxGimmickView::OnSelectionChange"
375                         <<std::endl);
376     wxBusyCursor busy;
377     bool valid = ValidateSelected(sel,
378                                   mSelectionMinDimension,
379                                   mSelectionMaxDimension );
380     mText->SetLabel(_T("Status: ")+crea::std2wx(GetMessage()));
381     if(valid)
382       {
383         ReadImageThreaded(sel);
384       }
385     else
386       {
387         mViewer->SetMovieSize(1);
388         mViewer->SetImage(0,GetDefaultImage());
389         //      mViewer->Hide();
390       }
391
392     
393    }
394
395   //==================================================
396
397   //==================================================
398   ///Reads Images (Threaded)
399   void WxGimmickView::ReadImageThreaded(std::vector<tree::Node*> sel)
400   {     
401    GimmickDebugMessage(5,
402                        "ReadImageThreaded"
403                        <<std::endl);
404    int maxprio = GetMaximalPriority();
405    int prio = maxprio + 2000;
406
407    mViewer->SetMovieSize(sel.size());//ClearImages();
408    
409    //First load the selected images
410    mCurImageItemToShow = sel.front();
411    int index = 0;
412    std::vector<tree::Node*>::iterator selected;
413    for(selected=sel.begin();selected!=sel.end();++selected)
414      {
415        GimmickDebugMessage(5,
416                            "Requesting image from selected "
417                            <<(*selected)->GetAttribute("FullFileName")
418                            <<std::endl);
419        RequestReading(*selected,prio,index);
420        //       AddEntryToMap(*selected);
421        prio--;
422        index++;
423      }
424         
425         //Going up
426         prio = maxprio + 20;
427         std::vector<tree::Node*> up;
428         GetTreeViewMap()["Local database"]->GetNodes(up,true);
429         std::vector<tree::Node*>::iterator iterUp;
430         for(iterUp=up.begin();iterUp!=up.end();++iterUp)
431         {
432                 GimmickDebugMessage(5,
433                                 "Requesting image from neighbors up "
434                                 <<(*iterUp)->GetAttribute("FullFileName")
435                                 <<std::endl);
436                 RequestReading(*iterUp,prio,-1);
437                 //              AddEntryToMap(*iterUp);
438                 prio--;
439                 if (prio == maxprio) break;
440         }
441
442         //Going down
443         prio = maxprio + 19;
444         std::vector<tree::Node*> down;
445         GetTreeViewMap()["Local database"]->GetNodes(down,false);
446         std::vector<tree::Node*>::iterator iterDown;
447         for(iterDown=down.begin();iterDown!=down.end();++iterDown)
448         {
449                 GimmickDebugMessage(5,
450                                 "Requesting image from neighbors down "
451                                 <<(*iterDown)->GetAttribute("FullFileName")
452                                 <<std::endl);
453                 RequestReading(*iterDown,prio,-1);
454                 //              AddEntryToMap(*iterDown);
455                 prio--;
456                 if (prio == maxprio) break;
457         }       
458   }
459
460   //==================================================
461
462   //==================================================
463   /// Processes the queue of image events 
464   void WxGimmickView::ProcessImageEvents()
465   {
466     if (!mConstructed) return;
467
468     //    int level=GetTreeViewMap()["Local database"]->GetNumberOfLevels();
469     //    std::vector<tree::Node*> sel=GetTreeViewMap()["Local database"]->GetSelected(level+1);
470     /*
471     GimmickDebugMessage(5,
472                         "Processing Images. Lock Started"
473                         <<std::endl);
474     */
475     MultiThreadImageReaderEventLock();
476     
477
478     while (!IsQueueEmpty())
479       {
480         GimmickDebugMessage(5,
481                             "Queue not empty"
482                             <<std::endl);
483         
484         vtkImageData* image = GetNextImageQueued();
485         if( image!=0 ) 
486           {
487             int index =  GetNextSelectionIndexQueued();
488             if (index>=0) 
489               {
490                 mViewer->SetImage(index,image);
491               }
492             /*
493             tree::Node* node=GetNextNodeQueued();
494             
495
496             bool found=false;
497             std::vector<tree::Node*>::iterator i;
498             for(i=sel.begin();i!=sel.end()&&!found;++i)
499               {
500                 if((*i)==node)
501                   {
502                     mViewer->AddImage(image);
503                     found=true;
504                   }
505               }
506             */
507             
508           }
509         UnqueueNext();
510       }
511     /*
512     if(!(mViewer->ImagesEmpty()))
513       {
514         GimmickDebugMessage(5,
515                             "Showing images"
516                             <<std::endl);
517         //      mViewer->ShowImages();
518         //      mViewer->Show();
519       }
520     */
521     ClearQueue();
522         
523
524     MultiThreadImageReaderEventUnlock();
525     /*
526         GimmickDebugMessage(5,
527                                 "Processing Images. Lock Ended"
528                                 <<std::endl);
529     */
530   }
531  
532   //==================================================
533
534   //==================================================
535    void  WxGimmickView::OnInternalIdle()
536   {
537    if (!mConstructed) return;
538    ProcessImageEvents();
539    static bool first_time = true;
540    if (false)
541      {
542         mViewer->SetMovieSize(1);
543         mViewer->SetImage(0,GetDefaultImage());
544         first_time = false;
545      }
546    //  mViewer->Refresh();
547   }
548   
549   //=================================================
550  
551   //=================================================
552   void WxGimmickView::OnRemove(wxCommandEvent& event)
553   {
554         //TODO Select current tree handler       
555     wxBusyCursor busy;
556     GetTreeViewMap()["Local database"]->RemoveSelected(1);
557   }
558   //=================================================
559
560   //=================================================
561   /// AddProgress Gimmick callback
562   void WxGimmickView::OnAddProgress( Gimmick::AddProgress& p)
563   {
564
565     char mess[200];
566     sprintf(mess,"%i dirs - %i files - %i handled - %i added",
567            p.GetNumberScannedDirs(),
568            p.GetNumberScannedFiles(),
569            p.GetNumberHandledFiles(),
570            p.GetNumberAddedFiles());
571     //    std::cout << "OnAddProgress "<<mess<<std::endl;
572     wxString s(wxString::From8BitData(mess));
573     //  std::cout << "Pulse"<<std::endl;
574     if (!mProgressDialog->Pulse(s)) 
575       {
576         p.SetStop();
577       }
578     //  std::cout << "OnAddProgress ok"<<std::endl;
579   }
580   //=================================================
581
582   //=================================================
583   void WxGimmickView::DisplayAddSummary()
584   {
585     const Gimmick::AddProgress& p = mGimmick->GetAddProgress();
586     std::stringstream mess;
587     mess << "Dirs \tscanned\t: " << p.GetNumberScannedDirs()  << "\n";
588     mess << "Files\tscanned\t: " << p.GetNumberScannedFiles() << "\n";
589     mess << "Files\thandled\t: " << p.GetNumberHandledFiles() << "\n\n";
590     mess << "Files\tadded  \t: " << p.GetNumberAddedFiles()   << "\n\n";
591
592     /*    char times[500];
593     sprintf(times,"Time to parse dir \t\t: %ld ms \t%d°/o\nTime to read files info \t: %ld ms \t%d°/o\nTime to update structs \t: %ld ms \t%d°/o\nTime to update database \t: %ld ms \t%d°/o\nTotal time \t\t\t: %ld ms",
594             summary.parse_time,
595             (int)( summary.parse_time*100./summary.total_time),
596             summary.file_scan_time,
597             (int)(summary.file_scan_time*100./summary.total_time),
598             summary.update_structs_time,
599             (int)(summary.update_structs_time*100./summary.total_time),
600             summary.update_database_time,
601             (int)(summary.update_database_time*100./summary.total_time),
602             summary.total_time );
603     
604     mess << times;
605     */
606     wxMessageBox(std2wx(mess.str()),_T("Addition result"),wxOK,this);
607   }
608
609    //=================================================
610
611    //=================================================
612   BEGIN_EVENT_TABLE(WxGimmickView, wxPanel)
613     EVT_TOOL(TOOL_ADDFILES_ID, WxGimmickView::OnAddFiles)
614     EVT_TOOL(TOOL_ADDDIR_ID, WxGimmickView::OnAddDir)
615         EVT_TOOL(TOOL_REMOVE_ID, WxGimmickView::OnRemove)
616   END_EVENT_TABLE()
617   //=================================================
618
619 } // EO namespace creaImageIO
620
621