PluginToolGenerateHash.py

changeset 1
ce3163531e4b
parent 0
8014a543718a
child 4
b0a982bcf664
equal deleted inserted replaced
0:8014a543718a 1:ce3163531e4b
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2013 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing the 'Generate Hash' tool plug-in.
8 """
9
10 import os
11 import hashlib
12
13 from PyQt4.QtCore import QObject, QTranslator
14 from PyQt4.QtGui import QMenu
15
16 from E5Gui.E5Application import e5App
17 from E5Gui import E5FileDialog, E5MessageBox
18
19 # Start-Of-Header
20 name = "Generate Hash Tool Plug-in"
21 author = "Detlev Offenbach <detlev@die-offenbachs.de>"
22 autoactivate = True
23 deactivateable = True
24 version = "0.1.0"
25 className = "ToolGenerateHashPlugin"
26 packageName = "ToolGenerateHash"
27 shortDescription = "Split, merge or convert camel case text"
28 longDescription = \
29 """Plug-in to generate a hash for a selectable file or directory. The"""\
30 """ hash string will be inserted at the cursor position of the current"""\
31 """ editor. The menu will be disabled, if no editor is open."""
32 needsRestart = False
33 pyqtApi = 2
34 # End-Of-Header
35
36 error = ""
37
38
39 class ToolGenerateHashPlugin(QObject):
40 """
41 Class implementing the 'Generate Hash' tool plug-in.
42 """
43 Hashes = {
44 "MD5": hashlib.md5,
45 "SHA1": hashlib.sha1,
46 "SHA224": hashlib.sha224,
47 "SHA256": hashlib.sha256,
48 "SHA384": hashlib.sha384,
49 "SHA512": hashlib.sha512,
50 }
51
52 def __init__(self, ui):
53 """
54 Constructor
55
56 @param ui reference to the user interface object (UI.UserInterface)
57 """
58 QObject.__init__(self, ui)
59 self.__ui = ui
60
61 self.__translator = None
62 self.__loadTranslator()
63
64 self.__initMenus()
65
66 self.__editors = {}
67
68 def activate(self):
69 """
70 Public method to activate this plugin.
71
72 @return tuple of None and activation status (boolean)
73 """
74 global error
75 error = "" # clear previous error
76
77 self.__ui.showMenu.connect(self.__populateMenu)
78
79 e5App().getObject("ViewManager").editorOpenedEd.connect(
80 self.__editorOpened)
81 e5App().getObject("ViewManager").editorClosedEd.connect(
82 self.__editorClosed)
83
84 for editor in e5App().getObject("ViewManager").getOpenEditors():
85 self.__editorOpened(editor)
86
87 return None, True
88
89 def deactivate(self):
90 """
91 Public method to deactivate this plugin.
92 """
93 self.__ui.showMenu.disconnect(self.__populateMenu)
94
95 e5App().getObject("ViewManager").editorOpenedEd.disconnect(
96 self.__editorOpened)
97 e5App().getObject("ViewManager").editorClosedEd.disconnect(
98 self.__editorClosed)
99
100 for editor, acts in self.__editors.items():
101 editor.showMenu.disconnect(self.__editorShowMenu)
102 menu = editor.getMenu("Tools")
103 if menu is not None:
104 for act in acts:
105 menu.removeAction(act)
106 self.__editors = {}
107
108 def __loadTranslator(self):
109 """
110 Private method to load the translation file.
111 """
112 if self.__ui is not None:
113 loc = self.__ui.getLocale()
114 if loc and loc != "C":
115 locale_dir = os.path.join(
116 os.path.dirname(__file__), "ToolGenerateHash", "i18n")
117 translation = "generatehash_{0}".format(loc)
118 translator = QTranslator(None)
119 loaded = translator.load(translation, locale_dir)
120 if loaded:
121 self.__translator = translator
122 e5App().installTranslator(self.__translator)
123 else:
124 print("Warning: translation file '{0}' could not be"
125 " loaded.".format(translation))
126 print("Using default.")
127
128 def __initMenus(self):
129 """
130 Private method to initialize the hash generation menus.
131 """
132 self.__fileMenu = QMenu(self.tr("Generate File Hash"))
133 self.__fileMenu.addAction("MD5", self.__hashFile).setData("MD5")
134 self.__fileMenu.addAction("SHA1", self.__hashFile).setData("SHA1")
135 self.__fileMenu.addAction("SHA224", self.__hashFile).setData("SHA224")
136 self.__fileMenu.addAction("SHA256", self.__hashFile).setData("SHA256")
137 self.__fileMenu.addAction("SHA384", self.__hashFile).setData("SHA384")
138 self.__fileMenu.addAction("SHA512", self.__hashFile).setData("SHA512")
139
140 self.__dirMenu = QMenu(self.tr("Generate Directory Hash"))
141 self.__dirMenu.addAction(
142 "MD5", self.__hashDirectory).setData("MD5")
143 self.__dirMenu.addAction(
144 "SHA1", self.__hashDirectory).setData("SHA1")
145 self.__dirMenu.addAction(
146 "SHA224", self.__hashDirectory).setData("SHA224")
147 self.__dirMenu.addAction(
148 "SHA256", self.__hashDirectory).setData("SHA256")
149 self.__dirMenu.addAction(
150 "SHA384", self.__hashDirectory).setData("SHA384")
151 self.__dirMenu.addAction(
152 "SHA512", self.__hashDirectory).setData("SHA512")
153
154 def __populateMenu(self, name, menu):
155 """
156 Private slot to populate the tools menu with our entries.
157
158 @param name name of the menu (string)
159 @param menu reference to the menu to be populated (QMenu)
160 """
161 if name != "Tools":
162 return
163
164 editor = e5App().getObject("ViewManager").activeWindow()
165
166 if not menu.isEmpty():
167 menu.addSeparator()
168
169 act = menu.addMenu(self.__fileMenu)
170 act.setEnabled(editor is not None)
171 act = menu.addMenu(self.__dirMenu)
172 act.setEnabled(editor is not None)
173
174 def __editorOpened(self, editor):
175 """
176 Private slot called, when a new editor was opened.
177
178 @param editor reference to the new editor (QScintilla.Editor)
179 """
180 menu = editor.getMenu("Tools")
181 if menu is not None:
182 self.__editors[editor] = []
183 if not menu.isEmpty():
184 act = menu.addSeparator()
185 self.__editors[editor].append(act)
186 act = menu.addMenu(self.__fileMenu)
187 self.__editors[editor].append(act)
188 act = menu.addMenu(self.__dirMenu)
189 self.__editors[editor].append(act)
190
191 def __editorClosed(self, editor):
192 """
193 Private slot called, when an editor was closed.
194
195 @param editor reference to the editor (QScintilla.Editor)
196 """
197 try:
198 del self.__editors[editor]
199 except KeyError:
200 pass
201
202 def __insertHash(self, hashStr):
203 """
204 Private method to insert the generated hash string.
205
206 @param hashStr hash string (string)
207 """
208 if hashStr:
209 editor = e5App().getObject("ViewManager").activeWindow()
210 line, index = editor.getCursorPosition()
211 # It should be done on this way to allow undo
212 editor.beginUndoAction()
213 editor.insertAt(hashStr, line, index)
214 editor.endUndoAction()
215
216 def __hashFile(self):
217 """
218 Private slot to generate the hash for a file.
219 """
220 act = self.sender()
221 if act is None:
222 return
223
224 name = E5FileDialog.getOpenFileName(
225 self.__ui,
226 self.trUtf8("Generate File Hash"))
227 if name:
228 try:
229 f = open(name, "rb")
230 hashStr = self.Hashes[act.data()](f.read()).hexdigest()
231 f.close()
232 except (IOError, OSError) as err:
233 E5MessageBox.critical(
234 self.__ui,
235 self.trUtf8("Generate File Hash"),
236 self.trUtf8("""<p>The hash for <b>{0}</b> could not"""
237 """ be generated.</p><p>Reason: {1}</p>""")
238 .format(name, str(err))
239 )
240 return
241
242 self.__insertHash(hashStr)
243
244 def __hashDirectory(self):
245 """
246 Private slot to generate the hash for a directory.
247 """
248 act = self.sender()
249 if act is None:
250 return
251
252 folder = E5FileDialog.getExistingDirectory(
253 self.__ui,
254 self.trUtf8("Generate Directory Hash"),
255 "",
256 E5FileDialog.Options(E5FileDialog.Option(0)))
257 if folder and os.path.isdir(folder):
258 fails = 0
259 hashes = []
260 for name in os.listdir(folder):
261 if not name.startswith(".") and \
262 os.path.isfile(os.path.join(folder, name)):
263 try:
264 f = open(os.path.join(folder, name), "rb")
265 hashStr = self.Hashes[act.data()](f.read()).hexdigest()
266 f.close()
267 hashes.append((name, hashStr))
268 except (IOError, OSError):
269 fails += 1
270 if fails:
271 E5MessageBox.critical(
272 self.__ui,
273 self.trUtf8("Generate Directory Hash"),
274 self.trUtf8("""<p>The hash for some files could not"""
275 """ be generated.</p>""")
276 )
277 else:
278 editor = e5App().getObject("ViewManager").activeWindow()
279 line, index = editor.getCursorPosition()
280 indLevel = (editor.indentation(line) //
281 editor.indentationWidth())
282 if editor.indentationsUseTabs():
283 indString = '\t'
284 else:
285 indString = editor.indentationWidth() * ' '
286 indent = (indLevel + 1) * indString
287 code = ["["]
288 for hash in hashes:
289 code.append("{0}{1},".format(indent, str(hash)))
290 code.append("{0}]".format(indLevel * indString))
291
292 self.__insertHash(os.linesep.join(code))

eric ide

mercurial