electrum

Electrum Bitcoin wallet
git clone https://git.parazyd.org/electrum
Log | Files | Refs | Submodules

commit 23fe2062a15d9293a73419b2d9e08ec1c6552927
parent f185906950ba71ffb3f27f794595d8ce09a045a6
Author: qua-non <akshayaurora@gmail.com>
Date:   Fri, 21 Feb 2014 13:20:27 +0530

some further updates to the installation wizzard

Diffstat:
Mgui/kivy/dialog.py | 51++++++++++++++++++++++++++++++++++++++++++++++-----
Mgui/kivy/installwizard.py | 124+++++++++++++++++++++++++++++++++++++++----------------------------------------
Mgui/kivy/main.kv | 4+++-
Mgui/kivy/main_window.py | 21++++++++++++++++-----
4 files changed, 126 insertions(+), 74 deletions(-)

diff --git a/gui/kivy/dialog.py b/gui/kivy/dialog.py @@ -117,26 +117,36 @@ class InfoBubble(Bubble): '''Bubble to be used to display short Help Information''' message = StringProperty(_('Nothing set !')) - '''Message to be displayed defaults to "nothing set"''' + '''Message to be displayed; defaults to "nothing set"''' icon = StringProperty('') ''' Icon to be displayed along with the message defaults to '' + + :attr:`icon` is a `StringProperty` defaults to `''` ''' fs = BooleanProperty(False) ''' Show Bubble in half screen mode + + :attr:`fs` is a `BooleanProperty` defaults to `False` ''' modal = BooleanProperty(False) ''' Allow bubble to be hidden on touch. + + :attr:`modal` is a `BooleanProperty` defauult to `False`. ''' exit = BooleanProperty(False) - ''' exit app after bubble is closes + '''Indicates whether to exit app after bubble is closed. + + :attr:`exit` is a `BooleanProperty` defaults to False. ''' dim_background = BooleanProperty(False) - ''' Whether to draw a background on the windows behind the bubble + ''' Indicates Whether to draw a background on the windows behind the bubble. + + :attr:`dim` is a `BooleanProperty` defaults to `False`. ''' def on_touch_down(self, touch): @@ -151,7 +161,13 @@ class InfoBubble(Bubble): self.modal, self.exit = modal, exit if width: self.width = width - Window.add_widget(self) + if self.modal: + from kivy.uix.modalview import ModalView + self._modal_view = m = ModalView() + Window.add_widget(m) + m.add_widget(self) + else: + Window.add_widget(self) # wait for the bubble to adjust it's size according to text then animate Clock.schedule_once(lambda dt: self._show(pos, duration)) @@ -180,6 +196,10 @@ class InfoBubble(Bubble): ''' Auto fade out the Bubble ''' def on_stop(*l): + if self.modal: + m = self._modal_view + m.remove_widget(self) + Window.remove_widget(m) Window.remove_widget(self) if self.exit: App.get_running_app().stop() @@ -470,13 +490,33 @@ class RestoreSeedDialog(CreateAccountDialog): def on_parent(self, instance, value): if value: - stepper = self.ids.stepper; + tis = self.ids.text_input_seed + tis.focus = True + tis._keyboard.bind(on_key_down=self.on_key_down) + 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 on_key_down(self, keyboard, keycode, key, modifiers): + if keycode[1] == 'enter': + self.on_enter() + #super + + def on_enter(self): + self._remove_keyboard() + # press next + self.ids.next.dispatch('on_release') + + def _remove_keyboard(self): + tis = self.ids.text_input_seed + if tis._keyboard: + tis._keyboard.unbind(on_key_down=self.on_key_down) + tis.focus = False + def close(self): + self._remove_keyboard() if self._back in app.navigation_higherarchy: app.navigation_higherarchy.pop() self._back = None @@ -540,6 +580,7 @@ class ChangePasswordDialog(CreateAccountDialog): if value: stepper = self.ids.stepper stepper.opacity = 1 + self.ids.ti_wallet_name.focus = True stepper.source = 'atlas://gui/kivy/theming/light/stepper_left' self._back = _back = partial(self.ids.back.dispatch, 'on_release') app.navigation_higherarchy.append(_back) diff --git a/gui/kivy/installwizard.py b/gui/kivy/installwizard.py @@ -20,6 +20,13 @@ app = App.get_running_app() class InstallWizard(Widget): + '''Instalation Wizzard. Responsible for instantiating the + creation/restoration of wallets. + + events:: + `on_wizard_complete` Fired when the wizard is done creating/ restoring + wallet/s. + ''' __events__ = ('on_wizard_complete', ) @@ -33,13 +40,15 @@ class InstallWizard(Widget): msg= _("Electrum is generating your addresses," " please wait."), on_complete=None): + '''Perform a blocking task in the background by running the passed + method in a thread. + ''' def target(): # run your threaded function task() # on completion hide message - Clock.schedule_once(lambda dt: - app.show_info_bubble(text="Complete", arrow_pos=None)) + Clock.schedule_once(lambda dt: app.info_bubble.hide()) # call completion routine if on_complete: Clock.schedule_once(lambda dt: on_complete()) @@ -51,12 +60,14 @@ class InstallWizard(Widget): t.start() def run(self): + '''Entry point of our Installation wizard + ''' CreateRestoreDialog(on_release=self.on_creatrestore_complete).open() def on_creatrestore_complete(self, dialog, button): if not button: - self.dispatch('on_wizard_complete', None) - return + return self.dispatch('on_wizard_complete', None) + wallet = Wallet(self.storage) gap = self.config.get('gap_limit', 5) if gap !=5: @@ -70,7 +81,7 @@ class InstallWizard(Widget): elif button == dialog.ids.restore: # restore self.restore_seed_dialog(wallet) - #elif button == dialog.ids.watching: + #if button == dialog.ids.watching: #TODO: not available in the new design # self.action = 'watching' else: @@ -99,30 +110,15 @@ class InstallWizard(Widget): except Exception: import traceback traceback.print_exc(file=sys.stdout) - app.show_error(_('No account tied to this seedphrase'), exit=True) + 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): + wallet_name=None, mode='create'): # renamed from show_seed() '''Can be called directly (password is None) or from a password-protected callback (password is not None)''' @@ -131,7 +127,7 @@ class InstallWizard(Widget): if instance == None: wallet.init_seed(None) else: - return MessageBoxError(message=_('No seed')).open() + return app.show_error(_('No seed')) if password is None or not instance: seed = wallet.get_mnemonic(None) @@ -139,7 +135,7 @@ class InstallWizard(Widget): try: seed = self.wallet.get_seed(password) except Exception: - return MessageBoxError(message=_('Incorrect Password')) + return app.show_error(_('Incorrect Password')) brainwallet = seed @@ -160,8 +156,10 @@ class InstallWizard(Widget): def on_ok_press(_dlg, _btn): _dlg.close() if _btn != _dlg.ids.confirm: - self.change_password_dialog(wallet) + if not instance: + self.change_password_dialog(wallet) return + # confirm if instance is None: # in initial phase def create(password): @@ -173,21 +171,20 @@ class InstallWizard(Widget): Clock.schedule_once(lambda dt: app.show_error(err)) wallet.synchronize() # generate first addresses offline - self.waiting_dialog(partial(create, password), - on_complete=self.load_network) + self.waiting_dialog( + partial(create, password), + on_complete=partial(self.load_network, wallet, mode=mode)) from electrum_gui.kivy.dialog import InitSeedDialog InitSeedDialog(message=msg2, - seed_msg=brainwallet, - seed=seed, - on_release=on_ok_press).open() + seed_msg=brainwallet, seed=seed, on_release=on_ok_press).open() 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)""" if instance and not wallet.seed: - return MessageBoxExit(message=_('No seed !!')).open() + return ShowError(_('No seed !!'), exit=True, modal=True) if instance is not None: if wallet.use_encryption: @@ -210,9 +207,11 @@ class InstallWizard(Widget): 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 CreateRestoreDialog( on_release=self.on_creatrestore_complete).open() return @@ -236,17 +235,20 @@ class InstallWizard(Widget): return app.show_error(_('Passwords do not match')) if mode == 'restore': + try: + wallet.save_seed(new_password) + except Exception as err: + app.show_error(str(err)) + return _dlg.close() - wallet.save_seed(new_password) self.load_network(wallet, mode='restore') return if not instance: # create _dlg.close() - self.load_network(wallet, mode='create') + #self.load_network(wallet, mode='create') return self.init_seed_dialog(password=new_password, - wallet=wallet, - wallet_name=wallet_name) + wallet=wallet, wallet_name=wallet_name, mode=mode) try: seed = wallet.decode_seed(password) @@ -275,48 +277,44 @@ class InstallWizard(Widget): mode=mode, on_release=on_release).open() - def load_network(self, wallet, mode=None): + def load_network(self, wallet, mode='create'): #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) + if self.network: + if self.network.interfaces: + if mode not in ('restore', 'create'): + self.network_dialog() + else: + app.show_error(_('You are offline')) + self.network.stop() + self.network = None + + 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 + 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 + app.show_info(_("This wallet was restored offline." + "It may contain more addresses than displayed.")) + return self.dispatch('on_wizard_complete', wallet) if wallet.is_found(): - app.show_info_bubble(_("Recovery successful"), - width='200dp', - pos=Window.center) + app.show_info(_("Recovery successful")) else: - app.show_info_bubble(_("No transactions found for this seed"), - width='200dp', - pos=Window.center) + app.show_info(_("No transactions found for this seed")) + self.dispatch('on_wizard_complete', wallet) self.waiting_dialog(lambda: wallet.restore(get_text), on_complete=on_complete) - def on_wizard_complete(self, instance, wallet): + def on_wizard_complete(self, wallet): pass diff --git a/gui/kivy/main.kv b/gui/kivy/main.kv @@ -94,7 +94,6 @@ height: self.width if self.fs else (lbl.texture_size[1] + dp(27)) BoxLayout: padding: '5dp' - spacing: '5dp' Widget: size_hint: None, 1 width: '4dp' if root.fs else '2dp' @@ -104,6 +103,9 @@ mipmap: True size_hint: None, 1 width: (root.width - dp(20)) if root.fs else (0 if not root.icon else '32dp') + Widget: + size_hint_y: None + width: '5dp' Label: id: lbl markup: True diff --git a/gui/kivy/main_window.py b/gui/kivy/main_window.py @@ -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) @@ -230,17 +230,27 @@ class ElectrumWindow(App): width='200dp', pos=None, arrow_pos=None, - exit=False): + exit=False, + icon='atlas://gui/kivy/theming/light/error',): ''' Show a error Message Bubble. ''' self.show_info_bubble( text=error, - icon='atlas://gui/kivy/theming/light/error', + icon=icon, width=width, pos=pos or Window.center, arrow_pos=arrow_pos, exit=exit) + def show_info(self, error, + width='200dp', + pos=None, + arrow_pos=None, + exit=False): + ''' Show a Info Message Bubble. + ''' + self.show_error(error, icon='atlas://gui/kivy/theming/light/error') + def show_info_bubble(self, text=_('Hello World'), pos=(0, 0), @@ -265,8 +275,9 @@ class ElectrumWindow(App): info_bubble = self.info_bubble = InfoBubble() if info_bubble.parent: - info_bubble.hide() - return + Window.remove_widget(info_bubble + if not info_bubble.modal else + info_bubble._modal_view) if not arrow_pos: info_bubble.show_arrow = False