1.9.4
[electrum-nvc.git] / gui / qt / main_window.py
index 2b9d72e..640fb1a 100644 (file)
@@ -24,11 +24,7 @@ import shutil
 import StringIO
 
 
-try:
-    import PyQt4
-except:
-    sys.exit("Error: Could not import PyQt4 on Linux systems, you may try 'sudo apt-get install python-qt4'")
-
+import PyQt4
 from PyQt4.QtGui import *
 from PyQt4.QtCore import *
 import PyQt4.QtCore as QtCore
@@ -36,10 +32,7 @@ import PyQt4.QtCore as QtCore
 from electrum.bitcoin import MIN_RELAY_TX_FEE, is_valid
 from electrum.plugins import run_hook
 
-try:
-    import icons_rc
-except:
-    sys.exit("Error: Could not import icons_rc.py, please generate it with: 'pyrcc4 icons.qrc -o gui/icons_rc.py'")
+import icons_rc
 
 from electrum.wallet import format_satoshis
 from electrum import Transaction
@@ -102,7 +95,7 @@ class StatusBarButton(QPushButton):
 
 
 
-default_column_widths = { "history":[40,140,350,140], "contacts":[350,330], "receive":[[370], [370,200,130]] }
+default_column_widths = { "history":[40,140,350,140], "contacts":[350,330], "receive": [370,200,130] }
 
 class ElectrumWindow(QMainWindow):
     def changeEvent(self, event):
@@ -134,19 +127,24 @@ class ElectrumWindow(QMainWindow):
         if reason == QSystemTrayIcon.DoubleClick:
             self.showNormal()
 
+    def showNormal(self):
+        self.setWindowState(self.windowState() & ~QtCore.Qt.WindowMinimized | QtCore.Qt.WindowActive)
 
-    def __init__(self, config, network, go_lite):
+    def __init__(self, config, network):
         QMainWindow.__init__(self)
 
         self.config = config
         self.network = network
-        self.go_lite = go_lite
 
         self._close_electrum = False
         self.lite = None
-        self.current_account = self.config.get("current_account", None)
 
-        self.icon = QIcon(':icons/electrum.png')
+        if sys.platform == 'darwin':
+          self.icon = QIcon(":icons/electrum_dark_icon.png")
+          #self.icon = QIcon(":icons/lock.png")
+        else:
+          self.icon = QIcon(':icons/electrum_light_icon.png')
+
         self.tray = QSystemTrayIcon(self.icon, self)
         self.tray.setToolTip('Electrum')
         self.tray.activated.connect(self.tray_activated)
@@ -157,7 +155,6 @@ class ElectrumWindow(QMainWindow):
 
         self.need_update = threading.Event()
 
-        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))
 
@@ -167,7 +164,7 @@ class ElectrumWindow(QMainWindow):
         self.completions = QStringListModel()
 
         self.tabs = tabs = QTabWidget(self)
-        self.column_widths = self.config.get("column_widths", default_column_widths )
+        self.column_widths = self.config.get("column_widths_2", default_column_widths )
         tabs.addTab(self.create_history_tab(), _('History') )
         tabs.addTab(self.create_send_tab(), _('Send') )
         tabs.addTab(self.create_receive_tab(), _('Receive') )
@@ -180,6 +177,7 @@ class ElectrumWindow(QMainWindow):
         g = self.config.get("winpos-qt",[100, 100, 840, 400])
         self.setGeometry(g[0], g[1], g[2], g[3])
 
+        self.setWindowIcon(QIcon(":icons/electrum.png"))
         self.init_menubar()
 
         QShortcut(QKeySequence("Ctrl+W"), self, self.close)
@@ -193,35 +191,72 @@ class ElectrumWindow(QMainWindow):
         self.connect(self, QtCore.SIGNAL('transaction_signal'), lambda: self.notify_transactions() )
 
         self.history_list.setFocus(True)
-        
-        # dark magic fix by flatfly; https://bitcointalk.org/index.php?topic=73651.msg959913#msg959913
-        if platform.system() == 'Windows':
-            n = 3 if self.wallet.seed else 2
-            tabs.setCurrentIndex (n)
-            tabs.setCurrentIndex (0)
 
+        # network callbacks
+        if self.network:
+            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')))
+
+            # set initial message
+            self.console.showMessage(self.network.banner)
+
+        self.wallet = None
+        self.init_lite()
+
+
+    def go_full(self):
+        self.config.set_key('lite_mode', False, True)
+        self.mini.hide()
+        self.show()
+
+    def go_lite(self):
+        self.config.set_key('lite_mode', True, True)
+        self.hide()
+        self.mini.show()
+
+
+    def init_lite(self):
+        import lite_window
+        if not self.check_qt_version():
+            if self.config.get('lite_mode') is True:
+                msg = "Electrum was unable to load the 'Lite GUI' because it needs Qt version >= 4.7.\nChanging your config to use the 'Classic' GUI"
+                QMessageBox.warning(None, "Could not start Lite GUI.", msg)
+                self.config.set_key('lite_mode', False, True)
+                sys.exit(0)
+            self.mini = None
+            self.show()
+            return
 
-    
+        actuator = lite_window.MiniActuator(self)
 
+        # Should probably not modify the current path but instead
+        # change the behaviour of rsrc(...)
+        old_path = QDir.currentPath()
+        actuator.load_theme()
 
-    def load_wallet(self, wallet):
-        import electrum
-        self.wallet = wallet
+        self.mini = lite_window.MiniWindow(actuator, self.go_full, self.config)
 
-        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 )
-        self.update_wallet()
-        # set initial message
-        self.console.showMessage(self.network.banner)
-        # Once GUI has been initialized check if we want to announce something since the callback has been called before the GUI was initialized
-        self.notify_transactions()
+        driver = lite_window.MiniDriver(self, self.mini)
 
+        # Reset path back to original value now that loading the GUI
+        # is completed.
+        QDir.setCurrent(old_path)
+
+        if self.config.get('lite_mode') is True:
+            self.go_lite()
+        else:
+            self.go_full()
+
+
+    def check_qt_version(self):
+        qtVersion = qVersion()
+        return int(qtVersion[0]) >= 4 and int(qtVersion[2]) >= 7
+    
+
+    def update_account_selector(self):
         # account selector
         accounts = self.wallet.get_account_names()
         self.account_selector.clear()
@@ -232,25 +267,31 @@ class ElectrumWindow(QMainWindow):
         else:
             self.account_selector.hide()
 
-        self.new_account.setEnabled(self.wallet.seed_version>4)
 
+    def load_wallet(self, wallet):
+        import electrum
+        self.wallet = wallet
+        self.accounts_expanded = self.wallet.storage.get('accounts_expanded',{})
+        self.current_account = self.wallet.storage.get("current_account", None)
+
+        title = 'Electrum ' + self.wallet.electrum_version + '  -  ' + self.wallet.storage.path
+        if self.wallet.is_watching_only(): title += ' [%s]' % (_('watching only'))
+        self.setWindowTitle( title )
+        self.update_wallet()
+        # Once GUI has been initialized check if we want to announce something since the callback has been called before the GUI was initialized
+        self.notify_transactions()
+        self.update_account_selector()
+        self.new_account.setEnabled(self.wallet.seed_version>4)
         self.update_lock_icon()
         self.update_buttons_on_seed()
         self.update_console()
 
