Commit 07446e4038c30bcac42070bdc2e0541182088e6d

Authored by tatiana
1 parent 208b8ff6

ENH: Project toolbar and task_import buttons and operations / restructured dialogs

invesalius/constants.py
... ... @@ -276,7 +276,7 @@ VTK_WARNING = 0
276 276 #----------------------------------------------------------
277 277  
278 278 [ID_FILE_IMPORT, ID_FILE_LOAD_INTERNET, ID_FILE_SAVE, ID_FILE_PHOTO,
279   -ID_FILE_PRINT] = [wx.NewId() for number in range(5)]
  279 +ID_FILE_PRINT, ID_FILE_OPEN] = [wx.NewId() for number in range(6)]
280 280  
281 281  
282 282  
... ...
invesalius/gui/dialogs.py
... ... @@ -16,10 +16,15 @@
16 16 # PARTICULAR. Consulte a Licenca Publica Geral GNU para obter mais
17 17 # detalhes.
18 18 #--------------------------------------------------------------------------
  19 +import os
  20 +import sys
  21 +
19 22 import wx
20 23 from wx.lib import masked
21 24 import wx.lib.pubsub as ps
22 25  
  26 +import project
  27 +
23 28 class NumberDialog(wx.Dialog):
24 29 def __init__(self, message, value=0):
25 30 pre = wx.PreDialog()
... ... @@ -115,4 +120,74 @@ class ProgressDialog(object):
115 120  
116 121 def Close(self):
117 122 self.dlg.Destroy()
  123 +
  124 +
  125 +
  126 +
  127 +
  128 +
  129 +#---------
  130 +WILDCARD_OPEN = "InVesalius 3 project (*.inv3)|*.inv3|"\
  131 + "All files (*.*)|*.*"
  132 +
  133 +def ShowOpenProjectDialog():
  134 + # Default system path
  135 + if sys.platform == 'win32':
  136 + default_path = ""
  137 + else:
  138 + default_path = os.getcwd()
  139 +
  140 + dlg = wx.FileDialog(None, message="Open InVesalius 3 project...",
  141 + defaultDir=default_path,
  142 + defaultFile="", wildcard=WILDCARD_OPEN,
  143 + style=wx.OPEN|wx.CHANGE_DIR)
  144 +
  145 + # In OSX this filter is not working - wxPython 2.8.10 problem
  146 + if sys.platform != 'darwin':
  147 + dlg.SetFilterIndex(0)
  148 + else:
  149 + dlg.SetFilterIndex(1)
  150 +
  151 + # Show the dialog and retrieve the user response. If it is the OK response,
  152 + # process the data.
  153 + filepath = None
  154 + if dlg.ShowModal() == wx.ID_OK:
  155 + # This returns a Python list of files that were selected.
  156 + filepath = dlg.GetPath()
  157 +
  158 + # Destroy the dialog. Don't do this until you are done with it!
  159 + # BAD things can happen otherwise!
  160 + dlg.Destroy()
  161 + return filepath
  162 +
  163 +def ShowImportDirDialog():
  164 + dlg = wx.DirDialog(None, "Choose a DICOM folder:", "",
  165 + style=wx.DD_DEFAULT_STYLE
  166 + | wx.DD_DIR_MUST_EXIST
  167 + | wx.DD_CHANGE_DIR)
  168 +
  169 + path = None
  170 + if dlg.ShowModal() == wx.ID_OK:
  171 + path = dlg.GetPath()
118 172  
  173 + # Only destroy a dialog after you're done with it.
  174 + dlg.Destroy()
  175 + return path
  176 +
  177 +def ShowSaveAsProjectDialog(default_filename=None):
  178 + dlg = wx.FileDialog(None,
  179 + "Save project as...", # title
  180 + "", # last used directory
  181 + default_filename,
  182 + "InVesalius project (*.inv3)|*.inv3",
  183 + wx.SAVE|wx.OVERWRITE_PROMPT)
  184 + #dlg.SetFilterIndex(0) # default is VTI
  185 +
  186 + filename = None
  187 + if dlg.ShowModal() == wx.ID_OK:
  188 + filename = dlg.GetPath()
  189 + extension = "inv3"
  190 + if sys.platform != 'win32':
  191 + if filename.split(".")[-1] != extension:
  192 + filename = filename + "." + extension
  193 + return filename
... ...
invesalius/gui/frame.py
... ... @@ -28,6 +28,7 @@ import wx.lib.pubsub as ps
28 28 import constants as const
29 29 import default_tasks as tasks
30 30 import default_viewers as viewers
  31 +import gui.dialogs as dlg
