URI: 
       tMove trezor-specific install wizard code to plugin - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit 3e8598c245c55aaa408199bc56800224639bd892
   DIR parent 54cdd551fead951b8c04624ea0b97090b3b10668
  HTML Author: Neil Booth <kyuupichan@gmail.com>
       Date:   Sat,  9 Jan 2016 15:20:31 +0900
       
       Move trezor-specific install wizard code to plugin
       
       Diffstat:
         M gui/qt/installwizard.py             |      85 -------------------------------
         M lib/wizard.py                       |      18 ------------------
         M plugins/trezor/plugin.py            |      22 ++++++++++++----------
         M plugins/trezor/qt_generic.py        |      98 ++++++++++++++++++++++++++++++-
       
       4 files changed, 107 insertions(+), 116 deletions(-)
       ---
   DIR diff --git a/gui/qt/installwizard.py b/gui/qt/installwizard.py
       t@@ -418,88 +418,3 @@ class InstallWizard(WindowModalDialog, WizardBase):
                self.set_layout(vbox)
                if not self.exec_():
                    raise UserCancelled
       -
       -    def request_trezor_init_settings(self, method, device):
       -        vbox = QVBoxLayout()
       -
       -        main_label = QLabel(_("Initialization settings for your %s:") % device)
       -        vbox.addWidget(main_label)
       -
       -        OK_button = OkButton(self, _('Next'))
       -
       -        if method in [self.TIM_NEW, self.TIM_RECOVER]:
       -            gb = QGroupBox()
       -            vbox1 = QVBoxLayout()
       -            gb.setLayout(vbox1)
       -            vbox.addWidget(gb)
       -            gb.setTitle(_("Select your seed length:"))
       -            choices = [
       -                _("12 words"),
       -                _("18 words"),
       -                _("24 words"),
       -            ]
       -            bg = QButtonGroup()
       -            for i, choice in enumerate(choices):
       -                rb = QRadioButton(gb)
       -                rb.setText(choice)
       -                bg.addButton(rb)
       -                bg.setId(rb, i)
       -                vbox1.addWidget(rb)
       -                rb.setChecked(True)
       -            cb_pin = QCheckBox(_('Enable PIN protection'))
       -            cb_pin.setChecked(True)
       -        else:
       -            text = QTextEdit()
       -            text.setMaximumHeight(60)
       -            if method == self.TIM_MNEMONIC:
       -                msg = _("Enter your BIP39 mnemonic:")
       -            else:
       -                msg = _("Enter the master private key beginning with xprv:")
       -                def set_enabled():
       -                    OK_button.setEnabled(Wallet.is_xprv(
       -                        self.get_seed_text(text)))
       -                text.textChanged.connect(set_enabled)
       -                OK_button.setEnabled(False)
       -
       -            vbox.addWidget(QLabel(msg))
       -            vbox.addWidget(text)
       -            pin = QLineEdit()
       -            pin.setValidator(QRegExpValidator(QRegExp('[1-9]{0,10}')))
       -            pin.setMaximumWidth(100)
       -            hbox_pin = QHBoxLayout()
       -            hbox_pin.addWidget(QLabel(_("Enter your PIN (digits 1-9):")))
       -            hbox_pin.addWidget(pin)
       -            hbox_pin.addStretch(1)
       -
       -        label = QLabel(_("Enter a label to name your device:"))
       -        name = QLineEdit()
       -        hl = QHBoxLayout()
       -        hl.addWidget(label)
       -        hl.addWidget(name)
       -        hl.addStretch(1)
       -        vbox.addLayout(hl)
       -
       -        if method in [self.TIM_NEW, self.TIM_RECOVER]:
       -            vbox.addWidget(cb_pin)
       -        else:
       -            vbox.addLayout(hbox_pin)
       -
       -        cb_phrase = QCheckBox(_('Enable Passphrase protection'))
       -        cb_phrase.setChecked(False)
       -        vbox.addWidget(cb_phrase)
       -
       -        vbox.addStretch(1)
       -        vbox.addLayout(Buttons(CancelButton(self), OK_button))
       -        self.set_layout(vbox)
       -
       -        if not self.exec_():
       -            raise UserCancelled
       -
       -        if method in [self.TIM_NEW, self.TIM_RECOVER]:
       -            item = bg.checkedId()
       -            pin = cb_pin.isChecked()
       -        else:
       -            item = ' '.join(str(self.get_seed_text(text)).split())
       -            pin = str(pin.text())
       -
       -        return (item, unicode(name.text()), pin, cb_phrase.isChecked())
   DIR diff --git a/lib/wizard.py b/lib/wizard.py
       t@@ -48,7 +48,6 @@ class WizardBase(PrintError):
                ('multisig',  _("Multi-signature wallet")),
                ('hardware',  _("Hardware wallet")),
            ]
       -    TIM_NEW, TIM_RECOVER, TIM_MNEMONIC, TIM_PRIVKEY = range(0, 4)
        
            # Derived classes must set:
            #   self.language_for_seed
       t@@ -103,23 +102,6 @@ class WizardBase(PrintError):
                dynamic feedback.  If not provided, Wallet.is_any is used."""
                raise NotImplementedError
        
       -    def request_trezor_init_settings(self, method, device):
       -        """Ask the user for the information needed to initialize a trezor-
       -        compatible device.  Method is one of the TIM_ trezor init
       -        method constants.  TIM_NEW and TIM_RECOVER should ask how many
       -        seed words to use, and return 0, 1 or 2 for a 12, 18 or 24
       -        word seed respectively.  TIM_MNEMONIC should ask for a
       -        mnemonic.  TIM_PRIVKEY should ask for a master private key.
       -        All four methods should additionally ask for a name to label
       -        the device, PIN information and whether passphrase protection is
       -        to be enabled (True/False, default to False).  For TIM_NEW and
       -        TIM_RECOVER, the pin information is whether pin protection
       -        is required (True/False, default to True); for TIM_MNEMONIC and
       -        TIM_PRIVKEY is is the pin as a string of digits 1-9.
       -        The result is a 4-tuple: (TIM specific data, label, pininfo,
       -        passphraseprotection)."""
       -        raise NotImplementedError
       -
            def request_many(self, n, xpub_hot=None):
                """If xpub_hot is provided, a new wallet is being created.  Request N
                master public keys for cosigners; xpub_hot is the master xpub
   DIR diff --git a/plugins/trezor/plugin.py b/plugins/trezor/plugin.py
       t@@ -14,7 +14,9 @@ from electrum.transaction import (deserialize, is_extended_pubkey,
        from electrum.wallet import BIP32_HD_Wallet, BIP44_Wallet
        from electrum.util import ThreadJob
        from electrum.plugins import DeviceMgr
       -from electrum.wizard import WizardBase
       +
       +# Trezor initialization methods
       +TIM_NEW, TIM_RECOVER, TIM_MNEMONIC, TIM_PRIVKEY = range(0, 4)
        
        class DeviceDisconnectedError(Exception):
            pass
       t@@ -247,7 +249,7 @@ class TrezorCompatiblePlugin(BasePlugin, ThreadJob):
                if isinstance(wallet, self.wallet_class):
                    self.device_manager().close_wallet(wallet)
        
       -    def initialize_device(self, wallet, wizard):
       +    def initialize_device(self, wallet):
                # Prevent timeouts during initialization
                wallet.last_operation = self.prevent_timeout
        
       t@@ -268,22 +270,22 @@ class TrezorCompatiblePlugin(BasePlugin, ThreadJob):
                    _("Upload a master private key")
                ]
        
       -        method = wizard.query_choice(msg, methods)
       +        method = wallet.handler.query_choice(msg, methods)
                (item, label, pin_protection, passphrase_protection) \
       -            = wizard.request_trezor_init_settings(method, self.device)
       +            = wallet.handler.request_trezor_init_settings(method, self.device)
        
                client = self.get_client(wallet)
                language = 'english'
        
       -        if method == WizardBase.TIM_NEW:
       +        if method == TIM_NEW:
                    strength = 64 * (item + 2)  # 128, 192 or 256
                    client.reset_device(True, strength, passphrase_protection,
                                        pin_protection, label, language)
       -        elif method == WizardBase.TIM_RECOVER:
       +        elif method == TIM_RECOVER:
                    word_count = 6 * (item + 2)  # 12, 18 or 24
                    client.recovery_device(word_count, passphrase_protection,
                                           pin_protection, label, language)
       -        elif method == WizardBase.TIM_MNEMONIC:
       +        elif method == TIM_MNEMONIC:
                    pin = pin_protection  # It's the pin, not a boolean
                    client.load_device_by_mnemonic(str(item), pin,
                                                   passphrase_protection,
       t@@ -293,7 +295,7 @@ class TrezorCompatiblePlugin(BasePlugin, ThreadJob):
                    client.load_device_by_xprv(item, pin, passphrase_protection,
                                               label, language)
        
       -    def select_device(self, wallet, wizard):
       +    def select_device(self, wallet):
                '''Called when creating a new wallet.  Select the device to use.  If
                the device is uninitialized, go through the intialization
                process.'''
       t@@ -306,10 +308,10 @@ class TrezorCompatiblePlugin(BasePlugin, ThreadJob):
                labels = list(map(client_desc, clients))
        
                msg = _("Please select which %s device to use:") % self.device
       -        client = clients[wizard.query_choice(msg, labels)]
       +        client = clients[wallet.handler.query_choice(msg, labels)]
                self.device_manager().pair_wallet(wallet, client)
                if not client.is_initialized():
       -            self.initialize_device(wallet, wizard)
       +            self.initialize_device(wallet)
        
            def on_restore_wallet(self, wallet, wizard):
                assert isinstance(wallet, self.wallet_class)
   DIR diff --git a/plugins/trezor/qt_generic.py b/plugins/trezor/qt_generic.py
       t@@ -8,12 +8,13 @@ from PyQt4.Qt import QVBoxLayout, QLabel, SIGNAL
        from electrum_gui.qt.main_window import StatusBarButton
        from electrum_gui.qt.password_dialog import PasswordDialog
        from electrum_gui.qt.util import *
       -from plugin import TrezorCompatiblePlugin
       +from .plugin import TrezorCompatiblePlugin, TIM_NEW, TIM_RECOVER, TIM_MNEMONIC
        
        from electrum.i18n import _
        from electrum.plugins import hook, DeviceMgr
        from electrum.util import PrintError
       -from electrum.wallet import BIP44_Wallet
       +from electrum.wallet import Wallet, BIP44_Wallet
       +from electrum.wizard import UserCancelled
        
        
        # By far the trickiest thing about this handler is the window stack;
       t@@ -134,6 +135,97 @@ class QtHandler(PrintError):
                finally:
                    assert dialog == self.window_stack.pop()
        
       +    def query_choice(self, msg, labels):
       +        return self.win.query_choice(msg, labels)
       +
       +    def request_trezor_init_settings(self, method, device):
       +        wizard = self.win
       +
       +        vbox = QVBoxLayout()
       +        main_label = QLabel(_("Initialization settings for your %s:") % device)
       +        vbox.addWidget(main_label)
       +        OK_button = OkButton(wizard, _('Next'))
       +
       +        def clean_text(widget):
       +            text = unicode(widget.toPlainText()).strip()
       +            return ' '.join(text.split())
       +
       +        if method in [TIM_NEW, TIM_RECOVER]:
       +            gb = QGroupBox()
       +            vbox1 = QVBoxLayout()
       +            gb.setLayout(vbox1)
       +            vbox.addWidget(gb)
       +            gb.setTitle(_("Select your seed length:"))
       +            choices = [
       +                _("12 words"),
       +                _("18 words"),
       +                _("24 words"),
       +            ]
       +            bg = QButtonGroup()
       +            for i, choice in enumerate(choices):
       +                rb = QRadioButton(gb)
       +                rb.setText(choice)
       +                bg.addButton(rb)
       +                bg.setId(rb, i)
       +                vbox1.addWidget(rb)
       +                rb.setChecked(True)
       +            cb_pin = QCheckBox(_('Enable PIN protection'))
       +            cb_pin.setChecked(True)
       +        else:
       +            text = QTextEdit()
       +            text.setMaximumHeight(60)
       +            if method == TIM_MNEMONIC:
       +                msg = _("Enter your BIP39 mnemonic:")
       +            else:
       +                msg = _("Enter the master private key beginning with xprv:")
       +                def set_enabled():
       +                    OK_button.setEnabled(Wallet.is_xprv(clean_text(text)))
       +                text.textChanged.connect(set_enabled)
       +                OK_button.setEnabled(False)
       +
       +            vbox.addWidget(QLabel(msg))
       +            vbox.addWidget(text)
       +            pin = QLineEdit()
       +            pin.setValidator(QRegExpValidator(QRegExp('[1-9]{0,10}')))
       +            pin.setMaximumWidth(100)
       +            hbox_pin = QHBoxLayout()
       +            hbox_pin.addWidget(QLabel(_("Enter your PIN (digits 1-9):")))
       +            hbox_pin.addWidget(pin)
       +            hbox_pin.addStretch(1)
       +
       +        label = QLabel(_("Enter a label to name your device:"))
       +        name = QLineEdit()
       +        hl = QHBoxLayout()
       +        hl.addWidget(label)
       +        hl.addWidget(name)
       +        hl.addStretch(1)
       +        vbox.addLayout(hl)
       +
       +        if method in [TIM_NEW, TIM_RECOVER]:
       +            vbox.addWidget(cb_pin)
       +        else:
       +            vbox.addLayout(hbox_pin)
       +
       +        cb_phrase = QCheckBox(_('Enable Passphrase protection'))
       +        cb_phrase.setChecked(False)
       +        vbox.addWidget(cb_phrase)
       +
       +        vbox.addStretch(1)
       +        vbox.addLayout(Buttons(CancelButton(wizard), OK_button))
       +
       +        wizard.set_layout(vbox)
       +        if not wizard.exec_():
       +            raise UserCancelled
       +
       +        if method in [TIM_NEW, TIM_RECOVER]:
       +            item = bg.checkedId()
       +            pin = cb_pin.isChecked()
       +        else:
       +            item = ' '.join(str(clean_text(text)).split())
       +            pin = str(pin.text())
       +
       +        return (item, unicode(name.text()), pin, cb_phrase.isChecked())
       +
        
        def qt_plugin_class(base_plugin_class):
        
       t@@ -159,7 +251,7 @@ def qt_plugin_class(base_plugin_class):
            def on_create_wallet(self, wallet, wizard):
                assert type(wallet) == self.wallet_class
                wallet.handler = self.create_handler(wizard)
       -        self.select_device(wallet, wizard)
       +        self.select_device(wallet)
                wallet.create_hd_account(None)
        
            @hook