Work in progress on Label syncing
[electrum-nvc.git] / gui / gui_classic.py
index ff58063..133dd75 100644 (file)
@@ -41,6 +41,7 @@ except:
 from electrum.wallet import format_satoshis
 from electrum.bitcoin import Transaction, is_valid
 from electrum import mnemonic
+from electrum import util, bitcoin, commands
 
 import bmp, pyqrnative
 import exchange_rate
@@ -250,17 +251,18 @@ def waiting_dialog(f):
 def ok_cancel_buttons(dialog):
     hbox = QHBoxLayout()
     hbox.addStretch(1)
-    b = QPushButton("OK")
-    hbox.addWidget(b)
-    b.clicked.connect(dialog.accept)
     b = QPushButton("Cancel")
     hbox.addWidget(b)
     b.clicked.connect(dialog.reject)
+    b = QPushButton("OK")
+    hbox.addWidget(b)
+    b.clicked.connect(dialog.accept)
+    b.setDefault(True)
     return hbox
 
 
 default_column_widths = { "history":[40,140,350,140], "contacts":[350,330], 
-       "receive":[[370],[370,200,130,130],[370,200,130,130]] }
+       "receive":[[370],[370,200,130]] }
 
 class ElectrumWindow(QMainWindow):
 
@@ -269,13 +271,16 @@ class ElectrumWindow(QMainWindow):
         self.lite = None
         self.wallet = wallet
         self.config = config
-        self.wallet.interface.register_callback('updated', self.update_callback)
-        self.wallet.interface.register_callback('banner', lambda: self.emit(QtCore.SIGNAL('banner_signal')) )
-        self.wallet.interface.register_callback('disconnected', self.update_callback)
-        self.wallet.interface.register_callback('disconnecting', self.update_callback)
+        self.init_plugins()
+
+        self.create_status_bar()
+
+        self.wallet.interface.register_callback('updated', lambda: self.emit(QtCore.SIGNAL('update_wallet')))
+        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.expert_mode = config.get('classic_expert_mode', False)
-        self.merchant_name = config.get('merchant_name', 'Invoice')
 
         set_language(config.get('language'))
 
@@ -292,7 +297,6 @@ class ElectrumWindow(QMainWindow):
         tabs.setMinimumSize(600, 400)
         tabs.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
         self.setCentralWidget(tabs)
-        self.create_status_bar()
 
         g = self.config.get("winpos-qt",[100, 100, 840, 400])
         self.setGeometry(g[0], g[1], g[2], g[3])
@@ -305,7 +309,8 @@ class ElectrumWindow(QMainWindow):
         QShortcut(QKeySequence("Ctrl+PgUp"), self, lambda: tabs.setCurrentIndex( (tabs.currentIndex() - 1 )%tabs.count() ))
         QShortcut(QKeySequence("Ctrl+PgDown"), self, lambda: tabs.setCurrentIndex( (tabs.currentIndex() + 1 )%tabs.count() ))
         
-        self.connect(self, QtCore.SIGNAL('updatesignal'), self.update_wallet)
+        self.connect(self, QtCore.SIGNAL('update_wallet'), self.update_wallet)
+        self.connect(self, QtCore.SIGNAL('update_status'), self.update_status)
         self.connect(self, QtCore.SIGNAL('banner_signal'), lambda: self.console.showMessage(self.wallet.banner) )
         self.history_list.setFocus(True)
         
@@ -321,25 +326,53 @@ class ElectrumWindow(QMainWindow):
         # set initial message
         self.console.showMessage(self.wallet.banner)
 
