structural change: wrap wallet instanciation inside the gui class
authorThomasV <thomasv@gitorious>
Thu, 22 Aug 2013 10:39:41 +0000 (12:39 +0200)
committerThomasV <thomasv@gitorious>
Thu, 22 Aug 2013 10:39:41 +0000 (12:39 +0200)
electrum
gui/gui_classic.py
gui/installwizard.py [new file with mode: 0644]
gui/password_dialog.py [new file with mode: 0644]
gui/seed_dialog.py [new file with mode: 0644]

index b92e6a7..a8142fc 100755 (executable)
--- a/electrum
+++ b/electrum
@@ -22,6 +22,7 @@ import sys, os, time, json
 import optparse
 import platform
 from decimal import Decimal
+import traceback
 
 try:
     import ecdsa  
@@ -106,7 +107,6 @@ if __name__ == '__main__':
         util.check_windows_wallet_migration()
 
     config = SimpleConfig(config_options)
-    wallet = Wallet(config)
 
 
     if len(args)==0:
@@ -124,86 +124,22 @@ if __name__ == '__main__':
         try:
             gui = __import__('electrum_gui.gui_' + gui_name, fromlist=['electrum_gui'])
         except ImportError:
-            sys.exit("Error: Unknown GUI: " + gui_name )
+            traceback.print_exc(file=sys.stdout)
+            sys.exit()
+            #sys.exit("Error: Unknown GUI: " + gui_name )
         
-        interface = Interface(config, True)
-        wallet.interface = interface
-
-        gui = gui.ElectrumGui(wallet, config)
-
-        found = config.wallet_file_exists
-        if not found:
-            a = gui.restore_or_create()
-            if not a: exit()
-
-            if a =='create':
-                wallet.init_seed(None)
-                gui.show_seed()
-                if gui.verify_seed():
-                    wallet.save_seed()
-                else:
-                    exit()
-
-            else:
-                # ask for seed and gap.
-                sg = gui.seed_dialog()
-                if not sg: exit()
-                seed, gap = sg
-                if not seed: exit()
-                wallet.gap_limit = gap
-                if len(seed) == 128:
-                    wallet.seed = ''
-                    wallet.init_sequence(str(seed))
-                else:
-                    wallet.init_seed(str(seed))
-                    wallet.save_seed()
-            
-            # select a server.
-            s = gui.network_dialog()
-            if s is None:
-                config.set_key("server", None, True)
-                config.set_key('auto_cycle', False, True)
-            
-        interface.start(wait = False)
-        interface.send([('server.peers.subscribe',[])])
-
-        # generate the first addresses, in case we are offline
-        if not found and ( s is None or a == 'create'):
-            wallet.synchronize()
-
-        verifier = WalletVerifier(interface, config)
-        verifier.start()
-        wallet.set_verifier(verifier)
-        synchronizer = WalletSynchronizer(wallet, config)
-        synchronizer.start()
-
-        if not found and a == 'restore' and s is not None:
-            try:
-                keep_it = gui.restore_wallet()
-                wallet.fill_addressbook()
-            except:
-                import traceback
-                traceback.print_exc(file=sys.stdout)
-                exit()
-
-            if not keep_it: exit()
-
-        if not found:
-            gui.password_dialog()
-
-        #wallet.save()
+        gui = gui.ElectrumGui(config)
         gui.main(url)
-        #wallet.save()
-
-        verifier.stop()
-        synchronizer.stop()
-        interface.stop()
 
         # we use daemon threads, their termination is enforced.
         # this sleep command gives them time to terminate cleanly. 
         time.sleep(0.1)
         sys.exit(0)
 
+
+    # instanciate wallet for command-line
+    wallet = Wallet(config)
+
     if cmd not in known_commands:
         cmd = 'help'
 
index 17d6321..83c670e 100644 (file)
@@ -42,7 +42,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
+from electrum import util, bitcoin, commands, Interface, Wallet, WalletVerifier, WalletSynchronizer
 
 import bmp, pyqrnative
 import exchange_rate
@@ -265,6 +265,7 @@ class ElectrumWindow(QMainWindow):
         if reason == QSystemTrayIcon.DoubleClick:
             self.showNormal()
 
+
     def __init__(self, wallet, config):
         QMainWindow.__init__(self)
         self._close_electrum = False
