From 7d9a30a54577855923b3fc3d985aa2adbe314323 Mon Sep 17 00:00:00 2001 From: Andrew Resch Date: Fri, 9 Nov 2007 12:08:15 +0000 Subject: [PATCH] Updates to the Connection Manager. Updates to TorrentManager. --- TODO | 1 + deluge/core/torrentmanager.py | 125 +++++++-------- deluge/ui/gtkui/connectionmanager.py | 149 +++++++++++++----- .../ui/gtkui/glade/connection_manager.glade | 8 +- 4 files changed, 177 insertions(+), 106 deletions(-) diff --git a/TODO b/TODO index 757adabc6..95e3c993c 100644 --- a/TODO +++ b/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 diff --git a/deluge/core/torrentmanager.py b/deluge/core/torrentmanager.py index 51e4181e1..a602b58ec 100644 --- a/deluge/core/torrentmanager.py +++ b/deluge/core/torrentmanager.py @@ -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 diff --git a/deluge/ui/gtkui/connectionmanager.py b/deluge/ui/gtkui/connectionmanager.py index 6788ac452..f586e993b 100644 --- a/deluge/ui/gtkui/connectionmanager.py +++ b/deluge/ui/gtkui/connectionmanager.py @@ -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 diff --git a/deluge/ui/gtkui/glade/connection_manager.glade b/deluge/ui/gtkui/glade/connection_manager.glade index 4c7fb9005..53d23ac9c 100644 --- a/deluge/ui/gtkui/glade/connection_manager.glade +++ b/deluge/ui/gtkui/glade/connection_manager.glade @@ -1,6 +1,6 @@ - + True @@ -270,6 +270,10 @@ 0 + + False + False + @@ -283,6 +287,8 @@ + False + False 1