Use a stack for current modes

This commit is contained in:
Florian Bruhin 2014-04-24 06:44:58 +02:00
parent 19d25b2282
commit 3d292fbc27
5 changed files with 43 additions and 12 deletions

1
TODO
View File

@ -4,7 +4,6 @@ keyparser foo
- Get to insert mode when clicking flash plugins
- Handle keybind to get out of insert mode (e.g. esc)
- Pass keypresses to statusbar correctly
- Use stack for modes and .leave()
- Switch to normal mode if new page loaded
- Add passthrough-keys option to pass through unmapped keys
- Add auto-insert-mode to switch to insert mode if editable element is focused

View File

@ -403,7 +403,7 @@ class HintManager(QObject):
self._elems = {}
self._target = None
self._frame = None
modemanager.enter("normal")
modemanager.leave("hint")
message.clear()
def handle_partial_key(self, keystr):

View File

@ -47,6 +47,11 @@ def enter(mode):
manager.enter(mode)
def leave(mode):
"""Leave the mode 'mode'."""
manager.leave(mode)
class ModeManager(QObject):
"""Manager for keyboard modes.
@ -54,7 +59,9 @@ class ModeManager(QObject):
Attributes:
_handlers: A dictionary of modes and their handlers.
_passthrough: A list of modes in which to pass through events.
mode: The current mode.
_mode_stack: A list of the modes we're currently in, with the active
one on the right.
mode: The current mode (readonly property).
Signals:
entered: Emitted when a mode is entered.
@ -70,7 +77,14 @@ class ModeManager(QObject):
super().__init__(parent)
self._handlers = {}
self._passthrough = []
self.mode = None
self._mode_stack = []
@property
def mode(self):
"""Read-only property for the current mode."""
if not self._mode_stack:
return None
return self._mode_stack[-1]
def register(self, mode, handler, passthrough=False):
"""Register a new mode.
@ -88,19 +102,34 @@ class ModeManager(QObject):
def enter(self, mode):
"""Enter a new mode.
Args:
mode; The name of the mode to enter.
Emit:
leaved: With the old mode name.
entered: With the new mode name.
"""
oldmode = self.mode
logging.debug("Switching mode: {} -> {}".format(oldmode, mode))
logging.debug("Switching mode to {}".format(mode))
logging.debug("Mode stack: {}".format(self._mode_stack))
if mode not in self._handlers:
raise ValueError("No handler for mode {}".format(mode))
if oldmode is not None:
self.leaved.emit(oldmode)
self.mode = mode
self._mode_stack.append(mode)
self.entered.emit(mode)
def leave(self, mode):
"""Leave a mode.
Args:
mode; The name of the mode to leave.
Emit:
leaved: With the old mode name.
"""
try:
self._mode_stack.remove(mode)
except ValueError:
raise ValueError("Mode {} not on mode stack!".format(mode))
self.leaved.emit(mode)
def eventFilter(self, obj, evt):
"""Filter all events based on the currently set mode.

View File

@ -272,7 +272,10 @@ class BrowserTab(QWebView):
logging.debug("Clicked editable element!")
modemanager.enter("insert")
else:
modemanager.enter("normal")
try:
modemanager.leave("insert")
except ValueError:
pass
if self._force_open_target is not None:
self._open_target = self._force_open_target

View File

@ -363,7 +363,7 @@ class _Command(QLineEdit):
clear_completion_selection: Always emitted.
hide_completion: Always emitted so the completion is hidden.
"""
modemanager.enter("normal")
modemanager.leave("command")
if e.reason() in [Qt.MouseFocusReason, Qt.TabFocusReason,
Qt.BacktabFocusReason, Qt.OtherFocusReason]:
self.setText('')