diff --git a/deluge/common.py b/deluge/common.py index ddd619a85..1ccb241dd 100644 --- a/deluge/common.py +++ b/deluge/common.py @@ -66,23 +66,6 @@ def get_default_plugin_dir(): ## Formatting text functions -def estimate_eta(total_size, total_done, download_rate): - """Returns a string with the estimated ETA and will return 'Unlimited' - if the torrent is complete - """ - try: - return ftime(get_eta(total_size, total_done, download_rate)) - except ZeroDivisionError: - return "Infinity" - -def get_eta(size, done, speed): - """Returns the ETA in seconds - Will raise an exception if the torrent is completed - """ - if (size - done) == 0: - raise ZeroDivisionError - return (size - done) / speed - def fsize(fsize_b): """Returns formatted string describing filesize fsize_b should be in bytes @@ -105,16 +88,14 @@ def fspeed(bps): """Returns a formatted string representing transfer speed""" return '%s/s' % (fsize(bps)) -def fseed(num_seeds, total_seeds): - """Returns a formatted string num_seeds (total_seeds)""" - return str(str(num_seeds) + " (" + str(total_seeds) + ")") - def fpeer(num_peers, total_peers): """Returns a formatted string num_peers (total_peers)""" return str(str(num_peers) + " (" + str(total_peers) + ")") def ftime(seconds): """Returns a formatted time string""" + if seconds is 0: + return "Infinity" if seconds < 60: return '%ds' % (seconds) minutes = int(seconds/60) diff --git a/deluge/core/torrent.py b/deluge/core/torrent.py index df90a9448..aa7fc497c 100644 --- a/deluge/core/torrent.py +++ b/deluge/core/torrent.py @@ -43,6 +43,8 @@ class Torrent: self.handle = handle # Set the torrent_id for this torrent self.torrent_id = str(handle.info_hash()) + # This is for saving the total uploaded between sessions + self.total_uploaded = 0 def get_state(self): """Returns the state of this torrent for saving to the session state""" @@ -62,7 +64,23 @@ class Torrent: eta = 0 return eta - + + def get_ratio(self): + """Returns the ratio for this torrent""" + up = self.total_uploaded + self.handle.status().total_payload_upload + down = self.handle.status().total_done + + # 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 + def get_status(self, keys): """Returns the status of the torrent based on the keys provided""" # Create the full dictionary @@ -70,11 +88,27 @@ class Torrent: # Adjust progress to be 0-100 value progress = status.progress*100 - + + # Get the total number of seeds and peers + if status.num_complete is -1: + total_seeds = status.num_seeds + else: + total_seeds = status.num_complete + + if status.num_incomplete is -1: + total_peers = status.num_peers - status.num_seeds + else: + total_peers = status.num_incomplete + full_status = { "name": self.handle.torrent_info().name(), "total_size": self.handle.torrent_info().total_size(), - "num_pieces": self.handle.status().num_pieces, + "num_files": self.handle.torrent_info().num_files(), + "num_pieces": self.handle.torrent_info().num_pieces(), + "piece_length": self.handle.torrent_info().piece_length(), + "distributed_copies": status.distributed_copies, + "total_done": status.total_done, + "total_uploaded": self.total_uploaded + status.total_payload_upload, "state": int(status.state), "paused": status.paused, "progress": progress, @@ -83,11 +117,14 @@ class Torrent: "total_payload_upload": status.total_payload_upload, "download_payload_rate": status.download_payload_rate, "upload_payload_rate": status.upload_payload_rate, - "num_peers": status.num_peers, + "num_peers": status.num_peers - status.num_seeds, "num_seeds": status.num_seeds, + "total_peers": total_peers, + "total_seeds": total_seeds, "total_wanted": status.total_wanted, "eta": self.get_eta(), - "ratio": 0.0 + "ratio": self.get_ratio(), + "tracker": status.current_tracker } # Create the desired status dictionary and return it diff --git a/deluge/ui/gtkui/mainwindow.py b/deluge/ui/gtkui/mainwindow.py index c544469d5..19024a1f0 100644 --- a/deluge/ui/gtkui/mainwindow.py +++ b/deluge/ui/gtkui/mainwindow.py @@ -40,6 +40,7 @@ import pkg_resources from menubar import MenuBar from toolbar import ToolBar from torrentview import TorrentView +from torrentdetails import TorrentDetails from deluge.log import LOG as log @@ -56,11 +57,13 @@ class MainWindow: self.menubar = MenuBar(self) self.toolbar = ToolBar(self) self.torrentview = TorrentView(self) + self.torrentdetails = TorrentDetails(self) gobject.timeout_add(1000, self.update) def update(self): self.torrentview.update() + self.torrentdetails.update() return True def show(self): diff --git a/deluge/ui/gtkui/torrentdetails.py b/deluge/ui/gtkui/torrentdetails.py new file mode 100644 index 000000000..5c31edab5 --- /dev/null +++ b/deluge/ui/gtkui/torrentdetails.py @@ -0,0 +1,130 @@ +# +# torrentdetails.py +# +# 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. + +"""The torrent details component shows info about the selected torrent.""" + +import pygtk +pygtk.require('2.0') +import gtk, gtk.glade +import gettext + +import deluge.ui.functions as functions +import deluge.common +from deluge.log import LOG as log + +class TorrentDetails: + def __init__(self, window): + self.window = window + glade = self.window.main_glade + + self.core = functions.get_core() + + self.notebook = glade.get_widget("torrent_info") + self.details_tab = glade.get_widget("torrentdetails_tab") + + # Get the labels we need to update. + self.progress_bar = glade.get_widget("progressbar") + self.name = glade.get_widget("summary_name") + self.total_size = glade.get_widget("summary_total_size") + self.num_files = glade.get_widget("summary_num_files") + self.pieces = glade.get_widget("summary_pieces") + self.availability = glade.get_widget("summary_availability") + self.total_downloaded = glade.get_widget("summary_total_downloaded") + self.total_uploaded = glade.get_widget("summary_total_uploaded") + self.download_speed = glade.get_widget("summary_download_speed") + self.upload_speed = glade.get_widget("summary_upload_speed") + self.seeders = glade.get_widget("summary_seeders") + self.peers = glade.get_widget("summary_peers") + self.percentage_done = glade.get_widget("summary_percentage_done") + self.share_ratio = glade.get_widget("summary_share_ratio") + self.tracker = glade.get_widget("summary_tracker") + self.tracker_status = glade.get_widget("summary_tracker_status") + self.next_announce = glade.get_widget("summary_next_announce") + self.eta = glade.get_widget("summary_eta") + + def update(self): + # Only update if this page is showing + if self.notebook.page_num(self.details_tab) is \ + self.notebook.get_current_page(): + # Get the first selected torrent + selected = self.window.torrentview.get_selected_torrents() + + # Only use the first torrent in the list or return if None selected + if selected is not None: + selected = selected[0] + else: + # No torrent is selected in the torrentview + return + + # Get the torrent status + status_keys = ["progress", "name", "total_size", "num_files", + "num_pieces", "piece_length", "distributed_copies", + "total_done", "total_payload_download", "total_uploaded", + "total_payload_upload", "download_payload_rate", + "upload_payload_rate", "num_peers", "num_seeds", "total_peers", + "total_seeds", "eta", "ratio", "tracker", "next_announce"] + status = functions.get_torrent_status(self.core, + selected, + status_keys) + + # We need to adjust the value core gives us for progress + progress = status["progress"]/100 + self.progress_bar.set_fraction(progress) + self.progress_bar.set_text(deluge.common.fpcnt(progress)) + + self.name.set_text(status["name"]) + self.total_size.set_text(deluge.common.fsize(status["total_size"])) + self.num_files.set_text(str(status["num_files"])) + self.pieces.set_text("%s (%s)" % (status["num_pieces"], + deluge.common.fsize(status["piece_length"]))) + self.availability.set_text("%.3f" % status["distributed_copies"]) + self.total_downloaded.set_text("%s (%s)" % \ + (deluge.common.fsize(status["total_done"]), + deluge.common.fsize(status["total_payload_download"]))) + self.total_uploaded.set_text("%s (%s)" % \ + (deluge.common.fsize(status["total_uploaded"]), + deluge.common.fsize(status["total_payload_upload"]))) + self.download_speed.set_text( + deluge.common.fspeed(status["download_payload_rate"])) + self.upload_speed.set_text( + deluge.common.fspeed(status["upload_payload_rate"])) + self.seeders.set_text(deluge.common.fpeer(status["num_seeds"], + status["total_seeds"])) + self.peers.set_text(deluge.common.fpeer(status["num_peers"], + status["total_peers"])) + self.eta.set_text(deluge.common.ftime(status["eta"])) + self.share_ratio.set_text("%.3f" % status["ratio"]) + self.tracker.set_text(status["tracker"]) + self.next_announce.set_text( + deluge.common.ftime(status["next_announce"])) + diff --git a/deluge/ui/gtkui/torrentview.py b/deluge/ui/gtkui/torrentview.py index 175e3cccd..ffb6ae7fa 100644 --- a/deluge/ui/gtkui/torrentview.py +++ b/deluge/ui/gtkui/torrentview.py @@ -63,11 +63,13 @@ class TorrentView(listview.ListView): self.add_func_column("Seeders", listview.cell_data_peer, [int, int], - status_field=["num_seeds", "num_seeds"]) + status_field=["num_seeds", + "total_seeds"]) self.add_func_column("Peers", listview.cell_data_peer, [int, int], - status_field=["num_peers", "num_peers"]) + status_field=["num_peers", + "total_peers"]) self.add_func_column("Down Speed", listview.cell_data_speed, [float], @@ -201,6 +203,11 @@ class TorrentView(listview.ListView): torrent_ids.append( self.liststore.get_value( self.liststore.get_iter(path), 0)) + + if len(torrent_ids) is 0: + # Only return a list if there is something in it. + return None + return torrent_ids except ValueError: return None