Compare commits

...

154 Commits

Author SHA1 Message Date
luigi1111
588b8435b7 Merge pull request #4051
1215a6e Assume untrusted daemon in simple mode (j-berman)
499c2a4 qsTr scan tx error (j-berman)
3b0e66a Display clear error when user scans older tx via untrusted daemon (j-berman)
4cd6652 Update balance after calling scan_tx (j-berman)
2023-09-30 18:34:24 -04:00
luigi1111
8983cae468 Merge pull request #4220
f5cb244 build: prepare v0.18.3.0 (selsta)
2023-09-30 18:24:50 -04:00
luigi1111
3612866f9f Merge pull request #4219
8f7de0e p2pool: update to v3.7 (SChernykh)
2023-09-30 18:24:28 -04:00
luigi1111
beb336cb93 Merge pull request #4217
b60a98a workflows: run flatpak only in main repo (selsta)
2023-09-30 18:23:54 -04:00
luigi1111
90cbe37846 Merge pull request #4216
7040e3b docker: update zlib to 1.3 (selsta)
2023-09-30 18:23:33 -04:00
luigi1111
10984a0a37 Merge pull request #4211
145ea10 flatpak: Start workflow after release (BigmenPixel0)
2023-09-30 18:22:48 -04:00
selsta
f5cb2443d1 build: prepare v0.18.3.0 2023-09-30 23:43:41 +02:00
SChernykh
8f7de0e9fc p2pool: update to v3.7 2023-09-30 12:26:38 +02:00
selsta
b60a98ae6c workflows: run flatpak only in main repo 2023-09-15 21:35:02 +02:00
selsta
7040e3b72f docker: update zlib to 1.3 2023-09-15 20:00:31 +02:00
luigi1111
12a0966eb9 Merge pull request #4213
d338e06 p2pool: update to v3.6.2 (SChernykh)
2023-09-14 22:27:37 -05:00
luigi1111
5ff03786c7 Merge pull request #4210
d42caf1 cmake: update libicu to 73 (selsta)
2023-09-14 22:27:06 -05:00
luigi1111
483b825a2f Merge pull request #4157
6c4a8fb DaemonManager.cpp: disable JIT on macOS ARM (selsta)
2023-09-14 22:26:02 -05:00
luigi1111
ca304fc63d Merge pull request #4156
ad1b53f main: add ARM build tag for auto updater (selsta)
2023-09-14 22:25:31 -05:00
luigi1111
5a1a349977 Merge pull request #4155
a9e0aff workflows: set default arch for macOS bundle (selsta)
2023-09-14 22:25:08 -05:00
luigi1111
5683f76cd0 Merge pull request #4154
371ff61 cmake: copy missing boost lib, run codesign (selsta)
2023-09-14 22:23:23 -05:00
luigi1111
cc7d7da346 Merge pull request #4153
cad8874 README: add mingw-w64-x86_64-pcre for msys2 instructions (selsta)
2023-09-14 22:22:28 -05:00
luigi1111
d10e4d1e50 Merge pull request #4150
5345dcc cmake: add install_name_tool to fix svg rendering (selsta)
2023-09-14 22:22:03 -05:00
SChernykh
d338e06abd p2pool: update to v3.6.2 2023-09-03 17:39:28 +02:00
BigmenPixel0
145ea10d93 flatpak: Start workflow after release 2023-08-18 12:51:39 +05:00
selsta
d42caf1fbc cmake: update libicu to 73 2023-08-18 01:25:18 +02:00
luigi1111
705cc6573f Merge pull request #4151
7765b8b flatpak: Add workflow (BigmenPixel0)
2023-08-17 14:39:09 -05:00
luigi1111
5c3544f211 Merge pull request #4201
a65fbee Fixing broken link to Arch linux package repo (web3d3v)
2023-08-17 10:34:49 -05:00
luigi1111
f859664443 Merge pull request #4190
17e3ed6 p2pool: update to v3.5 (SChernykh)
2023-08-17 10:34:02 -05:00
luigi1111
2d25364f42 Merge pull request #4185
ddcc17b installers/windows/Readme.htm Updated blockchain size and added pruning description (Dvd-Znf)
2023-08-17 10:33:30 -05:00
luigi1111
8323fb02ca Merge pull request #4183
f6549f3 deploy: remove libssp (tobtoht)
2023-08-17 10:32:58 -05:00
luigi1111
d442ca38dc Merge pull request #4177
fa2241f WizardSummary: fix seed language and hide during restore (selsta)
2023-08-17 10:32:31 -05:00
luigi1111
57409a8c47 Merge pull request #4158
6bd11f2 TxUtils: add handleOpenAliasResolution func, simplify code (selsta)
2023-08-17 10:31:52 -05:00
luigi1111
f002987edd Merge pull request #4149
434f548 Prove/Check: clear text fields on wallet close (plowsof)
2023-08-17 10:31:23 -05:00
luigi1111
866a7b3a78 Merge pull request #4147
3331078 p2pool: fix crash without network connection (selsta)
6ac8e7a p2pool: add more detailed failure message (selsta)
2023-08-17 10:31:00 -05:00
luigi1111
f342d46541 Merge pull request #4146
90c4aa4 wizard: add Ledger Stax image (selsta)
2023-08-17 10:30:28 -05:00
luigi1111
f5e016930b Merge pull request #4145
7a4052f readme: tweak build instructions (Botspot)
2023-08-17 10:30:07 -05:00
luigi1111
ac9a305543 Merge pull request #4144
4cbfa5e docker: update OpenSSL to 1.1.1u (tobtoht)
2023-08-17 10:29:22 -05:00
luigi1111
f824aebfaa Merge pull request #4143
b6e336d docker: update Linux & Windows Qt to 5.15.10 (tobtoht)
2023-08-17 10:28:59 -05:00
BigmenPixel0
7765b8b462 flatpak: Add workflow 2023-08-15 19:18:45 +05:00
web3d3v
a65fbee213 Fixing broken link to Arch linux package repo 2023-07-27 06:28:36 +03:00
SChernykh
17e3ed6c97 p2pool: update to v3.5 2023-06-30 19:00:00 +02:00
tobtoht
b6e336dbaf docker: update Linux & Windows Qt to 5.15.10 2023-06-06 21:48:59 +02:00
Dvd-Znf
ddcc17b7b8 installers/windows/Readme.htm Updated blockchain size and added pruning description 2023-06-04 11:28:23 +03:00
tobtoht
f6549f328b deploy: remove libssp
dfa6dd8c26
2023-05-30 20:06:36 +02:00
tobtoht
4cbfa5efb2 docker: update OpenSSL to 1.1.1u 2023-05-30 16:35:36 +02:00
selsta
fa2241f1a5 WizardSummary: fix seed language and hide during restore 2023-05-16 19:55:54 +02:00
selsta
6bd11f2270 TxUtils: add handleOpenAliasResolution func, simplify code 2023-04-21 14:45:09 +02:00
selsta
6c4a8fb819 DaemonManager.cpp: disable JIT on macOS ARM 2023-04-19 16:02:22 +02:00
selsta
ad1b53fa63 main: add ARM build tag for auto updater 2023-04-17 21:56:42 +02:00
selsta
a9e0affe59 workflows: set default arch for macOS bundle 2023-04-17 21:47:30 +02:00
selsta
371ff6105b cmake: copy missing boost lib, run codesign 2023-04-17 21:45:50 +02:00
selsta
cad8874724 README: add mingw-w64-x86_64-pcre for msys2 instructions 2023-04-17 19:28:04 +02:00
selsta
5345dcc11b cmake: add install_name_tool to fix svg rendering 2023-04-15 21:41:29 +02:00
selsta
33310786db p2pool: fix crash without network connection 2023-04-13 15:45:56 +02:00
selsta
6ac8e7a464 p2pool: add more detailed failure message 2023-04-13 15:44:52 +02:00
plowsof
434f548a87 Prove/Check: clear text fields on wallet close 2023-04-10 23:37:29 +01:00
selsta
90c4aa4ec6 wizard: add Ledger Stax image 2023-04-07 23:15:14 +02:00
Botspot
7a4052f3af readme: tweak build instructions 2023-04-06 02:10:50 +02:00
luigi1111
f650e96363 Merge pull request #4137
9f33c77 build: prepare v0.18.2.2 (selsta)
2023-04-03 22:28:56 -04:00
luigi1111
91e3d3ae04 Merge pull request #4142
7d9c128 p2pool: update to v3.2 (SChernykh)
2023-04-03 22:28:24 -04:00
selsta
9f33c77a47 build: prepare v0.18.2.2 2023-04-04 03:01:50 +02:00
SChernykh
7d9c1284f9 p2pool: update to v3.2 2023-03-31 19:50:26 +02:00
luigi1111
84899f4884 Merge pull request #4138
f0ccf29 docker: fix linux build (selsta)
2023-03-28 12:41:18 -04:00
luigi1111
9c9ff13bd2 Merge pull request #4130
5e949db wizard: add Ledger Stax (selsta)
2023-03-28 12:40:51 -04:00
luigi1111
b117b9be61 Merge pull request #4126
bdf14a2 remove output blackballing (tobtoht)
2023-03-28 12:40:07 -04:00
selsta
f0ccf29f48 docker: fix linux build 2023-03-27 16:38:36 +02:00
luigi1111
3e80d563df Merge pull request #4135
cd1eab4 docker: remove duplicate library (selsta)
2023-03-27 10:25:47 -04:00
luigi1111
e4bdff0a0c Merge pull request #4133
4941b49 p2pool: update to v3.1 (SChernykh)
2023-03-27 10:25:22 -04:00
luigi1111
6b82c01891 Merge pull request #4125
511e2f4 README: remove unmaintained debian repo (selsta)
2023-03-27 10:24:15 -04:00
selsta
cd1eab45d0 docker: remove duplicate library 2023-03-24 18:11:09 +01:00
selsta
511e2f467a README: remove unmaintained debian repo 2023-03-21 22:39:07 +01:00
SChernykh
4941b494cc p2pool: update to v3.1 2023-03-18 19:06:56 +01:00
selsta
5e949dbc15 wizard: add Ledger Stax 2023-03-17 21:38:21 +01:00
tobtoht
bdf14a2520 remove output blackballing 2023-03-03 14:02:58 +01:00
luigi1111
710e3f6948 Merge pull request #4109
56a91b2 docker: update hidapi to 0.13.1 on linux (selsta)
2023-02-25 14:54:37 -05:00
luigi1111
6ec9e24f2f Merge pull request #4120
a50491d build: prepare v0.18.2.0 (selsta)
2023-02-25 13:56:09 -05:00
luigi1111
cb9af349cd Merge pull request #4124
8a910ad DaemonManager: remove systemd check (plowsof)
2023-02-25 13:55:42 -05:00
luigi1111
c8687a961c Merge pull request #4121
e8020c8 cmake: fix windows deploy (selsta)
2023-02-25 13:55:14 -05:00
plowsof
8a910ad4c7 DaemonManager: remove systemd check 2023-02-21 00:53:48 +00:00
selsta
e8020c86df cmake: fix windows deploy 2023-02-19 01:29:17 +01:00
selsta
a50491d0b2 build: prepare v0.18.2.0 2023-02-18 21:49:51 +01:00
luigi1111
bdd91b053d Merge pull request #4113
7d2f2ca Utils.js simplify ago func (backfire-monism-net)
2023-02-15 10:53:13 -05:00
luigi1111
4b23148e68 Merge pull request #4112
500dc57 p2pool: update to v3.0 (SChernykh)
2023-02-15 10:52:48 -05:00
luigi1111
e167bbce20 Merge pull request #4103
c437dab docker: update Windows and Linux Qt to 5.15.8 (selsta)
2023-02-15 10:52:02 -05:00
luigi1111
3338bc3741 Merge pull request #4092
587ea68 p2pool: Stop p2pool mining on node switch (devhyper)
2023-02-15 10:51:37 -05:00
luigi1111
af368c93ce Merge pull request #3936
757bc7d p2pool: Restart monerod only when needed and with proper args (devhyper)
2023-02-15 10:51:05 -05:00
luigi1111
5ced4ef547 Merge pull request #3878
198dfb3 wizard: redesign seed page (rating89us)
2023-02-15 10:50:11 -05:00
rating89us
198dfb338c wizard: redesign seed page
- move mnemonic seed
- restore height into a separate page
- pdf template
- seed verification
- responsive UI
- accessibility
2023-02-12 23:25:49 +01:00
devhyper
587ea68a99 p2pool: Stop p2pool mining on node switch 2023-02-02 17:32:06 -08:00
backfire-monism-net
7d2f2cacbf Utils.js simplify ago func 2023-02-01 00:35:13 -08:00
devhyper
757bc7d7b9 p2pool: Restart monerod only when needed and with proper args 2023-01-31 18:23:20 -08:00
SChernykh
500dc573e4 p2pool: update to v3.0 2023-01-31 19:16:24 +01:00
selsta
56a91b2d1b docker: update hidapi to 0.13.1 on linux 2023-01-25 20:09:55 +01:00
selsta
c437dab90f docker: update Windows and Linux Qt to 5.15.8 2023-01-16 17:56:15 +01:00
luigi1111
b7ba9437d8 Merge pull request #4095
7095061 p2pool: update to v2.7 (SChernykh)
2023-01-11 12:18:46 -05:00
luigi1111
76fa06ceab Merge pull request #4091
a3b54a9 Override desktop theming (devhyper)
2023-01-11 12:17:33 -05:00
luigi1111
4487471ada Merge pull request #4088
a01dc06 open-wallet: set network type when using file browser (plowsof)
2023-01-11 12:16:55 -05:00
luigi1111
55a0bc46e4 Merge pull request #4085
c8127f6 main: skip proxy when setting localhost remote node (selsta)
2023-01-11 12:16:27 -05:00
luigi1111
3e17445a4d Merge pull request #4082
4cc6bcb README: add unbound for Windows (selsta)
2023-01-11 12:15:55 -05:00
luigi1111
fc077fa54e Merge pull request #4079
8b682fb workflows: remove unnecessary dependency (selsta)
2023-01-11 12:15:30 -05:00
SChernykh
70950619b8 p2pool: update to v2.7 2023-01-03 21:35:19 +01:00
plowsof
a01dc06a54 open-wallet: set network type when using file browser
Co-authored-by: selsta <selsta@users.noreply.github.com>
2022-12-28 18:46:22 +00:00
devhyper
a3b54a942c Override desktop theming 2022-12-26 11:24:23 +01:00
selsta
c8127f651d main: skip proxy when setting localhost remote node 2022-12-18 17:51:19 +01:00
selsta
4cc6bcbd7d README: add unbound for Windows 2022-12-03 23:22:29 +01:00
selsta
8b682fbd2b workflows: remove unnecessary dependency 2022-12-03 04:35:53 +01:00
luigi1111
48393db2c7 Merge pull request #4078
a9b52f6 Sign/Verify: clear text fields on wallet close (plowsof)
2022-12-01 23:49:50 -06:00
luigi1111
faa4473b17 Merge pull request #4077
7faec48 History: add open folder button after CSV export (selsta)
2022-12-01 23:49:25 -06:00
luigi1111
9924dfe8af Merge pull request #4066
6984bb8 docker: update Qt to 5.15.7 (selsta)
2022-12-01 23:48:54 -06:00
luigi1111
47f336bf33 Merge pull request #4065
c0a739c Transfer: update mixin, silence warning (selsta)
2022-12-01 23:48:33 -06:00
luigi1111
07b75fb692 Merge pull request #4064
2d25454 docker: update zlib on android (selsta)
2022-12-01 23:48:05 -06:00
luigi1111
6c39e82519 Merge pull request #4062
2fa79c6 workflows: verify p2pool hashes (plowsof)
2022-12-01 23:45:58 -06:00
luigi1111
f8178f2e54 Merge pull request #4061
4743e44 deploy: update libicu to 72 (selsta)
2022-12-01 23:45:24 -06:00
luigi1111
75290d2454 Merge pull request #4060
9e2ae68 p2pool: update to 2.6 (selsta)
2022-12-01 23:45:02 -06:00
luigi1111
b180ac8cab Merge pull request #4059
43cc666 README: update Debian dependencies (2l47)
2022-12-01 23:44:28 -06:00
luigi1111
58c7c9ab76 Merge pull request #4055
c390afd main: fix a potential warning (selsta)
2022-12-01 23:43:46 -06:00
luigi1111
b8e6cb221b Merge pull request #4048
83921a4 main: update blockchain size (selsta)
2022-12-01 23:42:49 -06:00
luigi1111
ef2e711e15 Merge pull request #4047
80ade41 DaemonManager: take dataDir into account when sending cmd (selsta)
2022-12-01 23:42:04 -06:00
luigi1111
2ade733867 Merge pull request #4043
7954661 Android: disable simple mode (malinero)
22a1509 Android: hide local node settings (malinero)
499eeee Android: hide log tab (malinero)
8cf76cf Android: hide mining tab (malinero)
6441d99 Android: useRemoteNode default to true (malinero)
2022-12-01 23:40:39 -06:00
luigi1111
1735154b81 Merge pull request #3616
acf876f Docker android: avoid gradle auto download (malinero)
2022-12-01 23:39:28 -06:00
plowsof
a9b52f6752 Sign/Verify: clear text fields on wallet close 2022-12-02 05:32:25 +00:00
selsta
7faec48c0a History: add open folder button after CSV export 2022-12-02 05:56:51 +01:00
selsta
9e2ae684ed p2pool: update to 2.6 2022-11-30 05:30:00 +01:00
selsta
6984bb8113 docker: update Qt to 5.15.7 2022-11-13 02:57:50 +01:00
selsta
c0a739c9fa Transfer: update mixin, silence warning 2022-11-11 01:59:28 +01:00
selsta
2d254542f3 docker: update zlib on android 2022-11-07 06:16:38 +01:00
plowsof
2fa79c670e workflows: verify p2pool hashes 2022-11-04 00:45:35 +00:00
selsta
4743e443dc deploy: update libicu to 72 2022-11-01 00:11:42 +01:00
2l47
43cc666e77 README: update Debian dependencies 2022-10-31 17:07:26 -05:00
j-berman
1215a6e5d8 Assume untrusted daemon in simple mode 2022-10-29 14:25:20 -05:00
j-berman
499c2a47fc qsTr scan tx error 2022-10-29 14:22:37 -05:00
selsta
c390afd258 main: fix a potential warning 2022-10-29 04:55:01 +02:00
j-berman
3b0e66a3d0 Display clear error when user scans older tx via untrusted daemon 2022-10-28 16:14:31 -05:00
j-berman
4cd6652825 Update balance after calling scan_tx 2022-10-20 16:23:10 -05:00
selsta
80ade41905 DaemonManager: take dataDir into account when sending cmd 2022-10-07 02:28:44 +02:00
selsta
83921a4bc8 main: update blockchain size 2022-10-07 02:00:28 +02:00
malinero
acf876f4b2 Docker android: avoid gradle auto download 2022-10-02 11:06:57 +02:00
malinero
7954661100 Android: disable simple mode 2022-10-02 10:40:07 +02:00
malinero
22a1509316 Android: hide local node settings 2022-10-02 10:40:07 +02:00
malinero
499eeee59a Android: hide log tab 2022-10-02 10:40:07 +02:00
malinero
8cf76cf7c2 Android: hide mining tab 2022-10-02 10:40:07 +02:00
malinero
6441d99279 Android: useRemoteNode default to true 2022-10-02 10:39:48 +02:00
luigi1111
aef4a982dc Merge pull request #4042
df9b35e build: prepare v0.18.1.2 (selsta)
2022-09-28 14:22:34 -05:00
luigi1111
f93c67740c Merge pull request #4041
ff0c068 Android: disable asking for desktop entry (malinero)
2022-09-28 14:22:14 -05:00
luigi1111
4b8e0f36ab Merge pull request #4040
b801ef5 Use different colors for different subaccounts (rating89us)
2022-09-28 14:21:49 -05:00
luigi1111
c247b96c4a Merge pull request #4039
6a8a123 workflows: fix windows ci deploy (selsta)
2022-09-28 14:21:22 -05:00
luigi1111
085f4af1dc Merge pull request #4036
6f2aafd Fix behavior when switching nodes (j-berman)
2022-09-28 14:20:56 -05:00
luigi1111
49a6c8ba9c Merge pull request #3615
96b6e59 Github workflow android: remove obsolete docker layers (malinero)
1b119eb Docker android: update Qt to 5.15.6 (and API level to 29) (malinero)
64a6ca7 Docker android: upgrade base image (malinero)
8b35660 Docker android: bump libraries (malinero)
131154b Docker android: update SDK and NDK (malinero)
2022-09-28 14:20:22 -05:00
selsta
df9b35e947 build: prepare v0.18.1.2 2022-09-28 01:15:03 +02:00
malinero
96b6e5972f Github workflow android: remove obsolete docker layers 2022-09-27 21:06:16 +02:00
rating89us
b801ef594b Use different colors for different subaccounts 2022-09-26 10:18:46 +02:00
malinero
ff0c068cb8 Android: disable asking for desktop entry 2022-09-25 11:33:23 +02:00
malinero
1b119eb8f5 Docker android: update Qt to 5.15.6 (and API level to 29) 2022-09-25 10:32:33 +02:00
selsta
6a8a123da8 workflows: fix windows ci deploy 2022-09-22 13:08:42 +02:00
j-berman
6f2aafdd6c Fix behavior when switching nodes
- Improved synchronization when switching nodes
- Avoid infinite "Connecting" loop
- Pause refresh loop while switching, don't start until connected
2022-09-21 21:56:55 -06:00
malinero
64a6ca7fc7 Docker android: upgrade base image 2022-09-18 11:34:41 +02:00
malinero
8b356605b4 Docker android: bump libraries 2022-09-18 11:34:41 +02:00
malinero
131154ba80 Docker android: update SDK and NDK 2022-09-18 08:16:54 +02:00
95 changed files with 25553 additions and 799 deletions

107
.github/verify_p2pool.py vendored Normal file
View File

@@ -0,0 +1,107 @@
import requests
import subprocess
from urllib.request import urlretrieve
import difflib
sech_key = "https://p2pool.io/SChernykh.asc"
sech_key_backup = "https://raw.githubusercontent.com/monero-project/gitian.sigs/master/gitian-pubkeys/SChernykh.asc"
sech_key_fp = "1FCA AB4D 3DC3 310D 16CB D508 C47F 82B5 4DA8 7ADF"
p2pool_files = [{
"os": "WIN",
"filename": "windows-x64.zip",
},
{
"os": "LINUX",
"filename": "linux-x64.tar.gz"
},
{
"os": "MACOS_AARCH64",
"filename": "macos-aarch64.tar.gz",
},
{
"os": "MACOS",
"filename": "macos-x64.tar.gz",
}]
def get_hash(fname):
fhash = subprocess.check_output(["sha256sum", fname]).decode("utf-8")
print(fhash.strip())
return fhash.split()[0]
def main():
global p2pool_files, sech_key, sech_key_backup, sech_key_fp
p2pool_tag_api = "https://api.github.com/repos/SChernykh/p2pool/releases/latest"
data = requests.get(p2pool_tag_api).json()
tag = data["tag_name"]
head = f"p2pool-{tag}-"
url = f"https://github.com/SChernykh/p2pool/releases/download/{tag}/"
try:
urlretrieve(sech_key,"SChernykh.asc")
except:
urlretrieve(sech_key_backup,"SChernykh.asc")
urlretrieve(f"{url}sha256sums.txt.asc","sha256sums.txt.asc")
subprocess.check_call(["gpg", "--import", "SChernykh.asc"])
subprocess.check_call(["gpg", "--verify", "sha256sums.txt.asc"])
fingerprint = subprocess.check_output(["gpg","--fingerprint", "SChernykh"]).decode("utf-8").splitlines()[1].strip()
assert fingerprint == sech_key_fp
with open("sha256sums.txt.asc","r") as f:
lines = f.readlines()
signed_hashes = {}
for line in lines:
if "Name:" in line:
signed_fname = line.split()[1]
if "SHA256:" in line:
signed_hashes[signed_fname] = line.split()[1].lower()
expected = ""
for i in range(len(p2pool_files)):
fname = p2pool_files[i]["filename"]
str_os =p2pool_files[i]["os"]
dl = f"{url}{head}{fname}"
urlretrieve(dl,f"{head}{fname}")
fhash = get_hash(f"{head}{fname}")
assert signed_hashes[f"{head}{fname}"] == fhash
if i == 0:
expected += f" #ifdef Q_OS_{str_os}\n"
else:
expected += f" #elif defined(Q_OS_{str_os})\n"
expected += f" url = \"https://github.com/SChernykh/p2pool/releases/download/{tag}/{head}{fname}\";\n"
expected += f" fileName = m_p2poolPath + \"/{head}{fname}\";\n"
expected += f" validHash = \"{fhash}\";\n"
expected += " #endif\n"
print(f"Expected:\n{expected}")
with open("src/p2pool/P2PoolManager.cpp","r") as f:
p2pool_lines = f.readlines()
unexpected = ""
ignore = 1
for line in p2pool_lines:
if ignore == 0:
unexpected += line
if "QString validHash;" in line:
ignore = 0
if "#endif" in line and ignore == 0:
break
d = difflib.Differ()
diff = d.compare(str(unexpected).splitlines(True),str(expected).splitlines(True))
print("Unexpected:")
for i in diff:
if i.startswith("?"):
continue
print(i.replace("\n",""))
assert unexpected == expected
if __name__ == "__main__":
main()

