Browse Source

complete and refactor Fx preferences and use in Send/Receive tabs

patch-4
Sander van Grieken 3 years ago
parent
commit
d3e2737308
  1. 61
      electrum/gui/qml/components/Preferences.qml
  2. 18
      electrum/gui/qml/components/Receive.qml
  3. 18
      electrum/gui/qml/components/Send.qml
  4. 5
      electrum/gui/qml/qeapp.py
  5. 10
      electrum/gui/qml/qeconfig.py
  6. 37
      electrum/gui/qml/qedaemon.py
  7. 107
      electrum/gui/qml/qefx.py
  8. 6
      electrum/gui/qml/qenetwork.py

61
electrum/gui/qml/components/Preferences.qml

@ -35,12 +35,20 @@ Pane {
ComboBox { ComboBox {
id: baseUnit id: baseUnit
model: ['BTC','mBTC','bits','sat'] model: ['BTC','mBTC','bits','sat']
onCurrentValueChanged: {
if (activeFocus)
Config.baseUnit = currentValue
}
} }
CheckBox { CheckBox {
id: thousands id: thousands
Layout.columnSpan: 2 Layout.columnSpan: 2
text: qsTr('Add thousands separators to bitcoin amounts') text: qsTr('Add thousands separators to bitcoin amounts')
onCheckedChanged: {
if (activeFocus)
Config.thousandsSeparator = checked
}
} }
CheckBox { CheckBox {
@ -50,45 +58,58 @@ Pane {
enabled: false enabled: false
} }
CheckBox {
id: writeLogs
Layout.columnSpan: 2
text: qsTr('Write logs to file')
enabled: false
}
Label { Label {
text: qsTr('Fiat Currency') text: qsTr('Fiat Currency')
} }
ComboBox { ComboBox {
id: currencies id: currencies
model: Daemon.currencies model: Daemon.fx.currencies
onCurrentValueChanged: {
if (activeFocus)
Daemon.fx.fiatCurrency = currentValue
}
}
CheckBox {
id: historyRates
text: qsTr('History rates')
enabled: currencies.currentValue != ''
Layout.columnSpan: 2
onCheckStateChanged: {
if (activeFocus)
Daemon.fx.historyRates = checked
} }
} }
Label {
text: qsTr('Source')
enabled: currencies.currentValue != ''
} }
RowLayout { ComboBox {
Layout.fillWidth: true id: rateSources
Layout.alignment: Qt.AlignHCenter enabled: currencies.currentValue != ''
Button { model: Daemon.fx.rateSources
text: qsTr('Save') onModelChanged: {
onClicked: save() currentIndex = rateSources.indexOfValue(Daemon.fx.rateSource)
}
onCurrentValueChanged: {
if (activeFocus)
Daemon.fx.rateSource = currentValue
} }
} }
} }
function save() { }
Config.baseUnit = baseUnit.currentValue
Config.thousandsSeparator = thousands.checked
Config.fiatCurrency = currencies.currentValue ? currencies.currentValue : ''
app.stack.pop()
} }
Component.onCompleted: { Component.onCompleted: {
baseUnit.currentIndex = ['BTC','mBTC','bits','sat'].indexOf(Config.baseUnit) baseUnit.currentIndex = ['BTC','mBTC','bits','sat'].indexOf(Config.baseUnit)
thousands.checked = Config.thousandsSeparator thousands.checked = Config.thousandsSeparator
currencies.currentIndex = currencies.indexOfValue(Config.fiatCurrency) currencies.currentIndex = currencies.indexOfValue(Daemon.fx.fiatCurrency)
historyRates.checked = Daemon.fx.historyRates
rateSources.currentIndex = rateSources.indexOfValue(Daemon.fx.rateSource)
} }
} }

18
electrum/gui/qml/components/Receive.qml

