URI: 
       tallow offline creation/recovery within the gui - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit cf1f533613549e918bae5c73ae8a8d243fe8b933
   DIR parent 2385cc3ad8f1a72cafca42137272735bd1fdc2a1
  HTML Author: thomasv <thomasv@gitorious>
       Date:   Tue, 20 Nov 2012 15:30:46 +0100
       
       allow offline creation/recovery within the gui
       
       Diffstat:
         M electrum                            |      49 +++++++++++++++++++------------
         M lib/gui.py                          |     118 ++++++++++++++++---------------
         M lib/gui_qt.py                       |      73 ++++++++++++++++---------------
         M lib/interface.py                    |       2 ++
       
       4 files changed, 133 insertions(+), 109 deletions(-)
       ---
   DIR diff --git a/electrum b/electrum
       t@@ -197,36 +197,49 @@ if __name__ == '__main__':
                else:
                    sys.exit("Error: Unknown GUI: " + pref_gui )
        
       +        gui = gui.ElectrumGui(wallet, config)
       +        
                interface = Interface(config, True)
       +        wallet.interface = interface
                interface.start()
                interface.send([('server.peers.subscribe',[])])
        
       -        wallet.interface = interface
       -        
       -        gui = gui.ElectrumGui(wallet, config)
       +        found = config.wallet_file_exists
       +        if not found:
       +            a = gui.restore_or_create()
       +            if not a: exit()
       +
       +            if a =='create':
       +                wallet.new_seed(None)
       +                wallet.init_mpk( wallet.seed )
       +            else:
       +                # ask for seed and gap.
       +                if not gui.seed_dialog(): exit()
       +                wallet.init_mpk( wallet.seed )
       +            
       +            # select a server.
       +            s = gui.network_dialog()
       +            if s is None:
       +                gui.create_wallet()
       +
       +
                interface.register_callback('peers', gui.server_list_changed)
        
                verifier = WalletVerifier(interface, config)
                wallet.set_verifier(verifier)
       -
                WalletSynchronizer(wallet, config).start()
       -        try:
       -            found = config.wallet_file_exists
       -            if not found:
       -                found = gui.restore_or_create()
       -        except SystemExit(e):
       -            exit(e)
       -        except BaseException(e):
       -            import traceback
       -            traceback.print_exc(file=sys.stdout)
       -            #gui.show_message(e.message)
       -            exit(1)
        
       -        if not found:
       -            exit(1)
       +        if not found and a == 'restore' and s is not None:
       +            try:
       +                ok = gui.restore_wallet()
       +            except:
       +                import traceback
       +                traceback.print_exc(file=sys.stdout)
       +                exit()
        
       -        verifier.start()
       +            if not ok: exit()
        
       +        verifier.start()
                gui.main(url)
                wallet.save()
                sys.exit(0)
   DIR diff --git a/lib/gui.py b/lib/gui.py
       t@@ -97,58 +97,8 @@ def restore_create_dialog(wallet):
            dialog.destroy()
        
            if r==2: return False
       -        
       -    is_recovery = (r==1)
       -
       -    # ask for the server.
       -    if not run_network_dialog( wallet, parent=None ): return False
       -
       -    if not is_recovery:
       -
       -        wallet.new_seed(None)
       -        # generate first key
       -        wallet.init_mpk( wallet.seed )
       -        wallet.up_to_date_event.clear()
       -        wallet.update()
       +    return 'restore' if r==1 else 'create'
        
       -        # run a dialog indicating the seed, ask the user to remember it
       -        show_seed_dialog(wallet, None, None)
       -            
       -        #ask for password
       -        change_password_dialog(wallet, None, None)
       -    else:
       -        # ask for seed and gap.
       -        run_recovery_dialog( wallet )
       -
       -        dialog = gtk.MessageDialog(
       -            parent = None,
       -            flags = gtk.DIALOG_MODAL, 
       -            buttons = gtk.BUTTONS_CANCEL, 
       -            message_format = "Please wait..."  )
       -        dialog.show()
       -
       -        def recover_thread( wallet, dialog ):
       -            wallet.init_mpk( wallet.seed ) # not encrypted at this point
       -            wallet.up_to_date_event.clear()
       -            wallet.update()
       -
       -            if wallet.is_found():
       -                # history and addressbook
       -                wallet.update_tx_history()
       -                wallet.fill_addressbook()
       -                print "Recovery successful"
       -
       -            gobject.idle_add( dialog.destroy )
       -
       -        thread.start_new_thread( recover_thread, ( wallet, dialog ) )
       -        r = dialog.run()
       -        dialog.destroy()
       -        if r==gtk.RESPONSE_CANCEL: return False
       -        if not wallet.is_found:
       -            show_message("No transactions found for this seed")
       -
       -    wallet.save()
       -    return True
        
        
        def run_recovery_dialog(wallet):
       t@@ -197,12 +147,13 @@ def run_recovery_dialog(wallet):
            dialog.destroy()
        
            if r==gtk.RESPONSE_CANCEL:
       -        sys.exit(1)
       +        return False
       +
            try:
                gap = int(gap)
            except:
                show_message("error")
       -        sys.exit(1)
       +        return False
        
            try:
                seed.decode('hex')
       t@@ -211,11 +162,12 @@ def run_recovery_dialog(wallet):
                seed = mnemonic.mn_decode( seed.split(' ') )
            if not seed:
                show_message("no seed")
       -        sys.exit(1)
       +        return False
                
            wallet.seed = seed
            wallet.gap_limit = gap
            wallet.save()
       +    return True
        
        
        
       t@@ -328,7 +280,7 @@ def run_network_dialog( wallet, parent ):
                    status = "Not connected"
            else:
                import random
       -        status = "Please choose a server."
       +        status = "Please choose a server.\nSelect cancel if you are offline."
        
            server = interface.server
            plist, servers_list = interface.get_servers_list()
       t@@ -575,6 +527,7 @@ class ElectrumWindow:
                self.window.set_border_width(0)
                self.window.connect('mykeypress', gtk.main_quit)
                self.window.set_default_size(720, 350)
       +        self.wallet_updated = False
        
                vbox = gtk.VBox()
        
       t@@ -651,7 +604,6 @@ class ElectrumWindow:
                self.context_id = self.status_bar.get_context_id("statusbar")
                self.update_status_bar()
        
       -        self.wallet_updated = False
                self.wallet.interface.register_callback('updated', self.update_callback)
        
        
       t@@ -1302,3 +1254,57 @@ class ElectrumGui():
        
            def server_list_changed(self):
                pass
       +
       +    def seed_dialog(self):
       +        # ask for seed and gap.
       +        return run_recovery_dialog( self.wallet )
       +
       +    def network_dialog(self):
       +        return run_network_dialog( self.wallet, parent=None )
       +
       +    def create_wallet(self):
       +        wallet = self.wallet
       +        wallet.new_seed(None)
       +        # generate first key
       +        wallet.init_mpk( wallet.seed )
       +        wallet.synchronize()
       +        #wallet.up_to_date_event.clear()
       +        #wallet.update()
       +        # run a dialog indicating the seed, ask the user to remember it
       +        show_seed_dialog(wallet, None, None)
       +        #ask for password
       +        change_password_dialog(wallet, None, None)
       +
       +    def restore_wallet(self):
       +        wallet = self.wallet
       +
       +        dialog = gtk.MessageDialog(
       +            parent = None,
       +            flags = gtk.DIALOG_MODAL, 
       +            buttons = gtk.BUTTONS_CANCEL, 
       +            message_format = "Please wait..."  )
       +        dialog.show()
       +        wallet.save()
       +
       +        def recover_thread( wallet, dialog ):
       +            wallet.init_mpk( wallet.seed ) # not encrypted at this point
       +            wallet.up_to_date_event.clear()
       +            wallet.update()
       +
       +            if wallet.is_found():
       +                # history and addressbook
       +                wallet.update_tx_history()
       +                wallet.fill_addressbook()
       +                print "Recovery successful"
       +
       +            gobject.idle_add( dialog.destroy )
       +
       +        thread.start_new_thread( recover_thread, ( wallet, dialog ) )
       +        r = dialog.run()
       +        dialog.destroy()
       +        if r==gtk.RESPONSE_CANCEL: return False
       +        if not wallet.is_found:
       +            show_message("No transactions found for this seed")
       +
       +        wallet.save()
       +        return True
   DIR diff --git a/lib/gui_qt.py b/lib/gui_qt.py
       t@@ -1367,11 +1367,13 @@ class ElectrumWindow(QMainWindow):
                        status = _("Connected to")+" %s\n%d blocks"%(interface.host, wallet.verifier.height)
                    else:
                        status = _("Not connected")
       +            server = interface.server
                else:
                    import random
       -            status = _("Please choose a server.")
       +            status = _("Please choose a server.") + "\n" + _("Select 'Cancel' if you are offline.")
       +            server = None
       +            interface.proxy = None
        
       -        server = interface.server
                plist, servers_list = interface.get_servers_list()
        
                d = QDialog(parent)
       t@@ -1414,8 +1416,6 @@ class ElectrumWindow(QMainWindow):
                grid.addWidget(server_host, 0, 2)
                grid.addWidget(server_port, 0, 3)
        
       -        host, port, protocol = server.split(':')
       -
                def change_protocol(p):
                    protocol = protocol_letters[p]
                    host = unicode(server_host.text())
       t@@ -1465,7 +1465,10 @@ class ElectrumWindow(QMainWindow):
                            server_protocol.model().setData(j, QtCore.QVariant(0,False), QtCore.Qt.UserRole-1)
        
        
       -        change_server(host,protocol)
       +        if server:
       +            host, port, protocol = server.split(':')
       +            change_server(host,protocol)
       +
                servers_list_widget.connect(servers_list_widget, SIGNAL('itemClicked(QTreeWidgetItem*, int)'), lambda x: change_server(unicode(x.text(0))))
                grid.addWidget(servers_list_widget, 1, 1, 1, 3)
        
       t@@ -1541,16 +1544,30 @@ class ElectrumGui:
        
        
            def restore_or_create(self):
       -
                msg = _("Wallet file not found.")+"\n"+_("Do you want to create a new wallet, or to restore an existing one?")
                r = QMessageBox.question(None, _('Message'), msg, _('Create'), _('Restore'), _('Cancel'), 0, 2)
       -        if r==2: return False
       +        if r==2: return None
       +        return 'restore' if r==1 else 'create'
       +
       +    def seed_dialog(self):
       +        return ElectrumWindow.seed_dialog( self.wallet )
       +
       +    def network_dialog(self):
       +        return ElectrumWindow.network_dialog( self.wallet, parent=None )
                
       -        is_recovery = (r==1)
       +    def create_wallet(self):
                wallet = self.wallet
       -        # ask for the server.
       -        if not ElectrumWindow.network_dialog( wallet, parent=None ): return False
       +        # generate the first addresses
       +        wallet.synchronize()
       +        # run a dialog indicating the seed, ask the user to remember it
       +        ElectrumWindow.show_seed_dialog(wallet)
       +        # ask for password
       +        ElectrumWindow.change_password_dialog(wallet)
       +        wallet.save()
        
       +
       +    def restore_wallet(self):
       +        wallet = self.wallet
                # wait until we are connected, because the user might have selected another server
                if not wallet.interface.is_connected:
                    waiting = lambda: False if wallet.interface.is_connected else "connecting...\n"
       t@@ -1559,32 +1576,18 @@ class ElectrumGui:
                waiting = lambda: False if wallet.up_to_date else "Please wait...\nAddresses generated: %d\nKilobytes received: %.1f"\
                    %(len(wallet.all_addresses()), wallet.interface.bytes_received/1024.)
        
       -        if not is_recovery:
       -            wallet.new_seed(None)
       -            wallet.init_mpk( wallet.seed )
       -            wallet.up_to_date_event.clear()
       -            wallet.up_to_date = False
       -            wallet.interface.poke('synchronizer')
       -            waiting_dialog(waiting)
       -            # run a dialog indicating the seed, ask the user to remember it
       -            ElectrumWindow.show_seed_dialog(wallet)
       -            #ask for password
       -            ElectrumWindow.change_password_dialog(wallet)
       +        wallet.up_to_date_event.clear()
       +        wallet.up_to_date = False
       +        wallet.interface.poke('synchronizer')
       +        waiting_dialog(waiting)
       +        if wallet.is_found():
       +            # history and addressbook
       +            wallet.fill_addressbook()
       +            print "Recovery successful"
       +            wallet.save()
                else:
       -            # ask for seed and gap.
       -            if not ElectrumWindow.seed_dialog( wallet ): return False
       -            wallet.init_mpk( wallet.seed )
       -            wallet.up_to_date_event.clear()
       -            wallet.up_to_date = False
       -            wallet.interface.poke('synchronizer')
       -            waiting_dialog(waiting)
       -            if wallet.is_found():
       -                # history and addressbook
       -                wallet.fill_addressbook()
       -                print "Recovery successful"
       -                wallet.save()
       -            else:
       -                QMessageBox.information(None, _('Error'), _("No transactions found for this seed"), _('OK'))
       +            QMessageBox.information(None, _('Error'), _("No transactions found for this seed"), _('OK'))
       +            return False
        
                wallet.save()
                return True
   DIR diff --git a/lib/interface.py b/lib/interface.py
       t@@ -352,6 +352,8 @@ class Interface(threading.Thread):
        
        
            def __init__(self, config=None, loop=False):
       +        self.server = None
       +        self.proxy = None
        
                if config is None:
                    from simple_config import SimpleConfig