View File

@@ -34,7 +34,7 @@ jobs:
- 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 libprotobuf-dev protobuf-compiler
- name: install monero gui dependencies
run: sudo apt -y install qtbase5-dev qt5-default qtdeclarative5-dev qml-module-qtqml-models2 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-platform qml-module-qt-labs-folderlistmodel qttools5-dev-tools qml-module-qtquick-templates2 libqt5svg5-dev libgcrypt20-dev xvfb
run: sudo apt -y install qtbase5-dev qtdeclarative5-dev qml-module-qtqml-models2 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-platform qml-module-qt-labs-folderlistmodel qttools5-dev-tools qml-module-qtquick-templates2 libqt5svg5-dev libgcrypt20-dev xvfb
- name: build
run: DEV_MODE=ON make release -j3
- name: test qml
@@ -52,7 +52,7 @@ jobs:
- uses: eine/setup-msys2@v2
with:
update: true
install: mingw-w64-x86_64-toolchain make mingw-w64-x86_64-cmake mingw-w64-x86_64-boost mingw-w64-x86_64-openssl mingw-w64-x86_64-zeromq mingw-w64-x86_64-libsodium mingw-w64-x86_64-hidapi mingw-w64-x86_64-protobuf-c mingw-w64-x86_64-libusb mingw-w64-x86_64-unbound git mingw-w64-x86_64-qt5 mingw-w64-x86_64-libgcrypt
install: mingw-w64-x86_64-toolchain make mingw-w64-x86_64-pcre mingw-w64-x86_64-cmake mingw-w64-x86_64-boost mingw-w64-x86_64-openssl mingw-w64-x86_64-zeromq mingw-w64-x86_64-libsodium mingw-w64-x86_64-hidapi mingw-w64-x86_64-protobuf-c mingw-w64-x86_64-libusb mingw-w64-x86_64-unbound git mingw-w64-x86_64-qt5 mingw-w64-x86_64-libgcrypt
- name: build
run: DEV_MODE=ON make release-win64 -j2
- name: deploy
@@ -75,19 +75,22 @@ jobs:
run: python3 monero-gui/.github/qt_helper.py mac_x64 desktop 5.15.2 clang_64 c384008156fe63cc183bade0316828c598ff3e5074397c0c9ccc588d6cdc5aca
working-directory: ../
- name: build
run: CMAKE_PREFIX_PATH=/Users/runner/work/monero-gui/5.15.2/clang_64 make release -j3
run: |
mkdir build && cd build
cmake -D CMAKE_BUILD_TYPE=Release -D ARCH=default -D CMAKE_PREFIX_PATH=/Users/runner/work/monero-gui/5.15.2/clang_64 ..
make
- name: deploy
run: make deploy
working-directory: build/release
working-directory: build
- name: test qml
run: build/release/bin/monero-wallet-gui.app/Contents/MacOS/monero-wallet-gui --test-qml
run: build/bin/monero-wallet-gui.app/Contents/MacOS/monero-wallet-gui --test-qml
- name: create .tar
run: tar -cf monero-wallet-gui.tar monero-wallet-gui.app
working-directory: build/release/bin
working-directory: build/bin
- uses: actions/upload-artifact@v2
with:
name: ${{ github.job }}
path: build/release/bin/monero-wallet-gui.tar
path: build/bin/monero-wallet-gui.tar
docker-linux-static:
runs-on: ubuntu-20.04
@@ -162,6 +165,8 @@ jobs:
run: docker build --tag monero:build-env-android --build-arg THREADS=3 --file Dockerfile.android .
- name: build
run: docker run --rm -v /home/runner/work/monero-gui/monero-gui:/monero-gui -e THREADS=3 monero:build-env-android
- name: Remove obsolete docker layers
run: docker images -a | grep none | awk '{ print $3; }' | xargs docker rmi || true
- uses: actions/upload-artifact@v2
with:
name: ${{ github.job }}

174
.github/workflows/flatpak.yml vendored Normal file
View File

@@ -0,0 +1,174 @@
name: Flatpak
on:
release:
types: released
jobs:
part1:
name: Part 1/3
if: github.repository == 'monero-project/monero-gui'
runs-on: ubuntu-latest
container:
image: bilelmoussaoui/flatpak-github-actions:kde-5.15-22.08
options: --privileged
strategy:
matrix:
arch: [x86_64, aarch64]
steps:
- name: Checkout
uses: actions/checkout@v3
with:
submodules: recursive
- name: Install deps
run: dnf -y install docker
- name: Setup QEMU
uses: docker/setup-qemu-action@v2
with:
platforms: arm64
- name: Build flatpak
uses: flatpak/flatpak-github-actions/flatpak-builder@v6
env:
FLATPAK_BUILDER_N_JOBS: 3
with:
manifest-path: share/org.getmonero.Monero.yaml
arch: ${{ matrix.arch }}
cache: false
stop-at-module: boost
- name: Tar flatpak-builder
run: tar -cvf flatpak-builder.tar .flatpak-builder
- name: Save flatpak-builder
uses: actions/upload-artifact@v3
with:
name: flatpak-builder-${{ matrix.arch }}
path: flatpak-builder.tar
part2:
name: Part 2/3
if: github.repository == 'monero-project/monero-gui'
needs: part1
runs-on: ubuntu-latest
container:
image: bilelmoussaoui/flatpak-github-actions:kde-5.15-22.08
options: --privileged
strategy:
matrix:
arch: [x86_64, aarch64]
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Install deps
run: dnf -y install docker
- name: Setup QEMU
uses: docker/setup-qemu-action@v2
with:
platforms: arm64
- name: Restore flatpak-builder
uses: actions/download-artifact@v3
with:
name: flatpak-builder-${{ matrix.arch }}
- name: Untar flatpak-builder
run: tar -xvf flatpak-builder.tar
- name: Build flatpak
uses: flatpak/flatpak-github-actions/flatpak-builder@v6
env:
FLATPAK_BUILDER_N_JOBS: 3
with:
manifest-path: share/org.getmonero.Monero.yaml
arch: ${{ matrix.arch }}
cache: false
stop-at-module: monero-gui
- name: Tar flatpak-builder
run: tar -cvf flatpak-builder.tar .flatpak-builder
- name: Save flatpak-builder
uses: actions/upload-artifact@v3
with:
name: flatpak-builder-${{ matrix.arch }}
path: flatpak-builder.tar
part3:
name: Part 3/3
if: github.repository == 'monero-project/monero-gui'
needs: [part1, part2]
runs-on: ubuntu-latest
container:
image: bilelmoussaoui/flatpak-github-actions:kde-5.15-22.08
options: --privileged
strategy:
matrix:
arch: [x86_64, aarch64]
steps:
- name: Checkout
uses: actions/checkout@v3
with:
submodules: recursive
- name: Add version and date
run: |
sed -i 's/<version>/${{ github.event.release.tag_name }}/g' $GITHUB_WORKSPACE/share/org.getmonero.Monero.metainfo.xml
sed -i 's/<date>/'"$(date '+%F')"'/g' $GITHUB_WORKSPACE/share/org.getmonero.Monero.metainfo.xml
- name: Install deps
run: dnf -y install docker
- name: Setup QEMU
uses: docker/setup-qemu-action@v2
with:
platforms: arm64
- name: Restore flatpak-builder
uses: actions/download-artifact@v3
with:
name: flatpak-builder-${{ matrix.arch }}
- name: Untar flatpak-builder
run: tar -xvf flatpak-builder.tar
- name: Build flatpak
uses: flatpak/flatpak-github-actions/flatpak-builder@v6
env:
FLATPAK_BUILDER_N_JOBS: 3
with:
manifest-path: share/org.getmonero.Monero.yaml
arch: ${{ matrix.arch }}
cache: false
- name: Validate AppData
working-directory: flatpak_app/files/share/appdata
run: appstream-util validate org.getmonero.Monero.appdata.xml
- name: Delete flatpak-builder
uses: geekyeggo/delete-artifact@v2
with:
name: flatpak-builder-${{ matrix.arch }}
- name: Print hashes
working-directory: flatpak_app/files/bin
run: |
echo "Hashes of the ${{ matrix.arch }} binaries:" >> $GITHUB_STEP_SUMMARY
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
for bin in monero-blockchain-ancestry monero-blockchain-depth monero-blockchain-export monero-blockchain-import monero-blockchain-mark-spent-outputs monero-blockchain-prune monero-blockchain-prune-known-spent-data monero-blockchain-stats monero-blockchain-usage monerod monero-gen-ssl-cert monero-gen-trusted-multisig monero-wallet-cli monero-wallet-gui monero-wallet-rpc p2pool; do sha256sum $bin; done >> $GITHUB_STEP_SUMMARY
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
echo "An example command to check hashes:" >> $GITHUB_STEP_SUMMARY
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
echo "$ flatpak run --command=sha256sum org.getmonero.Monero /app/bin/monero-wallet-gui" >> $GITHUB_STEP_SUMMARY
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
- name: Publish to Flathub Beta
uses: flatpak/flatpak-github-actions/flat-manager@v6
with:
flat-manager-url: https://hub.flathub.org
repository: beta
token: ${{ secrets.FLATHUB_ }}

16
.github/workflows/verify_p2pool.yml vendored Normal file
View File

@@ -0,0 +1,16 @@
name: ci/gh-actions/verify
on:
push:
paths:
- 'src/p2pool/P2PoolManager.cpp'
pull_request:
paths:
- 'src/p2pool/P2PoolManager.cpp'
jobs:
p2pool-hashes:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Verify Hashes
run: |
python3 .github/verify_p2pool.py

View File

@@ -4,8 +4,8 @@ project(monero-gui)
message(STATUS "Initiating compile using CMake ${CMAKE_VERSION}")
set(VERSION_MAJOR "18")
set(VERSION_MINOR "1")
set(VERSION_REVISION "1")
set(VERSION_MINOR "3")
set(VERSION_REVISION "0")
set(VERSION "0.${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_REVISION}")
option(STATIC "Link libraries statically, requires static Qt")

View File

@@ -1,47 +1,50 @@
FROM debian:stretch
FROM debian:buster
ARG THREADS=1
ARG ANDROID_NDK_REVISION=21d
ARG ANDROID_NDK_HASH=bcf4023eb8cb6976a4c7cff0a8a8f145f162bf4d
ARG ANDROID_SDK_REVISION=4333796
ARG ANDROID_SDK_HASH=92ffee5a1d98d856634e8b71132e8a95d96c83a63fde1099be3d86df3106def9
ARG QT_VERSION=5.15.2
ARG ANDROID_NDK_REVISION=21e
ARG ANDROID_NDK_HASH=c3ebc83c96a4d7f539bd72c241b2be9dcd29bda9
ARG ANDROID_SDK_REVISION=7302050_latest
ARG ANDROID_SDK_HASH=7a00faadc0864f78edd8f4908a629a46d622375cbe2e5814e82934aebecdb622
ARG QT_VERSION=v5.15.7-lts-lgpl
WORKDIR /opt/android
ENV WORKDIR=/opt/android
ENV ANDROID_NATIVE_API_LEVEL=28
ENV ANDROID_NATIVE_API_LEVEL=30
ENV ANDROID_API=android-${ANDROID_NATIVE_API_LEVEL}
ENV ANDROID_CLANG=aarch64-linux-android${ANDROID_NATIVE_API_LEVEL}-clang
ENV ANDROID_CLANGPP=aarch64-linux-android${ANDROID_NATIVE_API_LEVEL}-clang++
ENV ANDROID_NDK_ROOT=${WORKDIR}/android-ndk-r${ANDROID_NDK_REVISION}
ENV ANDROID_SDK_ROOT=${WORKDIR}/tools
ENV JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
ENV ANDROID_SDK_ROOT=${WORKDIR}/cmdline-tools
ENV JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64
ENV PATH=${JAVA_HOME}/bin:${PATH}
ENV PREFIX=${WORKDIR}/prefix
ENV TOOLCHAIN_DIR=${ANDROID_NDK_ROOT}/toolchains/llvm/prebuilt/linux-x86_64
RUN apt-get update \
&& apt-get install -y ant automake build-essential ca-certificates-java file gettext git libc6 libncurses5 \
libssl-dev libstdc++6 libtinfo5 libtool libz1 openjdk-8-jdk-headless openjdk-8-jre-headless pkg-config python3 \
libssl-dev libstdc++6 libtinfo5 libtool libz1 openjdk-11-jdk-headless openjdk-11-jre-headless pkg-config python3 \
unzip wget
RUN wget -q https://dl.google.com/android/repository/sdk-tools-linux-${ANDROID_SDK_REVISION}.zip \
&& unzip -q sdk-tools-linux-${ANDROID_SDK_REVISION}.zip \
&& rm -f sdk-tools-linux-${ANDROID_SDK_REVISION}.zip
RUN PACKAGE_NAME=commandlinetools-linux-${ANDROID_SDK_REVISION}.zip \
&& wget -q https://dl.google.com/android/repository/${PACKAGE_NAME} \
&& echo "${ANDROID_SDK_HASH} ${PACKAGE_NAME}" | sha256sum -c \
&& unzip -q ${PACKAGE_NAME} \
&& rm -f ${PACKAGE_NAME}
RUN wget -q https://dl.google.com/android/repository/android-ndk-r${ANDROID_NDK_REVISION}-linux-x86_64.zip \
&& unzip -q android-ndk-r${ANDROID_NDK_REVISION}-linux-x86_64.zip \
&& rm -f android-ndk-r${ANDROID_NDK_REVISION}-linux-x86_64.zip
RUN PACKAGE_NAME=android-ndk-r${ANDROID_NDK_REVISION}-linux-x86_64.zip \
&& wget -q https://dl.google.com/android/repository/${PACKAGE_NAME} \
&& echo "${ANDROID_NDK_HASH} ${PACKAGE_NAME}" | sha1sum -c \
&& unzip -q ${PACKAGE_NAME} \
&& rm -f ${PACKAGE_NAME}
RUN cd ${ANDROID_SDK_ROOT} && echo y | ./bin/sdkmanager "platform-tools" "platforms;${ANDROID_API}" "tools" > /dev/null
RUN cp -r ${WORKDIR}/platforms ${WORKDIR}/platform-tools ${ANDROID_SDK_ROOT}
RUN echo y | ${ANDROID_SDK_ROOT}/bin/sdkmanager --sdk_root=${ANDROID_SDK_ROOT} "build-tools;28.0.3" "platforms;${ANDROID_API}" "tools" > /dev/null
ENV HOST_PATH=${PATH}
ENV PATH=${TOOLCHAIN_DIR}/aarch64-linux-android/bin:${TOOLCHAIN_DIR}/bin:${PATH}
ARG ZLIB_VERSION=1.2.12
ARG ZLIB_HASH=91844808532e5ce316b3c010929493c0244f3d37593afd6de04f71821d5136d9
ARG ZLIB_VERSION=1.3
ARG ZLIB_HASH=ff0ba4c292013dbc27530b3a81e1f9a813cd39de01ca5e0f8bf355702efa593e
RUN wget -q https://zlib.net/zlib-${ZLIB_VERSION}.tar.gz \
&& echo "${ZLIB_HASH} zlib-${ZLIB_VERSION}.tar.gz" | sha256sum -c \
&& tar -xzf zlib-${ZLIB_VERSION}.tar.gz \
@@ -76,7 +79,6 @@ RUN git clone git://code.qt.io/qt/qt5.git -b ${QT_VERSION} --depth 1 \
-skip qtpurchasing \
-skip qtgamepad -skip qtscript -skip qtdoc \
-no-warnings-are-errors \
&& sed -i '213,215d' qtbase/src/3rdparty/pcre2/src/sljit/sljitConfigInternal.h \
&& PATH=${HOST_PATH} make -j${THREADS} \
&& PATH=${HOST_PATH} make -j${THREADS} install \
&& cd qttools/src/linguist/lrelease \
@@ -99,7 +101,7 @@ RUN wget -q http://ftp.gnu.org/pub/gnu/libiconv/libiconv-${ICONV_VERSION}.tar.gz
ARG BOOST_VERSION=1_74_0
ARG BOOST_VERSION_DOT=1.74.0
ARG BOOST_HASH=83bfc1507731a0906e387fc28b7ef5417d591429e51e788417fe9ff025e116b1
RUN wget -q https://downloads.sourceforge.net/project/boost/boost/${BOOST_VERSION_DOT}/boost_${BOOST_VERSION}.tar.bz2 \
RUN wget -q https://boostorg.jfrog.io/artifactory/main/release/${BOOST_VERSION_DOT}/source/boost_${BOOST_VERSION}.tar.bz2 \
&& echo "${BOOST_HASH} boost_${BOOST_VERSION}.tar.bz2" | sha256sum -c \
&& tar -xf boost_${BOOST_VERSION}.tar.bz2 \
&& rm -f boost_${BOOST_VERSION}.tar.bz2 \
@@ -115,8 +117,8 @@ RUN wget -q https://downloads.sourceforge.net/project/boost/boost/${BOOST_VERSIO
install -j${THREADS} \
&& rm -rf $(pwd)
ARG OPENSSL_VERSION=1.1.1q
ARG OPENSSL_HASH=d7939ce614029cdff0b6c20f0e2e5703158a489a72b2507b8bd51bf8c8fd10ca
ARG OPENSSL_VERSION=1.1.1u
ARG OPENSSL_HASH=e2f8d84b523eecd06c7be7626830370300fbcc15386bf5142d72758f6963ebc6
RUN wget -q https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz \
&& echo "${OPENSSL_HASH} openssl-${OPENSSL_VERSION}.tar.gz" | sha256sum -c \
&& tar -xzf openssl-${OPENSSL_VERSION}.tar.gz \
@@ -143,8 +145,8 @@ RUN wget https://github.com/libexpat/libexpat/releases/download/R_2_4_1/expat-${
make -j$THREADS install && \
rm -rf $(pwd)
ARG UNBOUND_VERSION=1.13.2
ARG UNBOUND_HASH=0a13b547f3b92a026b5ebd0423f54c991e5718037fd9f72445817f6a040e1a83
ARG UNBOUND_VERSION=1.16.2
ARG UNBOUND_HASH=2e32f283820c24c51ca1dd8afecfdb747c7385a137abe865c99db4b257403581
RUN wget https://www.nlnetlabs.nl/downloads/unbound/unbound-${UNBOUND_VERSION}.tar.gz && \
echo "${UNBOUND_HASH} unbound-${UNBOUND_VERSION}.tar.gz" | sha256sum -c && \
tar -xzf unbound-${UNBOUND_VERSION}.tar.gz && \
@@ -155,8 +157,8 @@ RUN wget https://www.nlnetlabs.nl/downloads/unbound/unbound-${UNBOUND_VERSION}.t
make -j$THREADS install && \
rm -rf $(pwd)
ARG ZMQ_VERSION=v4.3.3
ARG ZMQ_HASH=04f5bbedee58c538934374dc45182d8fc5926fa3
ARG ZMQ_VERSION=v4.3.4
ARG ZMQ_HASH=4097855ddaaa65ed7b5e8cb86d143842a594eebd
RUN git clone https://github.com/zeromq/libzmq.git -b ${ZMQ_VERSION} --depth 1 \
&& cd libzmq \
&& git checkout ${ZMQ_HASH} \
@@ -178,38 +180,42 @@ RUN set -ex \
&& make -j${THREADS} install \
&& rm -rf $(pwd)
RUN git clone -b libgpg-error-1.38 --depth 1 git://git.gnupg.org/libgpg-error.git \
RUN git clone -b libgpg-error-1.41 --depth 1 git://git.gnupg.org/libgpg-error.git \
&& cd libgpg-error \
&& git reset --hard 71d278824c5fe61865f7927a2ed1aa3115f9e439 \
&& git reset --hard 98032624ae89a67ee6fe3b1db5d95032e681d163 \
&& ./autogen.sh \
&& CC=${ANDROID_CLANG} CXX=${ANDROID_CLANGPP} ./configure --host=aarch64-linux-android --prefix=${PREFIX} --disable-rpath --disable-shared --enable-static --disable-doc --disable-tests \
&& PATH=${TOOLCHAIN_DIR}/bin:${HOST_PATH} make -j${THREADS} \
&& make -j${THREADS} install \
&& rm -rf $(pwd)
RUN git clone -b libgcrypt-1.8.5 --depth 1 git://git.gnupg.org/libgcrypt.git \
RUN git clone -b libgcrypt-1.10.1 --depth 1 git://git.gnupg.org/libgcrypt.git \
&& cd libgcrypt \
&& git reset --hard 56606331bc2a80536db9fc11ad53695126007298 \
&& git reset --hard ae0e567820c37f9640440b3cff77d7c185aa6742 \
&& ./autogen.sh \
&& CC=${ANDROID_CLANG} CXX=${ANDROID_CLANGPP} ./configure --host=aarch64-linux-android --prefix=${PREFIX} --with-gpg-error-prefix=${PREFIX} --disable-shared --enable-static --disable-doc --disable-tests \
&& PATH=${TOOLCHAIN_DIR}/bin:${HOST_PATH} make -j${THREADS} \
&& make -j${THREADS} install \
&& rm -rf $(pwd)
RUN cd tools \
&& wget -q http://dl-ssl.google.com/android/repository/tools_r25.2.5-linux.zip \
&& unzip -q tools_r25.2.5-linux.zip \
&& rm -f tools_r25.2.5-linux.zip \
&& echo y | ${ANDROID_SDK_ROOT}/tools/android update sdk --no-ui --all --filter build-tools-28.0.3
RUN git clone -b v3.19.7 --depth 1 https://github.com/Kitware/CMake \
RUN git clone -b v3.24.2 --depth 1 https://github.com/Kitware/CMake \
&& cd CMake \
&& git reset --hard 22612dd53a46c7f9b4c3f4b7dbe5c78f9afd9581 \
&& git reset --hard 31f835410efeea50acd43512eb9e5646a26ea177 \
&& PATH=${HOST_PATH} ./bootstrap \
&& PATH=${HOST_PATH} make -j${THREADS} \
&& PATH=${HOST_PATH} make -j${THREADS} install \
&& rm -rf $(pwd)
RUN GRADLE_VERSION=5.6.4 \
&& GRADLE_HASH=1f3067073041bc44554d0efe5d402a33bc3d3c93cc39ab684f308586d732a80d \
&& wget -q https\://services.gradle.org/distributions/gradle-${GRADLE_VERSION}-bin.zip \
&& echo "${GRADLE_HASH} gradle-${GRADLE_VERSION}-bin.zip" | sha256sum -c \
&& GRADLE_LOCAL_PATH=gradle/wrapper/dists/gradle-${GRADLE_VERSION}-bin/bxirm19lnfz6nurbatndyydux \
&& mkdir -p ${GRADLE_LOCAL_PATH} \
&& mv gradle-${GRADLE_VERSION}-bin.zip ${GRADLE_LOCAL_PATH}
ENV GRADLE_USER_HOME=${WORKDIR}/gradle
CMD set -ex \
&& cd /monero-gui \
&& mkdir -p build/Android/release \
@@ -226,7 +232,9 @@ CMD set -ex \
-DBoost_USE_STATIC_RUNTIME=ON \
-DLRELEASE_PATH="${PREFIX}/bin" \
-DQT_ANDROID_APPLICATION_BINARY="monero-wallet-gui" \
-DANDROID_SDK="${ANDROID_SDK_ROOT}" \
-DWITH_SCANNER=ON \
-DWITH_DESKTOP_ENTRY=OFF \
../../.. \
&& PATH=${HOST_PATH} make generate_translations_header \
&& make -j${THREADS} -C src \

