Changeset 499a58


Ignore:
Timestamp:
02/23/2011 06:47:16 PM (14 years ago)
Author:
Andrew Resch <andrewresch@gmail.com>
Branches:
2.0.x, develop, extjs4-port, master
Children:
4c2f9a, 64e38e
Parents:
5f0f72
Message:

Revert 67ea05921cb904cb2ddf5811cd96534321bfeefa which changed how event handlers worked.
Unfortunately this will not work with plugins as they do not have the events defined and
the creation of the event object fails.

Files:
17 edited

Legend:

Unmodified
Added
Removed
  • ChangeLog

    r5f0f72 r499a58  
    1111        * #995: Rewrote tracker_icons
    1212        * Make the distinction between adding to the session new unmanaged torrents and torrents loaded from state. This will break backwards compatability.
    13         * Pass a copy of an event instead of passing the event arguments to the event handlers. This will break backwards compatability.
    1413
    1514==== GtkUI ====
  • deluge/core/eventmanager.py

    r5f0f72 r499a58  
    5656            for handler in self.handlers[event.name]:
    5757                #log.debug("Running handler %s for event %s with args: %s", event.name, handler, event.args)
    58                 handler(event.copy())
     58                handler(*event.args)
    5959
    6060    def register_event_handler(self, event, handler):
  • deluge/core/rpcserver.py

    r5f0f72 r499a58  
    487487        for session_id, interest in self.factory.interested_events.iteritems():
    488488            if event.name in interest:
    489                 log.debug("Emit Event: %s %s", event.name, zip(event.__slots__,
    490                                                                event.args))
     489                log.debug("Emit Event: %s %s", event.name, event.args)
    491490                # This session is interested so send a RPC_EVENT
    492491                self.factory.session_protocols[session_id].sendData(
  • deluge/event.py

    r5f0f72 r499a58  
    33#
    44# Copyright (C) 2009 Andrew Resch <andrewresch@gmail.com>
    5 # Copyright (C) 2010 Pedro Algarvio <pedro@algarvio.me>
    65#
    76# Deluge is free software.
     
    4948    This metaclass simply keeps a list of all events classes created.
    5049    """
    51     __slots__ = ()
    52 
    5350    def __init__(cls, name, bases, dct):
    5451        super(DelugeEventMetaClass, cls).__init__(name, bases, dct)
     
    6663
    6764    """
    68     __slots__     = ()
    6965    __metaclass__ = DelugeEventMetaClass
    7066
    7167    def _get_name(self):
    7268        return self.__class__.__name__
     69
     70    def _get_args(self):
     71        if not hasattr(self, "_args"):
     72            return []
     73        return self._args
     74
    7375    name = property(fget=_get_name)
    74 
    75     def _get_args(self):
    76         return [getattr(self, arg) for arg in self.__slots__]
    7776    args = property(fget=_get_args)
    7877
    79     def copy(self):
    80         return self.__class__(*self.args)
    81 
    8278class TorrentAddedEvent(DelugeEvent):
    8379    """
    8480    Emitted when a new torrent is successfully added to the session.
    8581    """
    86     __slots__ = ('torrent_id', 'from_state')
    87 
    8882    def __init__(self, torrent_id, from_state):
    8983        """
     
    9387        :type from_state: bool
    9488        """
    95         self.torrent_id = torrent_id
    96         self.from_state = from_state
     89        self._args = [torrent_id, from_state]
    9790
    9891class TorrentRemovedEvent(DelugeEvent):
     
    10093    Emitted when a torrent has been removed from the session.
    10194    """
    102     __slots__ = ('torrent_id',)
    103 
    104     def __init__(self, torrent_id):
    105         """
    106         :param torrent_id: the torrent_id
    107         :type torrent_id: string
    108         """
    109         self.torrent_id = torrent_id
     95    def __init__(self, torrent_id):
     96        """
     97        :param torrent_id: the torrent_id
     98        :type torrent_id: string
     99        """
     100        self._args = [torrent_id]
    110101
    111102class PreTorrentRemovedEvent(DelugeEvent):
     
    113104    Emitted when a torrent is about to be removed from the session.
    114105    """
    115     __slots__ = ('torrent_id',)
    116 
    117     def __init__(self, torrent_id):
    118         """
    119         :param torrent_id: the torrent_id
    120         :type torrent_id: string
    121         """
    122         self.torrent_id = torrent_id
     106    def __init__(self, torrent_id):
     107        """
     108        :param torrent_id: the torrent_id
     109        :type torrent_id: string
     110        """
     111        self._args = [torrent_id]
    123112
    124113class TorrentStateChangedEvent(DelugeEvent):
     
    126115    Emitted when a torrent changes state.
    127116    """
    128     __slots__ = ('torrent_id', 'state')
    129 
    130117    def __init__(self, torrent_id, state):
    131118        """
     
    135122        :type state: string
    136123        """
    137         self.torrent_id = torrent_id
    138         self.state = state
     124        self._args = [torrent_id, state]
    139125
    140126class TorrentQueueChangedEvent(DelugeEvent):
     
    142128    Emitted when the queue order has changed.
    143129    """
     130    pass
    144131
    145132class TorrentFolderRenamedEvent(DelugeEvent):
     
    147134    Emitted when a folder within a torrent has been renamed.
    148135    """
    149     __slots__ = ('torrent_id', 'old', 'new')
    150 
    151136    def __init__(self, torrent_id, old, new):
    152137        """
     
    158143        :type new: string
    159144        """
    160         self.torrent_id = torrent_id
    161         self.old = old
    162         self.new = new
     145        self._args = [torrent_id, old, new]
    163146
    164147class TorrentFileRenamedEvent(DelugeEvent):
     
    166149    Emitted when a file within a torrent has been renamed.
    167150    """
    168     __slots__ = ('torrent_id', 'index', 'filename')
    169 
    170     def __init__(self, torrent_id, index, filename):
     151    def __init__(self, torrent_id, index, name):
    171152        """
    172153        :param torrent_id: the torrent_id
     
    174155        :param index: the index of the file
    175156        :type index: int
    176         :param filename: the new filename
    177         :type filename: string
    178         """
    179         self.torrent_id = torrent_id
    180         self.index = index
    181         self.filename = filename
     157        :param name: the new filename
     158        :type name: string
     159        """
     160        self._args = [torrent_id, index, name]
    182161
    183162class TorrentFinishedEvent(DelugeEvent):
     
    185164    Emitted when a torrent finishes downloading.
    186165    """
    187     __slots__ = ('torrent_id',)
    188 
    189     def __init__(self, torrent_id):
    190         """
    191         :param torrent_id: the torrent_id
    192         :type torrent_id: string
    193         """
    194         self.torrent_id = torrent_id
     166    def __init__(self, torrent_id):
     167        """
     168        :param torrent_id: the torrent_id
     169        :type torrent_id: string
     170        """
     171        self._args = [torrent_id]
    195172
    196173class TorrentResumedEvent(DelugeEvent):
     
    198175    Emitted when a torrent resumes from a paused state.
    199176    """
    200     __slots__ = ('torrent_id',)
    201 
    202     def __init__(self, torrent_id):
    203         """
    204         :param torrent_id: the torrent_id
    205         :type torrent_id: string
    206         """
    207         self.torrent_id = torrent_id
     177    def __init__(self, torrent_id):
     178        """
     179        :param torrent_id: the torrent_id
     180        :type torrent_id: string
     181        """
     182        self._args = [torrent_id]
    208183
    209184class TorrentFileCompletedEvent(DelugeEvent):
     
    214189
    215190    """
    216     __slots__ = ('torrent_id', 'index')
    217 
    218191    def __init__(self, torrent_id, index):
    219192        """
     
    223196        :type index: int
    224197        """
    225         self.torrent_id = torrent_id
    226         self.index = index
     198        self._args = [torrent_id, index]
    227199
    228200class NewVersionAvailableEvent(DelugeEvent):
     
    230202    Emitted when a more recent version of Deluge is available.
    231203    """
    232     __slots__ = ('new_release',)
    233 
    234204    def __init__(self, new_release):
    235205        """
     
    237207        :type new_release: string
    238208        """
    239         self.new_release = new_release
     209        self._args = [new_release]
    240210
    241211class SessionStartedEvent(DelugeEvent):
     
    244214    the daemon is initially started.
    245215    """
     216    pass
    246217
    247218class SessionPausedEvent(DelugeEvent):
     
    249220    Emitted when the session has been paused.
    250221    """
     222    pass
    251223
    252224class SessionResumedEvent(DelugeEvent):
     
    254226    Emitted when the session has been resumed.
    255227    """
     228    pass
    256229
    257230class ConfigValueChangedEvent(DelugeEvent):
     
    259232    Emitted when a config value changes in the Core.
    260233    """
    261     __slots__ = ('key', 'value')
    262 
    263234    def __init__(self, key, value):
    264235        """
     
    267238        :param value: the new value of the `:param:key`
    268239        """
    269         self.key = key
    270         self.value = value
     240        self._args = [key, value]
    271241
    272242class PluginEnabledEvent(DelugeEvent):
     
    274244    Emitted when a plugin is enabled in the Core.
    275245    """
    276     __slots__ = ('plugin_name',)
    277 
    278     def __init__(self, plugin_name):
    279         """
    280         :param plugin_name: the plugin name
    281         :type plugin_name: string
    282         """
    283         self.plugin_name = plugin_name
     246    def __init__(self, name):
     247        self._args = [name]
    284248
    285249class PluginDisabledEvent(DelugeEvent):
     
    287251    Emitted when a plugin is disabled in the Core.
    288252    """
    289     __slots__ = ('plugin_name',)
    290 
    291     def __init__(self, plugin_name):
    292         """
    293         :param plugin_name: the plugin name
    294         :type plugin_name: string
    295         """
    296         self.plugin_name = plugin_name
     253    def __init__(self, name):
     254        self._args = [name]
  • deluge/ui/client.py

    r5f0f72 r499a58  
    4646import deluge.common
    4747import deluge.component as component
    48 from deluge.event import known_events
     48from deluge.log import LOG as log
    4949
    5050if deluge.common.windows_check():
     
    167167
    168168            if message_type == RPC_EVENT:
    169                 event_name = request[1]
     169                event = request[1]
    170170                #log.debug("Received RPCEvent: %s", event)
    171171                # A RPCEvent was received from the daemon so run any handlers
    172172                # associated with it.
    173                 if event_name in self.factory.event_handlers:
    174                     event = known_events[event_name](*request[2])
    175                     for handler in self.factory.event_handlers[event_name]:
    176                         reactor.callLater(0, handler, event.copy())
     173                if event in self.factory.event_handlers:
     174                    for handler in self.factory.event_handlers[event]:
     175                        reactor.callLater(0, handler, *request[2])
    177176                continue
    178177
  • deluge/ui/console/eventlog.py

    r5f0f72 r499a58  
    6363        client.register_event_handler("PluginDisabledEvent", self.on_plugin_disabled_event)
    6464
    65     def on_torrent_added_event(self, event):
     65    def on_torrent_added_event(self, torrent_id, from_state):
    6666        def on_torrent_status(status):
    6767            self.console.write(self.prefix + "TorrentAdded(from_state=%s): {!info!}%s (%s)" % (
    68                 event.from_state, status["name"], event.torrent_id)
     68                from_state, status["name"], torrent_id)
    6969            )
    70         client.core.get_torrent_status(event.torrent_id, ["name"]).addCallback(on_torrent_status)
     70        client.core.get_torrent_status(torrent_id, ["name"]).addCallback(on_torrent_status)
    7171
    72     def on_torrent_removed_event(self, event):
     72    def on_torrent_removed_event(self, torrent_id):
    7373        self.console.write(self.prefix + "TorrentRemoved: {!info!}%s (%s)" %
    74             (self.console.get_torrent_name(event.torrent_id), event.torrent_id))
     74            (self.console.get_torrent_name(torrent_id), torrent_id))
    7575
    76     def on_torrent_state_changed_event(self, event):
     76    def on_torrent_state_changed_event(self, torrent_id, state):
    7777        # Modify the state string color
    78         if event.state in colors.state_color:
    79             state = colors.state_color[event.state] + event.state
     78        if state in colors.state_color:
     79            state = colors.state_color[state] + state
    8080
    8181        self.console.write(self.prefix + "TorrentStateChanged: %s {!info!}%s (%s)" %
    82             (state, self.console.get_torrent_name(event.torrent_id), event.torrent_id))
     82            (state, self.console.get_torrent_name(torrent_id), torrent_id))
    8383
    84     def on_torrent_paused_event(self, event):
     84    def on_torrent_paused_event(self, torrent_id):
    8585        self.console.write(self.prefix + "TorrentPaused: {!info!}%s (%s)" %
    86             (self.console.get_torrent_name(event.torrent_id), event.torrent_id))
     86            (self.console.get_torrent_name(torrent_id), torrent_id))
    8787
    88     def on_torrent_finished_event(self, event):
     88    def on_torrent_finished_event(self, torrent_id):
    8989        self.console.write(self.prefix + "TorrentFinished: {!info!}%s (%s)" %
    90             (self.console.get_torrent_name(event.torrent_id), event.torrent_id))
     90            (self.console.get_torrent_name(torrent_id), torrent_id))
    9191
    92     def on_new_version_available_event(self, event):
     92    def on_new_version_available_event(self, version):
    9393        self.console.write(self.prefix + "NewVersionAvailable: {!info!}%s" %
    94             (event.new_release))
     94            (version))
    9595
    96     def on_session_paused_event(self, event):
     96    def on_session_paused_event(self):
    9797        self.console.write(self.prefix + "SessionPaused")
    9898
    99     def on_session_resumed_event(self, event):
     99    def on_session_resumed_event(self):
    100100        self.console.write(self.prefix + "SessionResumed")
    101101
    102     def on_config_value_changed_event(self, event):
     102    def on_config_value_changed_event(self, key, value):
    103103        color = "{!white,black,bold!}"
    104         if type(event.value) in colors.type_color:
    105             color = colors.type_color[type(event.value)]
     104        if type(value) in colors.type_color:
     105            color = colors.type_color[type(value)]
    106106
    107107        self.console.write(self.prefix + "ConfigValueChanged: {!input!}%s: %s%s" %
    108             (event.key, color, event.value))
     108            (key, color, value))
    109109
    110     def on_plugin_enabled_event(self, event):
    111         self.console.write(self.prefix + "PluginEnabled: {!info!}%s" % event.plugin_name)
     110    def on_plugin_enabled_event(self, name):
     111        self.console.write(self.prefix + "PluginEnabled: {!info!}%s" % name)
    112112
    113     def on_plugin_disabled_event(self, event):
    114         self.console.write(self.prefix + "PluginDisabled: {!info!}%s" % event.plugin_name)
     113    def on_plugin_disabled_event(self, name):
     114        self.console.write(self.prefix + "PluginDisabled: {!info!}%s" % name)
  • deluge/ui/console/main.py

    r5f0f72 r499a58  
    3535#
    3636
    37 import os
    38 import sys
    39 import logging
     37import os, sys
    4038import optparse
    4139import shlex
     
    4442from twisted.internet import defer, reactor
    4543
     44from deluge.ui.console import UI_PATH
    4645import deluge.component as component
    4746from deluge.ui.client import client
    4847import deluge.common
    4948from deluge.ui.coreconfig import CoreConfig
    50 from deluge.ui.sessionproxy import SessionProxy
    5149from deluge.ui.console.statusbars import StatusBars
    5250from deluge.ui.console.eventlog import EventLog
    53 #import screen
     51import screen
    5452import colors
     53from deluge.log import LOG as log
    5554from deluge.ui.ui import _UI
    56 from deluge.ui.console import UI_PATH
    57 
    58 log = logging.getLogger(__name__)
    5955
    6056class Console(_UI):
     
    6460    def __init__(self):
    6561        super(Console, self).__init__("console")
    66         group = optparse.OptionGroup(self.parser, "Console Options","These options control how "
    67                                      "the console connects to the daemon.  These options will be "
    68                                      "used if you pass a command, or if you have autoconnect "
    69                                      "enabled for the console ui.")
    70 
    71         group.add_option("-d","--daemon",dest="daemon_addr",
    72                          action="store",type="str",default="127.0.0.1",
    73                          help="Set the address of the daemon to connect to."
    74                               " [default: %default]")
    75         group.add_option("-p","--port",dest="daemon_port",
    76                          help="Set the port to connect to the daemon on. [default: %default]",
    77                          action="store",type="int",default=58846)
    78         group.add_option("-u","--username",dest="daemon_user",
    79                          help="Set the username to connect to the daemon with. [default: %default]",
    80                          action="store",type="string")
    81         group.add_option("-P","--password",dest="daemon_pass",
    82                          help="Set the password to connect to the daemon with. [default: %default]",
    83                          action="store",type="string")
     62        cmds = load_commands(os.path.join(UI_PATH, 'commands'))
     63
     64        group = optparse.OptionGroup(self.parser, "Console Commands",
     65            "\n".join(cmds.keys()))
    8466        self.parser.add_option_group(group)
    85 
    86         self.cmds = load_commands(os.path.join(UI_PATH, 'commands'))
    87         class CommandOptionGroup(optparse.OptionGroup):
    88             def __init__(self, parser, title, description=None, cmds = None):
    89                 optparse.OptionGroup.__init__(self,parser,title,description)
    90                 self.cmds = cmds
    91 
    92             def format_help(self, formatter):
    93                 result = formatter.format_heading(self.title)
    94                 formatter.indent()
    95                 if self.description:
    96                     result += "%s\n"%formatter.format_description(self.description)
    97                 for cname in self.cmds:
    98                     cmd = self.cmds[cname]
    99                     if cmd.interactive_only or cname in cmd.aliases: continue
    100                     allnames = [cname]
    101                     allnames.extend(cmd.aliases)
    102                     cname = "/".join(allnames)
    103                     result += formatter.format_heading(" - ".join([cname,cmd.__doc__]))
    104                     formatter.indent()
    105                     result += "%*s%s\n" % (formatter.current_indent, "", cmd.usage)
    106                     formatter.dedent()
    107                 formatter.dedent()
    108                 return result
    109         cmd_group = CommandOptionGroup(self.parser, "Console Commands",
    110                                        description="The following commands can be issued at the "
    111                                        "command line.  Commands should be quoted, so, for example, "
    112                                        "to pause torrent with id 'abc' you would run: '%s "
    113                                        "\"pause abc\"'"%os.path.basename(sys.argv[0]),
    114                                        cmds=self.cmds)
    115         self.parser.add_option_group(cmd_group)
    11667
    11768    def start(self):
    11869        super(Console, self).start()
    119         ConsoleUI(self.args,self.cmds,(self.options.daemon_addr,
    120                   self.options.daemon_port,self.options.daemon_user,
    121                   self.options.daemon_pass))
     70
     71        ConsoleUI(self.args)
    12272
    12373def start():
     
    14090        raise Exception(msg)
    14191
    142 
    14392class BaseCommand(object):
    14493
    14594    usage = 'usage'
    146     interactive_only = False
    14795    option_list = tuple()
    14896    aliases = []
     
    171119                            epilog = self.epilog,
    172120                            option_list = self.option_list)
    173 
    174121
    175122def load_commands(command_dir, exclude=[]):
     
    193140        return {}
    194141
    195 
    196142class ConsoleUI(component.Component):
    197     def __init__(self, args=None, cmds = None, daemon = None):
     143    def __init__(self, args=None):
    198144        component.Component.__init__(self, "ConsoleUI", 2)
    199145
    200         # keep track of events for the log view
    201         self.events = []
     146        self.batch_write = False
    202147
    203148        try:
     
    208153
    209154        log.debug("Using encoding: %s", self.encoding)
    210 
    211 
    212         # start up the session proxy
    213         self.sessionproxy = SessionProxy()
     155        # Load all the commands
     156        self._commands = load_commands(os.path.join(UI_PATH, 'commands'))
    214157
    215158        client.set_disconnect_callback(self.on_client_disconnect)
     
    220163            args = args[0]
    221164            self.interactive = False
    222             if not cmds:
    223                 print "Sorry, couldn't find any commands"
    224                 return
    225             else:
    226                 self._commands = cmds
    227                 from commander import Commander
    228                 cmdr = Commander(cmds)
    229                 if daemon:
    230                     cmdr.exec_args(args,*daemon)
    231                 else:
    232                     cmdr.exec_args(args,None,None,None,None)
    233                
     165
     166        # Try to connect to the localhost daemon
     167        def on_connect(result):
     168            def on_started(result):
     169                if not self.interactive:
     170                    def on_started(result):
     171                        deferreds = []
     172                        # If we have args, lets process them and quit
     173                        # allow multiple commands split by ";"
     174                        for arg in args.split(";"):
     175                            deferreds.append(defer.maybeDeferred(self.do_command, arg.strip()))
     176
     177                        def on_complete(result):
     178                            self.do_command("quit")
     179
     180                        dl = defer.DeferredList(deferreds).addCallback(on_complete)
     181
     182                    # We need to wait for the rpcs in start() to finish before processing
     183                    # any of the commands.
     184                    self.started_deferred.addCallback(on_started)
     185            component.start().addCallback(on_started)
     186
     187        d = client.connect()
     188        d.addCallback(on_connect)
    234189
    235190        self.coreconfig = CoreConfig()
     
    240195            curses.wrapper(self.run)
    241196        elif self.interactive and deluge.common.windows_check():
    242             print """\nDeluge-console does not run in interactive mode on Windows. \n
    243 Please use commands from the command line, eg:\n
    244     deluge-console.exe help
    245     deluge-console.exe info
    246     deluge-console.exe "add --help"
    247     deluge-console.exe "add -p c:\\mytorrents c:\\new.torrent"
    248             """
     197            print "You cannot run the deluge-console in interactive mode in Windows.\
     198            Please use commands from the command line, eg: deluge-console config;help;exit"
    249199        else:
    250200            reactor.run()
     
    261211        # pass it the function that handles commands
    262212        colors.init_colors()
     213        self.screen = screen.Screen(stdscr, self.do_command, self.tab_completer, self.encoding)
    263214        self.statusbars = StatusBars()
    264         from modes.connectionmanager import ConnectionManager
    265         self.screen = ConnectionManager(stdscr, self.encoding)
    266215        self.eventlog = EventLog()
    267216
     
    277226        reactor.run()
    278227
    279 
    280228    def start(self):
     229        # This gets fired once we have received the torrents list from the core
     230        self.started_deferred = defer.Deferred()
     231
    281232        # Maintain a list of (torrent_id, name) for use in tab completion
    282233        self.torrents = []
    283         if not self.interactive:
    284             self.started_deferred = defer.Deferred()
    285             def on_session_state(result):
    286                 def on_torrents_status(torrents):
    287                     for torrent_id, status in torrents.items():
    288                         self.torrents.append((torrent_id, status["name"]))
    289                     self.started_deferred.callback(True)
    290 
    291                 client.core.get_torrents_status({"id": result}, ["name"]).addCallback(on_torrents_status)
    292             client.core.get_session_state().addCallback(on_session_state)
    293 
    294            
     234        def on_session_state(result):
     235            def on_torrents_status(torrents):
     236                for torrent_id, status in torrents.items():
     237                    self.torrents.append((torrent_id, status["name"]))
     238                self.started_deferred.callback(True)
     239
     240            client.core.get_torrents_status({"id": result}, ["name"]).addCallback(on_torrents_status)
     241        client.core.get_session_state().addCallback(on_session_state)
     242
     243        # Register some event handlers to keep the torrent list up-to-date
     244        client.register_event_handler("TorrentAddedEvent", self.on_torrent_added_event)
     245        client.register_event_handler("TorrentRemovedEvent", self.on_torrent_removed_event)
     246
     247    def update(self):
     248        pass
     249
     250    def set_batch_write(self, batch):
     251        """
     252        When this is set the screen is not refreshed after a `:meth:write` until
     253        this is set to False.
     254
     255        :param batch: set True to prevent screen refreshes after a `:meth:write`
     256        :type batch: bool
     257
     258        """
     259        self.batch_write = batch
     260        if not batch and self.interactive:
     261            self.screen.refresh()
     262
     263    def write(self, line):
     264        """
     265        Writes a line out depending on if we're in interactive mode or not.
     266
     267        :param line: str, the line to print
     268
     269        """
     270        if self.interactive:
     271            self.screen.add_line(line, not self.batch_write)
     272        else:
     273            print(colors.strip_colors(line))
     274
     275    def do_command(self, cmd):
     276        """
     277        Processes a command.
     278
     279        :param cmd: str, the command string
     280
     281        """
     282        if not cmd:
     283            return
     284        cmd, _, line = cmd.partition(' ')
     285        try:
     286            parser = self._commands[cmd].create_parser()
     287        except KeyError:
     288            self.write("{!error!}Unknown command: %s" % cmd)
     289            return
     290        args = self._commands[cmd].split(line)
     291
     292        # Do a little hack here to print 'command --help' properly
     293        parser._print_help = parser.print_help
     294        def print_help(f=None):
     295            if self.interactive:
     296                self.write(parser.format_help())
     297            else:
     298                parser._print_help(f)
     299        parser.print_help = print_help
     300
     301        # Only these commands can be run when not connected to a daemon
     302        not_connected_cmds = ["help", "connect", "quit"]
     303        aliases = []
     304        for c in not_connected_cmds:
     305            aliases.extend(self._commands[c].aliases)
     306        not_connected_cmds.extend(aliases)
     307
     308        if not client.connected() and cmd not in not_connected_cmds:
     309            self.write("{!error!}Not connected to a daemon, please use the connect command first.")
     310            return
     311
     312        try:
     313            options, args = parser.parse_args(args)
     314        except Exception, e:
     315            self.write("{!error!}Error parsing options: %s" % e)
     316            return
     317
     318        if not getattr(options, '_exit', False):
     319            try:
     320                ret = self._commands[cmd].handle(*args, **options.__dict__)
     321            except Exception, e:
     322                self.write("{!error!}" + str(e))
     323                log.exception(e)
     324                import traceback
     325                self.write("%s" % traceback.format_exc())
     326                return defer.succeed(True)
     327            else:
     328                return ret
     329
     330    def tab_completer(self, line, cursor, second_hit):
     331        """
     332        Called when the user hits 'tab' and will autocomplete or show options.
     333        If a command is already supplied in the line, this function will call the
     334        complete method of the command.
     335
     336        :param line: str, the current input string
     337        :param cursor: int, the cursor position in the line
     338        :param second_hit: bool, if this is the second time in a row the tab key
     339            has been pressed
     340
     341        :returns: 2-tuple (string, cursor position)
     342
     343        """
     344        # First check to see if there is no space, this will mean that it's a
     345        # command that needs to be completed.
     346        if " " not in line:
     347            possible_matches = []
     348            # Iterate through the commands looking for ones that startwith the
     349            # line.
     350            for cmd in self._commands:
     351                if cmd.startswith(line):
     352                    possible_matches.append(cmd + " ")
     353
     354            line_prefix = ""
     355        else:
     356            cmd = line.split(" ")[0]
     357            if cmd in self._commands:
     358                # Call the command's complete method to get 'er done
     359                possible_matches = self._commands[cmd].complete(line.split(" ")[-1])
     360                line_prefix = " ".join(line.split(" ")[:-1]) + " "
     361            else:
     362                # This is a bogus command
     363                return (line, cursor)
     364
     365        # No matches, so just return what we got passed
     366        if len(possible_matches) == 0:
     367            return (line, cursor)
     368        # If we only have 1 possible match, then just modify the line and
     369        # return it, else we need to print out the matches without modifying
     370        # the line.
     371        elif len(possible_matches) == 1:
     372            new_line = line_prefix + possible_matches[0]
     373            return (new_line, len(new_line))
     374        else:
     375            if second_hit:
     376                # Only print these out if it's a second_hit
     377                self.write(" ")
     378                for match in possible_matches:
     379                    self.write(match)
     380            else:
     381                p = " ".join(line.split(" ")[:-1])
     382                new_line = " ".join([p, os.path.commonprefix(possible_matches)])
     383                if len(new_line) > len(line):
     384                    line = new_line
     385                    cursor = len(line)
     386            return (line, cursor)
     387
     388    def tab_complete_torrent(self, line):
     389        """
     390        Completes torrent_ids or names.
     391
     392        :param line: str, the string to complete
     393
     394        :returns: list of matches
     395
     396        """
     397
     398        possible_matches = []
     399
     400        # Find all possible matches
     401        for torrent_id, torrent_name in self.torrents:
     402            if torrent_id.startswith(line):
     403                possible_matches.append(torrent_id + " ")
     404            if torrent_name.startswith(line):
     405                possible_matches.append(torrent_name + " ")
     406
     407        return possible_matches
     408
     409    def get_torrent_name(self, torrent_id):
     410        """
     411        Gets a torrent name from the torrents list.
     412
     413        :param torrent_id: str, the torrent_id
     414
     415        :returns: the name of the torrent or None
     416        """
     417
     418        for tid, name in self.torrents:
     419            if torrent_id == tid:
     420                return name
     421
     422        return None
     423
    295424    def match_torrent(self, string):
    296425        """
     
    311440        return ret
    312441
    313 
    314     def get_torrent_name(self, torrent_id):
    315         if self.interactive and hasattr(self.screen,"get_torrent_name"):
    316             return self.screen.get_torrent_name(torrent_id)
    317 
    318         for tid, name in self.torrents:
    319             if torrent_id == tid:
    320                 return name
    321        
    322         return None
    323 
    324 
    325     def set_batch_write(self, batch):
    326         # only kept for legacy reasons, don't actually do anything
    327         pass
    328 
    329     def set_mode(self, mode):
    330         reactor.removeReader(self.screen)
    331         self.screen = mode
    332         self.statusbars.screen = self.screen
    333         reactor.addReader(self.screen)
     442    def on_torrent_added_event(self, event):
     443        def on_torrent_status(status):
     444            self.torrents.append((event.torrent_id, status["name"]))
     445        client.core.get_torrent_status(event.torrent_id, ["name"]).addCallback(on_torrent_status)
     446
     447    def on_torrent_removed_event(self, event):
     448        for index, (tid, name) in enumerate(self.torrents):
     449            if event.torrent_id == tid:
     450                del self.torrents[index]
    334451
    335452    def on_client_disconnect(self):
    336453        component.stop()
    337 
    338     def write(self, s):
    339         if self.interactive:
    340             self.events.append(s)
    341         else:
    342             print colors.strip_colors(s)
  • deluge/ui/coreconfig.py

    r5f0f72 r499a58  
    4646        component.Component.__init__(self, "CoreConfig")
    4747        self.config = {}
    48         def on_configvaluechanged_event(event):
    49             self.config[event.key] = event.value
     48        def on_configvaluechanged_event(key, value):
     49            self.config[key] = value
    5050        client.register_event_handler("ConfigValueChangedEvent", on_configvaluechanged_event)
    5151
  • deluge/ui/gtkui/files_tab.py

    r5f0f72 r499a58  
    628628        self._editing_index = None
    629629
    630     def _on_torrentfilerenamed_event(self, event):
    631         log.debug("index: %s name: %s", event.index, event.filename)
    632 
    633         if event.torrent_id not in self.files_list:
     630    def _on_torrentfilerenamed_event(self, torrent_id, index, name):
     631        log.debug("index: %s name: %s", index, name)
     632
     633        if torrent_id not in self.files_list:
    634634            return
    635635
    636         old_name = self.files_list[event.torrent_id][event.index]["path"]
    637         self.files_list[event.torrent_id][event.index]["path"] = event.filename
     636        old_name = self.files_list[torrent_id][index]["path"]
     637        self.files_list[torrent_id][index]["path"] = name
    638638
    639639        # We need to update the filename displayed if we're currently viewing
    640640        # this torrents files.
    641         if event.torrent_id == self.torrent_id:
     641        if torrent_id == self.torrent_id:
    642642            old_name_len = len(old_name.split("/"))
    643             name_len = len(event.filename.split("/"))
     643            name_len = len(name.split("/"))
    644644            if old_name_len != name_len:
    645645                # The parent path list changes depending on which way the file
     
    648648                    parent_path = [o for o in old_name.split("/")[:-1]]
    649649                else:
    650                     parent_path = [o for o in event.filename.split("/")[:-1]]
     650                    parent_path = [o for o in name.split("/")[:-1]]
    651651                # Find the iter to the parent folder we need to add a new folder
    652652                # to.
     
    655655                        if len(parent_path) == 1:
    656656                            # This is the parent iter
    657                             to_create = event.filename.split("/")[len(old_name.split("/")[:-1]):-1]
     657                            to_create = name.split("/")[len(old_name.split("/")[:-1]):-1]
    658658                            parent_iter = itr
    659659
     
    674674                            # Find the iter for the file that needs to be moved
    675675                            def get_file_iter(model, path, itr, user_data):
    676                                 if model[itr][5] == event.index:
    677                                     model[itr][0] = event.filename.split("/")[-1]
     676                                if model[itr][5] == index:
     677                                    model[itr][0] = name.split("/")[-1]
    678678                                    t = self.treestore.append(
    679679                                        parent_iter,
     
    694694                    self.treestore.foreach(find_parent, None)
    695695                else:
    696                     new_folders = event.filename.split("/")[:-1]
     696                    new_folders = name.split("/")[:-1]
    697697                    parent_iter = None
    698698                    for f in new_folders:
     
    708708                # This is just changing a filename without any folder changes
    709709                def set_file_name(model, path, itr, user_data):
    710                     if model[itr][5] == event.index:
    711                         model[itr][0] = os.path.split(event.filename)[-1]
     710                    if model[itr][5] == index:
     711                        model[itr][0] = os.path.split(name)[-1]
    712712                        return True
    713713                self.treestore.foreach(set_file_name, None)
     
    755755            itr = parent
    756756
    757     def _on_torrentfolderrenamed_event(self, event):
     757    def _on_torrentfolderrenamed_event(self, torrent_id, old_folder, new_folder):
    758758        log.debug("on_torrent_folder_renamed_signal")
    759         log.debug("old_folder: %s new_folder: %s", event.old, event.new)
    760 
    761         if event.torrent_id not in self.files_list:
     759        log.debug("old_folder: %s new_folder: %s", old_folder, new_folder)
     760
     761        if torrent_id not in self.files_list:
    762762            return
    763763
    764         if event.old[-1] != "/":
    765             event.old += "/"
    766         if event.new[-1] != "/":
    767             event.new += "/"
    768 
    769         for fd in self.files_list[event.torrent_id]:
    770             if fd["path"].startswith(event.old):
    771                 fd["path"] = fd["path"].replace(event.old, event.new, 1)
    772 
    773         if event.torrent_id == self.torrent_id:
    774 
    775             old_split = event.old.split("/")
     764        if old_folder[-1] != "/":
     765            old_folder += "/"
     766        if new_folder[-1] != "/":
     767            new_folder += "/"
     768
     769        for fd in self.files_list[torrent_id]:
     770            if fd["path"].startswith(old_folder):
     771                fd["path"] = fd["path"].replace(old_folder, new_folder, 1)
     772
     773        if torrent_id == self.torrent_id:
     774
     775            old_split = old_folder.split("/")
    776776            try:
    777777                old_split.remove("")
     
    779779                pass
    780780
    781             new_split = event.new.split("/")
     781            new_split = new_folder.split("/")
    782782            try:
    783783                new_split.remove("")
     
    785785                pass
    786786
    787             old_folder_iter = self.get_iter_at_path(event.old)
     787            old_folder_iter = self.get_iter_at_path(old_folder)
    788788            old_folder_iter_parent = self.treestore.iter_parent(old_folder_iter)
    789789
    790             new_folder_iter = self.get_iter_at_path(event.new)
     790            new_folder_iter = self.get_iter_at_path(new_folder)
    791791            if len(new_split) == len(old_split):
    792792                # These are at the same tree depth, so it's a simple rename
     
    808808            self.remove_childless_folders(old_folder_iter_parent)
    809809
    810     def _on_torrentremoved_event(self, event):
    811         if event.torrent_id in self.files_list:
    812             del self.files_list[event.torrent_id]
     810    def _on_torrentremoved_event(self, torrent_id):
     811        if torrent_id in self.files_list:
     812            del self.files_list[torrent_id]
    813813
    814814    def _on_drag_data_get_data(self, treeview, context, selection, target_id, etime):
  • deluge/ui/gtkui/mainwindow.py

    r5f0f72 r499a58  
    248248            self.window.set_title("Deluge")
    249249
    250     def on_newversionavailable_event(self, event):
     250    def on_newversionavailable_event(self, new_version):
    251251        if self.config["show_new_releases"]:
    252252            from deluge.ui.gtkui.new_release_dialog import NewReleaseDialog
    253             reactor.callLater(5.0, NewReleaseDialog().show, event.new_release)
    254 
    255     def on_torrentfinished_event(self, event):
     253            reactor.callLater(5.0, NewReleaseDialog().show, new_version)
     254
     255    def on_torrentfinished_event(self, torrent_id):
    256256        from deluge.ui.gtkui.notification import Notification
    257         Notification().notify(event.torrent_id)
     257        Notification().notify(torrent_id)
  • deluge/ui/gtkui/menubar.py

    r5f0f72 r499a58  
    231231
    232232    ### Callbacks ###
    233     def on_torrentstatechanged_event(self, event):
    234         if event.state == "Paused":
     233    def on_torrentstatechanged_event(self, torrent_id, state):
     234        if state == "Paused":
    235235            self.update_menu()
    236236
    237     def on_torrentresumed_event(self, event):
     237    def on_torrentresumed_event(self, torrent_id):
    238238        self.update_menu()
    239239
  • deluge/ui/gtkui/pluginmanager.py

    r5f0f72 r499a58  
    9292            self.enable_plugin(plugin)
    9393
    94     def _on_plugin_enabled_event(self, event):
    95         self.enable_plugin(event.plugin_name)
     94    def _on_plugin_enabled_event(self, name):
     95        self.enable_plugin(name)
    9696
    97     def _on_plugin_disabled_event(self, event):
    98         self.disable_plugin(event.plugin_name)
     97    def _on_plugin_disabled_event(self, name):
     98        self.disable_plugin(name)
    9999
    100100    ## Hook functions
  • deluge/ui/gtkui/statusbar.py

    r5f0f72 r499a58  
    289289        client.core.get_free_space().addCallback(self._on_get_free_space)
    290290
    291     def on_configvaluechanged_event(self, event):
     291    def on_configvaluechanged_event(self, key, value):
    292292        """
    293293        This is called when we receive a ConfigValueChangedEvent from
     
    295295        """
    296296
    297         if event.key in self.config_value_changed_dict.keys():
    298             self.config_value_changed_dict[event.key](event.value)
     297        if key in self.config_value_changed_dict.keys():
     298            self.config_value_changed_dict[key](value)
    299299
    300300    def _on_max_connections_global(self, max_connections):
  • deluge/ui/gtkui/systemtray.py

    r5f0f72 r499a58  
    211211            "payload_download_rate"]).addCallback(self._on_get_session_status)
    212212
    213     def config_value_changed(self, event):
     213    def config_value_changed(self, key, value):
    214214        """This is called when we received a config_value_changed signal from
    215215        the core."""
    216216
    217         if event.key in self.config_value_changed_dict.keys():
    218             self.config_value_changed_dict[event.key](event.value)
     217        if key in self.config_value_changed_dict.keys():
     218            self.config_value_changed_dict[key](value)
    219219
    220220    def _on_max_download_speed(self, max_download_speed):
  • deluge/ui/gtkui/torrentview.py

    r5f0f72 r499a58  
    522522        widget.stop_emission("drag-drop")
    523523
    524     def on_torrentadded_event(self, event):
    525         self.add_row(event.torrent_id)
    526         self.mark_dirty(event.torrent_id)
    527 
    528     def on_torrentremoved_event(self, event):
    529         self.remove_row(event.torrent_id)
    530 
    531     def on_torrentstatechanged_event(self, event):
     524    def on_torrentadded_event(self, torrent_id, from_state):
     525        self.add_row(torrent_id)
     526        self.mark_dirty(torrent_id)
     527
     528    def on_torrentremoved_event(self, torrent_id):
     529        self.remove_row(torrent_id)
     530
     531    def on_torrentstatechanged_event(self, torrent_id, state):
    532532        # Update the torrents state
    533533        for row in self.liststore:
    534             if not event.torrent_id == row[self.columns["torrent_id"].column_indices[0]]:
     534            if not torrent_id == row[self.columns["torrent_id"].column_indices[0]]:
    535535                continue
    536             row[self.get_column_index(_("Progress"))[1]] = event.state
    537 
    538         self.mark_dirty(event.torrent_id)
    539 
    540     def on_sessionpaused_event(self, event):
     536            row[self.get_column_index(_("Progress"))[1]] = state
     537
     538        self.mark_dirty(torrent_id)
     539
     540    def on_sessionpaused_event(self):
    541541        self.mark_dirty()
    542542        self.update()
    543543
    544     def on_sessionresumed_event(self, event):
     544    def on_sessionresumed_event(self):
    545545        self.mark_dirty()
    546546        self.update()
    547547
    548     def on_torrentqueuechanged_event(self, event):
     548    def on_torrentqueuechanged_event(self):
    549549        self.mark_dirty()
    550550        self.update()
  • deluge/ui/sessionproxy.py

    r5f0f72 r499a58  
    237237            return d.addCallback(on_status, None, keys)
    238238
    239     def on_torrent_state_changed(self, event):
    240         if event.torrent_id in self.torrents:
    241             self.torrents[event.torrent_id][1]["state"] = event.state
    242             self.cache_times[event.torrent_id]["state"] = time.time()
    243 
    244     def on_torrent_added(self, event):
    245         self.torrents[event.torrent_id] = [time.time() - self.cache_time - 1, {}]
    246         self.cache_times[event.torrent_id] = {}
     239    def on_torrent_state_changed(self, torrent_id, state):
     240        if torrent_id in self.torrents:
     241            self.torrents[torrent_id][1]["state"] = state
     242            self.cache_times[torrent_id]["state"] = time.time()
     243
     244    def on_torrent_added(self, torrent_id, from_state):
     245        self.torrents[torrent_id] = [time.time() - self.cache_time - 1, {}]
     246        self.cache_times[torrent_id] = {}
    247247        def on_status(status):
    248             self.torrents[event.torrent_id][1].update(status)
     248            self.torrents[torrent_id][1].update(status)
    249249            t = time.time()
    250250            for key in status:
    251                 self.cache_times[event.torrent_id][key] = t
    252         client.core.get_torrent_status(event.torrent_id, []).addCallback(on_status)
    253 
    254     def on_torrent_removed(self, event):
    255         del self.torrents[event.torrent_id]
    256         del self.cache_times[event.torrent_id]
     251                self.cache_times[torrent_id][key] = t
     252        client.core.get_torrent_status(torrent_id, []).addCallback(on_status)
     253
     254    def on_torrent_removed(self, torrent_id):
     255        del self.torrents[torrent_id]
     256        del self.cache_times[torrent_id]
  • deluge/ui/web/pluginmanager.py

    r5f0f72 r499a58  
    5959        "script_directories": directories
    6060    }
    61 
     61   
    6262class PluginManager(PluginManagerBase, component.Component):
    6363    def __init__(self):
     
    6565        self.config = ConfigManager("web.conf")
    6666        PluginManagerBase.__init__(self, "web.conf", "deluge.plugin.web")
    67 
     67       
    6868        client.register_event_handler("PluginEnabledEvent", self._on_plugin_enabled_event)
    6969        client.register_event_handler("PluginDisabledEvent", self._on_plugin_disabled_event)
    70 
     70   
    7171    def _on_get_enabled_plugins(self, plugins):
    7272        for plugin in plugins:
    7373            self.enable_plugin(plugin)
     74   
     75    def _on_plugin_enabled_event(self, name):
     76        self.enable_plugin(name)
    7477
    75     def _on_plugin_enabled_event(self, event):
    76         self.enable_plugin(event.plugin_name)
    77 
    78     def _on_plugin_disabled_event(self, event):
    79         self.disable_plugin(event.plugin_name)
    80 
     78    def _on_plugin_disabled_event(self, name):
     79        self.disable_plugin(name)
     80   
    8181    def disable_plugin(self, name):
    8282        # Get the plugin instance
     
    8686            log.info("Plugin has no web ui")
    8787            return
    88 
     88       
    8989        info = gather_info(plugin)
    9090
     
    9292        for script in info["scripts"]:
    9393            scripts.remove_script("%s/%s" % (name.lower(), os.path.basename(script).lower()))
    94 
     94       
    9595        for script in info["debug_scripts"]:
    9696            scripts.remove_script("%s/%s" % (name.lower(), os.path.basename(script).lower()), "debug")
    9797            scripts.remove_script("%s/%s" % (name.lower(), os.path.basename(script).lower()), "dev")
    98 
     98       
    9999        super(PluginManager, self).disable_plugin(name)
    100 
     100   
    101101    def enable_plugin(self, name):
    102102        super(PluginManager, self).enable_plugin(name)
    103 
     103       
    104104        # Get the plugin instance
    105105        try:
     
    108108            log.info("Plugin has no web ui")
    109109            return
    110 
     110       
    111111        info = gather_info(plugin)
    112 
     112       
    113113        scripts = component.get("Scripts")
    114114        for script in info["scripts"]:
     
    128128        d = client.core.get_enabled_plugins()
    129129        d.addCallback(self._on_get_enabled_plugins)
    130 
     130   
    131131    def stop(self):
    132132        """
     
    134134        """
    135135        self.disable_plugins()
    136 
     136   
    137137    def update(self):
    138138        pass
    139 
     139   
    140140    def get_plugin_resources(self, name):
    141141        # Get the plugin instance
Note: See TracChangeset for help on using the changeset viewer.