Commit 83ca712cfef3e4954e22f4402ee9ac6d8c388b9b

Authored by Paulo Henrique Junqueira Amorim
1 parent ef930662

ENH: Display save dialog in the close project not saved

invesalius/control.py
@@ -154,27 +154,42 @@ class Controller(): @@ -154,27 +154,42 @@ class Controller():
154 st = session.project_status 154 st = session.project_status
155 if st == const.PROJ_CLOSE: 155 if st == const.PROJ_CLOSE:
156 return -1 156 return -1
157 - filename = session.project_path[1]  
158 - if (st == const.PROJ_NEW) or (st == const.PROJ_CHANGE):  
159 - answer = dialog.SaveChangesDialog(filename)  
160 - if not answer:  
161 - debug("Close without changes")  
162 - self.CloseProject()  
163 - ps.Publisher().sendMessage("Enable state project", False)  
164 - ps.Publisher().sendMessage('Set project name')  
165 - elif answer == 1:  
166 - self.ShowDialogSaveProject()  
167 - debug("Save changes and close") 157 + try:
  158 + filename = session.project_path[1]
  159 + except(AttributeError):
  160 + print "Not exist project"
  161 + filename = None
  162 +
  163 + if (filename):
  164 + if (st == const.PROJ_NEW) or (st == const.PROJ_CHANGE):
  165 + answer = dialog.SaveChangesDialog(filename, self.frame)
  166 +
  167 + if not answer:
  168 + debug("Close without changes")
  169 + self.CloseProject()
  170 + ps.Publisher().sendMessage("Enable state project", False)
  171 + ps.Publisher().sendMessage('Set project name')
  172 + ps.Publisher().sendMessage('Close Window')
  173 + elif answer == 1:
  174 + self.ShowDialogSaveProject()
  175 + debug("Save changes and close")
  176 + self.CloseProject()
  177 + ps.Publisher().sendMessage("Enable state project", False)
  178 + ps.Publisher().sendMessage('Set project name')
  179 + ps.Publisher().sendMessage('Close Window')
  180 + elif answer == -1:
  181 + debug("Cancel")
  182 + else:
168 self.CloseProject() 183 self.CloseProject()
169 ps.Publisher().sendMessage("Enable state project", False) 184 ps.Publisher().sendMessage("Enable state project", False)
170 ps.Publisher().sendMessage('Set project name') 185 ps.Publisher().sendMessage('Set project name')
171 - elif answer == -1:  
172 - debug("Cancel") 186 + ps.Publisher().sendMessage('Close Window')
  187 +
173 else: 188 else:
174 - self.CloseProject()  
175 - ps.Publisher().sendMessage("Enable state project", False)  
176 - ps.Publisher().sendMessage('Set project name')  
177 - 189 + ps.Publisher().sendMessage('Stop Config Recording')
  190 + ps.Publisher().sendMessage('Close Window')
  191 +
  192 +