@@ -352,10 +353,21 @@ class ElectrumWindow(QMainWindow):
         wallet_folder = self.wallet.config.path
         re.sub("(\/\w*.dat)$", "", wallet_folder)
         file_name = QFileDialog.getOpenFileName(self, "Select your wallet file", wallet_folder, "*.dat")
-        if not file_name:
-            return
-        else:
-          self.load_wallet(file_name)
+        return file_name
+
+    def open_wallet(self):
+        n = self.select_wallet_file()
+        if n:
+            self.load_wallet(n)
+
+    def new_wallet(self):
+        n = self.getOpenFileName("Select wallet file")
+
+        wizard = installwizard.InstallWizard(self.config, self.interface)
+        wallet = wizard.run()
+        if wallet: 
+            self.load_wallet(wallet)
+        
 
 
     def init_menubar(self):
@@ -363,7 +375,10 @@ class ElectrumWindow(QMainWindow):
 
         electrum_menu = menubar.addMenu(_("&File"))
         open_wallet_action = electrum_menu.addAction(_("Open wallet"))
-        open_wallet_action.triggered.connect(self.select_wallet_file)
+        open_wallet_action.triggered.connect(self.open_wallet)
+
+        new_wallet_action = electrum_menu.addAction(_("New wallet"))
+        new_wallet_action.triggered.connect(self.new_wallet)
 
         preferences_name = _("Preferences")
         if sys.platform == 'darwin':
@@ -430,6 +445,7 @@ class ElectrumWindow(QMainWindow):
 
         self.setMenuBar(menubar)
 
+
     def load_wallet(self, filename):
         import electrum
 
@@ -1395,7 +1411,7 @@ class ElectrumWindow(QMainWindow):
             sb.addPermanentWidget( StatusBarButton( QIcon(":icons/switchgui.png"), _("Switch to Lite Mode"), self.go_lite ) )
         if self.wallet.seed:
             self.lock_icon = QIcon(":icons/lock.png") if self.wallet.use_encryption else QIcon(":icons/unlock.png")
-            self.password_button = StatusBarButton( self.lock_icon, _("Password"), lambda: self.change_password_dialog(self.wallet, self) )
+            self.password_button = StatusBarButton( self.lock_icon, _("Password"), self.change_password_dialog )
             sb.addPermanentWidget( self.password_button )
         sb.addPermanentWidget( StatusBarButton( QIcon(":icons/preferences.png"), _("Preferences"), self.settings_dialog ) )
         if self.wallet.seed:
@@ -1406,6 +1422,13 @@ class ElectrumWindow(QMainWindow):
         self.run_hook('create_status_bar', (sb,))
 
         self.setStatusBar(sb)
+
+
+    def change_password_dialog(self):
+        from password_dialog import PasswordDialog
+        d = PasswordDialog(self.wallet, self)
+        d.run()
+
         
     def go_lite(self):
         import gui_lite
@@ -1490,63 +1513,12 @@ class ElectrumWindow(QMainWindow):
         except:
             QMessageBox.warning(self, _('Error'), _('Incorrect Password'), _('OK'))
             return
-        self.show_seed(seed, self.wallet.imported_keys, self)
-
-
-    @classmethod
-    def show_seed(self, seed, imported_keys, parent=None):
-        dialog = QDialog(parent)
-        dialog.setModal(1)
-        dialog.setWindowTitle('Electrum' + ' - ' + _('Seed'))
-
-        brainwallet = ' '.join(mnemonic.mn_encode(seed))
-
-        label1 = QLabel(_("Your wallet generation seed is")+ ":")
-
-        seed_text = QTextEdit(brainwallet)
-        seed_text.setReadOnly(True)
-        seed_text.setMaximumHeight(130)
-        
-        msg2 =  _("Please write down or memorize these 12 words (order is important).") + " " \
-              + _("This seed will allow you to recover your wallet in case of computer failure.") + " " \
-              + _("Your seed is also displayed as QR code, in case you want to transfer it to a mobile phone.") + "<p>" \
-              + "<b>"+_("WARNING")+":</b> " + _("Never disclose your seed. Never type it on a website.") + "</b><p>"
-        if imported_keys:
-            msg2 += "<b>"+_("WARNING")+":</b> " + _("Your wallet contains imported keys. These keys cannot be recovered from seed.") + "</b><p>"
-        label2 = QLabel(msg2)
-        label2.setWordWrap(True)
-
-        logo = QLabel()
-        logo.setPixmap(QPixmap(":icons/seed.png").scaledToWidth(56))
-        logo.setMaximumWidth(60)
-
-        qrw = QRCodeWidget(seed)
-
-        ok_button = QPushButton(_("OK"))
-        ok_button.setDefault(True)
-        ok_button.clicked.connect(dialog.accept)
-
-        grid = QGridLayout()
-        #main_layout.addWidget(logo, 0, 0)
-
-        grid.addWidget(logo, 0, 0)
-        grid.addWidget(label1, 0, 1)
-
-        grid.addWidget(seed_text, 1, 0, 1, 2)
-
-        grid.addWidget(qrw, 0, 2, 2, 1)
 
