From c4e688b450438961c6d4f13fda493f83f94a7dfe Mon Sep 17 00:00:00 2001 From: Andrew Resch Date: Mon, 23 Jul 2007 20:43:42 +0000 Subject: [PATCH] Added TorrentManager class for handling torrents. Added get_torrent_state() in the core, but this will be changed. --- deluge/core/core.py | 56 +++++++++++++++---------------- deluge/core/torrent.py | 51 +++++++++++++++++++++++++--- deluge/core/torrentmanager.py | 61 ++++++++++++++++++++++++++++++++++ deluge/ui/gtkui/gtkui.py | 2 +- deluge/ui/gtkui/signals.py | 15 ++++++--- deluge/ui/gtkui/torrentview.py | 29 +++++++++++++--- 6 files changed, 170 insertions(+), 44 deletions(-) create mode 100644 deluge/core/torrentmanager.py diff --git a/deluge/core/core.py b/deluge/core/core.py index 86033b3db..b8e51a3fe 100644 --- a/deluge/core/core.py +++ b/deluge/core/core.py @@ -52,8 +52,7 @@ import deluge.libtorrent as lt from deluge.config import Config import deluge.common -from deluge.core.torrent import Torrent -from deluge.core.torrentqueue import TorrentQueue +from deluge.core.torrentmanager import TorrentManager # Get the logger log = logging.getLogger("deluge") @@ -69,11 +68,9 @@ class Core(dbus.service.Object): def __init__(self, path="/org/deluge_torrent/Core"): log.debug("Core init..") - # A dictionary containing hash keys to Torrent objects - self.torrents = {} - # Instantiate the TorrentQueue - self.queue = TorrentQueue() - + # Start the TorrentManager + self.torrents = TorrentManager() + # Setup DBUS bus_name = dbus.service.BusName("org.deluge_torrent.Deluge", bus=dbus.SessionBus()) @@ -95,6 +92,12 @@ class Core(dbus.service.Object): self.loop.run() # Exported Methods + @dbus.service.method("org.deluge_torrent.Deluge") + def shutdown(self): + """Shutdown the core""" + log.info("Shutting down core..") + self.loop.quit() + @dbus.service.method(dbus_interface="org.deluge_torrent.Deluge", in_signature="say", out_signature="") def add_torrent_file(self, filename, filedump): @@ -108,6 +111,7 @@ class Core(dbus.service.Object): # Bdecode the filedata sent from the UI torrent_filedump = lt.bdecode(filedump) + handle = None try: handle = self.session.add_torrent(lt.torrent_info(torrent_filedump), self.config["download_location"], @@ -132,24 +136,24 @@ class Core(dbus.service.Object): except IOError: log.warning("Unable to save torrent file: %s", filename) - # Create a Torrent object - torrent = Torrent(handle) - - # Store the Torrent object in the dictionary - self.torrents[str(handle.info_hash())] = torrent + # Add the torrent to the torrentmanager + torrent_id = self.torrents.add(handle) - # Add the torrent id to the queue - self.queue.append(str(handle.info_hash())) - # Emit the torrent_added signal - self.torrent_added(str(handle.info_hash())) + self.torrent_added(torrent_id) - - @dbus.service.method("org.deluge_torrent.Deluge") - def shutdown(self): - log.info("Shutting down core..") - self.loop.quit() - + @dbus.service.method(dbus_interface="org.deluge_torrent.Deluge", + in_signature="s", out_signature="(six)") + def get_torrent_info(self, torrent_id): + # Get the info tuple from the torrent and return it + return self.torrents[torrent_id].get_info() + + @dbus.service.method(dbus_interface="org.deluge_torrent.Deluge", + in_signature="s", + out_signature="(ibdixxddiixii)") + def get_torrent_status(self, torrent_id): + # Get the status tuple from the torrent and return it + return self.torrents[torrent_id].get_status() ## Queueing functions ###### @dbus.service.method(dbus_interface="org.deluge_torrent.Deluge", @@ -159,7 +163,7 @@ class Core(dbus.service.Object): if self.queue.top(torrent_id): self.torrent_queue_top() # Store the new torrent position in the torrent object - self.torrents[torrent_id].set_position(self.queue[torrent_id]) +# self.torrents[torrent_id].set_position(self.queue[torrent_id]) @dbus.service.method(dbus_interface="org.deluge_torrent.Deluge", in_signature="s", out_signature="") @@ -167,8 +171,6 @@ class Core(dbus.service.Object): # If the queue method returns True, then we should emit a signal if self.queue.up(torrent_id): self.torrent_queue_up() - # Store the new torrent position in the torrent object - self.torrents[torrent_id].set_position(self.queue[torrent_id]) @dbus.service.method(dbus_interface="org.deluge_torrent.Deluge", in_signature="s", out_signature="") @@ -176,8 +178,6 @@ class Core(dbus.service.Object): # If the queue method returns True, then we should emit a signal if self.queue.down(torrent_id): self.torrent_queue_down() - # Store the new torrent position in the torrent object - self.torrents[torrent_id].set_position(self.queue[torrent_id]) @dbus.service.method(dbus_interface="org.deluge_torrent.Deluge", in_signature="s", out_signature="") @@ -185,8 +185,6 @@ class Core(dbus.service.Object): # If the queue method returns True, then we should emit a signal if self.queue.bottom(torrent_id): self.torrent_queue_bottom() - # Store the new torrent position in the torrent object - self.torrents[torrent_id].set_position(self.queue[torrent_id]) # Signals @dbus.service.signal(dbus_interface="org.deluge_torrent.Deluge", diff --git a/deluge/core/torrent.py b/deluge/core/torrent.py index 55ebfe9e7..8b59dac59 100644 --- a/deluge/core/torrent.py +++ b/deluge/core/torrent.py @@ -34,11 +34,52 @@ import deluge.libtorrent as lt class Torrent: - def __init__(self, handle): + def __init__(self, handle, queue): # Set the libtorrent handle self.handle = handle + # Set the queue this torrent belongs too + self.queue = queue + # Set the torrent_id for this torrent + self.torrent_id = str(handle.info_hash()) + + def get_eta(self): + """Returns the ETA in seconds for this torrent""" + left = self.handle.status().total_wanted \ + - self.handle.status().total_done - def set_position(self, position): - """Store the torrents queue position""" - self.position = position - + # The torrent file is done + if left == 0: + return 0 + + # Calculate the ETA in seconds and return it + return (left / self.handle.status().download_payload_rate) + + def get_info(self): + """Returns the torrents info.. stuff that remains constant, such as + name.""" + + return ( + self.handle.torrent_info().name(), + self.handle.torrent_info().total_size(), + self.handle.status().num_pieces + ) + + def get_status(self): + """Returns the torrent status""" + status = self.handle.status() + + return ( + status.state, + status.paused, + status.progress, + status.next_announce.seconds, + status.total_payload_download, + status.total_payload_upload, + status.download_payload_rate, + status.upload_payload_rate, + status.num_peers, + status.num_seeds, + status.total_wanted, + self.get_eta(), + self.queue[self.torrent_id] + ) diff --git a/deluge/core/torrentmanager.py b/deluge/core/torrentmanager.py new file mode 100644 index 000000000..bb71fec54 --- /dev/null +++ b/deluge/core/torrentmanager.py @@ -0,0 +1,61 @@ +# +# torrentmanager.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. + +import logging + +from deluge.core.torrent import Torrent +from deluge.core.torrentqueue import TorrentQueue + +# Get the logger +log = logging.getLogger("deluge") + +class TorrentManager: + def __init__(self): + log.debug("TorrentManager init..") + # Create the torrents dict { torrent_id: Torrent } + self.torrents = {} + self.queue = TorrentQueue() + + def __getitem__(self, torrent_id): + """Return the Torrent with torrent_id""" + return self.torrents[torrent_id] + + def add(self, handle): + """Add a torrent to the manager and returns it's torrent_id""" + # Create a Torrent object + torrent = Torrent(handle, self.queue) + # Add the torrent object to the dictionary + self.torrents[torrent.torrent_id] = torrent + # Add the torrent to the queue + self.queue.append(torrent.torrent_id) + return torrent.torrent_id diff --git a/deluge/ui/gtkui/gtkui.py b/deluge/ui/gtkui/gtkui.py index dfd64fcff..ee1f34e4e 100644 --- a/deluge/ui/gtkui/gtkui.py +++ b/deluge/ui/gtkui/gtkui.py @@ -62,7 +62,7 @@ class GtkUI: self.main_window = MainWindow() # Start the signal receiver - self.signal_receiver = Signals() + self.signal_receiver = Signals(self) # Show the main window self.main_window.show() diff --git a/deluge/ui/gtkui/signals.py b/deluge/ui/gtkui/signals.py index 90ba2a654..00827cdcc 100644 --- a/deluge/ui/gtkui/signals.py +++ b/deluge/ui/gtkui/signals.py @@ -57,10 +57,15 @@ from deluge.config import Config log = logging.getLogger("deluge") class Signals: - def __init__(self): - core = functions.get_core() - core.connect_to_signal("torrent_added", self.torrent_added_signal) + def __init__(self, ui): + self.ui = ui + self.core = functions.get_core() + self.core.connect_to_signal("torrent_added", self.torrent_added_signal) - def torrent_added_signal(self, torrentid): + def torrent_added_signal(self, torrent_id): log.debug("torrent_added signal received..") - log.debug("torrent id: %s", torrentid) + log.debug("torrent id: %s", torrent_id) + # Add the torrent to the treeview + self.ui.main_window.torrentview.add_torrent(torrent_id, + self.core.get_torrent_info(torrent_id), + self.core.get_torrent_status(torrent_id)) diff --git a/deluge/ui/gtkui/torrentview.py b/deluge/ui/gtkui/torrentview.py index cab25c937..5f2341a4c 100644 --- a/deluge/ui/gtkui/torrentview.py +++ b/deluge/ui/gtkui/torrentview.py @@ -54,9 +54,8 @@ class TorrentView: ## TreeModel setup ## # UID, Q#, Status Icon, Name, Size, Progress, Message, Seeders, Peers, # DL, UL, ETA, Share - self.torrent_model = gtk.ListStore(int, gobject.TYPE_UINT, - gtk.gdk.Pixbuf, str, gobject.TYPE_UINT64, float, str, int, int, - int, int, int, int, gobject.TYPE_UINT, float) + self.torrent_model = gtk.ListStore(str, int, gtk.gdk.Pixbuf, str, + long, float, str, int, int, int, int, int, int, int, float) ## TreeView setup ## self.torrent_view.set_model(self.torrent_model) @@ -150,8 +149,30 @@ class TorrentView: self.torrent_view.get_selection().connect("changed", self.on_selection_changed) + def add_torrent(self, torrent_id, info, status): + """Adds a new torrent row to the treeview""" + # UID, Q#, Status Icon, Name, Size, Progress, Message, Seeders, Peers, + # DL, UL, ETA, Share + self.torrent_model.insert(status[12], [ + torrent_id, + status[12]+1, + None, ## Status Icon + info[0], + info[2], + status[2], + status[0], + status[9], + status[9], + status[8], + status[8], + status[6], + status[7], + status[11], + 0.0 + ]) + ### Callbacks ### - def on_button_press_event(self, widget, event): + def on_button_press_event(self, widget, event, data): log.debug("on_button_press_event") def on_selection_changed(self, treeselection, data):