Browse Source

split user entered fields object from invoice uri parsing object

patch-4
Sander van Grieken 3 years ago
parent
commit
12d726efc2
  1. 9
      electrum/gui/qml/components/ConfirmTxDialog.qml
  2. 58
      electrum/gui/qml/components/Send.qml
  3. 4
      electrum/gui/qml/qeapp.py
  4. 153
      electrum/gui/qml/qeinvoice.py

9
electrum/gui/qml/components/ConfirmTxDialog.qml

@ -17,6 +17,9 @@ Dialog {
property alias amountLabelText: amountLabel.text
property alias sendButtonText: sendButton.text
signal txcancelled
signal txaccepted
title: qsTr('Confirm Transaction')
// copy these to finalizer
@ -206,7 +209,10 @@ Dialog {
Button {
text: qsTr('Cancel')
onClicked: dialog.close()
onClicked: {
txcancelled()
dialog.close()
}
}
Button {
@ -214,6 +220,7 @@ Dialog {
text: qsTr('Pay')
enabled: finalizer.valid
onClicked: {
txaccepted()
finalizer.send_onchain()
dialog.close()
}

58
electrum/gui/qml/components/Send.qml

@ -15,6 +15,7 @@ Pane {
recipient.text = ''
amount.text = ''
message.text = ''
is_max.checked = false
}
GridLayout {
@ -44,8 +45,9 @@ Pane {
wrapMode: Text.Wrap
placeholderText: qsTr('Paste address or invoice')
onTextChanged: {
if (activeFocus)
invoice.recipient = text
//if (activeFocus)
//userEnteredPayment.recipient = text
userEnteredPayment.recipient = recipient.text
}
}
@ -79,7 +81,7 @@ Pane {
fiatfield: amountFiat
Layout.preferredWidth: parent.width /3
onTextChanged: {
invoice.create_invoice(recipient.text, is_max.checked ? MAX : Config.unitsToSats(amount.text), message.text)
userEnteredPayment.amount = is_max.checked ? MAX : Config.unitsToSats(amount.text)
}
}
@ -94,7 +96,7 @@ Pane {
id: is_max
text: qsTr('Max')
onCheckedChanged: {
invoice.create_invoice(recipient.text, is_max.checked ? MAX : Config.unitsToSats(amount.text), message.text)
userEnteredPayment.amount = is_max.checked ? MAX : Config.unitsToSats(amount.text)
}
}
}
@ -125,7 +127,7 @@ Pane {
Layout.columnSpan: 2
Layout.fillWidth: true
onTextChanged: {
invoice.create_invoice(recipient.text, is_max.checked ? MAX : Config.unitsToSats(amount.text), message.text)
userEnteredPayment.message = message.text
}
}
@ -136,29 +138,30 @@ Pane {
Button {
text: qsTr('Save')
enabled: invoice.canSave
enabled: userEnteredPayment.canSave
icon.source: '../../icons/save.png'
onClicked: {
invoice.save_invoice()
invoice.clear()
userEnteredPayment.save_invoice()
userEnteredPayment.clear()
rootItem.clear()
}
}
Button {
text: qsTr('Pay now')
enabled: invoice.canPay
enabled: userEnteredPayment.canPay
icon.source: '../../icons/confirmed.png'
onClicked: {
invoice.save_invoice()
var dialog = confirmPaymentDialog.createObject(app, {
'address': recipient.text,
'satoshis': Config.unitsToSats(amount.text),
'satoshis': is_max.checked ? MAX : Config.unitsToSats(amount.text),
'message': message.text
})
dialog.txaccepted.connect(function() {
userEnteredPayment.clear()
rootItem.clear()
})
dialog.open()
invoice.clear()
rootItem.clear()
}
}
@ -293,6 +296,26 @@ Pane {
FocusScope { id: parkFocus }
}
UserEnteredPayment {
id: userEnteredPayment
wallet: Daemon.currentWallet
//onValidationError: {
//if (recipient.activeFocus) {
//// no popups when editing
//return
//}
//var dialog = app.messageDialog.createObject(app, {'text': message })
//dialog.open()
//// rootItem.clear()
//}
onInvoiceSaved: {
Daemon.currentWallet.invoiceModel.init_model()
}
}
Invoice {
id: invoice
wallet: Daemon.currentWallet
@ -314,11 +337,12 @@ Pane {
}
}
onValidationSuccess: {
// address only -> fill form fields
// address only -> fill form fields and clear this instance
// else -> show invoice confirmation dialog
if (invoiceType == Invoice.OnchainOnlyAddress)
if (invoiceType == Invoice.OnchainOnlyAddress) {
recipient.text = invoice.recipient
else {
invoice.clear()
} else {
var dialog = invoiceDialog.createObject(rootItem, {'invoice': invoice})
dialog.open()
}
@ -326,8 +350,8 @@ Pane {
onInvoiceCreateError: console.log(code + ' ' + message)
onInvoiceSaved: {
console.log('invoice got saved')
Daemon.currentWallet.invoiceModel.init_model()
}
}
}

4
electrum/gui/qml/qeapp.py

@ -19,7 +19,7 @@ from .qewalletdb import QEWalletDB
from .qebitcoin import QEBitcoin
from .qefx import QEFX
from .qetxfinalizer import QETxFinalizer
from .qeinvoice import QEInvoice
from .qeinvoice import QEInvoice, QEUserEnteredPayment
from .qetypes import QEAmount
from .qeaddressdetails import QEAddressDetails
from .qetxdetails import QETxDetails
@ -146,6 +146,8 @@ class ElectrumQmlApplication(QGuiApplication):
qmlRegisterType(QEFX, 'org.electrum', 1, 0, 'FX')
qmlRegisterType(QETxFinalizer, 'org.electrum', 1, 0, 'TxFinalizer')
qmlRegisterType(QEInvoice, 'org.electrum', 1, 0, 'Invoice')
qmlRegisterType(QEUserEnteredPayment, 'org.electrum', 1, 0, 'UserEnteredPayment')
qmlRegisterType(QEAddressDetails, 'org.electrum', 1, 0, 'AddressDetails')
qmlRegisterType(QETxDetails, 'org.electrum', 1, 0, 'TxDetails')
qmlRegisterType(QEChannelOpener, 'org.electrum', 1, 0, 'ChannelOpener')

153
electrum/gui/qml/qeinvoice.py

@ -305,33 +305,154 @@ class QEInvoice(QObject):
self._wallet.wallet.save_invoice(self._effectiveInvoice)
self.invoiceSaved.emit()
@pyqtSlot(str, QEAmount, str)
def create_invoice(self, address: str, amount: QEAmount, message: str):
# create invoice from user entered fields
# (any other type of invoice is created from parsing recipient)
self._logger.debug('creating invoice to %s, amount=%s, message=%s' % (address, repr(amount), message))
self.clear()
class QEUserEnteredPayment(QObject):
_logger = get_logger(__name__)
_wallet = None
_recipient = None
_message = None
_amount = QEAmount()
_key = None
_canSave = False
_canPay = False
validationError = pyqtSignal([str,str], arguments=['code','message'])
invoiceCreateError = pyqtSignal([str,str], arguments=['code', 'message'])
invoiceSaved = pyqtSignal()
walletChanged = pyqtSignal()
@pyqtProperty(QEWallet, notify=walletChanged)
def wallet(self):
return self._wallet
@wallet.setter
def wallet(self, wallet: QEWallet):
if self._wallet != wallet:
self._wallet = wallet
self.walletChanged.emit()
recipientChanged = pyqtSignal()
@pyqtProperty(str, notify=recipientChanged)
def recipient(self):
return self._recipient
@recipient.setter
def recipient(self, recipient: str):
if self._recipient != recipient:
self._recipient = recipient
self.validate()
self.recipientChanged.emit()
messageChanged = pyqtSignal()
@pyqtProperty(str, notify=messageChanged)
def message(self):
return self._message
@message.setter
def message(self, message):
if self._message != message:
self._message = message
self.messageChanged.emit()
amountChanged = pyqtSignal()
@pyqtProperty(QEAmount, notify=amountChanged)
def amount(self):
return self._amount
@amount.setter
def amount(self, amount):
if self._amount != amount:
self._amount = amount
self.validate()
self.amountChanged.emit()
canSaveChanged = pyqtSignal()
@pyqtProperty(bool, notify=canSaveChanged)
def canSave(self):
return self._canSave
@canSave.setter
def canSave(self, canSave):
if self._canSave != canSave:
self._canSave = canSave
self.canSaveChanged.emit()
canPayChanged = pyqtSignal()
@pyqtProperty(bool, notify=canPayChanged)
def canPay(self):
return self._canPay
@canPay.setter
def canPay(self, canPay):
if self._canPay != canPay:
self._canPay = canPay
self.canPayChanged.emit()
if not address:
self.invoiceCreateError.emit('fatal', _('Recipient not specified.') + ' ' + _('Please scan a Bitcoin address or a payment request'))
keyChanged = pyqtSignal()
@pyqtProperty(bool, notify=keyChanged)
def key(self):
return self._key
@key.setter
def key(self, key):
if self._key != key:
self._key = key
self.keyChanged.emit()
def validate(self):
self.canPay = False
self.canSave = False
self._logger.debug('validate')
if not self._recipient:
self.validationError.emit('recipient', _('Recipient not specified.'))
return
if not bitcoin.is_address(address):
self.invoiceCreateError.emit('fatal', _('Invalid Bitcoin address'))
if not bitcoin.is_address(self._recipient):
self.validationError.emit('recipient', _('Invalid Bitcoin address'))
return
if amount.isEmpty:
self.invoiceCreateError.emit('fatal', _('Invalid amount'))
if self._amount.isEmpty:
self.validationError.emit('amount', _('Invalid amount'))
return
inv_amt = '!' if amount.isMax else (amount.satsInt * 1000) # FIXME msat precision from UI?
if self._amount.isMax:
self.canPay = True
else:
self.canSave = True
if self.get_max_spendable() >= self._amount.satsInt:
self.canPay = True
def get_max_spendable(self):
c, u, x = self._wallet.wallet.get_balance()
#TODO determine real max
return c
@pyqtSlot()
def save_invoice(self):
assert self.canSave
assert not self._amount.isMax
self._logger.debug('saving invoice to %s, amount=%s, message=%s' % (self._recipient, repr(self._amount), self._message))
inv_amt = self._amount.satsInt
try:
outputs = [PartialTxOutput.from_address_and_value(address, inv_amt)]
invoice = self._wallet.wallet.create_invoice(outputs=outputs, message=message, pr=None, URI=None)
outputs = [PartialTxOutput.from_address_and_value(self._recipient, inv_amt)]
self._logger.debug(repr(outputs))
invoice = self._wallet.wallet.create_invoice(outputs=outputs, message=self._message, pr=None, URI=None)
except InvoiceError as e:
self.invoiceCreateError.emit('fatal', _('Error creating payment') + ':\n' + str(e))
return
self.set_effective_invoice(invoice)
self.key = self._wallet.wallet.get_key_for_outgoing_invoice(invoice)
self._wallet.wallet.save_invoice(invoice)
self.invoiceSaved.emit()
@pyqtSlot()
def clear(self):
self._recipient = None
self._amount = QEAmount()
self._message = None
self.canSave = False
self.canPay = False

Loading…
Cancel
Save