diff --git a/deluge/core/pluginmanager.py b/deluge/core/pluginmanager.py index c5313c0ce..c9ee11b5f 100644 --- a/deluge/core/pluginmanager.py +++ b/deluge/core/pluginmanager.py @@ -59,6 +59,14 @@ class PluginManager(deluge.pluginmanagerbase.PluginManagerBase): log.debug("Registering status field %s with PluginManager", field) self.status_fields[field] = function + def deregister_status_field(self, field): + """Deregisters a status field""" + log.debug("Deregistering status field %s with PluginManager", field) + try: + del self.status_fields[field] + except: + log.warning("Unable to deregister status field %s", field) + def get_status(self, torrent_id, fields): """Return the value of status fields for the selected torrent_id.""" status = {} @@ -76,7 +84,14 @@ class PluginManager(deluge.pluginmanagerbase.PluginManagerBase): self.hooks[hook].append(function) except KeyError: log.warning("Plugin attempting to register invalid hook.") - + + def deregister_hook(self, hook, function): + """Deregisters a hook function""" + try: + self.hooks[hook].remove(function) + except: + log.warning("Unable to deregister hook %s", hook) + def run_post_torrent_add(self, torrent_id): """This hook is run after a torrent has been added to the session.""" log.debug("run_post_torrent_add") diff --git a/deluge/pluginmanagerbase.py b/deluge/pluginmanagerbase.py index dadfb1759..b5da2ff7c 100644 --- a/deluge/pluginmanagerbase.py +++ b/deluge/pluginmanagerbase.py @@ -108,6 +108,7 @@ class PluginManagerBase: entry_point = egg.get_entry_info(self.entry_name, name) cls = entry_point.load() instance = cls(self) + instance.enable() plugin_name = plugin_name.replace("-", " ") self.plugins[plugin_name] = instance if plugin_name not in self.config["enabled_plugins"]: @@ -116,11 +117,10 @@ class PluginManagerBase: def disable_plugin(self, name): """Disables a plugin""" - - self.plugins[name].disable() try: + self.plugins[name].disable() del self.plugins[name] - self.config["enabled_plugins"].remove(plugin_name) + self.config["enabled_plugins"].remove(name) except KeyError: log.warning("Plugin %s is not enabled..", name) diff --git a/deluge/plugins/init.py b/deluge/plugins/init.py index 5891c4616..1221b6b74 100644 --- a/deluge/plugins/init.py +++ b/deluge/plugins/init.py @@ -1,9 +1,51 @@ +# +# init.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. + +from deluge.log import LOG as log + class PluginBase: def __init__(self): - pass + self.plugin = None def enable(self): - pass + try: + self.plugin.enable() + except Exception, e: + log.warning("Unable to enable plugin: %s", e) + def disable(self): - pass + try: + self.plugin.disable() + except Exception, e: + log.warning("Unable to disable plugin: %s", e) diff --git a/deluge/plugins/queue/queue/__init__.py b/deluge/plugins/queue/queue/__init__.py index 852a80fda..0d69a2054 100644 --- a/deluge/plugins/queue/queue/__init__.py +++ b/deluge/plugins/queue/queue/__init__.py @@ -31,20 +31,24 @@ # this exception statement from your version. If you delete this exception # statement from all source files in the program, then also delete it here. -from core import Core -from gtkui import GtkUI - from deluge.log import LOG as log -class CorePlugin: - def __init__(self, plugin_manager): - # Load the Core portion of the plugin - self.core = Core(plugin_manager) - - def disable(self): - pass +from deluge.plugins.init import PluginBase -class GtkUIPlugin: - def __init__(self, plugin_manager): +class CorePlugin(PluginBase): + def __init__(self, plugin_api): + # Load the Core portion of the plugin + try: + from core import Core + self.plugin = Core(plugin_api) + except Exception, e: + log.debug("Did not load a Core plugin: %s", e) + +class GtkUIPlugin(PluginBase): + def __init__(self, plugin_api): # Load the GtkUI portion of the plugin - self.gtkui = GtkUI(plugin_manager) + try: + from gtkui import GtkUI + self.plugin = GtkUI(plugin_api) + except Exception, e: + log.debug("Did not load a GtkUI plugin: %s", e) diff --git a/deluge/plugins/queue/queue/core.py b/deluge/plugins/queue/queue/core.py index b69ab34f0..ca4d67b65 100644 --- a/deluge/plugins/queue/queue/core.py +++ b/deluge/plugins/queue/queue/core.py @@ -35,10 +35,12 @@ from torrentqueue import TorrentQueue from deluge.log import LOG as log class Core: - def __init__(self, plugin): - # Get the pluginmanager reference - self.plugin = plugin + def __init__(self, plugin_api): + # Get the plugin_api + self.plugin = plugin_api + log.info("Queue Core plugin initialized..") + def enable(self): # Instantiate the TorrentQueue object self.queue = TorrentQueue() @@ -50,14 +52,21 @@ class Core: # Register the 'queue' status field self.plugin.register_status_field("queue", self._status_field_queue) - log.info("Queue Core plugin initialized..") + log.debug("Queue Core plugin enabled..") def disable(self): - pass - - def shutdown(self): - # Save the queue state + # Save queue state self.queue.save_state() + # Delete the queue + del self.queue + self.queue = None + # De-register hooks + self.plugin.deregister_hook("post_torrent_add", self._post_torrent_add) + self.plugin.deregister_hook("post_torrent_remove", + self._post_torrent_remove) + + # De-register status fields + self.plugin.deregister_status_field("queue") ## Hooks for core ## def _post_torrent_add(self, torrent_id): diff --git a/deluge/plugins/queue/queue/gtkui.py b/deluge/plugins/queue/queue/gtkui.py index e9600df8a..8722b60c5 100644 --- a/deluge/plugins/queue/queue/gtkui.py +++ b/deluge/plugins/queue/queue/gtkui.py @@ -33,40 +33,29 @@ import pkg_resources import gtk.glade -import gettext -import locale from deluge.log import LOG as log +import ui -class GtkUI: - def __init__(self, plugin_manager): - # Initialize gettext - locale.setlocale(locale.LC_MESSAGES, '') - locale.bindtextdomain("deluge", - pkg_resources.resource_filename( - "deluge", "i18n")) - locale.textdomain("deluge") - gettext.bindtextdomain("deluge", - pkg_resources.resource_filename( - "deluge", "i18n")) - gettext.textdomain("deluge") - gettext.install("deluge", - pkg_resources.resource_filename( - "deluge", "i18n")) +class GtkUI(ui.UI): + def __init__(self, plugin_api): + log.debug("Calling UI init") + # Call UI constructor + ui.UI.__init__(self, plugin_api) log.debug("Queue GtkUI plugin initalized..") - self.plugin = plugin_manager - + + def load_interface(self): # Get the queue menu from the glade file menu_glade = gtk.glade.XML(pkg_resources.resource_filename("queue", "glade/queuemenu.glade")) menu_glade.signal_autoconnect({ "on_menuitem_queuetop_activate": \ - self.on_menuitem_queuetop_activate, - "on_menuitem_queueup_activate": self.on_menuitem_queueup_activate, + self.on_queuetop_activate, + "on_menuitem_queueup_activate": self.on_queueup_activate, "on_menuitem_queuedown_activate": \ - self.on_menuitem_queuedown_activate, + self.on_queuedown_activate, "on_menuitem_queuebottom_activate": \ - self.on_menuitem_queuebottom_activate + self.on_queuebottom_activate }) menu = menu_glade.get_widget("menu_queue") @@ -76,93 +65,45 @@ class GtkUI: # self.torrent_queue_changed_signal) # Get the torrentview component from the plugin manager - self.torrentview = self.plugin.get_torrentview() + #self.torrentview = self.plugin.get_torrentview() # Add the '#' column at the first position - self.torrentview.add_text_column("#", + #self.torrentview.add_text_column("#", + self.plugin.add_torrentview_text_column("#", col_type=int, position=0, status_field=["queue"]) # Update the new column right away - self.torrentview.update(["#"]) + self.update_interface() # Add a toolbar buttons - self.plugin.get_toolbar().add_separator() - self.plugin.get_toolbar().add_toolbutton(stock="gtk-go-up", + self.toolbar_sep = self.plugin.add_toolbar_separator() + self.toolbutton_up = self.plugin.add_toolbar_button( + stock="gtk-go-up", label=_("Queue Up"), tooltip=_("Queue selected torrents up"), - callback=self.on_toolbutton_queueup_clicked) + callback=self.on_queueup_activate) - self.plugin.get_toolbar().add_toolbutton(stock="gtk-go-down", + self.toolbutton_down = self.plugin.add_toolbar_button( + stock="gtk-go-down", label=_("Queue Down"), tooltip=_("Queue selected torrents down"), - callback=self.on_toolbutton_queuedown_clicked) + callback=self.on_queuedown_activate) # Add the queue menu to the torrent menu - queue_menuitem = gtk.ImageMenuItem("Queue") + self.queue_menuitem = gtk.ImageMenuItem("Queue") queue_image = gtk.Image() queue_image.set_from_stock(gtk.STOCK_SORT_ASCENDING, gtk.ICON_SIZE_MENU) - queue_menuitem.set_image(queue_image) - queue_menuitem.set_submenu(menu) - queue_menuitem.show_all() - self.plugin.get_torrentmenu().append(queue_menuitem) - - ## Menu callbacks ## - def on_menuitem_queuetop_activate(self, data=None): - log.debug("on_menuitem_queuetop_activate") - # Get the selected torrents - torrent_ids = self.plugin.get_selected_torrents() - for torrent_id in torrent_ids: - self.core.queue_top(torrent_id) - return - - def on_menuitem_queueup_activate(self, data=None): - log.debug("on_menuitem_queueup_activate") - # Get the selected torrents - torrent_ids = self.plugin.get_selected_torrents() - for torrent_id in torrent_ids: - self.core.queue_up(torrent_id) - return - - def on_menuitem_queuedown_activate(self, data=None): - log.debug("on_menuitem_queuedown_activate") - # Get the selected torrents - torrent_ids = self.plugin.get_selected_torrents() - for torrent_id in torrent_ids: - self.core.queue_down(torrent_id) - return - - def on_menuitem_queuebottom_activate(self, data=None): - log.debug("on_menuitem_queuebottom_activate") - # Get the selected torrents - torrent_ids = self.plugin.get_selected_torrents() - for torrent_id in torrent_ids: - self.core.queue_bottom(torrent_id) - return - - ## Toolbutton callbacks ## - def on_toolbutton_queuedown_clicked(self, widget): - log.debug("on_toolbutton_queuedown_clicked") - # Get the selected torrents - torrent_ids = self.plugin.get_selected_torrents() - for torrent_id in torrent_ids: - self.core.queue_down(torrent_id) - return - - def on_toolbutton_queueup_clicked(self, widget): - log.debug("on_toolbutton_queueup_clicked") - # Get the selected torrents - torrent_ids = self.plugin.get_selected_torrents() - for torrent_id in torrent_ids: - self.core.queue_up(torrent_id) - return + self.queue_menuitem.set_image(queue_image) + self.queue_menuitem.set_submenu(menu) + self.queue_menuitem.show_all() + self.plugin.add_torrentmenu_menu(self.queue_menuitem) - ## Signals ## - def torrent_queue_changed_signal(self): - """This function is called whenever we receive a 'torrent_queue_changed' - signal from the core plugin. - """ - log.debug("torrent_queue_changed signal received..") - # We only need to update the queue column - self.torrentview.update(["#"]) - return - + def unload_interface(self): + self.plugin.remove_torrentmenu_menu(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) + self.plugin.remove_torrentview_column("#") + + def update_interface(self): + self.plugin.update_torrent_view(["#"]) diff --git a/deluge/plugins/queue/queue/ui.py b/deluge/plugins/queue/queue/ui.py new file mode 100644 index 000000000..7a188c371 --- /dev/null +++ b/deluge/plugins/queue/queue/ui.py @@ -0,0 +1,116 @@ +# +# ui.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 gettext +import locale +import pkg_resources +from deluge.log import LOG as log + +class UI: + def __init__(self, plugin_api): + self.plugin = plugin_api + # Initialize gettext + locale.setlocale(locale.LC_MESSAGES, '') + locale.bindtextdomain("deluge", + pkg_resources.resource_filename( + "deluge", "i18n")) + locale.textdomain("deluge") + gettext.bindtextdomain("deluge", + pkg_resources.resource_filename( + "deluge", "i18n")) + gettext.textdomain("deluge") + gettext.install("deluge", + pkg_resources.resource_filename( + "deluge", "i18n")) + + def enable(self): + log.debug("Enabling UI plugin") + # Load the interface and connect the callbacks + self.load_interface() + + def disable(self): + self.unload_interface() + + def load_interface(self): + pass + + def unload_interface(self): + pass + + def update_interface(self): + pass + + ## Menu callbacks ## + def on_queuetop_activate(self, data=None): + log.debug("on_menuitem_queuetop_activate") + # Get the selected torrents + torrent_ids = self.plugin.get_selected_torrents() + for torrent_id in torrent_ids: + self.core.queue_top(torrent_id) + return + + def on_queueup_activate(self, data=None): + log.debug("on_menuitem_queueup_activate") + # Get the selected torrents + torrent_ids = self.plugin.get_selected_torrents() + for torrent_id in torrent_ids: + self.core.queue_up(torrent_id) + return + + def on_queuedown_activate(self, data=None): + log.debug("on_menuitem_queuedown_activate") + # Get the selected torrents + torrent_ids = self.plugin.get_selected_torrents() + for torrent_id in torrent_ids: + self.core.queue_down(torrent_id) + return + + def on_queuebottom_activate(self, data=None): + log.debug("on_menuitem_queuebottom_activate") + # Get the selected torrents + torrent_ids = self.plugin.get_selected_torrents() + for torrent_id in torrent_ids: + self.core.queue_bottom(torrent_id) + return + + ## Signals ## + def torrent_queue_changed_signal(self): + """This function is called whenever we receive a 'torrent_queue_changed' + signal from the core plugin. + """ + log.debug("torrent_queue_changed signal received..") + # We only need to update the queue column +# self.torrentview.update(["#"]) + self.update_interface() + return + diff --git a/deluge/plugins/queue/setup.py b/deluge/plugins/queue/setup.py index 4aa3ceec9..9f7231642 100644 --- a/deluge/plugins/queue/setup.py +++ b/deluge/plugins/queue/setup.py @@ -46,7 +46,7 @@ setup( entry_points=""" [deluge.plugin.core] Queue = queue:CorePlugin - [deluge.plugin.ui.gtk] + [deluge.plugin.gtkui] Queue = queue:GtkUIPlugin """ ) diff --git a/deluge/plugins/testp/testp/__init__.py b/deluge/plugins/testp/testp/__init__.py index 19ace0e75..6a417f2b3 100644 --- a/deluge/plugins/testp/testp/__init__.py +++ b/deluge/plugins/testp/testp/__init__.py @@ -36,19 +36,19 @@ from deluge.log import LOG as log from deluge.plugins.init import PluginBase class CorePlugin(PluginBase): - def __init__(self, plugin_manager): + def __init__(self, plugin_api): # Load the Core portion of the plugin try: from core import Core - self.core = Core() + self.plugin = Core(plugin_api) except: pass class GtkUIPlugin(PluginBase): - def __init__(self, plugin_manager): + def __init__(self, plugin_api): # Load the GtkUI portion of the plugin try: from gtkui import GtkUI - self.gtkui = GtkUI() + self.plugin = GtkUI() except: pass diff --git a/deluge/plugins/testp/testp/core.py b/deluge/plugins/testp/testp/core.py index 2f6fb4bc8..b49b6a84d 100644 --- a/deluge/plugins/testp/testp/core.py +++ b/deluge/plugins/testp/testp/core.py @@ -34,7 +34,7 @@ from deluge.log import LOG as log class Core: - def __init__(self): + def __init__(self, plugin_api): pass def enable(self): diff --git a/deluge/ui/gtkui/pluginmanager.py b/deluge/ui/gtkui/pluginmanager.py index b5084226a..ce56e33af 100644 --- a/deluge/ui/gtkui/pluginmanager.py +++ b/deluge/ui/gtkui/pluginmanager.py @@ -53,23 +53,33 @@ class PluginManager(deluge.pluginmanagerbase.PluginManagerBase, deluge.pluginmanagerbase.PluginManagerBase.__init__( self, "gtkui.conf", "deluge.plugin.gtkui") - - def get_torrentview(self): - """Returns a reference to the torrentview component""" - return component.get("TorrentView") - def get_toolbar(self): - """Returns a reference to the toolbar component""" - return component.get("ToolBar") - - def get_menubar(self): - """Returns a reference to the menubar component""" - return component.get("MenuBar") - - def get_torrentmenu(self): - """Returns a reference to the torrentmenu component""" - return component.get("MenuBar").torrentmenu + ## Plugin functions.. will likely move to own class.. + def add_torrentview_text_column(self, *args, **kwargs): + return component.get("TorrentView").add_text_column(*args, **kwargs) + + def remove_torrentview_column(self, *args): + return component.get("TorrentView").remove_column(*args) + + def add_toolbar_separator(self): + return component.get("ToolBar").add_separator() + + def add_toolbar_button(self, *args, **kwargs): + return component.get("ToolBar").add_toolbutton(*args, **kwargs) + + def remove_toolbar_button(self, *args): + return component.get("ToolBar").remove(*args) + + def add_torrentmenu_menu(self, *args): + return component.get("MenuBar").torrentmenu.append(*args) + + def remove_torrentmenu_menu(self, *args): + return component.get("MenuBar").torrentmenu.remove(*args) + + def update_torrent_view(self, *args): + return component.get("TorrentView").update(*args) + def get_selected_torrents(self): """Returns a list of the selected torrent_ids""" return component.get("TorrentView").get_selected_torrents() diff --git a/deluge/ui/gtkui/toolbar.py b/deluge/ui/gtkui/toolbar.py index bda9e21e5..a4f4bb716 100644 --- a/deluge/ui/gtkui/toolbar.py +++ b/deluge/ui/gtkui/toolbar.py @@ -108,7 +108,7 @@ class ToolBar(component.Component): # Show the new toolbutton toolbutton.show() - return + return toolbutton def add_separator(self, position=None): """Adds a separator toolitem""" @@ -118,8 +118,15 @@ class ToolBar(component.Component): else: # Append the separator self.toolbar.insert(sep, -1) - return + + sep.show() + return sep + + def remove(self, widget): + """Removes a widget from the toolbar""" + self.toolbar.remove(widget) + ### Callbacks ### def on_toolbutton_add_clicked(self, data): log.debug("on_toolbutton_add_clicked")