deluge/deluge/ui/gtkui/torrentview_data_funcs.py
bendikro 8ecc0e11a7 Fix for #1885 and add simple caching to the data funcs for the torrentview
* Fix for #1885 (Wrong tracker icon in torrent list)
* Moved the data functions from torrentview/listview into
  torrentview_data_funcs.py
* Added caching the current value of the cell renderer for the data functions
* Reordered if-tests in deluge.common.fsize
* Disable data funcs when column is hidden
2013-12-23 16:21:24 +00:00

303 lines
10 KiB
Python

# -*- coding: utf-8 -*-
# torrentview_data_funcs.py
#
# Copyright (C) 2007, 2008 Andrew Resch <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.,
# 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 deluge.common as common
import gtk
import warnings
import gobject
import deluge.component as component
# Status icons.. Create them from file only once to avoid constantly
# re-creating them.
icon_downloading = gtk.gdk.pixbuf_new_from_file(common.get_pixmap("downloading16.png"))
icon_seeding = gtk.gdk.pixbuf_new_from_file(common.get_pixmap("seeding16.png"))
icon_inactive = gtk.gdk.pixbuf_new_from_file(common.get_pixmap("inactive16.png"))
icon_alert = gtk.gdk.pixbuf_new_from_file(common.get_pixmap("alert16.png"))
icon_queued = gtk.gdk.pixbuf_new_from_file(common.get_pixmap("queued16.png"))
icon_checking = gtk.gdk.pixbuf_new_from_file(common.get_pixmap("checking16.png"))
# Holds the info for which status icon to display based on state
ICON_STATE = {
"Allocating": icon_checking,
"Checking": icon_checking,
"Downloading": icon_downloading,
"Seeding": icon_seeding,
"Paused": icon_inactive,
"Error": icon_alert,
"Queued": icon_queued,
"Checking Resume Data": icon_checking
}
def _(message): return message
TRANSLATE = {
"Downloading": _("Downloading"),
"Seeding": _("Seeding"),
"Paused": _("Paused"),
"Checking": _("Checking"),
"Queued": _("Queued"),
"Error": _("Error"),
}
del _
def _t(text):
if text in TRANSLATE:
text = TRANSLATE[text]
return _(text)
# Cache the key used to calculate the current value set for the specific cell
# renderer. This is much cheaper than fetch the current value and test if
# it's equal.
func_last_value = {"cell_data_speed_down": None,
"cell_data_speed_up": None,
"cell_data_time": None,
"cell_data_ratio_seeders": None,
"cell_data_ratio_ratio": None,
"cell_data_ratio_avail": None,
"cell_data_date": None,
"cell_data_date_or_never": None,
"cell_data_speed_limit_down": None,
"cell_data_speed_limit_up": None,
"cell_data_trackericon": None,
"cell_data_statusicon": None,
"cell_data_queue": None,
"cell_data_progress": [None, None],
}
def cell_data_statusicon(column, cell, model, row, data):
"""Display text with an icon"""
try:
state = model.get_value(row, data)
if func_last_value["cell_data_statusicon"] == state:
return
func_last_value["cell_data_statusicon"] = state
icon = ICON_STATE[state]
#Supress Warning: g_object_set_qdata: assertion `G_IS_OBJECT (object)' failed
original_filters = warnings.filters[:]
warnings.simplefilter("ignore")
try:
cell.set_property("pixbuf", icon)
finally:
warnings.filters = original_filters
except KeyError:
pass
def create_blank_pixbuf():
i = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, True, 8, 16, 16)
i.fill(0x00000000)
return i
def set_icon(icon, cell):
if icon:
pixbuf = icon.get_cached_icon()
if pixbuf is None:
try:
pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(icon.get_filename(), 16, 16)
except gobject.GError, e:
# Failed to load the pixbuf (Bad image file), so set a blank pixbuf
pixbuf = create_blank_pixbuf()
finally:
icon.set_cached_icon(pixbuf)
else:
pixbuf = create_blank_pixbuf()
#Suppress Warning: g_object_set_qdata: assertion `G_IS_OBJECT (object)' failed
with warnings.catch_warnings():
warnings.simplefilter("ignore")
cell.set_property("pixbuf", pixbuf)
def cell_data_trackericon(column, cell, model, row, data):
host = model[row][data]
if func_last_value["cell_data_trackericon"] == host:
return
if host:
if not component.get("TrackerIcons").has(host):
# Set blank icon while waiting for the icon to be loaded
set_icon(None, cell)
component.get("TrackerIcons").fetch(host)
func_last_value["cell_data_trackericon"] = None
else:
set_icon(component.get("TrackerIcons").get(host), cell)
# Only set the last value when we have found the icon
func_last_value["cell_data_trackericon"] = host
else:
set_icon(None, cell)
func_last_value["cell_data_trackericon"] = None
def cell_data_progress(column, cell, model, row, data):
"""Display progress bar with text"""
(value, state_str) = model.get(row, *data)
if func_last_value["cell_data_progress"][0] != value:
func_last_value["cell_data_progress"][0] = value
cell.set_property("value", value)
textstr = _t(state_str)
if state_str != "Seeding" and value < 100:
textstr = textstr + " %.2f%%" % value
if func_last_value["cell_data_progress"][1] != textstr:
func_last_value["cell_data_progress"][1] = textstr
cell.set_property("text", textstr)
def cell_data_queue(column, cell, model, row, data):
value = model.get_value(row, data)
if func_last_value["cell_data_queue"] == value:
return
func_last_value["cell_data_queue"] = value
if value < 0:
cell.set_property("text", "")
else:
cell.set_property("text", str(value + 1))
def cell_data_speed(cell, model, row, data, cache_key):
"""Display value as a speed, eg. 2 KiB/s"""
try:
speed = model.get_value(row, data)
except AttributeError, e:
print "AttributeError"
import traceback
traceback.print_exc()
if func_last_value[cache_key] == speed:
return
func_last_value[cache_key] = speed
speed_str = ""
if speed > 0:
speed_str = common.fspeed(speed)
cell.set_property('text', speed_str)
def cell_data_speed_down(column, cell, model, row, data):
"""Display value as a speed, eg. 2 KiB/s"""
cell_data_speed(cell, model, row, data, "cell_data_speed_down")
def cell_data_speed_up(column, cell, model, row, data):
"""Display value as a speed, eg. 2 KiB/s"""
cell_data_speed(cell, model, row, data, "cell_data_speed_up")
def cell_data_speed_limit(cell, model, row, data, cache_key):
"""Display value as a speed, eg. 2 KiB/s"""
speed = model.get_value(row, data)
if func_last_value[cache_key] == speed:
return
func_last_value[cache_key] = speed
speed_str = ""
if speed > 0:
speed_str = common.fspeed(speed * 1024)
cell.set_property('text', speed_str)
def cell_data_speed_limit_down(column, cell, model, row, data):
cell_data_speed_limit(cell, model, row, data, "cell_data_speed_limit_down")
def cell_data_speed_limit_up(column, cell, model, row, data):
cell_data_speed_limit(cell, model, row, data, "cell_data_speed_limit_up")
def cell_data_size(column, cell, model, row, data):
"""Display value in terms of size, eg. 2 MB"""
size = model.get_value(row, data)
cell.set_property('text', common.fsize(size))
def cell_data_peer(column, cell, model, row, data):
"""Display values as 'value1 (value2)'"""
(first, second) = model.get(row, *data)
# Only display a (total) if second is greater than -1
if second > -1:
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)
if func_last_value["cell_data_time"] == time:
return
func_last_value["cell_data_time"] = time
if time <= 0:
time_str = ""
else:
time_str = common.ftime(time)
cell.set_property('text', time_str)
def cell_data_ratio(cell, model, row, data, cache_key):
"""Display value as a ratio with a precision of 3."""
ratio = model.get_value(row, data)
# Previous value in cell is the same as for this value, so ignore
if func_last_value[cache_key] == ratio:
return
func_last_value[cache_key] = ratio
cell.set_property('text', "" if ratio < 0 else "%.3f" % ratio)
def cell_data_ratio_seeders(column, cell, model, row, data):
cell_data_ratio(cell, model, row, data, "cell_data_ratio_seeders")
def cell_data_ratio_ratio(column, cell, model, row, data):
cell_data_ratio(cell, model, row, data, "cell_data_ratio_ratio")
def cell_data_ratio_avail(column, cell, model, row, data):
cell_data_ratio(cell, model, row, data, "cell_data_ratio_avail")
def cell_data_date(column, cell, model, row, data):
"""Display value as date, eg 05/05/08"""
date = model.get_value(row, data)
if func_last_value["cell_data_date"] == date:
return
func_last_value["cell_data_date"] = date
date_str = common.fdate(date)
cell.set_property('text', date_str)
def cell_data_date_or_never(column, cell, model, row, data):
"""Display value as date, eg 05/05/08 or Never"""
value = model.get_value(row, data)
if func_last_value["cell_data_date_or_never"] == value:
return
func_last_value["cell_data_date_or_never"] = value
date_str = common.fdate(value) if value > 0.0 else _("Never")
cell.set_property('text', date_str)