-        #init plugins
-        for p in self.wallet.plugins:
+
+    # plugins
+    def init_plugins(self):
+        import imp, pkgutil
+        if os.path.exists("plugins"):
+            fp, pathname, description = imp.find_module('plugins')
+            imp.load_module('electrum_plugins', fp, pathname, description)
+            plugin_names = [name for a, name, b in pkgutil.iter_modules(['plugins'])]
+            self.plugins = map(lambda name: imp.load_source('electrum_plugins.'+name, os.path.join(pathname,name+'.py')), plugin_names)
+        else:
+            import electrum_plugins
+            plugin_names = [name for a, name, b in pkgutil.iter_modules(electrum_plugins.__path__)]
+            self.plugins = [ __import__('electrum_plugins.'+name, fromlist=['electrum_plugins']) for name in plugin_names]
+
+        self.plugin_hooks = {}
+        for p in self.plugins:
             try:
-                p.init_gui(self)
+                p.init(self)
             except:
                 print_msg("Error:cannot initialize plugin",p)
                 traceback.print_exc(file=sys.stdout)
 
+    def set_hook(self, name, callback):
+        h = self.plugin_hooks.get(name, [])
+        h.append(callback)
+        self.plugin_hooks[name] = h
+
+    def unset_hook(self, name, callback):
+        h = self.plugin_hooks.get(name,[])
+        if callback in h: h.remove(callback)
+        self.plugin_hooks[name] = h
+
+    def run_hook(self, name, args):
+        for cb in self.plugin_hooks.get(name,[]):
+            apply(cb, args)
+
 
     def close(self):
         QMainWindow.close(self)
-        self.wallet.run_hook('close_main_window', (self,))
+        self.run_hook('close_main_window', (self,))
 
     def connect_slots(self, sender):
         self.connect(sender, QtCore.SIGNAL('timersignal'), self.timer_actions)
         self.previous_payto_e=''
 
     def timer_actions(self):
-        self.wallet.run_hook('timer_actions', (self,))
+        self.run_hook('timer_actions', (self,))
             
         if self.payto_e.hasFocus():
             return
@@ -357,10 +390,8 @@ class ElectrumWindow(QMainWindow):
                     self.payto_e.setText(s)
 
 
-    def update_callback(self):
-        self.emit(QtCore.SIGNAL('updatesignal'))
 
-    def update_wallet(self):
+    def update_status(self):
         if self.wallet.interface and self.wallet.interface.is_connected:
             if not self.wallet.up_to_date:
                 text = _("Synchronizing...")
@@ -379,6 +410,8 @@ class ElectrumWindow(QMainWindow):
         self.statusBar().showMessage(text)
         self.status_button.setIcon( icon )
 
+    def update_wallet(self):
+        self.update_status()
         if self.wallet.up_to_date or not self.wallet.interface.is_connected:
             self.update_history_tab()
             self.update_receive_tab()
@@ -423,7 +456,7 @@ class ElectrumWindow(QMainWindow):
 
 
     def show_tx_details(self, tx):
-        dialog = QDialog(None)
+        dialog = QDialog(self)
         dialog.setModal(1)
         dialog.setWindowTitle(_("Transaction Details"))
         vbox = QVBoxLayout()
@@ -488,6 +521,9 @@ class ElectrumWindow(QMainWindow):
         text = unicode( item.text(2) )
         if text: 
             self.wallet.labels[tx_hash] = text
+            # Label changed
+            self.run_hook('label_changed',(self, str(tx_hash), text))
+
             item.setForeground(2, QBrush(QColor('black')))
         else:
             if s: self.wallet.labels.pop(tx_hash)
@@ -499,10 +535,9 @@ class ElectrumWindow(QMainWindow):
 
     def edit_label(self, is_recv):
         l = self.receive_list if is_recv else self.contacts_list
-        c = 2 if is_recv else 1
         item = l.currentItem()
         item.setFlags(Qt.ItemIsEditable|Qt.ItemIsSelectable | Qt.ItemIsUserCheckable | Qt.ItemIsEnabled | Qt.ItemIsDragEnabled)
-        l.editItem( item, c )
+        l.editItem( item, 1 )
         item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsUserCheckable | Qt.ItemIsEnabled | Qt.ItemIsDragEnabled)
 
 
@@ -531,6 +566,7 @@ class ElectrumWindow(QMainWindow):
                     if old_addr != addr:
                         self.wallet.labels[addr] = text
                         changed = True