-        run_hook('load_wallet')
-
-
-    def select_wallet_file(self):
-        wallet_folder = self.wallet.storage.path
-        re.sub("(\/\w*.dat)$", "", wallet_folder)
-        file_name = unicode( QFileDialog.getOpenFileName(self, "Select your wallet file", wallet_folder) )
-        return file_name
+        run_hook('load_wallet', wallet)
 
 
     def open_wallet(self):
-
-        filename = self.select_wallet_file()
+        wallet_folder = self.wallet.storage.path
+        filename = unicode( QFileDialog.getOpenFileName(self, "Select your wallet file", wallet_folder) )
         if not filename:
             return
 
@@ -273,12 +314,11 @@ class ElectrumWindow(QMainWindow):
         import shutil
         path = self.wallet.storage.path
         wallet_folder = os.path.dirname(path)
-        new_filename, ok = QInputDialog.getText(self, _('Filename'), _('Current directory') + ': ' + wallet_folder + '\n' + _('Enter a filename for the copy of your wallet') + ':')
-        new_filename = unicode(new_filename)
-        if not ok or not new_filename:
+        filename = unicode( QFileDialog.getSaveFileName(self, _('Enter a filename for the copy of your wallet'), wallet_folder) )
+        if not filename:
             return
 
-        new_path = os.path.join(wallet_folder, new_filename)
+        new_path = os.path.join(wallet_folder, filename)
         if new_path != path:
             try:
                 shutil.copy2(path, new_path)
@@ -291,14 +331,15 @@ class ElectrumWindow(QMainWindow):
         import installwizard
 
         wallet_folder = os.path.dirname(self.wallet.storage.path)
-        filename, ok = QInputDialog.getText(self, _('Filename'), _('Current directory') + ': ' + wallet_folder + '\n'+_('Enter a new file name') + ':')
-        filename = unicode(filename)
-        if not ok or not filename:
+        filename = unicode( QFileDialog.getSaveFileName(self, _('Enter a new file name'), wallet_folder) )
+        if not filename:
             return
         filename = os.path.join(wallet_folder, filename)
 
         storage = WalletStorage({'wallet_path': filename})
-        assert not storage.file_exists
+        if storage.file_exists:
+            QMessageBox.critical(None, "Error", _("File exists"))
+            return
 
         wizard = installwizard.InstallWizard(self.config, self.network, storage)
         wallet = wizard.run()
@@ -333,7 +374,9 @@ class ElectrumWindow(QMainWindow):
 
         wallet_menu.addSeparator()
 
-        #if self.wallet.seed:
+        pw = wallet_menu.addAction(_("&Password"))
+        pw.triggered.connect(self.change_password_dialog)
+
         show_seed = wallet_menu.addAction(_("&Seed"))
         show_seed.triggered.connect(self.show_seed_dialog)
 
@@ -342,21 +385,21 @@ class ElectrumWindow(QMainWindow):
 
         wallet_menu.addSeparator()
 
-        csv_transaction_menu = wallet_menu.addMenu(_("&Create transaction"))
-
-        csv_transaction_file = csv_transaction_menu.addAction(_("&From CSV file"))
-        csv_transaction_file.triggered.connect(self.do_process_from_csv_file)
-
-        csv_transaction_text = csv_transaction_menu.addAction(_("&From CSV text"))
-        csv_transaction_text.triggered.connect(self.do_process_from_csv_text)
+        labels_menu = wallet_menu.addMenu(_("&Labels"))
+        import_labels = labels_menu.addAction(_("&Import"))
+        import_labels.triggered.connect(self.do_import_labels)
+        export_labels = labels_menu.addAction(_("&Export"))
+        export_labels.triggered.connect(self.do_export_labels)
 
-        raw_transaction_menu = wallet_menu.addMenu(_("&Load transaction"))
+        keys_menu = wallet_menu.addMenu(_("&Private keys"))
+        import_keys = keys_menu.addAction(_("&Import"))
+        import_keys.triggered.connect(self.do_import_privkey)
+        export_keys = keys_menu.addAction(_("&Export"))
+        export_keys.triggered.connect(self.do_export_privkeys)
 
-        raw_transaction_file = raw_transaction_menu.addAction(_("&From file"))
-        raw_transaction_file.triggered.connect(self.do_process_from_file)
+        ex_history = wallet_menu.addAction(_("&Export History"))
+        ex_history.triggered.connect(self.do_export_history)
 
-        raw_transaction_text = raw_transaction_menu.addAction(_("&From text"))
-        raw_transaction_text.triggered.connect(self.do_process_from_text)
 
 
         tools_menu = menubar.addMenu(_("&Tools"))
@@ -366,25 +409,29 @@ class ElectrumWindow(QMainWindow):
         preferences_menu = tools_menu.addAction(preferences_name)
         preferences_menu.triggered.connect(self.settings_dialog)
 
+        network = tools_menu.addAction(_("&Network"))
+        network.triggered.connect(self.run_network_dialog)
+
         plugins_labels = tools_menu.addAction(_("&Plugins"))
         plugins_labels.triggered.connect(self.plugins_dialog)
 
-        wallet_menu.addSeparator()
+        tools_menu.addSeparator()
 
-        labels_menu = tools_menu.addMenu(_("&Labels"))
-        import_labels = labels_menu.addAction(_("&Import"))
-        import_labels.triggered.connect(self.do_import_labels)
-        export_labels = labels_menu.addAction(_("&Export"))
-        export_labels.triggered.connect(self.do_export_labels)
+        csv_transaction_menu = tools_menu.addMenu(_("&Create transaction"))
 
-        keys_menu = tools_menu.addMenu(_("&Private keys"))
-        import_keys = keys_menu.addAction(_("&Import"))
-        import_keys.triggered.connect(self.do_import_privkey)
-        export_keys = keys_menu.addAction(_("&Export"))
-        export_keys.triggered.connect(self.do_export_privkeys)
+        csv_transaction_file = csv_transaction_menu.addAction(_("&From CSV file"))
+        csv_transaction_file.triggered.connect(self.do_process_from_csv_file)
 
-        ex_history = tools_menu.addAction(_("&Export History"))
-        ex_history.triggered.connect(self.do_export_history)
+        csv_transaction_text = csv_transaction_menu.addAction(_("&From CSV text"))
+        csv_transaction_text.triggered.connect(self.do_process_from_csv_text)
+
+        raw_transaction_menu = tools_menu.addMenu(_("&Load transaction"))
+
+        raw_transaction_file = raw_transaction_menu.addAction(_("&From file"))
+        raw_transaction_file.triggered.connect(self.do_process_from_file)
+
+        raw_transaction_text = raw_transaction_menu.addAction(_("&From text"))
+        raw_transaction_text.triggered.connect(self.do_process_from_text)
 
 
         help_menu = menubar.addMenu(_("&Help"))
