Can now remove torrents.

Torrent view is now updating in timer.
This commit is contained in:
Andrew Resch 2007-07-24 01:53:35 +00:00
parent c4e688b450
commit ca5297e20d
11 changed files with 238 additions and 52 deletions

View file

@ -143,7 +143,21 @@ class Core(dbus.service.Object):
self.torrent_added(torrent_id)
@dbus.service.method(dbus_interface="org.deluge_torrent.Deluge",
in_signature="s", out_signature="(six)")
in_signature="s", out_signature="")
def remove_torrent(self, torrent_id):
log.debug("Removing torrent %s from the core.", torrent_id)
try:
# Remove from libtorrent session
self.session.remove_torrent(self.torrents[torrent_id].handle)
# Remove from TorrentManager
self.torrents.remove(torrent_id)
# Emit the torrent_removed signal
self.torrent_removed(torrent_id)
except RuntimeError, KeyError:
log.warning("Error removing torrent")
@dbus.service.method(dbus_interface="org.deluge_torrent.Deluge",
in_signature="s", out_signature="(sxi)")
def get_torrent_info(self, torrent_id):
# Get the info tuple from the torrent and return it
return self.torrents[torrent_id].get_info()
@ -154,6 +168,20 @@ class Core(dbus.service.Object):
def get_torrent_status(self, torrent_id):
# Get the status tuple from the torrent and return it
return self.torrents[torrent_id].get_status()
@dbus.service.method(dbus_interface="org.deluge_torrent.Deluge",
in_signature="",
out_signature="as")
def get_torrent_status_template(self):
# A list of strings the correspond to the status tuple
return self.torrents.get_status_template()
@dbus.service.method(dbus_interface="org.deluge_torrent.Deluge",
in_signature="",
out_signature="as")
def get_torrent_info_template(self):
# A list of strings the correspond to the info tuple
return self.torrents.get_info_template()
## Queueing functions ######
@dbus.service.method(dbus_interface="org.deluge_torrent.Deluge",
@ -162,8 +190,6 @@ class Core(dbus.service.Object):
# If the queue method returns True, then we should emit a signal
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])
@dbus.service.method(dbus_interface="org.deluge_torrent.Deluge",
in_signature="s", out_signature="")
@ -199,6 +225,12 @@ class Core(dbus.service.Object):
"""Emitted when a new torrent fails addition to the session"""
log.debug("torrent_add_failed signal emitted")
@dbus.service.signal(dbus_interface="org.deluge_torrent.Deluge",
signature="s")
def torrent_removed(self, torrent_id):
"""Emitted when a torrent has been removed from the core"""
log.debug("torrent_remove signal emitted")
@dbus.service.signal(dbus_interface="org.deluge_torrent.Deluge",
signature="s")
def torrent_queue_top(self, torrent_id):

View file

