URI: 
       tMerge branch '1.9' of git://github.com/spesmilo/electrum into 1.9 - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit 853d32b73d4b829330974146cd2d3caad5e8d04c
   DIR parent 238ed351349eb1a84cba0b4c940c72e5e6cd98c8
  HTML Author: thomasv <thomasv@gitorious>
       Date:   Thu, 29 Aug 2013 17:37:09 +0200
       
       Merge branch '1.9' of git://github.com/spesmilo/electrum into 1.9
       
       Diffstat:
         M gui/gui_classic.py                  |      82 +++++++++----------------------
         M gui/installwizard.py                |      28 +++++++++++++++++++++-------
         M gui/qt_util.py                      |      50 +++++++++++++++++++++++++++++++
         M lib/account.py                      |       3 +++
         M lib/wallet.py                       |      45 +++++++++++++++++++++++++++-----
       
       5 files changed, 137 insertions(+), 71 deletions(-)
       ---
   DIR diff --git a/gui/gui_classic.py b/gui/gui_classic.py
       t@@ -147,29 +147,6 @@ class UpdateLabel(QLabel):
        
        
        
       -class Timer(QtCore.QThread):
       -    def run(self):
       -        while True:
       -            self.emit(QtCore.SIGNAL('timersignal'))
       -            time.sleep(0.5)
       -
       -class HelpButton(QPushButton):
       -    def __init__(self, text):
       -        QPushButton.__init__(self, '?')
       -        self.setFocusPolicy(Qt.NoFocus)
       -        self.setFixedWidth(20)
       -        self.clicked.connect(lambda: QMessageBox.information(self, 'Help', text, 'OK') )
       -
       -
       -class EnterButton(QPushButton):
       -    def __init__(self, text, func):
       -        QPushButton.__init__(self, text)
       -        self.func = func
       -        self.clicked.connect(func)
       -
       -    def keyPressEvent(self, e):
       -        if e.key() == QtCore.Qt.Key_Return:
       -            apply(self.func,())
        
        class MyTreeWidget(QTreeWidget):
            def __init__(self, parent):
       t@@ -208,26 +185,6 @@ class StatusBarButton(QPushButton):
        
        
        
       -def waiting_dialog(f):
       -
       -    s = Timer()
       -    s.start()
       -    w = QDialog()
       -    w.resize(200, 70)
       -    w.setWindowTitle('Electrum')
       -    l = QLabel('')
       -    vbox = QVBoxLayout()
       -    vbox.addWidget(l)
       -    w.setLayout(vbox)
       -    w.show()
       -    def ff():
       -        s = f()
       -        if s: l.setText(s)
       -        else: w.close()
       -    w.connect(s, QtCore.SIGNAL('timersignal'), ff)
       -    w.exec_()
       -    w.destroy()
       -
        
        
        
       t@@ -1454,22 +1411,31 @@ class ElectrumWindow(QMainWindow):
        
        
            def new_account_dialog(self):
       -        text, ok = QInputDialog.getText(self, _('New Account'), _('Name') + ':')
       -        if not ok or not text: 
       -            return
       -        name = unicode(text)
       -        try:
       -            self.create_new_account(name)
       -        except:
       -            QMessageBox.warning(self, _('Error'), _('Incorrect Password'), _('OK'))
       +
       +        dialog = QDialog(self)
       +        dialog.setModal(1)
       +        dialog.setWindowTitle(_("New Account"))
       +
       +        addr = self.wallet.new_account_address()
       +        vbox = QVBoxLayout()
       +        vbox.addWidget(QLabel("To add another account, please send bitcoins to the following address:"))
       +        e = QLineEdit(addr)
       +        e.setReadOnly(True)
       +        vbox.addWidget(e)
       +
       +        ok_button = QPushButton(_("OK"))
       +        ok_button.setDefault(True)
       +        ok_button.clicked.connect(dialog.accept)
       +
       +        hbox = QHBoxLayout()
       +        hbox.addStretch(1)
       +        hbox.addWidget(ok_button)
       +        vbox.addLayout(hbox)
       +
       +        dialog.setLayout(vbox)
       +        dialog.exec_()
       +
                    
       -    @protected
       -    def create_new_account(self, name, password):
       -        self.wallet.create_new_account(name, password)
       -        self.wallet.synchronize()
       -        self.update_receive_tab()
       -        self.update_history_tab()
       -        self.update_completions()
        
            def show_master_public_key(self):
                dialog = QDialog(self)
   DIR diff --git a/gui/installwizard.py b/gui/installwizard.py
       t@@ -3,10 +3,14 @@ from PyQt4.QtCore import *
        import PyQt4.QtCore as QtCore
        from i18n import _
        
       -from electrum import Wallet, mnemonic
       +from electrum import Wallet, mnemonic, WalletVerifier, WalletSynchronizer
       +
        from seed_dialog import SeedDialog
        from network_dialog import NetworkDialog
        from qt_util import *
       +from amountedit import AmountEdit
       +
       +import sys
        
        class InstallWizard(QDialog):
        
       t@@ -107,8 +111,8 @@ class InstallWizard(QDialog):
                d.run()
        
        
       -    def restore_wallet(self):
       -        wallet = self.wallet
       +    def restore_wallet(self, wallet):
       +
                # wait until we are connected, because the user might have selected another server
                if not wallet.interface.is_connected:
                    waiting = lambda: False if wallet.interface.is_connected else "%s \n" % (_("Connecting..."))
       t@@ -121,9 +125,9 @@ class InstallWizard(QDialog):
                wallet.interface.poke('synchronizer')
                waiting_dialog(waiting)
                if wallet.is_found():
       -            print_error( "Recovery successful" )
       +            QMessageBox.information(None, _('Information'), _("Recovery successful"), _('OK'))
                else:
       -            QMessageBox.information(None, _('Error'), _("No transactions found for this seed"), _('OK'))
       +            QMessageBox.information(None, _('Information'), _("No transactions found for this seed"), _('OK'))
        
                return True
        
       t@@ -145,7 +149,7 @@ class InstallWizard(QDialog):
                        exit()
                else:
                    # ask for seed and gap.
       -            sg = gui.seed_dialog()
       +            sg = self.seed_dialog()
                    if not sg: exit()
                    seed, gap = sg
                    if not seed: exit()
       t@@ -163,6 +167,16 @@ class InstallWizard(QDialog):
                    self.config.set_key("server", None, True)
                    self.config.set_key('auto_cycle', False, True)
        
       +        self.interface.start(wait = False)
       +
       +        # start wallet threads
       +        verifier = WalletVerifier(self.interface, self.config)
       +        verifier.start()
       +        wallet.set_verifier(verifier)
       +        synchronizer = WalletSynchronizer(wallet, self.config)
       +        synchronizer.start()
       +
       +
                # generate the first addresses, in case we are offline
                if s is None or a == 'create':
                    wallet.synchronize()
       t@@ -170,7 +184,7 @@ class InstallWizard(QDialog):
        
                if a == 'restore' and s is not None:
                    try:
       -                keep_it = gui.restore_wallet()
       +                keep_it = self.restore_wallet(wallet)
                        wallet.fill_addressbook()
                    except:
                        import traceback
   DIR diff --git a/gui/qt_util.py b/gui/qt_util.py
       t@@ -2,6 +2,56 @@ from i18n import _
        from PyQt4.QtGui import *
        from PyQt4.QtCore import *
        import os.path
       +import time
       +
       +
       +class Timer(QThread):
       +    def run(self):
       +        while True:
       +            self.emit(SIGNAL('timersignal'))
       +            time.sleep(0.5)
       +
       +
       +class EnterButton(QPushButton):
       +    def __init__(self, text, func):
       +        QPushButton.__init__(self, text)
       +        self.func = func
       +        self.clicked.connect(func)
       +
       +    def keyPressEvent(self, e):
       +        if e.key() == Qt.Key_Return:
       +            apply(self.func,())
       +
       +
       +def waiting_dialog(f):
       +
       +    s = Timer()
       +    s.start()
       +    w = QDialog()
       +    w.resize(200, 70)
       +    w.setWindowTitle('Electrum')
       +    l = QLabel('')
       +    vbox = QVBoxLayout()
       +    vbox.addWidget(l)
       +    w.setLayout(vbox)
       +    w.show()
       +    def ff():
       +        s = f()
       +        if s: l.setText(s)
       +        else: w.close()
       +    w.connect(s, SIGNAL('timersignal'), ff)
       +    w.exec_()
       +    w.destroy()
       +
       +
       +class HelpButton(QPushButton):
       +    def __init__(self, text):
       +        QPushButton.__init__(self, '?')
       +        self.setFocusPolicy(Qt.NoFocus)
       +        self.setFixedWidth(20)
       +        self.clicked.connect(lambda: QMessageBox.information(self, 'Help', text, 'OK') )
       +
       +
        
        def backup_wallet(path):
            import shutil
   DIR diff --git a/lib/account.py b/lib/account.py
       t@@ -160,6 +160,9 @@ class BIP32_Account(Account):
                address = public_key_to_bc_address( pubkey.decode('hex') )
                return address
        
       +    def first_address(self):
       +        return self.get_address(0,0)
       +
            def get_pubkey(self, for_change, n):
                K = self.K
                chain = self.c
   DIR diff --git a/lib/wallet.py b/lib/wallet.py
       t@@ -90,6 +90,8 @@ class Wallet:
                self.master_public_keys = config.get('master_public_keys',{})
                self.master_private_keys = config.get('master_private_keys', {})
        
       +        self.first_addresses = config.get('first_addresses',{})
       +
                self.load_accounts(config)
        
                self.transactions = {}
       t@@ -204,7 +206,7 @@ class Wallet:
                self.config.set_key('master_private_keys', self.master_private_keys, True)
        
                # create default account
       -        self.create_account('Main account')
       +        self.create_account('1','Main account')
        
        
            def find_root_by_master_key(self, c, K):
       t@@ -229,7 +231,7 @@ class Wallet:
        
        
            def account_id(self, account_type, i):
       -        if account_type is None:
       +        if account_type == '1':
                    return "m/0'/%d"%i
                elif account_type == '2of2':
                    return "m/1'/%d & m/2'/%d"%(i,i)
       t@@ -249,11 +251,26 @@ class Wallet:
                return i
        
        
       -    def create_account(self, name, account_type = None):
       +    def new_account_address(self, account_type = '1'):
       +        i = self.num_accounts(account_type)
       +        k = self.account_id(account_type,i)
       +
       +        addr = self.first_addresses.get(k)
       +        if not addr: 
       +            account_id, account = self.next_account(account_type)
       +            addr = account.first_address()
       +            self.first_addresses[k] = addr
       +            self.config.set_key('first_addresses',self.first_addresses)
       +
       +        return addr
       +
       +
       +    def next_account(self, account_type = '1'):
       +
                i = self.num_accounts(account_type)
                account_id = self.account_id(account_type,i)
        
       -        if account_type is None:
       +        if account_type is '1':
                    master_c0, master_K0, _ = self.master_public_keys["m/0'/"]
                    c0, K0, cK0 = bip32_public_derivation(master_c0.decode('hex'), master_K0.decode('hex'), "m/0'/", "m/0'/%d"%i)
                    account = BIP32_Account({ 'c':c0, 'K':K0, 'cK':cK0 })
       t@@ -274,6 +291,11 @@ class Wallet:
                    c5, K5, cK5 = bip32_public_derivation(master_c5.decode('hex'), master_K5.decode('hex'), "m/5'/", "m/5'/%d"%i)
                    account = BIP32_Account_2of3({ 'c':c3, 'K':K3, 'cK':cK3, 'c2':c4, 'K2':K4, 'cK2':cK4, 'c3':c5, 'K3':K5, 'cK3':cK5 })
        
       +        return account_id, account
       +
       +
       +    def create_account(self, account_type = '1', name = 'unnamed'):
       +        account_id, account = self.next_account(account_type)
                self.accounts[account_id] = account
                self.save_accounts()
                self.labels[account_id] = name
       t@@ -297,18 +319,18 @@ class Wallet:
                        self.accounts[k] = BIP32_Account(v)
        
        
       -
       -
            def addresses(self, include_change = True):
                o = self.get_account_addresses(-1, include_change)
                for a in self.accounts.keys():
                    o += self.get_account_addresses(a, include_change)
       +        o += self.first_addresses.values()
                return o
        
        
            def is_mine(self, address):
                return address in self.addresses(True)
        
       +
            def is_change(self, address):
                if not self.is_mine(address): return False
                if address in self.imported_keys.keys(): return False
       t@@ -577,13 +599,24 @@ class Wallet:
                return new_addresses
                
        
       +
       +    def create_pending_accounts(self):
       +        for account_type in ['1','2of2','2of3']:
       +            a = self.new_account_address(account_type)
       +            if self.address_is_old(a):
       +                print "creating account", a
       +                self.create_account(account_type)
       +
       +
            def synchronize_account(self, account):
                new = []
                new += self.synchronize_sequence(account, 0)
                new += self.synchronize_sequence(account, 1)
                return new
        
       +
            def synchronize(self):
       +        self.create_pending_accounts()
                new = []
                for account in self.accounts.values():
                    new += self.synchronize_account(account)