diff --git a/main.cpp b/main.cpp index 0e0d58e3..917f1e58 100644 --- a/main.cpp +++ b/main.cpp @@ -116,12 +116,21 @@ int main(int argc, char *argv[]) #endif if (!moneroAccountsRootDir.empty()) { - QString moneroAccountsDir = moneroAccountsRootDir.at(0) + "/Monero Accounts"; - QDir tempDir; - tempDir.mkpath(moneroAccountsDir); + QString moneroAccountsDir = moneroAccountsRootDir.at(0) + "/Monero/wallets"; engine.rootContext()->setContextProperty("moneroAccountsDir", moneroAccountsDir); } + + // Get default account name + QString accountName = qgetenv("USER"); // mac/linux + if (accountName.isEmpty()){ + accountName = qgetenv("USERNAME"); // Windows + } + if (accountName.isEmpty()) { + accountName = "My monero Account"; + } + + engine.rootContext()->setContextProperty("defaultAccountName", accountName); engine.rootContext()->setContextProperty("applicationDirectory", QApplication::applicationDirPath()); engine.load(QUrl(QStringLiteral("qrc:///main.qml"))); QObject *rootObject = engine.rootObjects().first(); diff --git a/main.qml b/main.qml index 440b79f4..c2639433 100644 --- a/main.qml +++ b/main.qml @@ -130,6 +130,12 @@ ApplicationWindow { } + function openWalletFromFile(){ + persistentSettings.restore_height = 0 + persistentSettings.is_recovering = false + appWindow.password = "" + fileDialog.open(); + } function initialize() { console.log("initializing..") @@ -148,6 +154,12 @@ ApplicationWindow { if (currentWallet != undefined) { console.log("closing currentWallet") walletManager.closeWallet(currentWallet); + } else { + + // set page to transfer if not changing daemon + middlePanel.state = "Transfer"; + leftPanel.selectItem(middlePanel.state) + } // wallet already opened with wizard, we just need to initialize it @@ -158,7 +170,6 @@ ApplicationWindow { restoreHeight = persistentSettings.restore_height } - console.log("using wizard wallet") connectWallet(wizard.settings['wallet']) isNewWallet = true @@ -171,6 +182,7 @@ ApplicationWindow { walletManager.openWalletAsync(wallet_path, appWindow.password, persistentSettings.testnet); } + } @@ -189,8 +201,7 @@ ApplicationWindow { } function walletPath() { - var wallet_path = persistentSettings.wallet_path + "/" + persistentSettings.account_name + "/" - + persistentSettings.account_name; + var wallet_path = persistentSettings.wallet_path return wallet_path; } @@ -305,12 +316,19 @@ ApplicationWindow { function walletsFound() { + if (persistentSettings.wallet_path.length > 0) { + var lastOpenedExists = walletManager.walletExists(persistentSettings.wallet_path); + if (lastOpenedExists) { + console.log("Last opened wallet exists in:",persistentSettings.wallet_path) + } + } + + // Check if wallets exists in default path var wallets = walletManager.findWallets(moneroAccountsDir); if (wallets.length === 0) { wallets = walletManager.findWallets(applicationDirectory); } - print(wallets); - return wallets.length > 0; + return (wallets.length > 0 || lastOpenedExists); } @@ -423,6 +441,17 @@ ApplicationWindow { splash.close() } + // close wallet and show wizard + function showWizard(){ + walletInitialized = false; + splashCounter = 0; + // we can't close async here. Gui crashes if wallet is open + walletManager.closeWallet(currentWallet); + wizard.restart(); + rootItem.state = "wizard" + + } + objectName: "appWindow" visible: true @@ -440,10 +469,13 @@ ApplicationWindow { walletManager.walletOpened.connect(onWalletOpened); walletManager.walletClosed.connect(onWalletClosed); - rootItem.state = walletsFound() ? "normal" : "wizard"; - if (rootItem.state === "normal") { - initialize(persistentSettings) + if(!walletsFound()) { + rootItem.state = "wizard" + } else { + rootItem.state = "normal" + initialize(persistentSettings); } + } onRightPanelExpandedChanged: { @@ -493,6 +525,24 @@ ApplicationWindow { } } + //Open Wallet from file + FileDialog { + id: fileDialog + title: "Please choose a file" + folder: "file://" +moneroAccountsDir + nameFilters: [ "Wallet files (*.keys)"] + + onAccepted: { + persistentSettings.wallet_path = walletManager.urlToLocalPath(fileDialog.fileUrl) + initialize(); + } + onRejected: { + console.log("Canceled") + rootItem.state = "wizard"; + } + + } + PasswordDialog { id: passwordDialog standardButtons: StandardButton.Ok + StandardButton.Cancel @@ -501,7 +551,8 @@ ApplicationWindow { appWindow.initialize(); } onRejected: { - appWindow.enableUI(false) + //appWindow.enableUI(false) + rootItem.state = "wizard" } onDiscard: { appWindow.enableUI(false) @@ -729,6 +780,10 @@ ApplicationWindow { rootItem.state = "normal" // TODO: listen for this state change in appWindow; appWindow.initialize(); } + onOpenWalletFromFileClicked: { + rootItem.state = "normal" // TODO: listen for this state change in appWindow; + appWindow.openWalletFromFile(); + } } property int maxWidth: leftPanel.width + 655 + rightPanel.width @@ -810,7 +865,6 @@ ApplicationWindow { } } onClosing: { - walletManager.closeWallet(currentWallet); - console.log("onClosing called"); + //walletManager.closeWallet(currentWallet); } } diff --git a/pages/Settings.qml b/pages/Settings.qml index 8bfb4d2e..34c53640 100644 --- a/pages/Settings.qml +++ b/pages/Settings.qml @@ -56,15 +56,6 @@ Rectangle { daemonAddress = persistentSettings.daemon_address.split(":"); console.log("address: " + persistentSettings.daemon_address) // try connecting to daemon - var connectedToDaemon = currentWallet.connectToDaemon(); - - if(!connectedToDaemon){ - console.log("not connected"); - //TODO: Print error? - //daemonStatusText.text = qsTr("Unable to connect to Daemon.") - //daemonStatusText.visible = true - } - } @@ -241,36 +232,46 @@ Rectangle { RowLayout { - id: daemonStatusRow + Label { + id: closeWalletLabel - Layout.fillWidth: true + Layout.fillWidth: true + color: "#4A4949" + text: qsTr("Manage wallet") + translationManager.emptyString + fontSize: 16 + } + } + RowLayout { Text { - id: daemonStatusText + id: closeWalletTip font.family: "Arial" - font.pixelSize: 18 - wrapMode: Text.Wrap - textFormat: Text.RichText - horizontalAlignment: Text.AlignHCenter - color: "#FF0000" - visible: true //!currentWallet.connected + font.pointSize: 12 + color: "#4A4646" + Layout.fillWidth: true + wrapMode: Text.WordWrap + text: qsTr("Close current wallet and open wizard") + + translationManager.emptyString } -// StandardButton { -// id: checkConnectionButton -// anchors.left: daemonStatusText.right -// anchors.leftMargin: 30 -// width: 90 -// text: qsTr("Check again") + translationManager.emptyString -// shadowReleasedColor: "#FF4304" -// shadowPressedColor: "#B32D00" -// releasedColor: "#FF6C3C" -// pressedColor: "#FF4304" -// visible: true -// onClicked: { -// checkDaemonConnection(); -// } -// } + + 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(); + } + } } } diff --git a/src/libwalletqt/Wallet.cpp b/src/libwalletqt/Wallet.cpp index 3c8858b5..004d84ce 100644 --- a/src/libwalletqt/Wallet.cpp +++ b/src/libwalletqt/Wallet.cpp @@ -268,5 +268,6 @@ Wallet::Wallet(Bitmonero::Wallet *w, QObject *parent) Wallet::~Wallet() { + qDebug("~Wallet: Closing wallet"); Bitmonero::WalletManagerFactory::getWalletManager()->closeWallet(m_walletImpl); } diff --git a/wizard/WizardCreateWallet.qml b/wizard/WizardCreateWallet.qml index 6d632cbe..bef91bc2 100644 --- a/wizard/WizardCreateWallet.qml +++ b/wizard/WizardCreateWallet.qml @@ -54,7 +54,8 @@ Item { settingsObject['account_name'] = uiItem.accountNameText settingsObject['words'] = uiItem.wordsTexttext settingsObject['wallet_path'] = uiItem.walletPath - return true; + var walletFullPath = wizard.createWalletPath(uiItem.walletPath,uiItem.accountNameText); + return !wizard.walletExists(walletFullPath); } function checkNextButton() { @@ -70,25 +71,24 @@ Item { // TODO: create wallet in temporary filename and a) move it to the path specified by user after the final // page submitted or b) delete it when program closed before reaching final page - var wallet_filename = oshelper.temporaryFilename(); - if (typeof settingsObject.wallet === 'undefined') { - //var wallet = walletManager.createWallet(wallet_filename, "", settingsObject.language) - var testnet = appWindow.persistentSettings.testnet; - var wallet = walletManager.createWallet(wallet_filename, "", settingsObject.wallet_language, - testnet) - uiItem.wordsTextItem.memoText = wallet.seed - // saving wallet in "global" settings object - // TODO: wallet should have a property pointing to the file where it stored or loaded from - settingsObject.wallet = wallet - } else { - print("wallet already created. we just stepping back"); + // Always delete the wallet object before creating new - we could be stepping back from recovering wallet + if (typeof settingsObject.wallet !== 'undefined') { + settingsObject.wallet.destroy() + console.log("deleting wallet") } + + var wallet_filename = oshelper.temporaryFilename(); + //var wallet = walletManager.createWallet(wallet_filename, "", settingsObject.language) + var testnet = appWindow.persistentSettings.testnet; + var wallet = walletManager.createWallet(wallet_filename, "", settingsObject.wallet_language, + testnet) + uiItem.wordsTextItem.memoText = wallet.seed + // saving wallet in "global" settings object + // TODO: wallet should have a property pointing to the file where it stored or loaded from + settingsObject.wallet = wallet settingsObject.wallet_filename = wallet_filename } - - - WizardManageWalletUI { id: uiItem titleText: qsTr("A new wallet has been created for you") + translationManager.emptyString diff --git a/wizard/WizardMain.qml b/wizard/WizardMain.qml index 543ee14d..446d7720 100644 --- a/wizard/WizardMain.qml +++ b/wizard/WizardMain.qml @@ -28,6 +28,7 @@ import QtQuick 2.2 import Qt.labs.settings 1.0 +import QtQuick.Dialogs 1.2 import "../components" @@ -38,17 +39,37 @@ Rectangle { property int currentPage: 0 property var paths: { - "create_wallet" : [welcomePage, optionsPage, createWalletPage, passwordPage, donationPage, finishPage ], - "recovery_wallet" : [welcomePage, optionsPage, recoveryWalletPage, passwordPage, donationPage, finishPage ] + // "create_wallet" : [welcomePage, optionsPage, createWalletPage, passwordPage, donationPage, finishPage ], + // "recovery_wallet" : [welcomePage, optionsPage, recoveryWalletPage, passwordPage, donationPage, finishPage ], + // disable donation page + "create_wallet" : [welcomePage, optionsPage, createWalletPage, passwordPage, finishPage ], + "recovery_wallet" : [welcomePage, optionsPage, recoveryWalletPage, passwordPage, finishPage ], + } property string currentPath: "create_wallet" property var pages: paths[currentPath] signal useMoneroClicked() + signal openWalletFromFileClicked() border.color: "#DBDBDB" border.width: 1 color: "#FFFFFF" + function restart(){ + wizard.currentPage = 0; + wizard.settings = ({}) + wizard.currentPath = "create_wallet" + wizard.pages = paths[currentPath] + + //hide all pages except first + for (var i = 1; i < wizard.pages.length; i++){ + wizard.pages[i].opacity = 0; + } + //Show first pages + wizard.pages[0].opacity = 1; + + } + function switchPage(next) { // save settings for current page; if (next && typeof pages[currentPage].onPageClosed !== 'undefined') { @@ -58,7 +79,7 @@ Rectangle { }; } - print ("switchpage: currentPage: ", currentPage); + console.log("switchpage: currentPage: ", currentPage); if (currentPage > 0 || currentPage < pages.length - 1) { pages[currentPage].opacity = 0 @@ -103,24 +124,40 @@ Rectangle { currentPage = pages.indexOf(recoveryWalletPage) wizard.nextButton.visible = true recoveryWalletPage.onPageOpened(settings); + } + function openOpenWalletPage() { + console.log("open wallet from file page"); + wizard.openWalletFromFileClicked(); + } + + function createWalletPath(folder_path,account_name){ + + // Remove trailing slash - (default on windows and mac) + if (folder_path.substring(folder_path.length -1) === "/"){ + folder_path = folder_path.substring(0,folder_path.length -1) + } + + return folder_path + "/" + account_name + "/" + account_name + } + + function walletExists(path){ + if(walletManager.walletExists(path)){ + walletExistsErrorDialog.open(); + return true; + } + return false; } //! actually writes the wallet function applySettings() { console.log("Here we apply the settings"); // here we need to actually move wallet to the new location + console.log(settings.wallet_full_path); - // Remove trailing slash - (default on windows and mac) - if (settings.wallet_path.substring(settings.wallet_path.length -1) === "/"){ - settings.wallet_path = settings.wallet_path.substring(0,settings.wallet_path.length -1) - } + var new_wallet_filename = createWalletPath(settings.wallet_path,settings.account_name) - var new_wallet_filename = settings.wallet_path + "/" - + settings.account_name + "/" - + settings.account_name; - - console.log("saving to wizard: "+ new_wallet_filename) + console.log("saving in wizard: "+ new_wallet_filename) // moving wallet files to the new destination, if user changed it if (new_wallet_filename !== settings.wallet_filename) { // using previously saved wallet; @@ -140,25 +177,32 @@ Rectangle { appWindow.persistentSettings.language = settings.language appWindow.persistentSettings.locale = settings.locale appWindow.persistentSettings.account_name = settings.account_name - appWindow.persistentSettings.wallet_path = settings.wallet_path - appWindow.persistentSettings.allow_background_mining = settings.allow_background_mining - appWindow.persistentSettings.auto_donations_enabled = settings.auto_donations_enabled - appWindow.persistentSettings.auto_donations_amount = settings.auto_donations_amount + appWindow.persistentSettings.wallet_path = new_wallet_filename + appWindow.persistentSettings.allow_background_mining = false //settings.allow_background_mining + appWindow.persistentSettings.auto_donations_enabled = false //settings.auto_donations_enabled + appWindow.persistentSettings.auto_donations_amount = false //settings.auto_donations_amount appWindow.persistentSettings.daemon_address = settings.daemon_address appWindow.persistentSettings.testnet = settings.testnet appWindow.persistentSettings.restore_height = (isNaN(settings.restore_height))? 0 : settings.restore_height appWindow.persistentSettings.is_recovering = (settings.is_recovering === undefined)? false : settings.is_recovering + } // reading settings from persistent storage Component.onCompleted: { - console.log("rootItem: ", appWindow); settings['allow_background_mining'] = appWindow.persistentSettings.allow_background_mining settings['auto_donations_enabled'] = appWindow.persistentSettings.auto_donations_enabled settings['auto_donations_amount'] = appWindow.persistentSettings.auto_donations_amount } + MessageDialog { + id: walletExistsErrorDialog + title: "Error" + text: qsTr("A wallet with same name already exists. Please change wallet name") + translationManager.emptyString + onAccepted: { + } + } Rectangle { id: nextButton @@ -206,6 +250,7 @@ Rectangle { anchors.rightMargin: 50 onCreateWalletClicked: wizard.openCreateWalletPage() onRecoveryWalletClicked: wizard.openRecoveryWalletPage() + onOpenWalletClicked: wizard.openOpenWalletPage(); } WizardCreateWallet { @@ -228,8 +273,6 @@ Rectangle { anchors.rightMargin: 50 } - - WizardPassword { id: passwordPage anchors.top: parent.top @@ -299,7 +342,7 @@ Rectangle { visible: parent.paths[currentPath][currentPage] === finishPage onClicked: { wizard.applySettings(); - wizard.useMoneroClicked() + wizard.useMoneroClicked(); } } } diff --git a/wizard/WizardManageWalletUI.qml b/wizard/WizardManageWalletUI.qml index 7104dc9f..ad0f2e7e 100644 --- a/wizard/WizardManageWalletUI.qml +++ b/wizard/WizardManageWalletUI.qml @@ -126,7 +126,13 @@ Item { renderType: Text.NativeRendering color: "#FF6C3C" focus: true - text: qsTr("My account name") + translationManager.emptyString + text: defaultAccountName + + + Keys.onReleased: { + wizard.nextButton.enabled = (accountName.length > 0) + } + } Rectangle { diff --git a/wizard/WizardOptions.qml b/wizard/WizardOptions.qml index 8f9a2753..e2eaa958 100644 --- a/wizard/WizardOptions.qml +++ b/wizard/WizardOptions.qml @@ -35,8 +35,10 @@ Item { id: page signal createWalletClicked() signal recoveryWalletClicked() + signal openWalletClicked() opacity: 0 visible: false + property var buttonSize: 190 function saveDaemonAddress() { wizard.settings["daemon_address"] = daemonAddress.text @@ -96,16 +98,23 @@ Item { anchors.centerIn: parent spacing: 40 + Column { anchors.verticalCenter: parent.verticalCenter spacing: 30 Rectangle { - width: 202; height: 202 - radius: 101 + width: page.buttonSize; height: page.buttonSize + radius: page.buttonSize color: createWalletArea.containsMouse ? "#DBDBDB" : "#FFFFFF" + Image { + width:page.buttonSize -30 + height:page.buttonSize -30 + fillMode: Image.PreserveAspectFit + horizontalAlignment: Image.AlignRight + verticalAlignment: Image.AlignTop anchors.centerIn: parent source: "qrc:///images/createWallet.png" } @@ -126,7 +135,9 @@ Item { font.pixelSize: 16 color: "#4A4949" horizontalAlignment: Text.AlignHCenter - text: qsTr("This is my first time, I want to
create a new account") + translationManager.emptyString + width:page.buttonSize + wrapMode: Text.WordWrap + text: qsTr("This is my first time, I want to create a new account") + translationManager.emptyString } } @@ -135,11 +146,14 @@ Item { spacing: 30 Rectangle { - width: 202; height: 202 - radius: 101 + width: page.buttonSize; height: page.buttonSize + radius: page.buttonSize color: recoverWalletArea.containsMouse ? "#DBDBDB" : "#FFFFFF" Image { + width:page.buttonSize -30 + height:page.buttonSize -30 + fillMode: Image.PreserveAspectFit anchors.centerIn: parent source: "qrc:///images/recoverWallet.png" } @@ -160,9 +174,53 @@ Item { font.pixelSize: 16 color: "#4A4949" horizontalAlignment: Text.AlignHCenter - text: qsTr("I want to recover my account
from my 25 word seed") + translationManager.emptyString + text: qsTr("I want to recover my account from my 25 word seed") + translationManager.emptyString + width:page.buttonSize + wrapMode: Text.WordWrap } } + + Column { + anchors.verticalCenter: parent.verticalCenter + spacing: 30 + + Rectangle { + width: page.buttonSize; height: page.buttonSize + radius: page.buttonSize + color: openWalletArea.containsMouse ? "#DBDBDB" : "#FFFFFF" + + Image { + width:page.buttonSize -30 + height:page.buttonSize -30 + fillMode: Image.PreserveAspectFit + anchors.centerIn: parent + source: "qrc:///images/openAccount.png" + } + + MouseArea { + id: openWalletArea + anchors.fill: parent + hoverEnabled: true + onClicked: { + page.saveDaemonAddress() + page.openWalletClicked() + } + } + } + + Text { + font.family: "Arial" + font.pixelSize: 16 + color: "#4A4949" + horizontalAlignment: Text.AlignHCenter + text: qsTr("I want to open a wallet from file") + translationManager.emptyString + width:page.buttonSize + wrapMode: Text.WordWrap + } + } + + + } diff --git a/wizard/WizardPassword.qml b/wizard/WizardPassword.qml index 476c5742..8645a300 100644 --- a/wizard/WizardPassword.qml +++ b/wizard/WizardPassword.qml @@ -46,6 +46,7 @@ Item { function onPageOpened(settingsObject) { wizard.nextButton.enabled = true + handlePassword(); if (wizard.currentPath === "create_wallet") { passwordPage.titleText = qsTr("Now that your wallet has been created, please set a password for the wallet") + translationManager.emptyString diff --git a/wizard/WizardRecoveryWallet.qml b/wizard/WizardRecoveryWallet.qml index f4c5091e..236c59a1 100644 --- a/wizard/WizardRecoveryWallet.qml +++ b/wizard/WizardRecoveryWallet.qml @@ -43,6 +43,8 @@ Item { function onPageOpened(settingsObject) { checkNextButton(); + // Empty seedText when restoring multiple times in one session + uiItem.wordsTextItem.memoText = ""; } function checkNextButton() { @@ -54,7 +56,12 @@ Item { settingsObject['account_name'] = uiItem.accountNameText settingsObject['words'] = Utils.lineBreaksToSpaces(uiItem.wordsTextItem.memoText) settingsObject['wallet_path'] = uiItem.walletPath - settingsObject['restore_height'] = parseInt(uiItem.restoreHeight) + var restoreHeight = parseInt(uiItem.restoreHeight); + settingsObject['restore_height'] = isNaN(restoreHeight)? 0 : restoreHeight + var walletFullPath = wizard.createWalletPath(uiItem.walletPath,uiItem.accountNameText); + if(wizard.walletExists(walletFullPath)){ + return false + } return recoveryWallet(settingsObject) } @@ -76,7 +83,7 @@ Item { WizardManageWalletUI { id: uiItem - accountNameText: qsTr("My account name") + translationManager.emptyString + accountNameText: defaultAccountName titleText: qsTr("We're ready to recover your account") + translationManager.emptyString wordsTextTitle: qsTr("Please enter your 25 word private key") + translationManager.emptyString wordsTextItem.clipboardButtonVisible: false diff --git a/wizard/WizardWelcome.qml b/wizard/WizardWelcome.qml index ef97f984..3553a6a5 100644 --- a/wizard/WizardWelcome.qml +++ b/wizard/WizardWelcome.qml @@ -45,13 +45,18 @@ Item { onOpacityChanged: visible = opacity !== 0 - - function onPageClosed(settingsObject) { + + // set default language to first item if none selected + if(gridView.currentIndex === -1) { + gridView.currentIndex = 0 + } + var lang = languagesModel.get(gridView.currentIndex); settingsObject['language'] = lang.display_name; settingsObject['wallet_language'] = lang.wallet_language; settingsObject['locale'] = lang.locale; + console.log("Language chosen: ",lang.display_name) return true } @@ -108,7 +113,15 @@ Item { // and set current language accordingly XmlRole { name: "isCurrent"; query: "@enabled/string()" } - + onStatusChanged: { + if(status === XmlListModel.Ready){ + console.log("languages availible: ",count); + if(count === 1){ + console.log("Skipping language page until more languages are availible") + wizard.switchPage(true); + } + } + } } // Flags view