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