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 @@
-
-
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..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
@@ -287,6 +290,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 +331,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 +349,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):
@@ -379,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)
@@ -600,3 +620,33 @@ 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
+
+ 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.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.search_pending = reactor.callLater(0.7, self.update)
+ return
+
+ if self.filter is None:
+ self.filter = {}
+
+ self.filter['name'] = search_string
+ self.search_pending = reactor.callLater(0.7, self.update)