Compare commits

...

87 Commits

Author SHA1 Message Date
luigi1111
f03ea0461c Merge pull request #2560
6ce9a3c History: fix translations (xiphon)
2019-12-05 09:35:52 -06:00
xiphon
6ce9a3cba0 History: fix translations 2019-12-05 15:18:15 +00:00
luigi1111
8cd32987d4 Revert "Merge pull request #2526"
This reverts commit 457b1dee49, reversing
changes made to 7cca39ad48.
2019-12-05 09:03:56 -06:00
luigi1111
648b775a25 Merge pull request #2559
e81a589 Transfer: improve amount sanitization (xiphon)
2019-12-05 08:53:47 -06:00
luigi1111
b24ccc2fe3 Merge pull request #2558
074d8fb WizardLang: fix display text (selsta)
2019-12-05 08:52:57 -06:00
luigi1111
00783e7b68 Merge pull request #2557
b632d07 WizardRestoreWallet1: fix placeholder text visibility (selsta)
2019-12-05 08:52:11 -06:00
luigi1111
dafc47050a Merge pull request #2556
1c2920a WizardAskPassword: fix lock icon (selsta)
2019-12-05 08:51:05 -06:00
luigi1111
0e65d89172 Merge pull request #2555
676b8d6 History: add date, amount, integrated addr (incoming) to tx details (xiphon)
2019-12-05 08:50:15 -06:00
luigi1111
fd9e7d00ed Merge pull request #2553
9d5eb00 TransactionHistory: guard tx info list against concurrent access (xiphon)
2019-12-05 08:49:14 -06:00
luigi1111
3d7ded209a Merge pull request #2540
983a3ba Translation: fix untranslated strings (selsta)
2019-12-05 08:47:54 -06:00
xiphon
e81a589a8d Transfer: improve amount sanitization 2019-12-05 10:13:29 +00:00
selsta
074d8fb42e WizardLang: fix display text 2019-12-04 23:18:44 +01:00
selsta
b632d078e5 WizardRestoreWallet1: fix placeholder text visibility 2019-12-04 23:05:42 +01:00
selsta
1c2920a339 WizardAskPassword: fix lock icon 2019-12-04 22:24:08 +01:00
xiphon
676b8d6921 History: add date, amount, integrated addr (incoming) to tx details 2019-12-04 21:07:10 +00:00
xiphon
9d5eb002ae TransactionHistory: guard tx info list against concurrent access 2019-12-04 10:33:54 +00:00
luigi1111
63d4ba6df8 Merge pull request #2551
646d339 Wallet: persistent subaddress account selection (xiphon)
2019-12-03 22:32:58 -06:00
luigi1111
c2dbda63c6 Merge pull request #2543
bc40942 StandardDropdown: implement automatic closing (xiphon)
2019-12-03 22:32:10 -06:00
luigi1111
6e7b4ff9f9 Merge pull request #2542
32f7666 DatePicker: don't propagate mouse events to underlying controls (xiphon)
2019-12-03 22:31:20 -06:00
luigi1111
1269f0a13a Merge pull request #2532
265afe1 DaemonManager: increase daemon start timeout to 120 seconds (xiphon)
2019-12-03 22:30:22 -06:00
luigi1111
04b91e76f2 Merge pull request #2529
4cc3d3f Label: change cursor on link hover (selsta)
2019-12-03 22:29:14 -06:00
luigi1111
c9c7bb9171 Merge pull request #2528
2ab3d8e MiddlePanel: remove margin bottom (selsta)
2019-12-03 22:27:37 -06:00
luigi1111
619661a61d Merge pull request #2527
c06cb5c MiddlePanel: remove color stripe for consistency (selsta)
2019-12-03 22:26:51 -06:00
luigi1111
457b1dee49 Merge pull request #2526
20a5814 Transfer: add parenthesis to links (selsta)
2019-12-03 22:26:00 -06:00
luigi1111
7cca39ad48 Merge pull request #2520
7b0cd19 wizard: Language button on home and add back button (selsta)
2019-12-03 22:24:06 -06:00
luigi1111
90406dfd1e Merge pull request #2517
9e4bfb1 WarningBox: hover cursor and disable selecting text (selsta)
2019-12-03 22:22:45 -06:00
luigi1111
6d7abaf5c0 Merge pull request #2515
c0fa4f5 SettingsLayout: pointing mouse cursor and selecting text (selsta)
2019-12-03 22:21:51 -06:00
xiphon
bc40942889 StandardDropdown: implement automatic closing 2019-12-03 22:45:15 +00:00
xiphon
646d3394d3 Wallet: persistent subaddress account selection 2019-12-03 12:39:34 +00:00
selsta
c06cb5cc58 MiddlePanel: remove color stripe for consistency 2019-12-02 23:19:31 +01:00
selsta
983a3ba7ad Translation: fix untranslated strings 2019-12-02 00:09:43 +01:00
xiphon
265afe1610 DaemonManager: increase daemon start timeout to 120 seconds 2019-11-29 17:24:40 +00:00
xiphon
32f7666912 DatePicker: don't propagate mouse events to underlying controls 2019-11-29 17:22:00 +00:00
selsta
20a58143b6 Transfer: add parenthesis to links 2019-11-28 12:25:33 +01:00
selsta
4cc3d3f3e2 Label: change cursor on link hover 2019-11-28 00:59:44 +01:00
selsta
2ab3d8ebf2 MiddlePanel: remove margin bottom 2019-11-28 00:55:00 +01:00
selsta
9e4bfb1ef2 WarningBox: hover cursor and disable selecting text 2019-11-28 00:08:59 +01:00
selsta
7b0cd19487 wizard: Language button on home and add back button 2019-11-27 19:20:58 +01:00
selsta
c0fa4f5d27 SettingsLayout: pointing mouse cursor and selecting text 2019-11-27 18:49:18 +01:00
luigi1111
d5f4d5d93f Merge pull request #2506
f47335f Wizard, AddressBook, SettingsNode: prevent undesired text selection (xiphon)
2019-11-27 10:26:03 -06:00
luigi1111
9ba1960207 Merge pull request #2504
f75aa22 main: omit onWalletRefresh call with uninitialized currentWallet (xiphon)
2019-11-27 10:24:54 -06:00
luigi1111
04a665db0c Merge pull request #2449
4a52681 workflows: check if QML loads successfully (selsta)
2019-11-27 10:23:45 -06:00
xiphon
f47335f89f Wizard, AddressBook, SettingsNode: prevent undesired text selection 2019-11-27 12:33:30 +00:00
xiphon
f75aa22b26 main: omit onWalletRefresh call with uninitialized currentWallet 2019-11-27 09:14:35 +00:00
luigi1111
50e1ce1460 Merge pull request #2502
bd20626 Installer: fix 'GUI Wallet Guide' shortcut target filename (xiphon)
2019-11-26 15:18:25 -06:00
luigi1111
df02532fd5 Merge pull request #2500
8738210 PasswordDialog: fix text field height changing on input (Windows) (xiphon)
2019-11-26 15:17:38 -06:00
xiphon
bd20626460 Installer: fix 'GUI Wallet Guide' shortcut target filename 2019-11-26 16:25:24 +00:00
xiphon
8738210991 PasswordDialog: fix text field height changing on input (Windows) 2019-11-26 16:09:09 +00:00
luigi1111
6c2c17ada1 Merge pull request #2489
0daf2aa CheckBox: use Font Awesome plus/minus icons, remove unused images (xiphon)
2019-11-25 12:57:28 -06:00
luigi1111
380f218b3a Merge pull request #2494
56023fa build: MacOS openssl path provided by brew, fallback to default (xiphon)
2019-11-25 12:49:05 -06:00
luigi1111
12647fac73 Merge pull request #2491
1dc45ba Input: fix cursor shape, should be 'Qt.IBeamCursor' (xiphon)
2019-11-25 12:47:26 -06:00
luigi1111
9f0f40af80 Merge pull request #2486
06ccded Transfer: fix NaN fiat conversion (selsta)
2019-11-25 12:46:09 -06:00
luigi1111
c316fab29f Merge pull request #2485
ff38e96 build: set BUILD_TAG to fix update notification (selsta)
2019-11-25 12:45:22 -06:00
luigi1111
37de27d7f6 Merge pull request #2477
a9a59fd main: ask whether to stop local node upon switching to remote node (xiphon)
2019-11-25 12:44:28 -06:00
luigi1111
c61d857a67 Merge pull request #2464
e2a187f AppWindow: append wallet name to window title (xiphon)
2019-11-25 12:43:31 -06:00
xiphon
56023facaa build: MacOS openssl path provided by brew, fallback to default 2019-11-25 14:46:18 +00:00
xiphon
1dc45bad87 Input: fix cursor shape, should be 'Qt.IBeamCursor' 2019-11-25 07:56:30 +00:00
xiphon
0daf2aacf5 CheckBox: use Font Awesome plus/minus icons, remove unused images 2019-11-25 06:37:21 +00:00
selsta
06ccded94e Transfer: fix NaN fiat conversion 2019-11-25 00:57:59 +01:00
selsta
ff38e965bd build: set BUILD_TAG to fix update notification 2019-11-25 00:27:29 +01:00
xiphon
a9a59fd314 main: ask whether to stop local node upon switching to remote node 2019-11-24 10:19:40 +00:00
xiphon
e2a187f892 AppWindow: append wallet name to window title 2019-11-24 08:49:59 +00:00
selsta
4a526810ce workflows: check if QML loads successfully 2019-11-20 15:32:42 +01:00
luigi1111
2f5c47e95f Merge pull request #2448
d2b9d56 ContextMenu: styling, implement ContextMenuItem component (xiphon)
2019-11-19 10:36:34 -06:00
luigi1111
34b216e6dc Merge pull request #2444
5a65d28 build: set submodule to v0.15.0.1 (selsta)
2019-11-19 10:35:25 -06:00
xiphon
d2b9d5690b ContextMenu: styling, implement ContextMenuItem component 2019-11-19 12:32:53 +00:00
luigi1111
d10f1b5d30 Merge pull request #2447
d92cc94 readme: add 'zeromq-devel' to Fedora deps (xiphon)
2019-11-18 13:00:54 -06:00
luigi1111
fea3bb503f Merge pull request #2446
f57b2d5 workflows: add basic ubuntu/macOS build script (selsta)
2019-11-18 12:58:46 -06:00
xiphon
d92cc944cb readme: add 'zeromq-devel' to Fedora deps 2019-11-17 19:32:13 +00:00
selsta
f57b2d57cd workflows: add basic ubuntu/macOS build script 2019-11-14 22:12:38 +01:00
luigi1111
cf0e5a811e Merge pull request #2440
e9cdaf4 Transfer: convert and display entered amount in fiat currency (xiphon)
2019-11-13 09:08:16 -06:00
luigi1111
ea8f51d168 Merge pull request #2439
17f032e fiat: fix invalid type, don't round conversion rate to whole number (xiphon)
2019-11-13 09:06:51 -06:00
luigi1111
e8befc4c67 Merge pull request #2438
92f9bec installer: automatically set app version information (xiphon)
2019-11-13 09:05:55 -06:00
luigi1111
5518771a8b Merge pull request #2437
ef565e5 build: embed version metadata into binary (xiphon)
2019-11-13 09:04:49 -06:00
luigi1111
47bc0f2a3c Merge pull request #2435
0e3f3c1 SettingsWallet: refactor list items into separate component (xiphon)
2019-11-13 09:03:51 -06:00
luigi1111
8bd820b909 Merge pull request #2429
74e12ce ContextMenu: implement 'paste' context menu for all text fields (xiphon)
2019-11-13 09:03:02 -06:00
luigi1111
f948d0e214 Merge pull request #2428
5fe6b48 Settings: fix 'Light theme' checkbox (xiphon)
2019-11-13 09:02:03 -06:00
luigi1111
3a7c9e6c8e Merge pull request #2417
212c8dd Warning added that balance reflects only incoming transactions for view-only wallets (peli-pro)
2019-11-13 09:00:44 -06:00
selsta
5a65d28d29 build: set submodule to v0.15.0.1 2019-11-13 15:45:42 +01:00
xiphon
e9cdaf4dbe Transfer: convert and display entered amount in fiat currency 2019-11-13 08:10:49 +00:00
xiphon
17f032ea11 fiat: fix invalid type, don't round conversion rate to whole number 2019-11-13 06:34:33 +00:00
xiphon
ef565e5fa3 build: embed version metadata into binary 2019-11-12 16:23:02 +00:00
xiphon
92f9bec1e7 installer: automatically set app version information 2019-11-12 02:25:29 +00:00
xiphon
0e3f3c13a1 SettingsWallet: refactor list items into separate component 2019-11-11 21:14:39 +00:00
xiphon
74e12ce71d ContextMenu: implement 'paste' context menu for all text fields 2019-11-08 12:41:32 +00:00
xiphon
5fe6b48517 Settings: fix 'Light theme' checkbox 2019-11-04 21:47:38 +00:00
peli-pro
212c8dd054 Warning added that balance reflects only incoming transactions for view-only wallets 2019-10-17 14:25:36 +02:00
56 changed files with 884 additions and 885 deletions