@ -31,8 +31,13 @@
# 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
import deluge.libtorrent as lt
# Get the logger
log = logging.getLogger("deluge")
class Torrent:
def __init__(self, handle, queue):
# Set the libtorrent handle
@ -42,17 +47,20 @@ class Torrent:
# Set the torrent_id for this torrent
self.torrent_id = str(handle.info_hash())
def __del__(self):
self.queue.remove(self.torrent_id)
def get_eta(self):
"""Returns the ETA in seconds for this torrent"""
left = self.handle.status().total_wanted \
- self.handle.status().total_done
# 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)
try:
eta = left / self.handle.status().download_payload_rate
except ZeroDivisionError:
eta = 0
return eta
def get_info(self):
"""Returns the torrents info.. stuff that remains constant, such as
@ -83,3 +91,4 @@ class Torrent:
self.get_eta(),
self.queue[self.torrent_id]
)

View file

@ -59,3 +59,37 @@ class TorrentManager:
# Add the torrent to the queue
self.queue.append(torrent.torrent_id)
return torrent.torrent_id
def remove(self, torrent_id):
"""Remove a torrent from the manager"""
try:
del self.torrents[torrent_id]
except KeyError, ValueError:
return False
return True
def get_info_template(self):
"""Returns a list of strings that correspond to the info tuple"""
return [
"name",
"total_size",
"num_pieces"
]
def get_status_template(self):
"""Returns a list of strings that correspond to the status tuple"""
return [
"state",
"paused",
"progress",
"next_announce",
"total_payload_download",
"total_payload_upload",
"download_payload_rate",
"upload_payload_rate",
"num_peers",
"num_seeds",
"total_wanted",
"eta",
"position"
]

View file

@ -54,7 +54,11 @@ class TorrentQueue:
"""Prepend torrent_id to the top of the queue"""
log.debug("Prepend torrent %s to queue..", torrent_id)
self.queue.insert(0, torrent_id)
def remove(self, torrent_id):
"""Removes torrent_id from the list"""
self.queue.remove(torrent_id)
def up(self, torrent_id):
"""Move torrent_id up one in the queue"""
if torrent_id not in self.queue:

View file

@ -62,7 +62,7 @@ def cell_data_time(column, cell, model, iter, data):
time_str = _("Infinity")
else:
time_str = deluge.common.ftime(time)
cell.set_property('text', time_str)
cell.set_property('text', time_str)
def cell_data_ratio(column, cell, model, iter, data):
ratio = float(model.get_value(iter, data))

View file

@ -85,3 +85,28 @@ def add_torrent_file():
(path, filename) = os.path.split(torrent_file)
core.add_torrent_file(filename, f.read())
f.close()
def remove_torrent(torrent_ids):
"""Removes torrent_ids from the core.. Expects a list of torrent_ids"""
log.debug("Attempting to removing torrents: %s", torrent_ids)
core = get_core()
for torrent_id in torrent_ids:
core.remove_torrent(torrent_id)
def get_torrent_status_dict(core, torrent_id):
"""Builds and returns a status dictionary using the status template"""
status = core.get_torrent_status(torrent_id)
template = core.get_torrent_status_template()
status_dict = {}
for string in template:
status_dict[string] = status[template.index(string)]
return status_dict
def get_torrent_info_dict(core, torrent_id):
"""Builds and returns an info dictionary using the info template"""
info = core.get_torrent_info(torrent_id)
template = core.get_torrent_info_template()
info_dict = {}
for string in template:
info_dict[string] = info[template.index(string)]
return info_dict

View file

@ -58,7 +58,7 @@
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="label" translatable="yes">_Remove Torrent</property>
<property name="use_underline">True</property>
<signal name="activate" handler="remove_torrent"/>
<signal name="activate" handler="on_menuitem_remove_activate"/>
<child internal-child="image">
<widget class="GtkImage" id="menu-item-image9">
<property name="visible">True</property>

View file

@ -36,6 +36,7 @@ import logging
import pygtk
pygtk.require('2.0')
import gtk, gtk.glade
import gobject
import pkg_resources
from menubar import MenuBar
@ -58,7 +59,13 @@ class MainWindow:
self.menubar = MenuBar(self)
self.toolbar = ToolBar(self)
self.torrentview = TorrentView(self)
gobject.timeout_add(1000, self.update)
def update(self):
self.torrentview.update()
return True
def show(self):
self.window.show_all()

View file

@ -125,6 +125,8 @@ class MenuBar:
log.debug("on_menuitem_edittrackers_activate")
def on_menuitem_remove_activate(self, data=None):
log.debug("on_menuitem_remove_activate")
functions.remove_torrent(
self.window.torrentview.get_selected_torrents())
def on_menuitem_queuetop_activate(self, data=None):
log.debug("on_menuitem_queuetop_activate")
def on_menuitem_queueup_activate(self, data=None):

View file

@ -61,11 +61,17 @@ class Signals:
self.ui = ui
self.core = functions.get_core()
self.core.connect_to_signal("torrent_added", self.torrent_added_signal)
self.core.connect_to_signal("torrent_removed",
self.torrent_removed_signal)
def torrent_added_signal(self, torrent_id):
log.debug("torrent_added signal received..")
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))
self.ui.main_window.torrentview.add_row(torrent_id)
def torrent_removed_signal(self, torrent_id):
log.debug("torrent_remove signal received..")
log.debug("torrent id: %s", torrent_id)
# Remove the torrent from the treeview
self.ui.main_window.torrentview.remove_row(torrent_id)

View file

@ -40,14 +40,33 @@ import gobject
import gettext
import columns
import functions
# Get the logger
log = logging.getLogger("deluge")
# Initializes the columns for the torrent_view
(TORRENT_VIEW_COL_UID,
TORRENT_VIEW_COL_QUEUE,
TORRENT_VIEW_COL_STATUSICON,
TORRENT_VIEW_COL_NAME,
TORRENT_VIEW_COL_SIZE,
TORRENT_VIEW_COL_PROGRESS,
TORRENT_VIEW_COL_STATUS,
TORRENT_VIEW_COL_CONNECTED_SEEDS,
TORRENT_VIEW_COL_SEEDS,
TORRENT_VIEW_COL_CONNECTED_PEERS,
TORRENT_VIEW_COL_PEERS,
TORRENT_VIEW_COL_DOWNLOAD,
TORRENT_VIEW_COL_UPLOAD,
TORRENT_VIEW_COL_ETA,
TORRENT_VIEW_COL_RATIO) = range(15)
class TorrentView:
def __init__(self, window):
log.debug("TorrentView Init..")
self.window = window
self.core = functions.get_core()
# Get the torrent_view widget
self.torrent_view = self.window.main_glade.get_widget("torrent_view")
@ -63,23 +82,6 @@ class TorrentView:
self.torrent_view.set_reorderable(True)
self.torrent_view.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
# Initializes the columns for the torrent_view
(TORRENT_VIEW_COL_UID,
TORRENT_VIEW_COL_QUEUE,
TORRENT_VIEW_COL_STATUSICON,
TORRENT_VIEW_COL_NAME,
TORRENT_VIEW_COL_SIZE,
TORRENT_VIEW_COL_PROGRESS,
TORRENT_VIEW_COL_STATUS,
TORRENT_VIEW_COL_CONNECTED_SEEDS,
TORRENT_VIEW_COL_SEEDS,
TORRENT_VIEW_COL_CONNECTED_PEERS,
TORRENT_VIEW_COL_PEERS,
TORRENT_VIEW_COL_DOWNLOAD,
TORRENT_VIEW_COL_UPLOAD,
TORRENT_VIEW_COL_ETA,
TORRENT_VIEW_COL_RATIO) = range(15)
self.queue_column = columns.add_text_column(
self.torrent_view, "#",
TORRENT_VIEW_COL_QUEUE)
@ -149,32 +151,97 @@ class TorrentView:
self.torrent_view.get_selection().connect("changed",
self.on_selection_changed)
def add_torrent(self, torrent_id, info, status):
def update(self):
"""Update the view, this is likely called by a timer"""
# Iterate through the torrent_model and update rows
row = self.torrent_model.get_iter_first()
while row is not None:
torrent_id = self.torrent_model.get_value(row, 0)
status = functions.get_torrent_status_dict(self.core, torrent_id)
# Set values for each column in the row
self.torrent_model.set_value(row, TORRENT_VIEW_COL_QUEUE,
status["position"]+1)
self.torrent_model.set_value(row, TORRENT_VIEW_COL_PROGRESS,
status["progress"]*100)
self.torrent_model.set_value(row, TORRENT_VIEW_COL_STATUS,
status["state"])
self.torrent_model.set_value(row, TORRENT_VIEW_COL_CONNECTED_SEEDS,
status["num_seeds"])
self.torrent_model.set_value(row, TORRENT_VIEW_COL_SEEDS,
status["num_seeds"])
self.torrent_model.set_value(row, TORRENT_VIEW_COL_CONNECTED_PEERS,
status["num_peers"])
self.torrent_model.set_value(row, TORRENT_VIEW_COL_PEERS,
status["num_peers"])
self.torrent_model.set_value(row, TORRENT_VIEW_COL_DOWNLOAD,
status["download_payload_rate"])
self.torrent_model.set_value(row, TORRENT_VIEW_COL_UPLOAD,
status["upload_payload_rate"])
self.torrent_model.set_value(row, TORRENT_VIEW_COL_ETA,
status["eta"])
row = self.torrent_model.iter_next(row)
def add_row(self, torrent_id):
"""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], [
# Get the status and info dictionaries
status = functions.get_torrent_status_dict(self.core, torrent_id)
info = functions.get_torrent_info_dict(self.core, torrent_id)
# Insert the row with info provided from core
self.torrent_model.insert(status["position"], [
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
status["position"]+1,
None,
info["name"],
info["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):
"""Removes a row with torrent_id"""
row = self.torrent_model.get_iter_first()
while row is not None:
# Check if this row is the row we want to remove
if self.torrent_model.get_value(row, 0) == torrent_id:
self.torrent_model.remove(row)
# Force an update of the torrentview
self.update()
break
row = self.torrent_model.iter_next(row)
def get_selected_torrents(self):
"""Returns a list of selected torrents or None"""
torrent_ids = []
paths = self.torrent_view.get_selection().get_selected_rows()[1]
try:
for path in paths:
torrent_ids.append(
self.torrent_model.get_value(
self.torrent_model.get_iter(path), 0))
return torrent_ids
except ValueError:
return None
### Callbacks ###
def on_button_press_event(self, widget, event, data):
def on_button_press_event(self, widget, event):
log.debug("on_button_press_event")
# We only care about right-clicks
if event.button == 3:
# Show the Torrent menu from the MenuBar
torrentmenu = self.window.menubar.torrentmenu.get_widget(
"torrent_menu")
torrentmenu.popup(None, None, None, event.button, event.time)
def on_selection_changed(self, treeselection, data):
def on_selection_changed(self, treeselection):
log.debug("on_selection_changed")