diff options
Diffstat (limited to 'plugins/quickopen')
-rw-r--r--[-rwxr-xr-x] | plugins/quickopen/quickopen/__init__.py | 36 | ||||
-rw-r--r--[-rwxr-xr-x] | plugins/quickopen/quickopen/popup.py | 877 | ||||
-rw-r--r--[-rwxr-xr-x] | plugins/quickopen/quickopen/virtualdirs.py | 84 | ||||
-rw-r--r--[-rwxr-xr-x] | plugins/quickopen/quickopen/windowhelper.py | 218 |
4 files changed, 607 insertions, 608 deletions
diff --git a/plugins/quickopen/quickopen/__init__.py b/plugins/quickopen/quickopen/__init__.py index 54e95984..3ae72a45 100755..100644 --- a/plugins/quickopen/quickopen/__init__.py +++ b/plugins/quickopen/quickopen/__init__.py @@ -21,30 +21,30 @@ from gi.repository import GObject, Peas from windowhelper import WindowHelper class QuickOpenPlugin(GObject.Object, Peas.Activatable): - __gtype_name__ = "QuickOpenPlugin" + __gtype_name__ = "QuickOpenPlugin" - object = GObject.Property(type=GObject.Object) + object = GObject.Property(type=GObject.Object) - def __init__(self): - GObject.Object.__init__(self) + def __init__(self): + GObject.Object.__init__(self) - self._popup_size = (450, 300) + self._popup_size = (450, 300) - def do_activate(self): - window = self.object - self._helper = WindowHelper(window, self) + def do_activate(self): + window = self.object + self._helper = WindowHelper(window, self) - def do_deactivate(self): - self._helper.deactivate() - self._helper = None + def do_deactivate(self): + self._helper.deactivate() + self._helper = None - def do_update_state(self): - self._helper.update_ui() + def do_update_state(self): + self._helper.update_ui() - def get_popup_size(self): - return self._popup_size + def get_popup_size(self): + return self._popup_size - def set_popup_size(self, size): - self._popup_size = size + def set_popup_size(self, size): + self._popup_size = size -# ex:ts=8:et: +# ex:ts=4:et: diff --git a/plugins/quickopen/quickopen/popup.py b/plugins/quickopen/quickopen/popup.py index b571b68b..c6cc8016 100755..100644 --- a/plugins/quickopen/quickopen/popup.py +++ b/plugins/quickopen/quickopen/popup.py @@ -24,533 +24,532 @@ from gi.repository import GObject, Gio, GLib, Gdk, Gtk, Pango, Pluma from virtualdirs import VirtualDirectory class Popup(Gtk.Dialog): - __gtype_name__ = "QuickOpenPopup" + __gtype_name__ = "QuickOpenPopup" - def __init__(self, window, paths, handler): - Gtk.Dialog.__init__(self, - title=_('Quick Open'), - parent=window, - flags=Gtk.DialogFlags.DESTROY_WITH_PARENT | Gtk.DialogFlags.MODAL, - buttons=(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL)) + def __init__(self, window, paths, handler): + Gtk.Dialog.__init__(self, + title=_('Quick Open'), + parent=window, + flags=Gtk.DialogFlags.DESTROY_WITH_PARENT | Gtk.DialogFlags.MODAL, + buttons=(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL)) - self._open_button = self.add_button(Gtk.STOCK_OPEN, Gtk.ResponseType.ACCEPT) + self._open_button = self.add_button(Gtk.STOCK_OPEN, Gtk.ResponseType.ACCEPT) - self._handler = handler - self._build_ui() + self._handler = handler + self._build_ui() - self._size = (0, 0) - self._dirs = [] - self._cache = {} - self._theme = None - self._cursor = None - self._shift_start = None + self._size = (0, 0) + self._dirs = [] + self._cache = {} + self._theme = None + self._cursor = None + self._shift_start = None - self._busy_cursor = Gdk.Cursor(Gdk.CursorType.WATCH) + self._busy_cursor = Gdk.Cursor(Gdk.CursorType.WATCH) - accel_group = Gtk.AccelGroup() - accel_group.connect(Gdk.KEY_l, Gdk.ModifierType.CONTROL_MASK, 0, self.on_focus_entry) + accel_group = Gtk.AccelGroup() + accel_group.connect(Gdk.KEY_l, Gdk.ModifierType.CONTROL_MASK, 0, self.on_focus_entry) - self.add_accel_group(accel_group) + self.add_accel_group(accel_group) - unique = [] + unique = [] - for path in paths: - if not path.get_uri() in unique: - self._dirs.append(path) - unique.append(path.get_uri()) + for path in paths: + if not path.get_uri() in unique: + self._dirs.append(path) + unique.append(path.get_uri()) - def get_final_size(self): - return self._size + def get_final_size(self): + return self._size - def _build_ui(self): - vbox = self.get_content_area() - vbox.set_spacing(3) + def _build_ui(self): + vbox = self.get_content_area() + vbox.set_spacing(3) - self._entry = Gtk.Entry() + self._entry = Gtk.Entry() - self._entry.connect('changed', self.on_changed) - self._entry.connect('key-press-event', self.on_key_press_event) + self._entry.connect('changed', self.on_changed) + self._entry.connect('key-press-event', self.on_key_press_event) - sw = Gtk.ScrolledWindow() - sw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) - sw.set_shadow_type(Gtk.ShadowType.OUT) + sw = Gtk.ScrolledWindow() + sw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) + sw.set_shadow_type(Gtk.ShadowType.OUT) - tv = Gtk.TreeView() - tv.set_headers_visible(False) + tv = Gtk.TreeView() + tv.set_headers_visible(False) - self._store = Gtk.ListStore(Gio.Icon, str, GObject.Object, Gio.FileType) - tv.set_model(self._store) + self._store = Gtk.ListStore(Gio.Icon, str, GObject.Object, Gio.FileType) + tv.set_model(self._store) - self._treeview = tv - tv.connect('row-activated', self.on_row_activated) + self._treeview = tv + tv.connect('row-activated', self.on_row_activated) - renderer = Gtk.CellRendererPixbuf() - column = Gtk.TreeViewColumn() - column.pack_start(renderer, False) - column.add_attribute(renderer, "gicon", 0) + renderer = Gtk.CellRendererPixbuf() + column = Gtk.TreeViewColumn() + column.pack_start(renderer, False) + column.add_attribute(renderer, "gicon", 0) - renderer = Gtk.CellRendererText() - column.pack_start(renderer, True) - column.add_attribute(renderer, "markup", 1) + renderer = Gtk.CellRendererText() + column.pack_start(renderer, True) + column.add_attribute(renderer, "markup", 1) - column.set_cell_data_func(renderer, self.on_cell_data_cb, None) + column.set_cell_data_func(renderer, self.on_cell_data_cb, None) - tv.append_column(column) - sw.add(tv) - - selection = tv.get_selection() - selection.connect('changed', self.on_selection_changed) - selection.set_mode(Gtk.SelectionMode.MULTIPLE) + tv.append_column(column) + sw.add(tv) - vbox.pack_start(self._entry, False, False, 0) - vbox.pack_start(sw, True, True, 0) + selection = tv.get_selection() + selection.connect('changed', self.on_selection_changed) + selection.set_mode(Gtk.SelectionMode.MULTIPLE) - lbl = Gtk.Label() - lbl.set_alignment(0, 0.5) - lbl.set_ellipsize(Pango.EllipsizeMode.MIDDLE) - self._info_label = lbl + vbox.pack_start(self._entry, False, False, 0) + vbox.pack_start(sw, True, True, 0) - vbox.pack_start(lbl, False, False, 0) + lbl = Gtk.Label() + lbl.set_alignment(0, 0.5) + lbl.set_ellipsize(Pango.EllipsizeMode.MIDDLE) + self._info_label = lbl - # Initial selection - self.on_selection_changed(tv.get_selection()) - vbox.show_all() + vbox.pack_start(lbl, False, False, 0) - def on_cell_data_cb(self, column, cell, model, piter, user_data): - path = model.get_path(piter) - - if self._cursor and path == self._cursor.get_path(): - style = self._treeview.get_style() - bg = style.bg[Gtk.StateType.PRELIGHT] - - cell.set_property('cell-background-gdk', bg) - cell.set_property('style', Pango.Style.ITALIC) - else: - cell.set_property('cell-background-set', False) - cell.set_property('style-set', False) + # Initial selection + self.on_selection_changed(tv.get_selection()) + vbox.show_all() - def _icon_from_stock(self, stock): - theme = Gtk.icon_theme_get_default() - size = Gtk.icon_size_lookup(Gtk.IconSize.MENU) - pixbuf = theme.load_icon(stock, size[0], Gtk.IconLookupFlags.USE_BUILTIN) + def on_cell_data_cb(self, column, cell, model, piter, user_data): + path = model.get_path(piter) - return pixbuf + if self._cursor and path == self._cursor.get_path(): + style = self._treeview.get_style() + bg = style.bg[Gtk.StateType.PRELIGHT] - def _list_dir(self, gfile): - entries = [] + cell.set_property('cell-background-gdk', bg) + cell.set_property('style', Pango.Style.ITALIC) + else: + cell.set_property('cell-background-set', False) + cell.set_property('style-set', False) - try: - ret = gfile.enumerate_children("standard::*", Gio.FileQueryInfoFlags.NONE, None) - except GLib.GError: - pass + def _icon_from_stock(self, stock): + theme = Gtk.icon_theme_get_default() + size = Gtk.icon_size_lookup(Gtk.IconSize.MENU) + pixbuf = theme.load_icon(stock, size[0], Gtk.IconLookupFlags.USE_BUILTIN) - if isinstance(ret, Gio.FileEnumerator): - while True: - entry = ret.next_file(None) + return pixbuf - if not entry: - break + def _list_dir(self, gfile): + entries = [] - entries.append((gfile.get_child(entry.get_name()), entry)) - else: - entries = ret + try: + ret = gfile.enumerate_children("standard::*", Gio.FileQueryInfoFlags.NONE, None) + except GLib.GError: + pass - children = [] + if isinstance(ret, Gio.FileEnumerator): + while True: + entry = ret.next_file(None) - for entry in entries: - children.append((entry[0], entry[1].get_name(), entry[1].get_file_type(), entry[1].get_icon())) + if not entry: + break - return children + entries.append((gfile.get_child(entry.get_name()), entry)) + else: + entries = ret - def _compare_entries(self, a, b, lpart): - if lpart in a: - if lpart in b: - return cmp(a.index(lpart), b.index(lpart)) - else: - return -1 - elif lpart in b: - return 1 - else: - return 0 + children = [] - def _match_glob(self, s, glob): - if glob: - glob += '*' + for entry in entries: + children.append((entry[0], entry[1].get_name(), entry[1].get_file_type(), entry[1].get_icon())) - return fnmatch.fnmatch(s, glob) + return children - def do_search_dir(self, parts, d): - if not parts or not d: - return [] + def _compare_entries(self, a, b, lpart): + if lpart in a: + if lpart in b: + return cmp(a.index(lpart), b.index(lpart)) + else: + return -1 + elif lpart in b: + return 1 + else: + return 0 - if not d in self._cache: - entries = self._list_dir(d) - entries.sort(lambda x, y: cmp(x[1].lower(), y[1].lower())) + def _match_glob(self, s, glob): + if glob: + glob += '*' - self._cache[d] = entries - else: - entries = self._cache[d] + return fnmatch.fnmatch(s, glob) - found = [] - newdirs = [] + def do_search_dir(self, parts, d): + if not parts or not d: + return [] - lpart = parts[0].lower() + if not d in self._cache: + entries = self._list_dir(d) + entries.sort(lambda x, y: cmp(x[1].lower(), y[1].lower())) - for entry in entries: - if not entry: - continue + self._cache[d] = entries + else: + entries = self._cache[d] - lentry = entry[1].lower() + found = [] + newdirs = [] - if not lpart or lpart in lentry or self._match_glob(lentry, lpart): - if entry[2] == Gio.FileType.DIRECTORY: - if len(parts) > 1: - newdirs.append(entry[0]) - else: - found.append(entry) - elif entry[2] == Gio.FileType.REGULAR and \ - (not lpart or len(parts) == 1): - found.append(entry) + lpart = parts[0].lower() - found.sort(lambda a, b: self._compare_entries(a[1].lower(), b[1].lower(), lpart)) + for entry in entries: + if not entry: + continue - if lpart == '..': - newdirs.append(d.get_parent()) + lentry = entry[1].lower() - for dd in newdirs: - found.extend(self.do_search_dir(parts[1:], dd)) + if not lpart or lpart in lentry or self._match_glob(lentry, lpart): + if entry[2] == Gio.FileType.DIRECTORY: + if len(parts) > 1: + newdirs.append(entry[0]) + else: + found.append(entry) + elif entry[2] == Gio.FileType.REGULAR and \ + (not lpart or len(parts) == 1): + found.append(entry) - return found + found.sort(lambda a, b: self._compare_entries(a[1].lower(), b[1].lower(), lpart)) - def _replace_insensitive(self, s, find, rep): - out = '' - l = s.lower() - find = find.lower() - last = 0 + if lpart == '..': + newdirs.append(d.get_parent()) - if len(find) == 0: - return xml.sax.saxutils.escape(s) + for dd in newdirs: + found.extend(self.do_search_dir(parts[1:], dd)) - while True: - m = l.find(find, last) + return found - if m == -1: - break - else: - out += xml.sax.saxutils.escape(s[last:m]) + rep % (xml.sax.saxutils.escape(s[m:m + len(find)]),) - last = m + len(find) + def _replace_insensitive(self, s, find, rep): + out = '' + l = s.lower() + find = find.lower() + last = 0 - return out + xml.sax.saxutils.escape(s[last:]) + if len(find) == 0: + return xml.sax.saxutils.escape(s) + while True: + m = l.find(find, last) - def make_markup(self, parts, path): - out = [] + if m == -1: + break + else: + out += xml.sax.saxutils.escape(s[last:m]) + rep % (xml.sax.saxutils.escape(s[m:m + len(find)]),) + last = m + len(find) - for i in range(0, len(parts)): - out.append(self._replace_insensitive(path[i], parts[i], "<b>%s</b>")) + return out + xml.sax.saxutils.escape(s[last:]) - return os.sep.join(out) + def make_markup(self, parts, path): + out = [] - def _get_icon(self, f): - query = f.query_info(Gio.FILE_ATTRIBUTE_STANDARD_ICON, Gio.FileQueryInfoFlags.NONE, None) + for i in range(0, len(parts)): + out.append(self._replace_insensitive(path[i], parts[i], "<b>%s</b>")) - if not query: - return None - else: - return query.get_icon() + return os.sep.join(out) - def _make_parts(self, parent, child, pp): - parts = [] + def _get_icon(self, f): + query = f.query_info(Gio.FILE_ATTRIBUTE_STANDARD_ICON, Gio.FileQueryInfoFlags.NONE, None) - # We went from parent, to child, using pp - idx = len(pp) - 1 + if not query: + return None + else: + return query.get_icon() - while idx >= 0: - if pp[idx] == '..': - parts.insert(0, '..') - else: - parts.insert(0, child.get_basename()) - child = child.get_parent() + def _make_parts(self, parent, child, pp): + parts = [] - idx -= 1 + # We went from parent, to child, using pp + idx = len(pp) - 1 - return parts + while idx >= 0: + if pp[idx] == '..': + parts.insert(0, '..') + else: + parts.insert(0, child.get_basename()) + child = child.get_parent() - def normalize_relative(self, parts): - if not parts: - return [] + idx -= 1 - out = self.normalize_relative(parts[:-1]) + return parts - if parts[-1] == '..': - if not out or (out[-1] == '..') or len(out) == 1: - out.append('..') - else: - del out[-1] - else: - out.append(parts[-1]) + def normalize_relative(self, parts): + if not parts: + return [] - return out + out = self.normalize_relative(parts[:-1]) - def _append_to_store(self, item): - if not item in self._stored_items: - self._store.append(item) - self._stored_items[item] = True + if parts[-1] == '..': + if not out or (out[-1] == '..') or len(out) == 1: + out.append('..') + else: + del out[-1] + else: + out.append(parts[-1]) - def _clear_store(self): - self._store.clear() - self._stored_items = {} + return out - def _show_virtuals(self): - for d in self._dirs: - if isinstance(d, VirtualDirectory): - for entry in d.enumerate_children("standard::*", 0, None): - self._append_to_store((entry[1].get_icon(), xml.sax.saxutils.escape(entry[1].get_name()), entry[0], entry[1].get_file_type())) + def _append_to_store(self, item): + if not item in self._stored_items: + self._store.append(item) + self._stored_items[item] = True - def _set_busy(self, busy): - if busy: - self.get_window().set_cursor(self._busy_cursor) - else: - self.get_window().set_cursor(None) + def _clear_store(self): + self._store.clear() + self._stored_items = {} - Gdk.flush() + def _show_virtuals(self): + for d in self._dirs: + if isinstance(d, VirtualDirectory): + for entry in d.enumerate_children("standard::*", 0, None): + self._append_to_store((entry[1].get_icon(), xml.sax.saxutils.escape(entry[1].get_name()), entry[0], entry[1].get_file_type())) - def _remove_cursor(self): - if self._cursor: - path = self._cursor.get_path() - self._cursor = None + def _set_busy(self, busy): + if busy: + self.get_window().set_cursor(self._busy_cursor) + else: + self.get_window().set_cursor(None) - self._store.row_changed(path, self._store.get_iter(path)) + Gdk.flush() - def do_search(self): - self._set_busy(True) - self._remove_cursor() + def _remove_cursor(self): + if self._cursor: + path = self._cursor.get_path() + self._cursor = None - text = self._entry.get_text().strip() - self._clear_store() + self._store.row_changed(path, self._store.get_iter(path)) - if text == '': - self._show_virtuals() - else: - parts = self.normalize_relative(text.split(os.sep)) - files = [] + def do_search(self): + self._set_busy(True) + self._remove_cursor() - for d in self._dirs: - for entry in self.do_search_dir(parts, d): - pathparts = self._make_parts(d, entry[0], parts) - self._append_to_store((entry[3], self.make_markup(parts, pathparts), entry[0], entry[2])) + text = self._entry.get_text().strip() + self._clear_store() - piter = self._store.get_iter_first() + if text == '': + self._show_virtuals() + else: + parts = self.normalize_relative(text.split(os.sep)) + files = [] - if piter: - self._treeview.get_selection().select_path(self._store.get_path(piter)) + for d in self._dirs: + for entry in self.do_search_dir(parts, d): + pathparts = self._make_parts(d, entry[0], parts) + self._append_to_store((entry[3], self.make_markup(parts, pathparts), entry[0], entry[2])) - self.get_window().set_cursor(None) - self._set_busy(False) + piter = self._store.get_iter_first() - def do_show(self): - Gtk.Window.do_show(self) + if piter: + self._treeview.get_selection().select_path(self._store.get_path(piter)) - self._entry.grab_focus() - self._entry.set_text("") - - self.do_search() - - def on_changed(self, editable): - self.do_search() - self.on_selection_changed(self._treeview.get_selection()) - - def _shift_extend(self, towhere): - selection = self._treeview.get_selection() - - if not self._shift_start: - model, rows = selection.get_selected_rows() - start = rows[0] - - self._shift_start = Gtk.TreeRowReference(self._store, start) - else: - start = self._shift_start.get_path() - - selection.unselect_all() - selection.select_range(start, towhere) - - def _select_index(self, idx, hasctrl, hasshift): - path = (idx,) - - if not (hasctrl or hasshift): - self._treeview.get_selection().unselect_all() - - if hasshift: - self._shift_extend(path) - else: - self._shift_start = None - - if not hasctrl: - self._treeview.get_selection().select_path(path) - - self._treeview.scroll_to_cell(path, None, True, 0.5, 0) - self._remove_cursor() - - if hasctrl or hasshift: - self._cursor = Gtk.TreeRowReference(self._store, path) - - piter = self._store.get_iter(path) - self._store.row_changed(path, piter) - - def _move_selection(self, howmany, hasctrl, hasshift): - num = self._store.iter_n_children(None) - - if num == 0: - return True - - # Test for cursor - path = None - - if self._cursor: - path = self._cursor.get_path() - else: - model, rows = self._treeview.get_selection().get_selected_rows() - - if len(rows) == 1: - path = rows[0] - - if not path: - if howmany > 0: - self._select_index(0, hasctrl, hasshift) - else: - self._select_index(num - 1, hasctrl, hasshift) - else: - idx = path[0] - - if idx + howmany < 0: - self._select_index(0, hasctrl, hasshift) - elif idx + howmany >= num: - self._select_index(num - 1, hasctrl, hasshift) - else: - self._select_index(idx + howmany, hasctrl, hasshift) + self.get_window().set_cursor(None) + self._set_busy(False) - return True + def do_show(self): + Gtk.Window.do_show(self) + + self._entry.grab_focus() + self._entry.set_text("") + + self.do_search() + + def on_changed(self, editable): + self.do_search() + self.on_selection_changed(self._treeview.get_selection()) + + def _shift_extend(self, towhere): + selection = self._treeview.get_selection() + + if not self._shift_start: + model, rows = selection.get_selected_rows() + start = rows[0] + + self._shift_start = Gtk.TreeRowReference(self._store, start) + else: + start = self._shift_start.get_path() + + selection.unselect_all() + selection.select_range(start, towhere) + + def _select_index(self, idx, hasctrl, hasshift): + path = (idx,) + + if not (hasctrl or hasshift): + self._treeview.get_selection().unselect_all() + + if hasshift: + self._shift_extend(path) + else: + self._shift_start = None + + if not hasctrl: + self._treeview.get_selection().select_path(path) + + self._treeview.scroll_to_cell(path, None, True, 0.5, 0) + self._remove_cursor() + + if hasctrl or hasshift: + self._cursor = Gtk.TreeRowReference(self._store, path) + + piter = self._store.get_iter(path) + self._store.row_changed(path, piter) + + def _move_selection(self, howmany, hasctrl, hasshift): + num = self._store.iter_n_children(None) - def _direct_file(self): - uri = self._entry.get_text() - gfile = None - - if Pluma.utils_is_valid_uri(uri): - gfile = Gio.file_new_for_uri(uri) - elif os.path.isabs(uri): - f = Gio.file_new_for_uri(uri) - - if f.query_exists(): - gfile = f - - return gfile - - def _activate(self): - model, rows = self._treeview.get_selection().get_selected_rows() - ret = True - - for row in rows: - s = model.get_iter(row) - info = model.get(s, 2, 3) - - if info[1] != Gio.FileType.DIRECTORY: - ret = ret and self._handler(info[0]) - else: - text = self._entry.get_text() - - for i in range(len(text) - 1, -1, -1): - if text[i] == os.sep: - break - - self._entry.set_text(os.path.join(text[:i], os.path.basename(info[0].get_uri())) + os.sep) - self._entry.set_position(-1) - self._entry.grab_focus() - return True - - if rows and ret: - self.destroy() - - if not rows: - gfile = self._direct_file() - - if gfile and self._handler(gfile): - self.destroy() - else: - ret = False - else: - ret = False - - return ret - - def toggle_cursor(self): - if not self._cursor: - return - - path = self._cursor.get_path() - selection = self._treeview.get_selection() - - if selection.path_is_selected(path): - selection.unselect_path(path) - else: - selection.select_path(path) - - def on_key_press_event(self, widget, event): - move_mapping = { - Gdk.KEY_Down: 1, - Gdk.KEY_Up: -1, - Gdk.KEY_Page_Down: 5, - Gdk.KEY_Page_Up: -5 - } - - if event.keyval == Gdk.KEY_Escape: - self.destroy() - return True - elif event.keyval in move_mapping: - return self._move_selection(move_mapping[event.keyval], event.state & Gdk.ModifierType.CONTROL_MASK, event.state & Gdk.ModifierType.SHIFT_MASK) - elif event.keyval in [Gdk.KEY_Return, Gdk.KEY_KP_Enter, Gdk.KEY_Tab, Gdk.KEY_ISO_Left_Tab]: - return self._activate() - elif event.keyval == Gdk.KEY_space and event.state & Gdk.ModifierType.CONTROL_MASK: - self.toggle_cursor() - - return False - - def on_row_activated(self, view, path, column): - self._activate() - - def do_response(self, response): - if response != Gtk.ResponseType.ACCEPT or not self._activate(): - self.destroy() - - def do_configure_event(self, event): - if self.get_realized(): - alloc = self.get_allocation() - self._size = (alloc.width, alloc.height) - - return Gtk.Dialog.do_configure_event(self, event) - - def on_selection_changed(self, selection): - model, rows = selection.get_selected_rows() - - gfile = None - fname = None - - if not rows: - gfile = self._direct_file() - elif len(rows) == 1: - gfile = model.get(model.get_iter(rows[0]), 2)[0] - else: - fname = '' - - if gfile: - if gfile.is_native(): - fname = xml.sax.saxutils.escape(gfile.get_path()) - else: - fname = xml.sax.saxutils.escape(gfile.get_uri()) - - self._open_button.set_sensitive(fname != None) - self._info_label.set_markup(fname or '') - - def on_focus_entry(self, group, accel, keyval, modifier): + if num == 0: + return True + + # Test for cursor + path = None + + if self._cursor: + path = self._cursor.get_path() + else: + model, rows = self._treeview.get_selection().get_selected_rows() + + if len(rows) == 1: + path = rows[0] + + if not path: + if howmany > 0: + self._select_index(0, hasctrl, hasshift) + else: + self._select_index(num - 1, hasctrl, hasshift) + else: + idx = path[0] + + if idx + howmany < 0: + self._select_index(0, hasctrl, hasshift) + elif idx + howmany >= num: + self._select_index(num - 1, hasctrl, hasshift) + else: + self._select_index(idx + howmany, hasctrl, hasshift) + + return True + + def _direct_file(self): + uri = self._entry.get_text() + gfile = None + + if Pluma.utils_is_valid_uri(uri): + gfile = Gio.file_new_for_uri(uri) + elif os.path.isabs(uri): + f = Gio.file_new_for_uri(uri) + + if f.query_exists(): + gfile = f + + return gfile + + def _activate(self): + model, rows = self._treeview.get_selection().get_selected_rows() + ret = True + + for row in rows: + s = model.get_iter(row) + info = model.get(s, 2, 3) + + if info[1] != Gio.FileType.DIRECTORY: + ret = ret and self._handler(info[0]) + else: + text = self._entry.get_text() + + for i in range(len(text) - 1, -1, -1): + if text[i] == os.sep: + break + + self._entry.set_text(os.path.join(text[:i], os.path.basename(info[0].get_uri())) + os.sep) + self._entry.set_position(-1) self._entry.grab_focus() + return True -# ex:ts=8:et: + if rows and ret: + self.destroy() + + if not rows: + gfile = self._direct_file() + + if gfile and self._handler(gfile): + self.destroy() + else: + ret = False + else: + ret = False + + return ret + + def toggle_cursor(self): + if not self._cursor: + return + + path = self._cursor.get_path() + selection = self._treeview.get_selection() + + if selection.path_is_selected(path): + selection.unselect_path(path) + else: + selection.select_path(path) + + def on_key_press_event(self, widget, event): + move_mapping = { + Gdk.KEY_Down: 1, + Gdk.KEY_Up: -1, + Gdk.KEY_Page_Down: 5, + Gdk.KEY_Page_Up: -5 + } + + if event.keyval == Gdk.KEY_Escape: + self.destroy() + return True + elif event.keyval in move_mapping: + return self._move_selection(move_mapping[event.keyval], event.state & Gdk.ModifierType.CONTROL_MASK, event.state & Gdk.ModifierType.SHIFT_MASK) + elif event.keyval in [Gdk.KEY_Return, Gdk.KEY_KP_Enter, Gdk.KEY_Tab, Gdk.KEY_ISO_Left_Tab]: + return self._activate() + elif event.keyval == Gdk.KEY_space and event.state & Gdk.ModifierType.CONTROL_MASK: + self.toggle_cursor() + + return False + + def on_row_activated(self, view, path, column): + self._activate() + + def do_response(self, response): + if response != Gtk.ResponseType.ACCEPT or not self._activate(): + self.destroy() + + def do_configure_event(self, event): + if self.get_realized(): + alloc = self.get_allocation() + self._size = (alloc.width, alloc.height) + + return Gtk.Dialog.do_configure_event(self, event) + + def on_selection_changed(self, selection): + model, rows = selection.get_selected_rows() + + gfile = None + fname = None + + if not rows: + gfile = self._direct_file() + elif len(rows) == 1: + gfile = model.get(model.get_iter(rows[0]), 2)[0] + else: + fname = '' + + if gfile: + if gfile.is_native(): + fname = xml.sax.saxutils.escape(gfile.get_path()) + else: + fname = xml.sax.saxutils.escape(gfile.get_uri()) + + self._open_button.set_sensitive(fname != None) + self._info_label.set_markup(fname or '') + + def on_focus_entry(self, group, accel, keyval, modifier): + self._entry.grab_focus() + +# ex:ts=4:et: diff --git a/plugins/quickopen/quickopen/virtualdirs.py b/plugins/quickopen/quickopen/virtualdirs.py index a2d6985a..53d716a2 100755..100644 --- a/plugins/quickopen/quickopen/virtualdirs.py +++ b/plugins/quickopen/quickopen/virtualdirs.py @@ -20,64 +20,64 @@ from gi.repository import Gio, Gtk class VirtualDirectory(object): - def __init__(self, name): - self._name = name - self._children = [] + def __init__(self, name): + self._name = name + self._children = [] - def get_uri(self): - return 'virtual://' + self._name + def get_uri(self): + return 'virtual://' + self._name - def get_parent(self): - return None + def get_parent(self): + return None - def enumerate_children(self, attr, flags, callback): - return self._children + def enumerate_children(self, attr, flags, callback): + return self._children - def append(self, child): - if not child.is_native(): - return + def append(self, child): + if not child.is_native(): + return - try: - info = child.query_info("standard::*", Gio.FileQueryInfoFlags.NONE, None) + try: + info = child.query_info("standard::*", Gio.FileQueryInfoFlags.NONE, None) - if info: - self._children.append((child, info)) - except: - pass + if info: + self._children.append((child, info)) + except: + pass class RecentDocumentsDirectory(VirtualDirectory): - def __init__(self, maxitems=10): - VirtualDirectory.__init__(self, 'recent') + def __init__(self, maxitems=10): + VirtualDirectory.__init__(self, 'recent') - self._maxitems = maxitems - self.fill() + self._maxitems = maxitems + self.fill() - def fill(self): - manager = Gtk.RecentManager.get_default() + def fill(self): + manager = Gtk.RecentManager.get_default() - items = manager.get_items() - items.sort(lambda a, b: cmp(b.get_visited(), a.get_visited())) + items = manager.get_items() + items.sort(lambda a, b: cmp(b.get_visited(), a.get_visited())) - added = 0 + added = 0 - for item in items: - if item.has_group('pluma'): - self.append(Gio.file_new_for_uri(item.get_uri())) - added += 1 + for item in items: + if item.has_group('pluma'): + self.append(Gio.file_new_for_uri(item.get_uri())) + added += 1 - if added >= self._maxitems: - break + if added >= self._maxitems: + break class CurrentDocumentsDirectory(VirtualDirectory): - def __init__(self, window): - VirtualDirectory.__init__(self, 'documents') + def __init__(self, window): + VirtualDirectory.__init__(self, 'documents') - self.fill(window) + self.fill(window) - def fill(self, window): - for doc in window.get_documents(): - location = doc.get_location() - if location: - self.append(location) + def fill(self, window): + for doc in window.get_documents(): + location = doc.get_location() + if location: + self.append(location) -# ex:ts=8:et: +# ex:ts=4:et: diff --git a/plugins/quickopen/quickopen/windowhelper.py b/plugins/quickopen/quickopen/windowhelper.py index c23629cf..19e44cba 100755..100644 --- a/plugins/quickopen/quickopen/windowhelper.py +++ b/plugins/quickopen/quickopen/windowhelper.py @@ -27,7 +27,7 @@ ui_str = """<ui> <menubar name="MenuBar"> <menu name="FileMenu" action="File"> <placeholder name="FileOps_2"> - <menuitem name="QuickOpen" action="QuickOpen"/> + <menuitem name="QuickOpen" action="QuickOpen"/> </placeholder> </menu> </menubar> @@ -35,157 +35,157 @@ ui_str = """<ui> """ class WindowHelper: - def __init__(self, window, plugin): - self._window = window - self._plugin = plugin + def __init__(self, window, plugin): + self._window = window + self._plugin = plugin - self._popup = None - self._install_menu() + self._popup = None + self._install_menu() - def deactivate(self): - self._uninstall_menu() - self._window = None - self._plugin = None + def deactivate(self): + self._uninstall_menu() + self._window = None + self._plugin = None - def update_ui(self): - pass + def update_ui(self): + pass - def _uninstall_menu(self): - manager = self._window.get_ui_manager() + def _uninstall_menu(self): + manager = self._window.get_ui_manager() - manager.remove_ui(self._ui_id) - manager.remove_action_group(self._action_group) + manager.remove_ui(self._ui_id) + manager.remove_action_group(self._action_group) - manager.ensure_update() + manager.ensure_update() - def _install_menu(self): - manager = self._window.get_ui_manager() - self._action_group = Gtk.ActionGroup("PlumaQuickOpenPluginActions") - self._action_group.add_actions([ - ("QuickOpen", Gtk.STOCK_OPEN, _("Quick open"), - '<Ctrl><Alt>O', _("Quickly open documents"), - self.on_quick_open_activate) - ]) + def _install_menu(self): + manager = self._window.get_ui_manager() + self._action_group = Gtk.ActionGroup("PlumaQuickOpenPluginActions") + self._action_group.add_actions([ + ("QuickOpen", Gtk.STOCK_OPEN, _("Quick open"), + '<Ctrl><Alt>O', _("Quickly open documents"), + self.on_quick_open_activate) + ]) - manager.insert_action_group(self._action_group, -1) - self._ui_id = manager.add_ui_from_string(ui_str) + manager.insert_action_group(self._action_group, -1) + self._ui_id = manager.add_ui_from_string(ui_str) - def _create_popup(self): - paths = [] + def _create_popup(self): + paths = [] - # Open documents - paths.append(CurrentDocumentsDirectory(self._window)) + # Open documents + paths.append(CurrentDocumentsDirectory(self._window)) - doc = self._window.get_active_document() + doc = self._window.get_active_document() - # Current document directory - if doc and doc.is_local(): - gfile = doc.get_location() - paths.append(gfile.get_parent()) + # Current document directory + if doc and doc.is_local(): + gfile = doc.get_location() + paths.append(gfile.get_parent()) - # File browser root directory - bus = self._window.get_message_bus() + # File browser root directory + bus = self._window.get_message_bus() - try: - msg = bus.send_sync('/plugins/filebrowser', 'get_root') + try: + msg = bus.send_sync('/plugins/filebrowser', 'get_root') - if msg: - uri = msg.get_value('uri') + if msg: + uri = msg.get_value('uri') - if uri: - gfile = Gio.file_new_for_uri(uri) + if uri: + gfile = Gio.file_new_for_uri(uri) - if gfile.is_native(): - paths.append(gfile) + if gfile.is_native(): + paths.append(gfile) - except StandardError: - pass + except StandardError: + pass - # Recent documents - paths.append(RecentDocumentsDirectory()) + # Recent documents + paths.append(RecentDocumentsDirectory()) - # Local bookmarks - for path in self._local_bookmarks(): - paths.append(path) + # Local bookmarks + for path in self._local_bookmarks(): + paths.append(path) - # Desktop directory - desktopdir = self._desktop_dir() + # Desktop directory + desktopdir = self._desktop_dir() - if desktopdir: - paths.append(Gio.file_new_for_path(desktopdir)) + if desktopdir: + paths.append(Gio.file_new_for_path(desktopdir)) - # Home directory - paths.append(Gio.file_new_for_path(os.path.expanduser('~'))) + # Home directory + paths.append(Gio.file_new_for_path(os.path.expanduser('~'))) - self._popup = Popup(self._window, paths, self.on_activated) + self._popup = Popup(self._window, paths, self.on_activated) - self._popup.set_default_size(*self._plugin.get_popup_size()) - self._popup.set_transient_for(self._window) - self._popup.set_position(Gtk.WindowPosition.CENTER_ON_PARENT) + self._popup.set_default_size(*self._plugin.get_popup_size()) + self._popup.set_transient_for(self._window) + self._popup.set_position(Gtk.WindowPosition.CENTER_ON_PARENT) - self._window.get_group().add_window(self._popup) + self._window.get_group().add_window(self._popup) - self._popup.connect('destroy', self.on_popup_destroy) + self._popup.connect('destroy', self.on_popup_destroy) - def _local_bookmarks(self): - filename = os.path.expanduser('~/.gtk-bookmarks') + def _local_bookmarks(self): + filename = os.path.expanduser('~/.gtk-bookmarks') - if not os.path.isfile(filename): - return [] + if not os.path.isfile(filename): + return [] - paths = [] + paths = [] - for line in file(filename, 'r').xreadlines(): - uri = line.strip().split(" ")[0] - f = Gio.file_new_for_uri(uri) + for line in file(filename, 'r').xreadlines(): + uri = line.strip().split(" ")[0] + f = Gio.file_new_for_uri(uri) - if f.is_native(): - try: - info = f.query_info(Gio.FILE_ATTRIBUTE_STANDARD_TYPE, Gio.FileQueryInfoFlags.NONE, None) + if f.is_native(): + try: + info = f.query_info(Gio.FILE_ATTRIBUTE_STANDARD_TYPE, Gio.FileQueryInfoFlags.NONE, None) - if info and info.get_file_type() == Gio.FileType.DIRECTORY: - paths.append(f) - except GLib.GError: - pass + if info and info.get_file_type() == Gio.FileType.DIRECTORY: + paths.append(f) + except GLib.GError: + pass - return paths + return paths - def _desktop_dir(self): - config = os.getenv('XDG_CONFIG_HOME') + def _desktop_dir(self): + config = os.getenv('XDG_CONFIG_HOME') - if not config: - config = os.path.expanduser('~/.config') + if not config: + config = os.path.expanduser('~/.config') - config = os.path.join(config, 'user-dirs.dirs') - desktopdir = None + config = os.path.join(config, 'user-dirs.dirs') + desktopdir = None - if os.path.isfile(config): - for line in file(config, 'r').xreadlines(): - line = line.strip() + if os.path.isfile(config): + for line in file(config, 'r').xreadlines(): + line = line.strip() - if line.startswith('XDG_DESKTOP_DIR'): - parts = line.split('=', 1) - desktopdir = os.path.expandvars(parts[1].strip('"').strip("'")) - break + if line.startswith('XDG_DESKTOP_DIR'): + parts = line.split('=', 1) + desktopdir = os.path.expandvars(parts[1].strip('"').strip("'")) + break - if not desktopdir: - desktopdir = os.path.expanduser('~/Desktop') + if not desktopdir: + desktopdir = os.path.expanduser('~/Desktop') - return desktopdir + return desktopdir - # Callbacks - def on_quick_open_activate(self, action): - if not self._popup: - self._create_popup() + # Callbacks + def on_quick_open_activate(self, action): + if not self._popup: + self._create_popup() - self._popup.show() + self._popup.show() - def on_popup_destroy(self, popup): - self._plugin.set_popup_size(popup.get_final_size()) - self._popup = None + def on_popup_destroy(self, popup): + self._plugin.set_popup_size(popup.get_final_size()) + self._popup = None - def on_activated(self, gfile): - Pluma.commands_load_uri(self._window, gfile.get_uri(), None, -1) - return True + def on_activated(self, gfile): + Pluma.commands_load_uri(self._window, gfile.get_uri(), None, -1) + return True -# ex:ts=8:et: +# ex:ts=4:et: |