-        vbox = QVBoxLayout()
-        vbox.addLayout(grid)
-        vbox.addWidget(label2)
+        from seed_dialog import SeedDialog
+        d = SeedDialog(self)
+        d.show_seed(seed, self.wallet.imported_keys)
 
-        hbox = QHBoxLayout()
-        hbox.addStretch(1)
-        hbox.addWidget(ok_button)
-        vbox.addLayout(hbox)
 
-        dialog.setLayout(vbox)
-        dialog.exec_()
 
     def show_qrcode(self, data, title = "QR code"):
         if not data: return
@@ -1728,79 +1700,6 @@ class ElectrumWindow(QMainWindow):
 
 
 
-    @staticmethod
-    def change_password_dialog( wallet, parent=None ):
-
-        if not wallet.seed:
-            QMessageBox.information(parent, _('Error'), _('No seed'), _('OK'))
-            return
-
-        d = QDialog(parent)
-        d.setModal(1)
-
-        pw = QLineEdit()
-        pw.setEchoMode(2)
-        new_pw = QLineEdit()
-        new_pw.setEchoMode(2)
-        conf_pw = QLineEdit()
-        conf_pw.setEchoMode(2)
-
-        vbox = QVBoxLayout()
-        if parent:
-            msg = (_('Your wallet is encrypted. Use this dialog to change your password.')+'\n'\
-                   +_('To disable wallet encryption, enter an empty new password.')) \
-                   if wallet.use_encryption else _('Your wallet keys are not encrypted')
-        else:
-            msg = _("Please choose a password to encrypt your wallet keys.")+'\n'\
-                  +_("Leave these fields empty if you want to disable encryption.")
-        vbox.addWidget(QLabel(msg))
-
-        grid = QGridLayout()
-        grid.setSpacing(8)
-
-        if wallet.use_encryption:
-            grid.addWidget(QLabel(_('Password')), 1, 0)
-            grid.addWidget(pw, 1, 1)
-
-        grid.addWidget(QLabel(_('New Password')), 2, 0)
-        grid.addWidget(new_pw, 2, 1)
-
-        grid.addWidget(QLabel(_('Confirm Password')), 3, 0)
-        grid.addWidget(conf_pw, 3, 1)
-        vbox.addLayout(grid)
-
-        vbox.addLayout(ok_cancel_buttons(d))
-        d.setLayout(vbox) 
-
-        if not d.exec_(): return
-
-        password = unicode(pw.text()) if wallet.use_encryption else None
-        new_password = unicode(new_pw.text())
-        new_password2 = unicode(conf_pw.text())
-
-        try:
-            seed = wallet.decode_seed(password)
-        except:
-            QMessageBox.warning(parent, _('Error'), _('Incorrect Password'), _('OK'))
-            return
-
-        if new_password != new_password2:
-            QMessageBox.warning(parent, _('Error'), _('Passwords do not match'), _('OK'))
-            return ElectrumWindow.change_password_dialog(wallet, parent) # Retry
-
-        try:
-            wallet.update_password(seed, password, new_password)
-        except:
-            QMessageBox.warning(parent, _('Error'), _('Failed to update password'), _('OK'))
-            return
-
-        QMessageBox.information(parent, _('Success'), _('Password was updated successfully'), _('OK'))
-
-        if parent: 
-            icon = QIcon(":icons/lock.png") if wallet.use_encryption else QIcon(":icons/unlock.png")
-            parent.password_button.setIcon( icon )
-
-
 
     def generate_transaction_information_widget(self, tx):
         tabs = QTabWidget(self)
@@ -2282,10 +2181,13 @@ class OpenFileEventFilter(QObject):
                 return True
         return False
 
+
+
+
 class ElectrumGui:
 