@@ -411,6 +458,9 @@ class ElectrumWindow(QMainWindow):
 
 
     def notify_transactions(self):
+        if not self.network or not self.network.is_connected(): 
+            return
+
         print_error("Notifying GUI")
         if len(self.network.interface.pending_transactions_for_notifications) > 0:
             # Combine the transactions if there are more then three
@@ -439,22 +489,6 @@ class ElectrumWindow(QMainWindow):
 
 
 
-    def set_label(self, name, text = None):
-        changed = False
-        old_text = self.wallet.labels.get(name)
-        if text:
-            if old_text != text:
-                self.wallet.labels[name] = text
-                self.wallet.storage.put('labels', self.wallet.labels)
-                changed = True
-        else:
-            if old_text:
-                self.wallet.labels.pop(name)
-                changed = True
-        run_hook('set_label', name, text, changed)
-        return changed
-
-
     # custom wrappers for getOpenFileName and getSaveFileName, that remember the path selected by the user
     def getOpenFileName(self, title, filter = ""):
         directory = self.config.get('io_dir', os.path.expanduser('~'))
@@ -497,38 +531,48 @@ class ElectrumWindow(QMainWindow):
         assert self.decimal_point in [5,8]
         return "BTC" if self.decimal_point == 8 else "mBTC"
 
-    def set_status_text(self, text):
-        self.balance_label.setText(text)
-        run_hook('set_status_text', text)
-
 
     def update_status(self):
-        if self.network.interface and self.network.interface.is_connected:
+        if self.network is None:
+            text = _("Offline")
+            icon = QIcon(":icons/status_disconnected.png")
+
+        elif self.network.is_connected():
             if not self.wallet.up_to_date:
                 text = _("Synchronizing...")
                 icon = QIcon(":icons/status_waiting.png")
+            elif self.network.server_lag > 1:
+                text = _("Server is lagging (%d blocks)"%self.network.server_lag)
+                icon = QIcon(":icons/status_lagging.png")
             else:
                 c, u = self.wallet.get_account_balance(self.current_account)
                 text =  _( "Balance" ) + ": %s "%( self.format_amount(c) ) + self.base_unit()
                 if u: text +=  " [%s unconfirmed]"%( self.format_amount(u,True).strip() )
+
+                r = {}
+                run_hook('set_quote_text', c+u, r)
+                quote = r.get(0)
+                if quote:
+                    text += "  (%s)"%quote
+
                 self.tray.setToolTip(text)
                 icon = QIcon(":icons/status_connected.png")
         else:
             text = _("Not connected")
             icon = QIcon(":icons/status_disconnected.png")
 
-        self.set_status_text(text)
+        self.balance_label.setText(text)
         self.status_button.setIcon( icon )
 
+
     def update_wallet(self):
         self.update_status()
-        if self.wallet.up_to_date or not self.network.interface.is_connected:
+        if self.wallet.up_to_date or not self.network or not self.network.is_connected():
             self.update_history_tab()
             self.update_receive_tab()
             self.update_contacts_tab()
             self.update_completions()
 
-
         
     def create_history_tab(self):
         self.history_list = l = MyTreeWidget(self)
@@ -576,7 +620,7 @@ class ElectrumWindow(QMainWindow):
         tx_hash = str(item.data(0, Qt.UserRole).toString())
         tx = self.wallet.transactions.get(tx_hash)
         text = unicode( item.text(2) )
-        self.set_label(tx_hash, text) 
+        self.wallet.set_label(tx_hash, text) 
         if text: 
             item.setForeground(2, QBrush(QColor('black')))
         else:
@@ -615,7 +659,7 @@ class ElectrumWindow(QMainWindow):
             if not is_editable:
                 return
 
-            changed = self.set_label(addr, text)
+            changed = self.wallet.set_label(addr, text)
             if changed:
                 self.update_history_tab()
                 self.update_completions()
@@ -635,11 +679,12 @@ class ElectrumWindow(QMainWindow):
         self.history_list.clear()
         for item in self.wallet.get_tx_history(self.current_account):
             tx_hash, conf, is_mine, value, fee, balance, timestamp = item
+            time_str = _("unknown")
             if conf > 0:
                 try:
                     time_str = datetime.datetime.fromtimestamp( timestamp).isoformat(' ')[:-3]
-                except:
-                    time_str = _("unknown")
+                except Exception:
+                    time_str = _("error")
 
             if conf == -1:
                 time_str = 'unverified'
@@ -751,9 +796,9 @@ class ElectrumWindow(QMainWindow):
             if self.amount_e.is_shortcut:
                 self.amount_e.is_shortcut = False
                 c, u = self.wallet.get_account_balance(self.current_account)
-                inputs, total, fee = self.wallet.choose_tx_inputs( c + u, 0, self.current_account)
+                inputs, total, fee = self.wallet.choose_tx_inputs_from_account( c + u, 0, self.current_account)
                 fee = self.wallet.estimated_fee(inputs)
-                amount = c + u - fee
+                amount = total - fee
                 self.amount_e.setText( self.format_amount(amount) )
                 self.fee_e.setText( self.format_amount( fee ) )
                 return
@@ -764,7 +809,7 @@ class ElectrumWindow(QMainWindow):
             if not is_fee: fee = None
             if amount is None:
                 return
-            inputs, total, fee = self.wallet.choose_tx_inputs( amount, fee, self.current_account )
+            inputs, total, fee = self.wallet.choose_tx_inputs_from_account( amount, fee, self.current_account )
             if not is_fee:
                 self.fee_e.setText( self.format_amount( fee ) )
             if inputs:
@@ -820,12 +865,12 @@ class ElectrumWindow(QMainWindow):
 
         try:
             amount = self.read_amount(unicode( self.amount_e.text()))
-        except:
+        except Exception:
             QMessageBox.warning(self, _('Error'), _('Invalid Amount'), _('OK'))
             return
         try:
             fee = self.read_amount(unicode( self.fee_e.text()))
-        except:
+        except Exception:
             QMessageBox.warning(self, _('Error'), _('Invalid Fee'), _('OK'))
             return
 
@@ -842,7 +887,7 @@ class ElectrumWindow(QMainWindow):
 
         try:
             tx = self.wallet.mktx_from_account( [(to_address, amount)], password, fee, self.current_account)
-        except BaseException, e:
+        except Exception as e:
             traceback.print_exc(file=sys.stdout)
             self.show_message(str(e))
             return
@@ -851,10 +896,8 @@ class ElectrumWindow(QMainWindow):
             QMessageBox.warning(self, _('Error'), _("This transaction requires a higher fee, or it will not be propagated by the network."), _('OK'))
             return
 
-        run_hook('send_tx', tx)
-
         if label: 
