Merge pull request #1511

Settings overhaul (27 commits by skftn)
This commit is contained in:
luigi1111 2018-08-14 16:15:31 -05:00
commit 3483b8dbec
No known key found for this signature in database
GPG key ID: F4ACA0183641E010
29 changed files with 2270 additions and 956 deletions

View file

@ -37,6 +37,7 @@ import QtGraphicalEffects 1.0
import moneroComponents.Wallet 1.0 import moneroComponents.Wallet 1.0
import "./pages" import "./pages"
import "./pages/settings"
Rectangle { Rectangle {
id: root id: root
@ -141,7 +142,7 @@ Rectangle {
}, State { }, State {
name: "Settings" name: "Settings"
PropertyChanges { target: root; currentView: settingsView } PropertyChanges { target: root; currentView: settingsView }
PropertyChanges { target: mainFlickable; contentHeight: settingsView.settingsHeight + 100 } PropertyChanges { target: mainFlickable; contentHeight: settingsView.settingsHeight }
}, State { }, State {
name: "Mining" name: "Mining"
PropertyChanges { target: root; currentView: miningView } PropertyChanges { target: root; currentView: miningView }

View file

@ -53,7 +53,7 @@ Rectangle{
font.family: MoneroComponents.Style.fontRegular.name font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 14 * scaleRatio font.pixelSize: 14 * scaleRatio
text: labelHeader text: labelHeader
color: MoneroComponents.Style.greyFontColor color: MoneroComponents.Style.dimmedFontColor
} }
Text { Text {
@ -77,7 +77,7 @@ Rectangle{
label2.color = MoneroComponents.Style.defaultFontColor; label2.color = MoneroComponents.Style.defaultFontColor;
} }
onExited: { onExited: {
label1.color = MoneroComponents.Style.greyFontColor; label1.color = MoneroComponents.Style.dimmedFontColor
label2.color = MoneroComponents.Style.dimmedFontColor; label2.color = MoneroComponents.Style.dimmedFontColor;
} }
onClicked: { onClicked: {

View file

@ -103,6 +103,8 @@ Item {
leftPadding: 10 leftPadding: 10
topPadding: 10 topPadding: 10
color: MoneroComponents.Style.defaultFontColor color: MoneroComponents.Style.defaultFontColor
selectionColor: MoneroComponents.Style.dimmedFontColor
selectedTextColor: MoneroComponents.Style.defaultFontColor
background: Rectangle { background: Rectangle {
radius: 2 radius: 2

View file

@ -32,31 +32,25 @@ import QtQuick 2.7
import "../js/TxUtils.js" as TxUtils import "../js/TxUtils.js" as TxUtils
import "../components" as MoneroComponents import "../components" as MoneroComponents
TextArea { TextArea {
property bool error: false
property bool addressValidation: false
property bool wrapAnywhere: true
property int fontSize: 18 * scaleRatio property int fontSize: 18 * scaleRatio
property bool fontBold: false property bool fontBold: false
property string fontColor: MoneroComponents.Style.defaultFontColor
property bool mouseSelection: true
property bool error: false
property bool addressValidation: false
id: textArea id: textArea
font.family: MoneroComponents.Style.fontRegular.name font.family: MoneroComponents.Style.fontRegular.name
color: fontColor
font.pixelSize: fontSize font.pixelSize: fontSize
font.bold: fontBold font.bold: fontBold
horizontalAlignment: TextInput.AlignLeft horizontalAlignment: TextInput.AlignLeft
selectByMouse: true selectByMouse: mouseSelection
color: MoneroComponents.Style.defaultFontColor
selectionColor: MoneroComponents.Style.dimmedFontColor selectionColor: MoneroComponents.Style.dimmedFontColor
selectedTextColor: MoneroComponents.Style.defaultFontColor selectedTextColor: MoneroComponents.Style.defaultFontColor
wrapMode: {
if(wrapAnywhere){
return Text.WrapAnywhere;
} else {
return Text.WordWrap;
}
}
onTextChanged: { onTextChanged: {
if(addressValidation){ if(addressValidation){
// js replacement for `RegExpValidator { regExp: /[0-9A-Fa-f]{95}/g }` // js replacement for `RegExpValidator { regExp: /[0-9A-Fa-f]{95}/g }`

View file

@ -50,6 +50,8 @@ Item {
property alias inlineButtonText: inlineButtonId.text property alias inlineButtonText: inlineButtonId.text
property alias inlineIcon: inlineIcon.visible property alias inlineIcon: inlineIcon.visible
property bool copyButton: false property bool copyButton: false
property bool borderDisabled: false
property string borderColor: { property string borderColor: {
if(input.activeFocus){ if(input.activeFocus){
return MoneroComponents.Style.inputBorderColorActive; return MoneroComponents.Style.inputBorderColorActive;
@ -57,9 +59,8 @@ Item {
return MoneroComponents.Style.inputBorderColorInActive; return MoneroComponents.Style.inputBorderColorInActive;
} }
} }
property bool borderDisabled: false
property int fontSize: 18 * scaleRatio property int fontSize: 18 * scaleRatio
property bool showBorder: true
property bool fontBold: false property bool fontBold: false
property alias fontColor: input.color property alias fontColor: input.color
property bool error: false property bool error: false
@ -140,6 +141,7 @@ Item {
anchors.top: showingHeader ? inputLabel.bottom : parent.top anchors.top: showingHeader ? inputLabel.bottom : parent.top
anchors.topMargin: showingHeader ? 12 * scaleRatio : 2 * scaleRatio anchors.topMargin: showingHeader ? 12 * scaleRatio : 2 * scaleRatio
width: parent.width width: parent.width
clip: true
Text { Text {
id: placeholderLabel id: placeholderLabel
@ -200,6 +202,8 @@ Item {
onEditingFinished: item.editingFinished() onEditingFinished: item.editingFinished()
onAccepted: item.accepted(); onAccepted: item.accepted();
onTextChanged: item.textUpdated() onTextChanged: item.textUpdated()
topPadding: 10 * scaleRatio
bottomPadding: 10 * scaleRatio
} }
MoneroComponents.InlineButton { MoneroComponents.InlineButton {

View file

@ -32,25 +32,56 @@ import QtQuick.Layouts 1.1
import "../components" as MoneroComponents import "../components" as MoneroComponents
ColumnLayout { ColumnLayout {
id: lineditmulti id: item
property alias text: multiLine.text
property alias placeholderText: placeholderLabel.text Layout.fillWidth: true
Layout.preferredHeight: childrenRect.height
property alias text: input.text
property alias labelText: inputLabel.text property alias labelText: inputLabel.text
property alias error: multiLine.error
property alias readOnly: multiLine.readOnly
property alias addressValidation: multiLine.addressValidation
property alias labelButtonText: labelButton.text property alias labelButtonText: labelButton.text
property alias placeholderText: placeholderLabel.text
property bool placeholderCenter: false
property string placeholderFontFamily: MoneroComponents.Style.fontRegular.name
property bool placeholderFontBold: false
property int placeholderFontSize: 18 * scaleRatio
property string placeholderColor: MoneroComponents.Style.defaultFontColor
property real placeholderOpacity: 0.35
property bool borderDisabled: false
property string borderColor: {
if(input.error && input.text !== ""){
return MoneroComponents.Style.inputBorderColorInvalid;
} else if(input.activeFocus){
return MoneroComponents.Style.inputBorderColorActive;
} else {
return MoneroComponents.Style.inputBorderColorInActive;
}
}
property bool error: false
property string labelFontColor: MoneroComponents.Style.defaultFontColor
property bool labelFontBold: false property bool labelFontBold: false
property int labelFontSize: 16 * scaleRatio
property bool labelButtonVisible: false property bool labelButtonVisible: false
property bool copyButton: false
property bool wrapAnywhere: true property string fontColor: "white"
property bool showingHeader: true
property bool showBorder: true
property bool fontBold: false property bool fontBold: false
property int fontSize: 16 * scaleRatio property int fontSize: 16 * scaleRatio
property bool mouseSelection: true
property alias readOnly: input.readOnly
property bool copyButton: false
property bool showingHeader: true
property var wrapMode: Text.NoWrap
property alias addressValidation: input.addressValidation
property string backgroundColor: "" // mock
signal labelButtonClicked(); signal labelButtonClicked();
signal inputLabelLinkActivated(); signal inputLabelLinkActivated();
signal editingFinished();
spacing: 0 spacing: 0
Rectangle { Rectangle {
@ -65,11 +96,17 @@ ColumnLayout {
anchors.top: parent.top anchors.top: parent.top
anchors.left: parent.left anchors.left: parent.left
font.family: MoneroComponents.Style.fontRegular.name font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 16 * scaleRatio font.pixelSize: item.labelFontSize
font.bold: labelFontBold font.bold: labelFontBold
textFormat: Text.RichText textFormat: Text.RichText
color: MoneroComponents.Style.defaultFontColor color: item.labelFontColor
onLinkActivated: inputLabelLinkActivated() onLinkActivated: inputLabelLinkActivated()
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.NoButton
cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor
}
} }
MoneroComponents.LabelButton { MoneroComponents.LabelButton {
@ -80,14 +117,14 @@ ColumnLayout {
MoneroComponents.LabelButton { MoneroComponents.LabelButton {
id: copyButtonId id: copyButtonId
visible: copyButton && multiLine.text !== "" visible: copyButton && input.text !== ""
text: qsTr("Copy") text: qsTr("Copy")
anchors.right: labelButton.visible ? inputLabel.right : parent.right anchors.right: labelButton.visible ? inputLabel.right : parent.right
anchors.rightMargin: labelButton.visible? 4 : 0 anchors.rightMargin: labelButton.visible? 4 : 0
onClicked: { onClicked: {
if (multiLine.text.length > 0) { if (input.text.length > 0) {
console.log("Copied to clipboard"); console.log("Copied to clipboard");
clipboard.setText(multiLine.text); clipboard.setText(input.text);
appWindow.showStatusMessage(qsTr("Copied to clipboard"), 3); appWindow.showStatusMessage(qsTr("Copied to clipboard"), 3);
} }
} }
@ -95,27 +132,32 @@ ColumnLayout {
} }
MoneroComponents.InputMulti { MoneroComponents.InputMulti {
id: multiLine id: input
readOnly: false readOnly: false
addressValidation: true addressValidation: false
anchors.top: parent.showingHeader ? inputLabelRect.bottom : parent.top anchors.top: item.showingHeader ? inputLabelRect.bottom : item.top
Layout.fillWidth: true Layout.fillWidth: true
topPadding: parent.showingHeader ? 10 * scaleRatio : 0 topPadding: item.showingHeader ? 10 * scaleRatio : 0
bottomPadding: 10 * scaleRatio bottomPadding: 10 * scaleRatio
wrapAnywhere: parent.wrapAnywhere wrapMode: item.wrapMode
fontSize: parent.fontSize fontSize: item.fontSize
fontBold: parent.fontBold fontBold: item.fontBold
fontColor: item.fontColor
mouseSelection: item.mouseSelection
onEditingFinished: item.editingFinished()
error: item.error
Text { Text {
id: placeholderLabel id: placeholderLabel
visible: multiLine.text ? false : true visible: input.text ? false : true
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left anchors.left: parent.left
anchors.leftMargin: 10 * scaleRatio anchors.leftMargin: 10 * scaleRatio
opacity: 0.35 opacity: item.placeholderOpacity
color: MoneroComponents.Style.defaultFontColor color: item.placeholderColor
font.family: MoneroComponents.Style.fontRegular.name font.family: item.placeholderFontFamily
font.pixelSize: 18 * scaleRatio font.bold: item.placeholderFontBold
font.pixelSize: item.placeholderFontSize
text: "" text: ""
z: 3 z: 3
} }
@ -123,18 +165,10 @@ ColumnLayout {
Rectangle { Rectangle {
color: "transparent" color: "transparent"
border.width: 1 border.width: 1
border.color: { border.color: item.borderColor
if(multiLine.error && multiLine.text !== ""){
return MoneroComponents.Style.inputBorderColorInvalid;
} else if(multiLine.activeFocus){
return MoneroComponents.Style.inputBorderColorActive;
} else {
return MoneroComponents.Style.inputBorderColorInActive;
}
}
radius: 4 radius: 4
anchors.fill: parent anchors.fill: parent
visible: lineditmulti.showBorder visible: !item.borderDisabled
} }
} }
} }

View file

@ -108,6 +108,8 @@ Item {
leftPadding: 10 leftPadding: 10
topPadding: 10 topPadding: 10
color: MoneroComponents.Style.defaultFontColor color: MoneroComponents.Style.defaultFontColor
selectionColor: MoneroComponents.Style.dimmedFontColor
selectedTextColor: MoneroComponents.Style.defaultFontColor
background: Rectangle { background: Rectangle {
radius: 2 radius: 2

View file

@ -53,6 +53,8 @@ GridLayout {
property string lineEditBorderColor: Qt.rgba(0, 0, 0, 0.15) property string lineEditBorderColor: Qt.rgba(0, 0, 0, 0.15)
property string lineEditBackgroundColor: "white" property string lineEditBackgroundColor: "white"
property string lineEditFontColor: "black" property string lineEditFontColor: "black"
property int lineEditFontSize: 18 * scaleRatio
property int labelFontSize: 16 * scaleRatio
property bool lineEditFontBold: true property bool lineEditFontBold: true
signal editingFinished() signal editingFinished()
@ -61,7 +63,7 @@ GridLayout {
return daemonAddr.text.trim() + ":" + daemonPort.text.trim() return daemonAddr.text.trim() + ":" + daemonPort.text.trim()
} }
LineEdit { LineEditMulti {
id: daemonAddr id: daemonAddr
Layout.fillWidth: true Layout.fillWidth: true
placeholderText: qsTr("Remote Node Hostname / IP") + translationManager.emptyString placeholderText: qsTr("Remote Node Hostname / IP") + translationManager.emptyString
@ -70,14 +72,16 @@ GridLayout {
placeholderFontSize: root.placeholderFontSize placeholderFontSize: root.placeholderFontSize
placeholderColor: root.placeholderColor placeholderColor: root.placeholderColor
placeholderOpacity: root.placeholderOpacity placeholderOpacity: root.placeholderOpacity
onEditingFinished: root.editingFinished() labelFontSize: root.labelFontSize
borderColor: lineEditBorderColor borderColor: lineEditBorderColor
backgroundColor: lineEditBackgroundColor backgroundColor: lineEditBackgroundColor
fontColor: lineEditFontColor fontColor: lineEditFontColor
fontBold: lineEditFontBold fontBold: lineEditFontBold
fontSize: lineEditFontSize
onEditingFinished: root.editingFinished()
} }
LineEdit { LineEditMulti {
id: daemonPort id: daemonPort
Layout.fillWidth: true Layout.fillWidth: true
placeholderText: qsTr("Port") + translationManager.emptyString placeholderText: qsTr("Port") + translationManager.emptyString
@ -86,10 +90,13 @@ GridLayout {
placeholderFontSize: root.placeholderFontSize placeholderFontSize: root.placeholderFontSize
placeholderColor: root.placeholderColor placeholderColor: root.placeholderColor
placeholderOpacity: root.placeholderOpacity placeholderOpacity: root.placeholderOpacity
onEditingFinished: root.editingFinished() labelFontSize: root.labelFontSize
borderColor: lineEditBorderColor borderColor: lineEditBorderColor
backgroundColor: lineEditBackgroundColor backgroundColor: lineEditBackgroundColor
fontColor: lineEditFontColor fontColor: lineEditFontColor
fontBold: lineEditFontBold fontBold: lineEditFontBold
fontSize: lineEditFontSize
onEditingFinished: root.editingFinished()
} }
} }

View file

@ -32,6 +32,7 @@ import "../components" as MoneroComponents
Item { Item {
id: dropdown id: dropdown
property int itemTopMargin: 0
property alias dataModel: repeater.model property alias dataModel: repeater.model
property string shadowPressedColor property string shadowPressedColor
property string shadowReleasedColor property string shadowReleasedColor
@ -76,6 +77,7 @@ Item {
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
anchors.top: parent.top anchors.top: parent.top
anchors.topMargin: parent.itemTopMargin
height: dropdown.dropdownHeight height: dropdown.dropdownHeight
Rectangle { Rectangle {

View file

@ -11,7 +11,6 @@ QtObject {
property string grey: "#404040" property string grey: "#404040"
property string defaultFontColor: "white" property string defaultFontColor: "white"
property string greyFontColor: "#808080"
property string dimmedFontColor: "#BBBBBB" property string dimmedFontColor: "#BBBBBB"
property string inputBoxBackground: "black" property string inputBoxBackground: "black"
property string inputBoxBackgroundError: "#FFDDDD" property string inputBoxBackgroundError: "#FFDDDD"

63
components/WarningBox.qml Normal file
View file

@ -0,0 +1,63 @@
import QtQuick 2.7
import QtQuick.Layouts 1.1
import QtQuick.Controls 2.0
import "." as MoneroComponents
Rectangle {
id: root
property alias text: content.text
property int fontSize: 15 * scaleRatio
Layout.fillWidth: true
Layout.preferredHeight: warningLayout.height
color: "#09FFFFFF"
radius: 4
border.color: MoneroComponents.Style.inputBorderColorInActive
border.width: 1
signal linkActivated;
RowLayout {
id: warningLayout
spacing: 0
anchors.left: parent.left
anchors.right: parent.right
Image {
Layout.alignment: Qt.AlignVCenter
Layout.preferredHeight: 33
Layout.preferredWidth: 33
Layout.rightMargin: 14
Layout.leftMargin: 14
Layout.topMargin: 12
Layout.bottomMargin: 12
source: "../images/warning.png"
}
TextArea {
id: content
Layout.fillWidth: true
color: MoneroComponents.Style.defaultFontColor
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: root.fontSize
horizontalAlignment: TextInput.AlignLeft
selectByMouse: false
textFormat: Text.RichText
wrapMode: Text.WordWrap
textMargin: 0
leftPadding: 0
topPadding: 6
readOnly: true
onLinkActivated: root.linkActivated();
// @TODO: Legacy. Remove after Qt 5.8.
// https://stackoverflow.com/questions/41990013
MouseArea {
anchors.fill: parent
enabled: false
}
}
}
}

BIN
images/settings_local.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 651 B

BIN
images/settings_navbar_side.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
images/settings_remote.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 440 B

View file

@ -26,4 +26,31 @@ function formatDate( date, params ) {
function isNumeric(n) { function isNumeric(n) {
return !isNaN(parseFloat(n)) && isFinite(n); return !isNaN(parseFloat(n)) && isFinite(n);
}
function showSeedPage() {
// Shows `Settings->Seed & keys`. Prompts a password dialog.
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();
} }

View file

@ -11,12 +11,11 @@ function setCustomWindowDecorations(custom) {
var y = appWindow.y var y = appWindow.y
if (x < 0) x = 0 if (x < 0) x = 0
if (y < 0) y = 0 if (y < 0) y = 0
// Update persistentSettings // Update persistentSettings
persistentSettings.customDecorations = custom; persistentSettings.customDecorations = custom;
titleBar.visible = custom; titleBar.visible = custom;
daemonConsolePopup.titleBar.visible = custom;
if (custom) { if (custom) {
appWindow.flags = flagsCustomDecorations; appWindow.flags = flagsCustomDecorations;
@ -25,7 +24,7 @@ function setCustomWindowDecorations(custom) {
appWindow.flags = flags; appWindow.flags = flags;
daemonConsolePopup.flags = flags; daemonConsolePopup.flags = flags;
} }
// Reset window // Reset window
appWindow.hide() appWindow.hide()
appWindow.x = x appWindow.x = x

View file

@ -40,6 +40,7 @@ import moneroComponents.NetworkType 1.0
import "components" import "components"
import "wizard" import "wizard"
import "../js/Utils.js" as Utils
import "js/Windows.js" as Windows import "js/Windows.js" as Windows
ApplicationWindow { ApplicationWindow {
@ -1414,31 +1415,7 @@ ApplicationWindow {
updateBalance(); updateBalance();
} }
onKeysClicked: { onKeysClicked: Utils.showSeedPage();
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 { RightPanel {

View file

@ -128,7 +128,8 @@ Rectangle {
copyButton: true copyButton: true
addressValidation: false addressValidation: false
readOnly: true readOnly: true
wrapAnywhere: false wrapMode: Text.WordWrap
fontColor: "white"
} }
} }

View file

@ -1,818 +0,0 @@
// Copyright (c) 2014-2018, 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 "../js/Windows.js" as Windows
import "../js/Utils.js" as Utils
import "../components"
import moneroComponents.Clipboard 1.0
Rectangle {
property bool viewOnly: false
property alias settingsHeight: mainLayout.height
id: page
color: "transparent"
// fires on every page load
function onPageCompleted() {
console.log("Settings page loaded");
if(typeof daemonManager != "undefined"){
daemonRunning = persistentSettings.useRemoteNode ? false : appWindow.daemonRunning;
}
logLevelDropdown.update()
}
Clipboard { id: clipboard }
ColumnLayout {
id: mainLayout
anchors.margins: (isMobile)? 17 : 40
anchors.left: parent.left
anchors.top: parent.top
anchors.right: parent.right
spacing: 26 * scaleRatio
//! Manage wallet
RowLayout {
Layout.fillWidth: true
Label {
id: manageWalletLabel
fontSize: 22 * scaleRatio
Layout.fillWidth: true
text: qsTr("Manage wallet") + translationManager.emptyString
Layout.topMargin: 10 * scaleRatio
}
Rectangle {
anchors.top: manageWalletLabel.bottom
anchors.topMargin: 4
anchors.left: parent.left
anchors.right: parent.right
Layout.fillWidth: true
height: 2
color: Style.dividerColor
opacity: Style.dividerOpacity
}
}
GridLayout {
columns: (isMobile)? 1 : 4
StandardButton {
id: closeWalletButton
small: true
text: qsTr("Close wallet") + translationManager.emptyString
visible: true
onClicked: {
console.log("closing wallet button clicked")
appWindow.showWizard();
}
}
StandardButton {
id: createViewOnlyWalletButton
enabled: !viewOnly
small: true
text: qsTr("Create view only wallet") + translationManager.emptyString
visible: true
onClicked: {
wizard.openCreateViewOnlyWalletPage();
}
}
/* Rescan cache - Disabled until we know it's needed
StandardButton {
id: rescanWalletbutton
shadowReleasedColor: "#FF4304"
shadowPressedColor: "#B32D00"
releasedColor: "#FF6C3C"
pressedColor: "#FF4304"
text: qsTr("Rescan wallet cache") + translationManager.emptyString
onClicked: {
// Show confirmation dialog
confirmationDialog.title = qsTr("Rescan wallet cache") + translationManager.emptyString;
confirmationDialog.text = qsTr("Are you sure you want to rebuild the wallet cache?\n"
+ "The following information will be deleted\n"
+ "- Recipient addresses\n"
+ "- Tx keys\n"
+ "- Tx descriptions\n\n"
+ "The old wallet cache file will be renamed and can be restored later.\n"
);
confirmationDialog.icon = StandardIcon.Question
confirmationDialog.cancelText = qsTr("Cancel")
confirmationDialog.onAcceptedCallback = function() {
walletManager.closeWallet();
walletManager.clearWalletCache(persistentSettings.wallet_path);
walletManager.openWalletAsync(persistentSettings.wallet_path, appWindow.walletPassword,
persistentSettings.nettype);
}
confirmationDialog.onRejectedCallback = null;
confirmationDialog.open()
}
}
*/
StandardButton {
id: rescanSpentButton
small: true
enabled: !persistentSettings.useRemoteNode
text: qsTr("Rescan wallet balance") + translationManager.emptyString
onClicked: {
if (!currentWallet.rescanSpent()) {
console.error("Error: ", currentWallet.errorString);
informationPopup.title = qsTr("Error") + translationManager.emptyString;
informationPopup.text = qsTr("Error: ") + currentWallet.errorString
informationPopup.icon = StandardIcon.Critical
informationPopup.onCloseCallback = null
informationPopup.open();
} else {
informationPopup.title = qsTr("Information") + translationManager.emptyString
informationPopup.text = qsTr("Successfully rescanned spent outputs.") + translationManager.emptyString
informationPopup.icon = StandardIcon.Information
informationPopup.onCloseCallback = null
informationPopup.open();
}
}
}
}
RowLayout{
Layout.fillWidth: true
StandardButton {
id: changePasswordButton
small: true
text: qsTr("Change password") + translationManager.emptyString
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 {
Layout.fillWidth: true
LabelSubheader {
text: qsTr("Daemon mode") + translationManager.emptyString
}
}
ColumnLayout {
RadioButton {
id: remoteDisconnect
checked: !persistentSettings.useRemoteNode
text: qsTr("Local Node") + translationManager.emptyString
onClicked: {
persistentSettings.useRemoteNode = false;
remoteConnect.checked = false;
appWindow.disconnectRemoteNode();
}
}
RadioButton {
id: remoteConnect
checked: persistentSettings.useRemoteNode
text: qsTr("Remote Node") + translationManager.emptyString
onClicked: {
persistentSettings.useRemoteNode = true;
remoteDisconnect.checked = false;
appWindow.connectRemoteNode();
}
}
}
RowLayout {
visible: !isMobile && !persistentSettings.useRemoteNode
Layout.fillWidth: true
LabelSubheader {
text: qsTr("Bootstrap node") + translationManager.emptyString
}
}
RowLayout {
visible: !isMobile && !persistentSettings.useRemoteNode
ColumnLayout {
Layout.fillWidth: true
RemoteNodeEdit {
id: bootstrapNodeEdit
Layout.minimumWidth: 100 * scaleRatio
Layout.bottomMargin: 20 * scaleRatio
lineEditBackgroundColor: "transparent"
lineEditFontColor: "white"
lineEditBorderColor: Style.inputBorderColorActive
daemonAddrLabelText: qsTr("Address") + translationManager.emptyString
daemonPortLabelText: qsTr("Port") + translationManager.emptyString
daemonAddrText: persistentSettings.bootstrapNodeAddress.split(":")[0].trim()
daemonPortText: {
var node_split = persistentSettings.bootstrapNodeAddress.split(":");
if(node_split.length == 2){
(node_split[1].trim() == "") ? "18081" : node_split[1];
} else {
return ""
}
}
onEditingFinished: {
persistentSettings.bootstrapNodeAddress = daemonAddrText ? bootstrapNodeEdit.getAddress() : "";
console.log("setting bootstrap node to " + persistentSettings.bootstrapNodeAddress)
}
}
}
}
RowLayout {
visible: persistentSettings.useRemoteNode
ColumnLayout {
Layout.fillWidth: true
RemoteNodeEdit {
id: remoteNodeEdit
Layout.minimumWidth: 100 * scaleRatio
lineEditBackgroundColor: "transparent"
lineEditFontColor: "white"
lineEditBorderColor: Qt.rgba(255, 255, 255, 0.35)
daemonAddrLabelText: qsTr("Address")
daemonPortLabelText: qsTr("Port")
property var rna: persistentSettings.remoteNodeAddress
daemonAddrText: rna.search(":") != -1 ? rna.split(":")[0].trim() : ""
daemonPortText: rna.search(":") != -1 ? (rna.split(":")[1].trim() == "") ? "18081" : rna.split(":")[1] : ""
onEditingFinished: {
persistentSettings.remoteNodeAddress = remoteNodeEdit.getAddress();
console.log("setting remote node to " + persistentSettings.remoteNodeAddress)
}
}
}
}
RowLayout{
visible: persistentSettings.useRemoteNode
Layout.fillWidth: true
StandardButton {
id: remoteNodeSave
small: true
text: qsTr("Connect") + translationManager.emptyString
onClicked: {
// Update daemon login
persistentSettings.remoteNodeAddress = remoteNodeEdit.getAddress();
persistentSettings.daemonUsername = daemonUsername.text;
persistentSettings.daemonPassword = daemonPassword.text;
persistentSettings.useRemoteNode = true
currentWallet.setDaemonLogin(persistentSettings.daemonUsername, persistentSettings.daemonPassword);
appWindow.connectRemoteNode()
}
}
}
//! Manage daemon
RowLayout {
visible: !isMobile
Label {
id: manageDaemonLabel
fontSize: 22 * scaleRatio
text: qsTr("Manage Daemon") + translationManager.emptyString
}
Rectangle {
anchors.top: manageDaemonLabel.bottom
anchors.topMargin: 4
anchors.left: parent.left
anchors.right: parent.right
Layout.fillWidth: true
height: 2
color: Style.dividerColor
opacity: Style.dividerOpacity
}
}
GridLayout {
visible: !isMobile && !persistentSettings.useRemoteNode
id: daemonStatusRow
columns: (isMobile) ? 2 : 4
StandardButton {
id: startDaemonButton
small: true
visible: !daemonRunning
text: qsTr("Start Local Node") + translationManager.emptyString
onClicked: {
// Update bootstrap daemon address
persistentSettings.bootstrapNodeAddress = bootstrapNodeEdit.daemonAddrText ? bootstrapNodeEdit.getAddress() : "";
// Set current daemon address to local
appWindow.currentDaemonAddress = appWindow.localDaemonAddress;
appWindow.startDaemon(daemonFlags.text);
}
}
StandardButton {
id: stopDaemonButton
small: true
visible: daemonRunning
text: qsTr("Stop Local Node") + translationManager.emptyString
onClicked: {
appWindow.stopDaemon()
}
}
StandardButton {
id: daemonStatusButton
small: true
visible: true
text: qsTr("Show status") + translationManager.emptyString
onClicked: {
daemonManager.sendCommand("status",currentWallet.nettype);
daemonConsolePopup.open();
}
}
}
ColumnLayout {
id: blockchainFolderRow
visible: !isMobile && !persistentSettings.useRemoteNode
RowLayout {
Layout.fillWidth: true
Layout.bottomMargin: 14 * scaleRatio
LabelSubheader {
text: qsTr("Blockchain location") + translationManager.emptyString
}
}
RowLayout {
visible: persistentSettings.blockchainDataDir.length > 0
LineEdit {
id: blockchainFolder
Layout.preferredWidth: 200
Layout.fillWidth: true
text: persistentSettings.blockchainDataDir;
placeholderText: qsTr("(optional)") + translationManager.emptyString
}
}
RowLayout {
Layout.fillWidth: true
Layout.topMargin: 8
StandardButton {
id: blockchainFolderButton
small: true
visible: true
text: qsTr("Change location") + translationManager.emptyString
onClicked: {
//mouse.accepted = false
if(persistentSettings.blockchainDataDir != "")
blockchainFileDialog.folder = "file://" + persistentSettings.blockchainDataDir
blockchainFileDialog.open()
blockchainFolder.focus = true
}
}
}
}
RowLayout{
CheckBox {
id: daemonAdvanced
text: qsTr("Show advanced") + translationManager.emptyString
}
}
RowLayout {
visible: daemonAdvanced.checked && !isMobile && !persistentSettings.useRemoteNode
id: daemonFlagsRow
LineEdit {
id: daemonFlags
Layout.preferredWidth: 200
Layout.fillWidth: true
labelText: qsTr("Local daemon startup flags") + translationManager.emptyString
text: appWindow.persistentSettings.daemonFlags;
placeholderText: qsTr("(optional)") + translationManager.emptyString
}
}
ColumnLayout {
visible: (daemonAdvanced.checked || isMobile) && persistentSettings.useRemoteNode
GridLayout {
columns: (isMobile) ? 1 : 2
columnSpacing: 32
LineEdit {
id: daemonUsername
Layout.fillWidth: true
labelText: "Daemon username"
text: persistentSettings.daemonUsername
placeholderText: qsTr("Username") + translationManager.emptyString
}
LineEdit {
id: daemonPassword
Layout.fillWidth: true
labelText: "Daemon password"
text: persistentSettings.daemonPassword
placeholderText: qsTr("Password") + translationManager.emptyString
echoMode: TextInput.Password
}
}
}
RowLayout {
visible: !isMobile
Label {
id: layoutSettingsLabel
fontSize: 22 * scaleRatio
text: qsTr("Layout settings") + translationManager.emptyString
}
Rectangle {
anchors.top: layoutSettingsLabel.bottom
anchors.topMargin: 4
anchors.left: parent.left
anchors.right: parent.right
Layout.fillWidth: true
height: 2
color: Style.dividerColor
opacity: Style.dividerOpacity
}
}
RowLayout {
CheckBox {
visible: !isMobile
id: customDecorationsCheckBox
checked: persistentSettings.customDecorations
onClicked: Windows.setCustomWindowDecorations(checked)
text: qsTr("Custom decorations") + translationManager.emptyString
}
}
// Log level
RowLayout {
Label {
id: logLevelLabel
fontSize: 22 * scaleRatio
text: qsTr("Log level") + translationManager.emptyString
}
Rectangle {
anchors.top: logLevelLabel.bottom
anchors.topMargin: 4
anchors.left: parent.left
anchors.right: parent.right
Layout.fillWidth: true
height: 2
color: Style.dividerColor
opacity: Style.dividerOpacity
}
}
GridLayout {
columns: (isMobile)? 1 : 3
Layout.fillWidth: true
columnSpacing: 32
ColumnLayout {
spacing: 0
Layout.fillWidth: true
ListModel {
id: logLevel
ListElement { name: "none"; column1: "0"; }
ListElement { column1: "1"; }
ListElement { column1: "2"; }
ListElement { column1: "3"; }
ListElement { column1: "4"; }
ListElement { column1: "custom"; }
}
StandardDropdown {
id: logLevelDropdown
dataModel: logLevel
currentIndex: appWindow.persistentSettings.logLevel;
onChanged: {
if (currentIndex == 5) {
console.log("log categories changed: ", logCategories.text);
walletManager.setLogCategories(logCategories.text);
}
else {
console.log("log level changed: ",currentIndex);
walletManager.setLogLevel(currentIndex);
}
appWindow.persistentSettings.logLevel = currentIndex;
}
Layout.fillWidth: true
shadowReleasedColor: "#FF4304"
shadowPressedColor: "#B32D00"
releasedColor: "#363636"
pressedColor: "#202020"
}
// Make sure dropdown is on top
}
ColumnLayout {
Layout.fillWidth: true
}
ColumnLayout {
Layout.fillWidth: true
}
z: parent.z + 1
}
ColumnLayout {
LineEdit {
id: logCategories
Layout.fillWidth: true
text: appWindow.persistentSettings.logCategories
labelText: "Log Categories"
placeholderText: "(e.g. *:WARNING,net.p2p:DEBUG)"
enabled: logLevelDropdown.currentIndex === 5
onEditingFinished: {
if(enabled) {
console.log("log categories changed: ", text);
walletManager.setLogCategories(text);
appWindow.persistentSettings.logCategories = text;
}
}
}
}
// Version
RowLayout {
Label {
id: debugLabel
text: qsTr("Debug info") + translationManager.emptyString
fontSize: 22
anchors.topMargin: 30 * scaleRatio
Layout.topMargin: 30 * scaleRatio
}
Rectangle {
anchors.top: debugLabel.bottom
anchors.topMargin: 4
anchors.left: parent.left
anchors.right: parent.right
Layout.fillWidth: true
height: 2
color: Style.dividerColor
opacity: Style.dividerOpacity
}
}
GridLayout {
id: grid
columns: 2
columnSpacing: 20 * scaleRatio
TextBlock {
font.pixelSize: 14
text: qsTr("GUI version: ") + translationManager.emptyString
}
TextBlock {
font.pixelSize: 14
font.bold: true
text: Version.GUI_VERSION + " (Qt " + qtRuntimeVersion + ")" + translationManager.emptyString
}
TextBlock {
id: guiMoneroVersion
font.pixelSize: 14
text: qsTr("Embedded Monero version: ") + translationManager.emptyString
}
TextBlock {
font.pixelSize: 14
font.bold: true
text: Version.GUI_MONERO_VERSION + translationManager.emptyString
}
TextBlock {
Layout.fillWidth: true
font.pixelSize: 14
text: qsTr("Wallet name: ") + translationManager.emptyString
}
TextBlock {
Layout.fillWidth: true
font.pixelSize: 14
font.bold: true
text: walletName + translationManager.emptyString
}
TextBlock {
id: restoreHeight
font.pixelSize: 14
textFormat: Text.RichText
text: (typeof currentWallet == "undefined") ? "" : qsTr("Wallet creation height: ") + translationManager.emptyString
}
TextBlock {
id: restoreHeightText
textFormat: Text.RichText
font.pixelSize: 14
font.bold: true
property var style: "<style type='text/css'>a {cursor:pointer;text-decoration: none; color: #FF6C3C}</style>"
text: (currentWallet ? currentWallet.walletCreationHeight : "") + style + qsTr(" <a href='#'> (Click to change)</a>") + translationManager.emptyString
onLinkActivated: {
inputDialog.labelText = qsTr("Set a new restore height:") + translationManager.emptyString;
inputDialog.inputText = currentWallet ? currentWallet.walletCreationHeight : "0";
inputDialog.onAcceptedCallback = function() {
var _restoreHeight = inputDialog.inputText;
if(Utils.isNumeric(_restoreHeight)){
_restoreHeight = parseInt(_restoreHeight);
if(_restoreHeight >= 0) {
currentWallet.walletCreationHeight = _restoreHeight
// Restore height is saved in .keys file. Set password to trigger rewrite.
currentWallet.setPassword(appWindow.walletPassword)
// Show confirmation dialog
confirmationDialog.title = qsTr("Rescan wallet cache") + translationManager.emptyString;
confirmationDialog.text = qsTr("Are you sure you want to rebuild the wallet cache?\n"
+ "The following information will be deleted\n"
+ "- Recipient addresses\n"
+ "- Tx keys\n"
+ "- Tx descriptions\n\n"
+ "The old wallet cache file will be renamed and can be restored later.\n"
);
confirmationDialog.icon = StandardIcon.Question
confirmationDialog.cancelText = qsTr("Cancel")
confirmationDialog.onAcceptedCallback = function() {
walletManager.closeWallet();
walletManager.clearWalletCache(persistentSettings.wallet_path);
walletManager.openWalletAsync(persistentSettings.wallet_path, appWindow.walletPassword,
persistentSettings.nettype);
}
confirmationDialog.onRejectedCallback = null;
confirmationDialog.open()
return;
}
}
appWindow.showStatusMessage(qsTr("Invalid restore height specified. Must be a number."),3);
}
inputDialog.onRejectedCallback = null;
inputDialog.open()
}
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.NoButton
cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor
}
}
TextBlock {
Layout.fillWidth: true
font.pixelSize: 14
text: qsTr("Wallet log path: ") + translationManager.emptyString
}
TextBlock {
Layout.fillWidth: true
font.pixelSize: 14
text: walletLogPath
}
}
}
// Choose blockchain folder
FileDialog {
id: blockchainFileDialog
title: qsTr("Please choose a folder") + translationManager.emptyString;
selectFolder: true
folder: "file://" + persistentSettings.blockchainDataDir
onAccepted: {
var dataDir = walletManager.urlToLocalPath(blockchainFileDialog.fileUrl);
console.log(dataDir);
var validator = daemonManager.validateDataDir(dataDir);
if(!validator.valid) {
confirmationDialog.title = qsTr("Warning") + translationManager.emptyString;
confirmationDialog.text = "";
if(validator.readOnly) {
confirmationDialog.text += qsTr("Error: Filesystem is read only") + "\n\n"
}
if(validator.storageAvailable < estimatedBlockchainSize) {
confirmationDialog.text += qsTr("Warning: There's only %1 GB available on the device. Blockchain requires ~%2 GB of data.").arg(validator.storageAvailable).arg(estimatedBlockchainSize) + "\n\n"
} else {
confirmationDialog.text += qsTr("Note: There's %1 GB available on the device. Blockchain requires ~%2 GB of data.").arg(validator.storageAvailable).arg(estimatedBlockchainSize) + "\n\n"
}
if(!validator.lmdbExists) {
confirmationDialog.text += qsTr("Note: lmdb folder not found. A new folder will be created.") + "\n\n"
}
confirmationDialog.icon = StandardIcon.Question
confirmationDialog.cancelText = qsTr("Cancel")
// Continue
confirmationDialog.onAcceptedCallback = function() {
persistentSettings.blockchainDataDir = dataDir
}
// Cancel
confirmationDialog.onRejectedCallback = function() {
};
confirmationDialog.open()
} else {
persistentSettings.blockchainDataDir = dataDir
}
delete validator;
}
onRejected: {
console.log("data dir selection canceled")
}
}
// fires only once
Component.onCompleted: {
if(typeof daemonManager != "undefined")
daemonManager.daemonConsoleUpdated.connect(onDaemonConsoleUpdated)
}
function onDaemonConsoleUpdated(message){
// Update daemon console
daemonConsolePopup.textArea.logMessage(message)
}
}

View file

@ -33,6 +33,7 @@ import moneroComponents.Clipboard 1.0
import moneroComponents.PendingTransaction 1.0 import moneroComponents.PendingTransaction 1.0
import moneroComponents.Wallet 1.0 import moneroComponents.Wallet 1.0
import "../components" import "../components"
import "../components" as MoneroComponents
import "." 1.0 import "." 1.0
@ -43,6 +44,7 @@ Rectangle {
signal sweepUnmixableClicked() signal sweepUnmixableClicked()
color: "transparent" color: "transparent"
property string warningContent: ""
property string startLinkText: qsTr("<style type='text/css'>a {text-decoration: none; color: #FF6C3C; font-size: 14px;}</style><font size='2'> (</font><a href='#'>Start daemon</a><font size='2'>)</font>") + translationManager.emptyString property string startLinkText: qsTr("<style type='text/css'>a {text-decoration: none; color: #FF6C3C; font-size: 14px;}</style><font size='2'> (</font><a href='#'>Start daemon</a><font size='2'>)</font>") + translationManager.emptyString
property bool showAdvanced: false property bool showAdvanced: false
@ -122,47 +124,13 @@ Rectangle {
spacing: 30 * scaleRatio spacing: 30 * scaleRatio
RowLayout{ RowLayout {
visible: warningText.text !== "" visible: root.warningContent !== ""
Rectangle { MoneroComponents.WarningBox {
id: statusRect text: warningContent
Layout.preferredHeight: warningText.height + 40 onLinkActivated: {
Layout.fillWidth: true appWindow.startDaemon(appWindow.persistentSettings.daemonFlags);
radius: 2
border.color: Style.inputBorderColorInActive
border.width: 1
color: "transparent"
GridLayout{
Layout.fillWidth: true
Layout.preferredHeight: warningText.height + 40
Image {
Layout.alignment: Qt.AlignVCenter
Layout.preferredHeight: 33
Layout.preferredWidth: 33
Layout.leftMargin: 10
Layout.topMargin: 10
source: "../images/warning.png"
}
Text {
id: warningText
Layout.topMargin: 12 * scaleRatio
Layout.preferredWidth: statusRect.width - 80
Layout.leftMargin: 6
text: qsTr("This page lets you sign/verify a message (or file contents) with your address.") + translationManager.emptyString
wrapMode: Text.Wrap
font.family: Style.fontRegular.name
font.pixelSize: 14 * scaleRatio
color: Style.defaultFontColor
textFormat: Text.RichText
onLinkActivated: {
appWindow.startDaemon(appWindow.persistentSettings.daemonFlags);
}
}
} }
} }
} }
@ -255,6 +223,8 @@ Rectangle {
+ translationManager.emptyString + translationManager.emptyString
labelButtonText: qsTr("Resolve") + translationManager.emptyString labelButtonText: qsTr("Resolve") + translationManager.emptyString
placeholderText: "4.. / 8.." placeholderText: "4.. / 8.."
wrapMode: Text.WrapAnywhere
addressValidation: true
onInputLabelLinkActivated: { appWindow.showPageRequest("AddressBook") } onInputLabelLinkActivated: { appWindow.showPageRequest("AddressBook") }
} }
@ -319,17 +289,19 @@ Rectangle {
RowLayout { RowLayout {
// payment id input // payment id input
LineEdit { LineEditMulti {
id: paymentIdLine id: paymentIdLine
fontBold: true fontBold: true
labelText: qsTr("Payment ID <font size='2'>( Optional )</font>") + translationManager.emptyString labelText: qsTr("Payment ID <font size='2'>( Optional )</font>") + translationManager.emptyString
placeholderText: qsTr("16 or 64 hexadecimal characters") + translationManager.emptyString placeholderText: qsTr("16 or 64 hexadecimal characters") + translationManager.emptyString
Layout.fillWidth: true Layout.fillWidth: true
wrapMode: Text.WrapAnywhere
addressValidation: false
} }
} }
RowLayout { RowLayout {
LineEdit { LineEditMulti {
id: descriptionLine id: descriptionLine
labelText: qsTr("Description <font size='2'>( Optional )</font>") + translationManager.emptyString labelText: qsTr("Description <font size='2'>( Optional )</font>") + translationManager.emptyString
placeholderText: qsTr("Saved to local wallet history") + translationManager.emptyString placeholderText: qsTr("Saved to local wallet history") + translationManager.emptyString
@ -352,7 +324,7 @@ Rectangle {
} }
// There is no warning box displayed // There is no warning box displayed
if(warningText.text !== ''){ if(root.warningContent !== ''){
return false; return false;
} }
@ -707,7 +679,7 @@ Rectangle {
function updateStatus() { function updateStatus() {
pageRoot.enabled = true; pageRoot.enabled = true;
if(typeof currentWallet === "undefined") { if(typeof currentWallet === "undefined") {
warningText.text = qsTr("Wallet is not connected to daemon.") + root.startLinkText root.warningContent = qsTr("Wallet is not connected to daemon.") + root.startLinkText
return; return;
} }
@ -719,20 +691,20 @@ Rectangle {
switch (currentWallet.connected()) { switch (currentWallet.connected()) {
case Wallet.ConnectionStatus_Disconnected: case Wallet.ConnectionStatus_Disconnected:
warningText.text = qsTr("Wallet is not connected to daemon.") + root.startLinkText root.warningContent = qsTr("Wallet is not connected to daemon.") + root.startLinkText
break break
case Wallet.ConnectionStatus_WrongVersion: case Wallet.ConnectionStatus_WrongVersion:
warningText.text = qsTr("Connected daemon is not compatible with GUI. \n" + root.warningContent = qsTr("Connected daemon is not compatible with GUI. \n" +
"Please upgrade or connect to another daemon") "Please upgrade or connect to another daemon")
break break
default: default:
if(!appWindow.daemonSynced){ if(!appWindow.daemonSynced){
warningText.text = qsTr("Waiting on daemon synchronization to finish") root.warningContent = qsTr("Waiting on daemon synchronization to finish")
} else { } else {
// everything OK, enable transfer page // everything OK, enable transfer page
// Light wallet is always ready // Light wallet is always ready
pageRoot.enabled = true; pageRoot.enabled = true;
warningText.text = ""; root.warningContent = "";
} }
} }
} }

346
pages/settings/Navbar.qml Normal file
View file

@ -0,0 +1,346 @@
// Copyright (c) 2014-2018, 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 "../../js/Windows.js" as Windows
import "../../js/Utils.js" as Utils
import "../../components" as MoneroComponents
import "../../pages"
import "."
import moneroComponents.Clipboard 1.0
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 96
color: "transparent"
ColumnLayout {
spacing: 0
Layout.preferredHeight: 32
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
GridLayout {
id: grid
anchors.horizontalCenter: parent.horizontalCenter
columnSpacing: 0
property string fontColor: "white"
property int fontSize: 13 * scaleRatio
property bool fontBold: true
property var fontFamily: MoneroComponents.Style.fontRegular.name
property string borderColor: "#808080"
property int textMargin: {
// left-right margins for a given cell
if(isMobile){
return 10;
} else if(appWindow.width < 890){
return 32;
} else {
return 64;
}
}
Image {
Layout.preferredWidth: 2
Layout.preferredHeight: 32
source: {
if(settingsStateView.state === "Wallet"){
return "../../images/settings_navbar_side_active.png"
} else {
return "../../images/settings_navbar_side.png"
}
}
}
ColumnLayout {
// WALLET
id: navWallet
Layout.preferredWidth: navWalletText.width + grid.textMargin
Layout.minimumWidth: 72 * scaleRatio
Layout.preferredHeight: 32
spacing: 0
Rectangle {
color: grid.borderColor
Layout.preferredHeight: 1
Layout.fillWidth: true
}
Rectangle {
color: settingsStateView.state === "Wallet" ? grid.borderColor : "transparent"
height: 30 * scaleRatio
Layout.fillWidth: true
Text {
id: navWalletText
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
font.family: grid.fontFamily
font.pixelSize: grid.fontSize
font.bold: grid.fontBold
text: qsTr("Wallet") + translationManager.emptyString
color: grid.fontColor
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: { settingsStateView.state = "Wallet" }
}
}
Rectangle {
color: grid.borderColor
Layout.preferredHeight: 1
Layout.fillWidth: true
}
}
Rectangle{
Layout.preferredWidth: 1
Layout.preferredHeight: 32
color: grid.borderColor
}
ColumnLayout {
// UI
id: navUI
Layout.preferredWidth: navUIText.width + grid.textMargin
Layout.preferredHeight: 32
Layout.minimumWidth: 72 * scaleRatio
spacing: 0
Rectangle {
color: grid.borderColor
Layout.preferredHeight: 1
Layout.fillWidth: true
}
Rectangle {
color: settingsStateView.state === "UI" ? grid.borderColor : "transparent"
height: 30 * scaleRatio
Layout.fillWidth: true
Text {
id: navUIText
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
font.family: grid.fontFamily
font.pixelSize: grid.fontSize
font.bold: grid.fontBold
text: qsTr("Layout") + translationManager.emptyString
color: grid.fontColor
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: { settingsStateView.state = "UI" }
}
}
Rectangle {
color: grid.borderColor
Layout.preferredHeight: 1
Layout.fillWidth: true
}
}
Rectangle{
Layout.preferredWidth: 1
Layout.preferredHeight: 32
color: grid.borderColor
}
ColumnLayout {
// NODE
id: navNode
Layout.preferredWidth: navNodeText.width + grid.textMargin
Layout.preferredHeight: 32
Layout.minimumWidth: 72 * scaleRatio
spacing: 0
Rectangle {
color: grid.borderColor
Layout.preferredHeight: 1
Layout.fillWidth: true
}
Rectangle {
color: settingsStateView.state === "Node" ? grid.borderColor : "transparent"
height: 30 * scaleRatio
Layout.fillWidth: true
Text {
id: navNodeText
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
font.family: grid.fontFamily
font.pixelSize: grid.fontSize
font.bold: grid.fontBold
text: qsTr("Node") + translationManager.emptyString
color: grid.fontColor
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: { settingsStateView.state = "Node" }
}
}
Rectangle {
color: grid.borderColor
Layout.preferredHeight: 1
Layout.fillWidth: true
}
}
Rectangle{
Layout.preferredWidth: 1
Layout.preferredHeight: 32
color: grid.borderColor
}
ColumnLayout {
// LOG
id: navLog
Layout.preferredWidth: navLogText.width + grid.textMargin
Layout.preferredHeight: 32
Layout.minimumWidth: 72 * scaleRatio
spacing: 0
Rectangle {
color: grid.borderColor
Layout.preferredHeight: 1
Layout.fillWidth: true
}
Rectangle {
color: settingsStateView.state === "Log" ? grid.borderColor : "transparent"
height: 30 * scaleRatio
Layout.fillWidth: true
Text {
id: navLogText
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
font.family: grid.fontFamily
font.pixelSize: grid.fontSize
font.bold: grid.fontBold
text: qsTr("Log") + translationManager.emptyString
color: grid.fontColor
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: { settingsStateView.state = "Log" }
}
}
Rectangle {
color: grid.borderColor
Layout.preferredHeight: 1
Layout.fillWidth: true
}
}
Rectangle{
Layout.preferredWidth: 1
Layout.preferredHeight: 32
color: grid.borderColor
}
ColumnLayout {
// INFO
id: navInfo
Layout.preferredWidth: navInfoText.width + grid.textMargin
Layout.preferredHeight: 32
Layout.minimumWidth: 72 * scaleRatio
spacing: 0
Rectangle {
color: grid.borderColor
Layout.preferredHeight: 1
Layout.fillWidth: true
}
Rectangle {
color: settingsStateView.state === "Info" ? grid.borderColor : "transparent"
height: 30 * scaleRatio
Layout.fillWidth: true
Text {
id: navInfoText
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
font.family: grid.fontFamily
font.pixelSize: grid.fontSize
font.bold: grid.fontBold
text: qsTr("Info") + translationManager.emptyString
color: grid.fontColor
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: { settingsStateView.state = "Info" }
}
}
Rectangle {
color: grid.borderColor
Layout.preferredHeight: 1
Layout.fillWidth: true
}
}
Image {
Layout.preferredWidth: 2
Layout.preferredHeight: 32
source: {
if(settingsStateView.state === "Info"){
return "../../images/settings_navbar_side_active.png"
} else {
return "../../images/settings_navbar_side.png"
}
}
rotation: 180
}
Rectangle {
color: "transparent"
Layout.fillWidth: true
}
}
}
}

139
pages/settings/Settings.qml Normal file
View file

@ -0,0 +1,139 @@
// Copyright (c) 2014-2018, 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 "../../js/Windows.js" as Windows
import "../../js/Utils.js" as Utils
import "../../components" as MoneroComponents
import "../../pages"
import "."
import moneroComponents.Clipboard 1.0
ColumnLayout {
id: settingsPage
Layout.fillWidth: true
Layout.preferredHeight: 900
spacing: 0
Clipboard { id: clipboard }
property bool viewOnly: false
property int settingsHeight: 900
Navbar{}
Rectangle{
id: settingsStateView
property Item currentView
property Item previousView
property SettingsWallet settingsWalletView: SettingsWallet { }
property SettingsLayout settingsLayoutView: SettingsLayout { }
property SettingsNode settingsNodeView: SettingsNode { }
property SettingsLog settingsLogView: SettingsLog { }
property SettingsInfo settingsInfoView: SettingsInfo { }
Layout.fillWidth: true
Layout.preferredHeight: parent.height
color: "transparent"
state: "Wallet"
onCurrentViewChanged: {
if (previousView) {
// if (typeof previousView.onPageClosed === "function") {
// previousView.onPageClosed();
// }
}
previousView = currentView
if (currentView) {
stackView.replace(currentView)
// Component.onCompleted is called before wallet is initilized
// if (typeof currentView.onPageCompleted === "function") {
// currentView.onPageCompleted();
// }
}
}
states: [
State {
name: "Wallet"
PropertyChanges { target: settingsStateView; currentView: settingsStateView.settingsWalletView }
}, State {
name: "UI"
PropertyChanges { target: settingsStateView; currentView: settingsStateView.settingsLayoutView }
}, State {
name: "Node"
PropertyChanges { target: settingsStateView; currentView: settingsStateView.settingsNodeView }
}, State {
name: "Log"
PropertyChanges { target: settingsStateView; currentView: settingsStateView.settingsLogView }
}, State {
name: "Info"
PropertyChanges { target: settingsStateView; currentView: settingsStateView.settingsInfoView }
}
]
StackView {
id: stackView
initialItem: settingsStateView.settingsWalletView
anchors.fill: parent
clip: false // otherwise animation will affect left panel
delegate: StackViewDelegate {
pushTransition: StackViewTransition {
PropertyAnimation {
target: enterItem
property: "x"
from: 0 - target.width
to: 0
duration: 300
easing.type: Easing.OutCubic
}
PropertyAnimation {
target: exitItem
property: "x"
from: 0
to: target.width
duration: 300
easing.type: Easing.OutCubic
}
}
}
}
}
function onDaemonConsoleUpdated(message){
// Update daemon console
settingsStateView.settingsLogView.consoleArea.logMessage(message)
}
// fires on every page load
function onPageCompleted() {
console.log("Settings page loaded");
}
}

View file

@ -0,0 +1,302 @@
// Copyright (c) 2014-2018, 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.7
import QtQuick.Layouts 1.1
import QtQuick.Controls 2.0
import QtQuick.Dialogs 1.2
import "../../js/Utils.js" as Utils
import "../../version.js" as Version
import "../../components" as MoneroComponents
Rectangle {
color: "transparent"
height: 1400
Layout.fillWidth: true
ColumnLayout {
id: infoLayout
Layout.fillWidth: true
anchors.left: parent.left
anchors.top: parent.top
anchors.right: parent.right
anchors.margins: (isMobile)? 17 : 20
anchors.topMargin: 0
spacing: 30
GridLayout {
columns: 2
columnSpacing: 0
MoneroComponents.TextBlock {
font.pixelSize: 14
text: qsTr("GUI version: ") + translationManager.emptyString
}
MoneroComponents.TextBlock {
font.pixelSize: 14
text: Version.GUI_VERSION + " (Qt " + qtRuntimeVersion + ")" + translationManager.emptyString
}
Rectangle {
height: 1
Layout.topMargin: 2 * scaleRatio
Layout.bottomMargin: 2 * scaleRatio
Layout.fillWidth: true
color: MoneroComponents.Style.dividerColor
opacity: MoneroComponents.Style.dividerOpacity
}
Rectangle {
height: 1
Layout.topMargin: 2 * scaleRatio
Layout.bottomMargin: 2 * scaleRatio
Layout.fillWidth: true
color: MoneroComponents.Style.dividerColor
opacity: MoneroComponents.Style.dividerOpacity
}
MoneroComponents.TextBlock {
id: guiMoneroVersion
font.pixelSize: 14
text: qsTr("Embedded Monero version: ") + translationManager.emptyString
}
MoneroComponents.TextBlock {
font.pixelSize: 14
text: Version.GUI_MONERO_VERSION + translationManager.emptyString
}
Rectangle {
height: 1
Layout.topMargin: 2 * scaleRatio
Layout.bottomMargin: 2 * scaleRatio
Layout.fillWidth: true
color: MoneroComponents.Style.dividerColor
opacity: MoneroComponents.Style.dividerOpacity
}
Rectangle {
height: 1
Layout.topMargin: 2 * scaleRatio
Layout.bottomMargin: 2 * scaleRatio
Layout.fillWidth: true
color: MoneroComponents.Style.dividerColor
opacity: MoneroComponents.Style.dividerOpacity
}
MoneroComponents.TextBlock {
Layout.fillWidth: true
font.pixelSize: 14
text: qsTr("Wallet path: ") + translationManager.emptyString
}
MoneroComponents.TextBlock {
Layout.fillWidth: true
Layout.maximumWidth: 360
font.pixelSize: 14
text: {
var wallet_path = walletPath();
if(isIOS)
wallet_path = moneroAccountsDir + wallet_path;
return wallet_path;
}
}
Rectangle {
height: 1
Layout.topMargin: 2 * scaleRatio
Layout.bottomMargin: 2 * scaleRatio
Layout.fillWidth: true
color: MoneroComponents.Style.dividerColor
opacity: MoneroComponents.Style.dividerOpacity
}
Rectangle {
height: 1
Layout.topMargin: 2 * scaleRatio
Layout.bottomMargin: 2 * scaleRatio
Layout.fillWidth: true
color: MoneroComponents.Style.dividerColor
opacity: MoneroComponents.Style.dividerOpacity
}
MoneroComponents.TextBlock {
id: restoreHeight
font.pixelSize: 14
textFormat: Text.RichText
text: (typeof currentWallet == "undefined") ? "" : qsTr("Wallet creation height: ") + translationManager.emptyString
}
MoneroComponents.TextBlock {
id: restoreHeightText
Layout.fillWidth: true
textFormat: Text.RichText
font.pixelSize: 14
font.bold: true
property var style: "<style type='text/css'>a {cursor:pointer;text-decoration: none; color: #FF6C3C}</style>"
text: (currentWallet ? currentWallet.walletCreationHeight : "") + style + qsTr(" <a href='#'> (Click to change)</a>") + translationManager.emptyString
onLinkActivated: {
inputDialog.labelText = qsTr("Set a new restore height:") + translationManager.emptyString;
inputDialog.inputText = currentWallet ? currentWallet.walletCreationHeight : "0";
inputDialog.onAcceptedCallback = function() {
var _restoreHeight = inputDialog.inputText;
if(Utils.isNumeric(_restoreHeight)){
_restoreHeight = parseInt(_restoreHeight);
if(_restoreHeight >= 0) {
currentWallet.walletCreationHeight = _restoreHeight
// Restore height is saved in .keys file. Set password to trigger rewrite.
currentWallet.setPassword(appWindow.walletPassword)
// Show confirmation dialog
confirmationDialog.title = qsTr("Rescan wallet cache") + translationManager.emptyString;
confirmationDialog.text = qsTr("Are you sure you want to rebuild the wallet cache?\n"
+ "The following information will be deleted\n"
+ "- Recipient addresses\n"
+ "- Tx keys\n"
+ "- Tx descriptions\n\n"
+ "The old wallet cache file will be renamed and can be restored later.\n"
);
confirmationDialog.icon = StandardIcon.Question
confirmationDialog.cancelText = qsTr("Cancel")
confirmationDialog.onAcceptedCallback = function() {
walletManager.closeWallet();
walletManager.clearWalletCache(persistentSettings.wallet_path);
walletManager.openWalletAsync(persistentSettings.wallet_path, appWindow.walletPassword,
persistentSettings.nettype);
}
confirmationDialog.onRejectedCallback = null;
confirmationDialog.open()
return;
}
}
appWindow.showStatusMessage(qsTr("Invalid restore height specified. Must be a number."),3);
}
inputDialog.onRejectedCallback = null;
inputDialog.open()
}
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.NoButton
cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor
}
}
Rectangle {
height: 1
Layout.topMargin: 2 * scaleRatio
Layout.bottomMargin: 2 * scaleRatio
Layout.fillWidth: true
color: MoneroComponents.Style.dividerColor
opacity: MoneroComponents.Style.dividerOpacity
}
Rectangle {
height: 1
Layout.topMargin: 2 * scaleRatio
Layout.bottomMargin: 2 * scaleRatio
Layout.fillWidth: true
color: MoneroComponents.Style.dividerColor
opacity: MoneroComponents.Style.dividerOpacity
}
MoneroComponents.TextBlock {
Layout.fillWidth: true
font.pixelSize: 14
text: qsTr("Wallet log path: ") + translationManager.emptyString
}
MoneroComponents.TextBlock {
Layout.fillWidth: true
font.pixelSize: 14
text: walletLogPath
}
}
// Copy info to clipboard
Rectangle {
color: "transparent"
Layout.preferredHeight: 24 * scaleRatio
Layout.fillWidth: true
Rectangle {
id: rectCopy
color: MoneroComponents.Style.buttonBackgroundColorDisabled
width: btnCopy.width + 40
height: 24
radius: 2
Text {
id: btnCopy
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
color: MoneroComponents.Style.defaultFontColor
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 14 * scaleRatio
font.bold: true
text: qsTr("Copy to clipboard") + translationManager.emptyString
}
MouseArea {
cursorShape: Qt.PointingHandCursor
anchors.fill: parent
onClicked: {
var data = "";
data += "GUI version: " + Version.GUI_VERSION + " (Qt " + qtRuntimeVersion + ")";
data += "\nEmbedded Monero version: " + Version.GUI_MONERO_VERSION;
data += "\nWallet path: ";
var wallet_path = walletPath();
if(isIOS)
wallet_path = moneroAccountsDir + wallet_path;
data += wallet_path;
data += "\nWallet creation height: ";
if(currentWallet)
data += currentWallet.walletCreationHeight;
data += "\nWallet log path: " + walletLogPath;
console.log("Copied to clipboard");
clipboard.setText(data);
appWindow.showStatusMessage(qsTr("Copied to clipboard"), 3);
}
}
}
}
}
Component.onCompleted: {
}
}

View file

@ -0,0 +1,75 @@
// Copyright (c) 2014-2018, 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.7
import QtQuick.Layouts 1.1
import QtQuick.Controls 2.0
import QtQuick.Dialogs 1.2
import "../../js/Utils.js" as Utils
import "../../js/Windows.js" as Windows
import "../../components" as MoneroComponents
Rectangle {
color: "transparent"
height: 1400
Layout.fillWidth: true
ColumnLayout {
id: settingsUI
property int itemHeight: 60 * scaleRatio
Layout.fillWidth: true
anchors.left: parent.left
anchors.top: parent.top
anchors.right: parent.right
anchors.margins: (isMobile)? 17 : 20
anchors.topMargin: 0
spacing: 0
MoneroComponents.CheckBox {
visible: !isMobile
id: customDecorationsCheckBox
checked: persistentSettings.customDecorations
onClicked: Windows.setCustomWindowDecorations(checked)
text: qsTr("Custom decorations") + translationManager.emptyString
}
MoneroComponents.TextBlock {
visible: isMobile
font.pixelSize: 14
textFormat: Text.RichText
Layout.fillWidth: true
text: qsTr("No Layout options exist yet in mobile mode.") + translationManager.emptyString;
}
}
Component.onCompleted: {
console.log('SettingsLayout loaded');
}
}

View file

@ -0,0 +1,245 @@
// Copyright (c) 2014-2018, 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.7
import QtQuick.Layouts 1.1
import QtQuick.Controls 2.0
import "../../js/Utils.js" as Utils
import "../../components" as MoneroComponents
Rectangle {
property alias consoleArea: consoleArea
color: "transparent"
height: 1400
Layout.fillWidth: true
ColumnLayout {
id: settingsLog
property int itemHeight: 60 * scaleRatio
Layout.fillWidth: true
anchors.left: parent.left
anchors.top: parent.top
anchors.right: parent.right
anchors.margins: (isMobile)? 17 : 20
anchors.topMargin: 0
spacing: 10
// Rectangle {
// // divider
// Layout.preferredHeight: 1 * scaleRatio
// Layout.fillWidth: true
// Layout.bottomMargin: 8 * scaleRatio
// color: MoneroComponents.Style.dividerColor
// opacity: MoneroComponents.Style.dividerOpacity
// }
Text {
Layout.bottomMargin: 2 * scaleRatio
color: MoneroComponents.Style.defaultFontColor
font.pixelSize: 18 * scaleRatio
font.family: MoneroComponents.Style.fontRegular.name
text: qsTr("Log level") + translationManager.emptyString
}
GridLayout {
id: logGrid
columns: appWindow.persistentSettings.logLevel === 5 ? 2 : 1
Layout.fillWidth: true
columnSpacing: 32 * scaleRatio
z: parent.z + 1
ColumnLayout {
spacing: 0
Layout.fillWidth: true
ListModel {
id: logLevel
ListElement { column1: "0"; name: "none"; }
ListElement { column1: "1"; }
ListElement { column1: "2"; }
ListElement { column1: "3"; }
ListElement { column1: "4"; }
ListElement { column1: "custom"; }
}
MoneroComponents.StandardDropdown {
id: logLevelDropdown
dataModel: logLevel
itemTopMargin: 2 * scaleRatio
currentIndex: appWindow.persistentSettings.logLevel;
onChanged: {
if (currentIndex == 5) {
console.log("log categories changed: ", logCategories.text);
walletManager.setLogCategories(logCategories.text);
}
else {
console.log("log level changed: ",currentIndex);
walletManager.setLogLevel(currentIndex);
}
appWindow.persistentSettings.logLevel = currentIndex;
}
Layout.fillWidth: true
Layout.preferredWidth: logGrid.width / 2
shadowReleasedColor: "#FF4304"
shadowPressedColor: "#B32D00"
releasedColor: "#363636"
pressedColor: "#202020"
}
}
MoneroComponents.LineEdit {
id: logCategories
visible: persistentSettings.logLevel === 5
Layout.fillWidth: true
Layout.preferredWidth: logGrid.width / 2
text: appWindow.persistentSettings.logCategories
placeholderText: "(e.g. *:WARNING,net.p2p:DEBUG)"
placeholderFontSize: 14 * scaleRatio
fontSize: 14 * scaleRatio
enabled: logLevelDropdown.currentIndex === 5
onEditingFinished: {
if(enabled) {
console.log("log categories changed: ", text);
walletManager.setLogCategories(text);
appWindow.persistentSettings.logCategories = text;
}
}
}
}
Text {
Layout.topMargin: 10 * scaleRatio
Layout.bottomMargin: 2 * scaleRatio
color: MoneroComponents.Style.defaultFontColor
font.pixelSize: 18 * scaleRatio
font.family: MoneroComponents.Style.fontRegular.name
text: qsTr("Daemon log") + translationManager.emptyString
}
Flickable {
id: flickable
Layout.fillWidth: true
Layout.preferredHeight: 240 * scaleRatio
TextArea.flickable: TextArea {
id : consoleArea
anchors.fill: parent
color: MoneroComponents.Style.defaultFontColor
selectionColor: MoneroComponents.Style.dimmedFontColor
textFormat: TextEdit.RichText
selectByMouse: true
selectByKeyboard: true
font.family: "Ariel"
font.pixelSize: 14 * scaleRatio
wrapMode: TextEdit.Wrap
readOnly: true
background: Rectangle {
color: "transparent"
anchors.fill: parent
border.color: Qt.rgba(255, 255, 255, 0.25);
border.width: 1
radius: 4
}
function logCommand(msg){
msg = log_color(msg, "lime");
consoleArea.append(msg);
}
function logMessage(msg){
msg = msg.trim();
var color = "white";
if(msg.toLowerCase().indexOf('error') >= 0){
color = "red";
} else if (msg.toLowerCase().indexOf('warning') >= 0){
color = "yellow";
}
// format multi-lines
if(msg.split("\n").length >= 2){
msg = msg.split("\n").join('<br>');
}
log(msg, color);
}
function log_color(msg, color){
return "<span style='color: " + color + ";' >" + msg + "</span>";
}
function log(msg, color){
var timestamp = Utils.formatDate(new Date(), {
weekday: undefined,
month: "numeric",
timeZoneName: undefined
});
var _timestamp = log_color("[" + timestamp + "]", "#FFFFFF");
var _msg = log_color(msg, color);
consoleArea.append(_timestamp + " " + _msg);
// scroll to bottom
//if(flickable.contentHeight > content.height){
// flickable.contentY = flickable.contentHeight;
//}
}
}
ScrollBar.vertical: ScrollBar {
// TODO: scrollbar always visible is buggy.
// QT 5.9 introduces `policy: ScrollBar.AlwaysOn`
contentItem.opacity: 1
anchors.top: flickable.top
anchors.left: flickable.right
anchors.leftMargin: 10 * scaleRatio
anchors.bottom: flickable.bottom
}
}
MoneroComponents.LineEdit {
id: sendCommandText
Layout.fillWidth: true
fontBold: false
placeholderText: qsTr("command + enter (e.g 'help' or 'status')") + translationManager.emptyString
placeholderFontSize: 16 * scaleRatio
onAccepted: {
if(text.length > 0) {
consoleArea.logCommand(">>> " + text)
daemonManager.sendCommand(text, currentWallet.nettype);
}
text = ""
}
}
}
Component.onCompleted: {
logLevelDropdown.currentIndex = persistentSettings.logLevel;
logLevelDropdown.update();
if(typeof daemonManager != "undefined")
daemonManager.daemonConsoleUpdated.connect(onDaemonConsoleUpdated)
}
}

View file

@ -0,0 +1,497 @@
// Copyright (c) 2014-2018, 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.7
import QtQuick.Layouts 1.1
import QtQuick.Controls 2.0
import "../../components" as MoneroComponents
Rectangle{
color: "transparent"
height: 1400
Layout.fillWidth: true
/* main layout */
ColumnLayout {
id: root
anchors.margins: (isMobile)? 17 : 20
anchors.topMargin: 0
anchors.left: parent.left
anchors.top: parent.top
anchors.right: parent.right
spacing: 0 * scaleRatio
property int labelWidth: 120
property int editWidth: 400
property int lineEditFontSize: 14 * scaleRatio
property int buttonWidth: 110
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 90
color: "transparent"
Rectangle {
id: localNodeDivider
Layout.fillWidth: true
anchors.topMargin: 0 * scaleRatio
anchors.left: parent.left
anchors.right: parent.right
height: 1
color: MoneroComponents.Style.dividerColor
opacity: MoneroComponents.Style.dividerOpacity
}
Rectangle {
visible: !persistentSettings.useRemoteNode
Layout.fillHeight: true
anchors.top: parent.top
anchors.bottom: parent.bottom
color: "white"
width: 2
}
Rectangle {
width: parent.width
height: localNodeHeader.height + localNodeArea.contentHeight
color: "transparent";
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
Rectangle {
id: localNodeIcon
color: "transparent"
height: 32
width: 32
anchors.left: parent.left
anchors.leftMargin: 16 * scaleRatio
anchors.verticalCenter: parent.verticalCenter
Image{
height: 27
width: 27
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
source: "../../images/settings_local.png"
}
}
Text {
id: localNodeHeader
anchors.left: localNodeIcon.right
anchors.leftMargin: 14 * scaleRatio
anchors.top: parent.top
color: "white"
font.bold: true
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 16 * scaleRatio
text: qsTr("Local node") + translationManager.emptyString
}
TextArea {
id: localNodeArea
anchors.top: localNodeHeader.bottom
anchors.topMargin: 4 * scaleRatio
anchors.left: localNodeIcon.right
anchors.leftMargin: 14 * scaleRatio
color: MoneroComponents.Style.dimmedFontColor
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 15 * scaleRatio
horizontalAlignment: TextInput.AlignLeft
selectByMouse: false
wrapMode: Text.WordWrap;
textMargin: 0
leftPadding: 0
topPadding: 0
text: qsTr("The blockchain is downloaded to your computer. Provides higher security and requires more local storage.") + translationManager.emptyString
width: parent.width - (localNodeIcon.width + localNodeIcon.anchors.leftMargin + anchors.leftMargin)
// @TODO: Legacy. Remove after Qt 5.8.
// https://stackoverflow.com/questions/41990013
MouseArea {
anchors.fill: parent
enabled: false
}
}
}
MouseArea {
cursorShape: Qt.PointingHandCursor
anchors.fill: parent
onClicked: {
persistentSettings.useRemoteNode = false;
appWindow.disconnectRemoteNode();
}
}
}
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 90
color: "transparent"
Rectangle {
id: remoteNodeDivider
Layout.fillWidth: true
anchors.topMargin: 0 * scaleRatio
anchors.left: parent.left
anchors.right: parent.right
height: 1
color: MoneroComponents.Style.dividerColor
opacity: MoneroComponents.Style.dividerOpacity
}
Rectangle {
visible: persistentSettings.useRemoteNode
Layout.fillHeight: true
anchors.top: parent.top
anchors.bottom: parent.bottom
color: "white"
width: 2
}
Rectangle {
width: parent.width
height: remoteNodeHeader.height + remoteNodeArea.contentHeight
color: "transparent";
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
Rectangle {
id: remoteNodeIcon
color: "transparent"
height: 32
width: 32
anchors.left: parent.left
anchors.leftMargin: 16 * scaleRatio
anchors.verticalCenter: parent.verticalCenter
Image{
height: 27
width: 22
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
source: "../../images/settings_remote.png"
}
}
Text {
id: remoteNodeHeader
anchors.left: remoteNodeIcon.right
anchors.leftMargin: 14 * scaleRatio
anchors.top: parent.top
color: "white"
font.bold: true
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 16 * scaleRatio
text: qsTr("Remote node") + translationManager.emptyString
}
TextArea {
id: remoteNodeArea
anchors.top: remoteNodeHeader.bottom
anchors.topMargin: 4 * scaleRatio
anchors.left: remoteNodeIcon.right
anchors.leftMargin: 14 * scaleRatio
color: MoneroComponents.Style.dimmedFontColor
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 15 * scaleRatio
activeFocusOnPress: false
horizontalAlignment: TextInput.AlignLeft
selectByMouse: false
wrapMode: Text.WordWrap;
textMargin: 0
leftPadding: 0
topPadding: 0
text: qsTr("Uses a third-party server to connect to the Monero network. Less secure, but easier on your computer.") + translationManager.emptyString
width: parent.width - (remoteNodeIcon.width + remoteNodeIcon.anchors.leftMargin + anchors.leftMargin)
// @TODO: Legacy. Remove after Qt 5.8.
// https://stackoverflow.com/questions/41990013
MouseArea {
anchors.fill: parent
enabled: false
}
}
MouseArea {
cursorShape: Qt.PointingHandCursor
anchors.fill: parent
onClicked: {
persistentSettings.useRemoteNode = true;
appWindow.connectRemoteNode();
}
}
}
Rectangle {
id: localNodeBottomDivider
Layout.fillWidth: true
anchors.topMargin: 0 * scaleRatio
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
height: 1
color: MoneroComponents.Style.dividerColor
opacity: MoneroComponents.Style.dividerOpacity
}
}
ColumnLayout {
id: remoteNodeLayout
anchors.margins: 0
spacing: 20 * scaleRatio
Layout.fillWidth: true
Layout.topMargin: 20
visible: !isMobile && persistentSettings.useRemoteNode
MoneroComponents.WarningBox {
Layout.topMargin: 26 * scaleRatio
Layout.bottomMargin: 6 * scaleRatio
text: qsTr("To find a remote node, type 'Monero remote node' into your favorite search engine. Please ensure the node is run by a trusted third-party.") + translationManager.emptyString
}
MoneroComponents.RemoteNodeEdit {
id: remoteNodeEdit
Layout.minimumWidth: 100 * scaleRatio
lineEditBackgroundColor: "transparent"
lineEditFontColor: "white"
lineEditFontBold: false
lineEditBorderColor: Qt.rgba(255, 255, 255, 0.35)
labelFontSize: 14 * scaleRatio
placeholderFontSize: 15 * scaleRatio
daemonAddrLabelText: qsTr("Address")
daemonPortLabelText: qsTr("Port")
property var rna: persistentSettings.remoteNodeAddress
daemonAddrText: rna.search(":") != -1 ? rna.split(":")[0].trim() : ""
daemonPortText: rna.search(":") != -1 ? (rna.split(":")[1].trim() == "") ? "18081" : rna.split(":")[1] : ""
onEditingFinished: {
persistentSettings.remoteNodeAddress = remoteNodeEdit.getAddress();
console.log("setting remote node to " + persistentSettings.remoteNodeAddress)
}
}
GridLayout {
columns: (isMobile) ? 1 : 2
columnSpacing: 32
MoneroComponents.LineEdit {
id: daemonUsername
Layout.fillWidth: true
labelText: "Daemon username"
text: persistentSettings.daemonUsername
placeholderText: qsTr("(optional)") + translationManager.emptyString
placeholderFontSize: 15 * scaleRatio
labelFontSize: 14 * scaleRatio
fontSize: 15 * scaleRatio
}
MoneroComponents.LineEdit {
id: daemonPassword
Layout.fillWidth: true
labelText: "Daemon password"
text: persistentSettings.daemonPassword
placeholderText: qsTr("Password") + translationManager.emptyString
echoMode: TextInput.Password
placeholderFontSize: 15 * scaleRatio
labelFontSize: 14 * scaleRatio
fontSize: 15 * scaleRatio
}
}
Rectangle {
id: rectConnectRemote
Layout.topMargin: 12 * scaleRatio
color: MoneroComponents.Style.buttonBackgroundColorDisabled
width: btnConnectRemote.width + 40
height: 26
radius: 2
Text {
id: btnConnectRemote
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
color: MoneroComponents.Style.defaultFontColor
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 14 * scaleRatio
font.bold: true
text: qsTr("Connect") + translationManager.emptyString
}
MouseArea {
cursorShape: Qt.PointingHandCursor
anchors.fill: parent
onClicked: {
// Update daemon login
persistentSettings.remoteNodeAddress = remoteNodeEdit.getAddress();
persistentSettings.daemonUsername = daemonUsername.text;
persistentSettings.daemonPassword = daemonPassword.text;
persistentSettings.useRemoteNode = true
currentWallet.setDaemonLogin(persistentSettings.daemonUsername, persistentSettings.daemonPassword);
appWindow.connectRemoteNode()
}
}
}
}
ColumnLayout {
id: localNodeLayout
anchors.margins: 0
spacing: 20 * scaleRatio
Layout.topMargin: 40
anchors.left: parent.left
anchors.right: parent.right
visible: !isMobile && !persistentSettings.useRemoteNode
Rectangle {
color: "transparent"
Layout.topMargin: 0 * scaleRatio
Layout.bottomMargin: 8 * scaleRatio
Layout.preferredHeight: 24 * scaleRatio
Layout.preferredWidth: parent.width
Rectangle {
id: rectStopNode
color: MoneroComponents.Style.buttonBackgroundColorDisabled
width: btnStopNode.width + 40
height: 24
radius: 2
Text {
id: btnStopNode
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
color: MoneroComponents.Style.defaultFontColor
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 14 * scaleRatio
font.bold: true
text: qsTr("Stop local node") + translationManager.emptyString
}
MouseArea {
cursorShape: Qt.PointingHandCursor
anchors.fill: parent
onClicked: {
appWindow.stopDaemon();
}
}
}
}
RowLayout {
MoneroComponents.LineEditMulti {
id: blockchainFolder
Layout.preferredWidth: 200
Layout.fillWidth: true
fontSize: 15 * scaleRatio
labelFontSize: 14 * scaleRatio
property string style: "<style type='text/css'>a {cursor:pointer;text-decoration: none; color: #FF6C3C}</style>"
labelText: qsTr("Blockchain location") + style + qsTr(" <a href='#'> (change)</a>") + translationManager.emptyString
placeholderText: qsTr("(default)") + translationManager.emptyString
placeholderFontSize: 15 * scaleRatio
text: {
if(persistentSettings.blockchainDataDir.length > 0){
return persistentSettings.blockchainDataDir;
} else { return "" }
}
addressValidation: false
onInputLabelLinkActivated: {
//mouse.accepted = false
if(persistentSettings.blockchainDataDir !== ""){
blockchainFileDialog.folder = "file://" + persistentSettings.blockchainDataDir;
}
blockchainFileDialog.open();
blockchainFolder.focus = true;
}
}
}
RowLayout {
id: daemonFlagsRow
MoneroComponents.LineEditMulti {
id: daemonFlags
Layout.preferredWidth: 200
Layout.fillWidth: true
labelFontSize: 14 * scaleRatio
fontSize: 15 * scaleRatio
labelText: qsTr("Daemon startup flags") + translationManager.emptyString
placeholderText: qsTr("(optional)") + translationManager.emptyString
placeholderFontSize: 15 * scaleRatio
text: appWindow.persistentSettings.daemonFlags
addressValidation: false
}
}
RowLayout {
visible: !isMobile && !persistentSettings.useRemoteNode
ColumnLayout {
Layout.fillWidth: true
MoneroComponents.RemoteNodeEdit {
id: bootstrapNodeEdit
Layout.minimumWidth: 100 * scaleRatio
Layout.bottomMargin: 20 * scaleRatio
lineEditBackgroundColor: "transparent"
lineEditFontColor: "white"
lineEditBorderColor: MoneroComponents.Style.inputBorderColorActive
placeholderFontSize: 15 * scaleRatio
labelFontSize: 14 * scaleRatio
lineEditFontBold: false
lineEditFontSize: 15 * scaleRatio
daemonAddrLabelText: qsTr("Bootstrap Address")
daemonPortLabelText: qsTr("Bootstrap Port")
daemonAddrText: persistentSettings.bootstrapNodeAddress.split(":")[0].trim()
daemonPortText: {
var node_split = persistentSettings.bootstrapNodeAddress.split(":");
if(node_split.length == 2){
(node_split[1].trim() == "") ? "18081" : node_split[1];
} else {
return ""
}
}
onEditingFinished: {
persistentSettings.bootstrapNodeAddress = daemonAddrText ? bootstrapNodeEdit.getAddress() : "";
console.log("setting bootstrap node to " + persistentSettings.bootstrapNodeAddress)
}
}
}
}
}
}
}

View file

@ -0,0 +1,433 @@
// Copyright (c) 2014-2018, 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.7
import QtQuick.Layouts 1.1
import QtQuick.Controls 2.0
import QtQuick.Dialogs 1.2
import "../../js/Utils.js" as Utils
import "../../components" as MoneroComponents
Rectangle {
color: "transparent"
height: 1400
Layout.fillWidth: true
ColumnLayout {
id: settingsWallet
property int itemHeight: 60 * scaleRatio
Layout.fillWidth: true
anchors.left: parent.left
anchors.top: parent.top
anchors.right: parent.right
anchors.margins: (isMobile)? 17 : 20
anchors.topMargin: 0
spacing: 0
Rectangle {
// divider
Layout.preferredHeight: 1 * scaleRatio
Layout.fillWidth: true
Layout.bottomMargin: 8 * scaleRatio
color: MoneroComponents.Style.dividerColor
opacity: MoneroComponents.Style.dividerOpacity
}
GridLayout {
Layout.fillWidth: true
Layout.preferredHeight: settingsWallet.itemHeight
columnSpacing: 0
ColumnLayout {
Layout.fillWidth: true
anchors.verticalCenter: parent.verticalCenter
spacing: 0
Text {
Layout.fillWidth: true
Layout.preferredHeight: 20 * scaleRatio
Layout.topMargin: 8 * scaleRatio
color: "white"
font.bold: true
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 16 * scaleRatio
text: qsTr("Close this wallet") + translationManager.emptyString
}
TextArea {
Layout.fillWidth: true
color: MoneroComponents.Style.dimmedFontColor
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 14 * scaleRatio
horizontalAlignment: TextInput.AlignLeft
selectByMouse: false
wrapMode: Text.WordWrap;
textMargin: 0
leftPadding: 0
topPadding: 0
text: qsTr("Logs out of this wallet.") + translationManager.emptyString
width: parent.width
readOnly: true
// @TODO: Legacy. Remove after Qt 5.8.
// https://stackoverflow.com/questions/41990013
MouseArea {
anchors.fill: parent
enabled: false
}
}
}
Rectangle {
Layout.minimumWidth: 120 * scaleRatio
Layout.preferredWidth: closeWalletText.width + (20 * scaleRatio)
Layout.preferredHeight: parent.height
color: "transparent"
Rectangle{
width: parent.width
height: 24 * scaleRatio
radius: 2 * scaleRatio
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
color: MoneroComponents.Style.buttonBackgroundColorDisabled
Text {
id: closeWalletText
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
color: MoneroComponents.Style.defaultFontColor
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 14 * scaleRatio
font.bold: true
text: qsTr("Close wallet") + translationManager.emptyString
}
MouseArea {
cursorShape: Qt.PointingHandCursor
anchors.fill: parent
onClicked: {
appWindow.showWizard();
}
}
}
}
}
Rectangle {
// divider
Layout.preferredHeight: 1 * scaleRatio
Layout.fillWidth: true
Layout.topMargin: 8 * scaleRatio
Layout.bottomMargin: 8 * scaleRatio
color: MoneroComponents.Style.dividerColor
opacity: MoneroComponents.Style.dividerOpacity
}
GridLayout {
Layout.fillWidth: true
Layout.preferredHeight: settingsWallet.itemHeight
columnSpacing: 0
ColumnLayout {
Layout.fillWidth: true
anchors.verticalCenter: parent.verticalCenter
spacing: 0
Text {
Layout.fillWidth: true
Layout.preferredHeight: 20 * scaleRatio
Layout.topMargin: 8 * scaleRatio
color: "white"
font.bold: true
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 16 * scaleRatio
text: qsTr("Create a view-only wallet") + translationManager.emptyString
}
TextArea {
Layout.fillWidth: true
color: MoneroComponents.Style.dimmedFontColor
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 14 * scaleRatio
horizontalAlignment: TextInput.AlignLeft
selectByMouse: false
wrapMode: Text.WordWrap;
textMargin: 0
leftPadding: 0
topPadding: 0
text: qsTr("Creates a new wallet that can only view transactions, cannot initialize transactions.") + translationManager.emptyString
width: parent.width
readOnly: true
// @TODO: Legacy. Remove after Qt 5.8.
// https://stackoverflow.com/questions/41990013
MouseArea {
anchors.fill: parent
enabled: false
}
}
}
Rectangle {
Layout.minimumWidth: 120 * scaleRatio
Layout.preferredWidth: createViewOnlyText.width + (20 * scaleRatio)
Layout.preferredHeight: parent.height
color: "transparent"
Rectangle{
width: parent.width
height: 24 * scaleRatio
radius: 2 * scaleRatio
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
color: MoneroComponents.Style.buttonBackgroundColorDisabled
Text {
id: createViewOnlyText
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
color: MoneroComponents.Style.defaultFontColor
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 14 * scaleRatio
font.bold: true
text: qsTr("Create wallet") + translationManager.emptyString
}
MouseArea {
cursorShape: Qt.PointingHandCursor
anchors.fill: parent
onClicked: {
wizard.openCreateViewOnlyWalletPage();
}
}
}
}
}
Rectangle {
// divider
Layout.preferredHeight: 1 * scaleRatio
Layout.fillWidth: true
Layout.topMargin: 8 * scaleRatio
Layout.bottomMargin: 8 * scaleRatio
color: MoneroComponents.Style.dividerColor
opacity: MoneroComponents.Style.dividerOpacity
}
GridLayout {
Layout.fillWidth: true
Layout.preferredHeight: settingsWallet.itemHeight
columnSpacing: 0
ColumnLayout {
Layout.fillWidth: true
anchors.verticalCenter: parent.verticalCenter
spacing: 0
Text {
Layout.fillWidth: true
Layout.preferredHeight: 20 * scaleRatio
Layout.topMargin: 8 * scaleRatio
color: "white"
font.bold: true
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 16 * scaleRatio
text: qsTr("Show seed & keys") + translationManager.emptyString
}
TextArea {
Layout.fillWidth: true
color: MoneroComponents.Style.dimmedFontColor
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 14 * scaleRatio
horizontalAlignment: TextInput.AlignLeft
selectByMouse: false
wrapMode: Text.WordWrap;
textMargin: 0 * scaleRatio
leftPadding: 0
topPadding: 0
text: qsTr("Store this information safely to recover your wallet in the future.") + translationManager.emptyString
width: parent.width
readOnly: true
// @TODO: Legacy. Remove after Qt 5.8.
// https://stackoverflow.com/questions/41990013
MouseArea {
anchors.fill: parent
enabled: false
}
}
}
Rectangle {
Layout.minimumWidth: 120 * scaleRatio
Layout.preferredWidth: showSeedText.width + (20 * scaleRatio)
Layout.preferredHeight: parent.height
color: "transparent"
Rectangle{
width: parent.width
height: 24 * scaleRatio
radius: 2 * scaleRatio
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
color: MoneroComponents.Style.buttonBackgroundColorDisabled
Text {
id: showSeedText
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
color: MoneroComponents.Style.defaultFontColor
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 14 * scaleRatio
font.bold: true
text: qsTr("Show seed") + translationManager.emptyString
}
MouseArea {
cursorShape: Qt.PointingHandCursor
anchors.fill: parent
onClicked: Utils.showSeedPage();
}
}
}
}
Rectangle {
// divider
Layout.preferredHeight: 1 * scaleRatio
Layout.fillWidth: true
Layout.topMargin: 8 * scaleRatio
Layout.bottomMargin: 8 * scaleRatio
color: MoneroComponents.Style.dividerColor
opacity: MoneroComponents.Style.dividerOpacity
}
GridLayout {
Layout.fillWidth: true
Layout.preferredHeight: settingsWallet.itemHeight
columnSpacing: 0
ColumnLayout {
Layout.fillWidth: true
anchors.verticalCenter: parent.verticalCenter
spacing: 0
Text {
Layout.fillWidth: true
Layout.preferredHeight: 20 * scaleRatio
Layout.topMargin: 8 * scaleRatio
color: "white"
font.bold: true
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 16 * scaleRatio
text: qsTr("Rescan wallet balance") + translationManager.emptyString
}
TextArea {
Layout.fillWidth: true
color: MoneroComponents.Style.dimmedFontColor
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 14 * scaleRatio
horizontalAlignment: TextInput.AlignLeft
selectByMouse: false
wrapMode: Text.WordWrap;
textMargin: 0
leftPadding: 0
topPadding: 0
text: qsTr("Use this feature if you think the shown balance is not accurate.") + translationManager.emptyString
width: parent.width
readOnly: true
// @TODO: Legacy. Remove after Qt 5.8.
// https://stackoverflow.com/questions/41990013
MouseArea {
anchors.fill: parent
enabled: false
}
}
}
Rectangle {
Layout.minimumWidth: 120 * scaleRatio
Layout.preferredWidth: rescanButtonText.width + (20 * scaleRatio)
Layout.preferredHeight: parent.height
color: "transparent"
Rectangle{
width: parent.width
height: 24 * scaleRatio
radius: 2 * scaleRatio
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
color: MoneroComponents.Style.buttonBackgroundColorDisabled
Text {
id: rescanButtonText
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
color: MoneroComponents.Style.defaultFontColor
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 14 * scaleRatio
font.bold: true
text: qsTr("Rescan") + translationManager.emptyString
}
MouseArea {
cursorShape: Qt.PointingHandCursor
anchors.fill: parent
onClicked: {
if (!currentWallet.rescanSpent()) {
console.error("Error: ", currentWallet.errorString);
informationPopup.title = qsTr("Error") + translationManager.emptyString;
informationPopup.text = qsTr("Error: ") + currentWallet.errorString
informationPopup.icon = StandardIcon.Critical
informationPopup.onCloseCallback = null
informationPopup.open();
} else {
informationPopup.title = qsTr("Information") + translationManager.emptyString
informationPopup.text = qsTr("Successfully rescanned spent outputs.") + translationManager.emptyString
informationPopup.icon = StandardIcon.Information
informationPopup.onCloseCallback = null
informationPopup.open();
}
}
}
}
}
}
}
Component.onCompleted: {
console.log('SettingsWallet loaded');
}
}

13
qml.qrc
View file

@ -19,7 +19,6 @@
<file>pages/History.qml</file> <file>pages/History.qml</file>
<file>pages/AddressBook.qml</file> <file>pages/AddressBook.qml</file>
<file>pages/Mining.qml</file> <file>pages/Mining.qml</file>
<file>pages/Settings.qml</file>
<file>components/NetworkStatusItem.qml</file> <file>components/NetworkStatusItem.qml</file>
<file>images/statusConnected.png</file> <file>images/statusConnected.png</file>
<file>images/statusDisconnected.png</file> <file>images/statusDisconnected.png</file>
@ -210,5 +209,17 @@
<file>js/Utils.js</file> <file>js/Utils.js</file>
<file>components/RadioButton.qml</file> <file>components/RadioButton.qml</file>
<file>images/editIcon.png</file> <file>images/editIcon.png</file>
<file>pages/settings/Settings.qml</file>
<file>pages/settings/SettingsWallet.qml</file>
<file>pages/settings/SettingsNode.qml</file>
<file>pages/settings/SettingsLog.qml</file>
<file>pages/settings/SettingsLayout.qml</file>
<file>pages/settings/SettingsInfo.qml</file>
<file>pages/settings/Navbar.qml</file>
<file>images/settings_remote.png</file>
<file>images/settings_navbar_side.png</file>
<file>images/settings_navbar_side_active.png</file>
<file>images/settings_local.png</file>
<file>components/WarningBox.qml</file>
</qresource> </qresource>
</RCC> </RCC>