-    def __init__(self, wallet, config, app=None):
-        self.wallet = wallet
+    def __init__(self, config, app=None):
+        self.interface = Interface(config, True)
         self.config = config
         self.windows = []
         self.efilter = OpenFileEventFilter(self.windows)
@@ -2293,116 +2195,32 @@ class ElectrumGui:
             self.app = QApplication(sys.argv)
         self.app.installEventFilter(self.efilter)
 
-    def restore_or_create(self):
-        msg = _("Wallet file not found.")+"\n"+_("Do you want to create a new wallet, or to restore an existing one?")
-        r = QMessageBox.question(None, _('Message'), msg, _('Create'), _('Restore'), _('Cancel'), 0, 2)
-        if r==2: return None
-        return 'restore' if r==1 else 'create'
-
-
-    def verify_seed(self):
-        r = self.seed_dialog(False)
-        if r != self.wallet.seed:
-            QMessageBox.warning(None, _('Error'), 'incorrect seed', 'OK')
-            return False
-        else:
-            return True
-        
 
-
-    def seed_dialog(self, is_restore=True):
-        d = QDialog()
-        d.setModal(1)
-
-        vbox = QVBoxLayout()
-        if is_restore:
-            msg = _("Please enter your wallet seed (or your master public key if you want to create a watching-only wallet)." + ' ')
-        else:
-            msg = _("Your seed is important! To make sure that you have properly saved your seed, please type it here." + ' ')
-
-        msg += _("Your seed can be entered as a sequence of words, or as a hexadecimal string."+ '\n')
-        
-        label=QLabel(msg)
-        label.setWordWrap(True)
-        vbox.addWidget(label)
-
-        seed_e = QTextEdit()
-        seed_e.setMaximumHeight(100)
-        vbox.addWidget(seed_e)
-
-        if is_restore:
-            grid = QGridLayout()
-            grid.setSpacing(8)
-            gap_e = AmountEdit(None, True)
-            gap_e.setText("5")
-            grid.addWidget(QLabel(_('Gap limit')), 2, 0)
-            grid.addWidget(gap_e, 2, 1)
-            grid.addWidget(HelpButton(_('Keep the default value unless you modified this parameter in your wallet.')), 2, 3)
-            vbox.addLayout(grid)
-
-        vbox.addLayout(ok_cancel_buttons(d))
-        d.setLayout(vbox) 
-
-        if not d.exec_(): return
-
-        try:
-            seed = str(seed_e.toPlainText())
-            seed.decode('hex')
-        except:
-            try:
-                seed = mnemonic.mn_decode( seed.split() )
-            except:
-                QMessageBox.warning(None, _('Error'), _('I cannot decode this'), _('OK'))
-                return
-
-        if not seed:
-            QMessageBox.warning(None, _('Error'), _('No seed'), _('OK'))
-            return
-
-        if not is_restore:
-            return seed
+    def main(self, url):
+            
+        found = self.config.wallet_file_exists
+        if not found:
+            import installwizard
+            wizard = installwizard.InstallWizard(self.config, self.interface)
+            wallet = wizard.run()
+            if not wallet: 
+                exit()
         else:
-            try:
-                gap = int(unicode(gap_e.text()))
-            except:
-                QMessageBox.warning(None, _('Error'), 'error', 'OK')
-                return
-            return seed, gap
-
-
-    def network_dialog(self):
-        return NetworkDialog(self.wallet.interface, self.config, None).do_exec()
-        
-
-    def show_seed(self):
-        ElectrumWindow.show_seed(self.wallet.seed, self.wallet.imported_keys)
+            wallet = Wallet(self.config)
 
-    def password_dialog(self):
-        if self.wallet.seed:
-            ElectrumWindow.change_password_dialog(self.wallet)
-
-
-    def restore_wallet(self):
-        wallet = self.wallet
-        # wait until we are connected, because the user might have selected another server
-        if not wallet.interface.is_connected:
-            waiting = lambda: False if wallet.interface.is_connected else "%s \n" % (_("Connecting..."))
-            waiting_dialog(waiting)
+        self.wallet = wallet
 
-        waiting = lambda: False if wallet.is_up_to_date() else "%s\n%s %d\n%s %.1f"\
-            %(_("Please wait..."),_("Addresses generated:"),len(wallet.addresses(True)),_("Kilobytes received:"), wallet.interface.bytes_received/1024.)
+        self.interface.start(wait = False)
+        self.interface.send([('server.peers.subscribe',[])])
+        wallet.interface = self.interface
 