178 ########################### 193 ###########################
179 def OnOpenProject(self, pubsub_evt): 194 def OnOpenProject(self, pubsub_evt):
180 path = pubsub_evt.data 195 path = pubsub_evt.data
@@ -212,7 +227,7 @@ class Controller(): @@ -212,7 +227,7 @@ class Controller():
212 227
213 surface = srf.Surface() 228 surface = srf.Surface()
214 surface._set_class_index(proj.last_surface_index) 229 surface._set_class_index(proj.last_surface_index)
215 - 230 +
216 self.LoadProject() 231 self.LoadProject()
217 232
218 session = ses.Session() 233 session = ses.Session()
@@ -233,7 +248,7 @@ class Controller(): @@ -233,7 +248,7 @@ class Controller():
233 248
234 session.SaveProject() 249 session.SaveProject()
235 ps.Publisher().sendMessage('End busy cursor') 250 ps.Publisher().sendMessage('End busy cursor')
236 - 251 +
237 def CloseProject(self): 252 def CloseProject(self):
238 proj = prj.Project() 253 proj = prj.Project()
239 proj.Close() 254 proj.Close()
@@ -320,7 +335,7 @@ class Controller(): @@ -320,7 +335,7 @@ class Controller():
320 335
321 const.THRESHOLD_OUTVALUE = proj.threshold_range[0] 336 const.THRESHOLD_OUTVALUE = proj.threshold_range[0]
322 const.THRESHOLD_INVALUE = proj.threshold_range[1] 337 const.THRESHOLD_INVALUE = proj.threshold_range[1]
323 - 338 +
324 const.WINDOW_LEVEL[_('Default')] = (proj.window, proj.level) 339 const.WINDOW_LEVEL[_('Default')] = (proj.window, proj.level)
325 const.WINDOW_LEVEL[_('Manual')] = (proj.window, proj.level) 340 const.WINDOW_LEVEL[_('Manual')] = (proj.window, proj.level)
326 341
@@ -404,9 +419,9 @@ class Controller(): @@ -404,9 +419,9 @@ class Controller():
404 if not filelist: 419 if not filelist:
405 debug("Not used the IPPSorter") 420 debug("Not used the IPPSorter")
406 filelist = [i.image.file for i in dicom_group.GetHandSortedList()[::interval]] 421 filelist = [i.image.file for i in dicom_group.GetHandSortedList()[::interval]]
407 -  
408 -  
409 - 422 +
  423 +
  424 +
410 zspacing = dicom_group.zspacing * interval 425 zspacing = dicom_group.zspacing * interval
411 size = dicom.image.size 426 size = dicom.image.size
412 bits = dicom.image.bits_allocad 427 bits = dicom.image.bits_allocad
invesalius/gui/dialogs.py
@@ -30,7 +30,6 @@ import project as proj @@ -30,7 +30,6 @@ import project as proj
30 import session as ses 30 import session as ses
31 import utils 31 import utils
32 32
33 -  
34 class NumberDialog(wx.Dialog): 33 class NumberDialog(wx.Dialog):
35 def __init__(self, message, value=0): 34 def __init__(self, message, value=0):
36 pre = wx.PreDialog() 35 pre = wx.PreDialog()
@@ -341,7 +340,7 @@ def NewMask(): @@ -341,7 +340,7 @@ def NewMask():
341 import data.mask as mask 340 import data.mask as mask
342 dlg = wx.TextEntryDialog(None, _('Name of new mask:'), 341 dlg = wx.TextEntryDialog(None, _('Name of new mask:'),
343 _('InVesalius 3 - New mask')) 342 _('InVesalius 3 - New mask'))
344 - 343 +
345 dlg.CenterOnScreen() 344 dlg.CenterOnScreen()
346 default_mask_name = const.MASK_NAME_PATTERN %(mask.Mask.general_index+2) 345 default_mask_name = const.MASK_NAME_PATTERN %(mask.Mask.general_index+2)
347 dlg.SetValue(default_mask_name) 346 dlg.SetValue(default_mask_name)
@@ -367,20 +366,19 @@ def InexistentPath(path): @@ -367,20 +366,19 @@ def InexistentPath(path):
367 dlg.ShowModal() 366 dlg.ShowModal()
368 dlg.Destroy() 367 dlg.Destroy()
369 368
370 -def SaveChangesDialog(filename): 369 +def SaveChangesDialog(filename, parent):
371 current_dir = os.path.abspath(".") 370 current_dir = os.path.abspath(".")
372 msg = _("The project %s has been modified.\nSave changes?")%filename 371 msg = _("The project %s has been modified.\nSave changes?")%filename
373 if sys.platform == 'darwin': 372 if sys.platform == 'darwin':
374 dlg = wx.MessageDialog(None, "", msg, 373 dlg = wx.MessageDialog(None, "", msg,
375 wx.ICON_QUESTION | wx.YES_NO | wx.CANCEL) 374 wx.ICON_QUESTION | wx.YES_NO | wx.CANCEL)
376 else: 375 else:
377 - dlg = wx.MessageDialog(None, msg,  
378 - "InVesalius 3",  
379 - wx.ICON_QUESTION | wx.YES_NO | wx.CANCEL) 376 + dlg = wx.MessageDialog(None, "TESTETSTE", "InVesalius 3",
  377 + wx.ICON_QUESTION | wx.YES_NO | wx.CANCEL)
