Updates to the Connection Manager.
Updates to TorrentManager.
This commit is contained in:
parent
a043858f2e
commit
7d9a30a545
1
TODO
1
TODO
|
@ -18,4 +18,5 @@
|
|||
* Add queue preferences tab
|
||||
* Add classic/normal mode to preferences
|
||||
* Implement 'Classic' mode
|
||||
* Add remove torrent dialog and ability to remove data
|
||||
|
||||
|
|
|
@ -136,16 +136,7 @@ class TorrentManager:
|
|||
filedump = "".join(chr(b) for b in filedump)
|
||||
else:
|
||||
# Get the data from the file
|
||||
try:
|
||||
log.debug("Attempting to open %s for add.", filename)
|
||||
_file = open(
|
||||
os.path.join(
|
||||
self.config["torrentfiles_location"], filename), "rb")
|
||||
filedump = _file.read()
|
||||
_file.close()
|
||||
except IOError:
|
||||
log.warning("Unable to open %s", filename)
|
||||
return None
|
||||
filedump = self.load_torrent(filename)
|
||||
|
||||
# Attempt to load fastresume data
|
||||
try:
|
||||
|
@ -156,12 +147,10 @@ class TorrentManager:
|
|||
"rb")
|
||||
fastresume = lt.bdecode(_file.read())
|
||||
_file.close()
|
||||
except IOError:
|
||||
log.debug("Unable to load .fastresume..")
|
||||
except IOError, e:
|
||||
log.debug("Unable to load .fastresume: %s", e)
|
||||
fastresume = None
|
||||
|
||||
# Bdecode the filedata
|
||||
torrent_filedump = lt.bdecode(filedump)
|
||||
handle = None
|
||||
|
||||
# Make sure we have a valid download_location
|
||||
|
@ -180,13 +169,13 @@ class TorrentManager:
|
|||
|
||||
try:
|
||||
handle = self.session.add_torrent(
|
||||
lt.torrent_info(torrent_filedump),
|
||||
lt.torrent_info(filedump),
|
||||
str(save_path),
|
||||
resume_data=fastresume,
|
||||
storage_mode=storage_mode,
|
||||
paused=paused)
|
||||
except RuntimeError:
|
||||
log.warning("Error adding torrent")
|
||||
except RuntimeError, e:
|
||||
log.warning("Error adding torrent: %s", e)
|
||||
|
||||
if not handle or not handle.is_valid():
|
||||
# The torrent was not added to the session
|
||||
|
@ -202,7 +191,16 @@ class TorrentManager:
|
|||
# Set per-torrent limits
|
||||
handle.set_max_connections(self.max_connections)
|
||||
handle.set_max_uploads(self.max_uploads)
|
||||
|
||||
|
||||
# Save the torrent file
|
||||
self.save_torrent(filename, filedump)
|
||||
|
||||
# Save the session state
|
||||
self.save_state()
|
||||
return torrent.torrent_id
|
||||
|
||||
def save_torrent(self, filename, filedump):
|
||||
"""Saves a torrent file"""
|
||||
log.debug("Attempting to save torrent file: %s", filename)
|
||||
# Test if the torrentfiles_location is accessible
|
||||
if os.access(
|
||||
|
@ -211,25 +209,37 @@ class TorrentManager:
|
|||
# The directory probably doesn't exist, so lets create it
|
||||
try:
|
||||
os.makedirs(os.path.join(self.config["torrentfiles_location"]))
|
||||
except IOError:
|
||||
log.warning("Unable to create torrent files directory..")
|
||||
except IOError, e:
|
||||
log.warning("Unable to create torrent files directory: %s", e)
|
||||
|
||||
# Write the .torrent file to the torrent directory
|
||||
try:
|
||||
save_file = open(os.path.join(self.config["torrentfiles_location"],
|
||||
filename),
|
||||
"wb")
|
||||
save_file.write(lt.bencode(torrent_filedump))
|
||||
save_file.write(lt.bencode(filedump))
|
||||
save_file.close()
|
||||
except IOError:
|
||||
log.warning("Unable to save torrent file: %s", filename)
|
||||
|
||||
log.debug("Torrent %s added.", handle.info_hash())
|
||||
except IOError, e:
|
||||
log.warning("Unable to save torrent file: %s", e)
|
||||
|
||||
# Save the session state
|
||||
self.save_state()
|
||||
return torrent.torrent_id
|
||||
|
||||
def load_torrent(self, filename):
|
||||
"""Load a torrent file and return it's torrent info"""
|
||||
filedump = None
|
||||
# Get the torrent data from the torrent file
|
||||
try:
|
||||
log.debug("Attempting to open %s for add.", filename)
|
||||
_file = open(
|
||||
os.path.join(
|
||||
self.config["torrentfiles_location"], filename),
|
||||
"rb")
|
||||
filedump = lt.bdecode(_file.read())
|
||||
_file.close()
|
||||
except IOError, e:
|
||||
log.warning("Unable to open %s: e", filename, e)
|
||||
return False
|
||||
|
||||
return filedump
|
||||
|
||||
def remove(self, torrent_id):
|
||||
"""Remove a torrent from the manager"""
|
||||
try:
|
||||
|
@ -302,67 +312,52 @@ class TorrentManager:
|
|||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def force_recheck(self, torrent_id):
|
||||
"""Forces a re-check of the torrent's data"""
|
||||
log.debug("Doing a forced recheck on %s", torrent_id)
|
||||
torrent = self.torrents[torrent_id]
|
||||
paused = self.torrents[torrent_id].handle.status().paused
|
||||
torrent_info = None
|
||||
### Check for .torrent file prior to removing and make a copy if needed
|
||||
### FIXME
|
||||
|
||||
if os.access(os.path.join(self.config["torrentfiles_location"] +\
|
||||
"/" + torrent.filename), os.F_OK) is False:
|
||||
torrent_info = torrent.handle.get_torrent_info().create_torrent()
|
||||
self.save_torrent(torrent.filename, torrent_info)
|
||||
|
||||
# We start by removing it from the lt session
|
||||
try:
|
||||
# We start by removing it from the lt session
|
||||
self.session.remove_torrent(self.torrents[torrent_id].handle, 0)
|
||||
self.session.remove_torrent(torrent.handle, 0)
|
||||
except (RuntimeError, KeyError), e:
|
||||
log.warning("Error removing torrent: %s", e)
|
||||
return False
|
||||
|
||||
# Remove the fastresume file if there
|
||||
self.delete_fastresume(torrent_id)
|
||||
|
||||
# Get the torrent data from the torrent file
|
||||
filename = self.torrents[torrent_id].filename
|
||||
try:
|
||||
log.debug("Attempting to open %s for add.", filename)
|
||||
_file = open(
|
||||
os.path.join(
|
||||
self.config["torrentfiles_location"], filename), "rb")
|
||||
filedump = _file.read()
|
||||
_file.close()
|
||||
except IOError, e:
|
||||
log.warning("Unable to open %s: e", filename, e)
|
||||
return False
|
||||
|
||||
# Bdecode the filedata
|
||||
torrent_filedump = lt.bdecode(filedump)
|
||||
handle = None
|
||||
# Load the torrent info from file if needed
|
||||
if torrent_info == None:
|
||||
torrent_info = self.load_torrent(torrent.filename)
|
||||
|
||||
# Next we re-add the torrent
|
||||
# Make sure we have a valid download_location
|
||||
if self.torrents[torrent_id].save_path is None:
|
||||
self.torrents[torrent_id].save_path = \
|
||||
self.config["download_location"]
|
||||
|
||||
# Make sure we are adding it with the correct allocation method.
|
||||
if self.torrents[torrent_id].compact is None:
|
||||
self.torrents[torrent_id].compact = \
|
||||
self.config["compact_allocation"]
|
||||
|
||||
# Set the right storage_mode
|
||||
if self.torrents[torrent_id].compact:
|
||||
if torrent.compact:
|
||||
storage_mode = lt.storage_mode_t(1)
|
||||
else:
|
||||
storage_mode = lt.storage_mode_t(2)
|
||||
|
||||
|
||||
# Add the torrent to the lt session
|
||||
try:
|
||||
handle = self.session.add_torrent(
|
||||
lt.torrent_info(torrent_filedump),
|
||||
str(self.torrents[torrent_id].save_path),
|
||||
torrent.handle = self.session.add_torrent(
|
||||
lt.torrent_info(torrent_info),
|
||||
str(torrent.save_path),
|
||||
storage_mode=storage_mode,
|
||||
paused=paused)
|
||||
except RuntimeError, e:
|
||||
log.warning("Error adding torrent: %s", e)
|
||||
|
||||
if not handle or not handle.is_valid():
|
||||
if not torrent.handle or not torrent.handle.is_valid():
|
||||
# The torrent was not added to the session
|
||||
return False
|
||||
|
||||
|
|
|
@ -193,10 +193,30 @@ class ConnectionManager(component.Component):
|
|||
self.liststore.foreach(update_row)
|
||||
# Update the buttons
|
||||
self.update_buttons()
|
||||
|
||||
# See if there is any row selected
|
||||
paths = self.hostlist.get_selection().get_selected_rows()[1]
|
||||
if len(paths) < 1:
|
||||
# And there is at least 1 row
|
||||
if self.liststore.iter_n_children(None) > 0:
|
||||
# Then select the first row
|
||||
self.hostlist.get_selection().select_iter(self.liststore.get_iter_first())
|
||||
return True
|
||||
|
||||
def update_buttons(self):
|
||||
"""Updates the buttons based on selection"""
|
||||
if self.liststore.iter_n_children(None) < 1:
|
||||
# There is nothing in the list
|
||||
self.glade.get_widget("button_startdaemon").set_sensitive(True)
|
||||
self.glade.get_widget("button_connect").set_sensitive(False)
|
||||
self.glade.get_widget("button_removehost").set_sensitive(False)
|
||||
self.glade.get_widget("image_startdaemon").set_from_stock(
|
||||
gtk.STOCK_EXECUTE, gtk.ICON_SIZE_MENU)
|
||||
self.glade.get_widget("label_startdaemon").set_text(
|
||||
"_Start Daemon")
|
||||
self.glade.get_widget("label_startdaemon").set_use_underline(
|
||||
True)
|
||||
|
||||
# Get the selected row's URI
|
||||
paths = self.hostlist.get_selection().get_selected_rows()[1]
|
||||
# If nothing is selected, just return
|
||||
|
@ -213,33 +233,46 @@ class ConnectionManager(component.Component):
|
|||
|
||||
# Make actual URI string
|
||||
uri = "http://" + uri
|
||||
|
||||
# Make sure buttons are sensitive at start
|
||||
self.glade.get_widget("button_startdaemon").set_sensitive(True)
|
||||
self.glade.get_widget("button_connect").set_sensitive(True)
|
||||
self.glade.get_widget("button_removehost").set_sensitive(True)
|
||||
|
||||
# See if this is the currently connected URI
|
||||
if status == HOSTLIST_STATUS.index("Connected"):
|
||||
# Display a disconnect button if we're connected to this host
|
||||
self.glade.get_widget("button_connect").set_label("gtk-disconnect")
|
||||
self.glade.get_widget("button_removehost").set_sensitive(False)
|
||||
else:
|
||||
self.glade.get_widget("button_connect").set_label("gtk-connect")
|
||||
if status == HOSTLIST_STATUS.index("Offline") and not localhost:
|
||||
self.glade.get_widget("button_connect").set_sensitive(False)
|
||||
|
||||
# Check to see if the host is online
|
||||
if status == HOSTLIST_STATUS.index("Connected") \
|
||||
or status == HOSTLIST_STATUS.index("Online"):
|
||||
self.glade.get_widget("image_startdaemon").set_from_stock(
|
||||
gtk.STOCK_STOP, gtk.ICON_SIZE_MENU)
|
||||
self.glade.get_widget("label_startdaemon").set_text(
|
||||
"_Stop Daemon")
|
||||
|
||||
# Update the start daemon button if the selected host is localhost
|
||||
if localhost:
|
||||
# Check to see if the host is online
|
||||
if status == HOSTLIST_STATUS.index("Connected") \
|
||||
or status == HOSTLIST_STATUS.index("Online"):
|
||||
self.glade.get_widget("image_startdaemon").set_from_stock(
|
||||
gtk.STOCK_STOP, gtk.ICON_SIZE_MENU)
|
||||
self.glade.get_widget("label_startdaemon").set_text(
|
||||
"_Stop local daemon")
|
||||
else:
|
||||
# The localhost is not online
|
||||
self.glade.get_widget("image_startdaemon").set_from_stock(
|
||||
gtk.STOCK_EXECUTE, gtk.ICON_SIZE_MENU)
|
||||
self.glade.get_widget("label_startdaemon").set_text(
|
||||
"_Start local daemon")
|
||||
# Make sure label is displayed correctly using mnemonics
|
||||
self.glade.get_widget("label_startdaemon").set_use_underline(
|
||||
True)
|
||||
|
||||
if localhost and status == HOSTLIST_STATUS.index("Offline"):
|
||||
# The localhost is not online
|
||||
self.glade.get_widget("image_startdaemon").set_from_stock(
|
||||
gtk.STOCK_EXECUTE, gtk.ICON_SIZE_MENU)
|
||||
self.glade.get_widget("label_startdaemon").set_text(
|
||||
"_Start Daemon")
|
||||
|
||||
if not localhost:
|
||||
# An offline host
|
||||
self.glade.get_widget("button_startdaemon").set_sensitive(False)
|
||||
|
||||
# Make sure label is displayed correctly using mnemonics
|
||||
self.glade.get_widget("label_startdaemon").set_use_underline(
|
||||
True)
|
||||
|
||||
def save(self):
|
||||
"""Save the current host list to file"""
|
||||
def append_row(model=None, path=None, row=None, columns=None):
|
||||
|
@ -279,27 +312,29 @@ class ConnectionManager(component.Component):
|
|||
response = dialog.run()
|
||||
if response == 1:
|
||||
# We add the host
|
||||
hostname = hostname_entry.get_text()
|
||||
if hostname.startswith("http://"):
|
||||
hostname = hostname[7:]
|
||||
self.add_host(hostname_entry.get_text(),
|
||||
port_spinbutton.get_value_as_int())
|
||||
|
||||
# Check to make sure the hostname is at least 1 character long
|
||||
if len(hostname) < 1:
|
||||
dialog.hide()
|
||||
return
|
||||
|
||||
# Get the port and concatenate the hostname string
|
||||
port = port_spinbutton.get_value_as_int()
|
||||
hostname = hostname + ":" + str(port)
|
||||
row = self.liststore.append()
|
||||
self.liststore.set_value(row, HOSTLIST_COL_URI, hostname)
|
||||
# Save the host list to file
|
||||
self.save()
|
||||
# Update the status of the hosts
|
||||
self._update()
|
||||
|
||||
dialog.hide()
|
||||
dialog.hide()
|
||||
|
||||
def add_host(self, hostname, port):
|
||||
"""Adds the host to the list"""
|
||||
if hostname.startswith("http://"):
|
||||
hostname = hostname[7:]
|
||||
|
||||
# Check to make sure the hostname is at least 1 character long
|
||||
if len(hostname) < 1:
|
||||
return
|
||||
|
||||
# Get the port and concatenate the hostname string
|
||||
hostname = hostname + ":" + str(port)
|
||||
row = self.liststore.append()
|
||||
self.liststore.set_value(row, HOSTLIST_COL_URI, hostname)
|
||||
# Save the host list to file
|
||||
self.save()
|
||||
# Update the status of the hosts
|
||||
self._update()
|
||||
|
||||
def on_button_removehost_clicked(self, widget):
|
||||
log.debug("on_button_removehost_clicked")
|
||||
# Get the selected rows
|
||||
|
@ -307,12 +342,24 @@ class ConnectionManager(component.Component):
|
|||
for path in paths:
|
||||
self.liststore.remove(self.liststore.get_iter(path))
|
||||
|
||||
# Update the hostlist
|
||||
self._update()
|
||||
|
||||
# Save the host list
|
||||
self.save()
|
||||
|
||||
def on_button_startdaemon_clicked(self, widget):
|
||||
log.debug("on_button_startdaemon_clicked")
|
||||
if self.liststore.iter_n_children(None) < 1:
|
||||
# There is nothing in the list, so lets create a localhost entry
|
||||
self.add_host("localhost", 58846)
|
||||
# ..and start the daemon.
|
||||
self.start_localhost(58846)
|
||||
return
|
||||
|
||||
paths = self.hostlist.get_selection().get_selected_rows()[1]
|
||||
if len(paths) < 1:
|
||||
return
|
||||
row = self.liststore.get_iter(paths[0])
|
||||
status = self.liststore.get_value(row, HOSTLIST_COL_STATUS)
|
||||
uri = self.liststore.get_value(row, HOSTLIST_COL_URI)
|
||||
|
@ -327,10 +374,15 @@ class ConnectionManager(component.Component):
|
|||
# Update display to show change
|
||||
self.update()
|
||||
elif HOSTLIST_STATUS[status] == "Offline":
|
||||
log.debug("Start localhost daemon..")
|
||||
# Spawn a local daemon
|
||||
os.popen("deluged -p %s" % port)
|
||||
self.start_localhost(port)
|
||||
|
||||
def start_localhost(self, port):
|
||||
"""Starts a localhost daemon"""
|
||||
port = str(port)
|
||||
log.info("Starting localhost:%s daemon..", port)
|
||||
# Spawn a local daemon
|
||||
os.popen("deluged -p %s" % port)
|
||||
|
||||
def on_button_close_clicked(self, widget):
|
||||
log.debug("on_button_close_clicked")
|
||||
self.hide()
|
||||
|
@ -341,6 +393,12 @@ class ConnectionManager(component.Component):
|
|||
row = self.liststore.get_iter(paths[0])
|
||||
status = self.liststore.get_value(row, HOSTLIST_COL_STATUS)
|
||||
uri = self.liststore.get_value(row, HOSTLIST_COL_URI)
|
||||
# Determine if this is a localhost
|
||||
localhost = False
|
||||
port = uri.split(":")[1]
|
||||
if uri.split(":")[0] == "localhost":
|
||||
localhost = True
|
||||
|
||||
uri = "http://" + uri
|
||||
if status == HOSTLIST_STATUS.index("Connected"):
|
||||
# If we are connected to this host, then we will disconnect.
|
||||
|
@ -352,8 +410,19 @@ class ConnectionManager(component.Component):
|
|||
# column information because it can be up to 5 seconds out of sync.
|
||||
if not self.test_online_status(uri):
|
||||
log.warning("Host does not appear to be online..")
|
||||
# If this is an offline localhost.. lets start it and connect
|
||||
if localhost:
|
||||
self.start_localhost(port)
|
||||
# We need to wait for the host to start before connecting
|
||||
while not self.test_online_status(uri):
|
||||
sleep(10)
|
||||
client.set_core_uri(uri)
|
||||
self._update()
|
||||
self.hide()
|
||||
|
||||
# Update the list to show proper status
|
||||
self._update()
|
||||
|
||||
return
|
||||
|
||||
# Status is OK, so lets change to this host
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
|
||||
<!--Generated with glade3 3.2.2 on Thu Oct 25 01:07:45 2007 by andrew@fragment-->
|
||||
<!--Generated with glade3 3.2.2 on Fri Nov 9 03:49:00 2007 by andrew@fragment-->
|
||||
<glade-interface>
|
||||
<widget class="GtkDialog" id="connection_manager">
|
||||
<property name="has_focus">True</property>
|
||||
|
@ -270,6 +270,10 @@
|
|||
<property name="response_id">0</property>
|
||||
<signal name="clicked" handler="on_button_close_clicked"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkButton" id="button_connect">
|
||||
|
@ -283,6 +287,8 @@
|
|||
<signal name="clicked" handler="on_button_connect_clicked"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
|
Loading…
Reference in New Issue