diff --git a/components/NewPasswordDialog.qml b/components/NewPasswordDialog.qml
new file mode 100644
index 00000000..414a225d
--- /dev/null
+++ b/components/NewPasswordDialog.qml
@@ -0,0 +1,254 @@
+// Copyright (c) 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.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 password: passwordInput1.text
+
+ // same signals as Dialog has
+ signal accepted()
+ signal rejected()
+ signal closeCallback()
+
+ function open() {
+ leftPanel.enabled = false
+ middlePanel.enabled = false
+ titleBar.enabled = false
+ show();
+ root.visible = true;
+ passwordInput1.text = "";
+ passwordInput2.text = "";
+ passwordInput1.focus = true
+ }
+
+ function close() {
+ leftPanel.enabled = true
+ middlePanel.enabled = true
+ titleBar.enabled = true
+ root.visible = false;
+ closeCallback();
+ }
+
+ // TODO: implement without hardcoding sizes
+ width: 480
+ height: 360
+
+ // Make window draggable
+ MouseArea {
+ anchors.fill: parent
+ property point lastMousePos: Qt.point(0, 0)
+ onPressed: { lastMousePos = Qt.point(mouseX, mouseY); }
+ onMouseXChanged: root.x += (mouseX - lastMousePos.x)
+ onMouseYChanged: root.y += (mouseY - lastMousePos.y)
+ }
+
+ ColumnLayout {
+ z: bg.z + 1
+ id: mainLayout
+ spacing: 10
+ anchors { fill: parent; margins: 35 * scaleRatio }
+
+ ColumnLayout {
+ id: column
+ //anchors {fill: parent; margins: 16 }
+ Layout.alignment: Qt.AlignHCenter
+
+ Label {
+ text: qsTr("Please enter new password")
+ Layout.alignment: Qt.AlignHCenter
+ Layout.columnSpan: 2
+ Layout.fillWidth: true
+ horizontalAlignment: Text.AlignHCenter
+ font.pixelSize: 18 * scaleRatio
+ font.family: "Arial"
+ color: "#555555"
+ }
+
+ TextField {
+ id : passwordInput1
+ Layout.fillWidth: true
+ Layout.alignment: Qt.AlignHCenter
+ Layout.maximumWidth: 400 * scaleRatio
+ horizontalAlignment: TextInput.AlignHCenter
+ verticalAlignment: TextInput.AlignVCenter
+ font.family: "Arial"
+ font.pixelSize: 32 * scaleRatio
+ echoMode: TextInput.Password
+ KeyNavigation.tab: passwordInput2
+
+ style: TextFieldStyle {
+ renderType: Text.NativeRendering
+ textColor: "#35B05A"
+ passwordCharacter: "•"
+ // no background
+ background: Rectangle {
+ radius: 0
+ border.width: 0
+ }
+ }
+ Keys.onEscapePressed: {
+ root.close()
+ root.rejected()
+ }
+ }
+
+ // underline
+ Rectangle {
+ height: 1
+ color: "#DBDBDB"
+ Layout.fillWidth: true
+ Layout.alignment: Qt.AlignHCenter
+ anchors.bottomMargin: 3
+ Layout.maximumWidth: passwordInput1.width
+ }
+ // padding
+ Rectangle {
+ Layout.fillWidth: true
+ Layout.alignment: Qt.AlignHCenter
+ height: 10
+ opacity: 0
+ color: "black"
+ }
+
+ Label {
+ text: qsTr("Please confirm new password")
+ Layout.alignment: Qt.AlignHCenter
+ Layout.columnSpan: 2
+ Layout.fillWidth: true
+ horizontalAlignment: Text.AlignHCenter
+ font.pixelSize: 18 * scaleRatio
+ font.family: "Arial"
+ color: "#555555"
+ }
+
+ TextField {
+ id : passwordInput2
+ Layout.fillWidth: true
+ Layout.alignment: Qt.AlignHCenter
+ Layout.maximumWidth: 400 * scaleRatio
+ 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: {
+ if (passwordInput1.text === passwordInput2.text) {
+ 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
+ Layout.maximumWidth: passwordInput1.width
+ }
+ // padding
+ Rectangle {
+ Layout.fillWidth: true
+ Layout.alignment: Qt.AlignHCenter
+ height: 10
+ opacity: 0
+ color: "black"
+ }
+ }
+ // Ok/Cancel buttons
+ RowLayout {
+ id: buttons
+ spacing: 60 * scaleRatio
+ Layout.alignment: Qt.AlignHCenter
+
+ MoneroComponents.StandardButton {
+ id: cancelButton
+ shadowReleasedColor: "#FF4304"
+ shadowPressedColor: "#B32D00"
+ releasedColor: "#FF6C3C"
+ pressedColor: "#FF4304"
+ text: qsTr("Cancel") + translationManager.emptyString
+ KeyNavigation.tab: passwordInput1
+ onClicked: {
+ root.close()
+ root.rejected()
+ }
+ }
+ MoneroComponents.StandardButton {
+ id: okButton
+ shadowReleasedColor: "#FF4304"
+ shadowPressedColor: "#B32D00"
+ releasedColor: "#FF6C3C"
+ pressedColor: "#FF4304"
+ text: qsTr("Continue")
+ KeyNavigation.tab: cancelButton
+ enabled: passwordInput1.text === passwordInput2.text
+ onClicked: {
+ root.close()
+ root.accepted()
+ }
+ }
+ }
+ }
+}
diff --git a/main.qml b/main.qml
index 944eefa2..387d1b5d 100644
--- a/main.qml
+++ b/main.qml
@@ -53,7 +53,7 @@ ApplicationWindow {
property var currentWallet;
property var transaction;
property var transactionDescription;
- property alias password : passwordDialog.password
+ property var walletPassword
property bool isNewWallet: false
property int restoreHeight:0
property bool daemonSynced: false
@@ -166,7 +166,7 @@ ApplicationWindow {
persistentSettings.restore_height = 0
restoreHeight = 0;
persistentSettings.is_recovering = false
- appWindow.password = ""
+ walletPassword = ""
fileDialog.open();
}
@@ -226,7 +226,7 @@ ApplicationWindow {
wallet_path = moneroAccountsDir + wallet_path;
// console.log("opening wallet at: ", wallet_path, "with password: ", appWindow.password);
console.log("opening wallet at: ", wallet_path, ", testnet: ", persistentSettings.testnet);
- walletManager.openWalletAsync(wallet_path, appWindow.password,
+ walletManager.openWalletAsync(wallet_path, walletPassword,
persistentSettings.testnet);
}
@@ -338,25 +338,25 @@ ApplicationWindow {
walletName = usefulName(wallet.path)
console.log(">>> wallet opened: " + wallet)
if (wallet.status !== Wallet.Status_Ok) {
- if (appWindow.password === '') {
- console.error("Error opening wallet with empty password: ", wallet.errorString);
- console.log("closing wallet async : " + wallet.address)
- closeWallet();
- // try to open wallet with password;
- passwordDialog.open(walletName);
- } else {
- // opening with password but password doesn't match
- console.error("Error opening wallet with password: ", wallet.errorString);
-
- informationPopup.title = qsTr("Error") + translationManager.emptyString;
- informationPopup.text = qsTr("Couldn't open wallet: ") + wallet.errorString;
- informationPopup.icon = StandardIcon.Critical
- console.log("closing wallet async : " + wallet.address)
- closeWallet();
- informationPopup.open()
- informationPopup.onCloseCallback = function() {
- passwordDialog.open(walletName)
- }
+ passwordDialog.onAcceptedCallback = function() {
+ walletPassword = passwordDialog.password;
+ appWindow.initialize();
+ }
+ passwordDialog.onRejectedCallback = function() {
+ walletPassword = "";
+ //appWindow.enableUI(false)
+ rootItem.state = "wizard";
+ }
+ // opening with password but password doesn't match
+ console.error("Error opening wallet with password: ", wallet.errorString);
+ informationPopup.title = qsTr("Error") + translationManager.emptyString;
+ informationPopup.text = qsTr("Couldn't open wallet: ") + wallet.errorString;
+ informationPopup.icon = StandardIcon.Critical
+ console.log("closing wallet async : " + wallet.address)
+ closeWallet();
+ informationPopup.open()
+ informationPopup.onCloseCallback = function() {
+ passwordDialog.open(walletName)
}
return;
}
@@ -951,7 +951,14 @@ ApplicationWindow {
rootItem.state = "wizard"
} else {
rootItem.state = "normal"
+ passwordDialog.onAcceptedCallback = function() {
+ walletPassword = passwordDialog.password;
initialize(persistentSettings);
+ }
+ passwordDialog.onRejectedCallback = function() {
+ rootItem.state = "wizard"
+ }
+ passwordDialog.open(usefulName(walletPath()))
}
checkUpdates();
@@ -1013,8 +1020,8 @@ ApplicationWindow {
id: transactionConfirmationPopup
onAccepted: {
close();
- transactionConfirmationPasswordDialog.onAcceptedCallback = function() {
- if(appWindow.password === transactionConfirmationPasswordDialog.password){
+ passwordDialog.onAcceptedCallback = function() {
+ if(walletPassword === passwordDialog.password){
// Save transaction to file if view only wallet
if(viewOnly) {
saveTxDialog.open();
@@ -1026,15 +1033,12 @@ ApplicationWindow {
informationPopup.text = qsTr("Wrong password");
informationPopup.open()
informationPopup.onCloseCallback = function() {
- transactionConfirmationPasswordDialog.open()
+ passwordDialog.open()
}
}
- transactionConfirmationPasswordDialog.password = ""
}
- transactionConfirmationPasswordDialog.onRejectedCallback = function() {
- transactionConfirmationPasswordDialog.password = ""
- }
- transactionConfirmationPasswordDialog.open()
+ passwordDialog.onRejectedCallback = null;
+ passwordDialog.open()
}
}
@@ -1072,7 +1076,15 @@ ApplicationWindow {
console.log(moneroAccountsDir)
console.log(fileDialog.fileUrl)
console.log(persistentSettings.wallet_path)
- initialize();
+ passwordDialog.onAcceptedCallback = function() {
+ walletPassword = passwordDialog.password;
+ initialize();
+ }
+ passwordDialog.onRejectedCallback = function() {
+ console.log("Canceled")
+ rootItem.state = "wizard";
+ }
+ passwordDialog.open(usefulName(walletPath()));
}
onRejected: {
console.log("Canceled")
@@ -1138,21 +1150,6 @@ ApplicationWindow {
visible: false
z: parent.z + 1
anchors.fill: parent
- onAccepted: {
- appWindow.initialize();
- }
- onRejected: {
- //appWindow.enableUI(false)
- rootItem.state = "wizard"
- }
-
- }
-
- PasswordDialog {
- id: transactionConfirmationPasswordDialog
- z: parent.z + 1
- visible:false
- anchors.fill: parent
property var onAcceptedCallback
property var onRejectedCallback
onAccepted: {
@@ -1165,34 +1162,26 @@ ApplicationWindow {
}
}
- PasswordDialog {
- id: settingsPasswordDialog
+ NewPasswordDialog {
+ id: newPasswordDialog
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"
-
+ if (currentWallet.setPassword(newPasswordDialog.password)) {
+ appWindow.walletPassword = newPasswordDialog.password;
+ informationPopup.title = qsTr("Information") + translationManager.emptyString;
+ informationPopup.text = qsTr("Password changed successfully") + translationManager.emptyString;
+ informationPopup.icon = StandardIcon.Information;
} else {
informationPopup.title = qsTr("Error") + translationManager.emptyString;
- informationPopup.text = qsTr("Wrong password");
- informationPopup.open()
- informationPopup.onCloseCallback = function() {
- settingsPasswordDialog.open()
- }
+ informationPopup.text = qsTr("Error: ") + currentWallet.errorString;
+ informationPopup.icon = StandardIcon.Critical;
}
-
- settingsPasswordDialog.password = ""
+ informationPopup.onCloseCallback = null;
+ informationPopup.open();
}
onRejected: {
- appWindow.showPageRequest("Settings");
}
}
@@ -1278,7 +1267,31 @@ ApplicationWindow {
onMiningClicked: { middlePanel.state = "Mining"; if(isMobile) hideMenu(); updateBalance(); }
onSignClicked: { middlePanel.state = "Sign"; if(isMobile) hideMenu(); updateBalance(); }
onSettingsClicked: { middlePanel.state = "Settings"; if(isMobile) hideMenu(); updateBalance(); }
- onKeysClicked: { settingsPasswordDialog.open(); if(isMobile) hideMenu(); updateBalance(); }
+ onKeysClicked: {
+ passwordDialog.onAcceptedCallback = function() {
+ if(walletPassword === passwordDialog.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() {
+ passwordDialog.open()
+ }
+ }
+ }
+ passwordDialog.onRejectedCallback = function() {
+ appWindow.showPageRequest("Settings");
+ }
+ passwordDialog.open();
+ if(isMobile) hideMenu();
+ updateBalance();
+ }
}
RightPanel {
diff --git a/pages/Settings.qml b/pages/Settings.qml
index a83b53ee..61844b4f 100644
--- a/pages/Settings.qml
+++ b/pages/Settings.qml
@@ -164,6 +164,32 @@ Rectangle {
}
}
}
+
+ StandardButton {
+ id: changePasswordButton
+ text: qsTr("Change password") + translationManager.emptyString
+ shadowReleasedColor: "#FF4304"
+ shadowPressedColor: "#B32D00"
+ releasedColor: "#FF6C3C"
+ pressedColor: "#FF4304"
+ onClicked: {
+ passwordDialog.onAcceptedCallback = function() {
+ if(appWindow.walletPassword === passwordDialog.password){
+ newPasswordDialog.open()
+ } else {
+ informationPopup.title = qsTr("Error") + translationManager.emptyString;
+ informationPopup.text = qsTr("Wrong password");
+ informationPopup.open()
+ informationPopup.onCloseCallback = function() {
+ changePasswordDialog.open()
+ }
+ passwordDialog.open()
+ }
+ }
+ passwordDialog.onRejectedCallback = null;
+ passwordDialog.open()
+ }
+ }
}
RowLayout {
diff --git a/qml.qrc b/qml.qrc
index 36d8213c..7ea33ba2 100644
--- a/qml.qrc
+++ b/qml.qrc
@@ -135,6 +135,7 @@
pages/TxKey.qml
components/IconButton.qml
components/PasswordDialog.qml
+ components/NewPasswordDialog.qml
components/ProcessingSplash.qml
components/ProgressBar.qml
components/StandardDialog.qml
diff --git a/wizard/WizardMain.qml b/wizard/WizardMain.qml
index d5c9eb11..f792b383 100644
--- a/wizard/WizardMain.qml
+++ b/wizard/WizardMain.qml
@@ -226,7 +226,7 @@ ColumnLayout {
m_wallet.setPassword(settings.wallet_password);
// Store password in session to be able to use password protected functions (e.g show seed)
- appWindow.password = settings.wallet_password
+ appWindow.walletPassword = settings.wallet_password
// saving wallet_filename;
settings['wallet_filename'] = new_wallet_filename;