diff --git a/deluge/ui/gtkui/filtertreeview.py b/deluge/ui/gtkui/filtertreeview.py index d011609ff..359f1a6ba 100644 --- a/deluge/ui/gtkui/filtertreeview.py +++ b/deluge/ui/gtkui/filtertreeview.py @@ -1,41 +1,17 @@ -# -# filtertreeview.py +# -*- coding: utf-8 -*- # # Copyright (C) 2008 Martijn Voncken -# Copyright (C) 2008 Andrew Resch -# -# Deluge is free software. -# -# You may redistribute it and/or modify it under the terms of the -# GNU General Public License, as published by the Free Software -# Foundation; either version 3 of the License, or (at your option) -# any later version. -# -# deluge is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -# See the GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with deluge. If not, write to: -# The Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor -# Boston, MA 02110-1301, USA. -# -# In addition, as a special exception, the copyright holders give -# permission to link the code of portions of this program with the OpenSSL -# library. -# You must obey the GNU General Public License in all respects for all of -# the code used other than OpenSSL. If you modify file(s) with this -# exception, you may extend this exception to your version of the file(s), -# but you are not obligated to do so. If you do not wish to do so, delete -# this exception statement from your version. If you delete this exception -# statement from all source files in the program, then also delete it here. +# 2008 Andrew Resch +# 2014 Calum Lind # +# This file is part of Deluge and is licensed under GNU General Public License 3.0, or later, with +# the additional special exception to link portions of this program with the OpenSSL library. +# See LICENSE for more details. # import os import gtk +import pango import logging import warnings from gobject import GError @@ -67,25 +43,65 @@ TRACKER_PIX = { FILTER_COLUMN = 5 -#sidebar-treeview + class FilterTreeView(component.Component): def __init__(self): component.Component.__init__(self, "FilterTreeView", interval=2) self.window = component.get("MainWindow") - main_builder = self.window.get_builder() - self.hpaned = main_builder.get_object("main_window_hpaned") - self.scrolled = main_builder.get_object("scrolledwindow_sidebar") - self.sidebar = component.get("SideBar") self.config = ConfigManager("gtkui.conf") + self.tracker_icons = component.get("TrackerIcons") - self.label_view = gtk.TreeView() - self.sidebar.add_tab(self.label_view, "filters", "Filters") + self.sidebar = component.get("SideBar") + self.treeview = gtk.TreeView() + self.sidebar.add_tab(self.treeview, "filters", "Filters") #set filter to all when hidden: self.sidebar.notebook.connect("hide", self._on_hide) - #menu + # Create the treestore + #cat, value, label, count, pixmap, visible + self.treestore = gtk.TreeStore(str, str, str, int, gtk.gdk.Pixbuf, bool) + + # Create the column and cells + column = gtk.TreeViewColumn("Filters") + column.set_sizing(gtk.TREE_VIEW_COLUMN_AUTOSIZE) + # icon cell + self.cell_pix = gtk.CellRendererPixbuf() + column.pack_start(self.cell_pix, expand=False) + column.add_attribute(self.cell_pix, 'pixbuf', 4) + # label cell + cell_label = gtk.CellRendererText() + cell_label.set_property('ellipsize', pango.ELLIPSIZE_END) + column.pack_start(cell_label, expand=True) + column.set_cell_data_func(cell_label, self.render_cell_data, None) + # count cell + self.cell_count = gtk.CellRendererText() + self.cell_count.set_property('xalign', 1.0) + column.pack_start(self.cell_count, expand=False) + + self.treeview.append_column(column) + + # Style + self.treeview.set_show_expanders(True) + self.treeview.set_headers_visible(False) + self.treeview.set_level_indentation(-21) + # Force theme to use expander-size so we don't cut out entries due to indentation hack. + gtk.rc_parse_string("""style "treeview-style" {GtkTreeView::expander-size = 7} + class "GtkTreeView" style "treeview-style" """) + + self.treeview.set_model(self.treestore) + self.treeview.get_selection().connect("changed", self.on_selection_changed) + self.create_model_filter() + + self.treeview.connect("button-press-event", self.on_button_press_event) + + #colors using current theme. + style = self.window.window.get_style() + self.colour_background = style.bg[gtk.STATE_NORMAL] + self.colour_foreground = style.fg[gtk.STATE_NORMAL] + + # filtertree menu builder = gtk.Builder() builder.add_from_file(resource_filename("deluge.ui.gtkui", os.path.join("glade", "filtertree_menu.ui"))) self.menu = builder.get_object("filtertree_menu") @@ -97,43 +113,6 @@ class FilterTreeView(component.Component): self.default_menu_items = self.menu.get_children() - # Create the liststore - #cat, value, label, count, pixmap, visible - self.treestore = gtk.TreeStore(str, str, str, int, gtk.gdk.Pixbuf, bool) - - # Create the column - column = gtk.TreeViewColumn("Filters") - column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED) - render = gtk.CellRendererPixbuf() - self.renderpix = render - column.pack_start(render, expand=False) - column.add_attribute(render, 'pixbuf', 4) - render = gtk.CellRendererText() - column.pack_start(render, expand=False) - column.set_cell_data_func(render, self.render_cell_data,None) - - self.label_view.append_column(column) - - #style: - self.label_view.set_show_expanders(True) - self.label_view.set_headers_visible(False) - self.label_view.set_level_indentation(-35) - # Force the theme to use an expander-size of 15 so that we don't cut out - # entries due to our indentation hack. - gtk.rc_parse_string('style "treeview-style" { GtkTreeView::expander-size = 15 } class "GtkTreeView" style "treeview-style"') - - self.label_view.set_model(self.treestore) - self.label_view.get_selection().connect("changed", self.on_selection_changed) - self.create_model_filter() - - #init..... - self.label_view.connect("button-press-event", self.on_button_press_event) - - #colors using current theme. - style = self.window.window.get_style() - self.colour_background = style.bg[gtk.STATE_NORMAL] - self.colour_foreground = style.fg[gtk.STATE_NORMAL] - def start(self): #add Cat nodes: self.cat_nodes = {} @@ -144,14 +123,15 @@ class FilterTreeView(component.Component): for state in ["All", "Active"] + TORRENT_STATE: self.update_row("state", state, 0, _(state)) - self.cat_nodes["tracker_host"] = self.treestore.append(None, ["cat", "tracker_host", _("Trackers"), 0, None, False]) - self.update_row("tracker_host", "All" , 0, _("All")) - self.update_row("tracker_host", "Error" , 0, _("Error")) - self.update_row("tracker_host", "" , 0, _("None")) + self.cat_nodes["tracker_host"] = self.treestore.append(None, ["cat", "tracker_host", + _("Trackers"), 0, None, False]) + self.update_row("tracker_host", "All", 0, _("All")) + self.update_row("tracker_host", "Error", 0, _("Error")) + self.update_row("tracker_host", "", 0, _("None")) self.cat_nodes["owner"] = self.treestore.append(None, ["cat", "owner", _("Owner"), 0, None, False]) - self.update_row("owner", "localclient" , 0, _("Admin")) - self.update_row("owner", "" , 0, _("None")) + self.update_row("owner", "localclient", 0, _("Admin")) + self.update_row("owner", "", 0, _("None")) # We set to this expand the rows on start-up self.expand_rows = True @@ -164,7 +144,7 @@ class FilterTreeView(component.Component): def create_model_filter(self): self.model_filter = self.treestore.filter_new() self.model_filter.set_visible_column(FILTER_COLUMN) - self.label_view.set_model(self.model_filter) + self.treeview.set_model(self.model_filter) def cb_update_filter_tree(self, filter_items): #create missing cat_nodes @@ -177,17 +157,14 @@ class FilterTreeView(component.Component): #update rows visible_filters = [] - for cat,filters in filter_items.iteritems(): + for cat, filters in filter_items.iteritems(): for value, count in filters: self.update_row(cat, value, count) visible_filters.append((cat, value)) # hide root-categories not returned by core-part of the plugin. for cat in self.cat_nodes: - if cat in filter_items: - self.treestore.set_value(self.cat_nodes[cat], FILTER_COLUMN, True) - else: - self.treestore.set_value(self.cat_nodes[cat], FILTER_COLUMN, False) + self.treestore.set_value(self.cat_nodes[cat], FILTER_COLUMN, True if cat in filter_items else False) # hide items not returned by core-plugin. for f in self.filters: @@ -195,13 +172,13 @@ class FilterTreeView(component.Component): self.treestore.set_value(self.filters[f], FILTER_COLUMN, False) if self.expand_rows: - self.label_view.expand_all() + self.treeview.expand_all() self.expand_rows = False if not self.selected_path: self.select_default_filter() - def update_row(self, cat, value , count, label=None): + def update_row(self, cat, value, count, label=None): def on_get_icon(icon): if icon: self.set_row_image(cat, value, icon.get_filename()) @@ -220,7 +197,7 @@ class FilterTreeView(component.Component): elif not label and value: label = _(value) - row = self.treestore.append(self.cat_nodes[cat],[cat, value, label, count , pix, True]) + row = self.treestore.append(self.cat_nodes[cat], [cat, value, label, count, pix, True]) self.filters[(cat, value)] = row if cat == "tracker_host" and value not in ("All", "Error") and value: @@ -231,9 +208,7 @@ class FilterTreeView(component.Component): return row def render_cell_data(self, column, cell, model, row, data): - "cell renderer" cat = model.get_value(row, 0) - value = model.get_value(row, 1) label = model.get_value(row, 2) count = model.get_value(row, 3) @@ -245,21 +220,18 @@ class FilterTreeView(component.Component): finally: warnings.filters = original_filters - if pix: - self.renderpix.set_property("visible", True) - else: - self.renderpix.set_property("visible", False) + self.cell_pix.set_property("visible", True if pix else False) if cat == "cat": - txt = label - cell.set_property("cell-background-gdk", self.colour_background) - cell.set_property("foreground-gdk", self.colour_foreground) + self.cell_count.set_property("visible", False) + cell.set_padding(10, 2) + label = "%s" % label else: - txt = "%s (%s)" % (label, count) - cell.set_property("cell-background", None) - cell.set_property("foreground", None) - - cell.set_property('text', txt) + count_txt = "%s" % count + self.cell_count.set_property('markup', count_txt) + self.cell_count.set_property("visible", True) + cell.set_padding(2, 1) + cell.set_property('markup', label) def get_pixmap(self, cat, value): pix = None @@ -282,7 +254,7 @@ class FilterTreeView(component.Component): def set_row_image(self, cat, value, filename): pix = None - try: #assume we could get trashed images here.. + try: # assume we could get trashed images here.. pix = gtk.gdk.pixbuf_new_from_file_at_size(filename, 16, 16) except Exception, e: log.debug(e) @@ -293,10 +265,9 @@ class FilterTreeView(component.Component): self.treestore.set_value(row, 4, pix) return False - def on_selection_changed(self, selection): try: - (model, row) = self.label_view.get_selection().get_selected() + (model, row) = self.treeview.get_selection().get_selected() if not row: log.debug("nothing selected") return @@ -322,18 +293,16 @@ class FilterTreeView(component.Component): hide_cat = [] if not self.config["sidebar_show_trackers"]: hide_cat = ["tracker_host"] - client.core.get_filter_tree(self.config["sidebar_show_zero"], hide_cat).addCallback(self.cb_update_filter_tree) + client.core.get_filter_tree(self.config["sidebar_show_zero"], + hide_cat).addCallback(self.cb_update_filter_tree) except Exception, e: log.debug(e) - ### Callbacks ### def on_button_press_event(self, widget, event): - """This is a callback for showing the right-click context menu. - NOT YET! - """ + """This is a callback for showing the right-click context menu.""" x, y = event.get_coords() - path = self.label_view.get_path_at_pos(int(x), int(y)) + path = self.treeview.get_path_at_pos(int(x), int(y)) if not path: return path = path[0] @@ -342,20 +311,20 @@ class FilterTreeView(component.Component): if event.button == 1: # Prevent selecting a category label if cat == "cat": - if self.label_view.row_expanded(path): - self.label_view.collapse_row(path) + if self.treeview.row_expanded(path): + self.treeview.collapse_row(path) else: - self.label_view.expand_row(path, False) + self.treeview.expand_row(path, False) if not self.selected_path: self.select_default_filter() else: - self.label_view.get_selection().select_path(self.selected_path) + self.treeview.get_selection().select_path(self.selected_path) return True elif event.button == 3: #assign current cat, value to self: x, y = event.get_coords() - path = self.label_view.get_path_at_pos(int(x), int(y)) + path = self.treeview.get_path_at_pos(int(x), int(y)) if not path: return row = self.model_filter.get_iter(path[0]) @@ -375,7 +344,7 @@ class FilterTreeView(component.Component): def set_menu_sensitivity(self): #select-all/pause/resume - sensitive = (self.cat != "cat" and self.count <> 0) + sensitive = (self.cat != "cat" and self.count != 0) for item in self.default_menu_items: item.set_sensitive(sensitive) @@ -402,4 +371,4 @@ class FilterTreeView(component.Component): def select_default_filter(self): row = self.filters[("state", "All")] path = self.treestore.get_path(row) - self.label_view.get_selection().select_path(path) + self.treeview.get_selection().select_path(path)