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
243 if self.layout(): QWidget().setLayout(self.layout())
244 make_seed_dialog(self, wallet.seed, wallet.imported_keys)
248 def password_dialog(self, wallet):
249 msg = _("Please choose a password to encrypt your wallet keys.")+'\n'\
250 +_("Leave these fields empty if you want to disable encryption.")
251 from password_dialog import make_password_dialog, run_password_dialog
252 if self.layout(): QWidget().setLayout(self.layout())
253 make_password_dialog(self, wallet, msg)
254 run_password_dialog(self, wallet, self)
259 action = self.restore_or_create()
260 if not action: exit()
262 wallet = Wallet(self.storage)
263 gap = self.config.get('gap_limit', 5)
265 wallet.gap_limit = gap
266 wallet.storage.put('gap_limit', gap, True)
268 if action == 'create':
269 wallet.init_seed(None)
270 self.show_seed(wallet)
271 if self.verify_seed(wallet):
274 wallet.create_accounts()
275 wallet.synchronize() # generate first addresses offline
276 self.waiting_dialog(create)
280 elif action == 'restore':
281 # ask for seed and gap.
282 seed = self.seed_dialog()
285 wallet.init_seed(str(seed))
288 elif action == 'watching':
289 # ask for seed and gap.
290 K, chain = self.mpk_dialog()
294 wallet.create_watching_only_wallet(chain,K)
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)