View File

@@ -1,7 +1,7 @@
FROM ubuntu:16.04
ARG THREADS=1
ARG QT_VERSION=v5.15.6-lts-lgpl
ARG QT_VERSION=v5.15.10-lts-lgpl
ENV CFLAGS="-fPIC"
ENV CPPFLAGS="-fPIC"
@@ -113,9 +113,9 @@ RUN git clone -b xkbcommon-0.5.0 --depth 1 https://github.com/xkbcommon/libxkbco
make -j$THREADS install && \
rm -rf $(pwd)
RUN git clone -b v1.2.11 --depth 1 https://github.com/madler/zlib && \
RUN git clone -b v1.3 --depth 1 https://github.com/madler/zlib && \
cd zlib && \
git reset --hard cacf7f1d4e3d44d871b605da3b647f07d718623f && \
git reset --hard 09155eaa2f9270dc4ed1fa13e2b4b2613e6e4851 && \
./configure --static && \
make -j$THREADS && \
make -j$THREADS install && \
@@ -130,11 +130,12 @@ RUN git clone -b VER-2-10-2 --depth 1 https://git.savannah.gnu.org/git/freetype/
make -j$THREADS install && \
rm -rf $(pwd)
RUN git clone -b R_2_2_9 --depth 1 https://github.com/libexpat/libexpat && \
cd libexpat/expat && \
git reset --hard a7bc26b69768f7fb24f0c7976fae24b157b85b13 && \
./buildconf.sh && \
./configure --disable-shared --enable-static && \
RUN wget https://github.com/libexpat/libexpat/releases/download/R_2_4_8/expat-2.4.8.tar.bz2 && \
echo "a247a7f6bbb21cf2ca81ea4cbb916bfb9717ca523631675f99b3d4a5678dcd16 expat-2.4.8.tar.bz2" | sha256sum -c && \
tar -xf expat-2.4.8.tar.bz2 && \
rm expat-2.4.8.tar.bz2 && \
cd expat-2.4.8 && \
./configure --enable-static --disable-shared --prefix=/usr && \
make -j$THREADS && \
make -j$THREADS install && \
rm -rf $(pwd)
@@ -164,26 +165,16 @@ RUN wget https://boostorg.jfrog.io/artifactory/main/release/1.80.0/source/boost_
./b2 --with-atomic --with-system --with-filesystem --with-thread --with-date_time --with-chrono --with-regex --with-serialization --with-program_options --with-locale variant=release link=static runtime-link=static cflags="${CFLAGS}" cxxflags="${CXXFLAGS}" install -a --prefix=/usr && \
rm -rf $(pwd)
RUN wget https://www.openssl.org/source/openssl-1.1.1q.tar.gz && \
echo "d7939ce614029cdff0b6c20f0e2e5703158a489a72b2507b8bd51bf8c8fd10ca openssl-1.1.1q.tar.gz" | sha256sum -c && \
tar -xzf openssl-1.1.1q.tar.gz && \
rm openssl-1.1.1q.tar.gz && \
cd openssl-1.1.1q && \
RUN wget https://www.openssl.org/source/openssl-1.1.1u.tar.gz && \
echo "e2f8d84b523eecd06c7be7626830370300fbcc15386bf5142d72758f6963ebc6 openssl-1.1.1u.tar.gz" | sha256sum -c && \
tar -xzf openssl-1.1.1u.tar.gz && \
rm openssl-1.1.1u.tar.gz && \
cd openssl-1.1.1u && \
./config no-asm no-shared no-zlib-dynamic --prefix=/usr --openssldir=/usr && \
make -j$THREADS && \
make -j$THREADS install && \
rm -rf $(pwd)
RUN wget https://github.com/libexpat/libexpat/releases/download/R_2_4_8/expat-2.4.8.tar.bz2 && \
echo "a247a7f6bbb21cf2ca81ea4cbb916bfb9717ca523631675f99b3d4a5678dcd16 expat-2.4.8.tar.bz2" | sha256sum -c && \
tar -xf expat-2.4.8.tar.bz2 && \
rm expat-2.4.8.tar.bz2 && \
cd expat-2.4.8 && \
./configure --enable-static --disable-shared --prefix=/usr && \
make -j$THREADS && \
make -j$THREADS install && \
rm -rf $(pwd)
RUN wget https://www.nlnetlabs.nl/downloads/unbound/unbound-1.16.2.tar.gz && \
echo "2e32f283820c24c51ca1dd8afecfdb747c7385a137abe865c99db4b257403581 unbound-1.16.2.tar.gz" | sha256sum -c && \
tar -xzf unbound-1.16.2.tar.gz && \
@@ -242,9 +233,9 @@ RUN git clone -b v1.0.26 --depth 1 https://github.com/libusb/libusb && \
make -j$THREADS install && \
rm -rf $(pwd)
RUN git clone -b hidapi-0.12.0 --depth 1 https://github.com/libusb/hidapi && \
RUN git clone -b hidapi-0.13.1 --depth 1 https://github.com/libusb/hidapi && \
cd hidapi && \
git reset --hard 76108294092c023a4ece99eb3219559cea0d5066 && \
git reset --hard 4ebce6b5059b086d05ca7e091ce04a5fd08ac3ac && \
./bootstrap && \
./configure --disable-shared --enable-static && \
make -j$THREADS && \

View File

@@ -1,7 +1,7 @@
FROM ubuntu:20.04
ARG THREADS=1
ARG QT_VERSION=v5.15.6-lts-lgpl
ARG QT_VERSION=v5.15.10-lts-lgpl
ENV SOURCE_DATE_EPOCH=1397818193
RUN apt update && \
@@ -12,9 +12,9 @@ RUN apt update && \
RUN update-alternatives --set x86_64-w64-mingw32-g++ $(which x86_64-w64-mingw32-g++-posix) && \
update-alternatives --set x86_64-w64-mingw32-gcc $(which x86_64-w64-mingw32-gcc-posix)
RUN git clone -b v0.18.1.0 --depth 1 https://github.com/monero-project/monero && \
RUN git clone -b v0.18.2.0 --depth 1 https://github.com/monero-project/monero && \
cd monero && \
git reset --hard 727bc5b6878170332bf2d838f2c60d1c8dc685c8 && \
git reset --hard 99be9a044f3854f339548e2d99c539c18d7b1b01 && \
cp -a contrib/depends / && \
cd .. && \
rm -rf monero

View File

