Compare commits
466 Commits
v0.0-beta-
...
v0.10.3.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 = dirty
|
||||
@@ -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
|
||||
|
||||
101
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,6 +62,7 @@ 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
|
||||
}
|
||||
@@ -73,7 +76,7 @@ Rectangle {
|
||||
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 +86,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
|
||||
@@ -105,10 +120,11 @@ Rectangle {
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: logoItem.bottom
|
||||
anchors.topMargin: 30
|
||||
anchors.topMargin: 26
|
||||
spacing: 5
|
||||
|
||||
Label {
|
||||
id: balanceLabel
|
||||
text: qsTr("Balance") + translationManager.emptyString
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 50
|
||||
@@ -131,9 +147,17 @@ Rectangle {
|
||||
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,6 +168,7 @@ Rectangle {
|
||||
}
|
||||
|
||||
Label {
|
||||
id: unlockedBalanceLabel
|
||||
text: qsTr("Unlocked balance") + translationManager.emptyString
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 50
|
||||
@@ -155,9 +180,17 @@ 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -183,7 +216,7 @@ Rectangle {
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.top: column1.bottom
|
||||
anchors.topMargin: 50
|
||||
anchors.topMargin: 25
|
||||
color: "#1C1C1C"
|
||||
|
||||
Column {
|
||||
@@ -239,6 +272,7 @@ Rectangle {
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
visible: transferButton.present
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.leftMargin: 16
|
||||
@@ -264,6 +298,7 @@ Rectangle {
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
visible: addressBookButton.present
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.leftMargin: 16
|
||||
@@ -286,6 +321,7 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
Rectangle {
|
||||
visible: receiveButton.present
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.leftMargin: 16
|
||||
@@ -309,6 +345,7 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
Rectangle {
|
||||
visible: historyButton.present
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.leftMargin: 16
|
||||
@@ -316,7 +353,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 +383,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 +392,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 +406,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 +415,7 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
Rectangle {
|
||||
visible: txkeyButton.present
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.leftMargin: 16
|
||||
@@ -390,7 +430,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 +439,7 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
Rectangle {
|
||||
visible: signButton.present
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.leftMargin: 16
|
||||
|
||||
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
|
||||
|
||||
|
||||
@@ -42,7 +42,9 @@ Rectangle {
|
||||
property Item currentView
|
||||
property Item previousView
|
||||
property bool basicMode : false
|
||||
property string balanceLabelText: qsTr("Balance") + translationManager.emptyString
|
||||
property string balanceText
|
||||
property string unlockedBalanceLabelText: qsTr("Unlocked Balance") + translationManager.emptyString
|
||||
property string unlockedBalanceText
|
||||
|
||||
property Transfer transferView: Transfer { }
|
||||
@@ -51,6 +53,7 @@ Rectangle {
|
||||
property History historyView: History { }
|
||||
property Sign signView: Sign { }
|
||||
property Settings settingsView: Settings { }
|
||||
property Mining miningView: Mining { }
|
||||
property AddressBook addressBookView: AddressBook { }
|
||||
|
||||
|
||||
@@ -143,7 +146,7 @@ Rectangle {
|
||||
PropertyChanges { target: root; currentView: settingsView }
|
||||
}, State {
|
||||
name: "Mining"
|
||||
PropertyChanges { /*TODO*/ }
|
||||
PropertyChanges { target: root; currentView: miningView }
|
||||
}
|
||||
]
|
||||
|
||||
@@ -198,17 +201,16 @@ Rectangle {
|
||||
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: qsTr("Balance:")
|
||||
text: root.balanceLabelText + ":"
|
||||
}
|
||||
|
||||
Text {
|
||||
@@ -217,7 +219,6 @@ Rectangle {
|
||||
height: 20
|
||||
font.family: "Arial"
|
||||
font.pixelSize: 18
|
||||
font.letterSpacing: -1
|
||||
elide: Text.ElideRight
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
verticalAlignment: Text.AlignBottom
|
||||
@@ -237,16 +238,16 @@ Rectangle {
|
||||
}
|
||||
|
||||
Text {
|
||||
id: availableBalanceLabel
|
||||
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: root.unlockedBalanceLabelText + ":"
|
||||
}
|
||||
|
||||
Text {
|
||||
@@ -255,7 +256,6 @@ Rectangle {
|
||||
height: 20
|
||||
font.family: "Arial"
|
||||
font.pixelSize: 14
|
||||
font.letterSpacing: -1
|
||||
elide: Text.ElideRight
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
verticalAlignment: Text.AlignBottom
|
||||
|
||||
99
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,7 +64,7 @@ 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 and Linux Mint 18 "Sarah" - Cinnamon x64)
|
||||
|
||||
1. Install Monero dependencies.
|
||||
|
||||
@@ -83,31 +85,29 @@ Packaging for your favorite distribution would be a welcome contribution!
|
||||
|
||||
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`
|
||||
|
||||
- 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`
|
||||
|
||||
- Optional : To build the flag `WITH_SCANNER`
|
||||
|
||||
`sudo apt install qtmultimedia5-dev qml-module-qtmultimedia libzbar-dev`
|
||||
|
||||
6. Build the GUI.
|
||||
|
||||
`qmake`
|
||||
`./build.sh`
|
||||
|
||||
`make`
|
||||
7. Run the GUI client.
|
||||
|
||||
7. Before running the GUI, it's recommended that you have the Monero daemon running in the background.
|
||||
|
||||
`./monerod`
|
||||
|
||||
8. Run the GUI client.
|
||||
|
||||
`./release/bin/monero-core`
|
||||
`./build/release/bin/monero-wallet-gui`
|
||||
|
||||
### On OS X:
|
||||
|
||||
@@ -115,28 +115,38 @@ 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`
|
||||
|
||||
`brew install qt5` (or download QT 5.8+ from [qt.io](https://www.qt.io/download-open-source/))
|
||||
|
||||
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`
|
||||
|
||||
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:
|
||||
5. Add Qt bin dir to your path (check first if directory exists; 5.8 is the current version)
|
||||
|
||||
`export PATH=$PATH:$HOME/Qt/5.7/clang_64/bin`
|
||||
`export PATH=$PATH:$HOME/Qt/5.8/clang_64/bin`
|
||||
|
||||
where ```Qt``` is the folder you selected to install Qt.
|
||||
5. Add Qt bin dir to your path. Example:
|
||||
|
||||
`export PATH=$PATH:/usr/local/opt/qt5/bin`
|
||||
|
||||
make sure this is where Qt 5.x is installed on **your** system eg `$HOME/Qt/5.8/clang_64/bin` if you downloaded from qt.io.
|
||||
|
||||
6. Grab an up-to-date copy of the monero-core repository.
|
||||
|
||||
`git clone https://github.com/monero-project/monero-core.git`
|
||||
`git clone https://github.com/monero-project/monero-core.git`
|
||||
|
||||
7. Go into the repository.
|
||||
|
||||
`cd monero-core`
|
||||
`cd monero-core`
|
||||
|
||||
8. Build libwallet
|
||||
|
||||
@@ -164,8 +174,13 @@ 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)**
|
||||
```
|
||||
pacman -S mingw-w64-i686-toolchain make mingw-w64-i686-cmake mingw-w64-i686-boost
|
||||
|
||||
```
|
||||
|
||||
3. Install git into msys2 environment:
|
||||
|
||||
@@ -179,35 +194,35 @@ More info: http://stackoverflow.com/a/35098040/1683164
|
||||
- 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 resulting executable can be found in ```.\release\bin```
|
||||
|
||||
65
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"
|
||||
@@ -54,11 +85,11 @@ popd
|
||||
echo "var GUI_MONERO_VERSION = \"$VERSIONTAG\"" >> 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
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
|
||||
|
||||
147
components/DaemonConsole.qml
Normal file
@@ -0,0 +1,147 @@
|
||||
// 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
|
||||
|
||||
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,12 +39,14 @@ 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
|
||||
@@ -61,15 +63,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 +97,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
|
||||
}
|
||||
|
||||
@@ -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 < 10)? "#FF6C3C" : "#545454"
|
||||
text: {
|
||||
if (!isPending)
|
||||
if(confirmations < 10)
|
||||
return blockHeight + " " + qsTr("(%1/10 confirmations)").arg(confirmations)
|
||||
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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
82
components/Notifier.qml
Normal file
@@ -0,0 +1,82 @@
|
||||
// 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.message = message
|
||||
item.active = true
|
||||
hider.running = true
|
||||
}
|
||||
}
|
||||
@@ -52,13 +52,6 @@ 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
|
||||
@@ -74,7 +67,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 +100,14 @@ Window {
|
||||
}
|
||||
}
|
||||
Keys.onReturnPressed: {
|
||||
root.accepted()
|
||||
root.close()
|
||||
root.accepted()
|
||||
|
||||
}
|
||||
Keys.onEscapePressed: {
|
||||
root.rejected()
|
||||
root.close()
|
||||
root.rejected()
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -149,7 +144,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,10 @@ 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 +83,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,6 +45,9 @@ 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
|
||||
@@ -98,6 +101,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 +132,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,15 @@ 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 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 +219,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 same destination</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 {
|
||||
|
||||
@@ -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,39 +41,37 @@ 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 || checked ? "#FFE00A" : "#000000"
|
||||
height: 30
|
||||
width: height
|
||||
|
||||
Image {
|
||||
anchors.centerIn: parent
|
||||
rotation: parent.checked ? 180 : 0
|
||||
source: parent.containsMouse || parent.checked ? "../images/goToBasicVersionHovered.png" :
|
||||
source: parent.customDecorations || parent.checked ? "../images/goToBasicVersionHovered.png" :
|
||||
"../images/gotoBasicVersion.png"
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: basicMouseArea
|
||||
hoverEnabled: true
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
parent.checked = !parent.checked
|
||||
|
||||
@@ -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
|
||||
git -C $MONERO_DIR fetch --tags
|
||||
git -C $MONERO_DIR checkout v0.10.3.1
|
||||
|
||||
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,24 @@ 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
|
||||
|
||||
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
|
||||
|
||||
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/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/spain.png
Normal file
|
After Width: | Height: | Size: 6.9 KiB |
BIN
lang/flags/taiwan.png
Normal file
|
After Width: | Height: | Size: 8.9 KiB |
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<languages>
|
||||
|
||||
<!--
|
||||
@@ -12,13 +12,23 @@ List of available languages for your wallet's seed:
|
||||
6 : Japanese
|
||||
-->
|
||||
<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="German" 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="Spanish" 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="French" flag="/lang/flags/france.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="Italian" flag="/lang/flags/italy.png" qs="none"/>
|
||||
<language display_name="日本語" locale="ja_JP" wallet_language="Japanese" flag="/lang/flags/japan.png" qs="none"/>
|
||||
<language display_name="Nederlands" locale="nl_NL" wallet_language="Dutch" 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="Portuguese" flag="/lang/flags/brazil.png" qs="none"/>
|
||||
<!-- <language display_name="русский язык" locale="ru_RU" wallet_language="Russian" flag="/lang/flags/russia.png" qs="none"/> -->
|
||||
<language display_name="简体中文 (中国)" locale="zh-cn_CN" wallet_language="English" flag="/lang/flags/china.png" qs="none"/>
|
||||
<language display_name="繁體中文 (台灣)" locale="zh-tw_CN" wallet_language="English" flag="/lang/flags/taiwan.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
|
||||
@@ -26,3 +48,5 @@ export QT_PLUGIN_PATH=\`pwd\`/plugins
|
||||
export QML2_IMPORT_PATH=\`pwd\`/qml
|
||||
./$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();
|
||||
}
|
||||
|
||||
386
main.qml
@@ -54,13 +54,20 @@ ApplicationWindow {
|
||||
property var transaction;
|
||||
property var transactionDescription;
|
||||
property alias password : passwordDialog.password
|
||||
property int splashCounter: 0
|
||||
property bool isNewWallet: false
|
||||
property int restoreHeight:0
|
||||
property bool daemonSynced: false
|
||||
property int maxWindowHeight: (Screen.height < 900)? 720 : 800;
|
||||
property bool daemonRunning: false
|
||||
property alias toolTip: toolTip
|
||||
property string walletName
|
||||
property bool viewOnly: false
|
||||
property bool foundNewBlock: false
|
||||
property int timeToUnlock: 0
|
||||
property bool qrScannerEnabled: (typeof builtWithScanner != "undefined") && builtWithScanner
|
||||
property int blocksToSync: 1
|
||||
property var isMobile: (appWindow.width > 700) ? false : true
|
||||
property var cameraUi
|
||||
|
||||
// true if wallet ever synchronized
|
||||
property bool walletInitialized : false
|
||||
@@ -80,8 +87,9 @@ ApplicationWindow {
|
||||
return
|
||||
}
|
||||
|
||||
if(seq === "Ctrl+D") middlePanel.state = "Dashboard"
|
||||
else if(seq === "Ctrl+S") middlePanel.state = "Transfer"
|
||||
// Dashboard is not implemented
|
||||
// if(seq === "Ctrl+") middlePanel.state = "Dashboard"
|
||||
if(seq === "Ctrl+S") middlePanel.state = "Transfer"
|
||||
else if(seq === "Ctrl+R") middlePanel.state = "Receive"
|
||||
else if(seq === "Ctrl+K") middlePanel.state = "TxKey"
|
||||
else if(seq === "Ctrl+H") middlePanel.state = "History"
|
||||
@@ -89,6 +97,7 @@ ApplicationWindow {
|
||||
else if(seq === "Ctrl+M") middlePanel.state = "Mining"
|
||||
else if(seq === "Ctrl+I") middlePanel.state = "Sign"
|
||||
else if(seq === "Ctrl+E") middlePanel.state = "Settings"
|
||||
else if(seq === "Ctrl+D") middlePanel.state = "Advanced"
|
||||
else if(seq === "Ctrl+Tab" || seq === "Alt+Tab") {
|
||||
/*
|
||||
if(middlePanel.state === "Dashboard") middlePanel.state = "Transfer"
|
||||
@@ -140,6 +149,11 @@ ApplicationWindow {
|
||||
function mousePressed(obj, mouseX, mouseY) {}
|
||||
function mouseReleased(obj, mouseX, mouseY) {}
|
||||
|
||||
function loadPage(page) {
|
||||
middlePanel.state = page;
|
||||
leftPanel.selectItem(page);
|
||||
}
|
||||
|
||||
function openWalletFromFile(){
|
||||
persistentSettings.restore_height = 0
|
||||
restoreHeight = 0;
|
||||
@@ -150,15 +164,23 @@ ApplicationWindow {
|
||||
|
||||
function initialize() {
|
||||
console.log("initializing..")
|
||||
|
||||
walletInitialized = false;
|
||||
|
||||
// Use stored log level
|
||||
if (persistentSettings.logLevel == 5)
|
||||
walletManager.setLogCategories(persistentSettings.logCategories)
|
||||
else
|
||||
walletManager.setLogLevel(persistentSettings.logLevel)
|
||||
|
||||
// setup language
|
||||
var locale = persistentSettings.locale
|
||||
if (locale !== "") {
|
||||
translationManager.setLanguage(locale.split("_")[0]);
|
||||
}
|
||||
|
||||
// Reload transfer page with translations enabled
|
||||
middlePanel.transferView.onPageCompleted();
|
||||
|
||||
// If currentWallet exists, we're just switching daemon - close/reopen wallet
|
||||
if (typeof currentWallet !== "undefined" && currentWallet !== null) {
|
||||
console.log("Daemon change - closing " + currentWallet)
|
||||
@@ -173,7 +195,6 @@ ApplicationWindow {
|
||||
}
|
||||
|
||||
walletManager.setDaemonAddress(persistentSettings.daemon_address)
|
||||
|
||||
// wallet already opened with wizard, we just need to initialize it
|
||||
if (typeof wizard.settings['wallet'] !== 'undefined') {
|
||||
console.log("using wizard wallet")
|
||||
@@ -206,6 +227,7 @@ ApplicationWindow {
|
||||
currentWallet.newBlock.disconnect(onWalletNewBlock)
|
||||
currentWallet.moneySpent.disconnect(onWalletMoneySent)
|
||||
currentWallet.moneyReceived.disconnect(onWalletMoneyReceived)
|
||||
currentWallet.unconfirmedMoneyReceived.disconnect(onWalletUnconfirmedMoneyReceived)
|
||||
currentWallet.transactionCreated.disconnect(onTransactionCreated)
|
||||
currentWallet.connectionStatusChanged.disconnect(onWalletConnectionStatusChanged)
|
||||
middlePanel.paymentClicked.disconnect(handlePayment);
|
||||
@@ -217,8 +239,11 @@ ApplicationWindow {
|
||||
}
|
||||
|
||||
function connectWallet(wallet) {
|
||||
showProcessingSplash("Please wait...")
|
||||
currentWallet = wallet
|
||||
walletName = usefulName(wallet.path)
|
||||
updateSyncing(false)
|
||||
|
||||
viewOnly = currentWallet.viewOnly;
|
||||
|
||||
// connect handlers
|
||||
currentWallet.refreshed.connect(onWalletRefresh)
|
||||
@@ -226,6 +251,7 @@ ApplicationWindow {
|
||||
currentWallet.newBlock.connect(onWalletNewBlock)
|
||||
currentWallet.moneySpent.connect(onWalletMoneySent)
|
||||
currentWallet.moneyReceived.connect(onWalletMoneyReceived)
|
||||
currentWallet.unconfirmedMoneyReceived.connect(onWalletUnconfirmedMoneyReceived)
|
||||
currentWallet.transactionCreated.connect(onTransactionCreated)
|
||||
currentWallet.connectionStatusChanged.connect(onWalletConnectionStatusChanged)
|
||||
middlePanel.paymentClicked.connect(handlePayment);
|
||||
@@ -235,6 +261,10 @@ ApplicationWindow {
|
||||
console.log("initializing with daemon address: ", persistentSettings.daemon_address)
|
||||
console.log("Recovering from seed: ", persistentSettings.is_recovering)
|
||||
console.log("restore Height", persistentSettings.restore_height)
|
||||
|
||||
// Use saved daemon rpc login settings
|
||||
currentWallet.setDaemonLogin(persistentSettings.daemonUsername, persistentSettings.daemonPassword);
|
||||
|
||||
currentWallet.initAsync(persistentSettings.daemon_address, 0, persistentSettings.is_recovering, persistentSettings.restore_height);
|
||||
}
|
||||
|
||||
@@ -243,12 +273,35 @@ ApplicationWindow {
|
||||
return wallet_path;
|
||||
}
|
||||
|
||||
function onWalletConnectionStatusChanged(){
|
||||
console.log("Wallet connection status changed")
|
||||
middlePanel.updateStatus();
|
||||
function usefulName(path) {
|
||||
// arbitrary "short enough" limit
|
||||
if (path.length < 32)
|
||||
return path
|
||||
return path.replace(/.*[\/\\]/, '').replace(/\.keys$/, '')
|
||||
}
|
||||
|
||||
function onWalletConnectionStatusChanged(status){
|
||||
console.log("Wallet connection status changed " + status)
|
||||
middlePanel.updateStatus();
|
||||
leftPanel.networkStatus.connected = status
|
||||
leftPanel.progressBar.visible = (status === Wallet.ConnectionStatus_Connected) && !daemonSynced
|
||||
|
||||
// Update fee multiplier dropdown on transfer page
|
||||
middlePanel.transferView.updatePriorityDropdown();
|
||||
|
||||
// If wallet isnt connected and no daemon is running - Ask
|
||||
if(!walletInitialized && status === Wallet.ConnectionStatus_Disconnected && !daemonManager.running(persistentSettings.testnet)){
|
||||
daemonManagerDialog.open();
|
||||
}
|
||||
// initialize transaction history once wallet is initialized first time;
|
||||
if (!walletInitialized) {
|
||||
currentWallet.history.refresh()
|
||||
walletInitialized = true
|
||||
}
|
||||
}
|
||||
|
||||
function onWalletOpened(wallet) {
|
||||
walletName = usefulName(wallet.path)
|
||||
console.log(">>> wallet opened: " + wallet)
|
||||
if (wallet.status !== Wallet.Status_Ok) {
|
||||
if (appWindow.password === '') {
|
||||
@@ -256,7 +309,7 @@ ApplicationWindow {
|
||||
console.log("closing wallet async : " + wallet.address)
|
||||
closeWallet();
|
||||
// try to open wallet with password;
|
||||
passwordDialog.open(wallet.path);
|
||||
passwordDialog.open(walletName);
|
||||
} else {
|
||||
// opening with password but password doesn't match
|
||||
console.error("Error opening wallet with password: ", wallet.errorString);
|
||||
@@ -268,7 +321,7 @@ ApplicationWindow {
|
||||
closeWallet();
|
||||
informationPopup.open()
|
||||
informationPopup.onCloseCallback = function() {
|
||||
passwordDialog.open(wallet.path)
|
||||
passwordDialog.open(walletName)
|
||||
}
|
||||
}
|
||||
return;
|
||||
@@ -276,7 +329,6 @@ ApplicationWindow {
|
||||
|
||||
// wallet opened successfully, subscribing for wallet updates
|
||||
connectWallet(wallet)
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -288,32 +340,37 @@ ApplicationWindow {
|
||||
console.log(">>> wallet updated")
|
||||
middlePanel.unlockedBalanceText = leftPanel.unlockedBalanceText = walletManager.displayAmount(currentWallet.unlockedBalance);
|
||||
middlePanel.balanceText = leftPanel.balanceText = walletManager.displayAmount(currentWallet.balance);
|
||||
// Update history if new block found since last update
|
||||
if(foundNewBlock) {
|
||||
foundNewBlock = false;
|
||||
console.log("New block found - updating history")
|
||||
currentWallet.history.refresh()
|
||||
timeToUnlock = currentWallet.history.minutesToUnlock
|
||||
leftPanel.minutesToUnlockTxt = (timeToUnlock > 0)? (timeToUnlock == 20)? qsTr("Unlocked balance (waiting for block)").arg(timeToUnlock) : qsTr("Unlocked balance (~%1 min)").arg(timeToUnlock) : qsTr("Unlocked balance");
|
||||
}
|
||||
}
|
||||
|
||||
function onWalletRefresh() {
|
||||
console.log(">>> wallet refreshed")
|
||||
if (splash.visible) {
|
||||
hideProcessingSplash()
|
||||
}
|
||||
|
||||
// Daemon connected
|
||||
leftPanel.networkStatus.connected = currentWallet.connected
|
||||
leftPanel.networkStatus.connected = currentWallet.connected()
|
||||
|
||||
// Check daemon status
|
||||
var dCurrentBlock = currentWallet.daemonBlockChainHeight();
|
||||
var dTargetBlock = currentWallet.daemonBlockChainTargetHeight();
|
||||
|
||||
// Daemon fully synced
|
||||
// TODO: implement onDaemonSynced or similar in wallet API and don't start refresh thread before daemon is synced
|
||||
daemonSynced = (currentWallet.connected != Wallet.ConnectionStatus_Disconnected && dCurrentBlock >= dTargetBlock)
|
||||
// targetBlock = currentBlock = 1 before network connection is established.
|
||||
daemonSynced = dCurrentBlock >= dTargetBlock && dTargetBlock != 1
|
||||
// Update daemon sync progress
|
||||
leftPanel.progressBar.updateProgress(dCurrentBlock,dTargetBlock);
|
||||
leftPanel.progressBar.visible = !daemonSynced && currentWallet.connected() !== Wallet.ConnectionStatus_Disconnected
|
||||
// Update wallet sync progress
|
||||
updateSyncing((currentWallet.connected() !== Wallet.ConnectionStatus_Disconnected) && !daemonSynced)
|
||||
// Update transfer page status
|
||||
middlePanel.updateStatus();
|
||||
|
||||
// If wallet isnt connected and no daemon is running - Ask
|
||||
if(currentWallet.connected === Wallet.ConnectionStatus_Disconnected && !daemonManager.running() && !walletInitialized){
|
||||
daemonManagerDialog.open();
|
||||
}
|
||||
|
||||
// Refresh is succesfull if blockchain height > 1
|
||||
if (currentWallet.blockChainHeight() > 1){
|
||||
|
||||
@@ -323,6 +380,9 @@ ApplicationWindow {
|
||||
console.log("Saving wallet after first refresh");
|
||||
currentWallet.store()
|
||||
isNewWallet = false
|
||||
|
||||
// Update History
|
||||
currentWallet.history.refresh();
|
||||
}
|
||||
|
||||
// recovering from seed is finished after first refresh
|
||||
@@ -331,49 +391,60 @@ ApplicationWindow {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// initialize transaction history once wallet is initializef first time;
|
||||
if (!walletInitialized) {
|
||||
currentWallet.history.refresh()
|
||||
walletInitialized = true
|
||||
}
|
||||
|
||||
onWalletUpdate();
|
||||
}
|
||||
|
||||
function startDaemon(flags){
|
||||
// Pause refresh while starting daemon
|
||||
currentWallet.pauseRefresh();
|
||||
|
||||
appWindow.showProcessingSplash(qsTr("Waiting for daemon to start..."))
|
||||
daemonManager.start(flags);
|
||||
daemonManager.start(flags, persistentSettings.testnet);
|
||||
persistentSettings.daemonFlags = flags
|
||||
}
|
||||
|
||||
function stopDaemon(){
|
||||
appWindow.showProcessingSplash(qsTr("Waiting for daemon to stop..."))
|
||||
daemonManager.stop();
|
||||
daemonManager.stop(persistentSettings.testnet);
|
||||
}
|
||||
|
||||
function onDaemonStarted(){
|
||||
console.log("daemon started");
|
||||
daemonRunning = true;
|
||||
hideProcessingSplash();
|
||||
currentWallet.connected(true);
|
||||
// resume refresh
|
||||
currentWallet.startRefresh();
|
||||
}
|
||||
function onDaemonStopped(){
|
||||
console.log("daemon stopped");
|
||||
hideProcessingSplash();
|
||||
daemonRunning = false;
|
||||
currentWallet.connected(true);
|
||||
}
|
||||
|
||||
function onDaemonStartFailure(){
|
||||
console.log("daemon start failed");
|
||||
hideProcessingSplash();
|
||||
// resume refresh
|
||||
currentWallet.startRefresh();
|
||||
daemonRunning = false;
|
||||
informationPopup.title = qsTr("Daemon failed to start") + translationManager.emptyString;
|
||||
informationPopup.text = qsTr("Please check your wallet and daemon log for errors. You can also try to start %1 manually.").arg((isWindows)? "monerod.exe" : "monerod")
|
||||
informationPopup.icon = StandardIcon.Critical
|
||||
informationPopup.onCloseCallback = null
|
||||
informationPopup.open();
|
||||
}
|
||||
|
||||
function onWalletNewBlock(blockHeight) {
|
||||
function onWalletNewBlock(blockHeight, targetHeight) {
|
||||
// Update progress bar
|
||||
var remaining = targetHeight - blockHeight;
|
||||
if(blocksToSync < remaining) {
|
||||
blocksToSync = remaining;
|
||||
}
|
||||
|
||||
// Update progress bar
|
||||
var currHeight = blockHeight
|
||||
//fast refresh until restoreHeight is reached
|
||||
var increment = ((restoreHeight == 0) || currHeight < restoreHeight)? 1000 : 10
|
||||
|
||||
if(currHeight > splashCounter + increment){
|
||||
splashCounter = currHeight
|
||||
leftPanel.progressBar.updateProgress(currHeight,currentWallet.daemonBlockChainTargetHeight());
|
||||
}
|
||||
leftPanel.progressBar.updateProgress(blockHeight,targetHeight, blocksToSync);
|
||||
foundNewBlock = true;
|
||||
}
|
||||
|
||||
function onWalletMoneyReceived(txId, amount) {
|
||||
@@ -382,6 +453,12 @@ ApplicationWindow {
|
||||
currentWallet.history.refresh() // this will refresh model
|
||||
}
|
||||
|
||||
function onWalletUnconfirmedMoneyReceived(txId, amount) {
|
||||
// refresh history
|
||||
console.log("unconfirmed money found")
|
||||
currentWallet.history.refresh()
|
||||
}
|
||||
|
||||
function onWalletMoneySent(txId, amount) {
|
||||
// refresh transaction history here
|
||||
currentWallet.refresh()
|
||||
@@ -403,7 +480,7 @@ ApplicationWindow {
|
||||
if (transaction.status !== PendingTransaction.Status_Ok) {
|
||||
console.error("Can't create transaction: ", transaction.errorString);
|
||||
informationPopup.title = qsTr("Error") + translationManager.emptyString;
|
||||
if (currentWallet.connected == Wallet.ConnectionStatus_WrongVersion)
|
||||
if (currentWallet.connected() == Wallet.ConnectionStatus_WrongVersion)
|
||||
informationPopup.text = qsTr("Can't create transaction: Wrong daemon version: ") + transaction.errorString
|
||||
else
|
||||
informationPopup.text = qsTr("Can't create transaction: ") + transaction.errorString
|
||||
@@ -433,7 +510,7 @@ ApplicationWindow {
|
||||
+ (paymentId === "" ? "" : (qsTr("\nPayment ID: ") + paymentId))
|
||||
+ qsTr("\n\nAmount: ") + walletManager.displayAmount(transaction.amount)
|
||||
+ qsTr("\nFee: ") + walletManager.displayAmount(transaction.fee)
|
||||
+ qsTr("\n\nMixin: ") + mixinCount
|
||||
+ qsTr("\n\nRingsize: ") + (mixinCount + 1)
|
||||
+ qsTr("\n\Number of transactions: ") + transaction.txCount
|
||||
+ (transactionDescription === "" ? "" : (qsTr("\n\nDescription: ") + transactionDescription))
|
||||
+ translationManager.emptyString
|
||||
@@ -444,7 +521,7 @@ ApplicationWindow {
|
||||
|
||||
|
||||
// called on "transfer"
|
||||
function handlePayment(address, paymentId, amount, mixinCount, priority, description) {
|
||||
function handlePayment(address, paymentId, amount, mixinCount, priority, description, createFile) {
|
||||
console.log("Creating transaction: ")
|
||||
console.log("\taddress: ", address,
|
||||
", payment_id: ", paymentId,
|
||||
@@ -463,6 +540,7 @@ ApplicationWindow {
|
||||
console.log("integer amount: ", amountxmr);
|
||||
console.log("integer unlocked",currentWallet.unlockedBalance)
|
||||
if (amountxmr <= 0) {
|
||||
hideProcessingSplash()
|
||||
informationPopup.title = qsTr("Error") + translationManager.emptyString;
|
||||
informationPopup.text = qsTr("Amount is wrong: expected number from %1 to %2")
|
||||
.arg(walletManager.displayAmount(0))
|
||||
@@ -474,8 +552,9 @@ ApplicationWindow {
|
||||
informationPopup.open()
|
||||
return;
|
||||
} else if (amountxmr > currentWallet.unlockedBalance) {
|
||||
hideProcessingSplash()
|
||||
informationPopup.title = qsTr("Error") + translationManager.emptyString;
|
||||
informationPopup.text = qsTr("insufficient funds. Unlocked balance: %1")
|
||||
informationPopup.text = qsTr("Insufficient funds. Unlocked balance: %1")
|
||||
.arg(walletManager.displayAmount(currentWallet.unlockedBalance))
|
||||
+ translationManager.emptyString
|
||||
|
||||
@@ -492,6 +571,24 @@ ApplicationWindow {
|
||||
currentWallet.createTransactionAsync(address, paymentId, amountxmr, mixinCount, priority);
|
||||
}
|
||||
|
||||
//Choose where to save transaction
|
||||
FileDialog {
|
||||
id: saveTxDialog
|
||||
title: "Please choose a location"
|
||||
folder: "file://" +moneroAccountsDir
|
||||
selectExisting: false;
|
||||
|
||||
onAccepted: {
|
||||
handleTransactionConfirmed()
|
||||
}
|
||||
onRejected: {
|
||||
// do nothing
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
function handleSweepUnmixable() {
|
||||
console.log("Creating transaction: ")
|
||||
|
||||
@@ -532,7 +629,7 @@ ApplicationWindow {
|
||||
}
|
||||
|
||||
// called after user confirms transaction
|
||||
function handleTransactionConfirmed() {
|
||||
function handleTransactionConfirmed(fileName) {
|
||||
// grab transaction.txid before commit, since it clears it.
|
||||
// we actually need to copy it, because QML will incredibly
|
||||
// call the function multiple times when the variable is used
|
||||
@@ -543,6 +640,20 @@ ApplicationWindow {
|
||||
for (var i = 0; i < txid_org.length; ++i)
|
||||
txid[i] = txid_org[i]
|
||||
|
||||
// View only wallet - we save the tx
|
||||
if(viewOnly && saveTxDialog.fileUrl){
|
||||
// No file specified - abort
|
||||
if(!saveTxDialog.fileUrl) {
|
||||
currentWallet.disposeTransaction(transaction)
|
||||
return;
|
||||
}
|
||||
|
||||
var path = walletManager.urlToLocalPath(saveTxDialog.fileUrl)
|
||||
|
||||
// Store to file
|
||||
transaction.setFilename(path);
|
||||
}
|
||||
|
||||
if (!transaction.commit()) {
|
||||
console.log("Error committing transaction: " + transaction.errorString);
|
||||
informationPopup.title = qsTr("Error") + translationManager.emptyString
|
||||
@@ -555,12 +666,16 @@ ApplicationWindow {
|
||||
txid_text += ", "
|
||||
txid_text += txid[i]
|
||||
}
|
||||
informationPopup.text = qsTr("Money sent successfully: %1 transaction(s) ").arg(txid.length) + txid_text + translationManager.emptyString
|
||||
informationPopup.text = (viewOnly)? qsTr("Transaction saved to file: %1").arg(path) : qsTr("Money sent successfully: %1 transaction(s) ").arg(txid.length) + txid_text + translationManager.emptyString
|
||||
informationPopup.icon = StandardIcon.Information
|
||||
if (transactionDescription.length > 0) {
|
||||
for (var i = 0; i < txid.length; ++i)
|
||||
currentWallet.setUserNote(txid[i], transactionDescription);
|
||||
}
|
||||
|
||||
// Clear tx fields
|
||||
middlePanel.transferView.clearFields()
|
||||
|
||||
}
|
||||
informationPopup.onCloseCallback = null
|
||||
informationPopup.open()
|
||||
@@ -582,6 +697,7 @@ ApplicationWindow {
|
||||
informationPopup.title = qsTr("Error") + translationManager.emptyString;
|
||||
informationPopup.text = "internal error";
|
||||
informationPopup.icon = StandardIcon.Critical
|
||||
informationPopup.onCloseCallback = null
|
||||
informationPopup.open()
|
||||
return
|
||||
}
|
||||
@@ -600,7 +716,7 @@ ApplicationWindow {
|
||||
else {
|
||||
var dCurrentBlock = currentWallet.daemonBlockChainHeight();
|
||||
var confirmations = dCurrentBlock - height
|
||||
informationPopup.text = qsTr("This address received %1 monero, with %2 confirmations").arg(received).arg(confirmations);
|
||||
informationPopup.text = qsTr("This address received %1 monero, with %2 confirmation(s).").arg(received).arg(confirmations);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -615,6 +731,11 @@ ApplicationWindow {
|
||||
informationPopup.open()
|
||||
}
|
||||
|
||||
function updateSyncing(syncing) {
|
||||
var text = (syncing ? qsTr("Balance (syncing)") : qsTr("Balance")) + translationManager.emptyString
|
||||
leftPanel.balanceLabelText = text
|
||||
middlePanel.balanceLabelText = text
|
||||
}
|
||||
|
||||
// blocks UI if wallet can't be opened or no connection to the daemon
|
||||
function enableUI(enable) {
|
||||
@@ -640,14 +761,14 @@ ApplicationWindow {
|
||||
// close wallet and show wizard
|
||||
function showWizard(){
|
||||
walletInitialized = false;
|
||||
splashCounter = 0;
|
||||
closeWallet();
|
||||
currentWallet = undefined;
|
||||
wizard.restart();
|
||||
rootItem.state = "wizard"
|
||||
// reset balance
|
||||
leftPanel.balanceText = leftPanel.unlockedBalanceText = walletManager.displayAmount(0);
|
||||
}
|
||||
|
||||
|
||||
objectName: "appWindow"
|
||||
visible: true
|
||||
width: rightPanelExpanded ? 1269 : 1269 - 300
|
||||
@@ -682,8 +803,24 @@ ApplicationWindow {
|
||||
walletManager.walletClosed.connect(onWalletClosed);
|
||||
|
||||
daemonManager.daemonStarted.connect(onDaemonStarted);
|
||||
daemonManager.daemonStartFailure.connect(onDaemonStartFailure);
|
||||
daemonManager.daemonStopped.connect(onDaemonStopped);
|
||||
|
||||
// Connect app exit to qml window exit handling
|
||||
mainApp.closing.connect(appWindow.close);
|
||||
|
||||
if( appWindow.qrScannerEnabled ){
|
||||
console.log("qrScannerEnabled : load component QRCodeScanner");
|
||||
var component = Qt.createComponent("components/QRCodeScanner.qml");
|
||||
if (component.status == Component.Ready) {
|
||||
console.log("Camera component ready");
|
||||
cameraUi = component.createObject(appWindow);
|
||||
} else {
|
||||
console.log("component not READY !!!");
|
||||
appWindow.qrScannerEnabled = false;
|
||||
}
|
||||
} else console.log("qrScannerEnabled disabled");
|
||||
|
||||
if(!walletsFound()) {
|
||||
rootItem.state = "wizard"
|
||||
} else {
|
||||
@@ -691,6 +828,7 @@ ApplicationWindow {
|
||||
initialize(persistentSettings);
|
||||
}
|
||||
|
||||
checkUpdates();
|
||||
}
|
||||
|
||||
onRightPanelExpandedChanged: {
|
||||
@@ -709,6 +847,7 @@ ApplicationWindow {
|
||||
property bool auto_donations_enabled : false
|
||||
property int auto_donations_amount : 50
|
||||
property bool allow_background_mining : false
|
||||
property bool miningIgnoreBattery : true
|
||||
property bool testnet: false
|
||||
property string daemon_address: "localhost:18081"
|
||||
property string payment_id
|
||||
@@ -716,6 +855,11 @@ ApplicationWindow {
|
||||
property bool is_recovering : false
|
||||
property bool customDecorations : true
|
||||
property string daemonFlags
|
||||
property int logLevel: 0
|
||||
property string logCategories: ""
|
||||
property string daemonUsername: ""
|
||||
property string daemonPassword: ""
|
||||
property bool transferShowAdvanced: false
|
||||
}
|
||||
|
||||
// Information dialog
|
||||
@@ -736,10 +880,31 @@ ApplicationWindow {
|
||||
id: transactionConfirmationPopup
|
||||
onAccepted: {
|
||||
close();
|
||||
handleTransactionConfirmed()
|
||||
|
||||
// Save transaction to file if view only wallet
|
||||
if(viewOnly) {
|
||||
saveTxDialog.open();
|
||||
return;
|
||||
} else
|
||||
handleTransactionConfirmed()
|
||||
}
|
||||
}
|
||||
|
||||
StandardDialog {
|
||||
id: confirmationDialog
|
||||
property var onAcceptedCallback
|
||||
property var onRejectedCallback
|
||||
onAccepted: {
|
||||
if (onAcceptedCallback)
|
||||
onAcceptedCallback()
|
||||
}
|
||||
onRejected: {
|
||||
if (onRejectedCallback)
|
||||
onRejectedCallback();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//Open Wallet from file
|
||||
FileDialog {
|
||||
id: fileDialog
|
||||
@@ -773,6 +938,9 @@ ApplicationWindow {
|
||||
|
||||
DaemonManagerDialog {
|
||||
id: daemonManagerDialog
|
||||
onRejected: {
|
||||
loadPage("Settings");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -785,8 +953,6 @@ ApplicationWindow {
|
||||
messageText: qsTr("Please wait...")
|
||||
}
|
||||
|
||||
|
||||
|
||||
Item {
|
||||
id: rootItem
|
||||
anchors.fill: parent
|
||||
@@ -802,7 +968,7 @@ ApplicationWindow {
|
||||
PropertyChanges { target: titleBar; basicButtonVisible: false }
|
||||
PropertyChanges { target: wizard; visible: true }
|
||||
PropertyChanges { target: appWindow; width: 930; }
|
||||
PropertyChanges { target: appWindow; height: 595; }
|
||||
PropertyChanges { target: appWindow; height: 650; }
|
||||
PropertyChanges { target: resizeArea; visible: false }
|
||||
PropertyChanges { target: titleBar; maximizeButtonVisible: false }
|
||||
PropertyChanges { target: frameArea; blocked: true }
|
||||
@@ -838,7 +1004,7 @@ ApplicationWindow {
|
||||
onTxkeyClicked: middlePanel.state = "TxKey"
|
||||
onHistoryClicked: middlePanel.state = "History"
|
||||
onAddressBookClicked: middlePanel.state = "AddressBook"
|
||||
onMiningClicked: middlePanel.state = "Minning"
|
||||
onMiningClicked: middlePanel.state = "Mining"
|
||||
onSignClicked: middlePanel.state = "Sign"
|
||||
onSettingsClicked: middlePanel.state = "Settings"
|
||||
}
|
||||
@@ -906,19 +1072,15 @@ ApplicationWindow {
|
||||
properties: "visible"
|
||||
value: false
|
||||
}
|
||||
NumberAnimation {
|
||||
PropertyAction {
|
||||
target: appWindow
|
||||
properties: "height"
|
||||
to: 30
|
||||
easing.type: Easing.InCubic
|
||||
duration: 200
|
||||
value: 30
|
||||
}
|
||||
NumberAnimation {
|
||||
PropertyAction {
|
||||
target: appWindow
|
||||
properties: "width"
|
||||
to: 470
|
||||
easing.type: Easing.InCubic
|
||||
duration: 200
|
||||
value: 470
|
||||
}
|
||||
PropertyAction {
|
||||
targets: [leftPanel, rightPanel]
|
||||
@@ -931,12 +1093,10 @@ ApplicationWindow {
|
||||
value: true
|
||||
}
|
||||
|
||||
NumberAnimation {
|
||||
PropertyAction {
|
||||
target: appWindow
|
||||
properties: "height"
|
||||
to: middlePanel.height
|
||||
easing.type: Easing.InCubic
|
||||
duration: 200
|
||||
value: middlePanel.height
|
||||
}
|
||||
|
||||
onStopped: {
|
||||
@@ -948,12 +1108,10 @@ ApplicationWindow {
|
||||
|
||||
SequentialAnimation {
|
||||
id: goToProAnimation
|
||||
NumberAnimation {
|
||||
PropertyAction {
|
||||
target: appWindow
|
||||
properties: "height"
|
||||
to: 30
|
||||
easing.type: Easing.InCubic
|
||||
duration: 200
|
||||
value: 30
|
||||
}
|
||||
PropertyAction {
|
||||
target: middlePanel
|
||||
@@ -965,19 +1123,15 @@ ApplicationWindow {
|
||||
properties: "visible"
|
||||
value: true
|
||||
}
|
||||
NumberAnimation {
|
||||
PropertyAction {
|
||||
target: appWindow
|
||||
properties: "width"
|
||||
to: rightPanelExpanded ? 1269 : 1269 - 300
|
||||
easing.type: Easing.InCubic
|
||||
duration: 200
|
||||
value: rightPanelExpanded ? 1269 : 1269 - 300
|
||||
}
|
||||
NumberAnimation {
|
||||
PropertyAction {
|
||||
target: appWindow
|
||||
properties: "height"
|
||||
to: maxWindowHeight
|
||||
easing.type: Easing.InCubic
|
||||
duration: 200
|
||||
value: maxWindowHeight
|
||||
}
|
||||
PropertyAction {
|
||||
target: frameArea
|
||||
@@ -1004,7 +1158,7 @@ ApplicationWindow {
|
||||
}
|
||||
}
|
||||
|
||||
property int maxWidth: leftPanel.width + 655 + rightPanel.width
|
||||
property int minWidth: 326
|
||||
property int minHeight: 720
|
||||
MouseArea {
|
||||
id: resizeArea
|
||||
@@ -1038,9 +1192,9 @@ ApplicationWindow {
|
||||
var dx = previousPosition.x - pos.x
|
||||
var dy = previousPosition.y - pos.y
|
||||
|
||||
if(appWindow.width - dx > parent.maxWidth)
|
||||
if(appWindow.width - dx > parent.minWidth)
|
||||
appWindow.width -= dx
|
||||
else appWindow.width = parent.maxWidth
|
||||
else appWindow.width = parent.minWidth
|
||||
|
||||
if(appWindow.height - dy > parent.minHeight)
|
||||
appWindow.height -= dy
|
||||
@@ -1111,16 +1265,72 @@ ApplicationWindow {
|
||||
lineHeight: 0.7
|
||||
font.family: "Arial"
|
||||
font.pixelSize: 12
|
||||
font.letterSpacing: -1
|
||||
color: "#FFFFFF"
|
||||
}
|
||||
}
|
||||
|
||||
Notifier {
|
||||
id: notifier
|
||||
}
|
||||
}
|
||||
|
||||
onClosing: {
|
||||
// Close wallet non async on exit
|
||||
walletManager.closeWallet();
|
||||
// Stop daemon
|
||||
daemonManager.stop();
|
||||
|
||||
// If daemon is running - prompt user before exiting
|
||||
if(typeof daemonManager != undefined && daemonManager.running(persistentSettings.testnet)) {
|
||||
close.accepted = false;
|
||||
|
||||
// Show confirmation dialog
|
||||
confirmationDialog.title = qsTr("Daemon is running") + translationManager.emptyString;
|
||||
confirmationDialog.text = qsTr("Daemon will still be running in background when GUI is closed.");
|
||||
confirmationDialog.icon = StandardIcon.Question
|
||||
confirmationDialog.cancelText = qsTr("Stop daemon")
|
||||
confirmationDialog.onAcceptedCallback = function() {
|
||||
closeAccepted();
|
||||
}
|
||||
|
||||
confirmationDialog.onRejectedCallback = function() {
|
||||
daemonManager.stop(persistentSettings.testnet);
|
||||
closeAccepted();
|
||||
};
|
||||
|
||||
confirmationDialog.open()
|
||||
|
||||
} else {
|
||||
closeAccepted();
|
||||
}
|
||||
}
|
||||
|
||||
function closeAccepted(){
|
||||
// Close wallet non async on exit
|
||||
daemonManager.exit();
|
||||
walletManager.closeWallet();
|
||||
Qt.quit();
|
||||
}
|
||||
|
||||
function checkUpdates() {
|
||||
var update = walletManager.checkUpdates("monero-gui", "gui")
|
||||
if (update === "")
|
||||
return
|
||||
print("Update found: " + update)
|
||||
var parts = update.split("|")
|
||||
if (parts.length == 4) {
|
||||
var version = parts[0]
|
||||
var hash = parts[1]
|
||||
var user_url = parts[2]
|
||||
var auto_url = parts[3]
|
||||
var msg = qsTr("New version of monero-wallet-gui is available: %1<br>%2").arg(version).arg(user_url) + translationManager.emptyString
|
||||
notifier.show(msg)
|
||||
}
|
||||
else {
|
||||
print("Failed to parse update spec")
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: updatesTimer
|
||||
interval: 3600*1000; running: true; repeat: true
|
||||
onTriggered: checkUpdates()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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,112 @@ 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
|
||||
}
|
||||
|
||||
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 \
|
||||
-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 +213,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 +235,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 +253,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 \
|
||||
@@ -176,16 +280,22 @@ macx {
|
||||
# translation stuff
|
||||
TRANSLATIONS = \ # English is default language, no explicit translation file
|
||||
$$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_zh-cn.ts \ # Chinese (Simplified-China)
|
||||
$$PWD/translations/monero-core_zh-tw.ts \ # Chinese (Traditional-Taiwan)
|
||||
|
||||
CONFIG(release, debug|release) {
|
||||
DESTDIR = release/bin
|
||||
@@ -195,7 +305,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 +317,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,
|
||||
@@ -261,10 +375,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 +389,8 @@ OTHER_FILES += \
|
||||
$$TRANSLATIONS
|
||||
|
||||
DISTFILES += \
|
||||
notes.txt
|
||||
notes.txt \
|
||||
monero/src/wallet/CMakeLists.txt
|
||||
|
||||
|
||||
# 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,40 @@ 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 {
|
||||
@@ -93,6 +114,7 @@ Rectangle {
|
||||
anchors.leftMargin: 17
|
||||
anchors.rightMargin: 17
|
||||
anchors.topMargin: 5
|
||||
placeholderText: qsTr("Paste 64 hexadecimal characters") + translationManager.emptyString
|
||||
}
|
||||
|
||||
Label {
|
||||
@@ -101,7 +123,7 @@ 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
|
||||
}
|
||||
@@ -114,44 +136,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 +302,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)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -244,7 +244,7 @@ Rectangle {
|
||||
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
|
||||
}
|
||||
@@ -270,7 +270,7 @@ Rectangle {
|
||||
anchors.left: toDatePicker.right
|
||||
anchors.leftMargin: 17
|
||||
width: 60
|
||||
text: qsTr("FILTER")
|
||||
text: qsTr("Filter") + translationManager.emptyString
|
||||
shadowReleasedColor: "#4D0051"
|
||||
shadowPressedColor: "#2D002F"
|
||||
releasedColor: "#6B0072"
|
||||
@@ -307,7 +307,7 @@ Rectangle {
|
||||
|
||||
CheckBox {
|
||||
id: advancedFilteringCheckBox
|
||||
text: qsTr("Advanced filtering")
|
||||
text: qsTr("Advanced filtering") + translationManager.emptyString
|
||||
anchors.left: filterButton.right
|
||||
anchors.bottom: filterButton.bottom
|
||||
anchors.leftMargin: 17
|
||||
@@ -333,9 +333,9 @@ Rectangle {
|
||||
|
||||
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 }
|
||||
|
||||
}
|
||||
|
||||
@@ -393,7 +393,7 @@ Rectangle {
|
||||
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
|
||||
}
|
||||
@@ -540,6 +540,11 @@ Rectangle {
|
||||
anchors.rightMargin: 14
|
||||
onContentYChanged: flickableScroll.flickableContentYChanged()
|
||||
model: root.model
|
||||
addressBookModel: null
|
||||
}
|
||||
}
|
||||
|
||||
function onPageCompleted() {
|
||||
table.addressBookModel = appWindow.currentWallet ? appWindow.currentWallet.addressBookModel : null
|
||||
}
|
||||
}
|
||||
|
||||
210
pages/Mining.qml
@@ -27,8 +27,214 @@
|
||||
// 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
|
||||
|
||||
function isDaemonLocal() {
|
||||
var daemonAddress = appWindow.persistentSettings.daemon_address
|
||||
if (daemonAddress === "")
|
||||
return false
|
||||
var daemonHost = daemonAddress.split(":")[0]
|
||||
if (daemonHost === "127.0.0.1" || daemonHost === "localhost")
|
||||
return true
|
||||
return false
|
||||
}
|
||||
|
||||
/* main layout */
|
||||
ColumnLayout {
|
||||
id: mainLayout
|
||||
anchors.margins: 40
|
||||
anchors.bottomMargin: 10
|
||||
|
||||
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 {
|
||||
// Disable this option until stable
|
||||
visible: false
|
||||
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
|
||||
anchors.topMargin: 17
|
||||
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,8 @@ Rectangle {
|
||||
/* main layout */
|
||||
ColumnLayout {
|
||||
id: mainLayout
|
||||
anchors.margins: 40
|
||||
anchors.margins: 17
|
||||
anchors.topMargin: 40
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.top
|
||||
anchors.right: parent.right
|
||||
@@ -203,39 +211,6 @@ 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 {
|
||||
id: paymentIdRow
|
||||
Label {
|
||||
@@ -249,7 +224,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,17 +244,57 @@ 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("")
|
||||
}
|
||||
}
|
||||
|
||||
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("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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -296,7 +311,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 +373,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 +408,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 +429,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,51 +39,22 @@ import moneroComponents.Clipboard 1.0
|
||||
|
||||
Rectangle {
|
||||
property var daemonAddress
|
||||
property bool viewOnly: false
|
||||
|
||||
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
|
||||
@@ -92,83 +63,18 @@ Rectangle {
|
||||
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
|
||||
@@ -176,97 +82,8 @@ Rectangle {
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
StandardButton {
|
||||
id: closeWalletButton
|
||||
|
||||
// Layout.leftMargin: 30
|
||||
// Layout.minimumWidth: 100
|
||||
width: 100
|
||||
text: qsTr("Close wallet") + translationManager.emptyString
|
||||
shadowReleasedColor: "#FF4304"
|
||||
shadowPressedColor: "#B32D00"
|
||||
@@ -278,21 +95,60 @@ 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") + translationManager.emptyString
|
||||
onClicked: {
|
||||
settingsPasswordDialog.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"
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
id: daemonStatusRow
|
||||
Layout.fillWidth: true
|
||||
|
||||
StandardButton {
|
||||
visible: true
|
||||
enabled: !appWindow.daemonRunning
|
||||
id: startDaemonButton
|
||||
width: 110
|
||||
text: qsTr("Start daemon") + translationManager.emptyString
|
||||
shadowReleasedColor: "#FF4304"
|
||||
shadowPressedColor: "#B32D00"
|
||||
@@ -307,7 +163,6 @@ Rectangle {
|
||||
visible: true
|
||||
enabled: appWindow.daemonRunning
|
||||
id: stopDaemonButton
|
||||
width: 110
|
||||
text: qsTr("Stop daemon") + translationManager.emptyString
|
||||
shadowReleasedColor: "#FF4304"
|
||||
shadowPressedColor: "#B32D00"
|
||||
@@ -320,19 +175,20 @@ 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 {
|
||||
@@ -352,6 +208,109 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
id: daemonAddrRow
|
||||
Layout.fillWidth: true
|
||||
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") + translationManager.emptyString
|
||||
}
|
||||
|
||||
|
||||
LineEdit {
|
||||
id: daemonPort
|
||||
Layout.preferredWidth: 100
|
||||
Layout.fillWidth: true
|
||||
text: (daemonAddress !== undefined) ? daemonAddress[1] : "18081"
|
||||
placeholderText: qsTr("Port") + translationManager.emptyString
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
|
||||
Label {
|
||||
id: daemonLoginLabel
|
||||
Layout.fillWidth: true
|
||||
color: "#4A4949"
|
||||
text: qsTr("Login (optional)") + translationManager.emptyString
|
||||
fontSize: 16
|
||||
}
|
||||
|
||||
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"
|
||||
visible: true
|
||||
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,6 +322,65 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
|
||||
// Log level
|
||||
RowLayout {
|
||||
Label {
|
||||
id: logLevelLabel
|
||||
color: "#4A4949"
|
||||
text: qsTr("Log level") + translationManager.emptyString
|
||||
fontSize: 16
|
||||
}
|
||||
|
||||
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("Version") + translationManager.emptyString
|
||||
fontSize: 16
|
||||
anchors.topMargin: 30
|
||||
Layout.topMargin: 30
|
||||
}
|
||||
}
|
||||
Rectangle {
|
||||
Layout.fillWidth: true
|
||||
height: 1
|
||||
color: "#DEDEDE"
|
||||
}
|
||||
|
||||
Label {
|
||||
id: guiVersion
|
||||
Layout.topMargin: 8
|
||||
@@ -377,26 +395,54 @@ Rectangle {
|
||||
text: qsTr("Embedded Monero version: ") + Version.GUI_MONERO_VERSION + translationManager.emptyString
|
||||
fontSize: 16
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 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){
|
||||
informationPopup.title = qsTr("Wallet mnemonic seed") + translationManager.emptyString;
|
||||
informationPopup.text = currentWallet.seed
|
||||
informationPopup.open()
|
||||
informationPopup.onCloseCallback = function() {
|
||||
informationPopup.text = ""
|
||||
}
|
||||
|
||||
} else {
|
||||
informationPopup.title = qsTr("Error") + translationManager.emptyString;
|
||||
informationPopup.text = qsTr("Wrong password");
|
||||
informationPopup.open()
|
||||
informationPopup.onCloseCallback = function() {
|
||||
settingsPasswordDialog.open()
|
||||
}
|
||||
}
|
||||
|
||||
settingsPasswordDialog.password = ""
|
||||
}
|
||||
onRejected: {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// fires on every page load
|
||||
function onPageCompleted() {
|
||||
console.log("Settings page loaded");
|
||||
initSettings();
|
||||
viewOnly = currentWallet.viewOnly;
|
||||
appWindow.daemonRunning = daemonManager.running(persistentSettings.testnet)
|
||||
}
|
||||
|
||||
// fires only once
|
||||
|
||||
@@ -164,7 +164,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 +192,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 +205,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 +239,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"
|
||||
@@ -349,7 +349,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 +377,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 +390,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 +423,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"
|
||||
|
||||
@@ -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,313 @@ 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
|
||||
Label {
|
||||
id: transactionPriority
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 17
|
||||
fontSize: 14
|
||||
x: (parent.width - 17) / 2 + 17
|
||||
text: qsTr("Transaction priority") + 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"
|
||||
}
|
||||
}
|
||||
|
||||
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)"
|
||||
}
|
||||
}
|
||||
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
|
||||
|
||||
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 }
|
||||
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"
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
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: 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
|
||||
}
|
||||
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 }
|
||||
|
||||
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))
|
||||
}
|
||||
}
|
||||
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 }
|
||||
}
|
||||
|
||||
// Priorites after v5
|
||||
ListModel {
|
||||
id: priorityModelV5
|
||||
|
||||
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")
|
||||
}
|
||||
ListElement { column1: qsTr("Low (x1 fee)") ; column2: ""; priority: 1}
|
||||
ListElement { column1: qsTr("Default (x4 fee)") ; column2: ""; priority: 2 }
|
||||
ListElement { column1: qsTr("Medium (x20 fee)") ; column2: ""; priority: 3 }
|
||||
ListElement { column1: qsTr("High (x166 fee)") ; column2: ""; priority: 4 }
|
||||
|
||||
}
|
||||
|
||||
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
|
||||
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
|
||||
}
|
||||
|
||||
onLinkActivated: appWindow.showPageRequest("AddressBook")
|
||||
}
|
||||
// recipient address input
|
||||
RowLayout {
|
||||
id: addressLineRow
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: addressLabel.bottom
|
||||
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
|
||||
|
||||
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 }
|
||||
}
|
||||
onLinkActivated: appWindow.showPageRequest("AddressBook")
|
||||
}
|
||||
// recipient address input
|
||||
RowLayout {
|
||||
id: addressLineRow
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: addressLabel.bottom
|
||||
|
||||
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"))
|
||||
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 +424,263 @@ 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 {
|
||||
// Label {
|
||||
// id: manageWalletLabel
|
||||
// Layout.fillWidth: true
|
||||
// color: "#4A4949"
|
||||
// text: qsTr("Advanced options") + translationManager.emptyString
|
||||
// fontSize: 16
|
||||
// Layout.topMargin: 20
|
||||
// }
|
||||
|
||||
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()
|
||||
}
|
||||
|
||||
|
||||
RowLayout {
|
||||
visible: persistentSettings.transferShowAdvanced
|
||||
Layout.topMargin: 50
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
StandardButton {
|
||||
id: rescanSpentButton
|
||||
text: qsTr("Rescan spent") + translationManager.emptyString
|
||||
shadowReleasedColor: "#FF4304"
|
||||
shadowPressedColor: "#B32D00"
|
||||
releasedColor: "#FF6C3C"
|
||||
pressedColor: "#FF4304"
|
||||
enabled: pageRoot.enabled
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
//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 +709,38 @@ Rectangle {
|
||||
function onPageCompleted() {
|
||||
console.log("transfer page loaded")
|
||||
updateStatus();
|
||||
updateMixin();
|
||||
updatePriorityDropdown()
|
||||
}
|
||||
|
||||
function updatePriorityDropdown() {
|
||||
// Use new fee multipliers after v5 fork
|
||||
if (typeof currentWallet != "undefined" && currentWallet.useForkRules(5)) {
|
||||
priorityDropdown.dataModel = priorityModelV5;
|
||||
priorityDropdown.currentIndex = 1
|
||||
} else {
|
||||
priorityDropdown.dataModel = priorityModel;
|
||||
priorityDropdown.currentIndex = 0
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//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
|
||||
|
||||
@@ -209,7 +209,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"
|
||||
|
||||
16
qml.qrc
@@ -100,13 +100,24 @@
|
||||
<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/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/taiwan.png</file>
|
||||
<file>lang/flags/uk.png</file>
|
||||
<file>lang/flags/usa.png</file>
|
||||
<file>lang/flags/indonesia.png</file>
|
||||
<file>wizard/WizardManageWalletUI.qml</file>
|
||||
<file>wizard/WizardRecoveryWallet.qml</file>
|
||||
<file>wizard/WizardMemoTextInput.qml</file>
|
||||
@@ -122,5 +133,10 @@
|
||||
<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>
|
||||
</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,11 @@
|
||||
#include <QtConcurrent/QtConcurrent>
|
||||
#include <QApplication>
|
||||
#include <QProcess>
|
||||
#include <QTime>
|
||||
|
||||
namespace {
|
||||
static const int DAEMON_START_TIMEOUT_SECONDS = 30;
|
||||
}
|
||||
|
||||
DaemonManager * DaemonManager::m_instance = nullptr;
|
||||
QStringList DaemonManager::m_clArgs;
|
||||
@@ -23,24 +28,19 @@ DaemonManager *DaemonManager::instance(const QStringList *args)
|
||||
return m_instance;
|
||||
}
|
||||
|
||||
bool DaemonManager::start(const QString &flags)
|
||||
bool DaemonManager::start(const QString &flags, bool testnet)
|
||||
{
|
||||
//
|
||||
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 +54,9 @@ bool DaemonManager::start(const QString &flags)
|
||||
arguments << str;
|
||||
}
|
||||
|
||||
arguments << "--check-updates" << "disabled";
|
||||
|
||||
qDebug() << "starting monerod " + process;
|
||||
qDebug() << "starting monerod " + m_monerod;
|
||||
qDebug() << "With command line arguments " << arguments;
|
||||
|
||||
m_daemon = new QProcess();
|
||||
@@ -66,33 +67,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 +191,62 @@ 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;
|
||||
QString external_cmd = m_monerod + " " + cmd;
|
||||
qDebug() << "sending external cmd: " << external_cmd;
|
||||
|
||||
// Add testnet flag if needed
|
||||
if (testnet)
|
||||
external_cmd += " --testnet";
|
||||
external_cmd += "\n";
|
||||
|
||||
p.start(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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,30 +13,40 @@ 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);
|
||||
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();
|
||||
|
||||
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,14 @@ QList<TransactionInfo *> TransactionHistory::getAll() const
|
||||
if (ti->timestamp() <= firstDateTime) {
|
||||
firstDateTime = ti->timestamp();
|
||||
}
|
||||
// store last tx height
|
||||
if (ti->confirmations() < 10 && ti->blockHeight() >= lastTxHeight ){
|
||||
lastTxHeight = ti->blockHeight();
|
||||
// TODO: Fetch block time and confirmations needed from wallet2?
|
||||
m_minutesToUnlock = (10 - ti->confirmations()) * 2;
|
||||
m_locked = true;
|
||||
}
|
||||
|
||||
}
|
||||
emit refreshFinished();
|
||||
|
||||
@@ -81,9 +91,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)
|
||||
|
||||
@@ -17,6 +17,8 @@ class TransactionHistory : public QObject
|
||||
Q_PROPERTY(int count READ count)
|
||||
Q_PROPERTY(QDateTime firstDateTime READ firstDateTime NOTIFY firstDateTimeChanged)
|
||||
Q_PROPERTY(QDateTime lastDateTime READ lastDateTime NOTIFY lastDateTimeChanged)
|
||||
Q_PROPERTY(int minutesToUnlock READ minutesToUnlock)
|
||||
Q_PROPERTY(bool locked READ locked)
|
||||
|
||||
public:
|
||||
Q_INVOKABLE TransactionInfo *transaction(int index);
|
||||
@@ -26,6 +28,8 @@ public:
|
||||
quint64 count() const;
|
||||
QDateTime firstDateTime() const;
|
||||
QDateTime lastDateTime() const;
|
||||
quint64 minutesToUnlock() const;
|
||||
bool locked() const;
|
||||
|
||||
signals:
|
||||
void refreshStarted() const;
|
||||
@@ -45,6 +49,9 @@ private:
|
||||
mutable QList<TransactionInfo*> m_tinfo;
|
||||
mutable QDateTime m_firstDateTime;
|
||||
mutable QDateTime m_lastDateTime;
|
||||
mutable int m_minutesToUnlock;
|
||||
// history contains locked transfers
|
||||
mutable bool m_locked;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -46,6 +46,11 @@ quint64 TransactionInfo::blockHeight() const
|
||||
return m_pimpl->blockHeight();
|
||||
}
|
||||
|
||||
quint64 TransactionInfo::confirmations() const
|
||||
{
|
||||
return m_pimpl->confirmations();
|
||||
}
|
||||
|
||||
QString TransactionInfo::hash() const
|
||||
{
|
||||
return QString::fromStdString(m_pimpl->hash());
|
||||
|
||||
@@ -18,6 +18,7 @@ class TransactionInfo : public QObject
|
||||
Q_PROPERTY(QString displayAmount READ displayAmount)
|
||||
Q_PROPERTY(QString fee READ fee)
|
||||
Q_PROPERTY(quint64 blockHeight READ blockHeight)
|
||||
Q_PROPERTY(quint64 confirmations READ confirmations)
|
||||
Q_PROPERTY(QString hash READ hash)
|
||||
Q_PROPERTY(QDateTime timestamp READ timestamp)
|
||||
Q_PROPERTY(QString date READ date)
|
||||
@@ -42,6 +43,7 @@ public:
|
||||
QString displayAmount() const;
|
||||
QString fee() const;
|
||||
quint64 blockHeight() const;
|
||||
quint64 confirmations() const;
|
||||
//! transaction_id
|
||||
QString hash() const;
|
||||
QDateTime timestamp() const;
|
||||
|
||||
92
src/libwalletqt/UnsignedTransaction.cpp
Normal file
@@ -0,0 +1,92 @@
|
||||
#include "UnsignedTransaction.h"
|
||||
#include <QVector>
|
||||
#include <QDebug>
|
||||
|
||||
UnsignedTransaction::Status UnsignedTransaction::status() const
|
||||
{
|
||||
return static_cast<Status>(m_pimpl->status());
|
||||
}
|
||||
|
||||
QString UnsignedTransaction::errorString() const
|
||||
{
|
||||
return QString::fromStdString(m_pimpl->errorString());
|
||||
}
|
||||
|
||||
quint64 UnsignedTransaction::amount(int index) const
|
||||
{
|
||||
std::vector<uint64_t> arr = m_pimpl->amount();
|
||||
if(index > arr.size() - 1)
|
||||
return 0;
|
||||
return arr[index];
|
||||
}
|
||||
|
||||
quint64 UnsignedTransaction::fee(int index) const
|
||||
{
|
||||
std::vector<uint64_t> arr = m_pimpl->fee();
|
||||
if(index > arr.size() - 1)
|
||||
return 0;
|
||||
return arr[index];
|
||||
}
|
||||
|
||||
quint64 UnsignedTransaction::mixin(int index) const
|
||||
{
|
||||
std::vector<uint64_t> arr = m_pimpl->mixin();
|
||||
if(index > arr.size() - 1)
|
||||
return 0;
|
||||
return arr[index];
|
||||
}
|
||||
|
||||
quint64 UnsignedTransaction::txCount() const
|
||||
{
|
||||
return m_pimpl->txCount();
|
||||
}
|
||||
|
||||
quint64 UnsignedTransaction::minMixinCount() const
|
||||
{
|
||||
return m_pimpl->minMixinCount();
|
||||
}
|
||||
|
||||
QString UnsignedTransaction::confirmationMessage() const
|
||||
{
|
||||
return QString::fromStdString(m_pimpl->confirmationMessage());
|
||||
}
|
||||
|
||||
QStringList UnsignedTransaction::paymentId() const
|
||||
{
|
||||
QList<QString> list;
|
||||
for (const auto &t: m_pimpl->paymentId())
|
||||
list.append(QString::fromStdString(t));
|
||||
return list;
|
||||
}
|
||||
|
||||
QStringList UnsignedTransaction::recipientAddress() const
|
||||
{
|
||||
QList<QString> list;
|
||||
for (const auto &t: m_pimpl->recipientAddress())
|
||||
list.append(QString::fromStdString(t));
|
||||
return list;
|
||||
}
|
||||
|
||||
bool UnsignedTransaction::sign(const QString &fileName) const
|
||||
{
|
||||
if(!m_pimpl->sign(fileName.toStdString()))
|
||||
return false;
|
||||
// export key images
|
||||
return m_walletImpl->exportKeyImages(fileName.toStdString() + "_keyImages");
|
||||
}
|
||||
|
||||
void UnsignedTransaction::setFilename(const QString &fileName)
|
||||
{
|
||||
m_fileName = fileName;
|
||||
}
|
||||
|
||||
UnsignedTransaction::UnsignedTransaction(Monero::UnsignedTransaction *pt, Monero::Wallet *walletImpl, QObject *parent)
|
||||
: QObject(parent), m_pimpl(pt), m_walletImpl(walletImpl)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
UnsignedTransaction::~UnsignedTransaction()
|
||||
{
|
||||
delete m_pimpl;
|
||||
}
|
||||
59
src/libwalletqt/UnsignedTransaction.h
Normal file
@@ -0,0 +1,59 @@
|
||||
#ifndef UNSIGNEDTRANSACTION_H
|
||||
#define UNSIGNEDTRANSACTION_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include <wallet/wallet2_api.h>
|
||||
|
||||
class UnsignedTransaction : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(Status status READ status)
|
||||
Q_PROPERTY(QString errorString READ errorString)
|
||||
// Q_PROPERTY(QList<qulonglong> amount READ amount)
|
||||
// Q_PROPERTY(QList<qulonglong> fee READ fee)
|
||||
Q_PROPERTY(quint64 txCount READ txCount)
|
||||
Q_PROPERTY(QString confirmationMessage READ confirmationMessage)
|
||||
Q_PROPERTY(QStringList recipientAddress READ recipientAddress)
|
||||
Q_PROPERTY(QStringList paymentId READ paymentId)
|
||||
Q_PROPERTY(quint64 minMixinCount READ minMixinCount)
|
||||
|
||||
public:
|
||||
enum Status {
|
||||
Status_Ok = Monero::UnsignedTransaction::Status_Ok,
|
||||
Status_Error = Monero::UnsignedTransaction::Status_Error,
|
||||
Status_Critical = Monero::UnsignedTransaction::Status_Critical
|
||||
};
|
||||
Q_ENUM(Status)
|
||||
|
||||
enum Priority {
|
||||
Priority_Low = Monero::UnsignedTransaction::Priority_Low,
|
||||
Priority_Medium = Monero::UnsignedTransaction::Priority_Medium,
|
||||
Priority_High = Monero::UnsignedTransaction::Priority_High
|
||||
};
|
||||
Q_ENUM(Priority)
|
||||
|
||||
Status status() const;
|
||||
QString errorString() const;
|
||||
Q_INVOKABLE quint64 amount(int index) const;
|
||||
Q_INVOKABLE quint64 fee(int index) const;
|
||||
Q_INVOKABLE quint64 mixin(int index) const;
|
||||
QStringList recipientAddress() const;
|
||||
QStringList paymentId() const;
|
||||
quint64 txCount() const;
|
||||
QString confirmationMessage() const;
|
||||
quint64 minMixinCount() const;
|
||||
Q_INVOKABLE bool sign(const QString &fileName) const;
|
||||
Q_INVOKABLE void setFilename(const QString &fileName);
|
||||
|
||||
private:
|
||||
explicit UnsignedTransaction(Monero::UnsignedTransaction * pt, Monero::Wallet *walletImpl, QObject *parent = 0);
|
||||
~UnsignedTransaction();
|
||||
private:
|
||||
friend class Wallet;
|
||||
Monero::UnsignedTransaction * m_pimpl;
|
||||
QString m_fileName;
|
||||
Monero::Wallet * m_walletImpl;
|
||||
};
|
||||
|
||||
#endif // UNSIGNEDTRANSACTION_H
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "Wallet.h"
|
||||
#include "PendingTransaction.h"
|
||||
#include "UnsignedTransaction.h"
|
||||
#include "TransactionHistory.h"
|
||||
#include "AddressBook.h"
|
||||
#include "model/TransactionHistoryModel.h"
|
||||
@@ -15,10 +16,12 @@
|
||||
#include <QtConcurrent/QtConcurrent>
|
||||
#include <QList>
|
||||
#include <QVector>
|
||||
#include <QMutex>
|
||||
#include <QMutexLocker>
|
||||
|
||||
namespace {
|
||||
static const int DAEMON_BLOCKCHAIN_HEIGHT_CACHE_TTL_SECONDS = 10;
|
||||
static const int DAEMON_BLOCKCHAIN_TARGET_HEIGHT_CACHE_TTL_SECONDS = 60;
|
||||
static const int DAEMON_BLOCKCHAIN_HEIGHT_CACHE_TTL_SECONDS = 5;
|
||||
static const int DAEMON_BLOCKCHAIN_TARGET_HEIGHT_CACHE_TTL_SECONDS = 30;
|
||||
static const int WALLET_CONNECTION_STATUS_CACHE_TTL_SECONDS = 5;
|
||||
}
|
||||
|
||||
@@ -44,10 +47,16 @@ public:
|
||||
emit m_wallet->moneyReceived(QString::fromStdString(txId), amount);
|
||||
}
|
||||
|
||||
virtual void unconfirmedMoneyReceived(const std::string &txId, uint64_t amount)
|
||||
{
|
||||
qDebug() << __FUNCTION__;
|
||||
emit m_wallet->unconfirmedMoneyReceived(QString::fromStdString(txId), amount);
|
||||
}
|
||||
|
||||
virtual void newBlock(uint64_t height)
|
||||
{
|
||||
// qDebug() << __FUNCTION__;
|
||||
emit m_wallet->newBlock(height);
|
||||
emit m_wallet->newBlock(height, m_wallet->daemonBlockChainTargetHeight());
|
||||
}
|
||||
|
||||
virtual void updated()
|
||||
@@ -91,17 +100,41 @@ Wallet::Status Wallet::status() const
|
||||
return static_cast<Status>(m_walletImpl->status());
|
||||
}
|
||||
|
||||
Wallet::ConnectionStatus Wallet::connected() const
|
||||
bool Wallet::testnet() const
|
||||
{
|
||||
return m_walletImpl->testnet();
|
||||
}
|
||||
|
||||
|
||||
void Wallet::updateConnectionStatusAsync()
|
||||
{
|
||||
QFuture<Monero::Wallet::ConnectionStatus> future = QtConcurrent::run(m_walletImpl, &Monero::Wallet::connected);
|
||||
QFutureWatcher<Monero::Wallet::ConnectionStatus> *connectionWatcher = new QFutureWatcher<Monero::Wallet::ConnectionStatus>();
|
||||
|
||||
connect(connectionWatcher, &QFutureWatcher<Monero::Wallet::ConnectionStatus>::finished, [=]() {
|
||||
QFuture<Monero::Wallet::ConnectionStatus> future = connectionWatcher->future();
|
||||
connectionWatcher->deleteLater();
|
||||
ConnectionStatus newStatus = static_cast<ConnectionStatus>(future.result());
|
||||
if (newStatus != m_connectionStatus || !m_initialized) {
|
||||
m_initialized = true;
|
||||
m_connectionStatus = newStatus;
|
||||
qDebug() << "NEW STATUS " << newStatus;
|
||||
emit connectionStatusChanged(newStatus);
|
||||
}
|
||||
// Release lock
|
||||
m_connectionStatusRunning = false;
|
||||
});
|
||||
connectionWatcher->setFuture(future);
|
||||
}
|
||||
|
||||
Wallet::ConnectionStatus Wallet::connected(bool forceCheck)
|
||||
{
|
||||
// cache connection status
|
||||
if (!m_initialized || m_connectionStatusTime.elapsed() / 1000 > m_connectionStatusTtl) {
|
||||
m_initialized = true;
|
||||
ConnectionStatus newStatus = static_cast<ConnectionStatus>(m_walletImpl->connected());
|
||||
if (newStatus != m_connectionStatus) {
|
||||
m_connectionStatus = newStatus;
|
||||
emit connectionStatusChanged();
|
||||
}
|
||||
if (forceCheck || !m_initialized || (m_connectionStatusTime.elapsed() / 1000 > m_connectionStatusTtl && !m_connectionStatusRunning) || m_connectionStatusTime.elapsed() > 30000) {
|
||||
qDebug() << "Checking connection status";
|
||||
m_connectionStatusRunning = true;
|
||||
m_connectionStatusTime.restart();
|
||||
updateConnectionStatusAsync();
|
||||
}
|
||||
|
||||
return m_connectionStatus;
|
||||
@@ -139,17 +172,57 @@ bool Wallet::store(const QString &path)
|
||||
|
||||
bool Wallet::init(const QString &daemonAddress, quint64 upperTransactionLimit, bool isRecovering, quint64 restoreHeight)
|
||||
{
|
||||
return m_walletImpl->init(daemonAddress.toStdString(), upperTransactionLimit);
|
||||
}
|
||||
|
||||
void Wallet::initAsync(const QString &daemonAddress, quint64 upperTransactionLimit, bool isRecovering, quint64 restoreHeight)
|
||||
{
|
||||
qDebug() << "init non async";
|
||||
if (isRecovering){
|
||||
qDebug() << "RESTORING";
|
||||
m_walletImpl->setRecoveringFromSeed(true);
|
||||
m_walletImpl->setRefreshFromBlockHeight(restoreHeight);
|
||||
}
|
||||
m_walletImpl->initAsync(daemonAddress.toStdString(), upperTransactionLimit);
|
||||
m_walletImpl->init(daemonAddress.toStdString(), upperTransactionLimit, m_daemonUsername.toStdString(), m_daemonPassword.toStdString());
|
||||
return true;
|
||||
}
|
||||
|
||||
void Wallet::setDaemonLogin(const QString &daemonUsername, const QString &daemonPassword)
|
||||
{
|
||||
// store daemon login
|
||||
m_daemonUsername = daemonUsername;
|
||||
m_daemonPassword = daemonPassword;
|
||||
}
|
||||
|
||||
void Wallet::initAsync(const QString &daemonAddress, quint64 upperTransactionLimit, bool isRecovering, quint64 restoreHeight)
|
||||
{
|
||||
qDebug() << "initAsync: " + daemonAddress;
|
||||
// Change status to disconnected if connected
|
||||
if(m_connectionStatus != Wallet::ConnectionStatus_Disconnected) {
|
||||
m_connectionStatus = Wallet::ConnectionStatus_Disconnected;
|
||||
emit connectionStatusChanged(m_connectionStatus);
|
||||
}
|
||||
|
||||
QFuture<bool> future = QtConcurrent::run(this, &Wallet::init,
|
||||
daemonAddress, upperTransactionLimit, isRecovering, restoreHeight);
|
||||
QFutureWatcher<bool> * watcher = new QFutureWatcher<bool>();
|
||||
|
||||
connect(watcher, &QFutureWatcher<bool>::finished,
|
||||
this, [this, watcher, daemonAddress, upperTransactionLimit, isRecovering, restoreHeight]() {
|
||||
QFuture<bool> future = watcher->future();
|
||||
watcher->deleteLater();
|
||||
if(future.result()){
|
||||
qDebug() << "init async finished - starting refresh";
|
||||
connected(true);
|
||||
m_walletImpl->startRefresh();
|
||||
|
||||
}
|
||||
});
|
||||
watcher->setFuture(future);
|
||||
}
|
||||
|
||||
//! create a view only wallet
|
||||
bool Wallet::createViewOnly(const QString &path, const QString &password) const
|
||||
{
|
||||
// Create path
|
||||
QDir d = QFileInfo(path).absoluteDir();
|
||||
d.mkpath(d.absolutePath());
|
||||
return m_walletImpl->createWatchOnly(path.toStdString(),password.toStdString(),m_walletImpl->getSeedLanguage());
|
||||
}
|
||||
|
||||
bool Wallet::connectToDaemon()
|
||||
@@ -162,6 +235,11 @@ void Wallet::setTrustedDaemon(bool arg)
|
||||
m_walletImpl->setTrustedDaemon(arg);
|
||||
}
|
||||
|
||||
bool Wallet::viewOnly() const
|
||||
{
|
||||
return m_walletImpl->watchOnly();
|
||||
}
|
||||
|
||||
quint64 Wallet::balance() const
|
||||
{
|
||||
return m_walletImpl->balance();
|
||||
@@ -191,10 +269,10 @@ quint64 Wallet::daemonBlockChainHeight() const
|
||||
|
||||
quint64 Wallet::daemonBlockChainTargetHeight() const
|
||||
{
|
||||
|
||||
if (m_daemonBlockChainTargetHeight == 0
|
||||
if (m_daemonBlockChainTargetHeight <= 1
|
||||
|| m_daemonBlockChainTargetHeightTime.elapsed() / 1000 > m_daemonBlockChainTargetHeightTtl) {
|
||||
m_daemonBlockChainTargetHeight = m_walletImpl->daemonBlockChainTargetHeight();
|
||||
|
||||
// Target height is set to 0 if daemon is synced.
|
||||
// Use current height from daemon when target height < current height
|
||||
if (m_daemonBlockChainTargetHeight < m_daemonBlockChainHeight){
|
||||
@@ -217,6 +295,7 @@ bool Wallet::refresh()
|
||||
|
||||
void Wallet::refreshAsync()
|
||||
{
|
||||
qDebug() << "refresh async";
|
||||
m_walletImpl->refreshAsync();
|
||||
}
|
||||
|
||||
@@ -230,6 +309,16 @@ int Wallet::autoRefreshInterval() const
|
||||
return m_walletImpl->autoRefreshInterval();
|
||||
}
|
||||
|
||||
void Wallet::startRefresh() const
|
||||
{
|
||||
m_walletImpl->startRefresh();
|
||||
}
|
||||
|
||||
void Wallet::pauseRefresh() const
|
||||
{
|
||||
m_walletImpl->pauseRefresh();
|
||||
}
|
||||
|
||||
PendingTransaction *Wallet::createTransaction(const QString &dst_addr, const QString &payment_id,
|
||||
quint64 amount, quint32 mixin_count,
|
||||
PendingTransaction::Priority priority)
|
||||
@@ -248,13 +337,14 @@ void Wallet::createTransactionAsync(const QString &dst_addr, const QString &paym
|
||||
QFuture<PendingTransaction*> future = QtConcurrent::run(this, &Wallet::createTransaction,
|
||||
dst_addr, payment_id,amount, mixin_count, priority);
|
||||
QFutureWatcher<PendingTransaction*> * watcher = new QFutureWatcher<PendingTransaction*>();
|
||||
watcher->setFuture(future);
|
||||
|
||||
connect(watcher, &QFutureWatcher<PendingTransaction*>::finished,
|
||||
this, [this, watcher,dst_addr,payment_id,mixin_count]() {
|
||||
QFuture<PendingTransaction*> future = watcher->future();
|
||||
watcher->deleteLater();
|
||||
emit transactionCreated(future.result(),dst_addr,payment_id,mixin_count);
|
||||
});
|
||||
watcher->setFuture(future);
|
||||
}
|
||||
|
||||
PendingTransaction *Wallet::createTransactionAll(const QString &dst_addr, const QString &payment_id,
|
||||
@@ -274,13 +364,14 @@ void Wallet::createTransactionAllAsync(const QString &dst_addr, const QString &p
|
||||
QFuture<PendingTransaction*> future = QtConcurrent::run(this, &Wallet::createTransactionAll,
|
||||
dst_addr, payment_id, mixin_count, priority);
|
||||
QFutureWatcher<PendingTransaction*> * watcher = new QFutureWatcher<PendingTransaction*>();
|
||||
watcher->setFuture(future);
|
||||
|
||||
connect(watcher, &QFutureWatcher<PendingTransaction*>::finished,
|
||||
this, [this, watcher,dst_addr,payment_id,mixin_count]() {
|
||||
QFuture<PendingTransaction*> future = watcher->future();
|
||||
watcher->deleteLater();
|
||||
emit transactionCreated(future.result(),dst_addr,payment_id,mixin_count);
|
||||
});
|
||||
watcher->setFuture(future);
|
||||
}
|
||||
|
||||
PendingTransaction *Wallet::createSweepUnmixableTransaction()
|
||||
@@ -294,13 +385,31 @@ void Wallet::createSweepUnmixableTransactionAsync()
|
||||
{
|
||||
QFuture<PendingTransaction*> future = QtConcurrent::run(this, &Wallet::createSweepUnmixableTransaction);
|
||||
QFutureWatcher<PendingTransaction*> * watcher = new QFutureWatcher<PendingTransaction*>();
|
||||
watcher->setFuture(future);
|
||||
|
||||
connect(watcher, &QFutureWatcher<PendingTransaction*>::finished,
|
||||
this, [this, watcher]() {
|
||||
QFuture<PendingTransaction*> future = watcher->future();
|
||||
watcher->deleteLater();
|
||||
emit transactionCreated(future.result(),"","",0);
|
||||
});
|
||||
watcher->setFuture(future);
|
||||
}
|
||||
|
||||
UnsignedTransaction * Wallet::loadTxFile(const QString &fileName)
|
||||
{
|
||||
qDebug() << "Trying to sign " << fileName;
|
||||
Monero::UnsignedTransaction * ptImpl = m_walletImpl->loadUnsignedTx(fileName.toStdString());
|
||||
UnsignedTransaction * result = new UnsignedTransaction(ptImpl, m_walletImpl, this);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Wallet::submitTxFile(const QString &fileName) const
|
||||
{
|
||||
qDebug() << "Trying to submit " << fileName;
|
||||
if (!m_walletImpl->submitTransaction(fileName.toStdString()))
|
||||
return false;
|
||||
// import key images
|
||||
return m_walletImpl->importKeyImages(fileName.toStdString() + "_keyImages");
|
||||
}
|
||||
|
||||
void Wallet::disposeTransaction(PendingTransaction *t)
|
||||
@@ -309,6 +418,11 @@ void Wallet::disposeTransaction(PendingTransaction *t)
|
||||
delete t;
|
||||
}
|
||||
|
||||
void Wallet::disposeTransaction(UnsignedTransaction *t)
|
||||
{
|
||||
delete t;
|
||||
}
|
||||
|
||||
TransactionHistory *Wallet::history() const
|
||||
{
|
||||
return m_history;
|
||||
@@ -450,6 +564,40 @@ bool Wallet::verifySignedMessage(const QString &message, const QString &address,
|
||||
return m_walletImpl->verifySignedMessage(message.toStdString(), address.toStdString(), signature.toStdString());
|
||||
}
|
||||
}
|
||||
bool Wallet::parse_uri(const QString &uri, QString &address, QString &payment_id, uint64_t &amount, QString &tx_description, QString &recipient_name, QVector<QString> &unknown_parameters, QString &error)
|
||||
{
|
||||
std::string s_address, s_payment_id, s_tx_description, s_recipient_name, s_error;
|
||||
std::vector<std::string> s_unknown_parameters;
|
||||
bool res= m_walletImpl->parse_uri(uri.toStdString(), s_address, s_payment_id, amount, s_tx_description, s_recipient_name, s_unknown_parameters, s_error);
|
||||
if(res)
|
||||
{
|
||||
address = QString::fromStdString(s_address);
|
||||
payment_id = QString::fromStdString(s_payment_id);
|
||||
tx_description = QString::fromStdString(s_tx_description);
|
||||
recipient_name = QString::fromStdString(s_recipient_name);
|
||||
for( const auto &p : s_unknown_parameters )
|
||||
unknown_parameters.append(QString::fromStdString(p));
|
||||
}
|
||||
error = QString::fromStdString(s_error);
|
||||
return res;
|
||||
}
|
||||
|
||||
bool Wallet::rescanSpent()
|
||||
{
|
||||
return m_walletImpl->rescanSpent();
|
||||
}
|
||||
|
||||
bool Wallet::useForkRules(quint8 required_version, quint64 earlyBlocks) const
|
||||
{
|
||||
if(m_connectionStatus == Wallet::ConnectionStatus_Disconnected)
|
||||
return false;
|
||||
try {
|
||||
return m_walletImpl->useForkRules(required_version,earlyBlocks);
|
||||
} catch (const std::exception &e) {
|
||||
qDebug() << e.what();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Wallet::Wallet(Monero::Wallet *w, QObject *parent)
|
||||
: QObject(parent)
|
||||
@@ -473,6 +621,9 @@ Wallet::Wallet(Monero::Wallet *w, QObject *parent)
|
||||
m_daemonBlockChainHeightTime.restart();
|
||||
m_daemonBlockChainTargetHeightTime.restart();
|
||||
m_initialized = false;
|
||||
m_connectionStatusRunning = false;
|
||||
m_daemonUsername = "";
|
||||
m_daemonPassword = "";
|
||||
}
|
||||
|
||||
Wallet::~Wallet()
|
||||
@@ -480,7 +631,9 @@ Wallet::~Wallet()
|
||||
qDebug("~Wallet: Closing wallet");
|
||||
|
||||
delete m_history;
|
||||
m_history = NULL;
|
||||
//Monero::WalletManagerFactory::getWalletManager()->closeWallet(m_walletImpl);
|
||||
delete m_walletImpl;
|
||||
m_walletImpl = NULL;
|
||||
qDebug("m_walletImpl deleted");
|
||||
}
|
||||
|
||||
@@ -3,9 +3,12 @@
|
||||
|
||||
#include <QObject>
|
||||
#include <QTime>
|
||||
#include <QMutex>
|
||||
#include <QtConcurrent/QtConcurrent>
|
||||
|
||||
#include "wallet/wallet2_api.h" // we need to have an access to the Monero::Wallet::Status enum here;
|
||||
#include "PendingTransaction.h" // we need to have an access to the PendingTransaction::Priority enum here;
|
||||
#include "UnsignedTransaction.h"
|
||||
|
||||
namespace Monero {
|
||||
class Wallet; // forward declaration
|
||||
@@ -24,7 +27,8 @@ class Wallet : public QObject
|
||||
Q_PROPERTY(QString seed READ getSeed)
|
||||
Q_PROPERTY(QString seedLanguage READ getSeedLanguage)
|
||||
Q_PROPERTY(Status status READ status)
|
||||
Q_PROPERTY(ConnectionStatus connected READ connected)
|
||||
Q_PROPERTY(bool testnet READ testnet)
|
||||
// Q_PROPERTY(ConnectionStatus connected READ connected)
|
||||
Q_PROPERTY(bool synchronized READ synchronized)
|
||||
Q_PROPERTY(QString errorString READ errorString)
|
||||
Q_PROPERTY(QString address READ address)
|
||||
@@ -36,7 +40,7 @@ class Wallet : public QObject
|
||||
Q_PROPERTY(QString path READ path)
|
||||
Q_PROPERTY(AddressBookModel * addressBookModel READ addressBookModel)
|
||||
Q_PROPERTY(AddressBook * addressBook READ addressBook)
|
||||
|
||||
Q_PROPERTY(bool viewOnly READ viewOnly)
|
||||
|
||||
public:
|
||||
|
||||
@@ -69,8 +73,12 @@ public:
|
||||
//! returns last operation's status
|
||||
Status status() const;
|
||||
|
||||
//! returns true testnet wallet.
|
||||
bool testnet() const;
|
||||
|
||||
//! returns whether the wallet is connected, and version status
|
||||
ConnectionStatus connected() const;
|
||||
Q_INVOKABLE ConnectionStatus connected(bool forceCheck = false);
|
||||
void updateConnectionStatusAsync();
|
||||
|
||||
//! returns true if wallet was ever synchronized
|
||||
bool synchronized() const;
|
||||
@@ -93,10 +101,16 @@ public:
|
||||
Q_INVOKABLE bool store(const QString &path = "");
|
||||
|
||||
//! initializes wallet
|
||||
Q_INVOKABLE bool init(const QString &daemonAddress, quint64 upperTransactionLimit, bool isRecovering = false, quint64 restoreHeight = 0);
|
||||
Q_INVOKABLE bool init(const QString &daemonAddress, quint64 upperTransactionLimit = 0, bool isRecovering = false, quint64 restoreHeight = 0);
|
||||
|
||||
//! initializes wallet asynchronously
|
||||
Q_INVOKABLE void initAsync(const QString &daemonAddress, quint64 upperTransactionLimit, bool isRecovering = false, quint64 restoreHeight = 0);
|
||||
Q_INVOKABLE void initAsync(const QString &daemonAddress, quint64 upperTransactionLimit = 0, bool isRecovering = false, quint64 restoreHeight = 0);
|
||||
|
||||
// Set daemon rpc user/pass
|
||||
Q_INVOKABLE void setDaemonLogin(const QString &daemonUsername = "", const QString &daemonPassword = "");
|
||||
|
||||
//! create a view only wallet
|
||||
Q_INVOKABLE bool createViewOnly(const QString &path, const QString &password) const;
|
||||
|
||||
//! connects to daemon
|
||||
Q_INVOKABLE bool connectToDaemon();
|
||||
@@ -110,6 +124,9 @@ public:
|
||||
//! returns unlocked balance
|
||||
Q_INVOKABLE quint64 unlockedBalance() const;
|
||||
|
||||
//! returns if view only wallet
|
||||
Q_INVOKABLE bool viewOnly() const;
|
||||
|
||||
//! returns current wallet's block height
|
||||
//! (can be less than daemon's blockchain height when wallet sync in progress)
|
||||
Q_INVOKABLE quint64 blockChainHeight() const;
|
||||
@@ -132,6 +149,10 @@ public:
|
||||
//! return auto-refresh interval in seconds
|
||||
Q_INVOKABLE int autoRefreshInterval() const;
|
||||
|
||||
// pause/resume refresh
|
||||
Q_INVOKABLE void startRefresh() const;
|
||||
Q_INVOKABLE void pauseRefresh() const;
|
||||
|
||||
//! creates transaction
|
||||
Q_INVOKABLE PendingTransaction * createTransaction(const QString &dst_addr, const QString &payment_id,
|
||||
quint64 amount, quint32 mixin_count,
|
||||
@@ -156,9 +177,19 @@ public:
|
||||
//! creates async sweep unmixable transaction
|
||||
Q_INVOKABLE void createSweepUnmixableTransactionAsync();
|
||||
|
||||
//! Sign a transfer from file
|
||||
Q_INVOKABLE UnsignedTransaction * loadTxFile(const QString &fileName);
|
||||
|
||||
//! Submit a transfer from file
|
||||
Q_INVOKABLE bool submitTxFile(const QString &fileName) const;
|
||||
|
||||
|
||||
//! deletes transaction and frees memory
|
||||
Q_INVOKABLE void disposeTransaction(PendingTransaction * t);
|
||||
|
||||
//! deletes unsigned transaction and frees memory
|
||||
Q_INVOKABLE void disposeTransaction(UnsignedTransaction * t);
|
||||
|
||||
//! returns transaction history
|
||||
TransactionHistory * history() const;
|
||||
|
||||
@@ -183,6 +214,8 @@ public:
|
||||
//! verify a signed message
|
||||
Q_INVOKABLE bool verifySignedMessage(const QString &message, const QString &address, const QString &signature, bool filename = false) const;
|
||||
|
||||
//! Parse URI
|
||||
Q_INVOKABLE bool parse_uri(const QString &uri, QString &address, QString &payment_id, uint64_t &amount, QString &tx_description, QString &recipient_name, QVector<QString> &unknown_parameters, QString &error);
|
||||
|
||||
//! saved payment id
|
||||
QString paymentId() const;
|
||||
@@ -191,8 +224,12 @@ public:
|
||||
|
||||
Q_INVOKABLE bool setUserNote(const QString &txid, const QString ¬e);
|
||||
Q_INVOKABLE QString getUserNote(const QString &txid) const;
|
||||
|
||||
Q_INVOKABLE QString getTxKey(const QString &txid) const;
|
||||
// Rescan spent outputs
|
||||
Q_INVOKABLE bool rescanSpent();
|
||||
|
||||
// check if fork rules should be used
|
||||
Q_INVOKABLE bool useForkRules(quint8 version, quint64 earlyBlocks = 0) const;
|
||||
|
||||
// TODO: setListenter() when it implemented in API
|
||||
signals:
|
||||
@@ -206,13 +243,14 @@ signals:
|
||||
|
||||
void moneySpent(const QString &txId, quint64 amount);
|
||||
void moneyReceived(const QString &txId, quint64 amount);
|
||||
void newBlock(quint64 height);
|
||||
void unconfirmedMoneyReceived(const QString &txId, quint64 amount);
|
||||
void newBlock(quint64 height, quint64 targetHeight);
|
||||
void historyModelChanged() const;
|
||||
|
||||
// emitted when transaction is created async
|
||||
void transactionCreated(PendingTransaction * transaction, QString address, QString paymentId, quint32 mixinCount);
|
||||
|
||||
void connectionStatusChanged() const;
|
||||
void connectionStatusChanged(ConnectionStatus status) const;
|
||||
|
||||
private:
|
||||
Wallet(QObject * parent = nullptr);
|
||||
@@ -241,6 +279,10 @@ private:
|
||||
mutable bool m_initialized;
|
||||
AddressBook * m_addressBook;
|
||||
mutable AddressBookModel * m_addressBookModel;
|
||||
QMutex m_connectionStatusMutex;
|
||||
bool m_connectionStatusRunning;
|
||||
QString m_daemonUsername;
|
||||
QString m_daemonPassword;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "Wallet.h"
|
||||
#include "wallet/wallet2_api.h"
|
||||
#include "zxcvbn-c/zxcvbn.h"
|
||||
#include "QRCodeImageProvider.h"
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
#include <QDir>
|
||||
@@ -63,13 +64,14 @@ void WalletManager::openWalletAsync(const QString &path, const QString &password
|
||||
QFuture<Wallet*> future = QtConcurrent::run(this, &WalletManager::openWallet,
|
||||
path, password, testnet);
|
||||
QFutureWatcher<Wallet*> * watcher = new QFutureWatcher<Wallet*>();
|
||||
watcher->setFuture(future);
|
||||
|
||||
connect(watcher, &QFutureWatcher<Wallet*>::finished,
|
||||
this, [this, watcher]() {
|
||||
QFuture<Wallet*> future = watcher->future();
|
||||
watcher->deleteLater();
|
||||
emit walletOpened(future.result());
|
||||
});
|
||||
watcher->setFuture(future);
|
||||
}
|
||||
|
||||
|
||||
@@ -85,6 +87,22 @@ Wallet *WalletManager::recoveryWallet(const QString &path, const QString &memo,
|
||||
return m_currentWallet;
|
||||
}
|
||||
|
||||
Wallet *WalletManager::createWalletFromKeys(const QString &path, const QString &language, bool testnet,
|
||||
const QString &address, const QString &viewkey, const QString &spendkey,
|
||||
quint64 restoreHeight)
|
||||
{
|
||||
QMutexLocker locker(&m_mutex);
|
||||
if (m_currentWallet) {
|
||||
qDebug() << "Closing open m_currentWallet" << m_currentWallet;
|
||||
delete m_currentWallet;
|
||||
m_currentWallet = NULL;
|
||||
}
|
||||
Monero::Wallet * w = m_pimpl->createWalletFromKeys(path.toStdString(), language.toStdString(), testnet, restoreHeight,
|
||||
address.toStdString(), viewkey.toStdString(), spendkey.toStdString());
|
||||
m_currentWallet = new Wallet(w);
|
||||
return m_currentWallet;
|
||||
}
|
||||
|
||||
|
||||
QString WalletManager::closeWallet()
|
||||
{
|
||||
@@ -104,7 +122,6 @@ void WalletManager::closeWalletAsync()
|
||||
{
|
||||
QFuture<QString> future = QtConcurrent::run(this, &WalletManager::closeWallet);
|
||||
QFutureWatcher<QString> * watcher = new QFutureWatcher<QString>();
|
||||
watcher->setFuture(future);
|
||||
|
||||
connect(watcher, &QFutureWatcher<QString>::finished,
|
||||
this, [this, watcher]() {
|
||||
@@ -112,6 +129,7 @@ void WalletManager::closeWalletAsync()
|
||||
watcher->deleteLater();
|
||||
emit walletClosed(future.result());
|
||||
});
|
||||
watcher->setFuture(future);
|
||||
}
|
||||
|
||||
bool WalletManager::walletExists(const QString &path) const
|
||||
@@ -182,6 +200,16 @@ bool WalletManager::addressValid(const QString &address, bool testnet) const
|
||||
return Monero::Wallet::addressValid(address.toStdString(), testnet);
|
||||
}
|
||||
|
||||
bool WalletManager::keyValid(const QString &key, const QString &address, bool isViewKey, bool testnet) const
|
||||
{
|
||||
std::string error;
|
||||
if(!Monero::Wallet::keyValid(key.toStdString(), address.toStdString(), isViewKey, testnet, error)){
|
||||
qDebug() << QString::fromStdString(error);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
QString WalletManager::paymentIdFromAddress(const QString &address, bool testnet) const
|
||||
{
|
||||
return QString::fromStdString(Monero::Wallet::paymentIdFromAddress(address.toStdString(), testnet));
|
||||
@@ -227,6 +255,25 @@ double WalletManager::miningHashRate() const
|
||||
return m_pimpl->miningHashRate();
|
||||
}
|
||||
|
||||
bool WalletManager::isMining() const
|
||||
{
|
||||
if(!m_currentWallet->connected())
|
||||
return false;
|
||||
return m_pimpl->isMining();
|
||||
}
|
||||
|
||||
bool WalletManager::startMining(const QString &address, quint32 threads, bool backgroundMining, bool ignoreBattery)
|
||||
{
|
||||
if(threads == 0)
|
||||
threads = 1;
|
||||
return m_pimpl->startMining(address.toStdString(), threads, backgroundMining, ignoreBattery);
|
||||
}
|
||||
|
||||
bool WalletManager::stopMining()
|
||||
{
|
||||
return m_pimpl->stopMining();
|
||||
}
|
||||
|
||||
QString WalletManager::resolveOpenAlias(const QString &address) const
|
||||
{
|
||||
bool dnssec_valid = false;
|
||||
@@ -234,12 +281,23 @@ QString WalletManager::resolveOpenAlias(const QString &address) const
|
||||
res = std::string(dnssec_valid ? "true" : "false") + "|" + res;
|
||||
return QString::fromStdString(res);
|
||||
}
|
||||
bool WalletManager::parse_uri(const QString &uri, QString &address, QString &payment_id, uint64_t &amount, QString &tx_description, QString &recipient_name, QVector<QString> &unknown_parameters, QString &error)
|
||||
{
|
||||
if (m_currentWallet)
|
||||
return m_currentWallet->parse_uri(uri, address, payment_id, amount, tx_description, recipient_name, unknown_parameters, error);
|
||||
return false;
|
||||
}
|
||||
|
||||
void WalletManager::setLogLevel(int logLevel)
|
||||
{
|
||||
Monero::WalletManagerFactory::setLogLevel(logLevel);
|
||||
}
|
||||
|
||||
void WalletManager::setLogCategories(const QString &categories)
|
||||
{
|
||||
Monero::WalletManagerFactory::setLogCategories(categories.toStdString());
|
||||
}
|
||||
|
||||
QString WalletManager::urlToLocalPath(const QUrl &url) const
|
||||
{
|
||||
return QDir::toNativeSeparators(url.toLocalFile());
|
||||
@@ -265,6 +323,21 @@ double WalletManager::getPasswordStrength(const QString &password) const
|
||||
return e;
|
||||
}
|
||||
|
||||
bool WalletManager::saveQrCode(const QString &code, const QString &path) const
|
||||
{
|
||||
QSize size;
|
||||
// 240 <=> mainLayout.qrCodeSize (Receive.qml)
|
||||
return QRCodeImageProvider::genQrImage(code, &size).scaled(size.expandedTo(QSize(240, 240)), Qt::KeepAspectRatio).save(path, "PNG", 100);
|
||||
}
|
||||
|
||||
QString WalletManager::checkUpdates(const QString &software, const QString &subdir) const
|
||||
{
|
||||
const std::tuple<bool, std::string, std::string, std::string, std::string> result = Monero::WalletManager::checkUpdates(software.toStdString(), subdir.toStdString());
|
||||
if (!std::get<0>(result))
|
||||
return QString("");
|
||||
return QString::fromStdString(std::get<1>(result) + "|" + std::get<2>(result) + "|" + std::get<3>(result) + "|" + std::get<4>(result));
|
||||
}
|
||||
|
||||
WalletManager::WalletManager(QObject *parent) : QObject(parent)
|
||||
{
|
||||
m_pimpl = Monero::WalletManagerFactory::getWalletManager();
|
||||
|
||||
@@ -53,6 +53,14 @@ public:
|
||||
Q_INVOKABLE Wallet * recoveryWallet(const QString &path, const QString &memo,
|
||||
bool testnet = false, quint64 restoreHeight = 0);
|
||||
|
||||
Q_INVOKABLE Wallet * createWalletFromKeys(const QString &path,
|
||||
const QString &language,
|
||||
bool testnet,
|
||||
const QString &address,
|
||||
const QString &viewkey,
|
||||
const QString &spendkey = "",
|
||||
quint64 restoreHeight = 0);
|
||||
|
||||
/*!
|
||||
* \brief closeWallet - closes current open wallet and frees memory
|
||||
* \return wallet address
|
||||
@@ -92,6 +100,8 @@ public:
|
||||
|
||||
Q_INVOKABLE bool paymentIdValid(const QString &payment_id) const;
|
||||
Q_INVOKABLE bool addressValid(const QString &address, bool testnet) const;
|
||||
Q_INVOKABLE bool keyValid(const QString &key, const QString &address, bool isViewKey, bool testnet) const;
|
||||
|
||||
Q_INVOKABLE QString paymentIdFromAddress(const QString &address, bool testnet) const;
|
||||
|
||||
Q_INVOKABLE QString checkPayment(const QString &address, const QString &txid, const QString &txkey, const QString &daemon_address) const;
|
||||
@@ -103,11 +113,16 @@ public:
|
||||
Q_INVOKABLE quint64 blockchainTargetHeight() const;
|
||||
Q_INVOKABLE double miningHashRate() const;
|
||||
|
||||
Q_INVOKABLE bool isMining() const;
|
||||
Q_INVOKABLE bool startMining(const QString &address, quint32 threads, bool backgroundMining, bool ignoreBattery);
|
||||
Q_INVOKABLE bool stopMining();
|
||||
|
||||
// QML missing such functionality, implementing these helpers here
|
||||
Q_INVOKABLE QString urlToLocalPath(const QUrl &url) const;
|
||||
Q_INVOKABLE QUrl localPathToUrl(const QString &path) const;
|
||||
|
||||
void setLogLevel(int logLevel);
|
||||
Q_INVOKABLE void setLogLevel(int logLevel);
|
||||
Q_INVOKABLE void setLogCategories(const QString &categories);
|
||||
|
||||
Q_INVOKABLE quint64 add(quint64 x, quint64 y) const { return x + y; }
|
||||
Q_INVOKABLE quint64 sub(quint64 x, quint64 y) const { return x - y; }
|
||||
@@ -117,6 +132,9 @@ public:
|
||||
Q_INVOKABLE double getPasswordStrength(const QString &password) const;
|
||||
|
||||
Q_INVOKABLE QString resolveOpenAlias(const QString &address) const;
|
||||
Q_INVOKABLE bool parse_uri(const QString &uri, QString &address, QString &payment_id, uint64_t &amount, QString &tx_description, QString &recipient_name, QVector<QString> &unknown_parameters, QString &error);
|
||||
Q_INVOKABLE bool saveQrCode(const QString &, const QString &) const;
|
||||
Q_INVOKABLE QString checkUpdates(const QString &software, const QString &subdir) const;
|
||||
|
||||
signals:
|
||||
|
||||
|
||||
@@ -63,6 +63,11 @@ bool AddressBookModel::deleteRow(int row)
|
||||
m_addressBook->deleteRow(row);
|
||||
}
|
||||
|
||||
int AddressBookModel::lookupPaymentID(const QString &payment_id) const
|
||||
{
|
||||
return m_addressBook->lookupPaymentID(payment_id);
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> AddressBookModel::roleNames() const
|
||||
{
|
||||
QHash<int, QByteArray> roleNames = QAbstractListModel::roleNames();
|
||||
|
||||
@@ -24,6 +24,7 @@ public:
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
Q_INVOKABLE bool deleteRow(int row);
|
||||
Q_INVOKABLE int lookupPaymentID(const QString &payment_id) const;
|
||||
virtual QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
public slots:
|
||||
|
||||
@@ -75,7 +75,15 @@ QVariant TransactionHistoryModel::data(const QModelIndex &index, int role) const
|
||||
result = tInfo->fee();
|
||||
break;
|
||||
case TransactionBlockHeightRole:
|
||||
result = tInfo->blockHeight();
|
||||
// Use NULL QVariant for transactions without height.
|
||||
// Forces them to be displayed at top when sorted by blockHeight.
|
||||
if (tInfo->blockHeight() != 0) {
|
||||
result = tInfo->blockHeight();
|
||||
}
|
||||
break;
|
||||
|
||||
case TransactionConfirmationsRole:
|
||||
result = tInfo->confirmations();
|
||||
break;
|
||||
case TransactionHashRole:
|
||||
result = tInfo->hash();
|
||||
@@ -121,6 +129,7 @@ QHash<int, QByteArray> TransactionHistoryModel::roleNames() const
|
||||
roleNames.insert(TransactionAtomicAmountRole, "atomicAmount");
|
||||
roleNames.insert(TransactionFeeRole, "fee");
|
||||
roleNames.insert(TransactionBlockHeightRole, "blockHeight");
|
||||
roleNames.insert(TransactionConfirmationsRole, "confirmations");
|
||||
roleNames.insert(TransactionHashRole, "hash");
|
||||
roleNames.insert(TransactionTimeStampRole, "timeStamp");
|
||||
roleNames.insert(TransactionPaymentIdRole, "paymentId");
|
||||
|
||||
@@ -25,6 +25,7 @@ public:
|
||||
TransactionDisplayAmountRole,
|
||||
TransactionFeeRole,
|
||||
TransactionBlockHeightRole,
|
||||
TransactionConfirmationsRole,
|
||||
TransactionHashRole,
|
||||
TransactionTimeStampRole,
|
||||
TransactionPaymentIdRole,
|
||||
|
||||
@@ -1233,7 +1233,7 @@ Description: </source>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../main.qml" line="442"/>
|
||||
<source>insufficient funds. Unlocked balance: %1</source>
|
||||
<source>Insufficient funds. Unlocked balance: %1</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
|
||||
2422
translations/monero-core_eo.ts
Normal file
2361
translations/monero-core_fi.ts
Normal file
2348
translations/monero-core_hi.ts
Normal file
@@ -1,834 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE TS>
|
||||
<TS version="2.1" language="hi_IN">
|
||||
<context>
|
||||
<name>AddressBook</name>
|
||||
<message>
|
||||
<location filename="../pages/AddressBook.qml" line="47"/>
|
||||
<source>Add new entry</source>
|
||||
<translation>नयी प्रविष्टि डालें</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../pages/AddressBook.qml" line="56"/>
|
||||
<location filename="../pages/AddressBook.qml" line="173"/>
|
||||
<source>Address</source>
|
||||
<translation>पता</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../pages/AddressBook.qml" line="58"/>
|
||||
<source><b>Tip tekst test</b></source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../pages/AddressBook.qml" line="77"/>
|
||||
<source>Payment ID <font size='2'>(Optional)</font></source>
|
||||
<translation>भुगतान आईडी <font size='2'>(वैकल्पिक)</font></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../pages/AddressBook.qml" line="79"/>
|
||||
<source><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 thevtransfer</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../pages/AddressBook.qml" line="99"/>
|
||||
<source>Description <font size='2'>(Local database)</font></source>
|
||||
<translation>विवरण <font size='2'>(स्थानीय डेटाबेस)</font></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../pages/AddressBook.qml" line="101"/>
|
||||
<source><b>Tip tekst test</b><br/><br/>test line 2</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../pages/AddressBook.qml" line="126"/>
|
||||
<source>ADD</source>
|
||||
<translation>जोड़ें</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../pages/AddressBook.qml" line="174"/>
|
||||
<source>Payment ID</source>
|
||||
<translation>भुगतान आईडी</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../pages/AddressBook.qml" line="175"/>
|
||||
<source>Description</source>
|
||||
<translation>विवरण</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>AddressBookTable</name>
|
||||
<message>
|
||||
<location filename="../components/AddressBookTable.qml" line="47"/>
|
||||
<source>No more results</source>
|
||||
<translation>और अधिक परिणाम नहीं हैं</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../components/AddressBookTable.qml" line="106"/>
|
||||
<source>Payment ID:</source>
|
||||
<translation>भुगतान आईडी:</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>BasicPanel</name>
|
||||
<message>
|
||||
<location filename="../BasicPanel.qml" line="78"/>
|
||||
<source>Locked Balance:</source>
|
||||
<translation>बंद धनराशि:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../BasicPanel.qml" line="92"/>
|
||||
<source>78.9239845</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../BasicPanel.qml" line="116"/>
|
||||
<source>Available Balance:</source>
|
||||
<translation>उपलब्ध धनराशि:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../BasicPanel.qml" line="130"/>
|
||||
<source>2324.9239845</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../BasicPanel.qml" line="155"/>
|
||||
<source>amount...</source>
|
||||
<translation>राशि...</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../BasicPanel.qml" line="163"/>
|
||||
<source>SEND</source>
|
||||
<translation>भेजें</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../BasicPanel.qml" line="179"/>
|
||||
<source>destination...</source>
|
||||
<translation>गंतव्य...</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../BasicPanel.qml" line="191"/>
|
||||
<source>Privacy level</source>
|
||||
<translation>गोपनीयता स्तर</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../BasicPanel.qml" line="212"/>
|
||||
<source>payment ID (optional)...</source>
|
||||
<translation>भुगतान आईडी (वैकल्पिक)...</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Dashboard</name>
|
||||
<message>
|
||||
<location filename="../pages/Dashboard.qml" line="57"/>
|
||||
<source>Quick transfer</source>
|
||||
<translation>तत्काल स्थानांतरण</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../pages/Dashboard.qml" line="89"/>
|
||||
<source>SEND</source>
|
||||
<translation>भेजें</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../pages/Dashboard.qml" line="102"/>
|
||||
<source><style type='text/css'>a {text-decoration: none; color: #FF6C3C; font-size: 14px;}</style> lookng for security level and address book? go to <a href='#'>Transfer</a> tab</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>DashboardTable</name>
|
||||
<message>
|
||||
<location filename="../components/DashboardTable.qml" line="47"/>
|
||||
<source>No more results</source>
|
||||
<translation>और अधिक परिणाम नहीं हैं</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../components/DashboardTable.qml" line="137"/>
|
||||
<source>Date</source>
|
||||
<translation>तिथि</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../components/DashboardTable.qml" line="172"/>
|
||||
<source>Balance</source>
|
||||
<translation>धनराशि</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../components/DashboardTable.qml" line="193"/>
|
||||
<source>Amount</source>
|
||||
<translation>राशि</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>History</name>
|
||||
<message>
|
||||
<location filename="../pages/History.qml" line="47"/>
|
||||
<source>Filter trasactions history</source>
|
||||
<translation>लेनदेन इतिहास फिल्टर करें</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../pages/History.qml" line="56"/>
|
||||
<source>Address</source>
|
||||
<translation>पता</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../pages/History.qml" line="58"/>
|
||||
<location filename="../pages/History.qml" line="123"/>
|
||||
<location filename="../pages/History.qml" line="143"/>
|
||||
<location filename="../pages/History.qml" line="191"/>
|
||||
<location filename="../pages/History.qml" line="225"/>
|
||||
<location filename="../pages/History.qml" line="246"/>
|
||||
<source><b>Tip tekst test</b></source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../pages/History.qml" line="77"/>
|
||||
<source>Payment ID <font size='2'>(Optional)</font></source>
|
||||
<translation>भुगतान आईडी <font size='2'>(वैकल्पिक)</font></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../pages/History.qml" line="79"/>
|
||||
<source><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 thevtransfer</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../pages/History.qml" line="99"/>
|
||||
<source>Description <font size='2'>(Local database)</font></source>
|
||||
<translation>विवरण <font size='2'>(स्थानीय डेटाबेस)</font></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../pages/History.qml" line="101"/>
|
||||
<source><b>Tip tekst test</b><br/><br/>test line 2</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../pages/History.qml" line="121"/>
|
||||
<source>Date from</source>
|
||||
<translation>तिथि से</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../pages/History.qml" line="141"/>
|
||||
<location filename="../pages/History.qml" line="244"/>
|
||||
<source>To</source>
|
||||
<translation>तक</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../pages/History.qml" line="161"/>
|
||||
<source>FILTER</source>
|
||||
<translation>फिल्टर करें</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../pages/History.qml" line="170"/>
|
||||
<source>Advance filtering</source>
|
||||
<translation>उन्नत फिल्टर</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../pages/History.qml" line="189"/>
|
||||
<source>Type of transation</source>
|
||||
<translation>लेनदेन के प्रकार</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../pages/History.qml" line="223"/>
|
||||
<source>Amount from</source>
|
||||
<translation>राशि</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>HistoryTable</name>
|
||||
<message>
|
||||
<location filename="../components/HistoryTable.qml" line="47"/>
|
||||
<source>No more results</source>
|
||||
<translation>और अधिक परिणाम नहीं हैं</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../components/HistoryTable.qml" line="129"/>
|
||||
<source>Payment ID:</source>
|
||||
<translation>भुगतान आईडी:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../components/HistoryTable.qml" line="167"/>
|
||||
<source>Date</source>
|
||||
<translation>तिथि</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../components/HistoryTable.qml" line="202"/>
|
||||
<source>Balance</source>
|
||||
<translation>धनराशि</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../components/HistoryTable.qml" line="223"/>
|
||||
<source>Amount</source>
|
||||
<translation>राशि</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>LeftPanel</name>
|
||||
<message>
|
||||
<location filename="../LeftPanel.qml" line="103"/>
|
||||
<source>Balance</source>
|
||||
<translation>धनराशि</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../LeftPanel.qml" line="106"/>
|
||||
<source>Test tip 1<br/><br/>line 2</source>
|
||||
<translation>परीक्षण उपाय 1<br/><br/>line 2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../LeftPanel.qml" line="138"/>
|
||||
<source>Unlocked balance</source>
|
||||
<translation>खुली धनराशि</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../LeftPanel.qml" line="141"/>
|
||||
<source>Test tip 2<br/><br/>line 2</source>
|
||||
<translation>परीक्षण उपाय 2<br/><br/>line 2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../LeftPanel.qml" line="222"/>
|
||||
<source>Transfer</source>
|
||||
<translation>स्थानांतरण</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../LeftPanel.qml" line="223"/>
|
||||
<source>T</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../LeftPanel.qml" line="245"/>
|
||||
<source>Receive</source>
|
||||
<translation>प्राप्त करें</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../LeftPanel.qml" line="246"/>
|
||||
<source>R</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>NetworkStatusItem</name>
|
||||
<message>
|
||||
<location filename="../components/NetworkStatusItem.qml" line="58"/>
|
||||
<source>Network status</source>
|
||||
<translation>नेटवर्क स्थिति</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../components/NetworkStatusItem.qml" line="66"/>
|
||||
<source>Connected</source>
|
||||
<translation>कनेक्ट किया गया</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../components/NetworkStatusItem.qml" line="66"/>
|
||||
<source>Disconnected</source>
|
||||
<translation>डिस्कनेक्ट किया गया</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>PrivacyLevelSmall</name>
|
||||
<message>
|
||||
<location filename="../components/PrivacyLevelSmall.qml" line="102"/>
|
||||
<source>LOW</source>
|
||||
<translation>निम्न</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../components/PrivacyLevelSmall.qml" line="113"/>
|
||||
<source>MEDIUM</source>
|
||||
<translation>मध्यम</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../components/PrivacyLevelSmall.qml" line="124"/>
|
||||
<source>HIGH</source>
|
||||
<translation>उच्च</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Receive</name>
|
||||
<message>
|
||||
<location filename="../pages/Receive.qml" line="79"/>
|
||||
<source>Address</source>
|
||||
<translation>पता</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../pages/Receive.qml" line="86"/>
|
||||
<source>ReadOnly wallet address displayed here</source>
|
||||
<translation>यहाँ केवल पठनीय वॉलेट पता प्रदर्शित है</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../pages/Receive.qml" line="106"/>
|
||||
<source>Integrated address</source>
|
||||
<translation>एकीकृत पता</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../pages/Receive.qml" line="115"/>
|
||||
<source>ReadOnly wallet integrated address displayed here</source>
|
||||
<translation>यहाँ केवल पठनीय वॉलेट एकीकृत पता प्रदर्शित है</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../pages/Receive.qml" line="136"/>
|
||||
<source>Payment ID</source>
|
||||
<translation>भुगतान आईडी</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../pages/Receive.qml" line="144"/>
|
||||
<source>PaymentID here</source>
|
||||
<translation>भुगतान आईडी यहाँ</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../pages/Receive.qml" line="168"/>
|
||||
<source>Generate</source>
|
||||
<translation>उत्पन्न करें</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>RightPanel</name>
|
||||
<message>
|
||||
<location filename="../RightPanel.qml" line="58"/>
|
||||
<source>Twitter</source>
|
||||
<translation>ट्विटर</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../RightPanel.qml" line="59"/>
|
||||
<source>News</source>
|
||||
<translation>समाचार</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../RightPanel.qml" line="60"/>
|
||||
<source>Help</source>
|
||||
<translation>सहायता</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../RightPanel.qml" line="61"/>
|
||||
<source>About</source>
|
||||
<translation>बारे में</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>SearchInput</name>
|
||||
<message>
|
||||
<location filename="../components/SearchInput.qml" line="69"/>
|
||||
<source>Search by...</source>
|
||||
<translation>निम्न से खोजें...</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../components/SearchInput.qml" line="230"/>
|
||||
<source>SEARCH</source>
|
||||
<translation>खोजें</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>TickDelegate</name>
|
||||
<message>
|
||||
<location filename="../components/TickDelegate.qml" line="55"/>
|
||||
<source>LOW</source>
|
||||
<translation>निम्न</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../components/TickDelegate.qml" line="56"/>
|
||||
<source>MEDIUM</source>
|
||||
<translation>मध्यम</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../components/TickDelegate.qml" line="57"/>
|
||||
<source>HIGH</source>
|
||||
<translation>उच्च</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>TitleBar</name>
|
||||
<message>
|
||||
<location filename="../components/TitleBar.qml" line="38"/>
|
||||
<source>Monero - Donations</source>
|
||||
<translation>Monero - डोनेशन</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Transfer</name>
|
||||
<message>
|
||||
<location filename="../pages/Transfer.qml" line="57"/>
|
||||
<source>Amount</source>
|
||||
<translation>राशि</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../pages/Transfer.qml" line="67"/>
|
||||
<source>Transaction priority</source>
|
||||
<translation>लेनदेन प्राथमिकता</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../pages/Transfer.qml" line="89"/>
|
||||
<source>Amount...</source>
|
||||
<translation>राशि....</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../pages/Transfer.qml" line="96"/>
|
||||
<source>LOW</source>
|
||||
<translation>निम्न</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../pages/Transfer.qml" line="97"/>
|
||||
<source>MEDIUM</source>
|
||||
<translation>मध्यम</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../pages/Transfer.qml" line="98"/>
|
||||
<source>HIGH</source>
|
||||
<translation>उच्च</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../pages/Transfer.qml" line="127"/>
|
||||
<source>Privacy Level</source>
|
||||
<translation>गोपनीयता स्तर</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../pages/Transfer.qml" line="153"/>
|
||||
<source>Cost</source>
|
||||
<translation>मूल्य</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../pages/Transfer.qml" line="167"/>
|
||||
<source><style type='text/css'>a {text-decoration: none; color: #FF6C3C; font-size: 14px;}</style> Address <font size='2'> ( Type in or select from </font> <a href='#'>Address</a><font size='2'> book )</font></source>
|
||||
<translation type="unfinished"><style type='text/css'>a {text-decoration: none; color: #FF6C3C; font-size: 14px;}</style> पता <font size='2'> ( Type in or select from </font> <a href='#'>पता</a><font size='2'> पुस्तिका )</font></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../pages/Transfer.qml" line="194"/>
|
||||
<source>Payment ID <font size='2'>( Optional )</font></source>
|
||||
<translation>भुगतान आईडी <font size='2'>( वैकल्पिक )</font></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../pages/Transfer.qml" line="218"/>
|
||||
<source>Description <font size='2'>( An optional description that will be saved to the local address book if entered )</font></source>
|
||||
<translation>विवरण <font size='2'>( एक वैकल्पिक विवरण जिसे दर्ज़ करने पर यह स्थानीय पता पुस्तिका में सहेजा जायेगा )</font></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../pages/Transfer.qml" line="239"/>
|
||||
<source>SEND</source>
|
||||
<translation>भेजें</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>WizardConfigure</name>
|
||||
<message>
|
||||
<location filename="../wizard/WizardConfigure.qml" line="79"/>
|
||||
<source>We’re almost there - let’s just configure some Monero preferences</source>
|
||||
<translation>हमने बस समाप्त कर लिया है - चलिए कुछ Monero प्राथमिकताएं कॉन्फ़िगर करते हैं</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../wizard/WizardConfigure.qml" line="97"/>
|
||||
<source>Kickstart the Monero blockchain?</source>
|
||||
<translation>Kickstart the Monero ब्लॉकचेन?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../wizard/WizardConfigure.qml" line="115"/>
|
||||
<source>It is very important to write it down as this is the only backup you will need for your wallet. You will be asked to confirm the seed in the next screen to ensure it has copied down correctly.</source>
|
||||
<translation>इसे लिखना बहुत आवश्यक है क्योंकि अपने वॉलेट के लिए आपको बस इस एकमात्र बैकअप की जरुरत पड़ेगी। यह सही से कॉपी किया गया है यह सुनिश्चित करने के लिए आपको अगली स्क्रीन पर सीड की पुष्टि करने के लिए कहा जायेगा।</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../wizard/WizardConfigure.qml" line="127"/>
|
||||
<source>Enable disk conservation mode?</source>
|
||||
<translation>डिस्क संरक्षण मोड सक्षम करें?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../wizard/WizardConfigure.qml" line="145"/>
|
||||
<source>Disk conservation mode uses substantially less disk-space, but the same amount of bandwidth as a regular Monero instance. However, storing the full blockchain is beneficial to the security of the Monero network. If you are on a device with limited disk space, then this option is appropriate for you.</source>
|
||||
<translation>डिस्क संरक्षण मोड काफी कम डिस्क-स्पेस प्रयोग करता है, लेकिन इसके लिए सामान्य Monero इंस्टैंस के बराबर बैंडविड्थ की आवश्यकता होती है। हालाँकि, Monero नेटवर्क की सुरक्षा के लिए पूरा ब्लॉकचेन संग्रहीत करना लाभदायक होता है। यदि आप कम डिस्क स्पेस वाली डिवाइस पर हैं तो यह विकल्प आपके लिए उपयुक्त है।</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../wizard/WizardConfigure.qml" line="158"/>
|
||||
<source>Allow background mining?</source>
|
||||
<translation>बैकग्रॉउंड माइनिंग की अनुमति दें?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../wizard/WizardConfigure.qml" line="176"/>
|
||||
<source>Mining secures the Monero network, and also pays a small reward for the work done. This option will let Monero mine when your computer is on mains power and is idle. It will stop mining when you continue working.</source>
|
||||
<translation>माइनिंग Monero नेटवर्क को सुरक्षित बनाता है, और साथ ही किये गए कार्य के लिए छोटा पुरस्कार भी देता है। यह विकल्प Monero को तब माइन करने देता है जब आपका कंप्यूटर मेंस पॉवर पर होता है और निष्क्रिय होता है। जब आप काम करना शुरू करते हैं तो यह माइनिंग बंद कर देता है।</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>WizardCreateWallet</name>
|
||||
<message>
|
||||
<location filename="../wizard/WizardCreateWallet.qml" line="90"/>
|
||||
<source>A new wallet has been created for you</source>
|
||||
<translation>आपके लिए एक नया वॉलेट बनाया गया है</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../wizard/WizardCreateWallet.qml" line="91"/>
|
||||
<source>This is the 25 word mnemonic for your wallet</source>
|
||||
<translation>यह आपके वॉलेट के लिए 25 शब्दों का स्मरक है</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>WizardDonation</name>
|
||||
<message>
|
||||
<location filename="../wizard/WizardDonation.qml" line="93"/>
|
||||
<source>Monero development is solely supported by donations</source>
|
||||
<translation>Monero का विकास पूरी तरह से डोनेशन से समर्थित है</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../wizard/WizardDonation.qml" line="113"/>
|
||||
<source>Enable auto-donations of?</source>
|
||||
<translation>ऑटो-डोनेशन सक्षम करें?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../wizard/WizardDonation.qml" line="153"/>
|
||||
<source>% of my fee added to each transaction</source>
|
||||
<translation>% मेरे शुल्क का प्रत्येक लेनदेन में जोड़ा जाता है</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../wizard/WizardDonation.qml" line="164"/>
|
||||
<source>For every transaction, a small transaction fee is charged. This option lets you add an additional amount, as a percentage of that fee, to your transaction to support Monero development. For instance, a 50% autodonation take a transaction fee of 0.005 XMR and add a 0.0025 XMR to support Monero development.</source>
|
||||
<translation>प्रत्येक लेनदेन के लिए एक छोटा शुल्क लगाया जाता है। यह विकल्प आपको Monero का विकास समर्थित करने के लिए अपने लेनदेन में शुल्क के प्रतिशत के रूप में एक अतिरिक्त राशि जोड़ने की अनुमति देता है। उदाहरण के लिए, 50% ऑटो-डोनेशन 0.005 XMR का लेनदेन शुल्क लेता है और Monero के विकास को समर्थित करने के लिए 0.0025 XMR जोड़ता है।</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../wizard/WizardDonation.qml" line="176"/>
|
||||
<source>Allow background mining?</source>
|
||||
<translation>बैकग्राउंड माइनिंग की अनुमति दें?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../wizard/WizardDonation.qml" line="194"/>
|
||||
<source>Mining secures the Monero network, and also pays a small reward for the work done. This option will let Monero mine when your computer is on mains power and is idle. It will stop mining when you continue working.</source>
|
||||
<translation>माइनिंग Monero नेटवर्क को सुरक्षित बनाता है, और साथ ही किये गए कार्य के लिए छोटा पुरस्कार भी देता है। यह विकल्प Monero को तब माइन करने देता है जब आपका कंप्यूटर मेंस पॉवर पर होता है और निष्क्रिय होता है। जब आप काम करना शुरू करते हैं तो यह माइनिंग बंद कर देता है।</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>WizardFinish</name>
|
||||
<message>
|
||||
<location filename="../wizard/WizardFinish.qml" line="41"/>
|
||||
<source><b>Language:</b></source>
|
||||
<translation><b>भाषा:</b></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../wizard/WizardFinish.qml" line="42"/>
|
||||
<source><b>Account name:</b> </source>
|
||||
<translation><b>खाता नाम:</b> </translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../wizard/WizardFinish.qml" line="43"/>
|
||||
<source><b>Words:</b> </source>
|
||||
<translation><b>शब्द:</b> </translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../wizard/WizardFinish.qml" line="44"/>
|
||||
<source><b>Wallet Path: </b></source>
|
||||
<translation><b>वॉलेट पाथ: </b></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../wizard/WizardFinish.qml" line="45"/>
|
||||
<source><b>Enable auto donation: </b></source>
|
||||
<translation><b>ऑटो डोनेशन सक्षम करें: </b></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../wizard/WizardFinish.qml" line="46"/>
|
||||
<source><b>Auto donation amount: </b></source>
|
||||
<translation><b>ऑटो डोनेशन राशि: </b></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../wizard/WizardFinish.qml" line="47"/>
|
||||
<source><b>Allow background mining: </b></source>
|
||||
<translation><b>बैकग्राउंड माइनिंग की अनुमति दें: </b></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../wizard/WizardFinish.qml" line="52"/>
|
||||
<source>An overview of your Monero configuration is below:</source>
|
||||
<translation>आपके Monero कॉन्फ़िगरेशन की समीक्षा नीचे दी गयी है:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../wizard/WizardFinish.qml" line="107"/>
|
||||
<source>You’re all setup!</source>
|
||||
<translation>आप बिल्कुल तैयार हैं!</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>WizardMain</name>
|
||||
<message>
|
||||
<location filename="../wizard/WizardMain.qml" line="308"/>
|
||||
<source>USE MONERO</source>
|
||||
<translation>MONERO प्रयोग करें</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>WizardManageWalletUI</name>
|
||||
<message>
|
||||
<location filename="../wizard/WizardManageWalletUI.qml" line="103"/>
|
||||
<source>This is the name of your wallet. You can change it to a different name if you’d like:</source>
|
||||
<translation>यह आपके वॉलेट का नाम है। यदि आप चाहें तो इसे दूसरे नाम में बदल सकते हैं:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../wizard/WizardManageWalletUI.qml" line="125"/>
|
||||
<source>My account name</source>
|
||||
<translation>मेरा खाता नाम</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../wizard/WizardManageWalletUI.qml" line="175"/>
|
||||
<source>Your wallet is stored in</source>
|
||||
<translation>आपका वॉलेट संग्रहीत है</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../wizard/WizardManageWalletUI.qml" line="187"/>
|
||||
<source>Please choose a directory</source>
|
||||
<translation>कृपया निर्देशिका चुनें</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>WizardMemoTextInput</name>
|
||||
<message>
|
||||
<location filename="../wizard/WizardMemoTextInput.qml" line="76"/>
|
||||
<source>It is very important to write it down as this is the only backup you will need for your wallet. You will be asked to confirm the seed in the next screen to ensure it has copied down correctly.</source>
|
||||
<translation>इसे लिखना बहुत आवश्यक है क्योंकि अपने वॉलेट के लिए आपको बस इस एकमात्र बैकअप की जरुरत पड़ेगी। यह सही से कॉपी किया गया है यह सुनिश्चित करने के लिए आपको अगली स्क्रीन पर सीड की पुष्टि करने के लिए कहा जायेगा।</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>WizardOptions</name>
|
||||
<message>
|
||||
<location filename="../wizard/WizardOptions.qml" line="62"/>
|
||||
<source>Welcome to Monero!</source>
|
||||
<translation>Monero में आपका स्वागत है!</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../wizard/WizardOptions.qml" line="74"/>
|
||||
<source>Please select one of the following options:</source>
|
||||
<translation>कृपया निम्नलिखित विकल्पों में से एक का चयन करें:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../wizard/WizardOptions.qml" line="110"/>
|
||||
<source>This is my first time, I want to<br/>create a new account</source>
|
||||
<translation>यह मेरे लिए पहली बार है, मैं एक नया<br/>खाता बनाना चाहता हूँ</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../wizard/WizardOptions.qml" line="141"/>
|
||||
<source>I want to recover my account<br/>from my 24 work seed</source>
|
||||
<translation>मैं अपने 24 वर्क सीड से अपना खाता<br/>रिकवर करना चाहता हूँ </translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>WizardPassword</name>
|
||||
<message>
|
||||
<location filename="../wizard/WizardPassword.qml" line="51"/>
|
||||
<source>Now that your wallet has been created, please set a password for the wallet</source>
|
||||
<translation>अब जबकि आपका वॉलेट बन गया है, कृपया वॉलेट के लिए पासवर्ड निर्धारित करें</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../wizard/WizardPassword.qml" line="53"/>
|
||||
<source>Now that your wallet has been restored, please set a password for the wallet</source>
|
||||
<translation>अब जबकि आपका वॉलेट पुनर्स्थापित हो गया है, कृपया वॉलेट के लिए पासवर्ड निर्धारित करें</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../wizard/WizardPassword.qml" line="135"/>
|
||||
<source>Note that this password cannot be recovered, and if forgotten you will need to restore your wallet from the mnemonic seed you were just given<br/><br/>
|
||||
Your password will be used to protect your wallet and to confirm actions, so make sure that your password is sufficiently secure.</source>
|
||||
<translation>ध्यान रखें, यह पासवर्ड दोबारा प्राप्त नहीं किया जा सकता है, और यदि आप इसे भूल जाते हैं तो आपको दिए गए स्मरक सीड से अपना वॉलेट पुनर्स्थापित करने की जरुरत पड़ेगी <br/><br/>
|
||||
आपका पासवर्ड वॉलेट सुरक्षित रखने के लिए और गतिविधियों की पुष्टि करने के लिए प्रयोग किया जायेगा, तो इस बात का ध्यान रखें कि आपका पासवर्ड पर्याप्त रूप से सुरक्षित रहे।</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>WizardRecoveryWallet</name>
|
||||
<message>
|
||||
<location filename="../wizard/WizardRecoveryWallet.qml" line="78"/>
|
||||
<source>My account name</source>
|
||||
<translation>मेरा खाता नाम</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../wizard/WizardRecoveryWallet.qml" line="79"/>
|
||||
<source>We're ready to recover your account</source>
|
||||
<translation>हम आपका खाता रिकवर करने के लिए तैयार हैं</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../wizard/WizardRecoveryWallet.qml" line="80"/>
|
||||
<source>Please enter your 25 word private key</source>
|
||||
<translation>कृपया अपनी 25 शब्दों की गोपनीय कुंजी डालें</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>WizardWelcome</name>
|
||||
<message>
|
||||
<location filename="../wizard/WizardWelcome.qml" line="69"/>
|
||||
<source>Welcome</source>
|
||||
<translation>आपका स्वागत है</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../wizard/WizardWelcome.qml" line="82"/>
|
||||
<source>Please choose a language and regional format.</source>
|
||||
<translation>कृपया अपनी भाषा और क्षेत्रीय स्वरूप डालें।</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>main</name>
|
||||
<message>
|
||||
<location filename="../main.qml" line="148"/>
|
||||
<location filename="../main.qml" line="203"/>
|
||||
<location filename="../main.qml" line="233"/>
|
||||
<source>Error</source>
|
||||
<translation>त्रुटि</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../main.qml" line="149"/>
|
||||
<source>Couldn't open wallet: </source>
|
||||
<translation>वॉलेट नहीं खुल पाया: </translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../main.qml" line="204"/>
|
||||
<source>Can't create transaction: </source>
|
||||
<translation>लेनदेन नहीं हो सकता है: </translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../main.qml" line="216"/>
|
||||
<source>Confirmation</source>
|
||||
<translation>पुष्टिकरण</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../main.qml" line="217"/>
|
||||
<source>Please confirm transaction:</source>
|
||||
<translation>कृपया लेनदेन की पुष्टि करें:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../main.qml" line="218"/>
|
||||
<source>Address: </source>
|
||||
<translation>पता:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../main.qml" line="219"/>
|
||||
<source>Payment ID: </source>
|
||||
<translation>भुगतान आईडी:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../main.qml" line="220"/>
|
||||
<source>Amount: </source>
|
||||
<translation>राशि:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../main.qml" line="221"/>
|
||||
<source>Fee: </source>
|
||||
<translation>शुल्क:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../main.qml" line="234"/>
|
||||
<source>Couldn't send the money: </source>
|
||||
<translation>पैसेनहीं भेज पाया: </translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../main.qml" line="237"/>
|
||||
<source>Information</source>
|
||||
<translation>जानकारी</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../main.qml" line="238"/>
|
||||
<source>Money sent successfully</source>
|
||||
<translation>पैसे सफलतापूर्वक भेजे गए</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../main.qml" line="310"/>
|
||||
<source>Initializing Wallet...</source>
|
||||
<translation>वॉलेट प्रारंभ हो रहा है...</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../main.qml" line="336"/>
|
||||
<source>Program setup wizard</source>
|
||||
<translation>प्रोग्राम सेटअप विज़ार्ड</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../main.qml" line="350"/>
|
||||
<source>Monero - Donations</source>
|
||||
<translation>Monero - डोनेशन</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../main.qml" line="389"/>
|
||||
<source>send to the same destination</source>
|
||||
<translation>समान गंतव्य पर भेजें</translation>
|
||||
</message>
|
||||
</context>
|
||||
</TS>
|
||||