diff options
Diffstat (limited to 'deluge/plugins/Stats/deluge/plugins/stats/gtkui.py')
-rw-r--r-- | deluge/plugins/Stats/deluge/plugins/stats/gtkui.py | 234 |
1 files changed, 181 insertions, 53 deletions
diff --git a/deluge/plugins/Stats/deluge/plugins/stats/gtkui.py b/deluge/plugins/Stats/deluge/plugins/stats/gtkui.py index d3bec7353..607fc406f 100644 --- a/deluge/plugins/Stats/deluge/plugins/stats/gtkui.py +++ b/deluge/plugins/Stats/deluge/plugins/stats/gtkui.py @@ -1,6 +1,7 @@ # # gtkui.py # +# Copyright (C) 2009 Ian Martin <ianmartin@cantab.net> # Copyright (C) 2008 Martijn Voncken <mvoncken@gmail.com> # # Basic plugin template created by: @@ -23,18 +24,7 @@ # 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. -# +# 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 @@ -45,89 +35,211 @@ # 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 -import os import gtk -import logging +import gobject from gtk.glade import XML -from twisted.internet import defer - -# Relative imports -from . import common -from . import graph - +import graph +import deluge from deluge import component +from deluge.log import LOG as log from deluge.common import fspeed from deluge.ui.client import client from deluge.ui.gtkui.torrentdetails import Tab from deluge.plugins.pluginbase import GtkPluginBase -log = logging.getLogger(__name__) +import common + +DEFAULT_CONF = { 'version': 1, + 'colors' :{ + 'bandwidth_graph': {'upload_rate': str(gtk.gdk.Color("blue")), + 'download_rate': str(gtk.gdk.Color("green")), + }, + 'connections_graph': { 'dht_nodes': str(gtk.gdk.Color("orange")), + 'dht_cache_nodes': str(gtk.gdk.Color("blue")), + 'dht_torrents': str(gtk.gdk.Color("green")), + 'num_connections': str(gtk.gdk.Color("darkred")), + }, + 'seeds_graph': { 'num_peers': str(gtk.gdk.Color("blue")), + }, + } + } + +def neat_time(column, cell, model, iter): + """Render seconds as seconds or minutes with label""" + seconds = model.get_value(iter, 0) + if seconds >60: + text = "%d %s" % (seconds / 60, _("minutes")) + elif seconds == 60: + text = _("1 minute") + elif seconds == 1: + text = _("1 second") + else: + text = "%d %s" % (seconds, _("seconds")) + cell.set_property('text', text) + return + +def int_str(number): + return (str(int(number))) + +def gtk_to_graph_color(color): + """Turns a gtk.gdk.Color into a tuple with range 0-1 as used by the graph""" + MAX = float(65535) + gtk_color = gtk.gdk.Color(color) + red = gtk_color.red / MAX + green = gtk_color.green / MAX + blue = gtk_color.blue / MAX + return (red, green, blue) + class GraphsTab(Tab): - def __init__(self, glade): + def __init__(self, glade, colors): Tab.__init__(self) - self._name = 'Graphs' self.glade = glade self.window = self.glade.get_widget('graph_tab') - self._child_widget = self.window self.notebook = self.glade.get_widget('graph_notebook') self.label = self.glade.get_widget('graph_label') + + self._name = 'Graphs' + self._child_widget = self.window self._tab_label = self.label + + self.colors = colors + self.bandwidth_graph = self.glade.get_widget('bandwidth_graph') - self.bandwidth_graph.connect('expose_event', self.expose) + self.bandwidth_graph.connect('expose_event', self.graph_expose) + + self.connections_graph = self.glade.get_widget('connections_graph') + self.connections_graph.connect('expose_event', self.graph_expose) + + self.seeds_graph = self.glade.get_widget('seeds_graph') + self.seeds_graph.connect('expose_event', self.graph_expose) + + self.notebook.connect('switch-page', self._on_notebook_switch_page) + + self.selected_interval = 1 #should come from config or similar + self.select_bandwidth_graph() + self.window.unparent() self.label.unparent() - self.graph_widget = self.bandwidth_graph - self.graph = graph.Graph() - self.graph.add_stat('payload_download_rate', label='Download Rate', color=graph.green) - self.graph.add_stat('payload_upload_rate', label='Upload Rate', color=graph.blue) - self.graph.set_left_axis(formatter=fspeed, min=10240) + self.intervals = None + self.intervals_combo = self.glade.get_widget('combo_intervals') + cell = gtk.CellRendererText() + self.intervals_combo.pack_start(cell, True) + self.intervals_combo.set_cell_data_func(cell, neat_time) + self.intervals_combo.connect("changed", self._on_selected_interval_changed) + self.update_intervals() + - def expose(self, widget, event): - """Redraw""" + def graph_expose(self, widget, event): context = self.graph_widget.window.cairo_create() # set a clip region context.rectangle(event.area.x, event.area.y, event.area.width, event.area.height) context.clip() - - width, height = self.graph_widget.allocation.width, self.graph_widget.allocation.height - self.graph.draw_to_context(context, width, height) + self.graph.draw_to_context(context, + self.graph_widget.allocation.width, + self.graph_widget.allocation.height) #Do not propagate the event return False def update(self): - log.debug("getstat keys: %s", self.graph.stat_info.keys()) - d1 = client.stats.get_stats(self.graph.stat_info.keys()) + d1 = client.stats.get_stats(self.graph.stat_info.keys(), self.selected_interval) d1.addCallback(self.graph.set_stats) - d2 = client.stats.get_config() - d2.addCallback(self.graph.set_config) - dl = defer.DeferredList([d1, d2]) - - def _on_update(result): - width, height = self.graph_widget.allocation.width, self.graph_widget.allocation.height - rect = gtk.gdk.Rectangle(0, 0, width, height) - self.graph_widget.window.invalidate_rect(rect, True) - - dl.addCallback(_on_update) + def _update_complete(result): + self.graph_widget.queue_draw() + d1.addCallback(_update_complete) + return True def clear(self): pass + def update_intervals(self): + client.stats.get_intervals().addCallback(self._on_intervals_changed) + def select_bandwidth_graph(self): + log.debug("Selecting bandwidth graph") + self.graph_widget = self.bandwidth_graph + self.graph = graph.Graph() + colors = self.colors['bandwidth_graph'] + self.graph.add_stat('download_rate', label='Download Rate', + color=gtk_to_graph_color(colors['download_rate'])) + self.graph.add_stat('upload_rate', label='Upload Rate', + color=gtk_to_graph_color(colors['upload_rate'])) + self.graph.set_left_axis(formatter=fspeed, min=10240, + formatter_scale=graph.size_formatter_scale) + + def select_connections_graph(self): + log.debug("Selecting connections graph") + self.graph_widget = self.connections_graph + g = graph.Graph() + self.graph = g + colors = self.colors['connections_graph'] + g.add_stat('dht_nodes', color=gtk_to_graph_color(colors['dht_nodes'])) + g.add_stat('dht_cache_nodes', color=gtk_to_graph_color(colors['dht_cache_nodes'])) + g.add_stat('dht_torrents', color=gtk_to_graph_color(colors['dht_torrents'])) + g.add_stat('num_connections', color=gtk_to_graph_color(colors['num_connections'])) + g.set_left_axis(formatter=int_str, min=10) + + def select_seeds_graph(self): + log.debug("Selecting connections graph") + self.graph_widget = self.seeds_graph + self.graph = graph.Graph() + colors = self.colors['seeds_graph'] + self.graph.add_stat('num_peers', color=gtk_to_graph_color(colors['num_peers'])) + self.graph.set_left_axis(formatter=int_str, min=10) + + def set_colors(self, colors): + self.colors = colors + # Fake switch page to update the graph colors (HACKY) + self._on_notebook_switch_page(self.notebook, + None, #This is unused + self.notebook.get_current_page()) + + def _on_intervals_changed(self, intervals): + liststore = gtk.ListStore(int) + for inter in intervals: + liststore.append([inter]) + self.intervals_combo.set_model(liststore) + try: + current = intervals.index(self.selected_interval) + except: + current = 0 + #should select the value saved in config + self.intervals_combo.set_active(current) + + def _on_selected_interval_changed(self, combobox): + model = combobox.get_model() + iter = combobox.get_active_iter() + self.selected_interval = model.get_value(iter, 0) + self.update() + return True + + def _on_notebook_switch_page(self, notebook, page, page_num): + p = notebook.get_nth_page(page_num) + if p is self.bandwidth_graph: + self.select_bandwidth_graph() + self.update() + elif p is self.connections_graph: + self.select_connections_graph() + self.update() + elif p is self.seeds_graph: + self.select_seeds_graph() + self.update() + return True class GtkUI(GtkPluginBase): def enable(self): log.debug("Stats plugin enable called") + self.config = deluge.configmanager.ConfigManager("stats.gtkui.conf", DEFAULT_CONF) self.glade = XML(common.get_resource("config.glade")) component.get("Preferences").add_page("Stats", self.glade.get_widget("prefs_box")) component.get("PluginManager").register_hook("on_apply_prefs", self.on_apply_prefs) component.get("PluginManager").register_hook("on_show_prefs", self.on_show_prefs) self.on_show_prefs() - self.graphs_tab = GraphsTab(XML(common.get_resource("tabs.glade"))) + self.graphs_tab = GraphsTab(XML(common.get_resource("tabs.glade")), self.config['colors']) self.torrent_details = component.get('TorrentDetails') self.torrent_details.add_tab(self.graphs_tab) @@ -139,15 +251,31 @@ class GtkUI(GtkPluginBase): def on_apply_prefs(self): log.debug("applying prefs for Stats") - config = { - "test":self.glade.get_widget("txt_test").get_text() - } + gtkconf = {} + for graph, colors in self.config['colors'].items(): + gtkconf[graph] = {} + for value, color in colors.items(): + try: + color_btn = self.glade.get_widget("%s_%s_color" % (graph, value)) + gtkconf[graph][value] = str(color_btn.get_color()) + except: + gtkconf[graph][value] = DEFAULT_CONF['colors'][graph][value] + self.config['colors'] = gtkconf + self.graphs_tab.set_colors(self.config['colors']) + + config = { } client.stats.set_config(config) def on_show_prefs(self): + for graph, colors in self.config['colors'].items(): + for value, color in colors.items(): + try: + color_btn = self.glade.get_widget("%s_%s_color" % (graph, value)) + color_btn.set_color(gtk.gdk.Color(color)) + except: + log.debug("Unable to set %s %s %s" % (graph, value, color)) client.stats.get_config().addCallback(self.cb_get_config) def cb_get_config(self, config): "callback for on show_prefs" - self.glade.get_widget("txt_test").set_text(config["test"]) - + pass |