-            self.set_label(tx.hash(), label)
+            self.wallet.set_label(tx.hash(), label)
 
         if tx.is_complete:
             h = self.wallet.send_tx(tx)
@@ -867,14 +910,8 @@ class ElectrumWindow(QMainWindow):
             else:
                 QMessageBox.warning(self, _('Error'), msg, _('OK'))
         else:
-            filename = label + '.txn' if label else 'unsigned_%s.txn' % (time.mktime(time.gmtime()))
-            try:
-                fileName = self.getSaveFileName(_("Select a transaction filename"), filename, "*.txn")
-                with open(fileName,'w') as f:
-                    f.write(json.dumps(tx.as_dict(),indent=4) + '\n')
-                QMessageBox.information(self, _('Unsigned transaction created'), _("Unsigned transaction was saved to file:") + " " +fileName, _('OK'))
-            except:
-                QMessageBox.warning(self, _('Error'), _('Could not write transaction to file'), _('OK'))
+
+            self.show_transaction(tx)
 
         # add recipient to addressbook
         if to_address not in self.wallet.addressbook and not self.wallet.is_mine(to_address):
@@ -885,13 +922,17 @@ class ElectrumWindow(QMainWindow):
 
     def set_url(self, url):
         address, amount, label, message, signature, identity, url = util.parse_url(url)
-        if self.base_unit() == 'mBTC': amount = str( 1000* Decimal(amount))
+
+        if amount and self.base_unit() == 'mBTC': amount = str( 1000* Decimal(amount))
+
+        if self.mini:
+            self.mini.set_payment_fields(address, amount)
 
         if label and self.wallet.labels.get(address) != label:
             if self.question('Give label "%s" to address %s ?'%(label,address)):
                 if address not in self.wallet.addressbook and not self.wallet.is_mine(address):
                     self.wallet.addressbook.append(address)
-                self.set_label(address, label)
+                self.wallet.set_label(address, label)
 
         run_hook('set_url', url, self.show_message, self.question)
 
@@ -901,7 +942,9 @@ class ElectrumWindow(QMainWindow):
         self.payto_e.setText(m_addr)
 
         self.message_e.setText(message)
-        self.amount_e.setText(amount)
+        if amount:
+            self.amount_e.setText(amount)
+
         if identity:
             self.set_frozen(self.payto_e,True)
             self.set_frozen(self.amount_e,True)
@@ -986,21 +1029,12 @@ class ElectrumWindow(QMainWindow):
         return w
 
 
-    def receive_tab_set_mode(self, i):
-        self.save_column_widths()
-        self.expert_mode = (i == 1)
-        self.config.set_key('classic_expert_mode', self.expert_mode, True)
-        self.update_receive_tab()
 
 
     def save_column_widths(self):
-        if not self.expert_mode:
-            widths = [ self.receive_list.columnWidth(0) ]
-        else:
-            widths = []
-            for i in range(self.receive_list.columnCount() -1):
-                widths.append(self.receive_list.columnWidth(i))
-        self.column_widths["receive"][self.expert_mode] = widths
+        self.column_widths["receive"] = []
+        for i in range(self.receive_list.columnCount() -1):
+            self.column_widths["receive"].append(self.receive_list.columnWidth(i))
         
         self.column_widths["history"] = []
         for i in range(self.history_list.columnCount() - 1):
@@ -1010,7 +1044,7 @@ class ElectrumWindow(QMainWindow):
         for i in range(self.contacts_list.columnCount() - 1):
             self.column_widths["contacts"].append(self.contacts_list.columnWidth(i))
 
-        self.config.set_key("column_widths", self.column_widths, True)
+        self.config.set_key("column_widths_2", self.column_widths, True)
 
 
     def create_contacts_tab(self):
@@ -1034,6 +1068,32 @@ class ElectrumWindow(QMainWindow):
             self.update_receive_tab()
             self.update_history_tab()
 
+    def edit_account_label(self, k):
+        text, ok = QInputDialog.getText(self, _('Rename account'), _('Name') + ':', text = self.wallet.labels.get(k,''))
+        if ok:
+            label = unicode(text)
+            self.wallet.set_label(k,label)
+            self.update_receive_tab()
+
+    def account_set_expanded(self, item, k, b):
+        item.setExpanded(b)
+        self.accounts_expanded[k] = b
+
+    def create_account_menu(self, position, k, item):
+        menu = QMenu()
+        if item.isExpanded():
+            menu.addAction(_("Minimize"), lambda: self.account_set_expanded(item, k, False))
+        else:
+            menu.addAction(_("Maximize"), lambda: self.account_set_expanded(item, k, True))
+        menu.addAction(_("Rename"), lambda: self.edit_account_label(k))
+        menu.addAction(_("View details"), lambda: self.show_account_details(k))
+        if self.wallet.account_is_pending(k):
+            menu.addAction(_("Delete"), lambda: self.delete_pending_account(k))
+        menu.exec_(self.receive_list.viewport().mapToGlobal(position))
+
+    def delete_pending_account(self, k):
+        self.wallet.delete_pending_account(k)
+        self.update_receive_tab()
 
     def create_receive_menu(self, position):
         # fixme: this function apparently has a side effect.
@@ -1042,24 +1102,30 @@ class ElectrumWindow(QMainWindow):
 
         item = self.receive_list.itemAt(position)
         if not item: return
+
         addr = unicode(item.text(0))
         if not is_valid(addr): 
-            item.setExpanded(not item.isExpanded())
+            k = str(item.data(0,32).toString())
+            if k:
+                self.create_account_menu(position, k, item)
+            else:
+                item.setExpanded(not item.isExpanded())
             return 
+
         menu = QMenu()
         menu.addAction(_("Copy to clipboard"), lambda: self.app.clipboard().setText(addr))
         menu.addAction(_("QR code"), lambda: self.show_qrcode("bitcoin:" + addr, _("Address")) )
         menu.addAction(_("Edit label"), lambda: self.edit_label(True))
-        menu.addAction(_("Private key"), lambda: self.show_private_key(addr))
-        menu.addAction(_("Sign message"), lambda: self.sign_message(addr))
+        if self.wallet.seed:
+            menu.addAction(_("Private key"), lambda: self.show_private_key(addr))
+            menu.addAction(_("Sign message"), lambda: self.sign_message(addr))
         if addr in self.wallet.imported_keys:
             menu.addAction(_("Remove from wallet"), lambda: self.delete_imported_key(addr))
 
-        if self.expert_mode:
-            t = _("Unfreeze") if addr in self.wallet.frozen_addresses else _("Freeze")
-            menu.addAction(t, lambda: self.toggle_freeze(addr))
-            t = _("Unprioritize") if addr in self.wallet.prioritized_addresses else _("Prioritize")
-            menu.addAction(t, lambda: self.toggle_priority(addr))
+        t = _("Unfreeze") if addr in self.wallet.frozen_addresses else _("Freeze")
+        menu.addAction(t, lambda: self.toggle_freeze(addr))
+        t = _("Unprioritize") if addr in self.wallet.prioritized_addresses else _("Prioritize")
+        menu.addAction(t, lambda: self.toggle_priority(addr))
             
         run_hook('receive_menu', menu)
         menu.exec_(self.receive_list.viewport().mapToGlobal(position))
