diff options
| author | Antoine Tenart | 2018-06-13 18:50:10 +0200 |
|---|---|---|
| committer | jvoisin | 2018-07-18 22:38:05 +0200 |
| commit | 926e8dac5f4a695ebbef3bba82d252bd7aee66da (patch) | |
| tree | 14904830a8342dbc67930bc08806ae648a6d066d | |
| parent | edc5f865527a38c3a82e57276217a46b9605f52a (diff) | |
nautilus: first working version
Improve the nautilus extension to get to a first working version:
- Single and multiple selections are working.
- The menu item only is there if mat2 has a chance to work on the
selected files.
- Errors are reported using notifications.
Signed-off-by: Antoine Tenart <antoine.tenart@ack.tf>
| -rw-r--r-- | nautilus/nautilus_mat2.py | 133 |
1 files changed, 123 insertions, 10 deletions
diff --git a/nautilus/nautilus_mat2.py b/nautilus/nautilus_mat2.py index 1216470..409df72 100644 --- a/nautilus/nautilus_mat2.py +++ b/nautilus/nautilus_mat2.py | |||
| @@ -2,28 +2,141 @@ | |||
| 2 | 2 | ||
| 3 | import gi | 3 | import gi |
| 4 | gi.require_version('Nautilus', '3.0') | 4 | gi.require_version('Nautilus', '3.0') |
| 5 | from gi.repository import Nautilus, GObject | 5 | gi.require_version('Gtk', '3.0') |
| 6 | from gi.repository import Nautilus, GObject, Gtk | ||
| 7 | from urllib.parse import unquote | ||
| 8 | |||
| 9 | import os | ||
| 10 | |||
| 11 | from libmat2 import parser_factory | ||
| 12 | |||
| 13 | class Mat2Wrapper(): | ||
| 14 | def __init__(self, filepath): | ||
| 15 | self.filepath = filepath | ||
| 16 | |||
| 17 | class StatusWindow(Gtk.Window): | ||
| 18 | def __init__(self, items): | ||
| 19 | self.window = Gtk.Window() | ||
| 20 | self.window.set_border_width(10) | ||
| 21 | |||
| 22 | self.items = items | ||
| 23 | self.confirm_window() | ||
| 24 | |||
| 25 | def confirm_window(self): | ||
| 26 | # Header bar | ||
| 27 | hb = Gtk.HeaderBar() | ||
| 28 | self.window.set_titlebar(hb) | ||
| 29 | hb.props.title = "Remove metadata" | ||
| 30 | |||
| 31 | cancel = Gtk.Button("Cancel") | ||
| 32 | cancel.connect("clicked", self.cancel_btn) | ||
| 33 | hb.pack_start(cancel) | ||
| 34 | |||
| 35 | self.remove = Gtk.Button("Remove") | ||
| 36 | self.remove.get_style_context().add_class(Gtk.STYLE_CLASS_SUGGESTED_ACTION); | ||
| 37 | self.remove.connect("clicked", self.remove_btn) | ||
| 38 | hb.pack_end(self.remove) | ||
| 39 | |||
| 40 | self.main_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) | ||
| 41 | self.window.add(self.main_box) | ||
| 42 | |||
| 43 | # Disclaimer | ||
| 44 | nitems = len(self.items) | ||
| 45 | if nitems > 1: | ||
| 46 | disclaimer = "Remove metadata from the %d following items:" % nitems | ||
| 47 | else: | ||
| 48 | disclaimer = "Remove metadata from the following item:" | ||
| 49 | self.main_box.pack_start(Gtk.Label(disclaimer, xalign=0), True, True, 0) | ||
| 50 | |||
| 51 | # List of files to clean | ||
| 52 | listbox = Gtk.ListBox() | ||
| 53 | self.main_box.pack_start(listbox, True, True, 0) | ||
| 54 | listbox.set_selection_mode(Gtk.SelectionMode.NONE) | ||
| 55 | for i in self.items: | ||
| 56 | listbox.add(Gtk.Label(os.path.basename(i), xalign=0)) | ||
| 57 | listbox.show_all() | ||
| 58 | |||
| 59 | # Options | ||
| 60 | hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10) | ||
| 61 | self.main_box.pack_start(hbox, True, True, 0) | ||
| 62 | label = Gtk.Label(xalign=0) | ||
| 63 | label.set_markup("Lightweight mode (only remove <i>some</i> metadata)") | ||
| 64 | hbox.pack_start(label, False, True, 0) | ||
| 65 | hbox.pack_start(Gtk.CheckButton(), False, True, 0) | ||
| 66 | |||
| 67 | self.window.show_all() | ||
| 68 | |||
| 69 | def error_window(self, items): | ||
| 70 | self.window.remove(self.main_box) | ||
| 71 | |||
| 72 | box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) | ||
| 73 | self.window.add(box) | ||
| 74 | |||
| 75 | # Disclaimer | ||
| 76 | box.pack_start(Gtk.Label("Could not remove metadata from the following items:", | ||
| 77 | xalign=0), True, True, 0) | ||
| 78 | |||
| 79 | # List of failed files | ||
| 80 | listbox = Gtk.ListBox() | ||
| 81 | box.pack_start(listbox, True, True, 0) | ||
| 82 | listbox.set_selection_mode(Gtk.SelectionMode.NONE) | ||
| 83 | for i in items: | ||
| 84 | listbox.add(Gtk.Label(os.path.basename(i), xalign=0)) | ||
| 85 | listbox.show_all() | ||
| 86 | |||
| 87 | self.window.show_all() | ||
| 88 | self.remove.hide() | ||
| 89 | |||
| 90 | def cancel_btn(self, button): | ||
| 91 | self.window.close() | ||
| 92 | |||
| 93 | def remove_btn(self, button): | ||
| 94 | failed = [] | ||
| 95 | for i in self.items: | ||
| 96 | p, mtype = parser_factory.get_parser(i) | ||
| 97 | if p is not None and p.remove_all(): | ||
| 98 | continue | ||
| 99 | failed.append(i) | ||
| 100 | |||
| 101 | # Everything went the right way, exit | ||
| 102 | if not len(failed): | ||
| 103 | self.window.close() | ||
| 104 | |||
| 105 | self.error_window(failed) | ||
| 6 | 106 | ||
| 7 | class ColumnExtension(GObject.GObject, Nautilus.MenuProvider): | 107 | class ColumnExtension(GObject.GObject, Nautilus.MenuProvider): |
| 8 | def menu_activate_cb(self, menu, file): | 108 | def __validate(self, file): |
| 9 | print "menu_activate_cb", file | 109 | if file.get_uri_scheme() != "file" or file.is_directory(): |
| 10 | # TODO: clean metadata here | 110 | return False |
| 111 | if not file.can_write(): | ||
| 112 | return False | ||
| 113 | return True | ||
| 114 | |||
| 115 | def __validate_set(self, files): | ||
| 116 | for f in files: | ||
| 117 | if self.__validate(f): | ||
| 118 | return True | ||
| 119 | return False | ||
| 120 | |||
| 121 | def menu_activate_cb(self, menu, files): | ||
| 122 | items = list(map(lambda x: unquote(x.get_uri()[7:]), files)) | ||
| 123 | StatusWindow(items) | ||
| 11 | 124 | ||
| 12 | def get_background_items(self, window, file): | 125 | def get_background_items(self, window, file): |
| 13 | """ https://bugzilla.gnome.org/show_bug.cgi?id=784278 """ | 126 | """ https://bugzilla.gnome.org/show_bug.cgi?id=784278 """ |
| 14 | return None | 127 | return None |
| 15 | 128 | ||
| 16 | def get_file_items(self, window, files): | 129 | def get_file_items(self, window, files): |
| 17 | if len(files) != 1: # we're not supporting multiple files for now | 130 | # Do not show the menu item if not a single file has a chance to be |
| 131 | # processed by mat2. | ||
| 132 | if not self.__validate_set(files): | ||
| 18 | return | 133 | return |
| 19 | 134 | ||
| 20 | file = files[0] | ||
| 21 | |||
| 22 | item = Nautilus.MenuItem( | 135 | item = Nautilus.MenuItem( |
| 23 | name="MAT2::Remove_metadata", | 136 | name="MAT2::Remove_metadata", |
| 24 | label="Remove metadata from %s" % file.get_name(), | 137 | label="Remove metadata", |
| 25 | tip="Remove metadata from %s" % file.get_name() | 138 | tip="Remove metadata" |
| 26 | ) | 139 | ) |
| 27 | item.connect('activate', self.menu_activate_cb, file) | 140 | item.connect('activate', self.menu_activate_cb, files) |
| 28 | 141 | ||
| 29 | return [item] | 142 | return [item] |
