Compare commits

..

2 Commits

Author SHA1 Message Date
luigi1111
a77a5909cf Merge pull request #2215 (again)
bf785bb build: checkout v0.14.1.0 tag (selsta)
2019-06-25 14:33:46 -05:00
selsta
bf785bb388 build: checkout v0.14.1.0 tag 2019-06-14 16:15:36 +02:00
186 changed files with 33438 additions and 34567 deletions

View File

@@ -1,34 +0,0 @@
name: GUI build
on: [push, pull_request]
jobs:
build-macos:
runs-on: macOS-latest
steps:
- uses: actions/checkout@v1
- name: update brew and install dependencies
run: brew update && brew install boost hidapi zmq libpgm unbound libsodium miniupnpc ldns expat doxygen graphviz libunwind-headers protobuf qt5
- name: build
run: export PATH=$PATH:/usr/local/opt/qt/bin && ./build.sh
- name: test qml
run: build/release/bin/monero-wallet-gui.app/Contents/MacOS/monero-wallet-gui --test-qml
build-ubuntu:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: update apt
run: sudo apt update
- name: install monero dependencies
run: sudo apt -y install build-essential cmake libboost-all-dev miniupnpc libunbound-dev graphviz doxygen libunwind8-dev pkg-config libssl-dev libzmq3-dev libsodium-dev libhidapi-dev libnorm-dev libusb-1.0-0-dev libpgm-dev
- name: install monero gui dependencies
run: sudo apt -y install qtbase5-dev qt5-default qtdeclarative5-dev qml-module-qtquick-controls qml-module-qtquick-controls2 qml-module-qtquick-dialogs qml-module-qtquick-xmllistmodel qml-module-qt-labs-settings qml-module-qt-labs-folderlistmodel qttools5-dev-tools qml-module-qtquick-templates2 libqt5svg5-dev xvfb
- name: build
run: ./build.sh
- name: test qml
run: xvfb-run -a build/release/bin/monero-wallet-gui --test-qml

19
.gitignore vendored
View File

@@ -13,22 +13,3 @@ 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

