move callbacks to the network class
[electrum-nvc.git] / gui / gui_classic.py
index 42b6e24..53ce98f 100644 (file)
@@ -21,6 +21,7 @@ from i18n import _, set_language
 from electrum.util import print_error, print_msg
 import os.path, json, ast, traceback
 import shutil
+import StringIO
 
 
 try:
@@ -32,7 +33,7 @@ from PyQt4.QtGui import *
 from PyQt4.QtCore import *
 import PyQt4.QtCore as QtCore
 
-from electrum.bitcoin import MIN_RELAY_TX_FEE
+from electrum.bitcoin import MIN_RELAY_TX_FEE, is_valid
 
 try:
     import icons_rc
@@ -40,10 +41,10 @@ except:
     sys.exit("Error: Could not import icons_rc.py, please generate it with: 'pyrcc4 icons.qrc -o gui/icons_rc.py'")
 
 from electrum.wallet import format_satoshis
-from electrum.bitcoin import Transaction, is_valid
+from electrum import Transaction
 from electrum import mnemonic
-from electrum import util, bitcoin, commands, Interface, Wallet, TxVerifier, WalletSynchronizer
-from electrum import SimpleConfig, Wallet, WalletSynchronizer, WalletStorage
+from electrum import util, bitcoin, commands, Interface, Wallet
+from electrum import SimpleConfig, Wallet, WalletStorage
 
 
 import bmp, pyqrnative
@@ -178,6 +179,7 @@ class StatusBarButton(QPushButton):
         self.setMaximumWidth(25)
         self.clicked.connect(func)
         self.func = func
+        self.setIconSize(QSize(25,25))
 
     def keyPressEvent(self, e):
         if e.key() == QtCore.Qt.Key_Return:
@@ -225,10 +227,11 @@ class ElectrumWindow(QMainWindow):
             self.showNormal()
 
 
-    def __init__(self, config):
+    def __init__(self, config, network):
         QMainWindow.__init__(self)
 
         self.config = config
+        self.network = network
         self.init_plugins()
 
         self._close_electrum = False
@@ -249,7 +252,6 @@ class ElectrumWindow(QMainWindow):
         self.expert_mode   = config.get('classic_expert_mode', False)
         self.decimal_point = config.get('decimal_point', 8)
         self.num_zeros     = int(config.get('num_zeros',0))
-        self.fee                   = int(config.get('fee_per_kb',20000))
 
         set_language(config.get('language'))
 
@@ -302,11 +304,11 @@ class ElectrumWindow(QMainWindow):
         import electrum
         self.wallet = wallet
 
-        self.wallet.interface.register_callback('updated', lambda: self.need_update.set())
-        self.wallet.interface.register_callback('banner', lambda: self.emit(QtCore.SIGNAL('banner_signal')))
-        self.wallet.interface.register_callback('disconnected', lambda: self.emit(QtCore.SIGNAL('update_status')))
-        self.wallet.interface.register_callback('disconnecting', lambda: self.emit(QtCore.SIGNAL('update_status')))
-        self.wallet.interface.register_callback('new_transaction', lambda: self.emit(QtCore.SIGNAL('transaction_signal')))
+        self.network.register_callback('updated', lambda: self.need_update.set())
+        self.network.register_callback('banner', lambda: self.emit(QtCore.SIGNAL('banner_signal')))
+        self.network.register_callback('disconnected', lambda: self.emit(QtCore.SIGNAL('update_status')))
+        self.network.register_callback('disconnecting', lambda: self.emit(QtCore.SIGNAL('update_status')))
+        self.network.register_callback('new_transaction', lambda: self.emit(QtCore.SIGNAL('transaction_signal')))
         title = 'Electrum ' + self.wallet.electrum_version + '  -  ' + self.wallet.storage.path
         if not self.wallet.seed: title += ' [%s]' % (_('seedless'))
         self.setWindowTitle( title )
@@ -317,7 +319,7 @@ class ElectrumWindow(QMainWindow):
         self.notify_transactions()
 
         # account selector
