9 |
9 |
10 import contextlib |
10 import contextlib |
11 import os |
11 import os |
12 import hashlib |
12 import hashlib |
13 |
13 |
14 from PyQt5.QtCore import QObject, QTranslator |
14 from PyQt6.QtCore import pyqtSlot, QObject, QTranslator |
15 from PyQt5.QtWidgets import QMenu |
15 from PyQt6.QtGui import QAction |
16 |
16 from PyQt6.QtWidgets import QMenu |
17 from E5Gui.E5Application import e5App |
17 |
18 from E5Gui import E5FileDialog, E5MessageBox |
18 from EricWidgets.EricApplication import ericApp |
|
19 from EricWidgets import EricFileDialog, EricMessageBox |
19 |
20 |
20 # Start-Of-Header |
21 # Start-Of-Header |
21 name = "Generate Hash Tool Plug-in" |
22 name = "Generate Hash Tool Plug-in" |
22 author = "Detlev Offenbach <detlev@die-offenbachs.de>" |
23 author = "Detlev Offenbach <detlev@die-offenbachs.de>" |
23 autoactivate = True |
24 autoactivate = True |
24 deactivateable = True |
25 deactivateable = True |
25 version = "3.2.0" |
26 version = "1.0.0" |
26 className = "ToolGenerateHashPlugin" |
27 className = "ToolGenerateHashPlugin" |
27 packageName = "ToolGenerateHash" |
28 packageName = "ToolGenerateHash" |
28 shortDescription = "Generate a hash for a selectable file or directory" |
29 shortDescription = "Generate a hash for a selectable file or directory" |
29 longDescription = ( |
30 longDescription = ( |
30 """Plug-in to generate a hash for a selectable file or directory. The""" |
31 """Plug-in to generate a hash for a selectable file or directory. The""" |
136 translation = "generatehash_{0}".format(loc) |
135 translation = "generatehash_{0}".format(loc) |
137 translator = QTranslator(None) |
136 translator = QTranslator(None) |
138 loaded = translator.load(translation, locale_dir) |
137 loaded = translator.load(translation, locale_dir) |
139 if loaded: |
138 if loaded: |
140 self.__translator = translator |
139 self.__translator = translator |
141 e5App().installTranslator(self.__translator) |
140 ericApp().installTranslator(self.__translator) |
142 else: |
141 else: |
143 print("Warning: translation file '{0}' could not be" |
142 print("Warning: translation file '{0}' could not be" |
144 " loaded.".format(translation)) |
143 " loaded.".format(translation)) |
145 print("Using default.") |
144 print("Using default.") |
146 |
145 |
147 def __initMenus(self): |
146 def __initMenus(self): |
148 """ |
147 """ |
149 Private method to initialize the hash generation menus. |
148 Private method to initialize the hash generation menus. |
150 """ |
149 """ |
151 self.__fileMenu = QMenu(self.tr("Generate File Hash")) |
150 self.__fileMenu = QMenu(self.tr("Generate File Hash")) |
152 self.__fileMenu.addAction("MD5", self.__hashFile).setData("MD5") |
151 for hash in self.Hashes: |
153 self.__fileMenu.addAction("SHA1", self.__hashFile).setData("SHA1") |
152 self.__fileMenu.addAction( |
154 self.__fileMenu.addAction("SHA224", self.__hashFile).setData("SHA224") |
153 hash.upper().replace("_", ":")).setData(hash) |
155 self.__fileMenu.addAction("SHA256", self.__hashFile).setData("SHA256") |
|
156 self.__fileMenu.addAction("SHA384", self.__hashFile).setData("SHA384") |
|
157 self.__fileMenu.addAction("SHA512", self.__hashFile).setData("SHA512") |
|
158 self.__fileMenu.setEnabled(False) |
154 self.__fileMenu.setEnabled(False) |
|
155 self.__fileMenu.triggered.connect(self.__hashFile) |
159 |
156 |
160 self.__dirMenu = QMenu(self.tr("Generate Directory Hash")) |
157 self.__dirMenu = QMenu(self.tr("Generate Directory Hash")) |
161 self.__dirMenu.addAction( |
158 for hash in self.Hashes: |
162 "MD5", self.__hashDirectory).setData("MD5") |
159 self.__dirMenu.addAction( |
163 self.__dirMenu.addAction( |
160 hash.upper().replace("_", ":")).setData(hash) |
164 "SHA1", self.__hashDirectory).setData("SHA1") |
|
165 self.__dirMenu.addAction( |
|
166 "SHA224", self.__hashDirectory).setData("SHA224") |
|
167 self.__dirMenu.addAction( |
|
168 "SHA256", self.__hashDirectory).setData("SHA256") |
|
169 self.__dirMenu.addAction( |
|
170 "SHA384", self.__hashDirectory).setData("SHA384") |
|
171 self.__dirMenu.addAction( |
|
172 "SHA512", self.__hashDirectory).setData("SHA512") |
|
173 self.__dirMenu.setEnabled(False) |
161 self.__dirMenu.setEnabled(False) |
|
162 self.__dirMenu.triggered.connect(self.__hashDirectory) |
174 |
163 |
175 def __populateMenu(self, name, menu): |
164 def __populateMenu(self, name, menu): |
176 """ |
165 """ |
177 Private slot to populate the tools menu with our entries. |
166 Private slot to populate the tools menu with our entries. |
178 |
167 |
179 @param name name of the menu (string) |
168 @param name name of the menu |
180 @param menu reference to the menu to be populated (QMenu) |
169 @type str |
|
170 @param menu reference to the menu to be populated |
|
171 @type QMenu |
181 """ |
172 """ |
182 if name not in ["Tools", "PluginTools"]: |
173 if name not in ["Tools", "PluginTools"]: |
183 return |
174 return |
184 |
175 |
185 editor = e5App().getObject("ViewManager").activeWindow() |
176 editor = ericApp().getObject("ViewManager").activeWindow() |
186 |
177 |
187 if name == "Tools": |
178 if name == "Tools": |
188 if not menu.isEmpty(): |
179 if not menu.isEmpty(): |
189 menu.addSeparator() |
180 menu.addSeparator() |
190 |
181 |
257 |
253 |
258 def __insertHash(self, hashStr): |
254 def __insertHash(self, hashStr): |
259 """ |
255 """ |
260 Private method to insert the generated hash string. |
256 Private method to insert the generated hash string. |
261 |
257 |
262 @param hashStr hash string (string) |
258 @param hashStr hash string |
|
259 @type str |
263 """ |
260 """ |
264 if hashStr: |
261 if hashStr: |
265 editor = e5App().getObject("ViewManager").activeWindow() |
262 editor = ericApp().getObject("ViewManager").activeWindow() |
266 line, index = editor.getCursorPosition() |
263 line, index = editor.getCursorPosition() |
267 # It should be done on this way to allow undo |
264 # It should be done this way to allow undo |
268 editor.beginUndoAction() |
265 editor.beginUndoAction() |
269 editor.insertAt(hashStr, line, index) |
266 editor.insertAt(hashStr, line, index) |
270 editor.endUndoAction() |
267 editor.endUndoAction() |
271 |
268 |
272 def __hashFile(self): |
269 @pyqtSlot(QAction) |
|
270 def __hashFile(self, act): |
273 """ |
271 """ |
274 Private slot to generate the hash for a file. |
272 Private slot to generate the hash for a file. |
275 """ |
273 |
276 act = self.sender() |
274 @param act reference to the action that was triggered |
|
275 @type QAction |
|
276 """ |
277 if act is None: |
277 if act is None: |
278 return |
278 return |
279 |
279 |
280 name = E5FileDialog.getOpenFileName( |
280 name = EricFileDialog.getOpenFileName( |
281 self.__ui, |
281 self.__ui, |
282 self.tr("Generate File Hash")) |
282 self.tr("Generate File Hash")) |
283 if name: |
283 if name: |
284 try: |
284 try: |
285 with open(name, "rb") as f: |
285 with open(name, "rb") as f: |
286 hashStr = self.Hashes[act.data()](f.read()).hexdigest() |
286 hashStr = hashlib.new(act.data(), f.read()).hexdigest() |
287 except OSError as err: |
287 except OSError as err: |
288 E5MessageBox.critical( |
288 EricMessageBox.critical( |
289 self.__ui, |
289 self.__ui, |
290 self.tr("Generate File Hash"), |
290 self.tr("Generate File Hash"), |
291 self.tr("""<p>The hash for <b>{0}</b> could not""" |
291 self.tr("""<p>The hash for <b>{0}</b> could not""" |
292 """ be generated.</p><p>Reason: {1}</p>""") |
292 """ be generated.</p><p>Reason: {1}</p>""") |
293 .format(name, str(err)) |
293 .format(name, str(err)) |
294 ) |
294 ) |
295 return |
295 return |
296 |
296 |
297 self.__insertHash(hashStr) |
297 self.__insertHash(hashStr) |
298 |
298 |
299 def __hashDirectory(self): |
299 @pyqtSlot(QAction) |
|
300 def __hashDirectory(self, act): |
300 """ |
301 """ |
301 Private slot to generate the hash for a directory. |
302 Private slot to generate the hash for a directory. |
302 """ |
303 |
303 act = self.sender() |
304 @param act reference to the action that was triggered |
|
305 @type QAction |
|
306 """ |
304 if act is None: |
307 if act is None: |
305 return |
308 return |
306 |
309 |
307 folder = E5FileDialog.getExistingDirectory( |
310 folder = EricFileDialog.getExistingDirectory( |
308 self.__ui, |
311 self.__ui, |
309 self.tr("Generate Directory Hash"), |
312 self.tr("Generate Directory Hash"), |
310 "", |
313 "", |
311 E5FileDialog.Options(E5FileDialog.Option(0))) |
314 EricFileDialog.Option(0)) |
312 if folder and os.path.isdir(folder): |
315 if folder and os.path.isdir(folder): |
313 fails = 0 |
316 fails = 0 |
314 hashes = [] |
317 hashes = [] |
315 for name in os.listdir(folder): |
318 for name in os.listdir(folder): |
316 if ( |
319 if ( |
317 not name.startswith(".") and |
320 not name.startswith(".") and |
318 os.path.isfile(os.path.join(folder, name)) |
321 os.path.isfile(os.path.join(folder, name)) |
319 ): |
322 ): |
320 try: |
323 try: |
321 with open(os.path.join(folder, name), "rb") as f: |
324 with open(os.path.join(folder, name), "rb") as f: |
322 hashStr = self.Hashes[act.data()]( |
325 hashStr = hashlib.new( |
323 f.read()).hexdigest() |
326 act.data(), f.read()).hexdigest() |
324 hashes.append((name, hashStr)) |
327 hashes.append((name, hashStr)) |
325 except OSError: |
328 except OSError: |
326 fails += 1 |
329 fails += 1 |
327 if fails: |
330 if fails: |
328 E5MessageBox.critical( |
331 EricMessageBox.critical( |
329 self.__ui, |
332 self.__ui, |
330 self.tr("Generate Directory Hash"), |
333 self.tr("Generate Directory Hash"), |
331 self.tr("""<p>The hash for some files could not""" |
334 self.tr("""<p>The hash for some files could not""" |
332 """ be generated.</p>""") |
335 """ be generated.</p>""") |
333 ) |
336 ) |
334 else: |
337 else: |
335 editor = e5App().getObject("ViewManager").activeWindow() |
338 editor = ericApp().getObject("ViewManager").activeWindow() |
336 line, index = editor.getCursorPosition() |
339 line, index = editor.getCursorPosition() |
337 indLevel = (editor.indentation(line) // |
340 indLevel = (editor.indentation(line) // |
338 editor.indentationWidth()) |
341 editor.indentationWidth()) |
339 if editor.indentationsUseTabs(): |
342 if editor.indentationsUseTabs(): |
340 indString = '\t' |
343 indString = '\t' |