@@ -1077,7 +1143,7 @@ class ElectrumWindow(QMainWindow):
     def delete_contact(self, x):
         if self.question(_("Do you want to remove")+" %s "%x +_("from your list of contacts?")):
             self.wallet.delete_contact(x)
-            self.set_label(x, None)
+            self.wallet.set_label(x, None)
             self.update_history_tab()
             self.update_contacts_tab()
             self.update_completions()
@@ -1110,25 +1176,26 @@ class ElectrumWindow(QMainWindow):
         item.setData(0,32, True) # is editable
 
         run_hook('update_receive_item', address, item)
-                
+
+        if not self.wallet.is_mine(address): return
+
         c, u = self.wallet.get_addr_balance(address)
         balance = self.format_amount(c + u)
         item.setData(2,0,balance)
 
-        if self.expert_mode:
-            if address in self.wallet.frozen_addresses: 
-                item.setBackgroundColor(0, QColor('lightblue'))
-            elif address in self.wallet.prioritized_addresses: 
-                item.setBackgroundColor(0, QColor('lightgreen'))
+        if address in self.wallet.frozen_addresses: 
+            item.setBackgroundColor(0, QColor('lightblue'))
+        elif address in self.wallet.prioritized_addresses: 
+            item.setBackgroundColor(0, QColor('lightgreen'))
         
 
     def update_receive_tab(self):
         l = self.receive_list
         
         l.clear()
-        l.setColumnHidden(2, not self.expert_mode)
-        l.setColumnHidden(3, not self.expert_mode)
-        for i,width in enumerate(self.column_widths['receive'][self.expert_mode]):
+        l.setColumnHidden(2, False)
+        l.setColumnHidden(3, False)
+        for i,width in enumerate(self.column_widths['receive']):
             l.setColumnWidth(i, width)
 
         if self.current_account is None:
@@ -1143,16 +1210,19 @@ class ElectrumWindow(QMainWindow):
             c,u = self.wallet.get_account_balance(k)
             account_item = QTreeWidgetItem( [ name, '', self.format_amount(c+u), ''] )
             l.addTopLevelItem(account_item)
-            account_item.setExpanded(True)
+            account_item.setExpanded(self.accounts_expanded.get(k, True))
+            account_item.setData(0, 32, k)
+
+            if not self.wallet.is_seeded(k):
+                icon = QIcon(":icons/key.png")
+                account_item.setIcon(0, icon)
             
-            for is_change in ([0,1] if self.expert_mode else [0]):
-                if self.expert_mode:
-                    name = _("Receiving") if not is_change else _("Change")
-                    seq_item = QTreeWidgetItem( [ name, '', '', '', ''] )
-                    account_item.addChild(seq_item)
-                    if not is_change: seq_item.setExpanded(True)
-                else:
-                    seq_item = account_item
+            for is_change in ([0,1]):
+                name = _("Receiving") if not is_change else _("Change")
+                seq_item = QTreeWidgetItem( [ name, '', '', '', ''] )
+                account_item.addChild(seq_item)
+                if not is_change: seq_item.setExpanded(True)
+
                 is_red = False
                 gap = 0
 
@@ -1174,6 +1244,18 @@ class ElectrumWindow(QMainWindow):
                     seq_item.addChild(item)
 
 
+        for k, addr in self.wallet.get_pending_accounts():
+            name = self.wallet.labels.get(k,'')
+            account_item = QTreeWidgetItem( [ name + "  [ "+_('pending account')+" ]", '', '', ''] )
+            self.update_receive_item(item)
+            l.addTopLevelItem(account_item)
+            account_item.setExpanded(True)
+            account_item.setData(0, 32, k)
+            item = QTreeWidgetItem( [ addr, '', '', '', ''] )
+            account_item.addChild(item)
+            self.update_receive_item(item)
+
+
         if self.wallet.imported_keys and (self.current_account is None or self.current_account == -1):
             c,u = self.wallet.get_imported_balance()
             account_item = QTreeWidgetItem( [ _('Imported'), '', self.format_amount(c+u), ''] )
@@ -1228,7 +1310,7 @@ class ElectrumWindow(QMainWindow):
         def mkfunc(f, method):
             return lambda *args: apply( f, (method, args, self.password_dialog ))
         for m in dir(c):
-            if m[0]=='_' or m=='wallet' or m == 'interface': continue
+            if m[0]=='_' or m in ['network','wallet']: continue
             methods[m] = mkfunc(c._run, m)
             
         console.updateNamespace(methods)
@@ -1286,7 +1368,7 @@ class ElectrumWindow(QMainWindow):
 
 
     def update_buttons_on_seed(self):
-        if self.wallet.seed:
+        if not self.wallet.is_watching_only():
            self.seed_button.show()
            self.password_button.show()
            self.send_button.setText(_("Send"))
@@ -1304,16 +1386,40 @@ class ElectrumWindow(QMainWindow):
 
 
     def new_contact_dialog(self):
-        text, ok = QInputDialog.getText(self, _('New Contact'), _('Address') + ':')
-        address = unicode(text)
-        if ok:
-            if is_valid(address):
-                self.wallet.add_contact(address)
-                self.update_contacts_tab()
-                self.update_history_tab()
-                self.update_completions()
-            else:
-                QMessageBox.warning(self, _('Error'), _('Invalid Address'), _('OK'))
+
+        d = QDialog(self)
+        vbox = QVBoxLayout(d)
+        vbox.addWidget(QLabel(_('New Contact')+':'))
+        
+        grid = QGridLayout()
+        line1 = QLineEdit()
+        line2 = QLineEdit()
+        grid.addWidget(QLabel(_("Address")), 1, 0)
+        grid.addWidget(line1, 1, 1)
+        grid.addWidget(QLabel(_("Name")), 2, 0)
+        grid.addWidget(line2, 2, 1)
+
+        vbox.addLayout(grid)
+        vbox.addLayout(ok_cancel_buttons(d))
+    
+        if not d.exec_():
+            return
+        
+        address = str(line1.text())
+        label = unicode(line2.text())
+        
+        if not is_valid(address):
+            QMessageBox.warning(self, _('Error'), _('Invalid Address'), _('OK'))
+            return
+        
+        self.wallet.add_contact(address)
+        if label:
+            self.wallet.set_label(address, label)
+
+        self.update_contacts_tab()
+        self.update_history_tab()
+        self.update_completions()
+        self.tabs.setCurrentIndex(3)
 
 
     def new_account_dialog(self):
@@ -1322,26 +1428,31 @@ class ElectrumWindow(QMainWindow):
         dialog.setModal(1)
         dialog.setWindowTitle(_("New Account"))
 
