URI: 
       tmove update thread into the interface - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit ee396a063303a341c6615904561b8ac2b4531797
   DIR parent a00b1e73a2c83f1528b9ee674ecef1a57f534e82
  HTML Author: thomasv <thomasv@gitorious>
       Date:   Wed,  8 Feb 2012 13:37:14 +0100
       
       move update thread into the interface
       
       Diffstat:
         M client/electrum                     |      15 ++++++++-------
         M client/gui.py                       |      90 ++++++++++---------------------
         M client/interface.py                 |      69 ++++++++++++++++++++++++++++++
         M client/wallet.py                    |      17 -----------------
       
       4 files changed, 106 insertions(+), 85 deletions(-)
       ---
   DIR diff --git a/client/electrum b/client/electrum
       t@@ -61,6 +61,7 @@ if __name__ == '__main__':
                import gui
                gui.init_wallet(wallet)
                gui = gui.BitcoinGUI(wallet)
       +        interface.start(wallet)
        
                if re.match('^bitcoin:', cmd):
        
       t@@ -111,12 +112,12 @@ if __name__ == '__main__':
                else:
                    password = None
        
       -        host = raw_input("server (default:%s):"%wallet.interface.host)
       -        port = raw_input("port (default:%d):"%wallet.interface.port)
       +        host = raw_input("server (default:%s):"%interface.host)
       +        port = raw_input("port (default:%d):"%interface.port)
                fee = raw_input("fee (default:%s):"%( str(Decimal(wallet.fee)/100000000)) )
                if fee: wallet.fee = float(fee)
       -        if host: wallet.interface.host = host
       -        if port: wallet.interface.port = int(port)
       +        if host: interface.host = host
       +        if port: interface.port = int(port)
                seed = raw_input("if you are restoring an existing wallet, enter the seed. otherwise just press enter: ")
                wallet.gap_limit = 5
                if seed:
       t@@ -153,8 +154,8 @@ if __name__ == '__main__':
        
            # open session
            if cmd not in ['password', 'mktx', 'history', 'label', 'contacts', 'help', 'validateaddress', 'signmessage', 'verifymessage', 'eval']:
       -        wallet.interface.new_session(wallet.all_addresses(), wallet.electrum_version)
       -        wallet.update()
       +        interface.new_session(wallet.all_addresses(), wallet.electrum_version)
       +        interface.update_wallet(wallet)
                wallet.save()
        
            # commands needing password
       t@@ -311,7 +312,7 @@ if __name__ == '__main__':
                        print "invalid key pair"
                        exit(1)
                    addr = wallet.imported_keys.keys()[0]
       -            wallet.history[addr] = wallet.interface.retrieve_history(addr)
       +            wallet.history[addr] = interface.retrieve_history(addr)
                    wallet.synchronize()
                    wallet.update_tx_history()
                    wallet.addresses = []
   DIR diff --git a/client/gui.py b/client/gui.py
       t@@ -486,10 +486,8 @@ class BitcoinGUI:
                show_message(msg, self.window)
        
            def __init__(self, wallet):
       -        self.error = ''
                self.wallet = wallet
       -        self.wallet.interface.is_connected = False
       -        self.period = 5
       +        self.funds_error = False # True if not enough funds
        
                self.window = MyWindow(gtk.WINDOW_TOPLEVEL)
                self.window.set_title(APP_NAME + " " + self.wallet.electrum_version)
       t@@ -596,52 +594,6 @@ class BitcoinGUI:
                                    gobject.idle_add( lambda: self.payto_entry.set_text(s) )
                        
        
       -        def update_wallet_thread():
       -            while True:
       -                try:
       -                    self.wallet.interface.is_connected = False
       -                    self.wallet.interface.new_session(self.wallet.all_addresses(), self.wallet.electrum_version)
       -                    self.update_session = False
       -                    self.info.set_text( self.wallet.interface.message)
       -                except:
       -                    traceback.print_exc(file=sys.stdout)
       -                    time.sleep(self.period)
       -                    continue
       -
       -                get_servers_time = 0
       -                while True:
       -                    try:
       -                        if self.wallet.interface.is_connected and self.update_session:
       -                            self.wallet.interface.update_session( self.wallet.all_addresses() )
       -                            self.update_session = False
       -
       -                        if time.time() - get_servers_time > 5*60:
       -                            wallet.interface.get_servers()
       -                        get_servers_time = time.time()
       -                        
       -                        self.period = 15 if self.wallet.interface.use_http() else 5
       -                        if self.wallet.update():
       -                            self.wallet.interface.update_session( self.wallet.all_addresses() )
       -                            gobject.idle_add( self.update_history_tab )
       -                            gobject.idle_add( self.update_receiving_tab )
       -                            # addressbook too...
       -
       -                        time.sleep(self.period)
       -                    except BaseException:
       -                        traceback.print_exc(file=sys.stdout)
       -                        print "starting new session"
       -                        break
       -                    except socket.gaierror:
       -                        self.wallet.interface.is_connected = False
       -                        break
       -                    except:
       -                        self.wallet.interface.is_connected = False
       -                        print "error"
       -                        traceback.print_exc(file=sys.stdout)
       -                        break
       -                self.error = '' if self.wallet.interface.is_connected else "Not connected"
       -                    
       -        thread.start_new_thread(update_wallet_thread, ())
                thread.start_new_thread(update_status_bar_thread, ())
                thread.start_new_thread(check_recipient_thread, ())
                self.notebook.set_current_page(0)
       t@@ -719,11 +671,11 @@ class BitcoinGUI:
                self.user_fee = False
        
                def entry_changed( entry, is_fee ):
       +            self.funds_error = False
                    amount = numbify(amount_entry)
                    fee = numbify(fee_entry)
                    if not is_fee: fee = None
       -            if amount is None: 
       -                #self.fee_box.hide();
       +            if amount is None:
                        return
                    inputs, total, fee = self.wallet.choose_tx_inputs( amount, fee )
                    if not is_fee:
       t@@ -733,12 +685,11 @@ class BitcoinGUI:
                        amount_entry.modify_text(gtk.STATE_NORMAL, gtk.gdk.color_parse("#000000"))
                        fee_entry.modify_text(gtk.STATE_NORMAL, gtk.gdk.color_parse("#000000"))
                        send_button.set_sensitive(True)
       -                self.error = ''
                    else:
                        send_button.set_sensitive(False)
                        amount_entry.modify_text(gtk.STATE_NORMAL, gtk.gdk.color_parse("#cc0000"))
                        fee_entry.modify_text(gtk.STATE_NORMAL, gtk.gdk.color_parse("#cc0000"))
       -                self.error = 'Not enough funds'
       +                self.funds_error = True
        
                amount_entry.connect('changed', entry_changed, False)
                fee_entry.connect('changed', entry_changed, True)        
       t@@ -1173,18 +1124,35 @@ class BitcoinGUI:
                return vbox
        
            def update_status_bar(self):
       -        c, u = self.wallet.get_balance()
       -        if self.wallet.interface.is_connected:
       -            self.status_image.set_from_stock(gtk.STOCK_YES, gtk.ICON_SIZE_MENU)
       -            self.network_button.set_tooltip_text("Connected to %s.\n%d blocks\nresponse time: %f"%(self.wallet.interface.host, self.wallet.interface.blocks, self.wallet.interface.rtime))
       +
       +        if self.funds_error:
       +            text = "Not enough funds"
       +        elif self.wallet.interface.is_connected:
       +            if self.wallet.interface.blocks > 0:
       +                self.status_image.set_from_stock(gtk.STOCK_YES, gtk.ICON_SIZE_MENU)
       +                self.network_button.set_tooltip_text("Connected to %s.\n%d blocks\nresponse time: %f"%(self.wallet.interface.host, self.wallet.interface.blocks, self.wallet.interface.rtime))
       +                c, u = self.wallet.get_balance()
       +                text =  "Balance: %s "%( format_satoshis(c) )
       +                if u: text +=  "[%s unconfirmed]"%( format_satoshis(u,True) )
       +            else:
       +                self.status_image.set_from_stock(gtk.STOCK_STOP, gtk.ICON_SIZE_MENU)
       +                self.network_button.set_tooltip_text("Connected to %s.\n%d blocks\nresponse time: %f"%(self.wallet.interface.host, self.wallet.interface.blocks, self.wallet.interface.rtime))
       +                text = "Server not ready"
                else:
                    self.status_image.set_from_stock(gtk.STOCK_NO, gtk.ICON_SIZE_MENU)
                    self.network_button.set_tooltip_text("Trying to contact %s.\n%d blocks"%(self.wallet.interface.host, self.wallet.interface.blocks))
       -        text =  "Balance: %s "%( format_satoshis(c) )
       -        if u: text +=  "[%s unconfirmed]"%( format_satoshis(u,True) )
       -        if self.error: text = self.error
       +            text = "Not connected"
       +
                self.status_bar.pop(self.context_id) 
       -        self.status_bar.push(self.context_id, text) 
       +        self.status_bar.push(self.context_id, text)
       +
       +        if self.wallet.interface.was_updated:
       +            self.update_history_tab()
       +            self.update_receiving_tab()
       +            # addressbook too...
       +            self.info.set_text( self.wallet.interface.message )
       +            self.wallet.interface.was_updated = False
       +        
        
            def update_receiving_tab(self):
                self.recv_list.clear()
   DIR diff --git a/client/interface.py b/client/interface.py
       t@@ -20,6 +20,7 @@
        import random, socket, ast
        
                
       +import thread, traceback, sys, time
        
        
        class Interface:
       t@@ -31,6 +32,7 @@ class Interface:
                self.message = ''
                self.set_port(50000)
                self.is_connected = False
       +        self.was_updated = True # fixme: use a semaphore
        
            def set_port(self, port_number):
                self.port = port_number
       t@@ -105,6 +107,7 @@ class Interface:
            def new_session(self, addresses, version):
                out = self.handler('session.new', [ version, addresses ] )
                self.session_id, self.message = ast.literal_eval( out )
       +        self.was_updated = True
        
            def update_session(self, addresses):
                out = self.handler('session.update', [ self.session_id, addresses ] )
       t@@ -113,3 +116,69 @@ class Interface:
            def get_servers(self):
                out = self.handler('peers')
                self.servers = map( lambda x:x[1], out )
       +
       +    def poll_interval(self):
       +        return 15 if self.use_http() else 5
       +
       +    def update_wallet(self, wallet):
       +        is_new = False
       +        changed_addresses = self.poll()
       +        for addr, blk_hash in changed_addresses.items():
       +            if wallet.status.get(addr) != blk_hash:
       +                print "updating history for", addr
       +                wallet.history[addr] = self.retrieve_history(addr)
       +                wallet.status[addr] = blk_hash
       +                is_new = True
       +
       +        if is_new:
       +            wallet.synchronize()
       +            wallet.update_tx_history()
       +            wallet.save()
       +            return True
       +        else:
       +            return False
       +
       +    def update_thread(self, wallet):
       +        while True:
       +            try:
       +                self.is_connected = False
       +                self.new_session(wallet.all_addresses(), wallet.electrum_version)
       +                self.update_session = False
       +            except:
       +                traceback.print_exc(file=sys.stdout)
       +                time.sleep(self.poll_interval())
       +                continue
       +
       +            get_servers_time = 0
       +            while True:
       +                try:
       +                    if self.is_connected and self.update_session:
       +                        self.update_session( wallet.all_addresses() )
       +                        self.update_session = False
       +
       +                    if time.time() - get_servers_time > 5*60:
       +                        self.get_servers()
       +                    get_servers_time = time.time()
       +
       +                    # define a method to update the list
       +                    if self.update_wallet(wallet):
       +                        self.update_session( wallet.all_addresses() )
       +                        self.was_updated = True  # for gui
       +
       +                    time.sleep(self.poll_interval())
       +                except BaseException:
       +                    traceback.print_exc(file=sys.stdout)
       +                    print "starting new session"
       +                    break
       +                except socket.gaierror:
       +                    self.is_connected = False
       +                    break
       +                except:
       +                    self.is_connected = False
       +                    print "error"
       +                    traceback.print_exc(file=sys.stdout)
       +                    break
       +                
       +
       +    def start(self, wallet):
       +        thread.start_new_thread(self.update_thread, (wallet,))
   DIR diff --git a/client/wallet.py b/client/wallet.py
       t@@ -573,23 +573,6 @@ class Wallet:
                    unconf += u
                return conf, unconf
        
       -    def update(self):
       -        is_new = False
       -        changed_addresses = self.interface.poll()
       -        for addr, blk_hash in changed_addresses.items():
       -            if self.status.get(addr) != blk_hash:
       -                print "updating history for", addr
       -                self.history[addr] = self.interface.retrieve_history(addr)
       -                self.status[addr] = blk_hash
       -                is_new = True
       -
       -        if is_new:
       -            self.synchronize()
       -            self.update_tx_history()
       -            self.save()
       -            return True
       -        else:
       -            return False
        
            def choose_tx_inputs( self, amount, fixed_fee ):
                """ todo: minimize tx size """