[3.6] bpo-6739: IDLE: Check for valid keybinding in config_keys (GH-2… by terryjreedy · Pull Request #2397 · python/cpython

Expand Up @@ -3,11 +3,16 @@ """ from tkinter import * from tkinter.ttk import Scrollbar import tkinter.messagebox as tkMessageBox from tkinter import messagebox import string import sys

class GetKeysDialog(Toplevel):
# Dialog title for invalid key sequence keyerror_title = 'Key Sequence Error'
def __init__(self, parent, title, action, currentKeySequences, _htest=False, _utest=False): """ Expand Down Expand Up @@ -54,6 +59,10 @@ def __init__(self, parent, title, action, currentKeySequences, self.deiconify() #geometry set, unhide self.wait_window()
def showerror(self, *args, **kwargs): # Make testing easier. Replace in #30751. messagebox.showerror(*args, **kwargs)
def CreateWidgets(self): frameMain = Frame(self,borderwidth=2,relief=SUNKEN) frameMain.pack(side=TOP,expand=TRUE,fill=BOTH) Expand Down Expand Up @@ -219,53 +228,70 @@ def TranslateKey(self, key, modifiers): return key
def OK(self, event=None): if self.advanced or self.KeysOK(): # doesn't check advanced string yet self.result=self.keyString.get() self.destroy() keys = self.keyString.get().strip() if not keys: self.showerror(title=self.keyerror_title, parent=self, message="No key specified.") return if (self.advanced or self.KeysOK(keys)) and self.bind_ok(keys): self.result = keys self.destroy()
def Cancel(self, event=None): self.result='' self.destroy()
def KeysOK(self): def KeysOK(self, keys): '''Validity check on user's 'basic' keybinding selection.
Doesn't check the string produced by the advanced dialog because 'modifiers' isn't set.
''' keys = self.keyString.get() keys.strip() finalKey = self.listKeysFinal.get(ANCHOR) modifiers = self.GetModifiers() # create a key sequence list for overlap check: keySequence = keys.split() keysOK = False title = 'Key Sequence Error' if not keys: tkMessageBox.showerror(title=title, parent=self, message='No keys specified.') elif not keys.endswith('>'): tkMessageBox.showerror(title=title, parent=self, message='Missing the final Key') title = self.keyerror_title if not keys.endswith('>'): self.showerror(title, parent=self, message='Missing the final Key') elif (not modifiers and finalKey not in self.functionKeys + self.moveKeys): tkMessageBox.showerror(title=title, parent=self, message='No modifier key(s) specified.') self.showerror(title=title, parent=self, message='No modifier key(s) specified.') elif (modifiers == ['Shift']) \ and (finalKey not in self.functionKeys + self.moveKeys + ('Tab', 'Space')): msg = 'The shift modifier by itself may not be used with'\ ' this key symbol.' tkMessageBox.showerror(title=title, parent=self, message=msg) self.showerror(title=title, parent=self, message=msg) elif keySequence in self.currentKeySequences: msg = 'This key combination is already in use.' tkMessageBox.showerror(title=title, parent=self, message=msg) self.showerror(title=title, parent=self, message=msg) else: keysOK = True return keysOK
def bind_ok(self, keys): "Return True if Tcl accepts the new keys else show message."
try: binding = self.bind(keys, lambda: None) except TclError as err: self.showerror( title=self.keyerror_title, parent=self, message=(f'The entered key sequence is not accepted.\n\n' f'Error: {err}')) return False else: self.unbind(keys, binding) return True

if __name__ == '__main__': import unittest unittest.main('idlelib.idle_test.test_config_key', verbosity=2, exit=False) from idlelib.idle_test.htest import run run(GetKeysDialog)