|
1 # -*- coding: utf-8 -*- |
|
2 |
|
3 # Copyright (c) 2021 Detlev Offenbach <detlev@die-offenbachs.de> |
|
4 # |
|
5 |
|
6 """ |
|
7 Module implementing a class representing the shortcuts JSON file. |
|
8 """ |
|
9 |
|
10 import json |
|
11 import time |
|
12 import typing |
|
13 |
|
14 from PyQt5.QtCore import QObject |
|
15 |
|
16 from E5Gui import E5MessageBox |
|
17 from E5Gui.E5OverrideCursor import E5OverridenCursor |
|
18 from E5Gui.E5Application import e5App |
|
19 |
|
20 import Preferences |
|
21 |
|
22 HelpViewer = typing.TypeVar("WebBrowserWindow") |
|
23 |
|
24 |
|
25 class ShortcutsFile(QObject): |
|
26 """ |
|
27 Class representing the shortcuts JSON file. |
|
28 """ |
|
29 def __init__(self, parent: QObject = None): |
|
30 """ |
|
31 Constructor |
|
32 |
|
33 @param parent reference to the parent object (defaults to None) |
|
34 @type QObject (optional) |
|
35 """ |
|
36 super(ShortcutsFile, self).__init__(parent) |
|
37 |
|
38 def __addActionsToDict(self, category: str, actions: list, |
|
39 actionsDict: dict): |
|
40 """ |
|
41 Private method to add a list of actions to the actions dictionary. |
|
42 |
|
43 @param category category of the actions |
|
44 @type str |
|
45 @param actions list of actions |
|
46 @type list of QAction |
|
47 @param actionsDict reference to the actions dictionary to be modified |
|
48 @type dict |
|
49 """ |
|
50 if actions: |
|
51 if category not in actionsDict: |
|
52 actionsDict[category] = {} |
|
53 for act in actions: |
|
54 if act.objectName(): |
|
55 # shortcuts are only exported, if their objectName is set |
|
56 actionsDict[category][act.objectName()] = ( |
|
57 act.shortcut().toString(), |
|
58 act.alternateShortcut().toString() |
|
59 ) |
|
60 |
|
61 def writeFile(self, filename: str, helpViewer: HelpViewer = None) -> bool: |
|
62 """ |
|
63 Public method to write the shortcuts data to a shortcuts JSON file. |
|
64 |
|
65 @param filename name of the shortcuts file |
|
66 @type str |
|
67 @param helpViewer reference to the help window object |
|
68 @type WebBrowserWindow |
|
69 @return flag indicating a successful write |
|
70 @rtype bool |
|
71 """ |
|
72 actionsDict = {} |
|
73 |
|
74 # step 1: collect all the shortcuts |
|
75 if helpViewer is None: |
|
76 self.__addActionsToDict( |
|
77 "Project", |
|
78 e5App().getObject("Project").getActions(), |
|
79 actionsDict |
|
80 ) |
|
81 self.__addActionsToDict( |
|
82 "General", |
|
83 e5App().getObject("UserInterface").getActions('ui'), |
|
84 actionsDict |
|
85 ) |
|
86 self.__addActionsToDict( |
|
87 "Wizards", |
|
88 e5App().getObject("UserInterface").getActions('wizards'), |
|
89 actionsDict |
|
90 ) |
|
91 self.__addActionsToDict( |
|
92 "Debug", |
|
93 e5App().getObject("DebugUI").getActions(), |
|
94 actionsDict |
|
95 ) |
|
96 self.__addActionsToDict( |
|
97 "Edit", |
|
98 e5App().getObject("ViewManager").getActions('edit'), |
|
99 actionsDict |
|
100 ) |
|
101 self.__addActionsToDict( |
|
102 "File", |
|
103 e5App().getObject("ViewManager").getActions('file'), |
|
104 actionsDict |
|
105 ) |
|
106 self.__addActionsToDict( |
|
107 "Search", |
|
108 e5App().getObject("ViewManager").getActions('search'), |
|
109 actionsDict |
|
110 ) |
|
111 self.__addActionsToDict( |
|
112 "View", |
|
113 e5App().getObject("ViewManager").getActions('view'), |
|
114 actionsDict |
|
115 ) |
|
116 self.__addActionsToDict( |
|
117 "Macro", |
|
118 e5App().getObject("ViewManager").getActions('macro'), |
|
119 actionsDict |
|
120 ) |
|
121 self.__addActionsToDict( |
|
122 "Bookmarks", |
|
123 e5App().getObject("ViewManager").getActions('bookmark'), |
|
124 actionsDict |
|
125 ) |
|
126 self.__addActionsToDict( |
|
127 "Spelling", |
|
128 e5App().getObject("ViewManager").getActions('spelling'), |
|
129 actionsDict |
|
130 ) |
|
131 self.__addActionsToDict( |
|
132 "Window", |
|
133 e5App().getObject("ViewManager").getActions('window'), |
|
134 actionsDict |
|
135 ) |
|
136 |
|
137 for category, ref in e5App().getPluginObjects(): |
|
138 if hasattr(ref, "getActions"): |
|
139 self.__addActionsToDict( |
|
140 category, ref.getActions(), actionsDict |
|
141 ) |
|
142 |
|
143 else: |
|
144 self.__addActionsToDict( |
|
145 helpViewer.getActionsCategory(), |
|
146 helpViewer.getActions(), |
|
147 actionsDict |
|
148 ) |
|
149 |
|
150 # step 2: assemble the data structure to be written |
|
151 shortcutsDict = {} |
|
152 # step 2.0: header |
|
153 shortcutsDict["header"] = { |
|
154 "comment": "eric keyboard shortcuts file", |
|
155 "saved": time.strftime('%Y-%m-%d, %H:%M:%S'), |
|
156 "author": Preferences.getUser("Email"), |
|
157 } |
|
158 # step 2.1: keyboard shortcuts |
|
159 shortcutsDict["shortcuts"] = actionsDict |
|
160 |
|
161 try: |
|
162 jsonString = json.dumps(shortcutsDict, indent=2) |
|
163 with open(filename, "w") as f: |
|
164 f.write(jsonString) |
|
165 except (TypeError, EnvironmentError) as err: |
|
166 with E5OverridenCursor(): |
|
167 E5MessageBox.critical( |
|
168 None, |
|
169 self.tr("Export Keyboard Shortcuts"), |
|
170 self.tr( |
|
171 "<p>The keyboard shortcuts file <b>{0}</b> could not" |
|
172 " be written.</p><p>Reason: {1}</p>" |
|
173 ).format(filename, str(err)) |
|
174 ) |
|
175 return False |
|
176 |
|
177 return True |
|
178 |
|
179 def readFile(self, filename: str) -> bool: |
|
180 """ |
|
181 Public method to read the shortcuts data from a shortcuts JSON file. |
|
182 |
|
183 @param filename name of the shortcuts file |
|
184 @type str |
|
185 @return Dictionary of dictionaries of shortcuts. The keys of the |
|
186 dictionary are the shortcuts categories, the values are |
|
187 dictionaries. These dictionaries have the shortcut name as their |
|
188 key and a tuple of accelerators as their value. |
|
189 @rtype dict |
|
190 """ |
|
191 try: |
|
192 with open(filename, "r") as f: |
|
193 jsonString = f.read() |
|
194 shortcutsDict = json.loads(jsonString) |
|
195 except (EnvironmentError, json.JSONDecodeError) as err: |
|
196 E5MessageBox.critical( |
|
197 None, |
|
198 self.tr("Import Keyboard Shortcuts"), |
|
199 self.tr( |
|
200 "<p>The keyboard shortcuts file <b>{0}</b> could not be" |
|
201 " read.</p><p>Reason: {1}</p>" |
|
202 ).format(filename, str(err)) |
|
203 ) |
|
204 return {} |
|
205 |
|
206 return shortcutsDict["shortcuts"] |