Make yes/no questions work
This commit is contained in:
parent
f43549d452
commit
cfd70e7821
@ -55,7 +55,8 @@ from qutebrowser.config.config import ConfigManager
|
|||||||
from qutebrowser.keyinput.modeman import ModeManager
|
from qutebrowser.keyinput.modeman import ModeManager
|
||||||
from qutebrowser.widgets.mainwindow import MainWindow
|
from qutebrowser.widgets.mainwindow import MainWindow
|
||||||
from qutebrowser.widgets.crash import ExceptionCrashDialog, FatalCrashDialog
|
from qutebrowser.widgets.crash import ExceptionCrashDialog, FatalCrashDialog
|
||||||
from qutebrowser.keyinput.modeparsers import NormalKeyParser, HintKeyParser
|
from qutebrowser.keyinput.modeparsers import (NormalKeyParser, HintKeyParser,
|
||||||
|
PromptKeyParser)
|
||||||
from qutebrowser.keyinput.keyparser import PassthroughKeyParser
|
from qutebrowser.keyinput.keyparser import PassthroughKeyParser
|
||||||
from qutebrowser.commands.managers import CommandManager, SearchManager
|
from qutebrowser.commands.managers import CommandManager, SearchManager
|
||||||
from qutebrowser.commands.exceptions import CommandError
|
from qutebrowser.commands.exceptions import CommandError
|
||||||
@ -212,6 +213,7 @@ class QuteBrowser(QApplication):
|
|||||||
'passthrough': PassthroughKeyParser('keybind.passthrough', self),
|
'passthrough': PassthroughKeyParser('keybind.passthrough', self),
|
||||||
'command': PassthroughKeyParser('keybind.command', self),
|
'command': PassthroughKeyParser('keybind.command', self),
|
||||||
'prompt': PassthroughKeyParser('keybind.prompt', self),
|
'prompt': PassthroughKeyParser('keybind.prompt', self),
|
||||||
|
'yesno': PromptKeyParser(self),
|
||||||
}
|
}
|
||||||
self.modeman = ModeManager()
|
self.modeman = ModeManager()
|
||||||
self.modeman.register('normal', self._keyparsers['normal'].handle)
|
self.modeman.register('normal', self._keyparsers['normal'].handle)
|
||||||
@ -225,6 +227,7 @@ class QuteBrowser(QApplication):
|
|||||||
passthrough=True)
|
passthrough=True)
|
||||||
self.modeman.register('prompt', self._keyparsers['prompt'].handle,
|
self.modeman.register('prompt', self._keyparsers['prompt'].handle,
|
||||||
passthrough=True)
|
passthrough=True)
|
||||||
|
self.modeman.register('yesno', self._keyparsers['yesno'].handle)
|
||||||
|
|
||||||
def _init_log(self):
|
def _init_log(self):
|
||||||
"""Initialisation of the logging output.
|
"""Initialisation of the logging output.
|
||||||
|
@ -121,8 +121,13 @@ SECTION_DESC = {
|
|||||||
" leave-mode: Leave the command mode."),
|
" leave-mode: Leave the command mode."),
|
||||||
'keybind.prompt': (
|
'keybind.prompt': (
|
||||||
"Keybindings for prompts in the status line.\n"
|
"Keybindings for prompts in the status line.\n"
|
||||||
|
"You can bind normal keys in this mode, but they will be only active "
|
||||||
|
"when a yes/no-prompt is asked. For other prompt modes, you can only "
|
||||||
|
"bind special keys.\n"
|
||||||
"Useful hidden commands to map in this section:\n"
|
"Useful hidden commands to map in this section:\n"
|
||||||
" prompt-accept: Confirm the entered value\n"
|
" prompt-accept: Confirm the entered value.\n"
|
||||||
|
" prompt-yes: Answer yes to a yes/no question.\n"
|
||||||
|
" prompt-no: Answer no to a yes/no question.\n"
|
||||||
" leave-mode: Leave the prompt mode."),
|
" leave-mode: Leave the prompt mode."),
|
||||||
'aliases': (
|
'aliases': (
|
||||||
"Aliases for commands.\n"
|
"Aliases for commands.\n"
|
||||||
@ -701,6 +706,8 @@ DATA = OrderedDict([
|
|||||||
('<Escape>', 'leave-mode'),
|
('<Escape>', 'leave-mode'),
|
||||||
('<Ctrl-N>', 'leave-mode'),
|
('<Ctrl-N>', 'leave-mode'),
|
||||||
('<Return>', 'prompt-accept'),
|
('<Return>', 'prompt-accept'),
|
||||||
|
('y', 'prompt-yes'),
|
||||||
|
('n', 'prompt-no'),
|
||||||
)),
|
)),
|
||||||
|
|
||||||
('aliases', sect.ValueList(
|
('aliases', sect.ValueList(
|
||||||
|
@ -59,6 +59,17 @@ class NormalKeyParser(CommandKeyParser):
|
|||||||
return super()._handle_single_key(e)
|
return super()._handle_single_key(e)
|
||||||
|
|
||||||
|
|
||||||
|
class PromptKeyParser(CommandKeyParser):
|
||||||
|
|
||||||
|
"""KeyParser for yes/no prompts."""
|
||||||
|
|
||||||
|
def __init__(self, parent=None):
|
||||||
|
super().__init__(parent, supports_count=False, supports_chains=True)
|
||||||
|
# We don't want an extra section for this in the config, so we just
|
||||||
|
# abuse the keybind.prompt section.
|
||||||
|
self.read_config('keybind.prompt')
|
||||||
|
|
||||||
|
|
||||||
class HintKeyParser(CommandKeyParser):
|
class HintKeyParser(CommandKeyParser):
|
||||||
|
|
||||||
"""KeyChainParser for hints.
|
"""KeyChainParser for hints.
|
||||||
|
@ -22,6 +22,7 @@ from PyQt5.QtWidgets import QHBoxLayout, QWidget, QLineEdit
|
|||||||
|
|
||||||
import qutebrowser.keyinput.modeman as modeman
|
import qutebrowser.keyinput.modeman as modeman
|
||||||
import qutebrowser.commands.utils as cmdutils
|
import qutebrowser.commands.utils as cmdutils
|
||||||
|
import qutebrowser.config.config as config
|
||||||
from qutebrowser.widgets.statusbar._textbase import TextBase
|
from qutebrowser.widgets.statusbar._textbase import TextBase
|
||||||
from qutebrowser.widgets.misc import MinimalLineEdit
|
from qutebrowser.widgets.misc import MinimalLineEdit
|
||||||
from qutebrowser.utils.usertypes import PromptMode, Question
|
from qutebrowser.utils.usertypes import PromptMode, Question
|
||||||
@ -36,7 +37,7 @@ class Prompt(QWidget):
|
|||||||
loop: A local QEventLoop to spin in exec_.
|
loop: A local QEventLoop to spin in exec_.
|
||||||
_hbox: The QHBoxLayout used to display the text and prompt.
|
_hbox: The QHBoxLayout used to display the text and prompt.
|
||||||
_txt: The TextBase instance (QLabel) used to display the prompt text.
|
_txt: The TextBase instance (QLabel) used to display the prompt text.
|
||||||
_input: The QueryInput instance (QLineEdit) used for the input.
|
_input: The MinimalLineEdit instance (QLineEdit) used for the input.
|
||||||
|
|
||||||
Signals:
|
Signals:
|
||||||
show_prompt: Emitted when the prompt widget wants to be shown.
|
show_prompt: Emitted when the prompt widget wants to be shown.
|
||||||
@ -61,7 +62,7 @@ class Prompt(QWidget):
|
|||||||
self._txt = TextBase()
|
self._txt = TextBase()
|
||||||
self._hbox.addWidget(self._txt)
|
self._hbox.addWidget(self._txt)
|
||||||
|
|
||||||
self._input = _QueryInput()
|
self._input = MinimalLineEdit()
|
||||||
self._hbox.addWidget(self._input)
|
self._hbox.addWidget(self._input)
|
||||||
|
|
||||||
def on_mode_left(self, mode):
|
def on_mode_left(self, mode):
|
||||||
@ -71,7 +72,7 @@ class Prompt(QWidget):
|
|||||||
cancelled: Emitted when the mode was forcibly left by the user
|
cancelled: Emitted when the mode was forcibly left by the user
|
||||||
without answering the question.
|
without answering the question.
|
||||||
"""
|
"""
|
||||||
if mode == 'prompt':
|
if mode in ['prompt', 'yesno']:
|
||||||
self._txt.setText('')
|
self._txt.setText('')
|
||||||
self._input.clear()
|
self._input.clear()
|
||||||
self._input.setEchoMode(QLineEdit.Normal)
|
self._input.setEchoMode(QLineEdit.Normal)
|
||||||
@ -100,10 +101,36 @@ class Prompt(QWidget):
|
|||||||
self.question.answer = (self.question.user, password)
|
self.question.answer = (self.question.user, password)
|
||||||
modeman.leave('prompt', 'prompt accept')
|
modeman.leave('prompt', 'prompt accept')
|
||||||
self.hide_prompt.emit()
|
self.hide_prompt.emit()
|
||||||
else:
|
elif self.question.mode == PromptMode.text:
|
||||||
# User just entered all information needed in some other mode.
|
# User just entered text.
|
||||||
self.question.answer = self._input.text()
|
self.question.answer = self._input.text()
|
||||||
modeman.leave('prompt', 'prompt accept')
|
modeman.leave('prompt', 'prompt accept')
|
||||||
|
elif self.question.mode == PromptMode.yesno:
|
||||||
|
# User wants to accept the default of a yes/no question.
|
||||||
|
self.question.answer = self.question.default
|
||||||
|
modeman.leave('yesno', 'yesno accept')
|
||||||
|
else:
|
||||||
|
raise ValueError("Invalid question mode!")
|
||||||
|
|
||||||
|
@cmdutils.register(instance='mainwindow.status.prompt', hide=True,
|
||||||
|
modes=['yesno'])
|
||||||
|
def prompt_yes(self):
|
||||||
|
"""Answer yes to a yes/no prompt."""
|
||||||
|
if self.question.mode != PromptMode.yesno:
|
||||||
|
# We just ignore this if we don't have a yes/no question.
|
||||||
|
return
|
||||||
|
self.question.answer = True
|
||||||
|
modeman.leave('yesno', 'yesno accept')
|
||||||
|
|
||||||
|
@cmdutils.register(instance='mainwindow.status.prompt', hide=True,
|
||||||
|
modes=['yesno'])
|
||||||
|
def prompt_no(self):
|
||||||
|
"""Answer no to a yes/no prompt."""
|
||||||
|
if self.question.mode != PromptMode.yesno:
|
||||||
|
# We just ignore this if we don't have a yes/no question.
|
||||||
|
return
|
||||||
|
self.question.answer = False
|
||||||
|
modeman.leave('yesno', 'prompt accept')
|
||||||
|
|
||||||
def display(self):
|
def display(self):
|
||||||
"""Display the question in self.question in the widget.
|
"""Display the question in self.question in the widget.
|
||||||
@ -114,27 +141,31 @@ class Prompt(QWidget):
|
|||||||
q = self.question
|
q = self.question
|
||||||
if q.mode == PromptMode.yesno:
|
if q.mode == PromptMode.yesno:
|
||||||
if q.default is None:
|
if q.default is None:
|
||||||
suffix = " [y/n]"
|
suffix = ""
|
||||||
elif q.default:
|
elif q.default:
|
||||||
suffix = " [Y/n]"
|
suffix = " (yes)"
|
||||||
else:
|
else:
|
||||||
suffix = " [y/N]"
|
suffix = " (no)"
|
||||||
self._txt.setText(q.text + suffix)
|
self._txt.setText(q.text + suffix)
|
||||||
self._input.hide()
|
self._input.hide()
|
||||||
|
mode = 'yesno'
|
||||||
elif q.mode == PromptMode.text:
|
elif q.mode == PromptMode.text:
|
||||||
self._txt.setText(q.text)
|
self._txt.setText(q.text)
|
||||||
if q.default:
|
if q.default:
|
||||||
self._input.setText(q.default)
|
self._input.setText(q.default)
|
||||||
self._input.show()
|
self._input.show()
|
||||||
|
mode = 'prompt'
|
||||||
elif q.mode == PromptMode.user_pwd:
|
elif q.mode == PromptMode.user_pwd:
|
||||||
self._txt.setText(q.text)
|
self._txt.setText(q.text)
|
||||||
if q.default:
|
if q.default:
|
||||||
self._input.setText(q.default)
|
self._input.setText(q.default)
|
||||||
self._input.show()
|
self._input.show()
|
||||||
|
mode = 'prompt'
|
||||||
else:
|
else:
|
||||||
raise ValueError("Invalid prompt mode!")
|
raise ValueError("Invalid prompt mode!")
|
||||||
self._input.setFocus()
|
self._input.setFocus()
|
||||||
self.show_prompt.emit()
|
self.show_prompt.emit()
|
||||||
|
modeman.enter(mode, 'question asked')
|
||||||
|
|
||||||
@pyqtSlot(Question, bool)
|
@pyqtSlot(Question, bool)
|
||||||
def ask_question(self, question, blocking):
|
def ask_question(self, question, blocking):
|
||||||
@ -163,13 +194,3 @@ class Prompt(QWidget):
|
|||||||
self.cancelled.connect(self.loop.quit)
|
self.cancelled.connect(self.loop.quit)
|
||||||
self.loop.exec_()
|
self.loop.exec_()
|
||||||
return self.question.answer
|
return self.question.answer
|
||||||
|
|
||||||
|
|
||||||
class _QueryInput(MinimalLineEdit):
|
|
||||||
|
|
||||||
"""QLineEdit used for input."""
|
|
||||||
|
|
||||||
def focusInEvent(self, e):
|
|
||||||
"""Extend focusInEvent to enter command mode."""
|
|
||||||
modeman.enter('prompt', 'auth focus')
|
|
||||||
super().focusInEvent(e)
|
|
||||||
|
Loading…
Reference in New Issue
Block a user