Browse Source
qt wizard: make "GoBack" unroll the call stack to avoid stack overflow
fixes #6069
hard-fail-on-bad-server-string
SomberNight
5 years ago
No known key found for this signature in database
GPG Key ID: B33B5F232C6271E9
2 changed files with
30 additions and
19 deletions
-
electrum/base_wizard.py
-
electrum/gui/qt/installwizard.py
|
|
@ -113,18 +113,21 @@ class BaseWizard(Logger): |
|
|
|
def can_go_back(self): |
|
|
|
return len(self._stack) > 1 |
|
|
|
|
|
|
|
def go_back(self): |
|
|
|
def go_back(self, *, rerun_previous: bool = True) -> None: |
|
|
|
if not self.can_go_back(): |
|
|
|
return |
|
|
|
# pop 'current' frame |
|
|
|
self._stack.pop() |
|
|
|
# pop 'previous' frame |
|
|
|
stack_item = self._stack.pop() |
|
|
|
prev_frame = self._stack[-1] |
|
|
|
# try to undo side effects since we last entered 'previous' frame |
|
|
|
# FIXME only self.storage is properly restored |
|
|
|
self.data = copy.deepcopy(stack_item.db_data) |
|
|
|
# rerun 'previous' frame |
|
|
|
self.run(stack_item.action, *stack_item.args, **stack_item.kwargs) |
|
|
|
# FIXME only self.data is properly restored |
|
|
|
self.data = copy.deepcopy(prev_frame.db_data) |
|
|
|
|
|
|
|
if rerun_previous: |
|
|
|
# pop 'previous' frame |
|
|
|
self._stack.pop() |
|
|
|
# rerun 'previous' frame |
|
|
|
self.run(prev_frame.action, *prev_frame.args, **prev_frame.kwargs) |
|
|
|
|
|
|
|
def reset_stack(self): |
|
|
|
self._stack = [] |
|
|
|
|
|
@ -96,19 +96,27 @@ def wizard_dialog(func): |
|
|
|
def func_wrapper(*args, **kwargs): |
|
|
|
run_next = kwargs['run_next'] |
|
|
|
wizard = args[0] # type: InstallWizard |
|
|
|
wizard.back_button.setText(_('Back') if wizard.can_go_back() else _('Cancel')) |
|
|
|
try: |
|
|
|
out = func(*args, **kwargs) |
|
|
|
if type(out) is not tuple: |
|
|
|
out = (out,) |
|
|
|
run_next(*out) |
|
|
|
except GoBack: |
|
|
|
if wizard.can_go_back(): |
|
|
|
wizard.go_back() |
|
|
|
return |
|
|
|
else: |
|
|
|
wizard.close() |
|
|
|
while True: |
|
|
|
wizard.back_button.setText(_('Back') if wizard.can_go_back() else _('Cancel')) |
|
|
|
# current dialog |
|
|
|
try: |
|
|
|
out = func(*args, **kwargs) |
|
|
|
if type(out) is not tuple: |
|
|
|
out = (out,) |
|
|
|
except GoBack: |
|
|
|
if not wizard.can_go_back(): |
|
|
|
wizard.close() |
|
|
|
# to go back from the current dialog, we just let the caller unroll the stack: |
|
|
|
raise |
|
|
|
# next dialog |
|
|
|
try: |
|
|
|
run_next(*out) |
|
|
|
except GoBack: |
|
|
|
# to go back from the next dialog, we ask the wizard to restore state |
|
|
|
wizard.go_back(rerun_previous=False) |
|
|
|
# and we re-run the current dialog (by continuing) |
|
|
|
else: |
|
|
|
break |
|
|
|
return func_wrapper |
|
|
|
|
|
|
|
|
|
|
|