Compare commits

...

201 Commits

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

[Czech]
dskch83

[German]
Christian
M5M400
Sneaky Squid
Paul Rant

[Japanese]
Andrew Onishi
Scott Anecito

[French]
el00ruobuob
glv2

[Dutch]
Jonathan Heirbaut
siesero

[Italian]
erciccione
Luca Ciavatta
Alessandro Lotta
stefanomarty

[Finnish]
vaa red

[Chinese (Simplified)]
jindouyunz
TE Scott
razorshaman909

[Catalan]
Assumpta Anglada
BennyBeat
Ecron
Joan Montané

[Ukrainian]
Agent LvM
TheFuzzStone

[Russian]
Agent LvM
TheFuzzStone
Russian Bear

[Chinese (Traditional)]
Lafudoci
2019-10-26 13:08:33 +00:00
peli-pro
212c8dd054 Warning added that balance reflects only incoming transactions for view-only wallets 2019-10-17 14:25:36 +02:00
luigi1111
290582d428 Merge pull request #2416
582267a main: apply WalletMode check on start (xiphon)
2019-10-16 14:22:56 -05:00
xiphon
582267a923 main: apply WalletMode check on start 2019-10-15 18:07:08 +00:00
luigi1111
fe3c06c36b Merge pull request #2415
631a1c4 fix fee labels in transfer (#2412) (jtgrassie)
2019-10-14 17:59:13 -05:00
luigi1111
95d7826163 Merge pull request #2413
c60c9ee Change 'Pootle' to 'Weblate' in readme (erciccione)
2019-10-14 17:58:15 -05:00
luigi1111
5e2099ad47 Merge pull request #2411
965081c DaemonManager: reset disconnectedEpoch on start, start timeout 60s (xiphon)
2019-10-14 17:57:23 -05:00
luigi1111
44280d1e52 Merge pull request #2399
d3b20d2 SimpleMode: implement 'switch to another public node' button (xiphon)
2019-10-14 17:53:08 -05:00
luigi1111
897d879dad Merge pull request #2398
32257c8 DaemonManager: implement async sendCommand (xiphon)
2019-10-14 17:50:54 -05:00
Jethro Grassie
631a1c49c8 fix fee labels in transfer (#2412) 2019-10-13 13:07:52 -04:00
xiphon
d3b20d2c04 SimpleMode: implement "switch to another public node" button 2019-10-11 01:01:19 +00:00
erciccione
c60c9ee69a Change 'Pootle' to 'Weblate' in readme 2019-10-10 11:46:59 +02:00
xiphon
965081c554 DaemonManager: reset disconnectedEpoch on start, start timeout 60s 2019-10-09 02:02:58 +00:00
luigi1111
e6458b58ef Merge pull request #2402
f72ed25 Transfer: forbid long Payment IDs (xiphon)
2019-10-08 15:21:35 -05:00
luigi1111
9207462676 Merge pull request #2401
947e265 Transfer: warn on long Payment ID filled into description field (xiphon)
2019-10-08 15:20:07 -05:00
luigi1111
ab020358e7 Merge pull request #2400
77ff362 SettingsNode: 'auto' special case for Bootstrap Address edit (xiphon)
2019-10-08 15:19:01 -05:00
luigi1111
135cfbac68 Merge pull request #2397
9d40baa SimpleMode: allow wrong local daemon version (xiphon)
2019-10-08 15:17:50 -05:00
luigi1111
3dbf09e7ad Merge pull request #2393
a6cd010 windeploy: bump icu version to 64, add libdouble-conversion.dll (stoffu)
2019-10-08 15:17:02 -05:00
xiphon
32257c8fab DaemonManager: implement async sendCommand 2019-10-07 10:39:30 +00:00
luigi1111
5ecca50977 Merge pull request #2403
ae2fdc7 build: build, install and link against randomx library (xiphon)
2019-09-30 18:59:26 -05:00
xiphon
ae2fdc7ab3 build: build, install and link against randomx library 2019-09-28 12:20:30 +00:00
xiphon
f72ed257ce Transfer: forbid long Payment IDs 2019-09-28 02:01:20 +00:00
xiphon
947e265a1a Transfer: warn on long Payment ID filled into description field 2019-09-28 01:46:22 +00:00
xiphon
77ff362b58 SettingsNode: 'auto' special case for Bootstrap Address edit 2019-09-27 15:50:38 +00:00
xiphon
9d40baa3ef SimpleMode: allow wrong local daemon version 2019-09-26 23:36:18 +00:00
luigi1111
d3b81cb6f8 Merge pull request #2391
4905341 TitleBar: add close wallet button (selsta)
c87ebf1 TitleBar: slightly reduce size of moon icon (selsta)
2019-09-24 11:15:28 -05:00
selsta
c87ebf1f31 TitleBar: slightly reduce size of moon icon 2019-09-24 17:53:02 +02:00
selsta
4905341999 TitleBar: add close wallet button 2019-09-24 17:53:02 +02:00
luigi1111
047dee4eb4 Merge pull request #2396
413507b build: highlight minimum required Qt version (selsta)
2019-09-24 10:52:48 -05:00
luigi1111
dd1046b31f Merge pull request #2392
411505b SimpleMode: ignore persistent daemon flags (xiphon)
2019-09-24 10:51:29 -05:00
luigi1111
2b82a472ae Merge pull request #2390
4f4e879 main: set TERM='goaway' (selsta)
2019-09-24 10:48:43 -05:00
luigi1111
8d5ef035d2 Merge pull request #2389
448727f WizardLang: reduce top margin (selsta)
2019-09-24 10:47:37 -05:00
luigi1111
a3d41a80bf Merge pull request #2383
2ca76ff LeftPanel: new balance card (selsta)
2019-09-24 10:46:40 -05:00
selsta
413507bba9 build: highlight minimum required Qt version 2019-09-23 16:47:56 +02:00
selsta
2ca76ff13c LeftPanel: new balance card 2019-09-21 01:23:09 +02:00
stoffu
a6cd010695 windeploy: bump icu version to 64, add libdouble-conversion.dll 2019-09-19 14:06:18 +09:00
xiphon
411505bff5 SimpleMode: ignore persistent daemon flags 2019-09-16 23:54:05 +00:00
selsta
4f4e879f8d main: set TERM="goaway" 2019-09-15 20:43:52 +02:00
selsta
448727f4b5 WizardLang: reduce top margin 2019-09-14 21:47:20 +02:00
luigi1111
ca8138bb46 Merge pull request #2385
bc22de4 DaemonManager: use 'sync_info' to avoid bootstrap daemon requests (xiphon)
2019-09-14 12:46:18 -05:00
luigi1111
10764b8a68 Merge pull request #2384
2c78f77 WizardController: fix overlap with network type dropdown (selsta)
2019-09-14 12:45:20 -05:00
luigi1111
b91afaf5c7 Merge pull request #2378
738e802 macOS/Windows: fix compiler warning (selsta)
2019-09-14 12:44:35 -05:00
luigi1111
31501316c9 Merge pull request #2377
8dab075 repo: remove isMobile leftovers (selsta)
2019-09-14 12:43:36 -05:00
luigi1111
120a62257f Merge pull request #2376
5f81b57 TitleBar: show wallet name (selsta)
2019-09-14 12:42:51 -05:00
luigi1111
a1e416ee83 Merge pull request #2375
6df9e58 fontawesome: fix regular/solid font style (selsta)
2019-09-14 12:41:52 -05:00
luigi1111
3cf2dc0c04 Merge pull request #2370
0d247a9 SimpleMode: automatic public nodes discovering and switching (xiphon)
2019-09-14 12:41:02 -05:00
selsta
6df9e584b3 fontawesome: fix regular/solid font style 2019-09-10 13:14:10 +02:00
xiphon
0d247a9b8a SimpleMode: automatic public nodes discovering and switching 2019-09-09 15:24:26 +00:00
xiphon
bc22de47f9 DaemonManager: use 'sync_info' to avoid bootstrap daemon requests 2019-09-09 01:14:06 +00:00
luigi1111
a5b2d5e727 Merge pull request #2373
4c05bff main: node and log page are hidden in simple mode (selsta)
2019-09-08 20:13:24 -05:00
selsta
2c78f77eb2 WizardController: fix overlap with network type dropdown 2019-09-08 17:06:14 +02:00
selsta
738e802f3c macOS/Windows: fix compiler warning 2019-09-06 00:22:39 +02:00
selsta
8dab0755d3 repo: remove isMobile leftovers 2019-09-06 00:11:12 +02:00
selsta
5f81b573c0 TitleBar: show wallet name 2019-09-05 18:49:28 +02:00
luigi1111
a267712d10 Merge pull request #2358
5392dd7 TitleBar: change Light Theme icon from 'light bulb' to 'moon' (xiphon)
2019-09-04 09:49:57 -05:00
luigi1111
0abaae073d Merge pull request #2372
cb9cb6e FontAwesome: bump to 5.10.2 (xiphon)
2019-09-04 09:48:58 -05:00
luigi1111
a6791561d6 Merge pull request #2366
a83910d SettingsNode: make input read only (selsta)
2019-09-04 09:48:06 -05:00
luigi1111
3ca2473239 Merge pull request #2362
3a33dde fix invalid include paths, compilation warnings, update README.md (xiphon)
2019-09-04 09:46:13 -05:00
luigi1111
779cc3e24d Merge pull request #2361
336ed9d sync and update language files (erciccione)
2019-09-04 09:44:41 -05:00
luigi1111
cfd2139310 Merge pull request #2346
049cef9 android: fix build (selsta)
2019-09-04 09:42:09 -05:00
selsta
4c05bff21e main: node and log page are hidden in simple mode 2019-09-04 00:06:26 +02:00
xiphon
5392dd7ed0 TitleBar: change Light Theme icon from 'light bulb' to 'moon' 2019-09-03 18:51:12 +00:00
xiphon
cb9cb6eb09 FontAwesome: bump to 5.10.2 2019-09-03 18:43:12 +00:00
xiphon
3a33ddeecd fix invalid include paths, compilation warnings, update README.md 2019-09-02 20:01:28 +00:00
selsta
a83910d7de SettingsNode: make input read only 2019-09-01 02:38:03 +02:00
erciccione
336ed9d6e5 sync and update language files 2019-08-28 12:44:06 +02:00
luigi1111
346e942e93 Merge pull request #2360
29580de History: fix tx key 'click to reveal' handling (xiphon)
2019-08-27 14:58:33 -05:00
luigi1111
13a5be7306 Merge pull request #2357
67e08da README: update (selsta)
2019-08-27 14:57:46 -05:00
luigi1111
bdceff6380 Merge pull request #2355
e660b2d build: link libstdc++ on Windows to statically link libwinpthreads (xiphon)
2019-08-27 14:56:11 -05:00
luigi1111
17c61f897a Merge pull request #2353
40bdf69 Ledger: improve hw wallet splash screen (selsta)
2019-08-27 14:55:15 -05:00
luigi1111
9a58e88ec6 Merge pull request #2351
b616e1c SettingsNode: change icons (selsta)
2019-08-27 14:53:29 -05:00
luigi1111
355cccaa64 Merge pull request #2175
ab47b4a Expose get/set attrs for wallet cache in libwalletqt, requires #5534 (xmrdsc)
2019-08-27 14:52:17 -05:00
xiphon
29580de2c7 History: fix tx key 'click to reveal' handling 2019-08-26 04:05:35 +00:00
selsta
67e08da918 README: update 2019-08-22 00:07:12 +02:00
xiphon
e660b2d169 build: link libstdc++ on Windows to statically link libwinpthreads 2019-08-20 14:17:46 +00:00
selsta
40bdf692d1 Ledger: improve hw wallet splash screen 2019-08-17 01:05:22 +02:00
luigi1111
562c46660a Merge pull request #2349
1ec22b3 history: fix start/end of the day calculation, apply local timezone (xiphon)
2019-08-14 15:52:02 -05:00
luigi1111
0724dd0043 Merge pull request #2348
a01ffc6 daemon: async daemon status check, don't freeze on wallet startup (xiphon)
2019-08-14 15:45:54 -05:00
luigi1111
c0932a1bd5 Merge pull request #2347
e1bbc1e LeftPanel: use currency symbol for fiat toggle (selsta)
2019-08-14 15:44:21 -05:00
luigi1111
d7a65fafad Merge pull request #2340
2f5c926 WizardLanguage: add missing qsTr() (selsta)
2019-08-14 15:43:06 -05:00
luigi1111
239e27c1b5 Merge pull request #2338
18f7a6a Receive: fix warning (selsta)
2019-08-14 15:42:04 -05:00
luigi1111
1ca10373a3 Merge pull request #2336
30a3abe Wallet: explicitly set trusted daemon flag (xiphon)
2019-08-14 15:40:33 -05:00
luigi1111
ac6687f6ff Merge pull request #2313
01740a2 images: fix known incorrect sRGB profile warning (selsta)
2019-08-14 15:39:32 -05:00
selsta
b616e1c8f6 SettingsNode: change icons 2019-08-14 20:35:53 +02:00
xiphon
1ec22b3d0c history: fix start/end of the day calculation, apply local timezone 2019-08-13 14:25:16 +00:00
xiphon
a01ffc6e1a daemon: async daemon status check, don't freeze on wallet startup 2019-08-13 12:21:47 +00:00
selsta
e1bbc1e525 LeftPanel: use currency symbol for fiat toggle 2019-08-12 00:10:24 +02:00
selsta
049cef9ce3 android: fix build 2019-08-10 22:09:30 +02:00
selsta
18f7a6a694 Receive: fix warning 2019-08-07 14:19:56 +02:00
xiphon
30a3abedbe Wallet: explicitly set trusted daemon flag 2019-08-07 06:43:18 +00:00
selsta
2f5c926c82 WizardLanguage: add missing qsTr() 2019-08-06 23:44:53 +02:00
luigi1111
55b4425c5d Merge pull request #2335
f666e6f main: don't attempt to close already closed wallet (xiphon)
2019-08-06 15:06:27 -05:00
luigi1111
dc49d7af38 Merge pull request #2331
e546ce8 WizardRestoreWallet1: use RadioButtons instead of buttons (selsta)
2019-08-06 15:05:36 -05:00
luigi1111
e01c2e903a Merge pull request #2327
059a2d7 SettingsNode: make button text more consistent (selsta)
2019-08-06 15:04:39 -05:00
luigi1111
886be81af2 Merge pull request #2315
1e64ebe QML: warning fixes (selsta)
2019-08-06 15:03:40 -05:00
luigi1111
671ddf5bef Merge pull request #2314
8abf8f8 wizard: bug fixes (selsta)
2019-08-06 15:02:36 -05:00
luigi1111
5f8cb04fee Merge pull request #2221
2d72f55 device: show address on device display (ph4r05)
2019-08-06 15:01:48 -05:00
luigi1111
3f06560c51 Revert "set submodule v0.14.1.2"
This reverts commit 8d17018019.
2019-08-06 15:00:43 -05:00
xiphon
f666e6f42e main: don't attempt to close already closed wallet 2019-08-06 10:50:26 +00:00
selsta
e546ce83b4 WizardRestoreWallet1: use RadioButtons instead of buttons 2019-07-31 18:17:46 +02:00
selsta
059a2d754e SettingsNode: make button text more consistent 2019-07-27 18:08:24 +02:00
selsta
1e64ebe17a QML: warning fixes 2019-07-24 05:24:37 +02:00
selsta
8abf8f844f wizard: bug fixes
- property binding loop
- wrong transition
- html in plaintext
2019-07-24 05:07:54 +02:00
selsta
01740a253d images: fix known incorrect sRGB profile warning 2019-07-24 04:05:39 +02:00
Dusan Klinec
2d72f55e57 device: show address on device display 2019-07-15 17:54:50 +02:00
dsc
ab47b4a783 Expose get/set attrs for wallet cache in libwalletqt, requires #5534 2019-05-25 22:38:38 +02:00
166 changed files with 33382 additions and 32410 deletions

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

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

View File

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

View File

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

View File

@@ -9,7 +9,7 @@ Copyright (c) 2014-2019, The Monero Project
- Mail: [dev@getmonero.org](mailto:dev@getmonero.org) - Mail: [dev@getmonero.org](mailto:dev@getmonero.org)
- Github: [https://github.com/monero-project/monero-gui](https://github.com/monero-project/monero-gui) - Github: [https://github.com/monero-project/monero-gui](https://github.com/monero-project/monero-gui)
- IRC: [#monero-dev on Freenode](irc://chat.freenode.net/#monero-dev) - IRC: [#monero-dev on Freenode](irc://chat.freenode.net/#monero-dev)
- Translation platform (Pootle): [translate.getmonero.org](https://translate.getmonero.org) - Translation platform (Weblate): [translate.getmonero.org](https://translate.getmonero.org)
## Vulnerability response ## Vulnerability response
@@ -75,6 +75,8 @@ Packaging for your favorite distribution would be a welcome contribution!
## Compiling the Monero GUI from source ## Compiling the Monero GUI from source
*Note*: Qt 5.9.7 is the minimum version required to build the GUI.
### On Linux: ### On Linux:
(Tested on Ubuntu 17.10 x64, Ubuntu 18.04 x64 and Gentoo x64) (Tested on Ubuntu 17.10 x64, Ubuntu 18.04 x64 and Gentoo x64)
@@ -83,7 +85,7 @@ Packaging for your favorite distribution would be a welcome contribution!
- For Debian distributions (Debian, Ubuntu, Mint, Tails...) - For Debian distributions (Debian, Ubuntu, Mint, Tails...)
`sudo apt install build-essential cmake libboost-all-dev miniupnpc libunbound-dev graphviz doxygen libunwind8-dev pkg-config libssl-dev libzmq3-dev libsodium-dev libhidapi-dev` `sudo apt install build-essential cmake libboost-all-dev miniupnpc libunbound-dev graphviz doxygen libunwind8-dev pkg-config libssl-dev libzmq3-dev libsodium-dev libhidapi-dev libnorm-dev libusb-1.0-0-dev libpgm-dev`
- For Gentoo - For Gentoo
@@ -91,11 +93,11 @@ Packaging for your favorite distribution would be a welcome contribution!
- For Fedora - For Fedora
`sudo dnf install make automake cmake gcc-c++ boost-devel miniupnpc-devel graphviz doxygen unbound-devel libunwind-devel pkgconfig openssl-devel libcurl-devel hidapi-devel libusb-devel` `sudo dnf install make automake cmake gcc-c++ boost-devel miniupnpc-devel graphviz doxygen unbound-devel libunwind-devel pkgconfig openssl-devel libcurl-devel hidapi-devel libusb-devel zeromq-devel`
2. Install Qt: 2. Install Qt:
*Note*: Qt 5.9.7 is the minimum version required to build the GUI. This makes **some** distributions (mostly based on debian, like Ubuntu 16.x or Linux Mint 18.x) obsolete due to their repositories containing an older Qt version. *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 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.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

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

BIN
images/card-background-black.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

BIN
images/card-background-white.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 419 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 436 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 612 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 170 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 170 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 399 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 760 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 193 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 195 B

View File

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

Before

Width:  |  Height:  |  Size: 359 B

View File

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

Before

Width:  |  Height:  |  Size: 371 B

View File

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

Before

Width:  |  Height:  |  Size: 379 B

View File

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

Before

Width:  |  Height:  |  Size: 328 B

View File

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

View File

@@ -6,7 +6,7 @@ Copyright (c) 2017-2019, The Monero Project
This is a *Inno Setup* script `Monero.iss` plus some related files This is a *Inno Setup* script `Monero.iss` plus some related files
that allows you to build a standalone Windows installer (.exe) for that allows you to build a standalone Windows installer (.exe) for
the GUI wallet that comes with the Boron Butterfly release of Monero. the GUI wallet that comes with the Carbon Chamaeleon release of Monero.
This turns the GUI wallet into a more or less standard Windows program, This turns the GUI wallet into a more or less standard Windows program,
by default installed into a subdirectory of `C:\Program Files`, a by default installed into a subdirectory of `C:\Program Files`, a
@@ -18,7 +18,7 @@ Monero.
As the setup script in file [Monero.iss](Monero.iss) has to list many As the setup script in file [Monero.iss](Monero.iss) has to list many
files and directories of the GUI wallet package to install by name, files and directories of the GUI wallet package to install by name,
this version of the script only works with exactly the GUI wallet this version of the script only works with exactly the GUI wallet
for Monero release *Boron Butterfly* that you find on for Monero release *Carbon Chamaeleon* that you find on
[the official download page](https://getmonero.org/downloads/). [the official download page](https://getmonero.org/downloads/).
It should however be easy to modify the script for future It should however be easy to modify the script for future
@@ -32,15 +32,15 @@ See [LICENSE](LICENSE).
You can only build on Windows, and the result is always a You can only build on Windows, and the result is always a
Windows .exe file that can act as a standalone installer for the Windows .exe file that can act as a standalone installer for the
Boron Butterfly GUI wallet. Carbon Chamaeleon GUI wallet.
Note that the installer build process is now reproducible / deterministic. For details check the file [Deterministic.md](Deterministic.md). Note that the installer build process is now reproducible / deterministic. For details check the file [Deterministic.md](Deterministic.md).
The build steps in detail: The build steps in detail:
1. Install *Inno Setup*. You can get it from [here](http://www.jrsoftware.org/isdl.php) 1. Install *Inno Setup*. You can get it from [here](http://www.jrsoftware.org/isdl.php)
2. Get the Inno Setup script plus related files by cloning the whole [monero-gui GitHub repository](https://github.com/monero-project/monero-gui); you will only need the files in the installer directory `installers\windows` however. Depending on development state, additionally you may have to checkout a specific branch, like `release-v0.14`. 2. Get the Inno Setup script plus related files by cloning the whole [monero-gui GitHub repository](https://github.com/monero-project/monero-gui); you will only need the files in the installer directory `installers\windows` however. Depending on development state, additionally instead of simply using `master` you may have to checkout a specific branch, like `release-v0.15`.
3. The setup script is written to take the GUI wallet files from a subdirectory named `bin`; so create `installers\windows\bin`, get the zip file of the GUI wallet from [here](https://getmonero.org/downloads/), unpack it somewhere, and copy all the files and subdirectories in the single subdirectory there (currently named `monero-gui-0.14.1.2`) to this `bin` subdirectory 3. The setup script is written to take the GUI wallet files from a subdirectory named `bin`; so create `installers\windows\bin`, get the zip file of the GUI wallet from [here](https://getmonero.org/downloads/), unpack it somewhere, and copy all the files and subdirectories in the single subdirectory there (currently named `monero-gui-0.15.0.0`) to this `bin` subdirectory
4. Start Inno Setup, load `Monero.iss` and compile it 4. Start Inno Setup, load `Monero.iss` and compile it
5. The result i.e. the finished installer will be the file `mysetup.exe` in the `installers\windows\Output` subdirectory 5. The result i.e. the finished installer will be the file `mysetup.exe` in the `installers\windows\Output` subdirectory

View File

@@ -1,13 +1,12 @@
<html> <html>
<head> <head>
<title>Monero Boron Butterfly GUI Wallet</title> <title>Monero Carbon Chamaeleon GUI Wallet</title>
</head> </head>
<body style="font-family: Arial, Helvetica, sans-serif"> <body style="font-family: Arial, Helvetica, sans-serif">
<h1>Monero Boron Butterfly GUI Wallet</h1> <h1>Monero Carbon Chamaeleon GUI Wallet</h1>
<p>Copyright (c) 2014-2019, The Monero Project<br> <p>Copyright (c) 2014-2019, The Monero Project</p>
Date: July 20, 2019</p>
<h2>Preface</h2> <h2>Preface</h2>
@@ -23,7 +22,7 @@
<h2>Content of the Package</h2> <h2>Content of the Package</h2>
<p>You just installed the <i>Monero GUI wallet</i> for Windows, release Boron Butterfly, version 0.14.1.2. <p>You just installed the <i>Monero GUI wallet</i> for Windows, release Carbon Chamaeleon, version {#GuiVersion}.
The wallet enables you to send and receive Moneroj in a secure and very private way. The wallet enables you to send and receive Moneroj in a secure and very private way.
</p> </p>
@@ -61,7 +60,7 @@
provides the most security and privacy possible for you.</p> 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 <p>However if your Internet access makes it difficult to run a full node, or if you have simply no room to store
the blockchain locally (somewhat over 70 GB in July 2019, and of course growing), you can compromise and try to connect the blockchain locally (somewhat over 74 GB in November 2019, and of course growing), you can compromise and try to connect
to a remote node. One way of finding such a node is checking to a remote node. One way of finding such a node is checking
<a href="https://moneroworld.com/#nodes">this page</a>. <a href="https://moneroworld.com/#nodes">this page</a>.
</p> </p>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 440 KiB

After

Width:  |  Height:  |  Size: 440 KiB

View File

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

View File

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

View File

@@ -125,6 +125,9 @@ int main(int argc, char *argv[])
// qDebug() << "High DPI auto scaling - enabled"; // qDebug() << "High DPI auto scaling - enabled";
//#endif //#endif
// Turn off colors in monerod log output.
qputenv("TERM", "goaway");
MainApp app(argc, argv); MainApp app(argc, argv);
app.setApplicationName("monero-core"); app.setApplicationName("monero-core");
@@ -171,7 +174,10 @@ int main(int argc, char *argv[])
QCoreApplication::translate("main", "Log to specified file"), QCoreApplication::translate("main", "Log to specified file"),
QCoreApplication::translate("main", "file")); QCoreApplication::translate("main", "file"));
QCommandLineOption testQmlOption("test-qml");
testQmlOption.setFlags(QCommandLineOption::HiddenFromHelp);
parser.addOption(logPathOption); parser.addOption(logPathOption);
parser.addOption(testQmlOption);
parser.addHelpOption(); parser.addHelpOption();
parser.process(app); parser.process(app);
@@ -192,7 +198,9 @@ int main(int argc, char *argv[])
qWarning().noquote() << "app startd" << "(log: " + logPath + ")"; qWarning().noquote() << "app startd" << "(log: " + logPath + ")";
// Desktop entry // Desktop entry
#ifdef Q_OS_LINUX
registerXdgMime(app); registerXdgMime(app);
#endif
IPC *ipc = new IPC(&app); IPC *ipc = new IPC(&app);
QStringList posArgs = parser.positionalArguments(); QStringList posArgs = parser.positionalArguments();
@@ -400,6 +408,10 @@ int main(int argc, char *argv[])
return 1; return 1;
} }
// QML loaded successfully.
if (parser.isSet(testQmlOption))
return 0;
#ifdef WITH_SCANNER #ifdef WITH_SCANNER
QObject *qmlCamera = rootObject->findChild<QObject*>("qrCameraQML"); QObject *qmlCamera = rootObject->findChild<QObject*>("qrCameraQML");
if (qmlCamera) if (qmlCamera)

515
main.qml
View File

@@ -47,7 +47,7 @@ import "js/Windows.js" as Windows
ApplicationWindow { ApplicationWindow {
id: appWindow id: appWindow
title: "Monero" title: "Monero" + (walletName ? " - " + walletName : "")
property var currentItem property var currentItem
property bool hideBalanceForced: false property bool hideBalanceForced: false
@@ -69,7 +69,6 @@ ApplicationWindow {
property bool foundNewBlock: false property bool foundNewBlock: false
property bool qrScannerEnabled: (typeof builtWithScanner != "undefined") && builtWithScanner property bool qrScannerEnabled: (typeof builtWithScanner != "undefined") && builtWithScanner
property int blocksToSync: 1 property int blocksToSync: 1
property var isMobile: (appWindow.width > 700 && !isAndroid) ? false : true
property bool isMining: false property bool isMining: false
property int walletMode: persistentSettings.walletMode property int walletMode: persistentSettings.walletMode
property var cameraUi property var cameraUi
@@ -87,8 +86,8 @@ ApplicationWindow {
property bool themeTransition: false property bool themeTransition: false
// fiat price conversion // fiat price conversion
property int fiatPriceXMRUSD: 0 property real fiatPriceXMRUSD: 0
property int fiatPriceXMREUR: 0 property real fiatPriceXMREUR: 0
property var fiatPriceAPIs: { property var fiatPriceAPIs: {
return { return {
"kraken": { "kraken": {
@@ -106,19 +105,6 @@ ApplicationWindow {
} }
} }
property string remoteNodeService: {
// support user-defined remote node aggregators
if(persistentSettings.remoteNodeService){
var service = persistentSettings.remoteNodeService;
if(service.charAt(service.length-1) !== "/")
service += "/";
return service;
}
// monero-gui workgroup maintained
return "https://autonode.xmr.pm/"
}
// true if wallet ever synchronized // true if wallet ever synchronized
property bool walletInitialized : false property bool walletInitialized : false
@@ -126,7 +112,6 @@ ApplicationWindow {
property var current_address property var current_address
property var current_address_label: "Primary" property var current_address_label: "Primary"
property int current_subaddress_table_index: 0 property int current_subaddress_table_index: 0
property int current_subaddress_account_table_index: 0
function altKeyReleased() { ctrlPressed = false; } function altKeyReleased() { ctrlPressed = false; }
@@ -239,7 +224,6 @@ ApplicationWindow {
if (typeof currentWallet !== "undefined" && currentWallet !== null) { if (typeof currentWallet !== "undefined" && currentWallet !== null) {
console.log("Daemon change - closing " + currentWallet) console.log("Daemon change - closing " + currentWallet)
closeWallet(); closeWallet();
currentWallet = undefined
} else if (!walletInitialized) { } else if (!walletInitialized) {
// set page to transfer if not changing daemon // set page to transfer if not changing daemon
middlePanel.state = "Transfer"; middlePanel.state = "Transfer";
@@ -286,25 +270,31 @@ ApplicationWindow {
function closeWallet(callback) { function closeWallet(callback) {
// Disconnect all listeners // Disconnect all listeners
if (typeof currentWallet !== "undefined" && currentWallet !== null) { if (typeof currentWallet === "undefined" || currentWallet === null) {
currentWallet.heightRefreshed.disconnect(onHeightRefreshed); if (callback) {
currentWallet.refreshed.disconnect(onWalletRefresh) callback();
currentWallet.updated.disconnect(onWalletUpdate) }
currentWallet.newBlock.disconnect(onWalletNewBlock) return;
currentWallet.moneySpent.disconnect(onWalletMoneySent)
currentWallet.moneyReceived.disconnect(onWalletMoneyReceived)
currentWallet.unconfirmedMoneyReceived.disconnect(onWalletUnconfirmedMoneyReceived)
currentWallet.transactionCreated.disconnect(onTransactionCreated)
currentWallet.connectionStatusChanged.disconnect(onWalletConnectionStatusChanged)
currentWallet.deviceButtonRequest.disconnect(onDeviceButtonRequest);
currentWallet.deviceButtonPressed.disconnect(onDeviceButtonPressed);
currentWallet.transactionCommitted.disconnect(onTransactionCommitted);
middlePanel.paymentClicked.disconnect(handlePayment);
middlePanel.sweepUnmixableClicked.disconnect(handleSweepUnmixable);
middlePanel.getProofClicked.disconnect(handleGetProof);
middlePanel.checkProofClicked.disconnect(handleCheckProof);
} }
currentWallet.heightRefreshed.disconnect(onHeightRefreshed);
currentWallet.refreshed.disconnect(onWalletRefresh)
currentWallet.updated.disconnect(onWalletUpdate)
currentWallet.newBlock.disconnect(onWalletNewBlock)
currentWallet.moneySpent.disconnect(onWalletMoneySent)
currentWallet.moneyReceived.disconnect(onWalletMoneyReceived)
currentWallet.unconfirmedMoneyReceived.disconnect(onWalletUnconfirmedMoneyReceived)
currentWallet.transactionCreated.disconnect(onTransactionCreated)
currentWallet.connectionStatusChanged.disconnect(onWalletConnectionStatusChanged)
currentWallet.deviceButtonRequest.disconnect(onDeviceButtonRequest);
currentWallet.deviceButtonPressed.disconnect(onDeviceButtonPressed);
currentWallet.transactionCommitted.disconnect(onTransactionCommitted);
middlePanel.paymentClicked.disconnect(handlePayment);
middlePanel.sweepUnmixableClicked.disconnect(handleSweepUnmixable);
middlePanel.getProofClicked.disconnect(handleGetProof);
middlePanel.checkProofClicked.disconnect(handleCheckProof);
appWindow.walletName = "";
currentWallet = undefined; currentWallet = undefined;
appWindow.showProcessingSplash(qsTr("Closing wallet...")); appWindow.showProcessingSplash(qsTr("Closing wallet..."));
@@ -344,7 +334,6 @@ ApplicationWindow {
} }
walletName = usefulName(wallet.path) walletName = usefulName(wallet.path)
updateSyncing(false)
viewOnly = currentWallet.viewOnly; viewOnly = currentWallet.viewOnly;
@@ -385,11 +374,21 @@ ApplicationWindow {
currentDaemonAddress = localDaemonAddress currentDaemonAddress = localDaemonAddress
console.log("initializing with daemon address: ", currentDaemonAddress) console.log("initializing with daemon address: ", currentDaemonAddress)
currentWallet.initAsync(currentDaemonAddress, 0, persistentSettings.is_recovering, persistentSettings.is_recovering_from_device, persistentSettings.restore_height); currentWallet.initAsync(
currentDaemonAddress,
isTrustedDaemon(),
0,
persistentSettings.is_recovering,
persistentSettings.is_recovering_from_device,
persistentSettings.restore_height);
// save wallet keys in case wallet settings have been changed in the init // save wallet keys in case wallet settings have been changed in the init
currentWallet.setPassword(walletPassword); currentWallet.setPassword(walletPassword);
} }
function isTrustedDaemon() {
return !persistentSettings.useRemoteNode || persistentSettings.is_trusted_daemon;
}
function walletPath() { function walletPath() {
var wallet_path = persistentSettings.wallet_path var wallet_path = persistentSettings.wallet_path
return wallet_path; return wallet_path;
@@ -406,24 +405,20 @@ ApplicationWindow {
if (!currentWallet) if (!currentWallet)
return; return;
var balance_unlocked = qsTr("HIDDEN"); var balance = "?.??";
var balance = qsTr("HIDDEN"); var balanceU = "?.??";
if(!hideBalanceForced && !persistentSettings.hideBalance){ if(!hideBalanceForced && !persistentSettings.hideBalance){
balance_unlocked = walletManager.displayAmount(currentWallet.unlockedBalance(currentWallet.currentSubaddressAccount));
balance = walletManager.displayAmount(currentWallet.balance(currentWallet.currentSubaddressAccount)); balance = walletManager.displayAmount(currentWallet.balance(currentWallet.currentSubaddressAccount));
balanceU = walletManager.displayAmount(currentWallet.unlockedBalance(currentWallet.currentSubaddressAccount));
} }
middlePanel.unlockedBalanceText = balance_unlocked;
leftPanel.unlockedBalanceText = balance_unlocked;
middlePanel.balanceText = balance;
leftPanel.balanceText = balance;
if (persistentSettings.fiatPriceEnabled) { if (persistentSettings.fiatPriceEnabled) {
appWindow.fiatApiUpdateBalance(balance, balance_unlocked); appWindow.fiatApiUpdateBalance(balance);
} }
var accountLabel = currentWallet.getSubaddressLabel(currentWallet.currentSubaddressAccount, 0); leftPanel.minutesToUnlock = (balance !== balanceU) ? currentWallet.history.minutesToUnlock : "";
leftPanel.balanceLabelText = qsTr("Balance (#%1%2)").arg(currentWallet.currentSubaddressAccount).arg(accountLabel === "" ? "" : (" " + accountLabel)); leftPanel.balanceString = balance
leftPanel.balanceUnlockedString = balanceU
} }
function onUriHandler(uri){ function onUriHandler(uri){
@@ -462,10 +457,6 @@ ApplicationWindow {
// Raise window // Raise window
appWindow.raise(); appWindow.raise();
appWindow.show(); appWindow.show();
// @TODO: remove after paymentID deprecation
if(params.hasOwnProperty("tx_payment_id"))
persistentSettings.showPid = true;
} }
} }
@@ -475,15 +466,23 @@ ApplicationWindow {
leftPanel.networkStatus.connected = status leftPanel.networkStatus.connected = status
// update local daemon status. // update local daemon status.
if(!isMobile && walletManager.isDaemonLocal(currentDaemonAddress)) const isDisconnected = status === Wallet.ConnectionStatus_Disconnected;
daemonRunning = status; if (walletManager.isDaemonLocal(currentDaemonAddress)) {
daemonRunning = !isDisconnected;
} else {
daemonRunning = false;
}
// Update fee multiplier dropdown on transfer page // Update fee multiplier dropdown on transfer page
middlePanel.transferView.updatePriorityDropdown(); middlePanel.transferView.updatePriorityDropdown();
// If wallet isnt connected, advanced wallet mode and no daemon is running - Ask // If wallet isnt connected, advanced wallet mode and no daemon is running - Ask
if(!isMobile && appWindow.walletMode >= 2 && walletManager.isDaemonLocal(currentDaemonAddress) && !walletInitialized && status === Wallet.ConnectionStatus_Disconnected && !daemonManager.running(persistentSettings.nettype)){ if (appWindow.walletMode >= 2 && walletManager.isDaemonLocal(currentDaemonAddress) && !walletInitialized && isDisconnected) {
daemonManagerDialog.open(); daemonManager.runningAsync(persistentSettings.nettype, function(running) {
if (!running) {
daemonManagerDialog.open();
}
});
} }
// initialize transaction history once wallet is initialized first time; // initialize transaction history once wallet is initialized first time;
if (!walletInitialized) { if (!walletInitialized) {
@@ -592,8 +591,6 @@ ApplicationWindow {
foundNewBlock = false; foundNewBlock = false;
console.log("New block found - updating history") console.log("New block found - updating history")
currentWallet.history.refresh(currentWallet.currentSubaddressAccount) currentWallet.history.refresh(currentWallet.currentSubaddressAccount)
var timeToUnlock = currentWallet.history.minutesToUnlock
leftPanel.minutesToUnlockTxt = (timeToUnlock > 0)? (timeToUnlock == 20)? qsTr("Unlocked balance (waiting for block)") : qsTr("Unlocked balance (~%1 min)").arg(timeToUnlock) : qsTr("Unlocked balance");
if(middlePanel.state == "History") if(middlePanel.state == "History")
middlePanel.historyView.update(); middlePanel.historyView.update();
@@ -602,10 +599,19 @@ ApplicationWindow {
function connectRemoteNode() { function connectRemoteNode() {
console.log("connecting remote node"); console.log("connecting remote node");
persistentSettings.useRemoteNode = true;
currentDaemonAddress = persistentSettings.remoteNodeAddress; const callback = function() {
currentWallet.initAsync(currentDaemonAddress); persistentSettings.useRemoteNode = true;
walletManager.setDaemonAddressAsync(currentDaemonAddress); currentDaemonAddress = persistentSettings.remoteNodeAddress;
currentWallet.initAsync(currentDaemonAddress, isTrustedDaemon());
walletManager.setDaemonAddressAsync(currentDaemonAddress);
};
if (typeof daemonManager != "undefined" && daemonRunning) {
showDaemonIsRunningDialog(callback);
} else {
callback();
}
} }
function disconnectRemoteNode() { function disconnectRemoteNode() {
@@ -615,7 +621,7 @@ ApplicationWindow {
console.log("disconnecting remote node"); console.log("disconnecting remote node");
persistentSettings.useRemoteNode = false; persistentSettings.useRemoteNode = false;
currentDaemonAddress = localDaemonAddress currentDaemonAddress = localDaemonAddress
currentWallet.initAsync(currentDaemonAddress); currentWallet.initAsync(currentDaemonAddress, isTrustedDaemon());
walletManager.setDaemonAddressAsync(currentDaemonAddress); walletManager.setDaemonAddressAsync(currentDaemonAddress);
} }
@@ -637,7 +643,7 @@ ApplicationWindow {
} }
// Update wallet sync progress // Update wallet sync progress
updateSyncing((currentWallet.connected() !== Wallet.ConnectionStatus_Disconnected) && !daemonSynced) leftPanel.isSyncing = (currentWallet.connected() !== Wallet.ConnectionStatus_Disconnected) && !daemonSynced
// Update transfer page status // Update transfer page status
middlePanel.updateStatus(); middlePanel.updateStatus();
@@ -687,8 +693,8 @@ ApplicationWindow {
simpleModeConnectionTimer.stop(); simpleModeConnectionTimer.stop();
appWindow.showProcessingSplash(qsTr("Waiting for daemon to start...")) appWindow.showProcessingSplash(qsTr("Waiting for daemon to start..."))
daemonManager.start(flags, persistentSettings.nettype, persistentSettings.blockchainDataDir, persistentSettings.bootstrapNodeAddress); const noSync = appWindow.walletMode === 0;
persistentSettings.daemonFlags = flags daemonManager.start(flags, persistentSettings.nettype, persistentSettings.blockchainDataDir, persistentSettings.bootstrapNodeAddress, noSync);
} }
function stopDaemon(){ function stopDaemon(){
@@ -704,6 +710,7 @@ ApplicationWindow {
// resume refresh // resume refresh
currentWallet.startRefresh(); currentWallet.startRefresh();
// resume simplemode connection timer // resume simplemode connection timer
appWindow.disconnectedEpoch = Utils.epoch();
simpleModeConnectionTimer.start(); simpleModeConnectionTimer.start();
} }
function onDaemonStopped(){ function onDaemonStopped(){
@@ -841,7 +848,9 @@ ApplicationWindow {
", priority: ", priority, ", priority: ", priority,
", description: ", description); ", description: ", description);
showProcessingSplash("Creating transaction"); var splashMsg = qsTr("Creating transaction...");
splashMsg += appWindow.currentWallet.isLedger() ? qsTr("\n\nPlease check your hardware wallet \nyour input may be required.") : "";
showProcessingSplash(splashMsg);
transactionDescription = description; transactionDescription = description;
@@ -1079,12 +1088,6 @@ ApplicationWindow {
informationPopup.open() informationPopup.open()
} }
function updateSyncing(syncing) {
var text = (syncing ? qsTr("Balance (syncing)") : qsTr("Balance")) + translationManager.emptyString
leftPanel.balanceLabelText = text
middlePanel.balanceLabelText = text
}
// blocks UI if wallet can't be opened or no connection to the daemon // blocks UI if wallet can't be opened or no connection to the daemon
function enableUI(enable) { function enableUI(enable) {
middlePanel.enabled = enable; middlePanel.enabled = enable;
@@ -1119,32 +1122,19 @@ ApplicationWindow {
// close wallet and show wizard // close wallet and show wizard
function showWizard(){ function showWizard(){
clearMoneroCardLabelText();
walletInitialized = false; walletInitialized = false;
closeWallet(function() { closeWallet(function() {
currentWallet = undefined;
wizard.restart(); wizard.restart();
wizard.wizardState = "wizardHome"; wizard.wizardState = "wizardHome";
rootItem.state = "wizard" rootItem.state = "wizard"
// reset balance // reset balance
leftPanel.balanceText = leftPanel.unlockedBalanceText = walletManager.displayAmount(0); clearMoneroCardLabelText();
fiatApiUpdateBalance(0, 0);
// disable timers // disable timers
userInActivityTimer.running = false; userInActivityTimer.running = false;
simpleModeConnectionTimer.running = false; simpleModeConnectionTimer.running = false;
}); });
} }
function hideMenu() {
goToBasicAnimation.start();
console.log(appWindow.width)
}
function showMenu() {
goToProAnimation.start();
console.log(appWindow.width)
}
objectName: "appWindow" objectName: "appWindow"
visible: true visible: true
@@ -1261,22 +1251,34 @@ ApplicationWindow {
Prices.getJSON(url); Prices.getJSON(url);
} }
function fiatApiUpdateBalance(balance, unlocked_balance){ function fiatApiCurrencySymbol() {
// update balance card switch (persistentSettings.fiatPriceCurrency) {
var ticker = persistentSettings.fiatPriceCurrency === "xmrusd" ? appWindow.fiatPriceXMRUSD : appWindow.fiatPriceXMREUR; case "xmrusd":
var symbol = persistentSettings.fiatPriceCurrency === "xmrusd" ? "$" : "€" return "USD";
if(ticker <= 0){ case "xmreur":
console.log(fiatApiError("Could not update balance card; invalid ticker value")); return "EUR";
leftPanel.unlockedBalanceTextFiat = "N/A"; default:
leftPanel.balanceTextFiat = "N/A"; console.error("unsupported currency", persistentSettings.fiatPriceCurrency);
return; return "UNSUPPORTED";
} }
}
var uFiat = Utils.formatMoney(unlocked_balance * ticker); function fiatApiConvertToFiat(amount) {
var bFiat = Utils.formatMoney(balance * ticker); var ticker = persistentSettings.fiatPriceCurrency === "xmrusd" ? appWindow.fiatPriceXMRUSD : appWindow.fiatPriceXMREUR;
if(ticker <= 0){
console.log(fiatApiError("Invalid ticker value: " + ticker));
return "?.??";
}
return (amount * ticker).toFixed(2);
}
leftPanel.unlockedBalanceTextFiat = symbol + uFiat; function fiatApiUpdateBalance(balance){
leftPanel.balanceTextFiat = symbol + bFiat; // update balance card
var bFiat = "?.??"
if (!hideBalanceForced && !persistentSettings.hideBalance) {
bFiat = fiatApiConvertToFiat(balance);
}
leftPanel.balanceFiatString = bFiat;
} }
function fiatTimerStart(){ function fiatTimerStart(){
@@ -1294,6 +1296,9 @@ ApplicationWindow {
Component.onCompleted: { Component.onCompleted: {
x = (Screen.width - width) / 2 x = (Screen.width - width) / 2
y = (Screen.height - maxWindowHeight) / 2 y = (Screen.height - maxWindowHeight) / 2
applyWalletMode(persistentSettings.walletMode);
// //
walletManager.walletOpened.connect(onWalletOpened); walletManager.walletOpened.connect(onWalletOpened);
walletManager.deviceButtonRequest.connect(onDeviceButtonRequest); walletManager.deviceButtonRequest.connect(onDeviceButtonRequest);
@@ -1383,7 +1388,6 @@ ApplicationWindow {
property bool useRemoteNode: false property bool useRemoteNode: false
property string remoteNodeAddress: "" property string remoteNodeAddress: ""
property string bootstrapNodeAddress: "" property string bootstrapNodeAddress: ""
property string remoteNodeRegion: ""
property bool segregatePreForkOutputs: true property bool segregatePreForkOutputs: true
property bool keyReuseMitigation2: true property bool keyReuseMitigation2: true
property int segregationHeight: 0 property int segregationHeight: 0
@@ -1391,9 +1395,7 @@ ApplicationWindow {
property bool hideBalance: false property bool hideBalance: false
property bool lockOnUserInActivity: true property bool lockOnUserInActivity: true
property int walletMode: 2 property int walletMode: 2
property string remoteNodeService: ""
property int lockOnUserInActivityInterval: 10 // minutes property int lockOnUserInActivityInterval: 10 // minutes
property bool showPid: false
property bool blackTheme: true property bool blackTheme: true
property bool fiatPriceEnabled: false property bool fiatPriceEnabled: false
@@ -1592,153 +1594,96 @@ ApplicationWindow {
states: [ states: [
State { State {
name: "wizard" name: "wizard"
PropertyChanges { target: leftPanel; visible: false }
PropertyChanges { target: middlePanel; visible: false } PropertyChanges { target: middlePanel; visible: false }
PropertyChanges { target: wizard; visible: true } PropertyChanges { target: wizard; visible: true }
PropertyChanges { target: resizeArea; visible: true } PropertyChanges { target: resizeArea; visible: true }
PropertyChanges { target: mobileHeader; visible: false }
PropertyChanges { target: titleBar; state: "essentials" } PropertyChanges { target: titleBar; state: "essentials" }
}, State { }, State {
name: "normal" name: "normal"
PropertyChanges { target: leftPanel; visible: (isMobile)? false : true }
PropertyChanges { target: middlePanel; visible: true } PropertyChanges { target: middlePanel; visible: true }
PropertyChanges { target: titleBar; basicButtonVisible: true }
PropertyChanges { target: wizard; visible: false } PropertyChanges { target: wizard; visible: false }
PropertyChanges { target: resizeArea; visible: true } PropertyChanges { target: resizeArea; visible: true }
PropertyChanges { target: titleBar; state: "default" } PropertyChanges { target: titleBar; state: "default" }
PropertyChanges { target: mobileHeader; visible: isMobile ? true : false }
} }
] ]
MobileHeader {
id: mobileHeader
visible: isMobile
anchors.left: parent.left
anchors.right: parent.right
height: visible? 65 : 0
MouseArea {
enabled: persistentSettings.customDecorations
property var previousPosition
anchors.fill: parent
propagateComposedEvents: true
onPressed: previousPosition = globalCursor.getPosition()
onPositionChanged: {
if (pressedButtons == Qt.LeftButton) {
var pos = globalCursor.getPosition()
var dx = pos.x - previousPosition.x
var dy = pos.y - previousPosition.y
appWindow.x += dx
appWindow.y += dy
previousPosition = pos
}
}
}
}
LeftPanel { LeftPanel {
id: leftPanel id: leftPanel
anchors.top: mobileHeader.bottom anchors.top: parent.top
anchors.left: parent.left anchors.left: parent.left
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
visible: rootItem.state == "normal" && middlePanel.state != "Merchant"
currentAccountIndex: currentWallet ? currentWallet.currentSubaddressAccount : 0
currentAccountLabel: {
if (currentWallet) {
return currentWallet.getSubaddressLabel(currentWallet.currentSubaddressAccount, 0);
}
return qsTr("Primary account") + translationManager.emptyString;
}
onTransferClicked: { onTransferClicked: {
middlePanel.state = "Transfer"; middlePanel.state = "Transfer";
middlePanel.flickable.contentY = 0; middlePanel.flickable.contentY = 0;
if(isMobile) {
hideMenu();
}
updateBalance(); updateBalance();
} }
onReceiveClicked: { onReceiveClicked: {
middlePanel.state = "Receive"; middlePanel.state = "Receive";
middlePanel.flickable.contentY = 0; middlePanel.flickable.contentY = 0;
if(isMobile) {
hideMenu();
}
updateBalance(); updateBalance();
} }
onMerchantClicked: { onMerchantClicked: {
middlePanel.state = "Merchant"; middlePanel.state = "Merchant";
middlePanel.flickable.contentY = 0; middlePanel.flickable.contentY = 0;
if(isMobile) {
hideMenu();
}
updateBalance(); updateBalance();
} }
onTxkeyClicked: { onTxkeyClicked: {
middlePanel.state = "TxKey"; middlePanel.state = "TxKey";
middlePanel.flickable.contentY = 0; middlePanel.flickable.contentY = 0;
if(isMobile) {
hideMenu();
}
updateBalance(); updateBalance();
} }
onSharedringdbClicked: { onSharedringdbClicked: {
middlePanel.state = "SharedRingDB"; middlePanel.state = "SharedRingDB";
middlePanel.flickable.contentY = 0; middlePanel.flickable.contentY = 0;
if(isMobile) {
hideMenu();
}
updateBalance(); updateBalance();
} }
onHistoryClicked: { onHistoryClicked: {
middlePanel.state = "History"; middlePanel.state = "History";
middlePanel.flickable.contentY = 0; middlePanel.flickable.contentY = 0;
if(isMobile) {
hideMenu();
}
updateBalance(); updateBalance();
} }
onAddressBookClicked: { onAddressBookClicked: {
middlePanel.state = "AddressBook"; middlePanel.state = "AddressBook";
middlePanel.flickable.contentY = 0; middlePanel.flickable.contentY = 0;
if(isMobile) {
hideMenu();
}
updateBalance(); updateBalance();
} }
onMiningClicked: { onMiningClicked: {
middlePanel.state = "Mining"; middlePanel.state = "Mining";
middlePanel.flickable.contentY = 0; middlePanel.flickable.contentY = 0;
if(isMobile) {
hideMenu();
}
updateBalance(); updateBalance();
} }
onSignClicked: { onSignClicked: {
middlePanel.state = "Sign"; middlePanel.state = "Sign";
middlePanel.flickable.contentY = 0; middlePanel.flickable.contentY = 0;
if(isMobile) {
hideMenu();
}
updateBalance(); updateBalance();
} }
onSettingsClicked: { onSettingsClicked: {
middlePanel.state = "Settings"; middlePanel.state = "Settings";
middlePanel.flickable.contentY = 0; middlePanel.flickable.contentY = 0;
if(isMobile) {
hideMenu();
}
updateBalance(); updateBalance();
} }
onAccountClicked: { onAccountClicked: {
middlePanel.state = "Account"; middlePanel.state = "Account";
middlePanel.flickable.contentY = 0; middlePanel.flickable.contentY = 0;
if(isMobile) {
hideMenu();
}
updateBalance(); updateBalance();
} }
} }
@@ -1746,102 +1691,14 @@ ApplicationWindow {
MiddlePanel { MiddlePanel {
id: middlePanel id: middlePanel
anchors.top: mobileHeader.bottom accountView.currentAccountIndex: currentWallet ? currentWallet.currentSubaddressAccount : 0
anchors.top: parent.top
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.left: leftPanel.visible ? leftPanel.right : parent.left anchors.left: leftPanel.visible ? leftPanel.right : parent.left
anchors.right: parent.right anchors.right: parent.right
state: "Transfer" state: "Transfer"
} }
SequentialAnimation {
id: goToBasicAnimation
// PropertyAction {
// target: appWindow
// properties: "visibility"
// value: Window.Windowed
// }
// PropertyAction {
// target: titleBar
// properties: "maximizeButtonVisible"
// value: false
// }
// PropertyAction {
// target: frameArea
// properties: "blocked"
// value: true
// }
PropertyAction {
target: resizeArea
properties: "visible"
value: true
}
// PropertyAction {
// target: appWindow
// properties: "height"
// value: 30
// }
// PropertyAction {
// target: appWindow
// properties: "width"
// value: 326
// }
PropertyAction {
target: leftPanel
properties: "visible"
value: false
}
PropertyAction {
target: middlePanel
properties: "basicMode"
value: true
}
// PropertyAction {
// target: appWindow
// properties: "height"
// value: middlePanel.height
// }
onStopped: {
// middlePanel.visible = false
leftPanel.visible = false
}
}
SequentialAnimation {
id: goToProAnimation
// PropertyAction {
// target: appWindow
// properties: "height"
// value: 30
// }
PropertyAction {
target: middlePanel
properties: "basicMode"
value: false
}
PropertyAction {
targets: [leftPanel, middlePanel, resizeArea]
properties: "visible"
value: true
}
// PropertyAction {
// target: appWindow
// properties: "height"
// value: maxWindowHeight
// }
// PropertyAction {
// target: frameArea
// properties: "blocked"
// value: false
// }
// PropertyAction {
// target: titleBar
// properties: "maximizeButtonVisible"
// value: true
// }
}
WizardController { WizardController {
id: wizard id: wizard
anchors.fill: parent anchors.fill: parent
@@ -1906,21 +1763,14 @@ ApplicationWindow {
TitleBar { TitleBar {
id: titleBar id: titleBar
visible: persistentSettings.customDecorations && middlePanel.state !== "Merchant" visible: persistentSettings.customDecorations && middlePanel.state !== "Merchant"
walletName: appWindow.walletName
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
onCloseClicked: appWindow.close(); onCloseClicked: appWindow.close();
onLanguageClicked: appWindow.toggleLanguageView(); onLanguageClicked: appWindow.toggleLanguageView();
onCloseWalletClicked: appWindow.showWizard();
onMaximizeClicked: appWindow.visibility = appWindow.visibility !== Window.Maximized ? Window.Maximized : Window.Windowed onMaximizeClicked: appWindow.visibility = appWindow.visibility !== Window.Maximized ? Window.Maximized : Window.Windowed
onMinimizeClicked: appWindow.visibility = Window.Minimized onMinimizeClicked: appWindow.visibility = Window.Minimized
onGoToBasicVersion: {
if (yes) {
// basicPanel.currentView = middlePanel.currentView
goToBasicAnimation.start()
} else {
// middlePanel.currentView = basicPanel.currentView
goToProAnimation.start()
}
}
} }
MoneroMerchant.MerchantTitlebar { MoneroMerchant.MerchantTitlebar {
@@ -2004,41 +1854,43 @@ ApplicationWindow {
onTriggered: appWindow.themeTransition = true; onTriggered: appWindow.themeTransition = true;
} }
function checkNoSyncFlag() {
if (!appWindow.daemonRunning) {
return true;
}
if (appWindow.walletMode == 0 && !daemonManager.noSync()) {
return false;
}
if (appWindow.walletMode == 1 && daemonManager.noSync()) {
return false;
}
return true;
}
function checkSimpleModeConnection(){ function checkSimpleModeConnection(){
// auto-connection mechanism for simple mode // auto-connection mechanism for simple mode
if(persistentSettings.nettype != NetworkType.MAINNET) return;
if(appWindow.walletMode >= 2) return; if(appWindow.walletMode >= 2) return;
var disconnected = leftPanel.networkStatus.connected === Wallet.ConnectionStatus_Disconnected; const disconnectedTimeoutSec = 30;
var disconnectedEpoch = appWindow.disconnectedEpoch; const firstCheckDelaySec = 2;
if(disconnectedEpoch === 0){
const connected = leftPanel.networkStatus.connected !== Wallet.ConnectionStatus_Disconnected;
const firstRun = appWindow.disconnectedEpoch == 0;
if (firstRun) {
appWindow.disconnectedEpoch = Utils.epoch() + firstCheckDelaySec - disconnectedTimeoutSec;
} else if (connected) {
appWindow.disconnectedEpoch = Utils.epoch(); appWindow.disconnectedEpoch = Utils.epoch();
} }
// disconnected longer than 5 seconds? const sinceLastConnect = Utils.epoch() - appWindow.disconnectedEpoch;
if(disconnected && disconnectedEpoch > 0 && (Utils.epoch() - disconnectedEpoch) >= 5){ if (sinceLastConnect < disconnectedTimeoutSec && checkNoSyncFlag()) {
// for bootstrap mode, first wait until daemon is killed return;
if(appWindow.walletMode === 1 && appWindow.daemonRunning) {
appWindow.stopDaemon();
return;
}
// fetch new node list
wizard.fetchRemoteNodes(function() {
// fetched node, connect
if(appWindow.walletMode === 0){
appWindow.connectRemoteNode();
} else if(appWindow.walletMode === 1){
appWindow.startDaemon(persistentSettings.daemonFlags);
}
// reset state
appWindow.disconnectedEpoch = 0;
return;
}, function(){
appWindow.showStatusMessage(qsTr("Failed to fetch remote nodes from third-party server."), simpleModeConnectionTimer.interval / 1000);
});
} }
if (appWindow.daemonRunning) {
appWindow.stopDaemon();
}
appWindow.startDaemon("");
} }
Timer { Timer {
@@ -2082,6 +1934,23 @@ ApplicationWindow {
statusMessage.visible = true statusMessage.visible = true
} }
function showDaemonIsRunningDialog(onClose) {
// Show confirmation dialog
confirmationDialog.title = qsTr("Local node is running") + translationManager.emptyString;
confirmationDialog.text = qsTr("Do you want to stop local node or keep it running in the background?") + translationManager.emptyString;
confirmationDialog.icon = StandardIcon.Question;
confirmationDialog.cancelText = qsTr("Force stop") + translationManager.emptyString;
confirmationDialog.okText = qsTr("Keep it running") + translationManager.emptyString;
confirmationDialog.onAcceptedCallback = function() {
onClose();
}
confirmationDialog.onRejectedCallback = function() {
daemonManager.stop(persistentSettings.nettype);
onClose();
};
confirmationDialog.open();
}
onClosing: { onClosing: {
close.accepted = false; close.accepted = false;
console.log("blocking close event"); console.log("blocking close event");
@@ -2103,22 +1972,12 @@ ApplicationWindow {
// If daemon is running - prompt user before exiting // If daemon is running - prompt user before exiting
if(typeof daemonManager != "undefined" && daemonRunning) { if(typeof daemonManager != "undefined" && daemonRunning) {
// Show confirmation dialog if (appWindow.walletMode == 0) {
confirmationDialog.title = qsTr("Daemon is running") + translationManager.emptyString; stopDaemon();
confirmationDialog.text = qsTr("Daemon will still be running in background when GUI is closed.");
confirmationDialog.icon = StandardIcon.Question
confirmationDialog.cancelText = qsTr("Stop daemon")
confirmationDialog.onAcceptedCallback = function() {
closeAccepted(); closeAccepted();
} else {
showDaemonIsRunningDialog(closeAccepted);
} }
confirmationDialog.onRejectedCallback = function() {
daemonManager.stop(persistentSettings.nettype);
closeAccepted();
};
confirmationDialog.open()
} else { } else {
closeAccepted(); closeAccepted();
} }
@@ -2140,17 +1999,12 @@ ApplicationWindow {
if (parts.length == 4) { if (parts.length == 4) {
var version = parts[0] var version = parts[0]
var hash = parts[1] var hash = parts[1]
//var user_url = parts[2] var user_url = parts[2]
//var auto_url = parts[3]
var osBuildTag = isMac ? "mac-x64" : isWindows ? "win-x64" : isLinux ? "linux-x64" : "unknownBuildTag"
var extension = isMac || isLinux ? ".tar.bz2" : isWindows ? ".zip" : ".unknownExtension"
var base_url = "https://downloads.getmonero.org/gui/monero-gui-"
var download_url = base_url + osBuildTag + "-v" + version + extension
var msg = "" var msg = ""
if (osBuildTag !== "unknownBuildTag") { if (isMac || isWindows || isLinux) {
msg = qsTr("New version of Monero v.%1 is available.<br><br>Download:<br>%2<br><br>SHA256 Hash:<br>%3").arg(version).arg(download_url).arg(hash) + translationManager.emptyString msg = qsTr("New version of Monero v%1 is available.<br><br>Download:<br>%2<br><br>SHA256 Hash:<br>%3").arg(version).arg(user_url).arg(hash) + translationManager.emptyString
} else { } else {
msg = qsTr("New version of Monero is available. Check out getmonero.org") + translationManager.emptyString msg = qsTr("New version of Monero v%1 is available. Check out getmonero.org").arg(version) + translationManager.emptyString
} }
notifier.show(msg) notifier.show(msg)
} else { } else {
@@ -2179,14 +2033,16 @@ ApplicationWindow {
// reset label text. othewise potential privacy leak showing unlock time when switching wallets // reset label text. othewise potential privacy leak showing unlock time when switching wallets
function clearMoneroCardLabelText(){ function clearMoneroCardLabelText(){
leftPanel.minutesToUnlockTxt = qsTr("Unlocked balance") leftPanel.balanceString = "?.??"
leftPanel.balanceLabelText = qsTr("Balance") leftPanel.balanceFiatString = "?.??"
} }
// some fields need an extra nudge when changing languages // some fields need an extra nudge when changing languages
function resetLanguageFields(){ function resetLanguageFields(){
clearMoneroCardLabelText() clearMoneroCardLabelText()
onWalletRefresh() if (currentWallet) {
onWalletRefresh();
}
} }
function userActivity() { function userActivity() {
@@ -2229,11 +2085,22 @@ ApplicationWindow {
} }
function changeWalletMode(mode){ function changeWalletMode(mode){
appWindow.disconnectedEpoch = 0;
appWindow.walletMode = mode; appWindow.walletMode = mode;
persistentSettings.walletMode = mode; persistentSettings.walletMode = mode;
persistentSettings.useRemoteNode = mode === 0 ? true : false; applyWalletMode(mode);
}
console.log("walletMode changed: " + (mode === 0 ? "simple": mode === 1 ? "simple (bootstrap)" : "Advanced")); function applyWalletMode(mode){
if (mode < 2) {
persistentSettings.useRemoteNode = false;
persistentSettings.bootstrapNodeAddress = "auto";
if (middlePanel.settingsView.settingsStateViewState === "Node" || middlePanel.settingsView.settingsStateViewState === "Log") {
middlePanel.settingsView.settingsStateViewState = "Wallet"
}
}
console.log("walletMode: " + (mode === 0 ? "simple": mode === 1 ? "simple (bootstrap)" : "Advanced"));
} }
// Daemon console // Daemon console

View File

@@ -1,6 +1,6 @@
# qml components require at least QT 5.9.0 # qml components require at least QT 5.9.7
lessThan (QT_MAJOR_VERSION, 5) | lessThan (QT_MINOR_VERSION, 9) { lessThan (QT_MAJOR_VERSION, 5) | lessThan (QT_MINOR_VERSION, 9) {
error("Can't build with Qt $${QT_VERSION}. Use at least Qt 5.9.0") error("Can't build with Qt $${QT_VERSION}. Use at least Qt 5.9.7")
} }
TEMPLATE = app TEMPLATE = app
@@ -16,10 +16,21 @@ packagesExist(libusb-1.0) {
packagesExist(hidapi-libusb) { packagesExist(hidapi-libusb) {
PKGCONFIG += hidapi-libusb PKGCONFIG += hidapi-libusb
} }
!win32 {
GCC_VERSION = $$system("g++ -dumpversion")
GCC_VERSION = $$split(GCC_VERSION, .)
GCC_VERSION_MAJOR = $$member(GCC_VERSION, 0)
GCC_VERSION_MINOR = $$member(GCC_VERSION, 1)
greaterThan(GCC_VERSION_MAJOR, 9) | if(equals(GCC_VERSION_MAJOR, 9) : greaterThan(GCC_VERSION_MINOR, 0)) {
GCC_9_1_OR_GREATER = TRUE
}
!win32 | !isEmpty(GCC_9_1_OR_GREATER) {
QMAKE_CXXFLAGS += -fPIC -fstack-protector -fstack-protector-strong QMAKE_CXXFLAGS += -fPIC -fstack-protector -fstack-protector-strong
QMAKE_LFLAGS += -fstack-protector -fstack-protector-strong QMAKE_LFLAGS += -fstack-protector -fstack-protector-strong
}
!win32 {
packagesExist(protobuf) { packagesExist(protobuf) {
PKGCONFIG += protobuf PKGCONFIG += protobuf
} }
@@ -142,25 +153,25 @@ ios:arm64 {
LIBS += \ LIBS += \
-L$$PWD/../ofxiOSBoost/build/libs/boost/lib/arm64 \ -L$$PWD/../ofxiOSBoost/build/libs/boost/lib/arm64 \
} }
LIBS_COMMON = \
-lwallet_merged \
-llmdb \
-lepee \
-lunbound \
-lsodium \
-leasylogging \
-lrandomx
!ios:!android { !ios:!android {
LIBS += -L$$WALLET_ROOT/lib \ LIBS += -L$$WALLET_ROOT/lib \
-lwallet_merged \ $$LIBS_COMMON
-llmdb \
-lepee \
-lunbound \
-lsodium \
-leasylogging
} }
android { android {
message("Host is Android") message("Host is Android")
LIBS += -L$$WALLET_ROOT/lib \ LIBS += -L$$WALLET_ROOT/lib \
-lwallet_merged \ $$LIBS_COMMON
-llmdb \
-lepee \
-lunbound \
-lsodium \
-leasylogging
} }
@@ -175,12 +186,7 @@ ios {
QMAKE_IOS_DEVICE_ARCHS = arm64 QMAKE_IOS_DEVICE_ARCHS = arm64
CONFIG += arm64 CONFIG += arm64
LIBS += -L$$WALLET_ROOT/lib-ios \ LIBS += -L$$WALLET_ROOT/lib-ios \
-lwallet_merged \ $$LIBS_COMMON
-llmdb \
-lepee \
-lunbound \
-lsodium \
-leasylogging
LIBS+= \ LIBS+= \
-L$$PWD/../OpenSSL-for-iPhone/lib \ -L$$PWD/../OpenSSL-for-iPhone/lib \
@@ -287,6 +293,7 @@ win32 {
-licudt \ -licudt \
-licutu \ -licutu \
-liconv \ -liconv \
-lstdc++ \
-lpthread \ -lpthread \
-lsetupapi \ -lsetupapi \
-lssl \ -lssl \
@@ -337,13 +344,13 @@ linux {
-llmdb \ -llmdb \
-lsodium \ -lsodium \
-lhidapi-libusb \ -lhidapi-libusb \
-lcrypto $$TREZOR_LINKER \ -lcrypto $$TREZOR_LINKER
-lX11
if(!android) { if(!android) {
LIBS+= \ LIBS+= \
-Wl,-Bdynamic \ -Wl,-Bdynamic \
-lGL -lGL \
-lX11
} }
# currently monero has an issue with "static" build and linunwind-dev, # currently monero has an issue with "static" build and linunwind-dev,
# so we link libunwind-dev only for non-Ubuntu distros # so we link libunwind-dev only for non-Ubuntu distros
@@ -363,11 +370,19 @@ macx {
# message("using static libraries") # message("using static libraries")
# LIBS+= -Wl,-Bstatic # LIBS+= -Wl,-Bstatic
# } # }
OPENSSL_LIBRARY_DIRS = $$system(brew --prefix openssl, lines, EXIT_CODE)
equals(EXIT_CODE, 0) {
OPENSSL_LIBRARY_DIRS = $$OPENSSL_LIBRARY_DIRS/lib
} else {
OPENSSL_LIBRARY_DIRS = /usr/local/ssl/lib
}
QT += macextras QT += macextras
OBJECTIVE_SOURCES += src/qt/macoshelper.mm OBJECTIVE_SOURCES += src/qt/macoshelper.mm
LIBS+= \ LIBS+= \
-L/usr/local/lib \ -L/usr/local/lib \
-L/usr/local/opt/openssl/lib \ -L$$OPENSSL_LIBRARY_DIRS \
-L/usr/local/opt/boost/lib \ -L/usr/local/opt/boost/lib \
-lboost_serialization \ -lboost_serialization \
-lboost_thread-mt \ -lboost_thread-mt \
@@ -497,6 +512,9 @@ DISTFILES += \
notes.txt \ notes.txt \
monero/src/wallet/CMakeLists.txt monero/src/wallet/CMakeLists.txt
VERSION = $$cat('version.js', lines)
VERSION = $$find(VERSION, 'GUI_VERSION')
VERSION = $$replace(VERSION, '.*(\d+\.\d+\.\d+\.\d+).*', '\1')
# windows application icon # windows application icon
RC_ICONS = images/appicon.ico RC_ICONS = images/appicon.ico

View File

@@ -37,7 +37,7 @@
#ifdef Q_OS_WIN32 #ifdef Q_OS_WIN32
#include <windows.h> #include <windows.h>
#endif #endif
#ifdef Q_OS_LINUX #if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)
#include <X11/XKBlib.h> #include <X11/XKBlib.h>
#undef KeyPress #undef KeyPress
#undef KeyRelease #undef KeyRelease
@@ -78,7 +78,7 @@ bool OSHelper::isCapsLock() const
// platform dependent method of determining if CAPS LOCK is on // platform dependent method of determining if CAPS LOCK is on
#if defined(Q_OS_WIN32) // MS Windows version #if defined(Q_OS_WIN32) // MS Windows version
return GetKeyState(VK_CAPITAL) == 1; return GetKeyState(VK_CAPITAL) == 1;
#elif defined(Q_OS_LINUX) // X11 version #elif defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID) // X11 version
Display * d = XOpenDisplay((char*)0); Display * d = XOpenDisplay((char*)0);
bool caps_state = false; bool caps_state = false;
if (d) { if (d) {

View File

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

View File

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

View File

@@ -181,7 +181,6 @@ Rectangle {
Layout.rightMargin: sideMargin Layout.rightMargin: sideMargin
columns: 2 columns: 2
columnSpacing: 20 columnSpacing: 20
z: 6
MoneroComponents.DatePicker { MoneroComponents.DatePicker {
id: fromDatePicker id: fromDatePicker
@@ -228,7 +227,7 @@ Rectangle {
MoneroComponents.TextPlain { MoneroComponents.TextPlain {
font.family: MoneroComponents.Style.fontRegular.name font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 15 font.pixelSize: 15
text: qsTr("Sort by") + ":" text: qsTr("Sort by") + ":" + translationManager.emptyString
color: MoneroComponents.Style.defaultFontColor color: MoneroComponents.Style.defaultFontColor
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
@@ -447,7 +446,7 @@ Rectangle {
MoneroComponents.TextPlain { MoneroComponents.TextPlain {
font.family: MoneroComponents.Style.fontRegular.name font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 15 font.pixelSize: 15
text: qsTr("Page") + ":" text: qsTr("Page") + ":" + translationManager.emptyString
color: MoneroComponents.Style.defaultFontColor color: MoneroComponents.Style.defaultFontColor
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
@@ -651,7 +650,7 @@ Rectangle {
MoneroComponents.TextPlain { MoneroComponents.TextPlain {
font.family: MoneroComponents.Style.fontRegular.name font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 15 font.pixelSize: 15
text: _amount + " XMR" text: displayAmount
color: MoneroComponents.Style.defaultFontColor color: MoneroComponents.Style.defaultFontColor
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
@@ -870,7 +869,7 @@ Rectangle {
MoneroComponents.TextPlain { MoneroComponents.TextPlain {
font.family: MoneroComponents.Style.fontRegular.name font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 15 font.pixelSize: 15
text: persistentSettings.historyHumanDates ? dateHuman : date + " " + time text: persistentSettings.historyHumanDates ? dateHuman : dateTime
color: MoneroComponents.Style.defaultFontColor color: MoneroComponents.Style.defaultFontColor
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
@@ -882,7 +881,7 @@ Rectangle {
onEntered: { onEntered: {
parent.color = MoneroComponents.Style.orange parent.color = MoneroComponents.Style.orange
if (persistentSettings.historyHumanDates) { if (persistentSettings.historyHumanDates) {
parent.text = date + " " + time; parent.text = dateTime;
} }
} }
onExited: { onExited: {
@@ -939,7 +938,7 @@ Rectangle {
anchors.leftMargin: 10 anchors.leftMargin: 10
text: FontAwesome.productHunt text: FontAwesome.productHunt
small: true small: true
label.font.family: FontAwesome.fontFamily label.font.family: FontAwesome.fontFamilyBrands
fontSize: 18 fontSize: 18
width: 36 width: 36
@@ -1197,7 +1196,7 @@ Rectangle {
if(res[i].state === 'copyable_address') root.toClipboard(address); if(res[i].state === 'copyable_address') root.toClipboard(address);
if(res[i].state === 'copyable_txkey') root.getTxKey(hash, res[i]); if(res[i].state === 'copyable_txkey') root.getTxKey(hash, res[i]);
if(res[i].state === 'set_tx_note') root.editDescription(hash); if(res[i].state === 'set_tx_note') root.editDescription(hash);
if(res[i].state === 'details') root.showTxDetails(hash, paymentId, destinations, subaddrAccount, subaddrIndex); if(res[i].state === 'details') root.showTxDetails(hash, paymentId, destinations, subaddrAccount, subaddrIndex, dateTime, displayAmount, isout);
if(res[i].state === 'proof') root.showTxProof(hash, paymentId, destinations, subaddrAccount, subaddrIndex); if(res[i].state === 'proof') root.showTxProof(hash, paymentId, destinations, subaddrAccount, subaddrIndex);
doCollapse = false; doCollapse = false;
break; break;
@@ -1361,8 +1360,9 @@ Rectangle {
// applying filters // applying filters
root.txData = JSON.parse(JSON.stringify(root.txModelData)); // deepcopy root.txData = JSON.parse(JSON.stringify(root.txModelData)); // deepcopy
var fromDate = fromDatePicker.currentDate.getTime() / 1000; const timezoneOffset = new Date().getTimezoneOffset() * 60;
var toDate = toDatePicker.currentDate.getTime() / 1000; var fromDate = Math.floor(fromDatePicker.currentDate.getTime() / 86400000) * 86400 + timezoneOffset;
var toDate = (Math.floor(toDatePicker.currentDate.getTime() / 86400000) + 1) * 86400 + timezoneOffset;
var txs = []; var txs = [];
for (var i = 0; i < root.txData.length; i++){ for (var i = 0; i < root.txData.length; i++){
@@ -1479,12 +1479,12 @@ Rectangle {
var timestamp = new Date(date + " " + time).getTime() / 1000; var timestamp = new Date(date + " " + time).getTime() / 1000;
var dateHuman = Utils.ago(timestamp); var dateHuman = Utils.ago(timestamp);
var _amount = amount; var displayAmount = amount;
if(_amount === 0){ if(displayAmount === 0){
// *sometimes* amount is 0, while the 'destinations string' // *sometimes* amount is 0, while the 'destinations string'
// has the correct amount, so we try to fetch it from that instead. // has the correct amount, so we try to fetch it from that instead.
_amount = TxUtils.destinationsToAmount(destinations); displayAmount = TxUtils.destinationsToAmount(destinations);
_amount = Number(_amount *1); displayAmount = Number(displayAmount *1);
} }
var tx_note = currentWallet.getUserNote(hash); var tx_note = currentWallet.getUserNote(hash);
@@ -1502,15 +1502,14 @@ Rectangle {
"i": i, "i": i,
"isout": isout, "isout": isout,
"amount": Number(amount), "amount": Number(amount),
"_amount": _amount, "displayAmount": displayAmount + " XMR",
"hash": hash, "hash": hash,
"paymentId": paymentId, "paymentId": paymentId,
"address": address, "address": address,
"destinations": destinations, "destinations": destinations,
"tx_note": tx_note, "tx_note": tx_note,
"time": time,
"date": date,
"dateHuman": dateHuman, "dateHuman": dateHuman,
"dateTime": date + " " + time,
"blockheight": blockheight, "blockheight": blockheight,
"address": address, "address": address,
"timestamp": timestamp, "timestamp": timestamp,
@@ -1582,22 +1581,25 @@ Rectangle {
elem.parent.text = txKey ? txKey : '-'; elem.parent.text = txKey ? txKey : '-';
elem.parent.state = 'ready'; elem.parent.state = 'ready';
}); });
} else {
toClipboard(elem.parent.text);
} }
toClipboard(elem.parent.text);
} }
function showTxDetails(hash, paymentId, destinations, subaddrAccount, subaddrIndex){ function showTxDetails(hash, paymentId, destinations, subaddrAccount, subaddrIndex, dateTime, amount, isout) {
var tx_note = currentWallet.getUserNote(hash) var tx_note = currentWallet.getUserNote(hash)
var rings = currentWallet.getRings(hash) var rings = currentWallet.getRings(hash)
var address_label = subaddrIndex == 0 ? (qsTr("Primary address") + translationManager.emptyString) : currentWallet.getSubaddressLabel(subaddrAccount, subaddrIndex) var address_label = subaddrIndex == 0 ? (qsTr("Primary address") + translationManager.emptyString) : currentWallet.getSubaddressLabel(subaddrAccount, subaddrIndex)
var address = currentWallet.address(subaddrAccount, subaddrIndex) var address = currentWallet.address(subaddrAccount, subaddrIndex)
const hasPaymentId = parseInt(paymentId, 16);
const integratedAddress = !isout && hasPaymentId ? currentWallet.integratedAddress(paymentId) : null;
if (rings) if (rings)
rings = rings.replace(/\|/g, '\n') rings = rings.replace(/\|/g, '\n')
currentWallet.getTxKeyAsync(hash, function(hash, tx_key) { currentWallet.getTxKeyAsync(hash, function(hash, tx_key) {
informationPopup.title = qsTr("Transaction details") + translationManager.emptyString; informationPopup.title = qsTr("Transaction details") + translationManager.emptyString;
informationPopup.content = buildTxDetailsString(hash, paymentId, tx_key, tx_note, destinations, rings, address, address_label); informationPopup.content = buildTxDetailsString(hash, paymentId, tx_key, tx_note, destinations, rings, address, address_label, integratedAddress, dateTime, amount);
informationPopup.onCloseCallback = null informationPopup.onCloseCallback = null
informationPopup.open(); informationPopup.open();
}); });
@@ -1625,16 +1627,18 @@ Rectangle {
appWindow.showStatusMessage(qsTr("Copied to clipboard"),3); appWindow.showStatusMessage(qsTr("Copied to clipboard"),3);
} }
function buildTxDetailsString(tx_id, paymentId, tx_key,tx_note, destinations, rings, address, address_label) { function buildTxDetailsString(tx_id, paymentId, tx_key,tx_note, destinations, rings, address, address_label, integratedAddress, dateTime, amount) {
var trStart = '<tr><td width="85" style="padding-top:5px"><b>', var trStart = '<tr><td style="white-space: nowrap; padding-top:5px"><b>',
trMiddle = '</b></td><td style="padding-left:10px;padding-top:5px;">', trMiddle = '</b></td><td style="padding-left:10px;padding-top:5px;">',
trEnd = "</td></tr>"; trEnd = "</td></tr>";
return '<table border="0">' return '<table border="0">'
+ (tx_id ? trStart + qsTr("Tx ID:") + trMiddle + tx_id + trEnd : "") + (tx_id ? trStart + qsTr("Tx ID:") + trMiddle + tx_id + trEnd : "")
+ (address_label ? trStart + qsTr("Address label:") + trMiddle + address_label + trEnd : "") + (dateTime ? trStart + qsTr("Date") + ":" + trMiddle + dateTime + trEnd : "")
+ (amount ? trStart + qsTr("Amount") + ":" + trMiddle + amount + trEnd : "")
+ (address ? trStart + qsTr("Address:") + trMiddle + address + trEnd : "") + (address ? trStart + qsTr("Address:") + trMiddle + address + trEnd : "")
+ (paymentId ? trStart + qsTr("Payment ID:") + trMiddle + paymentId + trEnd : "") + (paymentId ? trStart + qsTr("Payment ID:") + trMiddle + paymentId + trEnd : "")
+ (integratedAddress ? trStart + qsTr("Integrated address") + ":" + trMiddle + integratedAddress + trEnd : "")
+ (tx_key ? trStart + qsTr("Tx key:") + trMiddle + tx_key + trEnd : "") + (tx_key ? trStart + qsTr("Tx key:") + trMiddle + tx_key + trEnd : "")
+ (tx_note ? trStart + qsTr("Tx note:") + trMiddle + tx_note + trEnd : "") + (tx_note ? trStart + qsTr("Tx note:") + trMiddle + tx_note + trEnd : "")
+ (destinations ? trStart + qsTr("Destinations:") + trMiddle + destinations + trEnd : "") + (destinations ? trStart + qsTr("Destinations:") + trMiddle + destinations + trEnd : "")

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -33,8 +33,6 @@ Item {
property var hiddenAmounts: [] property var hiddenAmounts: []
function onPageCompleted() { function onPageCompleted() {
appWindow.hideMenu();
// prepare tracking // prepare tracking
trackingCheckbox.checked = root.enableTracking trackingCheckbox.checked = root.enableTracking
root.update(); root.update();
@@ -56,8 +54,6 @@ Item {
timer.running = false timer.running = false
root.enableTracking = false root.enableTracking = false
trackingModel.clear() trackingModel.clear()
appWindow.showMenu();
} }
Image { Image {
@@ -162,7 +158,7 @@ Item {
"<p>It's up to you whether to accept unconfirmed transactions or not. It is likely they'll be " + "<p>It's up to you whether to accept unconfirmed transactions or not. It is likely they'll be " +
"confirmed in short order, but there is still a possibility they might not, so for larger " + "confirmed in short order, but there is still a possibility they might not, so for larger " +
"values you may want to wait for one or more confirmation(s).</p>" "values you may want to wait for one or more confirmation(s).</p>"
); ) + translationManager.emptyString;
} else if(root.trackingError !== ""){ } else if(root.trackingError !== ""){
return root.trackingError; return root.trackingError;
} else if(trackingModel.count < 1){ } else if(trackingModel.count < 1){
@@ -269,7 +265,7 @@ Item {
font.pixelSize: 12 font.pixelSize: 12
font.bold: false font.bold: false
color: "white" color: "white"
text: "<style type='text/css'>a {text-decoration: none; color: #FF6C3C; font-size: 12px;}</style>Currently selected address: " + addressLabel + " <a href='#'>(Change)</a>" text: qsTr("<style type='text/css'>a {text-decoration: none; color: #FF6C3C; font-size: 12px;}</style>Currently selected address: ") + addressLabel + qsTr(" <a href='#'>(Change)</a>") + translationManager.emptyString
textFormat: Text.RichText textFormat: Text.RichText
themeTransition: false themeTransition: false
@@ -450,7 +446,7 @@ Item {
font.pixelSize: 14 font.pixelSize: 14
font.bold: false font.bold: false
color: "white" color: "white"
text: qsTr("Amount to receive") + " (XMR)" text: qsTr("Amount to receive") + " (XMR)" + translationManager.emptyString
themeTransition: false themeTransition: false
} }
@@ -459,7 +455,7 @@ Item {
width: 220 width: 220
source: "qrc:///images/merchant/input_box.png" source: "qrc:///images/merchant/input_box.png"
TextField { MoneroComponents.Input {
id: amountToReceive id: amountToReceive
topPadding: 0 topPadding: 0
leftPadding: 10 leftPadding: 10

View File

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

View File

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

View File

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

View File

@@ -57,7 +57,7 @@ Rectangle {
anchors.left: parent.left anchors.left: parent.left
anchors.top: parent.top anchors.top: parent.top
anchors.right: parent.right anchors.right: parent.right
anchors.margins: (isMobile)? 17 : 20 anchors.margins: 20
anchors.topMargin: 0 anchors.topMargin: 0
spacing: 30 spacing: 30

View File

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

View File

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

View File

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

View File

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

24
qml.qrc
View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -65,7 +65,7 @@ class Wallet : public QObject
Q_PROPERTY(Status status READ status) Q_PROPERTY(Status status READ status)
Q_PROPERTY(NetworkType::Type nettype READ nettype) Q_PROPERTY(NetworkType::Type nettype READ nettype)
// Q_PROPERTY(ConnectionStatus connected READ connected) // Q_PROPERTY(ConnectionStatus connected READ connected)
Q_PROPERTY(quint32 currentSubaddressAccount READ currentSubaddressAccount) Q_PROPERTY(quint32 currentSubaddressAccount READ currentSubaddressAccount NOTIFY currentSubaddressAccountChanged)
Q_PROPERTY(bool synchronized READ synchronized) Q_PROPERTY(bool synchronized READ synchronized)
Q_PROPERTY(QString errorString READ errorString) Q_PROPERTY(QString errorString READ errorString)
Q_PROPERTY(TransactionHistory * history READ history) Q_PROPERTY(TransactionHistory * history READ history)
@@ -144,11 +144,8 @@ public:
//! empty path stores in current location //! empty path stores in current location
Q_INVOKABLE bool store(const QString &path = ""); Q_INVOKABLE bool store(const QString &path = "");
//! initializes wallet
Q_INVOKABLE bool init(const QString &daemonAddress, quint64 upperTransactionLimit = 0, bool isRecovering = false, bool isRecoveringFromDevice = false, quint64 restoreHeight = 0);
//! initializes wallet asynchronously //! initializes wallet asynchronously
Q_INVOKABLE void initAsync(const QString &daemonAddress, quint64 upperTransactionLimit = 0, bool isRecovering = false, bool isRecoveringFromDevice = false, quint64 restoreHeight = 0); Q_INVOKABLE void initAsync(const QString &daemonAddress, bool trustedDaemon = false, quint64 upperTransactionLimit = 0, bool isRecovering = false, bool isRecoveringFromDevice = false, quint64 restoreHeight = 0);
// Set daemon rpc user/pass // Set daemon rpc user/pass
Q_INVOKABLE void setDaemonLogin(const QString &daemonUsername = "", const QString &daemonPassword = ""); Q_INVOKABLE void setDaemonLogin(const QString &daemonUsername = "", const QString &daemonPassword = "");
@@ -179,6 +176,11 @@ public:
Q_INVOKABLE void addSubaddress(const QString& label); Q_INVOKABLE void addSubaddress(const QString& label);
Q_INVOKABLE QString getSubaddressLabel(quint32 accountIndex, quint32 addressIndex) const; Q_INVOKABLE QString getSubaddressLabel(quint32 accountIndex, quint32 addressIndex) const;
Q_INVOKABLE void setSubaddressLabel(quint32 accountIndex, quint32 addressIndex, const QString &label); Q_INVOKABLE void setSubaddressLabel(quint32 accountIndex, quint32 addressIndex, const QString &label);
Q_INVOKABLE void deviceShowAddressAsync(quint32 accountIndex, quint32 addressIndex, const QString &paymentId);
//! hw-device backed wallets
Q_INVOKABLE bool isHwBacked() const;
Q_INVOKABLE bool isLedger() const;
//! returns if view only wallet //! returns if view only wallet
Q_INVOKABLE bool viewOnly() const; Q_INVOKABLE bool viewOnly() const;
@@ -288,6 +290,10 @@ public:
void setPaymentId(const QString &paymentId); void setPaymentId(const QString &paymentId);
//! Namespace your cacheAttribute keys to avoid collisions
Q_INVOKABLE bool setCacheAttribute(const QString &key, const QString &val);
Q_INVOKABLE QString getCacheAttribute(const QString &key) const;
Q_INVOKABLE bool setUserNote(const QString &txid, const QString &note); Q_INVOKABLE bool setUserNote(const QString &txid, const QString &note);
Q_INVOKABLE QString getUserNote(const QString &txid) const; Q_INVOKABLE QString getUserNote(const QString &txid) const;
Q_INVOKABLE QString getTxKey(const QString &txid) const; Q_INVOKABLE QString getTxKey(const QString &txid) const;
@@ -353,11 +359,13 @@ signals:
void deviceButtonPressed(); void deviceButtonPressed();
void transactionCommitted(bool status, PendingTransaction *t, const QStringList& txid); void transactionCommitted(bool status, PendingTransaction *t, const QStringList& txid);
void heightRefreshed(quint64 walletHeight, quint64 daemonHeight, quint64 targetHeight) const; void heightRefreshed(quint64 walletHeight, quint64 daemonHeight, quint64 targetHeight) const;
void deviceShowAddressShowed();
// emitted when transaction is created async // emitted when transaction is created async
void transactionCreated(PendingTransaction * transaction, QString address, QString paymentId, quint32 mixinCount); void transactionCreated(PendingTransaction * transaction, QString address, QString paymentId, quint32 mixinCount);
void connectionStatusChanged(int status) const; void connectionStatusChanged(int status) const;
void currentSubaddressAccountChanged() const;
private: private:
Wallet(QObject * parent = nullptr); Wallet(QObject * parent = nullptr);
@@ -374,6 +382,9 @@ private:
//! returns daemon's blockchain target height //! returns daemon's blockchain target height
quint64 daemonBlockChainTargetHeight() const; quint64 daemonBlockChainTargetHeight() const;
//! initializes wallet
bool init(const QString &daemonAddress, bool trustedDaemon, quint64 upperTransactionLimit, bool isRecovering, bool isRecoveringFromDevice, quint64 restoreHeight);
private: private:
friend class WalletManager; friend class WalletManager;
friend class WalletListenerImpl; friend class WalletListenerImpl;
@@ -385,6 +396,8 @@ private:
mutable TransactionHistoryModel * m_historyModel; mutable TransactionHistoryModel * m_historyModel;
mutable TransactionHistorySortFilterModel * m_historySortFilterModel; mutable TransactionHistorySortFilterModel * m_historySortFilterModel;
QString m_paymentId; QString m_paymentId;
AddressBook * m_addressBook;
mutable AddressBookModel * m_addressBookModel;
mutable QTime m_daemonBlockChainHeightTime; mutable QTime m_daemonBlockChainHeightTime;
mutable quint64 m_daemonBlockChainHeight; mutable quint64 m_daemonBlockChainHeight;
int m_daemonBlockChainHeightTtl; int m_daemonBlockChainHeightTtl;
@@ -396,8 +409,6 @@ private:
mutable QTime m_connectionStatusTime; mutable QTime m_connectionStatusTime;
mutable bool m_initialized; mutable bool m_initialized;
uint32_t m_currentSubaddressAccount; uint32_t m_currentSubaddressAccount;
AddressBook * m_addressBook;
mutable AddressBookModel * m_addressBookModel;
Subaddress * m_subaddress; Subaddress * m_subaddress;
mutable SubaddressModel * m_subaddressModel; mutable SubaddressModel * m_subaddressModel;
SubaddressAccount * m_subaddressAccount; SubaddressAccount * m_subaddressAccount;

View File

@@ -376,7 +376,7 @@ bool WalletManager::localDaemonSynced() const
bool WalletManager::isDaemonLocal(const QString &daemon_address) const bool WalletManager::isDaemonLocal(const QString &daemon_address) const
{ {
return Monero::Utils::isAddressLocal(daemon_address.toStdString()); return daemon_address.isEmpty() ? false : Monero::Utils::isAddressLocal(daemon_address.toStdString());
} }
QString WalletManager::resolveOpenAlias(const QString &address) const QString WalletManager::resolveOpenAlias(const QString &address) const

View File

@@ -50,7 +50,7 @@ void AddressBookModel::endReset(){
endResetModel(); endResetModel();
} }
int AddressBookModel::rowCount(const QModelIndex &parent) const int AddressBookModel::rowCount(const QModelIndex &) const
{ {
return m_addressBook->count(); return m_addressBook->count();
} }

View File

@@ -49,7 +49,7 @@ void SubaddressAccountModel::endReset(){
endResetModel(); endResetModel();
} }
int SubaddressAccountModel::rowCount(const QModelIndex &parent) const int SubaddressAccountModel::rowCount(const QModelIndex &) const
{ {
return m_subaddressAccount->count(); return m_subaddressAccount->count();
} }

View File

@@ -50,7 +50,7 @@ void SubaddressModel::endReset(){
endResetModel(); endResetModel();
} }
int SubaddressModel::rowCount(const QModelIndex &parent) const int SubaddressModel::rowCount(const QModelIndex &) const
{ {
return m_subaddress->count(); return m_subaddress->count();
} }

View File

@@ -38,7 +38,7 @@ QPair<bool, QFuture<void>> FutureScheduler::run(std::function<void()> function)
}); });
} }
QPair<bool, QFuture<QJSValueList>> FutureScheduler::run(std::function<QJSValueList() noexcept> function, const QJSValue &callback) noexcept QPair<bool, QFuture<QJSValueList>> FutureScheduler::run(std::function<QJSValueList() noexcept> function, const QJSValue &callback)
{ {
if (!callback.isCallable()) if (!callback.isCallable())
{ {

View File

@@ -22,7 +22,7 @@ public:
void shutdownWaitForFinished() noexcept; void shutdownWaitForFinished() noexcept;
QPair<bool, QFuture<void>> run(std::function<void()> function) noexcept; QPair<bool, QFuture<void>> run(std::function<void()> function) noexcept;
QPair<bool, QFuture<QJSValueList>> run(std::function<QJSValueList() noexcept> function, const QJSValue &callback) noexcept; QPair<bool, QFuture<QJSValueList>> run(std::function<QJSValueList() noexcept> function, const QJSValue &callback);
private: private:
bool add() noexcept; bool add() noexcept;

View File

@@ -36,9 +36,9 @@
#include <QMutex> #include <QMutex>
#include <QMutexLocker> #include <QMutexLocker>
#include <QString> #include <QString>
#include "src/libwalletqt/WalletManager.h" #include "libwalletqt/WalletManager.h"
#include "src/NetworkType.h" #include "NetworkType.h"
#include "src/qt/utils.h" #include "qt/utils.h"
#include "KeysFiles.h" #include "KeysFiles.h"

View File

@@ -30,8 +30,8 @@
#define KEYSFILES_H #define KEYSFILES_H
#include <qqmlcontext.h> #include <qqmlcontext.h>
#include "src/libwalletqt/WalletManager.h" #include "libwalletqt/WalletManager.h"
#include "src/NetworkType.h" #include "NetworkType.h"
#include <QtCore> #include <QtCore>
class WalletKeysFiles class WalletKeysFiles

View File

@@ -40,7 +40,7 @@
#include <QHash> #include <QHash>
#include <QMetaProperty> #include <QMetaProperty>
#include "src/qt/MoneroSettings.h" #include "qt/MoneroSettings.h"
/*! /*!
\qmlmodule moneroSettings 1.0 \qmlmodule moneroSettings 1.0

View File

@@ -29,7 +29,7 @@
#include <QtCore> #include <QtCore>
#include <QApplication> #include <QApplication>
#include "src/qt/TailsOS.h" #include "TailsOS.h"
#include "utils.h" #include "utils.h"
bool fileExists(QString path) { bool fileExists(QString path) {
@@ -67,6 +67,7 @@ QString getAccountName(){
return accountName; return accountName;
} }
#ifdef Q_OS_LINUX
QString xdgMime(QApplication &app){ QString xdgMime(QApplication &app){
return QString( return QString(
"[Desktop Entry]\n" "[Desktop Entry]\n"
@@ -88,7 +89,6 @@ QString xdgMime(QApplication &app){
} }
void registerXdgMime(QApplication &app){ void registerXdgMime(QApplication &app){
#ifdef Q_OS_LINUX
// Register desktop entry // Register desktop entry
// - MacOS handled via Info.plist // - MacOS handled via Info.plist
// - Windows handled in the installer by rbrunner7 // - Windows handled in the installer by rbrunner7
@@ -111,8 +111,8 @@ void registerXdgMime(QApplication &app){
#endif #endif
fileWrite(filePath, mime); fileWrite(filePath, mime);
#endif
} }
#endif
QString randomUserAgent(){ QString randomUserAgent(){
QStringList urand; QStringList urand;

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