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