|
1 # -*- coding: utf-8 -*- |
|
2 |
|
3 # Copyright (c) 2004 - 2022 Detlev Offenbach <detlev@die-offenbachs.de> |
|
4 # |
|
5 |
|
6 """ |
|
7 Module implementing functions dealing with keyboard shortcuts. |
|
8 """ |
|
9 |
|
10 import contextlib |
|
11 |
|
12 from PyQt6.QtCore import QFile, QIODevice, QCoreApplication |
|
13 from PyQt6.QtGui import QKeySequence |
|
14 |
|
15 from EricWidgets.EricApplication import ericApp |
|
16 from EricWidgets import EricMessageBox |
|
17 |
|
18 from Preferences import Prefs, syncPreferences |
|
19 |
|
20 |
|
21 def __readShortcut(act, category, prefClass): |
|
22 """ |
|
23 Private function to read a single keyboard shortcut from the settings. |
|
24 |
|
25 @param act reference to the action object (EricAction) |
|
26 @param category category the action belongs to (string) |
|
27 @param prefClass preferences class used as the storage area |
|
28 """ |
|
29 if act.objectName(): |
|
30 accel = prefClass.settings.value( |
|
31 "Shortcuts/{0}/{1}/Accel".format(category, act.objectName())) |
|
32 if accel is not None: |
|
33 act.setShortcut(QKeySequence(accel)) |
|
34 accel = prefClass.settings.value( |
|
35 "Shortcuts/{0}/{1}/AltAccel".format(category, act.objectName())) |
|
36 if accel is not None: |
|
37 act.setAlternateShortcut(QKeySequence(accel), removeEmpty=True) |
|
38 |
|
39 |
|
40 def readShortcuts(prefClass=Prefs, helpViewer=None, pluginName=None): |
|
41 """ |
|
42 Module function to read the keyboard shortcuts for the defined QActions. |
|
43 |
|
44 @param prefClass preferences class used as the storage area |
|
45 @param helpViewer reference to the help window object |
|
46 @param pluginName name of the plugin for which to load shortcuts |
|
47 (string) |
|
48 """ |
|
49 if helpViewer is None and pluginName is None: |
|
50 for act in ericApp().getObject("Project").getActions(): |
|
51 __readShortcut(act, "Project", prefClass) |
|
52 |
|
53 for act in ericApp().getObject("UserInterface").getActions('ui'): |
|
54 __readShortcut(act, "General", prefClass) |
|
55 |
|
56 for act in ericApp().getObject("UserInterface").getActions('wizards'): |
|
57 __readShortcut(act, "Wizards", prefClass) |
|
58 |
|
59 for act in ericApp().getObject("DebugUI").getActions(): |
|
60 __readShortcut(act, "Debug", prefClass) |
|
61 |
|
62 for act in ericApp().getObject("ViewManager").getActions('edit'): |
|
63 __readShortcut(act, "Edit", prefClass) |
|
64 |
|
65 for act in ericApp().getObject("ViewManager").getActions('file'): |
|
66 __readShortcut(act, "File", prefClass) |
|
67 |
|
68 for act in ericApp().getObject("ViewManager").getActions('search'): |
|
69 __readShortcut(act, "Search", prefClass) |
|
70 |
|
71 for act in ericApp().getObject("ViewManager").getActions('view'): |
|
72 __readShortcut(act, "View", prefClass) |
|
73 |
|
74 for act in ericApp().getObject("ViewManager").getActions('macro'): |
|
75 __readShortcut(act, "Macro", prefClass) |
|
76 |
|
77 for act in ericApp().getObject("ViewManager").getActions('bookmark'): |
|
78 __readShortcut(act, "Bookmarks", prefClass) |
|
79 |
|
80 for act in ericApp().getObject("ViewManager").getActions('spelling'): |
|
81 __readShortcut(act, "Spelling", prefClass) |
|
82 |
|
83 actions = ericApp().getObject("ViewManager").getActions('window') |
|
84 if actions: |
|
85 for act in actions: |
|
86 __readShortcut(act, "Window", prefClass) |
|
87 |
|
88 for category, ref in ericApp().getPluginObjects(): |
|
89 if hasattr(ref, "getActions"): |
|
90 actions = ref.getActions() |
|
91 for act in actions: |
|
92 __readShortcut(act, category, prefClass) |
|
93 |
|
94 if helpViewer is not None: |
|
95 helpViewerCategory = helpViewer.getActionsCategory() |
|
96 for act in helpViewer.getActions(): |
|
97 __readShortcut(act, helpViewerCategory, prefClass) |
|
98 |
|
99 if pluginName is not None: |
|
100 with contextlib.suppress(KeyError): |
|
101 ref = ericApp().getPluginObject(pluginName) |
|
102 if hasattr(ref, "getActions"): |
|
103 actions = ref.getActions() |
|
104 for act in actions: |
|
105 __readShortcut(act, pluginName, prefClass) |
|
106 |
|
107 |
|
108 def __saveShortcut(act, category, prefClass): |
|
109 """ |
|
110 Private function to write a single keyboard shortcut to the settings. |
|
111 |
|
112 @param act reference to the action object (EricAction) |
|
113 @param category category the action belongs to (string) |
|
114 @param prefClass preferences class used as the storage area |
|
115 """ |
|
116 if act.objectName(): |
|
117 prefClass.settings.setValue( |
|
118 "Shortcuts/{0}/{1}/Accel".format(category, act.objectName()), |
|
119 act.shortcut().toString()) |
|
120 prefClass.settings.setValue( |
|
121 "Shortcuts/{0}/{1}/AltAccel".format(category, act.objectName()), |
|
122 act.alternateShortcut().toString()) |
|
123 |
|
124 |
|
125 def saveShortcuts(prefClass=Prefs, helpViewer=None): |
|
126 """ |
|
127 Module function to write the keyboard shortcuts for the defined QActions. |
|
128 |
|
129 @param prefClass preferences class used as the storage area |
|
130 @param helpViewer reference to the help window object |
|
131 """ |
|
132 if helpViewer is None: |
|
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 ericApp().getObject("Project").getActions(): |
|
140 __saveShortcut(act, "Project", prefClass) |
|
141 |
|
142 for act in ericApp().getObject("UserInterface").getActions('ui'): |
|
143 __saveShortcut(act, "General", prefClass) |
|
144 |
|
145 for act in ericApp().getObject("UserInterface").getActions('wizards'): |
|
146 __saveShortcut(act, "Wizards", prefClass) |
|
147 |
|
148 for act in ericApp().getObject("DebugUI").getActions(): |
|
149 __saveShortcut(act, "Debug", prefClass) |
|
150 |
|
151 for act in ericApp().getObject("ViewManager").getActions('edit'): |
|
152 __saveShortcut(act, "Edit", prefClass) |
|
153 |
|
154 for act in ericApp().getObject("ViewManager").getActions('file'): |
|
155 __saveShortcut(act, "File", prefClass) |
|
156 |
|
157 for act in ericApp().getObject("ViewManager").getActions('search'): |
|
158 __saveShortcut(act, "Search", prefClass) |
|
159 |
|
160 for act in ericApp().getObject("ViewManager").getActions('view'): |
|
161 __saveShortcut(act, "View", prefClass) |
|
162 |
|
163 for act in ericApp().getObject("ViewManager").getActions('macro'): |
|
164 __saveShortcut(act, "Macro", prefClass) |
|
165 |
|
166 for act in ericApp().getObject("ViewManager").getActions('bookmark'): |
|
167 __saveShortcut(act, "Bookmarks", prefClass) |
|
168 |
|
169 for act in ericApp().getObject("ViewManager").getActions('spelling'): |
|
170 __saveShortcut(act, "Spelling", prefClass) |
|
171 |
|
172 actions = ericApp().getObject("ViewManager").getActions('window') |
|
173 if actions: |
|
174 for act in actions: |
|
175 __saveShortcut(act, "Window", prefClass) |
|
176 |
|
177 for category, ref in ericApp().getPluginObjects(): |
|
178 if hasattr(ref, "getActions"): |
|
179 actions = ref.getActions() |
|
180 for act in actions: |
|
181 __saveShortcut(act, category, prefClass) |
|
182 |
|
183 else: |
|
184 helpViewerCategory = helpViewer.getActionsCategory() |
|
185 |
|
186 # step 1: clear all previously saved shortcuts |
|
187 prefClass.settings.beginGroup( |
|
188 "Shortcuts/{0}".format(helpViewerCategory) |
|
189 ) |
|
190 prefClass.settings.remove("") |
|
191 prefClass.settings.endGroup() |
|
192 |
|
193 # step 2: save the shortcuts |
|
194 for act in helpViewer.getActions(): |
|
195 __saveShortcut(act, helpViewerCategory, prefClass) |
|
196 |
|
197 |
|
198 def exportShortcuts(fn, helpViewer=None): |
|
199 """ |
|
200 Module function to export the keyboard shortcuts for the defined QActions. |
|
201 |
|
202 @param fn filename of the export file |
|
203 @type str |
|
204 @param helpViewer reference to the help window object |
|
205 @type WebBrowserWindow |
|
206 """ |
|
207 # let the plugin manager create on demand plugin objects |
|
208 pm = ericApp().getObject("PluginManager") |
|
209 pm.initOnDemandPlugins() |
|
210 |
|
211 from .ShortcutsFile import ShortcutsFile |
|
212 shortcutsFile = ShortcutsFile() |
|
213 shortcutsFile.writeFile(fn, helpViewer) |
|
214 |
|
215 |
|
216 def importShortcuts(fn, helpViewer=None): |
|
217 """ |
|
218 Module function to import the keyboard shortcuts for the defined actions. |
|
219 |
|
220 @param fn filename of the import file |
|
221 @type str |
|
222 @param helpViewer reference to the help window object |
|
223 @type WebBrowserWindow |
|
224 """ |
|
225 # let the plugin manager create on demand plugin objects |
|
226 pm = ericApp().getObject("PluginManager") |
|
227 pm.initOnDemandPlugins() |
|
228 |
|
229 if fn.endswith(".ekj"): |
|
230 # new JSON based file |
|
231 from .ShortcutsFile import ShortcutsFile |
|
232 shortcutsFile = ShortcutsFile() |
|
233 shortcuts = shortcutsFile.readFile(fn) |
|
234 if shortcuts: |
|
235 setActions(shortcuts, helpViewer=helpViewer) |
|
236 saveShortcuts() |
|
237 syncPreferences() |
|
238 else: |
|
239 # old XML based file |
|
240 f = QFile(fn) |
|
241 if f.open(QIODevice.OpenModeFlag.ReadOnly): |
|
242 from EricXML.ShortcutsReader import ShortcutsReader |
|
243 reader = ShortcutsReader(f) |
|
244 reader.readXML() |
|
245 f.close() |
|
246 if not reader.hasError(): |
|
247 shortcuts = reader.getShortcuts() |
|
248 setActions(shortcuts, helpViewer=helpViewer) |
|
249 saveShortcuts() |
|
250 syncPreferences() |
|
251 else: |
|
252 EricMessageBox.critical( |
|
253 None, |
|
254 QCoreApplication.translate( |
|
255 "Shortcuts", "Import Keyboard Shortcuts"), |
|
256 QCoreApplication.translate( |
|
257 "Shortcuts", |
|
258 "<p>The keyboard shortcuts file <b>{0}</b> could not be" |
|
259 " read.</p>") |
|
260 .format(fn)) |
|
261 |
|
262 |
|
263 def __setAction(actions, shortcutsDict): |
|
264 """ |
|
265 Private function to set a single keyboard shortcut category shortcuts. |
|
266 |
|
267 @param actions list of actions to set |
|
268 @type list of EricAction |
|
269 @param shortcutsDict dictionary containing accelerator information for |
|
270 one category |
|
271 @type dict |
|
272 """ |
|
273 for act in actions: |
|
274 if act.objectName(): |
|
275 with contextlib.suppress(KeyError): |
|
276 accel, altAccel = shortcutsDict[act.objectName()] |
|
277 act.setShortcut(QKeySequence(accel)) |
|
278 act.setAlternateShortcut(QKeySequence(altAccel), |
|
279 removeEmpty=True) |
|
280 |
|
281 |
|
282 def setActions(shortcuts, helpViewer=None): |
|
283 """ |
|
284 Module function to set actions based on the imported shortcuts file. |
|
285 |
|
286 @param shortcuts dictionary containing the accelerator information |
|
287 read from a JSON or XML file |
|
288 @type dict |
|
289 @param helpViewer reference to the help window object |
|
290 @type WebBrowserWindow |
|
291 """ |
|
292 if helpViewer is None: |
|
293 if "Project" in shortcuts: |
|
294 __setAction( |
|
295 ericApp().getObject("Project").getActions(), |
|
296 shortcuts["Project"]) |
|
297 |
|
298 if "General" in shortcuts: |
|
299 __setAction( |
|
300 ericApp().getObject("UserInterface").getActions('ui'), |
|
301 shortcuts["General"]) |
|
302 |
|
303 if "Wizards" in shortcuts: |
|
304 __setAction( |
|
305 ericApp().getObject("UserInterface").getActions('wizards'), |
|
306 shortcuts["Wizards"]) |
|
307 |
|
308 if "Debug" in shortcuts: |
|
309 __setAction( |
|
310 ericApp().getObject("DebugUI").getActions(), |
|
311 shortcuts["Debug"]) |
|
312 |
|
313 if "Edit" in shortcuts: |
|
314 __setAction( |
|
315 ericApp().getObject("ViewManager").getActions('edit'), |
|
316 shortcuts["Edit"]) |
|
317 |
|
318 if "File" in shortcuts: |
|
319 __setAction( |
|
320 ericApp().getObject("ViewManager").getActions('file'), |
|
321 shortcuts["File"]) |
|
322 |
|
323 if "Search" in shortcuts: |
|
324 __setAction( |
|
325 ericApp().getObject("ViewManager").getActions('search'), |
|
326 shortcuts["Search"]) |
|
327 |
|
328 if "View" in shortcuts: |
|
329 __setAction( |
|
330 ericApp().getObject("ViewManager").getActions('view'), |
|
331 shortcuts["View"]) |
|
332 |
|
333 if "Macro" in shortcuts: |
|
334 __setAction( |
|
335 ericApp().getObject("ViewManager").getActions('macro'), |
|
336 shortcuts["Macro"]) |
|
337 |
|
338 if "Bookmarks" in shortcuts: |
|
339 __setAction( |
|
340 ericApp().getObject("ViewManager").getActions('bookmark'), |
|
341 shortcuts["Bookmarks"]) |
|
342 |
|
343 if "Spelling" in shortcuts: |
|
344 __setAction( |
|
345 ericApp().getObject("ViewManager").getActions('spelling'), |
|
346 shortcuts["Spelling"]) |
|
347 |
|
348 if "Window" in shortcuts: |
|
349 actions = ericApp().getObject("ViewManager").getActions('window') |
|
350 if actions: |
|
351 __setAction(actions, shortcuts["Window"]) |
|
352 |
|
353 for category, ref in ericApp().getPluginObjects(): |
|
354 if category in shortcuts and hasattr(ref, "getActions"): |
|
355 actions = ref.getActions() |
|
356 __setAction(actions, shortcuts[category]) |
|
357 |
|
358 else: |
|
359 category = helpViewer.getActionsCategory() |
|
360 if category in shortcuts: |
|
361 __setAction(helpViewer.getActions(), shortcuts[category]) |