diff --git a/deluge/ui/gtkui/columns.py b/deluge/ui/gtkui/columns.py deleted file mode 100644 index d47cd3c5a..000000000 --- a/deluge/ui/gtkui/columns.py +++ /dev/null @@ -1,153 +0,0 @@ -# -# columns.py -# -# Copyright (C) 2006 Zach Tibbitts ('zachtib') -# Copyright (C) 2007 Andrew Resch ('andar') -# -# 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 2 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 deluge.common - -# Cell data functions to pass to add_func_column() - -def cell_data_speed(column, cell, model, iter, data): - speed = int(model.get_value(iter, data)) - speed_str = deluge.common.fspeed(speed) - cell.set_property('text', speed_str) - -def cell_data_size(column, cell, model, iter, data): - size = long(model.get_value(iter, data)) - size_str = deluge.common.fsize(size) - cell.set_property('text', size_str) - -def cell_data_peer(column, cell, model, iter, data): - c1, c2 = data - a = int(model.get_value(iter, c1)) - b = int(model.get_value(iter, c2)) - cell.set_property('text', '%d (%d)'%(a, b)) - -def cell_data_time(column, cell, model, iter, data): - time = int(model.get_value(iter, data)) - if time < 0 or time == 0: - time_str = _("Infinity") - else: - time_str = deluge.common.ftime(time) - cell.set_property('text', time_str) - -def cell_data_ratio(column, cell, model, iter, data): - ratio = float(model.get_value(iter, data)) - if ratio == -1: - ratio_str = _("Unknown") - else: - ratio_str = "%.3f"%ratio - cell.set_property('text', ratio_str) - -## Functions to create columns - -def add_func_column(view, header, func, data, sortid=None): - column = gtk.TreeViewColumn(header) - render = gtk.CellRendererText() - column.pack_start(render, True) - column.set_cell_data_func(render, func, data) - if sortid is not None: - column.set_clickable(True) - column.set_sort_column_id(sortid) - else: - try: - if len(data) == 1: - column.set_clickable(True) - column.set_sort_column_id(data[0]) - except TypeError: - column.set_clickable(True) - column.set_sort_column_id(data) - column.set_resizable(True) - column.set_expand(False) - column.set_min_width(10) - column.set_reorderable(True) - view.append_column(column) - return column - - -def add_text_column(view, header, cid): - render = gtk.CellRendererText() - column = gtk.TreeViewColumn(header, render, text=cid) - column.set_clickable(True) - column.set_sort_column_id(cid) - column.set_resizable(True) - column.set_expand(False) - column.set_min_width(10) - column.set_reorderable(True) - view.append_column(column) - return column - -def add_progress_column(view, header, pid, mid): - render = gtk.CellRendererProgress() - column = gtk.TreeViewColumn(header, render, value=pid, text=mid) - column.set_clickable(True) - column.set_sort_column_id(pid) - column.set_resizable(True) - column.set_expand(False) - column.set_min_width(10) - column.set_reorderable(True) - view.append_column(column) - return column - -def add_toggle_column(view, header, cid, toggled_signal=None): - render = gtk.CellRendererToggle() - render.set_property('activatable', True) - column = gtk.TreeViewColumn(header, render, active=cid) - column.set_clickable(True) - column.set_resizable(True) - column.set_expand(False) - column.set_min_width(10) - column.set_reorderable(True) - view.append_column(column) - if toggled_signal is not None: - render.connect("toggled", toggled_signal) - return column - -def add_texticon_column(view, header, icon_col, text_col): - column = gtk.TreeViewColumn(header) - column.set_clickable(True) - column.set_resizable(True) - column.set_expand(False) - column.set_min_width(10) - column.set_reorderable(True) - render = gtk.CellRendererPixbuf() - column.pack_start(render, expand=False) - column.add_attribute(render, 'pixbuf', icon_col) - render = gtk.CellRendererText() - column.pack_start(render, expand=True) - column.add_attribute(render, 'text', text_col) - view.append_column(column) - return column diff --git a/deluge/ui/gtkui/listview.py b/deluge/ui/gtkui/listview.py index ca03fe61e..253d81bd3 100644 --- a/deluge/ui/gtkui/listview.py +++ b/deluge/ui/gtkui/listview.py @@ -38,6 +38,8 @@ pygtk.require('2.0') import gtk import gettext +import deluge.common + # Get the logger log = logging.getLogger("deluge") @@ -49,9 +51,9 @@ def cell_data_speed(column, cell, model, iter, data): cell.set_property('text', speed_str) def cell_data_size(column, cell, model, iter, data): - size = long(model.get_value(iter, data)) - size_str = deluge.common.fsize(size) - cell.set_property('text', size_str) + size = long(model.get_value(iter, data)) + size_str = deluge.common.fsize(size) + cell.set_property('text', size_str) def cell_data_peer(column, cell, model, iter, data): c1, c2 = data @@ -79,7 +81,6 @@ class ListView: class ListViewColumn: def __init__(self, name, column_indices): self.name = name - # self.column_types = column_types self.column_indices = column_indices def __init__(self, treeview_widget=None): @@ -101,6 +102,17 @@ class ListView: self.columns = {} self.liststore_columns = [] + def set_treeview(self, treeview_widget): + self.treeview = treeview_widget + return + + def get_column_index(self, name): + # Only return as list if needed + if len(self.columns[name].column_indices) > 1: + return self.columns[name].column_indices + else: + return self.columns[name].column_indices[0] + def create_new_liststore(self): # Create a new liststore with added column and move the data from the # old one to the new one. @@ -110,8 +122,6 @@ class ListView: # being the new liststore and the columns list def copy_row(model, path, row, user_data): new_list, columns = user_data - # Iterate over the columns except the last one. This one would have - # been just added and no need to copy it from the old list. for column in range(model.get_n_columns()): # Get the current value of the column for this row value = model.get_value(row, column) @@ -171,8 +181,12 @@ class ListView: column = gtk.TreeViewColumn(header) render = gtk.CellRendererText() column.pack_start(render, True) - column.set_cell_data_func(render, function, + if len(self.columns[header].column_indices) > 1: + 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]) column.set_clickable(True) column.set_sort_column_id(column_indices[sortid]) column.set_resizable(True) diff --git a/deluge/ui/gtkui/torrentview.py b/deluge/ui/gtkui/torrentview.py index a44b6645c..eb58085a2 100644 --- a/deluge/ui/gtkui/torrentview.py +++ b/deluge/ui/gtkui/torrentview.py @@ -45,61 +45,147 @@ import listview # Get the logger log = logging.getLogger("deluge") -class TorrentView: +class TorrentView(listview.ListView): def __init__(self, window): + # Call the ListView constructor + listview.ListView.__init__(self) log.debug("TorrentView Init..") self.window = window self.core = functions.get_core() - # Create a ListView object using the torrent_view from the mainwindow - self.torrent_view = listview.ListView( - self.window.main_glade.get_widget("torrent_view")) + # Set the treeview used in listview with the one from our glade file + self.set_treeview(self.window.main_glade.get_widget("torrent_view")) - self.torrent_view.add_text_column("torrent_id", visible=False) - self.torrent_view.add_texticon_column("Name") - self.torrent_view.add_func_column("Size", + self.add_text_column("torrent_id", visible=False) + self.add_texticon_column("Name") + self.add_func_column("Size", listview.cell_data_size, [long]) - self.torrent_view.add_progress_column("Progress") - self.torrent_view.add_func_column("Seeders", + self.add_progress_column("Progress") + self.add_func_column("Seeders", listview.cell_data_peer, [int, int]) - self.torrent_view.add_func_column("Peers", + self.add_func_column("Peers", listview.cell_data_peer, [int, int]) - self.torrent_view.add_func_column("Down Speed", + self.add_func_column("Down Speed", listview.cell_data_speed, - [int]) - self.torrent_view.add_func_column("Up Speed", + [float]) + self.add_func_column("Up Speed", listview.cell_data_speed, - [int]) - self.torrent_view.add_func_column("ETA", + [float]) + self.add_func_column("ETA", listview.cell_data_time, [int]) - self.torrent_view.add_func_column("Ratio", + self.add_func_column("Ratio", listview.cell_data_ratio, [float]) - + ### Connect Signals ### # Connect to the 'button-press-event' to know when to bring up the # torrent menu popup. - self.torrent_view.treeview.connect("button-press-event", + self.treeview.connect("button-press-event", self.on_button_press_event) # Connect to the 'changed' event of TreeViewSelection to get selection # changes. - self.torrent_view.treeview.get_selection().connect("changed", + self.treeview.get_selection().connect("changed", self.on_selection_changed) def update(self): - pass + """Update the view, this is likely called by a timer""" + # This function is used for the foreach method of the treemodel + def update_row(model, path, row, user_data): + torrent_id = self.liststore.get_value(row, 0) + status_keys = ["progress", "state", "num_seeds", + "num_peers", "download_payload_rate", "upload_payload_rate", + "eta"] + status = functions.get_torrent_status(self.core, torrent_id, + status_keys) + + # Set values for each column in the row + + self.liststore.set_value(row, + self.get_column_index("Progress")[0], + status["progress"]*100) + self.liststore.set_value(row, + self.get_column_index("Progress")[1], + status["state"]) + self.liststore.set_value(row, + self.get_column_index("Seeders")[0], + status["num_seeds"]) + self.liststore.set_value(row, + self.get_column_index("Seeders")[1], + status["num_seeds"]) + self.liststore.set_value(row, + self.get_column_index("Peers")[0], + status["num_peers"]) + self.liststore.set_value(row, + self.get_column_index("Peers")[1], + status["num_peers"]) + self.liststore.set_value(row, + self.get_column_index("Down Speed"), + status["download_payload_rate"]) + self.liststore.set_value(row, + self.get_column_index("Up Speed"), + status["upload_payload_rate"]) + self.liststore.set_value(row, + self.get_column_index("ETA"), + status["eta"]) + + # Iterates through every row and updates them accordingly + if self.liststore is not None: + self.liststore.foreach(update_row, None) def add_row(self, torrent_id): - pass - + """Adds a new torrent row to the treeview""" + # Get the status and info dictionaries + status_keys = ["name", "total_size", "progress", "state", + "num_seeds", "num_peers", "download_payload_rate", + "upload_payload_rate", "eta"] + status = functions.get_torrent_status(self.core, torrent_id, + status_keys) + # Insert the row with info provided from core + self.liststore.append([ + torrent_id, + None, + status["name"], + status["total_size"], + status["progress"]*100, + status["state"], + status["num_seeds"], + status["num_seeds"], + status["num_peers"], + status["num_peers"], + status["download_payload_rate"], + status["upload_payload_rate"], + status["eta"], + 0.0 + ]) + def remove_row(self, torrent_id): - pass + """Removes a row with torrent_id""" + row = self.liststore.get_iter_first() + while row is not None: + # Check if this row is the row we want to remove + if self.liststore.get_value(row, 0) == torrent_id: + self.liststore.remove(row) + # Force an update of the torrentview + self.update() + break + row = self.liststore.iter_next(row) def get_selected_torrents(self): - pass + """Returns a list of selected torrents or None""" + torrent_ids = [] + paths = self.treeview.get_selection().get_selected_rows()[1] + + try: + for path in paths: + torrent_ids.append( + self.liststore.get_value( + self.liststore.get_iter(path), 0)) + return torrent_ids + except ValueError: + return None ### Callbacks ### def on_button_press_event(self, widget, event):