Compare commits
635 Commits
v0.0-beta-
...
release-v0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ea8e3d0267 | ||
|
|
56868c06b5 | ||
|
|
3df70ff98c | ||
|
|
83ea363932 | ||
|
|
6d09555cd4 | ||
|
|
4d9d10013b | ||
|
|
ece743e22a | ||
|
|
86e9f3811b | ||
|
|
2bc86d1d9f | ||
|
|
fc576a8680 | ||
|
|
b8da85d0a4 | ||
|
|
3d0a571cc7 | ||
|
|
7c366ddf04 | ||
|
|
d0f3194574 | ||
|
|
98f768d2a6 | ||
|
|
77cd5a7a62 | ||
|
|
0d1b709def | ||
|
|
5f052964a9 | ||
|
|
39facceee6 | ||
|
|
c84abc7224 | ||
|
|
649f81954e | ||
|
|
1a156b8840 | ||
|
|
f7c883a6c3 | ||
|
|
31f318aaea | ||
|
|
94c92ba73c | ||
|
|
8480c70571 | ||
|
|
ee2b0fa713 | ||
|
|
9f4f2b582b | ||
|
|
d670f6d321 | ||
|
|
4ca5e82fca | ||
|
|
c29ccc13ae | ||
|
|
c04417d37b | ||
|
|
7521472325 | ||
|
|
73ba192a58 | ||
|
|
0fdc21e7fd | ||
|
|
ba0796b9ca | ||
|
|
1ce573afe2 | ||
|
|
234fd1bcda | ||
|
|
3adb29bc16 | ||
|
|
3f7e3ba3c4 | ||
|
|
a7f52db613 | ||
|
|
7f4fec7777 | ||
|
|
995a5e0046 | ||
|
|
13a65505a5 | ||
|
|
105336ba08 | ||
|
|
c39875de44 | ||
|
|
5339fbde8b | ||
|
|
47927e4822 | ||
|
|
c68c317776 | ||
|
|
b2cd48ceaf | ||
|
|
0eaebb01c4 | ||
|
|
c321147e36 | ||
|
|
27349d111d | ||
|
|
602a393d59 | ||
|
|
e9b6c510f4 | ||
|
|
5d78941712 | ||
|
|
fa27982650 | ||
|
|
f3eca6eadb | ||
|
|
009994b212 | ||
|
|
57a282c72a | ||
|
|
96808441cd | ||
|
|
6730b63018 | ||
|
|
7cc924d478 | ||
|
|
8a14e367d8 | ||
|
|
a0e38aafb2 | ||
|
|
4bac8fdb57 | ||
|
|
b41c981454 | ||
|
|
c65ee4e71c | ||
|
|
7d66cc5b25 | ||
|
|
e43b719b19 | ||
|
|
03af06718c | ||
|
|
b4ce56a994 | ||
|
|
92c0e00b12 | ||
|
|
e8bd548219 | ||
|
|
ed17399b74 | ||
|
|
04869f0aac | ||
|
|
16122d6e17 | ||
|
|
73895f5a7b | ||
|
|
535f1fc446 | ||
|
|
5d4f519a40 | ||
|
|
ff9d79da7a | ||
|
|
b8a4dab9b2 | ||
|
|
a492cb9f7e | ||
|
|
5043250a2a | ||
|
|
fe78f20c7c | ||
|
|
ecaa1a8e23 | ||
|
|
9e121fb676 | ||
|
|
62e1dc490f | ||
|
|
9037eed805 | ||
|
|
443eb47824 | ||
|
|
13753052bc | ||
|
|
08b54f69a5 | ||
|
|
037fa32c41 | ||
|
|
8e986b3a2d | ||
|
|
0cb6900295 | ||
|
|
affbb454fa | ||
|
|
a6f13f7ba2 | ||
|
|
8e14b8bc3e | ||
|
|
5cd05a51d4 | ||
|
|
c2c5f0c13d | ||
|
|
f11d2bc702 | ||
|
|
77448a6b73 | ||
|
|
a3e0589a5e | ||
|
|
41b2c282bd | ||
|
|
127790e4a1 | ||
|
|
9dc8879e2c | ||
|
|
72a7f1348f | ||
|
|
cfa2f816a5 | ||
|
|
de4ff2992e | ||
|
|
6beadba9cc | ||
|
|
6a0ed3ceae | ||
|
|
a046163477 | ||
|
|
5ec575b376 | ||
|
|
009362451d | ||
|
|
f6e7b79e81 | ||
|
|
d744d393f9 | ||
|
|
25852b4676 | ||
|
|
336726e82f | ||
|
|
afac71383b | ||
|
|
2ac9e8eabb | ||
|
|
fff5c716c8 | ||
|
|
2e53c524a1 | ||
|
|
da6aad33a4 | ||
|
|
f5450f9205 | ||
|
|
1f23df7e66 | ||
|
|
27e37f153f | ||
|
|
58f24efd39 | ||
|
|
24bd3010bf | ||
|
|
87ea145047 | ||
|
|
310df0befa | ||
|
|
a4a44d7c99 | ||
|
|
f00a181843 | ||
|
|
98b040670c | ||
|
|
f31b27d3fd | ||
|
|
8cd6f3f5b6 | ||
|
|
af1edc0c95 | ||
|
|
45106e5150 | ||
|
|
3a51c4b963 | ||
|
|
8da7c972db | ||
|
|
1c1d15821e | ||
|
|
ef4c2927b4 | ||
|
|
dd7732ce0c | ||
|
|
c750ca9507 | ||
|
|
feabe6713c | ||
|
|
a550c03a0b | ||
|
|
1336055e80 | ||
|
|
115102624e | ||
|
|
5a0adb18d3 | ||
|
|
a055293b52 | ||
|
|
a00c083ece | ||
|
|
22a769341a | ||
|
|
91757b8039 | ||
|
|
74da45766e | ||
|
|
949d85288d | ||
|
|
798b273888 | ||
|
|
e2bfe25b9d | ||
|
|
7f12d4869e | ||
|
|
b2f7058fcf | ||
|
|
06e01e3771 | ||
|
|
cbc9dd07c8 | ||
|
|
6633d309b5 | ||
|
|
1e7fbe5cb0 | ||
|
|
05084422a5 | ||
|
|
57ab7daa03 | ||
|
|
fc0a44cabc | ||
|
|
30e403fe58 | ||
|
|
5297b23248 | ||
|
|
96c8df23a4 | ||
|
|
06b12d167b | ||
|
|
4ca35af11a | ||
|
|
a154eabf87 | ||
|
|
2f5a865028 | ||
|
|
87d444d128 | ||
|
|
10c3b8c116 | ||
|
|
dcc633b716 | ||
|
|
b4f01b9f6a | ||
|
|
f6535354e4 | ||
|
|
60254812c8 | ||
|
|
d1b1823a50 | ||
|
|
fb456fc5fe | ||
|
|
508b512c45 | ||
|
|
b1d24f8aa7 | ||
|
|
6ba2548273 | ||
|
|
615ef5342e | ||
|
|
53e87b4a35 | ||
|
|
716010a869 | ||
|
|
fb3a6182fc | ||
|
|
4ee23b2218 | ||
|
|
d730766479 | ||
|
|
e231a1b63f | ||
|
|
0836bd9cfd | ||
|
|
6e381c3857 | ||
|
|
12573652a0 | ||
|
|
6262770e6e | ||
|
|
7fbd1cf1ca | ||
|
|
88b1403020 | ||
|
|
d782eacfd6 | ||
|
|
379b02c80b | ||
|
|
b3877868a3 | ||
|
|
716106c23e | ||
|
|
c3ae7f8c80 | ||
|
|
d85dfa4fae | ||
|
|
7c5cf985b5 | ||
|
|
5969284de8 | ||
|
|
61266ca17e | ||
|
|
84c8f790b6 | ||
|
|
b2827ca1dd | ||
|
|
8719caad1b | ||
|
|
bd2a336c5e | ||
|
|
46d573e697 | ||
|
|
9c4c34d502 | ||
|
|
413d064127 | ||
|
|
db306ca823 | ||
|
|
b4cab574bc | ||
|
|
f05f0b73c3 | ||
|
|
6fbba9f88c | ||
|
|
b1f5d69ce5 | ||
|
|
55116a0963 | ||
|
|
d759e0ee44 | ||
|
|
f6f8e219e7 | ||
|
|
d884edf136 | ||
|
|
439372ed5e | ||
|
|
476fdd4ebe | ||
|
|
9fb7c19b9b | ||
|
|
caf7b7fc6b | ||
|
|
2ce455940d | ||
|
|
e5719791bd | ||
|
|
57ae6df949 | ||
|
|
9f3bd9d896 | ||
|
|
9e3b3d89b6 | ||
|
|
eb24356a95 | ||
|
|
5952ff96d7 | ||
|
|
89fb48138f | ||
|
|
60890b9185 | ||
|
|
97f9fb6f01 | ||
|
|
a3c9c98652 | ||
|
|
48a7596953 | ||
|
|
93e20be247 | ||
|
|
a0233f103e | ||
|
|
df78427745 | ||
|
|
a32b30e98b | ||
|
|
f0a441301b | ||
|
|
174d6ad019 | ||
|
|
2e8051067f | ||
|
|
deb75afb7e | ||
|
|
62089df6e7 | ||
|
|
2542b14534 | ||
|
|
42fb1ed51d | ||
|
|
23a3b1265a | ||
|
|
1fe0600e1e | ||
|
|
a9e975f2cd | ||
|
|
1d74fa6f47 | ||
|
|
d920b20168 | ||
|
|
ec5c73e8aa | ||
|
|
f3dfd18641 | ||
|
|
3ecffbc767 | ||
|
|
b75fee7a68 | ||
|
|
94ca32a164 | ||
|
|
2839bcc7fb | ||
|
|
91e01d5470 | ||
|
|
760f34579f | ||
|
|
19157590a5 | ||
|
|
172243cdad | ||
|
|
d42d2dd742 | ||
|
|
10b00f8778 | ||
|
|
064c9805f6 | ||
|
|
5f2e5b041c | ||
|
|
7ab5511de3 | ||
|
|
51074a8fe6 | ||
|
|
43a33e717d | ||
|
|
69e037ba4d | ||
|
|
cdb9376b85 | ||
|
|
24c17a9fe3 | ||
|
|
628483c310 | ||
|
|
aeea9ad324 | ||
|
|
8655076b92 | ||
|
|
4310fb096b | ||
|
|
62fe3820e2 | ||
|
|
e4aa338869 | ||
|
|
f22e5fdd7b | ||
|
|
ed28144ae8 | ||
|
|
0090303a18 | ||
|
|
d6dd97f308 | ||
|
|
53d7962eaa | ||
|
|
58e68be613 | ||
|
|
ce8e5fe714 | ||
|
|
577726c184 | ||
|
|
e4a114321f | ||
|
|
2b24c91bc5 | ||
|
|
692f927903 | ||
|
|
35cd788968 | ||
|
|
82cb50994c | ||
|
|
897bc582f0 | ||
|
|
b0d0974561 | ||
|
|
fd4619628c | ||
|
|
5cf84ff1f5 | ||
|
|
7960241306 | ||
|
|
3c8a552522 | ||
|
|
6a666ead39 | ||
|
|
1918c5e24a | ||
|
|
c45cc3de41 | ||
|
|
6364530b86 | ||
|
|
b757cc28b8 | ||
|
|
b8745299ba | ||
|
|
1b021c599b | ||
|
|
4c2f78a78b | ||
|
|
ea1d2c3731 | ||
|
|
a2f01ea541 | ||
|
|
1a1a7a991b | ||
|
|
e3daa4b16e | ||
|
|
c30586ccc8 | ||
|
|
c9825c5c5b | ||
|
|
ab809b0df9 | ||
|
|
5589ef7fc9 | ||
|
|
b611871940 | ||
|
|
27bc424f04 | ||
|
|
f544eceaa5 | ||
|
|
8429cec6c3 | ||
|
|
632d347d07 | ||
|
|
7a79d318a6 | ||
|
|
3273d1f935 | ||
|
|
9f01082937 | ||
|
|
05c15930c3 | ||
|
|
a6f3510ee4 | ||
|
|
10d32032e9 | ||
|
|
9e62e1e097 | ||
|
|
fed4dd4654 | ||
|
|
0f3f6d215c | ||
|
|
bd959085f2 | ||
|
|
630a852669 | ||
|
|
2a8419c7cd | ||
|
|
b43f88cece | ||
|
|
c75d3cf9ec | ||
|
|
7987455fcf | ||
|
|
694352c1df | ||
|
|
03eaaa46e0 | ||
|
|
64d1e1546a | ||
|
|
fb014d8aff | ||
|
|
1ff4e9030b | ||
|
|
4fe6b1fd0b | ||
|
|
27e8090096 | ||
|
|
e3f81b9c49 | ||
|
|
2e3350c060 | ||
|
|
5db9bd9fdd | ||
|
|
223f09dc94 | ||
|
|
01e735cc0e | ||
|
|
bce496b8d1 | ||
|
|
988e299290 | ||
|
|
cc86720936 | ||
|
|
0e8b28b958 | ||
|
|
30cfe1041a | ||
|
|
18eb7a02cc | ||
|
|
e4bb7bed98 | ||
|
|
cebf4a01a8 | ||
|
|
afbfbeaa49 | ||
|
|
339d78c4ab | ||
|
|
62f016387f | ||
|
|
9859f33914 | ||
|
|
4e29c1474e | ||
|
|
30f87a1019 | ||
|
|
9fb884e5a6 | ||
|
|
c9d6267f67 | ||
|
|
9b633824d5 | ||
|
|
573b284017 | ||
|
|
14ea15e870 | ||
|
|
f11ec2d0bd | ||
|
|
36f245e983 | ||
|
|
6e2e8a55c2 | ||
|
|
50ee218198 | ||
|
|
5b1588b077 | ||
|
|
5d6e0f5851 | ||
|
|
2ea54a2401 | ||
|
|
578cafb059 | ||
|
|
9c0002ad9a | ||
|
|
8c17a8c388 | ||
|
|
3d9ffca016 | ||
|
|
c7435c5dfa | ||
|
|
cf364206de | ||
|
|
114ce41fcc | ||
|
|
8dc95a17e6 | ||
|
|
d9a2b1aa60 | ||
|
|
e4314ddb4c | ||
|
|
44bcb3d06c | ||
|
|
e90c18603a | ||
|
|
d5e1d3ea60 | ||
|
|
97bda6d597 | ||
|
|
05ef5eabf6 | ||
|
|
6e966f8ae0 | ||
|
|
2bbb585fc7 | ||
|
|
677432f634 | ||
|
|
67e504288f | ||
|
|
e8875e0e1f | ||
|
|
d354d4aa54 | ||
|
|
d855cb1542 | ||
|
|
d1202e44eb | ||
|
|
08d5730fbe | ||
|
|
92a5781b6a | ||
|
|
9ac8e26a48 | ||
|
|
0b017ff954 | ||
|
|
a34b7c7136 | ||
|
|
be09e3e596 | ||
|
|
ebcab010bb | ||
|
|
e826f7c1ec | ||
|
|
c524e226de | ||
|
|
86a387046f | ||
|
|
75bb620cb6 | ||
|
|
0f69ca4bff | ||
|
|
3f0f942779 | ||
|
|
f738b6ac67 | ||
|
|
fc6a214197 | ||
|
|
4c1bf7dcf8 | ||
|
|
8d35711448 | ||
|
|
1c79aaff87 | ||
|
|
4ff41181dc | ||
|
|
00aa23162c | ||
|
|
1f1aa9859b | ||
|
|
80210376f3 | ||
|
|
df60c8190b | ||
|
|
2ed59f41ed | ||
|
|
ce10016408 | ||
|
|
53c86adbbe | ||
|
|
023d96bc3e | ||
|
|
3adeab87ed | ||
|
|
2d6ddf043e | ||
|
|
a0fcf59348 | ||
|
|
465f6bfe27 | ||
|
|
2ca2376d45 | ||
|
|
6120013ae2 | ||
|
|
65d9bde498 | ||
|
|
6a40d38b93 | ||
|
|
6075592f62 | ||
|
|
fe6a095175 | ||
|
|
c909ab794a | ||
|
|
3759e276b2 | ||
|
|
20517cfd4d | ||
|
|
faacd3d6a1 | ||
|
|
97362504e8 | ||
|
|
5bfa9b5734 | ||
|
|
3ed4dee00e | ||
|
|
54ee0344b8 | ||
|
|
166a285a28 | ||
|
|
69479efcf3 | ||
|
|
27541f6ec9 | ||
|
|
2e8306b341 | ||
|
|
f33a824708 | ||
|
|
c6688dc876 | ||
|
|
de1d7046ee | ||
|
|
0e9ab11213 | ||
|
|
4a216ff786 | ||
|
|
57fa9830b6 | ||
|
|
87f55992f0 | ||
|
|
d589ab4058 | ||
|
|
34415bb660 | ||
|
|
cc06fab125 | ||
|
|
c94bd2ff72 | ||
|
|
20833579e9 | ||
|
|
08ceb5eba0 | ||
|
|
ad58e0008b | ||
|
|
57a556a495 | ||
|
|
ccdea1bf57 | ||
|
|
fdc71d2b18 | ||
|
|
ea7fab6efe | ||
|
|
1869e81883 | ||
|
|
fa4078f38c | ||
|
|
e145793d2f | ||
|
|
36cd7a625f | ||
|
|
3640bedeee | ||
|
|
2901a33698 | ||
|
|
4bcfe63c57 | ||
|
|
02ab113762 | ||
|
|
16be0ee344 | ||
|
|
78302be193 | ||
|
|
c6dc9a20e7 | ||
|
|
756a821f41 | ||
|
|
8a0163f14a | ||
|
|
40540cb38a | ||
|
|
fb743a0532 | ||
|
|
168e3544d0 | ||
|
|
979acf774a | ||
|
|
b80d9498ef | ||
|
|
6965b0af19 | ||
|
|
99230e3ff1 | ||
|
|
739d24efb4 | ||
|
|
f2a583fd49 | ||
|
|
488e4e2b86 | ||
|
|
7e8b6de186 | ||
|
|
6c8e770a61 | ||
|
|
e16180c2a5 | ||
|
|
8060307c62 | ||
|
|
7ab3373335 | ||
|
|
0b41fbc858 | ||
|
|
2586404339 | ||
|
|
eb909e1ae7 | ||
|
|
cb3281dee8 | ||
|
|
9dbbd4c9bc | ||
|
|
93d2eb5e1a | ||
|
|
faeead242c | ||
|
|
4e2e262f6a | ||
|
|
f1327ace32 | ||
|
|
43d5bd3e2d | ||
|
|
be564921d8 | ||
|
|
ef9bf72b52 | ||
|
|
e0e2b40682 | ||
|
|
f4e01e5756 | ||
|
|
501560940b | ||
|
|
a80df427e7 | ||
|
|
3cbad7350b | ||
|
|
58bcc3640c | ||
|
|
04ff16ddb2 | ||
|
|
c5c2a40ef5 | ||
|
|
b3232dc26f | ||
|
|
26be7fbd46 | ||
|
|
0e70e63e0a | ||
|
|
1ef1a140b7 | ||
|
|
a81a071d2d | ||
|
|
7b94a47350 | ||
|
|
bded77a22b | ||
|
|
de14886376 | ||
|
|
9425b77030 | ||
|
|
a52156627d | ||
|
|
ce87a1c4db | ||
|
|
4fb4bde34b | ||
|
|
1acd4a7ac8 | ||
|
|
2d12a3cf3d | ||
|
|
16f5889a15 | ||
|
|
c51a28f206 | ||
|
|
58147a24cf | ||
|
|
cf95742433 | ||
|
|
d4a40499ac | ||
|
|
ecd6c7a0ae | ||
|
|
4cc838f1ff | ||
|
|
8df270cc4b | ||
|
|
1d7a1f6d53 | ||
|
|
ef1d7f92f7 | ||
|
|
2e925b530b | ||
|
|
39f9d5a116 | ||
|
|
8482481478 | ||
|
|
61f4db61ec | ||
|
|
6d73fba14c | ||
|
|
955d13ef0a | ||
|
|
2d907c02f0 | ||
|
|
160e5c480a | ||
|
|
32a81517d6 | ||
|
|
e7b33347e7 | ||
|
|
d8ac731dd2 | ||
|
|
05e2472d93 | ||
|
|
4f44407187 | ||
|
|
2c69d3b726 | ||
|
|
4eedef048d | ||
|
|
adaa8cb806 | ||
|
|
6a19330e55 | ||
|
|
fb8d9bd5dc | ||
|
|
ea8bc5b56d | ||
|
|
d4b3834bce | ||
|
|
7f8d4ac3d2 | ||
|
|
de63e93024 | ||
|
|
977f5125e6 | ||
|
|
7f9cc73485 | ||
|
|
e08871a77e | ||
|
|
98c3d6897d | ||
|
|
98ca4f1a70 | ||
|
|
b538baa8d8 | ||
|
|
ae5c21ef17 | ||
|
|
24ccd27d79 | ||
|
|
15c79df378 | ||
|
|
fd983955b4 | ||
|
|
8f56e98397 | ||
|
|
842e4df223 | ||
|
|
e0be6d45c5 | ||
|
|
0c0de906c2 | ||
|
|
fdf0652e37 | ||
|
|
5981e9537b | ||
|
|
4a2266b295 | ||
|
|
20d3c301e7 | ||
|
|
7cbd61dae2 | ||
|
|
e8a47e322d | ||
|
|
b5ade0d9d1 | ||
|
|
a1c5e7fed2 | ||
|
|
a76067296e | ||
|
|
a8f30212d4 | ||
|
|
ad5115ac3c | ||
|
|
205bfcdd7b | ||
|
|
6034eaffc8 | ||
|
|
593839a374 | ||
|
|
8490c69692 | ||
|
|
a8e90069d6 | ||
|
|
e286bd1422 | ||
|
|
6437723772 | ||
|
|
1532c5638f | ||
|
|
ae537b6764 | ||
|
|
1ced5e34b6 | ||
|
|
3badb12ea3 | ||
|
|
24170f00cc | ||
|
|
b3424f73a8 | ||
|
|
f3e20e746e | ||
|
|
5c1bd85204 | ||
|
|
3c6c65e25e | ||
|
|
ee9888d9b6 | ||
|
|
b02751344a | ||
|
|
0cb9747547 | ||
|
|
145d753b2c | ||
|
|
8f95e95b21 | ||
|
|
e482135ded | ||
|
|
09d252d43b | ||
|
|
dad9c82166 | ||
|
|
6ce83c5ec2 | ||
|
|
ba8decca3f | ||
|
|
427d9e2645 | ||
|
|
84453912b1 | ||
|
|
ab927615d8 | ||
|
|
bb303d0063 | ||
|
|
eff31f07d9 | ||
|
|
2ce0024a10 | ||
|
|
bd07a990fb | ||
|
|
f012e4d968 | ||
|
|
192bfc70b0 | ||
|
|
f2aefeebb3 | ||
|
|
a526619f4b | ||
|
|
94e8f3ac4c | ||
|
|
932d5bee47 | ||
|
|
1cd7dd622f | ||
|
|
10ac65ffb1 | ||
|
|
4406d4bbaa | ||
|
|
c2a57f704b | ||
|
|
fdbd119445 | ||
|
|
80f7b1f96e | ||
|
|
1c5899731c | ||
|
|
d831395013 | ||
|
|
119832a55b | ||
|
|
d8f9e7360f | ||
|
|
3b1ad0be27 | ||
|
|
05434a994f | ||
|
|
f45099b398 | ||
|
|
7573f370b3 | ||
|
|
2eebe67005 |
3
.gitignore
vendored
@@ -1,4 +1,5 @@
|
||||
*.user
|
||||
*.user.*
|
||||
translations/*.qm
|
||||
build
|
||||
build
|
||||
version.js
|
||||
|
||||
4
.gitmodules
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
[submodule "monero"]
|
||||
path = monero
|
||||
url = https://github.com/monero-project/monero
|
||||
ignore = all
|
||||
@@ -90,7 +90,6 @@ Rectangle {
|
||||
height: 20
|
||||
font.family: "Arial"
|
||||
font.pixelSize: 12
|
||||
font.letterSpacing: -1
|
||||
elide: Text.ElideRight
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
verticalAlignment: Text.AlignBottom
|
||||
@@ -104,7 +103,6 @@ Rectangle {
|
||||
height: 20
|
||||
font.family: "Arial"
|
||||
font.pixelSize: 18
|
||||
font.letterSpacing: -1
|
||||
elide: Text.ElideRight
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
verticalAlignment: Text.AlignBottom
|
||||
@@ -128,7 +126,6 @@ Rectangle {
|
||||
height: 20
|
||||
font.family: "Arial"
|
||||
font.pixelSize: 12
|
||||
font.letterSpacing: -1
|
||||
elide: Text.ElideRight
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
verticalAlignment: Text.AlignBottom
|
||||
@@ -142,7 +139,6 @@ Rectangle {
|
||||
height: 20
|
||||
font.family: "Arial"
|
||||
font.pixelSize: 14
|
||||
font.letterSpacing: -1
|
||||
elide: Text.ElideRight
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
verticalAlignment: Text.AlignBottom
|
||||
|
||||
2
LICENSE
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2014-2015, The Monero Project
|
||||
Copyright (c) 2014-2017, The Monero Project
|
||||
|
||||
All rights reserved.
|
||||
|
||||
|
||||
129
LeftPanel.qml
@@ -35,9 +35,11 @@ Rectangle {
|
||||
id: panel
|
||||
|
||||
property alias unlockedBalanceText: unlockedBalanceText.text
|
||||
property alias balanceLabelText: balanceLabel.text
|
||||
property alias balanceText: balanceText.text
|
||||
property alias networkStatus : networkStatus
|
||||
property alias progressBar : progressBar
|
||||
property alias minutesToUnlockTxt: unlockedBalanceLabel.text
|
||||
|
||||
signal dashboardClicked()
|
||||
signal historyClicked()
|
||||
@@ -60,20 +62,22 @@ Rectangle {
|
||||
else if(pos === "TxKey") menuColumn.previousButton = txkeyButton
|
||||
else if(pos === "Sign") menuColumn.previousButton = signButton
|
||||
else if(pos === "Settings") menuColumn.previousButton = settingsButton
|
||||
else if(pos === "Advanced") menuColumn.previousButton = advancedButton
|
||||
|
||||
menuColumn.previousButton.checked = true
|
||||
}
|
||||
|
||||
width: 260
|
||||
width: (isMobile)? appWindow.width : 260
|
||||
color: "#FFFFFF"
|
||||
|
||||
// Item with monero logo
|
||||
Item {
|
||||
visible: !isMobile
|
||||
id: logoItem
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 40
|
||||
anchors.topMargin: (persistentSettings.customDecorations)? 66 : 36
|
||||
height: logo.implicitHeight
|
||||
|
||||
Image {
|
||||
@@ -83,6 +87,18 @@ Rectangle {
|
||||
source: "images/moneroLogo.png"
|
||||
}
|
||||
|
||||
Text {
|
||||
id: testnetLabel
|
||||
visible: persistentSettings.testnet
|
||||
text: qsTr("Testnet") + translationManager.emptyString
|
||||
anchors.top: logo.bottom
|
||||
anchors.topMargin: 5
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 50
|
||||
font.bold: true
|
||||
color: "red"
|
||||
}
|
||||
|
||||
/* Disable twitter/news panel
|
||||
Image {
|
||||
anchors.left: parent.left
|
||||
@@ -100,22 +116,26 @@ Rectangle {
|
||||
}
|
||||
|
||||
|
||||
|
||||
Column {
|
||||
visible: !isMobile
|
||||
id: column1
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: logoItem.bottom
|
||||
anchors.topMargin: 30
|
||||
anchors.topMargin: 26
|
||||
spacing: 5
|
||||
|
||||
Label {
|
||||
visible: !isMobile
|
||||
id: balanceLabel
|
||||
text: qsTr("Balance") + translationManager.emptyString
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 50
|
||||
tipText: qsTr("Test tip 1<br/><br/>line 2") + translationManager.emptyString
|
||||
}
|
||||
|
||||
Row {
|
||||
visible: !isMobile
|
||||
Item {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
height: 26
|
||||
@@ -128,12 +148,21 @@ Rectangle {
|
||||
}
|
||||
|
||||
Text {
|
||||
visible: !isMobile
|
||||
id: balanceText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
font.family: "Arial"
|
||||
font.pixelSize: 26
|
||||
color: "#000000"
|
||||
text: "N/A"
|
||||
// dynamically adjust text size
|
||||
font.pixelSize: {
|
||||
var digits = text.split('.')[0].length
|
||||
var defaultSize = 25;
|
||||
if(digits > 2) {
|
||||
return defaultSize - 1.1*digits
|
||||
}
|
||||
return defaultSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,10 +173,10 @@ Rectangle {
|
||||
}
|
||||
|
||||
Label {
|
||||
id: unlockedBalanceLabel
|
||||
text: qsTr("Unlocked balance") + translationManager.emptyString
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 50
|
||||
tipText: qsTr("Test tip 2<br/><br/>line 2") + translationManager.emptyString
|
||||
}
|
||||
|
||||
Text {
|
||||
@@ -155,12 +184,21 @@ Rectangle {
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 50
|
||||
font.family: "Arial"
|
||||
font.pixelSize: 18
|
||||
color: "#000000"
|
||||
text: "N/A"
|
||||
// dynamically adjust text size
|
||||
font.pixelSize: {
|
||||
var digits = text.split('.')[0].length
|
||||
var defaultSize = 18;
|
||||
if(digits > 3) {
|
||||
return defaultSize - 0.6*digits
|
||||
}
|
||||
return defaultSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Rectangle {
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
@@ -177,16 +215,26 @@ Rectangle {
|
||||
color: "#DBDBDB"
|
||||
}
|
||||
|
||||
|
||||
|
||||
Rectangle {
|
||||
id: menuRect
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.top: column1.bottom
|
||||
anchors.topMargin: 50
|
||||
anchors.top: (isMobile)? parent.top : column1.bottom
|
||||
anchors.topMargin: (isMobile)? 0 : 25
|
||||
color: "#1C1C1C"
|
||||
|
||||
|
||||
Flickable {
|
||||
contentHeight: 500
|
||||
anchors.fill: parent
|
||||
clip: true
|
||||
|
||||
|
||||
Column {
|
||||
|
||||
id: menuColumn
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
@@ -239,6 +287,7 @@ Rectangle {
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
visible: transferButton.present
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.leftMargin: 16
|
||||
@@ -264,6 +313,7 @@ Rectangle {
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
visible: addressBookButton.present
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.leftMargin: 16
|
||||
@@ -286,6 +336,7 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
Rectangle {
|
||||
visible: receiveButton.present
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.leftMargin: 16
|
||||
@@ -309,6 +360,7 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
Rectangle {
|
||||
visible: historyButton.present
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.leftMargin: 16
|
||||
@@ -316,7 +368,29 @@ Rectangle {
|
||||
height: 1
|
||||
}
|
||||
|
||||
/* // ------------- Mining tab ---------------
|
||||
// ------------- Advanced tab ---------------
|
||||
MenuButton {
|
||||
id: advancedButton
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
text: qsTr("Advanced") + translationManager.emptyString
|
||||
symbol: qsTr("D") + translationManager.emptyString
|
||||
dotColor: "#FFD781"
|
||||
onClicked: {
|
||||
parent.previousButton.checked = false
|
||||
parent.previousButton = advancedButton
|
||||
}
|
||||
}
|
||||
Rectangle {
|
||||
visible: advancedButton.present
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.leftMargin: 16
|
||||
color: "#505050"
|
||||
height: 1
|
||||
}
|
||||
|
||||
// ------------- Mining tab ---------------
|
||||
MenuButton {
|
||||
id: miningButton
|
||||
anchors.left: parent.left
|
||||
@@ -324,6 +398,7 @@ Rectangle {
|
||||
text: qsTr("Mining") + translationManager.emptyString
|
||||
symbol: qsTr("M") + translationManager.emptyString
|
||||
dotColor: "#FFD781"
|
||||
under: advancedButton
|
||||
onClicked: {
|
||||
parent.previousButton.checked = false
|
||||
parent.previousButton = miningButton
|
||||
@@ -332,34 +407,13 @@ Rectangle {
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
visible: miningButton.present
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.leftMargin: 16
|
||||
color: miningButton.checked || settingsButton.checked ? "#1C1C1C" : "#505050"
|
||||
height: 1
|
||||
}
|
||||
*/
|
||||
// ------------- Advanced tab ---------------
|
||||
MenuButton {
|
||||
id: advancedButton
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
text: qsTr("Advanced") + translationManager.emptyString
|
||||
symbol: qsTr("A") + translationManager.emptyString
|
||||
dotColor: "#AAFFBB"
|
||||
onClicked: {
|
||||
parent.previousButton.checked = false
|
||||
parent.previousButton = advancedButton
|
||||
}
|
||||
}
|
||||
Rectangle {
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.leftMargin: 16
|
||||
color: "#505050"
|
||||
height: 1
|
||||
}
|
||||
|
||||
// ------------- TxKey tab ---------------
|
||||
MenuButton {
|
||||
id: txkeyButton
|
||||
@@ -367,7 +421,7 @@ Rectangle {
|
||||
anchors.right: parent.right
|
||||
text: qsTr("Check payment") + translationManager.emptyString
|
||||
symbol: qsTr("K") + translationManager.emptyString
|
||||
dotColor: "#AAFFBB"
|
||||
dotColor: "#FFD781"
|
||||
under: advancedButton
|
||||
onClicked: {
|
||||
parent.previousButton.checked = false
|
||||
@@ -376,6 +430,7 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
Rectangle {
|
||||
visible: txkeyButton.present
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.leftMargin: 16
|
||||
@@ -390,7 +445,7 @@ Rectangle {
|
||||
anchors.right: parent.right
|
||||
text: qsTr("Sign/verify") + translationManager.emptyString
|
||||
symbol: qsTr("I") + translationManager.emptyString
|
||||
dotColor: "#AAFFBB"
|
||||
dotColor: "#FFD781"
|
||||
under: advancedButton
|
||||
onClicked: {
|
||||
parent.previousButton.checked = false
|
||||
@@ -399,6 +454,7 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
Rectangle {
|
||||
visible: signButton.present
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.leftMargin: 16
|
||||
@@ -422,6 +478,8 @@ Rectangle {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
NetworkStatusItem {
|
||||
id: networkStatus
|
||||
anchors.left: parent.left
|
||||
@@ -437,6 +495,9 @@ Rectangle {
|
||||
anchors.bottom: parent.bottom
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// indicate disabled state
|
||||
// Desaturate {
|
||||
// anchors.fill: parent
|
||||
|
||||
14
MainApp.cpp
Normal file
@@ -0,0 +1,14 @@
|
||||
#include "MainApp.h"
|
||||
#include <QCloseEvent>
|
||||
|
||||
bool MainApp::event (QEvent *event)
|
||||
{
|
||||
// Catch application exit event and signal to qml app to handle exit
|
||||
if(event->type() == QEvent::Close) {
|
||||
event->ignore();
|
||||
emit closing();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
18
MainApp.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifndef MAINAPP_H
|
||||
#define MAINAPP_H
|
||||
#include <QApplication>
|
||||
|
||||
class MainApp : public QApplication
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
MainApp(int &argc, char** argv) : QApplication(argc, argv) {};
|
||||
private:
|
||||
bool event(QEvent *e);
|
||||
signals:
|
||||
void closing();
|
||||
};
|
||||
|
||||
#endif // MAINAPP_H
|
||||
|
||||
|
||||
181
MiddlePanel.qml
@@ -29,6 +29,7 @@
|
||||
|
||||
import QtQml 2.0
|
||||
import QtQuick 2.2
|
||||
//import QtQuick.Controls 2.0
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Layouts 1.1
|
||||
import QtGraphicalEffects 1.0
|
||||
@@ -41,9 +42,13 @@ Rectangle {
|
||||
|
||||
property Item currentView
|
||||
property Item previousView
|
||||
property bool basicMode : false
|
||||
property bool basicMode : isMobile
|
||||
property string balanceLabelText: qsTr("Balance") + translationManager.emptyString
|
||||
property string balanceText
|
||||
property string unlockedBalanceLabelText: qsTr("Unlocked Balance") + translationManager.emptyString
|
||||
property string unlockedBalanceText
|
||||
property int minHeight: (appWindow.height > 800) ? appWindow.height : 800
|
||||
// property int headerHeight: header.height
|
||||
|
||||
property Transfer transferView: Transfer { }
|
||||
property Receive receiveView: Receive { }
|
||||
@@ -51,6 +56,7 @@ Rectangle {
|
||||
property History historyView: History { }
|
||||
property Sign signView: Sign { }
|
||||
property Settings settingsView: Settings { }
|
||||
property Mining miningView: Mining { }
|
||||
property AddressBook addressBookView: AddressBook { }
|
||||
|
||||
|
||||
@@ -70,7 +76,6 @@ Rectangle {
|
||||
previousView = currentView
|
||||
if (currentView) {
|
||||
stackView.replace(currentView)
|
||||
|
||||
// Component.onCompleted is called before wallet is initilized
|
||||
if (typeof currentView.onPageCompleted === "function") {
|
||||
currentView.onPageCompleted();
|
||||
@@ -123,27 +128,35 @@ Rectangle {
|
||||
name: "History"
|
||||
PropertyChanges { target: root; currentView: historyView }
|
||||
PropertyChanges { target: historyView; model: appWindow.currentWallet ? appWindow.currentWallet.historyModel : null }
|
||||
PropertyChanges { target: mainFlickable; contentHeight: minHeight }
|
||||
}, State {
|
||||
name: "Transfer"
|
||||
PropertyChanges { target: root; currentView: transferView }
|
||||
PropertyChanges { target: mainFlickable; contentHeight: 1000 }
|
||||
}, State {
|
||||
name: "Receive"
|
||||
PropertyChanges { target: root; currentView: receiveView }
|
||||
PropertyChanges { target: mainFlickable; contentHeight: minHeight }
|
||||
}, State {
|
||||
name: "TxKey"
|
||||
PropertyChanges { target: root; currentView: txkeyView }
|
||||
PropertyChanges { target: mainFlickable; contentHeight: minHeight }
|
||||
}, State {
|
||||
name: "AddressBook"
|
||||
PropertyChanges { target: root; currentView: addressBookView }
|
||||
PropertyChanges { target: mainFlickable; contentHeight: minHeight }
|
||||
}, State {
|
||||
name: "Sign"
|
||||
PropertyChanges { target: root; currentView: signView }
|
||||
PropertyChanges { target: mainFlickable; contentHeight: minHeight }
|
||||
}, State {
|
||||
name: "Settings"
|
||||
PropertyChanges { target: root; currentView: settingsView }
|
||||
PropertyChanges { target: mainFlickable; contentHeight: 1200 }
|
||||
}, State {
|
||||
name: "Mining"
|
||||
PropertyChanges { /*TODO*/ }
|
||||
PropertyChanges { target: root; currentView: miningView }
|
||||
PropertyChanges { target: mainFlickable; contentHeight: minHeight }
|
||||
}
|
||||
]
|
||||
|
||||
@@ -169,139 +182,47 @@ Rectangle {
|
||||
anchors.topMargin: appWindow.persistentSettings.customDecorations ? 30 : 0
|
||||
spacing: 0
|
||||
|
||||
|
||||
// BasicPanel header
|
||||
Rectangle {
|
||||
id: header
|
||||
anchors.leftMargin: 1
|
||||
anchors.rightMargin: 1
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 64
|
||||
color: "#FFFFFF"
|
||||
visible: basicMode
|
||||
|
||||
Image {
|
||||
id: logo
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.verticalCenterOffset: -5
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: appWindow.persistentSettings.customDecorations ? 20 : 40
|
||||
source: "images/moneroLogo2.png"
|
||||
}
|
||||
|
||||
Grid {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.top: parent.top
|
||||
anchors.right: parent.right
|
||||
anchors.topMargin: 10
|
||||
width: 256
|
||||
columns: 3
|
||||
|
||||
Text {
|
||||
|
||||
width: 116
|
||||
height: 20
|
||||
font.family: "Arial"
|
||||
font.pixelSize: 12
|
||||
font.letterSpacing: -1
|
||||
elide: Text.ElideRight
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
verticalAlignment: Text.AlignBottom
|
||||
color: "#535353"
|
||||
text: qsTr("Balance:")
|
||||
}
|
||||
|
||||
Text {
|
||||
id: balanceText
|
||||
width: 110
|
||||
height: 20
|
||||
font.family: "Arial"
|
||||
font.pixelSize: 18
|
||||
font.letterSpacing: -1
|
||||
elide: Text.ElideRight
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
verticalAlignment: Text.AlignBottom
|
||||
color: "#000000"
|
||||
text: root.balanceText
|
||||
}
|
||||
|
||||
Item {
|
||||
height: 20
|
||||
width: 20
|
||||
|
||||
Image {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: parent.left
|
||||
source: "images/lockIcon.png"
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
width: 116
|
||||
height: 20
|
||||
font.family: "Arial"
|
||||
font.pixelSize: 12
|
||||
font.letterSpacing: -1
|
||||
elide: Text.ElideRight
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
verticalAlignment: Text.AlignBottom
|
||||
color: "#535353"
|
||||
text: qsTr("Unlocked Balance:")
|
||||
}
|
||||
|
||||
Text {
|
||||
id: availableBalanceText
|
||||
width: 110
|
||||
height: 20
|
||||
font.family: "Arial"
|
||||
font.pixelSize: 14
|
||||
font.letterSpacing: -1
|
||||
elide: Text.ElideRight
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
verticalAlignment: Text.AlignBottom
|
||||
color: "#000000"
|
||||
text: root.unlockedBalanceText
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
height: 1
|
||||
color: "#DBDBDB"
|
||||
}
|
||||
}
|
||||
|
||||
// Views container
|
||||
StackView {
|
||||
id: stackView
|
||||
initialItem: transferView
|
||||
anchors.topMargin: 30
|
||||
Flickable {
|
||||
id: mainFlickable
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
anchors.margins: 4
|
||||
clip: true // otherwise animation will affect left panel
|
||||
clip: true
|
||||
// Disabled scrollbars, gives crash on startup on windows
|
||||
// ScrollIndicator.vertical: ScrollIndicator { }
|
||||
// ScrollBar.vertical: ScrollBar { } // uncomment to test
|
||||
|
||||
delegate: StackViewDelegate {
|
||||
pushTransition: StackViewTransition {
|
||||
PropertyAnimation {
|
||||
target: enterItem
|
||||
property: "x"
|
||||
from: 0 - target.width
|
||||
to: 0
|
||||
duration: 300
|
||||
}
|
||||
PropertyAnimation {
|
||||
target: exitItem
|
||||
property: "x"
|
||||
from: 0
|
||||
to: target.width
|
||||
duration: 300
|
||||
// Views container
|
||||
StackView {
|
||||
id: stackView
|
||||
initialItem: transferView
|
||||
// anchors.topMargin: 30
|
||||
// Layout.fillWidth: true
|
||||
// Layout.fillHeight: true
|
||||
anchors.fill:parent
|
||||
// anchors.margins: 4
|
||||
clip: true // otherwise animation will affect left panel
|
||||
|
||||
delegate: StackViewDelegate {
|
||||
pushTransition: StackViewTransition {
|
||||
PropertyAnimation {
|
||||
target: enterItem
|
||||
property: "x"
|
||||
from: 0 - target.width
|
||||
to: 0
|
||||
duration: 300
|
||||
}
|
||||
PropertyAnimation {
|
||||
target: exitItem
|
||||
property: "x"
|
||||
from: 0
|
||||
to: target.width
|
||||
duration: 300
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}// flickable
|
||||
}
|
||||
// border
|
||||
Rectangle {
|
||||
|
||||
146
README.md
@@ -1,4 +1,6 @@
|
||||
Copyright (c) 2014-2016, The Monero Project
|
||||
# Monero GUI
|
||||
|
||||
Copyright (c) 2014-2017, The Monero Project
|
||||
|
||||
## Development Resources
|
||||
|
||||
@@ -62,52 +64,67 @@ Packaging for your favorite distribution would be a welcome contribution!
|
||||
|
||||
### On Linux:
|
||||
|
||||
(Tested on Ubuntu 16.04 i386 and Linux Mint 18 "Sarah" - Cinnamon (64-bit))
|
||||
(Tested on Ubuntu 16.04 x86, 16.10 x64, Gentoo x64 and Linux Mint 18 "Sarah" - Cinnamon x64)
|
||||
|
||||
1. Install Monero dependencies.
|
||||
1. Install Monero dependencies
|
||||
|
||||
- For Ubuntu and Mint
|
||||
|
||||
`sudo apt install build-essential cmake libboost-all-dev miniupnpc libunbound-dev graphviz doxygen libunwind8-dev pkg-config libssl-dev`
|
||||
|
||||
2. Grab an up-to-date copy of the monero-core repository.
|
||||
- For Gentoo
|
||||
|
||||
`sudo emerge app-arch/xz-utils app-doc/doxygen dev-cpp/gtest dev-libs/boost dev-libs/expat dev-libs/openssl dev-util/cmake media-gfx/graphviz net-dns/unbound net-libs/ldns net-libs/miniupnpc sys-libs/libunwind`
|
||||
|
||||
2. Grab an up-to-date copy of the monero-core repository
|
||||
|
||||
`git clone https://github.com/monero-project/monero-core.git`
|
||||
|
||||
3. Go into the repository.
|
||||
3. Go into the repository
|
||||
|
||||
`cd monero-core`
|
||||
|
||||
4. Use the script to compile the Monero libs necessary to run the GUI.
|
||||
4. Install the GUI dependencies
|
||||
|
||||
`./get_libwallet_api.sh`
|
||||
|
||||
|
||||
5. Install the GUI dependencies.
|
||||
|
||||
- For Ubuntu 16.04 i386
|
||||
- For Ubuntu 16.04 x86
|
||||
|
||||
`sudo apt-get install qtbase5-dev qt5-default qtdeclarative5-dev qml-module-qtquick-controls qml-module-qtquick-xmllistmodel qttools5-dev-tools qml-module-qtquick-dialogs`
|
||||
|
||||
- For Ubuntu 16.04 x64
|
||||
- For Ubuntu 16.04+ x64
|
||||
|
||||
`sudo apt-get install qtbase5-dev qt5-default qtdeclarative5-dev qml-module-qtquick-controls qml-module-qtquick-xmllistmodel qttools5-dev-tools qml-module-qtquick-dialogs qml-module-qt-labs-settings libqt5qml-graphicaleffects`
|
||||
`sudo apt-get install qtbase5-dev qt5-default qtdeclarative5-dev qml-module-qtquick-controls qml-module-qtquick-xmllistmodel qttools5-dev-tools qml-module-qtquick-dialogs qml-module-qt-labs-settings libqt5qml-graphicaleffects`
|
||||
|
||||
- For Linux Mint 18 "Sarah" - Cinnamon (64-bit)
|
||||
- For Linux Mint 18 "Sarah" - Cinnamon x64
|
||||
|
||||
`sudo apt install qml-module-qt-labs-settings qml-module-qtgraphicaleffects`
|
||||
`sudo apt install qml-module-qt-labs-settings qml-module-qtgraphicaleffects`
|
||||
|
||||
6. Build the GUI.
|
||||
- For Gentoo
|
||||
|
||||
`qmake`
|
||||
`sudo emerge dev-qt/qtcore:5 dev-qt/qtdeclarative:5 dev-qt/qtquickcontrols:5 dev-qt/qtquickcontrols2:5 dev-qt/qtgraphicaleffects:5`
|
||||
|
||||
`make`
|
||||
- Optional : To build the flag `WITH_SCANNER`
|
||||
|
||||
7. Before running the GUI, it's recommended that you have the Monero daemon running in the background.
|
||||
- For Ubuntu and Mint
|
||||
|
||||
`./monerod`
|
||||
`sudo apt install qtmultimedia5-dev qml-module-qtmultimedia libzbar-dev`
|
||||
|
||||
8. Run the GUI client.
|
||||
- For Gentoo
|
||||
|
||||
`./release/bin/monero-core`
|
||||
The *qml* USE flag must be enabled.
|
||||
|
||||
`emerge dev-qt/qtmultimedia:5 media-gfx/zbar`
|
||||
|
||||
5. Build the GUI
|
||||
|
||||
- For Ubuntu and Mint
|
||||
|
||||
`./build.sh`
|
||||
|
||||
- For Gentoo
|
||||
|
||||
`QT_SELECT=5 ./build.sh`
|
||||
|
||||
The executable can be found in the build/release/bin folder.
|
||||
|
||||
### On OS X:
|
||||
|
||||
@@ -115,34 +132,35 @@ Packaging for your favorite distribution would be a welcome contribution!
|
||||
2. Install [homebrew](http://brew.sh/)
|
||||
3. Install [monero](https://github.com/monero-project/monero) dependencies:
|
||||
|
||||
`brew install boost --c++11`
|
||||
`brew install boost --c++11`
|
||||
|
||||
`brew install openssl` - to install openssl headers
|
||||
`brew install openssl` - to install openssl headers
|
||||
|
||||
`brew install pkgconfig`
|
||||
`brew install pkgconfig`
|
||||
|
||||
`brew install cmake`
|
||||
`brew install cmake`
|
||||
|
||||
4. Install latest Qt using official installer from [qt.io](https://www.qt.io/download-open-source/) (homebrew version might be outdated).
|
||||
5. Add Qt bin dir to your path:
|
||||
`brew install qt5` (or download QT 5.8+ from [qt.io](https://www.qt.io/download-open-source/))
|
||||
|
||||
`export PATH=$PATH:$HOME/Qt/5.7/clang_64/bin`
|
||||
If you have an older version of Qt installed via homebrew, you can force it to use 5.x like so:
|
||||
|
||||
`brew link --force --overwrite qt5`
|
||||
|
||||
where ```Qt``` is the folder you selected to install Qt.
|
||||
5. Add the Qt bin directory to your path
|
||||
|
||||
6. Grab an up-to-date copy of the monero-core repository.
|
||||
Example: `export PATH=$PATH:$HOME/Qt/5.8/clang_64/bin`
|
||||
|
||||
`git clone https://github.com/monero-project/monero-core.git`
|
||||
This is the directory where Qt 5.x is installed on **your** system
|
||||
|
||||
7. Go into the repository.
|
||||
6. Grab an up-to-date copy of the monero-core repository
|
||||
|
||||
`cd monero-core`
|
||||
`git clone https://github.com/monero-project/monero-core.git`
|
||||
|
||||
8. Build libwallet
|
||||
7. Go into the repository
|
||||
|
||||
`./get_libwallet_api.sh`
|
||||
`cd monero-core`
|
||||
|
||||
9. Start the build:
|
||||
8. Start the build
|
||||
|
||||
`./build.sh`
|
||||
|
||||
@@ -150,7 +168,7 @@ The executable can be found in the `build/release/bin` folder.
|
||||
|
||||
**Note:** Workaround for "ERROR: Xcode not set up properly"
|
||||
|
||||
Edit `$HOME/Qt/5.7/clang_64/mkspecs/features/mac/default_pre.prf`
|
||||
Edit `$HOME/Qt/5.8/clang_64/mkspecs/features/mac/default_pre.prf`
|
||||
|
||||
replace
|
||||
`isEmpty($$list($$system("/usr/bin/xcrun -find xcrun 2>/dev/null")))`
|
||||
@@ -164,50 +182,56 @@ More info: http://stackoverflow.com/a/35098040/1683164
|
||||
### On Windows:
|
||||
|
||||
1. Install [msys2](http://msys2.github.io/), follow the instructions on that page on how to update packages to the latest versions
|
||||
2. Install monero dependencies as described in [monero documentation](https://github.com/monero-project/monero) into msys2 environment.
|
||||
**As we only build application for x86, install only dependencies for x86 architecture (i686 in package name)**
|
||||
|
||||
3. Install git into msys2 environment:
|
||||
2. Install monero dependencies as described in [monero documentation](https://github.com/monero-project/monero) into msys2 environment
|
||||
**As we only build application for x86, install only dependencies for x86 architecture (i686 in package name)**
|
||||
```
|
||||
pacman -S mingw-w64-i686-toolchain make mingw-w64-i686-cmake mingw-w64-i686-boost
|
||||
|
||||
```
|
||||
|
||||
3. Install git into msys2 environment
|
||||
|
||||
```
|
||||
pacman -S git
|
||||
```
|
||||
|
||||
4. Install Qt5 from [official site](https://www.qt.io/download-open-source/).
|
||||
4. Install Qt5 from [official site](https://www.qt.io/download-open-source/)
|
||||
- download unified installer, run and select following options:
|
||||
- Qt > Qt 5.7 > MinGW 5.3.0 32 bit
|
||||
- Tools > MinGW 5.3.0
|
||||
- continue with installation
|
||||
|
||||
5. Open ```mingw``` shell:
|
||||
5. Open ```MinGW-w64 Win32 Shell``` shell
|
||||
|
||||
```%MSYS_ROOT%\msys2_shell.cmd -mingw32```
|
||||
|
||||
Where ```%MSYS_ROOT%``` will be ```c:\msys32``` if your host OS is x86-based or ```c:\msys64``` if your host OS
|
||||
is x64-based
|
||||
|
||||
6. Clone repository:
|
||||
6. Install the latest version of boost, specificly the required static libraries
|
||||
```
|
||||
cd
|
||||
wget http://sourceforge.net/projects/boost/files/boost/1.63.0/boost_1_63_0.tar.bz2
|
||||
tar xjf boost_1_63_0.tar.bz2
|
||||
cd boost_1_63_0
|
||||
./bootstrap.sh mingw
|
||||
./b2 --prefix=/mingw32/boost --layout=tagged --without-mpi --without-python toolset=gcc address-model=32 variant=debug,release link=static threading=multi runtime-link=static -j$(nproc) install
|
||||
```
|
||||
|
||||
7. Clone repository
|
||||
```
|
||||
cd
|
||||
git clone https://github.com/monero-project/monero-core.git
|
||||
```
|
||||
|
||||
7. Build libwallet:
|
||||
8. Build the GUI
|
||||
```
|
||||
cd monero-core
|
||||
./get_libwallet_api.sh
|
||||
export PATH=$(ls -rd /c/Qt/5.[6,7,8]/mingw53_32/bin | head -1):$PATH
|
||||
./build.sh
|
||||
cd build
|
||||
make deploy
|
||||
```
|
||||
close ```mingw``` shell after it done
|
||||
|
||||
8. Build application:
|
||||
|
||||
- open ```Qt environment``` shell (Qt 5.7 for Desktop (MinGW 5.3.0 32 bit) is shortcut name)
|
||||
- navigate to the project dir and build the app:
|
||||
```
|
||||
cd %MSYS_ROOT%\%USERNAME%\monero-core
|
||||
mkdir build
|
||||
cd build
|
||||
qmake ..\ -r "CONFIG+=release"
|
||||
mingw32-make release
|
||||
mingw32-make deploy
|
||||
```
|
||||
- grab result binary and dependencies in ```.\release\bin```
|
||||
The executable can be found in the ```.\release\bin``` directory.
|
||||
|
||||
147
VULNERABILITY_RESPONSE_PROCESS.md
Normal file
@@ -0,0 +1,147 @@
|
||||
# Monero GUI Vulnerability Response Process
|
||||
|
||||
## Preamble
|
||||
|
||||
Researchers/Hackers: while you research/hack, we ask that you please refrain from committing the following:
|
||||
- Denial of Service / Active exploiting against the network
|
||||
- Social Engineering of Monero staff or contractors
|
||||
- Any physical or electronic attacks against Monero community property and/or data centers
|
||||
|
||||
## I. Points of Contact for Security Issues
|
||||
|
||||
```
|
||||
ric@getmonero.org
|
||||
BDA6 BD70 42B7 21C4 67A9 759D 7455 C5E3 C0CD CEB9
|
||||
|
||||
luigi1111@getmonero.org
|
||||
8777 AB8F 778E E894 87A2 F8E7 F4AC A018 3641 E010
|
||||
|
||||
moneromooo.monero@gmail.com
|
||||
48B0 8161 FBDA DFE3 93AD FC3E 686F 0745 4D6C EFC3
|
||||
|
||||
jaquee.monero@gmail.com
|
||||
D21E 9CC1 2F51 C4FE A9E0 52FF 384E 52B0 9F45 DC39
|
||||
```
|
||||
|
||||
## II. Security Response Team
|
||||
|
||||
- fluffypony
|
||||
- luigi1111
|
||||
- moneromooo
|
||||
- Jaquee
|
||||
|
||||
## III. Incident Response
|
||||
|
||||
1. Researcher submits report via one or both of two methods:
|
||||
- a. Email
|
||||
- b. [HackerOne](https://hackerone.com/monero)
|
||||
|
||||
2. Response Team designates a Response Manager who is in charge of the particular report based on availability and/or knowledge-set
|
||||
|
||||
3. In no more than 3 working days, Response Team should gratefully respond to researcher using only encrypted, secure channels
|
||||
|
||||
4. Response Manager makes inquiries to satisfy any needed information to confirm if submission is indeed a vulnerability
|
||||
- a. If submission proves to be vulnerable, proceed to next step
|
||||
- b. If not vulnerable:
|
||||
- i. Response Manager responds with reasons why submission is not a vulnerability
|
||||
- ii. Response Manager moves discussion to a new or existing ticket on GitHub if necessary
|
||||
|
||||
5. If over email, Response Manager opens a HackerOne issue for new submission
|
||||
|
||||
6. Establish severity of vulnerability:
|
||||
- a. HIGH: impacts network as a whole, has potential to break entire network, results in the loss of monero, or is on a scale of great catastrophe
|
||||
- b. MEDIUM: impacts individual nodes, wallets, or must be carefully exploited
|
||||
- c. LOW: is not easily exploitable
|
||||
|
||||
7. Respond according to the severity of the vulnerability:
|
||||
- a. HIGH severities must be notified on website and reddit /r/Monero within 3 working days of classification
|
||||
- i. The notification should list appropriate steps for users to take, if any
|
||||
- ii. The notification must not include any details that could suggest an exploitation path
|
||||
- iii. The latter takes precedence over the former
|
||||
- b. MEDIUM and HIGH severities will require a Point Release
|
||||
- c. LOW severities will be addressed in the next Regular Release
|
||||
|
||||
8. Response Team applies appropriate patch(es)
|
||||
- a. Response Manager designates a PRIVATE git "hotfix branch" to work in
|
||||
- b. Patches are reviewed with the researcher
|
||||
- c. Any messages associated with PUBLIC commits during the time of review should not make reference to the security nature of the PRIVATE branch or its commits
|
||||
- d. Vulnerability announcement is drafted
|
||||
- i. Include the severity of the vulnerability
|
||||
- ii. Include all vulnerable systems/apps/code
|
||||
- iii. Include solutions (if any) if patch cannot be applied
|
||||
- e. Release date is discussed
|
||||
|
||||
9. At release date, Response Team coordinates with developers to finalize update:
|
||||
- a. Response Manager propagates the "hotfix branch" to trunk
|
||||
- b. Response Manager includes vulnerability announcement draft in release notes
|
||||
- c. Proceed with the Point or Regular Release
|
||||
|
||||
## IV. Post-release Disclosure Process
|
||||
|
||||
1. Response Team has 90 days to fulfill all points within section III
|
||||
|
||||
2. If the Incident Response process in section III is successfully completed:
|
||||
- a. Response Manager contacts researcher and asks if researcher wishes for credit
|
||||
- b. Finalize vulnerability announcement draft and include the following:
|
||||
- i. Project name and URL
|
||||
- ii. Versions known to be affected
|
||||
- iii. Versions known to be not affected (for example, the vulnerable code was introduced in a recent version, and older versions are therefore unaffected)
|
||||
- iv. Versions not checked
|
||||
- v. Type of vulnerability and its impact
|
||||
- vi. If already obtained or applicable, a CVE-ID
|
||||
- vii. The planned, coordinated release date
|
||||
- viii. Mitigating factors (for example, the vulnerability is only exposed in uncommon, non-default configurations)
|
||||
- ix. Workarounds (configuration changes users can make to reduce their exposure to the vulnerability)
|
||||
- x. If applicable, credits to the original reporter
|
||||
- c. Release finalized vulnerability announcement on website and reddit /r/Monero
|
||||
- d. For HIGH severities, release finalized vulnerability announcement on well-known mailing lists:
|
||||
- i. oss-security@lists.openwall.com
|
||||
- ii. bugtraq@securityfocus.com
|
||||
- e. If applicable, developers request a CVE-ID
|
||||
- i. The commit that applied the fix is made reference too in a future commit and includes a CVE-ID
|
||||
|
||||
3. If the Incident Response process in section III is *not* successfully completed:
|
||||
- a. Response Team and developers organize an IRC meeting to discuss why/what points in section III were not resolved and how the team can resolve them in the future
|
||||
- b. Any developer meetings immediately following the incident should include points made in section V
|
||||
- c. If disputes arise about whether or when to disclose information about a vulnerability, the Response Team will publicly discuss the issue via IRC and attempt to reach consensus
|
||||
- d. If consensus on a timely disclosure is not met (no later than 90 days), the researcher (after 90 days) has every right to expose the vulnerability to the public
|
||||
|
||||
## V. Incident Analysis
|
||||
|
||||
1. Isolate codebase
|
||||
- a. Response Team and developers should coordinate to work on the following:
|
||||
- i. Problematic implementation of classes/libraries/functions, etc.
|
||||
- ii. Focus on apps/distro packaging, etc.
|
||||
- iii. Operator/config error, etc.
|
||||
|
||||
2. Auditing
|
||||
- a. Response Team and developers should coordinate to work on the following:
|
||||
- i. Auditing of problem area(s) as discussed in point 1
|
||||
- ii. Generate internal reports and store for future reference
|
||||
- iii. If results are not sensitive, share with the public via IRC or GitHub
|
||||
|
||||
3. Response Team has 45 days following completion of section III to ensure completion of section V
|
||||
|
||||
## VI. Resolutions
|
||||
|
||||
Any further questions or resolutions regarding the incident(s) between the researcher and response + development team after public disclosure can be addressed via the following:
|
||||
|
||||
- [GitHub](https://github.com/monero-project/monero/issues/)
|
||||
- [HackerOne](https://hackerone.com/monero)
|
||||
- [Reddit /r/Monero](https://reddit.com/r/Monero/)
|
||||
- IRC
|
||||
- Email
|
||||
|
||||
## VII. Continuous Improvement
|
||||
|
||||
1. Response Team and developers should hold annual meetings to review the previous year's incidents
|
||||
|
||||
2. Response Team or designated person(s) should give a brief presentation, including:
|
||||
- a. Areas of Monero affected by the incidents
|
||||
- b. Any network downtime or monetary cost (if any) of the incidents
|
||||
- c. Ways in which the incidents could have been avoided (if any)
|
||||
- d. How effective this process was in dealing with the incidents
|
||||
|
||||
3. After the presentation, Response Team and developers should discuss:
|
||||
- a. Potential changes to development processes to reduce future incidents
|
||||
- b. Potential changes to this process to improve future responses
|
||||
53
android/README.md
Normal file
@@ -0,0 +1,53 @@
|
||||
Copyright (c) 2014-2017, The Monero Project
|
||||
|
||||
|
||||
## Current status : ALPHA
|
||||
|
||||
- Minimum Android 5.0 (api level 21)
|
||||
- Modal dialogs can appear in background giving the feeling that the application is frozen (Work around : turn screen off/on or switch to another app and back)
|
||||
|
||||
## Build using Docker
|
||||
|
||||
# Base environnement
|
||||
|
||||
cd monero/utils/build_scripts
|
||||
docker build -f android32.Dockerfile -t monero-android .
|
||||
cd ..
|
||||
|
||||
# Build GUI
|
||||
|
||||
cd android/docker
|
||||
docker build -t monero-gui-android .
|
||||
docker create -it --name monero-gui-android monero-gui-android bash
|
||||
|
||||
# Get the apk
|
||||
|
||||
docker cp monero-gui-android:/opt/android/monero-core/build/release/bin/bin/QtApp-debug.apk .
|
||||
|
||||
## Deployment
|
||||
|
||||
- Using ADB (Android debugger bridge) :
|
||||
|
||||
First, see section [Enable adb debugging on your device](https://developer.android.com/studio/command-line/adb.html#Enabling)
|
||||
The only place where we are allowed to play is `/data/local/tmp`. So :
|
||||
|
||||
adb push /opt/android/monero-core/build/release/bin/bin/QtApp-debug.apk /data/local/tmp
|
||||
adb shell pm install -r /data/local/tmp/QtApp-debug.apk
|
||||
|
||||
- Troubleshooting:
|
||||
|
||||
adb devices -l
|
||||
adb logcat
|
||||
|
||||
if using adb inside docker, make sure you did "docker run -v /dev/bus/usb:/dev/bus/usb --privileged"
|
||||
|
||||
- Using a web server
|
||||
|
||||
mkdir /usr/tmp
|
||||
cp QtApp-debug.apk /usr/tmp
|
||||
docker run -d -v /usr/tmp:/usr/share/nginx/html:ro -p 8080:80 nginx
|
||||
|
||||
Now it should be accessible through a web browser at
|
||||
|
||||
http://<your.local.ip>:8080/QtApp-debug.apk
|
||||
|
||||
108
android/docker/Dockerfile
Normal file
@@ -0,0 +1,108 @@
|
||||
FROM monero-android
|
||||
|
||||
#INSTALL JAVA
|
||||
RUN echo "deb http://ftp.fr.debian.org/debian/ jessie-backports main contrib non-free" >> /etc/apt/sources.list
|
||||
RUN dpkg --add-architecture i386 \
|
||||
&& apt-get update \
|
||||
&& apt-get install -y libc6:i386 libncurses5:i386 libstdc++6:i386 libz1:i386 \
|
||||
&& apt-get install -y -t jessie-backports ca-certificates-java openjdk-8-jdk-headless openjdk-8-jre-headless ant
|
||||
ENV JAVA_HOME /usr/lib/jvm/java-8-openjdk-amd64
|
||||
ENV PATH $JAVA_HOME/bin:$PATH
|
||||
|
||||
#Get Qt
|
||||
ENV QT_VERSION 5.8
|
||||
|
||||
RUN git clone git://code.qt.io/qt/qt5.git -b ${QT_VERSION} \
|
||||
&& cd qt5 \
|
||||
&& perl init-repository
|
||||
|
||||
## Note: Need to use libc++ but Qt does not provide mkspec for libc++.
|
||||
## Their support of it is quite recent and they claim they don't use it by default
|
||||
## [only because it produces bigger binary objects](https://bugreports.qt.io/browse/QTBUG-50724).
|
||||
|
||||
#Create new mkspec for clang + libc++
|
||||
RUN cp -r qt5/qtbase/mkspecs/android-clang qt5/qtbase/mkspecs/android-clang-libc \
|
||||
&& cd qt5/qtbase/mkspecs/android-clang-libc \
|
||||
&& sed -i '16i ANDROID_SOURCES_CXX_STL_LIBDIR = $$NDK_ROOT/sources/cxx-stl/llvm-libc++/libs/$$ANDROID_TARGET_ARCH' qmake.conf \
|
||||
&& sed -i '17i ANDROID_SOURCES_CXX_STL_INCDIR = $$NDK_ROOT/sources/cxx-stl/llvm-libc++/include' qmake.conf \
|
||||
&& echo "QMAKE_LIBS_PRIVATE = -lc++_shared -llog -lz -lm -ldl -lc -lgcc " >> qmake.conf \
|
||||
&& echo "QMAKE_CFLAGS -= -mfpu=vfp " >> qmake.conf \
|
||||
&& echo "QMAKE_CXXFLAGS -= -mfpu=vfp " >> qmake.conf \
|
||||
&& echo "QMAKE_CFLAGS += -mfpu=vfp4 " >> qmake.conf \
|
||||
&& echo "QMAKE_CXXFLAGS += -mfpu=vfp4 " >> qmake.conf
|
||||
|
||||
ENV ANDROID_API android-21
|
||||
|
||||
#ANDROID SDK TOOLS
|
||||
RUN echo y | $ANDROID_SDK_ROOT/tools/android update sdk --no-ui --all --filter platform-tools
|
||||
RUN echo y | $ANDROID_SDK_ROOT/tools/android update sdk --no-ui --all --filter ${ANDROID_API}
|
||||
RUN echo y | $ANDROID_SDK_ROOT/tools/android update sdk --no-ui --all --filter build-tools-25.0.1
|
||||
|
||||
ENV CLEAN_PATH $JAVA_HOME/bin:/usr/cmake-3.6.3-Linux-x86_64/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
||||
|
||||
#build Qt
|
||||
RUN cd qt5 && PATH=${CLEAN_PATH} ./configure -developer-build -release \
|
||||
-xplatform android-clang-libc \
|
||||
-android-ndk-platform ${ANDROID_API} \
|
||||
-android-ndk $ANDROID_NDK_ROOT \
|
||||
-android-sdk $ANDROID_SDK_ROOT \
|
||||
-opensource -confirm-license \
|
||||
-prefix ${WORKDIR}/Qt-${QT_VERSION} \
|
||||
-nomake tests -nomake examples \
|
||||
-skip qtserialport \
|
||||
-skip qtconnectivity \
|
||||
-skip qttranslations \
|
||||
-skip qtgamepad -skip qtscript -skip qtdoc
|
||||
|
||||
# build Qt tools : gnustl_shared.so is hard-coded in androiddeployqt
|
||||
# replace it with libc++_shared.so
|
||||
COPY androiddeployqt.patch qt5/qttools/androiddeployqt.patch
|
||||
RUN cd qt5/qttools \
|
||||
&& git apply androiddeployqt.patch \
|
||||
&& cd .. \
|
||||
&& PATH=${CLEAN_PATH} make -j4 \
|
||||
&& PATH=${CLEAN_PATH} make install
|
||||
|
||||
# Get iconv and ZBar
|
||||
ENV ICONV_VERSION 1.14
|
||||
RUN git clone https://github.com/ZBar/ZBar.git \
|
||||
&& curl -s -O http://ftp.gnu.org/pub/gnu/libiconv/libiconv-${ICONV_VERSION}.tar.gz \
|
||||
&& tar -xzf libiconv-${ICONV_VERSION}.tar.gz \
|
||||
&& cd libiconv-${ICONV_VERSION} \
|
||||
&& CC=arm-linux-androideabi-clang CXX=arm-linux-androideabi-clang++ ./configure --build=x86_64-linux-gnu --host=arm-eabi --prefix=${WORKDIR}/libiconv --disable-rpath
|
||||
|
||||
ENV PATH $ANDROID_SDK_ROOT/tools:$ANDROID_SDK_ROOT/platform-tools:${WORKDIR}/Qt-${QT_VERSION}/bin:$PATH
|
||||
|
||||
#Build libiconv.a and libzbarjni.a
|
||||
COPY android.mk.patch ZBar/android.mk.patch
|
||||
RUN cd ZBar \
|
||||
&& git apply android.mk.patch \
|
||||
&& echo \
|
||||
"APP_ABI := armeabi-v7a \n\
|
||||
APP_STL := c++_shared \n\
|
||||
TARGET_PLATFORM := ${ANDROID_API} \n\
|
||||
TARGET_ARCH_ABI := armeabi-v7a \n\
|
||||
APP_CFLAGS += -target armv7-none-linux-androideabi -fexceptions -fstack-protector-strong -fno-limit-debug-info -mfloat-abi=softfp -mfpu=vfp -fno-builtin-memmove -fno-omit-frame-pointer -fno-stack-protector\n"\
|
||||
>> android/jni/Application.mk \
|
||||
&& cd android \
|
||||
&& android update project --path . -t "${ANDROID_API}" \
|
||||
&& CC=arm-linux-androideabi-clang CXX=arm-linux-androideabi-clang++ ant -Dndk.dir=${ANDROID_NDK_ROOT} -Diconv.src=${WORKDIR}/libiconv-${ICONV_VERSION} zbar-clean zbar-ndk-build
|
||||
|
||||
#Can't directly call build.sh because of env variables
|
||||
RUN git clone https://github.com/monero-project/monero-core.git \
|
||||
&& cd monero-core \
|
||||
&& git submodule update \
|
||||
&& CC=arm-linux-androideabi-clang CXX=arm-linux-androideabi-clang++ BOOST_ROOT=/opt/android/boost_1_62_0 BOOST_LIBRARYDIR=${WORKDIR}/boost_${BOOST_VERSION}/android32/lib/ OPENSSL_ROOT_DIR=${WORKDIR}/openssl/ ./get_libwallet_api.sh release-android
|
||||
|
||||
RUN cp openssl/lib* ${ANDROID_NDK_ROOT}/platforms/${ANDROID_API}/arch-arm/usr/lib
|
||||
RUN cp boost_${BOOST_VERSION}/android32/lib/lib* ${ANDROID_NDK_ROOT}/platforms/${ANDROID_API}/arch-arm/usr/lib
|
||||
RUN cp ZBar/android/obj/local/armeabi-v7a/lib* ${ANDROID_NDK_ROOT}/platforms/${ANDROID_API}/arch-arm/usr/lib
|
||||
|
||||
ENV PATH $ANDROID_SDK_ROOT/tools:$ANDROID_SDK_ROOT/platform-tools:${WORKDIR}/Qt-${QT_VERSION}/bin:$CLEAN_PATH
|
||||
|
||||
# NB : zxcvbn-c needs to build a local binary and Qt don't care about these environnement variable
|
||||
RUN cd monero-core \
|
||||
&& CC="gcc" CXX="g++" ./build.sh release-android \
|
||||
&& cd build \
|
||||
&& make deploy
|
||||
|
||||
61
android/docker/android.mk.patch
Normal file
@@ -0,0 +1,61 @@
|
||||
diff --git a/android/jni/Android.mk b/android/jni/Android.mk
|
||||
index e442b07..158afd5 100644
|
||||
--- a/android/jni/Android.mk
|
||||
+++ b/android/jni/Android.mk
|
||||
@@ -12,14 +12,18 @@ LOCAL_PATH := $(ICONV_SRC)
|
||||
|
||||
LOCAL_MODULE := libiconv
|
||||
|
||||
+LOCAL_ARM_MODE := arm
|
||||
+LOCAL_CPP_FEATURES := exceptions rtti features
|
||||
LOCAL_CFLAGS := \
|
||||
-Wno-multichar \
|
||||
-D_ANDROID \
|
||||
- -DLIBDIR="c" \
|
||||
+ -DLIBDIR="\".\"" \
|
||||
-DBUILDING_LIBICONV \
|
||||
-DBUILDING_LIBCHARSET \
|
||||
-DIN_LIBRARY
|
||||
|
||||
+LOCAL_CFLAGS += -fno-stack-protector
|
||||
+
|
||||
LOCAL_SRC_FILES := \
|
||||
lib/iconv.c \
|
||||
libcharset/lib/localcharset.c \
|
||||
@@ -30,13 +34,14 @@ LOCAL_C_INCLUDES := \
|
||||
$(ICONV_SRC)/libcharset \
|
||||
$(ICONV_SRC)/libcharset/include
|
||||
|
||||
-include $(BUILD_SHARED_LIBRARY)
|
||||
+include $(BUILD_STATIC_LIBRARY)
|
||||
|
||||
LOCAL_LDLIBS := -llog -lcharset
|
||||
|
||||
# libzbarjni
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
+
|
||||
LOCAL_PATH := $(MY_LOCAL_PATH)
|
||||
LOCAL_MODULE := zbarjni
|
||||
LOCAL_SRC_FILES := ../../java/zbarjni.c \
|
||||
@@ -71,6 +76,17 @@ LOCAL_C_INCLUDES := ../include \
|
||||
../zbar \
|
||||
$(ICONV_SRC)/include
|
||||
|
||||
-LOCAL_SHARED_LIBRARIES := libiconv
|
||||
+LOCAL_STATIC_LIBRARIES := libiconv
|
||||
+LOCAL_ARM_MODE := arm
|
||||
+LOCAL_CPP_FEATURES := exceptions rtti features
|
||||
+
|
||||
+LOCAL_CFLAGS := \
|
||||
+ -Wno-multichar \
|
||||
+ -D_ANDROID \
|
||||
+ -DLIBDIR="\".\"" \
|
||||
+ -DBUILDING_LIBICONV \
|
||||
+ -DBUILDING_LIBCHARSET \
|
||||
+ -DIN_LIBRARY
|
||||
+
|
||||
|
||||
-include $(BUILD_SHARED_LIBRARY)
|
||||
\ No newline at end of file
|
||||
+include $(BUILD_STATIC_LIBRARY)
|
||||
62
android/docker/androiddeployqt.patch
Normal file
@@ -0,0 +1,62 @@
|
||||
diff --git a/src/androiddeployqt/main.cpp b/src/androiddeployqt/main.cpp
|
||||
index 8a8e591..71d693e 100644
|
||||
--- a/src/androiddeployqt/main.cpp
|
||||
+++ b/src/androiddeployqt/main.cpp
|
||||
@@ -1122,7 +1122,7 @@ bool updateLibsXml(const Options &options)
|
||||
|
||||
QString libsPath = QLatin1String("libs/") + options.architecture + QLatin1Char('/');
|
||||
|
||||
- QString qtLibs = QLatin1String("<item>gnustl_shared</item>\n");
|
||||
+ QString qtLibs = QLatin1String("<item>c++_shared</item>\n");
|
||||
QString bundledInLibs;
|
||||
QString bundledInAssets;
|
||||
foreach (Options::BundledFile bundledFile, options.bundledFiles) {
|
||||
@@ -2519,6 +2519,39 @@ bool installApk(const Options &options)
|
||||
return true;
|
||||
}
|
||||
|
||||
+bool copyStl(Options *options)
|
||||
+{
|
||||
+ if (options->deploymentMechanism == Options::Debug && !options->installApk)
|
||||
+ return true;
|
||||
+
|
||||
+ if (options->verbose)
|
||||
+ fprintf(stdout, "Copying LIBC++ STL library\n");
|
||||
+
|
||||
+ QString filePath = options->ndkPath
|
||||
+ + QLatin1String("/sources/cxx-stl/llvm-libc++")
|
||||
+ + QLatin1String("/libs/")
|
||||
+ + options->architecture
|
||||
+ + QLatin1String("/libc++_shared.so");
|
||||
+ if (!QFile::exists(filePath)) {
|
||||
+ fprintf(stderr, "LIBC STL library does not exist at %s\n", qPrintable(filePath));
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ QString destinationDirectory =
|
||||
+ options->deploymentMechanism == Options::Debug
|
||||
+ ? options->temporaryDirectoryName + QLatin1String("/lib")
|
||||
+ : options->outputDirectory + QLatin1String("/libs/") + options->architecture;
|
||||
+
|
||||
+ if (!copyFileIfNewer(filePath, destinationDirectory
|
||||
+ + QLatin1String("/libc++_shared.so"), options->verbose)) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ if (options->deploymentMechanism == Options::Debug && !deployToLocalTmp(options, QLatin1String("/lib/libc++_shared.so")))
|
||||
+ return false;
|
||||
+
|
||||
+ return true;
|
||||
+}
|
||||
bool copyGnuStl(Options *options)
|
||||
{
|
||||
if (options->deploymentMechanism == Options::Debug && !options->installApk)
|
||||
@@ -2870,7 +2903,7 @@ int main(int argc, char *argv[])
|
||||
if (Q_UNLIKELY(options.timing))
|
||||
fprintf(stdout, "[TIMING] %d ms: Read dependencies\n", options.timer.elapsed());
|
||||
|
||||
- if (options.deploymentMechanism != Options::Ministro && !copyGnuStl(&options))
|
||||
+ if (options.deploymentMechanism != Options::Ministro && !copyStl(&options))
|
||||
return CannotCopyGnuStl;
|
||||
|
||||
if (Q_UNLIKELY(options.timing))
|
||||
69
build.sh
@@ -1,8 +1,44 @@
|
||||
#!/bin/bash
|
||||
|
||||
BUILD_TYPE=$1
|
||||
source ./utils.sh
|
||||
platform=$(get_platform)
|
||||
# default build type
|
||||
if [ -z $BUILD_TYPE ]; then
|
||||
BUILD_TYPE=Release
|
||||
BUILD_TYPE=release
|
||||
fi
|
||||
|
||||
if [ "$BUILD_TYPE" == "release" ]; then
|
||||
echo "Building release"
|
||||
CONFIG="CONFIG+=release";
|
||||
BIN_PATH=release/bin
|
||||
elif [ "$BUILD_TYPE" == "release-static" ]; then
|
||||
echo "Building release-static"
|
||||
if [ "$platform" != "darwin" ]; then
|
||||
CONFIG="CONFIG+=release static";
|
||||
else
|
||||
# OS X: build static libwallet but dynamic Qt.
|
||||
echo "OS X: Building Qt project without static flag"
|
||||
CONFIG="CONFIG+=release";
|
||||
fi
|
||||
BIN_PATH=release/bin
|
||||
elif [ "$BUILD_TYPE" == "release-android" ]; then
|
||||
echo "Building release for ANDROID"
|
||||
CONFIG="CONFIG+=release static WITH_SCANNER";
|
||||
ANDROID=true
|
||||
BIN_PATH=release/bin
|
||||
elif [ "$BUILD_TYPE" == "debug-android" ]; then
|
||||
echo "Building debug for ANDROID : ultra INSECURE !!"
|
||||
CONFIG="CONFIG+=debug qml_debug WITH_SCANNER";
|
||||
ANDROID=true
|
||||
BIN_PATH=debug/bin
|
||||
elif [ "$BUILD_TYPE" == "debug" ]; then
|
||||
echo "Building debug"
|
||||
CONFIG="CONFIG+=debug"
|
||||
BIN_PATH=debug/bin
|
||||
else
|
||||
echo "Valid build types are release, release-static, release-android, debug-android and debug"
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
|
||||
@@ -12,27 +48,22 @@ ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
MONERO_DIR=monero
|
||||
MONEROD_EXEC=monerod
|
||||
|
||||
# Build libwallet if monero folder doesnt exist
|
||||
if [ ! -d $MONERO_DIR ]; then
|
||||
$SHELL get_libwallet_api.sh $BUILD_TYPE
|
||||
MAKE='make'
|
||||
if [[ $platform == *bsd* ]]; then
|
||||
MAKE='gmake'
|
||||
fi
|
||||
|
||||
# build libwallet
|
||||
$SHELL get_libwallet_api.sh $BUILD_TYPE
|
||||
|
||||
# build zxcvbn
|
||||
make -C src/zxcvbn-c
|
||||
$MAKE -C src/zxcvbn-c || exit
|
||||
|
||||
if [ ! -d build ]; then mkdir build; fi
|
||||
|
||||
if [ "$BUILD_TYPE" == "Release" ]; then
|
||||
CONFIG="CONFIG+=release";
|
||||
BIN_PATH=release/bin
|
||||
else
|
||||
CONFIG="CONFIG+=debug"
|
||||
BIN_PATH=debug/bin
|
||||
fi
|
||||
|
||||
# Platform indepenent settings
|
||||
platform=$(get_platform)
|
||||
if [ "$platform" == "linux32" ] || [ "$platform" == "linux64" ]; then
|
||||
if [ "$ANDROID" != true ] && ([ "$platform" == "linux32" ] || [ "$platform" == "linux64" ]); then
|
||||
distro=$(lsb_release -is)
|
||||
if [ "$distro" == "Ubuntu" ]; then
|
||||
CONFIG="$CONFIG libunwind_off"
|
||||
@@ -47,18 +78,18 @@ fi
|
||||
|
||||
# force version update
|
||||
get_tag
|
||||
echo "var GUI_VERSION = \"$VERSIONTAG\"" > version.js
|
||||
echo "var GUI_VERSION = \"$TAGNAME\"" > version.js
|
||||
pushd "$MONERO_DIR"
|
||||
get_tag
|
||||
popd
|
||||
echo "var GUI_MONERO_VERSION = \"$VERSIONTAG\"" >> version.js
|
||||
echo "var GUI_MONERO_VERSION = \"$TAGNAME\"" >> version.js
|
||||
|
||||
cd build
|
||||
qmake ../monero-wallet-gui.pro "$CONFIG"
|
||||
make
|
||||
qmake ../monero-wallet-gui.pro "$CONFIG" || exit
|
||||
$MAKE || exit
|
||||
|
||||
# Copy monerod to bin folder
|
||||
if [ "$platform" != "mingw32" ]; then
|
||||
if [ "$platform" != "mingw32" ] && [ "$ANDROID" != true ]; then
|
||||
cp ../$MONERO_DIR/bin/$MONEROD_EXEC $BIN_PATH
|
||||
fi
|
||||
|
||||
|
||||
@@ -87,7 +87,6 @@ ListView {
|
||||
anchors.rightMargin: 40
|
||||
font.family: "Arial"
|
||||
font.pixelSize: 16
|
||||
font.letterSpacing: -1
|
||||
color: "#545454"
|
||||
text: address
|
||||
}
|
||||
@@ -101,7 +100,6 @@ ListView {
|
||||
width: 139
|
||||
font.family: "Arial"
|
||||
font.pixelSize: 12
|
||||
font.letterSpacing: -1
|
||||
color: "#535353"
|
||||
text: qsTr("Payment ID:") + translationManager.emptyString
|
||||
}
|
||||
@@ -117,7 +115,6 @@ ListView {
|
||||
|
||||
font.family: "Arial"
|
||||
font.pixelSize: 13
|
||||
font.letterSpacing: -1
|
||||
color: "#545454"
|
||||
text: paymentId
|
||||
}
|
||||
@@ -125,7 +122,7 @@ ListView {
|
||||
ListModel {
|
||||
id: dropModel
|
||||
ListElement { name: "<b>Copy address to clipboard</b>"; icon: "../images/dropdownCopy.png" }
|
||||
ListElement { name: "<b>Send to same destination</b>"; icon: "../images/dropdownSend.png" }
|
||||
ListElement { name: "<b>Send to this address</b>"; icon: "../images/dropdownSend.png" }
|
||||
// ListElement { name: "<b>Find similar transactions</b>"; icon: "../images/dropdownSearch.png" }
|
||||
ListElement { name: "<b>Remove from address book</b>"; icon: "../images/dropdownDel.png" }
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import QtQuick 2.0
|
||||
import QtQuick.Layouts 1.1
|
||||
|
||||
Item {
|
||||
id: checkBox
|
||||
@@ -40,6 +41,7 @@ Item {
|
||||
signal clicked()
|
||||
height: 25
|
||||
width: label.x + label.width
|
||||
Layout.minimumWidth: label.x + label.contentWidth
|
||||
clip: true
|
||||
|
||||
Rectangle {
|
||||
@@ -74,7 +76,6 @@ Item {
|
||||
anchors.leftMargin: 25 + 12
|
||||
font.family: "Arial"
|
||||
font.pixelSize: checkBox.fontSize
|
||||
font.letterSpacing: -1
|
||||
color: "#525252"
|
||||
}
|
||||
|
||||
|
||||
156
components/DaemonConsole.qml
Normal file
@@ -0,0 +1,156 @@
|
||||
// Copyright (c) 2014-2015, 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.0
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Dialogs 1.2
|
||||
import QtQuick.Layouts 1.1
|
||||
import QtQuick.Controls.Styles 1.4
|
||||
import QtQuick.Window 2.0
|
||||
|
||||
import "../components" as MoneroComponents
|
||||
|
||||
Window {
|
||||
id: root
|
||||
modality: Qt.ApplicationModal
|
||||
flags: Qt.Window | Qt.FramelessWindowHint
|
||||
property alias title: dialogTitle.text
|
||||
property alias text: dialogContent.text
|
||||
property alias content: root.text
|
||||
property alias okVisible: okButton.visible
|
||||
property alias textArea: dialogContent
|
||||
property var icon
|
||||
|
||||
// same signals as Dialog has
|
||||
signal accepted()
|
||||
signal rejected()
|
||||
|
||||
|
||||
function open() {
|
||||
show()
|
||||
}
|
||||
|
||||
// TODO: implement without hardcoding sizes
|
||||
width: 480
|
||||
height: 280
|
||||
|
||||
// Make window draggable
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
property point lastMousePos: Qt.point(0, 0)
|
||||
onPressed: { lastMousePos = Qt.point(mouseX, mouseY); }
|
||||
onMouseXChanged: root.x += (mouseX - lastMousePos.x)
|
||||
onMouseYChanged: root.y += (mouseY - lastMousePos.y)
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: mainLayout
|
||||
spacing: 10
|
||||
anchors { fill: parent; margins: 35 }
|
||||
|
||||
RowLayout {
|
||||
id: column
|
||||
//anchors {fill: parent; margins: 16 }
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
|
||||
Label {
|
||||
id: dialogTitle
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
font.pixelSize: 32
|
||||
font.family: "Arial"
|
||||
color: "#555555"
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
TextArea {
|
||||
id : dialogContent
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
font.family: "Arial"
|
||||
textFormat: TextEdit.AutoText
|
||||
readOnly: true
|
||||
font.pixelSize: 12
|
||||
}
|
||||
}
|
||||
|
||||
// Ok/Cancel buttons
|
||||
RowLayout {
|
||||
id: buttons
|
||||
spacing: 60
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
|
||||
MoneroComponents.StandardButton {
|
||||
id: okButton
|
||||
width: 120
|
||||
fontSize: 14
|
||||
shadowReleasedColor: "#FF4304"
|
||||
shadowPressedColor: "#B32D00"
|
||||
releasedColor: "#FF6C3C"
|
||||
pressedColor: "#FF4304"
|
||||
text: qsTr("Close") + translationManager.emptyString
|
||||
onClicked: {
|
||||
root.close()
|
||||
root.accepted()
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
MoneroComponents.LineEdit {
|
||||
id: sendCommandText
|
||||
width: 300
|
||||
placeholderText: qsTr("command + enter (e.g help)") + translationManager.emptyString
|
||||
onAccepted: {
|
||||
if(text.length > 0)
|
||||
daemonManager.sendCommand(text,currentWallet.testnet);
|
||||
text = ""
|
||||
}
|
||||
}
|
||||
|
||||
// Status button
|
||||
// MoneroComponents.StandardButton {
|
||||
// id: sendCommandButton
|
||||
// enabled: sendCommandText.text.length > 0
|
||||
// fontSize: 14
|
||||
// shadowReleasedColor: "#FF4304"
|
||||
// shadowPressedColor: "#B32D00"
|
||||
// releasedColor: "#FF6C3C"
|
||||
// pressedColor: "#FF4304"
|
||||
// text: qsTr("Send command")
|
||||
// onClicked: {
|
||||
// daemonManager.sendCommand(sendCommandText.text,currentWallet.testnet);
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -39,18 +39,29 @@ Window {
|
||||
id: root
|
||||
modality: Qt.ApplicationModal
|
||||
flags: Qt.Window | Qt.FramelessWindowHint
|
||||
|
||||
property int countDown: 5;
|
||||
signal rejected()
|
||||
signal started();
|
||||
|
||||
function open() {
|
||||
show()
|
||||
countDown = 5;
|
||||
timer.start();
|
||||
}
|
||||
|
||||
// TODO: implement without hardcoding sizes
|
||||
width: 480
|
||||
height: 200
|
||||
|
||||
// Make window draggable
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
property point lastMousePos: Qt.point(0, 0)
|
||||
onPressed: { lastMousePos = Qt.point(mouseX, mouseY); }
|
||||
onMouseXChanged: root.x += (mouseX - lastMousePos.x)
|
||||
onMouseYChanged: root.y += (mouseY - lastMousePos.y)
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: mainLayout
|
||||
spacing: 10
|
||||
@@ -61,15 +72,29 @@ Window {
|
||||
//anchors {fill: parent; margins: 16 }
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
|
||||
Label {
|
||||
text: qsTr("Daemon doesn't appear to be running")
|
||||
Timer {
|
||||
id: timer
|
||||
interval: 1000;
|
||||
running: false;
|
||||
repeat: true
|
||||
onTriggered: {
|
||||
countDown--;
|
||||
if(countDown < 0){
|
||||
running = false;
|
||||
// Start daemon
|
||||
root.close()
|
||||
appWindow.startDaemon(persistentSettings.daemonFlags);
|
||||
root.started();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
text: qsTr("Starting Monero daemon in %1 seconds").arg(countDown);
|
||||
font.pixelSize: 18
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.columnSpan: 2
|
||||
Layout.fillWidth: true
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
font.pixelSize: 24
|
||||
font.family: "Arial"
|
||||
color: "#555555"
|
||||
}
|
||||
|
||||
}
|
||||
@@ -81,57 +106,39 @@ Window {
|
||||
|
||||
MoneroComponents.StandardButton {
|
||||
id: okButton
|
||||
width: 120
|
||||
visible:false
|
||||
fontSize: 14
|
||||
shadowReleasedColor: "#FF4304"
|
||||
shadowPressedColor: "#B32D00"
|
||||
releasedColor: "#FF6C3C"
|
||||
pressedColor: "#FF4304"
|
||||
text: qsTr("Start daemon")
|
||||
text: qsTr("Start daemon (%1)").arg(countDown)
|
||||
KeyNavigation.tab: cancelButton
|
||||
onClicked: {
|
||||
timer.stop();
|
||||
root.close()
|
||||
appWindow.startDaemon(daemonFlags.text);
|
||||
appWindow.startDaemon(persistentSettings.daemonFlags);
|
||||
root.started()
|
||||
}
|
||||
}
|
||||
|
||||
MoneroComponents.StandardButton {
|
||||
id: cancelButton
|
||||
width: 120
|
||||
fontSize: 14
|
||||
shadowReleasedColor: "#FF4304"
|
||||
shadowPressedColor: "#B32D00"
|
||||
releasedColor: "#FF6C3C"
|
||||
pressedColor: "#FF4304"
|
||||
text: qsTr("Cancel")
|
||||
text: qsTr("Use custom settings")
|
||||
|
||||
onClicked: {
|
||||
timer.stop();
|
||||
root.close()
|
||||
root.rejected()
|
||||
}
|
||||
}
|
||||
}
|
||||
RowLayout {
|
||||
id: advancedRow
|
||||
MoneroComponents.Label {
|
||||
id: daemonFlagsLabel
|
||||
color: "#4A4949"
|
||||
text: qsTr("Daemon startup flags") + translationManager.emptyString
|
||||
fontSize: 16
|
||||
}
|
||||
|
||||
MoneroComponents.LineEdit {
|
||||
id: daemonFlags
|
||||
Layout.preferredWidth: 200
|
||||
Layout.fillWidth: true
|
||||
text: appWindow.persistentSettings.daemonFlags;
|
||||
placeholderText: qsTr("(optional)")
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -145,7 +145,6 @@ ListView {
|
||||
Text {
|
||||
font.family: "Arial"
|
||||
font.pixelSize: 18
|
||||
font.letterSpacing: -1
|
||||
color: "#000000"
|
||||
text: date
|
||||
}
|
||||
@@ -153,7 +152,6 @@ ListView {
|
||||
Text {
|
||||
font.family: "Arial"
|
||||
font.pixelSize: 18
|
||||
font.letterSpacing: -1
|
||||
color: "#000000"
|
||||
text: time
|
||||
}
|
||||
@@ -175,7 +173,6 @@ ListView {
|
||||
Text {
|
||||
font.family: "Arial"
|
||||
font.pixelSize: 18
|
||||
font.letterSpacing: -1
|
||||
color: "#000000"
|
||||
text: balance
|
||||
}
|
||||
@@ -208,7 +205,6 @@ ListView {
|
||||
anchors.bottom: parent.bottom
|
||||
font.family: "Arial"
|
||||
font.pixelSize: 18
|
||||
font.letterSpacing: -1
|
||||
color: out ? "#FF4F41" : "#36B05B"
|
||||
text: amount
|
||||
}
|
||||
@@ -220,7 +216,7 @@ ListView {
|
||||
id: dropModel
|
||||
ListElement { name: "<b>Copy address to clipboard</b>"; icon: "../images/dropdownCopy.png" }
|
||||
ListElement { name: "<b>Add to address book</b>"; icon: "../images/dropdownAdd.png" }
|
||||
ListElement { name: "<b>Send to same destination</b>"; icon: "../images/dropdownSend.png" }
|
||||
ListElement { name: "<b>Send to this address</b>"; icon: "../images/dropdownSend.png" }
|
||||
ListElement { name: "<b>Find similar transactions</b>"; icon: "../images/dropdownSearch.png" }
|
||||
}
|
||||
|
||||
|
||||
@@ -285,7 +285,6 @@ Item {
|
||||
anchors.centerIn: parent
|
||||
font.family: "Arial"
|
||||
font.pixelSize: 12
|
||||
font.letterSpacing: -1
|
||||
font.bold: dayArea.pressed
|
||||
text: styleData.date.getDate()
|
||||
color: {
|
||||
@@ -322,7 +321,6 @@ Item {
|
||||
elide: Text.ElideRight
|
||||
font.family: "Arial"
|
||||
font.pixelSize: 9
|
||||
font.letterSpacing: -1
|
||||
color: "#535353"
|
||||
text: {
|
||||
var locale = Qt.locale()
|
||||
@@ -339,7 +337,6 @@ Item {
|
||||
anchors.centerIn: parent
|
||||
font.family: "Arial"
|
||||
font.pixelSize: 12
|
||||
font.letterSpacing: -1
|
||||
color: "#4A4646"
|
||||
text: styleData.title
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
|
||||
import QtQuick 2.0
|
||||
import moneroComponents.Clipboard 1.0
|
||||
import moneroComponents.AddressBookModel 1.0
|
||||
|
||||
|
||||
ListView {
|
||||
@@ -36,6 +37,7 @@ ListView {
|
||||
boundsBehavior: ListView.StopAtBounds
|
||||
property var previousItem
|
||||
property int rowSpacing: 12
|
||||
property var addressBookModel: null
|
||||
|
||||
function buildTxDetailsString(tx_id, paymentId, tx_key,tx_note, destinations) {
|
||||
var trStart = '<tr><td width="85" style="padding-top:5px"><b>',
|
||||
@@ -52,6 +54,15 @@ ListView {
|
||||
+ 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)
|
||||
}
|
||||
|
||||
|
||||
footer: Rectangle {
|
||||
@@ -188,7 +199,6 @@ ListView {
|
||||
anchors.bottom: parent.bottom
|
||||
font.family: "Arial"
|
||||
font.pixelSize: 12
|
||||
font.letterSpacing: -1
|
||||
color: "#535353"
|
||||
text: paymentId !== "" ? qsTr("Payment ID:") + translationManager.emptyString : ""
|
||||
}
|
||||
@@ -202,11 +212,24 @@ ListView {
|
||||
//elide: Text.ElideRight
|
||||
font.family: "Arial"
|
||||
font.pixelSize:13
|
||||
font.letterSpacing: -1
|
||||
color: "#545454"
|
||||
text: paymentId
|
||||
|
||||
}
|
||||
// Address book lookup
|
||||
TextEdit {
|
||||
readOnly: true
|
||||
selectByMouse: true
|
||||
id: addressBookLookupValue
|
||||
width: 136
|
||||
anchors.bottom: parent.bottom
|
||||
//elide: Text.ElideRight
|
||||
font.family: "Arial"
|
||||
font.pixelSize:13
|
||||
color: "#545454"
|
||||
text: "(" + lookupPaymentID(paymentId) + ")"
|
||||
visible: text !== "()"
|
||||
}
|
||||
}
|
||||
Row {
|
||||
// block height row
|
||||
@@ -224,7 +247,6 @@ ListView {
|
||||
width: 86
|
||||
font.family: "Arial"
|
||||
font.pixelSize: 12
|
||||
font.letterSpacing: -1
|
||||
color: "#535353"
|
||||
text: qsTr("BlockHeight:") + translationManager.emptyString
|
||||
}
|
||||
@@ -237,9 +259,18 @@ ListView {
|
||||
//elide: Text.ElideRight
|
||||
font.family: "Arial"
|
||||
font.pixelSize: 13
|
||||
font.letterSpacing: -1
|
||||
color: "#545454"
|
||||
text: blockHeight
|
||||
color: (confirmations < confirmationsRequired)? "#FF6C3C" : "#545454"
|
||||
text: {
|
||||
if (!isPending)
|
||||
if(confirmations < confirmationsRequired)
|
||||
return blockHeight + " " + qsTr("(%1/%2 confirmations)").arg(confirmations).arg(confirmationsRequired)
|
||||
else
|
||||
return blockHeight
|
||||
if (!isOut)
|
||||
return qsTr("UNCONFIRMED") + translationManager.emptyString
|
||||
return qsTr("PENDING") + translationManager.emptyString
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -277,7 +308,6 @@ ListView {
|
||||
Text {
|
||||
font.family: "Arial"
|
||||
font.pixelSize: 18
|
||||
font.letterSpacing: -1
|
||||
color: "#000000"
|
||||
text: date
|
||||
}
|
||||
@@ -285,7 +315,6 @@ ListView {
|
||||
Text {
|
||||
font.family: "Arial"
|
||||
font.pixelSize: 18
|
||||
font.letterSpacing: -1
|
||||
color: "#000000"
|
||||
text: time
|
||||
}
|
||||
@@ -310,7 +339,6 @@ ListView {
|
||||
Text {
|
||||
font.family: "Arial"
|
||||
font.pixelSize: 18
|
||||
font.letterSpacing: -1
|
||||
color: "#000000"
|
||||
text: balance
|
||||
}
|
||||
@@ -320,7 +348,6 @@ ListView {
|
||||
// -- "Amount column
|
||||
Column {
|
||||
anchors.top: parent.top
|
||||
width: 148
|
||||
|
||||
Text {
|
||||
anchors.left: parent.left
|
||||
@@ -342,10 +369,10 @@ ListView {
|
||||
}
|
||||
|
||||
Text {
|
||||
id: amountText
|
||||
anchors.bottom: parent.bottom
|
||||
font.family: "Arial"
|
||||
font.pixelSize: 18
|
||||
font.letterSpacing: -1
|
||||
color: isOut ? "#FF4F41" : "#36B05B"
|
||||
text: displayAmount
|
||||
}
|
||||
@@ -371,7 +398,6 @@ ListView {
|
||||
anchors.bottom: parent.bottom
|
||||
font.family: "Arial"
|
||||
font.pixelSize: 18
|
||||
font.letterSpacing: -1
|
||||
color: "#FF4F41"
|
||||
text: fee
|
||||
}
|
||||
@@ -417,7 +443,7 @@ ListView {
|
||||
id: dropModel
|
||||
ListElement { name: "<b>Copy address to clipboard</b>"; icon: "../images/dropdownCopy.png" }
|
||||
ListElement { name: "<b>Add to address book</b>"; icon: "../images/dropdownAdd.png" }
|
||||
ListElement { name: "<b>Send to same destination</b>"; icon: "../images/dropdownSend.png" }
|
||||
ListElement { name: "<b>Send to this address</b>"; icon: "../images/dropdownSend.png" }
|
||||
ListElement { name: "<b>Find similar transactions</b>"; icon: "../images/dropdownSearch.png" }
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import QtQuick 2.0
|
||||
import QtQuick.Layouts 1.1
|
||||
|
||||
Item {
|
||||
id: item
|
||||
@@ -35,6 +36,7 @@ Item {
|
||||
property alias textFormat: label.textFormat
|
||||
property string tipText: ""
|
||||
property int fontSize: 12
|
||||
property alias wrapMode: label.wrapMode
|
||||
signal linkActivated()
|
||||
width: icon.x + icon.width
|
||||
height: icon.height
|
||||
@@ -59,23 +61,23 @@ Item {
|
||||
visible: appWindow.whatIsEnable
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: icon
|
||||
enabled: appWindow.whatIsEnable
|
||||
hoverEnabled: true
|
||||
onEntered: {
|
||||
icon.visible = false
|
||||
var pos = appWindow.mapFromItem(icon, 0, -15)
|
||||
tipItem.text = item.tipText
|
||||
tipItem.x = pos.x
|
||||
if(tipItem.height > 30)
|
||||
pos.y -= tipItem.height - 28
|
||||
tipItem.y = pos.y
|
||||
tipItem.visible = true
|
||||
}
|
||||
onExited: {
|
||||
icon.visible = Qt.binding(function(){ return appWindow.whatIsEnable; })
|
||||
tipItem.visible = false
|
||||
}
|
||||
}
|
||||
// MouseArea {
|
||||
// anchors.fill: icon
|
||||
// enabled: appWindow.whatIsEnable
|
||||
// hoverEnabled: true
|
||||
// onEntered: {
|
||||
// icon.visible = false
|
||||
// var pos = appWindow.mapFromItem(icon, 0, -15)
|
||||
// tipItem.text = item.tipText
|
||||
// tipItem.x = pos.x
|
||||
// if(tipItem.height > 30)
|
||||
// pos.y -= tipItem.height - 28
|
||||
// tipItem.y = pos.y
|
||||
// tipItem.visible = true
|
||||
// }
|
||||
// onExited: {
|
||||
// icon.visible = Qt.binding(function(){ return appWindow.whatIsEnable; })
|
||||
// tipItem.visible = false
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
@@ -29,14 +29,18 @@
|
||||
import QtQuick 2.0
|
||||
|
||||
Item {
|
||||
id: item
|
||||
property alias placeholderText: input.placeholderText
|
||||
property alias text: input.text
|
||||
property alias validator: input.validator
|
||||
property alias readOnly : input.readOnly
|
||||
property alias cursorPosition: input.cursorPosition
|
||||
property alias echoMode: input.echoMode
|
||||
property int fontSize: 18
|
||||
property bool error: false
|
||||
|
||||
signal editingFinished()
|
||||
signal accepted();
|
||||
signal textUpdated();
|
||||
|
||||
height: 37
|
||||
|
||||
@@ -67,5 +71,8 @@ Item {
|
||||
anchors.leftMargin: 4
|
||||
anchors.rightMargin: 30
|
||||
font.pixelSize: parent.fontSize
|
||||
onEditingFinished: item.editingFinished()
|
||||
onAccepted: item.accepted();
|
||||
onTextChanged: item.textUpdated()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ Rectangle {
|
||||
|
||||
color: checked ? "#FFFFFF" : "#1C1C1C"
|
||||
property bool present: !under || under.checked || checked || under.numSelectedChildren > 0
|
||||
height: present ? ((appWindow.height >= 800) ? 64 : 56) : 0
|
||||
height: present ? ((appWindow.height >= 800) ? 64 : 52) : 0
|
||||
|
||||
transform: Scale {
|
||||
yScale: button.present ? 1 : 0
|
||||
|
||||
119
components/MobileHeader.qml
Normal file
@@ -0,0 +1,119 @@
|
||||
import QtQuick 2.2
|
||||
import QtGraphicalEffects 1.0
|
||||
import QtQuick.Layouts 1.1
|
||||
import moneroComponents.Wallet 1.0
|
||||
|
||||
|
||||
// BasicPanel header
|
||||
Rectangle {
|
||||
id: header
|
||||
anchors.leftMargin: 1
|
||||
anchors.rightMargin: 1
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 64
|
||||
color: "#FFFFFF"
|
||||
// visible: basicMode
|
||||
|
||||
Image {
|
||||
id: logo
|
||||
visible: appWindow.width > 460
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.verticalCenterOffset: -5
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: appWindow.persistentSettings.customDecorations ? 20 : 40
|
||||
source: "../images/moneroLogo2.png"
|
||||
}
|
||||
|
||||
Image {
|
||||
id: icon
|
||||
visible: !logo.visible
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
// anchors.verticalCenterOffset: -5
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: appWindow.persistentSettings.customDecorations ? 20 : 40
|
||||
source: "../images/moneroIcon.png"
|
||||
}
|
||||
|
||||
Grid {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.top: parent.top
|
||||
anchors.right: parent.right
|
||||
anchors.topMargin: 10
|
||||
width: 256
|
||||
columns: 3
|
||||
|
||||
Text {
|
||||
id: balanceLabel
|
||||
width: 116
|
||||
height: 20
|
||||
font.family: "Arial"
|
||||
font.pixelSize: 12
|
||||
font.letterSpacing: -1
|
||||
elide: Text.ElideRight
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
verticalAlignment: Text.AlignBottom
|
||||
color: "#535353"
|
||||
text: leftPanel.balanceLabelText + ":"
|
||||
}
|
||||
|
||||
Text {
|
||||
id: balanceText
|
||||
width: 110
|
||||
height: 20
|
||||
font.family: "Arial"
|
||||
font.pixelSize: 18
|
||||
font.letterSpacing: -1
|
||||
elide: Text.ElideRight
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
verticalAlignment: Text.AlignBottom
|
||||
color: "#000000"
|
||||
text: leftPanel.balanceText
|
||||
}
|
||||
|
||||
Item {
|
||||
height: 20
|
||||
width: 20
|
||||
|
||||
Image {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: parent.left
|
||||
source: "../images/lockIcon.png"
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
width: 116
|
||||
height: 20
|
||||
font.family: "Arial"
|
||||
font.pixelSize: 12
|
||||
font.letterSpacing: -1
|
||||
elide: Text.ElideRight
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
verticalAlignment: Text.AlignBottom
|
||||
color: "#535353"
|
||||
text: qsTr("Unlocked Balance:")
|
||||
}
|
||||
|
||||
Text {
|
||||
id: availableBalanceText
|
||||
width: 110
|
||||
height: 20
|
||||
font.family: "Arial"
|
||||
font.pixelSize: 14
|
||||
font.letterSpacing: -1
|
||||
elide: Text.ElideRight
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
verticalAlignment: Text.AlignBottom
|
||||
color: "#000000"
|
||||
text: leftPanel.unlockedBalanceText
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
height: 1
|
||||
color: "#DBDBDB"
|
||||
}
|
||||
}
|
||||
@@ -48,8 +48,11 @@ Row {
|
||||
}
|
||||
|
||||
function getConnectionStatusString(status) {
|
||||
if (status == Wallet.ConnectionStatus_Connected)
|
||||
if (status == Wallet.ConnectionStatus_Connected) {
|
||||
if(!appWindow.daemonSynced)
|
||||
return qsTr("Synchronizing")
|
||||
return qsTr("Connected")
|
||||
}
|
||||
if (status == Wallet.ConnectionStatus_WrongVersion)
|
||||
return qsTr("Wrong version")
|
||||
if (status == Wallet.ConnectionStatus_Disconnected)
|
||||
@@ -79,7 +82,7 @@ Row {
|
||||
font.family: "Arial"
|
||||
font.pixelSize: 12
|
||||
color: "#545454"
|
||||
text: qsTr("Network status")
|
||||
text: qsTr("Network status") + translationManager.emptyString
|
||||
}
|
||||
|
||||
Text {
|
||||
|
||||
83
components/Notifier.qml
Normal file
@@ -0,0 +1,83 @@
|
||||
// Copyright (c) 2017, 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.0
|
||||
import QtQuick.Controls 1.4
|
||||
import moneroComponents.Wallet 1.0
|
||||
|
||||
Item {
|
||||
id: item
|
||||
property string message: ""
|
||||
property bool active: false
|
||||
height: 120
|
||||
width: 240
|
||||
property int margin: 15
|
||||
x: parent.width - width - margin
|
||||
y: parent.height - height * scale.yScale - margin * scale.yScale
|
||||
|
||||
Rectangle {
|
||||
color: "#FF6C3C"
|
||||
border.color: "black"
|
||||
anchors.fill: parent
|
||||
|
||||
TextArea {
|
||||
id:versionText
|
||||
readOnly: true
|
||||
backgroundVisible: false
|
||||
textFormat: TextEdit.AutoText
|
||||
anchors.fill: parent
|
||||
font.family: "Arial"
|
||||
font.pixelSize: 12
|
||||
textMargin: 20
|
||||
textColor: "white"
|
||||
text: item.message
|
||||
}
|
||||
}
|
||||
|
||||
transform: Scale {
|
||||
id: scale
|
||||
yScale: item.active ? 1 : 0
|
||||
|
||||
Behavior on yScale {
|
||||
NumberAnimation { duration: 500; easing.type: Easing.InOutCubic }
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: hider
|
||||
interval: 12000; running: false; repeat: false
|
||||
onTriggered: { item.active = false }
|
||||
}
|
||||
|
||||
function show(message) {
|
||||
item.visible = true
|
||||
item.message = message
|
||||
item.active = true
|
||||
hider.running = true
|
||||
}
|
||||
}
|
||||
@@ -52,17 +52,19 @@ Window {
|
||||
show()
|
||||
}
|
||||
|
||||
function usefulName(path) {
|
||||
// arbitrary "short enough" limit
|
||||
if (path.length < 32)
|
||||
return path
|
||||
return path.replace(/.*[\/\\]/, '').replace(/\.keys$/, '')
|
||||
}
|
||||
|
||||
// TODO: implement without hardcoding sizes
|
||||
width: 480
|
||||
height: walletName ? 240 : 200
|
||||
|
||||
// Make window draggable
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
property point lastMousePos: Qt.point(0, 0)
|
||||
onPressed: { lastMousePos = Qt.point(mouseX, mouseY); }
|
||||
onMouseXChanged: root.x += (mouseX - lastMousePos.x)
|
||||
onMouseYChanged: root.y += (mouseY - lastMousePos.y)
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: mainLayout
|
||||
spacing: 10
|
||||
@@ -74,7 +76,7 @@ Window {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
|
||||
Label {
|
||||
text: root.walletName.length > 0 ? qsTr("Please enter wallet password for:<br>") + usefulName(root.walletName) : qsTr("Please enter wallet password")
|
||||
text: root.walletName.length > 0 ? qsTr("Please enter wallet password for:<br>") + root.walletName : qsTr("Please enter wallet password")
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.columnSpan: 2
|
||||
Layout.fillWidth: true
|
||||
@@ -107,12 +109,14 @@ Window {
|
||||
}
|
||||
}
|
||||
Keys.onReturnPressed: {
|
||||
root.accepted()
|
||||
root.close()
|
||||
root.accepted()
|
||||
|
||||
}
|
||||
Keys.onEscapePressed: {
|
||||
root.rejected()
|
||||
root.close()
|
||||
root.rejected()
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -149,7 +153,7 @@ Window {
|
||||
shadowPressedColor: "#B32D00"
|
||||
releasedColor: "#FF6C3C"
|
||||
pressedColor: "#FF4304"
|
||||
text: qsTr("Cancel")
|
||||
text: qsTr("Cancel") + translationManager.emptyString
|
||||
KeyNavigation.tab: passwordInput
|
||||
onClicked: {
|
||||
root.close()
|
||||
|
||||
@@ -64,7 +64,7 @@ Item {
|
||||
|
||||
color: {
|
||||
if(item.fillLevel < 3) return "#FF6C3C"
|
||||
if(item.fillLevel < 13) return "#FFE00A"
|
||||
if(item.fillLevel < 13) return "#AAFFBB"
|
||||
return "#36B25C"
|
||||
}
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ Item {
|
||||
|
||||
color: {
|
||||
if(item.fillLevel < 5) return "#FF6C3C"
|
||||
if(item.fillLevel < 13) return "#FFE00A"
|
||||
if(item.fillLevel < 13) return "#AAFFBB"
|
||||
return "#36B25C"
|
||||
}
|
||||
|
||||
@@ -94,34 +94,28 @@ Item {
|
||||
Text {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
font.family: "Arial"
|
||||
font.pixelSize: 11
|
||||
font.letterSpacing: -1
|
||||
font.bold: true
|
||||
font.pixelSize: 15
|
||||
color: "#000000"
|
||||
x: row.x + (row.positions[0] !== undefined ? row.positions[0].currentX - 3 : 0) - width
|
||||
text: qsTr("LOW") + translationManager.emptyString
|
||||
text: qsTr("Low") + translationManager.emptyString
|
||||
}
|
||||
|
||||
Text {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
font.family: "Arial"
|
||||
font.pixelSize: 11
|
||||
font.letterSpacing: -1
|
||||
font.bold: true
|
||||
font.pixelSize: 15
|
||||
color: "#000000"
|
||||
x: row.x + (row.positions[4] !== undefined ? row.positions[4].currentX - 3 : 0) - width
|
||||
text: qsTr("MEDIUM") + translationManager.emptyString
|
||||
text: qsTr("Medium") + translationManager.emptyString
|
||||
}
|
||||
|
||||
Text {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
font.family: "Arial"
|
||||
font.pixelSize: 11
|
||||
font.letterSpacing: -1
|
||||
font.bold: true
|
||||
font.pixelSize: 15
|
||||
color: "#000000"
|
||||
x: row.x + (row.positions[13] !== undefined ? row.positions[13].currentX - 3 : 0) - width
|
||||
text: qsTr("HIGH") + translationManager.emptyString
|
||||
text: qsTr("High") + translationManager.emptyString
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
|
||||
@@ -61,7 +61,7 @@ Window {
|
||||
id: messageTitle
|
||||
text: "Please wait..."
|
||||
font {
|
||||
pointSize: 22
|
||||
pixelSize: 22
|
||||
}
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
|
||||
@@ -72,7 +72,7 @@ Window {
|
||||
Text {
|
||||
id: heightProgress
|
||||
font {
|
||||
pointSize: 18
|
||||
pixelSize: 18
|
||||
}
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
|
||||
|
||||
@@ -37,12 +37,25 @@ Item {
|
||||
visible: false
|
||||
//clip: true
|
||||
|
||||
function updateProgress(currentBlock,targetBlock){
|
||||
function updateProgress(currentBlock,targetBlock, blocksToSync){
|
||||
if(targetBlock == 1) {
|
||||
fillLevel = 0
|
||||
progressText.text = qsTr("Establishing connection...");
|
||||
progressBar.visible = true
|
||||
return
|
||||
}
|
||||
|
||||
if(targetBlock > 0) {
|
||||
var progressLevel = ((currentBlock/targetBlock) * 100).toFixed(0);
|
||||
var remaining = targetBlock - currentBlock
|
||||
// wallet sync
|
||||
if(blocksToSync > 0)
|
||||
var progressLevel = (100*(blocksToSync - remaining)/blocksToSync).toFixed(0);
|
||||
// Daemon sync
|
||||
else
|
||||
var progressLevel = (100*(currentBlock/targetBlock)).toFixed(0);
|
||||
fillLevel = progressLevel
|
||||
progressText.text = qsTr("Synchronizing blocks %1/%2").arg(currentBlock.toFixed(0)).arg(targetBlock.toFixed(0));
|
||||
item.visible = (currentWallet.connected !== Wallet.ConnectionStatus_Disconnected) && (currentBlock < targetBlock)
|
||||
progressText.text = qsTr("Blocks remaining: %1").arg(remaining.toFixed(0));
|
||||
progressBar.visible = currentBlock < targetBlock
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
141
components/QRCodeScanner.qml
Normal file
@@ -0,0 +1,141 @@
|
||||
// Copyright (c) 2014-2017, 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.0
|
||||
import QtMultimedia 5.4
|
||||
import QtQuick.Dialogs 1.2
|
||||
import moneroComponents.QRCodeScanner 1.0
|
||||
|
||||
Rectangle {
|
||||
id : root
|
||||
|
||||
x: 0
|
||||
y: 0
|
||||
z: parent.z+1
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
|
||||
visible: false
|
||||
color: "black"
|
||||
state: "Stopped"
|
||||
|
||||
signal qrcode_decoded(string address, string payment_id, string amount, string tx_description, string recipient_name)
|
||||
|
||||
states: [
|
||||
State {
|
||||
name: "Capture"
|
||||
StateChangeScript {
|
||||
script: {
|
||||
root.visible = true
|
||||
camera.captureMode = Camera.CaptureStillImage
|
||||
camera.start()
|
||||
finder.enabled = true
|
||||
}
|
||||
}
|
||||
},
|
||||
State {
|
||||
name: "Stopped"
|
||||
StateChangeScript {
|
||||
script: {
|
||||
camera.stop()
|
||||
root.visible = false
|
||||
finder.enabled = false
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
Camera {
|
||||
id: camera
|
||||
objectName: "qrCameraQML"
|
||||
captureMode: Camera.CaptureStillImage
|
||||
|
||||
focus {
|
||||
focusMode: Camera.FocusContinuous
|
||||
}
|
||||
}
|
||||
QRCodeScanner {
|
||||
id : finder
|
||||
objectName: "QrFinder"
|
||||
onDecoded : {
|
||||
root.qrcode_decoded(address, payment_id, amount, tx_description, recipient_name)
|
||||
root.state = "Stopped"
|
||||
}
|
||||
onNotifyError : {
|
||||
if( warning )
|
||||
messageDialog.icon = StandardIcon.Critical
|
||||
else {
|
||||
messageDialog.icon = StandardIcon.Warning
|
||||
root.state = "Stopped"
|
||||
}
|
||||
messageDialog.text = error
|
||||
messageDialog.visible = true
|
||||
}
|
||||
}
|
||||
|
||||
VideoOutput {
|
||||
id: viewfinder
|
||||
visible: root.state == "Capture"
|
||||
|
||||
x: 0
|
||||
y: 0
|
||||
z: parent.z+1
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
|
||||
source: camera
|
||||
autoOrientation: true
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
propagateComposedEvents: true
|
||||
onPressAndHold: {
|
||||
if (camera.lockStatus == Camera.locked)camera.unlock()
|
||||
camera.searchAndLock()
|
||||
}
|
||||
onDoubleClicked: {
|
||||
root.state = "Stopped"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MessageDialog {
|
||||
id: messageDialog
|
||||
title: "Scanning QrCode"
|
||||
onAccepted: {
|
||||
root.state = "Stopped"
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
if( QtMultimedia.availableCameras.length == 0) {
|
||||
console.log("No camera available. Disable qrScannerEnabled");
|
||||
appWindow.qrScannerEnabled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -100,7 +100,6 @@ Item {
|
||||
font.family: "Arial"
|
||||
font.pixelSize: 12
|
||||
font.bold: true
|
||||
font.letterSpacing: -1
|
||||
color: "#4A4747"
|
||||
text: "NAME"
|
||||
}
|
||||
@@ -195,7 +194,6 @@ Item {
|
||||
anchors.rightMargin: 12
|
||||
font.family: "Arial"
|
||||
font.bold: true
|
||||
font.letterSpacing: -1
|
||||
font.pixelSize: 12
|
||||
color: delegateArea.pressed || parent.isCurrent ? "#FFFFFF" : "#4A4646"
|
||||
text: name
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import QtQuick 2.0
|
||||
import QtQuick.Layouts 1.1
|
||||
|
||||
Item {
|
||||
id: button
|
||||
@@ -41,6 +42,8 @@ Item {
|
||||
property alias text: label.text
|
||||
signal clicked()
|
||||
|
||||
// Dynamic label width
|
||||
Layout.minimumWidth: (label.contentWidth > 80)? label.contentWidth + 20 : 100
|
||||
|
||||
Rectangle {
|
||||
anchors.left: parent.left
|
||||
@@ -78,13 +81,12 @@ Item {
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
elide: Text.ElideRight
|
||||
font.family: "Arial"
|
||||
font.bold: true
|
||||
font.letterSpacing: -1
|
||||
font.pixelSize: button.fontSize
|
||||
color: parent.textColor
|
||||
visible: parent.icon === ""
|
||||
// font.capitalization : Font.Capitalize
|
||||
}
|
||||
|
||||
Image {
|
||||
|
||||
@@ -45,12 +45,23 @@ Window {
|
||||
property alias cancelVisible: cancelButton.visible
|
||||
property alias okVisible: okButton.visible
|
||||
property alias textArea: dialogContent
|
||||
property alias okText: okButton.text
|
||||
property alias cancelText: cancelButton.text
|
||||
|
||||
property var icon
|
||||
|
||||
// same signals as Dialog has
|
||||
signal accepted()
|
||||
signal rejected()
|
||||
|
||||
// Make window draggable
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
property point lastMousePos: Qt.point(0, 0)
|
||||
onPressed: { lastMousePos = Qt.point(mouseX, mouseY); }
|
||||
onMouseXChanged: root.x += (mouseX - lastMousePos.x)
|
||||
onMouseYChanged: root.y += (mouseY - lastMousePos.y)
|
||||
}
|
||||
|
||||
function open() {
|
||||
show()
|
||||
@@ -98,6 +109,21 @@ Window {
|
||||
spacing: 60
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
|
||||
MoneroComponents.StandardButton {
|
||||
id: cancelButton
|
||||
width: 120
|
||||
fontSize: 14
|
||||
shadowReleasedColor: "#FF4304"
|
||||
shadowPressedColor: "#B32D00"
|
||||
releasedColor: "#FF6C3C"
|
||||
pressedColor: "#FF4304"
|
||||
text: qsTr("Cancel") + translationManager.emptyString
|
||||
onClicked: {
|
||||
root.close()
|
||||
root.rejected()
|
||||
}
|
||||
}
|
||||
|
||||
MoneroComponents.StandardButton {
|
||||
id: okButton
|
||||
width: 120
|
||||
@@ -114,21 +140,6 @@ Window {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
MoneroComponents.StandardButton {
|
||||
id: cancelButton
|
||||
width: 120
|
||||
fontSize: 14
|
||||
shadowReleasedColor: "#FF4304"
|
||||
shadowPressedColor: "#B32D00"
|
||||
releasedColor: "#FF6C3C"
|
||||
pressedColor: "#FF4304"
|
||||
text: qsTr("Cancel")
|
||||
onClicked: {
|
||||
root.close()
|
||||
root.rejected()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -107,7 +107,7 @@ Item {
|
||||
font.bold: true
|
||||
font.pixelSize: 12
|
||||
color: "#FFFFFF"
|
||||
text: repeater.model.get(column.currentIndex).column1
|
||||
text: column.currentIndex < repeater.model.rowCount() ? qsTr(repeater.model.get(column.currentIndex).column1) + translationManager.emptyString : ""
|
||||
}
|
||||
|
||||
Text {
|
||||
@@ -119,7 +119,7 @@ Item {
|
||||
font.family: "Arial"
|
||||
font.pixelSize: 12
|
||||
color: "#FFFFFF"
|
||||
text: repeater.model.get(column.currentIndex).column2
|
||||
text: column.currentIndex < repeater.model.rowCount() ? qsTr(repeater.model.get(column.currentIndex).column2) + translationManager.emptyString : ""
|
||||
|
||||
property int w: 0
|
||||
Component.onCompleted: w = implicitWidth
|
||||
@@ -193,6 +193,19 @@ Item {
|
||||
Repeater {
|
||||
id: repeater
|
||||
|
||||
// Workaround for translations in listElements. All translated strings needs to be listed in this file.
|
||||
property string stringLow: qsTr("Low (x1 fee)") + translationManager.emptyString
|
||||
property string stringMedium: qsTr("Medium (x20 fee)") + translationManager.emptyString
|
||||
property string stringHigh: qsTr("High (x166 fee)") + translationManager.emptyString
|
||||
property string stringSlow: qsTr("Slow (x0.25 fee)") + translationManager.emptyString
|
||||
property string stringDefault: qsTr("Default (x1 fee)") + translationManager.emptyString
|
||||
property string stringFast: qsTr("Fast (x5 fee)") + translationManager.emptyString
|
||||
property string stringFastest: qsTr("Fastest (x41.5 fee)") + translationManager.emptyString
|
||||
property string stringAll: qsTr("All") + translationManager.emptyString
|
||||
property string stringSent: qsTr("Sent") + translationManager.emptyString
|
||||
property string stringReceived: qsTr("Received") + translationManager.emptyString
|
||||
|
||||
|
||||
delegate: Rectangle {
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
@@ -210,7 +223,7 @@ Item {
|
||||
font.bold: true
|
||||
font.pixelSize: 12
|
||||
color: "#FFFFFF"
|
||||
text: column1
|
||||
text: qsTr(column1) + translationManager.emptyString
|
||||
}
|
||||
|
||||
Text {
|
||||
|
||||
@@ -177,6 +177,13 @@ Item {
|
||||
|
||||
Repeater {
|
||||
id: repeater
|
||||
|
||||
// Workaround for translations in listElements. All translated strings needs to be listed in this file.
|
||||
property string stringCopy: qsTr("<b>Copy address to clipboard</b>") + translationManager.emptyString
|
||||
property string stringSend: qsTr("<b>Send to this address</b>") + translationManager.emptyString
|
||||
property string stringFind: qsTr("<b>Find similar transactions</b>") + translationManager.emptyString
|
||||
property string stringRemove: qsTr("<b>Remove from address book</b>") + translationManager.emptyString
|
||||
|
||||
delegate: Rectangle {
|
||||
id: delegate
|
||||
property bool containsMouse: index === mouseArea.currentIndex
|
||||
@@ -211,7 +218,7 @@ Item {
|
||||
onContainsMouseChanged: {
|
||||
if(containsMouse) {
|
||||
var pos = rootItem.mapFromItem(delegate, 30, -25)
|
||||
appWindow.toolTip.text = name
|
||||
appWindow.toolTip.text = qsTr(name) + translationManager.emptyString
|
||||
appWindow.toolTip.x = pos.x - appWindow.toolTip.width
|
||||
// if(appWindow.toolTip.height > 30)
|
||||
// pos.y -= appWindow.toolTip.height - 30
|
||||
|
||||
@@ -60,6 +60,13 @@ Rectangle {
|
||||
|
||||
Repeater {
|
||||
id: columnsRepeater
|
||||
|
||||
// Workaround for translations in listElements. All translated strings needs to be listed in this file.
|
||||
property string stringPaymentID: qsTr("Payment ID") + translationManager.emptyString
|
||||
property string stringDate: qsTr("Date") + translationManager.emptyString
|
||||
property string stringBlockHeight: qsTr("Block height") + translationManager.emptyString
|
||||
property string stringAmount: qsTr("Amount") + translationManager.emptyString
|
||||
|
||||
delegate: Rectangle {
|
||||
id: delegate
|
||||
property bool desc: false
|
||||
@@ -81,7 +88,7 @@ Rectangle {
|
||||
return "#FF4304"
|
||||
return index === header.activeSortColumn || delegateArea.containsMouse ? "#FF6C3C" : "#4A4949"
|
||||
}
|
||||
text: columnName
|
||||
text: qsTr(columnName) + translationManager.emptyString
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
|
||||
7
components/TextBlock.qml
Normal file
@@ -0,0 +1,7 @@
|
||||
import QtQuick 2.0
|
||||
|
||||
TextEdit {
|
||||
wrapMode: Text.Wrap
|
||||
readOnly: true
|
||||
selectByMouse: true
|
||||
}
|
||||
@@ -52,9 +52,9 @@ Item {
|
||||
font.pixelSize: 12
|
||||
color: "#4A4949"
|
||||
text: {
|
||||
if(currentIndex === 0) return qsTr("LOW") + translationManager.emptyString
|
||||
if(currentIndex === 3) return qsTr("MEDIUM") + translationManager.emptyString
|
||||
if(currentIndex === 13) return qsTr("HIGH") + translationManager.emptyString
|
||||
if(currentIndex === 0) return qsTr("Normal") + translationManager.emptyString
|
||||
if(currentIndex === 3) return qsTr("Medium") + translationManager.emptyString
|
||||
if(currentIndex === 13) return qsTr("High") + translationManager.emptyString
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,7 +65,6 @@ Window {
|
||||
lineHeight: 0.7
|
||||
font.family: "Arial"
|
||||
font.pixelSize: 12
|
||||
font.letterSpacing: -1
|
||||
color: "#FFFFFF"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,43 +41,42 @@ Rectangle {
|
||||
y: -height
|
||||
property string title
|
||||
property alias maximizeButtonVisible: maximizeButton.visible
|
||||
z: 1
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
font.family: "Arial"
|
||||
font.pixelSize: 15
|
||||
font.letterSpacing: -1
|
||||
color: "#FFFFFF"
|
||||
text: titleBar.title
|
||||
visible: customDecorations
|
||||
}
|
||||
|
||||
Behavior on y {
|
||||
NumberAnimation { duration: 100; easing.type: Easing.InQuad }
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: goToBasicVersionButton
|
||||
property bool containsMouse: titleBar.mouseX >= x && titleBar.mouseX <= x + width
|
||||
property bool checked: false
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
color: containsMouse || checked ? "#FFE00A" : "#000000"
|
||||
color: basicMouseArea.containsMouse || !leftPanel.visible ? "#FFE00A" : "#000000"
|
||||
height: 30
|
||||
width: height
|
||||
visible: isMobile
|
||||
|
||||
Image {
|
||||
anchors.centerIn: parent
|
||||
rotation: parent.checked ? 180 : 0
|
||||
source: parent.containsMouse || parent.checked ? "../images/goToBasicVersionHovered.png" :
|
||||
rotation: !leftPanel.visible ? 180 : 0
|
||||
source: parent.customDecorations || !leftPanel.visible ? "../images/goToBasicVersionHovered.png" :
|
||||
"../images/gotoBasicVersion.png"
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: basicMouseArea
|
||||
hoverEnabled: true
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
parent.checked = !parent.checked
|
||||
titleBar.goToBasicVersion(parent.checked)
|
||||
titleBar.goToBasicVersion(leftPanel.visible)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,39 +1,121 @@
|
||||
#!/bin/bash
|
||||
|
||||
|
||||
MONERO_URL=https://github.com/monero-project/monero.git
|
||||
MONERO_BRANCH=master
|
||||
# MONERO_URL=https://github.com/mbg033/monero.git
|
||||
# MONERO_BRANCH=develop
|
||||
# Buidling "debug" build optionally
|
||||
BUILD_TYPE=$1
|
||||
if [ -z $BUILD_TYPE ]; then
|
||||
BUILD_TYPE=Release
|
||||
fi
|
||||
# thanks to SO: http://stackoverflow.com/a/20283965/4118915
|
||||
if test -z "$CPU_CORE_COUNT"; then
|
||||
CPU_CORE_COUNT=$(grep -c ^processor /proc/cpuinfo 2>/dev/null || sysctl -n hw.ncpu)
|
||||
fi
|
||||
|
||||
pushd $(pwd)
|
||||
ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
|
||||
source $ROOT_DIR/utils.sh
|
||||
|
||||
|
||||
INSTALL_DIR=$ROOT_DIR/wallet
|
||||
MONERO_DIR=$ROOT_DIR/monero
|
||||
BUILD_LIBWALLET=false
|
||||
|
||||
# init and update monero submodule
|
||||
if [ ! -d $MONERO_DIR/src ]; then
|
||||
git submodule init monero
|
||||
fi
|
||||
git submodule update --remote
|
||||
git -C $MONERO_DIR fetch
|
||||
git -C $MONERO_DIR checkout release-v0.11.0.0
|
||||
|
||||
if [ ! -d $MONERO_DIR ]; then
|
||||
git clone --depth=1 $MONERO_URL $MONERO_DIR --branch $MONERO_BRANCH --single-branch
|
||||
# get monero core tag
|
||||
get_tag
|
||||
# create local monero branch
|
||||
git -C $MONERO_DIR checkout -B $VERSIONTAG
|
||||
|
||||
# Merge monero PR dependencies
|
||||
|
||||
# Workaround for git username requirements
|
||||
# Save current user settings and revert back when we are done with merging PR's
|
||||
OLD_GIT_USER=$(git -C $MONERO_DIR config --local user.name)
|
||||
OLD_GIT_EMAIL=$(git -C $MONERO_DIR config --local user.email)
|
||||
git -C $MONERO_DIR config user.name "Monero GUI"
|
||||
git -C $MONERO_DIR config user.email "gui@monero.local"
|
||||
# check for PR requirements in most recent commit message (i.e requires #xxxx)
|
||||
for PR in $(git log --format=%B -n 1 | grep -io "requires #[0-9]*" | sed 's/[^0-9]*//g'); do
|
||||
echo "Merging monero push request #$PR"
|
||||
# fetch pull request and merge
|
||||
git -C $MONERO_DIR fetch origin pull/$PR/head:PR-$PR
|
||||
git -C $MONERO_DIR merge --quiet PR-$PR -m "Merge monero PR #$PR"
|
||||
BUILD_LIBWALLET=true
|
||||
done
|
||||
|
||||
# revert back to old git config
|
||||
$(git -C $MONERO_DIR config user.name "$OLD_GIT_USER")
|
||||
$(git -C $MONERO_DIR config user.email "$OLD_GIT_EMAIL")
|
||||
|
||||
# Build libwallet if it doesnt exist
|
||||
if [ ! -f $MONERO_DIR/lib/libwallet_merged.a ]; then
|
||||
echo "libwallet_merged.a not found - Building libwallet"
|
||||
BUILD_LIBWALLET=true
|
||||
# Build libwallet if no previous version file exists
|
||||
elif [ ! -f $MONERO_DIR/version.sh ]; then
|
||||
echo "monero/version.h not found - Building libwallet"
|
||||
BUILD_LIBWALLET=true
|
||||
## Compare previously built version with submodule + merged PR's version.
|
||||
else
|
||||
cd $MONERO_DIR;
|
||||
git checkout $MONERO_BRANCH
|
||||
git pull;
|
||||
source $MONERO_DIR/version.sh
|
||||
# compare submodule version with latest build
|
||||
pushd "$MONERO_DIR"
|
||||
get_tag
|
||||
popd
|
||||
echo "latest libwallet version: $GUI_MONERO_VERSION"
|
||||
echo "Installed libwallet version: $VERSIONTAG"
|
||||
# check if recent
|
||||
if [ "$VERSIONTAG" != "$GUI_MONERO_VERSION" ]; then
|
||||
echo "Building new libwallet version $GUI_MONERO_VERSION"
|
||||
BUILD_LIBWALLET=true
|
||||
else
|
||||
echo "latest libwallet ($GUI_MONERO_VERSION) is already built. Remove monero/lib/libwallet_merged.a to force rebuild"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$BUILD_LIBWALLET" != true ]; then
|
||||
# exit this script
|
||||
return
|
||||
fi
|
||||
|
||||
echo "GUI_MONERO_VERSION=\"$VERSIONTAG\"" > $MONERO_DIR/version.sh
|
||||
|
||||
## Continue building libwallet
|
||||
|
||||
# default build type
|
||||
BUILD_TYPE=$1
|
||||
if [ -z $BUILD_TYPE ]; then
|
||||
BUILD_TYPE=release
|
||||
fi
|
||||
|
||||
STATIC=false
|
||||
ANDROID=false
|
||||
if [ "$BUILD_TYPE" == "release" ]; then
|
||||
echo "Building libwallet release"
|
||||
CMAKE_BUILD_TYPE=Release
|
||||
elif [ "$BUILD_TYPE" == "release-static" ]; then
|
||||
echo "Building libwallet release-static"
|
||||
CMAKE_BUILD_TYPE=Release
|
||||
STATIC=true
|
||||
elif [ "$BUILD_TYPE" == "release-android" ]; then
|
||||
echo "Building libwallet release-static for ANDROID"
|
||||
CMAKE_BUILD_TYPE=Release
|
||||
STATIC=true
|
||||
ANDROID=true
|
||||
elif [ "$BUILD_TYPE" == "debug-android" ]; then
|
||||
echo "Building libwallet debug-static for ANDROID"
|
||||
CMAKE_BUILD_TYPE=Debug
|
||||
STATIC=true
|
||||
ANDROID=true
|
||||
elif [ "$BUILD_TYPE" == "debug" ]; then
|
||||
echo "Building libwallet debug"
|
||||
CMAKE_BUILD_TYPE=Debug
|
||||
else
|
||||
echo "Valid build types are release, release-static, release-android, debug-android and debug"
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
|
||||
echo "cleaning up existing monero build dir, libs and includes"
|
||||
rm -fr $MONERO_DIR/build
|
||||
#rm -fr $MONERO_DIR/build
|
||||
rm -fr $MONERO_DIR/lib
|
||||
rm -fr $MONERO_DIR/include
|
||||
rm -fr $MONERO_DIR/bin
|
||||
@@ -46,38 +128,84 @@ pushd $MONERO_DIR/build/release
|
||||
platform=$(get_platform)
|
||||
# default make executable
|
||||
make_exec="make"
|
||||
|
||||
## OS X
|
||||
if [ "$platform" == "darwin" ]; then
|
||||
# Do something under Mac OS X platform
|
||||
echo "Configuring build for MacOS.."
|
||||
cmake -D CMAKE_BUILD_TYPE=$BUILD_TYPE -D STATIC=ON -D ARCH="x86-64" -D BUILD_64=ON -D BUILD_GUI_DEPS=ON -D INSTALL_VENDORED_LIBUNBOUND=ON -D CMAKE_INSTALL_PREFIX="$MONERO_DIR" ../..
|
||||
if [ "$STATIC" == true ]; then
|
||||
cmake -D CMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE -D STATIC=ON -D ARCH="x86-64" -D BUILD_64=ON -D BUILD_GUI_DEPS=ON -D INSTALL_VENDORED_LIBUNBOUND=ON -D CMAKE_INSTALL_PREFIX="$MONERO_DIR" ../..
|
||||
else
|
||||
cmake -D CMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE -D BUILD_GUI_DEPS=ON -D INSTALL_VENDORED_LIBUNBOUND=ON -D CMAKE_INSTALL_PREFIX="$MONERO_DIR" ../..
|
||||
fi
|
||||
|
||||
## LINUX 64
|
||||
elif [ "$platform" == "linux64" ]; then
|
||||
# Do something under GNU/Linux platform
|
||||
echo "Configuring build for Linux x64"
|
||||
cmake -D CMAKE_BUILD_TYPE=$BUILD_TYPE -D STATIC=ON -D ARCH="x86-64" -D BUILD_64=ON -D BUILD_GUI_DEPS=ON -D CMAKE_INSTALL_PREFIX="$MONERO_DIR" ../..
|
||||
if [ "$ANDROID" == true ]; then
|
||||
echo "Configuring build for Android on Linux host"
|
||||
cmake -D CMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE -D STATIC=ON -D ARCH="armv7-a" -D ANDROID=true -D BUILD_GUI_DEPS=ON -D USE_LTO=OFF -D INSTALL_VENDORED_LIBUNBOUND=ON -D CMAKE_INSTALL_PREFIX="$MONERO_DIR" ../..
|
||||
elif [ "$STATIC" == true ]; then
|
||||
cmake -D CMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE -D STATIC=ON -D ARCH="x86-64" -D BUILD_64=ON -D BUILD_GUI_DEPS=ON -D INSTALL_VENDORED_LIBUNBOUND=ON -D CMAKE_INSTALL_PREFIX="$MONERO_DIR" ../..
|
||||
else
|
||||
cmake -D CMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE -D BUILD_GUI_DEPS=ON -D CMAKE_INSTALL_PREFIX="$MONERO_DIR" ../..
|
||||
fi
|
||||
|
||||
## LINUX 32
|
||||
elif [ "$platform" == "linux32" ]; then
|
||||
# Do something under GNU/Linux platform
|
||||
echo "Configuring build for Linux i686"
|
||||
cmake -D CMAKE_BUILD_TYPE=$BUILD_TYPE -D STATIC=ON -D ARCH="i686" -D BUILD_64=OFF -D BUILD_GUI_DEPS=ON -D CMAKE_INSTALL_PREFIX="$MONERO_DIR" ../..
|
||||
if [ "$STATIC" == true ]; then
|
||||
cmake -D CMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE -D STATIC=ON -D ARCH="i686" -D BUILD_64=OFF -D BUILD_GUI_DEPS=ON -D INSTALL_VENDORED_LIBUNBOUND=ON -D CMAKE_INSTALL_PREFIX="$MONERO_DIR" ../..
|
||||
else
|
||||
cmake -D CMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE -D BUILD_GUI_DEPS=ON -D CMAKE_INSTALL_PREFIX="$MONERO_DIR" ../..
|
||||
fi
|
||||
|
||||
## LINUX ARMv7
|
||||
elif [ "$platform" == "linuxarmv7" ]; then
|
||||
echo "Configuring build for Linux armv7"
|
||||
if [ "$STATIC" == true ]; then
|
||||
cmake -D BUILD_TESTS=OFF -D ARCH="armv7-a" -D STATIC=ON -D BUILD_64=OFF -D BUILD_GUI_DEPS=ON -D CMAKE_INSTALL_PREFIX="$MONERO_DIR" ../..
|
||||
else
|
||||
cmake -D BUILD_TESTS=OFF -D ARCH="armv7-a" -D -D BUILD_64=OFF -D BUILD_GUI_DEPS=ON -D CMAKE_INSTALL_PREFIX="$MONERO_DIR" ../..
|
||||
fi
|
||||
|
||||
## LINUX other
|
||||
elif [ "$platform" == "linux" ]; then
|
||||
echo "Configuring build for Linux general"
|
||||
cmake -D CMAKE_BUILD_TYPE=$BUILD_TYPE -D STATIC=ON -D BUILD_GUI_DEPS=ON -D CMAKE_INSTALL_PREFIX="$MONERO_DIR" ../..
|
||||
if [ "$STATIC" == true ]; then
|
||||
cmake -D CMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE -D STATIC=ON -D BUILD_GUI_DEPS=ON -D INSTALL_VENDORED_LIBUNBOUND=ON -D CMAKE_INSTALL_PREFIX="$MONERO_DIR" ../..
|
||||
else
|
||||
cmake -D CMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE -D BUILD_GUI_DEPS=ON -D CMAKE_INSTALL_PREFIX="$MONERO_DIR" ../..
|
||||
fi
|
||||
|
||||
## Windows 64
|
||||
## Windows is always static to work outside msys2
|
||||
elif [ "$platform" == "mingw64" ]; then
|
||||
# Do something under Windows NT platform
|
||||
echo "Configuring build for MINGW64.."
|
||||
BOOST_ROOT=/mingw64/boost
|
||||
cmake -D CMAKE_BUILD_TYPE=$BUILD_TYPE -D STATIC=ON -D BOOST_ROOT="$BOOST_ROOT" -D ARCH="x86-64" -D BUILD_GUI_DEPS=ON -D INSTALL_VENDORED_LIBUNBOUND=ON -D CMAKE_INSTALL_PREFIX="$MONERO_DIR" -G "MSYS Makefiles" ../..
|
||||
cmake -D CMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE -D STATIC=ON -D BOOST_ROOT="$BOOST_ROOT" -D ARCH="x86-64" -D BUILD_GUI_DEPS=ON -D INSTALL_VENDORED_LIBUNBOUND=ON -D CMAKE_INSTALL_PREFIX="$MONERO_DIR" -G "MSYS Makefiles" ../..
|
||||
|
||||
## Windows 32
|
||||
elif [ "$platform" == "mingw32" ]; then
|
||||
# Do something under Windows NT platform
|
||||
echo "Configuring build for MINGW32.."
|
||||
BOOST_ROOT=/mingw32/boost
|
||||
cmake -D CMAKE_BUILD_TYPE=$BUILD_TYPE -D STATIC=ON -D Boost_DEBUG=ON -D BOOST_ROOT="$BOOST_ROOT" -D ARCH="i686" -D BUILD_64=OFF -D BUILD_GUI_DEPS=ON -D INSTALL_VENDORED_LIBUNBOUND=ON -D CMAKE_INSTALL_PREFIX="$MONERO_DIR" -G "MSYS Makefiles" ../..
|
||||
cmake -D CMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE -D STATIC=ON -D Boost_DEBUG=ON -D BOOST_ROOT="$BOOST_ROOT" -D ARCH="i686" -D BUILD_64=OFF -D BUILD_GUI_DEPS=ON -D INSTALL_VENDORED_LIBUNBOUND=ON -D CMAKE_INSTALL_PREFIX="$MONERO_DIR" -G "MSYS Makefiles" ../..
|
||||
make_exec="mingw32-make"
|
||||
else
|
||||
echo "Unsupported platform: $platform"
|
||||
popd
|
||||
exit 1
|
||||
echo "Unknown platform, configuring general build"
|
||||
if [ "$STATIC" == true ]; then
|
||||
cmake -D CMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE -D STATIC=ON -D BUILD_GUI_DEPS=ON -D CMAKE_INSTALL_PREFIX="$MONERO_DIR" ../..
|
||||
else
|
||||
cmake -D CMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE -D BUILD_GUI_DEPS=ON -D CMAKE_INSTALL_PREFIX="$MONERO_DIR" ../..
|
||||
fi
|
||||
fi
|
||||
|
||||
# set CPU core count
|
||||
# thanks to SO: http://stackoverflow.com/a/20283965/4118915
|
||||
if test -z "$CPU_CORE_COUNT"; then
|
||||
CPU_CORE_COUNT=$(grep -c ^processor /proc/cpuinfo 2>/dev/null || sysctl -n hw.ncpu)
|
||||
fi
|
||||
|
||||
# Build libwallet_merged
|
||||
pushd $MONERO_DIR/build/release/src/wallet
|
||||
@@ -88,25 +216,26 @@ popd
|
||||
|
||||
# Build monerod
|
||||
# win32 need to build daemon manually with msys2 toolchain
|
||||
if [ "$platform" != "mingw32" ]; then
|
||||
if [ "$platform" != "mingw32" ] && [ "$ANDROID" != true ]; then
|
||||
pushd $MONERO_DIR/build/release/src/daemon
|
||||
eval make -j$CPU_CORE_COUNT
|
||||
eval make install -j$CPU_CORE_COUNT
|
||||
eval make install -j$CPU_CORE_COUNT
|
||||
popd
|
||||
fi
|
||||
|
||||
# build install epee
|
||||
eval make -C $MONERO_DIR/build/release/contrib/epee all install
|
||||
|
||||
# unbound is one more dependency. can't be merged to the wallet_merged
|
||||
# since filename conflict (random.c.obj)
|
||||
# for Linux, we use libunbound shipped with the system, so we don't need to build it
|
||||
# install easylogging
|
||||
eval make -C $MONERO_DIR/build/release/external/easylogging++ all install
|
||||
|
||||
if [ "$platform" != "linux32" ] && [ "$platform" != "linux64" ]; then
|
||||
echo "Building libunbound..."
|
||||
pushd $MONERO_DIR/build/release/external/unbound
|
||||
# no need to make, it was already built as dependency for libwallet
|
||||
# make -j$CPU_CORE_COUNT
|
||||
$make_exec install -j$CPU_CORE_COUNT
|
||||
popd
|
||||
fi
|
||||
# Install libunwind
|
||||
echo "Installing libunbound..."
|
||||
pushd $MONERO_DIR/build/release/external/unbound
|
||||
# no need to make, it was already built as dependency for libwallet
|
||||
# make -j$CPU_CORE_COUNT
|
||||
$make_exec install -j$CPU_CORE_COUNT
|
||||
popd
|
||||
|
||||
popd
|
||||
|
||||
popd
|
||||
|
||||
5
installers/windows/.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
# The subdirectory with the individual GUI Wallet files
|
||||
bin/
|
||||
|
||||
# The subdirectory with the generated installer "mysetup.exe"
|
||||
Output/
|
||||
BIN
installers/windows/FinishImage.bmp
Normal file
|
After Width: | Height: | Size: 151 KiB |
31
installers/windows/LICENSE
Normal file
@@ -0,0 +1,31 @@
|
||||
Copyright (c) 2014-2017, 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.
|
||||
|
||||
Parts of the project are originally copyright (c) 2012-2013 The Cryptonote
|
||||
developers
|
||||
361
installers/windows/Monero.iss
Normal file
@@ -0,0 +1,361 @@
|
||||
; Monero GUI Wallet Beta 2 Installer for Windows
|
||||
; Copyright (c) 2014-2017, The Monero Project
|
||||
; See LICENSE
|
||||
|
||||
[Setup]
|
||||
AppName=Monero GUI Wallet
|
||||
AppVersion=0.10.3.1
|
||||
DefaultDirName={pf}\Monero GUI Wallet
|
||||
DefaultGroupName=Monero GUI Wallet
|
||||
UninstallDisplayIcon={app}\monero-wallet-gui.exe
|
||||
PrivilegesRequired=admin
|
||||
ArchitecturesInstallIn64BitMode=x64
|
||||
ArchitecturesAllowed=x64
|
||||
WizardSmallImageFile=WizardSmallImage.bmp
|
||||
WizardImageFile=WelcomeImage.bmp
|
||||
DisableWelcomePage=no
|
||||
LicenseFile=LICENSE
|
||||
|
||||
|
||||
[Languages]
|
||||
Name: "en"; MessagesFile: "compiler:Default.isl"
|
||||
; Without localized versions of special forms, messages etc. of the installer, and without translated ReadMe's
|
||||
; it probably does not make much sense to offer other install-time languages beside English
|
||||
; Name: "fr"; MessagesFile: "compiler:Languages\French.isl"
|
||||
; Name: "it"; MessagesFile: "compiler:Languages\Italian.isl"
|
||||
; Name: "jp"; MessagesFile: "compiler:Languages\Japanese.isl"
|
||||
; Name: "nl"; MessagesFile: "compiler:Languages\Dutch.isl"
|
||||
; Name: "pt"; MessagesFile: "compiler:Languages\Portuguese.isl"
|
||||
|
||||
|
||||
[Files]
|
||||
Source: "ReadMe.htm"; DestDir: "{app}"; Flags: comparetimestamp
|
||||
Source: "FinishImage.bmp"; Flags: dontcopy
|
||||
|
||||
; Monero GUI wallet
|
||||
Source: "bin\monero-wallet-gui.exe"; DestDir: "{app}"; Flags: comparetimestamp
|
||||
|
||||
; Monero GUI wallet log file
|
||||
; Beta 2 does not have the "--log-file" command-line option of the CLI wallet and insists to put the .log beside the .exe
|
||||
; so pre-create the file and give the necessary permissions to the wallet to write into it
|
||||
Source: "monero-wallet-gui.log"; DestDir: "{app}"; Flags: comparetimestamp; Permissions: users-modify
|
||||
|
||||
; Monero CLI wallet
|
||||
Source: "bin\monero-wallet-cli.exe"; DestDir: "{app}"; Flags: comparetimestamp
|
||||
|
||||
; Monero wallet RPC interface implementation
|
||||
Source: "bin\monero-wallet-rpc.exe"; DestDir: "{app}"; Flags: comparetimestamp
|
||||
|
||||
; Monero daemon
|
||||
Source: "bin\monerod.exe"; DestDir: "{app}"; Flags: comparetimestamp
|
||||
|
||||
; Monero daemon wrapped in a batch file that stops before the text window closes, to see any error messages
|
||||
Source: "monero-daemon.bat"; DestDir: "{app}"; Flags: comparetimestamp;
|
||||
|
||||
; Monero blockchain utilities
|
||||
Source: "bin\monero-blockchain-export.exe"; DestDir: "{app}"; Flags: comparetimestamp
|
||||
Source: "bin\monero-blockchain-import.exe"; DestDir: "{app}"; Flags: comparetimestamp
|
||||
Source: "bin\monero-utils-deserialize.exe"; DestDir: "{app}"; Flags: comparetimestamp
|
||||
|
||||
; Various .qm files for translating the wallet UI "on the fly" into all supported languages
|
||||
Source: "bin\translations\*"; DestDir: "{app}\translations"; Flags: recursesubdirs comparetimestamp
|
||||
|
||||
; Core Qt runtime
|
||||
Source: "bin\Qt5Core.dll"; DestDir: "{app}"; Flags: comparetimestamp
|
||||
Source: "bin\Qt5Gui.dll"; DestDir: "{app}"; Flags: comparetimestamp
|
||||
Source: "bin\Qt5Multimedia.dll"; DestDir: "{app}"; Flags: comparetimestamp
|
||||
Source: "bin\Qt5MultimediaQuick_p.dll"; DestDir: "{app}"; Flags: comparetimestamp
|
||||
Source: "bin\Qt5Network.dll"; DestDir: "{app}"; Flags: comparetimestamp
|
||||
Source: "bin\Qt5Qml.dll"; DestDir: "{app}"; Flags: comparetimestamp
|
||||
Source: "bin\Qt5Quick.dll"; DestDir: "{app}"; Flags: comparetimestamp
|
||||
Source: "bin\Qt5Svg.dll"; DestDir: "{app}"; Flags: comparetimestamp
|
||||
Source: "bin\Qt5Widgets.dll"; DestDir: "{app}"; Flags: comparetimestamp
|
||||
Source: "bin\Qt5XmlPatterns.dll"; DestDir: "{app}"; Flags: comparetimestamp
|
||||
|
||||
; Qt QML elements like the local files selector "FolderListModel" and "Settings"
|
||||
Source: "bin\Qt\*"; DestDir: "{app}\Qt"; Flags: recursesubdirs comparetimestamp
|
||||
|
||||
; Qt audio support
|
||||
Source: "bin\audio\*"; DestDir: "{app}\audio"; Flags: recursesubdirs comparetimestamp
|
||||
|
||||
; Qt bearer / network connection management
|
||||
Source: "bin\bearer\*"; DestDir: "{app}\bearer"; Flags: recursesubdirs comparetimestamp
|
||||
|
||||
; Qt Windows platform plugin
|
||||
Source: "bin\platforms\qwindows.dll"; DestDir: "{app}\platforms"; Flags: comparetimestamp
|
||||
|
||||
; Qt support for SVG icons
|
||||
Source: "bin\iconengines\*"; DestDir: "{app}\iconengines"; Flags: recursesubdirs comparetimestamp
|
||||
|
||||
; Qt support for various image formats (JPEG, BMP, SVG etc)
|
||||
Source: "bin\imageformats\*"; DestDir: "{app}\imageformats"; Flags: recursesubdirs comparetimestamp
|
||||
|
||||
; Qt multimedia support
|
||||
Source: "bin\QtMultimedia\*"; DestDir: "{app}\QtMultimedia"; Flags: recursesubdirs comparetimestamp
|
||||
Source: "bin\mediaservice\*"; DestDir: "{app}\mediaservice"; Flags: recursesubdirs comparetimestamp
|
||||
|
||||
; Qt support for "m3u" playlists
|
||||
; candidate for elimination? Don't think the GUI wallet needs such playlists
|
||||
Source: "bin\playlistformats\*"; DestDir: "{app}\playlistformats"; Flags: recursesubdirs comparetimestamp
|
||||
|
||||
; Qt graphical effects as part of the core runtime, effects like blurring and blending
|
||||
Source: "bin\QtGraphicalEffects\*"; DestDir: "{app}\QtGraphicalEffects"; Flags: recursesubdirs comparetimestamp
|
||||
|
||||
; Some more Qt graphical effects
|
||||
; "private" as a name for this directory looks a little strange. Historical reasons?
|
||||
Source: "bin\private\*"; DestDir: "{app}\private"; Flags: recursesubdirs comparetimestamp
|
||||
|
||||
; Qt QML files
|
||||
Source: "bin\QtQml\*"; DestDir: "{app}\QtQml"; Flags: recursesubdirs comparetimestamp
|
||||
|
||||
; Qt Quick files
|
||||
Source: "bin\QtQuick\*"; DestDir: "{app}\QtQuick"; Flags: recursesubdirs comparetimestamp
|
||||
Source: "bin\QtQuick.2\*"; DestDir: "{app}\QtQuick.2"; Flags: recursesubdirs comparetimestamp
|
||||
|
||||
; Qt Quick 2D Renderer fallback for systems / environments with "low-level graphics" i.e. without 3D support
|
||||
Source: "bin\scenegraph\*"; DestDir: "{app}\scenegraph"; Flags: recursesubdirs comparetimestamp
|
||||
Source: "bin\start-low-graphics-mode.bat"; DestDir: "{app}"; Flags: comparetimestamp
|
||||
|
||||
; Mesa, open-source OpenGL implementation; part of "low-level graphics" support
|
||||
Source: "bin\opengl32sw.dll"; DestDir: "{app}"; Flags: comparetimestamp
|
||||
|
||||
; Left out subdirectory "qmltooling" with the Qt QML debugger: Probably not relevant in an end-user package
|
||||
|
||||
; Microsoft Direct3D runtime
|
||||
Source: "bin\D3Dcompiler_47.dll"; DestDir: "{app}"; Flags: comparetimestamp
|
||||
|
||||
; bzip2 support
|
||||
Source: "bin\libbz2-1.dll"; DestDir: "{app}"; Flags: comparetimestamp
|
||||
|
||||
; ANGLE ("Almost Native Graphics Layer Engine") support, as used by Qt
|
||||
Source: "bin\libEGL.dll"; DestDir: "{app}"; Flags: comparetimestamp
|
||||
Source: "bin\libGLESV2.dll"; DestDir: "{app}"; Flags: comparetimestamp
|
||||
|
||||
; FreeType font engine, as used by Qt
|
||||
Source: "bin\libfreetype-6.dll"; DestDir: "{app}"; Flags: comparetimestamp
|
||||
|
||||
; GCC runtime, x64 version
|
||||
Source: "bin\libgcc_s_seh-1.dll"; DestDir: "{app}"; Flags: comparetimestamp
|
||||
|
||||
; GLib, low level core library e.g. for GNOME and GTK+
|
||||
; Really needed under Windows?
|
||||
Source: "bin\libglib-2.0-0.dll"; DestDir: "{app}"; Flags: comparetimestamp
|
||||
|
||||
; Graphite font support
|
||||
; Really needed?
|
||||
Source: "bin\libgraphite2.dll"; DestDir: "{app}"; Flags: comparetimestamp
|
||||
|
||||
; HarfBuzz OpenType text shaping engine
|
||||
; Really needed?
|
||||
Source: "bin\libharfbuzz-0.dll"; DestDir: "{app}"; Flags: comparetimestamp
|
||||
|
||||
; LibIconv, conversions between character encodings
|
||||
Source: "bin\libiconv-2.dll"; DestDir: "{app}"; Flags: comparetimestamp
|
||||
|
||||
; Part of cygwin? Needed by Qt somehow?
|
||||
Source: "bin\libicudt57.dll"; DestDir: "{app}"; Flags: comparetimestamp
|
||||
Source: "bin\libicuin57.dll"; DestDir: "{app}"; Flags: comparetimestamp
|
||||
Source: "bin\libicuuc57.dll"; DestDir: "{app}"; Flags: comparetimestamp
|
||||
|
||||
; Library for native language support, part of GNU gettext
|
||||
Source: "bin\libintl-8.dll"; DestDir: "{app}"; Flags: comparetimestamp
|
||||
|
||||
; JasPer, support for JPEG-2000
|
||||
Source: "bin\libjasper-1.dll"; DestDir: "{app}"; Flags: comparetimestamp
|
||||
|
||||
; libjpeg, C library for reading and writing JPEG image files
|
||||
Source: "bin\libjpeg-8.dll"; DestDir: "{app}"; Flags: comparetimestamp
|
||||
|
||||
; Little CMS, color management system
|
||||
Source: "bin\liblcms2-2.dll"; DestDir: "{app}"; Flags: comparetimestamp
|
||||
|
||||
; XZ Utils, LZMA compression library
|
||||
Source: "bin\liblzma-5.dll"; DestDir: "{app}"; Flags: comparetimestamp
|
||||
|
||||
; MNG / Portable Network Graphics ("animated PNG")
|
||||
Source: "bin\libmng-2.dll"; DestDir: "{app}"; Flags: comparetimestamp
|
||||
|
||||
; PCRE, Perl Compatible Regular Expressions
|
||||
Source: "bin\libpcre-1.dll"; DestDir: "{app}"; Flags: comparetimestamp
|
||||
Source: "bin\libpcre16-0.dll"; DestDir: "{app}"; Flags: comparetimestamp
|
||||
|
||||
; libpng, the official PNG reference library
|
||||
Source: "bin\libpng16-16.dll"; DestDir: "{app}"; Flags: comparetimestamp
|
||||
|
||||
; libstdc++, GNU Standard C++ Library
|
||||
Source: "bin\libstdc++-6.dll"; DestDir: "{app}"; Flags: comparetimestamp
|
||||
|
||||
; LibTIFF, TIFF Library and Utilities
|
||||
Source: "bin\libtiff-5.dll"; DestDir: "{app}"; Flags: comparetimestamp
|
||||
|
||||
; C++ threading support
|
||||
Source: "bin\libwinpthread-1.dll"; DestDir: "{app}"; Flags: comparetimestamp
|
||||
|
||||
; zlib compression library
|
||||
Source: "bin\zlib1.dll"; DestDir: "{app}"; Flags: comparetimestamp
|
||||
|
||||
|
||||
[Tasks]
|
||||
Name: desktopicon; Description: "Create a &desktop icon"; GroupDescription: "Additional icons:";
|
||||
|
||||
|
||||
[Run]
|
||||
Filename: "{app}\ReadMe.htm"; Description: "Show ReadMe"; Flags: postinstall shellexec skipifsilent
|
||||
|
||||
; DON'T offer to run the wallet right away, let the people read about initial blockchain download first in the ReadMe
|
||||
; Filename: "{app}\monero-wallet-gui.exe"; Description: "Run GUI Wallet now"; Flags: postinstall nowait skipifsilent
|
||||
|
||||
|
||||
[Code]
|
||||
var
|
||||
BlockChainDirPage: TInputDirWizardPage;
|
||||
blockChainDefaultDir: String;
|
||||
|
||||
procedure InitializeWizard;
|
||||
var s: String;
|
||||
width: Integer;
|
||||
begin
|
||||
// Large image for the "Welcome" page, with page reconfigured
|
||||
WizardForm.WelcomeLabel1.Visible := false;
|
||||
WizardForm.WelcomeLabel2.Visible := false;
|
||||
WizardForm.WizardBitmapImage.Height := 300;
|
||||
WizardForm.WizardBitmapImage.Width := 500;
|
||||
|
||||
// Image for the "Finnish" screen, in standard WizardBitmapImage size of 164 x 314
|
||||
ExtractTemporaryFile('FinishImage.bmp');
|
||||
WizardForm.WizardBitmapImage2.Bitmap.LoadFromFile(ExpandConstant('{tmp}\FinishImage.bmp'));
|
||||
|
||||
// Additional wizard page for entering a special blockchain location
|
||||
blockChainDefaultDir := ExpandConstant('{commonappdata}\bitmonero');
|
||||
s := 'The default folder to store the Monero blockchain is ' + blockChainDefaultDir;
|
||||
s := s + '. As this will need up to 20 GB of free space, you may want to use a folder on a different drive.';
|
||||
s := s + ' If yes, specify that folder here.';
|
||||
|
||||
BlockChainDirPage := CreateInputDirPage(wpSelectDir,
|
||||
'Select Blockchain Directory', 'Where should the blockchain be installed?',
|
||||
s,
|
||||
False, '');
|
||||
BlockChainDirPage.Add('');
|
||||
|
||||
BlockChainDirPage.Values[0] := GetPreviousData('BlockChainDir', '');
|
||||
if BlockChainDirPage.Values[0] = '' then begin
|
||||
// Unfortunately 'TInputDirWizardDirPage' does not allow empty field
|
||||
BlockChainDirPage.Values[0] := blockChainDefaultDir;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure RegisterPreviousData(PreviousDataKey: Integer);
|
||||
begin
|
||||
// Store the selected folder for further reinstall/upgrade
|
||||
SetPreviousData(PreviousDataKey, 'BlockChainDir', BlockChainDirPage.Values[0]);
|
||||
end;
|
||||
|
||||
function BlockChainDir(Param: String) : String;
|
||||
// Directory of the blockchain
|
||||
var s: String;
|
||||
begin
|
||||
s := BlockChainDirPage.Values[0];
|
||||
Result := s;
|
||||
// No quotes for folder name with blanks as this is never used as part of a command line
|
||||
end;
|
||||
|
||||
function UpdateReadyMemo(Space, NewLine, MemoUserInfoInfo, MemoDirInfo, MemoTypeInfo,
|
||||
MemoComponentsInfo, MemoGroupInfo, MemoTasksInfo: String): String;
|
||||
var s: String;
|
||||
begin
|
||||
// Fill the 'Ready Memo' with the normal settings and the custom settings
|
||||
s := '';
|
||||
s := s + MemoDirInfo + NewLine + NewLine;
|
||||
|
||||
s := s + 'Blockchain folder' + NewLine;
|
||||
s := s + Space + BlockChainDir('') + NewLine;
|
||||
|
||||
Result := s;
|
||||
end;
|
||||
|
||||
function DaemonLog(Param: String) : String;
|
||||
// Full filename of the log of the daemon
|
||||
begin
|
||||
Result := BlockChainDir('') + '\bitmonero.log';
|
||||
// No quotes for filename with blanks as this is never used as part of a command line
|
||||
end;
|
||||
|
||||
function DaemonFlags(Param: String): String;
|
||||
// Flags to add to the shortcut to the daemon
|
||||
var s: String;
|
||||
begin
|
||||
s := BlockChainDir('');
|
||||
if s = blockChainDefaultDir then begin
|
||||
// No need to add the default dir as flags for the daemon
|
||||
s := '';
|
||||
end;
|
||||
if Pos(' ', s) > 0 then begin
|
||||
// Quotes needed for filename with blanks
|
||||
s := '"' + s + '"';
|
||||
end;
|
||||
if s <> '' then begin
|
||||
s := '--data-dir ' + s;
|
||||
end;
|
||||
Result := s;
|
||||
end;
|
||||
|
||||
procedure CurStepChanged(CurStep: TSetupStep);
|
||||
var s: TArrayOfString;
|
||||
begin
|
||||
if CurStep = ssPostInstall then begin
|
||||
// Re-build "monero-daemon.bat" according to actual install and blockchain directory used
|
||||
SetArrayLength(s, 3);
|
||||
s[0] := 'REM Execute the Monero daemon and then stay with window open after it exits';
|
||||
s[1] := '"' + ExpandConstant('{app}\monerod.exe') + '" ' + DaemonFlags('');
|
||||
s[2] := 'PAUSE';
|
||||
SaveStringsToFile(ExpandConstant('{app}\monero-daemon.bat'), s, false);
|
||||
end;
|
||||
end;
|
||||
|
||||
function InitializeUninstall(): Boolean;
|
||||
var s: String;
|
||||
begin
|
||||
s := 'Please note: Uninstall will not delete any downloaded blockchain. ';
|
||||
s := s + 'If you do not need it anymore you have to delete it manually.';
|
||||
s := s + #13#10#13#10 + 'Uninstall will not delete any wallets that you created either.';
|
||||
MsgBox(s, mbInformation, MB_OK);
|
||||
Result := true;
|
||||
end;
|
||||
|
||||
|
||||
[Icons]
|
||||
; Icons in the "Monero GUI Wallet" program group
|
||||
; Windows will almost always display icons in alphabetical order, per level, so specify the text accordingly
|
||||
Name: "{group}\GUI Wallet"; Filename: "{app}\monero-wallet-gui.exe"
|
||||
Name: "{group}\Uninstall GUI Wallet"; Filename: "{uninstallexe}"
|
||||
|
||||
; Sub-folder "Utilities";
|
||||
; Note that Windows 10, unlike Windows 7, ignores such sub-folders completely
|
||||
; and insists on displaying ALL icons on one single level
|
||||
Name: "{group}\Utilities\Monero Daemon"; Filename: "{app}\monerod.exe"; Parameters: {code:DaemonFlags}
|
||||
Name: "{group}\Utilities\Read Me"; Filename: "{app}\ReadMe.htm"
|
||||
Name: "{group}\Utilities\Textual (CLI) Wallet"; Filename: "{app}\monero-wallet-cli.exe"
|
||||
|
||||
; Icons for troubleshooting problems / testing / debugging
|
||||
; To show that they are in some way different (not for everyday use), make them visually different
|
||||
; from the others by text, and make them sort at the end by the help of "x" in front
|
||||
Name: "{group}\Utilities\x (Check Blockchain Folder)"; Filename: "{win}\Explorer.exe"; Parameters: {code:BlockChainDir}
|
||||
Name: "{group}\Utilities\x (Check Daemon Log)"; Filename: "Notepad"; Parameters: {code:DaemonLog}
|
||||
Name: "{group}\Utilities\x (Check Default Wallet Folder)"; Filename: "{win}\Explorer.exe"; Parameters: "{userdocs}\Monero\wallets"
|
||||
Name: "{group}\Utilities\x (Check GUI Wallet Log)"; Filename: "Notepad"; Parameters: "{app}\monero-wallet-gui.log"
|
||||
Name: "{group}\Utilities\x (Try Daemon, Exit Confirm)"; Filename: "{app}\monero-daemon.bat"
|
||||
Name: "{group}\Utilities\x (Try GUI Wallet Low Graphics Mode)"; Filename: "{app}\start-low-graphics-mode.bat"
|
||||
Name: "{group}\Utilities\x (Try Kill Daemon)"; Filename: "Taskkill.exe"; Parameters: "/IM monerod.exe /T /F"
|
||||
|
||||
; Desktop icons, optional with the help of the "Task" section
|
||||
Name: "{userdesktop}\GUI Wallet"; Filename: "{app}\monero-wallet-gui.exe"; Tasks: desktopicon
|
||||
|
||||
|
||||
[Registry]
|
||||
; Store any special flags for the daemon in the registry location where the GUI wallet will take it from
|
||||
; So if the wallet is used to start the daemon instead of the separate icon the wallet will pass the correct flags
|
||||
; Side effect, mostly positive: The uninstaller will clean the registry
|
||||
Root: HKCU; Subkey: "Software\monero-project"; Flags: uninsdeletekeyifempty
|
||||
Root: HKCU; Subkey: "Software\monero-project\monero-core"; Flags: uninsdeletekey
|
||||
Root: HKCU; Subkey: "Software\monero-project\monero-core"; ValueType: string; ValueName: "daemonFlags"; ValueData: {code:DaemonFlags};
|
||||
|
||||
41
installers/windows/README.md
Normal file
@@ -0,0 +1,41 @@
|
||||
# Monero GUI Wallet Beta 2 Windows Installer #
|
||||
|
||||
Copyright (c) 2014-2017, The Monero Project
|
||||
|
||||
## Introduction ##
|
||||
|
||||
This is a *Inno Setup* script `Monero.iss` plus some related files that
|
||||
allows you to build a standalone Windows installer (.exe) for the
|
||||
Monero GUI Wallet Beta 2.
|
||||
|
||||
This turns the GUI Wallet into a more or less standard Windows program,
|
||||
by default installed into a subdirectory of `C:\Program Files`, a
|
||||
program group with some icons in the *Start* menu, and automatic
|
||||
uninstall support. It helps lower the "barrier to entry" somewhat,
|
||||
especially for less technically experienced users of Monero.
|
||||
|
||||
As the setup script in file [Monero.iss](Monero.iss) has to list every
|
||||
single file of the GUI Wallet package to install by name, this version
|
||||
of the script only works with exactly the GUI Beta 2 that you find on
|
||||
[the official download page](https://getmonero.org/downloads/).
|
||||
|
||||
But of course it will be easy to modify the script for future versions
|
||||
of the GUI Wallet.
|
||||
|
||||
## License ##
|
||||
|
||||
See [LICENSE](LICENSE).
|
||||
|
||||
## Building ##
|
||||
|
||||
You can only build on Windows, and the result is always a Windows .exe
|
||||
file that can act as a standalone installer for the GUI Wallet Beta 2.
|
||||
|
||||
The build steps in detail:
|
||||
|
||||
1. Install *Inno Setup*. You can get it from [here](http://www.jrsoftware.org/isdl.php)
|
||||
2. Get the Inno Setup script plus related files by cloning the whole [monero-core](https://github.com/monero-project/monero-core) repository; you will only need the files in the installer directory `installers\windows` however
|
||||
3. The setup script is written to take the GUI Wallet files from a subdirectory named `bin`; so create `installers\windows\bin`, get the zip file of the GUI Wallet Beta 2 from [here](https://getmonero.org/downloads/), unpack it somewhere, and copy all the files and subdirectories in the `monero-gui-0.10.3.1-beta2` directory to this `bin` subdirectory
|
||||
4. Start Inno Setup, load `Monero.iss` and compile it.
|
||||
5. The result i.e. the finished installer will be the file `mysetup.exe` in the `installers\windows\Output` subdirectory
|
||||
|
||||
174
installers/windows/ReadMe.htm
Normal file
@@ -0,0 +1,174 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Monero GUI Wallet Beta 2</title>
|
||||
</head>
|
||||
|
||||
<body style="font-family: Arial, Helvetica, sans-serif">
|
||||
<h1>Monero GUI Wallet Beta 2</h1>
|
||||
|
||||
<p>Copyright (c) 2014-2017, The Monero Project<br>
|
||||
Date: June 28, 2017</p>
|
||||
|
||||
<h2>Preface</h2>
|
||||
|
||||
<p>This ReadMe does not aim to be a complete introduction to Monero. If you are new to Monero or even to
|
||||
cryptocurrencies in general you find a good introduction on reddit at
|
||||
<a href="https://www.reddit.com/r/Monero/comments/5zgail/rmonero_newcomers_please_read_everything_you_need/">Newcomers Please Read. Everything You Need To Know</a>.
|
||||
You also find a lot of good tutorials on <a href="https://www.monero.how/">Monero.How</a>.
|
||||
</p>
|
||||
|
||||
<p>Please note that Monero and its software are constantly evolving and progressing; it probably won't take
|
||||
long for some of the information here to become outdated.
|
||||
</p>
|
||||
|
||||
<h2>Content of the Package</h2>
|
||||
|
||||
<p>You just installed the Beta 2 of the <i>Monero GUI Wallet</i> for Windows, more exact version 0.10.3.1. The wallet
|
||||
enables you to send and receive moneroj in a secure and very private way.
|
||||
</p>
|
||||
|
||||
<p>Also included is the <i>Monero daemon</i>, so you have everything now to run a so-called <i>full node</i>
|
||||
and become part of the network of nodes that manages the Monero blockchain; you don't need to install additional
|
||||
packages in order to start.</p>
|
||||
|
||||
<p>For checking whether there are already newer versions of this package you can go to the
|
||||
<a href="https://getmonero.org/downloads/">Downloads</a> page on <a href="https://getmonero.org/home">getmonero.org</a>,
|
||||
the official Monero site.</p>
|
||||
|
||||
<h2>Access to the Blockchain</h2>
|
||||
|
||||
<p>Any Monero wallet needs access to the <i>blockchain</i>, the ongoing ledger of all Monero transactions. For the
|
||||
GUI wallet there are two principal ways to get that access: You can let Monero sync with the network
|
||||
i.e. let it download the blockchain and store it locally on your computer, or you can configure your wallet to
|
||||
access a remote <i>open node</i> to get indirect access to the blockchain.</p>
|
||||
|
||||
<p>Working with your own copy of the blockchain is <b>preferred</b>: It strengthens the Monero network, and it
|
||||
provides the most security and privacy possible for you.</p>
|
||||
|
||||
<p>However if your Internet access makes it difficult to run a full node, or if you have simply no room to store
|
||||
the blockchain locally (over 17 GB in summer 2017, and of course growing), you can compromise and try to connect
|
||||
to a remote node. One way of finding such a node is checking
|
||||
<a href="https://moneroworld.com/pages/nodes.html">this page</a>.
|
||||
</p>
|
||||
|
||||
<h2>Initial Blockchain Download</h2>
|
||||
|
||||
<p>Please do read the following <b>before</b> jumping right in and starting the GUI wallet:</p>
|
||||
|
||||
<p>If you decide to work with your own copy of the blockchain, which you should whenever possible, you have to
|
||||
download it first; it's not part of the installed package.
|
||||
Beside the GUI wallet there is second program, the so-called <i>Monero daemon</i>, which will carry out that download.
|
||||
You find it in the <i>Utilities</i> sub-folder of the program group.</p>
|
||||
|
||||
<p>Depending on your Internet access and the speed of your computer this can take
|
||||
<b>several hours</b>, in some cases <b>more than a day</b>. Furthermore there are unfortunate cases where the
|
||||
download gets stuck somehow or doesn't work at all, e.g. because a firewall prevents access to other nodes of the
|
||||
Monero network.</p>
|
||||
|
||||
<p>The GUI wallet can start the daemon for you, but that way you will not see much during initial blockchain
|
||||
download, especially you probably won't see any error messages in case something goes wrong. By starting the
|
||||
daemon yourself "by hand" using the <i>Monero Daemon</i> icon in the <i>Utilities</i> sub-folder of the
|
||||
Monero program group you will see it running and displaying messages in a separate window.</p>
|
||||
|
||||
<p>If all goes well the daemon will finally display a message like this:
|
||||
<i>You are now synchronized with the network.</i></p>
|
||||
|
||||
<p><b>Then</b> you are ready for sure to start your Monero adventures by starting the GUI wallet.</p>
|
||||
|
||||
<h2>Allowing Other Nodes to Connect to Your Node</h2>
|
||||
|
||||
<p>When the Monero daemon downloads the blockchain it does so by connecting to other nodes of the network.</p>
|
||||
|
||||
<p>If you allow incoming TCP/IP connections to port 18080 on your computer and let your daemon run for extended
|
||||
periods of time you can "return the favor" and help others in turn to get access to Monero. However, depending on
|
||||
your Internet connection, firewall, modem, router, ISP etc. this might not be possible, and opening a port in such
|
||||
a way usually requires some technical knowledge.</p>
|
||||
|
||||
<p>If you want to try you may start e.g. with
|
||||
<a href="https://monero.stackexchange.com/questions/2479/how-do-i-enable-incoming-connections-eli5">this Monero Stack Exchange</a>
|
||||
question.</p>
|
||||
|
||||
<h2>Troubleshooting</h2>
|
||||
|
||||
<p>The Monero software and especially the GUI wallet are "work in progress", as you can expect seeing the word
|
||||
<i>Beta</i> in the name of the package, 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
|
||||
seed!</b></p>
|
||||
|
||||
<p>There is a <b>bug</b> in this beta of the GUI wallet that triggers if it is installed in a path that contains spaces /
|
||||
blank characters, like the default location for Windows programs <i>C:\Program Files</i> unfortunately does.
|
||||
Symptoms are problems in the communication between the wallet and the daemon, e.g. the wallet not "seeing" the
|
||||
daemon and then not knowing whether it is "synchronized" with the network and thus ready to work or not. You can
|
||||
avoid these problems by starting the daemon yourself, with the help of the <i>Monero Daemon</i> icon in the
|
||||
<i>Utilities</i> sub-folder of the Monero program group.</p>
|
||||
|
||||
<p>In the <i>Utilities</i> sub-folder there are several more icons that may help you to solve problems.
|
||||
These are the icons with a <i>x</i> in front and the name <i>(in parenthesis)</i> to make them visually stand
|
||||
apart from the "normal" ones because you will probably only need them in case of trouble, but not during normal
|
||||
usage of Monero.</p>
|
||||
|
||||
<p>Here an overview and short info what each icon does:</p>
|
||||
|
||||
<table cellpadding="3" border="1">
|
||||
<tr>
|
||||
<td><i>x (Try GUI Wallet Low Graphics Mode)</i></td>
|
||||
<td>Run the GUI wallet in a mode that allows for low-graphics
|
||||
environments, e.g. systems with very simple non-hardware-accelerated or emulated / virtualized video cards;
|
||||
also try if the display is simply slow or lags
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><i>x (Try Daemon, Exit Confirm)</i></td>
|
||||
<td>
|
||||
Run the Monero daemon in a window that does not automatically close if
|
||||
the daemon should exit because of a fatal error; useful in cases where the normal daemon icon
|
||||
just leads to a window that closes right away
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><i>x (Try Kill Daemon)</i></td>
|
||||
<td>
|
||||
Kill any running daemon (technically, any process called <i>monerod.exe</i>), whether
|
||||
with or without any visible window, for starting "with a clean slate"; easier than
|
||||
killing such tasks with the help of the Windows Task Manager
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><i>x (Check GUI Wallet Log)</i></td>
|
||||
<td>Open the log with status and error messages of the GUI wallet program in Notepad;
|
||||
experienced people have a chance to diagnose technical problems with the wallet by looking at the last few lines
|
||||
of this log</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><i>x (Check Daemon Log)</i></td>
|
||||
<td>
|
||||
Open the log with status and error messages of the daemon in Notepad; again, the last few
|
||||
lines of this (possible very long) log are the most important for troubleshooting
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><i>x (Check Default Wallet Folder)</i></td>
|
||||
<td>
|
||||
Open the standard wallet folder in Windows Explorer; useful e.g. if you want to backup
|
||||
your wallets
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><i>x (Check Blockchain Folder)</i></td>
|
||||
<td>
|
||||
Open the folder containing the blockchain in Windows Explorer
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
BIN
installers/windows/WelcomeImage.bmp
Normal file
|
After Width: | Height: | Size: 440 KiB |
BIN
installers/windows/WizardSmallImage.bmp
Normal file
|
After Width: | Height: | Size: 9.6 KiB |
3
installers/windows/monero-daemon.bat
Normal file
@@ -0,0 +1,3 @@
|
||||
REM Execute the Monero daemon and then stay with window open after it exits
|
||||
"C:\Program Files\Monero Core\monerod.exe"
|
||||
PAUSE
|
||||
1
installers/windows/monero-wallet-gui.log
Normal file
@@ -0,0 +1 @@
|
||||
-----
|
||||
41
ios_get_libwallet.api.sh
Executable file
@@ -0,0 +1,41 @@
|
||||
#!/bin/bash -e
|
||||
if [ -z $BUILD_TYPE ]; then
|
||||
BUILD_TYPE=release
|
||||
fi
|
||||
|
||||
ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
if [ -z $BOOST_LIBRARYDIR ]; then
|
||||
BOOST_LIBRARYDIR=${ROOT_DIR}/../ofxiOSBoost/build/ios/prefix/lib
|
||||
fi
|
||||
if [ -z $BOOST_INCLUDEDIR ]; then
|
||||
BOOST_INCLUDEDIR=${ROOT_DIR}/../ofxiOSBoost/build/ios/prefix/include
|
||||
fi
|
||||
if [ -z $OPENSSL_INCLUDE_DIR ]; then
|
||||
OPENSSL_INCLUDE_DIR=${ROOT_DIR}/../openssl/1.0.2j/include
|
||||
fi
|
||||
if [ -z $OPENSSL_ROOT_DIR ]; then
|
||||
OPENSSL_ROOT_DIR=${ROOT_DIR}/../openssl/1.0.2j
|
||||
fi
|
||||
|
||||
echo "Building IOS armv7"
|
||||
rm -r monero/build
|
||||
mkdir -p monero/build/release
|
||||
pushd monero/build/release
|
||||
cmake -D IOS=ON -D ARCH=armv7 -D BOOST_LIBRARYDIR=${BOOST_INCLUDEDIR} -D BOOST_INCLUDEDIR=${BOOST_INCLUDEDIR} -D OPENSSL_INCLUDE_DIR=${OPENSSL_INCLUDE_DIR} -D OPENSSL_ROOT_DIR=${OPENSSL_ROOT_DIR} -D CMAKE_BUILD_TYPE=debug -D STATIC=ON -D BUILD_GUI_DEPS=ON -D INSTALL_VENDORED_LIBUNBOUND=ON -D CMAKE_INSTALL_PREFIX="/Users/jacob/crypto/monero-core/monero" ../..
|
||||
make -j4 && make install
|
||||
popd
|
||||
echo "Building IOS arm64"
|
||||
rm -r monero/build
|
||||
mkdir -p monero/build/release
|
||||
pushd monero/build/release
|
||||
cmake -D IOS=ON -D ARCH=arm64 -D BOOST_LIBRARYDIR=${BOOST_INCLUDEDIR} -D BOOST_INCLUDEDIR=${BOOST_INCLUDEDIR} -D OPENSSL_INCLUDE_DIR=${OPENSSL_INCLUDE_DIR} -D OPENSSL_ROOT_DIR=${OPENSSL_ROOT_DIR} -D CMAKE_BUILD_TYPE=debug -D STATIC=ON -D BUILD_GUI_DEPS=ON -D INSTALL_VENDORED_LIBUNBOUND=ON -D CMAKE_INSTALL_PREFIX="/Users/jacob/crypto/monero-core/monero" ../..
|
||||
make -j4 && make install
|
||||
popd
|
||||
|
||||
echo "Creating fat library for armv7 and arm64"
|
||||
pushd monero
|
||||
mkdir -p lib-ios
|
||||
lipo -create lib-armv7/libwallet_merged.a lib-arm64/libwallet_merged.a -output lib-ios/libwallet_merged.a
|
||||
lipo -create lib-armv7/libunbound.a lib-arm64/libunbound.a -output lib-ios/libunbound.a
|
||||
lipo -create lib-armv7/libepee.a lib-arm64/libepee.a -output lib-ios/libepee.a
|
||||
popd
|
||||
BIN
lang/flags/croatia.png
Normal file
|
After Width: | Height: | Size: 6.8 KiB |
BIN
lang/flags/esperanto.png
Normal file
|
After Width: | Height: | Size: 4.4 KiB |
BIN
lang/flags/finland.png
Normal file
|
After Width: | Height: | Size: 4.9 KiB |
BIN
lang/flags/france.png
Normal file
|
After Width: | Height: | Size: 7.5 KiB |
BIN
lang/flags/indonesia.png
Normal file
|
After Width: | Height: | Size: 7.0 KiB |
BIN
lang/flags/israel.png
Normal file
|
After Width: | Height: | Size: 8.7 KiB |
BIN
lang/flags/japan.png
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
BIN
lang/flags/netherlands.png
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
BIN
lang/flags/poland.png
Normal file
|
After Width: | Height: | Size: 4.0 KiB |
BIN
lang/flags/south_korea.png
Normal file
|
After Width: | Height: | Size: 38 KiB |
BIN
lang/flags/spain.png
Normal file
|
After Width: | Height: | Size: 6.9 KiB |
BIN
lang/flags/sweden.png
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
BIN
lang/flags/taiwan.png
Normal file
|
After Width: | Height: | Size: 8.9 KiB |
@@ -3,22 +3,38 @@
|
||||
|
||||
<!--
|
||||
List of available languages for your wallet's seed:
|
||||
0 : English
|
||||
1 : Spanish
|
||||
2 : German
|
||||
3 : Italian
|
||||
4 : Portuguese
|
||||
5 : Russian
|
||||
6 : Japanese
|
||||
0 : Deutsch (German)
|
||||
1 : English
|
||||
2 : Español (Spanish)
|
||||
3 : Français (French)
|
||||
4 : Italiano (Italian)
|
||||
5 : Nederlands (Dutch)
|
||||
6 : Português (Portuguese)
|
||||
7 : русский язык (Russian)
|
||||
8 : 日本語 (Japanese)
|
||||
9 : 简体中文 (中国) (Simplified Chinese (Mainland))
|
||||
-->
|
||||
<language display_name="English (US)" locale="en_US" wallet_language="English" flag="/lang/flags/usa.png" qs="none"/>
|
||||
<!-- <language display_name="English (GB)" locale="en_GB" wallet_language="English" flag="/lang/flags/uk.png" qs="none"/>
|
||||
<language display_name="English (ZA)" locale="en_SA" wallet_language="English" flag="/lang/flags/rpa.png" qs="none"/>
|
||||
<language display_name="Russian" locale="ru_RU" wallet_language="Russian" flag="/lang/flags/russia.png" qs="none"/>
|
||||
<language display_name="Arabic (PS)" locale="ar_PS" wallet_language="English" flag="/lang/flags/palestine.png" qs="none"/>
|
||||
<language display_name="Hindi" locale="hi_IN" wallet_language="English" flag="/lang/flags/india.png" qs="none"/>
|
||||
<language display_name="Italian" locale="it_IT" wallet_language="Italian" flag="/lang/flags/italy.png" qs="none"/>
|
||||
<language display_name="German" locale="de_DE" wallet_language="German" flag="/lang/flags/german.png" qs="none"/>
|
||||
<language display_name="Mandarin" locale="zh_CN" wallet_language="English" flag="/lang/flags/china.png" qs="none"/>
|
||||
<language display_name="Portuguese (BR)" locale="pt_BR" wallet_language="Portuguese" flag="/lang/flags/brazil.png" qs="none"/> -->
|
||||
<!-- <language display_name="English (GB)" locale="en_GB" wallet_language="English" flag="/lang/flags/uk.png" qs="none"/> -->
|
||||
<!-- <language display_name="English (ZA)" locale="en_SA" wallet_language="English" flag="/lang/flags/rpa.png" qs="none"/> -->
|
||||
<!-- <language display_name="العربية (PS)" locale="ar_PS" wallet_language="English" flag="/lang/flags/palestine.png" qs="none"/> -->
|
||||
<language display_name="Deutsch" locale="de_DE" wallet_language="Deutsch" flag="/lang/flags/german.png" qs="none"/>
|
||||
<language display_name="Esperanto" locale="eo" wallet_language="English" flag="/lang/flags/esperanto.png" qs="none"/>
|
||||
<language display_name="Español" locale="es_ES" wallet_language="Español" flag="/lang/flags/spain.png" qs="none"/>
|
||||
<!-- <language display_name="Suomen kieli" locale="fi" wallet_language="English" flag="/lang/flags/finland.png" qs="none"/> -->
|
||||
<language display_name="Français" locale="fr_FR" wallet_language="Français" flag="/lang/flags/france.png" qs="none"/>
|
||||
<language display_name="Swedish" locale="sv_SE" wallet_language="English" flag="/lang/flags/sweden.png" qs="none"/>
|
||||
<!-- <language display_name="Hrvatski" locale="hr_HR" wallet_language="English" flag="/lang/flags/croatia.png" qs="none"/> -->
|
||||
<!-- <language display_name="हिन्दी" locale="hi_IN" wallet_language="English" flag="/lang/flags/india.png" qs="none"/> -->
|
||||
<language display_name="Bahasa Indonesia" locale="id_ID" wallet_language="English" flag="/lang/flags/indonesia.png" qs="none"/>
|
||||
<language display_name="Italiano" locale="it_IT" wallet_language="Italiano" flag="/lang/flags/italy.png" qs="none"/>
|
||||
<language display_name="日本語" locale="ja_JP" wallet_language="日本語" flag="/lang/flags/japan.png" qs="none"/>
|
||||
<language display_name="Nederlands" locale="nl_NL" wallet_language="Nederlands" flag="/lang/flags/netherlands.png" qs="none"/>
|
||||
<!-- <language display_name="Polski" locale="pl_PL" wallet_language="English" flag="/lang/flags/poland.png" qs="none"/> -->
|
||||
<language display_name="Português (BR)" locale="pt-br_BR" wallet_language="Português" flag="/lang/flags/brazil.png" qs="none"/>
|
||||
<language display_name="Русский язык" locale="ru_RU" wallet_language="русский язык" flag="/lang/flags/russia.png" qs="none"/>
|
||||
<language display_name="简体中文 (中国)" locale="zh-cn_CN" wallet_language="简体中文 (中国)" flag="/lang/flags/china.png" qs="none"/>
|
||||
<language display_name="繁體中文 (台灣)" locale="zh-tw_CN" wallet_language="English" flag="/lang/flags/taiwan.png" qs="none"/>
|
||||
<language display_name="עברית" locale="he_HE" wallet_language="English" flag="/lang/flags/israel.png" qs="none"/>
|
||||
<language display_name="한국어" locale="ko_KO" wallet_language="English" flag="/lang/flags/south_korea.png" qs="none"/>
|
||||
</languages>
|
||||
|
||||
@@ -9,14 +9,36 @@ GUI_EXEC=$2
|
||||
|
||||
platform=$(get_platform)
|
||||
|
||||
if [[ "$platform" == "linux64" ]]; then
|
||||
PLAT_DIR="/usr/lib/x86_64-linux-gnu"
|
||||
elif [[ "$platform" == "linux32" ]]; then
|
||||
PLAT_DIR="/usr/lib/i386-linux-gnu"
|
||||
elif [[ "$platform" == "linuxarmv7" ]]; then
|
||||
PLAT_DIR="/usr/lib/arm-linux-gnueabihf"
|
||||
elif [[ "$platform" == "linuxarmv8" ]]; then
|
||||
PLAT_DIR="/usr/lib/aarch64-linux-gnu"
|
||||
else
|
||||
PLAT_DIR="/usr/lib"
|
||||
fi
|
||||
|
||||
if [ -z "$QT_DIR" ]; then
|
||||
QT_DIR=$PLAT_DIR/qt5
|
||||
fi
|
||||
|
||||
if [ -z "$QTXML_DIR" ]; then
|
||||
QTXML_DIR=$PLAT_DIR
|
||||
fi
|
||||
|
||||
# Copy dependencies
|
||||
EXCLUDE='libstdc++|libgcc_s.so|libc.so|libpthread'
|
||||
cp -rv /usr/lib/x86_64-linux-gnu/qt5/qml $TARGET
|
||||
cp -rv /usr/lib/x86_64-linux-gnu/qt5/plugins $TARGET
|
||||
mkdir -p $TARGET/libs
|
||||
ldd $TARGET/$GUI_EXEC | grep "=> /" | awk '{print $3}' | grep -Ev $EXCLUDE | xargs -I '{}' cp -v '{}' $TARGET/libs
|
||||
ldd $TARGET/plugins/platforms/libqxcb.so| grep "=> /" | awk '{print $3}' | grep -Ev $EXCLUDE | xargs -I '{}' cp -v '{}' $TARGET/libs
|
||||
cp -v /usr/lib/x86_64-linux-gnu/libQt5XmlPatterns.so.5 $TARGET/libs
|
||||
INCLUDE='libunbound'
|
||||
cp -rv $QT_DIR/qml $TARGET || exit
|
||||
cp -rv $QT_DIR/plugins $TARGET || exit
|
||||
mkdir -p $TARGET/libs || exit
|
||||
#ldd $TARGET/$GUI_EXEC | grep "=> /" | awk '{print $3}' | grep $INCLUDE | xargs -I '{}' cp -v '{}' $TARGET/libs || exit
|
||||
#ldd $TARGET/$GUI_EXEC | grep "=> /" | awk '{print $3}' | grep -Ev $EXCLUDE | xargs -I '{}' cp -v '{}' $TARGET/libs || exit
|
||||
#ldd $TARGET/plugins/platforms/libqxcb.so| grep "=> /" | awk '{print $3}' | grep -Ev $EXCLUDE | xargs -I '{}' cp -v '{}' $TARGET/libs || exit
|
||||
#cp -v $QTXML_DIR/libQt5XmlPatterns.so.5 $TARGET/libs || exit
|
||||
|
||||
# Create start script
|
||||
cat > $TARGET/start-gui.sh <<EOL
|
||||
@@ -24,5 +46,9 @@ cat > $TARGET/start-gui.sh <<EOL
|
||||
export LD_LIBRARY_PATH=\`pwd\`/libs
|
||||
export QT_PLUGIN_PATH=\`pwd\`/plugins
|
||||
export QML2_IMPORT_PATH=\`pwd\`/qml
|
||||
./$GUI_EXEC
|
||||
# make it so that it can be called from anywhere and also through soft links
|
||||
SCRIPT_DIR="\$(dirname "\$(test -L "\${BASH_SOURCE[0]}" && readlink "\${BASH_SOURCE[0]}" || echo "\${BASH_SOURCE[0]}")")"
|
||||
"\$SCRIPT_DIR"/$GUI_EXEC
|
||||
EOL
|
||||
|
||||
chmod +x $TARGET/start-gui.sh
|
||||
|
||||
80
main.cpp
@@ -40,19 +40,45 @@
|
||||
#include "Wallet.h"
|
||||
#include "QRCodeImageProvider.h"
|
||||
#include "PendingTransaction.h"
|
||||
#include "UnsignedTransaction.h"
|
||||
#include "TranslationManager.h"
|
||||
#include "TransactionInfo.h"
|
||||
#include "TransactionHistory.h"
|
||||
#include "model/TransactionHistoryModel.h"
|
||||
#include "model/TransactionHistorySortFilterModel.h"
|
||||
#include "daemon/DaemonManager.h"
|
||||
#include "AddressBook.h"
|
||||
#include "model/AddressBookModel.h"
|
||||
#include "wallet/wallet2_api.h"
|
||||
#include "MainApp.h"
|
||||
|
||||
// IOS exclusions
|
||||
#ifndef Q_OS_IOS
|
||||
#include "daemon/DaemonManager.h"
|
||||
#endif
|
||||
|
||||
#ifdef WITH_SCANNER
|
||||
#include "QrCodeScanner.h"
|
||||
#endif
|
||||
|
||||
void messageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
|
||||
{
|
||||
// Send all message types to logger
|
||||
Monero::Wallet::debug(msg.toStdString());
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QApplication app(argc, argv);
|
||||
// // Enable high DPI scaling on windows & linux
|
||||
//#if !defined(Q_OS_ANDROID) && QT_VERSION >= 0x050600
|
||||
// QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
||||
// qDebug() << "High DPI auto scaling - enabled";
|
||||
//#endif
|
||||
|
||||
// Log settings
|
||||
Monero::Wallet::init(argv[0], "monero-wallet-gui");
|
||||
// qInstallMessageHandler(messageHandler);
|
||||
|
||||
MainApp app(argc, argv);
|
||||
|
||||
qDebug() << "app startd";
|
||||
|
||||
@@ -72,6 +98,9 @@ int main(int argc, char *argv[])
|
||||
qmlRegisterUncreatableType<PendingTransaction>("moneroComponents.PendingTransaction", 1, 0, "PendingTransaction",
|
||||
"PendingTransaction can't be instantiated directly");
|
||||
|
||||
qmlRegisterUncreatableType<UnsignedTransaction>("moneroComponents.UnsignedTransaction", 1, 0, "UnsignedTransaction",
|
||||
"UnsignedTransaction can't be instantiated directly");
|
||||
|
||||
qmlRegisterUncreatableType<WalletManager>("moneroComponents.WalletManager", 1, 0, "WalletManager",
|
||||
"WalletManager can't be instantiated directly");
|
||||
|
||||
@@ -91,10 +120,10 @@ int main(int argc, char *argv[])
|
||||
|
||||
qmlRegisterUncreatableType<TransactionInfo>("moneroComponents.TransactionInfo", 1, 0, "TransactionInfo",
|
||||
"TransactionHistory can't be instantiated directly");
|
||||
|
||||
#ifndef Q_OS_IOS
|
||||
qmlRegisterUncreatableType<DaemonManager>("moneroComponents.DaemonManager", 1, 0, "DaemonManager",
|
||||
"DaemonManager can't be instantiated directly");
|
||||
|
||||
#endif
|
||||
qmlRegisterUncreatableType<AddressBookModel>("moneroComponents.AddressBookModel", 1, 0, "AddressBookModel",
|
||||
"AddressBookModel can't be instantiated directly");
|
||||
|
||||
@@ -105,6 +134,10 @@ int main(int argc, char *argv[])
|
||||
qRegisterMetaType<TransactionInfo::Direction>();
|
||||
qRegisterMetaType<TransactionHistoryModel::TransactionInfoRole>();
|
||||
|
||||
#ifdef WITH_SCANNER
|
||||
qmlRegisterType<QrCodeScanner>("moneroComponents.QRCodeScanner", 1, 0, "QRCodeScanner");
|
||||
#endif
|
||||
|
||||
QQmlApplicationEngine engine;
|
||||
|
||||
OSCursor cursor;
|
||||
@@ -118,9 +151,14 @@ int main(int argc, char *argv[])
|
||||
|
||||
engine.addImageProvider(QLatin1String("qrcode"), new QRCodeImageProvider());
|
||||
const QStringList arguments = QCoreApplication::arguments();
|
||||
|
||||
engine.rootContext()->setContextProperty("mainApp", &app);
|
||||
|
||||
// Exclude daemon manager from IOS
|
||||
#ifndef Q_OS_IOS
|
||||
DaemonManager * daemonManager = DaemonManager::instance(&arguments);
|
||||
QObject::connect(&app, SIGNAL(aboutToQuit()), daemonManager, SLOT(closing()));
|
||||
engine.rootContext()->setContextProperty("daemonManager", daemonManager);
|
||||
#endif
|
||||
|
||||
// export to QML monero accounts root directory
|
||||
// wizard is talking about where
|
||||
@@ -128,13 +166,23 @@ int main(int argc, char *argv[])
|
||||
// backups - I reckon we save that in My Documents\Monero Accounts\ on
|
||||
// Windows, ~/Monero Accounts/ on nix / osx
|
||||
bool isWindows = false;
|
||||
bool isIOS = false;
|
||||
bool isMac = false;
|
||||
#ifdef Q_OS_WIN
|
||||
isWindows = true;
|
||||
QStringList moneroAccountsRootDir = QStandardPaths::standardLocations(QStandardPaths::DocumentsLocation);
|
||||
#elif defined(Q_OS_IOS)
|
||||
isIOS = true;
|
||||
QStringList moneroAccountsRootDir = QStandardPaths::standardLocations(QStandardPaths::DocumentsLocation);
|
||||
#elif defined(Q_OS_UNIX)
|
||||
QStringList moneroAccountsRootDir = QStandardPaths::standardLocations(QStandardPaths::HomeLocation);
|
||||
#endif
|
||||
#ifdef Q_OS_MAC
|
||||
isMac = true;
|
||||
#endif
|
||||
|
||||
engine.rootContext()->setContextProperty("isWindows", isWindows);
|
||||
engine.rootContext()->setContextProperty("isIOS", isIOS);
|
||||
|
||||
if (!moneroAccountsRootDir.empty()) {
|
||||
QString moneroAccountsDir = moneroAccountsRootDir.at(0) + "/Monero/wallets";
|
||||
@@ -153,15 +201,33 @@ int main(int argc, char *argv[])
|
||||
|
||||
engine.rootContext()->setContextProperty("defaultAccountName", accountName);
|
||||
engine.rootContext()->setContextProperty("applicationDirectory", QApplication::applicationDirPath());
|
||||
|
||||
bool builtWithScanner = false;
|
||||
#ifdef WITH_SCANNER
|
||||
builtWithScanner = true;
|
||||
#endif
|
||||
engine.rootContext()->setContextProperty("builtWithScanner", builtWithScanner);
|
||||
|
||||
// Load main window (context properties needs to be defined obove this line)
|
||||
engine.load(QUrl(QStringLiteral("qrc:///main.qml")));
|
||||
QObject *rootObject = engine.rootObjects().first();
|
||||
|
||||
#ifdef WITH_SCANNER
|
||||
QObject *qmlCamera = rootObject->findChild<QObject*>("qrCameraQML");
|
||||
if( qmlCamera ){
|
||||
qDebug() << "QrCodeScanner : object found";
|
||||
QCamera *camera_ = qvariant_cast<QCamera*>(qmlCamera->property("mediaObject"));
|
||||
QObject *qmlFinder = rootObject->findChild<QObject*>("QrFinder");
|
||||
qobject_cast<QrCodeScanner*>(qmlFinder)->setSource(camera_);
|
||||
} else {
|
||||
qDebug() << "QrCodeScanner : something went wrong !";
|
||||
}
|
||||
#endif
|
||||
|
||||
QObject::connect(eventFilter, SIGNAL(sequencePressed(QVariant,QVariant)), rootObject, SLOT(sequencePressed(QVariant,QVariant)));
|
||||
QObject::connect(eventFilter, SIGNAL(sequenceReleased(QVariant,QVariant)), rootObject, SLOT(sequenceReleased(QVariant,QVariant)));
|
||||
QObject::connect(eventFilter, SIGNAL(mousePressed(QVariant,QVariant,QVariant)), rootObject, SLOT(mousePressed(QVariant,QVariant,QVariant)));
|
||||
QObject::connect(eventFilter, SIGNAL(mouseReleased(QVariant,QVariant,QVariant)), rootObject, SLOT(mouseReleased(QVariant,QVariant,QVariant)));
|
||||
|
||||
//WalletManager::instance()->setLogLevel(WalletManager::LogLevel_Max);
|
||||
|
||||
return app.exec();
|
||||
}
|
||||
|
||||
1
monero
Submodule
@@ -9,10 +9,11 @@ CONFIG += c++11
|
||||
# cleaning "auto-generated" bitmonero directory on "make distclean"
|
||||
QMAKE_DISTCLEAN += -r $$WALLET_ROOT
|
||||
|
||||
INCLUDEPATH += $$WALLET_ROOT/include \
|
||||
INCLUDEPATH += $$WALLET_ROOT/include \
|
||||
$$PWD/src/libwalletqt \
|
||||
$$PWD/src/QR-Code-generator \
|
||||
$$PWD/src
|
||||
$$PWD/src \
|
||||
$$WALLET_ROOT/src
|
||||
|
||||
HEADERS += \
|
||||
filter.h \
|
||||
@@ -32,11 +33,11 @@ HEADERS += \
|
||||
src/QR-Code-generator/BitBuffer.hpp \
|
||||
src/QR-Code-generator/QrCode.hpp \
|
||||
src/QR-Code-generator/QrSegment.hpp \
|
||||
src/daemon/DaemonManager.h \
|
||||
src/model/AddressBookModel.h \
|
||||
src/libwalletqt/AddressBook.h \
|
||||
src/zxcvbn-c/zxcvbn.h
|
||||
|
||||
src/zxcvbn-c/zxcvbn.h \
|
||||
src/libwalletqt/UnsignedTransaction.h \
|
||||
MainApp.h
|
||||
|
||||
SOURCES += main.cpp \
|
||||
filter.cpp \
|
||||
@@ -55,10 +56,16 @@ SOURCES += main.cpp \
|
||||
src/QR-Code-generator/BitBuffer.cpp \
|
||||
src/QR-Code-generator/QrCode.cpp \
|
||||
src/QR-Code-generator/QrSegment.cpp \
|
||||
src/daemon/DaemonManager.cpp \
|
||||
src/model/AddressBookModel.cpp \
|
||||
src/libwalletqt/AddressBook.cpp \
|
||||
src/zxcvbn-c/zxcvbn.c
|
||||
src/zxcvbn-c/zxcvbn.c \
|
||||
src/libwalletqt/UnsignedTransaction.cpp \
|
||||
MainApp.cpp
|
||||
|
||||
!ios {
|
||||
HEADERS += src/daemon/DaemonManager.h
|
||||
SOURCES += src/daemon/DaemonManager.cpp
|
||||
}
|
||||
|
||||
lupdate_only {
|
||||
SOURCES = *.qml \
|
||||
@@ -68,35 +75,115 @@ SOURCES = *.qml \
|
||||
wizard/*js
|
||||
}
|
||||
|
||||
|
||||
ios:armv7 {
|
||||
message("target is armv7")
|
||||
LIBS += \
|
||||
-L$$PWD/../ofxiOSBoost/build/libs/boost/lib/armv7 \
|
||||
}
|
||||
ios:arm64 {
|
||||
message("target is arm64")
|
||||
LIBS += \
|
||||
-L$$PWD/../ofxiOSBoost/build/libs/boost/lib/arm64 \
|
||||
}
|
||||
!ios {
|
||||
LIBS += -L$$WALLET_ROOT/lib \
|
||||
-lwallet_merged \
|
||||
-lepee \
|
||||
-lunbound \
|
||||
-leasylogging
|
||||
}
|
||||
|
||||
|
||||
ios {
|
||||
message("Host is IOS")
|
||||
|
||||
QMAKE_LFLAGS += -v
|
||||
QMAKE_IOS_DEVICE_ARCHS = arm64
|
||||
CONFIG += arm64
|
||||
LIBS += -L$$WALLET_ROOT/lib-ios \
|
||||
-lwallet_merged \
|
||||
-lepee \
|
||||
-lunbound
|
||||
|
||||
LIBS+= \
|
||||
-L$$PWD/../OpenSSL-for-iPhone/lib \
|
||||
-L$$PWD/../ofxiOSBoost/build/libs/boost/lib/arm64 \
|
||||
-lboost_serialization \
|
||||
-lboost_thread \
|
||||
-lboost_system \
|
||||
-lboost_date_time \
|
||||
-lboost_filesystem \
|
||||
-lboost_regex \
|
||||
-lboost_chrono \
|
||||
-lboost_program_options \
|
||||
-lssl \
|
||||
-lcrypto \
|
||||
-ldl
|
||||
}
|
||||
|
||||
CONFIG(WITH_SCANNER) {
|
||||
if( greaterThan(QT_MINOR_VERSION, 5) ) {
|
||||
message("using camera scanner")
|
||||
QT += multimedia
|
||||
DEFINES += "WITH_SCANNER"
|
||||
INCLUDEPATH += $$PWD/src/QR-Code-scanner
|
||||
HEADERS += \
|
||||
src/QR-Code-scanner/QrScanThread.h \
|
||||
src/QR-Code-scanner/QrCodeScanner.h
|
||||
SOURCES += \
|
||||
src/QR-Code-scanner/QrScanThread.cpp \
|
||||
src/QR-Code-scanner/QrCodeScanner.cpp
|
||||
android {
|
||||
INCLUDEPATH += $$PWD/../ZBar/include
|
||||
LIBS += -lzbarjni -liconv
|
||||
} else {
|
||||
LIBS += -lzbar
|
||||
}
|
||||
} else {
|
||||
message("Skipping camera scanner because of Incompatible Qt Version !")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# currently we only support x86 build as qt.io only provides prebuilt qt for x86 mingw
|
||||
|
||||
win32 {
|
||||
|
||||
# Win64 Host settings
|
||||
contains(QMAKE_HOST.arch, x86_64) {
|
||||
message("Host is 64bit")
|
||||
MSYS_PATH=c:/msys64/mingw32
|
||||
# QMAKE_HOST.arch is unreliable, will allways report 32bit if mingw32 shell is run.
|
||||
# Obtaining arch through uname should be reliable. This also fixes building the project in Qt creator without changes.
|
||||
MSYS_HOST_ARCH = $$system(uname -a | grep -o "x86_64")
|
||||
|
||||
# boost root path
|
||||
BOOST_PATH=c:/msys64/mingw64/boost
|
||||
# WIN64 Host settings
|
||||
contains(MSYS_HOST_ARCH, x86_64) {
|
||||
message("Host is 64bit")
|
||||
MSYS_ROOT_PATH=c:/msys64
|
||||
|
||||
# WIN32 Host settings
|
||||
} else {
|
||||
message("Host is 32bit")
|
||||
MSYS_PATH=c:/msys32/mingw32
|
||||
|
||||
# boost root path
|
||||
BOOST_PATH=c:/msys32/mingw32/boost
|
||||
|
||||
MSYS_ROOT_PATH=c:/msys32
|
||||
}
|
||||
|
||||
# WIN64 Target settings
|
||||
contains(QMAKE_HOST.arch, x86_64) {
|
||||
MSYS_MINGW_PATH=/mingw64
|
||||
|
||||
# WIN32 Target settings
|
||||
} else {
|
||||
MSYS_MINGW_PATH=/mingw32
|
||||
}
|
||||
|
||||
MSYS_PATH=$$MSYS_ROOT_PATH$$MSYS_MINGW_PATH
|
||||
|
||||
# boost root path
|
||||
BOOST_PATH=$$MSYS_PATH/boost
|
||||
BOOST_MINGW_PATH=$$MSYS_MINGW_PATH/boost
|
||||
|
||||
LIBS+=-L$$MSYS_PATH/lib
|
||||
LIBS+=-L$$MSYS_MINGW_PATH/lib
|
||||
LIBS+=-L$$BOOST_PATH/lib
|
||||
LIBS+=-L$$BOOST_MINGW_PATH/lib
|
||||
|
||||
LIBS+= \
|
||||
-Wl,-Bstatic \
|
||||
@@ -129,7 +216,18 @@ win32 {
|
||||
}
|
||||
|
||||
linux {
|
||||
LIBS+= -Wl,-Bstatic
|
||||
CONFIG(static) {
|
||||
message("using static libraries")
|
||||
LIBS+= -Wl,-Bstatic
|
||||
QMAKE_LFLAGS += -static-libgcc -static-libstdc++
|
||||
# contains(QT_ARCH, x86_64) {
|
||||
LIBS+= -lunbound
|
||||
# }
|
||||
} else {
|
||||
# On some distro's we need to add dynload
|
||||
LIBS+= -ldl
|
||||
}
|
||||
|
||||
LIBS+= \
|
||||
-lboost_serialization \
|
||||
-lboost_thread \
|
||||
@@ -140,9 +238,13 @@ linux {
|
||||
-lboost_chrono \
|
||||
-lboost_program_options \
|
||||
-lssl \
|
||||
-lcrypto \
|
||||
-Wl,-Bdynamic \
|
||||
-ldl
|
||||
-lcrypto
|
||||
|
||||
if(!android) {
|
||||
LIBS+= \
|
||||
-Wl,-Bdynamic \
|
||||
-lGL
|
||||
}
|
||||
# currently monero has an issue with "static" build and linunwind-dev,
|
||||
# so we link libunwind-dev only for non-Ubuntu distros
|
||||
CONFIG(libunwind_off) {
|
||||
@@ -154,6 +256,11 @@ linux {
|
||||
}
|
||||
|
||||
macx {
|
||||
# mixing static and shared libs are not supported on mac
|
||||
# CONFIG(static) {
|
||||
# message("using static libraries")
|
||||
# LIBS+= -Wl,-Bstatic
|
||||
# }
|
||||
LIBS+= \
|
||||
-L/usr/local/lib \
|
||||
-L/usr/local/opt/openssl/lib \
|
||||
@@ -175,17 +282,27 @@ macx {
|
||||
|
||||
# translation stuff
|
||||
TRANSLATIONS = \ # English is default language, no explicit translation file
|
||||
$$PWD/translations/monero-core.ts \ # translation source (copy this file when creating a new translation)
|
||||
$$PWD/translations/monero-core_ar.ts \ # Arabic
|
||||
$$PWD/translations/monero-core_de.ts \ # Deutsch
|
||||
$$PWD/translations/monero-core_pt-br.ts \ # Portuguese (Brazil)
|
||||
$$PWD/translations/monero-core_de.ts \ # German
|
||||
$$PWD/translations/monero-core_eo.ts \ # Esperanto
|
||||
$$PWD/translations/monero-core_es.ts \ # Spanish
|
||||
$$PWD/translations/monero-core_fi.ts \ # Finnish
|
||||
$$PWD/translations/monero-core_fr.ts \ # French
|
||||
$$PWD/translations/monero-core_hr.ts \ # Croatian
|
||||
$$PWD/translations/monero-core_in.ts \ # Hindi
|
||||
$$PWD/translations/monero-core_id.ts \ # Indonesian
|
||||
$$PWD/translations/monero-core_hi.ts \ # Hindi
|
||||
$$PWD/translations/monero-core_it.ts \ # Italian
|
||||
$$PWD/translations/monero-core_ja.ts \ # Japanese
|
||||
$$PWD/translations/monero-core_nl.ts \ # Dutch
|
||||
$$PWD/translations/monero-core_pl.ts \ # Polish
|
||||
$$PWD/translations/monero-core_ru.ts \ # Russian
|
||||
$$PWD/translations/monero-core_zh.ts \ # Chineese
|
||||
$$PWD/translations/monero-core_sv.ts \ # Swedish
|
||||
$$PWD/translations/monero-core_zh-cn.ts \ # Chinese (Simplified-China)
|
||||
$$PWD/translations/monero-core_zh-tw.ts \ # Chinese (Traditional-Taiwan)
|
||||
$$PWD/translations/monero-core_he.ts \ # Hebrew
|
||||
$$PWD/translations/monero-core_ko.ts \ # Korean
|
||||
|
||||
CONFIG(release, debug|release) {
|
||||
DESTDIR = release/bin
|
||||
@@ -195,7 +312,7 @@ CONFIG(release, debug|release) {
|
||||
} else {
|
||||
DESTDIR = debug/bin
|
||||
LANGUPD_OPTIONS =
|
||||
LANGREL_OPTIONS = -markuntranslated "MISS_TR "
|
||||
# LANGREL_OPTIONS = -markuntranslated "MISS_TR "
|
||||
}
|
||||
|
||||
TARGET_FULL_PATH = $$OUT_PWD/$$DESTDIR
|
||||
@@ -207,32 +324,36 @@ macx {
|
||||
}
|
||||
|
||||
|
||||
!ios {
|
||||
isEmpty(QMAKE_LUPDATE) {
|
||||
win32:LANGUPD = $$[QT_INSTALL_BINS]\lupdate.exe
|
||||
else:LANGUPD = $$[QT_INSTALL_BINS]/lupdate
|
||||
}
|
||||
|
||||
isEmpty(QMAKE_LUPDATE) {
|
||||
win32:LANGUPD = $$[QT_INSTALL_BINS]\lupdate.exe
|
||||
else:LANGUPD = $$[QT_INSTALL_BINS]/lupdate
|
||||
isEmpty(QMAKE_LRELEASE) {
|
||||
win32:LANGREL = $$[QT_INSTALL_BINS]\lrelease.exe
|
||||
else:LANGREL = $$[QT_INSTALL_BINS]/lrelease
|
||||
}
|
||||
|
||||
langupd.command = \
|
||||
$$LANGUPD $$LANGUPD_OPTIONS $$shell_path($$_PRO_FILE) -ts $$_PRO_FILE_PWD/$$TRANSLATIONS
|
||||
|
||||
|
||||
|
||||
langrel.depends = langupd
|
||||
langrel.input = TRANSLATIONS
|
||||
langrel.output = $$TRANSLATION_TARGET_DIR/${QMAKE_FILE_BASE}.qm
|
||||
langrel.commands = \
|
||||
$$LANGREL $$LANGREL_OPTIONS ${QMAKE_FILE_IN} -qm $$TRANSLATION_TARGET_DIR/${QMAKE_FILE_BASE}.qm
|
||||
langrel.CONFIG += no_link
|
||||
|
||||
QMAKE_EXTRA_TARGETS += langupd deploy deploy_win
|
||||
QMAKE_EXTRA_COMPILERS += langrel
|
||||
}
|
||||
|
||||
isEmpty(QMAKE_LRELEASE) {
|
||||
win32:LANGREL = $$[QT_INSTALL_BINS]\lrelease.exe
|
||||
else:LANGREL = $$[QT_INSTALL_BINS]/lrelease
|
||||
}
|
||||
|
||||
langupd.command = \
|
||||
$$LANGUPD $$LANGUPD_OPTIONS $$shell_path($$_PRO_FILE) -ts $$_PRO_FILE_PWD/$$TRANSLATIONS
|
||||
|
||||
|
||||
|
||||
langrel.depends = langupd
|
||||
langrel.input = TRANSLATIONS
|
||||
langrel.output = $$TRANSLATION_TARGET_DIR/${QMAKE_FILE_BASE}.qm
|
||||
langrel.commands = \
|
||||
$$LANGREL $$LANGREL_OPTIONS ${QMAKE_FILE_IN} -qm $$TRANSLATION_TARGET_DIR/${QMAKE_FILE_BASE}.qm
|
||||
langrel.CONFIG += no_link
|
||||
|
||||
QMAKE_EXTRA_TARGETS += langupd deploy deploy_win
|
||||
QMAKE_EXTRA_COMPILERS += langrel
|
||||
|
||||
|
||||
|
||||
# Update: no issues with the "slow link process" anymore,
|
||||
@@ -243,6 +364,7 @@ QMAKE_EXTRA_COMPILERS += langrel
|
||||
PRE_TARGETDEPS += langupd compiler_langrel_make_all
|
||||
|
||||
RESOURCES += qml.qrc
|
||||
CONFIG += qtquickcompiler
|
||||
|
||||
# Additional import path used to resolve QML modules in Qt Creator's code model
|
||||
QML_IMPORT_PATH =
|
||||
@@ -261,10 +383,13 @@ win32 {
|
||||
}
|
||||
}
|
||||
|
||||
linux {
|
||||
linux:!android {
|
||||
deploy.commands += $$escape_expand(\n\t) $$PWD/linuxdeploy_helper.sh $$DESTDIR $$TARGET
|
||||
}
|
||||
|
||||
android{
|
||||
deploy.commands += make install INSTALL_ROOT=$$DESTDIR && androiddeployqt --input android-libmonero-wallet-gui.so-deployment-settings.json --output $$DESTDIR --deployment bundled --android-platform android-21 --jdk /usr/lib/jvm/java-8-openjdk-amd64 -qmldir=$$PWD
|
||||
}
|
||||
|
||||
|
||||
OTHER_FILES += \
|
||||
@@ -272,7 +397,9 @@ OTHER_FILES += \
|
||||
$$TRANSLATIONS
|
||||
|
||||
DISTFILES += \
|
||||
notes.txt
|
||||
notes.txt \
|
||||
monero/src/wallet/CMakeLists.txt \
|
||||
components/MobileHeader.qml
|
||||
|
||||
|
||||
# windows application icon
|
||||
|
||||
12
oshelper.cpp
@@ -1,6 +1,8 @@
|
||||
#include "oshelper.h"
|
||||
#include <QTemporaryFile>
|
||||
#include <QDir>
|
||||
#include <QDebug>
|
||||
#include <QString>
|
||||
|
||||
OSHelper::OSHelper(QObject *parent) : QObject(parent)
|
||||
{
|
||||
@@ -18,6 +20,16 @@ QString OSHelper::temporaryFilename() const
|
||||
return tempFileName;
|
||||
}
|
||||
|
||||
bool OSHelper::removeTemporaryWallet(const QString &fileName) const
|
||||
{
|
||||
// Temporary files should be deleted automatically by default, in case they wouldn't, we delete them manually as well
|
||||
bool cache_deleted = QFile::remove(fileName);
|
||||
bool address_deleted = QFile::remove(fileName + ".address.txt");
|
||||
bool keys_deleted = QFile::remove(fileName +".keys");
|
||||
|
||||
return cache_deleted && address_deleted && keys_deleted;
|
||||
}
|
||||
|
||||
QString OSHelper::temporaryPath() const
|
||||
{
|
||||
return QDir::tempPath();
|
||||
|
||||
@@ -13,6 +13,7 @@ public:
|
||||
|
||||
Q_INVOKABLE QString temporaryFilename() const;
|
||||
Q_INVOKABLE QString temporaryPath() const;
|
||||
Q_INVOKABLE bool removeTemporaryWallet(const QString &walletName) const;
|
||||
|
||||
signals:
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import QtQuick 2.0
|
||||
import QtQuick.Layouts 1.1
|
||||
import "../components"
|
||||
import moneroComponents.AddressBook 1.0
|
||||
import moneroComponents.AddressBookModel 1.0
|
||||
@@ -57,20 +58,39 @@ Rectangle {
|
||||
anchors.top: newEntryText.bottom
|
||||
anchors.leftMargin: 17
|
||||
anchors.topMargin: 17
|
||||
text: qsTr("Address")
|
||||
text: qsTr("Address") + translationManager.emptyString
|
||||
fontSize: 14
|
||||
tipText: qsTr("<b>Tip tekst test</b>") + translationManager.emptyString
|
||||
}
|
||||
|
||||
StandardButton {
|
||||
id: qrfinderButton
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 17
|
||||
anchors.topMargin: 5
|
||||
anchors.top: addressLabel.bottom
|
||||
text: qsTr("QRCODE") + translationManager.emptyString
|
||||
shadowReleasedColor: "#FF4304"
|
||||
shadowPressedColor: "#B32D00"
|
||||
releasedColor: "#FF6C3C"
|
||||
pressedColor: "#FF4304"
|
||||
visible : appWindow.qrScannerEnabled
|
||||
enabled : visible
|
||||
width: visible ? 60 : 0
|
||||
onClicked: {
|
||||
cameraUi.state = "Capture"
|
||||
cameraUi.qrcode_decoded.connect(updateFromQrCode)
|
||||
}
|
||||
}
|
||||
|
||||
LineEdit {
|
||||
id: addressLine
|
||||
anchors.left: parent.left
|
||||
anchors.left: qrfinderButton.right
|
||||
anchors.right: parent.right
|
||||
anchors.top: addressLabel.bottom
|
||||
anchors.leftMargin: 17
|
||||
anchors.rightMargin: 17
|
||||
anchors.topMargin: 5
|
||||
error: true;
|
||||
placeholderText: qsTr("4...") + translationManager.emptyString
|
||||
}
|
||||
|
||||
Label {
|
||||
@@ -81,8 +101,6 @@ Rectangle {
|
||||
anchors.topMargin: 17
|
||||
text: qsTr("Payment ID <font size='2'>(Optional)</font>") + translationManager.emptyString
|
||||
fontSize: 14
|
||||
tipText: qsTr("<b>Payment ID</b><br/><br/>A unique user name used in<br/>the address book. It is not a<br/>transfer of information sent<br/>during the transfer")
|
||||
+ translationManager.emptyString
|
||||
}
|
||||
|
||||
LineEdit {
|
||||
@@ -93,6 +111,7 @@ Rectangle {
|
||||
anchors.leftMargin: 17
|
||||
anchors.rightMargin: 17
|
||||
anchors.topMargin: 5
|
||||
placeholderText: qsTr("Paste 64 hexadecimal characters") + translationManager.emptyString
|
||||
}
|
||||
|
||||
Label {
|
||||
@@ -101,9 +120,8 @@ Rectangle {
|
||||
anchors.top: paymentIdLine.bottom
|
||||
anchors.leftMargin: 17
|
||||
anchors.topMargin: 17
|
||||
text: qsTr("Description <font size='2'>(Local database)</font>") + translationManager.emptyString
|
||||
text: qsTr("Description <font size='2'>(Optional)</font>") + translationManager.emptyString
|
||||
fontSize: 14
|
||||
tipText: qsTr("<b>Tip test test</b><br/><br/>test line 2") + translationManager.emptyString
|
||||
}
|
||||
|
||||
LineEdit {
|
||||
@@ -114,44 +132,49 @@ Rectangle {
|
||||
anchors.leftMargin: 17
|
||||
anchors.rightMargin: 17
|
||||
anchors.topMargin: 5
|
||||
placeholderText: qsTr("Give this entry a name or description") + translationManager.emptyString
|
||||
}
|
||||
|
||||
StandardButton {
|
||||
|
||||
RowLayout {
|
||||
id: addButton
|
||||
anchors.left: parent.left
|
||||
anchors.top: descriptionLine.bottom
|
||||
anchors.leftMargin: 17
|
||||
anchors.topMargin: 17
|
||||
width: 60
|
||||
|
||||
shadowReleasedColor: "#FF4304"
|
||||
shadowPressedColor: "#B32D00"
|
||||
releasedColor: "#FF6C3C"
|
||||
pressedColor: "#FF4304"
|
||||
text: qsTr("ADD")
|
||||
enabled: checkInformation(addressLine.text, paymentIdLine.text, appWindow.persistentSettings.testnet)
|
||||
StandardButton {
|
||||
shadowReleasedColor: "#FF4304"
|
||||
shadowPressedColor: "#B32D00"
|
||||
releasedColor: "#FF6C3C"
|
||||
pressedColor: "#FF4304"
|
||||
text: qsTr("Add") + translationManager.emptyString
|
||||
enabled: checkInformation(addressLine.text, paymentIdLine.text, appWindow.persistentSettings.testnet)
|
||||
|
||||
onClicked: {
|
||||
if (!currentWallet.addressBook.addRow(addressLine.text.trim(), paymentIdLine.text.trim(), descriptionLine.text)) {
|
||||
informationPopup.title = qsTr("Error") + translationManager.emptyString;
|
||||
// TODO: check currentWallet.addressBook.errorString() instead.
|
||||
if(currentWallet.addressBook.errorCode() === AddressBook.Invalid_Address)
|
||||
informationPopup.text = qsTr("Invalid address")
|
||||
else if(currentWallet.addressBook.errorCode() === AddressBook.Invalid_Payment_Id)
|
||||
informationPopup.text = qsTr("Invalid Payment ID")
|
||||
else
|
||||
informationPopup.text = qsTr("Can't create entry")
|
||||
onClicked: {
|
||||
if (!currentWallet.addressBook.addRow(addressLine.text.trim(), paymentIdLine.text.trim(), descriptionLine.text)) {
|
||||
informationPopup.title = qsTr("Error") + translationManager.emptyString;
|
||||
// TODO: check currentWallet.addressBook.errorString() instead.
|
||||
if(currentWallet.addressBook.errorCode() === AddressBook.Invalid_Address)
|
||||
informationPopup.text = qsTr("Invalid address") + translationManager.emptyString
|
||||
else if(currentWallet.addressBook.errorCode() === AddressBook.Invalid_Payment_Id)
|
||||
informationPopup.text = currentWallet.addressBook.errorString()
|
||||
else
|
||||
informationPopup.text = qsTr("Can't create entry") + translationManager.emptyString
|
||||
|
||||
informationPopup.onCloseCallback = null
|
||||
informationPopup.open();
|
||||
} else {
|
||||
addressLine.text = "";
|
||||
paymentIdLine.text = "";
|
||||
descriptionLine.text = "";
|
||||
informationPopup.onCloseCallback = null
|
||||
informationPopup.open();
|
||||
} else {
|
||||
addressLine.text = "";
|
||||
paymentIdLine.text = "";
|
||||
descriptionLine.text = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Item {
|
||||
id: expandItem
|
||||
property bool expanded: false
|
||||
@@ -275,5 +298,13 @@ Rectangle {
|
||||
root.model = currentWallet.addressBookModel;
|
||||
}
|
||||
|
||||
function updateFromQrCode(address, payment_id, amount, tx_description, recipient_name) {
|
||||
console.log("updateFromQrCode")
|
||||
addressLine.text = address
|
||||
paymentIdLine.text = payment_id
|
||||
//amountLine.text = amount
|
||||
descriptionLine.text = recipient_name + " " + tx_description
|
||||
cameraUi.qrcode_decoded.disconnect(updateFromQrCode)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -120,6 +120,7 @@ Rectangle {
|
||||
|
||||
|
||||
Text {
|
||||
visible: !isMobile
|
||||
id: filterHeaderText
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
@@ -135,6 +136,7 @@ Rectangle {
|
||||
}
|
||||
|
||||
Label {
|
||||
visible: !isMobile
|
||||
id: selectedAmount
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
@@ -142,7 +144,6 @@ Rectangle {
|
||||
anchors.topMargin: 17
|
||||
text: getSelectedAmount()
|
||||
fontSize: 14
|
||||
tipText: qsTr("<b>Total amount of selected payments</b>") + translationManager.emptyString
|
||||
}
|
||||
|
||||
|
||||
@@ -156,7 +157,6 @@ Rectangle {
|
||||
anchors.topMargin: 17
|
||||
text: qsTr("Address")
|
||||
fontSize: 14
|
||||
tipText: qsTr("<b>Tip tekst test</b>") + translationManager.emptyString
|
||||
}
|
||||
|
||||
LineEdit {
|
||||
@@ -172,6 +172,7 @@ Rectangle {
|
||||
|
||||
// Filter by string
|
||||
LineEdit {
|
||||
visible: !isMobile
|
||||
id: searchLine
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
@@ -196,7 +197,6 @@ Rectangle {
|
||||
anchors.topMargin: 17
|
||||
text: qsTr("Description <font size='2'>(Local database)</font>") + translationManager.emptyString
|
||||
fontSize: 14
|
||||
tipText: qsTr("<b>Tip tekst test</b><br/><br/>test line 2") + translationManager.emptyString
|
||||
}
|
||||
|
||||
LineEdit {
|
||||
@@ -213,6 +213,7 @@ Rectangle {
|
||||
|
||||
// DateFrom picker
|
||||
Label {
|
||||
visible: !isMobile
|
||||
id: dateFromText
|
||||
anchors.left: parent.left
|
||||
anchors.top: searchLine.bottom // descriptionLine.bottom
|
||||
@@ -221,10 +222,10 @@ Rectangle {
|
||||
width: 156
|
||||
text: qsTr("Date from") + translationManager.emptyString
|
||||
fontSize: 14
|
||||
tipText: qsTr("<b>Tip tekst test</b>") + translationManager.emptyString
|
||||
}
|
||||
|
||||
DatePicker {
|
||||
visible: !isMobile
|
||||
id: fromDatePicker
|
||||
anchors.left: parent.left
|
||||
anchors.top: dateFromText.bottom
|
||||
@@ -239,17 +240,18 @@ Rectangle {
|
||||
|
||||
// DateTo picker
|
||||
Label {
|
||||
visible: !isMobile
|
||||
id: dateToText
|
||||
anchors.left: dateFromText.right
|
||||
anchors.top: searchLine.bottom //descriptionLine.bottom
|
||||
anchors.leftMargin: 17
|
||||
anchors.topMargin: 17
|
||||
text: qsTr("To")
|
||||
text: qsTr("To") + translationManager.emptyString
|
||||
fontSize: 14
|
||||
tipText: qsTr("<b>Tip tekst test</b>") + translationManager.emptyString
|
||||
}
|
||||
|
||||
DatePicker {
|
||||
visible: !isMobile
|
||||
id: toDatePicker
|
||||
anchors.left: fromDatePicker.right
|
||||
anchors.top: dateToText.bottom
|
||||
@@ -265,12 +267,13 @@ Rectangle {
|
||||
|
||||
|
||||
StandardButton {
|
||||
visible: !isMobile
|
||||
id: filterButton
|
||||
anchors.bottom: toDatePicker.bottom
|
||||
anchors.left: toDatePicker.right
|
||||
anchors.leftMargin: 17
|
||||
width: 60
|
||||
text: qsTr("FILTER")
|
||||
text: qsTr("Filter") + translationManager.emptyString
|
||||
shadowReleasedColor: "#4D0051"
|
||||
shadowPressedColor: "#2D002F"
|
||||
releasedColor: "#6B0072"
|
||||
@@ -306,8 +309,9 @@ Rectangle {
|
||||
}
|
||||
|
||||
CheckBox {
|
||||
visible: !isMobile
|
||||
id: advancedFilteringCheckBox
|
||||
text: qsTr("Advanced filtering")
|
||||
text: qsTr("Advanced filtering") + translationManager.emptyString
|
||||
anchors.left: filterButton.right
|
||||
anchors.bottom: filterButton.bottom
|
||||
anchors.leftMargin: 17
|
||||
@@ -320,6 +324,7 @@ Rectangle {
|
||||
}
|
||||
|
||||
Label {
|
||||
visible: !isMobile
|
||||
id: transactionTypeText
|
||||
anchors.left: parent.left
|
||||
anchors.top: fromDatePicker.bottom
|
||||
@@ -328,18 +333,18 @@ Rectangle {
|
||||
width: 156
|
||||
text: qsTr("Type of transaction") + translationManager.emptyString
|
||||
fontSize: 14
|
||||
tipText: qsTr("<b>Tip tekst test</b>") + translationManager.emptyString
|
||||
}
|
||||
|
||||
ListModel {
|
||||
id: transactionsModel
|
||||
ListElement { column1: "ALL"; column2: ""; value: TransactionInfo.Direction_Both }
|
||||
ListElement { column1: "SENT"; column2: ""; value: TransactionInfo.Direction_Out }
|
||||
ListElement { column1: "RECEIVED"; column2: ""; value: TransactionInfo.Direction_In }
|
||||
ListElement { column1: "All"; column2: ""; value: TransactionInfo.Direction_Both }
|
||||
ListElement { column1: "Sent"; column2: ""; value: TransactionInfo.Direction_Out }
|
||||
ListElement { column1: "Received"; column2: ""; value: TransactionInfo.Direction_In }
|
||||
|
||||
}
|
||||
|
||||
StandardDropdown {
|
||||
visible: !isMobile
|
||||
id: transactionTypeDropdown
|
||||
anchors.left: parent.left
|
||||
anchors.top: transactionTypeText.bottom
|
||||
@@ -355,6 +360,7 @@ Rectangle {
|
||||
}
|
||||
|
||||
Label {
|
||||
visible: !isMobile
|
||||
id: amountFromText
|
||||
anchors.left: transactionTypeText.right
|
||||
anchors.top: fromDatePicker.bottom
|
||||
@@ -363,10 +369,10 @@ Rectangle {
|
||||
width: 156
|
||||
text: qsTr("Amount from") + translationManager.emptyString
|
||||
fontSize: 14
|
||||
tipText: qsTr("<b>Tip tekst test</b>") + translationManager.emptyString
|
||||
}
|
||||
|
||||
LineEdit {
|
||||
visible: !isMobile
|
||||
id: amountFromLine
|
||||
anchors.left: transactionTypeDropdown.right
|
||||
anchors.top: amountFromText.bottom
|
||||
@@ -387,18 +393,19 @@ Rectangle {
|
||||
}
|
||||
|
||||
Label {
|
||||
visible: !isMobile
|
||||
id: amountToText
|
||||
anchors.left: amountFromText.right
|
||||
anchors.top: fromDatePicker.bottom
|
||||
anchors.leftMargin: 17
|
||||
anchors.topMargin: 17
|
||||
width: 156
|
||||
text: qsTr("To")
|
||||
text: qsTr("To") + translationManager.emptyString
|
||||
fontSize: 14
|
||||
tipText: qsTr("<b>Tip tekst test</b>") + translationManager.emptyString
|
||||
}
|
||||
|
||||
LineEdit {
|
||||
visible: !isMobile
|
||||
id: amountToLine
|
||||
anchors.left: amountFromLine.right
|
||||
anchors.top: amountToText.bottom
|
||||
@@ -420,6 +427,7 @@ Rectangle {
|
||||
}
|
||||
|
||||
Item {
|
||||
visible: !isMobile
|
||||
id: expandItem
|
||||
property bool expanded: false
|
||||
|
||||
@@ -449,16 +457,17 @@ Rectangle {
|
||||
|
||||
Rectangle {
|
||||
id: tableRect
|
||||
property int expandedHeight: parent.height - filterHeaderText.y - filterHeaderText.height - 17
|
||||
property int expandedHeight: parent.height - filterHeaderText.y - filterHeaderText.height - 5
|
||||
property int middleHeight: parent.height - fromDatePicker.y - fromDatePicker.height - 17
|
||||
property int collapsedHeight: parent.height - transactionTypeDropdown.y - transactionTypeDropdown.height - 17
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
// anchors.top: parent.top
|
||||
color: "#FFFFFF"
|
||||
z: 1
|
||||
|
||||
height: middleHeight
|
||||
height: (isMobile)? parent.height : middleHeight
|
||||
onHeightChanged: {
|
||||
if(height === middleHeight) z = 1
|
||||
else if(height === collapsedHeight) z = 0
|
||||
@@ -540,6 +549,11 @@ Rectangle {
|
||||
anchors.rightMargin: 14
|
||||
onContentYChanged: flickableScroll.flickableContentYChanged()
|
||||
model: root.model
|
||||
addressBookModel: null
|
||||
}
|
||||
}
|
||||
|
||||
function onPageCompleted() {
|
||||
table.addressBookModel = appWindow.currentWallet ? appWindow.currentWallet.addressBookModel : null
|
||||
}
|
||||
}
|
||||
|
||||
195
pages/Mining.qml
@@ -27,8 +27,199 @@
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import QtQuick 2.0
|
||||
import QtQuick.Layouts 1.1
|
||||
import QtQuick.Dialogs 1.2
|
||||
import "../components"
|
||||
import moneroComponents.Wallet 1.0
|
||||
|
||||
Rectangle {
|
||||
width: 100
|
||||
height: 62
|
||||
id: root
|
||||
color: "#F0EEEE"
|
||||
property var currentHashRate: 0
|
||||
|
||||
/* main layout */
|
||||
ColumnLayout {
|
||||
id: mainLayout
|
||||
anchors.margins: 40
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.top
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
spacing: 20
|
||||
|
||||
// solo
|
||||
ColumnLayout {
|
||||
id: soloBox
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
spacing: 20
|
||||
|
||||
Label {
|
||||
id: soloTitleLabel
|
||||
fontSize: 24
|
||||
text: qsTr("Solo mining") + translationManager.emptyString
|
||||
}
|
||||
|
||||
Label {
|
||||
id: soloLocalDaemonsLabel
|
||||
fontSize: 18
|
||||
color: "#D02020"
|
||||
text: qsTr("(only available for local daemons)")
|
||||
visible: !isDaemonLocal()
|
||||
}
|
||||
|
||||
Text {
|
||||
id: soloMainLabel
|
||||
text: qsTr("Mining with your computer helps strengthen the Monero network. The more that people mine, the harder it is for the network to be attacked, and every little bit helps.<br> <br>Mining also gives you a small chance to earn some Monero. Your computer will create hashes looking for block solutions. If you find a block, you will get the associated reward. Good luck!") + translationManager.emptyString
|
||||
wrapMode: Text.Wrap
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
id: soloMinerThreadsRow
|
||||
Label {
|
||||
id: soloMinerThreadsLabel
|
||||
color: "#4A4949"
|
||||
text: qsTr("CPU threads") + translationManager.emptyString
|
||||
fontSize: 16
|
||||
Layout.preferredWidth: 120
|
||||
}
|
||||
LineEdit {
|
||||
id: soloMinerThreadsLine
|
||||
Layout.preferredWidth: 200
|
||||
text: "1"
|
||||
placeholderText: qsTr("(optional)") + translationManager.emptyString
|
||||
validator: IntValidator { bottom: 1 }
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Layout.leftMargin: 125
|
||||
CheckBox {
|
||||
id: backgroundMining
|
||||
enabled: startSoloMinerButton.enabled
|
||||
checked: persistentSettings.allow_background_mining
|
||||
onClicked: {persistentSettings.allow_background_mining = checked}
|
||||
text: qsTr("Background mining (experimental)") + translationManager.emptyString
|
||||
checkedIcon: "../images/checkedVioletIcon.png"
|
||||
uncheckedIcon: "../images/uncheckedIcon.png"
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
// Disable this option until stable
|
||||
visible: false
|
||||
Layout.leftMargin: 125
|
||||
CheckBox {
|
||||
id: ignoreBattery
|
||||
enabled: startSoloMinerButton.enabled
|
||||
checked: !persistentSettings.miningIgnoreBattery
|
||||
onClicked: {persistentSettings.miningIgnoreBattery = !checked}
|
||||
text: qsTr("Enable mining when running on battery") + translationManager.emptyString
|
||||
checkedIcon: "../images/checkedVioletIcon.png"
|
||||
uncheckedIcon: "../images/uncheckedIcon.png"
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Label {
|
||||
id: manageSoloMinerLabel
|
||||
color: "#4A4949"
|
||||
text: qsTr("Manage miner") + translationManager.emptyString
|
||||
fontSize: 16
|
||||
}
|
||||
|
||||
StandardButton {
|
||||
visible: true
|
||||
//enabled: !walletManager.isMining()
|
||||
id: startSoloMinerButton
|
||||
width: 110
|
||||
text: qsTr("Start mining") + translationManager.emptyString
|
||||
shadowReleasedColor: "#FF4304"
|
||||
shadowPressedColor: "#B32D00"
|
||||
releasedColor: "#FF6C3C"
|
||||
pressedColor: "#FF4304"
|
||||
onClicked: {
|
||||
var success = walletManager.startMining(appWindow.currentWallet.address, soloMinerThreadsLine.text, persistentSettings.allow_background_mining, persistentSettings.miningIgnoreBattery)
|
||||
if (success) {
|
||||
update()
|
||||
} else {
|
||||
errorPopup.title = qsTr("Error starting mining") + translationManager.emptyString;
|
||||
errorPopup.text = qsTr("Couldn't start mining.<br>")
|
||||
if (!isDaemonLocal())
|
||||
errorPopup.text += qsTr("Mining is only available on local daemons. Run a local daemon to be able to mine.<br>")
|
||||
errorPopup.icon = StandardIcon.Critical
|
||||
errorPopup.open()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StandardButton {
|
||||
visible: true
|
||||
//enabled: walletManager.isMining()
|
||||
id: stopSoloMinerButton
|
||||
width: 110
|
||||
text: qsTr("Stop mining") + translationManager.emptyString
|
||||
shadowReleasedColor: "#FF4304"
|
||||
shadowPressedColor: "#B32D00"
|
||||
releasedColor: "#FF6C3C"
|
||||
pressedColor: "#FF4304"
|
||||
onClicked: {
|
||||
walletManager.stopMining()
|
||||
update()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
id: statusText
|
||||
text: qsTr("Status: not mining")
|
||||
textFormat: Text.RichText
|
||||
wrapMode: Text.Wrap
|
||||
}
|
||||
}
|
||||
|
||||
function updateStatusText() {
|
||||
var text = ""
|
||||
if (walletManager.isMining()) {
|
||||
if (text !== "")
|
||||
text += "<br>";
|
||||
text += qsTr("Mining at %1 H/s").arg(walletManager.miningHashRate())
|
||||
}
|
||||
if (text === "") {
|
||||
text += qsTr("Not mining") + translationManager.emptyString;
|
||||
}
|
||||
statusText.text = qsTr("Status: ") + text
|
||||
}
|
||||
|
||||
function update() {
|
||||
updateStatusText()
|
||||
startSoloMinerButton.enabled = !walletManager.isMining()
|
||||
stopSoloMinerButton.enabled = !startSoloMinerButton.enabled
|
||||
}
|
||||
|
||||
StandardDialog {
|
||||
id: errorPopup
|
||||
cancelVisible: false
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: timer
|
||||
interval: 2000; running: false; repeat: true
|
||||
onTriggered: update()
|
||||
}
|
||||
|
||||
function onPageCompleted() {
|
||||
console.log("Mining page loaded");
|
||||
|
||||
update()
|
||||
timer.running = isDaemonLocal()
|
||||
|
||||
}
|
||||
function onPageClosed() {
|
||||
timer.running = false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,16 +51,23 @@ Rectangle {
|
||||
function updatePaymentId(payment_id) {
|
||||
if (typeof appWindow.currentWallet === 'undefined' || appWindow.currentWallet == null)
|
||||
return
|
||||
|
||||
// generate a new one if not given as argument
|
||||
if (typeof payment_id === 'undefined') {
|
||||
payment_id = appWindow.currentWallet.generatePaymentId()
|
||||
appWindow.persistentSettings.payment_id = payment_id
|
||||
paymentIdLine.text = payment_id
|
||||
}
|
||||
addressLine.text = appWindow.currentWallet.address
|
||||
integratedAddressLine.text = appWindow.currentWallet.integratedAddress(payment_id)
|
||||
if (integratedAddressLine.text === "")
|
||||
integratedAddressLine.text = qsTr("Invalid payment ID")
|
||||
|
||||
if (payment_id.length > 0) {
|
||||
integratedAddressLine.text = appWindow.currentWallet.integratedAddress(payment_id)
|
||||
if (integratedAddressLine.text === "")
|
||||
integratedAddressLine.text = qsTr("Invalid payment ID")
|
||||
}
|
||||
else {
|
||||
paymentIdLine.text = ""
|
||||
integratedAddressLine.text = ""
|
||||
}
|
||||
|
||||
update()
|
||||
}
|
||||
|
||||
@@ -96,7 +103,7 @@ Rectangle {
|
||||
setTrackingLineText("-")
|
||||
return
|
||||
}
|
||||
if (appWindow.currentWallet.connected == Wallet.ConnectionStatus_Disconnected) {
|
||||
if (appWindow.currentWallet.connected() == Wallet.ConnectionStatus_Disconnected) {
|
||||
setTrackingLineText(qsTr("WARNING: no connection to daemon"))
|
||||
return
|
||||
}
|
||||
@@ -161,7 +168,9 @@ Rectangle {
|
||||
/* main layout */
|
||||
ColumnLayout {
|
||||
id: mainLayout
|
||||
anchors.margins: 40
|
||||
anchors.margins: (isMobile)? 17 : 40
|
||||
anchors.topMargin: 40
|
||||
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.top
|
||||
anchors.right: parent.right
|
||||
@@ -173,9 +182,8 @@ Rectangle {
|
||||
property int qrCodeSize: 240
|
||||
|
||||
|
||||
RowLayout {
|
||||
ColumnLayout {
|
||||
id: addressRow
|
||||
|
||||
Label {
|
||||
id: addressLabel
|
||||
fontSize: 14
|
||||
@@ -196,6 +204,7 @@ Rectangle {
|
||||
imageSource: "../images/copyToClipboard.png"
|
||||
onClicked: {
|
||||
if (addressLine.text.length > 0) {
|
||||
console.log(addressLine.text + " copied to clipboard")
|
||||
clipboard.setText(addressLine.text)
|
||||
}
|
||||
}
|
||||
@@ -203,42 +212,11 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
id: integratedAddressRow
|
||||
Label {
|
||||
id: integratedAddressLabel
|
||||
fontSize: 14
|
||||
text: qsTr("Integrated address") + translationManager.emptyString
|
||||
width: mainLayout.labelWidth
|
||||
}
|
||||
|
||||
|
||||
LineEdit {
|
||||
|
||||
id: integratedAddressLine
|
||||
fontSize: mainLayout.lineEditFontSize
|
||||
placeholderText: qsTr("ReadOnly wallet integrated address displayed here") + translationManager.emptyString
|
||||
readOnly: true
|
||||
width: mainLayout.editWidth
|
||||
Layout.fillWidth: true
|
||||
|
||||
onTextChanged: cursorPosition = 0
|
||||
|
||||
IconButton {
|
||||
imageSource: "../images/copyToClipboard.png"
|
||||
onClicked: {
|
||||
if (integratedAddressLine.text.length > 0) {
|
||||
clipboard.setText(integratedAddressLine.text)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
GridLayout {
|
||||
id: paymentIdRow
|
||||
columns:2
|
||||
Label {
|
||||
Layout.columnSpan: 2
|
||||
id: paymentIdLabel
|
||||
fontSize: 14
|
||||
text: qsTr("Payment ID") + translationManager.emptyString
|
||||
@@ -249,7 +227,7 @@ Rectangle {
|
||||
LineEdit {
|
||||
id: paymentIdLine
|
||||
fontSize: mainLayout.lineEditFontSize
|
||||
placeholderText: qsTr("16 or 64 hexadecimal characters") + translationManager.emptyString;
|
||||
placeholderText: qsTr("16 hexadecimal characters") + translationManager.emptyString;
|
||||
readOnly: false
|
||||
onTextChanged: updatePaymentId(paymentIdLine.text)
|
||||
|
||||
@@ -269,21 +247,61 @@ Rectangle {
|
||||
StandardButton {
|
||||
id: generatePaymentId
|
||||
width: 80
|
||||
fontSize: 14
|
||||
shadowReleasedColor: "#FF4304"
|
||||
shadowPressedColor: "#B32D00"
|
||||
releasedColor: "#FF6C3C"
|
||||
pressedColor: "#FF4304"
|
||||
text: qsTr("Generate")
|
||||
anchors.right: parent.right
|
||||
onClicked: {
|
||||
appWindow.persistentSettings.payment_id = appWindow.currentWallet.generatePaymentId();
|
||||
updatePaymentId()
|
||||
text: qsTr("Generate") + translationManager.emptyString;
|
||||
onClicked: updatePaymentId()
|
||||
}
|
||||
|
||||
StandardButton {
|
||||
id: clearPaymentId
|
||||
enabled: !!paymentIdLine.text
|
||||
width: 80
|
||||
shadowReleasedColor: "#FF4304"
|
||||
shadowPressedColor: "#B32D00"
|
||||
releasedColor: "#FF6C3C"
|
||||
pressedColor: "#FF4304"
|
||||
text: qsTr("Clear") + translationManager.emptyString;
|
||||
onClicked: updatePaymentId("")
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: integratedAddressRow
|
||||
Label {
|
||||
id: integratedAddressLabel
|
||||
fontSize: 14
|
||||
text: qsTr("Integrated address") + translationManager.emptyString
|
||||
width: mainLayout.labelWidth
|
||||
}
|
||||
|
||||
|
||||
LineEdit {
|
||||
|
||||
id: integratedAddressLine
|
||||
fontSize: mainLayout.lineEditFontSize
|
||||
placeholderText: qsTr("Generate payment ID for integrated address") + translationManager.emptyString
|
||||
readOnly: true
|
||||
width: mainLayout.editWidth
|
||||
Layout.fillWidth: true
|
||||
|
||||
onTextChanged: cursorPosition = 0
|
||||
|
||||
IconButton {
|
||||
imageSource: "../images/copyToClipboard.png"
|
||||
onClicked: {
|
||||
if (integratedAddressLine.text.length > 0) {
|
||||
clipboard.setText(integratedAddressLine.text)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
ColumnLayout {
|
||||
id: amountRow
|
||||
Label {
|
||||
id: amountLabel
|
||||
@@ -296,7 +314,7 @@ Rectangle {
|
||||
LineEdit {
|
||||
id: amountLine
|
||||
fontSize: mainLayout.lineEditFontSize
|
||||
placeholderText: qsTr("Amount") + translationManager.emptyString
|
||||
placeholderText: qsTr("Amount to receive") + translationManager.emptyString
|
||||
readOnly: false
|
||||
width: mainLayout.editWidth
|
||||
Layout.fillWidth: true
|
||||
@@ -358,6 +376,32 @@ Rectangle {
|
||||
standardButtons: StandardButton.Ok
|
||||
}
|
||||
|
||||
FileDialog {
|
||||
id: qrFileDialog
|
||||
title: "Please choose a name"
|
||||
folder: shortcuts.pictures
|
||||
selectExisting: false
|
||||
nameFilters: [ "Image (*.png)"]
|
||||
onAccepted: {
|
||||
if( ! walletManager.saveQrCode(makeQRCodeString(), walletManager.urlToLocalPath(fileUrl))) {
|
||||
console.log("Failed to save QrCode to file " + walletManager.urlToLocalPath(fileUrl) )
|
||||
trackingHowToUseDialog.title = qsTr("Save QrCode") + translationManager.emptyString;
|
||||
trackingHowToUseDialog.text = qsTr("Failed to save QrCode to ") + walletManager.urlToLocalPath(fileUrl) + translationManager.emptyString;
|
||||
trackingHowToUseDialog.icon = StandardIcon.Error
|
||||
trackingHowToUseDialog.open()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Menu {
|
||||
id: qrMenu
|
||||
title: "QrCode"
|
||||
MenuItem {
|
||||
text: qsTr("Save As") + translationManager.emptyString;
|
||||
onTriggered: qrFileDialog.open()
|
||||
}
|
||||
}
|
||||
|
||||
Image {
|
||||
id: qrCode
|
||||
anchors.margins: 50
|
||||
@@ -367,6 +411,15 @@ Rectangle {
|
||||
smooth: false
|
||||
fillMode: Image.PreserveAspectFit
|
||||
source: "image://qrcode/" + makeQRCodeString()
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
acceptedButtons: Qt.RightButton
|
||||
onClicked: {
|
||||
if (mouse.button == Qt.RightButton)
|
||||
qrMenu.popup()
|
||||
}
|
||||
onPressAndHold: qrFileDialog.open()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -379,12 +432,14 @@ Rectangle {
|
||||
function onPageCompleted() {
|
||||
console.log("Receive page loaded");
|
||||
|
||||
if(addressLine.text.length === 0 || addressLine.text !== appWindow.currentWallet.address) {
|
||||
updatePaymentId()
|
||||
if (appWindow.currentWallet) {
|
||||
if (addressLine.text.length === 0 || addressLine.text !== appWindow.currentWallet.address) {
|
||||
addressLine.text = appWindow.currentWallet.address
|
||||
}
|
||||
}
|
||||
|
||||
update()
|
||||
timer.running = true
|
||||
|
||||
}
|
||||
|
||||
function onPageClosed() {
|
||||
|
||||
@@ -39,234 +39,52 @@ import moneroComponents.Clipboard 1.0
|
||||
|
||||
Rectangle {
|
||||
property var daemonAddress
|
||||
property bool viewOnly: false
|
||||
id: page
|
||||
|
||||
color: "#F0EEEE"
|
||||
|
||||
Clipboard { id: clipboard }
|
||||
|
||||
function initSettings() {
|
||||
|
||||
|
||||
// Mnemonic seed settings
|
||||
memoTextInput.text = qsTr("Click button to show seed") + translationManager.emptyString
|
||||
showSeedButton.visible = true
|
||||
//runs on every page load
|
||||
|
||||
// Daemon settings
|
||||
|
||||
daemonAddress = persistentSettings.daemon_address.split(":");
|
||||
console.log("address: " + persistentSettings.daemon_address)
|
||||
// try connecting to daemon
|
||||
}
|
||||
|
||||
|
||||
PasswordDialog {
|
||||
id: settingsPasswordDialog
|
||||
|
||||
onAccepted: {
|
||||
if(appWindow.password === settingsPasswordDialog.password){
|
||||
memoTextInput.text = currentWallet.seed
|
||||
showSeedButton.visible = false
|
||||
} else {
|
||||
informationPopup.title = qsTr("Error") + translationManager.emptyString;
|
||||
informationPopup.text = qsTr("Wrong password");
|
||||
informationPopup.open()
|
||||
informationPopup.onCloseCallback = function() {
|
||||
settingsPasswordDialog.open()
|
||||
}
|
||||
}
|
||||
|
||||
settingsPasswordDialog.password = ""
|
||||
}
|
||||
onRejected: {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
ColumnLayout {
|
||||
id: mainLayout
|
||||
anchors.margins: 40
|
||||
anchors.margins: 17
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.top
|
||||
anchors.right: parent.right
|
||||
spacing: 10
|
||||
|
||||
|
||||
Label {
|
||||
id: seedLabel
|
||||
color: "#4A4949"
|
||||
fontSize: 16
|
||||
text: qsTr("Mnemonic seed: ") + translationManager.emptyString
|
||||
Layout.preferredWidth: 100
|
||||
Layout.alignment: Qt.AlignLeft
|
||||
}
|
||||
|
||||
TextArea {
|
||||
id: memoTextInput
|
||||
textMargin: 6
|
||||
font.family: "Arial"
|
||||
font.pointSize: 14
|
||||
wrapMode: TextEdit.WordWrap
|
||||
readOnly: true
|
||||
selectByMouse: true
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 100
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
|
||||
text: qsTr("Click button to show seed") + translationManager.emptyString
|
||||
|
||||
Image {
|
||||
id : clipboardButton
|
||||
anchors.right: memoTextInput.right
|
||||
anchors.bottom: memoTextInput.bottom
|
||||
source: "qrc:///images/greyTriangle.png"
|
||||
|
||||
Image {
|
||||
anchors.centerIn: parent
|
||||
source: "qrc:///images/copyToClipboard.png"
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: clipboard.setText(memoTextInput.text)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! Manage wallet
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
Text {
|
||||
id: wordsTipText
|
||||
font.family: "Arial"
|
||||
font.pointSize: 12
|
||||
color: "#4A4646"
|
||||
Label {
|
||||
id: manageWalletLabel
|
||||
Layout.fillWidth: true
|
||||
wrapMode: Text.WordWrap
|
||||
text: qsTr("This is very important to write down and keep secret. It is all you need to restore your wallet.")
|
||||
+ translationManager.emptyString
|
||||
}
|
||||
|
||||
StandardButton {
|
||||
|
||||
id: showSeedButton
|
||||
|
||||
fontSize: 14
|
||||
shadowReleasedColor: "#FF4304"
|
||||
shadowPressedColor: "#B32D00"
|
||||
releasedColor: "#FF6C3C"
|
||||
pressedColor: "#FF4304"
|
||||
text: qsTr("Show seed")
|
||||
Layout.alignment: Qt.AlignRight
|
||||
Layout.preferredWidth: 100
|
||||
onClicked: {
|
||||
settingsPasswordDialog.open();
|
||||
}
|
||||
color: "#4A4949"
|
||||
text: qsTr("Manage wallet") + translationManager.emptyString
|
||||
fontSize: 16
|
||||
Layout.topMargin: 10
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Rectangle {
|
||||
Layout.fillWidth: true
|
||||
height: 1
|
||||
color: "#DEDEDE"
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
id: daemonAddrRow
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 40
|
||||
Layout.topMargin: 40
|
||||
spacing: 10
|
||||
|
||||
Label {
|
||||
id: daemonAddrLabel
|
||||
|
||||
Layout.fillWidth: true
|
||||
color: "#4A4949"
|
||||
text: qsTr("Daemon address") + translationManager.emptyString
|
||||
fontSize: 16
|
||||
}
|
||||
|
||||
LineEdit {
|
||||
id: daemonAddr
|
||||
Layout.preferredWidth: 200
|
||||
Layout.fillWidth: true
|
||||
text: (daemonAddress !== undefined) ? daemonAddress[0] : ""
|
||||
placeholderText: qsTr("Hostname / IP")
|
||||
}
|
||||
|
||||
|
||||
LineEdit {
|
||||
id: daemonPort
|
||||
Layout.preferredWidth: 100
|
||||
Layout.fillWidth: true
|
||||
text: (daemonAddress !== undefined) ? daemonAddress[1] : "18081"
|
||||
placeholderText: qsTr("Port")
|
||||
}
|
||||
|
||||
|
||||
StandardButton {
|
||||
id: daemonAddrSave
|
||||
|
||||
Layout.fillWidth: false
|
||||
|
||||
Layout.leftMargin: 30
|
||||
Layout.minimumWidth: 100
|
||||
width: 60
|
||||
text: qsTr("Save") + translationManager.emptyString
|
||||
shadowReleasedColor: "#FF4304"
|
||||
shadowPressedColor: "#B32D00"
|
||||
releasedColor: "#FF6C3C"
|
||||
pressedColor: "#FF4304"
|
||||
visible: true
|
||||
onClicked: {
|
||||
console.log("saving daemon adress settings")
|
||||
var newDaemon = daemonAddr.text + ":" + daemonPort.text
|
||||
if(persistentSettings.daemon_address != newDaemon) {
|
||||
persistentSettings.daemon_address = newDaemon
|
||||
//reconnect wallet
|
||||
appWindow.initialize();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
RowLayout {
|
||||
Label {
|
||||
id: closeWalletLabel
|
||||
|
||||
Layout.fillWidth: true
|
||||
color: "#4A4949"
|
||||
text: qsTr("Manage wallet") + translationManager.emptyString
|
||||
fontSize: 16
|
||||
}
|
||||
}
|
||||
RowLayout {
|
||||
|
||||
Text {
|
||||
id: closeWalletTip
|
||||
font.family: "Arial"
|
||||
font.pointSize: 12
|
||||
color: "#4A4646"
|
||||
Layout.fillWidth: true
|
||||
wrapMode: Text.WordWrap
|
||||
text: qsTr("Close current wallet and open wizard")
|
||||
+ translationManager.emptyString
|
||||
}
|
||||
|
||||
|
||||
GridLayout {
|
||||
columns: (isMobile)? 2 : 4
|
||||
StandardButton {
|
||||
id: closeWalletButton
|
||||
|
||||
// Layout.leftMargin: 30
|
||||
// Layout.minimumWidth: 100
|
||||
width: 100
|
||||
text: qsTr("Close wallet") + translationManager.emptyString
|
||||
shadowReleasedColor: "#FF4304"
|
||||
shadowPressedColor: "#B32D00"
|
||||
@@ -278,21 +96,119 @@ Rectangle {
|
||||
appWindow.showWizard();
|
||||
}
|
||||
}
|
||||
|
||||
StandardButton {
|
||||
enabled: !viewOnly
|
||||
id: createViewOnlyWalletButton
|
||||
text: qsTr("Create view only wallet") + translationManager.emptyString
|
||||
shadowReleasedColor: "#FF4304"
|
||||
shadowPressedColor: "#B32D00"
|
||||
releasedColor: "#FF6C3C"
|
||||
pressedColor: "#FF4304"
|
||||
visible: true
|
||||
onClicked: {
|
||||
wizard.openCreateViewOnlyWalletPage();
|
||||
}
|
||||
}
|
||||
|
||||
StandardButton {
|
||||
id: showSeedButton
|
||||
shadowReleasedColor: "#FF4304"
|
||||
shadowPressedColor: "#B32D00"
|
||||
releasedColor: "#FF6C3C"
|
||||
pressedColor: "#FF4304"
|
||||
text: qsTr("Show seed & keys") + translationManager.emptyString
|
||||
onClicked: {
|
||||
settingsPasswordDialog.open();
|
||||
}
|
||||
}
|
||||
|
||||
/* Rescan cache - Disabled until we know it's needed
|
||||
|
||||
StandardButton {
|
||||
id: rescanWalletbutton
|
||||
shadowReleasedColor: "#FF4304"
|
||||
shadowPressedColor: "#B32D00"
|
||||
releasedColor: "#FF6C3C"
|
||||
pressedColor: "#FF4304"
|
||||
text: qsTr("Rescan wallet cache") + translationManager.emptyString
|
||||
onClicked: {
|
||||
// Show confirmation dialog
|
||||
confirmationDialog.title = qsTr("Rescan wallet cache") + translationManager.emptyString;
|
||||
confirmationDialog.text = qsTr("Are you sure you want to rebuild the wallet cache?\n"
|
||||
+ "The following information will be deleted\n"
|
||||
+ "- Recipient addresses\n"
|
||||
+ "- Tx keys\n"
|
||||
+ "- Tx descriptions\n\n"
|
||||
+ "The old wallet cache file will be renamed and can be restored later.\n"
|
||||
);
|
||||
confirmationDialog.icon = StandardIcon.Question
|
||||
confirmationDialog.cancelText = qsTr("Cancel")
|
||||
confirmationDialog.onAcceptedCallback = function() {
|
||||
walletManager.closeWallet();
|
||||
walletManager.clearWalletCache(persistentSettings.wallet_path);
|
||||
walletManager.openWalletAsync(persistentSettings.wallet_path, appWindow.password,
|
||||
persistentSettings.testnet);
|
||||
}
|
||||
|
||||
confirmationDialog.onRejectedCallback = null;
|
||||
|
||||
confirmationDialog.open()
|
||||
|
||||
}
|
||||
}
|
||||
*/
|
||||
StandardButton {
|
||||
id: rescanSpentButton
|
||||
text: qsTr("Rescan wallet balance") + translationManager.emptyString
|
||||
shadowReleasedColor: "#FF4304"
|
||||
shadowPressedColor: "#B32D00"
|
||||
releasedColor: "#FF6C3C"
|
||||
pressedColor: "#FF4304"
|
||||
onClicked: {
|
||||
if (!currentWallet.rescanSpent()) {
|
||||
console.error("Error: ", currentWallet.errorString);
|
||||
informationPopup.title = qsTr("Error") + translationManager.emptyString;
|
||||
informationPopup.text = qsTr("Error: ") + currentWallet.errorString
|
||||
informationPopup.icon = StandardIcon.Critical
|
||||
informationPopup.onCloseCallback = null
|
||||
informationPopup.open();
|
||||
} else {
|
||||
informationPopup.title = qsTr("Information") + translationManager.emptyString
|
||||
informationPopup.text = qsTr("Sucessfully rescanned spent outputs") + translationManager.emptyString
|
||||
informationPopup.icon = StandardIcon.Information
|
||||
informationPopup.onCloseCallback = null
|
||||
informationPopup.open();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! Manage daemon
|
||||
RowLayout {
|
||||
Label {
|
||||
id: manageDaemonLabel
|
||||
Layout.fillWidth: true
|
||||
color: "#4A4949"
|
||||
text: qsTr("Manage daemon") + translationManager.emptyString
|
||||
fontSize: 16
|
||||
anchors.topMargin: 30
|
||||
Layout.topMargin: 30
|
||||
}
|
||||
}
|
||||
Rectangle {
|
||||
Layout.fillWidth: true
|
||||
height: 1
|
||||
color: "#DEDEDE"
|
||||
}
|
||||
|
||||
GridLayout {
|
||||
id: daemonStatusRow
|
||||
columns: (isMobile) ? 2 : 4
|
||||
StandardButton {
|
||||
visible: true
|
||||
enabled: !appWindow.daemonRunning
|
||||
id: startDaemonButton
|
||||
width: 110
|
||||
text: qsTr("Start daemon") + translationManager.emptyString
|
||||
shadowReleasedColor: "#FF4304"
|
||||
shadowPressedColor: "#B32D00"
|
||||
@@ -307,7 +223,6 @@ Rectangle {
|
||||
visible: true
|
||||
enabled: appWindow.daemonRunning
|
||||
id: stopDaemonButton
|
||||
width: 110
|
||||
text: qsTr("Stop daemon") + translationManager.emptyString
|
||||
shadowReleasedColor: "#FF4304"
|
||||
shadowPressedColor: "#B32D00"
|
||||
@@ -320,21 +235,49 @@ Rectangle {
|
||||
|
||||
StandardButton {
|
||||
visible: true
|
||||
// enabled: appWindow.daemonRunning
|
||||
id: daemonConsolePopupButton
|
||||
width: 110
|
||||
text: qsTr("Show log") + translationManager.emptyString
|
||||
id: daemonStatusButton
|
||||
text: qsTr("Show status") + translationManager.emptyString
|
||||
shadowReleasedColor: "#FF4304"
|
||||
shadowPressedColor: "#B32D00"
|
||||
releasedColor: "#FF6C3C"
|
||||
pressedColor: "#FF4304"
|
||||
onClicked: {
|
||||
daemonManager.sendCommand("status",currentWallet.testnet);
|
||||
daemonConsolePopup.open();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
id: blockchainFolderRow
|
||||
Label {
|
||||
id: blockchainFolderLabel
|
||||
color: "#4A4949"
|
||||
text: qsTr("Blockchain location") + translationManager.emptyString
|
||||
fontSize: 16
|
||||
}
|
||||
LineEdit {
|
||||
id: blockchainFolder
|
||||
Layout.preferredWidth: 200
|
||||
Layout.fillWidth: true
|
||||
text: persistentSettings.blockchainDataDir
|
||||
placeholderText: qsTr("(optional)") + translationManager.emptyString
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
mouse.accepted = false
|
||||
if(persistentSettings.blockchainDataDir != "")
|
||||
blockchainFileDialog.folder = "file://" + persistentSettings.blockchainDataDir
|
||||
blockchainFileDialog.open()
|
||||
blockchainFolder.focus = true
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
id: daemonFlagsRow
|
||||
Label {
|
||||
@@ -352,6 +295,118 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
spacing: 10
|
||||
|
||||
Label {
|
||||
id: daemonAddrLabel
|
||||
Layout.fillWidth: true
|
||||
color: "#4A4949"
|
||||
text: qsTr("Daemon address") + translationManager.emptyString
|
||||
fontSize: 16
|
||||
}
|
||||
}
|
||||
|
||||
GridLayout {
|
||||
id: daemonAddrRow
|
||||
Layout.fillWidth: true
|
||||
columnSpacing: 10
|
||||
columns: (isMobile) ? 2 : 3
|
||||
|
||||
LineEdit {
|
||||
id: daemonAddr
|
||||
Layout.preferredWidth: 100
|
||||
Layout.fillWidth: true
|
||||
text: (daemonAddress !== undefined) ? daemonAddress[0] : ""
|
||||
placeholderText: qsTr("Hostname / IP") + translationManager.emptyString
|
||||
}
|
||||
|
||||
|
||||
LineEdit {
|
||||
id: daemonPort
|
||||
Layout.preferredWidth: 100
|
||||
Layout.fillWidth: true
|
||||
text: (daemonAddress !== undefined) ? daemonAddress[1] : "18081"
|
||||
placeholderText: qsTr("Port") + translationManager.emptyString
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
spacing: 10
|
||||
Label {
|
||||
id: daemonLoginLabel
|
||||
Layout.fillWidth: true
|
||||
color: "#4A4949"
|
||||
text: qsTr("Login (optional)") + translationManager.emptyString
|
||||
fontSize: 16
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
|
||||
LineEdit {
|
||||
id: daemonUsername
|
||||
Layout.preferredWidth: 100
|
||||
Layout.fillWidth: true
|
||||
text: persistentSettings.daemonUsername
|
||||
placeholderText: qsTr("Username") + translationManager.emptyString
|
||||
}
|
||||
|
||||
|
||||
LineEdit {
|
||||
id: daemonPassword
|
||||
Layout.preferredWidth: 100
|
||||
Layout.fillWidth: true
|
||||
text: persistentSettings.daemonPassword
|
||||
placeholderText: qsTr("Password") + translationManager.emptyString
|
||||
echoMode: TextInput.Password
|
||||
}
|
||||
|
||||
StandardButton {
|
||||
id: daemonAddrSave
|
||||
Layout.fillWidth: false
|
||||
Layout.leftMargin: 30
|
||||
text: qsTr("Connect") + translationManager.emptyString
|
||||
shadowReleasedColor: "#FF4304"
|
||||
shadowPressedColor: "#B32D00"
|
||||
releasedColor: "#FF6C3C"
|
||||
pressedColor: "#FF4304"
|
||||
onClicked: {
|
||||
console.log("saving daemon adress settings")
|
||||
var newDaemon = daemonAddr.text.trim() + ":" + daemonPort.text.trim()
|
||||
if(persistentSettings.daemon_address != newDaemon) {
|
||||
persistentSettings.daemon_address = newDaemon
|
||||
}
|
||||
|
||||
// Update daemon login
|
||||
persistentSettings.daemonUsername = daemonUsername.text;
|
||||
persistentSettings.daemonPassword = daemonPassword.text;
|
||||
currentWallet.setDaemonLogin(persistentSettings.daemonUsername, persistentSettings.daemonPassword);
|
||||
|
||||
//Reinit wallet
|
||||
currentWallet.initAsync(newDaemon);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Label {
|
||||
color: "#4A4949"
|
||||
text: qsTr("Layout settings") + translationManager.emptyString
|
||||
fontSize: 16
|
||||
anchors.topMargin: 30
|
||||
Layout.topMargin: 30
|
||||
}
|
||||
}
|
||||
Rectangle {
|
||||
Layout.fillWidth: true
|
||||
height: 1
|
||||
color: "#DEDEDE"
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
CheckBox {
|
||||
id: customDecorationsCheckBox
|
||||
@@ -363,45 +418,236 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
|
||||
Label {
|
||||
id: guiVersion
|
||||
// Log level
|
||||
|
||||
RowLayout {
|
||||
Label {
|
||||
color: "#4A4949"
|
||||
text: qsTr("Log level") + translationManager.emptyString
|
||||
fontSize: 16
|
||||
anchors.topMargin: 30
|
||||
Layout.topMargin: 30
|
||||
}
|
||||
}
|
||||
Rectangle {
|
||||
Layout.fillWidth: true
|
||||
height: 1
|
||||
color: "#DEDEDE"
|
||||
}
|
||||
ColumnLayout {
|
||||
ComboBox {
|
||||
id: logLevel
|
||||
model: [0,1,2,3,4,"custom"]
|
||||
currentIndex : appWindow.persistentSettings.logLevel;
|
||||
onCurrentIndexChanged: {
|
||||
if (currentIndex == 5) {
|
||||
console.log("log categories changed: ", logCategories.text);
|
||||
walletManager.setLogCategories(logCategories.text);
|
||||
}
|
||||
else {
|
||||
console.log("log level changed: ",currentIndex);
|
||||
walletManager.setLogLevel(currentIndex);
|
||||
}
|
||||
appWindow.persistentSettings.logLevel = currentIndex;
|
||||
}
|
||||
}
|
||||
|
||||
LineEdit {
|
||||
id: logCategories
|
||||
Layout.preferredWidth: 200
|
||||
Layout.fillWidth: true
|
||||
text: appWindow.persistentSettings.logCategories
|
||||
placeholderText: qsTr("(e.g. *:WARNING,net.p2p:DEBUG)") + translationManager.emptyString
|
||||
enabled: logLevel.currentIndex == 5
|
||||
onEditingFinished: {
|
||||
if(enabled) {
|
||||
console.log("log categories changed: ", text);
|
||||
walletManager.setLogCategories(text);
|
||||
appWindow.persistentSettings.logCategories = text;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Version
|
||||
RowLayout {
|
||||
Label {
|
||||
color: "#4A4949"
|
||||
text: qsTr("Debug info") + translationManager.emptyString
|
||||
fontSize: 16
|
||||
anchors.topMargin: 30
|
||||
Layout.topMargin: 30
|
||||
}
|
||||
}
|
||||
Rectangle {
|
||||
Layout.fillWidth: true
|
||||
height: 1
|
||||
color: "#DEDEDE"
|
||||
}
|
||||
|
||||
TextBlock {
|
||||
Layout.topMargin: 8
|
||||
color: "#4A4949"
|
||||
Layout.fillWidth: true
|
||||
text: qsTr("GUI version: ") + Version.GUI_VERSION + translationManager.emptyString
|
||||
fontSize: 16
|
||||
}
|
||||
|
||||
Label {
|
||||
TextBlock {
|
||||
id: guiMoneroVersion
|
||||
color: "#4A4949"
|
||||
Layout.fillWidth: true
|
||||
text: qsTr("Embedded Monero version: ") + Version.GUI_MONERO_VERSION + translationManager.emptyString
|
||||
fontSize: 16
|
||||
}
|
||||
|
||||
TextBlock {
|
||||
Layout.fillWidth: true
|
||||
text: (typeof currentWallet == "undefined") ? "" : qsTr("Wallet creation height: ") + currentWallet.walletCreationHeight + translationManager.emptyString
|
||||
}
|
||||
TextBlock {
|
||||
Layout.fillWidth: true
|
||||
text: (typeof currentWallet == "undefined") ? "" : qsTr("Wallet log path: ") + currentWallet.walletLogPath + translationManager.emptyString
|
||||
}
|
||||
TextBlock {
|
||||
Layout.fillWidth: true
|
||||
text: (typeof currentWallet == "undefined") ? "" : qsTr("Daemon log path: ") + currentWallet.daemonLogPath + translationManager.emptyString
|
||||
}
|
||||
}
|
||||
|
||||
// Daemon console
|
||||
StandardDialog {
|
||||
DaemonConsole {
|
||||
id: daemonConsolePopup
|
||||
height:500
|
||||
width:800
|
||||
cancelVisible: false
|
||||
title: qsTr("Daemon log")
|
||||
title: qsTr("Daemon log") + translationManager.emptyString
|
||||
onAccepted: {
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
PasswordDialog {
|
||||
id: settingsPasswordDialog
|
||||
|
||||
onAccepted: {
|
||||
if(appWindow.password === settingsPasswordDialog.password){
|
||||
if(currentWallet.seedLanguage == "") {
|
||||
console.log("No seed language set. Using English as default");
|
||||
currentWallet.setSeedLanguage("English");
|
||||
}
|
||||
|
||||
seedPopup.title = qsTr("Wallet seed & keys") + translationManager.emptyString;
|
||||
seedPopup.text = "<b>Wallet Mnemonic seed</b> <br>" + currentWallet.seed
|
||||
+ "<br><br> <b>" + qsTr("Secret view key") + ":</b> " + currentWallet.secretViewKey
|
||||
+ "<br><b>" + qsTr("Public view key") + ":</b> " + currentWallet.publicViewKey
|
||||
+ "<br><b>" + qsTr("Secret spend key") + ":</b> " + currentWallet.secretSpendKey
|
||||
+ "<br><b>" + qsTr("Public spend key") + ":</b> " + currentWallet.publicSpendKey
|
||||
seedPopup.open()
|
||||
seedPopup.width = 600
|
||||
seedPopup.height = 300
|
||||
seedPopup.onCloseCallback = function() {
|
||||
seedPopup.text = ""
|
||||
}
|
||||
|
||||
} else {
|
||||
informationPopup.title = qsTr("Error") + translationManager.emptyString;
|
||||
informationPopup.text = qsTr("Wrong password");
|
||||
informationPopup.open()
|
||||
informationPopup.onCloseCallback = function() {
|
||||
settingsPasswordDialog.open()
|
||||
}
|
||||
}
|
||||
|
||||
settingsPasswordDialog.password = ""
|
||||
}
|
||||
onRejected: {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
StandardDialog {
|
||||
id: seedPopup
|
||||
cancelVisible: false
|
||||
okVisible: true
|
||||
width:600
|
||||
height:400
|
||||
|
||||
property var onCloseCallback
|
||||
onAccepted: {
|
||||
if (onCloseCallback) {
|
||||
onCloseCallback()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Choose blockchain folder
|
||||
FileDialog {
|
||||
id: blockchainFileDialog
|
||||
title: qsTr("Please choose a folder") + translationManager.emptyString;
|
||||
selectFolder: true
|
||||
folder: "file://" + persistentSettings.blockchainDataDir
|
||||
|
||||
onAccepted: {
|
||||
var dataDir = walletManager.urlToLocalPath(blockchainFileDialog.fileUrl)
|
||||
var validator = daemonManager.validateDataDir(dataDir);
|
||||
if(!validator.valid) {
|
||||
|
||||
confirmationDialog.title = qsTr("Warning") + translationManager.emptyString;
|
||||
confirmationDialog.text = "";
|
||||
if(validator.readOnly) {
|
||||
confirmationDialog.text += qsTr("Error: Filesystem is read only") + "\n\n"
|
||||
}
|
||||
|
||||
if(validator.storageAvailable < 20) {
|
||||
confirmationDialog.text += qsTr("Warning: There's only %1 GB available on the device. Blockchain requires ~%2 GB of data.").arg(validator.storageAvailable).arg(15) + "\n\n"
|
||||
} else {
|
||||
confirmationDialog.text += qsTr("Note: There's %1 GB available on the device. Blockchain requires ~%2 GB of data.").arg(validator.storageAvailable).arg(15) + "\n\n"
|
||||
}
|
||||
|
||||
if(!validator.lmdbExists) {
|
||||
confirmationDialog.text += qsTr("Note: lmdb folder not found. A new folder will be created.") + "\n\n"
|
||||
}
|
||||
|
||||
|
||||
confirmationDialog.icon = StandardIcon.Question
|
||||
confirmationDialog.cancelText = qsTr("Cancel")
|
||||
|
||||
// Continue
|
||||
confirmationDialog.onAcceptedCallback = function() {
|
||||
persistentSettings.blockchainDataDir = dataDir
|
||||
}
|
||||
|
||||
// Cancel
|
||||
confirmationDialog.onRejectedCallback = function() {
|
||||
};
|
||||
|
||||
confirmationDialog.open()
|
||||
} else {
|
||||
persistentSettings.blockchainDataDir = dataDir
|
||||
}
|
||||
|
||||
delete validator;
|
||||
|
||||
|
||||
}
|
||||
onRejected: {
|
||||
console.log("data dir selection canceled")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// fires on every page load
|
||||
function onPageCompleted() {
|
||||
console.log("Settings page loaded");
|
||||
initSettings();
|
||||
viewOnly = currentWallet.viewOnly;
|
||||
|
||||
if(typeof daemonManager != "undefined")
|
||||
appWindow.daemonRunning = daemonManager.running(persistentSettings.testnet)
|
||||
}
|
||||
|
||||
// fires only once
|
||||
Component.onCompleted: {
|
||||
daemonManager.daemonConsoleUpdated.connect(onDaemonConsoleUpdated)
|
||||
if(typeof daemonManager != "undefined")
|
||||
daemonManager.daemonConsoleUpdated.connect(onDaemonConsoleUpdated)
|
||||
|
||||
|
||||
}
|
||||
|
||||
function onDaemonConsoleUpdated(message){
|
||||
|
||||
@@ -40,7 +40,7 @@ Rectangle {
|
||||
id: mainLayout
|
||||
|
||||
property int labelWidth: 120
|
||||
property int editWidth: 400
|
||||
// property int editWidth: 400
|
||||
property int lineEditFontSize: 12
|
||||
|
||||
color: "#F0EEEE"
|
||||
@@ -92,7 +92,7 @@ Rectangle {
|
||||
|
||||
// sign / verify
|
||||
ColumnLayout {
|
||||
anchors.margins: 10
|
||||
anchors.margins: 17
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
@@ -100,21 +100,9 @@ Rectangle {
|
||||
|
||||
spacing: 20
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: signBox
|
||||
color: "#00000000"
|
||||
border.width: 2
|
||||
border.color: "#CCCCCC"
|
||||
anchors.margins: -15
|
||||
}
|
||||
|
||||
// sign
|
||||
ColumnLayout {
|
||||
id: signBox
|
||||
anchors.margins: 40
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
|
||||
RowLayout {
|
||||
ColumnLayout {
|
||||
@@ -122,6 +110,7 @@ Rectangle {
|
||||
Label {
|
||||
text: qsTr("Sign a message or file contents with your address:") + translationManager.emptyString
|
||||
fontSize: 16
|
||||
wrapMode: Text.Wrap
|
||||
}
|
||||
Label {}
|
||||
}
|
||||
@@ -147,7 +136,7 @@ Rectangle {
|
||||
fontSize: mainLayout.lineEditFontSize
|
||||
placeholderText: qsTr("Message to sign") + translationManager.emptyString;
|
||||
readOnly: false
|
||||
Layout.fillWidth: true
|
||||
// Layout.fillWidth: true
|
||||
onTextChanged: signSignatureLine.text = ""
|
||||
|
||||
IconButton {
|
||||
@@ -164,7 +153,7 @@ Rectangle {
|
||||
id: signMessageButton
|
||||
anchors.right: parent.right
|
||||
width: 60
|
||||
text: qsTr("SIGN") + translationManager.emptyString
|
||||
text: qsTr("Sign") + translationManager.emptyString
|
||||
shadowReleasedColor: "#FF4304"
|
||||
shadowPressedColor: "#B32D00"
|
||||
releasedColor: "#FF6C3C"
|
||||
@@ -192,7 +181,7 @@ Rectangle {
|
||||
|
||||
FileDialog {
|
||||
id: signFileDialog
|
||||
title: "Please choose a file to sign"
|
||||
title: qsTr("Please choose a file to sign") + translationManager.emptyString;
|
||||
folder: "file://"
|
||||
nameFilters: [ "*"]
|
||||
|
||||
@@ -205,7 +194,7 @@ Rectangle {
|
||||
id: loadFileToSignButton
|
||||
anchors.rightMargin: 17
|
||||
width: 60
|
||||
text: qsTr("SELECT") + translationManager.emptyString
|
||||
text: qsTr("Select") + translationManager.emptyString
|
||||
shadowReleasedColor: "#FF4304"
|
||||
shadowPressedColor: "#B32D00"
|
||||
releasedColor: "#FF6C3C"
|
||||
@@ -239,7 +228,7 @@ Rectangle {
|
||||
id: signFileButton
|
||||
anchors.right: parent.right
|
||||
width: 60
|
||||
text: qsTr("SIGN") + translationManager.emptyString
|
||||
text: qsTr("Sign") + translationManager.emptyString
|
||||
shadowReleasedColor: "#FF4304"
|
||||
shadowPressedColor: "#B32D00"
|
||||
releasedColor: "#FF6C3C"
|
||||
@@ -254,21 +243,16 @@ Rectangle {
|
||||
|
||||
RowLayout {
|
||||
id: signSignatureRow
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.topMargin: 17
|
||||
|
||||
Label {
|
||||
id: signSignatureLabel
|
||||
fontSize: 14
|
||||
text: qsTr("Signature") + translationManager.emptyString
|
||||
width: mainLayout.labelWidth
|
||||
}
|
||||
|
||||
LineEdit {
|
||||
id: signSignatureLine
|
||||
anchors.left: signSignatureLabel.right
|
||||
anchors.right: parent.right
|
||||
fontSize: mainLayout.lineEditFontSize
|
||||
placeholderText: qsTr("Signature") + translationManager.emptyString;
|
||||
readOnly: true
|
||||
@@ -286,21 +270,10 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: verifyBox
|
||||
color: "#00000000"
|
||||
border.width: 2
|
||||
border.color: "#CCCCCC"
|
||||
anchors.margins: -15
|
||||
}
|
||||
|
||||
// verify
|
||||
ColumnLayout {
|
||||
id: verifyBox
|
||||
anchors.margins: 40
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: signBox.bottom
|
||||
|
||||
RowLayout {
|
||||
ColumnLayout {
|
||||
@@ -308,6 +281,8 @@ Rectangle {
|
||||
Label {
|
||||
text: qsTr("Verify a message or file signature from an address:") + translationManager.emptyString
|
||||
fontSize: 16
|
||||
// Layout.fillWidth: true
|
||||
wrapMode: Text.Wrap
|
||||
}
|
||||
Label {}
|
||||
}
|
||||
@@ -349,7 +324,7 @@ Rectangle {
|
||||
id: verifyMessageButton
|
||||
anchors.right: parent.right
|
||||
width: 60
|
||||
text: qsTr("VERIFY") + translationManager.emptyString
|
||||
text: qsTr("Verify") + translationManager.emptyString
|
||||
shadowReleasedColor: "#FF4304"
|
||||
shadowPressedColor: "#B32D00"
|
||||
releasedColor: "#FF6C3C"
|
||||
@@ -377,7 +352,7 @@ Rectangle {
|
||||
|
||||
FileDialog {
|
||||
id: verifyFileDialog
|
||||
title: "Please choose a file to verify"
|
||||
title: qsTr("Please choose a file to verify") + translationManager.emptyString;
|
||||
folder: "file://"
|
||||
nameFilters: [ "*"]
|
||||
|
||||
@@ -390,7 +365,7 @@ Rectangle {
|
||||
id: loadFileToVerifyButton
|
||||
anchors.rightMargin: 17
|
||||
width: 60
|
||||
text: qsTr("SELECT") + translationManager.emptyString
|
||||
text: qsTr("Select") + translationManager.emptyString
|
||||
shadowReleasedColor: "#FF4304"
|
||||
shadowPressedColor: "#B32D00"
|
||||
releasedColor: "#FF6C3C"
|
||||
@@ -423,7 +398,7 @@ Rectangle {
|
||||
id: verifyFileButton
|
||||
anchors.right: parent.right
|
||||
width: 60
|
||||
text: qsTr("VERIFY") + translationManager.emptyString
|
||||
text: qsTr("Verify") + translationManager.emptyString
|
||||
shadowReleasedColor: "#FF4304"
|
||||
shadowPressedColor: "#B32D00"
|
||||
releasedColor: "#FF6C3C"
|
||||
@@ -444,6 +419,8 @@ Rectangle {
|
||||
text: qsTr("<style type='text/css'>a {text-decoration: none; color: #FF6C3C; font-size: 14px;}</style>\
|
||||
Signing address <font size='2'> ( Paste in or select from </font> <a href='#'>Address book</a><font size='2'> )</font>")
|
||||
+ translationManager.emptyString
|
||||
// Layout.fillWidth: true
|
||||
wrapMode: Text.Wrap
|
||||
|
||||
onLinkActivated: appWindow.showPageRequest("AddressBook")
|
||||
}
|
||||
@@ -460,21 +437,16 @@ Rectangle {
|
||||
|
||||
RowLayout {
|
||||
id: verifySignatureRow
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.topMargin: 17
|
||||
|
||||
Label {
|
||||
id: verifySignatureLabel
|
||||
fontSize: 14
|
||||
text: qsTr("Signature") + translationManager.emptyString
|
||||
width: mainLayout.labelWidth
|
||||
}
|
||||
|
||||
LineEdit {
|
||||
id: verifySignatureLine
|
||||
anchors.left: verifySignatureLabel.right
|
||||
anchors.right: parent.right
|
||||
fontSize: mainLayout.lineEditFontSize
|
||||
placeholderText: qsTr("Signature") + translationManager.emptyString;
|
||||
Layout.fillWidth: true
|
||||
|
||||
@@ -41,7 +41,8 @@ Rectangle {
|
||||
signal sweepUnmixableClicked()
|
||||
|
||||
color: "#F0EEEE"
|
||||
property string startLinkText: "<style type='text/css'>a {text-decoration: none; color: #FF6C3C; font-size: 14px;}</style><font size='2'> (</font><a href='#'>Start daemon</a><font size='2'>)</font>"
|
||||
property string startLinkText: qsTr("<style type='text/css'>a {text-decoration: none; color: #FF6C3C; font-size: 14px;}</style><font size='2'> (</font><a href='#'>Start daemon</a><font size='2'>)</font>") + translationManager.emptyString
|
||||
property bool showAdvanced: false
|
||||
|
||||
function scaleValueToMixinCount(scaleValue) {
|
||||
var scaleToMixinCount = [4,5,6,7,8,9,10,11,12,13,14,15,20,25];
|
||||
@@ -69,6 +70,30 @@ Rectangle {
|
||||
oaPopup.open()
|
||||
}
|
||||
|
||||
function updateMixin() {
|
||||
var fillLevel = privacyLevelItem.fillLevel
|
||||
var mixin = scaleValueToMixinCount(fillLevel)
|
||||
print ("PrivacyLevel changed:" + fillLevel)
|
||||
print ("mixin count: " + mixin)
|
||||
privacyLabel.text = qsTr("Privacy level (ringsize %1)").arg(mixin+1) + translationManager.emptyString
|
||||
}
|
||||
|
||||
function updateFromQrCode(address, payment_id, amount, tx_description, recipient_name) {
|
||||
console.log("updateFromQrCode")
|
||||
addressLine.text = address
|
||||
paymentIdLine.text = payment_id
|
||||
amountLine.text = amount
|
||||
descriptionLine.text = recipient_name + " " + tx_description
|
||||
cameraUi.qrcode_decoded.disconnect(updateFromQrCode)
|
||||
}
|
||||
|
||||
function clearFields() {
|
||||
addressLine.text = ""
|
||||
paymentIdLine.text = ""
|
||||
amountLine.text = ""
|
||||
descriptionLine.text = ""
|
||||
}
|
||||
|
||||
// Information dialog
|
||||
StandardDialog {
|
||||
// dynamically change onclose handler
|
||||
@@ -84,331 +109,317 @@ Rectangle {
|
||||
|
||||
Item {
|
||||
id: pageRoot
|
||||
anchors.fill: parent
|
||||
Label {
|
||||
id: amountLabel
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.top
|
||||
anchors.leftMargin: 17
|
||||
anchors.rightMargin: 17
|
||||
anchors.topMargin: 17
|
||||
text: qsTr("Amount") + translationManager.emptyString
|
||||
fontSize: 14
|
||||
}
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.topMargin: 20
|
||||
height: 400
|
||||
|
||||
Label {
|
||||
id: transactionPriority
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 17
|
||||
fontSize: 14
|
||||
x: (parent.width - 17) / 2 + 17
|
||||
text: qsTr("Transaction priority") + translationManager.emptyString
|
||||
}
|
||||
Label {
|
||||
id: amountLabel
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.top
|
||||
anchors.leftMargin: 17
|
||||
anchors.rightMargin: 17
|
||||
anchors.topMargin: 17
|
||||
text: qsTr("Amount") + translationManager.emptyString
|
||||
fontSize: 14
|
||||
}
|
||||
|
||||
Row {
|
||||
id: amountRow
|
||||
anchors.top: amountLabel.bottom
|
||||
anchors.topMargin: 5
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 7
|
||||
width: (parent.width - 17) / 2 + 10
|
||||
Item {
|
||||
width: 37
|
||||
height: 37
|
||||
|
||||
Image {
|
||||
anchors.centerIn: parent
|
||||
source: "../images/moneroIcon.png"
|
||||
}
|
||||
}
|
||||
// Amount input
|
||||
LineEdit {
|
||||
id: amountLine
|
||||
placeholderText: qsTr("") + translationManager.emptyString
|
||||
width: parent.width - 37 - 17 - 60
|
||||
validator: DoubleValidator {
|
||||
bottom: 0.0
|
||||
top: 18446744.073709551615
|
||||
decimals: 12
|
||||
notation: DoubleValidator.StandardNotation
|
||||
locale: "C"
|
||||
}
|
||||
}
|
||||
|
||||
StandardButton {
|
||||
id: amountAllButton
|
||||
//anchors.left: amountLine.right
|
||||
//anchors.top: amountLine.top
|
||||
//anchors.bottom: amountLine.bottom
|
||||
width: 60
|
||||
text: qsTr("or ALL") + translationManager.emptyString
|
||||
shadowReleasedColor: "#FF4304"
|
||||
shadowPressedColor: "#B32D00"
|
||||
releasedColor: "#FF6C3C"
|
||||
pressedColor: "#FF4304"
|
||||
enabled : true
|
||||
onClicked: amountLine.text = "(all)"
|
||||
}
|
||||
}
|
||||
|
||||
ListModel {
|
||||
id: priorityModel
|
||||
// ListElement: cannot use script for property value, so
|
||||
// code like this wont work:
|
||||
// ListElement { column1: qsTr("LOW") + translationManager.emptyString ; column2: ""; priority: PendingTransaction.Priority_Low }
|
||||
|
||||
ListElement { column1: qsTr("LOW (x1 fee)") ; column2: ""; priority: PendingTransaction.Priority_Low }
|
||||
ListElement { column1: qsTr("MEDIUM (x20 fee)") ; column2: ""; priority: PendingTransaction.Priority_Medium }
|
||||
ListElement { column1: qsTr("HIGH (x166 fee)") ; column2: ""; priority: PendingTransaction.Priority_High }
|
||||
}
|
||||
|
||||
StandardDropdown {
|
||||
id: priorityDropdown
|
||||
anchors.top: transactionPriority.bottom
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 17
|
||||
anchors.topMargin: 5
|
||||
anchors.left: transactionPriority.left
|
||||
shadowReleasedColor: "#FF4304"
|
||||
shadowPressedColor: "#B32D00"
|
||||
releasedColor: "#FF6C3C"
|
||||
pressedColor: "#FF4304"
|
||||
dataModel: priorityModel
|
||||
z: 1
|
||||
}
|
||||
Label {
|
||||
id: transactionPriority
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 17
|
||||
fontSize: 14
|
||||
x: (parent.width - 17) / 2 + 17
|
||||
text: qsTr("Transaction priority") + translationManager.emptyString
|
||||
}
|
||||
|
||||
|
||||
Row {
|
||||
id: amountRow
|
||||
anchors.top: amountLabel.bottom
|
||||
anchors.topMargin: 5
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 7
|
||||
width: (parent.width - 17) / 2 + 10
|
||||
Item {
|
||||
width: 37
|
||||
height: 37
|
||||
|
||||
Label {
|
||||
id: privacyLabel
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: amountRow.bottom
|
||||
anchors.leftMargin: 17
|
||||
anchors.rightMargin: 17
|
||||
anchors.topMargin: 30
|
||||
fontSize: 14
|
||||
text: qsTr("Privacy level") + translationManager.emptyString
|
||||
}
|
||||
Image {
|
||||
anchors.centerIn: parent
|
||||
source: "../images/moneroIcon.png"
|
||||
}
|
||||
}
|
||||
// Amount input
|
||||
LineEdit {
|
||||
id: amountLine
|
||||
placeholderText: qsTr("") + translationManager.emptyString
|
||||
width: parent.width - 37 - 17 - 60
|
||||
validator: DoubleValidator {
|
||||
bottom: 0.0
|
||||
top: 18446744.073709551615
|
||||
decimals: 12
|
||||
notation: DoubleValidator.StandardNotation
|
||||
locale: "C"
|
||||
}
|
||||
}
|
||||
|
||||
PrivacyLevel {
|
||||
id: privacyLevelItem
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: privacyLabel.bottom
|
||||
anchors.leftMargin: 17
|
||||
anchors.rightMargin: 17
|
||||
anchors.topMargin: 5
|
||||
onFillLevelChanged: {
|
||||
print ("PrivacyLevel changed:" + fillLevel)
|
||||
print ("mixin count:" + scaleValueToMixinCount(fillLevel))
|
||||
}
|
||||
}
|
||||
StandardButton {
|
||||
id: amountAllButton
|
||||
//anchors.left: amountLine.right
|
||||
//anchors.top: amountLine.top
|
||||
//anchors.bottom: amountLine.bottom
|
||||
width: 60
|
||||
text: qsTr("All") + translationManager.emptyString
|
||||
shadowReleasedColor: "#FF4304"
|
||||
shadowPressedColor: "#B32D00"
|
||||
releasedColor: "#FF6C3C"
|
||||
pressedColor: "#FF4304"
|
||||
enabled : true
|
||||
onClicked: amountLine.text = "(all)"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Label {
|
||||
id: costLabel
|
||||
anchors.right: parent.right
|
||||
anchors.top: amountRow.bottom
|
||||
anchors.leftMargin: 17
|
||||
anchors.rightMargin: 17
|
||||
anchors.topMargin: 30
|
||||
fontSize: 14
|
||||
text: qsTr("Transaction cost")
|
||||
}
|
||||
// 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.
|
||||
|
||||
// Priorities before v5
|
||||
ListModel {
|
||||
id: priorityModel
|
||||
|
||||
Label {
|
||||
id: addressLabel
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: privacyLevelItem.bottom
|
||||
anchors.leftMargin: 17
|
||||
anchors.rightMargin: 17
|
||||
anchors.topMargin: 30
|
||||
fontSize: 14
|
||||
textFormat: Text.RichText
|
||||
text: qsTr("<style type='text/css'>a {text-decoration: none; color: #FF6C3C; font-size: 14px;}</style>\
|
||||
Address <font size='2'> ( Paste in or select from </font> <a href='#'>Address book</a><font size='2'> )</font>")
|
||||
+ translationManager.emptyString
|
||||
ListElement { column1: qsTr("Low (x1 fee)") ; column2: ""; priority: PendingTransaction.Priority_Low }
|
||||
ListElement { column1: qsTr("Medium (x20 fee)") ; column2: ""; priority: PendingTransaction.Priority_Medium }
|
||||
ListElement { column1: qsTr("High (x166 fee)") ; column2: ""; priority: PendingTransaction.Priority_High }
|
||||
}
|
||||
|
||||
onLinkActivated: appWindow.showPageRequest("AddressBook")
|
||||
}
|
||||
// recipient address input
|
||||
RowLayout {
|
||||
id: addressLineRow
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: addressLabel.bottom
|
||||
// Priorites after v5
|
||||
ListModel {
|
||||
id: priorityModelV5
|
||||
|
||||
LineEdit {
|
||||
id: addressLine
|
||||
anchors.left: parent.left
|
||||
anchors.right: resolveButton.left
|
||||
anchors.leftMargin: 17
|
||||
anchors.topMargin: 5
|
||||
placeholderText: "4..."
|
||||
// validator: RegExpValidator { regExp: /[0-9A-Fa-f]{95}/g }
|
||||
}
|
||||
ListElement { column1: qsTr("Slow (x0.25 fee)") ; column2: ""; priority: 1}
|
||||
ListElement { column1: qsTr("Default (x1 fee)") ; column2: ""; priority: 2 }
|
||||
ListElement { column1: qsTr("Fast (x5 fee)") ; column2: ""; priority: 3 }
|
||||
ListElement { column1: qsTr("Fastest (x41.5 fee)") ; column2: ""; priority: 4 }
|
||||
|
||||
StandardButton {
|
||||
id: resolveButton
|
||||
anchors.right: parent.right
|
||||
anchors.leftMargin: 17
|
||||
anchors.topMargin: 17
|
||||
anchors.rightMargin: 17
|
||||
width: 60
|
||||
text: qsTr("RESOLVE") + translationManager.emptyString
|
||||
shadowReleasedColor: "#FF4304"
|
||||
shadowPressedColor: "#B32D00"
|
||||
releasedColor: "#FF6C3C"
|
||||
pressedColor: "#FF4304"
|
||||
enabled : isValidOpenAliasAddress(addressLine.text)
|
||||
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.testnet)
|
||||
if (parts[0] === "true") {
|
||||
if (address_ok) {
|
||||
addressLine.text = parts[1]
|
||||
addressLine.cursorPosition = 0
|
||||
}
|
||||
else
|
||||
oa_message(qsTr("No valid address found at this OpenAlias address"))
|
||||
} else if (parts[0] === "false") {
|
||||
if (address_ok) {
|
||||
addressLine.text = parts[1]
|
||||
addressLine.cursorPosition = 0
|
||||
oa_message(qsTr("Address found, but the DNSSEC signatures could not be verified, so this address may be spoofed"))
|
||||
}
|
||||
|
||||
StandardDropdown {
|
||||
id: priorityDropdown
|
||||
anchors.top: transactionPriority.bottom
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 17
|
||||
anchors.topMargin: 5
|
||||
anchors.left: transactionPriority.left
|
||||
shadowReleasedColor: "#FF4304"
|
||||
shadowPressedColor: "#B32D00"
|
||||
releasedColor: "#FF6C3C"
|
||||
pressedColor: "#FF4304"
|
||||
z: 1
|
||||
}
|
||||
|
||||
Label {
|
||||
id: addressLabel
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: amountRow.bottom
|
||||
anchors.leftMargin: 17
|
||||
anchors.rightMargin: 17
|
||||
anchors.topMargin: 30
|
||||
fontSize: 14
|
||||
textFormat: Text.RichText
|
||||
text: qsTr("<style type='text/css'>a {text-decoration: none; color: #FF6C3C; font-size: 14px;}</style>\
|
||||
Address <font size='2'> ( Paste in or select from </font> <a href='#'>Address book</a><font size='2'> )</font>")
|
||||
+ translationManager.emptyString
|
||||
|
||||
onLinkActivated: appWindow.showPageRequest("AddressBook")
|
||||
}
|
||||
// recipient address input
|
||||
RowLayout {
|
||||
id: addressLineRow
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: addressLabel.bottom
|
||||
|
||||
StandardButton {
|
||||
id: qrfinderButton
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 17
|
||||
anchors.topMargin: 5
|
||||
text: qsTr("QR Code") + translationManager.emptyString
|
||||
shadowReleasedColor: "#FF4304"
|
||||
shadowPressedColor: "#B32D00"
|
||||
releasedColor: "#FF6C3C"
|
||||
pressedColor: "#FF4304"
|
||||
visible : appWindow.qrScannerEnabled
|
||||
enabled : visible
|
||||
width: visible ? 60 : 0
|
||||
onClicked: {
|
||||
cameraUi.state = "Capture"
|
||||
cameraUi.qrcode_decoded.connect(updateFromQrCode)
|
||||
}
|
||||
}
|
||||
LineEdit {
|
||||
id: addressLine
|
||||
anchors.left: qrfinderButton.right
|
||||
anchors.right: resolveButton.left
|
||||
//anchors.leftMargin: 17
|
||||
anchors.topMargin: 5
|
||||
placeholderText: "4..."
|
||||
// validator: RegExpValidator { regExp: /[0-9A-Fa-f]{95}/g }
|
||||
}
|
||||
|
||||
StandardButton {
|
||||
id: resolveButton
|
||||
anchors.right: parent.right
|
||||
anchors.leftMargin: 17
|
||||
anchors.topMargin: 17
|
||||
anchors.rightMargin: 17
|
||||
width: 60
|
||||
text: qsTr("Resolve") + translationManager.emptyString
|
||||
shadowReleasedColor: "#FF4304"
|
||||
shadowPressedColor: "#B32D00"
|
||||
releasedColor: "#FF6C3C"
|
||||
pressedColor: "#FF4304"
|
||||
enabled : isValidOpenAliasAddress(addressLine.text)
|
||||
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.testnet)
|
||||
if (parts[0] === "true") {
|
||||
if (address_ok) {
|
||||
addressLine.text = parts[1]
|
||||
addressLine.cursorPosition = 0
|
||||
}
|
||||
else
|
||||
oa_message(qsTr("No valid address found at this OpenAlias address"))
|
||||
} else if (parts[0] === "false") {
|
||||
if (address_ok) {
|
||||
addressLine.text = parts[1]
|
||||
addressLine.cursorPosition = 0
|
||||
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("No valid address found at this OpenAlias address, but the DNSSEC signatures could not be verified, so this may be spoofed"))
|
||||
oa_message(qsTr("Internal error"))
|
||||
}
|
||||
} else {
|
||||
oa_message(qsTr("Internal error"))
|
||||
}
|
||||
} else {
|
||||
oa_message(qsTr("Internal error"))
|
||||
oa_message(qsTr("No address found"))
|
||||
}
|
||||
} else {
|
||||
oa_message(qsTr("No address found"))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Label {
|
||||
id: paymentIdLabel
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: addressLineRow.bottom
|
||||
anchors.leftMargin: 17
|
||||
anchors.rightMargin: 17
|
||||
anchors.topMargin: 17
|
||||
fontSize: 14
|
||||
text: qsTr("Payment ID <font size='2'>( Optional )</font>") + translationManager.emptyString
|
||||
}
|
||||
Label {
|
||||
id: paymentIdLabel
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: addressLineRow.bottom
|
||||
anchors.leftMargin: 17
|
||||
anchors.rightMargin: 17
|
||||
anchors.topMargin: 17
|
||||
fontSize: 14
|
||||
text: qsTr("Payment ID <font size='2'>( Optional )</font>") + translationManager.emptyString
|
||||
}
|
||||
|
||||
// payment id input
|
||||
LineEdit {
|
||||
id: paymentIdLine
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: paymentIdLabel.bottom
|
||||
anchors.leftMargin: 17
|
||||
anchors.rightMargin: 17
|
||||
anchors.topMargin: 5
|
||||
placeholderText: qsTr("16 or 64 hexadecimal characters") + translationManager.emptyString
|
||||
// validator: DoubleValidator { top: 0.0 }
|
||||
}
|
||||
// payment id input
|
||||
LineEdit {
|
||||
id: paymentIdLine
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: paymentIdLabel.bottom
|
||||
anchors.leftMargin: 17
|
||||
anchors.rightMargin: 17
|
||||
anchors.topMargin: 5
|
||||
placeholderText: qsTr("16 or 64 hexadecimal characters") + translationManager.emptyString
|
||||
// validator: DoubleValidator { top: 0.0 }
|
||||
}
|
||||
|
||||
Label {
|
||||
id: descriptionLabel
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: paymentIdLine.bottom
|
||||
anchors.leftMargin: 17
|
||||
anchors.rightMargin: 17
|
||||
anchors.topMargin: 17
|
||||
fontSize: 14
|
||||
text: qsTr("Description <font size='2'>( Optional - saved to local wallet history )</font>")
|
||||
+ translationManager.emptyString
|
||||
}
|
||||
Label {
|
||||
id: descriptionLabel
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: paymentIdLine.bottom
|
||||
anchors.leftMargin: 17
|
||||
anchors.rightMargin: 17
|
||||
anchors.topMargin: 17
|
||||
fontSize: 14
|
||||
text: qsTr("Description <font size='2'>( Optional )</font>")
|
||||
+ translationManager.emptyString
|
||||
}
|
||||
|
||||
LineEdit {
|
||||
id: descriptionLine
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: descriptionLabel.bottom
|
||||
anchors.leftMargin: 17
|
||||
anchors.rightMargin: 17
|
||||
anchors.topMargin: 5
|
||||
}
|
||||
LineEdit {
|
||||
id: descriptionLine
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: descriptionLabel.bottom
|
||||
anchors.leftMargin: 17
|
||||
anchors.rightMargin: 17
|
||||
anchors.topMargin: 5
|
||||
placeholderText: qsTr("Saved to local wallet history") + translationManager.emptyString
|
||||
}
|
||||
|
||||
function checkInformation(amount, address, payment_id, testnet) {
|
||||
address = address.trim()
|
||||
payment_id = payment_id.trim()
|
||||
function checkInformation(amount, address, payment_id, testnet) {
|
||||
address = address.trim()
|
||||
payment_id = payment_id.trim()
|
||||
|
||||
var amount_ok = amount.length > 0
|
||||
var address_ok = walletManager.addressValid(address, testnet)
|
||||
var payment_id_ok = payment_id.length == 0 || walletManager.paymentIdValid(payment_id)
|
||||
var ipid = walletManager.paymentIdFromAddress(address, testnet)
|
||||
if (ipid.length > 0 && payment_id.length > 0)
|
||||
payment_id_ok = false
|
||||
var amount_ok = amount.length > 0
|
||||
var address_ok = walletManager.addressValid(address, testnet)
|
||||
var payment_id_ok = payment_id.length == 0 || walletManager.paymentIdValid(payment_id)
|
||||
var ipid = walletManager.paymentIdFromAddress(address, testnet)
|
||||
if (ipid.length > 0 && payment_id.length > 0)
|
||||
payment_id_ok = false
|
||||
|
||||
addressLine.error = !address_ok
|
||||
amountLine.error = !amount_ok
|
||||
paymentIdLine.error = !payment_id_ok
|
||||
addressLine.error = !address_ok
|
||||
amountLine.error = !amount_ok
|
||||
paymentIdLine.error = !payment_id_ok
|
||||
|
||||
return amount_ok && address_ok && payment_id_ok
|
||||
}
|
||||
return amount_ok && address_ok && payment_id_ok
|
||||
}
|
||||
|
||||
StandardButton {
|
||||
id: sendButton
|
||||
anchors.left: parent.left
|
||||
anchors.top: descriptionLine.bottom
|
||||
anchors.leftMargin: 17
|
||||
anchors.topMargin: 17
|
||||
width: 60
|
||||
text: qsTr("SEND") + translationManager.emptyString
|
||||
shadowReleasedColor: "#FF4304"
|
||||
shadowPressedColor: "#B32D00"
|
||||
releasedColor: "#FF6C3C"
|
||||
pressedColor: "#FF4304"
|
||||
enabled : pageRoot.checkInformation(amountLine.text, addressLine.text, paymentIdLine.text, appWindow.persistentSettings.testnet)
|
||||
onClicked: {
|
||||
console.log("Transfer: paymentClicked")
|
||||
var priority = priorityModel.get(priorityDropdown.currentIndex).priority
|
||||
console.log("priority: " + priority)
|
||||
console.log("amount: " + amountLine.text)
|
||||
addressLine.text = addressLine.text.trim()
|
||||
paymentIdLine.text = paymentIdLine.text.trim()
|
||||
root.paymentClicked(addressLine.text, paymentIdLine.text, amountLine.text, scaleValueToMixinCount(privacyLevelItem.fillLevel),
|
||||
priority, descriptionLine.text)
|
||||
|
||||
}
|
||||
}
|
||||
RowLayout {
|
||||
anchors.left: parent.left
|
||||
anchors.top: descriptionLine.bottom
|
||||
anchors.leftMargin: 17
|
||||
anchors.topMargin: 17
|
||||
|
||||
StandardButton {
|
||||
id: sweepUnmixableButton
|
||||
anchors.right: parent.right
|
||||
anchors.top: descriptionLine.bottom
|
||||
anchors.rightMargin: 17
|
||||
anchors.topMargin: 17
|
||||
width: 60*2
|
||||
text: qsTr("SWEEP UNMIXABLE") + translationManager.emptyString
|
||||
shadowReleasedColor: "#FF4304"
|
||||
shadowPressedColor: "#B32D00"
|
||||
releasedColor: "#FF6C3C"
|
||||
pressedColor: "#FF4304"
|
||||
enabled : true
|
||||
onClicked: {
|
||||
console.log("Transfer: sweepUnmixableClicked")
|
||||
root.sweepUnmixableClicked()
|
||||
StandardButton {
|
||||
id: sendButton
|
||||
text: qsTr("Send") + translationManager.emptyString
|
||||
shadowReleasedColor: "#FF4304"
|
||||
shadowPressedColor: "#B32D00"
|
||||
releasedColor: "#FF6C3C"
|
||||
pressedColor: "#FF4304"
|
||||
enabled : !appWindow.viewOnly && pageRoot.checkInformation(amountLine.text, addressLine.text, paymentIdLine.text, appWindow.persistentSettings.testnet)
|
||||
onClicked: {
|
||||
console.log("Transfer: paymentClicked")
|
||||
var priority = priorityModel.get(priorityDropdown.currentIndex).priority
|
||||
console.log("priority: " + priority)
|
||||
console.log("amount: " + amountLine.text)
|
||||
addressLine.text = addressLine.text.trim()
|
||||
paymentIdLine.text = paymentIdLine.text.trim()
|
||||
root.paymentClicked(addressLine.text, paymentIdLine.text, amountLine.text, scaleValueToMixinCount(privacyLevelItem.fillLevel),
|
||||
priority, descriptionLine.text)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // pageRoot
|
||||
|
||||
Rectangle {
|
||||
id:desaturate
|
||||
@@ -417,7 +428,231 @@ Rectangle {
|
||||
opacity: 0.1
|
||||
visible: (pageRoot.enabled)? 0 : 1;
|
||||
}
|
||||
} // Rectangle
|
||||
|
||||
ColumnLayout {
|
||||
anchors.top: pageRoot.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.margins: 17
|
||||
spacing:10
|
||||
enabled: !viewOnly || pageRoot.enabled
|
||||
|
||||
RowLayout {
|
||||
CheckBox {
|
||||
id: showAdvancedCheckbox
|
||||
checked: persistentSettings.transferShowAdvanced
|
||||
onClicked: {
|
||||
persistentSettings.transferShowAdvanced = !persistentSettings.transferShowAdvanced
|
||||
}
|
||||
text: qsTr("Show advanced options") + translationManager.emptyString
|
||||
checkedIcon: "../images/checkedVioletIcon.png"
|
||||
uncheckedIcon: "../images/uncheckedIcon.png"
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
visible: persistentSettings.transferShowAdvanced
|
||||
Layout.fillWidth: true
|
||||
height: 1
|
||||
color: "#DEDEDE"
|
||||
Layout.bottomMargin: 30
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
visible: persistentSettings.transferShowAdvanced
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
Label {
|
||||
id: privacyLabel
|
||||
fontSize: 14
|
||||
text: ""
|
||||
}
|
||||
|
||||
Label {
|
||||
id: costLabel
|
||||
fontSize: 14
|
||||
text: qsTr("Transaction cost") + translationManager.emptyString
|
||||
anchors.right: parent.right
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
PrivacyLevel {
|
||||
visible: persistentSettings.transferShowAdvanced
|
||||
id: privacyLevelItem
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
onFillLevelChanged: updateMixin()
|
||||
}
|
||||
|
||||
|
||||
GridLayout {
|
||||
visible: persistentSettings.transferShowAdvanced
|
||||
Layout.topMargin: 50
|
||||
|
||||
|
||||
columns: (isMobile) ? 2 : 6
|
||||
|
||||
StandardButton {
|
||||
id: sweepUnmixableButton
|
||||
text: qsTr("Sweep Unmixable") + translationManager.emptyString
|
||||
shadowReleasedColor: "#FF4304"
|
||||
shadowPressedColor: "#B32D00"
|
||||
releasedColor: "#FF6C3C"
|
||||
pressedColor: "#FF4304"
|
||||
enabled : pageRoot.enabled
|
||||
onClicked: {
|
||||
console.log("Transfer: sweepUnmixableClicked")
|
||||
root.sweepUnmixableClicked()
|
||||
}
|
||||
}
|
||||
|
||||
StandardButton {
|
||||
id: saveTxButton
|
||||
text: qsTr("Create tx file") + translationManager.emptyString
|
||||
shadowReleasedColor: "#FF4304"
|
||||
shadowPressedColor: "#B32D00"
|
||||
releasedColor: "#FF6C3C"
|
||||
pressedColor: "#FF4304"
|
||||
visible: appWindow.viewOnly
|
||||
enabled: pageRoot.checkInformation(amountLine.text, addressLine.text, paymentIdLine.text, appWindow.persistentSettings.testnet)
|
||||
onClicked: {
|
||||
console.log("Transfer: saveTx Clicked")
|
||||
var priority = priorityModel.get(priorityDropdown.currentIndex).priority
|
||||
console.log("priority: " + priority)
|
||||
console.log("amount: " + amountLine.text)
|
||||
addressLine.text = addressLine.text.trim()
|
||||
paymentIdLine.text = paymentIdLine.text.trim()
|
||||
root.paymentClicked(addressLine.text, paymentIdLine.text, amountLine.text, scaleValueToMixinCount(privacyLevelItem.fillLevel),
|
||||
priority, descriptionLine.text)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
StandardButton {
|
||||
id: signTxButton
|
||||
text: qsTr("Sign tx file") + translationManager.emptyString
|
||||
shadowReleasedColor: "#FF4304"
|
||||
shadowPressedColor: "#B32D00"
|
||||
releasedColor: "#FF6C3C"
|
||||
pressedColor: "#FF4304"
|
||||
visible: !appWindow.viewOnly
|
||||
onClicked: {
|
||||
console.log("Transfer: sign tx clicked")
|
||||
signTxDialog.open();
|
||||
}
|
||||
}
|
||||
|
||||
StandardButton {
|
||||
id: submitTxButton
|
||||
text: qsTr("Submit tx file") + translationManager.emptyString
|
||||
shadowReleasedColor: "#FF4304"
|
||||
shadowPressedColor: "#B32D00"
|
||||
releasedColor: "#FF6C3C"
|
||||
pressedColor: "#FF4304"
|
||||
visible: appWindow.viewOnly
|
||||
enabled: pageRoot.enabled
|
||||
onClicked: {
|
||||
console.log("Transfer: submit tx clicked")
|
||||
submitTxDialog.open();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
//SignTxDialog
|
||||
FileDialog {
|
||||
id: signTxDialog
|
||||
title: qsTr("Please choose a file") + translationManager.emptyString
|
||||
folder: "file://" +moneroAccountsDir
|
||||
nameFilters: [ "Unsigned transfers (*)"]
|
||||
|
||||
onAccepted: {
|
||||
var path = walletManager.urlToLocalPath(fileUrl);
|
||||
// Load the unsigned tx from file
|
||||
var transaction = currentWallet.loadTxFile(path);
|
||||
|
||||
if (transaction.status !== PendingTransaction.Status_Ok) {
|
||||
console.error("Can't load unsigned transaction: ", transaction.errorString);
|
||||
informationPopup.title = qsTr("Error") + translationManager.emptyString;
|
||||
informationPopup.text = qsTr("Can't load unsigned transaction: ") + transaction.errorString
|
||||
informationPopup.icon = StandardIcon.Critical
|
||||
informationPopup.onCloseCallback = null
|
||||
informationPopup.open();
|
||||
// deleting transaction object, we don't want memleaks
|
||||
transaction.destroy();
|
||||
} else {
|
||||
confirmationDialog.text = qsTr("\nNumber of transactions: ") + transaction.txCount
|
||||
for (var i = 0; i < transaction.txCount; ++i) {
|
||||
confirmationDialog.text += qsTr("\nTransaction #%1").arg(i+1)
|
||||
+qsTr("\nRecipient: ") + transaction.recipientAddress[i]
|
||||
+ (transaction.paymentId[i] == "" ? "" : qsTr("\n\payment ID: ") + transaction.paymentId[i])
|
||||
+ qsTr("\nAmount: ") + walletManager.displayAmount(transaction.amount(i))
|
||||
+ qsTr("\nFee: ") + walletManager.displayAmount(transaction.fee(i))
|
||||
+ qsTr("\nRingsize: ") + transaction.mixin(i+1)
|
||||
|
||||
// TODO: add descriptions to unsigned_tx_set?
|
||||
// + (transactionDescription === "" ? "" : (qsTr("\n\nDescription: ") + transactionDescription))
|
||||
+ translationManager.emptyString
|
||||
if (i > 0) {
|
||||
confirmationDialog.text += "\n\n"
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
console.log(transaction.confirmationMessage);
|
||||
|
||||
// Show confirmation dialog
|
||||
confirmationDialog.title = qsTr("Confirmation") + translationManager.emptyString
|
||||
confirmationDialog.icon = StandardIcon.Question
|
||||
confirmationDialog.onAcceptedCallback = function() {
|
||||
transaction.sign(path+"_signed");
|
||||
transaction.destroy();
|
||||
};
|
||||
confirmationDialog.onRejectedCallback = transaction.destroy;
|
||||
|
||||
confirmationDialog.open()
|
||||
}
|
||||
|
||||
}
|
||||
onRejected: {
|
||||
// File dialog closed
|
||||
console.log("Canceled")
|
||||
}
|
||||
}
|
||||
|
||||
//SignTxDialog
|
||||
FileDialog {
|
||||
id: submitTxDialog
|
||||
title: qsTr("Please choose a file") + translationManager.emptyString
|
||||
folder: "file://" +moneroAccountsDir
|
||||
nameFilters: [ "signed transfers (*)"]
|
||||
|
||||
onAccepted: {
|
||||
if(!currentWallet.submitTxFile(walletManager.urlToLocalPath(fileUrl))){
|
||||
informationPopup.title = qsTr("Error") + translationManager.emptyString;
|
||||
informationPopup.text = qsTr("Can't submit transaction: ") + currentWallet.errorString
|
||||
informationPopup.icon = StandardIcon.Critical
|
||||
informationPopup.onCloseCallback = null
|
||||
informationPopup.open();
|
||||
} else {
|
||||
informationPopup.title = qsTr("Information") + translationManager.emptyString
|
||||
informationPopup.text = qsTr("Money sent successfully") + translationManager.emptyString
|
||||
informationPopup.icon = StandardIcon.Information
|
||||
informationPopup.onCloseCallback = null
|
||||
informationPopup.open();
|
||||
}
|
||||
}
|
||||
onRejected: {
|
||||
console.log("Canceled")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
x: root.width/2 - width/2
|
||||
@@ -446,19 +681,32 @@ Rectangle {
|
||||
function onPageCompleted() {
|
||||
console.log("transfer page loaded")
|
||||
updateStatus();
|
||||
updateMixin();
|
||||
updatePriorityDropdown()
|
||||
}
|
||||
|
||||
function updatePriorityDropdown() {
|
||||
priorityDropdown.dataModel = priorityModelV5;
|
||||
priorityDropdown.currentIndex = 1
|
||||
priorityDropdown.update()
|
||||
}
|
||||
|
||||
//TODO: Add daemon sync status
|
||||
//TODO: enable send page when we're connected and daemon is synced
|
||||
|
||||
function updateStatus() {
|
||||
console.log("updated transfer page status")
|
||||
if(typeof currentWallet === "undefined") {
|
||||
statusText.text = qsTr("Wallet is not connected to daemon.") + "<br>" + root.startLinkText
|
||||
return;
|
||||
}
|
||||
|
||||
switch (currentWallet.connected) {
|
||||
if (currentWallet.viewOnly) {
|
||||
// statusText.text = qsTr("Wallet is view only.")
|
||||
//return;
|
||||
}
|
||||
pageRoot.enabled = false;
|
||||
|
||||
switch (currentWallet.connected()) {
|
||||
case Wallet.ConnectionStatus_Disconnected:
|
||||
statusText.text = qsTr("Wallet is not connected to daemon.") + "<br>" + root.startLinkText
|
||||
break
|
||||
|
||||
@@ -89,18 +89,22 @@ Rectangle {
|
||||
Text {
|
||||
text: qsTr("Verify that a third party made a payment by supplying:") + translationManager.emptyString
|
||||
wrapMode: Text.Wrap
|
||||
Layout.fillWidth: true;
|
||||
}
|
||||
Text {
|
||||
text: qsTr(" - the recipient address") + translationManager.emptyString
|
||||
wrapMode: Text.Wrap
|
||||
Layout.fillWidth: true;
|
||||
}
|
||||
Text {
|
||||
text: qsTr(" - the transaction ID") + translationManager.emptyString
|
||||
wrapMode: Text.Wrap
|
||||
Layout.fillWidth: true;
|
||||
}
|
||||
Text {
|
||||
text: qsTr(" - the secret transaction key supplied by the sender") + translationManager.emptyString
|
||||
wrapMode: Text.Wrap
|
||||
Layout.fillWidth: true;
|
||||
}
|
||||
Text {
|
||||
text: qsTr("If a payment had several transactions then each must be checked and the results combined.") + translationManager.emptyString
|
||||
@@ -209,7 +213,7 @@ Rectangle {
|
||||
anchors.top: txKeyRow.bottom
|
||||
anchors.topMargin: 17
|
||||
width: 60
|
||||
text: qsTr("CHECK") + translationManager.emptyString
|
||||
text: qsTr("Check") + translationManager.emptyString
|
||||
shadowReleasedColor: "#FF4304"
|
||||
shadowPressedColor: "#B32D00"
|
||||
releasedColor: "#FF6C3C"
|
||||
|
||||
22
qml.qrc
@@ -100,13 +100,27 @@
|
||||
<file>lang/flags/bangladesh.png</file>
|
||||
<file>lang/flags/brazil.png</file>
|
||||
<file>lang/flags/china.png</file>
|
||||
<file>lang/flags/croatia.png</file>
|
||||
<file>lang/flags/esperanto.png</file>
|
||||
<file>lang/flags/finland.png</file>
|
||||
<file>lang/flags/france.png</file>
|
||||
<file>lang/flags/german.png</file>
|
||||
<file>lang/flags/india.png</file>
|
||||
<file>lang/flags/indonesia.png</file>
|
||||
<file>lang/flags/italy.png</file>
|
||||
<file>lang/flags/japan.png</file>
|
||||
<file>lang/flags/netherlands.png</file>
|
||||
<file>lang/flags/palestine.png</file>
|
||||
<file>lang/flags/poland.png</file>
|
||||
<file>lang/flags/rpa.png</file>
|
||||
<file>lang/flags/russia.png</file>
|
||||
<file>lang/flags/spain.png</file>
|
||||
<file>lang/flags/sweden.png</file>
|
||||
<file>lang/flags/taiwan.png</file>
|
||||
<file>lang/flags/uk.png</file>
|
||||
<file>lang/flags/usa.png</file>
|
||||
<file>lang/flags/israel.png</file>
|
||||
<file>lang/flags/south_korea.png</file>
|
||||
<file>wizard/WizardManageWalletUI.qml</file>
|
||||
<file>wizard/WizardRecoveryWallet.qml</file>
|
||||
<file>wizard/WizardMemoTextInput.qml</file>
|
||||
@@ -114,7 +128,6 @@
|
||||
<file>pages/Receive.qml</file>
|
||||
<file>pages/TxKey.qml</file>
|
||||
<file>components/IconButton.qml</file>
|
||||
<file>lang/flags/italy.png</file>
|
||||
<file>components/PasswordDialog.qml</file>
|
||||
<file>components/ProcessingSplash.qml</file>
|
||||
<file>components/ProgressBar.qml</file>
|
||||
@@ -122,5 +135,12 @@
|
||||
<file>pages/Sign.qml</file>
|
||||
<file>components/DaemonManagerDialog.qml</file>
|
||||
<file>version.js</file>
|
||||
<file>wizard/WizardPasswordUI.qml</file>
|
||||
<file>wizard/WizardCreateViewOnlyWallet.qml</file>
|
||||
<file>components/DaemonConsole.qml</file>
|
||||
<file>components/QRCodeScanner.qml</file>
|
||||
<file>components/Notifier.qml</file>
|
||||
<file>components/MobileHeader.qml</file>
|
||||
<file>components/TextBlock.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
104
src/QR-Code-scanner/QrCodeScanner.cpp
Normal file
@@ -0,0 +1,104 @@
|
||||
// Copyright (c) 2014-2017, 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 "QrCodeScanner.h"
|
||||
#include <WalletManager.h>
|
||||
#include <QVideoProbe>
|
||||
#include <QCamera>
|
||||
|
||||
QrCodeScanner::QrCodeScanner(QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_processTimerId(-1)
|
||||
, m_processInterval(750)
|
||||
, m_enabled(true)
|
||||
{
|
||||
m_probe = new QVideoProbe(this);
|
||||
m_thread = new QrScanThread(this);
|
||||
m_thread->start();
|
||||
QObject::connect(m_thread, SIGNAL(decoded(int,QString)), this, SLOT(processCode(int,QString)));
|
||||
QObject::connect(m_thread, SIGNAL(notifyError(const QString &, bool)), this, SIGNAL(notifyError(const QString &, bool)));
|
||||
connect(m_probe, SIGNAL(videoFrameProbed(QVideoFrame)), this, SLOT(processFrame(QVideoFrame)));
|
||||
}
|
||||
void QrCodeScanner::setSource(QCamera *camera)
|
||||
{
|
||||
m_probe->setSource(camera);
|
||||
}
|
||||
void QrCodeScanner::processCode(int type, const QString &data)
|
||||
{
|
||||
if (! m_enabled) return;
|
||||
qDebug() << "decoded - type: " << type << " data: " << data;
|
||||
QString address, payment_id, tx_description, recipient_name, error;
|
||||
QVector<QString> unknown_parameters;
|
||||
uint64_t amount(0);
|
||||
if( ! WalletManager::instance()->parse_uri(data, address, payment_id, amount, tx_description, recipient_name, unknown_parameters, error) )
|
||||
{
|
||||
qDebug() << "Failed to parse_uri : " << error;
|
||||
emit notifyError(error);
|
||||
return;
|
||||
}
|
||||
if(unknown_parameters.size() > 0)
|
||||
{
|
||||
qDebug() << "unknown parameters " << unknown_parameters;
|
||||
emit notifyError(error, true);
|
||||
}
|
||||
qDebug() << "Parsed URI : " << address << " " << payment_id << " " << amount << " " << tx_description << " " << recipient_name << " " << error;
|
||||
QString s_amount = WalletManager::instance()->displayAmount(amount);
|
||||
qDebug() << "Amount passed " << s_amount ;
|
||||
emit decoded(address, payment_id, s_amount, tx_description, recipient_name);
|
||||
}
|
||||
void QrCodeScanner::processFrame(QVideoFrame frame)
|
||||
{
|
||||
if(frame.isValid()){
|
||||
m_curFrame = frame;
|
||||
}
|
||||
}
|
||||
bool QrCodeScanner::enabled() const
|
||||
{
|
||||
return m_enabled;
|
||||
}
|
||||
void QrCodeScanner::setEnabled(bool enabled)
|
||||
{
|
||||
m_enabled = enabled;
|
||||
if(!enabled && (m_processTimerId != -1) )
|
||||
{
|
||||
this->killTimer(m_processTimerId);
|
||||
m_processTimerId = -1;
|
||||
}
|
||||
else if (enabled && (m_processTimerId == -1) )
|
||||
{
|
||||
m_processTimerId = this->startTimer(m_processInterval);
|
||||
}
|
||||
emit enabledChanged();
|
||||
}
|
||||
void QrCodeScanner::timerEvent(QTimerEvent *event)
|
||||
{
|
||||
if( (event->timerId() == m_processTimerId) ){
|
||||
m_thread->addFrame(m_curFrame);
|
||||
}
|
||||
}
|
||||
|
||||
75
src/QR-Code-scanner/QrCodeScanner.h
Normal file
@@ -0,0 +1,75 @@
|
||||
// Copyright (c) 2014-2017, 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.
|
||||
|
||||
#ifndef QRCODESCANNER_H_
|
||||
#define QRCODESCANNER_H_
|
||||
|
||||
#include <QImage>
|
||||
#include <QVideoFrame>
|
||||
#include "QrScanThread.h"
|
||||
|
||||
class QVideoProbe;
|
||||
class QCamera;
|
||||
|
||||
class QrCodeScanner : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged)
|
||||
|
||||
public:
|
||||
QrCodeScanner(QObject *parent = Q_NULLPTR);
|
||||
|
||||
void setSource(QCamera*);
|
||||
|
||||
bool enabled() const;
|
||||
void setEnabled(bool enabled);
|
||||
|
||||
public Q_SLOTS:
|
||||
void processCode(int type, const QString &data);
|
||||
void processFrame(QVideoFrame);
|
||||
|
||||
Q_SIGNALS:
|
||||
void enabledChanged();
|
||||
|
||||
void decoded(const QString &address, const QString &payment_id, const QString &amount, const QString &tx_description, const QString &recipient_name);
|
||||
void decode(int type, const QString &data);
|
||||
void notifyError(const QString &error, bool warning = false);
|
||||
|
||||
protected:
|
||||
void timerEvent(QTimerEvent *);
|
||||
QrScanThread *m_thread;
|
||||
int m_processTimerId;
|
||||
int m_processInterval;
|
||||
int m_enabled;
|
||||
QVideoFrame m_curFrame;
|
||||
QVideoProbe *m_probe;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
132
src/QR-Code-scanner/QrScanThread.cpp
Normal file
@@ -0,0 +1,132 @@
|
||||
// Copyright (c) 2014-2017, 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 "QrScanThread.h"
|
||||
#include <QtGlobal>
|
||||
#include <QDebug>
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)
|
||||
extern QImage qt_imageFromVideoFrame(const QVideoFrame &f);
|
||||
#else
|
||||
QImage qt_imageFromVideoFrame(const QVideoFrame &f){
|
||||
Q_ASSERT_X(0 != 0, "qt_imageFromVideoFrame", "Should have been managed in .pro");
|
||||
return QImage();
|
||||
}
|
||||
#endif
|
||||
|
||||
QrScanThread::QrScanThread(QObject *parent)
|
||||
: QThread(parent)
|
||||
,m_running(true)
|
||||
{
|
||||
m_scanner.set_handler(*this);
|
||||
}
|
||||
|
||||
void QrScanThread::image_callback(zbar::Image &image)
|
||||
{
|
||||
qDebug() << "image_callback : Found Code ! " ;
|
||||
for(zbar::Image::SymbolIterator sym = image.symbol_begin();
|
||||
sym != image.symbol_end();
|
||||
++sym)
|
||||
if(!sym->get_count()) {
|
||||
QString data = QString::fromStdString(sym->get_data());
|
||||
emit decoded(sym->get_type(), data);
|
||||
}
|
||||
}
|
||||
|
||||
void QrScanThread::processZImage(zbar::Image &image)
|
||||
{
|
||||
m_scanner.recycle_image(image);
|
||||
zbar::Image tmp = image.convert(*(long*)"Y800");
|
||||
m_scanner.scan(tmp);
|
||||
image.set_symbols(tmp.get_symbols());
|
||||
}
|
||||
|
||||
bool QrScanThread::zimageFromQImage(const QImage &qimg, zbar::Image &dst)
|
||||
{
|
||||
switch( qimg.format() ){
|
||||
case QImage::Format_RGB32 :
|
||||
case QImage::Format_ARGB32 :
|
||||
case QImage::Format_ARGB32_Premultiplied :
|
||||
break;
|
||||
default :
|
||||
emit notifyError(QString("Invalid QImage Format !"));
|
||||
return false;
|
||||
}
|
||||
unsigned int bpl( qimg.bytesPerLine() ), width( bpl / 4), height( qimg.height());
|
||||
dst.set_size(width, height);
|
||||
dst.set_format("BGR4");
|
||||
unsigned long datalen = qimg.byteCount();
|
||||
dst.set_data(qimg.bits(), datalen);
|
||||
if((width * 4 != bpl) || (width * height * 4 > datalen)){
|
||||
emit notifyError(QString("QImage to Zbar::Image failed !"));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
void QrScanThread::processQImage(const QImage &qimg)
|
||||
{
|
||||
try {
|
||||
m_image = QSharedPointer<zbar::Image>(new zbar::Image());
|
||||
if( ! zimageFromQImage(qimg, *m_image) )
|
||||
return;
|
||||
processZImage(*m_image);
|
||||
}
|
||||
catch(std::exception &e) {
|
||||
qDebug() << "ERROR: " << e.what();
|
||||
emit notifyError(e.what());
|
||||
}
|
||||
}
|
||||
|
||||
void QrScanThread::processVideoFrame(const QVideoFrame &frame)
|
||||
{
|
||||
processQImage( qt_imageFromVideoFrame(frame) );
|
||||
}
|
||||
|
||||
void QrScanThread::stop()
|
||||
{
|
||||
m_running = false;
|
||||
}
|
||||
|
||||
void QrScanThread::addFrame(const QVideoFrame &frame)
|
||||
{
|
||||
QMutexLocker locker(&m_mutex);
|
||||
m_queue.append(frame);
|
||||
m_waitCondition.wakeOne();
|
||||
}
|
||||
|
||||
void QrScanThread::run()
|
||||
{
|
||||
QVideoFrame frame;
|
||||
while(m_running) {
|
||||
QMutexLocker locker(&m_mutex);
|
||||
while(m_queue.isEmpty())
|
||||
m_waitCondition.wait(&m_mutex);
|
||||
processVideoFrame(m_queue.takeFirst());
|
||||
}
|
||||
}
|
||||
|
||||
69
src/QR-Code-scanner/QrScanThread.h
Normal file
@@ -0,0 +1,69 @@
|
||||
// Copyright (c) 2014-2017, 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.
|
||||
|
||||
#ifndef _QRSCANTHREAD_H_
|
||||
#define _QRSCANTHREAD_H_
|
||||
|
||||
#include <QThread>
|
||||
#include <QMutex>
|
||||
#include <QWaitCondition>
|
||||
#include <QEvent>
|
||||
#include <QVideoFrame>
|
||||
#include <QCamera>
|
||||
#include <zbar.h>
|
||||
|
||||
class QrScanThread : public QThread, public zbar::Image::Handler
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QrScanThread(QObject *parent = Q_NULLPTR);
|
||||
void addFrame(const QVideoFrame &frame);
|
||||
|
||||
Q_SIGNALS:
|
||||
void decoded(int type, const QString &data);
|
||||
void notifyError(const QString &error, bool warning = false);
|
||||
|
||||
protected:
|
||||
virtual void run();
|
||||
virtual void stop();
|
||||
void processVideoFrame(const QVideoFrame &);
|
||||
void processQImage(const QImage &);
|
||||
void processZImage(zbar::Image &image);
|
||||
virtual void image_callback(zbar::Image &image);
|
||||
bool zimageFromQImage(const QImage&, zbar::Image &);
|
||||
|
||||
private:
|
||||
zbar::ImageScanner m_scanner;
|
||||
QSharedPointer<zbar::Image> m_image;
|
||||
bool m_running;
|
||||
QMutex m_mutex;
|
||||
QWaitCondition m_waitCondition;
|
||||
QList<QVideoFrame> m_queue;
|
||||
};
|
||||
#endif
|
||||
@@ -7,6 +7,15 @@
|
||||
#include <QtConcurrent/QtConcurrent>
|
||||
#include <QApplication>
|
||||
#include <QProcess>
|
||||
#include <QTime>
|
||||
#include <QStorageInfo>
|
||||
#include <QVariantMap>
|
||||
#include <QVariant>
|
||||
#include <QMap>
|
||||
|
||||
namespace {
|
||||
static const int DAEMON_START_TIMEOUT_SECONDS = 30;
|
||||
}
|
||||
|
||||
DaemonManager * DaemonManager::m_instance = nullptr;
|
||||
QStringList DaemonManager::m_clArgs;
|
||||
@@ -23,24 +32,19 @@ DaemonManager *DaemonManager::instance(const QStringList *args)
|
||||
return m_instance;
|
||||
}
|
||||
|
||||
bool DaemonManager::start(const QString &flags)
|
||||
bool DaemonManager::start(const QString &flags, bool testnet, const QString &dataDir)
|
||||
{
|
||||
//
|
||||
QString process;
|
||||
#ifdef Q_OS_WIN
|
||||
process = QApplication::applicationDirPath() + "/monerod.exe";
|
||||
#elif defined(Q_OS_UNIX)
|
||||
process = QApplication::applicationDirPath() + "/monerod";
|
||||
#endif
|
||||
|
||||
if (process.length() == 0) {
|
||||
qDebug() << "no daemon binary defined for current platform";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// prepare command line arguments and pass to monerod
|
||||
QStringList arguments;
|
||||
|
||||
// Start daemon with --detach flag on non-windows platforms
|
||||
#ifndef Q_OS_WIN
|
||||
arguments << "--detach";
|
||||
#endif
|
||||
|
||||
if(testnet)
|
||||
arguments << "--testnet";
|
||||
|
||||
foreach (const QString &str, m_clArgs) {
|
||||
qDebug() << QString(" [%1] ").arg(str);
|
||||
if (!str.isEmpty())
|
||||
@@ -54,8 +58,20 @@ bool DaemonManager::start(const QString &flags)
|
||||
arguments << str;
|
||||
}
|
||||
|
||||
// Custom data-dir
|
||||
if(!dataDir.isEmpty()) {
|
||||
if(testnet)
|
||||
arguments << "--testnet-data-dir";
|
||||
else
|
||||
arguments << "--data-dir";
|
||||
arguments << dataDir;
|
||||
}
|
||||
|
||||
qDebug() << "starting monerod " + process;
|
||||
arguments << "--check-updates" << "disabled";
|
||||
|
||||
|
||||
|
||||
qDebug() << "starting monerod " + m_monerod;
|
||||
qDebug() << "With command line arguments " << arguments;
|
||||
|
||||
m_daemon = new QProcess();
|
||||
@@ -66,33 +82,100 @@ bool DaemonManager::start(const QString &flags)
|
||||
connect (m_daemon, SIGNAL(readyReadStandardError()), this, SLOT(printError()));
|
||||
|
||||
// Start monerod
|
||||
m_daemon->start(process,arguments);
|
||||
bool started = m_daemon->waitForStarted();
|
||||
bool started = m_daemon->startDetached(m_monerod, arguments);
|
||||
|
||||
// add state changed listener
|
||||
connect(m_daemon,SIGNAL(stateChanged(QProcess::ProcessState)),this,SLOT(stateChanged(QProcess::ProcessState)));
|
||||
|
||||
if (!started) {
|
||||
qDebug() << "Daemon start error: " + m_daemon->errorString();
|
||||
} else {
|
||||
emit daemonStarted();
|
||||
emit daemonStartFailure();
|
||||
return false;
|
||||
}
|
||||
|
||||
return started;
|
||||
}
|
||||
// Start start watcher
|
||||
QFuture<bool> future = QtConcurrent::run(this, &DaemonManager::startWatcher, testnet);
|
||||
QFutureWatcher<bool> * watcher = new QFutureWatcher<bool>();
|
||||
connect(watcher, &QFutureWatcher<bool>::finished,
|
||||
this, [this, watcher]() {
|
||||
QFuture<bool> future = watcher->future();
|
||||
watcher->deleteLater();
|
||||
if(future.result())
|
||||
emit daemonStarted();
|
||||
else
|
||||
emit daemonStartFailure();
|
||||
});
|
||||
watcher->setFuture(future);
|
||||
|
||||
bool DaemonManager::stop()
|
||||
{
|
||||
if (initialized) {
|
||||
qDebug() << "stopping daemon";
|
||||
// we can't use QProcess::terminate() on windows console process
|
||||
// write exit command to stdin
|
||||
m_daemon->write("exit\n");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DaemonManager::stop(bool testnet)
|
||||
{
|
||||
QString message;
|
||||
sendCommand("exit",testnet,message);
|
||||
qDebug() << message;
|
||||
|
||||
// Start stop watcher - Will kill if not shutting down
|
||||
QFuture<bool> future = QtConcurrent::run(this, &DaemonManager::stopWatcher, testnet);
|
||||
QFutureWatcher<bool> * watcher = new QFutureWatcher<bool>();
|
||||
connect(watcher, &QFutureWatcher<bool>::finished,
|
||||
this, [this, watcher]() {
|
||||
QFuture<bool> future = watcher->future();
|
||||
watcher->deleteLater();
|
||||
if(future.result()) {
|
||||
emit daemonStopped();
|
||||
}
|
||||
});
|
||||
watcher->setFuture(future);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DaemonManager::startWatcher(bool testnet) const
|
||||
{
|
||||
// Check if daemon is started every 2 seconds
|
||||
QTime timer;
|
||||
timer.restart();
|
||||
while(true && !m_app_exit && timer.elapsed() / 1000 < DAEMON_START_TIMEOUT_SECONDS ) {
|
||||
QThread::sleep(2);
|
||||
if(!running(testnet)) {
|
||||
qDebug() << "daemon not running. checking again in 2 seconds.";
|
||||
} else {
|
||||
qDebug() << "daemon is started. Waiting 5 seconds to let daemon catch up";
|
||||
QThread::sleep(5);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DaemonManager::stopWatcher(bool testnet) const
|
||||
{
|
||||
// Check if daemon is running every 2 seconds. Kill if still running after 10 seconds
|
||||
int counter = 0;
|
||||
while(true && !m_app_exit) {
|
||||
QThread::sleep(2);
|
||||
counter++;
|
||||
if(running(testnet)) {
|
||||
qDebug() << "Daemon still running. " << counter;
|
||||
if(counter >= 5) {
|
||||
qDebug() << "Killing it! ";
|
||||
#ifdef Q_OS_WIN
|
||||
QProcess::execute("taskkill /F /IM monerod.exe");
|
||||
#else
|
||||
QProcess::execute("pkill monerod");
|
||||
#endif
|
||||
}
|
||||
|
||||
} else
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void DaemonManager::stateChanged(QProcess::ProcessState state)
|
||||
{
|
||||
qDebug() << "STATE CHANGED: " << state;
|
||||
@@ -123,29 +206,102 @@ void DaemonManager::printError()
|
||||
}
|
||||
}
|
||||
|
||||
bool DaemonManager::running() const
|
||||
{
|
||||
if (initialized) {
|
||||
qDebug() << m_daemon->state();
|
||||
qDebug() << QProcess::NotRunning;
|
||||
// m_daemon->write("status\n");
|
||||
return m_daemon->state() > QProcess::NotRunning;
|
||||
bool DaemonManager::running(bool testnet) const
|
||||
{
|
||||
QString status;
|
||||
sendCommand("status",testnet, status);
|
||||
qDebug() << status;
|
||||
// `./monerod status` returns BUSY when syncing.
|
||||
// Treat busy as connected, until fixed upstream.
|
||||
if (status.contains("Height:") || status.contains("BUSY") ) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool DaemonManager::sendCommand(const QString &cmd,bool testnet) const
|
||||
{
|
||||
QString message;
|
||||
return sendCommand(cmd, testnet, message);
|
||||
}
|
||||
|
||||
bool DaemonManager::sendCommand(const QString &cmd,bool testnet, QString &message) const
|
||||
{
|
||||
QProcess p;
|
||||
QStringList external_cmd;
|
||||
external_cmd << cmd;
|
||||
|
||||
// Add testnet flag if needed
|
||||
if (testnet)
|
||||
external_cmd << "--testnet";
|
||||
|
||||
qDebug() << "sending external cmd: " << external_cmd;
|
||||
|
||||
|
||||
p.start(m_monerod, external_cmd);
|
||||
|
||||
bool started = p.waitForFinished(-1);
|
||||
message = p.readAllStandardOutput();
|
||||
emit daemonConsoleUpdated(message);
|
||||
return started;
|
||||
}
|
||||
|
||||
void DaemonManager::exit()
|
||||
{
|
||||
qDebug("DaemonManager: exit()");
|
||||
m_app_exit = true;
|
||||
}
|
||||
|
||||
QVariantMap DaemonManager::validateDataDir(const QString &dataDir) const
|
||||
{
|
||||
QVariantMap result;
|
||||
bool valid = true;
|
||||
bool readOnly = false;
|
||||
int storageAvailable = 0;
|
||||
bool lmdbExists = true;
|
||||
|
||||
QStorageInfo storage(dataDir);
|
||||
if (storage.isValid() && storage.isReady()) {
|
||||
if (storage.isReadOnly()) {
|
||||
readOnly = true;
|
||||
valid = false;
|
||||
}
|
||||
|
||||
// Make sure there is 20GB storage available
|
||||
storageAvailable = storage.bytesAvailable()/1000/1000/1000;
|
||||
if (storageAvailable < 20) {
|
||||
valid = false;
|
||||
}
|
||||
} else {
|
||||
valid = false;
|
||||
}
|
||||
|
||||
|
||||
if (!QDir(dataDir+"/lmdb").exists()) {
|
||||
lmdbExists = false;
|
||||
valid = false;
|
||||
}
|
||||
|
||||
result.insert("valid", valid);
|
||||
result.insert("lmdbExists", lmdbExists);
|
||||
result.insert("readOnly", readOnly);
|
||||
result.insert("storageAvailable", storageAvailable);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
DaemonManager::DaemonManager(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
|
||||
}
|
||||
// Platform depetent path to monerod
|
||||
#ifdef Q_OS_WIN
|
||||
m_monerod = QApplication::applicationDirPath() + "/monerod.exe";
|
||||
#elif defined(Q_OS_UNIX)
|
||||
m_monerod = QApplication::applicationDirPath() + "/monerod";
|
||||
#endif
|
||||
|
||||
void DaemonManager::closing()
|
||||
{
|
||||
qDebug() << __FUNCTION__;
|
||||
stop();
|
||||
// Wait for daemon to stop before exiting (max 10 secs)
|
||||
if (initialized) {
|
||||
m_daemon->waitForFinished(10000);
|
||||
if (m_monerod.length() == 0) {
|
||||
qCritical() << "no daemon binary defined for current platform";
|
||||
m_has_daemon = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <QObject>
|
||||
#include <QUrl>
|
||||
#include <QProcess>
|
||||
#include <QVariantMap>
|
||||
|
||||
class DaemonManager : public QObject
|
||||
{
|
||||
@@ -13,30 +14,41 @@ public:
|
||||
|
||||
static DaemonManager * instance(const QStringList *args);
|
||||
|
||||
Q_INVOKABLE bool start(const QString &flags);
|
||||
Q_INVOKABLE bool stop();
|
||||
Q_INVOKABLE bool start(const QString &flags, bool testnet, const QString &dataDir = "");
|
||||
Q_INVOKABLE bool stop(bool testnet);
|
||||
|
||||
// return true if daemon process is started
|
||||
Q_INVOKABLE bool running() const;
|
||||
Q_INVOKABLE bool running(bool testnet) const;
|
||||
// Send daemon command from qml and prints output in console window.
|
||||
Q_INVOKABLE bool sendCommand(const QString &cmd, bool testnet) const;
|
||||
Q_INVOKABLE void exit();
|
||||
Q_INVOKABLE QVariantMap validateDataDir(const QString &dataDir) const;
|
||||
|
||||
private:
|
||||
|
||||
bool sendCommand(const QString &cmd, bool testnet, QString &message) const;
|
||||
bool startWatcher(bool testnet) const;
|
||||
bool stopWatcher(bool testnet) const;
|
||||
signals:
|
||||
void daemonStarted();
|
||||
void daemonStopped();
|
||||
void daemonConsoleUpdated(QString message);
|
||||
void daemonStarted() const;
|
||||
void daemonStopped() const;
|
||||
void daemonStartFailure() const;
|
||||
void daemonConsoleUpdated(QString message) const;
|
||||
|
||||
public slots:
|
||||
void printOutput();
|
||||
void printError();
|
||||
void closing();
|
||||
void stateChanged(QProcess::ProcessState state);
|
||||
|
||||
private:
|
||||
|
||||
explicit DaemonManager(QObject *parent = 0);
|
||||
static DaemonManager * m_instance;
|
||||
static QStringList m_clArgs;
|
||||
QProcess *m_daemon;
|
||||
bool initialized = false;
|
||||
QString m_monerod;
|
||||
bool m_has_daemon = true;
|
||||
bool m_app_exit = false;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -68,3 +68,8 @@ quint64 AddressBook::count() const
|
||||
{
|
||||
return m_rows.size();
|
||||
}
|
||||
|
||||
int AddressBook::lookupPaymentID(const QString &payment_id) const
|
||||
{
|
||||
return m_addressBookImpl->lookupPaymentID(payment_id.toStdString());
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ public:
|
||||
quint64 count() const;
|
||||
Q_INVOKABLE QString errorString() const;
|
||||
Q_INVOKABLE int errorCode() const;
|
||||
Q_INVOKABLE int lookupPaymentID(const QString &payment_id) const;
|
||||
|
||||
enum ErrorCode {
|
||||
Status_Ok,
|
||||
|
||||
@@ -13,7 +13,10 @@ QString PendingTransaction::errorString() const
|
||||
|
||||
bool PendingTransaction::commit()
|
||||
{
|
||||
return m_pimpl->commit();
|
||||
// Save transaction to file if fileName is set.
|
||||
if(!m_fileName.isEmpty())
|
||||
return m_pimpl->commit(m_fileName.toStdString());
|
||||
return m_pimpl->commit(m_fileName.toStdString());
|
||||
}
|
||||
|
||||
quint64 PendingTransaction::amount() const
|
||||
@@ -47,6 +50,11 @@ quint64 PendingTransaction::txCount() const
|
||||
return m_pimpl->txCount();
|
||||
}
|
||||
|
||||
void PendingTransaction::setFilename(const QString &fileName)
|
||||
{
|
||||
m_fileName = fileName;
|
||||
}
|
||||
|
||||
PendingTransaction::PendingTransaction(Monero::PendingTransaction *pt, QObject *parent)
|
||||
: QObject(parent), m_pimpl(pt)
|
||||
{
|
||||
|
||||
@@ -44,6 +44,7 @@ public:
|
||||
quint64 fee() const;
|
||||
QStringList txid() const;
|
||||
quint64 txCount() const;
|
||||
Q_INVOKABLE void setFilename(const QString &fileName);
|
||||
|
||||
private:
|
||||
explicit PendingTransaction(Monero::PendingTransaction * pt, QObject *parent = 0);
|
||||
@@ -51,6 +52,7 @@ private:
|
||||
private:
|
||||
friend class Wallet;
|
||||
Monero::PendingTransaction * m_pimpl;
|
||||
QString m_fileName;
|
||||
};
|
||||
|
||||
#endif // PENDINGTRANSACTION_H
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#include "QRCodeImageProvider.h"
|
||||
|
||||
QImage QRCodeImageProvider::requestImage(const QString &id, QSize *size, const QSize &requestedSize)
|
||||
QImage QRCodeImageProvider::genQrImage(const QString &id, QSize *size)
|
||||
{
|
||||
using namespace qrcodegen;
|
||||
|
||||
@@ -15,3 +15,8 @@ QImage QRCodeImageProvider::requestImage(const QString &id, QSize *size, const Q
|
||||
*size = QSize(qrcode.size, qrcode.size);
|
||||
return img;
|
||||
}
|
||||
|
||||
QImage QRCodeImageProvider::requestImage(const QString &id, QSize *size, const QSize &/* requestedSize */)
|
||||
{
|
||||
return genQrImage(id, size);
|
||||
}
|
||||
|
||||
@@ -7,5 +7,6 @@ public:
|
||||
QRCodeImageProvider(): QQuickImageProvider(QQuickImageProvider::Image) {}
|
||||
|
||||
QImage requestImage(const QString &id, QSize *size, const QSize &requestedSize);
|
||||
static QImage genQrImage(const QString &id, QSize *size);
|
||||
};
|
||||
|
||||
|
||||
@@ -31,7 +31,9 @@ QList<TransactionInfo *> TransactionHistory::getAll() const
|
||||
|
||||
QDateTime firstDateTime = QDateTime(QDate(2014, 4, 18)); // the genesis block
|
||||
QDateTime lastDateTime = QDateTime::currentDateTime().addDays(1); // tomorrow (guard against jitter and timezones)
|
||||
|
||||
quint64 lastTxHeight = 0;
|
||||
m_locked = false;
|
||||
m_minutesToUnlock = 0;
|
||||
TransactionHistory * parent = const_cast<TransactionHistory*>(this);
|
||||
for (const auto i : m_pimpl->getAll()) {
|
||||
TransactionInfo * ti = new TransactionInfo(i, parent);
|
||||
@@ -43,6 +45,15 @@ QList<TransactionInfo *> TransactionHistory::getAll() const
|
||||
if (ti->timestamp() <= firstDateTime) {
|
||||
firstDateTime = ti->timestamp();
|
||||
}
|
||||
quint64 requiredConfirmations = (ti->blockHeight() < ti->unlockTime()) ? ti->unlockTime() - ti->blockHeight() : 0;
|
||||
// store last tx height
|
||||
if (ti->confirmations() < requiredConfirmations && ti->blockHeight() >= lastTxHeight) {
|
||||
lastTxHeight = ti->blockHeight();
|
||||
// TODO: Fetch block time and confirmations needed from wallet2?
|
||||
m_minutesToUnlock = (requiredConfirmations - ti->confirmations()) * 2;
|
||||
m_locked = true;
|
||||
}
|
||||
|
||||
}
|
||||
emit refreshFinished();
|
||||
|
||||
@@ -81,9 +92,19 @@ QDateTime TransactionHistory::lastDateTime() const
|
||||
return m_lastDateTime;
|
||||
}
|
||||
|
||||
quint64 TransactionHistory::minutesToUnlock() const
|
||||
{
|
||||
return m_minutesToUnlock;
|
||||
}
|
||||
|
||||
bool TransactionHistory::TransactionHistory::locked() const
|
||||
{
|
||||
return m_locked;
|
||||
}
|
||||
|
||||
|
||||
TransactionHistory::TransactionHistory(Monero::TransactionHistory *pimpl, QObject *parent)
|
||||
: QObject(parent), m_pimpl(pimpl)
|
||||
: QObject(parent), m_pimpl(pimpl), m_minutesToUnlock(0), m_locked(false)
|
||||
{
|
||||
m_firstDateTime = QDateTime(QDate(2014, 4, 18)); // the genesis block
|
||||
m_lastDateTime = QDateTime::currentDateTime().addDays(1); // tomorrow (guard against jitter and timezones)
|
||||
|
||||