2020-10-15 19:18:54 +02:00
/*
* This file is part of the Flowee project
2024-10-01 17:55:05 +02:00
* Copyright (C) 2020-2024 Tom Zander <tom@flowee.org>
2020-10-15 19:18:54 +02:00
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
2022-11-26 10:46:57 +01:00
import QtQuick
2025-06-18 17:48:29 +02:00
import QtQuick . Controls . Basic as QQC2
2022-11-26 10:46:57 +01:00
import QtQuick . Layouts
import QtQuick . Window
2022-11-14 21:19:31 +01:00
import "../Flowee" as Flowee
import "../ControlColors.js" as ControlColors
2022-11-26 10:46:57 +01:00
import Flowee . org . pay
2020-06-11 17:41:18 +02:00
2021-11-24 19:54:55 +01:00
Item {
2021-11-23 16:46:37 +01:00
id: sendPanel
2021-11-27 09:26:28 +01:00
focus: true
2021-11-23 16:46:37 +01:00
2023-09-05 19:09:46 +02:00
onActiveFocusChanged: {
if ( ! activeFocus )
return ;
/*
The application can be started with a click on a payment link,
in that case the link gets made available in the following property
and we start a payment protocol with the value.
Afterwards we reset the property to avoid the next opening of this
screen repeating the payment.
*/
2025-09-10 13:57:13 +02:00
var paymentProtcolUrl = intent . paymentUrl ;
2023-09-05 19:09:46 +02:00
if ( paymentProtcolUrl !== "" ) {
payment . targetAddress = paymentProtcolUrl ;
2025-09-10 13:57:13 +02:00
intent . paymentUrl = "" ;
2023-09-05 19:09:46 +02:00
}
}
2021-11-16 19:14:45 +01:00
Payment { // the model behind the Payment logic
id: payment
2021-11-18 14:25:47 +01:00
fiatPrice: Fiat . price
account: portfolio . current
2023-08-30 22:42:08 +02:00
2021-11-16 19:14:45 +01:00
}
2021-11-24 19:54:55 +01:00
Rectangle { // background
anchors.fill: parent
2023-02-21 16:40:46 +01:00
color: palette . window
2021-11-24 19:54:55 +01:00
}
2021-11-23 16:46:37 +01:00
Flickable {
id: contentArea
width: sendPanel . width - 20
2021-11-24 19:54:55 +01:00
y: 40
x: 10
height: parent . height - 40
2021-11-23 16:46:37 +01:00
contentHeight: mainColumn . height
contentWidth: width
2021-11-24 14:56:52 +01:00
clip: true
2021-11-23 16:46:37 +01:00
Column {
id: mainColumn
2021-04-22 22:04:30 +02:00
width: parent . width
2021-11-23 16:46:37 +01:00
spacing: 10
Repeater {
model: payment . details
delegate: Item {
width: mainColumn . width
height: loader . height + 6
Loader {
id: loader
width: parent . width
height: status === Loader . Ready ? item.implicitHeight : 0
sourceComponent: {
if ( modelData . type === Payment . PayToAddress )
2024-10-01 17:55:05 +02:00
return destinationFields ;
2021-11-23 16:46:37 +01:00
if ( modelData . type === Payment . InputSelector )
2024-10-01 17:55:05 +02:00
return inputFields ;
if ( modelData . type === Payment . CommentOutput )
return opReturnInput ;
2021-11-23 16:46:37 +01:00
return null ; // should never happen
}
onLoaded: item . paymentDetail = modelData
2021-11-17 14:24:19 +01:00
}
2020-10-23 22:34:34 +02:00
2021-11-23 16:46:37 +01:00
Rectangle {
id: deleteDetailButton
anchors.right: parent . right
anchors.rightMargin: 10
y: - 3
width: 32
height: 32
visible: modelData . collapsable && ! modelData . collapsed
2023-02-21 16:40:46 +01:00
color: mouseArea . containsMouse ? palette.button : palette . window
border.color: palette . button
2020-06-12 23:37:32 +02:00
2021-11-23 16:46:37 +01:00
Image {
source: "qrc:/edit-delete.svg"
width: 24
height: 24
anchors.centerIn: parent
}
2021-04-26 19:57:00 +02:00
2021-11-23 16:46:37 +01:00
MouseArea {
id: mouseArea
anchors.fill: parent
anchors.margins: - 3
cursorShape: Qt . ArrowCursor
hoverEnabled: true
onClicked: okCancelDiag . visible = true ;
2021-11-16 19:14:45 +01:00
}
}
2021-11-23 16:46:37 +01:00
Flowee . Dialog {
id: okCancelDiag
onAccepted: payment . remove ( modelData ) ;
2022-05-18 17:32:23 +02:00
title: qsTr ( "Confirm delete" )
text: qsTr ( "Do you really want to delete this detail?" )
2021-11-23 16:46:37 +01:00
}
2021-04-29 16:15:05 +02:00
}
2021-11-23 16:46:37 +01:00
}
2020-06-12 23:37:32 +02:00
2021-11-23 16:46:37 +01:00
RowLayout {
width: parent . width
spacing: 0
Flowee . Button {
text: qsTr ( "Add Destination" )
onClicked: payment . addExtraOutput ( ) ;
}
Item { Layout.fillWidth: true }
Flowee . Button {
id: prepareButton
text: qsTr ( "Prepare" )
enabled: payment . isValid
property QtObject portfolioUsed: null
onClicked: {
portfolioUsed = portfolio . current
2022-05-18 20:16:34 +02:00
if ( payment . walletNeedsPin ) {
passwdDialog . start ( )
} else {
payment . prepare ( ) ;
}
2021-11-23 16:46:37 +01:00
}
}
2022-07-14 19:19:19 +02:00
Flowee . PasswdDialog {
2022-05-18 20:16:34 +02:00
id: passwdDialog
title: qsTr ( "Enter your PIN" )
2022-06-29 20:06:01 +02:00
2022-07-14 19:19:19 +02:00
onAccepted: {
2022-06-29 20:06:01 +02:00
payment . decrypt ( pwd ) ;
if ( payment . error === "" )
payment . prepare ( ) ;
2022-05-18 20:16:34 +02:00
}
}
2023-09-02 20:23:29 +02:00
Flowee . Dialog {
title: qsTr ( "Warning" )
2024-05-28 23:23:31 +02:00
standardButtons: QQC2 . DialogButtonBox . Ok
2023-09-02 20:23:29 +02:00
text: {
var warnings = payment . warnings
if ( warnings . length === 0 )
return "" ;
2023-09-05 21:18:32 +02:00
return qsTr ( "Payment request warnings:" )
2023-09-02 20:23:29 +02:00
+ "\n" + warnings . join ( "\n" ) ;
}
visible: text !== ""
onAccepted: payment . clearWarnings ( ) ;
}
2021-11-23 16:46:37 +01:00
}
2022-07-11 19:17:05 +02:00
Flowee . WarningLabel {
id: warningLabel
2021-11-30 11:11:06 +01:00
width: parent . width
2022-07-11 19:17:05 +02:00
text: payment . error
color: txid . color // make sure this is 'disabled' when the warning is not for this wallet.
2021-11-23 16:46:37 +01:00
}
Flowee . GroupBox {
id: txDetails
Layout.columnSpan: 4
title: qsTr ( "Transaction Details" )
width: parent . width
GridLayout {
columns: 2
property bool txOk: payment . txPrepared
2024-05-28 23:23:31 +02:00
Flowee . Label {
2021-11-23 16:46:37 +01:00
// no need translating this one.
text: "TxId:"
Layout.alignment: Qt . AlignRight | Qt . AlignTop
}
2021-11-30 13:54:11 +01:00
Flowee . LabelWithClipboard {
2021-11-23 16:46:37 +01:00
id: txid
text: payment . txid === "" ? qsTr ( "Not prepared yet" ) : payment . txid
Layout.fillWidth: true
// Change the color when the portfolio changed since 'prepare' was clicked.
color: prepareButton . portfolioUsed === portfolio . current
2022-12-14 14:41:55 +01:00
? palette.windowText
: Qt . darker ( palette . windowText , ( Pay . useDarkSkin ? 1.6 : 0.4 ) )
2022-03-22 23:17:35 +01:00
menuText: qsTr ( "Copy transaction-ID" )
2021-11-23 16:46:37 +01:00
}
2024-05-28 23:23:31 +02:00
Flowee . Label {
2021-11-23 16:46:37 +01:00
text: qsTr ( "Fee" ) + ":"
Layout.alignment: Qt . AlignRight
}
Flowee . BitcoinAmountLabel {
value: ! parent . txOk ? 0 : payment . assignedFee
colorize: false
color: txid . color
}
2024-05-28 23:23:31 +02:00
Flowee . Label {
2021-11-23 16:46:37 +01:00
text: qsTr ( "Transaction size" ) + ":"
Layout.alignment: Qt . AlignRight
}
2024-05-28 23:23:31 +02:00
Flowee . Label {
2021-11-23 16:46:37 +01:00
text: {
if ( ! parent . txOk )
return "" ;
var rc = payment . txSize ;
2021-12-04 15:43:48 +01:00
return qsTr ( "%1 bytes" ) . arg ( rc )
2021-11-23 16:46:37 +01:00
}
color: txid . color
}
2024-05-28 23:23:31 +02:00
Flowee . Label {
2021-11-23 16:46:37 +01:00
text: qsTr ( "Fee per byte" ) + ":"
Layout.alignment: Qt . AlignRight
}
2024-05-28 23:23:31 +02:00
Flowee . Label {
2021-11-23 16:46:37 +01:00
text: {
if ( ! parent . txOk )
return "" ;
var rc = payment . assignedFee / payment . txSize ;
var fee = rc . toFixed ( 3 ) ; // no more than 3 numbers behind the separator
fee = ( fee * 1.0 ) . toString ( ) ; // remove trailing zero's (1.000 => 1)
2021-12-04 15:43:48 +01:00
return qsTr ( "%1 sat/byte" , "fee" ) . arg ( fee ) ;
2021-11-23 16:46:37 +01:00
}
color: txid . color
}
}
}
2021-12-09 18:55:06 +01:00
Flowee . DialogButtonBox {
id: box
2021-11-23 16:46:37 +01:00
width: parent . width
2024-05-28 23:23:31 +02:00
standardButtons: QQC2 . DialogButtonBox . Cancel | QQC2 . DialogButtonBox . Ok
2021-12-09 18:55:06 +01:00
onStandardButtonsChanged: {
2024-05-28 23:23:31 +02:00
var okButton = standardButton ( QQC2 . DialogButtonBox . Ok )
2021-12-09 18:55:06 +01:00
if ( okButton !== null ) {
okButton . text = qsTr ( "Send" )
okButton . enabled = canSend
}
2021-04-23 19:59:49 +02:00
}
2021-12-09 18:55:06 +01:00
property bool canSend: payment . isValid && payment . txPrepared
&& prepareButton . portfolioUsed === portfolio . current ; // also make sure we prepared for the current portfolio.
2024-05-28 23:23:31 +02:00
onCanSendChanged: setEnabled ( QQC2 . DialogButtonBox . Ok , canSend )
2021-12-09 18:55:06 +01:00
onRejected: payment . reset ( ) ;
2024-10-14 14:12:05 +02:00
onAccepted: {
2025-03-16 22:14:20 +01:00
payment . markUserApproved ( ) ;
broadcastFeedback . personalNote = payment . userComment
broadcastFeedback . start ( ) ;
2024-10-14 14:12:05 +02:00
}
2021-04-23 19:59:49 +02:00
}
2020-06-12 20:53:01 +02:00
}
2021-04-26 21:59:22 +02:00
}
2021-04-23 19:59:49 +02:00
2021-11-30 13:50:40 +01:00
// the panel that allows us to tweak the payment (add details)
2021-11-24 19:20:06 +01:00
PaymentTweakingPanel {
anchors.fill: parent
}
2021-11-27 09:26:28 +01:00
Keys.forwardTo: Flowee . ListViewKeyHandler {
id: listViewKeyHandler
}
2021-11-24 19:20:06 +01:00
2022-12-07 18:30:02 +01:00
Flowee . BroadcastFeedback {
2024-10-14 14:12:05 +02:00
id: broadcastFeedback
2025-02-04 22:54:05 +01:00
anchors.leftMargin: 0
anchors.rightMargin: 0
2025-09-05 12:22:40 +02:00
fullScreen: true
2025-02-04 22:54:05 +01:00
bitcoinAmount: payment . paymentAmount
fiatPrice: payment . fiatPrice
targetAddress: payment . niceAddress
status: payment . broadcastStatus
2025-03-16 22:14:20 +01:00
processNote: function process ( note ) {
payment . userComment = note
}
2025-02-04 22:54:05 +01:00
onCloseButtonPressed: {
payment . reset ( ) ;
reset ( ) ;
}
2021-11-29 23:16:45 +01:00
}
2021-11-16 19:14:45 +01:00
// ============= Payment components ===============
2021-04-26 21:59:22 +02:00
2021-11-29 23:16:45 +01:00
/*
2021-12-14 13:32:58 +01:00
* Destination.
2021-11-29 23:16:45 +01:00
* The payment-output (address based) component.
*/
2021-11-16 19:14:45 +01:00
Component {
id: destinationFields
Flowee . GroupBox {
id: destinationPane
property QtObject paymentDetail: null
collapsable: paymentDetail . collapsable
2021-12-14 13:32:58 +01:00
onEffectiveCollapsedChanged: paymentDetail . collapsed = effectiveCollapsed
2021-11-16 19:14:45 +01:00
collapsed: paymentDetail . collapsed
2021-11-18 17:40:41 +01:00
title: qsTr ( "Destination" )
summary: {
var ad = paymentDetail . address
if ( ad === "" )
ad = "\'\'" ;
if ( paymentDetail . fiatFollows ) {
if ( paymentDetail . maxSelected )
var amount = qsTr ( "Max available" , "The maximum balance available" )
else
2022-08-14 16:46:23 +02:00
amount = Pay . amountToStringPretty ( paymentDetail . paymentAmount )
2021-11-18 17:40:41 +01:00
+ " " + Pay . unitName ;
}
else {
2023-03-12 12:58:41 +01:00
amount = Fiat . formattedPrice ( paymentDetail . paymentAmountFiat )
2021-11-18 17:40:41 +01:00
}
return qsTr ( "%1 to %2" , "summary text to pay X-euro to address M" )
. arg ( amount ) . arg ( ad ) ;
}
2021-12-09 15:44:22 +01:00
Item {
implicitWidth: parent . width
implicitHeight: Math . max ( contentColumn . height , warningArea . visible ? warningArea.height : 0 )
ColumnLayout {
id: contentColumn
width: parent . width
RowLayout {
width: parent . width
Flowee . TextField {
id: destination
focus: true
property var addressType: Pay . identifyString ( text ) ;
Layout.fillWidth: true
Layout.columnSpan: 3
2023-10-31 15:25:31 +01:00
placeholderText: enabled ? qsTr ( "Enter Bitcoin Cash Address" ) : ""
2021-12-09 15:44:22 +01:00
text: destinationPane . paymentDetail . address
onTextChanged: {
destinationPane . paymentDetail . address = text
2022-04-12 21:38:08 +02:00
addressInfo . createInfo ( ) ;
2021-12-09 15:44:22 +01:00
}
2023-03-12 20:31:02 +01:00
color: {
if ( ! activeFocus && text !== "" && ! addressInfo . addressOk )
return mainWindow . errorRed
return palette . windowText
2021-12-09 15:44:22 +01:00
}
2023-09-02 20:23:29 +02:00
enabled: paymentDetail . editable
2021-12-09 15:44:22 +01:00
}
2024-05-28 23:23:31 +02:00
Flowee . Label {
2021-12-09 15:44:22 +01:00
color: "green"
font.pixelSize: 24
2023-05-06 11:34:42 +02:00
text: addressInfo . addressOk ? "✔" : " "
2021-12-09 15:44:22 +01:00
}
2021-11-18 14:25:47 +01:00
}
2021-12-09 16:09:48 +01:00
Flowee . LabelWithClipboard {
2023-05-31 15:47:14 +02:00
visible: paymentDetail . address !== text
2021-12-09 16:09:48 +01:00
Layout.fillWidth: true
text: paymentDetail . formattedTarget
horizontalAlignment: Qt . AlignRight
font.italic: true
2022-12-16 19:57:43 +01:00
menuText: qsTr ( "Copy Address" )
2021-12-09 16:09:48 +01:00
}
2023-03-12 20:31:02 +01:00
Flowee . AddressInfoWidget {
2022-04-07 18:16:03 +02:00
id: addressInfo
width: parent . width
2023-03-12 20:31:02 +01:00
addressType: destination . addressType
2022-04-07 18:16:03 +02:00
}
2024-05-28 23:23:31 +02:00
Flowee . Label {
2021-12-09 15:44:22 +01:00
id: payAmount
text: qsTr ( "Amount" ) + ":"
}
RowLayout {
Flowee . FiatValueField {
id: fiatValueField
visible: Fiat . price > 0
2023-03-12 12:58:41 +01:00
onValueEdited: destinationPane . paymentDetail . paymentAmountFiat = value
value: destinationPane . paymentDetail . paymentAmountFiat
2021-12-09 15:44:22 +01:00
}
Flowee . CheckBox {
id: amountSelector
sliderOnIndicator: false
visible: Fiat . price > 0
enabled: false
checked: destinationPane . paymentDetail . fiatFollows
}
Flowee . BitcoinValueField {
id: bitcoinValueField
value: destinationPane . paymentDetail . paymentAmount
2023-05-30 19:25:09 +02:00
onValueEdited: destinationPane . paymentDetail . paymentAmount = value
2021-12-09 15:44:22 +01:00
}
Flowee . Button {
id: sendAll
visible: destinationPane . paymentDetail . maxAllowed
text: qsTr ( "Max" )
checkable: true
checked: destinationPane . paymentDetail . maxSelected
onClicked: destinationPane . paymentDetail . maxSelected = checked
}
2021-11-16 19:14:45 +01:00
}
2021-04-26 21:59:22 +02:00
}
2021-12-09 15:44:22 +01:00
Item {
id: warningArea
// BTC address entered warning.
2022-11-18 13:09:12 +01:00
visible: ( destination . addressType === Wallet . LegacySH || destination . addressType === Wallet . LegacyPKH )
2021-12-09 16:09:48 +01:00
&& paymentDetail . forceLegacyOk === false ;
2021-12-09 15:44:22 +01:00
width: parent . width - 40
height: warningColumn . height + 20 + destination . height
Rectangle {
anchors.fill: warningColumn
2022-09-08 20:21:22 +02:00
anchors.margins: - 7
2023-02-21 16:40:46 +01:00
color: palette . window
2022-09-08 20:21:22 +02:00
border.width: 2
2023-04-18 21:54:43 +02:00
border.color: mainWindow . errorRed
2021-12-09 15:44:22 +01:00
radius: 10
}
Flowee . ArrowPoint {
x: 20
anchors.bottom: warningColumn . top
2022-09-08 20:21:22 +02:00
anchors.bottomMargin: 4
2021-12-09 15:44:22 +01:00
rotation: - 90
2023-04-18 21:54:43 +02:00
color: mainWindow . errorRed
2021-12-09 15:44:22 +01:00
}
Column {
id: warningColumn
x: 10
y: destination . height + 10
width: parent . width
spacing: 10
2024-05-28 23:23:31 +02:00
Flowee . Label {
2021-12-09 15:44:22 +01:00
font.bold: true
font.pixelSize: warning . font . pixelSize * 1.2
text: qsTr ( "Warning" )
}
2024-05-28 23:23:31 +02:00
Flowee . Label {
2021-12-09 15:44:22 +01:00
id: warning
width: parent . width
text: qsTr ( "This is a BTC address, which is an incompatible coin. Your funds could get lost and Flowee will have no way to recover them. Are you sure this is the right address?" )
wrapMode: Text . WrapAtWordBoundaryOrAnywhere
}
RowLayout {
width: parent . width
Item {
width: 1 ; height: 1
Layout.fillWidth: true
}
2024-05-28 23:23:31 +02:00
Flowee . Button {
2021-12-09 15:44:22 +01:00
text: qsTr ( "Continue" )
2021-12-09 16:09:48 +01:00
onClicked: paymentDetail . forceLegacyOk = true
2021-12-09 15:44:22 +01:00
}
2024-05-28 23:23:31 +02:00
Flowee . Button {
2021-12-09 15:44:22 +01:00
text: qsTr ( "Cancel" )
2023-06-04 19:20:46 +02:00
onClicked: destination . text = ""
2021-12-09 15:44:22 +01:00
}
}
}
2021-04-26 21:59:22 +02:00
}
}
}
2020-06-11 17:41:18 +02:00
}
2021-11-19 11:20:01 +01:00
2021-11-23 16:46:37 +01:00
/*
* The input selector component.
*/
2021-11-19 11:20:01 +01:00
Component {
id: inputFields
Flowee . GroupBox {
2021-11-23 16:46:37 +01:00
id: inputsPane
collapsable: paymentDetail . collapsable
collapsed: paymentDetail . collapsed
2021-12-04 18:35:06 +01:00
onEffectiveCollapsedChanged: paymentDetail . collapsed = effectiveCollapsed
2021-11-23 16:46:37 +01:00
property QtObject paymentDetail: null
2021-11-30 13:50:40 +01:00
title: qsTr ( "Coin Selector" )
2021-11-23 16:46:37 +01:00
summary: qsTr ( "Selected %1 %2 in %3 coins" , "selected 2 BCH in 5 coins" , paymentDetail . selectedCount )
2022-08-14 16:46:23 +02:00
. arg ( Pay . amountToStringPretty ( paymentDetail . selectedValue ) )
2021-11-23 16:46:37 +01:00
. arg ( Pay . unitName )
. arg ( paymentDetail . selectedCount )
2021-11-27 09:26:28 +01:00
// make this tabs arrow-navigation go to our coinsListView.
Component.onCompleted: listViewKeyHandler . target = coinsListView
2021-11-24 17:41:41 +01:00
columns: 4
2024-05-28 23:23:31 +02:00
Flowee . Label {
2021-11-24 17:41:41 +01:00
text: qsTr ( "Total" , "Number of coins" ) + ":"
}
2024-05-28 23:23:31 +02:00
Flowee . Label {
2021-11-24 17:41:41 +01:00
text: coinsListView . count
Layout.fillWidth: true
}
2024-05-28 23:23:31 +02:00
Flowee . Label {
2021-11-24 17:41:41 +01:00
text: qsTr ( "Needed" ) + ":"
}
Flowee . BitcoinAmountLabel {
id: neededAmountLabel
2023-02-22 15:28:06 +01:00
value: payment . paymentAmount
2021-11-24 17:41:41 +01:00
Layout.fillWidth: true
colorize: false
}
// next row
2024-05-28 23:23:31 +02:00
Flowee . Label {
2021-11-24 17:41:41 +01:00
text: qsTr ( "Selected" ) + ":"
}
2024-05-28 23:23:31 +02:00
Flowee . Label {
2021-11-24 17:41:41 +01:00
text: inputsPane . paymentDetail . selectedCount
Layout.fillWidth: true
}
2024-05-28 23:23:31 +02:00
Flowee . Label {
2021-11-24 17:41:41 +01:00
text: qsTr ( "Value" ) + ":"
}
Flowee . BitcoinAmountLabel {
value: inputsPane . paymentDetail . selectedValue
Layout.fillWidth: true
colorize: false
}
2021-11-24 14:56:52 +01:00
2021-11-24 17:41:41 +01:00
// next row
ListView {
id: coinsListView
clip: true
Layout.columnSpan: 4
Layout.fillWidth: true
implicitHeight: {
var ch = contentHeight
2021-11-27 09:26:28 +01:00
var suggested = contentArea . height * 0.7
2021-11-24 17:41:41 +01:00
if ( ch < 0 || suggested < ch )
return suggested
return ch
2021-11-23 16:46:37 +01:00
}
2021-11-24 17:41:41 +01:00
model: inputsPane . paymentDetail . coins
2021-11-24 14:56:52 +01:00
2021-11-24 17:41:41 +01:00
property bool menuIsOpen: false
2021-11-23 16:46:37 +01:00
2021-11-24 17:41:41 +01:00
delegate: Rectangle {
width: ListView . view . width - 5
height: mainText . height + ageLabel . height + 12
2023-02-21 16:40:46 +01:00
color: index % 2 == 0 ? palette.alternateBase : palette . base
2021-11-23 16:46:37 +01:00
2021-11-24 17:41:41 +01:00
Rectangle {
id: lockedRect
color: Pay . useDarkSkin ? "#002558" : "#1a6ae2"
anchors.fill: parent
visible: locked // if the UTXO is user-locked
2024-05-28 23:23:31 +02:00
QQC2 . ToolTip {
2021-11-24 17:41:41 +01:00
delay: 600
text: qsTr ( "Locked coins will never be used for payments. Right-click for menu." )
2024-06-30 22:50:16 +02:00
visible: model . locked && rowMouseArea . containsMouse
2021-11-23 16:46:37 +01:00
}
}
2024-05-28 23:23:31 +02:00
Flowee . CheckBox {
2021-11-24 17:41:41 +01:00
y: 6
id: selectedBox
checked: model . selected
visible: ! lockedRect . visible
2024-06-30 22:50:16 +02:00
enabled: visible
2021-11-24 17:41:41 +01:00
}
2024-05-28 23:23:31 +02:00
Flowee . Label {
2021-11-24 17:41:41 +01:00
id: mainText
y: 6
anchors.right: amountLabel . left
anchors.left: parent . left
anchors.leftMargin: 50
text: {
var fancy = cloakedAddress ;
if ( typeof fancy != "undefined" )
return fancy ;
return address ;
2021-11-23 16:46:37 +01:00
}
2024-05-28 23:23:31 +02:00
elide: Flowee . Label . ElideRight
2021-11-24 17:41:41 +01:00
}
Flowee . BitcoinAmountLabel {
id: amountLabel
value: model . value
anchors.baseline: mainText . baseline
2024-09-25 16:02:24 +02:00
anchors.right: cfIcon . visible ? cfIcon.left : parent . right
2023-11-06 12:23:41 +01:00
// only HD wallets can use this
2021-11-24 19:58:44 +01:00
anchors.rightMargin: portfolio . current . isHDWallet ? 30 : 0
2025-03-03 13:47:34 +01:00
colorize: false
2025-03-16 22:18:18 +01:00
fiatWidth: Pay . isMainChain ? 90 : 0
2021-11-24 17:41:41 +01:00
}
2024-05-28 23:23:31 +02:00
Flowee . Label {
2021-11-24 17:41:41 +01:00
id: ageLabel
text: qsTr ( "Age" ) + ": " + age
anchors.left: mainText . left
anchors.top: mainText . bottom
font.pixelSize: mainText . font . pixelSize * 0.8
}
MouseArea {
id: rowMouseArea
anchors.fill: parent
acceptedButtons: Qt . LeftButton | Qt . RightButton
hoverEnabled: locked
2022-10-13 15:27:08 +02:00
onClicked: ( mouse ) = > {
2021-11-24 17:41:41 +01:00
// make it easy for the user to close a menu with either mouse
// button without instantly triggering another action.
if ( coinsListView . menuIsOpen ) {
coinsListView . menuIsOpen = false
return ;
}
2023-09-02 20:23:29 +02:00
if ( mouse . button === Qt . LeftButton ) {
2024-06-30 22:50:16 +02:00
if ( ! model . locked ) {
var willCheck = ! selectedBox . checked
selectedBox . checked = willCheck
inputsPane . paymentDetail . setRowIncluded ( index , willCheck )
}
2021-11-24 17:41:41 +01:00
}
else {
coinsListView . menuIsOpen = true
// Make sure that the menu
// opens where we clicked.
mousePos . x = mouse . x
mousePos . y = mouse . y
lockingMenu . open ( ) ;
2021-11-23 16:46:37 +01:00
}
}
2021-11-24 17:41:41 +01:00
Item {
id: mousePos
width: 1 ; height: 1
2024-05-28 23:23:31 +02:00
QQC2 . Menu {
2021-11-24 17:41:41 +01:00
id: lockingMenu
2024-05-28 23:23:31 +02:00
QQC2 . MenuItem {
2021-11-24 17:41:41 +01:00
text: selectedBox . checked ? qsTr ( "Unselect All" ) : qsTr ( "Select All" )
onClicked: {
coinsListView . menuIsOpen = false
if ( selectedBox . checked )
inputsPane . paymentDetail . unselectAll ( ) ;
else
inputsPane . paymentDetail . selectAll ( ) ;
}
}
2024-05-28 23:23:31 +02:00
QQC2 . MenuItem {
2021-11-24 17:41:41 +01:00
text: locked ? qsTr ( "Unlock coin" ) : qsTr ( "Lock coin" )
onClicked: {
inputsPane . paymentDetail . setOutputLocked ( index , ! locked )
coinsListView . menuIsOpen = false
}
}
2024-05-28 23:23:31 +02:00
QQC2 . MenuItem {
2024-01-15 20:17:10 +01:00
text: qsTr ( "Copy Address" )
onClicked: Pay . copyToClipboard ( Pay . chainPrefix + address ) ;
}
2021-11-24 17:41:41 +01:00
}
2021-11-23 16:46:37 +01:00
}
2021-11-24 17:41:41 +01:00
}
2023-11-06 12:23:41 +01:00
Flowee . CFIcon {
2024-09-25 16:02:24 +02:00
id: cfIcon
2021-11-24 17:41:41 +01:00
anchors.right: parent . right
anchors.verticalCenter: mainText . verticalCenter
2024-06-30 22:50:16 +02:00
visible: model . fused
2021-11-23 16:46:37 +01:00
}
}
}
2021-11-19 11:20:01 +01:00
}
}
2024-10-01 17:55:05 +02:00
/*
* Op-Return comment / data field.
*/
Component {
id: opReturnInput
Flowee . GroupBox {
property QtObject paymentDetail: null
collapsable: paymentDetail . collapsable
onEffectiveCollapsedChanged: paymentDetail . collapsed = effectiveCollapsed
collapsed: paymentDetail . collapsed
title: qsTr ( "Public-comment" )
columns: 2
Flowee . Label {
wrapMode: Text . WrapAtWordBoundaryOrAnywhere
Layout.columnSpan: 2
text: {
if ( paymentDetail . editable ) // user-created.
return qsTr ( "Add a comment you want to include in the transaction, visible for everyone." )
return qsTr ( "Custom message, to be included in the transaction." )
}
font.italic: true
}
Flowee . Label {
text: qsTr ( "Text" ) + ":"
}
Flowee . TextField {
id: textData
Layout.fillWidth: true
text: paymentDetail . editable ? paymentDetail.commentString : paymentDetail . preview
enabled: paymentDetail . editable
onTextChanged: if ( paymentDetail . editable ) paymentDetail . commentString = text
}
Flowee . Label {
text: qsTr ( "Size" ) + ":"
}
Flowee . Label {
text: paymentDetail . size
}
}
}
2020-06-11 17:41:18 +02:00
}