@ -81,19 +81,19 @@ Pane {
TextField { TextField {
id: amountFiat id: amountFiat
visible: Config.fiatCurrency != '' visible: Daemon.fx.fiatCurrency != ''
font.family: FixedFont font.family: FixedFont
Layout.fillWidth: true Layout.fillWidth: true
inputMethodHints: Qt.ImhDigitsOnly inputMethodHints: Qt.ImhDigitsOnly
} }
Label { Label {
visible: Config.fiatCurrency != '' visible: Daemon.fx.fiatCurrency != ''
text: Config.fiatCurrency text: Daemon.fx.fiatCurrency
color: Material.accentColor color: Material.accentColor
} }
Item { visible: Config.fiatCurrency == ''; width: 1; height: 1; Layout.columnSpan: 2 } Item { visible: Daemon.fx.fiatCurrency == ''; width: 1; height: 1; Layout.columnSpan: 2 }
RowLayout { RowLayout {
Layout.columnSpan: 4 Layout.columnSpan: 4
@ -356,22 +356,22 @@ Pane {
if (amountFiat.activeFocus) if (amountFiat.activeFocus)
return return
var a = Config.unitsToSats(amount.text) var a = Config.unitsToSats(amount.text)
amountFiat.text = Daemon.fiatValue(a) amountFiat.text = Daemon.fx.fiatValue(a)
} }
} }
Connections { Connections {
target: amountFiat target: amountFiat
function onTextChanged() { function onTextChanged() {
if (amountFiat.activeFocus) { if (amountFiat.activeFocus) {
amount.text = Daemon.satoshiValue(amountFiat.text) amount.text = Daemon.fx.satoshiValue(amountFiat.text)
} }
} }
} }
Connections { Connections {
target: Network target: Daemon.fx
function onFiatUpdated() { function onQuotesUpdated() {
var a = Config.unitsToSats(amount.text) var a = Config.unitsToSats(amount.text)
amountFiat.text = Daemon.fiatValue(a) amountFiat.text = Daemon.fx.fiatValue(a)
} }
} }

18
electrum/gui/qml/components/Send.qml

@ -52,19 +52,19 @@ Pane {
TextField { TextField {
id: amountFiat id: amountFiat
visible: Config.fiatCurrency != '' visible: Daemon.fx.fiatCurrency != ''
font.family: FixedFont font.family: FixedFont
placeholderText: qsTr('Amount') placeholderText: qsTr('Amount')
inputMethodHints: Qt.ImhPreferNumbers inputMethodHints: Qt.ImhPreferNumbers
} }
Label { Label {
visible: Config.fiatCurrency != '' visible: Daemon.fx.fiatCurrency != ''
text: Config.fiatCurrency text: Daemon.fx.fiatCurrency
color: Material.accentColor color: Material.accentColor
} }
Item { visible: Config.fiatCurrency == ''; height: 1; Layout.columnSpan: 2; Layout.fillWidth: true } Item { visible: Daemon.fx.fiatCurrency == ''; height: 1; Layout.columnSpan: 2; Layout.fillWidth: true }
Item { width: 1; height: 1 } // workaround colspan on baseunit messing up row above Item { width: 1; height: 1 } // workaround colspan on baseunit messing up row above
@ -115,22 +115,22 @@ Pane {
if (amountFiat.activeFocus) if (amountFiat.activeFocus)
return return
var a = Config.unitsToSats(amount.text) var a = Config.unitsToSats(amount.text)
amountFiat.text = Daemon.fiatValue(a) amountFiat.text = Daemon.fx.fiatValue(a)
} }
} }
Connections { Connections {
target: amountFiat target: amountFiat
function onTextChanged() { function onTextChanged() {
if (amountFiat.activeFocus) { if (amountFiat.activeFocus) {
amount.text = Daemon.satoshiValue(amountFiat.text) amount.text = Daemon.fx.satoshiValue(amountFiat.text)
} }
} }
} }
Connections { Connections {
target: Network target: Daemon.fx
function onFiatUpdated() { function onQuotesUpdated() {
var a = Config.unitsToSats(amount.text) var a = Config.unitsToSats(amount.text)
amountFiat.text = Daemon.fiatValue(a) amountFiat.text = Daemon.fx.fiatValue(a)
} }
} }