+                        self.run_hook('label_changed',(self, addr, text))
                 else:
                     print_error("Error: This is one of your aliases")
                     label = self.wallet.labels.get(addr,'')
@@ -547,11 +583,11 @@ class ElectrumWindow(QMainWindow):
                 
             self.current_item_changed(item)
 
-        self.wallet.run_hook('item_changed',(self, item, column))
+        self.run_hook('item_changed',(self, item, column))
 
 
     def current_item_changed(self, a):
-        self.wallet.run_hook('current_item_changed',(self, a))
+        self.run_hook('current_item_changed',(self, a))
 
 
 
@@ -697,7 +733,7 @@ class ElectrumWindow(QMainWindow):
         self.amount_e.textChanged.connect(lambda: entry_changed(False) )
         self.fee_e.textChanged.connect(lambda: entry_changed(True) )
 
-        self.wallet.run_hook('create_send_tab',(self,grid))
+        self.run_hook('create_send_tab',(self,grid))
         return w2
 
 
@@ -711,8 +747,12 @@ class ElectrumWindow(QMainWindow):
         self.completions.setStringList(l)
 
 
+    def protected(func):
+        return lambda s, *args: s.do_protect(func, args)
+
 
-    def do_send(self):
+    @protected
+    def do_send(self, password):
 
         label = unicode( self.message_e.text() )
         r = unicode( self.payto_e.text() )
@@ -747,20 +787,13 @@ class ElectrumWindow(QMainWindow):
             QMessageBox.warning(self, _('Error'), _('Invalid Fee'), _('OK'))
             return
 
-        if self.wallet.use_encryption:
-            password = self.password_dialog()
-            if not password:
-                return
-        else:
-            password = None
-
         try:
             tx = self.wallet.mktx( [(to_address, amount)], password, fee)
         except BaseException, e:
             self.show_message(str(e))
             return
 
-        self.wallet.run_hook('send_tx', (wallet, self, tx))
+        self.run_hook('send_tx', (self.wallet, self, tx))
 
         if label: 
             self.wallet.labels[tx.hash()] = label
@@ -868,7 +901,7 @@ class ElectrumWindow(QMainWindow):
 
 
     def create_receive_tab(self):
-        l,w,hbox = self.create_list_tab([ _('Address'), _('Label'), _(''), _('Balance'), _('Tx')])
+        l,w,hbox = self.create_list_tab([ _('Address'), _('Label'), _('Balance'), _('Tx')])
         l.setContextMenuPolicy(Qt.CustomContextMenu)
         l.customContextMenuRequested.connect(self.create_receive_menu)
         self.connect(l, SIGNAL('itemDoubleClicked(QTreeWidgetItem*, int)'), lambda a, b: self.address_label_clicked(a,b,l,0,1))
@@ -938,11 +971,14 @@ 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())
+            return 
         menu = QMenu()
         menu.addAction(_("Copy to clipboard"), lambda: self.app.clipboard().setText(addr))
-        menu.addAction(_("QR code"), lambda: ElectrumWindow.show_qrcode("bitcoin:" + addr, _("Address")) )
+        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.view_private_key(addr))
+        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))
@@ -953,7 +989,7 @@ class ElectrumWindow(QMainWindow):
             t = _("Unprioritize") if addr in self.wallet.prioritized_addresses else _("Prioritize")
             menu.addAction(t, lambda: self.toggle_priority(addr))
             
-        self.wallet.run_hook('receive_menu', (self, menu,))
+        self.run_hook('receive_menu', (self, menu,))
         menu.exec_(self.receive_list.viewport().mapToGlobal(position))
 
 
@@ -1006,15 +1042,16 @@ class ElectrumWindow(QMainWindow):
 
 
     def update_receive_item(self, item):
+        item.setFont(0, QFont(MONOSPACE_FONT))
         address = str(item.data(0,0).toString())
         label = self.wallet.labels.get(address,'')
         item.setData(1,0,label)
 
-        self.wallet.run_hook('update_receive_item', (self, address, item))
+        self.run_hook('update_receive_item', (self, address, item))
                 
         c, u = self.wallet.get_addr_balance(address)
         balance = format_satoshis( c + u, False, self.wallet.num_zeros )
-        item.setData(3,0,balance)
+        item.setData(2,0,balance)
 
         if self.expert_mode:
             if address in self.wallet.frozen_addresses: 
@@ -1027,8 +1064,8 @@ class ElectrumWindow(QMainWindow):
         l = self.receive_list
         
         l.clear()
+        l.setColumnHidden(2, not self.expert_mode)
         l.setColumnHidden(3, not self.expert_mode)
-        l.setColumnHidden(4, not self.expert_mode)
         if not self.expert_mode:
             width = self.column_widths['receive'][0][0]
             l.setColumnWidth(0, width)
@@ -1040,7 +1077,7 @@ class ElectrumWindow(QMainWindow):
         for k, account in self.wallet.accounts.items():
             name = account.get('name',str(k))
             c,u = self.wallet.get_account_balance(k)
-            account_item = QTreeWidgetItem( [ name, '', '', format_satoshis(c+u), ''] )
+            account_item = QTreeWidgetItem( [ name, '', format_satoshis(c+u), ''] )
             l.addTopLevelItem(account_item)
             account_item.setExpanded(True)
             
@@ -1065,9 +1102,7 @@ class ElectrumWindow(QMainWindow):
                             gap = 0
 
                     num_tx = '*' if h == ['*'] else "%d"%len(h)
-                    item = QTreeWidgetItem( [ address, '', '', '', num_tx] )
-                    item.setFont(0, QFont(MONOSPACE_FONT))
-                    item.setFont(2, QFont(MONOSPACE_FONT))
+                    item = QTreeWidgetItem( [ address, '', '', num_tx] )
                     self.update_receive_item(item)
                     if is_red:
                         item.setBackgroundColor(1, QColor('red'))
@@ -1075,13 +1110,11 @@ class ElectrumWindow(QMainWindow):
 
         if self.wallet.imported_keys:
             c,u = self.wallet.get_imported_balance()
-            account_item = QTreeWidgetItem( [ _('Imported'), '', '', format_satoshis(c+u), ''] )
+            account_item = QTreeWidgetItem( [ _('Imported'), '', format_satoshis(c+u), ''] )
             l.addTopLevelItem(account_item)
             account_item.setExpanded(True)
             for address in self.wallet.imported_keys.keys():
-                item = QTreeWidgetItem( [ address, '', '', '', ''] )
-                item.setFont(0, QFont(MONOSPACE_FONT))
-                item.setFont(2, QFont(MONOSPACE_FONT))
+                item = QTreeWidgetItem( [ address, '', '', ''] )
                 self.update_receive_item(item)
                 account_item.addChild(item)
                 
@@ -1128,7 +1161,6 @@ class ElectrumWindow(QMainWindow):
 
     def create_console_tab(self):
         from qt_console import Console
-        from electrum import util, bitcoin, commands
         self.console = console = Console()
         self.console.history = self.config.get("console-history",[])
         self.console.history_index = len(self.console.history)
@@ -1164,10 +1196,12 @@ class ElectrumWindow(QMainWindow):
             sb.addPermanentWidget( StatusBarButton( QIcon(":icons/lock.png"), _("Password"), lambda: self.change_password_dialog(self.wallet, self) ) )
         sb.addPermanentWidget( StatusBarButton( QIcon(":icons/preferences.png"), _("Preferences"), self.settings_dialog ) )
         if self.wallet.seed:
-            sb.addPermanentWidget( StatusBarButton( QIcon(":icons/seed.png"), _("Seed"), lambda: self.show_seed_dialog(self.wallet, self) ) )
+            sb.addPermanentWidget( StatusBarButton( QIcon(":icons/seed.png"), _("Seed"), self.show_seed_dialog ) )
         self.status_button = StatusBarButton( QIcon(":icons/status_disconnected.png"), _("Network"), lambda: self.network_dialog(self.wallet, self) ) 
         sb.addPermanentWidget( self.status_button )
 
