summaryrefslogtreecommitdiff
path: root/mat-gui
diff options
context:
space:
mode:
Diffstat (limited to 'mat-gui')
-rwxr-xr-xmat-gui93
1 files changed, 50 insertions, 43 deletions
diff --git a/mat-gui b/mat-gui
index dbea525..f481b07 100755
--- a/mat-gui
+++ b/mat-gui
@@ -1,7 +1,7 @@
1#!/usr/bin/env python 1#!/usr/bin/env python
2# -*- coding: utf-8 -* 2# -*- coding: utf-8 -*
3 3
4''' Metadata anonymisation toolkit - GUI edition ''' 4""" Metadata anonymisation toolkit - GUI edition """
5 5
6from gi.repository import GObject, Gtk, GLib 6from gi.repository import GObject, Gtk, GLib
7from gi.repository import Gdk, GdkPixbuf 7from gi.repository import Gdk, GdkPixbuf
@@ -22,17 +22,19 @@ logging.basicConfig(level=mat.LOGGING_LEVEL)
22 22
23 23
24class CFile(GObject.Object): 24class CFile(GObject.Object):
25 ''' Contain the "parser" class of the file "filename" 25 """ Contain the "parser" class of the file "filename"
26 This class exist just to be "around" my parser.Generic_parser class, 26 This class exist just to be "around" my parser.Generic_parser class,
27 since the Gtk.ListStore does not accept it because it does not 27 since the Gtk.ListStore does not accept it because it does not
28 extends Gobject.Object 28 extends Gobject.Object
29 ''' 29 """
30
30 def __init__(self, filename, **kwargs): 31 def __init__(self, filename, **kwargs):
31 self.file = mat.create_class_file(filename, 0, **kwargs) 32 self.file = mat.create_class_file(filename, 0, **kwargs)
32 33
33 34
34class GUI(object): 35class GUI(object):
35 ''' Main GUI class ''' 36 """ Main GUI class """
37
36 def __init__(self): 38 def __init__(self):
37 # Preferences 39 # Preferences
38 self.add2archive = False 40 self.add2archive = False
@@ -67,7 +69,7 @@ class GUI(object):
67 self.window.show_all() 69 self.window.show_all()
68 70
69 def __init_supported_popup(self): 71 def __init_supported_popup(self):
70 ''' Initialise the "supported formats" popup ''' 72 """ Initialise the "supported formats" popup """
71 self.supported_dict = mat.XMLParser() 73 self.supported_dict = mat.XMLParser()
72 xml_parser = xml.sax.make_parser() 74 xml_parser = xml.sax.make_parser()
73 xml_parser.setContentHandler(self.supported_dict) 75 xml_parser.setContentHandler(self.supported_dict)
@@ -89,7 +91,7 @@ class GUI(object):
89 self.cb_update_supported_popup(supported_cbox) # to initially fill the dialog 91 self.cb_update_supported_popup(supported_cbox) # to initially fill the dialog
90 92
91 def __set_drag_treeview(self): 93 def __set_drag_treeview(self):
92 ''' Setup the drag'n'drop handling by the treeview ''' 94 """ Setup the drag'n'drop handling by the treeview """
93 self.treeview.drag_dest_set( 95 self.treeview.drag_dest_set(
94 Gtk.DestDefaults.MOTION | 96 Gtk.DestDefaults.MOTION |
95 Gtk.DestDefaults.HIGHLIGHT | 97 Gtk.DestDefaults.HIGHLIGHT |
@@ -99,17 +101,18 @@ class GUI(object):
99 targets.add_uri_targets(80) 101 targets.add_uri_targets(80)
100 self.treeview.drag_dest_set_target_list(targets) 102 self.treeview.drag_dest_set_target_list(targets)
101 103
102 def cb_hide_widget(self, widget, _): 104 @staticmethod
103 ''' This function is a little hack to hide instead 105 def cb_hide_widget(widget, _):
106 """ This function is a little hack to hide instead
104 of close re-usable popups, like supported-fileformats, 107 of close re-usable popups, like supported-fileformats,
105 popup-metadata, ...''' 108 popup-metadata, ..."""
106 widget.hide() 109 widget.hide()
107 return False 110 return False
108 111
109 def cb_update_supported_popup(self, window): 112 def cb_update_supported_popup(self, window):
110 ''' Fill GtkEntries of the supported_format_popups 113 """ Fill GtkEntries of the supported_format_popups
111 with corresponding data. 114 with corresponding data.
112 ''' 115 """
113 index = window.get_model()[window.get_active_iter()][0] 116 index = window.get_model()[window.get_active_iter()][0]
114 support = self.builder.get_object('supported_support') 117 support = self.builder.get_object('supported_support')
115 support.set_text(self.supported_dict.list[index]['support']) 118 support.set_text(self.supported_dict.list[index]['support'])
@@ -120,15 +123,16 @@ class GUI(object):
120 remaining = self.builder.get_object('supported_remaining').get_buffer() 123 remaining = self.builder.get_object('supported_remaining').get_buffer()
121 remaining.set_text(self.supported_dict.list[index]['remaining']) 124 remaining.set_text(self.supported_dict.list[index]['remaining'])
122 125
123 def cb_close_application(self, _): 126 @staticmethod
124 ''' Close the application ''' 127 def cb_close_application(_):
128 """ Close the application """
125 Gtk.main_quit() 129 Gtk.main_quit()
126 130
127 def cb_add_files(self, button): 131 def cb_add_files(self, button):
128 ''' Add the files chosen by the filechooser ("Add" button) ''' 132 """ Add the files chosen by the filechooser ("Add" button) """
129 chooser = Gtk.FileChooserDialog(title=_('Choose files'), 133 chooser = Gtk.FileChooserDialog(title=_('Choose files'),
130 parent=self.window, action=Gtk.FileChooserAction.OPEN, 134 parent=self.window, action=Gtk.FileChooserAction.OPEN,
131 buttons=(Gtk.STOCK_OK, 0, Gtk.STOCK_CANCEL, 1)) 135 buttons=(Gtk.STOCK_OK, 0, Gtk.STOCK_CANCEL, 1))
132 chooser.set_default_response(0) 136 chooser.set_default_response(0)
133 chooser.set_select_multiple(True) 137 chooser.set_select_multiple(True)
134 138
@@ -151,9 +155,9 @@ class GUI(object):
151 chooser.destroy() 155 chooser.destroy()
152 156
153 def cb_popup_metadata(self, widget, row, col): 157 def cb_popup_metadata(self, widget, row, col):
154 ''' Popup that display on double-click 158 """ Popup that display on double-click
155 metadata from a file 159 metadata from a file
156 ''' 160 """
157 metadataPopupListStore = self.builder.get_object('MetadataPopupListStore') 161 metadataPopupListStore = self.builder.get_object('MetadataPopupListStore')
158 metadataPopupListStore.clear() 162 metadataPopupListStore.clear()
159 if self.liststore[row][0].file.is_clean(): 163 if self.liststore[row][0].file.is_clean():
@@ -171,7 +175,7 @@ class GUI(object):
171 popup_metadata.hide() 175 popup_metadata.hide()
172 176
173 def cb_about_popup(self, button): 177 def cb_about_popup(self, button):
174 ''' About popup ''' 178 """ About popup """
175 w = Gtk.AboutDialog() 179 w = Gtk.AboutDialog()
176 w.set_authors(['Julien (jvoisin) Voisin', ]) 180 w.set_authors(['Julien (jvoisin) Voisin', ])
177 w.set_artists(['Marine Benoît', ]) 181 w.set_artists(['Marine Benoît', ])
@@ -187,26 +191,26 @@ class GUI(object):
187 w.destroy() 191 w.destroy()
188 192
189 def cb_supported_popup(self, w): 193 def cb_supported_popup(self, w):
190 ''' Show the "supported formats" popup''' 194 """ Show the "supported formats" popup"""
191 dialog = self.builder.get_object('SupportedWindow') 195 dialog = self.builder.get_object('SupportedWindow')
192 dialog.show_all() 196 dialog.show_all()
193 dialog.run() 197 dialog.run()
194 dialog.hide() 198 dialog.hide()
195 199
196 def cb_clear_list(self, _): 200 def cb_clear_list(self, _):
197 ''' Clear the file list ''' 201 """ Clear the file list """
198 self.liststore.clear() 202 self.liststore.clear()
199 203
200 def cb_mat_check(self, button): 204 def cb_mat_check(self, button):
201 ''' Callback for checking files ''' 205 """ Callback for checking files """
202 self.__process_files(self.__mat_check) 206 self.__process_files(self.__mat_check)
203 207
204 def cb_mat_clean(self, button): 208 def cb_mat_clean(self, button):
205 ''' Callback for cleaning files ''' 209 """ Callback for cleaning files """
206 self.__process_files(self.__mat_clean) 210 self.__process_files(self.__mat_clean)
207 211
208 def cb_preferences_popup(self, button): 212 def cb_preferences_popup(self, button):
209 ''' Preferences popup ''' 213 """ Preferences popup """
210 dialog = Gtk.Dialog(_('Preferences'), self.window, 0, (Gtk.STOCK_OK, 0)) 214 dialog = Gtk.Dialog(_('Preferences'), self.window, 0, (Gtk.STOCK_OK, 0))
211 dialog.connect('delete-event', self.cb_hide_widget) 215 dialog.connect('delete-event', self.cb_hide_widget)
212 dialog.set_resizable(False) 216 dialog.set_resizable(False)
@@ -242,15 +246,15 @@ non-anonymised) file to output archive'))
242 dialog.hide() 246 dialog.hide()
243 247
244 def cb_drag_data_received(self, widget, context, x, y, selection, target_type, timestamp): 248 def cb_drag_data_received(self, widget, context, x, y, selection, target_type, timestamp):
245 ''' This function is called when something is 249 """ This function is called when something is
246 drag'n'droped into mat. 250 drag'n'droped into mat.
247 It basically add files. 251 It basically add files.
248 ''' 252 """
249 253
250 def clean_path(url): 254 def clean_path(url):
251 ''' Since the dragged urls are ugly, 255 """ Since the dragged urls are ugly,
252 we need to process them 256 we need to process them
253 ''' 257 """
254 url = urllib2.unquote(url) # unquote url 258 url = urllib2.unquote(url) # unquote url
255 url = url.decode('utf-8') # decode in utf-8 259 url = url.decode('utf-8') # decode in utf-8
256 if url.startswith('file:\\\\\\'): # windows 260 if url.startswith('file:\\\\\\'): # windows
@@ -265,7 +269,7 @@ non-anonymised) file to output archive'))
265 GLib.idle_add(self.populate(cleaned_urls).next) # asynchronous processing 269 GLib.idle_add(self.populate(cleaned_urls).next) # asynchronous processing
266 270
267 def __add_file_to_treeview(self, filename): 271 def __add_file_to_treeview(self, filename):
268 ''' Add a file to the list if its format is supported ''' 272 """ Add a file to the list if its format is supported """
269 cf = CFile(filename, add2archive=self.add2archive, low_pdf_quality=self.pdf_quality) 273 cf = CFile(filename, add2archive=self.add2archive, low_pdf_quality=self.pdf_quality)
270 if cf.file and cf.file.is_writable: 274 if cf.file and cf.file.is_writable:
271 self.liststore.append([cf, cf.file.basename, _('Unknown')]) 275 self.liststore.append([cf, cf.file.basename, _('Unknown')])
@@ -273,7 +277,7 @@ non-anonymised) file to output archive'))
273 return True 277 return True
274 278
275 def __process_files(self, func): 279 def __process_files(self, func):
276 ''' Launch the function "func" in a asynchronous way ''' 280 """ Launch the function "func" in a asynchronous way """
277 iterator = self.treeview.get_selection().get_selected_rows()[1] 281 iterator = self.treeview.get_selection().get_selected_rows()[1]
278 if not iterator: # if nothing is selected : select everything 282 if not iterator: # if nothing is selected : select everything
279 iterator = range(len(self.liststore)) 283 iterator = range(len(self.liststore))
@@ -281,14 +285,14 @@ non-anonymised) file to output archive'))
281 GLib.idle_add(task.next) 285 GLib.idle_add(task.next)
282 286
283 def __invert(self, button, name): 287 def __invert(self, button, name):
284 ''' Invert a preference state ''' 288 """ Invert a preference state """
285 if name == 'pdf_quality': 289 if name == 'pdf_quality':
286 self.pdf_quality = not self.pdf_quality 290 self.pdf_quality = not self.pdf_quality
287 elif name == 'add2archive': 291 elif name == 'add2archive':
288 self.add2archive = not self.add2archive 292 self.add2archive = not self.add2archive
289 293
290 def populate(self, filenames): 294 def populate(self, filenames):
291 ''' Append selected files by add_file to the self.liststore ''' 295 """ Append selected files by add_file to the self.liststore """
292 not_supported = [] 296 not_supported = []
293 for filename in filenames: # filenames : all selected files/folders 297 for filename in filenames: # filenames : all selected files/folders
294 if os.path.isdir(filename): # if "filename" is a directory 298 if os.path.isdir(filename): # if "filename" is a directory
@@ -308,11 +312,11 @@ non-anonymised) file to output archive'))
308 yield False 312 yield False
309 313
310 def __popup_non_supported(self, filelist): 314 def __popup_non_supported(self, filelist):
311 ''' Popup that warn the user about the unsupported files 315 """ Popup that warn the user about the unsupported files
312 that he want to process 316 that he want to process
313 ''' 317 """
314 dialog = Gtk.Dialog(title=_('Not-supported'), parent=self.window, 318 dialog = Gtk.Dialog(title=_('Not-supported'), parent=self.window,
315 flags=Gtk.DialogFlags.MODAL, buttons=(Gtk.STOCK_OK, 0)) 319 flags=Gtk.DialogFlags.MODAL, buttons=(Gtk.STOCK_OK, 0))
316 dialog.set_size_request(220, 180) 320 dialog.set_size_request(220, 180)
317 vbox = Gtk.VBox(spacing=5) 321 vbox = Gtk.VBox(spacing=5)
318 sc = Gtk.ScrolledWindow() 322 sc = Gtk.ScrolledWindow()
@@ -345,12 +349,12 @@ non-anonymised) file to output archive'))
345 dialog.destroy() 349 dialog.destroy()
346 350
347 def __popup_archive(self, file_name, files_list): 351 def __popup_archive(self, file_name, files_list):
348 ''' Popup that shows the user what files 352 """ Popup that shows the user what files
349 are not going to be include into to outputed 353 are not going to be include into to outputed
350 archive 354 archive
351 ''' 355 """
352 dialog = Gtk.Dialog(title=_('Non-supported files in archive'), parent=self.window, 356 dialog = Gtk.Dialog(title=_('Non-supported files in archive'), parent=self.window,
353 flags=Gtk.DialogFlags.MODAL, buttons=(_('Clean'), 0)) 357 flags=Gtk.DialogFlags.MODAL, buttons=(_('Clean'), 0))
354 dialog.set_size_request(220, 180) 358 dialog.set_size_request(220, 180)
355 vbox = Gtk.VBox(spacing=5) 359 vbox = Gtk.VBox(spacing=5)
356 sc = Gtk.ScrolledWindow() 360 sc = Gtk.ScrolledWindow()
@@ -360,7 +364,7 @@ non-anonymised) file to output archive'))
360 dialog.get_content_area().pack_start(sc, True, True, 0) 364 dialog.get_content_area().pack_start(sc, True, True, 0)
361 store = Gtk.ListStore(bool, str) 365 store = Gtk.ListStore(bool, str)
362 for i in files_list: # store.extend is not supported, wtf?! 366 for i in files_list: # store.extend is not supported, wtf?!
363 store.append([0,os.path.basename(i)]) 367 store.append([0, os.path.basename(i)])
364 368
365 treeview = Gtk.TreeView(store) 369 treeview = Gtk.TreeView(store)
366 column_toggle = Gtk.TreeViewColumn(_('Include')) 370 column_toggle = Gtk.TreeViewColumn(_('Include'))
@@ -375,15 +379,17 @@ non-anonymised) file to output archive'))
375 cellrenderer_toggle = Gtk.CellRendererToggle() 379 cellrenderer_toggle = Gtk.CellRendererToggle()
376 column_toggle.pack_start(cellrenderer_toggle, True) 380 column_toggle.pack_start(cellrenderer_toggle, True)
377 column_toggle.add_attribute(cellrenderer_toggle, 'active', 0) 381 column_toggle.add_attribute(cellrenderer_toggle, 'active', 0)
382
378 def cell_toggled(widget, path, model): 383 def cell_toggled(widget, path, model):
379 model[path][0] = not model[path][0] 384 model[path][0] = not model[path][0]
385
380 cellrenderer_toggle.connect('toggled', cell_toggled, store) 386 cellrenderer_toggle.connect('toggled', cell_toggled, store)
381 387
382 vbox.pack_start(Gtk.Label(_('MAT is not able to clean the' 388 vbox.pack_start(Gtk.Label(_('MAT is not able to clean the'
383 ' following files, found in the %s archive') % file_name), False, False, 0) 389 ' following files, found in the %s archive') % file_name), False, False, 0)
384 label = Gtk.Label() 390 label = Gtk.Label()
385 label.set_markup('Select the files you want to <b>include</b>' 391 label.set_markup('Select the files you want to <b>include</b>'
386 ' in the cleaned up archive anyway.') 392 ' in the cleaned up archive anyway.')
387 vbox.pack_start(label, False, False, 0) 393 vbox.pack_start(label, False, False, 0)
388 vbox.pack_start(treeview, True, True, 0) 394 vbox.pack_start(treeview, True, True, 0)
389 395
@@ -393,7 +399,7 @@ non-anonymised) file to output archive'))
393 return [i[1] for i in store if i[0]] 399 return [i[1] for i in store if i[0]]
394 400
395 def __mat_check(self, iterator): 401 def __mat_check(self, iterator):
396 ''' Check elements in iterator are clean ''' 402 """ Check elements in iterator are clean """
397 for line in iterator: # for each file in selection 403 for line in iterator: # for each file in selection
398 msg = _('Checking %s') % self.liststore[line][1].decode('utf-8', 'replace') 404 msg = _('Checking %s') % self.liststore[line][1].decode('utf-8', 'replace')
399 logging.info(msg) 405 logging.info(msg)
@@ -408,7 +414,7 @@ non-anonymised) file to output archive'))
408 yield False 414 yield False
409 415
410 def __mat_clean(self, iterator): 416 def __mat_clean(self, iterator):
411 ''' Clean elements in iterator ''' 417 """ Clean elements in iterator """
412 for line in iterator: # for each file in selection 418 for line in iterator: # for each file in selection
413 msg = _('Cleaning %s') % self.liststore[line][1].decode('utf-8', 'replace') 419 msg = _('Cleaning %s') % self.liststore[line][1].decode('utf-8', 'replace')
414 logging.info(msg) 420 logging.info(msg)
@@ -430,6 +436,7 @@ non-anonymised) file to output archive'))
430 self.statusbar.push(0, _('Ready')) 436 self.statusbar.push(0, _('Ready'))
431 yield False 437 yield False
432 438
439
433if __name__ == '__main__': 440if __name__ == '__main__':
434 gettext.install('MAT', unicode=True) 441 gettext.install('MAT', unicode=True)
435 442