5
electrum/gui/qml/qeapp.py

@ -16,6 +16,7 @@ from .qewallet import QEWallet
from .qeqr import QEQRParser, QEQRImageProvider from .qeqr import QEQRParser, QEQRImageProvider
from .qewalletdb import QEWalletDB from .qewalletdb import QEWalletDB
from .qebitcoin import QEBitcoin from .qebitcoin import QEBitcoin
from .qefx import QEFX
class QEAppController(QObject): class QEAppController(QObject):
userNotify = pyqtSignal(str) userNotify = pyqtSignal(str)
@ -83,7 +84,6 @@ class ElectrumQmlApplication(QGuiApplication):
self.logger = get_logger(__name__) self.logger = get_logger(__name__)
#ElectrumQmlApplication._config = config
ElectrumQmlApplication._daemon = daemon ElectrumQmlApplication._daemon = daemon
qmlRegisterType(QEWalletListModel, 'org.electrum', 1, 0, 'WalletListModel') qmlRegisterType(QEWalletListModel, 'org.electrum', 1, 0, 'WalletListModel')
@ -91,6 +91,7 @@ class ElectrumQmlApplication(QGuiApplication):
qmlRegisterType(QEWalletDB, 'org.electrum', 1, 0, 'WalletDB') qmlRegisterType(QEWalletDB, 'org.electrum', 1, 0, 'WalletDB')
qmlRegisterType(QEBitcoin, 'org.electrum', 1, 0, 'Bitcoin') qmlRegisterType(QEBitcoin, 'org.electrum', 1, 0, 'Bitcoin')
qmlRegisterType(QEQRParser, 'org.electrum', 1, 0, 'QRParser') qmlRegisterType(QEQRParser, 'org.electrum', 1, 0, 'QRParser')
qmlRegisterType(QEFX, 'org.electrum', 1, 0, 'FX')
self.engine = QQmlApplicationEngine(parent=self) self.engine = QQmlApplicationEngine(parent=self)
self.engine.addImportPath('./qml') self.engine.addImportPath('./qml')
@ -121,8 +122,6 @@ class ElectrumQmlApplication(QGuiApplication):
'protocol_version': version.PROTOCOL_VERSION 'protocol_version': version.PROTOCOL_VERSION
}) })
self._qeconfig.fiatCurrencyChanged.connect(self._qedaemon.setFiatCurrency)
qInstallMessageHandler(self.message_handler) qInstallMessageHandler(self.message_handler)
# get notified whether root QML document loads or not # get notified whether root QML document loads or not

10
electrum/gui/qml/qeconfig.py

@ -68,16 +68,6 @@ class QEConfig(QObject):
self.config.amt_add_thousands_sep = checked self.config.amt_add_thousands_sep = checked
self.thousandsSeparatorChanged.emit() self.thousandsSeparatorChanged.emit()
fiatCurrencyChanged = pyqtSignal()
@pyqtProperty(str, notify=fiatCurrencyChanged)
def fiatCurrency(self):
return self.config.get('currency')
@fiatCurrency.setter
def fiatCurrency(self, currency):
self.config.set_key('currency', currency)
self.fiatCurrencyChanged.emit()
@pyqtSlot('qint64', result=str) @pyqtSlot('qint64', result=str)
@pyqtSlot('qint64', bool, result=str) @pyqtSlot('qint64', bool, result=str)
def formatSats(self, satoshis, with_unit=False): def formatSats(self, satoshis, with_unit=False):

37
electrum/gui/qml/qedaemon.py

