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