-        accounts = self.wallet.get_accounts()
+        accounts = self.wallet.get_account_names()
         self.account_selector.clear()
         if len(accounts) > 1:
             self.account_selector.addItems([_("All accounts")] + accounts.values())
@@ -326,10 +328,14 @@ class ElectrumWindow(QMainWindow):
         else:
             self.account_selector.hide()
 
+        self.new_account.setEnabled(self.wallet.seed_version>4)
+
         self.update_lock_icon()
         self.update_buttons_on_seed()
         self.update_console()
 
+        self.run_hook('load_wallet')
+
 
     def select_wallet_file(self):
         wallet_folder = self.wallet.storage.path
@@ -351,20 +357,11 @@ class ElectrumWindow(QMainWindow):
 
         interface = self.wallet.interface
         blockchain = self.wallet.verifier.blockchain
-
-        self.wallet.verifier.stop()
-        self.wallet.synchronizer.stop()
+        self.wallet.stop_threads()
         
-        # create wallet 
+        # create new wallet 
         wallet = Wallet(storage)
-        wallet.interface = interface
-
-        verifier = TxVerifier(interface, blockchain, storage)
-        verifier.start()
-        wallet.set_verifier(verifier)
-
-        synchronizer = WalletSynchronizer(wallet)
-        synchronizer.start()
+        wallet.start_threads(interface, blockchain)
 
         self.load_wallet(wallet)
 
@@ -379,7 +376,7 @@ class ElectrumWindow(QMainWindow):
         storage = WalletStorage({'wallet_path': filename})
         assert not storage.file_exists
 
-        wizard = installwizard.InstallWizard(self.config, self.wallet.interface, storage)
+        wizard = installwizard.InstallWizard(self.config, self.wallet.interface, self.wallet.verifier.blockchain, storage)
         wallet = wizard.run()
         if wallet: 
             self.load_wallet(wallet)
@@ -397,7 +394,7 @@ class ElectrumWindow(QMainWindow):
         new_wallet_action.triggered.connect(self.new_wallet)
 
         wallet_backup = file_menu.addAction(_("&Copy"))
-        wallet_backup.triggered.connect(lambda: backup_wallet(self.config.path))
+        wallet_backup.triggered.connect(lambda: backup_wallet(self.wallet.storage.path))
 
         quit_item = file_menu.addAction(_("&Close"))
         quit_item.triggered.connect(self.close)
@@ -419,6 +416,14 @@ class ElectrumWindow(QMainWindow):
         raw_transaction_text = raw_transaction_menu.addAction(_("&From text"))
         raw_transaction_text.triggered.connect(self.do_process_from_text)
 
+        csv_transaction_menu = wallet_menu.addMenu(_("&Load CSV transaction"))
+
+        csv_transaction_file = csv_transaction_menu.addAction(_("&From file"))
+        csv_transaction_file.triggered.connect(self.do_process_from_csv_file)
+
+        csv_transaction_text = csv_transaction_menu.addAction(_("&From text"))
+        csv_transaction_text.triggered.connect(self.do_process_from_csv_text)
+
         wallet_menu.addSeparator()
 
         show_menu = wallet_menu.addMenu(_("Show"))
@@ -434,8 +439,8 @@ class ElectrumWindow(QMainWindow):
         new_contact = wallet_menu.addAction(_("&New contact"))
         new_contact.triggered.connect(self.new_contact_dialog)
 
-        new_account = wallet_menu.addAction(_("&New account"))
-        new_account.triggered.connect(self.new_account_dialog)
+        self.new_account = wallet_menu.addAction(_("&New account"))
+        self.new_account.triggered.connect(self.new_account_dialog)
 
         import_menu = menubar.addMenu(_("&Import"))
         in_labels = import_menu.addAction(_("&Labels"))
@@ -531,11 +536,6 @@ class ElectrumWindow(QMainWindow):
         return
 
 
