diff --git a/deluge/core/core.py b/deluge/core/core.py index be86f36d7..67abf00c7 100644 --- a/deluge/core/core.py +++ b/deluge/core/core.py @@ -380,6 +380,10 @@ class Core( def export_disable_plugin(self, plugin): self.plugins.disable_plugin(plugin) return None + + def export_force_recheck(self, torrent_id): + """Forces a data recheck on torrent_id""" + return self.torrents.force_recheck(torrent_id) # Signals def torrent_added(self, torrent_id): diff --git a/deluge/core/torrentmanager.py b/deluge/core/torrentmanager.py index 222ddeebc..51e4181e1 100644 --- a/deluge/core/torrentmanager.py +++ b/deluge/core/torrentmanager.py @@ -235,8 +235,8 @@ class TorrentManager: try: # Remove from libtorrent session self.session.remove_torrent(self.torrents[torrent_id].handle, 0) - except RuntimeError, KeyError: - log.warning("Error removing torrent") + except (RuntimeError, KeyError), e: + log.warning("Error removing torrent: %s", e) return False try: @@ -303,6 +303,71 @@ class TorrentManager: 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) + paused = self.torrents[torrent_id].handle.status().paused + ### Check for .torrent file prior to removing and make a copy if needed + ### FIXME + + try: + # We start by removing it from the lt session + self.session.remove_torrent(self.torrents[torrent_id].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 + + # 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: + storage_mode = lt.storage_mode_t(1) + else: + storage_mode = lt.storage_mode_t(2) + + try: + handle = self.session.add_torrent( + lt.torrent_info(torrent_filedump), + str(self.torrents[torrent_id].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(): + # The torrent was not added to the session + return False + + return True + def load_state(self): """Load the state of the TorrentManager from the torrents.state file""" state = TorrentManagerState() diff --git a/deluge/plugins/queue/queue/gtkui.py b/deluge/plugins/queue/queue/gtkui.py index ee0ef626e..53e8ebb60 100644 --- a/deluge/plugins/queue/queue/gtkui.py +++ b/deluge/plugins/queue/queue/gtkui.py @@ -89,6 +89,9 @@ class GtkUI(ui.UI): tooltip=_("Queue selected torrents down"), callback=self.on_queuedown_activate) + # Add a separator before menu + self.menu_sep = self.plugin.add_torrentmenu_separator() + # Add the queue menu to the torrent menu self.queue_menuitem = gtk.ImageMenuItem("Queue") queue_image = gtk.Image() @@ -99,7 +102,8 @@ class GtkUI(ui.UI): self.plugin.add_torrentmenu_menu(self.queue_menuitem) def unload_interface(self): - self.plugin.remove_torrentmenu_menu(self.queue_menuitem) + self.plugin.remove_torrentmenu_item(self.menu_sep) + self.plugin.remove_torrentmenu_item(self.queue_menuitem) self.plugin.remove_toolbar_button(self.toolbar_sep) self.plugin.remove_toolbar_button(self.toolbutton_up) self.plugin.remove_toolbar_button(self.toolbutton_down) diff --git a/deluge/ui/client.py b/deluge/ui/client.py index 6578684ee..9b2cb393a 100644 --- a/deluge/ui/client.py +++ b/deluge/ui/client.py @@ -314,7 +314,15 @@ def disable_plugin(plugin): get_core().disable_plugin(plugin) except (AttributeError, socket.error): set_core_uri(None) - + +def force_recheck(torrent_ids): + """Forces a data recheck on torrent_ids""" + try: + for torrent_id in torrent_ids: + get_core().force_recheck(torrent_id) + except (AttributeError, socket.error): + set_core_uri(None) + def open_url_in_browser(url): """Opens link in the desktop's default browser""" def start_browser(): diff --git a/deluge/ui/gtkui/glade/torrent_menu.glade b/deluge/ui/gtkui/glade/torrent_menu.glade index deb1cecbf..00617a06e 100644 --- a/deluge/ui/gtkui/glade/torrent_menu.glade +++ b/deluge/ui/gtkui/glade/torrent_menu.glade @@ -4,6 +4,28 @@ True + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + _Open Folder + True + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-open + 1 + + + + + + + True + + True @@ -102,5 +124,27 @@ + + + True + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + _Force Re-check + True + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-redo + 1 + + + + diff --git a/deluge/ui/gtkui/menubar.py b/deluge/ui/gtkui/menubar.py index 12bea2206..0b48e1523 100644 --- a/deluge/ui/gtkui/menubar.py +++ b/deluge/ui/gtkui/menubar.py @@ -92,7 +92,8 @@ class MenuBar(component.Component): "on_menuitem_edittrackers_activate": \ self.on_menuitem_edittrackers_activate, "on_menuitem_remove_activate": self.on_menuitem_remove_activate, - + "on_menuitem_recheck_activate": self.on_menuitem_recheck_activate, + "on_menuitem_open_folder": self.on_menuitem_open_folder_activate }) self.change_sensitivity = [ @@ -121,6 +122,12 @@ class MenuBar(component.Component): self.window.main_glade.get_widget("separatormenuitem").hide() self.window.main_glade.get_widget("menuitem_quitdaemon").hide() + def add_torrentmenu_separator(self): + sep = gtk.SeparatorMenuItem() + self.torrentmenu.append(sep) + sep.show() + return sep + ### Callbacks ### ## File Menu ## @@ -162,17 +169,17 @@ class MenuBar(component.Component): def on_menuitem_pause_activate(self, data=None): log.debug("on_menuitem_pause_activate") client.pause_torrent( - component.get("TorrentView").get_selected_torrents()) + component.get("TorrentView").get_selected_torrents()) def on_menuitem_resume_activate(self, data=None): log.debug("on_menuitem_resume_activate") client.resume_torrent( - component.get("TorrentView").get_selected_torrents()) + component.get("TorrentView").get_selected_torrents()) def on_menuitem_updatetracker_activate(self, data=None): log.debug("on_menuitem_updatetracker_activate") client.force_reannounce( - component.get("TorrentView").get_selected_torrents()) + component.get("TorrentView").get_selected_torrents()) def on_menuitem_edittrackers_activate(self, data=None): log.debug("on_menuitem_edittrackers_activate") @@ -180,8 +187,16 @@ class MenuBar(component.Component): def on_menuitem_remove_activate(self, data=None): log.debug("on_menuitem_remove_activate") client.remove_torrent( - component.get("TorrentView").get_selected_torrents()) - + component.get("TorrentView").get_selected_torrents()) + + def on_menuitem_recheck_activate(self, data=None): + log.debug("on_menuitem_recheck_activate") + client.force_recheck( + component.get("TorrentView").get_selected_torrents()) + + def on_menuitem_open_folder_activate(self, data=None): + log.debug("on_menuitem_open_folder") + ## View Menu ## def on_menuitem_toolbar_toggled(self, value): log.debug("on_menuitem_toolbar_toggled") diff --git a/deluge/ui/gtkui/pluginmanager.py b/deluge/ui/gtkui/pluginmanager.py index ce56e33af..e90179a29 100644 --- a/deluge/ui/gtkui/pluginmanager.py +++ b/deluge/ui/gtkui/pluginmanager.py @@ -74,9 +74,12 @@ class PluginManager(deluge.pluginmanagerbase.PluginManagerBase, def add_torrentmenu_menu(self, *args): return component.get("MenuBar").torrentmenu.append(*args) - def remove_torrentmenu_menu(self, *args): + def remove_torrentmenu_item(self, *args): return component.get("MenuBar").torrentmenu.remove(*args) + def add_torrentmenu_separator(self): + return component.get("MenuBar").add_torrentmenu_separator() + def update_torrent_view(self, *args): return component.get("TorrentView").update(*args)