PluginToolGenerateHash.py

branch
eric7
changeset 61
6fc29f5292d3
parent 59
992bee3beceb
child 62
3d0bb45398c6
equal deleted inserted replaced
60:d3a8515784ec 61:6fc29f5292d3
41 41
42 class ToolGenerateHashPlugin(QObject): 42 class ToolGenerateHashPlugin(QObject):
43 """ 43 """
44 Class implementing the 'Generate Hash' tool plug-in. 44 Class implementing the 'Generate Hash' tool plug-in.
45 """ 45 """
46
46 Hashes = [ 47 Hashes = [
47 h for h in ("md5", "sha1", "sha224", "sha256", "sha384", "sha512", 48 h
48 "sha3_224", "sha3_256", "sha3_384", "sha3_512") 49 for h in (
50 "md5",
51 "sha1",
52 "sha224",
53 "sha256",
54 "sha384",
55 "sha512",
56 "sha3_224",
57 "sha3_256",
58 "sha3_384",
59 "sha3_512",
60 )
49 if h in hashlib.algorithms_guaranteed 61 if h in hashlib.algorithms_guaranteed
50 ] 62 ]
51 63
52 def __init__(self, ui): 64 def __init__(self, ui):
53 """ 65 """
54 Constructor 66 Constructor
55 67
56 @param ui reference to the user interface object (UI.UserInterface) 68 @param ui reference to the user interface object (UI.UserInterface)
57 """ 69 """
58 super().__init__(ui) 70 super().__init__(ui)
59 self.__ui = ui 71 self.__ui = ui
60 72
61 self.__translator = None 73 self.__translator = None
62 self.__loadTranslator() 74 self.__loadTranslator()
63 75
64 self.__initMenus() 76 self.__initMenus()
65 77
66 self.__editors = {} 78 self.__editors = {}
67 self.__mainActions = [] 79 self.__mainActions = []
68 80
69 def activate(self): 81 def activate(self):
70 """ 82 """
71 Public method to activate this plugin. 83 Public method to activate this plugin.
72 84
73 @return tuple of None and activation status 85 @return tuple of None and activation status
74 @rtype bool 86 @rtype bool
75 """ 87 """
76 global error 88 global error
77 error = "" # clear previous error 89 error = "" # clear previous error
78 90
79 self.__ui.showMenu.connect(self.__populateMenu) 91 self.__ui.showMenu.connect(self.__populateMenu)
80 92
81 menu = self.__ui.getMenu("plugin_tools") 93 menu = self.__ui.getMenu("plugin_tools")
82 if menu is not None: 94 if menu is not None:
83 if not menu.isEmpty(): 95 if not menu.isEmpty():
84 act = menu.addSeparator() 96 act = menu.addSeparator()
85 self.__mainActions.append(act) 97 self.__mainActions.append(act)
86 act = menu.addMenu(self.__fileMenu) 98 act = menu.addMenu(self.__fileMenu)
87 self.__mainActions.append(act) 99 self.__mainActions.append(act)
88 act = menu.addMenu(self.__dirMenu) 100 act = menu.addMenu(self.__dirMenu)
89 self.__mainActions.append(act) 101 self.__mainActions.append(act)
90 102
91 ericApp().getObject("ViewManager").editorOpenedEd.connect( 103 ericApp().getObject("ViewManager").editorOpenedEd.connect(self.__editorOpened)
92 self.__editorOpened) 104 ericApp().getObject("ViewManager").editorClosedEd.connect(self.__editorClosed)
93 ericApp().getObject("ViewManager").editorClosedEd.connect( 105
94 self.__editorClosed)
95
96 for editor in ericApp().getObject("ViewManager").getOpenEditors(): 106 for editor in ericApp().getObject("ViewManager").getOpenEditors():
97 self.__editorOpened(editor) 107 self.__editorOpened(editor)
98 108
99 return None, True 109 return None, True
100 110
101 def deactivate(self): 111 def deactivate(self):
102 """ 112 """
103 Public method to deactivate this plugin. 113 Public method to deactivate this plugin.
104 """ 114 """
105 self.__ui.showMenu.disconnect(self.__populateMenu) 115 self.__ui.showMenu.disconnect(self.__populateMenu)
106 116
107 menu = self.__ui.getMenu("plugin_tools") 117 menu = self.__ui.getMenu("plugin_tools")
108 if menu is not None: 118 if menu is not None:
109 for act in self.__mainActions: 119 for act in self.__mainActions:
110 menu.removeAction(act) 120 menu.removeAction(act)
111 self.__mainActions = [] 121 self.__mainActions = []
112 122
113 ericApp().getObject("ViewManager").editorOpenedEd.disconnect( 123 ericApp().getObject("ViewManager").editorOpenedEd.disconnect(
114 self.__editorOpened) 124 self.__editorOpened
125 )
115 ericApp().getObject("ViewManager").editorClosedEd.disconnect( 126 ericApp().getObject("ViewManager").editorClosedEd.disconnect(
116 self.__editorClosed) 127 self.__editorClosed
117 128 )
129
118 for editor, acts in self.__editors.items(): 130 for editor, acts in self.__editors.items():
119 editor.showMenu.disconnect(self.__editorShowMenu) 131 editor.showMenu.disconnect(self.__editorShowMenu)
120 menu = editor.getMenu("Tools") 132 menu = editor.getMenu("Tools")
121 if menu is not None: 133 if menu is not None:
122 for act in acts: 134 for act in acts:
123 menu.removeAction(act) 135 menu.removeAction(act)
124 self.__editors = {} 136 self.__editors = {}
125 137
126 def __loadTranslator(self): 138 def __loadTranslator(self):
127 """ 139 """
128 Private method to load the translation file. 140 Private method to load the translation file.
129 """ 141 """
130 if self.__ui is not None: 142 if self.__ui is not None:
131 loc = self.__ui.getLocale() 143 loc = self.__ui.getLocale()
132 if loc and loc != "C": 144 if loc and loc != "C":
133 locale_dir = os.path.join( 145 locale_dir = os.path.join(
134 os.path.dirname(__file__), "ToolGenerateHash", "i18n") 146 os.path.dirname(__file__), "ToolGenerateHash", "i18n"
147 )
135 translation = "generatehash_{0}".format(loc) 148 translation = "generatehash_{0}".format(loc)
136 translator = QTranslator(None) 149 translator = QTranslator(None)
137 loaded = translator.load(translation, locale_dir) 150 loaded = translator.load(translation, locale_dir)
138 if loaded: 151 if loaded:
139 self.__translator = translator 152 self.__translator = translator
140 ericApp().installTranslator(self.__translator) 153 ericApp().installTranslator(self.__translator)
141 else: 154 else:
142 print("Warning: translation file '{0}' could not be" 155 print(
143 " loaded.".format(translation)) 156 "Warning: translation file '{0}' could not be"
157 " loaded.".format(translation)
158 )
144 print("Using default.") 159 print("Using default.")
145 160
146 def __initMenus(self): 161 def __initMenus(self):
147 """ 162 """
148 Private method to initialize the hash generation menus. 163 Private method to initialize the hash generation menus.
149 """ 164 """
150 self.__fileMenu = QMenu(self.tr("Generate File Hash")) 165 self.__fileMenu = QMenu(self.tr("Generate File Hash"))
151 for hashName in self.Hashes: 166 for hashName in self.Hashes:
152 self.__fileMenu.addAction( 167 self.__fileMenu.addAction(hashName.upper().replace("_", ":")).setData(
153 hashName.upper().replace("_", ":")).setData(hashName) 168 hashName
169 )
154 self.__fileMenu.setEnabled(False) 170 self.__fileMenu.setEnabled(False)
155 self.__fileMenu.triggered.connect(self.__hashFile) 171 self.__fileMenu.triggered.connect(self.__hashFile)
156 172
157 self.__dirMenu = QMenu(self.tr("Generate Directory Hash")) 173 self.__dirMenu = QMenu(self.tr("Generate Directory Hash"))
158 for hashName in self.Hashes: 174 for hashName in self.Hashes:
159 self.__dirMenu.addAction( 175 self.__dirMenu.addAction(hashName.upper().replace("_", ":")).setData(
160 hashName.upper().replace("_", ":")).setData(hashName) 176 hashName
177 )
161 self.__dirMenu.setEnabled(False) 178 self.__dirMenu.setEnabled(False)
162 self.__dirMenu.triggered.connect(self.__hashDirectory) 179 self.__dirMenu.triggered.connect(self.__hashDirectory)
163 180
164 def __populateMenu(self, name, menu): 181 def __populateMenu(self, name, menu):
165 """ 182 """
166 Private slot to populate the tools menu with our entries. 183 Private slot to populate the tools menu with our entries.
167 184
168 @param name name of the menu 185 @param name name of the menu
169 @type str 186 @type str
170 @param menu reference to the menu to be populated 187 @param menu reference to the menu to be populated
171 @type QMenu 188 @type QMenu
172 """ 189 """
173 if name not in ["Tools", "PluginTools"]: 190 if name not in ["Tools", "PluginTools"]:
174 return 191 return
175 192
176 editor = ericApp().getObject("ViewManager").activeWindow() 193 editor = ericApp().getObject("ViewManager").activeWindow()
177 194
178 if name == "Tools": 195 if name == "Tools":
179 if not menu.isEmpty(): 196 if not menu.isEmpty():
180 menu.addSeparator() 197 menu.addSeparator()
181 198
182 act = menu.addMenu(self.__fileMenu) 199 act = menu.addMenu(self.__fileMenu)
183 act.setEnabled(editor is not None) 200 act.setEnabled(editor is not None)
184 act = menu.addMenu(self.__dirMenu) 201 act = menu.addMenu(self.__dirMenu)
185 act.setEnabled(editor is not None) 202 act.setEnabled(editor is not None)
186 elif name == "PluginTools" and self.__mainActions: 203 elif name == "PluginTools" and self.__mainActions:
187 self.__mainActions[-2].setEnabled(editor is not None) 204 self.__mainActions[-2].setEnabled(editor is not None)
188 self.__mainActions[-1].setEnabled(editor is not None) 205 self.__mainActions[-1].setEnabled(editor is not None)
189 206
190 def __editorOpened(self, editor): 207 def __editorOpened(self, editor):
191 """ 208 """
192 Private slot called, when a new editor was opened. 209 Private slot called, when a new editor was opened.
193 210
194 @param editor reference to the new editor 211 @param editor reference to the new editor
195 @type Editor 212 @type Editor
196 """ 213 """
197 menu = editor.getMenu("Tools") 214 menu = editor.getMenu("Tools")
198 if menu is not None: 215 if menu is not None:
203 act = menu.addMenu(self.__fileMenu) 220 act = menu.addMenu(self.__fileMenu)
204 self.__editors[editor].append(act) 221 self.__editors[editor].append(act)
205 act = menu.addMenu(self.__dirMenu) 222 act = menu.addMenu(self.__dirMenu)
206 self.__editors[editor].append(act) 223 self.__editors[editor].append(act)
207 editor.showMenu.connect(self.__editorShowMenu) 224 editor.showMenu.connect(self.__editorShowMenu)
208 225
209 self.__fileMenu.setEnabled(True) 226 self.__fileMenu.setEnabled(True)
210 self.__dirMenu.setEnabled(True) 227 self.__dirMenu.setEnabled(True)
211 228
212 def __editorClosed(self, editor): 229 def __editorClosed(self, editor):
213 """ 230 """
214 Private slot called, when an editor was closed. 231 Private slot called, when an editor was closed.
215 232
216 @param editor reference to the editor 233 @param editor reference to the editor
217 @type Editor 234 @type Editor
218 """ 235 """
219 with contextlib.suppress(KeyError): 236 with contextlib.suppress(KeyError):
220 del self.__editors[editor] 237 del self.__editors[editor]
221 if not self.__editors: 238 if not self.__editors:
222 self.__fileMenu.setEnabled(False) 239 self.__fileMenu.setEnabled(False)
223 self.__dirMenu.setEnabled(False) 240 self.__dirMenu.setEnabled(False)
224 241
225 def __editorShowMenu(self, menuName, menu, editor): 242 def __editorShowMenu(self, menuName, menu, editor):
226 """ 243 """
227 Private slot called, when the the editor context menu or a submenu is 244 Private slot called, when the the editor context menu or a submenu is
228 about to be shown. 245 about to be shown.
229 246
230 @param menuName name of the menu to be shown 247 @param menuName name of the menu to be shown
231 @type str 248 @type str
232 @param menu reference to the menu 249 @param menu reference to the menu
233 @type QMenu 250 @type QMenu
234 @param editor reference to the editor 251 @param editor reference to the editor
235 @type Editor 252 @type Editor
236 """ 253 """
237 if ( 254 if menuName == "Tools" and self.__fileMenu.menuAction() not in menu.actions():
238 menuName == "Tools" and
239 self.__fileMenu.menuAction() not in menu.actions()
240 ):
241 # Re-add our menu 255 # Re-add our menu
242 self.__editors[editor] = [] 256 self.__editors[editor] = []
243 if not menu.isEmpty(): 257 if not menu.isEmpty():
244 act = menu.addSeparator() 258 act = menu.addSeparator()
245 self.__editors[editor].append(act) 259 self.__editors[editor].append(act)
246 act = menu.addMenu(self.__fileMenu) 260 act = menu.addMenu(self.__fileMenu)
247 self.__editors[editor].append(act) 261 self.__editors[editor].append(act)
248 act = menu.addMenu(self.__dirMenu) 262 act = menu.addMenu(self.__dirMenu)
249 self.__editors[editor].append(act) 263 self.__editors[editor].append(act)
250 264
251 self.__fileMenu.setEnabled(True) 265 self.__fileMenu.setEnabled(True)
252 self.__dirMenu.setEnabled(True) 266 self.__dirMenu.setEnabled(True)
253 267
254 def __insertHash(self, hashStr): 268 def __insertHash(self, hashStr):
255 """ 269 """
256 Private method to insert the generated hash string. 270 Private method to insert the generated hash string.
257 271
258 @param hashStr hash string 272 @param hashStr hash string
259 @type str 273 @type str
260 """ 274 """
261 if hashStr: 275 if hashStr:
262 editor = ericApp().getObject("ViewManager").activeWindow() 276 editor = ericApp().getObject("ViewManager").activeWindow()
263 line, index = editor.getCursorPosition() 277 line, index = editor.getCursorPosition()
264 # It should be done this way to allow undo 278 # It should be done this way to allow undo
265 editor.beginUndoAction() 279 editor.beginUndoAction()
266 editor.insertAt(hashStr, line, index) 280 editor.insertAt(hashStr, line, index)
267 editor.endUndoAction() 281 editor.endUndoAction()
268 282
269 @pyqtSlot(QAction) 283 @pyqtSlot(QAction)
270 def __hashFile(self, act): 284 def __hashFile(self, act):
271 """ 285 """
272 Private slot to generate the hash for a file. 286 Private slot to generate the hash for a file.
273 287
274 @param act reference to the action that was triggered 288 @param act reference to the action that was triggered
275 @type QAction 289 @type QAction
276 """ 290 """
277 if act is None: 291 if act is None:
278 return 292 return
279 293
280 name = EricFileDialog.getOpenFileName( 294 name = EricFileDialog.getOpenFileName(self.__ui, self.tr("Generate File Hash"))
281 self.__ui,
282 self.tr("Generate File Hash"))
283 if name: 295 if name:
284 try: 296 try:
285 with open(name, "rb") as f: 297 with open(name, "rb") as f:
286 hashStr = hashlib.new(act.data(), f.read()).hexdigest() 298 hashStr = hashlib.new(act.data(), f.read()).hexdigest()
287 except OSError as err: 299 except OSError as err:
288 EricMessageBox.critical( 300 EricMessageBox.critical(
289 self.__ui, 301 self.__ui,
290 self.tr("Generate File Hash"), 302 self.tr("Generate File Hash"),
291 self.tr("""<p>The hash for <b>{0}</b> could not""" 303 self.tr(
292 """ be generated.</p><p>Reason: {1}</p>""") 304 """<p>The hash for <b>{0}</b> could not"""
293 .format(name, str(err)) 305 """ be generated.</p><p>Reason: {1}</p>"""
306 ).format(name, str(err)),
294 ) 307 )
295 return 308 return
296 309
297 self.__insertHash(hashStr) 310 self.__insertHash(hashStr)
298 311
299 @pyqtSlot(QAction) 312 @pyqtSlot(QAction)
300 def __hashDirectory(self, act): 313 def __hashDirectory(self, act):
301 """ 314 """
302 Private slot to generate the hash for a directory. 315 Private slot to generate the hash for a directory.
303 316
304 @param act reference to the action that was triggered 317 @param act reference to the action that was triggered
305 @type QAction 318 @type QAction
306 """ 319 """
307 if act is None: 320 if act is None:
308 return 321 return
309 322
310 folder = EricFileDialog.getExistingDirectory( 323 folder = EricFileDialog.getExistingDirectory(
311 self.__ui, 324 self.__ui, self.tr("Generate Directory Hash"), "", EricFileDialog.Option(0)
312 self.tr("Generate Directory Hash"), 325 )
313 "",
314 EricFileDialog.Option(0))
315 if folder and os.path.isdir(folder): 326 if folder and os.path.isdir(folder):
316 fails = 0 327 fails = 0
317 hashes = [] 328 hashes = []
318 for name in os.listdir(folder): 329 for name in os.listdir(folder):
319 if ( 330 if not name.startswith(".") and os.path.isfile(
320 not name.startswith(".") and 331 os.path.join(folder, name)
321 os.path.isfile(os.path.join(folder, name))
322 ): 332 ):
323 try: 333 try:
324 with open(os.path.join(folder, name), "rb") as f: 334 with open(os.path.join(folder, name), "rb") as f:
325 hashStr = hashlib.new( 335 hashStr = hashlib.new(act.data(), f.read()).hexdigest()
326 act.data(), f.read()).hexdigest()
327 hashes.append((name, hashStr)) 336 hashes.append((name, hashStr))
328 except OSError: 337 except OSError:
329 fails += 1 338 fails += 1
330 if fails: 339 if fails:
331 EricMessageBox.critical( 340 EricMessageBox.critical(
332 self.__ui, 341 self.__ui,
333 self.tr("Generate Directory Hash"), 342 self.tr("Generate Directory Hash"),
334 self.tr("""<p>The hash for some files could not""" 343 self.tr(
335 """ be generated.</p>""") 344 """<p>The hash for some files could not"""
345 """ be generated.</p>"""
346 ),
336 ) 347 )
337 else: 348 else:
338 editor = ericApp().getObject("ViewManager").activeWindow() 349 editor = ericApp().getObject("ViewManager").activeWindow()
339 line, index = editor.getCursorPosition() 350 line, index = editor.getCursorPosition()
340 indLevel = (editor.indentation(line) // 351 indLevel = editor.indentation(line) // editor.indentationWidth()
341 editor.indentationWidth())
342 if editor.indentationsUseTabs(): 352 if editor.indentationsUseTabs():
343 indString = '\t' 353 indString = "\t"
344 else: 354 else:
345 indString = editor.indentationWidth() * ' ' 355 indString = editor.indentationWidth() * " "
346 indent = (indLevel + 1) * indString 356 indent = (indLevel + 1) * indString
347 code = ["["] 357 code = ["["]
348 for name, hashStr in hashes: 358 for name, hashStr in hashes:
349 code.append("{0}('{1}', '{2}'),".format( 359 code.append("{0}('{1}', '{2}'),".format(indent, name, hashStr))
350 indent, name, hashStr))
351 code.append("{0}]".format(indLevel * indString)) 360 code.append("{0}]".format(indLevel * indString))
352 361
353 self.__insertHash(os.linesep.join(code)) 362 self.__insertHash(os.linesep.join(code))
363
354 364
355 # 365 #
356 # eflag: noqa = M801 366 # eflag: noqa = M801

eric ide

mercurial