|
1 # -*- coding: utf-8 -*- |
|
2 |
|
3 # Copyright (c) 2004 - 2009 Detlev Offenbach <detlev@die-offenbachs.de> |
|
4 # |
|
5 |
|
6 """ |
|
7 Module implementing functions dealing with keyboard shortcuts. |
|
8 """ |
|
9 |
|
10 import cStringIO |
|
11 |
|
12 from PyQt4.QtCore import * |
|
13 from PyQt4.QtGui import * |
|
14 |
|
15 from E4Gui.E4Application import e4App |
|
16 |
|
17 from Preferences import Prefs, syncPreferences |
|
18 |
|
19 from E4XML.XMLUtilities import make_parser |
|
20 from E4XML.XMLErrorHandler import XMLErrorHandler, XMLFatalParseError |
|
21 from E4XML.ShortcutsHandler import ShortcutsHandler |
|
22 from E4XML.ShortcutsWriter import ShortcutsWriter |
|
23 from E4XML.XMLEntityResolver import XMLEntityResolver |
|
24 |
|
25 def __readShortcut(act, category, prefClass): |
|
26 """ |
|
27 Private function to read a single keyboard shortcut from the settings. |
|
28 |
|
29 @param act reference to the action object (E4Action) |
|
30 @param category category the action belongs to (string) |
|
31 @param prefClass preferences class used as the storage area |
|
32 """ |
|
33 if act.objectName(): |
|
34 accel = prefClass.settings.value( |
|
35 "Shortcuts/{0}/{1}/Accel".format(category, act.objectName())) |
|
36 if accel.isValid(): |
|
37 act.setShortcut(QKeySequence(accel.toString())) |
|
38 accel = prefClass.settings.value( |
|
39 "Shortcuts/{0}/{1}/AltAccel".format(category, act.objectName())) |
|
40 if accel.isValid(): |
|
41 act.setAlternateShortcut(QKeySequence(accel.toString())) |
|
42 |
|
43 def readShortcuts(prefClass = Prefs, helpViewer = None, pluginName = None): |
|
44 """ |
|
45 Module function to read the keyboard shortcuts for the defined QActions. |
|
46 |
|
47 @keyparam prefClass preferences class used as the storage area |
|
48 @keyparam helpViewer reference to the help window object |
|
49 @keyparam pluginName name of the plugin for which to load shortcuts (string) |
|
50 """ |
|
51 if helpViewer is None and pluginName is None: |
|
52 for act in e4App().getObject("Project").getActions(): |
|
53 __readShortcut(act, "Project", prefClass) |
|
54 |
|
55 for act in e4App().getObject("UserInterface").getActions('ui'): |
|
56 __readShortcut(act, "General", prefClass) |
|
57 |
|
58 for act in e4App().getObject("UserInterface").getActions('wizards'): |
|
59 __readShortcut(act, "Wizards", prefClass) |
|
60 |
|
61 for act in e4App().getObject("DebugUI").getActions(): |
|
62 __readShortcut(act, "Debug", prefClass) |
|
63 |
|
64 for act in e4App().getObject("ViewManager").getActions('edit'): |
|
65 __readShortcut(act, "Edit", prefClass) |
|
66 |
|
67 for act in e4App().getObject("ViewManager").getActions('file'): |
|
68 __readShortcut(act, "File", prefClass) |
|
69 |
|
70 for act in e4App().getObject("ViewManager").getActions('search'): |
|
71 __readShortcut(act, "Search", prefClass) |
|
72 |
|
73 for act in e4App().getObject("ViewManager").getActions('view'): |
|
74 __readShortcut(act, "View", prefClass) |
|
75 |
|
76 for act in e4App().getObject("ViewManager").getActions('macro'): |
|
77 __readShortcut(act, "Macro", prefClass) |
|
78 |
|
79 for act in e4App().getObject("ViewManager").getActions('bookmark'): |
|
80 __readShortcut(act, "Bookmarks", prefClass) |
|
81 |
|
82 for act in e4App().getObject("ViewManager").getActions('spelling'): |
|
83 __readShortcut(act, "Spelling", prefClass) |
|
84 |
|
85 actions = e4App().getObject("ViewManager").getActions('window') |
|
86 if actions: |
|
87 for act in actions: |
|
88 __readShortcut(act, "Window", prefClass) |
|
89 |
|
90 for category, ref in e4App().getPluginObjects(): |
|
91 if hasattr(ref, "getActions"): |
|
92 actions = ref.getActions() |
|
93 for act in actions: |
|
94 __readShortcut(act, category, prefClass) |
|
95 |
|
96 if helpViewer is not None: |
|
97 for act in helpViewer.getActions(): |
|
98 __readShortcut(act, "HelpViewer", prefClass) |
|
99 |
|
100 if pluginName is not None: |
|
101 try: |
|
102 ref = e4App().getPluginObject(pluginName) |
|
103 if hasattr(ref, "getActions"): |
|
104 actions = ref.getActions() |
|
105 for act in actions: |
|
106 __readShortcut(act, pluginName, prefClass) |
|
107 except KeyError: |
|
108 # silently ignore non available plugins |
|
109 pass |
|
110 |
|
111 def __saveShortcut(act, category, prefClass): |
|
112 """ |
|
113 Private function to write a single keyboard shortcut to the settings. |
|
114 |
|
115 @param act reference to the action object (E4Action) |
|
116 @param category category the action belongs to (string) |
|
117 @param prefClass preferences class used as the storage area |
|
118 """ |
|
119 if act.objectName(): |
|
120 prefClass.settings.setValue( |
|
121 "Shortcuts/{0}/{1}/Accel".format(category, act.objectName()), |
|
122 QVariant(act.shortcut())) |
|
123 prefClass.settings.setValue( |
|
124 "Shortcuts/{0}/{1}/AltAccel".format(category, act.objectName()), |
|
125 QVariant(act.alternateShortcut())) |
|
126 |
|
127 def saveShortcuts(prefClass = Prefs): |
|
128 """ |
|
129 Module function to write the keyboard shortcuts for the defined QActions. |
|
130 |
|
131 @param prefClass preferences class used as the storage area |
|
132 """ |
|
133 # step 1: clear all previously saved shortcuts |
|
134 prefClass.settings.beginGroup("Shortcuts") |
|
135 prefClass.settings.remove("") |
|
136 prefClass.settings.endGroup() |
|
137 |
|
138 # step 2: save the various shortcuts |
|
139 for act in e4App().getObject("Project").getActions(): |
|
140 __saveShortcut(act, "Project", prefClass) |
|
141 |
|
142 for act in e4App().getObject("UserInterface").getActions('ui'): |
|
143 __saveShortcut(act, "General", prefClass) |
|
144 |
|
145 for act in e4App().getObject("UserInterface").getActions('wizards'): |
|
146 __saveShortcut(act, "Wizards", prefClass) |
|
147 |
|
148 for act in e4App().getObject("DebugUI").getActions(): |
|
149 __saveShortcut(act, "Debug", prefClass) |
|
150 |
|
151 for act in e4App().getObject("ViewManager").getActions('edit'): |
|
152 __saveShortcut(act, "Edit", prefClass) |
|
153 |
|
154 for act in e4App().getObject("ViewManager").getActions('file'): |
|
155 __saveShortcut(act, "File", prefClass) |
|
156 |
|
157 for act in e4App().getObject("ViewManager").getActions('search'): |
|
158 __saveShortcut(act, "Search", prefClass) |
|
159 |
|
160 for act in e4App().getObject("ViewManager").getActions('view'): |
|
161 __saveShortcut(act, "View", prefClass) |
|
162 |
|
163 for act in e4App().getObject("ViewManager").getActions('macro'): |
|
164 __saveShortcut(act, "Macro", prefClass) |
|
165 |
|
166 for act in e4App().getObject("ViewManager").getActions('bookmark'): |
|
167 __saveShortcut(act, "Bookmarks", prefClass) |
|
168 |
|
169 for act in e4App().getObject("ViewManager").getActions('spelling'): |
|
170 __saveShortcut(act, "Spelling", prefClass) |
|
171 |
|
172 actions = e4App().getObject("ViewManager").getActions('window') |
|
173 if actions: |
|
174 for act in actions: |
|
175 __saveShortcut(act, "Window", prefClass) |
|
176 |
|
177 for category, ref in e4App().getPluginObjects(): |
|
178 if hasattr(ref, "getActions"): |
|
179 actions = ref.getActions() |
|
180 for act in actions: |
|
181 __saveShortcut(act, category, prefClass) |
|
182 |
|
183 for act in e4App().getObject("DummyHelpViewer").getActions(): |
|
184 __saveShortcut(act, "HelpViewer", prefClass) |
|
185 |
|
186 def exportShortcuts(fn): |
|
187 """ |
|
188 Module function to export the keyboard shortcuts for the defined QActions. |
|
189 |
|
190 @param fn filename of the export file (string) |
|
191 @return flag indicating success |
|
192 """ |
|
193 try: |
|
194 if fn.lower().endswith("e4kz"): |
|
195 try: |
|
196 import gzip |
|
197 except ImportError: |
|
198 QMessageBox.critical(None, |
|
199 QApplication.translate("Shortcuts", "Export Keyboard Shortcuts"), |
|
200 QApplication.translate("Shortcuts", |
|
201 """Compressed keyboard shortcut files""" |
|
202 """ not supported. The compression library is missing.""")) |
|
203 return 0 |
|
204 f = gzip.open(fn, "wb") |
|
205 else: |
|
206 f = open(fn, "wb") |
|
207 |
|
208 ShortcutsWriter(f).writeXML() |
|
209 |
|
210 f.close() |
|
211 return True |
|
212 except IOError: |
|
213 return False |
|
214 |
|
215 def importShortcuts(fn): |
|
216 """ |
|
217 Module function to import the keyboard shortcuts for the defined E4Actions. |
|
218 |
|
219 @param fn filename of the import file (string) |
|
220 @return flag indicating success |
|
221 """ |
|
222 try: |
|
223 if fn.lower().endswith("kz"): |
|
224 try: |
|
225 import gzip |
|
226 except ImportError: |
|
227 QMessageBox.critical(None, |
|
228 QApplication.translate("Shortcuts", "Import Keyboard Shortcuts"), |
|
229 QApplication.translate("Shortcuts", |
|
230 """Compressed keyboard shortcut files""" |
|
231 """ not supported. The compression library is missing.""")) |
|
232 return False |
|
233 f = gzip.open(fn, "rb") |
|
234 else: |
|
235 f = open(fn, "rb") |
|
236 try: |
|
237 line = f.readline() |
|
238 dtdLine = f.readline() |
|
239 finally: |
|
240 f.close() |
|
241 except IOError: |
|
242 QMessageBox.critical(None, |
|
243 QApplication.translate("Shortcuts", "Import Keyboard Shortcuts"), |
|
244 QApplication.translate("Shortcuts", |
|
245 "<p>The keyboard shortcuts could not be read from file <b>{0}</b>.</p>") |
|
246 .format(fn)) |
|
247 return False |
|
248 |
|
249 if fn.lower().endswith("kz"): |
|
250 # work around for a bug in xmlproc |
|
251 validating = False |
|
252 else: |
|
253 validating = dtdLine.startswith("<!DOCTYPE") |
|
254 parser = make_parser(validating) |
|
255 handler = ShortcutsHandler() |
|
256 er = XMLEntityResolver() |
|
257 eh = XMLErrorHandler() |
|
258 |
|
259 parser.setContentHandler(handler) |
|
260 parser.setEntityResolver(er) |
|
261 parser.setErrorHandler(eh) |
|
262 |
|
263 try: |
|
264 if fn.lower().endswith("kz"): |
|
265 try: |
|
266 import gzip |
|
267 except ImportError: |
|
268 QMessageBox.critical(None, |
|
269 QApplication.translate("Shortcuts", "Import Keyboard Shortcuts"), |
|
270 QApplication.translate("Shortcuts", |
|
271 """Compressed keyboard shortcut files""" |
|
272 """ not supported. The compression library is missing.""")) |
|
273 return False |
|
274 f = gzip.open(fn, "rb") |
|
275 else: |
|
276 f = open(fn, "rb") |
|
277 try: |
|
278 try: |
|
279 parser.parse(f) |
|
280 except UnicodeEncodeError: |
|
281 f.seek(0) |
|
282 buf = cStringIO.StringIO(f.read()) |
|
283 parser.parse(buf) |
|
284 finally: |
|
285 f.close() |
|
286 except IOError: |
|
287 QMessageBox.critical(None, |
|
288 QApplication.translate("Shortcuts", "Import Keyboard Shortcuts"), |
|
289 QApplication.translate("Shortcuts", |
|
290 "<p>The keyboard shortcuts could not be read from file <b>{0}</b>.</p>") |
|
291 .format(fn)) |
|
292 return False |
|
293 |
|
294 except XMLFatalParseError: |
|
295 QMessageBox.critical(None, |
|
296 QApplication.translate("Shortcuts", "Import Keyboard Shortcuts"), |
|
297 QApplication.translate("Shortcuts", |
|
298 "<p>The keyboard shortcuts file <b>{0}</b> has invalid contents.</p>") |
|
299 .format(fn)) |
|
300 eh.showParseMessages() |
|
301 return False |
|
302 |
|
303 eh.showParseMessages() |
|
304 |
|
305 shortcuts = handler.getShortcuts() |
|
306 |
|
307 setActions(shortcuts) |
|
308 |
|
309 saveShortcuts() |
|
310 syncPreferences() |
|
311 |
|
312 return True |
|
313 |
|
314 def __setAction(actions, sdict): |
|
315 """ |
|
316 Private function to write a single keyboard shortcut to the settings. |
|
317 |
|
318 @param actions list of actions to set (list of E4Action) |
|
319 @param sdict dictionary containg accelerator information for one category |
|
320 """ |
|
321 for act in actions: |
|
322 if act.objectName(): |
|
323 try: |
|
324 accel, altAccel = sdict[act.objectName()] |
|
325 act.setShortcut(QKeySequence(accel)) |
|
326 act.setAlternateShortcut(QKeySequence(altAccel)) |
|
327 except KeyError: |
|
328 pass |
|
329 |
|
330 def setActions(shortcuts): |
|
331 """ |
|
332 Module function to set actions based on new format shortcuts file. |
|
333 |
|
334 @param shortcuts dictionary containing the accelerator information |
|
335 read from a XML file |
|
336 """ |
|
337 if shortcuts.has_key("Project"): |
|
338 __setAction(e4App().getObject("Project").getActions(), |
|
339 shortcuts["Project"]) |
|
340 |
|
341 if shortcuts.has_key("General"): |
|
342 __setAction(e4App().getObject("UserInterface").getActions('ui'), |
|
343 shortcuts["General"]) |
|
344 |
|
345 if shortcuts.has_key("Wizards"): |
|
346 __setAction(e4App().getObject("UserInterface").getActions('wizards'), |
|
347 shortcuts["Wizards"]) |
|
348 |
|
349 if shortcuts.has_key("Debug"): |
|
350 __setAction(e4App().getObject("DebugUI").getActions(), |
|
351 shortcuts["Debug"]) |
|
352 |
|
353 if shortcuts.has_key("Edit"): |
|
354 __setAction(e4App().getObject("ViewManager").getActions('edit'), |
|
355 shortcuts["Edit"]) |
|
356 |
|
357 if shortcuts.has_key("File"): |
|
358 __setAction(e4App().getObject("ViewManager").getActions('file'), |
|
359 shortcuts["File"]) |
|
360 |
|
361 if shortcuts.has_key("Search"): |
|
362 __setAction(e4App().getObject("ViewManager").getActions('search'), |
|
363 shortcuts["Search"]) |
|
364 |
|
365 if shortcuts.has_key("View"): |
|
366 __setAction(e4App().getObject("ViewManager").getActions('view'), |
|
367 shortcuts["View"]) |
|
368 |
|
369 if shortcuts.has_key("Macro"): |
|
370 __setAction(e4App().getObject("ViewManager").getActions('macro'), |
|
371 shortcuts["Macro"]) |
|
372 |
|
373 if shortcuts.has_key("Bookmarks"): |
|
374 __setAction(e4App().getObject("ViewManager").getActions('bookmark'), |
|
375 shortcuts["Bookmarks"]) |
|
376 |
|
377 if shortcuts.has_key("Spelling"): |
|
378 __setAction(e4App().getObject("ViewManager").getActions('spelling'), |
|
379 shortcuts["Spelling"]) |
|
380 |
|
381 if shortcuts.has_key("Window"): |
|
382 actions = e4App().getObject("ViewManager").getActions('window') |
|
383 if actions: |
|
384 __setAction(actions, shortcuts["Window"]) |
|
385 |
|
386 for category, ref in e4App().getPluginObjects(): |
|
387 if shortcuts.has_key(category) and hasattr(ref, "getActions"): |
|
388 actions = ref.getActions() |
|
389 __setAction(actions, shortcuts[category]) |
|
390 |
|
391 if shortcuts.has_key("HelpViewer"): |
|
392 __setAction(e4App().getObject("DummyHelpViewer").getActions(), |
|
393 shortcuts["HelpViewer"]) |