31 32 import import_panel as imp
32 33 from project import Project
33 34  
... ... @@ -82,6 +83,15 @@ class Frame(wx.Frame):
82 83 ps.Publisher().subscribe(self.SetProjectName, 'Set project name')
83 84 ps.Publisher().subscribe(self.ShowContentPanel, 'Cancel DICOM load')
84 85 ps.Publisher().subscribe(self.HideImportPanel, 'Hide import panel')
  86 + ps.Publisher().subscribe(self.BeginBusyCursor, 'Begin busy cursor')
  87 + ps.Publisher().subscribe(self.EndBusyCursor, 'End busy cursor')
  88 +
  89 +
  90 + def EndBusyCursor(self, pubsub_evt=None):
  91 + wx.EndBusyCursor()
  92 +
  93 + def BeginBusyCursor(self, pubsub_evt=None):
  94 + wx.BeginBusyCursor()
85 95  
86 96 def SetProjectName(self, pubsub_evt):
87 97 proj_name = pubsub_evt.data
... ... @@ -377,26 +387,15 @@ class ProjectToolBar(wx.ToolBar):
377 387  
378 388 def __init_items(self):
379 389  
380   -
381   - BMP_IMPORT = wx.Bitmap(os.path.join(const.ICON_DIR, "file_import.png"),
382   - wx.BITMAP_TYPE_PNG)
383   - BMP_NET = wx.Bitmap(os.path.join(const.ICON_DIR,
384   - "file_from_internet.png"),
385   - wx.BITMAP_TYPE_PNG)
386   - BMP_SAVE = wx.Bitmap(os.path.join(const.ICON_DIR, "file_save.png"),
387   - wx.BITMAP_TYPE_PNG)
388   - BMP_PRINT = wx.Bitmap(os.path.join(const.ICON_DIR, "print.png"),
389   - wx.BITMAP_TYPE_PNG)
390   - BMP_PHOTO = wx.Bitmap(os.path.join(const.ICON_DIR, "tool_photo.png"),
391   - wx.BITMAP_TYPE_PNG)
392   -
393 390 if sys.platform == 'darwin':
394   - BMP_IMPORT = wx.Bitmap(os.path.join(const.ICON_DIR,
395   - "file_import_original.png"),
396   - wx.BITMAP_TYPE_PNG)
397 391 BMP_NET = wx.Bitmap(os.path.join(const.ICON_DIR,
398 392 "file_from_internet_original.png"),
399 393 wx.BITMAP_TYPE_PNG)
  394 + BMP_IMPORT = wx.Bitmap(os.path.join(const.ICON_DIR,
  395 + "file_import_original.png"),
  396 + wx.BITMAP_TYPE_PNG)
  397 + BMP_OPEN = wx.Bitmap(os.path.join(const.ICON_DIR,"file_open_original.png"),
  398 + wx.BITMAP_TYPE_PNG)
400 399 BMP_SAVE = wx.Bitmap(os.path.join(const.ICON_DIR,
401 400 "file_save_original.png"),
402 401 wx.BITMAP_TYPE_PNG)
... ... @@ -407,25 +406,28 @@ class ProjectToolBar(wx.ToolBar):
407 406 "tool_photo_original.png"),
408 407 wx.BITMAP_TYPE_PNG)
409 408 else:
410   - BMP_IMPORT = wx.Bitmap(os.path.join(const.ICON_DIR,
411   - "file_import.png"),
412   - wx.BITMAP_TYPE_PNG)
413   - BMP_NET = wx.Bitmap(os.path.join(const.ICON_DIR,
414   - "file_from_internet.png"),
  409 + BMP_NET = wx.Bitmap(os.path.join(const.ICON_DIR,"file_from_internet.png"),
415 410 wx.BITMAP_TYPE_PNG)
  411 + BMP_IMPORT = wx.Bitmap(os.path.join(const.ICON_DIR, "file_import.png"),
  412 + wx.BITMAP_TYPE_PNG)
  413 + BMP_OPEN = wx.Bitmap(os.path.join(const.ICON_DIR,"file_open.png"),
  414 + wx.BITMAP_TYPE_PNG)
416 415 BMP_SAVE = wx.Bitmap(os.path.join(const.ICON_DIR, "file_save.png"),
417   - wx.BITMAP_TYPE_PNG)
  416 + wx.BITMAP_TYPE_PNG)