@ -8,9 +8,9 @@ from electrum.util import register_callback, get_new_wallet_name, WalletFileExce
from electrum.logging import get_logger from electrum.logging import get_logger
from electrum.wallet import Wallet, Abstract_Wallet from electrum.wallet import Wallet, Abstract_Wallet
from electrum.storage import WalletStorage, StorageReadWriteError from electrum.storage import WalletStorage, StorageReadWriteError
from electrum.bitcoin import COIN
from .qewallet import QEWallet from .qewallet import QEWallet
from .qefx import QEFX
# wallet list model. supports both wallet basenames (wallet file basenames) # wallet list model. supports both wallet basenames (wallet file basenames)
# and whole Wallet instances (loaded wallets) # and whole Wallet instances (loaded wallets)
@ -86,6 +86,7 @@ class QEDaemon(QObject):
def __init__(self, daemon, parent=None): def __init__(self, daemon, parent=None):
super().__init__(parent) super().__init__(parent)
self.daemon = daemon self.daemon = daemon
self.qefx = QEFX(daemon.fx, daemon.config)
_logger = get_logger(__name__) _logger = get_logger(__name__)
_loaded_wallets = QEWalletListModel() _loaded_wallets = QEWalletListModel()
@ -98,7 +99,7 @@ class QEDaemon(QObject):
activeWalletsChanged = pyqtSignal() activeWalletsChanged = pyqtSignal()
availableWalletsChanged = pyqtSignal() availableWalletsChanged = pyqtSignal()
walletOpenError = pyqtSignal([str], arguments=["error"]) walletOpenError = pyqtSignal([str], arguments=["error"])
currenciesChanged = pyqtSignal() fxChanged = pyqtSignal()
@pyqtSlot() @pyqtSlot()
@pyqtSlot(str) @pyqtSlot(str)
@ -135,31 +136,6 @@ class QEDaemon(QObject):
self._logger.error(str(e)) self._logger.error(str(e))
self.walletOpenError.emit(str(e)) self.walletOpenError.emit(str(e))
@pyqtSlot(str, result=str)
def fiatValue(self, satoshis):
rate = self.daemon.fx.exchange_rate()
try:
sd = Decimal(satoshis)
if sd == 0:
return ''
except:
return ''
return self.daemon.fx.value_str(satoshis,rate)
# TODO: move conversion to FxThread
@pyqtSlot(str, result=str)
def satoshiValue(self, fiat):
rate = self.daemon.fx.exchange_rate()
try:
fd = Decimal(fiat)
except:
return ''
v = fd / Decimal(rate) * COIN
return '' if v.is_nan() else self.daemon.config.format_amount(v)
@pyqtSlot()
def setFiatCurrency(self):
self.daemon.fx.set_currency(self.daemon.config.get('currency'))
@pyqtProperty('QString') @pyqtProperty('QString')
def path(self): def path(self):
@ -180,6 +156,7 @@ class QEDaemon(QObject):
return self._available_wallets return self._available_wallets
@pyqtProperty('QVariantList', notify=currenciesChanged) @pyqtProperty(QEFX, notify=fxChanged)
def currencies(self): def fx(self):
return [''] + self.daemon.fx.get_currencies(False) return self.qefx

107
electrum/gui/qml/qefx.py

