]> Creatis software - creaImageIO.git/blob - src2/creaImageIOWxGimmickView.cpp
bug correction : no spaces in descriptor files
[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(crea::wx2std(mNotebook->GetPageText(mNotebook->GetSelection())),filenames);
329
330         mProgressDialog->Pulse(_T("Updating view..."));
331
332         UpdateTreeViewLevel(crea::wx2std(mNotebook->GetPageText(mNotebook->GetSelection())),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         std::string name = crea::wx2std(mNotebook->GetCurrentPage()->GetName());
346     long style = wxDD_DEFAULT_STYLE | wxDD_DIR_MUST_EXIST;
347     wxDirDialog* FD = 
348       new wxDirDialog( 0, 
349                        _T("Select directory"),
350                        mCurrentDirectory,
351                        style);
352     
353     if (FD->ShowModal()==wxID_OK)
354       {
355
356         
357                   std::string dirname = wx2std (FD->GetPath());
358                   bool recurse =  isNeedRecursive(dirname);
359                   if (recurse)
360                  {
361              recurse = wxMessageBox(_T("Recurse into sub-directories ?"),  _T("Scan directory"),         wxYES_NO,this ) == wxYES ? true : false;
362                  }
363                 
364                 wxBusyCursor busy;
365                 wxString title(_T("Adding directory"));
366                 if (recurse) 
367                 title = _T("Adding directory (recursive)");
368                 mProgressDialog = 
369                 new wxProgressDialog(_T("Adding directory"),
370                                         _T(""),
371                                         1000,
372                                         this,
373                                         wxPD_ELAPSED_TIME |
374                                         //                             wxPD_ESTIMATED_TIME | 
375                                         //                             wxPD_REMAINING_TIME |
376                                         wxPD_CAN_ABORT );
377                 
378                 mCurrentDirectory = FD->GetPath();  
379                 mGimmick->AddDir(crea::wx2std(mNotebook->GetPageText(mNotebook->GetSelection())),dirname,recurse);
380                 mProgressDialog->Pulse(_T("Updating view..."));
381                 
382                 UpdateTreeViewLevel(crea::wx2std(mNotebook->GetPageText(mNotebook->GetSelection())),1);
383                 delete mProgressDialog;
384                 DisplayAddSummary();
385
386           }
387     mViewer->StartPlayer();
388   }
389
390     //=================================================
391    // Test a directory to know if contains sub-directory to analyze
392   bool WxGimmickView::isNeedRecursive(std::string i_name)
393   {
394       boost::filesystem::directory_iterator iter(i_name), end_iter;
395           bool bfindir = false;
396                   for(; iter != end_iter; ++iter)
397                   {
398                           if(boost::filesystem::is_directory(*iter))
399                           {
400                                   return true;
401                           }
402                   }
403                   return false;
404   }
405   //=================================================
406
407   //=================================================
408   void WxGimmickView::OnSelectionChange(const std::vector<tree::Node*>& sel, bool isSelection, int selection, bool needProcess)
409   {      
410     GimmickDebugMessage(5,
411                         "WxGimmickView::OnSelectionChange"
412                         <<std::endl);
413     wxBusyCursor busy;
414         bool valid=true;
415         
416         if(sel.size()==0)
417         {
418                 
419                 valid= ValidateSelected(NULL,
420                                 mSelectionMinDimension,
421                                 mSelectionMaxDimension );
422         }
423         else if(needProcess)
424         {
425                 ResetExtent();
426                 std::vector<tree::Node*>::const_iterator i;
427                 for(i=sel.begin();i!=sel.end()&&valid;++i)
428                 {
429                         valid= ValidateSelected((*i),
430                                 mSelectionMinDimension,
431                                 mSelectionMaxDimension );
432                 }
433         }
434         else if(isSelection)
435         {
436                 valid= ValidateSelected(sel.front(),
437                                 mSelectionMinDimension,
438                                 mSelectionMaxDimension );
439         }
440         else
441         {
442                 ResetExtent();
443                 std::vector<tree::Node*>::const_iterator i;
444                 for(i=sel.begin();i!=sel.end()&&valid;++i)
445                 {
446                         valid= ValidateSelected((*i),
447                                 mSelectionMinDimension,
448                                 mSelectionMaxDimension );
449                 }
450         }
451         
452     mText->SetLabel(crea::std2wx(GetMessage()));
453     /*if(valid)
454       {
455         ReadImageThreaded(sel);
456       }
457     else
458       {
459                   ClearSelection();
460       }*/
461         ReadImageThreaded(sel);
462
463     
464    }
465
466   //==================================================
467
468   //==================================================
469   ///Reads Images (Threaded)
470   void WxGimmickView::ReadImageThreaded(const std::vector<tree::Node*>& sel)
471   {     
472    GimmickDebugMessage(5,
473                        "ReadImageThreaded"
474                        <<std::endl);
475    int maxprio = GetMaximalPriority();
476    int prio = maxprio + 2000;
477
478    if(sel.size()>0)
479    {
480    //First load the selected images
481    mCurImageItemToShow = sel.front();
482    pointers.clear();
483    int index = 0;
484    std::vector<tree::Node*>::const_iterator selected;
485    for(selected=sel.begin();selected!=sel.end();++selected)
486      {
487        GimmickDebugMessage(5,
488                            "Requesting image from selected "
489                            <<(*selected)->GetAttribute("FullFileName")
490                            <<std::endl);
491            ImagePointerHolder* ph=new ImagePointerHolder(GetDefaultImage());
492            pointers.push_back(ph);
493        RequestReading(*selected,prio,index,ph);
494        //       AddEntryToMap(*selected);
495        prio--;
496        index++;
497      }
498         mViewer->SetImageVector(pointers);
499         //Going up
500         prio = maxprio + 20;
501         std::vector<tree::Node*> up;
502         GetTreeViewMap()["Local database"]->GetNodes(up,true);
503         std::vector<tree::Node*>::iterator iterUp;
504         for(iterUp=up.begin();iterUp!=up.end();++iterUp)
505         {
506                 GimmickDebugMessage(5,
507                                 "Requesting image from neighbors up "
508                                 <<(*iterUp)->GetAttribute("FullFileName")
509                                 <<std::endl);
510                 ImagePointerHolder* ph=new ImagePointerHolder(GetDefaultImage());
511                 RequestReading(*iterUp,prio,-1,ph);
512                 //              AddEntryToMap(*iterUp);
513                 prio--;
514                 if (prio == maxprio) break;
515         }
516
517         //Going down
518         prio = maxprio + 19;
519         std::vector<tree::Node*> down;
520         GetTreeViewMap()["Local database"]->GetNodes(down,false);
521         std::vector<tree::Node*>::iterator iterDown;
522         for(iterDown=down.begin();iterDown!=down.end();++iterDown)
523         {
524                 GimmickDebugMessage(5,
525                                 "Requesting image from neighbors down "
526                                 <<(*iterDown)->GetAttribute("FullFileName")
527                                 <<std::endl);
528                 ImagePointerHolder* ph=new ImagePointerHolder(GetDefaultImage());
529                 RequestReading(*iterDown,prio,-1,ph);
530                 //              AddEntryToMap(*iterDown);
531                 prio--;
532                 if (prio == maxprio) break;
533         }
534    }
535    else
536    {
537            pointers.clear();
538            ImagePointerHolder* ph=new ImagePointerHolder(GetDefaultImage());
539            pointers.push_back(ph);
540            mViewer->SetImageVector(pointers);
541    }
542   }
543
544   //==================================================
545
546   //==================================================
547
548   //==================================================
549    void  WxGimmickView::OnInternalIdle()
550   {
551    if (!mConstructed) return;
552    static bool first_time = true;
553    if (false)
554    {
555         first_time = false;
556      }
557    //   GimmickMessage(1,"WxGimmickView : Refresh viewer"<<std::endl);
558         //  mViewer->StartPlayer();
559    if(mViewer)
560    {
561            mViewer->RefreshIfNecessary();
562    }
563   }
564
565    //==================================================
566
567   //==================================================
568    void  WxGimmickView::ClearSelection()
569   {
570         pointers.clear();
571         pointers.push_back(new ImagePointerHolder(GetDefaultImage()));
572         mViewer->SetImageVector(pointers);
573         mViewer->RefreshIfNecessary();
574         ResetExtent();
575   }
576   
577   //=================================================
578  
579   //=================================================
580   void WxGimmickView::OnRemove(wxCommandEvent& event)
581   {
582         //TODO Select current tree handler       
583     wxBusyCursor busy;
584     GetTreeViewMap()["Local database"]->RemoveSelected();
585
586         ClearSelection();
587   }
588   //=================================================
589
590   //=================================================
591   /// AddProgress Gimmick callback
592   void WxGimmickView::OnAddProgress( Gimmick::AddProgress& p)
593   {
594
595     char mess[200];
596    
597         sprintf(mess,"%i dirs : %i files :\n            %i handled - %i added",
598            p.GetNumberScannedDirs(),
599            p.GetNumberScannedFiles(),
600            p.GetNumberHandledFiles(),
601            p.GetNumberAddedFiles());
602     //    std::cout << "OnAddProgress "<<mess<<std::endl;
603     wxString s(wxString::From8BitData(mess));
604     //  std::cout << "Pulse"<<std::endl;
605     if (!mProgressDialog->Pulse(s)) 
606       {
607         p.SetStop();
608       }
609     //  std::cout << "OnAddProgress ok"<<std::endl;
610   }
611   //=================================================
612
613   //=================================================
614   void WxGimmickView::DisplayAddSummary()
615   {
616     const Gimmick::AddProgress& p = mGimmick->GetAddProgress();
617     std::stringstream mess;
618     mess << "Dirs \tscanned\t: " << p.GetNumberScannedDirs()  << "\n";
619     mess << "Files\tscanned\t: " << p.GetNumberScannedFiles() << "\n";
620     mess << "Files\thandled\t: " << p.GetNumberHandledFiles() << "\n\n";
621     mess << "Files\tadded  \t: " << p.GetNumberAddedFiles()   << "\n\n";
622
623     /*    char times[500];
624     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",
625             summary.parse_time,
626             (int)( summary.parse_time*100./summary.total_time),
627             summary.file_scan_time,
628             (int)(summary.file_scan_time*100./summary.total_time),
629             summary.update_structs_time,
630             (int)(summary.update_structs_time*100./summary.total_time),
631             summary.update_database_time,
632             (int)(summary.update_database_time*100./summary.total_time),
633             summary.total_time );
634     
635     mess << times;
636     */
637     wxMessageBox(std2wx(mess.str()),_T("Addition result"),wxOK,this);
638   }
639
640   //////////////////////////////////////////////////
641   // Add a DB to application                                      //
642   // @param event : WxEvent                                               //
643   // @return : -                                                                  //
644   //////////////////////////////////////////////////
645   void WxGimmickView::OnAddDB(wxCommandEvent& event)
646   {
647     
648           //Select DB
649           long style = wxDD_DEFAULT_STYLE | wxDD_DIR_MUST_EXIST;
650           std::string wc("*.sqlite3*");
651           wxFileDialog* FD = new wxFileDialog( 0, 
652                                          _T("Select file"),
653                                          _T(""),
654                                          _T(""),
655                                          crea::std2wx(wc),
656                                          style,
657                                          wxDefaultPosition);
658     
659     if (FD->ShowModal()==wxID_OK)
660         {
661                 wxBusyCursor busy;
662                 wxArrayString files;
663                 FD->GetPaths(files);
664                 std::stringstream st;
665                 for(int i = 0; i< files.size(); i++)
666                 {
667                         st<< "remote_" << i+1;
668                         //create TreeHandler
669                         mGimmick->addDB(st.str(), crea::wx2std(files[i]));
670                         //create TreeView
671                         CreateSingleTreeView(st.str());
672                 }
673         }
674     
675                 
676   }
677
678    //=================================================
679
680    //=================================================
681   BEGIN_EVENT_TABLE(WxGimmickView, wxPanel)
682     EVT_TOOL(TOOL_ADDFILES_ID, WxGimmickView::OnAddFiles)
683     EVT_TOOL(TOOL_ADDDIR_ID, WxGimmickView::OnAddDir)
684         EVT_TOOL(TOOL_REMOVE_ID, WxGimmickView::OnRemove)
685         EVT_TOOL(TOOL_ADDDATABASE_ID, WxGimmickView::OnAddDB)
686   END_EVENT_TABLE()
687   //=================================================
688
689 } // EO namespace creaImageIO
690
691