mirror of
https://github.com/monero-project/monero-gui.git
synced 2024-12-23 03:59:38 +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 {
|
}, State {
|
||||||
name: "Receive"
|
name: "Receive"
|
||||||
PropertyChanges { target: root; currentView: receiveView }
|
PropertyChanges { target: root; currentView: receiveView }
|
||||||
PropertyChanges { target: mainFlickable; contentHeight: minHeight }
|
PropertyChanges { target: mainFlickable; contentHeight: 1000 * scaleRatio }
|
||||||
}, State {
|
}, State {
|
||||||
name: "TxKey"
|
name: "TxKey"
|
||||||
PropertyChanges { target: root; currentView: txkeyView }
|
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
|
// -- "Date", "Balance" and "Amound" section
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
import QtQuick 2.0
|
import QtQuick 2.0
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
|
property alias image : buttonImage
|
||||||
property alias imageSource : buttonImage.source
|
property alias imageSource : buttonImage.source
|
||||||
|
|
||||||
signal clicked(var mouse)
|
signal clicked(var mouse)
|
||||||
|
@ -53,7 +54,8 @@ Item {
|
||||||
MouseArea {
|
MouseArea {
|
||||||
id: buttonArea
|
id: buttonArea
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
|
||||||
onPressed: {
|
onPressed: {
|
||||||
buttonImage.x = buttonImage.x + 2
|
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 cursorPosition: input.cursorPosition
|
||||||
property alias echoMode: input.echoMode
|
property alias echoMode: input.echoMode
|
||||||
property int fontSize: 18 * scaleRatio
|
property int fontSize: 18 * scaleRatio
|
||||||
|
property bool showBorder: true
|
||||||
property bool error: false
|
property bool error: false
|
||||||
signal editingFinished()
|
signal editingFinished()
|
||||||
signal accepted();
|
signal accepted();
|
||||||
|
@ -52,6 +53,7 @@ Item {
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
|
visible: showBorder
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.bottomMargin: 1 * scaleRatio
|
anchors.bottomMargin: 1 * scaleRatio
|
||||||
color: "#DBDBDB"
|
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 "model/TransactionHistorySortFilterModel.h"
|
||||||
#include "AddressBook.h"
|
#include "AddressBook.h"
|
||||||
#include "model/AddressBookModel.h"
|
#include "model/AddressBookModel.h"
|
||||||
|
#include "Subaddress.h"
|
||||||
|
#include "model/SubaddressModel.h"
|
||||||
#include "wallet/api/wallet2_api.h"
|
#include "wallet/api/wallet2_api.h"
|
||||||
#include "MainApp.h"
|
#include "MainApp.h"
|
||||||
|
|
||||||
|
@ -133,6 +135,12 @@ int main(int argc, char *argv[])
|
||||||
qmlRegisterUncreatableType<AddressBook>("moneroComponents.AddressBook", 1, 0, "AddressBook",
|
qmlRegisterUncreatableType<AddressBook>("moneroComponents.AddressBook", 1, 0, "AddressBook",
|
||||||
"AddressBook can't be instantiated directly");
|
"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<PendingTransaction::Priority>();
|
||||||
qRegisterMetaType<TransactionInfo::Direction>();
|
qRegisterMetaType<TransactionInfo::Direction>();
|
||||||
qRegisterMetaType<TransactionHistoryModel::TransactionInfoRole>();
|
qRegisterMetaType<TransactionHistoryModel::TransactionInfoRole>();
|
||||||
|
|
45
main.qml
45
main.qml
|
@ -310,8 +310,10 @@ ApplicationWindow {
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateBalance() {
|
function updateBalance() {
|
||||||
middlePanel.unlockedBalanceText = leftPanel.unlockedBalanceText = middlePanel.state === "Receive" ? qsTr("HIDDEN") : walletManager.displayAmount(currentWallet.unlockedBalance);
|
if (!currentWallet)
|
||||||
middlePanel.balanceText = leftPanel.balanceText = middlePanel.state === "Receive" ? qsTr("HIDDEN") : walletManager.displayAmount(currentWallet.balance);
|
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){
|
function onWalletConnectionStatusChanged(status){
|
||||||
|
@ -329,7 +331,7 @@ ApplicationWindow {
|
||||||
}
|
}
|
||||||
// initialize transaction history once wallet is initialized first time;
|
// initialize transaction history once wallet is initialized first time;
|
||||||
if (!walletInitialized) {
|
if (!walletInitialized) {
|
||||||
currentWallet.history.refresh()
|
currentWallet.history.refresh(currentWallet.currentSubaddressAccount)
|
||||||
walletInitialized = true
|
walletInitialized = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -377,7 +379,7 @@ ApplicationWindow {
|
||||||
if(foundNewBlock) {
|
if(foundNewBlock) {
|
||||||
foundNewBlock = false;
|
foundNewBlock = false;
|
||||||
console.log("New block found - updating history")
|
console.log("New block found - updating history")
|
||||||
currentWallet.history.refresh()
|
currentWallet.history.refresh(currentWallet.currentSubaddressAccount)
|
||||||
timeToUnlock = currentWallet.history.minutesToUnlock
|
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");
|
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");
|
console.log("Saving wallet after first refresh");
|
||||||
currentWallet.store()
|
currentWallet.store()
|
||||||
isNewWallet = false
|
isNewWallet = false
|
||||||
|
|
||||||
|
// Update History
|
||||||
|
currentWallet.history.refresh(currentWallet.currentSubaddressAccount);
|
||||||
}
|
}
|
||||||
|
|
||||||
// recovering from seed is finished after first refresh
|
// recovering from seed is finished after first refresh
|
||||||
|
@ -463,7 +468,7 @@ ApplicationWindow {
|
||||||
|
|
||||||
// Update history on every refresh if it's empty
|
// Update history on every refresh if it's empty
|
||||||
if(currentWallet.history.count == 0)
|
if(currentWallet.history.count == 0)
|
||||||
currentWallet.history.refresh()
|
currentWallet.history.refresh(currentWallet.currentSubaddressAccount)
|
||||||
|
|
||||||
onWalletUpdate();
|
onWalletUpdate();
|
||||||
}
|
}
|
||||||
|
@ -526,19 +531,21 @@ ApplicationWindow {
|
||||||
currentWallet.refresh()
|
currentWallet.refresh()
|
||||||
console.log("Confirmed money found")
|
console.log("Confirmed money found")
|
||||||
// history refresh is handled by walletUpdated
|
// history refresh is handled by walletUpdated
|
||||||
|
currentWallet.history.refresh(currentWallet.currentSubaddressAccount) // this will refresh model
|
||||||
|
currentWallet.subaddress.refresh(currentWallet.currentSubaddressAccount)
|
||||||
}
|
}
|
||||||
|
|
||||||
function onWalletUnconfirmedMoneyReceived(txId, amount) {
|
function onWalletUnconfirmedMoneyReceived(txId, amount) {
|
||||||
// refresh history
|
// refresh history
|
||||||
console.log("unconfirmed money found")
|
console.log("unconfirmed money found")
|
||||||
currentWallet.history.refresh()
|
currentWallet.history.refresh(currentWallet.currentSubaddressAccount)
|
||||||
}
|
}
|
||||||
|
|
||||||
function onWalletMoneySent(txId, amount) {
|
function onWalletMoneySent(txId, amount) {
|
||||||
// refresh transaction history here
|
// refresh transaction history here
|
||||||
console.log("money sent found")
|
console.log("money sent found")
|
||||||
currentWallet.refresh()
|
currentWallet.refresh()
|
||||||
currentWallet.history.refresh() // this will refresh model
|
currentWallet.history.refresh(currentWallet.currentSubaddressAccount) // this will refresh model
|
||||||
}
|
}
|
||||||
|
|
||||||
function walletsFound() {
|
function walletsFound() {
|
||||||
|
@ -584,8 +591,11 @@ ApplicationWindow {
|
||||||
// here we show confirmation popup;
|
// here we show confirmation popup;
|
||||||
|
|
||||||
transactionConfirmationPopup.title = qsTr("Confirmation") + translationManager.emptyString
|
transactionConfirmationPopup.title = qsTr("Confirmation") + translationManager.emptyString
|
||||||
transactionConfirmationPopup.text = qsTr("Please confirm transaction:\n")
|
transactionConfirmationPopup.text = qsTr("Please confirm transaction:\n");
|
||||||
+ (address === "" ? "" : (qsTr("\nAddress: ") + address))
|
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))
|
+ (paymentId === "" ? "" : (qsTr("\nPayment ID: ") + paymentId))
|
||||||
+ qsTr("\n\nAmount: ") + walletManager.displayAmount(transaction.amount)
|
+ qsTr("\n\nAmount: ") + walletManager.displayAmount(transaction.amount)
|
||||||
+ qsTr("\nFee: ") + walletManager.displayAmount(transaction.fee)
|
+ 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 {
|
DaemonManagerDialog {
|
||||||
id: daemonManagerDialog
|
id: daemonManagerDialog
|
||||||
onRejected: {
|
onRejected: {
|
||||||
|
|
|
@ -35,6 +35,8 @@ HEADERS += \
|
||||||
src/QR-Code-generator/QrSegment.hpp \
|
src/QR-Code-generator/QrSegment.hpp \
|
||||||
src/model/AddressBookModel.h \
|
src/model/AddressBookModel.h \
|
||||||
src/libwalletqt/AddressBook.h \
|
src/libwalletqt/AddressBook.h \
|
||||||
|
src/model/SubaddressModel.h \
|
||||||
|
src/libwalletqt/Subaddress.h \
|
||||||
src/zxcvbn-c/zxcvbn.h \
|
src/zxcvbn-c/zxcvbn.h \
|
||||||
src/libwalletqt/UnsignedTransaction.h \
|
src/libwalletqt/UnsignedTransaction.h \
|
||||||
MainApp.h
|
MainApp.h
|
||||||
|
@ -58,6 +60,8 @@ SOURCES += main.cpp \
|
||||||
src/QR-Code-generator/QrSegment.cpp \
|
src/QR-Code-generator/QrSegment.cpp \
|
||||||
src/model/AddressBookModel.cpp \
|
src/model/AddressBookModel.cpp \
|
||||||
src/libwalletqt/AddressBook.cpp \
|
src/libwalletqt/AddressBook.cpp \
|
||||||
|
src/model/SubaddressModel.cpp \
|
||||||
|
src/libwalletqt/Subaddress.cpp \
|
||||||
src/zxcvbn-c/zxcvbn.c \
|
src/zxcvbn-c/zxcvbn.c \
|
||||||
src/libwalletqt/UnsignedTransaction.cpp \
|
src/libwalletqt/UnsignedTransaction.cpp \
|
||||||
MainApp.cpp
|
MainApp.cpp
|
||||||
|
|
|
@ -546,7 +546,7 @@ Rectangle {
|
||||||
|
|
||||||
function onPageCompleted() {
|
function onPageCompleted() {
|
||||||
if(currentWallet != null && typeof currentWallet.history !== "undefined" ) {
|
if(currentWallet != null && typeof currentWallet.history !== "undefined" ) {
|
||||||
currentWallet.history.refresh()
|
currentWallet.history.refresh(currentWallet.currentSubaddressAccount)
|
||||||
table.addressBookModel = currentWallet ? currentWallet.addressBookModel : null
|
table.addressBookModel = currentWallet ? currentWallet.addressBookModel : null
|
||||||
transactionTypeDropdown.update()
|
transactionTypeDropdown.update()
|
||||||
}
|
}
|
||||||
|
|
|
@ -151,7 +151,7 @@ Rectangle {
|
||||||
releasedColor: "#FF6C3C"
|
releasedColor: "#FF6C3C"
|
||||||
pressedColor: "#FF4304"
|
pressedColor: "#FF4304"
|
||||||
onClicked: {
|
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) {
|
if (success) {
|
||||||
update()
|
update()
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -38,14 +38,17 @@ import moneroComponents.Wallet 1.0
|
||||||
import moneroComponents.WalletManager 1.0
|
import moneroComponents.WalletManager 1.0
|
||||||
import moneroComponents.TransactionHistory 1.0
|
import moneroComponents.TransactionHistory 1.0
|
||||||
import moneroComponents.TransactionHistoryModel 1.0
|
import moneroComponents.TransactionHistoryModel 1.0
|
||||||
|
import moneroComponents.Subaddress 1.0
|
||||||
|
import moneroComponents.SubaddressModel 1.0
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
|
id: pageReceive
|
||||||
color: "#F0EEEE"
|
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 paymentIdText : paymentIdLine.text
|
||||||
property alias integratedAddressText : integratedAddressLine.text
|
property alias integratedAddressText : integratedAddressLine.text
|
||||||
property var model
|
|
||||||
property string trackingLineText: ""
|
property string trackingLineText: ""
|
||||||
|
|
||||||
function updatePaymentId(payment_id) {
|
function updatePaymentId(payment_id) {
|
||||||
|
@ -80,7 +83,7 @@ Rectangle {
|
||||||
function makeQRCodeString() {
|
function makeQRCodeString() {
|
||||||
var s = "monero:"
|
var s = "monero:"
|
||||||
var nfields = 0
|
var nfields = 0
|
||||||
s += addressLine.text
|
s += current_address;
|
||||||
var amount = amountLine.text.trim()
|
var amount = amountLine.text.trim()
|
||||||
if (amount !== "") {
|
if (amount !== "") {
|
||||||
s += (nfields++ ? "&" : "?")
|
s += (nfields++ ? "&" : "?")
|
||||||
|
@ -192,27 +195,66 @@ Rectangle {
|
||||||
id: addressRow
|
id: addressRow
|
||||||
Label {
|
Label {
|
||||||
id: addressLabel
|
id: addressLabel
|
||||||
text: qsTr("Address") + translationManager.emptyString
|
text: qsTr("Addresses") + translationManager.emptyString
|
||||||
width: mainLayout.labelWidth
|
width: mainLayout.labelWidth
|
||||||
}
|
}
|
||||||
|
|
||||||
LineEdit {
|
Rectangle {
|
||||||
id: addressLine
|
id: tableRect
|
||||||
fontSize: mainLayout.lineEditFontSize
|
|
||||||
placeholderText: qsTr("ReadOnly wallet address displayed here") + translationManager.emptyString;
|
|
||||||
readOnly: true
|
|
||||||
width: mainLayout.editWidth
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
onTextChanged: cursorPosition = 0
|
Layout.preferredHeight: 200
|
||||||
|
color: "#FFFFFF"
|
||||||
IconButton {
|
Scroll {
|
||||||
imageSource: "../images/copyToClipboard.png"
|
id: flickableScroll
|
||||||
onClicked: {
|
anchors.right: table.right
|
||||||
if (addressLine.text.length > 0) {
|
anchors.top: table.top
|
||||||
console.log(addressLine.text + " copied to clipboard")
|
anchors.bottom: table.bottom
|
||||||
clipboard.setText(addressLine.text)
|
flickable: table
|
||||||
appWindow.showStatusMessage(qsTr("Address copied to clipboard"),3)
|
|
||||||
}
|
}
|
||||||
|
SubaddressTable {
|
||||||
|
id: table
|
||||||
|
anchors.fill: parent
|
||||||
|
onContentYChanged: flickableScroll.flickableContentYChanged()
|
||||||
|
onCurrentItemChanged: {
|
||||||
|
current_address = appWindow.currentWallet.address(appWindow.currentWallet.currentSubaddressAccount, table.currentIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
spacing: 20
|
||||||
|
StandardButton {
|
||||||
|
shadowReleasedColor: "#FF4304"
|
||||||
|
shadowPressedColor: "#B32D00"
|
||||||
|
releasedColor: "#FF6C3C"
|
||||||
|
pressedColor: "#FF4304"
|
||||||
|
text: qsTr("Create new address") + translationManager.emptyString;
|
||||||
|
onClicked: {
|
||||||
|
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() {
|
function onPageCompleted() {
|
||||||
console.log("Receive page loaded");
|
console.log("Receive page loaded");
|
||||||
|
table.model = currentWallet.subaddressModel;
|
||||||
|
|
||||||
if (appWindow.currentWallet) {
|
if (appWindow.currentWallet) {
|
||||||
if (addressLine.text.length === 0 || addressLine.text !== appWindow.currentWallet.address) {
|
current_address = appWindow.currentWallet.address(appWindow.currentWallet.currentSubaddressAccount, 0)
|
||||||
addressLine.text = appWindow.currentWallet.address
|
appWindow.currentWallet.subaddress.refresh(appWindow.currentWallet.currentSubaddressAccount)
|
||||||
}
|
table.currentIndex = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
update()
|
update()
|
||||||
|
|
2
qml.qrc
2
qml.qrc
|
@ -51,6 +51,7 @@
|
||||||
<file>tabs/TweetsModel.qml</file>
|
<file>tabs/TweetsModel.qml</file>
|
||||||
<file>components/Scroll.qml</file>
|
<file>components/Scroll.qml</file>
|
||||||
<file>components/AddressBookTable.qml</file>
|
<file>components/AddressBookTable.qml</file>
|
||||||
|
<file>components/SubaddressTable.qml</file>
|
||||||
<file>images/deleteIcon.png</file>
|
<file>images/deleteIcon.png</file>
|
||||||
<file>images/moneroIcon.png</file>
|
<file>images/moneroIcon.png</file>
|
||||||
<file>components/StandardDropdown.qml</file>
|
<file>components/StandardDropdown.qml</file>
|
||||||
|
@ -136,6 +137,7 @@
|
||||||
<file>components/IconButton.qml</file>
|
<file>components/IconButton.qml</file>
|
||||||
<file>components/PasswordDialog.qml</file>
|
<file>components/PasswordDialog.qml</file>
|
||||||
<file>components/NewPasswordDialog.qml</file>
|
<file>components/NewPasswordDialog.qml</file>
|
||||||
|
<file>components/InputDialog.qml</file>
|
||||||
<file>components/ProcessingSplash.qml</file>
|
<file>components/ProcessingSplash.qml</file>
|
||||||
<file>components/ProgressBar.qml</file>
|
<file>components/ProgressBar.qml</file>
|
||||||
<file>components/StandardDialog.qml</file>
|
<file>components/StandardDialog.qml</file>
|
||||||
|
|
|
@ -50,6 +50,16 @@ quint64 PendingTransaction::txCount() const
|
||||||
return m_pimpl->txCount();
|
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)
|
void PendingTransaction::setFilename(const QString &fileName)
|
||||||
{
|
{
|
||||||
m_fileName = fileName;
|
m_fileName = fileName;
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
#define PENDINGTRANSACTION_H
|
#define PENDINGTRANSACTION_H
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
#include <QList>
|
||||||
|
#include <QVariant>
|
||||||
|
|
||||||
#include <wallet/api/wallet2_api.h>
|
#include <wallet/api/wallet2_api.h>
|
||||||
|
|
||||||
|
@ -19,6 +21,7 @@ class PendingTransaction : public QObject
|
||||||
Q_PROPERTY(quint64 fee READ fee)
|
Q_PROPERTY(quint64 fee READ fee)
|
||||||
Q_PROPERTY(QStringList txid READ txid)
|
Q_PROPERTY(QStringList txid READ txid)
|
||||||
Q_PROPERTY(quint64 txCount READ txCount)
|
Q_PROPERTY(quint64 txCount READ txCount)
|
||||||
|
Q_PROPERTY(QList<QVariant> subaddrIndices READ subaddrIndices)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum Status {
|
enum Status {
|
||||||
|
@ -44,6 +47,7 @@ public:
|
||||||
quint64 fee() const;
|
quint64 fee() const;
|
||||||
QStringList txid() const;
|
QStringList txid() const;
|
||||||
quint64 txCount() const;
|
quint64 txCount() const;
|
||||||
|
QList<QVariant> subaddrIndices() const;
|
||||||
Q_INVOKABLE void setFilename(const QString &fileName);
|
Q_INVOKABLE void setFilename(const QString &fileName);
|
||||||
|
|
||||||
private:
|
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;
|
// 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
|
// XXX this invalidates previously saved history that might be used by model
|
||||||
emit refreshStarted();
|
emit refreshStarted();
|
||||||
|
@ -37,6 +37,10 @@ QList<TransactionInfo *> TransactionHistory::getAll() const
|
||||||
TransactionHistory * parent = const_cast<TransactionHistory*>(this);
|
TransactionHistory * parent = const_cast<TransactionHistory*>(this);
|
||||||
for (const auto i : m_pimpl->getAll()) {
|
for (const auto i : m_pimpl->getAll()) {
|
||||||
TransactionInfo * ti = new TransactionInfo(i, parent);
|
TransactionInfo * ti = new TransactionInfo(i, parent);
|
||||||
|
if (ti->subaddrAccount() != accountIndex) {
|
||||||
|
delete ti;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
m_tinfo.append(ti);
|
m_tinfo.append(ti);
|
||||||
// looking for transactions timestamp scope
|
// looking for transactions timestamp scope
|
||||||
if (ti->timestamp() >= lastDateTime) {
|
if (ti->timestamp() >= lastDateTime) {
|
||||||
|
@ -69,12 +73,12 @@ QList<TransactionInfo *> TransactionHistory::getAll() const
|
||||||
return m_tinfo;
|
return m_tinfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TransactionHistory::refresh()
|
void TransactionHistory::refresh(quint32 accountIndex)
|
||||||
{
|
{
|
||||||
// rebuilding transaction list in wallet_api;
|
// rebuilding transaction list in wallet_api;
|
||||||
m_pimpl->refresh();
|
m_pimpl->refresh();
|
||||||
// copying list here and keep track on every item to avoid memleaks
|
// copying list here and keep track on every item to avoid memleaks
|
||||||
getAll();
|
getAll(accountIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
quint64 TransactionHistory::count() const
|
quint64 TransactionHistory::count() const
|
||||||
|
|
|
@ -23,8 +23,8 @@ class TransactionHistory : public QObject
|
||||||
public:
|
public:
|
||||||
Q_INVOKABLE TransactionInfo *transaction(int index);
|
Q_INVOKABLE TransactionInfo *transaction(int index);
|
||||||
// Q_INVOKABLE TransactionInfo * transaction(const QString &id);
|
// Q_INVOKABLE TransactionInfo * transaction(const QString &id);
|
||||||
Q_INVOKABLE QList<TransactionInfo*> getAll() const;
|
Q_INVOKABLE QList<TransactionInfo*> getAll(quint32 accountIndex) const;
|
||||||
Q_INVOKABLE void refresh();
|
Q_INVOKABLE void refresh(quint32 accountIndex);
|
||||||
quint64 count() const;
|
quint64 count() const;
|
||||||
QDateTime firstDateTime() const;
|
QDateTime firstDateTime() const;
|
||||||
QDateTime lastDateTime() const;
|
QDateTime lastDateTime() const;
|
||||||
|
|
|
@ -48,6 +48,24 @@ quint64 TransactionInfo::blockHeight() const
|
||||||
return m_pimpl->blockHeight();
|
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
|
quint64 TransactionInfo::confirmations() const
|
||||||
{
|
{
|
||||||
return m_pimpl->confirmations();
|
return m_pimpl->confirmations();
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include <wallet/api/wallet2_api.h>
|
#include <wallet/api/wallet2_api.h>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
|
#include <QSet>
|
||||||
|
|
||||||
class Transfer;
|
class Transfer;
|
||||||
|
|
||||||
|
@ -18,6 +19,9 @@ class TransactionInfo : public QObject
|
||||||
Q_PROPERTY(QString displayAmount READ displayAmount)
|
Q_PROPERTY(QString displayAmount READ displayAmount)
|
||||||
Q_PROPERTY(QString fee READ fee)
|
Q_PROPERTY(QString fee READ fee)
|
||||||
Q_PROPERTY(quint64 blockHeight READ blockHeight)
|
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 confirmations READ confirmations)
|
||||||
Q_PROPERTY(quint64 unlockTime READ unlockTime)
|
Q_PROPERTY(quint64 unlockTime READ unlockTime)
|
||||||
Q_PROPERTY(QString hash READ hash)
|
Q_PROPERTY(QString hash READ hash)
|
||||||
|
@ -44,6 +48,9 @@ public:
|
||||||
QString displayAmount() const;
|
QString displayAmount() const;
|
||||||
QString fee() const;
|
QString fee() const;
|
||||||
quint64 blockHeight() const;
|
quint64 blockHeight() const;
|
||||||
|
QSet<quint32> subaddrIndex() const;
|
||||||
|
quint32 subaddrAccount() const;
|
||||||
|
QString label() const;
|
||||||
quint64 confirmations() const;
|
quint64 confirmations() const;
|
||||||
quint64 unlockTime() const;
|
quint64 unlockTime() const;
|
||||||
//! transaction_id
|
//! transaction_id
|
||||||
|
|
|
@ -3,9 +3,11 @@
|
||||||
#include "UnsignedTransaction.h"
|
#include "UnsignedTransaction.h"
|
||||||
#include "TransactionHistory.h"
|
#include "TransactionHistory.h"
|
||||||
#include "AddressBook.h"
|
#include "AddressBook.h"
|
||||||
|
#include "Subaddress.h"
|
||||||
#include "model/TransactionHistoryModel.h"
|
#include "model/TransactionHistoryModel.h"
|
||||||
#include "model/TransactionHistorySortFilterModel.h"
|
#include "model/TransactionHistorySortFilterModel.h"
|
||||||
#include "model/AddressBookModel.h"
|
#include "model/AddressBookModel.h"
|
||||||
|
#include "model/SubaddressModel.h"
|
||||||
#include "wallet/api/wallet2_api.h"
|
#include "wallet/api/wallet2_api.h"
|
||||||
|
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
|
@ -155,9 +157,9 @@ bool Wallet::setPassword(const QString &password)
|
||||||
return m_walletImpl->setPassword(password.toStdString());
|
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
|
QString Wallet::path() const
|
||||||
|
@ -241,14 +243,63 @@ bool Wallet::viewOnly() const
|
||||||
return m_walletImpl->watchOnly();
|
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
|
quint64 Wallet::blockChainHeight() const
|
||||||
|
@ -288,7 +339,8 @@ quint64 Wallet::daemonBlockChainTargetHeight() const
|
||||||
bool Wallet::refresh()
|
bool Wallet::refresh()
|
||||||
{
|
{
|
||||||
bool result = m_walletImpl->refresh();
|
bool result = m_walletImpl->refresh();
|
||||||
m_history->refresh();
|
m_history->refresh(currentSubaddressAccount());
|
||||||
|
m_subaddress->refresh(currentSubaddressAccount());
|
||||||
if (result)
|
if (result)
|
||||||
emit updated();
|
emit updated();
|
||||||
return result;
|
return result;
|
||||||
|
@ -324,9 +376,10 @@ PendingTransaction *Wallet::createTransaction(const QString &dst_addr, const QSt
|
||||||
quint64 amount, quint32 mixin_count,
|
quint64 amount, quint32 mixin_count,
|
||||||
PendingTransaction::Priority priority)
|
PendingTransaction::Priority priority)
|
||||||
{
|
{
|
||||||
|
std::set<uint32_t> subaddr_indices;
|
||||||
Monero::PendingTransaction * ptImpl = m_walletImpl->createTransaction(
|
Monero::PendingTransaction * ptImpl = m_walletImpl->createTransaction(
|
||||||
dst_addr.toStdString(), payment_id.toStdString(), amount, mixin_count,
|
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);
|
PendingTransaction * result = new PendingTransaction(ptImpl,0);
|
||||||
return result;
|
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,
|
PendingTransaction *Wallet::createTransactionAll(const QString &dst_addr, const QString &payment_id,
|
||||||
quint32 mixin_count, PendingTransaction::Priority priority)
|
quint32 mixin_count, PendingTransaction::Priority priority)
|
||||||
{
|
{
|
||||||
|
std::set<uint32_t> subaddr_indices;
|
||||||
Monero::PendingTransaction * ptImpl = m_walletImpl->createTransaction(
|
Monero::PendingTransaction * ptImpl = m_walletImpl->createTransaction(
|
||||||
dst_addr.toStdString(), payment_id.toStdString(), Monero::optional<uint64_t>(), mixin_count,
|
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);
|
PendingTransaction * result = new PendingTransaction(ptImpl, this);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -458,6 +512,18 @@ AddressBookModel *Wallet::addressBookModel() const
|
||||||
return m_addressBookModel;
|
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
|
QString Wallet::generatePaymentId() const
|
||||||
{
|
{
|
||||||
|
@ -668,14 +734,18 @@ Wallet::Wallet(Monero::Wallet *w, QObject *parent)
|
||||||
, m_historyModel(nullptr)
|
, m_historyModel(nullptr)
|
||||||
, m_addressBook(nullptr)
|
, m_addressBook(nullptr)
|
||||||
, m_addressBookModel(nullptr)
|
, m_addressBookModel(nullptr)
|
||||||
|
, m_subaddress(nullptr)
|
||||||
|
, m_subaddressModel(nullptr)
|
||||||
, m_daemonBlockChainHeight(0)
|
, m_daemonBlockChainHeight(0)
|
||||||
, m_daemonBlockChainHeightTtl(DAEMON_BLOCKCHAIN_HEIGHT_CACHE_TTL_SECONDS)
|
, m_daemonBlockChainHeightTtl(DAEMON_BLOCKCHAIN_HEIGHT_CACHE_TTL_SECONDS)
|
||||||
, m_daemonBlockChainTargetHeight(0)
|
, m_daemonBlockChainTargetHeight(0)
|
||||||
, m_daemonBlockChainTargetHeightTtl(DAEMON_BLOCKCHAIN_TARGET_HEIGHT_CACHE_TTL_SECONDS)
|
, m_daemonBlockChainTargetHeightTtl(DAEMON_BLOCKCHAIN_TARGET_HEIGHT_CACHE_TTL_SECONDS)
|
||||||
, m_connectionStatusTtl(WALLET_CONNECTION_STATUS_CACHE_TTL_SECONDS)
|
, m_connectionStatusTtl(WALLET_CONNECTION_STATUS_CACHE_TTL_SECONDS)
|
||||||
|
, m_currentSubaddressAccount(0)
|
||||||
{
|
{
|
||||||
m_history = new TransactionHistory(m_walletImpl->history(), this);
|
m_history = new TransactionHistory(m_walletImpl->history(), this);
|
||||||
m_addressBook = new AddressBook(m_walletImpl->addressBook(), this);
|
m_addressBook = new AddressBook(m_walletImpl->addressBook(), this);
|
||||||
|
m_subaddress = new Subaddress(m_walletImpl->subaddress(), this);
|
||||||
m_walletImpl->setListener(new WalletListenerImpl(this));
|
m_walletImpl->setListener(new WalletListenerImpl(this));
|
||||||
m_connectionStatus = Wallet::ConnectionStatus_Disconnected;
|
m_connectionStatus = Wallet::ConnectionStatus_Disconnected;
|
||||||
// start cache timers
|
// start cache timers
|
||||||
|
@ -696,6 +766,10 @@ Wallet::~Wallet()
|
||||||
|
|
||||||
delete m_history;
|
delete m_history;
|
||||||
m_history = NULL;
|
m_history = NULL;
|
||||||
|
delete m_addressBook;
|
||||||
|
m_addressBook = NULL;
|
||||||
|
delete m_subaddress;
|
||||||
|
m_subaddress = NULL;
|
||||||
//Monero::WalletManagerFactory::getWalletManager()->closeWallet(m_walletImpl);
|
//Monero::WalletManagerFactory::getWalletManager()->closeWallet(m_walletImpl);
|
||||||
if(status() == Status_Critical)
|
if(status() == Status_Critical)
|
||||||
qDebug("Not storing wallet cache");
|
qDebug("Not storing wallet cache");
|
||||||
|
|
|
@ -20,6 +20,8 @@ class TransactionHistoryModel;
|
||||||
class TransactionHistorySortFilterModel;
|
class TransactionHistorySortFilterModel;
|
||||||
class AddressBook;
|
class AddressBook;
|
||||||
class AddressBookModel;
|
class AddressBookModel;
|
||||||
|
class Subaddress;
|
||||||
|
class SubaddressModel;
|
||||||
|
|
||||||
class Wallet : public QObject
|
class Wallet : public QObject
|
||||||
{
|
{
|
||||||
|
@ -29,17 +31,17 @@ class Wallet : public QObject
|
||||||
Q_PROPERTY(Status status READ status)
|
Q_PROPERTY(Status status READ status)
|
||||||
Q_PROPERTY(bool testnet READ testnet)
|
Q_PROPERTY(bool testnet READ testnet)
|
||||||
// Q_PROPERTY(ConnectionStatus connected READ connected)
|
// Q_PROPERTY(ConnectionStatus connected READ connected)
|
||||||
|
Q_PROPERTY(quint32 currentSubaddressAccount READ currentSubaddressAccount)
|
||||||
Q_PROPERTY(bool synchronized READ synchronized)
|
Q_PROPERTY(bool synchronized READ synchronized)
|
||||||
Q_PROPERTY(QString errorString READ errorString)
|
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(TransactionHistory * history READ history)
|
||||||
Q_PROPERTY(QString paymentId READ paymentId WRITE setPaymentId)
|
Q_PROPERTY(QString paymentId READ paymentId WRITE setPaymentId)
|
||||||
Q_PROPERTY(TransactionHistorySortFilterModel * historyModel READ historyModel NOTIFY historyModelChanged)
|
Q_PROPERTY(TransactionHistorySortFilterModel * historyModel READ historyModel NOTIFY historyModelChanged)
|
||||||
Q_PROPERTY(QString path READ path)
|
Q_PROPERTY(QString path READ path)
|
||||||
Q_PROPERTY(AddressBookModel * addressBookModel READ addressBookModel)
|
Q_PROPERTY(AddressBookModel * addressBookModel READ addressBookModel)
|
||||||
Q_PROPERTY(AddressBook * addressBook READ addressBook)
|
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(bool viewOnly READ viewOnly)
|
||||||
Q_PROPERTY(QString secretViewKey READ getSecretViewKey)
|
Q_PROPERTY(QString secretViewKey READ getSecretViewKey)
|
||||||
Q_PROPERTY(QString publicViewKey READ getPublicViewKey)
|
Q_PROPERTY(QString publicViewKey READ getPublicViewKey)
|
||||||
|
@ -98,7 +100,7 @@ public:
|
||||||
Q_INVOKABLE bool setPassword(const QString &password);
|
Q_INVOKABLE bool setPassword(const QString &password);
|
||||||
|
|
||||||
//! returns wallet's public address
|
//! returns wallet's public address
|
||||||
QString address() const;
|
Q_INVOKABLE QString address(quint32 accountIndex, quint32 addressIndex) const;
|
||||||
|
|
||||||
//! returns wallet file's path
|
//! returns wallet file's path
|
||||||
QString path() const;
|
QString path() const;
|
||||||
|
@ -126,10 +128,22 @@ public:
|
||||||
Q_INVOKABLE void setTrustedDaemon(bool arg);
|
Q_INVOKABLE void setTrustedDaemon(bool arg);
|
||||||
|
|
||||||
//! returns balance
|
//! returns balance
|
||||||
Q_INVOKABLE quint64 balance() const;
|
Q_INVOKABLE quint64 balance(quint32 accountIndex) const;
|
||||||
|
Q_INVOKABLE quint64 balanceAll() const;
|
||||||
|
|
||||||
//! returns unlocked balance
|
//! 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
|
//! returns if view only wallet
|
||||||
Q_INVOKABLE bool viewOnly() const;
|
Q_INVOKABLE bool viewOnly() const;
|
||||||
|
@ -209,6 +223,12 @@ public:
|
||||||
//! returns adress book model
|
//! returns adress book model
|
||||||
AddressBookModel *addressBookModel() const;
|
AddressBookModel *addressBookModel() const;
|
||||||
|
|
||||||
|
//! returns subaddress
|
||||||
|
Subaddress *subaddress();
|
||||||
|
|
||||||
|
//! returns subadress model
|
||||||
|
SubaddressModel *subaddressModel();
|
||||||
|
|
||||||
//! generate payment id
|
//! generate payment id
|
||||||
Q_INVOKABLE QString generatePaymentId() const;
|
Q_INVOKABLE QString generatePaymentId() const;
|
||||||
|
|
||||||
|
@ -302,8 +322,11 @@ private:
|
||||||
int m_connectionStatusTtl;
|
int m_connectionStatusTtl;
|
||||||
mutable QTime m_connectionStatusTime;
|
mutable QTime m_connectionStatusTime;
|
||||||
mutable bool m_initialized;
|
mutable bool m_initialized;
|
||||||
|
uint32_t m_currentSubaddressAccount;
|
||||||
AddressBook * m_addressBook;
|
AddressBook * m_addressBook;
|
||||||
mutable AddressBookModel * m_addressBookModel;
|
mutable AddressBookModel * m_addressBookModel;
|
||||||
|
Subaddress * m_subaddress;
|
||||||
|
mutable SubaddressModel * m_subaddressModel;
|
||||||
QMutex m_connectionStatusMutex;
|
QMutex m_connectionStatusMutex;
|
||||||
bool m_connectionStatusRunning;
|
bool m_connectionStatusRunning;
|
||||||
QString m_daemonUsername;
|
QString m_daemonUsername;
|
||||||
|
|
|
@ -49,7 +49,7 @@ Wallet *WalletManager::openWallet(const QString &path, const QString &password,
|
||||||
__PRETTY_FUNCTION__, qPrintable(path), testnet);
|
__PRETTY_FUNCTION__, qPrintable(path), testnet);
|
||||||
|
|
||||||
Monero::Wallet * w = m_pimpl->openWallet(path.toStdString(), password.toStdString(), 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);
|
m_currentWallet = new Wallet(w);
|
||||||
|
|
||||||
// move wallet to the GUI thread. Otherwise it wont be emitting signals
|
// move wallet to the GUI thread. Otherwise it wont be emitting signals
|
||||||
|
@ -110,7 +110,7 @@ QString WalletManager::closeWallet()
|
||||||
QMutexLocker locker(&m_mutex);
|
QMutexLocker locker(&m_mutex);
|
||||||
QString result;
|
QString result;
|
||||||
if (m_currentWallet) {
|
if (m_currentWallet) {
|
||||||
result = m_currentWallet->address();
|
result = m_currentWallet->address(0, 0);
|
||||||
delete m_currentWallet;
|
delete m_currentWallet;
|
||||||
} else {
|
} else {
|
||||||
qCritical() << "Trying to close non existing wallet " << m_currentWallet;
|
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;
|
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:
|
case TransactionConfirmationsRole:
|
||||||
result = tInfo->confirmations();
|
result = tInfo->confirmations();
|
||||||
break;
|
break;
|
||||||
|
@ -133,6 +152,9 @@ QHash<int, QByteArray> TransactionHistoryModel::roleNames() const
|
||||||
roleNames.insert(TransactionAtomicAmountRole, "atomicAmount");
|
roleNames.insert(TransactionAtomicAmountRole, "atomicAmount");
|
||||||
roleNames.insert(TransactionFeeRole, "fee");
|
roleNames.insert(TransactionFeeRole, "fee");
|
||||||
roleNames.insert(TransactionBlockHeightRole, "blockHeight");
|
roleNames.insert(TransactionBlockHeightRole, "blockHeight");
|
||||||
|
roleNames.insert(TransactionSubaddrIndexRole, "subaddrIndex");
|
||||||
|
roleNames.insert(TransactionSubaddrAccountRole, "subaddrAccount");
|
||||||
|
roleNames.insert(TransactionLabelRole, "label");
|
||||||
roleNames.insert(TransactionConfirmationsRole, "confirmations");
|
roleNames.insert(TransactionConfirmationsRole, "confirmations");
|
||||||
roleNames.insert(TransactionConfirmationsRequiredRole, "confirmationsRequired");
|
roleNames.insert(TransactionConfirmationsRequiredRole, "confirmationsRequired");
|
||||||
roleNames.insert(TransactionHashRole, "hash");
|
roleNames.insert(TransactionHashRole, "hash");
|
||||||
|
|
|
@ -25,6 +25,9 @@ public:
|
||||||
TransactionDisplayAmountRole,
|
TransactionDisplayAmountRole,
|
||||||
TransactionFeeRole,
|
TransactionFeeRole,
|
||||||
TransactionBlockHeightRole,
|
TransactionBlockHeightRole,
|
||||||
|
TransactionSubaddrIndexRole,
|
||||||
|
TransactionSubaddrAccountRole,
|
||||||
|
TransactionLabelRole,
|
||||||
TransactionConfirmationsRole,
|
TransactionConfirmationsRole,
|
||||||
TransactionConfirmationsRequiredRole,
|
TransactionConfirmationsRequiredRole,
|
||||||
TransactionHashRole,
|
TransactionHashRole,
|
||||||
|
|
Loading…
Reference in a new issue