-        addr = self.wallet.new_account_address()
         vbox = QVBoxLayout()
-        msg = _("Electrum considers that an account exists only if it contains bitcoins.") + '\n' \
-              + _("To create a new account, please send coins to the first address of that account.") + '\n' \
-              + _("Note: you will need to wait for 2 confirmations before the account is created.")
-        vbox.addWidget(QLabel(msg))
-        vbox.addWidget(QLabel(_('Address')+':'))
-        e = QLineEdit(addr)
-        e.setReadOnly(True)
+        vbox.addWidget(QLabel(_('Account name')+':'))
+        e = QLineEdit()
         vbox.addWidget(e)
+        msg = _("Note: Newly created accounts are 'pending' until they receive bitcoins.") + " " \
+            + _("You will need to wait for 2 confirmations until the correct balance is displayed and more addresses are created for that account.")
+        l = QLabel(msg)
+        l.setWordWrap(True)
+        vbox.addWidget(l)
 
         vbox.addLayout(ok_cancel_buttons(dialog))
         dialog.setLayout(vbox)
         r = dialog.exec_()
-        if r:
-            self.payto(addr)
+        if not r: return
+
+        name = str(e.text())
+        if not name: return
 
+        self.wallet.create_pending_account('1', name)
+        self.update_receive_tab()
+        self.tabs.setCurrentIndex(2)
+        
             
 
-    def show_master_public_key(self):
+    def show_master_public_key_old(self):
         dialog = QDialog(self)
         dialog.setModal(1)
         dialog.setWindowTitle(_("Master Public Key"))
@@ -1364,10 +1475,63 @@ class ElectrumWindow(QMainWindow):
 
         vbox = QVBoxLayout()
         vbox.addLayout(main_layout)
-        hbox = QHBoxLayout()
-        hbox.addStretch(1)
-        hbox.addWidget(ok_button)
-        vbox.addLayout(hbox)
+        vbox.addLayout(close_button(dialog))
+        dialog.setLayout(vbox)
+        dialog.exec_()
+        
+
+    def show_master_public_key(self):
+
+        if self.wallet.seed_version == 4:
+            self.show_master_public_key_old()
+            return
+
+        dialog = QDialog(self)
+        dialog.setModal(1)
+        dialog.setWindowTitle(_("Master Public Keys"))
+
+        chain_text = QTextEdit()
+        chain_text.setReadOnly(True)
+        chain_text.setMaximumHeight(170)
+        chain_qrw = QRCodeWidget()
+
+        mpk_text = QTextEdit()
+        mpk_text.setReadOnly(True)
+        mpk_text.setMaximumHeight(170)
+        mpk_qrw = QRCodeWidget()
+
+        main_layout = QGridLayout()
+
+        main_layout.addWidget(QLabel(_('Key')), 1, 0)
+        main_layout.addWidget(mpk_text, 1, 1)
+        main_layout.addWidget(mpk_qrw, 1, 2)
+
+        main_layout.addWidget(QLabel(_('Chain')), 2, 0)
+        main_layout.addWidget(chain_text, 2, 1)
+        main_layout.addWidget(chain_qrw, 2, 2)
+
+        def update(key):
+            c, K, cK = self.wallet.master_public_keys[str(key)]
+            chain_text.setText(c)
+            chain_qrw.set_addr(c)
+            chain_qrw.update_qr()
+            mpk_text.setText(K)
+            mpk_qrw.set_addr(K)
+            mpk_qrw.update_qr()
+            
+        key_selector = QComboBox()
+        keys = sorted(self.wallet.master_public_keys.keys())
+        key_selector.addItems(keys)
+
+        main_layout.addWidget(QLabel(_('Derivation:')), 0, 0)
+        main_layout.addWidget(key_selector, 0, 1)
+        dialog.connect(key_selector,SIGNAL("activated(QString)"),update) 
+
+        update(keys[0])
+
+        vbox = QVBoxLayout()
+        vbox.addLayout(main_layout)
+        vbox.addLayout(close_button(dialog))
 
         dialog.setLayout(vbox)
         dialog.exec_()
@@ -1375,18 +1539,29 @@ class ElectrumWindow(QMainWindow):
 
     @protected
     def show_seed_dialog(self, password):
-        if not self.wallet.seed:
-            QMessageBox.information(parent, _('Message'), _('No seed'), _('OK'))
-            return
-        try:
-            seed = self.wallet.decode_seed(password)
-        except:
-            QMessageBox.warning(self, _('Error'), _('Incorrect Password'), _('OK'))
+        if self.wallet.is_watching_only():
+            QMessageBox.information(self, _('Message'), _('This is a watching-only wallet'), _('OK'))
             return
 
-        from seed_dialog import SeedDialog
-        d = SeedDialog(self)
-        d.show_seed(seed, self.wallet.imported_keys)
+        if self.wallet.seed:
+            try:
+                mnemonic = self.wallet.get_mnemonic(password)
+            except Exception:
+                QMessageBox.warning(self, _('Error'), _('Incorrect Password'), _('OK'))
+                return
+            from seed_dialog import SeedDialog
+            d = SeedDialog(self, mnemonic, self.wallet.imported_keys)
+            d.exec_()
+        else:
+            l = {}
+            for k in self.wallet.master_private_keys.keys():
+                pk = self.wallet.get_master_private_key(k, password)
+                l[k] = pk
+            from seed_dialog import PrivateKeysDialog
+            d = PrivateKeysDialog(self,l)
+            d.exec_()
+
+
 
 
 
@@ -1403,11 +1578,21 @@ class ElectrumWindow(QMainWindow):
         hbox = QHBoxLayout()
         hbox.addStretch(1)
 
-        def print_qr(self):
-            filename = "qrcode.bmp"
+        filename = os.path.join(self.config.path, "qrcode.bmp")
+
+        def print_qr():
             bmp.save_qrcode(qrw.qr, filename)
             QMessageBox.information(None, _('Message'), _("QR code saved to file") + " " + filename, _('OK'))
 
+        def copy_to_clipboard():
+            bmp.save_qrcode(qrw.qr, filename)
+            self.app.clipboard().setImage(QImage(filename))
+            QMessageBox.information(None, _('Message'), _("QR code saved to clipboard"), _('OK'))
+
+        b = QPushButton(_("Copy"))
+        hbox.addWidget(b)
+        b.clicked.connect(copy_to_clipboard)
+
         b = QPushButton(_("Save"))
         hbox.addWidget(b)
         b.clicked.connect(print_qr)
@@ -1442,7 +1627,7 @@ class ElectrumWindow(QMainWindow):
         if not address: return
         try:
             pk_list = self.wallet.get_private_key(address, password)
-        except BaseException, e:
+        except Exception as e:
             self.show_message(str(e))
             return
         QMessageBox.information(self, _('Private key'), _('Address')+ ': ' + address + '\n\n' + _('Private key') + ': ' + '\n'.join(pk_list), _('OK'))
