URI: 
       tqt wizard: make "GoBack" unroll the call stack to avoid stack overflow - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit f13f46c555b979b265c7da9b6e340b6342f9e4b0
   DIR parent aa32e31a3dbd9a6517ae40187b1160940f764958
  HTML Author: SomberNight <somber.night@protonmail.com>
       Date:   Fri,  3 Apr 2020 18:58:51 +0200
       
       qt wizard: make "GoBack" unroll the call stack to avoid stack overflow
       
       fixes #6069
       
       Diffstat:
         M electrum/base_wizard.py             |      17 ++++++++++-------
         M electrum/gui/qt/installwizard.py    |      32 +++++++++++++++++++------------
       
       2 files changed, 30 insertions(+), 19 deletions(-)
       ---
   DIR diff --git a/electrum/base_wizard.py b/electrum/base_wizard.py
       t@@ -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 = []
   DIR diff --git a/electrum/gui/qt/installwizard.py b/electrum/gui/qt/installwizard.py
       t@@ -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