From 4568f336672e2e689b4bd5e7b4bc783526c636c2 Mon Sep 17 00:00:00 2001
From: jvoisin
Date: Fri, 26 Apr 2013 03:03:15 +0200
Subject: Simplify the FORMATS file
---
data/FORMATS | 102 ++++++++++++++++++++++++++++-------------------------------
1 file changed, 48 insertions(+), 54 deletions(-)
diff --git a/data/FORMATS b/data/FORMATS
index 3219998..b398be1 100644
--- a/data/FORMATS
+++ b/data/FORMATS
@@ -3,115 +3,109 @@
Portable Network Graphics
.png
image/png
- full
- textual metadata + date
- removal of harmful fields is done with hachoir
+ Full
+ Textual metadata and date
+ Removal of harmful fields with hachoir.
+ None
Jpeg
.jpeg, .jpg
image/jpeg
- partial
- comment + exif/photoshop/adobe
- removal of harmful fields is done with hachoir
- Canon Raw tags :
- http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/CanonRaw.html
-
+ Partial
+ Comments and exif/photoshop/adobe
+ Removal of harmful fields with hachoir.
+ Canon Raw tags
Open Document
.odt, .odx, .ods, ...
application/opendocument
- full
- a meta.xml file
- removal of the meta.xml file
+ Full
+ A meta.xml file
+ Removal of the meta.xml file.
+ None
Office Openxml
.docx, .pptx, .xlsx, ...
application/officeopenxml
- full
- a docProps folder containings xml metadata files
- removal of the docProps folder
+ Full
+ A docProps folder containings xml metadata files.
+ Removal of the docProps folder
+ None
Portable Document Fileformat
.pdf
application/pdf
- full
- a lot
- rendering of the PDF file on a cairo surface with the help of
- poppler in order to remove all the internal metadata.
- For now, cairo create some metadata.
- They can be remove if you install either exiftool, or python-pdfrw.
- The next version of python-cairo will support PDF metadata.
-
+ Full
+ A lot
+ Rendering of the PDF file on a cairo surface with the help of poppler.
+ None
- Tape ARchive and Bziped ones
- .tar, .tar.bz2
- application/x-tar, application/x-bzip2
- full
- metadata from the file itself, metadata from the file contained
- into the archive, and metadata added by tar to the file at then
- creation of the archive
- extraction of each file, treatement of the file, add treated file
- to a new archive, right before the add, remove the metadata added by tar
- itself. When the new archive is complete, remove all his metadata.
+ Tape ARchive
+ .tar, .tar.bz2, .tar.gz
+ application/x-tar, application/x-gzip, application/x-bzip2
+ Full
+ Metadata from compressed files, metadata added to them by tar and metadata from the tar itself.
+ Extraction and processing of each file, creation of a new archive, processing of this archive.
+ None
Zip
.zip
application/zip
- partial
- metadata from the file itself, metadata from the file contained
- into the archive, and metadata added by zip to the file when added to
- the archive.
- extraction of each file, treatement of the file, add treated file
- to a new archive. When the new archive is complete, remove all his metadata
- metadata added by zip itself to internal files
+ Partial
+ Metadata from compressed files, metadata added to them by zip and metadata from the zip itself.
+ Extraction and processing of each file, creation of a new archive, processing of this archive.
+ Metadata added by zip itself to internal files
MPEG Audio
.mp3, .mp2, .mp1, .mpa
audio/mpeg
- full
- id3
- removal of harmful fields is done with hachoir
+ Full
+ Id3
+ Removal of harmful fields with hachoir
+ None
Ogg Vorbis
.ogg
audio/vorbis
- full
+ Full
Vorbis
- removal of harmful fields is done with mutagen
+ Removal of harmful fields with mutagen
+ None
Free Lossless Audio Codec
.flac
audio/x-flac
- full
+ Full
Flac, Vorbis
- removal of harmful fields is done with mutagen
+ Removal of harmful fields with mutagen
+ None
- Torrent
- .torrent
- application/torrent
- full
- torrent
- remove all the compromizing metadata with a heavily tuned version
- of the bencode lib by Petru Paled
+ Torrent
+ .torrent
+ application/torrent
+ Full
+ Torrent specific metadata
+ Remove all the compromizing metadata with a heavily tuned version of the bencode lib by Petru Paled
+ None
--
cgit v1.3
From 7481af5e859be20b7a72a6e3a6a9d36c0749398f Mon Sep 17 00:00:00 2001
From: jvoisin
Date: Fri, 26 Apr 2013 03:03:37 +0200
Subject: Prettify mat -l output
---
mat | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/mat b/mat
index da43198..82e0e0a 100755
--- a/mat
+++ b/mat
@@ -113,9 +113,9 @@ def list_supported():
print('%s (%s)' % (item['name'], item['extension']))
print('\tsupport : ' + item['support'])
print('\tmetadata : ' + item['metadata'])
- print('\tmethod : ' + item['method'] + '\n')
- if item['support'] == 'partial':
- print('\tremaining : ' + item['remaining'] + '\n')
+ print('\tmethod : ' + item['method'])
+ print('\tremaining : ' + item['remaining'])
+ print('\n')
sys.exit(0)
--
cgit v1.3
From 3e2670ea9a87ce55f5308b0d5343bd49aab25c0b Mon Sep 17 00:00:00 2001
From: jvoisin
Date: Sat, 27 Apr 2013 16:27:31 +0200
Subject: Remove a leftover file (FORMATS)
---
MAT/FORMATS | 117 ------------------------------------------------------------
1 file changed, 117 deletions(-)
delete mode 100644 MAT/FORMATS
diff --git a/MAT/FORMATS b/MAT/FORMATS
deleted file mode 100644
index 3f0751c..0000000
--- a/MAT/FORMATS
+++ /dev/null
@@ -1,117 +0,0 @@
-
-
- Portable Network Graphics
- .png
- image/png
- full
- textual metadata + date
- removal of harmful fields is done with hachoir
-
-
-
- Jpeg
- .jpeg, .jpg
- image/jpeg
- partial
- comment + exif/photoshop/adobe
- removal of harmful fields is done with hachoir
- Canon Raw tags :
- http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/CanonRaw.html
-
-
-
-
- Open Document
- .odt, .odx, .ods, ...
- application/opendocument
- full
- a meta.xml file
- removal of the meta.xml file
-
-
-
- Office Openxml
- .docx, .pptx, .xlsx, ...
- application/officeopenxml
- full
- a docProps folder containings xml metadata files
- removal of the docProps folder
-
-
-
- Portable Document Fileformat
- .pdf
- application/pdf
- full
- a lot
- rendering of the PDF file on a cairo surface with the help of
- poppler in order to remove all the internal metadata.
- For now, cairo create some metadata.
- They can be remove if you install either exiftool, or python-pdfrw.
- The next version of python-cairo will support PDF metadata.
-
-
-
-
- Tape ARchive
- .tar, .tar.bz2, .tar.gz
- application/x-tar, application/x-gzip, application/x-bzip2
- full
- metadata from the file itself, metadata from the file contained
- into the archive, and metadata added by tar to the file at then
- creation of the archive
- extraction of each file, treatement of the file, add treated file
- to a new archive, right before the add, remove the metadata added by tar
- itself. When the new archive is complete, remove all his metadata.
-
-
-
- Zip
- .zip
- application/zip
- partial
- metadata from the file itself, metadata from the file contained
- into the archive, and metadata added by zip to the file when added to
- the archive.
- extraction of each file, treatement of the file, add treated file
- to a new archive. When the new archive is complete, remove all his metadata
- metadata added by zip itself to internal files
-
-
-
- MPEG Audio
- .mp3, .mp2, .mp1, .mpa
- audio/mpeg
- full
- id3
- removal of harmful fields is done with hachoir
-
-
-
- Ogg Vorbis
- .ogg
- audio/vorbis
- full
- Vorbis
- removal of harmful fields is done with mutagen
-
-
-
- Free Lossless Audio Codec
- .flac
- audio/x-flac
- full
- Flac, Vorbis
- removal of harmful fields is done with mutagen
-
-
-
- Torrent
- .torrent
- application/torrent
- full
- torrent
- remove all the compromizing metadata with a heavily tuned version
- of the bencode lib by Petru Paled
-
-
--
cgit v1.3
From df3a1b246031fa06adecf7dbf6e54600b20b10ba Mon Sep 17 00:00:00 2001
From: jvoisin
Date: Sat, 27 Apr 2013 16:39:45 +0200
Subject: The GUI now use glade !
Warning: this is a pretty huge commit
Not everything is ported now, but this is
already a big step.
---
MAT/mat.py | 15 +-
data/mat.ui | 625 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
mat | 3 +-
mat-gui | 581 +++++++++++++++++++++----------------------------------
4 files changed, 849 insertions(+), 375 deletions(-)
create mode 100644 data/mat.ui
diff --git a/MAT/mat.py b/MAT/mat.py
index 3a0938a..0da5c3b 100644
--- a/MAT/mat.py
+++ b/MAT/mat.py
@@ -39,14 +39,13 @@ def get_logo():
elif os.path.isfile('/usr/local/share/pixmaps/mat.png'):
return '/usr/local/share/pixmaps/mat.png'
-def get_formats():
- if os.path.isfile('./data/FORMATS'):
- return './data/FORMATS'
- elif os.path.isfile('/usr/share/mat/FORMATS'):
- return '/usr/share/mat/FORMATS'
- elif os.path.isfile('/usr/local/share/mat/FORMATS'):
- return '/usr/local/share/mat/FORMATS'
-
+def get_datadir():
+ if os.path.isdir('./data/'):
+ return './data/'
+ elif os.path.isdir('/usr/share/mat/'):
+ return '/usr/share/mat/'
+ elif os.path.isdir('/usr/local/share/mat/'):
+ return '/usr/local/share/mat/'
class XMLParser(xml.sax.handler.ContentHandler):
'''
diff --git a/data/mat.ui b/data/mat.ui
new file mode 100644
index 0000000..83d1702
--- /dev/null
+++ b/data/mat.ui
@@ -0,0 +1,625 @@
+
+
+
+
+
+
+ False
+ Supported formats
+ False
+ True
+ True
+ dialog
+ True
+ True
+ False
+ False
+
+
+ False
+ vertical
+ 10
+
+
+ True
+ False
+ center
+ center
+ True
+ True
+ 5
+ 5
+
+
+ True
+ False
+ False
+ False
+ ●
+
+
+ 1
+ 1
+ 1
+ 1
+
+
+
+
+ True
+ False
+ Support
+
+
+ 0
+ 1
+ 1
+ 1
+
+
+
+
+ True
+ False
+ Metadata
+
+
+ 0
+ 2
+ 1
+ 1
+
+
+
+
+ True
+ False
+ Method
+
+
+ 0
+ 3
+ 1
+ 1
+
+
+
+
+ True
+ False
+ Remaining
+
+
+ 0
+ 4
+ 1
+ 1
+
+
+
+
+ True
+ False
+ True
+ 5
+ True
+ 1
+ 1
+
+
+
+ 1
+ 0
+ 1
+ 1
+
+
+
+
+ True
+ False
+ 39
+ Fileformat
+
+
+ 0
+ 0
+ 1
+ 1
+
+
+
+
+ True
+ False
+ natural
+ False
+ word
+
+
+ 1
+ 2
+ 1
+ 1
+
+
+
+
+ True
+ False
+ word
+
+
+ 1
+ 4
+ 1
+ 1
+
+
+
+
+ True
+ False
+ word
+
+
+ 1
+ 3
+ 1
+ 1
+
+
+
+
+ False
+ True
+ 0
+
+
+
+
+ False
+
+
+ gtk-ok
+ True
+ False
+ True
+ True
+
+
+ False
+ True
+ 1
+
+
+
+
+ False
+ True
+ end
+ 1
+
+
+
+
+
+ supported_OK
+
+
+
+ True
+ False
+ 1
+ gtk-remove
+
+
+ True
+ False
+ gtk-properties
+
+
+ True
+ False
+ gtk-clear
+
+
+ True
+ False
+ gtk-find
+
+
+ True
+ False
+ gtk-info
+
+
+ True
+ False
+ gtk-about
+
+
diff --git a/mat b/mat
index da43198..c0b5ee3 100755
--- a/mat
+++ b/mat
@@ -6,6 +6,7 @@
import sys
import xml.sax
import optparse
+import os
import hachoir_core
@@ -104,7 +105,7 @@ def list_supported():
handler = mat.XMLParser()
parser = xml.sax.make_parser()
parser.setContentHandler(handler)
- path = mat.get_formats()
+ path = os.path.join(mat.get_formats(), 'FORMATS')
with open(path, 'r') as xmlfile:
parser.parse(xmlfile)
diff --git a/mat-gui b/mat-gui
index 57d04d9..74e8959 100755
--- a/mat-gui
+++ b/mat-gui
@@ -5,12 +5,10 @@
Metadata anonymisation toolkit - GUI edition
'''
-import gi
-from gi.repository import GObject
-from gi.repository import Gtk, Gdk, GdkPixbuf
+from gi.repository import GObject, Gtk
+from gi.repository import Gdk, GdkPixbuf
import gettext
-#import locale
import logging
import os
import sys
@@ -21,24 +19,21 @@ import urllib2
from MAT import mat
from MAT import strippers
-
logging.basicConfig(level=mat.LOGGING_LEVEL)
-class CFile(object):
+class CFile(GObject.Object):
'''
Contain the "parser" class of the file "filename"
This class exist just to be "around" my parser.Generic_parser class,
- since the Gtk.ListStore does not accept it.
+ since the Gtk.ListStore does not accept it because it does not
+ extends Gobject.Object
'''
def __init__(self, filename, backup, **kwargs):
- try:
- self.file = mat.create_class_file(filename, backup, **kwargs)
- except:
- self.file = None
+ self.file = mat.create_class_file(filename, backup, **kwargs)
-class GUI:
+class GUI(object):
'''
Main GUI class
'''
@@ -50,204 +45,101 @@ class GUI:
self.pdf_quality = False
# Main window
- self.window = Gtk.Window()
- self.window.set_title('Metadata Anonymisation Toolkit')
- self.window.connect('destroy', Gtk.main_quit)
- self.window.set_default_size(800, 600)
+ self.builder = Gtk.Builder()
+ self.builder.add_from_file(os.path.join(mat.get_datadir(), 'mat.ui'))
+ self.builder.connect_signals(self)
+
self.logo = mat.get_logo()
icon = GdkPixbuf.Pixbuf.new_from_file_at_size(self.logo, 50, 50)
- self.window.set_icon(icon)
- self.accelerator = Gtk.AccelGroup()
- self.window.add_accel_group(self.accelerator)
-
- vbox = Gtk.VBox()
- self.window.add(vbox)
-
- menubar = self.__create_menu()
- toolbar = self.__create_toolbar()
- content = Gtk.ScrolledWindow()
- content.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
- vbox.pack_start(menubar, False, True, 0)
- vbox.pack_start(toolbar, False, True, 0)
- vbox.pack_start(content, True, True, 0)
-
- # parser.class - name - path - type - cleaned
- self.liststore = Gtk.ListStore(object, str, str, str, str, str)
-
- self.treeview = Gtk.TreeView(model=self.liststore)
- self.treeview.set_search_column(1) # filename column is searchable
- self.treeview.set_rules_hint(True) # alternate colors for rows
- self.treeview.set_rubber_banding(True) # mouse selection
- self.treeview.connect("key_press_event", self.treeview_keyboard_event)
- self.treeview.connect('row-activated', self.__popup_metadata)
- self.treeview.connect('drag_data_received',
- self.__on_drag_data_received)
- self.treeview.drag_dest_set(Gtk.DestDefaults.MOTION |
- Gtk.DestDefaults.HIGHLIGHT | Gtk.DestDefaults.DROP,
- [], Gdk.DragAction.COPY)
- targets = Gtk.TargetList.new([])
- targets.add_uri_targets(80)
- self.treeview.drag_dest_set_target_list(targets)
- self.__add_columns()
- self.selection = self.treeview.get_selection()
- self.selection.set_mode(Gtk.SelectionMode.MULTIPLE)
+ self.window = self.builder.get_object('MainWindow')
+ self.window.set_icon(icon)
+ self.liststore = self.builder.get_object('Liststore')
+ ''' The liststore contains:
+ 0: a CFile instance which represent the file
+ 1: the file's path
+ 2: the file's name
+ 3: the file's mimetype
+ 4: the file's state (translated string)
+ 5: the cleaned copy's path
+ 6: the file's state (-1: unknown, 0: clean, 1: dirty)
+ '''
- content.add(self.treeview)
+ self.treeview = self.builder.get_object('Treeview')
+ self.treeview.get_column(4).set_visible(self.backup)
- self.statusbar = Gtk.Statusbar()
+ self.statusbar = self.builder.get_object('Statusbar')
self.statusbar.push(1, _('Ready'))
- vbox.pack_start(self.statusbar, False, False, 0)
+
+ self.__init_supported_popup()
+ self.__set_drag_treeview()
self.window.show_all()
- def __create_toolbar(self):
- '''
- Returns a vbox object, which contains a toolbar with buttons
- '''
- toolbar = Gtk.Toolbar()
-
- toolbutton = Gtk.ToolButton(Gtk.STOCK_ADD)
- toolbutton.set_label(_('Add'))
- toolbutton.connect('clicked', self.__add_files)
- toolbutton.set_tooltip_text(_('Add files'))
- toolbar.add(toolbutton)
-
- toolbutton = Gtk.ToolButton(Gtk.STOCK_CLEAR)
- toolbutton.set_label(_('Clean'))
- toolbutton.connect('clicked', self.__process_files, self.__mat_clean)
- toolbutton.set_tooltip_text(_('Clean selected files'))
- toolbar.add(toolbutton)
-
- toolbutton = Gtk.ToolButton(Gtk.STOCK_FIND)
- toolbutton.set_label(_('Check'))
- toolbutton.connect('clicked', self.__process_files, self.__mat_check)
- toolbutton.set_tooltip_text(_('Check selected files for harmful meta'))
- toolbar.add(toolbutton)
-
- toolbutton = Gtk.ToolButton(stock_id=Gtk.STOCK_REMOVE)
- toolbutton.set_label(_('Clear the filelist'))
- toolbutton.connect('clicked', lambda x: self.liststore.clear())
- toolbutton.set_tooltip_text(_('Clear the filelist'))
- toolbar.add(toolbutton)
-
- toolbutton = Gtk.ToolButton(stock_id=Gtk.STOCK_QUIT)
- toolbutton.set_label(_('Quit'))
- toolbutton.connect('clicked', Gtk.main_quit)
- toolbar.add(toolbutton)
-
- vbox = Gtk.VBox(spacing=3)
- vbox.pack_start(toolbar, False, False, 0)
- return vbox
-
- def __add_columns(self):
- '''
- Create the columns, and add them to the treeview
- '''
- colname = [_('Path'), _('Filename'), _('Mimetype'), _('State'),
- _('Cleaned file')]
+ def __init_supported_popup(self):
+ ''' Initialize the "supported formats" popup '''
+ self.supported_dict = mat.XMLParser()
+ parser = xml.sax.make_parser()
+ parser.setContentHandler(self.supported_dict)
+ path = os.path.join(mat.get_datadir(), 'FORMATS')
+ with open(path, 'r') as xmlfile:
+ parser.parse(xmlfile)
- for i, j in enumerate(colname, 1):
- filename_column = Gtk.CellRendererText()
- column = Gtk.TreeViewColumn(j, filename_column, text=i)
- column.set_sort_column_id(i)
- column.set_resizable(True) # column is resizeable
- self.treeview.append_column(column)
+ supported_cbox = self.builder.get_object('supported_cbox')
+ store = Gtk.ListStore(int, str)
+ for i, j in enumerate(self.supported_dict.list):
+ store.append([i, j['name']])
+ supported_cbox.set_model(store)
+ supported_cbox.set_active(0)
- def __create_menu_item(self, name, func, menu, pix, shortcut):
- '''
- Create a MenuItem() like Preferences, Quit, Add, Clean, ...
- '''
- item = Gtk.ImageMenuItem()
- if shortcut:
- key, mod = Gtk.accelerator_parse(shortcut)
- item.add_accelerator('activate', self.accelerator,
- key, mod, Gtk.AccelFlags.VISIBLE)
- picture = Gtk.Image()
- picture.set_from_stock(pix, Gtk.IconSize.MENU)
- item.set_image(picture)
- item.set_label('_' + name)
- item.set_use_underline(True)
- item.connect('activate', func)
- menu.append(item)
-
- def __create_sub_menu(self, name, menubar):
- '''
- Create a submenu like File, Edit, Clean, ...
- '''
- submenu = Gtk.Menu()
- menuitem = Gtk.MenuItem()
- menuitem.set_submenu(submenu)
- menuitem.set_label('_' + name)
- menuitem.set_use_underline(True)
- menubar.append(menuitem)
- return submenu
-
- def __create_menu(self):
+ self.builder.get_object('supported_metadata').set_buffer(Gtk.TextBuffer())
+ self.builder.get_object('supported_remaining').set_buffer(Gtk.TextBuffer())
+ self.builder.get_object('supported_method').set_buffer(Gtk.TextBuffer())
+
+ self.cb_update_supported_popup(supported_cbox) # to initially fill the dialog
+
+ def __set_drag_treeview(self):
+ ''' Setup the drag'n'drop handling by the treeview '''
+ self.treeview.drag_dest_set(Gtk.DestDefaults.MOTION |
+ Gtk.DestDefaults.HIGHLIGHT | Gtk.DestDefaults.DROP,
+ [], Gdk.DragAction.COPY)
+ targets = Gtk.TargetList.new([])
+ targets.add_uri_targets(80)
+ self.treeview.drag_dest_set_target_list(targets)
+
+ def cb_update_supported_popup(self, w):
'''
- Return a MenuBar
+ Fill GtkEntries of the supported_format_popups
+ with corresponding data.
'''
- menubar = Gtk.MenuBar()
-
- file_menu = self.__create_sub_menu(_('Files'), menubar)
- self.__create_menu_item(_('Add files'), self.__add_files, file_menu,
- Gtk.STOCK_ADD, 'O')
- self.__create_menu_item(_('Quit'), Gtk.main_quit, file_menu,
- Gtk.STOCK_QUIT, 'Q')
-
- edit_menu = self.__create_sub_menu(_('Edit'), menubar)
- self.__create_menu_item(_('Clear the filelist'),
- lambda x: self.liststore.clear(), edit_menu, Gtk.STOCK_REMOVE,
- None)
- self.__create_menu_item(_('Preferences'), self.__preferences,
- edit_menu, Gtk.STOCK_PREFERENCES, 'P')
-
- process_menu = self.__create_sub_menu(_('Process'), menubar)
- item = Gtk.ImageMenuItem()
- key, mod = Gtk.accelerator_parse('L')
- item.add_accelerator('activate', self.accelerator,
- key, mod, Gtk.AccelFlags.VISIBLE)
- picture = Gtk.Image()
- picture.set_from_stock(Gtk.STOCK_CLEAR, Gtk.IconSize.MENU)
- item.set_image(picture)
- item.set_label(_('Clean'))
- item.connect('activate', self.__process_files, self.__mat_clean)
- process_menu.append(item)
-
- item = Gtk.ImageMenuItem()
- key, mod = Gtk.accelerator_parse('h')
- item.add_accelerator('activate', self.accelerator,
- key, mod, Gtk.AccelFlags.VISIBLE)
- picture = Gtk.Image()
- picture.set_from_stock(Gtk.STOCK_FIND, Gtk.IconSize.MENU)
- item.set_image(picture)
- item.set_label(_('Check'))
- item.connect('activate', self.__process_files, self.__mat_check)
- process_menu.append(item)
-
- help_menu = self.__create_sub_menu(_('Help'), menubar)
- self.__create_menu_item(_('Supported formats'), self.__supported,
- help_menu, Gtk.STOCK_INFO, False)
- self.__create_menu_item(_('About'), self.__about, help_menu,
- Gtk.STOCK_ABOUT, False)
-
- return menubar
-
- def treeview_keyboard_event(self, widget, event):
+ i = w.get_active_iter()
+ index, _ = w.get_model()[i]
+ support = self.builder.get_object('supported_support')
+ support.set_text(self.supported_dict.list[index]['support'])
+ metadata = self.builder.get_object('supported_metadata').get_buffer()
+ metadata.set_text(self.supported_dict.list[index]['metadata'])
+ method = self.builder.get_object('supported_method').get_buffer()
+ method.set_text(self.supported_dict.list[index]['method'])
+ remaining = self.builder.get_object('supported_remaining').get_buffer()
+ remaining.set_text(self.supported_dict.list[index]['remaining'])
+
+ def cb_treeview_keyboard_event(self, widget, event):
'''
Remove selected files from the treeview
when the use hit the 'suppr' key
'''
if Gdk.keyval_name(event.keyval) == "Delete":
rows = []
- self.selection.selected_foreach(
- lambda model, path, iter: rows.append(iter))
+ self.treeview.get_selection().selected_foreach(
+ lambda model, path, iter: rows.append(iter))
[self.liststore.remove(i) for i in rows]
- def __add_files(self, button):
- '''
- Add the files chosed by the filechoser ("Add" button)
- '''
+ def cb_close_application(self, _):
+ ''' Close the application '''
+ Gtk.main_quit()
+
+ def cb_add_files(self, button):
+ ''' Add the files chosed by the filechoser ("Add" button) '''
chooser = Gtk.FileChooserDialog(title=_('Choose files'),
parent=self.window, action=Gtk.FileChooserAction.OPEN,
buttons=(Gtk.STOCK_OK, 0, Gtk.STOCK_CANCEL, 1))
@@ -259,8 +151,8 @@ class GUI:
all_filter.add_pattern('*')
chooser.add_filter(all_filter)
- supported_filter = Gtk.FileFilter()
# filter that shows only supported formats
+ supported_filter = Gtk.FileFilter()
[supported_filter.add_mime_type(i) for i in strippers.STRIPPERS.keys()]
supported_filter.set_name(_('Supported files'))
chooser.add_filter(supported_filter)
@@ -269,58 +161,24 @@ class GUI:
if not response: # Gtk.STOCK_OK
filenames = chooser.get_filenames()
- task = self.populate(filenames)
- GObject.idle_add(task.next) # asynchrone processing
+ GObject.idle_add(self.populate(filenames).next) # asynchrone processing
chooser.destroy()
- def populate(self, filenames):
- '''
- Append selected files by add_file to the self.liststore
- '''
- not_supported = []
- for filename in filenames: # filenames : all selected files/folders
- if os.path.isdir(filename): # if "filename" is a directory
- for root, dirs, files in os.walk(filename):
- for item in files:
- path_to_file = os.path.join(root, item)
- if self.__add_file_to_treeview(path_to_file):
- not_supported.append(item)
- else: # filename is a regular file
- if self.__add_file_to_treeview(filename):
- not_supported.append(filename)
- yield True
- if not_supported:
- self.__popup_non_supported(not_supported)
- yield False
-
- def __add_file_to_treeview(self, filename):
- '''
- Add a file to the list if it's format is supported
- '''
- if not os.path.isfile(filename):
- # if filename does not exist
- return False
-
- cf = CFile(filename, self.backup, add2archive=self.add2archive, low_pdf_quality=self.pdf_quality)
- if cf.file: # if the file is supported by the mat
- self.liststore.append([cf, os.path.dirname(cf.file.filename) + os.path.sep,
- cf.file.basename, cf.file.mime, _('unknow'), 'None'])
- return False
- return True
-
- def __popup_metadata(self, widget, row, col):
+ def cb_popup_metadata(self, widget, row, col):
'''
Popup that display on double-clic
metadata from a file
+
+ FIXME: use a prettier GUI ?
'''
label = '%s\'s metadatas:\n' % self.liststore[row][1]
meta = ''
- if self.liststore[row][4] == _('Clean') or\
- self.liststore[row][0].file.is_clean():
+ if not self.liststore[row][6] or self.liststore[row][0].file.is_clean():
meta = 'No metadata found'
self.liststore[row][4] = _('Clean')
else:
self.liststore[row][4] = _('Dirty')
+ self.liststore[row][6] = 1
iterator = self.liststore[row][0].file.get_meta().iteritems()
for i, j in iterator:
name = '-' + str(i) + ' : '
@@ -345,45 +203,8 @@ class GUI:
if click:
w.destroy()
- def __popup_non_supported(self, filelist):
- '''
- Popup that warn the user about the unsupported files
- that he want to process
- '''
- dialog = Gtk.Dialog(title=_('Not-supported'), parent=self.window,
- flags=0, buttons=(Gtk.STOCK_OK, 0))
- vbox = Gtk.VBox(spacing=5)
- dialog.get_content_area().pack_start(vbox, True, True, 0)
- store = Gtk.ListStore(str, str)
-
- # append filename - mimetype to the store
- #FIXME : I'm ugly
- for item in filelist:
- mime = mimetypes.guess_type(item)[0]
- if mime:
- store.append([item, mime])
- else:
- store.append([item, 'unknown'])
-
- treeview = Gtk.TreeView(store)
- vbox.pack_start(treeview, True, True, 0)
-
- #create column
- rendererText = Gtk.CellRendererText()
- column = Gtk.TreeViewColumn(_('Filename'), rendererText, text=0)
- treeview.append_column(column)
- column = Gtk.TreeViewColumn(_('Mimetype'), rendererText, text=1)
- treeview.append_column(column)
-
- dialog.show_all()
- click = dialog.run()
- if not click: # Ok button
- dialog.destroy()
-
- def __about(self, button):
- '''
- About popup
- '''
+ def cb_about_popup(self, button):
+ ''' About popup '''
w = Gtk.AboutDialog()
w.set_authors(['Julien (jvoisin) Voisin', ])
w.set_artists(['Marine Benoît', ])
@@ -398,63 +219,28 @@ class GUI:
w.run()
w.destroy()
- def __supported(self, button):
- '''
- List the supported formats
- '''
- dialog = Gtk.Dialog(_('Supported formats'), self.window, 0,
- (Gtk.STOCK_CLOSE, 0))
- vbox = Gtk.VBox(spacing=5)
- dialog.get_content_area().pack_start(vbox, True, True, 0)
-
- label = Gtk.Label()
- label.set_markup('Supported fileformats')
- vbox.pack_start(label, True, True, 0)
-
- #parsing xml
- handler = mat.XMLParser()
- parser = xml.sax.make_parser()
- parser.setContentHandler(handler)
- path = mat.get_formats()
- with open(path, 'r') as xmlfile:
- parser.parse(xmlfile)
-
- def expander_callback(current):
- ''' Close every expander except the current one '''
- for i in vbox.get_children()[1:]: # first child is a Gtk.Label
- if i != current:
- i.set_expanded(False)
-
- for item in handler.list: # list of dict : one dict per format
- # create one expander per format
- # only if the format is supported
- if item['mimetype'].split(',')[0] in strippers.STRIPPERS:
- # some format have more than one mimetype
- title = '%s (%s)' % (item['name'], item['extension'])
- support = ('\t%s : %s' % ('support', item['support']))
- metadata = '\n\tmetadata : ' + item['metadata']
- method = '\n\tmethod : ' + item['method']
- content = support + metadata + method
- if item['support'] == 'partial':
- content += '\n\tremaining : ' + item['remaining']
-
- expander = Gtk.Expander()
- expander.set_label(title)
- vbox.pack_start(expander, False, False, 0)
- label = Gtk.Label()
- label.set_markup(content)
- expander.add(label)
- expander.connect('activate', expander_callback)
-
+ def cb_supported_popup(self, w):
+ ''' Show the "supported formats" popup'''
+ dialog = self.builder.get_object('SupportedWindow')
dialog.show_all()
click = dialog.run()
if not click: # Close
- dialog.destroy()
+ dialog.hide()
- def __preferences(self, button):
- '''
- Preferences popup
- '''
+ def cb_clear_list(self, _):
+ ''' Clear the file list '''
+ self.liststore.clear()
+
+ def cb_mat_check(self, button):
+ ''' Callback for checking files '''
+ self.__process_files(self.mat_check)
+
+ def cb_mat_clean(self, button):
+ ''' Callback for cleaning files '''
+ self.__process_files(self.mat_clean)
+
+ def cb_preferences_popup(self, button):
+ ''' Preferences popup '''
dialog = Gtk.Dialog(_('Preferences'), self.window, 0,
(Gtk.STOCK_OK, 0))
dialog.set_resizable(False)
@@ -472,8 +258,7 @@ class GUI:
force = Gtk.CheckButton(_('Force Clean'), False)
force.set_active(self.force)
force.connect('toggled', self.__invert, 'force')
- force.set_tooltip_text(_('Do not check if already clean before \
-cleaning'))
+ force.set_tooltip_text(_('Do not check if already clean before cleaning'))
table.attach(force, 0, 1, 0, 1)
backup = Gtk.CheckButton(_('Backup'), False)
@@ -498,31 +283,14 @@ non-anonymised) file to output archive'))
hbox.show_all()
if not dialog.run(): # Gtk.STOCK_OK
- for i in self.liststore: # update preferences
- i[0].backup = self.backup
- i[0].add2archive = self.add2archive
- if i[2].startswith('pdf'):
- i[0].pdf_quality = self.pdf_quality
+ for file in self.liststore: # update preferences
+ file[0].backup = self.backup
+ file[0].add2archive = self.add2archive
+ if file[2].startswith('pdf'):
+ file[0].pdf_quality = self.pdf_quality
dialog.destroy()
- def __invert(self, button, name):
- '''
- Invert a preference state
- '''
- if name == 'force':
- self.force = not self.force
- elif name == 'backup':
- self.backup = not self.backup
- for line in xrange(len(self.liststore)):
- # change the "backup" property of all files
- self.liststore[line][0].file.backup = self.backup
- self.treeview.get_column(4).set_visible(self.backup)
- elif name == 'pdf_quality':
- self.pdf_quality = not self.pdf_quality
- elif name == 'add2archive':
- self.add2archive = not self.add2archive
-
- def __on_drag_data_received(self, widget, context,
+ def cb_drag_data_received(self, widget, context,
x, y, selection, target_type, timestamp):
'''
This function is called when something is
@@ -530,7 +298,6 @@ non-anonymised) file to output archive'))
It basically add files.
'''
-
def clean_path(url):
'''
Since the dragged urls are ugly,
@@ -551,43 +318,126 @@ non-anonymised) file to output archive'))
task = self.populate(urls)
GObject.idle_add(task.next) # asynchrone processing
- def __process_files(self, button, func):
+ def __add_file_to_treeview(self, filename):
+ '''
+ Add a file to the list if its format is supported
+ '''
+ cf = CFile(filename, self.backup, add2archive=self.add2archive,
+ low_pdf_quality=self.pdf_quality)
+ if cf.file: # if the file is supported by the mat
+ self.liststore.append([cf, os.path.dirname(cf.file.filename) + os.path.sep,
+ cf.file.basename, cf.file.mime, _('unknow'), 'None', -1])
+ return False
+ return True
+
+ def __process_files(self, func):
'''
Launch the function "func" in a asynchrone way
'''
- iterator = self.selection.get_selected_rows()[1]
+ iterator = self.treeview.get_selection().get_selected_rows()[1]
if not iterator: # if nothing is selected : select everything
iterator = xrange(len(self.liststore))
task = func(iterator) # launch func() in an asynchrone way
GObject.idle_add(task.next)
- def __mat_check(self, iterator):
+ def __invert(self, button, name):
+ ''' Invert a preference state '''
+ if name == 'force':
+ self.force = not self.force
+ elif name == 'pdf_quality':
+ self.pdf_quality = not self.pdf_quality
+ elif name == 'add2archive':
+ self.add2archive = not self.add2archive
+ elif name == 'backup':
+ self.backup = not self.backup
+ for line in xrange(len(self.liststore)):
+ # change the "backup" property of all files
+ self.liststore[line][0].file.backup = self.backup
+ self.treeview.get_column(4).set_visible(self.backup)
+
+ def populate(self, filenames):
+ '''
+ Append selected files by add_file to the self.liststore
+ '''
+ not_supported = []
+ for filename in filenames: # filenames : all selected files/folders
+ if os.path.isdir(filename): # if "filename" is a directory
+ for root, dirs, files in os.walk(filename):
+ for item in files:
+ path_to_file = os.path.join(root, item)
+ if self.__add_file_to_treeview(path_to_file):
+ not_supported.append(item)
+ yield True
+ else: # filename is a regular file
+ if self.__add_file_to_treeview(filename):
+ not_supported.append(filename)
+ yield True
+ if not_supported:
+ self.__popup_non_supported(not_supported)
+ yield False
+
+ def __popup_non_supported(self, filelist):
'''
- Check if selected elements are clean
+ Popup that warn the user about the unsupported files
+ that he want to process
'''
+ dialog = Gtk.Dialog(title=_('Not-supported'), parent=self.window,
+ flags=0, buttons=(Gtk.STOCK_OK, 0))
+ vbox = Gtk.VBox(spacing=5)
+ dialog.get_content_area().pack_start(vbox, True, True, 0)
+ store = Gtk.ListStore(str, str)
+
+ # append filename - mimetype to the store
+ for item in filelist:
+ mime = mimetypes.guess_type(item)[0]
+ if mime:
+ store.append([item, mime])
+ else:
+ store.append([item, 'unknown'])
+
+ treeview = Gtk.TreeView(store)
+ vbox.pack_start(treeview, True, True, 0)
+
+ #create column
+ rendererText = Gtk.CellRendererText()
+ column = Gtk.TreeViewColumn(_('Filename'), rendererText, text=0)
+ treeview.append_column(column)
+ column = Gtk.TreeViewColumn(_('Mimetype'), rendererText, text=1)
+ treeview.append_column(column)
+
+ dialog.show_all()
+ click = dialog.run()
+ if not click: # Ok button
+ dialog.destroy()
+
+ def mat_check(self, iterator):
+ ''' Check elements in iterator are clean '''
for line in iterator: # for each file in selection
- self.statusbar.push(0, _('Checking %s...') % self.liststore[line][1])
- if self.force or self.liststore[line][4] != _('Clean'):
+ print self.liststore[line][0].file
+ logging.info('Checking %s' % self.liststore[line][2])
+ self.statusbar.push(0, _('Checking %s...') % self.liststore[line][2])
+
+ if self.force or self.liststore[line][6]:
if self.liststore[line][0].file.is_clean():
- string = _('Clean')
+ self.liststore[line][4] = _('Clean')
+ self.liststore[line][6] = 0
else:
- string = _('Dirty')
- logging.info('%s is %s' % (self.liststore[line][1], string))
- self.liststore[line][4] = string
+ self.liststore[line][4] = _('Dirty')
+ self.liststore[line][6] = 1
+ logging.info('%s is %s' % (self.liststore[line][1], self.liststore[line][4]))
yield True
self.statusbar.push(0, _('Ready'))
yield False
- def __mat_clean(self, iterator):
- '''
- Clean selected elements
- '''
+ def mat_clean(self, iterator):
+ ''' Clean elements in iterator '''
for line in iterator: # for each file in selection
- logging.info('Cleaning %s' % self.liststore[line][1])
- self.statusbar.push(0, _('Cleaning %s...') % self.liststore[line][1])
- if self.force or self.liststore[line][4] != _('Clean'):
+ logging.info('Cleaning %s' % self.liststore[line][2])
+ self.statusbar.push(0, _('Cleaning %s...') % self.liststore[line][2])
+ if self.force or self.liststore[line][6]:
if self.liststore[line][0].file.remove_all():
self.liststore[line][4] = _('Clean')
+ self.liststore[line][6] = 0
if self.backup: # the backup copy state
self.liststore[line][5] = os.path.basename(self.liststore[line][0].file.output)
yield True
@@ -597,7 +447,6 @@ non-anonymised) file to output archive'))
if __name__ == '__main__':
gettext.install('MAT', unicode=True)
- #Main
gui = GUI()
#Add files from command line
--
cgit v1.3
From 4eaf9bffc0f07708c6447b71c7b3e7ad8483e316 Mon Sep 17 00:00:00 2001
From: jvoisin
Date: Sat, 27 Apr 2013 16:41:26 +0200
Subject: Cleaning of the setup.py file
This commit:
- remove the leftover nautilus line
- install the glade file
- remove the leftover tar-related line
---
setup.py | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/setup.py b/setup.py
index eaa4947..f4accba 100755
--- a/setup.py
+++ b/setup.py
@@ -23,15 +23,14 @@ setup(
platforms = 'linux',
license = 'GPLv2',
url = 'https://mat.boum.org',
- packages = ['MAT', 'MAT.hachoir_editor', 'MAT.bencode', 'MAT.tarfile'],
+ packages = ['MAT', 'MAT.hachoir_editor', 'MAT.bencode'],
scripts = ['mat', 'mat-gui'],
data_files = [
( 'share/applications', ['mat.desktop'] ),
- ( 'share/mat', ['data/FORMATS'] ),
+ ( 'share/mat', ['data/FORMATS', 'data/mat.ui'] ),
( 'share/pixmaps', ['data/mat.png'] ),
( 'share/doc/mat', ['README', 'TODO'] ),
( 'share/man/man1', ['mat.1', 'mat-gui.1'] ),
- ( 'share/nautilus-python/extensions', ['nautilus/nautilus-mat.py'] ),
],
cmdclass = {
'build': build_extra.build_extra,
--
cgit v1.3
From 9ef770c24e2d79280f5ae0009a98c44535448ffe Mon Sep 17 00:00:00 2001
From: jvoisin
Date: Sat, 27 Apr 2013 16:45:58 +0200
Subject: Fix a merge mistake
---
mat | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mat b/mat
index 6151c86..d996708 100755
--- a/mat
+++ b/mat
@@ -105,7 +105,7 @@ def list_supported():
handler = mat.XMLParser()
parser = xml.sax.make_parser()
parser.setContentHandler(handler)
- path = os.path.join(mat.get_formats(), 'FORMATS')
+ path = os.path.join(mat.get_datadir(), 'FORMATS')
with open(path, 'r') as xmlfile:
parser.parse(xmlfile)
--
cgit v1.3
From e4194794275b00fbf4710f99e14baa51f2ffe118 Mon Sep 17 00:00:00 2001
From: jvoisin
Date: Mon, 29 Apr 2013 21:50:58 +0200
Subject: Enhancement of drag'n'drop handling
---
mat-gui | 21 +++++++++++----------
1 file changed, 11 insertions(+), 10 deletions(-)
diff --git a/mat-gui b/mat-gui
index 74e8959..a8def3a 100755
--- a/mat-gui
+++ b/mat-gui
@@ -304,19 +304,18 @@ non-anonymised) file to output archive'))
we need to process them
'''
url = urllib2.unquote(url) # unescape stupid chars
- url = url.replace('\n', '')
+ url = url.decode('utf-8') # decode in utf-8
if url.startswith('file:\\\\\\'): # windows
return url[8:] # 8 is len('file:///')
- elif url.startswith('file://'): # nautilus, rox
+ elif url.startswith('file://'): # nautilus, rox, thunar
return url[7:] # 7 is len('file://')
elif url.startswith('file:'): # xffm
return url[5:] # 5 is len('file:')
- urls = selection.get_data().split('\r')
- urls = urls[:-1] # last entry in only a '\n'
+ urls = selection.get_uris()
+ urls = urls[:-1] # last entry in always a '\n'
urls = map(clean_path, urls)
- task = self.populate(urls)
- GObject.idle_add(task.next) # asynchrone processing
+ GObject.idle_add(self.populate(urls).next) # asynchrone processing
def __add_file_to_treeview(self, filename):
'''
@@ -414,8 +413,9 @@ non-anonymised) file to output archive'))
''' Check elements in iterator are clean '''
for line in iterator: # for each file in selection
print self.liststore[line][0].file
- logging.info('Checking %s' % self.liststore[line][2])
- self.statusbar.push(0, _('Checking %s...') % self.liststore[line][2])
+ msg = 'Checking %s ' % self.liststore[line][2]
+ logging.info(msg)
+ self.statusbar.push(0, msg)
if self.force or self.liststore[line][6]:
if self.liststore[line][0].file.is_clean():
@@ -432,8 +432,9 @@ non-anonymised) file to output archive'))
def mat_clean(self, iterator):
''' Clean elements in iterator '''
for line in iterator: # for each file in selection
- logging.info('Cleaning %s' % self.liststore[line][2])
- self.statusbar.push(0, _('Cleaning %s...') % self.liststore[line][2])
+ msg = _('Cleaning %s') % self.liststore[line][2]
+ logging.info(msg)
+ self.statusbar.push(0, msg)
if self.force or self.liststore[line][6]:
if self.liststore[line][0].file.remove_all():
self.liststore[line][4] = _('Clean')
--
cgit v1.3
From f5f1f9b0087a7fe535cc0f0072182f49d39619b2 Mon Sep 17 00:00:00 2001
From: jvoisin
Date: Mon, 29 Apr 2013 22:24:12 +0200
Subject: Drag'n'drop should be working now
---
mat-gui | 2 --
1 file changed, 2 deletions(-)
diff --git a/mat-gui b/mat-gui
index a8def3a..f84994b 100755
--- a/mat-gui
+++ b/mat-gui
@@ -313,7 +313,6 @@ non-anonymised) file to output archive'))
return url[5:] # 5 is len('file:')
urls = selection.get_uris()
- urls = urls[:-1] # last entry in always a '\n'
urls = map(clean_path, urls)
GObject.idle_add(self.populate(urls).next) # asynchrone processing
@@ -412,7 +411,6 @@ non-anonymised) file to output archive'))
def mat_check(self, iterator):
''' Check elements in iterator are clean '''
for line in iterator: # for each file in selection
- print self.liststore[line][0].file
msg = 'Checking %s ' % self.liststore[line][2]
logging.info(msg)
self.statusbar.push(0, msg)
--
cgit v1.3