Compare commits

..

367 Commits

Author SHA1 Message Date
luigi1111
113efbfdf0 Merge pull request #3678
0e1c6ae build: prepare v0.17.2.3 (selsta)
2021-08-30 16:14:30 -04:00
selsta
0e1c6ae60f build: prepare v0.17.2.3 2021-08-29 20:49:45 +02:00
luigi1111
b461373b8a Merge pull request #3674
3719f00 TxKey: fix get / check proof (selsta)
2021-08-26 21:30:02 -04:00
luigi1111
046124cd9b Merge pull request #3672
09003dd StandardDialog: use secondary color for cancel button (rating89us)
2021-08-26 21:29:18 -04:00
luigi1111
0ca7e4ec76 Merge pull request #3670
ac432fe InputDialog: use secondary color for cancel Button (rating89us)
2021-08-26 21:28:38 -04:00
luigi1111
376eaecf08 Merge pull request #3667
52c8d68 WizardRestoreWallet4: 'Open wallet' -> 'Create wallet'; add translation (rating89us)
2021-08-26 21:28:08 -04:00
luigi1111
316f8b1762 Merge pull request #3666
4fec3a4 WizardHeader: fix subtitle text width (rating89us)
2021-08-26 21:25:22 -04:00
luigi1111
cbed1ed6f7 Merge pull request #3665
02e0ac1 cmake: remove unnecessary steps (selsta)
2021-08-26 21:24:34 -04:00
luigi1111
3507e848cf Merge pull request #3650
946fa53 Receive: implement payment request (rating89us)
2021-08-26 21:23:23 -04:00
luigi1111
60967d3930 Merge pull request #3644
57f9cf9 History: fix transactions missing after midnight (selsta)
2021-08-26 21:22:05 -04:00
luigi1111
55a262b892 Merge pull request #3618
5234570 WizardCreateDevice1: display images; differentiate Ledger Nano X and S; add label to dropdown (rating89us)
2021-08-26 21:19:11 -04:00
selsta
3719f00953 TxKey: fix get / check proof 2021-08-20 23:51:04 +02:00
rating89us
09003dd140 StandardDialog: use secondary color for cancel button 2021-08-20 14:34:38 +02:00
rating89us
ac432fe947 InputDialog: use secondary color for cancel Button 2021-08-20 13:23:43 +02:00
rating89us
5234570afa WizardCreateDevice1: display images; differentiate Ledger Nano X and S; add label to dropdown 2021-08-19 17:26:32 +02:00
rating89us
946fa538b9 Receive: implement payment request 2021-08-19 17:13:57 +02:00
rating89us
52c8d68240 WizardRestoreWallet4: "Open wallet" -> "Create wallet"; add translation 2021-08-15 21:25:20 +02:00
rating89us
4fec3a4d6f WizardHeader: fix subtitle text width 2021-08-13 14:56:22 +02:00
selsta
02e0ac1309 cmake: remove unnecessary steps 2021-08-12 01:08:13 +02:00
luigi1111
51828babbb Merge pull request #3641
d8fb9ec Transfer: use defaultFontColor for text cursor when address field is blank (rating89us)
2021-07-26 15:37:47 -04:00
luigi1111
a13e4b622c Merge pull request #3640
7805430 Account, Receive, RemoteNodeList, SettingsNode: selection indicator in lists (rating89us)
2021-07-26 15:37:26 -04:00
luigi1111
56a17e0a85 Merge pull request #3638
faf9ec3 AddressBook: add Grab QR code inline button (rating89us)
2021-07-26 15:36:48 -04:00
luigi1111
e74ef368df Merge pull request #3637
22291b1 NetworkStatusItem: add tooltip to switch node button; adjust colors of lightning icon, switch node button and network status (rating89us)
2021-07-26 15:36:20 -04:00
luigi1111
857d034f18 Merge pull request #3634
b30be48 README: TOC, update building titles (rating89us)
2021-07-26 15:35:55 -04:00
luigi1111
3f4cedea54 Merge pull request #3630
284caf8 RemoteNodeList: truncate long addresses (rating89us)
2021-07-26 15:35:13 -04:00
luigi1111
4376880b46 Merge pull request #3627
d20c589 Tooltip: fix tooltip width (rating89us)
2021-07-26 15:34:50 -04:00
luigi1111
98057487f6 Merge pull request #3624
ea9ed3e openpgp: add missing include (selsta)
2021-07-26 15:34:29 -04:00
luigi1111
06025352ce Merge pull request #3620
c4c549e Upgrade Font Awesome icons to v5.15.3 (rating89us)
2021-07-26 15:31:58 -04:00
selsta
57f9cf9d85 History: fix transactions missing after midnight 2021-07-26 00:42:44 +02:00
rating89us
d8fb9ec081 Transfer: use defaultFontColor for text cursor when address field is blank 2021-07-25 20:09:52 +02:00
rating89us
faf9ec3027 AddressBook: add Grab QR code inline button
Co-authored-by: selsta <selsta@users.noreply.github.com>
2021-07-25 09:08:17 +02:00
rating89us
22291b1df1 NetworkStatusItem: add tooltip to switch node button; adjust colors of lightning icon, switch node button and network status 2021-07-23 08:14:20 +02:00
rating89us
7805430f4f Account, Receive, RemoteNodeList, SettingsNode: selection indicator in lists 2021-07-23 08:13:01 +02:00
rating89us
b30be48a24 README: TOC, update building titles 2021-07-22 18:06:44 +02:00
rating89us
284caf83f6 RemoteNodeList: truncate long addresses 2021-07-21 01:34:02 +02:00
rating89us
d20c589e42 Tooltip: fix tooltip width 2021-07-16 09:59:45 +02:00
selsta
ea9ed3e0be openpgp: add missing include 2021-07-15 19:43:41 +02:00
rating89us
c4c549e57a Upgrade Font Awesome icons to v5.15.3 2021-07-12 23:15:59 +02:00
luigi1111
b6682330a6 Merge pull request #3611
0ce3e4b WizardOpenWallet1: navigate with keyboard; enable accessibility (rating89us)
2021-07-11 22:19:28 -04:00
luigi1111
b54ee598d8 Merge pull request #3523
20106b2 Tooltip: fix binding loop (selsta)
2021-07-11 22:18:49 -04:00
luigi1111
7da11b050c Merge pull request #3617
94b6a5b cmake: fix incorrect rebase (selsta)
2021-07-10 20:08:56 -04:00
selsta
94b6a5bbf5 cmake: fix incorrect rebase 2021-07-11 02:03:46 +02:00
luigi1111
5a88d4a669 Merge pull request #3565
3d6e9ce cmake: remove unnecessary file globbing (selsta)
2021-07-10 18:02:58 -04:00
selsta
3d6e9ce571 cmake: remove unnecessary file globbing 2021-07-10 23:58:25 +02:00
luigi1111
987e716374 Merge pull request #3614
3631482 SettingsInfo: fix displaying of Graphics mode and Tails on clipboard output (rating89us)
2021-07-10 17:55:11 -04:00
luigi1111
f81bfa1865 Merge pull request #3613
6739b51 WizardWalletInput: red border if error; error messages; remove placeholders; smaller font; icon for browse button (rating89us)
2021-07-10 17:54:34 -04:00
luigi1111
e4a3e282b5 Merge pull request #3593
2c0cf0d WizardCreateDevice1: move 'choose your device' dropdown to the top (rating89us)
2021-07-10 17:53:26 -04:00
luigi1111
c017522a3c Merge pull request #3599
f82336c TxConfirmationDialog: fix displaying of '<' when using fontMonoRegular (rating89us)
2021-07-10 17:52:32 -04:00
rating89us
6739b51a5b WizardWalletInput: red border if error; error messages; remove placeholders; smaller font; icon for browse button
Update WizardWalletInput.qml
2021-07-10 20:14:23 +02:00
rating89us
3631482419 SettingsInfo: fix displaying of Graphics mode and Tails on clipboard output 2021-07-09 23:00:18 +02:00
luigi1111
1c61ec2511 Merge pull request #3603
8419fce LanguageSidebar: navigate/select language with keyboard; enable accessibility; selected indicator; remember previous focused item (rating89us)
2021-07-06 11:50:34 -04:00
luigi1111
d0707d78a1 Merge pull request #3602
15dbbaf cmake: enable position independent code for quirc (selsta)
2021-07-06 11:50:01 -04:00
luigi1111
083b0fb7a8 Merge pull request #3601
d8f9d2f Transfer: fix fee label alignment (selsta)
2021-07-06 11:49:37 -04:00
luigi1111
24d113377b Merge pull request #3598
dbc8c7d qr: scan valid addresses that miss an uri prefix (selsta)
2021-07-06 11:48:58 -04:00
luigi1111
5e076325cd Merge pull request #3590
2db8f77 Transfer: UI changes to description field (use LineEdit, decrease font size, new placeholder) (rating89us)
2021-07-06 11:48:27 -04:00
luigi1111
5aef186c8a Merge pull request #3588
0de95e3 RemoteNodeList: reduce spacing between icons (selsta)
2021-07-06 11:47:49 -04:00
luigi1111
81f0209006 Merge pull request #3582
54e183a SettingsInfo: add portable mode to wallet mode (selsta)
2021-07-06 11:47:06 -04:00
luigi1111
b4e6f20b53 Merge pull request #3580
0fd0fc5 Receive: selected address details on top; QR code click to ampliate/right click to save as image; click on description to edit; display full address; use standard button for 'create new address' (rating89us)
2021-07-06 11:46:35 -04:00
luigi1111
a278781abf Merge pull request #3562
6610f6f cmake: fix compilation with zxcvbn, always enable (selsta)
2021-07-06 11:44:20 -04:00
luigi1111
2d82439b56 Merge pull request #3559
3eae630 History: collapse 'Sort & Filter' when user types (rating89us)
2021-07-06 11:43:48 -04:00
luigi1111
0b0bc87184 Merge pull request #3544
f75a244 Wizard: set unused wallet name (selsta)
2021-07-06 11:43:09 -04:00
luigi1111
59fcda43c6 Merge pull request #3505
76be4b8 main: set correct size for pruned blockchain (selsta)
2021-07-06 11:42:37 -04:00
luigi1111
6e87e2cb5b Merge pull request #3504
8236277 main: simplify fiat ticker code (selsta)
2021-07-06 11:42:09 -04:00
luigi1111
8730743207 Merge pull request #3503
b2255cf main: use Utils.epoch() for epoch (selsta)
2021-07-06 11:41:11 -04:00
luigi1111
4c67007e5b Merge pull request #3502
aa8c1a5 main: remove redundant assignment (selsta)
2021-07-06 11:40:42 -04:00
luigi1111
0ae1c721ef Merge pull request #3491
dbda233 pages: set correct icon fallback opacity (selsta)
2021-07-06 11:40:10 -04:00
luigi1111
21cce4cfb4 Merge pull request #3487
b2fbe51 StandardButton: fix warning with fallbackicon (selsta)
2021-07-06 11:39:19 -04:00
luigi1111
d595957405 Merge pull request #3165
3907dac Account: remove 'Balance:' label; add XMR; align balances (rating89us)
2021-07-06 11:36:19 -04:00
rating89us
0ce3e4b1e7 WizardOpenWallet1: navigate with keyboard; enable accessibility 2021-07-06 10:41:03 +02:00
rating89us
8419fce062 LanguageSidebar: navigate/select language with keyboard; enable accessibility; selected indicator; remember previous focused item 2021-07-04 21:56:57 +02:00
selsta
15dbbaf691 cmake: enable position independent code for quirc 2021-07-01 18:36:43 +02:00
selsta
d8f9d2f160 Transfer: fix fee label alignment 2021-07-01 01:19:57 +02:00
selsta
dbda233b94 pages: set correct icon fallback opacity 2021-07-01 00:46:03 +02:00
rating89us
f82336ce8c TxConfirmationDialog: fix displaying of "<" when using fontMonoRegular 2021-06-29 12:34:39 +02:00
selsta
dbc8c7d473 qr: scan valid addresses that miss an uri prefix 2021-06-29 04:53:24 +02:00
rating89us
2c0cf0d652 WizardCreateDevice1: move "choose your device" dropdown to the top 2021-06-28 00:33:49 +02:00
rating89us
2db8f77a0a Transfer: UI changes to description field (use LineEdit, decrease font size, new placeholder) 2021-06-26 21:25:19 +02:00
rating89us
0fd0fc5ceb Receive: selected address details on top; QR code click to ampliate/right click to save as image; click on description to edit; display full address; use standard button for "create new address" 2021-06-26 16:01:59 +02:00
selsta
0de95e3071 RemoteNodeList: reduce spacing between icons 2021-06-25 01:58:07 +02:00
luigi1111
b58bff39a0 Merge pull request #3586
614a7a0 RemoteNodeList: display shield icon if trusted daemon (rating89us)
2021-06-24 13:55:08 -05:00
luigi1111
bea763d7f8 Merge pull request #3585
b9a1fa8 History: display Payment proof dialog immediately after clicking the button (rating89us)
2021-06-24 13:54:42 -05:00
luigi1111
59a0184ebd Merge pull request #3584
51ac3ca StandardDropdown: use ArrowCursor; remove rotation of dropdownIcon; change background color on mouse hover; smaller text (rating89us)
2021-06-24 13:54:16 -05:00
luigi1111
1a8e3111e4 Merge pull request #3583
192b36f StandardDropdown: remove dots from corners (rating89us)
2021-06-24 13:53:22 -05:00
rating89us
614a7a086a RemoteNodeList: display shield icon if trusted daemon 2021-06-23 03:09:29 +02:00
rating89us
b9a1fa8563 History: display Payment proof dialog immediately after clicking the button 2021-06-22 21:19:27 +02:00
rating89us
51ac3ca981 StandardDropdown: use ArrowCursor; remove rotation of dropdownIcon; change background color on mouse hover; smaller text 2021-06-22 20:38:21 +02:00
rating89us
192b36f74f StandardDropdown: remove dots from corners 2021-06-22 10:09:11 +02:00
selsta
54e183a7f5 SettingsInfo: add portable mode to wallet mode 2021-06-22 02:30:54 +02:00
luigi1111
453388f744 Merge pull request #3578
64dd55a TitleBar: maximize window when title bar is double clicked (rating89us)
2021-06-21 13:41:10 -05:00
luigi1111
afc2b35ed0 Merge pull request #3576
4e2b1ce Transfer: don't overlap inside borders; fix margins (rating89us)
2021-06-21 13:40:36 -05:00
luigi1111
9114887866 Merge pull request #3575
08dd89d Transfer: remove leftMargin of 'Address' label (rating89us)
2021-06-21 13:39:47 -05:00
luigi1111
2afb346563 Merge pull request #3574
eacc57f StandardDropdown: use ColumnLayout; use same height of LineEdit; include dropdownLabel (rating89us)
2021-06-21 13:39:00 -05:00
luigi1111
bc8f39c311 Merge pull request #3571
c15c5b5 TransactionHistory: use displayAmount for amount (selsta)
2021-06-21 13:38:37 -05:00
luigi1111
286a3d140d Merge pull request #3569
ffd31c5 AddressBook: use LineEdit on descriptionLine; add tab/backtab; forceActiveFocus on addressLine; use Enter/Return key to save; cancel/delete buttons (rating89us)
2021-06-21 13:38:02 -05:00
luigi1111
5f2b5d940c Merge pull request #3550
417eaea History: stay on the same page after editing description (rating89us)
2021-06-21 13:36:34 -05:00
rating89us
64dd55a9a6 TitleBar: maximize window when title bar is double clicked 2021-06-20 19:28:11 +02:00
rating89us
eacc57fb44 StandardDropdown: use ColumnLayout; use same height of LineEdit; include dropdownLabel 2021-06-20 00:02:59 +02:00
rating89us
4e2b1cec95 Transfer: don't overlap inside borders; fix margins 2021-06-19 21:16:54 +02:00
rating89us
08dd89de58 Transfer: remove leftMargin of "Address" label 2021-06-19 18:21:40 +02:00
selsta
c15c5b5227 TransactionHistory: use displayAmount for amount 2021-06-18 02:08:37 +02:00
rating89us
ffd31c50da AddressBook: use LineEdit on descriptionLine; add tab/backtab; forceActiveFocus on addressLine; use Enter/Return key to save; cancel/delete buttons 2021-06-17 13:37:19 +02:00
luigi1111
b970cad48b Merge pull request #3564
dfe8146 SettingsInfo, WizardRestoreWallet1, WizardCreateDevice1: Correct restore height date when typed in wrong format (rating89us)
2021-06-16 14:53:44 -05:00
luigi1111
752f1faa93 Merge pull request #3563
b319dbb main: fixes bug not accepting new restore height (rating89us)
2021-06-16 14:53:17 -05:00
luigi1111
60b33d3a91 Merge pull request #3545
52aef11 LineEdit: use ColumnLayout instead of Item (also used in LineEditMulti) (rating89us)
2021-06-16 14:49:26 -05:00
luigi1111
5de306ab7a Merge pull request #3513
877fb9e README: freenode -> libera (selsta)
2021-06-16 14:47:59 -05:00
rating89us
dfe8146f5c SettingsInfo, WizardRestoreWallet1, WizardCreateDevice1: Correct restore height date when typed in wrong format 2021-06-15 16:34:07 +02:00
selsta
6610f6f2da cmake: fix compilation with zxcvbn, always enable 2021-06-14 21:47:54 +02:00
rating89us
b319dbb1b2 main: fixes bug not accepting new restore height 2021-06-14 21:21:16 +02:00
rating89us
3eae630cfe History: collapse "Sort & Filter" when user types 2021-06-12 20:43:35 +02:00
rating89us
52aef114fa LineEdit: use ColumnLayout instead of Item (also used in LineEditMulti) 2021-06-11 17:13:52 +02:00
luigi1111
7c379e2cda Merge pull request #3548
979e0da History: add fontAwesomeFallbackIcon (rating89us)
2021-06-10 11:07:53 -05:00
luigi1111
244459e606 Merge pull request #3546
8ac1b4e AddressBook: add 'See transactions' button (rating89us)
2021-06-10 11:07:10 -05:00
luigi1111
0e561de0a9 Merge pull request #3543
c5bad8e SettingsLog: fix text color bug on theme switch; new warning and green text colors (rating89us)
2021-06-10 11:06:31 -05:00
luigi1111
ceac6c8a47 Merge pull request #3542
f6a66b6 SettingsLog: ScrollBar always visible (except Mac) (rating89us)
2021-06-10 11:06:04 -05:00
luigi1111
b542f15531 Merge pull request #3541
2f1092d Slider: use MoneroComponents.TextPlain instead of Text on label (rating89us)
2021-06-10 11:05:38 -05:00
luigi1111
3621ab3344 Merge pull request #3539
b825f6e StandardDropdown: add FontAwesome fallback icons (rating89us)
2021-06-10 11:05:01 -05:00
luigi1111
4850e13895 Merge pull request #3538
ad38f15 DatePicker: date input with fixed size; longer animation; move up calendar rectangle (rating89us)
2021-06-10 11:04:39 -05:00
luigi1111
950e20d400 Merge pull request #3537
5a41849 SettingsLog: new placeholder text in command field (no commands in translation string) (rating89us)
2021-06-10 11:04:15 -05:00
luigi1111
124a8b5f4e Merge pull request #3536
cea712e History: close sortAndFilter when exiting Transactions page (rating89us)
2021-06-10 11:03:31 -05:00
luigi1111
0bd4d731d2 Merge pull request #3535
1f8aa0d History: change default dates of 'Date from' and 'Date to' DatePicker components (rating89us)
2021-06-10 11:02:36 -05:00
luigi1111
e3a17a66ff Merge pull request #3534
9ab104b DatePicker: display currently selected month when opening calendar (rating89us)
2021-06-10 11:01:52 -05:00
luigi1111
4f385b9a04 Merge pull request #3533
39d561d DatePicker: support mouse wheel to navigate months (rating89us)
2021-06-10 11:01:19 -05:00
luigi1111
2c54787644 Merge pull request #3532
23301da DatePicker: highlight selected date/today; hide invalid days (rating89us)
2021-06-10 10:27:42 -05:00
luigi1111
7770621a2f Merge pull request #3531
2c51762 DatePicker: FontAwesome fallback icons (rating89us)
2021-06-10 10:25:55 -05:00
luigi1111
b22fc4266c Merge pull request #3528
f06d6e0 Transfer: add XMR unit on transactions with a single recipient; move 'send all' button next to Amount label (rating89us)
2021-06-10 10:22:52 -05:00
luigi1111
2290e7e762 Merge pull request #3527
1512908 Transfer: fix y position of recipient elements (rating89us)
2021-06-10 10:21:07 -05:00
luigi1111
f8344ce7c6 Merge pull request #3525
ed1bc2e build: fix typo (rating89us)
2021-06-10 10:20:12 -05:00
luigi1111
1be9ea4828 Merge pull request #3524
aca6174 AddressBook: add Font Awesome fallback icons (rating89us)
2021-06-10 10:19:35 -05:00
luigi1111
b07016b7cd Merge pull request #3522
c9ee4bf History: move cursor to end of search input field after importing address (rating89us)
2021-06-10 10:18:59 -05:00
luigi1111
179b74e570 Merge pull request #3521
10a01fa Receive: add tooltip to search transactions button (rating89us)
2021-06-10 10:18:27 -05:00
luigi1111
0a6f6cb9ac Merge pull request #3520
0775b52 History: clean search bar inline button (rating89us)
2021-06-10 10:16:26 -05:00
rating89us
417eaeae28 History: stay on the same page after editing description 2021-06-10 12:59:39 +02:00
rating89us
8ac1b4ef58 AddressBook: add "See transactions" button 2021-06-10 09:05:09 +02:00
rating89us
979e0da9e0 History: add fontAwesomeFallbackIcon 2021-06-09 17:14:55 +02:00
rating89us
1f8aa0dff0 History: change default dates of "Date from" and "Date to" DatePicker components 2021-06-09 09:38:12 +02:00
selsta
f75a2447a7 Wizard: set unused wallet name 2021-06-09 01:00:16 +02:00
rating89us
f6a66b6779 SettingsLog: ScrollBar always visible (except Mac) 2021-06-07 22:37:39 +02:00
rating89us
c5bad8ec49 SettingsLog: fix text color bug on theme switch; new warning and green text colors 2021-06-07 22:35:54 +02:00
rating89us
2f1092de55 Slider: use MoneroComponents.TextPlain instead of Text on label 2021-06-07 15:30:18 +02:00
rating89us
b825f6e1bd StandardDropdown: add FontAwesome fallback icons 2021-06-07 14:02:19 +02:00
rating89us
ad38f155bc DatePicker: date input with fixed size; longer animation; move up calendar rectangle 2021-06-07 13:39:16 +02:00
rating89us
5a418499d4 SettingsLog: new placeholder text in command field (no commands in translation string) 2021-06-07 12:03:28 +02:00
rating89us
cea712e51d History: close sortAndFilter when exiting Transactions page 2021-06-07 11:31:40 +02:00
rating89us
39d561d9f2 DatePicker: support mouse wheel to navigate months 2021-06-06 23:21:32 +02:00
rating89us
23301da51b DatePicker: highlight selected date/today; hide invalid days 2021-06-06 23:15:53 +02:00
rating89us
9ab104b38a DatePicker: display currently selected month when opening calendar 2021-06-06 21:55:34 +02:00
rating89us
2c517623a1 DatePicker: FontAwesome fallback icons 2021-06-06 20:40:06 +02:00
rating89us
f06d6e067f Transfer: add XMR unit on transactions with a single recipient; move "send all" button next to Amount label 2021-06-04 19:39:21 +02:00
rating89us
1512908751 Transfer: fix y position of recipient elements 2021-06-04 19:35:19 +02:00
rating89us
ed1bc2eece build: fix typo 2021-06-02 19:33:22 +02:00
rating89us
0775b529c4 History: clean search bar inline button 2021-06-02 19:09:31 +02:00
rating89us
aca6174ef4 AddressBook: add Font Awesome fallback icons 2021-06-02 17:07:01 +02:00
selsta
20106b29ba Tooltip: fix binding loop 2021-06-02 17:06:45 +02:00
rating89us
c9ee4bf286 History: move cursor to end of search input field after importing address 2021-06-02 16:56:34 +02:00
rating89us
10a01fa5b4 Receive: add tooltip to search transactions button 2021-06-02 16:43:11 +02:00
luigi1111
2946127ed7 Merge pull request #3512
8411ec0 main: hide/show popups before/after inactivity screen lock (rating89us)
2021-06-01 01:39:21 -05:00
luigi1111
416979cdbd Merge pull request #3496
7997e6a AddressBook: highlight background when selecting contact for transfer page (rating89us)
2021-06-01 01:38:45 -05:00
luigi1111
1442215ce5 Merge pull request #3490
9d3864b Implement tooltips in multiple pages and components (rating89us)
2021-06-01 01:37:47 -05:00
luigi1111
ba3bdcd6a1 Merge pull request #3216
fa45b8f Receive: add search transactions button (rating89us)
2021-06-01 01:35:46 -05:00
selsta
877fb9ea87 README: freenode -> libera 2021-05-29 05:18:32 +02:00
rating89us
9d3864b7f0 Implement tooltips in multiple pages and components 2021-05-29 04:02:19 +02:00
rating89us
8411ec0787 main: hide/show popups before/after inactivity screen lock 2021-05-28 12:22:59 +02:00
selsta
76be4b8c0a main: set correct size for pruned blockchain 2021-05-26 03:39:35 +02:00
selsta
8236277906 main: simplify fiat ticker code 2021-05-26 01:09:30 +02:00
selsta
b2255cfd24 main: use Utils.epoch() for epoch 2021-05-26 00:55:50 +02:00
selsta
aa8c1a5421 main: remove redundant assignment 2021-05-26 00:28:58 +02:00
rating89us
7997e6aaf4 AddressBook: highlight background when selecting contact for transfer page 2021-05-22 11:31:05 +02:00
rating89us
fa45b8f96e Receive: add search transactions button 2021-05-22 10:59:17 +02:00
selsta
b2fbe51659 StandardButton: fix warning with fallbackicon 2021-05-19 02:01:10 +02:00
luigi1111
937cb98256 Merge pull request #3469
9cfeba9 cmake: cleanup hidapi / libusb (selsta)
2021-05-13 00:24:51 -05:00
selsta
9cfeba9ba1 cmake: cleanup hidapi / libusb 2021-05-13 07:12:28 +02:00
luigi1111
e730e3ff63 Merge pull request #3468
46dec78 cmake: move external subdir before -Werror (selsta)
2021-05-12 23:27:48 -05:00
luigi1111
6b580cbb00 Merge pull request #3467
c8c8736 js: fix getApproximateBlockchainHeight (testnet) (selsta)
2021-05-12 23:27:10 -05:00
luigi1111
cb33fe2fc0 Merge pull request #3466
380c5b5 Transfer: fix QR code scanner inline button icon (xiphon)
2021-05-12 23:26:38 -05:00
luigi1111
bff6f7587f Merge pull request #3464
9360de4 cmake: fix WITH_SCANNER static build (link against Qt5MultimediaQuick) (xiphon)
2021-05-12 23:26:11 -05:00
luigi1111
12a72970fb Merge pull request #3463
138e164 Transfer: highlight invalid address (xiphon)
2021-05-12 23:25:46 -05:00
luigi1111
16e1d64b74 Merge pull request #3462
410ad22 LineEditMulti: fix 'error' property (xiphon)
2021-05-12 23:25:23 -05:00
luigi1111
9dbad4745d Merge pull request #3461
8d59880 cmake: prepare v0.17.2.2 (selsta)
2021-05-12 23:24:59 -05:00
luigi1111
0e7d1ab65b Merge pull request #3459
7d34086 WizardSummary: display bootstrap address only in local node mode (selsta)
2021-05-12 23:24:29 -05:00
luigi1111
b69eff367c Merge pull request #3458
755d218 WizardSummary: display daemon address only in remote node mode (selsta)
2021-05-12 23:24:06 -05:00
luigi1111
54ef114370 Merge pull request #3456
b304140 Transfer: vertical center address (selsta)
2021-05-12 23:23:38 -05:00
luigi1111
e984949aa7 Merge pull request #3455
a021b71 cmake: don't add fstack-clash-protection with clang (selsta)
2021-05-12 23:22:36 -05:00
luigi1111
25be9d5b9b Merge pull request #3451
a89ac67 Docker: Linux - fix docker cache and apt update issue (xiphon)
2021-05-12 23:21:55 -05:00
selsta
46dec78806 cmake: move external subdir before -Werror 2021-05-08 23:29:57 +02:00
selsta
c8c8736cf3 js: fix getApproximateBlockchainHeight (testnet) 2021-05-08 16:45:45 +02:00
xiphon
380c5b5588 Transfer: fix QR code scanner inline button icon 2021-05-08 11:38:35 +00:00
xiphon
9360de4ef8 cmake: fix WITH_SCANNER static build (link against Qt5MultimediaQuick) 2021-05-08 11:02:05 +00:00
xiphon
138e164878 Transfer: highlight invalid address 2021-05-08 10:02:19 +00:00
xiphon
410ad22821 LineEditMulti: fix 'error' property 2021-05-08 09:56:00 +00:00
selsta
8d59880d02 cmake: prepare v0.17.2.2 2021-05-07 15:52:28 +02:00
selsta
7d340869fc WizardSummary: display bootstrap address only in local node mode 2021-05-06 20:19:16 +02:00
selsta
755d218594 WizardSummary: display daemon address only in remote node mode 2021-05-06 19:25:48 +02:00
selsta
b304140720 Transfer: vertical center address 2021-05-05 22:29:47 +02:00
selsta
a021b71261 cmake: don't add fstack-clash-protection with clang 2021-05-05 21:39:15 +02:00
xiphon
a89ac67d59 Docker: Linux - fix docker cache and apt update issue 2021-04-30 14:05:27 +00:00
luigi1111
426dc3fa47 Merge pull request #3448
2cda1fc cmake: link with wallet_api instead of wallet_merged (selsta)
2021-04-29 14:16:56 -04:00
luigi1111
947a70a638 Merge pull request #3447
dac0c04 main: fix Monero GUI window centering (xiphon)
2021-04-29 14:16:32 -04:00
luigi1111
9041e73345 Merge pull request #3446
ab5cb01 docker: fix boost bintray links (selsta)
2021-04-29 14:16:10 -04:00
luigi1111
ea01a536ce Merge pull request #3445
bc528cc main: drop unused altKeyReleased routine (xiphon)
2021-04-29 14:15:46 -04:00
luigi1111
56f471b1b6 Merge pull request #3444
ad6f26c main: drop unused enableUI routine (xiphon)
2021-04-29 14:14:51 -04:00
luigi1111
9a216682c8 Merge pull request #3443
db8c4ed main: handleTransactionConfirmed - fix 'no file specified' case (xiphon)
2021-04-29 14:14:24 -04:00
luigi1111
e2e5a3919b Merge pull request #3441
837dd61 Revert 'Animation slow down for debugging' (selsta)
2021-04-29 14:13:57 -04:00
luigi1111
adc7c02782 Merge pull request #3439
51ece5f Wallet: drop unused paymentId property (xiphon)
2021-04-29 14:12:31 -04:00
luigi1111
4c85aea7c3 Merge pull request #3438
b3ad95f cmake: WIN_DEPLOY_DLLS - update libicu version to 68 (xiphon)
2021-04-29 14:12:09 -04:00
luigi1111
5c2076daa1 Merge pull request #3437
7558a23 main: remove minor switch/case code duplication (selsta)
2021-04-29 14:11:45 -04:00
luigi1111
578324348d Merge pull request #3436
14b1476 History: cleanup unused lookupPaymentID function (selsta)
2021-04-29 14:10:53 -04:00
luigi1111
dc3e35a928 Merge pull request #3434
989f135 Navbar: fix layout bug on resize (selsta)
2021-04-29 14:08:24 -04:00
luigi1111
0ee5259466 Merge pull request #3433
e13d49f Navbar: horizontally center text (selsta)
2021-04-29 14:07:58 -04:00
luigi1111
c3e88adc6d Merge pull request #3430
db0485c main: simplify blackTheme code (selsta)
2021-04-29 14:07:24 -04:00
luigi1111
c368ce2776 Merge pull request #3428
0fb9306 Makefile: add CMAKE_BUILD_TYPE=Debug to debug build (selsta)
2021-04-29 14:06:40 -04:00
selsta
2cda1fca69 cmake: link with wallet_api instead of wallet_merged 2021-04-27 13:49:28 +02:00
xiphon
dac0c04d20 main: fix Monero GUI window centering 2021-04-26 21:11:21 +00:00
selsta
ab5cb01510 docker: fix boost bintray links 2021-04-26 19:51:03 +02:00
xiphon
bc528ccb77 main: drop unused altKeyReleased routine 2021-04-26 11:52:31 +00:00
xiphon
ad6f26c8b4 main: drop unused enableUI routine 2021-04-26 11:46:56 +00:00
xiphon
db8c4edb08 main: handleTransactionConfirmed - fix 'no file specified' case 2021-04-26 11:17:59 +00:00
selsta
837dd6184e Revert "Animation slow down for debugging"
This reverts commit baff7f213f.
2021-04-25 23:53:43 +02:00
xiphon
51ece5fd00 Wallet: drop unused paymentId property 2021-04-25 00:05:35 +00:00
xiphon
b3ad95fdfc cmake: WIN_DEPLOY_DLLS - update libicu version to 68 2021-04-24 22:08:25 +00:00
luigi1111
d2fc4e60c6 Merge pull request #3431
4e67cd0 Wallet: omit redundant 'delete' on destruction (xiphon)
2021-04-24 16:17:06 -04:00
luigi1111
1ea38be404 Merge pull request #3429
1f904d4 RemoteNodeEdit: fix getAddress() and isValid() inconsistency (xiphon)
2021-04-24 16:16:33 -04:00
luigi1111
d69b1e0520 Merge pull request #3427
0a4b017 cmake: link translations target with Qt5::Core (selsta)
2021-04-24 16:16:05 -04:00
luigi1111
c11e32f511 Merge pull request #3208
01c3c19 SuccessfulTxDialog: add View progress button (rating89us)
2021-04-24 16:14:28 -04:00
selsta
7558a23243 main: remove minor switch/case code duplication 2021-04-24 08:25:12 +02:00
selsta
14b1476786 History: cleanup unused lookupPaymentID function 2021-04-24 07:25:05 +02:00
selsta
989f135d9a Navbar: fix layout bug on resize 2021-04-24 05:32:09 +02:00
selsta
e13d49f43e Navbar: horizontally center text 2021-04-24 05:24:43 +02:00
xiphon
4e67cd0014 Wallet: omit redundant 'delete' on destruction 2021-04-22 23:08:41 +00:00
selsta
db0485c600 main: simplify blackTheme code 2021-04-22 23:14:32 +02:00
xiphon
1f904d4cff RemoteNodeEdit: fix getAddress() and isValid() inconsistency 2021-04-22 21:00:48 +00:00
selsta
0a4b017697 cmake: link translations target with Qt5::Core 2021-04-22 21:03:41 +02:00
selsta
0fb93061b1 Makefile: add CMAKE_BUILD_TYPE=Debug to debug build 2021-04-22 18:54:25 +02:00
luigi1111
bc1131ce41 Merge pull request #3425
2fcacd1 main: update estimatedBlockchainSize (rating89us)
2021-04-22 01:58:29 -04:00
luigi1111
5667526ef6 Merge pull request #3424
341b267 Merchant: display selected subaddress (selsta)
2021-04-22 01:58:02 -04:00
luigi1111
fe5992debd Merge pull request #3423
398e28e Account, Receive: add missing fallback icons (selsta)
2021-04-22 01:57:35 -04:00
luigi1111
ca09151092 Merge pull request #3422
69a6c6b WizardDaemonSettings: implement full remote node configuration support (xiphon)
2021-04-22 01:57:04 -04:00
luigi1111
4ddc6b1c90 Merge pull request #3420
becc747 WalletManager: support kdf round in device wallet restore (selsta)
2021-04-22 01:56:39 -04:00
luigi1111
46bc94fbe8 Merge pull request #3419
820b221 WizardHome: fix kdf textbox displaying incorrect value (selsta)
2021-04-22 01:55:54 -04:00
luigi1111
842a9278d0 Merge pull request #3414
23f71e1 WizardSummary: don't display node address in simple mode (selsta)
2021-04-22 01:54:27 -04:00
luigi1111
f57e115e99 Merge pull request #3413
684fd94 WizardDaemonSettings: add reset button to db location (selsta)
2021-04-22 01:53:54 -04:00
luigi1111
beb566f11e Merge pull request #2242
9fc6179 macOS: add basic menubar support (selsta)
2021-04-22 01:53:03 -04:00
rating89us
2fcacd1e84 main: update estimatedBlockchainSize 2021-04-21 19:04:55 +02:00
selsta
341b267852 Merchant: display selected subaddress 2021-04-21 04:13:39 +02:00
selsta
398e28ed24 Account, Receive: add missing fallback icons 2021-04-21 03:57:39 +02:00
xiphon
69a6c6b821 WizardDaemonSettings: implement full remote node configuration support 2021-04-20 22:15:15 +00:00
selsta
becc74714b WalletManager: support kdf round in device wallet restore 2021-04-20 21:44:23 +02:00
selsta
820b221fa5 WizardHome: fix kdf textbox displaying incorrect value 2021-04-20 21:28:04 +02:00
selsta
23f71e1959 WizardSummary: don't display node address in simple mode 2021-04-19 07:21:11 +02:00
selsta
684fd941fb WizardDaemonSettings: add reset button to db location 2021-04-19 07:17:07 +02:00
selsta
9fc617956d macOS: add basic menubar support 2021-04-18 15:50:36 +02:00
luigi1111
02ae14fd6b Merge pull request #3405
62faf4d Navbar: fix width being slightly off (selsta)
2021-04-16 12:57:35 -05:00
luigi1111
a84d7bd2cb Merge pull request #3404
ba62f9c main: omit QML Screen type, use QGuiApplication::primaryScreen() instead (xiphon)
2021-04-16 12:57:08 -05:00
luigi1111
84b9264d1d Merge pull request #3401
767b9e0 TextPlain, Label: implement tooltips. Transfer: advanced - use tooltips (xiphon)
2021-04-16 12:56:34 -05:00
luigi1111
0ae6435429 Merge pull request #3397
6f7192b Transfer: fix desktop icon style (selsta)
2021-04-16 12:55:59 -05:00
luigi1111
c47332e2f1 Merge pull request #3395
d60bbb7 Wizard: use endsWith, fix todo (selsta)
2021-04-16 12:55:37 -05:00
luigi1111
7dcd33f203 Merge pull request #3394
c60252d LanguageSidebar: simplify code (selsta)
2021-04-16 12:55:08 -05:00
luigi1111
bed56137e3 Merge pull request #3392
475f263 main: lower minimum required QtQml.Models version to 2.2 (xiphon)
2021-04-16 12:54:44 -05:00
selsta
62faf4d82e Navbar: fix width being slightly off 2021-04-16 02:37:25 +02:00
xiphon
ba62f9c686 main: omit QML Screen type, use QGuiApplication::primaryScreen() instead 2021-04-15 19:50:32 +00:00
selsta
6f7192bb12 Transfer: fix desktop icon style 2021-04-15 14:55:40 +02:00
xiphon
767b9e05b3 TextPlain, Label: implement tooltips. Transfer: advanced - use tooltips 2021-04-15 00:09:45 +00:00
selsta
d60bbb72f7 Wizard: use endsWith, fix todo 2021-04-14 21:34:17 +02:00
selsta
c60252d3ce LanguageSidebar: simplify code 2021-04-14 19:17:01 +02:00
xiphon
475f26398d main: lower minimum required QtQml.Models version to 2.2 2021-04-14 15:34:05 +00:00
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
Ben Evanoff
7c32fe6b5c remove copy qr uri to clipboard button 2021-01-02 14:34:59 -06:00
rating89us
01c3c19653 SuccessfulTxDialog: add View progress button 2020-12-04 12:53:40 +01:00
rating89us
cedfa5aabb History: search by receiving address, receiving address label, address book label 2020-11-07 20:04:12 +01: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
3907dac198 Account: remove "Balance:" label; add XMR; align balances 2020-10-17 13:57:24 +02:00
175 changed files with 59363 additions and 307077 deletions

