Clean up Question objects correctly
This commit is contained in:
parent
cb6550debb
commit
b79cdbc416
1
doc/TODO
1
doc/TODO
@ -50,7 +50,6 @@ Downloads
|
||||
Improvements / minor features
|
||||
=============================
|
||||
|
||||
- Make sure Question objects are deleteLater'ed correctly.
|
||||
- qutebrowser local_file.foo should open that file in $PWD
|
||||
- Distinction between :q and :wq, add ZZ and ZQ shortcuts.
|
||||
- set_toggle to toggle setting between two states
|
||||
|
@ -389,11 +389,10 @@ class DownloadManager(QObject):
|
||||
q.default = suggested_filename
|
||||
q.answered.connect(download.set_filename)
|
||||
q.cancelled.connect(download.cancel)
|
||||
q.answered.connect(q.deleteLater)
|
||||
q.cancelled.connect(q.deleteLater)
|
||||
q.completed.connect(q.deleteLater)
|
||||
q.destroyed.connect(partial(self.questions.remove, q))
|
||||
self.questions.append(q)
|
||||
download.cancelled.connect(q.abort)
|
||||
download.cancelled.connect(q.deleteLater)
|
||||
message.instance().ask(q, blocking=False)
|
||||
|
||||
@pyqtSlot(DownloadItem)
|
||||
|
@ -97,6 +97,7 @@ def ask_async(message, mode, handler, default=None):
|
||||
q.mode = mode
|
||||
q.default = default
|
||||
q.answered.connect(handler)
|
||||
q.completed.connect(q.deleteLater)
|
||||
bridge.ask(q, blocking=False)
|
||||
|
||||
|
||||
@ -117,6 +118,7 @@ def confirm_async(message, yes_action, no_action=None, default=None):
|
||||
q.answered_yes.connect(yes_action)
|
||||
if no_action is not None:
|
||||
q.answered_no.connect(no_action)
|
||||
q.completed.connect(q.deleteLater)
|
||||
bridge.ask(q, blocking=False)
|
||||
|
||||
|
||||
|
@ -240,6 +240,10 @@ class Question(QObject):
|
||||
|
||||
"""A question asked to the user, e.g. via the status bar.
|
||||
|
||||
Note the creator is responsible for cleaning up the question after it
|
||||
doesn't need it anymore, e.g. via connecting Question.completed to
|
||||
Question.deleteLater.
|
||||
|
||||
Attributes:
|
||||
mode: A PromptMode enum member.
|
||||
yesno: A question which can be answered with yes/no.
|
||||
@ -256,8 +260,6 @@ class Question(QObject):
|
||||
|
||||
Signals:
|
||||
answered: Emitted when the question has been answered by the user.
|
||||
This is emitted from qutebrowser.widgets.statusbar._prompt so
|
||||
it can be emitted after the mode is left.
|
||||
arg: The answer to the question.
|
||||
cancelled: Emitted when the question has been cancelled by the user.
|
||||
aborted: Emitted when the question was aborted programatically.
|
||||
@ -266,6 +268,7 @@ class Question(QObject):
|
||||
answered with yes.
|
||||
answered_no: Convienience signal emitted when a yesno question was
|
||||
answered with no.
|
||||
completed: Emitted when the question was completed in any way.
|
||||
"""
|
||||
|
||||
answered = pyqtSignal(object)
|
||||
@ -273,6 +276,7 @@ class Question(QObject):
|
||||
aborted = pyqtSignal()
|
||||
answered_yes = pyqtSignal()
|
||||
answered_no = pyqtSignal()
|
||||
completed = pyqtSignal()
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
@ -286,6 +290,21 @@ class Question(QObject):
|
||||
def __repr__(self):
|
||||
return '<{} "{}">'.format(self.__class__.__name__, self.text)
|
||||
|
||||
def done(self):
|
||||
"""Must be called when the queston was answered completely."""
|
||||
self.answered.emit(self.answer)
|
||||
if self.mode == PromptMode.yesno:
|
||||
if self.answer:
|
||||
self.answered_yes.emit()
|
||||
else:
|
||||
self.answered_no.emit()
|
||||
self.completed.emit()
|
||||
|
||||
def cancel(self):
|
||||
"""Cancel the question (resulting from user-input)."""
|
||||
self.cancelled.emit()
|
||||
self.completed.emit()
|
||||
|
||||
def abort(self):
|
||||
"""Abort the question.
|
||||
|
||||
@ -295,6 +314,7 @@ class Question(QObject):
|
||||
self.is_aborted = True
|
||||
try:
|
||||
self.aborted.emit()
|
||||
self.completed.emit()
|
||||
except TypeError as e:
|
||||
# FIXME
|
||||
# We seem to get "pyqtSignal must be bound to a QObject, not
|
||||
|
@ -76,7 +76,7 @@ class Prompt(QWidget):
|
||||
self._input.setEchoMode(QLineEdit.Normal)
|
||||
self.hide_prompt.emit()
|
||||
if self.question.answer is None and not self.question.is_aborted:
|
||||
self.question.cancelled.emit()
|
||||
self.question.cancel()
|
||||
|
||||
@cmdutils.register(instance='mainwindow.status.prompt', hide=True,
|
||||
modes=['prompt'])
|
||||
@ -99,22 +99,22 @@ class Prompt(QWidget):
|
||||
self.question.answer = (self.question.user, password)
|
||||
modeman.leave('prompt', 'prompt accept')
|
||||
self.hide_prompt.emit()
|
||||
self.question.answered.emit(self.question.answer)
|
||||
self.question.done()
|
||||
elif self.question.mode == PromptMode.text:
|
||||
# User just entered text.
|
||||
self.question.answer = self._input.text()
|
||||
modeman.leave('prompt', 'prompt accept')
|
||||
self.question.answered.emit(self.question.answer)
|
||||
self.question.done()
|
||||
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')
|
||||
self.question.answered.emit(self.question.answer)
|
||||
self.question.done()
|
||||
elif self.question.mode == PromptMode.alert:
|
||||
# User acknowledged an alert
|
||||
self.question.answer = None
|
||||
modeman.leave('prompt', 'alert accept')
|
||||
self.question.answered.emit(self.question.answer)
|
||||
self.question.done()
|
||||
else:
|
||||
raise ValueError("Invalid question mode!")
|
||||
|
||||
@ -127,8 +127,7 @@ class Prompt(QWidget):
|
||||
return
|
||||
self.question.answer = True
|
||||
modeman.leave('yesno', 'yesno accept')
|
||||
self.question.answered.emit(self.question.answer)
|
||||
self.question.answered_yes.emit()
|
||||
self.question.done()
|
||||
|
||||
@cmdutils.register(instance='mainwindow.status.prompt', hide=True,
|
||||
modes=['yesno'])
|
||||
@ -139,8 +138,7 @@ class Prompt(QWidget):
|
||||
return
|
||||
self.question.answer = False
|
||||
modeman.leave('yesno', 'prompt accept')
|
||||
self.question.answered.emit(self.question.answer)
|
||||
self.question.answered_no.emit()
|
||||
self.question.done()
|
||||
|
||||
@pyqtSlot(Question, bool)
|
||||
def ask_question(self, question, blocking):
|
||||
|
Loading…
Reference in New Issue
Block a user