ยปCore Development>Code coverage>Lib/idlelib/config_key.py

Python code coverage for Lib/idlelib/config_key.py

#countcontent
1n/a"""
2n/aDialog for building Tkinter accelerator key bindings
3n/a"""
4n/afrom tkinter import *
5n/afrom tkinter.ttk import Scrollbar
6n/aimport tkinter.messagebox as tkMessageBox
7n/aimport string
8n/aimport sys
9n/a
10n/aclass GetKeysDialog(Toplevel):
11n/a def __init__(self, parent, title, action, currentKeySequences,
12n/a _htest=False, _utest=False):
13n/a """
14n/a action - string, the name of the virtual event these keys will be
15n/a mapped to
16n/a currentKeys - list, a list of all key sequence lists currently mapped
17n/a to virtual events, for overlap checking
18n/a _utest - bool, do not wait when running unittest
19n/a _htest - bool, change box location when running htest
20n/a """
21n/a Toplevel.__init__(self, parent)
22n/a self.withdraw() #hide while setting geometry
23n/a self.configure(borderwidth=5)
24n/a self.resizable(height=FALSE, width=FALSE)
25n/a self.title(title)
26n/a self.transient(parent)
27n/a self.grab_set()
28n/a self.protocol("WM_DELETE_WINDOW", self.Cancel)
29n/a self.parent = parent
30n/a self.action=action
31n/a self.currentKeySequences = currentKeySequences
32n/a self.result = ''
33n/a self.keyString = StringVar(self)
34n/a self.keyString.set('')
35n/a self.SetModifiersForPlatform() # set self.modifiers, self.modifier_label
36n/a self.modifier_vars = []
37n/a for modifier in self.modifiers:
38n/a variable = StringVar(self)
39n/a variable.set('')
40n/a self.modifier_vars.append(variable)
41n/a self.advanced = False
42n/a self.CreateWidgets()
43n/a self.LoadFinalKeyList()
44n/a self.update_idletasks()
45n/a self.geometry(
46n/a "+%d+%d" % (
47n/a parent.winfo_rootx() +
48n/a (parent.winfo_width()/2 - self.winfo_reqwidth()/2),
49n/a parent.winfo_rooty() +
50n/a ((parent.winfo_height()/2 - self.winfo_reqheight()/2)
51n/a if not _htest else 150)
52n/a ) ) #centre dialog over parent (or below htest box)
53n/a if not _utest:
54n/a self.deiconify() #geometry set, unhide
55n/a self.wait_window()
56n/a
57n/a def CreateWidgets(self):
58n/a frameMain = Frame(self,borderwidth=2,relief=SUNKEN)
59n/a frameMain.pack(side=TOP,expand=TRUE,fill=BOTH)
60n/a frameButtons=Frame(self)
61n/a frameButtons.pack(side=BOTTOM,fill=X)
62n/a self.buttonOK = Button(frameButtons,text='OK',
63n/a width=8,command=self.OK)
64n/a self.buttonOK.grid(row=0,column=0,padx=5,pady=5)
65n/a self.buttonCancel = Button(frameButtons,text='Cancel',
66n/a width=8,command=self.Cancel)
67n/a self.buttonCancel.grid(row=0,column=1,padx=5,pady=5)
68n/a self.frameKeySeqBasic = Frame(frameMain)
69n/a self.frameKeySeqAdvanced = Frame(frameMain)
70n/a self.frameControlsBasic = Frame(frameMain)
71n/a self.frameHelpAdvanced = Frame(frameMain)
72n/a self.frameKeySeqAdvanced.grid(row=0,column=0,sticky=NSEW,padx=5,pady=5)
73n/a self.frameKeySeqBasic.grid(row=0,column=0,sticky=NSEW,padx=5,pady=5)
74n/a self.frameKeySeqBasic.lift()
75n/a self.frameHelpAdvanced.grid(row=1,column=0,sticky=NSEW,padx=5)
76n/a self.frameControlsBasic.grid(row=1,column=0,sticky=NSEW,padx=5)
77n/a self.frameControlsBasic.lift()
78n/a self.buttonLevel = Button(frameMain,command=self.ToggleLevel,
79n/a text='Advanced Key Binding Entry >>')
80n/a self.buttonLevel.grid(row=2,column=0,stick=EW,padx=5,pady=5)
81n/a labelTitleBasic = Label(self.frameKeySeqBasic,
82n/a text="New keys for '"+self.action+"' :")
83n/a labelTitleBasic.pack(anchor=W)
84n/a labelKeysBasic = Label(self.frameKeySeqBasic,justify=LEFT,
85n/a textvariable=self.keyString,relief=GROOVE,borderwidth=2)
86n/a labelKeysBasic.pack(ipadx=5,ipady=5,fill=X)
87n/a self.modifier_checkbuttons = {}
88n/a column = 0
89n/a for modifier, variable in zip(self.modifiers, self.modifier_vars):
90n/a label = self.modifier_label.get(modifier, modifier)
91n/a check=Checkbutton(self.frameControlsBasic,
92n/a command=self.BuildKeyString,
93n/a text=label,variable=variable,onvalue=modifier,offvalue='')
94n/a check.grid(row=0,column=column,padx=2,sticky=W)
95n/a self.modifier_checkbuttons[modifier] = check
96n/a column += 1
97n/a labelFnAdvice=Label(self.frameControlsBasic,justify=LEFT,
98n/a text=\
99n/a "Select the desired modifier keys\n"+
100n/a "above, and the final key from the\n"+
101n/a "list on the right.\n\n" +
102n/a "Use upper case Symbols when using\n" +
103n/a "the Shift modifier. (Letters will be\n" +
104n/a "converted automatically.)")
105n/a labelFnAdvice.grid(row=1,column=0,columnspan=4,padx=2,sticky=W)
106n/a self.listKeysFinal=Listbox(self.frameControlsBasic,width=15,height=10,
107n/a selectmode=SINGLE)
108n/a self.listKeysFinal.bind('<ButtonRelease-1>',self.FinalKeySelected)
109n/a self.listKeysFinal.grid(row=0,column=4,rowspan=4,sticky=NS)
110n/a scrollKeysFinal=Scrollbar(self.frameControlsBasic,orient=VERTICAL,
111n/a command=self.listKeysFinal.yview)
112n/a self.listKeysFinal.config(yscrollcommand=scrollKeysFinal.set)
113n/a scrollKeysFinal.grid(row=0,column=5,rowspan=4,sticky=NS)
114n/a self.buttonClear=Button(self.frameControlsBasic,
115n/a text='Clear Keys',command=self.ClearKeySeq)
116n/a self.buttonClear.grid(row=2,column=0,columnspan=4)
117n/a labelTitleAdvanced = Label(self.frameKeySeqAdvanced,justify=LEFT,
118n/a text="Enter new binding(s) for '"+self.action+"' :\n"+
119n/a "(These bindings will not be checked for validity!)")
120n/a labelTitleAdvanced.pack(anchor=W)
121n/a self.entryKeysAdvanced=Entry(self.frameKeySeqAdvanced,
122n/a textvariable=self.keyString)
123n/a self.entryKeysAdvanced.pack(fill=X)
124n/a labelHelpAdvanced=Label(self.frameHelpAdvanced,justify=LEFT,
125n/a text="Key bindings are specified using Tkinter keysyms as\n"+
126n/a "in these samples: <Control-f>, <Shift-F2>, <F12>,\n"
127n/a "<Control-space>, <Meta-less>, <Control-Alt-Shift-X>.\n"
128n/a "Upper case is used when the Shift modifier is present!\n\n" +
129n/a "'Emacs style' multi-keystroke bindings are specified as\n" +
130n/a "follows: <Control-x><Control-y>, where the first key\n" +
131n/a "is the 'do-nothing' keybinding.\n\n" +
132n/a "Multiple separate bindings for one action should be\n"+
133n/a "separated by a space, eg., <Alt-v> <Meta-v>." )
134n/a labelHelpAdvanced.grid(row=0,column=0,sticky=NSEW)
135n/a
136n/a def SetModifiersForPlatform(self):
137n/a """Determine list of names of key modifiers for this platform.
138n/a
139n/a The names are used to build Tk bindings -- it doesn't matter if the
140n/a keyboard has these keys, it matters if Tk understands them. The
141n/a order is also important: key binding equality depends on it, so
142n/a config-keys.def must use the same ordering.
143n/a """
144n/a if sys.platform == "darwin":
145n/a self.modifiers = ['Shift', 'Control', 'Option', 'Command']
146n/a else:
147n/a self.modifiers = ['Control', 'Alt', 'Shift']
148n/a self.modifier_label = {'Control': 'Ctrl'} # short name
149n/a
150n/a def ToggleLevel(self):
151n/a if self.buttonLevel.cget('text')[:8]=='Advanced':
152n/a self.ClearKeySeq()
153n/a self.buttonLevel.config(text='<< Basic Key Binding Entry')
154n/a self.frameKeySeqAdvanced.lift()
155n/a self.frameHelpAdvanced.lift()
156n/a self.entryKeysAdvanced.focus_set()
157n/a self.advanced = True
158n/a else:
159n/a self.ClearKeySeq()
160n/a self.buttonLevel.config(text='Advanced Key Binding Entry >>')
161n/a self.frameKeySeqBasic.lift()
162n/a self.frameControlsBasic.lift()
163n/a self.advanced = False
164n/a
165n/a def FinalKeySelected(self,event):
166n/a self.BuildKeyString()
167n/a
168n/a def BuildKeyString(self):
169n/a keyList = modifiers = self.GetModifiers()
170n/a finalKey = self.listKeysFinal.get(ANCHOR)
171n/a if finalKey:
172n/a finalKey = self.TranslateKey(finalKey, modifiers)
173n/a keyList.append(finalKey)
174n/a self.keyString.set('<' + '-'.join(keyList) + '>')
175n/a
176n/a def GetModifiers(self):
177n/a modList = [variable.get() for variable in self.modifier_vars]
178n/a return [mod for mod in modList if mod]
179n/a
180n/a def ClearKeySeq(self):
181n/a self.listKeysFinal.select_clear(0,END)
182n/a self.listKeysFinal.yview(MOVETO, '0.0')
183n/a for variable in self.modifier_vars:
184n/a variable.set('')
185n/a self.keyString.set('')
186n/a
187n/a def LoadFinalKeyList(self):
188n/a #these tuples are also available for use in validity checks
189n/a self.functionKeys=('F1','F2','F2','F4','F5','F6','F7','F8','F9',
190n/a 'F10','F11','F12')
191n/a self.alphanumKeys=tuple(string.ascii_lowercase+string.digits)
192n/a self.punctuationKeys=tuple('~!@#%^&*()_-+={}[]|;:,.<>/?')
193n/a self.whitespaceKeys=('Tab','Space','Return')
194n/a self.editKeys=('BackSpace','Delete','Insert')
195n/a self.moveKeys=('Home','End','Page Up','Page Down','Left Arrow',
196n/a 'Right Arrow','Up Arrow','Down Arrow')
197n/a #make a tuple of most of the useful common 'final' keys
198n/a keys=(self.alphanumKeys+self.punctuationKeys+self.functionKeys+
199n/a self.whitespaceKeys+self.editKeys+self.moveKeys)
200n/a self.listKeysFinal.insert(END, *keys)
201n/a
202n/a def TranslateKey(self, key, modifiers):
203n/a "Translate from keycap symbol to the Tkinter keysym"
204n/a translateDict = {'Space':'space',
205n/a '~':'asciitilde','!':'exclam','@':'at','#':'numbersign',
206n/a '%':'percent','^':'asciicircum','&':'ampersand','*':'asterisk',
207n/a '(':'parenleft',')':'parenright','_':'underscore','-':'minus',
208n/a '+':'plus','=':'equal','{':'braceleft','}':'braceright',
209n/a '[':'bracketleft',']':'bracketright','|':'bar',';':'semicolon',
210n/a ':':'colon',',':'comma','.':'period','<':'less','>':'greater',
211n/a '/':'slash','?':'question','Page Up':'Prior','Page Down':'Next',
212n/a 'Left Arrow':'Left','Right Arrow':'Right','Up Arrow':'Up',
213n/a 'Down Arrow': 'Down', 'Tab':'Tab'}
214n/a if key in translateDict:
215n/a key = translateDict[key]
216n/a if 'Shift' in modifiers and key in string.ascii_lowercase:
217n/a key = key.upper()
218n/a key = 'Key-' + key
219n/a return key
220n/a
221n/a def OK(self, event=None):
222n/a if self.advanced or self.KeysOK(): # doesn't check advanced string yet
223n/a self.result=self.keyString.get()
224n/a self.destroy()
225n/a
226n/a def Cancel(self, event=None):
227n/a self.result=''
228n/a self.destroy()
229n/a
230n/a def KeysOK(self):
231n/a '''Validity check on user's 'basic' keybinding selection.
232n/a
233n/a Doesn't check the string produced by the advanced dialog because
234n/a 'modifiers' isn't set.
235n/a
236n/a '''
237n/a keys = self.keyString.get()
238n/a keys.strip()
239n/a finalKey = self.listKeysFinal.get(ANCHOR)
240n/a modifiers = self.GetModifiers()
241n/a # create a key sequence list for overlap check:
242n/a keySequence = keys.split()
243n/a keysOK = False
244n/a title = 'Key Sequence Error'
245n/a if not keys:
246n/a tkMessageBox.showerror(title=title, parent=self,
247n/a message='No keys specified.')
248n/a elif not keys.endswith('>'):
249n/a tkMessageBox.showerror(title=title, parent=self,
250n/a message='Missing the final Key')
251n/a elif (not modifiers
252n/a and finalKey not in self.functionKeys + self.moveKeys):
253n/a tkMessageBox.showerror(title=title, parent=self,
254n/a message='No modifier key(s) specified.')
255n/a elif (modifiers == ['Shift']) \
256n/a and (finalKey not in
257n/a self.functionKeys + self.moveKeys + ('Tab', 'Space')):
258n/a msg = 'The shift modifier by itself may not be used with'\
259n/a ' this key symbol.'
260n/a tkMessageBox.showerror(title=title, parent=self, message=msg)
261n/a elif keySequence in self.currentKeySequences:
262n/a msg = 'This key combination is already in use.'
263n/a tkMessageBox.showerror(title=title, parent=self, message=msg)
264n/a else:
265n/a keysOK = True
266n/a return keysOK
267n/a
268n/a
269n/aif __name__ == '__main__':
270n/a from idlelib.idle_test.htest import run
271n/a run(GetKeysDialog)