380 try: 378 try:
381 answer = dlg.ShowModal() 379 answer = dlg.ShowModal()
382 - except(wx._core.PyAssertionError):  
383 - answer = dlg.GetReturnCode() 380 + except(wx._core.PyAssertionError): #TODO: FIX win64
  381 + answer = wx.ID_YES
384 382
385 dlg.Destroy() 383 dlg.Destroy()
386 os.chdir(current_dir) 384 os.chdir(current_dir)
@@ -621,4 +619,3 @@ def ExportPicture(type_=""): @@ -621,4 +619,3 @@ def ExportPicture(type_=""):
621 return () 619 return ()
622 620
623 621
624 -  
invesalius/gui/frame.py
@@ -91,9 +91,10 @@ class Frame(wx.Frame): @@ -91,9 +91,10 @@ class Frame(wx.Frame):
91 ps.Publisher().subscribe(self.BeginBusyCursor, 'Begin busy cursor') 91 ps.Publisher().subscribe(self.BeginBusyCursor, 'Begin busy cursor')
92 ps.Publisher().subscribe(self.EndBusyCursor, 'End busy cursor') 92 ps.Publisher().subscribe(self.EndBusyCursor, 'End busy cursor')
93 ps.Publisher().subscribe(self.HideContentPanel, 'Hide content panel') 93 ps.Publisher().subscribe(self.HideContentPanel, 'Hide content panel')
  94 + ps.Publisher().subscribe(self.CloseProgram, 'Close Window')
94 95
95 def EndBusyCursor(self, pubsub_evt=None): 96 def EndBusyCursor(self, pubsub_evt=None):
96 - try: 97 + try:
97 wx.EndBusyCursor() 98 wx.EndBusyCursor()
98 except wx._core.PyAssertionError: 99 except wx._core.PyAssertionError:
99 #xEndBusyCursor(): no matching wxBeginBusyCursor() for wxEndBusyCursor() 100 #xEndBusyCursor(): no matching wxBeginBusyCursor() for wxEndBusyCursor()
@@ -104,7 +105,7 @@ class Frame(wx.Frame): @@ -104,7 +105,7 @@ class Frame(wx.Frame):
104 105
105 def SetProjectName(self, pubsub_evt): 106 def SetProjectName(self, pubsub_evt):
106 proj_name = pubsub_evt.data 107 proj_name = pubsub_evt.data
107 - 108 +
108 if not(proj_name): 109 if not(proj_name):
109 self.SetTitle("InVesalius 3") 110 self.SetTitle("InVesalius 3")
110 else: 111 else:
@@ -123,6 +124,7 @@ class Frame(wx.Frame): @@ -123,6 +124,7 @@ class Frame(wx.Frame):
123 #self.Bind(wx.EVT_CLOSE, self.OnExit) 124 #self.Bind(wx.EVT_CLOSE, self.OnExit)
124 125
125 def CloseWindow(self, evt): 126 def CloseWindow(self, evt):
  127 + ps.Publisher().sendMessage('Close Project')
126 ps.Publisher().sendMessage("Stop Config Recording") 128 ps.Publisher().sendMessage("Stop Config Recording")
127 self.Destroy() 129 self.Destroy()
128 130
@@ -248,8 +250,8 @@ class Frame(wx.Frame): @@ -248,8 +250,8 @@ class Frame(wx.Frame):
248 self.SaveAsProject() 250 self.SaveAsProject()
249 elif id == const.ID_PROJECT_CLOSE: 251 elif id == const.ID_PROJECT_CLOSE:
250 self.CloseProject() 252 self.CloseProject()
251 - #elif id == const.ID_EXIT:  
252 - # self.OnExit(evt) 253 + elif id == const.ID_EXIT:
  254 + self.OnExit()