View File

@@ -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-platform qml-module-qt-labs-folderlistmodel qttools5-dev-tools qml-module-qtquick-templates2 libqt5svg5-dev libgcrypt20-dev xvfb
- name: build
run: DEV_MODE=ON make release -j3
- name: test qml
@@ -67,7 +67,7 @@ jobs:
- 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
run: pip3 install requests semantic_version lxml py7zr
- name: download qt
run: |
curl -O https://raw.githubusercontent.com/engnr/qt-downloader/master/qt-downloader
@@ -79,6 +79,8 @@ jobs:
- 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
@@ -99,12 +101,16 @@ jobs:
key: docker-linux-static-{hash}
restore-keys: |
docker-linux-static-
- name: preprare build enviroment
- 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: prepare build environment
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 }}
@@ -124,10 +130,12 @@ jobs:
key: docker-windows-static-{hash}
restore-keys: |
docker-windows-static-
- name: preprare build enviroment
- name: prepare build environment
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 }}
@@ -141,7 +149,7 @@ jobs:
- uses: actions/checkout@v1
with:
submodules: recursive
- name: preprare build enviroment
- name: prepare build environment
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

View File

@@ -4,14 +4,13 @@ project(monero-gui)
message(STATUS "Initiating compile using CMake ${CMAKE_VERSION}")
set(VERSION_MAJOR "17")
set(VERSION_MINOR "1")
set(VERSION_REVISION "9")
set(VERSION_MINOR "2")
set(VERSION_REVISION "3")
set(VERSION "0.${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_REVISION}")
option(STATIC "Link libraries statically, requires static Qt")
option(USE_DEVICE_TREZOR "Trezor support compilation" ON)
option(ENABLE_PASS_STRENGTH_METER "Enable zxcvbn library for password strength" OFF)
option(WITH_SCANNER "Enable webcam QR scanner" OFF)
option(DEV_MODE "Checkout latest monero master on build" OFF)
@@ -48,8 +47,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()
@@ -57,16 +57,13 @@ if(NOT MANUAL_SUBMODULES)
endif()
add_subdirectory(monero)
add_subdirectory(external)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)
set_property(TARGET wallet_merged PROPERTY FOLDER "monero")
get_directory_property(ARCH_WIDTH DIRECTORY "monero" DEFINITION ARCH_WIDTH)
get_directory_property(UNBOUND_LIBRARY DIRECTORY "monero" DEFINITION UNBOUND_LIBRARY)
get_directory_property(DEVICE_TREZOR_READY DIRECTORY "monero" DEFINITION DEVICE_TREZOR_READY)
get_directory_property(TREZOR_DEP_LIBS DIRECTORY "monero" DEFINITION TREZOR_DEP_LIBS)
if (NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
add_definitions(-DQT_NO_DEBUG)
@@ -80,13 +77,6 @@ if(STATIC)
add_definitions(-DMONERO_GUI_STATIC)
endif()
# Include password strength library
if(ENABLE_PASS_STRENGTH_METER)
message(STATUS "Building with pass strength meter support.")
else()
add_definitions(-DDISABLE_PASS_STRENGTH_METER)
endif()
include(CMakePackageConfigHelpers)
# force version update
@@ -139,18 +129,6 @@ endif()
find_library(SODIUM_LIBRARY sodium)
message(STATUS "libsodium: libraries at ${SODIUM_LIBRARY}")
# LibUSB
find_package(LibUSB)
message(STATUS "libusb: include dir at ${LibUSB_INCLUDE_DIRS}")
message(STATUS "libusb: libraries at ${LibUSB_LIBRARIES}")
# HIDApi
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)
set(Boost_DEBUG ON)
@@ -298,10 +276,12 @@ list(APPEND QT5_LIBRARIES
if(STATIC)
set(QT5_EXTRA_PATHS ${QT5_PKG_CONFIG_Qt5Qml_PREFIX}/qml/Qt/labs/folderlistmodel)
list(APPEND QT5_EXTRA_PATHS ${QT5_PKG_CONFIG_Qt5Qml_PREFIX}/qml/Qt/labs/settings)
list(APPEND QT5_EXTRA_PATHS ${QT5_PKG_CONFIG_Qt5Qml_PREFIX}/qml/Qt/labs/platform)
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)
@@ -322,14 +302,16 @@ if(STATIC)
dialogsprivateplugin
qmlfolderlistmodelplugin
qmlsettingsplugin
qtlabsplatformplugin
qmlxmllistmodelplugin
qquicklayoutsplugin
modelsplugin
)
if(WITH_SCANNER)
list(APPEND QT5_EXTRA_LIBRARIES_LIST
declarative_multimedia
Qt5MultimediaQuick_p
Qt5MultimediaQuick
)
endif()
@@ -476,7 +458,7 @@ if (NOT OPENBSD AND NOT (WIN32 AND (CMAKE_C_COMPILER_ID STREQUAL "GNU" AND CMAKE
add_c_flag_if_supported(-fcf-protection=full C_SECURITY_FLAGS)
add_cxx_flag_if_supported(-fcf-protection=full CXX_SECURITY_FLAGS)
endif()
if (NOT WIN32 AND NOT OPENBSD)
if (NOT WIN32 AND NOT OPENBSD AND NOT "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
add_c_flag_if_supported(-fstack-clash-protection C_SECURITY_FLAGS)
add_cxx_flag_if_supported(-fstack-clash-protection CXX_SECURITY_FLAGS)
endif()
@@ -539,26 +521,5 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11 ${C_SECURITY_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 ${CXX_SECURITY_FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LD_SECURITY_FLAGS} ${STATIC_FLAGS}")
if (HIDAPI_FOUND OR LibUSB_COMPILE_TEST_PASSED)
if (APPLE)
if(DEPENDS)
list(APPEND EXTRA_LIBRARIES "-framework Foundation -framework IOKit")
else()
find_library(COREFOUNDATION CoreFoundation)
find_library(IOKIT IOKit)
list(APPEND EXTRA_LIBRARIES ${IOKIT})
list(APPEND EXTRA_LIBRARIES ${COREFOUNDATION})
endif()
endif()
if (WIN32)
find_library(VERSION_LIBRARY version PATHS /usr/x86_64-w64-mingw32/lib)
if(VERSION_LIBRARY STREQUAL "VERSION_LIBRARY-NOTFOUND")
set(VERSION_LIBRARY Version)
endif()
list(APPEND EXTRA_LIBRARIES setupapi ${VERSION_LIBRARY})
endif()
endif()
add_subdirectory(external)
add_subdirectory(translations)
add_subdirectory(src)

View File

@@ -1,4 +1,4 @@
FROM debian:unstable
FROM debian:stretch
ARG THREADS=1
ARG ANDROID_NDK_REVISION=21d
@@ -22,8 +22,9 @@ 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 cmake file gettext git libc6 libncurses5 \
libstdc++6 libtinfo5 libtool libz1 openjdk-8-jdk-headless openjdk-8-jre-headless pkg-config python3 unzip wget
&& 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 \
@@ -77,11 +78,11 @@ RUN git clone git://code.qt.io/qt/qt5.git -b ${QT_VERSION} --depth 1 \
&& 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)
&& 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
@@ -97,7 +98,7 @@ RUN wget -q http://ftp.gnu.org/pub/gnu/libiconv/libiconv-${ICONV_VERSION}.tar.gz
ARG BOOST_VERSION=1_74_0
ARG BOOST_VERSION_DOT=1.74.0
ARG BOOST_HASH=83bfc1507731a0906e387fc28b7ef5417d591429e51e788417fe9ff025e116b1
RUN wget -q https://dl.bintray.com/boostorg/release/${BOOST_VERSION_DOT}/source/boost_${BOOST_VERSION}.tar.bz2 \
RUN wget -q https://downloads.sourceforge.net/project/boost/boost/${BOOST_VERSION_DOT}/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 \
@@ -175,6 +176,14 @@ RUN cd tools \
&& 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 \

View File

@@ -8,10 +8,12 @@ ENV CPPFLAGS="-fPIC"
ENV CXXFLAGS="-fPIC"
ENV SOURCE_DATE_EPOCH=1397818193
RUN apt update
RUN apt update && \
apt install -y automake autopoint bison gettext git gperf libgl1-mesa-dev libglib2.0-dev \
libpng12-dev libpthread-stubs0-dev libsodium-dev libtool-bin libudev-dev libusb-1.0-0-dev mesa-common-dev \
pkg-config python wget xutils-dev
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 && \
RUN git clone -b xorgproto-2020.1 --depth 1 https://gitlab.freedesktop.org/xorg/proto/xorgproto && \
cd xorgproto && \
git reset --hard c62e8203402cafafa5ba0357b6d1c019156c9f36 && \
./autogen.sh && \
@@ -27,8 +29,7 @@ RUN git clone -b 1.12 --depth 1 https://gitlab.freedesktop.org/xorg/proto/xcbpro
make -j$THREADS install && \
rm -rf $(pwd)
RUN apt install -y libtool-bin && \
git clone -b libXau-1.0.9 --depth 1 https://gitlab.freedesktop.org/xorg/lib/libxau && \
RUN git clone -b libXau-1.0.9 --depth 1 https://gitlab.freedesktop.org/xorg/lib/libxau && \
cd libxau && \
git reset --hard d9443b2c57b512cfb250b35707378654d86c7dea && \
./autogen.sh --enable-shared --disable-static && \
@@ -36,8 +37,7 @@ RUN apt install -y libtool-bin && \
make -j$THREADS install && \
rm -rf $(pwd)
RUN apt install -y libpthread-stubs0-dev && \
git clone -b 1.12 --depth 1 https://gitlab.freedesktop.org/xorg/lib/libxcb && \
RUN git clone -b 1.12 --depth 1 https://gitlab.freedesktop.org/xorg/lib/libxcb && \
cd libxcb && \
git reset --hard d34785a34f28fa6a00f8ce00d87e3132ff0f6467 && \
./autogen.sh --enable-shared --disable-static && \
@@ -105,8 +105,7 @@ RUN git clone -b 0.4.1 --depth 1 https://gitlab.freedesktop.org/xorg/lib/libxcb-
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 && \
RUN 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 && \
@@ -140,8 +139,7 @@ RUN git clone -b R_2_2_9 --depth 1 https://github.com/libexpat/libexpat && \
make -j$THREADS install && \
rm -rf $(pwd)
RUN apt install -y autopoint gettext gperf libpng12-dev && \
git clone -b 2.13.92 --depth 1 https://gitlab.freedesktop.org/fontconfig/fontconfig && \
RUN git clone -b 2.13.92 --depth 1 https://gitlab.freedesktop.org/fontconfig/fontconfig && \
cd fontconfig && \
git reset --hard b1df1101a643ae16cdfa1d83b939de2497b1bf27 && \
./autogen.sh --disable-shared --enable-static --sysconfdir=/etc --localstatedir=/var && \
@@ -157,8 +155,7 @@ RUN git clone -b release-64-2 --depth 1 https://github.com/unicode-org/icu && \
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 && \
RUN wget https://downloads.sourceforge.net/project/boost/boost/1.73.0/boost_1_73_0.tar.gz && \
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 && \
@@ -177,8 +174,7 @@ RUN wget https://www.openssl.org/source/openssl-1.1.1g.tar.gz && \
make -j$THREADS install && \
rm -rf $(pwd)
RUN apt install -y libgl1-mesa-dev libglib2.0-dev mesa-common-dev && \
rm /usr/lib/x86_64-linux-gnu/libX11.a && \
RUN 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 && \
@@ -218,8 +214,7 @@ RUN apt install -y libgl1-mesa-dev libglib2.0-dev mesa-common-dev && \
cd ../../../.. && \
rm -rf $(pwd)
RUN apt install -y libudev-dev && \
git clone -b v1.0.23 --depth 1 https://github.com/libusb/libusb && \
RUN git clone -b v1.0.23 --depth 1 https://github.com/libusb/libusb && \
cd libusb && \
git reset --hard e782eeb2514266f6738e242cdcb18e3ae1ed06fa && \
./autogen.sh --disable-shared --enable-static && \
@@ -236,8 +231,7 @@ RUN git clone -b hidapi-0.9.0 --depth 1 https://github.com/libusb/hidapi && \
make -j$THREADS install && \
rm -rf $(pwd)
RUN apt install -y libsodium-dev && \
git clone -b v4.3.2 --depth 1 https://github.com/zeromq/libzmq && \
RUN git clone -b v4.3.2 --depth 1 https://github.com/zeromq/libzmq && \
cd libzmq && \
git reset --hard a84ffa12b2eb3569ced199660bac5ad128bff1f0 && \
./autogen.sh && \
@@ -280,5 +274,3 @@ RUN git clone -b v3.18.4 --depth 1 https://github.com/Kitware/CMake && \
make -j$THREADS && \
make -j$THREADS install && \
rm -rf $(pwd)
RUN apt install -y libusb-1.0-0-dev

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

@@ -2,8 +2,12 @@ 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
builddir := build
@@ -13,9 +17,11 @@ ifeq ($(USE_SINGLE_BUILDDIR), OFF)
builddir := $(builddir)/$(os)
topdir := $(topdir)/..
branch:=$(shell git branch | grep '\* ' | cut -f2- -d' '| sed -e 's|[:/\\ \(\)]|_|g')
builddir := $(builddir)/$(branch)
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
@@ -25,7 +31,7 @@ endif
default:
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) -DMANUAL_SUBMODULES=${MANUAL_SUBMODULES} .. && $(MAKE) VERBOSE=1
mkdir -p build && cd build && cmake -D DEV_MODE=$(or ${DEV_MODE},ON) -DMANUAL_SUBMODULES=${MANUAL_SUBMODULES} -D CMAKE_BUILD_TYPE=Debug .. && $(MAKE) VERBOSE=1
depends:
mkdir -p build/$(target)/release

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);
@@ -119,6 +116,12 @@ Rectangle {
transferView.sendTo(address, paymentId, description);
}
// open Transactions page with search term in search field
function searchInHistory(searchTerm){
root.state = "History";
historyView.searchInHistory(searchTerm);
}
states: [
State {
name: "History"
@@ -136,30 +139,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 +159,7 @@ Rectangle {
name: "Account"
PropertyChanges { target: root; currentView: accountView }
PropertyChanges { target: mainFlickable; contentHeight: accountView.accountHeight + 80 }
}
}
]
ColumnLayout {

View File

@@ -2,12 +2,29 @@
Copyright (c) 2014-2019, The Monero Project
## Table of Contents
* [Development resources](#development-resources)
* [Vulnerability response](#vulnerability-response)
* [Introduction](#introduction)
* [About this project](#about-this-project)
* [Supporting the project](#supporting-the-project)
* [License](#license)
* [Translations](#translations)
* [Installing the Monero GUI from a package](#installing-the-monero-gui-from-a-package)
* [Compiling the Monero GUI from source](#compiling-the-monero-gui-from-source)
+ [Building Reproducible Windows static binaries with Docker (any OS)](#building-reproducible-windows-static-binaries-with-docker-any-os)
+ [Building Reproducible Linux static binaries with Docker (any OS)](#building-reproducible-linux-static-binaries-with-docker-any-os)
+ [Building Android APK with Docker (any OS) *Experimental*](#building-android-apk-with-docker-any-os-experimental)
+ [Building on Linux](#building-on-linux)
+ [Building on OS X](#building-on-os-x)
+ [Building on Windows](#building-on-windows)
## Development resources
- Web: [getmonero.org](https://getmonero.org)
- Mail: [dev@getmonero.org](mailto:dev@getmonero.org)
- Github: [https://github.com/monero-project/monero-gui](https://github.com/monero-project/monero-gui)
- IRC: [#monero-dev on Freenode](irc://chat.freenode.net/#monero-dev)
- IRC: [#monero-gui on Libera](irc://irc.libera.chat/#monero-gui)
- Translation platform (Weblate): [translate.getmonero.org](https://translate.getmonero.org)
- UI Design: [Monero-GUI on Figma](https://www.figma.com/file/DplJ2DDQfIKiuRvolHX2hN/Monero-GUI)
@@ -72,7 +89,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 +97,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
@@ -109,7 +127,7 @@ Packaging for your favorite distribution would be a welcome contribution!
```
git clone --branch master --recursive https://github.com/monero-project/monero-gui.git
```
\* `master` - replace with the desired version tag (e.g. `v0.17.1.5`) to build the release binaries.
\* `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
@@ -179,7 +197,7 @@ Packaging for your favorite distribution would be a welcome contribution!
http://<your.local.ip>:8080/QtApp-debug.apk
```
### On Linux:
### Building on Linux
(Tested on Ubuntu 17.10 x64, Ubuntu 18.04 x64 and Gentoo x64)
@@ -207,7 +225,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-platform qml-module-qt-labs-folderlistmodel qttools5-dev-tools qml-module-qtquick-templates2 libqt5svg5-dev`
- For Gentoo
@@ -243,7 +261,7 @@ The following instructions will fetch Qt from your distribution's repositories i
The executable can be found in the build/release/bin folder.
### On OS X:
### Building on OS X
1. Install Xcode from AppStore
@@ -251,7 +269,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:
@@ -276,7 +294,7 @@ The executable can be found in the `build/release/bin` folder.
For building an application bundle see `DEPLOY.md`.
### On Windows:
### Building on Windows
The Monero GUI on Windows is 64 bits only; 32-bit Windows GUI builds are not officially supported anymore.

View File

@@ -17,11 +17,7 @@ if(APPLE OR (WIN32 AND NOT STATIC))
add_custom_command(TARGET deploy
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${_qt_svg_dylib} $<TARGET_FILE_DIR:monero-wallet-gui>/../PlugIns/imageformats/
COMMAND ${CMAKE_INSTALL_NAME_TOOL} -change "${CMAKE_PREFIX_PATH}/lib/QtGui.framework/Versions/5/QtGui" "@executable_path/../Frameworks/QtGui.fr amework/Versions/5/QtGui" $<TARGET_FILE_DIR:monero-wallet-gui>/../PlugIns/imageformats/libqsvg.dylib
COMMAND ${CMAKE_INSTALL_NAME_TOOL} -change "${CMAKE_PREFIX_PATH}/lib/QtWidgets.framework/Versions/5/QtWidgets" "@executable_path/../Frameworks/ QtGui.framework/Versions/5/QtGui" $<TARGET_FILE_DIR:monero-wallet-gui>/../PlugIns/imageformats/libqsvg.dylib
COMMAND ${CMAKE_INSTALL_NAME_TOOL} -change "${CMAKE_PREFIX_PATH}/lib/QtSvg.framework/Versions/5/QtSvg" "@executable_path/../Frameworks/QtGui.fr amework/Versions/5/QtGui" $<TARGET_FILE_DIR:monero-wallet-gui>/../PlugIns/imageformats/libqsvg.dylib
COMMAND ${CMAKE_INSTALL_NAME_TOOL} -change "${CMAKE_PREFIX_PATH}/lib/QtCore.framework/Versions/5/QtCore" "@executable_path/../Frameworks/QtGui. framework/Versions/5/QtGui" $<TARGET_FILE_DIR:monero-wallet-gui>/../PlugIns/imageformats/libqsvg.dylib
COMMENT "Copying libqsvg.dylib, running install_name_tool"
COMMENT "Copying libqsvg.dylib"
)
endif()
@@ -78,19 +74,19 @@ if(APPLE OR (WIN32 AND NOT STATIC))
)
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
list(APPEND WIN_DEPLOY_DLLS
libicudtd67.dll
libicuind67.dll
libicuiod67.dll
libicutud67.dll
libicuucd67.dll
libicudtd68.dll
libicuind68.dll
libicuiod68.dll
libicutud68.dll
libicuucd68.dll
)
else() # assume release
list(APPEND WIN_DEPLOY_DLLS
libicudt67.dll
libicuin67.dll
libicuio67.dll
libicutu67.dll
libicuuc67.dll
libicudt68.dll
libicuin68.dll
libicuio68.dll
libicutu68.dll
libicuuc68.dll
)
endif()
list(TRANSFORM WIN_DEPLOY_DLLS PREPEND "$ENV{MSYSTEM_PREFIX}/bin/")

View File

@@ -1,60 +0,0 @@
# - try to find HIDAPI library
# from http://www.signal11.us/oss/hidapi/
#
# Cache Variables: (probably not for direct use in your scripts)
# HIDAPI_INCLUDE_DIR
# HIDAPI_LIBRARY
#
# Non-cache variables you might use in your CMakeLists.txt:
# HIDAPI_FOUND
# HIDAPI_INCLUDE_DIRS
# HIDAPI_LIBRARIES
#
# Requires these CMake modules:
# FindPackageHandleStandardArgs (known included with CMake >=2.6.2)
#
# Original Author:
# 2009-2010 Ryan Pavlik <rpavlik@iastate.edu> <abiryan@ryand.net>
# http://academic.cleardefinition.com
# Iowa State University HCI Graduate Program/VRAC
#
# Copyright Iowa State University 2009-2010.
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
find_library(HIDAPI_LIBRARY
NAMES hidapi hidapi-libusb)
find_path(HIDAPI_INCLUDE_DIR
NAMES hidapi.h
PATH_SUFFIXES
hidapi)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(HIDAPI
DEFAULT_MSG
HIDAPI_LIBRARY
HIDAPI_INCLUDE_DIR)
if(HIDAPI_FOUND)
set(HIDAPI_LIBRARIES "${HIDAPI_LIBRARY}")
if((STATIC AND UNIX AND NOT APPLE) OR (DEPENDS AND CMAKE_SYSTEM_NAME STREQUAL "Linux"))
find_library(LIBUSB-1.0_LIBRARY usb-1.0)
find_library(LIBUDEV_LIBRARY udev)
if(LIBUSB-1.0_LIBRARY)
set(HIDAPI_LIBRARIES "${HIDAPI_LIBRARIES};${LIBUSB-1.0_LIBRARY}")
if(LIBUDEV_LIBRARY)
set(HIDAPI_LIBRARIES "${HIDAPI_LIBRARIES};${LIBUDEV_LIBRARY}")
else()
message(WARNING "libudev library not found, binaries may fail to link.")
endif()
else()
message(WARNING "libusb-1.0 library not found, binaries may fail to link.")
endif()
endif()
set(HIDAPI_INCLUDE_DIRS "${HIDAPI_INCLUDE_DIR}")
endif()
mark_as_advanced(HIDAPI_INCLUDE_DIR HIDAPI_LIBRARY)

View File

@@ -1,149 +0,0 @@
# - Find libusb for portable USB support
# This module will find libusb as published by
# http://libusb.sf.net and
# http://libusb-win32.sf.net
#
# It will use PkgConfig if present and supported, else search
# it on its own. If the LibUSB_ROOT_DIR environment variable
# is defined, it will be used as base path.
# The following standard variables get defined:
# LibUSB_FOUND: true if LibUSB was found
# LibUSB_HEADER_FILE: the location of the C header file
# LibUSB_INCLUDE_DIRS: the directory that contains the include file
# LibUSB_LIBRARIES: the library
# source: https://github.com/IntelRealSense/librealsense
include ( CheckLibraryExists )
include ( CheckIncludeFile )
find_package ( PkgConfig )
if ( PKG_CONFIG_FOUND )
pkg_check_modules ( PKGCONFIG_LIBUSB libusb-1.0 )
if ( NOT PKGCONFIG_LIBUSB_FOUND )
pkg_check_modules ( PKGCONFIG_LIBUSB libusb )
endif ( NOT PKGCONFIG_LIBUSB_FOUND )
endif ( PKG_CONFIG_FOUND )
if ( PKGCONFIG_LIBUSB_FOUND )
set ( LibUSB_INCLUDE_DIRS ${PKGCONFIG_LIBUSB_INCLUDE_DIRS} )
foreach ( i ${PKGCONFIG_LIBUSB_LIBRARIES} )
string ( REGEX MATCH "[^-]*" ibase "${i}" )
find_library ( ${ibase}_LIBRARY
NAMES ${i}
PATHS ${PKGCONFIG_LIBUSB_LIBRARY_DIRS}
)
if ( ${ibase}_LIBRARY )
list ( APPEND LibUSB_LIBRARIES ${${ibase}_LIBRARY} )
endif ( ${ibase}_LIBRARY )
mark_as_advanced ( ${ibase}_LIBRARY )
endforeach ( i )
else ( PKGCONFIG_LIBUSB_FOUND )
find_file ( LibUSB_HEADER_FILE
NAMES
libusb.h usb.h
PATHS
$ENV{ProgramFiles}/LibUSB-Win32
$ENV{LibUSB_ROOT_DIR}
PATH_SUFFIXES
include
libusb-1.0
include/libusb-1.0
)
mark_as_advanced ( LibUSB_HEADER_FILE )
get_filename_component ( LibUSB_INCLUDE_DIRS "${LibUSB_HEADER_FILE}" PATH )
if ( ${CMAKE_SYSTEM_NAME} STREQUAL "Windows" )
# LibUSB-Win32 binary distribution contains several libs.
# Use the lib that got compiled with the same compiler.
if ( MSVC )
if ( WIN32 )
set ( LibUSB_LIBRARY_PATH_SUFFIX lib/msvc )
else ( WIN32 )
set ( LibUSB_LIBRARY_PATH_SUFFIX lib/msvc_x64 )
endif ( WIN32 )
elseif ( BORLAND )
set ( LibUSB_LIBRARY_PATH_SUFFIX lib/bcc )
elseif ( CMAKE_COMPILER_IS_GNUCC )
set ( LibUSB_LIBRARY_PATH_SUFFIX lib/gcc )
endif ( MSVC )
endif ( ${CMAKE_SYSTEM_NAME} STREQUAL "Windows" )
find_library ( usb_LIBRARY
NAMES
usb-1.0 libusb usb
PATHS
$ENV{ProgramFiles}/LibUSB-Win32
$ENV{LibUSB_ROOT_DIR}
PATH_SUFFIXES
${LibUSB_LIBRARY_PATH_SUFFIX}
)
mark_as_advanced ( usb_LIBRARY )
if ( usb_LIBRARY )
set ( LibUSB_LIBRARIES ${usb_LIBRARY} )
endif ( usb_LIBRARY )
endif ( PKGCONFIG_LIBUSB_FOUND )
if ( LibUSB_INCLUDE_DIRS AND LibUSB_LIBRARIES )
set ( LibUSB_FOUND true )
endif ( LibUSB_INCLUDE_DIRS AND LibUSB_LIBRARIES )
if ( LibUSB_FOUND )
set ( CMAKE_REQUIRED_INCLUDES "${LibUSB_INCLUDE_DIRS}" )
check_include_file ( "${LibUSB_HEADER_FILE}" LibUSB_FOUND )
endif ( LibUSB_FOUND )
if ( LibUSB_FOUND )
check_library_exists ( "${LibUSB_LIBRARIES}" usb_open "" LibUSB_FOUND )
check_library_exists ( "${LibUSB_LIBRARIES}" libusb_get_device_list "" LibUSB_VERSION_1.0 )
check_library_exists ( "${LibUSB_LIBRARIES}" libusb_get_port_numbers "" LibUSB_VERSION_1.0.16 )
if((STATIC AND UNIX AND NOT APPLE) OR (DEPENDS AND CMAKE_SYSTEM_NAME STREQUAL "Linux"))
find_library(LIBUDEV_LIBRARY udev)
if(LIBUDEV_LIBRARY)
set(LibUSB_LIBRARIES "${LibUSB_LIBRARIES};${LIBUDEV_LIBRARY}")
else()
message(WARNING "libudev library not found, binaries may fail to link.")
endif()
endif()
# Library 1.0.16+ compilation test.
# The check_library_exists does not work well on Apple with shared libs.
if (APPLE OR LibUSB_VERSION_1.0.16 OR STATIC)
if (APPLE)
if(DEPENDS)
list(APPEND TEST_COMPILE_EXTRA_LIBRARIES "-framework Foundation -framework IOKit")
else()
find_library(COREFOUNDATION CoreFoundation)
find_library(IOKIT IOKit)
list(APPEND TEST_COMPILE_EXTRA_LIBRARIES ${IOKIT})
list(APPEND TEST_COMPILE_EXTRA_LIBRARIES ${COREFOUNDATION})
endif()
endif()
if (WIN32)
list(APPEND TEST_COMPILE_EXTRA_LIBRARIES setupapi)
endif()
list(APPEND TEST_COMPILE_EXTRA_LIBRARIES ${LibUSB_LIBRARIES})
try_compile(LibUSB_COMPILE_TEST_PASSED
${CMAKE_BINARY_DIR}
"${CMAKE_SOURCE_DIR}/cmake/test-libusb-version.c"
CMAKE_FLAGS
"-DINCLUDE_DIRECTORIES=${LibUSB_INCLUDE_DIRS}"
"-DLINK_DIRECTORIES=${LibUSB_LIBRARIES}"
LINK_LIBRARIES ${TEST_COMPILE_EXTRA_LIBRARIES}
OUTPUT_VARIABLE OUTPUT)
unset(TEST_COMPILE_EXTRA_LIBRARIES)
message(STATUS "LibUSB Compilation test: ${LibUSB_COMPILE_TEST_PASSED}")
endif()
endif ( LibUSB_FOUND )
if ( NOT LibUSB_FOUND )
if ( NOT LibUSB_FIND_QUIETLY )
message ( STATUS "LibUSB not found, try setting LibUSB_ROOT_DIR environment variable." )
endif ( NOT LibUSB_FIND_QUIETLY )
if ( LibUSB_FIND_REQUIRED )
message ( FATAL_ERROR "" )
endif ( LibUSB_FIND_REQUIRED )
endif ( NOT LibUSB_FOUND )

View File

@@ -1,19 +1,17 @@
import QtQuick 2.9
import QtQuick.Layouts 1.1
import FontAwesome 1.0
import "../components" as MoneroComponents
RowLayout {
id: advancedOptionsItem
property alias title: title.text
property alias tooltip: title.tooltip
property alias button1: button1
property alias button2: button2
property alias button3: button3
property alias helpTextLarge: helpTextLarge
property alias helpTextSmall: helpTextSmall
RowLayout {
id: titlecolumn
Layout.alignment: Qt.AlignTop | Qt.AlignLeft
@@ -24,24 +22,9 @@ RowLayout {
MoneroComponents.Label {
id: title
fontSize: 14
tooltipIconVisible: true
}
MoneroComponents.Label {
id: iconLabel
fontSize: 12
text: FontAwesome.questionCircle
fontFamily: FontAwesome.fontFamily
opacity: 0.3
MouseArea {
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: helpText.visible = !helpText.visible
onEntered: parent.opacity = 0.4
onExited: parent.opacity = 0.3
}
}
Rectangle {
id: separator
Layout.fillWidth: true
@@ -78,29 +61,5 @@ RowLayout {
visible: button3.text
}
}
ColumnLayout {
id: helpText
visible: false
Layout.alignment: Qt.AlignTop | Qt.AlignLeft
MoneroComponents.TextPlain {
id: helpTextLarge
visible: helpTextLarge.text
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 13
color: MoneroComponents.Style.defaultFontColor
}
MoneroComponents.TextPlain {
id: helpTextSmall
visible: helpTextSmall.text
Layout.leftMargin: 5
textFormat: Text.RichText
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 12
color: MoneroComponents.Style.defaultFontColor
}
}
}
}

View File

@@ -48,9 +48,17 @@ Item {
property int fontSize: 14
property alias fontColor: label.color
property bool iconOnTheLeft: true
property alias tooltipIconVisible: label.tooltipIconVisible
property alias tooltip: label.tooltip
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 +84,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;
@@ -115,7 +123,10 @@ Item {
MouseArea {
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onEntered: !label.tooltipIconVisible && label.tooltip ? label.tooltipPopup.open() : ""
onExited: !label.tooltipIconVisible && label.tooltip ? label.tooltipPopup.close() : ""
onClicked: {
toggle()
}

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
}
}

View File

@@ -32,6 +32,7 @@ import QtQuick.Controls 2.2 as QtQuickControls2
import QtQuick.Layouts 1.2
import QtGraphicalEffects 1.0
import QtQuick.Controls.Styles 1.2
import FontAwesome 1.0
import "." as MoneroComponents
import "effects/" as MoneroEffects
@@ -91,8 +92,8 @@ Item {
anchors.left: parent.left
anchors.right: parent.right
height: parent.height - 1
anchors.leftMargin: datePicker.expanded ? 1 : 0
anchors.rightMargin: datePicker.expanded ? 1 : 0
anchors.leftMargin: 0
anchors.rightMargin: 0
radius: 4
y: 1
color: datePicker.backgroundColor
@@ -221,21 +222,18 @@ Item {
Layout.fillWidth: true
color: "transparent"
Image {
MoneroEffects.ImageMask {
id: button
anchors.right: parent.right
anchors.rightMargin: 10
anchors.verticalCenter: parent.verticalCenter
source: "qrc:///images/whiteDropIndicator.png"
visible: false
}
ColorOverlay {
source: button
anchors.fill: button
image: "qrc:///images/whiteDropIndicator.png"
height: 8
width: 12
fontAwesomeFallbackIcon: FontAwesome.arrowDown
fontAwesomeFallbackSize: 14
color: MoneroComponents.Style.defaultFontColor
rotation: datePicker.expanded ? 180 : 0
opacity: 1
}
MouseArea {
@@ -252,12 +250,16 @@ Item {
id: popup
padding: 0
closePolicy: QtQuickControls2.Popup.CloseOnEscape | QtQuickControls2.Popup.CloseOnPressOutsideParent
onOpened: {
calendar.visibleMonth = currentDate.getMonth();
calendar.visibleYear = currentDate.getFullYear();
}
Rectangle {
id: calendarRect
width: head.width
x: head.x
y: head.y + head.height + 10
y: head.y + head.height - 2
color: MoneroComponents.Style.middlePanelBackgroundColor
border.width: 1
@@ -266,11 +268,16 @@ Item {
clip: true
Behavior on height {
NumberAnimation { duration: 100; easing.type: Easing.InQuad }
NumberAnimation { duration: 150; easing.type: Easing.InQuad }
}
MouseArea {
anchors.fill: parent
scrollGestureEnabled: false
onWheel: {
if (wheel.angleDelta.y > 0) return calendar.showPreviousMonth();
if (wheel.angleDelta.y < 0) return calendar.showNextMonth();
}
}
Rectangle {
@@ -305,11 +312,6 @@ Item {
id: dayRect
anchors.fill: parent
radius: parent.implicitHeight / 2
color: {
if(dayArea.pressed && styleData.visibleMonth)
return MoneroComponents.Style.blackTheme ? "#20FFFFFF" : "#10000000"
return "transparent";
}
}
MoneroComponents.TextPlain {
@@ -327,19 +329,32 @@ Item {
text: styleData.date.getDate()
themeTransition: false
color: {
if(!styleData.visibleMonth) return MoneroComponents.Style.lightGreyFontColor
if(dayArea.pressed) return MoneroComponents.Style.defaultFontColor
if(styleData.today) return MoneroComponents.Style.orange
return MoneroComponents.Style.defaultFontColor
if (currentDate.toDateString() === styleData.date.toDateString()) {
if (dayArea.containsMouse) {
dayRect.color = MoneroComponents.Style.buttonBackgroundColorHover;
} else {
dayRect.color = MoneroComponents.Style.buttonBackgroundColor;
}
} else {
if (dayArea.containsMouse) {
dayRect.color = MoneroComponents.Style.blackTheme ? "#20FFFFFF" : "#10000000"
} else {
dayRect.color = "transparent";
}
}
if(!styleData.valid) return "transparent"
if(styleData.date.toDateString() === (new Date()).toDateString()) return "#FFFF00"
if(!styleData.visibleMonth) return MoneroComponents.Style.lightGreyFontColor
if(dayArea.pressed) return MoneroComponents.Style.defaultFontColor
return MoneroComponents.Style.defaultFontColor
}
}
MouseArea {
id: dayArea
anchors.fill: parent
visible: styleData.valid
hoverEnabled: true
onEntered: dayRect.color = MoneroComponents.Style.blackTheme ? "#20FFFFFF" : "#10000000"
onExited: dayRect.color = "transparent"
cursorShape: Qt.PointingHandCursor
onClicked: {
if(styleData.visibleMonth) {
@@ -397,18 +412,15 @@ Item {
anchors.bottom: parent.bottom
width: height
Image {
MoneroEffects.ImageMask {
id: prevMonthIcon
anchors.centerIn: parent
source: "qrc:///images/prevMonth.png"
visible: false
}
ColorOverlay {
source: prevMonthIcon
anchors.fill: prevMonthIcon
image: "qrc:///images/prevMonth.png"
height: 8
width: 12
fontAwesomeFallbackIcon: FontAwesome.arrowLeft
fontAwesomeFallbackSize: 14
color: MoneroComponents.Style.defaultFontColor
opacity: 0.5
}
MouseArea {
@@ -426,19 +438,16 @@ Item {
anchors.bottom: parent.bottom
width: height
Image {
MoneroEffects.ImageMask {
id: nextMonthIcon
anchors.centerIn: parent
source: "qrc:///images/prevMonth.png"
visible: false
}
ColorOverlay {
source: nextMonthIcon
anchors.fill: nextMonthIcon
color: MoneroComponents.Style.defaultFontColor
opacity: 0.5
image: "qrc:///images/prevMonth.png"
height: 8
width: 12
rotation: 180
fontAwesomeFallbackIcon: FontAwesome.arrowLeft
fontAwesomeFallbackSize: 14
color: MoneroComponents.Style.defaultFontColor
}
MouseArea {

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

@@ -36,19 +36,28 @@ MoneroEffects.ImageMask {
color: MoneroComponents.Style.defaultFontColor
image: ""
property alias tooltip: tooltip.text
signal clicked(var mouse)
MoneroComponents.Tooltip {
id: tooltip
anchors.fill: parent
tooltipLeft: true
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onEntered: {
tooltip.text ? tooltip.tooltipPopup.open() : ""
button.width = button.width + 2
button.height = button.height + 2
}
onExited: {
tooltip.text ? tooltip.tooltipPopup.close() : ""
button.width = button.width - 2
button.height = button.height - 2
}

View File

@@ -43,10 +43,13 @@ Item {
property alias text: inlineText.text
property alias fontPixelSize: inlineText.font.pixelSize
property alias fontFamily: inlineText.font.family
property alias fontStyleName: inlineText.font.styleName
property bool isFontAwesomeIcon: fontFamily == FontAwesome.fontFamily || fontFamily == FontAwesome.fontFamilySolid
property alias buttonColor: rect.color
property alias tooltip: tooltip.text
property alias tooltipLeft: tooltip.tooltipLeft
property alias tooltipBottom: tooltip.tooltipBottom
Layout.rightMargin: isFontAwesomeIcon ? 0 : 4
height: isFontAwesomeIcon ? 30 : 24
width: isFontAwesomeIcon ? height : inlineText.width + 16
@@ -82,17 +85,27 @@ Item {
}
}
MoneroComponents.Tooltip {
id: tooltip
anchors.fill: parent
}
MouseArea {
id: buttonArea
cursorShape: rect.enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
hoverEnabled: true
anchors.fill: parent
onClicked: doClick()
onClicked: {
tooltip.text ? tooltip.tooltipPopup.close() : ""
doClick()
}
onEntered: {
tooltip.text ? tooltip.tooltipPopup.open() : ""
rect.color = buttonColor ? buttonColor : "#707070";
rect.opacity = 0.8;
}
onExited: {
tooltip.text ? tooltip.tooltipPopup.close() : ""
rect.opacity = 1.0;
rect.color = buttonColor ? buttonColor : "#808080";
}

View File

@@ -129,6 +129,7 @@ Item {
MoneroComponents.StandardButton {
id: cancelButton
primary: false
small: true
width: 120
fontSize: 14

View File

@@ -34,7 +34,10 @@ import "../components" as MoneroComponents
Item {
id: item
property alias text: label.text
property alias tooltip: label.tooltip
property alias tooltipIconVisible: label.tooltipIconVisible
property alias color: label.color
property alias labelMouseArea: labelMouseArea
property int textFormat: Text.PlainText
property string tipText: ""
property int fontSize: 16
@@ -70,9 +73,13 @@ Item {
onLinkActivated: item.linkActivated()
textFormat: parent.textFormat
MouseArea {
id: labelMouseArea
anchors.fill: parent
hoverEnabled: true
acceptedButtons: Qt.NoButton
cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor
cursorShape: parent.hoveredLink || (tooltip && !tooltipIconVisible) ? Qt.PointingHandCursor : Qt.ArrowCursor
onEntered: tooltip && !tooltipIconVisible ? parent.tooltipPopup.open() : undefined
onExited: tooltip && !tooltipIconVisible ? parent.tooltipPopup.close() : undefined
}
}
}

View File

@@ -37,17 +37,6 @@ import QtQuick.Controls 2.0
Drawer {
id: sideBar
// @TODO: Qt 5.10 introduces `opened` built-in for Drawer
property bool isOpened: false
onClosed: {
isOpened = false;
}
onOpened: {
isOpened = true;
}
width: 240
height: parent.height - (persistentSettings.customDecorations ? 50 : 0)
y: titleBar.height
@@ -64,26 +53,64 @@ Drawer {
color: "red"
ListView {
id: languagesListView
clip: true
Layout.fillHeight: true
Layout.fillWidth: true
boundsBehavior: Flickable.StopAtBounds
width: sideBar.width
height: sideBar.height
focus: true
model: langModel
Keys.onUpPressed: currentIndex !== 0 ? currentIndex = currentIndex - 1 : ""
Keys.onBacktabPressed: currentIndex !== 0 ? currentIndex = currentIndex - 1 : ""
Keys.onDownPressed: currentIndex + 1 !== count ? currentIndex = currentIndex + 1 : ""
Keys.onTabPressed: currentIndex + 1 !== count ? currentIndex = currentIndex + 1 : ""
delegate: Rectangle {
id: item
color: "transparent"
color: index == languagesListView.currentIndex ? MoneroComponents.Style.titleBarButtonHoverColor : "transparent"
width: sideBar.width
height: 32
Accessible.role: Accessible.ListItem
Accessible.name: display_name
Keys.onEnterPressed: setSelectedItemAsLanguage();
Keys.onReturnPressed: setSelectedItemAsLanguage();
Keys.onSpacePressed: setSelectedItemAsLanguage();
function setSelectedItemAsLanguage() {
var locale_spl = locale.split("_");
// reload active translations
console.log(locale_spl[0]);
translationManager.setLanguage(locale_spl[0]);
// set wizard language settings
persistentSettings.locale = locale;
persistentSettings.language = display_name;
persistentSettings.language_wallet = wallet_language;
appWindow.showStatusMessage(qsTr("Language changed."), 3);
appWindow.toggleLanguageView();
}
Rectangle {
id: selectedIndicator
anchors.left: parent.left
anchors.leftMargin: 0
height: parent.height
width: 2
color: index == languagesListView.currentIndex ? MoneroComponents.Style.buttonBackgroundColor : "transparent"
}
Rectangle {
id: flagRect
height: 24
width: 24
anchors.left: parent.left
anchors.left: selectedIndicator.right
anchors.leftMargin: 4
anchors.verticalCenter: parent.verticalCenter
color: "transparent"
@@ -96,8 +123,8 @@ Drawer {
MoneroComponents.TextPlain {
anchors.left: parent.left
anchors.leftMargin: 30
font.bold: true
anchors.leftMargin: 32
font.bold: languagesListView.currentIndex == index ? true : false
font.pixelSize: 14
color: MoneroComponents.Style.defaultFontColor
text: display_name
@@ -123,21 +150,7 @@ Drawer {
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: {
var locale_spl = locale.split("_");
// reload active translations
console.log(locale_spl[0]);
translationManager.setLanguage(locale_spl[0]);
// set wizard language settings
persistentSettings.locale = locale;
persistentSettings.language = display_name;
persistentSettings.language_wallet = wallet_language;
appWindow.showStatusMessage(qsTr("Language changed."), 3);
appWindow.toggleLanguageView();
}
onClicked: setSelectedItemAsLanguage();
hoverEnabled: true
onEntered: {
// item.color = "#26FFFFFF"
@@ -177,4 +190,12 @@ Drawer {
}
}
}
function selectCurrentLanguage() {
for (var i = 0; i < langModel.count; ++i) {
if (langModel.get(i).display_name === persistentSettings.language) {
languagesListView.currentIndex = i;
}
}
}
}

View File

@@ -33,14 +33,21 @@ import QtQuick.Layouts 1.1
import "../components" as MoneroComponents
Item {
ColumnLayout {
id: item
Layout.fillWidth: true
default property alias content: inlineButtons.children
property alias input: input
property alias text: input.text
property int inputPaddingLeft: 10
property int inputPaddingRight: 10
property int inputPaddingTop: 10
property int inputPaddingBottom: 10
property int inputRadius: 4
property bool password: false
property bool passwordHidden: true
property var passwordLinked: null
@@ -52,31 +59,40 @@ Item {
property int placeholderFontSize: 18
property string placeholderColor: MoneroComponents.Style.defaultFontColor
property real placeholderOpacity: 0.35
property real placeholderLeftMargin: {
if (placeholderCenter) {
return undefined;
} else {
return inputPaddingLeft;
}
}
property alias acceptableInput: input.acceptableInput
property alias validator: input.validator
property alias readOnly : input.readOnly
property alias cursorPosition: input.cursorPosition
property alias inlineIcon: inlineIcon.visible
property bool copyButton: false
property bool pasteButton: false
property alias copyButtonText: copyButtonId.text
property alias copyButtonEnabled: copyButtonId.enabled
property bool borderDisabled: false
property string borderColor: {
if(error && input.text !== ""){
if ((error && input.text !== "") || (errorWhenEmpty && input.text == "")) {
return MoneroComponents.Style.inputBorderColorInvalid;
} else if(input.activeFocus){
} else if (input.activeFocus) {
return MoneroComponents.Style.inputBorderColorActive;
} else {
return MoneroComponents.Style.inputBorderColorInActive;
}
}
property string fontFamily: MoneroComponents.Style.fontRegular.name
property int fontSize: 18
property bool fontBold: false
property alias fontColor: input.color
property bool error: false
property bool errorWhenEmpty: false
property alias labelText: inputLabel.text
property alias labelColor: inputLabel.color
property alias labelTextFormat: inputLabel.textFormat
@@ -87,15 +103,13 @@ Item {
property alias labelWrapMode: inputLabel.wrapMode
property alias labelHorizontalAlignment: inputLabel.horizontalAlignment
property bool showingHeader: inputLabel.text !== "" || copyButton
property int inputHeight: 42
property int inputHeight: 39
signal labelLinkActivated(); // input label, rich text <a> signal
signal editingFinished();
signal accepted();
signal textUpdated();
height: showingHeader ? (inputLabel.height + inputItem.height + 2) : 42
onActiveFocusChanged: activeFocus && input.forceActiveFocus()
onTextUpdated: {
// check to remove placeholder text when there is content
@@ -141,45 +155,100 @@ Item {
}
}
MoneroComponents.TextPlain {
id: inputLabel
anchors.top: parent.top
anchors.left: parent.left
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: labelFontSize
font.bold: labelFontBold
textFormat: Text.RichText
color: MoneroComponents.Style.defaultFontColor
onLinkActivated: item.labelLinkActivated()
spacing: 0
Rectangle {
id: inputLabelRect
color: "transparent"
Layout.fillWidth: true
height: (inputLabel.height + 10)
visible: showingHeader ? true : false
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.NoButton
cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor
}
}
MoneroComponents.TextPlain {
id: inputLabel
anchors.top: parent.top
anchors.left: parent.left
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: labelFontSize
font.bold: labelFontBold
textFormat: Text.RichText
color: MoneroComponents.Style.defaultFontColor
onLinkActivated: item.labelLinkActivated()
MoneroComponents.LabelButton {
id: copyButtonId
text: qsTr("Copy") + translationManager.emptyString
anchors.right: parent.right
onClicked: {
if (input.text.length > 0) {
console.log("Copied to clipboard");
clipboard.setText(input.text);
appWindow.showStatusMessage(qsTr("Copied to clipboard"), 3);
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.NoButton
cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor
}
}
RowLayout {
anchors.right: parent.right
spacing: 16
MoneroComponents.LabelButton {
id: copyButtonId
text: qsTr("Copy") + translationManager.emptyString
onClicked: {
if (input.text.length > 0) {
console.log("Copied to clipboard");
clipboard.setText(input.text);
appWindow.showStatusMessage(qsTr("Copied to clipboard"), 3);
}
}
visible: copyButton && input.text !== ""
}
MoneroComponents.LabelButton {
id: pasteButtonId
onClicked: {
input.clear();
input.paste();
}
text: qsTr("Paste") + translationManager.emptyString
visible: pasteButton
}
}
visible: copyButton && input.text !== ""
}
Item{
id: inputItem
height: inputHeight
anchors.top: showingHeader ? inputLabel.bottom : parent.top
anchors.topMargin: showingHeader ? 12 : 2
width: parent.width
clip: true
MoneroComponents.Input {
id: input
KeyNavigation.backtab: item.KeyNavigation.backtab
KeyNavigation.tab: item.KeyNavigation.tab
Layout.fillWidth: true
Layout.preferredHeight: inputHeight
leftPadding: item.inputPaddingLeft
rightPadding: (inlineButtons.width > 0 ? inlineButtons.width + inlineButtons.spacing : 0) + inputPaddingRight
topPadding: item.inputPaddingTop
bottomPadding: item.inputPaddingBottom
font.family: item.fontFamily
font.pixelSize: item.fontSize
font.bold: item.fontBold
onEditingFinished: item.editingFinished()
onAccepted: item.accepted();
onTextChanged: item.textUpdated()
echoMode: isPasswordHidden() ? TextInput.Password : TextInput.Normal
MoneroComponents.Label {
visible: password || passwordLinked
fontSize: 20
text: isPasswordHidden() ? FontAwesome.eye : FontAwesome.eyeSlash
opacity: eyeMouseArea.containsMouse ? 0.9 : 0.7
fontFamily: FontAwesome.fontFamily
anchors.right: parent.right
anchors.rightMargin: 15
anchors.verticalCenter: parent.verticalCenter
anchors.verticalCenterOffset: 1
MouseArea {
id: eyeMouseArea
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
hoverEnabled: true
onClicked: passwordToggle()
}
}
MoneroComponents.TextPlain {
id: placeholderLabel
@@ -187,13 +256,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
@@ -216,64 +279,15 @@ Item {
anchors.fill: parent
border.width: borderDisabled ? 0 : 1
border.color: borderColor
radius: 4
radius: item.inputRadius
}
Image {
id: inlineIcon
width: 26
height: 26
anchors.top: parent.top
anchors.topMargin: 8
anchors.left: parent.left
anchors.leftMargin: 12
source: "qrc:///images/moneroIcon-28x28.png"
visible: false
}
MoneroComponents.Input {
id: input
anchors.fill: parent
anchors.leftMargin: inlineIcon.visible ? 44 : 0
font.pixelSize: item.fontSize
font.bold: item.fontBold
KeyNavigation.tab: item.KeyNavigation.tab
onEditingFinished: item.editingFinished()
onAccepted: item.accepted();
onTextChanged: item.textUpdated()
rightPadding: inlineButtons.width + 14
topPadding: 10
bottomPadding: 10
echoMode: isPasswordHidden() ? TextInput.Password : TextInput.Normal
MoneroComponents.Label {
visible: password || passwordLinked
fontSize: 20
text: isPasswordHidden() ? FontAwesome.eye : FontAwesome.eyeSlash
opacity: eyeMouseArea.containsMouse ? 0.9 : 0.7
fontFamily: FontAwesome.fontFamily
anchors.right: parent.right
anchors.rightMargin: 15
anchors.verticalCenter: parent.verticalCenter
anchors.verticalCenterOffset: 1
MouseArea {
id: eyeMouseArea
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
hoverEnabled: true
onClicked: passwordToggle()
}
}
RowLayout {
id: inlineButtons
anchors.bottom: parent.bottom
anchors.top: parent.top
anchors.right: parent.right
anchors.margins: 4
spacing: 4
}
RowLayout {
id: inlineButtons
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
anchors.rightMargin: inputPaddingRight
spacing: 4
}
}
}

View File

@@ -44,7 +44,7 @@ ColumnLayout {
property alias placeholderText: placeholderLabel.text
property int inputPaddingLeft: 10
property alias inputPaddingRight: input.rightPadding
property int inputPaddingRight: 10
property int inputPaddingTop: 10
property int inputPaddingBottom: 10
property int inputRadius: 4
@@ -67,7 +67,8 @@ ColumnLayout {
}
}
property bool error: false
property alias error: input.error
property alias cursorPosition: input.cursorPosition
property string labelFontColor: MoneroComponents.Style.defaultFontColor
property bool labelFontBold: false
@@ -75,6 +76,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
@@ -90,6 +92,8 @@ ColumnLayout {
signal labelButtonClicked();
signal inputLabelLinkActivated();
signal editingFinished();
signal returnPressed();
signal enterPressed();
onActiveFocusChanged: activeFocus && input.forceActiveFocus()
@@ -158,22 +162,25 @@ 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: inlineButtons.width + 14
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
mouseSelection: item.mouseSelection
onEditingFinished: item.editingFinished()
error: item.error
Keys.onReturnPressed: item.returnPressed()
Keys.onEnterPressed: item.enterPressed()
MoneroComponents.TextPlain {
id: placeholderLabel
@@ -201,9 +208,9 @@ ColumnLayout {
RowLayout {
id: inlineButtons
anchors.top: parent.top
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
anchors.margins: 4
anchors.rightMargin: inputPaddingRight
spacing: 4
}
}

55
components/MenuBar.qml Normal file
View File

@@ -0,0 +1,55 @@
// Copyright (c) 2014-2019, The Monero Project
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import Qt.labs.platform 1.0 as PlatformLabs
import "." as MoneroComponents
PlatformLabs.MenuBar {
PlatformLabs.Menu {
title: qsTr("File")
PlatformLabs.MenuItem {
enabled: appWindow.viewState === "normal"
text: qsTr("Close Wallet")
onTriggered: appWindow.showWizard()
}
}
PlatformLabs.Menu {
title: qsTr("View")
PlatformLabs.MenuItem {
text: MoneroComponents.Style.blackTheme ? qsTr("Light Theme") : qsTr("Dark Theme")
onTriggered: {
MoneroComponents.Style.blackTheme = !MoneroComponents.Style.blackTheme;
}
}
PlatformLabs.MenuItem {
text: qsTr("Change Language")
onTriggered: appWindow.toggleLanguageView();
}
}
}

208
components/Navbar.qml Normal file
View File

@@ -0,0 +1,208 @@
// 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
Layout.fillWidth: true
color: items[index].active ? grid.borderColor : "transparent"
implicitHeight: children[0].implicitHeight
implicitWidth: children[0].implicitWidth
MoneroComponents.TextPlain {
anchors.centerIn: parent
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

@@ -80,7 +80,7 @@ Rectangle {
if(item.connected == Wallet.ConnectionStatus_Connected){
return 1
} else {
return 0.5
MoneroComponents.Style.blackTheme ? 0.5 : 0.3
}
}
@@ -92,7 +92,7 @@ Rectangle {
source: {
if(appWindow.isMining) {
return "qrc:///images/miningxmr.png"
} else if(item.connected == Wallet.ConnectionStatus_Connected) {
} else if(item.connected == Wallet.ConnectionStatus_Connected || !MoneroComponents.Style.blackTheme) {
return "qrc:///images/lightning.png"
} else {
return "qrc:///images/lightning-white.png"
@@ -126,8 +126,8 @@ Rectangle {
font.family: MoneroComponents.Style.fontMedium.name
font.bold: true
font.pixelSize: 13
color: MoneroComponents.Style.dimmedFontColor
opacity: MoneroComponents.Style.blackTheme ? 0.65 : 0.5
color: MoneroComponents.Style.blackTheme ? MoneroComponents.Style.dimmedFontColor : MoneroComponents.Style.defaultFontColor
opacity: MoneroComponents.Style.blackTheme ? 0.65 : 0.75
text: qsTr("Network status") + translationManager.emptyString
themeTransition: false
}
@@ -159,16 +159,18 @@ Rectangle {
}
}
Text {
MoneroComponents.TextPlain {
anchors.left: statusTextVal.right
anchors.leftMargin: 16
anchors.verticalCenter: parent.verticalCenter
color: refreshMouseArea.containsMouse ? MoneroComponents.Style.dimmedFontColor : MoneroComponents.Style.defaultFontColor
color: refreshMouseArea.containsMouse ? MoneroComponents.Style.defaultFontColor : MoneroComponents.Style.dimmedFontColor
font.family: FontAwesome.fontFamilySolid
font.pixelSize: 24
font.styleName: "Solid"
opacity: iconItem.opacity * (refreshMouseArea.visible ? 1 : 0.5)
opacity: 0.85
text: FontAwesome.random
themeTransition: false
tooltip: qsTr("Switch to another public remote node") + translationManager.emptyString;
visible: (
!appWindow.disconnected &&
!persistentSettings.useRemoteNode &&
@@ -181,6 +183,8 @@ Rectangle {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
visible: true
onEntered: parent.tooltipPopup.open()
onExited: parent.tooltipPopup.close()
onClicked: {
const callback = function(result) {
refreshMouseArea.visible = true;

View File

@@ -90,6 +90,9 @@ Rectangle {
if (!parsed.error) {
root.qrcode_decoded(parsed.address, parsed.payment_id, parsed.amount, parsed.tx_description, parsed.recipient_name, parsed.extra_parameters);
root.state = "Stopped";
} else if (walletManager.addressValid(data, appWindow.persistentSettings.nettype)) {
root.qrcode_decoded(data, "", "", "", "", null);
root.state = "Stopped";
} else {
onNotifyError(parsed.error);
}

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,24 +66,25 @@ GridLayout {
signal editingFinished()
signal textChanged()
onActiveFocusChanged: activeFocus && daemonAddr.forceActiveFocus()
function isValid() {
return daemonAddr.text.trim().length > 0 && daemonPort.acceptableInput
}
function getAddress() {
if (!isValid()) {
return "";
}
var addr = daemonAddr.text.trim();
var port = daemonPort.text.trim();
// validation
if(addr === "" || addr.length < 2) return "";
if(!Utils.isNumeric(port)) return "";
return addr + ":" + port;
}
LineEdit {
MoneroComponents.LineEdit {
id: daemonAddr
Layout.fillWidth: true
Layout.preferredWidth: root.width/3
placeholderText: qsTr("Remote Node Hostname / IP") + translationManager.emptyString
placeholderFontFamily: root.placeholderFontFamily
placeholderFontBold: root.placeholderFontBold
@@ -92,7 +92,6 @@ GridLayout {
placeholderColor: root.placeholderColor
placeholderOpacity: root.placeholderOpacity
labelFontSize: root.labelFontSize
borderColor: lineEditBorderColor
backgroundColor: lineEditBackgroundColor
fontColor: lineEditFontColor
fontBold: lineEditFontBold
@@ -105,9 +104,9 @@ GridLayout {
text: initialHostPort[1]
}
LineEdit {
MoneroComponents.LineEdit {
id: daemonPort
Layout.fillWidth: true
Layout.preferredWidth: root.width/3
placeholderText: qsTr("Port") + translationManager.emptyString
placeholderFontFamily: root.placeholderFontFamily
placeholderFontBold: root.placeholderFontBold
@@ -115,7 +114,6 @@ GridLayout {
placeholderColor: root.placeholderColor
placeholderOpacity: root.placeholderOpacity
labelFontSize: root.labelFontSize
borderColor: lineEditBorderColor
backgroundColor: lineEditBackgroundColor
fontColor: lineEditFontColor
fontBold: lineEditFontBold

View File

@@ -0,0 +1,163 @@
// 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.Layouts 1.1
import FontAwesome 1.0
import "." as MoneroComponents
import "effects/" as MoneroEffects
ColumnLayout {
id: remoteNodeList
spacing: 20
MoneroComponents.CheckBox {
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)
}
ColumnLayout {
spacing: 0
Repeater {
model: remoteNodesModel
Rectangle {
height: 30
Layout.fillWidth: true
color: itemMouseArea.containsMouse || trustedDaemonCheckMark.labelMouseArea.containsMouse || index === remoteNodesModel.selected ? MoneroComponents.Style.titleBarButtonHoverColor : "transparent"
Rectangle {
visible: index === remoteNodesModel.selected
Layout.fillHeight: true
anchors.top: parent.top
anchors.bottom: parent.bottom
color: "darkgrey"
width: 2
}
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"
property var trusted: remoteNodesModel.get(index).trusted
MoneroComponents.TextPlain {
id: addressText
width: parent.width - trustedDaemonCheckMark.width
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
elide: Text.ElideMiddle
}
MoneroComponents.Label {
id: trustedDaemonCheckMark
anchors.left: addressText.right
anchors.leftMargin: 6
anchors.verticalCenter: parent.verticalCenter
z: itemMouseArea.z + 1
fontSize: 16
fontFamily: FontAwesome.fontFamilySolid
fontColor: index === remoteNodesModel.selected ? MoneroComponents.Style.defaultFontColor : MoneroComponents.Style.dimmedFontColor
styleName: "Solid"
visible: trusted
text: FontAwesome.shieldAlt
tooltip: qsTr("Trusted daemon") + translationManager.emptyString
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
height: 30
spacing: 2
MoneroComponents.InlineButton {
buttonColor: "transparent"
fontFamily: FontAwesome.fontFamily
fontPixelSize: 18
text: FontAwesome.edit
tooltip: qsTr("Edit remote node") + translationManager.emptyString
tooltipLeft: true
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
tooltip: qsTr("Remove remote node") + translationManager.emptyString
tooltipLeft: true
onClicked: remoteNodesModel.removeSelectNextIfNeeded(index)
}
}
}
}
}
}

View File

@@ -16,11 +16,11 @@ ColumnLayout {
spacing: 0
Text {
MoneroComponents.TextPlain {
id: label
color: MoneroComponents.Style.defaultFontColor
font.pixelSize: 14
Layout.fillWidth: true
font.family: MoneroComponents.Style.fontRegular.name
}
QtQuickControls.Slider {

View File

@@ -52,6 +52,9 @@ Item {
else return 16;
}
property alias label: label
property alias tooltip: tooltip.text
property alias tooltipLeft: tooltip.tooltipLeft
property alias tooltipPopup: tooltip.tooltipPopup
signal clicked()
height: small ? 30 : 36
@@ -143,6 +146,7 @@ Item {
width: button.small ? 16 : 20
height: button.small ? 16 : 20
source: {
if (fontAwesomeIcon) return "";
if(button.rightIconInactive !== "" && !button.enabled) {
return button.rightIconInactive;
}
@@ -161,11 +165,18 @@ Item {
}
}
MoneroComponents.Tooltip {
id: tooltip
anchors.fill: parent
}
MouseArea {
id: buttonArea
anchors.fill: parent
hoverEnabled: true
onClicked: doClick()
onEntered: tooltip.text ? tooltip.tooltipPopup.open() : ""
onExited: tooltip.text ? tooltip.tooltipPopup.close() : ""
cursorShape: Qt.PointingHandCursor
}

View File

@@ -171,6 +171,7 @@ Rectangle {
MoneroComponents.StandardButton {
id: cancelButton
primary: false
text: qsTr("Cancel") + translationManager.emptyString
onClicked: {
root.close()

View File

@@ -29,12 +29,16 @@
import QtQuick 2.9
import QtQuick.Controls 2.2
import QtGraphicalEffects 1.0
import FontAwesome 1.0
import QtQuick.Layouts 1.1
import "../components" as MoneroComponents
import "../components/effects/" as MoneroEffects
Item {
ColumnLayout {
id: dropdown
Layout.fillWidth: true
property int itemTopMargin: 0
property alias dataModel: repeater.model
property string shadowPressedColor
@@ -44,46 +48,66 @@ Item {
property string textColor: MoneroComponents.Style.defaultFontColor
property alias currentIndex: columnid.currentIndex
readonly property alias expanded: popup.visible
property int dropdownHeight: 42
property int fontHeaderSize: 16
property alias labelText: dropdownLabel.text
property alias labelColor: dropdownLabel.color
property alias labelTextFormat: dropdownLabel.textFormat
property alias labelWrapMode: dropdownLabel.wrapMode
property alias labelHorizontalAlignment: dropdownLabel.horizontalAlignment
property bool showingHeader: dropdownLabel.text !== ""
property int labelFontSize: 14
property bool labelFontBold: false
property int dropdownHeight: 39
property int fontSize: 14
property int fontItemSize: 14
property string colorBorder: MoneroComponents.Style.inputBorderColorInActive
property string colorHeaderBackground: "transparent"
property bool headerBorder: true
property bool headerFontBold: false
height: dropdownHeight
signal changed();
onExpandedChanged: if(expanded) appWindow.currentItem = dropdown
Item {
id: head
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
anchors.topMargin: parent.itemTopMargin
height: dropdown.dropdownHeight
spacing: 0
Rectangle {
id: dropdownLabelRect
color: "transparent"
Layout.fillWidth: true
height: (dropdownLabel.height + 10)
visible: showingHeader ? true : false
Rectangle {
color: "transparent"
border.width: dropdown.headerBorder ? 1 : 0
border.color: dropdown.colorBorder
radius: 4
anchors.fill: parent
MoneroComponents.TextPlain {
id: dropdownLabel
anchors.top: parent.top
anchors.left: parent.left
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: labelFontSize
font.bold: labelFontBold
textFormat: Text.RichText
color: MoneroComponents.Style.defaultFontColor
}
}
Rectangle {
id: head
color: dropArea.containsMouse ? MoneroComponents.Style.titleBarButtonHoverColor : "transparent"
border.width: dropdown.headerBorder ? 1 : 0
border.color: dropdown.colorBorder
radius: 4
Layout.fillWidth: true
Layout.preferredHeight: dropdownHeight
MoneroComponents.TextPlain {
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin: 12
anchors.leftMargin: 10
anchors.right: dropIndicator.left
anchors.rightMargin: 12
width: droplist.width
elide: Text.ElideRight
font.family: MoneroComponents.Style.fontRegular.name
font.bold: dropdown.headerFontBold
font.pixelSize: dropdown.fontHeaderSize
font.pixelSize: dropdown.fontSize
color: dropdown.textColor
text: columnid.currentIndex < repeater.model.count ? qsTr(repeater.model.get(columnid.currentIndex).column1) + translationManager.emptyString : ""
}
@@ -96,19 +120,15 @@ Item {
anchors.rightMargin: 12
width: dropdownIcon.width
Image {
MoneroEffects.ImageMask {
id: dropdownIcon
anchors.centerIn: parent
source: "qrc:///images/whiteDropIndicator.png"
visible: false
}
ColorOverlay {
source: dropdownIcon
anchors.fill: dropdownIcon
image: "qrc:///images/whiteDropIndicator.png"
height: 8
width: 12
fontAwesomeFallbackIcon: FontAwesome.arrowDown
fontAwesomeFallbackSize: 14
color: MoneroComponents.Style.defaultFontColor
rotation: dropdown.expanded ? 180 : 0
opacity: 1
}
}
@@ -117,7 +137,7 @@ Item {
anchors.fill: parent
onClicked: dropdown.expanded ? popup.close() : popup.open()
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
cursorShape: Qt.ArrowCursor
}
}
@@ -128,7 +148,7 @@ Item {
Rectangle {
id: droplist
x: dropdown.x
anchors.left: parent.left
width: dropdown.width
y: head.y + head.height
clip: true
@@ -188,25 +208,11 @@ Item {
text: ""
}
Rectangle {
anchors.left: parent.left
anchors.top: parent.top
width: 3; height: 3
color: parent.color
}
Rectangle {
anchors.right: parent.right
anchors.top: parent.top
width: 3; height: 3
color: parent.color
}
MouseArea {
id: itemArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
cursorShape: Qt.ArrowCursor
onClicked: {
popup.close()

View File

@@ -132,7 +132,7 @@ Rectangle {
fontSize: 16
}
// open folder / done buttons
// view progress / open folder / done buttons
RowLayout {
id: buttons
spacing: 70
@@ -140,6 +140,20 @@ Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 50
MoneroComponents.StandardButton {
id: viewProgressButton
visible: !appWindow.viewOnly
text: qsTr("View progress") + translationManager.emptyString;
width: 200
primary: false
KeyNavigation.tab: doneButton
onClicked: {
doSearchInHistory(root.transactionID);
root.close()
root.rejected()
}
}
MoneroComponents.StandardButton {
id: openFolderButton
visible: appWindow.viewOnly
@@ -156,7 +170,7 @@ Rectangle {
text: qsTr("Done") + translationManager.emptyString;
width: 200
focus: root.visible
KeyNavigation.tab: openFolderButton
KeyNavigation.tab: appWindow.viewOnly ? openFolderButton : viewProgressButton
onClicked: {
root.close()
root.accepted()

View File

@@ -12,6 +12,10 @@ Text {
property bool themeTransition: true
property string themeTransitionBlackColor: ""
property string themeTransitionWhiteColor: ""
property alias tooltip: tooltip.text
property alias tooltipLeft: tooltip.tooltipLeft
property alias tooltipIconVisible: tooltip.tooltipIconVisible
property alias tooltipPopup: tooltip.tooltipPopup
font.family: MoneroComponents.Style.fontMedium.name
font.bold: false
font.pixelSize: 14
@@ -25,4 +29,10 @@ Text {
blackColor: root.themeTransitionBlackColor !== "" ? root.themeTransitionBlackColor : MoneroComponents.Style._b_defaultFontColor
whiteColor: root.themeTransitionWhiteColor !== "" ? root.themeTransitionWhiteColor : MoneroComponents.Style._w_defaultFontColor
}
MoneroComponents.Tooltip {
id: tooltip
anchors.top: parent.top
anchors.left: tooltipIconVisible ? parent.right : parent.left
}
}

View File

@@ -110,12 +110,24 @@ Rectangle {
opacity: 0.75
}
MoneroComponents.Tooltip {
id: btnCloseWalletTooltip
anchors.fill: parent
text: qsTr("Close this wallet and return to main menu") + translationManager.emptyString
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onEntered: parent.color = MoneroComponents.Style.titleBarButtonHoverColor
onExited: parent.color = "transparent"
onEntered: {
parent.color = MoneroComponents.Style.titleBarButtonHoverColor
btnCloseWalletTooltip.tooltipPopup.open()
}
onExited: {
parent.color = "transparent"
btnCloseWalletTooltip.tooltipPopup.close()
}
onClicked: root.closeWalletClicked(leftPanel.visible)
}
}
@@ -138,12 +150,24 @@ Rectangle {
opacity: 0.75
}
MoneroComponents.Tooltip {
id: btnLanguageToggleTooltip
anchors.fill: parent
text: qsTr("Change language") + translationManager.emptyString
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onEntered: parent.color = MoneroComponents.Style.titleBarButtonHoverColor
onExited: parent.color = "transparent"
onEntered: {
parent.color = MoneroComponents.Style.titleBarButtonHoverColor
btnLanguageToggleTooltip.tooltipPopup.open()
}
onExited: {
parent.color = "transparent"
btnLanguageToggleTooltip.tooltipPopup.close()
}
onClicked: root.languageClicked()
}
}
@@ -165,15 +189,26 @@ Rectangle {
opacity: 0.75
}
MoneroComponents.Tooltip {
id: btnSwitchThemeTooltip
anchors.fill: parent
text: MoneroComponents.Style.blackTheme ? qsTr("Switch to light theme") : qsTr("Switch to dark theme") + translationManager.emptyString
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onEntered: parent.color = MoneroComponents.Style.titleBarButtonHoverColor
onExited: parent.color = "transparent"
onEntered: {
parent.color = MoneroComponents.Style.titleBarButtonHoverColor
btnSwitchThemeTooltip.tooltipPopup.open()
}
onExited: {
parent.color = "transparent"
btnSwitchThemeTooltip.tooltipPopup.close()
}
onClicked: {
MoneroComponents.Style.blackTheme = !MoneroComponents.Style.blackTheme;
persistentSettings.blackTheme = MoneroComponents.Style.blackTheme;
}
}
}
@@ -347,6 +382,7 @@ Rectangle {
anchors.fill: parent
propagateComposedEvents: true
onPressed: previousPosition = globalCursor.getPosition()
onDoubleClicked: root.maximizeClicked()
onPositionChanged: {
if (pressedButtons == Qt.LeftButton) {
var pos = globalCursor.getPosition()

111
components/Tooltip.qml Normal file
View File

@@ -0,0 +1,111 @@
// 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 FontAwesome 1.0
import "." as MoneroComponents
Rectangle {
property alias text: tooltip.text
property alias tooltipPopup: popup
property bool tooltipIconVisible: false
property bool tooltipLeft: false
property bool tooltipBottom: tooltipIconVisible ? false : true
color: "transparent"
height: tooltipIconVisible ? icon.height : parent.height
width: tooltipIconVisible ? icon.width : parent.width
visible: text != ""
Text {
id: icon
visible: tooltipIconVisible
color: MoneroComponents.Style.orange
font.family: FontAwesome.fontFamily
font.pixelSize: 10
font.styleName: "Regular"
leftPadding: 5
rightPadding: 5
text: FontAwesome.questionCircle
opacity: mouseArea.containsMouse ? 0.7 : 1
MouseArea {
id: mouseArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.WhatsThisCursor
onEntered: popup.open()
onExited: popup.close()
}
}
ToolTip {
id: popup
height: tooltip.height + 20
background: Rectangle {
border.color: MoneroComponents.Style.buttonInlineBackgroundColor
border.width: 1
color: MoneroComponents.Style.titleBarBackgroundGradientStart
radius: 4
}
closePolicy: Popup.NoAutoClose
padding: 10
x: tooltipLeft
? (tooltipIconVisible ? icon.x - icon.width : parent.x - tooltip.width - 20 + parent.width/2)
: (tooltipIconVisible ? icon.x + icon.width : parent.x + parent.width/2)
y: tooltipBottom
? (tooltipIconVisible ? icon.y + height : parent.y + parent.height + 2)
: (tooltipIconVisible ? icon.y - height : parent.y - tooltip.height - 20)
enter: Transition {
NumberAnimation { property: "opacity"; from: 0.0; to: 1.0; duration: 150 }
}
exit: Transition {
NumberAnimation { property: "opacity"; from: 1.0; to: 0.0; duration: 150 }
}
delay: 200
RowLayout {
Layout.maximumWidth: 350
Text {
id: tooltip
width: contentWidth
color: MoneroComponents.Style.defaultFontColor
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 12
textFormat: Text.RichText
wrapMode: Text.WordWrap
}
}
}
}

View File

@@ -27,7 +27,8 @@
// 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 1.4 as QtQuickControls1
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.1
import "../components" as MoneroComponents
@@ -35,11 +36,14 @@ 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: 580
height: 400
width: 590
height: layout.height + layout.anchors.margins * 2
color: MoneroComponents.Style.blackTheme ? "black" : "white"
visible: false
radius: 10
@@ -53,8 +57,8 @@ Rectangle {
}
KeyNavigation.tab: confirmButton
property var recipients: []
property var transactionAmount: ""
property var transactionAddress: ""
property var transactionDescription: ""
property var transactionFee: ""
property var transactionPriority: ""
@@ -127,8 +131,8 @@ Rectangle {
}
function clearFields() {
root.recipients = [];
root.transactionAmount = "";
root.transactionAddress = "";
root.transactionDescription = "";
root.transactionFee = "";
root.transactionPriority = "";
@@ -137,13 +141,16 @@ Rectangle {
function showFiatConversion(valueXMR) {
const fiatFee = fiatApiConvertToFiat(valueXMR);
return "%1 %2".arg(fiatFee < 0.01 ? "<0.01" : "~" + fiatFee).arg(fiatApiCurrencySymbol());
return "%1 %2".arg(fiatFee < 0.01 ? "&lt;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
anchors.fill: parent
anchors.margins: 25
RowLayout {
Layout.topMargin: 10
@@ -181,11 +188,11 @@ Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 71
BusyIndicator {
id: txAmountBusyIndicator
Layout.fillWidth: true
Layout.alignment : Qt.AlignTop | Qt.AlignLeft
running: root.transactionAmount == "(all)"
QtQuickControls1.BusyIndicator {
id: txAmountBusyIndicator
Layout.fillHeight: true
Layout.fillWidth: true
running: root.transactionAmount == "(all)"
}
Text {
@@ -220,16 +227,10 @@ Rectangle {
columnSpacing: 15
rowSpacing: 16
ColumnLayout {
Layout.fillWidth: true
Layout.alignment : Qt.AlignTop | Qt.AlignLeft
Text {
Layout.fillWidth: true
color: MoneroComponents.Style.dimmedFontColor
text: qsTr("From") + ":" + translationManager.emptyString
font.pixelSize: 15
}
Text {
color: MoneroComponents.Style.dimmedFontColor
text: qsTr("From") + ":" + translationManager.emptyString
font.pixelSize: 15
}
ColumnLayout {
@@ -266,57 +267,70 @@ Rectangle {
}
}
ColumnLayout {
Layout.fillWidth: true
Layout.alignment : Qt.AlignTop | Qt.AlignLeft
Text {
Layout.fillWidth: true
font.pixelSize: 15
color: MoneroComponents.Style.dimmedFontColor
text: qsTr("To") + ":" + translationManager.emptyString
}
Text {
font.pixelSize: 15
color: MoneroComponents.Style.dimmedFontColor
text: qsTr("To") + ":" + translationManager.emptyString
}
ColumnLayout {
Flickable {
id: flickable
property int linesInMultipleRecipientsMode: 7
Layout.fillWidth: true
spacing: 16
Layout.preferredHeight: recipients.length > 1
? linesInMultipleRecipientsMode * (recipientsArea.contentHeight / recipientsArea.lineCount)
: recipientsArea.contentHeight
boundsBehavior: isMac ? Flickable.DragAndOvershootBounds : Flickable.StopAtBounds
clip: true
Text {
Layout.fillWidth: true
font.pixelSize: 15
font.family: MoneroComponents.Style.fontRegular.name
textFormat: Text.RichText
wrapMode: Text.Wrap
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: {
if (root.transactionAddress) {
const addressBookName = currentWallet ? currentWallet.addressBook.getDescription(root.transactionAddress) : null;
var fulladdress = root.transactionAddress;
var spacedaddress = fulladdress.match(/.{1,4}/g);
var spacedaddress = spacedaddress.join(' ');
if (!addressBookName) {
return qsTr("Monero address") + "<br>" + spacedaddress + translationManager.emptyString;
} else {
return FontAwesome.addressBook + " " + addressBookName + "<br>" + spacedaddress;
return recipients.map(function (recipient, index) {
var addressBookName = null;
if (currentWallet) {
addressBookName = currentWallet.addressBook.getDescription(recipient.address);
}
} else {
return "";
}
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
}
}
ColumnLayout {
Layout.fillWidth: true
Layout.alignment : Qt.AlignTop | Qt.AlignLeft
Text {
Layout.fillWidth: true
color: MoneroComponents.Style.dimmedFontColor
text: qsTr("Fee") + ":" + translationManager.emptyString
font.pixelSize: 15
}
Text {
color: MoneroComponents.Style.dimmedFontColor
text: qsTr("Fee") + ":" + translationManager.emptyString
font.pixelSize: 15
}
RowLayout {
@@ -364,7 +378,7 @@ Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 50
BusyIndicator {
QtQuickControls1.BusyIndicator {
visible: !bottomTextAnimation.running
running: !bottomTextAnimation.running
scale: .5

View File

@@ -4,4 +4,5 @@ add_library(quirc STATIC
quirc/lib/quirc.c
quirc/lib/version_db.c
)
set_target_properties(quirc PROPERTIES POSITION_INDEPENDENT_CODE ON)
target_include_directories(quirc PUBLIC quirc/lib)

View File

@@ -3,811 +3,71 @@ import QtQuick 2.9
Object {
//Font Awesome version 5.15.3
FontLoader {
id: regular
source: "./fa-regular-400.ttf"
source: "./fa-regular-400.otf"
}
FontLoader {
id: brands
source: "./fa-brands-400.ttf"
source: "./fa-brands-400.otf"
}
FontLoader {
id: solid
source: "./fa-solid-900.ttf"
source: "./fa-solid-900.otf"
}
property string fontFamily: regular.name
property string fontFamilyBrands: brands.name
property string fontFamilySolid: solid.name
// Icons
// Icons used in Monero GUI (Font Awesome version 5.15.3)
// To add new icons, check unicodes in Font Awesome Free's Cheatsheet:
// https://fontawesome.com/v5/cheatsheet/free/solid
// https://fontawesome.com/v5/cheatsheet/free/regular
// https://fontawesome.com/v5/cheatsheet/free/brands
property string addressBook : "\uf2b9"
property string addressBookO : "\uf2ba"
property string addressCard : "\uf2bb"
property string addressCardO : "\uf2bc"
property string adjust : "\uf042"
property string adn : "\uf170"
property string alignCenter : "\uf037"
property string alignJustify : "\uf039"
property string alignLeft : "\uf036"
property string alignRight : "\uf038"
property string amazon : "\uf270"
property string ambulance : "\uf0f9"
property string americanSignLanguageInterpreting : "\uf2a3"
property string anchor : "\uf13d"
property string android : "\uf17b"
property string angellist : "\uf209"
property string angleDoubleDown : "\uf103"
property string angleDoubleLeft : "\uf100"
property string angleDoubleRight : "\uf101"
property string angleDoubleUp : "\uf102"
property string angleDown : "\uf107"
property string angleLeft : "\uf104"
property string angleRight : "\uf105"
property string angleUp : "\uf106"
property string apple : "\uf179"
property string archive : "\uf187"
property string areaChart : "\uf1fe"
property string arrowCircleDown : "\uf0ab"
property string arrowCircleLeft : "\uf0a8"
property string arrowCircleODown : "\uf01a"
property string arrowCircleOLeft : "\uf190"
property string arrowCircleORight : "\uf18e"
property string arrowCircleOUp : "\uf01b"
property string arrowCircleRight : "\uf0a9"
property string arrowCircleUp : "\uf0aa"
property string arrowDown : "\uf063"
property string arrowLeft : "\uf060"
property string arrowRight : "\uf061"
property string arrowUp : "\uf062"
property string arrows : "\uf047"
property string arrowsAlt : "\uf0b2"
property string arrowsH : "\uf07e"
property string arrowsV : "\uf07d"
property string aslInterpreting : "\uf2a3"
property string assistiveListeningSystems : "\uf2a2"
property string asterisk : "\uf069"
property string at : "\uf1fa"
property string audioDescription : "\uf29e"
property string automobile : "\uf1b9"
property string backward : "\uf04a"
property string balanceScale : "\uf24e"
property string ban : "\uf05e"
property string bandcamp : "\uf2d5"
property string bank : "\uf19c"
property string barChart : "\uf080"
property string barChartO : "\uf080"
property string barcode : "\uf02a"
property string bars : "\uf0c9"
property string bath : "\uf2cd"
property string bathtub : "\uf2cd"
property string battery : "\uf240"
property string battery0 : "\uf244"
property string battery1 : "\uf243"
property string battery2 : "\uf242"
property string battery3 : "\uf241"
property string battery4 : "\uf240"
property string batteryEmpty : "\uf244"
property string batteryFull : "\uf240"
property string batteryHalf : "\uf242"
property string batteryQuarter : "\uf243"
property string batteryThreeQuarters : "\uf241"
property string bed : "\uf236"
property string beer : "\uf0fc"
property string behance : "\uf1b4"
property string behanceSquare : "\uf1b5"
property string bell : "\uf0f3"
property string bellO : "\uf0a2"
property string bellSlash : "\uf1f6"
property string bellSlashO : "\uf1f7"
property string bicycle : "\uf206"
property string binoculars : "\uf1e5"
property string birthdayCake : "\uf1fd"
property string bitbucket : "\uf171"
property string bitbucketSquare : "\uf172"
property string bitcoin : "\uf15a"
property string blackTie : "\uf27e"
property string blind : "\uf29d"
property string bluetooth : "\uf293"
property string bluetoothB : "\uf294"
property string bold : "\uf032"
property string bolt : "\uf0e7"
property string bomb : "\uf1e2"
property string book : "\uf02d"
property string bookmark : "\uf02e"
property string bookmarkO : "\uf097"
property string braille : "\uf2a1"
property string briefcase : "\uf0b1"
property string btc : "\uf15a"
property string bug : "\uf188"
property string building : "\uf1ad"
property string buildingO : "\uf0f7"
property string bullhorn : "\uf0a1"
property string bullseye : "\uf140"
property string bus : "\uf207"
property string buysellads : "\uf20d"
property string cab : "\uf1ba"
property string calculator : "\uf1ec"
property string calendar : "\uf073"
property string calendarCheckO : "\uf274"
property string calendarMinusO : "\uf272"
property string calendarO : "\uf133"
property string calendarPlusO : "\uf271"
property string calendarTimesO : "\uf273"
property string camera : "\uf030"
property string cameraRetro : "\uf083"
property string car : "\uf1b9"
property string caretDown : "\uf0d7"
property string caretLeft : "\uf0d9"
property string caretRight : "\uf0da"
property string caretSquareODown : "\uf150"
property string caretSquareOLeft : "\uf191"
property string caretSquareORight : "\uf152"
property string caretSquareOUp : "\uf151"
property string caretUp : "\uf0d8"
property string cartArrowDown : "\uf218"
property string cartPlus : "\uf217"
property string cashRegister: "\uf788"
property string cc : "\uf20a"
property string ccAmex : "\uf1f3"
property string ccDinersClub : "\uf24c"
property string ccDiscover : "\uf1f2"
property string ccJcb : "\uf24b"
property string ccMastercard : "\uf1f1"
property string ccPaypal : "\uf1f4"
property string ccStripe : "\uf1f5"
property string ccVisa : "\uf1f0"
property string certificate : "\uf0a3"
property string chain : "\uf0c1"
property string chainBroken : "\uf127"
property string check : "\uf00c"
property string checkCircle : "\uf058"
property string checkCircleO : "\uf05d"
property string checkSquare : "\uf14a"
property string checkSquareO : "\uf046"
property string chevronCircleDown : "\uf13a"
property string chevronCircleLeft : "\uf137"
property string chevronCircleRight : "\uf138"
property string chevronCircleUp : "\uf139"
property string chevronDown : "\uf078"
property string chevronLeft : "\uf053"
property string chevronRight : "\uf054"
property string chevronUp : "\uf077"
property string child : "\uf1ae"
property string chrome : "\uf268"
property string circle : "\uf111"
property string circleO : "\uf10c"
property string circleONotch : "\uf1ce"
property string circleThin : "\uf1db"
property string clipboard : "\uf0ea"
property string clockO : "\uf017"
property string clone : "\uf24d"
property string close : "\uf00d"
property string cloud : "\uf0c2"
property string cloudDownload : "\uf0ed"
property string cloudUpload : "\uf0ee"
property string cny : "\uf157"
property string code : "\uf121"
property string codeFork : "\uf126"
property string codepen : "\uf1cb"
property string codiepie : "\uf284"
property string coffee : "\uf0f4"
property string cog : "\uf013"
property string cogs : "\uf085"
property string columns : "\uf0db"
property string comment : "\uf075"
property string commentO : "\uf0e5"
property string commenting : "\uf27a"
property string commentingO : "\uf27b"
property string comments : "\uf086"
property string commentsO : "\uf0e6"
property string compass : "\uf14e"
property string compress : "\uf066"
property string connectdevelop : "\uf20e"
property string contao : "\uf26d"
property string copy : "\uf0c5"
property string copyright : "\uf1f9"
property string creativeCommons : "\uf25e"
property string creditCard : "\uf09d"
property string creditCardAlt : "\uf283"
property string crop : "\uf125"
property string crosshairs : "\uf05b"
property string css3 : "\uf13c"
property string cube : "\uf1b2"
property string cubes : "\uf1b3"
property string cut : "\uf0c4"
property string cutlery : "\uf0f5"
property string dashboard : "\uf0e4"
property string dashcube : "\uf210"
property string database : "\uf1c0"
property string deaf : "\uf2a4"
property string deafness : "\uf2a4"
property string dedent : "\uf03b"
property string delicious : "\uf1a5"
property string desktop : "\uf108"
property string deviantart : "\uf1bd"
property string diamond : "\uf219"
property string digg : "\uf1a6"
property string dollar : "\uf155"
property string dotCircleO : "\uf192"
property string download : "\uf019"
property string dribbble : "\uf17d"
property string driversLicense : "\uf2c2"
property string driversLicenseO : "\uf2c3"
property string dropbox : "\uf16b"
property string drupal : "\uf1a9"
property string edge : "\uf282"
property string edit : "\uf044"
property string eercast : "\uf2da"
property string eject : "\uf052"
property string ellipsisH : "\uf141"
property string ellipsisV : "\uf142"
property string empire : "\uf1d1"
property string envelope : "\uf0e0"
property string envelopeO : "\uf003"
property string envelopeOpen : "\uf2b6"
property string envelopeOpenO : "\uf2b7"
property string envelopeSquare : "\uf199"
property string envira : "\uf299"
property string eraser : "\uf12d"
property string etsy : "\uf2d7"
property string eur : "\uf153"
property string euro : "\uf153"
property string exchange : "\uf0ec"
property string exclamation : "\uf12a"
property string exclamationCircle : "\uf06a"
property string exclamationTriangle : "\uf071"
property string expand : "\uf065"
property string expeditedssl : "\uf23e"
property string externalLink : "\uf08e"
property string externalLinkSquare : "\uf14c"
property string eye : "\uf06e"
property string eyeSlash : "\uf070"
property string eyedropper : "\uf1fb"
property string fa : "\uf2b4"
property string facebook : "\uf09a"
property string facebookF : "\uf09a"
property string facebookOfficial : "\uf230"
property string facebookSquare : "\uf082"
property string fastBackward : "\uf049"
property string fastForward : "\uf050"
property string fax : "\uf1ac"
property string feed : "\uf09e"
property string female : "\uf182"
property string fighterJet : "\uf0fb"
property string file : "\uf15b"
property string fileArchiveO : "\uf1c6"
property string fileAudioO : "\uf1c7"
property string fileCodeO : "\uf1c9"
property string fileExcelO : "\uf1c3"
property string fileImageO : "\uf1c5"
property string fileMovieO : "\uf1c8"
property string fileO : "\uf016"
property string filePdfO : "\uf1c1"
property string filePhotoO : "\uf1c5"
property string filePictureO : "\uf1c5"
property string filePowerpointO : "\uf1c4"
property string fileSoundO : "\uf1c7"
property string fileText : "\uf15c"
property string fileTextO : "\uf0f6"
property string fileVideoO : "\uf1c8"
property string fileWordO : "\uf1c2"
property string fileZipO : "\uf1c6"
property string filesO : "\uf0c5"
property string film : "\uf008"
property string filter : "\uf0b0"
property string fire : "\uf06d"
property string fireExtinguisher : "\uf134"
property string firefox : "\uf269"
property string firstOrder : "\uf2b0"
property string flag : "\uf024"
property string flagCheckered : "\uf11e"
property string flagO : "\uf11d"
property string flash : "\uf0e7"
property string flask : "\uf0c3"
property string flickr : "\uf16e"
property string floppyO : "\uf0c7"
property string folder : "\uf07b"
property string folderO : "\uf114"
property string folderOpen : "\uf07c"
property string folderOpenO : "\uf115"
property string font : "\uf031"
property string fontAwesome : "\uf2b4"
property string fonticons : "\uf280"
property string fortAwesome : "\uf286"
property string forumbee : "\uf211"
property string forward : "\uf04e"
property string foursquare : "\uf180"
property string freeCodeCamp : "\uf2c5"
property string frownO : "\uf119"
property string futbolO : "\uf1e3"
property string gamepad : "\uf11b"
property string gavel : "\uf0e3"
property string gbp : "\uf154"
property string ge : "\uf1d1"
property string gear : "\uf013"
property string gears : "\uf085"
property string genderless : "\uf22d"
property string getPocket : "\uf265"
property string gg : "\uf260"
property string ggCircle : "\uf261"
property string gift : "\uf06b"
property string git : "\uf1d3"
property string gitSquare : "\uf1d2"
property string github : "\uf09b"
property string githubAlt : "\uf113"
property string githubSquare : "\uf092"
property string gitlab : "\uf296"
property string gittip : "\uf184"
property string glass : "\uf000"
property string glide : "\uf2a5"
property string glideG : "\uf2a6"
property string globe : "\uf0ac"
property string google : "\uf1a0"
property string googlePlus : "\uf0d5"
property string googlePlusCircle : "\uf2b3"
property string googlePlusOfficial : "\uf2b3"
property string googlePlusSquare : "\uf0d4"
property string googleWallet : "\uf1ee"
property string graduationCap : "\uf19d"
property string gratipay : "\uf184"
property string grav : "\uf2d6"
property string group : "\uf0c0"
property string hSquare : "\uf0fd"
property string hackerNews : "\uf1d4"
property string handGrabO : "\uf255"
property string handLizardO : "\uf258"
property string handODown : "\uf0a7"
property string handOLeft : "\uf0a5"
property string handORight : "\uf0a4"
property string handOUp : "\uf0a6"
property string handPaperO : "\uf256"
property string handPeaceO : "\uf25b"
property string handPointerO : "\uf25a"
property string handRockO : "\uf255"
property string handScissorsO : "\uf257"
property string handSpockO : "\uf259"
property string handStopO : "\uf256"
property string handshakeO : "\uf2b5"
property string hardOfHearing : "\uf2a4"
property string hashtag : "\uf292"
property string hddO : "\uf0a0"
property string header : "\uf1dc"
property string headphones : "\uf025"
property string heart : "\uf004"
property string heartO : "\uf08a"
property string heartbeat : "\uf21e"
property string history : "\uf1da"
property string home : "\uf015"
property string hospitalO : "\uf0f8"
property string hotel : "\uf236"
property string hourglass : "\uf254"
property string hourglass1 : "\uf251"
property string hourglass2 : "\uf252"
property string hourglass3 : "\uf253"
property string hourglassEnd : "\uf253"
property string hourglassHalf : "\uf252"
property string hourglassO : "\uf250"
property string hourglassStart : "\uf251"
property string houzz : "\uf27c"
property string html5 : "\uf13b"
property string iCursor : "\uf246"
property string idBadge : "\uf2c1"
property string idCard : "\uf2c2"
property string idCardO : "\uf2c3"
property string ils : "\uf20b"
property string image : "\uf03e"
property string imdb : "\uf2d8"
property string inbox : "\uf01c"
property string indent : "\uf03c"
property string industry : "\uf275"
property string houseUser : "\ue065"
property string infinity : "\uf534"
property string info : "\uf129"
property string infoCircle : "\uf05a"
property string inr : "\uf156"
property string instagram : "\uf16d"
property string institution : "\uf19c"
property string internetExplorer : "\uf26b"
property string intersex : "\uf224"
property string ioxhost : "\uf208"
property string italic : "\uf033"
property string joomla : "\uf1aa"
property string jpy : "\uf157"
property string jsfiddle : "\uf1cc"
property string key : "\uf084"
property string keyboardO : "\uf11c"
property string krw : "\uf159"
property string language : "\uf1ab"
property string laptop : "\uf109"
property string lastfm : "\uf202"
property string lastfmSquare : "\uf203"
property string leaf : "\uf06c"
property string leanpub : "\uf212"
property string legal : "\uf0e3"
property string lemonO : "\uf094"
property string levelDown : "\uf149"
property string levelUp : "\uf148"
property string lifeBouy : "\uf1cd"
property string lifeBuoy : "\uf1cd"
property string lifeRing : "\uf1cd"
property string lifeSaver : "\uf1cd"
property string lightbulbO : "\uf0eb"
property string lineChart : "\uf201"
property string link : "\uf0c1"
property string linkedin : "\uf0e1"
property string linkedinSquare : "\uf08c"
property string linode : "\uf2b8"
property string linux : "\uf17c"
property string list : "\uf03a"
property string listAlt : "\uf022"
property string listOl : "\uf0cb"
property string listUl : "\uf0ca"
property string locationArrow : "\uf124"
property string lock : "\uf023"
property string longArrowDown : "\uf175"
property string longArrowLeft : "\uf177"
property string longArrowRight : "\uf178"
property string longArrowUp : "\uf176"
property string lowVision : "\uf2a8"
property string magic : "\uf0d0"
property string magnet : "\uf076"
property string mailForward : "\uf064"
property string mailReply : "\uf112"
property string mailReplyAll : "\uf122"
property string male : "\uf183"
property string map : "\uf279"
property string mapMarker : "\uf041"
property string mapO : "\uf278"
property string mapPin : "\uf276"
property string mapSigns : "\uf277"
property string mars : "\uf222"
property string marsDouble : "\uf227"
property string marsStroke : "\uf229"
property string marsStrokeH : "\uf22b"
property string marsStrokeV : "\uf22a"
property string maxcdn : "\uf136"
property string meanpath : "\uf20c"
property string medium : "\uf23a"
property string medkit : "\uf0fa"
property string meetup : "\uf2e0"
property string mehO : "\uf11a"
property string mercury : "\uf223"
property string microchip : "\uf2db"
property string microphone : "\uf130"
property string microphoneSlash : "\uf131"
property string minus : "\uf068"
property string minusCircle : "\uf056"
property string minusSquare : "\uf146"
property string minusSquareO : "\uf147"
property string mixcloud : "\uf289"
property string mobile : "\uf10b"
property string mobilePhone : "\uf10b"
property string modx : "\uf285"
property string money : "\uf0d6"
property string moonO : "\uf186"
property string mortarBoard : "\uf19d"
property string motorcycle : "\uf21c"
property string mousePointer : "\uf245"
property string music : "\uf001"
property string navicon : "\uf0c9"
property string neuter : "\uf22c"
property string newspaperO : "\uf1ea"
property string objectGroup : "\uf247"
property string objectUngroup : "\uf248"
property string odnoklassniki : "\uf263"
property string odnoklassnikiSquare : "\uf264"
property string opencart : "\uf23d"
property string openid : "\uf19b"
property string opera : "\uf26a"
property string optinMonster : "\uf23c"
property string outdent : "\uf03b"
property string pagelines : "\uf18c"
property string paintBrush : "\uf1fc"
property string paperPlane : "\uf1d8"
property string paperPlaneO : "\uf1d9"
property string paperclip : "\uf0c6"
property string paragraph : "\uf1dd"
property string monero : "\uf3d0"
property string paste : "\uf0ea"
property string pause : "\uf04c"
property string pauseCircle : "\uf28b"
property string pauseCircleO : "\uf28c"
property string paw : "\uf1b0"
property string paypal : "\uf1ed"
property string pencil : "\uf040"
property string pencilSquare : "\uf14b"
property string pencilSquareO : "\uf044"
property string percent : "\uf295"
property string phone : "\uf095"
property string phoneSquare : "\uf098"
property string photo : "\uf03e"
property string pictureO : "\uf03e"
property string pieChart : "\uf200"
property string piedPiper : "\uf2ae"
property string piedPiperAlt : "\uf1a8"
property string piedPiperPp : "\uf1a7"
property string pinterest : "\uf0d2"
property string pinterestP : "\uf231"
property string pinterestSquare : "\uf0d3"
property string plane : "\uf072"
property string play : "\uf04b"
property string playCircle : "\uf144"
property string playCircleO : "\uf01d"
property string plug : "\uf1e6"
property string plus : "\uf067"
property string plusCircle : "\uf055"
property string plusSquare : "\uf0fe"
property string plusSquareO : "\uf196"
property string podcast : "\uf2ce"
property string powerOff : "\uf011"
property string printIcon : "\uf02f"
property string productHunt : "\uf288"
property string puzzlePiece : "\uf12e"
property string qq : "\uf1d6"
property string qrcode : "\uf029"
property string question : "\uf128"
property string questionCircle : "\uf059"
property string questionCircleO : "\uf29c"
property string quora : "\uf2c4"
property string quoteLeft : "\uf10d"
property string quoteRight : "\uf10e"
property string ra : "\uf1d0"
property string random : "\uf074"
property string ravelry : "\uf2d9"
property string rebel : "\uf1d0"
property string recycle : "\uf1b8"
property string reddit : "\uf1a1"
property string redditAlien : "\uf281"
property string redditSquare : "\uf1a2"
property string refresh : "\uf021"
property string registered : "\uf25d"
property string remove : "\uf00d"
property string renren : "\uf18b"
property string reorder : "\uf0c9"
property string repeat : "\uf01e"
property string reply : "\uf112"
property string replyAll : "\uf122"
property string resistance : "\uf1d0"
property string retweet : "\uf079"
property string rmb : "\uf157"
property string road : "\uf018"
property string rocket : "\uf135"
property string rotateLeft : "\uf0e2"
property string rotateRight : "\uf01e"
property string rouble : "\uf158"
property string rss : "\uf09e"
property string rssSquare : "\uf143"
property string rub : "\uf158"
property string ruble : "\uf158"
property string rupee : "\uf156"
property string s15 : "\uf2cd"
property string safari : "\uf267"
property string save : "\uf0c7"
property string scissors : "\uf0c4"
property string scribd : "\uf28a"
property string search : "\uf002"
property string searchMinus : "\uf010"
property string searchPlus : "\uf00e"
property string sellsy : "\uf213"
property string send : "\uf1d8"
property string sendO : "\uf1d9"
property string server : "\uf233"
property string share : "\uf064"
property string shareAlt : "\uf1e0"
property string shareAltSquare : "\uf1e1"
property string shareSquare : "\uf14d"
property string shareSquareO : "\uf045"
property string shekel : "\uf20b"
property string sheqel : "\uf20b"
property string shield : "\uf132"
property string ship : "\uf21a"
property string shirtsinbulk : "\uf214"
property string shoppingBag : "\uf290"
property string shoppingBasket : "\uf291"
property string shoppingCart : "\uf07a"
property string shower : "\uf2cc"
property string signIn : "\uf090"
property string signLanguage : "\uf2a7"
property string shieldAlt : "\uf3ed"
property string signOutAlt : "\uf2f5"
property string signOut : "\uf08b"
property string signal : "\uf012"
property string signing : "\uf2a7"
property string simplybuilt : "\uf215"
property string sitemap : "\uf0e8"
property string skyatlas : "\uf216"
property string skype : "\uf17e"
property string slack : "\uf198"
property string sliders : "\uf1de"
property string slideshare : "\uf1e7"
property string smileO : "\uf118"
property string snapchat : "\uf2ab"
property string snapchatGhost : "\uf2ac"
property string snapchatSquare : "\uf2ad"
property string snowflakeO : "\uf2dc"
property string soccerBallO : "\uf1e3"
property string sort : "\uf0dc"
property string sortAlphaAsc : "\uf15d"
property string sortAlphaDesc : "\uf15e"
property string sortAmountAsc : "\uf160"
property string sortAmountDesc : "\uf161"
property string sortAsc : "\uf0de"
property string sortDesc : "\uf0dd"
property string sortDown : "\uf0dd"
property string sortNumericAsc : "\uf162"
property string sortNumericDesc : "\uf163"
property string sortUp : "\uf0de"
property string soundcloud : "\uf1be"
property string spaceShuttle : "\uf197"
property string spinner : "\uf110"
property string spoon : "\uf1b1"
property string spotify : "\uf1bc"
property string square : "\uf0c8"
property string squareO : "\uf096"
property string stackExchange : "\uf18d"
property string stackOverflow : "\uf16c"
property string star : "\uf005"
property string starHalf : "\uf089"
property string starHalfEmpty : "\uf123"
property string starHalfFull : "\uf123"
property string starHalfO : "\uf123"
property string starO : "\uf006"
property string steam : "\uf1b6"
property string steamSquare : "\uf1b7"
property string stepBackward : "\uf048"
property string stepForward : "\uf051"
property string stethoscope : "\uf0f1"
property string stickyNote : "\uf249"
property string stickyNoteO : "\uf24a"
property string stop : "\uf04d"
property string stopCircle : "\uf28d"
property string stopCircleO : "\uf28e"
property string streetView : "\uf21d"
property string strikethrough : "\uf0cc"
property string stumbleupon : "\uf1a4"
property string stumbleuponCircle : "\uf1a3"
property string subscript : "\uf12c"
property string subway : "\uf239"
property string suitcase : "\uf0f2"
property string sunO : "\uf185"
property string superpowers : "\uf2dd"
property string superscript : "\uf12b"
property string support : "\uf1cd"
property string table : "\uf0ce"
property string tablet : "\uf10a"
property string tachometer : "\uf0e4"
property string tag : "\uf02b"
property string tags : "\uf02c"
property string tasks : "\uf0ae"
property string taxi : "\uf1ba"
property string telegram : "\uf2c6"
property string television : "\uf26c"
property string tencentWeibo : "\uf1d5"
property string terminal : "\uf120"
property string textHeight : "\uf034"
property string textWidth : "\uf035"
property string th : "\uf00a"
property string thLarge : "\uf009"
property string thList : "\uf00b"
property string themeisle : "\uf2b2"
property string thermometer : "\uf2c7"
property string thermometer0 : "\uf2cb"
property string thermometer1 : "\uf2ca"
property string thermometer2 : "\uf2c9"
property string thermometer3 : "\uf2c8"
property string thermometer4 : "\uf2c7"
property string thermometerEmpty : "\uf2cb"
property string thermometerFull : "\uf2c7"
property string thermometerHalf : "\uf2c9"
property string thermometerQuarter : "\uf2ca"
property string thermometerThreeQuarters : "\uf2c8"
property string thumbTack : "\uf08d"
property string thumbsDown : "\uf165"
property string thumbsODown : "\uf088"
property string thumbsOUp : "\uf087"
property string thumbsUp : "\uf164"
property string ticket : "\uf145"
property string times : "\uf00d"
property string timesCircle : "\uf057"
property string timesCircleO : "\uf05c"
property string timesRectangle : "\uf2d3"
property string timesRectangleO : "\uf2d4"
property string tint : "\uf043"
property string toggleDown : "\uf150"
property string toggleLeft : "\uf191"
property string toggleOff : "\uf204"
property string toggleOn : "\uf205"
property string toggleRight : "\uf152"
property string toggleUp : "\uf151"
property string trademark : "\uf25c"
property string train : "\uf238"
property string transgender : "\uf224"
property string transgenderAlt : "\uf225"
property string trash : "\uf1f8"
property string trashO : "\uf014"
property string tree : "\uf1bb"
property string trello : "\uf181"
property string tripadvisor : "\uf262"
property string trophy : "\uf091"
property string truck : "\uf0d1"
property string tryIcon : "\uf195"
property string tty : "\uf1e4"
property string tumblr : "\uf173"
property string tumblrSquare : "\uf174"
property string turkishLira : "\uf195"
property string tv : "\uf26c"
property string twitch : "\uf1e8"
property string twitter : "\uf099"
property string twitterSquare : "\uf081"
property string umbrella : "\uf0e9"
property string underline : "\uf0cd"
property string undo : "\uf0e2"
property string universalAccess : "\uf29a"
property string university : "\uf19c"
property string unlink : "\uf127"
property string unlock : "\uf09c"
property string unlockAlt : "\uf13e"
property string unsorted : "\uf0dc"
property string upload : "\uf093"
property string usb : "\uf287"
property string usd : "\uf155"
property string user : "\uf007"
property string userCircle : "\uf2bd"
property string userCircleO : "\uf2be"
property string userMd : "\uf0f0"
property string userO : "\uf2c0"
property string userPlus : "\uf234"
property string userSecret : "\uf21b"
property string userTimes : "\uf235"
property string users : "\uf0c0"
property string vcard : "\uf2bb"
property string vcardO : "\uf2bc"
property string venus : "\uf221"
property string venusDouble : "\uf226"
property string venusMars : "\uf228"
property string viacoin : "\uf237"
property string viadeo : "\uf2a9"
property string viadeoSquare : "\uf2aa"
property string videoCamera : "\uf03d"
property string vimeo : "\uf27d"
property string vimeoSquare : "\uf194"
property string vine : "\uf1ca"
property string vk : "\uf189"
property string volumeControlPhone : "\uf2a0"
property string volumeDown : "\uf027"
property string volumeOff : "\uf026"
property string volumeUp : "\uf028"
property string warning : "\uf071"
property string wechat : "\uf1d7"
property string weibo : "\uf18a"
property string weixin : "\uf1d7"
property string whatsapp : "\uf232"
property string wheelchair : "\uf193"
property string wheelchairAlt : "\uf29b"
property string wifi : "\uf1eb"
property string wikipediaW : "\uf266"
property string windowClose : "\uf2d3"
property string windowCloseO : "\uf2d4"
property string windowMaximize : "\uf2d0"
property string windowMinimize : "\uf2d1"
property string windowRestore : "\uf2d2"
property string windows : "\uf17a"
property string won : "\uf159"
property string wordpress : "\uf19a"
property string wpbeginner : "\uf297"
property string wpexplorer : "\uf2de"
property string wpforms : "\uf298"
property string wrench : "\uf0ad"
property string xing : "\uf168"
property string xingSquare : "\uf169"
property string yCombinator : "\uf23b"
property string yCombinatorSquare : "\uf1d4"
property string yahoo : "\uf19e"
property string yc : "\uf23b"
property string ycSquare : "\uf1d4"
property string yelp : "\uf1e9"
property string yen : "\uf157"
property string yoast : "\uf2b1"
property string youtube : "\uf167"
property string youtubePlay : "\uf16a"
property string youtubeSquare : "\uf166"
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
images/ledgerNanoS.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
images/ledgerNanoX.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
images/trezor.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

BIN
images/trezor@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 301 KiB

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

@@ -74,13 +74,29 @@ function isValidOpenAliasAddress(address) {
return true
}
function makeQRCodeString(addr, amount) {
function makeQRCodeString(addr, amount, txDescription, recipientName) {
var XMR_URI_SCHEME = "monero:"
var XMR_AMOUNT = "tx_amount"
var XMR_RECIPIENT_NAME = "recipient_name"
var XMR_TX_DESCRIPTION = "tx_description"
var qrCodeString =""
qrCodeString += (XMR_URI_SCHEME + addr)
if (amount !== undefined && amount !== ""){
qrCodeString += ("?" + XMR_AMOUNT + "=" + amount)
}
if (txDescription !== undefined && txDescription !== ""){
if (amount == ""){
qrCodeString += ("?" + XMR_TX_DESCRIPTION + "=" + encodeURI(txDescription))
} else {
qrCodeString += ("&" + XMR_TX_DESCRIPTION + "=" + encodeURI(txDescription))
}
}
if (recipientName !== undefined && recipientName !== ""){
if (amount == "" && txDescription == ""){
qrCodeString += ("?" + XMR_RECIPIENT_NAME + "=" + encodeURI(recipientName))
} else {
qrCodeString += ("&" + XMR_RECIPIENT_NAME + "=" + encodeURI(recipientName))
}
}
return qrCodeString
}

View File

@@ -113,5 +113,20 @@ function capitalize(s){
}
function removeTrailingZeros(value) {
return (value + '').replace(/\.?0*$/, '');
return (value + '').replace(/(\.\d*?)0+$/, '$1').replace(/\.$/, '');
}
function parseDateStringOrRestoreHeightAsInteger(value) {
// Parse date string or restore height as integer
var restoreHeight = 0;
if (value.indexOf('-') === 4 && value.length === 10) {
restoreHeight = Wizard.getApproximateBlockchainHeight(value, Utils.netTypeToString());
} else if (parseInt(value.substring(0, 4)) >= 2014 && parseInt(value.substring(0, 4)) <= 2025 && value.length === 8) {
// Correct date typed in a wrong format (20201225 instead of 2020-12-25)
var restoreHeightHyphenated = value.substring(0, 4) + "-" + value.substring(4, 6) + "-" + value.substring(6, 8);
restoreHeight = Wizard.getApproximateBlockchainHeight(restoreHeightHyphenated, Utils.netTypeToString());
} else {
restoreHeight = parseInt(value);
}
return restoreHeight;
}

View File

@@ -69,10 +69,7 @@ function walletPathExists(accountsDir, directory, filename, isIOS, walletManager
if(!filename || filename === "") return false;
if(!directory || directory === "") return false;
// make sure directory endswith path seperator
// @TODO: use .endswith() after Qt 5.8
var trailing_path_sep = directory[directory.length-1];
if(trailing_path_sep !== "/" && trailing_path_sep !== "\\")
if (!directory.endsWith("/") && !directory.endsWith("\\"))
directory += "/"
if(isIOS)
@@ -85,6 +82,17 @@ function walletPathExists(accountsDir, directory, filename, isIOS, walletManager
return false;
}
function unusedWalletName(directory, filename, walletManager) {
for (var i = 0; i < 100; i++) {
var walletName = filename + (i > 0 ? "_" + i : "");
if (!walletManager.walletExists(directory + "/" + walletName + "/" + walletName)) {
return walletName;
}
}
return filename;
}
function isAscii(str){
for (var i = 0; i < str.length; i++) {
if (str.charCodeAt(i) > 127)
@@ -158,7 +166,7 @@ function getApproximateBlockchainHeight(_date, _nettype){
if(_nettype == "Testnet"){
// testnet got some huge rollbacks, so the estimation is way off
var approximateTestnetRolledBackBlocks = 303967;
var approximateTestnetRolledBackBlocks = 342100;
if(approxBlockchainHeight > approximateTestnetRolledBackBlocks)
approxBlockchainHeight -= approximateTestnetRolledBackBlocks
}

360
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.2
import QtQuick 2.9
import QtQuick.Window 2.0
import QtQuick.Controls 1.1
@@ -53,11 +54,15 @@ import "version.js" as Version
ApplicationWindow {
id: appWindow
title: "Monero" + (walletName ? " - " + walletName : "")
title: "Monero" +
(persistentSettings.displayWalletNameInTitleBar && walletName
? " - " + walletName
: "")
minimumWidth: 750
minimumHeight: 450
property var currentItem
property var previousActiveFocusItem
property bool hideBalanceForced: false
property bool ctrlPressed: false
property alias persistentSettings : persistentSettings
@@ -69,7 +74,7 @@ ApplicationWindow {
property int restoreHeight:0
property bool daemonSynced: false
property bool walletSynced: false
property int maxWindowHeight: (isAndroid || isIOS)? screenHeight : (screenHeight < 900)? 720 : 800;
property int maxWindowHeight: (isAndroid || isIOS)? screenAvailableHeight : (screenAvailableHeight < 900)? 720 : 800;
property bool daemonRunning: !persistentSettings.useRemoteNode && !disconnected
property int daemonStartStopInProgress: 0
property alias toolTip: toolTip
@@ -88,16 +93,14 @@ ApplicationWindow {
readonly property string localDaemonAddress : "localhost:" + getDefaultDaemonRpcPort(persistentSettings.nettype)
property string currentDaemonAddress;
property int disconnectedEpoch: 0
property int estimatedBlockchainSize: 75 // GB
property int estimatedBlockchainSize: persistentSettings.pruneBlockchain ? 40 : 105 // GB
property alias viewState: rootItem.state
property string prevSplashText;
property bool splashDisplayedBeforeButtonRequest;
property int appEpoch: Math.floor((new Date).getTime() / 1000)
property bool themeTransition: false
// fiat price conversion
property real fiatPriceXMRUSD: 0
property real fiatPriceXMREUR: 0
property real fiatPrice: 0
property var fiatPriceAPIs: {
return {
"kraken": {
@@ -123,8 +126,6 @@ ApplicationWindow {
property var current_address_label: "Primary"
property int current_subaddress_table_index: 0
function altKeyReleased() { ctrlPressed = false; }
function showPageRequest(page) {
middlePanel.state = page
leftPanel.selectItem(page)
@@ -140,12 +141,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"
@@ -165,11 +162,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"
@@ -181,11 +175,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"
@@ -220,6 +211,9 @@ ApplicationWindow {
if (prevState) {
appWindow.viewState = prevState;
}
if (wizard.wizardState == "wizardOpenWallet1") {
wizard.wizardStateView.wizardOpenWallet1View.pageRoot.forceActiveFocus();
}
};
passwordDialog.open(usefulName(persistentSettings.wallet_path));
}
@@ -367,17 +361,18 @@ ApplicationWindow {
middlePanel.getProofClicked.connect(handleGetProof);
middlePanel.checkProofClicked.connect(handleCheckProof);
persistentSettings.restore_height = currentWallet.walletCreationHeight;
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(
@@ -394,7 +389,7 @@ ApplicationWindow {
}
function isTrustedDaemon() {
return !persistentSettings.useRemoteNode || persistentSettings.is_trusted_daemon;
return !persistentSettings.useRemoteNode || remoteNodesModel.currentRemoteNode().trusted;
}
function usefulName(path) {
@@ -430,8 +425,8 @@ ApplicationWindow {
leftPanel.balanceString = balance
leftPanel.balanceUnlockedString = balanceU
if (middlePanel.state === "Account") {
middlePanel.accountView.balanceAllText = walletManager.displayAmount(appWindow.currentWallet.balanceAll());
middlePanel.accountView.unlockedBalanceAllText = walletManager.displayAmount(appWindow.currentWallet.unlockedBalanceAll());
middlePanel.accountView.balanceAllText = walletManager.displayAmount(appWindow.currentWallet.balanceAll()) + " XMR";
middlePanel.accountView.unlockedBalanceAllText = walletManager.displayAmount(appWindow.currentWallet.unlockedBalanceAll()) + " XMR";
}
}
@@ -496,7 +491,7 @@ ApplicationWindow {
walletInitialized = true
// check if daemon was already mining and add mining logo if true
middlePanel.miningView.update();
middlePanel.advancedView.miningView.update();
}
}
@@ -540,12 +535,6 @@ ApplicationWindow {
// try to resolve common wallet cache errors automatically
switch (wallet.errorString) {
case "basic_string::_M_replace_aux":
walletManager.clearWalletCache(wallet.path);
walletPassword = passwordDialog.password;
appWindow.initialize();
console.error("Repairing wallet cache with error: ", wallet.errorString);
appWindow.showStatusMessage(qsTr("Repairing incompatible wallet cache. Resyncing wallet."),6);
return;
case "std::bad_alloc":
walletManager.clearWalletCache(wallet.path);
walletPassword = passwordDialog.password;
@@ -623,7 +612,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(),
@@ -649,6 +640,7 @@ ApplicationWindow {
console.log("disconnecting remote node");
persistentSettings.useRemoteNode = false;
currentDaemonAddress = localDaemonAddress
currentWallet.setDaemonLogin("", "");
currentWallet.initAsync(
currentDaemonAddress,
isTrustedDaemon(),
@@ -721,7 +713,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){
@@ -817,7 +809,7 @@ ApplicationWindow {
return false;
}
function onTransactionCreated(pendingTransaction,address,paymentId,mixinCount){
function onTransactionCreated(pendingTransaction, addresses, paymentId, mixinCount) {
console.log("Transaction created");
txConfirmationPopup.bottomText.text = "";
transaction = pendingTransaction;
@@ -849,48 +841,49 @@ ApplicationWindow {
}
}
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);
txConfirmationPopup.bottomTextAnimation.running = false
txConfirmationPopup.bottomText.text = qsTr("Creating transaction...") + translationManager.emptyString;
txConfirmationPopup.transactionAddress = address;
txConfirmationPopup.transactionAmount = Utils.removeTrailingZeros(amount);
txConfirmationPopup.transactionPriority = priority;
txConfirmationPopup.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) {
txConfirmationPopup.errorText.text = qsTr("Amount is wrong: expected number from %1 to %2")
.arg(walletManager.displayAmount(0))
.arg(walletManager.displayAmount(currentWallet.unlockedBalance()))
+ translationManager.emptyString;
return;
} else if (amountxmr > currentWallet.unlockedBalance()) {
txConfirmationPopup.errorText.text = qsTr("Insufficient funds. Unlocked balance: %1")
.arg(walletManager.displayAmount(currentWallet.unlockedBalance()))
+ translationManager.emptyString;
return;
}
const recipientAll = recipients.find(function (recipient) {
return recipient.amount == "(all)";
});
if (recipientAll && recipients.length > 1) {
throw "Sending all requires one destination address";
}
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 (amount === "(all)")
currentWallet.createTransactionAllAsync(address, paymentId, mixinCount, priority);
else
currentWallet.createTransactionAsync(address, paymentId, amountxmr, mixinCount, priority);
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
@@ -940,7 +933,7 @@ ApplicationWindow {
// called after user confirms transaction
function handleTransactionConfirmed(fileName) {
// View only wallet - we save the tx
if(viewOnly && saveTxDialog.fileUrl){
if(viewOnly){
// No file specified - abort
if(!saveTxDialog.fileUrl) {
currentWallet.disposeTransaction(transaction)
@@ -985,6 +978,11 @@ ApplicationWindow {
});
}
function doSearchInHistory(searchTerm) {
middlePanel.searchInHistory(searchTerm);
leftPanel.selectItem(middlePanel.state)
}
// called on "getProof"
function handleGetProof(txid, address, message) {
console.log("Getting payment proof: ")
@@ -1007,7 +1005,6 @@ ApplicationWindow {
}
function txProofComputed(txid, result){
informationPopup.title = qsTr("Payment proof") + translationManager.emptyString;
if (result.indexOf("error|") === 0) {
var errorString = result.split("|")[1];
informationPopup.text = qsTr("Couldn't generate a proof because of the following reason: \n") + errorString + translationManager.emptyString;
@@ -1016,8 +1013,6 @@ ApplicationWindow {
informationPopup.text = result;
informationPopup.icon = StandardIcon.Critical;
}
informationPopup.onCloseCallback = null
informationPopup.open()
}
// called on "checkProof"
@@ -1072,12 +1067,6 @@ ApplicationWindow {
informationPopup.open()
}
// blocks UI if wallet can't be opened or no connection to the daemon
function enableUI(enable) {
middlePanel.enabled = enable;
leftPanel.enabled = enable;
}
function showProcessingSplash(message) {
console.log("Displaying processing splash")
if (typeof message != 'undefined') {
@@ -1115,19 +1104,22 @@ ApplicationWindow {
middlePanel.addressBookView.clearFields();
middlePanel.transferView.clearFields();
middlePanel.receiveView.clearFields();
middlePanel.historyView.clearFields();
// disable timers
userInActivityTimer.running = false;
});
}
objectName: "appWindow"
visible: true
width: screenWidth > 980 ? 980 : 800
height: screenHeight > maxWindowHeight ? maxWindowHeight : 700
width: screenAvailableWidth > 980
? 980
: Math.min(screenAvailableWidth, 800)
height: screenAvailableHeight > maxWindowHeight
? maxWindowHeight
: Math.min(screenAvailableHeight, 700)
color: MoneroComponents.Style.appWindowBackgroundColor
flags: persistentSettings.customDecorations ? Windows.flagsCustomDecorations : Windows.flags
onWidthChanged: x -= 0
Timer {
id: fiatPriceTimer
@@ -1150,7 +1142,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";
@@ -1212,10 +1204,7 @@ ApplicationWindow {
return;
}
if(persistentSettings.fiatPriceCurrency === "xmrusd")
appWindow.fiatPriceXMRUSD = ticker;
else if(persistentSettings.fiatPriceCurrency === "xmreur")
appWindow.fiatPriceXMREUR = ticker;
appWindow.fiatPrice = ticker;
appWindow.updateBalance();
}
@@ -1254,7 +1243,7 @@ ApplicationWindow {
}
function fiatApiConvertToFiat(amount) {
var ticker = persistentSettings.fiatPriceCurrency === "xmrusd" ? appWindow.fiatPriceXMRUSD : appWindow.fiatPriceXMREUR;
const ticker = appWindow.fiatPrice;
if(ticker <= 0){
fiatApiError("Invalid ticker value: " + ticker);
return "?.??";
@@ -1262,6 +1251,15 @@ ApplicationWindow {
return (amount * ticker).toFixed(2);
}
function fiatApiConvertToXMR(amount) {
const ticker = appWindow.fiatPrice;
if(ticker <= 0){
fiatApiError("Invalid ticker value: " + ticker);
return "?.??";
}
return (amount / ticker).toFixed(12);
}
function fiatApiUpdateBalance(balance){
// update balance card
var bFiat = "?.??"
@@ -1284,8 +1282,12 @@ ApplicationWindow {
}
Component.onCompleted: {
x = (Screen.width - width) / 2
y = (Screen.height - maxWindowHeight) / 2
if (screenAvailableWidth > width) {
x = (screenAvailableWidth - width) / 2;
}
if (screenAvailableHeight > height) {
y = (screenAvailableHeight - height) / 2;
}
translationManager.setLanguage(persistentSettings.locale.split("_")[0]);
@@ -1353,6 +1355,8 @@ ApplicationWindow {
confirmationDialog.open();
}
}
remoteNodesModel.initialize();
}
MoneroSettings {
@@ -1373,36 +1377,49 @@ ApplicationWindow {
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
property int walletMode: 2
property int lockOnUserInActivityInterval: 10 // minutes
property bool blackTheme: true
property bool blackTheme: MoneroComponents.Style.blackTheme
property bool checkForUpdates: true
property bool autosave: true
property int autosaveMinutes: 10
property bool pruneBlockchain: false
property bool fiatPriceEnabled: false
property bool fiatPriceToggle: false
@@ -1433,6 +1450,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
@@ -1513,6 +1612,10 @@ ApplicationWindow {
y: (parent.height - height) / 2
}
MoneroComponents.RemoteNodeDialog {
id: remoteNodeDialog
}
// Choose blockchain folder
FileDialog {
id: blockchainFileDialog
@@ -1684,18 +1787,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;
@@ -1708,14 +1799,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();
}
@@ -1758,7 +1843,9 @@ ApplicationWindow {
anchors.fill: blurredArea
source: blurredArea
radius: 64
visible: passwordDialog.visible || inputDialog.visible || splash.visible || updateDialog.visible || devicePassphraseDialog.visible || txConfirmationPopup.visible || successfulTxPopup.visible
visible: passwordDialog.visible || inputDialog.visible || splash.visible || updateDialog.visible ||
devicePassphraseDialog.visible || txConfirmationPopup.visible || successfulTxPopup.visible ||
remoteNodeDialog.visible
}
@@ -1811,7 +1898,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();
@@ -1862,7 +1949,8 @@ ApplicationWindow {
}
function toggleLanguageView(){
languageSidebar.isOpened ? languageSidebar.close() : languageSidebar.open();
languageSidebar.visible ? languageSidebar.close() : languageSidebar.open();
languageSidebar.selectCurrentLanguage()
resetLanguageFields()
}
@@ -1938,12 +2026,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);
}
}
@@ -2121,8 +2210,7 @@ ApplicationWindow {
function userActivity() {
// register user activity
var epoch = Math.floor((new Date).getTime()/1000);
appWindow.userLastActive = epoch;
appWindow.userLastActive = Utils.epoch();
}
function checkInUserActivity() {
@@ -2130,23 +2218,32 @@ ApplicationWindow {
if(!persistentSettings.lockOnUserInActivity) return;
if(passwordDialog.visible) return;
var inputDialogVisible = inputDialog && inputDialog.visible
var successfulTxPopupVisible = successfulTxPopup && successfulTxPopup.visible
var informationPopupVisible = informationPopup && informationPopup.visible
// prompt password after X seconds of inactivity
var epoch = Math.floor((new Date).getTime() / 1000);
var inactivity = epoch - appWindow.userLastActive;
var inactivity = Utils.epoch() - appWindow.userLastActive;
if(inactivity < (persistentSettings.lockOnUserInActivityInterval * 60)) return;
passwordDialog.onAcceptedCallback = function() {
if(walletPassword === passwordDialog.password){
passwordDialog.close();
if (inputDialogVisible) inputDialog.open(inputDialog.inputText)
if (successfulTxPopupVisible) successfulTxPopup.open(successfulTxPopup.transactionID)
if (informationPopupVisible) informationPopup.open()
} else {
passwordDialog.showError(qsTr("Wrong password"));
}
if (inputDialogVisible) inputDialog.open(inputDialog.inputText)
}
passwordDialog.onRejectedCallback = function() { appWindow.showWizard(); }
if (inputDialogVisible) inputDialog.close()
remoteNodeDialog.close();
informationPopup.close()
txConfirmationPopup.close()
txConfirmationPopup.clearFields()
txConfirmationPopup.rejected()
successfulTxPopup.close();
passwordDialog.open();
}
@@ -2163,7 +2260,6 @@ ApplicationWindow {
function changeWalletMode(mode){
appWindow.disconnectedEpoch = 0;
appWindow.walletMode = mode;
persistentSettings.walletMode = mode;
applyWalletMode(mode);
}
@@ -2267,8 +2363,12 @@ ApplicationWindow {
MoneroComponents.LanguageSidebar {
id: languageSidebar
dragMargin: 0
onAboutToShow: previousActiveFocusItem = activeFocusItem;
onClosed: { if (previousActiveFocusItem) previousActiveFocusItem.forceActiveFocus() }
}
MoneroComponents.MenuBar { }
Network {
id: network
proxyAddress: persistentSettings.getProxyAddress()

2
monero

Submodule monero updated: 8fef32e45c...2222bea92f

View File

@@ -103,6 +103,7 @@ Rectangle {
MoneroComponents.TextPlain {
id: balanceAll
Layout.rightMargin: 87
font.family: MoneroComponents.Style.fontMonoRegular.name;
font.pixelSize: 16
color: MoneroComponents.Style.defaultFontColor
@@ -115,7 +116,8 @@ Rectangle {
onExited: parent.color = MoneroComponents.Style.defaultFontColor
onClicked: {
console.log("Copied to clipboard");
clipboard.setText(parent.text);
var balanceAllNumberOnly = parent.text.slice(0, -4);
clipboard.setText(balanceAllNumberOnly);
appWindow.showStatusMessage(qsTr("Copied to clipboard"),3)
}
}
@@ -136,6 +138,7 @@ Rectangle {
MoneroComponents.TextPlain {
id: unlockedBalanceAll
Layout.rightMargin: 87
font.family: MoneroComponents.Style.fontMonoRegular.name;
font.pixelSize: 16
color: MoneroComponents.Style.defaultFontColor
@@ -148,7 +151,8 @@ Rectangle {
onExited: parent.color = MoneroComponents.Style.defaultFontColor
onClicked: {
console.log("Copied to clipboard");
clipboard.setText(parent.text);
var unlockedBalanceAllNumberOnly = parent.text.slice(0, -4);
clipboard.setText(unlockedBalanceAllNumberOnly);
appWindow.showStatusMessage(qsTr("Copied to clipboard"),3)
}
}
@@ -190,7 +194,16 @@ Rectangle {
height: subaddressAccountListRow.subaddressAccountListItemHeight
width: parent ? parent.width : undefined
Layout.fillWidth: true
color: "transparent"
color: itemMouseArea.containsMouse || index === currentAccountIndex ? MoneroComponents.Style.titleBarButtonHoverColor : "transparent"
Rectangle {
visible: index === currentAccountIndex
Layout.fillHeight: true
anchors.top: parent.top
anchors.bottom: parent.bottom
color: "darkgrey"
width: 2
}
Rectangle {
color: MoneroComponents.Style.appWindowBorderColor
@@ -226,7 +239,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
@@ -241,7 +254,7 @@ Rectangle {
id: addressLabel
color: MoneroComponents.Style.defaultFontColor
anchors.verticalCenter: parent.verticalCenter
anchors.left: mainLayout.width >= 590 ? balanceTextLabel.left : balanceNumberLabel.left
anchors.left: balanceNumberLabel.left
anchors.leftMargin: -addressLabel.width - 30
fontSize: 16
fontFamily: MoneroComponents.Style.fontMonoRegular.name;
@@ -249,18 +262,6 @@ Rectangle {
themeTransition: false
}
MoneroComponents.Label {
id: balanceTextLabel
visible: mainLayout.width >= 590
color: MoneroComponents.Style.defaultFontColor
anchors.verticalCenter: parent.verticalCenter
anchors.left: balanceNumberLabel.left
anchors.leftMargin: -balanceTextLabel.width - 5
fontSize: 16
text: qsTr("Balance: ") + translationManager.emptyString
themeTransition: false
}
MoneroComponents.Label {
id: balanceNumberLabel
color: MoneroComponents.Style.defaultFontColor
@@ -269,18 +270,17 @@ Rectangle {
anchors.leftMargin: -balanceNumberLabel.width
fontSize: 16
fontFamily: MoneroComponents.Style.fontMonoRegular.name;
text: balance
text: balance + " XMR"
elide: Text.ElideRight
textWidth: mainLayout.width < 660 ? 70 : 135
textWidth: 180
themeTransition: false
}
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)
@@ -299,10 +299,14 @@ Rectangle {
MoneroComponents.IconButton {
id: renameButton
image: "qrc:///images/edit.svg"
fontAwesomeFallbackIcon: FontAwesome.edit
fontAwesomeFallbackSize: 22
color: MoneroComponents.Style.defaultFontColor
opacity: 0.5
opacity: isOpenGL ? 0.5 : 1
fontAwesomeFallbackOpacity: 0.5
Layout.preferredWidth: 23
Layout.preferredHeight: 21
tooltip: qsTr("Edit account label") + translationManager.emptyString
onClicked: pageAccount.renameSubaddressAccountLabel(index);
}
@@ -310,10 +314,14 @@ Rectangle {
MoneroComponents.IconButton {
id: copyButton
image: "qrc:///images/copy.svg"
fontAwesomeFallbackIcon: FontAwesome.clipboard
fontAwesomeFallbackSize: 22
color: MoneroComponents.Style.defaultFontColor
opacity: 0.5
opacity: isOpenGL ? 0.5 : 1
fontAwesomeFallbackOpacity: 0.5
Layout.preferredWidth: 16
Layout.preferredHeight: 21
tooltip: qsTr("Copy address to clipboard") + translationManager.emptyString
onClicked: {
console.log("Address copied to clipboard");
@@ -375,8 +383,8 @@ Rectangle {
subaddressAccountListView.model = appWindow.currentWallet.subaddressAccountModel;
appWindow.currentWallet.subaddress.refresh(appWindow.currentWallet.currentSubaddressAccount)
balanceAll.text = walletManager.displayAmount(appWindow.currentWallet.balanceAll())
unlockedBalanceAll.text = walletManager.displayAmount(appWindow.currentWallet.unlockedBalanceAll())
balanceAll.text = walletManager.displayAmount(appWindow.currentWallet.balanceAll()) + " XMR"
unlockedBalanceAll.text = walletManager.displayAmount(appWindow.currentWallet.unlockedBalanceAll()) + " XMR"
}
}

View File

@@ -134,11 +134,11 @@ Rectangle {
height: addressBookListRow.addressBookListItemHeight
width: parent ? parent.width : undefined
Layout.fillWidth: true
color: "transparent"
color: itemMouseArea.containsMouse ? MoneroComponents.Style.titleBarButtonHoverColor : "transparent"
function doSend() {
console.log("Sending to: ", address +" "+ paymentId);
middlePanel.sendTo(address, paymentId, description);
middlePanel.sendTo(address, paymentId);
leftPanel.selectItem(middlePanel.state)
}
@@ -159,7 +159,7 @@ Rectangle {
Rectangle {
anchors.fill: parent
anchors.topMargin: 5
anchors.rightMargin: 110
anchors.rightMargin: 125
color: "transparent"
MoneroComponents.Label {
@@ -187,8 +187,10 @@ Rectangle {
}
MouseArea {
id: itemMouseArea
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
hoverEnabled: true
visible: root.selectAndSend
onClicked: {
doSend();
@@ -207,21 +209,42 @@ Rectangle {
id: sendToButton
image: "qrc:///images/arrow-right-in-circle-outline-medium-white.svg"
color: MoneroComponents.Style.defaultFontColor
opacity: 0.5
opacity: isOpenGL ? 0.5 : 1
fontAwesomeFallbackIcon: FontAwesome.arrowRight
fontAwesomeFallbackSize: 22
fontAwesomeFallbackOpacity: 0.5
Layout.preferredWidth: 20
Layout.preferredHeight: 20
tooltip: qsTr("Send to this address") + translationManager.emptyString
onClicked: {
doSend();
}
}
MoneroComponents.IconButton {
fontAwesomeFallbackIcon: FontAwesome.searchPlus
fontAwesomeFallbackSize: 22
color: MoneroComponents.Style.defaultFontColor
fontAwesomeFallbackOpacity: 0.5
Layout.preferredWidth: 23
Layout.preferredHeight: 21
tooltip: qsTr("See transactions") + translationManager.emptyString
onClicked: doSearchInHistory(address)
}
MoneroComponents.IconButton {
id: renameButton
image: "qrc:///images/edit.svg"
color: MoneroComponents.Style.defaultFontColor
opacity: 0.5
opacity: isOpenGL ? 0.5 : 1
fontAwesomeFallbackIcon: FontAwesome.edit
fontAwesomeFallbackSize: 22
fontAwesomeFallbackOpacity: 0.5
Layout.preferredWidth: 23
Layout.preferredHeight: 21
tooltip: qsTr("Edit address label") + translationManager.emptyString
onClicked: {
addressBookListView.currentIndex = index;
@@ -232,10 +255,14 @@ Rectangle {
MoneroComponents.IconButton {
id: copyButton
image: "qrc:///images/copy.svg"
color: MoneroComponents.Style.defaultFontColor
opacity: isOpenGL ? 0.5 : 1
fontAwesomeFallbackIcon: FontAwesome.clipboard
fontAwesomeFallbackSize: 22
fontAwesomeFallbackOpacity: 0.5
Layout.preferredWidth: 16
Layout.preferredHeight: 21
color: MoneroComponents.Style.defaultFontColor
opacity: 0.5
tooltip: qsTr("Copy address to clipboard") + translationManager.emptyString
onClicked: {
console.log("Address copied to clipboard");
@@ -292,6 +319,8 @@ Rectangle {
MoneroComponents.LineEditMulti {
id: addressLine
Layout.topMargin: 20
KeyNavigation.backtab: deleteButton.visible ? deleteButton: cancelButton
KeyNavigation.tab: resolveButton.visible ? resolveButton : descriptionLine
labelText: "<style type='text/css'>a {text-decoration: none; color: #858585; font-size: 14px;}</style> %1"
.arg(qsTr("Address")) + translationManager.emptyString
placeholderText: {
@@ -313,6 +342,31 @@ Rectangle {
descriptionLine.text = parsed.tx_description;
}
}
onEnterPressed: addButton.enabled ? addButton.clicked() : ""
onReturnPressed: addButton.enabled ? addButton.clicked() : ""
MoneroComponents.InlineButton {
fontFamily: FontAwesome.fontFamilySolid
fontStyleName: "Solid"
fontPixelSize: 18
text: FontAwesome.desktop
tooltip: qsTr("Grab QR code from screen") + translationManager.emptyString
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) {
addressLine.text = parsed.address
descriptionLine.text = parsed.recipient_name
break;
} else if (walletManager.addressValid(codes[index], appWindow.persistentSettings.nettype)) {
addressLine.text = codes[index];
break;
}
}
}
}
MoneroComponents.InlineButton {
buttonColor: MoneroComponents.Style.orange
@@ -328,6 +382,8 @@ Rectangle {
MoneroComponents.StandardButton {
id: resolveButton
KeyNavigation.backtab: addressLine
KeyNavigation.tab: descriptionLine
Layout.topMargin: 10
text: qsTr("Resolve") + translationManager.emptyString
visible: TxUtils.isValidOpenAliasAddress(addressLine.text)
@@ -365,17 +421,25 @@ Rectangle {
}
}
MoneroComponents.LineEditMulti {
MoneroComponents.LineEdit {
id: descriptionLine
KeyNavigation.backtab: resolveButton.visible ? resolveButton : addressLine
KeyNavigation.tab: addButton.enabled ? addButton : cancelButton
Layout.topMargin: 20
Layout.fillWidth: true
fontSize: 16
placeholderFontSize: 16
labelText: "<style type='text/css'>a {text-decoration: none; color: #858585; font-size: 14px;}</style> %1"
.arg(qsTr("Description")) + translationManager.emptyString
placeholderText: qsTr("Add a name...") + translationManager.emptyString
onAccepted: addButton.enabled ? addButton.clicked() : ""
}
RowLayout {
Layout.topMargin: 20
MoneroComponents.StandardButton {
id: addButton
KeyNavigation.backtab: descriptionLine
KeyNavigation.tab: cancelButton
text: (root.editEntry ? qsTr("Save") : qsTr("Add")) + translationManager.emptyString
enabled: root.checkInformation(addressLine.text, appWindow.persistentSettings.nettype)
onClicked: {
@@ -401,39 +465,25 @@ Rectangle {
}
}
Text {
MoneroComponents.StandardButton {
id: cancelButton
Layout.leftMargin: 20
font.pixelSize: 16
font.bold: false
color: MoneroComponents.Style.defaultFontColor
KeyNavigation.backtab: addButton
KeyNavigation.tab: deleteButton.visible ? deleteButton : addressLine
text: qsTr("Cancel") + translationManager.emptyString
MouseArea {
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: root.showAddressBook();
}
primary: false
onClicked: root.showAddressBook();
}
Text {
MoneroComponents.StandardButton {
id: deleteButton
KeyNavigation.backtab: cancelButton
KeyNavigation.tab: addressLine
visible: root.editEntry
Layout.leftMargin: 20
font.pixelSize: 16
font.bold: false
color: MoneroComponents.Style.defaultFontColor
text: qsTr("Delete") + translationManager.emptyString
MouseArea {
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
currentWallet.addressBook.deleteRow(addressBookListView.currentIndex);
root.showAddressBook();
}
primary: false
onClicked: {
currentWallet.addressBook.deleteRow(addressBookListView.currentIndex);
root.showAddressBook();
}
}
}
@@ -464,6 +514,7 @@ Rectangle {
addressBookEmptyLayout.visible = false
addressBookLayout.visible = false;
addContactLayout.visible = true;
addressLine.forceActiveFocus();
}
function showEditAddress(address, description) {
@@ -474,12 +525,14 @@ Rectangle {
addContactLayout.visible = true;
addressLine.text = address;
descriptionLine.text = description;
addressLine.forceActiveFocus();
addressLine.cursorPosition = addressLine.text.length;
}
function updateFromQrCode(address, payment_id, amount, tx_description, recipient_name) {
console.log("updateFromQrCode")
addressLine.text = address
descriptionLine.text = recipient_name + " " + tx_description
descriptionLine.text = recipient_name
cameraUi.qrcode_decoded.disconnect(updateFromQrCode)
}

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

@@ -154,12 +154,15 @@ Rectangle {
Layout.fillWidth: true
input.topPadding: 6
input.bottomPadding: 6
fontSize: 16
fontSize: 15
labelFontSize: 14
placeholderText: qsTr("Search by Transaction ID, Address, Description, Amount or Blockheight") + translationManager.emptyString
placeholderFontSize: 16
placeholderFontSize: 15
inputHeight: 34
onTextUpdated: {
if (!sortAndFilter.collapsed) {
sortAndFilter.collapsed = true;
}
if(searchInput.text != null && searchInput.text.length >= 3){
root.sortSearchString = searchInput.text;
root.reset();
@@ -170,6 +173,27 @@ Rectangle {
root.updateFilter();
}
}
Rectangle {
color: "transparent"
height: cleanButton.height
width: cleanButton.width
Layout.rightMargin: -8
Layout.leftMargin: -2
MoneroComponents.InlineButton {
id: cleanButton
buttonColor: "transparent"
fontFamily: FontAwesome.fontFamilySolid
fontStyleName: "Solid"
fontPixelSize: 18
text: FontAwesome.times
tooltip: qsTr("Clean") + translationManager.emptyString
tooltipLeft: true
visible: searchInput.text != ""
onClicked: searchInput.text = ""
}
}
}
}
@@ -588,6 +612,7 @@ Rectangle {
color: "transparent"
Rectangle {
visible: !isFailed && !isPending
anchors.top: parent.top
anchors.topMargin: 24
anchors.horizontalCenter: parent.horizontalCenter
@@ -596,6 +621,19 @@ Rectangle {
radius: 8
color: isout ? "#d85a00" : "#2eb358"
}
MoneroComponents.TextPlain {
visible: isFailed || isPending
anchors.top: parent.top
anchors.topMargin: 24
anchors.horizontalCenter: parent.horizontalCenter
font.family: FontAwesome.fontFamilySolid
font.styleName: isFailed ? "Solid" : ""
font.pixelSize: 15
text: isFailed ? FontAwesome.times : FontAwesome.clockO
color: isFailed ? "#FF0000" : MoneroComponents.Style.defaultFontColor
themeTransition: false
}
}
ColumnLayout {
@@ -633,7 +671,7 @@ Rectangle {
MoneroComponents.TextPlain {
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 15
text: (isout ? qsTr("Sent") : qsTr("Received")) + translationManager.emptyString
text: (isout ? qsTr("Sent") : qsTr("Received")) + (isFailed ? " (" + qsTr("Failed") + ")" : (isPending ? " (" + qsTr("Pending") + ")" : "")) + translationManager.emptyString
color: MoneroComponents.Style.historyHeaderTextColor
anchors.verticalCenter: parent.verticalCenter
themeTransitionBlackColor: MoneroComponents.Style._b_historyHeaderTextColor
@@ -764,14 +802,7 @@ Rectangle {
font.pixelSize: 15
text: {
if (isout) {
if (isFailed) {
return qsTr("Failed") + translationManager.emptyString;
}
if (isPending) {
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 +811,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;
@@ -953,6 +982,8 @@ Rectangle {
label.font.family: FontAwesome.fontFamily
fontSize: 18
width: 34
tooltip: qsTr("Transaction details") + translationManager.emptyString
tooltipLeft: true
MouseArea {
state: "details"
@@ -960,8 +991,14 @@ Rectangle {
hoverEnabled: true
z: parent.z + 1
onEntered: parent.opacity = 0.8;
onExited: parent.opacity = 1.0;
onEntered: {
parent.opacity = 0.8;
parent.tooltipPopup.open()
}
onExited: {
parent.opacity = 1.0;
parent.tooltipPopup.close()
}
}
}
@@ -983,6 +1020,8 @@ Rectangle {
label.font.family: FontAwesome.fontFamilyBrands
fontSize: 18
width: 34
tooltip: qsTr("Generate payment proof") + translationManager.emptyString
tooltipLeft: true
MouseArea {
state: "proof"
@@ -990,8 +1029,14 @@ Rectangle {
hoverEnabled: true
z: parent.z + 1
onEntered: parent.opacity = 0.8;
onExited: parent.opacity = 1.0;
onEntered: {
parent.opacity = 0.8;
parent.tooltipPopup.open()
}
onExited: {
parent.opacity = 1.0;
parent.tooltipPopup.close()
}
}
}
}
@@ -1227,7 +1272,7 @@ Rectangle {
if(res[i].state === 'copyable_address') (address ? root.toClipboard(address) : root.toClipboard(addressField.text));
if(res[i].state === 'copyable_receiving_address') root.toClipboard(currentWallet.address(subaddrAccount, subaddrIndex));
if(res[i].state === 'copyable_txkey') root.getTxKey(hash, res[i]);
if(res[i].state === 'set_tx_note') root.editDescription(hash, tx_note);
if(res[i].state === 'set_tx_note') root.editDescription(hash, tx_note, root.txPage);
if(res[i].state === 'details') root.showTxDetails(hash, paymentId, destinations, subaddrAccount, subaddrIndex, dateTime, displayAmount, isout);
if(res[i].state === 'proof') root.showTxProof(hash, paymentId, destinations, subaddrAccount, subaddrIndex);
doCollapse = false;
@@ -1266,6 +1311,8 @@ Rectangle {
image: "qrc:///images/whiteDropIndicator.png"
rotation: delegate.collapsed ? 180 : 0
color: MoneroComponents.Style.defaultFontColor
fontAwesomeFallbackIcon: FontAwesome.arrowDown
fontAwesomeFallbackSize: 14
}
}
@@ -1341,7 +1388,7 @@ Rectangle {
checked: persistentSettings.historyHumanDates
onClicked: {
persistentSettings.historyHumanDates = !persistentSettings.historyHumanDates
root.updateDisplay(root.txOffset, root.txMax, false);
root.updateDisplay(root.txOffset, root.txMax);
}
text: qsTr("Human readable date format") + translationManager.emptyString
}
@@ -1388,7 +1435,7 @@ Rectangle {
}
}
function updateFilter(){
function updateFilter(currentPage){
// applying filters
root.txData = JSON.parse(JSON.stringify(root.txModelData)); // deepcopy
@@ -1417,6 +1464,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) {
@@ -1432,6 +1485,9 @@ Rectangle {
root.updateSort();
root.updateDisplay(root.txOffset, root.txMax);
if (currentPage) {
root.paginationJump(parseInt(currentPage));
}
}
function updateSort(){
@@ -1447,15 +1503,14 @@ Rectangle {
root.updateDisplay(root.txOffset, root.txMax);
}
function updateDisplay(tx_offset, tx_max, auto_collapse) {
if(typeof auto_collapse === 'undefined') auto_collapse = false;
function updateDisplay(tx_offset, tx_max) {
txListViewModel.clear();
// limit results as per tx_max (root.txMax)
var txs = root.txData.slice(tx_offset, tx_offset + tx_max);
// make first result on the first page collapsed by default
if(auto_collapse && root.txPage === 1 && txs.length > 0 && (root.sortSearchString == null || root.sortSearchString === ""))
// collapse tx if there is a single result
if(root.txPage === 1 && txs.length === 1)
root.txDataCollapsed.push(txs[0]['hash']);
// populate listview
@@ -1522,8 +1577,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 +1604,7 @@ Rectangle {
"hash": hash,
"paymentId": paymentId,
"address": address,
"addressBookName": addressBookName,
"destinations": destinations,
"tx_note": tx_note,
"dateHuman": dateHuman,
@@ -1551,6 +1615,8 @@ Rectangle {
"fee": fee,
"confirmations": confirmations,
"confirmationsRequired": confirmationsRequired,
"receivingAddress": receivingAddress,
"receivingAddressLabel": receivingAddressLabel,
"subaddrAccount": subaddrAccount,
"subaddrIndex": subaddrIndex
});
@@ -1560,20 +1626,20 @@ Rectangle {
root.txCount = root.txData.length;
}
function update() {
function update(currentPage) {
// handle outside mutation of tx model; incoming/outgoing funds or new blocks. Update table.
currentWallet.history.refresh(currentWallet.currentSubaddressAccount);
root.updateTransactionsFromModel();
root.updateFilter();
root.updateFilter(currentPage);
}
function editDescription(_hash, _tx_note){
function editDescription(_hash, _tx_note, currentPage){
inputDialog.labelText = qsTr("Set description:") + translationManager.emptyString;
inputDialog.onAcceptedCallback = function() {
appWindow.currentWallet.setUserNote(_hash, inputDialog.inputText);
appWindow.showStatusMessage(qsTr("Updated description."),3);
root.update();
root.update(currentPage);
}
inputDialog.onRejectedCallback = null;
inputDialog.open(_tx_note);
@@ -1654,6 +1720,10 @@ Rectangle {
console.log("getProof: Generate clicked: txid " + hash + ", address " + address);
middlePanel.getProofClicked(hash, address, '');
informationPopup.title = qsTr("Payment proof") + translationManager.emptyString;
informationPopup.text = qsTr("Generating payment proof") + "..." + translationManager.emptyString;
informationPopup.onCloseCallback = null
informationPopup.open()
}
function toClipboard(text){
@@ -1682,16 +1752,6 @@ Rectangle {
+ translationManager.emptyString;
}
function lookupPaymentID(paymentId) {
if (!addressBookModel)
return ""
var idx = addressBookModel.lookupPaymentID(paymentId)
if (idx < 0)
return ""
idx = addressBookModel.index(idx, 0)
return addressBookModel.data(idx, AddressBookModel.AddressBookDescriptionRole)
}
FileDialog {
id: writeCSVFileDialog
title: qsTr("Please choose a folder") + translationManager.emptyString
@@ -1735,16 +1795,38 @@ Rectangle {
root.model = appWindow.currentWallet.historyModel;
root.model.sortRole = TransactionHistoryModel.TransactionBlockHeightRole
root.model.sort(0, Qt.DescendingOrder);
fromDatePicker.currentDate = model.transactionHistory.firstDateTime
var count = root.model.rowCount()
if (count > 0) {
//date of the first transaction
fromDatePicker.currentDate = root.model.data(root.model.index((count - 1), 0), TransactionHistoryModel.TransactionDateRole);
} else {
//date of monero birth (2014-04-18)
fromDatePicker.currentDate = model.transactionHistory.firstDateTime
}
}
root.reset();
root.refresh();
root.initialized = true;
root.updateFilter();
}
function onPageClosed(){
root.initialized = false;
root.reset(true);
root.clearFields();
}
function searchInHistory(searchTerm){
searchInput.text = searchTerm;
searchInput.forceActiveFocus();
searchInput.cursorPosition = searchInput.text.length;
sortAndFilter.collapsed = true;
}
function clearFields() {
sortAndFilter.collapsed = false;
searchInput.text = "";
root.txDataCollapsed = [];
}
}

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

@@ -50,6 +50,7 @@ Rectangle {
color: "transparent"
property var model
property alias receiveHeight: mainLayout.height
property var state: "Address"
function renameSubaddressLabel(_index){
inputDialog.labelText = qsTr("Set the label of the selected address:") + translationManager.emptyString;
@@ -60,6 +61,17 @@ Rectangle {
inputDialog.open(appWindow.currentWallet.getSubaddressLabel(appWindow.currentWallet.currentSubaddressAccount, _index))
}
function generateQRCodeString() {
if (pageReceive.state == "PaymentRequest") {
return TxUtils.makeQRCodeString(appWindow.current_address,
(amountToReceiveXMR.text != "" && parseFloat(amountToReceiveXMR.text) != 0 ? amountToReceiveXMR.text : ""),
(txDescriptionInput.text != "" ? txDescriptionInput.text : ""),
(receiverNameInput.text != "" ? receiverNameInput.text : ""));
} else {
return TxUtils.makeQRCodeString(appWindow.current_address);
}
}
Clipboard { id: clipboard }
/* main layout */
@@ -72,17 +84,467 @@ Rectangle {
anchors.top: parent.top
anchors.right: parent.right
spacing: 20
spacing: 15
ColumnLayout {
id: selectedAddressDetailsColumn
Layout.alignment: Qt.AlignHCenter
spacing: 0
property int qrSize: 220
MoneroComponents.Navbar {
Layout.alignment: Qt.AlignHCenter
Layout.bottomMargin: 10
MoneroComponents.NavbarItem {
active: state == "Address"
text: qsTr("Address") + translationManager.emptyString
onSelected: state = "Address"
}
MoneroComponents.NavbarItem {
active: state == "PaymentRequest"
text: qsTr("Payment request") + translationManager.emptyString
onSelected: {
state = "PaymentRequest";
qrCodeTextMouseArea.hoverEnabled = true;
}
}
}
Rectangle {
id: qrContainer
color: MoneroComponents.Style.blackTheme ? "white" : "transparent"
Layout.fillWidth: true
Layout.alignment: Qt.AlignHCenter
Layout.maximumWidth: parent.qrSize
Layout.preferredHeight: width
radius: 4
Image {
id: qrCode
anchors.fill: parent
anchors.margins: 1
smooth: false
fillMode: Image.PreserveAspectFit
source: "image://qrcode/" + generateQRCodeString();
MouseArea {
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
acceptedButtons: Qt.LeftButton | Qt.RightButton
onEntered: qrCodeTooltip.tooltipPopup.open()
onExited: qrCodeTooltip.tooltipPopup.close()
onClicked: {
if (mouse.button == Qt.LeftButton){
walletManager.saveQrCodeToClipboard(generateQRCodeString());
appWindow.showStatusMessage(qsTr("QR code copied to clipboard") + translationManager.emptyString, 3);
} else if (mouse.button == Qt.RightButton){
qrMenu.x = this.mouseX;
qrMenu.y = this.mouseY;
qrMenu.open()
}
}
}
}
Menu {
id: qrMenu
title: "QrCode"
MenuItem {
text: qsTr("Copy to clipboard") + translationManager.emptyString;
onTriggered: walletManager.saveQrCodeToClipboard(generateQRCodeString())
}
MenuItem {
text: qsTr("Save as Image") + translationManager.emptyString;
onTriggered: qrFileDialog.open()
}
}
MoneroComponents.Tooltip {
id: qrCodeTooltip
text: qsTr("Left click: copy QR code to clipboard") + "<br>" + qsTr("Right click: save QR code as image file") + translationManager.emptyString
}
}
MoneroComponents.TextPlain {
id: qrCodeText
Layout.alignment: Qt.AlignHCenter
Layout.topMargin: 6
Layout.maximumWidth: 285
Layout.minimumHeight: 75
verticalAlignment: Text.AlignVCenter
visible: paymentRequestGridLayout.visible
font.pixelSize: 12
color: qrCodeTextMouseArea.containsMouse ? MoneroComponents.Style.orange : MoneroComponents.Style.defaultFontColor
text: generateQRCodeString();
wrapMode: Text.WrapAnywhere
tooltip: qsTr("Copy payment request to clipboard") + translationManager.emptyString
themeTransition: false
MouseArea {
id: qrCodeTextMouseArea
hoverEnabled: false //true when Payment request navbar button is clicked (fix bug displaying tooltip when navbar button is clicked)
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onEntered: parent.tooltipPopup.open()
onExited: parent.tooltipPopup.close()
onClicked: {
clipboard.setText(qrCodeText.text);
appWindow.showStatusMessage(qsTr("Payment request copied to clipboard") + translationManager.emptyString, 3);
}
}
}
GridLayout {
id: paymentRequestGridLayout
columns: 3
rows: 4
visible: pageReceive.state == "PaymentRequest"
Layout.alignment: Qt.AlignHCenter
Layout.topMargin: 6
Layout.preferredWidth: 285
Layout.maximumWidth: 285
MoneroComponents.Label {
id: amountTitleFiat
Layout.bottomMargin: 3
Layout.preferredWidth: 90
visible: persistentSettings.fiatPriceEnabled
fontSize: 14
text: qsTr("Amount") + translationManager.emptyString
}
MoneroComponents.Input {
id: amountToReceiveFiat
Layout.preferredWidth: 165
Layout.maximumWidth: 165
visible: persistentSettings.fiatPriceEnabled
topPadding: 5
leftPadding: 5
font.family: MoneroComponents.Style.fontMonoRegular.name
font.pixelSize: 14
font.bold: false
horizontalAlignment: TextInput.AlignLeft
verticalAlignment: TextInput.AlignVCenter
selectByMouse: true
color: MoneroComponents.Style.defaultFontColor
placeholderText: "0.00"
background: Rectangle {
color: MoneroComponents.Style.blackTheme ? "transparent" : "white"
radius: 3
border.color: parent.activeFocus ? MoneroComponents.Style.inputBorderColorActive : MoneroComponents.Style.inputBorderColorInActive
border.width: 1
}
onTextEdited: {
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;
}
}
if (amountToReceiveFiat.text == "") {
amountToReceiveXMR.text = "";
} else {
amountToReceiveXMR.text = fiatApiConvertToXMR(amountToReceiveFiat.text);
}
}
validator: RegExpValidator {
regExp: /^\s*(\d{1,8})?([\.,]\d{1,2})?\s*$/
}
}
MoneroComponents.Label {
Layout.bottomMargin: 3
visible: persistentSettings.fiatPriceEnabled
fontSize: 14
text: appWindow.fiatApiCurrencySymbol();
}
MoneroComponents.Label {
id: amountTitleXMR
Layout.bottomMargin: 3
Layout.preferredWidth: 90
fontSize: 14
text: persistentSettings.fiatPriceEnabled ? "" : qsTr("Amount") + translationManager.emptyString
}
MoneroComponents.Input {
id: amountToReceiveXMR
Layout.preferredWidth: 165
Layout.maximumWidth: 165
topPadding: 5
leftPadding: 5
font.family: MoneroComponents.Style.fontMonoRegular.name
font.pixelSize: 14
font.bold: false
horizontalAlignment: TextInput.AlignLeft
verticalAlignment: TextInput.AlignVCenter
selectByMouse: true
color: MoneroComponents.Style.defaultFontColor
placeholderText: "0.000000000000"
background: Rectangle {
color: MoneroComponents.Style.blackTheme ? "transparent" : "white"
radius: 3
border.color: parent.activeFocus ? MoneroComponents.Style.inputBorderColorActive : MoneroComponents.Style.inputBorderColorInActive
border.width: 1
}
onTextEdited: {
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;
}
}
if (amountToReceiveXMR.text == "") {
amountToReceiveFiat.text = "";
} else {
amountToReceiveFiat.text = fiatApiConvertToFiat(amountToReceiveXMR.text);
}
}
validator: RegExpValidator {
regExp: /^\s*(\d{1,8})?([\.,]\d{1,12})?\s*$/
}
}
MoneroComponents.Label {
Layout.bottomMargin: 3
fontSize: 14
text: "XMR"
}
MoneroComponents.Label {
id: txDescription
Layout.bottomMargin: 3
Layout.preferredWidth: 90
fontSize: 14
text: qsTr("Description") + translationManager.emptyString
tooltip: qsTr("What is being payed for (a product, service, donation) (optional)") + translationManager.emptyString
tooltipIconVisible: true
}
MoneroComponents.Input {
id: txDescriptionInput
Layout.preferredWidth: 165
Layout.maximumWidth: 165
topPadding: 7
leftPadding: 7
font.pixelSize: 14
font.bold: false
horizontalAlignment: TextInput.AlignLeft
verticalAlignment: TextInput.AlignVCenter
selectByMouse: true
color: MoneroComponents.Style.defaultFontColor
placeholderText: qsTr("Visible to the sender") + translationManager.emptyString
background: Rectangle {
color: MoneroComponents.Style.blackTheme ? "transparent" : "white"
radius: 3
border.color: parent.activeFocus ? MoneroComponents.Style.inputBorderColorActive : MoneroComponents.Style.inputBorderColorInActive
border.width: 1
}
}
MoneroComponents.Label {
Layout.bottomMargin: 3
fontSize: 14
text: ""
}
MoneroComponents.Label {
id: receiverNameLabel
Layout.bottomMargin: 3
Layout.preferredWidth: 90
fontSize: 14
text: qsTr("Your name") + translationManager.emptyString
tooltip: qsTr("Your name, company or website (optional)") + translationManager.emptyString
tooltipIconVisible: true
}
MoneroComponents.Input {
id: receiverNameInput
Layout.preferredWidth: 165
Layout.maximumWidth: 165
topPadding: 7
leftPadding: 7
font.pixelSize: 14
font.bold: false
horizontalAlignment: TextInput.AlignLeft
verticalAlignment: TextInput.AlignVCenter
selectByMouse: true
color: MoneroComponents.Style.defaultFontColor
placeholderText: qsTr("Visible to the sender") + translationManager.emptyString
background: Rectangle {
color: MoneroComponents.Style.blackTheme ? "transparent" : "white"
radius: 3
border.color: parent.activeFocus ? MoneroComponents.Style.inputBorderColorActive : MoneroComponents.Style.inputBorderColorInActive
border.width: 1
}
}
MoneroComponents.Label {
Layout.bottomMargin: 3
fontSize: 14
text: ""
}
}
MoneroComponents.TextPlain {
id: selectedaddressIndex
Layout.alignment: Qt.AlignHCenter
Layout.preferredWidth: 220
Layout.maximumWidth: 220
Layout.topMargin: 15
visible: pageReceive.state == "Address"
horizontalAlignment: Text.AlignHCenter
text: qsTr("Address #") + subaddressListView.currentIndex + translationManager.emptyString
wrapMode: Text.WordWrap
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 17
textFormat: Text.RichText
color: MoneroComponents.Style.defaultFontColor
themeTransition: false
}
MoneroComponents.TextPlain {
id: selectedAddressDrescription
Layout.alignment: Qt.AlignHCenter
Layout.preferredWidth: 220
Layout.maximumWidth: 220
Layout.topMargin: 10
visible: pageReceive.state == "Address"
horizontalAlignment: Text.AlignHCenter
text: "(" + qsTr("no label") + ")" + translationManager.emptyString
wrapMode: Text.WordWrap
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 17
textFormat: Text.RichText
color: selectedAddressDrescriptionMouseArea.containsMouse ? MoneroComponents.Style.orange : MoneroComponents.Style.dimmedFontColor
themeTransition: false
tooltip: subaddressListView.currentIndex > 0 ? qsTr("Edit address label") : "" + translationManager.emptyString
MouseArea {
id: selectedAddressDrescriptionMouseArea
visible: subaddressListView.currentIndex > 0
hoverEnabled: true
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onEntered: parent.tooltip ? parent.tooltipPopup.open() : ""
onExited: parent.tooltip ? parent.tooltipPopup.close() : ""
onClicked: {
renameSubaddressLabel(appWindow.current_subaddress_table_index);
}
}
}
MoneroComponents.TextPlain {
id: selectedAddress
Layout.alignment: Qt.AlignHCenter
Layout.maximumWidth: 300
Layout.topMargin: 11
visible: pageReceive.state == "Address"
text: appWindow.current_address ? appWindow.current_address : ""
horizontalAlignment: TextInput.AlignHCenter
wrapMode: Text.Wrap
textFormat: Text.RichText
color: selectedAddressMouseArea.containsMouse ? MoneroComponents.Style.orange : MoneroComponents.Style.defaultFontColor
font.pixelSize: 15
font.family: MoneroComponents.Style.fontRegular.name
themeTransition: false
tooltip: qsTr("Copy address to clipboard") + translationManager.emptyString
MouseArea {
id: selectedAddressMouseArea
hoverEnabled: true
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onEntered: parent.tooltip ? parent.tooltipPopup.open() : ""
onExited: parent.tooltip ? parent.tooltipPopup.close() : ""
onClicked: {
clipboard.setText(appWindow.current_address);
appWindow.showStatusMessage(qsTr("Address copied to clipboard") + translationManager.emptyString, 3);
}
}
}
MoneroComponents.StandardButton {
Layout.preferredWidth: 220
Layout.alignment: Qt.AlignHCenter
Layout.topMargin: 18
small: true
text: qsTr("Show on device") + translationManager.emptyString
fontSize: 14
visible: appWindow.currentWallet ? appWindow.currentWallet.isHwBacked() : false
onClicked: {
appWindow.currentWallet.deviceShowAddressAsync(
appWindow.currentWallet.currentSubaddressAccount,
appWindow.current_subaddress_table_index,
'');
}
}
}
ColumnLayout {
id: addressRow
spacing: 0
MoneroComponents.LabelSubheader {
Layout.fillWidth: true
fontSize: 24
textFormat: Text.RichText
text: qsTr("Addresses") + translationManager.emptyString
RowLayout {
spacing: 0
MoneroComponents.LabelSubheader {
Layout.fillWidth: true
fontSize: 24
textFormat: Text.RichText
text: qsTr("Addresses") + translationManager.emptyString
}
MoneroComponents.StandardButton {
id: createAddressButton
small: true
text: qsTr("Create new address") + translationManager.emptyString
fontSize: 13
onClicked: {
inputDialog.labelText = qsTr("Set the label of the new address:") + translationManager.emptyString
inputDialog.onAcceptedCallback = function() {
appWindow.currentWallet.subaddress.addRow(appWindow.currentWallet.currentSubaddressAccount, inputDialog.inputText)
current_subaddress_table_index = appWindow.currentWallet.numSubaddresses(appWindow.currentWallet.currentSubaddressAccount) - 1
subaddressListView.currentIndex = current_subaddress_table_index
}
inputDialog.onRejectedCallback = null;
inputDialog.open()
}
Rectangle {
anchors.top: createAddressButton.bottom
anchors.topMargin: 8
anchors.left: createAddressButton.left
anchors.right: createAddressButton.right
height: 2
color: MoneroComponents.Style.appWindowBorderColor
MoneroEffects.ColorTransition {
targetObj: parent
blackColor: MoneroComponents.Style._b_appWindowBorderColor
whiteColor: MoneroComponents.Style._w_appWindowBorderColor
}
}
}
}
ColumnLayout {
@@ -107,7 +569,16 @@ 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 {
visible: index === appWindow.current_subaddress_table_index
Layout.fillHeight: true
anchors.top: parent.top
anchors.bottom: parent.bottom
color: "darkgrey"
width: 2
}
Rectangle{
anchors.right: parent.right
@@ -127,7 +598,7 @@ Rectangle {
Rectangle {
anchors.fill: parent
anchors.topMargin: 5
anchors.rightMargin: 80
anchors.rightMargin: 90
color: "transparent"
MoneroComponents.Label {
@@ -143,7 +614,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 +638,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;
}
}
@@ -183,14 +653,30 @@ Rectangle {
height: 21
spacing: 10
MoneroComponents.IconButton {
fontAwesomeFallbackIcon: FontAwesome.searchPlus
fontAwesomeFallbackSize: 22
color: MoneroComponents.Style.defaultFontColor
fontAwesomeFallbackOpacity: 0.5
Layout.preferredWidth: 23
Layout.preferredHeight: 21
tooltip: qsTr("See transactions") + translationManager.emptyString
onClicked: doSearchInHistory(address)
}
MoneroComponents.IconButton {
id: renameButton
image: "qrc:///images/edit.svg"
fontAwesomeFallbackIcon: FontAwesome.edit
fontAwesomeFallbackSize: 22
color: MoneroComponents.Style.defaultFontColor
opacity: 0.5
opacity: isOpenGL ? 0.5 : 1
fontAwesomeFallbackOpacity: 0.5
Layout.preferredWidth: 23
Layout.preferredHeight: 21
visible: index !== 0
tooltip: qsTr("Edit address label") + translationManager.emptyString
onClicked: {
renameSubaddressLabel(index);
@@ -200,10 +686,14 @@ Rectangle {
MoneroComponents.IconButton {
id: copyButton
image: "qrc:///images/copy.svg"
fontAwesomeFallbackIcon: FontAwesome.clipboard
fontAwesomeFallbackSize: 22
color: MoneroComponents.Style.defaultFontColor
opacity: 0.5
opacity: isOpenGL ? 0.5 : 1
fontAwesomeFallbackOpacity: 0.5
Layout.preferredWidth: 16
Layout.preferredHeight: 21
tooltip: qsTr("Copy address to clipboard") + translationManager.emptyString
onClicked: {
console.log("Address copied to clipboard");
@@ -220,6 +710,16 @@ Rectangle {
appWindow.currentWallet.currentSubaddressAccount,
subaddressListView.currentIndex
);
if (subaddressListView.currentIndex == 0) {
selectedAddressDrescription.text = qsTr("Primary address") + translationManager.emptyString;
} else {
var selectedAddressLabel = appWindow.currentWallet.getSubaddressLabel(appWindow.currentWallet.currentSubaddressAccount, appWindow.current_subaddress_table_index);
if (selectedAddressLabel == "") {
selectedAddressDrescription.text = "(" + qsTr("no label") + ")" + translationManager.emptyString
} else {
selectedAddressDrescription.text = selectedAddressLabel
}
}
}
}
}
@@ -235,96 +735,6 @@ Rectangle {
whiteColor: MoneroComponents.Style._w_appWindowBorderColor
}
}
MoneroComponents.CheckBox {
id: addNewAddressCheckbox
border: false
uncheckedIcon: FontAwesome.plusCircle
toggleOnClick: false
fontAwesomeIcons: true
fontSize: 16
iconOnTheLeft: true
Layout.fillWidth: true
Layout.topMargin: 10
text: qsTr("Create new address") + translationManager.emptyString;
onClicked: {
inputDialog.labelText = qsTr("Set the label of the new address:") + translationManager.emptyString
inputDialog.onAcceptedCallback = function() {
appWindow.currentWallet.subaddress.addRow(appWindow.currentWallet.currentSubaddressAccount, inputDialog.inputText)
current_subaddress_table_index = appWindow.currentWallet.numSubaddresses(appWindow.currentWallet.currentSubaddressAccount) - 1
subaddressListView.currentIndex = current_subaddress_table_index
}
inputDialog.onRejectedCallback = null;
inputDialog.open()
}
}
}
ColumnLayout {
Layout.alignment: Qt.AlignHCenter
spacing: 11
property int qrSize: 220
Rectangle {
id: qrContainer
color: MoneroComponents.Style.blackTheme ? "white" : "transparent"
Layout.fillWidth: true
Layout.maximumWidth: parent.qrSize
Layout.preferredHeight: width
radius: 4
Image {
id: qrCode
anchors.fill: parent
anchors.margins: 1
smooth: false
fillMode: Image.PreserveAspectFit
source: "image://qrcode/" + TxUtils.makeQRCodeString(appWindow.current_address)
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.RightButton
onPressAndHold: qrFileDialog.open()
}
}
}
MoneroComponents.StandardButton {
Layout.preferredWidth: 220
small: true
text: FontAwesome.save + " %1".arg(qsTr("Save as image")) + translationManager.emptyString
label.font.family: FontAwesome.fontFamily
fontSize: 13
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
text: FontAwesome.eye + " %1".arg(qsTr("Show on device")) + translationManager.emptyString
label.font.family: FontAwesome.fontFamily
fontSize: 13
visible: appWindow.currentWallet ? appWindow.currentWallet.isHwBacked() : false
onClicked: {
appWindow.currentWallet.deviceShowAddressAsync(
appWindow.currentWallet.currentSubaddressAccount,
appWindow.current_subaddress_table_index,
'');
}
}
}
MessageDialog {
@@ -339,12 +749,14 @@ Rectangle {
selectExisting: false
nameFilters: ["Image (*.png)"]
onAccepted: {
if(!walletManager.saveQrCode(TxUtils.makeQRCodeString(appWindow.current_address), walletManager.urlToLocalPath(fileUrl))) {
if(!walletManager.saveQrCode(generateQRCodeString(), walletManager.urlToLocalPath(fileUrl))) {
console.log("Failed to save QrCode to file " + walletManager.urlToLocalPath(fileUrl) )
receivePageDialog.title = qsTr("Save QrCode") + translationManager.emptyString;
receivePageDialog.text = qsTr("Failed to save QrCode to ") + walletManager.urlToLocalPath(fileUrl) + translationManager.emptyString;
receivePageDialog.icon = StandardIcon.Error
receivePageDialog.open()
} else {
appWindow.showStatusMessage(qsTr("QR code saved to ") + walletManager.urlToLocalPath(fileUrl) + translationManager.emptyString, 3);
}
}
}
@@ -352,16 +764,23 @@ Rectangle {
function onPageCompleted() {
console.log("Receive page loaded");
pageReceive.clearFields();
subaddressListView.model = appWindow.currentWallet.subaddressModel;
if (appWindow.currentWallet) {
appWindow.current_address = appWindow.currentWallet.address(appWindow.currentWallet.currentSubaddressAccount, 0)
appWindow.currentWallet.subaddress.refresh(appWindow.currentWallet.currentSubaddressAccount)
if (subaddressListView.currentIndex == -1) {
subaddressListView.currentIndex = 0;
}
}
}
function clearFields() {
// @TODO: add fields
amountToReceiveFiat.text = "";
amountToReceiveXMR.text = "";
txDescriptionInput.text = "";
receiverNameInput.text = "";
}
function onPageClosed() {

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 ? " (" + tx_description + ")" : "") : (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 ? 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,167 +170,550 @@ Rectangle {
}
}
// recipient address input
RowLayout {
id: addressLineRow
Layout.fillWidth: true
ListModel {
id: recipientModel
LineEditMulti {
id: addressLine
KeyNavigation.tab: amountLine
spacing: 0
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);
}
}
readonly property int maxRecipients: 16
MoneroComponents.InlineButton {
fontFamily: FontAwesome.fontFamily
text: FontAwesome.addressBook
onClicked: {
middlePanel.addressBookView.selectAndSend = true;
appWindow.showPageRequest("AddressBook");
ListElement {
address: ""
amount: ""
}
function newRecipient(address, amount) {
if (recipientModel.count < maxRecipients) {
recipientModel.append({address: address, amount: amount});
return true;
}
return false;
}
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;
}
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);
}
function hasEmptyAmount() {
for (var index = 0; index < recipientModel.count; ++index) {
if (recipientModel.get(index).amount === "") {
return true;
}
}
return false;
}
MoneroComponents.InlineButton {
fontFamily: FontAwesome.fontFamily
text: FontAwesome.qrcode
visible: appWindow.qrScannerEnabled
onClicked: {
cameraUi.state = "Capture"
cameraUi.qrcode_decoded.connect(updateFromQrCode)
function hasEmptyAddress() {
for (var index = 0; index < recipientModel.count; ++index) {
if (recipientModel.get(index).address === "") {
return true;
}
}
}
}
return false;
}
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"))
}
}
}
function hasInvalidAddress() {
for (var index = 0; index < recipientModel.count; ++index) {
if (!TxUtils.checkAddress(recipientModel.get(index).address, appWindow.persistentSettings.nettype)) {
return true;
}
}
return false;
}
}
GridLayout {
columns: appWindow.walletMode < 2 ? 1 : 2
Layout.fillWidth: true
columnSpacing: 32
Item {
Layout.fillWidth: true
implicitHeight: recipientLayout.height
ColumnLayout {
Layout.fillWidth: true
Layout.minimumWidth: 200
ColumnLayout {
id: recipientLayout
anchors.left: parent.left
anchors.right: parent.right
spacing: 0
// Amount input
LineEdit {
id: amountLine
KeyNavigation.tab: sendButton
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
readonly property int colSpacing: 10
readonly property int rowSpacing: 10
readonly property int secondRowWidth: 125
readonly property int thirdRowWidth: 50
onLabelLinkActivated: {
middlePanel.accountView.selectAndSend = true;
appWindow.showPageRequest("Account")
}
placeholderText: "0.00"
width: 100
fontBold: true
onTextChanged: {
amountLine.text = amountLine.text.trim().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;
RowLayout {
Layout.bottomMargin: recipientLayout.rowSpacing / 2
spacing: recipientLayout.colSpacing
RowLayout {
id: addressLabel
spacing: 6
Layout.fillWidth: true
MoneroComponents.TextPlain {
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 16
color: MoneroComponents.Style.defaultFontColor
text: qsTr("Address") + translationManager.emptyString
}
MoneroComponents.InlineButton {
fontFamily: FontAwesome.fontFamilySolid
fontStyleName: "Solid"
fontPixelSize: 18
text: FontAwesome.desktop
tooltip: qsTr("Grab QR code from screen") + translationManager.emptyString
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;
} else if (walletManager.addressValid(codes[index], appWindow.persistentSettings.nettype)) {
fillPaymentDetails(codes[index]);
break;
}
}
}
}
amountLine.error = walletManager.amountFromString(amountLine.text) > appWindow.getUnlockedBalance()
}
validator: RegExpValidator {
regExp: /^\s*(\d{1,8})?([\.,]\d{1,12})?\s*$/
}
MoneroComponents.InlineButton {
text: qsTr("All") + translationManager.emptyString
onClicked: amountLine.text = "(all)"
MoneroComponents.InlineButton {
fontFamily: FontAwesome.fontFamilySolid
fontStyleName: "Solid"
text: FontAwesome.qrcode
visible: appWindow.qrScannerEnabled
tooltip: qsTr("Scan QR code") + translationManager.emptyString
onClicked: {
cameraUi.state = "Capture"
cameraUi.qrcode_decoded.connect(updateFromQrCode)
}
}
MoneroComponents.InlineButton {
fontFamily: FontAwesome.fontFamily
text: FontAwesome.addressBook
tooltip: qsTr("Import from address book") + translationManager.emptyString
onClicked: {
middlePanel.addressBookView.selectAndSend = true;
appWindow.showPageRequest("AddressBook");
}
}
Item {
Layout.fillWidth: true
}
}
}
RowLayout {
id: amountLabel
spacing: 6
Layout.preferredWidth: 125
Layout.maximumWidth: recipientLayout.secondRowWidth
MoneroComponents.TextPlain {
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 16
color: MoneroComponents.Style.defaultFontColor
text: qsTr("Amount") + translationManager.emptyString
}
MoneroComponents.InlineButton {
fontFamily: FontAwesome.fontFamilySolid
fontStyleName: "Solid"
fontPixelSize: 16
text: FontAwesome.infinity
visible: recipientModel.count == 1
tooltip: qsTr("Send all unlocked balance of this account") + translationManager.emptyString
onClicked: recipientRepeater.itemAt(0).children[1].children[2].text = "(all)";
}
Item {
Layout.fillWidth: true
}
}
Item {
Layout.preferredWidth: recipientLayout.thirdRowWidth
}
}
Repeater {
id: recipientRepeater
model: recipientModel
ColumnLayout {
spacing: 0
Rectangle {
Layout.fillWidth: true
Layout.topMargin: -1
Layout.leftMargin: 1
Layout.rightMargin: recipientLayout.thirdRowWidth + 1
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 ? 0 : 1
Layout.bottomMargin: 2
Layout.fillWidth: true
addressValidation: true
borderDisabled: true
fontColor: error && text != "" ? MoneroComponents.Style.errorColor : MoneroComponents.Style.defaultFontColor
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, parsed.recipient_name);
}
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.topMargin: index > 0 ? 0 : 1
Layout.bottomMargin: 1
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: index > 0 ? 0 : 1
Layout.bottomMargin: 2
Layout.rightMargin: recipientLayout.colSpacing / 2
Layout.preferredWidth: 125
Layout.maximumWidth: 125
borderDisabled: true
fontFamily: MoneroComponents.Style.fontMonoRegular.name
fontSize: 14
inputPaddingLeft: 0
inputPaddingRight: 0
inputPaddingTop: 0
inputPaddingBottom: 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: FontAwesome.times
tooltip: qsTr("Remove recipient") + translationManager.emptyString
tooltipLeft: true
visible: recipientModel.count > 1
MouseArea {
id: mouseArea
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
hoverEnabled: true
onEntered: parent.tooltipPopup.open()
onExited: parent.tooltipPopup.close()
onClicked: recipientModel.remove(index);
}
}
MoneroComponents.TextPlain {
Layout.leftMargin: recipientLayout.colSpacing / 2
Layout.preferredWidth: recipientLayout.thirdRowWidth
horizontalAlignment: Text.AlignHCenter
font.family: MoneroComponents.Style.fontRegular.name
text: "XMR"
visible: recipientModel.count == 1
}
}
}
}
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
Layout.topMargin: recipientModel.count > 1 ? 0 : -1
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
Layout.topMargin: recipientModel.count > 1 ? 0 : -1
Layout.maximumWidth: recipientLayout.secondRowWidth
borderDisabled: true
fontFamily: MoneroComponents.Style.fontMonoRegular.name
fontSize: 14
inputHeight: 30
inputPaddingLeft: 0
inputPaddingRight: 0
inputPaddingTop: 0
inputPaddingBottom: 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
Layout.maximumWidth: 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
Layout.topMargin: recipientModel.count > 1 ? 0 : -1
Layout.maximumWidth: recipientLayout.secondRowWidth
borderDisabled: true
fontFamily: MoneroComponents.Style.fontMonoRegular.name
fontSize: 14
inputHeight: 30
inputPaddingLeft: 0
inputPaddingRight: 0
inputPaddingTop: 0
inputPaddingBottom: 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
Layout.topMargin: recipientModel.count > 1 ? 0 : -1
Layout.maximumWidth: 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
// 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.maximumWidth: 200
id: priorityDropdown
currentIndex: 0
dataModel: priorityModelV5
labelText: qsTr("Transaction priority") + translationManager.emptyString
labelFontSize: 16
}
MoneroComponents.TextPlain {
id: feeLabel
Layout.alignment: Qt.AlignRight
Layout.topMargin: 12
Layout.alignment: Qt.AlignBottom
Layout.bottomMargin: 11
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: {
@@ -339,12 +729,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;
});
}
@@ -352,56 +751,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. \
@@ -430,9 +793,11 @@ Rectangle {
}
}
LineEditMulti {
LineEdit {
id: descriptionLine
placeholderText: qsTr("Saved to local wallet history") + translationManager.emptyString
placeholderFontSize: 16
fontSize: 16
placeholderText: qsTr("Saved to local wallet history") + " (" + qsTr("only visible to you") + ")" + translationManager.emptyString
Layout.fillWidth: true
visible: descriptionCheckbox.checked
}
@@ -489,26 +854,25 @@ Rectangle {
RowLayout {
StandardButton {
id: sendButton
KeyNavigation.tab: addressLine
rightIcon: "qrc:///images/rightArrow.png"
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
@@ -549,34 +913,32 @@ Rectangle {
console.log("Transfer: import key images clicked")
importKeyImagesDialog.open();
}
helpTextLarge.text: qsTr("Required for view-only wallets to display the real balance") + translationManager.emptyString
helpTextSmall.text: {
tooltip: {
var errorMessage = "";
if (appWindow.viewOnly && !appWindow.isTrustedDaemon()){
errorMessage = "<p class='orange'>" + qsTr("* To import, you must connect to a local node or a trusted remote node") + "</p>";
}
return "<style type='text/css'>p{line-height:20px; margin-top:0px; margin-bottom:0px; color:" + MoneroComponents.Style.defaultFontColor +
var header = qsTr("Required for view-only wallets to display the real balance") + translationManager.emptyString;
return "<style type='text/css'>.header{ font-size: 13px; } p{line-height:20px; margin-top:0px; margin-bottom:0px; " +
";} p.orange{color:#ff9323;}</style>" +
"<div class='header'>" + header + "</div>" +
"<p>" + qsTr("1. Using cold wallet, export the key images into a file") + "</p>" +
"<p>" + qsTr("2. Using view-only wallet, import the key images file") + "</p>" +
errorMessage + translationManager.emptyString
}
helpTextSmall.themeTransition: false
}
AdvancedOptionsItem {
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
@@ -590,14 +952,15 @@ Rectangle {
console.log("Transfer: submit tx clicked")
submitTxDialog.open();
}
helpTextLarge.text: qsTr("Spend XMR from a cold (offline) wallet") + translationManager.emptyString
helpTextSmall.text: {
tooltip: {
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 +
var header = qsTr("Spend XMR from a cold (offline) wallet") + translationManager.emptyString;
return "<style type='text/css'>.header{ font-size: 13px; } p{line-height:20px; margin-top:0px; margin-bottom:0px; " +
";} p.orange{color:#ff9323;}</style>" +
"<div class='header'>" + header + "</div>" +
"<p>" + qsTr("1. Using view-only wallet, export the outputs into a file") + "</p>" +
"<p>" + qsTr("2. Using cold wallet, import the outputs file and export the key images") + "</p>" +
"<p>" + qsTr("3. Using view-only wallet, import the key images file and create a transaction file") + "</p>" +
@@ -605,7 +968,6 @@ Rectangle {
"<p>" + qsTr("4. Using cold wallet, sign your transaction file") + "</p>" +
"<p>" + qsTr("5. Using view-only wallet, submit your signed transaction") + "</p>" + translationManager.emptyString
}
helpTextSmall.themeTransition: false
}
AdvancedOptionsItem {
@@ -617,7 +979,7 @@ Rectangle {
console.log("Transfer: sweepUnmixableClicked")
root.sweepUnmixableClicked()
}
helpTextLarge.text: qsTr("Create a transaction that spends old unmovable outputs") + translationManager.emptyString
tooltip: qsTr("Create a transaction that spends old unmovable outputs") + translationManager.emptyString
}
}
@@ -794,19 +1156,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
@@ -116,7 +116,7 @@ Rectangle {
enabled: TxUtils.checkTxID(getProofTxIdLine.text) && (getProofAddressLine.text.length == 0 || TxUtils.checkAddress(getProofAddressLine.text, appWindow.persistentSettings.nettype))
onClicked: {
console.log("getProof: Generate clicked: txid " + getProofTxIdLine.text + ", address " + getProofAddressLine.text + ", message: " + getProofMessageLine.text);
root.getProofClicked(getProofTxIdLine.text, getProofAddressLine.text, getProofMessageLine.text)
middlePanel.getProofClicked(getProofTxIdLine.text, getProofAddressLine.text, getProofMessageLine.text)
}
}
@@ -201,7 +201,7 @@ Rectangle {
enabled: TxUtils.checkTxID(checkProofTxIdLine.text) && TxUtils.checkSignature(checkProofSignatureLine.text) && ((checkProofSignatureLine.text.indexOf("SpendProofV") === 0 && checkProofAddressLine.text.length == 0) || (checkProofSignatureLine.text.indexOf("SpendProofV") !== 0 && TxUtils.checkAddress(checkProofAddressLine.text, appWindow.persistentSettings.nettype)))
onClicked: {
console.log("checkProof: Check clicked: txid " + checkProofTxIdLine.text + ", address " + checkProofAddressLine.text + ", message " + checkProofMessageLine.text + ", signature " + checkProofSignatureLine.text);
root.checkProofClicked(checkProofTxIdLine.text, checkProofAddressLine.text, checkProofMessageLine.text, checkProofSignatureLine.text)
middlePanel.checkProofClicked(checkProofTxIdLine.text, checkProofAddressLine.text, checkProofMessageLine.text, checkProofSignatureLine.text)
}
}

View File

@@ -35,7 +35,7 @@ Item {
function onPageCompleted() {
if (appWindow.currentWallet) {
appWindow.current_address = appWindow.currentWallet.address(appWindow.currentWallet.currentSubaddressAccount, 0)
appWindow.current_address = appWindow.currentWallet.address(appWindow.currentWallet.currentSubaddressAccount, appWindow.current_subaddress_table_index);
}
// prepare tracking
trackingCheckbox.checked = root.enableTracking

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

@@ -42,13 +42,15 @@ Rectangle {
Layout.fillWidth: true
property alias infoHeight: infoLayout.height
property string walletModeString: {
var modeStr;
if(appWindow.walletMode === 0){
return qsTr("Simple mode") + translationManager.emptyString;
modeStr = qsTr("Simple mode") + translationManager.emptyString;
} else if(appWindow.walletMode === 1){
return qsTr("Simple mode") + " (bootstrap)" + translationManager.emptyString;
modeStr = qsTr("Simple mode") + " (bootstrap)" + translationManager.emptyString;
} else if(appWindow.walletMode === 2){
return "%1 (%2)".arg(qsTr("Advanced mode")).arg(persistentSettings.useRemoteNode ? qsTr("Remote node") : qsTr("Local node")) + translationManager.emptyString;
modeStr = "%1 (%2)".arg(qsTr("Advanced mode")).arg(persistentSettings.useRemoteNode ? qsTr("Remote node") : qsTr("Local node")) + translationManager.emptyString;
}
return modeStr + (persistentSettings.portable ? ", %1".arg(qsTr("portable")) : "");
}
ColumnLayout {
@@ -189,13 +191,7 @@ Rectangle {
inputDialog.onAcceptedCallback = function() {
var _restoreHeight;
if (inputDialog.inputText) {
var restoreHeightText = inputDialog.inputText;
// Parse date string or restore height as integer
if(restoreHeightText.indexOf('-') === 4 && restoreHeightText.length === 10) {
_restoreHeight = Wizard.getApproximateBlockchainHeight(restoreHeightText, Utils.netTypeToString());
} else {
_restoreHeight = parseInt(restoreHeightText)
}
_restoreHeight = Utils.parseDateStringOrRestoreHeightAsInteger(inputDialog.inputText);
}
if (!isNaN(_restoreHeight)) {
if(_restoreHeight >= 0) {
@@ -399,9 +395,9 @@ Rectangle {
data += "\nWallet log path: " + logger.logFilePath;
data += "\nWallet mode: " + walletModeString;
data += "\nGraphics mode: " + isOpenGL ? "OpenGL" : "Low graphics mode";
data += "\nGraphics mode: " + (isOpenGL ? "OpenGL" : "Low graphics mode");
if (isTails)
data += "\nTails: " + tailsUsePersistence ? "persistent" : "persistence disabled";
data += "\nTails: " + (tailsUsePersistence ? "persistent" : "persistence disabled");
console.log("Copied to clipboard");
clipboard.setText(data);

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
@@ -83,7 +89,6 @@ Rectangle {
toggleOnClick: false
onClicked: {
MoneroComponents.Style.blackTheme = !MoneroComponents.Style.blackTheme;
persistentSettings.blackTheme = MoneroComponents.Style.blackTheme;
}
}
@@ -173,52 +178,34 @@ Rectangle {
Layout.leftMargin: 36
columnSpacing: 32
ColumnLayout {
spacing: 10
Layout.fillWidth: true
MoneroComponents.StandardDropdown {
id: fiatPriceProviderDropDown
Layout.maximumWidth: 200
labelText: qsTr("Price source") + translationManager.emptyString
labelFontSize: 14
dataModel: fiatPriceProvidersModel
onChanged: {
var obj = dataModel.get(currentIndex);
persistentSettings.fiatPriceProvider = obj.data;
MoneroComponents.Label {
Layout.fillWidth: true
fontSize: 14
text: qsTr("Price source") + translationManager.emptyString
}
MoneroComponents.StandardDropdown {
id: fiatPriceProviderDropDown
Layout.fillWidth: true
dataModel: fiatPriceProvidersModel
onChanged: {
var obj = dataModel.get(currentIndex);
persistentSettings.fiatPriceProvider = obj.data;
if(persistentSettings.fiatPriceEnabled)
appWindow.fiatApiRefresh();
}
if(persistentSettings.fiatPriceEnabled)
appWindow.fiatApiRefresh();
}
}
ColumnLayout {
spacing: 10
Layout.fillWidth: true
MoneroComponents.StandardDropdown {
id: fiatPriceCurrencyDropdown
Layout.maximumWidth: 100
labelText: qsTr("Currency") + translationManager.emptyString
labelFontSize: 14
currentIndex: persistentSettings.fiatPriceCurrency === "xmrusd" ? 0 : 1
dataModel: fiatPriceCurrencyModel
onChanged: {
var obj = dataModel.get(currentIndex);
persistentSettings.fiatPriceCurrency = obj.data;
MoneroComponents.Label {
Layout.fillWidth: true
fontSize: 14
text: qsTr("Currency") + translationManager.emptyString
}
MoneroComponents.StandardDropdown {
id: fiatPriceCurrencyDropdown
Layout.fillWidth: true
currentIndex: persistentSettings.fiatPriceCurrency === "xmrusd" ? 0 : 1
dataModel: fiatPriceCurrencyModel
onChanged: {
var obj = dataModel.get(currentIndex);
persistentSettings.fiatPriceCurrency = obj.data;
if(persistentSettings.fiatPriceEnabled)
appWindow.fiatApiRefresh();
}
if(persistentSettings.fiatPriceEnabled)
appWindow.fiatApiRefresh();
}
}

View File

@@ -28,7 +28,7 @@
import QtQuick 2.9
import QtQuick.Layouts 1.1
import QtQuick.Controls 2.0
import QtQuick.Controls 2.2
import "../../js/Utils.js" as Utils
import "../../components" as MoneroComponents
@@ -132,6 +132,18 @@ Rectangle {
font.pixelSize: 18
font.family: MoneroComponents.Style.fontRegular.name
text: qsTr("Daemon log") + translationManager.emptyString
themeTransition: false
onColorChanged: {
var flickableContentYBefore = flickable.contentY
var daemonLogText = consoleArea.text
consoleArea.clear();
if (MoneroComponents.Style.blackTheme) {
consoleArea.append(daemonLogText.replace(/#000000/g, '#ffffff').replace(/#008000/g, '#00ff00'));
} else {
consoleArea.append(daemonLogText.replace(/#ffffff/g, '#000000').replace(/#00ff00/g, '#008000'));
}
flickable.contentY = flickableContentYBefore
}
}
Item {
@@ -164,7 +176,7 @@ Rectangle {
wrapMode: TextEdit.Wrap
readOnly: true
function logCommand(msg){
msg = log_color(msg, "lime");
msg = log_color(msg, MoneroComponents.Style.blackTheme ? "lime" : "green");
consoleArea.append(msg);
}
function logMessage(msg){
@@ -173,7 +185,7 @@ Rectangle {
if(msg.toLowerCase().indexOf('error') >= 0){
color = MoneroComponents.Style.errorColor;
} else if (msg.toLowerCase().indexOf('warning') >= 0){
color = MoneroComponents.Style.warningColor;
color = "#fa6800"
}
// format multi-lines
@@ -206,6 +218,7 @@ Rectangle {
ScrollBar.vertical: ScrollBar {
onActiveChanged: if (!active && !isMac) active = true
policy: isMac ? ScrollBar.AsNeeded : ScrollBar.AlwaysOn
}
}
}
@@ -213,10 +226,14 @@ Rectangle {
MoneroComponents.LineEdit {
id: sendCommandText
Layout.fillWidth: true
inputPaddingTop: 0
inputPaddingBottom: 0
property var lastCommands: []
property int currentCommandIndex
enabled: !persistentSettings.useRemoteNode
fontBold: false
placeholderText: qsTr("command + enter (e.g 'help' or 'status')") + translationManager.emptyString
fontSize: 16
placeholderText: qsTr("Type a command (e.g '%1' or '%2') and press Enter").arg("help").arg("status") + translationManager.emptyString
placeholderFontSize: 16
Keys.onUpPressed: {
if (currentCommandIndex != 0) {

View File

@@ -72,7 +72,7 @@ Rectangle{
Layout.fillHeight: true
anchors.top: parent.top
anchors.bottom: parent.bottom
color: MoneroComponents.Style.blackTheme ? "white" : "darkgrey"
color: "darkgrey"
width: 2
}
@@ -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 {
@@ -165,7 +165,7 @@ Rectangle{
Layout.fillHeight: true
anchors.top: parent.top
anchors.bottom: parent.bottom
color: MoneroComponents.Style.blackTheme ? "white" : "darkgrey"
color: "darkgrey"
width: 2
}
@@ -248,96 +248,16 @@ Rectangle{
}
}
ColumnLayout {
id: remoteNodeLayout
anchors.margins: 0
spacing: 20
Layout.fillWidth: true
Layout.topMargin: 20
MoneroComponents.WarningBox {
Layout.topMargin: 46
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
visible: persistentSettings.useRemoteNode
}
MoneroComponents.WarningBox {
Layout.topMargin: 26
Layout.bottomMargin: 6
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
}
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
currentWallet.setDaemonLogin(persistentSettings.daemonUsername, persistentSettings.daemonPassword);
appWindow.connectRemoteNode()
}
}
MoneroComponents.RemoteNodeList {
Layout.fillWidth: true
Layout.topMargin: 26
visible: persistentSettings.useRemoteNode
}
ColumnLayout {
@@ -398,7 +318,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 +351,7 @@ Rectangle{
}
}
}
}
}
}
}

19
qml.qrc
View File

@@ -3,10 +3,16 @@
<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/RemoteNodeList.qml</file>
<file>components/SettingsListItem.qml</file>
<file>components/Slider.qml</file>
<file>components/Tooltip.qml</file>
<file>components/UpdateDialog.qml</file>
<file>images/whatIsIcon.png</file>
<file>images/whatIsIcon@2x.png</file>
@@ -15,6 +21,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>
@@ -39,6 +46,7 @@
<file>images/prevMonth.png</file>
<file>images/prevMonth@2x.png</file>
<file>components/TitleBar.qml</file>
<file>components/MenuBar.qml</file>
<file>images/resize.png</file>
<file>images/resize@2x.png</file>
<file>images/resizeHovered.png</file>
@@ -162,7 +170,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>
@@ -172,9 +179,9 @@
<file>images/merchant/arrow_right.png</file>
<file>images/merchant/bg.png</file>
<file>images/merchant/input_box.png</file>
<file>fonts/FontAwesome/fa-brands-400.ttf</file>
<file>fonts/FontAwesome/fa-regular-400.ttf</file>
<file>fonts/FontAwesome/fa-solid-900.ttf</file>
<file>fonts/FontAwesome/fa-brands-400.otf</file>
<file>fonts/FontAwesome/fa-regular-400.otf</file>
<file>fonts/FontAwesome/fa-solid-900.otf</file>
<file>fonts/FontAwesome/FontAwesome.qml</file>
<file>fonts/FontAwesome/Object.qml</file>
<file>fonts/FontAwesome/qmldir</file>
@@ -245,5 +252,9 @@
<file>images/success@2x.png</file>
<file>components/SuccessfulTxDialog.qml</file>
<file>components/TxConfirmationDialog.qml</file>
<file>images/ledgerNanoS.png</file>
<file>images/ledgerNanoX.png</file>
<file>images/trezor.png</file>
<file>images/trezor@2x.png</file>
</qresource>
</RCC>

View File

@@ -1,7 +1,4 @@
add_subdirectory(QR-Code-scanner)
add_subdirectory(daemon)
add_subdirectory(libwalletqt)
add_subdirectory(model)
add_subdirectory(openpgp)
add_subdirectory(zxcvbn-c)
@@ -20,7 +17,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"
@@ -48,13 +45,6 @@ if(APPLE)
list(APPEND SOURCE_FILES "qt/macoshelper.mm")
endif()
if(ENABLE_PASS_STRENGTH_METER)
file(GLOB PASS_STRENGTH_FILES
"zxcvbn-c/zxcvbn.h"
"zxcvbn-c/zxcvbn.c"
)
endif()
set(EXECUTABLE_FLAG)
if(MINGW)
set(EXECUTABLE_FLAG WIN32)
@@ -76,7 +66,6 @@ endif()
set(monero_wallet_gui_sources
${SOURCE_FILES}
${PASS_STRENGTH_FILES}
${RESOURCES}
)
@@ -100,9 +89,6 @@ message(STATUS "OpenGL: libraries at ${OPENGL_LIBRARIES}")
target_include_directories(monero-wallet-gui PUBLIC ${Qt5Gui_PRIVATE_INCLUDE_DIRS})
file(GLOB_RECURSE SRC_SOURCES *.cpp)
file(GLOB_RECURSE SRC_HEADERS *.h)
target_include_directories(monero-wallet-gui PUBLIC
${CMAKE_SOURCE_DIR}/monero/include
${CMAKE_SOURCE_DIR}/monero/src
@@ -115,8 +101,6 @@ target_include_directories(monero-wallet-gui PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/model
${CMAKE_CURRENT_SOURCE_DIR}/QR-Code-scanner
${CMAKE_CURRENT_SOURCE_DIR}/zxcvbn-c
${LibUSB_INCLUDE_DIRS}
${HIDAPI_INCLUDE_DIRS}
${X11_INCLUDE_DIR}
${Boost_INCLUDE_DIRS}
${OPENSSL_INCLUDE_DIR}
@@ -139,33 +123,20 @@ endif()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Widgets_EXECUTABLE_COMPILE_FLAGS}")
target_link_libraries(monero-wallet-gui
wallet_merged
${LMDB_LIBRARY}
epee
wallet_api
qrcodegen
${UNBOUND_LIBRARY}
${SODIUM_LIBRARY}
easylogging
blockchain_db
randomx
hardforks
${Boost_LIBRARIES}
${OPENSSL_LIBRARIES}
${CMAKE_DL_LIBS}
${LibUSB_LIBRARIES}
${HIDAPI_LIBRARIES}
${QT5_LIBRARIES}
${EXTRA_LIBRARIES}
${ICU_LIBRARIES}
openpgp
qrdecoder
translations
zxcvbn
)
if(DEVICE_TREZOR_READY)
target_link_libraries(monero-wallet-gui ${TREZOR_DEP_LIBS})
endif()
if(X11_FOUND)
target_link_libraries(monero-wallet-gui ${X11_LIBRARIES})
endif()

View File

@@ -1,3 +1,31 @@
// 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>

View File

@@ -1,3 +1,31 @@
// 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;

View File

@@ -1,4 +0,0 @@
file(GLOB_RECURSE SRC_SOURCES *.cpp)
file(GLOB_RECURSE SRC_HEADERS *.h)

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

@@ -121,13 +121,6 @@ quint64 AddressBook::count() const
return m_rows.size();
}
int AddressBook::lookupPaymentID(const QString &payment_id) const
{
QReadLocker locker(&m_lock);
return m_addressBookImpl->lookupPaymentID(payment_id.toStdString());
}
QString AddressBook::getDescription(const QString &address) const
{
QReadLocker locker(&m_lock);

View File

@@ -51,7 +51,6 @@ public:
quint64 count() const;
Q_INVOKABLE QString errorString() const;
Q_INVOKABLE int errorCode() const;
Q_INVOKABLE int lookupPaymentID(const QString &payment_id) const;
Q_INVOKABLE QString getDescription(const QString &address) const;
enum ErrorCode {

View File

@@ -1,4 +0,0 @@
file(GLOB_RECURSE SRC_SOURCES *.cpp)
file(GLOB_RECURSE SRC_HEADERS *.h)

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

@@ -181,7 +181,6 @@ QString TransactionHistory::writeCSV(quint32 accountIndex, QString out)
TransactionInfo info(tx, this);
// collect column data
double amount = info.amount();
quint64 atomicAmount = info.atomicAmount();
quint32 subaddrAccount = info.subaddrAccount();
QString fee = info.fee();
@@ -212,7 +211,7 @@ QString TransactionHistory::writeCSV(quint32 accountIndex, QString out)
// format and write
QString line = QString("%1,%2,%3,%4,%5,%6,%7,%8,\"%9\",%10,%11\n")
.arg(QString::number(blockHeight), QString::number(epoch), date)
.arg(direction, QString::number(amount), QString::number(atomicAmount))
.arg(direction, displayAmount, QString::number(atomicAmount))
.arg(info.fee(), info.hash(), label, QString::number(subaddrAccount))
.arg(paymentId);
output << line;

View File

@@ -532,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);
});
}
@@ -571,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);
});
}
@@ -586,7 +605,7 @@ void Wallet::createSweepUnmixableTransactionAsync()
{
m_scheduler.run([this] {
PendingTransaction *tx = createSweepUnmixableTransaction();
emit transactionCreated(tx, "", "", 0);
emit transactionCreated(tx, {""}, "", 0);
});
}
@@ -626,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
@@ -712,16 +746,6 @@ QString Wallet::integratedAddress(const QString &paymentId) const
return QString::fromStdString(m_walletImpl->integratedAddress(paymentId.toStdString()));
}
QString Wallet::paymentId() const
{
return m_paymentId;
}
void Wallet::setPaymentId(const QString &paymentId)
{
m_paymentId = paymentId;
}
QString Wallet::getCacheAttribute(const QString &key) const {
return QString::fromStdString(m_walletImpl->getCacheAttribute(key.toStdString()));
}
@@ -1056,9 +1080,9 @@ void Wallet::onPassphraseEntered(const QString &passphrase, bool enter_on_device
Wallet::Wallet(Monero::Wallet *w, QObject *parent)
: QObject(parent)
, m_walletImpl(w)
, m_history(nullptr)
, m_history(new TransactionHistory(m_walletImpl->history(), this))
, m_historyModel(nullptr)
, m_addressBook(nullptr)
, m_addressBook(new AddressBook(m_walletImpl->addressBook(), this))
, m_addressBookModel(nullptr)
, m_daemonBlockChainHeight(0)
, m_daemonBlockChainHeightTtl(DAEMON_BLOCKCHAIN_HEIGHT_CACHE_TTL_SECONDS)
@@ -1069,18 +1093,14 @@ Wallet::Wallet(Monero::Wallet *w, QObject *parent)
, m_disconnected(true)
, m_initialized(false)
, m_currentSubaddressAccount(0)
, m_subaddress(nullptr)
, m_subaddress(new Subaddress(m_walletImpl->subaddress(), this))
, m_subaddressModel(nullptr)
, m_subaddressAccount(nullptr)
, m_subaddressAccount(new SubaddressAccount(m_walletImpl->subaddressAccount(), this))
, m_subaddressAccountModel(nullptr)
, m_refreshEnabled(false)
, m_refreshing(false)
, m_scheduler(this)
{
m_history = new TransactionHistory(m_walletImpl->history(), this);
m_addressBook = new AddressBook(m_walletImpl->addressBook(), this);
m_subaddress = new Subaddress(m_walletImpl->subaddress(), this);
m_subaddressAccount = new SubaddressAccount(m_walletImpl->subaddressAccount(), this);
m_walletListener = new WalletListenerImpl(this);
m_walletImpl->setListener(m_walletListener);
m_currentSubaddressAccount = getCacheAttribute(ATTRIBUTE_SUBADDRESS_ACCOUNT).toUInt();
@@ -1103,17 +1123,6 @@ Wallet::~Wallet()
m_walletImpl->stop();
m_scheduler.shutdownWaitForFinished();
delete m_addressBook;
m_addressBook = NULL;
delete m_history;
m_history = NULL;
delete m_addressBook;
m_addressBook = NULL;
delete m_subaddress;
m_subaddress = NULL;
delete m_subaddressAccount;
m_subaddressAccount = NULL;
//Monero::WalletManagerFactory::getWalletManager()->closeWallet(m_walletImpl);
if(status() == Status_Critical)
qDebug("Not storing wallet cache");

View File

@@ -75,7 +75,6 @@ class Wallet : public QObject, public PassprasePrompter
Q_PROPERTY(bool synchronized READ synchronized)
Q_PROPERTY(QString errorString READ errorString)
Q_PROPERTY(TransactionHistory * history READ history)
Q_PROPERTY(QString paymentId READ paymentId WRITE setPaymentId)
Q_PROPERTY(TransactionHistorySortFilterModel * historyModel READ historyModel NOTIFY historyModelChanged)
Q_PROPERTY(QString path READ path)
Q_PROPERTY(AddressBookModel * addressBookModel READ addressBookModel)
@@ -216,15 +215,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,
@@ -255,10 +252,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;
@@ -299,11 +297,6 @@ public:
//! Parse URI
Q_INVOKABLE bool parse_uri(const QString &uri, QString &address, QString &payment_id, uint64_t &amount, QString &tx_description, QString &recipient_name, QVector<QString> &unknown_parameters, QString &error);
//! saved payment id
QString paymentId() const;
void setPaymentId(const QString &paymentId);
//! Namespace your cacheAttribute keys to avoid collisions
Q_INVOKABLE bool setCacheAttribute(const QString &key, const QString &val);
Q_INVOKABLE QString getCacheAttribute(const QString &key) const;
@@ -382,7 +375,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;
@@ -415,6 +412,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);
@@ -433,7 +437,6 @@ private:
// Used for UI history view
mutable TransactionHistoryModel * m_historyModel;
mutable TransactionHistorySortFilterModel * m_historySortFilterModel;
QString m_paymentId;
AddressBook * m_addressBook;
mutable AddressBookModel * m_addressBookModel;
mutable QElapsedTimer m_daemonBlockChainHeightTime;

View File

@@ -31,6 +31,8 @@
#include "wallet/api/wallet2_api.h"
#include "zxcvbn-c/zxcvbn.h"
#include "QRCodeImageProvider.h"
#include <QClipboard>
#include <QGuiApplication>
#include <QFile>
#include <QFileInfo>
#include <QDir>
@@ -169,7 +171,7 @@ Wallet *WalletManager::createWalletFromKeys(const QString &path, const QString &
}
Wallet *WalletManager::createWalletFromDevice(const QString &path, const QString &password, NetworkType::Type nettype,
const QString &deviceName, quint64 restoreHeight, const QString &subaddressLookahead)
const QString &deviceName, quint64 restoreHeight, const QString &subaddressLookahead, quint64 kdfRounds)
{
QMutexLocker locker(&m_mutex);
WalletPassphraseListenerImpl tmpListener(this);
@@ -187,7 +189,7 @@ Wallet *WalletManager::createWalletFromDevice(const QString &path, const QString
m_currentWallet = NULL;
}
Monero::Wallet * w = m_pimpl->createWalletFromDevice(path.toStdString(), password.toStdString(), static_cast<Monero::NetworkType>(nettype),
deviceName.toStdString(), restoreHeight, subaddressLookahead.toStdString(), 1, &tmpListener);
deviceName.toStdString(), restoreHeight, subaddressLookahead.toStdString(), kdfRounds, &tmpListener);
w->setListener(nullptr);
m_currentWallet = new Wallet(w);
@@ -202,10 +204,10 @@ Wallet *WalletManager::createWalletFromDevice(const QString &path, const QString
void WalletManager::createWalletFromDeviceAsync(const QString &path, const QString &password, NetworkType::Type nettype,
const QString &deviceName, quint64 restoreHeight, const QString &subaddressLookahead)
const QString &deviceName, quint64 restoreHeight, const QString &subaddressLookahead, quint64 kdfRounds)
{
m_scheduler.run([this, path, password, nettype, deviceName, restoreHeight, subaddressLookahead] {
Wallet *wallet = createWalletFromDevice(path, password, nettype, deviceName, restoreHeight, subaddressLookahead);
m_scheduler.run([this, path, password, nettype, deviceName, restoreHeight, subaddressLookahead, kdfRounds] {
Wallet *wallet = createWalletFromDevice(path, password, nettype, deviceName, restoreHeight, subaddressLookahead, kdfRounds);
emit walletCreated(wallet);
});
}
@@ -251,7 +253,7 @@ QString WalletManager::errorString() const
return tr("Unknown error");
}
quint64 WalletManager::maximumAllowedAmount() const
quint64 WalletManager::maximumAllowedAmount()
{
return Monero::Wallet::maximumAllowedAmount();
}
@@ -266,7 +268,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 +278,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());
@@ -448,7 +461,6 @@ QUrl WalletManager::localPathToUrl(const QString &path) const
return QUrl::fromLocalFile(path);
}
#ifndef DISABLE_PASS_STRENGTH_METER
double WalletManager::getPasswordStrength(const QString &password) const
{
static const char *local_dict[] = {
@@ -463,7 +475,6 @@ double WalletManager::getPasswordStrength(const QString &password) const
ZxcvbnUnInit();
return e;
}
#endif
bool WalletManager::saveQrCode(const QString &code, const QString &path) const
{
@@ -471,6 +482,14 @@ bool WalletManager::saveQrCode(const QString &code, const QString &path) const
return QRCodeImageProvider::genQrImage(code, &size).scaled(size.expandedTo(QSize(240, 240)), Qt::KeepAspectRatio).save(path, "PNG", 100);
}
void WalletManager::saveQrCodeToClipboard(const QString &code) const
{
QClipboard *clipboard = QGuiApplication::clipboard();
QSize size;
clipboard->setImage(QRCodeImageProvider::genQrImage(code, &size).scaled(size.expandedTo(QSize(240, 240)), Qt::KeepAspectRatio), QClipboard::Clipboard);
clipboard->setImage(QRCodeImageProvider::genQrImage(code, &size).scaled(size.expandedTo(QSize(240, 240)), Qt::KeepAspectRatio), QClipboard::Selection);
}
void WalletManager::checkUpdatesAsync(
const QString &software,
const QString &subdir,

View File

@@ -103,14 +103,16 @@ public:
NetworkType::Type nettype,
const QString &deviceName,
quint64 restoreHeight = 0,
const QString &subaddressLookahead = "");
const QString &subaddressLookahead = "",
quint64 kdfRounds = 1);
Q_INVOKABLE void createWalletFromDeviceAsync(const QString &path,
const QString &password,
NetworkType::Type nettype,
const QString &deviceName,
quint64 restoreHeight = 0,
const QString &subaddressLookahead = "");
const QString &subaddressLookahead = "",
quint64 kdfRounds = 1);
/*!
* \brief closeWallet - closes current open wallet and frees memory
* \return wallet address
@@ -133,9 +135,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;
@@ -171,14 +174,13 @@ public:
Q_INVOKABLE qint64 addi(qint64 x, qint64 y) const { return x + y; }
Q_INVOKABLE qint64 subi(qint64 x, qint64 y) const { return x - y; }
#ifndef DISABLE_PASS_STRENGTH_METER
Q_INVOKABLE double getPasswordStrength(const QString &password) const;
#endif
Q_INVOKABLE QString resolveOpenAlias(const QString &address) const;
Q_INVOKABLE bool parse_uri(const QString &uri, QString &address, QString &payment_id, uint64_t &amount, QString &tx_description, QString &recipient_name, QVector<QString> &unknown_parameters, QString &error) const;
Q_INVOKABLE QVariantMap parse_uri_to_object(const QString &uri) const;
Q_INVOKABLE bool saveQrCode(const QString &, const QString &) const;
Q_INVOKABLE void saveQrCodeToClipboard(const QString &) const;
Q_INVOKABLE void checkUpdatesAsync(
const QString &software,
const QString &subdir,

View File

@@ -27,14 +27,9 @@
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "filter.h"
#include <QtGlobal>
#include <QKeyEvent>
#include <QDebug>
#ifdef QT_DEBUG
#include "private/qabstractanimation_p.h"
#endif
filter::filter(QObject *parent) :
QObject(parent)
{
@@ -91,21 +86,6 @@ bool filter::eventFilter(QObject *obj, QEvent *ev) {
case QEvent::KeyRelease: {
QKeyEvent *ke = static_cast<QKeyEvent*>(ev);
#ifdef QT_DEBUG
if(ke->key() == Qt::Key_F9){
QUnifiedTimer::instance()->setSlowModeEnabled(true);
QUnifiedTimer::instance()->setSlowdownFactor(10);
qDebug() << "Slow animations enabled";
}
if(ke->key() == Qt::Key_F10){
QUnifiedTimer::instance()->setSlowModeEnabled(false);
QUnifiedTimer::instance()->setSlowdownFactor(1);
qDebug() << "Slow animations disabled";
}
#endif
if(ke->key() == Qt::Key_Backtab)
m_backtabPressed = false;

View File

@@ -72,6 +72,9 @@
#include "qt/KeysFiles.h"
#include "qt/MoneroSettings.h"
#include "qt/NetworkAccessBlockingFactory.h"
#ifdef Q_OS_MAC
#include "qt/macoshelper.h"
#endif
// IOS exclusions
#ifndef Q_OS_IOS
@@ -123,6 +126,7 @@ 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)
@@ -132,6 +136,7 @@ Q_IMPORT_PLUGIN(QtQuickControls1Plugin)
Q_IMPORT_PLUGIN(QtQuick2DialogsPlugin)
Q_IMPORT_PLUGIN(QmlFolderListModelPlugin)
Q_IMPORT_PLUGIN(QmlSettingsPlugin)
Q_IMPORT_PLUGIN(QtLabsPlatformPlugin)
Q_IMPORT_PLUGIN(QtQuick2DialogsPrivatePlugin)
Q_IMPORT_PLUGIN(QtQuick2PrivateWidgetsPlugin)
Q_IMPORT_PLUGIN(QtQuickControls2Plugin)
@@ -177,6 +182,10 @@ int main(int argc, char *argv[])
if(qgetenv("QMLSCENE_DEVICE") == "softwarecontext")
isOpenGL = false;
#ifdef Q_OS_MAC
// macOS window tabbing is not supported
MacOSHelper::disableWindowTabbing();
#endif
// disable "QApplication: invalid style override passed" warning
if (isDesktop) qputenv("QT_STYLE_OVERRIDE", "fusion");
#ifdef Q_OS_LINUX
@@ -330,7 +339,7 @@ Verify update binary using 'shasum'-compatible (SHA256 algo) output signed by tw
// screen settings
// Mobile is designed on 128dpi
qreal ref_dpi = 128;
QRect geo = QGuiApplication::primaryScreen()->availableGeometry();
QSize screenAvailableSize = QGuiApplication::primaryScreen()->availableSize();
QRect rect = QGuiApplication::primaryScreen()->geometry();
qreal dpi = QGuiApplication::primaryScreen()->logicalDotsPerInch();
qreal physicalDpi = QGuiApplication::primaryScreen()->physicalDotsPerInch();
@@ -353,6 +362,7 @@ Verify update binary using 'shasum'-compatible (SHA256 algo) output signed by tw
qWarning().nospace().noquote() << "Qt:" << QT_VERSION_STR << " GUI:" << GUI_VERSION
<< " | screen: " << rect.width() << "x" << rect.height()
<< " - available: " << screenAvailableSize
<< " - dpi: " << dpi << " - ratio:" << calculated_ratio;
// registering types for QML
@@ -451,8 +461,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);
@@ -463,8 +473,8 @@ Verify update binary using 'shasum'-compatible (SHA256 algo) output signed by tw
engine.rootContext()->setContextProperty("isOpenGL", isOpenGL);
engine.rootContext()->setContextProperty("isTails", isTails);
engine.rootContext()->setContextProperty("screenWidth", geo.width());
engine.rootContext()->setContextProperty("screenHeight", geo.height());
engine.rootContext()->setContextProperty("screenAvailableWidth", screenAvailableSize.width());
engine.rootContext()->setContextProperty("screenAvailableHeight", screenAvailableSize.height());
#ifndef Q_OS_IOS
const QString desktopFolder = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);

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>
@@ -55,6 +61,40 @@
#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)
{
@@ -99,6 +139,26 @@ 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();
@@ -163,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
*/
@@ -43,6 +45,7 @@ public:
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

@@ -87,11 +87,6 @@ bool AddressBookModel::deleteRow(int row)
return m_addressBook->deleteRow(row);
}
int AddressBookModel::lookupPaymentID(const QString &payment_id) const
{
return m_addressBook->lookupPaymentID(payment_id);
}
QHash<int, QByteArray> AddressBookModel::roleNames() const
{
QHash<int, QByteArray> roleNames = QAbstractListModel::roleNames();

View File

@@ -52,7 +52,6 @@ public:
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
Q_INVOKABLE bool deleteRow(int row);
Q_INVOKABLE int lookupPaymentID(const QString &payment_id) const;
virtual QHash<int, QByteArray> roleNames() const override;
public slots:

View File

@@ -1,4 +0,0 @@
file(GLOB_RECURSE SRC_SOURCES *.cpp)
file(GLOB_RECURSE SRC_HEADERS *.h)

View File

@@ -28,6 +28,7 @@
#pragma once
#include <string>
#include <vector>
#include <gcrypt.h>

View File

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

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