34
.github/workflows/build.yml vendored Normal file
View File

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

View File

@@ -40,8 +40,8 @@ import "components/effects/" as MoneroEffects
Rectangle { Rectangle {
id: panel id: panel
property int currentAccountIndex: 0 property int currentAccountIndex
property string currentAccountLabel: "Primary account" property alias currentAccountLabel: accountLabel.text
property string balanceString: "?.??" property string balanceString: "?.??"
property string balanceUnlockedString: "?.??" property string balanceUnlockedString: "?.??"
property string balanceFiatString: "?.??" property string balanceFiatString: "?.??"
@@ -184,7 +184,7 @@ Rectangle {
MoneroComponents.Label { MoneroComponents.Label {
fontSize: 12 fontSize: 12
id: accountIndex id: accountIndex
text: qsTr("Account") + " #" + currentAccountIndex text: qsTr("Account") + translationManager.emptyString + " #" + currentAccountIndex
color: MoneroComponents.Style.blackTheme ? "white" : "black" color: MoneroComponents.Style.blackTheme ? "white" : "black"
anchors.left: parent.left anchors.left: parent.left
anchors.leftMargin: 60 anchors.leftMargin: 60
@@ -204,7 +204,6 @@ Rectangle {
fontSize: 16 fontSize: 16
id: accountLabel id: accountLabel
textWidth: 170 textWidth: 170
text: currentAccountLabel
color: MoneroComponents.Style.blackTheme ? "white" : "black" color: MoneroComponents.Style.blackTheme ? "white" : "black"
anchors.left: parent.left anchors.left: parent.left
anchors.leftMargin: 60 anchors.leftMargin: 60
@@ -238,7 +237,7 @@ Rectangle {
font.pixelSize: 16 font.pixelSize: 16
text: { text: {
if (persistentSettings.fiatPriceEnabled && persistentSettings.fiatPriceToggle) { if (persistentSettings.fiatPriceEnabled && persistentSettings.fiatPriceToggle) {
return persistentSettings.fiatPriceCurrency == "xmrusd" ? "USD" : "EUR" return appWindow.fiatApiCurrencySymbol();
} else { } else {
return "XMR" return "XMR"
} }

View File

@@ -168,23 +168,6 @@ 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 { ColumnLayout {
anchors.fill: parent anchors.fill: parent
anchors.margins: { anchors.margins: {
@@ -195,6 +178,7 @@ Rectangle {
} }
anchors.topMargin: appWindow.persistentSettings.customDecorations ? 50 : 0 anchors.topMargin: appWindow.persistentSettings.customDecorations ? 50 : 0
anchors.bottomMargin: 0
spacing: 0 spacing: 0
Flickable { Flickable {
@@ -253,7 +237,7 @@ Rectangle {
Rectangle { Rectangle {
id: borderLeft id: borderLeft
visible: middlePanel.state !== "Merchant" visible: middlePanel.state !== "Merchant"
anchors.top: styledRow.bottom anchors.top: parent.top
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.left: parent.left anchors.left: parent.left
width: 1 width: 1

View File

@@ -93,7 +93,7 @@ Packaging for your favorite distribution would be a welcome contribution!
- For Fedora - 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` `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`
2. Install Qt: 2. Install Qt:

View File

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

View File

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

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

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

View File

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

View File

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

View File

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

View File

@@ -69,5 +69,10 @@ Item {
color: fontColor color: fontColor
onLinkActivated: item.linkActivated() onLinkActivated: item.linkActivated()
textFormat: parent.textFormat textFormat: parent.textFormat
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.NoButton
cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor
}
} }
} }

View File

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

View File

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

View File

@@ -187,7 +187,7 @@ Item {
text: qsTr("CAPSLOCKS IS ON.") + translationManager.emptyString; text: qsTr("CAPSLOCKS IS ON.") + translationManager.emptyString;
} }
TextField { MoneroComponents.Input {
id: passwordInput1 id: passwordInput1
Layout.topMargin: 6 Layout.topMargin: 6
Layout.fillWidth: true Layout.fillWidth: true
@@ -203,6 +203,7 @@ Item {
return passwordInput2 return passwordInput2
} }
} }
implicitHeight: 50
bottomPadding: 10 bottomPadding: 10
leftPadding: 10 leftPadding: 10
topPadding: 10 topPadding: 10
@@ -296,7 +297,7 @@ Item {
color: MoneroComponents.Style.defaultFontColor color: MoneroComponents.Style.defaultFontColor
} }
TextField { MoneroComponents.Input {
id: passwordInput2 id: passwordInput2
visible: !passwordDialogMode visible: !passwordDialogMode
Layout.topMargin: 6 Layout.topMargin: 6
@@ -307,6 +308,7 @@ Item {
font.pixelSize: 24 font.pixelSize: 24
echoMode: TextInput.Password echoMode: TextInput.Password
KeyNavigation.tab: okButton KeyNavigation.tab: okButton
implicitHeight: 50
bottomPadding: 10 bottomPadding: 10
leftPadding: 10 leftPadding: 10
topPadding: 10 topPadding: 10

View File

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

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

View File

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

View File

@@ -39,7 +39,6 @@ Item {
id: root id: root
property string image: "" property string image: ""
property string color: "" property string color: ""
property bool fontAwesomeFallbackEnabled: true
property var fontAwesomeFallbackIcon: "" property var fontAwesomeFallbackIcon: ""
property string fontAwesomeFallbackFont: FontAwesome.fontFamilySolid property string fontAwesomeFallbackFont: FontAwesome.fontFamilySolid
property string fontAwesomeFallbackStyle: "Solid" property string fontAwesomeFallbackStyle: "Solid"
@@ -69,13 +68,13 @@ Item {
anchors.fill: root anchors.fill: root
source: svgMask source: svgMask
color: root.color color: root.color
visible: isOpenGL visible: image && isOpenGL
} }
Text { Text {
id: fontAwesomeFallback id: fontAwesomeFallback
visible: !isOpenGL && root.fontAwesomeFallback visible: !imgMockColor.visible
text: !isOpenGL ? root.fontAwesomeFallbackIcon : "" text: root.fontAwesomeFallbackIcon
font.family: root.fontAwesomeFallbackFont font.family: root.fontAwesomeFallbackFont
font.pixelSize: root.fontAwesomeFallbackSize font.pixelSize: root.fontAwesomeFallbackSize
font.styleName: root.fontAwesomeFallbackStyle font.styleName: root.fontAwesomeFallbackStyle

View File

@@ -17,7 +17,7 @@ if [ ! -d $MONERO_DIR/src ]; then
fi fi
git submodule update --remote git submodule update --remote
git -C $MONERO_DIR fetch git -C $MONERO_DIR fetch
git -C $MONERO_DIR checkout v0.15.0.0 git -C $MONERO_DIR checkout v0.15.0.1
# get monero core tag # get monero core tag
pushd $MONERO_DIR pushd $MONERO_DIR
@@ -144,9 +144,9 @@ make_exec="make"
if [ "$platform" == "darwin" ]; then if [ "$platform" == "darwin" ]; then
echo "Configuring build for MacOS.." echo "Configuring build for MacOS.."
if [ "$STATIC" == true ]; then 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_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_TAG="mac-x64" -D BUILD_GUI_DEPS=ON -D INSTALL_VENDORED_LIBUNBOUND=ON $BUILD_TREZOR_FLAGS -D CMAKE_INSTALL_PREFIX="$MONERO_DIR" ../..
else else
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" ../.. 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" ../..
fi fi
## LINUX 64 ## LINUX 64
@@ -156,9 +156,9 @@ elif [ "$platform" == "linux64" ]; then
echo "Configuring build for Android on Linux host" 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" ../.. 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 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_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_TAG="linux-x64" -D BUILD_GUI_DEPS=ON -D INSTALL_VENDORED_LIBUNBOUND=ON $BUILD_TREZOR_FLAGS -D CMAKE_INSTALL_PREFIX="$MONERO_DIR" ../..
else else
cmake -D CMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE -D BUILD_GUI_DEPS=ON $BUILD_TREZOR_FLAGS -D CMAKE_INSTALL_PREFIX="$MONERO_DIR" ../.. 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" ../..
fi fi
## LINUX 32 ## LINUX 32
@@ -194,7 +194,7 @@ elif [ "$platform" == "mingw64" ]; then
# Do something under Windows NT platform # Do something under Windows NT platform
echo "Configuring build for MINGW64.." echo "Configuring build for MINGW64.."
BOOST_ROOT=/mingw64/boost 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_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_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 ../..
## Windows 32 ## Windows 32
elif [ "$platform" == "mingw32" ]; then elif [ "$platform" == "mingw32" ]; then

Binary file not shown.

Before

Width:  |  Height:  |  Size: 170 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 170 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 399 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 760 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 193 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 195 B

View File

@@ -1,6 +1,7 @@
; Monero Carbon Chamaeleon GUI Wallet Installer for Windows ; Monero Carbon Chamaeleon GUI Wallet Installer for Windows
; Copyright (c) 2017-2019, The Monero Project ; Copyright (c) 2017-2019, The Monero Project
; See LICENSE ; See LICENSE
#define GuiVersion GetFileVersion("bin\monero-wallet-gui.exe")
[Setup] [Setup]
AppName=Monero GUI Wallet AppName=Monero GUI Wallet
@@ -8,7 +9,8 @@ AppName=Monero GUI Wallet
; Thus it's important to keep this stable over releases ; 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 ; With a different "AppName" InnoSetup would treat a mere update as a completely new application and thus mess up
AppVersion=0.15.0.0 AppVersion={#GuiVersion}
VersionInfoVersion={#GuiVersion}
DefaultDirName={pf}\Monero GUI Wallet DefaultDirName={pf}\Monero GUI Wallet
DefaultGroupName=Monero GUI Wallet DefaultGroupName=Monero GUI Wallet
UninstallDisplayIcon={app}\monero-wallet-gui.exe UninstallDisplayIcon={app}\monero-wallet-gui.exe
@@ -39,6 +41,8 @@ UsedUserAreasWarning=no
; play a role in only in few cases as the first standard user in a Windows installation does have admin rights. ; 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. ; So, for the time being, this installer simply disregards this problem.
[Messages]
SetupWindowTitle=%1 {#GuiVersion} Installer
[Languages] [Languages]
Name: "en"; MessagesFile: "compiler:Default.isl" Name: "en"; MessagesFile: "compiler:Default.isl"
@@ -65,7 +69,7 @@ Name: "en"; MessagesFile: "compiler:Default.isl"
; Note that it would be very dangerous to use "ignoreversion" on files that may be shared with other ; 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. ; applications somehow. Luckily this is no issue here because ALL files are "private" to Monero.
Source: "ReadMe.htm"; DestDir: "{app}"; Flags: ignoreversion Source: {#file AddBackslash(SourcePath) + "ReadMe.htm"}; DestDir: "{app}"; DestName: "ReadMe.htm"; Flags: ignoreversion
Source: "FinishImage.bmp"; Flags: dontcopy Source: "FinishImage.bmp"; Flags: dontcopy
; Monero GUI wallet exe and guide ; Monero GUI wallet exe and guide
@@ -313,7 +317,7 @@ end;
; Icons in the "Monero GUI Wallet" program group ; Icons in the "Monero GUI Wallet" program group
; Windows will almost always display icons in alphabetical order, per level, so specify the text accordingly ; 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"; Filename: "{app}\monero-wallet-gui.exe";
Name: "{group}\GUI Wallet Guide"; Filename: "{app}\monero-GUI-guide.pdf"; IconFilename: "{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}\Uninstall GUI Wallet"; Filename: "{uninstallexe}" Name: "{group}\Uninstall GUI Wallet"; Filename: "{uninstallexe}"
; Sub-folder "Utilities"; ; Sub-folder "Utilities";

View File

@@ -6,8 +6,7 @@
<body style="font-family: Arial, Helvetica, sans-serif"> <body style="font-family: Arial, Helvetica, sans-serif">
<h1>Monero Carbon Chamaeleon GUI Wallet</h1> <h1>Monero Carbon Chamaeleon GUI Wallet</h1>
<p>Copyright (c) 2014-2019, The Monero Project<br> <p>Copyright (c) 2014-2019, The Monero Project</p>
Date: November 1, 2019</p>
<h2>Preface</h2> <h2>Preface</h2>
@@ -23,7 +22,7 @@
<h2>Content of the Package</h2> <h2>Content of the Package</h2>
<p>You just installed the <i>Monero GUI wallet</i> for Windows, release Carbon Chamaeleon, version 0.15.0.0. <p>You just installed the <i>Monero GUI wallet</i> for Windows, release Carbon Chamaeleon, version {#GuiVersion}.
The wallet enables you to send and receive Moneroj in a secure and very private way. The wallet enables you to send and receive Moneroj in a secure and very private way.
</p> </p>

View File

@@ -174,7 +174,10 @@ int main(int argc, char *argv[])
QCoreApplication::translate("main", "Log to specified file"), QCoreApplication::translate("main", "Log to specified file"),
QCoreApplication::translate("main", "file")); QCoreApplication::translate("main", "file"));
QCommandLineOption testQmlOption("test-qml");
testQmlOption.setFlags(QCommandLineOption::HiddenFromHelp);
parser.addOption(logPathOption); parser.addOption(logPathOption);
parser.addOption(testQmlOption);
parser.addHelpOption(); parser.addHelpOption();
parser.process(app); parser.process(app);
@@ -405,6 +408,10 @@ int main(int argc, char *argv[])
return 1; return 1;
} }
// QML loaded successfully.
if (parser.isSet(testQmlOption))
return 0;
#ifdef WITH_SCANNER #ifdef WITH_SCANNER
QObject *qmlCamera = rootObject->findChild<QObject*>("qrCameraQML"); QObject *qmlCamera = rootObject->findChild<QObject*>("qrCameraQML");
if (qmlCamera) if (qmlCamera)

122
main.qml
View File

@@ -47,7 +47,7 @@ import "js/Windows.js" as Windows
ApplicationWindow { ApplicationWindow {
id: appWindow id: appWindow
title: "Monero" title: "Monero" + (walletName ? " - " + walletName : "")
property var currentItem property var currentItem
property bool hideBalanceForced: false property bool hideBalanceForced: false
@@ -86,8 +86,8 @@ ApplicationWindow {
property bool themeTransition: false property bool themeTransition: false
// fiat price conversion // fiat price conversion
property int fiatPriceXMRUSD: 0 property real fiatPriceXMRUSD: 0
property int fiatPriceXMREUR: 0 property real fiatPriceXMREUR: 0
property var fiatPriceAPIs: { property var fiatPriceAPIs: {
return { return {
"kraken": { "kraken": {
@@ -112,7 +112,6 @@ ApplicationWindow {
property var current_address property var current_address
property var current_address_label: "Primary" property var current_address_label: "Primary"
property int current_subaddress_table_index: 0 property int current_subaddress_table_index: 0
property int current_subaddress_account_table_index: 0
function altKeyReleased() { ctrlPressed = false; } function altKeyReleased() { ctrlPressed = false; }
@@ -418,8 +417,6 @@ ApplicationWindow {
} }
leftPanel.minutesToUnlock = (balance !== balanceU) ? currentWallet.history.minutesToUnlock : ""; leftPanel.minutesToUnlock = (balance !== balanceU) ? currentWallet.history.minutesToUnlock : "";
leftPanel.currentAccountIndex = currentWallet.currentSubaddressAccount;
leftPanel.currentAccountLabel = currentWallet.getSubaddressLabel(currentWallet.currentSubaddressAccount, 0);
leftPanel.balanceString = balance leftPanel.balanceString = balance
leftPanel.balanceUnlockedString = balanceU leftPanel.balanceUnlockedString = balanceU
} }
@@ -469,14 +466,18 @@ ApplicationWindow {
leftPanel.networkStatus.connected = status leftPanel.networkStatus.connected = status
// update local daemon status. // update local daemon status.
if(walletManager.isDaemonLocal(currentDaemonAddress)) const isDisconnected = status === Wallet.ConnectionStatus_Disconnected;
daemonRunning = status; if (walletManager.isDaemonLocal(currentDaemonAddress)) {
daemonRunning = !isDisconnected;
} else {
daemonRunning = false;
}
// Update fee multiplier dropdown on transfer page // Update fee multiplier dropdown on transfer page
middlePanel.transferView.updatePriorityDropdown(); middlePanel.transferView.updatePriorityDropdown();
// If wallet isnt connected, advanced wallet mode and no daemon is running - Ask // If wallet isnt connected, advanced wallet mode and no daemon is running - Ask
if (appWindow.walletMode >= 2 && walletManager.isDaemonLocal(currentDaemonAddress) && !walletInitialized && status === Wallet.ConnectionStatus_Disconnected) { if (appWindow.walletMode >= 2 && walletManager.isDaemonLocal(currentDaemonAddress) && !walletInitialized && isDisconnected) {
daemonManager.runningAsync(persistentSettings.nettype, function(running) { daemonManager.runningAsync(persistentSettings.nettype, function(running) {
if (!running) { if (!running) {
daemonManagerDialog.open(); daemonManagerDialog.open();
@@ -598,10 +599,19 @@ ApplicationWindow {
function connectRemoteNode() { function connectRemoteNode() {
console.log("connecting remote node"); console.log("connecting remote node");
persistentSettings.useRemoteNode = true;
currentDaemonAddress = persistentSettings.remoteNodeAddress; const callback = function() {
currentWallet.initAsync(currentDaemonAddress, isTrustedDaemon()); persistentSettings.useRemoteNode = true;
walletManager.setDaemonAddressAsync(currentDaemonAddress); currentDaemonAddress = persistentSettings.remoteNodeAddress;
currentWallet.initAsync(currentDaemonAddress, isTrustedDaemon());
walletManager.setDaemonAddressAsync(currentDaemonAddress);
};
if (typeof daemonManager != "undefined" && daemonRunning) {
showDaemonIsRunningDialog(callback);
} else {
callback();
}
} }
function disconnectRemoteNode() { function disconnectRemoteNode() {
@@ -1241,17 +1251,32 @@ ApplicationWindow {
Prices.getJSON(url); Prices.getJSON(url);
} }
function fiatApiUpdateBalance(balance){ function fiatApiCurrencySymbol() {
// update balance card switch (persistentSettings.fiatPriceCurrency) {
case "xmrusd":
return "USD";
case "xmreur":
return "EUR";
default:
console.error("unsupported currency", persistentSettings.fiatPriceCurrency);
return "UNSUPPORTED";
}
}
function fiatApiConvertToFiat(amount) {
var ticker = persistentSettings.fiatPriceCurrency === "xmrusd" ? appWindow.fiatPriceXMRUSD : appWindow.fiatPriceXMREUR; var ticker = persistentSettings.fiatPriceCurrency === "xmrusd" ? appWindow.fiatPriceXMRUSD : appWindow.fiatPriceXMREUR;
if(ticker <= 0){ if(ticker <= 0){
console.log(fiatApiError("Could not update balance card; invalid ticker value")); console.log(fiatApiError("Invalid ticker value: " + ticker));
leftPanel.balanceFiatString = "?.??"; return "?.??";
return;
} }
return (amount * ticker).toFixed(2);
}
function fiatApiUpdateBalance(balance){
// update balance card
var bFiat = "?.??" var bFiat = "?.??"
if (!hideBalanceForced && !persistentSettings.hideBalance) { if (!hideBalanceForced && !persistentSettings.hideBalance) {
bFiat = (balance * ticker).toFixed(2); bFiat = fiatApiConvertToFiat(balance);
} }
leftPanel.balanceFiatString = bFiat; leftPanel.balanceFiatString = bFiat;
} }
@@ -1588,6 +1613,13 @@ ApplicationWindow {
anchors.left: parent.left anchors.left: parent.left
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
visible: rootItem.state == "normal" && middlePanel.state != "Merchant" visible: rootItem.state == "normal" && middlePanel.state != "Merchant"
currentAccountIndex: currentWallet ? currentWallet.currentSubaddressAccount : 0
currentAccountLabel: {
if (currentWallet) {
return currentWallet.getSubaddressLabel(currentWallet.currentSubaddressAccount, 0);
}
return qsTr("Primary account") + translationManager.emptyString;
}
onTransferClicked: { onTransferClicked: {
middlePanel.state = "Transfer"; middlePanel.state = "Transfer";
@@ -1659,6 +1691,7 @@ ApplicationWindow {
MiddlePanel { MiddlePanel {
id: middlePanel id: middlePanel
accountView.currentAccountIndex: currentWallet ? currentWallet.currentSubaddressAccount : 0
anchors.top: parent.top anchors.top: parent.top
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.left: leftPanel.visible ? leftPanel.right : parent.left anchors.left: leftPanel.visible ? leftPanel.right : parent.left
@@ -1901,6 +1934,23 @@ ApplicationWindow {
statusMessage.visible = true statusMessage.visible = true
} }
function showDaemonIsRunningDialog(onClose) {
// Show confirmation dialog
confirmationDialog.title = qsTr("Local node is running") + translationManager.emptyString;
confirmationDialog.text = qsTr("Do you want to stop local node or keep it running in the background?") + translationManager.emptyString;
confirmationDialog.icon = StandardIcon.Question;
confirmationDialog.cancelText = qsTr("Force stop") + translationManager.emptyString;
confirmationDialog.okText = qsTr("Keep it running") + translationManager.emptyString;
confirmationDialog.onAcceptedCallback = function() {
onClose();
}
confirmationDialog.onRejectedCallback = function() {
daemonManager.stop(persistentSettings.nettype);
onClose();
};
confirmationDialog.open();
}
onClosing: { onClosing: {
close.accepted = false; close.accepted = false;
console.log("blocking close event"); console.log("blocking close event");
@@ -1922,27 +1972,12 @@ ApplicationWindow {
// If daemon is running - prompt user before exiting // If daemon is running - prompt user before exiting
if(typeof daemonManager != "undefined" && daemonRunning) { if(typeof daemonManager != "undefined" && daemonRunning) {
// Show confirmation dialog
confirmationDialog.title = qsTr("Daemon is running") + translationManager.emptyString;
confirmationDialog.text = qsTr("Daemon will still be running in background when GUI is closed.");
confirmationDialog.icon = StandardIcon.Question
confirmationDialog.cancelText = qsTr("Stop daemon")
confirmationDialog.onAcceptedCallback = function() {
closeAccepted();
}
confirmationDialog.onRejectedCallback = function() {
daemonManager.stop(persistentSettings.nettype);
closeAccepted();
};
if (appWindow.walletMode == 0) { if (appWindow.walletMode == 0) {
stopDaemon(); stopDaemon();
closeAccepted(); closeAccepted();
} else { } else {
confirmationDialog.open(); showDaemonIsRunningDialog(closeAccepted);
} }
} else { } else {
closeAccepted(); closeAccepted();
} }
@@ -1964,17 +1999,12 @@ ApplicationWindow {
if (parts.length == 4) { if (parts.length == 4) {
var version = parts[0] var version = parts[0]
var hash = parts[1] var hash = parts[1]
//var user_url = parts[2] var user_url = parts[2]
//var auto_url = parts[3]
var osBuildTag = isMac ? "mac-x64" : isWindows ? "win-x64" : isLinux ? "linux-x64" : "unknownBuildTag"
var extension = isMac || isLinux ? ".tar.bz2" : isWindows ? ".zip" : ".unknownExtension"
var base_url = "https://downloads.getmonero.org/gui/monero-gui-"
var download_url = base_url + osBuildTag + "-v" + version + extension
var msg = "" var msg = ""
if (osBuildTag !== "unknownBuildTag") { if (isMac || isWindows || isLinux) {
msg = qsTr("New version of Monero v.%1 is available.<br><br>Download:<br>%2<br><br>SHA256 Hash:<br>%3").arg(version).arg(download_url).arg(hash) + translationManager.emptyString msg = qsTr("New version of Monero v%1 is available.<br><br>Download:<br>%2<br><br>SHA256 Hash:<br>%3").arg(version).arg(user_url).arg(hash) + translationManager.emptyString
} else { } else {
msg = qsTr("New version of Monero is available. Check out getmonero.org") + translationManager.emptyString msg = qsTr("New version of Monero v%1 is available. Check out getmonero.org").arg(version) + translationManager.emptyString
} }
notifier.show(msg) notifier.show(msg)
} else { } else {
@@ -2010,7 +2040,9 @@ ApplicationWindow {
// some fields need an extra nudge when changing languages // some fields need an extra nudge when changing languages
function resetLanguageFields(){ function resetLanguageFields(){
clearMoneroCardLabelText() clearMoneroCardLabelText()
onWalletRefresh() if (currentWallet) {
onWalletRefresh();
}
} }
function userActivity() { function userActivity() {

View File

@@ -370,11 +370,19 @@ macx {
# message("using static libraries") # message("using static libraries")
# LIBS+= -Wl,-Bstatic # 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 QT += macextras
OBJECTIVE_SOURCES += src/qt/macoshelper.mm OBJECTIVE_SOURCES += src/qt/macoshelper.mm
LIBS+= \ LIBS+= \
-L/usr/local/lib \ -L/usr/local/lib \
-L/usr/local/opt/openssl/lib \ -L$$OPENSSL_LIBRARY_DIRS \
-L/usr/local/opt/boost/lib \ -L/usr/local/opt/boost/lib \
-lboost_serialization \ -lboost_serialization \
-lboost_thread-mt \ -lboost_thread-mt \
@@ -504,6 +512,9 @@ DISTFILES += \
notes.txt \ notes.txt \
monero/src/wallet/CMakeLists.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 # windows application icon
RC_ICONS = images/appicon.ico RC_ICONS = images/appicon.ico

View File

@@ -31,6 +31,7 @@ import QtQuick.Controls 2.0
import QtQuick.Controls.Styles 1.4 import QtQuick.Controls.Styles 1.4
import QtQuick.Layouts 1.1 import QtQuick.Layouts 1.1
import QtQuick.Dialogs 1.2 import QtQuick.Dialogs 1.2
import FontAwesome 1.0
import "../components" as MoneroComponents import "../components" as MoneroComponents
import "../components/effects/" as MoneroEffects import "../components/effects/" as MoneroEffects
@@ -48,6 +49,7 @@ Rectangle {
property var model property var model
property alias accountHeight: mainLayout.height property alias accountHeight: mainLayout.height
property bool selectAndSend: false property bool selectAndSend: false
property int currentAccountIndex
function renameSubaddressAccountLabel(_index){ function renameSubaddressAccountLabel(_index){
inputDialog.labelText = qsTr("Set the label of the selected account:") + translationManager.emptyString; inputDialog.labelText = qsTr("Set the label of the selected account:") + translationManager.emptyString;
@@ -179,6 +181,7 @@ Rectangle {
clip: true clip: true
boundsBehavior: ListView.StopAtBounds boundsBehavior: ListView.StopAtBounds
interactive: false interactive: false
currentIndex: currentAccountIndex
delegate: Rectangle { delegate: Rectangle {
id: tableItem2 id: tableItem2
@@ -210,7 +213,7 @@ Rectangle {
MoneroComponents.Label { MoneroComponents.Label {
id: idLabel id: idLabel
color: index === appWindow.current_subaddress_account_table_index ? MoneroComponents.Style.defaultFontColor : "#757575" color: index === currentAccountIndex ? MoneroComponents.Style.defaultFontColor : "#757575"
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left anchors.left: parent.left
anchors.leftMargin: 6 anchors.leftMargin: 6
@@ -277,9 +280,9 @@ Rectangle {
onEntered: tableItem2.color = MoneroComponents.Style.titleBarButtonHoverColor onEntered: tableItem2.color = MoneroComponents.Style.titleBarButtonHoverColor
onExited: tableItem2.color = "transparent" onExited: tableItem2.color = "transparent"
onClicked: { onClicked: {
if (index == subaddressAccountListView.currentIndex && selectAndSend) appWindow.currentWallet.switchSubaddressAccount(index);
if (selectAndSend)
appWindow.showPageRequest("Transfer"); appWindow.showPageRequest("Transfer");
subaddressAccountListView.currentIndex = index;
} }
} }
} }
@@ -318,17 +321,9 @@ 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: { onCurrentIndexChanged: {
if (selectAndSend) { appWindow.onWalletUpdate();
appWindow.showPageRequest("Transfer");
}
} }
} }
} }
@@ -349,8 +344,9 @@ Rectangle {
id: addNewAccountCheckbox id: addNewAccountCheckbox
visible: !selectAndSend visible: !selectAndSend
border: false border: false
checkedIcon: "qrc:///images/plus-in-circle-medium-white.png" uncheckedIcon: FontAwesome.plusCircle
uncheckedIcon: "qrc:///images/plus-in-circle-medium-white.png" toggleOnClick: false
fontAwesomeIcons: true
fontSize: 16 fontSize: 16
iconOnTheLeft: true iconOnTheLeft: true
Layout.fillWidth: true Layout.fillWidth: true
@@ -362,8 +358,6 @@ Rectangle {
inputDialog.onAcceptedCallback = function() { inputDialog.onAcceptedCallback = function() {
appWindow.currentWallet.subaddressAccount.addRow(inputDialog.inputText) appWindow.currentWallet.subaddressAccount.addRow(inputDialog.inputText)
appWindow.currentWallet.switchSubaddressAccount(appWindow.currentWallet.numSubaddressAccounts() - 1) appWindow.currentWallet.switchSubaddressAccount(appWindow.currentWallet.numSubaddressAccounts() - 1)
current_subaddress_account_table_index = appWindow.currentWallet.numSubaddressAccounts() - 1
subaddressAccountListView.currentIndex = current_subaddress_account_table_index
appWindow.onWalletUpdate(); appWindow.onWalletUpdate();
} }
inputDialog.onRejectedCallback = null; inputDialog.onRejectedCallback = null;

View File

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

View File

@@ -181,7 +181,6 @@ Rectangle {
Layout.rightMargin: sideMargin Layout.rightMargin: sideMargin
columns: 2 columns: 2
columnSpacing: 20 columnSpacing: 20
z: 6
MoneroComponents.DatePicker { MoneroComponents.DatePicker {
id: fromDatePicker id: fromDatePicker
@@ -228,7 +227,7 @@ Rectangle {
MoneroComponents.TextPlain { MoneroComponents.TextPlain {
font.family: MoneroComponents.Style.fontRegular.name font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 15 font.pixelSize: 15
text: qsTr("Sort by") + ":" text: qsTr("Sort by") + ":" + translationManager.emptyString
color: MoneroComponents.Style.defaultFontColor color: MoneroComponents.Style.defaultFontColor
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
@@ -447,7 +446,7 @@ Rectangle {
MoneroComponents.TextPlain { MoneroComponents.TextPlain {
font.family: MoneroComponents.Style.fontRegular.name font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 15 font.pixelSize: 15
text: qsTr("Page") + ":" text: qsTr("Page") + ":" + translationManager.emptyString
color: MoneroComponents.Style.defaultFontColor color: MoneroComponents.Style.defaultFontColor
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
@@ -651,7 +650,7 @@ Rectangle {
MoneroComponents.TextPlain { MoneroComponents.TextPlain {
font.family: MoneroComponents.Style.fontRegular.name font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 15 font.pixelSize: 15
text: _amount + " XMR" text: displayAmount
color: MoneroComponents.Style.defaultFontColor color: MoneroComponents.Style.defaultFontColor
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
@@ -870,7 +869,7 @@ Rectangle {
MoneroComponents.TextPlain { MoneroComponents.TextPlain {
font.family: MoneroComponents.Style.fontRegular.name font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 15 font.pixelSize: 15
text: persistentSettings.historyHumanDates ? dateHuman : date + " " + time text: persistentSettings.historyHumanDates ? dateHuman : dateTime
color: MoneroComponents.Style.defaultFontColor color: MoneroComponents.Style.defaultFontColor
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
@@ -882,7 +881,7 @@ Rectangle {
onEntered: { onEntered: {
parent.color = MoneroComponents.Style.orange parent.color = MoneroComponents.Style.orange
if (persistentSettings.historyHumanDates) { if (persistentSettings.historyHumanDates) {
parent.text = date + " " + time; parent.text = dateTime;
} }
} }
onExited: { onExited: {
@@ -1197,7 +1196,7 @@ Rectangle {
if(res[i].state === 'copyable_address') root.toClipboard(address); if(res[i].state === 'copyable_address') root.toClipboard(address);
if(res[i].state === 'copyable_txkey') root.getTxKey(hash, res[i]); 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 === 'set_tx_note') root.editDescription(hash);
if(res[i].state === 'details') root.showTxDetails(hash, paymentId, destinations, subaddrAccount, subaddrIndex); if(res[i].state === 'details') root.showTxDetails(hash, paymentId, destinations, subaddrAccount, subaddrIndex, dateTime, displayAmount, isout);
if(res[i].state === 'proof') root.showTxProof(hash, paymentId, destinations, subaddrAccount, subaddrIndex); if(res[i].state === 'proof') root.showTxProof(hash, paymentId, destinations, subaddrAccount, subaddrIndex);
doCollapse = false; doCollapse = false;
break; break;
@@ -1480,12 +1479,12 @@ Rectangle {
var timestamp = new Date(date + " " + time).getTime() / 1000; var timestamp = new Date(date + " " + time).getTime() / 1000;
var dateHuman = Utils.ago(timestamp); var dateHuman = Utils.ago(timestamp);
var _amount = amount; var displayAmount = amount;
if(_amount === 0){ if(displayAmount === 0){
// *sometimes* amount is 0, while the 'destinations string' // *sometimes* amount is 0, while the 'destinations string'
// has the correct amount, so we try to fetch it from that instead. // has the correct amount, so we try to fetch it from that instead.
_amount = TxUtils.destinationsToAmount(destinations); displayAmount = TxUtils.destinationsToAmount(destinations);
_amount = Number(_amount *1); displayAmount = Number(displayAmount *1);
} }
var tx_note = currentWallet.getUserNote(hash); var tx_note = currentWallet.getUserNote(hash);
@@ -1503,15 +1502,14 @@ Rectangle {
"i": i, "i": i,
"isout": isout, "isout": isout,
"amount": Number(amount), "amount": Number(amount),
"_amount": _amount, "displayAmount": displayAmount + " XMR",
"hash": hash, "hash": hash,
"paymentId": paymentId, "paymentId": paymentId,
"address": address, "address": address,
"destinations": destinations, "destinations": destinations,
"tx_note": tx_note, "tx_note": tx_note,
"time": time,
"date": date,
"dateHuman": dateHuman, "dateHuman": dateHuman,
"dateTime": date + " " + time,
"blockheight": blockheight, "blockheight": blockheight,
"address": address, "address": address,
"timestamp": timestamp, "timestamp": timestamp,
@@ -1588,17 +1586,20 @@ Rectangle {
} }
} }
function showTxDetails(hash, paymentId, destinations, subaddrAccount, subaddrIndex){ function showTxDetails(hash, paymentId, destinations, subaddrAccount, subaddrIndex, dateTime, amount, isout) {
var tx_note = currentWallet.getUserNote(hash) var tx_note = currentWallet.getUserNote(hash)
var rings = currentWallet.getRings(hash) var rings = currentWallet.getRings(hash)
var address_label = subaddrIndex == 0 ? (qsTr("Primary address") + translationManager.emptyString) : currentWallet.getSubaddressLabel(subaddrAccount, subaddrIndex) var address_label = subaddrIndex == 0 ? (qsTr("Primary address") + translationManager.emptyString) : currentWallet.getSubaddressLabel(subaddrAccount, subaddrIndex)
var address = currentWallet.address(subaddrAccount, subaddrIndex) var address = currentWallet.address(subaddrAccount, subaddrIndex)
const hasPaymentId = parseInt(paymentId, 16);
const integratedAddress = !isout && hasPaymentId ? currentWallet.integratedAddress(paymentId) : null;
if (rings) if (rings)
rings = rings.replace(/\|/g, '\n') rings = rings.replace(/\|/g, '\n')
currentWallet.getTxKeyAsync(hash, function(hash, tx_key) { currentWallet.getTxKeyAsync(hash, function(hash, tx_key) {
informationPopup.title = qsTr("Transaction details") + translationManager.emptyString; informationPopup.title = qsTr("Transaction details") + translationManager.emptyString;
informationPopup.content = buildTxDetailsString(hash, paymentId, tx_key, tx_note, destinations, rings, address, address_label); informationPopup.content = buildTxDetailsString(hash, paymentId, tx_key, tx_note, destinations, rings, address, address_label, integratedAddress, dateTime, amount);
informationPopup.onCloseCallback = null informationPopup.onCloseCallback = null
informationPopup.open(); informationPopup.open();
}); });
@@ -1626,16 +1627,18 @@ Rectangle {
appWindow.showStatusMessage(qsTr("Copied to clipboard"),3); appWindow.showStatusMessage(qsTr("Copied to clipboard"),3);
} }
function buildTxDetailsString(tx_id, paymentId, tx_key,tx_note, destinations, rings, address, address_label) { function buildTxDetailsString(tx_id, paymentId, tx_key,tx_note, destinations, rings, address, address_label, integratedAddress, dateTime, amount) {
var trStart = '<tr><td width="85" style="padding-top:5px"><b>', var trStart = '<tr><td style="white-space: nowrap; padding-top:5px"><b>',
trMiddle = '</b></td><td style="padding-left:10px;padding-top:5px;">', trMiddle = '</b></td><td style="padding-left:10px;padding-top:5px;">',
trEnd = "</td></tr>"; trEnd = "</td></tr>";
return '<table border="0">' return '<table border="0">'
+ (tx_id ? trStart + qsTr("Tx ID:") + trMiddle + tx_id + trEnd : "") + (tx_id ? trStart + qsTr("Tx ID:") + trMiddle + tx_id + trEnd : "")
+ (address_label ? trStart + qsTr("Address label:") + trMiddle + address_label + trEnd : "") + (dateTime ? trStart + qsTr("Date") + ":" + trMiddle + dateTime + trEnd : "")
+ (amount ? trStart + qsTr("Amount") + ":" + trMiddle + amount + trEnd : "")
+ (address ? trStart + qsTr("Address:") + trMiddle + address + trEnd : "") + (address ? trStart + qsTr("Address:") + trMiddle + address + trEnd : "")
+ (paymentId ? trStart + qsTr("Payment ID:") + trMiddle + paymentId + 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_key ? trStart + qsTr("Tx key:") + trMiddle + tx_key + trEnd : "")
+ (tx_note ? trStart + qsTr("Tx note:") + trMiddle + tx_note + trEnd : "") + (tx_note ? trStart + qsTr("Tx note:") + trMiddle + tx_note + trEnd : "")
+ (destinations ? trStart + qsTr("Destinations:") + trMiddle + destinations + trEnd : "") + (destinations ? trStart + qsTr("Destinations:") + trMiddle + destinations + trEnd : "")

View File

@@ -244,8 +244,9 @@ Rectangle {
MoneroComponents.CheckBox { MoneroComponents.CheckBox {
id: addNewAddressCheckbox id: addNewAddressCheckbox
border: false border: false
checkedIcon: "qrc:///images/plus-in-circle-medium-white.png" uncheckedIcon: FontAwesome.plusCircle
uncheckedIcon: "qrc:///images/plus-in-circle-medium-white.png" toggleOnClick: false
fontAwesomeIcons: true
fontSize: 16 fontSize: 16
iconOnTheLeft: true iconOnTheLeft: true
Layout.fillWidth: true Layout.fillWidth: true

View File

@@ -168,6 +168,10 @@ Rectangle {
labelText: qsTr("<style type='text/css'>a {text-decoration: none; color: #858585; font-size: 14px;}</style>\ 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>") Amount <font size='2'> ( </font> <a href='#'>Change account</a><font size='2'> )</font>")
+ translationManager.emptyString + translationManager.emptyString
copyButton: !isNaN(amountLine.text) && persistentSettings.fiatPriceEnabled
copyButtonText: fiatApiCurrencySymbol() + " ~" + fiatApiConvertToFiat(amountLine.text)
copyButtonEnabled: false
onLabelLinkActivated: { onLabelLinkActivated: {
middlePanel.accountView.selectAndSend = true; middlePanel.accountView.selectAndSend = true;
appWindow.showPageRequest("Account") appWindow.showPageRequest("Account")
@@ -178,9 +182,17 @@ Rectangle {
inlineButtonText: qsTr("All") + translationManager.emptyString inlineButtonText: qsTr("All") + translationManager.emptyString
inlineButton.onClicked: amountLine.text = "(all)" inlineButton.onClicked: amountLine.text = "(all)"
onTextChanged: { onTextChanged: {
if(amountLine.text.indexOf('.') === 0){ const match = amountLine.text.match(/^0+(\d.*)/);
amountLine.text = '0' + amountLine.text; 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;
}
}
} }
validator: RegExpValidator { validator: RegExpValidator {
@@ -257,18 +269,14 @@ Rectangle {
appWindow.showPageRequest("AddressBook"); appWindow.showPageRequest("AddressBook");
} }
pasteButton: true pasteButton: true
onPaste: function(clipboardText) { onTextChanged: {
const parsed = walletManager.parse_uri_to_object(clipboardText); const parsed = walletManager.parse_uri_to_object(text);
if (!parsed.error) { if (!parsed.error) {
addressLine.text = parsed.address; addressLine.text = parsed.address;
setPaymentId(parsed.payment_id); setPaymentId(parsed.payment_id);
amountLine.text = parsed.amount; amountLine.text = parsed.amount;
setDescription(parsed.tx_description); setDescription(parsed.tx_description);
} else {
addressLine.text = clipboardText;
} }
}
onTextChanged: {
warningLongPidTransfer = isLongPidService(text); warningLongPidTransfer = isLongPidService(text);
} }
inlineButton.text: FontAwesome.qrcode inlineButton.text: FontAwesome.qrcode
@@ -343,8 +351,9 @@ Rectangle {
CheckBox { CheckBox {
id: descriptionCheckbox id: descriptionCheckbox
border: false border: false
checkedIcon: "qrc:///images/plus-in-circle-medium-white.png" checkedIcon: FontAwesome.minusCircle
uncheckedIcon: "qrc:///images/plus-in-circle-medium-white.png" uncheckedIcon: FontAwesome.plusCircle
fontAwesomeIcons: true
fontSize: descriptionLine.labelFontSize fontSize: descriptionLine.labelFontSize
iconOnTheLeft: true iconOnTheLeft: true
Layout.fillWidth: true Layout.fillWidth: true
@@ -370,8 +379,9 @@ Rectangle {
CheckBox { CheckBox {
id: paymentIdCheckbox id: paymentIdCheckbox
border: false border: false
checkedIcon: "qrc:///images/plus-in-circle-medium-white.png" checkedIcon: FontAwesome.minusCircle
uncheckedIcon: "qrc:///images/plus-in-circle-medium-white.png" uncheckedIcon: FontAwesome.plusCircle
fontAwesomeIcons: true
fontSize: paymentIdLine.labelFontSize fontSize: paymentIdLine.labelFontSize
iconOnTheLeft: true iconOnTheLeft: true
Layout.fillWidth: true Layout.fillWidth: true
@@ -756,7 +766,8 @@ Rectangle {
// Currently opened wallet is not view-only // Currently opened wallet is not view-only
if(appWindow.viewOnly){ if(appWindow.viewOnly){
root.sendButtonWarning = qsTr("Wallet is view-only and sends are not possible.") + translationManager.emptyString; 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;
return false; return false;
} }

View File

@@ -158,7 +158,7 @@ Item {
"<p>It's up to you whether to accept unconfirmed transactions or not. It is likely they'll be " + "<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 " + "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>" "values you may want to wait for one or more confirmation(s).</p>"
); ) + translationManager.emptyString;
} else if(root.trackingError !== ""){ } else if(root.trackingError !== ""){
return root.trackingError; return root.trackingError;
} else if(trackingModel.count < 1){ } else if(trackingModel.count < 1){
@@ -265,7 +265,7 @@ Item {
font.pixelSize: 12 font.pixelSize: 12
font.bold: false font.bold: false
color: "white" color: "white"
text: "<style type='text/css'>a {text-decoration: none; color: #FF6C3C; font-size: 12px;}</style>Currently selected address: " + addressLabel + " <a href='#'>(Change)</a>" 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
textFormat: Text.RichText textFormat: Text.RichText
themeTransition: false themeTransition: false
@@ -446,7 +446,7 @@ Item {
font.pixelSize: 14 font.pixelSize: 14
font.bold: false font.bold: false
color: "white" color: "white"
text: qsTr("Amount to receive") + " (XMR)" text: qsTr("Amount to receive") + " (XMR)" + translationManager.emptyString
themeTransition: false themeTransition: false
} }
@@ -455,7 +455,7 @@ Item {
width: 220 width: 220
source: "qrc:///images/merchant/input_box.png" source: "qrc:///images/merchant/input_box.png"
TextField { MoneroComponents.Input {
id: amountToReceive id: amountToReceive
topPadding: 0 topPadding: 0
leftPadding: 10 leftPadding: 10

View File

@@ -72,6 +72,7 @@ Rectangle {
id: themeCheckbox id: themeCheckbox
checked: !MoneroComponents.Style.blackTheme checked: !MoneroComponents.Style.blackTheme
text: qsTr("Light theme") + translationManager.emptyString text: qsTr("Light theme") + translationManager.emptyString
toggleOnClick: false
onClicked: { onClicked: {
MoneroComponents.Style.blackTheme = !MoneroComponents.Style.blackTheme; MoneroComponents.Style.blackTheme = !MoneroComponents.Style.blackTheme;
persistentSettings.blackTheme = MoneroComponents.Style.blackTheme; persistentSettings.blackTheme = MoneroComponents.Style.blackTheme;
@@ -92,7 +93,8 @@ Rectangle {
Layout.leftMargin: 42 Layout.leftMargin: 42
spacing: 0 spacing: 0
MoneroComponents.TextBlock { Text {
color: MoneroComponents.Style.defaultFontColor
font.pixelSize: 14 font.pixelSize: 14
Layout.fillWidth: true Layout.fillWidth: true
text: { text: {
@@ -141,6 +143,12 @@ Rectangle {
} }
onMoved: persistentSettings.lockOnUserInActivityInterval = userInactivitySlider.value; onMoved: persistentSettings.lockOnUserInActivityInterval = userInactivitySlider.value;
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.NoButton
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
}
} }
} }

View File

@@ -119,7 +119,7 @@ Rectangle{
text: qsTr("Local node") + translationManager.emptyString text: qsTr("Local node") + translationManager.emptyString
} }
TextArea { Text {
id: localNodeArea id: localNodeArea
anchors.top: localNodeHeader.bottom anchors.top: localNodeHeader.bottom
anchors.topMargin: 4 anchors.topMargin: 4
@@ -129,14 +129,11 @@ Rectangle{
font.family: MoneroComponents.Style.fontRegular.name font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 15 font.pixelSize: 15
horizontalAlignment: TextInput.AlignLeft horizontalAlignment: TextInput.AlignLeft
selectByMouse: false
wrapMode: Text.WordWrap; wrapMode: Text.WordWrap;
textMargin: 0
leftPadding: 0 leftPadding: 0
topPadding: 0 topPadding: 0
text: qsTr("The blockchain is downloaded to your computer. Provides higher security and requires more local storage.") + translationManager.emptyString 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) width: parent.width - (localNodeIcon.width + localNodeIcon.anchors.leftMargin + anchors.leftMargin)
readOnly: true
// @TODO: Legacy. Remove after Qt 5.8. // @TODO: Legacy. Remove after Qt 5.8.
// https://stackoverflow.com/questions/41990013 // https://stackoverflow.com/questions/41990013
@@ -221,7 +218,7 @@ Rectangle{
text: qsTr("Remote node") + translationManager.emptyString text: qsTr("Remote node") + translationManager.emptyString
} }
TextArea { Text {
id: remoteNodeArea id: remoteNodeArea
anchors.top: remoteNodeHeader.bottom anchors.top: remoteNodeHeader.bottom
anchors.topMargin: 4 anchors.topMargin: 4
@@ -230,16 +227,12 @@ Rectangle{
color: MoneroComponents.Style.dimmedFontColor color: MoneroComponents.Style.dimmedFontColor
font.family: MoneroComponents.Style.fontRegular.name font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 15 font.pixelSize: 15
activeFocusOnPress: false
horizontalAlignment: TextInput.AlignLeft horizontalAlignment: TextInput.AlignLeft
selectByMouse: false
wrapMode: Text.WordWrap; wrapMode: Text.WordWrap;
textMargin: 0
leftPadding: 0 leftPadding: 0
topPadding: 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 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) width: parent.width - (remoteNodeIcon.width + remoteNodeIcon.anchors.leftMargin + anchors.leftMargin)
readOnly: true
// @TODO: Legacy. Remove after Qt 5.8. // @TODO: Legacy. Remove after Qt 5.8.
// https://stackoverflow.com/questions/41990013 // https://stackoverflow.com/questions/41990013
@@ -253,7 +246,6 @@ Rectangle{
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
anchors.fill: parent anchors.fill: parent
onClicked: { onClicked: {
persistentSettings.useRemoteNode = true;
appWindow.connectRemoteNode(); appWindow.connectRemoteNode();
} }
} }

View File

@@ -47,312 +47,97 @@ Rectangle {
anchors.right: parent.right anchors.right: parent.right
anchors.margins: 20 anchors.margins: 20
anchors.topMargin: 0 anchors.topMargin: 0
spacing: 0 spacing: 8
Rectangle { MoneroComponents.SettingsListItem {
// divider buttonText: qsTr("Close wallet") + translationManager.emptyString
Layout.preferredHeight: 1 description: qsTr("Logs out of this wallet.") + translationManager.emptyString
Layout.fillWidth: true title: qsTr("Close this wallet") + translationManager.emptyString
Layout.bottomMargin: 8
color: MoneroComponents.Style.dividerColor
opacity: MoneroComponents.Style.dividerOpacity
}
GridLayout { onClicked: {
Layout.fillWidth: true middlePanel.addressBookView.clearFields();
Layout.preferredHeight: childrenRect.height middlePanel.transferView.clearFields();
columnSpacing: 0 middlePanel.receiveView.clearFields();
appWindow.showWizard();
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
} }
} }
Rectangle { MoneroComponents.SettingsListItem {
// divider buttonText: qsTr("Create wallet") + translationManager.emptyString
Layout.preferredHeight: 1 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
Layout.fillWidth: true title: qsTr("Create a view-only wallet") + translationManager.emptyString
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 visible: !appWindow.viewOnly
ColumnLayout { onClicked: {
Layout.fillWidth: true var newPath = currentWallet.path + "_viewonly";
Layout.alignment: Qt.AlignVCenter if (currentWallet.createViewOnly(newPath, appWindow.walletPassword)) {
spacing: 0 console.log("view only wallet created in " + newPath);
informationPopup.title = qsTr("Success") + translationManager.emptyString;
MoneroComponents.TextPlain { 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);
Layout.fillWidth: true informationPopup.open()
Layout.preferredHeight: 20 informationPopup.onCloseCallback = null
Layout.topMargin: 8 } else {
color: MoneroComponents.Style.defaultFontColor informationPopup.title = qsTr("Error") + translationManager.emptyString;
opacity: MoneroComponents.Style.blackTheme ? 1.0 : 0.8 informationPopup.text = currentWallet.errorString;
font.bold: true informationPopup.open()
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.StandardButton { MoneroComponents.SettingsListItem {
small: true buttonText: qsTr("Show seed") + translationManager.emptyString
text: qsTr("Create wallet") + translationManager.emptyString description: qsTr("Store this information safely to recover your wallet in the future.") + translationManager.emptyString
onClicked: { title: qsTr("Show seed & keys") + translationManager.emptyString
var newPath = currentWallet.path + "_viewonly";
if (currentWallet.createViewOnly(newPath, appWindow.walletPassword)) { onClicked: {
console.log("view only wallet created in " + newPath); Utils.showSeedPage();
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 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()
} else { } else {
informationPopup.title = qsTr("Error") + translationManager.emptyString; informationPopup.title = qsTr("Error") + translationManager.emptyString;
informationPopup.text = currentWallet.errorString; informationPopup.text = qsTr("Wrong password") + translationManager.emptyString;
informationPopup.open() informationPopup.open()
informationPopup.onCloseCallback = function() {
passwordDialog.open()
}
} }
} }
width: 135 passwordDialog.onRejectedCallback = null;
} passwordDialog.open()
}
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){
passwordDialog.openNewPasswordDialog()
} 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
} }
} }
} }

View File

@@ -7,11 +7,8 @@
<file>images/download-white@2x.png</file> <file>images/download-white@2x.png</file>
<file>images/external-link-white.png</file> <file>images/external-link-white.png</file>
<file>images/external-link-white@2x.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/Label.qml</file>
<file>components/SettingsListItem.qml</file>
<file>images/whatIsIcon.png</file> <file>images/whatIsIcon.png</file>
<file>images/whatIsIcon@2x.png</file> <file>images/whatIsIcon@2x.png</file>
<file>images/lockIcon.png</file> <file>images/lockIcon.png</file>
@@ -21,6 +18,8 @@
<file>pages/History.qml</file> <file>pages/History.qml</file>
<file>pages/AddressBook.qml</file> <file>pages/AddressBook.qml</file>
<file>pages/Mining.qml</file> <file>pages/Mining.qml</file>
<file>components/ContextMenu.qml</file>
<file>components/ContextMenuItem.qml</file>
<file>components/NetworkStatusItem.qml</file> <file>components/NetworkStatusItem.qml</file>
<file>components/Input.qml</file> <file>components/Input.qml</file>
<file>components/StandardButton.qml</file> <file>components/StandardButton.qml</file>
@@ -171,8 +170,6 @@
<file>components/WarningBox.qml</file> <file>components/WarningBox.qml</file>
<file>images/miningxmr.png</file> <file>images/miningxmr.png</file>
<file>images/miningxmr@2x.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/Merchant.qml</file>
<file>pages/merchant/MerchantCheckbox.qml</file> <file>pages/merchant/MerchantCheckbox.qml</file>
<file>pages/merchant/MerchantTrackingList.qml</file> <file>pages/merchant/MerchantTrackingList.qml</file>

View File

@@ -43,7 +43,7 @@
#include <QMap> #include <QMap>
namespace { namespace {
static const int DAEMON_START_TIMEOUT_SECONDS = 60; static const int DAEMON_START_TIMEOUT_SECONDS = 120;
} }
DaemonManager * DaemonManager::m_instance = nullptr; DaemonManager * DaemonManager::m_instance = nullptr;

View File

@@ -32,10 +32,13 @@
#include <QFile> #include <QFile>
#include <QDebug> #include <QDebug>
#include <QReadLocker>
#include <QWriteLocker>
TransactionInfo *TransactionHistory::transaction(int index) TransactionInfo *TransactionHistory::transaction(int index)
{ {
QReadLocker locker(&m_tinfoLock);
if (index < 0 || index >= m_tinfo.size()) { if (index < 0 || index >= m_tinfo.size()) {
qCritical("%s: no transaction info for index %d", __FUNCTION__, index); qCritical("%s: no transaction info for index %d", __FUNCTION__, index);
@@ -53,41 +56,48 @@ TransactionInfo *TransactionHistory::transaction(int index)
QList<TransactionInfo *> TransactionHistory::getAll(quint32 accountIndex) const 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 firstDateTime = QDateTime(QDate(2014, 4, 18)); // the genesis block
QDateTime lastDateTime = QDateTime::currentDateTime().addDays(1); // tomorrow (guard against jitter and timezones) QDateTime lastDateTime = QDateTime::currentDateTime().addDays(1); // tomorrow (guard against jitter and timezones)
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 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;
}
}
} }
emit refreshFinished(); emit refreshFinished();
if (m_firstDateTime != firstDateTime) { if (m_firstDateTime != firstDateTime) {
@@ -112,6 +122,8 @@ void TransactionHistory::refresh(quint32 accountIndex)
quint64 TransactionHistory::count() const quint64 TransactionHistory::count() const
{ {
QReadLocker locker(&m_tinfoLock);
return m_tinfo.count(); return m_tinfo.count();
} }

View File

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

View File

@@ -55,6 +55,8 @@ namespace {
static const int DAEMON_BLOCKCHAIN_HEIGHT_CACHE_TTL_SECONDS = 5; static const int DAEMON_BLOCKCHAIN_HEIGHT_CACHE_TTL_SECONDS = 5;
static const int DAEMON_BLOCKCHAIN_TARGET_HEIGHT_CACHE_TTL_SECONDS = 30; static const int DAEMON_BLOCKCHAIN_TARGET_HEIGHT_CACHE_TTL_SECONDS = 30;
static const int WALLET_CONNECTION_STATUS_CACHE_TTL_SECONDS = 5; static const int WALLET_CONNECTION_STATUS_CACHE_TTL_SECONDS = 5;
static constexpr char ATTRIBUTE_SUBADDRESS_ACCOUNT[] ="gui.subaddress_account";
} }
class WalletListenerImpl : public Monero::WalletListener class WalletListenerImpl : public Monero::WalletListener
@@ -316,8 +318,13 @@ void Wallet::switchSubaddressAccount(quint32 accountIndex)
if (accountIndex < numSubaddressAccounts()) if (accountIndex < numSubaddressAccounts())
{ {
m_currentSubaddressAccount = accountIndex; 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_subaddress->refresh(m_currentSubaddressAccount);
m_history->refresh(m_currentSubaddressAccount); m_history->refresh(m_currentSubaddressAccount);
emit currentSubaddressAccountChanged();
} }
} }
void Wallet::addSubaddressAccount(const QString& label) void Wallet::addSubaddressAccount(const QString& label)
@@ -982,6 +989,7 @@ Wallet::Wallet(Monero::Wallet *w, QObject *parent)
m_walletListener = new WalletListenerImpl(this); m_walletListener = new WalletListenerImpl(this);
m_walletImpl->setListener(m_walletListener); m_walletImpl->setListener(m_walletListener);
m_connectionStatus = Wallet::ConnectionStatus_Disconnected; m_connectionStatus = Wallet::ConnectionStatus_Disconnected;
m_currentSubaddressAccount = getCacheAttribute(ATTRIBUTE_SUBADDRESS_ACCOUNT).toUInt();
// start cache timers // start cache timers
m_connectionStatusTime.restart(); m_connectionStatusTime.restart();
m_daemonBlockChainHeightTime.restart(); m_daemonBlockChainHeightTime.restart();

View File

@@ -65,7 +65,7 @@ class Wallet : public QObject
Q_PROPERTY(Status status READ status) Q_PROPERTY(Status status READ status)
Q_PROPERTY(NetworkType::Type nettype READ nettype) Q_PROPERTY(NetworkType::Type nettype READ nettype)
// Q_PROPERTY(ConnectionStatus connected READ connected) // Q_PROPERTY(ConnectionStatus connected READ connected)
Q_PROPERTY(quint32 currentSubaddressAccount READ currentSubaddressAccount) Q_PROPERTY(quint32 currentSubaddressAccount READ currentSubaddressAccount NOTIFY currentSubaddressAccountChanged)
Q_PROPERTY(bool synchronized READ synchronized) Q_PROPERTY(bool synchronized READ synchronized)
Q_PROPERTY(QString errorString READ errorString) Q_PROPERTY(QString errorString READ errorString)
Q_PROPERTY(TransactionHistory * history READ history) Q_PROPERTY(TransactionHistory * history READ history)
@@ -365,6 +365,7 @@ signals:
void transactionCreated(PendingTransaction * transaction, QString address, QString paymentId, quint32 mixinCount); void transactionCreated(PendingTransaction * transaction, QString address, QString paymentId, quint32 mixinCount);
void connectionStatusChanged(int status) const; void connectionStatusChanged(int status) const;
void currentSubaddressAccountChanged() const;
private: private:
Wallet(QObject * parent = nullptr); Wallet(QObject * parent = nullptr);

View File

@@ -150,7 +150,7 @@ ColumnLayout {
color: MoneroComponents.Style.defaultFontColor color: MoneroComponents.Style.defaultFontColor
} }
TextField { MoneroComponents.Input {
id: passwordInput id: passwordInput
Layout.topMargin: 6 Layout.topMargin: 6
@@ -180,14 +180,15 @@ ColumnLayout {
color: "transparent" color: "transparent"
MoneroComponents.Label { MoneroComponents.Label {
fontSize: 20 fontSize: 18
text: FontAwesome.lock text: FontAwesome.lock
opacity: 0.5 opacity: 0.5
fontFamily: FontAwesome.fontFamily fontFamily: FontAwesome.fontFamilySolid
styleName: "Solid"
anchors.right: parent.right anchors.right: parent.right
anchors.rightMargin: 15 anchors.rightMargin: 10
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
anchors.verticalCenterOffset: 3 anchors.verticalCenterOffset: 1
} }
} }
} }
@@ -207,7 +208,7 @@ ColumnLayout {
color: MoneroComponents.Style.defaultFontColor color: MoneroComponents.Style.defaultFontColor
} }
TextField { MoneroComponents.Input {
id : passwordInputConfirm id : passwordInputConfirm
Layout.topMargin: 6 Layout.topMargin: 6
@@ -237,14 +238,15 @@ ColumnLayout {
color: "transparent" color: "transparent"
MoneroComponents.Label { MoneroComponents.Label {
fontSize: 20 fontSize: 18
text: FontAwesome.lock text: FontAwesome.lock
opacity: 0.5 opacity: 0.5
fontFamily: FontAwesome.fontFamily fontFamily: FontAwesome.fontFamilySolid
styleName: "Solid"
anchors.right: parent.right anchors.right: parent.right
anchors.rightMargin: 15 anchors.rightMargin: 10
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
anchors.verticalCenterOffset: 3 anchors.verticalCenterOffset: 1
} }
} }
} }

View File

@@ -158,7 +158,7 @@ Rectangle {
} }
} }
TextArea { Text {
id: errorMsg id: errorMsg
text: qsTr("Error writing wallet from hardware device. Check application logs.") + translationManager.emptyString; text: qsTr("Error writing wallet from hardware device. Check application logs.") + translationManager.emptyString;
visible: errorMsg.text !== "" visible: errorMsg.text !== ""
@@ -167,16 +167,10 @@ Rectangle {
color: MoneroComponents.Style.errorColor color: MoneroComponents.Style.errorColor
font.pixelSize: 16 font.pixelSize: 16
selectionColor: MoneroComponents.Style.textSelectionColor
selectedTextColor: MoneroComponents.Style.textSelectedColor
selectByMouse: true
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
textMargin: 0
leftPadding: 0 leftPadding: 0
topPadding: 0 topPadding: 0
bottomPadding: 0 bottomPadding: 0
readOnly: true
} }
WizardNav { WizardNav {

View File

@@ -91,7 +91,7 @@ ColumnLayout {
Layout.topMargin: 6 Layout.topMargin: 6
spacing: 0 spacing: 0
TextArea { Text {
text: qsTr("Bootstrap node") + translationManager.emptyString text: qsTr("Bootstrap node") + translationManager.emptyString
Layout.topMargin: 10 Layout.topMargin: 10
Layout.fillWidth: true Layout.fillWidth: true
@@ -105,19 +105,13 @@ ColumnLayout {
} }
} }
selectionColor: MoneroComponents.Style.textSelectionColor
selectedTextColor: MoneroComponents.Style.textSelectedColor
selectByMouse: true
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
textMargin: 0
leftPadding: 0 leftPadding: 0
topPadding: 0 topPadding: 0
bottomPadding: 0 bottomPadding: 0
readOnly: true
} }
TextArea { Text {
text: qsTr("Additionally, you may specify a bootstrap node to use Monero immediately.") + translationManager.emptyString text: qsTr("Additionally, you may specify a bootstrap node to use Monero immediately.") + translationManager.emptyString
Layout.topMargin: 4 Layout.topMargin: 4
Layout.fillWidth: true Layout.fillWidth: true
@@ -133,16 +127,10 @@ ColumnLayout {
} }
} }
selectionColor: MoneroComponents.Style.textSelectionColor
selectedTextColor: MoneroComponents.Style.textSelectedColor
selectByMouse: true
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
textMargin: 0
leftPadding: 0 leftPadding: 0
topPadding: 0 topPadding: 0
bottomPadding: 0 bottomPadding: 0
readOnly: true
} }
} }

View File

@@ -41,7 +41,7 @@ ColumnLayout {
spacing: 4 spacing: 4
Layout.maximumWidth: wizardController.wizardSubViewWidth Layout.maximumWidth: wizardController.wizardSubViewWidth
TextArea { Text {
text: title text: title
Layout.fillWidth: true Layout.fillWidth: true
font.family: MoneroComponents.Style.fontRegular.name font.family: MoneroComponents.Style.fontRegular.name
@@ -55,19 +55,13 @@ ColumnLayout {
} }
} }
selectionColor: MoneroComponents.Style.textSelectionColor
selectedTextColor: MoneroComponents.Style.textSelectedColor
selectByMouse: true
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
textMargin: 0
leftPadding: 0 leftPadding: 0
topPadding: 0 topPadding: 0
bottomPadding: 0 bottomPadding: 0
readOnly: true
} }
TextArea { Text {
Layout.fillWidth: true Layout.fillWidth: true
Layout.alignment: Qt.AlignCenter Layout.alignment: Qt.AlignCenter
visible: parent.subtitle !== "" visible: parent.subtitle !== ""
@@ -84,14 +78,8 @@ ColumnLayout {
} }
} }
selectionColor: MoneroComponents.Style.textSelectionColor
selectedTextColor: MoneroComponents.Style.textSelectedColor
selectByMouse: true
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
textMargin: 0
leftPadding: 0 leftPadding: 0
topPadding: 0 topPadding: 0
readOnly: true
} }
} }

View File

@@ -149,12 +149,10 @@ Rectangle {
} }
MoneroComponents.StandardButton { MoneroComponents.StandardButton {
visible: !persistentSettings.customDecorations
small: true small: true
text: qsTr("Change language") + translationManager.emptyString text: qsTr("Change language") + translationManager.emptyString
onClicked: { onClicked: {
wizardController.wizardStackView.backTransition = false;
appWindow.toggleLanguageView(); appWindow.toggleLanguageView();
} }
} }

View File

@@ -67,7 +67,7 @@ Rectangle {
width: parent.width - 100 width: parent.width - 100
anchors.horizontalCenter: parent.horizontalCenter; anchors.horizontalCenter: parent.horizontalCenter;
TextArea { Text {
text: qsTr("Language settings") + translationManager.emptyString text: qsTr("Language settings") + translationManager.emptyString
Layout.fillWidth: true Layout.fillWidth: true
font.family: MoneroComponents.Style.fontRegular.name font.family: MoneroComponents.Style.fontRegular.name
@@ -80,19 +80,13 @@ Rectangle {
} }
} }
selectionColor: MoneroComponents.Style.textSelectionColor
selectedTextColor: MoneroComponents.Style.textSelectedColor
selectByMouse: true
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
textMargin: 0
leftPadding: 0 leftPadding: 0
topPadding: 0 topPadding: 0
bottomPadding: 0 bottomPadding: 0
readOnly: true
} }
TextArea { Text {
Layout.fillWidth: true Layout.fillWidth: true
visible: parent.subtitle !== "" visible: parent.subtitle !== ""
@@ -108,15 +102,9 @@ Rectangle {
} }
} }
selectionColor: MoneroComponents.Style.textSelectionColor
selectedTextColor: MoneroComponents.Style.textSelectedColor
selectByMouse: true
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
textMargin: 0
leftPadding: 0 leftPadding: 0
topPadding: 0 topPadding: 0
readOnly: true
} }
Flow { Flow {
@@ -190,7 +178,7 @@ Rectangle {
// set wizard language settings // set wizard language settings
wizard.language_locale = locale; wizard.language_locale = locale;
wizard.language_wallet = wallet_language; wizard.language_wallet = wallet_language;
wizard.language_language = display_name + " (" + locale_spl[1] + ") "; wizard.language_language = display_name;
appWindow.showStatusMessage(qsTr("Language changed."), 3); appWindow.showStatusMessage(qsTr("Language changed."), 3);
appWindow.toggleLanguageView(); appWindow.toggleLanguageView();

View File

@@ -57,7 +57,7 @@ Rectangle {
color: "transparent" color: "transparent"
} }
TextArea { Text {
id: textWelcome id: textWelcome
opacity: 0 opacity: 0
Layout.preferredWidth: parent.width / 1.3 Layout.preferredWidth: parent.width / 1.3
@@ -69,12 +69,9 @@ Rectangle {
font.bold: true font.bold: true
font.pixelSize: 18 font.pixelSize: 18
horizontalAlignment: TextInput.AlignHCenter horizontalAlignment: TextInput.AlignHCenter
selectByMouse: false
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
textMargin: 0
leftPadding: 0 leftPadding: 0
topPadding: 0 topPadding: 0
readOnly: true
Behavior on opacity { Behavior on opacity {
NumberAnimation { NumberAnimation {

View File

@@ -138,13 +138,13 @@ Rectangle {
WizardNav { WizardNav {
Layout.topMargin: 5 Layout.topMargin: 5
btnPrevText: qsTr("Change language") + translationManager.emptyString btnPrevText: qsTr("Back to menu") + translationManager.emptyString
btnNext.visible: false btnNext.visible: false
progressSteps: 0 progressSteps: 0
onPrevClicked: { onPrevClicked: {
wizardController.wizardStackView.backTransition = true; wizardController.wizardStackView.backTransition = wizardController.wizardStatePrevious.viewName == 'wizardLanguage';
wizardController.wizardState = 'wizardLanguage'; wizardController.wizardState = wizardController.wizardStatePrevious.viewName == 'wizardLanguage' ? 'wizardLanguage' : 'wizardHome';
} }
} }
} }

View File

@@ -198,7 +198,7 @@ Rectangle {
Layout.fillWidth: true Layout.fillWidth: true
} }
TextArea { Text {
text: { text: {
// truncate on window width // truncate on window width
var maxLength = wizardController.layoutScale <= 1 ? 12 : 16 var maxLength = wizardController.layoutScale <= 1 ? 12 : 16
@@ -214,19 +214,13 @@ Rectangle {
color: MoneroComponents.Style.defaultFontColor color: MoneroComponents.Style.defaultFontColor
font.pixelSize: 16 font.pixelSize: 16
selectionColor: MoneroComponents.Style.dimmedFontColor
selectedTextColor: MoneroComponents.Style.defaultFontColor
selectByMouse: false
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
textMargin: 0
leftPadding: 0 leftPadding: 0
topPadding: networktype !== -1 ? 8 : 4 topPadding: networktype !== -1 ? 8 : 4
bottomPadding: 0 bottomPadding: 0
readOnly: true
} }
TextArea { Text {
visible: networktype !== -1 visible: networktype !== -1
Layout.preferredHeight: 24 Layout.preferredHeight: 24
Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
@@ -236,16 +230,10 @@ Rectangle {
color: MoneroComponents.Style.dimmedFontColor color: MoneroComponents.Style.dimmedFontColor
font.pixelSize: 14 font.pixelSize: 14
selectionColor: MoneroComponents.Style.textSelectionColor
selectedTextColor: MoneroComponents.Style.textSelectedColor
selectByMouse: false
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
textMargin: 0
leftPadding: 0 leftPadding: 0
topPadding: 0 topPadding: 0
bottomPadding: 0 bottomPadding: 0
readOnly: true
} }
Item { Item {

View File

@@ -185,7 +185,7 @@ Rectangle {
} }
} }
TextArea { MoneroComponents.InputMulti {
id: seedInput id: seedInput
property bool error: false property bool error: false
width: parent.width width: parent.width
@@ -213,7 +213,7 @@ Rectangle {
font.family: MoneroComponents.Style.fontRegular.name font.family: MoneroComponents.Style.fontRegular.name
text: qsTr("Enter your 25 (or 24) word mnemonic seed") + translationManager.emptyString text: qsTr("Enter your 25 (or 24) word mnemonic seed") + translationManager.emptyString
color: MoneroComponents.Style.defaultFontColor color: MoneroComponents.Style.defaultFontColor
visible: !seedInput.text && !parent.focus visible: !seedInput.text
} }
} }
} }