From 603c1e7ee9a45d7d202e90bc473df27c721ad147 Mon Sep 17 00:00:00 2001 From: Jaquee Date: Mon, 7 Aug 2017 10:48:13 +0200 Subject: [PATCH] Add Keys page --- LeftPanel.qml | 28 +++++- MiddlePanel.qml | 36 ++------ main.qml | 32 +++++++ pages/Keys.qml | 213 +++++++++++++++++++++++++++++++++++++++++++++ pages/Settings.qml | 67 -------------- qml.qrc | 1 + 6 files changed, 277 insertions(+), 100 deletions(-) create mode 100644 pages/Keys.qml diff --git a/LeftPanel.qml b/LeftPanel.qml index 6f843fc7..8433d7f3 100644 --- a/LeftPanel.qml +++ b/LeftPanel.qml @@ -50,6 +50,7 @@ Rectangle { signal addressBookClicked() signal miningClicked() signal signClicked() + signal keysClicked() function selectItem(pos) { menuColumn.previousButton.checked = false @@ -483,10 +484,33 @@ Rectangle { color: "#505050" height: 1 } + // ------------- Sign/verify tab --------------- + MenuButton { + id: keysButton + anchors.left: parent.left + anchors.right: parent.right + text: qsTr("Seed & Keys") + translationManager.emptyString + symbol: qsTr("Y") + translationManager.emptyString + dotColor: "#FFD781" + under: settingsButton + onClicked: { + parent.previousButton.checked = false + parent.previousButton = keysButton + panel.keysClicked() + } + } + Rectangle { + visible: settingsButton.present + anchors.left: parent.left + anchors.right: parent.right + anchors.leftMargin: 16 + color: "#505050" + height: 1 + } - } + } // Column - } + } // Flickable NetworkStatusItem { id: networkStatus diff --git a/MiddlePanel.qml b/MiddlePanel.qml index 404a9d40..1ffd3132 100644 --- a/MiddlePanel.qml +++ b/MiddlePanel.qml @@ -58,6 +58,7 @@ Rectangle { property Settings settingsView: Settings { } property Mining miningView: Mining { } property AddressBook addressBookView: AddressBook { } + property Keys keysView: Keys { } signal paymentClicked(string address, string paymentId, string amount, int mixinCount, int priority, string description) @@ -93,33 +94,6 @@ Rectangle { transferView.sendTo(address, paymentId, description); } - - // XXX: just for memo, to be removed - // states: [ - // State { - // name: "Dashboard" - // PropertyChanges { target: loader; source: "pages/Dashboard.qml" } - // }, State { - // name: "History" - // PropertyChanges { target: loader; source: "pages/History.qml" } - // }, State { - // name: "Transfer" - // PropertyChanges { target: loader; source: "pages/Transfer.qml" } - // }, State { - // name: "Receive" - // PropertyChanges { target: loader; source: "pages/Receive.qml" } - // }, State { - // name: "AddressBook" - // PropertyChanges { target: loader; source: "pages/AddressBook.qml" } - // }, State { - // name: "Settings" - // PropertyChanges { target: loader; source: "pages/Settings.qml" } - // }, State { - // name: "Mining" - // PropertyChanges { target: loader; source: "pages/Mining.qml" } - // } - // ] - states: [ State { name: "Dashboard" @@ -157,6 +131,10 @@ Rectangle { name: "Mining" PropertyChanges { target: root; currentView: miningView } PropertyChanges { target: mainFlickable; contentHeight: minHeight } + }, State { + name: "Keys" + PropertyChanges { target: root; currentView: keysView } + PropertyChanges { target: mainFlickable; contentHeight: minHeight } } ] @@ -195,11 +173,7 @@ Rectangle { StackView { id: stackView initialItem: transferView - // anchors.topMargin: 30 - // Layout.fillWidth: true - // Layout.fillHeight: true anchors.fill:parent - // anchors.margins: 4 clip: true // otherwise animation will affect left panel delegate: StackViewDelegate { diff --git a/main.qml b/main.qml index bb7f9a5c..b72f21ff 100644 --- a/main.qml +++ b/main.qml @@ -988,6 +988,37 @@ ApplicationWindow { onAcceptedCallback(); } } + + PasswordDialog { + id: settingsPasswordDialog + z: parent.z + 1 + visible:false + anchors.fill: parent + onAccepted: { + if(appWindow.password === settingsPasswordDialog.password){ + if(currentWallet.seedLanguage == "") { + console.log("No seed language set. Using English as default"); + currentWallet.setSeedLanguage("English"); + } + + // Load keys page + middlePanel.state = "Keys" + + } else { + informationPopup.title = qsTr("Error") + translationManager.emptyString; + informationPopup.text = qsTr("Wrong password"); + informationPopup.open() + informationPopup.onCloseCallback = function() { + settingsPasswordDialog.open() + } + } + + settingsPasswordDialog.password = "" + } + onRejected: { + appWindow.showPageRequest("Settings"); + } + } DaemonManagerDialog { id: daemonManagerDialog @@ -1068,6 +1099,7 @@ ApplicationWindow { onMiningClicked: {middlePanel.state = "Mining"; if(isMobile) hideMenu()} onSignClicked: {middlePanel.state = "Sign"; if(isMobile) hideMenu()} onSettingsClicked: {middlePanel.state = "Settings"; if(isMobile) hideMenu()} + onKeysClicked: {settingsPasswordDialog.open(); if(isMobile) hideMenu()} } RightPanel { diff --git a/pages/Keys.qml b/pages/Keys.qml new file mode 100644 index 00000000..6c78b7a3 --- /dev/null +++ b/pages/Keys.qml @@ -0,0 +1,213 @@ +// Copyright (c) 2014-2017, 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.Controls.Styles 1.4 +import QtQuick.Layouts 1.1 +import QtQuick.Dialogs 1.2 +import "../version.js" as Version + + +import "../components" +import moneroComponents.Clipboard 1.0 + +Rectangle { + property bool viewOnly: false + id: page + + color: "#F0EEEE" + + Clipboard { id: clipboard } + + ColumnLayout { + id: mainLayout + anchors.margins: 17 * scaleRatio + anchors.left: parent.left + anchors.top: parent.top + anchors.right: parent.right + spacing: 20 * scaleRatio + Layout.fillWidth: true + + //! Manage wallet + ColumnLayout { + Layout.fillWidth: true + Label { + Layout.fillWidth: true + text: qsTr("Mnemonic seed") + translationManager.emptyString + } + Rectangle { + Layout.fillWidth: true + height: 1 + color: "#DEDEDE" + } + TextEdit { + id: seedText + wrapMode: TextEdit.Wrap + Layout.fillWidth: true; + font.pixelSize: 14 * scaleRatio + readOnly: true + MouseArea { + anchors.fill: parent + onClicked: { + parent.selectAll() + parent.copy() + parent.deselect() + console.log("copied to clipboard"); + } + } + } + } + + ColumnLayout { + Layout.fillWidth: true + Label { + Layout.fillWidth: true + text: qsTr("Keys") + translationManager.emptyString + } + Rectangle { + Layout.fillWidth: true + height: 1 + color: "#DEDEDE" + } + TextEdit { + id: keysText + wrapMode: TextEdit.Wrap + Layout.fillWidth: true; + font.pixelSize: 14 * scaleRatio + textFormat: TextEdit.RichText + readOnly: true + MouseArea { + anchors.fill: parent + onClicked: { + parent.selectAll() + parent.copy() + parent.deselect() + console.log("copied to clipboard"); + } + } + } + } + + ColumnLayout { + Layout.fillWidth: true + Label { + Layout.fillWidth: true + text: qsTr("Export wallet") + translationManager.emptyString + } + Rectangle { + Layout.fillWidth: true + height: 1 + color: "#DEDEDE" + } + + + RowLayout { + StandardButton { + enabled: !fullWalletQRCode.visible + id: showFullQr + text: qsTr("Spendable Wallet") + translationManager.emptyString + onClicked: { + viewOnlyQRCode.visible = false + } + } + StandardButton { + enabled: fullWalletQRCode.visible + id: showViewOnlyQr + text: qsTr("View Only Wallet") + translationManager.emptyString + onClicked: { + viewOnlyQRCode.visible = true + } + } + Layout.bottomMargin: 30 * scaleRatio + } + + + Image { + visible: !viewOnlyQRCode.visible + id: fullWalletQRCode + Layout.fillWidth: true + Layout.minimumHeight: 180 * scaleRatio + smooth: false + fillMode: Image.PreserveAspectFit + } + + Image { + visible: false + id: viewOnlyQRCode + Layout.fillWidth: true + Layout.minimumHeight: 180 * scaleRatio + smooth: false + fillMode: Image.PreserveAspectFit + } + + Text { + Layout.fillWidth: true + font.bold: true + font.pixelSize: 16 * scaleRatio + text: (viewOnlyQRCode.visible) ? qsTr("View Only Wallet") + translationManager.emptyString : qsTr("Spendable Wallet") + translationManager.emptyString + horizontalAlignment: Text.AlignHCenter + } + } + } + + // fires on every page load + function onPageCompleted() { + console.log("keys page loaded"); + + keysText.text = "" + qsTr("Secret view key") + ": " + currentWallet.secretViewKey + keysText.text += "

" + qsTr("Public view key") + ": " + currentWallet.publicViewKey + keysText.text += (!currentWallet.viewOnly) ? "

" + qsTr("Secret spend key") + ": " + currentWallet.secretSpendKey : "" + keysText.text += "

" + qsTr("Public spend key") + ": " + currentWallet.publicSpendKey + + seedText.text = currentWallet.seed + + if(typeof currentWallet != "undefined") { + viewOnlyQRCode.source = "image://qrcode/monero:" + currentWallet.address+"?secret_view_key="+currentWallet.secretViewKey+"&restore_height="+currentWallet.restoreHeight + fullWalletQRCode.source = viewOnlyQRCode.source +"&secret_spend_key="+currentWallet.secretSpendKey + + if(currentWallet.viewOnly) { + viewOnlyQRCode.visible = true + showFullQr.visible = false + showViewOnlyQr.visible = false + seedText.text = qsTr("(View Only Wallet - No mnemonic seed available)") + translationManager.emptyString + } + } + } + + // fires only once + Component.onCompleted: { + + } + +} + + + + + diff --git a/pages/Settings.qml b/pages/Settings.qml index 61e1cd16..015878d8 100644 --- a/pages/Settings.qml +++ b/pages/Settings.qml @@ -111,18 +111,6 @@ Rectangle { } } - StandardButton { - id: showSeedButton - shadowReleasedColor: "#FF4304" - shadowPressedColor: "#B32D00" - releasedColor: "#FF6C3C" - pressedColor: "#FF4304" - text: qsTr("Show seed & keys") + translationManager.emptyString - onClicked: { - settingsPasswordDialog.open(); - } - } - /* Rescan cache - Disabled until we know it's needed StandardButton { @@ -588,61 +576,6 @@ Rectangle { } } - PasswordDialog { - id: settingsPasswordDialog - - onAccepted: { - if(appWindow.password === settingsPasswordDialog.password){ - if(currentWallet.seedLanguage == "") { - console.log("No seed language set. Using English as default"); - currentWallet.setSeedLanguage("English"); - } - - seedPopup.title = qsTr("Wallet seed & keys") + translationManager.emptyString; - seedPopup.text = "Wallet Mnemonic seed
" + currentWallet.seed - + "

" + qsTr("Secret view key") + ": " + currentWallet.secretViewKey - + "
" + qsTr("Public view key") + ": " + currentWallet.publicViewKey - + "
" + qsTr("Secret spend key") + ": " + currentWallet.secretSpendKey - + "
" + qsTr("Public spend key") + ": " + currentWallet.publicSpendKey - seedPopup.open() - seedPopup.width = 600 - seedPopup.height = 300 - seedPopup.onCloseCallback = function() { - seedPopup.text = "" - } - - } else { - informationPopup.title = qsTr("Error") + translationManager.emptyString; - informationPopup.text = qsTr("Wrong password"); - informationPopup.open() - informationPopup.onCloseCallback = function() { - settingsPasswordDialog.open() - } - } - - settingsPasswordDialog.password = "" - } - onRejected: { - - } - - } - - StandardDialog { - id: seedPopup - cancelVisible: false - okVisible: true - width:600 - height:400 - - property var onCloseCallback - onAccepted: { - if (onCloseCallback) { - onCloseCallback() - } - } - } - // Choose blockchain folder FileDialog { id: blockchainFileDialog diff --git a/qml.qrc b/qml.qrc index 00468ad3..a8ba7c87 100644 --- a/qml.qrc +++ b/qml.qrc @@ -146,5 +146,6 @@ components/TextBlock.qml wizard/WizardDaemonSettings.qml components/RemoteNodeEdit.qml + pages/Keys.qml