from electrum.wallet import format_satoshis
from electrum.bitcoin import Transaction, is_valid
from electrum import mnemonic
+from electrum import util, bitcoin, commands
import bmp, pyqrnative
import exchange_rate
def ok_cancel_buttons(dialog):
hbox = QHBoxLayout()
hbox.addStretch(1)
- b = QPushButton("OK")
- hbox.addWidget(b)
- b.clicked.connect(dialog.accept)
b = QPushButton("Cancel")
hbox.addWidget(b)
b.clicked.connect(dialog.reject)
+ b = QPushButton("OK")
+ hbox.addWidget(b)
+ b.clicked.connect(dialog.accept)
+ b.setDefault(True)
return hbox
default_column_widths = { "history":[40,140,350,140], "contacts":[350,330],
- "receive":[[370],[370,200,130,130],[370,200,130,130]] }
+ "receive":[[370],[370,200,130]] }
class ElectrumWindow(QMainWindow):
self.config = config
self.init_plugins()
- self.wallet.interface.register_callback('updated', self.update_callback)
- self.wallet.interface.register_callback('banner', lambda: self.emit(QtCore.SIGNAL('banner_signal')) )
- self.wallet.interface.register_callback('disconnected', self.update_callback)
- self.wallet.interface.register_callback('disconnecting', self.update_callback)
+ self.create_status_bar()
+
+ self.wallet.interface.register_callback('updated', lambda: self.emit(QtCore.SIGNAL('update_wallet')))
+ self.wallet.interface.register_callback('banner', lambda: self.emit(QtCore.SIGNAL('banner_signal')))
+ self.wallet.interface.register_callback('disconnected', lambda: self.emit(QtCore.SIGNAL('update_status')))
+ self.wallet.interface.register_callback('disconnecting', lambda: self.emit(QtCore.SIGNAL('update_status')))
self.expert_mode = config.get('classic_expert_mode', False)
- self.merchant_name = config.get('merchant_name', 'Invoice')
set_language(config.get('language'))
tabs.setMinimumSize(600, 400)
tabs.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
self.setCentralWidget(tabs)
- self.create_status_bar()
g = self.config.get("winpos-qt",[100, 100, 840, 400])
self.setGeometry(g[0], g[1], g[2], g[3])
QShortcut(QKeySequence("Ctrl+PgUp"), self, lambda: tabs.setCurrentIndex( (tabs.currentIndex() - 1 )%tabs.count() ))
QShortcut(QKeySequence("Ctrl+PgDown"), self, lambda: tabs.setCurrentIndex( (tabs.currentIndex() + 1 )%tabs.count() ))
- self.connect(self, QtCore.SIGNAL('updatesignal'), self.update_wallet)
+ self.connect(self, QtCore.SIGNAL('update_wallet'), self.update_wallet)
+ self.connect(self, QtCore.SIGNAL('update_status'), self.update_status)
self.connect(self, QtCore.SIGNAL('banner_signal'), lambda: self.console.showMessage(self.wallet.banner) )
self.history_list.setFocus(True)
self.payto_e.setText(s)
- def update_callback(self):
- self.emit(QtCore.SIGNAL('updatesignal'))
- def update_wallet(self):
+ def update_status(self):
if self.wallet.interface and self.wallet.interface.is_connected:
if not self.wallet.up_to_date:
text = _("Synchronizing...")
self.statusBar().showMessage(text)
self.status_button.setIcon( icon )
+ def update_wallet(self):
+ self.update_status()
if self.wallet.up_to_date or not self.wallet.interface.is_connected:
self.update_history_tab()
self.update_receive_tab()
def show_tx_details(self, tx):
- dialog = QDialog(None)
+ dialog = QDialog(self)
dialog.setModal(1)
dialog.setWindowTitle(_("Transaction Details"))
vbox = QVBoxLayout()
text = unicode( item.text(2) )
if text:
self.wallet.labels[tx_hash] = text
+ # Label changed
+ self.run_hook('label_changed',(self, str(tx_hash), text))
+
item.setForeground(2, QBrush(QColor('black')))
else:
if s: self.wallet.labels.pop(tx_hash)
def edit_label(self, is_recv):
l = self.receive_list if is_recv else self.contacts_list
- c = 2 if is_recv else 1
item = l.currentItem()
item.setFlags(Qt.ItemIsEditable|Qt.ItemIsSelectable | Qt.ItemIsUserCheckable | Qt.ItemIsEnabled | Qt.ItemIsDragEnabled)
- l.editItem( item, c )
+ l.editItem( item, 1 )
item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsUserCheckable | Qt.ItemIsEnabled | Qt.ItemIsDragEnabled)
if old_addr != addr:
self.wallet.labels[addr] = text
changed = True
+ self.run_hook('label_changed',(self, addr, text))
else:
print_error("Error: This is one of your aliases")
label = self.wallet.labels.get(addr,'')
self.completions.setStringList(l)
+ def protected(func):
+ return lambda s, *args: s.do_protect(func, args)
- def do_send(self):
+
+ @protected
+ def do_send(self, password):
label = unicode( self.message_e.text() )
r = unicode( self.payto_e.text() )
QMessageBox.warning(self, _('Error'), _('Invalid Fee'), _('OK'))
return
- if self.wallet.use_encryption:
- password = self.password_dialog()
- if not password:
- return
- else:
- password = None
-
try:
tx = self.wallet.mktx( [(to_address, amount)], password, fee)
except BaseException, e:
self.show_message(str(e))
return
- self.run_hook('send_tx', (wallet, self, tx))
+ self.run_hook('send_tx', (self.wallet, self, tx))
if label:
self.wallet.labels[tx.hash()] = label
def create_receive_tab(self):
- l,w,hbox = self.create_list_tab([ _('Address'), _('Label'), _(''), _('Balance'), _('Tx')])
+ l,w,hbox = self.create_list_tab([ _('Address'), _('Label'), _('Balance'), _('Tx')])
l.setContextMenuPolicy(Qt.CustomContextMenu)
l.customContextMenuRequested.connect(self.create_receive_menu)
self.connect(l, SIGNAL('itemDoubleClicked(QTreeWidgetItem*, int)'), lambda a, b: self.address_label_clicked(a,b,l,0,1))
item = self.receive_list.itemAt(position)
if not item: return
addr = unicode(item.text(0))
+ if not is_valid(addr):
+ item.setExpanded(not item.isExpanded())
+ return
menu = QMenu()
menu.addAction(_("Copy to clipboard"), lambda: self.app.clipboard().setText(addr))
- menu.addAction(_("QR code"), lambda: ElectrumWindow.show_qrcode("bitcoin:" + addr, _("Address")) )
+ menu.addAction(_("QR code"), lambda: self.show_qrcode("bitcoin:" + addr, _("Address")) )
menu.addAction(_("Edit label"), lambda: self.edit_label(True))
- menu.addAction(_("Private key"), lambda: self.view_private_key(addr))
+ menu.addAction(_("Private key"), lambda: self.show_private_key(addr))
menu.addAction(_("Sign message"), lambda: self.sign_message(addr))
if addr in self.wallet.imported_keys:
menu.addAction(_("Remove from wallet"), lambda: self.delete_imported_key(addr))
def update_receive_item(self, item):
+ item.setFont(0, QFont(MONOSPACE_FONT))
address = str(item.data(0,0).toString())
label = self.wallet.labels.get(address,'')
item.setData(1,0,label)
c, u = self.wallet.get_addr_balance(address)
balance = format_satoshis( c + u, False, self.wallet.num_zeros )
- item.setData(3,0,balance)
+ item.setData(2,0,balance)
if self.expert_mode:
if address in self.wallet.frozen_addresses:
l = self.receive_list
l.clear()
+ l.setColumnHidden(2, not self.expert_mode)
l.setColumnHidden(3, not self.expert_mode)
- l.setColumnHidden(4, not self.expert_mode)
if not self.expert_mode:
width = self.column_widths['receive'][0][0]
l.setColumnWidth(0, width)
for k, account in self.wallet.accounts.items():
name = account.get('name',str(k))
c,u = self.wallet.get_account_balance(k)
- account_item = QTreeWidgetItem( [ name, '', '', format_satoshis(c+u), ''] )
+ account_item = QTreeWidgetItem( [ name, '', format_satoshis(c+u), ''] )
l.addTopLevelItem(account_item)
account_item.setExpanded(True)
gap = 0
num_tx = '*' if h == ['*'] else "%d"%len(h)
- item = QTreeWidgetItem( [ address, '', '', '', num_tx] )
- item.setFont(0, QFont(MONOSPACE_FONT))
- item.setFont(2, QFont(MONOSPACE_FONT))
+ item = QTreeWidgetItem( [ address, '', '', num_tx] )
self.update_receive_item(item)
if is_red:
item.setBackgroundColor(1, QColor('red'))
if self.wallet.imported_keys:
c,u = self.wallet.get_imported_balance()
- account_item = QTreeWidgetItem( [ _('Imported'), '', '', format_satoshis(c+u), ''] )
+ account_item = QTreeWidgetItem( [ _('Imported'), '', format_satoshis(c+u), ''] )
l.addTopLevelItem(account_item)
account_item.setExpanded(True)
for address in self.wallet.imported_keys.keys():
- item = QTreeWidgetItem( [ address, '', '', '', ''] )
- item.setFont(0, QFont(MONOSPACE_FONT))
- item.setFont(2, QFont(MONOSPACE_FONT))
+ item = QTreeWidgetItem( [ address, '', '', ''] )
self.update_receive_item(item)
account_item.addChild(item)
def create_console_tab(self):
from qt_console import Console
- from electrum import util, bitcoin, commands
self.console = console = Console()
self.console.history = self.config.get("console-history",[])
self.console.history_index = len(self.console.history)
sb.addPermanentWidget( StatusBarButton( QIcon(":icons/lock.png"), _("Password"), lambda: self.change_password_dialog(self.wallet, self) ) )
sb.addPermanentWidget( StatusBarButton( QIcon(":icons/preferences.png"), _("Preferences"), self.settings_dialog ) )
if self.wallet.seed:
- sb.addPermanentWidget( StatusBarButton( QIcon(":icons/seed.png"), _("Seed"), lambda: self.show_seed_dialog(self.wallet, self) ) )
+ sb.addPermanentWidget( StatusBarButton( QIcon(":icons/seed.png"), _("Seed"), self.show_seed_dialog ) )
self.status_button = StatusBarButton( QIcon(":icons/status_disconnected.png"), _("Network"), lambda: self.network_dialog(self.wallet, self) )
sb.addPermanentWidget( self.status_button )
+ self.run_hook('create_status_bar', (sb,))
+
self.setStatusBar(sb)
def go_lite(self):
QMessageBox.warning(self, _('Error'), _('Invalid Address'), _('OK'))
def show_master_public_key(self):
- dialog = QDialog(None)
+ dialog = QDialog(self)
dialog.setModal(1)
dialog.setWindowTitle(_("Master Public Key"))
main_text.setText(self.wallet.get_master_public_key())
main_text.setReadOnly(True)
main_text.setMaximumHeight(170)
- qrw = QRCodeWidget(self.wallet.get_master_public_key(), 6)
+ qrw = QRCodeWidget(self.wallet.get_master_public_key())
ok_button = QPushButton(_("OK"))
ok_button.setDefault(True)
dialog.exec_()
- @classmethod
- def show_seed_dialog(self, wallet, parent=None):
- if not wallet.seed:
+ @protected
+ def show_seed_dialog(self, password):
+ if not self.wallet.seed:
QMessageBox.information(parent, _('Message'), _('No seed'), _('OK'))
return
-
- if wallet.use_encryption:
- password = parent.password_dialog()
- if not password:
- return
- else:
- password = None
-
try:
- seed = wallet.decode_seed(password)
+ seed = self.wallet.decode_seed(password)
except:
QMessageBox.warning(parent, _('Error'), _('Incorrect Password'), _('OK'))
return
+ self.show_seed(seed, self)
- self.show_seed(seed)
@classmethod
- def show_seed(self, seed):
- dialog = QDialog(None)
+ def show_seed(self, seed, parent=None):
+ dialog = QDialog(parent)
dialog.setModal(1)
dialog.setWindowTitle('Electrum' + ' - ' + _('Seed'))
logo.setPixmap(QPixmap(":icons/seed.png").scaledToWidth(56))
logo.setMaximumWidth(60)
- qrw = QRCodeWidget(seed, 4)
+ qrw = QRCodeWidget(seed)
ok_button = QPushButton(_("OK"))
ok_button.setDefault(True)
dialog.setLayout(vbox)
dialog.exec_()
- @staticmethod
- def show_qrcode(data, title = "QR code"):
+ def show_qrcode(self, data, title = "QR code"):
if not data: return
- d = QDialog(None)
+ d = QDialog(self)
d.setModal(1)
d.setWindowTitle(title)
d.setMinimumSize(270, 300)
d.setLayout(vbox)
d.exec_()
- def view_private_key(self,address):
- if not address: return
+
+ def do_protect(self, func, args):
if self.wallet.use_encryption:
password = self.password_dialog()
if not password:
return
else:
password = None
+
+ if args != (False,):
+ args = (self,) + args + (password,)
+ else:
+ args = (self,password)
+ apply( func, args)
+
+ @protected
+ def show_private_key(self, address, password):
+ if not address: return
try:
pk = self.wallet.get_private_key(address, password)
except BaseException, e:
self.show_message(str(e))
return
-
QMessageBox.information(self, _('Private key'), 'Address'+ ': ' + address + '\n\n' + _('Private key') + ': ' + pk, _('OK'))
- def sign_message(self,address):
+ @protected
+ def do_sign(self, address, message, signature, password):
+ try:
+ sig = self.wallet.sign_message(str(address.text()), str(message.toPlainText()), password)
+ signature.setText(sig)
+ except BaseException, e:
+ self.show_message(str(e))
+
+ def sign_message(self, address):
if not address: return
d = QDialog(self)
d.setModal(1)
layout.addWidget(sign_signature, 3, 1)
layout.setRowStretch(3,1)
- def do_sign():
- if self.wallet.use_encryption:
- password = self.password_dialog()
- if not password:
- return
- else:
- password = None
-
- try:
- signature = self.wallet.sign_message(str(sign_address.text()), str(sign_message.toPlainText()), password)
- sign_signature.setText(signature)
- except BaseException, e:
- self.show_message(str(e))
- return
hbox = QHBoxLayout()
b = QPushButton(_("Sign"))
hbox.addWidget(b)
- b.clicked.connect(do_sign)
+ b.clicked.connect(lambda: self.do_sign(sign_address, sign_message, sign_signature))
b = QPushButton(_("Close"))
b.clicked.connect(d.accept)
hbox.addWidget(b)
tree_widget.setColumnWidth(0, 300)
tree_widget.setColumnWidth(1, 50)
- for output in tx.d["outputs"]:
- item = QTreeWidgetItem( ["%s" %(output["address"]), "%s" % ( format_satoshis(output["value"]))] )
+ for address, value in tx.outputs:
+ item = QTreeWidgetItem( [address, "%s" % ( format_satoshis(value))] )
tree_widget.addTopLevelItem(item)
tree_widget.setMaximumHeight(100)
return self.tx_dict_from_text(file_content)
- def sign_raw_transaction(self, tx, input_info):
- if self.wallet.use_encryption:
- password = self.password_dialog()
- if not password:
- return
- else:
- password = None
-
+ @protected
+ def sign_raw_transaction(self, tx, input_info, password):
try:
self.wallet.signrawtransaction(tx, input_info, [], password)
self.create_send_transaction_window(tx_dict)
- def do_export_privkeys(self):
+ @protected
+ def do_export_privkeys(self, password):
self.show_message("%s\n%s\n%s" % (_("WARNING: ALL your private keys are secret."), _("Exposing a single private key can compromise your entire wallet!"), _("In particular, DO NOT use 'redeem private key' services proposed by third parties.")))
- if self.wallet.use_encryption:
- password = self.password_dialog()
- if not password:
- return
- else:
- password = None
try:
select_export = _('Select file to export your private keys to')
fileName = QFileDialog.getSaveFileName(QWidget(), select_export, os.path.expanduser('~/electrum-private-keys.csv'), "*.csv")
QMessageBox.critical(None, _("Unable to import labels"), _("Electrum was unable to import your labels.")+"\n" + str(reason))
-
def do_export_labels(self):
labels = self.wallet.labels
try:
except (IOError, os.error), reason:
QMessageBox.critical(None, "Unable to export labels", _("Electrum was unable to export your labels.")+"\n" + str(reason))
+
def do_export_history(self):
from gui_lite import csv_transaction
csv_transaction(self.wallet)
- def do_import_privkey(self):
+
+ @protected
+ def do_import_privkey(self, password):
if not self.wallet.imported_keys:
r = QMessageBox.question(None, _('Warning'), _('Warning: Imported keys are not recoverable from seed.') + ' ' \
+ _('If you ever need to restore your wallet from its seed, these keys will be lost.') + '\n\n' \
text, ok = QInputDialog.getText(self, _('Import private key'), _('Private Key') + ':')
if not ok: return
sec = str(text).strip()
- if self.wallet.use_encryption:
- password = self.password_dialog()
- if not password:
- return
- else:
- password = None
try:
addr = self.wallet.import_key(sec, password)
if not addr:
except BaseException as e:
QMessageBox.critical(None, _("Unable to import key"), str(e))
+
def settings_dialog(self):
d = QDialog(self)
d.setWindowTitle(_('Electrum Settings'))
vbox = QVBoxLayout()
tabs = QTabWidget(self)
+ self.settings_tab = tabs
vbox.addWidget(tabs)
tab1 = QWidget()
traceback.print_exc(file=sys.stdout)
grid_plugins.setRowStretch(i+1,1)
+ self.run_hook('create_settings_tab', (self,tabs,))
+
vbox.addLayout(ok_cancel_buttons(d))
d.setLayout(vbox)
def show_seed(self):
- ElectrumWindow.show_seed_dialog(self.wallet)
+ ElectrumWindow.show_seed(self.wallet.seed)
def password_dialog(self):
- ElectrumWindow.change_password_dialog(self.wallet)
+ if self.wallet.seed:
+ ElectrumWindow.change_password_dialog(self.wallet)
def restore_wallet(self):