URI: 
       tMerge pull request #4396 from SomberNight/storage_upgrade_wizard - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit 8d07094ede7ff3e29df4b0fd7b22e234c75aca53
   DIR parent 4fc677c8766b0e1638bce900f96874d2d013e895
  HTML Author: ThomasV <thomasv@electrum.org>
       Date:   Fri,  1 Jun 2018 13:22:10 +0200
       
       Merge pull request #4396 from SomberNight/storage_upgrade_wizard
       
       storage upgrade as part of the wizard. fix storage upgrade on kivy.
       Diffstat:
         M gui/kivy/main_window.py             |       2 +-
         M gui/kivy/uix/dialogs/installwizard… |       4 +++-
         M gui/qt/installwizard.py             |      31 ++++++++++++++++++++-----------
         M lib/base_wizard.py                  |       9 ++++++++-
         M lib/daemon.py                       |       2 --
         M lib/storage.py                      |      15 +++++++++++----
       
       6 files changed, 43 insertions(+), 20 deletions(-)
       ---
   DIR diff --git a/gui/kivy/main_window.py b/gui/kivy/main_window.py
       t@@ -503,7 +503,7 @@ class ElectrumWindow(App):
                        self.load_wallet(wallet)
                else:
                    Logger.debug('Electrum: Wallet not found. Launching install wizard')
       -            storage = WalletStorage(path)
       +            storage = WalletStorage(path, manual_upgrades=True)
                    wizard = Factory.InstallWizard(self.electrum_config, storage)
                    wizard.bind(on_wizard_complete=self.on_wizard_complete)
                    action = wizard.storage.get_action()
   DIR diff --git a/gui/kivy/uix/dialogs/installwizard.py b/gui/kivy/uix/dialogs/installwizard.py
       t@@ -744,7 +744,7 @@ class InstallWizard(BaseWizard, Widget):
                """overriden by main_window"""
                pass
        
       -    def waiting_dialog(self, task, msg):
       +    def waiting_dialog(self, task, msg, on_finished=None):
                '''Perform a blocking task in the background by running the passed
                method in a thread.
                '''
       t@@ -756,6 +756,8 @@ class InstallWizard(BaseWizard, Widget):
                        self.show_error(str(err))
                    # on  completion hide message
                    Clock.schedule_once(lambda dt: app.info_bubble.hide(now=True), -1)
       +            if on_finished:
       +                Clock.schedule_once(lambda dt: on_finished(), -1)
        
                app = App.get_running_app()
                app.show_info_bubble(
   DIR diff --git a/gui/qt/installwizard.py b/gui/qt/installwizard.py
       t@@ -284,13 +284,8 @@ class InstallWizard(QDialog, MessageBoxMixin, BaseWizard):
                        self.show_warning(_('The file was removed'))
                    return
        
       -        if self.storage.requires_upgrade():
       -            self.storage.upgrade()
       -            self.wallet = Wallet(self.storage)
       -            return self.wallet
       -
                action = self.storage.get_action()
       -        if action and action != 'new':
       +        if action and action not in ('new', 'upgrade_storage'):
                    self.hide()
                    msg = _("The file '{}' contains an incompletely created wallet.\n"
                            "Do you want to complete its creation now?").format(path)
       t@@ -473,12 +468,26 @@ class InstallWizard(QDialog, MessageBoxMixin, BaseWizard):
            def terminate(self):
                self.accept_signal.emit()
        
       -    def waiting_dialog(self, task, msg):
       -        self.please_wait.setText(msg)
       -        self.refresh_gui()
       -        t = threading.Thread(target = task)
       +    def waiting_dialog(self, task, msg, on_finished=None):
       +        label = WWLabel(msg)
       +        vbox = QVBoxLayout()
       +        vbox.addSpacing(100)
       +        label.setMinimumWidth(300)
       +        label.setAlignment(Qt.AlignCenter)
       +        vbox.addWidget(label)
       +        self.set_layout(vbox, next_enabled=False)
       +        self.back_button.setEnabled(False)
       +
       +        t = threading.Thread(target=task)
                t.start()
       -        t.join()
       +        while True:
       +            t.join(1.0/60)
       +            if t.is_alive():
       +                self.refresh_gui()
       +            else:
       +                break
       +        if on_finished:
       +            on_finished()
        
            @wizard_dialog
            def choice_dialog(self, title, message, choices, run_next):
   DIR diff --git a/lib/base_wizard.py b/lib/base_wizard.py
       t@@ -26,11 +26,12 @@
        import os
        import sys
        import traceback
       +from functools import partial
        
        from . import bitcoin
        from . import keystore
        from .keystore import bip44_derivation
       -from .wallet import Imported_Wallet, Standard_Wallet, Multisig_Wallet, wallet_types
       +from .wallet import Imported_Wallet, Standard_Wallet, Multisig_Wallet, wallet_types, Wallet
        from .storage import STO_EV_USER_PW, STO_EV_XPUB_PW, get_derivation_used_for_hw_device_encryption
        from .i18n import _
        from .util import UserCancelled, InvalidPassword
       t@@ -100,6 +101,12 @@ class BaseWizard(object):
                choices = [pair for pair in wallet_kinds if pair[0] in wallet_types]
                self.choice_dialog(title=title, message=message, choices=choices, run_next=self.on_wallet_type)
        
       +    def upgrade_storage(self):
       +        def on_finished():
       +            self.wallet = Wallet(self.storage)
       +            self.terminate()
       +        self.waiting_dialog(partial(self.storage.upgrade), _('Upgrading wallet format...'), on_finished=on_finished)
       +
            def load_2fa(self):
                self.storage.put('wallet_type', '2fa')
                self.storage.put('use_trustedcoin', True)
   DIR diff --git a/lib/daemon.py b/lib/daemon.py
       t@@ -238,8 +238,6 @@ class Daemon(DaemonThread):
                    storage.decrypt(password)
                if storage.requires_split():
                    return
       -        if storage.requires_upgrade():
       -            return
                if storage.get_action():
                    return
                wallet = Wallet(storage)
   DIR diff --git a/lib/storage.py b/lib/storage.py
       t@@ -578,10 +578,17 @@ class WalletStorage(PrintError):
                    return True
        
            def get_action(self):
       -        action = run_hook('get_action', self)
       -        if action:
       -            return action
       -        if not self.file_exists():
       +        if self.file_exists():
       +            action = run_hook('get_action', self)
       +            if action and self.requires_upgrade():
       +                raise WalletFileException(_('Incomplete wallet files cannot be upgraded.'))
       +            elif self.requires_upgrade():
       +                return 'upgrade_storage'
       +            elif action:
       +                return action
       +            else:
       +                return None
       +        else:
                    return 'new'
        
            def get_seed_version(self):