1 from PyQt4.QtGui import *
2 from PyQt4.QtCore import *
3 import PyQt4.QtCore as QtCore
5 from electrum.i18n import _
6 from electrum import Wallet, mnemonic
8 from seed_dialog import SeedDialog
9 from network_dialog import NetworkDialog
11 from amountedit import AmountEdit
16 class InstallWizard(QDialog):
18 def __init__(self, config, network, storage):
19 QDialog.__init__(self)
21 self.network = network
22 self.storage = storage
23 self.setMinimumSize(575, 400)
24 self.setWindowTitle('Electrum')
25 self.connect(self, QtCore.SIGNAL('accept'), self.accept)
28 def restore_or_create(self):
33 msg = _("Electrum could not find an existing wallet.")+"\n\n"+_("Did you use Electrum before and want to restore a previous wallet or is this your first time and do you want to create a new wallet?"+"\n")
35 label.setWordWrap(True)
36 grid.addWidget(label, 0, 0)
41 b1.setText(_("Create new wallet"))
45 b2.setText(_("Restore wallet from seed"))
48 b3.setText(_("Restore wallet from master public key"))
50 grid.addWidget(b1,1,0)
51 grid.addWidget(b2,2,0)
52 grid.addWidget(b3,3,0)
54 vbox = QVBoxLayout(self)
58 vbox.addLayout(ok_cancel_buttons(self, _('Next')))
73 def verify_seed(self, wallet):
74 r = self.seed_dialog(False)
79 QMessageBox.warning(None, _('Error'), _('Incorrect seed'), _('OK'))
85 def seed_dialog(self, is_restore=True):
87 if self.layout(): QWidget().setLayout(self.layout())
89 vbox = QVBoxLayout(self)
91 msg = _("Please enter your wallet seed.\n" + ' ')
92 msg += _("Your seed can be entered as a sequence of words, or as a hexadecimal string."+ ' \n')
94 msg = _("Your seed is important!") \
95 + "\n" + _("To make sure that you have properly saved your seed, please retype it here." + ' ')
98 logo.setPixmap(QPixmap(":icons/seed.png").scaledToWidth(56))
99 logo.setMaximumWidth(60)
102 label.setWordWrap(True)
105 seed_e.setMaximumHeight(100)
107 vbox.addWidget(label)
110 grid.addWidget(logo, 0, 0)
111 grid.addWidget(seed_e, 0, 1)
117 vbox.addLayout(ok_cancel_buttons(self, _('Next')))
123 seed = str(seed_e.toPlainText())
127 seed = mnemonic.mn_decode( seed.split() )
129 QMessageBox.warning(None, _('Error'), _('I cannot decode this'), _('OK'))
133 QMessageBox.warning(None, _('Error'), _('No seed'), _('OK'))
140 def waiting_dialog(self, task, msg= _("Electrum is generating your addresses, please wait.")):
143 self.emit(QtCore.SIGNAL('accept'))
145 if self.layout(): QWidget().setLayout(self.layout())
146 vbox = QVBoxLayout(self)
147 self.waiting_label = QLabel(msg)
148 vbox.addWidget(self.waiting_label)
149 t = threading.Thread(target = target)
155 def mpk_dialog(self):
157 if self.layout(): QWidget().setLayout(self.layout())
159 vbox = QVBoxLayout(self)
160 msg = _("Please enter your master public key.")
163 label.setWordWrap(True)
164 vbox.addWidget(label)
167 mpk_e.setMaximumHeight(100)
168 vbox.addWidget(mpk_e)
175 vbox.addLayout(ok_cancel_buttons(self, _('Next')))
177 if not self.exec_(): return
179 mpk = str(mpk_e.toPlainText())
183 def network_dialog(self):
185 if self.layout(): QWidget().setLayout(self.layout())
190 label = QLabel(_("Electrum communicates with Electrum servers to get information about your transactions and addresses. The servers all fulfil the same purpose only differing in hardware. In most cases you simply want to let Electrum pick one at random if you have a preference though feel free to select a server manually or stay offline.") + "\n\n" \
191 + _("How do you want to connect to a server: "))
192 label.setWordWrap(True)
193 grid.addWidget(label, 0, 0)
197 b1 = QRadioButton(gb)
198 b1.setText(_("Auto connect"))
201 b2 = QRadioButton(gb)
202 b2.setText(_("Select server manually"))
204 b3 = QRadioButton(gb)
205 b3.setText(_("Stay offline"))
207 grid.addWidget(b1,1,0)
208 grid.addWidget(b2,2,0)
209 grid.addWidget(b3,3,0)
211 vbox = QVBoxLayout(self)
215 vbox.addLayout(ok_cancel_buttons(self, _('Next')))
221 return NetworkDialog(self.network, self.config, None).do_exec()
224 self.config.set_key('auto_cycle', True, True)
228 self.config.set_key("server", None, True)
229 self.config.set_key('auto_cycle', False, True)
234 def show_seed(self, wallet):
235 from seed_dialog import make_seed_dialog
236 if self.layout(): QWidget().setLayout(self.layout())
237 make_seed_dialog(self, wallet.seed, wallet.imported_keys)
241 def password_dialog(self, wallet):
242 msg = _("Please choose a password to encrypt your wallet keys.")+'\n'\
243 +_("Leave these fields empty if you want to disable encryption.")
244 from password_dialog import make_password_dialog, run_password_dialog
245 if self.layout(): QWidget().setLayout(self.layout())
246 make_password_dialog(self, wallet, msg)
247 run_password_dialog(self, wallet, self)
252 action = self.restore_or_create()
253 if not action: exit()
255 wallet = Wallet(self.storage)
256 gap = self.config.get('gap_limit', 5)
258 wallet.gap_limit = gap
259 wallet.storage.put('gap_limit', gap, True)
261 if action == 'create':
262 wallet.init_seed(None)
263 self.show_seed(wallet)
264 if self.verify_seed(wallet):
267 wallet.create_accounts()
268 wallet.synchronize() # generate first addresses offline
269 self.waiting_dialog(create)
273 elif action == 'restore':
274 # ask for seed and gap.
275 seed = self.seed_dialog()
278 wallet.init_seed(str(seed))
281 elif action == 'watching':
282 # ask for seed and gap.
283 mpk = self.mpk_dialog()
292 QMessageBox.warning(None, _('Error'), _('error'), _('OK'))
294 wallet.create_watching_only_wallet(c0,K0)
299 #if not self.config.get('server'):
300 self.network_dialog()
302 # start wallet threads
303 wallet.start_threads(self.network)
305 if action == 'restore':
307 self.waiting_dialog(lambda: wallet.restore(self.waiting_label.setText))
309 if wallet.is_found():
310 QMessageBox.information(None, _('Information'), _("Recovery successful"), _('OK'))
312 QMessageBox.information(None, _('Information'), _("No transactions found for this seed"), _('OK'))
314 wallet.fill_addressbook()
316 self.password_dialog(wallet)