@@ -40,17 +40,17 @@ import "components/effects/" as MoneroEffects
Rectangle {
id: panel
property int currentAccountIndex
property alias currentAccountLabel: accountLabel.text
property string balanceString: "?.??"
property string balanceUnlockedString: "?.??"
property string balanceFiatString: "?.??"
property string minutesToUnlock: ""
property bool isSyncing: false
property alias unlockedBalanceText: unlockedBalanceText.text
property alias unlockedBalanceVisible: unlockedBalanceText.visible
property alias unlockedBalanceLabelVisible: unlockedBalanceLabel.visible
property alias balanceLabelText: balanceLabel.text
property alias balanceText: balanceText.text
property alias balanceTextFiat: balanceTextFiat.text
property alias unlockedBalanceTextFiat: unlockedBalanceTextFiat.text
property alias networkStatus : networkStatus
property alias progressBar : progressBar
property alias daemonProgressBar : daemonProgressBar
property alias minutesToUnlockTxt: unlockedBalanceLabel.text
property int titleBarHeight: 50
property string copyValue: ""
Clipboard { id: clipboard }
@@ -84,7 +84,7 @@ Rectangle {
menuColumn.previousButton.checked = true
}
width: 300
width: (isMobile)? appWindow.width : 300
color: "transparent"
anchors.bottom: parent.bottom
anchors.top: parent.top
@@ -108,18 +108,19 @@ Rectangle {
visible: true
z: 2
id: column1
height: 175
height: 210
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
anchors.topMargin: (persistentSettings.customDecorations)? 50 : 0
Item {
RowLayout {
Item {
anchors.left: parent.left
anchors.top: parent.top
anchors.topMargin: 20
anchors.leftMargin: 20
anchors.verticalCenter: parent.verticalCenter
height: 490
width: 260
@@ -127,9 +128,9 @@ Rectangle {
id: card
visible: !isOpenGL || MoneroComponents.Style.blackTheme
width: 260
height: 135
height: 170
fillMode: Image.PreserveAspectFit
source: MoneroComponents.Style.blackTheme ? "qrc:///images/card-background-black.png" : "qrc:///images/card-background-white.png"
source: "qrc:///images/card-background.png"
}
DropShadow {
@@ -171,6 +172,57 @@ Rectangle {
color: "#ff9323"
themeTransition: false
}
Rectangle {
height: (logoutImage.height + 8)
width: (logoutImage.width + 8)
color: "transparent"
anchors.right: parent.right
anchors.rightMargin: 8
anchors.top: parent.top
anchors.topMargin: 25
Image {
id: logoutImage
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
height: 16
width: 13
source: "qrc:///images/logout.png"
}
MouseArea{
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
middlePanel.addressBookView.clearFields();
middlePanel.transferView.clearFields();
middlePanel.receiveView.clearFields();
appWindow.showWizard();
}
}
}
MoneroComponents.Label {
fontSize: 20
text: "¥"
color: "white"
visible: persistentSettings.fiatPriceEnabled
anchors.right: parent.right
anchors.rightMargin: 45
anchors.top: parent.top
anchors.topMargin: 28
themeTransition: false
MouseArea{
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
persistentSettings.fiatPriceToggle = !persistentSettings.fiatPriceToggle
}
}
}
}
Item {
@@ -178,154 +230,181 @@ Rectangle {
anchors.top: parent.top
anchors.topMargin: 20
anchors.leftMargin: 20
anchors.verticalCenter: parent.verticalCenter
height: 490
width: 50
MoneroComponents.Label {
fontSize: 12
id: accountIndex
text: qsTr("Account") + translationManager.emptyString + " #" + currentAccountIndex
color: MoneroComponents.Style.blackTheme ? "white" : "black"
anchors.left: parent.left
anchors.leftMargin: 60
anchors.top: parent.top
anchors.topMargin: 23
themeTransition: false
MouseArea{
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: appWindow.showPageRequest("Account")
}
}
MoneroComponents.Label {
fontSize: 16
id: accountLabel
textWidth: 170
color: MoneroComponents.Style.blackTheme ? "white" : "black"
anchors.left: parent.left
anchors.leftMargin: 60
anchors.top: parent.top
anchors.topMargin: 36
themeTransition: false
elide: Text.ElideRight
MouseArea {
hoverEnabled: true
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: appWindow.showPageRequest("Account")
}
}
MoneroComponents.Label {
fontSize: 16
visible: isSyncing
text: qsTr("Syncing...")
color: MoneroComponents.Style.blackTheme ? "white" : "black"
anchors.left: parent.left
anchors.leftMargin: 20
anchors.bottom: currencyLabel.top
anchors.bottomMargin: 15
themeTransition: false
}
MoneroComponents.TextPlain {
id: currencyLabel
font.pixelSize: 16
text: {
if (persistentSettings.fiatPriceEnabled && persistentSettings.fiatPriceToggle) {
return appWindow.fiatApiCurrencySymbol();
} else {
return "XMR"
}
}
color: MoneroComponents.Style.blackTheme ? "white" : "black"
visible: !(persistentSettings.fiatPriceToggle && persistentSettings.fiatPriceEnabled)
id: balanceText
themeTransition: false
anchors.left: parent.left
anchors.leftMargin: 20
anchors.top: parent.top
anchors.topMargin: 100
themeTransition: false
MouseArea {
hoverEnabled: true
anchors.fill: parent
visible: persistentSettings.fiatPriceEnabled
cursorShape: Qt.PointingHandCursor
onClicked: persistentSettings.fiatPriceToggle = !persistentSettings.fiatPriceToggle
}
}
MoneroComponents.TextPlain {
id: balancePart1
themeTransition: false
anchors.left: parent.left
anchors.leftMargin: 58
anchors.baseline: currencyLabel.baseline
color: MoneroComponents.Style.blackTheme ? "white" : "black"
text: {
if (persistentSettings.fiatPriceEnabled && persistentSettings.fiatPriceToggle) {
return balanceFiatString.split('.')[0] + "."
} else {
return balanceString.split('.')[0] + "."
}
}
anchors.topMargin: 76
font.family: "Arial"
color: "#FFFFFF"
text: "N/A"
// dynamically adjust text size
font.pixelSize: {
var defaultSize = 29;
var digits = (balancePart1.text.length - 1)
if (digits > 2 && !(persistentSettings.fiatPriceEnabled && persistentSettings.fiatPriceToggle)) {
return defaultSize - 1.1 * digits
} else {
return defaultSize
if (persistentSettings.hideBalance) {
return 20;
}
var digits = text.split('.')[0].length
var defaultSize = 22;
if(digits > 2) {
return defaultSize - 1.1*digits
}
return defaultSize;
}
MouseArea {
id: balancePart1MouseArea
hoverEnabled: true
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onEntered: {
balancePart1.color = MoneroComponents.Style.orange
balancePart2.color = MoneroComponents.Style.orange
parent.color = MoneroComponents.Style.orange
}
onExited: {
balancePart1.color = Qt.binding(function() { return MoneroComponents.Style.blackTheme ? "white" : "black" })
balancePart2.color = Qt.binding(function() { return MoneroComponents.Style.blackTheme ? "white" : "black" })
parent.color = MoneroComponents.Style.white
}
onClicked: {
console.log("Copied to clipboard");
clipboard.setText(balancePart1.text + balancePart2.text);
clipboard.setText(parent.text);
appWindow.showStatusMessage(qsTr("Copied to clipboard"),3)
}
}
}
MoneroComponents.TextPlain {
id: balancePart2
visible: !balanceText.visible
id: balanceTextFiat
themeTransition: false
anchors.left: balancePart1.right
anchors.leftMargin: 2
anchors.baseline: currencyLabel.baseline
color: MoneroComponents.Style.blackTheme ? "white" : "black"
text: {
if (persistentSettings.fiatPriceEnabled && persistentSettings.fiatPriceToggle) {
return balanceFiatString.split('.')[1]
} else {
return balanceString.split('.')[1]
}
}
font.pixelSize: 16
anchors.left: parent.left
anchors.leftMargin: 20
anchors.top: parent.top
anchors.topMargin: 76
font.family: "Arial"
color: "#FFFFFF"
text: "N/A"
font.pixelSize: balanceText.font.pixelSize
MouseArea {
hoverEnabled: true
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onEntered: balancePart1MouseArea.entered()
onExited: balancePart1MouseArea.exited()
onClicked: balancePart1MouseArea.clicked(mouse)
onEntered: {
parent.color = MoneroComponents.Style.orange
}
onExited: {
parent.color = MoneroComponents.Style.white
}
onClicked: {
console.log("Copied to clipboard");
clipboard.setText(parent.text);
appWindow.showStatusMessage(qsTr("Copied to clipboard"),3)
}
}
}
MoneroComponents.TextPlain {
id: unlockedBalanceText
visible: !(persistentSettings.fiatPriceToggle && persistentSettings.fiatPriceEnabled)
themeTransition: false
anchors.left: parent.left
anchors.leftMargin: 20
anchors.top: parent.top
anchors.topMargin: 126
font.family: "Arial"
color: "#FFFFFF"
text: "N/A"
// dynamically adjust text size
font.pixelSize: {
if (persistentSettings.hideBalance) {
return 20;
}
var digits = text.split('.')[0].length
var defaultSize = 20;
if(digits > 3) {
return defaultSize - 0.6*digits
}
return defaultSize;
}
MouseArea {
hoverEnabled: true
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onEntered: {
parent.color = MoneroComponents.Style.orange
}
onExited: {
parent.color = MoneroComponents.Style.white
}
onClicked: {
console.log("Copied to clipboard");
clipboard.setText(parent.text);
appWindow.showStatusMessage(qsTr("Copied to clipboard"),3)
}
}
}
MoneroComponents.TextPlain {
id: unlockedBalanceTextFiat
themeTransition: false
visible: !unlockedBalanceText.visible
anchors.left: parent.left
anchors.leftMargin: 20
anchors.top: parent.top
anchors.topMargin: 126
font.family: "Arial"
color: "#FFFFFF"
text: "N/A"
font.pixelSize: unlockedBalanceText.font.pixelSize
MouseArea {
hoverEnabled: true
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onEntered: {
parent.color = MoneroComponents.Style.orange
}
onExited: {
parent.color = MoneroComponents.Style.white
}
onClicked: {
console.log("Copied to clipboard");
clipboard.setText(parent.text);
appWindow.showStatusMessage(qsTr("Copied to clipboard"),3)
}
}
}
MoneroComponents.Label {
id: unlockedBalanceLabel
visible: true
text: qsTr("Unlocked balance") + translationManager.emptyString
color: "white"
fontSize: 14
anchors.left: parent.left
anchors.leftMargin: 20
anchors.top: parent.top
anchors.topMargin: 110
themeTransition: false
}
MoneroComponents.Label {
visible: !isMobile
id: balanceLabel
text: qsTr("Balance") + translationManager.emptyString
color: "white"
fontSize: 14
anchors.left: parent.left
anchors.leftMargin: 20
anchors.top: parent.top
anchors.topMargin: 60
elide: Text.ElideRight
textWidth: 238
themeTransition: false
}
Item { //separator
anchors.left: parent.left
anchors.right: parent.right
@@ -341,7 +420,7 @@ Rectangle {
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.top: column1.bottom
anchors.top: (isMobile)? parent.top : column1.bottom
color: "transparent"
Flickable {

View File

@@ -34,7 +34,6 @@
#include <QDebug>
#include "Logger.h"
#include "src/qt/TailsOS.h"
#include "wallet/api/wallet2_api.h"
// default log path by OS (should be writable)
@@ -67,9 +66,6 @@ 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

@@ -46,6 +46,11 @@ Rectangle {
property Item currentView
property Item previousView
property bool basicMode : isMobile
property string balanceLabelText: qsTr("Balance") + translationManager.emptyString
property string balanceText
property string unlockedBalanceLabelText: qsTr("Unlocked Balance") + translationManager.emptyString
property string unlockedBalanceText
property int minHeight: (appWindow.height > 800) ? appWindow.height : 800
property alias contentHeight: mainFlickable.contentHeight
property alias flickable: mainFlickable
@@ -168,6 +173,23 @@ Rectangle {
}
]
// color stripe at the top
Row {
id: styledRow
visible: currentView !== merchantView
height: 4
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
z: parent.z + 1
Rectangle { height: 4; width: parent.width / 5; color: "#FFE00A" }
Rectangle { height: 4; width: parent.width / 5; color: "#6B0072" }
Rectangle { height: 4; width: parent.width / 5; color: "#FF6C3C" }
Rectangle { height: 4; width: parent.width / 5; color: "#FFD781" }
Rectangle { height: 4; width: parent.width / 5; color: "#FF4F41" }
}
ColumnLayout {
anchors.fill: parent
anchors.margins: {
@@ -178,7 +200,6 @@ Rectangle {
}
anchors.topMargin: appWindow.persistentSettings.customDecorations ? 50 : 0
anchors.bottomMargin: 0
spacing: 0
Flickable {
@@ -188,13 +209,13 @@ Rectangle {
clip: true
ScrollBar.vertical: ScrollBar {
parent: root
parent: mainFlickable.parent
anchors.left: parent.right
anchors.leftMargin: -14 // 10 margin + 4 scrollbar width
anchors.leftMargin: 3
anchors.top: parent.top
anchors.topMargin: persistentSettings.customDecorations ? 60 : 10
anchors.topMargin: 4
anchors.bottom: parent.bottom
anchors.bottomMargin: persistentSettings.customDecorations ? 15 : 10
anchors.bottomMargin: persistentSettings.customDecorations ? 4 : 0
}
onFlickingChanged: {
@@ -237,7 +258,7 @@ Rectangle {
Rectangle {
id: borderLeft
visible: middlePanel.state !== "Merchant"
anchors.top: parent.top
anchors.top: styledRow.bottom
anchors.bottom: parent.bottom
anchors.left: parent.left
width: 1

View File

@@ -9,7 +9,7 @@ Copyright (c) 2014-2019, The Monero Project
- Mail: [dev@getmonero.org](mailto:dev@getmonero.org)
- Github: [https://github.com/monero-project/monero-gui](https://github.com/monero-project/monero-gui)
- IRC: [#monero-dev on Freenode](irc://chat.freenode.net/#monero-dev)
- Translation platform (Weblate): [translate.getmonero.org](https://translate.getmonero.org)
- Translation platform (Pootle): [translate.getmonero.org](https://translate.getmonero.org)
## Vulnerability response
@@ -75,8 +75,6 @@ Packaging for your favorite distribution would be a welcome contribution!
## Compiling the Monero GUI from source
*Note*: Qt 5.9.7 is the minimum version required to build the GUI.
### On Linux:
(Tested on Ubuntu 17.10 x64, Ubuntu 18.04 x64 and Gentoo x64)
@@ -85,7 +83,7 @@ Packaging for your favorite distribution would be a welcome contribution!
- For Debian distributions (Debian, Ubuntu, Mint, Tails...)
`sudo apt install build-essential cmake libboost-all-dev miniupnpc libunbound-dev graphviz doxygen libunwind8-dev pkg-config libssl-dev libzmq3-dev libsodium-dev libhidapi-dev libnorm-dev libusb-1.0-0-dev libpgm-dev`
`sudo apt install build-essential cmake libboost-all-dev miniupnpc libunbound-dev graphviz doxygen libunwind8-dev pkg-config libssl-dev libzmq3-dev libsodium-dev libhidapi-dev`
- For Gentoo
@@ -93,11 +91,11 @@ Packaging for your favorite distribution would be a welcome contribution!
- For Fedora
`sudo dnf install make automake cmake gcc-c++ boost-devel miniupnpc-devel graphviz doxygen unbound-devel libunwind-devel pkgconfig openssl-devel libcurl-devel hidapi-devel libusb-devel zeromq-devel`
`sudo dnf install make automake cmake gcc-c++ boost-devel miniupnpc-devel graphviz doxygen unbound-devel libunwind-devel pkgconfig openssl-devel libcurl-devel hidapi-devel libusb-devel`
2. Install Qt:
*Note*: The Qt 5.9.7 or newer requirement makes **some** distributions (mostly based on debian, like Ubuntu 16.x or Linux Mint 18.x) obsolete due to their repositories containing an older Qt version.
*Note*: Qt 5.9.7 is the minimum version required to build the GUI. This makes **some** distributions (mostly based on debian, like Ubuntu 16.x or Linux Mint 18.x) obsolete due to their repositories containing an older Qt version.
The recommended way is to install 5.9.7 from the [official Qt installer](https://www.qt.io/download-qt-installer) or [compiling it yourself](https://wiki.qt.io/Install_Qt_5_on_Ubuntu). This ensures you have the correct version. Higher versions *can* work but as it differs from our production build target, slight differences may occur.
@@ -167,8 +165,9 @@ The executable can be found in the build/release/bin folder.
5. Add the Qt bin directory to your path
- 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`
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
6. Grab an up-to-date copy of the monero-gui repository

View File

@@ -38,10 +38,8 @@ Item {
property alias text: label.text
property string checkedIcon: "qrc:///images/check-white.svg"
property string uncheckedIcon
property bool fontAwesomeIcons: false
property int imgWidth: 13
property int imgHeight: 13
property bool toggleOnClick: true
property bool checked: false
property alias background: backgroundRect.color
property bool border: true
@@ -53,16 +51,14 @@ Item {
width: checkBoxLayout.width
function toggle(){
if (checkBox.toggleOnClick) {
checkBox.checked = !checkBox.checked
}
checkBox.checked = !checkBox.checked
checkBox.clicked()
}
RowLayout {
id: checkBoxLayout
layoutDirection: iconOnTheLeft ? Qt.LeftToRight : Qt.RightToLeft
spacing: 10
spacing: (!isMobile ? 10 : 8)
Item {
id: checkMark
@@ -90,11 +86,9 @@ Item {
width: checkBox.imgWidth
height: checkBox.imgHeight
color: MoneroComponents.Style.defaultFontColor
fontAwesomeFallbackIcon: checkBox.fontAwesomeIcons ? getIcon() : FontAwesome.plus
fontAwesomeFallbackIcon: FontAwesome.plus
fontAwesomeFallbackSize: 14
image: checkBox.fontAwesomeIcons ? "" : getIcon()
function getIcon() {
image: {
if (checkBox.checked || checkBox.uncheckedIcon == "")
return checkBox.checkedIcon;
return checkBox.uncheckedIcon;

View File

@@ -1,40 +0,0 @@
import QtQuick 2.9
import QtQuick.Controls 2.2
import FontAwesome 1.0
import "../components" as MoneroComponents
MouseArea {
signal paste()
id: root
acceptedButtons: Qt.RightButton
anchors.fill: parent
onClicked: {
if (mouse.button === Qt.RightButton)
contextMenu.open()
}
Menu {
id: contextMenu
background: Rectangle {
border.color: MoneroComponents.Style.buttonBackgroundColorDisabledHover
border.width: 1
radius: 2
color: MoneroComponents.Style.buttonBackgroundColorDisabled
}
padding: 1
width: 100
x: root.mouseX
y: root.mouseY
MoneroComponents.ContextMenuItem {
enabled: root.parent.canPaste === true
glyphIcon: FontAwesome.paste
onTriggered: root.paste()
text: qsTr("Paste") + translationManager.emptyString
}
}
}

View File

@@ -1,52 +0,0 @@
import QtQuick 2.9
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.1
import FontAwesome 1.0
import "../components" as MoneroComponents
MenuItem {
id: menuItem
property bool glyphIconSolid: true
property alias glyphIcon: glyphIcon.text
background: Rectangle {
color: MoneroComponents.Style.buttonBackgroundColorDisabledHover
opacity: mouse.containsMouse ? 1 : 0
MouseArea {
id: mouse
anchors.fill: parent
hoverEnabled: true
onClicked: menuItem.triggered()
visible: menuItem.enabled
}
}
contentItem: RowLayout {
anchors.fill: parent
anchors.leftMargin: 10
anchors.rightMargin: 10
opacity: menuItem.enabled ? 1 : 0.4
spacing: 8
Text {
id: glyphIcon
color: MoneroComponents.Style.buttonTextColor
font.family: glyphIconSolid ? FontAwesome.fontFamilySolid : FontAwesome.fontFamily
font.pixelSize: 14
font.styleName: glyphIconSolid ? "Solid" : "Regular"
}
Text {
color: MoneroComponents.Style.buttonTextColor
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 14
Layout.fillWidth: true
text: menuItem.text
}
}
}

View File

@@ -178,11 +178,7 @@ Window {
onAccepted: {
if(text.length > 0) {
textArea.logCommand(">>> " + text)
daemonManager.sendCommandAsync(text.split(" "), currentWallet.nettype, function(result) {
if (!result) {
appWindow.showStatusMessage(qsTr("Failed to send command"), 3);
}
});
daemonManager.sendCommand(text, currentWallet.nettype);
}
text = ""
}

View File

@@ -28,7 +28,6 @@
import QtQuick 2.9
import QtQuick.Controls 1.2
import QtQuick.Controls 2.2 as QtQuickControls2
import QtQuick.Layouts 1.2
import QtGraphicalEffects 1.0
import QtQuick.Controls.Styles 1.2
@@ -38,7 +37,8 @@ import "effects/" as MoneroEffects
Item {
id: datePicker
readonly property alias expanded: popup.visible
z: parent.z + 1
property bool expanded: false
property date currentDate
property bool showCurrentDate: true
property color backgroundColor : MoneroComponents.Style.appWindowBorderColor
@@ -52,6 +52,19 @@ Item {
onExpandedChanged: if(expanded) appWindow.currentItem = datePicker
function hide() { datePicker.expanded = false }
function containsPoint(px, py) {
if(px < 0)
return false
if(px > width)
return false
if(py < 0)
return false
if(py > height + calendarRect.height)
return false
return true
}
Rectangle {
id: inputLabelRect
color: "transparent"
@@ -240,7 +253,7 @@ Item {
MouseArea {
anchors.fill: parent
onClicked: datePicker.expanded ? popup.close() : popup.open()
onClicked: datePicker.expanded = !datePicker.expanded
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
}
@@ -248,204 +261,195 @@ Item {
}
}
QtQuickControls2.Popup {
id: popup
padding: 0
Rectangle {
id: calendarRect
anchors.left: parent.left
anchors.right: parent.right
anchors.top: head.bottom
anchors.topMargin: 10
color: MoneroComponents.Style.middlePanelBackgroundColor
border.width: 1
border.color: MoneroComponents.Style.appWindowBorderColor
height: datePicker.expanded ? calendar.height + 2 : 0
clip: true
Behavior on height {
NumberAnimation { duration: 100; easing.type: Easing.InQuad }
}
Rectangle {
id: calendarRect
width: head.width
x: head.x
y: head.y + head.height + 10
anchors.left: parent.left
anchors.right: parent.right
anchors.leftMargin: 1
anchors.rightMargin: 1
anchors.top: parent.top
color: MoneroComponents.Style.appWindowBorderColor
height: 1
}
color: MoneroComponents.Style.middlePanelBackgroundColor
border.width: 1
border.color: MoneroComponents.Style.appWindowBorderColor
height: datePicker.expanded ? calendar.height + 2 : 0
clip: true
Calendar {
id: calendar
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
anchors.margins: 1
anchors.bottomMargin: 10
height: 220
frameVisible: false
Behavior on height {
NumberAnimation { duration: 100; easing.type: Easing.InQuad }
}
style: CalendarStyle {
gridVisible: false
background: Rectangle { color: MoneroComponents.Style.middlePanelBackgroundColor }
dayDelegate: Item {
z: parent.z + 1
implicitHeight: implicitWidth
implicitWidth: calendar.width / 7
MouseArea {
anchors.fill: parent
}
Rectangle {
id: dayRect
anchors.fill: parent
radius: parent.implicitHeight / 2
color: {
if(dayArea.pressed && styleData.visibleMonth)
return MoneroComponents.Style.blackTheme ? "#20FFFFFF" : "#10000000"
return "transparent";
}
}
Rectangle {
anchors.left: parent.left
anchors.right: parent.right
anchors.leftMargin: 1
anchors.rightMargin: 1
anchors.top: parent.top
color: MoneroComponents.Style.appWindowBorderColor
height: 1
}
MoneroComponents.TextPlain {
id: dayText
anchors.centerIn: parent
font.family: MoneroComponents.Style.fontMonoRegular.name
font.pixelSize: {
if(!styleData.visibleMonth) return 12
return 14
}
font.bold: {
if(dayArea.pressed || styleData.visibleMonth) return true;
return false;
}
text: styleData.date.getDate()
themeTransition: false
color: {
if(!styleData.visibleMonth) return MoneroComponents.Style.lightGreyFontColor
if(dayArea.pressed) return MoneroComponents.Style.defaultFontColor
if(styleData.today) return MoneroComponents.Style.orange
return MoneroComponents.Style.defaultFontColor
}
}
Calendar {
id: calendar
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
anchors.margins: 1
anchors.bottomMargin: 10
height: 220
frameVisible: false
style: CalendarStyle {
gridVisible: false
background: Rectangle { color: MoneroComponents.Style.middlePanelBackgroundColor }
dayDelegate: Item {
z: parent.z + 1
implicitHeight: implicitWidth
implicitWidth: calendar.width / 7
Rectangle {
id: dayRect
anchors.fill: parent
radius: parent.implicitHeight / 2
color: {
if(dayArea.pressed && styleData.visibleMonth)
return MoneroComponents.Style.blackTheme ? "#20FFFFFF" : "#10000000"
return "transparent";
MouseArea {
id: dayArea
anchors.fill: parent
hoverEnabled: true
onEntered: dayRect.color = MoneroComponents.Style.blackTheme ? "#20FFFFFF" : "#10000000"
onExited: dayRect.color = "transparent"
cursorShape: Qt.PointingHandCursor
onClicked: {
if(styleData.visibleMonth) {
currentDate = styleData.date
datePicker.expanded = false
} else {
var date = styleData.date
if(date.getMonth() > calendar.visibleMonth)
calendar.showNextMonth()
else calendar.showPreviousMonth()
}
datePicker.dateChanged();
}
}
}
dayOfWeekDelegate: Item {
implicitHeight: 20
implicitWidth: calendar.width / 7
MoneroComponents.TextPlain {
anchors.centerIn: parent
elide: Text.ElideRight
font.family: MoneroComponents.Style.fontMonoRegular.name
font.pixelSize: 12
color: MoneroComponents.Style.lightGreyFontColor
themeTransition: false
text: {
var locale = Qt.locale()
return locale.dayName(styleData.dayOfWeek, Locale.ShortFormat)
}
}
}
navigationBar: Rectangle {
color: MoneroComponents.Style.middlePanelBackgroundColor
implicitWidth: calendar.width
implicitHeight: 30
MoneroComponents.TextPlain {
anchors.centerIn: parent
font.family: MoneroComponents.Style.fontMonoRegular.name
font.pixelSize: 14
color: MoneroComponents.Style.dimmedFontColor
themeTransition: false
text: styleData.title
}
Item {
anchors.left: parent.left
anchors.leftMargin: 4
anchors.top: parent.top
anchors.bottom: parent.bottom
width: height
Image {
id: prevMonthIcon
anchors.centerIn: parent
source: "qrc:///images/prevMonth.png"
visible: false
}
MoneroComponents.TextPlain {
id: dayText
anchors.centerIn: parent
font.family: MoneroComponents.Style.fontMonoRegular.name
font.pixelSize: {
if(!styleData.visibleMonth) return 12
return 14
}
font.bold: {
if(dayArea.pressed || styleData.visibleMonth) return true;
return false;
}
text: styleData.date.getDate()
themeTransition: false
color: {
if(!styleData.visibleMonth) return MoneroComponents.Style.lightGreyFontColor
if(dayArea.pressed) return MoneroComponents.Style.defaultFontColor
if(styleData.today) return MoneroComponents.Style.orange
return MoneroComponents.Style.defaultFontColor
}
ColorOverlay {
source: prevMonthIcon
anchors.fill: prevMonthIcon
color: MoneroComponents.Style.defaultFontColor
opacity: 0.5
}
MouseArea {
id: dayArea
anchors.fill: parent
hoverEnabled: true
onEntered: dayRect.color = MoneroComponents.Style.blackTheme ? "#20FFFFFF" : "#10000000"
onExited: dayRect.color = "transparent"
cursorShape: Qt.PointingHandCursor
onClicked: {
if(styleData.visibleMonth) {
currentDate = styleData.date
popup.close()
} else {
var date = styleData.date
if(date.getMonth() > calendar.visibleMonth)
calendar.showNextMonth()
else calendar.showPreviousMonth()
}
datePicker.dateChanged();
}
anchors.fill: parent
onClicked: calendar.showPreviousMonth()
}
}
dayOfWeekDelegate: Item {
implicitHeight: 20
implicitWidth: calendar.width / 7
Item {
anchors.right: parent.right
anchors.rightMargin: 4
anchors.top: parent.top
anchors.bottom: parent.bottom
width: height
MoneroComponents.TextPlain {
Image {
id: nextMonthIcon
anchors.centerIn: parent
elide: Text.ElideRight
font.family: MoneroComponents.Style.fontMonoRegular.name
font.pixelSize: 12
color: MoneroComponents.Style.lightGreyFontColor
themeTransition: false
text: {
var locale = Qt.locale()
return locale.dayName(styleData.dayOfWeek, Locale.ShortFormat)
}
}
}
navigationBar: Rectangle {
color: MoneroComponents.Style.middlePanelBackgroundColor
implicitWidth: calendar.width
implicitHeight: 30
MoneroComponents.TextPlain {
anchors.centerIn: parent
font.family: MoneroComponents.Style.fontMonoRegular.name
font.pixelSize: 14
color: MoneroComponents.Style.dimmedFontColor
themeTransition: false
text: styleData.title
source: "qrc:///images/prevMonth.png"
visible: false
}
Item {
anchors.left: parent.left
anchors.leftMargin: 4
anchors.top: parent.top
anchors.bottom: parent.bottom
width: height
Image {
id: prevMonthIcon
anchors.centerIn: parent
source: "qrc:///images/prevMonth.png"
visible: false
}
ColorOverlay {
source: prevMonthIcon
anchors.fill: prevMonthIcon
color: MoneroComponents.Style.defaultFontColor
opacity: 0.5
}
MouseArea {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
anchors.fill: parent
onClicked: calendar.showPreviousMonth()
}
ColorOverlay {
source: nextMonthIcon
anchors.fill: nextMonthIcon
color: MoneroComponents.Style.defaultFontColor
opacity: 0.5
rotation: 180
}
Item {
anchors.right: parent.right
anchors.rightMargin: 4
anchors.top: parent.top
anchors.bottom: parent.bottom
width: height
Image {
id: nextMonthIcon
anchors.centerIn: parent
source: "qrc:///images/prevMonth.png"
visible: false
}
ColorOverlay {
source: nextMonthIcon
anchors.fill: nextMonthIcon
color: MoneroComponents.Style.defaultFontColor
opacity: 0.5
rotation: 180
}
MouseArea {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
anchors.fill: parent
onClicked: calendar.showNextMonth()
}
MouseArea {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
anchors.fill: parent
onClicked: calendar.showNextMonth()
}
}
}

View File

@@ -32,7 +32,6 @@ import QtQuick 2.9
import "../components" as MoneroComponents
TextField {
id: textField
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 18
font.bold: true
@@ -45,12 +44,4 @@ TextField {
background: Rectangle {
color: "transparent"
}
MoneroComponents.ContextMenu {
cursorShape: Qt.IBeamCursor
onPaste: {
textField.clear();
textField.paste();
}
}
}

View File

@@ -86,7 +86,7 @@ Item {
color: MoneroComponents.Style.defaultFontColor
}
MoneroComponents.Input {
TextField {
id : input
focus: true
Layout.topMargin: 6

View File

@@ -57,10 +57,6 @@ TextArea {
onTextChanged: {
if(addressValidation){
// js replacement for `RegExpValidator { regExp: /[0-9A-Fa-f]{95}/g }`
if (textArea.text.startsWith("monero:")) {
error = false;
return;
}
textArea.text = textArea.text.replace(/[^a-z0-9.@\-]/gi,'');
var address_ok = TxUtils.checkAddress(textArea.text, appWindow.persistentSettings.nettype) || TxUtils.isValidOpenAliasAddress(textArea.text);
if(!address_ok) error = true;
@@ -68,12 +64,4 @@ TextArea {
TextArea.cursorPosition = textArea.text.length;
}
}
MoneroComponents.ContextMenu {
cursorShape: Qt.IBeamCursor
onPaste: {
textArea.clear();
textArea.paste();
}
}
}

View File

@@ -45,7 +45,6 @@ Item {
property alias horizontalAlignment: label.horizontalAlignment
property alias elide: label.elide
property alias textWidth: label.width
property alias styleName: label.font.styleName
property alias themeTransition: label.themeTransition
signal linkActivated()
height: label.height
@@ -69,10 +68,5 @@ Item {
color: fontColor
onLinkActivated: item.linkActivated()
textFormat: parent.textFormat
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.NoButton
cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor
}
}
}

View File

@@ -34,6 +34,8 @@ 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

@@ -53,8 +53,6 @@ Item {
property alias inlineButtonText: inlineButtonId.text
property alias inlineIcon: inlineIcon.visible
property bool copyButton: false
property alias copyButtonText: copyButtonId.text
property alias copyButtonEnabled: copyButtonId.enabled
property bool borderDisabled: false
property string borderColor: {

View File

@@ -80,6 +80,9 @@ ColumnLayout {
property alias readOnly: input.readOnly
property bool copyButton: false
property bool pasteButton: false
property var onPaste: function(clipboardText) {
item.text = clipboardText;
}
property bool showingHeader: labelText != "" || copyButton || pasteButton
property var wrapMode: Text.NoWrap
property alias addressValidation: input.addressValidation
@@ -143,10 +146,7 @@ ColumnLayout {
MoneroComponents.LabelButton {
id: pasteButtonId
onClicked: {
input.clear();
input.paste();
}
onClicked: item.onPaste(clipboard.text())
text: qsTr("Paste") + translationManager.emptyString
visible: pasteButton
}

118
components/MobileHeader.qml Normal file
View File

@@ -0,0 +1,118 @@
import QtQuick 2.9
import QtGraphicalEffects 1.0
import QtQuick.Layouts 1.1
import moneroComponents.Wallet 1.0
import "../components" as MoneroComponents
// BasicPanel header
Rectangle {
id: header
anchors.leftMargin: 1
anchors.rightMargin: 1
Layout.fillWidth: true
Layout.preferredHeight: 64
color: "#FFFFFF"
Image {
id: logo
visible: appWindow.width > 460
anchors.verticalCenter: parent.verticalCenter
anchors.verticalCenterOffset: -5
anchors.left: parent.left
anchors.leftMargin: 50
source: "qrc:///images/moneroLogo2.png"
}
Image {
id: icon
visible: !logo.visible
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin: 40
source: "qrc:///images/moneroIcon.png"
}
Grid {
anchors.verticalCenter: parent.verticalCenter
anchors.top: parent.top
anchors.right: parent.right
anchors.topMargin: 10
width: 256
columns: 3
MoneroComponents.TextPlain {
id: balanceLabel
width: 116
height: 20
font.family: "Arial"
font.pixelSize: 12
font.letterSpacing: -1
elide: Text.ElideRight
horizontalAlignment: Text.AlignLeft
verticalAlignment: Text.AlignBottom
color: "#535353"
text: leftPanel.balanceLabelText + ":"
}
MoneroComponents.TextPlain {
id: balanceText
width: 110
height: 20
font.family: "Arial"
font.pixelSize: 18
font.letterSpacing: -1
elide: Text.ElideRight
horizontalAlignment: Text.AlignLeft
verticalAlignment: Text.AlignBottom
color: "#000000"
text: leftPanel.balanceText
}
Item {
height: 20
width: 20
Image {
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
source: "qrc:///images/lockIcon.png"
}
}
MoneroComponents.TextPlain {
width: 116
height: 20
font.family: "Arial"
font.pixelSize: 12
font.letterSpacing: -1
elide: Text.ElideRight
horizontalAlignment: Text.AlignLeft
verticalAlignment: Text.AlignBottom
color: "#535353"
text: qsTr("Unlocked Balance:")
}
MoneroComponents.TextPlain {
id: availableBalanceText
width: 110
height: 20
font.family: "Arial"
font.pixelSize: 14
font.letterSpacing: -1
elide: Text.ElideRight
horizontalAlignment: Text.AlignLeft
verticalAlignment: Text.AlignBottom
color: "#000000"
text: leftPanel.unlockedBalanceText
}
}
Rectangle {
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
height: 1
color: "#DBDBDB"
}
}

View File

@@ -29,7 +29,6 @@
import QtQuick 2.9
import QtQuick.Layouts 1.1
import FontAwesome 1.0
import moneroComponents.Wallet 1.0
import "../components" as MoneroComponents
@@ -89,7 +88,6 @@ Rectangle {
}
MouseArea {
anchors.fill: parent
visible: appWindow.walletMode >= 2
cursorShape: Qt.PointingHandCursor
onClicked: {
if(!appWindow.isMining) {
@@ -135,7 +133,6 @@ Rectangle {
MouseArea {
anchors.fill: parent
visible: appWindow.walletMode >= 2
cursorShape: Qt.PointingHandCursor
onClicked: {
if(!appWindow.isMining) {
@@ -147,50 +144,6 @@ Rectangle {
}
}
}
Text {
anchors.left: statusTextVal.right
anchors.leftMargin: 16
anchors.verticalCenter: parent.verticalCenter
color: refreshMouseArea.containsMouse ? MoneroComponents.Style.dimmedFontColor : MoneroComponents.Style.defaultFontColor
font.family: FontAwesome.fontFamilySolid
font.pixelSize: 24
font.styleName: "Solid"
opacity: iconItem.opacity * (refreshMouseArea.visible ? 1 : 0.5)
text: FontAwesome.random
visible: (
item.connected != Wallet.ConnectionStatus_Disconnected &&
!persistentSettings.useRemoteNode &&
persistentSettings.bootstrapNodeAddress == "auto"
)
MouseArea {
id: refreshMouseArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
visible: true
onClicked: {
const callback = function(result) {
refreshMouseArea.visible = true;
if (result) {
appWindow.showStatusMessage(qsTr("Successfully switched to another public node"), 3);
appWindow.currentWallet.refreshHeightAsync();
} else {
appWindow.showStatusMessage(qsTr("Failed to switch public node"), 3);
}
};
daemonManager.sendCommandAsync(
["set_bootstrap_daemon", "auto"],
appWindow.currentWallet.nettype,
callback);
refreshMouseArea.visible = false;
appWindow.showStatusMessage(qsTr("Switching to another public node"), 3);
}
}
}
}
}
}

View File

@@ -0,0 +1,287 @@
// 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

@@ -0,0 +1,321 @@
// 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,63 +44,34 @@ Item {
z: parent.z + 2
property bool isHidden: true
property alias password: passwordInput1.text
property alias password: passwordInput.text
property string walletName
property string errorText
property bool passwordDialogMode
property bool passphraseDialogMode
property bool newPasswordDialogMode
property bool shiftIsPressed: false
property bool isCapsLocksActive: false
property bool backspaceIsPressed: false
// same signals as Dialog has
signal accepted()
signal acceptedNewPassword()
signal acceptedPassphrase()
signal rejected()
signal rejectedNewPassword()
signal rejectedPassphrase()
signal closeCallback()
function _openInit(walletName, errorText) {
function open(walletName, errorText) {
isHidden = true
capsLockTextLabel.visible = oshelper.isCapsLock();
passwordInput1.echoMode = TextInput.Password
passwordInput2.echoMode = TextInput.Password
passwordInput1.text = ""
passwordInput2.text = ""
passwordInput1.forceActiveFocus();
passwordInput.echoMode = TextInput.Password
passwordInput.text = ""
passwordInput.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);
}
@@ -109,7 +80,6 @@ Item {
inactiveOverlay.visible = false
leftPanel.enabled = true
middlePanel.enabled = true
wizard.enabled = true
titleBar.state = "default"
root.visible = false;
@@ -118,12 +88,6 @@ 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
@@ -138,14 +102,7 @@ Item {
Layout.maximumWidth: 400
Label {
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;
}
}
text: (root.walletName.length > 0 ? qsTr("Please enter wallet password for: ") + root.walletName : qsTr("Please enter wallet password")) + translationManager.emptyString
Layout.fillWidth: true
font.pixelSize: 16
@@ -154,41 +111,19 @@ 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;
}
MoneroComponents.Input {
id: passwordInput1
TextField {
id : passwordInput
Layout.topMargin: 6
Layout.fillWidth: true
horizontalAlignment: TextInput.AlignLeft
@@ -196,21 +131,24 @@ Item {
font.family: MoneroComponents.Style.fontLight.name
font.pixelSize: 24
echoMode: TextInput.Password
KeyNavigation.tab: {
if (passwordDialogMode) {
return okButton
} else {
return passwordInput2
}
}
implicitHeight: 50
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();
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 = "";
}
}
background: Rectangle {
radius: 2
@@ -239,7 +177,8 @@ Item {
cursorShape: Qt.PointingHandCursor
hoverEnabled: true
onClicked: {
toggleIsHidden();
passwordInput.echoMode = isHidden ? TextInput.Normal : TextInput.Password;
isHidden = !isHidden;
}
onEntered: {
parent.opacity = 0.9
@@ -256,130 +195,28 @@ Item {
Keys.enabled: root.visible
Keys.onReturnPressed: {
root.close()
if (passwordDialogMode) {
root.accepted()
} else if (newPasswordDialogMode) {
root.acceptedNewPassword()
} else if (passphraseDialogMode) {
root.acceptedPassphrase()
}
root.accepted()
}
Keys.onEscapePressed: {
root.close()
if (passwordDialogMode) {
root.rejected()
} else if (newPasswordDialogMode) {
root.rejectedNewPassword()
} else if (passphraseDialogMode) {
root.rejectedPassphrase()
root.rejected()
}
Keys.onPressed: {
if(event.key === Qt.Key_Shift){
shiftIsPressed = true;
}
if(event.key === Qt.Key_Backspace){
backspaceIsPressed = true;
}
}
}
// 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
}
MoneroComponents.Input {
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
implicitHeight: 50
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.onReleased: {
if(event.key === Qt.Key_Shift){
shiftIsPressed = false;
}
if(event.key === Qt.Key_Backspace){
backspaceIsPressed =false;
}
}
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
@@ -392,38 +229,26 @@ Item {
MoneroComponents.StandardButton {
id: cancelButton
small: true
text: qsTr("Cancel") + translationManager.emptyString
KeyNavigation.tab: passwordInput1
text: root.walletName.length > 0 ? qsTr("Change wallet") + translationManager.emptyString : qsTr("Cancel") + translationManager.emptyString
KeyNavigation.tab: passwordInput
onClicked: {
root.close()
if (passwordDialogMode) {
root.rejected()
} else if (newPasswordDialogMode) {
root.rejectedNewPassword()
} else if (passphraseDialogMode) {
root.rejectedPassphrase()
}
root.rejected()
}
}
MoneroComponents.StandardButton {
id: okButton
small: true
text: qsTr("Ok") + translationManager.emptyString
text: qsTr("Continue") + translationManager.emptyString
KeyNavigation.tab: cancelButton
enabled: (passwordDialogMode == true) ? true : passwordInput1.text === passwordInput2.text
onClicked: {
root.close()
if (passwordDialogMode) {
root.accepted()
} else if (newPasswordDialogMode) {
root.acceptedNewPassword()
} else if (passphraseDialogMode) {
root.acceptedPassphrase()
}
root.accepted()
}
}
}
}
}
}

View File

@@ -74,7 +74,7 @@ Item {
MoneroComponents.TextPlain {
id: label
Layout.leftMargin: 10
Layout.leftMargin: (!isMobile ? 10 : 8)
color: MoneroComponents.Style.defaultFontColor
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: radioButton.fontSize

View File

@@ -35,7 +35,7 @@ import "../js/Utils.js" as Utils
import "../components" as MoneroComponents
GridLayout {
columns: 2
columns: (isMobile) ? 1 : 2
columnSpacing: 32
id: root
property alias daemonAddrText: daemonAddr.text

View File

@@ -1,65 +0,0 @@
import QtQuick 2.9
import QtQuick.Layouts 1.1
import "../components" as MoneroComponents
ColumnLayout {
property alias buttonText: button.text
property alias description: description.text
property alias title: title.text
signal clicked()
id: settingsListItem
Layout.fillWidth: true
spacing: 0
Rectangle {
// divider
Layout.preferredHeight: 1
Layout.fillWidth: true
Layout.bottomMargin: 8
color: MoneroComponents.Style.dividerColor
opacity: MoneroComponents.Style.dividerOpacity
}
RowLayout {
Layout.fillWidth: true
spacing: 0
ColumnLayout {
Layout.fillWidth: true
Layout.alignment: Qt.AlignVCenter
spacing: 0
MoneroComponents.TextPlain {
id: title
Layout.fillWidth: true
Layout.preferredHeight: 20
Layout.topMargin: 8
color: MoneroComponents.Style.defaultFontColor
opacity: MoneroComponents.Style.blackTheme ? 1.0 : 0.8
font.bold: true
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 16
}
MoneroComponents.TextPlainArea {
id: description
color: MoneroComponents.Style.dimmedFontColor
colorBlackTheme: MoneroComponents.Style._b_dimmedFontColor
colorWhiteTheme: MoneroComponents.Style._w_dimmedFontColor
Layout.fillWidth: true
horizontalAlignment: TextInput.AlignLeft
}
}
MoneroComponents.StandardButton {
id: button
small: true
onClicked: {
settingsListItem.clicked()
}
width: 135
}
}
}

View File

@@ -82,8 +82,10 @@ Rectangle {
function open() {
// Center
root.x = parent.width/2 - root.width/2
root.y = 100
if(!isMobile) {
root.x = parent.width/2 - root.width/2
root.y = 100
}
root.z = 11
root.visible = true;
}
@@ -94,14 +96,14 @@ Rectangle {
}
// TODO: implement without hardcoding sizes
width: 520
height: 380
width: isMobile ? screenWidth : 520
height: isMobile ? screenHeight : 380
ColumnLayout {
id: mainLayout
spacing: 10
anchors.fill: parent
anchors.margins: 20
anchors.margins: (isMobile? 17 : 20)
RowLayout {
id: column

View File

@@ -27,7 +27,6 @@
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import QtQuick 2.9
import QtQuick.Controls 2.2
import QtGraphicalEffects 1.0
import "../components" as MoneroComponents
@@ -43,7 +42,7 @@ Item {
property string releasedColor: MoneroComponents.Style.titleBarButtonHoverColor
property string textColor: MoneroComponents.Style.defaultFontColor
property alias currentIndex: columnid.currentIndex
readonly property alias expanded: popup.visible
property bool expanded: false
property int dropdownHeight: 42
property int fontHeaderSize: 16
property int fontItemSize: 14
@@ -57,6 +56,18 @@ Item {
signal changed();
onExpandedChanged: if(expanded) appWindow.currentItem = dropdown
function hide() { dropdown.expanded = false }
function containsPoint(px, py) {
if(px < 0)
return false
if(px > width)
return false
if(py < 0)
return false
if(py > height + droplist.height)
return false
return true
}
// Workaroud for suspected memory leak in 5.8 causing malloc crash on app exit
function update() {
@@ -117,118 +128,118 @@ Item {
MouseArea {
id: dropArea
anchors.fill: parent
onClicked: dropdown.expanded ? popup.close() : popup.open()
onClicked: dropdown.expanded = !dropdown.expanded
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
}
}
Popup {
id: popup
padding: 0
Rectangle {
id: droplist
anchors.left: parent.left
anchors.right: parent.right
anchors.top: head.bottom
clip: true
height: dropdown.expanded ? columnid.height : 0
color: dropdown.pressedColor
Rectangle {
id: droplist
x: dropdown.x
width: dropdown.width
y: head.y + head.height
clip: true
height: dropdown.expanded ? columnid.height : 0
anchors.left: parent.left
anchors.top: parent.top
width: 3; height: 3
color: dropdown.pressedColor
}
Rectangle {
anchors.left: parent.left
anchors.top: parent.top
width: 3; height: 3
color: dropdown.pressedColor
}
Rectangle {
anchors.right: parent.right
anchors.top: parent.top
width: 3; height: 3
color: dropdown.pressedColor
}
Rectangle {
anchors.right: parent.right
anchors.top: parent.top
width: 3; height: 3
color: dropdown.pressedColor
}
Behavior on height {
NumberAnimation { duration: 100; easing.type: Easing.InQuad }
}
Behavior on height {
NumberAnimation { duration: 100; easing.type: Easing.InQuad }
}
Column {
id: columnid
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
property int currentIndex: 0
Column {
id: columnid
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
property int currentIndex: 0
Repeater {
id: repeater
Repeater {
id: repeater
// Workaround for translations in listElements. All translated strings needs to be listed in this file.
property string stringLow: qsTr("Low (x1 fee)") + translationManager.emptyString
property string stringMedium: qsTr("Medium (x20 fee)") + translationManager.emptyString
property string stringHigh: qsTr("High (x166 fee)") + translationManager.emptyString
property string stringSlow: qsTr("Slow (x0.25 fee)") + translationManager.emptyString
property string stringDefault: qsTr("Default (x1 fee)") + translationManager.emptyString
property string stringFast: qsTr("Fast (x5 fee)") + translationManager.emptyString
property string stringFastest: qsTr("Fastest (x41.5 fee)") + translationManager.emptyString
property string stringAll: qsTr("All") + translationManager.emptyString
property string stringSent: qsTr("Sent") + translationManager.emptyString
property string stringReceived: qsTr("Received") + translationManager.emptyString
// Workaround for translations in listElements. All translated strings needs to be listed in this file.
property string stringAutomatic: qsTr("Automatic") + translationManager.emptyString
property string stringSlow: qsTr("Slow (x0.2 fee)") + translationManager.emptyString
property string stringNormal: qsTr("Normal (x1 fee)") + translationManager.emptyString
property string stringFast: qsTr("Fast (x5 fee)") + translationManager.emptyString
property string stringFastest: qsTr("Fastest (x200 fee)") + translationManager.emptyString
delegate: Rectangle {
anchors.left: parent.left
anchors.right: parent.right
height: (dropdown.dropdownHeight * 0.75)
//radius: index === repeater.count - 1 ? 4 : 0
color: itemArea.containsMouse || index === columnid.currentIndex || itemArea.containsMouse ? dropdown.releasedColor : dropdown.pressedColor
delegate: Rectangle {
MoneroComponents.TextPlain {
id: col1Text
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.right: col2Text.left
anchors.leftMargin: 12
anchors.rightMargin: 0
font.family: MoneroComponents.Style.fontRegular.name
font.bold: true
font.pixelSize: fontItemSize
color: itemArea.containsMouse || index === columnid.currentIndex || itemArea.containsMouse ? "#FA6800" : "#FFFFFF"
text: qsTr(column1) + translationManager.emptyString
}
MoneroComponents.TextPlain {
id: col2Text
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
height: (dropdown.dropdownHeight * 0.75)
//radius: index === repeater.count - 1 ? 4 : 0
color: itemArea.containsMouse || index === columnid.currentIndex || itemArea.containsMouse ? dropdown.releasedColor : dropdown.pressedColor
anchors.rightMargin: 45
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 14
color: "#FFFFFF"
text: ""
}
MoneroComponents.TextPlain {
id: col1Text
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.right: col2Text.left
anchors.leftMargin: 12
anchors.rightMargin: 0
font.family: MoneroComponents.Style.fontRegular.name
font.bold: true
font.pixelSize: fontItemSize
color: itemArea.containsMouse || index === columnid.currentIndex || itemArea.containsMouse ? "#FA6800" : "#FFFFFF"
text: qsTr(column1) + translationManager.emptyString
}
Rectangle {
anchors.left: parent.left
anchors.top: parent.top
width: 3; height: 3
color: parent.color
}
MoneroComponents.TextPlain {
id: col2Text
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
anchors.rightMargin: 45
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 14
color: "#FFFFFF"
text: ""
}
Rectangle {
anchors.right: parent.right
anchors.top: parent.top
width: 3; height: 3
color: parent.color
}
Rectangle {
anchors.left: parent.left
anchors.top: parent.top
width: 3; height: 3
color: parent.color
}
MouseArea {
id: itemArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
Rectangle {
anchors.right: parent.right
anchors.top: parent.top
width: 3; height: 3
color: parent.color
}
MouseArea {
id: itemArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
popup.close()
columnid.currentIndex = index
changed();
dropdown.update()
}
onClicked: {
dropdown.expanded = false
columnid.currentIndex = index
changed();
dropdown.update()
}
}
}

View File

@@ -51,6 +51,7 @@ QtObject {
property string titleBarBackgroundBorderColor: blackTheme ? _b_titleBarBackgroundBorderColor : _w_titleBarBackgroundBorderColor
property string titleBarLogoSource: blackTheme ? _b_titleBarLogoSource : _w_titleBarLogoSource
property string titleBarMinimizeSource: blackTheme ? _b_titleBarMinimizeSource : _w_titleBarMinimizeSource
property string titleBarExpandSource: blackTheme ? _b_titleBarExpandSource : _w_titleBarExpandSource
property string titleBarFullscreenSource: blackTheme ? _b_titleBarFullscreenSource : _w_titleBarFullscreenSource
property string titleBarCloseSource: blackTheme ? _b_titleBarCloseSource : _w_titleBarCloseSource
property string titleBarButtonHoverColor: blackTheme ? _b_titleBarButtonHoverColor : _w_titleBarButtonHoverColor
@@ -107,6 +108,7 @@ QtObject {
property string _b_titleBarBackgroundBorderColor: "#2f2f2f"
property string _b_titleBarLogoSource: "qrc:///images/titlebarLogo.png"
property string _b_titleBarMinimizeSource: "qrc:///images/minimize.svg"
property string _b_titleBarExpandSource: "qrc:///images/sidebar.svg"
property string _b_titleBarFullscreenSource: "qrc:///images/fullscreen.svg"
property string _b_titleBarCloseSource: "qrc:///images/close.svg"
property string _b_titleBarButtonHoverColor: "#10FFFFFF"
@@ -163,6 +165,7 @@ QtObject {
property string _w_titleBarBackgroundBorderColor: "#DEDEDE"
property string _w_titleBarLogoSource: "qrc:///images/themes/white/titlebarLogo.png"
property string _w_titleBarMinimizeSource: "qrc:///images/themes/white/minimize.svg"
property string _w_titleBarExpandSource: "qrc:///images/themes/white/expand.svg"
property string _w_titleBarFullscreenSource: "qrc:///images/themes/white/fullscreen.svg"
property string _w_titleBarCloseSource: "qrc:///images/themes/white/close.svg"
property string _w_titleBarButtonHoverColor: "#11000000"

View File

@@ -38,14 +38,14 @@ import "effects/" as MoneroEffects
Rectangle {
id: root
property int mouseX: 0
property bool basicButtonVisible: false
property bool customDecorations: persistentSettings.customDecorations
property bool showMinimizeButton: true
property bool showMaximizeButton: true
property bool showCloseButton: true
property string walletName: ""
height: {
if(!persistentSettings.customDecorations) return 0;
if(!persistentSettings.customDecorations || isMobile) return 0;
return 50;
}
@@ -56,18 +56,18 @@ Rectangle {
signal maximizeClicked
signal minimizeClicked
signal languageClicked
signal closeWalletClicked
signal goToBasicVersion(bool yes)
state: "default"
states: [
State {
name: "default";
PropertyChanges { target: btnCloseWallet; visible: true}
PropertyChanges { target: btnSidebarCollapse; visible: true}
PropertyChanges { target: btnLanguageToggle; visible: true}
}, State {
// show only theme switcher and window controls
name: "essentials";
PropertyChanges { target: btnCloseWallet; visible: false}
PropertyChanges { target: btnSidebarCollapse; visible: false}
PropertyChanges { target: btnLanguageToggle; visible: false}
}
]
@@ -93,20 +93,22 @@ Rectangle {
// collapse sidebar
Rectangle {
id: btnCloseWallet
id: btnSidebarCollapse
visible: root.basicButtonVisible
color: "transparent"
Layout.preferredWidth: parent.height
Layout.preferredHeight: parent.height
Text {
text: FontAwesome.signOutAlt
font.family: FontAwesome.fontFamilySolid
font.pixelSize: 16
color: MoneroComponents.Style.defaultFontColor
font.styleName: "Solid"
MoneroEffects.ImageMask {
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
height: 14
width: 14
image: MoneroComponents.Style.titleBarExpandSource
color: MoneroComponents.Style.defaultFontColor
fontAwesomeFallbackIcon: FontAwesome.cube
fontAwesomeFallbackSize: 14
fontAwesomeFallbackOpacity: MoneroComponents.Style.blackTheme ? 1.0 : 0.9
opacity: 0.75
}
@@ -116,7 +118,7 @@ Rectangle {
cursorShape: Qt.PointingHandCursor
onEntered: parent.color = MoneroComponents.Style.titleBarButtonHoverColor
onExited: parent.color = "transparent"
onClicked: root.closeWalletClicked(leftPanel.visible)
onClicked: root.goToBasicVersion(leftPanel.visible)
}
}
@@ -129,10 +131,9 @@ Rectangle {
Text {
text: FontAwesome.globe
font.family: FontAwesome.fontFamilySolid
font.family: FontAwesome.fontFamily
font.pixelSize: 16
color: MoneroComponents.Style.defaultFontColor
font.styleName: "Solid"
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
opacity: 0.75
@@ -155,10 +156,9 @@ Rectangle {
Layout.preferredHeight: parent.height
Text {
text: FontAwesome.moonO
font.family: MoneroComponents.Style.blackTheme ? FontAwesome.fontFamilySolid : FontAwesome.fontFamily
font.styleName: MoneroComponents.Style.blackTheme ? "Solid" : "Regular"
font.pixelSize: 15
text: MoneroComponents.Style.blackTheme ? FontAwesome.lightbulbO : FontAwesome.moonO
font.family: FontAwesome.fontFamily
font.pixelSize: 16
color: MoneroComponents.Style.defaultFontColor
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
@@ -189,7 +189,6 @@ Rectangle {
// monero logo
Item {
visible: walletName.length === 0
Layout.fillWidth: true
Layout.preferredHeight: parent.height
@@ -217,22 +216,6 @@ Rectangle {
}
}
Item {
visible: walletName.length > 0
Layout.fillWidth: true
Layout.preferredHeight: parent.height
MoneroComponents.TextPlain {
font.pixelSize: 20
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
width: parent.width
height: parent.height
elide: Text.ElideRight
text: walletName
}
}
// minimize
Rectangle {
color: "transparent"

View File

@@ -37,26 +37,26 @@ Rectangle {
source: "qrc:///images/warning.png"
}
Text {
TextArea {
id: content
Layout.fillWidth: true
color: MoneroComponents.Style.defaultFontColor
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: root.fontSize
horizontalAlignment: TextInput.AlignLeft
selectByMouse: true
textFormat: Text.RichText
wrapMode: Text.WordWrap
textMargin: 0
leftPadding: 4
rightPadding: 18
topPadding: 10
bottomPadding: 10
readOnly: true
onLinkActivated: root.linkActivated();
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.NoButton
cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor
}
selectionColor: MoneroComponents.Style.textSelectionColor
selectedTextColor: MoneroComponents.Style.textSelectedColor
}
}
}

View File

@@ -39,9 +39,8 @@ Item {
id: root
property string image: ""
property string color: ""
property bool fontAwesomeFallbackEnabled: true
property var fontAwesomeFallbackIcon: ""
property string fontAwesomeFallbackFont: FontAwesome.fontFamilySolid
property string fontAwesomeFallbackStyle: "Solid"
property int fontAwesomeFallbackSize: 16
property double fontAwesomeFallbackOpacity: 0.8
property string fontAwesomeFallbackColor: MoneroComponents.Style.defaultFontColor
@@ -68,16 +67,15 @@ Item {
anchors.fill: root
source: svgMask
color: root.color
visible: image && isOpenGL
visible: isOpenGL
}
Text {
id: fontAwesomeFallback
visible: !imgMockColor.visible
text: root.fontAwesomeFallbackIcon
font.family: root.fontAwesomeFallbackFont
visible: !isOpenGL && root.fontAwesomeFallback
text: !isOpenGL ? root.fontAwesomeFallbackIcon : ""
font.family: FontAwesome.fontFamily
font.pixelSize: root.fontAwesomeFallbackSize
font.styleName: root.fontAwesomeFallbackStyle
color: root.fontAwesomeFallbackColor
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter

View File

@@ -4,23 +4,10 @@ import QtQuick 2.9
Object {
FontLoader {
id: regular
source: "./fa-regular-400.ttf"
source: "./fontawesome-webfont.ttf"
}
FontLoader {
id: brands
source: "./fa-brands-400.ttf"
}
FontLoader {
id: solid
source: "./fa-solid-900.ttf"
}
property string fontFamily: regular.name
property string fontFamilyBrands: brands.name
property string fontFamilySolid: solid.name
property string fontFamily: "FontAwesome"
// Icons
property string addressBook : "\uf2b9"
@@ -607,7 +594,6 @@ Object {
property string shower : "\uf2cc"
property string signIn : "\uf090"
property string signLanguage : "\uf2a7"
property string signOutAlt : "\uf2f5"
property string signOut : "\uf08b"
property string signal : "\uf012"
property string signing : "\uf2a7"

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

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.15.0.1
git -C $MONERO_DIR checkout v0.14.1.0
# get monero core tag
pushd $MONERO_DIR
@@ -144,9 +144,9 @@ make_exec="make"
if [ "$platform" == "darwin" ]; then
echo "Configuring build for MacOS.."
if [ "$STATIC" == true ]; then
cmake -D CMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE -D STATIC=ON -D ARCH="x86-64" -D BUILD_64=ON -D BUILD_TAG="mac-x64" -D BUILD_GUI_DEPS=ON -D INSTALL_VENDORED_LIBUNBOUND=ON $BUILD_TREZOR_FLAGS -D CMAKE_INSTALL_PREFIX="$MONERO_DIR" ../..
cmake -D CMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE -D STATIC=ON -D ARCH="x86-64" -D BUILD_64=ON -D BUILD_GUI_DEPS=ON -D INSTALL_VENDORED_LIBUNBOUND=ON $BUILD_TREZOR_FLAGS -D CMAKE_INSTALL_PREFIX="$MONERO_DIR" ../..
else
cmake -D CMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE -D BUILD_TAG="mac-x64" -D BUILD_GUI_DEPS=ON -D INSTALL_VENDORED_LIBUNBOUND=ON $BUILD_TREZOR_FLAGS -D CMAKE_INSTALL_PREFIX="$MONERO_DIR" ../..
cmake -D CMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE -D BUILD_GUI_DEPS=ON -D INSTALL_VENDORED_LIBUNBOUND=ON $BUILD_TREZOR_FLAGS -D CMAKE_INSTALL_PREFIX="$MONERO_DIR" ../..
fi
## LINUX 64
@@ -156,9 +156,9 @@ elif [ "$platform" == "linux64" ]; then
echo "Configuring build for Android on Linux host"
cmake -D CMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE -D STATIC=ON -D ARCH="armv7-a" -D ANDROID=true -D BUILD_GUI_DEPS=ON -D USE_LTO=OFF -D INSTALL_VENDORED_LIBUNBOUND=ON $BUILD_TREZOR_FLAGS -D CMAKE_INSTALL_PREFIX="$MONERO_DIR" ../..
elif [ "$STATIC" == true ]; then
cmake -D CMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE -D STATIC=ON -D ARCH="x86-64" -D BUILD_64=ON -D BUILD_TAG="linux-x64" -D BUILD_GUI_DEPS=ON -D INSTALL_VENDORED_LIBUNBOUND=ON $BUILD_TREZOR_FLAGS -D CMAKE_INSTALL_PREFIX="$MONERO_DIR" ../..
cmake -D CMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE -D STATIC=ON -D ARCH="x86-64" -D BUILD_64=ON -D BUILD_GUI_DEPS=ON -D INSTALL_VENDORED_LIBUNBOUND=ON $BUILD_TREZOR_FLAGS -D CMAKE_INSTALL_PREFIX="$MONERO_DIR" ../..
else
cmake -D CMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE -D BUILD_TAG="linux-x64" -D BUILD_GUI_DEPS=ON $BUILD_TREZOR_FLAGS -D CMAKE_INSTALL_PREFIX="$MONERO_DIR" ../..
cmake -D CMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE -D BUILD_GUI_DEPS=ON $BUILD_TREZOR_FLAGS -D CMAKE_INSTALL_PREFIX="$MONERO_DIR" ../..
fi
## LINUX 32
@@ -194,7 +194,7 @@ elif [ "$platform" == "mingw64" ]; then
# Do something under Windows NT platform
echo "Configuring build for MINGW64.."
BOOST_ROOT=/mingw64/boost
cmake -D CMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE -D STATIC=ON -D BOOST_ROOT="$BOOST_ROOT" -D ARCH="x86-64" -D BUILD_TAG="win-x64" -D BUILD_GUI_DEPS=ON -D INSTALL_VENDORED_LIBUNBOUND=ON $BUILD_TREZOR_FLAGS -D CMAKE_INSTALL_PREFIX="$MONERO_DIR" -G "MSYS Makefiles" -D CMAKE_TOOLCHAIN_FILE=../../cmake/64-bit-toolchain.cmake -D MSYS2_FOLDER=c:/msys64 ../..
cmake -D CMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE -D STATIC=ON -D BOOST_ROOT="$BOOST_ROOT" -D ARCH="x86-64" -D BUILD_GUI_DEPS=ON -D INSTALL_VENDORED_LIBUNBOUND=ON $BUILD_TREZOR_FLAGS -D CMAKE_INSTALL_PREFIX="$MONERO_DIR" -G "MSYS Makefiles" -D CMAKE_TOOLCHAIN_FILE=../../cmake/64-bit-toolchain.cmake -D MSYS2_FOLDER=c:/msys64 ../..
## Windows 32
elif [ "$platform" == "mingw32" ]; then
@@ -253,7 +253,4 @@ if [ -d $MONERO_DIR/build/$BUILD_TYPE/external/unbound ]; then
popd
fi
# install randomx
eval make -C $MONERO_DIR/build/$BUILD_TYPE/external/randomx all install
popd

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

BIN
images/card-background.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

BIN
images/card-background@2x.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 419 B

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 436 B

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 612 B

After

Width:  |  Height:  |  Size: 15 KiB

BIN
images/minus-white.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 170 B

BIN
images/minus-white@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 170 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 399 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 760 B

BIN
images/plus-white.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 193 B

BIN
images/plus-white@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 195 B

View File

@@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" width="27" height="27" viewBox="0 0 27 27">
<g fill="none" fill-rule="evenodd" stroke="#FFF" stroke-linecap="round" stroke-width="1.25">
<path d="M1.595 2.19h5.357v5.358"/>
<path d="M6.682 3.021A12.49 12.49 0 0 0 1 13.5C1 20.404 6.596 26 13.5 26S26 20.404 26 13.5 20.404 1 13.5 1"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 359 B

View File

@@ -0,0 +1,7 @@
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="27" viewBox="0 0 22 27">
<g fill="none" fill-rule="evenodd" stroke="#FFF" stroke-linecap="round" stroke-width="1.071">
<path d="M20.412 7.818h-6.47v-6.25"/>
<path d="M21 26H1V1h12.941L21 7.818z"/>
<path d="M7.154 15.404l3.333-3.333 3.334 3.334M10.487 20.286v-7.548"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 371 B

6
images/sidebar.svg Normal file
View File

@@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18">
<g fill="none" fill-rule="evenodd" stroke="#FFF" stroke-width="1.636" opacity="1">
<rect width="16.364" height="16.364" x=".818" y=".818" rx="1.636"/>
<path fill="#FFF" d="M6.182 17.182V.818H1.64a.822.822 0 0 0-.822.822v14.72c0 .454.368.822.822.822h4.542z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 379 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.7 KiB

View File

@@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 14 14">
<g fill="none" fill-rule="evenodd" opacity="1">
<path fill="none" d="M-11-11h36v36h-36z" opacity="1"/>
<path stroke="#000" stroke-linecap="round" stroke-width="1.556" d="M13 13L1.686 1.686M1 7.222V1h6.222"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 328 B

View File

@@ -1,30 +0,0 @@
# 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

@@ -1,7 +1,6 @@
; Monero Carbon Chamaeleon GUI Wallet Installer for Windows
; Monero Boron Butterfly GUI Wallet Installer for Windows
; Copyright (c) 2017-2019, The Monero Project
; See LICENSE
#define GuiVersion GetFileVersion("bin\monero-wallet-gui.exe")
[Setup]
AppName=Monero GUI Wallet
@@ -9,8 +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={#GuiVersion}
VersionInfoVersion={#GuiVersion}
AppVersion=0.14.1.0
DefaultDirName={pf}\Monero GUI Wallet
DefaultGroupName=Monero GUI Wallet
UninstallDisplayIcon={app}\monero-wallet-gui.exe
@@ -23,8 +21,6 @@ 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:
@@ -41,8 +37,6 @@ UsedUserAreasWarning=no
; play a role in only in few cases as the first standard user in a Windows installation does have admin rights.
; So, for the time being, this installer simply disregards this problem.
[Messages]
SetupWindowTitle=%1 {#GuiVersion} Installer
[Languages]
Name: "en"; MessagesFile: "compiler:Default.isl"
@@ -62,19 +56,19 @@ Name: "en"; MessagesFile: "compiler:Default.isl"
; .exe/.dll file possibly with version info).
;
; This is far more robust than relying on version info or on file dates (flag "comparetimestamp").
; As of version 0.15.0.0, the Monero .exe files do not carry version info anyway in their .exe headers.
; As of version 0.14.1.0, the Monero .exe files do not carry version info anyway in their .exe headers.
; The only small drawback seems to be somewhat longer update times because each and every file is
; copied again, even if already present with correct file date and identical content.
;
; Note that it would be very dangerous to use "ignoreversion" on files that may be shared with other
; applications somehow. Luckily this is no issue here because ALL files are "private" to Monero.
Source: {#file AddBackslash(SourcePath) + "ReadMe.htm"}; DestDir: "{app}"; DestName: "ReadMe.htm"; Flags: ignoreversion
Source: "ReadMe.htm"; DestDir: "{app}"; Flags: ignoreversion
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-wallet-guide.pdf"; DestDir: "{app}"; Flags: ignoreversion
Source: "bin\monero-GUI-guide.pdf"; DestDir: "{app}"; Flags: ignoreversion
; Monero CLI wallet
Source: "bin\monero-wallet-cli.exe"; DestDir: "{app}"; Flags: ignoreversion
@@ -201,7 +195,7 @@ begin
// Additional wizard page for entering a special blockchain location
blockChainDefaultDir := ExpandConstant('{commonappdata}\bitmonero');
s := 'The default folder to store the Monero blockchain is ' + blockChainDefaultDir;
s := s + '. As this will need more than 74 GB of free space, you may want to use a folder on a different drive.';
s := s + '. As this will need more than 70 GB of free space, you may want to use a folder on a different drive.';
s := s + ' If yes, specify that folder here.';
BlockChainDirPage := CreateInputDirPage(wpSelectDir,
@@ -317,7 +311,7 @@ end;
; Icons in the "Monero GUI Wallet" program group
; Windows will almost always display icons in alphabetical order, per level, so specify the text accordingly
Name: "{group}\GUI Wallet"; Filename: "{app}\monero-wallet-gui.exe";
Name: "{group}\GUI Wallet Guide"; Filename: "{app}\monero-gui-wallet-guide.pdf"; IconFilename: "{app}\monero-wallet-gui.exe"
Name: "{group}\GUI Wallet Guide"; Filename: "{app}\monero-GUI-guide.pdf"; IconFilename: "{app}\monero-wallet-gui.exe"
Name: "{group}\Uninstall GUI Wallet"; Filename: "{uninstallexe}"
; Sub-folder "Utilities";

View File

@@ -6,7 +6,7 @@ Copyright (c) 2017-2019, The Monero Project
This is a *Inno Setup* script `Monero.iss` plus some related files
that allows you to build a standalone Windows installer (.exe) for
the GUI wallet that comes with the Carbon Chamaeleon release of Monero.
the GUI wallet that comes with the Boron Butterfly release of Monero.
This turns the GUI wallet into a more or less standard Windows program,
by default installed into a subdirectory of `C:\Program Files`, a
@@ -18,7 +18,7 @@ Monero.
As the setup script in file [Monero.iss](Monero.iss) has to list many
files and directories of the GUI wallet package to install by name,
this version of the script only works with exactly the GUI wallet
for Monero release *Carbon Chamaeleon* that you find on
for Monero release *Boron Butterfly* that you find on
[the official download page](https://getmonero.org/downloads/).
It should however be easy to modify the script for future
@@ -32,15 +32,13 @@ See [LICENSE](LICENSE).
You can only build on Windows, and the result is always a
Windows .exe file that can act as a standalone installer for the
Carbon Chamaeleon GUI wallet.
Note that the installer build process is now reproducible / deterministic. For details check the file [Deterministic.md](Deterministic.md).
Boron Butterfly GUI wallet.
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 instead of simply using `master` you may have to checkout a specific branch, like `release-v0.15`.
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.15.0.0`) to this `bin` subdirectory
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
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

@@ -1,12 +1,13 @@
<html>
<head>
<title>Monero Carbon Chamaeleon GUI Wallet</title>
<title>Monero Boron Butterfly GUI Wallet</title>
</head>
<body style="font-family: Arial, Helvetica, sans-serif">
<h1>Monero Carbon Chamaeleon GUI Wallet</h1>
<h1>Monero Boron Butterfly GUI Wallet</h1>
<p>Copyright (c) 2014-2019, The Monero Project</p>
<p>Copyright (c) 2014-2019, The Monero Project<br>
Date: May 7, 2019</p>
<h2>Preface</h2>
@@ -22,7 +23,7 @@
<h2>Content of the Package</h2>
<p>You just installed the <i>Monero GUI wallet</i> for Windows, release Carbon Chamaeleon, version {#GuiVersion}.
<p>You just installed the <i>Monero GUI wallet</i> for Windows, release Boron Butterfly, version 0.14.1.0.
The wallet enables you to send and receive Moneroj in a secure and very private way.
</p>
@@ -60,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 74 GB in November 2019, and of course growing), you can compromise and try to connect
the blockchain locally (somewhat over 70 GB in May 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>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 440 KiB

After

Width:  |  Height:  |  Size: 440 KiB

View File

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

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

@@ -46,6 +46,7 @@ function showSeedPage() {
leftPanel.selectItem(middlePanel.state);
}
passwordDialog.open();
if(isMobile) hideMenu();
updateBalance();
}
@@ -93,6 +94,16 @@ function netTypeToString(){
return nettype == 1 ? qsTr("Testnet") : nettype == 2 ? qsTr("Stagenet") : qsTr("Mainnet");
}
function randomChoice(arr){
return arr[Math.floor(Math.random() * arr.length)];
}
function filterNodes(nodes, port) {
if(typeof data === 'number')
port = port.toString();
return nodes.filter(function(_){return _.indexOf(port) !== -1});
}
function epoch(){
return Math.floor((new Date).getTime()/1000);
}
@@ -101,6 +112,25 @@ 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(...
@@ -133,3 +163,15 @@ function capitalize(s){
if (typeof s !== 'string') return ''
return s.charAt(0).toUpperCase() + s.slice(1)
}
function formatMoney(n, c, d, t) {
// https://stackoverflow.com/a/149099
var c = isNaN(c = Math.abs(c)) ? 2 : c,
d = d == undefined ? "." : d,
t = t == undefined ? "," : t,
s = n < 0 ? "-" : "",
i = String(parseInt(n = Math.abs(Number(n) || 0).toFixed(c))),
j = (j = i.length) > 3 ? j % 3 : 0;
return s + (j ? i.substr(0, j) + t : "") + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + t) + (c ? d + Math.abs(n - i).toFixed(c).slice(2) : "");
};

View File

@@ -39,8 +39,10 @@ function switchPage(next) {
console.log("switchpage: currentPage: ", currentPage);
// Update prev/next button positions for mobile/desktop
prevButton.anchors.verticalCenter = wizard.verticalCenter
nextButton.anchors.verticalCenter = wizard.verticalCenter
prevButton.anchors.verticalCenter = (!isMobile) ? wizard.verticalCenter : undefined
prevButton.anchors.bottom = (isMobile) ? wizard.bottom : undefined
nextButton.anchors.verticalCenter = (!isMobile) ? wizard.verticalCenter : undefined
nextButton.anchors.bottom = (isMobile) ? wizard.bottom : undefined
if (currentPage > 0 || currentPage < pages.length - 1) {
pages[currentPage].opacity = 0

View File

@@ -51,12 +51,4 @@ 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,9 +64,8 @@
#include "MainApp.h"
#include "qt/ipc.h"
#include "qt/utils.h"
#include "src/qt/TailsOS.h"
#include "qt/mime.h"
#include "src/qt/KeysFiles.h"
#include "src/qt/MoneroSettings.h"
#include "qt/prices.h"
// IOS exclusions
@@ -83,7 +82,6 @@ bool isAndroid = false;
bool isWindows = false;
bool isMac = false;
bool isLinux = false;
bool isTails = false;
bool isDesktop = false;
bool isOpenGL = true;
@@ -103,7 +101,6 @@ 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
@@ -125,43 +122,25 @@ int main(int argc, char *argv[])
// qDebug() << "High DPI auto scaling - enabled";
//#endif
// Turn off colors in monerod log output.
qputenv("TERM", "goaway");
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(isTails && TailsOS::usePersistence){
moneroAccountsDir = QDir::homePath() + "/Persistent/Monero/wallets";
} else if (!moneroAccountsRootDir.empty()) {
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
@@ -174,10 +153,7 @@ int main(int argc, char *argv[])
QCoreApplication::translate("main", "Log to specified file"),
QCoreApplication::translate("main", "file"));
QCommandLineOption testQmlOption("test-qml");
testQmlOption.setFlags(QCommandLineOption::HiddenFromHelp);
parser.addOption(logPathOption);
parser.addOption(testQmlOption);
parser.addHelpOption();
parser.process(app);
@@ -197,7 +173,6 @@ int main(int argc, char *argv[])
}
qWarning().noquote() << "app startd" << "(log: " + logPath + ")";
// Desktop entry
#ifdef Q_OS_LINUX
registerXdgMime(app);
#endif
@@ -249,9 +224,6 @@ 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");
@@ -341,8 +313,6 @@ 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);
@@ -356,7 +326,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("isTails", isTails);
engine.rootContext()->setContextProperty("isLinux", isLinux);
engine.rootContext()->setContextProperty("screenWidth", geo.width());
engine.rootContext()->setContextProperty("screenHeight", geo.height());
@@ -380,7 +350,6 @@ 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());
@@ -408,10 +377,6 @@ int main(int argc, char *argv[])
return 1;
}
// QML loaded successfully.
if (parser.isSet(testQmlOption))
return 0;
#ifdef WITH_SCANNER
QObject *qmlCamera = rootObject->findChild<QObject*>("qrCameraQML");
if (qmlCamera)

629
main.qml

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
# qml components require at least QT 5.9.7
lessThan (QT_MAJOR_VERSION, 5) | lessThan (QT_MINOR_VERSION, 9) {
error("Can't build with Qt $${QT_VERSION}. Use at least Qt 5.9.7")
# 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")
}
TEMPLATE = app
@@ -16,21 +16,10 @@ packagesExist(libusb-1.0) {
packagesExist(hidapi-libusb) {
PKGCONFIG += hidapi-libusb
}
GCC_VERSION = $$system("g++ -dumpversion")
GCC_VERSION = $$split(GCC_VERSION, .)
GCC_VERSION_MAJOR = $$member(GCC_VERSION, 0)
GCC_VERSION_MINOR = $$member(GCC_VERSION, 1)
greaterThan(GCC_VERSION_MAJOR, 9) | if(equals(GCC_VERSION_MAJOR, 9) : greaterThan(GCC_VERSION_MINOR, 0)) {
GCC_9_1_OR_GREATER = TRUE
}
!win32 | !isEmpty(GCC_9_1_OR_GREATER) {
!win32 {
QMAKE_CXXFLAGS += -fPIC -fstack-protector -fstack-protector-strong
QMAKE_LFLAGS += -fstack-protector -fstack-protector-strong
}
!win32 {
packagesExist(protobuf) {
PKGCONFIG += protobuf
}
@@ -76,12 +65,10 @@ 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/macoshelper.h \
src/qt/MoneroSettings.h \
src/qt/TailsOS.h
src/qt/prices.h
SOURCES += main.cpp \
filter.cpp \
@@ -112,11 +99,10 @@ 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/MoneroSettings.cpp \
src/qt/TailsOS.cpp
src/qt/prices.cpp
CONFIG(DISABLE_PASS_STRENGTH_METER) {
HEADERS -= src/zxcvbn-c/zxcvbn.h
@@ -153,25 +139,25 @@ ios:arm64 {
LIBS += \
-L$$PWD/../ofxiOSBoost/build/libs/boost/lib/arm64 \
}
LIBS_COMMON = \
-lwallet_merged \
-llmdb \
-lepee \
-lunbound \
-lsodium \
-leasylogging \
-lrandomx
!ios:!android {
LIBS += -L$$WALLET_ROOT/lib \
$$LIBS_COMMON
LIBS += -L$$WALLET_ROOT/lib \
-lwallet_merged \
-llmdb \
-lepee \
-lunbound \
-lsodium \
-leasylogging
}
android {
message("Host is Android")
LIBS += -L$$WALLET_ROOT/lib \
$$LIBS_COMMON
-lwallet_merged \
-llmdb \
-lepee \
-lunbound \
-lsodium \
-leasylogging
}
@@ -186,7 +172,12 @@ ios {
QMAKE_IOS_DEVICE_ARCHS = arm64
CONFIG += arm64
LIBS += -L$$WALLET_ROOT/lib-ios \
$$LIBS_COMMON
-lwallet_merged \
-llmdb \
-lepee \
-lunbound \
-lsodium \
-leasylogging
LIBS+= \
-L$$PWD/../OpenSSL-for-iPhone/lib \
@@ -293,7 +284,6 @@ win32 {
-licudt \
-licutu \
-liconv \
-lstdc++ \
-lpthread \
-lsetupapi \
-lssl \
@@ -349,8 +339,7 @@ linux {
if(!android) {
LIBS+= \
-Wl,-Bdynamic \
-lGL \
-lX11
-lGL
}
# currently monero has an issue with "static" build and linunwind-dev,
# so we link libunwind-dev only for non-Ubuntu distros
@@ -370,19 +359,9 @@ macx {
# message("using static libraries")
# LIBS+= -Wl,-Bstatic
# }
OPENSSL_LIBRARY_DIRS = $$system(brew --prefix openssl, lines, EXIT_CODE)
equals(EXIT_CODE, 0) {
OPENSSL_LIBRARY_DIRS = $$OPENSSL_LIBRARY_DIRS/lib
} else {
OPENSSL_LIBRARY_DIRS = /usr/local/ssl/lib
}
QT += macextras
OBJECTIVE_SOURCES += src/qt/macoshelper.mm
LIBS+= \
-L/usr/local/lib \
-L$$OPENSSL_LIBRARY_DIRS \
-L/usr/local/opt/openssl/lib \
-L/usr/local/opt/boost/lib \
-lboost_serialization \
-lboost_thread-mt \
@@ -393,7 +372,6 @@ macx {
-lboost_chrono \
-lboost_program_options \
-framework CoreFoundation \
-framework AppKit \
-lhidapi \
-lssl \
-lsodium \
@@ -512,9 +490,6 @@ DISTFILES += \
notes.txt \
monero/src/wallet/CMakeLists.txt
VERSION = $$cat('version.js', lines)
VERSION = $$find(VERSION, 'GUI_VERSION')
VERSION = $$replace(VERSION, '.*(\d+\.\d+\.\d+\.\d+).*', '\1')
# windows application icon
RC_ICONS = images/appicon.ico

View File

@@ -31,20 +31,6 @@
#include <QDir>
#include <QDebug>
#include <QString>
#ifdef Q_OS_MAC
#include "qt/macoshelper.h"
#endif
#ifdef Q_OS_WIN32
#include <windows.h>
#endif
#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)
#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)
{
@@ -72,27 +58,6 @@ 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) && !defined(Q_OS_ANDROID) // 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,7 +42,6 @@ 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

@@ -31,7 +31,6 @@ import QtQuick.Controls 2.0
import QtQuick.Controls.Styles 1.4
import QtQuick.Layouts 1.1
import QtQuick.Dialogs 1.2
import FontAwesome 1.0
import "../components" as MoneroComponents
import "../components/effects/" as MoneroEffects
@@ -49,7 +48,6 @@ Rectangle {
property var model
property alias accountHeight: mainLayout.height
property bool selectAndSend: false
property int currentAccountIndex
function renameSubaddressAccountLabel(_index){
inputDialog.labelText = qsTr("Set the label of the selected account:") + translationManager.emptyString;
@@ -66,7 +64,7 @@ Rectangle {
/* main layout */
ColumnLayout {
id: mainLayout
anchors.margins: 20
anchors.margins: (isMobile)? 17 : 20
anchors.topMargin: 40
anchors.left: parent.left
@@ -103,7 +101,8 @@ Rectangle {
id: balanceAll
font.family: MoneroComponents.Style.fontMonoRegular.name;
font.pixelSize: 16
color: MoneroComponents.Style.defaultFontColor
color: MoneroComponents.Style.dimmedFontColor
themeTransition: false
MouseArea {
hoverEnabled: true
@@ -136,7 +135,8 @@ Rectangle {
id: unlockedBalanceAll
font.family: MoneroComponents.Style.fontMonoRegular.name;
font.pixelSize: 16
color: MoneroComponents.Style.defaultFontColor
color: MoneroComponents.Style.dimmedFontColor
themeTransition: false
MouseArea {
hoverEnabled: true
@@ -177,11 +177,10 @@ Rectangle {
ListView {
id: subaddressAccountListView
Layout.fillWidth: true
Layout.fillHeight: true
anchors.fill: parent
clip: true
boundsBehavior: ListView.StopAtBounds
interactive: false
currentIndex: currentAccountIndex
delegate: Rectangle {
id: tableItem2
@@ -213,7 +212,7 @@ Rectangle {
MoneroComponents.Label {
id: idLabel
color: index === currentAccountIndex ? MoneroComponents.Style.defaultFontColor : "#757575"
color: index === appWindow.current_subaddress_account_table_index ? MoneroComponents.Style.defaultFontColor : "#757575"
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin: 6
@@ -280,9 +279,9 @@ Rectangle {
onEntered: tableItem2.color = MoneroComponents.Style.titleBarButtonHoverColor
onExited: tableItem2.color = "transparent"
onClicked: {
appWindow.currentWallet.switchSubaddressAccount(index);
if (selectAndSend)
if (index == subaddressAccountListView.currentIndex && selectAndSend)
appWindow.showPageRequest("Transfer");
subaddressAccountListView.currentIndex = index;
}
}
}
@@ -321,9 +320,17 @@ Rectangle {
}
}
}
onCurrentItemChanged: {
// reset global vars
appWindow.current_subaddress_account_table_index = subaddressAccountListView.currentIndex;
appWindow.currentWallet.switchSubaddressAccount(appWindow.current_subaddress_account_table_index);
appWindow.onWalletUpdate();
}
onCurrentIndexChanged: {
appWindow.onWalletUpdate();
if (selectAndSend) {
appWindow.showPageRequest("Transfer");
}
}
}
}
@@ -344,9 +351,8 @@ Rectangle {
id: addNewAccountCheckbox
visible: !selectAndSend
border: false
uncheckedIcon: FontAwesome.plusCircle
toggleOnClick: false
fontAwesomeIcons: true
checkedIcon: "qrc:///images/plus-in-circle-medium-white.png"
uncheckedIcon: "qrc:///images/plus-in-circle-medium-white.png"
fontSize: 16
iconOnTheLeft: true
Layout.fillWidth: true
@@ -358,6 +364,7 @@ Rectangle {
inputDialog.onAcceptedCallback = function() {
appWindow.currentWallet.subaddressAccount.addRow(inputDialog.inputText)
appWindow.currentWallet.switchSubaddressAccount(appWindow.currentWallet.numSubaddressAccounts() - 1)
current_subaddress_account_table_index = appWindow.currentWallet.numSubaddressAccounts() - 1
appWindow.onWalletUpdate();
}
inputDialog.onRejectedCallback = null;

View File

@@ -52,7 +52,7 @@ Rectangle {
ColumnLayout {
id: mainLayout
anchors.margins: 20
anchors.margins: (isMobile)? 17 : 20
anchors.topMargin: 40
anchors.left: parent.left
@@ -67,18 +67,21 @@ Rectangle {
spacing: 0
Layout.fillWidth: true
Text {
TextArea {
id: titleLabel
Layout.fillWidth: true
color: MoneroComponents.Style.defaultFontColor
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 32
horizontalAlignment: TextInput.AlignLeft
selectByMouse: false
wrapMode: Text.WordWrap;
textMargin: 0
leftPadding: 0
topPadding: 0
text: qsTr("Save your most used addresses here") + translationManager.emptyString
width: parent.width
readOnly: true
// @TODO: Legacy. Remove after Qt 5.8.
// https://stackoverflow.com/questions/41990013
@@ -88,17 +91,20 @@ Rectangle {
}
}
Text {
TextArea {
Layout.fillWidth: true
color: MoneroComponents.Style.dimmedFontColor
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 16
horizontalAlignment: TextInput.AlignLeft
selectByMouse: false
wrapMode: Text.WordWrap;
textMargin: 0
leftPadding: 0
topPadding: 0
text: qsTr("This makes it easier to send or receive Monero and reduces errors when typing in addresses manually.") + translationManager.emptyString
width: parent.width
readOnly: true
// @TODO: Legacy. Remove after Qt 5.8.
// https://stackoverflow.com/questions/41990013
@@ -139,7 +145,7 @@ Rectangle {
ListView {
id: addressBookListView
Layout.fillWidth: true
Layout.fillHeight: true
anchors.fill: parent
clip: true
boundsBehavior: ListView.StopAtBounds
interactive: false
@@ -278,9 +284,8 @@ Rectangle {
MoneroComponents.CheckBox {
id: addNewEntryCheckbox
border: false
uncheckedIcon: FontAwesome.plusCircle
toggleOnClick: false
fontAwesomeIcons: true
checkedIcon: "qrc:///images/plus-in-circle-medium-white.png"
uncheckedIcon: "qrc:///images/plus-in-circle-medium-white.png"
fontSize: 16
iconOnTheLeft: true
Layout.fillWidth: true
@@ -320,8 +325,8 @@ Rectangle {
wrapMode: Text.WrapAnywhere
addressValidation: true
pasteButton: true
onTextChanged: {
const parsed = walletManager.parse_uri_to_object(addressLine.text);
onPaste: function(clipboardText) {
const parsed = walletManager.parse_uri_to_object(clipboardText);
if (!parsed.error) {
addressLine.text = parsed.address;
descriptionLine.text = parsed.tx_description;

View File

@@ -49,9 +49,9 @@ Rectangle {
property var model
property int sideMargin: 50
property var initialized: false
property int txMax: Math.max(5, ((appWindow.height - 250) / 60))
property int txMax: 5
property int txOffset: 0
property int txPage: (txOffset / txMax) + 1
property int txPage: (txOffset / 5) + 1
property int txCount: 0
property var sortSearchString: null
property bool sortDirection: true // true = desc, false = asc
@@ -67,8 +67,6 @@ Rectangle {
color: "transparent"
onTxMaxChanged: root.updateDisplay(root.txOffset, root.txMax);
ColumnLayout {
id: pageRoot
anchors.topMargin: 40
@@ -181,6 +179,7 @@ Rectangle {
Layout.rightMargin: sideMargin
columns: 2
columnSpacing: 20
z: 6
MoneroComponents.DatePicker {
id: fromDatePicker
@@ -227,7 +226,7 @@ Rectangle {
MoneroComponents.TextPlain {
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 15
text: qsTr("Sort by") + ":" + translationManager.emptyString
text: qsTr("Sort by") + ":"
color: MoneroComponents.Style.defaultFontColor
anchors.verticalCenter: parent.verticalCenter
}
@@ -250,6 +249,7 @@ 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,6 +310,7 @@ Rectangle {
text: qsTr("Date") + translationManager.emptyString
color: root.sortBy === "timestamp" ? MoneroComponents.Style.defaultFontColor : MoneroComponents.Style.dimmedFontColor
themeTransition: false
anchors.verticalCenter: parent.verticalCenter
}
MoneroEffects.ImageMask {
@@ -369,6 +370,7 @@ Rectangle {
text: qsTr("Amount") + translationManager.emptyString
color: root.sortBy === "amount" ? MoneroComponents.Style.defaultFontColor : MoneroComponents.Style.dimmedFontColor
themeTransition: false
anchors.verticalCenter: parent.verticalCenter
}
MoneroEffects.ImageMask {
@@ -446,7 +448,7 @@ Rectangle {
MoneroComponents.TextPlain {
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 15
text: qsTr("Page") + ":" + translationManager.emptyString
text: qsTr("Page") + ":"
color: MoneroComponents.Style.defaultFontColor
anchors.verticalCenter: parent.verticalCenter
}
@@ -650,7 +652,7 @@ Rectangle {
MoneroComponents.TextPlain {
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 15
text: displayAmount
text: _amount + " XMR"
color: MoneroComponents.Style.defaultFontColor
anchors.verticalCenter: parent.verticalCenter
@@ -869,7 +871,7 @@ Rectangle {
MoneroComponents.TextPlain {
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 15
text: persistentSettings.historyHumanDates ? dateHuman : dateTime
text: persistentSettings.historyHumanDates ? dateHuman : date + " " + time
color: MoneroComponents.Style.defaultFontColor
anchors.verticalCenter: parent.verticalCenter
@@ -881,7 +883,7 @@ Rectangle {
onEntered: {
parent.color = MoneroComponents.Style.orange
if (persistentSettings.historyHumanDates) {
parent.text = dateTime;
parent.text = date + " " + time;
}
}
onExited: {
@@ -938,7 +940,7 @@ Rectangle {
anchors.leftMargin: 10
text: FontAwesome.productHunt
small: true
label.font.family: FontAwesome.fontFamilyBrands
label.font.family: FontAwesome.fontFamily
fontSize: 18
width: 36
@@ -1196,7 +1198,7 @@ Rectangle {
if(res[i].state === 'copyable_address') root.toClipboard(address);
if(res[i].state === 'copyable_txkey') root.getTxKey(hash, res[i]);
if(res[i].state === 'set_tx_note') root.editDescription(hash);
if(res[i].state === 'details') root.showTxDetails(hash, paymentId, destinations, subaddrAccount, subaddrIndex, dateTime, displayAmount, isout);
if(res[i].state === 'details') root.showTxDetails(hash, paymentId, destinations, subaddrAccount, subaddrIndex);
if(res[i].state === 'proof') root.showTxProof(hash, paymentId, destinations, subaddrAccount, subaddrIndex);
doCollapse = false;
break;
@@ -1341,14 +1343,13 @@ Rectangle {
root.updateDisplay(root.txOffset, root.txMax);
}
function reset(keepDate) {
function reset() {
root.txOffset = 0;
root.txMax = 5;
if (typeof root.model !== 'undefined' && root.model != null) {
if (!keepDate) {
root.model.dateFromFilter = "2014-04-18" // genesis block
root.model.dateToFilter = "9999-09-09" // fix before september 9999
}
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;
@@ -1360,9 +1361,8 @@ Rectangle {
// applying filters
root.txData = JSON.parse(JSON.stringify(root.txModelData)); // deepcopy
const timezoneOffset = new Date().getTimezoneOffset() * 60;
var fromDate = Math.floor(fromDatePicker.currentDate.getTime() / 86400000) * 86400 + timezoneOffset;
var toDate = (Math.floor(toDatePicker.currentDate.getTime() / 86400000) + 1) * 86400 + timezoneOffset;
var fromDate = fromDatePicker.currentDate.getTime() / 1000;
var toDate = toDatePicker.currentDate.getTime() / 1000;
var txs = [];
for (var i = 0; i < root.txData.length; i++){
@@ -1387,8 +1387,6 @@ 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);
}
@@ -1479,12 +1477,12 @@ Rectangle {
var timestamp = new Date(date + " " + time).getTime() / 1000;
var dateHuman = Utils.ago(timestamp);
var displayAmount = amount;
if(displayAmount === 0){
var _amount = amount;
if(_amount === 0){
// *sometimes* amount is 0, while the 'destinations string'
// has the correct amount, so we try to fetch it from that instead.
displayAmount = TxUtils.destinationsToAmount(destinations);
displayAmount = Number(displayAmount *1);
_amount = TxUtils.destinationsToAmount(destinations);
_amount = Number(_amount *1);
}
var tx_note = currentWallet.getUserNote(hash);
@@ -1502,14 +1500,15 @@ Rectangle {
"i": i,
"isout": isout,
"amount": Number(amount),
"displayAmount": displayAmount + " XMR",
"_amount": _amount,
"hash": hash,
"paymentId": paymentId,
"address": address,
"destinations": destinations,
"tx_note": tx_note,
"time": time,
"date": date,
"dateHuman": dateHuman,
"dateTime": date + " " + time,
"blockheight": blockheight,
"address": address,
"timestamp": timestamp,
@@ -1581,25 +1580,22 @@ Rectangle {
elem.parent.text = txKey ? txKey : '-';
elem.parent.state = 'ready';
});
} else {
toClipboard(elem.parent.text);
}
toClipboard(elem.parent.text);
}
function showTxDetails(hash, paymentId, destinations, subaddrAccount, subaddrIndex, dateTime, amount, isout) {
function showTxDetails(hash, paymentId, destinations, subaddrAccount, subaddrIndex){
var tx_note = currentWallet.getUserNote(hash)
var rings = currentWallet.getRings(hash)
var address_label = subaddrIndex == 0 ? (qsTr("Primary address") + translationManager.emptyString) : currentWallet.getSubaddressLabel(subaddrAccount, subaddrIndex)
var address = currentWallet.address(subaddrAccount, subaddrIndex)
const hasPaymentId = parseInt(paymentId, 16);
const integratedAddress = !isout && hasPaymentId ? currentWallet.integratedAddress(paymentId) : null;
if (rings)
rings = rings.replace(/\|/g, '\n')
currentWallet.getTxKeyAsync(hash, function(hash, tx_key) {
informationPopup.title = qsTr("Transaction details") + translationManager.emptyString;
informationPopup.content = buildTxDetailsString(hash, paymentId, tx_key, tx_note, destinations, rings, address, address_label, integratedAddress, dateTime, amount);
informationPopup.content = buildTxDetailsString(hash, paymentId, tx_key, tx_note, destinations, rings, address, address_label);
informationPopup.onCloseCallback = null
informationPopup.open();
});
@@ -1627,18 +1623,16 @@ Rectangle {
appWindow.showStatusMessage(qsTr("Copied to clipboard"),3);
}
function buildTxDetailsString(tx_id, paymentId, tx_key,tx_note, destinations, rings, address, address_label, integratedAddress, dateTime, amount) {
var trStart = '<tr><td style="white-space: nowrap; padding-top:5px"><b>',
function buildTxDetailsString(tx_id, paymentId, tx_key,tx_note, destinations, rings, address, address_label) {
var trStart = '<tr><td width="85" style="padding-top:5px"><b>',
trMiddle = '</b></td><td style="padding-left:10px;padding-top:5px;">',
trEnd = "</td></tr>";
return '<table border="0">'
+ (tx_id ? trStart + qsTr("Tx ID:") + trMiddle + tx_id + trEnd : "")
+ (dateTime ? trStart + qsTr("Date") + ":" + trMiddle + dateTime + trEnd : "")
+ (amount ? trStart + qsTr("Amount") + ":" + trMiddle + amount + trEnd : "")
+ (address_label ? trStart + qsTr("Address label:") + trMiddle + address_label + trEnd : "")
+ (address ? trStart + qsTr("Address:") + trMiddle + address + trEnd : "")
+ (paymentId ? trStart + qsTr("Payment ID:") + trMiddle + paymentId + trEnd : "")
+ (integratedAddress ? trStart + qsTr("Integrated address") + ":" + trMiddle + integratedAddress + trEnd : "")
+ (tx_key ? trStart + qsTr("Tx key:") + trMiddle + tx_key + trEnd : "")
+ (tx_note ? trStart + qsTr("Tx note:") + trMiddle + tx_note + trEnd : "")
+ (destinations ? trStart + qsTr("Destinations:") + trMiddle + destinations + trEnd : "")
@@ -1710,6 +1704,6 @@ Rectangle {
function onPageClosed(){
root.initialized = false;
root.reset(true);
root.reset();
}
}

View File

@@ -52,7 +52,7 @@ Rectangle {
anchors.top: parent.top
anchors.right: parent.right
anchors.margins: 20
anchors.margins: (isMobile)? 17 : 20
anchors.topMargin: 40
spacing: 30
@@ -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
}
}
@@ -251,7 +251,7 @@ Rectangle {
onClicked: {
loadPage("Settings")
}
Layout.alignment: Qt.AlignCenter
anchors.horizontalCenter: parent.horizontalCenter
width: 135
}
}
@@ -261,7 +261,6 @@ 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

@@ -41,7 +41,7 @@ Rectangle {
ColumnLayout {
id: mainLayout
Layout.fillWidth: true
anchors.margins: 20
anchors.margins: (isMobile)? 17 : 20
anchors.topMargin: 40
anchors.left: parent.left
anchors.top: parent.top

View File

@@ -31,7 +31,6 @@ import QtQuick.Controls 2.0
import QtQuick.Controls.Styles 1.4
import QtQuick.Layouts 1.1
import QtQuick.Dialogs 1.2
import FontAwesome 1.0
import "../components" as MoneroComponents
import "../components/effects/" as MoneroEffects
@@ -66,7 +65,7 @@ Rectangle {
/* main layout */
ColumnLayout {
id: mainLayout
anchors.margins: 20
anchors.margins: (isMobile)? 17 : 20
anchors.topMargin: 40
anchors.left: parent.left
@@ -102,7 +101,7 @@ Rectangle {
ListView {
id: subaddressListView
Layout.fillWidth: true
Layout.fillHeight: true
anchors.fill: parent
clip: true
boundsBehavior: ListView.StopAtBounds
interactive: false
@@ -244,9 +243,8 @@ Rectangle {
MoneroComponents.CheckBox {
id: addNewAddressCheckbox
border: false
uncheckedIcon: FontAwesome.plusCircle
toggleOnClick: false
fontAwesomeIcons: true
checkedIcon: "qrc:///images/plus-in-circle-medium-white.png"
uncheckedIcon: "qrc:///images/plus-in-circle-medium-white.png"
fontSize: 16
iconOnTheLeft: true
Layout.fillWidth: true
@@ -258,7 +256,6 @@ 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()
@@ -311,20 +308,6 @@ Rectangle {
appWindow.showStatusMessage(qsTr("Copied to clipboard") + translationManager.emptyString, 3);
}
}
MoneroComponents.StandardButton {
text: FontAwesome.eye
label.font.family: FontAwesome.fontFamily
fontSize: 24
width: 36
visible: appWindow.currentWallet ? appWindow.currentWallet.isHwBacked() : false
onClicked: {
appWindow.currentWallet.deviceShowAddressAsync(
appWindow.currentWallet.currentSubaddressAccount,
appWindow.current_subaddress_table_index,
'');
}
}
}
}

View File

@@ -80,7 +80,7 @@ Rectangle {
ColumnLayout {
id: mainLayout
Layout.fillWidth: true
anchors.margins: 20
anchors.margins: (isMobile)? 17 : 20
anchors.topMargin: 40
anchors.left: parent.left
@@ -296,7 +296,7 @@ Rectangle {
GridLayout{
Layout.topMargin: 12
columns: 2
columns: (isMobile) ? 1 : 2
columnSpacing: 32
ColumnLayout {
@@ -368,7 +368,7 @@ Rectangle {
GridLayout {
columnSpacing: 20
columns: 2
columns: (isMobile) ? 1 : 2
MoneroComponents.CheckBox {
id: segregatePreForkOutputs
@@ -405,7 +405,7 @@ Rectangle {
id: segregationHeightRow
Layout.fillWidth: true
Layout.topMargin: 17
columns: 2
columns: (isMobile) ? 1 : 2
columnSpacing: 32
MoneroComponents.LineEdit {

View File

@@ -88,7 +88,7 @@ Rectangle {
ColumnLayout {
id: mainLayout
Layout.fillWidth: true
anchors.margins: 20
anchors.margins: (isMobile)? 17 : 20
anchors.topMargin: 40
anchors.left: parent.left

View File

@@ -56,7 +56,7 @@ Rectangle {
property bool showAdvanced: false
// @TODO: remove after pid removal hardfork
property bool warningLongPidTransfer: false
property bool warningLongPidDescription: descriptionLine.text.match(/^[0-9a-f]{64}$/i)
property bool warningLongPidDescription: false
Clipboard { id: clipboard }
@@ -123,7 +123,7 @@ Rectangle {
ColumnLayout {
id: pageRoot
anchors.margins: 20
anchors.margins: (isMobile)? 17 : 20
anchors.topMargin: 40
anchors.left: parent.left
@@ -143,16 +143,8 @@ Rectangle {
}
}
RowLayout {
visible: leftPanel.minutesToUnlock !== ""
MoneroComponents.WarningBox {
text: qsTr("Spendable funds: %1 XMR. Please wait ~%2 minutes for your whole balance to become spendable.").arg(leftPanel.balanceUnlockedString).arg(leftPanel.minutesToUnlock)
}
}
GridLayout {
columns: appWindow.walletMode < 2 ? 1 : 2
columns: (isMobile || !(appWindow.walletMode >= 2)) ? 1 : 2
Layout.fillWidth: true
columnSpacing: 32
@@ -168,10 +160,6 @@ Rectangle {
labelText: qsTr("<style type='text/css'>a {text-decoration: none; color: #858585; font-size: 14px;}</style>\
Amount <font size='2'> ( </font> <a href='#'>Change account</a><font size='2'> )</font>")
+ translationManager.emptyString
copyButton: !isNaN(amountLine.text) && persistentSettings.fiatPriceEnabled
copyButtonText: fiatApiCurrencySymbol() + " ~" + fiatApiConvertToFiat(amountLine.text)
copyButtonEnabled: false
onLabelLinkActivated: {
middlePanel.accountView.selectAndSend = true;
appWindow.showPageRequest("Account")
@@ -182,17 +170,9 @@ Rectangle {
inlineButtonText: qsTr("All") + translationManager.emptyString
inlineButton.onClicked: amountLine.text = "(all)"
onTextChanged: {
const match = amountLine.text.match(/^0+(\d.*)/);
if (match) {
const cursorPosition = amountLine.cursorPosition;
amountLine.text = match[1];
amountLine.cursorPosition = Math.max(cursorPosition, 1) - 1;
} else if(amountLine.text.indexOf('.') === 0){
amountLine.text = '0' + amountLine.text;
if (amountLine.text.length > 2) {
amountLine.cursorPosition = 1;
}
}
if(amountLine.text.indexOf('.') === 0){
amountLine.text = '0' + amountLine.text;
}
}
validator: RegExpValidator {
@@ -223,10 +203,10 @@ Rectangle {
id: priorityModelV5
ListElement { column1: qsTr("Automatic") ; column2: ""; priority: 0}
ListElement { column1: qsTr("Slow (x0.2 fee)") ; column2: ""; priority: 1}
ListElement { column1: qsTr("Slow (x0.25 fee)") ; column2: ""; priority: 1}
ListElement { column1: qsTr("Normal (x1 fee)") ; column2: ""; priority: 2 }
ListElement { column1: qsTr("Fast (x5 fee)") ; column2: ""; priority: 3 }
ListElement { column1: qsTr("Fastest (x200 fee)") ; column2: ""; priority: 4 }
ListElement { column1: qsTr("Fastest (x41.5 fee)") ; column2: ""; priority: 4 }
}
StandardDropdown {
@@ -269,15 +249,20 @@ Rectangle {
appWindow.showPageRequest("AddressBook");
}
pasteButton: true
onTextChanged: {
const parsed = walletManager.parse_uri_to_object(text);
onPaste: function(clipboardText) {
const parsed = walletManager.parse_uri_to_object(clipboardText);
if (!parsed.error) {
addressLine.text = parsed.address;
setPaymentId(parsed.payment_id);
amountLine.text = parsed.amount;
setDescription(parsed.tx_description);
} else {
addressLine.text = clipboardText;
}
warningLongPidTransfer = isLongPidService(text);
}
onTextChanged: {
// @TODO: remove after pid removal hardfork
warningLongPidTransfer = !persistentSettings.showPid && isLongPidService(text)
}
inlineButton.text: FontAwesome.qrcode
inlineButton.fontPixelSize: 22
@@ -338,12 +323,6 @@ Rectangle {
}
}
MoneroComponents.WarningBox {
text: qsTr("Description field contents match long payment ID format. \
Please don't paste long payment ID into description field, your funds might be lost.") + translationManager.emptyString;
visible: warningLongPidDescription
}
ColumnLayout {
spacing: 15
@@ -351,9 +330,8 @@ Rectangle {
CheckBox {
id: descriptionCheckbox
border: false
checkedIcon: FontAwesome.minusCircle
uncheckedIcon: FontAwesome.plusCircle
fontAwesomeIcons: true
checkedIcon: "qrc:///images/plus-in-circle-medium-white.png"
uncheckedIcon: "qrc:///images/plus-in-circle-medium-white.png"
fontSize: descriptionLine.labelFontSize
iconOnTheLeft: true
Layout.fillWidth: true
@@ -374,14 +352,13 @@ Rectangle {
}
ColumnLayout {
visible: paymentIdCheckbox.checked
visible: appWindow.persistentSettings.showPid || paymentIdCheckbox.checked
// @TODO: remove after pid removal hardfork
CheckBox {
id: paymentIdCheckbox
border: false
checkedIcon: FontAwesome.minusCircle
uncheckedIcon: FontAwesome.plusCircle
fontAwesomeIcons: true
checkedIcon: "qrc:///images/plus-in-circle-medium-white.png"
uncheckedIcon: "qrc:///images/plus-in-circle-medium-white.png"
fontSize: paymentIdLine.labelFontSize
iconOnTheLeft: true
Layout.fillWidth: true
@@ -398,7 +375,6 @@ Rectangle {
id: paymentIdLine
fontBold: true
placeholderText: qsTr("64 hexadecimal characters") + translationManager.emptyString
readOnly: true
Layout.fillWidth: true
wrapMode: Text.WrapAnywhere
addressValidation: false
@@ -410,10 +386,8 @@ Rectangle {
MoneroComponents.WarningBox {
// @TODO: remove after pid removal hardfork
id: paymentIdWarningBox
text: qsTr("Long payment IDs are obsolete. \
Long payment IDs were not encrypted on the blockchain and would harm your privacy. \
If the party you're sending to still requires a long payment ID, please notify them.") + translationManager.emptyString;
visible: warningLongPidTransfer || paymentIdCheckbox.checked
text: qsTr("You can enable transfers with payment ID on the settings page.") + translationManager.emptyString;
visible: !persistentSettings.showPid && (warningLongPidTransfer || warningLongPidDescription)
}
MoneroComponents.WarningBox {
@@ -469,7 +443,7 @@ Rectangle {
anchors.top: pageRoot.bottom
anchors.left: parent.left
anchors.right: parent.right
anchors.margins: 20
anchors.margins: (isMobile)? 17 : 20
anchors.topMargin: 32
spacing: 26
enabled: !viewOnly || pageRoot.enabled
@@ -488,7 +462,7 @@ Rectangle {
GridLayout {
visible: persistentSettings.transferShowAdvanced && appWindow.walletMode >= 2
columns: 6
columns: (isMobile) ? 2 : 6
StandardButton {
id: sweepUnmixableButton
@@ -766,8 +740,7 @@ Rectangle {
// Currently opened wallet is not view-only
if(appWindow.viewOnly){
root.sendButtonWarning = qsTr("Wallet is view-only and sends are not possible. Unless key images are imported, " +
"the balance reflects only incoming but not outgoing transactions.") + translationManager.emptyString;
root.sendButtonWarning = qsTr("Wallet is view-only and sends are not possible.") + translationManager.emptyString;
return false;
}
@@ -788,11 +761,6 @@ Rectangle {
root.sendButtonWarning = qsTr("Transaction information is incorrect.") + translationManager.emptyString;
return false;
}
if (paymentIdWarningBox.visible) {
return false;
}
return true;
}
}

View File

@@ -45,7 +45,7 @@ Rectangle {
/* main layout */
ColumnLayout {
id: mainLayout
anchors.margins: 20
anchors.margins: (isMobile)? 17 : 20
anchors.topMargin: 40
anchors.left: parent.left
anchors.top: parent.top

View File

@@ -33,6 +33,8 @@ Item {
property var hiddenAmounts: []
function onPageCompleted() {
appWindow.hideMenu();
// prepare tracking
trackingCheckbox.checked = root.enableTracking
root.update();
@@ -54,6 +56,8 @@ Item {
timer.running = false
root.enableTracking = false
trackingModel.clear()
appWindow.showMenu();
}
Image {
@@ -89,8 +93,9 @@ Item {
anchors.right: parent.right
Item {
Layout.preferredHeight: 220
Layout.fillWidth: true
height: 220
anchors.left: parent.left
anchors.right: parent.right
Rectangle {
id: tracker
@@ -158,7 +163,7 @@ Item {
"<p>It's up to you whether to accept unconfirmed transactions or not. It is likely they'll be " +
"confirmed in short order, but there is still a possibility they might not, so for larger " +
"values you may want to wait for one or more confirmation(s).</p>"
) + translationManager.emptyString;
);
} else if(root.trackingError !== ""){
return root.trackingError;
} else if(trackingModel.count < 1){
@@ -253,7 +258,8 @@ Item {
Item {
Layout.preferredHeight: 40
Layout.fillWidth: true
anchors.left: parent.left
anchors.right: parent.right
Item {
width: (parent.width - qrImg.width) - (50)
@@ -265,7 +271,7 @@ Item {
font.pixelSize: 12
font.bold: false
color: "white"
text: qsTr("<style type='text/css'>a {text-decoration: none; color: #FF6C3C; font-size: 12px;}</style>Currently selected address: ") + addressLabel + qsTr(" <a href='#'>(Change)</a>") + translationManager.emptyString
text: "<style type='text/css'>a {text-decoration: none; color: #FF6C3C; font-size: 12px;}</style>Currently selected address: " + addressLabel + " <a href='#'>(Change)</a>"
textFormat: Text.RichText
themeTransition: false
@@ -446,7 +452,7 @@ Item {
font.pixelSize: 14
font.bold: false
color: "white"
text: qsTr("Amount to receive") + " (XMR)" + translationManager.emptyString
text: qsTr("Amount to receive") + " (XMR)"
themeTransition: false
}
@@ -455,7 +461,7 @@ Item {
width: 220
source: "qrc:///images/merchant/input_box.png"
MoneroComponents.Input {
TextField {
id: amountToReceive
topPadding: 0
leftPadding: 10
@@ -518,7 +524,8 @@ Item {
Item {
Layout.topMargin: 32
Layout.preferredHeight: 40
Layout.fillWidth: true
anchors.left: parent.left
anchors.right: parent.right
ColumnLayout {
spacing: 16
@@ -623,7 +630,7 @@ Item {
in_txpool = true;
} else {
if (blockchainHeight == null)
blockchainHeight = walletManager.blockchainHeight()
blockchainHeight = appWindow.currentWallet.blockChainHeight()
confirmations = blockchainHeight - blockHeight - 1
displayAmount = model.data(idx, TransactionHistoryModel.TransactionDisplayAmountRole);
}

View File

@@ -4,55 +4,38 @@ import QtGraphicalEffects 1.0
import "../../components" as MoneroComponents
Item {
RowLayout {
id: root
spacing: 10
property bool checked: false;
property alias text: content.text
signal changed;
width: checkBoxLayout.width
height: 22
Rectangle {
id: checkbox
anchors.left: parent.left
anchors.top: parent.top
implicitHeight: 22
width: 22
radius: 5
RowLayout {
id: checkBoxLayout
spacing: 10
Item {
height: root.height
width: root.height
Rectangle {
id: checkbox
anchors.fill: parent
radius: 5
Image {
id: imageChecked
visible: root.checked
anchors.centerIn: parent
source: "qrc:///images/uncheckedIcon.png"
}
}
DropShadow {
anchors.fill: source
cached: true
horizontalOffset: 3
verticalOffset: 3
radius: 8.0
samples: 16
color: "#20000000"
smooth: true
source: checkbox
}
}
MoneroComponents.TextPlain {
id: content
font.pixelSize: 14
font.bold: false
color: "white"
text: ""
themeTransition: false
Image {
id: imageChecked
visible: root.checked
anchors.centerIn: parent
source: "qrc:///images/uncheckedIcon.png"
}
}
MoneroComponents.TextPlain {
id: content
font.pixelSize: 14
font.bold: false
color: "white"
text: ""
themeTransition: false
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
@@ -63,4 +46,16 @@ Item {
changed();
}
}
DropShadow {
anchors.fill: source
cached: true
horizontalOffset: 3
verticalOffset: 3
radius: 8.0
samples: 16
color: "#20000000"
smooth: true
source: checkbox
}
}

View File

@@ -44,7 +44,7 @@ Rectangle {
property bool showCloseButton: true
height: {
if(!persistentSettings.customDecorations) return 0;
if(!persistentSettings.customDecorations || isMobile) return 0;
return 50;
}

View File

@@ -61,7 +61,9 @@ Rectangle {
property string borderColor: MoneroComponents.Style.blackTheme ? "#808080" : "#B9B9B9"
property int textMargin: {
// left-right margins for a given cell
if(appWindow.width < 890){
if(isMobile){
return 10;
} else if(appWindow.width < 890){
return 32;
} else {
return 64;

View File

@@ -57,7 +57,7 @@ Rectangle {
anchors.left: parent.left
anchors.top: parent.top
anchors.right: parent.right
anchors.margins: 20
anchors.margins: (isMobile)? 17 : 20
anchors.topMargin: 0
spacing: 30
@@ -208,11 +208,10 @@ Rectangle {
confirmationDialog.icon = StandardIcon.Question
confirmationDialog.cancelText = qsTr("Cancel")
confirmationDialog.onAcceptedCallback = function() {
appWindow.closeWallet(function() {
walletManager.clearWalletCache(persistentSettings.wallet_path);
walletManager.openWalletAsync(persistentSettings.wallet_path, appWindow.walletPassword,
persistentSettings.nettype, persistentSettings.kdfRounds);
});
walletManager.closeWallet();
walletManager.clearWalletCache(persistentSettings.wallet_path);
walletManager.openWalletAsync(persistentSettings.wallet_path, appWindow.walletPassword,
persistentSettings.nettype, persistentSettings.kdfRounds);
}
confirmationDialog.onRejectedCallback = null;
@@ -326,41 +325,6 @@ 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

@@ -47,11 +47,12 @@ Rectangle {
anchors.left: parent.left
anchors.top: parent.top
anchors.right: parent.right
anchors.margins: 20
anchors.margins: (isMobile)? 17 : 20
anchors.topMargin: 0
spacing: 6
MoneroComponents.CheckBox {
visible: !isMobile
id: customDecorationsCheckBox
checked: persistentSettings.customDecorations
onClicked: Windows.setCustomWindowDecorations(checked)
@@ -59,6 +60,7 @@ Rectangle {
}
MoneroComponents.CheckBox {
visible: !isMobile
id: hideBalanceCheckBox
checked: persistentSettings.hideBalance
onClicked: {
@@ -68,11 +70,20 @@ Rectangle {
text: qsTr("Hide balance") + translationManager.emptyString
}
MoneroComponents.CheckBox {
visible: !isMobile
id: showPidCheckBox
checked: persistentSettings.showPid
onClicked: {
persistentSettings.showPid = !persistentSettings.showPid
}
text: qsTr("Enable transfer with payment ID (OBSOLETE)") + translationManager.emptyString
}
MoneroComponents.CheckBox {
id: themeCheckbox
checked: !MoneroComponents.Style.blackTheme
text: qsTr("Light theme") + translationManager.emptyString
toggleOnClick: false
onClicked: {
MoneroComponents.Style.blackTheme = !MoneroComponents.Style.blackTheme;
persistentSettings.blackTheme = MoneroComponents.Style.blackTheme;
@@ -80,6 +91,7 @@ Rectangle {
}
MoneroComponents.CheckBox {
visible: !isMobile
id: userInActivityCheckbox
checked: persistentSettings.lockOnUserInActivity
onClicked: persistentSettings.lockOnUserInActivity = !persistentSettings.lockOnUserInActivity
@@ -93,8 +105,7 @@ Rectangle {
Layout.leftMargin: 42
spacing: 0
Text {
color: MoneroComponents.Style.defaultFontColor
MoneroComponents.TextBlock {
font.pixelSize: 14
Layout.fillWidth: true
text: {
@@ -143,12 +154,6 @@ Rectangle {
}
onMoved: persistentSettings.lockOnUserInActivityInterval = userInactivitySlider.value;
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.NoButton
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
}
}
}
@@ -262,6 +267,14 @@ Rectangle {
appWindow.toggleLanguageView();
}
}
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;
}
}
ListModel {

View File

@@ -47,7 +47,7 @@ Rectangle {
anchors.left: parent.left
anchors.top: parent.top
anchors.right: parent.right
anchors.margins: 20
anchors.margins: (isMobile)? 17 : 20
anchors.topMargin: 0
spacing: 10
@@ -216,11 +216,7 @@ Rectangle {
onAccepted: {
if(text.length > 0) {
consoleArea.logCommand(">>> " + text)
daemonManager.sendCommandAsync(text.split(" "), currentWallet.nettype, function(result) {
if (!result) {
appWindow.showStatusMessage(qsTr("Failed to send command"), 3);
}
});
daemonManager.sendCommand(text, currentWallet.nettype);
}
text = ""
}

View File

@@ -42,7 +42,7 @@ Rectangle{
/* main layout */
ColumnLayout {
id: root
anchors.margins: 20
anchors.margins: (isMobile)? 17 : 20
anchors.topMargin: 0
anchors.left: parent.left
@@ -96,13 +96,17 @@ Rectangle{
anchors.leftMargin: 16
anchors.verticalCenter: parent.verticalCenter
MoneroComponents.Label {
fontSize: 32
text: FontAwesome.home
fontFamily: FontAwesome.fontFamilySolid
anchors.centerIn: parent
fontColor: MoneroComponents.Style.defaultFontColor
styleName: "Solid"
MoneroEffects.ImageMask {
height: 27
width: 27
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
fontAwesomeFallbackIcon: FontAwesome.shield
fontAwesomeFallbackSize: 26
image: "qrc:///images/settings_local.svg"
color: MoneroComponents.Style.defaultFontColor
opacity: MoneroComponents.Style.blackTheme ? 1.0 : 0.8
}
}
@@ -119,7 +123,7 @@ Rectangle{
text: qsTr("Local node") + translationManager.emptyString
}
Text {
TextArea {
id: localNodeArea
anchors.top: localNodeHeader.bottom
anchors.topMargin: 4
@@ -129,11 +133,14 @@ Rectangle{
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 15
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)
readOnly: true
// @TODO: Legacy. Remove after Qt 5.8.
// https://stackoverflow.com/questions/41990013
@@ -195,13 +202,16 @@ Rectangle{
anchors.leftMargin: 16
anchors.verticalCenter: parent.verticalCenter
MoneroComponents.Label {
fontSize: 28
text: FontAwesome.cloud
fontFamily: FontAwesome.fontFamilySolid
styleName: "Solid"
anchors.centerIn: parent
fontColor: MoneroComponents.Style.defaultFontColor
MoneroEffects.ImageMask {
height: 29
width: 22
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
fontAwesomeFallbackIcon: FontAwesome.cloudDownload
fontAwesomeFallbackSize: 26
image: "qrc:///images/settings_remote.svg"
color: MoneroComponents.Style.defaultFontColor
opacity: MoneroComponents.Style.blackTheme ? 1.0 : 0.8
}
}
@@ -218,7 +228,7 @@ Rectangle{
text: qsTr("Remote node") + translationManager.emptyString
}
Text {
TextArea {
id: remoteNodeArea
anchors.top: remoteNodeHeader.bottom
anchors.topMargin: 4
@@ -227,12 +237,16 @@ Rectangle{
color: MoneroComponents.Style.dimmedFontColor
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 15
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)
readOnly: true
// @TODO: Legacy. Remove after Qt 5.8.
// https://stackoverflow.com/questions/41990013
@@ -246,6 +260,7 @@ Rectangle{
cursorShape: Qt.PointingHandCursor
anchors.fill: parent
onClicked: {
persistentSettings.useRemoteNode = true;
appWindow.connectRemoteNode();
}
}
@@ -270,7 +285,7 @@ Rectangle{
spacing: 20
Layout.fillWidth: true
Layout.topMargin: 20
visible: persistentSettings.useRemoteNode
visible: !isMobile && persistentSettings.useRemoteNode
MoneroComponents.WarningBox {
Layout.topMargin: 26
@@ -302,7 +317,7 @@ Rectangle{
}
GridLayout {
columns: 2
columns: (isMobile) ? 1 : 2
columnSpacing: 32
MoneroComponents.LineEdit {
@@ -362,11 +377,11 @@ Rectangle{
id: localNodeLayout
spacing: 20
Layout.topMargin: 40
visible: !persistentSettings.useRemoteNode
visible: !isMobile && !persistentSettings.useRemoteNode
MoneroComponents.StandardButton {
small: true
text: (appWindow.daemonRunning ? qsTr("Stop daemon") : qsTr("Start daemon")) + translationManager.emptyString
text: (appWindow.daemonRunning ? qsTr("Stop local node") : qsTr("Start daemon")) + translationManager.emptyString
onClicked: {
if (appWindow.daemonRunning) {
appWindow.stopDaemon();
@@ -388,7 +403,6 @@ Rectangle{
labelText: qsTr("Blockchain location") + style + qsTr(" <a href='#'> (change)</a>") + translationManager.emptyString
placeholderText: qsTr("(default)") + translationManager.emptyString
placeholderFontSize: 15
readOnly: true
text: {
if(persistentSettings.blockchainDataDir.length > 0){
return persistentSettings.blockchainDataDir;
@@ -421,7 +435,7 @@ Rectangle{
}
RowLayout {
visible: !persistentSettings.useRemoteNode
visible: !isMobile && !persistentSettings.useRemoteNode
ColumnLayout {
Layout.fillWidth: true
@@ -443,11 +457,7 @@ Rectangle{
}
}
onEditingFinished: {
if (daemonAddrText == "auto") {
persistentSettings.bootstrapNodeAddress = daemonAddrText;
} else {
persistentSettings.bootstrapNodeAddress = daemonAddrText ? bootstrapNodeEdit.getAddress() : "";
}
persistentSettings.bootstrapNodeAddress = daemonAddrText ? bootstrapNodeEdit.getAddress() : "";
console.log("setting bootstrap node to " + persistentSettings.bootstrapNodeAddress)
}
}

View File

@@ -45,99 +45,314 @@ Rectangle {
anchors.left: parent.left
anchors.top: parent.top
anchors.right: parent.right
anchors.margins: 20
anchors.margins: (isMobile)? 17 : 20
anchors.topMargin: 0
spacing: 8
spacing: 0
MoneroComponents.SettingsListItem {
buttonText: qsTr("Close wallet") + translationManager.emptyString
description: qsTr("Logs out of this wallet.") + translationManager.emptyString
title: qsTr("Close this wallet") + translationManager.emptyString
Rectangle {
// divider
Layout.preferredHeight: 1
Layout.fillWidth: true
Layout.bottomMargin: 8
color: MoneroComponents.Style.dividerColor
opacity: MoneroComponents.Style.dividerOpacity
}
onClicked: {
middlePanel.addressBookView.clearFields();
middlePanel.transferView.clearFields();
middlePanel.receiveView.clearFields();
appWindow.showWizard();
GridLayout {
Layout.fillWidth: true
Layout.preferredHeight: childrenRect.height
columnSpacing: 0
ColumnLayout {
Layout.fillWidth: true
Layout.alignment: Qt.AlignVCenter
spacing: 0
MoneroComponents.TextPlain {
Layout.fillWidth: true
Layout.preferredHeight: 20
Layout.topMargin: 8
color: MoneroComponents.Style.defaultFontColor
opacity: MoneroComponents.Style.blackTheme ? 1.0 : 0.8
font.bold: true
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 16
text: qsTr("Close this wallet") + translationManager.emptyString
}
MoneroComponents.TextPlainArea {
color: MoneroComponents.Style.dimmedFontColor
colorBlackTheme: MoneroComponents.Style._b_dimmedFontColor
colorWhiteTheme: MoneroComponents.Style._w_dimmedFontColor
width: parent.width
Layout.fillWidth: true
horizontalAlignment: TextInput.AlignLeft
text: qsTr("Logs out of this wallet.") + translationManager.emptyString
}
}
MoneroComponents.StandardButton {
small: true
text: qsTr("Close wallet") + translationManager.emptyString
onClicked: {
middlePanel.addressBookView.clearFields();
middlePanel.transferView.clearFields();
middlePanel.receiveView.clearFields();
appWindow.showWizard();
}
width: 135
}
}
MoneroComponents.SettingsListItem {
buttonText: qsTr("Create wallet") + translationManager.emptyString
description: qsTr("Creates a new wallet that can only view and initiate transactions, but requires a spendable wallet to sign transactions before sending.") + translationManager.emptyString
title: qsTr("Create a view-only wallet") + translationManager.emptyString
Rectangle {
// divider
Layout.preferredHeight: 1
Layout.fillWidth: true
Layout.topMargin: 8
Layout.bottomMargin: 8
color: MoneroComponents.Style.dividerColor
opacity: MoneroComponents.Style.dividerOpacity
}
GridLayout {
Layout.fillWidth: true
Layout.preferredHeight: childrenRect.height
columnSpacing: 0
visible: !appWindow.viewOnly
onClicked: {
var newPath = currentWallet.path + "_viewonly";
if (currentWallet.createViewOnly(newPath, appWindow.walletPassword)) {
console.log("view only wallet created in " + newPath);
informationPopup.title = qsTr("Success") + translationManager.emptyString;
informationPopup.text = qsTr('The view only wallet has been created with the same password as the current wallet. You can open it by closing this current wallet, clicking the "Open wallet from file" option, and selecting the view wallet in: \n%1\nYou can change the password in the wallet settings.').arg(newPath);
informationPopup.open()
informationPopup.onCloseCallback = null
} else {
informationPopup.title = qsTr("Error") + translationManager.emptyString;
informationPopup.text = currentWallet.errorString;
informationPopup.open()
ColumnLayout {
Layout.fillWidth: true
Layout.alignment: Qt.AlignVCenter
spacing: 0
MoneroComponents.TextPlain {
Layout.fillWidth: true
Layout.preferredHeight: 20
Layout.topMargin: 8
color: MoneroComponents.Style.defaultFontColor
opacity: MoneroComponents.Style.blackTheme ? 1.0 : 0.8
font.bold: true
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 16
text: qsTr("Create a view-only wallet") + translationManager.emptyString
}
MoneroComponents.TextPlainArea {
color: MoneroComponents.Style.dimmedFontColor
colorBlackTheme: MoneroComponents.Style._b_dimmedFontColor
colorWhiteTheme: MoneroComponents.Style._w_dimmedFontColor
width: parent.width
Layout.fillWidth: true
horizontalAlignment: TextInput.AlignLeft
text: qsTr("Creates a new wallet that can only view and initiate transactions, but requires a spendable wallet to sign transactions before sending.") + translationManager.emptyString
}
}
}
MoneroComponents.SettingsListItem {
buttonText: qsTr("Show seed") + translationManager.emptyString
description: qsTr("Store this information safely to recover your wallet in the future.") + translationManager.emptyString
title: qsTr("Show seed & keys") + translationManager.emptyString
onClicked: {
Utils.showSeedPage();
}
}
MoneroComponents.SettingsListItem {
buttonText: qsTr("Rescan") + translationManager.emptyString
description: qsTr("Use this feature if you think the shown balance is not accurate.") + translationManager.emptyString
title: qsTr("Rescan wallet balance") + translationManager.emptyString
visible: appWindow.walletMode >= 2
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();
}
}
}
MoneroComponents.SettingsListItem {
buttonText: qsTr("Change password") + translationManager.emptyString
description: qsTr("Change the password of your wallet.") + translationManager.emptyString
title: qsTr("Change wallet password") + translationManager.emptyString
onClicked: {
passwordDialog.onAcceptedCallback = function() {
if(appWindow.walletPassword === passwordDialog.password){
passwordDialog.openNewPasswordDialog()
MoneroComponents.StandardButton {
small: true
text: qsTr("Create wallet") + translationManager.emptyString
onClicked: {
var newPath = currentWallet.path + "_viewonly";
if (currentWallet.createViewOnly(newPath, appWindow.walletPassword)) {
console.log("view only wallet created in " + newPath);
informationPopup.title = qsTr("Success") + translationManager.emptyString;
informationPopup.text = qsTr('The view only wallet has been created with the same password as the current wallet. You can open it by closing this current wallet, clicking the "Open wallet from file" option, and selecting the view wallet in: \n%1\nYou can change the password in the wallet settings.').arg(newPath);
informationPopup.open()
informationPopup.onCloseCallback = null
} else {
informationPopup.title = qsTr("Error") + translationManager.emptyString;
informationPopup.text = qsTr("Wrong password") + translationManager.emptyString;
informationPopup.text = currentWallet.errorString;
informationPopup.open()
informationPopup.onCloseCallback = function() {
passwordDialog.open()
}
}
}
passwordDialog.onRejectedCallback = null;
passwordDialog.open()
width: 135
}
}
Rectangle {
// divider
visible: !appWindow.viewOnly
Layout.preferredHeight: 1
Layout.fillWidth: true
Layout.topMargin: 8
Layout.bottomMargin: 8
color: MoneroComponents.Style.dividerColor
opacity: MoneroComponents.Style.dividerOpacity
}
GridLayout {
Layout.fillWidth: true
Layout.preferredHeight: childrenRect.height
columnSpacing: 0
ColumnLayout {
Layout.fillWidth: true
Layout.alignment: Qt.AlignVCenter
spacing: 0
MoneroComponents.TextPlain {
Layout.fillWidth: true
Layout.preferredHeight: 20
Layout.topMargin: 8
color: MoneroComponents.Style.defaultFontColor
opacity: MoneroComponents.Style.blackTheme ? 1.0 : 0.8
font.bold: true
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 16
text: qsTr("Show seed & keys") + translationManager.emptyString
}
MoneroComponents.TextPlainArea {
color: MoneroComponents.Style.dimmedFontColor
colorBlackTheme: MoneroComponents.Style._b_dimmedFontColor
colorWhiteTheme: MoneroComponents.Style._w_dimmedFontColor
width: parent.width
Layout.fillWidth: true
horizontalAlignment: TextInput.AlignLeft
text: qsTr("Store this information safely to recover your wallet in the future.") + translationManager.emptyString
}
}
MoneroComponents.StandardButton {
small: true
text: qsTr("Show seed") + translationManager.emptyString
onClicked: {
Utils.showSeedPage();
}
width: 135
}
}
Rectangle {
// divider
Layout.preferredHeight: 1
Layout.fillWidth: true
Layout.topMargin: 8
Layout.bottomMargin: 8
color: MoneroComponents.Style.dividerColor
opacity: MoneroComponents.Style.dividerOpacity
}
GridLayout {
visible: appWindow.walletMode >= 2
Layout.fillWidth: true
Layout.preferredHeight: childrenRect.height
columnSpacing: 0
ColumnLayout {
Layout.fillWidth: true
Layout.alignment: Qt.AlignVCenter
spacing: 0
MoneroComponents.TextPlain {
Layout.fillWidth: true
Layout.preferredHeight: 20
Layout.topMargin: 8
color: MoneroComponents.Style.defaultFontColor
opacity: MoneroComponents.Style.blackTheme ? 1.0 : 0.8
font.bold: true
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 16
text: qsTr("Rescan wallet balance") + translationManager.emptyString
}
MoneroComponents.TextPlainArea {
color: MoneroComponents.Style.dimmedFontColor
colorBlackTheme: MoneroComponents.Style._b_dimmedFontColor
colorWhiteTheme: MoneroComponents.Style._w_dimmedFontColor
width: parent.width
Layout.fillWidth: true
horizontalAlignment: TextInput.AlignLeft
text: qsTr("Use this feature if you think the shown balance is not accurate.") + translationManager.emptyString
}
}
MoneroComponents.StandardButton {
small: true
text: qsTr("Rescan") + 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();
}
}
width: 135
}
}
Rectangle {
// divider
visible: appWindow.walletMode >= 2
Layout.preferredHeight: 1
Layout.fillWidth: true
Layout.topMargin: 8
Layout.bottomMargin: 8
color: MoneroComponents.Style.dividerColor
opacity: MoneroComponents.Style.dividerOpacity
}
GridLayout {
Layout.fillWidth: true
Layout.preferredHeight: childrenRect.height
columnSpacing: 0
ColumnLayout {
Layout.fillWidth: true
Layout.alignment: Qt.AlignVCenter
spacing: 0
MoneroComponents.TextPlain {
Layout.fillWidth: true
Layout.preferredHeight: 20
Layout.topMargin: 8
color: MoneroComponents.Style.defaultFontColor
opacity: MoneroComponents.Style.blackTheme ? 1.0 : 0.8
font.bold: true
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 16
text: qsTr("Change wallet password") + translationManager.emptyString
}
MoneroComponents.TextPlainArea {
color: MoneroComponents.Style.dimmedFontColor
colorBlackTheme: MoneroComponents.Style._b_dimmedFontColor
colorWhiteTheme: MoneroComponents.Style._w_dimmedFontColor
width: parent.width
Layout.fillWidth: true
horizontalAlignment: TextInput.AlignLeft
text: qsTr("Change the password of your wallet.") + translationManager.emptyString
}
}
MoneroComponents.StandardButton {
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") + translationManager.emptyString;
informationPopup.open()
informationPopup.onCloseCallback = function() {
passwordDialog.open()
}
}
}
passwordDialog.onRejectedCallback = null;
passwordDialog.open()
}
width: 135
}
}
}

27
qml.qrc
View File

@@ -7,8 +7,11 @@
<file>images/download-white@2x.png</file>
<file>images/external-link-white.png</file>
<file>images/external-link-white@2x.png</file>
<file>images/minus-white.png</file>
<file>images/minus-white@2x.png</file>
<file>images/plus-white.png</file>
<file>images/plus-white@2x.png</file>
<file>components/Label.qml</file>
<file>components/SettingsListItem.qml</file>
<file>images/whatIsIcon.png</file>
<file>images/whatIsIcon@2x.png</file>
<file>images/lockIcon.png</file>
@@ -18,8 +21,6 @@
<file>pages/History.qml</file>
<file>pages/AddressBook.qml</file>
<file>pages/Mining.qml</file>
<file>components/ContextMenu.qml</file>
<file>components/ContextMenuItem.qml</file>
<file>components/NetworkStatusItem.qml</file>
<file>components/Input.qml</file>
<file>components/StandardButton.qml</file>
@@ -95,7 +96,9 @@
<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>
@@ -106,14 +109,13 @@
<file>components/DaemonConsole.qml</file>
<file>components/QRCodeScanner.qml</file>
<file>components/Notifier.qml</file>
<file>components/MobileHeader.qml</file>
<file>components/TextBlock.qml</file>
<file>components/RemoteNodeEdit.qml</file>
<file>pages/Keys.qml</file>
<file>images/appicon.ico</file>
<file>images/card-background-black.png</file>
<file>images/card-background-black@2x.png</file>
<file>images/card-background-white.png</file>
<file>images/card-background-white@2x.png</file>
<file>images/card-background.png</file>
<file>images/card-background@2x.png</file>
<file>images/moneroLogo_white.png</file>
<file>images/question.png</file>
<file>images/question@2x.png</file>
@@ -167,18 +169,20 @@
<file>pages/settings/SettingsLayout.qml</file>
<file>pages/settings/SettingsInfo.qml</file>
<file>pages/settings/Navbar.qml</file>
<file>images/settings_local.svg</file>
<file>images/settings_remote.svg</file>
<file>components/WarningBox.qml</file>
<file>images/miningxmr.png</file>
<file>images/miningxmr@2x.png</file>
<file>images/plus-in-circle-medium-white.png</file>
<file>images/plus-in-circle-medium-white@2x.png</file>
<file>pages/merchant/Merchant.qml</file>
<file>pages/merchant/MerchantCheckbox.qml</file>
<file>pages/merchant/MerchantTrackingList.qml</file>
<file>images/merchant/arrow_right.png</file>
<file>images/merchant/bg.png</file>
<file>images/merchant/input_box.png</file>
<file>fonts/FontAwesome/fa-brands-400.ttf</file>
<file>fonts/FontAwesome/fa-regular-400.ttf</file>
<file>fonts/FontAwesome/fa-solid-900.ttf</file>
<file>fonts/FontAwesome/fontawesome-webfont.ttf</file>
<file>fonts/FontAwesome/FontAwesome.qml</file>
<file>fonts/FontAwesome/Object.qml</file>
<file>fonts/FontAwesome/qmldir</file>
@@ -234,6 +238,7 @@
<file>images/middlePanelShadow.png</file>
<file>images/themes/white/titlebarLogo@2x.png</file>
<file>images/themes/white/titlebarLogo.png</file>
<file>images/sidebar.svg</file>
<file>images/fullscreen.svg</file>
<file>images/close.svg</file>
<file>images/minimize.svg</file>
@@ -241,12 +246,12 @@
<file>images/themes/white/fullscreen.svg</file>
<file>images/themes/white/minimize.svg</file>
<file>images/themes/white/question.svg</file>
<file>images/themes/white/expand.svg</file>
<file>components/effects/ColorTransition.qml</file>
<file>components/effects/GradientBackground.qml</file>
<file>images/check-white.svg</file>
<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

@@ -43,7 +43,7 @@
#include <QMap>
namespace {
static const int DAEMON_START_TIMEOUT_SECONDS = 120;
static const int DAEMON_START_TIMEOUT_SECONDS = 30;
}
DaemonManager * DaemonManager::m_instance = nullptr;
@@ -61,7 +61,7 @@ DaemonManager *DaemonManager::instance(const QStringList *args)
return m_instance;
}
bool DaemonManager::start(const QString &flags, NetworkType::Type nettype, const QString &dataDir, const QString &bootstrapNodeAddress, bool noSync /* = false*/)
bool DaemonManager::start(const QString &flags, NetworkType::Type nettype, const QString &dataDir, const QString &bootstrapNodeAddress)
{
// prepare command line arguments and pass to monerod
QStringList arguments;
@@ -99,10 +99,6 @@ bool DaemonManager::start(const QString &flags, NetworkType::Type nettype, const
arguments << "--bootstrap-daemon-address" << bootstrapNodeAddress;
}
if (noSync) {
arguments << "--no-sync";
}
arguments << "--check-updates" << "disabled";
// --max-concurrency based on threads available. max: 6
@@ -135,13 +131,11 @@ bool DaemonManager::start(const QString &flags, NetworkType::Type nettype, const
}
// Start start watcher
m_scheduler.run([this, nettype, noSync] {
if (startWatcher(nettype)) {
m_scheduler.run([this, nettype] {
if (startWatcher(nettype))
emit daemonStarted();
m_noSync = noSync;
} else {
else
emit daemonStartFailure();
}
});
return true;
@@ -150,7 +144,7 @@ bool DaemonManager::start(const QString &flags, NetworkType::Type nettype, const
bool DaemonManager::stop(NetworkType::Type nettype)
{
QString message;
sendCommand({"exit"}, nettype, message);
sendCommand("exit", nettype, message);
qDebug() << message;
// Start stop watcher - Will kill if not shutting down
@@ -240,27 +234,26 @@ void DaemonManager::printError()
bool DaemonManager::running(NetworkType::Type nettype) const
{
QString status;
sendCommand({"sync_info"}, nettype, status);
sendCommand("status", nettype, status);
qDebug() << status;
return status.contains("Height:");
// `./monerod status` returns BUSY when syncing.
// Treat busy as connected, until fixed upstream.
if (status.contains("Height:") || status.contains("BUSY") ) {
return true;
}
return false;
}
bool DaemonManager::noSync() const noexcept
bool DaemonManager::sendCommand(const QString &cmd, NetworkType::Type nettype) const
{
return m_noSync;
QString message;
return sendCommand(cmd, nettype, message);
}
void DaemonManager::runningAsync(NetworkType::Type nettype, const QJSValue& callback) const
{
m_scheduler.run([this, nettype] {
return QJSValueList({running(nettype)});
}, callback);
}
bool DaemonManager::sendCommand(const QStringList &cmd, NetworkType::Type nettype, QString &message) const
bool DaemonManager::sendCommand(const QString &cmd, NetworkType::Type nettype, QString &message) const
{
QProcess p;
QStringList external_cmd(cmd);
QStringList external_cmd;
external_cmd << cmd;
// Add network type flag if needed
if (nettype == NetworkType::TESTNET)
@@ -279,14 +272,6 @@ bool DaemonManager::sendCommand(const QStringList &cmd, NetworkType::Type nettyp
return started;
}
void DaemonManager::sendCommandAsync(const QStringList &cmd, NetworkType::Type nettype, const QJSValue& callback) const
{
m_scheduler.run([this, cmd, nettype] {
QString message;
return QJSValueList({sendCommand(cmd, nettype, message)});
}, callback);
}
void DaemonManager::exit()
{
qDebug("DaemonManager: exit()");

View File

@@ -44,21 +44,19 @@ public:
static DaemonManager * instance(const QStringList *args);
Q_INVOKABLE bool start(const QString &flags, NetworkType::Type nettype, const QString &dataDir = "", const QString &bootstrapNodeAddress = "", bool noSync = false);
Q_INVOKABLE bool start(const QString &flags, NetworkType::Type nettype, const QString &dataDir = "", const QString &bootstrapNodeAddress = "");
Q_INVOKABLE bool stop(NetworkType::Type nettype);
Q_INVOKABLE bool noSync() const noexcept;
// return true if daemon process is started
Q_INVOKABLE void runningAsync(NetworkType::Type nettype, const QJSValue& callback) const;
Q_INVOKABLE bool running(NetworkType::Type nettype) const;
// Send daemon command from qml and prints output in console window.
Q_INVOKABLE void sendCommandAsync(const QStringList &cmd, NetworkType::Type nettype, const QJSValue& callback) const;
Q_INVOKABLE bool sendCommand(const QString &cmd, NetworkType::Type nettype) const;
Q_INVOKABLE void exit();
Q_INVOKABLE QVariantMap validateDataDir(const QString &dataDir) const;
private:
bool running(NetworkType::Type nettype) const;
bool sendCommand(const QStringList &cmd, NetworkType::Type nettype, QString &message) const;
bool sendCommand(const QString &cmd, NetworkType::Type nettype, QString &message) const;
bool startWatcher(NetworkType::Type nettype) const;
bool stopWatcher(NetworkType::Type nettype) const;
signals:
@@ -83,9 +81,8 @@ private:
QString m_monerod;
bool m_has_daemon = true;
bool m_app_exit = false;
bool m_noSync = false;
mutable FutureScheduler m_scheduler;
FutureScheduler m_scheduler;
};
#endif // DAEMONMANAGER_H

View File

@@ -32,13 +32,10 @@
#include <QFile>
#include <QDebug>
#include <QReadLocker>
#include <QWriteLocker>
TransactionInfo *TransactionHistory::transaction(int index)
{
QReadLocker locker(&m_tinfoLock);
if (index < 0 || index >= m_tinfo.size()) {
qCritical("%s: no transaction info for index %d", __FUNCTION__, index);
@@ -56,48 +53,41 @@ TransactionInfo *TransactionHistory::transaction(int index)
QList<TransactionInfo *> TransactionHistory::getAll(quint32 accountIndex) const
{
// XXX this invalidates previously saved history that might be used by model
emit refreshStarted();
qDeleteAll(m_tinfo);
m_tinfo.clear();
QDateTime firstDateTime = QDateTime(QDate(2014, 4, 18)); // the genesis block
QDateTime lastDateTime = QDateTime::currentDateTime().addDays(1); // tomorrow (guard against jitter and timezones)
emit refreshStarted();
{
QWriteLocker locker(&m_tinfoLock);
// XXX this invalidates previously saved history that might be used by model
qDeleteAll(m_tinfo);
m_tinfo.clear();
quint64 lastTxHeight = 0;
m_locked = false;
m_minutesToUnlock = 0;
TransactionHistory * parent = const_cast<TransactionHistory*>(this);
for (const auto i : m_pimpl->getAll()) {
TransactionInfo * ti = new TransactionInfo(i, parent);
if (ti->subaddrAccount() != accountIndex) {
delete ti;
continue;
}
m_tinfo.append(ti);
// looking for transactions timestamp scope
if (ti->timestamp() >= lastDateTime) {
lastDateTime = ti->timestamp();
}
if (ti->timestamp() <= firstDateTime) {
firstDateTime = ti->timestamp();
}
quint64 requiredConfirmations = (ti->blockHeight() < ti->unlockTime()) ? ti->unlockTime() - ti->blockHeight() : 10;
// store last tx height
if (ti->confirmations() < requiredConfirmations && ti->blockHeight() >= lastTxHeight) {
lastTxHeight = ti->blockHeight();
// TODO: Fetch block time and confirmations needed from wallet2?
m_minutesToUnlock = (requiredConfirmations - ti->confirmations()) * 2;
m_locked = true;
}
quint64 lastTxHeight = 0;
m_locked = false;
m_minutesToUnlock = 0;
TransactionHistory * parent = const_cast<TransactionHistory*>(this);
for (const auto i : m_pimpl->getAll()) {
TransactionInfo * ti = new TransactionInfo(i, parent);
if (ti->subaddrAccount() != accountIndex) {
delete ti;
continue;
}
m_tinfo.append(ti);
// looking for transactions timestamp scope
if (ti->timestamp() >= lastDateTime) {
lastDateTime = ti->timestamp();
}
if (ti->timestamp() <= firstDateTime) {
firstDateTime = ti->timestamp();
}
quint64 requiredConfirmations = (ti->blockHeight() < ti->unlockTime()) ? ti->unlockTime() - ti->blockHeight() : 10;
// store last tx height
if (ti->confirmations() < requiredConfirmations && ti->blockHeight() >= lastTxHeight) {
lastTxHeight = ti->blockHeight();
// TODO: Fetch block time and confirmations needed from wallet2?
m_minutesToUnlock = (requiredConfirmations - ti->confirmations()) * 2;
m_locked = true;
}
}
}
emit refreshFinished();
if (m_firstDateTime != firstDateTime) {
@@ -122,8 +112,6 @@ void TransactionHistory::refresh(quint32 accountIndex)
quint64 TransactionHistory::count() const
{
QReadLocker locker(&m_tinfoLock);
return m_tinfo.count();
}

View File

@@ -31,7 +31,6 @@
#include <QObject>
#include <QList>
#include <QReadWriteLock>
#include <QDateTime>
namespace Monero {
@@ -77,7 +76,6 @@ private:
friend class Wallet;
Monero::TransactionHistory * m_pimpl;
mutable QList<TransactionInfo*> m_tinfo;
mutable QReadWriteLock m_tinfoLock;
mutable QDateTime m_firstDateTime;
mutable QDateTime m_lastDateTime;
mutable int m_minutesToUnlock;

View File

@@ -40,7 +40,7 @@ QString UnsignedTransaction::errorString() const
return QString::fromStdString(m_pimpl->errorString());
}
quint64 UnsignedTransaction::amount(size_t index) const
quint64 UnsignedTransaction::amount(int index) const
{
std::vector<uint64_t> arr = m_pimpl->amount();
if(index > arr.size() - 1)
@@ -48,7 +48,7 @@ quint64 UnsignedTransaction::amount(size_t index) const
return arr[index];
}
quint64 UnsignedTransaction::fee(size_t index) const
quint64 UnsignedTransaction::fee(int index) const
{
std::vector<uint64_t> arr = m_pimpl->fee();
if(index > arr.size() - 1)
@@ -56,7 +56,7 @@ quint64 UnsignedTransaction::fee(size_t index) const
return arr[index];
}
quint64 UnsignedTransaction::mixin(size_t index) const
quint64 UnsignedTransaction::mixin(int index) const
{
std::vector<uint64_t> arr = m_pimpl->mixin();
if(index > arr.size() - 1)

View File

@@ -56,9 +56,9 @@ public:
Status status() const;
QString errorString() const;
Q_INVOKABLE quint64 amount(size_t index) const;
Q_INVOKABLE quint64 fee(size_t index) const;
Q_INVOKABLE quint64 mixin(size_t index) const;
Q_INVOKABLE quint64 amount(int index) const;
Q_INVOKABLE quint64 fee(int index) const;
Q_INVOKABLE quint64 mixin(int index) const;
QStringList recipientAddress() const;
QStringList paymentId() const;
quint64 txCount() const;

View File

@@ -55,8 +55,6 @@ namespace {
static const int DAEMON_BLOCKCHAIN_HEIGHT_CACHE_TTL_SECONDS = 5;
static const int DAEMON_BLOCKCHAIN_TARGET_HEIGHT_CACHE_TTL_SECONDS = 30;
static const int WALLET_CONNECTION_STATUS_CACHE_TTL_SECONDS = 5;
static constexpr char ATTRIBUTE_SUBADDRESS_ACCOUNT[] ="gui.subaddress_account";
}
class WalletListenerImpl : public Monero::WalletListener
@@ -208,7 +206,7 @@ bool Wallet::store(const QString &path)
return m_walletImpl->store(path.toStdString());
}
bool Wallet::init(const QString &daemonAddress, bool trustedDaemon, quint64 upperTransactionLimit, bool isRecovering, bool isRecoveringFromDevice, quint64 restoreHeight)
bool Wallet::init(const QString &daemonAddress, quint64 upperTransactionLimit, bool isRecovering, bool isRecoveringFromDevice, quint64 restoreHeight)
{
qDebug() << "init non async";
if (isRecovering){
@@ -223,7 +221,6 @@ bool Wallet::init(const QString &daemonAddress, bool trustedDaemon, quint64 uppe
m_walletImpl->setRefreshFromBlockHeight(restoreHeight);
}
m_walletImpl->init(daemonAddress.toStdString(), upperTransactionLimit, m_daemonUsername.toStdString(), m_daemonPassword.toStdString());
setTrustedDaemon(trustedDaemon);
return true;
}
@@ -234,7 +231,7 @@ void Wallet::setDaemonLogin(const QString &daemonUsername, const QString &daemon
m_daemonPassword = daemonPassword;
}
void Wallet::initAsync(const QString &daemonAddress, bool trustedDaemon, quint64 upperTransactionLimit, bool isRecovering, bool isRecoveringFromDevice, quint64 restoreHeight)
void Wallet::initAsync(const QString &daemonAddress, quint64 upperTransactionLimit, bool isRecovering, bool isRecoveringFromDevice, quint64 restoreHeight)
{
qDebug() << "initAsync: " + daemonAddress;
// Change status to disconnected if connected
@@ -243,28 +240,19 @@ void Wallet::initAsync(const QString &daemonAddress, bool trustedDaemon, quint64
emit connectionStatusChanged(m_connectionStatus);
}
m_scheduler.run([this, daemonAddress, trustedDaemon, upperTransactionLimit, isRecovering, isRecoveringFromDevice, restoreHeight] {
bool success = init(daemonAddress, trustedDaemon, upperTransactionLimit, isRecovering, isRecoveringFromDevice, restoreHeight);
m_scheduler.run([this, daemonAddress, upperTransactionLimit, isRecovering, isRecoveringFromDevice, restoreHeight] {
bool success = init(daemonAddress, upperTransactionLimit, isRecovering, isRecoveringFromDevice, restoreHeight);
if (success)
{
emit walletCreationHeightChanged();
qDebug() << "init async finished - starting refresh";
connected(true);
m_walletImpl->startRefresh();
}
});
}
bool Wallet::isHwBacked() const
{
return m_walletImpl->getDeviceType() != Monero::Wallet::Device_Software;
}
bool Wallet::isLedger() const
{
return m_walletImpl->getDeviceType() == Monero::Wallet::Device_Ledger;
}
//! create a view only wallet
bool Wallet::createViewOnly(const QString &path, const QString &password) const
{
@@ -318,13 +306,8 @@ void Wallet::switchSubaddressAccount(quint32 accountIndex)
if (accountIndex < numSubaddressAccounts())
{
m_currentSubaddressAccount = accountIndex;
if (!setCacheAttribute(ATTRIBUTE_SUBADDRESS_ACCOUNT, QString::number(m_currentSubaddressAccount)))
{
qWarning() << "failed to set " << ATTRIBUTE_SUBADDRESS_ACCOUNT << " cache attribute";
}
m_subaddress->refresh(m_currentSubaddressAccount);
m_history->refresh(m_currentSubaddressAccount);
emit currentSubaddressAccountChanged();
}
}
void Wallet::addSubaddressAccount(const QString& label)
@@ -352,13 +335,6 @@ void Wallet::setSubaddressLabel(quint32 accountIndex, quint32 addressIndex, cons
{
m_walletImpl->setSubaddressLabel(accountIndex, addressIndex, label.toStdString());
}
void Wallet::deviceShowAddressAsync(quint32 accountIndex, quint32 addressIndex, const QString &paymentId)
{
m_scheduler.run([this, accountIndex, addressIndex, paymentId] {
m_walletImpl->deviceShowAddress(accountIndex, addressIndex, paymentId.toStdString());
emit deviceShowAddressShowed();
});
}
void Wallet::refreshHeightAsync()
{
@@ -548,8 +524,7 @@ bool Wallet::submitTxFile(const QString &fileName) const
void Wallet::commitTransactionAsync(PendingTransaction *t)
{
m_scheduler.run([this, t] {
auto txIdList = t->txid(); // retrieve before commit
emit transactionCommitted(t->commit(), t, txIdList);
emit transactionCommitted(t->commit(), t, t->txid());
});
}
@@ -647,15 +622,6 @@ void Wallet::setPaymentId(const QString &paymentId)
m_paymentId = paymentId;
}
QString Wallet::getCacheAttribute(const QString &key) const {
return QString::fromStdString(m_walletImpl->getCacheAttribute(key.toStdString()));
}
bool Wallet::setCacheAttribute(const QString &key, const QString &val)
{
return m_walletImpl->setCacheAttribute(key.toStdString(), val.toStdString());
}
bool Wallet::setUserNote(const QString &txid, const QString &note)
{
return m_walletImpl->setUserNote(txid.toStdString(), note.toStdString());
@@ -970,16 +936,16 @@ Wallet::Wallet(Monero::Wallet *w, QObject *parent)
, m_historyModel(nullptr)
, m_addressBook(nullptr)
, m_addressBookModel(nullptr)
, m_subaddress(nullptr)
, m_subaddressModel(nullptr)
, m_subaddressAccount(nullptr)
, m_subaddressAccountModel(nullptr)
, m_daemonBlockChainHeight(0)
, m_daemonBlockChainHeightTtl(DAEMON_BLOCKCHAIN_HEIGHT_CACHE_TTL_SECONDS)
, m_daemonBlockChainTargetHeight(0)
, m_daemonBlockChainTargetHeightTtl(DAEMON_BLOCKCHAIN_TARGET_HEIGHT_CACHE_TTL_SECONDS)
, m_connectionStatusTtl(WALLET_CONNECTION_STATUS_CACHE_TTL_SECONDS)
, m_currentSubaddressAccount(0)
, m_subaddress(nullptr)
, m_subaddressModel(nullptr)
, m_subaddressAccount(nullptr)
, m_subaddressAccountModel(nullptr)
, m_scheduler(this)
{
m_history = new TransactionHistory(m_walletImpl->history(), this);
@@ -989,7 +955,6 @@ Wallet::Wallet(Monero::Wallet *w, QObject *parent)
m_walletListener = new WalletListenerImpl(this);
m_walletImpl->setListener(m_walletListener);
m_connectionStatus = Wallet::ConnectionStatus_Disconnected;
m_currentSubaddressAccount = getCacheAttribute(ATTRIBUTE_SUBADDRESS_ACCOUNT).toUInt();
// start cache timers
m_connectionStatusTime.restart();
m_daemonBlockChainHeightTime.restart();

Some files were not shown because too many files have changed in this diff Show More