Have torrent.get_ratio return -1 when downloaded bytes is 0.
Have torrentview and statistics_tab display an infinity character when ratio is -1
This commit is contained in:
parent
190b180255
commit
6aae2acbe5
|
@ -410,19 +410,11 @@ class Torrent:
|
|||
else:
|
||||
status = self.status
|
||||
|
||||
up = status.all_time_upload
|
||||
down = status.all_time_download
|
||||
# Return -1.0 if the downloaded bytes is 0, this is to represent infinity
|
||||
if status.all_time_download == 0:
|
||||
return -1.0
|
||||
|
||||
# Convert 'up' and 'down' to floats for proper calculation
|
||||
up = float(up)
|
||||
down = float(down)
|
||||
|
||||
try:
|
||||
ratio = up / down
|
||||
except ZeroDivisionError:
|
||||
return 0.0
|
||||
|
||||
return ratio
|
||||
return float(status.all_time_upload) / float(status.all_time_download)
|
||||
|
||||
def get_files(self):
|
||||
"""Returns a list of files this torrent contains"""
|
||||
|
|
|
@ -2,19 +2,19 @@
|
|||
# listview.py
|
||||
#
|
||||
# Copyright (C) 2007, 2008 Andrew Resch ('andar') <andrewresch@gmail.com>
|
||||
#
|
||||
#
|
||||
# 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.,
|
||||
|
@ -50,7 +50,7 @@ def cell_data_speed(column, cell, model, row, data):
|
|||
speed_str = ""
|
||||
if speed > 0:
|
||||
speed_str = deluge.common.fspeed(speed)
|
||||
|
||||
|
||||
cell.set_property('text', speed_str)
|
||||
|
||||
def cell_data_size(column, cell, model, row, data):
|
||||
|
@ -67,7 +67,7 @@ def cell_data_peer(column, cell, model, row, data):
|
|||
cell.set_property('text', '%d (%d)' % (first, second))
|
||||
else:
|
||||
cell.set_property('text', '%d' % first)
|
||||
|
||||
|
||||
def cell_data_time(column, cell, model, row, data):
|
||||
"""Display value as time, eg 1m10s"""
|
||||
time = model.get_value(row, data)
|
||||
|
@ -76,15 +76,15 @@ def cell_data_time(column, cell, model, row, data):
|
|||
else:
|
||||
time_str = deluge.common.ftime(time)
|
||||
cell.set_property('text', time_str)
|
||||
|
||||
|
||||
def cell_data_ratio(column, cell, model, row, data):
|
||||
"""Display value as a ratio with a precision of 3."""
|
||||
ratio = model.get_value(row, data)
|
||||
if ratio == -1:
|
||||
ratio_str = _("Unknown")
|
||||
if ratio < 0:
|
||||
ratio_str = "∞"
|
||||
else:
|
||||
ratio_str = "%.3f" % ratio
|
||||
|
||||
|
||||
cell.set_property('text', ratio_str)
|
||||
|
||||
class ListViewColumnState:
|
||||
|
@ -96,7 +96,7 @@ class ListViewColumnState:
|
|||
self.visible = visible
|
||||
self.sort = sort
|
||||
self.sort_order = sort_order
|
||||
|
||||
|
||||
class ListView:
|
||||
"""ListView is used to make custom GtkTreeViews. It supports the adding
|
||||
and removing of columns, creating a menu for a column toggle list and
|
||||
|
@ -108,8 +108,8 @@ class ListView:
|
|||
def __init__(self, name, column_indices):
|
||||
# Name is how a column is identified and is also the header
|
||||
self.name = name
|
||||
# Column_indices holds the indexes to the liststore_columns that
|
||||
# this column utilizes. It is stored as a list.
|
||||
# Column_indices holds the indexes to the liststore_columns that
|
||||
# this column utilizes. It is stored as a list.
|
||||
self.column_indices = column_indices
|
||||
# Column is a reference to the GtkTreeViewColumn object
|
||||
self.column = None
|
||||
|
@ -122,19 +122,19 @@ class ListView:
|
|||
# If this is set, it is used to sort the model
|
||||
self.sort_func = None
|
||||
self.sort_id = None
|
||||
|
||||
|
||||
def __init__(self, treeview_widget=None, state_file=None):
|
||||
log.debug("ListView initialized..")
|
||||
|
||||
|
||||
if treeview_widget is not None:
|
||||
# User supplied a treeview widget
|
||||
self.treeview = treeview_widget
|
||||
else:
|
||||
self.treeview = gtk.TreeView()
|
||||
|
||||
|
||||
if state_file:
|
||||
self.load_state(state_file)
|
||||
|
||||
|
||||
self.liststore = None
|
||||
self.model_filter = None
|
||||
|
||||
|
@ -155,13 +155,13 @@ class ListView:
|
|||
# A list of menus that self.menu will be a submenu of everytime it is
|
||||
# created.
|
||||
self.checklist_menus = []
|
||||
|
||||
|
||||
# Create the model filter and column
|
||||
self.add_bool_column("filter", hidden=True)
|
||||
|
||||
def create_model_filter(self):
|
||||
"""create new filter-model
|
||||
must be called after listview.create_new_liststore
|
||||
must be called after listview.create_new_liststore
|
||||
"""
|
||||
sort_column = None
|
||||
if self.model_filter:
|
||||
|
@ -171,7 +171,7 @@ class ListView:
|
|||
model_filter.set_visible_column(
|
||||
self.columns["filter"].column_indices[0])
|
||||
self.model_filter = gtk.TreeModelSort(model_filter)
|
||||
self.set_sort_functions()
|
||||
self.set_sort_functions()
|
||||
self.treeview.set_model(self.model_filter)
|
||||
if sort_column and sort_column != (None, None):
|
||||
self.model_filter.set_sort_column_id(*sort_column)
|
||||
|
@ -184,13 +184,13 @@ class ListView:
|
|||
column.sort_id,
|
||||
column.sort_func,
|
||||
column.sort_id)
|
||||
|
||||
|
||||
def save_state(self, filename):
|
||||
"""Saves the listview state (column positions and visibility) to
|
||||
filename."""
|
||||
# A list of ListViewColumnStates
|
||||
state = []
|
||||
|
||||
|
||||
# Get the list of TreeViewColumns from the TreeView
|
||||
treeview_columns = self.treeview.get_columns()
|
||||
counter = 0
|
||||
|
@ -200,12 +200,12 @@ class ListView:
|
|||
if self.get_column_name(id) == column.get_title():
|
||||
sort = id
|
||||
# Append a new column state to the state list
|
||||
state.append(ListViewColumnState(column.get_title(), counter,
|
||||
column.get_width(), column.get_visible(),
|
||||
state.append(ListViewColumnState(column.get_title(), counter,
|
||||
column.get_width(), column.get_visible(),
|
||||
sort, int(column.get_sort_order())))
|
||||
# Increase the counter because this is how we determine position
|
||||
counter += 1
|
||||
|
||||
|
||||
# Get the config location for saving the state file
|
||||
config_location = ConfigManager("gtkui.conf")["config_location"]
|
||||
|
||||
|
@ -216,13 +216,13 @@ class ListView:
|
|||
state_file.close()
|
||||
except IOError, e:
|
||||
log.warning("Unable to save state file: %s", e)
|
||||
|
||||
|
||||
def load_state(self, filename):
|
||||
"""Load the listview state from filename."""
|
||||
# Get the config location for loading the state file
|
||||
config_location = ConfigManager("gtkui.conf")["config_location"]
|
||||
state = None
|
||||
|
||||
|
||||
try:
|
||||
log.debug("Loading ListView state file: %s", filename)
|
||||
state_file = open(os.path.join(config_location, filename), "rb")
|
||||
|
@ -230,16 +230,16 @@ class ListView:
|
|||
state_file.close()
|
||||
except (EOFError, IOError), e:
|
||||
log.warning("Unable to load state file: %s", e)
|
||||
|
||||
|
||||
# Keep the state in self.state so we can access it as we add new columns
|
||||
self.state = state
|
||||
|
||||
|
||||
def set_treeview(self, treeview_widget):
|
||||
"""Set the treeview widget that this listview uses."""
|
||||
self.treeview = treeview_widget
|
||||
self.treeview.set_model(self.liststore)
|
||||
return
|
||||
|
||||
|
||||
def get_column_index(self, name):
|
||||
"""Get the liststore column indices belonging to this column.
|
||||
Will return a list.
|
||||
|
@ -251,33 +251,33 @@ class ListView:
|
|||
for key, value in self.columns.items():
|
||||
if index in value.column_indices:
|
||||
return key
|
||||
|
||||
|
||||
def get_state_field_column(self, field):
|
||||
"""Returns the column number for the state field"""
|
||||
for column in self.columns.keys():
|
||||
if self.columns[column].status_field == None:
|
||||
continue
|
||||
|
||||
|
||||
for f in self.columns[column].status_field:
|
||||
if field == f:
|
||||
return self.columns[column].column_indices[
|
||||
self.columns[column].status_field.index(f)]
|
||||
|
||||
|
||||
def on_menuitem_toggled(self, widget):
|
||||
"""Callback for the generated column menuitems."""
|
||||
# Get the column name from the widget
|
||||
name = widget.get_child().get_text()
|
||||
|
||||
|
||||
# Set the column's visibility based on the widgets active state
|
||||
self.columns[name].column.set_visible(widget.get_active())
|
||||
return
|
||||
|
||||
|
||||
def register_checklist_menu(self, menu):
|
||||
"""Register a checklist menu with the listview. It will automatically
|
||||
attach any new checklist menu it makes to this menu.
|
||||
"""
|
||||
self.checklist_menus.append(menu)
|
||||
|
||||
|
||||
def create_checklist_menu(self):
|
||||
"""Creates a menu used for toggling the display of columns."""
|
||||
menu = gtk.Menu()
|
||||
|
@ -297,20 +297,20 @@ class ListView:
|
|||
menuitem.connect("toggled", self.on_menuitem_toggled)
|
||||
# Add the new checkmenuitem to the menu
|
||||
menu.append(menuitem)
|
||||
|
||||
|
||||
# Attach this new menu to all the checklist_menus
|
||||
for _menu in self.checklist_menus:
|
||||
_menu.set_submenu(menu)
|
||||
_menu.show_all()
|
||||
|
||||
|
||||
return menu
|
||||
|
||||
def create_new_liststore(self):
|
||||
"""Creates a new GtkListStore based on the liststore_columns list"""
|
||||
# Create a new liststore with added column and move the data from the
|
||||
# Create a new liststore with added column and move the data from the
|
||||
# old one to the new one.
|
||||
new_list = gtk.ListStore(*tuple(self.liststore_columns))
|
||||
|
||||
|
||||
# This function is used in the liststore.foreach method with user_data
|
||||
# being the new liststore and the columns list
|
||||
def copy_row(model, path, row, user_data):
|
||||
|
@ -321,17 +321,17 @@ class ListView:
|
|||
value = model.get_value(row, column)
|
||||
# Set the value of this row and column in the new liststore
|
||||
new_list.set_value(new_row, column, value)
|
||||
|
||||
|
||||
# Do the actual row copy
|
||||
if self.liststore is not None:
|
||||
self.liststore.foreach(copy_row, (new_list, self.columns))
|
||||
|
||||
|
||||
self.liststore = new_list
|
||||
# Create the model
|
||||
self.create_model_filter()
|
||||
|
||||
|
||||
return
|
||||
|
||||
|
||||
def remove_column(self, header):
|
||||
"""Removes the column with the name 'header' from the listview"""
|
||||
# Start by removing this column from the treeview
|
||||
|
@ -348,11 +348,11 @@ class ListView:
|
|||
# We need to shift this column_indices
|
||||
for index in column.column_indices:
|
||||
index = index - len(column_indices)
|
||||
|
||||
|
||||
# Remove from the liststore columns list
|
||||
for index in column_indices:
|
||||
del self.liststore_columns[index]
|
||||
|
||||
|
||||
# Create a new liststore
|
||||
self.create_new_liststore()
|
||||
|
||||
|
@ -360,8 +360,8 @@ class ListView:
|
|||
self.create_checklist_menu()
|
||||
|
||||
return
|
||||
|
||||
def add_column(self, header, render, col_types, hidden, position,
|
||||
|
||||
def add_column(self, header, render, col_types, hidden, position,
|
||||
status_field, sortid, text=0, value=0, pixbuf=0, function=None,
|
||||
column_type=None, sort_func=None):
|
||||
"""Adds a column to the ListView"""
|
||||
|
@ -374,23 +374,23 @@ class ListView:
|
|||
else:
|
||||
self.liststore_columns.append(col_types)
|
||||
column_indices.append(len(self.liststore_columns) - 1)
|
||||
|
||||
|
||||
# Add to the index list so we know the order of the visible columns.
|
||||
if position is not None:
|
||||
self.column_index.insert(position, header)
|
||||
else:
|
||||
self.column_index.append(header)
|
||||
|
||||
|
||||
# Create a new column object and add it to the list
|
||||
self.columns[header] = self.ListViewColumn(header, column_indices)
|
||||
|
||||
|
||||
self.columns[header].status_field = status_field
|
||||
self.columns[header].sort_func = sort_func
|
||||
self.columns[header].sort_id = column_indices[sortid]
|
||||
|
||||
|
||||
# Create a new list with the added column
|
||||
self.create_new_liststore()
|
||||
|
||||
|
||||
column = gtk.TreeViewColumn(header)
|
||||
if column_type == "text":
|
||||
column.pack_start(render)
|
||||
|
@ -403,11 +403,11 @@ class ListView:
|
|||
elif column_type == "func":
|
||||
column.pack_start(render, True)
|
||||
if len(self.columns[header].column_indices) > 1:
|
||||
column.set_cell_data_func(render, function,
|
||||
column.set_cell_data_func(render, function,
|
||||
tuple(self.columns[header].column_indices))
|
||||
else:
|
||||
column.set_cell_data_func(render, function,
|
||||
self.columns[header].column_indices[0])
|
||||
self.columns[header].column_indices[0])
|
||||
elif column_type == "progress":
|
||||
column.pack_start(render)
|
||||
if function is None:
|
||||
|
@ -416,7 +416,7 @@ class ListView:
|
|||
column.add_attribute(render, "value",
|
||||
self.columns[header].column_indices[value])
|
||||
else:
|
||||
column.set_cell_data_func(render, function,
|
||||
column.set_cell_data_func(render, function,
|
||||
tuple(self.columns[header].column_indices))
|
||||
elif column_type == "texticon":
|
||||
column.pack_start(render[pixbuf], False)
|
||||
|
@ -445,7 +445,7 @@ class ListView:
|
|||
if column_state.width > 0:
|
||||
column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
|
||||
column.set_fixed_width(column_state.width)
|
||||
|
||||
|
||||
if column_state.sort is not None and column_state.sort > -1:
|
||||
self.model_filter.set_sort_column_id(column_state.sort, column_state.sort_order)
|
||||
column.set_visible(column_state.visible)
|
||||
|
@ -461,10 +461,10 @@ class ListView:
|
|||
self.columns[header].column = column
|
||||
# Re-create the menu item because of the new column
|
||||
self.create_checklist_menu()
|
||||
|
||||
|
||||
return True
|
||||
|
||||
def add_text_column(self, header, col_type=str, hidden=False,
|
||||
|
||||
def add_text_column(self, header, col_type=str, hidden=False,
|
||||
position=None,
|
||||
status_field=None,
|
||||
sortid=0,
|
||||
|
@ -475,63 +475,63 @@ class ListView:
|
|||
render = gtk.CellRendererText()
|
||||
self.add_column(header, render, col_type, hidden, position,
|
||||
status_field, sortid, column_type=column_type, sort_func=sort_func)
|
||||
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def add_bool_column(self, header, col_type=bool, hidden=False,
|
||||
position=None,
|
||||
status_field=None,
|
||||
sortid=0,
|
||||
column_type="bool"):
|
||||
|
||||
|
||||
"""Add a bool column to the listview"""
|
||||
render = gtk.CellRendererToggle()
|
||||
self.add_column(header, render, col_type, hidden, position,
|
||||
status_field, sortid, column_type=column_type)
|
||||
|
||||
def add_func_column(self, header, function, col_types, sortid=0,
|
||||
|
||||
def add_func_column(self, header, function, col_types, sortid=0,
|
||||
hidden=False, position=None, status_field=None,
|
||||
column_type="func", sort_func=None):
|
||||
"""Add a function column to the listview. Need a header name, the
|
||||
function and the column types."""
|
||||
|
||||
|
||||
render = gtk.CellRendererText()
|
||||
self.add_column(header, render, col_types, hidden, position,
|
||||
status_field, sortid, column_type=column_type,
|
||||
status_field, sortid, column_type=column_type,
|
||||
function=function, sort_func=sort_func)
|
||||
|
||||
return True
|
||||
|
||||
def add_progress_column(self, header, col_types=[float, str],
|
||||
sortid=0,
|
||||
hidden=False,
|
||||
position=None,
|
||||
def add_progress_column(self, header, col_types=[float, str],
|
||||
sortid=0,
|
||||
hidden=False,
|
||||
position=None,
|
||||
status_field=None,
|
||||
function=None,
|
||||
column_type="progress"):
|
||||
"""Add a progress column to the listview."""
|
||||
|
||||
|
||||
render = gtk.CellRendererProgress()
|
||||
self.add_column(header, render, col_types, hidden, position,
|
||||
status_field, sortid, function=function,
|
||||
column_type=column_type,
|
||||
column_type=column_type,
|
||||
value=0, text=1)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def add_texticon_column(self, header, col_types=[str, str],
|
||||
sortid=1,
|
||||
hidden=False,
|
||||
position=None,
|
||||
hidden=False,
|
||||
position=None,
|
||||
status_field=None,
|
||||
column_type="texticon",
|
||||
function=None):
|
||||
"""Adds a texticon column to the listview."""
|
||||
render1 = gtk.CellRendererPixbuf()
|
||||
render2 = gtk.CellRendererText()
|
||||
|
||||
render2 = gtk.CellRendererText()
|
||||
|
||||
self.add_column(header, (render1, render2), col_types, hidden,
|
||||
position, status_field, sortid,
|
||||
position, status_field, sortid,
|
||||
column_type=column_type, function=function,
|
||||
pixbuf=0, text=1)
|
||||
|
||||
|
|
|
@ -46,6 +46,8 @@ def fpeer_size_second(first, second):
|
|||
return "%s (%s)" % (first, deluge.common.fsize(second))
|
||||
|
||||
def fratio(value):
|
||||
if value < 0:
|
||||
return "∞"
|
||||
return "%.3f" % value
|
||||
|
||||
def fpcnt(value):
|
||||
|
|
|
@ -113,7 +113,7 @@ def queue_column_sort(model, iter1, iter2, data):
|
|||
return 1
|
||||
if v2 > v1:
|
||||
return -1
|
||||
|
||||
|
||||
class TorrentView(listview.ListView, component.Component):
|
||||
"""TorrentView handles the listing of torrents."""
|
||||
def __init__(self):
|
||||
|
@ -130,7 +130,7 @@ class TorrentView(listview.ListView, component.Component):
|
|||
|
||||
# We keep a copy of the previous status to compare for changes
|
||||
self.prev_status = {}
|
||||
|
||||
|
||||
# Register the columns menu with the listview so it gets updated
|
||||
# accordingly.
|
||||
self.register_checklist_menu(
|
||||
|
@ -196,7 +196,7 @@ class TorrentView(listview.ListView, component.Component):
|
|||
self.on_selection_changed)
|
||||
|
||||
self.treeview.connect("drag-drop", self.on_drag_drop)
|
||||
|
||||
|
||||
def start(self):
|
||||
"""Start the torrentview"""
|
||||
# We need to get the core session state to know which torrents are in
|
||||
|
@ -297,12 +297,12 @@ class TorrentView(listview.ListView, component.Component):
|
|||
if row[column_index[i]] != row_value:
|
||||
row[column_index[i]] = row_value
|
||||
except Exception, e:
|
||||
log.debug("%s", e)
|
||||
|
||||
log.debug("%s", e)
|
||||
|
||||
# Update the toolbar buttons just in case some state has changed
|
||||
component.get("ToolBar").update_buttons()
|
||||
component.get("MenuBar").update_menu()
|
||||
|
||||
|
||||
self.prev_status = status
|
||||
|
||||
def _on_get_torrents_status(self, status):
|
||||
|
|
Loading…
Reference in New Issue