PiecesBar implementation.

We now provide an option to the user to see the states of a torrent's pieces, ie, completed, downloading, waiting, missing.
If the user has this option enabled, another 3 will be shown to him(on the GTK UI), which will allow him to choose the colors for each piece state.
This commit is contained in:
Pedro Algarvio 2011-05-04 23:26:46 +01:00
commit da5c5d4b84
6 changed files with 732 additions and 9 deletions

View file

@ -781,6 +781,152 @@
</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>
@ -1255,15 +1401,29 @@
<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>
<property name="spacing">5</property> <property name="spacing">5</property>
<child> <child>
<widget class="GtkProgressBar" id="progressbar"> <widget class="GtkVBox" id="status_progress_vbox">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="show_text">True</property> <child>
<property name="pulse_step">0.10000000149</property> <widget class="GtkProgressBar" id="progressbar">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="show_text">True</property>
<property name="pulse_step">0.10000000149</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<placeholder/>
</child>
</widget> </widget>
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>
<property name="fill">False</property> <property name="fill">True</property>
<property name="position">0</property> <property name="position">0</property>
</packing> </packing>
</child> </child>

View file

@ -2249,11 +2249,13 @@ Use at your own risk if you wish to help us debug
this new feature.</property> this new feature.</property>
<property name="use_action_appearance">False</property> <property name="use_action_appearance">False</property>
<property name="draw_indicator">True</property> <property name="draw_indicator">True</property>
<signal name="toggled" handler="on_piecesbar_toggle_toggled"/>
<child> <child>
<widget class="GtkLabel" id="label62"> <widget class="GtkLabel" id="label62">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="label" translatable="yes">Show pieces bar instead of the progress bar (&lt;b&gt;EXPERIMENTAL!!!&lt;/b&gt;)</property> <property name="label" translatable="yes">Show a pieces bar in the torrent's
status tab (&lt;b&gt;EXPERIMENTAL!!!&lt;/b&gt;)</property>
<property name="use_markup">True</property> <property name="use_markup">True</property>
</widget> </widget>
</child> </child>
@ -2264,6 +2266,245 @@ this new feature.</property>
<property name="position">1</property> <property name="position">1</property>
</packing> </packing>
</child> </child>
<child>
<widget class="GtkExpander" id="piecebar_colors_expander">
<property name="can_focus">True</property>
<child>
<widget class="GtkAlignment" id="alignment58">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="left_padding">25</property>
<child>
<widget class="GtkTable" id="table6">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="n_rows">4</property>
<property name="n_columns">3</property>
<property name="column_spacing">5</property>
<property name="row_spacing">1</property>
<child>
<widget class="GtkLabel" id="label66">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">1</property>
<property name="label" translatable="yes">Completed:</property>
</widget>
<packing>
<property name="x_options">GTK_FILL</property>
</packing>
</child>
<child>
<widget class="GtkColorButton" id="completed_color">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<property name="xalign">0</property>
<property name="color">#000000000000</property>
<signal name="color_set" handler="on_completed_color_set"/>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="x_options"></property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label67">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">1</property>
<property name="label" translatable="yes">Downloading:</property>
</widget>
<packing>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options">GTK_FILL</property>
</packing>
</child>
<child>
<widget class="GtkColorButton" id="downloading_color">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<property name="xalign">0</property>
<property name="color">#000000000000</property>
<signal name="color_set" handler="on_downloading_color_set"/>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options"></property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label69">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">1</property>
<property name="label" translatable="yes">Waiting:</property>
</widget>
<packing>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="x_options">GTK_FILL</property>
</packing>
</child>
<child>
<widget class="GtkColorButton" id="waiting_color">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<property name="xalign">0</property>
<property name="color">#000000000000</property>
<signal name="color_set" handler="on_waiting_color_set"/>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="x_options"></property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label70">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">1</property>
<property name="label" translatable="yes">Missing:</property>
</widget>
<packing>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="x_options">GTK_FILL</property>
</packing>
</child>
<child>
<widget class="GtkColorButton" id="missing_color">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<property name="xalign">0</property>
<property name="color">#000000000000</property>
<signal name="color_set" handler="on_missing_color_set"/>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="x_options"></property>
</packing>
</child>
<child>
<widget class="GtkButton" id="revert_color_completed">
<property name="label">gtk-revert-to-saved</property>
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="tooltip" translatable="yes">Revert color to default</property>
<property name="use_action_appearance">False</property>
<property name="use_stock">True</property>
<property name="image_position">right</property>
<signal name="clicked" handler="on_revert_color_completed_clicked"/>
</widget>
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="x_options"></property>
</packing>
</child>
<child>
<widget class="GtkButton" id="revert_color_downloading">
<property name="label">gtk-revert-to-saved</property>
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="tooltip" translatable="yes">Revert color to default</property>
<property name="use_action_appearance">False</property>
<property name="use_stock">True</property>
<property name="image_position">right</property>
<signal name="clicked" handler="on_revert_color_downloading_clicked"/>
</widget>
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options"></property>
</packing>
</child>
<child>
<widget class="GtkButton" id="revert_color_waiting">
<property name="label">gtk-revert-to-saved</property>
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="tooltip" translatable="yes">Revert color to default</property>
<property name="use_action_appearance">False</property>
<property name="use_stock">True</property>
<property name="image_position">right</property>
<signal name="clicked" handler="on_revert_color_waiting_clicked"/>
</widget>
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="x_options"></property>
</packing>
</child>
<child>
<widget class="GtkButton" id="revert_color_missing">
<property name="label">gtk-revert-to-saved</property>
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="tooltip" translatable="yes">Revert color to default</property>
<property name="use_action_appearance">False</property>
<property name="use_stock">True</property>
<property name="image_position">right</property>
<signal name="clicked" handler="on_revert_color_missing_clicked"/>
</widget>
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="x_options"></property>
</packing>
</child>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkLabel" id="label73">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Piece Colors</property>
</widget>
<packing>
<property name="type">label_item</property>
</packing>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">2</property>
</packing>
</child>
</widget> </widget>
</child> </child>
</widget> </widget>

