Browse Source

frontend improvements, refactor qeinvoicelistmodel

patch-4
Sander van Grieken 3 years ago
parent
commit
3fd33169f5
  1. 4
      electrum/gui/qml/components/Receive.qml
  2. 9
      electrum/gui/qml/components/RequestDialog.qml
  3. 12
      electrum/gui/qml/components/Send.qml
  4. 4
      electrum/gui/qml/components/controls/FiatField.qml
  5. 26
      electrum/gui/qml/components/controls/InvoiceDelegate.qml
  6. 2
      electrum/gui/qml/qebitcoin.py
  7. 51
      electrum/gui/qml/qeinvoicelistmodel.py
  8. 15
      electrum/gui/qml/qetypes.py

4
electrum/gui/qml/components/Receive.qml

@ -39,7 +39,7 @@ Pane {
BtcField {
id: amount
fiatfield: amountFiat
Layout.preferredWidth: parent.width /2
Layout.preferredWidth: parent.width /3
}
Label {
@ -55,7 +55,7 @@ Pane {
id: amountFiat
btcfield: amount
visible: Daemon.fx.enabled
Layout.preferredWidth: parent.width /2
Layout.preferredWidth: parent.width /3
}
Label {

9
electrum/gui/qml/components/RequestDialog.qml

@ -164,10 +164,12 @@ Dialog {
Label {
text: qsTr('Address')
visible: !modelItem.is_lightning
}
Label {
Layout.fillWidth: true
Layout.columnSpan: 3
visible: !modelItem.is_lightning
font.family: FixedFont
font.pixelSize: constants.fontSizeLarge
wrapMode: Text.WrapAnywhere
@ -175,6 +177,7 @@ Dialog {
}
ToolButton {
icon.source: '../../icons/copy_bw.png'
visible: !modelItem.is_lightning
onClicked: {
AppController.textToClipboard(modelItem.address)
}
@ -203,8 +206,10 @@ Dialog {
}
Component.onCompleted: {
_bip21uri = bitcoin.create_uri(modelItem.address, modelItem.amount, modelItem.message, modelItem.timestamp, modelItem.expiration - modelItem.timestamp)
qr.source = 'image://qrgen/' + _bip21uri
if (!modelItem.is_lightning) {
_bip21uri = bitcoin.create_bip21_uri(modelItem.address, modelItem.amount, modelItem.message, modelItem.timestamp, modelItem.expiration - modelItem.timestamp)
qr.source = 'image://qrgen/' + _bip21uri
}
}
Bitcoin {

12
electrum/gui/qml/components/Send.qml

@ -74,7 +74,7 @@ Pane {
BtcField {
id: amount
fiatfield: amountFiat
Layout.preferredWidth: parent.width /2
Layout.preferredWidth: parent.width /3
}
Label {
@ -91,7 +91,7 @@ Pane {
id: amountFiat
btcfield: amount
visible: Daemon.fx.enabled
Layout.preferredWidth: parent.width /2
Layout.preferredWidth: parent.width /3
}
Label {
@ -123,6 +123,7 @@ Pane {
Button {
text: qsTr('Save')
enabled: invoice.invoiceType != Invoice.Invalid
icon.source: '../../icons/save.png'
onClicked: {
Daemon.currentWallet.create_invoice(recipient.text, amount.text, message.text)
}
@ -131,6 +132,7 @@ Pane {
Button {
text: qsTr('Pay now')
enabled: invoice.invoiceType != Invoice.Invalid // TODO && has funds
icon.source: '../../icons/confirmed.png'
onClicked: {
var f_amount = parseFloat(amount.text)
if (isNaN(f_amount))
@ -193,7 +195,7 @@ Pane {
model: Daemon.currentWallet.invoiceModel
delegate: InvoiceDelegate {
onClicked: {
var dialog = confirmInvoiceDialog.createObject(app, {'invoice' : invoice, 'invoice_key': model.key})
var dialog = invoiceDialog.createObject(app, {'invoice' : invoice, 'invoice_key': model.key})
dialog.open()
}
}
@ -227,7 +229,7 @@ Pane {
}
Component {
id: confirmInvoiceDialog
id: invoiceDialog
InvoiceDialog {
onDoPay: {
if (invoice.invoiceType == Invoice.OnchainInvoice) {
@ -285,7 +287,7 @@ Pane {
if (invoiceType == Invoice.OnchainOnlyAddress)
recipient.text = invoice.recipient
else {
var dialog = confirmInvoiceDialog.createObject(rootItem, {'invoice': invoice})
var dialog = invoiceDialog.createObject(rootItem, {'invoice': invoice})
dialog.open()
}
}

4
electrum/gui/qml/components/controls/FiatField.qml

@ -13,7 +13,9 @@ TextField {
inputMethodHints: Qt.ImhPreferNumbers
onTextChanged: {
if (amountFiat.activeFocus)
btcfield.text = text == '' ? '' : Config.satsToUnits(Daemon.fx.satoshiValue(amountFiat.text))
btcfield.text = text == ''
? ''
: Config.satsToUnits(Daemon.fx.satoshiValue(amountFiat.text))
}
Connections {

26
electrum/gui/qml/components/controls/InvoiceDelegate.qml

@ -36,6 +36,18 @@ ItemDelegate {
source: model.is_lightning
? "../../../icons/lightning.png"
: "../../../icons/bitcoin.png"
Image {
visible: model.onchain_fallback
z: -1
source: "../../../icons/bitcoin.png"
anchors {
right: parent.right
bottom: parent.bottom
}
width: parent.width /2
height: parent.height /2
}
}
RowLayout {
@ -55,13 +67,13 @@ ItemDelegate {
Label {
id: amount
text: model.amount == 0 ? '' : Config.formatSats(model.amount)
text: model.amount.isEmpty ? '' : Config.formatSats(model.amount)
font.pixelSize: constants.fontSizeMedium
font.family: FixedFont
}
Label {
text: model.amount == 0 ? '' : Config.baseUnit
text: model.amount.isEmpty ? '' : Config.baseUnit
font.pixelSize: constants.fontSizeMedium
color: Material.accentColor
}
@ -95,14 +107,14 @@ ItemDelegate {
id: fiatValue
visible: Daemon.fx.enabled
Layout.alignment: Qt.AlignRight
text: model.amount == 0 ? '' : Daemon.fx.fiatValue(model.amount, false)
text: model.amount.isEmpty ? '' : Daemon.fx.fiatValue(model.amount, false)
font.family: FixedFont
font.pixelSize: constants.fontSizeSmall
}
Label {
visible: Daemon.fx.enabled
Layout.alignment: Qt.AlignRight
text: model.amount == 0 ? '' : Daemon.fx.fiatCurrency
text: model.amount.isEmpty ? '' : Daemon.fx.fiatCurrency
font.pixelSize: constants.fontSizeSmall
color: Material.accentColor
}
@ -119,16 +131,16 @@ ItemDelegate {
Connections {
target: Config
function onBaseUnitChanged() {
amount.text = model.amount == 0 ? '' : Config.formatSats(model.amount)
amount.text = model.amount.isEmpty ? '' : Config.formatSats(model.amount)
}
function onThousandsSeparatorChanged() {
amount.text = model.amount == 0 ? '' : Config.formatSats(model.amount)
amount.text = model.amount.isEmpty ? '' : Config.formatSats(model.amount)
}
}
Connections {
target: Daemon.fx
function onQuotesUpdated() {
fiatValue.text = model.amount == 0 ? '' : Daemon.fx.fiatValue(model.amount, false)
fiatValue.text = model.amount.isEmpty ? '' : Daemon.fx.fiatValue(model.amount, false)
}
}

2
electrum/gui/qml/qebitcoin.py

@ -123,7 +123,7 @@ class QEBitcoin(QObject):
return { 'error': str(e) }
@pyqtSlot(str, QEAmount, str, int, int, result=str)
def create_uri(self, address, satoshis, message, timestamp, expiry):
def create_bip21_uri(self, address, satoshis, message, timestamp, expiry):
extra_params = {}
if expiry:
extra_params['time'] = str(timestamp)

51
electrum/gui/qml/qeinvoicelistmodel.py

@ -18,7 +18,8 @@ class QEAbstractInvoiceListModel(QAbstractListModel):
self.init_model()
# define listmodel rolemap
_ROLE_NAMES=('key','is_lightning','timestamp','date','message','amount','status','status_str','address','expiration','type')
_ROLE_NAMES=('key', 'is_lightning', 'timestamp', 'date', 'message', 'amount',
'status', 'status_str', 'address', 'expiration', 'type', 'onchain_fallback')
_ROLE_KEYS = range(Qt.UserRole, Qt.UserRole + len(_ROLE_NAMES))
_ROLE_MAP = dict(zip(_ROLE_KEYS, [bytearray(x.encode()) for x in _ROLE_NAMES]))
_ROLE_RMAP = dict(zip(_ROLE_NAMES, _ROLE_KEYS))
@ -96,6 +97,19 @@ class QEAbstractInvoiceListModel(QAbstractListModel):
return
i = i + 1
def invoice_to_model(self, invoice: Invoice):
item = self.get_invoice_as_dict(invoice)
item['key'] = invoice.get_id()
item['is_lightning'] = invoice.is_lightning()
if invoice.is_lightning() and 'address' not in item:
item['address'] = ''
item['date'] = format_time(item['timestamp'])
item['amount'] = QEAmount(from_invoice=invoice)
item['onchain_fallback'] = invoice.is_lightning() and invoice._lnaddr.get_fallback_address()
item['type'] = 'invoice'
return item
@abstractmethod
def get_invoice_for_key(self, key: str):
raise Exception('provide impl')
@ -105,55 +119,52 @@ class QEAbstractInvoiceListModel(QAbstractListModel):
raise Exception('provide impl')
@abstractmethod
def invoice_to_model(self, invoice: Invoice):
def get_invoice_as_dict(self, invoice: Invoice):
raise Exception('provide impl')
class QEInvoiceListModel(QEAbstractInvoiceListModel):
def __init__(self, wallet, parent=None):
super().__init__(wallet, parent)
_logger = get_logger(__name__)
def get_invoice_list(self):
return self.wallet.get_unpaid_invoices()
def invoice_to_model(self, invoice: Invoice):
item = self.wallet.export_invoice(invoice)
item['is_lightning'] = invoice.is_lightning()
item['date'] = format_time(item['timestamp'])
item['amount'] = QEAmount(amount_sat=invoice.get_amount_sat())
item['key'] = invoice.get_id()
item = super().invoice_to_model(invoice)
item['type'] = 'invoice'
return item
def get_invoice_list(self):
return self.wallet.get_unpaid_invoices()
def get_invoice_for_key(self, key: str):
return self.wallet.get_invoice(key)
def get_invoice_as_dict(self, invoice: Invoice):
return self.wallet.export_invoice(invoice)
class QERequestListModel(QEAbstractInvoiceListModel):
def __init__(self, wallet, parent=None):
super().__init__(wallet, parent)
_logger = get_logger(__name__)
def get_invoice_list(self):
return self.wallet.get_unpaid_requests()
def invoice_to_model(self, req: Invoice):
item = self.wallet.export_request(req)
item['key'] = req.get_rhash() if req.is_lightning() else req.get_address()
item['is_lightning'] = req.is_lightning()
item['date'] = format_time(item['timestamp'])
item['amount'] = QEAmount(amount_sat=req.get_amount_sat())
item = super().invoice_to_model(req)
item['type'] = 'request'
return item
def get_invoice_list(self):
return self.wallet.get_unpaid_requests()
def get_invoice_for_key(self, key: str):
return self.wallet.get_request(key)
def get_invoice_as_dict(self, req: Invoice):
return self.wallet.export_request(req)
@pyqtSlot(str, int)
def updateRequest(self, key, status):
self.updateInvoice(key, status)

15
electrum/gui/qml/qetypes.py

@ -15,11 +15,18 @@ from electrum.util import profiler
class QEAmount(QObject):
_logger = get_logger(__name__)
def __init__(self, *, amount_sat: int = 0, amount_msat: int = 0, is_max: bool = False, parent=None):
def __init__(self, *, amount_sat: int = 0, amount_msat: int = 0, is_max: bool = False, from_invoice = None, parent=None):
super().__init__(parent)
self._amount_sat = amount_sat
self._amount_msat = amount_msat
self._is_max = is_max
if from_invoice:
inv_amt = from_invoice.get_amount_msat()
if inv_amt == '!':
self._is_max = True
elif inv_amt is not None:
self._amount_msat = inv_amt
self._amount_sat = from_invoice.get_amount_sat()
valueChanged = pyqtSignal()
@ -43,6 +50,10 @@ class QEAmount(QObject):
def isMax(self):
return self._is_max
@pyqtProperty(bool, notify=valueChanged)
def isEmpty(self):
return not(self._is_max or self._amount_sat or self._amount_msat)
def __eq__(self, other):
if isinstance(other, QEAmount):
return self._amount_sat == other._amount_sat and self._amount_msat == other._amount_msat and self._is_max == other._is_max
@ -60,4 +71,4 @@ class QEAmount(QObject):
return '%s(sats=%d, msats=%d)' % (s, self._amount_sat, self._amount_msat)
def __repr__(self):
return f"<QEAmount max={self._is_max} sats={self._amount_sat} msats={self._amount_msat}>"
return f"<QEAmount max={self._is_max} sats={self._amount_sat} msats={self._amount_msat} empty={self.isEmpty}>"

Loading…
Cancel
Save