tRegister loaded wallets in daemon, to prevent a wallet from being opened twice. Simplify the wizard logic. - electrum - Electrum Bitcoin wallet
 (HTM) git clone https://git.parazyd.org/electrum
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) Submodules
       ---
 (DIR) commit 62868ab29a785d9b03b1d13c409d925c6b2d340b
 (DIR) parent 3d9f321cae28f5806e5d75d9032d3c89a7459dd2
 (HTM) Author: ThomasV <thomasv@electrum.org>
       Date:   Tue,  5 Jan 2016 13:51:03 +0100
       
       Register loaded wallets in daemon, to prevent a wallet from being opened twice.
       Simplify the wizard logic.
       
       Diffstat:
         M electrum                            |       9 +++++----
         M gui/android.py                      |       2 +-
         M gui/gtk.py                          |       4 ++--
         M gui/kivy/__init__.py                |       2 +-
         M gui/qt/__init__.py                  |      13 ++++++-------
         M gui/qt/installwizard.py             |      17 ++++++++++++++++-
         M gui/stdio.py                        |       2 +-
         M gui/text.py                         |       2 +-
         M lib/daemon.py                       |      27 ++++++++++++++-------------
         M lib/wizard.py                       |      75 +++++++++++++------------------
       
       10 files changed, 78 insertions(+), 75 deletions(-)
       ---
 (DIR) diff --git a/electrum b/electrum
       t@@ -98,12 +98,12 @@ def prompt_password(prompt, confirm=True):
        
        
        
       -def init_gui(config, network, plugins):
       +def init_gui(config, network, daemon, plugins):
            gui_name = config.get('gui', 'qt')
            if gui_name in ['lite', 'classic']:
                gui_name = 'qt'
            gui = __import__('electrum_gui.' + gui_name, fromlist=['electrum_gui'])
       -    gui = gui.ElectrumGui(config, network, plugins)
       +    gui = gui.ElectrumGui(config, network, daemon, plugins)
            return gui
        
        
       t@@ -343,9 +343,10 @@ if __name__ == '__main__':
                        plugins.start()
                    else:
                        network = None
       -            gui = init_gui(config, network, plugins)
       -            daemon = Daemon(config, network, gui)
       +            daemon = Daemon(config, network)
                    daemon.start()
       +            gui = init_gui(config, network, daemon, plugins)
       +            daemon.gui = gui
                    gui.main()
                    sys.exit(0)
        
 (DIR) diff --git a/gui/android.py b/gui/android.py
       t@@ -904,7 +904,7 @@ config = None
        
        class ElectrumGui:
        
       -    def __init__(self, _config, _network, plugins):
       +    def __init__(self, _config, _network, daemon, plugins):
                global wallet, network, contacts, config
                network = _network
                config = _config
 (DIR) diff --git a/gui/gtk.py b/gui/gtk.py
       t@@ -1189,7 +1189,7 @@ class ElectrumWindow:
                    tooltip = tx_hash + "\n%d confirmations"%conf if tx_hash else ''
                    details = self.get_tx_details(tx_hash)
        
       -            self.history_list.prepend( [tx_hash, conf_icon, time_str, label, is_default_label,
       +            self.history_list.prepend( [tx_hash, conf_icon, time_str, label, False,
                                                format_satoshis(value,True,self.num_zeros, whitespaces=True),
                                                format_satoshis(balance,False,self.num_zeros, whitespaces=True), tooltip, details] )
                if cursor: self.history_treeview.set_cursor( cursor )
       t@@ -1284,7 +1284,7 @@ class ElectrumWindow:
        
        class ElectrumGui():
        
       -    def __init__(self, config, network, plugins):
       +    def __init__(self, config, network, daemon, plugins):
                self.network = network
                self.config = config
        
 (DIR) diff --git a/gui/kivy/__init__.py b/gui/kivy/__init__.py
       t@@ -35,7 +35,7 @@ from main_window import ElectrumWindow
        
        class ElectrumGui:
        
       -    def __init__(self, config, network, plugins, app=None):
       +    def __init__(self, config, network, daemon, plugins):
                Logger.debug('ElectrumGUI: initialising')
                self.network = network
                self.config = config
 (DIR) diff --git a/gui/qt/__init__.py b/gui/qt/__init__.py
       t@@ -66,7 +66,7 @@ class OpenFileEventFilter(QObject):
        
        class ElectrumGui(MessageBoxMixin):
        
       -    def __init__(self, config, network, plugins):
       +    def __init__(self, config, network, daemon, plugins):
                set_language(config.get('language'))
                # Uncomment this call to verify objects are being properly
                # GC-ed when windows are closed
       t@@ -74,6 +74,7 @@ class ElectrumGui(MessageBoxMixin):
                #                            ElectrumWindow], interval=5)])
                self.network = network
                self.config = config
       +        self.daemon = daemon
                self.plugins = plugins
                self.windows = []
                self.efilter = OpenFileEventFilter(self.windows)
       t@@ -134,12 +135,10 @@ class ElectrumGui(MessageBoxMixin):
                # Use a signal as can be called from daemon thread
                self.app.emit(SIGNAL('new_window'), path, uri)
        
       -    def create_window_for_wallet(self, wallet, task):
       +    def create_window_for_wallet(self, wallet):
                w = ElectrumWindow(self, wallet)
                self.windows.append(w)
                self.build_tray_menu()
       -        if task:
       -            WaitingDialog(w, task[0], task[1])
                # FIXME: Remove in favour of the load_wallet hook
                run_hook('on_new_window', w)
                return w
       t@@ -153,10 +152,10 @@ class ElectrumGui(MessageBoxMixin):
                        break
                else:
                    wizard = InstallWizard(self.config, self.app, self.plugins)
       -            result = wizard.open_wallet(self.network, path)
       -            if not result:
       +            wallet = self.daemon.load_wallet(path, wizard)
       +            if not wallet:
                        return
       -            w = self.create_window_for_wallet(*result)
       +            w = self.create_window_for_wallet(wallet)
        
                if uri:
                    w.pay_to_URI(uri)
 (DIR) diff --git a/gui/qt/installwizard.py b/gui/qt/installwizard.py
       t@@ -17,7 +17,8 @@ from electrum.mnemonic import prepare_seed
        from electrum.wizard import (WizardBase, UserCancelled,
                                     MSG_ENTER_PASSWORD, MSG_RESTORE_PASSPHRASE,
                                     MSG_COSIGNER, MSG_ENTER_SEED_OR_MPK,
       -                             MSG_SHOW_MPK, MSG_VERIFY_SEED)
       +                             MSG_SHOW_MPK, MSG_VERIFY_SEED,
       +                             MSG_GENERATING_WAIT)
        
        class CosignWidget(QWidget):
            size = 120
       t@@ -134,6 +135,20 @@ class InstallWizard(WindowModalDialog, WizardBase):
                if self.config.get('server') is None:
                    self.network_dialog(network)
        
       +    def show_restore(self, wallet, network, action):
       +        def on_finished(b):
       +            if action == 'restore':
       +                if network:
       +                    if wallet.is_found():
       +                        msg = _("Recovery successful")
       +                    else:
       +                        msg = _("No transactions found for this seed")
       +                else:
       +                    msg = _("This wallet was restored offline. It may "
       +                            "contain more addresses than displayed.")
       +                self.show_message(msg)
       +        WaitingDialog(self, MSG_GENERATING_WAIT, wallet.wait_until_synchronized, on_finished)
       +
            def set_layout(self, layout):
                w = QWidget()
                w.setLayout(layout)
 (DIR) diff --git a/gui/stdio.py b/gui/stdio.py
       t@@ -12,7 +12,7 @@ import sys, getpass, datetime
        
        class ElectrumGui:
        
       -    def __init__(self, config, network, plugins):
       +    def __init__(self, config, network, daemon, plugins):
                self.network = network
                self.config = config
                storage = WalletStorage(config.get_wallet_path())
 (DIR) diff --git a/gui/text.py b/gui/text.py
       t@@ -12,7 +12,7 @@ import tty, sys
        
        class ElectrumGui:
        
       -    def __init__(self, config, network, plugins):
       +    def __init__(self, config, network, daemon, plugins):
        
                self.config = config
                self.network = network
 (DIR) diff --git a/lib/daemon.py b/lib/daemon.py
       t@@ -61,16 +61,13 @@ class RequestHandler(SimpleJSONRPCRequestHandler):
        
        class Daemon(DaemonThread):
        
       -    def __init__(self, config, network, gui=None):
       +    def __init__(self, config, network):
                DaemonThread.__init__(self)
                self.config = config
                self.network = network
       -        self.gui = gui
       +        self.gui = None
                self.wallets = {}
       -        if gui is None:
       -            self.wallet = self.load_wallet(config)
       -        else:
       -            self.wallet = None
       +        self.wallet = None
                self.cmd_runner = Commands(self.config, self.wallet, self.network)
                host = config.get('rpchost', 'localhost')
                port = config.get('rpcport', 0)
       t@@ -123,22 +120,26 @@ class Daemon(DaemonThread):
                    response = "Error: Electrum is running in daemon mode. Please stop the daemon first."
                return response
        
       -    def load_wallet(self, config):
       -        path = config.get_wallet_path()
       +    def load_wallet(self, path, wizard=None):
                if path in self.wallets:
                    wallet = self.wallets[path]
                else:
       -            storage = WalletStorage(path)
       -            wallet = Wallet(storage)
       -            wallet.start_threads(self.network)
       -            self.wallets[path] = wallet
       +            if wizard:
       +                wallet = wizard.open_wallet(self.network, path)
       +            else:
       +                storage = WalletStorage(path)
       +                wallet = Wallet(storage)
       +                wallet.start_threads(self.network)
       +            if wallet:
       +                self.wallets[path] = wallet
                return wallet
        
            def run_cmdline(self, config_options):
                config = SimpleConfig(config_options)
                cmdname = config.get('cmd')
                cmd = known_commands[cmdname]
       -        wallet = self.load_wallet(config) if cmd.requires_wallet else None
       +        path = config.get_wallet_path()
       +        wallet = self.load_wallet(path) if cmd.requires_wallet else None
                # arguments passed to function
                args = map(lambda x: config.get(x), cmd.params)
                # decode json arguments
 (DIR) diff --git a/lib/wizard.py b/lib/wizard.py
       t@@ -126,43 +126,9 @@ class WizardBase(PrintError):
                """Choose a server if one is not set in the config anyway."""
                raise NotImplementedError
        
       -    def open_existing_wallet(self, storage, network):
       -        wallet = Wallet(storage)
       -        self.update_wallet_format(wallet)
       -        self.run_wallet_actions(wallet)
       -        wallet.start_threads(network)
       -        return wallet, None
       -
       -    def create_new_wallet(self, storage, network):
       -        action, wallet = self.create_or_restore(storage)
       -        self.run_wallet_actions(wallet)
       -
       -        if network:
       -            self.choose_server(network)
       -        else:
       -            self.show_warning(_('You are offline'))
       -
       -        def task():
       -            # Synchronize before starting the threads
       -            wallet.synchronize()
       -            wallet.start_threads(network)
       -# FIXME
       -#            if action == 'create':
       -#                msg = _('Wallet addresses generated.')
       -#            else:
       -#                wallet.wait_until_synchronized()
       -#                if network:
       -#                    if wallet.is_found():
       -#                        msg = _("Recovery successful")
       -#                    else:
       -#                        msg = _("No transactions found for this seed")
       -#                else:
       -#                    msg = _("This wallet was restored offline. It may "
       -#                            "contain more addresses than displayed.")
       -#            self.show_message(msg)
       -
       -        return wallet, (MSG_GENERATING_WAIT, task)
       -
       +    def show_restore(self, wallet, network, action):
       +        """Show restore result"""
       +        pass
        
            def open_wallet(self, network, filename):
                '''The main entry point of the wizard.  Open a wallet from the given
       t@@ -170,22 +136,43 @@ class WizardBase(PrintError):
                install wizard proper.'''
                storage = WalletStorage(filename)
                if storage.file_exists:
       -            return self.open_existing_wallet(storage, network)
       +            wallet = Wallet(storage)
       +            self.update_wallet_format(wallet)
       +            task = None
                else:
       -            return self.create_new_wallet(storage, network)
       +            cr, wallet = self.create_or_restore(storage)
       +            if not wallet:
       +                return
       +            task = lambda: self.show_restore(wallet, network, cr)
        
       -    def run_wallet_actions(self, wallet):
       -        if not wallet:
       -            return
       -        action = orig_action = wallet.get_action()
       +        action = wallet.get_action()
       +        requires_action = action is not None
                while action:
                    self.run_wallet_action(wallet, action)
                    action = wallet.get_action()
       +
                # Save the wallet after successful completion of actions.
                # It will be saved again once synchronized.
       -        if orig_action:
       +        if requires_action:
                    wallet.storage.write()
        
       +        if network:
       +            self.choose_server(network)
       +        else:
       +            self.show_warning(_('You are offline'))
       +
       +        # start wallet threads
       +        if network:
       +            wallet.start_threads(network)
       +        else:
       +            wallet.synchronize()
       +
       +        if task:
       +            task()
       +
       +        return wallet
       +
       +
            def run_wallet_action(self, wallet, action):
                self.print_error("action %s on %s" % (action, wallet.basename()))
                # Run the action on the wallet plugin, if any, then the