+        self.run_hook('create_status_bar', (sb,))
+
         self.setStatusBar(sb)
         
     def go_lite(self):
@@ -1194,7 +1228,7 @@ class ElectrumWindow(QMainWindow):
                 QMessageBox.warning(self, _('Error'), _('Invalid Address'), _('OK'))
 
     def show_master_public_key(self):
-        dialog = QDialog(None)
+        dialog = QDialog(self)
         dialog.setModal(1)
         dialog.setWindowTitle(_("Master Public Key"))
 
@@ -1202,7 +1236,7 @@ class ElectrumWindow(QMainWindow):
         main_text.setText(self.wallet.get_master_public_key())
         main_text.setReadOnly(True)
         main_text.setMaximumHeight(170)
-        qrw = QRCodeWidget(self.wallet.get_master_public_key(), 6)
+        qrw = QRCodeWidget(self.wallet.get_master_public_key())
 
         ok_button = QPushButton(_("OK"))
         ok_button.setDefault(True)
@@ -1225,30 +1259,22 @@ class ElectrumWindow(QMainWindow):
         dialog.exec_()
         
 
-    @classmethod
-    def show_seed_dialog(self, wallet, parent=None):
-        if not wallet.seed:
+    @protected
+    def show_seed_dialog(self, password):
+        if not self.wallet.seed:
             QMessageBox.information(parent, _('Message'), _('No seed'), _('OK'))
             return
-
-        if wallet.use_encryption:
-            password = parent.password_dialog()
-            if not password:
-                return
-        else:
-            password = None
-            
         try:
-            seed = wallet.decode_seed(password)
+            seed = self.wallet.decode_seed(password)
         except:
             QMessageBox.warning(parent, _('Error'), _('Incorrect Password'), _('OK'))
             return
+        self.show_seed(seed, self)
 
-        self.show_seed(seed)
 
     @classmethod
-    def show_seed(self, seed):
-        dialog = QDialog(None)
+    def show_seed(self, seed, parent=None):
+        dialog = QDialog(parent)
         dialog.setModal(1)
         dialog.setWindowTitle('Electrum' + ' - ' + _('Seed'))
 
@@ -1271,7 +1297,7 @@ class ElectrumWindow(QMainWindow):
         logo.setPixmap(QPixmap(":icons/seed.png").scaledToWidth(56))
         logo.setMaximumWidth(60)
 
-        qrw = QRCodeWidget(seed, 4)
+        qrw = QRCodeWidget(seed)
 
         ok_button = QPushButton(_("OK"))
         ok_button.setDefault(True)
@@ -1299,10 +1325,9 @@ class ElectrumWindow(QMainWindow):
         dialog.setLayout(vbox)
         dialog.exec_()
 
-    @staticmethod
-    def show_qrcode(data, title = "QR code"):
+    def show_qrcode(self, data, title = "QR code"):
         if not data: return
-        d = QDialog(None)
+        d = QDialog(self)
         d.setModal(1)
         d.setWindowTitle(title)
         d.setMinimumSize(270, 300)
@@ -1331,25 +1356,42 @@ class ElectrumWindow(QMainWindow):
         d.setLayout(vbox)
         d.exec_()
 
-    def view_private_key(self,address):
-        if not address: return
+
+    def do_protect(self, func, args):
         if self.wallet.use_encryption:
             password = self.password_dialog()
             if not password:
                 return
         else:
             password = None
+            
+        if args != (False,):
+            args = (self,) + args + (password,)
+        else:
+            args = (self,password)
+        apply( func, args)
+
 
+    @protected
+    def show_private_key(self, address, password):
+        if not address: return
         try:
             pk = self.wallet.get_private_key(address, password)
         except BaseException, e:
             self.show_message(str(e))
             return
-
         QMessageBox.information(self, _('Private key'), 'Address'+ ': ' + address + '\n\n' + _('Private key') + ': ' + pk, _('OK'))
 
 
