Thread: [PythonReports-checkins] PythonReports/PythonReports design.py, 1.5, 1.6
Brought to you by:
a1s
From: alexander s. <a1...@us...> - 2006-11-03 16:33:42
|
Update of /cvsroot/pythonreports/PythonReports/PythonReports In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv9698 Modified Files: design.py Log Message: handle file loading errors; prompt to save changes on open file/new file/exit Index: design.py =================================================================== RCS file: /cvsroot/pythonreports/PythonReports/PythonReports/design.py,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** design.py 3 Nov 2006 12:49:31 -0000 1.5 --- design.py 3 Nov 2006 16:33:34 -0000 1.6 *************** *** 2,10 **** """History (most recent first): ! 02-nov-2006 [als] fix ColorSelection: hide indicator when color is unset, bell when invalid value entered, pass rgb string to askcolor(), retake focus after askcolor ! 02-nov-2006 [als] pop up the tree menu on Shift+F10; added element reordering commands "move up" and "move down" 02-nov-2006 [als] create automatic hotkeys in insertion menus --- 2,12 ---- """History (most recent first): ! 03-nov-2006 [als] handle file loading errors; ! prompt to save changes on open file/new file/exit ! 03-nov-2006 [als] fix ColorSelection: hide indicator when color is unset, bell when invalid value entered, pass rgb string to askcolor(), retake focus after askcolor ! 03-nov-2006 [als] pop up the tree menu on Shift+F10; added element reordering commands "move up" and "move down" 02-nov-2006 [als] create automatic hotkeys in insertion menus *************** *** 677,680 **** --- 679,683 ---- report = None current_node = None + terminated = False @property *************** *** 698,705 **** Toplevel.__init__(self, class_="PythonReportsDesigner", **options) self.build() if filename: self.loadFile(filename) - else: - self.makeReport() # layout --- 701,709 ---- Toplevel.__init__(self, class_="PythonReportsDesigner", **options) self.build() + # build a pristine tree to use if filename is not passed + # or cannot be opened. + self.makeReport() if filename: self.loadFile(filename) # layout *************** *** 708,712 **** """Do the window layout""" self.buildMenu() - # statusbar self.statusbar = Label(self, borderwidth=1, relief=SUNKEN) self.statusbar.pack(side=BOTTOM, fill=X) --- 712,715 ---- *************** *** 752,755 **** --- 755,759 ---- width=720, height=100) self.vp.add(self.canvas) + self.bind("<Destroy>", self.OnWindowClose) def buildMenu(self): *************** *** 761,765 **** # File menu _popup = self._build_menu_item(_menu, ''"_File", type="cascade") ! self._build_menu_item(_popup, ''"_New", command=self.makeReport) self._build_menu_item(_popup, ''"_Open", command=self.OnMenuFileOpen) self._build_menu_item(_popup, ''"_Save", --- 765,769 ---- # File menu _popup = self._build_menu_item(_menu, ''"_File", type="cascade") ! self._build_menu_item(_popup, ''"_New", command=self.OnMenuFileNew) self._build_menu_item(_popup, ''"_Open", command=self.OnMenuFileOpen) self._build_menu_item(_popup, ''"_Save", *************** *** 886,891 **** --- 890,916 ---- _widget.event_generate(event) + def OnWindowClose(self, event): + """Handle Destroy event for the toplevel window""" + # this handler gets destroy events for all child widgets, + # including Message dialogs. Check update when the first + # child of the tree widget gets destroyed, ignore all others. + if not self.terminated and event.widget.startswith(str(self.tree)): + # some of the window widgets have been destroyed yet + # and the window looks weird. hide it away. + # (we cannot return to the editor anyway.) + self.withdraw() + self.checkUpdate(dlgtype="yesno") + self.terminated = True + + def OnMenuFileNew(self): + """Create new empty template""" + if not self.checkUpdate(): + return + self.makeReport() + def OnMenuFileOpen(self): """Load template file""" + if not self.checkUpdate(): + return _filename = tkFileDialog.askopenfilename(**self.fileoptions) if _filename: *************** *** 894,898 **** def OnMenuQuit(self): """Exit the application""" ! # TODO: save file self.destroy() --- 919,924 ---- def OnMenuQuit(self): """Exit the application""" ! if not self.checkUpdate(): ! return self.destroy() *************** *** 1193,1200 **** _tree.open("report") self.select("report") def loadFile(self, filename): """Load report file""" ! self.report = prt.load(filename) self.filename = filename self.filedir = os.path.dirname(os.path.abspath(filename)) --- 1219,1242 ---- _tree.open("report") self.select("report") + # Note: str(report) returns normalized text, + # may differ from contents of the loaded file. + # Note: loaded_text must be evaluated + # after TreeNodeData construction (that may + # make some unsignificant changes to the tree) + self.loaded_text = str(self.report) def loadFile(self, filename): """Load report file""" ! try: ! self.report = prt.load(filename) ! except Exception, _err: ! _focus = self.focus_get() or self.tree.hlist ! Message(self, icon="error", type="ok", ! title=self._("File load error"), ! message=self._("Error loading file %(file)s:\n%(error)s") ! % {"file": os.path.abspath(filename), "error": _err}).show() ! # FIXME: still unfocused... ! _focus.focus_set() ! return self.filename = filename self.filedir = os.path.dirname(os.path.abspath(filename)) *************** *** 1216,1229 **** if None, open Save File dialog. """ if not self.updateTree(): ! return if not filename: filename = tkFileDialog.asksaveasfilename(**self.fileoptions) if not filename: ! return self.report.write(filename) self.report.filename = self.filename = filename self.filedir = os.path.dirname(os.path.abspath(filename)) def updateTree(self, errors="strict"): --- 1258,1276 ---- if None, open Save File dialog. + Return value: True if the template saved successfully, + False otherwise. + """ if not self.updateTree(): ! return False if not filename: filename = tkFileDialog.asksaveasfilename(**self.fileoptions) if not filename: ! return False self.report.write(filename) self.report.filename = self.filename = filename self.filedir = os.path.dirname(os.path.abspath(filename)) + self.loaded_text = str(self.report) + return True def updateTree(self, errors="strict"): *************** *** 1274,1277 **** --- 1321,1361 ---- return True + def checkUpdate(self, dlgtype="yesnocancel"): + """Check if the template has unsaved changes; prompt to save + + Parameters: + dlgtype: MessageBox type - "yesno" or "yesnocancel". + + If there are unsaved changes in the tree, prompt user + to save the template. By default, the prompt dialog + has buttons "Yes", "No" and "Cancel". When the window + is closed by operational system, the operation cannot + be canceled, so there may be only "Yes" and "No" buttons, + giving the user one last chance to save changes. + + Return value: False to cancel operation, True to proceed. + + """ + # first, do silent update (saveFile will do validating update later) + self.updateTree(errors="ignore") + if str(self.report) == self.loaded_text: + # no changes + return True + _focus = self.focus_get() + if self.filename: + _msg = self._("Do you want to save the changes you made to %s?") \ + % os.path.basename(self.filename) + else: + _msg = self._("Do you want to save the changes" + " you made to new template?") + _okcancel = Message(self, icon="warning", type=dlgtype, + title=self._("Unsaved changes detected"), message=_msg).show() + _focus.focus_set() + if _okcancel == "cancel": + return False + elif _okcancel == "no": + return True + return self.saveFile(self.filename) + @staticmethod def _validate(tree, validator): *************** *** 1287,1290 **** --- 1371,1375 ---- _focus = self.focus_get() # validate the tree + # XXX seems to be a repetition (done in updateTree?) - unneeded self._validate(self.report, prt.Report) # get the data |