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
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" \
43 + _("What do you want to do?") + "\n"
45 label.setWordWrap(True)
46 grid.addWidget(label, 0, 0)
51 b1.setText(_("Create new wallet"))
55 b2.setText(_("Restore an existing wallet from its seed"))
58 b3.setText(_("Create a watching-only version of an existing wallet"))
60 grid.addWidget(b1,1,0)
61 grid.addWidget(b2,2,0)
62 grid.addWidget(b3,3,0)
69 vbox.addLayout(ok_cancel_buttons(self, _('Next')))
84 def verify_seed(self, wallet):
85 r = self.seed_dialog(False)
89 if r != wallet.get_mnemonic(None):
90 QMessageBox.warning(None, _('Error'), _('Incorrect seed'), _('OK'))
96 def seed_dialog(self, is_restore=True):
100 msg = _("Please enter your wallet seed.") + "\n"
102 msg = _("Your seed is important!") \
103 + "\n" + _("To make sure that you have properly saved your seed, please retype it here.")
106 logo.setPixmap(QPixmap(":icons/seed.png").scaledToWidth(56))
107 logo.setMaximumWidth(60)
110 label.setWordWrap(True)
113 seed_e.setMaximumHeight(100)
115 vbox.addWidget(label)
118 grid.addWidget(logo, 0, 0)
119 grid.addWidget(seed_e, 0, 1)
124 vbox.addLayout(ok_cancel_buttons(self, _('Next')))
126 self.set_layout(vbox)
130 seed = seed_e.toPlainText()
131 seed = unicode(seed.toLower())
134 QMessageBox.warning(None, _('Error'), _('No seed'), _('OK'))
137 if not Wallet.is_seed(seed):
138 QMessageBox.warning(None, _('Error'), _('Invalid seed'), _('OK'))
145 def waiting_dialog(self, task, msg= _("Electrum is generating your addresses, please wait.")):
148 self.emit(QtCore.SIGNAL('accept'))
151 self.waiting_label = QLabel(msg)
152 vbox.addWidget(self.waiting_label)
153 self.set_layout(vbox)
154 t = threading.Thread(target = target)
160 def mpk_dialog(self):
163 vbox.addWidget(QLabel(_("Please enter your master public key.")))
168 label = QLabel(_("Key"))
169 grid.addWidget(label, 0, 0)
171 mpk_e.setMaximumHeight(100)
172 grid.addWidget(mpk_e, 0, 1)
177 vbox.addLayout(ok_cancel_buttons(self, _('Next')))
179 self.set_layout(vbox)
183 mpk = str(mpk_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 #gap = self.config.get('gap_limit', 5)
261 # wallet.gap_limit = gap
262 # wallet.storage.put('gap_limit', gap, True)
264 if action == 'create':
265 wallet = Wallet(self.storage)
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)
277 elif action == 'restore':
278 seed = self.seed_dialog()
279 if not Wallet.is_seed(seed):
281 wallet = Wallet.from_seed(seed, self.storage)
282 ok, old_password, password = self.password_dialog(wallet)
283 wallet.save_seed(password)
285 elif action == 'watching':
286 mpk = self.mpk_dialog()
289 wallet = Wallet.from_mpk(mpk, self.storage)
293 #if not self.config.get('server'):
295 if self.network.interfaces:
296 self.network_dialog()
298 QMessageBox.information(None, _('Warning'), _('You are offline'), _('OK'))
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))
310 if wallet.is_found():
311 QMessageBox.information(None, _('Information'), _("Recovery successful"), _('OK'))
313 QMessageBox.information(None, _('Information'), _("No transactions found for this seed"), _('OK'))
315 QMessageBox.information(None, _('Information'), _("This wallet was restored offline. It may contain more addresses than displayed."), _('OK'))