First prototype of new prompts
This commit is contained in:
parent
ced618eccb
commit
903e31efa4
@ -30,7 +30,7 @@ from PyQt5.QtWidgets import QWidget, QVBoxLayout, QApplication, QSizePolicy
|
||||
from qutebrowser.commands import runners, cmdutils
|
||||
from qutebrowser.config import config
|
||||
from qutebrowser.utils import message, log, usertypes, qtutils, objreg, utils
|
||||
from qutebrowser.mainwindow import tabbedbrowser, messageview
|
||||
from qutebrowser.mainwindow import tabbedbrowser, messageview, prompt
|
||||
from qutebrowser.mainwindow.statusbar import bar
|
||||
from qutebrowser.completion import completionwidget, completer
|
||||
from qutebrowser.keyinput import modeman
|
||||
@ -179,10 +179,14 @@ class MainWindow(QWidget):
|
||||
partial_match=True)
|
||||
|
||||
self._keyhint = keyhintwidget.KeyHintView(self.win_id, self)
|
||||
self._overlays.append((self._keyhint, self._keyhint.update_geometry))
|
||||
self._add_overlay(self._keyhint, self._keyhint.update_geometry)
|
||||
self._messageview = messageview.MessageView(parent=self)
|
||||
self._overlays.append((self._messageview,
|
||||
self._messageview.update_geometry))
|
||||
self._add_overlay(self._messageview, self._messageview.update_geometry)
|
||||
self._promptcontainer = prompt.PromptContainer(self)
|
||||
self._add_overlay(self._promptcontainer,
|
||||
self._promptcontainer.update_geometry,
|
||||
centered=True)
|
||||
self._promptcontainer.hide()
|
||||
|
||||
log.init.debug("Initializing modes...")
|
||||
modeman.init(self.win_id, self)
|
||||
@ -206,33 +210,40 @@ class MainWindow(QWidget):
|
||||
|
||||
objreg.get("app").new_window.emit(self)
|
||||
|
||||
def _update_overlay_geometry(self, widget=None):
|
||||
def _add_overlay(self, widget, signal, *, centered=False):
|
||||
self._overlays.append((widget, signal, centered))
|
||||
|
||||
def _update_overlay_geometry(self, widget=None, centered=None):
|
||||
"""Reposition/resize the given overlay.
|
||||
|
||||
If no widget is given, reposition/resize all overlays.
|
||||
"""
|
||||
if widget is None:
|
||||
for w, _signal in self._overlays:
|
||||
self._update_overlay_geometry(w)
|
||||
for w, _signal, centered in self._overlays:
|
||||
self._update_overlay_geometry(w, centered)
|
||||
return
|
||||
|
||||
assert centered is not None
|
||||
|
||||
if not widget.isVisible():
|
||||
return
|
||||
|
||||
size_hint = widget.sizeHint()
|
||||
if widget.sizePolicy().horizontalPolicy() == QSizePolicy.Expanding:
|
||||
width = self.width()
|
||||
left = 0
|
||||
else:
|
||||
width = size_hint.width()
|
||||
left = (self.width() - size_hint.width()) / 2 if centered else 0
|
||||
|
||||
status_position = config.get('ui', 'status-position')
|
||||
if status_position == 'bottom':
|
||||
top = self.height() - self.status.height() - size_hint.height()
|
||||
top = qtutils.check_overflow(top, 'int', fatal=False)
|
||||
topleft = QPoint(0, top)
|
||||
bottomright = QPoint(width, self.status.geometry().top())
|
||||
topleft = QPoint(left, top)
|
||||
bottomright = QPoint(left + width, self.status.geometry().top())
|
||||
elif status_position == 'top':
|
||||
topleft = self.status.geometry().bottomLeft()
|
||||
topleft = QPoint(left, self.status.geometry().bottom())
|
||||
bottom = self.status.height() + size_hint.height()
|
||||
bottom = qtutils.check_overflow(bottom, 'int', fatal=False)
|
||||
bottomright = QPoint(width, bottom)
|
||||
@ -261,8 +272,7 @@ class MainWindow(QWidget):
|
||||
completer_obj.on_selection_changed)
|
||||
objreg.register('completion', self._completion, scope='window',
|
||||
window=self.win_id)
|
||||
self._overlays.append((self._completion,
|
||||
self._completion.update_geometry))
|
||||
self._add_overlay(self._completion, self._completion.update_geometry)
|
||||
|
||||
def _init_command_dispatcher(self):
|
||||
dispatcher = commands.CommandDispatcher(self.win_id,
|
||||
@ -350,10 +360,11 @@ class MainWindow(QWidget):
|
||||
|
||||
def _connect_overlay_signals(self):
|
||||
"""Connect the resize signal and resize everything once."""
|
||||
for widget, signal in self._overlays:
|
||||
for widget, signal, centered in self._overlays:
|
||||
signal.connect(
|
||||
functools.partial(self._update_overlay_geometry, widget))
|
||||
self._update_overlay_geometry(widget)
|
||||
functools.partial(self._update_overlay_geometry, widget,
|
||||
centered))
|
||||
self._update_overlay_geometry(widget, centered)
|
||||
|
||||
def _set_default_geometry(self):
|
||||
"""Set some sensible default geometry."""
|
||||
@ -374,7 +385,7 @@ class MainWindow(QWidget):
|
||||
cmd = self._get_object('status-command')
|
||||
message_bridge = self._get_object('message-bridge')
|
||||
mode_manager = self._get_object('mode-manager')
|
||||
prompter = self._get_object('prompter')
|
||||
#prompter = self._get_object('prompter')
|
||||
|
||||
# misc
|
||||
self.tabbed_browser.close_window.connect(self.close)
|
||||
@ -384,7 +395,7 @@ class MainWindow(QWidget):
|
||||
mode_manager.entered.connect(status.on_mode_entered)
|
||||
mode_manager.left.connect(status.on_mode_left)
|
||||
mode_manager.left.connect(cmd.on_mode_left)
|
||||
mode_manager.left.connect(prompter.on_mode_left)
|
||||
#mode_manager.left.connect(prompter.on_mode_left)
|
||||
|
||||
# commands
|
||||
keyparsers[usertypes.KeyMode.normal].keystring_updated.connect(
|
||||
@ -408,8 +419,8 @@ class MainWindow(QWidget):
|
||||
message_bridge.s_set_text.connect(status.set_text)
|
||||
message_bridge.s_maybe_reset_text.connect(status.txt.maybe_reset_text)
|
||||
message_bridge.s_set_cmd_text.connect(cmd.set_cmd_text)
|
||||
message_bridge.s_question.connect(prompter.ask_question,
|
||||
Qt.DirectConnection)
|
||||
#message_bridge.s_question.connect(prompter.ask_question,
|
||||
# Qt.DirectConnection)
|
||||
|
||||
# statusbar
|
||||
tabs.current_tab_changed.connect(status.prog.on_tab_changed)
|
||||
|
215
qutebrowser/mainwindow/prompt.py
Normal file
215
qutebrowser/mainwindow/prompt.py
Normal file
@ -0,0 +1,215 @@
|
||||
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
|
||||
|
||||
# Copyright 2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
|
||||
#
|
||||
# This file is part of qutebrowser.
|
||||
#
|
||||
# qutebrowser is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# qutebrowser is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with qutebrowser. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""Showing prompts above the statusbar."""
|
||||
|
||||
import collections
|
||||
|
||||
from PyQt5.QtCore import pyqtSignal, Qt
|
||||
from PyQt5.QtWidgets import QWidget, QGridLayout, QVBoxLayout, QLineEdit, QLabel, QSpacerItem
|
||||
|
||||
from qutebrowser.config import style, config
|
||||
from qutebrowser.utils import usertypes
|
||||
|
||||
|
||||
AuthTuple = collections.namedtuple('AuthTuple', ['user', 'password'])
|
||||
|
||||
|
||||
class Error(Exception):
|
||||
|
||||
"""Base class for errors in this module."""
|
||||
|
||||
|
||||
class PromptContainer(QWidget):
|
||||
|
||||
update_geometry = pyqtSignal()
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
self.setObjectName('Prompt')
|
||||
self.setAttribute(Qt.WA_StyledBackground, True)
|
||||
self._layout = QVBoxLayout(self)
|
||||
self._layout.setContentsMargins(10, 10, 10, 10)
|
||||
style.set_register_stylesheet(self,
|
||||
generator=self._generate_stylesheet)
|
||||
|
||||
def _generate_stylesheet(self):
|
||||
"""Generate a stylesheet with the right edge rounded."""
|
||||
stylesheet = """
|
||||
QWidget#Prompt {
|
||||
border-POSITION-left-radius: 10px;
|
||||
border-POSITION-right-radius: 10px;
|
||||
}
|
||||
|
||||
QWidget {
|
||||
/* FIXME
|
||||
font: {{ font['keyhint'] }};
|
||||
FIXME
|
||||
*/
|
||||
color: {{ color['statusbar.fg.prompt'] }};
|
||||
background-color: {{ color['statusbar.bg.prompt'] }};
|
||||
}
|
||||
|
||||
QLineEdit {
|
||||
border: 1px solid grey;
|
||||
}
|
||||
"""
|
||||
position = config.get('ui', 'status-position')
|
||||
if position == 'top':
|
||||
return stylesheet.replace('POSITION', 'bottom')
|
||||
elif position == 'bottom':
|
||||
return stylesheet.replace('POSITION', 'top')
|
||||
else:
|
||||
raise ValueError("Invalid position {}!".format(position))
|
||||
|
||||
def _show_prompt(self, prompt):
|
||||
while True:
|
||||
# FIXME do we really want to delete children?
|
||||
child = self._layout.takeAt(0)
|
||||
if child is None:
|
||||
break
|
||||
child.deleteLater()
|
||||
|
||||
self._layout.addWidget(prompt)
|
||||
self.update_geometry.emit()
|
||||
|
||||
|
||||
class _BasePrompt(QWidget):
|
||||
|
||||
"""Base class for all prompts."""
|
||||
|
||||
def __init__(self, question, parent=None):
|
||||
super().__init__(parent)
|
||||
self._question = question
|
||||
self._layout = QGridLayout(self)
|
||||
self._layout.setVerticalSpacing(15)
|
||||
|
||||
def _init_title(self, title, *, span=1):
|
||||
label = QLabel('<b>{}</b>'.format(title), self)
|
||||
self._layout.addWidget(label, 0, 0, 1, span)
|
||||
|
||||
def accept(self, value=None):
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class LineEditPrompt(_BasePrompt):
|
||||
|
||||
def __init__(self, question, parent=None):
|
||||
super().__init__(parent)
|
||||
self._lineedit = QLineEdit(self)
|
||||
self._layout.addWidget(self._lineedit, 1, 0)
|
||||
self._init_title(question.text)
|
||||
if question.default:
|
||||
self._lineedit.setText(question.default)
|
||||
|
||||
def accept(self, value=None):
|
||||
text = value if value is not None else self._lineedit.text()
|
||||
self._question.answer = text
|
||||
|
||||
|
||||
class DownloadFilenamePrompt(LineEditPrompt):
|
||||
|
||||
# FIXME have a FilenamePrompt
|
||||
|
||||
def __init__(self, question, parent=None):
|
||||
super().__init__(question, parent)
|
||||
# FIXME show :prompt-open-download keybinding
|
||||
# key_mode = self.KEY_MODES[self._question.mode]
|
||||
# key_config = objreg.get('key-config')
|
||||
# all_bindings = key_config.get_reverse_bindings_for(key_mode.name)
|
||||
# bindings = all_bindings.get('prompt-open-download', [])
|
||||
# if bindings:
|
||||
# text += ' ({} to open)'.format(bindings[0])
|
||||
|
||||
|
||||
def accept(self, value=None):
|
||||
text = value if value is not None else self._lineedit.text()
|
||||
self._question.answer = usertypes.FileDownloadTarget(text)
|
||||
|
||||
|
||||
class AuthenticationPrompt(_BasePrompt):
|
||||
|
||||
def __init__(self, question, parent=None):
|
||||
super().__init__(question, parent)
|
||||
self._init_title(question.text, span=2)
|
||||
user_label = QLabel("Username:", self)
|
||||
self._user_lineedit = QLineEdit(self)
|
||||
password_label = QLabel("Password:", self)
|
||||
self._password_lineedit = QLineEdit(self)
|
||||
self._password_lineedit.setEchoMode(QLineEdit.Password)
|
||||
self._layout.addWidget(user_label, 1, 0)
|
||||
self._layout.addWidget(self._user_lineedit, 1, 1)
|
||||
self._layout.addWidget(password_label, 2, 0)
|
||||
self._layout.addWidget(self._password_lineedit, 2, 1)
|
||||
assert not question.default, question.default
|
||||
|
||||
spacer = QSpacerItem(0, 10)
|
||||
self._layout.addItem(spacer, 3, 0)
|
||||
|
||||
help_1 = QLabel("<b>Accept:</b> Enter")
|
||||
help_2 = QLabel("<b>Abort:</b> Escape")
|
||||
self._layout.addWidget(help_1, 4, 0)
|
||||
self._layout.addWidget(help_2, 5, 0)
|
||||
|
||||
def accept(self, value=None):
|
||||
if value is not None:
|
||||
if ':' not in value:
|
||||
raise Error("Value needs to be in the format "
|
||||
"username:password, but {} was given".format(
|
||||
value))
|
||||
username, password = value.split(':', maxsplit=1)
|
||||
self._question.answer = AuthTuple(username, password)
|
||||
else:
|
||||
self._question.answer = AuthTuple(self._user_lineedit.text(),
|
||||
self._password_lineedit.text())
|
||||
|
||||
|
||||
class YesNoPrompt(_BasePrompt):
|
||||
|
||||
def __init__(self, question, parent=None):
|
||||
super().__init__(question, parent)
|
||||
self._init_title(question.text)
|
||||
# FIXME
|
||||
# "Enter/y: yes"
|
||||
# "n: no"
|
||||
# (depending on default)
|
||||
|
||||
def accept(self, value=None):
|
||||
if value is None:
|
||||
self._question.answer = self._question.default
|
||||
elif value == 'yes':
|
||||
self._question.answer = True
|
||||
elif value == 'no':
|
||||
self._question.answer = False
|
||||
else:
|
||||
raise Error("Invalid value {} - expected yes/no!".format(value))
|
||||
|
||||
|
||||
class AlertPrompt(_BasePrompt):
|
||||
|
||||
def __init__(self, question, parent=None):
|
||||
super().__init__(question, parent)
|
||||
self._init_title(question.text)
|
||||
# FIXME
|
||||
# Enter: acknowledge
|
||||
|
||||
def accept(self, value=None):
|
||||
if value is not None:
|
||||
raise Error("No value is permitted with alert prompts!")
|
||||
# Doing nothing otherwise
|
@ -162,16 +162,9 @@ class StatusBar(QWidget):
|
||||
self.txt = textwidget.Text()
|
||||
self._stack.addWidget(self.txt)
|
||||
|
||||
self.prompt = prompt.Prompt(win_id)
|
||||
self._stack.addWidget(self.prompt)
|
||||
|
||||
self.cmd.show_cmd.connect(self._show_cmd_widget)
|
||||
self.cmd.hide_cmd.connect(self._hide_cmd_widget)
|
||||
self._hide_cmd_widget()
|
||||
prompter = objreg.get('prompter', scope='window', window=self._win_id)
|
||||
prompter.show_prompt.connect(self._show_prompt_widget)
|
||||
prompter.hide_prompt.connect(self._hide_prompt_widget)
|
||||
self._hide_prompt_widget()
|
||||
|
||||
self.keystring = keystring.KeyString()
|
||||
self._hbox.addWidget(self.keystring)
|
||||
@ -285,21 +278,6 @@ class StatusBar(QWidget):
|
||||
self._stack.setCurrentWidget(self.txt)
|
||||
self.maybe_hide()
|
||||
|
||||
def _show_prompt_widget(self):
|
||||
"""Show prompt widget instead of temporary text."""
|
||||
if self._stack.currentWidget() is self.prompt:
|
||||
return
|
||||
self._set_prompt_active(True)
|
||||
self._stack.setCurrentWidget(self.prompt)
|
||||
self.show()
|
||||
|
||||
def _hide_prompt_widget(self):
|
||||
"""Show temporary text instead of prompt widget."""
|
||||
self._set_prompt_active(False)
|
||||
log.statusbar.debug("Hiding prompt widget")
|
||||
self._stack.setCurrentWidget(self.txt)
|
||||
self.maybe_hide()
|
||||
|
||||
@pyqtSlot(str)
|
||||
def set_text(self, val):
|
||||
"""Set a normal (persistent) text in the status bar."""
|
||||
|
@ -30,12 +30,6 @@ from qutebrowser.commands import cmdutils, cmdexc
|
||||
from qutebrowser.utils import usertypes, log, qtutils, objreg, utils
|
||||
|
||||
|
||||
PromptContext = collections.namedtuple('PromptContext',
|
||||
['question', 'text', 'input_text',
|
||||
'echo_mode', 'input_visible'])
|
||||
AuthTuple = collections.namedtuple('AuthTuple', ['user', 'password'])
|
||||
|
||||
|
||||
class Prompter(QObject):
|
||||
|
||||
"""Manager for questions to be shown in the statusbar.
|
||||
@ -67,12 +61,8 @@ class Prompter(QObject):
|
||||
_question: A Question object with the question to be asked to the user.
|
||||
_loops: A list of local EventLoops to spin in when blocking.
|
||||
_queue: A deque of waiting questions.
|
||||
_busy: If we're currently busy with asking a question.
|
||||
_prompt: The current prompt object if we're handling a question.
|
||||
_win_id: The window ID this object is associated with.
|
||||
|
||||
Signals:
|
||||
show_prompt: Emitted when the prompt widget should be shown.
|
||||
hide_prompt: Emitted when the prompt widget should be hidden.
|
||||
"""
|
||||
|
||||
KEY_MODES = {
|
||||
@ -83,22 +73,19 @@ class Prompter(QObject):
|
||||
usertypes.PromptMode.download: usertypes.KeyMode.prompt,
|
||||
}
|
||||
|
||||
show_prompt = pyqtSignal()
|
||||
hide_prompt = pyqtSignal()
|
||||
|
||||
def __init__(self, win_id, parent=None):
|
||||
super().__init__(parent)
|
||||
self._shutting_down = False
|
||||
self._question = None
|
||||
self._loops = []
|
||||
self._queue = collections.deque()
|
||||
self._busy = False
|
||||
self._prompt = None
|
||||
self._win_id = win_id
|
||||
|
||||
def __repr__(self):
|
||||
return utils.get_repr(self, loops=len(self._loops),
|
||||
question=self._question, queue=len(self._queue),
|
||||
busy=self._busy)
|
||||
prompt=self._prompt)
|
||||
|
||||
def _pop_later(self):
|
||||
"""Helper to call self._pop as soon as everything else is done."""
|
||||
@ -115,78 +102,31 @@ class Prompter(QObject):
|
||||
# https://github.com/The-Compiler/qutebrowser/issues/415
|
||||
self.ask_question(question, blocking=False)
|
||||
|
||||
def _get_ctx(self):
|
||||
"""Get a PromptContext based on the current state."""
|
||||
if not self._busy:
|
||||
return None
|
||||
prompt = objreg.get('prompt', scope='window', window=self._win_id)
|
||||
ctx = PromptContext(question=self._question,
|
||||
text=prompt.txt.text(),
|
||||
input_text=prompt.lineedit.text(),
|
||||
echo_mode=prompt.lineedit.echoMode(),
|
||||
input_visible=prompt.lineedit.isVisible())
|
||||
return ctx
|
||||
|
||||
def _restore_ctx(self, ctx):
|
||||
"""Restore state from a PromptContext.
|
||||
def _restore_prompt(self, prompt):
|
||||
"""Restore an old prompt which was interrupted.
|
||||
|
||||
Args:
|
||||
ctx: A PromptContext previously saved by _get_ctx, or None.
|
||||
prompt: A Prompt object or None.
|
||||
|
||||
Return: True if a context was restored, False otherwise.
|
||||
Return: True if a prompt was restored, False otherwise.
|
||||
"""
|
||||
log.statusbar.debug("Restoring context {}".format(ctx))
|
||||
if ctx is None:
|
||||
self.hide_prompt.emit()
|
||||
self._busy = False
|
||||
log.statusbar.debug("Restoring prompt {}".format(prompt))
|
||||
if prompt is None:
|
||||
self._prompt.hide() # FIXME
|
||||
self._prompt = None
|
||||
return False
|
||||
self._question = ctx.question
|
||||
prompt = objreg.get('prompt', scope='window', window=self._win_id)
|
||||
prompt.txt.setText(ctx.text)
|
||||
prompt.lineedit.setText(ctx.input_text)
|
||||
prompt.lineedit.setEchoMode(ctx.echo_mode)
|
||||
prompt.lineedit.setVisible(ctx.input_visible)
|
||||
self.show_prompt.emit()
|
||||
self._prompt = prompt
|
||||
# FIXME do promptcintainer stuff here??
|
||||
prompt.show()
|
||||
mode = self.KEY_MODES[ctx.question.mode]
|
||||
ctx.question.aborted.connect(
|
||||
lambda: modeman.maybe_leave(self._win_id, mode, 'aborted'))
|
||||
modeman.enter(self._win_id, mode, 'question asked')
|
||||
return True
|
||||
|
||||
def _display_question_yesno(self, prompt):
|
||||
"""Display a yes/no question."""
|
||||
if self._question.default is None:
|
||||
suffix = ""
|
||||
elif self._question.default:
|
||||
suffix = " (yes)"
|
||||
else:
|
||||
suffix = " (no)"
|
||||
prompt.txt.setText(self._question.text + suffix)
|
||||
prompt.lineedit.hide()
|
||||
|
||||
def _display_question_input(self, prompt):
|
||||
"""Display a question with an input."""
|
||||
text = self._question.text
|
||||
if self._question.mode == usertypes.PromptMode.download:
|
||||
key_mode = self.KEY_MODES[self._question.mode]
|
||||
key_config = objreg.get('key-config')
|
||||
all_bindings = key_config.get_reverse_bindings_for(key_mode.name)
|
||||
bindings = all_bindings.get('prompt-open-download', [])
|
||||
if bindings:
|
||||
text += ' ({} to open)'.format(bindings[0])
|
||||
prompt.txt.setText(text)
|
||||
if self._question.default:
|
||||
prompt.lineedit.setText(self._question.default)
|
||||
prompt.lineedit.show()
|
||||
|
||||
def _display_question_alert(self, prompt):
|
||||
"""Display a JS alert 'question'."""
|
||||
prompt.txt.setText(self._question.text + ' (ok)')
|
||||
prompt.lineedit.hide()
|
||||
|
||||
def _display_question(self):
|
||||
"""Display the question saved in self._question."""
|
||||
prompt = objreg.get('prompt', scope='window', window=self._win_id)
|
||||
handlers = {
|
||||
usertypes.PromptMode.yesno: self._display_question_yesno,
|
||||
usertypes.PromptMode.text: self._display_question_input,
|
||||
@ -199,8 +139,9 @@ class Prompter(QObject):
|
||||
log.modes.debug("Question asked, focusing {!r}".format(
|
||||
prompt.lineedit))
|
||||
prompt.lineedit.setFocus()
|
||||
self.show_prompt.emit()
|
||||
self._busy = True
|
||||
prompt.show()
|
||||
# FIXME
|
||||
self._prompt = prompt
|
||||
|
||||
def shutdown(self):
|
||||
"""Cancel all blocking questions.
|
||||
@ -228,8 +169,8 @@ class Prompter(QObject):
|
||||
prompt.txt.setText('')
|
||||
prompt.lineedit.clear()
|
||||
prompt.lineedit.setEchoMode(QLineEdit.Normal)
|
||||
self.hide_prompt.emit()
|
||||
self._busy = False
|
||||
self._prompt.hide() # FIXME
|
||||
self._prompt = None
|
||||
if self._question.answer is None and not self._question.is_aborted:
|
||||
self._question.cancel()
|
||||
|
||||
@ -251,83 +192,24 @@ class Prompter(QObject):
|
||||
prompt = objreg.get('prompt', scope='window', window=self._win_id)
|
||||
text = value if value is not None else prompt.lineedit.text()
|
||||
|
||||
if (self._question.mode == usertypes.PromptMode.user_pwd and
|
||||
self._question.user is None):
|
||||
# User just entered a username
|
||||
self._question.user = text
|
||||
prompt.txt.setText("Password:")
|
||||
prompt.lineedit.clear()
|
||||
prompt.lineedit.setEchoMode(QLineEdit.Password)
|
||||
elif self._question.mode == usertypes.PromptMode.user_pwd:
|
||||
# User just entered a password
|
||||
self._question.answer = AuthTuple(self._question.user, text)
|
||||
modeman.maybe_leave(self._win_id, usertypes.KeyMode.prompt,
|
||||
'prompt accept')
|
||||
self._question.done()
|
||||
elif self._question.mode == usertypes.PromptMode.text:
|
||||
# User just entered text.
|
||||
self._question.answer = text
|
||||
modeman.maybe_leave(self._win_id, usertypes.KeyMode.prompt,
|
||||
'prompt accept')
|
||||
self._question.done()
|
||||
elif self._question.mode == usertypes.PromptMode.download:
|
||||
# User just entered a path for a download.
|
||||
target = usertypes.FileDownloadTarget(text)
|
||||
self._question.answer = target
|
||||
modeman.maybe_leave(self._win_id, usertypes.KeyMode.prompt,
|
||||
'prompt accept')
|
||||
self._question.done()
|
||||
elif self._question.mode == usertypes.PromptMode.yesno:
|
||||
# User wants to accept the default of a yes/no question.
|
||||
if value is None:
|
||||
self._question.answer = self._question.default
|
||||
elif value == 'yes':
|
||||
self._question.answer = True
|
||||
elif value == 'no':
|
||||
self._question.answer = False
|
||||
else:
|
||||
raise cmdexc.CommandError("Invalid value {} - expected "
|
||||
"yes/no!".format(value))
|
||||
modeman.maybe_leave(self._win_id, usertypes.KeyMode.yesno,
|
||||
'yesno accept')
|
||||
self._question.done()
|
||||
elif self._question.mode == usertypes.PromptMode.alert:
|
||||
if value is not None:
|
||||
raise cmdexc.CommandError("No value is permitted with alert "
|
||||
"prompts!")
|
||||
# User acknowledged an alert
|
||||
self._question.answer = None
|
||||
modeman.maybe_leave(self._win_id, usertypes.KeyMode.prompt,
|
||||
'alert accept')
|
||||
self._question.done()
|
||||
else:
|
||||
raise ValueError("Invalid question mode!")
|
||||
self._prompt.accept(text)
|
||||
modeman.maybe_leave(self._win_id, self._question.mode,
|
||||
':prompt-accept')
|
||||
self._question.done()
|
||||
|
||||
@cmdutils.register(instance='prompter', hide=True, scope='window',
|
||||
modes=[usertypes.KeyMode.yesno],
|
||||
deprecated='Use :prompt-accept yes instead!')
|
||||
def prompt_yes(self):
|
||||
"""Answer yes to a yes/no prompt."""
|
||||
if self._question.mode != usertypes.PromptMode.yesno:
|
||||
# We just ignore this if we don't have a yes/no question.
|
||||
return
|
||||
self._question.answer = True
|
||||
modeman.maybe_leave(self._win_id, usertypes.KeyMode.yesno,
|
||||
'yesno accept')
|
||||
self._question.done()
|
||||
self.prompt_accept('yes')
|
||||
|
||||
@cmdutils.register(instance='prompter', hide=True, scope='window',
|
||||
modes=[usertypes.KeyMode.yesno],
|
||||
deprecated='Use :prompt-accept no instead!')
|
||||
def prompt_no(self):
|
||||
"""Answer no to a yes/no prompt."""
|
||||
if self._question.mode != usertypes.PromptMode.yesno:
|
||||
# We just ignore this if we don't have a yes/no question.
|
||||
return
|
||||
self._question.answer = False
|
||||
modeman.maybe_leave(self._win_id, usertypes.KeyMode.yesno,
|
||||
'prompt accept')
|
||||
self._question.done()
|
||||
self.prompt_accept('no')
|
||||
|
||||
@cmdutils.register(instance='prompter', hide=True, scope='window',
|
||||
modes=[usertypes.KeyMode.prompt], maxsplit=0)
|
||||
@ -376,7 +258,7 @@ class Prompter(QObject):
|
||||
question.abort()
|
||||
return None
|
||||
|
||||
if self._busy and not blocking:
|
||||
if self._prompt is not None and not blocking:
|
||||
# We got an async question, but we're already busy with one, so we
|
||||
# just queue it up for later.
|
||||
log.statusbar.debug("Adding {} to queue.".format(question))
|
||||
@ -386,7 +268,7 @@ class Prompter(QObject):
|
||||
if blocking:
|
||||
# If we're blocking we save the old state on the stack, so we can
|
||||
# restore it after exec, if exec gets called multiple times.
|
||||
context = self._get_ctx()
|
||||
old_prompt = self._prompt
|
||||
|
||||
self._question = question
|
||||
self._display_question()
|
||||
@ -401,7 +283,7 @@ class Prompter(QObject):
|
||||
question.completed.connect(loop.quit)
|
||||
question.completed.connect(loop.deleteLater)
|
||||
loop.exec_()
|
||||
if not self._restore_ctx(context):
|
||||
if not self._restore_prompt(old_prompt):
|
||||
# Nothing left to restore, so we can go back to popping async
|
||||
# questions.
|
||||
if self._queue:
|
||||
|
@ -336,7 +336,6 @@ class Question(QObject):
|
||||
For text, a default text as string.
|
||||
For user_pwd, a default username as string.
|
||||
text: The prompt text to display to the user.
|
||||
user: The value the user entered as username.
|
||||
answer: The value the user entered (as password for user_pwd).
|
||||
is_aborted: Whether the question was aborted.
|
||||
|
||||
@ -365,7 +364,6 @@ class Question(QObject):
|
||||
self._mode = None
|
||||
self.default = None
|
||||
self.text = None
|
||||
self.user = None
|
||||
self.answer = None
|
||||
self.is_aborted = False
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user