418 417 BMP_PRINT = wx.Bitmap(os.path.join(const.ICON_DIR, "print.png"),
419 418 wx.BITMAP_TYPE_PNG)
420 419 BMP_PHOTO = wx.Bitmap(os.path.join(const.ICON_DIR, "tool_photo.png"),
421   - wx.BITMAP_TYPE_PNG)
  420 + wx.BITMAP_TYPE_PNG)
422 421  
423   - self.AddLabelTool(const.ID_FILE_IMPORT,
424   - "Import medical image...",
425   - BMP_IMPORT)
426 422 self.AddLabelTool(const.ID_FILE_LOAD_INTERNET,
427 423 "Load medical image...",
428 424 BMP_NET)
  425 + self.AddLabelTool(const.ID_FILE_IMPORT,
  426 + "Import medical image...",
  427 + BMP_IMPORT)
  428 + self.AddLabelTool(const.ID_FILE_OPEN,
  429 + "Open InVesalius 3 project...",
  430 + BMP_OPEN)
429 431 self.AddLabelTool(const.ID_FILE_SAVE,
430 432 "Save InVesalius project",
431 433 BMP_SAVE)
... ... @@ -440,32 +442,36 @@ class ProjectToolBar(wx.ToolBar):
440 442  
441 443 def __bind_events(self):
442 444 self.Bind(wx.EVT_TOOL, self.OnToolSave, id=const.ID_FILE_SAVE)
  445 + self.Bind(wx.EVT_TOOL, self.OnToolOpen, id=const.ID_FILE_OPEN)
  446 + self.Bind(wx.EVT_TOOL, self.OnToolImport, id=const.ID_FILE_IMPORT)
443 447  
444   - def OnToolSave(self, evt):
445   - filename = None
446   - project_name = (Project().name).replace(' ','_')
447   -
  448 + def OnToolImport(self, event):
  449 + dirpath = dlg.ShowImportDirDialog()
  450 + if dirpath:
  451 + ps.Publisher().sendMessage("Load data to import panel", path)
  452 + event.Skip()
  453 +
  454 + def OnToolOpen(self, event):
  455 + filepath = dlg.ShowOpenProjectDialog()
  456 + if filepath:
  457 + ps.Publisher().sendMessage('Open Project', filepath)
  458 + event.Skip()
  459 +
  460 + def OnToolSave(self, event):
  461 + filename = (Project().name).replace(' ','_')
448 462 if Project().save_as:
449   - dlg = wx.FileDialog(None,
450   - "Save InVesalius project as...", # title
451   - "", # last used directory
452   - project_name, # filename
453   - "InVesalius project (*.inv3)|*.inv3",
454   - wx.SAVE|wx.OVERWRITE_PROMPT)
455   - dlg.SetFilterIndex(0) # default is VTI
456   -
457   - if dlg.ShowModal() == wx.ID_OK:
458   - filename = dlg.GetPath()
459   - print "filename", filename
460   - extension = "inv3"
461   - if sys.platform != 'win32':
462   - if filename.split(".")[-1] != extension:
463   - filename = filename + "."+ extension
464   -
465   - Project().save_as = False
466   -
  463 + filename = dlg.ShowSaveAsProjectDialog(filename)
  464 + if filename:
  465 + Project().save_as = False
  466 + else:
  467 + return
467 468 ps.Publisher().sendMessage('Save Project',filename)
468   -# ------------------------------------------------------------------
  469 + event.Skip()
  470 +
  471 +
  472 +
  473 +
  474 + # ------------------------------------------------------------------
469 475  
470 476 class ObjectToolBar(wx.ToolBar):
471 477 def __init__(self, parent):
... ... @@ -593,11 +599,14 @@ class SliceToolBar(wx.ToolBar):
593 599 BMP_SLICE = wx.Bitmap(os.path.join(const.ICON_DIR,
594 600 "slice_original.png"),
595 601 wx.BITMAP_TYPE_PNG)
  602 +
  603 + BMP_CROSS = wx.Bitmap(os.path.join(const.ICON_DIR,"cross_original.png"),
  604 + wx.BITMAP_TYPE_PNG)