@ -0,0 +1,107 @@
from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject
from decimal import Decimal
from electrum.logging import get_logger
from electrum.exchange_rate import FxThread
from electrum.simple_config import SimpleConfig
from electrum.util import register_callback
from electrum.bitcoin import COIN
class QEFX(QObject):
def __init__(self, fxthread: FxThread, config: SimpleConfig, parent=None):
super().__init__(parent)
self.fx = fxthread
self.config = config
register_callback(self.on_quotes, ['on_quotes'])
register_callback(self.on_history, ['on_history'])
_logger = get_logger(__name__)
quotesUpdated = pyqtSignal()
def on_quotes(self, event, *args):
self._logger.debug('new quotes')
self.quotesUpdated.emit()
historyUpdated = pyqtSignal()
def on_history(self, event, *args):
self._logger.debug('new history')
self.historyUpdated.emit()
currenciesChanged = pyqtSignal()
@pyqtProperty('QVariantList', notify=currenciesChanged)
def currencies(self):
return [''] + self.fx.get_currencies(self.historyRates)
rateSourcesChanged = pyqtSignal()
@pyqtProperty('QVariantList', notify=rateSourcesChanged)
def rateSources(self):
return self.fx.get_exchanges_by_ccy(self.fiatCurrency, self.historyRates)
fiatCurrencyChanged = pyqtSignal()
@pyqtProperty(str, notify=fiatCurrencyChanged)
def fiatCurrency(self):
return self.fx.get_currency()
@fiatCurrency.setter
def fiatCurrency(self, currency):
if currency != self.fiatCurrency:
self.fx.set_currency(currency)
self.enabled = currency != ''
self.fiatCurrencyChanged.emit()
self.rateSourcesChanged.emit()
historyRatesChanged = pyqtSignal()
@pyqtProperty(bool, notify=historyRatesChanged)
def historyRates(self):
return self.fx.get_history_config()
@historyRates.setter
def historyRates(self, checked):
if checked != self.historyRates:
self.fx.set_history_config(checked)
self.historyRatesChanged.emit()
self.rateSourcesChanged.emit()
rateSourceChanged = pyqtSignal()
@pyqtProperty(str, notify=rateSourceChanged)
def rateSource(self):
return self.fx.config_exchange()
@rateSource.setter
def rateSource(self, source):
if source != self.rateSource:
self.fx.set_exchange(source)
self.rateSourceChanged.emit()
enabledChanged = pyqtSignal()
@pyqtProperty(bool, notify=enabledChanged)
def enabled(self):
return self.fx.is_enabled()
@enabled.setter
def enabled(self, enable):
if enable != self.enabled:
self.fx.set_enabled(enable)
self.enabledChanged.emit()
@pyqtSlot(str, result=str)
def fiatValue(self, satoshis):
rate = self.fx.exchange_rate()
try:
sd = Decimal(satoshis)
if sd == 0:
return ''
except:
return ''
return self.fx.value_str(satoshis,rate)
@pyqtSlot(str, result=str)
def satoshiValue(self, fiat):
rate = self.fx.exchange_rate()
try:
fd = Decimal(fiat)
except:
return ''
v = fd / Decimal(rate) * COIN
return '' if v.is_nan() else self.config.format_amount(v)

6
electrum/gui/qml/qenetwork.py

@ -15,7 +15,6 @@ class QENetwork(QObject):
register_callback(self.on_proxy_set, ['proxy_set']) register_callback(self.on_proxy_set, ['proxy_set'])
register_callback(self.on_status, ['status']) register_callback(self.on_status, ['status'])
register_callback(self.on_fee_histogram, ['fee_histogram']) register_callback(self.on_fee_histogram, ['fee_histogram'])
register_callback(self.on_fiat, ['on_quotes','on_history'])
_logger = get_logger(__name__) _logger = get_logger(__name__)
@ -27,7 +26,6 @@ class QENetwork(QObject):
proxyChanged = pyqtSignal() proxyChanged = pyqtSignal()
statusChanged = pyqtSignal() statusChanged = pyqtSignal()
feeHistogramUpdated = pyqtSignal() feeHistogramUpdated = pyqtSignal()
fiatUpdated = pyqtSignal()
# shared signal for static properties # shared signal for static properties
dataChanged = pyqtSignal() dataChanged = pyqtSignal()
@ -62,10 +60,6 @@ class QENetwork(QObject):
self._logger.debug('fee histogram updated') self._logger.debug('fee histogram updated')
self.feeHistogramUpdated.emit() self.feeHistogramUpdated.emit()
def on_fiat(self, event, *args):
self._logger.debug('new fiat quotes')
self.fiatUpdated.emit()
@pyqtProperty(int,notify=heightChanged) @pyqtProperty(int,notify=heightChanged)
def height(self): def height(self):
return self._height return self._height

Loading…
Cancel
Save