From 4b092628df377f486c43ddbab5c4e02dc96632fc Mon Sep 17 00:00:00 2001 From: Neil Booth Date: Wed, 3 Jun 2015 14:24:15 +0900 Subject: [PATCH] Have transaction_dialog use send_tx() This is working towards showing transactions before asking for passwords. I think it also means the transaction dialog now interacts properly with plugins, whereas it didn't before. send_tx now takes a callback instead of a label, and does not decide on whether to broadast itself; that is left to its caller. broadcast_transaction() takes care of adding the description of the successfully broadcast transaction to the wallet. Previously labels could be added to the wallet even if the broadcast was cancelled by the user or unsuccessful, which doesn't seem right. Lengthen the dialog messages a little, as some window managers lose the "Please Wait" title bar owing to window decorations if the message is too short. --- gui/qt/main_window.py | 54 ++++++++++++++++++------------------ gui/qt/transaction_dialog.py | 10 ++++--- 2 files changed, 33 insertions(+), 31 deletions(-) diff --git a/gui/qt/main_window.py b/gui/qt/main_window.py index 6c16a117..5c4f57bd 100644 --- a/gui/qt/main_window.py +++ b/gui/qt/main_window.py @@ -1071,7 +1071,7 @@ class ElectrumWindow(QMainWindow): r = self.read_send_tab() if not r: return - outputs, fee, label, coins = r + outputs, fee, tx_desc, coins = r try: tx = self.wallet.make_unsigned_transaction(coins, outputs, fee) if not tx: @@ -1094,39 +1094,45 @@ 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()}): return - self.send_tx(tx, label) + def sign_done(success): + if success: + if not tx.is_complete() or self.config.get('show_before_broadcast'): + self.show_transaction(tx) + self.do_clear() + else: + self.broadcast_transaction(tx, tx_desc) + + self.send_tx(tx, sign_done) @protected - def send_tx(self, tx, label, password): + def send_tx(self, tx, callback, password): + '''Sign the transaction in a separate thread. When done, calls + the callback with a success code of True or False. + ''' self.send_button.setDisabled(True) # call hook to see if plugin needs gui interaction run_hook('send_tx', tx) # sign the tx + success = [False] # Array to work around python scoping def sign_thread(): - if self.wallet.is_watching_only(): - return tx - self.wallet.sign_transaction(tx, password) - return tx - - def sign_done(tx): - if label and tx.is_complete(): - self.wallet.set_label(tx.hash(), label) - if not tx.is_complete() or self.config.get('show_before_broadcast'): - self.show_transaction(tx) - self.do_clear() - return - self.broadcast_transaction(tx) + if not self.wallet.is_watching_only(): + self.wallet.sign_transaction(tx, password) + def on_sign_successful(ret): + success[0] = True + def on_dialog_close(): + self.send_button.setDisabled(False) + callback(success[0]) # keep a reference to WaitingDialog or the gui might crash - self.waiting_dialog = WaitingDialog(self, 'Signing..', sign_thread, sign_done, lambda: self.send_button.setDisabled(False)) + self.waiting_dialog = WaitingDialog(self, 'Signing transaction...', sign_thread, on_sign_successful, on_dialog_close) self.waiting_dialog.start() - def broadcast_transaction(self, tx): + def broadcast_transaction(self, tx, tx_desc): def broadcast_thread(): # non-GUI thread @@ -1151,6 +1157,8 @@ class ElectrumWindow(QMainWindow): def broadcast_done(status, msg): # GUI thread if status: + if tx_desc is not None and tx.is_complete(): + self.wallet.set_label(tx.hash(), tx_desc) QMessageBox.information(self, '', _('Payment sent.') + '\n' + msg, _('OK')) self.update_invoices_list() self.do_clear() @@ -1158,7 +1166,7 @@ class ElectrumWindow(QMainWindow): QMessageBox.warning(self, _('Error'), msg, _('OK')) self.send_button.setDisabled(False) - self.waiting_dialog = WaitingDialog(self, 'Broadcasting..', broadcast_thread, broadcast_done) + self.waiting_dialog = WaitingDialog(self, 'Broadcasting transaction...', broadcast_thread, broadcast_done) self.waiting_dialog.start() @@ -2109,14 +2117,6 @@ class ElectrumWindow(QMainWindow): return self.tx_from_text(file_content) - @protected - def sign_raw_transaction(self, tx, password): - try: - self.wallet.sign_transaction(tx, password) - except Exception as e: - traceback.print_exc(file=sys.stdout) - QMessageBox.warning(self, _("Error"), str(e)) - def do_process_from_text(self): text = text_dialog(self, _('Input raw transaction'), _("Transaction:"), _("Load transaction")) if not text: diff --git a/gui/qt/transaction_dialog.py b/gui/qt/transaction_dialog.py index d2f59208..3e239d98 100644 --- a/gui/qt/transaction_dialog.py +++ b/gui/qt/transaction_dialog.py @@ -103,7 +103,7 @@ class TxDialog(QWidget): self.update() def do_broadcast(self): - self.parent.broadcast_transaction(self.tx) + self.parent.broadcast_transaction(self.tx, None) self.saved = True def close(self): @@ -124,9 +124,11 @@ class TxDialog(QWidget): def sign(self): - self.parent.sign_raw_transaction(self.tx) - self.update() - + def sign_done(success): + self.sign_button.setDisabled(False) + self.update() + self.sign_button.setDisabled(True) + self.parent.send_tx(self.tx, sign_done) def save(self): name = 'signed_%s.txn' % (self.tx.hash()[0:8]) if self.tx.is_complete() else 'unsigned.txn'