aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorluigi1111 <luigi1111w@gmail.com>2019-02-01 01:04:38 -0600
committerluigi1111 <luigi1111w@gmail.com>2019-02-01 01:04:38 -0600
commit10d8fc01ea1ed6b60b04943138a0c2cbeef62d9c (patch)
tree839b023db51da6aadd95e5beef2a38f5d59a4b1c
parent443e9c260ddfbcea88166133049540aebdd4f477 (diff)
parentbd809abc52cc8d312c0023cfc9ae2d14e191d0b5 (diff)
downloadmonzero-gui-10d8fc01ea1ed6b60b04943138a0c2cbeef62d9c.tar.gz
monzero-gui-10d8fc01ea1ed6b60b04943138a0c2cbeef62d9c.tar.xz
monzero-gui-10d8fc01ea1ed6b60b04943138a0c2cbeef62d9c.zip
Merge pull request #1905
bd809ab add account support (selsta)
-rw-r--r--LeftPanel.qml29
-rw-r--r--MiddlePanel.qml8
-rw-r--r--components/Label.qml2
-rwxr-xr-ximages/plus-in-circle-medium-white.pngbin0 -> 399 bytes
-rwxr-xr-ximages/plus-in-circle-medium-white@2x.pngbin0 -> 760 bytes
-rw-r--r--main.cpp8
-rw-r--r--main.qml22
-rw-r--r--monero-wallet-gui.pro4
-rw-r--r--pages/Account.qml352
-rw-r--r--pages/Transfer.qml8
-rw-r--r--qml.qrc3
-rw-r--r--src/libwalletqt/SubaddressAccount.cpp56
-rw-r--r--src/libwalletqt/SubaddressAccount.h33
-rw-r--r--src/libwalletqt/Wallet.cpp22
-rw-r--r--src/libwalletqt/Wallet.h12
-rw-r--r--src/model/SubaddressAccountModel.cpp66
-rw-r--r--src/model/SubaddressAccountModel.h36
17 files changed, 654 insertions, 7 deletions
diff --git a/LeftPanel.qml b/LeftPanel.qml
index 425c955c..fce19dec 100644
--- a/LeftPanel.qml
+++ b/LeftPanel.qml
@@ -61,6 +61,7 @@ Rectangle {
signal signClicked()
signal keysClicked()
signal merchantClicked()
+ signal accountClicked()
function selectItem(pos) {
menuColumn.previousButton.checked = false
@@ -76,7 +77,7 @@ Rectangle {
else if(pos === "Settings") menuColumn.previousButton = settingsButton
else if(pos === "Advanced") menuColumn.previousButton = advancedButton
else if(pos === "Keys") menuColumn.previousButton = keysButton
-
+ else if(pos === "Account") menuColumn.previousButton = accountButton
menuColumn.previousButton.checked = true
}
@@ -285,6 +286,8 @@ Rectangle {
anchors.leftMargin: 20
anchors.top: parent.top
anchors.topMargin: 60
+ elide: Text.ElideRight
+ textWidth: 238
}
Item { //separator
anchors.left: parent.left
@@ -331,6 +334,30 @@ Rectangle {
height: 1
}
+ // ------------- Account tab ---------------
+ MoneroComponents.MenuButton {
+ id: accountButton
+ anchors.left: parent.left
+ anchors.right: parent.right
+ text: qsTr("Account") + translationManager.emptyString
+ symbol: qsTr("T") + translationManager.emptyString
+ dotColor: "#44AAFF"
+ onClicked: {
+ parent.previousButton.checked = false
+ parent.previousButton = accountButton
+ panel.accountClicked()
+ }
+ }
+
+ Rectangle {
+ visible: accountButton.present
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.leftMargin: 16
+ color: "#313131"
+ height: 1
+ }
+
// ------------- Transfer tab ---------------
MoneroComponents.MenuButton {
id: transferButton
diff --git a/MiddlePanel.qml b/MiddlePanel.qml
index 4ed21c58..df0aa1b3 100644
--- a/MiddlePanel.qml
+++ b/MiddlePanel.qml
@@ -67,7 +67,7 @@ Rectangle {
property Mining miningView: Mining { }
property AddressBook addressBookView: AddressBook { }
property Keys keysView: Keys { }
-
+ property Account accountView: Account { }
signal paymentClicked(string address, string paymentId, string amount, int mixinCount, int priority, string description)
signal sweepUnmixableClicked()
@@ -160,7 +160,11 @@ Rectangle {
name: "Keys"
PropertyChanges { target: root; currentView: keysView }
PropertyChanges { target: mainFlickable; contentHeight: keysView.keysHeight }
- }
+ }, State {
+ name: "Account"
+ PropertyChanges { target: root; currentView: accountView }
+ PropertyChanges { target: mainFlickable; contentHeight: minHeight }
+ }
]
// color stripe at the top
diff --git a/components/Label.qml b/components/Label.qml
index 1edc14e8..05c65da6 100644
--- a/components/Label.qml
+++ b/components/Label.qml
@@ -44,6 +44,8 @@ Item {
property alias wrapMode: label.wrapMode
property alias horizontalAlignment: label.horizontalAlignment
property alias hoveredLink: label.hoveredLink
+ property alias elide: label.elide
+ property alias textWidth: label.width
signal linkActivated()
height: label.height * scaleRatio
width: label.width * scaleRatio
diff --git a/images/plus-in-circle-medium-white.png b/images/plus-in-circle-medium-white.png
new file mode 100755
index 00000000..ddc548fb
--- /dev/null
+++ b/images/plus-in-circle-medium-white.png
Binary files differ
diff --git a/images/plus-in-circle-medium-white@2x.png b/images/plus-in-circle-medium-white@2x.png
new file mode 100755
index 00000000..c4c3af90
--- /dev/null
+++ b/images/plus-in-circle-medium-white@2x.png
Binary files differ
diff --git a/main.cpp b/main.cpp
index 43b1f5a6..b47d1191 100644
--- a/main.cpp
+++ b/main.cpp
@@ -55,6 +55,8 @@
#include "model/AddressBookModel.h"
#include "Subaddress.h"
#include "model/SubaddressModel.h"
+#include "SubaddressAccount.h"
+#include "model/SubaddressAccountModel.h"
#include "wallet/api/wallet2_api.h"
#include "Logger.h"
#include "MainApp.h"
@@ -208,6 +210,12 @@ int main(int argc, char *argv[])
qmlRegisterUncreatableType<Subaddress>("moneroComponents.Subaddress", 1, 0, "Subaddress",
"Subaddress can't be instantiated directly");
+ qmlRegisterUncreatableType<SubaddressAccountModel>("moneroComponents.SubaddressAccountModel", 1, 0, "SubaddressAccountModel",
+ "SubaddressAccountModel can't be instantiated directly");
+
+ qmlRegisterUncreatableType<SubaddressAccount>("moneroComponents.SubaddressAccount", 1, 0, "SubaddressAccount",
+ "SubaddressAccount can't be instantiated directly");
+
qRegisterMetaType<PendingTransaction::Priority>();
qRegisterMetaType<TransactionInfo::Direction>();
qRegisterMetaType<TransactionHistoryModel::TransactionInfoRole>();
diff --git a/main.qml b/main.qml
index df84d763..7de16518 100644
--- a/main.qml
+++ b/main.qml
@@ -86,10 +86,11 @@ ApplicationWindow {
// true if wallet ever synchronized
property bool walletInitialized : false
- // Current selected address / subaddress (Receive page)
+ // Current selected address / subaddress / (Receive/Account page)
property var current_address
property var current_address_label: "Primary"
property int current_subaddress_table_index: 0
+ property int current_subaddress_account_table_index: 0
function altKeyReleased() { ctrlPressed = false; }
@@ -117,6 +118,7 @@ ApplicationWindow {
else if(seq === "Ctrl+E") middlePanel.state = "Settings"
else if(seq === "Ctrl+Y") leftPanel.keysClicked()
else if(seq === "Ctrl+D") middlePanel.state = "Advanced"
+ else if(seq === "Ctrl+T") middlePanel.state = "Account"
else if(seq === "Ctrl+Tab" || seq === "Alt+Tab") {
/*
if(middlePanel.state === "Transfer") middlePanel.state = "Receive"
@@ -128,7 +130,8 @@ ApplicationWindow {
else if(middlePanel.state === "Mining") middlePanel.state = "Sign"
else if(middlePanel.state === "Sign") middlePanel.state = "Settings"
*/
- if(middlePanel.state === "Settings") middlePanel.state = "Transfer"
+ if(middlePanel.state === "Settings") middlePanel.state = "Account"
+ else if(middlePanel.state === "Account") middlePanel.state = "Transfer"
else if(middlePanel.state === "Transfer") middlePanel.state = "AddressBook"
else if(middlePanel.state === "AddressBook") middlePanel.state = "Receive"
else if(middlePanel.state === "Receive") middlePanel.state = "History"
@@ -156,7 +159,8 @@ ApplicationWindow {
else if(middlePanel.state === "History") middlePanel.state = "Receive"
else if(middlePanel.state === "Receive") middlePanel.state = "AddressBook"
else if(middlePanel.state === "AddressBook") middlePanel.state = "Transfer"
- else if(middlePanel.state === "Transfer") middlePanel.state = "Settings"
+ else if(middlePanel.state === "Transfer") middlePanel.state = "Account"
+ else if(middlePanel.state === "Account") middlePanel.state = "Settings"
}
if (middlePanel.state !== "Advanced") updateBalance();
@@ -368,6 +372,9 @@ ApplicationWindow {
leftPanel.unlockedBalanceText = balance_unlocked;
middlePanel.balanceText = balance;
leftPanel.balanceText = balance;
+
+ var accountLabel = currentWallet.getSubaddressLabel(currentWallet.currentSubaddressAccount, 0);
+ leftPanel.balanceLabelText = qsTr("Balance (#%1%2)").arg(currentWallet.currentSubaddressAccount).arg(accountLabel === "" ? "" : (" – " + accountLabel));
}
function onWalletConnectionStatusChanged(status){
@@ -1435,6 +1442,15 @@ ApplicationWindow {
}
onKeysClicked: Utils.showSeedPage();
+
+ onAccountClicked: {
+ middlePanel.state = "Account";
+ middlePanel.flickable.contentY = 0;
+ if(isMobile) {
+ hideMenu();
+ }
+ updateBalance();
+ }
}
RightPanel {
diff --git a/monero-wallet-gui.pro b/monero-wallet-gui.pro
index 2662c5c9..15405d29 100644
--- a/monero-wallet-gui.pro
+++ b/monero-wallet-gui.pro
@@ -50,6 +50,8 @@ HEADERS += \
src/libwalletqt/AddressBook.h \
src/model/SubaddressModel.h \
src/libwalletqt/Subaddress.h \
+ src/model/SubaddressAccountModel.h \
+ src/libwalletqt/SubaddressAccount.h \
src/zxcvbn-c/zxcvbn.h \
src/libwalletqt/UnsignedTransaction.h \
Logger.h \
@@ -76,6 +78,8 @@ SOURCES += main.cpp \
src/libwalletqt/AddressBook.cpp \
src/model/SubaddressModel.cpp \
src/libwalletqt/Subaddress.cpp \
+ src/model/SubaddressAccountModel.cpp \
+ src/libwalletqt/SubaddressAccount.cpp \
src/zxcvbn-c/zxcvbn.c \
src/libwalletqt/UnsignedTransaction.cpp \
Logger.cpp \
diff --git a/pages/Account.qml b/pages/Account.qml
new file mode 100644
index 00000000..ba06a81c
--- /dev/null
+++ b/pages/Account.qml
@@ -0,0 +1,352 @@
+// Copyright (c) 2014-2019, 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 2.0
+import QtQuick.Controls.Styles 1.4
+import QtQuick.Layouts 1.1
+import QtQuick.Dialogs 1.2
+
+import "../components" as MoneroComponents
+import moneroComponents.Clipboard 1.0
+import moneroComponents.Wallet 1.0
+import moneroComponents.WalletManager 1.0
+import moneroComponents.TransactionHistory 1.0
+import moneroComponents.TransactionHistoryModel 1.0
+import "../js/TxUtils.js" as TxUtils
+
+Rectangle {
+ id: pageAccount
+ color: "transparent"
+ property var model
+ property alias accountHeight: mainLayout.height
+ property bool selectAndSend: false
+
+ function renameSubaddressAccountLabel(_index){
+ inputDialog.labelText = qsTr("Set the label of the selected account:") + translationManager.emptyString;
+ inputDialog.inputText = appWindow.currentWallet.getSubaddressLabel(_index, 0);
+ inputDialog.onAcceptedCallback = function() {
+ appWindow.currentWallet.subaddressAccount.setLabel(_index, inputDialog.inputText)
+ }
+ inputDialog.onRejectedCallback = null;
+ inputDialog.open()
+ }
+
+ Clipboard { id: clipboard }
+
+ /* main layout */
+ ColumnLayout {
+ id: mainLayout
+ anchors.margins: (isMobile)? 17 * scaleRatio : 20 * scaleRatio
+ anchors.topMargin: 40 * scaleRatio
+
+ anchors.left: parent.left
+ anchors.top: parent.top
+ anchors.right: parent.right
+
+ spacing: 20 * scaleRatio
+
+ ColumnLayout {
+ id: balanceRow
+ visible: !selectAndSend
+ spacing: 0
+
+ MoneroComponents.LabelSubheader {
+ Layout.fillWidth: true
+ textFormat: Text.RichText
+ text: qsTr("Balance All")
+ }
+
+ RowLayout {
+ Layout.topMargin: 22 * scaleRatio
+ Text {
+ text: qsTr("Total balance: ")
+ Layout.fillWidth: true
+ color: "#757575"
+ font.pixelSize: 14
+ font.family: MoneroComponents.Style.fontRegular.name
+ }
+ Text {
+ id: balanceAll
+ font.family: MoneroComponents.Style.fontRegular.name
+ font.pixelSize: 14
+ color: MoneroComponents.Style.white
+ MouseArea {
+ hoverEnabled: true
+ anchors.fill: parent
+ cursorShape: Qt.PointingHandCursor
+ onEntered: {
+ parent.color = MoneroComponents.Style.orange
+ }
+ onExited: {
+ parent.color = MoneroComponents.Style.white
+ }
+ onClicked: {
+ console.log("Copied to clipboard");
+ clipboard.setText(parent.text);
+ appWindow.showStatusMessage(qsTr("Copied to clipboard"),3)
+ }
+ }
+ }
+ }
+
+ RowLayout {
+ Layout.topMargin: 10 * scaleRatio
+ Text {
+ text: qsTr("Total unlocked balance: ")
+ Layout.fillWidth: true
+ color: "#757575"
+ font.pixelSize: 14
+ font.family: MoneroComponents.Style.fontRegular.name
+ }
+ Text {
+ id: unlockedBalanceAll
+ font.family: MoneroComponents.Style.fontRegular.name
+ font.pixelSize: 14
+ color: MoneroComponents.Style.white
+ MouseArea {
+ hoverEnabled: true
+ anchors.fill: parent
+ cursorShape: Qt.PointingHandCursor
+ onEntered: {
+ parent.color = MoneroComponents.Style.orange
+ }
+ onExited: {
+ parent.color = MoneroComponents.Style.white
+ }
+ onClicked: {
+ console.log("Copied to clipboard");
+ clipboard.setText(parent.text);
+ appWindow.showStatusMessage(qsTr("Copied to clipboard"),3)
+ }
+ }
+ }
+ }
+ }
+
+ ColumnLayout {
+ id: addressRow
+ spacing: 0
+
+ MoneroComponents.LabelSubheader {
+ Layout.fillWidth: true
+ textFormat: Text.RichText
+ text: qsTr("Accounts")
+ }
+
+ ColumnLayout {
+ id: subaddressAccountListRow
+ property int subaddressAccountListItemHeight: 50 * scaleRatio
+ Layout.topMargin: 6 * scaleRatio
+ Layout.fillWidth: true
+ Layout.minimumWidth: 240
+ Layout.preferredHeight: subaddressAccountListItemHeight * subaddressAccountListView.count
+ visible: subaddressAccountListView.count >= 1
+
+ ListView {
+ id: subaddressAccountListView
+ Layout.fillWidth: true
+ anchors.fill: parent
+ clip: true
+ boundsBehavior: ListView.StopAtBounds
+ delegate: Rectangle {
+ id: tableItem2
+ height: subaddressAccountListRow.subaddressAccountListItemHeight
+ width: parent.width
+ Layout.fillWidth: true
+ color: "transparent"
+ Rectangle {
+ anchors.right: parent.right
+ anchors.left: parent.left
+ anchors.top: parent.top
+ height: 1
+ color: "#404040"
+ visible: index !== 0
+ }
+
+ Rectangle {
+ anchors.fill: parent
+ anchors.topMargin: 5 * scaleRatio
+ anchors.rightMargin: 80 * scaleRatio
+ color: "transparent"
+
+ MoneroComponents.Label {
+ id: idLabel
+ color: index === appWindow.current_subaddress_account_table_index ? "white" : "#757575"
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.left: parent.left
+ anchors.leftMargin: 6 * scaleRatio
+ fontSize: 14 * scaleRatio
+ fontBold: true
+ text: "#" + index
+ }
+
+ MoneroComponents.Label {
+ id: nameLabel
+ color: "#a5a5a5"
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.left: idLabel.right
+ anchors.leftMargin: 6 * scaleRatio
+ fontSize: 14 * scaleRatio
+ fontBold: true
+ text: label
+ elide: Text.ElideRight
+ textWidth: addressLabel.x - nameLabel.x - 1
+ }
+
+ MoneroComponents.Label {
+ id: addressLabel
+ color: "white"
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.left: balanceLabel.left
+ anchors.leftMargin: (mainLayout.width < 510 ? -70 : -125) * scaleRatio
+ fontSize: 14 * scaleRatio
+ fontBold: true
+ text: TxUtils.addressTruncate(address, mainLayout.width < 510 ? 3 : 6)
+ }
+
+ MoneroComponents.Label {
+ id: balanceLabel
+ color: "white"
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.left: parent.right
+ anchors.leftMargin: (mainLayout.width < 510 ? -120 : -180) * scaleRatio
+ fontSize: 14 * scaleRatio
+ fontBold: true
+ text: qsTr("Balance: ") + balance
+ elide: mainLayout.width < 510 ? Text.ElideRight : Text.ElideNone
+ textWidth: 120
+ }
+
+ MouseArea {
+ cursorShape: Qt.PointingHandCursor
+ anchors.fill: parent
+ hoverEnabled: true
+ onEntered: {
+ tableItem2.color = "#26FFFFFF"
+ }
+ onExited: {
+ tableItem2.color = "transparent"
+ }
+ onClicked: {
+ if (index == subaddressAccountListView.currentIndex && selectAndSend) {
+ appWindow.showPageRequest("Transfer");
+ }
+ subaddressAccountListView.currentIndex = index;
+ }
+ }
+ }
+
+ MoneroComponents.IconButton {
+ id: renameButton
+ imageSource: "../images/editIcon.png"
+ anchors.right: parent.right
+ anchors.rightMargin: 30 * scaleRatio
+ anchors.topMargin: 1 * scaleRatio
+
+ onClicked: {
+ renameSubaddressAccountLabel(index);
+ }
+ }
+
+ MoneroComponents.IconButton {
+ id: copyButton
+ imageSource: "../images/dropdownCopy.png"
+ anchors.right: parent.right
+
+ onClicked: {
+ console.log("Address copied to clipboard");
+ clipboard.setText(address);
+ appWindow.showStatusMessage(qsTr("Address copied to clipboard"),3);
+ }
+ }
+ }
+ onCurrentItemChanged: {
+ // reset global vars
+ appWindow.current_subaddress_account_table_index = subaddressAccountListView.currentIndex;
+ appWindow.currentWallet.switchSubaddressAccount(appWindow.current_subaddress_account_table_index);
+ appWindow.onWalletUpdate();
+ }
+
+ onCurrentIndexChanged: {
+ if (selectAndSend) {
+ appWindow.showPageRequest("Transfer");
+ }
+ }
+ }
+ }
+
+ Rectangle {
+ color: "#404040"
+ Layout.fillWidth: true
+ height: 1
+ }
+
+ MoneroComponents.CheckBox {
+ id: addNewAccountCheckbox
+ visible: !selectAndSend
+ border: false
+ checkedIcon: "qrc:///images/plus-in-circle-medium-white.png"
+ uncheckedIcon: "qrc:///images/plus-in-circle-medium-white.png"
+ fontSize: 14 * scaleRatio
+ iconOnTheLeft: true
+ Layout.fillWidth: true
+ Layout.topMargin: 10 * scaleRatio
+ text: qsTr("Create new account") + translationManager.emptyString;
+ onClicked: {
+ inputDialog.labelText = qsTr("Set the label of the new account:") + translationManager.emptyString
+ inputDialog.inputText = qsTr("(Untitled)")
+ inputDialog.onAcceptedCallback = function() {
+ appWindow.currentWallet.subaddressAccount.addRow(inputDialog.inputText)
+ appWindow.currentWallet.switchSubaddressAccount(appWindow.currentWallet.numSubaddressAccounts() - 1)
+ current_subaddress_account_table_index = appWindow.currentWallet.numSubaddressAccounts() - 1
+ appWindow.onWalletUpdate();
+ }
+ inputDialog.onRejectedCallback = null;
+ inputDialog.open()
+ }
+ }
+ }
+ }
+
+ function onPageCompleted() {
+ console.log("account");
+ if (appWindow.currentWallet !== undefined) {
+ appWindow.currentWallet.subaddressAccount.refresh();
+ subaddressAccountListView.model = appWindow.currentWallet.subaddressAccountModel;
+ appWindow.currentWallet.subaddress.refresh(appWindow.currentWallet.currentSubaddressAccount)
+
+ balanceAll.text = walletManager.displayAmount(appWindow.currentWallet.balanceAll())
+ unlockedBalanceAll.text = walletManager.displayAmount(appWindow.currentWallet.unlockedBalanceAll())
+ }
+ }
+
+ function onPageClosed() {
+ selectAndSend = false;
+ }
+}
diff --git a/pages/Transfer.qml b/pages/Transfer.qml
index 51d3d6c3..dcfa2073 100644
--- a/pages/Transfer.qml
+++ b/pages/Transfer.qml
@@ -137,7 +137,13 @@ Rectangle {
id: amountLine
Layout.fillWidth: true
inlineIcon: true
- labelText: qsTr("Amount") + translationManager.emptyString
+ labelText: qsTr("<style type='text/css'>a {text-decoration: none; color: #858585; font-size: 14px;}</style>\
+ Amount <font size='2'> ( </font> <a href='#'>Change account</a><font size='2'> )</font>")
+ + translationManager.emptyString
+ onLabelLinkActivated: {
+ middlePanel.accountView.selectAndSend = true;
+ appWindow.showPageRequest("Account")
+ }
placeholderText: qsTr("") + translationManager.emptyString
width: 100 * scaleRatio
fontBold: true
diff --git a/qml.qrc b/qml.qrc
index c3b0316c..1a234299 100644
--- a/qml.qrc
+++ b/qml.qrc
@@ -17,6 +17,7 @@
<file>images/whatIsIcon@2x.png</file>
<file>images/lockIcon.png</file>
<file>components/MenuButton.qml</file>
+ <file>pages/Account.qml</file>
<file>pages/Transfer.qml</file>
<file>pages/History.qml</file>
<file>pages/AddressBook.qml</file>
@@ -232,6 +233,8 @@
<file>images/eyeHide@2x.png</file>
<file>images/eyeShow.png</file>
<file>images/eyeShow@2x.png</file>
+ <file>images/plus-in-circle-medium-white.png</file>
+ <file>images/plus-in-circle-medium-white@2x.png</file>
<file>pages/merchant/Merchant.qml</file>
<file>pages/merchant/MerchantCheckbox.qml</file>
<file>pages/merchant/MerchantTrackingList.qml</file>
diff --git a/src/libwalletqt/SubaddressAccount.cpp b/src/libwalletqt/SubaddressAccount.cpp
new file mode 100644
index 00000000..83557141
--- /dev/null
+++ b/src/libwalletqt/SubaddressAccount.cpp
@@ -0,0 +1,56 @@
+#include "SubaddressAccount.h"
+#include <QDebug>
+
+SubaddressAccount::SubaddressAccount(Monero::SubaddressAccount *subaddressAccountImpl, QObject *parent)
+ : QObject(parent), m_subaddressAccountImpl(subaddressAccountImpl)
+{
+ qDebug(__FUNCTION__);
+ getAll();
+}
+
+QList<Monero::SubaddressAccountRow*> SubaddressAccount::getAll(bool update) const
+{
+ qDebug(__FUNCTION__);
+
+ emit refreshStarted();
+
+ if(update)
+ m_rows.clear();
+
+ if (m_rows.empty()){
+ for (auto &row: m_subaddressAccountImpl->getAll()) {
+ m_rows.append(row);
+ }
+ }
+
+ emit refreshFinished();
+ return m_rows;
+}
+
+Monero::SubaddressAccountRow * SubaddressAccount::getRow(int index) const
+{
+ return m_rows.at(index);
+}
+
+void SubaddressAccount::addRow(const QString &label) const
+{
+ m_subaddressAccountImpl->addRow(label.toStdString());
+ getAll(true);
+}
+
+void SubaddressAccount::setLabel(quint32 accountIndex, const QString &label) const
+{
+ m_subaddressAccountImpl->setLabel(accountIndex, label.toStdString());
+ getAll(true);
+}
+
+void SubaddressAccount::refresh() const
+{
+ m_subaddressAccountImpl->refresh();
+ getAll(true);
+}
+
+quint64 SubaddressAccount::count() const
+{
+ return m_rows.size();
+}
diff --git a/src/libwalletqt/SubaddressAccount.h b/src/libwalletqt/SubaddressAccount.h
new file mode 100644
index 00000000..ee40c22e
--- /dev/null
+++ b/src/libwalletqt/SubaddressAccount.h
@@ -0,0 +1,33 @@
+#ifndef SUBADDRESSACCOUNT_H
+#define SUBADDRESSACCOUNT_H
+
+#include <wallet/api/wallet2_api.h>
+#include <QObject>
+#include <QList>
+#include <QDateTime>
+
+class SubaddressAccount : public QObject
+{
+ Q_OBJECT
+public:
+ Q_INVOKABLE QList<Monero::SubaddressAccountRow*> getAll(bool update = false) const;
+ Q_INVOKABLE Monero::SubaddressAccountRow * getRow(int index) const;
+ Q_INVOKABLE void addRow(const QString &label) const;
+ Q_INVOKABLE void setLabel(quint32 accountIndex, const QString &label) const;
+ Q_INVOKABLE void refresh() const;
+ quint64 count() const;
+
+signals:
+ void refreshStarted() const;
+ void refreshFinished() const;
+
+public slots:
+
+private:
+ explicit SubaddressAccount(Monero::SubaddressAccount * subaddressAccountImpl, QObject *parent);
+ friend class Wallet;
+ Monero::SubaddressAccount * m_subaddressAccountImpl;
+ mutable QList<Monero::SubaddressAccountRow*> m_rows;
+};
+
+#endif // SUBADDRESSACCOUNT_H
diff --git a/src/libwalletqt/Wallet.cpp b/src/libwalletqt/Wallet.cpp
index 85761e0b..e488b635 100644
--- a/src/libwalletqt/Wallet.cpp
+++ b/src/libwalletqt/Wallet.cpp
@@ -4,10 +4,12 @@
#include "TransactionHistory.h"
#include "AddressBook.h"
#include "Subaddress.h"
+#include "SubaddressAccount.h"
#include "model/TransactionHistoryModel.h"
#include "model/TransactionHistorySortFilterModel.h"
#include "model/AddressBookModel.h"
#include "model/SubaddressModel.h"
+#include "model/SubaddressAccountModel.h"
#include "wallet/api/wallet2_api.h"
#include <QFile>
@@ -357,6 +359,7 @@ bool Wallet::refresh()
bool result = m_walletImpl->refresh();
m_history->refresh(currentSubaddressAccount());
m_subaddress->refresh(currentSubaddressAccount());
+ m_subaddressAccount->getAll(true);
if (result)
emit updated();
return result;
@@ -543,6 +546,20 @@ SubaddressModel *Wallet::subaddressModel()
return m_subaddressModel;
}
+SubaddressAccount *Wallet::subaddressAccount() const
+{
+ return m_subaddressAccount;
+}
+
+SubaddressAccountModel *Wallet::subaddressAccountModel() const
+{
+ if (!m_subaddressAccountModel) {
+ Wallet * w = const_cast<Wallet*>(this);
+ m_subaddressAccountModel = new SubaddressAccountModel(w,m_subaddressAccount);
+ }
+ return m_subaddressAccountModel;
+}
+
QString Wallet::generatePaymentId() const
{
return QString::fromStdString(Monero::Wallet::genPaymentId());
@@ -858,6 +875,8 @@ Wallet::Wallet(Monero::Wallet *w, QObject *parent)
, m_addressBookModel(nullptr)
, m_subaddress(nullptr)
, m_subaddressModel(nullptr)
+ , m_subaddressAccount(nullptr)
+ , m_subaddressAccountModel(nullptr)
, m_daemonBlockChainHeight(0)
, m_daemonBlockChainHeightTtl(DAEMON_BLOCKCHAIN_HEIGHT_CACHE_TTL_SECONDS)
, m_daemonBlockChainTargetHeight(0)
@@ -868,6 +887,7 @@ Wallet::Wallet(Monero::Wallet *w, QObject *parent)
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_subaddressAccount = new SubaddressAccount(m_walletImpl->subaddressAccount(), this);
m_walletListener = new WalletListenerImpl(this);
m_walletImpl->setListener(m_walletListener);
m_connectionStatus = Wallet::ConnectionStatus_Disconnected;
@@ -893,6 +913,8 @@ Wallet::~Wallet()
m_addressBook = NULL;
delete m_subaddress;
m_subaddress = NULL;
+ delete m_subaddressAccount;
+ m_subaddressAccount = NULL;
//Monero::WalletManagerFactory::getWalletManager()->closeWallet(m_walletImpl);
if(status() == Status_Critical)
qDebug("Not storing wallet cache");
diff --git a/src/libwalletqt/Wallet.h b/src/libwalletqt/Wallet.h
index 8197e567..e3357528 100644
--- a/src/libwalletqt/Wallet.h
+++ b/src/libwalletqt/Wallet.h
@@ -24,6 +24,8 @@ class AddressBook;
class AddressBookModel;
class Subaddress;
class SubaddressModel;
+class SubaddressAccount;
+class SubaddressAccountModel;
class Wallet : public QObject
{
@@ -44,6 +46,8 @@ class Wallet : public QObject
Q_PROPERTY(AddressBook * addressBook READ addressBook)
Q_PROPERTY(SubaddressModel * subaddressModel READ subaddressModel)
Q_PROPERTY(Subaddress * subaddress READ subaddress)
+ Q_PROPERTY(SubaddressAccountModel * subaddressAccountModel READ subaddressAccountModel)
+ Q_PROPERTY(SubaddressAccount * subaddressAccount READ subaddressAccount)
Q_PROPERTY(bool viewOnly READ viewOnly)
Q_PROPERTY(QString secretViewKey READ getSecretViewKey)
Q_PROPERTY(QString publicViewKey READ getPublicViewKey)
@@ -234,6 +238,12 @@ public:
//! returns subadress model
SubaddressModel *subaddressModel();
+ //! returns subaddress account
+ SubaddressAccount *subaddressAccount() const;
+
+ //! returns subadress account model
+ SubaddressAccountModel *subaddressAccountModel() const;
+
//! generate payment id
Q_INVOKABLE QString generatePaymentId() const;
@@ -348,6 +358,8 @@ private:
mutable AddressBookModel * m_addressBookModel;
Subaddress * m_subaddress;
mutable SubaddressModel * m_subaddressModel;
+ SubaddressAccount * m_subaddressAccount;
+ mutable SubaddressAccountModel * m_subaddressAccountModel;
QMutex m_connectionStatusMutex;
bool m_connectionStatusRunning;
QString m_daemonUsername;
diff --git a/src/model/SubaddressAccountModel.cpp b/src/model/SubaddressAccountModel.cpp
new file mode 100644
index 00000000..fa2ce0b2
--- /dev/null
+++ b/src/model/SubaddressAccountModel.cpp
@@ -0,0 +1,66 @@
+#include "SubaddressAccountModel.h"
+#include "SubaddressAccount.h"
+#include <QDebug>
+#include <QHash>
+#include <wallet/api/wallet2_api.h>
+
+SubaddressAccountModel::SubaddressAccountModel(QObject *parent, SubaddressAccount *subaddressAccount)
+ : QAbstractListModel(parent), m_subaddressAccount(subaddressAccount)
+{
+ qDebug(__FUNCTION__);
+ connect(m_subaddressAccount,SIGNAL(refreshStarted()),this,SLOT(startReset()));
+ connect(m_subaddressAccount,SIGNAL(refreshFinished()),this,SLOT(endReset()));
+}
+
+void SubaddressAccountModel::startReset(){
+ qDebug("SubaddressAccountModel::startReset");
+ beginResetModel();
+}
+void SubaddressAccountModel::endReset(){
+ qDebug("SubaddressAccountModel::endReset");
+ endResetModel();
+}
+
+int SubaddressAccountModel::rowCount(const QModelIndex &parent) const
+{
+ return m_subaddressAccount->count();
+}
+
+QVariant SubaddressAccountModel::data(const QModelIndex &index, int role) const
+{
+ if (!index.isValid() || index.row() < 0 || (unsigned)index.row() >= m_subaddressAccount->count())
+ return {};
+
+ Monero::SubaddressAccountRow * sr = m_subaddressAccount->getRow(index.row());
+
+ QVariant result = "";
+ switch (role) {
+ case SubaddressAccountAddressRole:
+ result = QString::fromStdString(sr->getAddress());
+ break;
+ case SubaddressAccountLabelRole:
+ result = QString::fromStdString(sr->getLabel());
+ break;
+ case SubaddressAccountBalanceRole:
+ result = QString::fromStdString(sr->getBalance());
+ break;
+ case SubaddressAccountUnlockedBalanceRole:
+ result = QString::fromStdString(sr->getUnlockedBalance());
+ break;
+ }
+
+ return result;
+}
+
+QHash<int, QByteArray> SubaddressAccountModel::roleNames() const
+{
+ static QHash<int, QByteArray> roleNames;
+ if (roleNames.empty())
+ {
+ roleNames.insert(SubaddressAccountAddressRole, "address");
+ roleNames.insert(SubaddressAccountLabelRole, "label");
+ roleNames.insert(SubaddressAccountBalanceRole, "balance");
+ roleNames.insert(SubaddressAccountUnlockedBalanceRole, "unlockedBalance");
+ }
+ return roleNames;
+}
diff --git a/src/model/SubaddressAccountModel.h b/src/model/SubaddressAccountModel.h
new file mode 100644
index 00000000..e78a3f84
--- /dev/null
+++ b/src/model/SubaddressAccountModel.h
@@ -0,0 +1,36 @@
+#ifndef SUBADDRESSACCOUNTMODEL_H
+#define SUBADDRESSACCOUNTMODEL_H
+
+#include <QAbstractListModel>
+
+class SubaddressAccount;
+
+class SubaddressAccountModel : public QAbstractListModel
+{
+ Q_OBJECT
+
+public:
+ enum SubaddressAccountRowRole {
+ SubaddressAccountRole = Qt::UserRole + 1, // for the SubaddressAccountRow object;
+ SubaddressAccountAddressRole,
+ SubaddressAccountLabelRole,
+ SubaddressAccountBalanceRole,
+ SubaddressAccountUnlockedBalanceRole,
+ };
+ Q_ENUM(SubaddressAccountRowRole)
+
+ SubaddressAccountModel(QObject *parent, SubaddressAccount *subaddressAccount);
+
+ 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:
+ SubaddressAccount *m_subaddressAccount;
+};
+
+#endif // SUBADDRESSACCOUNTMODEL_H