596 605 else:
597 606 BMP_SLICE = wx.Bitmap(os.path.join(const.ICON_DIR, "slice.png"),
598 607 wx.BITMAP_TYPE_PNG)
599 608  
600   - BMP_CROSS = wx.Bitmap(os.path.join(const.ICON_DIR, "cross.png"),
  609 + BMP_CROSS = wx.Bitmap(os.path.join(const.ICON_DIR, "cross.png"),
601 610 wx.BITMAP_TYPE_PNG)
602 611  
603 612 self.AddLabelTool(ID_SLICE_SCROLL, "Scroll slice",
... ...
invesalius/gui/task_importer.py
... ... @@ -25,15 +25,13 @@ import wx.lib.platebtn as pbtn
25 25 import wx.lib.pubsub as ps
26 26  
27 27 import constants as const
  28 +import gui.dialogs as dlg
28 29  
29 30 BTN_IMPORT_LOCAL = wx.NewId()
30 31 BTN_IMPORT_PACS = wx.NewId()
31 32 BTN_OPEN_PROJECT = wx.NewId()
32 33  
33   -WILDCARD_OPEN = "InVesalius 1 project (*.promed)|*.promed|"\
34   - "InVesalius 2 project (*.inv)|*.inv|"\
35   - "InVesalius 3 project (*.inv3)|*.inv3|"\
36   - "All files (*.*)|*.*"
  34 +
37 35  
38 36 class TaskPanel(wx.Panel):
39 37 def __init__(self, parent):
... ... @@ -93,9 +91,9 @@ class InnerTaskPanel(wx.Panel):
93 91 # Image(s) for buttons
94 92 BMP_IMPORT = wx.Bitmap("../icons/file_import.png", wx.BITMAP_TYPE_PNG)
95 93 BMP_NET = wx.Bitmap("../icons/file_from_internet.png", wx.BITMAP_TYPE_PNG)
96   - BMP_NULL = wx.Bitmap("../icons/object_invisible.jpg", wx.BITMAP_TYPE_JPEG)
  94 + BMP_OPEN_PROJECT = wx.Bitmap("../icons/file_open.png", wx.BITMAP_TYPE_PNG)
97 95  
98   - bmp_list = [BMP_IMPORT, BMP_NET, BMP_NULL]
  96 + bmp_list = [BMP_IMPORT, BMP_NET, BMP_OPEN_PROJECT]
99 97 for bmp in bmp_list:
100 98 bmp.SetWidth(25)
101 99 bmp.SetHeight(25)
... ... @@ -103,12 +101,12 @@ class InnerTaskPanel(wx.Panel):
103 101 # Buttons related to hyperlinks
104 102 button_style = pbtn.PB_STYLE_SQUARE | pbtn.PB_STYLE_DEFAULT
105 103  
106   - button_import_local = pbtn.PlateButton(self, BTN_IMPORT_LOCAL, "",
107   - BMP_IMPORT, style=button_style)
108 104 button_import_pacs = pbtn.PlateButton(self, BTN_IMPORT_PACS, "", BMP_NET,
109 105 style=button_style)
  106 + button_import_local = pbtn.PlateButton(self, BTN_IMPORT_LOCAL, "",
  107 + BMP_IMPORT, style=button_style)
110 108 button_open_proj = pbtn.PlateButton(self, BTN_OPEN_PROJECT, "",
111   - BMP_NULL, style=button_style)
  109 + BMP_OPEN_PROJECT, style=button_style)
112 110  
113 111 # When using PlaneButton, it is necessary to bind events from parent win
114 112 self.Bind(wx.EVT_BUTTON, self.OnButton)
... ... @@ -119,10 +117,10 @@ class InnerTaskPanel(wx.Panel):
119 117  
120 118 fixed_sizer = wx.FlexGridSizer(rows=3, cols=2, hgap=2, vgap=0)
121 119 fixed_sizer.AddGrowableCol(0, 1)
122   - fixed_sizer.AddMany([ (link_import_local, 1, flag_link, 3),
123   - (button_import_local, 0, flag_button),
124   - (link_import_pacs, 1, flag_link, 3),
  120 + fixed_sizer.AddMany([ (link_import_pacs, 1, flag_link, 3),
125 121 (button_import_pacs, 0, flag_button),
  122 + (link_import_local, 1, flag_link, 3),
  123 + (button_import_local, 0, flag_button),
126 124 (link_open_proj, 1, flag_link, 3),
127 125 (button_open_proj, 0, flag_button) ])
128 126  
... ... @@ -137,76 +135,44 @@ class InnerTaskPanel(wx.Panel):
137 135  
138 136 # Test load and unload specific projects' links
139 137 self.TestLoadProjects()
140   - #self.UnloadProjects()
141   - ps.Publisher().subscribe(self.OnLinkImport,("Run menu item",
142   - str(const.ID_FILE_IMPORT)))
143   -
144   - def OnLinkImport(self, evt=None):
145   - dlg = wx.DirDialog(self, "Choose a directory:", "",
146   - style=wx.DD_DEFAULT_STYLE
147   - | wx.DD_DIR_MUST_EXIST
148   - | wx.DD_CHANGE_DIR)
149   -
150   - if dlg.ShowModal() == wx.ID_OK:
151   - path = dlg.GetPath()
152   - ps.Publisher().sendMessage("Load data to import panel", path)
153   -
154   - # Only destroy a dialog after you're done with it.
155   - dlg.Destroy()
156   -
157   - try:
158   - if evt:
159   - evt.Skip()
160   - except(AttributeError):
161   - pass
162   -
163   - def OnLinkImportPACS(self, evt=None):
  138 +
  139 + def OnLinkImport(self, event):
  140 + self.LinkImport()
  141 + event.Skip()
  142 +
  143 + def OnLinkImportPACS(self, event):
  144 + self.LinkImportPACS()
  145 + event.Skip()
  146 +
  147 + def OnLinkOpenProject(self, event):
  148 + self.LinkOpenProject()
  149 + event.Skip()
  150 +
  151 + def LinkImport(self):
  152 + dirpath = dlg.ShowImportDirDialog()
  153 + if dirpath:
  154 + ps.Publisher().sendMessage("Load data to import panel", dirpath)
  155 +
  156 + def LinkImportPACS(self):
164 157 print "TODO: Send Signal - Import DICOM files from PACS"
165   - if evt:
166   - evt.Skip()
167 158  
168   - def OnLinkOpenProject(self, evt=None, proj_name=""):
169   - if proj_name:
170   - print "TODO: Send Signal - Open project "+ proj_name
  159 + def LinkOpenProject(self, filename=None):
  160 + if filename:
  161 + print "TODO: Send Signal - Open inv3 last project"
171 162 else:
172   - if sys.platform == 'win32':
173   - path = ""
174   - else:
175   - path = os.getcwd()
176   - dlg = wx.FileDialog(self, message="Open project...",
177   - defaultDir=path,
178   - defaultFile="", wildcard=WILDCARD_OPEN,
179   - style=wx.OPEN|wx.CHANGE_DIR)
180   - if sys.platform != 'darwin':
181   - dlg.SetFilterIndex(2)
182   - else:
183   - dlg.SetFilterIndex(3)
184   -
185   - # Show the dialog and retrieve the user response. If it is the OK response,
186   - # process the data.
187   - if dlg.ShowModal() == wx.ID_OK:
188   - # This returns a Python list of files that were selected.
189   - proj_path = dlg.GetPath()
190   - proj_name = dlg.GetFilename()
191   - ps.Publisher().sendMessage('Open Project', proj_path)
192   - print "TODO: Send Signal - Change frame title "+ proj_name
193   -
194   - # Destroy the dialog. Don't do this until you are done with it!
195   - # BAD things can happen otherwise!
196   - dlg.Destroy()
197   -
198   - if evt:
199   - evt.Skip()
  163 + filepath = dlg.ShowOpenProjectDialog()
  164 + if filepath:
  165 + ps.Publisher().sendMessage('Open Project', filepath)
200 166  
201 167 def OnButton(self, evt):
202 168 id = evt.GetId()
203 169  
204 170 if id == BTN_IMPORT_LOCAL:
205   - self.OnLinkImport()
  171 + self.LinkImport()
206 172 elif id == BTN_IMPORT_PACS:
207   - self.OnLinkImportPACS()
  173 + self.LinkImportPACS()
208 174 else: #elif id == BTN_OPEN_PROJECT:
209   - self.OnLinkOpenProject()
  175 + self.LinkOpenProject()
210 176  
211 177 def TestLoadProjects(self):
212 178 self.LoadProject("test1.inv3")
... ... @@ -235,7 +201,7 @@ class InnerTaskPanel(wx.Panel):
235 201 proj_link.AutoBrowse(False)
236 202 proj_link.UpdateLink()
237 203 proj_link.Bind(hl.EVT_HYPERLINK_LEFT,
238   - lambda e: self.OnLinkOpenProject(e, proj_name))
  204 + lambda e: self.LinkOpenProject(proj_name))
239 205  
240 206 # Add to existing frame
241 207 self.sizer.Add(proj_link, 1, wx.GROW | wx.EXPAND | wx.ALL, 2)
... ...