URI: 
       twizard: some fixes - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit 2da6692f73921f3b651569900a63e9f3ce7fbc57
   DIR parent ef1330df5d3f7b5021bf7fc453657a7ea0d3af1c
  HTML Author: SomberNight <somber.night@protonmail.com>
       Date:   Mon,  4 Mar 2019 02:08:23 +0100
       
       wizard: some fixes
       
       related: #5174
       
       Diffstat:
         M electrum/base_wizard.py             |       9 +++++----
         M electrum/gui/qt/__init__.py         |      84 ++++++++++++++++---------------
         M electrum/gui/qt/installwizard.py    |      23 +++++++++++++----------
         M electrum/storage.py                 |       5 ++++-
       
       4 files changed, 66 insertions(+), 55 deletions(-)
       ---
   DIR diff --git a/electrum/base_wizard.py b/electrum/base_wizard.py
       t@@ -299,7 +299,8 @@ class BaseWizard(object):
                        _('Debug message') + '\n',
                        debug_msg
                    ])
       -            self.confirm_dialog(title=title, message=msg, run_next= lambda x: self.choose_hw_device(purpose))
       +            self.confirm_dialog(title=title, message=msg,
       +                                run_next=lambda x: self.choose_hw_device(purpose, storage=storage))
                    return
                # select device
                self.devices = devices
       t@@ -326,15 +327,15 @@ class BaseWizard(object):
                                    + _('Please try again.'))
                    devmgr = self.plugins.device_manager
                    devmgr.unpair_id(device_info.device.id_)
       -            self.choose_hw_device(purpose)
       +            self.choose_hw_device(purpose, storage=storage)
                    return
                except (UserCancelled, GoBack):
       -            self.choose_hw_device(purpose)
       +            self.choose_hw_device(purpose, storage=storage)
                    return
                except BaseException as e:
                    traceback.print_exc(file=sys.stderr)
                    self.show_error(str(e))
       -            self.choose_hw_device(purpose)
       +            self.choose_hw_device(purpose, storage=storage)
                    return
                if purpose == HWD_SETUP_NEW_WALLET:
                    def f(derivation, script_type):
   DIR diff --git a/electrum/gui/qt/__init__.py b/electrum/gui/qt/__init__.py
       t@@ -28,6 +28,7 @@ import signal
        import sys
        import traceback
        import threading
       +from typing import Optional
        
        
        try:
       t@@ -46,9 +47,9 @@ from electrum.plugin import run_hook
        from electrum.base_wizard import GoBack
        from electrum.util import (UserCancelled, PrintError, profiler,
                                   WalletFileException, BitcoinException, get_new_wallet_name)
       -from electrum.wallet import Wallet
       +from electrum.wallet import Wallet, Abstract_Wallet
        
       -from .installwizard import InstallWizard
       +from .installwizard import InstallWizard, WalletAlreadyOpenInMemory
        
        
        from .util import get_default_language, read_QIcon, ColorScheme
       t@@ -191,7 +192,7 @@ class ElectrumGui(PrintError):
                                        self.network_updated_signal_obj)
                self.nd.show()
        
       -    def create_window_for_wallet(self, wallet):
       +    def _create_window_for_wallet(self, wallet):
                w = ElectrumWindow(self, wallet)
                self.windows.append(w)
                self.build_tray_menu()
       t@@ -212,9 +213,10 @@ class ElectrumGui(PrintError):
                return wrapper
        
            @count_wizards_in_progress
       -    def start_new_window(self, path, uri, app_is_starting=False):
       +    def start_new_window(self, path, uri, *, app_is_starting=False):
                '''Raises the window for the wallet if it is open.  Otherwise
                opens the wallet and creates a new window for it'''
       +        wallet = None
                try:
                    wallet = self.daemon.load_wallet(path, None)
                except BaseException as e:
       t@@ -222,49 +224,20 @@ class ElectrumGui(PrintError):
                    d = QMessageBox(QMessageBox.Warning, _('Error'),
                                    _('Cannot load wallet') + ' (1):\n' + str(e))
                    d.exec_()
       -            if app_is_starting:
       -                # do not return so that the wizard can appear
       -                wallet = None
       -            else:
       +            # if app is starting, still let wizard to appear
       +            if not app_is_starting:
                        return
                if not wallet:
       -            wizard = InstallWizard(self.config, self.app, self.plugins)
       -            storage = None
       -            try:
       -                path, storage = wizard.select_storage(path, self.daemon.get_wallet)
       -                # storage is None if file does not exist
       -                if storage is None:
       -                    wizard.path = path # needed by trustedcoin plugin
       -                    wizard.run('new')
       -                    storage = wizard.create_storage(path)
       -                else:
       -                    wizard.run_upgrades(storage)
       -            except UserCancelled:
       -                return
       -            except GoBack as e:
       -                self.print_error('[start_new_window] Exception caught (GoBack)', e)
       -            except (WalletFileException, BitcoinException) as e:
       -                traceback.print_exc(file=sys.stderr)
       -                d = QMessageBox(QMessageBox.Warning, _('Error'),
       -                                _('Cannot load wallet') + ' (2):\n' + str(e))
       -                d.exec_()
       -                return
       -            finally:
       -                wizard.terminate()
       -            # return if wallet creation is not complete
       -            if storage is None or storage.get_action():
       -                return
       -            wallet = Wallet(storage)
       -            if not self.daemon.get_wallet(wallet.storage.path):
       -                # wallet was not in memory
       -                wallet.start_network(self.daemon.network)
       -                self.daemon.add_wallet(wallet)
       +            wallet = self._start_wizard_to_select_or_create_wallet(path)
       +        if not wallet:
       +            return
       +        # create or raise window
                try:
                    for w in self.windows:
                        if w.wallet.storage.path == wallet.storage.path:
                            break
                    else:
       -                w = self.create_window_for_wallet(wallet)
       +                w = self._create_window_for_wallet(wallet)
                except BaseException as e:
                    traceback.print_exc(file=sys.stdout)
                    d = QMessageBox(QMessageBox.Warning, _('Error'),
       t@@ -284,6 +257,37 @@ class ElectrumGui(PrintError):
                w.activateWindow()
                return w
        
       +    def _start_wizard_to_select_or_create_wallet(self, path) -> Optional[Abstract_Wallet]:
       +        wizard = InstallWizard(self.config, self.app, self.plugins)
       +        try:
       +            path, storage = wizard.select_storage(path, self.daemon.get_wallet)
       +            # storage is None if file does not exist
       +            if storage is None:
       +                wizard.path = path  # needed by trustedcoin plugin
       +                wizard.run('new')
       +                storage = wizard.create_storage(path)
       +            else:
       +                wizard.run_upgrades(storage)
       +        except (UserCancelled, GoBack):
       +            return
       +        except WalletAlreadyOpenInMemory as e:
       +            return e.wallet
       +        except (WalletFileException, BitcoinException) as e:
       +            traceback.print_exc(file=sys.stderr)
       +            d = QMessageBox(QMessageBox.Warning, _('Error'),
       +                            _('Cannot load wallet') + ' (2):\n' + str(e))
       +            d.exec_()
       +            return
       +        finally:
       +            wizard.terminate()
       +        # return if wallet creation is not complete
       +        if storage is None or storage.get_action():
       +            return
       +        wallet = Wallet(storage)
       +        wallet.start_network(self.daemon.network)
       +        self.daemon.add_wallet(wallet)
       +        return wallet
       +
            def close_window(self, window):
                if window in self.windows:
                   self.windows.remove(window)
   DIR diff --git a/electrum/gui/qt/installwizard.py b/electrum/gui/qt/installwizard.py
       t@@ -6,7 +6,7 @@ import os
        import sys
        import threading
        import traceback
       -from typing import Tuple, List, Callable
       +from typing import Tuple, List, Callable, NamedTuple, Optional
        
        from PyQt5.QtCore import QRect, QEventLoop, Qt, pyqtSignal
        from PyQt5.QtGui import QPalette, QPen, QPainter, QPixmap
       t@@ -14,7 +14,7 @@ from PyQt5.QtWidgets import (QWidget, QDialog, QLabel, QHBoxLayout, QMessageBox,
                                     QVBoxLayout, QLineEdit, QFileDialog, QPushButton,
                                     QGridLayout, QSlider, QScrollArea)
        
       -from electrum.wallet import Wallet
       +from electrum.wallet import Wallet, Abstract_Wallet
        from electrum.storage import WalletStorage
        from electrum.util import UserCancelled, InvalidPassword, WalletFileException
        from electrum.base_wizard import BaseWizard, HWD_SETUP_DECRYPT_WALLET, GoBack
       t@@ -104,6 +104,11 @@ def wizard_dialog(func):
            return func_wrapper
        
        
       +class WalletAlreadyOpenInMemory(Exception):
       +    def __init__(self, wallet: Abstract_Wallet):
       +        super().__init__()
       +        self.wallet = wallet
       +
        
        # WindowModalDialog must come first as it overrides show_error
        class InstallWizard(QDialog, MessageBoxMixin, BaseWizard):
       t@@ -162,7 +167,7 @@ class InstallWizard(QDialog, MessageBoxMixin, BaseWizard):
                self.raise_()
                self.refresh_gui()  # Need for QT on MacOSX.  Lame.
        
       -    def select_storage(self, path, get_wallet_from_daemon):
       +    def select_storage(self, path, get_wallet_from_daemon) -> Tuple[str, Optional[WalletStorage]]:
        
                vbox = QVBoxLayout()
                hbox = QHBoxLayout()
       t@@ -254,7 +259,7 @@ class InstallWizard(QDialog, MessageBoxMixin, BaseWizard):
                        break
                    wallet_from_memory = get_wallet_from_daemon(self.temp_storage.path)
                    if wallet_from_memory:
       -                return wallet_from_memory
       +                raise WalletAlreadyOpenInMemory(wallet_from_memory)
                    if self.temp_storage.file_exists() and self.temp_storage.is_encrypted():
                        if self.temp_storage.is_encrypted_with_user_pw():
                            password = self.pw_e.text()
       t@@ -267,7 +272,7 @@ class InstallWizard(QDialog, MessageBoxMixin, BaseWizard):
                            except BaseException as e:
                                traceback.print_exc(file=sys.stdout)
                                QMessageBox.information(None, _('Error'), str(e))
       -                        return
       +                        raise UserCancelled()
                        elif self.temp_storage.is_encrypted_with_hw_device():
                            try:
                                self.run('choose_hw_device', HWD_SETUP_DECRYPT_WALLET, storage=self.temp_storage)
       t@@ -281,11 +286,9 @@ class InstallWizard(QDialog, MessageBoxMixin, BaseWizard):
                            except BaseException as e:
                                traceback.print_exc(file=sys.stdout)
                                QMessageBox.information(None, _('Error'), str(e))
       -                        return
       -                    if self.temp_storage.is_past_initial_decryption():
       -                        break
       -                    else:
       -                        return
       +                        raise UserCancelled()
       +                    assert self.temp_storage.is_past_initial_decryption()
       +                    break
                        else:
                            raise Exception('Unexpected encryption version')
        
   DIR diff --git a/electrum/storage.py b/electrum/storage.py
       t@@ -119,7 +119,10 @@ class WalletStorage(PrintError):
                    if encryption is disabled completely (self.is_encrypted() == False),
                    or if encryption is enabled but the contents have already been decrypted.
                """
       -        return bool(self.db.data)
       +        try:
       +            return bool(self.db.data)
       +        except AttributeError:
       +            return False
        
            def is_encrypted(self):
                """Return if storage encryption is currently enabled."""