@@ -1455,7 +1640,7 @@ class ElectrumWindow(QMainWindow):
         try:
             sig = self.wallet.sign_message(str(address.text()), message, password)
             signature.setText(sig)
-        except BaseException, e:
+        except Exception as e:
             self.show_message(str(e))
 
     def sign_message(self, address):
@@ -1517,7 +1702,7 @@ class ElectrumWindow(QMainWindow):
         def do_verify():
             message = unicode(verify_message.toPlainText())
             message = message.encode('utf-8')
-            if self.wallet.verify_message(verify_address.text(), str(verify_signature.toPlainText()), message):
+            if bitcoin.verify_message(verify_address.text(), str(verify_signature.toPlainText()), message):
                 self.show_message(_("Signature verified"))
             else:
                 self.show_message(_("Error: wrong signature"))
@@ -1583,18 +1768,20 @@ class ElectrumWindow(QMainWindow):
             txt.decode('hex')
             tx = Transaction(txt)
             return tx
-        except:
+        except Exception:
             pass
 
         try:
             tx_dict = json.loads(str(txt))
             assert "hex" in tx_dict.keys()
             assert "complete" in tx_dict.keys()
+            tx = Transaction(tx_dict["hex"], tx_dict["complete"])
             if not tx_dict["complete"]:
                 assert "input_info" in tx_dict.keys()
-            tx = Transaction(tx_dict["hex"])
+                input_info = json.loads(tx_dict['input_info'])
+                tx.add_input_info(input_info)
             return tx
-        except:
+        except Exception:
             pass
         
         QMessageBox.critical(None, _("Unable to parse transaction"), _("Electrum was unable to parse your transaction"))
@@ -1645,7 +1832,7 @@ class ElectrumWindow(QMainWindow):
 
         try:
             tx = self.wallet.make_unsigned_transaction(outputs, None, None)
-        except BaseException, e:
+        except Exception as e:
             self.show_message(str(e))
             return
 
@@ -1664,7 +1851,8 @@ class ElectrumWindow(QMainWindow):
             return
 
     def do_process_from_csv_text(self):
-        text = text_dialog(self, _('Input CSV'), _("CSV:"), _("Load CSV"))
+        text = text_dialog(self, _('Input CSV'), _("Please enter a list of outputs.") + '\n' \
+                               + _("Format: address, amount. One output per line"), _("Load CSV"))
         if not text:
             return
         f = StringIO.StringIO(text)
@@ -1697,7 +1885,7 @@ class ElectrumWindow(QMainWindow):
             export_error_label = _("Electrum was unable to produce a private key-export.")
             QMessageBox.critical(None, _("Unable to create csv"), export_error_label + "\n" + str(reason))
 
-        except BaseException, e:
+        except Exception as e:
           self.show_message(str(e))
           return
 
@@ -1750,7 +1938,7 @@ class ElectrumWindow(QMainWindow):
         for key in text:
             try:
                 addr = self.wallet.import_key(key, password)
-            except BaseException as e:
+            except Exception as e:
                 badkeys.append(key)
                 continue
             if not addr: 
@@ -1770,89 +1958,66 @@ class ElectrumWindow(QMainWindow):
         d.setWindowTitle(_('Electrum Settings'))
         d.setModal(1)
         vbox = QVBoxLayout()
+        grid = QGridLayout()
+        grid.setColumnStretch(0,1)
 
-        tabs = QTabWidget(self)
-        self.settings_tab = tabs
-        vbox.addWidget(tabs)
-
-        tab1 = QWidget()
-        grid_ui = QGridLayout(tab1)
-        grid_ui.setColumnStretch(0,1)
-        tabs.addTab(tab1, _('Display') )
-
-        nz_label = QLabel(_('Display zeros'))
-        grid_ui.addWidget(nz_label, 0, 0)
+        nz_label = QLabel(_('Display zeros') + ':')
+        grid.addWidget(nz_label, 0, 0)
         nz_e = AmountEdit(None,True)
         nz_e.setText("%d"% self.num_zeros)
-        grid_ui.addWidget(nz_e, 0, 1)
+        grid.addWidget(nz_e, 0, 1)
         msg = _('Number of zeros displayed after the decimal point. For example, if this is set to 2, "1." will be displayed as "1.00"')
-        grid_ui.addWidget(HelpButton(msg), 0, 2)
+        grid.addWidget(HelpButton(msg), 0, 2)
         if not self.config.is_modifiable('num_zeros'):
             for w in [nz_e, nz_label]: w.setEnabled(False)
         
         lang_label=QLabel(_('Language') + ':')
-        grid_ui.addWidget(lang_label, 1, 0)
+        grid.addWidget(lang_label, 1, 0)
         lang_combo = QComboBox()
         from electrum.i18n import languages
         lang_combo.addItems(languages.values())
         try:
             index = languages.keys().index(self.config.get("language",''))
-        except:
+        except Exception:
             index = 0
         lang_combo.setCurrentIndex(index)
-        grid_ui.addWidget(lang_combo, 1, 1)
-        grid_ui.addWidget(HelpButton(_('Select which language is used in the GUI (after restart).')+' '), 1, 2)
+        grid.addWidget(lang_combo, 1, 1)
+        grid.addWidget(HelpButton(_('Select which language is used in the GUI (after restart).')+' '), 1, 2)
         if not self.config.is_modifiable('language'):
             for w in [lang_combo, lang_label]: w.setEnabled(False)
 
-        expert_cb = QCheckBox(_('Expert mode'))
-        expert_cb.setChecked(self.expert_mode)
-        grid_ui.addWidget(expert_cb, 3, 0)
-        hh =  _('In expert mode, your client will:') + '\n'  \
-            + _(' - Show change addresses in the Receive tab') + '\n'  \
-            + _(' - Display the balance of each address') + '\n'  \
-            + _(' - Add freeze/prioritize actions to addresses.') 
-        grid_ui.addWidget(HelpButton(hh), 3, 2)
-        grid_ui.setRowStretch(4,1)
-
-        # wallet tab
-        tab2 = QWidget()
-        grid_wallet = QGridLayout(tab2)
-        grid_wallet.setColumnStretch(0,1)
-        tabs.addTab(tab2, _('Wallet') )
         
-        fee_label = QLabel(_('Transaction fee'))
-        grid_wallet.addWidget(fee_label, 0, 0)
+        fee_label = QLabel(_('Transaction fee') + ':')
+        grid.addWidget(fee_label, 2, 0)
         fee_e = AmountEdit(self.base_unit)
         fee_e.setText(self.format_amount(self.wallet.fee).strip())
-        grid_wallet.addWidget(fee_e, 0, 2)
+        grid.addWidget(fee_e, 2, 1)
         msg = _('Fee per kilobyte of transaction.') + ' ' \
             + _('Recommended value') + ': ' + self.format_amount(50000)
