Example #1
0
File: ui.py Project: np/alot
    def _input_filter(self, keys, raw):
        """
        handles keypresses.
        This function gets triggered directly by class:`urwid.MainLoop`
        upon user input and is supposed to pass on its `keys` parameter
        to let the root widget handle keys. We intercept the input here
        to trigger custom commands as defined in our keybindings.
        """
        logging.debug("Got key (%s, %s)" % (keys, raw))
        # work around: escape triggers this twice, with keys = raw = []
        # the first time..
        if not keys:
            return
        # let widgets handle input if key is virtual window resize keypress
        # or we are in "passall" mode
        elif 'window resize' in keys or self._passall:
            return keys
        # end "lockdown" mode if the right key was pressed
        elif self._locked and keys[0] == self._unlock_key:
            self._locked = False
            self.mainloop.widget = self.root_widget
            if callable(self._unlock_callback):
                self._unlock_callback()
        # otherwise interpret keybinding
        else:
            # define callback that resets input queue
            def clear(*args):
                if self._alarm is not None:
                    self.mainloop.remove_alarm(self._alarm)
                self.input_queue = []
                self.update()

            key = keys[0]
            self.input_queue.append(key)
            keyseq = ' '.join(self.input_queue)
            candidates = settings.get_mapped_input_keysequences(self.mode,
                                                                prefix=keyseq)
            if keyseq in candidates:
                # case: current input queue is a mapped keysequence
                # get binding and interpret it if non-null
                cmdline = settings.get_keybinding(self.mode, keyseq)
                if cmdline:
                    clear()
                    logging.debug("cmdline: '%s'" % cmdline)
                    # move keys are always passed
                    if cmdline.startswith('move '):
                        movecmd = cmdline[5:].rstrip()
                        logging.debug("GOT MOVE: '%s'" % movecmd)
                        if movecmd in ['up', 'down', 'page up', 'page down']:
                            return [movecmd]
                    elif not self._locked:
                        try:
                            self.apply_commandline(cmdline)
                        except CommandParseError, e:
                            self.notify(e.message, priority='error')
            elif not candidates:
                # case: no sequence with prefix keyseq is mapped
                # just clear the input queue
                clear()
Example #2
0
File: ui.py Project: fagga/alot
    def _input_filter(self, keys, raw):
        """
        handles keypresses.
        This function gets triggered directly by class:`urwid.MainLoop`
        upon user input and is supposed to pass on its `keys` parameter
        to let the root widget handle keys. We intercept the input here
        to trigger custom commands as defined in our keybindings.
        """
        logging.debug("Got key (%s, %s)" % (keys, raw))
        # work around: escape triggers this twice, with keys = raw = []
        # the first time..
        if not keys:
            return
        # let widgets handle input if key is virtual window resize keypress
        # or we are in "passall" mode
        elif 'window resize' in keys or self._passall:
            return keys
        # end "lockdown" mode if the right key was pressed
        elif self._locked and keys[0] == self._unlock_key:
            self._locked = False
            self.mainloop.widget = self.root_widget
            if callable(self._unlock_callback):
                self._unlock_callback()
        # otherwise interpret keybinding
        else:
            # define callback that resets input queue
            def clear(*args):
                if self._alarm is not None:
                    self.mainloop.remove_alarm(self._alarm)
                self.input_queue = []
                self.update()

            key = keys[0]
            self.input_queue.append(key)
            keyseq = ' '.join(self.input_queue)
            cmdline = settings.get_keybinding(self.mode, keyseq)
            if cmdline:
                clear()
                logging.debug("cmdline: '%s'" % cmdline)
                # move keys are always passed
                if cmdline.startswith('move '):
                    movecmd = cmdline[5:].rstrip()
                    logging.debug("GOT MOVE: '%s'" % movecmd)
                    if movecmd in ['up', 'down', 'page up', 'page down']:
                        return [movecmd]
                elif not self._locked:
                    try:
                        self.apply_commandline(cmdline)
                    except CommandParseError, e:
                        self.notify(e.message, priority='error')

            timeout = float(settings.get('input_timeout'))
            if self._alarm is not None:
                self.mainloop.remove_alarm(self._alarm)
            self._alarm = self.mainloop.set_alarm_in(timeout, clear)
            # update statusbar
            self.update()
Example #3
0
File: ui.py Project: t-8ch/alot
 def keypress(self, size, key):
     """overwrites `urwid.WidgetWrap.keypress`"""
     mode = self.ui.mode
     if self.select_cancel_only:
         mode = 'global'
     cmdline = settings.get_keybinding(mode, key)
     if cmdline:
         try:
             cmd = commandfactory(cmdline, mode)
             if self.allowed_command(cmd):
                 self.ui.apply_command(cmd)
                 return None
         except CommandParseError, e:
             self.ui.notify(e.message, priority='error')