@@ -120,7 +120,7 @@ Rectangle {
width: 260
height: 135
fillMode: Image.PreserveAspectFit
source: MoneroComponents.Style.blackTheme ? "qrc:///images/card-background-black.png" : "qrc:///images/card-background-white.png"
source: MoneroComponents.Style.blackTheme ? "qrc:///images/card-background-black" + (currentAccountIndex % MoneroComponents.Style.accountColors.length) + ".png" : "qrc:///images/card-background-white.png"
}
DropShadow {

View File

@@ -86,8 +86,7 @@ Status of the translations:
## Installing the Monero GUI from a package
Packages are available for
* Arch Linux: [monero-gui](https://www.archlinux.org/packages/community/x86_64/monero-gui/)
* Debian: See the [whonix/monero-gui repository](https://gitlab.com/whonix/monero-gui#how-to-install-monero-using-apt-get)
* Arch Linux: [monero-gui](https://archlinux.org/packages/extra/x86_64/monero-gui/)
* Void Linux: `xbps-install -S monero-gui`
* Flatpak: [Monero GUI](https://flathub.org/apps/details/org.getmonero.Monero)
* GuixSD: `guix package -i monero-gui`
@@ -108,7 +107,7 @@ Packaging for your favorite distribution would be a welcome contribution!
```
git clone --branch master --recursive https://github.com/monero-project/monero-gui.git
```
\* `master` - replace with the desired version tag (e.g. `v0.18.1.1`) to build the release binaries.
\* `master` - replace with the desired version tag (e.g. `v0.18.3.0`) to build the release binaries.
3. Prepare build environment
```
cd monero-gui
@@ -131,7 +130,7 @@ Packaging for your favorite distribution would be a welcome contribution!
```
git clone --branch master --recursive https://github.com/monero-project/monero-gui.git
```
\* `master` - replace with the desired version tag (e.g. `v0.18.1.1`) to build the release binaries.
\* `master` - replace with the desired version tag (e.g. `v0.18.3.0`) to build the release binaries.
3. Prepare build environment
```
cd monero-gui
@@ -221,15 +220,15 @@ Packaging for your favorite distribution would be a welcome contribution!
2. Install Qt:
*Note*: The Qt 5.9.7 or newer requirement makes **some** distributions (mostly based on debian, like Ubuntu 16.x or Linux Mint 18.x) obsolete due to their repositories containing an older Qt version.
*Note*: The Qt 5.9.7 or newer requirement makes **some** distributions (mostly based on Debian, like Ubuntu 16.x or Linux Mint 18.x) obsolete due to their repositories containing an older Qt version.
The recommended way is to install 5.9.7 from the [official Qt installer](https://www.qt.io/download-qt-installer) or [compiling it yourself](https://wiki.qt.io/Install_Qt_5_on_Ubuntu). This ensures you have the correct version. Higher versions *can* work but as it differs from our production build target, slight differences may occur.
The following instructions will fetch Qt from your distribution's repositories instead. Take note of what version it installs. Your mileage may vary.
- For Ubuntu 17.10+
- For Debian distributions (Debian, Ubuntu, Mint, Tails...)
`sudo apt install qtbase5-dev qt5-default qtdeclarative5-dev qml-module-qtqml-models2 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-platform qml-module-qt-labs-folderlistmodel qttools5-dev-tools qml-module-qtquick-templates2 libqt5svg5-dev`
`sudo apt install qtbase5-dev qtdeclarative5-dev qml-module-qtqml-models2 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-platform qml-module-qt-labs-folderlistmodel qttools5-dev-tools qml-module-qtquick-templates2 libqt5svg5-dev`
- For Gentoo
@@ -240,7 +239,7 @@ The following instructions will fetch Qt from your distribution's repositories i
- Optional : To build the flag `WITH_SCANNER`
- For Ubuntu
- For Debian distributions (Debian, Ubuntu, Mint, Tails...)
`sudo apt install qtmultimedia5-dev qml-module-qtmultimedia`
@@ -258,18 +257,10 @@ The following instructions will fetch Qt from your distribution's repositories i
4. Build
If on x86-64:
```
make release -j4
```
If on ppc64le:
```
make release-linux-ppc64le -j4
```
\* `4` - number of CPU threads to use
\* Add `CMAKE_PREFIX_PATH` environment variable to set a custom Qt install directory, e.g. `CMAKE_PREFIX_PATH=$HOME/Qt/5.9.7/gcc_64 make release -j4`
@@ -319,7 +310,7 @@ The Monero GUI on Windows is 64 bits only; 32-bit Windows GUI builds are not off
3. Install MSYS2 packages for Monero dependencies; the needed 64-bit packages have `x86_64` in their names
```
pacman -S mingw-w64-x86_64-toolchain make mingw-w64-x86_64-cmake mingw-w64-x86_64-boost mingw-w64-x86_64-openssl mingw-w64-x86_64-zeromq mingw-w64-x86_64-libsodium mingw-w64-x86_64-hidapi mingw-w64-x86_64-protobuf-c mingw-w64-x86_64-libusb mingw-w64-x86_64-libgcrypt
pacman -S mingw-w64-x86_64-toolchain make mingw-w64-x86_64-cmake mingw-w64-x86_64-boost mingw-w64-x86_64-openssl mingw-w64-x86_64-zeromq mingw-w64-x86_64-libsodium mingw-w64-x86_64-hidapi mingw-w64-x86_64-protobuf-c mingw-w64-x86_64-libusb mingw-w64-x86_64-libgcrypt mingw-w64-x86_64-unbound mingw-w64-x86_64-pcre
```
You find more details about those dependencies in the [Monero documentation](https://github.com/monero-project/monero). Note that that there is no more need to compile Boost from source; like everything else, you can install it now with a MSYS2 package.

View File

@@ -17,7 +17,33 @@ if(APPLE OR (WIN32 AND NOT STATIC))
add_custom_command(TARGET deploy
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${_qt_svg_dylib} $<TARGET_FILE_DIR:monero-wallet-gui>/../PlugIns/imageformats/
COMMENT "Copying libqsvg.dylib"
COMMAND ${CMAKE_INSTALL_NAME_TOOL} -change "${CMAKE_PREFIX_PATH}/lib/QtGui.framework/Versions/5/QtGui" "@executable_path/../Frameworks/QtGui.framework/Versions/5/QtGui" $<TARGET_FILE_DIR:monero-wallet-gui>/../PlugIns/imageformats/libqsvg.dylib
COMMAND ${CMAKE_INSTALL_NAME_TOOL} -change "${CMAKE_PREFIX_PATH}/lib/QtWidgets.framework/Versions/5/QtWidgets" "@executable_path/../Frameworks/QtWidgets.framework/Versions/5/QtWidgets" $<TARGET_FILE_DIR:monero-wallet-gui>/../PlugIns/imageformats/libqsvg.dylib
COMMAND ${CMAKE_INSTALL_NAME_TOOL} -change "${CMAKE_PREFIX_PATH}/lib/QtSvg.framework/Versions/5/QtSvg" "@executable_path/../Frameworks/QtSvg.framework/Versions/5/QtSvg" $<TARGET_FILE_DIR:monero-wallet-gui>/../PlugIns/imageformats/libqsvg.dylib
COMMAND ${CMAKE_INSTALL_NAME_TOOL} -change "${CMAKE_PREFIX_PATH}/lib/QtCore.framework/Versions/5/QtCore" "@executable_path/../Frameworks/QtCore.framework/Versions/5/QtCore" $<TARGET_FILE_DIR:monero-wallet-gui>/../PlugIns/imageformats/libqsvg.dylib
COMMENT "Copying libqsvg.dylib, running install_name_tool"
)
endif()
# libbost_filesyste-mt.dylib has a dependency on libboost_atomic-mt.dylib, maydeployqt does not copy it by itself
find_package(Boost COMPONENTS atomic)
get_target_property(BOOST_ATOMIC_LIB_PATH Boost::atomic LOCATION)
if(EXISTS ${BOOST_ATOMIC_LIB_PATH})
add_custom_command(TARGET deploy
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy "${BOOST_ATOMIC_LIB_PATH}" "$<TARGET_FILE_DIR:monero-wallet-gui>/../Frameworks/"
COMMENT "Copying libboost_atomic-mt.dylib"
)
endif()
# Apple Silicon requires all binaries to be codesigned
find_program(CODESIGN_EXECUTABLE NAMES codesign)
if(CODESIGN_EXECUTABLE)
add_custom_command(TARGET deploy
POST_BUILD
COMMAND "${CODESIGN_EXECUTABLE}" --force --deep --sign - "$<TARGET_FILE_DIR:monero-wallet-gui>/../.."
COMMENT "Running codesign..."
)
endif()
@@ -42,7 +68,7 @@ if(APPLE OR (WIN32 AND NOT STATIC))
zlib1.dll
libzstd.dll
libwinpthread-1.dll
libtiff-5.dll
libtiff-6.dll
libstdc++-6.dll
libpng16-16.dll
libpcre16-0.dll
@@ -58,7 +84,6 @@ if(APPLE OR (WIN32 AND NOT STATIC))
libglib-2.0-0.dll
libfreetype-6.dll
libbz2-1.dll
libssp-0.dll
libpcre2-16-0.dll
libhidapi-0.dll
libdouble-conversion.dll
@@ -69,24 +94,24 @@ if(APPLE OR (WIN32 AND NOT STATIC))
#platform files
libgcc_s_seh-1.dll
#openssl files
libssl-1_1-x64.dll
libcrypto-1_1-x64.dll
libssl-3-x64.dll
libcrypto-3-x64.dll
)
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
list(APPEND WIN_DEPLOY_DLLS
libicudtd71.dll
libicuind71.dll
libicuiod71.dll
libicutud71.dll
libicuucd71.dll
libicudtd73.dll
libicuind73.dll
libicuiod73.dll
libicutud73.dll
libicuucd73.dll
)
else() # assume release
list(APPEND WIN_DEPLOY_DLLS
libicudt71.dll
libicuin71.dll
libicuio71.dll
libicutu71.dll
libicuuc71.dll
libicudt73.dll
libicuin73.dll
libicuio73.dll
libicutu73.dll
libicuuc73.dll
)
endif()
list(TRANSFORM WIN_DEPLOY_DLLS PREPEND "$ENV{MSYSTEM_PREFIX}/bin/")

View File

@@ -66,7 +66,7 @@ Item {
anchors.fill: parent
color: buttonArea.containsMouse ? MoneroComponents.Style.buttonInlineBackgroundColorHover : MoneroComponents.Style.buttonInlineBackgroundColor
radius: 4
border.width: parent.focus && parent.enabled ? 1 : 0
MoneroComponents.TextPlain {
id: inlineText

View File

@@ -40,6 +40,8 @@ ColumnLayout {
default property alias content: inlineButtons.children
property alias input: input
property bool inputHasFocus: input.activeFocus
property bool tabNavigationEnabled: true
property alias text: input.text
property int inputPaddingLeft: 10
@@ -109,6 +111,8 @@ ColumnLayout {
signal editingFinished();
signal accepted();
signal textUpdated();
signal backtabPressed();
signal tabPressed();
onActiveFocusChanged: activeFocus && input.forceActiveFocus()
onTextUpdated: {
@@ -212,8 +216,18 @@ ColumnLayout {
MoneroComponents.Input {
id: input
KeyNavigation.backtab: item.KeyNavigation.backtab
KeyNavigation.tab: item.KeyNavigation.tab
Keys.onBacktabPressed: {
item.backtabPressed();
if (item.KeyNavigation.backtab) {
item.KeyNavigation.backtab.forceActiveFocus()
}
}
Keys.onTabPressed: {
item.tabPressed();
if (item.KeyNavigation.tab) {
item.KeyNavigation.tab.forceActiveFocus()
}
}
Layout.fillWidth: true
Layout.preferredHeight: inputHeight

View File

@@ -92,7 +92,7 @@ Rectangle {
anchors.leftMargin: 20
height: parent.height
width: 2
color: button.checked ? MoneroComponents.Style.buttonBackgroundColor : "transparent"
color: button.checked ? MoneroComponents.Style.accountColors[currentAccountIndex % MoneroComponents.Style.accountColors.length] : "transparent"
// button text
MoneroComponents.TextPlain {

View File

@@ -201,6 +201,7 @@ Rectangle {
daemonManager.sendCommandAsync(
["set_bootstrap_daemon", "auto"],
appWindow.currentWallet.nettype,
persistentSettings.blockchainDataDir,
callback);
refreshMouseArea.visible = false;

View File

@@ -81,6 +81,7 @@ QtObject {
property string leftPanelBackgroundGradientStart: blackTheme ? _b_leftPanelBackgroundGradientStart : _w_leftPanelBackgroundGradientStart
property string leftPanelBackgroundGradientStop: blackTheme ? _b_leftPanelBackgroundGradientStop : _w_leftPanelBackgroundGradientStop
property string historyHeaderTextColor: blackTheme ? _b_historyHeaderTextColor : _w_historyHeaderTextColor
property var accountColors: blackTheme ? _b_accountColors : _w_accountColors
property string _b_defaultFontColor: "white"
property string _b_dimmedFontColor: "#BBBBBB"
@@ -142,6 +143,7 @@ QtObject {
property string _b_leftPanelBackgroundGradientStart: "#222222"
property string _b_leftPanelBackgroundGradientStop: "#1a1a1a"
property string _b_historyHeaderTextColor: "#C0C0C0"
property var _b_accountColors: ["#6E513C", "#842129", "#458421", "#742184", "#291DBE", "#846F21", "#217F84", "#696969"]
property string _w_defaultFontColor: "black"
property string _w_dimmedFontColor: "#3f3f3f"
@@ -203,4 +205,5 @@ QtObject {
property string _w_leftPanelBackgroundGradientStart: "white"
property string _w_leftPanelBackgroundGradientStop: "#f5f5f5"
property string _w_historyHeaderTextColor: "#515151"
property var _w_accountColors: ["#6E513C", "#6E513C", "#842129", "#458421", "#742184", "#291DBE", "#846F21", "#217F84", "#696969"]
}

View File

@@ -21,6 +21,14 @@ Text {
font.pixelSize: 14
textFormat: Text.PlainText
Rectangle {
width: root.contentWidth
height: root.height
anchors.left: parent.left
anchors.top: parent.top
color: root.focus ? MoneroComponents.Style.titleBarButtonHoverColor : "transparent"
}
MoneroEffects.ColorTransition {
enabled: root.themeTransition
themeTransition: root.themeTransition

View File

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

View File

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

BIN
images/ledgerStax.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

BIN
images/verify-white.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 956 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
images/verify.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 854 B

BIN
images/verify@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
images/write-down-white.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 779 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
images/write-down.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 728 B

BIN
images/write-down@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -167,7 +167,6 @@ Type: files; Name: "{app}\libstdc++-6.dll"
Type: files; Name: "{app}\libtiff-5.dll"
Type: files; Name: "{app}\libwinpthread-1.dll"
Type: files; Name: "{app}\zlib1.dll"
Type: files; Name: "{app}\libssp-0.dll"
Type: files; Name: "{app}\libhidapi-0.dll"
Type: files; Name: "{app}\libeay32.dll"
Type: files; Name: "{app}\ssleay32.dll"

View File

@@ -56,11 +56,14 @@
i.e. let it download the blockchain and store it locally on your computer, or you can configure your wallet to
access a remote <i>open node</i> to get indirect access to the blockchain.</p>
<p>Working with your own copy of the blockchain is <b>preferred</b>: It strengthens the Monero network, and it
<p>You can also <i>Prune</i> the blockchain in order to save 2/3 of storage space while keeping the full transaction history.
More information regarding how pruning works can be found <a href="https://www.getmonero.org/resources/moneropedia/pruning.html">here</a>.</p>
<p>Working with your own copy of the blockchain, even pruned, is <b>preferred</b>: It strengthens the Monero network, and it
provides the most security and privacy possible for you.</p>
<p>However if your Internet access makes it difficult to run a full node, or if you have simply no room to store
the blockchain locally (about 90 GB in May 2020, and of course growing), you can compromise and try to connect
the blockchain locally (about 160 GB in June 2023, and of course growing), you can compromise and try to connect
to a remote node. One way of finding such a node is checking
<a href="https://moneroworld.com/#nodes">this page</a>.
</p>

View File

@@ -76,3 +76,34 @@ function isValidOpenAliasAddress(address) {
// make sure it is not some kind of floating number
return address.length > 2 && isNaN(parseFloat(address)) && address.indexOf('.') >= 0
}
function handleOpenAliasResolution(address, descriptionText) {
const result = walletManager.resolveOpenAlias(address);
if (!result) {
return { message: qsTr("No address found") };
}
const [isDnssecValid, resolvedAddress] = result.split("|");
const isAddressValid = walletManager.addressValid(resolvedAddress, appWindow.persistentSettings.nettype);
let updatedDescriptionText = descriptionText;
if (isDnssecValid === "true") {
if (isAddressValid) {
updatedDescriptionText = descriptionText ? `${address} ${descriptionText}` : address;
return { address: resolvedAddress, description: updatedDescriptionText };
} else {
return { message: qsTr("No valid address found at this OpenAlias address") };
}
} else if (isDnssecValid === "false") {
if (isAddressValid) {
return {
address: resolvedAddress,
message: qsTr("Address found, but the DNSSEC signatures could not be verified, so this address may be spoofed"),
};
} else {
return { message: qsTr("No valid address found at this OpenAlias address, but the DNSSEC signatures could not be verified, so this may be spoofed") };
}
} else {
return { message: qsTr("Internal error") };
}
}

View File

@@ -57,12 +57,12 @@ function ago(epoch) {
if(delta < 60)
return qsTr("%n second(s) ago", "0", Math.floor(delta))
else if (delta >= 60 && delta <= 3600)
else if (delta < 3600)
return qsTr("%n minute(s) ago", "0", Math.floor(delta / 60))
else if (delta >= 3600 && delta <= 86400)
return qsTr("%n hour(s) ago", "0", Math.floor(delta / 60 / 60))
else if (delta >= 86400)
return qsTr("%n day(s) ago", "0", Math.floor(delta / 24 / 60 / 60))
else if (delta < 86400)
return qsTr("%n hour(s) ago", "0", Math.floor(delta / 3600))
else
return qsTr("%n day(s) ago", "0", Math.floor(delta / 86400))
}
function netTypeToString(){

View File

@@ -94,7 +94,7 @@ ApplicationWindow {
readonly property string localDaemonAddress : "localhost:" + getDefaultDaemonRpcPort(persistentSettings.nettype)
property string currentDaemonAddress;
property int disconnectedEpoch: 0
property int estimatedBlockchainSize: persistentSettings.pruneBlockchain ? 40 : 105 // GB
property int estimatedBlockchainSize: persistentSettings.pruneBlockchain ? 55 : 150 // GB
property alias viewState: rootItem.state
property string prevSplashText;
property bool splashDisplayedBeforeButtonRequest;
@@ -379,7 +379,7 @@ ApplicationWindow {
}
function isTrustedDaemon() {
return !persistentSettings.useRemoteNode || remoteNodesModel.currentRemoteNode().trusted;
return appWindow.walletMode >= 2 && (!persistentSettings.useRemoteNode || remoteNodesModel.currentRemoteNode().trusted);
}
function usefulName(path) {
@@ -469,7 +469,7 @@ ApplicationWindow {
// If wallet isnt connected, advanced wallet mode and no daemon is running - Ask
if (appWindow.walletMode >= 2 && !persistentSettings.useRemoteNode && !walletInitialized && disconnected) {
daemonManager.runningAsync(persistentSettings.nettype, function(running) {
daemonManager.runningAsync(persistentSettings.nettype, persistentSettings.blockchainDataDir, function(running) {
if (!running) {
daemonManagerDialog.open();
}
@@ -602,6 +602,9 @@ ApplicationWindow {
function connectRemoteNode() {
console.log("connecting remote node");
p2poolManager.exit();
p2poolManager.getStatus();
const callback = function() {
persistentSettings.useRemoteNode = true;
const remoteNode = remoteNodesModel.currentRemoteNode();
@@ -630,6 +633,10 @@ ApplicationWindow {
return;
console.log("disconnecting remote node");
p2poolManager.exit();
p2poolManager.getStatus();
persistentSettings.useRemoteNode = false;
currentDaemonAddress = localDaemonAddress
currentWallet.setDaemonLogin("", "");
@@ -694,7 +701,8 @@ ApplicationWindow {
// Daemon connected
leftPanel.networkStatus.connected = currentWallet ? currentWallet.connected() : Wallet.ConnectionStatus_Disconnected
currentWallet.refreshHeightAsync();
if (currentWallet)
currentWallet.refreshHeightAsync();
}
function startDaemon(flags){
@@ -714,7 +722,7 @@ ApplicationWindow {
appWindow.showProcessingSplash(qsTr("Waiting for daemon to stop..."));
}
p2poolManager.exit()
daemonManager.stopAsync(persistentSettings.nettype, function(result) {
daemonManager.stopAsync(persistentSettings.nettype, persistentSettings.blockchainDataDir, function(result) {
daemonStartStopInProgress = 0;
if (splash) {
hideProcessingSplash();
@@ -747,6 +755,12 @@ ApplicationWindow {
currentWallet.startRefresh();
informationPopup.title = qsTr("Daemon failed to start") + translationManager.emptyString;
informationPopup.text = error + ".\n\n" + qsTr("Please check your wallet and daemon log for errors. You can also try to start %1 manually.").arg((isWindows)? "monerod.exe" : "monerod")
if (middlePanel.advancedView.miningView.stopMiningEnabled == true) {
walletManager.stopMining()
p2poolManager.exit()
middlePanel.advancedView.miningView.update()
informationPopup.text += qsTr("\n\nExiting p2pool. Please check that port 18083 is available.") + translationManager.emptyString;
}
informationPopup.icon = StandardIcon.Critical
informationPopup.onCloseCallback = null
informationPopup.open();
@@ -1118,6 +1132,7 @@ ApplicationWindow {
middlePanel.transferView.clearFields();
middlePanel.receiveView.clearFields();
middlePanel.historyView.clearFields();
middlePanel.advancedView.clearFields();
// disable timers
userInActivityTimer.running = false;
});
@@ -1395,7 +1410,7 @@ ApplicationWindow {
property bool historyShowAdvanced: false
property bool historyHumanDates: true
property string blockchainDataDir: ""
property bool useRemoteNode: false
property bool useRemoteNode: isAndroid
property string remoteNodeAddress: "" // TODO: drop after v0.17.2.0 release
property string remoteNodesSerialized: JSON.stringify({
selected: 0,
@@ -1445,8 +1460,15 @@ ApplicationWindow {
function getWalletProxyAddress() {
if (!useRemoteNode) {
return "";
} else {
const remoteAddress = remoteNodesModel.currentRemoteNode().address;
// skip proxy when using localhost remote node
if (remoteAddress.startsWith("127.0.0.1:") || remoteAddress.startsWith("localhost:")) {
return "";
} else {
return getProxyAddress();
}
}
return getProxyAddress();
}
Component.onCompleted: {
@@ -2141,7 +2163,7 @@ ApplicationWindow {
if (currentWallet) {
handler(!currentWallet.disconnected);
} else {
daemonManager.runningAsync(persistentSettings.nettype, handler);
daemonManager.runningAsync(persistentSettings.nettype, persistentSettings.blockchainDataDir, handler);
}
}
}
@@ -2164,7 +2186,7 @@ ApplicationWindow {
function getBuildTag() {
if (isMac) {
return "mac-x64";
return isARM ? "mac-armv8" : "mac-x64";
}
if (isWindows) {
return oshelper.installed ? "install-win-x64" : "win-x64";

2
monero

Submodule monero updated: 7cbae6ca98...f9b81a589e

View File

@@ -238,7 +238,7 @@ Rectangle {
Layout.fillHeight: true
anchors.top: parent.top
anchors.bottom: parent.bottom
color: "darkgrey"
color: MoneroComponents.Style.accountColors[currentAccountIndex % MoneroComponents.Style.accountColors.length]
width: 2
}

View File

@@ -387,34 +387,17 @@ Rectangle {
visible: TxUtils.isValidOpenAliasAddress(addressLine.text)
enabled : visible
onClicked: {
var result = walletManager.resolveOpenAlias(addressLine.text)
if (result) {
var parts = result.split("|")
if (parts.length === 2) {
var address_ok = walletManager.addressValid(parts[1], appWindow.persistentSettings.nettype)
if (parts[0] === "true") {
if (address_ok) {
// prepend openalias to description
descriptionLine.text = descriptionLine.text ? addressLine.text + " " + descriptionLine.text : addressLine.text
addressLine.text = parts[1]
} else {
root.oa_message(qsTr("No valid address found at this OpenAlias address"))
}
} else if (parts[0] === "false") {
if (address_ok) {
addressLine.text = parts[1]
root.oa_message(qsTr("Address found, but the DNSSEC signatures could not be verified, so this address may be spoofed"))
} else {
root.oa_message(qsTr("No valid address found at this OpenAlias address, but the DNSSEC signatures could not be verified, so this may be spoofed"))
}
} else {
root.oa_message(qsTr("Internal error"))
}
} else {
root.oa_message(qsTr("Internal error"))
const response = TxUtils.handleOpenAliasResolution(addressLine.text, descriptionLine.text);
if (response) {
if (response.message) {
oa_message(response.message);
}
if (response.address) {
addressLine.text = response.address;
}
if (response.description) {
descriptionLine.text = response.description;
}
} else {
root.oa_message(qsTr("No address found"))
}
}
}

View File

@@ -40,6 +40,8 @@ ColumnLayout {
spacing: 0
property int panelHeight: 900
property alias miningView: stateView.miningView
property alias signView: stateView.signView
property alias prooveView: stateView.prooveView
property alias state: stateView.state
MoneroComponents.Navbar {
@@ -52,6 +54,7 @@ ColumnLayout {
active: state == "Mining"
text: qsTr("Mining") + translationManager.emptyString
onSelected: state = "Mining"
visible: !isAndroid
}
MoneroComponents.NavbarItem {
active: state == "Prove"
@@ -81,7 +84,7 @@ ColumnLayout {
Layout.fillWidth: true
Layout.preferredHeight: panelHeight
color: "transparent"
state: "Mining"
state: isAndroid ? "Prove" : "Mining"
onCurrentViewChanged: {
if (previousView) {
@@ -120,7 +123,7 @@ ColumnLayout {
StackView {
id: stackView
initialItem: stateView.miningView
initialItem: isAndroid ? stateView.prooveView : stateView.miningView
anchors.fill: parent
clip: false // otherwise animation will affect left panel
@@ -146,4 +149,10 @@ ColumnLayout {
}
}
}
function clearFields() {
signView.clearFields();
prooveView.clearFields();
}
}

View File

@@ -1765,18 +1765,25 @@ Rectangle {
var written = currentWallet.history.writeCSV(currentWallet.currentSubaddressAccount, dataDir);
if(written !== ""){
informationPopup.title = qsTr("Success") + translationManager.emptyString;
confirmationDialog.title = qsTr("Success") + translationManager.emptyString;
var text = qsTr("CSV file written to: %1").arg(written) + "\n\n"
text += qsTr("Tip: Use your favorite spreadsheet software to sort on blockheight.") + "\n\n" + translationManager.emptyString;
informationPopup.text = text;
informationPopup.icon = StandardIcon.Information;
confirmationDialog.text = text;
confirmationDialog.icon = StandardIcon.Information;
confirmationDialog.cancelText = qsTr("Open folder") + translationManager.emptyString;
confirmationDialog.onAcceptedCallback = null;
confirmationDialog.onRejectedCallback = function() {
oshelper.openContainingFolder(written);
}
confirmationDialog.open();
} else {
informationPopup.title = qsTr("Error") + translationManager.emptyString;
informationPopup.text = qsTr("Error exporting transaction data.") + "\n\n" + translationManager.emptyString;
informationPopup.icon = StandardIcon.Critical;
informationPopup.onCloseCallback = null;
informationPopup.open();
}
informationPopup.onCloseCallback = null;
informationPopup.open();
}
Component.onCompleted: {
var _folder = 'file://' + appWindow.accountsDir;

View File

@@ -41,7 +41,8 @@ Rectangle {
property alias miningHeight: mainLayout.height
property double currentHashRate: 0
property int threads: idealThreadCount / 2
property alias stopMiningEnabled: stopSoloMinerButton.enabled
property string args: ""
ColumnLayout {
id: mainLayout
Layout.fillWidth: true
@@ -293,11 +294,12 @@ Rectangle {
var success;
if (persistentSettings.allow_p2pool_mining) {
if (p2poolManager.isInstalled()) {
if (persistentSettings.allowRemoteNodeMining) {
args = daemonManager.getArgs(persistentSettings.blockchainDataDir) //updates arguments
if (persistentSettings.allowRemoteNodeMining || (args.includes("--zmq-pub tcp://127.0.0.1:18083") || args.includes("--zmq-pub=tcp://127.0.0.1:18083")) && !args.includes("--no-zmq")) {
startP2Pool()
}
else {
daemonManager.stopAsync(persistentSettings.nettype, startP2PoolLocal)
daemonManager.stopAsync(persistentSettings.nettype, persistentSettings.blockchainDataDir, startP2PoolLocal)
}
}
else {
@@ -585,12 +587,35 @@ Rectangle {
function startP2PoolLocal() {
var noSync = false;
var customDaemonArgs = persistentSettings.daemonFlags.toLowerCase();
var daemonArgs = "--zmq-pub " + "tcp://127.0.0.1:18083 " + "--disable-dns-checkpoints "
if (!customDaemonArgs.includes("--zmq-pub") && !customDaemonArgs.includes("--disable-dns-checkpoints") && !customDaemonArgs.includes("--no-zmq")) {
daemonArgs = daemonArgs + customDaemonArgs;
//these args will be deleted because DaemonManager::start will re-add them later.
//--no-zmq must be deleted. removing '--zmq-pub=tcp...' lets us blindly add '--zmq-pub tcp...' later without risking duplication.
var defaultArgs = ["--detach","--data-dir","--bootstrap-daemon-address","--prune-blockchain","--no-sync","--check-updates","--non-interactive","--max-concurrency","--no-zmq","--zmq-pub=tcp://127.0.0.1:18083"]
var customDaemonArgsArray = args.split(' ');
var flag = "";
var allArgs = [];
var p2poolArgs = ["--zmq-pub tcp://127.0.0.1:18083"];
//create an array (allArgs) of ['--arg value','--arg2','--arg3']
for (let i = 0; i < customDaemonArgsArray.length; i++) {
if(!customDaemonArgsArray[i].startsWith("--")) {
flag += " " + customDaemonArgsArray[i]
} else {
if(flag){
allArgs.push(flag)
}
flag = customDaemonArgsArray[i]
}
}
var success = daemonManager.start(daemonArgs, persistentSettings.nettype, persistentSettings.blockchainDataDir, persistentSettings.bootstrapNodeAddress, noSync, persistentSettings.pruneBlockchain)
allArgs.push(flag)
//pop from allArgs if value is inside the deleteme array (defaultArgs)
allArgs = allArgs.filter( ( el ) => !defaultArgs.includes( el.split(" ")[0] ) )
//append required p2pool flags
for (let i = 0; i < p2poolArgs.length; i++) {
if(!allArgs.includes(p2poolArgs[i])) {
allArgs.push(p2poolArgs[i])
continue
}
}
var success = daemonManager.start(allArgs.join(" "), persistentSettings.nettype, persistentSettings.blockchainDataDir, persistentSettings.bootstrapNodeAddress, noSync, persistentSettings.pruneBlockchain)
if (success) {
startP2Pool()
}
@@ -616,10 +641,25 @@ Rectangle {
}
}
function p2poolDownloadFailed() {
function p2poolDownloadFailed(errorCode) {
statusMessage.visible = false
errorPopup.title = qsTr("P2Pool Installation Failed") + translationManager.emptyString;
errorPopup.text = qsTr("P2Pool installation failed.") + isWindows ? (" " + qsTr("Try starting the program with administrator privileges.")) : ""
switch (errorCode) {
case P2PoolManager.HashVerificationFailed:
errorPopup.text = qsTr("Hash verification failed.") + translationManager.emptyString;
break;
case P2PoolManager.BinaryNotAvailable:
errorPopup.text = qsTr("P2Pool download is not available.") + translationManager.emptyString;
break;
case P2PoolManager.ConnectionIssue:
errorPopup.text = qsTr("P2Pool download failed due to a connection issue.") + translationManager.emptyString;
break;
case P2PoolManager.InstallationFailed:
errorPopup.text = qsTr("P2Pool installation failed.") + (isWindows ? (" " + qsTr("Try starting the program with administrator privileges.")) : "")
break;
default:
errorPopup.text = qsTr("Unknown error.") + translationManager.emptyString;
}
errorPopup.icon = StandardIcon.Critical
errorPopup.open()
update()

View File

@@ -580,7 +580,8 @@ Rectangle {
Layout.fillHeight: true
anchors.top: parent.top
anchors.bottom: parent.bottom
color: "darkgrey"
property int currentAccountIndex: currentWallet ? currentWallet.currentSubaddressAccount : 0
color: MoneroComponents.Style.accountColors[currentAccountIndex % MoneroComponents.Style.accountColors.length]
width: 2
}

View File

@@ -50,15 +50,6 @@ Rectangle {
return true
}
function validUnsigned(s) {
if (s.length == 0)
return false
for (var i = 0; i < s.length; ++i)
if ("0123456789".indexOf(s[i]) == -1)
return false
return true
}
function validRing(str, relative) {
var outs = str.split(" ");
if (outs.length == 0)
@@ -109,136 +100,6 @@ Rectangle {
color: MoneroComponents.Style.defaultFontColor
}
MoneroComponents.LabelSubheader {
Layout.fillWidth: true
textFormat: Text.RichText
text: qsTr("Outputs marked as spent") + translationManager.emptyString
tooltip: qsTr(
"In order to obscure which inputs in a Monero transaction are being spent, a third party should not be able " +
"to tell which inputs in a ring are already known to be spent. Being able to do so would weaken the protection " +
"afforded by ring signatures. If all but one of the inputs are known to be already spent, then the input being " +
"actually spent becomes apparent, thereby nullifying the effect of ring signatures, one of the three main layers " +
"of privacy protection Monero uses.<br>" +
"To help transactions avoid those inputs, a list of known spent ones can be used to avoid using them in new " +
"transactions. Such a list is maintained by the Monero project and is available on the getmonero.org website, " +
"and you can import this list here.<br>" +
"Alternatively, you can scan the blockchain (and the blockchain of key-reusing Monero clones) yourself " +
"using the monero-blockchain-mark-spent-outputs tool to create a list of known spent outputs.<br>"
) + translationManager.emptyString
}
MoneroComponents.TextPlain {
textFormat: Text.RichText
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 14
text: qsTr("This sets which outputs are known to be spent, and thus not to be used as privacy placeholders in ring signatures. ") +
qsTr("You should only have to load a file when you want to refresh the list. Manual adding/removing is possible if needed.") + translationManager.emptyString
wrapMode: Text.Wrap
Layout.fillWidth: true;
color: MoneroComponents.Style.defaultFontColor
}
ColumnLayout {
Layout.fillWidth: true
Layout.topMargin: 12
FileDialog {
id: loadBlackballFileDialog
title: qsTr("Please choose a file from which to load outputs to mark as spent") + translationManager.emptyString;
folder: "file://"
nameFilters: ["*"]
onAccepted: {
loadBlackballFileLine.text = walletManager.urlToLocalPath(loadBlackballFileDialog.fileUrl)
}
}
MoneroComponents.LineEdit {
id: loadBlackballFileLine
Layout.fillWidth: true
fontSize: 16
placeholderFontSize: 16
placeholderText: qsTr("Path to file") + "..." + translationManager.emptyString
labelFontSize: 14
labelText: qsTr("Filename with outputs to mark as spent") + ":" + translationManager.emptyString
copyButton: true
readOnly: false
}
RowLayout {
Layout.fillWidth: true
Layout.topMargin: 18
MoneroComponents.StandardButton {
id: selectBlackballFileButton
text: qsTr("Browse") + translationManager.emptyString
enabled: true
small: true
onClicked: {
loadBlackballFileDialog.open()
}
}
MoneroComponents.StandardButton {
id: loadBlackballFileButton
text: qsTr("Load") + translationManager.emptyString
small: true
enabled: !!appWindow.currentWallet && loadBlackballFileLine.text !== ""
onClicked: appWindow.currentWallet.blackballOutputs(walletManager.urlToLocalPath(loadBlackballFileDialog.fileUrl), true)
}
}
}
GridLayout {
Layout.fillWidth: true
columnSpacing: 20
MoneroComponents.LineEdit {
id: blackballOutputAmountLine
Layout.fillWidth: true
fontSize: 16
labelFontSize: 14
labelText: qsTr("Or manually mark a single output as spent/unspent:") + translationManager.emptyString
placeholderFontSize: 16
placeholderText: qsTr("Paste output amount") + "..." + translationManager.emptyString
readOnly: false
validator: IntValidator { bottom: 0 }
}
MoneroComponents.LineEdit {
id: blackballOutputOffsetLine
Layout.fillWidth: true
fontSize: 16
labelFontSize: 14
labelText: " "
placeholderFontSize: 16
placeholderText: qsTr("Paste output offset") + "..." + translationManager.emptyString
readOnly: false
validator: IntValidator { bottom: 0 }
}
}
RowLayout {
Layout.fillWidth: true
Layout.topMargin: 18
MoneroComponents.StandardButton {
id: blackballButton
text: qsTr("Mark as spent") + translationManager.emptyString
small: true
enabled: !!appWindow.currentWallet && validUnsigned(blackballOutputAmountLine.text) && validUnsigned(blackballOutputOffsetLine.text)
onClicked: appWindow.currentWallet.blackballOutput(blackballOutputAmountLine.text, blackballOutputOffsetLine.text)
}
MoneroComponents.StandardButton {
id: unblackballButton
text: qsTr("Mark as unspent") + translationManager.emptyString
small: true
enabled: !!appWindow.currentWallet && validUnsigned(blackballOutputAmountLine.text) && validUnsigned(blackballOutputOffsetLine.text)
onClicked: appWindow.currentWallet.unblackballOutput(blackballOutputAmountLine.text, blackballOutputOffsetLine.text)
}
}
MoneroComponents.LabelSubheader {
Layout.fillWidth: true
Layout.topMargin: 24

View File

@@ -421,6 +421,16 @@ Rectangle {
}
}
function clearFields() {
verifyMessageLine.text = ""
signMessageLine.text = ""
signSignatureLine.text = ""
verifyAddressLine.text = ""
verifySignatureLine.text = ""
signFileLine.text = ""
verifyFileLine.text = ""
}
function onPageCompleted() {
console.log("Sign/verify page loaded");
}

View File

@@ -51,7 +51,7 @@ Rectangle {
color: "transparent"
property alias transferHeight1: pageRoot.height
property alias transferHeight2: advancedLayout.height
property int mixin: 10 // (ring size 11)
property int mixin: 15 // (ring size 16)
property string warningContent: ""
property string sendButtonWarning: {
// Currently opened wallet is not view-only
@@ -415,41 +415,18 @@ Rectangle {
text: qsTr("Resolve") + translationManager.emptyString
visible: TxUtils.isValidOpenAliasAddress(address)
onClicked: {
var result = walletManager.resolveOpenAlias(address)
if (result) {
var parts = result.split("|")
if (parts.length == 2) {
var address_ok = walletManager.addressValid(parts[1], appWindow.persistentSettings.nettype)
if (parts[0] === "true") {
if (address_ok) {
// prepend openalias to description
descriptionLine.text = descriptionLine.text ? address + " " + descriptionLine.text : address
descriptionCheckbox.checked = true
recipientRepeater.itemAt(index).children[1].children[0].text = parts[1];
}
else
oa_message(qsTr("No valid address found at this OpenAlias address"))
}
else if (parts[0] === "false") {
if (address_ok) {
recipientRepeater.itemAt(index).children[1].children[0].text = parts[1];
oa_message(qsTr("Address found, but the DNSSEC signatures could not be verified, so this address may be spoofed"))
}
else
{
oa_message(qsTr("No valid address found at this OpenAlias address, but the DNSSEC signatures could not be verified, so this may be spoofed"))
}
}
else {
oa_message(qsTr("Internal error"))
}
const response = TxUtils.handleOpenAliasResolution(address, descriptionLine.text);
if (response) {
if (response.message) {
oa_message(response.message);
}
else {
oa_message(qsTr("Internal error"))
if (response.address) {
recipientRepeater.itemAt(index).children[1].children[0].text = response.address;
}
if (response.description) {
descriptionLine.text = response.description;
descriptionCheckbox.checked = true;
}
}
else {
oa_message(qsTr("No address found"))
}
}
}

View File

@@ -259,6 +259,17 @@ Rectangle {
}
}
function clearFields() {
checkProofAddressLine.text = ""
checkProofMessageLine.text = ""
checkProofSignatureLine.text = ""
checkProofTxIdLine.text = ""
getProofAddressLine.text = ""
getProofMessageLine.text = ""
getProofTxIdLine.text = ""
getReserveProofAmtLine.text = ""
}
function onPageCompleted() {
console.log("TxKey page loaded");

View File

@@ -74,6 +74,7 @@ ColumnLayout {
active: settingsStateView.state == "Log"
text: qsTr("Log") + translationManager.emptyString
onSelected: settingsStateView.state = "Log"
visible: !isAndroid
}
MoneroComponents.NavbarItem {
active: settingsStateView.state == "Info"

View File

@@ -254,7 +254,7 @@ Rectangle {
onAccepted: {
if(text.length > 0) {
consoleArea.logCommand(">>> " + text)
daemonManager.sendCommandAsync(text.split(" "), currentWallet.nettype, function(result) {
daemonManager.sendCommandAsync(text.split(" "), currentWallet.nettype, persistentSettings.blockchainDataDir, function(result) {
if (!result) {
appWindow.showStatusMessage(qsTr("Failed to send command"), 3);
}

View File

@@ -55,6 +55,7 @@ Rectangle{
Layout.fillWidth: true
Layout.preferredHeight: 90
color: "transparent"
visible: !isAndroid
Rectangle {
id: localNodeDivider

View File

@@ -138,9 +138,19 @@ Rectangle {
inputDialog.onAcceptedCallback = function() {
var txid = inputDialog.inputText.trim();
if (currentWallet.scanTransactions([txid])) {
updateBalance();
appWindow.showStatusMessage(qsTr("Transaction successfully scanned"), 3);
} else {
appWindow.showStatusMessage(qsTr("Failed to scan transaction") + ": " + currentWallet.errorString, 5);
console.error("Error: ", currentWallet.errorString);
if (currentWallet.errorString == "The wallet has already seen 1 or more recent transactions than the scanned tx") {
informationPopup.title = qsTr("Error") + translationManager.emptyString;
informationPopup.text = qsTr("The wallet has already seen 1 or more recent transactions than the scanned transaction.\n\nIn order to rescan the transaction, you can re-sync your wallet by resetting the wallet restore height in the Settings > Info page. Make sure to use a restore height from before your wallet's earliest transaction.") + translationManager.emptyString;
informationPopup.icon = StandardIcon.Critical
informationPopup.onCloseCallback = null
informationPopup.open();
} else {
appWindow.showStatusMessage(qsTr("Failed to scan transaction") + ": " + currentWallet.errorString, 5);
}
}
}
inputDialog.onRejectedCallback = null;

32
qml.qrc
View File

@@ -119,8 +119,22 @@
<file>components/RemoteNodeEdit.qml</file>
<file>pages/Keys.qml</file>
<file>images/appicon.ico</file>
<file>images/card-background-black.png</file>
<file>images/card-background-black@2x.png</file>
<file>images/card-background-black0.png</file>
<file>images/card-background-black1.png</file>
<file>images/card-background-black2.png</file>
<file>images/card-background-black3.png</file>
<file>images/card-background-black4.png</file>
<file>images/card-background-black5.png</file>
<file>images/card-background-black6.png</file>
<file>images/card-background-black7.png</file>
<file>images/card-background-black0@2x.png</file>
<file>images/card-background-black1@2x.png</file>
<file>images/card-background-black2@2x.png</file>
<file>images/card-background-black3@2x.png</file>
<file>images/card-background-black4@2x.png</file>
<file>images/card-background-black5@2x.png</file>
<file>images/card-background-black6@2x.png</file>
<file>images/card-background-black7@2x.png</file>
<file>images/card-background-white.png</file>
<file>images/card-background-white@2x.png</file>
<file>images/moneroLogo_white.png</file>
@@ -192,6 +206,7 @@
<file>wizard/WizardCreateWallet2.qml</file>
<file>wizard/WizardCreateWallet3.qml</file>
<file>wizard/WizardCreateWallet4.qml</file>
<file>wizard/WizardCreateWallet5.qml</file>
<file>wizard/WizardCreateDevice1.qml</file>
<file>wizard/WizardDaemonSettings.qml</file>
<file>wizard/WizardHeader.qml</file>
@@ -266,7 +281,20 @@
<file>images/ledgerNanoS.png</file>
<file>images/ledgerNanoSPlus.png</file>
<file>images/ledgerNanoX.png</file>
<file>images/ledgerStax.png</file>
<file>images/trezor.png</file>
<file>images/trezor@2x.png</file>
<file>qtquickcontrols2.conf</file>
<file>images/write-down.png</file>
<file>images/write-down-white.png</file>
<file>images/write-down@2x.png</file>
<file>images/write-down-white@2x.png</file>
<file>images/verify.png</file>
<file>images/verify-white.png</file>
<file>images/verify@2x.png</file>
<file>images/verify-white@2x.png</file>
<file>wizard/SeedListItem.qml</file>
<file>wizard/SeedListGrid.qml</file>
<file>wizard/template.pdf</file>
</qresource>
</RCC>

2
qtquickcontrols2.conf Normal file
View File

@@ -0,0 +1,2 @@
[Controls]
Style=Desktop

View File

@@ -0,0 +1,10 @@
[Desktop Entry]
Name=Monero GUI
GenericName=Monero-GUI
Comment=Monero GUI
Exec=monero-wallet-gui
Type=Application
Terminal=false
Categories=Network;Qt;Finance;Office;
Icon=org.getmonero.Monero
StartupNotify=true

View File

@@ -0,0 +1,65 @@
<?xml version="1.0" encoding="UTF-8"?>
<component type="desktop-application">
<id>org.getmonero.Monero</id>
<metadata_license>CC0-1.0</metadata_license>
<project_license>BSD-3-Clause</project_license>
<content_rating type="oars-1.1"/>
<developer_name>The Monero Project</developer_name>
<categories>
<category>Network</category>
<category>Qt</category>
<category>Finance</category>
<category>Office</category>
</categories>
<name>Monero GUI</name>
<summary>Monero: the secure, private, untraceable cryptocurrency</summary>
<description>
<p>Monero is a private, secure, untraceable, decentralised digital currency. You
are your bank, you control your funds, and nobody can trace your transfers
unless you allow them to do so.</p>
<p>Privacy: Monero uses a cryptographically sound system to allow you to send
and receive funds without your transactions being easily revealed on the
blockchain (the ledger of transactions that everyone has). This ensures that
your purchases, receipts, and all transfers remain absolutely private by
default.</p>
<p>Security: Using the power of a distributed peer-to-peer consensus network,
every transaction on the network is cryptographically secured. Individual
wallets have a 25 word mnemonic seed that is only displayed once, and can be
written down to backup the wallet. Wallet files are encrypted with a passphrase
to ensure they are useless if stolen.</p>
<p>Untraceability: By taking advantage of ring signatures, a special property of
a certain type of cryptography, Monero is able to ensure that transactions are
not only untraceable, but have an optional measure of ambiguity that ensures
that transactions cannot easily be tied back to an individual user or computer.</p>
</description>
<launchable type="desktop-id">org.getmonero.Monero.desktop</launchable>
<screenshots>
<screenshot type="default">
<caption>A screenshot of the Monero GUI wallet</caption>
<image>https://raw.githubusercontent.com/monero-project/monero-site/master/img/downloads/gui.png</image>
</screenshot>
</screenshots>
<url type="homepage">https://getmonero.org</url>
<url type="bugtracker">https://github.com/monero-project/monero-gui/issues</url>
<url type="donation">https://getmonero.org/get-started/contributing</url>
<url type="faq">https://getmonero.org/get-started/faq</url>
<url type="help">https://getmonero.org/resources/user-guides</url>
<url type="translate">https://translate.getmonero.org</url>
<url type="contact">https://getmonero.org/community/hangouts</url>
<url type="contribute">https://getmonero.org/get-started/contributing</url>
<releases>
<release version="<version>" date="<date>"/>
</releases>
<custom>
<value key="flathub::manifest">https://github.com/monero-project/monero-gui/tree/master/share/org.getmonero.Monero.yaml</value>
</custom>
</component>

View File

@@ -0,0 +1,133 @@
app-id: org.getmonero.Monero
runtime: org.kde.Platform
runtime-version: 5.15-22.08
sdk: org.kde.Sdk
finish-args:
- --share=network
- --share=ipc
- --socket=x11
- --socket=wayland
- --device=all
- --filesystem=~/Monero:create
- --persist=.bitmonero
cleanup:
- /include
- /etc
- /share/man
- /lib/pkgconfig
- /lib/cmake
- '*.a'
- '*.la'
command: monero-wallet-gui
modules:
- name: protobuf
buildsystem: cmake-ninja
config-opts:
- -DCMAKE_BUILD_TYPE=Release
sources:
- type: git
url: https://github.com/protocolbuffers/protobuf
tag: v22.4
commit: 40e1daca18708c21c7edf07c489a688355bd297b
- name: boost
buildsystem: simple
build-commands:
- ./bootstrap.sh --prefix=$FLATPAK_DEST --with-libraries=chrono,date_time,filesystem,locale,program_options,regex,serialization,system,thread
- ./b2 headers
- ./b2 -j$FLATPAK_BUILDER_N_JOBS install variant=release --layout=system
sources:
- type: archive
url: https://boostorg.jfrog.io/artifactory/main/release/1.82.0/source/boost_1_82_0.tar.gz
sha256: 66a469b6e608a51f8347236f4912e27dc5c60c60d7d53ae9bfe4683316c6f04c
- name: libunbound
config-opts:
- --with-libunbound-only
sources:
- type: archive
url: https://nlnetlabs.nl/downloads/unbound/unbound-1.17.1.tar.gz
sha256: ee4085cecce12584e600f3d814a28fa822dfaacec1f94c84bfd67f8a5571a5f4
- name: libsodium
sources:
- type: archive
url: https://github.com/jedisct1/libsodium/releases/download/1.0.18-RELEASE/libsodium-1.0.18.tar.gz
sha256: 6f504490b342a4f8a4c4a02fc9b866cbef8622d5df4e5452b46be121e46636c1
- name: libusb
sources:
- type: archive
url: https://github.com/libusb/libusb/releases/download/v1.0.26/libusb-1.0.26.tar.bz2
sha256: 12ce7a61fc9854d1d2a1ffe095f7b5fac19ddba095c259e6067a46500381b5a5
- name: hidapi
buildsystem: cmake-ninja
config-opts:
- -DCMAKE_BUILD_TYPE=Release
sources:
- type: archive
url: https://github.com/libusb/hidapi/archive/hidapi-0.13.1.tar.gz
sha256: 476a2c9a4dc7d1fc97dd223b84338dbea3809a84caea2dcd887d9778725490e3
- name: libzmq
config-opts:
- --with-libsodium
- --disable-Werror
sources:
- type: archive
url: https://github.com/zeromq/libzmq/releases/download/v4.3.4/zeromq-4.3.4.tar.gz
sha256: c593001a89f5a85dd2ddf564805deb860e02471171b3f204944857336295c3e5
- name: libgss
sources:
- type: archive
url: https://ftp.gnu.org/gnu/gss/gss-1.0.4.tar.gz
sha256: ecceabdef4cae3fce7218b2ecb83eb4227dba44b53b61b8c2b2e88ae02419c73
- name: libuv
buildsystem: cmake-ninja
config-opts:
- -DCMAKE_BUILD_TYPE=Release
sources:
- type: archive
url: https://github.com/libuv/libuv/archive/v1.44.2.tar.gz
sha256: e6e2ba8b4c349a4182a33370bb9be5e23c51b32efb9b9e209d0e8556b73a48da
- name: p2pool
buildsystem: cmake-ninja
config-opts:
- -DCMAKE_BUILD_TYPE=Release
- -DWITH_LTO=OFF
sources:
- type: git
url: https://github.com/SChernykh/p2pool
tag: v3.2
commit: 92827035e07ff15da6b7645a332f3e59aa0ab1c4
post-install:
- install -Dm755 p2pool $FLATPAK_DEST/bin/p2pool
- name: monero-gui
buildsystem: cmake-ninja
config-opts:
- -DCMAKE_BUILD_TYPE=Release
- -DWITH_DESKTOP_ENTRY=OFF
- -DWITH_UPDATER=OFF
build-options:
arch:
aarch64:
config-opts:
- -DARCH=armv8-a
- -DBUILD_TAG=linux-armv8
x86_64:
config-opts:
- -DARCH=default
sources:
- type: dir
path: ../
post-install:
- install -Dpm644 share/org.getmonero.Monero.desktop $FLATPAK_DEST/share/applications/$FLATPAK_ID.desktop
- install -Dpm644 share/org.getmonero.Monero.metainfo.xml $FLATPAK_DEST/share/metainfo/$FLATPAK_ID.metainfo.xml
- for x in 16 24 32 48 64 96 128 256; do install -Dpm644 images/appicons/${x}x${x}.png $FLATPAK_DEST/share/icons/hicolor/${x}x${x}/apps/$FLATPAK_ID.png; done

View File

@@ -117,8 +117,17 @@ bool DaemonManager::start(const QString &flags, NetworkType::Type nettype, const
connect(m_daemon.get(), SIGNAL(readyReadStandardOutput()), this, SLOT(printOutput()));
connect(m_daemon.get(), SIGNAL(readyReadStandardError()), this, SLOT(printError()));
// Start monerod
bool started = m_daemon->startDetached(m_monerod, arguments);
#if defined(Q_OS_MAC) && defined(__aarch64__)
// RandomX crashes with JIT enabled when started as a detached process, disable it for now
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
env.insert("MONERO_RANDOMX_UMASK", "8");
m_daemon->setProcessEnvironment(env);
#endif
m_daemon->setProgram(m_monerod);
m_daemon->setArguments(arguments);
bool started = m_daemon->startDetached();
// add state changed listener
connect(m_daemon.get(), SIGNAL(stateChanged(QProcess::ProcessState)), this, SLOT(stateChanged(QProcess::ProcessState)));
@@ -130,8 +139,8 @@ bool DaemonManager::start(const QString &flags, NetworkType::Type nettype, const
}
// Start start watcher
m_scheduler.run([this, nettype, noSync] {
if (startWatcher(nettype)) {
m_scheduler.run([this, nettype, dataDir, noSync] {
if (startWatcher(nettype, dataDir)) {
emit daemonStarted();
m_noSync = noSync;
} else {
@@ -142,13 +151,13 @@ bool DaemonManager::start(const QString &flags, NetworkType::Type nettype, const
return true;
}
void DaemonManager::stopAsync(NetworkType::Type nettype, const QJSValue& callback)
void DaemonManager::stopAsync(NetworkType::Type nettype, const QString &dataDir, const QJSValue& callback)
{
const auto feature = m_scheduler.run([this, nettype] {
const auto feature = m_scheduler.run([this, nettype, dataDir] {
QString message;
sendCommand({"exit"}, nettype, message);
sendCommand({"exit"}, nettype, dataDir, message);
return QJSValueList({stopWatcher(nettype)});
return QJSValueList({stopWatcher(nettype, dataDir)});
}, callback);
if (!feature.first)
@@ -157,14 +166,14 @@ void DaemonManager::stopAsync(NetworkType::Type nettype, const QJSValue& callbac
}
}
bool DaemonManager::startWatcher(NetworkType::Type nettype) const
bool DaemonManager::startWatcher(NetworkType::Type nettype, const QString &dataDir) const
{
// Check if daemon is started every 2 seconds
QElapsedTimer timer;
timer.start();
while(true && !m_app_exit && timer.elapsed() / 1000 < DAEMON_START_TIMEOUT_SECONDS ) {
QThread::sleep(2);
if(!running(nettype)) {
if(!running(nettype, dataDir)) {
qDebug() << "daemon not running. checking again in 2 seconds.";
} else {
qDebug() << "daemon is started. Waiting 5 seconds to let daemon catch up";
@@ -175,14 +184,14 @@ bool DaemonManager::startWatcher(NetworkType::Type nettype) const
return false;
}
bool DaemonManager::stopWatcher(NetworkType::Type nettype) const
bool DaemonManager::stopWatcher(NetworkType::Type nettype, const QString &dataDir) const
{
// Check if daemon is running every 2 seconds. Kill if still running after 10 seconds
int counter = 0;
while(true && !m_app_exit) {
QThread::sleep(2);
counter++;
if(running(nettype)) {
if(running(nettype, dataDir)) {
qDebug() << "Daemon still running. " << counter;
if(counter >= 5) {
qDebug() << "Killing it! ";
@@ -236,10 +245,10 @@ void DaemonManager::printError()
}
}
bool DaemonManager::running(NetworkType::Type nettype) const
bool DaemonManager::running(NetworkType::Type nettype, const QString &dataDir) const
{
QString status;
sendCommand({"sync_info"}, nettype, status);
sendCommand({"sync_info"}, nettype, dataDir, status);
qDebug() << status;
return status.contains("Height:");
}
@@ -249,14 +258,14 @@ bool DaemonManager::noSync() const noexcept
return m_noSync;
}
void DaemonManager::runningAsync(NetworkType::Type nettype, const QJSValue& callback) const
void DaemonManager::runningAsync(NetworkType::Type nettype, const QString &dataDir, const QJSValue& callback) const
{
m_scheduler.run([this, nettype] {
return QJSValueList({running(nettype)});
m_scheduler.run([this, nettype, dataDir] {
return QJSValueList({running(nettype, dataDir)});
}, callback);
}
bool DaemonManager::sendCommand(const QStringList &cmd, NetworkType::Type nettype, QString &message) const
bool DaemonManager::sendCommand(const QStringList &cmd, NetworkType::Type nettype, const QString &dataDir, QString &message) const
{
QProcess p;
QStringList external_cmd(cmd);
@@ -267,6 +276,11 @@ bool DaemonManager::sendCommand(const QStringList &cmd, NetworkType::Type nettyp
else if (nettype == NetworkType::STAGENET)
external_cmd << "--stagenet";
// Custom data-dir
if (!dataDir.isEmpty()) {
external_cmd << "--data-dir" << dataDir;
}
qDebug() << "sending external cmd: " << external_cmd;
@@ -278,11 +292,11 @@ bool DaemonManager::sendCommand(const QStringList &cmd, NetworkType::Type nettyp
return started;
}
void DaemonManager::sendCommandAsync(const QStringList &cmd, NetworkType::Type nettype, const QJSValue& callback) const
void DaemonManager::sendCommandAsync(const QStringList &cmd, NetworkType::Type nettype, const QString &dataDir, const QJSValue& callback) const
{
m_scheduler.run([this, cmd, nettype] {
m_scheduler.run([this, cmd, nettype, dataDir] {
QString message;
return QJSValueList({sendCommand(cmd, nettype, message)});
return QJSValueList({sendCommand(cmd, nettype, dataDir, message)});
}, callback);
}
@@ -337,6 +351,57 @@ bool DaemonManager::checkLmdbExists(QString datadir) {
return validateDataDir(datadir).value("lmdbExists").value<bool>();
}
QString DaemonManager::getArgs(const QString &dataDir) {
if (!running(NetworkType::MAINNET, dataDir)) {
return args;
}
QProcess p;
QStringList tempArgs;
#ifdef Q_OS_WIN
//powershell
tempArgs << "Get-CimInstance Win32_Process -Filter \"name = 'monerod.exe'\" | select -ExpandProperty CommandLine ";
p.setProgram("powershell");
p.setArguments(tempArgs);
p.start();
p.waitForFinished();
args = p.readAllStandardOutput().simplified().trimmed();
#elif defined(Q_OS_UNIX)
//pgrep
tempArgs << "monerod";
p.setProgram("pgrep");
p.setArguments(tempArgs);
p.start();
p.waitForFinished();
QString pid = p.readAllStandardOutput().trimmed();
if (pid.isEmpty()) {
return args;
}
tempArgs.clear();
//ps
tempArgs << "-o";
tempArgs << "args=";
tempArgs << "-fp";
tempArgs << pid;
p.setProgram("ps");
p.setArguments(tempArgs);
p.start();
p.waitForFinished();
args = p.readAllStandardOutput().trimmed();
#endif
if (args.contains("--")) {
int index = args.indexOf("--");
args.remove(0, index);
}
else {
args = "";
}
return args;
}
DaemonManager::DaemonManager(QObject *parent)
: QObject(parent)
, m_scheduler(this)

View File

@@ -48,23 +48,24 @@ public:
~DaemonManager();
Q_INVOKABLE bool start(const QString &flags, NetworkType::Type nettype, const QString &dataDir = "", const QString &bootstrapNodeAddress = "", bool noSync = false, bool pruneBlockchain = false);
Q_INVOKABLE void stopAsync(NetworkType::Type nettype, const QJSValue& callback);
Q_INVOKABLE void stopAsync(NetworkType::Type nettype, const QString &dataDir, const QJSValue& callback);
Q_INVOKABLE bool noSync() const noexcept;
// return true if daemon process is started
Q_INVOKABLE void runningAsync(NetworkType::Type nettype, const QJSValue& callback) const;
Q_INVOKABLE void runningAsync(NetworkType::Type nettype, const QString &dataDir, const QJSValue& callback) const;
// Send daemon command from qml and prints output in console window.
Q_INVOKABLE void sendCommandAsync(const QStringList &cmd, NetworkType::Type nettype, const QJSValue& callback) const;
Q_INVOKABLE void sendCommandAsync(const QStringList &cmd, NetworkType::Type nettype, const QString &dataDir, const QJSValue& callback) const;
Q_INVOKABLE void exit();
Q_INVOKABLE QVariantMap validateDataDir(const QString &dataDir) const;
Q_INVOKABLE bool checkLmdbExists(QString datadir);
Q_INVOKABLE QString getArgs(const QString &dataDir);
private:
bool running(NetworkType::Type nettype) const;
bool sendCommand(const QStringList &cmd, NetworkType::Type nettype, QString &message) const;
bool startWatcher(NetworkType::Type nettype) const;
bool stopWatcher(NetworkType::Type nettype) const;
bool running(NetworkType::Type nettype, const QString &dataDir) const;
bool sendCommand(const QStringList &cmd, NetworkType::Type nettype, const QString &dataDir, QString &message) const;
bool startWatcher(NetworkType::Type nettype, const QString &dataDir) const;
bool stopWatcher(NetworkType::Type nettype, const QString &dataDir) const;
signals:
void daemonStarted() const;
void daemonStopped() const;
@@ -82,6 +83,7 @@ private:
QString m_monerod;
bool m_app_exit = false;
bool m_noSync = false;
QString args = "";
mutable FutureScheduler m_scheduler;
};

View File

@@ -101,20 +101,30 @@ NetworkType::Type Wallet::nettype() const
void Wallet::updateConnectionStatusAsync()
{
m_scheduler.run([this] {
qDebug() << "updateConnectionStatusAsync current status:" << m_connectionStatus;
if (m_connectionStatus == Wallet::ConnectionStatus_Disconnected)
{
setConnectionStatus(ConnectionStatus_Connecting);
}
ConnectionStatus newStatus = static_cast<ConnectionStatus>(m_walletImpl->connected());
setConnectionStatus(newStatus);
qDebug() << "Newest wallet status:" << newStatus;
if (m_connectionStatus != newStatus)
{
setConnectionStatus(newStatus);
if (newStatus == ConnectionStatus_Connected)
{
startRefresh();
}
}
// Release lock
m_connectionStatusRunning = false;
m_connectionStatusTime.restart();
});
}
Wallet::ConnectionStatus Wallet::connected(bool forceCheck)
{
if (!m_initialized)
if (!m_initialized || m_initializing)
{
return ConnectionStatus_Connecting;
}
@@ -123,7 +133,6 @@ Wallet::ConnectionStatus Wallet::connected(bool forceCheck)
if (forceCheck || (m_connectionStatusTime.elapsed() / 1000 > m_connectionStatusTtl && !m_connectionStatusRunning) || m_connectionStatusTime.elapsed() > 30000) {
qDebug() << "Checking connection status";
m_connectionStatusRunning = true;
m_connectionStatusTime.restart();
updateConnectionStatusAsync();
}
@@ -156,10 +165,9 @@ void Wallet::setConnectionStatus(ConnectionStatus value)
}
m_connectionStatus = value;
emit connectionStatusChanged(m_connectionStatus);
emit connectionStatusChanged(value);
bool disconnected = m_connectionStatus == Wallet::ConnectionStatus_Connecting ||
m_connectionStatus == Wallet::ConnectionStatus_Disconnected;
bool disconnected = value != Wallet::ConnectionStatus_Connected;
if (m_disconnected != disconnected)
{
@@ -280,6 +288,8 @@ void Wallet::initAsync(
const QString &proxyAddress /* = "" */)
{
qDebug() << "initAsync: " + daemonAddress;
m_initializing = true;
pauseRefresh();
const auto future = m_scheduler.run([this, daemonAddress, trustedDaemon, upperTransactionLimit, isRecovering, isRecoveringFromDevice, restoreHeight, proxyAddress] {
m_initialized = init(
daemonAddress,
@@ -289,12 +299,12 @@ void Wallet::initAsync(
isRecoveringFromDevice,
restoreHeight,
proxyAddress);
m_initializing = false;
if (m_initialized)
{
emit walletCreationHeightChanged();
qDebug() << "init async finished - starting refresh";
qDebug() << "init async finished: " + daemonAddress;
connected(true);
startRefresh();
}
else
{
@@ -544,12 +554,14 @@ bool Wallet::refresh(bool historyAndSubaddresses /* = true */)
void Wallet::startRefresh()
{
qDebug() << "Starting refresh";
m_refreshEnabled = true;
m_refreshNow = true;
}
void Wallet::pauseRefresh()
{
qDebug() << "Pausing refresh";
m_refreshEnabled = false;
}
@@ -1001,46 +1013,6 @@ QString Wallet::getDaemonLogPath() const
return QString::fromStdString(m_walletImpl->getDefaultDataDir()) + "/bitmonero.log";
}
bool Wallet::blackballOutput(const QString &amount, const QString &offset)
{
return m_walletImpl->blackballOutput(amount.toStdString(), offset.toStdString());
}
bool Wallet::blackballOutputs(const QList<QString> &pubkeys, bool add)
{
std::vector<std::string> std_pubkeys;
foreach (const QString &pubkey, pubkeys) {
std_pubkeys.push_back(pubkey.toStdString());
}
return m_walletImpl->blackballOutputs(std_pubkeys, add);
}
bool Wallet::blackballOutputs(const QString &filename, bool add)
{
QFile file(filename);
try {
if (!file.open(QIODevice::ReadOnly))
return false;
QList<QString> outputs;
QTextStream in(&file);
while (!in.atEnd()) {
outputs.push_back(in.readLine());
}
file.close();
return blackballOutputs(outputs, add);
}
catch (const std::exception &e) {
file.close();
return false;
}
}
bool Wallet::unblackballOutput(const QString &amount, const QString &offset)
{
return m_walletImpl->unblackballOutput(amount.toStdString(), offset.toStdString());
}
QString Wallet::getRing(const QString &key_image)
{
std::vector<uint64_t> cring;
@@ -1138,6 +1110,7 @@ Wallet::Wallet(Monero::Wallet *w, QObject *parent)
, m_connectionStatusTtl(WALLET_CONNECTION_STATUS_CACHE_TTL_SECONDS)
, m_disconnected(true)
, m_initialized(false)
, m_initializing(false)
, m_currentSubaddressAccount(0)
, m_subaddress(new Subaddress(m_walletImpl->subaddress(), this))
, m_subaddressModel(nullptr)

View File

@@ -341,12 +341,6 @@ public:
QString getDaemonLogPath() const;
QString getWalletLogPath() const;
// Blackalled outputs
Q_INVOKABLE bool blackballOutput(const QString &amount, const QString &offset);
Q_INVOKABLE bool blackballOutputs(const QList<QString> &outputs, bool add);
Q_INVOKABLE bool blackballOutputs(const QString &filename, bool add);
Q_INVOKABLE bool unblackballOutput(const QString &amount, const QString &offset);
// Rings
Q_INVOKABLE QString getRing(const QString &key_image);
Q_INVOKABLE QString getRings(const QString &txid);
@@ -461,6 +455,7 @@ private:
mutable QElapsedTimer m_connectionStatusTime;
bool m_disconnected;
std::atomic<bool> m_initialized;
std::atomic<bool> m_initializing;
uint32_t m_currentSubaddressAccount;
Subaddress * m_subaddress;
mutable SubaddressModel * m_subaddressModel;

View File

@@ -156,6 +156,7 @@ bool isLinux = false;
bool isTails = false;
bool isDesktop = false;
bool isOpenGL = true;
bool isARM = false;
int main(int argc, char *argv[])
{
@@ -177,6 +178,9 @@ int main(int argc, char *argv[])
#elif defined(Q_OS_MAC)
bool isMac = true;
#endif
#if defined(__aarch64__)
bool isARM = true;
#endif
// detect low graphics mode (start-low-graphics-mode.bat)
if(qgetenv("QMLSCENE_DEVICE") == "softwarecontext")
@@ -483,6 +487,7 @@ Verify update binary using 'shasum'-compatible (SHA256 algo) output signed by tw
engine.rootContext()->setContextProperty("isAndroid", isAndroid);
engine.rootContext()->setContextProperty("isOpenGL", isOpenGL);
engine.rootContext()->setContextProperty("isTails", isTails);
engine.rootContext()->setContextProperty("isARM", isARM);
engine.rootContext()->setContextProperty("screenAvailableWidth", screenAvailableSize.width());
engine.rootContext()->setContextProperty("screenAvailableHeight", screenAvailableSize.height());

View File

@@ -63,6 +63,7 @@
#include "QR-Code-scanner/Decoder.h"
#include "qt/ScopeGuard.h"
#include "NetworkType.h"
namespace
{
@@ -159,6 +160,18 @@ QList<QString> OSHelper::grabQrCodesFromScreen() const
return codes;
}
bool OSHelper::openFile(const QString &filePath) const
{
QString canonicalFilePath = QFileInfo(filePath).canonicalFilePath();
QUrl url = QUrl::fromLocalFile(canonicalFilePath);
if (!url.isValid())
{
qWarning() << "Malformed file path" << canonicalFilePath << url.errorString();
return false;
}
return QDesktopServices::openUrl(url);
}
bool OSHelper::openContainingFolder(const QString &filePath) const
{
QString canonicalFilePath = QFileInfo(filePath).canonicalFilePath();
@@ -280,3 +293,41 @@ bool OSHelper::installed() const
return false;
#endif
}
std::pair<quint8, QString> OSHelper::getNetworkTypeAndAddressFromFile(const QString &wallet)
{
quint8 networkType = NetworkType::MAINNET;
QString address = QString("");
// attempt to retreive wallet address
if(QFile::exists(wallet + ".address.txt")){
QFile file(wallet + ".address.txt");
file.open(QFile::ReadOnly | QFile::Text);
QString _address = QString(file.readAll());
if(!_address.isEmpty()){
address = _address;
if(address.startsWith("5") || address.startsWith("7")){
networkType = NetworkType::STAGENET;
} else if(address.startsWith("9") || address.startsWith("B")){
networkType = NetworkType::TESTNET;
}
}
file.close();
}
return std::make_pair(networkType, address);
}
quint8 OSHelper::getNetworkTypeFromFile(const QString &keysPath) const
{
QString walletPath = keysPath;
if(keysPath.endsWith(".keys")){
walletPath = keysPath.mid(0,keysPath.length()-5);
}
return getNetworkTypeAndAddressFromFile(walletPath).first;
}
void OSHelper::openSeedTemplate() const
{
QFile::copy(":/wizard/template.pdf", QDir::tempPath() + "/seed_template.pdf");
openFile(QDir::tempPath() + "/seed_template.pdf");
}

View File

@@ -46,13 +46,17 @@ public:
Q_INVOKABLE void createDesktopEntry() const;
Q_INVOKABLE QString downloadLocation() const;
Q_INVOKABLE QList<QString> grabQrCodesFromScreen() const;
Q_INVOKABLE bool openFile(const QString &filePath) const;
Q_INVOKABLE bool openContainingFolder(const QString &filePath) const;
Q_INVOKABLE QString openSaveFileDialog(const QString &title, const QString &folder, const QString &filename) const;
Q_INVOKABLE QString temporaryFilename() const;
Q_INVOKABLE QString temporaryPath() const;
Q_INVOKABLE bool removeTemporaryWallet(const QString &walletName) const;
Q_INVOKABLE bool isCapsLock() const;
Q_INVOKABLE quint8 getNetworkTypeFromFile(const QString &keysPath) const;
Q_INVOKABLE void openSeedTemplate() const;
static std::pair<quint8, QString> getNetworkTypeAndAddressFromFile(const QString &wallet);
private:
bool installed() const;

View File

@@ -43,23 +43,31 @@
#include <QMap>
#include <QCryptographicHash>
#if defined(Q_OS_MACOS) && defined(__aarch64__) && !defined(Q_OS_MACOS_AARCH64)
#define Q_OS_MACOS_AARCH64
#endif
void P2PoolManager::download() {
m_scheduler.run([this] {
QUrl url;
QString fileName;
QString validHash;
#ifdef Q_OS_WIN
url = "https://github.com/SChernykh/p2pool/releases/download/v2.2.1/p2pool-v2.2.1-windows-x64.zip";
fileName = m_p2poolPath + "/p2pool-v2.2.1-windows-x64.zip";
validHash = "06b6fe302600c959007bf94e7a5b445f45f823dc4e43ae6cf03b3b98a805167a";
url = "https://github.com/SChernykh/p2pool/releases/download/v3.7/p2pool-v3.7-windows-x64.zip";
fileName = m_p2poolPath + "/p2pool-v3.7-windows-x64.zip";
validHash = "9888afb51a206f1d2c6efc414dd1f498f82de58c689fbb73aceecd88ecdf6c43";
#elif defined(Q_OS_LINUX)
url = "https://github.com/SChernykh/p2pool/releases/download/v2.2.1/p2pool-v2.2.1-linux-x64.tar.gz";
fileName = m_p2poolPath + "/p2pool-v2.2.1-linux-x64.tar.gz";
validHash = "02f1daea0f8f99076b7da3368a43cc3989b800f8b5afaf4dfc7e8f9bdc27d274";
url = "https://github.com/SChernykh/p2pool/releases/download/v3.7/p2pool-v3.7-linux-x64.tar.gz";
fileName = m_p2poolPath + "/p2pool-v3.7-linux-x64.tar.gz";
validHash = "d5b932053f56f85b119450e64b1a7765c632f16c6226c8762b00e48f50e7e421";
#elif defined(Q_OS_MACOS_AARCH64)
url = "https://github.com/SChernykh/p2pool/releases/download/v3.7/p2pool-v3.7-macos-aarch64.tar.gz";
fileName = m_p2poolPath + "/p2pool-v3.7-macos-aarch64.tar.gz";
validHash = "d2b483a10c01f4a84faacbb8e2eedafef451ca4e6a4128e44800018556bb2c62";
#elif defined(Q_OS_MACOS)
url = "https://github.com/SChernykh/p2pool/releases/download/v2.2.1/p2pool-v2.2.1-macos-x64.tar.gz";
fileName = m_p2poolPath + "/p2pool-v2.2.1-macos-x64.tar.gz";
validHash = "d973a8dca922f209dfb6f203006f93664e19d870975621bec07e9d855e79d7d5";
url = "https://github.com/SChernykh/p2pool/releases/download/v3.7/p2pool-v3.7-macos-x64.tar.gz";
fileName = m_p2poolPath + "/p2pool-v3.7-macos-x64.tar.gz";
validHash = "444ded858b18a9ecba7d08a2d333188d1758a3da358817887d28d0827dc4287b";
#endif
QFile file(fileName);
epee::net_utils::http::http_simple_client http_client;
@@ -68,7 +76,10 @@ void P2PoolManager::download() {
std::chrono::milliseconds timeout = std::chrono::seconds(10);
http_client.set_server(url.host().toStdString(), "443", {});
bool success = http_client.invoke_get(url.path().toStdString(), timeout, {}, std::addressof(response), {{"User-Agent", userAgent}});
if (response->m_response_code == 302) {
if (success && response->m_response_code == 404) {
emit p2poolDownloadFailure(BinaryNotAvailable);
return;
} else if (success && response->m_response_code == 302) {
epee::net_utils::http::fields_list fields = response->m_header_info.m_etc_fields;
for (std::pair<std::string, std::string> i : fields) {
if (i.first == "Location") {
@@ -82,7 +93,7 @@ void P2PoolManager::download() {
}
}
if (!success) {
emit p2poolDownloadFailure();
emit p2poolDownloadFailure(ConnectionIssue);
}
else {
std::string stringData = response->m_body;
@@ -90,7 +101,7 @@ void P2PoolManager::download() {
QByteArray hashData = QCryptographicHash::hash(data, QCryptographicHash::Sha256);
QString hash = hashData.toHex();
if (hash != validHash) {
emit p2poolDownloadFailure();
emit p2poolDownloadFailure(HashVerificationFailed);
}
else {
file.open(QIODevice::WriteOnly);
@@ -102,7 +113,7 @@ void P2PoolManager::download() {
emit p2poolDownloadSuccess();
}
else {
emit p2poolDownloadFailure();
emit p2poolDownloadFailure(InstallationFailed);
}
}
}

View File

@@ -51,13 +51,22 @@ public:
Q_INVOKABLE bool isInstalled();
Q_INVOKABLE void getStatus();
Q_INVOKABLE void download();
enum DownloadError {
BinaryNotAvailable,
ConnectionIssue,
HashVerificationFailed,
InstallationFailed,
};
Q_ENUM(DownloadError)
private:
bool running(NetworkType::Type nettype) const;
signals:
void p2poolStartFailure() const;
void p2poolStatus(bool isMining, int hashrate) const;
void p2poolDownloadFailure() const;
void p2poolDownloadFailure(int errorCode) const;
void p2poolDownloadSuccess() const;
private:

View File

@@ -39,6 +39,7 @@
#include "libwalletqt/WalletManager.h"
#include "NetworkType.h"
#include "qt/utils.h"
#include "main/oshelper.h"
#include "KeysFiles.h"
@@ -121,26 +122,9 @@ void WalletKeysFilesModel::findWallets(const QString &moneroAccountsDir)
}
QString wallet(keysFileinfo.path() + QDir::separator() + keysFileinfo.completeBaseName());
quint8 networkType = NetworkType::MAINNET;
QString address = QString("");
// attempt to retreive wallet address
if(fileExists(wallet + ".address.txt")){
QFile file(wallet + ".address.txt");
file.open(QFile::ReadOnly | QFile::Text);
QString _address = QString(file.readAll());
if(!_address.isEmpty()){
address = _address;
if(address.startsWith("5") || address.startsWith("7")){
networkType = NetworkType::STAGENET;
} else if(address.startsWith("9") || address.startsWith("B")){
networkType = NetworkType::TESTNET;
}
}
file.close();
}
auto networkTypeAndAddress = OSHelper::getNetworkTypeAndAddressFromFile(wallet);
quint8 networkType = networkTypeAndAddress.first;
QString address = networkTypeAndAddress.second;
this->addWalletKeysFile(WalletKeysFiles(wallet, networkType, std::move(address)));
}

26
wizard/SeedListGrid.qml Normal file
View File

@@ -0,0 +1,26 @@
import QtQuick 2.9
import QtQuick.Dialogs 1.2
import QtQuick.Layouts 1.2
import QtQuick.Controls 2.0
import "../js/Wizard.js" as Wizard
import "../js/Utils.js" as Utils
import "../components" as MoneroComponents
GridLayout {
id: seedGrid
Layout.alignment: Qt.AlignHCenter
flow: GridLayout.TopToBottom
columns: wizardController.layoutScale == 1 ? 5 : wizardController.layoutScale == 2 ? 4 : wizardController.layoutScale == 3 ? 3 : 2
rows: wizardController.layoutScale == 1 ? 5 :wizardController.layoutScale == 2 ? 7 : wizardController.layoutScale == 3 ? 9 : 13
columnSpacing: wizardController.layoutScale == 1 ? 25 : 18
rowSpacing: 0
Component.onCompleted: {
var seed = wizardController.walletOptionsSeed.split(" ");
var component = Qt.createComponent("SeedListItem.qml");
for(var i = 0; i < seed.length; i++) {
component.createObject(seedGrid, {wordNumber: i, word: seed[i]});
}
}
}

153
wizard/SeedListItem.qml Normal file
View File

@@ -0,0 +1,153 @@
import "../components" as MoneroComponents;
import QtQuick 2.9
import QtQuick.Layouts 1.2
import FontAwesome 1.0
ColumnLayout {
id: seedListItem
property var wordNumber;
property var word;
property var wordSpelled: (word.split("")).join(". ")
property var acessibleText: (wordNumber + 1) + word
property alias wordText: wordText
property alias lineEdit: lineEdit
property alias icon: icon
spacing: 0
Layout.preferredWidth: 136
Layout.maximumWidth: 136
Layout.minimumWidth: 136
Accessible.role: Accessible.StaticText
Accessible.name: lineEdit.inputHasFocus && !lineEdit.readOnly ? qsTr("Please enter the word number") + " " + (wordNumber + 1) + "." +
(icon.visible ? (icon.wordsMatch ? qsTr("Green check mark") + "."
: qsTr("Red exclamation mark") + ".")
: "")
: (wordNumber + 1) + word + ". " +
(lineEdit.inputHasFocus && lineEdit.readOnly ? qsTr("Green check mark")
: qsTr("This word is spelled ") + " " + wordSpelled + ".") +
translationManager.emptyString
KeyNavigation.up: wordNumber == 0 ? (recoveryPhraseLabel.visible ? recoveryPhraseLabel : header) : parent.children[wordNumber - 1]
KeyNavigation.backtab: wordNumber == 0 ? (recoveryPhraseLabel.visible ? recoveryPhraseLabel : header) : parent.children[wordNumber - 1]
Keys.onUpPressed: focusOnPreviousField()
Keys.onBacktabPressed: focusOnPreviousField()
Keys.onDownPressed: focusOnNextField()
Keys.onTabPressed: focusOnNextField()
function focusOnPreviousField() {
if (wizardCreateWallet2.state == "verify") {
if (wordNumber < 5) {
if (recoveryPhraseLabel.visible) {
return recoveryPhraseLabel.forceActiveFocus();
} else {
return header.forceActiveFocus();
}
} else if (wordNumber >= 5 && wordNumber < 25) {
return parent.children[wizardCreateWallet2.hiddenWords[parseInt(wordNumber / 5) - 1]].lineEdit.forceActiveFocus()
}
} else {
if (wordNumber == 0) {
if (recoveryPhraseLabel.visible) {
return recoveryPhraseLabel.forceActiveFocus();
} else {
return header.forceActiveFocus();
}
} else {
return parent.children[wordNumber - 1].forceActiveFocus()
}
}
}
function focusOnNextField() {
if (wizardCreateWallet2.state == "verify") {
if (wordNumber < 20) {
return parent.children[wizardCreateWallet2.hiddenWords[parseInt(wordNumber / 5) + 1]].lineEdit.forceActiveFocus()
} else {
return navigation.btnPrev.forceActiveFocus()
}
} else {
if (wordNumber == 24) {
if (createNewSeedButton.visible) {
return createNewSeedButton.forceActiveFocus()
} else {
return printPDFTemplate.forceActiveFocus()
}
} else {
return parent.children[wordNumber + 1].forceActiveFocus()
}
}
}
RowLayout {
id: wordRow
spacing: 0
MoneroComponents.Label {
color: lineEdit.inputHasFocus ? MoneroComponents.Style.defaultFontColor : MoneroComponents.Style.dimmedFontColor
fontSize: 13
text: (wordNumber + 1)
themeTransition: false
}
MoneroComponents.LineEdit {
id: lineEdit
property bool firstUserInput: true
inputHeight: 29
inputPaddingLeft: 10
inputPaddingBottom: 2
inputPaddingRight: 0
borderDisabled: true
visible: !wordText.visible
fontSize: 16
fontBold: true
text: ""
tabNavigationEnabled: false
onTextChanged: {
if (lineEdit.text.length == wordText.text.length) {
firstUserInput = false;
}
}
onBacktabPressed: focusOnPreviousField()
onTabPressed: focusOnNextField()
}
MoneroComponents.Label {
id: wordText
Layout.leftMargin: 10
color: MoneroComponents.Style.defaultFontColor
fontSize: seedListItem.focus ? 19 : 16
fontBold: true
text: word
themeTransition: false
}
MoneroComponents.TextPlain {
id: icon
Layout.leftMargin: wordsMatch ? 10 : 0
property bool wordsMatch: lineEdit.text === wordText.text
property bool partialWordMatches: lineEdit.text === wordText.text.substring(0, lineEdit.text.length)
visible: lineEdit.text.length > 0 && !lineEdit.firstUserInput || lineEdit.firstUserInput && !partialWordMatches
font.family: FontAwesome.fontFamilySolid
font.styleName: "Solid"
font.pixelSize: 15
text: wordsMatch ? FontAwesome.checkCircle : FontAwesome.exclamationCircle
color: wordsMatch ? (MoneroComponents.Style.blackTheme ? "#00FF00" : "#008000") : "#FF0000"
themeTransition: false
onTextChanged: {
if (wizardCreateWallet2.seedListGrid && wordsMatch) {
if (wordNumber < 20) {
focusOnNextField();
}
lineEdit.readOnly = true;
}
}
}
}
Rectangle {
id: underLine
color: lineEdit.inputHasFocus ? MoneroComponents.Style.defaultFontColor : MoneroComponents.Style.appWindowBorderColor
Layout.fillWidth: true
height: 1
}
}

View File

@@ -50,13 +50,14 @@ Rectangle {
signal useMoneroClicked()
signal walletCreatedFromDevice(bool success)
function restart() {
function restart(generatingNewSeed) {
// Clear up any state, including `m_wallet`, which
// is the temp. wallet object whilst creating new wallets.
// This function is called automatically by navigating to `wizardHome`.
wizardStateView.state = "wizardHome"
wizardController.walletOptionsName = defaultAccountName;
wizardController.walletOptionsLocation = '';
if(!generatingNewSeed) {
wizardController.walletOptionsName = defaultAccountName;
wizardController.walletOptionsLocation = '';
}
wizardController.walletOptionsPassword = '';
wizardController.walletOptionsSeed = '';
wizardController.walletOptionsSeedOffset = '';
@@ -113,10 +114,18 @@ Rectangle {
property int layoutScale: {
if(appWindow.width < 800){
return 1;
} else {
if (appWindow.width < 506) {
//mobile (25 word mnemonic seed displayed in 2 columns)
return 4;
} else if (appWindow.width < 660) {
//tablet (25 word mnemonic seed displayed in 3 columns)
return 3;
} else if (appWindow.width < 842) {
//tablet (25 word mnemonic seed displayed in 4 columns)
return 2;
} else if (appWindow.width >= 842) {
//desktop (25 word mnemonic seed displayed in 5 columns)
return 1;
}
}
@@ -131,6 +140,7 @@ Rectangle {
property WizardCreateWallet2 wizardCreateWallet2View: WizardCreateWallet2 { }
property WizardCreateWallet3 wizardCreateWallet3View: WizardCreateWallet3 { }
property WizardCreateWallet4 wizardCreateWallet4View: WizardCreateWallet4 { }
property WizardCreateWallet5 wizardCreateWallet5View: WizardCreateWallet5 { }
property WizardRestoreWallet1 wizardRestoreWallet1View: WizardRestoreWallet1 { }
property WizardRestoreWallet2 wizardRestoreWallet2View: WizardRestoreWallet2 { }
property WizardRestoreWallet3 wizardRestoreWallet3View: WizardRestoreWallet3 { }
@@ -195,6 +205,10 @@ Rectangle {
name: "wizardCreateWallet4"
PropertyChanges { target: wizardStateView; currentView: wizardStateView.wizardCreateWallet4View }
PropertyChanges { target: wizardFlickable; contentHeight: wizardStateView.wizardCreateWallet4View.pageHeight + 80 }
}, State {
name: "wizardCreateWallet5"
PropertyChanges { target: wizardStateView; currentView: wizardStateView.wizardCreateWallet5View }
PropertyChanges { target: wizardFlickable; contentHeight: wizardStateView.wizardCreateWallet5View.pageHeight + 80 }
}, State {
name: "wizardRestoreWallet1"
PropertyChanges { target: wizardStateView; currentView: wizardStateView.wizardRestoreWallet1View }
@@ -308,7 +322,9 @@ Rectangle {
sidebarVisible: false
onAccepted: {
wizardController.openWalletFile(fileDialog.fileUrl);
var keysPath = walletManager.urlToLocalPath(fileDialog.fileUrl)
persistentSettings.nettype = oshelper.getNetworkTypeFromFile(keysPath);
wizardController.openWalletFile(keysPath);
}
onRejected: {
console.log("Canceled")
@@ -354,6 +370,10 @@ Rectangle {
return;
}
if (wizardStateView.wizardCreateWallet2View.seedListGrid) {
wizardStateView.wizardCreateWallet2View.seedListGrid.destroy();
}
// make sure temporary wallet files are deleted
console.log("Removing temporary wallet: " + wizardController.tmpWalletFilename)
oshelper.removeTemporaryWallet(wizardController.tmpWalletFilename)

View File

@@ -54,6 +54,7 @@ Rectangle {
ListElement { column1: "Ledger Nano S"; column2: "Ledger";}
ListElement { column1: "Ledger Nano S Plus"; column2: "Ledger";}
ListElement { column1: "Ledger Nano X"; column2: "Ledger";}
ListElement { column1: "Ledger Stax"; column2: "Ledger";}
ListElement { column1: "Trezor Model T"; column2: "Trezor";}
}
@@ -170,6 +171,8 @@ Rectangle {
return "qrc:///images/ledgerNanoSPlus.png";
} else if (ledgerType == "Ledger Nano X") {
return "qrc:///images/ledgerNanoX.png";
} else if (ledgerType == "Ledger Stax") {
return "qrc:///images/ledgerStax.png";
}
}
return "";
@@ -282,7 +285,7 @@ Rectangle {
function onCreateWalletFromDeviceCompleted(written){
hideProcessingSplash();
if(written){
wizardStateView.state = "wizardCreateWallet2";
wizardStateView.state = "wizardCreateWallet3";
} else {
errorMsg.text = qsTr("Error writing wallet from hardware device. Check application logs.") + translationManager.emptyString;
}

View File

@@ -40,8 +40,8 @@ Rectangle {
color: "transparent"
property alias pageHeight: pageRoot.height
property alias pageRoot: pageRoot
property string viewName: "wizardCreateWallet1"
property alias seed: seed
ColumnLayout {
id: pageRoot
@@ -51,6 +51,8 @@ Rectangle {
anchors.horizontalCenter: parent.horizontalCenter;
spacing: 0
KeyNavigation.down: createWalletHeader
KeyNavigation.tab: createWalletHeader
ColumnLayout {
Layout.fillWidth: true
@@ -60,6 +62,7 @@ Rectangle {
spacing: 20
WizardHeader {
id: createWalletHeader
title: {
var nettype = persistentSettings.nettype;
return qsTr("Create a new wallet") + (nettype === 2 ? " (" + qsTr("stagenet") + ")"
@@ -67,146 +70,42 @@ Rectangle {
: "") + translationManager.emptyString
}
subtitle: qsTr("Creates a new wallet on this computer.") + translationManager.emptyString
Accessible.role: Accessible.StaticText
Accessible.name: title + subtitle
Keys.onUpPressed: wizardNav.btnNext.enabled ? wizardNav.btnNext.forceActiveFocus() : wizardNav.wizardProgress.forceActiveFocus()
Keys.onBacktabPressed: wizardNav.btnNext.enabled ? wizardNav.btnNext.forceActiveFocus() : wizardNav.wizardProgress.forceActiveFocus()
Keys.onDownPressed: walletInput.walletName.forceActiveFocus();
Keys.onTabPressed: walletInput.walletName.forceActiveFocus();
}
WizardWalletInput{
id: walletInput
}
ColumnLayout {
spacing: 0
Layout.topMargin: -10
Layout.fillWidth: true
MoneroComponents.LineEditMulti {
id: seed
spacing: 0
inputPaddingLeft: 16
inputPaddingRight: 16
inputPaddingTop: 20
inputPaddingBottom: 20
inputRadius: 0
fontSize: 18
fontBold: true
wrapMode: Text.WordWrap
backgroundColor: "red"
addressValidation: false
labelText: qsTr("Mnemonic seed") + translationManager.emptyString
labelFontSize: 14
copyButton: false
readOnly: true
placeholderText: "-"
text: wizardController.walletOptionsSeed
}
MoneroComponents.WarningBox {
Rectangle {
anchors.left: parent.left
anchors.top: parent.top
anchors.bottom: parent.bottom
width: 1
color: MoneroComponents.Style.inputBorderColorInActive
}
Rectangle {
anchors.right: parent.right
anchors.left: parent.left
anchors.bottom: parent.bottom
height: 1
color: MoneroComponents.Style.inputBorderColorInActive
}
Rectangle {
anchors.right: parent.right
anchors.top: parent.top
anchors.bottom: parent.bottom
width: 1
color: MoneroComponents.Style.inputBorderColorInActive
}
radius: 0
border.color: MoneroComponents.Style.inputBorderColorInActive
border.width: 0
text: qsTr("This seed is <b>very</b> important to write down and keep secret. It is all you need to backup and restore your wallet.") + translationManager.emptyString
}
}
ColumnLayout {
spacing: 0
Layout.topMargin: 10
Layout.fillWidth: true
MoneroComponents.LineEditMulti {
id: restoreHeight
spacing: 0
inputPaddingLeft: 16
inputPaddingRight: 16
inputPaddingTop: 20
inputPaddingBottom: 20
inputRadius: 0
fontSize: 18
fontBold: true
wrapMode: Text.WordWrap
labelText: qsTr("Wallet restore height") + translationManager.emptyString
labelFontSize: 14
copyButton: false
readOnly: true
text: Utils.roundDownToNearestThousand(wizardController.m_wallet ? wizardController.m_wallet.walletCreationHeight : 0)
}
MoneroComponents.WarningBox {
Rectangle {
anchors.left: parent.left
anchors.top: parent.top
anchors.bottom: parent.bottom
width: 1
color: MoneroComponents.Style.inputBorderColorInActive
}
Rectangle {
anchors.right: parent.right
anchors.left: parent.left
anchors.bottom: parent.bottom
height: 1
color: MoneroComponents.Style.inputBorderColorInActive
}
Rectangle {
anchors.right: parent.right
anchors.top: parent.top
anchors.bottom: parent.bottom
width: 1
color: MoneroComponents.Style.inputBorderColorInActive
}
radius: 0
border.color: MoneroComponents.Style.inputBorderColorInActive
border.width: 0
text: qsTr("Should you restore your wallet in the future, specifying this block number will recover your wallet quicker.") + translationManager.emptyString
}
rowLayout: false
walletNameKeyNavigationBackTab: createWalletHeader
browseButtonKeyNavigationTab: wizardNav.btnPrev
}
WizardNav {
progressSteps: appWindow.walletMode <= 1 ? 3 : 4
id: wizardNav
progressSteps: appWindow.walletMode <= 1 ? 4 : 5
progress: 0
btnNext.enabled: walletInput.verify();
btnPrev.text: qsTr("Back to menu") + translationManager.emptyString
btnPrev.text: appWindow.width <= 506 ? "<" : qsTr("Back to menu") + translationManager.emptyString
onPrevClicked: {
wizardController.wizardStateView.wizardCreateWallet2View.pwField = "";
wizardController.wizardStateView.wizardCreateWallet2View.pwConfirmField = "";
if (wizardStateView.wizardCreateWallet2View.seedListGrid) {
wizardStateView.wizardCreateWallet2View.seedListGrid.destroy();
}
wizardController.wizardStateView.wizardCreateWallet3View.pwField = "";
wizardController.wizardStateView.wizardCreateWallet3View.pwConfirmField = "";
wizardStateView.state = "wizardHome";
}
btnPrevKeyNavigationBackTab: walletInput.errorMessageWalletLocation.text != "" ? walletInput.errorMessageWalletLocation : walletInput.browseButton
btnNextKeyNavigationTab: createWalletHeader
onNextClicked: {
wizardController.walletOptionsName = walletInput.walletName.text;
wizardController.walletOptionsLocation = walletInput.walletLocation.text;
wizardController.walletOptionsLocation = appWindow.walletMode >= 2 ? walletInput.walletLocation.text : appWindow.accountsDir;
wizardStateView.state = "wizardCreateWallet2";
wizardStateView.wizardCreateWallet2View.pageRoot.forceActiveFocus();
}
}
}

View File

@@ -27,9 +27,13 @@
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import QtQuick 2.9
import QtQuick.Dialogs 1.2
import QtQuick.Layouts 1.2
import QtQuick.Controls 2.0
import moneroComponents.Clipboard 1.0
import "../js/Wizard.js" as Wizard
import "../js/Utils.js" as Utils
import "../components" as MoneroComponents
Rectangle {
@@ -37,9 +41,56 @@ Rectangle {
color: "transparent"
property alias pageHeight: pageRoot.height
property alias pageRoot: pageRoot
property string viewName: "wizardCreateWallet2"
property alias pwField: passwordFields.password
property alias pwConfirmField: passwordFields.passwordConfirm
property var seedArray: wizardController.walletOptionsSeed.split(" ")
property var seedListGrid: ""
property var hiddenWords: [0, 5, 10, 15, 20]
Clipboard { id: clipboard }
state: "default"
states: [
State {
name: "default";
}, State {
name: "verify";
when: typeof currentWallet != "undefined" && wizardStateView.state == "wizardCreateWallet2"
PropertyChanges { target: header; title: qsTr("Verify your recovery phrase") + translationManager.emptyString }
PropertyChanges { target: header; imageIcon: wizardController.layoutScale != 4 ? (MoneroComponents.Style.blackTheme ? "qrc:///images/verify.png" : "qrc:///images/verify-white.png") : "" }
PropertyChanges { target: header; subtitle: qsTr("Please confirm that you have written down your recover phrase by filling in the five blank fields with the correct words. If you have not written down your recovery phrase on a piece of paper, click on the Previous button and write it down right now!") + translationManager.emptyString}
PropertyChanges { target: walletCreationDate; opacity: 0; enabled: false}
PropertyChanges { target: walletCreationDateValue; opacity: 0; enabled: false}
PropertyChanges { target: walletRestoreHeight; opacity: 0; enabled: false}
PropertyChanges { target: walletRestoreHeightValue; opacity: 0; enabled: false}
PropertyChanges { target: createNewSeedButton; opacity: 0; enabled: false}
PropertyChanges { target: copyToClipboardButton; opacity: 0; enabled: false}
PropertyChanges { target: printPDFTemplate; opacity: 0; enabled: false}
PropertyChanges { target: navigation; onPrevClicked: {
seedListGridColumn.clearFields();
wizardCreateWallet2.state = "default";
pageRoot.forceActiveFocus();
}}
PropertyChanges { target: navigation; onNextClicked: {
seedListGridColumn.clearFields();
wizardStateView.state = "wizardCreateWallet3";
wizardCreateWallet2.state = "default";
}}
}
]
MoneroComponents.TextPlain {
//PDF template text
// the translation of these strings is used to create localized PDF templates
visible: false
text: qsTr("Print this paper, fill it out, and keep it in a safe location. Never share your recovery phrase with anybody, especially with strangers offering technical support.") +
qsTr("Recovery phrase (mnemonic seed)") +
qsTr("These words are are a backup of your wallet. They are the only thing needed to access your funds and restore your Monero wallet, so keep this paper in a safe place and do not disclose it to anybody! It is strongly not recommended to store your recovery phrase digitally (in an email, online service, screenshot, photo, or any other type of computer file).") +
qsTr("Wallet creation date") +
qsTr("Wallet restore height") +
qsTr("For instructions on how to restore this wallet, visit www.getmonero.org and go to Resources > User Guides > \"How to restore a wallet from mnemonic seed\". Use only Monero wallets that are trusted and recommended by the Monero community (see a list of them in www.getmonero.org/downloads).") + translationManager.emptyString
}
ColumnLayout {
id: pageRoot
@@ -49,39 +100,350 @@ Rectangle {
anchors.horizontalCenter: parent.horizontalCenter;
spacing: 0
KeyNavigation.down: mobileDialog.visible ? mobileHeader : header
KeyNavigation.tab: mobileDialog.visible ? mobileHeader : header
ColumnLayout {
id: mobileDialog
Layout.fillWidth: true
Layout.topMargin: wizardController.wizardSubViewTopMargin
Layout.maximumWidth: wizardController.wizardSubViewWidth
Layout.alignment: Qt.AlignHCenter
spacing: 0
visible: wizardController.layoutScale == 4
spacing: 60
WizardAskPassword {
id: passwordFields
WizardHeader {
id: mobileHeader
title: qsTr("Write down your recovery phrase") + translationManager.emptyString
Accessible.role: Accessible.StaticText
Accessible.name: qsTr("Write down your recovery phrase") + translationManager.emptyString
Keys.onUpPressed: displaySeedButton.forceActiveFocus()
Keys.onBacktabPressed: displaySeedButton.forceActiveFocus()
KeyNavigation.down: mobileImage
KeyNavigation.tab: mobileImage
}
Image {
id: mobileImage
Layout.alignment: Qt.AlignHCenter
fillMode: Image.PreserveAspectCrop
source: MoneroComponents.Style.blackTheme ? "qrc:///images/write-down@2x.png" : "qrc:///images/write-down-white@2x.png"
width: 125
height: 125
sourceSize.width: 125
sourceSize.height: 125
Accessible.role: Accessible.Graphic
Accessible.name: qsTr("A pencil writing on a piece of paper") + translationManager.emptyString
KeyNavigation.up: mobileHeader
KeyNavigation.backtab: mobileHeader
KeyNavigation.down: mobileText
KeyNavigation.tab: mobileText
Rectangle {
width: mobileImage.width
height: mobileImage.height
color: mobileImage.focus ? MoneroComponents.Style.titleBarButtonHoverColor : "transparent"
}
}
Text {
id: mobileText
Layout.fillWidth: true
Layout.alignment: Qt.AlignHCenter
color: MoneroComponents.Style.dimmedFontColor
text: qsTr("The next page will display your recovery phrase, also known as mnemonic seed.") + " " + qsTr("These words are a backup of your wallet. Write these words down now on a piece of paper in the same order displayed. Keep this paper in a safe place and do not disclose it to anybody! Do not store these words digitally, always use a paper!") + translationManager.emptyString
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 14
wrapMode: Text.WordWrap
leftPadding: 0
topPadding: 0
Accessible.role: Accessible.StaticText
Accessible.name: qsTr("The next page will display your recovery phrase, also known as mnemonic seed.") + " " + qsTr("These words are a backup of your wallet. Write these words down now on a piece of paper in the same order displayed. Keep this paper in a safe place and do not disclose it to anybody! Do not store these words digitally, always use a paper!") + translationManager.emptyString
KeyNavigation.up: mobileImage
KeyNavigation.backtab: mobileImage
KeyNavigation.down: displaySeedButton
KeyNavigation.tab: displaySeedButton
Rectangle {
anchors.fill: parent
color: parent.focus ? MoneroComponents.Style.titleBarButtonHoverColor : "transparent"
}
}
MoneroComponents.StandardButton {
id: displaySeedButton
Layout.alignment: Qt.AlignHCenter;
text: qsTr("Display recovery phrase") + translationManager.emptyString
onClicked: {
mobileDialog.visible = false;
}
Accessible.role: Accessible.Button
Accessible.name: qsTr("The next page will display your recovery phrase, also known as mnemonic seed. ") + qsTr("These words are a backup of your wallet. Write these words down now on a piece of paper in the same order displayed. Keep this paper in a safe place and do not disclose it to anybody! Do not store these words digitally, always use a paper!") + translationManager.emptyString
KeyNavigation.up: mobileText
KeyNavigation.backtab: mobileText
KeyNavigation.down: mobileHeader
KeyNavigation.tab: mobileHeader
}
}
ColumnLayout {
id: mainPage
Layout.fillWidth: true
Layout.topMargin: wizardController.wizardSubViewTopMargin
Layout.maximumWidth: wizardController.wizardSubViewWidth
Layout.alignment: Qt.AlignHCenter
visible: !mobileDialog.visible
spacing: 15
WizardHeader {
id: header
imageIcon: wizardController.layoutScale != 4 ? (MoneroComponents.Style.blackTheme ? "qrc:///images/write-down.png" : "qrc:///images/write-down-white.png") : ""
title: qsTr("Write down your recovery phrase") + translationManager.emptyString
subtitleVisible: wizardController.layoutScale != 4
subtitle: qsTr("These words are a backup of your wallet. Write these words down now on a piece of paper in the same order displayed. Keep this paper in a safe place and do not disclose it to anybody! Do not store these words digitally, always use a paper!") + translationManager.emptyString
Accessible.role: Accessible.StaticText
Accessible.name: title + ". " + subtitle
Keys.onUpPressed: navigation.btnNext.enabled ? navigation.btnNext.forceActiveFocus() : navigation.wizardProgress.forceActiveFocus()
Keys.onBacktabPressed: navigation.btnNext.enabled ? navigation.btnNext.forceActiveFocus() : navigation.wizardProgress.forceActiveFocus()
Keys.onDownPressed: recoveryPhraseLabel.visible ? recoveryPhraseLabel.forceActiveFocus() : focusOnListGrid()
Keys.onTabPressed: recoveryPhraseLabel.visible ? recoveryPhraseLabel.forceActiveFocus() : focusOnListGrid()
function focusOnListGrid() {
if (wizardCreateWallet2.state == "verify") {
if (seedListGridColumn.children[0].children[wizardCreateWallet2.hiddenWords[0]].lineEdit.visible) {
return seedListGridColumn.children[0].children[wizardCreateWallet2.hiddenWords[0]].lineEdit.forceActiveFocus();
} else {
return seedListGridColumn.children[0].children[wizardCreateWallet2.hiddenWords[0]].forceActiveFocus();
}
} else {
return seedListGridColumn.children[0].children[0].forceActiveFocus();
}
}
}
MoneroComponents.TextPlain {
id: recoveryPhraseLabel
visible: wizardController.layoutScale != 4
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 15
font.bold: false
textFormat: Text.RichText
color: MoneroComponents.Style.dimmedFontColor
text: qsTr("Recovery phrase (mnemonic seed)") + ":" + translationManager.emptyString
themeTransition: false
tooltip: qsTr("These words encode your private spend key in a human readable format.") + "<br>" + qsTr("It is expected that some words may be repeated.") + translationManager.emptyString
tooltipIconVisible: true
Accessible.role: Accessible.StaticText
Accessible.name: qsTr("Recovery phrase (mnemonic seed)") + translationManager.emptyString;
KeyNavigation.up: header
KeyNavigation.backtab: header
Keys.onDownPressed: header.focusOnListGrid()
Keys.onTabPressed: header.focusOnListGrid()
}
ColumnLayout {
id: seedListGridColumn
function clearFields() {
for (var i = 0; i < wizardCreateWallet2.hiddenWords.length; i++) {
seedListGridColumn.children[0].children[wizardCreateWallet2.hiddenWords[i]].wordText.visible = true;
seedListGridColumn.children[0].children[wizardCreateWallet2.hiddenWords[i]].lineEdit.text = "";
seedListGridColumn.children[0].children[wizardCreateWallet2.hiddenWords[i]].lineEdit.readOnly = false;
}
}
}
RowLayout {
Layout.fillWidth: true
Layout.alignment: Qt.AlignRight
Timer {
id: checkSeedListGridDestruction
interval: 100; running: false; repeat: true
onTriggered: {
if (!wizardCreateWallet2.seedListGrid) {
var newSeedListGrid = Qt.createComponent("SeedListGrid.qml");
wizardCreateWallet2.seedListGrid = newSeedListGrid.createObject(seedListGridColumn);
appWindow.showStatusMessage(qsTr("New seed generated"),3);
pageRoot.forceActiveFocus();
checkSeedListGridDestruction.stop();
}
}
}
MoneroComponents.StandardButton {
id: createNewSeedButton
visible: appWindow.walletMode >= 2
small: true
primary: false
text: qsTr("Create new seed") + translationManager.emptyString
onClicked: {
wizardController.restart(true);
wizardController.createWallet();
wizardCreateWallet2.seedArray = wizardController.walletOptionsSeed.split(" ")
wizardCreateWallet2.seedListGrid.destroy();
checkSeedListGridDestruction.start();
}
Accessible.role: Accessible.Button
Accessible.name: qsTr("Create new seed") + translationManager.emptyString
KeyNavigation.up: (wizardCreateWallet2.seedListGrid && seedListGridColumn.children[0]) ? seedListGridColumn.children[0].children[24] : recoveryPhraseLabel
KeyNavigation.backtab: (wizardCreateWallet2.seedListGrid && seedListGridColumn.children[0]) ? seedListGridColumn.children[0].children[24] : recoveryPhraseLabel
KeyNavigation.down: copyToClipboardButton
KeyNavigation.tab: copyToClipboardButton
}
MoneroComponents.StandardButton {
id: copyToClipboardButton
visible: appWindow.walletMode >= 2
small: true
primary: false
text: qsTr("Copy to clipboard") + translationManager.emptyString
onClicked: {
clipboard.setText(wizardController.walletOptionsSeed);
appWindow.showStatusMessage(qsTr("Recovery phrase copied to clipboard"),3);
}
Accessible.role: Accessible.Button
Accessible.name: qsTr("Copy to clipboard") + translationManager.emptyString
KeyNavigation.up: createNewSeedButton
KeyNavigation.backtab: createNewSeedButton
KeyNavigation.down: printPDFTemplate.visible ? printPDFTemplate : walletCreationDate
KeyNavigation.tab: printPDFTemplate.visible ? printPDFTemplate : walletCreationDate
}
MoneroComponents.StandardButton {
id: printPDFTemplate
small: true
primary: false
text: qsTr("Print a template") + translationManager.emptyString
tooltip: qsTr("Print a template to write down your seed") + translationManager.emptyString
onClicked: {
oshelper.openSeedTemplate();
}
Accessible.role: Accessible.Button
Accessible.name: qsTr("Print a template to write down your seed") + translationManager.emptyString
KeyNavigation.up: copyToClipboardButton.visible ? copyToClipboardButton : (wizardCreateWallet2.seedListGrid && seedListGridColumn.children[0]) ? seedListGridColumn.children[0].children[24] : recoveryPhraseLabel
KeyNavigation.backtab: copyToClipboardButton.visible ? copyToClipboardButton : (wizardCreateWallet2.seedListGrid && seedListGridColumn.children[0]) ? seedListGridColumn.children[0].children[24] : recoveryPhraseLabel
KeyNavigation.down: walletCreationDate
KeyNavigation.tab: walletCreationDate
}
}
RowLayout {
Layout.topMargin: 0
Layout.fillWidth: true
Layout.maximumWidth: seedListGridColumn.width
spacing: 10
ColumnLayout {
spacing: 5
Layout.fillWidth: true
MoneroComponents.TextPlain {
id: walletCreationDate
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 15
font.bold: false
textFormat: Text.RichText
color: MoneroComponents.Style.dimmedFontColor
text: qsTr("Creation date") + ": " + translationManager.emptyString
themeTransition: false
Accessible.role: Accessible.StaticText
Accessible.name: qsTr("Creation date") + " " + walletCreationDateValue.text + translationManager.emptyString
KeyNavigation.up: printPDFTemplate.visible ? printPDFTemplate : copyToClipboardButton
KeyNavigation.backtab: printPDFTemplate.visible ? printPDFTemplate : copyToClipboardButton
KeyNavigation.down: walletRestoreHeight
KeyNavigation.tab: walletRestoreHeight
}
MoneroComponents.TextPlain {
id: walletCreationDateValue
property var locale: Qt.locale()
property date currentDate: new Date()
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 16
font.bold: true
textFormat: Text.RichText
color: MoneroComponents.Style.defaultFontColor
text: currentDate.toLocaleDateString(locale, Locale.ShortFormat)
}
}
ColumnLayout {
spacing: 5
Layout.fillWidth: true
MoneroComponents.TextPlain {
id: walletRestoreHeight
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 15
font.bold: false
textFormat: Text.RichText
color: MoneroComponents.Style.dimmedFontColor
text: qsTr("Restore height") + ":" + translationManager.emptyString
tooltip: wizardController.layoutScale != 4 ? qsTr("Enter this number when restoring the wallet to make your initial wallet synchronization faster.") : "" + translationManager.emptyString
tooltipIconVisible: true
themeTransition: false
Accessible.role: Accessible.StaticText
Accessible.name: qsTr("Restore height") + " " + Utils.roundDownToNearestThousand(wizardController.m_wallet ? wizardController.m_wallet.walletCreationHeight : 0) + translationManager.emptyString
KeyNavigation.up: walletCreationDate
KeyNavigation.backtab: walletCreationDate
Keys.onDownPressed: navigation.btnPrev.forceActiveFocus();
Keys.onTabPressed: navigation.btnPrev.forceActiveFocus();
}
MoneroComponents.TextPlain {
id: walletRestoreHeightValue
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 16
font.bold: true
textFormat: Text.RichText
color: MoneroComponents.Style.defaultFontColor
text: Utils.roundDownToNearestThousand(wizardController.m_wallet ? wizardController.m_wallet.walletCreationHeight : 0)
}
}
}
WizardNav {
progressSteps: appWindow.walletMode <= 1 ? 3 : 4
id: navigation
progressSteps: appWindow.walletMode <= 1 ? 4 : 5
progress: 1
btnNext.enabled: passwordFields.calcStrengthAndVerify();
onPrevClicked: {
if(wizardController.walletOptionsIsRecoveringFromDevice){
wizardStateView.state = "wizardCreateDevice1";
} else {
wizardStateView.state = "wizardCreateWallet1";
}
wizardStateView.state = "wizardCreateWallet1";
mobileDialog.visible = Qt.binding(function() { return wizardController.layoutScale == 4 })
}
btnPrevKeyNavigationBackTab: wizardCreateWallet2.state == "default" ? walletRestoreHeight
: seedListGridColumn.children[0].children[wizardCreateWallet2.hiddenWords[4]].lineEdit.visible ? seedListGridColumn.children[0].children[wizardCreateWallet2.hiddenWords[4]].lineEdit
: seedListGridColumn.children[0].children[24]
btnNextKeyNavigationTab: mobileDialog.visible ? mobileHeader : header
btnNext.enabled: walletCreationDate.opacity == 1 || appWindow.ctrlPressed ? true
: seedListGridColumn.children[0].children[hiddenWords[0]].icon.wordsMatch &&
seedListGridColumn.children[0].children[hiddenWords[1]].icon.wordsMatch &&
seedListGridColumn.children[0].children[hiddenWords[2]].icon.wordsMatch &&
seedListGridColumn.children[0].children[hiddenWords[3]].icon.wordsMatch &&
seedListGridColumn.children[0].children[hiddenWords[4]].icon.wordsMatch
onNextClicked: {
wizardController.walletOptionsPassword = passwordFields.password;
if(appWindow.walletMode === 0 || appWindow.walletMode === 1){
wizardStateView.state = "wizardCreateWallet4";
} else {
wizardStateView.state = "wizardCreateWallet3";
//choose five random words to hide
for (var i = 0; i < hiddenWords.length; i++) {
wizardCreateWallet2.hiddenWords[i] = Math.floor(Math.random() * 5) + 5 * i
}
wizardCreateWallet2.state = "verify";
for (var i = 0; i < hiddenWords.length; i++) {
seedListGridColumn.children[0].children[wizardCreateWallet2.hiddenWords[i]].wordText.visible = false;
}
seedListGridColumn.children[0].children[wizardCreateWallet2.hiddenWords[0]].lineEdit.forceActiveFocus();
}
}
}
}
function onPageCompleted(previousView){
wizardCreateWallet2.seedArray = wizardController.walletOptionsSeed.split(" ")
if (!wizardCreateWallet2.seedListGrid) {
var component = Qt.createComponent("SeedListGrid.qml");
wizardCreateWallet2.seedListGrid = component.createObject(seedListGridColumn);
}
}
}

View File

@@ -38,6 +38,8 @@ Rectangle {
color: "transparent"
property alias pageHeight: pageRoot.height
property string viewName: "wizardCreateWallet3"
property alias pwField: passwordFields.password
property alias pwConfirmField: passwordFields.passwordConfirm
ColumnLayout {
id: pageRoot
@@ -53,26 +55,32 @@ Rectangle {
Layout.topMargin: wizardController.wizardSubViewTopMargin
Layout.maximumWidth: wizardController.wizardSubViewWidth
Layout.alignment: Qt.AlignHCenter
spacing: 20
spacing: 0
WizardHeader {
title: qsTr("Daemon settings") + translationManager.emptyString
subtitle: qsTr("To be able to communicate with the Monero network your wallet needs to be connected to a Monero node. For best privacy it's recommended to run your own node.") + translationManager.emptyString
}
WizardDaemonSettings {
id: daemonSettings
WizardAskPassword {
id: passwordFields
}
WizardNav {
progressSteps: 4
progressSteps: appWindow.walletMode <= 1 ? 4 : 5
progress: 2
btnNext.enabled: passwordFields.calcStrengthAndVerify();
onPrevClicked: {
wizardStateView.state = "wizardCreateWallet2";
if(wizardController.walletOptionsIsRecoveringFromDevice){
wizardStateView.state = "wizardCreateDevice1";
} else {
wizardStateView.state = "wizardCreateWallet2";
wizardStateView.wizardCreateWallet2View.pageRoot.forceActiveFocus();
}
}
onNextClicked: {
daemonSettings.save();
wizardStateView.state = "wizardCreateWallet4";
wizardController.walletOptionsPassword = passwordFields.password;
if (appWindow.walletMode < 2) {
wizardStateView.state = "wizardCreateWallet5";
} else {
wizardStateView.state = "wizardCreateWallet4";
}
}
}
}

View File

@@ -30,7 +30,6 @@ import QtQuick 2.9
import QtQuick.Layouts 1.2
import QtQuick.Controls 2.0
import "../js/Wizard.js" as Wizard
import "../components" as MoneroComponents
Rectangle {
@@ -38,7 +37,6 @@ Rectangle {
color: "transparent"
property alias pageHeight: pageRoot.height
property alias wizardNav: wizardNav
property string viewName: "wizardCreateWallet4"
ColumnLayout {
@@ -58,35 +56,23 @@ Rectangle {
spacing: 20
WizardHeader {
title: qsTr("You're all set up!") + translationManager.emptyString
subtitle: qsTr("New wallet details:") + translationManager.emptyString
title: qsTr("Daemon settings") + translationManager.emptyString
subtitle: qsTr("To be able to communicate with the Monero network your wallet needs to be connected to a Monero node. For best privacy it's recommended to run your own node.") + translationManager.emptyString
}
WizardSummary {}
WizardDaemonSettings {
id: daemonSettings
}
WizardNav {
id: wizardNav
Layout.topMargin: 24
btnNextText: qsTr("Create wallet") + translationManager.emptyString
progressSteps: appWindow.walletMode <= 1 ? 3 : 4
progress: appWindow.walletMode <= 1 ? 2 : 3
progressSteps: 5
progress: 3
onPrevClicked: {
if (appWindow.walletMode <= 1){
wizardStateView.state = "wizardCreateWallet1";
} else {
wizardStateView.state = "wizardCreateWallet3";
}
wizardStateView.state = "wizardCreateWallet3";
}
onNextClicked: {
btnNext.enabled = false;
wizardController.wizardStateView.wizardCreateWallet2View.pwField = "";
wizardController.wizardStateView.wizardCreateWallet2View.pwConfirmField = "";
wizardController.writeWallet(function() {
wizardController.useMoneroClicked();
wizardController.walletOptionsIsRecoveringFromDevice = false;
btnNext.enabled = true;
});
daemonSettings.save();
wizardStateView.state = "wizardCreateWallet5";
}
}
}

View File

@@ -0,0 +1,94 @@
// Copyright (c) 2014-2019, The Monero Project
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import QtQuick 2.9
import QtQuick.Layouts 1.2
import QtQuick.Controls 2.0
import "../js/Wizard.js" as Wizard
import "../components" as MoneroComponents
Rectangle {
id: wizardCreateWallet5
color: "transparent"
property alias pageHeight: pageRoot.height
property alias wizardNav: wizardNav
property string viewName: "wizardCreateWallet5"
ColumnLayout {
id: pageRoot
Layout.alignment: Qt.AlignHCenter;
width: parent.width - 100
Layout.fillWidth: true
anchors.horizontalCenter: parent.horizontalCenter;
spacing: 0
ColumnLayout {
Layout.fillWidth: true
Layout.topMargin: wizardController.wizardSubViewTopMargin
Layout.maximumWidth: wizardController.wizardSubViewWidth
Layout.alignment: Qt.AlignHCenter
spacing: 20
WizardHeader {
title: qsTr("You're all set up!") + translationManager.emptyString
subtitle: qsTr("New wallet details:") + translationManager.emptyString
}
WizardSummary {}
WizardNav {
id: wizardNav
Layout.topMargin: 24
btnNextText: qsTr("Create wallet") + translationManager.emptyString
progressSteps: appWindow.walletMode <= 1 ? 4 : 5
progress: appWindow.walletMode <= 1 ? 3 : 4
onPrevClicked: {
if (appWindow.walletMode <= 1){
wizardStateView.state = "wizardCreateWallet1";
} else {
wizardStateView.state = "wizardCreateWallet4";
}
}
onNextClicked: {
btnNext.enabled = false;
wizardController.wizardStateView.wizardCreateWallet3View.pwField = "";
wizardController.wizardStateView.wizardCreateWallet3View.pwConfirmField = "";
wizardController.writeWallet(function() {
wizardController.useMoneroClicked();
wizardController.walletOptionsIsRecoveringFromDevice = false;
});
btnNext.enabled = true;
}
}
}
}
}

View File

@@ -38,44 +38,60 @@ import QtQuick.Controls 2.0
ColumnLayout {
property string title: ""
property string subtitle: ""
property alias imageIcon: icon.source
property bool subtitleVisible: true
spacing: 4
Layout.maximumWidth: wizardController.wizardSubViewWidth
Text {
text: title
font.family: MoneroComponents.Style.fontRegular.name
color: MoneroComponents.Style.defaultFontColor
opacity: MoneroComponents.Style.blackTheme ? 1.0 : 0.8
font.pixelSize: {
if(wizardController.layoutScale === 2 ){
return 34;
} else {
return 28;
}
RowLayout {
spacing: 0
Image {
id: icon
visible: icon.source != ""
source: ""
width: wizardController.layoutScale == 4 ? 35 : 50
height: wizardController.layoutScale == 4 ? 35 : 50
}
wrapMode: Text.WordWrap
leftPadding: 0
topPadding: 0
bottomPadding: 0
Text {
text: title
font.family: MoneroComponents.Style.fontRegular.name
color: MoneroComponents.Style.defaultFontColor
opacity: MoneroComponents.Style.blackTheme ? 1.0 : 0.8
font.pixelSize: {
if (wizardController.layoutScale == 4) {
return 16;
} else if (wizardController.layoutScale == 3) {
return 28;
} else if (wizardController.layoutScale <= 2) {
return 32;
}
}
Rectangle {
anchors.fill: parent
color: parent.parent.focus ? MoneroComponents.Style.titleBarButtonHoverColor : "transparent"
wrapMode: Text.WordWrap
leftPadding: 0
topPadding: 0
bottomPadding: 0
Rectangle {
anchors.fill: parent
color: parent.parent.parent.focus ? MoneroComponents.Style.titleBarButtonHoverColor : "transparent"
}
}
}
Text {
Layout.fillWidth: true
Layout.alignment: Qt.AlignLeft
visible: parent.subtitle !== ""
visible: parent.subtitle !== "" && subtitleVisible
color: MoneroComponents.Style.dimmedFontColor
text: subtitle
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: {
if(wizardController.layoutScale === 2 ){
if (wizardController.layoutScale <= 2 ) {
return 16;
} else {
return 14;

View File

@@ -86,6 +86,7 @@ Rectangle {
wizardController.restart();
wizardController.createWallet();
wizardStateView.state = "wizardCreateWallet1"
wizardStateView.wizardCreateWallet1View.pageRoot.forceActiveFocus();
}
}

View File

@@ -102,10 +102,12 @@ RowLayout {
font.bold: true
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: {
if(wizardController.layoutScale === 2 ){
return 22;
} else {
if (wizardController.layoutScale == 4) {
return 16;
} else if (wizardController.layoutScale == 3) {
return 20;
} else if (wizardController.layoutScale <= 2) {
return 22;
}
}
@@ -124,7 +126,7 @@ RowLayout {
color: MoneroComponents.Style.dimmedFontColor
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: {
if(wizardController.layoutScale === 2 ){
if (wizardController.layoutScale <= 2 ){
return 16;
} else {
return 14;

View File

@@ -41,7 +41,7 @@ Rectangle {
property alias pageHeight: pageRoot.height
property string viewName: "wizardModeSelection1"
property bool portable: persistentSettings.portable
property bool simpleModeAvailable: !isTails && appWindow.persistentSettings.nettype == 0
property bool simpleModeAvailable: !isTails && appWindow.persistentSettings.nettype == 0 && !isAndroid
function applyWalletMode(mode, wizardState) {
if (!persistentSettings.setPortable(portable)) {

View File

@@ -43,9 +43,10 @@ RowLayout {
property bool autoTransition: true
property alias btnPrev: btnPrev
property alias btnNext: btnNext
property alias wizardProgress: wizardProgress
property string btnPrevText: qsTr("Previous") + translationManager.emptyString
property string btnNextText: qsTr("Next") + translationManager.emptyString
Layout.topMargin: 20
Layout.topMargin: 0
Layout.preferredHeight: 70
Layout.preferredWidth: parent.width
@@ -70,9 +71,11 @@ RowLayout {
MoneroComponents.StandardButton {
id: btnPrev
width: appWindow.width <= 506 ? 45 : appWindow.width <= 660 ? 120 : 180
small: true
text: menuNav.btnPrevText
primary: false
text: appWindow.width <= 506 ? "<" : menuNav.btnPrevText
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
@@ -134,8 +137,9 @@ RowLayout {
MoneroComponents.StandardButton {
id: btnNext
width: appWindow.width <= 506 ? 45 : appWindow.width <= 660 ? 120 : 180
small: true
text: menuNav.btnNextText
text: appWindow.width <= 506 ? ">" : menuNav.btnNextText
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right

View File

@@ -34,6 +34,7 @@ import QtGraphicalEffects 1.0
import Qt.labs.folderlistmodel 2.1
import moneroComponents.NetworkType 1.0
import moneroComponents.WalletKeysFilesModel 1.0
import FontAwesome 1.0
import "../js/Wizard.js" as Wizard
import "../components"
@@ -329,8 +330,9 @@ Rectangle {
id: wizardNav
Layout.topMargin: 0
progressEnabled: false
btnPrev.text: qsTr("Back to menu") + translationManager.emptyString
btnNext.text: qsTr("Browse filesystem") + translationManager.emptyString
btnPrev.text: appWindow.width <= 506 ? "<" : qsTr("Back to menu") + translationManager.emptyString
btnNext.text: appWindow.width <= 506 ? qsTr("Browse") : qsTr("Browse filesystem") + translationManager.emptyString
btnNext.width: appWindow.width <= 506 ? 80 : appWindow.width <= 660 ? 120 : 180
btnNext.visible: true
btnPrevKeyNavigationBackTab: recentList.itemAt(recentList.count - 1)
btnNextKeyNavigationTab: openWalletFromFileHeader

View File

@@ -54,7 +54,8 @@ ColumnLayout {
WizardSummaryItem {
Layout.fillWidth: true
header: qsTr("Mnemonic seed language") + translationManager.emptyString
value: persistentSettings.language
value: persistentSettings.language_wallet
visible: wizardStateView.state === "wizardCreateWallet5" && !wizardController.walletOptionsIsRecoveringFromDevice
}
WizardSummaryItem {

View File

@@ -41,9 +41,16 @@ GridLayout {
Layout.fillWidth: true
property alias walletName: walletName
property alias walletLocation: walletLocation
property alias browseButton: browseButton
property alias errorMessageWalletName: errorMessageWalletName
property alias errorMessageWalletLocation: errorMessageWalletLocation
property bool rowLayout: true
property var walletNameKeyNavigationBackTab: browseButton
property var browseButtonKeyNavigationTab: walletName
columnSpacing: 20
columns: 2
columnSpacing: rowLayout ? 20 : 0
rowSpacing: rowLayout ? 0 : 20
columns: rowLayout ? 2 : 1
function verify() {
if (walletName.text !== '' && walletLocation.text !== '') {
@@ -61,79 +68,163 @@ GridLayout {
walletName.text = Wizard.unusedWalletName(appWindow.accountsDir, defaultAccountName, walletManager);
}
MoneroComponents.LineEdit {
id: walletName
Layout.preferredWidth: grid.width/5
ColumnLayout {
MoneroComponents.LineEdit {
id: walletName
Layout.preferredWidth: grid.width/5
function verify(){
if (walletName.text === "") {
errorMessageWalletName.text = qsTr("Wallet name is empty") + translationManager.emptyString;
return false;
}
if (/[\\\/]/.test(walletName.text)) {
errorMessageWalletName.text = qsTr("Wallet name is invalid") + translationManager.emptyString;
return false;
}
if (walletLocation.text !== "") {
var walletAlreadyExists = Wizard.walletPathExists(appWindow.accountsDir, walletLocation.text, walletName.text, isIOS, walletManager);
if (walletAlreadyExists) {
errorMessageWalletName.text = qsTr("Wallet already exists") + translationManager.emptyString;
function verify(){
if (walletName.text === "") {
errorMessageWalletName.text = qsTr("Wallet name is empty") + translationManager.emptyString;
return false;
}
if (/[\\\/]/.test(walletName.text)) {
errorMessageWalletName.text = qsTr("Wallet name is invalid") + translationManager.emptyString;
return false;
}
if (walletLocation.text !== "") {
var walletAlreadyExists = Wizard.walletPathExists(appWindow.accountsDir, walletLocation.text, walletName.text, isIOS, walletManager);
if (walletAlreadyExists) {
errorMessageWalletName.text = qsTr("Wallet already exists") + translationManager.emptyString;
return false;
}
}
errorMessageWalletName.text = "";
return true;
}
errorMessageWalletName.text = "";
return true;
labelText: qsTr("Wallet name") + translationManager.emptyString
labelFontSize: 14
fontSize: 16
placeholderFontSize: 16
placeholderText: ""
errorWhenEmpty: true
text: defaultAccountName
onTextChanged: walletName.error = !walletName.verify();
Component.onCompleted: walletName.error = !walletName.verify();
Accessible.role: Accessible.EditableText
Accessible.name: labelText + text
KeyNavigation.up: walletNameKeyNavigationBackTab
KeyNavigation.backtab: walletNameKeyNavigationBackTab
KeyNavigation.down: errorMessageWalletName.text != "" ? errorMessageWalletName : appWindow.walletMode >= 2 ? walletLocation : wizardNav.btnPrev
KeyNavigation.tab: errorMessageWalletName.text != "" ? errorMessageWalletName : appWindow.walletMode >= 2 ? walletLocation : wizardNav.btnPrev
}
labelText: qsTr("Wallet name") + translationManager.emptyString
labelFontSize: 14
fontSize: 16
placeholderFontSize: 16
placeholderText: ""
errorWhenEmpty: true
text: defaultAccountName
RowLayout {
Layout.preferredWidth: grid.width/5
onTextChanged: walletName.error = !walletName.verify();
Component.onCompleted: walletName.error = !walletName.verify();
MoneroComponents.TextPlain {
visible: errorMessageWalletName.text != ""
font.family: FontAwesome.fontFamilySolid
font.styleName: "Solid"
font.pixelSize: 15
text: FontAwesome.exclamationCircle
color: "#FF0000"
themeTransition: false
}
MoneroComponents.TextPlain {
id: errorMessageWalletName
textFormat: Text.PlainText
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 14
color: "#FF0000"
themeTransition: false
Accessible.role: Accessible.StaticText
Accessible.name: text
KeyNavigation.up: walletName
KeyNavigation.backtab: walletName
KeyNavigation.down: walletLocation
KeyNavigation.tab: walletLocation
}
}
}
MoneroComponents.LineEdit {
id: walletLocation
Layout.preferredWidth: grid.width/3
ColumnLayout {
visible: appWindow.walletMode >= 2
function verify() {
if (walletLocation.text == "") {
errorMessageWalletLocation.text = qsTr("Wallet location is empty") + translationManager.emptyString;
return false;
MoneroComponents.LineEdit {
id: walletLocation
Layout.preferredWidth: grid.width/3
function verify() {
if (walletLocation.text == "") {
errorMessageWalletLocation.text = qsTr("Wallet location is empty") + translationManager.emptyString;
return false;
}
errorMessageWalletLocation.text = "";
return true;
}
labelText: qsTr("Wallet location") + translationManager.emptyString
labelFontSize: 14
fontSize: 16
placeholderText: ""
placeholderFontSize: 16
errorWhenEmpty: true
text: appWindow.accountsDir + "/"
onTextChanged: {
walletLocation.error = !walletLocation.verify();
walletName.error = !walletName.verify();
}
Component.onCompleted: walletLocation.error = !walletLocation.verify();
Accessible.role: Accessible.EditableText
Accessible.name: labelText + text
KeyNavigation.up: errorMessageWalletName.text != "" ? errorMessageWalletName : walletName
KeyNavigation.backtab: errorMessageWalletName.text != "" ? errorMessageWalletName : walletName
KeyNavigation.down: browseButton
KeyNavigation.tab: browseButton
MoneroComponents.InlineButton {
id: browseButton
fontFamily: FontAwesome.fontFamilySolid
fontStyleName: "Solid"
fontPixelSize: 18
text: FontAwesome.folderOpen
tooltip: qsTr("Browse") + translationManager.emptyString
tooltipLeft: true
onClicked: {
fileWalletDialog.folder = walletManager.localPathToUrl(walletLocation.text)
fileWalletDialog.open()
walletLocation.focus = true
}
Accessible.role: Accessible.Button
Accessible.name: qsTr("Browse") + translationManager.emptyString
KeyNavigation.up: walletLocation
KeyNavigation.backtab: walletLocation
KeyNavigation.down: errorMessageWalletLocation.text != "" ? errorMessageWalletLocation : browseButtonKeyNavigationTab
KeyNavigation.tab: errorMessageWalletLocation.text != "" ? errorMessageWalletLocation : browseButtonKeyNavigationTab
}
errorMessageWalletLocation.text = "";
return true;
}
labelText: qsTr("Wallet location") + translationManager.emptyString
labelFontSize: 14
fontSize: 16
placeholderText: ""
placeholderFontSize: 16
errorWhenEmpty: true
text: appWindow.accountsDir + "/"
onTextChanged: {
walletLocation.error = !walletLocation.verify();
walletName.error = !walletName.verify();
}
Component.onCompleted: walletLocation.error = !walletLocation.verify();
RowLayout {
Layout.preferredWidth: grid.width/3
MoneroComponents.InlineButton {
fontFamily: FontAwesome.fontFamilySolid
fontStyleName: "Solid"
fontPixelSize: 18
text: FontAwesome.folderOpen
tooltip: qsTr("Browse") + translationManager.emptyString
tooltipLeft: true
onClicked: {
fileWalletDialog.folder = walletManager.localPathToUrl(walletLocation.text)
fileWalletDialog.open()
walletLocation.focus = true
MoneroComponents.TextPlain {
visible: errorMessageWalletLocation.text != ""
font.family: FontAwesome.fontFamilySolid
font.styleName: "Solid"
font.pixelSize: 15
text: FontAwesome.exclamationCircle
color: "#FF0000"
themeTransition: false
}
MoneroComponents.TextPlain {
id: errorMessageWalletLocation
textFormat: Text.PlainText
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 14
color: "#FF0000"
themeTransition: false
Accessible.role: Accessible.StaticText
Accessible.name: text
KeyNavigation.up: browseButton
KeyNavigation.backtab: browseButton
KeyNavigation.down: browseButtonKeyNavigationTab
KeyNavigation.tab: browseButtonKeyNavigationTab
}
}
}
@@ -152,50 +243,4 @@ GridLayout {
fileWalletDialog.visible = false;
}
}
RowLayout {
Layout.preferredWidth: grid.width/5
MoneroComponents.TextPlain {
visible: errorMessageWalletName.text != ""
font.family: FontAwesome.fontFamilySolid
font.styleName: "Solid"
font.pixelSize: 15
text: FontAwesome.exclamationCircle
color: "#FF0000"
themeTransition: false
}
MoneroComponents.TextPlain {
id: errorMessageWalletName
textFormat: Text.PlainText
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 14
color: "#FF0000"
themeTransition: false
}
}
RowLayout {
Layout.preferredWidth: grid.width/3
MoneroComponents.TextPlain {
visible: errorMessageWalletLocation.text != ""
font.family: FontAwesome.fontFamilySolid
font.styleName: "Solid"
font.pixelSize: 15
text: FontAwesome.exclamationCircle
color: "#FF0000"
themeTransition: false
}
MoneroComponents.TextPlain {
id: errorMessageWalletLocation
textFormat: Text.PlainText
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 14
color: "#FF0000"
themeTransition: false
}
}
}

23486
wizard/template.pdf Normal file

File diff suppressed because it is too large Load Diff