URI: 
       tExchange rate plugin fixes for multiple windows - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit f2fb856f1cbe3bf5562664c78e6dfa374d13bb23
   DIR parent 992c70a6885f22150086658cafb931d61240e505
  HTML Author: Neil Booth <kyuupichan@gmail.com>
       Date:   Wed,  2 Sep 2015 20:34:40 +0900
       
       Exchange rate plugin fixes for multiple windows
       
       This should be enough to keep everything working that was working
       before.  The plugin itself needs a lot more work to fix existing
       bugs and be sane.
       
       Diffstat:
         M gui/qt/__init__.py                  |       2 ++
         M gui/qt/history_widget.py            |       2 +-
         M gui/qt/main_window.py               |       2 +-
         M plugins/exchange_rate.py            |     234 ++++++++++++++++---------------
         M plugins/trustedcoin.py              |       2 +-
       
       5 files changed, 128 insertions(+), 114 deletions(-)
       ---
   DIR diff --git a/gui/qt/__init__.py b/gui/qt/__init__.py
       t@@ -201,6 +201,7 @@ class ElectrumGui:
                    self.start_new_window(self.config, full_path)
        
            def new_window(self, path):
       +        # Use a signal as can be called from daemon thread
                self.app.emit(SIGNAL('new_window'), self.config, path)
        
            def start_new_window(self, config, path=None):
       t@@ -215,6 +216,7 @@ class ElectrumGui:
                    if not wallet:
                        return
                    w = ElectrumWindow(config, self.network, self)
       +            run_hook('new_window', w)
                    w.connect_slots(self.timer)
        
                    # load new wallet in gui
   DIR diff --git a/gui/qt/history_widget.py b/gui/qt/history_widget.py
       t@@ -76,7 +76,7 @@ class HistoryWidget(MyTreeWidget):
                    self.insertTopLevelItem(0, item)
                    if current_tx == tx_hash:
                        self.setCurrentItem(item)
       -        run_hook('history_tab_update')
       +        run_hook('history_tab_update', self.parent)
        
            def update_item(self, tx_hash, conf, timestamp):
                icon, time_str = self.get_icon(conf, timestamp)
   DIR diff --git a/gui/qt/main_window.py b/gui/qt/main_window.py
       t@@ -1395,7 +1395,7 @@ class ElectrumWindow(QMainWindow):
                    e.setFrozen(False)
                self.set_pay_from([])
                self.update_status()
       -        run_hook('do_clear')
       +        run_hook('do_clear', self)
        
            def set_frozen_state(self, addrs, freeze):
                self.wallet.set_frozen_state(addrs, freeze)
   DIR diff --git a/plugins/exchange_rate.py b/plugins/exchange_rate.py
       t@@ -81,7 +81,7 @@ class Exchanger(ThreadJob):
                self.parent.refresh_fields()
        
            def run(self):
       -        if self.timeout <= time.time():
       +        if self.parent.gui and self.timeout <= time.time():
                    self.update_rate()
                    self.timeout = time.time() + 150
        
       t@@ -166,47 +166,50 @@ class Plugin(BasePlugin):
                BasePlugin.__init__(self,a,b)
                self.exchange = self.config.get('use_exchange', "Blockchain")
                self.currencies = [self.fiat_unit()]
       -        # Do price discovery
                self.exchanger = Exchanger(self)
       -        self.win = None
                self.resp_hist = {}
       -        self.fields = {}
       +        self.btc_rate = Decimal("0.0")
                self.network = None
       +        self.gui = None
        
            @hook
            def set_network(self, network):
       -        if self.network:
       -            self.network.remove_job(self.exchanger)
       -        self.network = network
       -        if network:
       -            network.add_job(self.exchanger)
       +        if self.gui and network != self.network:
       +            if self.network:
       +                self.network.remove_job(self.exchanger)
       +            self.network = network
       +            if network:
       +                network.add_job(self.exchanger)
        
            @hook
            def init_qt(self, gui):
                self.gui = gui
       -        self.win = self.gui.main_window
       -        self.win.connect(self.win, SIGNAL("refresh_currencies()"), self.win.update_status)
       -        self.btc_rate = Decimal("0.0")
       -        self.tx_list = {}
       -        self.gui.exchanger = self.exchanger #
       -        self.add_send_edit()
       -        self.add_receive_edit()
       -        self.win.update_status()
       +        for window in gui.windows:
       +            self.new_window(window)
       +
       +    @hook
       +    def new_window(self, window):
       +        window.connect(window, SIGNAL("refresh_currencies()"),
       +                       window.update_status)
       +        window.fx_fields = {}
       +        self.add_send_edit(window)
       +        self.add_receive_edit(window)
       +        window.update_status()
        
            def close(self):
                BasePlugin.close(self)
                self.set_network(None)
                self.exchanger = None
       -        self.gui.exchanger = None
       -        self.send_fiat_e.hide()
       -        self.receive_fiat_e.hide()
       -        self.win.update_status()
       +        for window in self.gui.windows:
       +            window.send_fiat_e.hide()
       +            window.receive_fiat_e.hide()
       +            window.update_status()
        
            def set_currencies(self, currency_options):
                self.currencies = sorted(currency_options)
       -        if self.win:
       -            self.win.emit(SIGNAL("refresh_currencies()"))
       -            self.win.emit(SIGNAL("refresh_currencies_combo()"))
       +        for window in self.gui.windows:
       +            window.emit(SIGNAL("refresh_currencies()"))
       +            window.emit(SIGNAL("refresh_currencies_combo()"))
        
            @hook
            def get_fiat_balance_text(self, btc_balance, r):
       t@@ -250,13 +253,13 @@ class Plugin(BasePlugin):
            @hook
            def load_wallet(self, wallet, window):
                tx_list = {}
       -        for item in self.wallet.get_history(self.wallet.storage.get("current_account", None)):
       +        for item in wallet.get_history(wallet.storage.get("current_account", None)):
                    tx_hash, conf, value, timestamp, balance = item
                    tx_list[tx_hash] = {'value': value, 'timestamp': timestamp }
        
       -        self.tx_list = tx_list
       +        wallet.fx_tx_list = tx_list
                self.set_network(wallet.network)
       -        t = threading.Thread(target=self.request_history_rates, args=())
       +        t = threading.Thread(target=self.request_history_rates, args=(tx_list,))
                t.setDaemon(True)
                t.start()
        
       t@@ -265,14 +268,12 @@ class Plugin(BasePlugin):
                return True
        
        
       -    def request_history_rates(self):
       -        if self.config.get('history_rates') != "checked":
       -            return
       -        if not self.tx_list:
       +    def request_history_rates(self, tx_list):
       +        if self.config.get('history_rates') != "checked" or not tx_list:
                    return
        
                try:
       -            mintimestr = datetime.datetime.fromtimestamp(int(min(self.tx_list.items(), key=lambda x: x[1]['timestamp'])[1]['timestamp'])).strftime('%Y-%m-%d')
       +            mintimestr = datetime.datetime.fromtimestamp(int(min(tx_list.items(), key=lambda x: x[1]['timestamp'])[1]['timestamp'])).strftime('%Y-%m-%d')
                except Exception:
                    return
                maxtimestr = datetime.datetime.now().strftime('%Y-%m-%d')
       t@@ -302,64 +303,67 @@ class Plugin(BasePlugin):
                    else:
                        return
        
       -        self.win.need_update.set()
       +        for window in self.gui.windows:
       +            window.need_update.set()
        
            @hook
       -    def history_tab_update(self):
       +    def history_tab_update(self, window):
                if self.config.get('history_rates') != "checked":
                    return
                if not self.resp_hist:
                    return
       -        if not self.wallet:
       -            return
        
       -        self.win.is_edit = True
       -        self.win.history_list.setColumnCount(7)
       -        self.win.history_list.setHeaderLabels( [ '', '', _('Date'), _('Description') , _('Amount'), _('Balance'), _('Fiat Amount')] )
       -        root = self.win.history_list.invisibleRootItem()
       -        childcount = root.childCount()
       -        for i in range(childcount):
       -            item = root.child(i)
       -            try:
       -                tx_info = self.tx_list[str(item.data(0, Qt.UserRole).toPyObject())]
       -            except Exception:
       -                newtx = self.wallet.get_history()
       -                v = newtx[[x[0] for x in newtx].index(str(item.data(0, Qt.UserRole).toPyObject()))][2]
       -                tx_info = {'timestamp':int(time.time()), 'value': v}
       -                pass
       -            tx_time = int(tx_info['timestamp'])
       -            tx_value = Decimal(str(tx_info['value'])) / COIN
       -            if self.exchange == "CoinDesk":
       -                tx_time_str = datetime.datetime.fromtimestamp(tx_time).strftime('%Y-%m-%d')
       -                try:
       -                    tx_fiat_val = "%.2f %s" % (tx_value * Decimal(self.resp_hist['bpi'][tx_time_str]), "USD")
       -                except KeyError:
       -                    tx_fiat_val = "%.2f %s" % (self.btc_rate * Decimal(str(tx_info['value']))/COIN , "USD")
       -            elif self.exchange == "Winkdex":
       -                tx_time_str = datetime.datetime.fromtimestamp(tx_time).strftime('%Y-%m-%d') + "T16:00:00-04:00"
       +        for window in self.gui.windows:
       +            wallet = window.wallet
       +            if not wallet:
       +                continue
       +            tx_list = wallet.fx_tx_list
       +            window.is_edit = True
       +            window.history_list.setColumnCount(7)
       +            window.history_list.setHeaderLabels([ '', '', _('Date'), _('Description') , _('Amount'), _('Balance'), _('Fiat Amount')] )
       +            root = window.history_list.invisibleRootItem()
       +            childcount = root.childCount()
       +            for i in range(childcount):
       +                item = root.child(i)
                        try:
       -                    tx_rate = self.resp_hist[[x['timestamp'] for x in self.resp_hist].index(tx_time_str)]['price']
       -                    tx_fiat_val = "%.2f %s" % (tx_value * Decimal(tx_rate)/Decimal("100.0"), "USD")
       -                except ValueError:
       -                    tx_fiat_val = "%.2f %s" % (self.btc_rate * Decimal(tx_info['value'])/COIN , "USD")
       -                except KeyError:
       -                    tx_fiat_val = _("No data")
       -            elif self.exchange == "BitcoinVenezuela":
       -                tx_time_str = datetime.datetime.fromtimestamp(tx_time).strftime('%Y-%m-%d')
       -                try:
       -                    num = self.resp_hist[tx_time_str].replace(',','')
       -                    tx_fiat_val = "%.2f %s" % (tx_value * Decimal(num), self.fiat_unit())
       -                except KeyError:
       -                    tx_fiat_val = _("No data")
       -
       -            tx_fiat_val = " "*(12-len(tx_fiat_val)) + tx_fiat_val
       -            item.setText(6, tx_fiat_val)
       -            item.setFont(6, QFont(MONOSPACE_FONT))
       -            if Decimal(str(tx_info['value'])) < 0:
       -                item.setForeground(6, QBrush(QColor("#BC1E1E")))
       -
       -        self.win.history_list.setColumnWidth(6, 120)
       -        self.win.is_edit = False
       +                    tx_info = tx_list[str(item.data(0, Qt.UserRole).toPyObject())]
       +                except Exception:
       +                    newtx = wallet.get_history()
       +                    v = newtx[[x[0] for x in newtx].index(str(item.data(0, Qt.UserRole).toPyObject()))][2]
       +                    tx_info = {'timestamp':int(time.time()), 'value': v}
       +                    pass
       +                tx_time = int(tx_info['timestamp'])
       +                tx_value = Decimal(str(tx_info['value'])) / COIN
       +                if self.exchange == "CoinDesk":
       +                    tx_time_str = datetime.datetime.fromtimestamp(tx_time).strftime('%Y-%m-%d')
       +                    try:
       +                        tx_fiat_val = "%.2f %s" % (tx_value * Decimal(self.resp_hist['bpi'][tx_time_str]), "USD")
       +                    except KeyError:
       +                        tx_fiat_val = "%.2f %s" % (self.btc_rate * Decimal(str(tx_info['value']))/COIN , "USD")
       +                elif self.exchange == "Winkdex":
       +                    tx_time_str = datetime.datetime.fromtimestamp(tx_time).strftime('%Y-%m-%d') + "T16:00:00-04:00"
       +                    try:
       +                        tx_rate = self.resp_hist[[x['timestamp'] for x in self.resp_hist].index(tx_time_str)]['price']
       +                        tx_fiat_val = "%.2f %s" % (tx_value * Decimal(tx_rate)/Decimal("100.0"), "USD")
       +                    except ValueError:
       +                        tx_fiat_val = "%.2f %s" % (self.btc_rate * Decimal(tx_info['value'])/COIN , "USD")
       +                    except KeyError:
       +                        tx_fiat_val = _("No data")
       +                elif self.exchange == "BitcoinVenezuela":
       +                    tx_time_str = datetime.datetime.fromtimestamp(tx_time).strftime('%Y-%m-%d')
       +                    try:
       +                        num = self.resp_hist[tx_time_str].replace(',','')
       +                        tx_fiat_val = "%.2f %s" % (tx_value * Decimal(num), self.fiat_unit())
       +                    except KeyError:
       +                        tx_fiat_val = _("No data")
       +
       +                tx_fiat_val = " "*(12-len(tx_fiat_val)) + tx_fiat_val
       +                item.setText(6, tx_fiat_val)
       +                item.setFont(6, QFont(MONOSPACE_FONT))
       +                if Decimal(str(tx_info['value'])) < 0:
       +                    item.setForeground(6, QBrush(QColor("#BC1E1E")))
       +
       +            window.is_edit = False
        
        
            def settings_widget(self, window):
       t@@ -392,7 +396,8 @@ class Plugin(BasePlugin):
                            hist_checkbox.setEnabled(True)
                        else:
                            disable_check()
       -                self.win.update_status()
       +                for window in self.gui.windows:
       +                    window.update_status()
                        try:
                            self.fiat_button
                        except:
       t@@ -418,7 +423,8 @@ class Plugin(BasePlugin):
                        else:
                            disable_check()
                        set_currencies(combo)
       -                self.win.update_status()
       +                for window in self.gui.windows:
       +                    window.update_status()
        
                def on_change_hist(checked):
                    if checked:
       t@@ -426,8 +432,9 @@ class Plugin(BasePlugin):
                        self.request_history_rates()
                    else:
                        self.config.set_key('history_rates', 'unchecked')
       -                self.win.history_list.setHeaderLabels( [ '', '', _('Date'), _('Description') , _('Amount'), _('Balance')] )
       -                self.win.history_list.setColumnCount(6)
       +                for window in self.gui.windows:
       +                    window.history_list.setHeaderLabels( [ '', '', _('Date'), _('Description') , _('Amount'), _('Balance')] )
       +                    window.history_list.setColumnCount(6)
        
                def set_hist_check(hist_checkbox):
                    hist_checkbox.setEnabled(self.exchange in ["CoinDesk", "Winkdex", "BitcoinVenezuela"])
       t@@ -457,7 +464,8 @@ class Plugin(BasePlugin):
                combo.currentIndexChanged.connect(on_change)
                combo_ex.currentIndexChanged.connect(on_change_ex)
                hist_checkbox.stateChanged.connect(on_change_hist)
       -        combo.connect(self.win, SIGNAL('refresh_currencies_combo()'), lambda: set_currencies(combo))
       +        for window in self.gui.windows:
       +            combo.connect(window, SIGNAL('refresh_currencies_combo()'), lambda: set_currencies(combo))
                combo_ex.connect(d, SIGNAL('refresh_exchanges_combo()'), lambda: set_exchanges(combo_ex))
                ok_button.clicked.connect(lambda: ok_clicked())
                layout.addWidget(combo,1,1)
       t@@ -475,27 +483,31 @@ class Plugin(BasePlugin):
        
            def refresh_fields(self):
                '''Update the display at the new rate'''
       -        for field in self.fields.values():
       -            field.textEdited.emit(field.text())
       -
       -    def add_send_edit(self):
       -        self.send_fiat_e = AmountEdit(self.fiat_unit)
       -        btc_e = self.win.amount_e
       -        fee_e = self.win.fee_e
       -        self.connect_fields(btc_e, self.send_fiat_e, fee_e)
       -        self.win.send_grid.addWidget(self.send_fiat_e, 4, 3, Qt.AlignHCenter)
       -        btc_e.frozen.connect(lambda: self.send_fiat_e.setFrozen(btc_e.isReadOnly()))
       -
       -    def add_receive_edit(self):
       -        self.receive_fiat_e = AmountEdit(self.fiat_unit)
       -        btc_e = self.win.receive_amount_e
       -        self.connect_fields(btc_e, self.receive_fiat_e, None)
       -        self.win.receive_grid.addWidget(self.receive_fiat_e, 2, 3, Qt.AlignHCenter)
       -
       -    def connect_fields(self, btc_e, fiat_e, fee_e):
       +        for window in self.gui.windows:
       +            for field in window.fx_fields.values():
       +                field.textEdited.emit(field.text())
       +
       +    def add_send_edit(self, window):
       +        window.send_fiat_e = AmountEdit(self.fiat_unit)
       +        self.connect_fields(window, True)
       +        window.send_grid.addWidget(window.send_fiat_e, 4, 3, Qt.AlignHCenter)
       +        window.amount_e.frozen.connect(lambda: window.send_fiat_e.setFrozen(window.amount_e.isReadOnly()))
       +
       +    def add_receive_edit(self, window):
       +        window.receive_fiat_e = AmountEdit(self.fiat_unit)
       +        self.connect_fields(window, False)
       +        window.receive_grid.addWidget(window.receive_fiat_e, 2, 3, Qt.AlignHCenter)
       +
       +    def connect_fields(self, window, send):
       +        if send:
       +            btc_e, fiat_e, fee_e = (window.amount_e, window.send_fiat_e,
       +                                    window.fee_e)
       +        else:
       +            btc_e, fiat_e, fee_e = (window.receive_amount_e,
       +                                    window.receive_fiat_e, None)
                def fiat_changed():
                    fiat_e.setStyleSheet(BLACK_FG)
       -            self.fields[(fiat_e, btc_e)] = fiat_e
       +            window.fx_fields[(fiat_e, btc_e)] = fiat_e
                    try:
                        fiat_amount = Decimal(str(fiat_e.text()))
                    except:
       t@@ -507,11 +519,11 @@ class Plugin(BasePlugin):
                        btc_amount = fiat_amount/exchange_rate
                        btc_e.setAmount(int(btc_amount*Decimal(COIN)))
                        btc_e.setStyleSheet(BLUE_FG)
       -                if fee_e: self.win.update_fee()
       +                if fee_e: window.update_fee()
                fiat_e.textEdited.connect(fiat_changed)
                def btc_changed():
                    btc_e.setStyleSheet(BLACK_FG)
       -            self.fields[(fiat_e, btc_e)] = btc_e
       +            window.fx_fields[(fiat_e, btc_e)] = btc_e
                    if self.exchanger is None:
                        return
                    btc_amount = btc_e.get_amount()
       t@@ -525,8 +537,8 @@ class Plugin(BasePlugin):
                        fiat_e.setCursorPosition(pos)
                        fiat_e.setStyleSheet(BLUE_FG)
                btc_e.textEdited.connect(btc_changed)
       -        self.fields[(fiat_e, btc_e)] = btc_e
       +        window.fx_fields[(fiat_e, btc_e)] = btc_e
        
            @hook
       -    def do_clear(self):
       -        self.send_fiat_e.setText('')
       +    def do_clear(self, window):
       +        window.send_fiat_e.setText('')
   DIR diff --git a/plugins/trustedcoin.py b/plugins/trustedcoin.py
       t@@ -319,7 +319,7 @@ class Plugin(BasePlugin):
                wallet.add_master_public_key('x3/', xpub3)
        
            @hook
       -    def do_clear(self):
       +    def do_clear(self, window):
                self.is_billing = False
        
            @hook