diff --git a/pages/Settings.qml b/pages/Settings.qml
index f735badf..4d8a4a49 100644
--- a/pages/Settings.qml
+++ b/pages/Settings.qml
@@ -39,51 +39,26 @@ import moneroComponents.Clipboard 1.0
Rectangle {
property var daemonAddress
+ property bool viewOnly: false
color: "#F0EEEE"
Clipboard { id: clipboard }
function initSettings() {
+ //runs on every page load
-
- // Mnemonic seed settings
- memoTextInput.text = qsTr("Click button to show seed") + translationManager.emptyString
- showSeedButton.visible = true
+ // Mnemonic seed setting
+ memoTextInput.text = (viewOnly)? qsTr("View only wallets doesn't have a mnemonic seed") : qsTr("Click button to show seed") + translationManager.emptyString
+ showSeedButton.enabled = !viewOnly
// Daemon settings
-
daemonAddress = persistentSettings.daemon_address.split(":");
console.log("address: " + persistentSettings.daemon_address)
// try connecting to daemon
}
- PasswordDialog {
- id: settingsPasswordDialog
-
- onAccepted: {
- if(appWindow.password === settingsPasswordDialog.password){
- memoTextInput.text = currentWallet.seed
- showSeedButton.visible = false
- } else {
- informationPopup.title = qsTr("Error") + translationManager.emptyString;
- informationPopup.text = qsTr("Wrong password");
- informationPopup.open()
- informationPopup.onCloseCallback = function() {
- settingsPasswordDialog.open()
- }
- }
-
- settingsPasswordDialog.password = ""
- }
- onRejected: {
-
- }
-
- }
-
-
ColumnLayout {
id: mainLayout
anchors.margins: 40
@@ -92,17 +67,59 @@ Rectangle {
anchors.right: parent.right
spacing: 10
-
- Label {
- id: seedLabel
- color: "#4A4949"
- fontSize: 16
- text: qsTr("Mnemonic seed: ") + translationManager.emptyString
- Layout.preferredWidth: 100
- Layout.alignment: Qt.AlignLeft
+ //! Manage wallet
+ RowLayout {
+ Label {
+ id: manageWalletLabel
+ Layout.fillWidth: true
+ color: "#4A4949"
+ text: qsTr("Manage wallet") + translationManager.emptyString
+ fontSize: 16
+ Layout.topMargin: 10
+ }
}
+ Rectangle {
+ Layout.fillWidth: true
+ height: 1
+ color: "#DEDEDE"
+ }
+
+ RowLayout {
+ StandardButton {
+ id: closeWalletButton
+ width: 100
+ text: qsTr("Close wallet") + translationManager.emptyString
+ shadowReleasedColor: "#FF4304"
+ shadowPressedColor: "#B32D00"
+ releasedColor: "#FF6C3C"
+ pressedColor: "#FF4304"
+ visible: true
+ onClicked: {
+ console.log("closing wallet button clicked")
+ appWindow.showWizard();
+ }
+ }
+
+ StandardButton {
+ enabled: !viewOnly
+ id: createViewOnlyWalletButton
+ text: qsTr("Create view only wallet") + translationManager.emptyString
+ shadowReleasedColor: "#FF4304"
+ shadowPressedColor: "#B32D00"
+ releasedColor: "#FF6C3C"
+ pressedColor: "#FF4304"
+ visible: true
+ onClicked: {
+ wizard.openCreateViewOnlyWalletPage();
+ }
+ }
+
+ }
+
+ //! show seed
TextArea {
+ enabled: !viewOnly
id: memoTextInput
textMargin: 6
wrapMode: TextEdit.WordWrap
@@ -113,7 +130,7 @@ Rectangle {
Layout.preferredHeight: 100
Layout.alignment: Qt.AlignHCenter
- text: qsTr("Click button to show seed") + translationManager.emptyString
+ text: (viewOnly)? qsTr("View only wallets doesn't have a mnemonic seed") : qsTr("Click button to show seed") + translationManager.emptyString
style: TextAreaStyle {
backgroundColor: "#FFFFFF"
@@ -137,7 +154,9 @@ Rectangle {
}
}
+
RowLayout {
+ enabled: !viewOnly
Layout.fillWidth: true
Text {
id: wordsTipText
@@ -151,37 +170,99 @@ Rectangle {
}
StandardButton {
-
id: showSeedButton
-
- fontSize: 14
shadowReleasedColor: "#FF4304"
shadowPressedColor: "#B32D00"
releasedColor: "#FF6C3C"
pressedColor: "#FF4304"
text: qsTr("Show seed")
Layout.alignment: Qt.AlignRight
- Layout.preferredWidth: 100
onClicked: {
settingsPasswordDialog.open();
}
}
}
-
-
-
+ //! Manage daemon
+ RowLayout {
+ Label {
+ id: manageDaemonLabel
+ color: "#4A4949"
+ text: qsTr("Manage daemon") + translationManager.emptyString
+ fontSize: 16
+ anchors.topMargin: 30
+ Layout.topMargin: 30
+ }
+ }
Rectangle {
Layout.fillWidth: true
height: 1
color: "#DEDEDE"
}
+ RowLayout {
+ StandardButton {
+ visible: true
+ enabled: !appWindow.daemonRunning
+ id: startDaemonButton
+ text: qsTr("Start daemon") + translationManager.emptyString
+ shadowReleasedColor: "#FF4304"
+ shadowPressedColor: "#B32D00"
+ releasedColor: "#FF6C3C"
+ pressedColor: "#FF4304"
+ onClicked: {
+ appWindow.startDaemon(daemonFlags.text)
+ }
+ }
+
+ StandardButton {
+ visible: true
+ enabled: appWindow.daemonRunning
+ id: stopDaemonButton
+ text: qsTr("Stop daemon") + translationManager.emptyString
+ shadowReleasedColor: "#FF4304"
+ shadowPressedColor: "#B32D00"
+ releasedColor: "#FF6C3C"
+ pressedColor: "#FF4304"
+ onClicked: {
+ appWindow.stopDaemon()
+ }
+ }
+
+ StandardButton {
+ visible: true
+ id: daemonConsolePopupButton
+ text: qsTr("Show log") + translationManager.emptyString
+ shadowReleasedColor: "#FF4304"
+ shadowPressedColor: "#B32D00"
+ releasedColor: "#FF6C3C"
+ pressedColor: "#FF4304"
+ onClicked: {
+ daemonConsolePopup.open();
+ }
+ }
+ }
+
+ RowLayout {
+ id: daemonFlagsRow
+ Label {
+ id: daemonFlagsLabel
+ color: "#4A4949"
+ text: qsTr("Daemon startup flags") + translationManager.emptyString
+ fontSize: 16
+ }
+ LineEdit {
+ id: daemonFlags
+ Layout.preferredWidth: 200
+ Layout.fillWidth: true
+ text: appWindow.persistentSettings.daemonFlags;
+ placeholderText: qsTr("(optional)") + translationManager.emptyString
+ }
+ }
+
RowLayout {
id: daemonAddrRow
Layout.fillWidth: true
- Layout.preferredHeight: 40
- Layout.topMargin: 40
spacing: 10
Label {
@@ -213,12 +294,8 @@ Rectangle {
StandardButton {
id: daemonAddrSave
-
Layout.fillWidth: false
-
Layout.leftMargin: 30
- Layout.minimumWidth: 100
- width: 60
text: qsTr("Save") + translationManager.emptyString
shadowReleasedColor: "#FF4304"
shadowPressedColor: "#B32D00"
@@ -238,120 +315,19 @@ Rectangle {
}
-
RowLayout {
Label {
- id: closeWalletLabel
-
- Layout.fillWidth: true
color: "#4A4949"
- text: qsTr("Manage wallet") + translationManager.emptyString
+ text: qsTr("Layout settings") + translationManager.emptyString
fontSize: 16
+ anchors.topMargin: 30
+ Layout.topMargin: 30
}
}
- RowLayout {
-
- Text {
- id: closeWalletTip
- font.family: "Arial"
- font.pointSize: 12
- color: "#4A4646"
- Layout.fillWidth: true
- wrapMode: Text.WordWrap
- text: qsTr("Close current wallet and open wizard")
- + translationManager.emptyString
- }
-
-
- StandardButton {
- id: closeWalletButton
-
-// Layout.leftMargin: 30
-// Layout.minimumWidth: 100
- width: 100
- text: qsTr("Close wallet") + translationManager.emptyString
- shadowReleasedColor: "#FF4304"
- shadowPressedColor: "#B32D00"
- releasedColor: "#FF6C3C"
- pressedColor: "#FF4304"
- visible: true
- onClicked: {
- console.log("closing wallet button clicked")
- appWindow.showWizard();
- }
- }
- }
-
- RowLayout {
- Label {
- id: manageDaemonLabel
- color: "#4A4949"
- text: qsTr("Manage daemon") + translationManager.emptyString
- fontSize: 16
- }
-
- StandardButton {
- visible: true
- enabled: !appWindow.daemonRunning
- id: startDaemonButton
- width: 110
- text: qsTr("Start daemon") + translationManager.emptyString
- shadowReleasedColor: "#FF4304"
- shadowPressedColor: "#B32D00"
- releasedColor: "#FF6C3C"
- pressedColor: "#FF4304"
- onClicked: {
- appWindow.startDaemon(daemonFlags.text)
- }
- }
-
- StandardButton {
- visible: true
- enabled: appWindow.daemonRunning
- id: stopDaemonButton
- width: 110
- text: qsTr("Stop daemon") + translationManager.emptyString
- shadowReleasedColor: "#FF4304"
- shadowPressedColor: "#B32D00"
- releasedColor: "#FF6C3C"
- pressedColor: "#FF4304"
- onClicked: {
- appWindow.stopDaemon()
- }
- }
-
- StandardButton {
- visible: true
- // enabled: appWindow.daemonRunning
- id: daemonConsolePopupButton
- width: 110
- text: qsTr("Show log") + translationManager.emptyString
- shadowReleasedColor: "#FF4304"
- shadowPressedColor: "#B32D00"
- releasedColor: "#FF6C3C"
- pressedColor: "#FF4304"
- onClicked: {
- daemonConsolePopup.open();
- }
- }
-
- }
-
- RowLayout {
- id: daemonFlagsRow
- Label {
- id: daemonFlagsLabel
- color: "#4A4949"
- text: qsTr("Daemon startup flags") + translationManager.emptyString
- fontSize: 16
- }
- LineEdit {
- id: daemonFlags
- Layout.preferredWidth: 200
- Layout.fillWidth: true
- text: appWindow.persistentSettings.daemonFlags;
- placeholderText: qsTr("(optional)") + translationManager.emptyString
- }
+ Rectangle {
+ Layout.fillWidth: true
+ height: 1
+ color: "#DEDEDE"
}
RowLayout {
@@ -386,6 +362,22 @@ Rectangle {
}
}
+ // Version
+ RowLayout {
+ Label {
+ color: "#4A4949"
+ text: qsTr("Version") + translationManager.emptyString
+ fontSize: 16
+ anchors.topMargin: 30
+ Layout.topMargin: 30
+ }
+ }
+ Rectangle {
+ Layout.fillWidth: true
+ height: 1
+ color: "#DEDEDE"
+ }
+
Label {
id: guiVersion
Layout.topMargin: 8
@@ -414,11 +406,35 @@ Rectangle {
}
}
+ PasswordDialog {
+ id: settingsPasswordDialog
+
+ onAccepted: {
+ if(appWindow.password === settingsPasswordDialog.password){
+ memoTextInput.text = currentWallet.seed
+ showSeedButton.enabled = false
+ } else {
+ informationPopup.title = qsTr("Error") + translationManager.emptyString;
+ informationPopup.text = qsTr("Wrong password");
+ informationPopup.open()
+ informationPopup.onCloseCallback = function() {
+ settingsPasswordDialog.open()
+ }
+ }
+
+ settingsPasswordDialog.password = ""
+ }
+ onRejected: {
+
+ }
+
+ }
// fires on every page load
function onPageCompleted() {
console.log("Settings page loaded");
initSettings();
+ viewOnly = currentWallet.viewOnly;
}
// fires only once
diff --git a/pages/Transfer.qml b/pages/Transfer.qml
index 5d04f457..70b7f3db 100644
--- a/pages/Transfer.qml
+++ b/pages/Transfer.qml
@@ -464,6 +464,11 @@ Rectangle {
return;
}
+ if (currentWallet.viewOnly) {
+ statusText.text = qsTr("Wallet is view only.")
+ return;
+ }
+
switch (currentWallet.connected) {
case Wallet.ConnectionStatus_Disconnected:
statusText.text = qsTr("Wallet is not connected to daemon.") + "
" + root.startLinkText
diff --git a/qml.qrc b/qml.qrc
index a952af0f..a4a76ce5 100644
--- a/qml.qrc
+++ b/qml.qrc
@@ -122,5 +122,7 @@
pages/Sign.qml
components/DaemonManagerDialog.qml
version.js
+ wizard/WizardPasswordUI.qml
+ wizard/WizardCreateViewOnlyWallet.qml
diff --git a/src/libwalletqt/Wallet.cpp b/src/libwalletqt/Wallet.cpp
index 47f4a06a..b39851dc 100644
--- a/src/libwalletqt/Wallet.cpp
+++ b/src/libwalletqt/Wallet.cpp
@@ -158,6 +158,15 @@ void Wallet::initAsync(const QString &daemonAddress, quint64 upperTransactionLim
m_walletImpl->initAsync(daemonAddress.toStdString(), upperTransactionLimit);
}
+//! create a view only wallet
+bool Wallet::createViewOnly(const QString &path, const QString &password) const
+{
+ // Create path
+ QDir d = QFileInfo(path).absoluteDir();
+ d.mkpath(d.absolutePath());
+ return m_walletImpl->createWatchOnly(path.toStdString(),password.toStdString(),m_walletImpl->getSeedLanguage());
+}
+
bool Wallet::connectToDaemon()
{
return m_walletImpl->connectToDaemon();
@@ -168,6 +177,11 @@ void Wallet::setTrustedDaemon(bool arg)
m_walletImpl->setTrustedDaemon(arg);
}
+bool Wallet::viewOnly() const
+{
+ return m_walletImpl->watchOnly();
+}
+
quint64 Wallet::balance() const
{
return m_walletImpl->balance();
diff --git a/src/libwalletqt/Wallet.h b/src/libwalletqt/Wallet.h
index 63d3b1a3..e4ff026b 100644
--- a/src/libwalletqt/Wallet.h
+++ b/src/libwalletqt/Wallet.h
@@ -36,7 +36,7 @@ class Wallet : public QObject
Q_PROPERTY(QString path READ path)
Q_PROPERTY(AddressBookModel * addressBookModel READ addressBookModel)
Q_PROPERTY(AddressBook * addressBook READ addressBook)
-
+ Q_PROPERTY(bool viewOnly READ viewOnly)
public:
@@ -98,6 +98,9 @@ public:
//! initializes wallet asynchronously
Q_INVOKABLE void initAsync(const QString &daemonAddress, quint64 upperTransactionLimit, bool isRecovering = false, quint64 restoreHeight = 0);
+ //! create a view only wallet
+ Q_INVOKABLE bool createViewOnly(const QString &path, const QString &password) const;
+
//! connects to daemon
Q_INVOKABLE bool connectToDaemon();
@@ -110,6 +113,9 @@ public:
//! returns unlocked balance
Q_INVOKABLE quint64 unlockedBalance() const;
+ //! returns if view only wallet
+ Q_INVOKABLE bool viewOnly() const;
+
//! returns current wallet's block height
//! (can be less than daemon's blockchain height when wallet sync in progress)
Q_INVOKABLE quint64 blockChainHeight() const;
diff --git a/wizard/WizardCreateViewOnlyWallet.qml b/wizard/WizardCreateViewOnlyWallet.qml
new file mode 100644
index 00000000..dc1b813e
--- /dev/null
+++ b/wizard/WizardCreateViewOnlyWallet.qml
@@ -0,0 +1,94 @@
+// Copyright (c) 2014-2015, 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 moneroComponents.WalletManager 1.0
+import QtQuick 2.2
+import "../components"
+import "utils.js" as Utils
+
+Item {
+
+ id: passwordPage
+ opacity: 0
+ visible: false
+
+ Behavior on opacity {
+ NumberAnimation { duration: 100; easing.type: Easing.InQuad }
+ }
+
+ onOpacityChanged: visible = opacity !== 0
+
+
+ function onPageOpened(settingsObject) {
+ wizard.nextButton.enabled = true
+ }
+
+ function onPageClosed(settingsObject) {
+ var walletFullPath = wizard.createWalletPath(uiItem.walletPath,uiItem.accountNameText);
+ settingsObject['view_only_wallet_path'] = walletFullPath
+ console.log("wallet path", walletFullPath)
+ return wizard.walletPathValid(walletFullPath);
+ }
+
+ Row {
+ id: dotsRow
+ anchors.top: parent.top
+ anchors.right: parent.right
+ anchors.topMargin: 85
+ spacing: 6
+
+ ListModel {
+ id: dotsModel
+ ListElement { dotColor: "#FFE00A" }
+ ListElement { dotColor: "#DBDBDB" }
+ }
+
+ Repeater {
+ model: dotsModel
+ delegate: Rectangle {
+ width: 12; height: 12
+ radius: 6
+ color: dotColor
+ }
+ }
+ }
+
+ WizardManageWalletUI {
+ id: uiItem
+ titleText: qsTr("Give your view only wallet a name") + translationManager.emptyString
+ wordsTextItem.visible: false
+ restoreHeightVisible:false
+ walletName: appWindow.walletName + "-viewonly"
+ progressDotsModel: dotsModel
+ }
+
+
+ Component.onCompleted: {
+ //parent.wizardRestarted.connect(onWizardRestarted)
+ }
+}
diff --git a/wizard/WizardMain.qml b/wizard/WizardMain.qml
index ec720026..124a5784 100644
--- a/wizard/WizardMain.qml
+++ b/wizard/WizardMain.qml
@@ -44,6 +44,7 @@ Rectangle {
// disable donation page
"create_wallet" : [welcomePage, optionsPage, createWalletPage, passwordPage, finishPage ],
"recovery_wallet" : [welcomePage, optionsPage, recoveryWalletPage, passwordPage, finishPage ],
+ "create_view_only_wallet" : [ createViewOnlyWalletPage, passwordPage ],
}
property string currentPath: "create_wallet"
@@ -89,15 +90,12 @@ Rectangle {
currentPage += step_value
pages[currentPage].opacity = 1;
- var nextButtonVisible = pages[currentPage] !== optionsPage;
+ var nextButtonVisible = pages[currentPage] !== optionsPage && currentPage < pages.length - 1;
nextButton.visible = nextButtonVisible;
if (typeof pages[currentPage].onPageOpened !== 'undefined') {
pages[currentPage].onPageOpened(settings,next)
}
-
-
-
}
}
@@ -130,6 +128,16 @@ Rectangle {
wizard.openWalletFromFileClicked();
}
+ function openCreateViewOnlyWalletPage(){
+ pages[currentPage].opacity = 0
+ currentPath = "create_view_only_wallet"
+ pages = paths[currentPath]
+ currentPage = pages.indexOf(createViewOnlyWalletPage)
+ createViewOnlyWalletPage.opacity = 1
+ nextButton.visible = true
+ rootItem.state = "wizard";
+ }
+
function createWalletPath(folder_path,account_name){
// Remove trailing slash - (default on windows and mac)
@@ -274,6 +282,16 @@ Rectangle {
anchors.rightMargin: 50
}
+ WizardCreateViewOnlyWallet {
+ id: createViewOnlyWalletPage
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+ anchors.right: nextButton.left
+ anchors.left: prevButton.right
+ anchors.leftMargin: 50
+ anchors.rightMargin: 50
+ }
+
WizardRecoveryWallet {
id: recoveryWalletPage
anchors.top: parent.top
@@ -356,4 +374,59 @@ Rectangle {
wizard.useMoneroClicked();
}
}
+
+ StandardButton {
+ id: createViewOnlyWalletButton
+ anchors.right: parent.right
+ anchors.bottom: parent.bottom
+ anchors.margins: 50
+ width: 110
+ text: qsTr("Create wallet") + translationManager.emptyString
+ shadowReleasedColor: "#FF4304"
+ shadowPressedColor: "#B32D00"
+ releasedColor: "#FF6C3C"
+ pressedColor: "#FF4304"
+ visible: currentPath === "create_view_only_wallet" && parent.paths[currentPath][currentPage] === passwordPage
+ enabled: passwordPage.passwordsMatch
+ onClicked: {
+ if (currentWallet.createViewOnly(settings['view_only_wallet_path'],passwordPage.password)) {
+ console.log("view only wallet created in ",settings['view_only_wallet_path']);
+ informationPopup.title = qsTr("Success") + translationManager.emptyString;
+ informationPopup.text = qsTr('The view only wallet has been created. You can open it by closing this current wallet, clicking the "Open wallet from file" option, and selecting the view wallet in: \n%1')
+ .arg(settings['view_only_wallet_path']);
+ informationPopup.open()
+ informationPopup.onCloseCallback = null
+ rootItem.state = "normal"
+ wizard.restart();
+
+ } else {
+ informationPopup.title = qsTr("Error") + translationManager.emptyString;
+ informationPopup.text = currentWallet.errorString;
+ informationPopup.open()
+ }
+
+ }
+ }
+
+ StandardButton {
+ id: abortViewOnlyButton
+ anchors.right: createViewOnlyWalletButton.left
+ anchors.bottom: parent.bottom
+ anchors.margins: 50
+ width: 110
+ text: qsTr("Abort") + translationManager.emptyString
+ shadowReleasedColor: "#FF4304"
+ shadowPressedColor: "#B32D00"
+ releasedColor: "#FF6C3C"
+ pressedColor: "#FF4304"
+ visible: currentPath === "create_view_only_wallet" && parent.paths[currentPath][currentPage] === passwordPage
+ onClicked: {
+ wizard.restart();
+ rootItem.state = "normal"
+ }
+ }
+
+
+
+
}
diff --git a/wizard/WizardManageWalletUI.qml b/wizard/WizardManageWalletUI.qml
index 4420de2d..d3bfb558 100644
--- a/wizard/WizardManageWalletUI.qml
+++ b/wizard/WizardManageWalletUI.qml
@@ -43,7 +43,8 @@ Item {
property alias wordsTextItem : memoTextItem
property alias restoreHeight : restoreHeightItem.text
property alias restoreHeightVisible: restoreHeightItem.visible
-
+ property alias walletName : accountName.text
+ property alias progressDotsModel : progressDots.model
// TODO extend properties if needed
@@ -64,6 +65,7 @@ Item {
}
Repeater {
+ id: progressDots
model: dotsModel
delegate: Rectangle {
width: 12; height: 12
@@ -184,7 +186,7 @@ Item {
Row {
anchors.left: parent.left
anchors.right: parent.right
- anchors.top: (restoreHeightItem.visible)? restoreHeightItem.bottom : memoTextItem.bottom
+ anchors.top: (restoreHeightItem.visible)? restoreHeightItem.bottom : (memoTextItem.visible)? memoTextItem.bottom : frameHeader.bottom
anchors.topMargin: 24
spacing: 16
diff --git a/wizard/WizardPassword.qml b/wizard/WizardPassword.qml
index c26a7407..adba7a94 100644
--- a/wizard/WizardPassword.qml
+++ b/wizard/WizardPassword.qml
@@ -36,8 +36,9 @@ Item {
id: passwordPage
opacity: 0
visible: false
-
property alias titleText: titleText.text
+ property alias passwordsMatch: passwordUI.passwordsMatch
+ property alias password: passwordUI.password
Behavior on opacity {
NumberAnimation { duration: 100; easing.type: Easing.InQuad }
}
@@ -47,7 +48,7 @@ Item {
function onPageOpened(settingsObject) {
wizard.nextButton.enabled = true
- handlePassword();
+ passwordUI.handlePassword();
if (wizard.currentPath === "create_wallet") {
passwordPage.titleText = qsTr("Give your wallet a password") + translationManager.emptyString
@@ -55,44 +56,22 @@ Item {
passwordPage.titleText = qsTr("Give your wallet a password") + translationManager.emptyString
}
- passwordItem.focus = true;
+ passwordUI.focus = true;
}
function onPageClosed(settingsObject) {
// TODO: set password on the final page
// settingsObject.wallet.setPassword(passwordItem.password)
- settingsObject['wallet_password'] = passwordItem.password
+ settingsObject['wallet_password'] = passwordUI.password
return true
}
function onWizardRestarted(){
// Reset password fields
- passwordItem.password = "";
- retypePasswordItem.password = "";
+ passwordUI.password = "";
+ passwordUI.confirmPassword = "";
}
- function handlePassword() {
- // allow to forward step only if passwords match
-
- wizard.nextButton.enabled = passwordItem.password === retypePasswordItem.password
-
- // scorePassword returns value from 0 to... lots
- var strength = walletManager.getPasswordStrength(passwordItem.password);
- // consider anything below 10 bits as dire
- strength -= 10
- if (strength < 0)
- strength = 0
- // use a slight parabola to discourage short passwords
- strength = strength ^ 1.2 / 3
- // mapScope does not clamp
- if (strength > 100)
- strength = 100
- // privacyLevel component uses 1..13 scale
- privacyLevel.fillLevel = Utils.mapScope(1, 100, 1, 13, strength)
- }
-
-
-
Row {
id: dotsRow
anchors.top: parent.top
@@ -111,6 +90,9 @@ Item {
Repeater {
model: dotsModel
delegate: Rectangle {
+ // Password page is last page when creating view only wallet
+ // TODO: make this dynamic for all pages in wizard
+ visible: (wizard.currentPath != "create_view_only_wallet" || index < 2)
width: 12; height: 12
radius: 6
color: dotColor
@@ -157,39 +139,12 @@ Item {
}
- WizardPasswordInput {
- id: passwordItem
- anchors.top: headerColumn.bottom
- anchors.horizontalCenter: parent.horizontalCenter
- anchors.topMargin: 24
- width: 300
- height: 62
- placeholderText : qsTr("Password") + translationManager.emptyString;
- KeyNavigation.tab: retypePasswordItem
- onChanged: handlePassword()
-
- }
-
- WizardPasswordInput {
- id: retypePasswordItem
- anchors.top: passwordItem.bottom
- anchors.horizontalCenter: parent.horizontalCenter
- anchors.topMargin: 24
- width: 300
- height: 62
- placeholderText : qsTr("Confirm password") + translationManager.emptyString;
- KeyNavigation.tab: passwordItem
- onChanged: handlePassword()
- }
-
- PrivacyLevelSmall {
- id: privacyLevel
- anchors.left: parent.left
+ WizardPasswordUI {
+ id: passwordUI
anchors.right: parent.right
- anchors.top: retypePasswordItem.bottom
- anchors.topMargin: 60
- background: "#F0EEEE"
- interactive: false
+ anchors.left: parent.left
+ anchors.top: headerColumn.bottom
+ anchors.topMargin: 30
}
Component.onCompleted: {
diff --git a/wizard/WizardPasswordUI.qml b/wizard/WizardPasswordUI.qml
new file mode 100644
index 00000000..c9a4b0c8
--- /dev/null
+++ b/wizard/WizardPasswordUI.qml
@@ -0,0 +1,96 @@
+// Copyright (c) 2014-2015, 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 moneroComponents.WalletManager 1.0
+import QtQuick 2.2
+import "../components"
+import "utils.js" as Utils
+
+FocusScope {
+ property alias password: passwordItem.password
+ property alias confirmPassword: retypePasswordItem.password
+ property bool passwordsMatch: passwordItem.password === retypePasswordItem.password
+
+ function handlePassword() {
+ // allow to forward step only if passwords match
+
+ wizard.nextButton.enabled = passwordItem.password === retypePasswordItem.password
+
+ // scorePassword returns value from 0 to... lots
+ var strength = walletManager.getPasswordStrength(passwordItem.password);
+ // consider anything below 10 bits as dire
+ strength -= 10
+ if (strength < 0)
+ strength = 0
+ // use a slight parabola to discourage short passwords
+ strength = strength ^ 1.2 / 3
+ // mapScope does not clamp
+ if (strength > 100)
+ strength = 100
+ // privacyLevel component uses 1..13 scale
+ privacyLevel.fillLevel = Utils.mapScope(1, 100, 1, 13, strength)
+ }
+
+ WizardPasswordInput {
+ id: passwordItem
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.topMargin: 24
+ width: 300
+ height: 62
+ placeholderText : qsTr("Password") + translationManager.emptyString;
+ KeyNavigation.tab: retypePasswordItem
+ onChanged: handlePassword()
+ focus: true
+ }
+
+ WizardPasswordInput {
+ id: retypePasswordItem
+ anchors.top: passwordItem.bottom
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.topMargin: 24
+ width: 300
+ height: 62
+ placeholderText : qsTr("Confirm password") + translationManager.emptyString;
+ KeyNavigation.tab: passwordItem
+ onChanged: handlePassword()
+ }
+
+ PrivacyLevelSmall {
+ id: privacyLevel
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.top: retypePasswordItem.bottom
+ anchors.topMargin: 60
+ background: "#F0EEEE"
+ interactive: false
+ }
+
+ Component.onCompleted: {
+ //parent.wizardRestarted.connect(onWizardRestarted)
+ }
+}
diff --git a/wizard/utils.js b/wizard/utils.js
index 7b9fc241..65409046 100644
--- a/wizard/utils.js
+++ b/wizard/utils.js
@@ -15,3 +15,10 @@ function tr(text) {
function lineBreaksToSpaces(text) {
return text.trim().replace(/(\r\n|\n|\r)/gm, " ");
}
+
+function usefulName(path) {
+ // arbitrary "short enough" limit
+ if (path.length < 32)
+ return path
+ return path.replace(/.*[\/\\]/, '').replace(/\.keys$/, '')
+}