-        wallet.set_up_to_date(False)
-        wallet.interface.poke('synchronizer')
-        waiting_dialog(waiting)
-        if wallet.is_found():
-            print_error( "Recovery successful" )
-        else:
-            QMessageBox.information(None, _('Error'), _("No transactions found for this seed"), _('OK'))
+        verifier = WalletVerifier(self.interface, self.config)
+        verifier.start()
+        wallet.set_verifier(verifier)
+        synchronizer = WalletSynchronizer(wallet, self.config)
+        synchronizer.start()
 
-        return True
 
-    def main(self,url):
         s = Timer()
         s.start()
         w = ElectrumWindow(self.wallet, self.config)
@@ -2415,4 +2233,8 @@ class ElectrumGui:
 
         self.app.exec_()
 
+        verifier.stop()
+        synchronizer.stop()
+        self.interface.stop()
+
 
diff --git a/gui/installwizard.py b/gui/installwizard.py
new file mode 100644 (file)
index 0000000..430ae93
--- /dev/null
@@ -0,0 +1,183 @@
+from PyQt4.QtGui import *
+from PyQt4.QtCore import *
+import PyQt4.QtCore as QtCore
+from i18n import _
+
+from electrum import Wallet, mnemonic
+from seed_dialog import SeedDialog
+from network_dialog import NetworkDialog
+from qt_util import *
+
+class InstallWizard(QDialog):
+
+    def __init__(self, config, interface):
+        QDialog.__init__(self)
+        self.config = config
+        self.interface = interface
+
+
+    def restore_or_create(self):
+        msg = _("Wallet file not found.")+"\n"+_("Do you want to create a new wallet, or to restore an existing one?")
+        r = QMessageBox.question(None, _('Message'), msg, _('Create'), _('Restore'), _('Cancel'), 0, 2)
+        if r==2: return None
+        return 'restore' if r==1 else 'create'
+
+
+    def verify_seed(self, wallet):
+        r = self.seed_dialog(False)
+        if r != wallet.seed:
+            QMessageBox.warning(None, _('Error'), 'incorrect seed', 'OK')
+            return False
+        else:
+            return True
+
+
+    def seed_dialog(self, is_restore=True):
+        d = QDialog()
+        d.setModal(1)
+
+        vbox = QVBoxLayout()
+        if is_restore:
+            msg = _("Please enter your wallet seed (or your master public key if you want to create a watching-only wallet)." + ' ')
+        else:
+            msg = _("Your seed is important! To make sure that you have properly saved your seed, please type it here." + ' ')
+
+        msg += _("Your seed can be entered as a sequence of words, or as a hexadecimal string."+ '\n')
+        
+        label=QLabel(msg)
+        label.setWordWrap(True)
+        vbox.addWidget(label)
+
+        seed_e = QTextEdit()
+        seed_e.setMaximumHeight(100)
+        vbox.addWidget(seed_e)
+
+        if is_restore:
+            grid = QGridLayout()
+            grid.setSpacing(8)
+            gap_e = AmountEdit(None, True)
+            gap_e.setText("5")
+            grid.addWidget(QLabel(_('Gap limit')), 2, 0)
+            grid.addWidget(gap_e, 2, 1)
+            grid.addWidget(HelpButton(_('Keep the default value unless you modified this parameter in your wallet.')), 2, 3)
+            vbox.addLayout(grid)
+
+        vbox.addLayout(ok_cancel_buttons(d))
+        d.setLayout(vbox) 
+
+        if not d.exec_(): return
+
+        try:
+            seed = str(seed_e.toPlainText())
+            seed.decode('hex')
+        except:
+            try:
+                seed = mnemonic.mn_decode( seed.split() )
+            except:
+                QMessageBox.warning(None, _('Error'), _('I cannot decode this'), _('OK'))
+                return
+
+        if not seed:
+            QMessageBox.warning(None, _('Error'), _('No seed'), _('OK'))
+            return
+
+        if not is_restore:
+            return seed
+        else:
+            try:
+                gap = int(unicode(gap_e.text()))
+            except:
+                QMessageBox.warning(None, _('Error'), 'error', 'OK')
+                return
+            return seed, gap
+
+
+    def network_dialog(self):
+        return NetworkDialog(self.interface, self.config, None).do_exec()
+        
+
+    def show_seed(self, wallet):
+        d = SeedDialog()
+        d.show_seed(wallet.seed, wallet.imported_keys)
+
+
+    def password_dialog(self, wallet):
+        from password_dialog import PasswordDialog
+        d = PasswordDialog(wallet)
+        d.run()
+
+
+    def restore_wallet(self):
+        wallet = self.wallet
+        # wait until we are connected, because the user might have selected another server
+        if not wallet.interface.is_connected:
+            waiting = lambda: False if wallet.interface.is_connected else "%s \n" % (_("Connecting..."))
+            waiting_dialog(waiting)
+
+        waiting = lambda: False if wallet.is_up_to_date() else "%s\n%s %d\n%s %.1f"\
+            %(_("Please wait..."),_("Addresses generated:"),len(wallet.addresses(True)),_("Kilobytes received:"), wallet.interface.bytes_received/1024.)
+
+        wallet.set_up_to_date(False)
+        wallet.interface.poke('synchronizer')
+        waiting_dialog(waiting)
+        if wallet.is_found():
+            print_error( "Recovery successful" )
+        else:
+            QMessageBox.information(None, _('Error'), _("No transactions found for this seed"), _('OK'))
+
+        return True
+
+
+    def run(self):
+
+        a = self.restore_or_create()
+        if not a: exit()
+
+        wallet = Wallet(self.config)
+        wallet.interface = self.interface
+
+        if a =='create':
+            wallet.init_seed(None)
+            self.show_seed(wallet)
+            if self.verify_seed(wallet):
+                wallet.save_seed()
+            else:
+                exit()
+        else:
+            # ask for seed and gap.
+            sg = gui.seed_dialog()
+            if not sg: exit()
+            seed, gap = sg
+            if not seed: exit()
+            wallet.gap_limit = gap
+            if len(seed) == 128:
+                wallet.seed = ''
+                wallet.init_sequence(str(seed))
+            else:
+                wallet.init_seed(str(seed))
+                wallet.save_seed()
+
+        # select a server.
+        s = self.network_dialog()
+        if s is None:
+            self.config.set_key("server", None, True)
+            self.config.set_key('auto_cycle', False, True)
+
+        # generate the first addresses, in case we are offline
+        if s is None or a == 'create':
+            wallet.synchronize()
+
+
+        if a == 'restore' and s is not None:
+            try:
+                keep_it = gui.restore_wallet()
+                wallet.fill_addressbook()
+            except:
+                import traceback
+                traceback.print_exc(file=sys.stdout)
+                exit()
+
+            if not keep_it: exit()
+
+
+        self.password_dialog(wallet)
diff --git a/gui/password_dialog.py b/gui/password_dialog.py
new file mode 100644 (file)
index 0000000..b8133ae
--- /dev/null
@@ -0,0 +1,104 @@
+#!/usr/bin/env python
+#
+# Electrum - lightweight Bitcoin client
+# Copyright (C) 2013 ecdsa@github
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+from PyQt4.QtGui import *
+from PyQt4.QtCore import *
+from i18n import _
+from qt_util import *
+
+
+class PasswordDialog(QDialog):
+
+    def __init__(self, wallet, parent=None):
+        QDialog.__init__(self, parent)
+        self.setModal(1)
+        self.wallet = wallet
+        self.parent = parent
+
+        self.pw = QLineEdit()
+        self.pw.setEchoMode(2)
+        self.new_pw = QLineEdit()
+        self.new_pw.setEchoMode(2)
+        self.conf_pw = QLineEdit()
+        self.conf_pw.setEchoMode(2)
+
+        vbox = QVBoxLayout()
+        if parent:
+            msg = (_('Your wallet is encrypted. Use this dialog to change your password.')+'\n'\
+                   +_('To disable wallet encryption, enter an empty new password.')) \
+                   if wallet.use_encryption else _('Your wallet keys are not encrypted')
+        else:
+            msg = _("Please choose a password to encrypt your wallet keys.")+'\n'\
+                  +_("Leave these fields empty if you want to disable encryption.")
+        vbox.addWidget(QLabel(msg))
+
+        grid = QGridLayout()
+        grid.setSpacing(8)
+
+        if wallet.use_encryption:
+            grid.addWidget(QLabel(_('Password')), 1, 0)
+            grid.addWidget(self.pw, 1, 1)
+
+        grid.addWidget(QLabel(_('New Password')), 2, 0)
+        grid.addWidget(self.new_pw, 2, 1)
+
+        grid.addWidget(QLabel(_('Confirm Password')), 3, 0)
+        grid.addWidget(self.conf_pw, 3, 1)
+        vbox.addLayout(grid)
+
+        vbox.addLayout(ok_cancel_buttons(self))
+        self.setLayout(vbox) 
+
+
+    def run(self):
+        wallet = self.wallet
+
+        if not wallet.seed:
+            QMessageBox.information(parent, _('Error'), _('No seed'), _('OK'))
+            return
+
+        if not self.exec_(): return
+
+        password = unicode(self.pw.text()) if wallet.use_encryption else None
+        new_password = unicode(self.new_pw.text())
+        new_password2 = unicode(self.conf_pw.text())
+
+        try:
+            seed = wallet.decode_seed(password)
+        except:
+            QMessageBox.warning(self.parent, _('Error'), _('Incorrect Password'), _('OK'))
+            return
+
+        if new_password != new_password2:
+            QMessageBox.warning(self.parent, _('Error'), _('Passwords do not match'), _('OK'))
+            self.run() # Retry
+
+        try:
+            wallet.update_password(seed, password, new_password)
+        except:
+            QMessageBox.warning(self.parent, _('Error'), _('Failed to update password'), _('OK'))
+            return
+
+        QMessageBox.information(self.parent, _('Success'), _('Password was updated successfully'), _('OK'))
+
+        if self.parent: 
+            icon = QIcon(":icons/lock.png") if wallet.use_encryption else QIcon(":icons/unlock.png")
+            self.parent.password_button.setIcon( icon )
+
+
+
diff --git a/gui/seed_dialog.py b/gui/seed_dialog.py
new file mode 100644 (file)
index 0000000..37f9c00
--- /dev/null
@@ -0,0 +1,82 @@
+#!/usr/bin/env python
+#
+# Electrum - lightweight Bitcoin client
+# Copyright (C) 2013 ecdsa@github
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+from PyQt4.QtGui import *
+from PyQt4.QtCore import *
+import PyQt4.QtCore as QtCore
+from i18n import _
+from electrum import mnemonic
+from qrcodewidget import QRCodeWidget
+
+class SeedDialog(QDialog):
+    def __init__(self, parent=None):
+        QDialog.__init__(self, parent)
+        self.setModal(1)
+        self.setWindowTitle('Electrum' + ' - ' + _('Seed'))
+
+
+    def show_seed(self, seed, imported_keys, parent=None):
+
+        brainwallet = ' '.join(mnemonic.mn_encode(seed))
+
+        label1 = QLabel(_("Your wallet generation seed is")+ ":")
+
+        seed_text = QTextEdit(brainwallet)
+        seed_text.setReadOnly(True)
+        seed_text.setMaximumHeight(130)
+        
+        msg2 =  _("Please write down or memorize these 12 words (order is important).") + " " \
+              + _("This seed will allow you to recover your wallet in case of computer failure.") + " " \
+              + _("Your seed is also displayed as QR code, in case you want to transfer it to a mobile phone.") + "<p>" \
+              + "<b>"+_("WARNING")+":</b> " + _("Never disclose your seed. Never type it on a website.") + "</b><p>"
+        if imported_keys:
+            msg2 += "<b>"+_("WARNING")+":</b> " + _("Your wallet contains imported keys. These keys cannot be recovered from seed.") + "</b><p>"
+        label2 = QLabel(msg2)
+        label2.setWordWrap(True)
+
+        logo = QLabel()
+        logo.setPixmap(QPixmap(":icons/seed.png").scaledToWidth(56))
+        logo.setMaximumWidth(60)
+
+        qrw = QRCodeWidget(seed)
+
+        ok_button = QPushButton(_("OK"))
+        ok_button.setDefault(True)
+        ok_button.clicked.connect(self.accept)
+
+        grid = QGridLayout()
+        #main_layout.addWidget(logo, 0, 0)
+
+        grid.addWidget(logo, 0, 0)
+        grid.addWidget(label1, 0, 1)
+
+        grid.addWidget(seed_text, 1, 0, 1, 2)
+
+        grid.addWidget(qrw, 0, 2, 2, 1)
+
+        vbox = QVBoxLayout()
+        vbox.addLayout(grid)
+        vbox.addWidget(label2)
+
+        hbox = QHBoxLayout()
+        hbox.addStretch(1)
+        hbox.addWidget(ok_button)
+        vbox.addLayout(hbox)
+
+        self.setLayout(vbox)
+        self.exec_()