remove show() in waiting dialog
[electrum-nvc.git] / gui / qt / installwizard.py
1 from PyQt4.QtGui import *
2 from PyQt4.QtCore import *
3 import PyQt4.QtCore as QtCore
4
5 from electrum.i18n import _
6 from electrum import Wallet, mnemonic
7
8 from seed_dialog import SeedDialog
9 from network_dialog import NetworkDialog
10 from util import *
11 from amountedit import AmountEdit
12
13 import sys
14 import threading
15
16 class InstallWizard(QDialog):
17
18     def __init__(self, config, network, storage):
19         QDialog.__init__(self)
20         self.config = config
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)
26
27
28     def restore_or_create(self):
29
30         grid = QGridLayout()
31         grid.setSpacing(5)
32
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")
34         label = QLabel(msg)
35         label.setWordWrap(True)
36         grid.addWidget(label, 0, 0)
37
38         gb = QGroupBox()
39
40         b1 = QRadioButton(gb)
41         b1.setText(_("Create new wallet"))
42         b1.setChecked(True)
43
44         b2 = QRadioButton(gb)
45         b2.setText(_("Restore wallet from seed"))
46
47         b3 = QRadioButton(gb)
48         b3.setText(_("Restore wallet from master public key"))
49
50         grid.addWidget(b1,1,0)
51         grid.addWidget(b2,2,0)
52         grid.addWidget(b3,3,0)
53
54         vbox = QVBoxLayout(self)
55         vbox.addLayout(grid)
56
57         vbox.addStretch(1)
58         vbox.addLayout(ok_cancel_buttons(self, _('Next')))
59
60         if not self.exec_():
61             return
62         
63         if b1.isChecked():
64             answer = 'create'
65         elif b2.isChecked():
66             answer = 'restore'
67         else:
68             answer = 'watching'
69
70         return answer
71
72
73     def verify_seed(self, wallet):
74         r = self.seed_dialog(False)
75         if not r:
76             return
77
78         if r != wallet.seed:
79             QMessageBox.warning(None, _('Error'), _('Incorrect seed'), _('OK'))
80             return False
81         else:
82             return True
83
84
85     def seed_dialog(self, is_restore=True):
86
87         if self.layout(): QWidget().setLayout(self.layout())
88
89         vbox = QVBoxLayout(self)
90         if is_restore:
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')
93         else:
94             msg = _("Your seed is important!") \
95                   + "\n" + _("To make sure that you have properly saved your seed, please retype it here." + ' ')
96         
97         logo = QLabel()
98         logo.setPixmap(QPixmap(":icons/seed.png").scaledToWidth(56))
99         logo.setMaximumWidth(60)
100
101         label = QLabel(msg)
102         label.setWordWrap(True)
103
104         seed_e = QTextEdit()
105         seed_e.setMaximumHeight(100)
106
107         vbox.addWidget(label)
108
109         grid = QGridLayout()
110         grid.addWidget(logo, 0, 0)
111         grid.addWidget(seed_e, 0, 1)
112
113         vbox.addLayout(grid)
114
115
116         vbox.addStretch(1)
117         vbox.addLayout(ok_cancel_buttons(self, _('Next')))
118
119         if not self.exec_():
120             return
121
122         try:
123             seed = str(seed_e.toPlainText())
124             seed.decode('hex')
125         except:
126             try:
127                 seed = mnemonic.mn_decode( seed.split() )
128             except:
129                 QMessageBox.warning(None, _('Error'), _('I cannot decode this'), _('OK'))
130                 return
131
132         if not seed:
133             QMessageBox.warning(None, _('Error'), _('No seed'), _('OK'))
134             return
135
136         return seed
137
138
139
140     def waiting_dialog(self, task, msg= _("Electrum is generating your addresses, please wait.")):
141         def target():
142             task()
143             self.emit(QtCore.SIGNAL('accept'))
144
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)
150         t.start()
151         self.exec_()
152
153
154
155     def mpk_dialog(self):
156
157         if self.layout(): QWidget().setLayout(self.layout())
158
159         vbox = QVBoxLayout(self)
160         msg = _("Please enter your master public key.")
161
162         label=QLabel(msg)
163         label.setWordWrap(True)
164         vbox.addWidget(label)
165
166         mpk_e = QTextEdit()
167         mpk_e.setMaximumHeight(100)
168         vbox.addWidget(mpk_e)
169
170         grid = QGridLayout()
171         grid.setSpacing(8)
172         vbox.addLayout(grid)
173
174         vbox.addStretch(1)
175         vbox.addLayout(ok_cancel_buttons(self, _('Next')))
176
177         if not self.exec_(): return
178
179         mpk = str(mpk_e.toPlainText())
180         return mpk
181
182
183     def network_dialog(self):
184         
185         if self.layout(): QWidget().setLayout(self.layout())
186
187         grid = QGridLayout()
188         grid.setSpacing(5)
189
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)
194
195         gb = QGroupBox()
196
197         b1 = QRadioButton(gb)
198         b1.setText(_("Auto connect"))
199         b1.setChecked(True)
200
201         b2 = QRadioButton(gb)
202         b2.setText(_("Select server manually"))
203
204         b3 = QRadioButton(gb)
205         b3.setText(_("Stay offline"))
206
207         grid.addWidget(b1,1,0)
208         grid.addWidget(b2,2,0)
209         grid.addWidget(b3,3,0)
210
211         vbox = QVBoxLayout(self)
212         vbox.addLayout(grid)
213
214         vbox.addStretch(1)
215         vbox.addLayout(ok_cancel_buttons(self, _('Next')))
216
217         if not self.exec_():
218             return
219         
220         if b2.isChecked():
221             return NetworkDialog(self.network, self.config, None).do_exec()
222
223         elif b1.isChecked():
224             self.config.set_key('auto_cycle', True, True)
225             return
226
227         else:
228             self.config.set_key("server", None, True)
229             self.config.set_key('auto_cycle', False, True)
230             return
231         
232         
233
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)
238         self.exec_()
239
240
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)
248
249
250     def run(self):
251
252         action = self.restore_or_create()
253         if not action: exit()
254
255         wallet = Wallet(self.storage)
256         gap = self.config.get('gap_limit', 5)
257         if gap != 5:
258             wallet.gap_limit = gap
259             wallet.storage.put('gap_limit', gap, True)
260
261         if action == 'create':
262             wallet.init_seed(None)
263             self.show_seed(wallet)
264             if self.verify_seed(wallet):
265                 def create():
266                     wallet.save_seed()
267                     wallet.create_accounts()
268                     wallet.synchronize()  # generate first addresses offline
269                 self.waiting_dialog(create)
270             else:
271                 return
272                 
273         elif action == 'restore':
274             # ask for seed and gap.
275             seed = self.seed_dialog()
276             if not seed:
277                 return
278             wallet.init_seed(str(seed))
279             wallet.save_seed()
280
281         elif action == 'watching':
282             # ask for seed and gap.
283             mpk = self.mpk_dialog()
284             if not mpk:
285                 return
286             wallet.seed = ''
287
288             print eval(mpk)
289             try:
290                 c0, K0 = eval(mpk)
291             except:
292                 QMessageBox.warning(None, _('Error'), _('error'), _('OK'))
293                 return
294             wallet.create_watching_only_wallet(c0,K0)
295
296
297         else: raise
298                 
299         #if not self.config.get('server'):
300         self.network_dialog()
301
302         # start wallet threads
303         wallet.start_threads(self.network)
304
305         if action == 'restore':
306
307             self.waiting_dialog(lambda: wallet.restore(self.waiting_label.setText))
308
309             if wallet.is_found():
310                 QMessageBox.information(None, _('Information'), _("Recovery successful"), _('OK'))
311             else:
312                 QMessageBox.information(None, _('Information'), _("No transactions found for this seed"), _('OK'))
313             
314             wallet.fill_addressbook()
315
316         self.password_dialog(wallet)
317
318         return wallet