1.9.4
[electrum-nvc.git] / gui / qt / main_window.py
index 59e6496..640fb1a 100644 (file)
@@ -95,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):
@@ -127,6 +127,8 @@ 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):
         QMainWindow.__init__(self)
@@ -136,9 +138,13 @@ class ElectrumWindow(QMainWindow):
 
         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)
@@ -158,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') )
@@ -171,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)
@@ -186,19 +193,15 @@ class ElectrumWindow(QMainWindow):
         self.history_list.setFocus(True)
 
         # network callbacks
-        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)
-
-        # 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)
+        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()
@@ -224,6 +227,7 @@ class ElectrumWindow(QMainWindow):
                 self.config.set_key('lite_mode', False, True)
                 sys.exit(0)
             self.mini = None
+            self.show()
             return
 
         actuator = lite_window.MiniActuator(self)
@@ -252,10 +256,23 @@ class ElectrumWindow(QMainWindow):
         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()
+        if len(accounts) > 1:
+            self.account_selector.addItems([_("All accounts")] + accounts.values())
+            self.account_selector.setCurrentIndex(0)
+            self.account_selector.show()
+        else:
+            self.account_selector.hide()
+
 
     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'))
@@ -263,19 +280,8 @@ class ElectrumWindow(QMainWindow):
         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()
-
-        # account selector
-        accounts = self.wallet.get_account_names()
-        self.account_selector.clear()
-        if len(accounts) > 1:
-            self.account_selector.addItems([_("All accounts")] + accounts.values())
-            self.account_selector.setCurrentIndex(0)
-            self.account_selector.show()
-        else:
-            self.account_selector.hide()
-
+        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()
@@ -283,16 +289,9 @@ class ElectrumWindow(QMainWindow):
         run_hook('load_wallet', 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
-
-
     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
 
@@ -315,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)
@@ -333,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()
@@ -459,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
@@ -531,12 +533,16 @@ class ElectrumWindow(QMainWindow):
 
 
     def update_status(self):
-        if self.network.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.is_lagging:
-                text = _("Server is lagging")
+            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)
@@ -561,7 +567,7 @@ class ElectrumWindow(QMainWindow):
 
     def update_wallet(self):
         self.update_status()
-        if self.wallet.up_to_date or not self.network.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()
@@ -673,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'
@@ -789,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
@@ -802,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:
@@ -858,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
 
@@ -880,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
@@ -903,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):
@@ -1031,10 +1032,9 @@ class ElectrumWindow(QMainWindow):
 
 
     def save_column_widths(self):
-        widths = []
+        self.column_widths["receive"] = []
         for i in range(self.receive_list.columnCount() -1):
-            widths.append(self.receive_list.columnWidth(i))
-        self.column_widths["receive"][1] = widths
+            self.column_widths["receive"].append(self.receive_list.columnWidth(i))
         
         self.column_widths["history"] = []
         for i in range(self.history_list.columnCount() - 1):
@@ -1044,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):
@@ -1069,22 +1069,32 @@ class ElectrumWindow(QMainWindow):
             self.update_history_tab()
 
     def edit_account_label(self, k):
-        text, ok = QInputDialog.getText(self, _('Rename account'), _('Name') + ':')
+        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: item.setExpanded(False))
+            menu.addAction(_("Minimize"), lambda: self.account_set_expanded(item, k, False))
         else:
-            menu.addAction(_("Maximize"), lambda: item.setExpanded(True))
+            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.
         # if it is not called the menu pops up several times
@@ -1106,8 +1116,9 @@ class ElectrumWindow(QMainWindow):
         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))
 
@@ -1165,7 +1176,9 @@ 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)
@@ -1182,7 +1195,7 @@ class ElectrumWindow(QMainWindow):
         l.clear()
         l.setColumnHidden(2, False)
         l.setColumnHidden(3, False)
-        for i,width in enumerate(self.column_widths['receive'][1]):
+        for i,width in enumerate(self.column_widths['receive']):
             l.setColumnWidth(i, width)
 
         if self.current_account is None:
@@ -1197,7 +1210,7 @@ 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):
@@ -1231,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), ''] )
@@ -1285,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)
@@ -1361,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):
@@ -1379,23 +1428,28 @@ 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_old(self):
@@ -1419,6 +1473,8 @@ class ElectrumWindow(QMainWindow):
         main_layout.addWidget(main_text, 1, 0)
         main_layout.addWidget(qrw, 1, 1 )
 
+        vbox = QVBoxLayout()
+        vbox.addLayout(main_layout)
         vbox.addLayout(close_button(dialog))
         dialog.setLayout(vbox)
         dialog.exec_()
@@ -1427,7 +1483,7 @@ class ElectrumWindow(QMainWindow):
     def show_master_public_key(self):
 
         if self.wallet.seed_version == 4:
-            self.show_master_public_keys_old()
+            self.show_master_public_key_old()
             return
 
         dialog = QDialog(self)
@@ -1460,7 +1516,7 @@ class ElectrumWindow(QMainWindow):
             chain_qrw.set_addr(c)
             chain_qrw.update_qr()
             mpk_text.setText(K)
-            mpk_qrw.set_addr(c)
+            mpk_qrw.set_addr(K)
             mpk_qrw.update_qr()
             
         key_selector = QComboBox()
@@ -1489,12 +1545,12 @@ class ElectrumWindow(QMainWindow):
 
         if self.wallet.seed:
             try:
-                seed = self.wallet.decode_seed(password)
-            except:
+                mnemonic = self.wallet.get_mnemonic(password)
+            except Exception:
                 QMessageBox.warning(self, _('Error'), _('Incorrect Password'), _('OK'))
                 return
             from seed_dialog import SeedDialog
-            d = SeedDialog(self, seed, self.wallet.imported_keys)
+            d = SeedDialog(self, mnemonic, self.wallet.imported_keys)
             d.exec_()
         else:
             l = {}
@@ -1522,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)
@@ -1561,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'))
@@ -1574,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):
@@ -1636,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"))
@@ -1702,7 +1768,7 @@ class ElectrumWindow(QMainWindow):
             txt.decode('hex')
             tx = Transaction(txt)
             return tx
-        except:
+        except Exception:
             pass
 
         try:
@@ -1715,7 +1781,7 @@ class ElectrumWindow(QMainWindow):
                 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"))
@@ -1766,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
 
@@ -1819,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
 
@@ -1872,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: 
@@ -1912,7 +1978,7 @@ class ElectrumWindow(QMainWindow):
         lang_combo.addItems(languages.values())
         try:
             index = languages.keys().index(self.config.get("language",''))
-        except:
+        except Exception:
             index = 0
         lang_combo.setCurrentIndex(index)
         grid.addWidget(lang_combo, 1, 1)
@@ -1961,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
 
@@ -1971,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
 
@@ -1984,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:
@@ -2007,6 +2073,8 @@ class ElectrumWindow(QMainWindow):
 
 
     def run_network_dialog(self):
+        if not self.network:
+            return
         NetworkDialog(self.wallet.network, self.config, self).do_exec()
 
     def closeEvent(self, event):
@@ -2014,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()
 
 
@@ -2042,21 +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():
-                    b = EnterButton(_('Settings'), p.settings_dialog)
-                    b.setEnabled( p.is_enabled() )
-                    grid.addWidget(b, 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)