-        grid_wallet.addWidget(HelpButton(msg), 0, 3)
+        grid.addWidget(HelpButton(msg), 2, 2)
         if not self.config.is_modifiable('fee_per_kb'):
             for w in [fee_e, fee_label]: w.setEnabled(False)
 
-        usechange_cb = QCheckBox(_('Use change addresses'))
-        usechange_cb.setChecked(self.wallet.use_change)
-        grid_wallet.addWidget(usechange_cb, 1, 0)
-        grid_wallet.addWidget(HelpButton(_('Using change addresses makes it more difficult for other people to track your transactions.')+' '), 1, 3)
-        if not self.config.is_modifiable('use_change'): usechange_cb.setEnabled(False)
-
         units = ['BTC', 'mBTC']
-        unit_label = QLabel(_('Base unit'))
-        grid_wallet.addWidget(unit_label, 3, 0)
+        unit_label = QLabel(_('Base unit') + ':')
+        grid.addWidget(unit_label, 3, 0)
         unit_combo = QComboBox()
         unit_combo.addItems(units)
         unit_combo.setCurrentIndex(units.index(self.base_unit()))
-        grid_wallet.addWidget(unit_combo, 3, 2)
-        grid_wallet.addWidget(HelpButton(_('Base unit of your wallet.')\
+        grid.addWidget(unit_combo, 3, 1)
+        grid.addWidget(HelpButton(_('Base unit of your wallet.')\
                                              + '\n1BTC=1000mBTC.\n' \
-                                             + _(' This settings affects the fields in the Send tab')+' '), 3, 3)
-        grid_wallet.setRowStretch(4,1)
+                                             + _(' This settings affects the fields in the Send tab')+' '), 3, 2)
 
+        usechange_cb = QCheckBox(_('Use change addresses'))
+        usechange_cb.setChecked(self.wallet.use_change)
+        grid.addWidget(usechange_cb, 4, 0)
+        grid.addWidget(HelpButton(_('Using change addresses makes it more difficult for other people to track your transactions.')+' '), 4, 2)
+        if not self.config.is_modifiable('use_change'): usechange_cb.setEnabled(False)
 
-        run_hook('create_settings_tab', tabs)
+        grid.setRowStretch(5,1)
 
+        vbox.addLayout(grid)
         vbox.addLayout(ok_cancel_buttons(d))
         d.setLayout(vbox) 
 
@@ -1862,7 +2027,7 @@ class ElectrumWindow(QMainWindow):
         fee = unicode(fee_e.text())
         try:
             fee = self.read_amount(fee)
-        except:
+        except Exception:
             QMessageBox.warning(self, _('Error'), _('Invalid value') +': %s'%fee, _('OK'))
             return
 
@@ -1872,7 +2037,7 @@ class ElectrumWindow(QMainWindow):
         try:
             nz = int( nz )
             if nz>8: nz=8
-        except:
+        except Exception:
             QMessageBox.warning(self, _('Error'), _('Invalid value')+':%s'%nz, _('OK'))
             return
 
@@ -1885,7 +2050,7 @@ class ElectrumWindow(QMainWindow):
         usechange_result = usechange_cb.isChecked()
         if self.wallet.use_change != usechange_result:
             self.wallet.use_change = usechange_result
-            self.config.set_key('use_change', self.wallet.use_change, True)
+            self.wallet.storage.put('use_change', self.wallet.use_change)
         
         unit_result = units[unit_combo.currentIndex()]
         if self.base_unit() != unit_result:
@@ -1901,15 +2066,15 @@ class ElectrumWindow(QMainWindow):
             self.config.set_key("language", lang_request, True)
             need_restart = True
             
-
         run_hook('close_settings_dialog')
 
         if need_restart:
             QMessageBox.warning(self, _('Success'), _('Please restart Electrum to activate the new GUI settings'), _('OK'))
 
-        self.receive_tab_set_mode(expert_cb.isChecked())
 
     def run_network_dialog(self):
+        if not self.network:
+            return
         NetworkDialog(self.wallet.network, self.config, self).do_exec()
 
     def closeEvent(self, event):
@@ -1917,6 +2082,7 @@ class ElectrumWindow(QMainWindow):
         self.config.set_key("winpos-qt", [g.left(),g.top(),g.width(),g.height()], True)
         self.save_column_widths()
         self.config.set_key("console-history", self.console.history[-50:], True)
+        self.wallet.storage.put('accounts_expanded', self.accounts_expanded)
         event.accept()
 
 
@@ -1945,19 +2111,29 @@ class ElectrumWindow(QMainWindow):
         grid.setColumnStretch(0,1)
         w.setLayout(grid)
 
-        def mk_toggle(cb, p):
-            return lambda: cb.setChecked(p.toggle())
+        def do_toggle(cb, p, w):
+            r = p.toggle()
+            cb.setChecked(r)
+            if w: w.setEnabled(r)
+
+        def mk_toggle(cb, p, w):
+            return lambda: do_toggle(cb,p,w)
+
         for i, p in enumerate(plugins):
             try:
                 cb = QCheckBox(p.fullname())
                 cb.setDisabled(not p.is_available())
                 cb.setChecked(p.is_enabled())
-                cb.clicked.connect(mk_toggle(cb,p))
                 grid.addWidget(cb, i, 0)
                 if p.requires_settings():
-                    grid.addWidget(EnterButton(_('Settings'), p.settings_dialog), i, 1)
+                    w = p.settings_widget(self)
+                    w.setEnabled( p.is_enabled() )
+                    grid.addWidget(w, i, 1)
+                else: 
+                    w = None
+                cb.clicked.connect(mk_toggle(cb,p,w))
                 grid.addWidget(HelpButton(p.description()), i, 2)
-            except:
+            except Exception:
                 print_msg(_("Error: cannot display plugin"), p)
                 traceback.print_exc(file=sys.stdout)
         grid.setRowStretch(i+1,1)
@@ -1965,3 +2141,33 @@ class ElectrumWindow(QMainWindow):
         vbox.addLayout(close_button(d))
 
         d.exec_()
+
+
+    def show_account_details(self, k):
+        d = QDialog(self)
+        d.setWindowTitle(_('Account Details'))
+        d.setModal(1)
+
+        vbox = QVBoxLayout(d)
+        roots = self.wallet.get_roots(k)
+
+        name = self.wallet.get_account_name(k)
+        label = QLabel('Name: ' + name)
+        vbox.addWidget(label)
+
+        acctype = '2 of 2' if len(roots) == 2 else '2 of 3' if len(roots) == 3 else 'Single key'
+        vbox.addWidget(QLabel('Type: ' + acctype))
+
+        label = QLabel('Derivation: ' + k)
+        vbox.addWidget(label)
+
+        #for root in roots:
+        #    mpk = self.wallet.master_public_keys[root]
+        #    text = QTextEdit()
+        #    text.setReadOnly(True)
+        #    text.setMaximumHeight(120)
+        #    text.setText(repr(mpk))
+        #    vbox.addWidget(text)
+
+        vbox.addLayout(close_button(d))
+        d.exec_()