URI: 
       tthe rest of the installation wizard +numerous small fixes - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit f185906950ba71ffb3f27f794595d8ce09a045a6
   DIR parent 30126c544b81bcb8ac6a510da9c9d42acf82ee28
  HTML Author: qua-non <akshayaurora@gmail.com>
       Date:   Thu, 20 Feb 2014 00:24:37 +0530
       
       tthe rest of the installation wizard +numerous small fixes
       
       Diffstat:
         M gui/kivy/dialog.py                  |      62 +++++++++++++++++++++----------
         M gui/kivy/drawer.py                  |      17 ++++++++++++-----
         M gui/kivy/installwizard.py           |     138 ++++++++++++++++++++++++++-----
         M gui/kivy/main.kv                    |     129 +++++++++++++++++++++++--------
         M gui/kivy/main_window.py             |      13 ++++++++-----
         M gui/kivy/theming/light-0.png        |       0 
         D gui/kivy/theming/light-1.png        |       0 
         M gui/kivy/theming/light.atlas        |       4 ++--
         M gui/kivy/theming/light/electrum_ic… |       0 
         M gui/kivy/theming/light/nfc_clock.p… |       0 
       
       10 files changed, 277 insertions(+), 86 deletions(-)
       ---
   DIR diff --git a/gui/kivy/dialog.py b/gui/kivy/dialog.py
       t@@ -131,20 +131,24 @@ class InfoBubble(Bubble):
            ''' Allow bubble to be hidden on touch.
            '''
        
       +    exit = BooleanProperty(False)
       +    ''' exit app after bubble is closes
       +    '''
       +
            dim_background = BooleanProperty(False)
            ''' Whether to draw a background on the windows behind the bubble
            '''
        
            def on_touch_down(self, touch):
                if self.modal:
       -            return
       +            return True
                self.hide()
                if self.collide_point(*touch.pos):
                    return True
        
       -    def show(self, pos, duration, width=None, modal=False):
       +    def show(self, pos, duration, width=None, modal=False, exit=False):
                '''Animate the bubble into position'''
       -        self.modal = modal
       +        self.modal, self.exit = modal, exit
                if width:
                    self.width = width
                Window.add_widget(self)
       t@@ -177,6 +181,11 @@ class InfoBubble(Bubble):
                '''
                def on_stop(*l):
                    Window.remove_widget(self)
       +            if self.exit:
       +                App.get_running_app().stop()
       +                import sys
       +                sys.exit()
       +
                anim = Animation(opacity=0, d=.25)
                anim.bind(on_complete=on_stop)
                anim.cancel_all(self)
       t@@ -412,6 +421,23 @@ class CreateAccountDialog(EventsDialog):
                    self.crcontent.add_widget(widget, index=index)
        
        
       +class CreateRestoreDialog(CreateAccountDialog):
       +    ''' Initial Dialog for creating or restoring seed'''
       +
       +    def on_parent(self, instance, value):
       +        if value:
       +            self.ids.but_close.disabled = True
       +            self.ids.but_close.opacity = 0
       +            self._back = _back = partial(app.dispatch, 'on_back')
       +            app.navigation_higherarchy.append(_back)
       +
       +    def close(self):
       +        if self._back in app.navigation_higherarchy:
       +            app.navigation_higherarchy.pop()
       +            self._back = None
       +        super(CreateRestoreDialog, self).close()
       +
       +
        class InitSeedDialog(CreateAccountDialog):
        
            seed_msg = StringProperty('')
       t@@ -436,30 +462,25 @@ class InitSeedDialog(CreateAccountDialog):
                    self._back = None
                super(InitSeedDialog, self).close()
        
       -class CreateRestoreDialog(CreateAccountDialog):
       -    ''' Initial Dialog for creating or restoring seed'''
       +class VerifySeedDialog(CreateAccountDialog):
       +
       +    pass
       +
       +class RestoreSeedDialog(CreateAccountDialog):
        
            def on_parent(self, instance, value):
                if value:
       -            self.ids.but_close.disabled = True
       -            self.ids.but_close.opacity = 0
       -            self._back = _back = partial(app.dispatch, 'on_back')
       +            stepper = self.ids.stepper;
       +            stepper.opacity = 1
       +            stepper.source = 'atlas://gui/kivy/theming/light/stepper_restore_seed'
       +            self._back = _back = partial(self.ids.back.dispatch, 'on_release')
                    app.navigation_higherarchy.append(_back)
        
            def close(self):
                if self._back in app.navigation_higherarchy:
                    app.navigation_higherarchy.pop()
                    self._back = None
       -        super(CreateRestoreDialog, self).close()
       -
       -
       -class VerifySeedDialog(CreateAccountDialog):
       -
       -    pass
       -
       -class RestoreSeedDialog(CreateAccountDialog):
       -
       -    pass
       +        super(RestoreSeedDialog, self).close()
        
        class NewContactDialog(Popup):
        
       t@@ -508,11 +529,12 @@ class ChangePasswordDialog(CreateAccountDialog):
            message = StringProperty(_('Empty Message'))
            '''Message to be displayed.'''
        
       -    mode = OptionProperty('new', options=('new', 'confirm', 'create'))
       +    mode = OptionProperty('new',
       +                          options=('new', 'confirm', 'create', 'restore'))
            ''' Defines the mode of the password dialog.'''
        
            def validate_new_password(self):
       -        self.ids.confirm.dispatch('on_release')
       +        self.ids.next.dispatch('on_release')
        
            def on_parent(self, instance, value):
                if value:
   DIR diff --git a/gui/kivy/drawer.py b/gui/kivy/drawer.py
       t@@ -31,7 +31,7 @@ class Drawer(StencilView):
            and defaults to 200 (milliseconds)
            '''
        
       -    scroll_distance = NumericProperty('4dp')
       +    scroll_distance = NumericProperty('9dp')
            '''Distance to move before scrolling the :class:`Drawer` in pixels.
            As soon as the distance has been traveled, the :class:`Drawer` will
            start to scroll, and no touch event will go to children.
       t@@ -68,6 +68,11 @@ class Drawer(StencilView):
                if self.disabled:
                    return
        
       +        if not self.collide_point(*touch.pos):
       +            return
       +
       +        touch.grab(self)
       +
                global app
                if not app:
                    from kivy.app import App
       t@@ -91,10 +96,9 @@ class Drawer(StencilView):
                return
        
            def on_touch_move(self, touch):
       -        global app
       -        if not app:
       -            from kivy.app import App
       -            app = App.get_running_app()
       +        if not touch.grab_current:
       +            return
       +
                # skip on tablet mode
                if app.ui_mode[0] == 't':
                    return super(Drawer, self).on_touch_move(touch)
       t@@ -124,6 +128,9 @@ class Drawer(StencilView):
                return
        
            def on_touch_up(self, touch):
       +        if not touch.grab_current:
       +            return
       +
                # skip on tablet mode
                if app.ui_mode[0] == 't':
                    return super(Drawer, self).on_touch_down(touch)
   DIR diff --git a/gui/kivy/installwizard.py b/gui/kivy/installwizard.py
       t@@ -1,14 +1,12 @@
        from electrum import Wallet
        from electrum.i18n import _
       -from electrum_gui.kivy.dialog import (CreateRestoreDialog, InitSeedDialog,
       -    ChangePasswordDialog)
        
        from kivy.app import App
        from kivy.uix.widget import Widget
        from kivy.core.window import Window
        from kivy.clock import Clock
        
       -#from seed_dialog import SeedDialog
       +from electrum_gui.kivy.dialog import CreateRestoreDialog
        #from network_dialog import NetworkDialog
        #from util import *
        #from amountedit import AmountEdit
       t@@ -33,13 +31,18 @@ class InstallWizard(Widget):
        
            def waiting_dialog(self, task,
                               msg= _("Electrum is generating your addresses,"
       -                              " please wait.")):
       +                              " please wait."),
       +                       on_complete=None):
       +
                def target():
       +            # run your threaded function
                    task()
       +            # on  completion hide message
                    Clock.schedule_once(lambda dt:
       -                app.show_info_bubble(text="Complete", duration=.5,
       -                    icon='atlas://gui/kivy/theming/light/important',
       -                    pos=Window.center, width='200dp', arrow_pos=None))
       +                app.show_info_bubble(text="Complete", arrow_pos=None))
       +            # 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',
       t@@ -66,13 +69,58 @@ class InstallWizard(Widget):
                    self.change_password_dialog(wallet=wallet)
                elif button == dialog.ids.restore:
                    # restore
       -            wallet.init_seed(None)
       -            self.restore_seed_dialog()
       +            self.restore_seed_dialog(wallet)
                #elif button == dialog.ids.watching:
       +        #TODO: not available in the new design
                #    self.action = 'watching'
                else:
                    self.dispatch('on_wizard_complete', None)
        
       +    def restore_seed_dialog(self, wallet):
       +        from electrum_gui.kivy.dialog import RestoreSeedDialog
       +        RestoreSeedDialog(
       +            on_release=partial(self.on_verify_restore_ok, wallet)).open()
       +
       +    def on_verify_restore_ok(self, wallet, _dlg, btn, restore=False):
       +
       +        if _dlg.ids.back == btn:
       +            _dlg.close()
       +            CreateRestoreDialog(
       +                on_release=self.on_creatrestore_complete).open()
       +            return
       +
       +        seed = unicode(_dlg.ids.text_input_seed.text)
       +        if not seed:
       +            app.show_error(_("No seed!"))
       +            return
       +
       +        try:
       +            wallet.init_seed(seed)
       +        except Exception:
       +            import traceback
       +            traceback.print_exc(file=sys.stdout)
       +            app.show_error(_('No account tied to this seedphrase'), exit=True)
       +            return
       +
       +        _dlg.close()
       +        self.change_password_dialog(wallet=wallet, mode='restore')
       +        return
       +
       +        from pudb import set_trace; set_trace()
       +        wallet = self.wallet
       +        #is_restore = bool(_dlg.__class__ == RestoreSeedDialog)
       +
       +        # Restore
       +        if len(seed) == 128:
       +            wallet.seed = ''
       +            wallet.init_sequence(str(seed))
       +        else:
       +            wallet.seed = ''
       +            wallet.init_seed(str(seed))
       +            wallet.save_seed()
       +
       +        return self.change_network_dialog()
       +
            def init_seed_dialog(self, wallet=None, instance=None, password=None,
                                 wallet_name=None):
                # renamed from show_seed()
       t@@ -125,15 +173,16 @@ class InstallWizard(Widget):
                                Clock.schedule_once(lambda dt:
                                    app.show_error(err))
                            wallet.synchronize()  # generate first addresses offline
       -                self.waiting_dialog(partial(create, password))
       -
       +                self.waiting_dialog(partial(create, password),
       +                                    on_complete=self.load_network)
        
       +        from electrum_gui.kivy.dialog import InitSeedDialog
                InitSeedDialog(message=msg2,
                                seed_msg=brainwallet,
                                seed=seed,
                                on_release=on_ok_press).open()
        
       -    def change_password_dialog(self, wallet=None, instance=None):
       +    def change_password_dialog(self, wallet=None, instance=None, mode='create'):
                """Can be called directly (instance is None)
                or from a callback (instance is not None)"""
        
       t@@ -154,13 +203,14 @@ class InstallWizard(Widget):
                    msg = _("Please choose a password to encrypt your wallet keys.") +\
                        '\n' + _("Leave these fields empty if you want to disable" + \
                        " encryption.")
       -            mode = 'create'
        
                def on_release(_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':
       +                    return
                        _dlg.close()
                        if not instance:
                            CreateRestoreDialog(
       t@@ -185,25 +235,29 @@ class InstallWizard(Widget):
                            ti_password.focus = True
                        return app.show_error(_('Passwords do not match'))
        
       +            if mode == 'restore':
       +                _dlg.close()
       +                wallet.save_seed(new_password)
       +                self.load_network(wallet, mode='restore')
       +                return
                    if not instance:
       +                # create
                        _dlg.close()
       -                self.init_seed_dialog(password=new_password,
       +                self.load_network(wallet, mode='create')
       +                return self.init_seed_dialog(password=new_password,
                                              wallet=wallet,
                                              wallet_name=wallet_name)
       -                return
        
                    try:
                        seed = wallet.decode_seed(password)
                    except BaseException:
       -                return MessageBoxError(
       -                    message=_('Incorrect Password')).open()
       +                return app.show_error(_('Incorrect Password'))
        
                    # test carefully
                    try:
                        wallet.update_password(seed, password, new_password)
                    except BaseException:
       -                return MessageBoxExit(
       -                    message=_('Failed to update password')).open()
       +                return app.show_error(_('Failed to update password'), exit=True)
                    else:
                        app.show_info_bubble(
                            text=_('Password successfully updated'), duration=1,
       t@@ -213,12 +267,56 @@ class InstallWizard(Widget):
        
                    if instance is None:  # in initial phase
                        self.load_wallet()
       -            self.app.gui.main_gui.update_wallet()
       +            self.app.update_wallet()
        
       +        from electrum_gui.kivy.dialog import ChangePasswordDialog
                cpd = ChangePasswordDialog(
                                     message=msg,
                                     mode=mode,
                                     on_release=on_release).open()
        
       +    def load_network(self, wallet, mode=None):
       +        #if not self.config.get('server'):
       +        if not self.network:
       +            return wallet.start_threads(self.network)
       +
       +        if not self.network.interfaces:
       +            app.show_error(_('You are offline'))
       +            self.network.stop()
       +            self.network = None
       +            return wallet.start_threads(self.network)
       +
       +        if mode not in ('restore', 'create'):
       +            self.network_dialog()
       +            return wallet.start_threads(self.network)
       +
       +        self.config.set_key('auto_cycle', True, True)
       +        wallet.start_threads(self.network)
       +
       +        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_bubble(
       +                    text=_("This wallet was restored offline. It may contain"
       +                           " more addresses than displayed."),
       +                    width='200dp',
       +                    pos=Window.center)
       +                return
       +
       +            if wallet.is_found():
       +                app.show_info_bubble(_("Recovery successful"),
       +                                     width='200dp',
       +                                     pos=Window.center)
       +            else:
       +                app.show_info_bubble(_("No transactions found for this seed"),
       +                                     width='200dp',
       +                                     pos=Window.center)
       +
       +        self.waiting_dialog(lambda: wallet.restore(get_text),
       +                            on_complete=on_complete)
       +
            def on_wizard_complete(self, instance, wallet):
                pass
   DIR diff --git a/gui/kivy/main.kv b/gui/kivy/main.kv
       t@@ -92,9 +92,9 @@
            size_hint: None, None
            width: '270dp' if root.fs else min(self.width, dp(270))
            height: self.width if self.fs else (lbl.texture_size[1] + dp(27))
       -    on_touch_down: self.hide()
            BoxLayout:
                padding: '5dp'
       +        spacing: '5dp'
                Widget:
                    size_hint: None, 1
                    width: '4dp' if root.fs else '2dp'
       t@@ -179,8 +179,8 @@
                        size_hint: 1, None
                        height: grid_logo.height/2.5 if self.opacity else 0
                Widget:
       -            size_hint: 1, None
       -            height: '5dp'
       +            size_hint: None, None
       +            size: '5dp', '5dp'
                GridLayout:
                    cols: 1
                    id: crcontent
       t@@ -219,6 +219,53 @@
                #    text: _('Create a Watching only wallet')
                #    root: root
        
       +<RestoreSeedDialog>
       +    GridLayout
       +        # leave room for future selection of gap through a widget
       +        # removed for mobile
       +        id: text_input_gap
       +        text: '5'
       +
       +        cols: 1
       +        padding: 0, '12dp'
       +        orientation: 'vertical'
       +        spacing: '12dp'
       +        size_hint: 1, None
       +        height: self.minimum_height
       +        CreateAccountTextInput:
       +            id: text_input_seed
       +            size_hint: 1, None
       +            height: '110dp'
       +            hint_text:
       +                _('Enter your seedphrase')
       +        Label:
       +            font_size: '12sp'
       +            text_size: self.width, None
       +            size_hint: 1, None
       +            height: self.texture_size[1]
       +            halign: 'justify'
       +            valign: 'middle'
       +            text:
       +                _('If you need additional information, please check '
       +                '[color=#0000ff][ref=1]'
       +                'https://electrum.org/faq.html#seed[/ref][/color]')
       +            on_ref_press:
       +                import webbrowser
       +                webbrowser.open('https://electrum.org/faq.html#seed')
       +    GridLayout:
       +        rows: 1
       +        spacing: '12dp'
       +        size_hint: 1, None
       +        height: self.minimum_height
       +        CreateAccountButtonBlue:
       +            id: back
       +            text: _('Back')
       +            root: root
       +        CreateAccountButtonGreen:
       +            id: next
       +            text: _('Next')
       +            root: root
       +
        <InitSeedDialog>
            spacing: '12dp'
            GridLayout:
       t@@ -281,37 +328,50 @@
        
        <ChangePasswordDialog>
            padding: '7dp'
       -    CreateAccountTextInput:
       -        id: ti_wallet_name
       -        hint_text: 'Your Wallet Name'
       -        multiline: False
       -        on_text_validate:
       -            next = ti_new_password if ti_password.disabled else ti_password
       -            next.focus = True
       -    CreateAccountTextInput:
       -        id: ti_password
       -        hint_text: 'Enter old pincode'
       +    GridLayout:
                size_hint_y: None
       -        height: 0 if self.disabled else '38sp'
       -        password: True
       -        disabled: True if root.mode in ('new', 'create') else False
       -        opacity: 0 if self.disabled else 1
       -        multiline: False
       -        on_text_validate:
       -            #root.validate_old_password()
       -            ti_new_password.focus = True
       -    CreateAccountTextInput:
       -        id: ti_new_password
       -        hint_text: 'Enter new pincode'
       -        multiline: False
       -        password: True
       -        on_text_validate: ti_confirm_password.focus = True
       -    CreateAccountTextInput:
       -        id: ti_confirm_password
       -        hint_text: 'Confirm pincode'
       -        password: True
       -        multiline: False
       -        on_text_validate: root.validate_new_passowrd()
       +        height: self.minimum_height
       +        cols: 1
       +        CreateAccountTextInput:
       +            id: ti_wallet_name
       +            hint_text: 'Your Wallet Name'
       +            multiline: False
       +            on_text_validate:
       +                next = ti_new_password if ti_password.disabled else ti_password
       +                next.focus = True
       +        Widget:
       +            size_hint_y: None
       +            height: '13dp'
       +        CreateAccountTextInput:
       +            id: ti_password
       +            hint_text: 'Enter old pincode'
       +            size_hint_y: None
       +            height: 0 if self.disabled else '38sp'
       +            password: True
       +            disabled: True if root.mode in ('new', 'create', 'restore') else False
       +            opacity: 0 if self.disabled else 1
       +            multiline: False
       +            on_text_validate:
       +                #root.validate_old_password()
       +                ti_new_password.focus = True
       +        Widget:
       +            size_hint_y: None
       +            height: 0 if ti_password.disabled else '13dp'
       +        CreateAccountTextInput:
       +            id: ti_new_password
       +            hint_text: 'Enter new pincode'
       +            multiline: False
       +            password: True
       +            on_text_validate: ti_confirm_password.focus = True
       +        Widget:
       +            size_hint_y: None
       +            height: '13dp'
       +        CreateAccountTextInput:
       +            id: ti_confirm_password
       +            hint_text: 'Confirm pincode'
       +            password: True
       +            multiline: False
       +            on_text_validate: root.validate_new_password()
            Widget
            GridLayout:
                rows: 1
       t@@ -322,9 +382,10 @@
                    id: back
                    text: _('Back')
                    root: root
       +            disabled: True if root.mode[0] == 'r' else self.disabled
                CreateAccountButtonGreen:
                    id: next
       -            text: _('Next')
       +            text: _('Confirm') if root.mode[0] == 'r' else _('Next')
                    root: root
        
        ###############################################
   DIR diff --git a/gui/kivy/main_window.py b/gui/kivy/main_window.py
       t@@ -106,7 +106,7 @@ class ElectrumWindow(App):
            def on_start(self):
                Window.bind(size=self.on_size,
                            on_keyboard=self.on_keyboard)
       -        Window.bind(keyboard_height=self.on_keyboard_height)
       +        #Window.bind(keyboard_height=self.on_keyboard_height)
                self.on_size(Window, Window.size)
                config = self.electrum_config
                storage = WalletStorage(config)
       t@@ -229,7 +229,8 @@ class ElectrumWindow(App):
            def show_error(self, error,
                           width='200dp',
                           pos=None,
       -                   arrow_pos=None):
       +                   arrow_pos=None,
       +                   exit=False):
                ''' Show a error Message Bubble.
                '''
                self.show_info_bubble(
       t@@ -237,7 +238,8 @@ class ElectrumWindow(App):
                            icon='atlas://gui/kivy/theming/light/error',
                            width=width,
                            pos=pos or Window.center,
       -                    arrow_pos=arrow_pos)
       +                    arrow_pos=arrow_pos,
       +                    exit=exit)
        
            def show_info_bubble(self,
                            text=_('Hello World'),
       t@@ -246,7 +248,8 @@ class ElectrumWindow(App):
                            arrow_pos='bottom_mid',
                            width=None,
                            icon='',
       -                    modal=False):
       +                    modal=False,
       +                    exit=False):
                '''Method to show a Information Bubble
        
                .. parameters::
       t@@ -291,4 +294,4 @@ class ElectrumWindow(App):
                    info_bubble.dim_background = False
                    info_bubble.background_image = 'atlas://data/images/defaulttheme/bubble'
                info_bubble.message = text
       -        info_bubble.show(pos, duration, width, modal=modal)
       +        info_bubble.show(pos, duration, width, modal=modal, exit=exit)
   DIR diff --git a/gui/kivy/theming/light-0.png b/gui/kivy/theming/light-0.png
       Binary files differ.
   DIR diff --git a/gui/kivy/theming/light-1.png b/gui/kivy/theming/light-1.png
       Binary files differ.
   DIR diff --git a/gui/kivy/theming/light.atlas b/gui/kivy/theming/light.atlas
       t@@ -1 +1 @@
parazyd.org:70 /git/electrum/commit/f185906950ba71ffb3f27f794595d8ce09a045a6.gph:649: line too long