URI: 
       tmake a regular gui module for android - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit 2d13107897f8e7acb9c7f5a4c1f54780934784db
   DIR parent d929c4d2ddc4dd910c8249a456a850255e86aa28
  HTML Author: ThomasV <thomasv@gitorious>
       Date:   Sun, 18 Nov 2012 11:34:52 +0100
       
       make a regular gui module for android
       
       Diffstat:
         M electrum                            |     136 +++++++++++++++++--------------
         D electrum4a.py                       |     986 -------------------------------
         M lib/gui.py                          |      18 +-----------------
         A lib/gui_android.py                  |     970 +++++++++++++++++++++++++++++++
         M lib/gui_qt.py                       |      17 +----------------
         M lib/interface.py                    |      22 ++++++++++++++++++++++
         M lib/simple_config.py                |      48 ++++++++++++-------------------
         M lib/util.py                         |      10 +++++-----
         M lib/wallet.py                       |      18 +++++++++++-------
       
       9 files changed, 1102 insertions(+), 1123 deletions(-)
       ---
   DIR diff --git a/electrum b/electrum
       t@@ -17,7 +17,7 @@
        # along with this program. If not, see <http://www.gnu.org/licenses/>.
        
        import re
       -import sys
       +import sys, os
        import optparse
        
        try:
       t@@ -121,10 +121,7 @@ def prompt_password(prompt, confirm=True):
                password = None
            return password
        
       -
       -
       -if __name__ == '__main__':
       -
       +def parse_args():
            usage = "usage: %prog [options] command\nCommands: "+ (', '.join(known_commands))
            parser = optparse.OptionParser(prog=usage)
            parser.add_option("-g", "--gui", dest="gui", help="User interface: qt, lite, gtk or text")
       t@@ -139,12 +136,20 @@ if __name__ == '__main__':
            parser.add_option("-s", "--server", dest="server", default=None, help="set server host:port:protocol, where protocol is t or h")
            parser.add_option("-p", "--proxy", dest="proxy", default=None, help="set proxy [type:]host[:port], where type is socks4,socks5 or http")
            parser.add_option("-v", "--verbose", action="store_true", dest="verbose", default=False, help="show debugging information")
       -    options, args = parser.parse_args()
       +    return parser.parse_args()
       +
        
       +if __name__ == '__main__':
       +
       +    options, args = parse_args()
            set_verbosity(options.verbose)
        
            # config is an object passed to the various constructors (wallet, interface, gui)
       -    config = SimpleConfig(options)
       +    if 'ANDROID_DATA' in os.environ:
       +        config = SimpleConfig({'wallet_path':"/sdcard/electrum.dat", 'blockchain_headers_path':'/sdcard', 'gui':'android'})
       +    else:
       +        config = SimpleConfig(eval(str(options)))
       +
            wallet = Wallet(config)
        
            if len(args)==0:
       t@@ -181,6 +186,11 @@ if __name__ == '__main__':
                          import lib.gui_text as gui
                      except ImportError:
                          import electrum.gui_text as gui
       +        elif pref_gui == 'android':
       +              try:
       +                  import lib.gui_android as gui
       +              except ImportError:
       +                  import electrum.gui_android as gui
                else:
                    sys.exit("Error: Unknown GUI: " + pref_gui )
        
       t@@ -201,9 +211,9 @@ if __name__ == '__main__':
                    found = config.wallet_file_exists
                    if not found:
                        found = gui.restore_or_create()
       -        except SystemExit, e:
       +        except SystemExit(e):
                    exit(e)
       -        except BaseException, e:
       +        except BaseException(e):
                    import traceback
                    traceback.print_exc(file=sys.stdout)
                    #gui.show_message(e.message)
       t@@ -222,8 +232,8 @@ if __name__ == '__main__':
                cmd = 'help'
        
            if not config.wallet_file_exists and cmd not in ['help','create','restore']:
       -        print "Error: Wallet file not found."
       -        print "Type 'electrum create' to create a new wallet, or provide a path to a wallet with the -w option"
       +        print("Error: Wallet file not found.")
       +        print("Type 'electrum create' to create a new wallet, or provide a path to a wallet with the -w option")
                sys.exit(0)
            
            if cmd in ['create', 'restore']:
       t@@ -267,30 +277,30 @@ if __name__ == '__main__':
                        verifier = WalletVerifier(interface, config)
                        wallet.set_verifier(verifier)
        
       -                print "Recovering wallet..."
       +                print("Recovering wallet...")
                        WalletSynchronizer(wallet, config).start()
                        wallet.up_to_date_event.clear()
                        wallet.up_to_date = False
                        wallet.update()
                        if wallet.is_found():
       -                    print "Recovery successful"
       +                    print("Recovery successful")
                        else:
       -                    print "Warning: Found no history for this wallet"
       +                    print("Warning: Found no history for this wallet")
                    else:
                        wallet.synchronize()
                    wallet.fill_addressbook()
                    wallet.save()
       -            print "Wallet saved in '%s'"%wallet.config.path
       +            print("Wallet saved in '%s'"%wallet.config.path)
                else:
                    wallet.new_seed(None)
                    wallet.init_mpk( wallet.seed )
                    wallet.synchronize() # there is no wallet thread 
                    wallet.save()
       -            print "Your wallet generation seed is: " + wallet.seed
       -            print "Please keep it in a safe place; if you lose it, you will not be able to restore your wallet."
       -            print "Equivalently, your wallet seed can be stored and recovered with the following mnemonic code:"
       -            print "\""+' '.join(mnemonic_encode(wallet.seed))+"\""
       -            print "Wallet saved in '%s'"%wallet.config.path
       +            print("Your wallet generation seed is: " + wallet.seed)
       +            print("Please keep it in a safe place; if you lose it, you will not be able to restore your wallet.")
       +            print("Equivalently, your wallet seed can be stored and recovered with the following mnemonic code:")
       +            print("\""+' '.join(mnemonic_encode(wallet.seed))+"\"")
       +            print("Wallet saved in '%s'"%wallet.config.path)
                    
                if password:
                    wallet.update_password(wallet.seed, None, password)
       t@@ -328,9 +338,9 @@ if __name__ == '__main__':
                        
            # important warning
            if cmd=='addresses' and options.show_keys:
       -        print "WARNING: ALL your private keys are secret."
       -        print "Exposing a single private key can compromise your entire wallet!"
       -        print "In particular, DO NOT use 'redeem private key' services proposed by third parties."
       +        print("WARNING: ALL your private keys are secret.")
       +        print("Exposing a single private key can compromise your entire wallet!")
       +        print("In particular, DO NOT use 'redeem private key' services proposed by third parties.")
        
            # commands needing password
            if cmd in protected_commands or ( cmd=='addresses' and options.show_keys):
       t@@ -351,23 +361,23 @@ if __name__ == '__main__':
                try:
                    wallet.import_key(keypair,password)
                    wallet.save()
       -            print "Keypair imported"
       -        except BaseException, e:
       +            print("Keypair imported")
       +        except BaseException(e):
                    print_error("Error: Keypair import failed: " + str(e))
        
            if cmd == 'help':
                cmd2 = firstarg
                if cmd2 not in known_commands:
                    parser.print_help()
       -            print "Type 'electrum help <command>' to see the help for a specific command"
       -            print "Type 'electrum --help' to see the list of options"
       -            print "List of commands:", ', '.join(known_commands)
       +            print("Type 'electrum help <command>' to see the help for a specific command")
       +            print("Type 'electrum --help' to see the list of options")
       +            print("List of commands:", ', '.join(known_commands))
                else:
       -            print known_commands[cmd2]
       +            print(known_commands[cmd2])
        
            elif cmd == 'seed':
                seed = wallet.pw_decode( wallet.seed, password)
       -        print seed + ' "' + ' '.join(mnemonic_encode(seed)) + '"'
       +        print(seed + ' "' + ' '.join(mnemonic_encode(seed)) + '"')
        
            elif cmd == 'deseed':
                if not wallet.seed:
       t@@ -376,7 +386,7 @@ if __name__ == '__main__':
                    print_error("Error: This wallet is encrypted")
                else:
                    ns = wallet.path + '.seed'
       -            print "Warning: you are going to extract the seed from '%s'\nThe seed will be saved in '%s'"%(wallet.path,ns)
       +            print("Warning: you are going to extract the seed from '%s'\nThe seed will be saved in '%s'"%(wallet.path,ns))
                    if raw_input("Are you sure you want to continue? (y/n) ") in ['y','Y','yes']:
                        f = open(ns,'w')
                        f.write(repr({'seed':wallet.seed, 'imported_keys':wallet.imported_keys})+"\n")
       t@@ -384,13 +394,13 @@ if __name__ == '__main__':
                        wallet.seed = ''
                        for k in wallet.imported_keys.keys(): wallet.imported_keys[k] = ''
                        wallet.save()
       -                print "Done."
       +                print("Done.")
                    else:
                        print_error("Action canceled.")
        
            elif cmd == 'reseed':
                if wallet.seed:
       -            print "Warning: This wallet already has a seed", wallet.seed
       +            print("Warning: This wallet already has a seed", wallet.seed)
                else:
                    ns = wallet.path + '.seed'
                    try:
       t@@ -414,13 +424,13 @@ if __name__ == '__main__':
                    wallet.init_mpk(seed)
                    if mpk == wallet.master_public_key:
                        wallet.save()
       -                print "Done: " + wallet.path
       +                print("Done: " + wallet.path)
                    else:
                        print_error("Error: Master public key does not match")
        
            elif cmd == 'validateaddress':
                addr = args[1]
       -        print wallet.is_valid(addr)
       +        print(wallet.is_valid(addr))
        
            elif cmd == 'balance':
                try:
       t@@ -430,36 +440,36 @@ if __name__ == '__main__':
                if addrs == []:
                    c, u = wallet.get_balance()
                    if u:
       -                print Decimal( c ) / 100000000 , Decimal( u ) / 100000000
       +                print(Decimal( c ) / 100000000 , Decimal( u ) / 100000000)
                    else:
       -                print Decimal( c ) / 100000000
       +                print(Decimal( c ) / 100000000)
                else:
                    for addr in addrs:
                        c, u = wallet.get_addr_balance(addr)
                        if u:
       -                    print "%s %s, %s" % (addr, str(Decimal(c)/100000000), str(Decimal(u)/100000000))
       +                    print("%s %s, %s" % (addr, str(Decimal(c)/100000000), str(Decimal(u)/100000000)))
                        else:
       -                    print "%s %s" % (addr, str(Decimal(c)/100000000))
       +                    print("%s %s" % (addr, str(Decimal(c)/100000000)))
        
            elif cmd in [ 'contacts']:
                for addr in wallet.addressbook:
       -            print addr, "   ", wallet.labels.get(addr)
       +            print(addr, "   ", wallet.labels.get(addr))
        
            elif cmd == 'eval':
       -        print eval(args[1])
       +        print(eval(args[1]))
                wallet.save()
        
            elif cmd == 'get':
                key = args[1]
       -        print wallet.config.get(key)
       +        print(wallet.config.get(key))
        
            elif cmd == 'set':
                key, value = args[1:3]
                if key not in ['seed', 'seed_version', 'master_public_key', 'use_encryption']:
                    wallet.config.set_key(key, value, True)
       -            print True
       +            print(True)
                else:
       -            print False
       +            print(False)
        
            elif cmd in [ 'addresses']:
                for addr in wallet.all_addresses():
       t@@ -481,7 +491,7 @@ if __name__ == '__main__':
                        m_addr = "%34s"%addr
                        if options.show_keys:
                            m_addr += ':' + str(wallet.get_private_key_base58(addr, password))
       -                print flags, m_addr, b, label
       +                print(flags, m_addr, b, label)
        
            if cmd == 'history':
                import datetime
       t@@ -496,8 +506,8 @@ if __name__ == '__main__':
                    if not label: label = tx_hash
                    else: label = label + ' '*(64 - len(label) )
        
       -            print "%17s"%time_str, "  " + label + "  " + format_satoshis(value)+ "  "+ format_satoshis(balance)
       -        print "# balance: ", format_satoshis(balance)
       +            print("%17s"%time_str, "  " + label + "  " + format_satoshis(value)+ "  "+ format_satoshis(balance))
       +        print("# balance: ", format_satoshis(balance))
        
            elif cmd == 'label':
                try:
       t@@ -529,7 +539,7 @@ if __name__ == '__main__':
                for k, v in wallet.labels.items():
                    if v == to_address:
                        to_address = k
       -                print "alias", to_address
       +                print("alias", to_address)
                        break
                    if change_addr and v == change_addr:
                        change_addr = k
       t@@ -543,9 +553,9 @@ if __name__ == '__main__':
        
                if tx and cmd=='payto': 
                    r, h = wallet.sendtx( tx )
       -            print h
       +            print(h)
                else:
       -            print tx
       +            print(tx)
        
                if is_temporary:
                    wallet.imported_keys.pop(from_addr)
       t@@ -555,7 +565,7 @@ if __name__ == '__main__':
            elif cmd == 'sendtx':
                tx = args[1]
                r, h = wallet.sendtx( tx )
       -        print h
       +        print(h)
        
            elif cmd == 'password':
                try:
       t@@ -569,13 +579,13 @@ if __name__ == '__main__':
            elif cmd == 'signmessage':
                if len(args) < 3:
                    print_error("Error: Invalid usage of signmessage.")
       -            print known_commands[cmd]
       +            print(known_commands[cmd])
                    sys.exit(1)
                address = args[1]
                message = ' '.join(args[2:])
                if len(args) > 3:
       -            print "Warning: Message was reconstructed from several arguments:", repr(message)
       -        print wallet.sign_message(address, message, password)
       +            print("Warning: Message was reconstructed from several arguments:", repr(message))
       +        print(wallet.sign_message(address, message, password))
        
            elif cmd == 'verifymessage':
                try:
       t@@ -584,30 +594,30 @@ if __name__ == '__main__':
                    message = ' '.join(args[3:])
                except:
                    print_error("Error: Not all parameters were given, displaying help instead.")
       -            print known_commands[cmd]
       +            print(known_commands[cmd])
                    sys.exit(1)
                if len(args) > 4:
       -            print "Warning: Message was reconstructed from several arguments:", repr(message)
       +            print("Warning: Message was reconstructed from several arguments:", repr(message))
                try:
                    wallet.verify_message(address, signature, message)
       -            print True
       +            print(True)
                except BaseException as e:
       -            print "Verification error: {0}".format(e)
       -            print False
       +            print_error("Verification error: {0}".format(e))
       +            print(False)
        
            elif cmd == 'freeze':
                addr = args[1]
       -        print wallet.freeze(addr)
       +        print(wallet.freeze(addr))
                
            elif cmd == 'unfreeze':
                addr = args[1]
       -        print wallet.unfreeze(addr)
       +        print(wallet.unfreeze(addr))
        
            elif cmd == 'prioritize':
                addr = args[1]
       -        print wallet.prioritize(addr)
       +        print(wallet.prioritize(addr))
        
            elif cmd == 'unprioritize':
                addr = args[1]
       -        print wallet.unprioritize(addr)
       +        print(wallet.unprioritize(addr))
        
   DIR diff --git a/electrum4a.py b/electrum4a.py
       t@@ -1,986 +0,0 @@
       -#!/usr/bin/env python
       -#
       -# Electrum - lightweight Bitcoin client
       -# Copyright (C) 2011 thomasv@gitorious
       -#
       -# This program is free software: you can redistribute it and/or modify
       -# it under the terms of the GNU General Public License as published by
       -# the Free Software Foundation, either version 3 of the License, or
       -# (at your option) any later version.
       -#
       -# This program is distributed in the hope that it will be useful,
       -# but WITHOUT ANY WARRANTY; without even the implied warranty of
       -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
       -# GNU General Public License for more details.
       -#
       -# You should have received a copy of the GNU General Public License
       -# along with this program. If not, see <http://www.gnu.org/licenses/>.
       -
       -
       -
       -
       -import android
       -
       -from interface import WalletSynchronizer
       -from wallet import Wallet, format_satoshis
       -import mnemonic
       -from decimal import Decimal
       -import datetime, re
       -
       -
       -
       -def modal_dialog(title, msg = None):
       -    droid.dialogCreateAlert(title,msg)
       -    droid.dialogSetPositiveButtonText('OK')
       -    droid.dialogShow()
       -    droid.dialogGetResponse()
       -    droid.dialogDismiss()
       -
       -def modal_input(title, msg, value = None, etype=None):
       -    droid.dialogCreateInput(title, msg, value, etype)
       -    droid.dialogSetPositiveButtonText('OK')
       -    droid.dialogSetNegativeButtonText('Cancel')
       -    droid.dialogShow()
       -    response = droid.dialogGetResponse().result
       -    droid.dialogDismiss()
       -    if response.get('which') == 'positive':
       -        return response.get('value')
       -
       -def modal_question(q, msg, pos_text = 'OK', neg_text = 'Cancel'):
       -    droid.dialogCreateAlert(q, msg)
       -    droid.dialogSetPositiveButtonText(pos_text)
       -    droid.dialogSetNegativeButtonText(neg_text)
       -    droid.dialogShow()
       -    response = droid.dialogGetResponse().result
       -    droid.dialogDismiss()
       -    return response.get('which') == 'positive'
       -
       -def edit_label(addr):
       -    v = modal_input('Edit label',None,wallet.labels.get(addr))
       -    if v is not None:
       -        if v:
       -            wallet.labels[addr] = v
       -        else:
       -            if addr in wallet.labels.keys():
       -                wallet.labels.pop(addr)
       -        wallet.update_tx_history()
       -        wallet.save()
       -        droid.fullSetProperty("labelTextView", "text", v)
       -
       -def select_from_contacts():
       -    title = 'Contacts:'
       -    droid.dialogCreateAlert(title)
       -    l = []
       -    for i in range(len(wallet.addressbook)):
       -        addr = wallet.addressbook[i]
       -        label = wallet.labels.get(addr,addr)
       -        l.append( label )
       -    droid.dialogSetItems(l)
       -    droid.dialogSetPositiveButtonText('New contact')
       -    droid.dialogShow()
       -    response = droid.dialogGetResponse().result
       -    droid.dialogDismiss()
       -
       -    if response.get('which') == 'positive':
       -        return 'newcontact'
       -
       -    result = response.get('item')
       -    print result
       -    if result is not None:
       -        addr = wallet.addressbook[result]
       -        return addr
       -
       -
       -def select_from_addresses():
       -    droid.dialogCreateAlert("Addresses:")
       -    l = []
       -    for i in range(len(wallet.addresses)):
       -        addr = wallet.addresses[i]
       -        label = wallet.labels.get(addr,addr)
       -        l.append( label )
       -    droid.dialogSetItems(l)
       -    droid.dialogShow()
       -    response = droid.dialogGetResponse()
       -    result = response.result.get('item')
       -    droid.dialogDismiss()
       -    if result is not None:
       -        addr = wallet.addresses[result]
       -        return addr
       -
       -
       -def protocol_name(p):
       -    if p == 't': return 'TCP/stratum'
       -    if p == 'h': return 'HTTP/Stratum'
       -    if p == 'n': return 'TCP/native'
       -
       -def protocol_dialog(host, protocol, z):
       -    droid.dialogCreateAlert('Protocol',host)
       -    if z:
       -        protocols = z.keys()
       -    else:
       -        protocols = ['t','h','n']
       -    l = []
       -    current = protocols.index(protocol)
       -    for p in protocols:
       -        l.append(protocol_name(p))
       -    droid.dialogSetSingleChoiceItems(l, current)
       -    droid.dialogSetPositiveButtonText('OK')
       -    droid.dialogSetNegativeButtonText('Cancel')
       -    droid.dialogShow()
       -    response = droid.dialogGetResponse().result
       -    if not response: return
       -    if response.get('which') == 'positive':
       -        response = droid.dialogGetSelectedItems().result[0]
       -        droid.dialogDismiss()
       -        p = protocols[response]
       -        port = z[p]
       -        return host + ':' + port + ':' + p
       -
       -
       -
       -
       -def make_layout(s, scrollable = False):
       -    content = """
       -
       -      <LinearLayout 
       -        android:id="@+id/zz"
       -        android:layout_width="match_parent"
       -        android:layout_height="wrap_content" 
       -        android:background="#ff222222">
       -
       -        <TextView
       -          android:id="@+id/textElectrum"
       -          android:text="Electrum"
       -          android:textSize="7pt"
       -          android:textColor="#ff4444ff"
       -          android:gravity="left"
       -          android:layout_height="wrap_content"
       -          android:layout_width="match_parent"
       -        />
       -      </LinearLayout>
       -
       -        %s   """%s
       -
       -    if scrollable:
       -        content = """
       -      <ScrollView 
       -        android:id="@+id/scrollview"
       -        android:layout_width="match_parent"
       -        android:layout_height="match_parent" >
       -
       -      <LinearLayout
       -        android:orientation="vertical" 
       -        android:layout_width="match_parent"
       -        android:layout_height="wrap_content" >
       -
       -      %s
       -
       -      </LinearLayout>
       -      </ScrollView>
       -      """%content
       -
       -
       -    return """<?xml version="1.0" encoding="utf-8"?>
       -      <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
       -        android:id="@+id/background"
       -        android:orientation="vertical" 
       -        android:layout_width="match_parent"
       -        android:layout_height="match_parent" 
       -        android:background="#ff000022">
       -
       -      %s 
       -      </LinearLayout>"""%content
       -
       -
       -
       -
       -def main_layout():
       -    return make_layout("""
       -        <TextView android:id="@+id/balanceTextView" 
       -                android:layout_width="match_parent"
       -                android:text=""
       -                android:textColor="#ffffffff"
       -                android:textAppearance="?android:attr/textAppearanceLarge" 
       -                android:padding="7dip"
       -                android:textSize="8pt"
       -                android:gravity="center_vertical|center_horizontal|left">
       -        </TextView>
       -
       -        <TextView android:id="@+id/historyTextView" 
       -                android:layout_width="match_parent"
       -                android:layout_height="wrap_content" 
       -                android:text="Recent transactions"
       -                android:textAppearance="?android:attr/textAppearanceLarge" 
       -                android:gravity="center_vertical|center_horizontal|center">
       -        </TextView>
       -
       -        %s """%get_history_layout(15),True)
       -
       -
       -
       -def qr_layout(addr):
       -    return make_layout("""
       -
       -     <TextView android:id="@+id/addrTextView" 
       -                android:layout_width="match_parent"
       -                android:layout_height="50" 
       -                android:text="%s"
       -                android:textAppearance="?android:attr/textAppearanceLarge" 
       -                android:gravity="center_vertical|center_horizontal|center">
       -     </TextView>
       -
       -     <ImageView
       -        android:id="@+id/qrView"
       -        android:gravity="center"
       -        android:layout_width="match_parent"
       -        android:layout_height="350"
       -        android:antialias="false"
       -        android:src="file:///sdcard/sl4a/qrcode.bmp" /> 
       -
       -     <TextView android:id="@+id/labelTextView" 
       -                android:layout_width="match_parent"
       -                android:layout_height="50" 
       -                android:text="%s"
       -                android:textAppearance="?android:attr/textAppearanceLarge" 
       -                android:gravity="center_vertical|center_horizontal|center">
       -     </TextView>
       -
       -     """%(addr,wallet.labels.get(addr,'')), True)
       -
       -payto_layout = make_layout("""
       -
       -        <TextView android:id="@+id/recipientTextView" 
       -                android:layout_width="match_parent"
       -                android:layout_height="wrap_content" 
       -                android:text="Pay to:"
       -                android:textAppearance="?android:attr/textAppearanceLarge" 
       -                android:gravity="left">
       -        </TextView>
       -
       -
       -        <EditText android:id="@+id/recipient"
       -                android:layout_width="match_parent"
       -                android:layout_height="wrap_content" 
       -                android:tag="Tag Me" android:inputType="text">
       -        </EditText>
       -
       -        <LinearLayout android:id="@+id/linearLayout1"
       -                android:layout_width="match_parent"
       -                android:layout_height="wrap_content">
       -                <Button android:id="@+id/buttonQR" android:layout_width="wrap_content"
       -                        android:layout_height="wrap_content" android:text="From QR code"></Button>
       -                <Button android:id="@+id/buttonContacts" android:layout_width="wrap_content"
       -                        android:layout_height="wrap_content" android:text="From Contacts"></Button>
       -        </LinearLayout>
       -
       -
       -        <TextView android:id="@+id/labelTextView" 
       -                android:layout_width="match_parent"
       -                android:layout_height="wrap_content" 
       -                android:text="Description:"
       -                android:textAppearance="?android:attr/textAppearanceLarge" 
       -                android:gravity="left">
       -        </TextView>
       -
       -        <EditText android:id="@+id/label"
       -                android:layout_width="match_parent"
       -                android:layout_height="wrap_content" 
       -                android:tag="Tag Me" android:inputType="text">
       -        </EditText>
       -
       -        <TextView android:id="@+id/amountLabelTextView" 
       -                android:layout_width="match_parent"
       -                android:layout_height="wrap_content" 
       -                android:text="Amount:"
       -                android:textAppearance="?android:attr/textAppearanceLarge" 
       -                android:gravity="left">
       -        </TextView>
       -
       -        <EditText android:id="@+id/amount"
       -                android:layout_width="match_parent"
       -                android:layout_height="wrap_content" 
       -                android:tag="Tag Me" android:inputType="numberDecimal">
       -        </EditText>
       -
       -        <LinearLayout android:layout_width="match_parent"
       -                android:layout_height="wrap_content" android:id="@+id/linearLayout1">
       -                <Button android:id="@+id/buttonPay" android:layout_width="wrap_content"
       -                        android:layout_height="wrap_content" android:text="Send"></Button>
       -        </LinearLayout>""",False)
       -
       -
       -
       -settings_layout = make_layout(""" <ListView
       -           android:id="@+id/myListView" 
       -           android:layout_width="match_parent"
       -           android:layout_height="wrap_content" />""")
       -
       -
       -
       -def get_history_values(n):
       -    values = []
       -    h = wallet.get_tx_history()
       -
       -    length = min(n, len(h))
       -    for i in range(length):
       -        line = h[-i-1]
       -        v = line['value']
       -        try:
       -            dt = datetime.datetime.fromtimestamp( line['timestamp'] )
       -            if dt.date() == dt.today().date():
       -                time_str = str( dt.time() )
       -            else:
       -                time_str = str( dt.date() )
       -            conf = 'v'
       -
       -        except:
       -            print line['timestamp']
       -            time_str = 'pending'
       -            conf = 'o'
       -
       -        tx_hash = line['tx_hash']
       -        label = wallet.labels.get(tx_hash)
       -        is_default_label = (label == '') or (label is None)
       -        if is_default_label: label = line['default_label']
       -        values.append((conf, '  ' + time_str, '  ' + format_satoshis(v,True), '  ' + label ))
       -
       -    return values
       -
       -
       -def get_history_layout(n):
       -    rows = ""
       -    i = 0
       -    values = get_history_values(n)
       -    for v in values:
       -        a,b,c,d = v
       -        color = "#ff00ff00" if a == 'v' else "#ffff0000"
       -        rows += """
       -        <TableRow>
       -          <TextView
       -            android:id="@+id/hl_%d_col1" 
       -            android:layout_column="0"
       -            android:text="%s"
       -            android:textColor="%s"
       -            android:padding="3" />
       -          <TextView
       -            android:id="@+id/hl_%d_col2" 
       -            android:layout_column="1"
       -            android:text="%s"
       -            android:padding="3" />
       -          <TextView
       -            android:id="@+id/hl_%d_col3" 
       -            android:layout_column="2"
       -            android:text="%s"
       -            android:padding="3" />
       -          <TextView
       -            android:id="@+id/hl_%d_col4" 
       -            android:layout_column="3"
       -            android:text="%s"
       -            android:padding="4" />
       -        </TableRow>"""%(i,a,color,i,b,i,c,i,d)
       -        i += 1
       -
       -    output = """
       -<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
       -    android:layout_width="fill_parent"
       -    android:layout_height="wrap_content"
       -    android:stretchColumns="0,1,2,3">
       -    %s
       -</TableLayout>"""% rows
       -    return output
       -
       -
       -def set_history_layout(n):
       -    values = get_history_values(n)
       -    i = 0
       -    for v in values:
       -        a,b,c,d = v
       -        droid.fullSetProperty("hl_%d_col1"%i,"text", a)
       -
       -        if a == 'v':
       -            droid.fullSetProperty("hl_%d_col1"%i, "textColor","#ff00ff00")
       -        else:
       -            droid.fullSetProperty("hl_%d_col1"%i, "textColor","#ffff0000")
       -
       -        droid.fullSetProperty("hl_%d_col2"%i,"text", b)
       -        droid.fullSetProperty("hl_%d_col3"%i,"text", c)
       -        droid.fullSetProperty("hl_%d_col4"%i,"text", d)
       -        i += 1
       -
       -
       -
       -
       -status_text = ''
       -def update_layout():
       -    global status_text
       -    if not wallet.interface.is_connected:
       -        text = "Not connected..."
       -    elif wallet.blocks == 0:
       -        text = "Server not ready"
       -    elif not wallet.up_to_date:
       -        text = "Synchronizing..."
       -    else:
       -        c, u = wallet.get_balance()
       -        text = "Balance:"+format_satoshis(c) 
       -        if u : text += '   [' + format_satoshis(u,True).strip() + ']'
       -
       -
       -    # vibrate if status changed
       -    if text != status_text:
       -        if status_text and wallet.interface.is_connected and wallet.up_to_date:
       -            droid.vibrate()
       -        status_text = text
       -
       -    droid.fullSetProperty("balanceTextView", "text", status_text)
       -
       -    if wallet.up_to_date:
       -        set_history_layout(15)
       -
       -
       -
       -
       -def pay_to(recipient, amount, fee, label):
       -
       -    if wallet.use_encryption:
       -        password  = droid.dialogGetPassword('Password').result
       -        if not password: return
       -    else:
       -        password = None
       -
       -    droid.dialogCreateSpinnerProgress("Electrum", "signing transaction...")
       -    droid.dialogShow()
       -
       -    try:
       -        tx = wallet.mktx( recipient, amount, label, password, fee)
       -    except BaseException, e:
       -        modal_dialog('error', e.message)
       -        droid.dialogDismiss()
       -        return
       -
       -    droid.dialogDismiss()
       -
       -    r, h = wallet.sendtx( tx )
       -    if r:
       -        modal_dialog('Payment sent', h)
       -        return True
       -    else:
       -        modal_dialog('Error', h)
       -
       -
       -
       -
       -
       -def recover():
       -
       -    droid.dialogCreateAlert("Wallet not found","Do you want to create a new wallet, or restore an existing one?")
       -    droid.dialogSetPositiveButtonText('Create')
       -    droid.dialogSetNeutralButtonText('Restore')
       -    droid.dialogSetNegativeButtonText('Cancel')
       -    droid.dialogShow()
       -    response = droid.dialogGetResponse().result
       -    droid.dialogDismiss()
       -    if response.get('which') == 'negative':
       -        exit(1)
       -
       -    is_recovery = response.get('which') == 'neutral'
       -
       -    if not is_recovery:
       -        wallet.new_seed(None)
       -    else:
       -        if modal_question("Input method",None,'QR Code', 'mnemonic'):
       -            code = droid.scanBarcode()
       -            r = code.result
       -            if r:
       -                seed = r['extras']['SCAN_RESULT']
       -            else:
       -                exit(1)
       -        else:
       -            m = modal_input('Mnemonic','please enter your code')
       -            try:
       -                seed = mnemonic.mn_decode(m.split(' '))
       -            except:
       -                modal_dialog('error: could not decode this seed')
       -                exit(1)
       -
       -        wallet.seed = str(seed)
       -
       -    modal_dialog('Your seed is:', wallet.seed)
       -    modal_dialog('Mnemonic code:', ' '.join(mnemonic.mn_encode(wallet.seed)) )
       -
       -    msg = "recovering wallet..." if is_recovery else "creating wallet..."
       -    droid.dialogCreateSpinnerProgress("Electrum", msg)
       -    droid.dialogShow()
       -
       -    wallet.init_mpk( wallet.seed )
       -    WalletSynchronizer(wallet,True).start()
       -    wallet.update()
       -
       -    droid.dialogDismiss()
       -    droid.vibrate()
       -
       -    if is_recovery:
       -        if wallet.is_found():
       -            wallet.update_tx_history()
       -            wallet.fill_addressbook()
       -            modal_dialog("recovery successful")
       -        else:
       -            if not modal_question("no transactions found for this seed","do you want to keep this wallet?"):
       -                exit(1)
       -
       -    change_password_dialog()
       -    wallet.save()
       -
       -
       -
       -def make_new_contact():
       -    code = droid.scanBarcode()
       -    r = code.result
       -    if r:
       -        data = r['extras']['SCAN_RESULT']
       -        if data:
       -            if re.match('^bitcoin:', data):
       -                address, _, _, _, _, _, _ = wallet.parse_url(data, None, None)
       -            elif wallet.is_valid(data):
       -                address = data
       -            else:
       -                address = None
       -            if address:
       -                if modal_question('Add to contacts?', address):
       -                    wallet.addressbook.append(address)
       -                    wallet.save()
       -        else:
       -            modal_dialog('Invalid address', data)
       -
       -
       -do_refresh = False
       -
       -def update_callback():
       -    global do_refresh
       -    print "gui callback", wallet.interface.is_connected, wallet.up_to_date
       -    do_refresh = True
       -    droid.eventPost("refresh",'z')
       -
       -def main_loop():
       -    global do_refresh
       -
       -    update_layout()
       -    out = None
       -    quitting = False
       -    while out is None:
       -
       -        event = droid.eventWait(1000).result
       -        if event is None:
       -            if do_refresh: 
       -                update_layout()
       -                do_refresh = False
       -            continue
       -
       -        print "got event in main loop", repr(event)
       -        if event == 'OK': continue
       -        if event is None: continue
       -        #if event["name"]=="refresh":
       -
       -
       -        # request 2 taps before we exit
       -        if event["name"]=="key":
       -            if event["data"]["key"] == '4':
       -                if quitting:
       -                    out = 'quit'
       -                else: 
       -                    quitting = True
       -        else: quitting = False
       -
       -        if event["name"]=="click":
       -            id=event["data"]["id"]
       -
       -        elif event["name"]=="settings":
       -            out = 'settings'
       -
       -        elif event["name"] in menu_commands:
       -            out = event["name"]
       -
       -            if out == 'contacts':
       -                global contact_addr
       -                contact_addr = select_from_contacts()
       -                if contact_addr == 'newcontact':
       -                    make_new_contact()
       -                    contact_addr = None
       -                if not contact_addr:
       -                    out = None
       -
       -            elif out == "receive":
       -                global receive_addr
       -                receive_addr = select_from_addresses()
       -                if receive_addr:
       -                    amount = modal_input('Amount', 'Amount you want receive. ', '', "numberDecimal")
       -                    if amount:
       -                        receive_addr = 'bitcoin:%s?amount=%s'%(receive_addr, amount)
       -
       -                if not receive_addr:
       -                    out = None
       -
       -
       -    return out
       -                    
       -
       -def payto_loop():
       -    global recipient
       -    if recipient:
       -        droid.fullSetProperty("recipient","text",recipient)
       -        recipient = None
       -
       -    out = None
       -    while out is None:
       -        event = droid.eventWait().result
       -        print "got event in payto loop", event
       -
       -        if event["name"] == "click":
       -            id = event["data"]["id"]
       -
       -            if id=="buttonPay":
       -
       -                droid.fullQuery()
       -                recipient = droid.fullQueryDetail("recipient").result.get('text')
       -                label  = droid.fullQueryDetail("label").result.get('text')
       -                amount = droid.fullQueryDetail('amount').result.get('text')
       -
       -                if not wallet.is_valid(recipient):
       -                    modal_dialog('Error','Invalid Bitcoin address')
       -                    continue
       -
       -                try:
       -                    amount = int( 100000000 * Decimal(amount) )
       -                except:
       -                    modal_dialog('Error','Invalid amount')
       -                    continue
       -
       -                result = pay_to(recipient, amount, wallet.fee, label)
       -                if result:
       -                    out = 'main'
       -
       -            elif id=="buttonContacts":
       -                addr = select_from_contacts()
       -                droid.fullSetProperty("recipient","text",addr)
       -
       -            elif id=="buttonQR":
       -                code = droid.scanBarcode()
       -                r = code.result
       -                if r:
       -                    data = r['extras']['SCAN_RESULT']
       -                    if data:
       -                        if re.match('^bitcoin:', data):
       -                            payto, amount, label, _, _, _, _ = wallet.parse_url(data, None, None)
       -                            droid.fullSetProperty("recipient", "text",payto)
       -                            droid.fullSetProperty("amount", "text", amount)
       -                            droid.fullSetProperty("label", "text", label)
       -                        else:
       -                            droid.fullSetProperty("recipient", "text", data)
       -
       -                    
       -        elif event["name"] in menu_commands:
       -            out = event["name"]
       -
       -        elif event["name"]=="key":
       -            if event["data"]["key"] == '4':
       -                out = 'main'
       -
       -        #elif event["name"]=="screen":
       -        #    if event["data"]=="destroy":
       -        #        out = 'main'
       -
       -    return out
       -
       -
       -receive_addr = ''
       -contact_addr = ''
       -recipient = ''
       -
       -def receive_loop():
       -    out = None
       -    while out is None:
       -        event = droid.eventWait().result
       -        print "got event", event
       -        if event["name"]=="key":
       -            if event["data"]["key"] == '4':
       -                out = 'main'
       -
       -        elif event["name"]=="clipboard":
       -            droid.setClipboard(receive_addr)
       -            modal_dialog('Address copied to clipboard',receive_addr)
       -
       -        elif event["name"]=="edit":
       -            edit_label(receive_addr)
       -
       -    return out
       -
       -def contacts_loop():
       -    global recipient
       -    out = None
       -    while out is None:
       -        event = droid.eventWait().result
       -        print "got event", event
       -        if event["name"]=="key":
       -            if event["data"]["key"] == '4':
       -                out = 'main'
       -
       -        elif event["name"]=="clipboard":
       -            droid.setClipboard(contact_addr)
       -            modal_dialog('Address copied to clipboard',contact_addr)
       -
       -        elif event["name"]=="edit":
       -            edit_label(contact_addr)
       -
       -        elif event["name"]=="paytocontact":
       -            recipient = contact_addr
       -            out = 'send'
       -
       -        elif event["name"]=="deletecontact":
       -            if modal_question('delete contact', contact_addr):
       -                out = 'main'
       -
       -    return out
       -
       -
       -def server_dialog(plist):
       -    droid.dialogCreateAlert("Public servers")
       -    droid.dialogSetItems( plist.keys() )
       -    droid.dialogSetPositiveButtonText('Private server')
       -    droid.dialogShow()
       -    response = droid.dialogGetResponse().result
       -    droid.dialogDismiss()
       -
       -    if response.get('which') == 'positive':
       -        return modal_input('Private server', None)
       -
       -    i = response.get('item')
       -    if i is not None:
       -        response = plist.keys()[i]
       -        return response
       -
       -
       -def seed_dialog():
       -    if wallet.use_encryption:
       -        password  = droid.dialogGetPassword('Seed').result
       -        if not password: return
       -    else:
       -        password = None
       -    
       -    try:
       -        seed = wallet.pw_decode( wallet.seed, password)
       -    except:
       -        modal_dialog('error','incorrect password')
       -        return
       -
       -    modal_dialog('Your seed is',seed)
       -    modal_dialog('Mnemonic code:', ' '.join(mnemonic.mn_encode(seed)) )
       -
       -def change_password_dialog():
       -    if wallet.use_encryption:
       -        password  = droid.dialogGetPassword('Your wallet is encrypted').result
       -        if password is None: return
       -    else:
       -        password = None
       -
       -    try:
       -        seed = wallet.pw_decode( wallet.seed, password)
       -    except:
       -        modal_dialog('error','incorrect password')
       -        return
       -
       -    new_password  = droid.dialogGetPassword('Choose a password').result
       -    if new_password == None:
       -        return
       -
       -    if new_password != '':
       -        password2  = droid.dialogGetPassword('Confirm new password').result
       -        if new_password != password2:
       -            modal_dialog('error','passwords do not match')
       -            return
       -
       -    wallet.update_password(seed, password, new_password)
       -    if new_password:
       -        modal_dialog('Password updated','your wallet is encrypted')
       -    else:
       -        modal_dialog('No password','your wallet is not encrypted')
       -    return True
       -
       -
       -def settings_loop():
       -
       -
       -    def set_listview():
       -        server, port, p = wallet.server.split(':')
       -        fee = str( Decimal( wallet.fee)/100000000 )
       -        is_encrypted = 'yes' if wallet.use_encryption else 'no'
       -        protocol = protocol_name(p)
       -        droid.fullShow(settings_layout)
       -        droid.fullSetList("myListView",['Server: ' + server, 'Protocol: '+ protocol, 'Port: '+port, 'Transaction fee: '+fee, 'Password: '+is_encrypted, 'Seed'])
       -
       -    set_listview()
       -
       -    out = None
       -    while out is None:
       -        event = droid.eventWait().result
       -        print "got event", event
       -        if event == 'OK': continue
       -        if not event: continue
       -
       -        plist = {}
       -        for item in wallet.interface.servers:
       -            host, pp = item
       -            z = {}
       -            for item2 in pp:
       -                protocol, port = item2
       -                z[protocol] = port
       -            plist[host] = z
       -
       -        if event["name"] == "itemclick":
       -            pos = event["data"]["position"]
       -            host, port, protocol = wallet.server.split(':')
       -
       -            if pos == "0": #server
       -                host = server_dialog(plist)
       -                if host:
       -                    p = plist[host]
       -                    port = p['t']
       -                    srv = host + ':' + port + ':t'
       -                    try:
       -                        wallet.set_server(srv)
       -                    except:
       -                        modal_dialog('error','invalid server')
       -                    set_listview()
       -
       -            elif pos == "1": #protocol
       -                if host in plist:
       -                    srv = protocol_dialog(host, protocol, plist[host])
       -                    if srv:
       -                        try:
       -                            wallet.set_server(srv)
       -                        except:
       -                            modal_dialog('error','invalid server')
       -                        set_listview()
       -
       -            elif pos == "2": #port
       -                a_port = modal_input('Port number', 'If you use a public server, this field is set automatically when you set the protocol', port, "number")
       -                if a_port:
       -                    if a_port != port:
       -                        srv = host + ':' + a_port + ':'+ protocol
       -                        try:
       -                            wallet.set_server(srv)
       -                        except:
       -                            modal_dialog('error','invalid port number')
       -                        set_listview()
       -
       -            elif pos == "3": #fee
       -                fee = modal_input('Transaction fee', 'The fee will be this amount multiplied by the number of inputs in your transaction. ', str( Decimal( wallet.fee)/100000000 ), "numberDecimal")
       -                if fee:
       -                    try:
       -                        fee = int( 100000000 * Decimal(fee) )
       -                    except:
       -                        modal_dialog('error','invalid fee value')
       -                    if wallet.fee != fee:
       -                        wallet.fee = fee
       -                        wallet.save()
       -                        set_listview()
       -        
       -            elif pos == "4":
       -                if change_password_dialog():
       -                    set_listview()
       -
       -            elif pos == "5":
       -                seed_dialog()
       -
       -
       -        elif event["name"] in menu_commands:
       -            out = event["name"]
       -
       -        elif event["name"] == 'cancel':
       -            out = 'main'
       -
       -        elif event["name"] == "key":
       -            if event["data"]["key"] == '4':
       -                out = 'main'
       -
       -    return out
       -
       -
       -
       -
       -menu_commands = ["send", "receive", "settings", "contacts", "main"]
       -droid = android.Android()
       -wallet = Wallet()
       -wallet.register_callback(update_callback)
       -
       -wallet.set_path("/sdcard/electrum.dat")
       -wallet.read()
       -if not wallet.file_exists:
       -    recover()
       -else:
       -    WalletSynchronizer(wallet,True).start()
       -
       -
       -s = 'main'
       -
       -def add_menu(s):
       -    droid.clearOptionsMenu()
       -    if s == 'main':
       -        droid.addOptionsMenuItem("Send","send",None,"")
       -        droid.addOptionsMenuItem("Receive","receive",None,"")
       -        droid.addOptionsMenuItem("Contacts","contacts",None,"")
       -        droid.addOptionsMenuItem("Settings","settings",None,"")
       -    elif s == 'receive':
       -        droid.addOptionsMenuItem("Copy","clipboard",None,"")
       -        droid.addOptionsMenuItem("Label","edit",None,"")
       -    elif s == 'contacts':
       -        droid.addOptionsMenuItem("Copy","clipboard",None,"")
       -        droid.addOptionsMenuItem("Label","edit",None,"")
       -        droid.addOptionsMenuItem("Pay to","paytocontact",None,"")
       -        #droid.addOptionsMenuItem("Delete","deletecontact",None,"")
       -
       -def make_bitmap(addr):
       -    # fixme: this is highly inefficient
       -    droid.dialogCreateSpinnerProgress("please wait")
       -    droid.dialogShow()
       -    try:
       -        import pyqrnative, bmp
       -        qr = pyqrnative.QRCode(4, pyqrnative.QRErrorCorrectLevel.L)
       -        qr.addData(addr)
       -        qr.make()
       -        k = qr.getModuleCount()
       -        assert k == 33
       -        bmp.save_qrcode(qr,"/sdcard/sl4a/qrcode.bmp")
       -    finally:
       -        droid.dialogDismiss()
       -
       -        
       -
       -while True:
       -    add_menu(s)
       -    if s == 'main':
       -        droid.fullShow(main_layout())
       -        s = main_loop()
       -        #droid.fullDismiss()
       -
       -    elif s == 'send':
       -        droid.fullShow(payto_layout)
       -        s = payto_loop()
       -        #droid.fullDismiss()
       -
       -    elif s == 'receive':
       -        make_bitmap(receive_addr)
       -        droid.fullShow(qr_layout(receive_addr))
       -        s = receive_loop()
       -
       -    elif s == 'contacts':
       -        make_bitmap(contact_addr)
       -        droid.fullShow(qr_layout(contact_addr))
       -        s = contacts_loop()
       -
       -    elif s == 'settings':
       -        #droid.fullShow(settings_layout)
       -        s = settings_loop()
       -        #droid.fullDismiss()
       -    else:
       -        break
       -
       -droid.makeToast("Bye!")
   DIR diff --git a/lib/gui.py b/lib/gui.py
       t@@ -331,23 +331,7 @@ def run_network_dialog( wallet, parent ):
                status = "Please choose a server."
        
            server = interface.server
       -
       -    if not wallet.interface.servers:
       -        servers_list = []
       -        for x in DEFAULT_SERVERS:
       -            h,port,protocol = x.split(':')
       -            servers_list.append( (h,[(protocol,port)] ) )
       -    else:
       -        servers_list = wallet.interface.servers
       -
       -    plist = {}
       -    for item in servers_list:
       -        host, pp = item
       -        z = {}
       -        for item2 in pp:
       -            protocol, port = item2
       -            z[protocol] = port
       -        plist[host] = z
       +    plist, servers_list = interface.get_servers_list()
        
            dialog = gtk.MessageDialog( parent, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
                                            gtk.MESSAGE_QUESTION, gtk.BUTTONS_OK_CANCEL, status)
   DIR diff --git a/lib/gui_android.py b/lib/gui_android.py
       t@@ -0,0 +1,970 @@
       +#!/usr/bin/env python
       +#
       +# Electrum - lightweight Bitcoin client
       +# Copyright (C) 2011 thomasv@gitorious
       +#
       +# This program is free software: you can redistribute it and/or modify
       +# it under the terms of the GNU General Public License as published by
       +# the Free Software Foundation, either version 3 of the License, or
       +# (at your option) any later version.
       +#
       +# This program is distributed in the hope that it will be useful,
       +# but WITHOUT ANY WARRANTY; without even the implied warranty of
       +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
       +# GNU General Public License for more details.
       +#
       +# You should have received a copy of the GNU General Public License
       +# along with this program. If not, see <http://www.gnu.org/licenses/>.
       +
       +
       +
       +
       +import android
       +
       +from electrum import SimpleConfig, Interface, WalletSynchronizer, Wallet, format_satoshis, mnemonic_encode, mnemonic_decode
       +from decimal import Decimal
       +import datetime, re
       +
       +
       +
       +def modal_dialog(title, msg = None):
       +    droid.dialogCreateAlert(title,msg)
       +    droid.dialogSetPositiveButtonText('OK')
       +    droid.dialogShow()
       +    droid.dialogGetResponse()
       +    droid.dialogDismiss()
       +
       +def modal_input(title, msg, value = None, etype=None):
       +    droid.dialogCreateInput(title, msg, value, etype)
       +    droid.dialogSetPositiveButtonText('OK')
       +    droid.dialogSetNegativeButtonText('Cancel')
       +    droid.dialogShow()
       +    response = droid.dialogGetResponse().result
       +    droid.dialogDismiss()
       +    if response.get('which') == 'positive':
       +        return response.get('value')
       +
       +def modal_question(q, msg, pos_text = 'OK', neg_text = 'Cancel'):
       +    droid.dialogCreateAlert(q, msg)
       +    droid.dialogSetPositiveButtonText(pos_text)
       +    droid.dialogSetNegativeButtonText(neg_text)
       +    droid.dialogShow()
       +    response = droid.dialogGetResponse().result
       +    droid.dialogDismiss()
       +    return response.get('which') == 'positive'
       +
       +def edit_label(addr):
       +    v = modal_input('Edit label',None,wallet.labels.get(addr))
       +    if v is not None:
       +        if v:
       +            wallet.labels[addr] = v
       +        else:
       +            if addr in wallet.labels.keys():
       +                wallet.labels.pop(addr)
       +        wallet.update_tx_history()
       +        wallet.save()
       +        droid.fullSetProperty("labelTextView", "text", v)
       +
       +def select_from_contacts():
       +    title = 'Contacts:'
       +    droid.dialogCreateAlert(title)
       +    l = []
       +    for i in range(len(wallet.addressbook)):
       +        addr = wallet.addressbook[i]
       +        label = wallet.labels.get(addr,addr)
       +        l.append( label )
       +    droid.dialogSetItems(l)
       +    droid.dialogSetPositiveButtonText('New contact')
       +    droid.dialogShow()
       +    response = droid.dialogGetResponse().result
       +    droid.dialogDismiss()
       +
       +    if response.get('which') == 'positive':
       +        return 'newcontact'
       +
       +    result = response.get('item')
       +    print result
       +    if result is not None:
       +        addr = wallet.addressbook[result]
       +        return addr
       +
       +
       +def select_from_addresses():
       +    droid.dialogCreateAlert("Addresses:")
       +    l = []
       +    for i in range(len(wallet.addresses)):
       +        addr = wallet.addresses[i]
       +        label = wallet.labels.get(addr,addr)
       +        l.append( label )
       +    droid.dialogSetItems(l)
       +    droid.dialogShow()
       +    response = droid.dialogGetResponse()
       +    result = response.result.get('item')
       +    droid.dialogDismiss()
       +    if result is not None:
       +        addr = wallet.addresses[result]
       +        return addr
       +
       +
       +def protocol_name(p):
       +    if p == 't': return 'TCP/stratum'
       +    if p == 'h': return 'HTTP/Stratum'
       +    if p == 'n': return 'TCP/native'
       +
       +def protocol_dialog(host, protocol, z):
       +    droid.dialogCreateAlert('Protocol',host)
       +    if z:
       +        protocols = z.keys()
       +    else:
       +        protocols = ['t','h','n']
       +    l = []
       +    current = protocols.index(protocol)
       +    for p in protocols:
       +        l.append(protocol_name(p))
       +    droid.dialogSetSingleChoiceItems(l, current)
       +    droid.dialogSetPositiveButtonText('OK')
       +    droid.dialogSetNegativeButtonText('Cancel')
       +    droid.dialogShow()
       +    response = droid.dialogGetResponse().result
       +    if not response: return
       +    if response.get('which') == 'positive':
       +        response = droid.dialogGetSelectedItems().result[0]
       +        droid.dialogDismiss()
       +        p = protocols[response]
       +        port = z[p]
       +        return host + ':' + port + ':' + p
       +
       +
       +
       +
       +def make_layout(s, scrollable = False):
       +    content = """
       +
       +      <LinearLayout 
       +        android:id="@+id/zz"
       +        android:layout_width="match_parent"
       +        android:layout_height="wrap_content" 
       +        android:background="#ff222222">
       +
       +        <TextView
       +          android:id="@+id/textElectrum"
       +          android:text="Electrum"
       +          android:textSize="7pt"
       +          android:textColor="#ff4444ff"
       +          android:gravity="left"
       +          android:layout_height="wrap_content"
       +          android:layout_width="match_parent"
       +        />
       +      </LinearLayout>
       +
       +        %s   """%s
       +
       +    if scrollable:
       +        content = """
       +      <ScrollView 
       +        android:id="@+id/scrollview"
       +        android:layout_width="match_parent"
       +        android:layout_height="match_parent" >
       +
       +      <LinearLayout
       +        android:orientation="vertical" 
       +        android:layout_width="match_parent"
       +        android:layout_height="wrap_content" >
       +
       +      %s
       +
       +      </LinearLayout>
       +      </ScrollView>
       +      """%content
       +
       +
       +    return """<?xml version="1.0" encoding="utf-8"?>
       +      <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
       +        android:id="@+id/background"
       +        android:orientation="vertical" 
       +        android:layout_width="match_parent"
       +        android:layout_height="match_parent" 
       +        android:background="#ff000022">
       +
       +      %s 
       +      </LinearLayout>"""%content
       +
       +
       +
       +
       +def main_layout():
       +    return make_layout("""
       +        <TextView android:id="@+id/balanceTextView" 
       +                android:layout_width="match_parent"
       +                android:text=""
       +                android:textColor="#ffffffff"
       +                android:textAppearance="?android:attr/textAppearanceLarge" 
       +                android:padding="7dip"
       +                android:textSize="8pt"
       +                android:gravity="center_vertical|center_horizontal|left">
       +        </TextView>
       +
       +        <TextView android:id="@+id/historyTextView" 
       +                android:layout_width="match_parent"
       +                android:layout_height="wrap_content" 
       +                android:text="Recent transactions"
       +                android:textAppearance="?android:attr/textAppearanceLarge" 
       +                android:gravity="center_vertical|center_horizontal|center">
       +        </TextView>
       +
       +        %s """%get_history_layout(15),True)
       +
       +
       +
       +def qr_layout(addr):
       +    return make_layout("""
       +
       +     <TextView android:id="@+id/addrTextView" 
       +                android:layout_width="match_parent"
       +                android:layout_height="50" 
       +                android:text="%s"
       +                android:textAppearance="?android:attr/textAppearanceLarge" 
       +                android:gravity="center_vertical|center_horizontal|center">
       +     </TextView>
       +
       +     <ImageView
       +        android:id="@+id/qrView"
       +        android:gravity="center"
       +        android:layout_width="match_parent"
       +        android:layout_height="350"
       +        android:antialias="false"
       +        android:src="file:///sdcard/sl4a/qrcode.bmp" /> 
       +
       +     <TextView android:id="@+id/labelTextView" 
       +                android:layout_width="match_parent"
       +                android:layout_height="50" 
       +                android:text="%s"
       +                android:textAppearance="?android:attr/textAppearanceLarge" 
       +                android:gravity="center_vertical|center_horizontal|center">
       +     </TextView>
       +
       +     """%(addr,wallet.labels.get(addr,'')), True)
       +
       +payto_layout = make_layout("""
       +
       +        <TextView android:id="@+id/recipientTextView" 
       +                android:layout_width="match_parent"
       +                android:layout_height="wrap_content" 
       +                android:text="Pay to:"
       +                android:textAppearance="?android:attr/textAppearanceLarge" 
       +                android:gravity="left">
       +        </TextView>
       +
       +
       +        <EditText android:id="@+id/recipient"
       +                android:layout_width="match_parent"
       +                android:layout_height="wrap_content" 
       +                android:tag="Tag Me" android:inputType="text">
       +        </EditText>
       +
       +        <LinearLayout android:id="@+id/linearLayout1"
       +                android:layout_width="match_parent"
       +                android:layout_height="wrap_content">
       +                <Button android:id="@+id/buttonQR" android:layout_width="wrap_content"
       +                        android:layout_height="wrap_content" android:text="From QR code"></Button>
       +                <Button android:id="@+id/buttonContacts" android:layout_width="wrap_content"
       +                        android:layout_height="wrap_content" android:text="From Contacts"></Button>
       +        </LinearLayout>
       +
       +
       +        <TextView android:id="@+id/labelTextView" 
       +                android:layout_width="match_parent"
       +                android:layout_height="wrap_content" 
       +                android:text="Description:"
       +                android:textAppearance="?android:attr/textAppearanceLarge" 
       +                android:gravity="left">
       +        </TextView>
       +
       +        <EditText android:id="@+id/label"
       +                android:layout_width="match_parent"
       +                android:layout_height="wrap_content" 
       +                android:tag="Tag Me" android:inputType="text">
       +        </EditText>
       +
       +        <TextView android:id="@+id/amountLabelTextView" 
       +                android:layout_width="match_parent"
       +                android:layout_height="wrap_content" 
       +                android:text="Amount:"
       +                android:textAppearance="?android:attr/textAppearanceLarge" 
       +                android:gravity="left">
       +        </TextView>
       +
       +        <EditText android:id="@+id/amount"
       +                android:layout_width="match_parent"
       +                android:layout_height="wrap_content" 
       +                android:tag="Tag Me" android:inputType="numberDecimal">
       +        </EditText>
       +
       +        <LinearLayout android:layout_width="match_parent"
       +                android:layout_height="wrap_content" android:id="@+id/linearLayout1">
       +                <Button android:id="@+id/buttonPay" android:layout_width="wrap_content"
       +                        android:layout_height="wrap_content" android:text="Send"></Button>
       +        </LinearLayout>""",False)
       +
       +
       +
       +settings_layout = make_layout(""" <ListView
       +           android:id="@+id/myListView" 
       +           android:layout_width="match_parent"
       +           android:layout_height="wrap_content" />""")
       +
       +
       +
       +def get_history_values(n):
       +    values = []
       +    h = wallet.get_tx_history()
       +    length = min(n, len(h))
       +    for i in range(length):
       +        tx_hash, conf, is_mine, value, fee, balance, timestamp = h[-i-1]
       +        try:
       +            dt = datetime.datetime.fromtimestamp( timestamp )
       +            if dt.date() == dt.today().date():
       +                time_str = str( dt.time() )
       +            else:
       +                time_str = str( dt.date() )
       +        except:
       +            time_str = 'pending'
       +
       +        conf_str = 'v' if conf else 'o'
       +        label, is_default_label = wallet.get_label(tx_hash)
       +        values.append((conf_str, '  ' + time_str, '  ' + format_satoshis(value,True), '  ' + label ))
       +
       +    return values
       +
       +
       +def get_history_layout(n):
       +    rows = ""
       +    i = 0
       +    values = get_history_values(n)
       +    for v in values:
       +        a,b,c,d = v
       +        color = "#ff00ff00" if a == 'v' else "#ffff0000"
       +        rows += """
       +        <TableRow>
       +          <TextView
       +            android:id="@+id/hl_%d_col1" 
       +            android:layout_column="0"
       +            android:text="%s"
       +            android:textColor="%s"
       +            android:padding="3" />
       +          <TextView
       +            android:id="@+id/hl_%d_col2" 
       +            android:layout_column="1"
       +            android:text="%s"
       +            android:padding="3" />
       +          <TextView
       +            android:id="@+id/hl_%d_col3" 
       +            android:layout_column="2"
       +            android:text="%s"
       +            android:padding="3" />
       +          <TextView
       +            android:id="@+id/hl_%d_col4" 
       +            android:layout_column="3"
       +            android:text="%s"
       +            android:padding="4" />
       +        </TableRow>"""%(i,a,color,i,b,i,c,i,d)
       +        i += 1
       +
       +    output = """
       +<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
       +    android:layout_width="fill_parent"
       +    android:layout_height="wrap_content"
       +    android:stretchColumns="0,1,2,3">
       +    %s
       +</TableLayout>"""% rows
       +    return output
       +
       +
       +def set_history_layout(n):
       +    values = get_history_values(n)
       +    i = 0
       +    for v in values:
       +        a,b,c,d = v
       +        droid.fullSetProperty("hl_%d_col1"%i,"text", a)
       +
       +        if a == 'v':
       +            droid.fullSetProperty("hl_%d_col1"%i, "textColor","#ff00ff00")
       +        else:
       +            droid.fullSetProperty("hl_%d_col1"%i, "textColor","#ffff0000")
       +
       +        droid.fullSetProperty("hl_%d_col2"%i,"text", b)
       +        droid.fullSetProperty("hl_%d_col3"%i,"text", c)
       +        droid.fullSetProperty("hl_%d_col4"%i,"text", d)
       +        i += 1
       +
       +
       +
       +
       +status_text = ''
       +def update_layout():
       +    global status_text
       +    if not wallet.interface.is_connected:
       +        text = "Not connected..."
       +    elif not wallet.up_to_date:
       +        text = "Synchronizing..."
       +    else:
       +        c, u = wallet.get_balance()
       +        text = "Balance:"+format_satoshis(c) 
       +        if u : text += '   [' + format_satoshis(u,True).strip() + ']'
       +
       +
       +    # vibrate if status changed
       +    if text != status_text:
       +        if status_text and wallet.interface.is_connected and wallet.up_to_date:
       +            droid.vibrate()
       +        status_text = text
       +
       +    droid.fullSetProperty("balanceTextView", "text", status_text)
       +
       +    if wallet.up_to_date:
       +        set_history_layout(15)
       +
       +
       +
       +
       +def pay_to(recipient, amount, fee, label):
       +
       +    if wallet.use_encryption:
       +        password  = droid.dialogGetPassword('Password').result
       +        if not password: return
       +    else:
       +        password = None
       +
       +    droid.dialogCreateSpinnerProgress("Electrum", "signing transaction...")
       +    droid.dialogShow()
       +
       +    try:
       +        tx = wallet.mktx( recipient, amount, label, password, fee)
       +    except BaseException, e:
       +        modal_dialog('error', e.message)
       +        droid.dialogDismiss()
       +        return
       +
       +    droid.dialogDismiss()
       +
       +    r, h = wallet.sendtx( tx )
       +    if r:
       +        modal_dialog('Payment sent', h)
       +        return True
       +    else:
       +        modal_dialog('Error', h)
       +
       +
       +
       +
       +
       +def recover():
       +
       +    droid.dialogCreateAlert("Wallet not found","Do you want to create a new wallet, or restore an existing one?")
       +    droid.dialogSetPositiveButtonText('Create')
       +    droid.dialogSetNeutralButtonText('Restore')
       +    droid.dialogSetNegativeButtonText('Cancel')
       +    droid.dialogShow()
       +    response = droid.dialogGetResponse().result
       +    droid.dialogDismiss()
       +    if response.get('which') == 'negative':
       +        exit(1)
       +
       +    is_recovery = response.get('which') == 'neutral'
       +
       +    if not is_recovery:
       +        wallet.new_seed(None)
       +    else:
       +        if modal_question("Input method",None,'QR Code', 'mnemonic'):
       +            code = droid.scanBarcode()
       +            r = code.result
       +            if r:
       +                seed = r['extras']['SCAN_RESULT']
       +            else:
       +                exit(1)
       +        else:
       +            m = modal_input('Mnemonic','please enter your code')
       +            try:
       +                seed = mnemonic_decode(m.split(' '))
       +            except:
       +                modal_dialog('error: could not decode this seed')
       +                exit(1)
       +
       +        wallet.seed = str(seed)
       +
       +    modal_dialog('Your seed is:', wallet.seed)
       +    modal_dialog('Mnemonic code:', ' '.join(mnemonic_encode(wallet.seed)) )
       +
       +    msg = "recovering wallet..." if is_recovery else "creating wallet..."
       +    droid.dialogCreateSpinnerProgress("Electrum", msg)
       +    droid.dialogShow()
       +
       +    wallet.init_mpk( wallet.seed )
       +    WalletSynchronizer(wallet,True).start()
       +    wallet.update()
       +
       +    droid.dialogDismiss()
       +    droid.vibrate()
       +
       +    if is_recovery:
       +        if wallet.is_found():
       +            wallet.update_tx_history()
       +            wallet.fill_addressbook()
       +            modal_dialog("recovery successful")
       +        else:
       +            if not modal_question("no transactions found for this seed","do you want to keep this wallet?"):
       +                exit(1)
       +
       +    change_password_dialog()
       +    wallet.save()
       +
       +
       +
       +def make_new_contact():
       +    code = droid.scanBarcode()
       +    r = code.result
       +    if r:
       +        data = r['extras']['SCAN_RESULT']
       +        if data:
       +            if re.match('^bitcoin:', data):
       +                address, _, _, _, _, _, _ = wallet.parse_url(data, None, None)
       +            elif wallet.is_valid(data):
       +                address = data
       +            else:
       +                address = None
       +            if address:
       +                if modal_question('Add to contacts?', address):
       +                    wallet.addressbook.append(address)
       +                    wallet.save()
       +        else:
       +            modal_dialog('Invalid address', data)
       +
       +
       +do_refresh = False
       +
       +def update_callback():
       +    global do_refresh
       +    print "gui callback", wallet.interface.is_connected, wallet.up_to_date
       +    do_refresh = True
       +    droid.eventPost("refresh",'z')
       +
       +def main_loop():
       +    global do_refresh
       +
       +    update_layout()
       +    out = None
       +    quitting = False
       +    while out is None:
       +
       +        event = droid.eventWait(1000).result
       +        if event is None:
       +            if do_refresh: 
       +                update_layout()
       +                do_refresh = False
       +            continue
       +
       +        print "got event in main loop", repr(event)
       +        if event == 'OK': continue
       +        if event is None: continue
       +        #if event["name"]=="refresh":
       +
       +
       +        # request 2 taps before we exit
       +        if event["name"]=="key":
       +            if event["data"]["key"] == '4':
       +                if quitting:
       +                    out = 'quit'
       +                else: 
       +                    quitting = True
       +        else: quitting = False
       +
       +        if event["name"]=="click":
       +            id=event["data"]["id"]
       +
       +        elif event["name"]=="settings":
       +            out = 'settings'
       +
       +        elif event["name"] in menu_commands:
       +            out = event["name"]
       +
       +            if out == 'contacts':
       +                global contact_addr
       +                contact_addr = select_from_contacts()
       +                if contact_addr == 'newcontact':
       +                    make_new_contact()
       +                    contact_addr = None
       +                if not contact_addr:
       +                    out = None
       +
       +            elif out == "receive":
       +                global receive_addr
       +                receive_addr = select_from_addresses()
       +                if receive_addr:
       +                    amount = modal_input('Amount', 'Amount you want receive. ', '', "numberDecimal")
       +                    if amount:
       +                        receive_addr = 'bitcoin:%s?amount=%s'%(receive_addr, amount)
       +
       +                if not receive_addr:
       +                    out = None
       +
       +
       +    return out
       +                    
       +
       +def payto_loop():
       +    global recipient
       +    if recipient:
       +        droid.fullSetProperty("recipient","text",recipient)
       +        recipient = None
       +
       +    out = None
       +    while out is None:
       +        event = droid.eventWait().result
       +        print "got event in payto loop", event
       +
       +        if event["name"] == "click":
       +            id = event["data"]["id"]
       +
       +            if id=="buttonPay":
       +
       +                droid.fullQuery()
       +                recipient = droid.fullQueryDetail("recipient").result.get('text')
       +                label  = droid.fullQueryDetail("label").result.get('text')
       +                amount = droid.fullQueryDetail('amount').result.get('text')
       +
       +                if not wallet.is_valid(recipient):
       +                    modal_dialog('Error','Invalid Bitcoin address')
       +                    continue
       +
       +                try:
       +                    amount = int( 100000000 * Decimal(amount) )
       +                except:
       +                    modal_dialog('Error','Invalid amount')
       +                    continue
       +
       +                result = pay_to(recipient, amount, wallet.fee, label)
       +                if result:
       +                    out = 'main'
       +
       +            elif id=="buttonContacts":
       +                addr = select_from_contacts()
       +                droid.fullSetProperty("recipient","text",addr)
       +
       +            elif id=="buttonQR":
       +                code = droid.scanBarcode()
       +                r = code.result
       +                if r:
       +                    data = r['extras']['SCAN_RESULT']
       +                    if data:
       +                        if re.match('^bitcoin:', data):
       +                            payto, amount, label, _, _, _, _ = wallet.parse_url(data, None, None)
       +                            droid.fullSetProperty("recipient", "text",payto)
       +                            droid.fullSetProperty("amount", "text", amount)
       +                            droid.fullSetProperty("label", "text", label)
       +                        else:
       +                            droid.fullSetProperty("recipient", "text", data)
       +
       +                    
       +        elif event["name"] in menu_commands:
       +            out = event["name"]
       +
       +        elif event["name"]=="key":
       +            if event["data"]["key"] == '4':
       +                out = 'main'
       +
       +        #elif event["name"]=="screen":
       +        #    if event["data"]=="destroy":
       +        #        out = 'main'
       +
       +    return out
       +
       +
       +receive_addr = ''
       +contact_addr = ''
       +recipient = ''
       +
       +def receive_loop():
       +    out = None
       +    while out is None:
       +        event = droid.eventWait().result
       +        print "got event", event
       +        if event["name"]=="key":
       +            if event["data"]["key"] == '4':
       +                out = 'main'
       +
       +        elif event["name"]=="clipboard":
       +            droid.setClipboard(receive_addr)
       +            modal_dialog('Address copied to clipboard',receive_addr)
       +
       +        elif event["name"]=="edit":
       +            edit_label(receive_addr)
       +
       +    return out
       +
       +def contacts_loop():
       +    global recipient
       +    out = None
       +    while out is None:
       +        event = droid.eventWait().result
       +        print "got event", event
       +        if event["name"]=="key":
       +            if event["data"]["key"] == '4':
       +                out = 'main'
       +
       +        elif event["name"]=="clipboard":
       +            droid.setClipboard(contact_addr)
       +            modal_dialog('Address copied to clipboard',contact_addr)
       +
       +        elif event["name"]=="edit":
       +            edit_label(contact_addr)
       +
       +        elif event["name"]=="paytocontact":
       +            recipient = contact_addr
       +            out = 'send'
       +
       +        elif event["name"]=="deletecontact":
       +            if modal_question('delete contact', contact_addr):
       +                out = 'main'
       +
       +    return out
       +
       +
       +def server_dialog(plist):
       +    droid.dialogCreateAlert("Public servers")
       +    droid.dialogSetItems( plist.keys() )
       +    droid.dialogSetPositiveButtonText('Private server')
       +    droid.dialogShow()
       +    response = droid.dialogGetResponse().result
       +    droid.dialogDismiss()
       +    if not response: return
       +
       +    if response.get('which') == 'positive':
       +        return modal_input('Private server', None)
       +
       +    i = response.get('item')
       +    if i is not None:
       +        response = plist.keys()[i]
       +        return response
       +
       +
       +def seed_dialog():
       +    if wallet.use_encryption:
       +        password  = droid.dialogGetPassword('Seed').result
       +        if not password: return
       +    else:
       +        password = None
       +    
       +    try:
       +        seed = wallet.pw_decode( wallet.seed, password)
       +    except:
       +        modal_dialog('error','incorrect password')
       +        return
       +
       +    modal_dialog('Your seed is',seed)
       +    modal_dialog('Mnemonic code:', ' '.join(mnemonic_encode(seed)) )
       +
       +def change_password_dialog():
       +    if wallet.use_encryption:
       +        password  = droid.dialogGetPassword('Your wallet is encrypted').result
       +        if password is None: return
       +    else:
       +        password = None
       +
       +    try:
       +        seed = wallet.pw_decode( wallet.seed, password)
       +    except:
       +        modal_dialog('error','incorrect password')
       +        return
       +
       +    new_password  = droid.dialogGetPassword('Choose a password').result
       +    if new_password == None:
       +        return
       +
       +    if new_password != '':
       +        password2  = droid.dialogGetPassword('Confirm new password').result
       +        if new_password != password2:
       +            modal_dialog('error','passwords do not match')
       +            return
       +
       +    wallet.update_password(seed, password, new_password)
       +    if new_password:
       +        modal_dialog('Password updated','your wallet is encrypted')
       +    else:
       +        modal_dialog('No password','your wallet is not encrypted')
       +    return True
       +
       +
       +def settings_loop():
       +
       +
       +    def set_listview():
       +        server, port, p = interface.server.split(':')
       +        fee = str( Decimal( wallet.fee)/100000000 )
       +        is_encrypted = 'yes' if wallet.use_encryption else 'no'
       +        protocol = protocol_name(p)
       +        droid.fullShow(settings_layout)
       +        droid.fullSetList("myListView",['Server: ' + server, 'Protocol: '+ protocol, 'Port: '+port, 'Transaction fee: '+fee, 'Password: '+is_encrypted, 'Seed'])
       +
       +    set_listview()
       +
       +    out = None
       +    while out is None:
       +        event = droid.eventWait().result
       +        print "got event", event
       +        if event == 'OK': continue
       +        if not event: continue
       +
       +        plist, servers_list = interface.get_servers_list()
       +
       +        if event["name"] == "itemclick":
       +            pos = event["data"]["position"]
       +            host, port, protocol = interface.server.split(':')
       +
       +            if pos == "0": #server
       +                host = server_dialog(plist)
       +                if host:
       +                    p = plist[host]
       +                    port = p['t']
       +                    srv = host + ':' + port + ':t'
       +                    wallet.config.set_key("server", srv, True)
       +                    try:
       +                        wallet.interface.set_server(srv)
       +                    except:
       +                        modal_dialog('error','invalid server')
       +                    set_listview()
       +
       +            elif pos == "1": #protocol
       +                if host in plist:
       +                    srv = protocol_dialog(host, protocol, plist[host])
       +                    if srv:
       +                        try:
       +                            wallet.interface.set_server(srv)
       +                        except:
       +                            modal_dialog('error','invalid server')
       +                        set_listview()
       +
       +            elif pos == "2": #port
       +                a_port = modal_input('Port number', 'If you use a public server, this field is set automatically when you set the protocol', port, "number")
       +                if a_port:
       +                    if a_port != port:
       +                        srv = host + ':' + a_port + ':'+ protocol
       +                        try:
       +                            wallet.interface.set_server(srv)
       +                        except:
       +                            modal_dialog('error','invalid port number')
       +                        set_listview()
       +
       +            elif pos == "3": #fee
       +                fee = modal_input('Transaction fee', 'The fee will be this amount multiplied by the number of inputs in your transaction. ', str( Decimal( wallet.fee)/100000000 ), "numberDecimal")
       +                if fee:
       +                    try:
       +                        fee = int( 100000000 * Decimal(fee) )
       +                    except:
       +                        modal_dialog('error','invalid fee value')
       +                    if wallet.fee != fee:
       +                        wallet.fee = fee
       +                        wallet.save()
       +                        set_listview()
       +        
       +            elif pos == "4":
       +                if change_password_dialog():
       +                    set_listview()
       +
       +            elif pos == "5":
       +                seed_dialog()
       +
       +
       +        elif event["name"] in menu_commands:
       +            out = event["name"]
       +
       +        elif event["name"] == 'cancel':
       +            out = 'main'
       +
       +        elif event["name"] == "key":
       +            if event["data"]["key"] == '4':
       +                out = 'main'
       +
       +    return out
       +
       +def add_menu(s):
       +    droid.clearOptionsMenu()
       +    if s == 'main':
       +        droid.addOptionsMenuItem("Send","send",None,"")
       +        droid.addOptionsMenuItem("Receive","receive",None,"")
       +        droid.addOptionsMenuItem("Contacts","contacts",None,"")
       +        droid.addOptionsMenuItem("Settings","settings",None,"")
       +    elif s == 'receive':
       +        droid.addOptionsMenuItem("Copy","clipboard",None,"")
       +        droid.addOptionsMenuItem("Label","edit",None,"")
       +    elif s == 'contacts':
       +        droid.addOptionsMenuItem("Copy","clipboard",None,"")
       +        droid.addOptionsMenuItem("Label","edit",None,"")
       +        droid.addOptionsMenuItem("Pay to","paytocontact",None,"")
       +        #droid.addOptionsMenuItem("Delete","deletecontact",None,"")
       +
       +
       +def make_bitmap(addr):
       +    # fixme: this is highly inefficient
       +    droid.dialogCreateSpinnerProgress("please wait")
       +    droid.dialogShow()
       +    try:
       +        import pyqrnative, bmp
       +        qr = pyqrnative.QRCode(4, pyqrnative.QRErrorCorrectLevel.L)
       +        qr.addData(addr)
       +        qr.make()
       +        k = qr.getModuleCount()
       +        assert k == 33
       +        bmp.save_qrcode(qr,"/sdcard/sl4a/qrcode.bmp")
       +    finally:
       +        droid.dialogDismiss()
       +
       +        
       +
       +
       +droid = android.Android()
       +menu_commands = ["send", "receive", "settings", "contacts", "main"]
       +wallet = None
       +interface = None
       +
       +class ElectrumGui:
       +
       +    def __init__(self, w, config, app=None):
       +        global wallet, interface
       +        wallet = w
       +        interface = wallet.interface
       +        interface.register_callback('updated',update_callback)
       +        interface.register_callback('connected', update_callback)
       +        interface.register_callback('disconnected', update_callback)
       +        interface.register_callback('disconnecting', update_callback)
       +
       +    def server_list_changed(self): pass
       +
       +    def main(self, url):
       +        s = 'main'
       +        while True:
       +            add_menu(s)
       +            if s == 'main':
       +                droid.fullShow(main_layout())
       +                s = main_loop()
       +
       +            elif s == 'send':
       +                droid.fullShow(payto_layout)
       +                s = payto_loop()
       +
       +            elif s == 'receive':
       +                make_bitmap(receive_addr)
       +                droid.fullShow(qr_layout(receive_addr))
       +                s = receive_loop()
       +
       +            elif s == 'contacts':
       +                make_bitmap(contact_addr)
       +                droid.fullShow(qr_layout(contact_addr))
       +                s = contacts_loop()
       +
       +            elif s == 'settings':
       +                s = settings_loop()
       +
       +            else:
       +                break
       +
       +        droid.makeToast("Bye!")
   DIR diff --git a/lib/gui_qt.py b/lib/gui_qt.py
       t@@ -1372,22 +1372,7 @@ class ElectrumWindow(QMainWindow):
                    status = _("Please choose a server.")
        
                server = interface.server
       -
       -        plist = {}
       -        if not wallet.interface.servers:
       -            servers_list = []
       -            for x in DEFAULT_SERVERS:
       -                h,port,protocol = x.split(':')
       -                servers_list.append( (h,[(protocol,port)] ) )
       -        else:
       -            servers_list = wallet.interface.servers
       -            for item in servers_list:
       -                _host, pp = item
       -                z = {}
       -                for item2 in pp:
       -                    _protocol, _port = item2
       -                    z[_protocol] = _port
       -                plist[_host] = z
       +        plist, servers_list = interface.get_servers_list()
        
                d = QDialog(parent)
                d.setModal(1)
   DIR diff --git a/lib/interface.py b/lib/interface.py
       t@@ -490,6 +490,28 @@ class Interface(threading.Thread):
                    self.is_connected = False  # this exits the polling loop
                    self.trigger_callback('disconnecting') # for actively disconnecting
        
       +
       +    def get_servers_list(self):
       +        plist = {}
       +        if not self.servers:
       +            servers_list = []
       +            for x in DEFAULT_SERVERS:
       +                h,port,protocol = x.split(':')
       +                servers_list.append( (h,[(protocol,port)] ) )
       +        else:
       +            servers_list = self.servers
       +        
       +        for item in servers_list:
       +            _host, pp = item
       +            z = {}
       +            for item2 in pp:
       +                _protocol, _port = item2
       +                z[_protocol] = _port
       +            plist[_host] = z
       +                
       +        return plist, servers_list
       +
       +
            def is_empty(self, channel):
                q = self.responses.get(channel)
                if q: 
   DIR diff --git a/lib/simple_config.py b/lib/simple_config.py
       t@@ -8,32 +8,29 @@ from version import ELECTRUM_VERSION, SEED_VERSION
        
        class SimpleConfig:
        
       -    def __init__(self, options=None):
       +    def __init__(self, options={}):
        
                # system conf, readonly
                self.system_config = {}
                self.read_system_config()
        
                # user conf, writeable
       +        self.user_dir = user_dir()
                self.user_config = {}
                self.read_user_config()
        
                # command-line options
       -        self.options_config = {}
       -        if options:
       -            if options.server: self.options_config['server'] = options.server
       -            if options.proxy: self.options_config['proxy'] = options.proxy
       -            if options.gui: self.options_config['gui'] = options.gui
       -
       +        self.options_config = options
        
                self.wallet_config = {}
                self.wallet_file_exists = False
       -        self.init_path(options)
       +        self.init_path(self.options_config.get('wallet_path'))
                print_error( "path", self.path )
                if self.path:
                    self.read_wallet_config(self.path)
                    
                    
       +            
                
        
            def set_key(self, key, value, save = False):
       t@@ -62,8 +59,7 @@ class SimpleConfig:
        
            def get(self, key, default=None):
                # 1. command-line options always override everything
       -        if self.options_config.has_key(key):
       -            # print "found", key, "in options"
       +        if self.options_config.has_key(key) and self.options_config.get(key) is not None:
                    out = self.options_config.get(key)
        
                # 2. user configuration 
       t@@ -123,7 +119,9 @@ class SimpleConfig:
        
        
            def read_user_config(self):
       -        name = os.path.join( user_dir(), 'electrum.conf')
       +        if not self.user_dir: return
       +
       +        name = os.path.join( self.user_dir, 'electrum.conf')
                if os.path.exists(name):
                    try:
                        import ConfigParser
       t@@ -140,17 +138,9 @@ class SimpleConfig:
                        pass
        
        
       -    def init_path(self, options):
       +    def init_path(self, path):
                """Set the path of the wallet."""
        
       -        path = None
       -        if options:
       -            # this will call read_wallet_config only if there is a wallet_path value in options
       -            try:
       -                path = options.wallet_path
       -            except:
       -                pass
       -
                if not path:
                    path = self.get('default_wallet_path')
        
       t@@ -159,23 +149,22 @@ class SimpleConfig:
                    return
        
                # Look for wallet file in the default data directory.
       -        # Keeps backwards compatibility.
       -        wallet_dir = user_dir()
       -
                # Make wallet directory if it does not yet exist.
       -        if not os.path.exists(wallet_dir):
       -            os.mkdir(wallet_dir)
       -        self.path = os.path.join(wallet_dir, "electrum.dat")
       +        if not os.path.exists(self.user_dir):
       +            os.mkdir(self.user_dir)
       +        self.path = os.path.join(self.user_dir, "electrum.dat")
        
        
            def save_user_config(self):
       +        if not self.user_dir: return
       +
                import ConfigParser
                config = ConfigParser.RawConfigParser()
                config.add_section('client')
                for k,v in self.user_config.items():
                    config.set('client', k, v)
        
       -        with open( os.path.join( user_dir(), 'electrum.conf'), 'wb') as configfile:
       +        with open( os.path.join( self.user_dir, 'electrum.conf'), 'wb') as configfile:
                    config.write(configfile)
                
        
       t@@ -207,6 +196,7 @@ class SimpleConfig:
                f = open(self.path,"w")
                f.write( s )
                f.close()
       -        import stat
       -        os.chmod(self.path,stat.S_IREAD | stat.S_IWRITE)
       +        if self.get('gui') != 'android':
       +            import stat
       +            os.chmod(self.path,stat.S_IREAD | stat.S_IWRITE)
        
   DIR diff --git a/lib/util.py b/lib/util.py
       t@@ -17,14 +17,14 @@ def print_error(*args):
        
        def user_dir():
            if "HOME" in os.environ:
       -      return os.path.join(os.environ["HOME"], ".electrum")
       +        return os.path.join(os.environ["HOME"], ".electrum")
            elif "LOCALAPPDATA" in os.environ:
       -      return os.path.join(os.environ["LOCALAPPDATA"], "Electrum")
       +        return os.path.join(os.environ["LOCALAPPDATA"], "Electrum")
            elif "APPDATA" in os.environ:
       -      return os.path.join(os.environ["APPDATA"], "Electrum")
       +        return os.path.join(os.environ["APPDATA"], "Electrum")
            else:
       -      raise BaseException("No home directory found in environment variables.")
       -
       +        #raise BaseException("No home directory found in environment variables.")
       +        return 
        
        def appdata_dir():
            """Find the path to the application data directory; add an electrum folder and return path."""
   DIR diff --git a/lib/wallet.py b/lib/wallet.py
       t@@ -379,7 +379,9 @@ class Wallet:
                    is_pruned = False
                    v_in = v_out = v = 0
                    d = self.transactions.get(tx_hash)
       -            if not d: return 0
       +            if not d: 
       +                return 0, 0, 0
       +
                    for item in d.get('inputs'):
                        addr = item.get('address')
                        if addr in addresses:
       t@@ -611,7 +613,8 @@ class Wallet:
                    self.transactions[tx_hash] = tx
        
                tx_height = tx.get('height')
       -        if tx_height>0: self.verifier.add(tx_hash, tx_height)
       +        if self.verifier and tx_height>0: 
       +            self.verifier.add(tx_hash, tx_height)
        
                self.update_tx_outputs(tx_hash)
        
       t@@ -632,7 +635,7 @@ class Wallet:
                    for tx_hash, tx_height in hist:
                        if tx_height>0:
                            # add it in case it was previously unconfirmed
       -                    self.verifier.add(tx_hash, tx_height)
       +                    if self.verifier: self.verifier.add(tx_hash, tx_height)
                            # set the height in case it changed
                            tx = self.transactions.get(tx_hash)
                            if tx:
       t@@ -692,8 +695,8 @@ class Wallet:
        
            def get_default_label(self, tx_hash):
                tx = self.transactions.get(tx_hash)
       +        default_label = ''
                if tx:
       -            default_label = ''
                    is_mine, _, _ = self.get_tx_value(tx_hash)
                    if is_mine:
                        for o in tx['outputs']:
       t@@ -1202,8 +1205,9 @@ class WalletSynchronizer(threading.Thread):
                                    if (tx_hash, tx_height) not in requested_tx and (tx_hash, tx_height) not in missing_tx:
                                        missing_tx.append( (tx_hash, tx_height) )
                                else:
       -                            timestamp = self.wallet.verifier.get_timestamp(tx_height)
       -                            self.wallet.set_tx_timestamp(tx_hash, timestamp)
       +                            if self.wallet.verifier:
       +                                timestamp = self.wallet.verifier.get_timestamp(tx_height)
       +                                self.wallet.set_tx_timestamp(tx_hash, timestamp)
        
                    elif method == 'blockchain.transaction.get':
                        tx_hash = params[0]
       t@@ -1239,6 +1243,6 @@ class WalletSynchronizer(threading.Thread):
                d = deserialize.parse_Transaction(vds)
                d['height'] = tx_height
                d['tx_hash'] = tx_hash
       -        d['timestamp'] = self.wallet.verifier.get_timestamp(tx_height)
       +        if self.wallet.verifier: d['timestamp'] = self.wallet.verifier.get_timestamp(tx_height)
                return d