electrum

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

commit ae4cfc9f0b69a3e12cb3e468c4841579c11b385d
parent 0d4de870a5159d491b604d29780f6bfb539c49f3
Author: Neil Booth <kyuupichan@gmail.com>
Date:   Fri, 13 Nov 2015 22:42:21 +0900

Unregister network callbacks from QT gui

Rework the callback system in QT to make this easy, and avoid
leaking window references that prevent the window from being
GC-ed on close

Diffstat:
Mgui/android.py | 4++--
Mgui/gtk.py | 4++--
Mgui/kivy/main_window.py | 13+++++++++----
Mgui/qt/main_window.py | 40++++++++++++++++++++++++++--------------
Mgui/stdio.py | 17+++++++----------
Mgui/text.py | 4++--
Mlib/network.py | 13++++++++++---
Mscripts/merchant/merchant.py | 4++--
8 files changed, 60 insertions(+), 39 deletions(-)

diff --git a/gui/android.py b/gui/android.py @@ -491,7 +491,7 @@ def make_new_contact(): do_refresh = False -def update_callback(): +def update_callback(event): global do_refresh print "gui callback", network.is_connected() do_refresh = True @@ -908,7 +908,7 @@ class ElectrumGui: global wallet, network, contacts, config network = _network config = _config - network.register_callback('updated', update_callback) + network.register_callback(update_callback, ['updated']) contacts = util.StoreDict(config, 'contacts') diff --git a/gui/gtk.py b/gui/gtk.py @@ -551,7 +551,7 @@ class ElectrumWindow: self.context_id = self.status_bar.get_context_id("statusbar") self.update_status_bar() - self.network.register_callback('updated', self.update_callback) + self.network.register_callback(self.update_callback, ['updated']) def update_status_bar_thread(): @@ -585,7 +585,7 @@ class ElectrumWindow: thread.start_new_thread(check_recipient_thread, ()) self.notebook.set_current_page(0) - def update_callback(self): + def update_callback(self, event): self.wallet_updated = True def do_update_password(self, button, wallet): diff --git a/gui/kivy/main_window.py b/gui/kivy/main_window.py @@ -382,13 +382,18 @@ class ElectrumWindow(App): # connect callbacks if self.network: - self.network.register_callback('updated', self._trigger_update_wallet) - self.network.register_callback('status', self._trigger_update_status) - self.network.register_callback('new_transaction', self._trigger_notify_transactions) + interests = ['update', 'status', 'new_transaction'] + self.network.register_callback(self.on_network, interests) self.wallet = None - + def on_network(self, event, *args): + if event == 'updated': + self._trigger_update_wallet() + elif event == 'status': + self._trigger_update_status() + elif event == 'new_transaction': + self._trigger_notify_transactions(*args) @profiler def load_wallet(self, wallet): diff --git a/gui/qt/main_window.py b/gui/qt/main_window.py @@ -160,12 +160,10 @@ class ElectrumWindow(QMainWindow, PrintError): # network callbacks if self.network: - self.network.register_callback('updated', lambda: self.need_update.set()) - self.network.register_callback('new_transaction', self.new_transaction) - self.register_callback('status', self.update_status) - self.register_callback('banner', self.console.showMessage) - self.register_callback('verified', self.history_list.update_item) - + self.connect(self, QtCore.SIGNAL('network'), self.on_network_qt) + interests = ['updated', 'new_transaction', 'status', + 'banner', 'verified'] + self.network.register_callback(self.on_network, interests) # set initial message self.console.showMessage(self.network.banner) @@ -194,11 +192,27 @@ class ElectrumWindow(QMainWindow, PrintError): self.show() self.raise_() - def register_callback(self, name, method): - """ run callback in the qt thread """ - self.connect(self, QtCore.SIGNAL(name), method) - self.network.register_callback(name, lambda *params: self.emit(QtCore.SIGNAL(name), *params)) + def on_network(self, event, *args): + if event == 'updated': + self.need_update.set() + elif event == 'new_transaction': + self.tx_notifications.append(args[0]) + elif event in ['status', 'banner', 'verified']: + # Handle in GUI thread + self.emit(QtCore.SIGNAL('network'), event, *args) + else: + self.print_error("unexpected network message:", event, args) + def on_network_qt(self, event, *args): + # Handle a network message in the GUI thread + if event == 'status': + self.update_status() + elif event == 'banner': + self.console.showMessage(args[0]) + elif event == 'verified': + self.history_list.update_item(*args) + else: + self.print_error("unexpected network_qt signal:", event, args) def fetch_alias(self): self.alias_info = None @@ -418,10 +432,6 @@ class ElectrumWindow(QMainWindow, PrintError): ]) QMessageBox.information(self, "Electrum - " + _("Reporting Bugs"), msg) - - def new_transaction(self, tx): - self.tx_notifications.append(tx) - def notify_transactions(self): if not self.network or not self.network.is_connected(): return @@ -2800,6 +2810,8 @@ class ElectrumWindow(QMainWindow, PrintError): NetworkDialog(self.wallet.network, self.config, self).do_exec() def closeEvent(self, event): + if self.network: + self.network.unregister_callback(self.on_network) self.config.set_key("is_maximized", self.isMaximized()) if not self.isMaximized(): g = self.geometry() diff --git a/gui/stdio.py b/gui/stdio.py @@ -34,10 +34,7 @@ class ElectrumGui: self.wallet.start_threads(network) self.contacts = StoreDict(self.config, 'contacts') - self.wallet.network.register_callback('updated', self.updated) - - self.wallet.network.register_callback('peers', self.peers) - self.wallet.network.register_callback('banner', self.print_banner) + network.register_callback(self.on_network, ['updated', 'banner']) self.commands = [_("[h] - displays this help text"), \ _("[i] - display transaction history"), \ _("[o] - enter payment order"), \ @@ -49,6 +46,12 @@ class ElectrumGui: _("[q] - quit") ] self.num_commands = len(self.commands) + def on_network(self, event, *args): + if event == 'updated': + self.updated() + elif event == 'banner': + self.print_banner() + def main_command(self): self.print_balance() c = raw_input("enter command: ") @@ -65,12 +68,6 @@ class ElectrumGui: elif c == "q" : self.done = 1 else: self.print_commands() - def peers(self): - print("got peers list:") - l = filter_protocol(self.wallet.network.get_servers(), 's') - for s in l: - print (s) - def updated(self): s = self.get_balance() if s != self.last_balance: diff --git a/gui/text.py b/gui/text.py @@ -53,7 +53,7 @@ class ElectrumGui: self.history = None if self.network: - self.network.register_callback('updated', self.update) + self.network.register_callback(self.update, ['updated']) self.tab_names = [_("History"), _("Send"), _("Receive"), _("Addresses"), _("Contacts"), _("Banner")] self.num_tabs = len(self.tab_names) @@ -80,7 +80,7 @@ class ElectrumGui: self.set_cursor(0) return s - def update(self): + def update(self, event): self.update_history() if self.tab == 0: self.print_history() diff --git a/lib/network.py b/lib/network.py @@ -194,14 +194,21 @@ class Network(util.DaemonThread): if self.plugins: self.plugins.set_network(self) - def register_callback(self, event, callback): + def register_callback(self, callback, events): with self.lock: - self.callbacks[event].append(callback) + for event in events: + self.callbacks[event].append(callback) + + def unregister_callback(self, callback): + with self.lock: + for callbacks in self.callbacks.values(): + if callback in callbacks: + callbacks.remove(callback) def trigger_callback(self, event, *args): with self.lock: callbacks = self.callbacks[event][:] - [callback(*args) for callback in callbacks] + [callback(event, *args) for callback in callbacks] def read_recent_servers(self): if not self.config.path: diff --git a/scripts/merchant/merchant.py b/scripts/merchant/merchant.py @@ -78,7 +78,7 @@ def row_to_dict(x): # this process detects when addresses have received payments -def on_wallet_update(): +def on_wallet_update(event): for addr, v in pending_requests.items(): h = wallet.history.get(addr, []) requested_amount = v.get('requested') @@ -280,7 +280,7 @@ if __name__ == '__main__': wallet.synchronize = lambda: None # prevent address creation by the wallet wallet.start_threads(network) - network.register_callback('updated', on_wallet_update) + network.register_callback(on_wallet_update, ['updated']) threading.Thread(target=db_thread, args=()).start()