253 elif id == const.ID_ABOUT: 255 elif id == const.ID_ABOUT:
254 self.ShowAbout() 256 self.ShowAbout()
255 elif id == const.ID_START: 257 elif id == const.ID_START:
@@ -286,9 +288,11 @@ class Frame(wx.Frame): @@ -286,9 +288,11 @@ class Frame(wx.Frame):
286 utils.debug("CloseProject") 288 utils.debug("CloseProject")
287 ps.Publisher().sendMessage('Close Project') 289 ps.Publisher().sendMessage('Close Project')
288 290
289 - def OnExit(self, event):  
290 - self.Exit()  
291 - event.Skip() 291 + def OnExit(self):
  292 + ps.Publisher().sendMessage('Close Project')
  293 +
  294 + def CloseProgram(self, pubsub_evt):
  295 + self.Destroy()
292 296
293 def Exit(self): 297 def Exit(self):
294 utils.debug("Exit") 298 utils.debug("Exit")
@@ -303,8 +307,8 @@ class Frame(wx.Frame): @@ -303,8 +307,8 @@ class Frame(wx.Frame):
303 self.aui_manager.Update() 307 self.aui_manager.Update()
304 308
305 #def OnClose(self): 309 #def OnClose(self):
306 - # # TODO: implement this, based on wx.Demo  
307 - # pass 310 + # TODO: implement this, based on wx.Demo
  311 + #pass
308 # ------------------------------------------------------------------------------ 312 # ------------------------------------------------------------------------------
309 # TODO: what will appear on ivMenuBar? 313 # TODO: what will appear on ivMenuBar?
310 # Menu items ID's, necessary to bind events on them 314 # Menu items ID's, necessary to bind events on them
@@ -417,7 +421,7 @@ class MenuBar(wx.MenuBar): @@ -417,7 +421,7 @@ class MenuBar(wx.MenuBar):
417 421
418 def SetStateProjectClose(self): 422 def SetStateProjectClose(self):
419 for item in self.enable_items: 423 for item in self.enable_items:
420 - self.Enable(item, False) 424 + self.Enable(item, False)
421 425
422 def __bind_events(self): 426 def __bind_events(self):
423 # TODO: in future, possibly when wxPython 2.9 is available, 427 # TODO: in future, possibly when wxPython 2.9 is available,
@@ -594,7 +598,7 @@ class ProjectToolBar(wx.ToolBar): @@ -594,7 +598,7 @@ class ProjectToolBar(wx.ToolBar):
594 598
595 def SetStateProjectClose(self): 599 def SetStateProjectClose(self):
596 for tool in self.enable_items: 600 for tool in self.enable_items:
597 - self.EnableTool(tool, False) 601 + self.EnableTool(tool, False)
598 602
599 def OnEnableState(self, pubsub_evt): 603 def OnEnableState(self, pubsub_evt):
600 state = pubsub_evt.data 604 state = pubsub_evt.data
@@ -730,7 +734,7 @@ class ObjectToolBar(wx.ToolBar): @@ -730,7 +734,7 @@ class ObjectToolBar(wx.ToolBar):
730 def SetStateProjectClose(self): 734 def SetStateProjectClose(self):
731 for tool in self.enable_items: 735 for tool in self.enable_items:
732 self.EnableTool(tool, False) 736 self.EnableTool(tool, False)
733 - self.UntoggleAllItems() 737 + self.UntoggleAllItems()
734 738
735 739
736 def __bind_events_wx(self): 740 def __bind_events_wx(self):
@@ -809,8 +813,8 @@ class SliceToolBar(wx.ToolBar): @@ -809,8 +813,8 @@ class SliceToolBar(wx.ToolBar):
809 813
810 def SetStateProjectClose(self): 814 def SetStateProjectClose(self):
811 for tool in self.enable_items: 815 for tool in self.enable_items:
812 - self.EnableTool(tool, False)  
813 - 816 + self.EnableTool(tool, False)
  817 +
814 def __bind_events_wx(self): 818 def __bind_events_wx(self):
815 self.Bind(wx.EVT_TOOL, self.OnClick) 819 self.Bind(wx.EVT_TOOL, self.OnClick)
816 820
@@ -916,7 +920,7 @@ shortHelp= _("Hide task panel")) @@ -916,7 +920,7 @@ shortHelp= _("Hide task panel"))
916 self.ontool_text = True 920 self.ontool_text = True
917 self.OnText() 921 self.OnText()
918 for tool in self.enable_items: 922 for tool in self.enable_items:
919 - self.EnableTool(tool, False) 923 + self.EnableTool(tool, False)
920 924
921 def __bind_events(self): 925 def __bind_events(self):
922 ps.Publisher().subscribe(self.SetLayoutButtonOnlyData, 926 ps.Publisher().subscribe(self.SetLayoutButtonOnlyData,
invesalius/gui/widgets/platebtn.py
@@ -11,9 +11,9 @@ @@ -11,9 +11,9 @@
11 Editra Control Library: PlateButton 11 Editra Control Library: PlateButton
12 12
13 The PlateButton is a custom owner drawn flat button, that in many ways emulates 13 The PlateButton is a custom owner drawn flat button, that in many ways emulates
14 -the buttons found the bookmark bar of the Safari browser. It can be used as a  
15 -drop in replacement for wx.Button/wx.BitmapButton under most circumstances. It  
16 -also offers a wide range of options for customizing its appearance, a 14 +the buttons found the bookmark bar of the Safari browser. It can be used as a
  15 +drop in replacement for wx.Button/wx.BitmapButton under most circumstances. It
  16 +also offers a wide range of options for customizing its appearance, a
17 description of each of the main style settings is listed below. 17 description of each of the main style settings is listed below.
18 18
19 Main Button Styles: 19 Main Button Styles:
@@ -77,7 +77,7 @@ __svnid__ = "$Id: platebtn.py 57713 2009-01-01 23:36:15Z CJP $" @@ -77,7 +77,7 @@ __svnid__ = "$Id: platebtn.py 57713 2009-01-01 23:36:15Z CJP $"
77 __revision__ = "$Revision: 57713 $" 77 __revision__ = "$Revision: 57713 $"
78 78
79 __all__ = ["PlateButton", "AdjustAlpha", "AdjustColor", "GetHighlightColor", 79 __all__ = ["PlateButton", "AdjustAlpha", "AdjustColor", "GetHighlightColor",
80 - "PLATE_NORMAL", "PLATE_PRESSED", "PLATE_HIGHLIGHT", 80 + "PLATE_NORMAL", "PLATE_PRESSED", "PLATE_HIGHLIGHT",
81 "PB_STYLE_DEFAULT", "PB_STYLE_GRADIENT", "PB_STYLE_SQUARE", 81 "PB_STYLE_DEFAULT", "PB_STYLE_GRADIENT", "PB_STYLE_SQUARE",
82 "PB_STYLE_NOBG", "PB_STYLE_DROPARROW", 82 "PB_STYLE_NOBG", "PB_STYLE_DROPARROW",
83 "EVT_PLATEBTN_DROPARROW_PRESSED"] 83 "EVT_PLATEBTN_DROPARROW_PRESSED"]
@@ -120,7 +120,7 @@ class PlateButton(wx.PyControl): @@ -120,7 +120,7 @@ class PlateButton(wx.PyControl):
120 displaying bitmaps and having an attached dropdown menu. 120 displaying bitmaps and having an attached dropdown menu.
121 121
122 """ 122 """
123 - def __init__(self, parent, id_=wx.ID_ANY, label='', bmp=None, 123 + def __init__(self, parent, id_=wx.ID_ANY, label='', bmp=None,
124 pos=wx.DefaultPosition, size=wx.DefaultSize, 124 pos=wx.DefaultPosition, size=wx.DefaultSize,
125 style=PB_STYLE_DEFAULT, name=wx.ButtonNameStr): 125 style=PB_STYLE_DEFAULT, name=wx.ButtonNameStr):
126 """Create a PlateButton 126 """Create a PlateButton
@@ -314,14 +314,14 @@ class PlateButton(wx.PyControl): @@ -314,14 +314,14 @@ class PlateButton(wx.PyControl):
314 color = GetHighlightColour() 314 color = GetHighlightColour()
315 pcolor = AdjustColour(color, -12) 315 pcolor = AdjustColour(color, -12)
316 colors = dict(default=True, 316 colors = dict(default=True,
317 - hlight=color, 317 + hlight=color,
318 press=pcolor, 318 press=pcolor,
319 htxt=BestLabelColour(self.GetForegroundColour())) 319 htxt=BestLabelColour(self.GetForegroundColour()))
320 return colors 320 return colors
321 321
322 def __LeaveWindow(self): 322 def __LeaveWindow(self):
323 if (self._style & PB_STYLE_TOGGLE) and self._pressed: 323 if (self._style & PB_STYLE_TOGGLE) and self._pressed:
324 - self.SetState(PLATE_PRESSED) 324 + self.SetState(PLATE_PRESSED)
325 else: 325 else:
326 self.SetState(PLATE_NORMAL) 326 self.SetState(PLATE_NORMAL)
327 327
@@ -363,7 +363,7 @@ class PlateButton(wx.PyControl): @@ -363,7 +363,7 @@ class PlateButton(wx.PyControl):
363 lsize = self.GetTextExtent(self.GetLabel()) 363 lsize = self.GetTextExtent(self.GetLabel())
364 width += lsize[0] 364 width += lsize[0]
365 height += lsize[1] 365 height += lsize[1]
366 - 366 +
367 if self._bmp['enable'] is not None: 367 if self._bmp['enable'] is not None:
368 bsize = self._bmp['enable'].GetSize() 368 bsize = self._bmp['enable'].GetSize()
369 width += (bsize[0] + 10) 369 width += (bsize[0] + 10)
@@ -423,7 +423,7 @@ class PlateButton(wx.PyControl): @@ -423,7 +423,7 @@ class PlateButton(wx.PyControl):
423 # GetBitmap Aliases for BitmapButton api 423 # GetBitmap Aliases for BitmapButton api
424 GetBitmapFocus = GetBitmapLabel 424 GetBitmapFocus = GetBitmapLabel
425 GetBitmapHover = GetBitmapLabel 425 GetBitmapHover = GetBitmapLabel
426 - 426 +
427 # Alias for GetLabel 427 # Alias for GetLabel
428 GetLabelText = wx.PyControl.GetLabel 428 GetLabelText = wx.PyControl.GetLabel
429 429
@@ -504,9 +504,9 @@ class PlateButton(wx.PyControl): @@ -504,9 +504,9 @@ class PlateButton(wx.PyControl):
504 504
505 if (self._style & PB_STYLE_TOGGLE): 505 if (self._style & PB_STYLE_TOGGLE):
506 self._pressed = not self._pressed 506 self._pressed = not self._pressed
507 - 507 +
508 self.SetFocus() 508 self.SetFocus()
509 - 509 +
510 def OnLeftUp(self, evt): 510 def OnLeftUp(self, evt):
511 """Post a button event if the control was previously in a 511 """Post a button event if the control was previously in a
512 pressed state. 512 pressed state.
@@ -586,7 +586,7 @@ class PlateButton(wx.PyControl): @@ -586,7 +586,7 @@ class PlateButton(wx.PyControl):
586 """Set the color of the label. The optimal label color is usually 586 """Set the color of the label. The optimal label color is usually
587 automatically selected depending on the button color. In some 587 automatically selected depending on the button color. In some
588 cases the colors that are choosen may not be optimal. 588 cases the colors that are choosen may not be optimal.
589 - 589 +
590 The normal state must be specified, if the other two params are left 590 The normal state must be specified, if the other two params are left
591 Null they will be automatically guessed based on the normal color. To 591 Null they will be automatically guessed based on the normal color. To
592 prevent this automatic color choices from happening either specify 592 prevent this automatic color choices from happening either specify
@@ -686,7 +686,7 @@ class PlateButton(wx.PyControl): @@ -686,7 +686,7 @@ class PlateButton(wx.PyControl):
686 686
687 self.PopupMenu(self._menu, (xpos, size[1] + adj)) 687 self.PopupMenu(self._menu, (xpos, size[1] + adj))
688 688
689 - def Toggle(self): 689 + def Toggle(self):
690 self._pressed = not self._pressed 690 self._pressed = not self._pressed
691 if self._pressed: 691 if self._pressed:
692 self.SetState(PLATE_PRESSED) 692 self.SetState(PLATE_PRESSED)