URI: 
       tkivy: simplify install wizard - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit f6661fdd2c9970970401b77db8383640222e4a5d
   DIR parent bd3f3c3554c1847724b4b093de50cc8e188b2c56
  HTML Author: ThomasV <thomasv@electrum.org>
       Date:   Thu, 14 Jan 2016 16:54:37 +0100
       
       kivy: simplify install wizard
       
       Diffstat:
         M gui/kivy/uix/dialogs/installwizard… |     371 ++++++++-----------------------
       
       1 file changed, 96 insertions(+), 275 deletions(-)
       ---
   DIR diff --git a/gui/kivy/uix/dialogs/installwizard.py b/gui/kivy/uix/dialogs/installwizard.py
       t@@ -35,30 +35,20 @@ class InstallWizard(Widget):
                self.config  = config
                self.network = network
                self.storage = storage
       +        self.wallet = Wallet(self.storage)
        
       -    def waiting_dialog(self, task,
       -                       msg= _("Electrum is generating your addresses,"
       -                              " please wait."),
       -                       on_complete=None):
       +    def waiting_dialog(self, task, msg):
                '''Perform a blocking task in the background by running the passed
                method in a thread.
                '''
       -
                def target():
       -
                    # run your threaded function
                    try:
                        task()
                    except Exception as err:
                        Clock.schedule_once(lambda dt: app.show_error(str(err)))
       -
                    # on  completion hide message
                    Clock.schedule_once(lambda dt: app.info_bubble.hide(now=True), -1)
       -
       -            # call completion routine
       -            if on_complete:
       -                Clock.schedule_once(lambda dt: on_complete())
       -
                app.show_info_bubble(
                    text=msg, icon='atlas://gui/kivy/theming/light/important',
                    pos=Window.center, width='200sp', arrow_pos=None, modal=True)
       t@@ -72,91 +62,77 @@ class InstallWizard(Widget):
        
            def is_any(self, seed_e):
                text = self.get_seed_text(seed_e)
       -        return (Wallet.is_seed(text) or
       -                Wallet.is_old_mpk(text) or
       -                Wallet.is_xpub(text) or
       -                Wallet.is_xprv(text) or
       -                Wallet.is_address(text) or
       -                Wallet.is_private_key(text))
       +        return Wallet.is_any(text)
        
       -    def run(self, action):
       -        '''Entry point of our Installation wizard
       -        '''
       +    def run(self, action, *args):
       +        '''Entry point of our Installation wizard'''
                if not action:
                    return
       -
       -        Factory.CreateRestoreDialog(
       -            on_release=self.on_creatrestore_complete,
       -            action=action).open()
       -
       -    def on_creatrestore_complete(self, dialog, button):
       -        if not button:
       -            # soft back or escape button pressed
       -            return self.dispatch('on_wizard_complete', None)
       -        dialog.close()
       -
       -        action = dialog.action
       -        if button == dialog.ids.create:
       -            wallet = Wallet(self.storage)
       -            self.password_dialog(wallet=wallet, mode='create')
       -
       -        elif button == dialog.ids.restore:
       -            wallet = None
       -            self.restore_seed_dialog(wallet)
       -
       +        if action == 'new':
       +            self.new()
       +        elif action == 'create':
       +            self.create()
       +        elif action == 'restore':
       +            self.restore()
       +        elif action == 'enter_pin':
       +            self.enter_pin(*args)
       +        elif action == 'confirm_pin':
       +            self.confirm_pin(*args)
       +        elif action == 'add_seed':
       +            self.add_seed(*args)
       +        elif action == 'terminate':
       +            self.terminate()
                else:
       -            self.dispatch('on_wizard_complete', None)
       +            raise BaseException("unknown action", action)
       +
       +    def new(self):
       +        def on_release(dialog, button):
       +            if not button:
       +                # soft back or escape button pressed
       +                return self.dispatch('on_wizard_complete', None)
       +            dialog.close()
       +            action = dialog.action
       +            if button == dialog.ids.create:
       +                self.run('create')
       +            elif button == dialog.ids.restore:
       +                self.run('restore')
       +            else:
       +                self.dispatch('on_wizard_complete', None)
       +        Factory.CreateRestoreDialog(on_release=on_release).open()
        
       -    def restore_seed_dialog(self, wallet):
       -        from electrum_gui.kivy.uix.dialogs.create_restore import\
       -            RestoreSeedDialog
       +    def restore(self):
       +        from create_restore import RestoreSeedDialog
       +        def on_seed(_dlg, btn):
       +            if btn is _dlg.ids.back:
       +                _dlg.close()
       +                self.run('new')
       +                return
       +            text = self.get_seed_text(_dlg.ids.text_input_seed)
       +            need_password = Wallet.should_encrypt(text)
       +            _dlg.close()
       +            if need_password:
       +                self.run('enter_pin', text)
       +            else:
       +                self.wallet = Wallet.from_text(text)
       +                # fixme: sync
                RestoreSeedDialog(
       -            on_release=partial(self.on_verify_restore_ok, wallet),
       +            on_release=partial(on_seed),
                    wizard=weakref.proxy(self)).open()
        
       -
       -    def on_verify_restore_ok(self, wallet, _dlg, btn, restore=False):
       -        if btn in (_dlg.ids.back, _dlg.ids.but_close) :
       -            _dlg.close()
       -            Factory.CreateRestoreDialog(
       -                on_release=self.on_creatrestore_complete).open()
       -            return
       -
       -        seed = self.get_seed_text(_dlg.ids.text_input_seed)
       -        if not seed:
       -            return app.show_error(_("No seed!"), duration=.5)
       -
       -        _dlg.close()
       -
       -        if Wallet.is_seed(seed):
       -            return self.password_dialog(wallet=wallet, mode='restore',
       -                                        seed=seed)
       -        elif Wallet.is_xpub(seed):
       -            wallet = Wallet.from_xpub(seed, self.storage)
       -        elif Wallet.is_address(seed):
       -            wallet = Wallet.from_address(seed, self.storage)
       -        elif Wallet.is_private_key(seed):
       -            wallet = Wallet.from_private_key(seed, self.storage)
       -        else:
       -            return app.show_error(_('Not a valid seed. App will now exit'),
       -                                  exit=True, modal=True, duration=.5)
       -        return
       -
       -
       -    def show_seed(self, wallet=None, instance=None, password=None,
       -                         wallet_name=None, mode='create', seed=''):
       -        if instance and (not wallet or not wallet.seed):
       -            return app.show_error(_('No seed'))
       -
       -        if not seed:
       -            try:
       -                seed = self.wallet.get_seed(password)
       -            except Exception:
       -                return app.show_error(_('Incorrect Password'))
       -
       -        brainwallet = seed
       -
       -        msg2 = _("[color=#414141]"+\
       +    def add_seed(self, seed, password):
       +        def task():
       +            self.wallet.add_seed(seed, password)
       +            self.wallet.create_master_keys(password)
       +            self.wallet.create_main_account()
       +            self.wallet.synchronize()
       +            self.run('terminate')
       +        msg= _("Electrum is generating your addresses, please wait.")
       +        self.waiting_dialog(task, msg)
       +
       +    def create(self):
       +        from create_restore import InitSeedDialog
       +        seed = self.wallet.make_seed()
       +        msg = _("[color=#414141]"+\
                        "[b]PLEASE WRITE DOWN YOUR SEED PASS[/b][/color]"+\
                        "[size=9]\n\n[/size]" +\
                        "[color=#929292]If you ever forget your pincode, your seed" +\
       t@@ -164,195 +140,40 @@ class InstallWizard(Widget):
                        "[b]only way to recover[/b][/color] your wallet. Your " +\
                        " [color=#EB984E][b]Bitcoins[/b][/color] will otherwise be" +\
                        " [color=#EB984E][b]lost forever![/b][/color]")
       -
       -        if wallet.imported_keys:
       -            msg2 += "[b][color=#ff0000ff]" + _("WARNING") + "[/color]:[/b] " +\
       -                    _("Your wallet contains imported keys. These keys cannot" +\
       -                    " be recovered from seed.")
       -
       -        def on_ok_press(_dlg, _btn):
       +        def on_ok(_dlg, _btn):
                    _dlg.close()
       -            mode = _dlg.mode
       -            if _btn != _dlg.ids.confirm:
       -                if not instance:
       -                    self.password_dialog(wallet, mode=mode)
       -                return
       -            # confirm
       -            if instance is None:
       -                # in initial phase create mode
       -                # save seed with password
       -
       -                def create(password):
       -                    wallet.add_seed(seed, password)
       -                    wallet.create_master_keys(password)
       -                    wallet.create_main_account()
       -                    wallet.synchronize()  # generate first addresses offline
       -
       -                self.waiting_dialog(partial(create, password),
       -                                    on_complete=partial(self.load_network,
       -                                                        wallet, mode=mode))
       -
       -
       -        from electrum_gui.kivy.uix.dialogs.create_restore import InitSeedDialog
       -        InitSeedDialog(message=msg2,
       -            seed_msg=brainwallet, on_release=on_ok_press, mode=mode).open()
       -
       -    def password_dialog(self, wallet=None, instance=None, mode='create',
       -                        seed=''):
       -        """Can be called directly (instance is None)
       -        or from a callback (instance is not None)"""
       -        app = App.get_running_app()
       -
       -        if mode != 'create' and wallet and wallet.is_watching_only():
       -            return app.show_error('This is a watching only wallet')
       -
       -        if instance and not wallet.seed:
       -            return app.show_error('No seed !!', exit=True, modal=True)
       -
       -        if instance is not None:
       -            if wallet.use_encryption:
       -                msg = (
       -                    _('Your wallet is encrypted. Use this dialog to change" + \
       -                    " your password.') + '\n' + _('To disable wallet" + \
       -                    " encryption, enter an empty new password.'))
       -                mode = 'confirm'
       +            if _btn == _dlg.ids.confirm:
       +                self.run('enter_pin', seed)
                    else:
       -               msg = _('Your wallet keys are not encrypted')
       -            mode = 'new'
       -        else:
       -            msg = _("Please choose a password to encrypt your wallet keys.") +\
       -                '\n' + _("Leave these fields empty if you want to disable" + \
       -                         " encryption.")
       -
       -        def on_release(wallet, seed, _dlg, _btn):
       -            ti_password = _dlg.ids.ti_password
       -            ti_new_password = _dlg.ids.ti_new_password
       -            ti_confirm_password = _dlg.ids.ti_confirm_password
       -            if _btn != _dlg.ids.next:
       -                if mode == 'restore':
       -                    # back is disabled cause seed is already set
       -                    return
       -                _dlg.close()
       -                if not instance:
       -                    # back on create
       -                    Factory.CreateRestoreDialog(
       -                        on_release=self.on_creatrestore_complete).open()
       -                return
       -
       -            # Confirm
       -            wallet_name = _dlg.ids.ti_wallet_name.text
       -            new_password = unicode(ti_new_password.text)
       -            new_password2 = unicode(ti_confirm_password.text)
       -
       -            if new_password != new_password2:
       -                # passwords don't match
       -                ti_password.text = ""
       -                ti_new_password.text = ""
       -                ti_confirm_password.text = ""
       -                if ti_password.disabled:
       -                    ti_new_password.focus = True
       -                else:
       -                    ti_password.focus = True
       -                return app.show_error(_('Passwords do not match'), duration=.5)
       -
       -            if not new_password:
       -                new_password = None
       -
       -            if mode == 'restore':
       -                password = unicode(ti_password.text)
       -                           # if wallet and wallet.use_encryption else
       -                           # None)
       -                if not password:
       -                    password = None
       -                wallet = Wallet.from_text(seed, password, self.storage)
       -
       -                def on_complete(*l):
       -                    self.load_network(wallet, mode='restore')
       -                    _dlg.close()
       -
       -                self.waiting_dialog(wallet.synchronize,
       -                                    msg=_("generating addresses"),
       -                                    on_complete=on_complete)
       -                return
       -
       -            if not instance:
       -                # create mode
       -                _dlg.close()
       -                seed = wallet.make_seed()
       -
       -                return self.show_seed(password=new_password, wallet=wallet,
       -                                      wallet_name=wallet_name, mode=mode,
       -                                      seed=seed)
       -
       -            # change password mode
       -            try:
       -                seed = wallet.decode_seed(password)
       -            except BaseException:
       -                return app.show_error(_('Incorrect Password'), duration=.5)
       -
       -            # test carefully
       -            try:
       -                wallet.update_password(seed, password, new_password)
       -            except BaseException:
       -                return app.show_error(_('Failed to update password'), exit=True)
       -            else:
       -                app.show_info_bubble(
       -                    text=_('Password successfully updated'), duration=1,
       -                    pos=_btn.pos)
       -            _dlg.close()
       -
       -            if instance is None:  # in initial phase
       -                self.load_wallet()
       -            self.app.update_wallet()
       -
       -        from electrum_gui.kivy.uix.dialogs.create_restore import ChangePasswordDialog
       -        cpd = ChangePasswordDialog(
       -                             message=msg,
       -                             mode=mode,
       -                             on_release=partial(on_release,
       -                                                wallet, seed)).open()
       -
       -    def load_network(self, wallet, mode='create'):
       -        #if not self.config.get('server'):
       -        if self.network:
       -            if self.network.interfaces:
       -                if mode not in ('restore', 'create'):
       -                    self.network_dialog()
       +                self.run('new')
       +        InitSeedDialog(message=msg, seed_msg=seed, on_release=on_ok, mode='create').open()
       +
       +    def enter_pin(self, seed):
       +        from password_dialog import PasswordDialog
       +        def callback(pin):
       +            self.run('confirm_pin', seed, pin)
       +        popup = PasswordDialog('Enter PIN', callback)
       +        popup.open()
       +
       +    def confirm_pin(self, seed, pin):
       +        from password_dialog import PasswordDialog
       +        def callback(conf):
       +            if conf == pin:
       +                self.run('add_seed', seed, pin)
                    else:
       -                app.show_error(_('You are offline'))
       -                self.network.stop()
       -                self.network = None
       +                app = App.get_running_app()
       +                app.show_error(_('Passwords do not match'), duration=.5)
       +        popup = PasswordDialog('Confirm PIN', callback)
       +        popup.open()
        
       -        if mode in ('restore', 'create'):
       -            # auto cycle
       -            self.config.set_key('auto_cycle', True, True)
       -
       -        # start wallet threads
       -        wallet.start_threads(self.network)
       -
       -        if not mode == 'restore':
       -            return self.dispatch('on_wizard_complete', wallet)
       -
       -        def get_text(text):
       -            def set_text(*l): app.info_bubble.ids.lbl.text=text
       -            Clock.schedule_once(set_text)
       -
       -        def on_complete(*l):
       -            if not self.network:
       -                app.show_info(
       -                    _("This wallet was restored offline. It may contain more"
       -                      " addresses than displayed."), duration=.5)
       -                return self.dispatch('on_wizard_complete', wallet)
       -
       -            if wallet.is_found():
       -                app.show_info(_("Recovery successful"), duration=.5)
       -            else:
       -                app.show_info(_("No transactions found for this seed"),
       -                              duration=.5)
       -            return self.dispatch('on_wizard_complete', wallet)
       -
       -        self.waiting_dialog(lambda: wallet.restore(get_text),
       -                            on_complete=on_complete)
       +    def terminate(self):
       +        self.wallet.start_threads(self.network)
       +        app.load_wallet(self.wallet)
       +        self.dispatch('on_wizard_complete', wallet)
        
            def on_wizard_complete(self, wallet):
       -        pass
       +        if wallet.is_found():
       +            app.show_info(_("Recovery successful"), duration=.5)
       +        else:
       +            app.show_info(_("No transactions found for this seed"),
       +                          duration=.5)