diff --git a/ChangeLog b/ChangeLog index dbfbda562..1ed3af7dd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -9,6 +9,8 @@ * #1112: Fix renaming files in add torrent dialog * #1247: Fix deluge-gtk from hanging on shutdown * #995: Rewrote tracker_icons + * Make the distinction between adding to the session new unmanaged torrents and torrents loaded from state. This will break backwards compatability. + * Pass a copy of an event instead of passing the event arguments to the event handlers. This will break backwards compatability. ==== GtkUI ==== * Fix uncaught exception when closing deluge in classic mode diff --git a/deluge/core/eventmanager.py b/deluge/core/eventmanager.py index b4aa1759a..7687bfc30 100644 --- a/deluge/core/eventmanager.py +++ b/deluge/core/eventmanager.py @@ -53,7 +53,7 @@ class EventManager(component.Component): if event.name in self.handlers: for handler in self.handlers[event.name]: #log.debug("Running handler %s for event %s with args: %s", event.name, handler, event.args) - handler(*event.args) + handler(event.copy()) def register_event_handler(self, event, handler): """ diff --git a/deluge/core/rpcserver.py b/deluge/core/rpcserver.py index ef088fe5b..a84ccbf75 100644 --- a/deluge/core/rpcserver.py +++ b/deluge/core/rpcserver.py @@ -485,7 +485,8 @@ class RPCServer(component.Component): # Find sessions interested in this event for session_id, interest in self.factory.interested_events.iteritems(): if event.name in interest: - log.debug("Emit Event: %s %s", event.name, event.args) + log.debug("Emit Event: %s %s", event.name, zip(event.__slots__, + event.args)) # This session is interested so send a RPC_EVENT self.factory.session_protocols[session_id].sendData( (RPC_EVENT, event.name, event.args) diff --git a/deluge/event.py b/deluge/event.py index e2b0f6f8b..a4fc8b4a3 100644 --- a/deluge/event.py +++ b/deluge/event.py @@ -2,6 +2,7 @@ # event.py # # Copyright (C) 2009 Andrew Resch +# Copyright (C) 2010 Pedro Algarvio # # Deluge is free software. # @@ -47,6 +48,8 @@ class DelugeEventMetaClass(type): """ This metaclass simply keeps a list of all events classes created. """ + __slots__ = () + def __init__(cls, name, bases, dct): super(DelugeEventMetaClass, cls).__init__(name, bases, dct) if name != "DelugeEvent": @@ -62,23 +65,26 @@ class DelugeEvent(object): :type args: list """ + __slots__ = () __metaclass__ = DelugeEventMetaClass def _get_name(self): return self.__class__.__name__ + name = property(fget=_get_name) def _get_args(self): - if not hasattr(self, "_args"): - return [] - return self._args - - name = property(fget=_get_name) + return [getattr(self, arg) for arg in self.__slots__] args = property(fget=_get_args) + def copy(self): + return self.__class__(*self.args) + class TorrentAddedEvent(DelugeEvent): """ Emitted when a new torrent is successfully added to the session. """ + __slots__ = ('torrent_id', 'from_state') + def __init__(self, torrent_id, from_state): """ :param torrent_id: the torrent_id of the torrent that was added @@ -86,34 +92,41 @@ class TorrentAddedEvent(DelugeEvent): :param from_state: was the torrent loaded from state? Or is it a new torrent. :type from_state: bool """ - self._args = [torrent_id, from_state] + self.torrent_id = torrent_id + self.from_state = from_state class TorrentRemovedEvent(DelugeEvent): """ Emitted when a torrent has been removed from the session. """ + __slots__ = ('torrent_id',) + def __init__(self, torrent_id): """ :param torrent_id: the torrent_id :type torrent_id: string """ - self._args = [torrent_id] + self.torrent_id = torrent_id class PreTorrentRemovedEvent(DelugeEvent): """ Emitted when a torrent is about to be removed from the session. """ + __slots__ = ('torrent_id',) + def __init__(self, torrent_id): """ :param torrent_id: the torrent_id :type torrent_id: string """ - self._args = [torrent_id] + self.torrent_id = torrent_id class TorrentStateChangedEvent(DelugeEvent): """ Emitted when a torrent changes state. """ + __slots__ = ('torrent_id', 'state') + def __init__(self, torrent_id, state): """ :param torrent_id: the torrent_id @@ -121,18 +134,20 @@ class TorrentStateChangedEvent(DelugeEvent): :param state: the new state :type state: string """ - self._args = [torrent_id, state] + self.torrent_id = torrent_id + self.state = state class TorrentQueueChangedEvent(DelugeEvent): """ Emitted when the queue order has changed. """ - pass class TorrentFolderRenamedEvent(DelugeEvent): """ Emitted when a folder within a torrent has been renamed. """ + __slots__ = ('torrent_id', 'old', 'new') + def __init__(self, torrent_id, old, new): """ :param torrent_id: the torrent_id @@ -142,44 +157,54 @@ class TorrentFolderRenamedEvent(DelugeEvent): :param new: the new folder name :type new: string """ - self._args = [torrent_id, old, new] + self.torrent_id = torrent_id + self.old = old + self.new = new class TorrentFileRenamedEvent(DelugeEvent): """ Emitted when a file within a torrent has been renamed. """ - def __init__(self, torrent_id, index, name): + __slots__ = ('torrent_id', 'index', 'filename') + + def __init__(self, torrent_id, index, filename): """ :param torrent_id: the torrent_id :type torrent_id: string :param index: the index of the file :type index: int - :param name: the new filename - :type name: string + :param filename: the new filename + :type filename: string """ - self._args = [torrent_id, index, name] + self.torrent_id = torrent_id + self.index = index + self.filename = filename class TorrentFinishedEvent(DelugeEvent): """ Emitted when a torrent finishes downloading. """ + __slots__ = ('torrent_id',) + def __init__(self, torrent_id): """ :param torrent_id: the torrent_id :type torrent_id: string """ - self._args = [torrent_id] + self.torrent_id = torrent_id class TorrentResumedEvent(DelugeEvent): """ Emitted when a torrent resumes from a paused state. """ + __slots__ = ('torrent_id',) + def __init__(self, torrent_id): """ :param torrent_id: the torrent_id :type torrent_id: string """ - self._args = [torrent_id] + self.torrent_id = torrent_id class TorrentFileCompletedEvent(DelugeEvent): """ @@ -188,6 +213,8 @@ class TorrentFileCompletedEvent(DelugeEvent): This will only work with libtorrent 0.15 or greater. """ + __slots__ = ('torrent_id', 'index') + def __init__(self, torrent_id, index): """ :param torrent_id: the torrent_id @@ -195,68 +222,75 @@ class TorrentFileCompletedEvent(DelugeEvent): :param index: the file index :type index: int """ - self._args = [torrent_id, index] + self.torrent_id = torrent_id + self.index = index class NewVersionAvailableEvent(DelugeEvent): """ Emitted when a more recent version of Deluge is available. """ + __slots__ = ('new_release',) + def __init__(self, new_release): """ :param new_release: the new version that is available :type new_release: string """ - self._args = [new_release] + self.new_release = new_release class SessionStartedEvent(DelugeEvent): """ Emitted when a session has started. This typically only happens once when the daemon is initially started. """ - pass class SessionPausedEvent(DelugeEvent): """ Emitted when the session has been paused. """ - pass class SessionResumedEvent(DelugeEvent): """ Emitted when the session has been resumed. """ - pass class ConfigValueChangedEvent(DelugeEvent): """ Emitted when a config value changes in the Core. """ + __slots__ = ('key', 'value') + def __init__(self, key, value): """ :param key: the key that changed :type key: string :param value: the new value of the `:param:key` """ - self._args = [key, value] + self.key = key + self.value = value class PluginEnabledEvent(DelugeEvent): """ Emitted when a plugin is enabled in the Core. """ - def __init__(self, name): + __slots__ = ('plugin_name',) + + def __init__(self, plugin_name): """ - :param name: the plugin name - :type name: string + :param plugin_name: the plugin name + :type plugin_name: string """ - self._args = [name] + self.plugin_name = plugin_name class PluginDisabledEvent(DelugeEvent): """ Emitted when a plugin is disabled in the Core. """ - def __init__(self, name): + __slots__ = ('plugin_name',) + + def __init__(self, plugin_name): """ - :param name: the plugin name - :type name: string + :param plugin_name: the plugin name + :type plugin_name: string """ - self._args = [name] + self.plugin_name = plugin_name diff --git a/deluge/plugins/AutoAdd/deluge/plugins/autoadd/core.py b/deluge/plugins/AutoAdd/deluge/plugins/autoadd/core.py index aa58d8f53..ad2da5863 100644 --- a/deluge/plugins/AutoAdd/deluge/plugins/autoadd/core.py +++ b/deluge/plugins/AutoAdd/deluge/plugins/autoadd/core.py @@ -57,7 +57,7 @@ OPTIONS_AVAILABLE = { #option: builtin "enabled":False, "path":False, "append_extension":False, - "abspath":False, + "abspath":False, "download_location":True, "max_download_speed":True, "max_upload_speed":True, @@ -79,8 +79,6 @@ MAX_NUM_ATTEMPTS = 10 class AutoaddOptionsChangedEvent(DelugeEvent): """Emitted when the options for the plugin are changed.""" - def __init__(self): - pass def CheckInput(cond, message): if not cond: @@ -88,7 +86,7 @@ def CheckInput(cond, message): class Core(CorePluginBase): def enable(self): - + #reduce typing, assigning some values to self... self.config = deluge.configmanager.ConfigManager("autoadd.conf", DEFAULT_PREFS) self.watchdirs = self.config["watchdirs"] @@ -127,7 +125,7 @@ class Core(CorePluginBase): def update(self): pass - + @export() def set_options(self, watchdir_id, options): """Update the options for a watch folder.""" @@ -147,14 +145,14 @@ class Core(CorePluginBase): #disable the watch loop if it was active if watchdir_id in self.update_timers: self.disable_watchdir(watchdir_id) - + self.watchdirs[watchdir_id].update(options) #re-enable watch loop if appropriate if self.watchdirs[watchdir_id]['enabled']: self.enable_watchdir(watchdir_id) self.config.save() component.get("EventManager").emit(AutoaddOptionsChangedEvent()) - + def load_torrent(self, filename): try: log.debug("Attempting to open %s for add.", filename) @@ -171,7 +169,7 @@ class Core(CorePluginBase): info = lt.torrent_info(lt.bdecode(filedump)) return filedump - + def update_watchdir(self, watchdir_id): """Check the watch folder for new torrents to add.""" watchdir_id = str(watchdir_id) @@ -185,7 +183,7 @@ class Core(CorePluginBase): log.warning("Invalid AutoAdd folder: %s", watchdir["abspath"]) self.disable_watchdir(watchdir_id) return - + # Generate options dict for watchdir opts = {} if 'stop_at_ratio_toggle' in watchdir: @@ -246,7 +244,7 @@ class Core(CorePluginBase): """Disables any watch folders with unhandled exceptions.""" self.disable_watchdir(watchdir_id) log.error("Disabling '%s', error during update: %s" % (self.watchdirs[watchdir_id]["path"], failure)) - + @export def enable_watchdir(self, watchdir_id): watchdir_id = str(watchdir_id) @@ -259,7 +257,7 @@ class Core(CorePluginBase): self.watchdirs[watchdir_id]['enabled'] = True self.config.save() component.get("EventManager").emit(AutoaddOptionsChangedEvent()) - + @export def disable_watchdir(self, watchdir_id): watchdir_id = str(watchdir_id) @@ -287,7 +285,7 @@ class Core(CorePluginBase): def get_config(self): """Returns the config dictionary.""" return self.config.config - + @export() def get_watchdirs(self): return self.watchdirs.keys() @@ -319,7 +317,7 @@ class Core(CorePluginBase): self.config.save() component.get("EventManager").emit(AutoaddOptionsChangedEvent()) return watchdir_id - + @export def remove(self, watchdir_id): """Remove a watch folder.""" diff --git a/deluge/plugins/AutoAdd/deluge/plugins/autoadd/gtkui.py b/deluge/plugins/AutoAdd/deluge/plugins/autoadd/gtkui.py index 3fe74ca29..0bda2fac2 100644 --- a/deluge/plugins/AutoAdd/deluge/plugins/autoadd/gtkui.py +++ b/deluge/plugins/AutoAdd/deluge/plugins/autoadd/gtkui.py @@ -113,22 +113,22 @@ class OptionsDialog(): self.glade.get_widget(field+"_entry").show() self.glade.get_widget(field+"_chooser").hide() self.set_sensitive() - + def on_get_enabled_plugins(result): - if 'Label' in result: + if 'Label' in result: self.glade.get_widget('label_frame').show() else: self.glade.get_widget('label_frame').hide() self.glade.get_widget('label_toggle').set_active(False) - + client.core.get_enabled_plugins().addCallback(on_get_enabled_plugins) - + def set_sensitive(self): maintoggles = ['download_location', 'append_extension', 'move_completed', 'label', \ 'max_download_speed', 'max_upload_speed', 'max_connections', \ 'max_upload_slots', 'add_paused', 'auto_managed', 'stop_at_ratio', 'queue_to_top'] [self.on_toggle_toggled(self.glade.get_widget(x+'_toggle')) for x in maintoggles] - + def on_toggle_toggled(self, tb): toggle = str(tb.name).replace("_toggle", "") isactive = tb.get_active() @@ -166,29 +166,29 @@ class OptionsDialog(): self.glade.get_widget('stop_at_ratio').set_active(isactive) self.glade.get_widget('stop_ratio').set_sensitive(isactive) self.glade.get_widget('remove_at_ratio').set_sensitive(isactive) - + def on_apply(self, Event=None): client.autoadd.set_options(str(self.watchdir_id), self.generate_opts()).addCallbacks(self.on_added, self.on_error_show) - + def on_error_show(self, result): self.glade.get_widget('error_label').set_text(result.value.exception_msg) self.err_dialog = self.glade.get_widget('error_dialog') self.err_dialog.set_transient_for(self.dialog) result.cleanFailure() self.err_dialog.show() - + def on_added(self, result): self.dialog.destroy() - + def on_error_ok(self, Event=None): self.err_dialog.hide() - + def on_add(self, Event=None): client.autoadd.add(self.generate_opts()).addCallbacks(self.on_added, self.on_error_show) - + def on_cancel(self, Event=None): self.dialog.destroy() - + def generate_opts(self): # generate options dict based on gtk objects options = {} @@ -217,11 +217,11 @@ class OptionsDialog(): options[id] = self.glade.get_widget(id).get_active() options[id+'_toggle'] = self.glade.get_widget(id+'_toggle').get_active() return options - + class GtkUI(GtkPluginBase): def enable(self): - + self.glade = gtk.glade.XML(get_resource("config.glade")) self.glade.signal_autoconnect({ "on_add_button_clicked": self.on_add_button_clicked, @@ -229,18 +229,18 @@ class GtkUI(GtkPluginBase): "on_remove_button_clicked": self.on_remove_button_clicked }) self.opts_dialog = OptionsDialog() - + component.get("PluginManager").register_hook("on_apply_prefs", self.on_apply_prefs) component.get("PluginManager").register_hook("on_show_prefs", self.on_show_prefs) client.register_event_handler("AutoaddOptionsChangedEvent", self.on_options_changed_event) - + self.watchdirs = {} - + vbox = self.glade.get_widget("watchdirs_vbox") sw = gtk.ScrolledWindow() sw.set_shadow_type(gtk.SHADOW_ETCHED_IN) sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) - + vbox.pack_start(sw, True, True, 0) self.store = self.create_model() @@ -256,28 +256,28 @@ class GtkUI(GtkPluginBase): component.get("Preferences").add_page("AutoAdd", self.glade.get_widget("prefs_box")) self.on_show_prefs() - + def disable(self): component.get("Preferences").remove_page("AutoAdd") component.get("PluginManager").deregister_hook("on_apply_prefs", self.on_apply_prefs) component.get("PluginManager").deregister_hook("on_show_prefs", self.on_show_prefs) - + def create_model(self): - + store = gtk.ListStore(str, bool, str) for watchdir_id, watchdir in self.watchdirs.iteritems(): store.append([watchdir_id, watchdir['enabled'], watchdir['path']]) return store - + def create_columns(self, treeView): rendererToggle = gtk.CellRendererToggle() column = gtk.TreeViewColumn("On", rendererToggle, activatable=True, active=1) - column.set_sort_column_id(1) + column.set_sort_column_id(1) treeView.append_column(column) tt = gtk.Tooltip() tt.set_text('Double-click to toggle') treeView.set_tooltip_cell(tt, None, None, rendererToggle) - + rendererText = gtk.CellRendererText() column = gtk.TreeViewColumn("Path", rendererText, text=2) column.set_sort_column_id(2) @@ -289,20 +289,20 @@ class GtkUI(GtkPluginBase): def load_watchdir_list(self): pass - + def add_watchdir_entry(self): pass - + def on_add_button_clicked(self, Event=None): #display options_window self.opts_dialog.show() - + def on_remove_button_clicked(self, Event=None): tree, tree_id = self.treeView.get_selection().get_selected() watchdir_id = str(self.store.get_value(tree_id, 0)) if watchdir_id: client.autoadd.remove(watchdir_id) - + def on_edit_button_clicked(self, Event=None, a=None, col=None): tree, tree_id = self.treeView.get_selection().get_selected() watchdir_id = str(self.store.get_value(tree_id, 0)) @@ -314,7 +314,7 @@ class GtkUI(GtkPluginBase): client.autoadd.enable_watchdir(watchdir_id) else: self.opts_dialog.show(self.watchdirs[watchdir_id], watchdir_id) - + def on_listitem_activated(self, treeview): tree, tree_id = self.treeView.get_selection().get_selected() if tree_id: @@ -323,7 +323,7 @@ class GtkUI(GtkPluginBase): else: self.glade.get_widget('edit_button').set_sensitive(False) self.glade.get_widget('remove_button').set_sensitive(False) - + def on_apply_prefs(self): log.debug("applying prefs for AutoAdd") for watchdir_id, watchdir in self.watchdirs.iteritems(): @@ -331,8 +331,8 @@ class GtkUI(GtkPluginBase): def on_show_prefs(self): client.autoadd.get_config().addCallback(self.cb_get_config) - - def on_options_changed_event(self): + + def on_options_changed_event(self, event): client.autoadd.get_config().addCallback(self.cb_get_config) def cb_get_config(self, config): @@ -344,4 +344,4 @@ class GtkUI(GtkPluginBase): # Disable the remove and edit buttons, because nothing in the store is selected self.glade.get_widget('remove_button').set_sensitive(False) self.glade.get_widget('edit_button').set_sensitive(False) - + diff --git a/deluge/plugins/Execute/deluge/plugins/execute/core.py b/deluge/plugins/Execute/deluge/plugins/execute/core.py index 4c5e66005..123cc63c9 100644 --- a/deluge/plugins/Execute/deluge/plugins/execute/core.py +++ b/deluge/plugins/Execute/deluge/plugins/execute/core.py @@ -62,15 +62,19 @@ class ExecuteCommandAddedEvent(DelugeEvent): """ Emitted when a new command is added. """ + __slots__ = ('command_id', 'event', 'command') def __init__(self, command_id, event, command): - self._args = [command_id, event, command] + self.command_id = command_id + self.event = event + self.command = command class ExecuteCommandRemovedEvent(DelugeEvent): """ Emitted when a command is removed. """ + __slots__ = ('command_id',) def __init__(self, command_id): - self._args = [command_id] + self.command_id = command_id class Core(CorePluginBase): def enable(self): @@ -80,17 +84,17 @@ class Core(CorePluginBase): # Go through the commands list and register event handlers for command in self.config["commands"]: - event = command[EXECUTE_EVENT] - if event in self.registered_events: + event_name = command[EXECUTE_EVENT] + if event_name in self.registered_events: continue - def create_event_handler(event): - def event_handler(torrent_id): - self.execute_commands(torrent_id, event) + def create_event_handler(event_name): + def event_handler(event): + self.execute_commands(event.torrent_id, event_name) return event_handler - event_handler = create_event_handler(event) - event_manager.register_event_handler(EVENT_MAP[event], event_handler) - self.registered_events[event] = event_handler + event_handler = create_event_handler(event_name) + event_manager.register_event_handler(EVENT_MAP[event_name], event_handler) + self.registered_events[event_name] = event_handler log.debug("Execute core plugin enabled!") diff --git a/deluge/plugins/Execute/deluge/plugins/execute/gtkui.py b/deluge/plugins/Execute/deluge/plugins/execute/gtkui.py index 7a341ea2b..82851814f 100644 --- a/deluge/plugins/Execute/deluge/plugins/execute/gtkui.py +++ b/deluge/plugins/Execute/deluge/plugins/execute/gtkui.py @@ -159,13 +159,13 @@ class ExecutePreferences(object): command = widget.get_text() client.execute.save_command(command_id, event, command) - def on_command_added_event(self, command_id, event, command): - log.debug("Adding command %s: %s", event, command) - self.add_command(command_id, event, command) + def on_command_added_event(self, event): + log.debug("Adding command %s: %s", event.event, event.command) + self.add_command(event.command_id, event.event, event.command) - def on_command_removed_event(self, command_id): - log.debug("Removing command %s", command_id) - self.remove_command(command_id) + def on_command_removed_event(self, event): + log.debug("Removing command %s", event.command_id) + self.remove_command(event.command_id) class GtkUI(GtkPluginBase): diff --git a/deluge/plugins/Extractor/deluge/plugins/extractor/core.py b/deluge/plugins/Extractor/deluge/plugins/extractor/core.py index f7c888e17..8221b5bc4 100644 --- a/deluge/plugins/Extractor/deluge/plugins/extractor/core.py +++ b/deluge/plugins/Extractor/deluge/plugins/extractor/core.py @@ -75,14 +75,14 @@ class Core(CorePluginBase): def update(self): pass - def _on_torrent_finished(self, torrent_id): + def _on_torrent_finished(self, event): """ This is called when a torrent finishes. We need to check to see if there are any files to extract. """ # Get the save path - save_path = component.get("TorrentManager")[torrent_id].get_status(["save_path"])["save_path"] - files = component.get("TorrentManager")[torrent_id].get_files() + save_path = component.get("TorrentManager")[event.torrent_id].get_status(["save_path"])["save_path"] + files = component.get("TorrentManager")[event.torrent_id].get_files() for f in files: ext = os.path.splitext(f["path"]) if ext[1] in (".gz", ".bz2", ".lzma"): @@ -98,22 +98,22 @@ class Core(CorePluginBase): # Now that we have the cmd, lets run it to extract the files fp = os.path.join(save_path, f["path"]) - + # Get the destination path dest = self.config["extract_path"] if self.config["use_name_folder"]: - name = component.get("TorrentManager")[torrent_id].get_status(["name"])["name"] + name = component.get("TorrentManager")[event.torrent_id].get_status(["name"])["name"] dest = os.path.join(dest, name) - # Create the destination folder if it doesn't exist + # Create the destination folder if it doesn't exist if not os.path.exists(dest): try: os.makedirs(dest) except Exception, e: log.error("Error creating destination folder: %s", e) return - - log.debug("Extracting to %s", dest) + + log.debug("Extracting to %s", dest) def on_extract_success(result, torrent_id): # XXX: Emit an event log.debug("Extract was successful for %s", torrent_id) @@ -124,8 +124,8 @@ class Core(CorePluginBase): # Run the command and add some callbacks d = getProcessValue(cmd[0], cmd[1].split() + [str(fp)], {}, str(dest)) - d.addCallback(on_extract_success, torrent_id) - d.addErrback(on_extract_failed, torrent_id) + d.addCallback(on_extract_success, event.torrent_id) + d.addErrback(on_extract_failed, event.torrent_id) @export def set_config(self, config): diff --git a/deluge/plugins/FreeSpace/deluge/plugins/freespace/core.py b/deluge/plugins/FreeSpace/deluge/plugins/freespace/core.py index 42aed12a6..6029cfe7a 100644 --- a/deluge/plugins/FreeSpace/deluge/plugins/freespace/core.py +++ b/deluge/plugins/FreeSpace/deluge/plugins/freespace/core.py @@ -53,12 +53,14 @@ class LowDiskSpaceEvent(DelugeEvent): """Triggered when the available space for a specific path is getting too low. """ + __slots__ = ('percents_dict',) + def __init__(self, percents_dict): """ :param percents: dictionary of path keys with their respecive occupation percentages. """ - self._args = [percents_dict] + self.percents_dict = percents_dict DEFAULT_PREFS = { "enabled": False, @@ -170,25 +172,25 @@ class Core(CorePluginBase): free_percent = free_blocks * 100 / total_blocks return free_percent - def __custom_email_notification(self, ocupied_percents): + def __custom_email_notification(self, event): subject = _("Low Disk Space Warning") message = _("You're running low on disk space:\n") - for path, ocupied_percent in ocupied_percents.iteritems(): + for path, ocupied_percent in event.percents_dict.iteritems(): message += _(' %s%% ocupation in %s\n') % (ocupied_percent, path) # "\"%s\"%% space occupation on %s") % (ocupied_percent, path) return subject, message - def __on_plugin_enabled(self, plugin_name): - if plugin_name == 'Notifications': + def __on_plugin_enabled(self, event): + if event.plugin_name == 'Notifications': component.get("CorePlugin.Notifications"). \ register_custom_email_notification( "LowDiskSpaceEvent", self.__custom_email_notification ) - def __on_plugin_disabled(self, plugin_name): - if plugin_name == 'Notifications': + def __on_plugin_disabled(self, event): + if event.plugin_name == 'Notifications': component.get("CorePlugin.Notifications"). \ deregister_custom_email_notification("LowDiskSpaceEvent") diff --git a/deluge/plugins/FreeSpace/deluge/plugins/freespace/gtkui.py b/deluge/plugins/FreeSpace/deluge/plugins/freespace/gtkui.py index 57a8117e4..fb0b5d5d8 100644 --- a/deluge/plugins/FreeSpace/deluge/plugins/freespace/gtkui.py +++ b/deluge/plugins/FreeSpace/deluge/plugins/freespace/gtkui.py @@ -132,22 +132,22 @@ class GtkUI(GtkPluginBase): self.glade.get_widget('enabled').set_active(config['enabled']) self.glade.get_widget('percent').set_value(config['percent']) - def __custom_popup_notification(self, ocupied_percents): + def __custom_popup_notification(self, event): title = _("Low Free Space") message = '' - for path, percent in ocupied_percents.iteritems(): + for path, percent in event.percents_dict.iteritems(): message += '%s%% %s\n' % (percent, path) message += '\n' return title, message - def __custom_blink_notification(self, ocupied_percents): + def __custom_blink_notification(self, event): return True # Yes, do blink - def __custom_sound_notification(self, ocupied_percents): + def __custom_sound_notification(self, event): return '' # Use default sound - def __on_plugin_enabled(self, plugin_name): - if plugin_name == 'Notifications': + def __on_plugin_enabled(self, event): + if event.plugin_name == 'Notifications': notifications = component.get("GtkPlugin.Notifications") notifications.register_custom_popup_notification( "LowDiskSpaceEvent", self.__custom_popup_notification @@ -159,7 +159,7 @@ class GtkUI(GtkPluginBase): "LowDiskSpaceEvent", self.__custom_sound_notification ) - def __on_plugin_disabled(self, plugin_name): + def __on_plugin_disabled(self, event): pass # if plugin_name == 'Notifications': # notifications = component.get("GtkPlugin.Notifications") diff --git a/deluge/plugins/Label/deluge/plugins/label/core.py b/deluge/plugins/Label/deluge/plugins/label/core.py index 63f8e7f6e..3380f2744 100644 --- a/deluge/plugins/Label/deluge/plugins/label/core.py +++ b/deluge/plugins/Label/deluge/plugins/label/core.py @@ -131,20 +131,20 @@ class Core(CorePluginBase): return dict( [(label, 0) for label in self.labels.keys()]) ## Plugin hooks ## - def post_torrent_add(self, torrent_id, from_state): + def post_torrent_add(self, event): log.debug("post_torrent_add") - torrent = self.torrents[torrent_id] + torrent = self.torrents[event.torrent_id] for label_id, options in self.labels.iteritems(): if options["auto_add"]: if self._has_auto_match(torrent, options): - self.set_torrent(torrent_id, label_id) + self.set_torrent(event.torrent_id, label_id) return - def post_torrent_remove(self, torrent_id): + def post_torrent_remove(self, event): log.debug("post_torrent_remove") - if torrent_id in self.torrent_labels: - del self.torrent_labels[torrent_id] + if event.torrent_id in self.torrent_labels: + del self.torrent_labels[event.torrent_id] ## Utils ## def clean_config(self): diff --git a/deluge/plugins/Notifications/deluge/plugins/notifications/core.py b/deluge/plugins/Notifications/deluge/plugins/notifications/core.py index f4b9075ca..7831bc3e8 100644 --- a/deluge/plugins/Notifications/deluge/plugins/notifications/core.py +++ b/deluge/plugins/Notifications/deluge/plugins/notifications/core.py @@ -186,9 +186,9 @@ Subject: %(subject)s return _("Notification email sent.") - def _on_torrent_finished_event(self, torrent_id): + def _on_torrent_finished_event(self, event): log.debug("Handler for TorrentFinishedEvent called for CORE") - torrent = component.get("TorrentManager")[torrent_id] + torrent = component.get("TorrentManager")[event.torrent_id] torrent_status = torrent.get_status({}) # Email subject = _("Finished Torrent \"%(name)s\"") % torrent_status diff --git a/deluge/plugins/Scheduler/deluge/plugins/scheduler/core.py b/deluge/plugins/Scheduler/deluge/plugins/scheduler/core.py index e7fd86aae..c3c5008ea 100644 --- a/deluge/plugins/Scheduler/deluge/plugins/scheduler/core.py +++ b/deluge/plugins/Scheduler/deluge/plugins/scheduler/core.py @@ -74,11 +74,12 @@ class SchedulerEvent(DelugeEvent): """ Emitted when a schedule state changes. """ + __slots__ = ('colour',) def __init__(self, colour): """ :param colour: str, the current scheduler state """ - self._args = [colour] + self.colour = colour class Core(CorePluginBase): def enable(self): @@ -117,8 +118,8 @@ class Core(CorePluginBase): pass - def on_config_value_changed(self, key, value): - if key in CONTROLLED_SETTINGS: + def on_config_value_changed(self, event): + if event.key in CONTROLLED_SETTINGS: self.do_schedule(False) def __apply_set_functions(self): diff --git a/deluge/plugins/Scheduler/deluge/plugins/scheduler/gtkui.py b/deluge/plugins/Scheduler/deluge/plugins/scheduler/gtkui.py index e688d345b..73d156285 100644 --- a/deluge/plugins/Scheduler/deluge/plugins/scheduler/gtkui.py +++ b/deluge/plugins/Scheduler/deluge/plugins/scheduler/gtkui.py @@ -201,9 +201,9 @@ class GtkUI(GtkPluginBase): client.scheduler.get_config().addCallback(on_get_config) - def on_scheduler_event(self, state): + def on_scheduler_event(self, event): def on_state_deferred(s): - self.status_item.set_image_from_file(get_resource(state.lower() + ".png")) + self.status_item.set_image_from_file(get_resource(event.colour.lower() + ".png")) self.state_deferred.addCallback(on_state_deferred) diff --git a/deluge/ui/client.py b/deluge/ui/client.py index 3fbae6e6f..1a4506691 100644 --- a/deluge/ui/client.py +++ b/deluge/ui/client.py @@ -45,6 +45,7 @@ import zlib import deluge.common import deluge.component as component from deluge.log import LOG as log +from deluge.event import known_events if deluge.common.windows_check(): import win32api @@ -140,7 +141,7 @@ class DelugeRPCProtocol(Protocol): while data: # Increase the byte counter self.factory.bytes_recv += len(data) - + dobj = zlib.decompressobj() try: request = rencode.loads(dobj.decompress(data)) @@ -163,13 +164,14 @@ class DelugeRPCProtocol(Protocol): message_type = request[0] if message_type == RPC_EVENT: - event = request[1] + event_name = request[1] #log.debug("Received RPCEvent: %s", event) # A RPCEvent was received from the daemon so run any handlers # associated with it. - if event in self.factory.event_handlers: - for handler in self.factory.event_handlers[event]: - reactor.callLater(0, handler, *request[2]) + if event_name in self.factory.event_handlers: + event = known_events[event_name](*request[2]) + for handler in self.factory.event_handlers[event_name]: + reactor.callLater(0, handler, event.copy()) continue request_id = request[1] @@ -213,7 +215,7 @@ class DelugeRPCClientFactory(ClientFactory): def __init__(self, daemon, event_handlers): self.daemon = daemon self.event_handlers = event_handlers - + self.bytes_recv = 0 self.bytes_sent = 0 @@ -329,7 +331,7 @@ class DaemonSSLProxy(DaemonProxy): :param request_id: the request_id of the Deferred to pop :type request_id: int - + """ return self.__deferred.pop(request_id) @@ -343,7 +345,7 @@ class DaemonSSLProxy(DaemonProxy): :param handler: the function to be called when `:param:event` is emitted from the daemon :type handler: function - + """ if event not in self.__factory.event_handlers: # This is a new event to handle, so we need to tell the daemon @@ -422,10 +424,10 @@ class DaemonSSLProxy(DaemonProxy): def get_bytes_recv(self): return self.__factory.bytes_recv - + def get_bytes_sent(self): return self.__factory.bytes_sent - + class DaemonClassicProxy(DaemonProxy): def __init__(self, event_handlers={}): import deluge.core.daemon @@ -466,7 +468,7 @@ class DaemonClassicProxy(DaemonProxy): :param handler: the function to be called when `:param:event` is emitted from the daemon :type handler: function - + """ self.__daemon.core.eventmanager.register_event_handler(event, handler) @@ -571,7 +573,7 @@ class Client(object): :rtype: bool :raises OSError: received from subprocess.call() - + """ try: if deluge.common.windows_check(): @@ -679,7 +681,7 @@ class Client(object): def get_bytes_recv(self): """ Returns the number of bytes received from the daemon. - + :returns: the number of bytes received :rtype: int """ @@ -688,11 +690,11 @@ class Client(object): def get_bytes_sent(self): """ Returns the number of bytes sent to the daemon. - + :returns: the number of bytes sent :rtype: int """ return self._daemon_proxy.get_bytes_sent() - + # This is the object clients will use client = Client() diff --git a/deluge/ui/console/eventlog.py b/deluge/ui/console/eventlog.py index 745709e73..c5caddf68 100644 --- a/deluge/ui/console/eventlog.py +++ b/deluge/ui/console/eventlog.py @@ -61,53 +61,53 @@ class EventLog(component.Component): client.register_event_handler("PluginEnabledEvent", self.on_plugin_enabled_event) client.register_event_handler("PluginDisabledEvent", self.on_plugin_disabled_event) - def on_torrent_added_event(self, torrent_id, from_state): + def on_torrent_added_event(self, event): def on_torrent_status(status): self.console.write(self.prefix + "TorrentAdded(from_state=%s): {!info!}%s (%s)" % ( - from_state, status["name"], torrent_id) + event.from_state, status["name"], event.torrent_id) ) - client.core.get_torrent_status(torrent_id, ["name"]).addCallback(on_torrent_status) + client.core.get_torrent_status(event.torrent_id, ["name"]).addCallback(on_torrent_status) - def on_torrent_removed_event(self, torrent_id): + def on_torrent_removed_event(self, event): self.console.write(self.prefix + "TorrentRemoved: {!info!}%s (%s)" % - (self.console.get_torrent_name(torrent_id), torrent_id)) + (self.console.get_torrent_name(event.torrent_id), event.torrent_id)) - def on_torrent_state_changed_event(self, torrent_id, state): + def on_torrent_state_changed_event(self, event): # Modify the state string color - if state in colors.state_color: - state = colors.state_color[state] + state + if event.state in colors.state_color: + state = colors.state_color[event.state] + event.state self.console.write(self.prefix + "TorrentStateChanged: %s {!info!}%s (%s)" % - (state, self.console.get_torrent_name(torrent_id), torrent_id)) + (state, self.console.get_torrent_name(event.torrent_id), event.torrent_id)) - def on_torrent_paused_event(self, torrent_id): + def on_torrent_paused_event(self, event): self.console.write(self.prefix + "TorrentPaused: {!info!}%s (%s)" % - (self.console.get_torrent_name(torrent_id), torrent_id)) + (self.console.get_torrent_name(event.torrent_id), event.torrent_id)) - def on_torrent_finished_event(self, torrent_id): + def on_torrent_finished_event(self, event): self.console.write(self.prefix + "TorrentFinished: {!info!}%s (%s)" % - (self.console.get_torrent_name(torrent_id), torrent_id)) + (self.console.get_torrent_name(event.torrent_id), event.torrent_id)) - def on_new_version_available_event(self, version): + def on_new_version_available_event(self, event): self.console.write(self.prefix + "NewVersionAvailable: {!info!}%s" % - (version)) + (event.new_release)) - def on_session_paused_event(self): + def on_session_paused_event(self, event): self.console.write(self.prefix + "SessionPaused") - def on_session_resumed_event(self): + def on_session_resumed_event(self, event): self.console.write(self.prefix + "SessionResumed") - def on_config_value_changed_event(self, key, value): + def on_config_value_changed_event(self, event): color = "{!white,black,bold!}" - if type(value) in colors.type_color: - color = colors.type_color[type(value)] + if type(event.value) in colors.type_color: + color = colors.type_color[type(event.value)] self.console.write(self.prefix + "ConfigValueChanged: {!input!}%s: %s%s" % - (key, color, value)) + (event.key, color, event.value)) - def on_plugin_enabled_event(self, name): - self.console.write(self.prefix + "PluginEnabled: {!info!}%s" % name) + def on_plugin_enabled_event(self, event): + self.console.write(self.prefix + "PluginEnabled: {!info!}%s" % event.plugin_name) - def on_plugin_disabled_event(self, name): - self.console.write(self.prefix + "PluginDisabled: {!info!}%s" % name) + def on_plugin_disabled_event(self, event): + self.console.write(self.prefix + "PluginDisabled: {!info!}%s" % event.plugin_name) diff --git a/deluge/ui/console/main.py b/deluge/ui/console/main.py index 4afb0fce7..7d5e1a91a 100644 --- a/deluge/ui/console/main.py +++ b/deluge/ui/console/main.py @@ -439,14 +439,14 @@ class ConsoleUI(component.Component): return ret - def on_torrent_added_event(self, torrent_id, from_state): + def on_torrent_added_event(self, event): def on_torrent_status(status): - self.torrents.append((torrent_id, status["name"])) - client.core.get_torrent_status(torrent_id, ["name"]).addCallback(on_torrent_status) + self.torrents.append((event.torrent_id, status["name"])) + client.core.get_torrent_status(event.torrent_id, ["name"]).addCallback(on_torrent_status) - def on_torrent_removed_event(self, torrent_id): + def on_torrent_removed_event(self, event): for index, (tid, name) in enumerate(self.torrents): - if torrent_id == tid: + if event.torrent_id == tid: del self.torrents[index] def on_client_disconnect(self): diff --git a/deluge/ui/coreconfig.py b/deluge/ui/coreconfig.py index c56019729..7028936c1 100644 --- a/deluge/ui/coreconfig.py +++ b/deluge/ui/coreconfig.py @@ -43,8 +43,8 @@ class CoreConfig(component.Component): log.debug("CoreConfig init..") component.Component.__init__(self, "CoreConfig") self.config = {} - def on_configvaluechanged_event(key, value): - self.config[key] = value + def on_configvaluechanged_event(event): + self.config[event.key] = event.value client.register_event_handler("ConfigValueChangedEvent", on_configvaluechanged_event) def start(self): diff --git a/deluge/ui/gtkui/files_tab.py b/deluge/ui/gtkui/files_tab.py index c43d85b1b..9b195a35d 100644 --- a/deluge/ui/gtkui/files_tab.py +++ b/deluge/ui/gtkui/files_tab.py @@ -602,34 +602,34 @@ class FilesTab(Tab): def _on_filename_editing_canceled(self, renderer): self._editing_index = None - def _on_torrentfilerenamed_event(self, torrent_id, index, name): - log.debug("index: %s name: %s", index, name) + def _on_torrentfilerenamed_event(self, event): + log.debug("index: %s name: %s", event.index, event.filename) - if torrent_id not in self.files_list: + if event.torrent_id not in self.files_list: return - old_name = self.files_list[torrent_id][index]["path"] - self.files_list[torrent_id][index]["path"] = name + old_name = self.files_list[event.torrent_id][event.index]["path"] + self.files_list[event.torrent_id][event.index]["path"] = event.filename # We need to update the filename displayed if we're currently viewing # this torrents files. - if torrent_id == self.torrent_id: + if event.torrent_id == self.torrent_id: old_name_len = len(old_name.split("/")) - name_len = len(name.split("/")) + name_len = len(event.filename.split("/")) if old_name_len != name_len: # The parent path list changes depending on which way the file # is moving in the tree if old_name_len < name_len: parent_path = [o for o in old_name.split("/")[:-1]] else: - parent_path = [o for o in name.split("/")[:-1]] + parent_path = [o for o in event.filename.split("/")[:-1]] # Find the iter to the parent folder we need to add a new folder # to. def find_parent(model, path, itr, user_data): if model[itr][0] == parent_path[0] + "/": if len(parent_path) == 1: # This is the parent iter - to_create = name.split("/")[len(old_name.split("/")[:-1]):-1] + to_create = event.filename.split("/")[len(old_name.split("/")[:-1]):-1] parent_iter = itr for tc in to_create: @@ -648,8 +648,8 @@ class FilesTab(Tab): # Find the iter for the file that needs to be moved def get_file_iter(model, path, itr, user_data): - if model[itr][5] == index: - model[itr][0] = name.split("/")[-1] + if model[itr][5] == event.index: + model[itr][0] = event.filename.split("/")[-1] t = self.treestore.append( parent_iter, self.treestore.get(itr, @@ -668,7 +668,7 @@ class FilesTab(Tab): if parent_path: self.treestore.foreach(find_parent, None) else: - new_folders = name.split("/")[:-1] + new_folders = event.filename.split("/")[:-1] parent_iter = None for f in new_folders: parent_iter = self.treestore.append(parent_iter, @@ -682,8 +682,8 @@ class FilesTab(Tab): else: # This is just changing a filename without any folder changes def set_file_name(model, path, itr, user_data): - if model[itr][5] == index: - model[itr][0] = os.path.split(name)[-1] + if model[itr][5] == event.index: + model[itr][0] = os.path.split(event.filename)[-1] return True self.treestore.foreach(set_file_name, None) @@ -729,40 +729,40 @@ class FilesTab(Tab): self.treestore.remove(itr) itr = parent - def _on_torrentfolderrenamed_event(self, torrent_id, old_folder, new_folder): + def _on_torrentfolderrenamed_event(self, event): log.debug("on_torrent_folder_renamed_signal") - log.debug("old_folder: %s new_folder: %s", old_folder, new_folder) + log.debug("old_folder: %s new_folder: %s", event.old, event.new) - if torrent_id not in self.files_list: + if event.torrent_id not in self.files_list: return - if old_folder[-1] != "/": - old_folder += "/" - if new_folder[-1] != "/": - new_folder += "/" + if event.old[-1] != "/": + event.old += "/" + if event.new[-1] != "/": + event.new += "/" - for fd in self.files_list[torrent_id]: - if fd["path"].startswith(old_folder): - fd["path"] = fd["path"].replace(old_folder, new_folder, 1) + for fd in self.files_list[event.torrent_id]: + if fd["path"].startswith(event.old): + fd["path"] = fd["path"].replace(event.old, event.new, 1) - if torrent_id == self.torrent_id: + if event.torrent_id == self.torrent_id: - old_split = old_folder.split("/") + old_split = event.old.split("/") try: old_split.remove("") except: pass - new_split = new_folder.split("/") + new_split = event.new.split("/") try: new_split.remove("") except: pass - old_folder_iter = self.get_iter_at_path(old_folder) + old_folder_iter = self.get_iter_at_path(event.old) old_folder_iter_parent = self.treestore.iter_parent(old_folder_iter) - new_folder_iter = self.get_iter_at_path(new_folder) + new_folder_iter = self.get_iter_at_path(event.new) if len(new_split) == len(old_split): # These are at the same tree depth, so it's a simple rename self.treestore[old_folder_iter][0] = new_split[-1] + "/" @@ -782,9 +782,9 @@ class FilesTab(Tab): # and if so, we delete it self.remove_childless_folders(old_folder_iter_parent) - def _on_torrentremoved_event(self, torrent_id): - if torrent_id in self.files_list: - del self.files_list[torrent_id] + def _on_torrentremoved_event(self, event): + if event.torrent_id in self.files_list: + del self.files_list[event.torrent_id] def _on_drag_data_get_data(self, treeview, context, selection, target_id, etime): paths = self.listview.get_selection().get_selected_rows()[1] diff --git a/deluge/ui/gtkui/mainwindow.py b/deluge/ui/gtkui/mainwindow.py index 344359f5b..0190976e7 100644 --- a/deluge/ui/gtkui/mainwindow.py +++ b/deluge/ui/gtkui/mainwindow.py @@ -245,11 +245,11 @@ class MainWindow(component.Component): else: self.window.set_title("Deluge") - def on_newversionavailable_event(self, new_version): + def on_newversionavailable_event(self, event): if self.config["show_new_releases"]: from deluge.ui.gtkui.new_release_dialog import NewReleaseDialog - reactor.callLater(5.0, NewReleaseDialog().show, new_version) + reactor.callLater(5.0, NewReleaseDialog().show, event.new_release) - def on_torrentfinished_event(self, torrent_id): + def on_torrentfinished_event(self, event): from deluge.ui.gtkui.notification import Notification - Notification().notify(torrent_id) + Notification().notify(event.torrent_id) diff --git a/deluge/ui/gtkui/menubar.py b/deluge/ui/gtkui/menubar.py index 1a9026965..8a4cb8c0a 100644 --- a/deluge/ui/gtkui/menubar.py +++ b/deluge/ui/gtkui/menubar.py @@ -228,11 +228,11 @@ class MenuBar(component.Component): return sep ### Callbacks ### - def on_torrentstatechanged_event(self, torrent_id, state): - if state == "Paused": + def on_torrentstatechanged_event(self, event): + if event.state == "Paused": self.update_menu() - def on_torrentresumed_event(self, torrent_id): + def on_torrentresumed_event(self, event): self.update_menu() def on_sessionpaused_event(self): diff --git a/deluge/ui/gtkui/pluginmanager.py b/deluge/ui/gtkui/pluginmanager.py index 8d0126461..5bbbef351 100644 --- a/deluge/ui/gtkui/pluginmanager.py +++ b/deluge/ui/gtkui/pluginmanager.py @@ -89,11 +89,11 @@ class PluginManager(deluge.pluginmanagerbase.PluginManagerBase, for plugin in enabled_plugins: self.enable_plugin(plugin) - def _on_plugin_enabled_event(self, name): - self.enable_plugin(name) + def _on_plugin_enabled_event(self, event): + self.enable_plugin(event.plugin_name) - def _on_plugin_disabled_event(self, name): - self.disable_plugin(name) + def _on_plugin_disabled_event(self, event): + self.disable_plugin(event.plugin_name) ## Hook functions def run_on_show_prefs(self): diff --git a/deluge/ui/gtkui/statusbar.py b/deluge/ui/gtkui/statusbar.py index a95e78b61..ff350aeab 100644 --- a/deluge/ui/gtkui/statusbar.py +++ b/deluge/ui/gtkui/statusbar.py @@ -286,14 +286,14 @@ class StatusBar(component.Component): client.core.get_session_status(keys).addCallback(self._on_get_session_status) client.core.get_free_space().addCallback(self._on_get_free_space) - def on_configvaluechanged_event(self, key, value): + def on_configvaluechanged_event(self, event): """ This is called when we receive a ConfigValueChangedEvent from the core. """ - if key in self.config_value_changed_dict.keys(): - self.config_value_changed_dict[key](value) + if event.key in self.config_value_changed_dict.keys(): + self.config_value_changed_dict[event.key](event.value) def _on_max_connections_global(self, max_connections): self.max_connections = max_connections diff --git a/deluge/ui/gtkui/systemtray.py b/deluge/ui/gtkui/systemtray.py index 807852399..a9eaffbeb 100644 --- a/deluge/ui/gtkui/systemtray.py +++ b/deluge/ui/gtkui/systemtray.py @@ -173,12 +173,12 @@ class SystemTray(component.Component): "payload_upload_rate", "payload_download_rate"]).addCallback(self._on_get_session_status) - def config_value_changed(self, key, value): + def config_value_changed(self, event): """This is called when we received a config_value_changed signal from the core.""" - if key in self.config_value_changed_dict.keys(): - self.config_value_changed_dict[key](value) + if event.key in self.config_value_changed_dict.keys(): + self.config_value_changed_dict[event.key](event.value) def _on_max_download_speed(self, max_download_speed): if self.max_download_speed != max_download_speed: diff --git a/deluge/ui/gtkui/torrentview.py b/deluge/ui/gtkui/torrentview.py index 637e5a510..f0573d98a 100644 --- a/deluge/ui/gtkui/torrentview.py +++ b/deluge/ui/gtkui/torrentview.py @@ -512,31 +512,31 @@ class TorrentView(listview.ListView, component.Component): def on_drag_drop(self, widget, drag_context, x, y, timestamp): widget.stop_emission("drag-drop") - def on_torrentadded_event(self, torrent_id, from_state): - self.add_row(torrent_id) - self.mark_dirty(torrent_id) + def on_torrentadded_event(self, event): + self.add_row(event.torrent_id) + self.mark_dirty(event.torrent_id) - def on_torrentremoved_event(self, torrent_id): - self.remove_row(torrent_id) + def on_torrentremoved_event(self, event): + self.remove_row(event.torrent_id) - def on_torrentstatechanged_event(self, torrent_id, state): + def on_torrentstatechanged_event(self, event): # Update the torrents state for row in self.liststore: - if not torrent_id == row[self.columns["torrent_id"].column_indices[0]]: + if not event.torrent_id == row[self.columns["torrent_id"].column_indices[0]]: continue - row[self.get_column_index(_("Progress"))[1]] = state + row[self.get_column_index(_("Progress"))[1]] = event.state - self.mark_dirty(torrent_id) + self.mark_dirty(event.torrent_id) - def on_sessionpaused_event(self): + def on_sessionpaused_event(self, event): self.mark_dirty() self.update() - def on_sessionresumed_event(self): + def on_sessionresumed_event(self, event): self.mark_dirty() self.update() - def on_torrentqueuechanged_event(self): + def on_torrentqueuechanged_event(self, event): self.mark_dirty() self.update() diff --git a/deluge/ui/sessionproxy.py b/deluge/ui/sessionproxy.py index 37f804566..9519edfd1 100644 --- a/deluge/ui/sessionproxy.py +++ b/deluge/ui/sessionproxy.py @@ -234,21 +234,21 @@ class SessionProxy(component.Component): d = client.core.get_torrents_status(filter_dict, keys, True) return d.addCallback(on_status, None, keys) - def on_torrent_state_changed(self, torrent_id, state): - if torrent_id in self.torrents: - self.torrents[torrent_id][1]["state"] = state - self.cache_times[torrent_id]["state"] = time.time() + def on_torrent_state_changed(self, event): + if event.torrent_id in self.torrents: + self.torrents[event.torrent_id][1]["state"] = event.state + self.cache_times[event.torrent_id]["state"] = time.time() - def on_torrent_added(self, torrent_id, from_state): - self.torrents[torrent_id] = [time.time() - self.cache_time - 1, {}] - self.cache_times[torrent_id] = {} + def on_torrent_added(self, event): + self.torrents[event.torrent_id] = [time.time() - self.cache_time - 1, {}] + self.cache_times[event.torrent_id] = {} def on_status(status): - self.torrents[torrent_id][1].update(status) + self.torrents[event.torrent_id][1].update(status) t = time.time() for key in status: - self.cache_times[torrent_id][key] = t - client.core.get_torrent_status(torrent_id, []).addCallback(on_status) + self.cache_times[event.torrent_id][key] = t + client.core.get_torrent_status(event.torrent_id, []).addCallback(on_status) - def on_torrent_removed(self, torrent_id): - del self.torrents[torrent_id] - del self.cache_times[torrent_id] + def on_torrent_removed(self, event): + del self.torrents[event.torrent_id] + del self.cache_times[event.torrent_id] diff --git a/deluge/ui/web/js/deluge-all/Deluge.js b/deluge/ui/web/js/deluge-all/Deluge.js index de82dd7af..382b611dd 100644 --- a/deluge/ui/web/js/deluge-all/Deluge.js +++ b/deluge/ui/web/js/deluge-all/Deluge.js @@ -46,7 +46,7 @@ Ext.apply(Ext, { return true; }, - isObjectsEqual: function(obj1, obj2) { + areObjectsEqual: function(obj1, obj2) { var equal = true; if (!obj1 || !obj2) return false; for (var i in obj1) { diff --git a/deluge/ui/web/js/deluge-all/TorrentGrid.js b/deluge/ui/web/js/deluge-all/TorrentGrid.js index 04a020432..0455113c5 100644 --- a/deluge/ui/web/js/deluge-all/TorrentGrid.js +++ b/deluge/ui/web/js/deluge-all/TorrentGrid.js @@ -284,8 +284,15 @@ return ids; }, - update: function(torrents) { + update: function(torrents, wipe) { var store = this.getStore(); + + // Need to perform a complete reload of the torrent grid. + if (wipe) { + store.removeAll(); + this.torrents = {}; + } + var newTorrents = []; // Update and add any new torrents. diff --git a/deluge/ui/web/js/deluge-all/UI.js b/deluge/ui/web/js/deluge-all/UI.js index e8e86a593..4a1b96278 100644 --- a/deluge/ui/web/js/deluge-all/UI.js +++ b/deluge/ui/web/js/deluge-all/UI.js @@ -114,6 +114,9 @@ deluge.ui = { update: function() { var filters = deluge.sidebar.getFilterStates(); + this.oldFilters = this.filters; + this.filters = filters; + deluge.client.web.update_ui(Deluge.Keys.Grid, filters, { success: this.onUpdate, failure: this.onUpdateError, @@ -170,7 +173,11 @@ deluge.ui = { ' (Down: ' + fspeed(data['stats'].download_rate, true) + ' Up: ' + fspeed(data['stats'].upload_rate, true) + ')'; } - deluge.torrents.update(data['torrents']); + if (Ext.areObjectsEqual(this.filters, this.oldFilters)) { + deluge.torrents.update(data['torrents']); + } else { + deluge.torrents.update(data['torrents'], true); + } deluge.statusbar.update(data['stats']); deluge.sidebar.update(data['filters']); this.errorCount = 0; diff --git a/deluge/ui/web/pluginmanager.py b/deluge/ui/web/pluginmanager.py index d247e0729..ec4c61c58 100644 --- a/deluge/ui/web/pluginmanager.py +++ b/deluge/ui/web/pluginmanager.py @@ -58,26 +58,26 @@ def gather_info(plugin): "debug_scripts": debug_scripts, "script_directories": directories } - + class PluginManager(PluginManagerBase, component.Component): def __init__(self): component.Component.__init__(self, "Web.PluginManager") self.config = ConfigManager("web.conf") PluginManagerBase.__init__(self, "web.conf", "deluge.plugin.web") - + client.register_event_handler("PluginEnabledEvent", self._on_plugin_enabled_event) client.register_event_handler("PluginDisabledEvent", self._on_plugin_disabled_event) - + def _on_get_enabled_plugins(self, plugins): for plugin in plugins: self.enable_plugin(plugin) - - def _on_plugin_enabled_event(self, name): - self.enable_plugin(name) - def _on_plugin_disabled_event(self, name): - self.disable_plugin(name) - + def _on_plugin_enabled_event(self, event): + self.enable_plugin(event.plugin_name) + + def _on_plugin_disabled_event(self, event): + self.disable_plugin(event.plugin_name) + def disable_plugin(self, name): # Get the plugin instance try: @@ -85,31 +85,31 @@ class PluginManager(PluginManagerBase, component.Component): except KeyError: log.info("Plugin has no web ui") return - + info = gather_info(plugin) scripts = component.get("Scripts") for script in info["scripts"]: scripts.remove_script("%s/%s" % (name.lower(), os.path.basename(script).lower())) - + for script in info["debug_scripts"]: scripts.remove_script("%s/%s" % (name.lower(), os.path.basename(script).lower()), "debug") scripts.remove_script("%s/%s" % (name.lower(), os.path.basename(script).lower()), "dev") - + super(PluginManager, self).disable_plugin(name) - + def enable_plugin(self, name): super(PluginManager, self).enable_plugin(name) - + # Get the plugin instance try: plugin = component.get("WebPlugin." + name) except KeyError: log.info("Plugin has no web ui") return - + info = gather_info(plugin) - + scripts = component.get("Scripts") for script in info["scripts"]: log.debug("adding script %s for %s", name, os.path.basename(script)) @@ -127,16 +127,16 @@ class PluginManager(PluginManagerBase, component.Component): # Update the enabled plugins from the core d = client.core.get_enabled_plugins() d.addCallback(self._on_get_enabled_plugins) - + def stop(self): """ Stop the plugin manager """ self.disable_plugins() - + def update(self): pass - + def get_plugin_resources(self, name): # Get the plugin instance try: