Updates for exchange_rate plugin
Have AmountEdit return an int if is_int, otherwise a Decimal Set the tray tooltip unconditionally. More verbose logging for exchage_rate plugin. Get rate_float from Coindesk as rate can have commas. Plugin tracks windows itself, and doesn't create its own members in the window objects. Clean up the edit handling.
This commit is contained in:
parent
95d3f6da1f
commit
34ce6d1821
|
@ -63,10 +63,9 @@ class AmountEdit(MyLineEdit):
|
|||
|
||||
def get_amount(self):
|
||||
try:
|
||||
x = int(str(self.text()))
|
||||
return (int if self.is_int else Decimal)(str(self.text()))
|
||||
except:
|
||||
return None
|
||||
return x
|
||||
|
||||
|
||||
class BTCAmountEdit(AmountEdit):
|
||||
|
|
|
@ -15,7 +15,6 @@ from electrum import util
|
|||
import seed_dialog
|
||||
from network_dialog import NetworkDialog
|
||||
from util import *
|
||||
from amountedit import AmountEdit
|
||||
|
||||
from electrum.plugins import always_hook, run_hook
|
||||
from electrum.mnemonic import prepare_seed
|
||||
|
|
|
@ -45,7 +45,7 @@ from electrum import SimpleConfig, Wallet, WalletStorage
|
|||
from electrum import Imported_Wallet
|
||||
from electrum import paymentrequest
|
||||
|
||||
from amountedit import AmountEdit, BTCAmountEdit, MyLineEdit, BTCkBEdit
|
||||
from amountedit import BTCAmountEdit, MyLineEdit, BTCkBEdit
|
||||
from network_dialog import NetworkDialog
|
||||
from qrcodewidget import QRCodeWidget, QRDialog
|
||||
from qrtextedit import ScanQRTextEdit, ShowQRTextEdit
|
||||
|
@ -523,14 +523,12 @@ class ElectrumWindow(QMainWindow):
|
|||
quote = r.get(0)
|
||||
if quote:
|
||||
text += "%s"%quote
|
||||
|
||||
if self.tray:
|
||||
self.tray.setToolTip("%s (%s)" % (text, self.wallet.basename()))
|
||||
icon = QIcon(":icons/status_connected.png")
|
||||
else:
|
||||
text = _("Not connected")
|
||||
icon = QIcon(":icons/status_disconnected.png")
|
||||
|
||||
self.tray.setToolTip("%s (%s)" % (text, self.wallet.basename()))
|
||||
self.balance_label.setText(text)
|
||||
self.status_button.setIcon( icon )
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ from threading import Thread
|
|||
import time
|
||||
import traceback
|
||||
from decimal import Decimal
|
||||
from functools import partial
|
||||
|
||||
from electrum.bitcoin import COIN
|
||||
from electrum.plugins import BasePlugin, hook
|
||||
|
@ -36,7 +37,9 @@ class ExchangeBase:
|
|||
return self.__class__.__name__
|
||||
|
||||
def update(self, ccy):
|
||||
self.print_error("getting fx quotes for", ccy)
|
||||
self.quotes = self.get_rates(ccy)
|
||||
self.print_error("received fx quotes")
|
||||
self.sig.emit(SIGNAL('fx_quotes'))
|
||||
return self.quotes
|
||||
|
||||
|
@ -46,6 +49,7 @@ class ExchangeBase:
|
|||
def set_history(self, ccy, history):
|
||||
'''History is a map of "%Y-%m-%d" strings to values'''
|
||||
self.history[ccy] = history
|
||||
self.print_error("received fx history for", ccy)
|
||||
self.sig.emit(SIGNAL("fx_history"))
|
||||
|
||||
def get_historical_rates(self, ccy):
|
||||
|
@ -131,7 +135,7 @@ class CoinDesk(ExchangeBase):
|
|||
'/v1/bpi/currentprice/%s.json' % ccy)
|
||||
ccys = [d['currency'] for d in dicts]
|
||||
result = dict.fromkeys(ccys)
|
||||
result[ccy] = Decimal(json['bpi'][ccy]['rate'])
|
||||
result[ccy] = Decimal(json['bpi'][ccy]['rate_float'])
|
||||
return result
|
||||
|
||||
def history_starts(self):
|
||||
|
@ -191,6 +195,7 @@ class Plugin(BasePlugin, ThreadJob):
|
|||
self.history_used_spot = False
|
||||
self.ccy_combo = None
|
||||
self.hist_checkbox = None
|
||||
self.windows = dict()
|
||||
|
||||
is_exchange = lambda obj: (inspect.isclass(obj)
|
||||
and issubclass(obj, ExchangeBase)
|
||||
|
@ -206,10 +211,9 @@ class Plugin(BasePlugin, ThreadJob):
|
|||
|
||||
def run(self):
|
||||
# This runs from the network thread which catches exceptions
|
||||
if self.parent.windows and self.timeout <= time.time():
|
||||
if self.windows and self.timeout <= time.time():
|
||||
self.timeout = time.time() + 150
|
||||
rates = self.exchange.update(self.ccy)
|
||||
self.refresh_fields()
|
||||
self.exchange.update(self.ccy)
|
||||
|
||||
def config_ccy(self):
|
||||
'''Use when dynamic fetching is needed'''
|
||||
|
@ -236,24 +240,81 @@ class Plugin(BasePlugin, ThreadJob):
|
|||
|
||||
def update_status_bars(self):
|
||||
'''Update status bar fiat balance in all windows'''
|
||||
for window in self.parent.windows:
|
||||
for window in self.windows:
|
||||
window.update_status()
|
||||
|
||||
def on_new_window(self, window):
|
||||
window.fx_fields = {}
|
||||
self.add_send_edit(window)
|
||||
self.add_receive_edit(window)
|
||||
# Additional send and receive edit boxes
|
||||
send_e = AmountEdit(self.config_ccy)
|
||||
window.send_grid.addWidget(send_e, 4, 3, Qt.AlignHCenter)
|
||||
window.amount_e.frozen.connect(
|
||||
lambda: send_e.setFrozen(window.amount_e.isReadOnly()))
|
||||
receive_e = AmountEdit(self.config_ccy)
|
||||
window.receive_grid.addWidget(receive_e, 2, 3, Qt.AlignHCenter)
|
||||
|
||||
self.windows[window] = {'edits': (send_e, receive_e),
|
||||
'last_edited': {}}
|
||||
self.connect_fields(window, window.amount_e, send_e, window.fee_e)
|
||||
self.connect_fields(window, window.receive_amount_e, receive_e, None)
|
||||
window.update_status()
|
||||
|
||||
def connect_fields(self, window, btc_e, fiat_e, fee_e):
|
||||
last_edited = self.windows[window]['last_edited']
|
||||
|
||||
def edit_changed(edit):
|
||||
edit.setStyleSheet(BLACK_FG)
|
||||
last_edited[(fiat_e, btc_e)] = edit
|
||||
amount = edit.get_amount()
|
||||
rate = self.exchange_rate()
|
||||
if rate is None or amount is None:
|
||||
if edit is fiat_e:
|
||||
btc_e.setText("")
|
||||
if fee_e:
|
||||
fee_e.setText("")
|
||||
else:
|
||||
fiat_e.setText("")
|
||||
else:
|
||||
if edit is fiat_e:
|
||||
btc_e.setAmount(int(amount / Decimal(rate) * COIN))
|
||||
if fee_e: window.update_fee()
|
||||
btc_e.setStyleSheet(BLUE_FG)
|
||||
else:
|
||||
fiat_e.setText("%.2f" % (amount * Decimal(rate) / COIN))
|
||||
fiat_e.setStyleSheet(BLUE_FG)
|
||||
|
||||
fiat_e.textEdited.connect(partial(edit_changed, fiat_e))
|
||||
btc_e.textEdited.connect(partial(edit_changed, btc_e))
|
||||
last_edited[(fiat_e, btc_e)] = btc_e
|
||||
|
||||
@hook
|
||||
def do_clear(self, window):
|
||||
self.windows[window]['edits'][0].setText('')
|
||||
|
||||
def on_close_window(self, window):
|
||||
self.windows.pop(window)
|
||||
|
||||
def close(self):
|
||||
# Get rid of hooks before updating status bars.
|
||||
BasePlugin.close(self)
|
||||
self.update_status_bars()
|
||||
for window, data in self.windows.items():
|
||||
for edit in data['edits']:
|
||||
edit.hide()
|
||||
window.update_status()
|
||||
|
||||
def on_fx_history(self):
|
||||
'''Called when historical fx quotes are updated'''
|
||||
for window in self.parent.windows:
|
||||
for window in self.windows:
|
||||
window.update_history_tab()
|
||||
|
||||
def on_fx_quotes(self):
|
||||
'''Called when fresh spot fx quotes come in'''
|
||||
self.update_status_bars()
|
||||
self.populate_ccy_combo()
|
||||
# Refresh edits with the new rate
|
||||
for window, data in self.windows.items():
|
||||
for edit in data['last_edited'].values():
|
||||
edit.textEdited.emit(edit.text())
|
||||
# History tab needs updating if it used spot
|
||||
if self.history_used_spot:
|
||||
self.on_fx_history()
|
||||
|
@ -284,14 +345,6 @@ class Plugin(BasePlugin, ThreadJob):
|
|||
combo.blockSignals(False)
|
||||
combo.setCurrentIndex(combo.findText(self.ccy))
|
||||
|
||||
def close(self):
|
||||
BasePlugin.close(self)
|
||||
for window in self.parent.windows:
|
||||
window.send_fiat_e.hide()
|
||||
window.receive_fiat_e.hide()
|
||||
window.update_history_tab()
|
||||
window.update_status()
|
||||
|
||||
def exchange_rate(self):
|
||||
'''Returns None, or the exchange rate as a Decimal'''
|
||||
rate = self.exchange.quotes.get(self.ccy)
|
||||
|
@ -405,9 +458,9 @@ class Plugin(BasePlugin, ThreadJob):
|
|||
self.config.set_key('history_rates', 'unchecked')
|
||||
|
||||
def ok_clicked():
|
||||
if self.exchange in ["CoinDesk", "itBit"]:
|
||||
self.timeout = 0
|
||||
d.accept();
|
||||
self.timeout = 0
|
||||
self.ccy_combo = None
|
||||
d.accept()
|
||||
|
||||
combo_ex = QComboBox()
|
||||
combo_ex.addItems(sorted(self.exchanges.keys()))
|
||||
|
@ -426,66 +479,4 @@ class Plugin(BasePlugin, ThreadJob):
|
|||
layout.addWidget(self.hist_checkbox,2,1)
|
||||
layout.addWidget(ok_button,3,1)
|
||||
|
||||
result = d.exec_()
|
||||
self.ccy_combo = None
|
||||
return result
|
||||
|
||||
def refresh_fields(self):
|
||||
'''Update the display at the new rate'''
|
||||
for window in self.parent.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.config_ccy)
|
||||
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.config_ccy)
|
||||
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)
|
||||
window.fx_fields[(fiat_e, btc_e)] = fiat_e
|
||||
try:
|
||||
fiat_amount = Decimal(str(fiat_e.text()))
|
||||
except:
|
||||
btc_e.setText("")
|
||||
if fee_e: fee_e.setText("")
|
||||
return
|
||||
exchange_rate = self.exchange_rate()
|
||||
if exchange_rate is not None:
|
||||
btc_amount = fiat_amount/exchange_rate
|
||||
btc_e.setAmount(int(btc_amount*Decimal(COIN)))
|
||||
btc_e.setStyleSheet(BLUE_FG)
|
||||
if fee_e: window.update_fee()
|
||||
fiat_e.textEdited.connect(fiat_changed)
|
||||
def btc_changed():
|
||||
btc_e.setStyleSheet(BLACK_FG)
|
||||
window.fx_fields[(fiat_e, btc_e)] = btc_e
|
||||
btc_amount = btc_e.get_amount()
|
||||
rate = self.exchange_rate()
|
||||
if rate is None or btc_amount is None:
|
||||
fiat_e.setText("")
|
||||
else:
|
||||
fiat_amount = rate * Decimal(btc_amount) / Decimal(COIN)
|
||||
pos = fiat_e.cursorPosition()
|
||||
fiat_e.setText("%.2f"%fiat_amount)
|
||||
fiat_e.setCursorPosition(pos)
|
||||
fiat_e.setStyleSheet(BLUE_FG)
|
||||
btc_e.textEdited.connect(btc_changed)
|
||||
window.fx_fields[(fiat_e, btc_e)] = btc_e
|
||||
|
||||
@hook
|
||||
def do_clear(self, window):
|
||||
window.send_fiat_e.setText('')
|
||||
return d.exec_()
|
||||
|
|
Loading…
Reference in New Issue