Browse Source

move request details into separate dialog

patch-4
Sander van Grieken 2 years ago
parent
commit
d4df633f22
  1. 124
      electrum/gui/qml/components/ReceiveDetailsDialog.qml
  2. 152
      electrum/gui/qml/components/ReceiveDialog.qml
  3. 7
      electrum/gui/qml/qerequestdetails.py
  4. 32
      electrum/gui/qml/qewallet.py
  5. 1
      electrum/wallet.py

124
electrum/gui/qml/components/ReceiveDetailsDialog.qml

@ -0,0 +1,124 @@
import QtQuick 2.6
import QtQuick.Layouts 1.0
import QtQuick.Controls 2.14
import QtQuick.Controls.Material 2.0
import QtQml.Models 2.1
import org.electrum 1.0
import "controls"
ElDialog {
id: dialog
property alias amount: amountBtc.text
property alias description: message.text
property alias expiry: expires.currentValue
parent: Overlay.overlay
modal: true
standardButtons: Dialog.Close
implicitWidth: parent.width
height: parent.height
Overlay.modal: Rectangle {
color: "#aa000000"
}
GridLayout {
id: form
width: parent.width
rowSpacing: constants.paddingSmall
columnSpacing: constants.paddingSmall
columns: 4
Label {
text: qsTr('Message')
}
TextField {
id: message
placeholderText: qsTr('Description of payment request')
Layout.columnSpan: 3
Layout.fillWidth: true
}
Label {
text: qsTr('Request')
wrapMode: Text.WordWrap
Layout.rightMargin: constants.paddingXLarge
}
BtcField {
id: amountBtc
fiatfield: amountFiat
Layout.preferredWidth: parent.width /3
}
Label {
text: Config.baseUnit
color: Material.accentColor
}
Item { width: 1; height: 1; Layout.fillWidth: true }
Item { visible: Daemon.fx.enabled; width: 1; height: 1 }
FiatField {
id: amountFiat
btcfield: amountBtc
visible: Daemon.fx.enabled
Layout.preferredWidth: parent.width /3
}
Label {
visible: Daemon.fx.enabled
text: Daemon.fx.fiatCurrency
color: Material.accentColor
}
Item { visible: Daemon.fx.enabled; width: 1; height: 1; Layout.fillWidth: true }
Label {
text: qsTr('Expires after')
Layout.fillWidth: false
}
ElComboBox {
id: expires
Layout.columnSpan: 2
textRole: 'text'
valueRole: 'value'
model: ListModel {
id: expiresmodel
Component.onCompleted: {
// we need to fill the model like this, as ListElement can't evaluate script
expiresmodel.append({'text': qsTr('10 minutes'), 'value': 10*60})
expiresmodel.append({'text': qsTr('1 hour'), 'value': 60*60})
expiresmodel.append({'text': qsTr('1 day'), 'value': 24*60*60})
expiresmodel.append({'text': qsTr('1 week'), 'value': 7*24*60*60})
expiresmodel.append({'text': qsTr('1 month'), 'value': 31*24*60*60})
expiresmodel.append({'text': qsTr('Never'), 'value': 0})
expires.currentIndex = 0
}
}
}
Item { width: 1; height: 1; Layout.fillWidth: true }
Button {
Layout.columnSpan: 4
Layout.alignment: Qt.AlignHCenter
text: qsTr('Create Request')
icon.source: '../../icons/qrcode.png'
onClicked: {
accept()
}
}
}
}

152
electrum/gui/qml/components/ReceiveDialog.qml

