From 28def22625d7969f1ec4ca95b6526192c5556404 Mon Sep 17 00:00:00 2001 From: Pedro Algarvio Date: Thu, 5 May 2011 18:27:20 +0100 Subject: [PATCH] PiecesBar enhancement. The pieces bar will now draw status text, like a regular progress bar does, and for the overall progress, a semi-transparent overlay is also drawn. --- deluge/ui/gtkui/gtkui.py | 6 -- deluge/ui/gtkui/piecesbar.py | 136 +++++++++++++++++++++++----------- deluge/ui/gtkui/status_tab.py | 4 +- 3 files changed, 94 insertions(+), 52 deletions(-) diff --git a/deluge/ui/gtkui/gtkui.py b/deluge/ui/gtkui/gtkui.py index 92da7715e..234148d6d 100644 --- a/deluge/ui/gtkui/gtkui.py +++ b/deluge/ui/gtkui/gtkui.py @@ -159,12 +159,6 @@ DEFAULT_PREFS = { "show_rate_in_title": False, "createtorrent.trackers": [], "show_piecesbar": False, -# "pieces_colors": [ -# [65535, 0, 0], -# [4874, 56494, 0], -# [65535, 55255, 0], -# [4883, 26985, 56540] -# ], "pieces_color_missing": [65535, 0, 0], "pieces_color_waiting": [4874, 56494, 0], "pieces_color_downloading": [65535, 55255, 0], diff --git a/deluge/ui/gtkui/piecesbar.py b/deluge/ui/gtkui/piecesbar.py index 9f358e5ef..71709d03c 100644 --- a/deluge/ui/gtkui/piecesbar.py +++ b/deluge/ui/gtkui/piecesbar.py @@ -34,11 +34,9 @@ # # -import pygtk -pygtk.require('2.0') import gtk -import gtk.gdk -import cairo +import pango +import pangocairo import logging from deluge.configmanager import ConfigManager @@ -58,12 +56,23 @@ class PiecesBar(gtk.DrawingArea): def __init__(self): gtk.DrawingArea.__init__(self) + # Get progress bar styles, in order to keep font consistency + pb = gtk.ProgressBar() + pb_style = pb.get_style() + self.text_font = pb_style.font_desc + self.text_font.set_weight(pango.WEIGHT_BOLD) + # Done with the ProgressBar styles, don't keep refs of it + del pb, pb_style + self.set_size_request(-1, 25) self.gtkui_config = ConfigManager("gtkui.conf") self.width = 0 self.height = 0 self.pieces = () self.num_pieces = None + self.text = "" + self.fraction = 0.0 + self.torrent_state = None self.connect('size-allocate', self.do_size_allocate_event) self.set_colormap(self.get_screen().get_rgba_colormap()) self.show() @@ -82,30 +91,10 @@ class PiecesBar(gtk.DrawingArea): event.area.width, event.area.height) cr.clip() -# # Sets the operator to clear which deletes everything below where -# # an object is drawn -# cr.set_operator(cairo.OPERATOR_CLEAR) -# # Makes the mask fill the entire area -# cr.rectangle(0.0, 0.0, event.area.width, event.area.height) -# # Deletes everything in the window (since the compositing operator -# # is clear and mask fills the entire window -# cr.fill() -# # Set the compositing operator back to the default -# cr.set_operator(cairo.OPERATOR_OVER) - - cr.set_line_width(max(cr.device_to_user_distance(0.5, 0.5))) -# bgColor = self.window.get_style().copy().bg[gtk.STATE_NORMAL] -# cr.set_source_rgba(0.53, 0.53, 0.53, 1.0) # Transparent -# cr.set_source_rgba(0.8, 0.8, 0.8, 1.0) # Transparent -# cr.set_source_rgb(0.3, 0.3, 0.3) # Transparent - cr.set_source_rgb(0.1, 0.1, 0.1) # Transparent -# cr.set_source_rgb(bgColor.red/65535.0, bgColor.green/65535.0, bgColor.blue/65535.0) -# cr.set_operator(cairo.OPERATOR_SOURCE) + cr.set_source_rgb(0.1, 0.1, 0.1) cr.rectangle(0.0, 0.0, event.area.width, event.area.height) cr.stroke() -# # Set the compositing operator back to the default -# cr.set_operator(cairo.OPERATOR_OVER) if not self.pieces and self.num_pieces is not None: @@ -121,13 +110,14 @@ class PiecesBar(gtk.DrawingArea): color[1]/65535.0, color[2]/65535.0, ) -# cr.set_source_rgba(*list(self.colors[3])+[0.5]) cr.rectangle(start, 1, piece_width, piece_height) cr.fill() start += piece_width + self.__write_text(cr, event) return if not self.pieces: + self.__write_text(cr, event) return # Create the cairo context @@ -137,48 +127,106 @@ class PiecesBar(gtk.DrawingArea): piece_height = self.height - 2 for state in self.pieces: -# cr.set_source_rgb(*self.colors[state]) -# cr.set_source_rgb(*self.colors[state]) - color = self.gtkui_config["pieces_color_%s" % COLOR_STATES[state]] cr.set_source_rgb( color[0]/65535.0, color[1]/65535.0, color[2]/65535.0, ) -# cr.set_source_rgba(*list(self.colors[state])+[0.5]) cr.rectangle(start_pos, 1, piece_width, piece_height) cr.fill() start_pos += piece_width + self.__write_text(cr, event) + + def __draw_progress_overlay(self, cr): + cr.set_source_rgba(0.1, 0.1, 0.1, 0.2) # Transparent + cr.rectangle(0.0, 0.0, self.width*self.fraction, self.height) + cr.fill() + + def __write_text(self, cr, event): + if not self.torrent_state: + # Nothing useful to draw, return now! + return + self.__draw_progress_overlay(cr) + + pg = pangocairo.CairoContext(cr) + pl = pg.create_layout() + pl.set_font_description(self.text_font) + pl.set_width(-1) # No text wrapping + + text = "" + if self.text: + text += self.text + else: + if self.torrent_state: + text += self.torrent_state + " " + if self.fraction == 1.0: + format = "%d%%" + else: + format = "%.2f%%" + text += format % (self.fraction*100) + log.debug("PiecesBar text %r", text) + pl.set_text(text) + plsize = pl.get_size() + text_width = plsize[0]/pango.SCALE + text_height = plsize[1]/pango.SCALE + area_width_without_text = event.area.width - text_width + area_height_without_text = event.area.height - text_height + cr.move_to(area_width_without_text/2, area_height_without_text/2) + cr.set_source_rgb(1.0, 1.0, 1.0) + pg.update_layout(pl) + pg.show_layout(pl) + + + def set_fraction(self, fraction): + self.fraction = fraction + self.update() + def set_pieces(self, pieces, num_pieces): if pieces != self.pieces: self.pieces = pieces self.num_pieces = num_pieces self.update() + def update_from_status(self, status): + update = False + + fraction = status["progress"]/100 + if fraction != self.fraction: + self.fraction = fraction + update = True + + torrent_state = status["state"] + if torrent_state != self.torrent_state: + self.torrent_state = torrent_state + update = True + + if torrent_state == "Checking": + self.update() + # Skip the pieces assignment + return + + if status['pieces'] != self.pieces: + self.pieces = status['pieces'] + self.num_pieces = status['num_pieces'] + update = True + + if update: + self.update() + def clear(self): self.pieces = [] self.num_pieces = None + self.fraction = 0.0 self.update() def update(self): self.queue_draw() def get_text(self): - return "" + return self.text def set_text(self, text): - pass - -# def on_pieces_colors_updated(self, key, colors): -# log.debug("Pieces bar got config change for key: %s values: %s", -# key, colors) -# if key != "pieces_colors": -# return -# # Make sure there's no state color missong -# self.colors[0] = [c/65535.0 for c in colors[0]] -# self.colors[1] = [c/65535.0 for c in colors[1]] -# self.colors[2] = [c/65535.0 for c in colors[2]] -# self.colors[3] = [c/65535.0 for c in colors[3]] -# self.update() + self.text = text + self.update() diff --git a/deluge/ui/gtkui/status_tab.py b/deluge/ui/gtkui/status_tab.py index 8d9c844b9..fee9509b0 100644 --- a/deluge/ui/gtkui/status_tab.py +++ b/deluge/ui/gtkui/status_tab.py @@ -126,7 +126,7 @@ class StatusTab(Tab): "max_upload_speed", "max_download_speed", "active_time", "seeding_time", "seed_rank", "is_auto_managed", "time_added"] if self.config['show_piecesbar']: - status_keys.append("pieces") + status_keys.extend(["pieces", "state"]) component.get("SessionProxy").get_torrent_status( @@ -166,7 +166,7 @@ class StatusTab(Tab): if w.get_fraction() != fraction: w.set_fraction(fraction) if self.config['show_piecesbar']: - self.piecesbar.set_pieces(status['pieces'], status["num_pieces"]) + self.piecesbar.update_from_status(status) def on_show_pieces_bar_config_changed(self, key, show): self.show_pieces_bar(show)