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
This commit is contained in:
Neil Booth 2015-11-13 22:42:21 +09:00
parent 0d4de870a5
commit ae4cfc9f0b
8 changed files with 60 additions and 39 deletions

View File

@ -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')

View File

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

View File

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

View File

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

View File

@ -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:

View File

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

View File

@ -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:

View File

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