Browse Source

handle gap limit warning when creating Request.

(using string error code for now, ideally should be properly defined
as an enum)

Also fix animation bug and work around broken ListView header implementation
patch-4
Sander van Grieken 3 years ago
parent
commit
03048d39b6
  1. 164
      electrum/gui/qml/components/Receive.qml
  2. 33
      electrum/gui/qml/qewallet.py

164
electrum/gui/qml/components/Receive.qml

@ -80,14 +80,12 @@ Pane {
Layout.columnSpan: 2
text: qsTr('Create Request')
onClicked: {
var a = parseFloat(amount.text)
Daemon.currentWallet.create_invoice(a, message.text, expires.currentValue)
createRequest()
}
}
}
Frame {
clip: true
verticalPadding: 0
horizontalPadding: 0
@ -103,18 +101,15 @@ Pane {
color: Qt.darker(Material.background, 1.25)
}
ListView {
ColumnLayout {
spacing: 0
anchors.fill: parent
model: Daemon.currentWallet.requestModel
headerPositioning: ListView.OverlayHeader
header: Item {
z: 1
height: hitem.height
width: ListView.view.width
Item {
Layout.preferredHeight: hitem.height
Layout.preferredWidth: parent.width
Rectangle {
anchors.fill: hitem
anchors.fill: parent
color: Qt.lighter(Material.background, 1.25)
}
RowLayout {
@ -127,76 +122,107 @@ Pane {
}
}
delegate: Item {
z: -1
height: item.height
width: ListView.view.width
GridLayout {
id: item
columns: 5
Image {
Layout.rowSpan: 2
Layout.preferredWidth: 32
Layout.preferredHeight: 32
source: model.type == 0 ? "../../icons/bitcoin.png" : "../../icons/lightning.png"
}
Label {
Layout.fillWidth: true
Layout.columnSpan: 2
text: model.message
font.pixelSize: constants.fontSizeLarge
}
Label {
text: qsTr('Amount: ')
font.pixelSize: constants.fontSizeSmall
}
Label {
text: model.amount
font.pixelSize: constants.fontSizeSmall
}
Label {
text: qsTr('Timestamp: ')
font.pixelSize: constants.fontSizeSmall
}
Label {
text: model.timestamp
font.pixelSize: constants.fontSizeSmall
}
Label {
text: qsTr('Status: ')
font.pixelSize: constants.fontSizeSmall
}
Label {
text: model.status
font.pixelSize: constants.fontSizeSmall
ListView {
Layout.fillHeight: true
Layout.fillWidth: true
clip: true
model: Daemon.currentWallet.requestModel
delegate: ItemDelegate {
id: root
height: item.height
width: ListView.view.width
onClicked: console.log('Request ' + index + ' clicked')
GridLayout {
id: item
anchors {
left: parent.left
right: parent.right
leftMargin: constants.paddingSmall
rightMargin: constants.paddingSmall
}
columns: 5
Image {
Layout.rowSpan: 2
Layout.preferredWidth: 32
Layout.preferredHeight: 32
source: model.type == 0 ? "../../icons/bitcoin.png" : "../../icons/lightning.png"
}
Label {
Layout.fillWidth: true
Layout.columnSpan: 2
text: model.message
font.pixelSize: constants.fontSizeLarge
}
Label {
text: qsTr('Amount: ')
font.pixelSize: constants.fontSizeSmall
}
Label {
text: model.amount
font.pixelSize: constants.fontSizeSmall
}
Label {
text: qsTr('Timestamp: ')
font.pixelSize: constants.fontSizeSmall
}
Label {
text: model.timestamp
font.pixelSize: constants.fontSizeSmall
}
Label {
text: qsTr('Status: ')
font.pixelSize: constants.fontSizeSmall
}
Label {
text: model.status
font.pixelSize: constants.fontSizeSmall
}
}
}
add: Transition {
NumberAnimation { properties: 'y'; from: -50; duration: 300 }
NumberAnimation { properties: 'opacity'; from: 0; to: 1.0; duration: 700 }
}
addDisplaced: Transition {
NumberAnimation { properties: 'y'; duration: 100 }
NumberAnimation { properties: 'opacity'; to: 1.0; duration: 700 * (1-from) }
}
}
add: Transition {
NumberAnimation { properties: 'y'; from: -50; duration: 300 }
NumberAnimation { properties: 'opacity'; from: 0; to: 1.0; duration: 700 }
}
addDisplaced: Transition {
NumberAnimation { properties: 'y'; duration: 100 }
}
}
}
function createRequest(ignoreGaplimit = false) {
var a = parseFloat(amount.text)
Daemon.currentWallet.create_invoice(a, message.text, expires.currentValue, false, ignoreGaplimit)
}
Connections {
target: Daemon.currentWallet
function onRequestCreateSuccess() {
message.text = ''
amount.text = ''
}
function onRequestCreateError(error) {
console.log(error)
var dialog = app.messageDialog.createObject(app, {'text': error})
function onRequestCreateError(code, error) {
if (code == 'gaplimit') {
var dialog = app.messageDialog.createObject(app, {'text': error, 'yesno': true})
dialog.yesClicked.connect(function() {
createRequest(true)
})
} else {
console.log(error)
var dialog = app.messageDialog.createObject(app, {'text': error})
}
dialog.open()
}
}

33
electrum/gui/qml/qewallet.py

@ -34,7 +34,7 @@ class QEWallet(QObject):
dataChanged = pyqtSignal() # dummy to silence warnings
requestCreateSuccess = pyqtSignal()
requestCreateError = pyqtSignal([str], arguments=['error'])
requestCreateError = pyqtSignal([str,str], arguments=['code','error'])
requestStatus = pyqtSignal()
def on_request_status(self, event, *args):
@ -122,12 +122,12 @@ class QEWallet(QObject):
tx = self.wallet.make_unsigned_transaction(coins=coins,outputs=outputs)
return True
def create_bitcoin_request(self, amount: int, message: str, expiration: int) -> Optional[str]:
def create_bitcoin_request(self, amount: int, message: str, expiration: int, ignore_gap: bool) -> Optional[str]:
addr = self.wallet.get_unused_address()
if addr is None:
# TODO implement
return
#if not self.wallet.is_deterministic(): # imported wallet
if not self.wallet.is_deterministic(): # imported wallet
# TODO implement
return
#msg = [
#_('No more addresses in your wallet.'), ' ',
#_('You are using a non-deterministic wallet, which cannot create new addresses.'), ' ',
@ -137,16 +137,18 @@ class QEWallet(QObject):
#if not self.question(''.join(msg)):
#return
#addr = self.wallet.get_receiving_address()
#else: # deterministic wallet
#if not self.question(_("Warning: The next address will not be recovered automatically if you restore your wallet from seed; you may need to add it manually.\n\nThis occurs because you have too many unused addresses in your wallet. To avoid this situation, use the existing addresses first.\n\nCreate anyway?")):
#return
#addr = self.wallet.create_new_address(False)
else: # deterministic wallet
if not ignore_gap:
self.requestCreateError.emit('gaplimit',_("Warning: The next address will not be recovered automatically if you restore your wallet from seed; you may need to add it manually.\n\nThis occurs because you have too many unused addresses in your wallet. To avoid this situation, use the existing addresses first.\n\nCreate anyway?"))
return
addr = self.wallet.create_new_address(False)
req = self.wallet.make_payment_request(addr, amount, message, expiration)
try:
self.wallet.add_payment_request(req)
except Exception as e:
self.logger.exception('Error adding payment request')
self.requestCreateError.emit(_('Error adding payment request') + ':\n' + repr(e))
self.requestCreateError.emit('fatal',_('Error adding payment request') + ':\n' + repr(e))
else:
# TODO: check this flow. Only if alias is defined in config. OpenAlias?
pass
@ -155,24 +157,25 @@ class QEWallet(QObject):
return addr
@pyqtSlot(int, 'QString', int)
def create_invoice(self, amount: int, message: str, expiration: int, is_lightning: bool = False):
@pyqtSlot(int, 'QString', int, bool)
@pyqtSlot(int, 'QString', int, bool, bool)
def create_invoice(self, amount: int, message: str, expiration: int, is_lightning: bool = False, ignore_gap: bool = False):
expiry = expiration #TODO: self.config.get('request_expiry', PR_DEFAULT_EXPIRATION_WHEN_CREATING)
try:
if is_lightning:
if not self.wallet.lnworker.channels:
#self.show_error(_("You need to open a Lightning channel first."))
self.requestCreateError.emit(_("You need to open a Lightning channel first."))
self.requestCreateError.emit('fatal',_("You need to open a Lightning channel first."))
return
# TODO maybe show a warning if amount exceeds lnworker.num_sats_can_receive (as in kivy)
key = self.wallet.lnworker.add_request(amount, message, expiry)
else:
key = self.create_bitcoin_request(amount, message, expiry)
key = self.create_bitcoin_request(amount, message, expiry, ignore_gap)
if not key:
return
#self.address_list.update()
self._addressModel.init_model()
except InvoiceError as e:
self.requestCreateError.emit(_('Error creating payment request') + ':\n' + str(e))
self.requestCreateError.emit('fatal',_('Error creating payment request') + ':\n' + str(e))
return
assert key is not None

Loading…
Cancel
Save