-    def set_fee(self, fee):
-        if self.fee != fee:
-            self.fee = fee
-            self.config.set_key('fee_per_kb', self.fee, True)
-        
 
     def set_label(self, name, text = None):
         changed = False
@@ -543,7 +543,7 @@ class ElectrumWindow(QMainWindow):
         if text:
             if old_text != text:
                 self.wallet.labels[name] = text
-                self.wallet.storage.set_key('labels', self.wallet.labels)
+                self.wallet.storage.put('labels', self.wallet.labels)
                 changed = True
         else:
             if old_text:
@@ -569,8 +569,6 @@ class ElectrumWindow(QMainWindow):
             self.config.set_key('io_dir', os.path.dirname(fileName), True)
         return fileName
 
-
-
     def close(self):
         QMainWindow.close(self)
         self.run_hook('close_main_window')
@@ -1024,6 +1022,10 @@ class ElectrumWindow(QMainWindow):
             except:
                 QMessageBox.warning(self, _('Error'), _('Could not write transaction to file'), _('OK'))
 
+        # add recipient to addressbook
+        if to_address not in self.wallet.addressbook and not self.wallet.is_mine(to_address):
+            self.wallet.addressbook.append(to_address)
+
 
 
 
@@ -1283,7 +1285,7 @@ class ElectrumWindow(QMainWindow):
             account_items = []
 
         for k, account in account_items:
-            name = self.wallet.labels.get(k, 'unnamed account')
+            name = self.wallet.get_account_name(k)
             c,u = self.wallet.get_account_balance(k)
             account_item = QTreeWidgetItem( [ name, '', self.format_amount(c+u), ''] )
             l.addTopLevelItem(account_item)
@@ -1364,7 +1366,7 @@ class ElectrumWindow(QMainWindow):
         console.history = self.config.get("console-history",[])
         console.history_index = len(console.history)
 
-        console.updateNamespace({'wallet' : self.wallet, 'interface' : self.wallet.interface, 'gui':self})
+        console.updateNamespace({'wallet' : self.wallet, 'network' : self.wallet.network, 'gui':self})
         console.updateNamespace({'util' : util, 'bitcoin':bitcoin})
 
         c = commands.Commands(self.wallet, self.wallet.interface, lambda: self.console.set_json(True))
@@ -1382,7 +1384,7 @@ class ElectrumWindow(QMainWindow):
         if s == _("All accounts"):
             self.current_account = None
         else:
-            accounts = self.wallet.get_accounts()
+            accounts = self.wallet.get_account_names()
             for k, v in accounts.items():
                 if v == s:
                     self.current_account = k
@@ -1455,7 +1457,7 @@ class ElectrumWindow(QMainWindow):
         if self.lite:
             self.lite.mini.show()
         else:
-            self.lite = gui_lite.ElectrumGui(self.wallet, self.config, self)
+            self.lite = gui_lite.ElectrumGui(self.config, None, None, self)
             self.lite.main(None)
 
 
@@ -1834,6 +1836,47 @@ class ElectrumWindow(QMainWindow):
         if tx_dict: 
             self.create_process_transaction_window(tx_dict)
 
+    def do_process_from_csvReader(self, csvReader):
+        outputs = []
+        try:
+            for row in csvReader:
+                address = row[0]
+                amount = float(row[1])
+                amount = int(100000000*amount)
+                outputs.append((address, amount))
+        except (ValueError, IOError, os.error), reason:
+            QMessageBox.critical(None,"Unable to read file or no transaction found", _("Electrum was unable to open your transaction file") + "\n" + str(reason))
+            return
+
+        try:
+            tx = self.wallet.make_unsigned_transaction(outputs, None, None, account=self.current_account)
+        except BaseException, e:
+            self.show_message(str(e))
+            return
+
+        tx_dict = tx.as_dict()
+        self.create_process_transaction_window(tx_dict)
+
+    def do_process_from_csv_file(self):
+        fileName = self.getOpenFileName(_("Select your transaction CSV"), "*.csv")
+        if not fileName:
+            return
+        try:
+            with open(fileName, "r") as f:
+                csvReader = csv.reader(f)
+                self.do_process_from_csvReader(csvReader)
+        except (ValueError, IOError, os.error), reason:
+            QMessageBox.critical(None,"Unable to read file or no transaction found", _("Electrum was unable to open your transaction file") + "\n" + str(reason))
+            return
+
+    def do_process_from_csv_text(self):
+        text = text_dialog(self, _('Input CSV'), _("CSV:"), _("Load CSV"))
+        if not text:
+            return
+        f = StringIO.StringIO(text)
+        csvReader = csv.reader(f)
+        self.do_process_from_csvReader(csvReader)
+
     def create_process_transaction_window(self, tx_dict):
         tx = Transaction(tx_dict["hex"])
             