-    def sign_message(self,address):
+    @protected
+    def do_sign(self, address, message, signature, password):
+        try:
+            sig = self.wallet.sign_message(str(address.text()), str(message.toPlainText()), password)
+            signature.setText(sig)
+        except BaseException, e:
+            self.show_message(str(e))
+
+    def sign_message(self, address):
         if not address: return
         d = QDialog(self)
         d.setModal(1)
@@ -1376,25 +1418,11 @@ class ElectrumWindow(QMainWindow):
         layout.addWidget(sign_signature, 3, 1)
         layout.setRowStretch(3,1)
 
-        def do_sign():
-            if self.wallet.use_encryption:
-                password = self.password_dialog()
-                if not password:
-                    return
-            else:
-                password = None
-
-            try:
-                signature = self.wallet.sign_message(str(sign_address.text()), str(sign_message.toPlainText()), password)
-                sign_signature.setText(signature)
-            except BaseException, e:
-                self.show_message(str(e))
-                return
 
         hbox = QHBoxLayout()
         b = QPushButton(_("Sign"))
         hbox.addWidget(b)
-        b.clicked.connect(do_sign)
+        b.clicked.connect(lambda: self.do_sign(sign_address, sign_message, sign_signature))
         b = QPushButton(_("Close"))
         b.clicked.connect(d.accept)
         hbox.addWidget(b)
@@ -1605,8 +1633,8 @@ class ElectrumWindow(QMainWindow):
         tree_widget.setColumnWidth(0, 300)
         tree_widget.setColumnWidth(1, 50)
 
-        for output in tx.d["outputs"]:
-            item = QTreeWidgetItem( ["%s" %(output["address"]), "%s" % ( format_satoshis(output["value"]))] )
+        for address, value in tx.outputs:
+            item = QTreeWidgetItem( [address, "%s" % ( format_satoshis(value))] )
             tree_widget.addTopLevelItem(item)
 
         tree_widget.setMaximumHeight(100)
@@ -1658,14 +1686,8 @@ class ElectrumWindow(QMainWindow):
         return self.tx_dict_from_text(file_content)
 
 
-    def sign_raw_transaction(self, tx, input_info):
-        if self.wallet.use_encryption:
-            password = self.password_dialog()
-            if not password:
-                return
-        else:
-            password = None
-
+    @protected
+    def sign_raw_transaction(self, tx, input_info, password):
         try:
             self.wallet.signrawtransaction(tx, input_info, [], password)
             
@@ -1762,15 +1784,10 @@ class ElectrumWindow(QMainWindow):
             self.create_send_transaction_window(tx_dict)
 
 
-    def do_export_privkeys(self):
+    @protected
+    def do_export_privkeys(self, password):
         self.show_message("%s\n%s\n%s" % (_("WARNING: ALL your private keys are secret."),  _("Exposing a single private key can compromise your entire wallet!"), _("In particular, DO NOT use 'redeem private key' services proposed by third parties.")))
 
-        if self.wallet.use_encryption:
-            password = self.password_dialog()
-            if not password:
-                return
-        else:
-            password = None
         try:
             select_export = _('Select file to export your private keys to')
             fileName = QFileDialog.getSaveFileName(QWidget(), select_export, os.path.expanduser('~/electrum-private-keys.csv'), "*.csv")
@@ -1809,7 +1826,6 @@ class ElectrumWindow(QMainWindow):
             QMessageBox.critical(None, _("Unable to import labels"), _("Electrum was unable to import your labels.")+"\n" + str(reason))
         
 
-
     def do_export_labels(self):
         labels = self.wallet.labels
         try:
@@ -1821,11 +1837,14 @@ class ElectrumWindow(QMainWindow):
         except (IOError, os.error), reason:
             QMessageBox.critical(None, "Unable to export labels", _("Electrum was unable to export your labels.")+"\n" + str(reason))
 
+
     def do_export_history(self):
         from gui_lite import csv_transaction
         csv_transaction(self.wallet)
 
