monero-gui/pages/Receive.qml

489 lines
22 KiB
QML
Raw Normal View History

2018-01-07 05:20:45 +00:00
// Copyright (c) 2014-2018, The Monero Project
2016-10-04 10:15:29 +00:00
//
// All rights reserved.
2016-10-04 10:15:29 +00:00
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
2016-10-04 10:15:29 +00:00
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
2016-10-04 10:15:29 +00:00
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
2016-10-04 10:15:29 +00:00
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
2016-10-04 10:15:29 +00:00
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2019-04-11 01:17:29 +00:00
import QtQuick 2.9
import QtQuick.Controls 2.0
import QtQuick.Controls.Styles 1.4
import QtQuick.Layouts 1.1
import QtQuick.Dialogs 1.2
2019-06-17 15:14:13 +00:00
import FontAwesome 1.0
2018-12-08 15:55:29 +00:00
import "../components" as MoneroComponents
2019-04-11 01:17:29 +00:00
import "../components/effects/" as MoneroEffects
import moneroComponents.Clipboard 1.0
import moneroComponents.Wallet 1.0
import moneroComponents.WalletManager 1.0
import moneroComponents.TransactionHistory 1.0
import moneroComponents.TransactionHistoryModel 1.0
import moneroComponents.Subaddress 1.0
import moneroComponents.SubaddressModel 1.0
import "../js/TxUtils.js" as TxUtils
Rectangle {
id: pageReceive
2017-12-08 23:01:10 +00:00
color: "transparent"
property var model
property alias receiveHeight: mainLayout.height
function renameSubaddressLabel(_index){
inputDialog.labelText = qsTr("Set the label of the selected address:") + translationManager.emptyString;
inputDialog.onAcceptedCallback = function() {
appWindow.currentWallet.subaddress.setLabel(appWindow.currentWallet.currentSubaddressAccount, _index, inputDialog.inputText);
}
inputDialog.onRejectedCallback = null;
2019-12-08 23:44:39 +00:00
inputDialog.open(appWindow.currentWallet.getSubaddressLabel(appWindow.currentWallet.currentSubaddressAccount, _index))
}
Clipboard { id: clipboard }
/* main layout */
ColumnLayout {
id: mainLayout
2019-09-05 22:11:12 +00:00
anchors.margins: 20
2019-04-25 19:09:23 +00:00
anchors.topMargin: 40
2017-04-03 16:51:55 +00:00
anchors.left: parent.left
anchors.top: parent.top
anchors.right: parent.right
spacing: 15
2017-04-03 16:51:55 +00:00
ColumnLayout {
id: selectedAddressDetailsColumn
Layout.alignment: Qt.AlignHCenter
spacing: 0
property int qrSize: 220
Rectangle {
id: qrContainer
color: MoneroComponents.Style.blackTheme ? "white" : "transparent"
Layout.fillWidth: true
Layout.alignment: Qt.AlignHCenter
Layout.maximumWidth: parent.qrSize
Layout.preferredHeight: width
radius: 4
Image {
id: qrCode
anchors.fill: parent
anchors.margins: 1
smooth: false
fillMode: Image.PreserveAspectFit
source: "image://qrcode/" + TxUtils.makeQRCodeString(appWindow.current_address)
MouseArea {
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
acceptedButtons: Qt.LeftButton | Qt.RightButton
onClicked: {
if (mouse.button == Qt.LeftButton){
selectedAddressDetailsColumn.qrSize = selectedAddressDetailsColumn.qrSize == 220 ? 300 : 220;
} else if (mouse.button == Qt.RightButton){
qrMenu.x = this.mouseX;
qrMenu.y = this.mouseY;
qrMenu.open()
}
}
}
}
Menu {
id: qrMenu
title: "QrCode"
MenuItem {
text: qsTr("Save as Image") + translationManager.emptyString;
onTriggered: qrFileDialog.open()
}
}
}
MoneroComponents.TextPlain {
id: selectedaddressIndex
Layout.alignment: Qt.AlignHCenter
Layout.preferredWidth: 220
Layout.maximumWidth: 220
Layout.topMargin: 15
horizontalAlignment: Text.AlignHCenter
text: qsTr("Address #") + subaddressListView.currentIndex + translationManager.emptyString
wrapMode: Text.WordWrap
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 17
textFormat: Text.RichText
color: MoneroComponents.Style.defaultFontColor
themeTransition: false
}
MoneroComponents.TextPlain {
id: selectedAddressDrescription
Layout.alignment: Qt.AlignHCenter
Layout.preferredWidth: 220
Layout.maximumWidth: 220
Layout.topMargin: 10
horizontalAlignment: Text.AlignHCenter
text: "(" + qsTr("no label") + ")" + translationManager.emptyString
wrapMode: Text.WordWrap
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 17
textFormat: Text.RichText
color: selectedAddressDrescriptionMouseArea.containsMouse ? MoneroComponents.Style.orange : MoneroComponents.Style.dimmedFontColor
themeTransition: false
tooltip: subaddressListView.currentIndex > 0 ? qsTr("Edit address label") : "" + translationManager.emptyString
MouseArea {
id: selectedAddressDrescriptionMouseArea
visible: subaddressListView.currentIndex > 0
hoverEnabled: true
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onEntered: parent.tooltip ? parent.tooltipPopup.open() : ""
onExited: parent.tooltip ? parent.tooltipPopup.close() : ""
onClicked: {
renameSubaddressLabel(appWindow.current_subaddress_table_index);
}
}
}
MoneroComponents.TextPlain {
id: selectedAddress
Layout.alignment: Qt.AlignHCenter
Layout.maximumWidth: 300
Layout.topMargin: 11
text: appWindow.current_address ? appWindow.current_address : ""
horizontalAlignment: TextInput.AlignHCenter
wrapMode: Text.Wrap
textFormat: Text.RichText
color: selectedAddressMouseArea.containsMouse ? MoneroComponents.Style.orange : MoneroComponents.Style.defaultFontColor
font.pixelSize: 15
font.family: MoneroComponents.Style.fontRegular.name
themeTransition: false
tooltip: qsTr("Copy address to clipboard") + translationManager.emptyString
MouseArea {
id: selectedAddressMouseArea
hoverEnabled: true
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onEntered: parent.tooltip ? parent.tooltipPopup.open() : ""
onExited: parent.tooltip ? parent.tooltipPopup.close() : ""
onClicked: {
clipboard.setText(appWindow.current_address);
appWindow.showStatusMessage(qsTr("Address copied to clipboard") + translationManager.emptyString, 3);
}
}
}
MoneroComponents.StandardButton {
Layout.preferredWidth: 220
Layout.alignment: Qt.AlignHCenter
Layout.topMargin: 18
small: true
text: qsTr("Show on device") + translationManager.emptyString
fontSize: 14
visible: appWindow.currentWallet ? appWindow.currentWallet.isHwBacked() : false
onClicked: {
appWindow.currentWallet.deviceShowAddressAsync(
appWindow.currentWallet.currentSubaddressAccount,
appWindow.current_subaddress_table_index,
'');
}
}
}
ColumnLayout {
id: addressRow
spacing: 0
RowLayout {
spacing: 0
MoneroComponents.LabelSubheader {
Layout.fillWidth: true
fontSize: 24
textFormat: Text.RichText
text: qsTr("Addresses") + translationManager.emptyString
}
MoneroComponents.StandardButton {
id: createAddressButton
small: true
text: qsTr("Create new address") + translationManager.emptyString
fontSize: 13
onClicked: {
inputDialog.labelText = qsTr("Set the label of the new address:") + translationManager.emptyString
inputDialog.onAcceptedCallback = function() {
appWindow.currentWallet.subaddress.addRow(appWindow.currentWallet.currentSubaddressAccount, inputDialog.inputText)
current_subaddress_table_index = appWindow.currentWallet.numSubaddresses(appWindow.currentWallet.currentSubaddressAccount) - 1
subaddressListView.currentIndex = current_subaddress_table_index
}
inputDialog.onRejectedCallback = null;
inputDialog.open()
}
Rectangle {
anchors.top: createAddressButton.bottom
anchors.topMargin: 8
anchors.left: createAddressButton.left
anchors.right: createAddressButton.right
height: 2
color: MoneroComponents.Style.appWindowBorderColor
MoneroEffects.ColorTransition {
targetObj: parent
blackColor: MoneroComponents.Style._b_appWindowBorderColor
whiteColor: MoneroComponents.Style._w_appWindowBorderColor
}
}
}
}
ColumnLayout {
id: subaddressListRow
2019-04-25 19:09:23 +00:00
property int subaddressListItemHeight: 50
Layout.topMargin: 6
Layout.fillWidth: true
Layout.minimumWidth: 240
Layout.preferredHeight: subaddressListItemHeight * subaddressListView.count
visible: subaddressListView.count >= 1
ListView {
id: subaddressListView
Layout.fillWidth: true
2019-07-21 19:51:47 +00:00
Layout.fillHeight: true
clip: true
boundsBehavior: ListView.StopAtBounds
2019-04-16 09:09:46 +00:00
interactive: false
delegate: Rectangle {
id: tableItem2
height: subaddressListRow.subaddressListItemHeight
2020-06-12 01:09:18 +00:00
width: parent ? parent.width : undefined
Layout.fillWidth: true
color: itemMouseArea.containsMouse || index === appWindow.current_subaddress_table_index ? MoneroComponents.Style.titleBarButtonHoverColor : "transparent"
Rectangle{
anchors.right: parent.right
anchors.left: parent.left
anchors.top: parent.top
height: 1
2019-04-11 01:17:29 +00:00
color: MoneroComponents.Style.appWindowBorderColor
visible: index !== 0
2019-04-11 01:17:29 +00:00
MoneroEffects.ColorTransition {
targetObj: parent
blackColor: MoneroComponents.Style._b_appWindowBorderColor
whiteColor: MoneroComponents.Style._w_appWindowBorderColor
}
}
Rectangle {
anchors.fill: parent
2018-12-19 23:06:23 +00:00
anchors.topMargin: 5
anchors.rightMargin: 90
color: "transparent"
2018-12-08 15:55:29 +00:00
MoneroComponents.Label {
id: idLabel
2019-04-11 01:17:29 +00:00
color: index === appWindow.current_subaddress_table_index ? MoneroComponents.Style.defaultFontColor : "#757575"
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
2019-04-25 19:09:23 +00:00
anchors.leftMargin: 6
2019-04-16 09:09:46 +00:00
fontSize: 16
text: "#" + index
2019-04-11 01:17:29 +00:00
themeTransition: false
}
2018-12-08 15:55:29 +00:00
MoneroComponents.Label {
id: nameLabel
color: index === appWindow.current_subaddress_table_index ? MoneroComponents.Style.defaultFontColor : MoneroComponents.Style.dimmedFontColor
anchors.verticalCenter: parent.verticalCenter
anchors.left: idLabel.right
2019-04-25 19:09:23 +00:00
anchors.leftMargin: 6
2019-04-16 09:09:46 +00:00
fontSize: 16
text: label
elide: Text.ElideRight
textWidth: addressLabel.x - nameLabel.x - 1
2019-04-11 01:17:29 +00:00
themeTransition: false
}
2018-12-08 15:55:29 +00:00
MoneroComponents.Label {
id: addressLabel
2019-04-11 01:17:29 +00:00
color: MoneroComponents.Style.defaultFontColor
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.right
2019-04-16 09:09:46 +00:00
anchors.leftMargin: -addressLabel.width - 5
fontSize: 16
fontFamily: MoneroComponents.Style.fontMonoRegular.name;
text: TxUtils.addressTruncatePretty(address, mainLayout.width < 520 ? 1 : (mainLayout.width < 650 ? 2 : 3))
2019-04-11 01:17:29 +00:00
themeTransition: false
}
MouseArea {
id: itemMouseArea
cursorShape: Qt.PointingHandCursor
anchors.fill: parent
hoverEnabled: true
2019-04-11 01:17:29 +00:00
onClicked: subaddressListView.currentIndex = index;
}
}
2019-04-16 09:09:46 +00:00
RowLayout {
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
2019-04-16 09:09:46 +00:00
anchors.rightMargin: 6
2019-04-11 01:17:29 +00:00
height: 21
2019-04-16 09:09:46 +00:00
spacing: 10
MoneroComponents.IconButton {
fontAwesomeFallbackIcon: FontAwesome.searchPlus
fontAwesomeFallbackSize: 22
color: MoneroComponents.Style.defaultFontColor
fontAwesomeFallbackOpacity: 0.5
Layout.preferredWidth: 23
Layout.preferredHeight: 21
tooltip: qsTr("See transactions") + translationManager.emptyString
onClicked: doSearchInHistory(address)
}
2019-04-16 09:09:46 +00:00
MoneroComponents.IconButton {
id: renameButton
image: "qrc:///images/edit.svg"
fontAwesomeFallbackIcon: FontAwesome.edit
fontAwesomeFallbackSize: 22
2019-04-16 09:09:46 +00:00
color: MoneroComponents.Style.defaultFontColor
opacity: isOpenGL ? 0.5 : 1
fontAwesomeFallbackOpacity: 0.5
2019-04-16 09:09:46 +00:00
Layout.preferredWidth: 23
Layout.preferredHeight: 21
visible: index !== 0
tooltip: qsTr("Edit address label") + translationManager.emptyString
2019-04-16 09:09:46 +00:00
onClicked: {
renameSubaddressLabel(index);
}
}
2019-04-16 09:09:46 +00:00
MoneroComponents.IconButton {
id: copyButton
image: "qrc:///images/copy.svg"
fontAwesomeFallbackIcon: FontAwesome.clipboard
fontAwesomeFallbackSize: 22
2019-04-16 09:09:46 +00:00
color: MoneroComponents.Style.defaultFontColor
opacity: isOpenGL ? 0.5 : 1
fontAwesomeFallbackOpacity: 0.5
2019-04-16 09:09:46 +00:00
Layout.preferredWidth: 16
Layout.preferredHeight: 21
tooltip: qsTr("Copy address to clipboard") + translationManager.emptyString
2019-04-16 09:09:46 +00:00
onClicked: {
console.log("Address copied to clipboard");
clipboard.setText(address);
appWindow.showStatusMessage(qsTr("Address copied to clipboard"),3);
}
}
}
}
onCurrentItemChanged: {
// reset global vars
2018-12-08 15:55:29 +00:00
appWindow.current_subaddress_table_index = subaddressListView.currentIndex;
appWindow.current_address = appWindow.currentWallet.address(
appWindow.currentWallet.currentSubaddressAccount,
subaddressListView.currentIndex
);
if (subaddressListView.currentIndex == 0) {
selectedAddressDrescription.text = qsTr("Primary address") + translationManager.emptyString;
} else {
var selectedAddressLabel = appWindow.currentWallet.getSubaddressLabel(appWindow.currentWallet.currentSubaddressAccount, appWindow.current_subaddress_table_index);
if (selectedAddressLabel == "") {
selectedAddressDrescription.text = "(" + qsTr("no label") + ")" + translationManager.emptyString
} else {
selectedAddressDrescription.text = selectedAddressLabel
}
}
}
}
}
Rectangle {
2019-04-11 01:17:29 +00:00
color: MoneroComponents.Style.appWindowBorderColor
Layout.fillWidth: true
height: 1
2019-04-11 01:17:29 +00:00
MoneroEffects.ColorTransition {
targetObj: parent
blackColor: MoneroComponents.Style._b_appWindowBorderColor
whiteColor: MoneroComponents.Style._w_appWindowBorderColor
}
}
}
MessageDialog {
id: receivePageDialog
standardButtons: StandardButton.Ok
}
2017-01-23 04:15:49 +00:00
FileDialog {
id: qrFileDialog
title: qsTr("Please choose a name") + translationManager.emptyString
2017-01-23 04:15:49 +00:00
folder: shortcuts.pictures
selectExisting: false
nameFilters: ["Image (*.png)"]
2017-01-23 04:15:49 +00:00
onAccepted: {
2018-12-08 15:55:29 +00:00
if(!walletManager.saveQrCode(TxUtils.makeQRCodeString(appWindow.current_address), walletManager.urlToLocalPath(fileUrl))) {
2017-01-23 04:15:49 +00:00
console.log("Failed to save QrCode to file " + walletManager.urlToLocalPath(fileUrl) )
receivePageDialog.title = qsTr("Save QrCode") + translationManager.emptyString;
receivePageDialog.text = qsTr("Failed to save QrCode to ") + walletManager.urlToLocalPath(fileUrl) + translationManager.emptyString;
receivePageDialog.icon = StandardIcon.Error
receivePageDialog.open()
2017-01-23 04:15:49 +00:00
}
}
}
}
2016-10-04 10:15:29 +00:00
function onPageCompleted() {
console.log("Receive page loaded");
subaddressListView.model = appWindow.currentWallet.subaddressModel;
2016-10-04 10:15:29 +00:00
if (appWindow.currentWallet) {
2018-12-08 15:55:29 +00:00
appWindow.current_address = appWindow.currentWallet.address(appWindow.currentWallet.currentSubaddressAccount, 0)
appWindow.currentWallet.subaddress.refresh(appWindow.currentWallet.currentSubaddressAccount)
if (subaddressListView.currentIndex == -1) {
subaddressListView.currentIndex = 0;
}
2016-10-04 10:15:29 +00:00
}
}
2018-12-18 19:06:29 +00:00
function clearFields() {
2019-01-14 00:02:44 +00:00
// @TODO: add fields
2018-12-18 19:06:29 +00:00
}
function onPageClosed() {
}
}