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:
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()