URI: 
       tUnregister network callbacks from QT gui - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit ae4cfc9f0b69a3e12cb3e468c4841579c11b385d
   DIR parent 0d4de870a5159d491b604d29780f6bfb539c49f3
  HTML 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:
         M gui/android.py                      |       4 ++--
         M gui/gtk.py                          |       4 ++--
         M gui/kivy/main_window.py             |      13 +++++++++----
         M gui/qt/main_window.py               |      40 ++++++++++++++++++++-----------
         M gui/stdio.py                        |      17 +++++++----------
         M gui/text.py                         |       4 ++--
         M lib/network.py                      |      13 ++++++++++---
         M scripts/merchant/merchant.py        |       4 ++--
       
       8 files changed, 60 insertions(+), 39 deletions(-)
       ---
   DIR diff --git a/gui/android.py b/gui/android.py
       t@@ -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
       t@@ -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')
        
   DIR diff --git a/gui/gtk.py b/gui/gtk.py
       t@@ -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():
       t@@ -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):
   DIR diff --git a/gui/kivy/main_window.py b/gui/kivy/main_window.py
       t@@ -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):
   DIR diff --git a/gui/qt/main_window.py b/gui/qt/main_window.py
       t@@ -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)
        
       t@@ -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
       t@@ -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
       t@@ -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()
   DIR diff --git a/gui/stdio.py b/gui/stdio.py
       t@@ -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"), \
       t@@ -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: ")
       t@@ -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:
   DIR diff --git a/gui/text.py b/gui/text.py
       t@@ -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)
       t@@ -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()
   DIR diff --git a/lib/network.py b/lib/network.py
       t@@ -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:
   DIR diff --git a/scripts/merchant/merchant.py b/scripts/merchant/merchant.py
       t@@ -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')
       t@@ -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()