View file

@ -157,7 +157,18 @@ DEFAULT_PREFS = {
"sidebar_show_trackers": True, "sidebar_show_trackers": True,
"sidebar_position": 170, "sidebar_position": 170,
"show_rate_in_title": False, "show_rate_in_title": False,
"createtorrent.trackers": [] "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],
"pieces_color_completed": [4883, 26985, 56540],
} }
class GtkUI(object): class GtkUI(object):

View file

@ -0,0 +1,184 @@
# -*- coding: utf-8 -*-
#
# listview.py
#
# Copyright (C) 2011 Pedro Algarvio <pedro@algarvio.me>
#
# 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.
#
#
import pygtk
pygtk.require('2.0')
import gtk
import gtk.gdk
import cairo
import logging
from deluge.configmanager import ConfigManager
log = logging.getLogger(__name__)
COLOR_STATES = {
0: "missing",
1: "waiting",
2: "downloading",
3: "completed"
}
class PiecesBar(gtk.DrawingArea):
# Draw in response to an expose-event
__gsignals__ = {"expose-event": "override"}
def __init__(self):
gtk.DrawingArea.__init__(self)
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.connect('size-allocate', self.do_size_allocate_event)
self.set_colormap(self.get_screen().get_rgba_colormap())
self.show()
def do_size_allocate_event(self, widget, size):
self.width = size.width
self.height = size.height
# Handle the expose-event by drawing
def do_expose_event(self, event=None):
# Create the cairo context
cr = self.window.cairo_create()
# Restrict Cairo to the exposed area; avoid extra work
cr.rectangle(event.area.x, event.area.y,
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.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:
# Complete Torrent
piece_height = self.height - 2
piece_width = self.width*1.0/self.num_pieces
start = 1
for _ in range(self.num_pieces):
# Like this to keep same aspect ratio
color = self.gtkui_config["pieces_color_%s" % COLOR_STATES[3]]
cr.set_source_rgb(
color[0]/65535.0,
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
return
if not self.pieces:
return
# Create the cairo context
start_pos = 1
num_pieces = self.num_pieces and self.num_pieces or len(self.pieces)
piece_width = self.width*1.0/num_pieces
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
def set_pieces(self, pieces, num_pieces):
if pieces != self.pieces:
self.pieces = pieces
self.num_pieces = num_pieces
self.update()
def clear(self):
self.pieces = []
self.num_pieces = None
self.update()
def update(self):
self.queue_draw()
def get_text(self):
return ""
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()

View file

@ -53,6 +53,14 @@ import deluge.configmanager
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
ACCOUNTS_USERNAME, ACCOUNTS_LEVEL, ACCOUNTS_PASSWORD = range(3) ACCOUNTS_USERNAME, ACCOUNTS_LEVEL, ACCOUNTS_PASSWORD = range(3)
COLOR_MISSING, COLOR_WAITING, COLOR_DOWNLOADING, COLOR_COMPLETED = range(4)
COLOR_STATES = {
"missing": COLOR_MISSING,
"waiting": COLOR_WAITING,
"downloading": COLOR_DOWNLOADING,
"completed": COLOR_COMPLETED
}
class Preferences(component.Component): class Preferences(component.Component):
def __init__(self): def __init__(self):
@ -152,9 +160,24 @@ class Preferences(component.Component):
"on_accounts_add_clicked": self._on_accounts_add_clicked, "on_accounts_add_clicked": self._on_accounts_add_clicked,
"on_accounts_delete_clicked": self._on_accounts_delete_clicked, "on_accounts_delete_clicked": self._on_accounts_delete_clicked,
"on_accounts_edit_clicked": self._on_accounts_edit_clicked, "on_accounts_edit_clicked": self._on_accounts_edit_clicked,
"on_alocation_toggled": self._on_alocation_toggled "on_alocation_toggled": self._on_alocation_toggled,
"on_piecesbar_toggle_toggled": self._on_piecesbar_toggle_toggled,
"on_completed_color_set": self._on_completed_color_set,
"on_revert_color_completed_clicked": self._on_revert_color_completed_clicked,
"on_downloading_color_set": self._on_downloading_color_set,
"on_revert_color_downloading_clicked": self._on_revert_color_downloading_clicked,
"on_waiting_color_set": self._on_waiting_color_set,
"on_revert_color_waiting_clicked": self._on_revert_color_waiting_clicked,
"on_missing_color_set": self._on_missing_color_set,
"on_revert_color_missing_clicked": self._on_revert_color_missing_clicked
}) })
from deluge.ui.gtkui.gtkui import DEFAULT_PREFS
self.COLOR_DEFAULTS = {}
for key in ("missing", "waiting", "downloading", "completed"):
self.COLOR_DEFAULTS[key] = DEFAULT_PREFS["pieces_color_%s" % key][:]
del DEFAULT_PREFS
# These get updated by requests done to the core # These get updated by requests done to the core
self.all_plugins = [] self.all_plugins = []
self.enabled_plugins = [] self.enabled_plugins = []
@ -527,6 +550,13 @@ class Preferences(component.Component):
self.gtkui_config["classic_mode"]) self.gtkui_config["classic_mode"])
self.glade.get_widget("chk_show_rate_in_title").set_active( self.glade.get_widget("chk_show_rate_in_title").set_active(
self.gtkui_config["show_rate_in_title"]) self.gtkui_config["show_rate_in_title"])
self.glade.get_widget("piecesbar_toggle").set_active(
self.gtkui_config["show_piecesbar"]
)
self.__set_color("completed", from_config=True)
self.__set_color("downloading", from_config=True)
self.__set_color("waiting", from_config=True)
self.__set_color("missing", from_config=True)
## Other tab ## ## Other tab ##
self.glade.get_widget("chk_show_new_releases").set_active( self.glade.get_widget("chk_show_new_releases").set_active(
@ -578,6 +608,13 @@ class Preferences(component.Component):
self.glade.get_widget("chk_show_dialog").get_active() self.glade.get_widget("chk_show_dialog").get_active()
new_gtkui_config["focus_add_dialog"] = \ new_gtkui_config["focus_add_dialog"] = \
self.glade.get_widget("chk_focus_dialog").get_active() self.glade.get_widget("chk_focus_dialog").get_active()
for state in ("missing", "waiting", "downloading", "completed"):
color = self.glade.get_widget("%s_color" % state).get_color()
new_gtkui_config["pieces_color_%s" % state] = [
color.red, color.green, color.blue
]
new_core_config["copy_torrent_file"] = \ new_core_config["copy_torrent_file"] = \
self.glade.get_widget("chk_copy_torrent_file").get_active() self.glade.get_widget("chk_copy_torrent_file").get_active()
new_core_config["del_copy_torrent_file"] = \ new_core_config["del_copy_torrent_file"] = \
@ -916,6 +953,7 @@ class Preferences(component.Component):
def on_test_port_clicked(self, data): def on_test_port_clicked(self, data):
log.debug("on_test_port_clicked") log.debug("on_test_port_clicked")
def on_get_test(status): def on_get_test(status):
if status: if status:
self.glade.get_widget("port_img").set_from_stock(gtk.STOCK_YES, 4) self.glade.get_widget("port_img").set_from_stock(gtk.STOCK_YES, 4)
@ -924,6 +962,8 @@ class Preferences(component.Component):
self.glade.get_widget("port_img").set_from_stock(gtk.STOCK_DIALOG_WARNING, 4) self.glade.get_widget("port_img").set_from_stock(gtk.STOCK_DIALOG_WARNING, 4)
self.glade.get_widget("port_img").show() self.glade.get_widget("port_img").show()
client.core.test_listen_port().addCallback(on_get_test) client.core.test_listen_port().addCallback(on_get_test)
# XXX: Consider using gtk.Spinner() instead of the loading gif
# It requires gtk.ver > 2.12
self.glade.get_widget("port_img").set_from_file( self.glade.get_widget("port_img").set_from_file(
deluge.common.get_pixmap('loading.gif') deluge.common.get_pixmap('loading.gif')
) )
@ -1210,3 +1250,60 @@ class Preferences(component.Component):
full_allocation_active = self.glade.get_widget("radio_full_allocation").get_active() full_allocation_active = self.glade.get_widget("radio_full_allocation").get_active()
self.glade.get_widget("chk_prioritize_first_last_pieces").set_sensitive(full_allocation_active) self.glade.get_widget("chk_prioritize_first_last_pieces").set_sensitive(full_allocation_active)
self.glade.get_widget("chk_sequential_download").set_sensitive(full_allocation_active) self.glade.get_widget("chk_sequential_download").set_sensitive(full_allocation_active)
def _on_piecesbar_toggle_toggled(self, widget):
self.gtkui_config['show_piecesbar'] = widget.get_active()
colors_widget = self.glade.get_widget("piecebar_colors_expander")
colors_widget.set_visible(widget.get_active())
def _on_completed_color_set(self, widget):
self.__set_color("completed")
def _on_revert_color_completed_clicked(self, widget):
self.__revert_color("completed")
def _on_downloading_color_set(self, widget):
self.__set_color("downloading")
def _on_revert_color_downloading_clicked(self, widget):
self.__revert_color("downloading")
def _on_waiting_color_set(self, widget):
self.__set_color("waiting")
def _on_revert_color_waiting_clicked(self, widget):
self.__revert_color("waiting")
def _on_missing_color_set(self, widget):
self.__set_color("missing")
def _on_revert_color_missing_clicked(self, widget):
self.__revert_color("missing")
def __set_color(self, state, from_config=False):
if from_config:
color = gtk.gdk.Color(*self.gtkui_config["pieces_color_%s" % state])
log.debug("Setting %r color state from config to %s", state,
(color.red, color.green, color.blue))
self.glade.get_widget("%s_color" % state).set_color(color)
else:
color = self.glade.get_widget("%s_color" % state).get_color()
log.debug("Setting %r color state to %s", state,
(color.red, color.green, color.blue))
self.gtkui_config["pieces_color_%s" % state] = [
color.red, color.green, color.blue
]
self.gtkui_config.save()
self.gtkui_config.apply_set_functions("pieces_colors")
self.glade.get_widget("revert_color_%s" % state).set_sensitive(
[color.red, color.green, color.blue] != self.COLOR_DEFAULTS[state]
)
def __revert_color(self, state, from_config=False):
log.debug("Reverting %r color state", state)
self.glade.get_widget("%s_color" % state).set_color(
gtk.gdk.Color(*self.COLOR_DEFAULTS[state])
)
self.glade.get_widget("revert_color_%s" % state).set_sensitive(False)
self.gtkui_config.apply_set_functions("pieces_colors")

View file

@ -42,7 +42,9 @@ import logging
from deluge.ui.client import client from deluge.ui.client import client
import deluge.component as component import deluge.component as component
import deluge.common import deluge.common
from deluge.configmanager import ConfigManager
from deluge.ui.gtkui.torrentdetails import Tab from deluge.ui.gtkui.torrentdetails import Tab
from deluge.ui.gtkui.piecesbar import PiecesBar
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -71,12 +73,17 @@ class StatusTab(Tab):
Tab.__init__(self) Tab.__init__(self)
# Get the labels we need to update. # Get the labels we need to update.
# widgetname, modifier function, status keys # widgetname, modifier function, status keys
glade = component.get("MainWindow").main_glade self.glade = glade = component.get("MainWindow").main_glade
self._name = "Status" self._name = "Status"
self._child_widget = glade.get_widget("status_tab") self._child_widget = glade.get_widget("status_tab")
self._tab_label = glade.get_widget("status_tab_label") self._tab_label = glade.get_widget("status_tab_label")
self.config = ConfigManager("gtkui.conf")
self.config.register_set_function(
"show_piecesbar",
self.on_show_pieces_bar_config_changed,
apply_now=True
)
self.label_widgets = [ self.label_widgets = [
(glade.get_widget("summary_pieces"), fpeer_size_second, ("num_pieces", "piece_length")), (glade.get_widget("summary_pieces"), fpeer_size_second, ("num_pieces", "piece_length")),
(glade.get_widget("summary_availability"), fratio, ("distributed_copies",)), (glade.get_widget("summary_availability"), fratio, ("distributed_copies",)),
@ -118,6 +125,9 @@ class StatusTab(Tab):
"tracker_status", "max_connections", "max_upload_slots", "tracker_status", "max_connections", "max_upload_slots",
"max_upload_speed", "max_download_speed", "active_time", "max_upload_speed", "max_download_speed", "active_time",
"seeding_time", "seed_rank", "is_auto_managed", "time_added"] "seeding_time", "seed_rank", "is_auto_managed", "time_added"]
if self.config['show_piecesbar']:
status_keys.append("pieces")
component.get("SessionProxy").get_torrent_status( component.get("SessionProxy").get_torrent_status(
selected, status_keys).addCallback(self._on_get_torrent_status) selected, status_keys).addCallback(self._on_get_torrent_status)
@ -155,9 +165,29 @@ class StatusTab(Tab):
fraction = status["progress"] / 100 fraction = status["progress"] / 100
if w.get_fraction() != fraction: if w.get_fraction() != fraction:
w.set_fraction(fraction) w.set_fraction(fraction)
if self.config['show_piecesbar']:
self.piecesbar.set_pieces(status['pieces'], status["num_pieces"])
def on_show_pieces_bar_config_changed(self, key, show):
self.show_pieces_bar(show)
def show_pieces_bar(self, show):
if hasattr(self, 'piecesbar'):
if show:
self.piecesbar.show()
else:
self.piecesbar.hide()
else:
if show:
self.piecesbar = PiecesBar()
self.glade.get_widget("status_progress_vbox").pack_start(
self.piecesbar, False, False, 5
)
def clear(self): def clear(self):
for widget in self.label_widgets: for widget in self.label_widgets:
widget[0].set_text("") widget[0].set_text("")
component.get("MainWindow").main_glade.get_widget("progressbar").set_fraction(0.0) component.get("MainWindow").main_glade.get_widget("progressbar").set_fraction(0.0)
if self.config['show_piecesbar']:
self.piecesbar.clear()