Compare commits

..

63 Commits

Author SHA1 Message Date
luigi1111
0461a28701 Merge pull request #2310
ff23a5b prices: improve error message (selsta)
2019-07-23 11:29:46 -05:00
luigi1111
a3b1590286 Merge pull request #2309
afe2b14 QML: fix more warnings (selsta)
2019-07-23 11:28:50 -05:00
luigi1111
b5cbb8b990 Merge pull request #2308
d4a6826 WizardController: make scrollbar visible (selsta)
2019-07-23 11:27:34 -05:00
selsta
ff23a5bf1e prices: improve error message 2019-07-23 01:00:40 +02:00
selsta
afe2b14430 QML: fix more warnings 2019-07-22 23:11:38 +02:00
selsta
d4a6826d13 WizardController: make scrollbar visible 2019-07-22 22:28:46 +02:00
luigi1111
8d17018019 set submodule v0.14.1.2 2019-07-22 13:40:20 -05:00
luigi1111
a65222d057 Merge pull request #2302
7e40a81 Account: fix theme switch label color (selsta)
2019-07-22 13:35:24 -05:00
luigi1111
25e56ee8fb Merge pull request #2307
f20ab12 QML: fix various warnings (selsta)
2019-07-22 13:29:31 -05:00
luigi1111
40c3e38f5a Merge pull request #2305
e6642c4 Account/Receive: update table on new entry (selsta)
2019-07-22 13:25:20 -05:00
luigi1111
f810c56100 Merge pull request #2303
5b81a1a Windows installer: Bumped the version number to 0.14.1.2 (rbrunner7)
2019-07-22 13:24:14 -05:00
luigi1111
95b3bb955c Merge pull request #2300
8f7d2b5 WizardAskPassword: improve label (selsta)
2019-07-22 13:21:50 -05:00
luigi1111
8db07974e2 Merge pull request #2299
e7653d0 updating the readme (parasew)
2019-07-22 13:20:41 -05:00
luigi1111
6c25650bbd Merge pull request #2297
7480f9b Changes Change wallet/Continue to Cancel/Ok (notmike-5)
2019-07-22 13:18:23 -05:00
luigi1111
4775fd74b8 Merge pull request #2294
ba33649 Fix segfault on Tails (tobtoht)
2019-07-22 13:11:15 -05:00
selsta
f20ab12cf3 QML: fix various warnings 2019-07-21 23:23:03 +02:00
selsta
e6642c4338 Account/Receive: update table on new entry 2019-07-21 21:17:18 +02:00
René Brunner
5b81a1a9d6 Windows installer: Bumped the version number to 0.14.1.2 2019-07-20 17:27:31 +02:00
selsta
7e40a810eb Account: fix theme switch label color 2019-07-20 02:54:16 +02:00
Matthias
e7653d0497 updating the readme 2019-07-19 18:03:48 +03:00
selsta
8f7d2b592a WizardAskPassword: improve label 2019-07-18 23:25:50 +02:00
notmike
7480f9b559 Changes Change wallet/Continue to Cancel/Ok
see #2290 #2204
2019-07-18 09:02:53 -06:00
thotbot
ba33649d7e Fix segfault on Tails 2019-07-18 13:22:38 +00:00
luigi1111
705439c78b Merge pull request #2289
cddba56 Fix project file (xmrdsc)
2019-07-16 11:50:11 -05:00
dsc
cddba56848 Fix project file 2019-07-16 18:47:12 +02:00
luigi1111
39fe5478b9 Merge pull request #2287
b96004a main: don't lock on inactivity if passwordDialog is visible (selsta)
2019-07-16 11:38:46 -05:00
luigi1111
cb3c310eb8 Merge pull request #2286
d2e7358 PasswordDialog: label improvements (selsta)
2019-07-16 11:37:19 -05:00
luigi1111
c426f1eb83 Merge pull request #2283
e04d563 src: fix compiler warnings (selsta)
2019-07-16 11:36:26 -05:00
luigi1111
beb94783c6 Merge pull request #2258
0b61328 Detect tails, support data persistence (xmrdsc)
2019-07-16 11:35:16 -05:00
dsc
0b61328971 Detect tails, support data persistence
Co-authored-by: Thotbot <thotbot@protonmail.com>
Co-authored-by: Selsta <selsta@sent.at>
2019-07-16 18:33:44 +02:00
selsta
b96004a101 main: don't lock on inactivity if passwordDialog is visible 2019-07-16 14:17:22 +02:00
selsta
d2e7358db7 PasswordDialog: label improvements 2019-07-16 14:08:22 +02:00
luigi1111
cfec9dde96 Merge pull request #2257
96c99b2 Replace Qt.labs.settings with MoneroSettings to allow for more customization (xmrdsc)
2019-07-15 23:38:56 -05:00
selsta
e04d563eb4 src: fix compiler warnings 2019-07-16 03:34:46 +02:00
dsc
96c99b250e Replace Qt.labs.settings with MoneroSettings to allow for more customization 2019-07-16 01:47:07 +02:00
luigi1111
4370733b2b Merge pull request #2282
d113bf1 main: fix password dialog overlay (selsta)
2019-07-15 18:43:33 -05:00
luigi1111
cac7662558 Merge pull request #2279
59550ec Windows installer: Achieve reproducible builds (rbrunner7)
2019-07-15 18:42:42 -05:00
luigi1111
0abd21b434 Merge pull request #2276
4b0d1dc Fixes #2275, transactionCommited txid list (ph4r05)
2019-07-15 18:41:19 -05:00
luigi1111
0d29ea33d8 Merge pull request #2256
817115f Start script for Tails (xmrdsc)
2019-07-15 18:39:39 -05:00
luigi1111
3a9f0e1100 Merge pull request #2240
35a0f25 PasswordDialog: merge components and bug fixes (selsta)
2019-07-15 18:38:32 -05:00
selsta
d113bf1a66 main: fix password dialog overlay 2019-07-15 21:56:57 +02:00
Dusan Klinec
4b0d1dcfbf Fixes #2275, transactionCommited txid list
txid list was empty when emitted
2019-07-15 16:17:21 +02:00
selsta
35a0f25b57 PasswordDialog: merge components and bug fixes
This commit merges PasswordDialog, PassphraseDialog and
NewPasswordDialog. Also the following bugs were fixed:

- Wizard pages still being active when opening a wallet
  from wizard.
- Capslock detection was buggy when copy pasting password, I
  replaced it with native implementations for each platform.
- isAlpha could throw errors when using special characters.
2019-07-15 00:05:10 +02:00
luigi1111
702b654f09 Merge pull request #2263
14619b9 History: don't reset date filtering when switching page (selsta)
2019-07-12 20:39:27 -05:00
luigi1111
f6de660e0e Merge pull request #2255
6baa963 NetworkStatusItem: simple mode has no node settings page (selsta)
2019-07-12 20:37:46 -05:00
luigi1111
b3402b3d4e Merge pull request #2251
5f5f210 History: dynamic number of tx rows (selsta)
2019-07-12 20:36:52 -05:00
luigi1111
5b411b471e Merge pull request #2250
84865cd History: allow to search for tx_note (selsta)
2019-07-12 20:35:29 -05:00
luigi1111
79dcb92d18 Merge pull request #2247
ab9e31e WalletManager: async close with splash screen (xiphon)
2019-07-12 20:34:10 -05:00
luigi1111
8bbc2e87bc Merge pull request #2246
c34a2b4 QML: fix warnings (selsta)
2019-07-12 20:33:22 -05:00
luigi1111
c10ea20f83 Merge pull request #2241
e1b4bcb build: minimum required qt version is 5.9 (selsta)
2019-07-12 20:32:14 -05:00
luigi1111
b4231a758c Merge pull request #2237
1b5796a WizardSummary: remove duplicated entry (selsta)
2019-07-12 20:31:17 -05:00
René Brunner
59550ec673 Windows installer: Achieve reproducible builds 2019-07-07 17:23:08 +02:00
selsta
6baa96360f NetworkStatusItem: simple mode has no node settings page 2019-07-05 20:57:19 +02:00
selsta
14619b9437 History: don't reset date filtering when switching page 2019-07-04 15:17:41 +02:00
dsc
817115fa47 Start script for Tails
Co-authored-by: thotbot <thotbot@protonmail.com>
2019-07-04 01:25:03 +02:00
selsta
5f5f2103c0 History: dynamic number of tx rows 2019-07-03 15:24:39 +02:00
selsta
84865cdead History: allow to search for tx_note 2019-07-03 13:54:01 +02:00
selsta
c34a2b43fc QML: fix warnings 2019-07-02 15:10:40 +02:00
xiphon
ab9e31e7cc WalletManager: async close with splash screen 2019-07-02 11:11:38 +00:00
selsta
e1b4bcb2ef build: minimum required qt version is 5.9 2019-07-01 14:40:20 +02:00
luigi1111
c4b3fbae1d Merge pull request #2235
9ab2922 Add vim generated files to gitignore (TheCharlatan)
2019-06-29 13:37:54 -05:00
selsta
1b5796a0ee WizardSummary: remove duplicated entry 2019-06-29 04:29:55 +02:00
TheCharlatan
9ab2922eb2 Add vim generated files to gitignore 2019-06-28 06:48:54 +02:00
54 changed files with 1055 additions and 898 deletions

19
.gitignore vendored
View File

@@ -13,3 +13,22 @@ monero-wallet-gui_plugin_import.cpp
monero-wallet-gui_qml_plugin_import.cpp
*.qmlc
*.jsc
### Vim ###
# Swap
[._]*.s[a-v][a-z]
[._]*.sw[a-p]
[._]s[a-rt-v][a-z]
[._]ss[a-gi-z]
[._]sw[a-p]
# Session
Session.vim
# Temporary
.netrwhist
*~
# Auto-generated tag files
tags
# Persistent undo
[._]*.un~

View File

