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)
161 vbox.addWidget(QLabel(_("Please enter your master public key.")))
166 label = QLabel(_("Key"))
167 grid.addWidget(label, 0, 0)
169 mpk_e.setMaximumHeight(100)
170 grid.addWidget(mpk_e, 0, 1)
172 label = QLabel(_("Chain"))
173 grid.addWidget(label, 1, 0)
174 chain_e = QTextEdit()
175 chain_e.setMaximumHeight(100)
176 grid.addWidget(chain_e, 1, 1)
181 vbox.addLayout(ok_cancel_buttons(self, _('Next')))
183 if not self.exec_(): return None, None
185 mpk = str(mpk_e.toPlainText()).strip()
186 chain = str(chain_e.toPlainText()).strip()
190 def network_dialog(self):
192 if self.layout(): QWidget().setLayout(self.layout())
197 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" \
198 + _("How do you want to connect to a server: "))
199 label.setWordWrap(True)
200 grid.addWidget(label, 0, 0)
204 b1 = QRadioButton(gb)
205 b1.setText(_("Auto connect"))
208 b2 = QRadioButton(gb)
209 b2.setText(_("Select server manually"))
211 b3 = QRadioButton(gb)
212 b3.setText(_("Stay offline"))
214 grid.addWidget(b1,1,0)
215 grid.addWidget(b2,2,0)
216 grid.addWidget(b3,3,0)
218 vbox = QVBoxLayout(self)
222 vbox.addLayout(ok_cancel_buttons(self, _('Next')))
228 return NetworkDialog(self.network, self.config, None).do_exec()
231 self.config.set_key('auto_cycle', True, True)
235 self.config.set_key("server", None, True)
236 self.config.set_key('auto_cycle', False, True)
241 def show_seed(self, wallet):
242 from seed_dialog import make_seed_dialog
244 vbox = make_seed_dialog(wallet.seed, wallet.imported_keys)
245 vbox.addLayout(ok_cancel_buttons(self, _("Next")))
247 if self.layout(): QWidget().setLayout(self.layout())
254 def password_dialog(self, wallet):
255 msg = _("Please choose a password to encrypt your wallet keys.")+'\n'\
256 +_("Leave these fields empty if you want to disable encryption.")
257 from password_dialog import make_password_dialog, run_password_dialog
258 if self.layout(): QWidget().setLayout(self.layout())
259 make_password_dialog(self, wallet, msg)
260 run_password_dialog(self, wallet, self)
265 action = self.restore_or_create()
266 if not action: exit()
268 wallet = Wallet(self.storage)
269 gap = self.config.get('gap_limit', 5)
271 wallet.gap_limit = gap
272 wallet.storage.put('gap_limit', gap, True)
274 if action == 'create':
275 wallet.init_seed(None)
276 self.show_seed(wallet)
277 if self.verify_seed(wallet):
280 wallet.create_accounts()
281 wallet.synchronize() # generate first addresses offline
282 self.waiting_dialog(create)
286 elif action == 'restore':
287 # ask for seed and gap.
288 seed = self.seed_dialog()
291 wallet.init_seed(str(seed))
294 elif action == 'watching':
295 # ask for seed and gap.
296 K, chain = self.mpk_dialog()
300 wallet.create_watching_only_wallet(chain,K)
305 #if not self.config.get('server'):
306 self.network_dialog()
308 # start wallet threads
309 wallet.start_threads(self.network)
311 if action == 'restore':
313 self.waiting_dialog(lambda: wallet.restore(self.waiting_label.setText))
315 if wallet.is_found():
316 QMessageBox.information(None, _('Information'), _("Recovery successful"), _('OK'))
318 QMessageBox.information(None, _('Information'), _("No transactions found for this seed"), _('OK'))
320 wallet.fill_addressbook()
322 self.password_dialog(wallet)