-    def do_import_privkey(self):
+
+    @protected
+    def do_import_privkey(self, password):
         if not self.wallet.imported_keys:
             r = QMessageBox.question(None, _('Warning'), _('Warning: Imported keys are not recoverable from seed.') + ' ' \
                                          + _('If you ever need to restore your wallet from its seed, these keys will be lost.') + '\n\n' \
@@ -1835,12 +1854,6 @@ class ElectrumWindow(QMainWindow):
         text, ok = QInputDialog.getText(self, _('Import private key'), _('Private Key') + ':')
         if not ok: return
         sec = str(text).strip()
-        if self.wallet.use_encryption:
-            password = self.password_dialog()
-            if not password:
-                return
-        else:
-            password = None
         try:
             addr = self.wallet.import_key(sec, password)
             if not addr:
@@ -1852,6 +1865,7 @@ class ElectrumWindow(QMainWindow):
         except BaseException as e:
             QMessageBox.critical(None, _("Unable to import key"), str(e))
 
+
     def settings_dialog(self):
         d = QDialog(self)
         d.setWindowTitle(_('Electrum Settings'))
@@ -1859,6 +1873,7 @@ class ElectrumWindow(QMainWindow):
         vbox = QVBoxLayout()
 
         tabs = QTabWidget(self)
+        self.settings_tab = tabs
         vbox.addWidget(tabs)
 
         tab1 = QWidget()
@@ -2013,25 +2028,27 @@ class ElectrumWindow(QMainWindow):
         grid_raw.setRowStretch(3,1)
 
         # plugins
-        tab5 = QWidget()
-        grid_plugins = QGridLayout(tab5)
-        grid_plugins.setColumnStretch(0,1)
-        tabs.addTab(tab5, _('Plugins') )
-        def mk_toggle(cb, p):
-            return lambda: cb.setChecked(p.toggle(self))
-        for i, p in enumerate(self.wallet.plugins):
-            try:
-                name, description = p.get_info()
-                cb = QCheckBox(name)
-                cb.setChecked(p.is_enabled())
-                cb.stateChanged.connect(mk_toggle(cb,p))
-                grid_plugins.addWidget(cb, i, 0)
-                grid_plugins.addWidget(HelpButton(description), i, 2)
-            except:
-                print_msg("Error: cannot display plugin", p)
-                traceback.print_exc(file=sys.stdout)
+        if self.plugins:
+            tab5 = QWidget()
+            grid_plugins = QGridLayout(tab5)
+            grid_plugins.setColumnStretch(0,1)
+            tabs.addTab(tab5, _('Plugins') )
+            def mk_toggle(cb, p):
+                return lambda: cb.setChecked(p.toggle(self))
+            for i, p in enumerate(self.plugins):
+                try:
+                    name, description = p.get_info()
+                    cb = QCheckBox(name)
+                    cb.setChecked(p.is_enabled())
+                    cb.stateChanged.connect(mk_toggle(cb,p))
+                    grid_plugins.addWidget(cb, i, 0)
+                    grid_plugins.addWidget(HelpButton(description), i, 2)
+                except:
+                    print_msg("Error: cannot display plugin", p)
+                    traceback.print_exc(file=sys.stdout)
+            grid_plugins.setRowStretch(i+1,1)
 
-        grid_plugins.setRowStretch(i+1,1)
+        self.run_hook('create_settings_tab', (self,tabs,))
 
         vbox.addLayout(ok_cancel_buttons(d))
         d.setLayout(vbox) 
@@ -2304,11 +2321,12 @@ class ElectrumGui:
         
 
     def show_seed(self):
-        ElectrumWindow.show_seed_dialog(self.wallet)
+        ElectrumWindow.show_seed(self.wallet.seed)
 
 
     def password_dialog(self):
-        ElectrumWindow.change_password_dialog(self.wallet)
+        if self.wallet.seed:
+            ElectrumWindow.change_password_dialog(self.wallet)
 
 
     def restore_wallet(self):