From c66637116ba25c05588957f9c976182a83704fcd Mon Sep 17 00:00:00 2001 From: Pedro Algarvio Date: Sun, 29 May 2011 17:10:57 +0100 Subject: [PATCH 1/2] Allow searching torrents by name on the GTK UI. --- deluge/core/filtermanager.py | 7 + deluge/ui/gtkui/glade/main_window.glade | 487 ++++++++++-------------- deluge/ui/gtkui/torrentview.py | 37 ++ 3 files changed, 236 insertions(+), 295 deletions(-) diff --git a/deluge/core/filtermanager.py b/deluge/core/filtermanager.py index e04cb9dbb..c52fec29b 100644 --- a/deluge/core/filtermanager.py +++ b/deluge/core/filtermanager.py @@ -78,6 +78,12 @@ def filter_one_keyword(torrent_ids, keyword): yield torrent_id break +def filter_by_name(torrent_ids, search_string): + all_torrents = component.get("TorrentManager").torrents + for torrent_id in torrent_ids: + if search_string[0].lower() in all_torrents[torrent_id].filename.lower(): + yield torrent_id + def tracker_error_filter(torrent_ids, values): filtered_torrent_ids = [] tm = component.get("TorrentManager") @@ -108,6 +114,7 @@ class FilterManager(component.Component): self.torrents = core.torrentmanager self.registered_filters = {} self.register_filter("keyword", filter_keywords) + self.register_filter("name", filter_by_name) self.tree_fields = {} self.register_tree_field("state", self._init_state_tree) diff --git a/deluge/ui/gtkui/glade/main_window.glade b/deluge/ui/gtkui/glade/main_window.glade index 4dd91c296..97dbd5509 100644 --- a/deluge/ui/gtkui/glade/main_window.glade +++ b/deluge/ui/gtkui/glade/main_window.glade @@ -384,174 +384,217 @@ - + True False - + True - False False - Add torrent - False - Add Torrent - True - gtk-add - + + + True + False + False + True + Add torrent + False + Add Torrent + True + gtk-add + + + + False + True + + + + + True + False + False + True + Remove torrent + False + Remove Torrent + gtk-remove + + + + False + True + + + + + True + False + + + False + + + + + True + False + False + True + Pause the selected torrents + False + Pause + True + gtk-media-pause + + + + False + True + + + + + True + False + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + True + Resume the selected torrents + False + Resume + gtk-media-play + + + + False + True + + + + + True + False + + + False + + + + + True + False + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + True + Queue Torrent Up + False + Queue Up + gtk-go-up + + + + False + True + + + + + True + False + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + True + Queue Torrent Down + False + Queue Down + gtk-go-down + + + + False + True + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + False + + + + + True + False + True + Preferences + False + Preferences + True + gtk-preferences + + + + False + True + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + True + Connection Manager + False + Connection Manager + gtk-network + + + + False + True + + - False - True + True + True + 0 - + True - False - False - Remove torrent - False - Remove Torrent - gtk-remove - + True + Search torrents by name + + True + False + gtk-clear + False + True + False + True + Clear the search + + False - True - - - - - True - False - - - False - - - - - True - False - False - Pause the selected torrents - False - Pause - True - gtk-media-pause - - - - False - True - - - - - True - False - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Resume the selected torrents - False - Resume - gtk-media-play - - - - False - True - - - - - True - False - - - False - - - - - True - False - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Queue Torrent Up - False - Queue Up - gtk-go-up - - - - False - True - - - - - True - False - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Queue Torrent Down - False - Queue Down - gtk-go-down - - - - False - True - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - False - - - - - True - False - Preferences - False - Preferences - True - gtk-preferences - - - - False - True - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Connection Manager - False - Connection Manager - gtk-network - - - - False - True + False + 5 + 1 False - True + False 1 @@ -641,152 +684,6 @@ - - True - False - - - gtk-open - True - False - False - True - True - - - - - - True - False - - - - - _Expand All - True - False - False - True - False - - - - True - False - gtk-zoom-fit - 1 - - - - - - - True - False - - - - - _Do Not Download - True - False - False - True - False - - - - True - False - gtk-no - 1 - - - - - - - _Normal Priority - True - False - False - True - False - - - - True - False - gtk-yes - 1 - - - - - - - _High Priority - True - False - False - True - False - - - - True - False - gtk-go-up - 1 - - - - - - - Hi_ghest Priority - True - False - False - True - False - - - - True - False - gtk-goto-top - 1 - - - - - - - True - False - - - _Add Peer - True - False - Add a peer by its IP - False - True - False - - - - True - False - gtk-add - 1 - - - - - False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK diff --git a/deluge/ui/gtkui/torrentview.py b/deluge/ui/gtkui/torrentview.py index ab23f45ad..67fae6adf 100644 --- a/deluge/ui/gtkui/torrentview.py +++ b/deluge/ui/gtkui/torrentview.py @@ -287,6 +287,15 @@ class TorrentView(listview.ListView, component.Component): self.treeview.connect("key-press-event", self.on_key_press_event) self.treeview.connect("columns-changed", self.on_columns_changed_event) + self.search_torrents_entry = self.window.main_glade.get_widget("search_torrents_entry") + self.search_torrents_entry.connect( + "icon-press", self.on_search_torrents_entry_icon_press + ) + self.search_torrents_entry.connect( + "changed", self.on_search_torrents_entry_changed + ) + + client.register_event_handler("TorrentStateChangedEvent", self.on_torrentstatechanged_event) client.register_event_handler("TorrentAddedEvent", self.on_torrentadded_event) client.register_event_handler("TorrentRemovedEvent", self.on_torrentremoved_event) @@ -319,6 +328,8 @@ class TorrentView(listview.ListView, component.Component): # We need to clear the liststore self.liststore.clear() self.prev_status = {} + self.filter = None + self.search_torrents_entry.set_text("") def shutdown(self): """Called when GtkUi is exiting""" @@ -335,7 +346,10 @@ class TorrentView(listview.ListView, component.Component): """Sets filters for the torrentview.. see: core.get_torrents_status """ + search_filter = self.filter and self.filter.get('name', None) or None self.filter = dict(filter_dict) #copied version of filter_dict. + if search_filter and 'name' not in filter_dict: + self.filter['name'] = search_filter self.update() def set_columns_to_update(self, columns=None): @@ -600,3 +614,26 @@ class TorrentView(listview.ListView, component.Component): torrentmenu = component.get("MenuBar").torrentmenu torrentmenu.popup(None, None, None, 3, event.time) return True + + def on_search_torrents_entry_icon_press(self, entry, icon, event): + if icon != gtk.ENTRY_ICON_SECONDARY: + return + + entry.set_text("") + if self.filter and 'name' in self.filter: + self.filter.pop('name', None) + self.update() + + def on_search_torrents_entry_changed(self, widget): + search_string = widget.get_text().lower() + if not search_string: + if self.filter and 'name' in self.filter: + self.filter.pop('name', None) + self.update() + return + + if self.filter is None: + self.filter = {} + + self.filter['name'] = search_string + self.update() From feed806983edbe3799b44f5000235c5140b4856f Mon Sep 17 00:00:00 2001 From: Pedro Algarvio Date: Sun, 29 May 2011 19:02:33 +0100 Subject: [PATCH 2/2] Wait at least 0.7 secs before triggering an update because of the search box, ie, allows typing the full search string before making the request. --- deluge/ui/gtkui/torrentview.py | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/deluge/ui/gtkui/torrentview.py b/deluge/ui/gtkui/torrentview.py index 67fae6adf..9221d3bf7 100644 --- a/deluge/ui/gtkui/torrentview.py +++ b/deluge/ui/gtkui/torrentview.py @@ -46,6 +46,8 @@ import logging import warnings from urlparse import urlparse +from twisted.internet import reactor + import deluge.common import deluge.component as component from deluge.ui.client import client @@ -270,6 +272,7 @@ class TorrentView(listview.ListView, component.Component): # Set filter to None for now self.filter = None + self.search_pending = None ### Connect Signals ### # Connect to the 'button-press-event' to know when to bring up the @@ -393,6 +396,9 @@ class TorrentView(listview.ListView, component.Component): def update(self): if self.got_state: + if self.search_pending is not None and self.search_pending.active(): + # An update request is scheduled, let's wait for that one + return # Send a status request gobject.idle_add(self.send_status_request) @@ -619,21 +625,28 @@ class TorrentView(listview.ListView, component.Component): if icon != gtk.ENTRY_ICON_SECONDARY: return + if self.search_pending and self.search_pending.active(): + self.search_pending.cancel() + entry.set_text("") if self.filter and 'name' in self.filter: self.filter.pop('name', None) - self.update() + self.search_pending = reactor.callLater(0.7, self.update) def on_search_torrents_entry_changed(self, widget): search_string = widget.get_text().lower() + + if self.search_pending and self.search_pending.active(): + self.search_pending.cancel() + if not search_string: if self.filter and 'name' in self.filter: self.filter.pop('name', None) - self.update() + self.search_pending = reactor.callLater(0.7, self.update) return if self.filter is None: self.filter = {} self.filter['name'] = search_string - self.update() + self.search_pending = reactor.callLater(0.7, self.update)