electrum

Electrum Bitcoin wallet
git clone https://git.parazyd.org/electrum
Log | Files | Refs | Submodules

commit ffd081ac2157138533abd1110dd2cacb9c18ddf4
parent 64887f7a744f94bc98effc3575364d0e2da62120
Author: Neil Booth <kyuupichan@gmail.com>
Date:   Wed, 23 Dec 2015 22:10:11 +0900

Clean up WaitingDialog

Prevent GC so callers don't have to.

Diffstat:
Mgui/qt/main_window.py | 21++++++++-------------
Mgui/qt/util.py | 79+++++++++++++++++++++++++++++++++++++++++--------------------------------------
Mplugins/audio_modem/qt.py | 42+++++++++++++++---------------------------
Mplugins/trustedcoin/qt.py | 9++++-----
4 files changed, 68 insertions(+), 83 deletions(-)

diff --git a/gui/qt/main_window.py b/gui/qt/main_window.py @@ -1280,16 +1280,14 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError): def sign_thread(): if not self.wallet.is_watching_only(): self.wallet.sign_transaction(tx, password) - def on_sign_successful(ret): + def on_signed(ret): success[0] = True - def on_dialog_close(): + def on_finished(): self.send_button.setDisabled(False) callback(success[0]) - # keep a reference to WaitingDialog or the gui might crash - self.waiting_dialog = WaitingDialog(parent, 'Signing transaction...', sign_thread, on_sign_successful, on_dialog_close) - self.waiting_dialog.start() - + WaitingDialog(parent, _('Signing transaction...'), sign_thread, + on_success=on_signed, on_finished=on_finished) def broadcast_transaction(self, tx, tx_desc, parent=None): @@ -1325,12 +1323,9 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError): self.show_error(msg, parent=parent) self.send_button.setDisabled(False) - if parent == None: - parent = self - self.waiting_dialog = WaitingDialog(parent, 'Broadcasting transaction...', broadcast_thread, broadcast_done) - self.waiting_dialog.start() - - + parent = parent or self + WaitingDialog(parent, _('Broadcasting transaction...'), + broadcast_thread, broadcast_done) def prepare_for_payment_request(self): self.tabs.setCurrentIndex(1) @@ -2238,7 +2233,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError): from electrum import qrscanner try: data = qrscanner.scan_qr(self.config) - except e: + except BaseException as e: self.show_error(str(e)) return if not data: diff --git a/gui/qt/util.py b/gui/qt/util.py @@ -21,44 +21,7 @@ RED_FG = "QWidget {color:red;}" BLUE_FG = "QWidget {color:blue;}" BLACK_FG = "QWidget {color:black;}" - -class WaitingDialog(QThread): - def __init__(self, parent, message, run_task, on_success=None, on_complete=None): - QThread.__init__(self) - self.parent = parent - self.d = QDialog(parent) - self.d.setWindowTitle('Please wait') - l = QLabel(message) - vbox = QVBoxLayout(self.d) - vbox.addWidget(l) - self.run_task = run_task - self.on_success = on_success - self.on_complete = on_complete - self.d.connect(self.d, SIGNAL('done'), self.close) - self.d.show() - - def run(self): - self.error = None - try: - self.result = self.run_task() - except BaseException as e: - traceback.print_exc(file=sys.stdout) - self.error = str(e) - self.d.emit(SIGNAL('done')) - - def close(self): - self.d.accept() - if self.error: - QMessageBox.warning(self.parent, _('Error'), self.error, _('OK')) - else: - if self.on_success: - if type(self.result) is not tuple: - self.result = (self.result,) - self.on_success(*self.result) - - if self.on_complete: - self.on_complete() - +dialogs = [] class Timer(QThread): stopped = False @@ -234,6 +197,46 @@ class WindowModalDialog(QDialog): if title: self.setWindowTitle(title) +class WaitingDialog(QThread, MessageBoxMixin): + '''Shows a please wait dialog whilst runnning a task. It is not + necessary to maintain a reference to this dialog.''' + def __init__(self, parent, message, task, on_success=None, + on_finished=None): + global dialogs + dialogs.append(self) # Prevent GC + QThread.__init__(self) + self.task = task + self.on_success = on_success + self.on_finished = on_finished + self.dialog = WindowModalDialog(parent, _("Please wait")) + vbox = QVBoxLayout(self.dialog) + vbox.addWidget(QLabel(message)) + self.dialog.show() + self.dialog.connect(self, SIGNAL("finished()"), self.finished) + self.start() + + def run(self): + self.error = None + try: + self.result = self.task() + except BaseException as e: + traceback.print_exc(file=sys.stdout) + self.error = str(e) + + def finished(self): + global dialogs + dialogs.remove(self) + if self.error: + self.show_error(self.error, parent=self.dialog.parent()) + elif self.on_success: + result = self.result + if type(result) is not tuple: + result = (result,) + self.on_success(*result) + if self.on_finished: + self.on_finished() + self.dialog.accept() + def line_dialog(parent, title, label, ok_label, default=None): dialog = WindowModalDialog(parent, title) dialog.setMinimumWidth(500) diff --git a/plugins/audio_modem/qt.py b/plugins/audio_modem/qt.py @@ -1,5 +1,4 @@ from functools import partial -import traceback import zlib import json from io import BytesIO @@ -75,24 +74,20 @@ class Plugin(BasePlugin): def handler(): blob = json.dumps(dialog.tx.as_dict()) - self.sender = self._send(parent=dialog, blob=blob) - self.sender.start() + self._send(parent=dialog, blob=blob) b.clicked.connect(handler) dialog.sharing_buttons.insert(-1, b) @hook def scan_text_edit(self, parent): - def handler(): - self.receiver = self._recv(parent=parent) - self.receiver.start() - parent.addButton(':icons/microphone.png', handler, _("Read from microphone")) + parent.addButton(':icons/microphone.png', partial(self._recv, parent), + _("Read from microphone")) @hook def show_text_edit(self, parent): def handler(): blob = str(parent.toPlainText()) - self.sender = self._send(parent=parent, blob=blob) - self.sender.start() + self._send(parent=parent, blob=blob) parent.addButton(':icons/speaker.png', handler, _("Send to speaker")) def _audio_interface(self): @@ -101,31 +96,25 @@ class Plugin(BasePlugin): def _send(self, parent, blob): def sender_thread(): - try: - with self._audio_interface() as interface: - src = BytesIO(blob) - dst = interface.player() - amodem.main.send(config=self.modem_config, src=src, dst=dst) - except Exception: - traceback.print_exc() + with self._audio_interface() as interface: + src = BytesIO(blob) + dst = interface.player() + amodem.main.send(config=self.modem_config, src=src, dst=dst) print_msg('Sending:', repr(blob)) blob = zlib.compress(blob) kbps = self.modem_config.modem_bps / 1e3 msg = 'Sending to Audio MODEM ({0:.1f} kbps)...'.format(kbps) - return WaitingDialog(parent=parent, message=msg, run_task=sender_thread) + WaitingDialog(parent, msg, sender_thread) def _recv(self, parent): def receiver_thread(): - try: - with self._audio_interface() as interface: - src = interface.recorder() - dst = BytesIO() - amodem.main.recv(config=self.modem_config, src=src, dst=dst) - return dst.getvalue() - except Exception: - traceback.print_exc() + with self._audio_interface() as interface: + src = interface.recorder() + dst = BytesIO() + amodem.main.recv(config=self.modem_config, src=src, dst=dst) + return dst.getvalue() def on_success(blob): if blob: @@ -135,5 +124,4 @@ class Plugin(BasePlugin): kbps = self.modem_config.modem_bps / 1e3 msg = 'Receiving from Audio MODEM ({0:.1f} kbps)...'.format(kbps) - return WaitingDialog(parent=parent, message=msg, - run_task=receiver_thread, on_success=on_success) + WaitingDialog(parent, msg, receiver_thread, on_success=on_success) diff --git a/plugins/trustedcoin/qt.py b/plugins/trustedcoin/qt.py @@ -92,9 +92,8 @@ class Plugin(TrustedCoinPlugin): if wallet.billing_info is None: # request billing info before forming the transaction task = partial(self.request_billing_info, wallet) - waiting_dialog = WaitingDialog(window, 'please wait...', task) - waiting_dialog.start() - waiting_dialog.wait() + dialog = WaitingDialog(window, 'please wait...', task) + dialog.wait() if wallet.billing_info is None: window.show_message('Could not contact server') return True @@ -103,8 +102,8 @@ class Plugin(TrustedCoinPlugin): def settings_dialog(self, window): task = partial(self.request_billing_info, window.wallet) - self.waiting_dialog = WaitingDialog(window, 'please wait...', task, partial(self.show_settings_dialog, window)) - self.waiting_dialog.start() + WaitingDialog(window, 'please wait...', task, + on_success=partial(self.show_settings_dialog, window)) def show_settings_dialog(self, window, success): if not success: