mirror of
https://github.com/monero-project/monero-gui.git
synced 2024-11-17 00:07:51 +00:00
Subaddresses minimal version: supports default account only
This commit is contained in:
parent
3b069ec049
commit
cee0474e37
28 changed files with 934 additions and 56 deletions
|
@ -112,7 +112,7 @@ Rectangle {
|
|||
}, State {
|
||||
name: "Receive"
|
||||
PropertyChanges { target: root; currentView: receiveView }
|
||||
PropertyChanges { target: mainFlickable; contentHeight: minHeight }
|
||||
PropertyChanges { target: mainFlickable; contentHeight: 1000 * scaleRatio }
|
||||
}, State {
|
||||
name: "TxKey"
|
||||
PropertyChanges { target: root; currentView: txkeyView }
|
||||
|
|
|
@ -266,6 +266,45 @@ ListView {
|
|||
|
||||
}
|
||||
}
|
||||
Item { //separator
|
||||
width: 100
|
||||
height: 14
|
||||
}
|
||||
// -- "Received by" title
|
||||
Text {
|
||||
anchors.bottom: parent.bottom
|
||||
font.family: "Arial"
|
||||
font.pixelSize: 12
|
||||
color: "#535353"
|
||||
text: (isOut ? qsTr("Spent from:") : qsTr("Received by:")) + translationManager.emptyString
|
||||
}
|
||||
Item { //separator
|
||||
width: 5
|
||||
height: 14
|
||||
}
|
||||
// -- "Index" value
|
||||
Text {
|
||||
anchors.bottom: parent.bottom
|
||||
font.family: "Arial"
|
||||
font.pixelSize: 13
|
||||
font.bold: true
|
||||
color: "#545454"
|
||||
text: "#" + subaddrIndex
|
||||
}
|
||||
Item { //separator
|
||||
width: 5
|
||||
height: 14
|
||||
}
|
||||
// -- "Label" value
|
||||
Text {
|
||||
anchors.bottom: parent.bottom
|
||||
font.family: "Arial"
|
||||
font.pixelSize: 13
|
||||
color: "#545454"
|
||||
text: label
|
||||
elide: Text.ElideRight
|
||||
width: detailsButton.x - x - 30
|
||||
}
|
||||
}
|
||||
|
||||
// -- "Date", "Balance" and "Amound" section
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
import QtQuick 2.0
|
||||
|
||||
Item {
|
||||
property alias image : buttonImage
|
||||
property alias imageSource : buttonImage.source
|
||||
|
||||
signal clicked(var mouse)
|
||||
|
@ -53,7 +54,8 @@ Item {
|
|||
MouseArea {
|
||||
id: buttonArea
|
||||
anchors.fill: parent
|
||||
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
|
||||
onPressed: {
|
||||
buttonImage.x = buttonImage.x + 2
|
||||
|
|
181
components/InputDialog.qml
Normal file
181
components/InputDialog.qml
Normal file
|
@ -0,0 +1,181 @@
|
|||
// Copyright (c) 2014-2018, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// 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.
|
||||
|
||||
import QtQuick 2.0
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Dialogs 1.2
|
||||
import QtQuick.Layouts 1.1
|
||||
import QtQuick.Controls.Styles 1.4
|
||||
import QtQuick.Window 2.0
|
||||
|
||||
import "../components" as MoneroComponents
|
||||
|
||||
Item {
|
||||
id: root
|
||||
visible: false
|
||||
Rectangle {
|
||||
id: bg
|
||||
z: parent.z + 1
|
||||
anchors.fill: parent
|
||||
color: "white"
|
||||
opacity: 0.9
|
||||
}
|
||||
|
||||
property alias labelText: label.text
|
||||
property alias inputText: input.text
|
||||
|
||||
// same signals as Dialog has
|
||||
signal accepted()
|
||||
signal rejected()
|
||||
|
||||
function open() {
|
||||
leftPanel.enabled = false
|
||||
middlePanel.enabled = false
|
||||
titleBar.enabled = false
|
||||
show()
|
||||
root.visible = true;
|
||||
input.focus = true;
|
||||
input.text = "";
|
||||
}
|
||||
|
||||
function close() {
|
||||
leftPanel.enabled = true
|
||||
middlePanel.enabled = true
|
||||
titleBar.enabled = true
|
||||
root.visible = false;
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
z: bg.z + 1
|
||||
id: mainLayout
|
||||
spacing: 10
|
||||
anchors { fill: parent; margins: 35 }
|
||||
|
||||
ColumnLayout {
|
||||
id: column
|
||||
//anchors {fill: parent; margins: 16 }
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
|
||||
Label {
|
||||
id: label
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
// Layout.columnSpan: 2
|
||||
Layout.fillWidth: true
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
font.pixelSize: 18 * scaleRatio
|
||||
font.family: "Arial"
|
||||
color: "#555555"
|
||||
}
|
||||
|
||||
TextField {
|
||||
id : input
|
||||
focus: true
|
||||
Layout.fillWidth: true
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
horizontalAlignment: TextInput.AlignHCenter
|
||||
verticalAlignment: TextInput.AlignVCenter
|
||||
font.family: "Arial"
|
||||
font.pixelSize: 32 * scaleRatio
|
||||
// echoMode: TextInput.Password
|
||||
KeyNavigation.tab: okButton
|
||||
|
||||
style: TextFieldStyle {
|
||||
renderType: Text.NativeRendering
|
||||
textColor: "#35B05A"
|
||||
// passwordCharacter: "•"
|
||||
// no background
|
||||
background: Rectangle {
|
||||
radius: 0
|
||||
border.width: 0
|
||||
}
|
||||
}
|
||||
Keys.onReturnPressed: {
|
||||
root.close()
|
||||
root.accepted()
|
||||
}
|
||||
Keys.onEscapePressed: {
|
||||
root.close()
|
||||
root.rejected()
|
||||
}
|
||||
}
|
||||
// underline
|
||||
Rectangle {
|
||||
height: 1
|
||||
color: "#DBDBDB"
|
||||
Layout.fillWidth: true
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
anchors.bottomMargin: 3
|
||||
}
|
||||
// padding
|
||||
Rectangle {
|
||||
Layout.fillWidth: true
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
height: 10
|
||||
opacity: 0
|
||||
color: "black"
|
||||
}
|
||||
}
|
||||
// Ok/Cancel buttons
|
||||
RowLayout {
|
||||
id: buttons
|
||||
spacing: 60
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
|
||||
MoneroComponents.StandardButton {
|
||||
id: cancelButton
|
||||
width: 120
|
||||
fontSize: 14
|
||||
shadowReleasedColor: "#FF4304"
|
||||
shadowPressedColor: "#B32D00"
|
||||
releasedColor: "#FF6C3C"
|
||||
pressedColor: "#FF4304"
|
||||
text: qsTr("Cancel") + translationManager.emptyString
|
||||
KeyNavigation.tab: input
|
||||
onClicked: {
|
||||
root.close()
|
||||
root.rejected()
|
||||
}
|
||||
}
|
||||
MoneroComponents.StandardButton {
|
||||
id: okButton
|
||||
width: 120
|
||||
fontSize: 14
|
||||
shadowReleasedColor: "#FF4304"
|
||||
shadowPressedColor: "#B32D00"
|
||||
releasedColor: "#FF6C3C"
|
||||
pressedColor: "#FF4304"
|
||||
text: qsTr("Ok")
|
||||
KeyNavigation.tab: cancelButton
|
||||
onClicked: {
|
||||
root.close()
|
||||
root.accepted()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -37,6 +37,7 @@ Item {
|
|||
property alias cursorPosition: input.cursorPosition
|
||||
property alias echoMode: input.echoMode
|
||||
property int fontSize: 18 * scaleRatio
|
||||
property bool showBorder: true
|
||||
property bool error: false
|
||||
signal editingFinished()
|
||||
signal accepted();
|
||||
|
@ -52,6 +53,7 @@ Item {
|
|||
}
|
||||
|
||||
Rectangle {
|
||||
visible: showBorder
|
||||
anchors.fill: parent
|
||||
anchors.bottomMargin: 1 * scaleRatio
|
||||
color: "#DBDBDB"
|
||||
|
|
109
components/SubaddressTable.qml
Normal file
109
components/SubaddressTable.qml
Normal file
|
@ -0,0 +1,109 @@
|
|||
// Copyright (c) 2014-2018, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// 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.
|
||||
|
||||
import QtQuick 2.0
|
||||
import moneroComponents.Clipboard 1.0
|
||||
|
||||
ListView {
|
||||
id: listView
|
||||
clip: true
|
||||
boundsBehavior: ListView.StopAtBounds
|
||||
highlightMoveDuration: 0
|
||||
|
||||
delegate: Rectangle {
|
||||
id: delegate
|
||||
height: 64
|
||||
width: listView.width
|
||||
|
||||
LineEdit {
|
||||
id: addressLine
|
||||
fontSize: 12
|
||||
readOnly: true
|
||||
width: parent.width
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.margins: 5
|
||||
onTextChanged: cursorPosition = 0
|
||||
text: address
|
||||
showBorder: false
|
||||
|
||||
IconButton {
|
||||
id: clipboardButton
|
||||
imageSource: "../images/copyToClipboard.png"
|
||||
onClicked: {
|
||||
console.log(addressLine.text + " copied to clipboard");
|
||||
clipboard.setText(addressLine.text);
|
||||
appWindow.showStatusMessage(qsTr("Address copied to clipboard"),3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
id: indexText
|
||||
anchors.top: addressLine.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 20
|
||||
font.family: "Arial"
|
||||
font.bold: true
|
||||
font.pixelSize: 12
|
||||
color: "#444444"
|
||||
text: "#" + index
|
||||
}
|
||||
|
||||
Text {
|
||||
id: labelText
|
||||
anchors.top: addressLine.bottom
|
||||
anchors.left: indexText.right
|
||||
anchors.right: parent.right
|
||||
anchors.leftMargin: 10
|
||||
font.family: "Arial"
|
||||
font.bold: true
|
||||
font.pixelSize: 12
|
||||
color: "#444444"
|
||||
text: label
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
z: 5
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: clipboardButton.width
|
||||
onClicked: listView.currentIndex = index
|
||||
}
|
||||
}
|
||||
|
||||
highlight: Rectangle {
|
||||
height: 64
|
||||
color: '#FF4304'
|
||||
opacity: 0.2
|
||||
z: 2
|
||||
}
|
||||
}
|
8
main.cpp
8
main.cpp
|
@ -50,6 +50,8 @@
|
|||
#include "model/TransactionHistorySortFilterModel.h"
|
||||
#include "AddressBook.h"
|
||||
#include "model/AddressBookModel.h"
|
||||
#include "Subaddress.h"
|
||||
#include "model/SubaddressModel.h"
|
||||
#include "wallet/api/wallet2_api.h"
|
||||
#include "MainApp.h"
|
||||
|
||||
|
@ -133,6 +135,12 @@ int main(int argc, char *argv[])
|
|||
qmlRegisterUncreatableType<AddressBook>("moneroComponents.AddressBook", 1, 0, "AddressBook",
|
||||
"AddressBook can't be instantiated directly");
|
||||
|
||||
qmlRegisterUncreatableType<SubaddressModel>("moneroComponents.SubaddressModel", 1, 0, "SubaddressModel",
|
||||
"SubaddressModel can't be instantiated directly");
|
||||
|
||||
qmlRegisterUncreatableType<Subaddress>("moneroComponents.Subaddress", 1, 0, "Subaddress",
|
||||
"Subaddress can't be instantiated directly");
|
||||
|
||||
qRegisterMetaType<PendingTransaction::Priority>();
|
||||
qRegisterMetaType<TransactionInfo::Direction>();
|
||||
qRegisterMetaType<TransactionHistoryModel::TransactionInfoRole>();
|
||||
|
|
45
main.qml
45
main.qml
|
@ -310,8 +310,10 @@ ApplicationWindow {
|
|||
}
|
||||
|
||||
function updateBalance() {
|
||||
middlePanel.unlockedBalanceText = leftPanel.unlockedBalanceText = middlePanel.state === "Receive" ? qsTr("HIDDEN") : walletManager.displayAmount(currentWallet.unlockedBalance);
|
||||
middlePanel.balanceText = leftPanel.balanceText = middlePanel.state === "Receive" ? qsTr("HIDDEN") : walletManager.displayAmount(currentWallet.balance);
|
||||
if (!currentWallet)
|
||||
return;
|
||||
middlePanel.unlockedBalanceText = leftPanel.unlockedBalanceText = middlePanel.state === "Receive" ? qsTr("HIDDEN") : walletManager.displayAmount(currentWallet.unlockedBalance(currentWallet.currentSubaddressAccount));
|
||||
middlePanel.balanceText = leftPanel.balanceText = middlePanel.state === "Receive" ? qsTr("HIDDEN") : walletManager.displayAmount(currentWallet.balance(currentWallet.currentSubaddressAccount));
|
||||
}
|
||||
|
||||
function onWalletConnectionStatusChanged(status){
|
||||
|
@ -329,7 +331,7 @@ ApplicationWindow {
|
|||
}
|
||||
// initialize transaction history once wallet is initialized first time;
|
||||
if (!walletInitialized) {
|
||||
currentWallet.history.refresh()
|
||||
currentWallet.history.refresh(currentWallet.currentSubaddressAccount)
|
||||
walletInitialized = true
|
||||
}
|
||||
}
|
||||
|
@ -377,7 +379,7 @@ ApplicationWindow {
|
|||
if(foundNewBlock) {
|
||||
foundNewBlock = false;
|
||||
console.log("New block found - updating history")
|
||||
currentWallet.history.refresh()
|
||||
currentWallet.history.refresh(currentWallet.currentSubaddressAccount)
|
||||
timeToUnlock = currentWallet.history.minutesToUnlock
|
||||
leftPanel.minutesToUnlockTxt = (timeToUnlock > 0)? (timeToUnlock == 20)? qsTr("Unlocked balance (waiting for block)") : qsTr("Unlocked balance (~%1 min)").arg(timeToUnlock) : qsTr("Unlocked balance");
|
||||
}
|
||||
|
@ -453,6 +455,9 @@ ApplicationWindow {
|
|||
console.log("Saving wallet after first refresh");
|
||||
currentWallet.store()
|
||||
isNewWallet = false
|
||||
|
||||
// Update History
|
||||
currentWallet.history.refresh(currentWallet.currentSubaddressAccount);
|
||||
}
|
||||
|
||||
// recovering from seed is finished after first refresh
|
||||
|
@ -463,7 +468,7 @@ ApplicationWindow {
|
|||
|
||||
// Update history on every refresh if it's empty
|
||||
if(currentWallet.history.count == 0)
|
||||
currentWallet.history.refresh()
|
||||
currentWallet.history.refresh(currentWallet.currentSubaddressAccount)
|
||||
|
||||
onWalletUpdate();
|
||||
}
|
||||
|
@ -526,19 +531,21 @@ ApplicationWindow {
|
|||
currentWallet.refresh()
|
||||
console.log("Confirmed money found")
|
||||
// history refresh is handled by walletUpdated
|
||||
currentWallet.history.refresh(currentWallet.currentSubaddressAccount) // this will refresh model
|
||||
currentWallet.subaddress.refresh(currentWallet.currentSubaddressAccount)
|
||||
}
|
||||
|
||||
function onWalletUnconfirmedMoneyReceived(txId, amount) {
|
||||
// refresh history
|
||||
console.log("unconfirmed money found")
|
||||
currentWallet.history.refresh()
|
||||
currentWallet.history.refresh(currentWallet.currentSubaddressAccount)
|
||||
}
|
||||
|
||||
function onWalletMoneySent(txId, amount) {
|
||||
// refresh transaction history here
|
||||
console.log("money sent found")
|
||||
currentWallet.refresh()
|
||||
currentWallet.history.refresh() // this will refresh model
|
||||
currentWallet.history.refresh(currentWallet.currentSubaddressAccount) // this will refresh model
|
||||
}
|
||||
|
||||
function walletsFound() {
|
||||
|
@ -584,8 +591,11 @@ ApplicationWindow {
|
|||
// here we show confirmation popup;
|
||||
|
||||
transactionConfirmationPopup.title = qsTr("Confirmation") + translationManager.emptyString
|
||||
transactionConfirmationPopup.text = qsTr("Please confirm transaction:\n")
|
||||
+ (address === "" ? "" : (qsTr("\nAddress: ") + address))
|
||||
transactionConfirmationPopup.text = qsTr("Please confirm transaction:\n");
|
||||
for (var i = 0; i < transaction.subaddrIndices.length; ++i)
|
||||
transactionConfirmationPopup.text += qsTr("\nSpending address index: ") + transaction.subaddrIndices[i]
|
||||
transactionConfirmationPopup.text +=
|
||||
(address === "" ? "" : (qsTr("\n\nAddress: ") + address))
|
||||
+ (paymentId === "" ? "" : (qsTr("\nPayment ID: ") + paymentId))
|
||||
+ qsTr("\n\nAmount: ") + walletManager.displayAmount(transaction.amount)
|
||||
+ qsTr("\nFee: ") + walletManager.displayAmount(transaction.fee)
|
||||
|
@ -1185,6 +1195,23 @@ ApplicationWindow {
|
|||
}
|
||||
}
|
||||
|
||||
InputDialog {
|
||||
id: inputDialog
|
||||
visible: false
|
||||
z: parent.z + 1
|
||||
anchors.fill: parent
|
||||
property var onAcceptedCallback
|
||||
property var onRejectedCallback
|
||||
onAccepted: {
|
||||
if (onAcceptedCallback)
|
||||
onAcceptedCallback()
|
||||
}
|
||||
onRejected: {
|
||||
if (onRejectedCallback)
|
||||
onRejectedCallback()
|
||||
}
|
||||
}
|
||||
|
||||
DaemonManagerDialog {
|
||||
id: daemonManagerDialog
|
||||
onRejected: {
|
||||
|
|
|
@ -35,6 +35,8 @@ HEADERS += \
|
|||
src/QR-Code-generator/QrSegment.hpp \
|
||||
src/model/AddressBookModel.h \
|
||||
src/libwalletqt/AddressBook.h \
|
||||
src/model/SubaddressModel.h \
|
||||
src/libwalletqt/Subaddress.h \
|
||||
src/zxcvbn-c/zxcvbn.h \
|
||||
src/libwalletqt/UnsignedTransaction.h \
|
||||
MainApp.h
|
||||
|
@ -58,6 +60,8 @@ SOURCES += main.cpp \
|
|||
src/QR-Code-generator/QrSegment.cpp \
|
||||
src/model/AddressBookModel.cpp \
|
||||
src/libwalletqt/AddressBook.cpp \
|
||||
src/model/SubaddressModel.cpp \
|
||||
src/libwalletqt/Subaddress.cpp \
|
||||
src/zxcvbn-c/zxcvbn.c \
|
||||
src/libwalletqt/UnsignedTransaction.cpp \
|
||||
MainApp.cpp
|
||||
|
|
|
@ -546,7 +546,7 @@ Rectangle {
|
|||
|
||||
function onPageCompleted() {
|
||||
if(currentWallet != null && typeof currentWallet.history !== "undefined" ) {
|
||||
currentWallet.history.refresh()
|
||||
currentWallet.history.refresh(currentWallet.currentSubaddressAccount)
|
||||
table.addressBookModel = currentWallet ? currentWallet.addressBookModel : null
|
||||
transactionTypeDropdown.update()
|
||||
}
|
||||
|
|
|
@ -151,7 +151,7 @@ Rectangle {
|
|||
releasedColor: "#FF6C3C"
|
||||
pressedColor: "#FF4304"
|
||||
onClicked: {
|
||||
var success = walletManager.startMining(appWindow.currentWallet.address, soloMinerThreadsLine.text, persistentSettings.allow_background_mining, persistentSettings.miningIgnoreBattery)
|
||||
var success = walletManager.startMining(appWindow.currentWallet.address(0, 0), soloMinerThreadsLine.text, persistentSettings.allow_background_mining, persistentSettings.miningIgnoreBattery)
|
||||
if (success) {
|
||||
update()
|
||||
} else {
|
||||
|
|
|
@ -38,14 +38,17 @@ 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
|
||||
|
||||
Rectangle {
|
||||
|
||||
id: pageReceive
|
||||
color: "#F0EEEE"
|
||||
property alias addressText : addressLine.text
|
||||
property var model
|
||||
property var current_address
|
||||
property alias addressText : pageReceive.current_address
|
||||
property alias paymentIdText : paymentIdLine.text
|
||||
property alias integratedAddressText : integratedAddressLine.text
|
||||
property var model
|
||||
property string trackingLineText: ""
|
||||
|
||||
function updatePaymentId(payment_id) {
|
||||
|
@ -80,7 +83,7 @@ Rectangle {
|
|||
function makeQRCodeString() {
|
||||
var s = "monero:"
|
||||
var nfields = 0
|
||||
s += addressLine.text
|
||||
s += current_address;
|
||||
var amount = amountLine.text.trim()
|
||||
if (amount !== "") {
|
||||
s += (nfields++ ? "&" : "?")
|
||||
|
@ -192,27 +195,66 @@ Rectangle {
|
|||
id: addressRow
|
||||
Label {
|
||||
id: addressLabel
|
||||
text: qsTr("Address") + translationManager.emptyString
|
||||
text: qsTr("Addresses") + translationManager.emptyString
|
||||
width: mainLayout.labelWidth
|
||||
}
|
||||
|
||||
LineEdit {
|
||||
id: addressLine
|
||||
fontSize: mainLayout.lineEditFontSize
|
||||
placeholderText: qsTr("ReadOnly wallet address displayed here") + translationManager.emptyString;
|
||||
readOnly: true
|
||||
width: mainLayout.editWidth
|
||||
Rectangle {
|
||||
id: tableRect
|
||||
Layout.fillWidth: true
|
||||
onTextChanged: cursorPosition = 0
|
||||
Layout.preferredHeight: 200
|
||||
color: "#FFFFFF"
|
||||
Scroll {
|
||||
id: flickableScroll
|
||||
anchors.right: table.right
|
||||
anchors.top: table.top
|
||||
anchors.bottom: table.bottom
|
||||
flickable: table
|
||||
}
|
||||
SubaddressTable {
|
||||
id: table
|
||||
anchors.fill: parent
|
||||
onContentYChanged: flickableScroll.flickableContentYChanged()
|
||||
onCurrentItemChanged: {
|
||||
current_address = appWindow.currentWallet.address(appWindow.currentWallet.currentSubaddressAccount, table.currentIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IconButton {
|
||||
imageSource: "../images/copyToClipboard.png"
|
||||
RowLayout {
|
||||
spacing: 20
|
||||
StandardButton {
|
||||
shadowReleasedColor: "#FF4304"
|
||||
shadowPressedColor: "#B32D00"
|
||||
releasedColor: "#FF6C3C"
|
||||
pressedColor: "#FF4304"
|
||||
text: qsTr("Create new address") + translationManager.emptyString;
|
||||
onClicked: {
|
||||
if (addressLine.text.length > 0) {
|
||||
console.log(addressLine.text + " copied to clipboard")
|
||||
clipboard.setText(addressLine.text)
|
||||
appWindow.showStatusMessage(qsTr("Address copied to clipboard"),3)
|
||||
inputDialog.labelText = qsTr("Set the label of the new address:") + translationManager.emptyString
|
||||
inputDialog.inputText = qsTr("(Untitled)")
|
||||
inputDialog.onAcceptedCallback = function() {
|
||||
appWindow.currentWallet.subaddress.addRow(appWindow.currentWallet.currentSubaddressAccount, inputDialog.inputText)
|
||||
table.currentIndex = appWindow.currentWallet.numSubaddresses() - 1
|
||||
}
|
||||
inputDialog.onRejectedCallback = null;
|
||||
inputDialog.open()
|
||||
}
|
||||
}
|
||||
StandardButton {
|
||||
shadowReleasedColor: "#FF4304"
|
||||
shadowPressedColor: "#B32D00"
|
||||
releasedColor: "#FF6C3C"
|
||||
pressedColor: "#FF4304"
|
||||
enabled: table.currentIndex > 0
|
||||
text: qsTr("Rename") + translationManager.emptyString;
|
||||
onClicked: {
|
||||
inputDialog.labelText = qsTr("Set the label of the selected address:") + translationManager.emptyString
|
||||
inputDialog.inputText = appWindow.currentWallet.getSubaddressLabel(appWindow.currentWallet.currentSubaddressAccount, table.currentIndex)
|
||||
inputDialog.onAcceptedCallback = function() {
|
||||
appWindow.currentWallet.subaddress.setLabel(appWindow.currentWallet.currentSubaddressAccount, table.currentIndex, inputDialog.inputText)
|
||||
}
|
||||
inputDialog.onRejectedCallback = null;
|
||||
inputDialog.open()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -436,11 +478,12 @@ Rectangle {
|
|||
|
||||
function onPageCompleted() {
|
||||
console.log("Receive page loaded");
|
||||
table.model = currentWallet.subaddressModel;
|
||||
|
||||
if (appWindow.currentWallet) {
|
||||
if (addressLine.text.length === 0 || addressLine.text !== appWindow.currentWallet.address) {
|
||||
addressLine.text = appWindow.currentWallet.address
|
||||
}
|
||||
current_address = appWindow.currentWallet.address(appWindow.currentWallet.currentSubaddressAccount, 0)
|
||||
appWindow.currentWallet.subaddress.refresh(appWindow.currentWallet.currentSubaddressAccount)
|
||||
table.currentIndex = 0
|
||||
}
|
||||
|
||||
update()
|
||||
|
|
2
qml.qrc
2
qml.qrc
|
@ -51,6 +51,7 @@
|
|||
<file>tabs/TweetsModel.qml</file>
|
||||
<file>components/Scroll.qml</file>
|
||||
<file>components/AddressBookTable.qml</file>
|
||||
<file>components/SubaddressTable.qml</file>
|
||||
<file>images/deleteIcon.png</file>
|
||||
<file>images/moneroIcon.png</file>
|
||||
<file>components/StandardDropdown.qml</file>
|
||||
|
@ -136,6 +137,7 @@
|
|||
<file>components/IconButton.qml</file>
|
||||
<file>components/PasswordDialog.qml</file>
|
||||
<file>components/NewPasswordDialog.qml</file>
|
||||
<file>components/InputDialog.qml</file>
|
||||
<file>components/ProcessingSplash.qml</file>
|
||||
<file>components/ProgressBar.qml</file>
|
||||
<file>components/StandardDialog.qml</file>
|
||||
|
|
|
@ -50,6 +50,16 @@ quint64 PendingTransaction::txCount() const
|
|||
return m_pimpl->txCount();
|
||||
}
|
||||
|
||||
QList<QVariant> PendingTransaction::subaddrIndices() const
|
||||
{
|
||||
std::vector<std::set<uint32_t>> subaddrIndices = m_pimpl->subaddrIndices();
|
||||
QList<QVariant> result;
|
||||
for (const auto& x : subaddrIndices)
|
||||
for (uint32_t i : x)
|
||||
result.push_back(i);
|
||||
return result;
|
||||
}
|
||||
|
||||
void PendingTransaction::setFilename(const QString &fileName)
|
||||
{
|
||||
m_fileName = fileName;
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
#define PENDINGTRANSACTION_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QList>
|
||||
#include <QVariant>
|
||||
|
||||
#include <wallet/api/wallet2_api.h>
|
||||
|
||||
|
@ -19,6 +21,7 @@ class PendingTransaction : public QObject
|
|||
Q_PROPERTY(quint64 fee READ fee)
|
||||
Q_PROPERTY(QStringList txid READ txid)
|
||||
Q_PROPERTY(quint64 txCount READ txCount)
|
||||
Q_PROPERTY(QList<QVariant> subaddrIndices READ subaddrIndices)
|
||||
|
||||
public:
|
||||
enum Status {
|
||||
|
@ -44,6 +47,7 @@ public:
|
|||
quint64 fee() const;
|
||||
QStringList txid() const;
|
||||
quint64 txCount() const;
|
||||
QList<QVariant> subaddrIndices() const;
|
||||
Q_INVOKABLE void setFilename(const QString &fileName);
|
||||
|
||||
private:
|
||||
|
|
84
src/libwalletqt/Subaddress.cpp
Normal file
84
src/libwalletqt/Subaddress.cpp
Normal file
|
@ -0,0 +1,84 @@
|
|||
// Copyright (c) 2018, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// 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.
|
||||
|
||||
#include "Subaddress.h"
|
||||
#include <QDebug>
|
||||
|
||||
Subaddress::Subaddress(Monero::Subaddress *subaddressImpl, QObject *parent)
|
||||
: QObject(parent), m_subaddressImpl(subaddressImpl)
|
||||
{
|
||||
qDebug(__FUNCTION__);
|
||||
getAll();
|
||||
}
|
||||
|
||||
QList<Monero::SubaddressRow*> Subaddress::getAll(bool update) const
|
||||
{
|
||||
qDebug(__FUNCTION__);
|
||||
|
||||
emit refreshStarted();
|
||||
|
||||
if(update)
|
||||
m_rows.clear();
|
||||
|
||||
if (m_rows.empty()){
|
||||
for (auto &row: m_subaddressImpl->getAll()) {
|
||||
m_rows.append(row);
|
||||
}
|
||||
}
|
||||
|
||||
emit refreshFinished();
|
||||
return m_rows;
|
||||
}
|
||||
|
||||
Monero::SubaddressRow * Subaddress::getRow(int index) const
|
||||
{
|
||||
return m_rows.at(index);
|
||||
}
|
||||
|
||||
void Subaddress::addRow(quint32 accountIndex, const QString &label) const
|
||||
{
|
||||
m_subaddressImpl->addRow(accountIndex, label.toStdString());
|
||||
getAll(true);
|
||||
}
|
||||
|
||||
void Subaddress::setLabel(quint32 accountIndex, quint32 addressIndex, const QString &label) const
|
||||
{
|
||||
m_subaddressImpl->setLabel(accountIndex, addressIndex, label.toStdString());
|
||||
getAll(true);
|
||||
}
|
||||
|
||||
void Subaddress::refresh(quint32 accountIndex) const
|
||||
{
|
||||
m_subaddressImpl->refresh(accountIndex);
|
||||
getAll(true);
|
||||
}
|
||||
|
||||
quint64 Subaddress::count() const
|
||||
{
|
||||
return m_rows.size();
|
||||
}
|
61
src/libwalletqt/Subaddress.h
Normal file
61
src/libwalletqt/Subaddress.h
Normal file
|
@ -0,0 +1,61 @@
|
|||
// Copyright (c) 2018, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// 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.
|
||||
|
||||
#ifndef SUBADDRESS_H
|
||||
#define SUBADDRESS_H
|
||||
|
||||
#include <wallet/api/wallet2_api.h>
|
||||
#include <QObject>
|
||||
#include <QList>
|
||||
#include <QDateTime>
|
||||
|
||||
class Subaddress : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
Q_INVOKABLE QList<Monero::SubaddressRow*> getAll(bool update = false) const;
|
||||
Q_INVOKABLE Monero::SubaddressRow * getRow(int index) const;
|
||||
Q_INVOKABLE void addRow(quint32 accountIndex, const QString &label) const;
|
||||
Q_INVOKABLE void setLabel(quint32 accountIndex, quint32 addressIndex, const QString &label) const;
|
||||
Q_INVOKABLE void refresh(quint32 accountIndex) const;
|
||||
quint64 count() const;
|
||||
|
||||
signals:
|
||||
void refreshStarted() const;
|
||||
void refreshFinished() const;
|
||||
|
||||
public slots:
|
||||
|
||||
private:
|
||||
explicit Subaddress(Monero::Subaddress * subaddressImpl, QObject *parent);
|
||||
friend class Wallet;
|
||||
Monero::Subaddress * m_subaddressImpl;
|
||||
mutable QList<Monero::SubaddressRow*> m_rows;
|
||||
};
|
||||
|
||||
#endif // SUBADDRESS_H
|
|
@ -22,7 +22,7 @@ TransactionInfo *TransactionHistory::transaction(int index)
|
|||
// return nullptr;
|
||||
//}
|
||||
|
||||
QList<TransactionInfo *> TransactionHistory::getAll() const
|
||||
QList<TransactionInfo *> TransactionHistory::getAll(quint32 accountIndex) const
|
||||
{
|
||||
// XXX this invalidates previously saved history that might be used by model
|
||||
emit refreshStarted();
|
||||
|
@ -37,6 +37,10 @@ QList<TransactionInfo *> TransactionHistory::getAll() const
|
|||
TransactionHistory * parent = const_cast<TransactionHistory*>(this);
|
||||
for (const auto i : m_pimpl->getAll()) {
|
||||
TransactionInfo * ti = new TransactionInfo(i, parent);
|
||||
if (ti->subaddrAccount() != accountIndex) {
|
||||
delete ti;
|
||||
continue;
|
||||
}
|
||||
m_tinfo.append(ti);
|
||||
// looking for transactions timestamp scope
|
||||
if (ti->timestamp() >= lastDateTime) {
|
||||
|
@ -69,12 +73,12 @@ QList<TransactionInfo *> TransactionHistory::getAll() const
|
|||
return m_tinfo;
|
||||
}
|
||||
|
||||
void TransactionHistory::refresh()
|
||||
void TransactionHistory::refresh(quint32 accountIndex)
|
||||
{
|
||||
// rebuilding transaction list in wallet_api;
|
||||
m_pimpl->refresh();
|
||||
// copying list here and keep track on every item to avoid memleaks
|
||||
getAll();
|
||||
getAll(accountIndex);
|
||||
}
|
||||
|
||||
quint64 TransactionHistory::count() const
|
||||
|
|
|
@ -23,8 +23,8 @@ class TransactionHistory : public QObject
|
|||
public:
|
||||
Q_INVOKABLE TransactionInfo *transaction(int index);
|
||||
// Q_INVOKABLE TransactionInfo * transaction(const QString &id);
|
||||
Q_INVOKABLE QList<TransactionInfo*> getAll() const;
|
||||
Q_INVOKABLE void refresh();
|
||||
Q_INVOKABLE QList<TransactionInfo*> getAll(quint32 accountIndex) const;
|
||||
Q_INVOKABLE void refresh(quint32 accountIndex);
|
||||
quint64 count() const;
|
||||
QDateTime firstDateTime() const;
|
||||
QDateTime lastDateTime() const;
|
||||
|
|
|
@ -48,6 +48,24 @@ quint64 TransactionInfo::blockHeight() const
|
|||
return m_pimpl->blockHeight();
|
||||
}
|
||||
|
||||
QSet<quint32> TransactionInfo::subaddrIndex() const
|
||||
{
|
||||
QSet<quint32> result;
|
||||
for (uint32_t i : m_pimpl->subaddrIndex())
|
||||
result.insert(i);
|
||||
return result;
|
||||
}
|
||||
|
||||
quint32 TransactionInfo::subaddrAccount() const
|
||||
{
|
||||
return m_pimpl->subaddrAccount();
|
||||
}
|
||||
|
||||
QString TransactionInfo::label() const
|
||||
{
|
||||
return QString::fromStdString(m_pimpl->label());
|
||||
}
|
||||
|
||||
quint64 TransactionInfo::confirmations() const
|
||||
{
|
||||
return m_pimpl->confirmations();
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <wallet/api/wallet2_api.h>
|
||||
#include <QObject>
|
||||
#include <QDateTime>
|
||||
#include <QSet>
|
||||
|
||||
class Transfer;
|
||||
|
||||
|
@ -18,6 +19,9 @@ class TransactionInfo : public QObject
|
|||
Q_PROPERTY(QString displayAmount READ displayAmount)
|
||||
Q_PROPERTY(QString fee READ fee)
|
||||
Q_PROPERTY(quint64 blockHeight READ blockHeight)
|
||||
Q_PROPERTY(QSet<quint32> subaddrIndex READ subaddrIndex)
|
||||
Q_PROPERTY(quint32 subaddrAccount READ subaddrAccount)
|
||||
Q_PROPERTY(QString label READ label)
|
||||
Q_PROPERTY(quint64 confirmations READ confirmations)
|
||||
Q_PROPERTY(quint64 unlockTime READ unlockTime)
|
||||
Q_PROPERTY(QString hash READ hash)
|
||||
|
@ -44,6 +48,9 @@ public:
|
|||
QString displayAmount() const;
|
||||
QString fee() const;
|
||||
quint64 blockHeight() const;
|
||||
QSet<quint32> subaddrIndex() const;
|
||||
quint32 subaddrAccount() const;
|
||||
QString label() const;
|
||||
quint64 confirmations() const;
|
||||
quint64 unlockTime() const;
|
||||
//! transaction_id
|
||||
|
|
|
@ -3,9 +3,11 @@
|
|||
#include "UnsignedTransaction.h"
|
||||
#include "TransactionHistory.h"
|
||||
#include "AddressBook.h"
|
||||
#include "Subaddress.h"
|
||||
#include "model/TransactionHistoryModel.h"
|
||||
#include "model/TransactionHistorySortFilterModel.h"
|
||||
#include "model/AddressBookModel.h"
|
||||
#include "model/SubaddressModel.h"
|
||||
#include "wallet/api/wallet2_api.h"
|
||||
|
||||
#include <QFile>
|
||||
|
@ -155,9 +157,9 @@ bool Wallet::setPassword(const QString &password)
|
|||
return m_walletImpl->setPassword(password.toStdString());
|
||||
}
|
||||
|
||||
QString Wallet::address() const
|
||||
QString Wallet::address(quint32 accountIndex, quint32 addressIndex) const
|
||||
{
|
||||
return QString::fromStdString(m_walletImpl->address());
|
||||
return QString::fromStdString(m_walletImpl->address(accountIndex, addressIndex));
|
||||
}
|
||||
|
||||
QString Wallet::path() const
|
||||
|
@ -241,14 +243,63 @@ bool Wallet::viewOnly() const
|
|||
return m_walletImpl->watchOnly();
|
||||
}
|
||||
|
||||
quint64 Wallet::balance() const
|
||||
quint64 Wallet::balance(quint32 accountIndex) const
|
||||
{
|
||||
return m_walletImpl->balance();
|
||||
return m_walletImpl->balance(accountIndex);
|
||||
}
|
||||
|
||||
quint64 Wallet::unlockedBalance() const
|
||||
quint64 Wallet::balanceAll() const
|
||||
{
|
||||
return m_walletImpl->unlockedBalance();
|
||||
return m_walletImpl->balanceAll();
|
||||
}
|
||||
|
||||
quint64 Wallet::unlockedBalance(quint32 accountIndex) const
|
||||
{
|
||||
return m_walletImpl->unlockedBalance(accountIndex);
|
||||
}
|
||||
|
||||
quint64 Wallet::unlockedBalanceAll() const
|
||||
{
|
||||
return m_walletImpl->unlockedBalanceAll();
|
||||
}
|
||||
|
||||
quint32 Wallet::currentSubaddressAccount() const
|
||||
{
|
||||
return m_currentSubaddressAccount;
|
||||
}
|
||||
void Wallet::switchSubaddressAccount(quint32 accountIndex)
|
||||
{
|
||||
if (accountIndex < numSubaddressAccounts())
|
||||
{
|
||||
m_currentSubaddressAccount = accountIndex;
|
||||
m_subaddress->refresh(m_currentSubaddressAccount);
|
||||
m_history->refresh(m_currentSubaddressAccount);
|
||||
}
|
||||
}
|
||||
void Wallet::addSubaddressAccount(const QString& label)
|
||||
{
|
||||
m_walletImpl->addSubaddressAccount(label.toStdString());
|
||||
switchSubaddressAccount(numSubaddressAccounts() - 1);
|
||||
}
|
||||
quint32 Wallet::numSubaddressAccounts() const
|
||||
{
|
||||
return m_walletImpl->numSubaddressAccounts();
|
||||
}
|
||||
quint32 Wallet::numSubaddresses(quint32 accountIndex) const
|
||||
{
|
||||
return m_walletImpl->numSubaddresses(accountIndex);
|
||||
}
|
||||
void Wallet::addSubaddress(const QString& label)
|
||||
{
|
||||
m_walletImpl->addSubaddress(currentSubaddressAccount(), label.toStdString());
|
||||
}
|
||||
QString Wallet::getSubaddressLabel(quint32 accountIndex, quint32 addressIndex) const
|
||||
{
|
||||
return QString::fromStdString(m_walletImpl->getSubaddressLabel(accountIndex, addressIndex));
|
||||
}
|
||||
void Wallet::setSubaddressLabel(quint32 accountIndex, quint32 addressIndex, const QString &label)
|
||||
{
|
||||
m_walletImpl->setSubaddressLabel(accountIndex, addressIndex, label.toStdString());
|
||||
}
|
||||
|
||||
quint64 Wallet::blockChainHeight() const
|
||||
|
@ -288,7 +339,8 @@ quint64 Wallet::daemonBlockChainTargetHeight() const
|
|||
bool Wallet::refresh()
|
||||
{
|
||||
bool result = m_walletImpl->refresh();
|
||||
m_history->refresh();
|
||||
m_history->refresh(currentSubaddressAccount());
|
||||
m_subaddress->refresh(currentSubaddressAccount());
|
||||
if (result)
|
||||
emit updated();
|
||||
return result;
|
||||
|
@ -324,9 +376,10 @@ PendingTransaction *Wallet::createTransaction(const QString &dst_addr, const QSt
|
|||
quint64 amount, quint32 mixin_count,
|
||||
PendingTransaction::Priority priority)
|
||||
{
|
||||
std::set<uint32_t> subaddr_indices;
|
||||
Monero::PendingTransaction * ptImpl = m_walletImpl->createTransaction(
|
||||
dst_addr.toStdString(), payment_id.toStdString(), amount, mixin_count,
|
||||
static_cast<Monero::PendingTransaction::Priority>(priority));
|
||||
static_cast<Monero::PendingTransaction::Priority>(priority), currentSubaddressAccount(), subaddr_indices);
|
||||
PendingTransaction * result = new PendingTransaction(ptImpl,0);
|
||||
return result;
|
||||
}
|
||||
|
@ -351,9 +404,10 @@ void Wallet::createTransactionAsync(const QString &dst_addr, const QString &paym
|
|||
PendingTransaction *Wallet::createTransactionAll(const QString &dst_addr, const QString &payment_id,
|
||||
quint32 mixin_count, PendingTransaction::Priority priority)
|
||||
{
|
||||
std::set<uint32_t> subaddr_indices;
|
||||
Monero::PendingTransaction * ptImpl = m_walletImpl->createTransaction(
|
||||
dst_addr.toStdString(), payment_id.toStdString(), Monero::optional<uint64_t>(), mixin_count,
|
||||
static_cast<Monero::PendingTransaction::Priority>(priority));
|
||||
static_cast<Monero::PendingTransaction::Priority>(priority), currentSubaddressAccount(), subaddr_indices);
|
||||
PendingTransaction * result = new PendingTransaction(ptImpl, this);
|
||||
return result;
|
||||
}
|
||||
|
@ -458,6 +512,18 @@ AddressBookModel *Wallet::addressBookModel() const
|
|||
return m_addressBookModel;
|
||||
}
|
||||
|
||||
Subaddress *Wallet::subaddress()
|
||||
{
|
||||
return m_subaddress;
|
||||
}
|
||||
|
||||
SubaddressModel *Wallet::subaddressModel()
|
||||
{
|
||||
if (!m_subaddressModel) {
|
||||
m_subaddressModel = new SubaddressModel(this, m_subaddress);
|
||||
}
|
||||
return m_subaddressModel;
|
||||
}
|
||||
|
||||
QString Wallet::generatePaymentId() const
|
||||
{
|
||||
|
@ -668,14 +734,18 @@ Wallet::Wallet(Monero::Wallet *w, QObject *parent)
|
|||
, m_historyModel(nullptr)
|
||||
, m_addressBook(nullptr)
|
||||
, m_addressBookModel(nullptr)
|
||||
, m_subaddress(nullptr)
|
||||
, m_subaddressModel(nullptr)
|
||||
, m_daemonBlockChainHeight(0)
|
||||
, m_daemonBlockChainHeightTtl(DAEMON_BLOCKCHAIN_HEIGHT_CACHE_TTL_SECONDS)
|
||||
, m_daemonBlockChainTargetHeight(0)
|
||||
, m_daemonBlockChainTargetHeightTtl(DAEMON_BLOCKCHAIN_TARGET_HEIGHT_CACHE_TTL_SECONDS)
|
||||
, m_connectionStatusTtl(WALLET_CONNECTION_STATUS_CACHE_TTL_SECONDS)
|
||||
, m_currentSubaddressAccount(0)
|
||||
{
|
||||
m_history = new TransactionHistory(m_walletImpl->history(), this);
|
||||
m_addressBook = new AddressBook(m_walletImpl->addressBook(), this);
|
||||
m_subaddress = new Subaddress(m_walletImpl->subaddress(), this);
|
||||
m_walletImpl->setListener(new WalletListenerImpl(this));
|
||||
m_connectionStatus = Wallet::ConnectionStatus_Disconnected;
|
||||
// start cache timers
|
||||
|
@ -696,6 +766,10 @@ Wallet::~Wallet()
|
|||
|
||||
delete m_history;
|
||||
m_history = NULL;
|
||||
delete m_addressBook;
|
||||
m_addressBook = NULL;
|
||||
delete m_subaddress;
|
||||
m_subaddress = NULL;
|
||||
//Monero::WalletManagerFactory::getWalletManager()->closeWallet(m_walletImpl);
|
||||
if(status() == Status_Critical)
|
||||
qDebug("Not storing wallet cache");
|
||||
|
|
|
@ -20,6 +20,8 @@ class TransactionHistoryModel;
|
|||
class TransactionHistorySortFilterModel;
|
||||
class AddressBook;
|
||||
class AddressBookModel;
|
||||
class Subaddress;
|
||||
class SubaddressModel;
|
||||
|
||||
class Wallet : public QObject
|
||||
{
|
||||
|
@ -29,17 +31,17 @@ class Wallet : public QObject
|
|||
Q_PROPERTY(Status status READ status)
|
||||
Q_PROPERTY(bool testnet READ testnet)
|
||||
// Q_PROPERTY(ConnectionStatus connected READ connected)
|
||||
Q_PROPERTY(quint32 currentSubaddressAccount READ currentSubaddressAccount)
|
||||
Q_PROPERTY(bool synchronized READ synchronized)
|
||||
Q_PROPERTY(QString errorString READ errorString)
|
||||
Q_PROPERTY(QString address READ address)
|
||||
Q_PROPERTY(quint64 balance READ balance)
|
||||
Q_PROPERTY(quint64 unlockedBalance READ unlockedBalance)
|
||||
Q_PROPERTY(TransactionHistory * history READ history)
|
||||
Q_PROPERTY(QString paymentId READ paymentId WRITE setPaymentId)
|
||||
Q_PROPERTY(TransactionHistorySortFilterModel * historyModel READ historyModel NOTIFY historyModelChanged)
|
||||
Q_PROPERTY(QString path READ path)
|
||||
Q_PROPERTY(AddressBookModel * addressBookModel READ addressBookModel)
|
||||
Q_PROPERTY(AddressBook * addressBook READ addressBook)
|
||||
Q_PROPERTY(SubaddressModel * subaddressModel READ subaddressModel)
|
||||
Q_PROPERTY(Subaddress * subaddress READ subaddress)
|
||||
Q_PROPERTY(bool viewOnly READ viewOnly)
|
||||
Q_PROPERTY(QString secretViewKey READ getSecretViewKey)
|
||||
Q_PROPERTY(QString publicViewKey READ getPublicViewKey)
|
||||
|
@ -98,7 +100,7 @@ public:
|
|||
Q_INVOKABLE bool setPassword(const QString &password);
|
||||
|
||||
//! returns wallet's public address
|
||||
QString address() const;
|
||||
Q_INVOKABLE QString address(quint32 accountIndex, quint32 addressIndex) const;
|
||||
|
||||
//! returns wallet file's path
|
||||
QString path() const;
|
||||
|
@ -126,10 +128,22 @@ public:
|
|||
Q_INVOKABLE void setTrustedDaemon(bool arg);
|
||||
|
||||
//! returns balance
|
||||
Q_INVOKABLE quint64 balance() const;
|
||||
Q_INVOKABLE quint64 balance(quint32 accountIndex) const;
|
||||
Q_INVOKABLE quint64 balanceAll() const;
|
||||
|
||||
//! returns unlocked balance
|
||||
Q_INVOKABLE quint64 unlockedBalance() const;
|
||||
Q_INVOKABLE quint64 unlockedBalance(quint32 accountIndex) const;
|
||||
Q_INVOKABLE quint64 unlockedBalanceAll() const;
|
||||
|
||||
//! account/address management
|
||||
quint32 currentSubaddressAccount() const;
|
||||
Q_INVOKABLE void switchSubaddressAccount(quint32 accountIndex);
|
||||
Q_INVOKABLE void addSubaddressAccount(const QString& label);
|
||||
Q_INVOKABLE quint32 numSubaddressAccounts() const;
|
||||
Q_INVOKABLE quint32 numSubaddresses(quint32 accountIndex) const;
|
||||
Q_INVOKABLE void addSubaddress(const QString& label);
|
||||
Q_INVOKABLE QString getSubaddressLabel(quint32 accountIndex, quint32 addressIndex) const;
|
||||
Q_INVOKABLE void setSubaddressLabel(quint32 accountIndex, quint32 addressIndex, const QString &label);
|
||||
|
||||
//! returns if view only wallet
|
||||
Q_INVOKABLE bool viewOnly() const;
|
||||
|
@ -209,6 +223,12 @@ public:
|
|||
//! returns adress book model
|
||||
AddressBookModel *addressBookModel() const;
|
||||
|
||||
//! returns subaddress
|
||||
Subaddress *subaddress();
|
||||
|
||||
//! returns subadress model
|
||||
SubaddressModel *subaddressModel();
|
||||
|
||||
//! generate payment id
|
||||
Q_INVOKABLE QString generatePaymentId() const;
|
||||
|
||||
|
@ -302,8 +322,11 @@ private:
|
|||
int m_connectionStatusTtl;
|
||||
mutable QTime m_connectionStatusTime;
|
||||
mutable bool m_initialized;
|
||||
uint32_t m_currentSubaddressAccount;
|
||||
AddressBook * m_addressBook;
|
||||
mutable AddressBookModel * m_addressBookModel;
|
||||
Subaddress * m_subaddress;
|
||||
mutable SubaddressModel * m_subaddressModel;
|
||||
QMutex m_connectionStatusMutex;
|
||||
bool m_connectionStatusRunning;
|
||||
QString m_daemonUsername;
|
||||
|
|
|
@ -49,7 +49,7 @@ Wallet *WalletManager::openWallet(const QString &path, const QString &password,
|
|||
__PRETTY_FUNCTION__, qPrintable(path), testnet);
|
||||
|
||||
Monero::Wallet * w = m_pimpl->openWallet(path.toStdString(), password.toStdString(), testnet);
|
||||
qDebug("%s: opened wallet: %s, status: %d", __PRETTY_FUNCTION__, w->address().c_str(), w->status());
|
||||
qDebug("%s: opened wallet: %s, status: %d", __PRETTY_FUNCTION__, w->address(0, 0).c_str(), w->status());
|
||||
m_currentWallet = new Wallet(w);
|
||||
|
||||
// move wallet to the GUI thread. Otherwise it wont be emitting signals
|
||||
|
@ -110,7 +110,7 @@ QString WalletManager::closeWallet()
|
|||
QMutexLocker locker(&m_mutex);
|
||||
QString result;
|
||||
if (m_currentWallet) {
|
||||
result = m_currentWallet->address();
|
||||
result = m_currentWallet->address(0, 0);
|
||||
delete m_currentWallet;
|
||||
} else {
|
||||
qCritical() << "Trying to close non existing wallet " << m_currentWallet;
|
||||
|
|
89
src/model/SubaddressModel.cpp
Normal file
89
src/model/SubaddressModel.cpp
Normal file
|
@ -0,0 +1,89 @@
|
|||
// Copyright (c) 2018, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// 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.
|
||||
|
||||
#include "SubaddressModel.h"
|
||||
#include "Subaddress.h"
|
||||
#include <QDebug>
|
||||
#include <QHash>
|
||||
#include <wallet/api/wallet2_api.h>
|
||||
|
||||
SubaddressModel::SubaddressModel(QObject *parent, Subaddress *subaddress)
|
||||
: QAbstractListModel(parent), m_subaddress(subaddress)
|
||||
{
|
||||
qDebug(__FUNCTION__);
|
||||
connect(m_subaddress,SIGNAL(refreshStarted()),this,SLOT(startReset()));
|
||||
connect(m_subaddress,SIGNAL(refreshFinished()),this,SLOT(endReset()));
|
||||
|
||||
}
|
||||
|
||||
void SubaddressModel::startReset(){
|
||||
qDebug(__FUNCTION__);
|
||||
beginResetModel();
|
||||
}
|
||||
void SubaddressModel::endReset(){
|
||||
qDebug(__FUNCTION__);
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
int SubaddressModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
return m_subaddress->count();
|
||||
}
|
||||
|
||||
QVariant SubaddressModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid() || index.row() < 0 || (unsigned)index.row() >= m_subaddress->count())
|
||||
return {};
|
||||
|
||||
Monero::SubaddressRow * sr = m_subaddress->getRow(index.row());
|
||||
if (!sr)
|
||||
return {};
|
||||
|
||||
QVariant result = "";
|
||||
switch (role) {
|
||||
case SubaddressAddressRole:
|
||||
result = QString::fromStdString(sr->getAddress());
|
||||
break;
|
||||
case SubaddressLabelRole:
|
||||
result = index.row() == 0 ? tr("Primary address") : QString::fromStdString(sr->getLabel());
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> SubaddressModel::roleNames() const
|
||||
{
|
||||
static QHash<int, QByteArray> roleNames;
|
||||
if (roleNames.empty())
|
||||
{
|
||||
roleNames.insert(SubaddressAddressRole, "address");
|
||||
roleNames.insert(SubaddressLabelRole, "label");
|
||||
}
|
||||
return roleNames;
|
||||
}
|
62
src/model/SubaddressModel.h
Normal file
62
src/model/SubaddressModel.h
Normal file
|
@ -0,0 +1,62 @@
|
|||
// Copyright (c) 2018, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// 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.
|
||||
|
||||
#ifndef SUBADDRESSMODEL_H
|
||||
#define SUBADDRESSMODEL_H
|
||||
|
||||
#include <QAbstractListModel>
|
||||
|
||||
class Subaddress;
|
||||
|
||||
class SubaddressModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum SubaddressRowRole {
|
||||
SubaddressRole = Qt::UserRole + 1, // for the SubaddressRow object;
|
||||
SubaddressAddressRole,
|
||||
SubaddressLabelRole,
|
||||
};
|
||||
Q_ENUM(SubaddressRowRole)
|
||||
|
||||
SubaddressModel(QObject *parent, Subaddress *subaddress);
|
||||
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
public slots:
|
||||
void startReset();
|
||||
void endReset();
|
||||
|
||||
private:
|
||||
Subaddress *m_subaddress;
|
||||
};
|
||||
|
||||
#endif // SUBADDRESSMODEL_H
|
|
@ -83,6 +83,25 @@ QVariant TransactionHistoryModel::data(const QModelIndex &index, int role) const
|
|||
}
|
||||
break;
|
||||
|
||||
case TransactionSubaddrIndexRole:
|
||||
{
|
||||
QString str = QString{""};
|
||||
bool first = true;
|
||||
for (quint32 i : tInfo->subaddrIndex()) {
|
||||
if (!first)
|
||||
str += QString{","};
|
||||
first = false;
|
||||
str += QString::number(i);
|
||||
}
|
||||
result = str;
|
||||
}
|
||||
break;
|
||||
case TransactionSubaddrAccountRole:
|
||||
result = tInfo->subaddrAccount();
|
||||
break;
|
||||
case TransactionLabelRole:
|
||||
result = tInfo->subaddrIndex().size() == 1 && *tInfo->subaddrIndex().begin() == 0 ? tr("Primary address") : tInfo->label();
|
||||
break;
|
||||
case TransactionConfirmationsRole:
|
||||
result = tInfo->confirmations();
|
||||
break;
|
||||
|
@ -133,6 +152,9 @@ QHash<int, QByteArray> TransactionHistoryModel::roleNames() const
|
|||
roleNames.insert(TransactionAtomicAmountRole, "atomicAmount");
|
||||
roleNames.insert(TransactionFeeRole, "fee");
|
||||
roleNames.insert(TransactionBlockHeightRole, "blockHeight");
|
||||
roleNames.insert(TransactionSubaddrIndexRole, "subaddrIndex");
|
||||
roleNames.insert(TransactionSubaddrAccountRole, "subaddrAccount");
|
||||
roleNames.insert(TransactionLabelRole, "label");
|
||||
roleNames.insert(TransactionConfirmationsRole, "confirmations");
|
||||
roleNames.insert(TransactionConfirmationsRequiredRole, "confirmationsRequired");
|
||||
roleNames.insert(TransactionHashRole, "hash");
|
||||
|
|
|
@ -25,6 +25,9 @@ public:
|
|||
TransactionDisplayAmountRole,
|
||||
TransactionFeeRole,
|
||||
TransactionBlockHeightRole,
|
||||
TransactionSubaddrIndexRole,
|
||||
TransactionSubaddrAccountRole,
|
||||
TransactionLabelRole,
|
||||
TransactionConfirmationsRole,
|
||||
TransactionConfirmationsRequiredRole,
|
||||
TransactionHashRole,
|
||||
|
|
Loading…
Reference in a new issue