# HG changeset patch # Parent f4981d8eb401dcf298f9e59c369f601972683f41 Issue #2053: Standardize IDLE dialogs. Patch by Tal Einat. diff --git a/Lib/idlelib/EditorWindow.py b/Lib/idlelib/EditorWindow.py --- a/Lib/idlelib/EditorWindow.py +++ b/Lib/idlelib/EditorWindow.py @@ -341,12 +341,35 @@ self.wmenu_end = end WindowList.register_callback(self.postwindowsmenu) - # Some abstractions so IDLE extensions are cross-IDE - self.askyesno = tkMessageBox.askyesno - self.askinteger = tkSimpleDialog.askinteger - self.showerror = tkMessageBox.showerror + self._highlight_workaround() # Fix selection tags on Windows - self._highlight_workaround() # Fix selection tags on Windows + # Standard dialogs (which also allow making IDLE extensions cross-IDE) + def _tk_dialog_wrapper(base_method): + def new_method(self, *args, **kwargs): + if 'master' not in kwargs and 'parent' not in kwargs: + kwargs['parent'] = self.text + result = base_method(self, *args, **kwargs) + self.text.focus_set() + return result + return new_method + + @_tk_dialog_wrapper + def showerror(self, *args, **kwargs): + return tkMessageBox.showerror(*args, **kwargs) + + @_tk_dialog_wrapper + def askokcancel(self, *args, **kwargs): + return tkMessageBox.askokcancel(*args, **kwargs) + + @_tk_dialog_wrapper + def askyesno(self, *args, **kwargs): + return tkMessageBox.askyesno(*args, **kwargs) + + @_tk_dialog_wrapper + def askinteger(self, *args, **kwargs): + return tkSimpleDialog.askinteger(*args, **kwargs) + + del _tk_dialog_wrapper def _highlight_workaround(self): # On Windows, Tk removes painting of the selection @@ -660,8 +683,7 @@ def goto_line_event(self, event): text = self.text - lineno = tkSimpleDialog.askinteger("Goto", - "Go to line number:",parent=text) + lineno = self.askinteger("Goto", "Go to line number:") if lineno is None: return "break" if lineno <= 0: @@ -690,11 +712,11 @@ try: (f, file, (suffix, mode, type)) = _find_module(name) except (NameError, ImportError), msg: - tkMessageBox.showerror("Import error", str(msg), parent=self.text) + self.showerror("Import error", str(msg)) return if type != imp.PY_SOURCE: - tkMessageBox.showerror("Unsupported type", - "%s is not a source module" % name, parent=self.text) + self.showerror("Unsupported type", + "%s is not a source module" % name) return if f: f.close() @@ -706,11 +728,8 @@ def open_class_browser(self, event=None): filename = self.io.filename if not filename: - tkMessageBox.showerror( - "No filename", - "This buffer has no associated filename", - master=self.text) - self.text.focus_set() + self.showerror("No filename", + "This buffer has no associated filename") return None head, tail = os.path.split(filename) base, ext = os.path.splitext(tail) @@ -1483,8 +1502,7 @@ "Turn tabs " + ("on", "off")[self.usetabs] + "?\nIndent width " + ("will be", "remains at")[self.usetabs] + " 8." + - "\n Note: a tab is always 8 columns", - parent=self.text): + "\n Note: a tab is always 8 columns"): self.usetabs = not self.usetabs # Try to prevent inconsistent indentation. # User must change indent width manually after using tabs. diff --git a/Lib/idlelib/IOBinding.py b/Lib/idlelib/IOBinding.py --- a/Lib/idlelib/IOBinding.py +++ b/Lib/idlelib/IOBinding.py @@ -252,7 +252,7 @@ chars = f.read() f.close() except IOError, msg: - tkMessageBox.showerror("I/O Error", str(msg), master=self.text) + self.editwin.showerror("I/O Error", str(msg)) return False chars = self.decode(chars) @@ -295,11 +295,10 @@ try: enc = coding_spec(chars) except LookupError, name: - tkMessageBox.showerror( + self.editwin.showerror( title="Error loading the file", message="The encoding '%s' is not known to this Python "\ - "installation. The file may not display correctly" % name, - master = self.text) + "installation. The file may not display correctly" % name) enc = None if enc: try: @@ -389,8 +388,7 @@ f.close() return True except IOError, msg: - tkMessageBox.showerror("I/O Error", str(msg), - master=self.text) + self.editwin.showerror("I/O Error", str(msg)) return False def encode(self, chars): @@ -417,10 +415,9 @@ except UnicodeError: failed = "Invalid encoding '%s'" % enc if failed: - tkMessageBox.showerror( + self.editwin.showerror( "I/O Error", - "%s. Saving as UTF-8" % failed, - master = self.text) + "%s. Saving as UTF-8" % failed) # If there was a UTF-8 signature, use that. This should not fail if self.fileencoding == BOM_UTF8 or failed: return BOM_UTF8 + chars.encode("utf-8") @@ -429,11 +426,10 @@ try: return chars.encode(self.fileencoding) except UnicodeError: - tkMessageBox.showerror( + self.editwin.showerror( "I/O Error", "Cannot save this as '%s' anymore. Saving as UTF-8" \ - % self.fileencoding, - master = self.text) + % self.fileencoding) return BOM_UTF8 + chars.encode("utf-8") # Nothing was declared, and we had not determined an encoding # on loading. Recommend an encoding line. @@ -514,7 +510,7 @@ status + output if output: output = "Printing command: %s\n" % repr(command) + output - tkMessageBox.showerror("Print status", output, master=self.text) + self.editwin.showerror("Print status", output) else: #no printing for this platform message = "Printing is not enabled for this platform: %s" % platform tkMessageBox.showinfo("Print status", message, master=self.text) diff --git a/Lib/idlelib/OutputWindow.py b/Lib/idlelib/OutputWindow.py --- a/Lib/idlelib/OutputWindow.py +++ b/Lib/idlelib/OutputWindow.py @@ -92,11 +92,10 @@ "insert -1line lineend") result = self._file_line_helper(line) if not result: - tkMessageBox.showerror( + self.showerror( "No special line", "The line you point at doesn't look like " - "a valid file name followed by a line number.", - master=self.text) + "a valid file name followed by a line number.") return filename, lineno = result edit = self.flist.open(filename) diff --git a/Lib/idlelib/PyShell.py b/Lib/idlelib/PyShell.py --- a/Lib/idlelib/PyShell.py +++ b/Lib/idlelib/PyShell.py @@ -765,11 +765,10 @@ exec code in self.locals except SystemExit: if not self.tkconsole.closing: - if tkMessageBox.askyesno( + if self.tkconsole.askyesno( "Exit?", "Do you want to exit altogether?", - default="yes", - master=self.tkconsole.text): + default=tkMessageBox.YES): raise else: self.showtraceback() @@ -799,30 +798,27 @@ self.tkconsole.stderr.write(s) def display_port_binding_error(self): - tkMessageBox.showerror( + self.tkconsole.showerror( "Port Binding Error", "IDLE can't bind to a TCP/IP port, which is necessary to " "communicate with its Python execution server. This might be " "because no networking is installed on this computer. " "Run IDLE with the -n command line switch to start without a " "subprocess and refer to Help/IDLE Help 'Running without a " - "subprocess' for further details.", - master=self.tkconsole.text) + "subprocess' for further details.") def display_no_subprocess_error(self): - tkMessageBox.showerror( + self.tkconsole.showerror( "Subprocess Startup Error", "IDLE's subprocess didn't make connection. Either IDLE can't " "start a subprocess or personal firewall software is blocking " - "the connection.", - master=self.tkconsole.text) + "the connection.") def display_executing_dialog(self): - tkMessageBox.showerror( + self.tkconsole.showerror( "Already executing", "The Python Shell window is already executing a command; " - "please wait until it is finished.", - master=self.tkconsole.text) + "please wait until it is finished.") class PyShell(OutputWindow): @@ -919,9 +915,8 @@ def toggle_debugger(self, event=None): if self.executing: - tkMessageBox.showerror("Don't debug now", - "You can only toggle the debugger when idle", - master=self.text) + self.showerror("Don't debug now", + "You can only toggle the debugger when idle") self.set_debugger_indicator() return "break" else: @@ -977,11 +972,10 @@ def close(self): "Extend EditorWindow.close()" if self.executing: - response = tkMessageBox.askokcancel( + response = self.askokcancel( "Kill?", "The program is still running!\n Do you want to kill it?", - default="ok", - parent=self.text) + default=tkMessageBox.OK) if response is False: return "cancel" self.stop_readline() @@ -1229,10 +1223,9 @@ try: sys.last_traceback except: - tkMessageBox.showerror("No stack trace", + self.showerror("No stack trace", "There is no stack trace yet.\n" - "(sys.last_traceback is not defined)", - master=self.text) + "(sys.last_traceback is not defined)") return from idlelib.StackViewer import StackBrowser sv = StackBrowser(self.root, self.flist) diff --git a/Lib/idlelib/ScriptBinding.py b/Lib/idlelib/ScriptBinding.py --- a/Lib/idlelib/ScriptBinding.py +++ b/Lib/idlelib/ScriptBinding.py @@ -73,13 +73,13 @@ except tokenize.TokenError, msg: msgtxt, (lineno, start) = msg self.editwin.gotoline(lineno) - self.errorbox("Tabnanny Tokenizing Error", - "Token Error: %s" % msgtxt) + self.editwin.showerror("Tabnanny Tokenizing Error", + "Token Error: %s" % msgtxt) return False except tabnanny.NannyNag, nag: # The error messages from tabnanny are too confusing... self.editwin.gotoline(nag.get_lineno()) - self.errorbox("Tab/space error", indent_message) + self.editwin.showerror("Tab/space error", indent_message) return False return True @@ -110,8 +110,9 @@ self.colorize_syntax_error(msg, lineno, offset) except: msg = "*** " + str(err) - self.errorbox("Syntax error", - "There's an error in your program:\n" + msg) + self.editwin.showerror( + "Syntax error", + "There's an error in your program:\n" + msg) return False finally: shell.set_warning_stream(saved_stream) @@ -200,9 +201,7 @@ if autosave and filename: self.editwin.io.save(None) else: - confirm = self.ask_save_dialog() - self.editwin.text.focus_set() - if confirm: + if self.ask_save_dialog(): self.editwin.io.save(None) filename = self.editwin.io.filename else: @@ -211,13 +210,7 @@ def ask_save_dialog(self): msg = "Source Must Be Saved\n" + 5*' ' + "OK to Save?" - confirm = tkMessageBox.askokcancel(title="Save Before Run or Check", - message=msg, - default=tkMessageBox.OK, - master=self.editwin.text) - return confirm - - def errorbox(self, title, message): - # XXX This should really be a function of EditorWindow... - tkMessageBox.showerror(title, message, master=self.editwin.text) - self.editwin.text.focus_set() + return self.editwin.askokcancel( + title="Save Before Run or Check", + message=msg, + default=tkMessageBox.OK)