@@ -1906,8 +1949,7 @@ class ElectrumWindow(QMainWindow):
             data = f.read()
             f.close()
             for key, value in json.loads(data).items():
-                self.wallet.labels[key] = value
-            self.wallet.save()
+                self.wallet.set_label(key, value)
             QMessageBox.information(None, _("Labels imported"), _("Your labels were imported from")+" '%s'" % str(labelsFile))
         except (IOError, os.error), reason:
             QMessageBox.critical(None, _("Unable to import labels"), _("Electrum was unable to import your labels.")+"\n" + str(reason))
@@ -2036,7 +2078,7 @@ class ElectrumWindow(QMainWindow):
         fee_label = QLabel(_('Transaction fee'))
         grid_wallet.addWidget(fee_label, 0, 0)
         fee_e = AmountEdit(self.base_unit)
-        fee_e.setText(self.format_amount(self.fee).strip())
+        fee_e.setText(self.format_amount(self.wallet.fee).strip())
         grid_wallet.addWidget(fee_e, 0, 2)
         msg = _('Fee per kilobyte of transaction.') + ' ' \
             + _('Recommended value') + ': ' + self.format_amount(50000)
@@ -2126,7 +2168,7 @@ class ElectrumWindow(QMainWindow):
             QMessageBox.warning(self, _('Error'), _('Invalid value') +': %s'%fee, _('OK'))
             return
 
-        self.set_fee(fee)
+        self.wallet.set_fee(fee)
         
         nz = unicode(nz_e.text())
         try:
@@ -2214,10 +2256,11 @@ class OpenFileEventFilter(QObject):
 
 class ElectrumGui:
 
-    def __init__(self, config, interface, blockchain, app=None):
-        self.interface = interface
+    def __init__(self, config, network, app=None):
+        self.network = network
+        #self.interface = interface
         self.config = config
-        self.blockchain = blockchain
+        #self.blockchain = network.blockchain
         self.windows = []
         self.efilter = OpenFileEventFilter(self.windows)
         if app is None:
@@ -2230,25 +2273,18 @@ class ElectrumGui:
         storage = WalletStorage(self.config)
         if not storage.file_exists:
             import installwizard
-            wizard = installwizard.InstallWizard(self.config, self.interface, storage)
+            wizard = installwizard.InstallWizard(self.config, self.interface, self.blockchain, storage)
             wallet = wizard.run()
             if not wallet: 
                 exit()
         else:
             wallet = Wallet(storage)
 
-        wallet.interface = self.interface
-
-        verifier = TxVerifier(self.interface, self.blockchain, storage)
-        verifier.start()
-        wallet.set_verifier(verifier)
-
-        synchronizer = WalletSynchronizer(wallet)
-        synchronizer.start()
+        wallet.start_threads(self.network)
 
         s = Timer()
         s.start()
-        w = ElectrumWindow(self.config)
+        w = ElectrumWindow(self.config, self.network)
         w.load_wallet(wallet)
 
         self.windows.append(w)
@@ -2260,7 +2296,6 @@ class ElectrumGui:
 
         self.app.exec_()
 
-        verifier.stop()
-        synchronizer.stop()
+        wallet.stop_threads()