electrum

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

commit 4e7f9c061bb2d35706fea1b66f2647157cbea8c1
parent 8c365fd6811016977f365d0b6bfcd2efb712528c
Author: ThomasV <thomasv@electrum.org>
Date:   Fri, 26 Feb 2016 10:17:38 +0100

kivy wizard: do not scan seed as qr code. separate screen for watching only wallets.

Diffstat:
Mgui/kivy/uix/dialogs/create_restore.py | 110+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------
Mgui/kivy/uix/dialogs/installwizard.py | 42++++++++++++++++++++++--------------------
2 files changed, 113 insertions(+), 39 deletions(-)

diff --git a/gui/kivy/uix/dialogs/create_restore.py b/gui/kivy/uix/dialogs/create_restore.py @@ -99,8 +99,8 @@ Builder.load_string(''' text_size: self.width, None height: self.texture_size[1] text: - _("Wallet file not found")+"\\n\\n" +\ - _("Do you want to create a new wallet ")+\ + _("Creating a new wallet.")+" " +\ + _("Do you want to create a wallet with a new seed")+\ _("or restore an existing one?") Widget size_hint: 1, 1 @@ -116,9 +116,13 @@ Builder.load_string(''' text: _('Create a new seed') root: root WizardButton: - id: restore + id: restore_seed text: _('I already have a seed') root: root + WizardButton: + id: restore_xpub + text: _('Watching-only wallet') + root: root <MButton@Button>: @@ -277,10 +281,65 @@ Builder.load_string(''' id: back text: _('Back') root: root + WizardButton: + id: next + text: _('Next') + root: root + disabled: True + + +<RestoreXpubDialog> + word: '' + Label: + color: root.text_color + size_hint: 1, None + text_size: self.width, None + height: self.texture_size[1] + text: "[b]MASTER PUBLIC KEY[/b]" + GridLayout + cols: 1 + padding: 0, '12dp' + orientation: 'vertical' + spacing: '12dp' + size_hint: 1, None + height: self.minimum_height + SeedButton: + id: text_input_seed + text: '' + on_text: Clock.schedule_once(root.on_text) + SeedLabel: + text: root.message + + GridLayout: + rows: 1 + spacing: '12dp' + size_hint: 1, None + height: self.minimum_height IconButton: id: scan + height: '48sp' on_release: root.scan_seed() icon: 'atlas://gui/kivy/theming/light/camera' + size_hint: 1, None + WizardButton: + text: _('Paste') + on_release: root.do_paste() + WizardButton: + text: _('Clear') + on_release: root.do_clear() + + Widget: + size_hint: 1, 1 + + GridLayout: + rows: 1 + spacing: '12dp' + size_hint: 1, None + height: self.minimum_height + WizardButton: + id: back + text: _('Back') + root: root WizardButton: id: next text: _('Next') @@ -397,7 +456,7 @@ class RestoreSeedDialog(WizardDialog): self.mnemonic = Mnemonic('en') def on_text(self, dt): - self.ids.next.disabled = not bool(self._test(self.get_seed_text())) + self.ids.next.disabled = not bool(self._test(self.get_text())) text = self.ids.text_input_seed.text if not text: @@ -432,14 +491,14 @@ class RestoreSeedDialog(WizardDialog): c.disabled = not enable_space def on_word(self, w): - text = self.get_seed_text() + text = self.get_text() words = text.split(' ') words[-1] = w text = ' '.join(words) self.ids.text_input_seed.text = text + ' ' self.ids.suggestions.clear_widgets() - def get_seed_text(self): + def get_text(self): ti = self.ids.text_input_seed text = unicode(ti.text).strip() text = ' '.join(text.split()) @@ -454,12 +513,6 @@ class RestoreSeedDialog(WizardDialog): text += c self.ids.text_input_seed.text = text - def scan_seed(self): - def on_complete(text): - self.ids.text_input_seed.text = text - app = App.get_running_app() - app.scan_qr(on_complete) - def on_parent(self, instance, value): if value: tis = self.ids.text_input_seed @@ -487,10 +540,29 @@ class RestoreSeedDialog(WizardDialog): tis._keyboard.unbind(on_key_down=self.on_key_down) tis.focus = False - def close(self): - #self._remove_keyboard() - app = App.get_running_app() - #if self._back in app.navigation_higherarchy: - # app.navigation_higherarchy.pop() - # self._back = None - super(RestoreSeedDialog, self).close() +class RestoreXpubDialog(WizardDialog): + + message = StringProperty('') + + def __init__(self, **kwargs): + super(RestoreXpubDialog, self).__init__(**kwargs) + self._test = kwargs['test'] + self.app = App.get_running_app() + + def get_text(self): + ti = self.ids.text_input_seed + return unicode(ti.text).strip() + + def on_text(self, dt): + self.ids.next.disabled = not bool(self._test(self.get_text())) + + def scan_seed(self): + def on_complete(text): + self.ids.text_input_seed.text = text + self.app.scan_qr(on_complete) + + def do_paste(self): + self.ids.text_input_seed.text = unicode(self.app._clipboard.paste()) + + def do_clear(self): + self.ids.text_input_seed.text = '' diff --git a/gui/kivy/uix/dialogs/installwizard.py b/gui/kivy/uix/dialogs/installwizard.py @@ -12,7 +12,7 @@ import threading from functools import partial import weakref -from create_restore import CreateRestoreDialog, ShowSeedDialog, RestoreSeedDialog +from create_restore import CreateRestoreDialog, ShowSeedDialog, RestoreSeedDialog, RestoreXpubDialog from password_dialog import PasswordDialog @@ -37,7 +37,6 @@ class InstallWizard(Widget): self.network = network self.storage = storage self.wallet = Wallet(self.storage) - self.is_restore = False def waiting_dialog(self, task, msg, on_complete=None): '''Perform a blocking task in the background by running the passed @@ -79,27 +78,36 @@ class InstallWizard(Widget): action = dialog.action if button == dialog.ids.create: self.run('create') - elif button == dialog.ids.restore: - self.run('restore') + elif button == dialog.ids.restore_seed: + self.run('restore_seed') + elif button == dialog.ids.restore_xpub: + self.run('restore_xpub') else: self.dispatch('on_wizard_complete', None) CreateRestoreDialog(on_release=on_release).open() - def restore(self): - self.is_restore = True + def restore_seed(self): def on_seed(_dlg, btn): _dlg.close() if btn is _dlg.ids.back: self.run('new') return - text = _dlg.get_seed_text() - if Wallet.should_encrypt(text): - self.run('enter_pin', (text,)) - else: - self.run('add_seed', (text, None)) - # fixme: sync - msg = _('You may use the camera to scan your seed. To create a watching-only wallet, scan your master public key.') - RestoreSeedDialog(test=Wallet.is_any, message=msg, on_release=on_seed).open() + text = _dlg.get_text() + self.run('enter_pin', (text,)) + msg = _('Please type your seed phrase using the virtual keyboard.') + RestoreSeedDialog(test=Wallet.is_seed, message=msg, on_release=on_seed).open() + + def restore_xpub(self): + def on_xpub(_dlg, btn): + _dlg.close() + if btn is _dlg.ids.back: + self.run('new') + return + text = _dlg.get_text() + self.run('add_seed', (text, None)) + + msg = _('To create a watching-only wallet, paste your master public key, or scan it using the camera button.') + RestoreXpubDialog(test=Wallet.is_xpub, message=msg, on_release=on_xpub).open() def add_seed(self, text, password): def task(): @@ -114,7 +122,6 @@ class InstallWizard(Widget): self.waiting_dialog(task, msg, self.terminate) def create(self): - self.is_restore = False seed = self.wallet.make_seed() msg = _("If you forget your PIN or lose your device, your seed phrase will be the " "only way to recover your funds.") @@ -156,11 +163,6 @@ class InstallWizard(Widget): def terminate(self): self.wallet.start_threads(self.network) - #if self.is_restore: - # if self.wallet.is_found(): - # app.show_info(_("Recovery successful"), duration=.5) - # else: - # app.show_info(_("No transactions found for this seed"), duration=.5) self.dispatch('on_wizard_complete', self.wallet) def on_wizard_complete(self, wallet):