Example #4
0
File: ui.py Project: tlevine/alot
class UI(object):
    """
    This class integrates all components of alot and offers
    methods for user interaction like :meth:`prompt`, :meth:`notify` etc.
    It handles the urwid widget tree and mainloop (we use twisted) and is
    responsible for opening, closing and focussing buffers.
    """
    def __init__(self, dbman, initialcmdline):
        """
        :param dbman: :class:`~alot.db.DBManager`
        :param initialcmdline: commandline applied after setting up interface
        :type initialcmdline: str
        :param colourmode: determines which theme to chose
        :type colourmode: int in [1,16,256]
        """
        self.dbman = dbman
        """Database Manager (:class:`~alot.db.manager.DBManager`)"""
        self.buffers = []
        """list of active buffers"""
        self.current_buffer = None
        """points to currently active :class:`~alot.buffers.Buffer`"""
        self.db_was_locked = False
        """flag used to prevent multiple 'index locked' notifications"""
        self.mode = 'global'
        """interface mode identifier - type of current buffer"""
        self.commandprompthistory = []
        """history of the command line prompt"""
        self.input_queue = []
        """stores partial keyboard input"""
        self.last_commandline = None
        """saves the last executed commandline"""

        # define empty notification pile
        self._notificationbar = None
        # should we show a status bar?
        self._show_statusbar = settings.get('show_statusbar')
        # pass keypresses to the root widget and never interpret bindings
        self._passall = False
        # indicates "input lock": only focus move commands are interpreted
        self._locked = False
        self._unlock_callback = None  # will be called after input lock ended
        self._unlock_key = None  # key that ends input lock

        # alarm handle for callback that clears input queue (to cancel alarm)
        self._alarm = None

        # create root widget
        global_att = settings.get_theming_attribute('global', 'body')
        mainframe = urwid.Frame(urwid.SolidFill())
        self.root_widget = urwid.AttrMap(mainframe, global_att)

        # set up main loop
        self.mainloop = urwid.MainLoop(self.root_widget,
                                       handle_mouse=False,
                                       event_loop=urwid.TwistedEventLoop(),
                                       unhandled_input=self._unhandeled_input,
                                       input_filter=self._input_filter)

        # set up colours
        colourmode = int(settings.get('colourmode'))
        logging.info('setup gui in %d colours' % colourmode)
        self.mainloop.screen.set_terminal_properties(colors=colourmode)

        logging.debug('fire first command')
        self.apply_commandline(initialcmdline)

        # start urwids mainloop
        self.mainloop.run()

    def _input_filter(self, keys, raw):
        """
        handles keypresses.
        This function gets triggered directly by class:`urwid.MainLoop`
        upon user input and is supposed to pass on its `keys` parameter
        to let the root widget handle keys. We intercept the input here
        to trigger custom commands as defined in our keybindings.
        """
        logging.debug("Got key (%s, %s)" % (keys, raw))
        # work around: escape triggers this twice, with keys = raw = []
        # the first time..
        if not keys:
            return
        # let widgets handle input if key is virtual window resize keypress
        # or we are in "passall" mode
        elif 'window resize' in keys or self._passall:
            return keys
        # end "lockdown" mode if the right key was pressed
        elif self._locked and keys[0] == self._unlock_key:
            self._locked = False
            self.mainloop.widget = self.root_widget
            if callable(self._unlock_callback):
                self._unlock_callback()
        # otherwise interpret keybinding
        else:
            # define callback that resets input queue
            def clear(*args):
                if self._alarm is not None:
                    self.mainloop.remove_alarm(self._alarm)
                self.input_queue = []

            def fire(ignored, cmdline):
                clear()
                logging.debug("cmdline: '%s'" % cmdline)
                if not self._locked:
                    try:
                        self.apply_commandline(cmdline)
                    except CommandParseError, e:
                        self.notify(e.message, priority='error')
                # move keys are always passed
                elif cmdline in [
                        'move up', 'move down', 'move page up',
                        'move page down'
                ]:
                    return [cmdline[5:]]

            key = keys[0]
            self.input_queue.append(key)
            keyseq = ' '.join(self.input_queue)
            candidates = settings.get_mapped_input_keysequences(self.mode,
                                                                prefix=keyseq)
            if keyseq in candidates:
                # case: current input queue is a mapped keysequence
                # get binding and interpret it if non-null
                cmdline = settings.get_keybinding(self.mode, keyseq)
                if cmdline:
                    if len(candidates) > 1:
                        timeout = float(settings.get('input_timeout'))
                        if self._alarm is not None:
                            self.mainloop.remove_alarm(self._alarm)
                        self._alarm = self.mainloop.set_alarm_in(
                            timeout, fire, cmdline)
                    else:
                        return fire(self.mainloop, cmdline)

            elif not candidates:
                # case: no sequence with prefix keyseq is mapped
                # just clear the input queue
                clear()
            else:
                # case: some sequences with proper prefix keyseq is mapped
                timeout = float(settings.get('input_timeout'))
                if self._alarm is not None:
                    self.mainloop.remove_alarm(self._alarm)
                self._alarm = self.mainloop.set_alarm_in(timeout, clear)
            # update statusbar
            self.update()