@ -11,9 +11,9 @@ import "controls"
ElDialog {
id: dialog
property string _bolt11
property string _bip21uri
property string _address
property string _bolt11: request.bolt11
property string _bip21uri: request.bip21
property string _address: request.address
property bool _render_qr: false // delay qr rendering until dialog is shown
@ -151,101 +151,10 @@ ElDialog {
color: Material.accentColor
}
// aaaaaaaaaaaaaaaaaaaa
GridLayout {
id: form
width: parent.width
rowSpacing: constants.paddingSmall
columnSpacing: constants.paddingSmall
columns: 4
Label {
text: qsTr('Message')
}
TextField {
id: message
placeholderText: qsTr('Description of payment request')
Layout.columnSpan: 3
Layout.fillWidth: true
}
Label {
text: qsTr('Request')
wrapMode: Text.WordWrap
Layout.rightMargin: constants.paddingXLarge
}
BtcField {
id: amount
fiatfield: amountFiat
Layout.preferredWidth: parent.width /3
}
Label {
text: Config.baseUnit
color: Material.accentColor
}
Item { width: 1; height: 1; Layout.fillWidth: true }
Item { visible: Daemon.fx.enabled; width: 1; height: 1 }
FiatField {
id: amountFiat
btcfield: amount
visible: Daemon.fx.enabled
Layout.preferredWidth: parent.width /3
}
Label {
visible: Daemon.fx.enabled
text: Daemon.fx.fiatCurrency
color: Material.accentColor
}
Item { visible: Daemon.fx.enabled; width: 1; height: 1; Layout.fillWidth: true }
Label {
text: qsTr('Expires after')
Layout.fillWidth: false
}
ElComboBox {
id: expires
Layout.columnSpan: 2
textRole: 'text'
valueRole: 'value'
model: ListModel {
id: expiresmodel
Component.onCompleted: {
// we need to fill the model like this, as ListElement can't evaluate script
expiresmodel.append({'text': qsTr('10 minutes'), 'value': 10*60})
expiresmodel.append({'text': qsTr('1 hour'), 'value': 60*60})
expiresmodel.append({'text': qsTr('1 day'), 'value': 24*60*60})
expiresmodel.append({'text': qsTr('1 week'), 'value': 7*24*60*60})
expiresmodel.append({'text': qsTr('1 month'), 'value': 31*24*60*60})
expiresmodel.append({'text': qsTr('Never'), 'value': 0})
expires.currentIndex = 0
}
}
}
Item { width: 1; height: 1; Layout.fillWidth: true }
Button {
Layout.columnSpan: 4
Layout.alignment: Qt.AlignHCenter
text: qsTr('Create Request')
icon.source: '../../icons/qrcode.png'
onClicked: {
createRequest()
}
}
Button {
text: 'specify'
onClicked: receiveDetailsDialog.open()
}
}
@ -267,29 +176,31 @@ ElDialog {
}
function createRequest(ignoreGaplimit = false) {
var qamt = Config.unitsToSats(amount.text)
var qamt = Config.unitsToSats(receiveDetailsDialog.amount)
if (qamt.satsInt > Daemon.currentWallet.lightningCanReceive.satsInt) {
console.log('Creating OnChain request')
Daemon.currentWallet.create_request(qamt, message.text, expires.currentValue, false, ignoreGaplimit)
Daemon.currentWallet.create_request(qamt, receiveDetailsDialog.description, receiveDetailsDialog.expiry, false, ignoreGaplimit)
} else {
console.log('Creating Lightning request')
Daemon.currentWallet.create_request(qamt, message.text, expires.currentValue, true)
Daemon.currentWallet.create_request(qamt, receiveDetailsDialog.description, receiveDetailsDialog.expiry, true)
}
}
function createDefaultRequest(ignoreGaplimit = false) {
console.log('Creating default request')
Daemon.currentWallet.create_default_request(ignoreGaplimit)
}
Connections {
target: Daemon.currentWallet
function onRequestCreateSuccess(key) {
message.text = ''
amount.text = ''
var dialog = requestdialog.createObject(app, { key: key })
dialog.open()
request.key = key
}
function onRequestCreateError(code, error) {
if (code == 'gaplimit') {
var dialog = app.messageDialog.createObject(app, {'text': error, 'yesno': true})
dialog.yesClicked.connect(function() {
createRequest(true)
createDefaultRequest(true)
})
} else {
console.log(error)
@ -297,14 +208,37 @@ ElDialog {
}
dialog.open()
}
function onRequestStatusChanged(key, status) {
Daemon.currentWallet.requestModel.updateRequest(key, status)
}
RequestDetails {
id: request
wallet: Daemon.currentWallet
key: dialog.key
onDetailsChanged: {
if (bolt11) {
rootLayout.state = 'bolt11'
} else if (bip21) {
rootLayout.state = 'bip21uri'
} else {
rootLayout.state = 'address'
}
}
}
ReceiveDetailsDialog {
id: receiveDetailsDialog
onAccepted: {
console.log('accepted')
Daemon.currentWallet.delete_request(request.key)
createRequest()
}
onRejected: {
console.log('rejected')
}
}
Component.onCompleted: {
_address = '1234567890'
rootLayout.state = 'address'
createDefaultRequest()
}
// hack. delay qr rendering until dialog is shown

7
electrum/gui/qml/qerequestdetails.py

@ -77,7 +77,7 @@ class QERequestDetails(QObject):
@pyqtProperty(str, notify=detailsChanged)
def address(self):
addr = self._req.get_address()
addr = self._req.get_address() if self._req else ''
return addr if addr else ''
@pyqtProperty(str, notify=detailsChanged)
@ -98,11 +98,11 @@ class QERequestDetails(QObject):
@pyqtProperty(str, notify=detailsChanged)
def bolt11(self):
return self._req.lightning_invoice
return self._req.lightning_invoice if self._req else ''
@pyqtProperty(str, notify=detailsChanged)
def bip21(self):
return self._req.get_bip21_URI()
return self._req.get_bip21_URI() if self._req else ''
@pyqtSlot(str, int)
@ -124,6 +124,7 @@ class QERequestDetails(QObject):
self._amount = QEAmount(from_invoice=self._req)
self.detailsChanged.emit()
self.initStatusStringTimer()
def initStatusStringTimer(self):

32
electrum/gui/qml/qewallet.py

@ -526,28 +526,50 @@ class QEWallet(AuthMixin, QObject, QtEventListener):
return
assert key is not None
self._requestModel.add_invoice(self.wallet.get_request(key))
self.requestModel.add_invoice(self.wallet.get_request(key))
self.requestCreateSuccess.emit(key)
@pyqtSlot()
@pyqtSlot(bool)
def create_default_request(self, ignore_gap: bool = False):
try:
if self.wallet.lnworker.channels:
if self.wallet.config.get('bolt11_fallback', True):
addr = self.wallet.get_unused_address()
# if addr is None, we ran out of addresses. for lightning enabled wallets, ignore for now
key = self.wallet.create_request(None, None, 3600, addr) # TODO : expiration from config
else:
key, addr = self.create_bitcoin_request(None, None, 3600, ignore_gap)
if not key:
return
# self.addressModel.init_model()
except InvoiceError as e:
self.requestCreateError.emit('fatal',_('Error creating payment request') + ':\n' + str(e))
return
assert key is not None
self.requestModel.add_invoice(self.wallet.get_request(key))
self.requestCreateSuccess.emit(key)
@pyqtSlot(str)
def delete_request(self, key: str):
self._logger.debug('delete req %s' % key)
self.wallet.delete_request(key)
self._requestModel.delete_invoice(key)
self.requestModel.delete_invoice(key)
@pyqtSlot(str, result='QVariant')
def get_request(self, key: str):
return self._requestModel.get_model_invoice(key)
return self.requestModel.get_model_invoice(key)
@pyqtSlot(str)
def delete_invoice(self, key: str):
self._logger.debug('delete inv %s' % key)
self.wallet.delete_invoice(key)
self._invoiceModel.delete_invoice(key)
self.invoiceModel.delete_invoice(key)
@pyqtSlot(str, result='QVariant')
def get_invoice(self, key: str):
return self._invoiceModel.get_model_invoice(key)
return self.invoiceModel.get_model_invoice(key)
@pyqtSlot(str, result=bool)
def verify_password(self, password):

1
electrum/wallet.py

@ -2467,6 +2467,7 @@ class Abstract_Wallet(ABC, Logger, EventListener):
# for receiving
amount_sat = amount_sat or 0
assert isinstance(amount_sat, int), f"{amount_sat!r}"
message = message or ''
address = address or None # converts "" to None
exp_delay = exp_delay or 0
timestamp = int(time.time())

Loading…
Cancel
Save