Compare commits

...

229 Commits

Author SHA1 Message Date
luigi1111
8444a9563e Merge pull request #3391
142c6bc cmake: prepare v0.17.2.1 (selsta)
2021-04-13 16:29:45 -05:00
luigi1111
2f41a6aecf Merge pull request #3390
f53af12 Wallet: fix transfer with Qt 5.12 (selsta)
2021-04-13 16:29:13 -05:00
luigi1111
61bb6d359f Merge pull request #3386
990e92b without StartupWMClass=monero-wallet-gui gnome-shell users can not add the applications to their favorites (Tobias Strauß)
2021-04-13 16:28:31 -05:00
luigi1111
938a4fada4 Merge pull request #3383
3a37364 cmake: remove typo (selsta)
2021-04-13 16:27:53 -05:00
selsta
142c6bc19f cmake: prepare v0.17.2.1 2021-04-13 16:15:24 +02:00
selsta
f53af12e02 Wallet: fix transfer with Qt 5.12 2021-04-13 07:27:05 +02:00
Tobias Strauß
990e92ba00 without StartupWMClass=monero-wallet-gui gnome-shell users can not add the applications to their favorites 2021-04-09 09:59:35 +02:00
luigi1111
816eeb4647 Merge pull request #3382
ddec66b build: prepare v0.17.2.0 (selsta)
2021-04-08 20:19:25 -05:00
luigi1111
d5b4f43f48 Merge pull request #3381
325e99d SettingsNode: fix icon size (selsta)
2021-04-08 20:10:16 -05:00
luigi1111
4597b4d94d Merge pull request #3380
c789efb workflows: test qml of docker compiled apps (selsta)
2021-04-08 20:09:52 -05:00
luigi1111
691fdac7a4 Merge pull request #3379
76b0b60 docker: build with QtQmlModels plugin (xiphon)
2021-04-08 20:01:08 -05:00
selsta
3a37364741 cmake: remove typo 2021-04-09 01:10:04 +02:00
selsta
c789efbe8a workflows: test qml of docker compiled apps 2021-04-08 01:36:06 +02:00
selsta
ddec66b2ad build: prepare v0.17.2.0 2021-04-08 01:32:54 +02:00
selsta
325e99d202 SettingsNode: fix icon size 2021-04-07 18:14:09 +02:00
xiphon
76b0b6013a docker: build with QtQmlModels plugin 2021-04-06 21:43:55 +00:00
luigi1111
183585653f Merge pull request #3373
6bc9627 SettingsNode: implement multiple remote nodes support (xiphon)
2021-04-06 11:35:23 -05:00
xiphon
6bc9627046 SettingsNode: implement multiple remote nodes support 2021-04-06 11:58:36 +00:00
luigi1111
ba7eeb12c5 Merge pull request #3371
ecc8b8c RemoteNodeEdit: change border color on focus (xiphon)
2021-04-05 21:43:23 -05:00
luigi1111
2354c615d1 Merge pull request #3370
74e1483 Checkbox: handle Enter/Return/Space keys, change border color on focus (xiphon)
2021-04-05 21:31:48 -05:00
luigi1111
3aa530aa84 Merge pull request #3345
6b0cb8d support pruning of new databases (benevanoff)
2021-04-05 21:31:00 -05:00
benevanoff
6b0cb8dadb support pruning of new databases 2021-04-05 18:56:19 -05:00
xiphon
ecc8b8cc99 RemoteNodeEdit: change border color on focus 2021-04-02 16:42:52 +00:00
xiphon
74e1483d0b Checkbox: handle Enter/Return/Space keys, change border color on focus 2021-04-02 12:10:24 +00:00
luigi1111
b3dace6b45 Merge pull request #3363
1e4c0d2 Renamed Norwegian translation file. (Anton Kling)
2021-03-30 14:07:07 -04:00
luigi1111
a17b88d80a Merge pull request #3361
7c881d0 LeftPanel: drop Advanced submenu items, use NavBar instead (xiphon)
2021-03-30 14:06:30 -04:00
luigi1111
1ee06fb78c Merge pull request #3360
d83f147 DaemonManager: start monerod with '--non-interactive' cli option set (xiphon)
2021-03-30 14:06:05 -04:00
luigi1111
ac2e9d370b Merge pull request #3332
a0a9d9e Transfer: implement sending to multiple recipients (xiphon)
2021-03-30 14:05:28 -04:00
xiphon
a0a9d9e31e Transfer: implement sending to multiple recipients 2021-03-23 08:50:10 +00:00
Anton Kling
1e4c0d2e0d Renamed Norwegian translation file. 2021-03-21 00:12:35 +01:00
xiphon
7c881d0100 LeftPanel: drop Advanced submenu items, use NavBar instead 2021-03-20 09:20:09 +00:00
xiphon
d83f14799e DaemonManager: start monerod with '--non-interactive' cli option set 2021-03-19 10:31:43 +00:00
luigi1111
34df4e74d4 Merge pull request #3359
244d622 Docker: Android - switch to debian:stretch, build CMake from source (xiphon)
2021-03-19 01:09:50 -04:00
luigi1111
9593a16cb0 Merge pull request #3357
34d3f65 Navbar: reimplement as a reusable component, drop redundant code (xiphon)
e94ac7c Navbar: move to components (xiphon)
2021-03-19 01:08:50 -04:00
luigi1111
3e8bc1dcd3 Merge pull request #3354
ad19dbb cmake: sync submodule if DEV_MODE=ON (selsta)
2021-03-19 01:08:02 -04:00
luigi1111
8dd06bba5c Merge pull request #3325
92a2ae1 TxConfirmationDialog: implement multiple recipients support, layout fixes (xiphon)
2021-03-19 01:06:59 -04:00
xiphon
244d622818 Docker: Android - switch to debian:stretch, build CMake from source 2021-03-17 12:57:28 +00:00
xiphon
34d3f6575a Navbar: reimplement as a reusable component, drop redundant code 2021-03-17 12:00:17 +00:00
xiphon
e94ac7c75d Navbar: move to components 2021-03-17 11:28:01 +00:00
selsta
ad19dbb440 cmake: sync submodule if DEV_MODE=ON 2021-03-12 01:26:57 +01:00
luigi1111
c18614f96f Merge pull request #3347
40adc6b use preferred colors for DaemonManagerDialog (Ben Evanoff)
2021-03-05 14:01:59 -05:00
luigi1111
16fdedc4d0 Merge pull request #3342
4403387 Translations from Weblate (weblate)
2021-03-05 14:01:20 -05:00
luigi1111
057de959b9 Merge pull request #3330
16fd2b4 LineEdit: fontFamily and inputPadding properties, fix backtab (xiphon)
2021-03-05 13:58:54 -05:00
luigi1111
88d26dbecf Merge pull request #3328
2bb1092 LineEditMulti: right padding, fontFamily, backtab, inline btns vcenter (xiphon)
2021-03-05 13:58:28 -05:00
luigi1111
059af2bb49 Merge pull request #3326
4f10683 OSHelper: Linux - fix isCapsLock memory leak (xiphon)
2021-03-05 13:58:00 -05:00
Weblate
4403387fa4 Translations from Weblate
Translation files updated:

    Found 724 source text(s) (2 new and 722 already existing)
    Removed 2 obsolete entries

Translators:

* Spanish

    * Luis Alejandro Herrera Bolaños
    * ian vatega
    * Miguel Medina
    * Michael Russo
    * Samuel
    * 0x82b
    * kombometralla
    * Tony Nguyen

* Slovak

    * Boris Sipos

* Vietnamese

    * Tabula Rasa

* Italian

    * 8uDD4T
    * Gleb Golov

* Chinese (Traditional)

    * Lafudoci

* Catalan

    * Joan Montané

* Persian

    * Nima Ghotbi

* Esperanto

    * Gilberto F da Silva

* Russian

    * Russian Bear
    * Agent LvM
    * v1docq47

* Japanese

    * Scott Anecito
    * x52fws
    * Lana

* Portuguese (Portugal)

    * Demofrager
    * Ian appel
    * EvolBit

* French

    * Bertrand Jacquin
    * lir4376
    * Loué Marie
    * el00ruobuob

* Czech

    * Michal Vašíček
    * dskch83

* Polish

    * ambercookie

* Greek

    * warraxxx
    * Georgios Apostolopoulos
    * ΚΥΡΙΑΚΟΣ ΚΑΡΑΚΥΡΙΟΣ
    * Marinus Savoritias
    * Iason Andreou
    * Donald A. Iljazi

* Lithuanian

    * Vytas
    * Aivaras Kasperaitis

* Portuguese (Brazil)

    * Renato MB
    * netrik182
    * Mathkamy

* Norwegian Bokmål

    * Allan Nordhøy

* Dutch

    * obit33
    * Edwin den Boer
    * dutchcodes

* Hebrew

    * Ori Levenglick
    * Yan Abu Arab

* German

    * G. Orwell
    * mr
    * Paul Janowitz
    * Nicolas
    * GreenPiece
    * SJ
    * Deleted User
    * Wobole

Signed-off-by: erciccione <erciccione@protonmail.com>
2021-03-03 16:47:09 +01:00
xiphon
92a2ae1a11 TxConfirmationDialog: implement multiple recipients support, layout fixes 2021-03-03 00:53:51 +00:00
Ben Evanoff
40adc6bbbf use preferred colors for DaemonManagerDialog 2021-03-02 14:49:49 -06:00
luigi1111
c073867657 Merge pull request #3331
e25e44b AddressBook: don't alter tx Description on recipient selection (xiphon)
2021-02-18 15:03:27 -05:00
luigi1111
a7f5b44488 Merge pull request #3329
3c27c57 CheckBox: change opacity to 70% in disabled state (xiphon)
2021-02-18 15:02:07 -05:00
luigi1111
8b8948954d Merge pull request #3327
b20b956 Wallet: estimateTransactionFeeAsync - multi dest support (xiphon)
2021-02-18 15:01:14 -05:00
luigi1111
2c763f5014 Merge pull request #3323
f40b10e workflows: add py7zr to macos bundle (selsta)
2021-02-18 14:58:50 -05:00
luigi1111
5d566d1c02 Merge pull request #3321
38f21a3 installers/windows: fix typo in readme.htm (secure-designer)
2021-02-18 14:58:24 -05:00
luigi1111
41520b3a71 Merge pull request #3317
c948c9d README: Update the homebrew install instructions (toh995)
2021-02-18 14:57:31 -05:00
luigi1111
5039de8327 Merge pull request #3315
04d5fa5 Wallet: refactor createTransaction (xiphon)
2021-02-18 14:55:10 -05:00
xiphon
2bb1092472 LineEditMulti: right padding, fontFamily, backtab, inline btns vcenter 2021-02-08 20:30:05 +00:00
xiphon
16fd2b4447 LineEdit: fontFamily and inputPadding properties, fix backtab 2021-02-08 20:29:28 +00:00
xiphon
3c27c570d4 CheckBox: change opacity to 70% in disabled state 2021-02-05 15:32:04 +00:00
xiphon
e25e44b45f AddressBook: don't alter tx Description on recipient selection 2021-02-05 15:28:38 +00:00
xiphon
b20b956e15 Wallet: estimateTransactionFeeAsync - multi dest support 2021-02-04 11:32:30 +00:00
xiphon
4f10683c2c OSHelper: Linux - fix isCapsLock memory leak 2021-02-03 10:41:33 +00:00
selsta
f40b10ea0b workflows: add py7zr to macos bundle 2021-02-02 00:58:19 +01:00
secure-designer
38f21a3e89 installers/windows: fix typo in readme.htm 2021-01-30 20:03:55 +00:00
luigi1111
1f0f21a8e5 Merge pull request #3314
9cf7c7f DaemonManager: enable dns block list in simple mode (selsta)
2021-01-29 00:33:07 -05:00
toh995
c948c9dd7c README: Update the homebrew install instructions 2021-01-27 00:32:49 -08:00
xiphon
04d5fa51cf Wallet: refactor createTransaction 2021-01-25 11:57:49 +00:00
luigi1111
c1573c2c2a Merge pull request #3308
5848aee Navbar: cleanup layout (xiphon)
2021-01-22 15:09:07 -05:00
luigi1111
42fba21c6b Merge pull request #3306
83bb7a9 Makefile: support USE_SINGLE_BUILDDIR=OFF without git installed (xiphon)
2021-01-22 15:08:20 -05:00
luigi1111
04e3ac9200 Merge pull request #3305
d3102b1 DaemonManager: refactoring - drop singleton usage (xiphon)
2021-01-22 15:07:39 -05:00
luigi1111
f9f319d571 Merge pull request #3302
55baa8b main: restrict max window width/height, fix initial window alignment (xiphon)
2021-01-22 15:07:00 -05:00
luigi1111
090dca7848 Merge pull request #3301
18f16d9 SettingsLayout: 'Display wallet name in title bar' option (xiphon)
2021-01-22 15:05:58 -05:00
selsta
9cf7c7f03c DaemonManager: enable dns block list in simple mode
Co-authored-by: xiphon <xiphon@protonmail.com>
2021-01-22 20:50:51 +01:00
luigi1111
d3d26e37d0 Merge pull request #3309
a25b164 SettingsLog: disable daemon command input in Remote Node mode (xiphon)
2021-01-21 23:41:50 -05:00
luigi1111
b79f1b8ff4 Merge pull request #3307
a214003 README: Windows docker builds are reproducible since v0.17.1.9 (xiphon)
2021-01-21 23:40:17 -05:00
luigi1111
2a44f95f16 Merge pull request #3311
45b5150 Utils: fix removeTrailingZeros regression (xiphon)
2021-01-20 22:43:27 -05:00
luigi1111
dc0ce27963 Merge pull request #3310
bd21914 README: MacOS - add libsodium monero dependency (xiphon)
2021-01-20 22:42:54 -05:00
luigi1111
378da8093d Merge pull request #3304
93b2231 Subaddress: log account subaddresses refresh error (xiphon)
2021-01-20 22:42:01 -05:00
luigi1111
5261f79e9f Merge pull request #3298
f3a24d9 main: fix kraken fiat api (selsta)
2021-01-20 22:41:21 -05:00
luigi1111
1659c7fd1a Merge pull request #3295
07a9b0e workflows: print sha256sum of windows gui (selsta)
2021-01-20 22:40:50 -05:00
luigi1111
ec7bc577d6 Merge pull request #3292
e9b894d Transfer: implement 'Grab QR code from screen' functionality (xiphon)
2021-01-20 22:40:14 -05:00
luigi1111
3f4de99be4 Merge pull request #3289
7c32fe6 remove copy qr uri to clipboard button (Ben Evanoff)
2021-01-20 22:39:43 -05:00
luigi1111
1a11f2b192 Merge pull request #3215
cedfa5a History: search by receiving address, receiving address label, address book label (rating89us)
2021-01-20 22:39:03 -05:00
luigi1111
e21d7be725 Merge pull request #3168
baa0ffa WizardRestoreWallet1: add view-only option in placeholder of private spend key (rating89us)
2021-01-20 22:38:24 -05:00
luigi1111
4098352faf Merge pull request #3164
1373e70 account/receive: highlight background and text of selected item (rating89us)
2021-01-20 22:37:24 -05:00
xiphon
a25b164cd5 SettingsLog: disable daemon command input in Remote Node mode 2021-01-19 09:42:14 +00:00
xiphon
45b5150487 Utils: fix removeTrailingZeros regression 2021-01-16 03:31:23 +00:00
xiphon
bd21914b9b README: MacOS - add libsodium monero dependency 2021-01-15 11:34:04 +00:00
xiphon
5848aee1c3 Navbar: cleanup layout 2021-01-15 10:09:44 +00:00
xiphon
a214003559 README: Windows docker builds are reproducible since v0.17.1.9 2021-01-15 00:01:34 +00:00
xiphon
83bb7a9297 Makefile: support USE_SINGLE_BUILDDIR=OFF without git installed
# Conflicts:
#	Makefile
2021-01-14 23:21:33 +00:00
xiphon
d3102b1cc5 DaemonManager: refactoring - drop singleton usage 2021-01-14 19:14:22 +00:00
xiphon
93b22311e3 Subaddress: log account subaddresses refresh error 2021-01-14 08:19:13 +00:00
xiphon
55baa8b695 main: restrict max window width/height, fix initial window alignment 2021-01-13 03:14:57 +00:00
xiphon
18f16d9ebd SettingsLayout: 'Display wallet name in title bar' option 2021-01-12 12:59:28 +00:00
xiphon
e9b894da16 Transfer: implement 'Grab QR code from screen' functionality 2021-01-11 01:35:54 +00:00
selsta
f3a24d92a4 main: fix kraken fiat api 2021-01-11 00:29:48 +01:00
selsta
07a9b0e6f7 workflows: print sha256sum of windows gui 2021-01-08 05:33:01 +01:00
Alexander Blair
3ca5f10fa8 Merge pull request #3294
f7b81797 build: prepare v0.17.1.9 (selsta)
2021-01-07 18:00:05 -08:00
selsta
f7b817972f build: prepare v0.17.1.9 2021-01-08 02:56:28 +01:00
Alexander Blair
9399839d96 Merge pull request #3287
72ab846b installer: remove high dpi shortcut (selsta)
2021-01-03 18:46:20 -08:00
Alexander Blair
51a4d1f629 Merge pull request #3283
5662841d docker: Windows - use Qt 5.15.2 (xiphon)
2021-01-03 18:45:48 -08:00
Alexander Blair
bbe3716542 Merge pull request #3277
8d4cda03 QR-Code-scanner: integrate QUIRC library, implement QrDecoder, drop ZBar (xiphon)
2021-01-03 18:45:26 -08:00
Ben Evanoff
7c32fe6b5c remove copy qr uri to clipboard button 2021-01-02 14:34:59 -06:00
selsta
72ab846be5 installer: remove high dpi shortcut
Qt 5.15 supports high DPI natively
2021-01-01 05:13:36 +01:00
Alexander Blair
8e6a2cde0f Merge pull request #3285
c34d4ee9 build: prepare v0.17.1.8 (selsta)
2020-12-30 01:53:31 -08:00
selsta
c34d4ee97c build: prepare v0.17.1.8 2020-12-30 10:37:36 +01:00
Alexander Blair
0194cf8f22 Merge pull request #3280
ba4d6993 LineEdit: fix padding, fix inline buttons layout, multiple btns support (xiphon)
2020-12-28 11:41:47 -08:00
Alexander Blair
ad06fcc79e Merge pull request #3271
78f5360a Transfer: support pasting amount with whitespaces (xiphon)
2020-12-28 11:41:38 -08:00
Alexander Blair
7d4b82c691 Merge pull request #3270
a1fdffca WizardRestoreWallet1: fix mnemonic seed placeholder (xiphon)
2020-12-28 11:41:15 -08:00
Alexander Blair
69f989d617 Merge pull request #3281
3f0bbfb6 Transfer: updateFromQrCode - fix extra space (empty recipient name) (xiphon)
2020-12-26 13:47:31 -08:00
Alexander Blair
0f3df860e3 Merge pull request #3275
772b828b cmake: MacOS - detect ICU link directory (required by Boost.Locale) (xiphon)
2020-12-26 13:45:24 -08:00
xiphon
5662841d22 docker: Windows - use Qt 5.15.2 2020-12-26 08:37:45 +00:00
xiphon
3f0bbfb6aa Transfer: updateFromQrCode - fix extra space (empty recipient name) 2020-12-24 10:07:08 +00:00
xiphon
ba4d6993b7 LineEdit: fix padding, fix inline buttons layout, multiple btns support 2020-12-24 08:20:38 +00:00
xiphon
8d4cda030e QR-Code-scanner: integrate QUIRC library, implement QrDecoder, drop ZBar 2020-12-23 15:08:42 +00:00
xiphon
772b828b67 cmake: MacOS - detect ICU link directory (required by Boost.Locale) 2020-12-20 20:00:23 +00:00
xiphon
78f5360af2 Transfer: support pasting amount with whitespaces 2020-12-14 11:59:45 +00:00
xiphon
a1fdffcabe WizardRestoreWallet1: fix mnemonic seed placeholder 2020-12-13 11:31:14 +00:00
luigi1111
fed00a5662 Merge pull request #3269
14a4777 build: prepare v0.17.1.7 (selsta)
2020-12-12 22:16:13 -06:00
luigi1111
79f2843b09 Merge pull request #3268
cebb789 Wallet: fix initialization flag handling (xiphon)
2020-12-12 22:15:10 -06:00
selsta
14a477748e build: prepare v0.17.1.7 2020-12-13 05:11:20 +01:00
xiphon
cebb78979c Wallet: fix initialization flag handling 2020-12-12 11:22:52 +00:00
Alexander Blair
df771470c2 Merge pull request #3267
90e9968d main: get back "Sending transaction ..." splash (xiphon)
2020-12-10 18:02:11 -08:00
Alexander Blair
e359c60f00 Merge pull request #3266
841d0e01 Utils: removeTrailingZeros - handle .0* decimal part (i.e. 1.00000) (xiphon)
2020-12-10 18:01:38 -08:00
Alexander Blair
53335a8487 Merge pull request #3264
2feee9e9 workflows: shorten name (selsta)
2020-12-10 18:01:19 -08:00
Alexander Blair
3f64312283 Merge pull request #3262
486ba055 main: disable QML cache (xiphon)
2020-12-10 17:59:09 -08:00
Alexander Blair
897946af13 Merge pull request #3260
ae8394e5 main: Linux - fix missing askDesktopShortcut setting (xiphon)
2020-12-10 17:58:42 -08:00
Alexander Blair
e90626e05a Merge pull request #3259
fa79e609 workflows: bump docker cache action (selsta)
2020-12-10 17:58:06 -08:00
xiphon
90e9968dcb main: get back "Sending transaction ..." splash 2020-12-10 23:59:12 +00:00
xiphon
841d0e01dc Utils: removeTrailingZeros - handle .0* decimal part (i.e. 1.00000) 2020-12-10 23:00:39 +00:00
selsta
2feee9e956 workflows: shorten name 2020-12-10 04:01:43 +01:00
xiphon
486ba05526 main: disable QML cache 2020-12-09 14:29:02 +00:00
xiphon
ae8394e5f8 main: Linux - fix missing askDesktopShortcut setting 2020-12-08 01:02:00 +00:00
selsta
fa79e609e1 workflows: bump docker cache action 2020-12-07 19:22:37 +01:00
luigi1111
cc352e4913 Merge pull request #3258
903539b build: prepare v0.17.1.6 (selsta)
2020-12-07 10:37:31 -06:00
selsta
903539bd30 build: prepare v0.17.1.6 2020-12-07 17:34:40 +01:00
Alexander Blair
af0b3142a0 Merge pull request #3255
606dbed4 README: update Linux Docker build instructions (xiphon)
2020-12-03 12:24:50 -08:00
Alexander Blair
6fe41e6f55 Merge pull request #3254
0d5d2dbf Transfer: fix focus, cycle focus between Address, Amount and Send (xiphon)
2020-12-03 12:24:22 -08:00
Alexander Blair
2a6ad67f77 Merge pull request #3253
110b09ef TxConfirmationDialog: fix keys handling (xiphon)
2020-12-03 12:23:58 -08:00
Alexander Blair
5652284572 Merge pull request #3252
0fdf81bc SuccessfulTxDialog: fix keys handling (xiphon)
2020-12-03 12:23:24 -08:00
Alexander Blair
2eeeadfd10 Merge pull request #3251
ea1fee2f main: Linux - ask to create desktop entry on the first start (xiphon)
2020-12-03 12:23:02 -08:00
xiphon
0d5d2dbf5e Transfer: fix focus, cycle focus between Address, Amount and Send 2020-12-03 19:40:15 +00:00
xiphon
606dbed4a0 README: update Linux Docker build instructions 2020-12-03 00:55:29 +00:00
Alexander Blair
301b20d19c Merge pull request #3249
ef54a32d workflows: print hash for reproducible builds (selsta)
2020-12-01 14:25:22 -08:00
Alexander Blair
f6196d48ab Merge pull request #3169
cd3a0f85 Restore: display red border if invalid seed (rating89us)
2020-12-01 14:25:01 -08:00
xiphon
110b09efba TxConfirmationDialog: fix keys handling 2020-12-01 16:25:35 +00:00
xiphon
0fdf81bc92 SuccessfulTxDialog: fix keys handling 2020-12-01 16:19:56 +00:00
xiphon
ea1fee2f5f main: Linux - ask to create desktop entry on the first start 2020-11-30 15:36:19 +00:00
selsta
ef54a32de0 workflows: print hash for reproducible builds 2020-11-26 10:34:19 +01:00
luigi1111
96f9c11320 Merge pull request #3248
2e81ea2 build: prepare v0.17.1.5 (selsta)
2020-11-25 17:24:18 -06:00
luigi1111
4a5b191f7f Merge pull request #3247
5150945 workflows: upload source archive artifact (xiphon)
2020-11-25 17:23:24 -06:00
luigi1111
148d487988 Merge pull request #3245
ec8cd13 portable: use portable storage folder to store QML disk cache (xiphon)
2020-11-25 17:22:38 -06:00
luigi1111
7b137f7682 Merge pull request #3097
56722e4 AddressBook: fix Qt warning (selsta)
2020-11-25 17:21:41 -06:00
selsta
2e81ea2c09 build: prepare v0.17.1.5 2020-11-25 16:36:37 +01:00
xiphon
5150945414 workflows: upload source archive artifact 2020-11-25 13:27:59 +00:00
xiphon
ec8cd137cc portable: use portable storage folder to store QML disk cache 2020-11-25 10:50:56 +00:00
Alexander Blair
d5365298d2 Merge pull request #3244
2d20bfd7 cmake: find libgcrypt include directory (xiphon)
2020-11-24 11:36:29 -08:00
Alexander Blair
30bf63b4b8 Merge pull request #3237
46cea8db History: fix sortCollapsedIcon rotation (xiphon)
2020-11-24 11:36:05 -08:00
Alexander Blair
e8ee55a502 Merge pull request #3236
b4c0cb65 Makefile: refactor USE_SINGLE_BUILDDIR=OFF builddir path (xiphon)
2020-11-24 11:35:45 -08:00
Alexander Blair
212fa083e2 Merge pull request #3231
56e61148 wizard: move language related settings to PersistentSettings (xiphon)
2020-11-24 11:35:24 -08:00
Alexander Blair
3daf16e65d Merge pull request #3229
45bfcfd2 workflows: build and upload macOS bundle (selsta)
2020-11-24 11:35:05 -08:00
Alexander Blair
abfaac9772 Merge pull request #3227
ff201af7 docker: Linux - use Qt 5.15.2 (xiphon)
2020-11-24 11:34:39 -08:00
Alexander Blair
28e6558a48 Merge pull request #3224
ef2be82c cmake: use QT_INSTALL_PREFIX instead of CMAKE_PREFIX_PATH (xiphon)
2020-11-24 11:34:15 -08:00
xiphon
2d20bfd7ac cmake: find libgcrypt include directory 2020-11-24 15:41:41 +00:00
selsta
45bfcfd2e9 workflows: build and upload macOS bundle 2020-11-24 01:00:26 +01:00
xiphon
46cea8db6b History: fix sortCollapsedIcon rotation 2020-11-15 02:50:18 +00:00
xiphon
b4c0cb65de Makefile: refactor USE_SINGLE_BUILDDIR=OFF builddir path 2020-11-15 02:45:28 +00:00
xiphon
56e611480a wizard: move language related settings to PersistentSettings 2020-11-12 22:47:07 +00:00
xiphon
ff201af778 docker: Linux - use Qt 5.15.2 2020-11-12 13:51:36 +00:00
xiphon
ef2be82c21 cmake: use QT_INSTALL_PREFIX instead of CMAKE_PREFIX_PATH 2020-11-10 02:00:07 +00:00
luigi1111
6fce5c7a84 Merge pull request #3223
1571662 build: prepare v0.17.1.4 (selsta)
2020-11-09 11:52:44 -06:00
selsta
157166269b build: prepare v0.17.1.4 2020-11-09 18:41:19 +01:00
luigi1111
caa273afea Merge pull request #3221
19a6f39 Revert 'docker: Linux - use Qt 5.15.2' (selsta)
2020-11-09 11:35:15 -06:00
luigi1111
d58ce3f599 Merge pull request #3217
18c964a docker: Android - use Qt 5.15.2, drop QT_PREFIX env variable (xiphon)
2020-11-09 11:32:46 -06:00
selsta
19a6f399f3 Revert "docker: Linux - use Qt 5.15.2"
This reverts commit 1adf58793f.
2020-11-09 15:37:46 +01:00
xiphon
18c964afca docker: Android - use Qt 5.15.2, drop QT_PREFIX env variable 2020-11-07 23:05:26 +00:00
luigi1111
158e0c3523 Merge pull request #3214
f3ddf52 build: prepare v0.17.1.3 (selsta)
2020-11-07 13:19:54 -06:00
luigi1111
770a7a344b Merge pull request #3204
e86fa3e cmake: workaround for MacOS '-framework' pkg-config flags issue (xiphon)
2020-11-07 13:17:21 -06:00
selsta
f3ddf525a4 build: prepare v0.17.1.3 2020-11-07 20:11:59 +01:00
rating89us
cedfa5aabb History: search by receiving address, receiving address label, address book label 2020-11-07 20:04:12 +01:00
luigi1111
df2b85e7ee Merge pull request #3200
5702bde workflows: upload Windows and Linux static binaries (xiphon)
2020-11-06 19:10:01 -06:00
xiphon
e86fa3e4fb cmake: workaround for MacOS '-framework' pkg-config flags issue 2020-11-06 13:51:02 +00:00
xiphon
5702bdef39 workflows: upload Windows and Linux static binaries 2020-11-06 13:48:08 +00:00
Alexander Blair
c7213abb9a Merge pull request #3212
be177d62 workflows: bump msys2 action to v2 (selsta)
2020-11-06 05:11:53 -08:00
Alexander Blair
5ee363f9f3 Merge pull request #3210
919b2e4f WizardLanguage: introduce LanguageButton component, replace the btn (xiphon)
8b9580d6 WizardHome: display icon + language instead of change language button (xiphon)
2020-11-06 05:11:29 -08:00
Alexander Blair
3e01647744 Merge pull request #3209
6f5bacab Logger: print to stdout till log file path gets initialized (xiphon)
2020-11-06 05:11:09 -08:00
Alexander Blair
f491b41100 Merge pull request #3205
6fab741f SettingsInfo: add selected node to info page (selsta)
2020-11-06 05:10:52 -08:00
Alexander Blair
a564abbe6b Merge pull request #3202
0997b38e SettingsWallet: fix warning (selsta)
2020-11-06 05:09:46 -08:00
Alexander Blair
149732af3a Merge pull request #3203
c2977ac4 DEPLOY: new hidapi release available (selsta)
2020-11-06 05:09:31 -08:00
Alexander Blair
2bb6da5f09 Merge pull request #3201
1adf5879 docker: Linux - use Qt 5.15.2 (xiphon)
2020-11-06 05:08:40 -08:00
Alexander Blair
11370c50eb Merge pull request #3199
d79f8e8b Makefile: MANUAL_SUBMODULES support (OFF by default) (xiphon)
2020-11-06 05:06:23 -08:00
Alexander Blair
0ae4677a25 Merge pull request #3198
a817bfba QThreadPool: adjust max threads count (4) (xiphon)
2020-11-06 05:06:10 -08:00
Alexander Blair
1c2879bda3 Merge pull request #3188
9fa597bb workflows: docker android apk build (xiphon)
2020-11-06 05:05:45 -08:00
selsta
0997b38e1e SettingsWallet: fix warning 2020-11-05 02:39:47 +01:00
selsta
be177d6205 workflows: bump msys2 action to v2 2020-11-05 00:32:16 +01:00
xiphon
919b2e4f3a WizardLanguage: introduce LanguageButton component, replace the btn 2020-11-04 03:10:02 +00:00
xiphon
8b9580d621 WizardHome: display icon + language instead of change language button
Co-authored-by: rating89us <45968869+rating89us@users.noreply.github.com>
2020-11-04 02:10:37 +00:00
xiphon
6f5bacabfd Logger: print to stdout till log file path gets initialized 2020-11-04 01:42:19 +00:00
selsta
6fab741f2e SettingsInfo: add selected node to info page 2020-11-02 01:26:40 +01:00
selsta
c2977ac410 DEPLOY: new hidapi release available 2020-11-01 00:25:08 +01:00
xiphon
1adf58793f docker: Linux - use Qt 5.15.2 2020-10-30 22:20:35 +00:00
xiphon
9fa597bb58 workflows: docker android apk build 2020-10-30 22:16:20 +00:00
xiphon
d79f8e8b17 Makefile: MANUAL_SUBMODULES support (OFF by default) 2020-10-30 03:05:06 +00:00
xiphon
a817bfba05 QThreadPool: adjust max threads count (4) 2020-10-30 02:58:38 +00:00
Alexander Blair
04429e85e6 Merge pull request #3159
9d2f083a repo: cleanup qmake (selsta)
2020-10-28 01:22:38 -07:00
Alexander Blair
e52d86d442 Merge pull request #3195
153154f4 cmake: Linux - Qt 5.15 installer support (xiphon)
2020-10-28 00:44:03 -07:00
Alexander Blair
7f164e739a Merge pull request #3194
9b18344d main: don't override user-provided QT_QPA_PLATFORM env variable (xiphon)
2020-10-28 00:43:43 -07:00
Alexander Blair
43214de7d0 Merge pull request #3193
ee013705 cmake: omit Qt5Widgets and Qt5Network modules (xiphon)
2020-10-28 00:43:18 -07:00
Alexander Blair
0cf683a6cf Merge pull request #3192
1b0f274a docker: Linux - CFLAGS and CXXFLAGS env variables (xiphon)
2020-10-28 00:42:59 -07:00
Alexander Blair
c9fd9634ee Merge pull request #3187
cd054f6c docker: fix Android build, update to Qt 5.15, README.md build steps (xiphon)
d6cb9b6c docker: move Android Dockerfile to root (xiphon)
2020-10-28 00:42:36 -07:00
Alexander Blair
ddcee95b88 Merge pull request #3186
fe730114 cmake: Android cross compilation support (xiphon)
2020-10-28 00:42:16 -07:00
Alexander Blair
299067a273 Merge pull request #3185
852378ac cmake: ZBar - Android support, fix find_package without pkg-config (xiphon)
2020-10-28 00:40:22 -07:00
Alexander Blair
08635e3030 Merge pull request #3163
25ca0811 transfer: new TxConfirmationDialog (rating89us)
2020-10-28 00:39:43 -07:00
Alexander Blair
fdff5f68dd Merge pull request #3160
9da52f23 SettingsWallet: disable creating view-only wallet for Ledger (rating89us)
2020-10-28 00:37:30 -07:00
xiphon
9b18344d23 main: don't override user-provided QT_QPA_PLATFORM env variable 2020-10-28 00:57:30 +00:00
xiphon
153154f484 cmake: Linux - Qt 5.15 installer support 2020-10-28 00:55:06 +00:00
xiphon
ee0137056d cmake: omit Qt5Widgets and Qt5Network modules 2020-10-28 00:44:58 +00:00
xiphon
1b0f274aed docker: Linux - CFLAGS and CXXFLAGS env variables 2020-10-27 10:59:41 +00:00
xiphon
cd054f6c26 docker: fix Android build, update to Qt 5.15, README.md build steps
Co-authored-by: takel
2020-10-26 11:24:45 +00:00
xiphon
d6cb9b6c85 docker: move Android Dockerfile to root 2020-10-22 04:13:19 +00:00
xiphon
852378accb cmake: ZBar - Android support, fix find_package without pkg-config 2020-10-21 20:48:38 +00:00
xiphon
fe73011422 cmake: Android cross compilation support 2020-10-21 20:29:17 +00:00
selsta
9d2f083a97 repo: cleanup qmake 2020-10-20 02:01:44 +02:00
rating89us
cd3a0f85a6 Restore: display red border if invalid seed 2020-10-18 17:06:34 +02:00
rating89us
1373e709d6 account/receive: highlight background and text of selected item 2020-10-17 20:19:50 +02:00
rating89us
baa0ffa5f9 WizardRestoreWallet1: add view-only option in placeholder of private spend key 2020-10-17 17:53:52 +02:00
rating89us
25ca081109 transfer: new TxConfirmationDialog 2020-10-17 12:11:13 +02:00
rating89us
9da52f2387 SettingsWallet: disable creating view-only wallet for Ledger 2020-10-17 03:10:33 +02:00
selsta
56722e4747 AddressBook: fix Qt warning 2020-09-21 00:47:32 +02:00
146 changed files with 33841 additions and 24449 deletions

View File

@@ -1,4 +1,4 @@
name: continuous-integration/gh-actions/gui
name: ci/gh-actions/gui
on: [push, pull_request]
@@ -10,7 +10,7 @@ jobs:
with:
submodules: recursive
- name: install dependencies
run: HOMEBREW_NO_AUTO_UPDATE=1 brew install boost hidapi zmq libpgm miniupnpc ldns expat libunwind-headers protobuf qt5 pkg-config
run: HOMEBREW_NO_AUTO_UPDATE=1 brew install boost hidapi zmq libpgm libsodium miniupnpc ldns expat libunwind-headers protobuf qt5 pkg-config
- name: build
run: DEV_MODE=ON make release -j3
- name: test qml
@@ -34,7 +34,7 @@ jobs:
- name: install monero dependencies
run: sudo apt -y install build-essential cmake libboost-all-dev miniupnpc libunbound-dev graphviz doxygen libunwind8-dev pkg-config libssl-dev libzmq3-dev libsodium-dev libhidapi-dev libnorm-dev libusb-1.0-0-dev libpgm-dev libprotobuf-dev protobuf-compiler
- name: install monero gui dependencies
run: sudo apt -y install qtbase5-dev qt5-default qtdeclarative5-dev qml-module-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 libgcrypt20-dev xvfb
run: sudo apt -y install qtbase5-dev qt5-default qtdeclarative5-dev qml-module-qtqml-models2 qml-module-qtquick-controls qml-module-qtquick-controls2 qml-module-qtquick-dialogs qml-module-qtquick-xmllistmodel qml-module-qt-labs-settings qml-module-qt-labs-folderlistmodel qttools5-dev-tools qml-module-qtquick-templates2 libqt5svg5-dev libgcrypt20-dev xvfb
- name: build
run: DEV_MODE=ON make release -j3
- name: test qml
@@ -49,7 +49,7 @@ jobs:
- uses: actions/checkout@v1
with:
submodules: recursive
- uses: eine/setup-msys2@v1
- uses: eine/setup-msys2@v2
with:
update: true
install: mingw-w64-x86_64-toolchain make mingw-w64-x86_64-cmake mingw-w64-x86_64-boost mingw-w64-x86_64-openssl mingw-w64-x86_64-zeromq mingw-w64-x86_64-libsodium mingw-w64-x86_64-hidapi mingw-w64-x86_64-protobuf-c mingw-w64-x86_64-libusb git mingw-w64-x86_64-qt5 mingw-w64-x86_64-libgcrypt
@@ -58,22 +58,65 @@ jobs:
- name: test qml
run: build/release/bin/monero-wallet-gui --test-qml
macos-bundle:
runs-on: macOS-latest
steps:
- uses: actions/checkout@v1
with:
submodules: recursive
- name: install dependencies
run: HOMEBREW_NO_AUTO_UPDATE=1 brew install boost hidapi zmq libpgm miniupnpc ldns expat libunwind-headers protobuf pkg-config python3 p7zip
- name: install dependencies
run: pip3 install requests semantic_version lxml py7zr
- name: download qt
run: |
curl -O https://raw.githubusercontent.com/engnr/qt-downloader/master/qt-downloader
chmod +x qt-downloader
./qt-downloader macos desktop 5.15.2 clang_64
working-directory: ../
- name: build
run: CMAKE_PREFIX_PATH=/Users/runner/work/monero-gui/5.15.2/clang_64 make release -j3
- name: deploy
run: make deploy
working-directory: build/release
- name: test qml
run: build/release/bin/monero-wallet-gui.app/Contents/MacOS/monero-wallet-gui --test-qml
- name: create .tar
run: tar -cf monero-wallet-gui.tar monero-wallet-gui.app
working-directory: build/release/bin
- uses: actions/upload-artifact@v2
with:
name: ${{ github.job }}
path: build/release/bin/monero-wallet-gui.tar
docker-linux-static:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v1
with:
submodules: recursive
- uses: satackey/action-docker-layer-caching@v0.0.8
- uses: satackey/action-docker-layer-caching@v0.0.10
continue-on-error: true
with:
key: docker-linux-static-{hash}
restore-keys: |
docker-linux-static-
- name: install dependencies
run: sudo apt -y install xvfb libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-randr0 libxcb-render-util0 libxcb-xkb1 libxkbcommon-x11-0
- name: preprare build enviroment
run: docker build --tag monero:build-env-linux --build-arg THREADS=3 --file Dockerfile.linux .
- name: build
run: docker run --rm -v /home/runner/work/monero-gui/monero-gui:/monero-gui -w /monero-gui monero:build-env-linux sh -c 'make release-static -j3'
- name: sha256sum
run: shasum -a256 /home/runner/work/monero-gui/monero-gui/build/release/bin/monero-wallet-gui
- name: test qml
run: xvfb-run -a /home/runner/work/monero-gui/monero-gui/build/release/bin/monero-wallet-gui --test-qml
- uses: actions/upload-artifact@v2
with:
name: ${{ github.job }}
path: |
/home/runner/work/monero-gui/monero-gui/build/release/bin/monero-wallet-gui
/home/runner/work/monero-gui/monero-gui/build/release/bin/monerod
docker-windows-static:
runs-on: ubuntu-20.04
@@ -81,7 +124,7 @@ jobs:
- uses: actions/checkout@v1
with:
submodules: recursive
- uses: satackey/action-docker-layer-caching@v0.0.8
- uses: satackey/action-docker-layer-caching@v0.0.10
continue-on-error: true
with:
key: docker-windows-static-{hash}
@@ -91,3 +134,44 @@ jobs:
run: docker build --tag monero:build-env-windows --build-arg THREADS=3 --file Dockerfile.windows .
- name: build
run: docker run --rm -v /home/runner/work/monero-gui/monero-gui:/monero-gui -w /monero-gui monero:build-env-windows sh -c 'make depends root=/depends target=x86_64-w64-mingw32 tag=win-x64 -j3'
- name: sha256sum
run: shasum -a256 /home/runner/work/monero-gui/monero-gui/build/x86_64-w64-mingw32/release/bin/monero-wallet-gui.exe
- uses: actions/upload-artifact@v2
with:
name: ${{ github.job }}
path: |
/home/runner/work/monero-gui/monero-gui/build/x86_64-w64-mingw32/release/bin/monero-wallet-gui.exe
/home/runner/work/monero-gui/monero-gui/build/x86_64-w64-mingw32/release/bin/monerod.exe
docker-android:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v1
with:
submodules: recursive
- name: preprare build enviroment
run: docker build --tag monero:build-env-android --build-arg THREADS=3 --file Dockerfile.android .
- name: build
run: docker run --rm -v /home/runner/work/monero-gui/monero-gui:/monero-gui -e THREADS=3 monero:build-env-android
- uses: actions/upload-artifact@v2
with:
name: ${{ github.job }}
path: /home/runner/work/monero-gui/monero-gui/build/Android/release/android-build/monero-gui.apk
source-archive:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v1
with:
submodules: recursive
- name: archive
run: |
pip install git-archive-all
export VERSION="monero-gui-$(git describe)"
export OUTPUT="$VERSION.tar"
echo "OUTPUT=$OUTPUT" >> $GITHUB_ENV
/home/runner/.local/bin/git-archive-all --prefix "$VERSION/" --force-submodules "$OUTPUT"
- uses: actions/upload-artifact@v2
with:
name: ${{ env.OUTPUT }}
path: /home/runner/work/monero-gui/monero-gui/${{ env.OUTPUT }}

3
.gitmodules vendored
View File

@@ -2,3 +2,6 @@
path = monero
url = https://github.com/monero-project/monero
ignore = all
[submodule "external/quirc"]
path = external/quirc
url = https://github.com/dlbeer/quirc/

View File

@@ -1,10 +1,10 @@
cmake_minimum_required(VERSION 3.5)
cmake_minimum_required(VERSION 3.12)
project(monero-gui)
message(STATUS "Initiating compile using CMake ${CMAKE_VERSION}")
set(VERSION_MAJOR "17")
set(VERSION_MINOR "1")
set(VERSION_MINOR "2")
set(VERSION_REVISION "1")
set(VERSION "0.${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_REVISION}")
@@ -48,8 +48,9 @@ if(NOT MANUAL_SUBMODULES)
else()
execute_process(COMMAND ${GIT_EXECUTABLE} fetch WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/monero RESULT_VARIABLE GIT_FETCH_RESULT)
execute_process(COMMAND ${GIT_EXECUTABLE} checkout -f origin/master WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/monero RESULT_VARIABLE GIT_CHECKOUT_MASTER_RESULT)
execute_process(COMMAND ${GIT_EXECUTABLE} submodule sync --recursive WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/monero RESULT_VARIABLE GIT_SUBMODULE_SYNC_RESULT)
execute_process(COMMAND ${GIT_EXECUTABLE} submodule update --init --force --recursive WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/monero RESULT_VARIABLE GIT_SUBMODULE_UPDATE_RESULT)
if(NOT GIT_FETCH_RESULT EQUAL "0" OR NOT GIT_CHECKOUT_MASTER_RESULT EQUAL "0" OR NOT GIT_SUBMODULE_UPDATE_RESULT EQUAL "0")
if(NOT GIT_FETCH_RESULT EQUAL "0" OR NOT GIT_CHECKOUT_MASTER_RESULT EQUAL "0" OR NOT GIT_SUBMODULE_SYNC_RESULT EQUAL "0" OR NOT GIT_SUBMODULE_UPDATE_RESULT EQUAL "0")
message(FATAL_ERROR "Updating git submodule to master (-DDEV_MODE=ON) failed")
endif()
endif()
@@ -76,7 +77,7 @@ if(STATIC)
message(STATUS "Initiating static build")
set(Boost_USE_STATIC_LIBS ON)
set(Boost_USE_STATIC_RUNTIME ON)
set(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
set(CMAKE_FIND_LIBRARY_SUFFIXES ".a" ${CMAKE_FIND_LIBRARY_SUFFIXES})
add_definitions(-DMONERO_GUI_STATIC)
endif()
@@ -131,12 +132,8 @@ message(STATUS "OpenSSL: Version ${OPENSSL_VERSION}")
message(STATUS "OpenSSL: include dir at ${OPENSSL_INCLUDE_DIR}")
message(STATUS "OpenSSL: libraries at ${OPENSSL_LIBRARIES} ${OPENSSL_SSL_LIBRARIES}")
# Zbar (for QR scanner)
if(WITH_SCANNER)
add_definitions(-DWITH_SCANNER)
find_package(ZBar0)
message(STATUS "libzbar: include dir at ${ZBAR_INCLUDE_DIR}")
message(STATUS "libzbar: libraries at ${ZBAR_LIBRARIES}")
endif()
# Sodium
@@ -149,9 +146,11 @@ message(STATUS "libusb: include dir at ${LibUSB_INCLUDE_DIRS}")
message(STATUS "libusb: libraries at ${LibUSB_LIBRARIES}")
# HIDApi
find_package(HIDAPI REQUIRED)
message(STATUS "libhidapi: include dir at ${HIDAPI_INCLUDE_DIRS}")
message(STATUS "libhidapi: libraries at ${HIDAPI_LIBRARIES}")
if(NOT ANDROID)
find_package(HIDAPI REQUIRED)
message(STATUS "libhidapi: include dir at ${HIDAPI_INCLUDE_DIRS}")
message(STATUS "libhidapi: libraries at ${HIDAPI_LIBRARIES}")
endif()
# Boost
if(DEBUG)
@@ -174,9 +173,12 @@ find_package(Boost 1.58 REQUIRED COMPONENTS
program_options
locale)
if(UNIX AND NOT APPLE)
if(UNIX AND NOT APPLE AND NOT ANDROID)
set(CMAKE_SKIP_RPATH ON)
set(CMAKE_FIND_LIBRARY_SUFFIXES_PREV ${CMAKE_FIND_LIBRARY_SUFFIXES})
set(CMAKE_FIND_LIBRARY_SUFFIXES ".so")
find_package(X11 REQUIRED)
set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES_PREV})
message(STATUS "X11_FOUND = ${X11_FOUND}")
message(STATUS "X11_INCLUDE_DIR = ${X11_INCLUDE_DIR}")
message(STATUS "X11_LIBRARIES = ${X11_LIBRARIES}")
@@ -204,9 +206,7 @@ endif()
set(QT5_LIBRARIES
Qt5Core
Qt5Quick
Qt5Widgets
Qt5Gui
Qt5Network
Qt5Qml
Qt5Svg
Qt5Xml
@@ -218,20 +218,17 @@ endif()
if(APPLE)
list(APPEND QT5_LIBRARIES Qt5MacExtras)
endif()
if(UNIX)
if(NOT CMAKE_PREFIX_PATH AND DEFINED ENV{CMAKE_PREFIX_PATH})
message(STATUS "Using CMAKE_PREFIX_PATH environment variable: '$ENV{CMAKE_PREFIX_PATH}'")
set(CMAKE_PREFIX_PATH $ENV{CMAKE_PREFIX_PATH})
endif()
if(NOT CMAKE_PREFIX_PATH)
if(APPLE AND NOT CMAKE_PREFIX_PATH)
execute_process(COMMAND brew --prefix qt5 OUTPUT_VARIABLE QT5_DIR OUTPUT_STRIP_TRAILING_WHITESPACE)
list(APPEND CMAKE_PREFIX_PATH ${QT5_DIR})
endif()
if(CMAKE_PREFIX_PATH)
include_directories(${CMAKE_PREFIX_PATH}/include)
set(CMAKE_BUILD_RPATH "${CMAKE_PREFIX_PATH}/lib")
endif()
endif()
find_package(PkgConfig REQUIRED)
@@ -253,7 +250,22 @@ foreach(QT5_MODULE ${QT5_LIBRARIES})
include_directories(${${QT5_MODULE}_INCLUDE_DIRS})
endforeach()
pkg_check_modules(QT5_PKG_CONFIG REQUIRED ${QT5_LIBRARIES})
if(NOT (CMAKE_CROSSCOMPILING AND ANDROID))
pkg_check_modules(QT5_PKG_CONFIG REQUIRED ${QT5_LIBRARIES})
else()
set(QT5_LIBRARIES_ABI)
foreach(QT5_MODULE ${QT5_LIBRARIES})
list(APPEND QT5_LIBRARIES_ABI "${QT5_MODULE}_${CMAKE_ANDROID_ARCH_ABI}")
endforeach()
pkg_check_modules(QT5_PKG_CONFIG REQUIRED ${QT5_LIBRARIES_ABI})
endif()
get_target_property(QMAKE_IMPORTED_LOCATION Qt5::qmake IMPORTED_LOCATION)
get_filename_component(QT_INSTALL_PREFIX "${QMAKE_IMPORTED_LOCATION}/../.." ABSOLUTE)
if(APPLE AND NOT STATIC)
set(CMAKE_BUILD_RPATH "${QT_INSTALL_PREFIX}/lib")
endif()
if(QT5_PKG_CONFIG_FOUND)
set(QT5_PKG_CONFIG "QT5_PKG_CONFIG")
@@ -261,15 +273,15 @@ if(QT5_PKG_CONFIG_FOUND)
set(QT5_PKG_CONFIG "${QT5_PKG_CONFIG}_STATIC")
endif()
if(APPLE)
list(JOIN ${QT5_PKG_CONFIG}_LDFLAGS_OTHER " " ${QT5_PKG_CONFIG}_LDFLAGS_OTHER)
list(JOIN ${QT5_PKG_CONFIG}_LIBRARIES " " ${QT5_PKG_CONFIG}_LIBRARIES)
list(JOIN ${QT5_PKG_CONFIG}_INCLUDE_DIRS " " ${QT5_PKG_CONFIG}_INCLUDE_DIRS)
if(UNIX AND CMAKE_PREFIX_PATH)
if(APPLE)
list(JOIN ${QT5_PKG_CONFIG}_LDFLAGS_OTHER " " ${QT5_PKG_CONFIG}_LDFLAGS_OTHER)
endif()
# temporal workaround for https://bugreports.qt.io/browse/QTBUG-80922
STRING(REPLACE "${QT5_PKG_CONFIG_Qt5Core_PREFIX}" "${CMAKE_PREFIX_PATH}" ${QT5_PKG_CONFIG}_LDFLAGS_OTHER "${${QT5_PKG_CONFIG}_LDFLAGS_OTHER}")
STRING(REPLACE "${QT5_PKG_CONFIG_Qt5Core_PREFIX}" "${CMAKE_PREFIX_PATH}" ${QT5_PKG_CONFIG}_LIBRARIES "${${QT5_PKG_CONFIG}_LIBRARIES}")
STRING(REPLACE "${QT5_PKG_CONFIG_Qt5Core_PREFIX}" "${CMAKE_PREFIX_PATH}" ${QT5_PKG_CONFIG}_INCLUDE_DIRS "${${QT5_PKG_CONFIG}_INCLUDE_DIRS}")
STRING(REPLACE "${QT5_PKG_CONFIG_Qt5Core_PREFIX}" "${QT_INSTALL_PREFIX}" ${QT5_PKG_CONFIG}_LDFLAGS_OTHER "${${QT5_PKG_CONFIG}_LDFLAGS_OTHER}")
STRING(REPLACE "${QT5_PKG_CONFIG_Qt5Core_PREFIX}" "${QT_INSTALL_PREFIX}" ${QT5_PKG_CONFIG}_LIBRARIES "${${QT5_PKG_CONFIG}_LIBRARIES}")
STRING(REPLACE "${QT5_PKG_CONFIG_Qt5Core_PREFIX}" "${QT_INSTALL_PREFIX}" ${QT5_PKG_CONFIG}_INCLUDE_DIRS "${${QT5_PKG_CONFIG}_INCLUDE_DIRS}")
STRING(REPLACE "${QT5_PKG_CONFIG_Qt5Core_PREFIX}" "${QT_INSTALL_PREFIX}" ${QT5_PKG_CONFIG}_LIBRARY_DIRS "${${QT5_PKG_CONFIG}_LIBRARY_DIRS}")
endif()
set(QT5_LIBRARIES ${${QT5_PKG_CONFIG}_LIBRARIES} ${${QT5_PKG_CONFIG}_LDFLAGS_OTHER})
@@ -290,6 +302,8 @@ if(STATIC)
list(APPEND QT5_EXTRA_PATHS ${QT5_PKG_CONFIG_Qt5Qml_PREFIX}/qml/QtGraphicalEffects)
list(APPEND QT5_EXTRA_PATHS ${QT5_PKG_CONFIG_Qt5Qml_PREFIX}/qml/QtGraphicalEffects/private)
list(APPEND QT5_EXTRA_PATHS ${QT5_PKG_CONFIG_Qt5Qml_PREFIX}/qml/QtMultimedia)
list(APPEND QT5_EXTRA_PATHS ${QT5_PKG_CONFIG_Qt5Qml_PREFIX}/qml/QtQml)
list(APPEND QT5_EXTRA_PATHS ${QT5_PKG_CONFIG_Qt5Qml_PREFIX}/qml/QtQml/Models.2)
list(APPEND QT5_EXTRA_PATHS ${QT5_PKG_CONFIG_Qt5Qml_PREFIX}/qml/QtQuick.2)
list(APPEND QT5_EXTRA_PATHS ${QT5_PKG_CONFIG_Qt5Qml_PREFIX}/qml/QtQuick/Controls)
list(APPEND QT5_EXTRA_PATHS ${QT5_PKG_CONFIG_Qt5Qml_PREFIX}/qml/QtQuick/Controls.2)
@@ -312,6 +326,7 @@ if(STATIC)
qmlsettingsplugin
qmlxmllistmodelplugin
qquicklayoutsplugin
modelsplugin
)
if(WITH_SCANNER)
@@ -330,6 +345,10 @@ if(STATIC)
windowplugin
)
if(NOT ${Qt5Core_VERSION} VERSION_LESS 5.14)
list(APPEND QT5_EXTRA_LIBRARIES_LIST qmlplugin)
endif()
set(QT5_EXTRA_LIBRARIES)
foreach(LIBRARY ${QT5_EXTRA_LIBRARIES_LIST})
find_library(${LIBRARY}_LIBRARY ${LIBRARY} PATHS ${QT5_EXTRA_PATHS} REQUIRED)
@@ -357,7 +376,6 @@ if(STATIC)
if(UNIX AND NOT APPLE)
list(APPEND QT5_INTEGRATION_LIBRARIES_LIST
Qt5XcbQpa
xcb-static
Qt5ServiceSupport
Qt5GlxSupport
)
@@ -371,11 +389,30 @@ if(STATIC)
endforeach()
if(UNIX AND NOT APPLE)
pkg_check_modules(X11XCB_XCBGLX_FONTCONFIG REQUIRED x11-xcb xcb-glx fontconfig)
list(APPEND QT5_LIBRARIES ${X11XCB_XCBGLX_FONTCONFIG_STATIC_LIBRARIES})
pkg_check_modules(X11XCB_XCBGLX REQUIRED x11-xcb xcb-glx)
list(APPEND QT5_LIBRARIES ${X11XCB_XCBGLX_LIBRARIES})
pkg_check_modules(FONTCONFIG REQUIRED fontconfig)
list(APPEND QT5_LIBRARIES ${FONTCONFIG_STATIC_LIBRARIES})
endif()
endif()
if(ANDROID)
set(QT5_EXTRA_LIBRARIES_LIST
GLESv2
log
z
jnigraphics
android
EGL
Qt5VirtualKeyboard_${CMAKE_ANDROID_ARCH_ABI}
c++_shared
)
foreach(LIBRARY ${QT5_EXTRA_LIBRARIES_LIST})
find_library(${LIBRARY}_LIBRARY ${LIBRARY} PATHS "${ANDROID_TOOLCHAIN_ROOT}/sysroot/usr/lib/${CMAKE_LIBRARY_ARCHITECTURE}/${ANDROID_PLATFORM_LEVEL}" REQUIRED)
list(APPEND QT5_LIBRARIES ${${LIBRARY}_LIBRARY})
endforeach()
endif()
message(STATUS "Using Boost include dir at ${Boost_INCLUDE_DIRS}")
message(STATUS "Using Boost libraries at ${Boost_LIBRARIES}")
@@ -525,6 +562,6 @@ if (HIDAPI_FOUND OR LibUSB_COMPILE_TEST_PASSED)
endif()
endif()
add_subdirectory(external)
add_subdirectory(translations)
add_subdirectory(src)

View File

@@ -2,19 +2,17 @@
Use macOS 10.12 - 10.13 for better backwards compability.
1. `HOMEBREW_OPTFLAGS="-march=core2" HOMEBREW_OPTIMIZATION_LEVEL="O0" brew install boost zmq libpgm miniupnpc libsodium expat libunwind-headers protobuf libgcrypt`
1. `HOMEBREW_OPTFLAGS="-march=core2" HOMEBREW_OPTIMIZATION_LEVEL="O0" brew install boost zmq libpgm miniupnpc libsodium expat libunwind-headers protobuf libgcrypt hidapi`
2. `HOMEBREW_OPTFLAGS="-march=core2" HOMEBREW_OPTIMIZATION_LEVEL="O0" brew install --HEAD hidapi`
2. Get the latest LTS from here: https://www.qt.io/offline-installers and install
3. Get the latest LTS from here: https://www.qt.io/offline-installers and install
3. `git clone --recursive -b v0.X.Y.Z --depth 1 https://github.com/monero-project/monero-gui`
4. `git clone --recursive -b v0.X.Y.Z --depth 1 https://github.com/monero-project/monero-gui`
4. `CMAKE_PREFIX_PATH=~/Qt5.12.8/5.12.8/clang_64 make release`
5. `CMAKE_PREFIX_PATH=~/Qt5.12.8/5.12.8/clang_64 make release`
5. `cd build/release && make deploy`
6. `cd build/release && make deploy`
7. Replace the `monerod` binary inside `monero-wallet-gui.app/Contents/MacOS/` with one built using deterministic builds / gitian.
6. Replace the `monerod` binary inside `monero-wallet-gui.app/Contents/MacOS/` with one built using deterministic builds / gitian.
## Codesigning and notarizing

207
Dockerfile.android Normal file
View File

@@ -0,0 +1,207 @@
FROM debian:stretch
ARG THREADS=1
ARG ANDROID_NDK_REVISION=21d
ARG ANDROID_NDK_HASH=bcf4023eb8cb6976a4c7cff0a8a8f145f162bf4d
ARG ANDROID_SDK_REVISION=4333796
ARG ANDROID_SDK_HASH=92ffee5a1d98d856634e8b71132e8a95d96c83a63fde1099be3d86df3106def9
ARG QT_VERSION=5.15.2
WORKDIR /opt/android
ENV WORKDIR=/opt/android
ENV ANDROID_NATIVE_API_LEVEL=28
ENV ANDROID_API=android-${ANDROID_NATIVE_API_LEVEL}
ENV ANDROID_CLANG=aarch64-linux-android${ANDROID_NATIVE_API_LEVEL}-clang
ENV ANDROID_CLANGPP=aarch64-linux-android${ANDROID_NATIVE_API_LEVEL}-clang++
ENV ANDROID_NDK_ROOT=${WORKDIR}/android-ndk-r${ANDROID_NDK_REVISION}
ENV ANDROID_SDK_ROOT=${WORKDIR}/tools
ENV JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
ENV PATH=${JAVA_HOME}/bin:${PATH}
ENV PREFIX=${WORKDIR}/prefix
ENV TOOLCHAIN_DIR=${ANDROID_NDK_ROOT}/toolchains/llvm/prebuilt/linux-x86_64
RUN apt-get update \
&& apt-get install -y ant automake build-essential ca-certificates-java file gettext git libc6 libncurses5 \
libssl-dev libstdc++6 libtinfo5 libtool libz1 openjdk-8-jdk-headless openjdk-8-jre-headless pkg-config python3 \
unzip wget
RUN wget -q https://dl.google.com/android/repository/sdk-tools-linux-${ANDROID_SDK_REVISION}.zip \
&& unzip -q sdk-tools-linux-${ANDROID_SDK_REVISION}.zip \
&& rm -f sdk-tools-linux-${ANDROID_SDK_REVISION}.zip
RUN wget -q https://dl.google.com/android/repository/android-ndk-r${ANDROID_NDK_REVISION}-linux-x86_64.zip \
&& unzip -q android-ndk-r${ANDROID_NDK_REVISION}-linux-x86_64.zip \
&& rm -f android-ndk-r${ANDROID_NDK_REVISION}-linux-x86_64.zip
RUN cd ${ANDROID_SDK_ROOT} && echo y | ./bin/sdkmanager "platform-tools" "platforms;${ANDROID_API}" "tools" > /dev/null
RUN cp -r ${WORKDIR}/platforms ${WORKDIR}/platform-tools ${ANDROID_SDK_ROOT}
ENV HOST_PATH=${PATH}
ENV PATH=${TOOLCHAIN_DIR}/aarch64-linux-android/bin:${TOOLCHAIN_DIR}/bin:${PATH}
ARG ZLIB_VERSION=1.2.11
ARG ZLIB_HASH=c3e5e9fdd5004dcb542feda5ee4f0ff0744628baf8ed2dd5d66f8ca1197cb1a1
RUN wget -q https://zlib.net/zlib-${ZLIB_VERSION}.tar.gz \
&& tar -xzf zlib-${ZLIB_VERSION}.tar.gz \
&& rm zlib-${ZLIB_VERSION}.tar.gz \
&& cd zlib-${ZLIB_VERSION} \
&& CC=${ANDROID_CLANG} CXX=${ANDROID_CLANGPP} ./configure --prefix=${PREFIX} --static \
&& make -j${THREADS} \
&& make -j${THREADS} install \
&& rm -rf $(pwd)
RUN git clone git://code.qt.io/qt/qt5.git -b ${QT_VERSION} --depth 1 \
&& cd qt5 \
&& perl init-repository --module-subset=default,-qtwebengine \
&& PATH=${HOST_PATH} ./configure -v -developer-build -release \
-xplatform android-clang \
-android-ndk-platform ${ANDROID_API} \
-android-ndk ${ANDROID_NDK_ROOT} \
-android-sdk ${ANDROID_SDK_ROOT} \
-android-ndk-host linux-x86_64 \
-no-dbus \
-opengl es2 \
-no-use-gold-linker \
-no-sql-mysql \
-opensource -confirm-license \
-android-arch arm64-v8a \
-prefix ${PREFIX} \
-nomake tools -nomake tests -nomake examples \
-skip qtwebengine \
-skip qtserialport \
-skip qtconnectivity \
-skip qttranslations \
-skip qtpurchasing \
-skip qtgamepad -skip qtscript -skip qtdoc \
-no-warnings-are-errors \
&& sed -i '213,215d' qtbase/src/3rdparty/pcre2/src/sljit/sljitConfigInternal.h \
&& PATH=${HOST_PATH} make -j${THREADS} \
&& PATH=${HOST_PATH} make -j${THREADS} install \
&& cd qttools/src/linguist/lrelease \
&& ../../../../qtbase/bin/qmake \
&& PATH=${HOST_PATH} make -j${THREADS} install \
&& cd ../../../.. \
&& rm -rf $(pwd)
ARG ICONV_VERSION=1.16
ARG ICONV_HASH=e6a1b1b589654277ee790cce3734f07876ac4ccfaecbee8afa0b649cf529cc04
RUN wget -q http://ftp.gnu.org/pub/gnu/libiconv/libiconv-${ICONV_VERSION}.tar.gz \
&& echo "${ICONV_HASH} libiconv-${ICONV_VERSION}.tar.gz" | sha256sum -c \
&& tar -xzf libiconv-${ICONV_VERSION}.tar.gz \
&& rm -f libiconv-${ICONV_VERSION}.tar.gz \
&& cd libiconv-${ICONV_VERSION} \
&& CC=${ANDROID_CLANG} CXX=${ANDROID_CLANGPP} ./configure --build=x86_64-linux-gnu --host=aarch64 --prefix=${PREFIX} --disable-rpath \
&& make -j${THREADS} \
&& make -j${THREADS} install
ARG BOOST_VERSION=1_74_0
ARG BOOST_VERSION_DOT=1.74.0
ARG BOOST_HASH=83bfc1507731a0906e387fc28b7ef5417d591429e51e788417fe9ff025e116b1
RUN wget -q https://dl.bintray.com/boostorg/release/${BOOST_VERSION_DOT}/source/boost_${BOOST_VERSION}.tar.bz2 \
&& echo "${BOOST_HASH} boost_${BOOST_VERSION}.tar.bz2" | sha256sum -c \
&& tar -xf boost_${BOOST_VERSION}.tar.bz2 \
&& rm -f boost_${BOOST_VERSION}.tar.bz2 \
&& cd boost_${BOOST_VERSION} \
&& PATH=${HOST_PATH} ./bootstrap.sh --prefix=${PREFIX} \
&& PATH=${TOOLCHAIN_DIR}/bin:${HOST_PATH} ./b2 --build-type=minimal link=static runtime-link=static \
--with-chrono --with-date_time --with-filesystem --with-program_options --with-regex --with-serialization \
--with-system --with-thread --with-locale --build-dir=android --stagedir=android toolset=clang threading=multi \
threadapi=pthread target-os=android -sICONV_PATH=${PREFIX} \
cflags='--target=aarch64-linux-android' \
cxxflags='--target=aarch64-linux-android' \
linkflags='--target=aarch64-linux-android --sysroot=${ANDROID_NDK_ROOT}/platforms/${ANDROID_API}/arch-arm64 ${ANDROID_NDK_ROOT}/sources/cxx-stl/llvm-libc++/libs/arm64-v8a/libc++_shared.so -nostdlib++' \
install -j${THREADS} \
&& rm -rf $(pwd)
ARG OPENSSL_VERSION=1.1.1g
ARG OPENSSL_HASH=ddb04774f1e32f0c49751e21b67216ac87852ceb056b75209af2443400636d46
RUN wget -q https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz \
&& tar -xzf openssl-${OPENSSL_VERSION}.tar.gz \
&& rm openssl-${OPENSSL_VERSION}.tar.gz \
&& cd openssl-${OPENSSL_VERSION} \
&& ANDROID_NDK_HOME=${ANDROID_NDK_ROOT} ./Configure CC=${ANDROID_CLANG} CXX=${ANDROID_CLANGPP} \
android-arm64 no-asm no-shared --static \
--with-zlib-include=${PREFIX}/include --with-zlib-lib=${PREFIX}/lib \
--prefix=${PREFIX} --openssldir=${PREFIX} \
&& sed -i 's/CNF_EX_LIBS=-ldl -pthread//g;s/BIN_CFLAGS=-pie $(CNF_CFLAGS) $(CFLAGS)//g' Makefile \
&& ANDROID_NDK_HOME=${ANDROID_NDK_ROOT} make -j${THREADS} \
&& make -j${THREADS} install \
&& rm -rf $(pwd)
ARG ZMQ_VERSION=v4.3.3
ARG ZMQ_HASH=04f5bbedee58c538934374dc45182d8fc5926fa3
RUN git clone https://github.com/zeromq/libzmq.git -b ${ZMQ_VERSION} --depth 1 \
&& cd libzmq \
&& git checkout ${ZMQ_HASH} \
&& ./autogen.sh \
&& CC=${ANDROID_CLANG} CXX=${ANDROID_CLANGPP} ./configure --prefix=${PREFIX} --host=aarch64-linux-android \
--enable-static --disable-shared \
&& make -j${THREADS} \
&& make -j${THREADS} install \
&& rm -rf $(pwd)
ARG SODIUM_VERSION=1.0.18
ARG SODIUM_HASH=4f5e89fa84ce1d178a6765b8b46f2b6f91216677
RUN set -ex \
&& git clone https://github.com/jedisct1/libsodium.git -b ${SODIUM_VERSION} --depth 1 \
&& cd libsodium \
&& test `git rev-parse HEAD` = ${SODIUM_HASH} || exit 1 \
&& ./autogen.sh \
&& CC=${ANDROID_CLANG} CXX=${ANDROID_CLANGPP} ./configure --prefix=${PREFIX} --host=aarch64-linux-android --enable-static --disable-shared \
&& make -j${THREADS} install \
&& rm -rf $(pwd)
RUN git clone -b libgpg-error-1.38 --depth 1 git://git.gnupg.org/libgpg-error.git \
&& cd libgpg-error \
&& git reset --hard 71d278824c5fe61865f7927a2ed1aa3115f9e439 \
&& ./autogen.sh \
&& CC=${ANDROID_CLANG} CXX=${ANDROID_CLANGPP} ./configure --host=aarch64-linux-android --prefix=${PREFIX} --disable-rpath --disable-shared --enable-static --disable-doc --disable-tests \
&& PATH=${TOOLCHAIN_DIR}/bin:${HOST_PATH} make -j${THREADS} \
&& make -j${THREADS} install \
&& rm -rf $(pwd)
RUN git clone -b libgcrypt-1.8.5 --depth 1 git://git.gnupg.org/libgcrypt.git \
&& cd libgcrypt \
&& git reset --hard 56606331bc2a80536db9fc11ad53695126007298 \
&& ./autogen.sh \
&& CC=${ANDROID_CLANG} CXX=${ANDROID_CLANGPP} ./configure --host=aarch64-linux-android --prefix=${PREFIX} --with-gpg-error-prefix=${PREFIX} --disable-shared --enable-static --disable-doc --disable-tests \
&& PATH=${TOOLCHAIN_DIR}/bin:${HOST_PATH} make -j${THREADS} \
&& make -j${THREADS} install \
&& rm -rf $(pwd)
RUN cd tools \
&& wget -q http://dl-ssl.google.com/android/repository/tools_r25.2.5-linux.zip \
&& unzip -q tools_r25.2.5-linux.zip \
&& rm -f tools_r25.2.5-linux.zip \
&& echo y | ${ANDROID_SDK_ROOT}/tools/android update sdk --no-ui --all --filter build-tools-28.0.3
RUN git clone -b v3.19.7 --depth 1 https://github.com/Kitware/CMake \
&& cd CMake \
&& git reset --hard 22612dd53a46c7f9b4c3f4b7dbe5c78f9afd9581 \
&& PATH=${HOST_PATH} ./bootstrap \
&& PATH=${HOST_PATH} make -j${THREADS} \
&& PATH=${HOST_PATH} make -j${THREADS} install \
&& rm -rf $(pwd)
CMD set -ex \
&& cd /monero-gui \
&& mkdir -p build/Android/release \
&& cd build/Android/release \
&& cmake \
-DCMAKE_TOOLCHAIN_FILE="${ANDROID_NDK_ROOT}/build/cmake/android.toolchain.cmake" \
-DCMAKE_PREFIX_PATH="${PREFIX}" \
-DCMAKE_FIND_ROOT_PATH="${PREFIX}" \
-DCMAKE_BUILD_TYPE=Release \
-DARCH="armv8-a" \
-DANDROID_NATIVE_API_LEVEL=${ANDROID_NATIVE_API_LEVEL} \
-DANDROID_ABI="arm64-v8a" \
-DANDROID_TOOLCHAIN=clang \
-DBoost_USE_STATIC_RUNTIME=ON \
-DLRELEASE_PATH="${PREFIX}/bin" \
-DQT_ANDROID_APPLICATION_BINARY="monero-wallet-gui" \
-DWITH_SCANNER=ON \
../../.. \
&& PATH=${HOST_PATH} make generate_translations_header \
&& make -j${THREADS} -C src \
&& make -j${THREADS} apk

View File

@@ -1,6 +1,12 @@
FROM ubuntu:16.04
ARG THREADS=1
ARG QT_VERSION=5.15.2
ENV CFLAGS="-fPIC"
ENV CPPFLAGS="-fPIC"
ENV CXXFLAGS="-fPIC"
ENV SOURCE_DATE_EPOCH=1397818193
RUN apt update
@@ -8,7 +14,7 @@ RUN apt install -y automake git pkg-config python xutils-dev && \
git clone -b xorgproto-2020.1 --depth 1 https://gitlab.freedesktop.org/xorg/proto/xorgproto && \
cd xorgproto && \
git reset --hard c62e8203402cafafa5ba0357b6d1c019156c9f36 && \
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./autogen.sh --disable-shared --enable-static && \
./autogen.sh && \
make -j$THREADS && \
make -j$THREADS install && \
rm -rf $(pwd)
@@ -16,7 +22,7 @@ RUN apt install -y automake git pkg-config python xutils-dev && \
RUN git clone -b 1.12 --depth 1 https://gitlab.freedesktop.org/xorg/proto/xcbproto && \
cd xcbproto && \
git reset --hard 6398e42131eedddde0d98759067dde933191f049 && \
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./autogen.sh --disable-shared --enable-static && \
./autogen.sh && \
make -j$THREADS && \
make -j$THREADS install && \
rm -rf $(pwd)
@@ -25,7 +31,7 @@ RUN apt install -y libtool-bin && \
git clone -b libXau-1.0.9 --depth 1 https://gitlab.freedesktop.org/xorg/lib/libxau && \
cd libxau && \
git reset --hard d9443b2c57b512cfb250b35707378654d86c7dea && \
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./autogen.sh --disable-shared --enable-static && \
./autogen.sh --enable-shared --disable-static && \
make -j$THREADS && \
make -j$THREADS install && \
rm -rf $(pwd)
@@ -34,7 +40,76 @@ RUN apt install -y libpthread-stubs0-dev && \
git clone -b 1.12 --depth 1 https://gitlab.freedesktop.org/xorg/lib/libxcb && \
cd libxcb && \
git reset --hard d34785a34f28fa6a00f8ce00d87e3132ff0f6467 && \
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./autogen.sh --disable-shared --enable-static && \
./autogen.sh --enable-shared --disable-static && \
make -j$THREADS && \
make -j$THREADS install && \
make -j$THREADS clean && \
rm /usr/local/lib/libxcb-xinerama.so && \
./autogen.sh --disable-shared --enable-static && \
make -j$THREADS && \
cp src/.libs/libxcb-xinerama.a /usr/local/lib/ && \
rm -rf $(pwd)
RUN git clone -b 0.4.0 --depth 1 https://gitlab.freedesktop.org/xorg/lib/libxcb-util && \
cd libxcb-util && \
git reset --hard acf790d7752f36e450d476ad79807d4012ec863b && \
git submodule init && \
git clone --depth 1 https://gitlab.freedesktop.org/xorg/util/xcb-util-m4 m4 && \
git -C m4 reset --hard f662e3a93ebdec3d1c9374382dcc070093a42fed && \
./autogen.sh --enable-shared --disable-static && \
make -j$THREADS && \
make -j$THREADS install && \
rm -rf $(pwd)
RUN git clone -b 0.4.0 --depth 1 https://gitlab.freedesktop.org/xorg/lib/libxcb-image && \
cd libxcb-image && \
git reset --hard d882052fb2ce439c6483fce944ba8f16f7294639 && \
git submodule init && \
git clone --depth 1 https://gitlab.freedesktop.org/xorg/util/xcb-util-m4 m4 && \
git -C m4 reset --hard f662e3a93ebdec3d1c9374382dcc070093a42fed && \
./autogen.sh --enable-shared --disable-static && \
make -j$THREADS && \
make -j$THREADS install && \
rm -rf $(pwd)
RUN git clone -b 0.4.0 --depth 1 https://gitlab.freedesktop.org/xorg/lib/libxcb-keysyms && \
cd libxcb-keysyms && \
git reset --hard 0e51ee5570a6a80bdf98770b975dfe8a57f4eeb1 && \
git submodule init && \
git clone --depth 1 https://gitlab.freedesktop.org/xorg/util/xcb-util-m4 m4 && \
git -C m4 reset --hard f662e3a93ebdec3d1c9374382dcc070093a42fed && \
./autogen.sh --enable-shared --disable-static && \
make -j$THREADS && \
make -j$THREADS install && \
rm -rf $(pwd)
RUN git clone -b 0.3.9 --depth 1 https://gitlab.freedesktop.org/xorg/lib/libxcb-render-util && \
cd libxcb-render-util && \
git reset --hard 0317caf63de532fd7a0493ed6afa871a67253747 && \
git submodule init && \
git clone --depth 1 https://gitlab.freedesktop.org/xorg/util/xcb-util-m4 m4 && \
git -C m4 reset --hard f662e3a93ebdec3d1c9374382dcc070093a42fed && \
./autogen.sh --enable-shared --disable-static && \
make -j$THREADS && \
make -j$THREADS install && \
rm -rf $(pwd)
RUN git clone -b 0.4.1 --depth 1 https://gitlab.freedesktop.org/xorg/lib/libxcb-wm && \
cd libxcb-wm && \
git reset --hard 24eb17df2e1245885e72c9d4bbb0a0f69f0700f2 && \
git submodule init && \
git clone --depth 1 https://gitlab.freedesktop.org/xorg/util/xcb-util-m4 m4 && \
git -C m4 reset --hard f662e3a93ebdec3d1c9374382dcc070093a42fed && \
./autogen.sh --enable-shared --disable-static && \
make -j$THREADS && \
make -j$THREADS install && \
rm -rf $(pwd)
RUN apt install -y bison && \
git clone -b xkbcommon-0.5.0 --depth 1 https://github.com/xkbcommon/libxkbcommon && \
cd libxkbcommon && \
git reset --hard c43c3c866eb9d52cd8f61e75cbef1c30d07f3a28 && \
./autogen.sh --prefix=/usr --enable-shared --disable-static --enable-x11 --disable-docs && \
make -j$THREADS && \
make -j$THREADS install && \
rm -rf $(pwd)
@@ -42,7 +117,7 @@ RUN apt install -y libpthread-stubs0-dev && \
RUN git clone -b v1.2.11 --depth 1 https://github.com/madler/zlib && \
cd zlib && \
git reset --hard cacf7f1d4e3d44d871b605da3b647f07d718623f && \
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./configure --static && \
./configure --static && \
make -j$THREADS && \
make -j$THREADS install && \
rm -rf $(pwd)
@@ -51,7 +126,7 @@ RUN git clone -b VER-2-10-2 --depth 1 https://git.savannah.gnu.org/git/freetype/
cd freetype2 && \
git reset --hard 132f19b779828b194b3fede187cee719785db4d8 && \
./autogen.sh && \
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./configure --disable-shared --enable-static --with-zlib=no && \
./configure --disable-shared --enable-static --with-zlib=no && \
make -j$THREADS && \
make -j$THREADS install && \
rm -rf $(pwd)
@@ -60,7 +135,7 @@ RUN git clone -b R_2_2_9 --depth 1 https://github.com/libexpat/libexpat && \
cd libexpat/expat && \
git reset --hard a7bc26b69768f7fb24f0c7976fae24b157b85b13 && \
./buildconf.sh && \
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./configure --disable-shared --enable-static && \
./configure --disable-shared --enable-static && \
make -j$THREADS && \
make -j$THREADS install && \
rm -rf $(pwd)
@@ -69,7 +144,7 @@ RUN apt install -y autopoint gettext gperf libpng12-dev && \
git clone -b 2.13.92 --depth 1 https://gitlab.freedesktop.org/fontconfig/fontconfig && \
cd fontconfig && \
git reset --hard b1df1101a643ae16cdfa1d83b939de2497b1bf27 && \
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./autogen.sh --disable-shared --enable-static --sysconfdir=/etc --localstatedir=/var && \
./autogen.sh --disable-shared --enable-static --sysconfdir=/etc --localstatedir=/var && \
make -j$THREADS && \
make -j$THREADS install && \
rm -rf $(pwd)
@@ -77,46 +152,56 @@ RUN apt install -y autopoint gettext gperf libpng12-dev && \
RUN git clone -b release-64-2 --depth 1 https://github.com/unicode-org/icu && \
cd icu/icu4c/source && \
git reset --hard e2d85306162d3a0691b070b4f0a73e4012433444 && \
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./configure --disable-shared --enable-static --disable-tests --disable-samples && \
./configure --disable-shared --enable-static --disable-tests --disable-samples && \
make -j$THREADS && \
make -j$THREADS install && \
rm -rf $(pwd)
RUN apt install -y wget && \
wget https://dl.bintray.com/boostorg/release/1.73.0/source/boost_1_73_0.tar.gz && \
echo "9995e192e68528793755692917f9eb6422f3052a53c5e13ba278a228af6c7acf boost_1_73_0.tar.gz" > hashsum.txt && \
sha256sum -c hashsum.txt && \
echo "9995e192e68528793755692917f9eb6422f3052a53c5e13ba278a228af6c7acf boost_1_73_0.tar.gz" | sha256sum -c && \
tar -xzf boost_1_73_0.tar.gz && \
rm boost_1_73_0.tar.gz && \
cd boost_1_73_0 && \
./bootstrap.sh && \
./b2 --with-atomic --with-system --with-filesystem --with-thread --with-date_time --with-chrono --with-regex --with-serialization --with-program_options --with-locale variant=release link=static runtime-link=static cflags='-fPIC' cxxflags='-fPIC' install -a --prefix=/usr && \
./b2 --with-atomic --with-system --with-filesystem --with-thread --with-date_time --with-chrono --with-regex --with-serialization --with-program_options --with-locale variant=release link=static runtime-link=static cflags="${CFLAGS}" cxxflags="${CXXFLAGS}" install -a --prefix=/usr && \
rm -rf $(pwd)
RUN wget https://www.openssl.org/source/openssl-1.1.1g.tar.gz && \
echo "ddb04774f1e32f0c49751e21b67216ac87852ceb056b75209af2443400636d46 openssl-1.1.1g.tar.gz" > hashsum.txt && \
sha256sum -c hashsum.txt && \
echo "ddb04774f1e32f0c49751e21b67216ac87852ceb056b75209af2443400636d46 openssl-1.1.1g.tar.gz" | sha256sum -c && \
tar -xzf openssl-1.1.1g.tar.gz && \
rm openssl-1.1.1g.tar.gz && \
cd openssl-1.1.1g && \
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./config no-asm no-shared no-zlib-dynamic --openssldir=/usr && \
./config no-asm no-shared no-zlib-dynamic --openssldir=/usr && \
make -j$THREADS && \
make -j$THREADS install && \
rm -rf $(pwd)
RUN apt install -y libgl1-mesa-dev libglib2.0-dev libxkbcommon-dev && \
wget https://download.qt.io/archive/qt/5.9/5.9.9/single/qt-everywhere-opensource-src-5.9.9.tar.xz && \
echo "5ce285209290a157d7f42ec8eb22bf3f1d76f2e03a95fc0b99b553391be01642 qt-everywhere-opensource-src-5.9.9.tar.xz" > hashsum.txt && \
sha256sum -c hashsum.txt && \
tar -xf qt-everywhere-opensource-src-5.9.9.tar.xz && \
rm qt-everywhere-opensource-src-5.9.9.tar.xz && \
cd qt-everywhere-opensource-src-5.9.9 && \
RUN apt install -y libgl1-mesa-dev libglib2.0-dev mesa-common-dev && \
rm /usr/lib/x86_64-linux-gnu/libX11.a && \
rm /usr/lib/x86_64-linux-gnu/libXext.a && \
rm /usr/lib/x86_64-linux-gnu/libX11-xcb.a && \
git clone git://code.qt.io/qt/qt5.git -b ${QT_VERSION} --depth 1 && \
cd qt5 && \
git clone git://code.qt.io/qt/qtbase.git -b ${QT_VERSION} --depth 1 && \
git clone git://code.qt.io/qt/qtdeclarative.git -b ${QT_VERSION} --depth 1 && \
git clone git://code.qt.io/qt/qtgraphicaleffects.git -b ${QT_VERSION} --depth 1 && \
git clone git://code.qt.io/qt/qtimageformats.git -b ${QT_VERSION} --depth 1 && \
git clone git://code.qt.io/qt/qtmultimedia.git -b ${QT_VERSION} --depth 1 && \
git clone git://code.qt.io/qt/qtquickcontrols.git -b ${QT_VERSION} --depth 1 && \
git clone git://code.qt.io/qt/qtquickcontrols2.git -b ${QT_VERSION} --depth 1 && \
git clone git://code.qt.io/qt/qtsvg.git -b ${QT_VERSION} --depth 1 && \
git clone git://code.qt.io/qt/qttools.git -b ${QT_VERSION} --depth 1 && \
git clone git://code.qt.io/qt/qttranslations.git -b ${QT_VERSION} --depth 1 && \
git clone git://code.qt.io/qt/qtx11extras.git -b ${QT_VERSION} --depth 1 && \
git clone git://code.qt.io/qt/qtxmlpatterns.git -b ${QT_VERSION} --depth 1 && \
sed -ri s/\(Libs:.*\)/\\1\ -lexpat/ /usr/local/lib/pkgconfig/fontconfig.pc && \
sed -ri s/\(Libs:.*\)/\\1\ -lz/ /usr/local/lib/pkgconfig/freetype2.pc && \
sed -ri s/\(Libs:.*\)/\\1\ -lXau/ /usr/local/lib/pkgconfig/xcb.pc && \
sed -i s/\\/usr\\/X11R6\\/lib64/\\/usr\\/local\\/lib/ qtbase/mkspecs/linux-g++-64/qmake.conf && \
./configure --prefix=/usr -platform linux-g++-64 -opensource -confirm-license -release -static -no-avx \
-opengl desktop -qpa xcb -system-freetype -fontconfig -glib \
-no-dbus -no-openssl -no-sql-sqlite -no-use-gold-linker \
-opengl desktop -qpa xcb -xcb -xcb-xlib -feature-xlib -system-freetype -fontconfig -glib \
-no-dbus -no-feature-qml-worker-script -no-linuxfb -no-openssl -no-sql-sqlite -no-kms -no-use-gold-linker \
-qt-harfbuzz -qt-libjpeg -qt-libpng -qt-pcre -qt-zlib \
-skip qt3d -skip qtandroidextras -skip qtcanvas3d -skip qtcharts -skip qtconnectivity -skip qtdatavis3d \
-skip qtdoc -skip qtgamepad -skip qtlocation -skip qtmacextras -skip qtnetworkauth -skip qtpurchasing \
@@ -137,7 +222,7 @@ RUN apt install -y libudev-dev && \
git clone -b v1.0.23 --depth 1 https://github.com/libusb/libusb && \
cd libusb && \
git reset --hard e782eeb2514266f6738e242cdcb18e3ae1ed06fa && \
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./autogen.sh --disable-shared --enable-static && \
./autogen.sh --disable-shared --enable-static && \
make -j$THREADS && \
make -j$THREADS install && \
rm -rf $(pwd)
@@ -146,23 +231,7 @@ RUN git clone -b hidapi-0.9.0 --depth 1 https://github.com/libusb/hidapi && \
cd hidapi && \
git reset --hard 7da5cc91fc0d2dbe4df4f08cd31f6ca1a262418f && \
./bootstrap && \
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./configure --disable-shared --enable-static && \
make -j$THREADS && \
make -j$THREADS install && \
rm -rf $(pwd)
RUN git clone -b libX11-1.6.9 --depth 1 https://gitlab.freedesktop.org/xorg/lib/libx11 && \
cd libx11 && \
git reset --hard db7cca17ad7807e92a928da9d4c68a00f4836da2 && \
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./autogen.sh --disable-shared --enable-static && \
make -j$THREADS && \
make -j$THREADS install && \
rm -rf $(pwd)
RUN git clone -b libXext-1.3.4 --depth 1 https://gitlab.freedesktop.org/xorg/lib/libxext && \
cd libxext && \
git reset --hard ebb167f34a3514783966775fb12573c4ed209625 && \
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./autogen.sh --disable-shared --enable-static && \
./configure --disable-shared --enable-static && \
make -j$THREADS && \
make -j$THREADS install && \
rm -rf $(pwd)
@@ -172,7 +241,7 @@ RUN apt install -y libsodium-dev && \
cd libzmq && \
git reset --hard a84ffa12b2eb3569ced199660bac5ad128bff1f0 && \
./autogen.sh && \
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./configure --disable-shared --enable-static --disable-libunwind --with-libsodium && \
./configure --disable-shared --enable-static --disable-libunwind --with-libsodium && \
make -j$THREADS && \
make -j$THREADS install && \
rm -rf $(pwd)
@@ -181,7 +250,7 @@ RUN git clone -b libgpg-error-1.38 --depth 1 git://git.gnupg.org/libgpg-error.gi
cd libgpg-error && \
git reset --hard 71d278824c5fe61865f7927a2ed1aa3115f9e439 && \
./autogen.sh && \
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./configure --disable-shared --enable-static --disable-doc --disable-tests && \
./configure --disable-shared --enable-static --disable-doc --disable-tests && \
make -j$THREADS && \
make -j$THREADS install && \
rm -rf $(pwd)
@@ -190,7 +259,7 @@ RUN git clone -b libgcrypt-1.8.5 --depth 1 git://git.gnupg.org/libgcrypt.git &&
cd libgcrypt && \
git reset --hard 56606331bc2a80536db9fc11ad53695126007298 && \
./autogen.sh && \
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./configure --disable-shared --enable-static --disable-doc && \
./configure --disable-shared --enable-static --disable-doc && \
make -j$THREADS && \
make -j$THREADS install && \
rm -rf $(pwd)
@@ -199,9 +268,17 @@ RUN git clone -b v3.10.0 --depth 1 https://github.com/protocolbuffers/protobuf &
cd protobuf && \
git reset --hard 6d4e7fd7966c989e38024a8ea693db83758944f1 && \
./autogen.sh && \
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./configure --enable-static --disable-shared && \
./configure --enable-static --disable-shared && \
make -j$THREADS && \
make -j$THREADS install && \
rm -rf $(pwd)
RUN apt install -y cmake libusb-1.0-0-dev
RUN git clone -b v3.18.4 --depth 1 https://github.com/Kitware/CMake && \
cd CMake && \
git reset --hard 3cc3d42aba879fff5e85b363ae8f21386a3f9f9b && \
./bootstrap && \
make -j$THREADS && \
make -j$THREADS install && \
rm -rf $(pwd)
RUN apt install -y libusb-1.0-0-dev

View File

@@ -1,6 +1,8 @@
FROM ubuntu:20.04
ARG THREADS=1
ARG QT_VERSION=5.15.2
ENV SOURCE_DATE_EPOCH=1397818193
RUN apt update && \
DEBIAN_FRONTEND=noninteractive apt install -y build-essential cmake g++-mingw-w64 gettext git libtool pkg-config \
@@ -19,26 +21,35 @@ RUN git clone -b v0.17.0.0 --depth 1 https://github.com/monero-project/monero &&
RUN make -j$THREADS -C /depends HOST=x86_64-w64-mingw32 NO_QT=1
RUN curl -LO https://download.qt.io/archive/qt/5.9/5.9.9/single/qt-everywhere-opensource-src-5.9.9.tar.xz && \
echo "5ce285209290a157d7f42ec8eb22bf3f1d76f2e03a95fc0b99b553391be01642 qt-everywhere-opensource-src-5.9.9.tar.xz" > hashsum.txt && \
sha256sum -c hashsum.txt && \
tar -xf qt-everywhere-opensource-src-5.9.9.tar.xz && \
rm qt-everywhere-opensource-src-5.9.9.tar.xz && \
cd qt-everywhere-opensource-src-5.9.9 && \
RUN git clone git://code.qt.io/qt/qt5.git -b ${QT_VERSION} --depth 1 && \
cd qt5 && \
git clone git://code.qt.io/qt/qtbase.git -b ${QT_VERSION} --depth 1 && \
git clone git://code.qt.io/qt/qtdeclarative.git -b ${QT_VERSION} --depth 1 && \
git clone git://code.qt.io/qt/qtgraphicaleffects.git -b ${QT_VERSION} --depth 1 && \
git clone git://code.qt.io/qt/qtimageformats.git -b ${QT_VERSION} --depth 1 && \
git clone git://code.qt.io/qt/qtmultimedia.git -b ${QT_VERSION} --depth 1 && \
git clone git://code.qt.io/qt/qtquickcontrols.git -b ${QT_VERSION} --depth 1 && \
git clone git://code.qt.io/qt/qtquickcontrols2.git -b ${QT_VERSION} --depth 1 && \
git clone git://code.qt.io/qt/qtsvg.git -b ${QT_VERSION} --depth 1 && \
git clone git://code.qt.io/qt/qttools.git -b ${QT_VERSION} --depth 1 && \
git clone git://code.qt.io/qt/qttranslations.git -b ${QT_VERSION} --depth 1 && \
git clone git://code.qt.io/qt/qtxmlpatterns.git -b ${QT_VERSION} --depth 1 && \
./configure --prefix=/depends/x86_64-w64-mingw32 -xplatform win32-g++ \
-device-option CROSS_COMPILE=/usr/bin/x86_64-w64-mingw32- \
-I $(pwd)/qtbase/src/3rdparty/angle/include \
-opensource -confirm-license -release -static -static-runtime -opengl dynamic -no-angle \
-no-avx -no-openssl -no-sql-sqlite \
-no-feature-qml-worker-script -no-openssl -no-sql-sqlite \
-qt-freetype -qt-harfbuzz -qt-libjpeg -qt-libpng -qt-pcre -qt-zlib \
-skip gamepad -skip location -skip qt3d -skip qtactiveqt -skip qtandroidextras -skip qtcanvas3d -skip qtcharts \
-skip qtconnectivity -skip qtdatavis3d -skip qtdoc -skip qtgamepad -skip qtlocation -skip qtmacextras \
-skip qtmultimedia -skip qtnetworkauth -skip qtpurchasing -skip qtscript -skip qtscxml -skip qtsensors \
-skip qtserialbus -skip qtserialport -skip qtspeech -skip qttools -skip qtvirtualkeyboard -skip qtwayland \
-skip qtwebchannel -skip qtwebengine -skip qtwebsockets -skip qtwebview -skip qtwinextras -skip qtx11extras \
-skip gamepad -skip location -skip qt3d -skip qtactiveqt -skip qtandroidextras \
-skip qtcanvas3d -skip qtcharts -skip qtconnectivity -skip qtdatavis3d -skip qtdoc \
-skip qtgamepad -skip qtlocation -skip qtmacextras -skip qtnetworkauth -skip qtpurchasing \
-skip qtscript -skip qtscxml -skip qtsensors -skip qtserialbus -skip qtserialport \
-skip qtspeech -skip qttools -skip qtvirtualkeyboard -skip qtwayland -skip qtwebchannel \
-skip qtwebengine -skip qtwebsockets -skip qtwebview -skip qtwinextras -skip qtx11extras \
-skip serialbus -skip webengine \
-nomake examples -nomake tests -nomake tools && \
make QMAKE="$(pwd)/qtbase/bin/qmake CONFIG-='debug debug_and_release'" -j$THREADS && \
make -j$THREADS && \
make -j$THREADS install && \
cd qttools/src/linguist/lrelease && \
../../../../qtbase/bin/qmake && \

View File

@@ -58,12 +58,9 @@ Rectangle {
signal historyClicked()
signal transferClicked()
signal receiveClicked()
signal txkeyClicked()
signal sharedringdbClicked()
signal advancedClicked()
signal settingsClicked()
signal addressBookClicked()
signal miningClicked()
signal signClicked()
signal accountClicked()
function selectItem(pos) {
@@ -72,10 +69,6 @@ Rectangle {
else if(pos === "Transfer") menuColumn.previousButton = transferButton
else if(pos === "Receive") menuColumn.previousButton = receiveButton
else if(pos === "AddressBook") menuColumn.previousButton = addressBookButton
else if(pos === "Mining") menuColumn.previousButton = miningButton
else if(pos === "TxKey") menuColumn.previousButton = txkeyButton
else if(pos === "SharedRingDB") menuColumn.previousButton = sharedringdbButton
else if(pos === "Sign") menuColumn.previousButton = signButton
else if(pos === "Settings") menuColumn.previousButton = settingsButton
else if(pos === "Advanced") menuColumn.previousButton = advancedButton
else if(pos === "Account") menuColumn.previousButton = accountButton
@@ -480,6 +473,7 @@ Rectangle {
onClicked: {
parent.previousButton.checked = false
parent.previousButton = advancedButton
panel.advancedClicked()
}
}
@@ -490,98 +484,6 @@ Rectangle {
anchors.leftMargin: 20
}
// ------------- Mining tab ---------------
MoneroComponents.MenuButton {
id: miningButton
visible: !isAndroid && !isIOS && appWindow.walletMode >= 2
anchors.left: parent.left
anchors.right: parent.right
text: qsTr("Mining") + translationManager.emptyString
symbol: qsTr("M") + translationManager.emptyString
under: advancedButton
onClicked: {
parent.previousButton.checked = false
parent.previousButton = miningButton
panel.miningClicked()
}
}
MoneroComponents.MenuButtonDivider {
visible: miningButton.present && appWindow.walletMode >= 2
anchors.left: parent.left
anchors.right: parent.right
anchors.leftMargin: 20
}
// ------------- TxKey tab ---------------
MoneroComponents.MenuButton {
id: txkeyButton
visible: appWindow.walletMode >= 2
anchors.left: parent.left
anchors.right: parent.right
text: qsTr("Prove/check") + translationManager.emptyString
symbol: qsTr("K") + translationManager.emptyString
under: advancedButton
onClicked: {
parent.previousButton.checked = false
parent.previousButton = txkeyButton
panel.txkeyClicked()
}
}
MoneroComponents.MenuButtonDivider {
visible: txkeyButton.present && appWindow.walletMode >= 2
anchors.left: parent.left
anchors.right: parent.right
anchors.leftMargin: 20
}
// ------------- Shared RingDB tab ---------------
MoneroComponents.MenuButton {
id: sharedringdbButton
visible: appWindow.walletMode >= 2
anchors.left: parent.left
anchors.right: parent.right
text: qsTr("Shared RingDB") + translationManager.emptyString
symbol: qsTr("G") + translationManager.emptyString
under: advancedButton
onClicked: {
parent.previousButton.checked = false
parent.previousButton = sharedringdbButton
panel.sharedringdbClicked()
}
}
MoneroComponents.MenuButtonDivider {
visible: sharedringdbButton.present && appWindow.walletMode >= 2
anchors.left: parent.left
anchors.right: parent.right
anchors.leftMargin: 20
}
// ------------- Sign/verify tab ---------------
MoneroComponents.MenuButton {
id: signButton
visible: appWindow.walletMode >= 2
anchors.left: parent.left
anchors.right: parent.right
text: qsTr("Sign/verify") + translationManager.emptyString
symbol: qsTr("I") + translationManager.emptyString
under: advancedButton
onClicked: {
parent.previousButton.checked = false
parent.previousButton = signButton
panel.signClicked()
}
}
MoneroComponents.MenuButtonDivider {
visible: signButton.present && appWindow.walletMode >= 2
anchors.left: parent.left
anchors.right: parent.right
anchors.leftMargin: 20
}
// ------------- Settings tab ---------------
MoneroComponents.MenuButton {
id: settingsButton

View File

@@ -1,40 +1,51 @@
ANDROID_STANDALONE_TOOLCHAIN_PATH ?= /usr/local/toolchain
MANUAL_SUBMODULES ?= OFF
dotgit=$(shell ls -d .git/config)
ifneq ($(dotgit), .git/config)
USE_SINGLE_BUILDDIR=1
ifeq ($(dotgit), .git/config)
ifeq ($(shell git --version > /dev/null 2>&1 ; echo $$?), 0)
git = yes
else
$(warning git command not found)
endif
endif
subbuilddir:=$(shell echo `uname | sed -e 's|[:/\\ \(\)]|_|g'`/`git branch | grep '\* ' | cut -f2- -d' '| sed -e 's|[:/\\ \(\)]|_|g'`)
builddir := build
topdir := ../..
ifeq ($(USE_SINGLE_BUILDDIR), OFF)
builddir := build/"$(subbuilddir)"
topdir := ../../../..
deldirs := $(builddir)
else
builddir := build
topdir := ../..
deldirs := $(builddir)/debug $(builddir)/release $(builddir)/fuzz
endif
os := $(shell echo `uname | sed -e 's|[:/\\ \(\)]|_|g'`)
builddir := $(builddir)/$(os)
topdir := $(topdir)/..
ifdef git
branch := $(shell git branch | grep '\* ' | cut -f2- -d' '| sed -e 's|[:/\\ \(\)]|_|g')
builddir := $(builddir)/$(branch)
topdir := $(topdir)/..
endif
deldirs := $(builddir)
else
deldirs := $(builddir)/debug $(builddir)/release $(builddir)/fuzz
endif
default:
mkdir -p build && cd build && cmake -D ARCH="x86-64" -D DEV_MODE=$(or ${DEV_MODE},OFF) -D BUILD_64=ON -D CMAKE_BUILD_TYPE=Release .. && $(MAKE)
mkdir -p build && cd build && cmake -D ARCH="x86-64" -D DEV_MODE=$(or ${DEV_MODE},OFF) -DMANUAL_SUBMODULES=${MANUAL_SUBMODULES} -D BUILD_64=ON -D CMAKE_BUILD_TYPE=Release .. && $(MAKE)
debug:
mkdir -p build && cd build && cmake -D DEV_MODE=$(or ${DEV_MODE},ON) .. && $(MAKE) VERBOSE=1
mkdir -p build && cd build && cmake -D DEV_MODE=$(or ${DEV_MODE},ON) -DMANUAL_SUBMODULES=${MANUAL_SUBMODULES} .. && $(MAKE) VERBOSE=1
depends:
mkdir -p build/$(target)/release
cd build/$(target)/release && cmake -D STATIC=ON -D DEV_MODE=$(or ${DEV_MODE},OFF) -D BUILD_TAG=$(tag) -D CMAKE_BUILD_TYPE=Release -D CMAKE_TOOLCHAIN_FILE=$(root)/$(target)/share/toolchain.cmake ../../.. && $(MAKE)
cd build/$(target)/release && cmake -D STATIC=ON -D DEV_MODE=$(or ${DEV_MODE},OFF) -DMANUAL_SUBMODULES=${MANUAL_SUBMODULES} -D BUILD_TAG=$(tag) -D CMAKE_BUILD_TYPE=Release -D CMAKE_TOOLCHAIN_FILE=$(root)/$(target)/share/toolchain.cmake ../../.. && $(MAKE)
devmode:
mkdir -p build && cd build && cmake -D ARCH="x86-64" -D DEV_MODE=$(or ${DEV_MODE},ON) -D BUILD_64=ON -D CMAKE_BUILD_TYPE=Release .. && $(MAKE)
mkdir -p build && cd build && cmake -D ARCH="x86-64" -D DEV_MODE=$(or ${DEV_MODE},ON) -DMANUAL_SUBMODULES=${MANUAL_SUBMODULES} -D BUILD_64=ON -D CMAKE_BUILD_TYPE=Release .. && $(MAKE)
clean:
mkdir -p build && cd build && rm -rf *
scanner:
mkdir -p build && cd build && cmake -D ARCH="x86-64" -D DEV_MODE=$(or ${DEV_MODE},ON) -D WITH_SCANNER=ON -D BUILD_64=ON -D CMAKE_BUILD_TYPE=Release .. && $(MAKE)
mkdir -p build && cd build && cmake -D ARCH="x86-64" -D DEV_MODE=$(or ${DEV_MODE},ON) -DMANUAL_SUBMODULES=${MANUAL_SUBMODULES} -D WITH_SCANNER=ON -D BUILD_64=ON -D CMAKE_BUILD_TYPE=Release .. && $(MAKE)
release:
mkdir -p $(builddir)/release && cd $(builddir)/release && cmake -D DEV_MODE=$(or ${DEV_MODE},OFF) -D ARCH="x86-64" -D CMAKE_BUILD_TYPE=Release $(topdir) && $(MAKE)
mkdir -p $(builddir)/release && cd $(builddir)/release && cmake -D DEV_MODE=$(or ${DEV_MODE},OFF) -DMANUAL_SUBMODULES=${MANUAL_SUBMODULES} -D ARCH="x86-64" -D CMAKE_BUILD_TYPE=Release $(topdir) && $(MAKE)
release-linux-armv8:
mkdir -p $(builddir)/release
@@ -42,17 +53,17 @@ release-linux-armv8:
cmake -D DEV_MODE=$(or ${DEV_MODE},OFF) -D ARCH="armv8-a" -D BUILD_64=ON -D CMAKE_BUILD_TYPE=Release -D BUILD_TAG="linux-armv8" $(topdir) && $(MAKE)
release-static:
mkdir -p $(builddir)/release && cd $(builddir)/release && cmake -D STATIC=ON -D DEV_MODE=$(or ${DEV_MODE},OFF) -D ARCH="x86-64" -D BUILD_64=ON -D CMAKE_BUILD_TYPE=Release $(topdir) && $(MAKE)
mkdir -p $(builddir)/release && cd $(builddir)/release && cmake -D STATIC=ON -D DEV_MODE=$(or ${DEV_MODE},OFF) -DMANUAL_SUBMODULES=${MANUAL_SUBMODULES} -D ARCH="x86-64" -D BUILD_64=ON -D CMAKE_BUILD_TYPE=Release $(topdir) && $(MAKE)
debug-static-win64:
mkdir -p $(builddir)/debug && cd $(builddir)/debug && cmake -D STATIC=ON -G "MSYS Makefiles" -D DEV_MODE=$(or ${DEV_MODE},ON) -D ARCH="x86-64" -D BUILD_64=ON -D CMAKE_BUILD_TYPE=Debug -D BUILD_TAG="win-x64" -D CMAKE_TOOLCHAIN_FILE=$(topdir)/cmake/64-bit-toolchain.cmake -D MSYS2_FOLDER=$(shell cd ${MINGW_PREFIX}/.. && pwd -W) -D MINGW=ON $(topdir) && $(MAKE)
mkdir -p $(builddir)/debug && cd $(builddir)/debug && cmake -D STATIC=ON -G "MSYS Makefiles" -D DEV_MODE=$(or ${DEV_MODE},ON) -DMANUAL_SUBMODULES=${MANUAL_SUBMODULES} -D ARCH="x86-64" -D BUILD_64=ON -D CMAKE_BUILD_TYPE=Debug -D BUILD_TAG="win-x64" -D CMAKE_TOOLCHAIN_FILE=$(topdir)/cmake/64-bit-toolchain.cmake -D MSYS2_FOLDER=$(shell cd ${MINGW_PREFIX}/.. && pwd -W) -D MINGW=ON $(topdir) && $(MAKE)
debug-static-mac64:
mkdir -p $(builddir)/debug
cd $(builddir)/debug && cmake -D STATIC=ON -D DEV_MODE=$(or ${DEV_MODE},ON) -D ARCH="x86-64" -D BUILD_64=ON -D CMAKE_BUILD_TYPE=release -D BUILD_TAG="mac-x64" $(topdir) && $(MAKE)
cd $(builddir)/debug && cmake -D STATIC=ON -D DEV_MODE=$(or ${DEV_MODE},ON) -DMANUAL_SUBMODULES=${MANUAL_SUBMODULES} -D ARCH="x86-64" -D BUILD_64=ON -D CMAKE_BUILD_TYPE=release -D BUILD_TAG="mac-x64" $(topdir) && $(MAKE)
release-static-win64:
mkdir -p $(builddir)/release && cd $(builddir)/release && cmake -D STATIC=ON -G "MSYS Makefiles" -D DEV_MODE=$(or ${DEV_MODE},OFF) -D ARCH="x86-64" -D BUILD_64=ON -D CMAKE_BUILD_TYPE=Release -D BUILD_TAG="win-x64" -D CMAKE_TOOLCHAIN_FILE=$(topdir)/cmake/64-bit-toolchain.cmake -D MSYS2_FOLDER=$(shell cd ${MINGW_PREFIX}/.. && pwd -W) -D MINGW=ON $(topdir) && $(MAKE)
mkdir -p $(builddir)/release && cd $(builddir)/release && cmake -D STATIC=ON -G "MSYS Makefiles" -D DEV_MODE=$(or ${DEV_MODE},OFF) -DMANUAL_SUBMODULES=${MANUAL_SUBMODULES} -D ARCH="x86-64" -D BUILD_64=ON -D CMAKE_BUILD_TYPE=Release -D BUILD_TAG="win-x64" -D CMAKE_TOOLCHAIN_FILE=$(topdir)/cmake/64-bit-toolchain.cmake -D MSYS2_FOLDER=$(shell cd ${MINGW_PREFIX}/.. && pwd -W) -D MINGW=ON $(topdir) && $(MAKE)
release-win64:
mkdir -p $(builddir)/release && cd $(builddir)/release && cmake -D STATIC=OFF -G "MSYS Makefiles" -D DEV_MODE=$(or ${DEV_MODE},OFF) -D ARCH="x86-64" -D BUILD_64=ON -D CMAKE_BUILD_TYPE=Release -D BUILD_TAG="win-x64" -D CMAKE_TOOLCHAIN_FILE=$(topdir)/cmake/64-bit-toolchain.cmake -D MSYS2_FOLDER=$(shell cd ${MINGW_PREFIX}/.. && pwd -W) -D MINGW=ON $(topdir) && $(MAKE)
mkdir -p $(builddir)/release && cd $(builddir)/release && cmake -D STATIC=OFF -G "MSYS Makefiles" -D DEV_MODE=$(or ${DEV_MODE},OFF) -DMANUAL_SUBMODULES=${MANUAL_SUBMODULES} -D ARCH="x86-64" -D BUILD_64=ON -D CMAKE_BUILD_TYPE=Release -D BUILD_TAG="win-x64" -D CMAKE_TOOLCHAIN_FILE=$(topdir)/cmake/64-bit-toolchain.cmake -D MSYS2_FOLDER=$(shell cd ${MINGW_PREFIX}/.. && pwd -W) -D MINGW=ON $(topdir) && $(MAKE)

View File

@@ -51,22 +51,19 @@ Rectangle {
property alias flickable: mainFlickable
property Transfer transferView: Transfer {
onPaymentClicked: root.paymentClicked(address, paymentId, amount, mixinCount, priority, description)
onPaymentClicked: root.paymentClicked(recipients, paymentId, mixinCount, priority, description)
onSweepUnmixableClicked: root.sweepUnmixableClicked()
}
property Receive receiveView: Receive { }
property Merchant merchantView: Merchant { }
property TxKey txkeyView: TxKey { }
property SharedRingDB sharedringdbView: SharedRingDB { }
property History historyView: History { }
property Sign signView: Sign { }
property Advanced advancedView: Advanced { }
property Settings settingsView: Settings { }
property Mining miningView: Mining { }
property AddressBook addressBookView: AddressBook { }
property Keys keysView: Keys { }
property Account accountView: Account { }
signal paymentClicked(string address, string paymentId, string amount, int mixinCount, int priority, string description)
signal paymentClicked(var recipients, string paymentId, int mixinCount, int priority, string description)
signal sweepUnmixableClicked()
signal generatePaymentIdInvoked()
signal getProofClicked(string txid, string address, string message);
@@ -136,30 +133,18 @@ Rectangle {
name: "Merchant"
PropertyChanges { target: root; currentView: merchantView }
PropertyChanges { target: mainFlickable; contentHeight: merchantView.merchantHeight + 80 }
}, State {
name: "TxKey"
PropertyChanges { target: root; currentView: txkeyView }
PropertyChanges { target: mainFlickable; contentHeight: txkeyView.txkeyHeight + 80 }
}, State {
name: "SharedRingDB"
PropertyChanges { target: root; currentView: sharedringdbView }
PropertyChanges { target: mainFlickable; contentHeight: sharedringdbView.panelHeight + 80 }
}, State {
name: "AddressBook"
PropertyChanges { target: root; currentView: addressBookView }
PropertyChanges { target: mainFlickable; contentHeight: addressBookView.addressbookHeight + 80 }
}, State {
name: "Sign"
PropertyChanges { target: root; currentView: signView }
PropertyChanges { target: mainFlickable; contentHeight: signView.signHeight + 80 }
name: "Advanced"
PropertyChanges { target: root; currentView: advancedView }
PropertyChanges { target: mainFlickable; contentHeight: advancedView.panelHeight }
}, State {
name: "Settings"
PropertyChanges { target: root; currentView: settingsView }
PropertyChanges { target: mainFlickable; contentHeight: settingsView.settingsHeight }
}, State {
name: "Mining"
PropertyChanges { target: root; currentView: miningView }
PropertyChanges { target: mainFlickable; contentHeight: miningView.miningHeight + 80 }
}, State {
name: "Keys"
PropertyChanges { target: root; currentView: keysView }
@@ -168,7 +153,7 @@ Rectangle {
name: "Account"
PropertyChanges { target: root; currentView: accountView }
PropertyChanges { target: mainFlickable; contentHeight: accountView.accountHeight + 80 }
}
}
]
ColumnLayout {

View File

@@ -72,7 +72,7 @@ Packages are available for
* Debian: See the [whonix/monero-gui repository](https://gitlab.com/whonix/monero-gui#how-to-install-monero-using-apt-get)
* Void Linux: `xbps-install -S monero-gui`
* GuixSD: `guix package -i monero-gui`
* macOS (homebrew): `brew cask install monero-wallet`
* macOS (homebrew): `brew install --cask monero-wallet`
Packaging for your favorite distribution would be a welcome contribution!
@@ -80,13 +80,14 @@ Packaging for your favorite distribution would be a welcome contribution!
*Note*: Qt 5.9.7 is the minimum version required to build the GUI.
### Building Windows static binaries with Docker (any OS)
### Building Reproducible Windows static binaries with Docker (any OS)
1. Install Docker [https://docs.docker.com/engine/install/](https://docs.docker.com/engine/install/)
2. Clone the repository
```
git clone --recursive https://github.com/monero-project/monero-gui.git
git clone --branch master --recursive https://github.com/monero-project/monero-gui.git
```
\* `master` - replace with the desired version tag (e.g. `v0.17.1.9`) to build the release binaries.
3. Prepare build environment
```
cd monero-gui
@@ -102,13 +103,14 @@ Packaging for your favorite distribution would be a welcome contribution!
\* `4` - number of CPU threads to use
5. Monero GUI Windows static binaries will be placed in `monero-gui/build/x86_64-w64-mingw32/release/bin` directory
### Building Linux static binaries with Docker (any OS)
### Building Reproducible Linux static binaries with Docker (any OS)
1. Install Docker [https://docs.docker.com/engine/install/](https://docs.docker.com/engine/install/)
2. Clone the repository
```
git clone --recursive https://github.com/monero-project/monero-gui.git
git clone --branch master --recursive https://github.com/monero-project/monero-gui.git
```
\* `master` - replace with the desired version tag (e.g. `v0.17.1.9`) to build the release binaries.
3. Prepare build environment
```
cd monero-gui
@@ -123,6 +125,60 @@ Packaging for your favorite distribution would be a welcome contribution!
\* `<MONERO_GUI_DIR_FULL_PATH>` - absolute path to `monero-gui` directory
\* `4` - number of CPU threads to use
5. Monero GUI Linux static binaries will be placed in `monero-gui/build/release/bin` directory
6. (*Optional*) Compare `monero-wallet-gui` SHA-256 hash to the one obtained from a trusted source
```
docker run --rm -it -v <MONERO_GUI_DIR_FULL_PATH>:/monero-gui -w /monero-gui monero:build-env-linux sh -c 'shasum -a 256 /monero-gui/build/release/bin/monero-wallet-gui'
```
\* `<MONERO_GUI_DIR_FULL_PATH>` - absolute path to `monero-gui` directory
### Building Android APK with Docker (any OS) *Experimental*
- Minimum Android 9 Pie (API 28)
- ARMv8-A 64-bit CPU
1. Install Docker [https://docs.docker.com/engine/install/](https://docs.docker.com/engine/install/)
2. Clone the repository
```
git clone --recursive https://github.com/monero-project/monero-gui.git
```
3. Prepare build environment
```
cd monero-gui
docker build --tag monero:build-env-android --build-arg THREADS=4 --file Dockerfile.android .
```
\* `4` - number of CPU threads to use
4. Build
```
docker run --rm -it -v <MONERO_GUI_DIR_FULL_PATH>:/monero-gui -e THREADS=4 monero:build-env-android
```
\* `<MONERO_GUI_DIR_FULL_PATH>` - absolute path to `monero-gui` directory
\* `4` - number of CPU threads to use
5. Monero GUI APK will be placed in `monero-gui/build/Android/release/android-build` directory
6. Deploy
* Using ADB (Android debugger bridge)
- [Enable adb debugging on your device](https://developer.android.com/studio/command-line/adb.html#Enabling)
* Connect your device with USB and install Monero GUI APK with adb:
```
adb install build/Android/release/android-build/monero-gui.apk
```
* Troubleshooting:
```
adb devices -l
adb logcat
```
* If using adb inside docker, make sure you did
```
docker run -v /dev/bus/usb:/dev/bus/usb --privileged
```
* Using a web server
```
mkdir /usr/tmp
cp build/Android/release/android-build/monero-gui.apk /usr/tmp
docker run -d -v /usr/tmp:/usr/share/nginx/html:ro -p 8080:80 nginx
```
Now it should be accessible through a web browser at
```
http://<your.local.ip>:8080/QtApp-debug.apk
```
### On Linux:
@@ -152,7 +208,7 @@ The following instructions will fetch Qt from your distribution's repositories i
- For Ubuntu 17.10+
`sudo apt 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`
`sudo apt install qtbase5-dev qt5-default qtdeclarative5-dev qml-module-qtqml-models2 qml-module-qtquick-controls qml-module-qtquick-controls2 qml-module-qtquick-dialogs qml-module-qtquick-xmllistmodel qml-module-qt-labs-settings qml-module-qt-labs-folderlistmodel qttools5-dev-tools qml-module-qtquick-templates2 libqt5svg5-dev`
- For Gentoo
@@ -162,13 +218,13 @@ The following instructions will fetch Qt from your distribution's repositories i
- For Ubuntu
`sudo apt install qtmultimedia5-dev qml-module-qtmultimedia libzbar-dev`
`sudo apt install qtmultimedia5-dev qml-module-qtmultimedia`
- For Gentoo
The *qml* USE flag must be enabled.
`emerge dev-qt/qtmultimedia:5 media-gfx/zbar`
`emerge dev-qt/qtmultimedia:5`
3. Clone repository
@@ -196,7 +252,7 @@ The executable can be found in the build/release/bin folder.
3. Install [monero](https://github.com/monero-project/monero) dependencies:
`brew install boost hidapi zmq libpgm miniupnpc ldns expat libunwind-headers protobuf libgcrypt`
`brew install boost hidapi zmq libpgm libsodium miniupnpc ldns expat libunwind-headers protobuf libgcrypt`
4. Install Qt:
@@ -235,12 +291,6 @@ The Monero GUI on Windows is 64 bits only; 32-bit Windows GUI builds are not off
pacman -S mingw-w64-x86_64-toolchain make mingw-w64-x86_64-cmake mingw-w64-x86_64-boost mingw-w64-x86_64-openssl mingw-w64-x86_64-zeromq mingw-w64-x86_64-libsodium mingw-w64-x86_64-hidapi mingw-w64-x86_64-protobuf-c mingw-w64-x86_64-libusb mingw-w64-x86_64-libgcrypt
```
Optional : To build the flag `WITH_SCANNER`
```
pacman -S mingw-w64-x86_64-zbar
```
You find more details about those dependencies in the [Monero documentation](https://github.com/monero-project/monero). Note that that there is no more need to compile Boost from source; like everything else, you can install it now with a MSYS2 package.
4. Install Qt5

View File

@@ -1,53 +0,0 @@
Copyright (c) 2014-2018, The Monero Project
## Current status : ALPHA
- Minimum Android 5.0 (api level 21)
- Modal dialogs can appear in background giving the feeling that the application is frozen (Work around : turn screen off/on or switch to another app and back)
## Build using Docker
# Base environnement
cd monero/utils/build_scripts
docker build -f android32.Dockerfile -t monero-android .
cd ..
# Build GUI
cd android/docker
docker build -t monero-gui-android .
docker create -it --name monero-gui-android monero-gui-android bash
# Get the apk
docker cp monero-gui-android:/opt/android/monero-gui/build/release/bin/bin/QtApp-debug.apk .
## Deployment
- Using ADB (Android debugger bridge) :
First, see section [Enable adb debugging on your device](https://developer.android.com/studio/command-line/adb.html#Enabling)
The only place where we are allowed to play is `/data/local/tmp`. So :
adb push /opt/android/monero-gui/build/release/bin/bin/QtApp-debug.apk /data/local/tmp
adb shell pm install -r /data/local/tmp/QtApp-debug.apk
- Troubleshooting:
adb devices -l
adb logcat
if using adb inside docker, make sure you did "docker run -v /dev/bus/usb:/dev/bus/usb --privileged"
- Using a web server
mkdir /usr/tmp
cp QtApp-debug.apk /usr/tmp
docker run -d -v /usr/tmp:/usr/share/nginx/html:ro -p 8080:80 nginx
Now it should be accessible through a web browser at
http://<your.local.ip>:8080/QtApp-debug.apk

View File

@@ -1,107 +0,0 @@
FROM monero-android
#INSTALL JAVA
RUN echo "deb http://ftp.fr.debian.org/debian/ jessie-backports main contrib non-free" >> /etc/apt/sources.list
RUN dpkg --add-architecture i386 \
&& apt-get update \
&& apt-get install -y libc6:i386 libncurses5:i386 libstdc++6:i386 libz1:i386 \
&& apt-get install -y -t jessie-backports ca-certificates-java openjdk-8-jdk-headless openjdk-8-jre-headless ant
ENV JAVA_HOME /usr/lib/jvm/java-8-openjdk-amd64
ENV PATH $JAVA_HOME/bin:$PATH
#Get Qt
ENV QT_VERSION 5.8
RUN git clone git://code.qt.io/qt/qt5.git -b ${QT_VERSION} \
&& cd qt5 \
&& perl init-repository
## Note: Need to use libc++ but Qt does not provide mkspec for libc++.
## Their support of it is quite recent and they claim they don't use it by default
## [only because it produces bigger binary objects](https://bugreports.qt.io/browse/QTBUG-50724).
#Create new mkspec for clang + libc++
RUN cp -r qt5/qtbase/mkspecs/android-clang qt5/qtbase/mkspecs/android-clang-libc \
&& cd qt5/qtbase/mkspecs/android-clang-libc \
&& sed -i '16i ANDROID_SOURCES_CXX_STL_LIBDIR = $$NDK_ROOT/sources/cxx-stl/llvm-libc++/libs/$$ANDROID_TARGET_ARCH' qmake.conf \
&& sed -i '17i ANDROID_SOURCES_CXX_STL_INCDIR = $$NDK_ROOT/sources/cxx-stl/llvm-libc++/include' qmake.conf \
&& echo "QMAKE_LIBS_PRIVATE = -lc++_shared -llog -lz -lm -ldl -lc -lgcc " >> qmake.conf \
&& echo "QMAKE_CFLAGS -= -mfpu=vfp " >> qmake.conf \
&& echo "QMAKE_CXXFLAGS -= -mfpu=vfp " >> qmake.conf \
&& echo "QMAKE_CFLAGS += -mfpu=vfp4 " >> qmake.conf \
&& echo "QMAKE_CXXFLAGS += -mfpu=vfp4 " >> qmake.conf
ENV ANDROID_API android-21
#ANDROID SDK TOOLS
RUN echo y | $ANDROID_SDK_ROOT/tools/android update sdk --no-ui --all --filter platform-tools
RUN echo y | $ANDROID_SDK_ROOT/tools/android update sdk --no-ui --all --filter ${ANDROID_API}
RUN echo y | $ANDROID_SDK_ROOT/tools/android update sdk --no-ui --all --filter build-tools-25.0.1
ENV CLEAN_PATH $JAVA_HOME/bin:/usr/cmake-3.6.3-Linux-x86_64/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
#build Qt
RUN cd qt5 && PATH=${CLEAN_PATH} ./configure -developer-build -release \
-xplatform android-clang-libc \
-android-ndk-platform ${ANDROID_API} \
-android-ndk $ANDROID_NDK_ROOT \
-android-sdk $ANDROID_SDK_ROOT \
-opensource -confirm-license \
-prefix ${WORKDIR}/Qt-${QT_VERSION} \
-nomake tests -nomake examples \
-skip qtserialport \
-skip qtconnectivity \
-skip qttranslations \
-skip qtgamepad -skip qtscript -skip qtdoc
# build Qt tools : gnustl_shared.so is hard-coded in androiddeployqt
# replace it with libc++_shared.so
COPY androiddeployqt.patch qt5/qttools/androiddeployqt.patch
RUN cd qt5/qttools \
&& git apply androiddeployqt.patch \
&& cd .. \
&& PATH=${CLEAN_PATH} make -j4 \
&& PATH=${CLEAN_PATH} make install
# Get iconv and ZBar
ENV ICONV_VERSION 1.14
RUN git clone https://github.com/ZBar/ZBar.git \
&& curl -s -O http://ftp.gnu.org/pub/gnu/libiconv/libiconv-${ICONV_VERSION}.tar.gz \
&& tar -xzf libiconv-${ICONV_VERSION}.tar.gz \
&& cd libiconv-${ICONV_VERSION} \
&& CC=arm-linux-androideabi-clang CXX=arm-linux-androideabi-clang++ ./configure --build=x86_64-linux-gnu --host=arm-eabi --prefix=${WORKDIR}/libiconv --disable-rpath
ENV PATH $ANDROID_SDK_ROOT/tools:$ANDROID_SDK_ROOT/platform-tools:${WORKDIR}/Qt-${QT_VERSION}/bin:$PATH
#Build libiconv.a and libzbarjni.a
COPY android.mk.patch ZBar/android.mk.patch
RUN cd ZBar \
&& git apply android.mk.patch \
&& echo \
"APP_ABI := armeabi-v7a \n\
APP_STL := c++_shared \n\
TARGET_PLATFORM := ${ANDROID_API} \n\
TARGET_ARCH_ABI := armeabi-v7a \n\
APP_CFLAGS += -target armv7-none-linux-androideabi -fexceptions -fstack-protector-strong -fno-limit-debug-info -mfloat-abi=softfp -mfpu=vfp -fno-builtin-memmove -fno-omit-frame-pointer -fno-stack-protector\n"\
>> android/jni/Application.mk \
&& cd android \
&& android update project --path . -t "${ANDROID_API}" \
&& CC=arm-linux-androideabi-clang CXX=arm-linux-androideabi-clang++ ant -Dndk.dir=${ANDROID_NDK_ROOT} -Diconv.src=${WORKDIR}/libiconv-${ICONV_VERSION} zbar-clean zbar-ndk-build
RUN cp openssl/lib* ${ANDROID_NDK_ROOT}/platforms/${ANDROID_API}/arch-arm/usr/lib
RUN cp boost_${BOOST_VERSION}/android32/lib/lib* ${ANDROID_NDK_ROOT}/platforms/${ANDROID_API}/arch-arm/usr/lib
RUN cp ZBar/android/obj/local/armeabi-v7a/lib* ${ANDROID_NDK_ROOT}/platforms/${ANDROID_API}/arch-arm/usr/lib
RUN git clone https://github.com/monero-project/monero-gui.git \
&& cd monero-gui \
&& git submodule update \
&& CC=arm-linux-androideabi-clang CXX=arm-linux-androideabi-clang++ BOOST_ROOT=/opt/android/boost_1_62_0 \
BOOST_LIBRARYDIR=${WORKDIR}/boost_${BOOST_VERSION}/android32/lib/ \
OPENSSL_ROOT_DIR=${WORKDIR}/openssl/ \
CMAKE_INCLUDE_PATH=${WORKDIR}/cppzmq/ \
CMAKE_LIBRARY_PATH=${WORKDIR}/zeromq4-1/.libs \
CXXFLAGS="-I ${WORKDIR}/zeromq4-1/include/" \
./build.sh release-android \
&& cd build \
&& make deploy

View File

@@ -1,61 +0,0 @@
diff --git a/android/jni/Android.mk b/android/jni/Android.mk
index e442b07..158afd5 100644
--- a/android/jni/Android.mk
+++ b/android/jni/Android.mk
@@ -12,14 +12,18 @@ LOCAL_PATH := $(ICONV_SRC)
LOCAL_MODULE := libiconv
+LOCAL_ARM_MODE := arm
+LOCAL_CPP_FEATURES := exceptions rtti features
LOCAL_CFLAGS := \
-Wno-multichar \
-D_ANDROID \
- -DLIBDIR="c" \
+ -DLIBDIR="\".\"" \
-DBUILDING_LIBICONV \
-DBUILDING_LIBCHARSET \
-DIN_LIBRARY
+LOCAL_CFLAGS += -fno-stack-protector
+
LOCAL_SRC_FILES := \
lib/iconv.c \
libcharset/lib/localcharset.c \
@@ -30,13 +34,14 @@ LOCAL_C_INCLUDES := \
$(ICONV_SRC)/libcharset \
$(ICONV_SRC)/libcharset/include
-include $(BUILD_SHARED_LIBRARY)
+include $(BUILD_STATIC_LIBRARY)
LOCAL_LDLIBS := -llog -lcharset
# libzbarjni
include $(CLEAR_VARS)
+
LOCAL_PATH := $(MY_LOCAL_PATH)
LOCAL_MODULE := zbarjni
LOCAL_SRC_FILES := ../../java/zbarjni.c \
@@ -71,6 +76,17 @@ LOCAL_C_INCLUDES := ../include \
../zbar \
$(ICONV_SRC)/include
-LOCAL_SHARED_LIBRARIES := libiconv
+LOCAL_STATIC_LIBRARIES := libiconv
+LOCAL_ARM_MODE := arm
+LOCAL_CPP_FEATURES := exceptions rtti features
+
+LOCAL_CFLAGS := \
+ -Wno-multichar \
+ -D_ANDROID \
+ -DLIBDIR="\".\"" \
+ -DBUILDING_LIBICONV \
+ -DBUILDING_LIBCHARSET \
+ -DIN_LIBRARY
+
-include $(BUILD_SHARED_LIBRARY)
\ No newline at end of file
+include $(BUILD_STATIC_LIBRARY)

View File

@@ -1,62 +0,0 @@
diff --git a/src/androiddeployqt/main.cpp b/src/androiddeployqt/main.cpp
index 8a8e591..71d693e 100644
--- a/src/androiddeployqt/main.cpp
+++ b/src/androiddeployqt/main.cpp
@@ -1122,7 +1122,7 @@ bool updateLibsXml(const Options &options)
QString libsPath = QLatin1String("libs/") + options.architecture + QLatin1Char('/');
- QString qtLibs = QLatin1String("<item>gnustl_shared</item>\n");
+ QString qtLibs = QLatin1String("<item>c++_shared</item>\n");
QString bundledInLibs;
QString bundledInAssets;
foreach (Options::BundledFile bundledFile, options.bundledFiles) {
@@ -2519,6 +2519,39 @@ bool installApk(const Options &options)
return true;
}
+bool copyStl(Options *options)
+{
+ if (options->deploymentMechanism == Options::Debug && !options->installApk)
+ return true;
+
+ if (options->verbose)
+ fprintf(stdout, "Copying LIBC++ STL library\n");
+
+ QString filePath = options->ndkPath
+ + QLatin1String("/sources/cxx-stl/llvm-libc++")
+ + QLatin1String("/libs/")
+ + options->architecture
+ + QLatin1String("/libc++_shared.so");
+ if (!QFile::exists(filePath)) {
+ fprintf(stderr, "LIBC STL library does not exist at %s\n", qPrintable(filePath));
+ return false;
+ }
+
+ QString destinationDirectory =
+ options->deploymentMechanism == Options::Debug
+ ? options->temporaryDirectoryName + QLatin1String("/lib")
+ : options->outputDirectory + QLatin1String("/libs/") + options->architecture;
+
+ if (!copyFileIfNewer(filePath, destinationDirectory
+ + QLatin1String("/libc++_shared.so"), options->verbose)) {
+ return false;
+ }
+
+ if (options->deploymentMechanism == Options::Debug && !deployToLocalTmp(options, QLatin1String("/lib/libc++_shared.so")))
+ return false;
+
+ return true;
+}
bool copyGnuStl(Options *options)
{
if (options->deploymentMechanism == Options::Debug && !options->installApk)
@@ -2870,7 +2903,7 @@ int main(int argc, char *argv[])
if (Q_UNLIKELY(options.timing))
fprintf(stdout, "[TIMING] %d ms: Read dependencies\n", options.timer.elapsed());
- if (options.deploymentMechanism != Options::Ministro && !copyGnuStl(&options))
+ if (options.deploymentMechanism != Options::Ministro && !copyStl(&options))
return CannotCopyGnuStl;
if (Q_UNLIKELY(options.timing))

121
build.sh
View File

@@ -1,121 +0,0 @@
#!/bin/bash
BUILD_TYPE=$1
BUILD_TREZOR=${BUILD_TREZOR-true}
source ./utils.sh
platform=$(get_platform)
# default build type
if [ -z $BUILD_TYPE ]; then
BUILD_TYPE=release
fi
# Return 0 if the command exists, 1 if it does not.
exists() {
command -v "$1" &>/dev/null
}
# Return the first value in $@ that's a runnable command.
find_command() {
for arg in "$@"; do
if exists "$arg"; then
echo "$arg"
return 0
fi
done
return 1
}
if [ "$BUILD_TYPE" == "release" ]; then
echo "Building release"
CONFIG="CONFIG+=release";
BIN_PATH=release/bin
elif [ "$BUILD_TYPE" == "release-static" ]; then
echo "Building release-static"
if [ "$platform" != "darwin" ]; then
CONFIG="CONFIG+=release static";
else
# OS X: build static libwallet but dynamic Qt.
echo "OS X: Building Qt project without static flag"
CONFIG="CONFIG+=release";
fi
BIN_PATH=release/bin
elif [ "$BUILD_TYPE" == "release-android" ]; then
echo "Building release for ANDROID"
CONFIG="CONFIG+=release static WITH_SCANNER DISABLE_PASS_STRENGTH_METER";
ANDROID=true
BIN_PATH=release/bin
DISABLE_PASS_STRENGTH_METER=true
elif [ "$BUILD_TYPE" == "debug-android" ]; then
echo "Building debug for ANDROID : ultra INSECURE !!"
CONFIG="CONFIG+=debug qml_debug WITH_SCANNER DISABLE_PASS_STRENGTH_METER";
ANDROID=true
BIN_PATH=debug/bin
DISABLE_PASS_STRENGTH_METER=true
elif [ "$BUILD_TYPE" == "debug" ]; then
echo "Building debug"
CONFIG="CONFIG+=debug"
BIN_PATH=debug/bin
else
echo "Valid build types are release, release-static, release-android, debug-android and debug"
exit 1;
fi
source ./utils.sh
pushd $(pwd)
ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
MONERO_DIR=monero
MONEROD_EXEC=monerod
MAKE='make'
if [[ $platform == *bsd* ]]; then
MAKE='gmake'
fi
# build libwallet
export BUILD_TREZOR
./get_libwallet_api.sh $BUILD_TYPE
# build zxcvbn
if [ "$DISABLE_PASS_STRENGTH_METER" != true ]; then
$MAKE -C src/zxcvbn-c || exit
fi
if [ ! -d build ]; then mkdir build; fi
# Platform indepenent settings
if [ "$ANDROID" != true ] && ([ "$platform" == "linux32" ] || [ "$platform" == "linux64" ]); then
exists lsb_release && distro="$(lsb_release -is)"
if [ "$distro" = "Ubuntu" ] || [ "$distro" = "Fedora" ] || test -f /etc/fedora-release; then
CONFIG="$CONFIG libunwind_off"
fi
fi
if [ "$platform" == "darwin" ]; then
BIN_PATH=$BIN_PATH/monero-wallet-gui.app/Contents/MacOS/
elif [ "$platform" == "mingw64" ] || [ "$platform" == "mingw32" ]; then
MONEROD_EXEC=monerod.exe
fi
# force version update
get_tag
GUI_VERSION=$(echo "$TAGNAME" | sed 's/^v\([[:digit:]]\)/\1/')
echo "var GUI_VERSION = \"$GUI_VERSION\"" > version.js
cd build
if ! QMAKE=$(find_command qmake qmake-qt5); then
echo "Failed to find suitable qmake command."
exit 1
fi
$QMAKE ../monero-wallet-gui.pro "$CONFIG" || exit
$MAKE || exit
# Copy monerod to bin folder
if [ "$platform" != "mingw32" ] && [ "$ANDROID" != true ]; then
cp ../$MONERO_DIR/bin/$MONEROD_EXEC $BIN_PATH
fi
# make deploy
popd

View File

@@ -1,22 +0,0 @@
# from http://code.google.com/p/low-cost-vision-2012/source/browse/CMakeModules/FindZBar0.cmake?name=2-helium-1&r=d61f248bd5565b3c086bf4769a04bfd98f7079df
# - Try to find ZBar
# This will define
#
# ZBAR_FOUND -
# ZBAR_LIBRARY_DIR -
# ZBAR_INCLUDE_DIR -
# ZBAR_LIBRARIES -
#
find_package(PkgConfig)
pkg_check_modules(PC_ZBAR QUIET zbar)
set(ZBAR_DEFINITIONS ${PC_ZBAR_CFLAGS_OTHER})
find_library(ZBAR_LIBRARIES NAMES zbar
HINTS ${PC_ZBAR_LIBDIR} ${PC_ZBAR_LIBRARY_DIRS} )
find_path(ZBAR_INCLUDE_DIR Decoder.h
HINTS ${PC_ZBAR_INCLUDEDIR} ${PC_ZBAR_INCLUDE_DIRS}
PATH_SUFFIXES zbar )
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(ZBAR DEFAULT_MSG ZBAR_LIBRARIES ZBAR_INCLUDE_DIR)
message(STATUS "Found zbar libraries ${ZBAR_LIBRARIES}")

View File

@@ -49,8 +49,14 @@ Item {
property alias fontColor: label.color
property bool iconOnTheLeft: true
signal clicked()
height: 25
width: checkBoxLayout.width
opacity: enabled ? 1 : 0.7
Keys.onEnterPressed: toggle()
Keys.onReturnPressed: Keys.onEnterPressed(event)
Keys.onSpacePressed: Keys.onEnterPressed(event)
function toggle(){
if (checkBox.toggleOnClick) {
@@ -76,7 +82,7 @@ Item {
radius: 3
color: checkBox.enabled ? "transparent" : MoneroComponents.Style.inputBoxBackgroundDisabled
border.color:
if(checkBox.checked){
if (checkBox.activeFocus) {
return MoneroComponents.Style.inputBorderColorActive;
} else {
return MoneroComponents.Style.inputBorderColorInActive;

View File

@@ -52,6 +52,7 @@ Window {
// TODO: implement without hardcoding sizes
width: 480
height: 200
color: MoneroComponents.Style.middlePanelBackgroundColor
// Make window draggable
MouseArea {
@@ -96,7 +97,7 @@ Window {
Layout.fillWidth: true
horizontalAlignment: Text.AlignHCenter
themeTransition: false
color: "black"
color: MoneroComponents.Style.defaultFontColor
}
}

66
components/Dialog.qml Normal file
View File

@@ -0,0 +1,66 @@
// Copyright (c) 2021, The Monero Project
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import QtQuick 2.9
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.1
import "." as MoneroComponents
Popup {
id: dialog
default property alias content: mainLayout.children
property alias title: header.text
background: Rectangle {
border.color: MoneroComponents.Style.blackTheme ? Qt.rgba(255, 255, 255, 0.25) : Qt.rgba(0, 0, 0, 0.25)
border.width: 1
color: MoneroComponents.Style.blackTheme ? "black" : "white"
radius: 10
}
closePolicy: Popup.CloseOnEscape
focus: true
padding: 20
x: (appWindow.width - width) / 2
y: (appWindow.height - height) / 2
ColumnLayout {
id: mainLayout
spacing: dialog.padding
Text {
id: header
color: MoneroComponents.Style.defaultFontColor
font.bold: true
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 18
visible: text != ""
}
}
}

View File

@@ -30,30 +30,25 @@ import QtQuick 2.9
import QtQuick.Layouts 1.1
import QtGraphicalEffects 1.0
import FontAwesome 1.0
import "." as MoneroComponents
import "./effects/" as MoneroEffects
Item {
id: inlineButton
height: parent.height
anchors.top: parent.top
anchors.bottom: parent.bottom
property bool small: false
property string shadowPressedColor: "#B32D00"
property string shadowReleasedColor: "#FF4304"
property string pressedColor: "#FF4304"
property string releasedColor: "#FF6C3C"
property string icon: ""
property string textColor: MoneroComponents.Style.inlineButtonTextColor
property int fontSize: small ? 14 : 16
property int rectHeight: small ? 24 : 24
property int rectHMargin: small ? 16 : 22
property alias text: inlineText.text
property alias fontPixelSize: inlineText.font.pixelSize
property alias fontFamily: inlineText.font.family
property bool isFontAwesomeIcon: fontFamily == FontAwesome.fontFamily || fontFamily == FontAwesome.fontFamilySolid
property alias buttonColor: rect.color
property alias buttonHeight: rect.height
height: isFontAwesomeIcon ? 30 : 24
width: isFontAwesomeIcon ? height : inlineText.width + 16
signal clicked()
function doClick() {
@@ -64,20 +59,16 @@ Item {
Rectangle{
id: rect
anchors.fill: parent
color: MoneroComponents.Style.buttonInlineBackgroundColor
height: 24
width: inlineText.text ? (inlineText.width + 16) : inlineButton.icon ? (inlineImage.width + 16) : rect.height
radius: 4
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
anchors.rightMargin: 4
MoneroComponents.TextPlain {
id: inlineText
font.family: MoneroComponents.Style.fontBold.name
font.bold: true
font.pixelSize: inlineButton.fontSize
font.pixelSize: inlineButton.isFontAwesomeIcon ? 22 : inlineButton.small ? 14 : 16
color: inlineButton.textColor
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
@@ -90,13 +81,6 @@ Item {
}
}
Image {
id: inlineImage
visible: inlineButton.icon !== ""
anchors.centerIn: parent
source: inlineButton.icon
}
MouseArea {
id: buttonArea
cursorShape: rect.enabled ? Qt.PointingHandCursor : Qt.ArrowCursor

View File

@@ -0,0 +1,67 @@
// Copyright (c) 2020, The Monero Project
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import QtQuick 2.9
import QtQuick.Layouts 1.3
import FontAwesome 1.0
import "../components" as MoneroComponents
Item {
implicitHeight: layout.height
implicitWidth: layout.width
RowLayout {
id: layout
opacity: mouseArea.containsMouse ? 1 : 0.85
spacing: 10
MoneroComponents.Label {
Layout.bottomMargin: 5
fontColor: MoneroComponents.Style.defaultFontColor
fontFamily: FontAwesome.fontFamilySolid
fontSize: 26
styleName: "Solid"
text: FontAwesome.language
}
MoneroComponents.TextPlain {
font.pixelSize: 14
text: persistentSettings.language
}
}
MouseArea {
id: mouseArea
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
hoverEnabled: true
onClicked: appWindow.toggleLanguageView()
}
}

View File

@@ -131,9 +131,9 @@ Drawer {
translationManager.setLanguage(locale_spl[0]);
// set wizard language settings
wizard.language_locale = locale;
wizard.language_wallet = wallet_language;
wizard.language_language = display_name;
persistentSettings.locale = locale;
persistentSettings.language = display_name;
persistentSettings.language_wallet = wallet_language;
appWindow.showStatusMessage(qsTr("Language changed."), 3);
appWindow.toggleLanguageView();

View File

@@ -29,11 +29,15 @@
import FontAwesome 1.0
import QtQuick 2.9
import QtGraphicalEffects 1.0
import QtQuick.Layouts 1.1
import "../components" as MoneroComponents
Item {
id: item
default property alias content: inlineButtons.children
property alias input: input
property alias text: input.text
@@ -48,13 +52,20 @@ Item {
property int placeholderFontSize: 18
property string placeholderColor: MoneroComponents.Style.defaultFontColor
property real placeholderOpacity: 0.35
property real placeholderLeftMargin: {
if (placeholderCenter) {
return undefined;
} else if (inlineIcon.visible) {
return inlineIcon.width + inlineIcon.anchors.leftMargin + inputPadding;
} else {
return inputPadding;
}
}
property alias acceptableInput: input.acceptableInput
property alias validator: input.validator
property alias readOnly : input.readOnly
property alias cursorPosition: input.cursorPosition
property alias inlineButton: inlineButtonId
property alias inlineButtonText: inlineButtonId.text
property alias inlineIcon: inlineIcon.visible
property bool copyButton: false
property alias copyButtonText: copyButtonId.text
@@ -71,6 +82,7 @@ Item {
}
}
property string fontFamily: MoneroComponents.Style.fontRegular.name
property int fontSize: 18
property bool fontBold: false
property alias fontColor: input.color
@@ -86,14 +98,16 @@ Item {
property alias labelHorizontalAlignment: inputLabel.horizontalAlignment
property bool showingHeader: inputLabel.text !== "" || copyButton
property int inputHeight: 42
property int inputPadding: 10
signal labelLinkActivated(); // input label, rich text <a> signal
signal editingFinished();
signal accepted();
signal textUpdated();
height: showingHeader ? (inputLabel.height + inputItem.height + 2) : 42
height: showingHeader ? (inputLabel.height + inputItem.height + 2) : inputHeight
onActiveFocusChanged: activeFocus && input.forceActiveFocus()
onTextUpdated: {
// check to remove placeholder text when there is content
if(item.isEmpty()){
@@ -174,7 +188,7 @@ Item {
id: inputItem
height: inputHeight
anchors.top: showingHeader ? inputLabel.bottom : parent.top
anchors.topMargin: showingHeader ? 12 : 2
anchors.topMargin: showingHeader ? 12 : 0
width: parent.width
clip: true
@@ -184,13 +198,7 @@ Item {
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: placeholderCenter ? parent.horizontalCenter : undefined
anchors.left: placeholderCenter ? undefined : parent.left
anchors.leftMargin: {
if(placeholderCenter){
return undefined;
}
else if(inlineIcon.visible){ return 50; }
else { return 10; }
}
anchors.leftMargin: placeholderLeftMargin
opacity: item.placeholderOpacity
color: item.placeholderColor
@@ -232,13 +240,18 @@ Item {
id: input
anchors.fill: parent
anchors.leftMargin: inlineIcon.visible ? 44 : 0
font.family: item.fontFamily
font.pixelSize: item.fontSize
font.bold: item.fontBold
KeyNavigation.backtab: item.KeyNavigation.backtab
KeyNavigation.tab: item.KeyNavigation.tab
onEditingFinished: item.editingFinished()
onAccepted: item.accepted();
onTextChanged: item.textUpdated()
topPadding: 10
bottomPadding: 10
leftPadding: inputPadding
rightPadding: (inlineButtons.width > 0 ? inlineButtons.width + inlineButtons.spacing : 0) + inputPadding
topPadding: inputPadding
bottomPadding: inputPadding
echoMode: isPasswordHidden() ? TextInput.Password : TextInput.Normal
MoneroComponents.Label {
@@ -260,13 +273,17 @@ Item {
onClicked: passwordToggle()
}
}
}
MoneroComponents.InlineButton {
id: inlineButtonId
visible: item.inlineButtonText ? true : false
anchors.right: parent.right
anchors.rightMargin: 8
RowLayout {
id: inlineButtons
anchors.bottom: parent.bottom
anchors.top: parent.top
anchors.right: parent.right
anchors.topMargin: inputPadding
anchors.bottomMargin: inputPadding
anchors.rightMargin: inputPadding
spacing: 4
}
}
}
}

View File

@@ -36,6 +36,8 @@ ColumnLayout {
Layout.fillWidth: true
default property alias content: inlineButtons.children
property alias text: input.text
property alias labelText: inputLabel.text
property alias labelButtonText: labelButton.text
@@ -73,6 +75,7 @@ ColumnLayout {
property bool labelButtonVisible: false
property string fontColor: MoneroComponents.Style.defaultFontColor
property string fontFamily: MoneroComponents.Style.fontRegular.name
property bool fontBold: false
property int fontSize: 16
@@ -85,15 +88,12 @@ ColumnLayout {
property alias addressValidation: input.addressValidation
property string backgroundColor: "" // mock
property alias inlineButton: inlineButtonId
property bool inlineButtonVisible: false
property alias inlineButton2: inlineButton2Id
property bool inlineButton2Visible: false
signal labelButtonClicked();
signal inputLabelLinkActivated();
signal editingFinished();
onActiveFocusChanged: activeFocus && input.forceActiveFocus()
spacing: 0
Rectangle {
id: inputLabelRect
@@ -159,14 +159,18 @@ ColumnLayout {
id: input
readOnly: false
addressValidation: false
KeyNavigation.backtab: item.KeyNavigation.backtab
KeyNavigation.priority: KeyNavigation.BeforeItem
KeyNavigation.tab: item.KeyNavigation.tab
Layout.fillWidth: true
leftPadding: item.inputPaddingLeft
rightPadding: item.inputPaddingRight
rightPadding: (inlineButtons.width > 0 ? inlineButtons.width + inlineButtons.spacing : 0) + inputPaddingRight
topPadding: item.inputPaddingTop
bottomPadding: item.inputPaddingBottom
wrapMode: item.wrapMode
font.family: item.fontFamily
fontSize: item.fontSize
fontBold: item.fontBold
fontColor: item.fontColor
@@ -198,18 +202,12 @@ ColumnLayout {
visible: !item.borderDisabled
}
MoneroComponents.InlineButton {
id: inlineButtonId
visible: (inlineButtonId.text || inlineButtonId.icon) && inlineButtonVisible ? true : false
RowLayout {
id: inlineButtons
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
anchors.rightMargin: 8
}
MoneroComponents.InlineButton {
id: inlineButton2Id
visible: (inlineButton2Id.text || inlineButton2Id.icon) && inlineButton2Visible ? true : false
anchors.right: parent.right
anchors.rightMargin: inlineButtonVisible ? 48 : 8
anchors.rightMargin: inputPaddingRight
spacing: 4
}
}
}

207
components/Navbar.qml Normal file
View File

@@ -0,0 +1,207 @@
// Copyright (c) 2014-2021, The Monero Project
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import QtQuick 2.9
import QtQuick.Layouts 1.1
import "." as MoneroComponents
Rectangle {
default property list<MoneroComponents.NavbarItem> items
color: "transparent"
height: grid.height
width: grid.width
GridLayout {
id: grid
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
columnSpacing: 0
property string fontColorActive: MoneroComponents.Style.blackTheme ? "white" : "white"
property string fontColorInActive: MoneroComponents.Style.blackTheme ? "white" : MoneroComponents.Style.dimmedFontColor
property int fontSize: 15
property bool fontBold: true
property var fontFamily: MoneroComponents.Style.fontRegular.name
property string borderColor: MoneroComponents.Style.blackTheme ? "#808080" : "#B9B9B9"
property int textMargin: {
// left-right margins for a given cell
if(appWindow.width < 890){
return 32;
} else {
return 64;
}
}
Rectangle {
// navbar left side border
id: navBarLeft
Layout.preferredWidth: 2
Layout.preferredHeight: 32
color: "transparent"
Rectangle {
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
width: 1
height: parent.height - 2
color: grid.borderColor
}
ColumnLayout {
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.right: parent.right
width: 1
spacing: 0
Rectangle {
Layout.preferredHeight: 1
Layout.preferredWidth: 1
color: grid.borderColor
}
Rectangle {
Layout.fillHeight: true
width: 1
color: items.length > 0 && items[0].active ? grid.borderColor : "transparent";
}
Rectangle {
color: grid.borderColor
Layout.preferredHeight: 1
Layout.preferredWidth: 1
}
}
}
Repeater {
model: items.length
RowLayout {
spacing: 0
Rectangle {
Layout.preferredWidth: 1
Layout.preferredHeight: 32
color: grid.borderColor
visible: index > 0 && items[index - 1].visible
}
ColumnLayout {
Layout.minimumWidth: 72
Layout.preferredHeight: 32
Layout.fillWidth: true
spacing: 0
visible: items[index].visible
Rectangle {
color: grid.borderColor
Layout.preferredHeight: 1
Layout.fillWidth: true
}
Rectangle {
Layout.minimumHeight: 30
color: items[index].active ? grid.borderColor : "transparent"
height: children[0].height
width: children[0].width
MoneroComponents.TextPlain {
anchors.verticalCenter: parent.verticalCenter
font.family: grid.fontFamily
font.pixelSize: grid.fontSize
font.bold: grid.fontBold
leftPadding: grid.textMargin / 2
rightPadding: grid.textMargin / 2
text: items[index].text
color: items[index].active ? grid.fontColorActive : grid.fontColorInActive
themeTransition: false
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: items[index].selected()
}
}
Rectangle {
color: grid.borderColor
Layout.preferredHeight: 1
Layout.fillWidth: true
}
}
}
}
Rectangle {
// navbar right side border
id: navBarRight
Layout.preferredWidth: 2
Layout.preferredHeight: 32
color: "transparent"
rotation: 180
Rectangle {
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
width: 1
height: parent.height - 2
color: grid.borderColor
}
ColumnLayout {
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.right: parent.right
width: 1
spacing: 0
Rectangle {
Layout.preferredHeight: 1
Layout.preferredWidth: 1
color: grid.borderColor
}
Rectangle {
Layout.fillHeight: true
width: 1
color: items.length > 0 && items[items.length - 1].active ? grid.borderColor : "transparent"
}
Rectangle {
color: grid.borderColor
Layout.preferredHeight: 1
Layout.preferredWidth: 1
}
}
}
}
}

37
components/NavbarItem.qml Normal file
View File

@@ -0,0 +1,37 @@
// Copyright (c) 2021, The Monero Project
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import QtQuick 2.9
QtObject {
property bool active: false
property string text
property bool visible: true
signal selected()
}

View File

@@ -0,0 +1,153 @@
// Copyright (c) 2021, The Monero Project
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import QtQuick 2.9
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.1
import "." as MoneroComponents
MoneroComponents.Dialog {
id: root
title: (editMode ? qsTr("Edit remote node") : qsTr("Add remote node")) + translationManager.emptyString
property var callbackOnSuccess: null
property bool editMode: false
property bool success: false
onActiveFocusChanged: activeFocus && remoteNodeAddress.forceActiveFocus()
function add(callbackOnSuccess) {
root.editMode = false;
root.callbackOnSuccess = callbackOnSuccess;
open();
}
function edit(remoteNode, callbackOnSuccess) {
const hostPort = remoteNode.address.match(/^(.*?)(?:\:?(\d*))$/);
if (hostPort) {
remoteNodeAddress.daemonAddrText = hostPort[1];
remoteNodeAddress.daemonPortText = hostPort[2];
}
daemonUsername.text = remoteNode.username;
daemonPassword.text = remoteNode.password;
setTrustedDaemonCheckBox.checked = remoteNode.trusted;
root.callbackOnSuccess = callbackOnSuccess;
root.editMode = true;
open();
}
onClosed: {
if (root.success && callbackOnSuccess) {
callbackOnSuccess({
address: remoteNodeAddress.getAddress(),
username: daemonUsername.text,
password: daemonPassword.text,
trusted: setTrustedDaemonCheckBox.checked,
});
}
remoteNodeAddress.daemonAddrText = "";
remoteNodeAddress.daemonPortText = "";
daemonUsername.text = "";
daemonPassword.text = "";
setTrustedDaemonCheckBox.checked = false;
root.success = false;
}
MoneroComponents.RemoteNodeEdit {
id: remoteNodeAddress
Layout.fillWidth: true
placeholderFontSize: 15
daemonAddrLabelText: qsTr("Address") + translationManager.emptyString
daemonPortLabelText: qsTr("Port") + translationManager.emptyString
}
RowLayout {
Layout.fillWidth: true
spacing: 32
MoneroComponents.LineEdit {
id: daemonUsername
Layout.fillWidth: true
Layout.minimumWidth: 220
labelText: qsTr("Daemon username") + translationManager.emptyString
placeholderText: qsTr("(optional)") + translationManager.emptyString
placeholderFontSize: 15
labelFontSize: 14
fontSize: 15
}
MoneroComponents.LineEdit {
id: daemonPassword
Layout.fillWidth: true
Layout.minimumWidth: 220
labelText: qsTr("Daemon password") + translationManager.emptyString
placeholderText: qsTr("Password") + translationManager.emptyString
password: true
placeholderFontSize: 15
labelFontSize: 14
fontSize: 15
}
}
MoneroComponents.CheckBox {
id: setTrustedDaemonCheckBox
activeFocusOnTab: true
text: qsTr("Mark as Trusted Daemon") + translationManager.emptyString
}
RowLayout {
Layout.alignment: Qt.AlignRight
spacing: parent.spacing
MoneroComponents.StandardButton {
activeFocusOnTab: true
fontBold: false
primary: false
text: qsTr("Cancel") + translationManager.emptyString
onClicked: root.close()
}
MoneroComponents.StandardButton {
activeFocusOnTab: true
fontBold: false
enabled: remoteNodeAddress.getAddress() != ""
text: qsTr("Ok") + translationManager.emptyString
onClicked: {
root.success = true;
root.close();
}
}
}
}

View File

@@ -56,7 +56,6 @@ GridLayout {
property int labelFontSize: 14
property string lineEditBackgroundColor: "transparent"
property string lineEditBorderColor: MoneroComponents.Style.inputBorderColorInActive
property string lineEditFontColor: MoneroComponents.Style.defaultFontColor
property bool lineEditFontBold: false
property int lineEditFontSize: 15
@@ -67,6 +66,8 @@ GridLayout {
signal editingFinished()
signal textChanged()
onActiveFocusChanged: activeFocus && daemonAddr.forceActiveFocus()
function isValid() {
return daemonAddr.text.trim().length > 0 && daemonPort.acceptableInput
}
@@ -92,7 +93,6 @@ GridLayout {
placeholderColor: root.placeholderColor
placeholderOpacity: root.placeholderOpacity
labelFontSize: root.labelFontSize
borderColor: lineEditBorderColor
backgroundColor: lineEditBackgroundColor
fontColor: lineEditFontColor
fontBold: lineEditFontBold
@@ -115,7 +115,6 @@ GridLayout {
placeholderColor: root.placeholderColor
placeholderOpacity: root.placeholderOpacity
labelFontSize: root.labelFontSize
borderColor: lineEditBorderColor
backgroundColor: lineEditBackgroundColor
fontColor: lineEditFontColor
fontBold: lineEditFontBold

View File

@@ -68,7 +68,7 @@ Item {
id: buttonRect
anchors.fill: parent
radius: 3
border.width: parent.focus ? 1 : 0
border.width: parent.focus && parent.enabled ? 1 : 0
state: button.enabled ? "active" : "disabled"
Component.onCompleted: state = state
@@ -76,7 +76,7 @@ Item {
states: [
State {
name: "hover"
when: buttonArea.containsMouse || button.focus
when: button.enabled && (buttonArea.containsMouse || button.focus)
PropertyChanges {
target: buttonRect
color: primary

View File

@@ -45,20 +45,11 @@ Rectangle {
radius: 10
border.color: MoneroComponents.Style.blackTheme ? Qt.rgba(255, 255, 255, 0.25) : Qt.rgba(0, 0, 0, 0.25)
border.width: 1
focus: true
Keys.enabled: true
Keys.onEscapePressed: {
root.close()
root.rejected()
}
Keys.onEnterPressed: {
root.close()
root.accepted()
}
Keys.onReturnPressed: {
root.close()
root.accepted()
}
KeyNavigation.tab: doneButton
Clipboard { id: clipboard }
@@ -72,7 +63,6 @@ Rectangle {
function open(txid) {
root.transactionID = txid;
root.visible = true;
root.forceActiveFocus();
}
function close() {
@@ -156,13 +146,6 @@ Rectangle {
text: qsTr("Open folder") + translationManager.emptyString;
width: 200
KeyNavigation.tab: doneButton
Keys.enabled: openFolderButton.visible
Keys.onReturnPressed: openFolderButton.onClicked
Keys.onEnterPressed: openFolderButton.onClicked
Keys.onEscapePressed: {
root.close()
root.rejected()
}
onClicked: {
oshelper.openContainingFolder(walletManager.urlToLocalPath(saveTxDialog.fileUrl))
}
@@ -172,15 +155,8 @@ Rectangle {
id: doneButton
text: qsTr("Done") + translationManager.emptyString;
width: 200
focus: true
focus: root.visible
KeyNavigation.tab: openFolderButton
Keys.enabled: doneButton.visible
Keys.onReturnPressed: doneButton.onClicked
Keys.onEnterPressed: doneButton.onClicked
Keys.onEscapePressed: {
root.close()
root.rejected()
}
onClicked: {
root.close()
root.accepted()

View File

@@ -0,0 +1,440 @@
// Copyright (c) 2014-2020, The Monero Project
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import QtQuick 2.9
import QtQuick.Controls 1.4 as QtQuickControls1
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.1
import "../components" as MoneroComponents
import FontAwesome 1.0
Rectangle {
id: root
property int margins: 25
x: parent.width/2 - root.width/2
y: parent.height/2 - root.height/2
// TODO: implement without hardcoding sizes
width: 590
height: layout.height + layout.anchors.margins * 2
color: MoneroComponents.Style.blackTheme ? "black" : "white"
visible: false
radius: 10
border.color: MoneroComponents.Style.blackTheme ? Qt.rgba(255, 255, 255, 0.25) : Qt.rgba(0, 0, 0, 0.25)
border.width: 1
Keys.enabled: true
Keys.onEscapePressed: {
root.close()
root.clearFields()
root.rejected()
}
KeyNavigation.tab: confirmButton
property var recipients: []
property var transactionAmount: ""
property var transactionDescription: ""
property var transactionFee: ""
property var transactionPriority: ""
property bool sweepUnmixable: false
property alias errorText: errorText
property alias confirmButton: confirmButton
property alias backButton: backButton
property alias bottomText: bottomText
property alias bottomTextAnimation: bottomTextAnimation
state: "default"
states: [
State {
// waiting for user action, show tx details + back and confirm buttons
name: "default";
when: errorText.text == "" && bottomText.text == ""
PropertyChanges { target: errorText; visible: false }
PropertyChanges { target: txAmountText; visible: root.transactionAmount !== "(all)" || (root.transactionAmount === "(all)" && currentWallet.isHwBacked() === true) }
PropertyChanges { target: txAmountBusyIndicator; visible: !txAmountText.visible }
PropertyChanges { target: txFiatAmountText; visible: txAmountText.visible && persistentSettings.fiatPriceEnabled && root.transactionAmount !== "(all)" }
PropertyChanges { target: txDetails; visible: true }
PropertyChanges { target: bottom; visible: true }
PropertyChanges { target: bottomMessage; visible: false }
PropertyChanges { target: buttons; visible: true }
PropertyChanges { target: backButton; visible: true; primary: false }
PropertyChanges { target: confirmButton; visible: true; focus: true }
}, State {
// error message being displayed, show only back button
name: "error";
when: errorText.text !== ""
PropertyChanges { target: dialogTitle; text: "Error" }
PropertyChanges { target: errorText; visible: true }
PropertyChanges { target: txAmountText; visible: false }
PropertyChanges { target: txAmountBusyIndicator; visible: false }
PropertyChanges { target: txFiatAmountText; visible: false }
PropertyChanges { target: txDetails; visible: false }
PropertyChanges { target: bottom; visible: true }
PropertyChanges { target: bottomMessage; visible: false }
PropertyChanges { target: buttons; visible: true }
PropertyChanges { target: backButton; visible: true; primary: true; focus: true }
PropertyChanges { target: confirmButton; visible: false }
}, State {
// creating or sending transaction, show tx details and don't show any button
name: "bottomText";
when: errorText.text == "" && bottomText.text !== ""
PropertyChanges { target: errorText; visible: false }
PropertyChanges { target: txAmountText; visible: root.transactionAmount !== "(all)" || (root.transactionAmount === "(all)" && currentWallet.isHwBacked() === true) }
PropertyChanges { target: txAmountBusyIndicator; visible: !txAmountText.visible }
PropertyChanges { target: txFiatAmountText; visible: txAmountText.visible && persistentSettings.fiatPriceEnabled && root.transactionAmount !== "(all)" }
PropertyChanges { target: txDetails; visible: true }
PropertyChanges { target: bottom; visible: true }
PropertyChanges { target: bottomMessage; visible: true }
PropertyChanges { target: buttons; visible: false }
}
]
// same signals as Dialog has
signal accepted()
signal rejected()
function open() {
root.visible = true;
//clean previous error message
errorText.text = "";
}
function close() {
root.visible = false;
}
function clearFields() {
root.recipients = [];
root.transactionAmount = "";
root.transactionDescription = "";
root.transactionFee = "";
root.transactionPriority = "";
root.sweepUnmixable = false;
}
function showFiatConversion(valueXMR) {
const fiatFee = fiatApiConvertToFiat(valueXMR);
return "%1 %2".arg(fiatFee < 0.01 ? "<0.01" : "~" + fiatFee).arg(fiatApiCurrencySymbol());
}
ColumnLayout {
id: layout
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
anchors.margins: parent.margins
spacing: 10
RowLayout {
Layout.topMargin: 10
Layout.fillWidth: true
MoneroComponents.Label {
id: dialogTitle
Layout.fillWidth: true
fontSize: 18
fontFamily: "Arial"
horizontalAlignment: Text.AlignHCenter
text: {
if (appWindow.viewOnly) {
return qsTr("Create transaction file") + translationManager.emptyString;
} else if (root.sweepUnmixable) {
return qsTr("Sweep unmixable outputs") + translationManager.emptyString;
} else {
return qsTr("Confirm send") + translationManager.emptyString;
}
}
}
}
Text {
id: errorText
Layout.fillWidth: true
Layout.fillHeight: true
color: MoneroComponents.Style.defaultFontColor
wrapMode: Text.Wrap
font.pixelSize: 15
}
ColumnLayout {
spacing: 0
Layout.fillWidth: true
Layout.preferredHeight: 71
QtQuickControls1.BusyIndicator {
id: txAmountBusyIndicator
Layout.fillHeight: true
Layout.fillWidth: true
running: root.transactionAmount == "(all)"
}
Text {
id: txAmountText
Layout.fillWidth: true
horizontalAlignment: Text.AlignHCenter
font.pixelSize: root.transactionAmount == "(all)" && currentWallet.isHwBacked() === true ? 32 : 42
color: MoneroComponents.Style.defaultFontColor
text: {
if (root.transactionAmount == "(all)" && currentWallet.isHwBacked() === true) {
return qsTr("All unlocked balance") + translationManager.emptyString;
} else {
return root.transactionAmount + " XMR " + translationManager.emptyString;
}
}
}
Text {
id: txFiatAmountText
Layout.fillWidth: true
horizontalAlignment: Text.AlignHCenter
font.pixelSize: 20
color: MoneroComponents.Style.buttonSecondaryTextColor
text: showFiatConversion(transactionAmount) + translationManager.emptyString
}
}
GridLayout {
columns: 2
id: txDetails
Layout.fillWidth: true
columnSpacing: 15
rowSpacing: 16
Text {
color: MoneroComponents.Style.dimmedFontColor
text: qsTr("From") + ":" + translationManager.emptyString
font.pixelSize: 15
}
ColumnLayout {
Layout.fillWidth: true
spacing: 16
Text {
Layout.fillWidth: true
font.pixelSize: 15
color: MoneroComponents.Style.defaultFontColor
text: {
if (currentWallet) {
var walletTitle = function() {
if (currentWallet.isLedger()) {
return "Ledger";
} else if (currentWallet.isTrezor()) {
return "Trezor";
} else {
return qsTr("My wallet");
}
}
var walletName = appWindow.walletName;
if (appWindow.currentWallet.numSubaddressAccounts() > 1) {
var currentSubaddressAccount = currentWallet.currentSubaddressAccount;
var currentAccountLabel = currentWallet.getSubaddressLabel(currentWallet.currentSubaddressAccount, 0);
return walletTitle() + " (" + walletName + ")" + "<br>" + qsTr("Account #") + currentSubaddressAccount + (currentAccountLabel !== "" ? " (" + currentAccountLabel + ")" : "") + translationManager.emptyString;
} else {
return walletTitle() + " (" + walletName + ")" + translationManager.emptyString;
}
} else {
return "";
}
}
}
}
Text {
font.pixelSize: 15
color: MoneroComponents.Style.dimmedFontColor
text: qsTr("To") + ":" + translationManager.emptyString
}
Flickable {
id: flickable
property int linesInMultipleRecipientsMode: 7
Layout.fillWidth: true
Layout.preferredHeight: recipients.length > 1
? linesInMultipleRecipientsMode * (recipientsArea.contentHeight / recipientsArea.lineCount)
: recipientsArea.contentHeight
boundsBehavior: isMac ? Flickable.DragAndOvershootBounds : Flickable.StopAtBounds
clip: true
TextArea.flickable: TextArea {
id : recipientsArea
color: MoneroComponents.Style.defaultFontColor
font.family: MoneroComponents.Style.fontMonoRegular.name
font.pixelSize: 14
topPadding: 0
bottomPadding: 0
leftPadding: 0
textMargin: 0
readOnly: true
selectByKeyboard: true
selectByMouse: true
selectionColor: MoneroComponents.Style.textSelectionColor
textFormat: TextEdit.RichText
wrapMode: TextEdit.Wrap
text: {
return recipients.map(function (recipient, index) {
var addressBookName = null;
if (currentWallet) {
addressBookName = currentWallet.addressBook.getDescription(recipient.address);
}
var title;
if (addressBookName) {
title = FontAwesome.addressBook + " " + addressBookName;
} else {
title = qsTr("Monero address") + translationManager.emptyString;
}
if (recipients.length > 1) {
title = "%1. %2 - %3 XMR".arg(index + 1).arg(title).arg(recipient.amount);
if (persistentSettings.fiatPriceEnabled) {
title += " (%1)".arg(showFiatConversion(recipient.amount));
}
}
const spacedaddress = recipient.address.match(/.{1,4}/g).join(' ');
return title + "<br>" + spacedaddress;
}).join("<br><br>");
}
}
ScrollBar.vertical: ScrollBar {
policy: recipientsArea.contentHeight > flickable.height ? ScrollBar.AlwaysOn : ScrollBar.AlwaysOff
}
}
Text {
color: MoneroComponents.Style.dimmedFontColor
text: qsTr("Fee") + ":" + translationManager.emptyString
font.pixelSize: 15
}
RowLayout {
Layout.fillWidth: true
spacing: 16
Text {
color: MoneroComponents.Style.defaultFontColor
font.pixelSize: 15
text: {
if (currentWallet) {
if (!root.transactionFee) {
if (currentWallet.isHwBacked() === true) {
return qsTr("See on device") + translationManager.emptyString;
} else {
return qsTr("Calculating fee") + "..." + translationManager.emptyString;
}
} else {
return root.transactionFee + " XMR"
}
} else {
return "";
}
}
}
Text {
Layout.fillWidth: true
Layout.leftMargin: 8
color: MoneroComponents.Style.buttonSecondaryTextColor
visible: persistentSettings.fiatPriceEnabled && root.transactionFee
font.pixelSize: 15
text: showFiatConversion(root.transactionFee)
}
}
}
ColumnLayout {
id: bottom
Layout.alignment: Qt.AlignBottom | Qt.AlignHCenter
Layout.fillWidth: true
RowLayout {
id: bottomMessage
Layout.fillWidth: true
Layout.preferredHeight: 50
QtQuickControls1.BusyIndicator {
visible: !bottomTextAnimation.running
running: !bottomTextAnimation.running
scale: .5
}
Text {
id: bottomText
color: MoneroComponents.Style.defaultFontColor
text: ""
horizontalAlignment: Text.AlignHCenter
wrapMode: Text.Wrap
font.pixelSize: 17
opacity: 1
SequentialAnimation{
id:bottomTextAnimation
running: false
loops: Animation.Infinite
alwaysRunToEnd: true
NumberAnimation { target: bottomText; property: "opacity"; to: 0; duration: 500}
NumberAnimation { target: bottomText; property: "opacity"; to: 1; duration: 500}
}
}
}
RowLayout {
id: buttons
spacing: 70
Layout.fillWidth: true
Layout.preferredHeight: 50
MoneroComponents.StandardButton {
id: backButton
text: qsTr("Back") + translationManager.emptyString;
width: 200
primary: false
KeyNavigation.tab: confirmButton
onClicked: {
root.close()
root.clearFields()
root.rejected()
}
}
MoneroComponents.StandardButton {
id: confirmButton
text: qsTr("Confirm") + translationManager.emptyString;
rightIcon: "qrc:///images/rightArrow.png"
width: 200
KeyNavigation.tab: backButton
onClicked: {
root.close()
root.accepted()
}
}
}
}
}
}

View File

@@ -1,27 +0,0 @@
android-no-sdk {
target.path = /data/user/qt
export(target.path)
INSTALLS += target
} else:android {
x86 {
target.path = /libs/x86
} else: armeabi-v7a {
target.path = /libs/armeabi-v7a
} else {
target.path = /libs/armeabi
}
export(target.path)
INSTALLS += target
} else:unix {
isEmpty(target.path) {
qnx {
target.path = /tmp/$${TARGET}/bin
} else {
target.path = /opt/$${TARGET}/bin
}
export(target.path)
}
INSTALLS += target
}
export(INSTALLS)

7
external/CMakeLists.txt vendored Normal file
View File

@@ -0,0 +1,7 @@
add_library(quirc STATIC
quirc/lib/decode.c
quirc/lib/identify.c
quirc/lib/quirc.c
quirc/lib/version_db.c
)
target_include_directories(quirc PUBLIC quirc/lib)

1
external/quirc vendored Submodule

Submodule external/quirc added at 7e7ab596e4

View File

@@ -403,6 +403,7 @@ Object {
property string inbox : "\uf01c"
property string indent : "\uf03c"
property string industry : "\uf275"
property string infinity : "\uf534"
property string info : "\uf129"
property string infoCircle : "\uf05a"
property string inr : "\uf156"

View File

@@ -1,286 +0,0 @@
#!/bin/bash
MONERO_URL=https://github.com/monero-project/monero.git
MONERO_BRANCH=master
pushd $(pwd)
ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
source $ROOT_DIR/utils.sh
INSTALL_DIR=$ROOT_DIR/wallet
MONERO_DIR=$ROOT_DIR/monero
BUILD_LIBWALLET=false
# init and update monero submodule
if [ ! -d $MONERO_DIR/src ]; then
git submodule init monero
fi
git submodule update --remote
git -C $MONERO_DIR fetch
git -C $MONERO_DIR checkout v0.17.1.1
# get monero core tag
pushd $MONERO_DIR
get_tag
popd
# create local monero branch
git -C $MONERO_DIR checkout -B $VERSIONTAG
# Merge monero PR dependencies
# Workaround for git username requirements
# Save current user settings and revert back when we are done with merging PR's
OLD_GIT_USER=$(git -C $MONERO_DIR config --local user.name)
OLD_GIT_EMAIL=$(git -C $MONERO_DIR config --local user.email)
git -C $MONERO_DIR config user.name "Monero GUI"
git -C $MONERO_DIR config user.email "gui@monero.local"
# check for PR requirements in most recent commit message (i.e requires #xxxx)
for PR in $(git log --format=%B -n 1 | grep -io "requires #[0-9]*" | sed 's/[^0-9]*//g'); do
echo "Merging monero push request #$PR"
# fetch pull request and merge
git -C $MONERO_DIR fetch origin pull/$PR/head:PR-$PR
git -C $MONERO_DIR merge --quiet PR-$PR -m "Merge monero PR #$PR"
BUILD_LIBWALLET=true
done
# revert back to old git config
$(git -C $MONERO_DIR config user.name "$OLD_GIT_USER")
$(git -C $MONERO_DIR config user.email "$OLD_GIT_EMAIL")
git -C $MONERO_DIR submodule init
git -C $MONERO_DIR submodule update
# Build libwallet if it doesnt exist
if [ ! -f $MONERO_DIR/lib/libwallet_merged.a ]; then
echo "libwallet_merged.a not found - Building libwallet"
BUILD_LIBWALLET=true
# Build libwallet if no previous version file exists
elif [ ! -f $MONERO_DIR/version.sh ]; then
echo "monero/version.h not found - Building libwallet"
BUILD_LIBWALLET=true
## Compare previously built version with submodule + merged PR's version.
else
source $MONERO_DIR/version.sh
# compare submodule version with latest build
pushd "$MONERO_DIR"
get_tag
popd
echo "latest libwallet version: $GUI_MONERO_VERSION"
echo "Installed libwallet version: $VERSIONTAG"
# check if recent
if [ "$VERSIONTAG" != "$GUI_MONERO_VERSION" ]; then
echo "Building new libwallet version $GUI_MONERO_VERSION"
BUILD_LIBWALLET=true
else
echo "latest libwallet ($GUI_MONERO_VERSION) is already built. Remove monero/lib/libwallet_merged.a to force rebuild"
fi
fi
if [ "$BUILD_LIBWALLET" != true ]; then
exit 0
fi
echo "GUI_MONERO_VERSION=\"$VERSIONTAG\"" > $MONERO_DIR/version.sh
## Continue building libwallet
# default build type
BUILD_TYPE=$1
if [ -z $BUILD_TYPE ]; then
BUILD_TYPE=release
fi
BUILD_TREZOR_FLAGS=" -DUSE_DEVICE_TREZOR=ON"
if [ "$BUILD_TREZOR" == false ]; then
BUILD_TREZOR_FLAGS=" -DUSE_DEVICE_TREZOR=OFF"
fi
BUILD_TREZOR_FLAGS=" -DUSE_DEVICE_TREZOR_UDP_RELEASE=ON ${BUILD_TREZOR_FLAGS}"
STATIC=false
ANDROID=false
if [ "$BUILD_TYPE" == "release" ]; then
echo "Building libwallet release"
CMAKE_BUILD_TYPE=Release
elif [ "$BUILD_TYPE" == "release-static" ]; then
echo "Building libwallet release-static"
CMAKE_BUILD_TYPE=Release
STATIC=true
elif [ "$BUILD_TYPE" == "release-android" ]; then
echo "Building libwallet release-static for ANDROID"
CMAKE_BUILD_TYPE=Release
STATIC=true
ANDROID=true
elif [ "$BUILD_TYPE" == "debug-android" ]; then
echo "Building libwallet debug-static for ANDROID"
CMAKE_BUILD_TYPE=Debug
STATIC=true
ANDROID=true
elif [ "$BUILD_TYPE" == "debug" ]; then
echo "Building libwallet debug"
CMAKE_BUILD_TYPE=Debug
STATIC=true
else
echo "Valid build types are release, release-static, release-android, debug-android and debug"
exit 1;
fi
echo "cleaning up existing monero build dir, libs and includes"
rm -fr $MONERO_DIR/build
rm -fr $MONERO_DIR/lib
rm -fr $MONERO_DIR/include
rm -fr $MONERO_DIR/bin
mkdir -p $MONERO_DIR/build/$BUILD_TYPE
pushd $MONERO_DIR/build/$BUILD_TYPE
# reusing function from "utils.sh"
platform=$(get_platform)
# default make executable
make_exec="make"
if [ -z "$ARCH" ]; then
ARCH="native"
if [ "$platform" == "darwin" ]; then
if [ "$STATIC" == true ]; then
ARCH="x86-64"
fi
elif [ "$platform" == "linux64" ]; then
if [ "$ANDROID" == true ]; then
ARCH="armv7-a"
elif [ "$STATIC" == true ]; then
ARCH="x86-64"
fi
elif [ "$platform" == "linux32" ]; then
if [ "$STATIC" == true ]; then
ARCH="i686"
fi
elif [ "$platform" == "linuxarmv7" ]; then
ARCH="armv7-a"
elif [ "$platform" == "mingw32" ]; then
ARCH="i686"
elif [ "$platform" == "mingw64" ]; then
ARCH="x86-64"
fi
fi
echo "Building for ARCH=$ARCH"
## OS X
if [ "$platform" == "darwin" ]; then
echo "Configuring build for MacOS.."
if [ "$STATIC" == true ]; then
cmake -D CMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE -D STATIC=ON -D ARCH="$ARCH" -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
cmake -D CMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE -D ARCH="$ARCH" -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
## LINUX 64
elif [ "$platform" == "linux64" ]; then
echo "Configuring build for Linux x64"
if [ "$ANDROID" == true ]; then
echo "Configuring build for Android on Linux host"
cmake -D CMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE -D STATIC=ON -D ARCH="$ARCH" -D ANDROID=true -D BUILD_GUI_DEPS=ON -D USE_LTO=OFF -D INSTALL_VENDORED_LIBUNBOUND=ON $BUILD_TREZOR_FLAGS -D CMAKE_INSTALL_PREFIX="$MONERO_DIR" ../..
elif [ "$STATIC" == true ]; then
cmake -D CMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE -D STATIC=ON -D ARCH="$ARCH" -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
cmake -D CMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE -D ARCH="$ARCH" -D BUILD_TAG="linux-x64" -D BUILD_GUI_DEPS=ON $BUILD_TREZOR_FLAGS -D CMAKE_INSTALL_PREFIX="$MONERO_DIR" ../..
fi
## LINUX 32
elif [ "$platform" == "linux32" ]; then
echo "Configuring build for Linux i686"
if [ "$STATIC" == true ]; then
cmake -D CMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE -D STATIC=ON -D ARCH="$ARCH" -D BUILD_64=OFF -D BUILD_GUI_DEPS=ON -D INSTALL_VENDORED_LIBUNBOUND=ON $BUILD_TREZOR_FLAGS -D CMAKE_INSTALL_PREFIX="$MONERO_DIR" ../..
else
cmake -D CMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE -D ARCH="$ARCH" -D BUILD_GUI_DEPS=ON $BUILD_TREZOR_FLAGS -D CMAKE_INSTALL_PREFIX="$MONERO_DIR" ../..
fi
## LINUX ARMv7
elif [ "$platform" == "linuxarmv7" ]; then
echo "Configuring build for Linux armv7"
if [ "$STATIC" == true ]; then
cmake -D BUILD_TESTS=OFF -D ARCH="$ARCH" -D STATIC=ON -D BUILD_64=OFF -D BUILD_GUI_DEPS=ON $BUILD_TREZOR_FLAGS -D CMAKE_INSTALL_PREFIX="$MONERO_DIR" ../..
else
cmake -D BUILD_TESTS=OFF -D ARCH="$ARCH" -D BUILD_64=OFF -D BUILD_GUI_DEPS=ON $BUILD_TREZOR_FLAGS -D CMAKE_INSTALL_PREFIX="$MONERO_DIR" ../..
fi
## LINUX other
elif [ "$platform" == "linux" ]; then
echo "Configuring build for Linux general"
if [ "$STATIC" == true ]; then
cmake -D CMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE -D STATIC=ON -D ARCH="$ARCH" -D BUILD_GUI_DEPS=ON -D INSTALL_VENDORED_LIBUNBOUND=ON $BUILD_TREZOR_FLAGS -D CMAKE_INSTALL_PREFIX="$MONERO_DIR" ../..
else
cmake -D CMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE -D ARCH="$ARCH" -D BUILD_GUI_DEPS=ON $BUILD_TREZOR_FLAGS -D CMAKE_INSTALL_PREFIX="$MONERO_DIR" ../..
fi
## Windows 64
## Windows is always static to work outside msys2
elif [ "$platform" == "mingw64" ]; then
# Do something under Windows NT platform
echo "Configuring build for MINGW64.."
BOOST_ROOT=/mingw64/boost
cmake -D CMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE -D STATIC=ON -D BOOST_ROOT="$BOOST_ROOT" -D ARCH="$ARCH" -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=$(cd $MINGW_PREFIX/.. && pwd -W) ../..
## Windows 32
elif [ "$platform" == "mingw32" ]; then
# Do something under Windows NT platform
echo "Configuring build for MINGW32.."
BOOST_ROOT=/mingw32/boost
cmake -D CMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE -D STATIC=ON -D Boost_DEBUG=ON -D BOOST_ROOT="$BOOST_ROOT" -D ARCH="$ARCH" -D BUILD_64=OFF -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/32-bit-toolchain.cmake -D MSYS2_FOLDER=$(cd $MINGW_PREFIX/.. && pwd -W) ../..
make_exec="mingw32-make"
else
echo "Unknown platform, configuring general build"
if [ "$STATIC" == true ]; then
cmake -D CMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE -D STATIC=ON -D ARCH="$ARCH" -D BUILD_GUI_DEPS=ON $BUILD_TREZOR_FLAGS -D CMAKE_INSTALL_PREFIX="$MONERO_DIR" ../..
else
cmake -D CMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE -D ARCH="$ARCH" -D BUILD_GUI_DEPS=ON $BUILD_TREZOR_FLAGS -D CMAKE_INSTALL_PREFIX="$MONERO_DIR" ../..
fi
fi
# set CPU core count
# thanks to SO: http://stackoverflow.com/a/20283965/4118915
if test -z "$CPU_CORE_COUNT"; then
CPU_CORE_COUNT=$(grep -c ^processor /proc/cpuinfo 2>/dev/null || sysctl -n hw.ncpu)
fi
# Build libwallet_merged
pushd $MONERO_DIR/build/$BUILD_TYPE/src/wallet
eval $make_exec version -C ../..
eval $make_exec -j$CPU_CORE_COUNT
eval $make_exec install -j$CPU_CORE_COUNT
popd
# Build monerod
# win32 need to build daemon manually with msys2 toolchain
if [ "$platform" != "mingw32" ] && [ "$ANDROID" != true ]; then
pushd $MONERO_DIR/build/$BUILD_TYPE/src/daemon
eval make -j$CPU_CORE_COUNT
eval make install -j$CPU_CORE_COUNT
popd
fi
# build install epee
eval make -C $MONERO_DIR/build/$BUILD_TYPE/contrib/epee all install
# install easylogging
eval make -C $MONERO_DIR/build/$BUILD_TYPE/external/easylogging++ all install
# install lmdb
eval make -C $MONERO_DIR/build/$BUILD_TYPE/external/db_drivers/liblmdb all install
# Install libunbound
if [ -d $MONERO_DIR/build/$BUILD_TYPE/external/unbound ]; then
echo "Installing libunbound..."
pushd $MONERO_DIR/build/$BUILD_TYPE/external/unbound
# no need to make, it was already built as dependency for libwallet
# make -j$CPU_CORE_COUNT
$make_exec install -j$CPU_CORE_COUNT
popd
fi
# install randomx
eval make -C $MONERO_DIR/build/$BUILD_TYPE/external/randomx all install
popd

View File

@@ -105,9 +105,6 @@ Source: "bin\extras\monero-gen-ssl-cert.exe"; DestDir: "{app}"; Flags: ignorever
; Qt Quick 2D Renderer fallback for systems / environments with "low-level graphics" i.e. without 3D support
Source: "bin\start-low-graphics-mode.bat"; DestDir: "{app}"; Flags: ignoreversion
; Use a scale factor of 2 for Qt for high-DPI systems, as long as Qt does not handle some such systems adequately
Source: "bin\start-high-dpi.bat"; DestDir: "{app}"; Flags: ignoreversion
; Mesa, open-source OpenGL implementation; part of "low-level graphics" support
Source: "bin\opengl32sw.dll"; DestDir: "{app}"; Flags: ignoreversion
@@ -170,6 +167,7 @@ Type: files; Name: "{app}\libssp-0.dll"
Type: files; Name: "{app}\libhidapi-0.dll"
Type: files; Name: "{app}\libeay32.dll"
Type: files; Name: "{app}\ssleay32.dll"
Type: files; Name: "{app}\start-high-dpi.bat"
Type: files; Name: "{group}\Utilities\x (Check Blockchain Folder).lnk"

View File

@@ -105,8 +105,8 @@
<p>The Monero software and especially the GUI wallet are "work in progress", and sometimes things go wrong.</p>
<p>Please note that despite any technical problems that you may encounter your Moneroj are almost always safe: You may
not be able to move them or you even may not see how many you currently have, but you most probably won't loose any.
But do remember that the seed needed to re-create the wallet <b>is</b> critical, however: <b>Never loose your
not be able to move them or you even may not see how many you currently have, but you most probably won't lose any.
But do remember that the seed needed to re-create the wallet <b>is</b> critical, however: <b>Never lose your
seed!</b></p>
<p>In the <i>Utilities</i> sub-folder there are several more icons that may help you to solve problems.

View File

@@ -1,49 +0,0 @@
#!/bin/bash -e
# 3 header files required by monero are missing from the IOS SDK. I copied them from iphoneSimulator SDK
# cd /Applications/XCode.app
# sudo cp ./Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/include/sys/vmmeter.h ./Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include/sys/
# sudo cp ./Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/include/netinet/udp_var.h ./Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include/netinet/
# sudo cp ./Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/include/netinet/ip_var.h ./Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include/netinet/
if [ -z $BUILD_TYPE ]; then
BUILD_TYPE=release
fi
ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
if [ -z $BOOST_LIBRARYDIR ]; then
BOOST_LIBRARYDIR=${ROOT_DIR}/../ofxiOSBoost/build/ios/prefix/lib
fi
if [ -z $BOOST_INCLUDEDIR ]; then
BOOST_INCLUDEDIR=${ROOT_DIR}/../ofxiOSBoost/build/ios/prefix/include
fi
if [ -z $OPENSSL_INCLUDE_DIR ]; then
OPENSSL_INCLUDE_DIR=${ROOT_DIR}/../openssl/1.0.2j/include
fi
if [ -z $OPENSSL_ROOT_DIR ]; then
OPENSSL_ROOT_DIR=${ROOT_DIR}/../openssl/1.0.2j
fi
echo "Building IOS armv7"
rm -r monero/build > /dev/null
mkdir -p monero/build/release
pushd monero/build/release
cmake -D IOS=ON -D ARCH=armv7 -D BOOST_LIBRARYDIR=${BOOST_INCLUDEDIR} -D BOOST_INCLUDEDIR=${BOOST_INCLUDEDIR} -D OPENSSL_INCLUDE_DIR=${OPENSSL_INCLUDE_DIR} -D OPENSSL_ROOT_DIR=${OPENSSL_ROOT_DIR} -D CMAKE_BUILD_TYPE=debug -D STATIC=ON -D BUILD_GUI_DEPS=ON -D INSTALL_VENDORED_LIBUNBOUND=ON -D CMAKE_INSTALL_PREFIX="/Users/jacob/crypto/monero-core/monero" ../..
make -j4 && make install
popd
echo "Building IOS arm64"
rm -r monero/build > /dev/null
mkdir -p monero/build/release
pushd monero/build/release
cmake -D IOS=ON -D ARCH=armv8-a -D BOOST_LIBRARYDIR=${BOOST_INCLUDEDIR} -D BOOST_INCLUDEDIR=${BOOST_INCLUDEDIR} -D OPENSSL_INCLUDE_DIR=${OPENSSL_INCLUDE_DIR} -D OPENSSL_ROOT_DIR=${OPENSSL_ROOT_DIR} -D CMAKE_BUILD_TYPE=debug -D STATIC=ON -D BUILD_GUI_DEPS=ON -D INSTALL_VENDORED_LIBUNBOUND=ON -D CMAKE_INSTALL_PREFIX="/Users/jacob/crypto/monero-core/monero" ../..
make -j4 && make install
popd
echo "Creating fat library for armv7 and arm64"
pushd monero
mkdir -p lib-ios
lipo -create lib-armv7/libwallet_merged.a lib-arm64/libwallet_merged.a -output lib-ios/libwallet_merged.a
lipo -create lib-armv7/libunbound.a lib-arm64/libunbound.a -output lib-ios/libunbound.a
lipo -create lib-armv7/libepee.a lib-arm64/libepee.a -output lib-ios/libepee.a
popd

View File

@@ -113,5 +113,5 @@ function capitalize(s){
}
function removeTrailingZeros(value) {
return (value + '').replace(/(\.\d*[1-9])0+$/, '$1');
return (value + '').replace(/(\.\d*?)0+$/, '$1').replace(/\.$/, '');
}

View File

@@ -1,62 +0,0 @@
#!/bin/bash
ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
source $ROOT_DIR/utils.sh
TARGET=$1
GUI_EXEC=$2
platform=$(get_platform)
if [[ "$platform" == "linux64" ]]; then
PLAT_DIR="/usr/lib/x86_64-linux-gnu"
elif [[ "$platform" == "linux32" ]]; then
PLAT_DIR="/usr/lib/i386-linux-gnu"
elif [[ "$platform" == "linuxarmv7" ]]; then
PLAT_DIR="/usr/lib/arm-linux-gnueabihf"
elif [[ "$platform" == "linuxarmv8" ]]; then
PLAT_DIR="/usr/lib/aarch64-linux-gnu"
else
PLAT_DIR="/usr/lib"
fi
if [ -z "$QT_DIR" ]; then
QT_DIR=$PLAT_DIR/qt5
fi
if [ -z "$QTXML_DIR" ]; then
QTXML_DIR=$PLAT_DIR
fi
# Copy dependencies
EXCLUDE='libstdc++|libgcc_s.so|libc.so|libpthread'
INCLUDE='libunbound'
cp -rv $QT_DIR/qml $TARGET || exit
cp -rv $QT_DIR/plugins $TARGET || exit
mkdir -p $TARGET/libs || exit
#ldd $TARGET/$GUI_EXEC | grep "=> /" | awk '{print $3}' | grep $INCLUDE | xargs -I '{}' cp -v '{}' $TARGET/libs || exit
#ldd $TARGET/$GUI_EXEC | grep "=> /" | awk '{print $3}' | grep -Ev $EXCLUDE | xargs -I '{}' cp -v '{}' $TARGET/libs || exit
#ldd $TARGET/plugins/platforms/libqxcb.so| grep "=> /" | awk '{print $3}' | grep -Ev $EXCLUDE | xargs -I '{}' cp -v '{}' $TARGET/libs || exit
#cp -v $QTXML_DIR/libQt5XmlPatterns.so.5 $TARGET/libs || exit
# Create start script
cat > $TARGET/start-gui.sh <<EOL
#!/bin/bash
export LD_LIBRARY_PATH=\`pwd\`/libs
export QT_PLUGIN_PATH=\`pwd\`/plugins
export QML2_IMPORT_PATH=\`pwd\`/qml
# make it so that it can be called from anywhere and also through soft links
SCRIPT_DIR="\$(dirname "\$(test -L "\${BASH_SOURCE[0]}" && readlink "\${BASH_SOURCE[0]}" || echo "\${BASH_SOURCE[0]}")")"
"\$SCRIPT_DIR"/$GUI_EXEC "\$@"
EOL
# Create start script
cat > $TARGET/start-tails.AppImage <<EOL
#!/bin/bash
# Silly hack to provide a launcher that is double clickable
bash ./start-gui.sh
EOL
chmod +x $TARGET/start-gui.sh
chmod +x $TARGET/start-tails.AppImage

433
main.qml
View File

@@ -26,6 +26,7 @@
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import QtQml.Models 2.12
import QtQuick 2.9
import QtQuick.Window 2.0
import QtQuick.Controls 1.1
@@ -53,7 +54,10 @@ import "version.js" as Version
ApplicationWindow {
id: appWindow
title: "Monero" + (walletName ? " - " + walletName : "")
title: "Monero" +
(persistentSettings.displayWalletNameInTitleBar && walletName
? " - " + walletName
: "")
minimumWidth: 750
minimumHeight: 450
@@ -65,7 +69,6 @@ ApplicationWindow {
property var currentWallet;
property bool disconnected: currentWallet ? currentWallet.disconnected : false
property var transaction;
property var transactionDescription;
property var walletPassword
property int restoreHeight:0
property bool daemonSynced: false
@@ -141,12 +144,8 @@ ApplicationWindow {
if(seq === "Ctrl+S") middlePanel.state = "Transfer"
else if(seq === "Ctrl+R") middlePanel.state = "Receive"
else if(seq === "Ctrl+K") middlePanel.state = "TxKey"
else if(seq === "Ctrl+H") middlePanel.state = "History"
else if(seq === "Ctrl+B") middlePanel.state = "AddressBook"
else if(seq === "Ctrl+M") middlePanel.state = "Mining"
else if(seq === "Ctrl+I") middlePanel.state = "Sign"
else if(seq === "Ctrl+G") middlePanel.state = "SharedRingDB"
else if(seq === "Ctrl+E") middlePanel.state = "Settings"
else if(seq === "Ctrl+D") middlePanel.state = "Advanced"
else if(seq === "Ctrl+T") middlePanel.state = "Account"
@@ -166,11 +165,8 @@ ApplicationWindow {
else if(middlePanel.state === "Transfer") middlePanel.state = "AddressBook"
else if(middlePanel.state === "AddressBook") middlePanel.state = "Receive"
else if(middlePanel.state === "Receive") middlePanel.state = "History"
else if(middlePanel.state === "History") middlePanel.state = "Mining"
else if(middlePanel.state === "Mining") middlePanel.state = "TxKey"
else if(middlePanel.state === "TxKey") middlePanel.state = "SharedRingDB"
else if(middlePanel.state === "SharedRingDB") middlePanel.state = "Sign"
else if(middlePanel.state === "Sign") middlePanel.state = "Settings"
else if(middlePanel.state === "History") middlePanel.state = "Advanced"
else if(middlePanel.state === "Advanced") middlePanel.state = "Settings"
} else if(seq === "Ctrl+Shift+Backtab" || seq === "Alt+Shift+Backtab") {
/*
if(middlePanel.state === "Settings") middlePanel.state = "Sign"
@@ -182,11 +178,8 @@ ApplicationWindow {
else if(middlePanel.state === "TxKey") middlePanel.state = "Receive"
else if(middlePanel.state === "Receive") middlePanel.state = "Transfer"
*/
if(middlePanel.state === "Settings") middlePanel.state = "Sign"
else if(middlePanel.state === "Sign") middlePanel.state = "SharedRingDB"
else if(middlePanel.state === "SharedRingDB") middlePanel.state = "TxKey"
else if(middlePanel.state === "TxKey") middlePanel.state = "Mining"
else if(middlePanel.state === "Mining") middlePanel.state = "History"
if(middlePanel.state === "Settings") middlePanel.state = "Advanced"
else if(middlePanel.state === "Advanced") middlePanel.state = "History"
else if(middlePanel.state === "History") middlePanel.state = "Receive"
else if(middlePanel.state === "Receive") middlePanel.state = "AddressBook"
else if(middlePanel.state === "AddressBook") middlePanel.state = "Transfer"
@@ -234,12 +227,6 @@ ApplicationWindow {
else
walletManager.setLogLevel(persistentSettings.logLevel)
// setup language
var locale = persistentSettings.locale
if (locale !== "") {
translationManager.setLanguage(locale.split("_")[0]);
}
// Reload transfer page with translations enabled
middlePanel.transferView.onPageCompleted();
@@ -378,13 +365,13 @@ ApplicationWindow {
console.log("Recovering from seed: ", persistentSettings.is_recovering)
console.log("restore Height", persistentSettings.restore_height)
// Use saved daemon rpc login settings
currentWallet.setDaemonLogin(persistentSettings.daemonUsername, persistentSettings.daemonPassword)
if(persistentSettings.useRemoteNode)
currentDaemonAddress = persistentSettings.remoteNodeAddress
else
currentDaemonAddress = localDaemonAddress
if (persistentSettings.useRemoteNode) {
const remoteNode = remoteNodesModel.currentRemoteNode();
currentDaemonAddress = remoteNode.address;
currentWallet.setDaemonLogin(remoteNode.username, remoteNode.password);
} else {
currentDaemonAddress = localDaemonAddress;
}
console.log("initializing with daemon address: ", currentDaemonAddress)
currentWallet.initAsync(
@@ -401,7 +388,7 @@ ApplicationWindow {
}
function isTrustedDaemon() {
return !persistentSettings.useRemoteNode || persistentSettings.is_trusted_daemon;
return !persistentSettings.useRemoteNode || remoteNodesModel.currentRemoteNode().trusted;
}
function usefulName(path) {
@@ -503,21 +490,35 @@ ApplicationWindow {
walletInitialized = true
// check if daemon was already mining and add mining logo if true
middlePanel.miningView.update();
middlePanel.advancedView.miningView.update();
}
}
function onDeviceButtonRequest(code){
prevSplashText = splash.messageText;
splashDisplayedBeforeButtonRequest = splash.visible;
appWindow.showProcessingSplash(qsTr("Please proceed to the device..."));
if (txConfirmationPopup.visible) {
txConfirmationPopup.bottomTextAnimation.running = true
if (!txConfirmationPopup.errorText.visible) {
txConfirmationPopup.bottomText.text = qsTr("Please confirm transaction on the device...") + translationManager.emptyString;
} else {
txConfirmationPopup.bottomText.text = qsTr("Please proceed to the device...") + translationManager.emptyString;
}
} else {
prevSplashText = splash.messageText;
splashDisplayedBeforeButtonRequest = splash.visible;
appWindow.showProcessingSplash(qsTr("Please proceed to the device..."));
}
}
function onDeviceButtonPressed(){
if (splashDisplayedBeforeButtonRequest){
appWindow.showProcessingSplash(prevSplashText);
if (txConfirmationPopup.visible) {
txConfirmationPopup.bottomTextAnimation.running = false;
txConfirmationPopup.bottomText.text = qsTr("Signing transaction in the device...") + translationManager.emptyString;
} else {
hideProcessingSplash();
if (splashDisplayedBeforeButtonRequest){
appWindow.showProcessingSplash(prevSplashText);
} else {
hideProcessingSplash();
}
}
}
@@ -616,7 +617,9 @@ ApplicationWindow {
const callback = function() {
persistentSettings.useRemoteNode = true;
currentDaemonAddress = persistentSettings.remoteNodeAddress;
const remoteNode = remoteNodesModel.currentRemoteNode();
currentDaemonAddress = remoteNode.address;
currentWallet.setDaemonLogin(remoteNode.username, remoteNode.password);
currentWallet.initAsync(
currentDaemonAddress,
isTrustedDaemon(),
@@ -642,6 +645,7 @@ ApplicationWindow {
console.log("disconnecting remote node");
persistentSettings.useRemoteNode = false;
currentDaemonAddress = localDaemonAddress
currentWallet.setDaemonLogin("", "");
currentWallet.initAsync(
currentDaemonAddress,
isTrustedDaemon(),
@@ -714,7 +718,7 @@ ApplicationWindow {
const noSync = appWindow.walletMode === 0;
const bootstrapNodeAddress = persistentSettings.walletMode < 2 ? "auto" : persistentSettings.bootstrapNodeAddress
daemonManager.start(flags, persistentSettings.nettype, persistentSettings.blockchainDataDir, bootstrapNodeAddress, noSync);
daemonManager.start(flags, persistentSettings.nettype, persistentSettings.blockchainDataDir, bootstrapNodeAddress, noSync, persistentSettings.pruneBlockchain);
}
function stopDaemon(callback, splash){
@@ -810,108 +814,81 @@ ApplicationWindow {
return false;
}
function onTransactionCreated(pendingTransaction,address,paymentId,mixinCount){
function onTransactionCreated(pendingTransaction, addresses, paymentId, mixinCount) {
console.log("Transaction created");
hideProcessingSplash();
txConfirmationPopup.bottomText.text = "";
transaction = pendingTransaction;
// validate address;
if (transaction.status !== PendingTransaction.Status_Ok) {
console.error("Can't create transaction: ", transaction.errorString);
informationPopup.title = qsTr("Error") + translationManager.emptyString;
if (currentWallet.connected() == Wallet.ConnectionStatus_WrongVersion)
informationPopup.text = qsTr("Can't create transaction: Wrong daemon version: ") + transaction.errorString
else
informationPopup.text = qsTr("Can't create transaction: ") + transaction.errorString
informationPopup.icon = StandardIcon.Critical
informationPopup.onCloseCallback = null
informationPopup.open();
if (currentWallet.connected() == Wallet.ConnectionStatus_WrongVersion) {
txConfirmationPopup.errorText.text = qsTr("Can't create transaction: Wrong daemon version: ") + transaction.errorString
} else {
txConfirmationPopup.errorText.text = qsTr("Can't create transaction: ") + transaction.errorString
}
// deleting transaction object, we don't want memleaks
currentWallet.disposeTransaction(transaction);
} else if (transaction.txCount == 0) {
informationPopup.title = qsTr("Error") + translationManager.emptyString
informationPopup.text = qsTr("No unmixable outputs to sweep") + translationManager.emptyString
informationPopup.icon = StandardIcon.Information
informationPopup.onCloseCallback = null
informationPopup.open()
console.error("Can't create transaction: ", transaction.errorString);
txConfirmationPopup.errorText.text = qsTr("No unmixable outputs to sweep") + translationManager.emptyString
// deleting transaction object, we don't want memleaks
currentWallet.disposeTransaction(transaction);
} else {
console.log("Transaction created, amount: " + walletManager.displayAmount(transaction.amount)
+ ", fee: " + walletManager.displayAmount(transaction.fee));
// here we show confirmation popup;
transactionConfirmationPopup.title = qsTr("Please confirm transaction:\n") + translationManager.emptyString;
transactionConfirmationPopup.text = "";
transactionConfirmationPopup.text += (address === "" ? "" : (qsTr("Address: ") + address));
transactionConfirmationPopup.text += (paymentId === "" ? "" : (qsTr("\nPayment ID: ") + paymentId));
transactionConfirmationPopup.text += qsTr("\n\nAmount: ") + walletManager.displayAmount(transaction.amount);
transactionConfirmationPopup.text += qsTr("\nFee: ") + walletManager.displayAmount(transaction.fee);
transactionConfirmationPopup.text += qsTr("\nRingsize: ") + (mixinCount + 1);
transactionConfirmationPopup.text += qsTr("\n\nNumber of transactions: ") + transaction.txCount
transactionConfirmationPopup.text += (transactionDescription === "" ? "" : (qsTr("\nDescription: ") + transactionDescription))
for (var i = 0; i < transaction.subaddrIndices.length; ++i){
transactionConfirmationPopup.text += qsTr("\nSpending address index: ") + transaction.subaddrIndices[i];
}
transactionConfirmationPopup.text += translationManager.emptyString;
transactionConfirmationPopup.icon = StandardIcon.Question
transactionConfirmationPopup.open()
// here we update txConfirmationPopup
txConfirmationPopup.transactionAmount = Utils.removeTrailingZeros(walletManager.displayAmount(transaction.amount));
txConfirmationPopup.transactionFee = Utils.removeTrailingZeros(walletManager.displayAmount(transaction.fee));
txConfirmationPopup.confirmButton.text = viewOnly ? qsTr("Save as file") : qsTr("Confirm") + translationManager.emptyString;
txConfirmationPopup.confirmButton.rightIcon = viewOnly ? "" : "qrc:///images/rightArrow.png"
}
}
function getDisplayAmountTotal(recipients) {
const amounts = recipients.map(function (recipient) {
return recipient.amount;
});
const total = walletManager.amountsSumFromStrings(amounts);
return Utils.removeTrailingZeros(walletManager.displayAmount(total));
}
// called on "transfer"
function handlePayment(address, paymentId, amount, mixinCount, priority, description, createFile) {
function handlePayment(recipients, paymentId, mixinCount, priority, description, createFile) {
console.log("Creating transaction: ")
console.log("\taddress: ", address,
console.log("\trecipients: ", recipients,
", payment_id: ", paymentId,
", amount: ", amount,
", mixins: ", mixinCount,
", priority: ", priority,
", description: ", description);
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;
// validate amount;
if (amount !== "(all)") {
var amountxmr = walletManager.amountFromString(amount);
console.log("integer amount: ", amountxmr);
console.log("integer unlocked", currentWallet.unlockedBalance())
if (amountxmr <= 0) {
hideProcessingSplash()
informationPopup.title = qsTr("Error") + translationManager.emptyString;
informationPopup.text = qsTr("Amount is wrong: expected number from %1 to %2")
.arg(walletManager.displayAmount(0))
.arg(walletManager.displayAmount(currentWallet.unlockedBalance()))
+ translationManager.emptyString
informationPopup.icon = StandardIcon.Critical
informationPopup.onCloseCallback = null
informationPopup.open()
return;
} else if (amountxmr > currentWallet.unlockedBalance()) {
hideProcessingSplash()
informationPopup.title = qsTr("Error") + translationManager.emptyString;
informationPopup.text = qsTr("Insufficient funds. Unlocked balance: %1")
.arg(walletManager.displayAmount(currentWallet.unlockedBalance()))
+ translationManager.emptyString
informationPopup.icon = StandardIcon.Critical
informationPopup.onCloseCallback = null
informationPopup.open()
return;
}
const recipientAll = recipients.find(function (recipient) {
return recipient.amount == "(all)";
});
if (recipientAll && recipients.length > 1) {
throw "Sending all requires one destination address";
}
if (amount === "(all)")
currentWallet.createTransactionAllAsync(address, paymentId, mixinCount, priority);
else
currentWallet.createTransactionAsync(address, paymentId, amountxmr, mixinCount, priority);
txConfirmationPopup.bottomTextAnimation.running = false;
txConfirmationPopup.bottomText.text = qsTr("Creating transaction...") + translationManager.emptyString;
txConfirmationPopup.recipients = recipients;
txConfirmationPopup.transactionAmount = recipientAll ? "(all)" : getDisplayAmountTotal(recipients);
txConfirmationPopup.transactionPriority = priority;
txConfirmationPopup.transactionDescription = description;
txConfirmationPopup.open();
if (recipientAll) {
currentWallet.createTransactionAllAsync(recipientAll.address, paymentId, mixinCount, priority);
} else {
const addresses = recipients.map(function (recipient) {
return recipient.address;
});
const amountsxmr = recipients.map(function (recipient) {
return recipient.amount;
});
currentWallet.createTransactionAsync(addresses, paymentId, amountsxmr, mixinCount, priority);
}
}
//Choose where to save transaction
@@ -935,40 +912,27 @@ ApplicationWindow {
function handleSweepUnmixable() {
console.log("Creating transaction: ")
txConfirmationPopup.sweepUnmixable = true;
transaction = currentWallet.createSweepUnmixableTransaction();
if (transaction.status !== PendingTransaction.Status_Ok) {
console.error("Can't create transaction: ", transaction.errorString);
informationPopup.title = qsTr("Error") + translationManager.emptyString;
informationPopup.text = qsTr("Can't create transaction: ") + transaction.errorString
informationPopup.icon = StandardIcon.Critical
informationPopup.onCloseCallback = null
informationPopup.open();
txConfirmationPopup.errorText.text = qsTr("Can't create transaction: ") + transaction.errorString + translationManager.emptyString
// deleting transaction object, we don't want memleaks
currentWallet.disposeTransaction(transaction);
} else if (transaction.txCount == 0) {
informationPopup.title = qsTr("Error") + translationManager.emptyString
informationPopup.text = qsTr("No unmixable outputs to sweep") + translationManager.emptyString
informationPopup.icon = StandardIcon.Information
informationPopup.onCloseCallback = null
informationPopup.open()
console.error("No unmixable outputs to sweep");
txConfirmationPopup.errorText.text = qsTr("No unmixable outputs to sweep") + translationManager.emptyString
// deleting transaction object, we don't want memleaks
currentWallet.disposeTransaction(transaction);
} else {
console.log("Transaction created, amount: " + walletManager.displayAmount(transaction.amount)
+ ", fee: " + walletManager.displayAmount(transaction.fee));
// here we show confirmation popup;
transactionConfirmationPopup.title = qsTr("Confirmation") + translationManager.emptyString
transactionConfirmationPopup.text = qsTr("Please confirm transaction:\n")
+ qsTr("\n\nAmount: ") + walletManager.displayAmount(transaction.amount)
+ qsTr("\nFee: ") + walletManager.displayAmount(transaction.fee)
+ translationManager.emptyString
transactionConfirmationPopup.icon = StandardIcon.Question
transactionConfirmationPopup.open()
txConfirmationPopup.transactionAmount = Utils.removeTrailingZeros(walletManager.displayAmount(transaction.amount));
txConfirmationPopup.transactionFee = Utils.removeTrailingZeros(walletManager.displayAmount(transaction.fee));
// committing transaction
}
txConfirmationPopup.open();
}
// called after user confirms transaction
@@ -986,7 +950,6 @@ ApplicationWindow {
// Store to file
transaction.setFilename(path);
}
appWindow.showProcessingSplash(qsTr("Sending transaction ..."));
currentWallet.commitTransactionAsync(transaction);
}
@@ -1001,13 +964,14 @@ ApplicationWindow {
informationPopup.onCloseCallback = null;
informationPopup.open();
} else {
if (transactionDescription.length > 0) {
if (txConfirmationPopup.transactionDescription.length > 0) {
for (var i = 0; i < txid.length; ++i)
currentWallet.setUserNote(txid[i], transactionDescription);
currentWallet.setUserNote(txid[i], txConfirmationPopup.transactionDescription);
}
// Clear tx fields
middlePanel.transferView.clearFields()
txConfirmationPopup.clearFields()
successfulTxPopup.open(txid)
}
currentWallet.refresh()
@@ -1157,11 +1121,14 @@ ApplicationWindow {
objectName: "appWindow"
visible: true
width: screenWidth > 980 ? 980 : 800
height: screenHeight > maxWindowHeight ? maxWindowHeight : 700
width: Screen.desktopAvailableWidth > 980
? 980
: Math.min(Screen.desktopAvailableWidth, 800)
height: Screen.desktopAvailableHeight > maxWindowHeight
? maxWindowHeight
: Math.min(Screen.desktopAvailableHeight, 700)
color: MoneroComponents.Style.appWindowBackgroundColor
flags: persistentSettings.customDecorations ? Windows.flagsCustomDecorations : Windows.flags
onWidthChanged: x -= 0
Timer {
id: fiatPriceTimer
@@ -1184,7 +1151,7 @@ ApplicationWindow {
}
var key = currency === "xmreur" ? "XXMRZEUR" : "XXMRZUSD";
var ticker = resp.result[key]["o"];
var ticker = resp.result[key]["c"][0];
return ticker;
} else if(url.startsWith("https://api.coingecko.com/api/v3/")){
var key = currency === "xmreur" ? "eur" : "usd";
@@ -1318,8 +1285,10 @@ ApplicationWindow {
}
Component.onCompleted: {
x = (Screen.width - width) / 2
y = (Screen.height - maxWindowHeight) / 2
x = (Screen.desktopAvailableWidth - width) / 2;
y = (Screen.desktopAvailableHeight - height) / 2;
translationManager.setLanguage(persistentSettings.locale.split("_")[0]);
applyWalletMode(persistentSettings.walletMode);
@@ -1366,6 +1335,27 @@ ApplicationWindow {
appWindow.fiatApiRefresh();
appWindow.fiatTimerStart();
}
if (persistentSettings.askDesktopShortcut && !persistentSettings.portable) {
persistentSettings.askDesktopShortcut = false;
if (isTails) {
oshelper.createDesktopEntry();
} else if (isLinux) {
confirmationDialog.title = qsTr("Desktop entry") + translationManager.emptyString;
confirmationDialog.text = qsTr("Would you like to register Monero GUI Desktop entry?") + translationManager.emptyString;
confirmationDialog.icon = StandardIcon.Question;
confirmationDialog.cancelText = qsTr("No") + translationManager.emptyString;
confirmationDialog.okText = qsTr("Yes") + translationManager.emptyString;
confirmationDialog.onAcceptedCallback = function() {
oshelper.createDesktopEntry();
};
confirmationDialog.onRejectedCallback = null;
confirmationDialog.open();
}
}
remoteNodesModel.initialize();
}
MoneroSettings {
@@ -1376,35 +1366,49 @@ ApplicationWindow {
return "";
}
property string language
property string locale
property bool askDesktopShortcut: isLinux
property string language: 'English (US)'
property string language_wallet: 'English'
property string locale: 'en_US'
property string account_name
property string wallet_path
property bool allow_background_mining : false
property bool miningIgnoreBattery : true
property var nettype: NetworkType.MAINNET
property int restore_height : 0
property bool is_trusted_daemon : false
property bool is_trusted_daemon : false // TODO: drop after v0.17.2.0 release
property bool is_recovering : false
property bool is_recovering_from_device : false
property bool customDecorations : true
property string daemonFlags
property int logLevel: 0
property string logCategories: ""
property string daemonUsername: ""
property string daemonPassword: ""
property string daemonUsername: "" // TODO: drop after v0.17.2.0 release
property string daemonPassword: "" // TODO: drop after v0.17.2.0 release
property bool transferShowAdvanced: false
property bool receiveShowAdvanced: false
property bool historyShowAdvanced: false
property bool historyHumanDates: true
property string blockchainDataDir: ""
property bool useRemoteNode: false
property string remoteNodeAddress: ""
property string remoteNodeAddress: "" // TODO: drop after v0.17.2.0 release
property string remoteNodesSerialized: JSON.stringify({
selected: 0,
nodes: remoteNodeAddress != ""
? [{
address: remoteNodeAddress,
username: daemonUsername,
password: daemonPassword,
trusted: is_trusted_daemon,
}]
: [],
})
property string bootstrapNodeAddress: ""
property bool segregatePreForkOutputs: true
property bool keyReuseMitigation2: true
property int segregationHeight: 0
property int kdfRounds: 1
property bool displayWalletNameInTitleBar: true
property bool hideBalance: false
property bool askPasswordBeforeSending: true
property bool lockOnUserInActivity: true
@@ -1414,6 +1418,7 @@ ApplicationWindow {
property bool checkForUpdates: true
property bool autosave: true
property int autosaveMinutes: 10
property bool pruneBlockchain: false
property bool fiatPriceEnabled: false
property bool fiatPriceToggle: false
@@ -1444,6 +1449,88 @@ ApplicationWindow {
}
}
ListModel {
id: remoteNodesModel
property int selected: 0
signal store()
function initialize() {
try {
const remoteNodes = JSON.parse(persistentSettings.remoteNodesSerialized);
for (var index = 0; index < remoteNodes.nodes.length; ++index) {
const remoteNode = remoteNodes.nodes[index];
remoteNodesModel.append(remoteNode);
}
selected = remoteNodes.selected % remoteNodesModel.count || 0;
} catch (e) {
console.error('failed to parse remoteNodesSerialized', e);
}
store.connect(function() {
var remoteNodes = [];
for (var index = 0; index < remoteNodesModel.count; ++index) {
remoteNodes.push(remoteNodesModel.get(index));
}
persistentSettings.remoteNodesSerialized = JSON.stringify({
selected: selected,
nodes: remoteNodes
});
});
}
function appendIfNotExists(newRemoteNode) {
for (var index = 0; index < remoteNodesModel.count; ++index) {
const remoteNode = remoteNodesModel.get(index);
if (remoteNode.address == newRemoteNode.address &&
remoteNode.username == newRemoteNode.username &&
remoteNode.password == newRemoteNode.password &&
remoteNode.trusted == newRemoteNode.trusted) {
return index;
}
}
remoteNodesModel.append(newRemoteNode);
return remoteNodesModel.count - 1;
}
function applyRemoteNode(index) {
selected = index;
const remoteNode = currentRemoteNode();
persistentSettings.useRemoteNode = true;
if (currentWallet) {
currentWallet.setDaemonLogin(remoteNode.username, remoteNode.password);
currentWallet.setTrustedDaemon(remoteNode.trusted);
appWindow.connectRemoteNode();
}
}
function currentRemoteNode() {
if (selected < remoteNodesModel.count) {
return remoteNodesModel.get(selected);
}
return {
address: "",
username: "",
password: "",
trusted: false,
};
}
function removeSelectNextIfNeeded(index) {
remoteNodesModel.remove(index);
if (selected == index) {
applyRemoteNode(selected % remoteNodesModel.count || 0);
} else if (selected > index) {
selected = selected - 1;
}
}
onCountChanged: store()
onDataChanged: store()
onSelectedChanged: store()
}
// Information dialog
StandardDialog {
// dynamically change onclose handler
@@ -1459,10 +1546,11 @@ ApplicationWindow {
}
}
// Confrirmation aka question dialog
StandardDialog {
// Transaction confirmation popup
TxConfirmationDialog {
// dynamically change onclose handler
id: txConfirmationPopup
z: parent.z + 1
id: transactionConfirmationPopup
onAccepted: {
var handleAccepted = function() {
// Save transaction to file if view only wallet
@@ -1523,6 +1611,10 @@ ApplicationWindow {
y: (parent.height - height) / 2
}
MoneroComponents.RemoteNodeDialog {
id: remoteNodeDialog
}
// Choose blockchain folder
FileDialog {
id: blockchainFileDialog
@@ -1694,18 +1786,6 @@ ApplicationWindow {
updateBalance();
}
onTxkeyClicked: {
middlePanel.state = "TxKey";
middlePanel.flickable.contentY = 0;
updateBalance();
}
onSharedringdbClicked: {
middlePanel.state = "SharedRingDB";
middlePanel.flickable.contentY = 0;
updateBalance();
}
onHistoryClicked: {
middlePanel.state = "History";
middlePanel.flickable.contentY = 0;
@@ -1718,14 +1798,8 @@ ApplicationWindow {
updateBalance();
}
onMiningClicked: {
middlePanel.state = "Mining";
middlePanel.flickable.contentY = 0;
updateBalance();
}
onSignClicked: {
middlePanel.state = "Sign";
onAdvancedClicked: {
middlePanel.state = "Advanced";
middlePanel.flickable.contentY = 0;
updateBalance();
}
@@ -1768,7 +1842,9 @@ ApplicationWindow {
anchors.fill: blurredArea
source: blurredArea
radius: 64
visible: passwordDialog.visible || inputDialog.visible || splash.visible || updateDialog.visible || devicePassphraseDialog.visible || successfulTxPopup.visible
visible: passwordDialog.visible || inputDialog.visible || splash.visible || updateDialog.visible ||
devicePassphraseDialog.visible || txConfirmationPopup.visible || successfulTxPopup.visible ||
remoteNodeDialog.visible
}
@@ -1821,7 +1897,7 @@ ApplicationWindow {
TitleBar {
id: titleBar
visible: persistentSettings.customDecorations && middlePanel.state !== "Merchant"
walletName: appWindow.walletName
walletName: persistentSettings.displayWalletNameInTitleBar ? appWindow.walletName : ""
anchors.left: parent.left
anchors.right: parent.right
onCloseClicked: appWindow.close();
@@ -1874,11 +1950,6 @@ ApplicationWindow {
function toggleLanguageView(){
languageSidebar.isOpened ? languageSidebar.close() : languageSidebar.open();
resetLanguageFields()
// update after changing language from settings page
if (persistentSettings.language != wizard.language_language) {
persistentSettings.language = wizard.language_language
persistentSettings.locale = wizard.language_locale
}
}
Timer {
@@ -1953,12 +2024,13 @@ ApplicationWindow {
return;
}
const simpleModeFlags = "--enable-dns-blocklist --out-peers 16";
if (appWindow.daemonRunning) {
appWindow.stopDaemon(function() {
appWindow.startDaemon("")
appWindow.startDaemon(simpleModeFlags)
});
} else {
appWindow.startDaemon("");
appWindow.startDaemon(simpleModeFlags);
}
}
@@ -2162,6 +2234,7 @@ ApplicationWindow {
passwordDialog.onRejectedCallback = function() { appWindow.showWizard(); }
if (inputDialogVisible) inputDialog.close()
remoteNodeDialog.close();
passwordDialog.open();
}

2
monero

Submodule monero updated: 76cc82c292...f6e63ef260

View File

@@ -1,581 +0,0 @@
# qml components require at least QT 5.9.7
lessThan (QT_MAJOR_VERSION, 5) | lessThan (QT_MINOR_VERSION, 9) {
error("Can't build with Qt $${QT_VERSION}. Use at least Qt 5.9.7")
}
TEMPLATE = app
QT += svg qml gui-private quick widgets
WALLET_ROOT=$$PWD/monero
CONFIG += c++11 link_pkgconfig
packagesExist(libusb-1.0) {
PKGCONFIG += libusb-1.0
}
packagesExist(hidapi-libusb) {
PKGCONFIG += hidapi-libusb
}
GCC_VERSION = $$system("g++ -dumpversion")
GCC_VERSION = $$split(GCC_VERSION, .)
GCC_VERSION_MAJOR = $$member(GCC_VERSION, 0)
GCC_VERSION_MINOR = $$member(GCC_VERSION, 1)
greaterThan(GCC_VERSION_MAJOR, 9) | if(equals(GCC_VERSION_MAJOR, 9) : greaterThan(GCC_VERSION_MINOR, 0)) {
GCC_9_1_OR_GREATER = TRUE
}
!win32 | !isEmpty(GCC_9_1_OR_GREATER) {
QMAKE_CXXFLAGS += -fPIC -fstack-protector -fstack-protector-strong
QMAKE_LFLAGS += -fstack-protector -fstack-protector-strong
}
!win32 {
packagesExist(protobuf) {
PKGCONFIG += protobuf
}
}
# cleaning "auto-generated" bitmonero directory on "make distclean"
QMAKE_DISTCLEAN += -r $$WALLET_ROOT
INCLUDEPATH += $$WALLET_ROOT/include \
$$PWD/src/libwalletqt \
$$PWD/src/QR-Code-generator \
$$PWD/src \
$$WALLET_ROOT/src \
$$WALLET_ROOT/external/easylogging++ \
$$WALLET_ROOT/contrib/epee/include
HEADERS += \
src/main/filter.h \
src/main/clipboardAdapter.h \
src/main/oscursor.h \
src/libwalletqt/WalletManager.h \
src/libwalletqt/Wallet.h \
src/libwalletqt/PassphraseHelper.h \
src/libwalletqt/PendingTransaction.h \
src/libwalletqt/TransactionHistory.h \
src/libwalletqt/TransactionInfo.h \
src/libwalletqt/QRCodeImageProvider.h \
src/libwalletqt/Transfer.h \
src/NetworkType.h \
src/main/oshelper.h \
src/TranslationManager.h \
src/model/TransactionHistoryModel.h \
src/model/TransactionHistorySortFilterModel.h \
src/QR-Code-generator/BitBuffer.hpp \
src/QR-Code-generator/QrCode.hpp \
src/QR-Code-generator/QrSegment.hpp \
src/model/AddressBookModel.h \
src/libwalletqt/AddressBook.h \
src/model/SubaddressModel.h \
src/libwalletqt/Subaddress.h \
src/model/SubaddressAccountModel.h \
src/libwalletqt/SubaddressAccount.h \
src/zxcvbn-c/zxcvbn.h \
src/libwalletqt/UnsignedTransaction.h \
src/main/Logger.h \
src/main/MainApp.h \
src/qt/downloader.h \
src/qt/FutureScheduler.h \
src/qt/ipc.h \
src/qt/KeysFiles.h \
src/qt/network.h \
src/qt/utils.h \
src/qt/macoshelper.h \
src/qt/MoneroSettings.h \
src/qt/TailsOS.h
SOURCES += src/main/main.cpp \
src/main/filter.cpp \
src/main/clipboardAdapter.cpp \
src/main/oscursor.cpp \
src/libwalletqt/WalletManager.cpp \
src/libwalletqt/WalletListenerImpl.cpp \
src/libwalletqt/Wallet.cpp \
src/libwalletqt/PassphraseHelper.cpp \
src/libwalletqt/PendingTransaction.cpp \
src/libwalletqt/TransactionHistory.cpp \
src/libwalletqt/TransactionInfo.cpp \
src/libwalletqt/QRCodeImageProvider.cpp \
src/main/oshelper.cpp \
src/openpgp/openpgp.cpp \
src/TranslationManager.cpp \
src/model/TransactionHistoryModel.cpp \
src/model/TransactionHistorySortFilterModel.cpp \
src/QR-Code-generator/BitBuffer.cpp \
src/QR-Code-generator/QrCode.cpp \
src/QR-Code-generator/QrSegment.cpp \
src/model/AddressBookModel.cpp \
src/libwalletqt/AddressBook.cpp \
src/model/SubaddressModel.cpp \
src/libwalletqt/Subaddress.cpp \
src/model/SubaddressAccountModel.cpp \
src/libwalletqt/SubaddressAccount.cpp \
src/zxcvbn-c/zxcvbn.c \
src/libwalletqt/UnsignedTransaction.cpp \
src/main/Logger.cpp \
src/main/MainApp.cpp \
src/qt/downloader.cpp \
src/qt/FutureScheduler.cpp \
src/qt/ipc.cpp \
src/qt/KeysFiles.cpp \
src/qt/network.cpp \
src/qt/updater.cpp \
src/qt/utils.cpp \
src/qt/MoneroSettings.cpp \
src/qt/TailsOS.cpp
CONFIG(DISABLE_PASS_STRENGTH_METER) {
HEADERS -= src/zxcvbn-c/zxcvbn.h
SOURCES -= src/zxcvbn-c/zxcvbn.c
DEFINES += "DISABLE_PASS_STRENGTH_METER"
}
!ios {
HEADERS += src/daemon/DaemonManager.h
SOURCES += src/daemon/DaemonManager.cpp
}
lupdate_only {
SOURCES = *.qml \
components/*.qml \
components/effects/*.qml \
pages/*.qml \
pages/settings/*.qml \
pages/merchant/*.qml \
wizard/*.qml \
wizard/*js
}
# Linker flags required by Trezor
TREZOR_LINKER = $$cat($$WALLET_ROOT/lib/trezor_link_flags.txt)
ios:armv7 {
message("target is armv7")
LIBS += \
-L$$PWD/../ofxiOSBoost/build/libs/boost/lib/armv7 \
}
ios:arm64 {
message("target is arm64")
LIBS += \
-L$$PWD/../ofxiOSBoost/build/libs/boost/lib/arm64 \
}
LIBS_COMMON = \
-lgcrypt \
-lgpg-error \
-lwallet_merged \
-llmdb \
-lepee \
-lunbound \
-lsodium \
-leasylogging \
-lrandomx
!ios:!android {
LIBS += -L$$WALLET_ROOT/lib \
$$LIBS_COMMON
}
android {
message("Host is Android")
LIBS += -L$$WALLET_ROOT/lib \
$$LIBS_COMMON
}
QMAKE_CXXFLAGS += -Werror -Wformat -Wformat-security
QMAKE_CFLAGS += -Werror -Wformat -Wformat-security
QMAKE_CXXFLAGS_RELEASE += -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1 -O2
QMAKE_CFLAGS_RELEASE += -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1 -O2
ios {
message("Host is IOS")
QMAKE_LFLAGS += -v
QMAKE_IOS_DEVICE_ARCHS = arm64
CONFIG += arm64
LIBS += -L$$WALLET_ROOT/lib-ios \
$$LIBS_COMMON
LIBS+= \
-L$$PWD/../OpenSSL-for-iPhone/lib \
-L$$PWD/../ofxiOSBoost/build/libs/boost/lib/arm64 \
-lboost_serialization \
-lboost_thread \
-lboost_system \
-lboost_date_time \
-lboost_filesystem \
-lboost_regex \
-lboost_chrono \
-lboost_program_options \
-lssl \
-lcrypto \
-ldl
}
CONFIG(WITH_SCANNER) {
if( greaterThan(QT_MINOR_VERSION, 5) ) {
message("using camera scanner")
QT += multimedia
DEFINES += "WITH_SCANNER"
INCLUDEPATH += $$PWD/src/QR-Code-scanner
HEADERS += \
src/QR-Code-scanner/QrScanThread.h \
src/QR-Code-scanner/QrCodeScanner.h
SOURCES += \
src/QR-Code-scanner/QrScanThread.cpp \
src/QR-Code-scanner/QrCodeScanner.cpp
android {
INCLUDEPATH += $$PWD/../ZBar/include
LIBS += -lzbarjni -liconv
} else {
LIBS += -lzbar
macx {
ZBAR_DIR = $$system(brew --prefix zbar, lines, EXIT_CODE)
equals(EXIT_CODE, 0) {
INCLUDEPATH += $$ZBAR_DIR/include
} else {
INCLUDEPATH += /usr/local/include
}
}
}
} else {
message("Skipping camera scanner because of Incompatible Qt Version !")
}
}
# currently we only support x86 build as qt.io only provides prebuilt qt for x86 mingw
win32 {
# QMAKE_HOST.arch is unreliable, will allways report 32bit if mingw32 shell is run.
# Obtaining arch through uname should be reliable. This also fixes building the project in Qt creator without changes.
MSYS_HOST_ARCH = $$system(uname -a | grep -o "x86_64")
# WIN64 Host settings
contains(MSYS_HOST_ARCH, x86_64) {
message("Host is 64bit")
MSYS_ROOT_PATH=c:/msys64
# WIN32 Host settings
} else {
message("Host is 32bit")
MSYS_ROOT_PATH=c:/msys32
}
# WIN64 Target settings
contains(QMAKE_HOST.arch, x86_64) {
MSYS_MINGW_PATH=/mingw64
# WIN32 Target settings
} else {
MSYS_MINGW_PATH=/mingw32
}
MSYS_PATH=$$MSYS_ROOT_PATH$$MSYS_MINGW_PATH
# boost root path
BOOST_PATH=$$MSYS_PATH/boost
BOOST_MINGW_PATH=$$MSYS_MINGW_PATH/boost
LIBS+=-L$$MSYS_PATH/lib
LIBS+=-L$$MSYS_MINGW_PATH/lib
LIBS+=-L$$BOOST_PATH/lib
LIBS+=-L$$BOOST_MINGW_PATH/lib
QMAKE_LFLAGS += -static-libgcc -static-libstdc++
LIBS+= \
-Wl,-Bdynamic \
-lwinscard \
-lwsock32 \
-lIphlpapi \
-lcrypt32 \
-lhidapi \
-lgdi32 $$TREZOR_LINKER \
-Wl,-Bstatic \
-lboost_serialization-mt \
-lboost_thread-mt \
-lboost_system-mt \
-lboost_date_time-mt \
-lboost_filesystem-mt \
-lboost_regex-mt \
-lboost_chrono-mt \
-lboost_program_options-mt \
-lboost_locale-mt \
-licuio \
-licuin \
-licuuc \
-licudt \
-licutu \
-liconv \
-lstdc++ \
-lpthread \
-lsetupapi \
-lssl \
-lsodium \
-lcrypto \
-lws2_32 \
-lole32
!contains(QMAKE_TARGET.arch, x86_64) {
message("Target is 32bit")
## Windows x86 (32bit) specific build here
## there's 2Mb stack in libwallet allocated internally, so we set stack=4Mb
## this fixes app crash for x86 Windows build
QMAKE_LFLAGS += -Wl,--stack,4194304
} else {
message("Target is 64bit")
}
QMAKE_LFLAGS += -Wl,--dynamicbase -Wl,--nxcompat
}
linux {
CONFIG(static) {
message("using static libraries")
LIBS+= -Wl,-Bstatic
QMAKE_LFLAGS += -static-libgcc -static-libstdc++
QMAKE_LIBDIR += /usr/local/ssl/lib
# contains(QT_ARCH, x86_64) {
LIBS+= -lunbound \
-lusb-1.0 \
-lhidapi-hidraw \
-ludev
# }
} else {
# On some distro's we need to add dynload
LIBS+= -ldl
}
LIBS+= \
-lboost_serialization \
-lboost_thread \
-lboost_system \
-lboost_date_time \
-lboost_filesystem \
-lboost_regex \
-lboost_chrono \
-lboost_program_options \
-lssl \
-llmdb \
-lsodium \
-lhidapi-libusb \
-lcrypto $$TREZOR_LINKER
if(!android) {
LIBS+= \
-Wl,-Bdynamic \
-lGL \
-lX11
}
# currently monero has an issue with "static" build and linunwind-dev,
# so we link libunwind-dev only for non-Ubuntu distros
CONFIG(libunwind_off) {
message(Building without libunwind)
} else {
message(Building with libunwind)
LIBS += -Wl,-Bdynamic -lunwind
}
QMAKE_LFLAGS += -pie -Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack
}
macx {
# mixing static and shared libs are not supported on mac
# CONFIG(static) {
# message("using static libraries")
# LIBS+= -Wl,-Bstatic
# }
OPENSSL_DIR = $$system(brew --prefix openssl, lines, EXIT_CODE)
!equals(EXIT_CODE, 0) {
OPENSSL_DIR = /usr/local/ssl
}
OPENSSL_LIBRARY_DIR = $$OPENSSL_DIR/lib
INCLUDEPATH += $$OPENSSL_DIR/include
BOOST_DIR = $$system(brew --prefix boost, lines, EXIT_CODE)
equals(EXIT_CODE, 0) {
INCLUDEPATH += $$BOOST_DIR/include
} else {
INCLUDEPATH += /usr/local/include
}
GCRYPT_DIR = $$system(brew --prefix libgcrypt, lines, EXIT_CODE)
equals(EXIT_CODE, 0) {
INCLUDEPATH += $$GCRYPT_DIR/include
} else {
INCLUDEPATH += /usr/local/include
}
GPGP_ERROR_DIR = $$system(brew --prefix libgpg-error, lines, EXIT_CODE)
equals(EXIT_CODE, 0) {
INCLUDEPATH += $$GPGP_ERROR_DIR/include
} else {
INCLUDEPATH += /usr/local/include
}
SODIUM_DIR = $$system(brew --prefix libsodium, lines, EXIT_CODE)
equals(EXIT_CODE, 0) {
INCLUDEPATH += $$SODIUM_DIR/include
} else {
INCLUDEPATH += /usr/local/include
}
QT += macextras
OBJECTIVE_SOURCES += src/qt/macoshelper.mm
LIBS+= -Wl,-dead_strip
LIBS+= -Wl,-dead_strip_dylibs
LIBS+= -Wl,-bind_at_load
LIBS+= \
-L/usr/local/lib \
-L$$OPENSSL_LIBRARY_DIR \
-L/usr/local/opt/boost/lib \
-lboost_serialization \
-lboost_thread-mt \
-lboost_system \
-lboost_date_time \
-lboost_filesystem \
-lboost_regex \
-lboost_chrono \
-lboost_program_options \
-framework CoreFoundation \
-framework AppKit \
-lhidapi \
-lssl \
-lsodium \
-lcrypto \
-ldl $$TREZOR_LINKER
QMAKE_LFLAGS += -pie
}
# translation stuff
TRANSLATIONS = $$files($$PWD/translations/monero-core_*.ts)
CONFIG(release, debug|release) {
DESTDIR = release/bin
LANGUPD_OPTIONS = -locations none -no-ui-lines -no-obsolete
LANGREL_OPTIONS = -compress -nounfinished -removeidentical
} else {
DESTDIR = debug/bin
LANGUPD_OPTIONS =
# LANGREL_OPTIONS = -markuntranslated "MISS_TR "
}
TRANSLATION_TARGET_DIR = $$OUT_PWD/translations
!ios {
isEmpty(QMAKE_LUPDATE) {
win32:LANGUPD = $$[QT_INSTALL_BINS]\lupdate.exe
else:LANGUPD = $$[QT_INSTALL_BINS]/lupdate
}
isEmpty(QMAKE_LRELEASE) {
win32:LANGREL = $$[QT_INSTALL_BINS]\lrelease.exe
else:LANGREL = $$[QT_INSTALL_BINS]/lrelease
}
langupd.command = \
$$LANGUPD $$LANGUPD_OPTIONS $$shell_path($$_PRO_FILE) -ts $$_PRO_FILE_PWD/$$TRANSLATIONS
langrel.depends = langupd
langrel.input = TRANSLATIONS
langrel.output = $$TRANSLATION_TARGET_DIR/${QMAKE_FILE_BASE}.qm
langrel.commands = \
$$LANGREL $$LANGREL_OPTIONS ${QMAKE_FILE_IN} -qm $$TRANSLATION_TARGET_DIR/${QMAKE_FILE_BASE}.qm
langrel.CONFIG += no_link
QMAKE_EXTRA_TARGETS += langupd deploy deploy_win
QMAKE_EXTRA_COMPILERS += langrel
# Compile an initial version of translation files when running qmake
# the first time and generate the resource file for translations.
!exists($$TRANSLATION_TARGET_DIR) {
mkpath($$TRANSLATION_TARGET_DIR)
}
qrc_entry = "<RCC>"
qrc_entry += ' <qresource prefix="/">'
write_file($$TRANSLATION_TARGET_DIR/translations.qrc, qrc_entry)
for(tsfile, TRANSLATIONS) {
qmfile = $$TRANSLATION_TARGET_DIR/$$basename(tsfile)
qmfile ~= s/.ts$/.qm/
system($$LANGREL $$LANGREL_OPTIONS $$tsfile -qm $$qmfile)
qrc_entry = " <file>$$basename(qmfile)</file>"
write_file($$TRANSLATION_TARGET_DIR/translations.qrc, qrc_entry, append)
}
qrc_entry = " </qresource>"
qrc_entry += "</RCC>"
write_file($$TRANSLATION_TARGET_DIR/translations.qrc, qrc_entry, append)
RESOURCES += $$TRANSLATION_TARGET_DIR/translations.qrc
}
# Update: no issues with the "slow link process" anymore,
# for development, just build debug version of libwallet_merged lib
# by invoking 'get_libwallet_api.sh Debug'
# so we update translations everytime even for debug build
PRE_TARGETDEPS += langupd compiler_langrel_make_all
RESOURCES += qml.qrc
CONFIG += qtquickcompiler
# Additional import path used to resolve QML modules in Qt Creator's code model
QML_IMPORT_PATH = fonts
# Default rules for deployment.
include(deployment.pri)
macx {
deploy.commands += macdeployqt $$sprintf("%1/%2/%3.app", $$OUT_PWD, $$DESTDIR, $$TARGET) -qmldir=$$PWD
}
win32 {
deploy.commands += windeployqt $$sprintf("%1/%2/%3.exe", $$OUT_PWD, $$DESTDIR, $$TARGET) -no-translations -qmldir=$$PWD
# Win64 msys2 deploy settings
contains(QMAKE_HOST.arch, x86_64) {
deploy.commands += $$escape_expand(\n\t) $$PWD/windeploy_helper.sh $$DESTDIR
}
}
linux:!android {
deploy.commands += $$escape_expand(\n\t) $$PWD/linuxdeploy_helper.sh $$DESTDIR $$TARGET
}
android{
deploy.commands += make install INSTALL_ROOT=$$DESTDIR && androiddeployqt --input android-libmonero-wallet-gui.so-deployment-settings.json --output $$DESTDIR --deployment bundled --android-platform android-21 --jdk /usr/lib/jvm/java-8-openjdk-amd64 -qmldir=$$PWD
}
OTHER_FILES += \
.gitignore \
$$TRANSLATIONS
DISTFILES += \
notes.txt \
monero/src/wallet/CMakeLists.txt
VERSION = $$cat('version.js', lines)
VERSION = $$find(VERSION, 'GUI_VERSION')
VERSION_LONG = $$replace(VERSION, '.*\"(.*)\"', '\1')
VERSION = $$replace(VERSION, '.*(\d+\.\d+\.\d+\.\d+).*', '\1')
# windows application icon
RC_ICONS = images/appicon.ico
# mac Info.plist & application icon
QMAKE_INFO_PLIST = $$PWD/share/Info.plist
macx {
QMAKE_POST_LINK += sed -i "''" -e "s/@VERSION@/$$VERSION/g" -e "s/@VERSION_LONG@/$$VERSION_LONG/g" "$$sprintf("%1/%2/%3.app", $$OUT_PWD, $$DESTDIR, $$TARGET)/Contents/Info.plist";
}
ICON = $$PWD/images/appicon.icns

View File

@@ -190,7 +190,7 @@ Rectangle {
height: subaddressAccountListRow.subaddressAccountListItemHeight
width: parent ? parent.width : undefined
Layout.fillWidth: true
color: "transparent"
color: itemMouseArea.containsMouse || index === currentAccountIndex ? MoneroComponents.Style.titleBarButtonHoverColor : "transparent"
Rectangle {
color: MoneroComponents.Style.appWindowBorderColor
@@ -226,7 +226,7 @@ Rectangle {
MoneroComponents.Label {
id: nameLabel
color: MoneroComponents.Style.dimmedFontColor
color: index === currentAccountIndex ? MoneroComponents.Style.defaultFontColor : MoneroComponents.Style.dimmedFontColor
anchors.verticalCenter: parent.verticalCenter
anchors.left: idLabel.right
anchors.leftMargin: 6
@@ -276,11 +276,10 @@ Rectangle {
}
MouseArea {
id: itemMouseArea
cursorShape: Qt.PointingHandCursor
anchors.fill: parent
hoverEnabled: true
onEntered: tableItem2.color = MoneroComponents.Style.titleBarButtonHoverColor
onExited: tableItem2.color = "transparent"
onClicked: {
appWindow.currentWallet.switchSubaddressAccount(index);
if (selectAndSend)

View File

@@ -132,13 +132,13 @@ Rectangle {
delegate: Rectangle {
id: tableItem2
height: addressBookListRow.addressBookListItemHeight
width: parent.width
width: parent ? parent.width : undefined
Layout.fillWidth: true
color: "transparent"
function doSend() {
console.log("Sending to: ", address +" "+ paymentId);
middlePanel.sendTo(address, paymentId, description);
middlePanel.sendTo(address, paymentId);
leftPanel.selectItem(middlePanel.state)
}
@@ -314,16 +314,16 @@ Rectangle {
}
}
inlineButton.text: FontAwesome.qrcode
inlineButton.fontPixelSize: 22
inlineButton.fontFamily: FontAwesome.fontFamily
inlineButton.textColor: MoneroComponents.Style.defaultFontColor
inlineButton.buttonColor: MoneroComponents.Style.orange
inlineButton.onClicked: {
cameraUi.state = "Capture"
cameraUi.qrcode_decoded.connect(root.updateFromQrCode)
MoneroComponents.InlineButton {
buttonColor: MoneroComponents.Style.orange
fontFamily: FontAwesome.fontFamily
text: FontAwesome.qrcode
visible : appWindow.qrScannerEnabled && !addressLine.text
onClicked: {
cameraUi.state = "Capture"
cameraUi.qrcode_decoded.connect(root.updateFromQrCode)
}
}
inlineButtonVisible : appWindow.qrScannerEnabled && !addressLine.text
}
MoneroComponents.StandardButton {

148
pages/Advanced.qml Normal file
View File

@@ -0,0 +1,148 @@
// Copyright (c) 2021, The Monero Project
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import QtQuick 2.9
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import QtQuick.Layouts 1.1
import "../components" as MoneroComponents
import "."
ColumnLayout {
id: root
Layout.fillWidth: true
Layout.preferredHeight: 900
spacing: 0
property int panelHeight: 900
property alias miningView: stateView.miningView
property alias state: stateView.state
MoneroComponents.Navbar {
Layout.alignment: Qt.AlignHCenter
Layout.topMargin: height
Layout.bottomMargin: height
MoneroComponents.NavbarItem {
active: state == "Mining"
text: qsTr("Mining") + translationManager.emptyString
onSelected: state = "Mining"
}
MoneroComponents.NavbarItem {
active: state == "Prove"
text: qsTr("Prove/check") + translationManager.emptyString
onSelected: state = "Prove"
}
MoneroComponents.NavbarItem {
active: state == "SharedRingDB"
text: qsTr("Shared RingDB") + translationManager.emptyString
onSelected: state = "SharedRingDB"
}
MoneroComponents.NavbarItem {
active: state == "Sign"
text: qsTr("Sign/verify") + translationManager.emptyString
onSelected: state = "Sign"
}
}
Rectangle{
id: stateView
property Item currentView
property Item previousView
property Mining miningView: Mining { }
property TxKey prooveView: TxKey { }
property SharedRingDB sharedRingDBView: SharedRingDB { }
property Sign signView: Sign { }
Layout.fillWidth: true
Layout.preferredHeight: panelHeight
color: "transparent"
state: "Mining"
onCurrentViewChanged: {
if (previousView) {
if (typeof previousView.onPageClosed === "function") {
previousView.onPageClosed();
}
}
previousView = currentView
if (currentView) {
stackView.replace(currentView)
if (typeof currentView.onPageCompleted === "function") {
currentView.onPageCompleted();
}
}
}
states: [
State {
name: "Mining"
PropertyChanges { target: stateView; currentView: stateView.miningView }
PropertyChanges { target: root; panelHeight: stateView.miningView.miningHeight + 140 }
}, State {
name: "Prove"
PropertyChanges { target: stateView; currentView: stateView.prooveView }
PropertyChanges { target: root; panelHeight: stateView.prooveView.txkeyHeight + 140 }
}, State {
name: "SharedRingDB"
PropertyChanges { target: stateView; currentView: stateView.sharedRingDBView }
PropertyChanges { target: root; panelHeight: stateView.sharedRingDBView.panelHeight + 140 }
}, State {
name: "Sign"
PropertyChanges { target: stateView; currentView: stateView.signView }
PropertyChanges { target: root; panelHeight: stateView.signView.signHeight + 140 }
}
]
StackView {
id: stackView
initialItem: stateView.miningView
anchors.fill: parent
clip: false // otherwise animation will affect left panel
delegate: StackViewDelegate {
pushTransition: StackViewTransition {
PropertyAnimation {
target: enterItem
property: "x"
from: 0 - target.width
to: 0
duration: 300
easing.type: Easing.OutCubic
}
PropertyAnimation {
target: exitItem
property: "x"
from: 0
to: target.width
duration: 300
easing.type: Easing.OutCubic
}
}
}
}
}
}

View File

@@ -127,7 +127,7 @@ Rectangle {
image: "qrc:///images/whiteDropIndicator.png"
fontAwesomeFallbackIcon: FontAwesome.arrowDown
fontAwesomeFallbackSize: 14
rotation: sortAndFilter.collapsed ? 0 : 180
rotation: sortAndFilter.collapsed ? 180 : 0
color: MoneroComponents.Style.defaultFontColor
MouseArea {
@@ -771,7 +771,6 @@ Rectangle {
return qsTr("Waiting confirmation...") + translationManager.emptyString;
}
if (address) {
const addressBookName = currentWallet ? currentWallet.addressBook.getDescription(address) : null;
return (addressBookName ? FontAwesome.addressBook + " " + addressBookName : TxUtils.addressTruncate(address, 8));
}
if (amount != 0) {
@@ -780,8 +779,6 @@ Rectangle {
return qsTr("My wallet") + translationManager.emptyString;
}
} else {
const receivingAddress = currentWallet ? currentWallet.address(subaddrAccount, subaddrIndex) : null;
const receivingAddressLabel = currentWallet ? appWindow.currentWallet.getSubaddressLabel(subaddrAccount, subaddrIndex) : null;
if (receivingAddress) {
if (subaddrIndex == 0) {
return qsTr("Address") + " #0" + " (" + qsTr("Primary address") + ")" + translationManager.emptyString;
@@ -1417,6 +1414,12 @@ Rectangle {
txs.push(item);
} else if(item.address !== "" && item.address.toLowerCase().startsWith(root.sortSearchString.toLowerCase())){
txs.push(item);
} else if(item.receivingAddress !== "" && item.receivingAddress.toLowerCase().startsWith(root.sortSearchString.toLowerCase())){
txs.push(item);
} else if(item.receivingAddressLabel !== "" && item.receivingAddressLabel.toLowerCase().startsWith(root.sortSearchString.toLowerCase())){
txs.push(item);
} else if(item.addressBookName !== "" && item.addressBookName.toLowerCase().startsWith(root.sortSearchString.toLowerCase())){
txs.push(item);
} else if(typeof item.blockheight !== "undefined" && item.blockheight.toString().startsWith(root.sortSearchString)) {
txs.push(item);
} else if(item.tx_note.toLowerCase().indexOf(root.sortSearchString.toLowerCase()) !== -1) {
@@ -1522,8 +1525,16 @@ Rectangle {
var tx_note = currentWallet.getUserNote(hash);
var address = "";
if(isout) {
var addressBookName = "";
var receivingAddress = "";
var receivingAddressLabel = "";
if (isout) {
address = TxUtils.destinationsToAddress(destinations);
addressBookName = currentWallet ? currentWallet.addressBook.getDescription(address) : null;
} else {
receivingAddress = currentWallet ? currentWallet.address(subaddrAccount, subaddrIndex) : null;
receivingAddressLabel = currentWallet ? appWindow.currentWallet.getSubaddressLabel(subaddrAccount, subaddrIndex) : null;
}
if (isout)
@@ -1541,6 +1552,7 @@ Rectangle {
"hash": hash,
"paymentId": paymentId,
"address": address,
"addressBookName": addressBookName,
"destinations": destinations,
"tx_note": tx_note,
"dateHuman": dateHuman,
@@ -1551,6 +1563,8 @@ Rectangle {
"fee": fee,
"confirmations": confirmations,
"confirmationsRequired": confirmationsRequired,
"receivingAddress": receivingAddress,
"receivingAddressLabel": receivingAddressLabel,
"subaddrAccount": subaddrAccount,
"subaddrIndex": subaddrIndex
});

View File

@@ -42,7 +42,7 @@ Rectangle {
id: mainLayout
Layout.fillWidth: true
anchors.margins: 20
anchors.topMargin: 40
anchors.topMargin: 0
anchors.left: parent.left
anchors.top: parent.top
anchors.right: parent.right

View File

@@ -107,7 +107,7 @@ Rectangle {
height: subaddressListRow.subaddressListItemHeight
width: parent ? parent.width : undefined
Layout.fillWidth: true
color: "transparent"
color: itemMouseArea.containsMouse || index === appWindow.current_subaddress_table_index ? MoneroComponents.Style.titleBarButtonHoverColor : "transparent"
Rectangle{
anchors.right: parent.right
@@ -143,7 +143,7 @@ Rectangle {
MoneroComponents.Label {
id: nameLabel
color: MoneroComponents.Style.dimmedFontColor
color: index === appWindow.current_subaddress_table_index ? MoneroComponents.Style.defaultFontColor : MoneroComponents.Style.dimmedFontColor
anchors.verticalCenter: parent.verticalCenter
anchors.left: idLabel.right
anchors.leftMargin: 6
@@ -167,11 +167,10 @@ Rectangle {
}
MouseArea {
id: itemMouseArea
cursorShape: Qt.PointingHandCursor
anchors.fill: parent
hoverEnabled: true
onEntered: tableItem2.color = MoneroComponents.Style.titleBarButtonHoverColor
onExited: tableItem2.color = "transparent"
onClicked: subaddressListView.currentIndex = index;
}
}
@@ -299,18 +298,6 @@ Rectangle {
onClicked: qrFileDialog.open()
}
MoneroComponents.StandardButton {
Layout.preferredWidth: 220
small: true
text: FontAwesome.clipboard + " %1".arg(qsTr("Copy to clipboard")) + translationManager.emptyString
label.font.family: FontAwesome.fontFamily
fontSize: 13
onClicked: {
clipboard.setText(TxUtils.makeQRCodeString(appWindow.current_address));
appWindow.showStatusMessage(qsTr("Copied to clipboard") + translationManager.emptyString, 3);
}
}
MoneroComponents.StandardButton {
Layout.preferredWidth: 220
small: true

View File

@@ -81,8 +81,7 @@ Rectangle {
id: mainLayout
Layout.fillWidth: true
anchors.margins: 20
anchors.topMargin: 40
anchors.topMargin: 0
anchors.left: parent.left
anchors.top: parent.top
anchors.right: parent.right

View File

@@ -89,8 +89,7 @@ Rectangle {
id: mainLayout
Layout.fillWidth: true
anchors.margins: 20
anchors.topMargin: 40
anchors.topMargin: 0
anchors.left: parent.left
anchors.top: parent.top
anchors.right: parent.right

View File

@@ -26,6 +26,7 @@
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import QtQml.Models 2.2
import QtQuick 2.9
import QtQuick.Controls 1.4
import QtQuick.Layouts 1.1
@@ -44,8 +45,7 @@ import "../js/Utils.js" as Utils
Rectangle {
id: root
signal paymentClicked(string address, string paymentId, string amount, int mixinCount,
int priority, string description)
signal paymentClicked(var recipients, string paymentId, int mixinCount, int priority, string description)
signal sweepUnmixableClicked()
color: "transparent"
@@ -61,19 +61,18 @@ Rectangle {
}
// There are sufficient unlocked funds available
if (walletManager.amountFromString(amountLine.text) > appWindow.getUnlockedBalance()) {
if (recipientModel.getAmountTotal() > appWindow.getUnlockedBalance()) {
return qsTr("Amount is more than unlocked balance.") + translationManager.emptyString;
}
if (addressLine.text)
{
if (!recipientModel.hasEmptyAddress()) {
// Address is valid
if (!TxUtils.checkAddress(addressLine.text, appWindow.persistentSettings.nettype)) {
if (recipientModel.hasInvalidAddress()) {
return qsTr("Address is invalid.") + translationManager.emptyString;
}
// Amount is nonzero
if (!amountLine.text || parseFloat(amountLine.text) <= 0) {
if (recipientModel.hasEmptyAmount()) {
return qsTr("Enter an amount.") + translationManager.emptyString;
}
}
@@ -93,12 +92,22 @@ Rectangle {
oaPopup.open()
}
function fillPaymentDetails(address, payment_id, amount, tx_description, recipient_name) {
if (recipientModel.count > 0) {
const last = recipientModel.count - 1;
if (recipientModel.get(recipientModel.count - 1).address == "") {
recipientModel.remove(last);
}
}
recipientModel.newRecipient(address, Utils.removeTrailingZeros(amount || ""));
setPaymentId(payment_id || "");
setDescription((recipient_name ? recipient_name + " " : "") + (tx_description || ""));
}
function updateFromQrCode(address, payment_id, amount, tx_description, recipient_name) {
console.log("updateFromQrCode")
addressLine.text = address
setPaymentId(payment_id);
amountLine.text = amount
setDescription(recipient_name + " " + tx_description);
fillPaymentDetails(address, payment_id, amount, tx_description, recipient_name);
cameraUi.qrcode_decoded.disconnect(updateFromQrCode)
}
@@ -113,10 +122,8 @@ Rectangle {
}
function clearFields() {
addressLine.text = ""
setPaymentId("");
amountLine.text = ""
setDescription("");
recipientModel.clear();
fillPaymentDetails("", "", "", "", "");
priorityDropdown.currentIndex = 0
}
@@ -163,166 +170,496 @@ Rectangle {
}
}
// recipient address input
RowLayout {
id: addressLineRow
Layout.fillWidth: true
ListModel {
id: recipientModel
LineEditMulti {
id: addressLine
spacing: 0
inputPaddingRight: inlineButtonVisible && inlineButton2Visible ? 100 : 60
fontBold: true
labelText: qsTr("Address") + translationManager.emptyString
labelButtonText: qsTr("Resolve") + translationManager.emptyString
placeholderText: {
if(persistentSettings.nettype == NetworkType.MAINNET){
return "4.. / 8.. / OpenAlias";
} else if (persistentSettings.nettype == NetworkType.STAGENET){
return "5.. / 7..";
} else if(persistentSettings.nettype == NetworkType.TESTNET){
return "9.. / B..";
}
}
wrapMode: Text.WrapAnywhere
addressValidation: true
onTextChanged: {
const parsed = walletManager.parse_uri_to_object(text);
if (!parsed.error) {
addressLine.text = parsed.address;
setPaymentId(parsed.payment_id);
amountLine.text = parsed.amount;
setDescription(parsed.tx_description);
}
}
inlineButton.text: FontAwesome.addressBook
inlineButton.buttonHeight: 30
inlineButton.fontPixelSize: 22
inlineButton.fontFamily: FontAwesome.fontFamily
inlineButton.textColor: MoneroComponents.Style.defaultFontColor
inlineButton.onClicked: {
middlePanel.addressBookView.selectAndSend = true;
appWindow.showPageRequest("AddressBook");
}
inlineButtonVisible: true
inlineButton2.text: FontAwesome.qrcode
inlineButton2.buttonHeight: 30
inlineButton2.fontPixelSize: 22
inlineButton2.fontFamily: FontAwesome.fontFamily
inlineButton2.textColor: MoneroComponents.Style.defaultFontColor
inlineButton2.onClicked: {
cameraUi.state = "Capture"
cameraUi.qrcode_decoded.connect(updateFromQrCode)
}
inlineButton2Visible: appWindow.qrScannerEnabled
}
}
readonly property int maxRecipients: 16
StandardButton {
id: resolveButton
width: 80
text: qsTr("Resolve") + translationManager.emptyString
visible: TxUtils.isValidOpenAliasAddress(addressLine.text)
enabled : visible
onClicked: {
var result = walletManager.resolveOpenAlias(addressLine.text)
if (result) {
var parts = result.split("|")
if (parts.length == 2) {
var address_ok = walletManager.addressValid(parts[1], appWindow.persistentSettings.nettype)
if (parts[0] === "true") {
if (address_ok) {
// prepend openalias to description
descriptionLine.text = descriptionLine.text ? addressLine.text + " " + descriptionLine.text : addressLine.text
descriptionCheckbox.checked = true
addressLine.text = parts[1]
}
else
oa_message(qsTr("No valid address found at this OpenAlias address"))
}
else if (parts[0] === "false") {
if (address_ok) {
addressLine.text = parts[1]
oa_message(qsTr("Address found, but the DNSSEC signatures could not be verified, so this address may be spoofed"))
}
else
{
oa_message(qsTr("No valid address found at this OpenAlias address, but the DNSSEC signatures could not be verified, so this may be spoofed"))
}
}
else {
oa_message(qsTr("Internal error"))
}
}
else {
oa_message(qsTr("Internal error"))
}
}
else {
oa_message(qsTr("No address found"))
}
}
}
ListElement {
address: ""
amount: ""
}
GridLayout {
columns: appWindow.walletMode < 2 ? 1 : 2
Layout.fillWidth: true
columnSpacing: 32
function newRecipient(address, amount) {
if (recipientModel.count < maxRecipients) {
recipientModel.append({address: address, amount: amount});
return true;
}
return false;
}
ColumnLayout {
Layout.fillWidth: true
Layout.minimumWidth: 200
function getRecipients() {
var recipients = [];
for (var index = 0; index < recipientModel.count; ++index) {
const recipient = recipientModel.get(index);
recipients.push({
address: recipient.address,
amount: recipient.amount,
});
}
return recipients;
}
// Amount input
LineEdit {
id: amountLine
Layout.fillWidth: true
inlineIcon: true
labelText: "<style type='text/css'>a {text-decoration: none; color: #858585; font-size: 14px;}</style>\
%1 <a href='#'>(%2)</a>".arg(qsTr("Amount")).arg(qsTr("Change account"))
+ translationManager.emptyString
copyButton: !isNaN(amountLine.text) && persistentSettings.fiatPriceEnabled
copyButtonText: "~%1 %2".arg(fiatApiConvertToFiat(amountLine.text)).arg(fiatApiCurrencySymbol())
copyButtonEnabled: false
function getAmountTotal() {
var sum = [];
for (var index = 0; index < recipientModel.count; ++index) {
const amount = recipientModel.get(index).amount;
if (amount == "(all)") {
return appWindow.getUnlockedBalance();
}
sum.push(amount || "0");
}
return walletManager.amountsSumFromStrings(sum);
}
onLabelLinkActivated: {
middlePanel.accountView.selectAndSend = true;
appWindow.showPageRequest("Account")
}
placeholderText: "0.00"
width: 100
fontBold: true
inlineButtonText: qsTr("All") + translationManager.emptyString
inlineButton.onClicked: amountLine.text = "(all)"
onTextChanged: {
amountLine.text = amountLine.text.replace(",", ".");
const match = amountLine.text.match(/^0+(\d.*)/);
if (match) {
const cursorPosition = amountLine.cursorPosition;
amountLine.text = match[1];
amountLine.cursorPosition = Math.max(cursorPosition, 1) - 1;
} else if(amountLine.text.indexOf('.') === 0){
amountLine.text = '0' + amountLine.text;
if (amountLine.text.length > 2) {
amountLine.cursorPosition = 1;
function hasEmptyAmount() {
for (var index = 0; index < recipientModel.count; ++index) {
if (recipientModel.get(index).amount === "") {
return true;
}
}
return false;
}
function hasEmptyAddress() {
for (var index = 0; index < recipientModel.count; ++index) {
if (recipientModel.get(index).address === "") {
return true;
}
}
return false;
}
function hasInvalidAddress() {
for (var index = 0; index < recipientModel.count; ++index) {
if (!TxUtils.checkAddress(recipientModel.get(index).address, appWindow.persistentSettings.nettype)) {
return true;
}
}
return false;
}
}
Item {
Layout.fillWidth: true
implicitHeight: recipientLayout.height
ColumnLayout {
id: recipientLayout
anchors.left: parent.left
anchors.right: parent.right
spacing: 0
readonly property int colSpacing: 10
readonly property int rowSpacing: 10
readonly property int secondRowWidth: 125
readonly property int thirdRowWidth: 50
RowLayout {
Layout.bottomMargin: recipientLayout.rowSpacing / 2
spacing: recipientLayout.colSpacing
RowLayout {
id: addressLabel
spacing: 6
Layout.fillWidth: true
MoneroComponents.TextPlain {
Layout.leftMargin: 10
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 16
color: MoneroComponents.Style.defaultFontColor
text: qsTr("Address") + translationManager.emptyString
}
MoneroComponents.InlineButton {
fontFamily: FontAwesome.fontFamily
fontPixelSize: 18
text: FontAwesome.desktop
onClicked: {
clearFields();
const codes = oshelper.grabQrCodesFromScreen();
for (var index = 0; index < codes.length; ++index) {
const parsed = walletManager.parse_uri_to_object(codes[index]);
if (!parsed.error) {
fillPaymentDetails(parsed.address, parsed.payment_id, parsed.amount, parsed.tx_description, parsed.recipient_name);
break;
}
}
}
}
amountLine.error = walletManager.amountFromString(amountLine.text) > appWindow.getUnlockedBalance()
}
validator: RegExpValidator {
regExp: /^(\d{1,8})?([\.,]\d{1,12})?$/
}
}
MoneroComponents.InlineButton {
fontFamily: FontAwesome.fontFamily
text: FontAwesome.qrcode
visible: appWindow.qrScannerEnabled
onClicked: {
cameraUi.state = "Capture"
cameraUi.qrcode_decoded.connect(updateFromQrCode)
}
}
MoneroComponents.InlineButton {
fontFamily: FontAwesome.fontFamily
text: FontAwesome.addressBook
onClicked: {
middlePanel.addressBookView.selectAndSend = true;
appWindow.showPageRequest("AddressBook");
}
}
Item {
Layout.fillWidth: true
}
}
MoneroComponents.TextPlain {
Layout.preferredWidth: recipientLayout.secondRowWidth
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 16
color: MoneroComponents.Style.defaultFontColor
text: qsTr("Amount") + translationManager.emptyString
}
Item {
Layout.preferredWidth: recipientLayout.thirdRowWidth
}
}
Repeater {
id: recipientRepeater
model: recipientModel
ColumnLayout {
spacing: 0
Rectangle {
Layout.fillWidth: true
Layout.rightMargin: recipientLayout.thirdRowWidth
color: MoneroComponents.Style.inputBorderColorInActive
height: 1
visible: index > 0
}
RowLayout {
spacing: 0
MoneroComponents.LineEditMulti {
KeyNavigation.backtab: index > 0 ? recipientRepeater.itemAt(index - 1).children[1].children[2] : sendButton
KeyNavigation.tab: parent.children[2]
Layout.alignment: Qt.AlignVCenter
Layout.topMargin: index > 0 ? recipientLayout.rowSpacing / 2 : 0
Layout.bottomMargin: recipientLayout.rowSpacing / 2
Layout.fillWidth: true
addressValidation: true
borderDisabled: true
fontFamily: MoneroComponents.Style.fontMonoRegular.name
fontSize: 14
inputPaddingBottom: 0
inputPaddingTop: 0
inputPaddingRight: 0
placeholderFontFamily: MoneroComponents.Style.fontMonoRegular.name
placeholderFontSize: 14
spacing: 0
wrapMode: Text.WrapAnywhere
placeholderText: {
if(persistentSettings.nettype == NetworkType.MAINNET){
return "4.. / 8.. / OpenAlias";
} else if (persistentSettings.nettype == NetworkType.STAGENET){
return "5.. / 7..";
} else if(persistentSettings.nettype == NetworkType.TESTNET){
return "9.. / B..";
}
}
onTextChanged: {
const parsed = walletManager.parse_uri_to_object(text);
if (!parsed.error) {
fillPaymentDetails(parsed.address, parsed.payment_id, parsed.amount, parsed.tx_description);
}
address = text;
}
text: address
MoneroComponents.InlineButton {
small: true
text: qsTr("Resolve") + translationManager.emptyString
visible: TxUtils.isValidOpenAliasAddress(address)
onClicked: {
var result = walletManager.resolveOpenAlias(address)
if (result) {
var parts = result.split("|")
if (parts.length == 2) {
var address_ok = walletManager.addressValid(parts[1], appWindow.persistentSettings.nettype)
if (parts[0] === "true") {
if (address_ok) {
// prepend openalias to description
descriptionLine.text = descriptionLine.text ? address + " " + descriptionLine.text : address
descriptionCheckbox.checked = true
recipientRepeater.itemAt(index).children[1].children[0].text = parts[1];
}
else
oa_message(qsTr("No valid address found at this OpenAlias address"))
}
else if (parts[0] === "false") {
if (address_ok) {
recipientRepeater.itemAt(index).children[1].children[0].text = parts[1];
oa_message(qsTr("Address found, but the DNSSEC signatures could not be verified, so this address may be spoofed"))
}
else
{
oa_message(qsTr("No valid address found at this OpenAlias address, but the DNSSEC signatures could not be verified, so this may be spoofed"))
}
}
else {
oa_message(qsTr("Internal error"))
}
}
else {
oa_message(qsTr("Internal error"))
}
}
else {
oa_message(qsTr("No address found"))
}
}
}
}
Rectangle {
Layout.fillHeight: true
Layout.leftMargin: recipientLayout.colSpacing / 2 - width
Layout.rightMargin: recipientLayout.colSpacing / 2
color: MoneroComponents.Style.inputBorderColorInActive
width: 1
}
MoneroComponents.LineEdit {
KeyNavigation.backtab: parent.children[0]
KeyNavigation.tab: index + 1 < recipientRepeater.count ? recipientRepeater.itemAt(index + 1).children[1].children[0] : sendButton
Layout.alignment: Qt.AlignVCenter
Layout.topMargin: recipientLayout.rowSpacing / 2
Layout.bottomMargin: recipientLayout.rowSpacing / 2
Layout.rightMargin: recipientLayout.colSpacing / 2
Layout.preferredWidth: 125
borderDisabled: true
fontFamily: MoneroComponents.Style.fontMonoRegular.name
fontSize: 14
inputPadding: 0
placeholderFontFamily: MoneroComponents.Style.fontMonoRegular.name
placeholderFontSize: 14
placeholderLeftMargin: 0
placeholderText: "0.00"
text: amount
onTextChanged: {
text = text.trim().replace(",", ".");
const match = text.match(/^0+(\d.*)/);
if (match) {
const cursorPosition = cursorPosition;
text = match[1];
cursorPosition = Math.max(cursorPosition, 1) - 1;
} else if(text.indexOf('.') === 0){
text = '0' + text;
if (text.length > 2) {
cursorPosition = 1;
}
}
error = walletManager.amountFromString(text) > appWindow.getUnlockedBalance();
amount = text;
}
validator: RegExpValidator {
regExp: /^\s*(\d{1,8})?([\.,]\d{1,12})?\s*$/
}
}
MoneroComponents.TextPlain {
Layout.leftMargin: recipientLayout.colSpacing / 2
Layout.preferredWidth: recipientLayout.thirdRowWidth
font.family: FontAwesome.fontFamilySolid
font.styleName: "Solid"
horizontalAlignment: Text.AlignHCenter
opacity: mouseArea.containsMouse ? 1 : 0.85
text: recipientModel.count == 1 ? FontAwesome.infinity : FontAwesome.times
MouseArea {
id: mouseArea
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
hoverEnabled: true
onClicked: {
if (recipientModel.count == 1) {
parent.parent.children[2].text = "(all)";
} else {
recipientModel.remove(index);
}
}
}
}
}
}
}
GridLayout {
id: totalLayout
Layout.topMargin: recipientLayout.rowSpacing / 2
Layout.fillWidth: true
columns: 3
columnSpacing: recipientLayout.colSpacing
rowSpacing: 0
RowLayout {
Layout.column: 0
Layout.row: 0
Layout.fillWidth: true
spacing: 0
CheckBox {
border: false
checked: false
enabled: {
if (recipientModel.count > 0 && recipientModel.get(0).amount == "(all)") {
return false;
}
if (recipientModel.count >= recipientModel.maxRecipients) {
return false;
}
return true;
}
fontAwesomeIcons: true
fontSize: descriptionLine.labelFontSize
iconOnTheLeft: true
text: qsTr("Add recipient") + translationManager.emptyString
toggleOnClick: false
uncheckedIcon: FontAwesome.plusCircle
onClicked: {
recipientModel.newRecipient("", "");
}
}
MoneroComponents.TextPlain {
Layout.fillWidth: true
horizontalAlignment: Text.AlignRight
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 16
text: recipientModel.count > 1 ? qsTr("Total") + translationManager.emptyString : ""
}
}
MoneroComponents.LineEdit {
id: totalValue
Layout.column: 1
Layout.row: 0
Layout.preferredWidth: recipientLayout.secondRowWidth
borderDisabled: true
fontFamily: MoneroComponents.Style.fontMonoRegular.name
fontSize: 14
inputHeight: 30
inputPadding: 0
readOnly: true
text: Utils.removeTrailingZeros(walletManager.displayAmount(recipientModel.getAmountTotal()))
visible: recipientModel.count > 1
}
MoneroComponents.TextPlain {
Layout.column: 2
Layout.row: 0
Layout.preferredWidth: recipientLayout.thirdRowWidth
horizontalAlignment: Text.AlignHCenter
font.family: MoneroComponents.Style.fontRegular.name
text: "XMR"
visible: recipientModel.count > 1
}
MoneroComponents.LineEdit {
Layout.column: 1
Layout.row: recipientModel.count > 1 ? 1 : 0
Layout.preferredWidth: recipientLayout.secondRowWidth
borderDisabled: true
fontFamily: MoneroComponents.Style.fontMonoRegular.name
fontSize: 14
inputHeight: 30
inputPadding: 0
opacity: 0.7
readOnly: true
text: fiatApiConvertToFiat(walletManager.displayAmount(recipientModel.getAmountTotal()))
visible: persistentSettings.fiatPriceEnabled
}
MoneroComponents.TextPlain {
Layout.column: 2
Layout.row: recipientModel.count > 1 ? 1 : 0
Layout.preferredWidth: recipientLayout.thirdRowWidth
font.family: MoneroComponents.Style.fontRegular.name
horizontalAlignment: Text.AlignHCenter
opacity: 0.7
text: fiatApiCurrencySymbol()
visible: persistentSettings.fiatPriceEnabled
}
}
}
Rectangle {
anchors.top: recipientLayout.top
anchors.topMargin: addressLabel.height + recipientLayout.rowSpacing / 2
anchors.bottom: recipientLayout.bottom
anchors.bottomMargin: totalLayout.height + recipientLayout.rowSpacing / 2
anchors.left: recipientLayout.left
anchors.right: recipientLayout.right
anchors.rightMargin: recipientLayout.thirdRowWidth
color: "transparent"
border.color: MoneroComponents.Style.inputBorderColorInActive
border.width: 1
radius: 4
}
}
ColumnLayout {
spacing: 0
visible: appWindow.walletMode >= 2
Label {
id: transactionPriority
Layout.topMargin: 0
text: qsTr("Transaction priority") + translationManager.emptyString
fontBold: false
fontSize: 16
}
// Note: workaround for translations in listElements
// ListElement: cannot use script for property value, so
// code like this wont work:
// ListElement { column1: qsTr("LOW") + translationManager.emptyString ; column2: ""; priority: PendingTransaction.Priority_Low }
// For translations to work, the strings need to be listed in
// the file components/StandardDropdown.qml too.
// Priorites after v5
ListModel {
id: priorityModelV5
ListElement { column1: qsTr("Automatic") ; column2: ""; priority: 0}
ListElement { column1: qsTr("Slow (x0.2 fee)") ; column2: ""; priority: 1}
ListElement { column1: qsTr("Normal (x1 fee)") ; column2: ""; priority: 2 }
ListElement { column1: qsTr("Fast (x5 fee)") ; column2: ""; priority: 3 }
ListElement { column1: qsTr("Fastest (x200 fee)") ; column2: ""; priority: 4 }
}
RowLayout {
Layout.topMargin: 5
spacing: 10
StandardDropdown {
Layout.preferredWidth: 200
id: priorityDropdown
currentIndex: 0
dataModel: priorityModelV5
}
MoneroComponents.TextPlain {
id: feeLabel
Layout.alignment: Qt.AlignRight
Layout.topMargin: 12
Layout.alignment: Qt.AlignVCenter
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 14
color: MoneroComponents.Style.defaultFontColor
opacity: 0.7
property bool estimating: false
property var estimatedFee: null
property string estimatedFeeFiat: {
@@ -338,12 +675,21 @@ Rectangle {
if (!sendButton.enabled || !currentWallet) {
return;
}
var addresses = [];
var amounts = [];
for (var index = 0; index < recipientModel.count; ++index) {
const recipient = recipientModel.get(index);
addresses.push(recipient.address);
amounts.push(walletManager.amountFromString(recipient.amount));
}
currentWallet.estimateTransactionFeeAsync(
addressLine.text,
walletManager.amountFromString(amountLine.text),
addresses,
amounts,
priorityModelV5.get(priorityDropdown.currentIndex).priority,
function (amount) {
estimatedFee = Utils.removeTrailingZeros(amount);
if (amount) {
estimatedFee = Utils.removeTrailingZeros(amount);
}
estimating = false;
});
}
@@ -351,56 +697,20 @@ Rectangle {
if (!sendButton.enabled || estimatedFee == null) {
return ""
}
return "%1: ~%2 XMR".arg(qsTr("Fee")).arg(estimatedFee) +
estimatedFeeFiat +
translationManager.emptyString;
return "~%1 XMR%2 %3".arg(estimatedFee)
.arg(estimatedFeeFiat)
.arg(qsTr("fee") + translationManager.emptyString);
}
BusyIndicator {
anchors.right: parent.right
anchors.left: parent.left
running: feeLabel.estimating
height: parent.height
width: height
}
}
}
ColumnLayout {
visible: appWindow.walletMode >= 2
Layout.alignment: Qt.AlignTop
Label {
id: transactionPriority
Layout.topMargin: 0
text: qsTr("Transaction priority") + translationManager.emptyString
fontBold: false
fontSize: 16
}
// Note: workaround for translations in listElements
// ListElement: cannot use script for property value, so
// code like this wont work:
// ListElement { column1: qsTr("LOW") + translationManager.emptyString ; column2: ""; priority: PendingTransaction.Priority_Low }
// For translations to work, the strings need to be listed in
// the file components/StandardDropdown.qml too.
// Priorites after v5
ListModel {
id: priorityModelV5
ListElement { column1: qsTr("Automatic") ; column2: ""; priority: 0}
ListElement { column1: qsTr("Slow (x0.2 fee)") ; column2: ""; priority: 1}
ListElement { column1: qsTr("Normal (x1 fee)") ; column2: ""; priority: 2 }
ListElement { column1: qsTr("Fast (x5 fee)") ; column2: ""; priority: 3 }
ListElement { column1: qsTr("Fastest (x200 fee)") ; column2: ""; priority: 4 }
}
StandardDropdown {
Layout.preferredWidth: 200
id: priorityDropdown
Layout.topMargin: 5
currentIndex: 0
dataModel: priorityModelV5
}
}
}
}
}
MoneroComponents.WarningBox {
text: qsTr("Description field contents match long payment ID format. \
@@ -492,21 +802,21 @@ Rectangle {
rightIconInactive: "qrc:///images/rightArrowInactive.png"
Layout.topMargin: 4
text: qsTr("Send") + translationManager.emptyString
enabled: !sendButtonWarningBox.visible && !warningContent && addressLine.text && !paymentIdWarningBox.visible
enabled: !sendButtonWarningBox.visible && !warningContent && !recipientModel.hasEmptyAddress() && !paymentIdWarningBox.visible
onClicked: {
console.log("Transfer: paymentClicked")
var priority = priorityModelV5.get(priorityDropdown.currentIndex).priority
console.log("priority: " + priority)
console.log("amount: " + amountLine.text)
addressLine.text = addressLine.text.trim()
setPaymentId(paymentIdLine.text.trim());
root.paymentClicked(addressLine.text, paymentIdLine.text, amountLine.text, root.mixin, priority, descriptionLine.text)
root.paymentClicked(recipientModel.getRecipients(), paymentIdLine.text, root.mixin, priority, descriptionLine.text)
}
}
}
function checkInformation(amount, address, nettype) {
return amount.length > 0 && walletManager.amountFromString(amountLine.text) <= appWindow.getUnlockedBalance() && TxUtils.checkAddress(address, nettype)
function checkInformation() {
return !recipientModel.hasEmptyAmount() &&
recipientModel.getAmountTotal() <= appWindow.getUnlockedBalance() &&
!recipientModel.hasInvalidAddress();
}
} // pageRoot
@@ -566,15 +876,13 @@ Rectangle {
visible: persistentSettings.transferShowAdvanced && appWindow.walletMode >= 2
title: qsTr("Offline transaction signing") + translationManager.emptyString
button1.text: qsTr("Create") + translationManager.emptyString
button1.enabled: appWindow.viewOnly && pageRoot.checkInformation(amountLine.text, addressLine.text, appWindow.persistentSettings.nettype)
button1.enabled: appWindow.viewOnly && pageRoot.checkInformation()
button1.onClicked: {
console.log("Transfer: saveTx Clicked")
var priority = priorityModelV5.get(priorityDropdown.currentIndex).priority
console.log("priority: " + priority)
console.log("amount: " + amountLine.text)
addressLine.text = addressLine.text.trim()
setPaymentId(paymentIdLine.text.trim());
root.paymentClicked(addressLine.text, paymentIdLine.text, amountLine.text, root.mixin, priority, descriptionLine.text)
root.paymentClicked(recipientModel.getRecipients(), paymentIdLine.text, root.mixin, priority, descriptionLine.text)
}
button2.text: qsTr("Sign (offline)") + translationManager.emptyString
button2.enabled: !appWindow.viewOnly
@@ -591,7 +899,7 @@ Rectangle {
helpTextLarge.text: qsTr("Spend XMR from a cold (offline) wallet") + translationManager.emptyString
helpTextSmall.text: {
var errorMessage = "";
if (appWindow.viewOnly && !pageRoot.checkInformation(amountLine.text, addressLine.text, appWindow.persistentSettings.nettype)){
if (appWindow.viewOnly && !pageRoot.checkInformation()) {
errorMessage = "<p class='orange'>" + qsTr("* To create a transaction file, please enter address and amount above") + "</p>";
}
return "<style type='text/css'>p{line-height:20px; margin-top:0px; margin-bottom:0px; color:" + MoneroComponents.Style.defaultFontColor +
@@ -792,19 +1100,9 @@ Rectangle {
}
// Popuplate fields from addressbook.
function sendTo(address, paymentId, description, amount){
function sendTo(address, paymentId, description, amount) {
middlePanel.state = 'Transfer';
if(typeof address !== 'undefined')
addressLine.text = address
if(typeof paymentId !== 'undefined')
setPaymentId(paymentId);
if(typeof description !== 'undefined')
setDescription(description);
if(typeof amount !== 'undefined')
amountLine.text = amount;
fillPaymentDetails(address, paymentId, amount, description);
}
}

View File

@@ -46,7 +46,7 @@ Rectangle {
ColumnLayout {
id: mainLayout
anchors.margins: 20
anchors.topMargin: 40
anchors.topMargin: 0
anchors.left: parent.left
anchors.top: parent.top
anchors.right: parent.right

View File

@@ -1,423 +0,0 @@
// Copyright (c) 2014-2018, The Monero Project
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import QtQuick 2.9
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import QtQuick.Layouts 1.1
import QtQuick.Dialogs 1.2
import "../../js/Windows.js" as Windows
import "../../js/Utils.js" as Utils
import "../../components" as MoneroComponents
import "../../pages"
import "."
import moneroComponents.Clipboard 1.0
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 96
color: "transparent"
ColumnLayout {
spacing: 0
Layout.preferredHeight: 32
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
GridLayout {
id: grid
Layout.alignment: Qt.AlignHCenter
columnSpacing: 0
property string fontColorActive: MoneroComponents.Style.blackTheme ? "white" : "white"
property string fontColorInActive: MoneroComponents.Style.blackTheme ? "white" : MoneroComponents.Style.dimmedFontColor
property int fontSize: 15
property bool fontBold: true
property var fontFamily: MoneroComponents.Style.fontRegular.name
property string borderColor: MoneroComponents.Style.blackTheme ? "#808080" : "#B9B9B9"
property int textMargin: {
// left-right margins for a given cell
if(appWindow.width < 890){
return 32;
} else {
return 64;
}
}
Rectangle {
// navbar left side border
id: navBarLeft
property bool isActive: settingsStateView.state === "Wallet"
Layout.preferredWidth: 2
Layout.preferredHeight: 32
color: "transparent"
Rectangle {
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
width: 1
height: parent.height - 2
color: grid.borderColor
}
ColumnLayout {
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.right: parent.right
width: 1
spacing: 0
Rectangle {
Layout.preferredHeight: 1
Layout.preferredWidth: 1
color: grid.borderColor
}
Rectangle {
Layout.fillHeight: true
width: 1
color: navBarLeft.isActive ? grid.borderColor : "transparent"
}
Rectangle {
color: grid.borderColor
Layout.preferredHeight: 1
Layout.preferredWidth: 1
}
}
}
ColumnLayout {
// WALLET
id: navWallet
property bool isActive: settingsStateView.state === "Wallet"
Layout.preferredWidth: navWalletText.width + grid.textMargin
Layout.minimumWidth: 72
Layout.preferredHeight: 32
spacing: 0
Rectangle {
color: grid.borderColor
Layout.preferredHeight: 1
Layout.fillWidth: true
}
Rectangle {
color: parent.isActive ? grid.borderColor : "transparent"
height: 30
Layout.fillWidth: true
MoneroComponents.TextPlain {
id: navWalletText
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
font.family: grid.fontFamily
font.pixelSize: grid.fontSize
font.bold: grid.fontBold
text: qsTr("Wallet") + translationManager.emptyString
color: navWallet.isActive ? grid.fontColorActive : grid.fontColorInActive
themeTransition: false
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: { settingsStateView.state = "Wallet" }
}
}
Rectangle {
color: grid.borderColor
Layout.preferredHeight: 1
Layout.fillWidth: true
}
}
Rectangle{
Layout.preferredWidth: 1
Layout.preferredHeight: 32
color: grid.borderColor
}
ColumnLayout {
// UI
id: navUI
property bool isActive: settingsStateView.state === "UI"
Layout.preferredWidth: navUIText.width + grid.textMargin
Layout.preferredHeight: 32
Layout.minimumWidth: 72
spacing: 0
Rectangle {
color: grid.borderColor
Layout.preferredHeight: 1
Layout.fillWidth: true
}
Rectangle {
color: parent.isActive ? grid.borderColor : "transparent"
height: 30
Layout.fillWidth: true
MoneroComponents.TextPlain {
id: navUIText
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
font.family: grid.fontFamily
font.pixelSize: grid.fontSize
font.bold: grid.fontBold
text: qsTr("Interface") + translationManager.emptyString
color: navUI.isActive ? grid.fontColorActive : grid.fontColorInActive
themeTransition: false
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: { settingsStateView.state = "UI" }
}
}
Rectangle {
color: grid.borderColor
Layout.preferredHeight: 1
Layout.fillWidth: true
}
}
Rectangle{
Layout.preferredWidth: 1
Layout.preferredHeight: 32
color: grid.borderColor
}
ColumnLayout {
// NODE
id: navNode
property bool isActive: settingsStateView.state === "Node"
visible: appWindow.walletMode >= 2
Layout.preferredWidth: navNodeText.width + grid.textMargin
Layout.preferredHeight: 32
Layout.minimumWidth: 72
spacing: 0
Rectangle {
color: grid.borderColor
Layout.preferredHeight: 1
Layout.fillWidth: true
}
Rectangle {
color: parent.isActive ? grid.borderColor : "transparent"
height: 30
Layout.fillWidth: true
MoneroComponents.TextPlain {
id: navNodeText
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
font.family: grid.fontFamily
font.pixelSize: grid.fontSize
font.bold: grid.fontBold
text: qsTr("Node") + translationManager.emptyString
color: navNode.isActive ? grid.fontColorActive : grid.fontColorInActive
themeTransition: false
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: { settingsStateView.state = "Node" }
}
}
Rectangle {
color: grid.borderColor
Layout.preferredHeight: 1
Layout.fillWidth: true
}
}
Rectangle{
visible: appWindow.walletMode >= 2
Layout.preferredWidth: 1
Layout.preferredHeight: 32
color: grid.borderColor
}
ColumnLayout {
// LOG
id: navLog
property bool isActive: settingsStateView.state === "Log"
Layout.preferredWidth: navLogText.width + grid.textMargin
Layout.preferredHeight: 32
Layout.minimumWidth: 72
spacing: 0
Rectangle {
color: grid.borderColor
Layout.preferredHeight: 1
Layout.fillWidth: true
}
Rectangle {
color: parent.isActive ? grid.borderColor : "transparent"
height: 30
Layout.fillWidth: true
MoneroComponents.TextPlain {
id: navLogText
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
font.family: grid.fontFamily
font.pixelSize: grid.fontSize
font.bold: grid.fontBold
text: qsTr("Log") + translationManager.emptyString
color: navLog.isActive ? grid.fontColorActive : grid.fontColorInActive
themeTransition: false
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: { settingsStateView.state = "Log" }
}
}
Rectangle {
color: grid.borderColor
Layout.preferredHeight: 1
Layout.fillWidth: true
}
}
Rectangle{
visible: appWindow.walletMode >= 2
Layout.preferredWidth: 1
Layout.preferredHeight: 32
color: grid.borderColor
}
ColumnLayout {
// INFO
id: navInfo
property bool isActive: settingsStateView.state === "Info"
Layout.preferredWidth: navInfoText.width + grid.textMargin
Layout.preferredHeight: 32
Layout.minimumWidth: 72
spacing: 0
Rectangle {
color: grid.borderColor
Layout.preferredHeight: 1
Layout.fillWidth: true
}
Rectangle {
color: parent.isActive ? grid.borderColor : "transparent"
height: 30
Layout.fillWidth: true
MoneroComponents.TextPlain {
id: navInfoText
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
font.family: grid.fontFamily
font.pixelSize: grid.fontSize
font.bold: grid.fontBold
text: qsTr("Info") + translationManager.emptyString
color: navInfo.isActive ? grid.fontColorActive : grid.fontColorInActive
themeTransition: false
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: { settingsStateView.state = "Info" }
}
}
Rectangle {
color: grid.borderColor
Layout.preferredHeight: 1
Layout.fillWidth: true
}
}
Rectangle {
// navbar right side border
id: navBarRight
property bool isActive: settingsStateView.state === "Info"
Layout.preferredWidth: 2
Layout.preferredHeight: 32
color: "transparent"
rotation: 180
Rectangle {
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
width: 1
height: parent.height - 2
color: grid.borderColor
}
ColumnLayout {
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.right: parent.right
width: 1
spacing: 0
Rectangle {
Layout.preferredHeight: 1
Layout.preferredWidth: 1
color: grid.borderColor
}
Rectangle {
Layout.fillHeight: true
width: 1
color: navBarRight.isActive ? grid.borderColor : "transparent"
}
Rectangle {
color: grid.borderColor
Layout.preferredHeight: 1
Layout.preferredWidth: 1
}
}
}
Rectangle {
color: "transparent"
Layout.fillWidth: true
}
}
}
}

View File

@@ -48,7 +48,38 @@ ColumnLayout {
property int settingsHeight: 900
property alias settingsStateViewState: settingsStateView.state
Navbar{}
MoneroComponents.Navbar {
Layout.alignment: Qt.AlignHCenter
Layout.topMargin: height
Layout.bottomMargin: height
MoneroComponents.NavbarItem {
active: settingsStateView.state == "Wallet"
text: qsTr("Wallet") + translationManager.emptyString
onSelected: settingsStateView.state = "Wallet"
}
MoneroComponents.NavbarItem {
active: settingsStateView.state == "UI"
text: qsTr("Interface") + translationManager.emptyString
onSelected: settingsStateView.state = "UI"
}
MoneroComponents.NavbarItem {
active: settingsStateView.state == "Node"
text: qsTr("Node") + translationManager.emptyString
visible: appWindow.walletMode >= 2
onSelected: settingsStateView.state = "Node"
}
MoneroComponents.NavbarItem {
active: settingsStateView.state == "Log"
text: qsTr("Log") + translationManager.emptyString
onSelected: settingsStateView.state = "Log"
}
MoneroComponents.NavbarItem {
active: settingsStateView.state == "Info"
text: qsTr("Info") + translationManager.emptyString
onSelected: settingsStateView.state = "Info"
}
}
Rectangle{
id: settingsStateView

View File

@@ -47,7 +47,7 @@ Rectangle {
} else if(appWindow.walletMode === 1){
return qsTr("Simple mode") + " (bootstrap)" + translationManager.emptyString;
} else if(appWindow.walletMode === 2){
return qsTr("Advanced mode") + translationManager.emptyString;
return "%1 (%2)".arg(qsTr("Advanced mode")).arg(persistentSettings.useRemoteNode ? qsTr("Remote node") : qsTr("Local node")) + translationManager.emptyString;
}
}

View File

@@ -66,6 +66,12 @@ Rectangle {
text: qsTr("Check for updates periodically") + translationManager.emptyString
}
MoneroComponents.CheckBox {
checked: persistentSettings.displayWalletNameInTitleBar
onClicked: persistentSettings.displayWalletNameInTitleBar = !persistentSettings.displayWalletNameInTitleBar
text: qsTr("Display wallet name in title bar") + translationManager.emptyString
}
MoneroComponents.CheckBox {
id: hideBalanceCheckBox
checked: persistentSettings.hideBalance

View File

@@ -215,6 +215,7 @@ Rectangle {
Layout.fillWidth: true
property var lastCommands: []
property int currentCommandIndex
enabled: !persistentSettings.useRemoteNode
fontBold: false
placeholderText: qsTr("command + enter (e.g 'help' or 'status')") + translationManager.emptyString
placeholderFontSize: 16

View File

@@ -130,7 +130,7 @@ Rectangle{
topPadding: 0
text: qsTr("The blockchain is downloaded to your computer. Provides higher security and requires more local storage.") + translationManager.emptyString
width: parent.width - (localNodeIcon.width + localNodeIcon.anchors.leftMargin + anchors.leftMargin)
}
}
}
MouseArea {
@@ -262,80 +262,94 @@ Rectangle{
text: qsTr("To find a remote node, type 'Monero remote node' into your favorite search engine. Please ensure the node is run by a trusted third-party.") + translationManager.emptyString
}
MoneroComponents.RemoteNodeEdit {
id: remoteNodeEdit
Layout.minimumWidth: 100
placeholderFontSize: 15
daemonAddrLabelText: qsTr("Address") + translationManager.emptyString
daemonPortLabelText: qsTr("Port") + translationManager.emptyString
initialAddress: persistentSettings.remoteNodeAddress
onEditingFinished: {
persistentSettings.remoteNodeAddress = remoteNodeEdit.getAddress();
console.log("setting remote node to " + persistentSettings.remoteNodeAddress);
if (persistentSettings.is_trusted_daemon) {
persistentSettings.is_trusted_daemon = !persistentSettings.is_trusted_daemon
currentWallet.setTrustedDaemon(persistentSettings.is_trusted_daemon)
setTrustedDaemonCheckBox.checked = !setTrustedDaemonCheckBox.checked
appWindow.showStatusMessage(qsTr("Remote node updated. Trusted daemon has been reset. Mark again, if desired."), 8);
}
}
}
GridLayout {
columns: 2
columnSpacing: 32
MoneroComponents.LineEdit {
id: daemonUsername
Layout.fillWidth: true
labelText: qsTr("Daemon username") + translationManager.emptyString
text: persistentSettings.daemonUsername
placeholderText: qsTr("(optional)") + translationManager.emptyString
placeholderFontSize: 15
labelFontSize: 14
fontSize: 15
}
MoneroComponents.LineEdit {
id: daemonPassword
Layout.fillWidth: true
labelText: qsTr("Daemon password") + translationManager.emptyString
text: persistentSettings.daemonPassword
placeholderText: qsTr("Password") + translationManager.emptyString
password: true
placeholderFontSize: 15
labelFontSize: 14
fontSize: 15
}
}
MoneroComponents.CheckBox {
id: setTrustedDaemonCheckBox
checked: persistentSettings.is_trusted_daemon
onClicked: {
persistentSettings.is_trusted_daemon = !persistentSettings.is_trusted_daemon
currentWallet.setTrustedDaemon(persistentSettings.is_trusted_daemon)
}
text: qsTr("Mark as Trusted Daemon") + translationManager.emptyString
border: false
checkedIcon: FontAwesome.minusCircle
uncheckedIcon: FontAwesome.plusCircle
fontAwesomeIcons: true
fontSize: 16
iconOnTheLeft: true
text: qsTr("Add remote node") + translationManager.emptyString
toggleOnClick: false
onClicked: remoteNodeDialog.add(remoteNodesModel.append)
}
MoneroComponents.StandardButton {
id: btnConnectRemote
enabled: remoteNodeEdit.isValid()
small: true
text: qsTr("Connect") + translationManager.emptyString
onClicked: {
// Update daemon login
persistentSettings.remoteNodeAddress = remoteNodeEdit.getAddress();
persistentSettings.daemonUsername = daemonUsername.text;
persistentSettings.daemonPassword = daemonPassword.text;
persistentSettings.useRemoteNode = true
ColumnLayout {
spacing: 0
currentWallet.setDaemonLogin(persistentSettings.daemonUsername, persistentSettings.daemonPassword);
Repeater {
model: remoteNodesModel
appWindow.connectRemoteNode()
Rectangle {
height: 30
Layout.fillWidth: true
color: itemMouseArea.containsMouse || index === remoteNodesModel.selected ? MoneroComponents.Style.titleBarButtonHoverColor : "transparent"
Rectangle {
color: MoneroComponents.Style.appWindowBorderColor
anchors.right: parent.right
anchors.left: parent.left
anchors.top: parent.top
height: 1
visible: index > 0
MoneroEffects.ColorTransition {
targetObj: parent
blackColor: MoneroComponents.Style._b_appWindowBorderColor
whiteColor: MoneroComponents.Style._w_appWindowBorderColor
}
}
Rectangle {
anchors.fill: parent
anchors.rightMargin: 80
color: "transparent"
MoneroComponents.TextPlain {
color: index === remoteNodesModel.selected ? MoneroComponents.Style.defaultFontColor : MoneroComponents.Style.dimmedFontColor
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin: 6
font.pixelSize: 16
text: address
themeTransition: false
}
MouseArea {
id: itemMouseArea
cursorShape: Qt.PointingHandCursor
anchors.fill: parent
hoverEnabled: true
onClicked: remoteNodesModel.applyRemoteNode(index)
}
}
RowLayout {
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
anchors.rightMargin: 6
height: 30
spacing: 10
MoneroComponents.InlineButton {
buttonColor: "transparent"
fontFamily: FontAwesome.fontFamily
fontPixelSize: 18
text: FontAwesome.edit
onClicked: remoteNodeDialog.edit(remoteNodesModel.get(index), function (remoteNode) {
remoteNodesModel.set(index, remoteNode)
})
}
MoneroComponents.InlineButton {
buttonColor: "transparent"
fontFamily: FontAwesome.fontFamily
text: FontAwesome.times
visible: remoteNodesModel.count > 1
onClicked: remoteNodesModel.removeSelectNextIfNeeded(index)
}
}
}
}
}
}
@@ -398,7 +412,7 @@ Rectangle{
placeholderFontSize: 15
text: persistentSettings.daemonFlags
addressValidation: false
error: text.match(/(^|\s)--(data-dir|bootstrap-daemon-address)/)
error: text.match(/(^|\s)--(data-dir|bootstrap-daemon-address|non-interactive)/)
onEditingFinished: {
if (!daemonFlags.error) {
persistentSettings.daemonFlags = daemonFlags.text;
@@ -431,7 +445,7 @@ Rectangle{
}
}
}
}
}
}
}

View File

@@ -62,7 +62,7 @@ Rectangle {
iconText: FontAwesome.eye
description: qsTr("Creates a new wallet that can only view and initiate transactions, but requires a spendable wallet to sign transactions before sending.") + translationManager.emptyString
title: qsTr("Create a view-only wallet") + translationManager.emptyString
visible: !appWindow.viewOnly
visible: !appWindow.viewOnly && (currentWallet ? !currentWallet.isLedger() : true)
onClicked: {
var newPath = currentWallet.path + "_viewonly";

View File

@@ -3,7 +3,12 @@
<file>main.qml</file>
<file>LeftPanel.qml</file>
<file>MiddlePanel.qml</file>
<file>components/Dialog.qml</file>
<file>components/Label.qml</file>
<file>components/LanguageButton.qml</file>
<file>components/Navbar.qml</file>
<file>components/NavbarItem.qml</file>
<file>components/RemoteNodeDialog.qml</file>
<file>components/SettingsListItem.qml</file>
<file>components/Slider.qml</file>
<file>components/UpdateDialog.qml</file>
@@ -14,6 +19,7 @@
<file>monero/utils/gpg_keys/fluffypony.asc</file>
<file>monero/utils/gpg_keys/luigi1111.asc</file>
<file>pages/Account.qml</file>
<file>pages/Advanced.qml</file>
<file>pages/Transfer.qml</file>
<file>pages/History.qml</file>
<file>pages/AddressBook.qml</file>
@@ -161,7 +167,6 @@
<file>pages/settings/SettingsLog.qml</file>
<file>pages/settings/SettingsLayout.qml</file>
<file>pages/settings/SettingsInfo.qml</file>
<file>pages/settings/Navbar.qml</file>
<file>components/WarningBox.qml</file>
<file>images/miningxmr.png</file>
<file>images/miningxmr@2x.png</file>
@@ -243,5 +248,6 @@
<file>images/success.png</file>
<file>images/success@2x.png</file>
<file>components/SuccessfulTxDialog.qml</file>
<file>components/TxConfirmationDialog.qml</file>
</qresource>
</RCC>

View File

@@ -20,7 +20,7 @@ file(GLOB SOURCE_FILES
"libwalletqt/PendingTransaction.cpp"
"libwalletqt/TransactionHistory.cpp"
"libwalletqt/TransactionInfo.cpp"
"libwalletqt/QRCodeImageProvider.cpp" QR
"libwalletqt/QRCodeImageProvider.cpp"
"libwalletqt/AddressBook.cpp"
"libwalletqt/Subaddress.cpp"
"libwalletqt/SubaddressAccount.cpp"
@@ -55,13 +55,6 @@ if(ENABLE_PASS_STRENGTH_METER)
)
endif()
if(WITH_SCANNER)
file(GLOB QR_CODE_FILES
"QR-Code-scanner/*.h"
"QR-Code-scanner/*.cpp"
)
endif()
set(EXECUTABLE_FLAG)
if(MINGW)
set(EXECUTABLE_FLAG WIN32)
@@ -81,13 +74,19 @@ if(APPLE)
list(APPEND RESOURCES ${ICON})
endif()
add_executable(monero-wallet-gui ${EXECUTABLE_FLAG} main/main.cpp
set(monero_wallet_gui_sources
${SOURCE_FILES}
${PASS_STRENGTH_FILES}
${QR_CODE_FILES}
${RESOURCES}
)
if(NOT ANDROID)
add_executable(monero-wallet-gui ${EXECUTABLE_FLAG} ${monero_wallet_gui_sources})
else()
add_library(monero-wallet-gui SHARED ${monero_wallet_gui_sources})
set_target_properties(monero-wallet-gui PROPERTIES COMPILE_DEFINITIONS "ANDROID")
endif()
set_target_properties(monero-wallet-gui PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin"
MACOSX_BUNDLE TRUE
@@ -121,7 +120,6 @@ target_include_directories(monero-wallet-gui PUBLIC
${X11_INCLUDE_DIR}
${Boost_INCLUDE_DIRS}
${OPENSSL_INCLUDE_DIR}
${ZBAR_INCLUDE_DIR}
)
target_compile_definitions(monero-wallet-gui
@@ -130,6 +128,14 @@ target_compile_definitions(monero-wallet-gui
${Qt5Qml_DEFINITIONS}
)
if(APPLE)
if(NOT ICU_ROOT)
execute_process(COMMAND brew --prefix icu4c OUTPUT_VARIABLE ICU_ROOT OUTPUT_STRIP_TRAILING_WHITESPACE)
endif()
find_package(ICU REQUIRED COMPONENTS data i18n uc)
target_link_directories(monero-wallet-gui PRIVATE ${ICU_ROOT}/lib)
endif()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Widgets_EXECUTABLE_COMPILE_FLAGS}")
target_link_libraries(monero-wallet-gui
@@ -152,6 +158,7 @@ target_link_libraries(monero-wallet-gui
${EXTRA_LIBRARIES}
${ICU_LIBRARIES}
openpgp
qrdecoder
translations
)
@@ -164,13 +171,15 @@ if(X11_FOUND)
endif()
if(WITH_SCANNER)
target_link_libraries(monero-wallet-gui
${ZBAR_LIBRARIES}
jpeg
v4l2
v4lconvert
rt
)
target_link_libraries(monero-wallet-gui qrscanner)
if(LINUX AND NOT ANDROID)
target_link_libraries(monero-wallet-gui
jpeg
v4l2
v4lconvert
rt
)
endif()
endif()
add_custom_command(TARGET monero-wallet-gui POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:daemon> $<TARGET_FILE_DIR:monero-wallet-gui>)

View File

@@ -1,4 +1,21 @@
file(GLOB_RECURSE SRC_SOURCES *.cpp)
file(GLOB_RECURSE SRC_HEADERS *.h)
add_library(qrdecoder STATIC
Decoder.cpp
)
target_link_libraries(qrdecoder
PUBLIC
Qt5::Gui
PRIVATE
quirc
)
if(WITH_SCANNER)
add_library(qrscanner
QrCodeScanner.cpp
QrScanThread.cpp
)
target_link_libraries(qrscanner
PUBLIC
Qt5::Multimedia
qrdecoder
)
endif()

View File

@@ -0,0 +1,99 @@
// Copyright (c) 2020, The Monero Project
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "Decoder.h"
#include <limits>
#include "quirc.h"
QrDecoder::QrDecoder()
: m_qr(quirc_new())
{
if (m_qr == nullptr)
{
throw std::runtime_error("QUIRC: failed to allocate memory");
}
}
QrDecoder::~QrDecoder()
{
quirc_destroy(m_qr);
}
std::vector<std::string> QrDecoder::decode(const QImage &image)
{
if (image.format() == QImage::Format_Grayscale8)
{
return decodeGrayscale8(image);
}
return decodeGrayscale8(image.convertToFormat(QImage::Format_Grayscale8));
}
std::vector<std::string> QrDecoder::decodeGrayscale8(const QImage &image)
{
if (quirc_resize(m_qr, image.width(), image.height()) < 0)
{
throw std::runtime_error("QUIRC: failed to allocate video memory");
}
uint8_t *rawImage = quirc_begin(m_qr, nullptr, nullptr);
if (rawImage == nullptr)
{
throw std::runtime_error("QUIRC: failed to get image buffer");
}
#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
std::copy(image.constBits(), image.constBits() + image.sizeInBytes(), rawImage);
#else
std::copy(image.constBits(), image.constBits() + image.byteCount(), rawImage);
#endif
quirc_end(m_qr);
const int count = quirc_count(m_qr);
if (count < 0)
{
throw std::runtime_error("QUIRC: failed to get the number of recognized QR-codes");
}
std::vector<std::string> result;
result.reserve(static_cast<size_t>(count));
for (int index = 0; index < count; ++index)
{
quirc_code code;
quirc_extract(m_qr, index, &code);
quirc_data data;
const quirc_decode_error_t err = quirc_decode(&code, &data);
if (err == QUIRC_SUCCESS)
{
result.emplace_back(&data.payload[0], &data.payload[data.payload_len]);
}
}
return result;
}

View File

@@ -0,0 +1,49 @@
// Copyright (c) 2020, The Monero Project
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <QImage>
struct quirc;
class QrDecoder
{
public:
QrDecoder(const QrDecoder &) = delete;
QrDecoder &operator=(const QrDecoder &) = delete;
QrDecoder();
~QrDecoder();
std::vector<std::string> decode(const QImage &image);
private:
std::vector<std::string> decodeGrayscale8(const QImage &image);
private:
quirc *m_qr;
};

View File

@@ -27,7 +27,6 @@
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "QrCodeScanner.h"
#include <WalletManager.h>
#include <QVideoProbe>
#include <QCamera>
@@ -40,7 +39,7 @@ QrCodeScanner::QrCodeScanner(QObject *parent)
m_probe = new QVideoProbe(this);
m_thread = new QrScanThread(this);
m_thread->start();
QObject::connect(m_thread, SIGNAL(decoded(int, QString)), this, SIGNAL(decoded(int, QString)));
QObject::connect(m_thread, SIGNAL(decoded(QString)), this, SIGNAL(decoded(QString)));
QObject::connect(m_thread, SIGNAL(notifyError(const QString &, bool)), this, SIGNAL(notifyError(const QString &, bool)));
connect(m_probe, SIGNAL(videoFrameProbed(QVideoFrame)), this, SLOT(processFrame(QVideoFrame)));
}

View File

@@ -56,8 +56,7 @@ public Q_SLOTS:
Q_SIGNALS:
void enabledChanged();
void decoded(int type, const QString &data);
void decode(int type, const QString &data);
void decoded(const QString &data);
void notifyError(const QString &error, bool warning = false);
protected:

View File

@@ -38,62 +38,15 @@ QrScanThread::QrScanThread(QObject *parent)
: QThread(parent)
,m_running(true)
{
m_scanner.set_handler(*this);
}
void QrScanThread::image_callback(zbar::Image &image)
{
qDebug() << "image_callback : Found Code ! " ;
for(zbar::Image::SymbolIterator sym = image.symbol_begin();
sym != image.symbol_end();
++sym)
if(!sym->get_count()) {
QString data = QString::fromStdString(sym->get_data());
emit decoded(sym->get_type(), data);
}
}
void QrScanThread::processZImage(zbar::Image &image)
{
m_scanner.recycle_image(image);
zbar::Image tmp = image.convert(*(long*)"Y800");
m_scanner.scan(tmp);
image.set_symbols(tmp.get_symbols());
}
bool QrScanThread::zimageFromQImage(const QImage &qimg, zbar::Image &dst)
{
switch( qimg.format() ){
case QImage::Format_RGB32 :
case QImage::Format_ARGB32 :
case QImage::Format_ARGB32_Premultiplied :
break;
default :
emit notifyError(QString("Invalid QImage Format !"));
return false;
}
unsigned int bpl( qimg.bytesPerLine() ), width( bpl / 4), height( qimg.height());
dst.set_size(width, height);
dst.set_format("BGR4");
#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
unsigned long datalen = qimg.sizeInBytes();
#else
unsigned long datalen = qimg.byteCount();
#endif
dst.set_data(qimg.bits(), datalen);
if((width * 4 != bpl) || (width * height * 4 > datalen)){
emit notifyError(QString("QImage to Zbar::Image failed !"));
return false;
}
return true;
}
void QrScanThread::processQImage(const QImage &qimg)
{
try {
m_image = QSharedPointer<zbar::Image>(new zbar::Image());
if( ! zimageFromQImage(qimg, *m_image) )
return;
processZImage(*m_image);
for (const std::string &code : m_decoder.decode(qimg))
{
emit decoded(QString::fromStdString(code));
}
}
catch(std::exception &e) {
qDebug() << "ERROR: " << e.what();

View File

@@ -35,9 +35,10 @@
#include <QEvent>
#include <QVideoFrame>
#include <QCamera>
#include <zbar.h>
class QrScanThread : public QThread, public zbar::Image::Handler
#include "Decoder.h"
class QrScanThread : public QThread
{
Q_OBJECT
@@ -47,20 +48,16 @@ public:
virtual void stop();
Q_SIGNALS:
void decoded(int type, const QString &data);
void decoded(const QString &data);
void notifyError(const QString &error, bool warning = false);
protected:
virtual void run();
void processVideoFrame(const QVideoFrame &);
void processQImage(const QImage &);
void processZImage(zbar::Image &image);
virtual void image_callback(zbar::Image &image);
bool zimageFromQImage(const QImage&, zbar::Image &);
private:
zbar::ImageScanner m_scanner;
QSharedPointer<zbar::Image> m_image;
QrDecoder m_decoder;
bool m_running;
QMutex m_mutex;
QWaitCondition m_waitCondition;

View File

@@ -27,6 +27,7 @@
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "DaemonManager.h"
#include "common/util.h"
#include <QElapsedTimer>
#include <QFile>
#include <QMutexLocker>
@@ -47,24 +48,7 @@ namespace {
static const int DAEMON_START_TIMEOUT_SECONDS = 120;
}
DaemonManager * DaemonManager::m_instance = nullptr;
QStringList DaemonManager::m_clArgs;
DaemonManager *DaemonManager::instance(const QStringList *args/* = nullptr*/)
{
if (!m_instance) {
m_instance = new DaemonManager;
// store command line arguments for later use
if (args != nullptr)
{
m_clArgs = *args;
}
}
return m_instance;
}
bool DaemonManager::start(const QString &flags, NetworkType::Type nettype, const QString &dataDir, const QString &bootstrapNodeAddress, bool noSync /* = false*/)
bool DaemonManager::start(const QString &flags, NetworkType::Type nettype, const QString &dataDir, const QString &bootstrapNodeAddress, bool noSync /* = false*/, bool pruneBlockchain /* = false*/)
{
if (!QFileInfo(m_monerod).isFile())
{
@@ -85,12 +69,6 @@ bool DaemonManager::start(const QString &flags, NetworkType::Type nettype, const
else if (nettype == NetworkType::STAGENET)
arguments << "--stagenet";
foreach (const QString &str, m_clArgs) {
qDebug() << QString(" [%1] ").arg(str);
if (!str.isEmpty())
arguments << str;
}
// Custom startup flags for daemon
foreach (const QString &str, flags.split(" ")) {
qDebug() << QString(" [%1] ").arg(str);
@@ -108,15 +86,18 @@ bool DaemonManager::start(const QString &flags, NetworkType::Type nettype, const
arguments << "--bootstrap-daemon-address" << bootstrapNodeAddress;
}
if (pruneBlockchain) {
if (!checkLmdbExists(dataDir)) { // check that DB has not already been created
arguments << "--prune-blockchain";
}
}
if (noSync) {
arguments << "--no-sync";
}
if (!flags.contains("--out-peers", Qt::CaseSensitive) && bootstrapNodeAddress == "auto") {
arguments << "--out-peers" << "16";
}
arguments << "--check-updates" << "disabled";
arguments << "--non-interactive";
// --max-concurrency based on threads available.
int32_t concurrency = qMax(1, QThread::idealThreadCount() / 2);
@@ -349,6 +330,13 @@ QVariantMap DaemonManager::validateDataDir(const QString &dataDir) const
return result;
}
bool DaemonManager::checkLmdbExists(QString datadir) {
if (datadir.isEmpty() || datadir.isNull()) {
datadir = QString::fromStdString(tools::get_default_data_dir());
}
return validateDataDir(datadir).value("lmdbExists").value<bool>();
}
DaemonManager::DaemonManager(QObject *parent)
: QObject(parent)
, m_scheduler(this)

View File

@@ -44,10 +44,10 @@ class DaemonManager : public QObject
Q_OBJECT
public:
explicit DaemonManager(QObject *parent = 0);
~DaemonManager();
static DaemonManager * instance(const QStringList *args = nullptr);
Q_INVOKABLE bool start(const QString &flags, NetworkType::Type nettype, const QString &dataDir = "", const QString &bootstrapNodeAddress = "", bool noSync = false);
Q_INVOKABLE bool start(const QString &flags, NetworkType::Type nettype, const QString &dataDir = "", const QString &bootstrapNodeAddress = "", bool noSync = false, bool pruneBlockchain = false);
Q_INVOKABLE void stopAsync(NetworkType::Type nettype, const QJSValue& callback);
Q_INVOKABLE bool noSync() const noexcept;
@@ -57,6 +57,7 @@ public:
Q_INVOKABLE void sendCommandAsync(const QStringList &cmd, NetworkType::Type nettype, const QJSValue& callback) const;
Q_INVOKABLE void exit();
Q_INVOKABLE QVariantMap validateDataDir(const QString &dataDir) const;
Q_INVOKABLE bool checkLmdbExists(QString datadir);
private:
@@ -76,11 +77,6 @@ public slots:
void stateChanged(QProcess::ProcessState state);
private:
explicit DaemonManager(QObject *parent = 0);
~DaemonManager();
static DaemonManager * m_instance;
static QStringList m_clArgs;
std::unique_ptr<QProcess> m_daemon;
QMutex m_daemonMutex;
QString m_monerod;

View File

@@ -78,7 +78,14 @@ void Subaddress::setLabel(quint32 accountIndex, quint32 addressIndex, const QStr
void Subaddress::refresh(quint32 accountIndex) const
{
m_subaddressImpl->refresh(accountIndex);
try
{
m_subaddressImpl->refresh(accountIndex);
}
catch (const std::exception &e)
{
qCritical() << "Failed to refresh account" << accountIndex << "subaddresses:" << e.what();
}
getAll();
}

View File

@@ -104,10 +104,7 @@ void Wallet::updateConnectionStatusAsync()
setConnectionStatus(ConnectionStatus_Connecting);
}
ConnectionStatus newStatus = static_cast<ConnectionStatus>(m_walletImpl->connected());
if (newStatus != m_connectionStatus || !m_initialized) {
m_initialized = true;
setConnectionStatus(newStatus);
}
setConnectionStatus(newStatus);
// Release lock
m_connectionStatusRunning = false;
});
@@ -115,8 +112,13 @@ void Wallet::updateConnectionStatusAsync()
Wallet::ConnectionStatus Wallet::connected(bool forceCheck)
{
if (!m_initialized)
{
return ConnectionStatus_Connecting;
}
// cache connection status
if (forceCheck || !m_initialized || (m_connectionStatusTime.elapsed() / 1000 > m_connectionStatusTtl && !m_connectionStatusRunning) || m_connectionStatusTime.elapsed() > 30000) {
if (forceCheck || (m_connectionStatusTime.elapsed() / 1000 > m_connectionStatusTtl && !m_connectionStatusRunning) || m_connectionStatusTime.elapsed() > 30000) {
qDebug() << "Checking connection status";
m_connectionStatusRunning = true;
m_connectionStatusTime.restart();
@@ -277,14 +279,25 @@ void Wallet::initAsync(
{
qDebug() << "initAsync: " + daemonAddress;
const auto future = m_scheduler.run([this, daemonAddress, trustedDaemon, upperTransactionLimit, isRecovering, isRecoveringFromDevice, restoreHeight, proxyAddress] {
bool success = init(daemonAddress, trustedDaemon, upperTransactionLimit, isRecovering, isRecoveringFromDevice, restoreHeight, proxyAddress);
if (success)
m_initialized = init(
daemonAddress,
trustedDaemon,
upperTransactionLimit,
isRecovering,
isRecoveringFromDevice,
restoreHeight,
proxyAddress);
if (m_initialized)
{
emit walletCreationHeightChanged();
qDebug() << "init async finished - starting refresh";
connected(true);
startRefresh();
}
else
{
qCritical() << "Failed to initialize the wallet";
}
});
if (future.first)
{
@@ -519,25 +532,44 @@ void Wallet::pauseRefresh()
m_refreshEnabled = false;
}
PendingTransaction *Wallet::createTransaction(const QString &dst_addr, const QString &payment_id,
quint64 amount, quint32 mixin_count,
PendingTransaction::Priority priority)
PendingTransaction *Wallet::createTransaction(
const QVector<QString> &destinationAddresses,
const QString &payment_id,
const QVector<QString> &destinationAmounts,
quint32 mixin_count,
PendingTransaction::Priority priority)
{
std::vector<std::string> destinations;
for (const auto &address : destinationAddresses) {
destinations.push_back(address.toStdString());
}
std::vector<uint64_t> amounts;
for (const auto &amount : destinationAmounts) {
amounts.push_back(Monero::Wallet::amountFromString(amount.toStdString()));
}
std::set<uint32_t> subaddr_indices;
Monero::PendingTransaction * ptImpl = m_walletImpl->createTransaction(
dst_addr.toStdString(), payment_id.toStdString(), amount, mixin_count,
static_cast<Monero::PendingTransaction::Priority>(priority), currentSubaddressAccount(), subaddr_indices);
PendingTransaction * result = new PendingTransaction(ptImpl,0);
Monero::PendingTransaction *ptImpl = m_walletImpl->createTransactionMultDest(
destinations,
payment_id.toStdString(),
amounts,
mixin_count,
static_cast<Monero::PendingTransaction::Priority>(priority),
currentSubaddressAccount(),
subaddr_indices);
PendingTransaction *result = new PendingTransaction(ptImpl, 0);
return result;
}
void Wallet::createTransactionAsync(const QString &dst_addr, const QString &payment_id,
quint64 amount, quint32 mixin_count,
PendingTransaction::Priority priority)
void Wallet::createTransactionAsync(
const QVector<QString> &destinationAddresses,
const QString &payment_id,
const QVector<QString> &destinationAmounts,
quint32 mixin_count,
PendingTransaction::Priority priority)
{
m_scheduler.run([this, dst_addr, payment_id, amount, mixin_count, priority] {
PendingTransaction *tx = createTransaction(dst_addr, payment_id, amount, mixin_count, priority);
emit transactionCreated(tx, dst_addr, payment_id, mixin_count);
m_scheduler.run([this, destinationAddresses, payment_id, destinationAmounts, mixin_count, priority] {
PendingTransaction *tx = createTransaction(destinationAddresses, payment_id, destinationAmounts, mixin_count, priority);
emit transactionCreated(tx, destinationAddresses, payment_id, mixin_count);
});
}
@@ -558,7 +590,7 @@ void Wallet::createTransactionAllAsync(const QString &dst_addr, const QString &p
{
m_scheduler.run([this, dst_addr, payment_id, mixin_count, priority] {
PendingTransaction *tx = createTransactionAll(dst_addr, payment_id, mixin_count, priority);
emit transactionCreated(tx, dst_addr, payment_id, mixin_count);
emit transactionCreated(tx, {dst_addr}, payment_id, mixin_count);
});
}
@@ -573,7 +605,7 @@ void Wallet::createSweepUnmixableTransactionAsync()
{
m_scheduler.run([this] {
PendingTransaction *tx = createSweepUnmixableTransaction();
emit transactionCreated(tx, "", "", 0);
emit transactionCreated(tx, {""}, "", 0);
});
}
@@ -613,17 +645,32 @@ void Wallet::disposeTransaction(UnsignedTransaction *t)
delete t;
}
void Wallet::estimateTransactionFeeAsync(const QString &destination,
quint64 amount,
PendingTransaction::Priority priority,
const QJSValue &callback)
void Wallet::estimateTransactionFeeAsync(
const QVector<QString> &destinationAddresses,
const QVector<quint64> &amounts,
PendingTransaction::Priority priority,
const QJSValue &callback)
{
m_scheduler.run([this, destination, amount, priority] {
const uint64_t fee = m_walletImpl->estimateTransactionFee(
{std::make_pair(destination.toStdString(), amount)},
static_cast<Monero::PendingTransaction::Priority>(priority));
return QJSValueList({QString::fromStdString(Monero::Wallet::displayAmount(fee))});
}, callback);
m_scheduler.run(
[this, destinationAddresses, amounts, priority] {
if (destinationAddresses.size() != amounts.size())
{
return QJSValueList({""});
}
std::vector<std::pair<std::string, uint64_t>> destinations;
destinations.reserve(destinationAddresses.size());
for (size_t index = 0; index < destinationAddresses.size(); ++index)
{
destinations.emplace_back(std::make_pair(destinationAddresses[index].toStdString(), amounts[index]));
}
const uint64_t fee = m_walletImpl->estimateTransactionFee(
destinations,
static_cast<Monero::PendingTransaction::Priority>(priority));
return QJSValueList({QString::fromStdString(Monero::Wallet::displayAmount(fee))});
},
callback);
}
TransactionHistory *Wallet::history() const
@@ -1054,6 +1101,7 @@ Wallet::Wallet(Monero::Wallet *w, QObject *parent)
, m_connectionStatus(Wallet::ConnectionStatus_Disconnected)
, m_connectionStatusTtl(WALLET_CONNECTION_STATUS_CACHE_TTL_SECONDS)
, m_disconnected(true)
, m_initialized(false)
, m_currentSubaddressAccount(0)
, m_subaddress(nullptr)
, m_subaddressModel(nullptr)
@@ -1074,7 +1122,6 @@ Wallet::Wallet(Monero::Wallet *w, QObject *parent)
m_connectionStatusTime.start();
m_daemonBlockChainHeightTime.start();
m_daemonBlockChainTargetHeightTime.start();
m_initialized = false;
m_connectionStatusRunning = false;
m_daemonUsername = "";
m_daemonPassword = "";

View File

@@ -29,6 +29,8 @@
#ifndef WALLET_H
#define WALLET_H
#include <atomic>
#include <QElapsedTimer>
#include <QObject>
#include <QMutex>
@@ -214,15 +216,13 @@ public:
Q_INVOKABLE void startRefresh();
Q_INVOKABLE void pauseRefresh();
//! creates transaction
Q_INVOKABLE PendingTransaction * createTransaction(const QString &dst_addr, const QString &payment_id,
quint64 amount, quint32 mixin_count,
PendingTransaction::Priority priority);
//! creates async transaction
Q_INVOKABLE void createTransactionAsync(const QString &dst_addr, const QString &payment_id,
quint64 amount, quint32 mixin_count,
PendingTransaction::Priority priority);
Q_INVOKABLE void createTransactionAsync(
const QVector<QString> &destinationAddresses,
const QString &payment_id,
const QVector<QString> &destinationAmounts,
quint32 mixin_count,
PendingTransaction::Priority priority);
//! creates transaction with all outputs
Q_INVOKABLE PendingTransaction * createTransactionAll(const QString &dst_addr, const QString &payment_id,
@@ -253,10 +253,11 @@ public:
//! deletes unsigned transaction and frees memory
Q_INVOKABLE void disposeTransaction(UnsignedTransaction * t);
Q_INVOKABLE void estimateTransactionFeeAsync(const QString &destination,
quint64 amount,
PendingTransaction::Priority priority,
const QJSValue &callback);
Q_INVOKABLE void estimateTransactionFeeAsync(
const QVector<QString> &destinationAddresses,
const QVector<quint64> &amounts,
PendingTransaction::Priority priority,
const QJSValue &callback);
//! returns transaction history
TransactionHistory * history() const;
@@ -380,7 +381,11 @@ signals:
void deviceShowAddressShowed();
// emitted when transaction is created async
void transactionCreated(PendingTransaction * transaction, QString address, QString paymentId, quint32 mixinCount);
void transactionCreated(
PendingTransaction *transaction,
const QVector<QString> &addresses,
const QString &paymentId,
quint32 mixinCount);
void connectionStatusChanged(int status) const;
void currentSubaddressAccountChanged() const;
@@ -413,6 +418,13 @@ private:
quint64 restoreHeight,
const QString& proxyAddress);
PendingTransaction *createTransaction(
const QVector<QString> &destinationAddresses,
const QString &payment_id,
const QVector<QString> &destinationAmounts,
quint32 mixin_count,
PendingTransaction::Priority priority);
bool disconnected() const;
bool refreshing() const;
void refreshingSet(bool value);
@@ -444,7 +456,7 @@ private:
int m_connectionStatusTtl;
mutable QElapsedTimer m_connectionStatusTime;
bool m_disconnected;
mutable bool m_initialized;
std::atomic<bool> m_initialized;
uint32_t m_currentSubaddressAccount;
Subaddress * m_subaddress;
mutable SubaddressModel * m_subaddressModel;

View File

@@ -251,7 +251,7 @@ QString WalletManager::errorString() const
return tr("Unknown error");
}
quint64 WalletManager::maximumAllowedAmount() const
quint64 WalletManager::maximumAllowedAmount()
{
return Monero::Wallet::maximumAllowedAmount();
}
@@ -266,7 +266,7 @@ QString WalletManager::displayAmount(quint64 amount)
return QString::fromStdString(Monero::Wallet::displayAmount(amount));
}
quint64 WalletManager::amountFromString(const QString &amount) const
quint64 WalletManager::amountFromString(const QString &amount)
{
return Monero::Wallet::amountFromString(amount.toStdString());
}
@@ -276,6 +276,17 @@ quint64 WalletManager::amountFromDouble(double amount) const
return Monero::Wallet::amountFromDouble(amount);
}
QString WalletManager::amountsSumFromStrings(const QVector<QString> &amounts)
{
quint64 sum = 0;
for (const auto &amountString : amounts)
{
const quint64 amount = amountFromString(amountString);
sum = sum + std::min(maximumAllowedAmount() - sum, amount);
}
return QString::number(sum);
}
bool WalletManager::paymentIdValid(const QString &payment_id) const
{
return Monero::Wallet::paymentIdValid(payment_id.toStdString());

View File

@@ -133,9 +133,10 @@ public:
//! since we can't call static method from QML, move it to this class
Q_INVOKABLE static QString displayAmount(quint64 amount);
Q_INVOKABLE quint64 amountFromString(const QString &amount) const;
Q_INVOKABLE static quint64 amountFromString(const QString &amount);
Q_INVOKABLE quint64 amountFromDouble(double amount) const;
Q_INVOKABLE quint64 maximumAllowedAmount() const;
Q_INVOKABLE static QString amountsSumFromStrings(const QVector<QString> &amounts);
Q_INVOKABLE static quint64 maximumAllowedAmount();
// QML JS engine doesn't support unsigned integers
Q_INVOKABLE QString maximumAllowedAmountAsString() const;

View File

@@ -117,13 +117,14 @@ Logger::Logger(QCoreApplication &parent, QString userDefinedLogFilePath)
c.setGlobally(el::ConfigurationType::ToFile, "false");
c.setGlobally(el::ConfigurationType::ToStandardOutput, "true");
el::Loggers::setDefaultConfigurations(c, true);
qInstallMessageHandler(messageHandler);
}
void Logger::resetLogFilePath(bool portable)
{
m_logFilePath = QDir::toNativeSeparators(getLogPath(m_userDefinedLogFilePath, portable));
Monero::Wallet::init(m_applicationFilePath.c_str(), "monero-wallet-gui", m_logFilePath.toStdString(), true);
qInstallMessageHandler(messageHandler);
qWarning() << "Logging to" << m_logFilePath;
emit logFilePathChanged();
}

View File

@@ -120,6 +120,10 @@ Q_IMPORT_PLUGIN(QQmlDebugServerFactory)
Q_IMPORT_PLUGIN(QTcpServerConnectionFactory)
Q_IMPORT_PLUGIN(QGenericEnginePlugin)
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
Q_IMPORT_PLUGIN(QtQmlPlugin)
#endif
Q_IMPORT_PLUGIN(QtQmlModelsPlugin)
Q_IMPORT_PLUGIN(QtQuick2Plugin)
Q_IMPORT_PLUGIN(QtQuickLayoutsPlugin)
Q_IMPORT_PLUGIN(QtGraphicalEffectsPlugin)
@@ -156,8 +160,6 @@ int main(int argc, char *argv[])
// platform dependant settings
#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS)
bool isDesktop = true;
#elif defined(Q_OS_LINUX)
bool isLinux = true;
#elif defined(Q_OS_ANDROID)
bool isAndroid = true;
#elif defined(Q_OS_IOS)
@@ -179,8 +181,8 @@ int main(int argc, char *argv[])
// disable "QApplication: invalid style override passed" warning
if (isDesktop) qputenv("QT_STYLE_OVERRIDE", "fusion");
#ifdef Q_OS_LINUX
// force platform xcb
if (isDesktop) qputenv("QT_QPA_PLATFORM", "xcb");
// platform xcb by default
if (isDesktop && qEnvironmentVariableIsEmpty("QT_QPA_PLATFORM")) qputenv("QT_QPA_PLATFORM", "xcb");
#endif
// enable High DPI scaling
@@ -189,6 +191,12 @@ int main(int argc, char *argv[])
// Turn off colors in monerod log output.
qputenv("TERM", "goaway");
#if defined(Q_OS_MACOS)
QDir::setCurrent(QDir(MacOSHelper::bundlePath() + QDir::separator() + "..").canonicalPath());
#endif
qputenv("QML_DISABLE_DISK_CACHE", "1");
MainApp app(argc, argv);
#if defined(Q_OS_WIN)
@@ -277,7 +285,6 @@ Verify update binary using 'shasum'-compatible (SHA256 algo) output signed by tw
if (logLevelOk && logLevel >= 0 && logLevel <= Monero::WalletManagerFactory::LogLevel_Max){
Monero::WalletManagerFactory::setLogLevel(logLevel);
}
qWarning().noquote() << "app startd" << "(log: " + logger.logFilePath() + ")";
if (parser.isSet(verifyUpdateOption))
{
@@ -305,11 +312,6 @@ Verify update binary using 'shasum'-compatible (SHA256 algo) output signed by tw
return 1;
}
// Desktop entry
#ifdef Q_OS_LINUX
registerXdgMime(app);
#endif
IPC *ipc = new IPC(&app);
QStringList posArgs = parser.positionalArguments();
@@ -326,10 +328,6 @@ Verify update binary using 'shasum'-compatible (SHA256 algo) output signed by tw
// start listening
QTimer::singleShot(0, ipc, SLOT(bind()));
#if defined(Q_OS_MACOS)
QDir::setCurrent(QDir(MacOSHelper::bundlePath() + QDir::separator() + "..").canonicalPath());
#endif
// screen settings
// Mobile is designed on 128dpi
qreal ref_dpi = 128;
@@ -454,8 +452,8 @@ Verify update binary using 'shasum'-compatible (SHA256 algo) output signed by tw
// Exclude daemon manager from IOS
#ifndef Q_OS_IOS
DaemonManager * daemonManager = DaemonManager::instance();
engine.rootContext()->setContextProperty("daemonManager", daemonManager);
DaemonManager daemonManager;
engine.rootContext()->setContextProperty("daemonManager", &daemonManager);
#endif
engine.rootContext()->setContextProperty("isWindows", isWindows);

View File

@@ -27,10 +27,16 @@
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "oshelper.h"
#include <unordered_set>
#include <QCoreApplication>
#include <QGuiApplication>
#include <QFileDialog>
#include <QScreen>
#include <QStandardPaths>
#include <QTemporaryFile>
#include <QWindow>
#include <QDir>
#include <QDebug>
#include <QDesktopServices>
@@ -46,13 +52,49 @@
#endif
#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)
#include <X11/XKBlib.h>
#undef Bool
#undef KeyPress
#undef KeyRelease
#undef FocusIn
#undef FocusOut
// #undef those Xlib #defines that conflict with QEvent::Type enum
#include "qt/utils.h"
#endif
#include "QR-Code-scanner/Decoder.h"
#include "qt/ScopeGuard.h"
namespace
{
QPixmap screenshot()
{
#ifdef Q_OS_MAC
return MacOSHelper::screenshot();
#else
std::unordered_set<QWindow *> hidden;
const QWindowList windows = QGuiApplication::allWindows();
for (QWindow *window : windows)
{
if (window->isVisible())
{
hidden.emplace(window);
window->hide();
}
}
const auto unhide = sg::make_scope_guard([&hidden]() {
for (QWindow *window : hidden)
{
window->show();
}
});
return QGuiApplication::primaryScreen()->grabWindow(0);
#endif
}
} // namespace
#if defined(Q_OS_WIN)
bool openFolderAndSelectItem(const QString &filePath)
{
@@ -85,11 +127,38 @@ OSHelper::OSHelper(QObject *parent) : QObject(parent)
}
void OSHelper::createDesktopEntry() const
{
#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)
registerXdgMime();
#endif
}
QString OSHelper::downloadLocation() const
{
return QStandardPaths::writableLocation(QStandardPaths::DownloadLocation);
}
QList<QString> OSHelper::grabQrCodesFromScreen() const
{
QList<QString> codes;
try
{
const QImage image = screenshot().toImage();
const std::vector<std::string> decoded = QrDecoder().decode(image);
std::for_each(decoded.begin(), decoded.end(), [&codes](const std::string &code) {
codes.push_back(QString::fromStdString(code));
});
}
catch (const std::exception &e)
{
qWarning() << e.what();
}
return codes;
}
bool OSHelper::openContainingFolder(const QString &filePath) const
{
QString canonicalFilePath = QFileInfo(filePath).canonicalFilePath();
@@ -154,6 +223,7 @@ bool OSHelper::isCapsLock() const
unsigned n;
XkbGetIndicatorState(d, XkbUseCoreKbd, &n);
caps_state = (n & 0x01) == 1;
XCloseDisplay(d);
}
return caps_state;
#elif defined(Q_OS_MAC)

View File

@@ -29,7 +29,9 @@
#ifndef OSHELPER_H
#define OSHELPER_H
#include <QList>
#include <QObject>
#include <QString>
/**
* @brief The OSHelper class - exports to QML some OS-related functions
*/
@@ -41,7 +43,9 @@ class OSHelper : public QObject
public:
explicit OSHelper(QObject *parent = 0);
Q_INVOKABLE void createDesktopEntry() const;
Q_INVOKABLE QString downloadLocation() const;
Q_INVOKABLE QList<QString> grabQrCodesFromScreen() const;
Q_INVOKABLE bool openContainingFolder(const QString &filePath) const;
Q_INVOKABLE QString openSaveFileDialog(const QString &title, const QString &folder, const QString &filename) const;
Q_INVOKABLE QString temporaryFilename() const;

View File

@@ -1,8 +1,10 @@
file(GLOB_RECURSE SOURCES *.cpp)
file(GLOB_RECURSE HEADERS *.h)
find_library(GCRYPT_LIBRARY gcrypt)
find_library(GPG_ERROR_LIBRARY gpg-error)
find_library(GCRYPT_LIBRARY gcrypt REQUIRED)
find_path(GCRYPT_INCLUDE_DIR gcrypt.h REQUIRED)
find_library(GPG_ERROR_LIBRARY gpg-error REQUIRED)
add_library(openpgp
${SOURCES}
@@ -10,7 +12,8 @@ add_library(openpgp
target_include_directories(openpgp
PUBLIC
${CMAKE_SOURCE_DIR}/monero/contrib/epee/include)
${CMAKE_SOURCE_DIR}/monero/contrib/epee/include
${GCRYPT_INCLUDE_DIR})
target_link_libraries(openpgp
PUBLIC

View File

@@ -1,8 +1,16 @@
#include "FutureScheduler.h"
#include <mutex>
#include <QThreadPool>
FutureScheduler::FutureScheduler(QObject *parent)
: QObject(parent), Alive(0), Stopping(false)
{
static std::once_flag once;
std::call_once(once, []() {
QThreadPool::globalInstance()->setMaxThreadCount(4);
});
}
FutureScheduler::~FutureScheduler()

View File

@@ -179,13 +179,13 @@ bool MoneroSettings::portable() const
return this->m_settings && this->m_settings->fileName() == portableFilePath();
}
bool MoneroSettings::portableConfigExists() const
bool MoneroSettings::portableConfigExists()
{
QFileInfo info(portableFilePath());
return info.exists() && info.isFile();
}
QString MoneroSettings::portableFilePath() const
QString MoneroSettings::portableFilePath()
{
static QString filename(QDir(portableFolderName()).absoluteFilePath("settings.ini"));
return filename;

View File

@@ -64,6 +64,7 @@ public:
Q_INVOKABLE void setWritable(bool enabled);
static QString portableFolderName();
static bool portableConfigExists();
public slots:
void _q_propertyChanged();
@@ -84,8 +85,7 @@ private:
void store();
bool portable() const;
bool portableConfigExists() const;
QString portableFilePath() const;
static QString portableFilePath();
std::unique_ptr<QSettings> portableSettings() const;
std::unique_ptr<QSettings> unportableSettings() const;
void swap(std::unique_ptr<QSettings> newSettings);

View File

@@ -29,6 +29,8 @@
#ifndef MACOSHELPER_H
#define MACOSHELPER_H
#include <QPixmap>
class MacOSHelper
{
MacOSHelper() {}
@@ -36,6 +38,7 @@ class MacOSHelper
public:
static bool isCapsLock();
static bool openFolderAndSelectItem(const QUrl &path);
static QPixmap screenshot();
static QString bundlePath();
};

View File

@@ -26,6 +26,8 @@
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <unordered_set>
#include <QtCore>
#include <QtGui>
#include <QtMac>
@@ -37,6 +39,8 @@
#include <ApplicationServices/ApplicationServices.h>
#include <Availability.h>
#include "ScopeGuard.h"
bool MacOSHelper::isCapsLock()
{
#ifdef __MAC_10_12
@@ -56,6 +60,41 @@ bool MacOSHelper::openFolderAndSelectItem(const QUrl &path)
return true;
}
QPixmap MacOSHelper::screenshot()
{
std::unordered_set<uintptr_t> appWindowIds;
for (NSWindow *window in [NSApp windows])
{
appWindowIds.insert((uintptr_t)[window windowNumber]);
}
CFArrayRef onScreenWindows = CGWindowListCreate(kCGWindowListOptionOnScreenOnly, kCGNullWindowID);
const auto onScreenWindowsClenaup = sg::make_scope_guard([&onScreenWindows]() {
CFRelease(onScreenWindows);
});
CFMutableArrayRef foreignWindows = CFArrayCreateMutable(NULL, CFArrayGetCount(onScreenWindows), NULL);
const auto foreignWindowsClenaup = sg::make_scope_guard([&foreignWindows]() {
CFRelease(foreignWindows);
});
for (CFIndex index = 0, count = CFArrayGetCount(onScreenWindows); index < count; ++index)
{
const uintptr_t windowId = reinterpret_cast<const uintptr_t>(CFArrayGetValueAtIndex(onScreenWindows, index));
if (appWindowIds.find(windowId) == appWindowIds.end())
{
CFArrayAppendValue(foreignWindows, reinterpret_cast<const void *>(windowId));
}
}
CGImageRef image = CGWindowListCreateImageFromArray(CGRectInfinite, foreignWindows, kCGWindowListOptionAll);
const auto imageClenaup = sg::make_scope_guard([&image]() {
CFRelease(image);
});
return QtMac::fromCGImageRef(image);
}
QString MacOSHelper::bundlePath()
{
NSBundle *main = [NSBundle mainBundle];

View File

@@ -27,7 +27,7 @@
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <QtCore>
#include <QApplication>
#include <QCoreApplication>
#include <QtGlobal>
#include "TailsOS.h"
@@ -88,7 +88,7 @@ QString getAccountName(){
}
#ifdef Q_OS_LINUX
QString xdgMime(QApplication &app){
QString xdgMime(){
return QString(
"[Desktop Entry]\n"
"Name=Monero GUI\n"
@@ -105,32 +105,32 @@ QString xdgMime(QApplication &app){
"StartupNotify=true\n"
"X-GNOME-Bugzilla-Bugzilla=GNOME\n"
"X-GNOME-UsesNotifications=true\n"
).arg(app.applicationFilePath());
"StartupWMClass=monero-wallet-gui\n"
).arg(QCoreApplication::applicationFilePath());
}
void registerXdgMime(QApplication &app){
void registerXdgMime(){
// Register desktop entry
// - MacOS handled via Info.plist
// - Windows handled in the installer by rbrunner7
// - Linux written to `QStandardPaths::ApplicationsLocation`
// - Tails written to persistent dotfiles
QString mime = xdgMime(app);
QString mime = xdgMime();
QString appPath = QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation);
QString filePath = QString("%1/monero-gui.desktop").arg(appPath);
if (TailsOS::detect() && TailsOS::detectDotPersistence() && TailsOS::usePersistence) {
TailsOS::persistXdgMime(filePath, mime);
return;
if (TailsOS::detect())
{
if (TailsOS::detectDotPersistence() && TailsOS::usePersistence)
{
TailsOS::persistXdgMime(filePath, mime);
}
}
else
{
QDir().mkpath(QFileInfo(filePath).path());
fileWrite(filePath, mime);
}
QFileInfo file(filePath);
QDir().mkpath(file.path()); // ensure directory exists
#ifdef QT_DEBUG
qDebug() << "Writing xdg mime: " << filePath;
#endif
fileWrite(filePath, mime);
}
#endif

View File

@@ -39,8 +39,8 @@ QByteArray fileOpen(QString path);
bool fileWrite(QString path, QString data);
QString getAccountName();
#ifdef Q_OS_LINUX
QString xdgMime(QApplication &app);
void registerXdgMime(QApplication &app);
QString xdgMime();
void registerXdgMime();
#endif
const static QRegExp reURI = QRegExp("^\\w+:\\/\\/([\\w+\\-?\\-_\\-=\\-&]+)");
QString randomUserAgent();

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

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