@@ -114,13 +114,12 @@ Rectangle {
anchors.top: parent.top
anchors.topMargin: (persistentSettings.customDecorations)? 50 : 0
RowLayout {
Item {
Item {
anchors.left: parent.left
anchors.top: parent.top
anchors.topMargin: 20
anchors.leftMargin: 20
anchors.verticalCenter: parent.verticalCenter
height: 490
width: 260
@@ -230,7 +229,6 @@ Rectangle {
anchors.top: parent.top
anchors.topMargin: 20
anchors.leftMargin: 20
anchors.verticalCenter: parent.verticalCenter
height: 490
width: 50

View File

@@ -34,6 +34,7 @@
#include <QDebug>
#include "Logger.h"
#include "src/qt/TailsOS.h"
#include "wallet/api/wallet2_api.h"
// default log path by OS (should be writable)
@@ -66,6 +67,9 @@ const QString getLogPath(const QString logPath)
{
const QFileInfo fi(logPath);
if(TailsOS::detect() && TailsOS::usePersistence)
return QDir::homePath() + "/Persistent/Monero/logs/" + defaultLogName;
if(!logPath.isEmpty() && !fi.isDir())
return fi.absoluteFilePath();
else {

View File

@@ -209,13 +209,13 @@ Rectangle {
clip: true
ScrollBar.vertical: ScrollBar {
parent: mainFlickable.parent
parent: root
anchors.left: parent.right
anchors.leftMargin: 3
anchors.leftMargin: -14 // 10 margin + 4 scrollbar width
anchors.top: parent.top
anchors.topMargin: 4
anchors.topMargin: persistentSettings.customDecorations ? 60 : 10
anchors.bottom: parent.bottom
anchors.bottomMargin: persistentSettings.customDecorations ? 4 : 0
anchors.bottomMargin: persistentSettings.customDecorations ? 15 : 10
}
onFlickingChanged: {

View File

@@ -165,9 +165,8 @@ The executable can be found in the build/release/bin folder.
5. Add the Qt bin directory to your path
Example: `export PATH=$PATH:$HOME/Qt/5.9.7/clang_64/bin`
This is the directory where Qt 5.x is installed on **your** system
- Example for Qt: `export PATH=$PATH:$HOME/Qt/5.9.7/clang_64/bin`
- Example for Homebrew: `export PATH=$PATH:/usr/local/opt/qt/bin`
6. Grab an up-to-date copy of the monero-gui repository

View File

@@ -34,8 +34,6 @@ import "../components/effects/" as MoneroEffects
Label {
id: item
fontSize: 18
anchors.left: parent.left
anchors.right: parent.right
Rectangle {
anchors.top: item.bottom

View File

@@ -88,6 +88,7 @@ Rectangle {
}
MouseArea {
anchors.fill: parent
visible: appWindow.walletMode >= 2
cursorShape: Qt.PointingHandCursor
onClicked: {
if(!appWindow.isMining) {
@@ -133,6 +134,7 @@ Rectangle {
MouseArea {
anchors.fill: parent
visible: appWindow.walletMode >= 2
cursorShape: Qt.PointingHandCursor
onClicked: {
if(!appWindow.isMining) {

View File

@@ -1,287 +0,0 @@
// Copyright (c) 2014-2019, 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.9
import QtQuick.Controls 2.0
import QtQuick.Dialogs 1.2
import QtQuick.Layouts 1.1
import QtQuick.Controls.Styles 1.4
import QtQuick.Window 2.0
import FontAwesome 1.0
import "../components" as MoneroComponents
Item {
id: root
visible: false
z: parent.z + 2
property bool isHidden: true
property alias password: passwordInput1.text
// same signals as Dialog has
signal accepted()
signal rejected()
signal closeCallback()
function open() {
isHidden = true
passwordInput1.echoMode = TextInput.Password;
passwordInput2.echoMode = TextInput.Password;
inactiveOverlay.visible = true
leftPanel.enabled = false
middlePanel.enabled = false
titleBar.state = "essentials"
root.visible = true;
passwordInput1.text = "";
passwordInput2.text = "";
passwordInput1.focus = true
}
function close() {
inactiveOverlay.visible = false
leftPanel.enabled = true
middlePanel.enabled = true
titleBar.state = "default"
root.visible = false;
closeCallback();
}
function toggleIsHidden() {
passwordInput1.echoMode = isHidden ? TextInput.Normal : TextInput.Password;
passwordInput2.echoMode = isHidden ? TextInput.Normal : TextInput.Password;
isHidden = !isHidden;
}
// TODO: implement without hardcoding sizes
width: 480
height: 360
ColumnLayout {
z: inactiveOverlay.z + 1
id: mainLayout
spacing: 10
anchors { fill: parent; margins: 35 }
ColumnLayout {
id: column
Layout.fillWidth: true
Layout.alignment: Qt.AlignHCenter
Layout.maximumWidth: 400
Label {
text: qsTr("Please enter new password") + translationManager.emptyString
Layout.fillWidth: true
font.pixelSize: 16
font.family: MoneroComponents.Style.fontLight.name
color: MoneroComponents.Style.defaultFontColor
}
TextField {
id : passwordInput1
Layout.topMargin: 6
Layout.fillWidth: true
horizontalAlignment: TextInput.AlignLeft
verticalAlignment: TextInput.AlignVCenter
font.family: MoneroComponents.Style.fontLight.name
font.pixelSize: 24
echoMode: TextInput.Password
bottomPadding: 10
leftPadding: 10
topPadding: 10
color: MoneroComponents.Style.defaultFontColor
selectionColor: MoneroComponents.Style.textSelectionColor
selectedTextColor: MoneroComponents.Style.textSelectedColor
KeyNavigation.tab: passwordInput2
background: Rectangle {
radius: 2
border.color: MoneroComponents.Style.inputBorderColorInActive
border.width: 1
color: MoneroComponents.Style.blackTheme ? "black" : "#A9FFFFFF"
MoneroComponents.Label {
fontSize: 20
text: isHidden ? FontAwesome.eye : FontAwesome.eyeSlash
opacity: 0.7
fontFamily: FontAwesome.fontFamily
anchors.right: parent.right
anchors.rightMargin: 15
anchors.verticalCenter: parent.verticalCenter
anchors.verticalCenterOffset: 1
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
hoverEnabled: true
onClicked: {
toggleIsHidden()
}
onEntered: {
parent.opacity = 0.9
parent.fontSize = 24
}
onExited: {
parent.opacity = 0.7
parent.fontSize = 20
}
}
}
}
Keys.onEscapePressed: {
root.close()
root.rejected()
}
}
// padding
Rectangle {
Layout.fillWidth: true
Layout.alignment: Qt.AlignHCenter
height: 10
opacity: 0
color: "black"
}
Label {
text: qsTr("Please confirm new password") + translationManager.emptyString
Layout.fillWidth: true
font.pixelSize: 16
font.family: MoneroComponents.Style.fontLight.name
color: MoneroComponents.Style.defaultFontColor
}
TextField {
id : passwordInput2
Layout.topMargin: 6
Layout.fillWidth: true
horizontalAlignment: TextInput.AlignLeft
verticalAlignment: TextInput.AlignVCenter
font.family: MoneroComponents.Style.fontLight.name
font.pixelSize: 24
echoMode: TextInput.Password
KeyNavigation.tab: okButton
bottomPadding: 10
leftPadding: 10
topPadding: 10
color: MoneroComponents.Style.defaultFontColor
selectionColor: MoneroComponents.Style.textSelectionColor
selectedTextColor: MoneroComponents.Style.textSelectedColor
background: Rectangle {
radius: 2
border.color: MoneroComponents.Style.inputBorderColorInActive
border.width: 1
color: MoneroComponents.Style.blackTheme ? "black" : "#A9FFFFFF"
MoneroComponents.Label {
fontSize: 20
text: isHidden ? FontAwesome.eye : FontAwesome.eyeSlash
opacity: 0.7
fontFamily: FontAwesome.fontFamily
anchors.right: parent.right
anchors.rightMargin: 15
anchors.verticalCenter: parent.verticalCenter
anchors.verticalCenterOffset: 1
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
hoverEnabled: true
onClicked: {
toggleIsHidden()
}
onEntered: {
parent.opacity = 0.9
parent.fontSize = 24
}
onExited: {
parent.opacity = 0.7
parent.fontSize = 20
}
}
}
}
Keys.onReturnPressed: {
if (passwordInput1.text === passwordInput2.text) {
root.close()
root.accepted()
}
}
Keys.onEscapePressed: {
root.close()
root.rejected()
}
}
// padding
Rectangle {
Layout.fillWidth: true
Layout.alignment: Qt.AlignHCenter
height: 10
opacity: 0
color: "black"
}
// Ok/Cancel buttons
RowLayout {
id: buttons
spacing: 16
Layout.topMargin: 16
Layout.alignment: Qt.AlignRight
MoneroComponents.StandardButton {
id: cancelButton
text: qsTr("Cancel") + translationManager.emptyString
KeyNavigation.tab: passwordInput1
onClicked: {
root.close()
root.rejected()
}
}
MoneroComponents.StandardButton {
id: okButton
text: qsTr("Continue") + translationManager.emptyString
KeyNavigation.tab: cancelButton
enabled: passwordInput1.text === passwordInput2.text
onClicked: {
root.close()
root.accepted()
}
}
}
}
}
}

View File

@@ -1,321 +0,0 @@
// Copyright (c) 2014-2019, 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.Controls 2.0
import QtQuick.Dialogs 1.2
import QtQuick.Layouts 1.1
import QtQuick.Controls.Styles 1.4
import QtQuick.Window 2.0
import FontAwesome 1.0
import "../components" as MoneroComponents
Item {
id: root
visible: false
z: parent.z + 2
property bool isHidden: true
property alias passphrase: passphaseInput1.text
property string walletName
property string errorText
// same signals as Dialog has
signal accepted()
signal rejected()
signal closeCallback()
function open(walletName, errorText) {
isHidden = true
passphaseInput1.echoMode = TextInput.Password;
passphaseInput2.echoMode = TextInput.Password;
inactiveOverlay.visible = true
root.walletName = walletName ? walletName : ""
root.errorText = errorText ? errorText : "";
leftPanel.enabled = false
middlePanel.enabled = false
titleBar.state = "essentials"
root.visible = true;
passphaseInput1.text = "";
passphaseInput2.text = "";
passphaseInput1.focus = true
}
function close() {
inactiveOverlay.visible = false
leftPanel.enabled = true
middlePanel.enabled = true
titleBar.state = "default"
root.visible = false;
closeCallback();
}
function toggleIsHidden() {
passphaseInput1.echoMode = isHidden ? TextInput.Normal : TextInput.Password;
passphaseInput2.echoMode = isHidden ? TextInput.Normal : TextInput.Password;
isHidden = !isHidden;
}
function showError(errorText) {
open(root.walletName, errorText);
}
// TODO: implement without hardcoding sizes
width: 480
height: 360
ColumnLayout {
z: inactiveOverlay.z + 1
id: mainLayout
spacing: 10
anchors { fill: parent; margins: 35 }
ColumnLayout {
id: column
Layout.fillWidth: true
Layout.alignment: Qt.AlignHCenter
Layout.maximumWidth: 400
Label {
text: (root.walletName.length > 0 ? qsTr("Please enter wallet device passphrase for: ") + root.walletName : qsTr("Please enter wallet device passphrase")) + translationManager.emptyString
Layout.fillWidth: true
font.pixelSize: 16
font.family: MoneroComponents.Style.fontLight.name
color: MoneroComponents.Style.defaultFontColor
}
Label {
text: qsTr("Warning: passphrase entry on host is a security risk as it can be captured by malware. It is advised to prefer device-based passphrase entry.") + translationManager.emptyString
Layout.fillWidth: true
wrapMode: Text.Wrap
font.pixelSize: 14
font.family: MoneroComponents.Style.fontLight.name
color: MoneroComponents.Style.warningColor
}
Label {
text: root.errorText
visible: root.errorText
color: MoneroComponents.Style.errorColor
font.pixelSize: 16
font.family: MoneroComponents.Style.fontLight.name
Layout.fillWidth: true
wrapMode: Text.Wrap
}
TextField {
id : passphaseInput1
Layout.topMargin: 6
Layout.fillWidth: true
horizontalAlignment: TextInput.AlignLeft
verticalAlignment: TextInput.AlignVCenter
font.family: MoneroComponents.Style.fontLight.name
font.pixelSize: 24
echoMode: TextInput.Password
bottomPadding: 10
leftPadding: 10
topPadding: 10
color: MoneroComponents.Style.defaultFontColor
selectionColor: MoneroComponents.Style.textSelectionColor
selectedTextColor: MoneroComponents.Style.textSelectedColor
KeyNavigation.tab: passphaseInput2
background: Rectangle {
radius: 2
border.color: MoneroComponents.Style.inputBorderColorInActive
border.width: 1
color: MoneroComponents.Style.blackTheme ? "black" : "#A9FFFFFF"
MoneroComponents.Label {
fontSize: 20
text: isHidden ? FontAwesome.eye : FontAwesome.eyeSlash
opacity: 0.7
fontFamily: FontAwesome.fontFamily
anchors.right: parent.right
anchors.rightMargin: 15
anchors.verticalCenter: parent.verticalCenter
anchors.verticalCenterOffset: 1
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
hoverEnabled: true
onClicked: {
toggleIsHidden()
}
onEntered: {
parent.opacity = 0.9
parent.fontSize = 24
}
onExited: {
parent.opacity = 0.7
parent.fontSize = 20
}
}
}
}
Keys.onEscapePressed: {
root.close()
root.rejected()
}
}
// padding
Rectangle {
Layout.fillWidth: true
Layout.alignment: Qt.AlignHCenter
height: 10
opacity: 0
color: "transparent"
}
Label {
text: qsTr("Please re-enter") + translationManager.emptyString
Layout.fillWidth: true
font.pixelSize: 16
font.family: MoneroComponents.Style.fontLight.name
color: MoneroComponents.Style.defaultFontColor
}
TextField {
id : passphaseInput2
Layout.topMargin: 6
Layout.fillWidth: true
horizontalAlignment: TextInput.AlignLeft
verticalAlignment: TextInput.AlignVCenter
font.family: MoneroComponents.Style.fontLight.name
font.pixelSize: 24
echoMode: TextInput.Password
KeyNavigation.tab: okButton
bottomPadding: 10
leftPadding: 10
topPadding: 10
color: MoneroComponents.Style.defaultFontColor
selectionColor: MoneroComponents.Style.dimmedFontColor
selectedTextColor: MoneroComponents.Style.defaultFontColor
background: Rectangle {
radius: 2
border.color: MoneroComponents.Style.inputBorderColorInActive
border.width: 1
color: MoneroComponents.Style.blackTheme ? "black" : "#A9FFFFFF"
MoneroComponents.Label {
fontSize: 20
text: isHidden ? FontAwesome.eye : FontAwesome.eyeSlash
opacity: 0.7
fontFamily: FontAwesome.fontFamily
anchors.right: parent.right
anchors.rightMargin: 15
anchors.verticalCenter: parent.verticalCenter
anchors.verticalCenterOffset: 1
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
hoverEnabled: true
onClicked: {
toggleIsHidden()
}
onEntered: {
parent.opacity = 0.9
parent.fontSize = 24
}
onExited: {
parent.opacity = 0.7
parent.fontSize = 20
}
}
}
}
Keys.onReturnPressed: {
if (passphaseInput1.text === passphaseInput2.text) {
root.close()
root.accepted()
}
}
Keys.onEscapePressed: {
root.close()
root.rejected()
}
}
// padding
Rectangle {
Layout.fillWidth: true
Layout.alignment: Qt.AlignHCenter
height: 10
opacity: 0
color: "black"
}
// Ok/Cancel buttons
RowLayout {
id: buttons
spacing: 16
Layout.topMargin: 16
Layout.alignment: Qt.AlignRight
MoneroComponents.StandardButton {
id: cancelButton
text: qsTr("Cancel") + translationManager.emptyString
KeyNavigation.tab: passphaseInput1
onClicked: {
root.close()
root.rejected()
}
}
MoneroComponents.StandardButton {
id: okButton
text: qsTr("Continue") + translationManager.emptyString
KeyNavigation.tab: cancelButton
enabled: passphaseInput1.text === passphaseInput2.text
onClicked: {
root.close()
root.accepted()
}
}
}
}
}
}

View File

@@ -44,34 +44,63 @@ Item {
z: parent.z + 2
property bool isHidden: true
property alias password: passwordInput.text
property alias password: passwordInput1.text
property string walletName
property string errorText
property bool shiftIsPressed: false
property bool isCapsLocksActive: false
property bool backspaceIsPressed: false
property bool passwordDialogMode
property bool passphraseDialogMode
property bool newPasswordDialogMode
// same signals as Dialog has
signal accepted()
signal acceptedNewPassword()
signal acceptedPassphrase()
signal rejected()
signal rejectedNewPassword()
signal rejectedPassphrase()
signal closeCallback()
function open(walletName, errorText) {
function _openInit(walletName, errorText) {
isHidden = true
passwordInput.echoMode = TextInput.Password
passwordInput.text = ""
passwordInput.forceActiveFocus();
capsLockTextLabel.visible = oshelper.isCapsLock();
passwordInput1.echoMode = TextInput.Password
passwordInput2.echoMode = TextInput.Password
passwordInput1.text = ""
passwordInput2.text = ""
passwordInput1.forceActiveFocus();
inactiveOverlay.visible = true // draw appwindow inactive
root.walletName = walletName ? walletName : ""
errorTextLabel.text = errorText ? errorText : "";
leftPanel.enabled = false
middlePanel.enabled = false
wizard.enabled = false
titleBar.state = "essentials"
root.visible = true;
appWindow.hideBalanceForced = true;
appWindow.updateBalance();
}
function open(walletName, errorText) {
passwordDialogMode = true;
passphraseDialogMode = false;
newPasswordDialogMode = false;
_openInit(walletName, errorText);
}
function openPassphraseDialog() {
passwordDialogMode = false;
passphraseDialogMode = true;
newPasswordDialogMode = false;
_openInit("", "");
}
function openNewPasswordDialog() {
passwordDialogMode = false;
passphraseDialogMode = false;
newPasswordDialogMode = true;
_openInit("", "");
}
function showError(errorText) {
open(root.walletName, errorText);
}
@@ -80,6 +109,7 @@ Item {
inactiveOverlay.visible = false
leftPanel.enabled = true
middlePanel.enabled = true
wizard.enabled = true
titleBar.state = "default"
root.visible = false;
@@ -88,6 +118,12 @@ Item {
closeCallback();
}
function toggleIsHidden() {
passwordInput1.echoMode = isHidden ? TextInput.Normal : TextInput.Password;
passwordInput2.echoMode = isHidden ? TextInput.Normal : TextInput.Password;
isHidden = !isHidden;
}
ColumnLayout {
z: inactiveOverlay.z + 1
id: mainLayout
@@ -102,7 +138,14 @@ Item {
Layout.maximumWidth: 400
Label {
text: (root.walletName.length > 0 ? qsTr("Please enter wallet password for: ") + root.walletName : qsTr("Please enter wallet password")) + translationManager.emptyString
text: {
if (newPasswordDialogMode) {
return qsTr("Please enter new wallet password") + translationManager.emptyString;
} else {
var device = passwordDialogMode ? qsTr("wallet password") : qsTr("wallet device passphrase");
return (root.walletName.length > 0 ? qsTr("Please enter %1 for: ").arg(device) + root.walletName : qsTr("Please enter %1").arg(device)) + translationManager.emptyString;
}
}
Layout.fillWidth: true
font.pixelSize: 16
@@ -111,19 +154,41 @@ Item {
color: MoneroComponents.Style.defaultFontColor
}
Label {
text: qsTr("Warning: passphrase entry on host is a security risk as it can be captured by malware. It is advised to prefer device-based passphrase entry.") + translationManager.emptyString
visible: passphraseDialogMode
Layout.fillWidth: true
wrapMode: Text.Wrap
font.pixelSize: 14
font.family: MoneroComponents.Style.fontLight.name
color: MoneroComponents.Style.warningColor
}
Label {
id: errorTextLabel
visible: root.errorText || text !== ""
color: MoneroComponents.Style.errorColor
font.pixelSize: 16
font.family: MoneroComponents.Style.fontLight.name
font.family: MoneroComponents.Style.fontLight.name
Layout.fillWidth: true
wrapMode: Text.Wrap
}
Label {
id: capsLockTextLabel
visible: false
color: MoneroComponents.Style.errorColor
font.pixelSize: 16
font.family: MoneroComponents.Style.fontLight.name
Layout.fillWidth: true
wrapMode: Text.Wrap
text: qsTr("CAPSLOCKS IS ON.") + translationManager.emptyString;
}
TextField {
id : passwordInput
id: passwordInput1
Layout.topMargin: 6
Layout.fillWidth: true
horizontalAlignment: TextInput.AlignLeft
@@ -131,24 +196,20 @@ Item {
font.family: MoneroComponents.Style.fontLight.name
font.pixelSize: 24
echoMode: TextInput.Password
KeyNavigation.tab: okButton
KeyNavigation.tab: {
if (passwordDialogMode) {
return okButton
} else {
return passwordInput2
}
}
bottomPadding: 10
leftPadding: 10
topPadding: 10
color: MoneroComponents.Style.defaultFontColor
selectionColor: MoneroComponents.Style.textSelectionColor
selectedTextColor: MoneroComponents.Style.textSelectedColor
onTextChanged: {
var letter = text[passwordInput.text.length - 1];
isCapsLocksActive = Utils.isUpperLock(shiftIsPressed, letter);
if(isCapsLocksActive && !backspaceIsPressed){
errorTextLabel.text = qsTr("CAPSLOCKS IS ON.") + translationManager.emptyString;
}
else{
errorTextLabel.text = "";
}
}
onTextChanged: capsLockTextLabel.visible = oshelper.isCapsLock();
background: Rectangle {
radius: 2
@@ -177,8 +238,7 @@ Item {
cursorShape: Qt.PointingHandCursor
hoverEnabled: true
onClicked: {
passwordInput.echoMode = isHidden ? TextInput.Normal : TextInput.Password;
isHidden = !isHidden;
toggleIsHidden();
}
onEntered: {
parent.opacity = 0.9
@@ -195,28 +255,129 @@ Item {
Keys.enabled: root.visible
Keys.onReturnPressed: {
root.close()
root.accepted()
if (passwordDialogMode) {
root.accepted()
} else if (newPasswordDialogMode) {
root.acceptedNewPassword()
} else if (passphraseDialogMode) {
root.acceptedPassphrase()
}
}
Keys.onEscapePressed: {
root.close()
root.rejected()
}
Keys.onPressed: {
if(event.key === Qt.Key_Shift){
shiftIsPressed = true;
}
if(event.key === Qt.Key_Backspace){
backspaceIsPressed = true;
if (passwordDialogMode) {
root.rejected()
} else if (newPasswordDialogMode) {
root.rejectedNewPassword()
} else if (passphraseDialogMode) {
root.rejectedPassphrase()
}
}
Keys.onReleased: {
if(event.key === Qt.Key_Shift){
shiftIsPressed = false;
}
if(event.key === Qt.Key_Backspace){
backspaceIsPressed =false;
}
// padding
Rectangle {
visible: !passwordDialogMode
Layout.fillWidth: true
Layout.alignment: Qt.AlignHCenter
height: 10
opacity: 0
color: "black"
}
Label {
visible: !passwordDialogMode
text: newPasswordDialogMode ? qsTr("Please confirm new password") : qsTr("Please confirm wallet device passphrase") + translationManager.emptyString
Layout.fillWidth: true
font.pixelSize: 16
font.family: MoneroComponents.Style.fontLight.name
color: MoneroComponents.Style.defaultFontColor
}
TextField {
id: passwordInput2
visible: !passwordDialogMode
Layout.topMargin: 6
Layout.fillWidth: true
horizontalAlignment: TextInput.AlignLeft
verticalAlignment: TextInput.AlignVCenter
font.family: MoneroComponents.Style.fontLight.name
font.pixelSize: 24
echoMode: TextInput.Password
KeyNavigation.tab: okButton
bottomPadding: 10
leftPadding: 10
topPadding: 10
color: MoneroComponents.Style.defaultFontColor
selectionColor: MoneroComponents.Style.textSelectionColor
selectedTextColor: MoneroComponents.Style.textSelectedColor
onTextChanged: capsLockTextLabel.visible = oshelper.isCapsLock();
background: Rectangle {
radius: 2
border.color: MoneroComponents.Style.inputBorderColorInActive
border.width: 1
color: MoneroComponents.Style.blackTheme ? "black" : "#A9FFFFFF"
MoneroComponents.Label {
fontSize: 20
text: isHidden ? FontAwesome.eye : FontAwesome.eyeSlash
opacity: 0.7
fontFamily: FontAwesome.fontFamily
anchors.right: parent.right
anchors.rightMargin: 15
anchors.verticalCenter: parent.verticalCenter
anchors.verticalCenterOffset: 1
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
hoverEnabled: true
onClicked: {
toggleIsHidden()
}
onEntered: {
parent.opacity = 0.9
parent.fontSize = 24
}
onExited: {
parent.opacity = 0.7
parent.fontSize = 20
}
}
}
}
Keys.onReturnPressed: {
if (passwordInput1.text === passwordInput2.text) {
root.close()
if (newPasswordDialogMode) {
root.acceptedNewPassword()
} else if (passphraseDialogMode) {
root.acceptedPassphrase()
}
}
}
Keys.onEscapePressed: {
root.close()
if (newPasswordDialogMode) {
root.rejectedNewPassword()
} else if (passphraseDialogMode) {
root.rejectedPassphrase()
}
}
}
// padding
Rectangle {
visible: !passwordDialogMode
Layout.fillWidth: true
Layout.alignment: Qt.AlignHCenter
height: 10
opacity: 0
color: "black"
}
// Ok/Cancel buttons
@@ -229,26 +390,38 @@ Item {
MoneroComponents.StandardButton {
id: cancelButton
small: true
text: root.walletName.length > 0 ? qsTr("Change wallet") + translationManager.emptyString : qsTr("Cancel") + translationManager.emptyString
KeyNavigation.tab: passwordInput
text: qsTr("Cancel") + translationManager.emptyString
KeyNavigation.tab: passwordInput1
onClicked: {
root.close()
root.rejected()
if (passwordDialogMode) {
root.rejected()
} else if (newPasswordDialogMode) {
root.rejectedNewPassword()
} else if (passphraseDialogMode) {
root.rejectedPassphrase()
}
}
}
MoneroComponents.StandardButton {
id: okButton
small: true
text: qsTr("Continue") + translationManager.emptyString
text: qsTr("Ok") + translationManager.emptyString
KeyNavigation.tab: cancelButton
enabled: (passwordDialogMode == true) ? true : passwordInput1.text === passwordInput2.text
onClicked: {
root.close()
root.accepted()
if (passwordDialogMode) {
root.accepted()
} else if (newPasswordDialogMode) {
root.acceptedNewPassword()
} else if (passphraseDialogMode) {
root.acceptedPassphrase()
}
}
}
}
}
}
}

View File

@@ -17,7 +17,7 @@ if [ ! -d $MONERO_DIR/src ]; then
fi
git submodule update --remote
git -C $MONERO_DIR fetch
git -C $MONERO_DIR checkout v0.14.1.0
git -C $MONERO_DIR checkout v0.14.1.2
# get monero core tag
pushd $MONERO_DIR

BIN
images/tails-grey.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

View File

@@ -0,0 +1,30 @@
# Building the Installer Deterministically
This file contains info about building the Windows installer deterministically, i.e. how different people on different Windows machines or VMs can build it and arrive at a result that is bit-for-bit identical. This approach is also known as *reproducible builds*, see e.g. [this Wikipedia article](https://en.wikipedia.org/wiki/Reproducible_builds).
The steps to build the Windows installer deterministically by a group of people are the following (for some details about the build process in general see `README.md`):
* Agree on a particular version of Inno Setup, and everybody install that
* Get the zip file for the Windows GUI wallet and unpack it, plus make sure / check that the file timestamps are preserved, i.e. upacked timestamp = timestamp in zip file
* Build using Inno Setup and the `Monero.iss` script file
* Success: All people arrive at a bit-for-bit identical installer .exe file, which they can verify by calculating and exchanging SHA256 hashes
Some background info why this process is relatively simple:
The tool used to build the Windows installer, Inno Setup, avoids many issues that make reproducible builds very challenging with many other compilers and similar tools: It does not store current date and time in the installer .exe file, and it does not seem to depend on the Windows version it runs on (tried with Windows 7 and two different editions of Windows 10), nor on the locale and display language.
So fortunately no complicated things as faked current system time or use of VMs with exactly prescribed versions of Windows are necessary.
The version of Inno Setup **is** important however: People wanting to reproducibly build the installer must agree on a particular version to use. This should not be hard to do however.
Also important are the **timestamps** of the source files because they go into the installer file, to be restored at install time.
You would think timestamp preservation is no problem when unpacking the zip archive with the files for the Windows GUI wallet from getmonero.org, but if you use the zip folder unpack functionality of the Windows 7 GUI, the files get the current date, **not** the file recorded in the zip file. (The Windows 10 GUI seems better here, and also the 7zip app.)
In any case, after unpacking, check the file dates in the `bin` directory where the installer script looks for them with the dates of the files in the zip file: They must be identical.
Note that the the following line in `Monero.iss` is also important regarding file timestamps:
TimeStampsInUTC=yes
Without this line the **timezone** of the machine used to build the installer would matter, with different timezones leading to different installer files.

View File

@@ -8,7 +8,7 @@ AppName=Monero GUI Wallet
; Thus it's important to keep this stable over releases
; With a different "AppName" InnoSetup would treat a mere update as a completely new application and thus mess up
AppVersion=0.14.1.0
AppVersion=0.14.1.2
DefaultDirName={pf}\Monero GUI Wallet
DefaultGroupName=Monero GUI Wallet
UninstallDisplayIcon={app}\monero-wallet-gui.exe
@@ -21,6 +21,8 @@ DisableWelcomePage=no
LicenseFile=LICENSE
AppPublisher=The Monero Developer Community
AppPublisherURL=https://getmonero.org
TimeStampsInUTC=yes
CompressionThreads=1
UsedUserAreasWarning=no
; The above directive silences the following compiler warning:
@@ -68,7 +70,7 @@ Source: "FinishImage.bmp"; Flags: dontcopy
; Monero GUI wallet exe and guide
Source: "bin\monero-wallet-gui.exe"; DestDir: "{app}"; Flags: ignoreversion
Source: "bin\monero-GUI-guide.pdf"; DestDir: "{app}"; Flags: ignoreversion
Source: "bin\monero-gui-wallet-guide.pdf"; DestDir: "{app}"; Flags: ignoreversion
; Monero CLI wallet
Source: "bin\monero-wallet-cli.exe"; DestDir: "{app}"; Flags: ignoreversion

View File

@@ -34,11 +34,13 @@ You can only build on Windows, and the result is always a
Windows .exe file that can act as a standalone installer for the
Boron Butterfly GUI wallet.
Note that the installer build process is now reproducible / deterministic. For details check the file [Deterministic.md](Deterministic.md).
The build steps in detail:
1. Install *Inno Setup*. You can get it from [here](http://www.jrsoftware.org/isdl.php)
2. Get the Inno Setup script plus related files by cloning the whole [monero-gui GitHub repository](https://github.com/monero-project/monero-gui); you will only need the files in the installer directory `installers\windows` however. Depending on development state, additionally you may have to checkout a specific branch, like `release-v0.14`.
3. The setup script is written to take the GUI wallet files from a subdirectory named `bin`; so create `installers\windows\bin`, get the zip file of the GUI wallet from [here](https://getmonero.org/downloads/), unpack it somewhere, and copy all the files and subdirectories in the single subdirectory there (currently named `monero-gui-0.14.1.0`) to this `bin` subdirectory
3. The setup script is written to take the GUI wallet files from a subdirectory named `bin`; so create `installers\windows\bin`, get the zip file of the GUI wallet from [here](https://getmonero.org/downloads/), unpack it somewhere, and copy all the files and subdirectories in the single subdirectory there (currently named `monero-gui-0.14.1.2`) to this `bin` subdirectory
4. Start Inno Setup, load `Monero.iss` and compile it
5. The result i.e. the finished installer will be the file `mysetup.exe` in the `installers\windows\Output` subdirectory

View File

@@ -7,7 +7,7 @@
<h1>Monero Boron Butterfly GUI Wallet</h1>
<p>Copyright (c) 2014-2019, The Monero Project<br>
Date: May 7, 2019</p>
Date: July 20, 2019</p>
<h2>Preface</h2>
@@ -23,7 +23,7 @@
<h2>Content of the Package</h2>
<p>You just installed the <i>Monero GUI wallet</i> for Windows, release Boron Butterfly, version 0.14.1.0.
<p>You just installed the <i>Monero GUI wallet</i> for Windows, release Boron Butterfly, version 0.14.1.2.
The wallet enables you to send and receive Moneroj in a secure and very private way.
</p>
@@ -61,7 +61,7 @@
provides the most security and privacy possible for you.</p>
<p>However if your Internet access makes it difficult to run a full node, or if you have simply no room to store
the blockchain locally (somewhat over 70 GB in May 2019, and of course growing), you can compromise and try to connect
the blockchain locally (somewhat over 70 GB in July 2019, and of course growing), you can compromise and try to connect
to a remote node. One way of finding such a node is checking
<a href="https://moneroworld.com/#nodes">this page</a>.
</p>

View File

@@ -1 +0,0 @@
-----

View File

@@ -12,13 +12,13 @@ function destinationsToAddress(destinations){
}
function addressTruncate(address, range){
if(typeof(address) === "undefined") return;
if(typeof(address) === "undefined") return "";
if(typeof(range) === "undefined") range = 8;
return address.substring(0, range) + "..." + address.substring(address.length-range);
}
function addressTruncatePretty(address, blocks){
if(typeof(address) === "undefined") return;
if(typeof(address) === "undefined") return "";
if(typeof(blocks) === "undefined") blocks = 2;
blocks = blocks <= 1 ? 1 : blocks >= 23 ? 23 : blocks;
var ret = "";

View File

@@ -112,25 +112,6 @@ function roundDownToNearestThousand(_num){
return Math.floor(_num/1000.0)*1000
}
function isAlpha(letter){ return letter.match(/^[A-Za-z0-9]+$/) !== null; }
function isLowerCaseChar(letter){ return letter === letter.toLowerCase(); }
function isUpperLock(shift, letter){
if(!isAlpha((letter))) return false;
if(shift) {
if(isLowerCaseChar(letter))
return true;
else
return false;
} else {
if(isLowerCaseChar(letter))
return false;
else
return true;
}
}
function qmlEach(item, properties, ignoredObjectNames, arr){
// Traverse QML object tree and return components that match
// via property names. Similar to jQuery("myclass").each(...

View File

@@ -51,4 +51,12 @@ SCRIPT_DIR="\$(dirname "\$(test -L "\${BASH_SOURCE[0]}" && readlink "\${BASH_SOU
"\$SCRIPT_DIR"/$GUI_EXEC "\$@"
EOL
# Create start script
cat > $TARGET/start-tails.AppImage <<EOL
#!/bin/bash
# Silly hack to provide a launcher that is double clickable
bash ./start-gui.sh
EOL
chmod +x $TARGET/start-gui.sh
chmod +x $TARGET/start-tails.AppImage

View File

@@ -64,8 +64,9 @@
#include "MainApp.h"
#include "qt/ipc.h"
#include "qt/utils.h"
#include "qt/mime.h"
#include "src/qt/TailsOS.h"
#include "src/qt/KeysFiles.h"
#include "src/qt/MoneroSettings.h"
#include "qt/prices.h"
// IOS exclusions
@@ -82,6 +83,7 @@ bool isAndroid = false;
bool isWindows = false;
bool isMac = false;
bool isLinux = false;
bool isTails = false;
bool isDesktop = false;
bool isOpenGL = true;
@@ -101,6 +103,7 @@ int main(int argc, char *argv[])
bool isWindows = true;
#elif defined(Q_OS_LINUX)
bool isLinux = true;
bool isTails = TailsOS::detect();
#elif defined(Q_OS_MAC)
bool isMac = true;
#endif
@@ -122,25 +125,40 @@ int main(int argc, char *argv[])
// qDebug() << "High DPI auto scaling - enabled";
//#endif
MainApp app(argc, argv);
app.setApplicationName("monero-core");
app.setOrganizationDomain("getmonero.org");
app.setOrganizationName("monero-project");
// Ask to enable Tails OS persistence mode, it affects:
// - Log file location
// - QML Settings file location (monero-core.conf)
// - Default wallets path
// Target directory is: ~/Persistent/Monero
if (isTails) {
if (!TailsOS::detectDataPersistence())
TailsOS::showDataPersistenceDisabledWarning();
else
TailsOS::askPersistence();
}
QString moneroAccountsDir;
#if defined(Q_OS_WIN) || defined(Q_OS_IOS)
QStringList moneroAccountsRootDir = QStandardPaths::standardLocations(QStandardPaths::DocumentsLocation);
#else
QStringList moneroAccountsRootDir = QStandardPaths::standardLocations(QStandardPaths::HomeLocation);
#endif
if (!moneroAccountsRootDir.empty()) {
if(isTails && TailsOS::usePersistence){
moneroAccountsDir = QDir::homePath() + "/Persistent/Monero/wallets";
} else if (!moneroAccountsRootDir.empty()) {
moneroAccountsDir = moneroAccountsRootDir.at(0) + "/Monero/wallets";
} else {
qCritical() << "Error: accounts root directory could not be set";
return 1;
}
MainApp app(argc, argv);
app.setApplicationName("monero-core");
app.setOrganizationDomain("getmonero.org");
app.setOrganizationName("monero-project");
#if defined(Q_OS_LINUX)
if (isDesktop) app.setWindowIcon(QIcon(":/images/appicon.ico"));
#endif
@@ -173,9 +191,8 @@ int main(int argc, char *argv[])
}
qWarning().noquote() << "app startd" << "(log: " + logPath + ")";
#ifdef Q_OS_LINUX
// Desktop entry
registerXdgMime(app);
#endif
IPC *ipc = new IPC(&app);
QStringList posArgs = parser.positionalArguments();
@@ -224,6 +241,9 @@ int main(int argc, char *argv[])
// registering types for QML
qmlRegisterType<clipboardAdapter>("moneroComponents.Clipboard", 1, 0, "Clipboard");
// Temporary Qt.labs.settings replacement
qmlRegisterType<MoneroSettings>("moneroComponents.Settings", 1, 0, "MoneroSettings");
qmlRegisterUncreatableType<Wallet>("moneroComponents.Wallet", 1, 0, "Wallet", "Wallet can't be instantiated directly");
@@ -313,6 +333,8 @@ int main(int argc, char *argv[])
engine.rootContext()->setContextProperty("walletLogPath", logPath);
engine.rootContext()->setContextProperty("tailsUsePersistence", TailsOS::usePersistence);
// Exclude daemon manager from IOS
#ifndef Q_OS_IOS
const QStringList arguments = (QStringList) QCoreApplication::arguments().at(0);
@@ -326,7 +348,7 @@ int main(int argc, char *argv[])
engine.rootContext()->setContextProperty("isIOS", isIOS);
engine.rootContext()->setContextProperty("isAndroid", isAndroid);
engine.rootContext()->setContextProperty("isOpenGL", isOpenGL);
engine.rootContext()->setContextProperty("isLinux", isLinux);
engine.rootContext()->setContextProperty("isTails", isTails);
engine.rootContext()->setContextProperty("screenWidth", geo.width());
engine.rootContext()->setContextProperty("screenHeight", geo.height());
@@ -350,6 +372,7 @@ int main(int argc, char *argv[])
accountName = "My monero Account";
engine.rootContext()->setContextProperty("defaultAccountName", accountName);
engine.rootContext()->setContextProperty("homePath", QDir::homePath());
engine.rootContext()->setContextProperty("applicationDirectory", QApplication::applicationDirPath());
engine.rootContext()->setContextProperty("idealThreadCount", QThread::idealThreadCount());

116
main.qml
View File

@@ -31,11 +31,11 @@ import QtQuick.Window 2.0
import QtQuick.Controls 1.1
import QtQuick.Controls.Styles 1.1
import QtQuick.Dialogs 1.2
import Qt.labs.settings 1.0
import moneroComponents.Wallet 1.0
import moneroComponents.PendingTransaction 1.0
import moneroComponents.NetworkType 1.0
import moneroComponents.Settings 1.0
import "components"
import "components" as MoneroComponents
@@ -283,7 +283,7 @@ ApplicationWindow {
titleBar.visible = persistentSettings.customDecorations;
}
function closeWallet() {
function closeWallet(callback) {
// Disconnect all listeners
if (typeof currentWallet !== "undefined" && currentWallet !== null) {
@@ -306,8 +306,17 @@ ApplicationWindow {
}
currentWallet = undefined;
walletManager.closeWallet();
appWindow.showProcessingSplash(qsTr("Closing wallet..."));
if (callback) {
walletManager.closeWalletAsync(function() {
hideProcessingSplash();
callback();
});
} else {
walletManager.closeWallet();
hideProcessingSplash();
}
}
function connectWallet(wallet) {
@@ -558,26 +567,21 @@ ApplicationWindow {
}
}
function onWalletClosed(walletAddress) {
hideProcessingSplash();
console.log(">>> wallet closed: " + walletAddress)
}
function onWalletPassphraseNeeded(){
if(rootItem.state !== "normal") return;
hideProcessingSplash();
console.log(">>> wallet passphrase needed: ")
passphraseDialog.onAcceptedCallback = function() {
walletManager.onPassphraseEntered(passphraseDialog.passphrase);
passwordDialog.onAcceptedPassphraseCallback = function() {
walletManager.onPassphraseEntered(passwordDialog.password);
this.onWalletOpening();
}
passphraseDialog.onRejectedCallback = function() {
passwordDialog.onRejectedPassphraseCallback = function() {
walletManager.onPassphraseEntered("", true);
this.onWalletOpening();
}
passphraseDialog.open()
passwordDialog.openPassphraseDialog()
}
function onWalletUpdate() {
@@ -1105,27 +1109,30 @@ ApplicationWindow {
console.log("Hiding processing splash")
splash.close();
leftPanel.enabled = true
middlePanel.enabled = true
titleBar.enabled = true
inactiveOverlay.visible = false;
if (!passwordDialog.visible) {
leftPanel.enabled = true
middlePanel.enabled = true
titleBar.enabled = true
inactiveOverlay.visible = false;
}
}
// close wallet and show wizard
function showWizard(){
clearMoneroCardLabelText();
walletInitialized = false;
closeWallet();
currentWallet = undefined;
wizard.restart();
wizard.wizardState = "wizardHome";
rootItem.state = "wizard"
// reset balance
leftPanel.balanceText = leftPanel.unlockedBalanceText = walletManager.displayAmount(0);
fiatApiUpdateBalance(0, 0);
// disable timers
userInActivityTimer.running = false;
simpleModeConnectionTimer.running = false;
closeWallet(function() {
currentWallet = undefined;
wizard.restart();
wizard.wizardState = "wizardHome";
rootItem.state = "wizard"
// reset balance
leftPanel.balanceText = leftPanel.unlockedBalanceText = walletManager.displayAmount(0);
fiatApiUpdateBalance(0, 0);
// disable timers
userInActivityTimer.running = false;
simpleModeConnectionTimer.running = false;
});
}
function hideMenu() {
@@ -1289,7 +1296,6 @@ ApplicationWindow {
y = (Screen.height - maxWindowHeight) / 2
//
walletManager.walletOpened.connect(onWalletOpened);
walletManager.walletClosed.connect(onWalletClosed);
walletManager.deviceButtonRequest.connect(onDeviceButtonRequest);
walletManager.deviceButtonPressed.connect(onDeviceButtonPressed);
walletManager.checkUpdatesComplete.connect(onWalletCheckUpdatesComplete);
@@ -1341,8 +1347,14 @@ ApplicationWindow {
}
}
Settings {
MoneroSettings {
id: persistentSettings
fileName: {
if(isTails && tailsUsePersistence)
return homePath + "/Persistent/Monero/monero-core.conf";
return "";
}
property string language
property string locale
property string account_name
@@ -1494,23 +1506,6 @@ ApplicationWindow {
}
}
PassphraseDialog {
id: passphraseDialog
visible: false
z: parent.z + 1
anchors.fill: parent
property var onAcceptedCallback
property var onRejectedCallback
onAccepted: {
if (onAcceptedCallback)
onAcceptedCallback();
}
onRejected: {
if (onRejectedCallback)
onRejectedCallback();
}
}
PasswordDialog {
id: passwordDialog
visible: false
@@ -1518,6 +1513,8 @@ ApplicationWindow {
anchors.fill: parent
property var onAcceptedCallback
property var onRejectedCallback
property var onAcceptedPassphraseCallback
property var onRejectedPassphraseCallback
onAccepted: {
if (onAcceptedCallback)
onAcceptedCallback();
@@ -1526,16 +1523,9 @@ ApplicationWindow {
if (onRejectedCallback)
onRejectedCallback();
}
}
NewPasswordDialog {
id: newPasswordDialog
z: parent.z + 1
visible:false
anchors.fill: parent
onAccepted: {
if (currentWallet.setPassword(newPasswordDialog.password)) {
appWindow.walletPassword = newPasswordDialog.password;
onAcceptedNewPassword: {
if (currentWallet.setPassword(passwordDialog.password)) {
appWindow.walletPassword = passwordDialog.password;
informationPopup.title = qsTr("Information") + translationManager.emptyString;
informationPopup.text = qsTr("Password changed successfully") + translationManager.emptyString;
informationPopup.icon = StandardIcon.Information;
@@ -1547,7 +1537,14 @@ ApplicationWindow {
informationPopup.onCloseCallback = null;
informationPopup.open();
}
onRejected: {
onRejectedNewPassword: {}
onAcceptedPassphrase: {
if (onAcceptedPassphraseCallback)
onAcceptedPassphraseCallback();
}
onRejectedPassphrase: {
if (onRejectedPassphraseCallback)
onRejectedPassphraseCallback();
}
}
@@ -2131,8 +2128,8 @@ ApplicationWindow {
console.log("close accepted");
// Close wallet non async on exit
daemonManager.exit();
walletManager.closeWallet();
Qt.quit();
closeWallet(Qt.quit);
}
function onWalletCheckUpdatesComplete(update) {
@@ -2201,6 +2198,7 @@ ApplicationWindow {
function checkInUserActivity() {
if(rootItem.state !== "normal") return;
if(!persistentSettings.lockOnUserInActivity) return;
if(passwordDialog.visible) return;
// prompt password after X seconds of inactivity
var epoch = Math.floor((new Date).getTime() / 1000);

View File

@@ -1,6 +1,6 @@
# qml components require at least QT 5.7.0
lessThan (QT_MAJOR_VERSION, 5) | lessThan (QT_MINOR_VERSION, 7) {
error("Can't build with Qt $${QT_VERSION}. Use at least Qt 5.7.0")
# qml components require at least QT 5.9.0
lessThan (QT_MAJOR_VERSION, 5) | lessThan (QT_MINOR_VERSION, 9) {
error("Can't build with Qt $${QT_VERSION}. Use at least Qt 5.9.0")
}
TEMPLATE = app
@@ -65,10 +65,12 @@ HEADERS += \
MainApp.h \
src/qt/FutureScheduler.h \
src/qt/ipc.h \
src/qt/mime.h \
src/qt/KeysFiles.h \
src/qt/utils.h \
src/qt/prices.h
src/qt/prices.h \
src/qt/macoshelper.h \
src/qt/MoneroSettings.h \
src/qt/TailsOS.h
SOURCES += main.cpp \
filter.cpp \
@@ -99,10 +101,11 @@ SOURCES += main.cpp \
MainApp.cpp \
src/qt/FutureScheduler.cpp \
src/qt/ipc.cpp \
src/qt/mime.cpp \
src/qt/KeysFiles.cpp \
src/qt/utils.cpp \
src/qt/prices.cpp
src/qt/prices.cpp \
src/qt/MoneroSettings.cpp \
src/qt/TailsOS.cpp
CONFIG(DISABLE_PASS_STRENGTH_METER) {
HEADERS -= src/zxcvbn-c/zxcvbn.h
@@ -334,7 +337,8 @@ linux {
-llmdb \
-lsodium \
-lhidapi-libusb \
-lcrypto $$TREZOR_LINKER
-lcrypto $$TREZOR_LINKER \
-lX11
if(!android) {
LIBS+= \
@@ -359,6 +363,8 @@ macx {
# message("using static libraries")
# LIBS+= -Wl,-Bstatic
# }
QT += macextras
OBJECTIVE_SOURCES += src/qt/macoshelper.mm
LIBS+= \
-L/usr/local/lib \
-L/usr/local/opt/openssl/lib \
@@ -372,6 +378,7 @@ macx {
-lboost_chrono \
-lboost_program_options \
-framework CoreFoundation \
-framework AppKit \
-lhidapi \
-lssl \
-lsodium \

View File

@@ -31,6 +31,20 @@
#include <QDir>
#include <QDebug>
#include <QString>
#ifdef Q_OS_MAC
#include "qt/macoshelper.h"
#endif
#ifdef Q_OS_WIN32
#include <windows.h>
#endif
#ifdef Q_OS_LINUX
#include <X11/XKBlib.h>
#undef KeyPress
#undef KeyRelease
#undef FocusIn
#undef FocusOut
// #undef those Xlib #defines that conflict with QEvent::Type enum
#endif
OSHelper::OSHelper(QObject *parent) : QObject(parent)
{
@@ -58,6 +72,27 @@ bool OSHelper::removeTemporaryWallet(const QString &fileName) const
return cache_deleted && address_deleted && keys_deleted;
}
// https://stackoverflow.com/a/3006934
bool OSHelper::isCapsLock() const
{
// platform dependent method of determining if CAPS LOCK is on
#if defined(Q_OS_WIN32) // MS Windows version
return GetKeyState(VK_CAPITAL) == 1;
#elif defined(Q_OS_LINUX) // X11 version
Display * d = XOpenDisplay((char*)0);
bool caps_state = false;
if (d) {
unsigned n;
XkbGetIndicatorState(d, XkbUseCoreKbd, &n);
caps_state = (n & 0x01) == 1;
}
return caps_state;
#elif defined(Q_OS_MAC)
return MacOSHelper::isCapsLock();
#endif
return false;
}
QString OSHelper::temporaryPath() const
{
return QDir::tempPath();

View File

@@ -42,6 +42,7 @@ public:
Q_INVOKABLE QString temporaryFilename() const;
Q_INVOKABLE QString temporaryPath() const;
Q_INVOKABLE bool removeTemporaryWallet(const QString &walletName) const;
Q_INVOKABLE bool isCapsLock() const;
signals:

View File

@@ -101,8 +101,7 @@ Rectangle {
id: balanceAll
font.family: MoneroComponents.Style.fontMonoRegular.name;
font.pixelSize: 16
color: MoneroComponents.Style.dimmedFontColor
themeTransition: false
color: MoneroComponents.Style.defaultFontColor
MouseArea {
hoverEnabled: true
@@ -135,8 +134,7 @@ Rectangle {
id: unlockedBalanceAll
font.family: MoneroComponents.Style.fontMonoRegular.name;
font.pixelSize: 16
color: MoneroComponents.Style.dimmedFontColor
themeTransition: false
color: MoneroComponents.Style.defaultFontColor
MouseArea {
hoverEnabled: true
@@ -177,7 +175,7 @@ Rectangle {
ListView {
id: subaddressAccountListView
Layout.fillWidth: true
anchors.fill: parent
Layout.fillHeight: true
clip: true
boundsBehavior: ListView.StopAtBounds
interactive: false
@@ -365,6 +363,7 @@ Rectangle {
appWindow.currentWallet.subaddressAccount.addRow(inputDialog.inputText)
appWindow.currentWallet.switchSubaddressAccount(appWindow.currentWallet.numSubaddressAccounts() - 1)
current_subaddress_account_table_index = appWindow.currentWallet.numSubaddressAccounts() - 1
subaddressAccountListView.currentIndex = current_subaddress_account_table_index
appWindow.onWalletUpdate();
}
inputDialog.onRejectedCallback = null;

View File

@@ -145,7 +145,7 @@ Rectangle {
ListView {
id: addressBookListView
Layout.fillWidth: true
anchors.fill: parent
Layout.fillHeight: true
clip: true
boundsBehavior: ListView.StopAtBounds
interactive: false

View File

@@ -49,9 +49,9 @@ Rectangle {
property var model
property int sideMargin: 50
property var initialized: false
property int txMax: 5
property int txMax: Math.max(5, ((appWindow.height - 250) / 60))
property int txOffset: 0
property int txPage: (txOffset / 5) + 1
property int txPage: (txOffset / txMax) + 1
property int txCount: 0
property var sortSearchString: null
property bool sortDirection: true // true = desc, false = asc
@@ -67,6 +67,8 @@ Rectangle {
color: "transparent"
onTxMaxChanged: root.updateDisplay(root.txOffset, root.txMax);
ColumnLayout {
id: pageRoot
anchors.topMargin: 40
@@ -249,7 +251,6 @@ Rectangle {
font.pixelSize: 15
text: qsTr("Blockheight") + translationManager.emptyString
color: root.sortBy === "blockheight" ? MoneroComponents.Style.defaultFontColor : MoneroComponents.Style.dimmedFontColor
anchors.verticalCenter: parent.verticalCenter
themeTransition: false
}
@@ -310,7 +311,6 @@ Rectangle {
text: qsTr("Date") + translationManager.emptyString
color: root.sortBy === "timestamp" ? MoneroComponents.Style.defaultFontColor : MoneroComponents.Style.dimmedFontColor
themeTransition: false
anchors.verticalCenter: parent.verticalCenter
}
MoneroEffects.ImageMask {
@@ -370,7 +370,6 @@ Rectangle {
text: qsTr("Amount") + translationManager.emptyString
color: root.sortBy === "amount" ? MoneroComponents.Style.defaultFontColor : MoneroComponents.Style.dimmedFontColor
themeTransition: false
anchors.verticalCenter: parent.verticalCenter
}
MoneroEffects.ImageMask {
@@ -1343,13 +1342,14 @@ Rectangle {
root.updateDisplay(root.txOffset, root.txMax);
}
function reset() {
function reset(keepDate) {
root.txOffset = 0;
root.txMax = 5;
if (typeof root.model !== 'undefined' && root.model != null) {
root.model.dateFromFilter = "2014-04-18" // genesis block
root.model.dateToFilter = "9999-09-09" // fix before september 9999
if (!keepDate) {
root.model.dateFromFilter = "2014-04-18" // genesis block
root.model.dateToFilter = "9999-09-09" // fix before september 9999
}
// negative values disable filters here;
root.model.amountFromFilter = -1;
root.model.amountToFilter = -1;
@@ -1387,6 +1387,8 @@ Rectangle {
txs.push(item);
} else if(item.blockheight.toString().startsWith(root.sortSearchString)) {
txs.push(item);
} else if(item.tx_note.toLowerCase().indexOf(root.sortSearchString.toLowerCase()) !== -1) {
txs.push(item);
} else if (item.hash.startsWith(root.sortSearchString)){
txs.push(item);
}
@@ -1704,6 +1706,6 @@ Rectangle {
function onPageClosed(){
root.initialized = false;
root.reset();
root.reset(true);
}
}

View File

@@ -116,11 +116,11 @@ Rectangle {
MoneroComponents.LineEdit {
Layout.fillWidth: true
id: walletCreationHeight
readOnly: true
copyButton: true
labelText: qsTr("Block #") + translationManager.emptyString
fontSize: 16
text: currentWallet.walletCreationHeight
}
}
@@ -261,6 +261,7 @@ Rectangle {
function onPageCompleted() {
console.log("keys page loaded");
walletCreationHeight.text = currentWallet.walletCreationHeight
secretViewKey.text = currentWallet.secretViewKey
publicViewKey.text = currentWallet.publicViewKey
secretSpendKey.text = (!currentWallet.viewOnly) ? currentWallet.secretSpendKey : ""

View File

@@ -101,7 +101,7 @@ Rectangle {
ListView {
id: subaddressListView
Layout.fillWidth: true
anchors.fill: parent
Layout.fillHeight: true
clip: true
boundsBehavior: ListView.StopAtBounds
interactive: false
@@ -256,6 +256,7 @@ Rectangle {
inputDialog.onAcceptedCallback = function() {
appWindow.currentWallet.subaddress.addRow(appWindow.currentWallet.currentSubaddressAccount, inputDialog.inputText)
current_subaddress_table_index = appWindow.currentWallet.numSubaddresses(appWindow.currentWallet.currentSubaddressAccount) - 1
subaddressListView.currentIndex = current_subaddress_table_index
}
inputDialog.onRejectedCallback = null;
inputDialog.open()

View File

@@ -93,9 +93,8 @@ Item {
anchors.right: parent.right
Item {
height: 220
anchors.left: parent.left
anchors.right: parent.right
Layout.preferredHeight: 220
Layout.fillWidth: true
Rectangle {
id: tracker
@@ -258,8 +257,7 @@ Item {
Item {
Layout.preferredHeight: 40
anchors.left: parent.left
anchors.right: parent.right
Layout.fillWidth: true
Item {
width: (parent.width - qrImg.width) - (50)
@@ -524,8 +522,7 @@ Item {
Item {
Layout.topMargin: 32
Layout.preferredHeight: 40
anchors.left: parent.left
anchors.right: parent.right
Layout.fillWidth: true
ColumnLayout {
spacing: 16
@@ -630,7 +627,7 @@ Item {
in_txpool = true;
} else {
if (blockchainHeight == null)
blockchainHeight = appWindow.currentWallet.blockChainHeight()
blockchainHeight = walletManager.blockchainHeight()
confirmations = blockchainHeight - blockHeight - 1
displayAmount = model.data(idx, TransactionHistoryModel.TransactionDisplayAmountRole);
}

View File

@@ -208,10 +208,11 @@ Rectangle {
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, persistentSettings.kdfRounds);
appWindow.closeWallet(function() {
walletManager.clearWalletCache(persistentSettings.wallet_path);
walletManager.openWalletAsync(persistentSettings.wallet_path, appWindow.walletPassword,
persistentSettings.nettype, persistentSettings.kdfRounds);
});
}
confirmationDialog.onRejectedCallback = null;
@@ -325,6 +326,41 @@ Rectangle {
font.pixelSize: 14
text: isOpenGL ? "OpenGL" : "Low graphics mode"
}
Rectangle {
visible: isTails
height: 1
Layout.topMargin: 2
Layout.bottomMargin: 2
Layout.fillWidth: true
color: MoneroComponents.Style.dividerColor
opacity: MoneroComponents.Style.dividerOpacity
}
Rectangle {
visible: isTails
height: 1
Layout.topMargin: 2
Layout.bottomMargin: 2
Layout.fillWidth: true
color: MoneroComponents.Style.dividerColor
opacity: MoneroComponents.Style.dividerOpacity
}
MoneroComponents.TextBlock {
visible: isTails
Layout.fillWidth: true
font.pixelSize: 14
text: qsTr("Tails: ") + translationManager.emptyString
}
MoneroComponents.TextBlock {
visible: isTails
Layout.fillWidth: true
color: MoneroComponents.Style.dimmedFontColor
font.pixelSize: 14
text: tailsUsePersistence ? qsTr("persistent") + translationManager.emptyString : qsTr("persistence disabled") + translationManager.emptyString;
}
}
// Copy info to clipboard

View File

@@ -339,7 +339,7 @@ Rectangle {
onClicked: {
passwordDialog.onAcceptedCallback = function() {
if(appWindow.walletPassword === passwordDialog.password){
newPasswordDialog.open()
passwordDialog.openNewPasswordDialog()
} else {
informationPopup.title = qsTr("Error") + translationManager.emptyString;
informationPopup.text = qsTr("Wrong password") + translationManager.emptyString;

View File

@@ -96,9 +96,7 @@
<file>pages/SharedRingDB.qml</file>
<file>components/effects/ImageMask.qml</file>
<file>components/IconButton.qml</file>
<file>components/PassphraseDialog.qml</file>
<file>components/PasswordDialog.qml</file>
<file>components/NewPasswordDialog.qml</file>
<file>components/InputDialog.qml</file>
<file>components/ProcessingSplash.qml</file>
<file>components/ProgressBar.qml</file>
@@ -253,5 +251,6 @@
<file>images/copy.svg</file>
<file>images/edit.svg</file>
<file>images/arrow-right-in-circle-outline-medium-white.svg</file>
<file>images/tails-grey.png</file>
</qresource>
</RCC>

View File

@@ -524,7 +524,8 @@ bool Wallet::submitTxFile(const QString &fileName) const
void Wallet::commitTransactionAsync(PendingTransaction *t)
{
m_scheduler.run([this, t] {
emit transactionCommitted(t->commit(), t, t->txid());
auto txIdList = t->txid(); // retrieve before commit
emit transactionCommitted(t->commit(), t, txIdList);
});
}

View File

@@ -351,7 +351,7 @@ signals:
void walletCreationHeightChanged();
void deviceButtonRequest(quint64 buttonCode);
void deviceButtonPressed();
void transactionCommitted(bool status, PendingTransaction *t, QStringList txid);
void transactionCommitted(bool status, PendingTransaction *t, const QStringList& txid);
void heightRefreshed(quint64 walletHeight, quint64 daemonHeight, quint64 targetHeight) const;
// emitted when transaction is created async

View File

@@ -66,7 +66,7 @@ public:
}
auto tmpPass = m_mgr->m_passphrase.toStdString();
m_mgr->m_passphrase = QString::null;
m_mgr->m_passphrase = QString();
return Monero::optional<std::string>(tmpPass);
}
@@ -228,11 +228,11 @@ QString WalletManager::closeWallet()
return result;
}
void WalletManager::closeWalletAsync()
void WalletManager::closeWalletAsync(const QJSValue& callback)
{
m_scheduler.run([this] {
emit walletClosed(closeWallet());
});
return QJSValueList({closeWallet()});
}, callback);
}
bool WalletManager::walletExists(const QString &path) const

View File

@@ -117,7 +117,7 @@ public:
/*!
* \brief closeWalletAsync - asynchronous version of "closeWallet"
*/
Q_INVOKABLE void closeWalletAsync();
Q_INVOKABLE void closeWalletAsync(const QJSValue& callback);
//! checks is given filename is a wallet;
Q_INVOKABLE bool walletExists(const QString &path) const;
@@ -192,7 +192,6 @@ signals:
void walletPassphraseNeeded();
void deviceButtonRequest(quint64 buttonCode);
void deviceButtonPressed();
void walletClosed(const QString &walletAddress);
void checkUpdatesComplete(const QString &result) const;
void miningStatus(bool isMining) const;

208
src/qt/MoneroSettings.cpp Normal file
View File

@@ -0,0 +1,208 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
****************************************************************************/
// Copyright (c) 2014-2019, 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.
#include <QtCore>
#include <QMetaObject>
#include <QSettings>
#include <QPointer>
#include <QJSValue>
#include <QHash>
#include <QMetaProperty>
#include "src/qt/MoneroSettings.h"
/*!
\qmlmodule moneroSettings 1.0
\title Monero Settings QML Component
\ingroup qmlmodules
\brief Provides persistent platform-independent application settings.
This component was introduced in order to have control over where the
configuration file is written. This is needed for Tails OS and
portable installations.
For more information, see: https://doc.qt.io/qt-5/qml-qt-labs-settings-settings.html and
https://github.com/qt/qtdeclarative/blob/v5.12.0/src/imports/settings/qqmlsettings.cpp
To use this module, import the module with the following line:
\code
import moneroComponents.Settings 1.0
\endcode
Usage:
\code
MoneroSettings { id: persistentSettings, property bool foo: true }
\endcode
@TODO: Remove this QML component after migrating to Qt >= 5.12.0, as
`Qt.labs.settings` provides the fileName via a Q_PROPERTY
*/
void MoneroSettings::load()
{
const QMetaObject *mo = this->metaObject();
const int offset = mo->propertyOffset();
const int count = mo->propertyCount();
for (int i = offset; i < count; ++i) {
QMetaProperty property = mo->property(i);
const QVariant previousValue = readProperty(property);
const QVariant currentValue = this->m_settings->value(property.name(), previousValue);
if (!currentValue.isNull() && (!previousValue.isValid()
|| (currentValue.canConvert(previousValue.type()) && previousValue != currentValue))) {
property.write(this, currentValue);
#ifdef QT_DEBUG
qDebug() << "QQmlSettings: load" << property.name() << "setting:" << currentValue << "default:" << previousValue;
#endif
}
// ensure that a non-existent setting gets written
// even if the property wouldn't change later
if (!this->m_settings->contains(property.name()))
this->_q_propertyChanged();
// setup change notifications on first load
if (!this->m_initialized && property.hasNotifySignal()) {
static const int propertyChangedIndex = mo->indexOfSlot("_q_propertyChanged()");
int signalIndex = property.notifySignalIndex();
QMetaObject::connect(this, signalIndex, this, propertyChangedIndex);
}
}
}
void MoneroSettings::_q_propertyChanged()
{
// Called on QML property change
const QMetaObject *mo = this->metaObject();
const int offset = mo->propertyOffset();
const int count = mo->propertyCount();
for (int i = offset; i < count; ++i) {
const QMetaProperty &property = mo->property(i);
const QVariant value = readProperty(property);
this->m_changedProperties.insert(property.name(), value);
#ifdef QT_DEBUG
//qDebug() << "QQmlSettings: cache" << property.name() << ":" << value;
#endif
}
if (this->m_timerId != 0)
this->killTimer(this->m_timerId);
this->m_timerId = this->startTimer(settingsWriteDelay);
}
QVariant MoneroSettings::readProperty(const QMetaProperty &property) const
{
QVariant var = property.read(this);
if (var.userType() == qMetaTypeId<QJSValue>())
var = var.value<QJSValue>().toVariant();
return var;
}
void MoneroSettings::init()
{
if (!this->m_initialized) {
this->m_settings = this->m_fileName.isEmpty() ? new QSettings() : new QSettings(this->m_fileName, QSettings::IniFormat);
#ifdef QT_DEBUG
qDebug() << "QQmlSettings: stored at" << this->m_settings->fileName();
#endif
this->load();
this->m_initialized = true;
}
}
void MoneroSettings::reset()
{
if (this->m_initialized && this->m_settings && !this->m_changedProperties.isEmpty())
this->store();
if (this->m_settings)
delete this->m_settings;
}
void MoneroSettings::store()
{
QHash<const char *, QVariant>::const_iterator it = this->m_changedProperties.constBegin();
while (it != this->m_changedProperties.constEnd()) {
this->m_settings->setValue(it.key(), it.value());
#ifdef QT_DEBUG
//qDebug() << "QQmlSettings: store" << it.key() << ":" << it.value();
#endif
++it;
}
this->m_changedProperties.clear();
}
void MoneroSettings::setFileName(const QString &fileName)
{
if (fileName != this->m_fileName) {
this->reset();
this->m_fileName = fileName;
if (this->m_initialized)
this->load();
}
}
QString MoneroSettings::fileName() const
{
return this->m_fileName;
}
void MoneroSettings::timerEvent(QTimerEvent *event)
{
if (event->timerId() == this->m_timerId) {
killTimer(this->m_timerId);
this->m_timerId = 0;
this->store();
}
QObject::timerEvent(event);
}
void MoneroSettings::componentComplete()
{
this->init();
}
void MoneroSettings::classBegin()
{
}
MoneroSettings::MoneroSettings(QObject *parent) :
QObject(parent)
{
}

81
src/qt/MoneroSettings.h Normal file
View File

@@ -0,0 +1,81 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
****************************************************************************/
// Copyright (c) 2014-2019, 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.
#ifndef MONEROSETTINGS_H
#define MONEROSETTINGS_H
#include <QtQml/qqmlparserstatus.h>
#include <QGuiApplication>
#include <QClipboard>
#include <QObject>
#include <QDebug>
#include <qsettings.h>
static const int settingsWriteDelay = 500; // ms
class MoneroSettings : public QObject, public QQmlParserStatus
{
Q_OBJECT
Q_INTERFACES(QQmlParserStatus)
Q_PROPERTY(QString fileName READ fileName WRITE setFileName FINAL)
public:
explicit MoneroSettings(QObject *parent = nullptr);
QString fileName() const;
void setFileName(const QString &fileName);
public slots:
void _q_propertyChanged();
protected:
void timerEvent(QTimerEvent *event) override;
void classBegin() override;
void componentComplete() override;
private:
QVariant readProperty(const QMetaProperty &property) const;
void init();
void reset();
void load();
void store();
QHash<const char *, QVariant> m_changedProperties;
QSettings *m_settings = NULL;
QString m_fileName = QString("");
bool m_initialized = false;
int m_timerId = 0;
};
#endif // MONEROSETTINGS_H

100
src/qt/TailsOS.cpp Normal file
View File

@@ -0,0 +1,100 @@
#include <QRegExp>
#include <QMessageBox>
#include <QPixmap>
#include <QTranslator>
#include "TailsOS.h"
#include "utils.h"
bool TailsOS::usePersistence = false;
QString TailsOS::tailsPathData = QString("/live/persistence/TailsData_unlocked/");
bool TailsOS::detect()
{
if (!fileExists("/etc/os-release"))
return false;
QByteArray data = fileOpen("/etc/os-release");
QRegularExpression re("TAILS_PRODUCT_NAME=\"Tails\"");
QRegularExpressionMatch os_match = re.match(data);
bool matched = os_match.hasMatch();
#ifdef QT_DEBUG
if (matched)
qDebug() << "Tails OS detected";
#endif
return matched;
}
bool TailsOS::detectDataPersistence()
{
return QDir(QDir::homePath() + "/Persistent").exists();
}
bool TailsOS::detectDotPersistence()
{
return QDir(tailsPathData + "dotfiles").exists();
}
void TailsOS::showDataPersistenceDisabledWarning()
{
QMessageBox msgBox;
msgBox.setText(QObject::tr("Warning: persistence disabled"));
msgBox.setWindowTitle(QObject::tr("Warning: persistence disabled"));
msgBox.setInformativeText(
QObject::tr("Monero GUI has detected that Tails persistence is "
"currently disabled. Any configurations you make inside "
"the Monero GUI will not be saved."
"\n\n"
"In addition, make sure to not save your wallet on the "
"filesystem, as it will be lost at shutdown."
"\n\n"
"To enable Tails persistence, setup an encrypted volume "
"and restart Tails. To gain a startup menu item, "
"enable the Tails \"dotfiles\" feature."));
msgBox.setStandardButtons(QMessageBox::Ok);
msgBox.setDefaultButton(QMessageBox::Ok);
msgBox.setIconPixmap(QPixmap(":/images/tails-grey.png"));
msgBox.exec();
}
void TailsOS::askPersistence()
{
QMessageBox msgBox;
msgBox.setWindowTitle(QObject::tr("Monero GUI"));
msgBox.setText(QObject::tr("Use Tails persistence?"));
msgBox.setInformativeText(
QObject::tr("Persist wallet files and configuration on the encrypted volume?"
"\n\n"
"In addition, you can enable Tails dotfiles persistence "
"to gain a start menu entry.\n"));
msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
msgBox.setDefaultButton(QMessageBox::Yes);
msgBox.setIconPixmap(QPixmap(":/images/tails-grey.png"));
TailsOS::usePersistence = (msgBox.exec() == QMessageBox::Yes);
}
void TailsOS::persistXdgMime(QString filePath, QString data)
{
QFileInfo file(filePath);
QString tailsPath = tailsPathData + "dotfiles/.local/share/applications/";
// write to persistent volume
#ifdef QT_DEBUG
qDebug() << "Writing xdg mime: " << tailsPath + file.fileName();
#endif
QDir().mkpath(tailsPath); // ensure directory exists
fileWrite(tailsPath + file.fileName(), data);
// write to current session
#ifdef QT_DEBUG
qDebug() << "Writing xdg mime: " << file.filePath();
#endif
QDir().mkpath(file.path()); // ensure directory exists
fileWrite(file.filePath(), data);
}

23
src/qt/TailsOS.h Normal file
View File

@@ -0,0 +1,23 @@
#ifndef TAILSOS_H
#define TAILSOS_H
#include <QApplication>
class TailsOS
{
public:
TailsOS();
static bool detect();
static bool detectDataPersistence();
static bool detectDotPersistence();
static void showDataPersistenceDisabledWarning();
static void askPersistence();
static void persistXdgMime(QString filePath, QString data);
static bool usePersistence;
static QString tailsPathData;
};
#endif // TAILSOS_H

View File

@@ -99,8 +99,8 @@ bool IPC::saveCommand(QString cmdString){
return true;
}
bool IPC::saveCommand(const QUrl &url){;
this->saveCommand(url.toString());
bool IPC::saveCommand(const QUrl &url){
return this->saveCommand(url.toString());
}
void IPC::handleConnection(){

View File

@@ -26,11 +26,15 @@
// 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.
#ifndef MIME_H
#define MIME_H
#ifndef MACOSHELPER_H
#define MACOSHELPER_H
#include <QApplication>
class MacOSHelper
{
MacOSHelper() {}
void registerXdgMime(QApplication &app);
public:
static bool isCapsLock();
};
#endif // MIME_H
#endif //MACOSHELPER_H

View File

@@ -27,44 +27,23 @@
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <QtCore>
#include <QApplication>
#include <QFile>
#include <QTextStream>
#include <QtGui>
#include <QtMac>
#include "macoshelper.h"
#include "mime.h"
#include "utils.h"
#import <Foundation/Foundation.h>
#import <Cocoa/Cocoa.h>
#include <CoreFoundation/CoreFoundation.h>
#include <ApplicationServices/ApplicationServices.h>
#include <Availability.h>
void registerXdgMime(QApplication &app){
// MacOS handled via Info.plist
// Windows handled in the installer by rbrunner7
QString xdg = QString(
"[Desktop Entry]\n"
"Name=Monero GUI\n"
"GenericName=Monero-GUI\n"
"X-GNOME-FullName=Monero-GUI\n"
"Comment=Monero GUI\n"
"Keywords=Monero;\n"
"Exec=%1 %u\n"
"Terminal=false\n"
"Type=Application\n"
"Icon=monero\n"
"Categories=Network;GNOME;Qt;\n"
"MimeType=x-scheme-handler/monero;x-scheme-handler/moneroseed\n"
"StartupNotify=true\n"
"X-GNOME-Bugzilla-Bugzilla=GNOME\n"
"X-GNOME-UsesNotifications=true\n"
).arg(app.applicationFilePath());
QString appPath = QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation);
QString filePath = QString("%1/monero-gui.desktop").arg(appPath);
qDebug() << QString("Writing %1").arg(filePath);
QFile file(filePath);
if(file.open(QIODevice::WriteOnly)){
QTextStream out(&file); out << xdg << endl;
file.close();
}
else
file.close();
bool MacOSHelper::isCapsLock()
{
#ifdef __MAC_10_12
NSUInteger flags = [NSEvent modifierFlags] & NSEventModifierFlagDeviceIndependentFlagsMask;
return (flags == NSEventModifierFlagCapsLock);
#else
NSUInteger flags = [NSEvent modifierFlags] & NSDeviceIndependentModifierFlagsMask;
return (flags & NSAlphaShiftKeyMask);
#endif
}

View File

@@ -53,7 +53,7 @@ void Prices::getJSON(const QString url) {
void Prices::gotJSON() {
// Check connectivity
if (!m_reply || m_reply->error() != QNetworkReply::NoError){
this->gotError();
this->gotError("Problem with reply from server. Check connectivity.");
m_reply->deleteLater();
return;
}
@@ -105,6 +105,6 @@ void Prices::gotError() {
}
void Prices::gotError(const QString &message) {
qCritical() << __FUNCTION__ << ": Error: " << message;
qCritical() << "[Fiat API] Error:" << message;
emit priceJsonError(message);
}

View File

@@ -27,15 +27,35 @@
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <QtCore>
#include <QApplication>
#include "src/qt/TailsOS.h"
#include "utils.h"
bool fileExists(QString path) {
QFileInfo check_file(path);
if (check_file.exists() && check_file.isFile())
return check_file.exists() && check_file.isFile();
}
QByteArray fileOpen(QString path) {
QFile file(path);
if(!file.open(QFile::ReadOnly | QFile::Text))
return QByteArray();
QByteArray data = file.readAll();
file.close();
return data;
}
bool fileWrite(QString path, QString data) {
QFile file(path);
if(file.open(QIODevice::WriteOnly)){
QTextStream out(&file); out << data << endl;
file.close();
return true;
else
return false;
}
return false;
}
QString getAccountName(){
@@ -47,6 +67,53 @@ QString getAccountName(){
return accountName;
}
QString xdgMime(QApplication &app){
return QString(
"[Desktop Entry]\n"
"Name=Monero GUI\n"
"GenericName=Monero-GUI\n"
"X-GNOME-FullName=Monero-GUI\n"
"Comment=Monero GUI\n"
"Keywords=Monero;\n"
"Exec=%1 %u\n"
"Terminal=false\n"
"Type=Application\n"
"Icon=monero\n"
"Categories=Network;GNOME;Qt;\n"
"MimeType=x-scheme-handler/monero;x-scheme-handler/moneroseed\n"
"StartupNotify=true\n"
"X-GNOME-Bugzilla-Bugzilla=GNOME\n"
"X-GNOME-UsesNotifications=true\n"
).arg(app.applicationFilePath());
}
void registerXdgMime(QApplication &app){
#ifdef Q_OS_LINUX
// Register desktop entry
// - MacOS handled via Info.plist
// - Windows handled in the installer by rbrunner7
// - Linux written to `QStandardPaths::ApplicationsLocation`
// - Tails written to persistent dotfiles
QString mime = xdgMime(app);
QString appPath = QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation);
QString filePath = QString("%1/monero-gui.desktop").arg(appPath);
if (TailsOS::detect() && TailsOS::detectDotPersistence() && TailsOS::usePersistence) {
TailsOS::persistXdgMime(filePath, mime);
return;
}
QFileInfo file(filePath);
QDir().mkpath(file.path()); // ensure directory exists
#ifdef QT_DEBUG
qDebug() << "Writing xdg mime: " << filePath;
#endif
fileWrite(filePath, mime);
#endif
}
QString randomUserAgent(){
QStringList urand;
urand << "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1"

View File

@@ -31,9 +31,14 @@
#include <QtCore>
#include <QRegExp>
#include <QApplication>
bool fileExists(QString path);
QByteArray fileOpen(QString path);
bool fileWrite(QString path, QString data);
QString getAccountName();
QString xdgMime(QApplication &app);
void registerXdgMime(QApplication &app);
const static QRegExp reURI = QRegExp("^\\w+:\\/\\/([\\w+\\-?\\-_\\-=\\-&]+)");
QString randomUserAgent();

View File

@@ -83,7 +83,7 @@ ColumnLayout {
WizardHeader{
title: qsTr("Give your wallet a password") + translationManager.emptyString
subtitle: qsTr("This password cannot be recovered. If you forget it then the wallet will have to be restored from its 25 word mnemonic seed.") + translationManager.emptyString
subtitle: qsTr("This password cannot be recovered. If you forget it then the wallet will have to be restored from your %1.").arg(!wizardController.walletOptionsIsRecoveringFromDevice ? qsTr("25 word mnemonic seed") : qsTr("hardware wallet"))+ translationManager.emptyString
}
MoneroComponents.WarningBox {
@@ -97,23 +97,12 @@ ColumnLayout {
TextInput {
id: progressText
anchors.top: parent.top
anchors.topMargin: 6
Layout.topMargin: 6
Layout.bottomMargin: 6
font.family: MoneroComponents.Style.fontMedium.name
font.pixelSize: 14
font.bold: false
color: MoneroComponents.Style.defaultFontColor
text: root.passwordStrengthText + '-'
height: 18
passwordCharacter: "*"
}
TextInput {
id: progressTextValue
font.family: MoneroComponents.Style.fontMedium.name
font.pixelSize: 13
font.bold: true
color: MoneroComponents.Style.defaultFontColor
height: 18
passwordCharacter: "*"
}

View File

@@ -273,12 +273,13 @@ Rectangle {
clip: true
ScrollBar.vertical: ScrollBar {
parent: wizardFlickable.parent
parent: wizardController
anchors.left: parent.right
anchors.leftMargin: 3
anchors.leftMargin: -14 // 10 margin + 4 scrollbar width
anchors.top: parent.top
anchors.topMargin: 4
anchors.topMargin: persistentSettings.customDecorations ? 60 : 10
anchors.bottom: parent.bottom
anchors.bottomMargin: persistentSettings.customDecorations ? 15 : 10
}
onFlickingChanged: {
@@ -498,15 +499,15 @@ Rectangle {
splash.close()
console.log(">>> wallet passphrase needed: ");
passphraseDialog.onAcceptedCallback = function() {
walletManager.onPassphraseEntered(passphraseDialog.passphrase);
passwordDialog.onAcceptedPassphraseCallback = function() {
walletManager.onPassphraseEntered(passwordDialog.password);
creatingWalletDeviceSplash();
}
passphraseDialog.onRejectedCallback = function() {
passwordDialog.onRejectedPassphraseCallback = function() {
walletManager.onPassphraseEntered("", true);
creatingWalletDeviceSplash();
}
passphraseDialog.open()
passwordDialog.openPassphraseDialog()
}
function onDeviceButtonRequest(code){

View File

@@ -151,7 +151,7 @@ Rectangle {
labelFontSize: 14
copyButton: false
readOnly: true
text: Utils.roundDownToNearestThousand(wizardController.m_wallet.walletCreationHeight)
text: Utils.roundDownToNearestThousand(wizardController.m_wallet ? wizardController.m_wallet.walletCreationHeight : 0)
}
MoneroComponents.WarningBox {

View File

@@ -69,7 +69,7 @@ ColumnLayout {
TextArea {
Layout.fillWidth: true
anchors.horizontalCenter: parent.horizontalCenter
Layout.alignment: Qt.AlignCenter
visible: parent.subtitle !== ""
color: MoneroComponents.Style.dimmedFontColor

View File

@@ -60,7 +60,7 @@ Rectangle {
id: textWelcome
opacity: 0
Layout.preferredWidth: parent.width / 1.3
anchors.horizontalCenter: parent.horizontalCenter
Layout.alignment: Qt.AlignCenter
color: MoneroComponents.Style.defaultFontColor
text: "Welcome - Wilkommen - Bonvenon - Bienvenido - Bienvenue - Välkommen - Selamat datang - Benvenuto - 歡迎 - Welkom - Bem Vindo - добро пожаловать"
@@ -97,7 +97,7 @@ Rectangle {
}
Layout.preferredWidth: size
Layout.preferredHeight: size
anchors.horizontalCenter: parent.horizontalCenter
Layout.alignment: Qt.AlignCenter
mipmap: true
property bool animSlow: false
@@ -149,7 +149,7 @@ Rectangle {
id: buttonsGrid
opacity: 0
columns: isMobile ? 1 : 2
anchors.horizontalCenter: parent.horizontalCenter
Layout.alignment: Qt.AlignCenter
Layout.topMargin: 20
Layout.fillWidth: true
columnSpacing: 20
@@ -190,7 +190,7 @@ Rectangle {
MoneroComponents.TextPlain {
id: versionText
opacity: 0
anchors.horizontalCenter: parent.horizontalCenter
Layout.alignment: Qt.AlignCenter
font.bold: true
font.pixelSize: 12
font.family: MoneroComponents.Style.fontRegular.name

View File

@@ -57,12 +57,6 @@ ColumnLayout {
value: wizardController.language_language
}
WizardSummaryItem {
Layout.fillWidth: true
header: qsTr("Wallet name") + translationManager.emptyString
value: walletOptionsName
}
WizardSummaryItem {
Layout.fillWidth: true
header: qsTr("Restore height") + translationManager.emptyString