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)
27 self.stack = QStackedLayout()
28 self.setLayout(self.stack)
31 def set_layout(self, layout):
34 self.stack.setCurrentIndex(self.stack.addWidget(w))
37 def restore_or_create(self):
42 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"
44 label.setWordWrap(True)
45 grid.addWidget(label, 0, 0)
50 b1.setText(_("Create new wallet"))
54 b2.setText(_("Restore wallet from seed"))
57 b3.setText(_("Create a watching-only version of an existing wallet"))
59 grid.addWidget(b1,1,0)
60 grid.addWidget(b2,2,0)
61 grid.addWidget(b3,3,0)
68 vbox.addLayout(ok_cancel_buttons(self, _('Next')))
83 def verify_seed(self, wallet):
84 r = self.seed_dialog(False)
88 if r != wallet.get_mnemonic(None):
89 QMessageBox.warning(None, _('Error'), _('Incorrect seed'), _('OK'))
95 def seed_dialog(self, is_restore=True):
99 msg = _("Please enter your wallet seed.") + "\n"
101 msg = _("Your seed is important!") \
102 + "\n" + _("To make sure that you have properly saved your seed, please retype it here.")
105 logo.setPixmap(QPixmap(":icons/seed.png").scaledToWidth(56))
106 logo.setMaximumWidth(60)
109 label.setWordWrap(True)
112 seed_e.setMaximumHeight(100)
114 vbox.addWidget(label)
117 grid.addWidget(logo, 0, 0)
118 grid.addWidget(seed_e, 0, 1)
123 vbox.addLayout(ok_cancel_buttons(self, _('Next')))
125 self.set_layout(vbox)
129 seed = unicode(seed_e.toPlainText())
132 QMessageBox.warning(None, _('Error'), _('No seed'), _('OK'))
139 def waiting_dialog(self, task, msg= _("Electrum is generating your addresses, please wait.")):
142 self.emit(QtCore.SIGNAL('accept'))
145 self.waiting_label = QLabel(msg)
146 vbox.addWidget(self.waiting_label)
147 self.set_layout(vbox)
148 t = threading.Thread(target = target)
154 def mpk_dialog(self):
157 vbox.addWidget(QLabel(_("Please enter your master public key.")))
162 label = QLabel(_("Key"))
163 grid.addWidget(label, 0, 0)
165 mpk_e.setMaximumHeight(100)
166 grid.addWidget(mpk_e, 0, 1)
168 label = QLabel(_("Chain"))
169 #grid.addWidget(label, 1, 0)
170 chain_e = QTextEdit()
171 chain_e.setMaximumHeight(100)
172 #grid.addWidget(chain_e, 1, 1)
177 vbox.addLayout(ok_cancel_buttons(self, _('Next')))
179 self.set_layout(vbox)
180 if not self.exec_(): return None, None
182 mpk = str(mpk_e.toPlainText()).strip()
183 chain = str(chain_e.toPlainText()).strip()
187 def network_dialog(self):
192 label = QLabel(_("Electrum communicates with remote 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.") + "\n\n" \
193 + _("How do you want to connect to a server:")+" ")
194 label.setWordWrap(True)
195 grid.addWidget(label, 0, 0)
199 b1 = QRadioButton(gb)
200 b1.setText(_("Auto connect"))
203 b2 = QRadioButton(gb)
204 b2.setText(_("Select server manually"))
206 #b3 = QRadioButton(gb)
207 #b3.setText(_("Stay offline"))
209 grid.addWidget(b1,1,0)
210 grid.addWidget(b2,2,0)
211 #grid.addWidget(b3,3,0)
217 vbox.addLayout(ok_cancel_buttons(self, _('Next')))
219 self.set_layout(vbox)
224 return NetworkDialog(self.network, self.config, None).do_exec()
227 self.config.set_key('auto_cycle', True, True)
231 self.config.set_key("server", None, True)
232 self.config.set_key('auto_cycle', False, True)
237 def show_seed(self, wallet):
238 from seed_dialog import make_seed_dialog
239 vbox = make_seed_dialog(wallet.get_mnemonic(None), wallet.imported_keys)
240 vbox.addLayout(ok_cancel_buttons(self, _("Next")))
241 self.set_layout(vbox)
245 def password_dialog(self, wallet):
246 msg = _("Please choose a password to encrypt your wallet keys.")+'\n'\
247 +_("Leave these fields empty if you want to disable encryption.")
248 from password_dialog import make_password_dialog, run_password_dialog
249 self.set_layout( make_password_dialog(self, wallet, msg) )
250 return run_password_dialog(self, wallet, self)
255 action = self.restore_or_create()
259 wallet = Wallet(self.storage)
260 gap = self.config.get('gap_limit', 5)
262 wallet.gap_limit = gap
263 wallet.storage.put('gap_limit', gap, True)
265 if action == 'create':
266 wallet.init_seed(None)
267 if not self.show_seed(wallet):
269 if not self.verify_seed(wallet):
271 ok, old_password, password = self.password_dialog(wallet)
273 wallet.save_seed(password)
274 wallet.synchronize() # generate first addresses offline
275 self.waiting_dialog(create)
278 elif action == 'restore':
279 seed = self.seed_dialog()
283 wallet.init_seed(seed)
286 traceback.print_exc(file=sys.stdout)
287 QMessageBox.warning(None, _('Error'), _('Incorrect seed'), _('OK'))
290 ok, old_password, password = self.password_dialog(wallet)
291 wallet.save_seed(password)
294 elif action == 'watching':
295 mpk = self.mpk_dialog()
299 wallet.create_watching_only_wallet(mpk)
303 #if not self.config.get('server'):
305 if self.network.interfaces:
306 self.network_dialog()
308 QMessageBox.information(None, _('Warning'), _('You are offline'), _('OK'))
311 # start wallet threads
312 wallet.start_threads(self.network)
314 if action == 'restore':
316 self.waiting_dialog(lambda: wallet.restore(self.waiting_label.setText))
319 if wallet.is_found():
320 QMessageBox.information(None, _('Information'), _("Recovery successful"), _('OK'))
322 QMessageBox.information(None, _('Information'), _("No transactions found for this seed"), _('OK'))
324 QMessageBox.information(None, _('Information'), _("This wallet was restored offline. It may contain more addresses than displayed."), _('OK'))