GTK UI search by torrent name filter as a "toolbar".
Now, instead of permanently having a search box to filter the visible torrents by name, we now, mimic a toolbar just for that, mapped to CTRL-F. There's also a menu item in the "View" menu and a toolbar icon to toggle it. Implemented "Match Case" for the search.
This commit is contained in:
parent
0ba51d0e51
commit
ea438609bf
|
@ -80,8 +80,23 @@ def filter_one_keyword(torrent_ids, keyword):
|
||||||
|
|
||||||
def filter_by_name(torrent_ids, search_string):
|
def filter_by_name(torrent_ids, search_string):
|
||||||
all_torrents = component.get("TorrentManager").torrents
|
all_torrents = component.get("TorrentManager").torrents
|
||||||
|
try:
|
||||||
|
search_string, match_case = search_string[0].split('::match')
|
||||||
|
except ValueError:
|
||||||
|
search_string = search_string[0]
|
||||||
|
match_case = False
|
||||||
|
|
||||||
|
if match_case is False:
|
||||||
|
search_string = search_string.lower()
|
||||||
|
|
||||||
for torrent_id in torrent_ids:
|
for torrent_id in torrent_ids:
|
||||||
if search_string[0].lower() in all_torrents[torrent_id].filename.lower():
|
torrent_name = all_torrents[torrent_id].get_name()
|
||||||
|
if match_case is False:
|
||||||
|
torrent_name = all_torrents[torrent_id].get_name().lower()
|
||||||
|
else:
|
||||||
|
torrent_name = all_torrents[torrent_id].get_name()
|
||||||
|
|
||||||
|
if search_string in torrent_name:
|
||||||
yield torrent_id
|
yield torrent_id
|
||||||
|
|
||||||
def tracker_error_filter(torrent_ids, values):
|
def tracker_error_filter(torrent_ids, values):
|
||||||
|
|
|
@ -225,6 +225,30 @@ class Torrent(object):
|
||||||
def get_options(self):
|
def get_options(self):
|
||||||
return self.options
|
return self.options
|
||||||
|
|
||||||
|
def get_name(self):
|
||||||
|
if self.handle.has_metadata():
|
||||||
|
name = self.torrent_info.file_at(0).path.split("/", 1)[0]
|
||||||
|
if not name:
|
||||||
|
name = self.torrent_info.name()
|
||||||
|
try:
|
||||||
|
return name.decode("utf8", "ignore")
|
||||||
|
except UnicodeDecodeError:
|
||||||
|
return name
|
||||||
|
elif self.magnet:
|
||||||
|
try:
|
||||||
|
keys = dict([k.split('=') for k in self.magnet.split('?')[-1].split('&')])
|
||||||
|
name = keys.get('dn')
|
||||||
|
if not name:
|
||||||
|
return self.torrent_id
|
||||||
|
name = unquote(name).replace('+', ' ')
|
||||||
|
try:
|
||||||
|
return name.decode("utf8", "ignore")
|
||||||
|
except UnicodeDecodeError:
|
||||||
|
return name
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
return self.torrent_id
|
||||||
|
|
||||||
def set_owner(self, account):
|
def set_owner(self, account):
|
||||||
self.owner = account
|
self.owner = account
|
||||||
|
|
||||||
|
@ -685,32 +709,6 @@ class Torrent(object):
|
||||||
return self.torrent_info.comment()
|
return self.torrent_info.comment()
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
def ti_name():
|
|
||||||
if self.handle.has_metadata():
|
|
||||||
name = self.torrent_info.file_at(0).path.split("/", 1)[0]
|
|
||||||
if not name:
|
|
||||||
name = self.torrent_info.name()
|
|
||||||
try:
|
|
||||||
return name.decode("utf8", "ignore")
|
|
||||||
except UnicodeDecodeError:
|
|
||||||
return name
|
|
||||||
|
|
||||||
elif self.magnet:
|
|
||||||
try:
|
|
||||||
keys = dict([k.split('=') for k in self.magnet.split('?')[-1].split('&')])
|
|
||||||
name = keys.get('dn')
|
|
||||||
if not name:
|
|
||||||
return self.torrent_id
|
|
||||||
name = unquote(name).replace('+', ' ')
|
|
||||||
try:
|
|
||||||
return name.decode("utf8", "ignore")
|
|
||||||
except UnicodeDecodeError:
|
|
||||||
return name
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
return self.torrent_id
|
|
||||||
|
|
||||||
def ti_priv():
|
def ti_priv():
|
||||||
if self.handle.has_metadata():
|
if self.handle.has_metadata():
|
||||||
return self.torrent_info.priv()
|
return self.torrent_info.priv()
|
||||||
|
@ -742,7 +740,7 @@ class Torrent(object):
|
||||||
"file_progress": self.get_file_progress,
|
"file_progress": self.get_file_progress,
|
||||||
"files": self.get_files,
|
"files": self.get_files,
|
||||||
"is_seed": self.handle.is_seed,
|
"is_seed": self.handle.is_seed,
|
||||||
"name": ti_name,
|
"name": self.get_name,
|
||||||
"num_files": ti_num_files,
|
"num_files": ti_num_files,
|
||||||
"num_pieces": ti_num_pieces,
|
"num_pieces": ti_num_pieces,
|
||||||
"pieces": ti_pieces_info,
|
"pieces": ti_pieces_info,
|
||||||
|
|
|
@ -38,14 +38,6 @@
|
||||||
<property name="use_stock">False</property>
|
<property name="use_stock">False</property>
|
||||||
<signal name="activate" handler="on_menuitem_addtorrent_activate"/>
|
<signal name="activate" handler="on_menuitem_addtorrent_activate"/>
|
||||||
<accelerator key="O" signal="activate" modifiers="GDK_CONTROL_MASK"/>
|
<accelerator key="O" signal="activate" modifiers="GDK_CONTROL_MASK"/>
|
||||||
<child internal-child="image">
|
|
||||||
<widget class="GtkImage" id="image1">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">False</property>
|
|
||||||
<property name="stock">gtk-add</property>
|
|
||||||
<property name="icon-size">1</property>
|
|
||||||
</widget>
|
|
||||||
</child>
|
|
||||||
</widget>
|
</widget>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
|
@ -58,14 +50,6 @@
|
||||||
<property name="use_stock">False</property>
|
<property name="use_stock">False</property>
|
||||||
<signal name="activate" handler="on_menuitem_createtorrent_activate"/>
|
<signal name="activate" handler="on_menuitem_createtorrent_activate"/>
|
||||||
<accelerator key="N" signal="activate" modifiers="GDK_CONTROL_MASK"/>
|
<accelerator key="N" signal="activate" modifiers="GDK_CONTROL_MASK"/>
|
||||||
<child internal-child="image">
|
|
||||||
<widget class="GtkImage" id="image2">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">False</property>
|
|
||||||
<property name="stock">gtk-new</property>
|
|
||||||
<property name="icon-size">1</property>
|
|
||||||
</widget>
|
|
||||||
</child>
|
|
||||||
</widget>
|
</widget>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
|
@ -83,14 +67,6 @@
|
||||||
<property name="use_stock">False</property>
|
<property name="use_stock">False</property>
|
||||||
<signal name="activate" handler="on_menuitem_quitdaemon_activate"/>
|
<signal name="activate" handler="on_menuitem_quitdaemon_activate"/>
|
||||||
<accelerator key="Q" signal="activate" modifiers="GDK_SHIFT_MASK | GDK_CONTROL_MASK"/>
|
<accelerator key="Q" signal="activate" modifiers="GDK_SHIFT_MASK | GDK_CONTROL_MASK"/>
|
||||||
<child internal-child="image">
|
|
||||||
<widget class="GtkImage" id="image3">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">False</property>
|
|
||||||
<property name="stock">gtk-quit</property>
|
|
||||||
<property name="icon-size">1</property>
|
|
||||||
</widget>
|
|
||||||
</child>
|
|
||||||
</widget>
|
</widget>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
|
@ -148,14 +124,6 @@
|
||||||
<property name="use_stock">False</property>
|
<property name="use_stock">False</property>
|
||||||
<signal name="activate" handler="on_menuitem_connectionmanager_activate"/>
|
<signal name="activate" handler="on_menuitem_connectionmanager_activate"/>
|
||||||
<accelerator key="M" signal="activate" modifiers="GDK_CONTROL_MASK"/>
|
<accelerator key="M" signal="activate" modifiers="GDK_CONTROL_MASK"/>
|
||||||
<child internal-child="image">
|
|
||||||
<widget class="GtkImage" id="image4">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">False</property>
|
|
||||||
<property name="stock">gtk-network</property>
|
|
||||||
<property name="icon-size">1</property>
|
|
||||||
</widget>
|
|
||||||
</child>
|
|
||||||
</widget>
|
</widget>
|
||||||
</child>
|
</child>
|
||||||
</widget>
|
</widget>
|
||||||
|
@ -239,6 +207,18 @@
|
||||||
<property name="use_underline">True</property>
|
<property name="use_underline">True</property>
|
||||||
</widget>
|
</widget>
|
||||||
</child>
|
</child>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkMenuItem" id="find_menuitem">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="sensitive">False</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="use_action_appearance">False</property>
|
||||||
|
<property name="label" translatable="yes">_Find ...</property>
|
||||||
|
<property name="use_underline">True</property>
|
||||||
|
<signal name="activate" handler="on_find_menuitem_activate"/>
|
||||||
|
<accelerator key="f" signal="activate" modifiers="GDK_CONTROL_MASK"/>
|
||||||
|
</widget>
|
||||||
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<widget class="GtkMenuItem" id="menu_Sidebar">
|
<widget class="GtkMenuItem" id="menu_Sidebar">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
|
@ -302,14 +282,6 @@
|
||||||
<property name="use_underline">True</property>
|
<property name="use_underline">True</property>
|
||||||
<property name="use_stock">False</property>
|
<property name="use_stock">False</property>
|
||||||
<signal name="activate" handler="on_menuitem_homepage_activate"/>
|
<signal name="activate" handler="on_menuitem_homepage_activate"/>
|
||||||
<child internal-child="image">
|
|
||||||
<widget class="GtkImage" id="image5">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">False</property>
|
|
||||||
<property name="stock">gtk-home</property>
|
|
||||||
<property name="icon-size">1</property>
|
|
||||||
</widget>
|
|
||||||
</child>
|
|
||||||
</widget>
|
</widget>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
|
@ -324,14 +296,6 @@
|
||||||
<property name="use_stock">False</property>
|
<property name="use_stock">False</property>
|
||||||
<signal name="activate" handler="on_menuitem_faq_activate"/>
|
<signal name="activate" handler="on_menuitem_faq_activate"/>
|
||||||
<accelerator key="F1" signal="activate"/>
|
<accelerator key="F1" signal="activate"/>
|
||||||
<child internal-child="image">
|
|
||||||
<widget class="GtkImage" id="image6">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">False</property>
|
|
||||||
<property name="stock">gtk-dialog-question</property>
|
|
||||||
<property name="icon-size">1</property>
|
|
||||||
</widget>
|
|
||||||
</child>
|
|
||||||
</widget>
|
</widget>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
|
@ -344,15 +308,6 @@
|
||||||
<property name="use_underline">True</property>
|
<property name="use_underline">True</property>
|
||||||
<property name="use_stock">False</property>
|
<property name="use_stock">False</property>
|
||||||
<signal name="activate" handler="on_menuitem_community_activate"/>
|
<signal name="activate" handler="on_menuitem_community_activate"/>
|
||||||
<child internal-child="image">
|
|
||||||
<widget class="GtkImage" id="image7">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">False</property>
|
|
||||||
<property name="xalign">0.4699999988079071</property>
|
|
||||||
<property name="stock">gtk-info</property>
|
|
||||||
<property name="icon-size">1</property>
|
|
||||||
</widget>
|
|
||||||
</child>
|
|
||||||
</widget>
|
</widget>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
|
@ -383,10 +338,6 @@
|
||||||
<property name="position">0</property>
|
<property name="position">0</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
|
||||||
<widget class="GtkHBox" id="hbox1">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">False</property>
|
|
||||||
<child>
|
<child>
|
||||||
<widget class="GtkToolbar" id="toolbar">
|
<widget class="GtkToolbar" id="toolbar">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
|
@ -426,6 +377,25 @@
|
||||||
<property name="homogeneous">True</property>
|
<property name="homogeneous">True</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkToolButton" id="toolbutton_filter">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="sensitive">False</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="tooltip" translatable="yes">Filter torrents by name.
|
||||||
|
This will filter torrents for the current selection on the sidebar.</property>
|
||||||
|
<property name="use_action_appearance">False</property>
|
||||||
|
<property name="label" translatable="yes">_Filter</property>
|
||||||
|
<property name="use_underline">True</property>
|
||||||
|
<property name="stock_id">gtk-find</property>
|
||||||
|
<signal name="clicked" handler="on_toolbutton_filter_clicked"/>
|
||||||
|
<accelerator key="f" signal="clicked" modifiers="GDK_CONTROL_MASK"/>
|
||||||
|
</widget>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="homogeneous">True</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<widget class="GtkSeparatorToolItem" id="separatortoolitem1">
|
<widget class="GtkSeparatorToolItem" id="separatortoolitem1">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
|
@ -562,39 +532,8 @@
|
||||||
</child>
|
</child>
|
||||||
</widget>
|
</widget>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="expand">True</property>
|
<property name="expand">False</property>
|
||||||
<property name="fill">True</property>
|
<property name="fill">True</property>
|
||||||
<property name="position">0</property>
|
|
||||||
</packing>
|
|
||||||
</child>
|
|
||||||
<child>
|
|
||||||
<widget class="GtkEntry" id="search_torrents_entry">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">True</property>
|
|
||||||
<property name="tooltip" translatable="yes">Search torrents by name</property>
|
|
||||||
<property name="invisible_char">•</property>
|
|
||||||
<property name="truncate_multiline">True</property>
|
|
||||||
<property name="caps_lock_warning">False</property>
|
|
||||||
<property name="secondary_icon_stock">gtk-clear</property>
|
|
||||||
<property name="primary_icon_activatable">False</property>
|
|
||||||
<property name="secondary_icon_activatable">True</property>
|
|
||||||
<property name="primary_icon_sensitive">False</property>
|
|
||||||
<property name="secondary_icon_sensitive">True</property>
|
|
||||||
<property name="secondary_icon_tooltip_text" translatable="yes">Clear the search</property>
|
|
||||||
<signal name="changed" handler="on_search_torrents_entry_changed"/>
|
|
||||||
<signal name="icon_press" handler="on_search_torrents_entry_icon_press"/>
|
|
||||||
</widget>
|
|
||||||
<packing>
|
|
||||||
<property name="expand">False</property>
|
|
||||||
<property name="fill">False</property>
|
|
||||||
<property name="padding">5</property>
|
|
||||||
<property name="position">1</property>
|
|
||||||
</packing>
|
|
||||||
</child>
|
|
||||||
</widget>
|
|
||||||
<packing>
|
|
||||||
<property name="expand">False</property>
|
|
||||||
<property name="fill">False</property>
|
|
||||||
<property name="position">1</property>
|
<property name="position">1</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
|
@ -624,9 +563,108 @@
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<widget class="GtkScrolledWindow" id="scrolledwindow1">
|
<widget class="GtkVBox" id="vbox2">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkHBox" id="search_box">
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkButton" id="close_search_button">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="receives_default">True</property>
|
||||||
|
<property name="has_tooltip">True</property>
|
||||||
|
<property name="tooltip" translatable="yes">Close</property>
|
||||||
|
<property name="use_action_appearance">False</property>
|
||||||
|
<property name="relief">none</property>
|
||||||
|
<signal name="clicked" handler="on_close_search_button_clicked"/>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkImage" id="close_search_image">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="stock">gtk-close</property>
|
||||||
|
<property name="icon-size">2</property>
|
||||||
|
</widget>
|
||||||
|
</child>
|
||||||
|
</widget>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">False</property>
|
||||||
|
<property name="position">0</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkLabel" id="label1">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="label" translatable="yes">Filter:</property>
|
||||||
|
</widget>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">False</property>
|
||||||
|
<property name="padding">1</property>
|
||||||
|
<property name="position">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkEntry" id="search_torrents_entry">
|
||||||
|
<property name="width_request">350</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="has_tooltip">True</property>
|
||||||
|
<property name="tooltip" translatable="yes">Filter torrents by name.
|
||||||
|
This will filter torrents for the current selection on the sidebar.</property>
|
||||||
|
<property name="invisible_char">•</property>
|
||||||
|
<property name="truncate_multiline">True</property>
|
||||||
|
<property name="invisible_char_set">True</property>
|
||||||
|
<property name="caps_lock_warning">False</property>
|
||||||
|
<property name="secondary_icon_stock">gtk-clear</property>
|
||||||
|
<property name="primary_icon_activatable">True</property>
|
||||||
|
<property name="secondary_icon_activatable">True</property>
|
||||||
|
<property name="primary_icon_sensitive">False</property>
|
||||||
|
<property name="secondary_icon_sensitive">True</property>
|
||||||
|
<property name="secondary_icon_tooltip_text" translatable="yes">Clear the search</property>
|
||||||
|
<property name="secondary_icon_tooltip_markup" translatable="yes">Clear the search</property>
|
||||||
|
<signal name="changed" handler="on_search_torrents_entry_changed"/>
|
||||||
|
<signal name="icon_press" handler="on_search_torrents_entry_icon_press"/>
|
||||||
|
</widget>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">False</property>
|
||||||
|
<property name="padding">1</property>
|
||||||
|
<property name="position">2</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkCheckButton" id="search_torrents_match">
|
||||||
|
<property name="label" translatable="yes">_Match Case</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="receives_default">False</property>
|
||||||
|
<property name="use_action_appearance">False</property>
|
||||||
|
<property name="use_underline">True</property>
|
||||||
|
<property name="draw_indicator">True</property>
|
||||||
|
<signal name="toggled" handler="on_search_torrents_match_toggled"/>
|
||||||
|
</widget>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">True</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="padding">1</property>
|
||||||
|
<property name="position">3</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</widget>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">0</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkScrolledWindow" id="scrolledwindow1">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
<property name="hscrollbar_policy">automatic</property>
|
<property name="hscrollbar_policy">automatic</property>
|
||||||
<property name="vscrollbar_policy">automatic</property>
|
<property name="vscrollbar_policy">automatic</property>
|
||||||
<property name="shadow_type">out</property>
|
<property name="shadow_type">out</property>
|
||||||
|
@ -639,9 +677,16 @@
|
||||||
</widget>
|
</widget>
|
||||||
</child>
|
</child>
|
||||||
</widget>
|
</widget>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">True</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</widget>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="resize">True</property>
|
<property name="resize">True</property>
|
||||||
<property name="shrink">False</property>
|
<property name="shrink">True</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
</widget>
|
</widget>
|
||||||
|
@ -684,152 +729,6 @@
|
||||||
</widget>
|
</widget>
|
||||||
</child>
|
</child>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="GtkMenu" id="menu_file_tab">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">False</property>
|
|
||||||
<child>
|
|
||||||
<widget class="GtkImageMenuItem" id="menuitem_open_file">
|
|
||||||
<property name="label">gtk-open</property>
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">False</property>
|
|
||||||
<property name="use_action_appearance">False</property>
|
|
||||||
<property name="use_underline">True</property>
|
|
||||||
<property name="use_stock">True</property>
|
|
||||||
<signal name="activate" handler="on_menuitem_open_file_activate"/>
|
|
||||||
</widget>
|
|
||||||
</child>
|
|
||||||
<child>
|
|
||||||
<widget class="GtkSeparatorMenuItem" id="menuitem3">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">False</property>
|
|
||||||
</widget>
|
|
||||||
</child>
|
|
||||||
<child>
|
|
||||||
<widget class="GtkImageMenuItem" id="menuitem_expand_all">
|
|
||||||
<property name="label" translatable="yes">_Expand All</property>
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">False</property>
|
|
||||||
<property name="use_action_appearance">False</property>
|
|
||||||
<property name="use_underline">True</property>
|
|
||||||
<property name="use_stock">False</property>
|
|
||||||
<signal name="activate" handler="on_menuitem_expand_all_activate"/>
|
|
||||||
<child internal-child="image">
|
|
||||||
<widget class="GtkImage" id="image1">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">False</property>
|
|
||||||
<property name="stock">gtk-zoom-fit</property>
|
|
||||||
<property name="icon-size">1</property>
|
|
||||||
</widget>
|
|
||||||
</child>
|
|
||||||
</widget>
|
|
||||||
</child>
|
|
||||||
<child>
|
|
||||||
<widget class="GtkSeparatorMenuItem" id="menuitem_priority_sep">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">False</property>
|
|
||||||
</widget>
|
|
||||||
</child>
|
|
||||||
<child>
|
|
||||||
<widget class="GtkImageMenuItem" id="menuitem_donotdownload">
|
|
||||||
<property name="label" translatable="yes">_Do Not Download</property>
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">False</property>
|
|
||||||
<property name="use_action_appearance">False</property>
|
|
||||||
<property name="use_underline">True</property>
|
|
||||||
<property name="use_stock">False</property>
|
|
||||||
<signal name="activate" handler="on_menuitem_donotdownload_activate"/>
|
|
||||||
<child internal-child="image">
|
|
||||||
<widget class="GtkImage" id="image2">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">False</property>
|
|
||||||
<property name="stock">gtk-no</property>
|
|
||||||
<property name="icon-size">1</property>
|
|
||||||
</widget>
|
|
||||||
</child>
|
|
||||||
</widget>
|
|
||||||
</child>
|
|
||||||
<child>
|
|
||||||
<widget class="GtkImageMenuItem" id="menuitem_normal">
|
|
||||||
<property name="label" translatable="yes">_Normal Priority</property>
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">False</property>
|
|
||||||
<property name="use_action_appearance">False</property>
|
|
||||||
<property name="use_underline">True</property>
|
|
||||||
<property name="use_stock">False</property>
|
|
||||||
<signal name="activate" handler="on_menuitem_normal_activate"/>
|
|
||||||
<child internal-child="image">
|
|
||||||
<widget class="GtkImage" id="image3">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">False</property>
|
|
||||||
<property name="stock">gtk-yes</property>
|
|
||||||
<property name="icon-size">1</property>
|
|
||||||
</widget>
|
|
||||||
</child>
|
|
||||||
</widget>
|
|
||||||
</child>
|
|
||||||
<child>
|
|
||||||
<widget class="GtkImageMenuItem" id="menuitem_high">
|
|
||||||
<property name="label" translatable="yes">_High Priority</property>
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">False</property>
|
|
||||||
<property name="use_action_appearance">False</property>
|
|
||||||
<property name="use_underline">True</property>
|
|
||||||
<property name="use_stock">False</property>
|
|
||||||
<signal name="activate" handler="on_menuitem_high_activate"/>
|
|
||||||
<child internal-child="image">
|
|
||||||
<widget class="GtkImage" id="image4">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">False</property>
|
|
||||||
<property name="stock">gtk-go-up</property>
|
|
||||||
<property name="icon-size">1</property>
|
|
||||||
</widget>
|
|
||||||
</child>
|
|
||||||
</widget>
|
|
||||||
</child>
|
|
||||||
<child>
|
|
||||||
<widget class="GtkImageMenuItem" id="menuitem_highest">
|
|
||||||
<property name="label" translatable="yes">Hi_ghest Priority</property>
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">False</property>
|
|
||||||
<property name="use_action_appearance">False</property>
|
|
||||||
<property name="use_underline">True</property>
|
|
||||||
<property name="use_stock">False</property>
|
|
||||||
<signal name="activate" handler="on_menuitem_highest_activate"/>
|
|
||||||
<child internal-child="image">
|
|
||||||
<widget class="GtkImage" id="image5">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">False</property>
|
|
||||||
<property name="stock">gtk-goto-top</property>
|
|
||||||
<property name="icon-size">1</property>
|
|
||||||
</widget>
|
|
||||||
</child>
|
|
||||||
</widget>
|
|
||||||
</child>
|
|
||||||
</widget>
|
|
||||||
<widget class="GtkMenu" id="menu_peer_tab">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">False</property>
|
|
||||||
<child>
|
|
||||||
<widget class="GtkImageMenuItem" id="menuitem4">
|
|
||||||
<property name="label" translatable="yes">_Add Peer</property>
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">False</property>
|
|
||||||
<property name="tooltip" translatable="yes">Add a peer by its IP</property>
|
|
||||||
<property name="use_action_appearance">False</property>
|
|
||||||
<property name="use_underline">True</property>
|
|
||||||
<property name="use_stock">False</property>
|
|
||||||
<signal name="activate" handler="on_menuitem_add_peer_activate"/>
|
|
||||||
<child internal-child="image">
|
|
||||||
<widget class="GtkImage" id="image1">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">False</property>
|
|
||||||
<property name="stock">gtk-add</property>
|
|
||||||
<property name="icon-size">1</property>
|
|
||||||
</widget>
|
|
||||||
</child>
|
|
||||||
</widget>
|
|
||||||
</child>
|
|
||||||
</widget>
|
|
||||||
<widget class="GtkDialog" id="move_storage_dialog">
|
<widget class="GtkDialog" id="move_storage_dialog">
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||||
|
|
|
@ -74,7 +74,9 @@ class ToolBar(component.Component):
|
||||||
"toolbutton_pause",
|
"toolbutton_pause",
|
||||||
"toolbutton_resume",
|
"toolbutton_resume",
|
||||||
"toolbutton_queue_up",
|
"toolbutton_queue_up",
|
||||||
"toolbutton_queue_down"
|
"toolbutton_queue_down",
|
||||||
|
"toolbutton_filter",
|
||||||
|
"find_menuitem"
|
||||||
]
|
]
|
||||||
|
|
||||||
self.config.register_set_function("classic_mode", self._on_classic_mode, True)
|
self.config.register_set_function("classic_mode", self._on_classic_mode, True)
|
||||||
|
|
|
@ -184,6 +184,86 @@ def seed_peer_column_sort(model, iter1, iter2, data):
|
||||||
return queue_peer_seed_sort_function(v2, v4)
|
return queue_peer_seed_sort_function(v2, v4)
|
||||||
return queue_peer_seed_sort_function(v1, v3)
|
return queue_peer_seed_sort_function(v1, v3)
|
||||||
|
|
||||||
|
class SearchBox(object):
|
||||||
|
def __init__(self, torrentview):
|
||||||
|
self.torrentview = torrentview
|
||||||
|
self.window = torrentview.window
|
||||||
|
|
||||||
|
self.visible = False
|
||||||
|
self.search_pending = None
|
||||||
|
|
||||||
|
self.search_box = self.window.main_glade.get_widget("search_box")
|
||||||
|
self.search_torrents_entry = self.window.main_glade.get_widget("search_torrents_entry")
|
||||||
|
self.close_search_button = self.window.main_glade.get_widget("close_search_button")
|
||||||
|
self.match_search_button = self.window.main_glade.get_widget("search_torrents_match")
|
||||||
|
self.window.main_glade.signal_autoconnect(self)
|
||||||
|
|
||||||
|
def show(self):
|
||||||
|
self.visible = True
|
||||||
|
self.search_box.show_all()
|
||||||
|
|
||||||
|
def hide(self):
|
||||||
|
self.visible = False
|
||||||
|
self.clear_search()
|
||||||
|
self.search_box.hide_all()
|
||||||
|
|
||||||
|
def clear_search(self):
|
||||||
|
if self.search_pending and self.search_pending.active():
|
||||||
|
self.search_pending.cancel()
|
||||||
|
|
||||||
|
self.search_torrents_entry.set_text("")
|
||||||
|
if self.torrentview.filter and 'name' in self.torrentview.filter:
|
||||||
|
self.torrentview.filter.pop('name', None)
|
||||||
|
self.search_pending = reactor.callLater(0.5, self.torrentview.update)
|
||||||
|
|
||||||
|
def set_search_filter(self):
|
||||||
|
if self.search_pending and self.search_pending.active():
|
||||||
|
self.search_pending.cancel()
|
||||||
|
|
||||||
|
if self.torrentview.filter and 'name' in self.torrentview.filter:
|
||||||
|
self.torrentview.filter.pop('name', None)
|
||||||
|
|
||||||
|
elif self.torrentview.filter is None:
|
||||||
|
self.torrentview.filter = {}
|
||||||
|
|
||||||
|
search_string = self.search_torrents_entry.get_text()
|
||||||
|
if not search_string:
|
||||||
|
self.clear_search()
|
||||||
|
else:
|
||||||
|
if self.match_search_button.get_active():
|
||||||
|
search_string += '::match'
|
||||||
|
self.torrentview.filter['name'] = search_string
|
||||||
|
|
||||||
|
def on_close_search_button_clicked(self, widget):
|
||||||
|
self.hide()
|
||||||
|
|
||||||
|
def on_find_menuitem_activate(self, widget):
|
||||||
|
if self.visible:
|
||||||
|
self.hide()
|
||||||
|
else:
|
||||||
|
self.show()
|
||||||
|
|
||||||
|
def on_toolbutton_filter_clicked(self, widget):
|
||||||
|
if self.visible:
|
||||||
|
self.hide()
|
||||||
|
else:
|
||||||
|
self.show()
|
||||||
|
|
||||||
|
def on_search_torrents_match_toggled(self, widget):
|
||||||
|
if self.search_torrents_entry.get_text():
|
||||||
|
self.set_search_filter()
|
||||||
|
self.search_pending = reactor.callLater(0.5, self.torrentview.update)
|
||||||
|
|
||||||
|
def on_search_torrents_entry_icon_press(self, entry, icon, event):
|
||||||
|
if icon != gtk.ENTRY_ICON_SECONDARY:
|
||||||
|
return
|
||||||
|
self.clear_search()
|
||||||
|
|
||||||
|
def on_search_torrents_entry_changed(self, widget):
|
||||||
|
self.set_search_filter()
|
||||||
|
self.search_pending = reactor.callLater(0.7, self.torrentview.update)
|
||||||
|
|
||||||
|
|
||||||
class TorrentView(listview.ListView, component.Component):
|
class TorrentView(listview.ListView, component.Component):
|
||||||
"""TorrentView handles the listing of torrents."""
|
"""TorrentView handles the listing of torrents."""
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
@ -272,7 +352,6 @@ class TorrentView(listview.ListView, component.Component):
|
||||||
|
|
||||||
# Set filter to None for now
|
# Set filter to None for now
|
||||||
self.filter = None
|
self.filter = None
|
||||||
self.search_pending = None
|
|
||||||
|
|
||||||
### Connect Signals ###
|
### Connect Signals ###
|
||||||
# Connect to the 'button-press-event' to know when to bring up the
|
# Connect to the 'button-press-event' to know when to bring up the
|
||||||
|
@ -290,15 +369,6 @@ class TorrentView(listview.ListView, component.Component):
|
||||||
self.treeview.connect("key-press-event", self.on_key_press_event)
|
self.treeview.connect("key-press-event", self.on_key_press_event)
|
||||||
self.treeview.connect("columns-changed", self.on_columns_changed_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("TorrentStateChangedEvent", self.on_torrentstatechanged_event)
|
||||||
client.register_event_handler("TorrentAddedEvent", self.on_torrentadded_event)
|
client.register_event_handler("TorrentAddedEvent", self.on_torrentadded_event)
|
||||||
client.register_event_handler("TorrentRemovedEvent", self.on_torrentremoved_event)
|
client.register_event_handler("TorrentRemovedEvent", self.on_torrentremoved_event)
|
||||||
|
@ -306,6 +376,8 @@ class TorrentView(listview.ListView, component.Component):
|
||||||
client.register_event_handler("SessionResumedEvent", self.on_sessionresumed_event)
|
client.register_event_handler("SessionResumedEvent", self.on_sessionresumed_event)
|
||||||
client.register_event_handler("TorrentQueueChangedEvent", self.on_torrentqueuechanged_event)
|
client.register_event_handler("TorrentQueueChangedEvent", self.on_torrentqueuechanged_event)
|
||||||
|
|
||||||
|
self.search_box = SearchBox(self)
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
"""Start the torrentview"""
|
"""Start the torrentview"""
|
||||||
# We need to get the core session state to know which torrents are in
|
# We need to get the core session state to know which torrents are in
|
||||||
|
@ -332,7 +404,7 @@ class TorrentView(listview.ListView, component.Component):
|
||||||
self.liststore.clear()
|
self.liststore.clear()
|
||||||
self.prev_status = {}
|
self.prev_status = {}
|
||||||
self.filter = None
|
self.filter = None
|
||||||
self.search_torrents_entry.set_text("")
|
self.search_box.hide()
|
||||||
|
|
||||||
def shutdown(self):
|
def shutdown(self):
|
||||||
"""Called when GtkUi is exiting"""
|
"""Called when GtkUi is exiting"""
|
||||||
|
@ -396,7 +468,7 @@ class TorrentView(listview.ListView, component.Component):
|
||||||
|
|
||||||
def update(self):
|
def update(self):
|
||||||
if self.got_state:
|
if self.got_state:
|
||||||
if self.search_pending is not None and self.search_pending.active():
|
if self.search_box.search_pending is not None and self.search_box.search_pending.active():
|
||||||
# An update request is scheduled, let's wait for that one
|
# An update request is scheduled, let's wait for that one
|
||||||
return
|
return
|
||||||
# Send a status request
|
# Send a status request
|
||||||
|
@ -620,33 +692,3 @@ class TorrentView(listview.ListView, component.Component):
|
||||||
torrentmenu = component.get("MenuBar").torrentmenu
|
torrentmenu = component.get("MenuBar").torrentmenu
|
||||||
torrentmenu.popup(None, None, None, 3, event.time)
|
torrentmenu.popup(None, None, None, 3, event.time)
|
||||||
return True
|
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)
|
|
||||||
|
|
Loading…
Reference in New Issue