qml: add export TX and scan of TX
This commit is contained in:
101
electrum/gui/qml/components/ExportTxDialog.qml
Normal file
101
electrum/gui/qml/components/ExportTxDialog.qml
Normal file
@@ -0,0 +1,101 @@
|
||||
import QtQuick 2.6
|
||||
import QtQuick.Layouts 1.0
|
||||
import QtQuick.Controls 2.14
|
||||
import QtQuick.Controls.Material 2.0
|
||||
|
||||
import "controls"
|
||||
|
||||
ElDialog {
|
||||
id: dialog
|
||||
|
||||
property QtObject txdetails
|
||||
|
||||
property string text
|
||||
property string text_qr
|
||||
// if text_qr is undefined text will be used
|
||||
property string text_help
|
||||
|
||||
title: qsTr('Export Transaction')
|
||||
|
||||
parent: Overlay.overlay
|
||||
modal: true
|
||||
standardButtons: Dialog.Close
|
||||
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
|
||||
Overlay.modal: Rectangle {
|
||||
color: "#aa000000"
|
||||
}
|
||||
|
||||
Flickable {
|
||||
anchors.fill: parent
|
||||
contentHeight: rootLayout.height
|
||||
clip:true
|
||||
interactive: height < contentHeight
|
||||
|
||||
ColumnLayout {
|
||||
id: rootLayout
|
||||
width: parent.width
|
||||
spacing: constants.paddingMedium
|
||||
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: qr.height
|
||||
Layout.topMargin: constants.paddingSmall
|
||||
Layout.bottomMargin: constants.paddingSmall
|
||||
QRImage {
|
||||
id: qr
|
||||
qrdata: dialog.text_qr
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
}
|
||||
|
||||
Label {
|
||||
visible: dialog.text_help
|
||||
text: dialog.text_help
|
||||
wrapMode: Text.Wrap
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
height: 1
|
||||
Layout.preferredWidth: qr.width
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
color: Material.accentColor
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
|
||||
FlatButton {
|
||||
text: qsTr('Copy')
|
||||
icon.source: '../../icons/copy_bw.png'
|
||||
onClicked: AppController.textToClipboard(dialog.text)
|
||||
}
|
||||
FlatButton {
|
||||
text: qsTr('Share')
|
||||
icon.source: '../../icons/share.png'
|
||||
onClicked: {
|
||||
AppController.doShare(dialog.text, dialog.title)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: dialog.enter
|
||||
function onRunningChanged() {
|
||||
if (!dialog.enter.running) {
|
||||
qr.render = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
text = dialog.txdetails.serializedTx(false)
|
||||
text_qr = dialog.txdetails.serializedTx(true)
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,8 @@ ElDialog {
|
||||
|
||||
property InvoiceParser invoiceParser
|
||||
|
||||
signal txFound(data: string)
|
||||
|
||||
parent: Overlay.overlay
|
||||
modal: true
|
||||
standardButtons: Dialog.Close
|
||||
@@ -28,6 +30,15 @@ ElDialog {
|
||||
qrscan.restart()
|
||||
}
|
||||
|
||||
function dispatch(data) {
|
||||
if (bitcoin.isRawTx(data)) {
|
||||
// app.stack.push(Qt.resolvedUrl('TxDetails.qml'), { rawtx: text })
|
||||
txFound(data)
|
||||
} else {
|
||||
invoiceParser.recipient = data
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
spacing: 0
|
||||
@@ -37,7 +48,7 @@ ElDialog {
|
||||
Layout.preferredWidth: parent.width
|
||||
Layout.fillHeight: true
|
||||
|
||||
onFound: invoiceParser.recipient = scanData
|
||||
onFound: dialog.dispatch(scanData)
|
||||
}
|
||||
|
||||
FlatButton {
|
||||
@@ -47,7 +58,7 @@ ElDialog {
|
||||
onClicked: {
|
||||
var _mid = manualInputDialog.createObject(mainView)
|
||||
_mid.accepted.connect(function() {
|
||||
invoiceParser.recipient = _mid.recipient
|
||||
dialog.dispatch(_mid.recipient)
|
||||
})
|
||||
_mid.open()
|
||||
}
|
||||
@@ -57,7 +68,7 @@ ElDialog {
|
||||
Layout.fillWidth: true
|
||||
icon.source: '../../icons/paste.png'
|
||||
text: qsTr('Paste from clipboard')
|
||||
onClicked: invoiceParser.recipient = AppController.clipboardToText()
|
||||
onClicked: dialog.dispatch(AppController.clipboardToText())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,4 +113,8 @@ ElDialog {
|
||||
onClosed: destroy()
|
||||
}
|
||||
}
|
||||
|
||||
Bitcoin {
|
||||
id: bitcoin
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,16 @@ Pane {
|
||||
|
||||
property QtObject menu: Menu {
|
||||
id: menu
|
||||
MenuItem {
|
||||
icon.color: 'transparent'
|
||||
action: Action {
|
||||
text: qsTr('Export')
|
||||
onTriggered: {
|
||||
var dialog = exportTxDialog.createObject(root, { txdetails: txdetails })
|
||||
dialog.open()
|
||||
}
|
||||
}
|
||||
}
|
||||
MenuItem {
|
||||
icon.color: 'transparent'
|
||||
action: Action {
|
||||
@@ -292,7 +302,7 @@ Pane {
|
||||
RowLayout {
|
||||
width: parent.width
|
||||
Label {
|
||||
text: root.txid
|
||||
text: txdetails.txid
|
||||
font.pixelSize: constants.fontSizeLarge
|
||||
font.family: FixedFont
|
||||
Layout.fillWidth: true
|
||||
@@ -301,10 +311,10 @@ Pane {
|
||||
ToolButton {
|
||||
icon.source: '../../icons/share.png'
|
||||
icon.color: 'transparent'
|
||||
enabled: root.txid
|
||||
enabled: txdetails.txid
|
||||
onClicked: {
|
||||
var dialog = app.genericShareDialog.createObject(root,
|
||||
{ title: qsTr('Transaction ID'), text: root.txid }
|
||||
{ title: qsTr('Transaction ID'), text: txdetails.txid }
|
||||
)
|
||||
dialog.open()
|
||||
}
|
||||
@@ -354,7 +364,7 @@ Pane {
|
||||
Layout.columnSpan: 2
|
||||
Button {
|
||||
text: qsTr('Sign')
|
||||
enabled: !txdetails.isComplete
|
||||
enabled: txdetails.canSign
|
||||
onClicked: txdetails.sign()
|
||||
}
|
||||
Button {
|
||||
@@ -401,4 +411,10 @@ Pane {
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: exportTxDialog
|
||||
ExportTxDialog {
|
||||
onClosed: destroy()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -278,6 +278,10 @@ Item {
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
|
||||
onTxFound: {
|
||||
app.stack.push(Qt.resolvedUrl('TxDetails.qml'), { rawtx: data })
|
||||
close()
|
||||
}
|
||||
onClosed: destroy()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,7 +154,7 @@ class QEBitcoin(QObject):
|
||||
return create_bip21_uri(address, satoshis.satsInt, message, extra_query_params=extra_params)
|
||||
|
||||
@pyqtSlot(str, result=bool)
|
||||
def verify_raw_tx(self, rawtx):
|
||||
def isRawTx(self, rawtx):
|
||||
try:
|
||||
tx_from_any(rawtx)
|
||||
return True
|
||||
|
||||
@@ -35,9 +35,9 @@ class QETxDetails(QObject):
|
||||
_can_cpfp = False
|
||||
_can_save_as_local = False
|
||||
_can_remove = False
|
||||
_can_sign = False
|
||||
_is_unrelated = False
|
||||
_is_complete = False
|
||||
|
||||
_is_mined = False
|
||||
|
||||
_mempool_depth = ''
|
||||
@@ -186,6 +186,10 @@ class QETxDetails(QObject):
|
||||
def canRemove(self):
|
||||
return self._can_remove
|
||||
|
||||
@pyqtProperty(bool, notify=detailsChanged)
|
||||
def canSign(self):
|
||||
return self._can_sign
|
||||
|
||||
@pyqtProperty(bool, notify=detailsChanged)
|
||||
def isUnrelated(self):
|
||||
return self._is_unrelated
|
||||
@@ -249,6 +253,7 @@ class QETxDetails(QObject):
|
||||
self._can_cpfp = txinfo.can_cpfp
|
||||
self._can_save_as_local = txinfo.can_save_as_local
|
||||
self._can_remove = txinfo.can_remove
|
||||
self._can_sign = not self._is_complete and self._wallet.wallet.can_sign(self._tx)
|
||||
|
||||
self.detailsChanged.emit()
|
||||
|
||||
@@ -326,3 +331,11 @@ class QETxDetails(QObject):
|
||||
|
||||
self._wallet.wallet.adb.remove_transaction(txid)
|
||||
self._wallet.wallet.save_db()
|
||||
|
||||
@pyqtSlot(result=str)
|
||||
@pyqtSlot(bool, result=str)
|
||||
def serializedTx(self, for_qr=False):
|
||||
if for_qr:
|
||||
return self._tx.to_qr_data()
|
||||
else:
|
||||
return str(self._tx)
|
||||
|
||||
Reference in New Issue
Block a user