Browse Source

Have show-before-broadcast defer password request

Show-before-send currently asks for the password
and creates a signed tx before showing anything.

This is a little unnerving as you can't see what
you're being asked to sign.

This patch does a few things:

- Adds a description label to the TX dialog
- You see the tx before being asked for password;
  that is only requested on pressing Sign
- in show-before-broadcast mode, the Send button
  text is instead "Show...".  Hook up this button
  text change to the prefs dialog too.
- Remove many redundant imports.  In particular
  PyQ4 is checked in main_window.py so no need
  in tx_dialog too.

Note I had to remove disabling of the Sign button,
because if the user presses "cancel" nothing will
re-enable it.
283
Neil Booth 10 years ago
parent
commit
56488daf04
  1. 62
      gui/qt/main_window.py
  2. 33
      gui/qt/transaction_dialog.py

62
gui/qt/main_window.py

@ -16,13 +16,9 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import sys, time, re, threading import sys, time, threading
from electrum.i18n import _, set_language import os.path, json, traceback
from electrum.util import block_explorer, block_explorer_info, block_explorer_URL
from electrum.util import print_error, print_msg
import os.path, json, ast, traceback
import shutil import shutil
import StringIO
import PyQt4 import PyQt4
@ -35,6 +31,9 @@ from electrum.plugins import run_hook
import icons_rc import icons_rc
from electrum.i18n import _
from electrum.util import block_explorer, block_explorer_info, block_explorer_URL
from electrum.util import print_error, print_msg
from electrum.util import format_satoshis, format_satoshis_plain, format_time, NotEnoughFunds, StoreDict from electrum.util import format_satoshis, format_satoshis_plain, format_time, NotEnoughFunds, StoreDict
from electrum import Transaction from electrum import Transaction
from electrum import mnemonic from electrum import mnemonic
@ -299,7 +298,6 @@ class ElectrumWindow(QMainWindow):
def backup_wallet(self): def backup_wallet(self):
import shutil
path = self.wallet.storage.path path = self.wallet.storage.path
wallet_folder = os.path.dirname(path) wallet_folder = os.path.dirname(path)
filename = unicode( QFileDialog.getSaveFileName(self, _('Enter a filename for the copy of your wallet'), wallet_folder) ) filename = unicode( QFileDialog.getSaveFileName(self, _('Enter a filename for the copy of your wallet'), wallet_folder) )
@ -570,9 +568,10 @@ class ElectrumWindow(QMainWindow):
d = address_dialog.AddressDialog(addr, self) d = address_dialog.AddressDialog(addr, self)
d.exec_() d.exec_()
def show_transaction(self, tx): def show_transaction(self, tx, tx_desc = None):
'''tx_desc is set only for txs created in the Send tab'''
import transaction_dialog import transaction_dialog
d = transaction_dialog.TxDialog(tx, self) d = transaction_dialog.TxDialog(tx, self, tx_desc)
d.show() d.show()
def update_history_tab(self): def update_history_tab(self):
@ -835,6 +834,21 @@ class ElectrumWindow(QMainWindow):
if self.qr_window and self.qr_window.isVisible(): if self.qr_window and self.qr_window.isVisible():
self.qr_window.set_content(addr, amount, message, uri) self.qr_window.set_content(addr, amount, message, uri)
def show_before_broadcast(self):
return self.config.get('show_before_broadcast', False)
def set_show_before_broadcast(self, show):
self.config.set_key('show_before_broadcast', bool(show))
self.set_send_button_text()
def set_send_button_text(self):
if self.show_before_broadcast():
text = _("Show...")
elif self.wallet.is_watching_only():
text = _("Create unsigned transaction")
else:
text = _("Send")
self.send_button.setText(text)
def create_send_tab(self): def create_send_tab(self):
self.send_grid = grid = QGridLayout() self.send_grid = grid = QGridLayout()
@ -888,7 +902,8 @@ class ElectrumWindow(QMainWindow):
grid.addWidget(self.fee_e_label, 5, 0) grid.addWidget(self.fee_e_label, 5, 0)
grid.addWidget(self.fee_e, 5, 1, 1, 2) grid.addWidget(self.fee_e, 5, 1, 1, 2)
self.send_button = EnterButton(_("Send"), self.do_send) self.send_button = EnterButton('', self.do_send)
self.set_send_button_text()
self.clear_button = EnterButton(_("Clear"), self.do_clear) self.clear_button = EnterButton(_("Clear"), self.do_clear)
buttons = QHBoxLayout() buttons = QHBoxLayout()
buttons.addStretch(1) buttons.addStretch(1)
@ -1096,15 +1111,17 @@ class ElectrumWindow(QMainWindow):
if not self.question(_("The fee for this transaction seems unusually high.\nAre you really sure you want to pay %(fee)s in fees?")%{ 'fee' : self.format_amount(fee) + ' '+ self.base_unit()}): if not self.question(_("The fee for this transaction seems unusually high.\nAre you really sure you want to pay %(fee)s in fees?")%{ 'fee' : self.format_amount(fee) + ' '+ self.base_unit()}):
return return
def sign_done(success): if self.show_before_broadcast():
if success: self.show_transaction(tx, tx_desc)
if not tx.is_complete() or self.config.get('show_before_broadcast'): else:
self.show_transaction(tx) def sign_done(success):
self.do_clear() if success:
else: if not tx.is_complete():
self.broadcast_transaction(tx, tx_desc) self.show_transaction(tx)
self.do_clear()
self.send_tx(tx, sign_done) else:
self.broadcast_transaction(tx, tx_desc)
self.send_tx(tx, sign_done)
@protected @protected
@ -1133,7 +1150,6 @@ class ElectrumWindow(QMainWindow):
self.waiting_dialog.start() self.waiting_dialog.start()
def broadcast_transaction(self, tx, tx_desc): def broadcast_transaction(self, tx, tx_desc):
def broadcast_thread(): def broadcast_thread():
@ -1670,7 +1686,7 @@ class ElectrumWindow(QMainWindow):
def update_buttons_on_seed(self): def update_buttons_on_seed(self):
self.seed_button.setVisible(self.wallet.has_seed()) self.seed_button.setVisible(self.wallet.has_seed())
self.password_button.setVisible(self.wallet.can_change_password()) self.password_button.setVisible(self.wallet.can_change_password())
self.send_button.setText(_("Create unsigned transaction") if self.wallet.is_watching_only() else _("Send")) self.set_send_button_text()
def change_password_dialog(self): def change_password_dialog(self):
@ -2539,8 +2555,8 @@ class ElectrumWindow(QMainWindow):
widgets.append((usechange_cb, None, usechange_help)) widgets.append((usechange_cb, None, usechange_help))
showtx_cb = QCheckBox(_('Show transaction before broadcast')) showtx_cb = QCheckBox(_('Show transaction before broadcast'))
showtx_cb.setChecked(self.config.get('show_before_broadcast', False)) showtx_cb.setChecked(self.show_before_broadcast())
showtx_cb.stateChanged.connect(lambda x: self.config.set_key('show_before_broadcast', showtx_cb.isChecked())) showtx_cb.stateChanged.connect(lambda x: self.set_show_before_broadcast(showtx_cb.isChecked()))
showtx_help = HelpButton(_('Display the details of your transactions before broadcasting it.')) showtx_help = HelpButton(_('Display the details of your transactions before broadcasting it.'))
widgets.append((showtx_cb, None, showtx_help)) widgets.append((showtx_cb, None, showtx_help))

