Lock mode while prompting.

This commit is contained in:
Florian Bruhin 2014-08-04 03:14:14 +02:00
parent 40acc5c6ff
commit 3dc7a1b735
5 changed files with 47 additions and 11 deletions

View File

@ -167,6 +167,14 @@ class HintManager(QObject):
modeman.instance().left.connect(self.on_mode_left)
modeman.instance().entered.connect(self.on_mode_entered)
def _cleanup(self):
"""Clean up after hinting."""
for elem in self._context.elems.values():
if not elem.label.isNull():
elem.label.removeFromDocument()
self._context = None
message.instance().set_text('')
def _hint_strings(self, elems):
"""Calculate the hint strings for elems.
@ -507,7 +515,10 @@ class HintManager(QObject):
self._context = ctx
self._connect_frame_signals()
self.hint_strings_updated.emit(strings)
modeman.enter(KeyMode.hint, 'HintManager.start')
try:
modeman.enter(KeyMode.hint, 'HintManager.start')
except modeman.ModeLockedError:
self._cleanup()
def handle_partial_key(self, keystr):
"""Handle a new partial keypress."""
@ -630,8 +641,4 @@ class HintManager(QObject):
# self._context might be None, because the current tab is not
# hinting.
return
for elem in self._context.elems.values():
if not elem.label.isNull():
elem.label.removeFromDocument()
self._context = None
message.instance().set_text('')
self._cleanup()

View File

@ -34,6 +34,11 @@ from qutebrowser.utils.usertypes import KeyMode
from qutebrowser.commands.exceptions import CommandError
class ModeLockedError(Exception):
"""Exception raised when the mode is currently locked."""
def instance():
"""Get the global modeman instance."""
return QApplication.instance().modeman
@ -49,6 +54,14 @@ def leave(mode, reason=None):
instance().leave(mode, reason)
def maybe_enter(mode, reason=None):
"""Convenience method to enter 'mode' without exceptions."""
try:
instance().enter(mode, reason)
except ModeLockedError as e:
pass
def maybe_leave(mode, reason=None):
"""Convenience method to leave 'mode' without exceptions."""
try:
@ -65,6 +78,9 @@ class ModeManager(QObject):
mode: The current mode (readonly property).
passthrough: A list of modes in which to pass through events.
mainwindow: The mainwindow object
locked: Whether current mode is locked. This means the current mode can
still be left (then locked will be reset), but no new mode can
be entered while the current mode is active.
_handlers: A dictionary of modes and their handlers.
_mode_stack: A list of the modes we're currently in, with the active
one on the right.
@ -86,6 +102,7 @@ class ModeManager(QObject):
def __init__(self, parent=None):
super().__init__(parent)
self.mainwindow = None
self.locked = False
self._handlers = {}
self.passthrough = []
self._mode_stack = []
@ -200,6 +217,11 @@ class ModeManager(QObject):
"""
if not isinstance(mode, KeyMode):
raise TypeError("Mode {} is no KeyMode member!".format(mode))
if self.locked:
logger.debug("Not entering mode {} because mode is locked to "
"{}.".format(mode, self.mode))
raise ModeLockedError("Mode is currently locked to {}".format(
self.mode))
logger.debug("Entering mode {}{}".format(
mode, '' if reason is None else ' (reason: {})'.format(reason)))
if mode not in self._handlers:
@ -238,6 +260,7 @@ class ModeManager(QObject):
self._mode_stack.remove(mode)
except ValueError:
raise ValueError("Mode {} not on mode stack!".format(mode))
self.locked = False
logger.debug("Leaving mode {}{}, new mode stack {}".format(
mode, '' if reason is None else ' (reason: {})'.format(reason),
self._mode_stack))

View File

@ -299,7 +299,7 @@ class Command(MinimalLineEdit):
def focusInEvent(self, e):
"""Extend focusInEvent to enter command mode."""
modeman.enter(KeyMode.command, 'cmd focus')
modeman.maybe_enter(KeyMode.command, 'cmd focus')
super().focusInEvent(e)

View File

@ -279,7 +279,13 @@ class Prompter:
self.question = question
mode = self._display_question()
question.aborted.connect(lambda: modeman.maybe_leave(mode, 'aborted'))
modeman.enter(mode, 'question asked')
try:
modeman.enter(mode, 'question asked')
except modeman.ModeLockedError:
if modeman.instance().mode != KeyMode.prompt:
question.abort()
return None
modeman.instance().locked = True
if blocking:
loop = EventLoop()
self._loops.append(loop)

View File

@ -233,7 +233,7 @@ class WebView(QWebView):
elif ((hitresult.isContentEditable() and webelem.is_writable(elem)) or
webelem.is_editable(elem)):
log.mouse.debug("Clicked editable element!")
modeman.enter(KeyMode.insert, 'click')
modeman.maybe_enter(KeyMode.insert, 'click')
else:
log.mouse.debug("Clicked non-editable element!")
if config.get('input', 'auto-leave-insert-mode'):
@ -247,7 +247,7 @@ class WebView(QWebView):
elem = webelem.focus_elem(self.page().currentFrame())
if webelem.is_editable(elem):
log.mouse.debug("Clicked editable element (delayed)!")
modeman.enter(KeyMode.insert, 'click-delayed')
modeman.maybe_enter(KeyMode.insert, 'click-delayed')
else:
log.mouse.debug("Clicked non-editable element (delayed)!")
if config.get('input', 'auto-leave-insert-mode'):
@ -402,7 +402,7 @@ class WebView(QWebView):
if elem.isNull():
log.webview.debug("Focused element is null!")
elif webelem.is_editable(elem):
modeman.enter(KeyMode.insert, 'load finished')
modeman.maybe_enter(KeyMode.insert, 'load finished')
@pyqtSlot(str)
def set_force_open_target(self, target):