33
gui/qt/transaction_dialog.py

@ -16,25 +16,17 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import sys, time, datetime, re, threading import datetime
from electrum.i18n import _, set_language import json
from electrum.util import print_error, print_msg
import os.path, json, ast, traceback
import shutil
import StringIO
try:
import PyQt4
except Exception:
sys.exit("Error: Could not import PyQt4 on Linux systems, you may try 'sudo apt-get install python-qt4'")
import PyQt4
from PyQt4.QtGui import * from PyQt4.QtGui import *
from PyQt4.QtCore import * from PyQt4.QtCore import *
import PyQt4.QtCore as QtCore import PyQt4.QtCore as QtCore
from electrum import transaction from electrum import transaction
from electrum.bitcoin import base_encode from electrum.bitcoin import base_encode
from electrum.i18n import _
from electrum.plugins import run_hook from electrum.plugins import run_hook
from util import * from util import *
@ -42,12 +34,16 @@ from util import *
class TxDialog(QWidget): class TxDialog(QWidget):
def __init__(self, tx, parent): def __init__(self, tx, parent, desc=None):
'''Transactions in the wallet will show their description.
Pass desc to give a description for txs not yet in the wallet.
'''
self.tx = tx self.tx = tx
tx_dict = tx.as_dict() tx_dict = tx.as_dict()
self.parent = parent self.parent = parent
self.wallet = parent.wallet self.wallet = parent.wallet
self.saved = True self.saved = True
self.desc = desc
QWidget.__init__(self) QWidget.__init__(self)
self.setMinimumWidth(600) self.setMinimumWidth(600)
@ -65,6 +61,8 @@ class TxDialog(QWidget):
self.status_label = QLabel() self.status_label = QLabel()
vbox.addWidget(self.status_label) vbox.addWidget(self.status_label)
self.tx_desc = QLabel()
vbox.addWidget(self.tx_desc)
self.date_label = QLabel() self.date_label = QLabel()
vbox.addWidget(self.date_label) vbox.addWidget(self.date_label)
self.amount_label = QLabel() self.amount_label = QLabel()
@ -125,9 +123,7 @@ class TxDialog(QWidget):
def sign(self): def sign(self):
def sign_done(success): def sign_done(success):
self.sign_button.setDisabled(False)
self.update() self.update()
self.sign_button.setDisabled(True)
self.parent.send_tx(self.tx, sign_done) self.parent.send_tx(self.tx, sign_done)
def save(self): def save(self):
@ -143,6 +139,7 @@ class TxDialog(QWidget):
def update(self): def update(self):
is_relevant, is_mine, v, fee = self.wallet.get_wallet_delta(self.tx) is_relevant, is_mine, v, fee = self.wallet.get_wallet_delta(self.tx)
tx_hash = self.tx.hash() tx_hash = self.tx.hash()
desc = self.desc
if self.wallet.can_sign(self.tx): if self.wallet.can_sign(self.tx):
self.sign_button.show() self.sign_button.show()
else: else:
@ -152,6 +149,7 @@ class TxDialog(QWidget):
status = _("Signed") status = _("Signed")
if tx_hash in self.wallet.transactions.keys(): if tx_hash in self.wallet.transactions.keys():
desc, is_default = self.wallet.get_label(tx_hash)
conf, timestamp = self.wallet.get_confirmations(tx_hash) conf, timestamp = self.wallet.get_confirmations(tx_hash)
if timestamp: if timestamp:
time_str = datetime.datetime.fromtimestamp(timestamp).isoformat(' ')[:-3] time_str = datetime.datetime.fromtimestamp(timestamp).isoformat(' ')[:-3]
@ -171,6 +169,11 @@ class TxDialog(QWidget):
tx_hash = 'unknown' tx_hash = 'unknown'
self.tx_hash_e.setText(tx_hash) self.tx_hash_e.setText(tx_hash)
if desc is None:
self.tx_desc.hide()
else:
self.tx_desc.setText(_("Description") + ': ' + desc)
self.tx_desc.show()
self.status_label.setText(_('Status:') + ' ' + status) self.status_label.setText(_('Status:') + ' ' + status)
if time_str is not None: if time_str is not None:

Loading…
Cancel
Save