mirror of
https://github.com/monero-project/monero-gui.git
synced 2026-04-02 03:27:25 -04:00
Compare commits
447 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
113efbfdf0 | ||
|
|
0e1c6ae60f | ||
|
|
b461373b8a | ||
|
|
046124cd9b | ||
|
|
0ca7e4ec76 | ||
|
|
376eaecf08 | ||
|
|
316f8b1762 | ||
|
|
cbed1ed6f7 | ||
|
|
3507e848cf | ||
|
|
60967d3930 | ||
|
|
55a262b892 | ||
|
|
3719f00953 | ||
|
|
09003dd140 | ||
|
|
ac432fe947 | ||
|
|
5234570afa | ||
|
|
946fa538b9 | ||
|
|
52c8d68240 | ||
|
|
4fec3a4d6f | ||
|
|
02e0ac1309 | ||
|
|
51828babbb | ||
|
|
a13e4b622c | ||
|
|
56a17e0a85 | ||
|
|
e74ef368df | ||
|
|
857d034f18 | ||
|
|
3f4cedea54 | ||
|
|
4376880b46 | ||
|
|
98057487f6 | ||
|
|
06025352ce | ||
|
|
57f9cf9d85 | ||
|
|
d8fb9ec081 | ||
|
|
faf9ec3027 | ||
|
|
22291b1df1 | ||
|
|
7805430f4f | ||
|
|
b30be48a24 | ||
|
|
284caf83f6 | ||
|
|
d20c589e42 | ||
|
|
ea9ed3e0be | ||
|
|
c4c549e57a | ||
|
|
b6682330a6 | ||
|
|
b54ee598d8 | ||
|
|
7da11b050c | ||
|
|
94b6a5bbf5 | ||
|
|
5a88d4a669 | ||
|
|
3d6e9ce571 | ||
|
|
987e716374 | ||
|
|
f81bfa1865 | ||
|
|
e4a3e282b5 | ||
|
|
c017522a3c | ||
|
|
6739b51a5b | ||
|
|
3631482419 | ||
|
|
1c61ec2511 | ||
|
|
d0707d78a1 | ||
|
|
083b0fb7a8 | ||
|
|
24d113377b | ||
|
|
5e076325cd | ||
|
|
5aef186c8a | ||
|
|
81f0209006 | ||
|
|
b4e6f20b53 | ||
|
|
a278781abf | ||
|
|
2d82439b56 | ||
|
|
0b0bc87184 | ||
|
|
59fcda43c6 | ||
|
|
6e87e2cb5b | ||
|
|
8730743207 | ||
|
|
4c67007e5b | ||
|
|
0ae1c721ef | ||
|
|
21cce4cfb4 | ||
|
|
d595957405 | ||
|
|
0ce3e4b1e7 | ||
|
|
8419fce062 | ||
|
|
15dbbaf691 | ||
|
|
d8f9d2f160 | ||
|
|
dbda233b94 | ||
|
|
f82336ce8c | ||
|
|
dbc8c7d473 | ||
|
|
2c0cf0d652 | ||
|
|
2db8f77a0a | ||
|
|
0fd0fc5ceb | ||
|
|
0de95e3071 | ||
|
|
b58bff39a0 | ||
|
|
bea763d7f8 | ||
|
|
59a0184ebd | ||
|
|
1a8e3111e4 | ||
|
|
614a7a086a | ||
|
|
b9a1fa8563 | ||
|
|
51ac3ca981 | ||
|
|
192b36f74f | ||
|
|
54e183a7f5 | ||
|
|
453388f744 | ||
|
|
afc2b35ed0 | ||
|
|
9114887866 | ||
|
|
2afb346563 | ||
|
|
bc8f39c311 | ||
|
|
286a3d140d | ||
|
|
5f2b5d940c | ||
|
|
64dd55a9a6 | ||
|
|
eacc57fb44 | ||
|
|
4e2b1cec95 | ||
|
|
08dd89de58 | ||
|
|
c15c5b5227 | ||
|
|
ffd31c50da | ||
|
|
b970cad48b | ||
|
|
752f1faa93 | ||
|
|
60b33d3a91 | ||
|
|
5de306ab7a | ||
|
|
dfe8146f5c | ||
|
|
6610f6f2da | ||
|
|
b319dbb1b2 | ||
|
|
3eae630cfe | ||
|
|
52aef114fa | ||
|
|
7c379e2cda | ||
|
|
244459e606 | ||
|
|
0e561de0a9 | ||
|
|
ceac6c8a47 | ||
|
|
b542f15531 | ||
|
|
3621ab3344 | ||
|
|
4850e13895 | ||
|
|
950e20d400 | ||
|
|
124a8b5f4e | ||
|
|
0bd4d731d2 | ||
|
|
e3a17a66ff | ||
|
|
4f385b9a04 | ||
|
|
2c54787644 | ||
|
|
7770621a2f | ||
|
|
b22fc4266c | ||
|
|
2290e7e762 | ||
|
|
f8344ce7c6 | ||
|
|
1be9ea4828 | ||
|
|
b07016b7cd | ||
|
|
179b74e570 | ||
|
|
0a6f6cb9ac | ||
|
|
417eaeae28 | ||
|
|
8ac1b4ef58 | ||
|
|
979e0da9e0 | ||
|
|
1f8aa0dff0 | ||
|
|
f75a2447a7 | ||
|
|
f6a66b6779 | ||
|
|
c5bad8ec49 | ||
|
|
2f1092de55 | ||
|
|
b825f6e1bd | ||
|
|
ad38f155bc | ||
|
|
5a418499d4 | ||
|
|
cea712e51d | ||
|
|
39d561d9f2 | ||
|
|
23301da51b | ||
|
|
9ab104b38a | ||
|
|
2c517623a1 | ||
|
|
f06d6e067f | ||
|
|
1512908751 | ||
|
|
ed1bc2eece | ||
|
|
0775b529c4 | ||
|
|
aca6174ef4 | ||
|
|
20106b29ba | ||
|
|
c9ee4bf286 | ||
|
|
10a01fa5b4 | ||
|
|
2946127ed7 | ||
|
|
416979cdbd | ||
|
|
1442215ce5 | ||
|
|
ba3bdcd6a1 | ||
|
|
877fb9ea87 | ||
|
|
9d3864b7f0 | ||
|
|
8411ec0787 | ||
|
|
76be4b8c0a | ||
|
|
8236277906 | ||
|
|
b2255cfd24 | ||
|
|
aa8c1a5421 | ||
|
|
7997e6aaf4 | ||
|
|
fa45b8f96e | ||
|
|
b2fbe51659 | ||
|
|
937cb98256 | ||
|
|
9cfeba9ba1 | ||
|
|
e730e3ff63 | ||
|
|
6b580cbb00 | ||
|
|
cb33fe2fc0 | ||
|
|
bff6f7587f | ||
|
|
12a72970fb | ||
|
|
16e1d64b74 | ||
|
|
9dbad4745d | ||
|
|
0e7d1ab65b | ||
|
|
b69eff367c | ||
|
|
54ef114370 | ||
|
|
e984949aa7 | ||
|
|
25be9d5b9b | ||
|
|
46dec78806 | ||
|
|
c8c8736cf3 | ||
|
|
380c5b5588 | ||
|
|
9360de4ef8 | ||
|
|
138e164878 | ||
|
|
410ad22821 | ||
|
|
8d59880d02 | ||
|
|
7d340869fc | ||
|
|
755d218594 | ||
|
|
b304140720 | ||
|
|
a021b71261 | ||
|
|
a89ac67d59 | ||
|
|
426dc3fa47 | ||
|
|
947a70a638 | ||
|
|
9041e73345 | ||
|
|
ea01a536ce | ||
|
|
56f471b1b6 | ||
|
|
9a216682c8 | ||
|
|
e2e5a3919b | ||
|
|
adc7c02782 | ||
|
|
4c85aea7c3 | ||
|
|
5c2076daa1 | ||
|
|
578324348d | ||
|
|
dc3e35a928 | ||
|
|
0ee5259466 | ||
|
|
c3e88adc6d | ||
|
|
c368ce2776 | ||
|
|
2cda1fca69 | ||
|
|
dac0c04d20 | ||
|
|
ab5cb01510 | ||
|
|
bc528ccb77 | ||
|
|
ad6f26c8b4 | ||
|
|
db8c4edb08 | ||
|
|
837dd6184e | ||
|
|
51ece5fd00 | ||
|
|
b3ad95fdfc | ||
|
|
d2fc4e60c6 | ||
|
|
1ea38be404 | ||
|
|
d69b1e0520 | ||
|
|
c11e32f511 | ||
|
|
7558a23243 | ||
|
|
14b1476786 | ||
|
|
989f135d9a | ||
|
|
e13d49f43e | ||
|
|
4e67cd0014 | ||
|
|
db0485c600 | ||
|
|
1f904d4cff | ||
|
|
0a4b017697 | ||
|
|
0fb93061b1 | ||
|
|
bc1131ce41 | ||
|
|
5667526ef6 | ||
|
|
fe5992debd | ||
|
|
ca09151092 | ||
|
|
4ddc6b1c90 | ||
|
|
46bc94fbe8 | ||
|
|
842a9278d0 | ||
|
|
f57e115e99 | ||
|
|
beb566f11e | ||
|
|
2fcacd1e84 | ||
|
|
341b267852 | ||
|
|
398e28ed24 | ||
|
|
69a6c6b821 | ||
|
|
becc74714b | ||
|
|
820b221fa5 | ||
|
|
23f71e1959 | ||
|
|
684fd941fb | ||
|
|
9fc617956d | ||
|
|
02ae14fd6b | ||
|
|
a84d7bd2cb | ||
|
|
84b9264d1d | ||
|
|
0ae6435429 | ||
|
|
c47332e2f1 | ||
|
|
7dcd33f203 | ||
|
|
bed56137e3 | ||
|
|
62faf4d82e | ||
|
|
ba62f9c686 | ||
|
|
6f7192bb12 | ||
|
|
767b9e05b3 | ||
|
|
d60bbb72f7 | ||
|
|
c60252d3ce | ||
|
|
475f26398d | ||
|
|
8444a9563e | ||
|
|
2f41a6aecf | ||
|
|
61bb6d359f | ||
|
|
938a4fada4 | ||
|
|
142c6bc19f | ||
|
|
f53af12e02 | ||
|
|
990e92ba00 | ||
|
|
816eeb4647 | ||
|
|
d5b4f43f48 | ||
|
|
4597b4d94d | ||
|
|
691fdac7a4 | ||
|
|
3a37364741 | ||
|
|
c789efbe8a | ||
|
|
ddec66b2ad | ||
|
|
325e99d202 | ||
|
|
76b0b6013a | ||
|
|
183585653f | ||
|
|
6bc9627046 | ||
|
|
ba7eeb12c5 | ||
|
|
2354c615d1 | ||
|
|
3aa530aa84 | ||
|
|
6b0cb8dadb | ||
|
|
ecc8b8cc99 | ||
|
|
74e1483d0b | ||
|
|
b3dace6b45 | ||
|
|
a17b88d80a | ||
|
|
1ee06fb78c | ||
|
|
ac2e9d370b | ||
|
|
a0a9d9e31e | ||
|
|
1e4c0d2e0d | ||
|
|
7c881d0100 | ||
|
|
d83f14799e | ||
|
|
34df4e74d4 | ||
|
|
9593a16cb0 | ||
|
|
3e8bc1dcd3 | ||
|
|
8dd06bba5c | ||
|
|
244d622818 | ||
|
|
34d3f6575a | ||
|
|
e94ac7c75d | ||
|
|
ad19dbb440 | ||
|
|
c18614f96f | ||
|
|
16fdedc4d0 | ||
|
|
057de959b9 | ||
|
|
88d26dbecf | ||
|
|
059af2bb49 | ||
|
|
4403387fa4 | ||
|
|
92a2ae1a11 | ||
|
|
40adc6bbbf | ||
|
|
c073867657 | ||
|
|
a7f5b44488 | ||
|
|
8b8948954d | ||
|
|
2c763f5014 | ||
|
|
5d566d1c02 | ||
|
|
41520b3a71 | ||
|
|
5039de8327 | ||
|
|
2bb1092472 | ||
|
|
16fd2b4447 | ||
|
|
3c27c570d4 | ||
|
|
e25e44b45f | ||
|
|
b20b956e15 | ||
|
|
4f10683c2c | ||
|
|
f40b10ea0b | ||
|
|
38f21a3e89 | ||
|
|
1f0f21a8e5 | ||
|
|
c948c9dd7c | ||
|
|
04d5fa51cf | ||
|
|
c1573c2c2a | ||
|
|
42fba21c6b | ||
|
|
04e3ac9200 | ||
|
|
f9f319d571 | ||
|
|
090dca7848 | ||
|
|
9cf7c7f03c | ||
|
|
d3d26e37d0 | ||
|
|
b79f1b8ff4 | ||
|
|
2a44f95f16 | ||
|
|
dc0ce27963 | ||
|
|
378da8093d | ||
|
|
5261f79e9f | ||
|
|
1659c7fd1a | ||
|
|
ec7bc577d6 | ||
|
|
3f4de99be4 | ||
|
|
1a11f2b192 | ||
|
|
e21d7be725 | ||
|
|
4098352faf | ||
|
|
a25b164cd5 | ||
|
|
45b5150487 | ||
|
|
bd21914b9b | ||
|
|
5848aee1c3 | ||
|
|
a214003559 | ||
|
|
83bb7a9297 | ||
|
|
d3102b1cc5 | ||
|
|
93b22311e3 | ||
|
|
55baa8b695 | ||
|
|
18f16d9ebd | ||
|
|
e9b894da16 | ||
|
|
f3a24d92a4 | ||
|
|
07a9b0e6f7 | ||
|
|
3ca5f10fa8 | ||
|
|
f7b817972f | ||
|
|
9399839d96 | ||
|
|
51a4d1f629 | ||
|
|
bbe3716542 | ||
|
|
7c32fe6b5c | ||
|
|
72ab846be5 | ||
|
|
8e6a2cde0f | ||
|
|
c34d4ee97c | ||
|
|
0194cf8f22 | ||
|
|
ad06fcc79e | ||
|
|
7d4b82c691 | ||
|
|
69f989d617 | ||
|
|
0f3df860e3 | ||
|
|
5662841d22 | ||
|
|
3f0bbfb6aa | ||
|
|
ba4d6993b7 | ||
|
|
8d4cda030e | ||
|
|
772b828b67 | ||
|
|
78f5360af2 | ||
|
|
a1fdffcabe | ||
|
|
fed00a5662 | ||
|
|
79f2843b09 | ||
|
|
14a477748e | ||
|
|
cebb78979c | ||
|
|
df771470c2 | ||
|
|
e359c60f00 | ||
|
|
53335a8487 | ||
|
|
3f64312283 | ||
|
|
897946af13 | ||
|
|
e90626e05a | ||
|
|
90e9968dcb | ||
|
|
841d0e01dc | ||
|
|
2feee9e956 | ||
|
|
486ba05526 | ||
|
|
ae8394e5f8 | ||
|
|
fa79e609e1 | ||
|
|
cc352e4913 | ||
|
|
903539bd30 | ||
|
|
01c3c19653 | ||
|
|
af0b3142a0 | ||
|
|
6fe41e6f55 | ||
|
|
2a6ad67f77 | ||
|
|
5652284572 | ||
|
|
2eeeadfd10 | ||
|
|
0d5d2dbf5e | ||
|
|
606dbed4a0 | ||
|
|
301b20d19c | ||
|
|
f6196d48ab | ||
|
|
110b09efba | ||
|
|
0fdf81bc92 | ||
|
|
ea1fee2f5f | ||
|
|
ef54a32de0 | ||
|
|
96f9c11320 | ||
|
|
4a5b191f7f | ||
|
|
148d487988 | ||
|
|
7b137f7682 | ||
|
|
2e81ea2c09 | ||
|
|
5150945414 | ||
|
|
ec8cd137cc | ||
|
|
d5365298d2 | ||
|
|
30bf63b4b8 | ||
|
|
e8ee55a502 | ||
|
|
212fa083e2 | ||
|
|
3daf16e65d | ||
|
|
abfaac9772 | ||
|
|
28e6558a48 | ||
|
|
2d20bfd7ac | ||
|
|
45bfcfd2e9 | ||
|
|
46cea8db6b | ||
|
|
b4c0cb65de | ||
|
|
56e611480a | ||
|
|
ff201af778 | ||
|
|
ef2be82c21 | ||
|
|
6fce5c7a84 | ||
|
|
157166269b | ||
|
|
caa273afea | ||
|
|
d58ce3f599 | ||
|
|
19a6f399f3 | ||
|
|
18c964afca | ||
|
|
cedfa5aabb | ||
|
|
cd3a0f85a6 | ||
|
|
1373e709d6 | ||
|
|
baa0ffa5f9 | ||
|
|
3907dac198 | ||
|
|
56722e4747 |
73
.github/workflows/build.yml
vendored
73
.github/workflows/build.yml
vendored
@@ -1,4 +1,4 @@
|
||||
name: continuous-integration/gh-actions/gui
|
||||
name: ci/gh-actions/gui
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
@@ -10,7 +10,7 @@ jobs:
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: install dependencies
|
||||
run: HOMEBREW_NO_AUTO_UPDATE=1 brew install boost hidapi zmq libpgm miniupnpc ldns expat libunwind-headers protobuf qt5 pkg-config
|
||||
run: HOMEBREW_NO_AUTO_UPDATE=1 brew install boost hidapi zmq libpgm libsodium miniupnpc ldns expat libunwind-headers protobuf qt5 pkg-config
|
||||
- name: build
|
||||
run: DEV_MODE=ON make release -j3
|
||||
- name: test qml
|
||||
@@ -34,7 +34,7 @@ jobs:
|
||||
- name: install monero dependencies
|
||||
run: sudo apt -y install build-essential cmake libboost-all-dev miniupnpc libunbound-dev graphviz doxygen libunwind8-dev pkg-config libssl-dev libzmq3-dev libsodium-dev libhidapi-dev libnorm-dev libusb-1.0-0-dev libpgm-dev libprotobuf-dev protobuf-compiler
|
||||
- name: install monero gui dependencies
|
||||
run: sudo apt -y install qtbase5-dev qt5-default qtdeclarative5-dev qml-module-qtquick-controls qml-module-qtquick-controls2 qml-module-qtquick-dialogs qml-module-qtquick-xmllistmodel qml-module-qt-labs-settings qml-module-qt-labs-folderlistmodel qttools5-dev-tools qml-module-qtquick-templates2 libqt5svg5-dev libgcrypt20-dev xvfb
|
||||
run: sudo apt -y install qtbase5-dev qt5-default qtdeclarative5-dev qml-module-qtqml-models2 qml-module-qtquick-controls qml-module-qtquick-controls2 qml-module-qtquick-dialogs qml-module-qtquick-xmllistmodel qml-module-qt-labs-settings qml-module-qt-labs-platform qml-module-qt-labs-folderlistmodel qttools5-dev-tools qml-module-qtquick-templates2 libqt5svg5-dev libgcrypt20-dev xvfb
|
||||
- name: build
|
||||
run: DEV_MODE=ON make release -j3
|
||||
- name: test qml
|
||||
@@ -58,22 +58,59 @@ jobs:
|
||||
- name: test qml
|
||||
run: build/release/bin/monero-wallet-gui --test-qml
|
||||
|
||||
macos-bundle:
|
||||
runs-on: macOS-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: install dependencies
|
||||
run: HOMEBREW_NO_AUTO_UPDATE=1 brew install boost hidapi zmq libpgm miniupnpc ldns expat libunwind-headers protobuf pkg-config python3 p7zip
|
||||
- name: install dependencies
|
||||
run: pip3 install requests semantic_version lxml py7zr
|
||||
- name: download qt
|
||||
run: |
|
||||
curl -O https://raw.githubusercontent.com/engnr/qt-downloader/master/qt-downloader
|
||||
chmod +x qt-downloader
|
||||
./qt-downloader macos desktop 5.15.2 clang_64
|
||||
working-directory: ../
|
||||
- name: build
|
||||
run: CMAKE_PREFIX_PATH=/Users/runner/work/monero-gui/5.15.2/clang_64 make release -j3
|
||||
- name: deploy
|
||||
run: make deploy
|
||||
working-directory: build/release
|
||||
- name: test qml
|
||||
run: build/release/bin/monero-wallet-gui.app/Contents/MacOS/monero-wallet-gui --test-qml
|
||||
- name: create .tar
|
||||
run: tar -cf monero-wallet-gui.tar monero-wallet-gui.app
|
||||
working-directory: build/release/bin
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: ${{ github.job }}
|
||||
path: build/release/bin/monero-wallet-gui.tar
|
||||
|
||||
docker-linux-static:
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
with:
|
||||
submodules: recursive
|
||||
- uses: satackey/action-docker-layer-caching@v0.0.8
|
||||
- uses: satackey/action-docker-layer-caching@v0.0.10
|
||||
continue-on-error: true
|
||||
with:
|
||||
key: docker-linux-static-{hash}
|
||||
restore-keys: |
|
||||
docker-linux-static-
|
||||
- name: preprare build enviroment
|
||||
- name: install dependencies
|
||||
run: sudo apt -y install xvfb libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-randr0 libxcb-render-util0 libxcb-xkb1 libxkbcommon-x11-0
|
||||
- name: prepare build environment
|
||||
run: docker build --tag monero:build-env-linux --build-arg THREADS=3 --file Dockerfile.linux .
|
||||
- name: build
|
||||
run: docker run --rm -v /home/runner/work/monero-gui/monero-gui:/monero-gui -w /monero-gui monero:build-env-linux sh -c 'make release-static -j3'
|
||||
- name: sha256sum
|
||||
run: shasum -a256 /home/runner/work/monero-gui/monero-gui/build/release/bin/monero-wallet-gui
|
||||
- name: test qml
|
||||
run: xvfb-run -a /home/runner/work/monero-gui/monero-gui/build/release/bin/monero-wallet-gui --test-qml
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: ${{ github.job }}
|
||||
@@ -87,16 +124,18 @@ jobs:
|
||||
- uses: actions/checkout@v1
|
||||
with:
|
||||
submodules: recursive
|
||||
- uses: satackey/action-docker-layer-caching@v0.0.8
|
||||
- uses: satackey/action-docker-layer-caching@v0.0.10
|
||||
continue-on-error: true
|
||||
with:
|
||||
key: docker-windows-static-{hash}
|
||||
restore-keys: |
|
||||
docker-windows-static-
|
||||
- name: preprare build enviroment
|
||||
- name: prepare build environment
|
||||
run: docker build --tag monero:build-env-windows --build-arg THREADS=3 --file Dockerfile.windows .
|
||||
- name: build
|
||||
run: docker run --rm -v /home/runner/work/monero-gui/monero-gui:/monero-gui -w /monero-gui monero:build-env-windows sh -c 'make depends root=/depends target=x86_64-w64-mingw32 tag=win-x64 -j3'
|
||||
- name: sha256sum
|
||||
run: shasum -a256 /home/runner/work/monero-gui/monero-gui/build/x86_64-w64-mingw32/release/bin/monero-wallet-gui.exe
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: ${{ github.job }}
|
||||
@@ -110,7 +149,7 @@ jobs:
|
||||
- uses: actions/checkout@v1
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: preprare build enviroment
|
||||
- name: prepare build environment
|
||||
run: docker build --tag monero:build-env-android --build-arg THREADS=3 --file Dockerfile.android .
|
||||
- name: build
|
||||
run: docker run --rm -v /home/runner/work/monero-gui/monero-gui:/monero-gui -e THREADS=3 monero:build-env-android
|
||||
@@ -118,3 +157,21 @@ jobs:
|
||||
with:
|
||||
name: ${{ github.job }}
|
||||
path: /home/runner/work/monero-gui/monero-gui/build/Android/release/android-build/monero-gui.apk
|
||||
|
||||
source-archive:
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: archive
|
||||
run: |
|
||||
pip install git-archive-all
|
||||
export VERSION="monero-gui-$(git describe)"
|
||||
export OUTPUT="$VERSION.tar"
|
||||
echo "OUTPUT=$OUTPUT" >> $GITHUB_ENV
|
||||
/home/runner/.local/bin/git-archive-all --prefix "$VERSION/" --force-submodules "$OUTPUT"
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: ${{ env.OUTPUT }}
|
||||
path: /home/runner/work/monero-gui/monero-gui/${{ env.OUTPUT }}
|
||||
|
||||
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -2,3 +2,6 @@
|
||||
path = monero
|
||||
url = https://github.com/monero-project/monero
|
||||
ignore = all
|
||||
[submodule "external/quirc"]
|
||||
path = external/quirc
|
||||
url = https://github.com/dlbeer/quirc/
|
||||
|
||||
@@ -4,14 +4,13 @@ project(monero-gui)
|
||||
message(STATUS "Initiating compile using CMake ${CMAKE_VERSION}")
|
||||
|
||||
set(VERSION_MAJOR "17")
|
||||
set(VERSION_MINOR "1")
|
||||
set(VERSION_MINOR "2")
|
||||
set(VERSION_REVISION "3")
|
||||
set(VERSION "0.${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_REVISION}")
|
||||
|
||||
option(STATIC "Link libraries statically, requires static Qt")
|
||||
|
||||
option(USE_DEVICE_TREZOR "Trezor support compilation" ON)
|
||||
option(ENABLE_PASS_STRENGTH_METER "Enable zxcvbn library for password strength" OFF)
|
||||
option(WITH_SCANNER "Enable webcam QR scanner" OFF)
|
||||
option(DEV_MODE "Checkout latest monero master on build" OFF)
|
||||
|
||||
@@ -48,8 +47,9 @@ if(NOT MANUAL_SUBMODULES)
|
||||
else()
|
||||
execute_process(COMMAND ${GIT_EXECUTABLE} fetch WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/monero RESULT_VARIABLE GIT_FETCH_RESULT)
|
||||
execute_process(COMMAND ${GIT_EXECUTABLE} checkout -f origin/master WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/monero RESULT_VARIABLE GIT_CHECKOUT_MASTER_RESULT)
|
||||
execute_process(COMMAND ${GIT_EXECUTABLE} submodule sync --recursive WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/monero RESULT_VARIABLE GIT_SUBMODULE_SYNC_RESULT)
|
||||
execute_process(COMMAND ${GIT_EXECUTABLE} submodule update --init --force --recursive WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/monero RESULT_VARIABLE GIT_SUBMODULE_UPDATE_RESULT)
|
||||
if(NOT GIT_FETCH_RESULT EQUAL "0" OR NOT GIT_CHECKOUT_MASTER_RESULT EQUAL "0" OR NOT GIT_SUBMODULE_UPDATE_RESULT EQUAL "0")
|
||||
if(NOT GIT_FETCH_RESULT EQUAL "0" OR NOT GIT_CHECKOUT_MASTER_RESULT EQUAL "0" OR NOT GIT_SUBMODULE_SYNC_RESULT EQUAL "0" OR NOT GIT_SUBMODULE_UPDATE_RESULT EQUAL "0")
|
||||
message(FATAL_ERROR "Updating git submodule to master (-DDEV_MODE=ON) failed")
|
||||
endif()
|
||||
endif()
|
||||
@@ -57,16 +57,13 @@ if(NOT MANUAL_SUBMODULES)
|
||||
endif()
|
||||
|
||||
add_subdirectory(monero)
|
||||
add_subdirectory(external)
|
||||
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
|
||||
set_property(TARGET wallet_merged PROPERTY FOLDER "monero")
|
||||
get_directory_property(ARCH_WIDTH DIRECTORY "monero" DEFINITION ARCH_WIDTH)
|
||||
get_directory_property(UNBOUND_LIBRARY DIRECTORY "monero" DEFINITION UNBOUND_LIBRARY)
|
||||
get_directory_property(DEVICE_TREZOR_READY DIRECTORY "monero" DEFINITION DEVICE_TREZOR_READY)
|
||||
get_directory_property(TREZOR_DEP_LIBS DIRECTORY "monero" DEFINITION TREZOR_DEP_LIBS)
|
||||
|
||||
if (NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
add_definitions(-DQT_NO_DEBUG)
|
||||
@@ -80,13 +77,6 @@ if(STATIC)
|
||||
add_definitions(-DMONERO_GUI_STATIC)
|
||||
endif()
|
||||
|
||||
# Include password strength library
|
||||
if(ENABLE_PASS_STRENGTH_METER)
|
||||
message(STATUS "Building with pass strength meter support.")
|
||||
else()
|
||||
add_definitions(-DDISABLE_PASS_STRENGTH_METER)
|
||||
endif()
|
||||
|
||||
include(CMakePackageConfigHelpers)
|
||||
|
||||
# force version update
|
||||
@@ -131,30 +121,14 @@ message(STATUS "OpenSSL: Version ${OPENSSL_VERSION}")
|
||||
message(STATUS "OpenSSL: include dir at ${OPENSSL_INCLUDE_DIR}")
|
||||
message(STATUS "OpenSSL: libraries at ${OPENSSL_LIBRARIES} ${OPENSSL_SSL_LIBRARIES}")
|
||||
|
||||
# Zbar (for QR scanner)
|
||||
if(WITH_SCANNER)
|
||||
add_definitions(-DWITH_SCANNER)
|
||||
find_package(ZBar0 REQUIRED)
|
||||
message(STATUS "libzbar: include dir at ${ZBAR_INCLUDE_DIR}")
|
||||
message(STATUS "libzbar: libraries at ${ZBAR_LIBRARIES}")
|
||||
endif()
|
||||
|
||||
# Sodium
|
||||
find_library(SODIUM_LIBRARY sodium)
|
||||
message(STATUS "libsodium: libraries at ${SODIUM_LIBRARY}")
|
||||
|
||||
# LibUSB
|
||||
find_package(LibUSB)
|
||||
message(STATUS "libusb: include dir at ${LibUSB_INCLUDE_DIRS}")
|
||||
message(STATUS "libusb: libraries at ${LibUSB_LIBRARIES}")
|
||||
|
||||
# HIDApi
|
||||
if(NOT ANDROID)
|
||||
find_package(HIDAPI REQUIRED)
|
||||
message(STATUS "libhidapi: include dir at ${HIDAPI_INCLUDE_DIRS}")
|
||||
message(STATUS "libhidapi: libraries at ${HIDAPI_LIBRARIES}")
|
||||
endif()
|
||||
|
||||
# Boost
|
||||
if(DEBUG)
|
||||
set(Boost_DEBUG ON)
|
||||
@@ -178,7 +152,10 @@ find_package(Boost 1.58 REQUIRED COMPONENTS
|
||||
|
||||
if(UNIX AND NOT APPLE AND NOT ANDROID)
|
||||
set(CMAKE_SKIP_RPATH ON)
|
||||
set(CMAKE_FIND_LIBRARY_SUFFIXES_PREV ${CMAKE_FIND_LIBRARY_SUFFIXES})
|
||||
set(CMAKE_FIND_LIBRARY_SUFFIXES ".so")
|
||||
find_package(X11 REQUIRED)
|
||||
set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES_PREV})
|
||||
message(STATUS "X11_FOUND = ${X11_FOUND}")
|
||||
message(STATUS "X11_INCLUDE_DIR = ${X11_INCLUDE_DIR}")
|
||||
message(STATUS "X11_LIBRARIES = ${X11_LIBRARIES}")
|
||||
@@ -229,11 +206,6 @@ if(UNIX)
|
||||
execute_process(COMMAND brew --prefix qt5 OUTPUT_VARIABLE QT5_DIR OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
list(APPEND CMAKE_PREFIX_PATH ${QT5_DIR})
|
||||
endif()
|
||||
|
||||
if(CMAKE_PREFIX_PATH)
|
||||
include_directories(${CMAKE_PREFIX_PATH}/include)
|
||||
set(CMAKE_BUILD_RPATH "${CMAKE_PREFIX_PATH}/lib")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
find_package(PkgConfig REQUIRED)
|
||||
@@ -265,6 +237,13 @@ else()
|
||||
pkg_check_modules(QT5_PKG_CONFIG REQUIRED ${QT5_LIBRARIES_ABI})
|
||||
endif()
|
||||
|
||||
get_target_property(QMAKE_IMPORTED_LOCATION Qt5::qmake IMPORTED_LOCATION)
|
||||
get_filename_component(QT_INSTALL_PREFIX "${QMAKE_IMPORTED_LOCATION}/../.." ABSOLUTE)
|
||||
|
||||
if(APPLE AND NOT STATIC)
|
||||
set(CMAKE_BUILD_RPATH "${QT_INSTALL_PREFIX}/lib")
|
||||
endif()
|
||||
|
||||
if(QT5_PKG_CONFIG_FOUND)
|
||||
set(QT5_PKG_CONFIG "QT5_PKG_CONFIG")
|
||||
if(STATIC)
|
||||
@@ -276,10 +255,10 @@ if(QT5_PKG_CONFIG_FOUND)
|
||||
list(JOIN ${QT5_PKG_CONFIG}_LDFLAGS_OTHER " " ${QT5_PKG_CONFIG}_LDFLAGS_OTHER)
|
||||
endif()
|
||||
# temporal workaround for https://bugreports.qt.io/browse/QTBUG-80922
|
||||
STRING(REPLACE "${QT5_PKG_CONFIG_Qt5Core_PREFIX}" "${CMAKE_PREFIX_PATH}" ${QT5_PKG_CONFIG}_LDFLAGS_OTHER "${${QT5_PKG_CONFIG}_LDFLAGS_OTHER}")
|
||||
STRING(REPLACE "${QT5_PKG_CONFIG_Qt5Core_PREFIX}" "${CMAKE_PREFIX_PATH}" ${QT5_PKG_CONFIG}_LIBRARIES "${${QT5_PKG_CONFIG}_LIBRARIES}")
|
||||
STRING(REPLACE "${QT5_PKG_CONFIG_Qt5Core_PREFIX}" "${CMAKE_PREFIX_PATH}" ${QT5_PKG_CONFIG}_INCLUDE_DIRS "${${QT5_PKG_CONFIG}_INCLUDE_DIRS}")
|
||||
STRING(REPLACE "${QT5_PKG_CONFIG_Qt5Core_PREFIX}" "${CMAKE_PREFIX_PATH}" ${QT5_PKG_CONFIG}_LIBRARY_DIRS "${${QT5_PKG_CONFIG}_LIBRARY_DIRS}")
|
||||
STRING(REPLACE "${QT5_PKG_CONFIG_Qt5Core_PREFIX}" "${QT_INSTALL_PREFIX}" ${QT5_PKG_CONFIG}_LDFLAGS_OTHER "${${QT5_PKG_CONFIG}_LDFLAGS_OTHER}")
|
||||
STRING(REPLACE "${QT5_PKG_CONFIG_Qt5Core_PREFIX}" "${QT_INSTALL_PREFIX}" ${QT5_PKG_CONFIG}_LIBRARIES "${${QT5_PKG_CONFIG}_LIBRARIES}")
|
||||
STRING(REPLACE "${QT5_PKG_CONFIG_Qt5Core_PREFIX}" "${QT_INSTALL_PREFIX}" ${QT5_PKG_CONFIG}_INCLUDE_DIRS "${${QT5_PKG_CONFIG}_INCLUDE_DIRS}")
|
||||
STRING(REPLACE "${QT5_PKG_CONFIG_Qt5Core_PREFIX}" "${QT_INSTALL_PREFIX}" ${QT5_PKG_CONFIG}_LIBRARY_DIRS "${${QT5_PKG_CONFIG}_LIBRARY_DIRS}")
|
||||
endif()
|
||||
|
||||
set(QT5_LIBRARIES ${${QT5_PKG_CONFIG}_LIBRARIES} ${${QT5_PKG_CONFIG}_LDFLAGS_OTHER})
|
||||
@@ -297,10 +276,12 @@ list(APPEND QT5_LIBRARIES
|
||||
if(STATIC)
|
||||
set(QT5_EXTRA_PATHS ${QT5_PKG_CONFIG_Qt5Qml_PREFIX}/qml/Qt/labs/folderlistmodel)
|
||||
list(APPEND QT5_EXTRA_PATHS ${QT5_PKG_CONFIG_Qt5Qml_PREFIX}/qml/Qt/labs/settings)
|
||||
list(APPEND QT5_EXTRA_PATHS ${QT5_PKG_CONFIG_Qt5Qml_PREFIX}/qml/Qt/labs/platform)
|
||||
list(APPEND QT5_EXTRA_PATHS ${QT5_PKG_CONFIG_Qt5Qml_PREFIX}/qml/QtGraphicalEffects)
|
||||
list(APPEND QT5_EXTRA_PATHS ${QT5_PKG_CONFIG_Qt5Qml_PREFIX}/qml/QtGraphicalEffects/private)
|
||||
list(APPEND QT5_EXTRA_PATHS ${QT5_PKG_CONFIG_Qt5Qml_PREFIX}/qml/QtMultimedia)
|
||||
list(APPEND QT5_EXTRA_PATHS ${QT5_PKG_CONFIG_Qt5Qml_PREFIX}/qml/QtQml)
|
||||
list(APPEND QT5_EXTRA_PATHS ${QT5_PKG_CONFIG_Qt5Qml_PREFIX}/qml/QtQml/Models.2)
|
||||
list(APPEND QT5_EXTRA_PATHS ${QT5_PKG_CONFIG_Qt5Qml_PREFIX}/qml/QtQuick.2)
|
||||
list(APPEND QT5_EXTRA_PATHS ${QT5_PKG_CONFIG_Qt5Qml_PREFIX}/qml/QtQuick/Controls)
|
||||
list(APPEND QT5_EXTRA_PATHS ${QT5_PKG_CONFIG_Qt5Qml_PREFIX}/qml/QtQuick/Controls.2)
|
||||
@@ -321,14 +302,16 @@ if(STATIC)
|
||||
dialogsprivateplugin
|
||||
qmlfolderlistmodelplugin
|
||||
qmlsettingsplugin
|
||||
qtlabsplatformplugin
|
||||
qmlxmllistmodelplugin
|
||||
qquicklayoutsplugin
|
||||
modelsplugin
|
||||
)
|
||||
|
||||
if(WITH_SCANNER)
|
||||
list(APPEND QT5_EXTRA_LIBRARIES_LIST
|
||||
declarative_multimedia
|
||||
Qt5MultimediaQuick_p
|
||||
Qt5MultimediaQuick
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -385,8 +368,10 @@ if(STATIC)
|
||||
endforeach()
|
||||
|
||||
if(UNIX AND NOT APPLE)
|
||||
pkg_check_modules(X11XCB_XCBGLX_FONTCONFIG REQUIRED x11-xcb xcb-glx fontconfig)
|
||||
list(APPEND QT5_LIBRARIES ${X11XCB_XCBGLX_FONTCONFIG_STATIC_LIBRARIES})
|
||||
pkg_check_modules(X11XCB_XCBGLX REQUIRED x11-xcb xcb-glx)
|
||||
list(APPEND QT5_LIBRARIES ${X11XCB_XCBGLX_LIBRARIES})
|
||||
pkg_check_modules(FONTCONFIG REQUIRED fontconfig)
|
||||
list(APPEND QT5_LIBRARIES ${FONTCONFIG_STATIC_LIBRARIES})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -413,7 +398,7 @@ message(STATUS "Using Boost libraries at ${Boost_LIBRARIES}")
|
||||
include_directories(SYSTEM ${Boost_INCLUDE_DIRS})
|
||||
if(MINGW)
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wa,-mbig-obj")
|
||||
set(EXTRA_LIBRARIES mswsock;ws2_32;iphlpapi;crypt32;bcrypt;winmm)
|
||||
set(EXTRA_LIBRARIES mswsock;ws2_32;iphlpapi;crypt32;bcrypt)
|
||||
if(DEPENDS)
|
||||
set(ICU_LIBRARIES icuio icui18n icuuc icudata icutu iconv)
|
||||
else()
|
||||
@@ -473,7 +458,7 @@ if (NOT OPENBSD AND NOT (WIN32 AND (CMAKE_C_COMPILER_ID STREQUAL "GNU" AND CMAKE
|
||||
add_c_flag_if_supported(-fcf-protection=full C_SECURITY_FLAGS)
|
||||
add_cxx_flag_if_supported(-fcf-protection=full CXX_SECURITY_FLAGS)
|
||||
endif()
|
||||
if (NOT WIN32 AND NOT OPENBSD)
|
||||
if (NOT WIN32 AND NOT OPENBSD AND NOT "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
|
||||
add_c_flag_if_supported(-fstack-clash-protection C_SECURITY_FLAGS)
|
||||
add_cxx_flag_if_supported(-fstack-clash-protection CXX_SECURITY_FLAGS)
|
||||
endif()
|
||||
@@ -536,26 +521,5 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11 ${C_SECURITY_FLAGS}")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 ${CXX_SECURITY_FLAGS}")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LD_SECURITY_FLAGS} ${STATIC_FLAGS}")
|
||||
|
||||
if (HIDAPI_FOUND OR LibUSB_COMPILE_TEST_PASSED)
|
||||
if (APPLE)
|
||||
if(DEPENDS)
|
||||
list(APPEND EXTRA_LIBRARIES "-framework Foundation -framework IOKit")
|
||||
else()
|
||||
find_library(COREFOUNDATION CoreFoundation)
|
||||
find_library(IOKIT IOKit)
|
||||
list(APPEND EXTRA_LIBRARIES ${IOKIT})
|
||||
list(APPEND EXTRA_LIBRARIES ${COREFOUNDATION})
|
||||
endif()
|
||||
endif()
|
||||
if (WIN32)
|
||||
find_library(VERSION_LIBRARY version PATHS /usr/x86_64-w64-mingw32/lib)
|
||||
if(VERSION_LIBRARY STREQUAL "VERSION_LIBRARY-NOTFOUND")
|
||||
set(VERSION_LIBRARY Version)
|
||||
endif()
|
||||
list(APPEND EXTRA_LIBRARIES setupapi ${VERSION_LIBRARY})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_subdirectory(translations)
|
||||
|
||||
add_subdirectory(src)
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
FROM debian:unstable
|
||||
FROM debian:stretch
|
||||
|
||||
ARG THREADS=1
|
||||
ARG ANDROID_NDK_REVISION=21d
|
||||
ARG ANDROID_NDK_HASH=bcf4023eb8cb6976a4c7cff0a8a8f145f162bf4d
|
||||
ARG ANDROID_SDK_REVISION=4333796
|
||||
ARG ANDROID_SDK_HASH=92ffee5a1d98d856634e8b71132e8a95d96c83a63fde1099be3d86df3106def9
|
||||
ARG QT_VERSION=5.15
|
||||
ARG QT_VERSION=5.15.2
|
||||
|
||||
WORKDIR /opt/android
|
||||
ENV WORKDIR=/opt/android
|
||||
@@ -19,12 +19,12 @@ ENV ANDROID_SDK_ROOT=${WORKDIR}/tools
|
||||
ENV JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
|
||||
ENV PATH=${JAVA_HOME}/bin:${PATH}
|
||||
ENV PREFIX=${WORKDIR}/prefix
|
||||
ENV QT_PREFIX=${WORKDIR}/Qt-${QT_VERSION}
|
||||
ENV TOOLCHAIN_DIR=${ANDROID_NDK_ROOT}/toolchains/llvm/prebuilt/linux-x86_64
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y ant automake build-essential ca-certificates-java cmake file gettext git libc6 libncurses5 \
|
||||
libstdc++6 libtinfo5 libtool libz1 openjdk-8-jdk-headless openjdk-8-jre-headless pkg-config python3 unzip wget
|
||||
&& apt-get install -y ant automake build-essential ca-certificates-java file gettext git libc6 libncurses5 \
|
||||
libssl-dev libstdc++6 libtinfo5 libtool libz1 openjdk-8-jdk-headless openjdk-8-jre-headless pkg-config python3 \
|
||||
unzip wget
|
||||
|
||||
RUN wget -q https://dl.google.com/android/repository/sdk-tools-linux-${ANDROID_SDK_REVISION}.zip \
|
||||
&& unzip -q sdk-tools-linux-${ANDROID_SDK_REVISION}.zip \
|
||||
@@ -66,7 +66,7 @@ RUN git clone git://code.qt.io/qt/qt5.git -b ${QT_VERSION} --depth 1 \
|
||||
-no-sql-mysql \
|
||||
-opensource -confirm-license \
|
||||
-android-arch arm64-v8a \
|
||||
-prefix ${QT_PREFIX} \
|
||||
-prefix ${PREFIX} \
|
||||
-nomake tools -nomake tests -nomake examples \
|
||||
-skip qtwebengine \
|
||||
-skip qtserialport \
|
||||
@@ -78,11 +78,11 @@ RUN git clone git://code.qt.io/qt/qt5.git -b ${QT_VERSION} --depth 1 \
|
||||
&& sed -i '213,215d' qtbase/src/3rdparty/pcre2/src/sljit/sljitConfigInternal.h \
|
||||
&& PATH=${HOST_PATH} make -j${THREADS} \
|
||||
&& PATH=${HOST_PATH} make -j${THREADS} install \
|
||||
&& cd qttools/src/linguist/lrelease && \
|
||||
../../../../qtbase/bin/qmake && \
|
||||
PATH=${HOST_PATH} make -j$THREADS install && \
|
||||
cd ../../../.. && \
|
||||
rm -rf $(pwd)
|
||||
&& cd qttools/src/linguist/lrelease \
|
||||
&& ../../../../qtbase/bin/qmake \
|
||||
&& PATH=${HOST_PATH} make -j${THREADS} install \
|
||||
&& cd ../../../.. \
|
||||
&& rm -rf $(pwd)
|
||||
|
||||
ARG ICONV_VERSION=1.16
|
||||
ARG ICONV_HASH=e6a1b1b589654277ee790cce3734f07876ac4ccfaecbee8afa0b649cf529cc04
|
||||
@@ -98,7 +98,7 @@ RUN wget -q http://ftp.gnu.org/pub/gnu/libiconv/libiconv-${ICONV_VERSION}.tar.gz
|
||||
ARG BOOST_VERSION=1_74_0
|
||||
ARG BOOST_VERSION_DOT=1.74.0
|
||||
ARG BOOST_HASH=83bfc1507731a0906e387fc28b7ef5417d591429e51e788417fe9ff025e116b1
|
||||
RUN wget -q https://dl.bintray.com/boostorg/release/${BOOST_VERSION_DOT}/source/boost_${BOOST_VERSION}.tar.bz2 \
|
||||
RUN wget -q https://downloads.sourceforge.net/project/boost/boost/${BOOST_VERSION_DOT}/boost_${BOOST_VERSION}.tar.bz2 \
|
||||
&& echo "${BOOST_HASH} boost_${BOOST_VERSION}.tar.bz2" | sha256sum -c \
|
||||
&& tar -xf boost_${BOOST_VERSION}.tar.bz2 \
|
||||
&& rm -f boost_${BOOST_VERSION}.tar.bz2 \
|
||||
@@ -152,25 +152,6 @@ RUN set -ex \
|
||||
&& make -j${THREADS} install \
|
||||
&& rm -rf $(pwd)
|
||||
|
||||
RUN git clone https://github.com/ZBar/ZBar.git --depth 1 \
|
||||
&& cd ZBar \
|
||||
&& git reset --hard 854a5d97059e395807091ac4d80c53f7968abb8f \
|
||||
&& sed -i 's/SHARED/STATIC/' android/jni/Android.mk \
|
||||
&& sed -i -E 's/(.*BUILD_STATIC_LIBRARY.*)/LOCAL_CPP_FEATURES := exceptions rtti features\n\0/' android/jni/Android.mk \
|
||||
&& sed -i -E 's/(.*BUILD_STATIC_LIBRARY.*)/LOCAL_CFLAGS := -Wno-multichar\n\0/' android/jni/Android.mk \
|
||||
&& sed -i -E 's/(.*BUILD_STATIC_LIBRARY.*)/LOCAL_CFLAGS += -D_ANDROID\n\0/' android/jni/Android.mk \
|
||||
&& sed -i -E 's/(.*BUILD_STATIC_LIBRARY.*)/LOCAL_CFLAGS += -DLIBDIR="\\".\\""\n\0/' android/jni/Android.mk \
|
||||
&& sed -i -E 's/(.*BUILD_STATIC_LIBRARY.*)/LOCAL_CFLAGS += -DBUILDING_LIBICONV\n\0/' android/jni/Android.mk \
|
||||
&& sed -i -E 's/(.*BUILD_STATIC_LIBRARY.*)/LOCAL_CFLAGS += -DBUILDING_LIBCHARSET\n\0/' android/jni/Android.mk \
|
||||
&& sed -i -E 's/(.*BUILD_STATIC_LIBRARY.*)/LOCAL_CFLAGS += -DIN_LIBRARY\n\0/' android/jni/Android.mk \
|
||||
&& sed -i -E 's/(.*BUILD_STATIC_LIBRARY.*)/LOCAL_CFLAGS += -fno-stack-protector\n\0/' android/jni/Android.mk \
|
||||
&& echo "APP_ABI := arm64-v8a \nAPP_STL := c++_shared \nTARGET_PLATFORM := ${ANDROID_API} \nTARGET_ARCH_ABI := arm64-v8a \nAPP_CFLAGS += -target aarch64-none-linux-android -fexceptions -fstack-protector-strong -fno-limit-debug-info -mfloat-abi=softfp -fno-builtin-memmove -fno-omit-frame-pointer -fno-stack-protector\n" \
|
||||
>> android/jni/Application.mk \
|
||||
&& cd android \
|
||||
&& CC=${ANDROID_CLANG} CXX=${ANDROID_CLANGPP} ${ANDROID_NDK_ROOT}/ndk-build ICONV_SRC=${WORKDIR}/libiconv-${ICONV_VERSION} -B V=1 NDK_APPLICATION_MK=jni/Application.mk \
|
||||
&& cp obj/local/arm64-v8a/lib* ${PREFIX}/lib \
|
||||
&& cp -r ../include/* ${PREFIX}/include
|
||||
|
||||
RUN git clone -b libgpg-error-1.38 --depth 1 git://git.gnupg.org/libgpg-error.git \
|
||||
&& cd libgpg-error \
|
||||
&& git reset --hard 71d278824c5fe61865f7927a2ed1aa3115f9e439 \
|
||||
@@ -195,21 +176,29 @@ RUN cd tools \
|
||||
&& rm -f tools_r25.2.5-linux.zip \
|
||||
&& echo y | ${ANDROID_SDK_ROOT}/tools/android update sdk --no-ui --all --filter build-tools-28.0.3
|
||||
|
||||
RUN git clone -b v3.19.7 --depth 1 https://github.com/Kitware/CMake \
|
||||
&& cd CMake \
|
||||
&& git reset --hard 22612dd53a46c7f9b4c3f4b7dbe5c78f9afd9581 \
|
||||
&& PATH=${HOST_PATH} ./bootstrap \
|
||||
&& PATH=${HOST_PATH} make -j${THREADS} \
|
||||
&& PATH=${HOST_PATH} make -j${THREADS} install \
|
||||
&& rm -rf $(pwd)
|
||||
|
||||
CMD set -ex \
|
||||
&& cd /monero-gui \
|
||||
&& mkdir -p build/Android/release \
|
||||
&& cd build/Android/release \
|
||||
&& cmake \
|
||||
-DCMAKE_TOOLCHAIN_FILE="${ANDROID_NDK_ROOT}/build/cmake/android.toolchain.cmake" \
|
||||
-DCMAKE_PREFIX_PATH="${PREFIX};${QT_PREFIX}" \
|
||||
-DCMAKE_FIND_ROOT_PATH="${PREFIX};${QT_PREFIX}" \
|
||||
-DCMAKE_PREFIX_PATH="${PREFIX}" \
|
||||
-DCMAKE_FIND_ROOT_PATH="${PREFIX}" \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DARCH="armv8-a" \
|
||||
-DANDROID_NATIVE_API_LEVEL=${ANDROID_NATIVE_API_LEVEL} \
|
||||
-DANDROID_ABI="arm64-v8a" \
|
||||
-DANDROID_TOOLCHAIN=clang \
|
||||
-DBoost_USE_STATIC_RUNTIME=ON \
|
||||
-DLRELEASE_PATH="${QT_PREFIX}/bin" \
|
||||
-DLRELEASE_PATH="${PREFIX}/bin" \
|
||||
-DQT_ANDROID_APPLICATION_BINARY="monero-wallet-gui" \
|
||||
-DWITH_SCANNER=ON \
|
||||
../../.. \
|
||||
|
||||
@@ -4,13 +4,16 @@ ARG THREADS=1
|
||||
ARG QT_VERSION=5.15.2
|
||||
|
||||
ENV CFLAGS="-fPIC"
|
||||
ENV CPPFLAGS="-fPIC"
|
||||
ENV CXXFLAGS="-fPIC"
|
||||
ENV SOURCE_DATE_EPOCH=1397818193
|
||||
|
||||
RUN apt update
|
||||
RUN apt update && \
|
||||
apt install -y automake autopoint bison gettext git gperf libgl1-mesa-dev libglib2.0-dev \
|
||||
libpng12-dev libpthread-stubs0-dev libsodium-dev libtool-bin libudev-dev libusb-1.0-0-dev mesa-common-dev \
|
||||
pkg-config python wget xutils-dev
|
||||
|
||||
RUN apt install -y automake git pkg-config python xutils-dev && \
|
||||
git clone -b xorgproto-2020.1 --depth 1 https://gitlab.freedesktop.org/xorg/proto/xorgproto && \
|
||||
RUN git clone -b xorgproto-2020.1 --depth 1 https://gitlab.freedesktop.org/xorg/proto/xorgproto && \
|
||||
cd xorgproto && \
|
||||
git reset --hard c62e8203402cafafa5ba0357b6d1c019156c9f36 && \
|
||||
./autogen.sh && \
|
||||
@@ -26,22 +29,25 @@ RUN git clone -b 1.12 --depth 1 https://gitlab.freedesktop.org/xorg/proto/xcbpro
|
||||
make -j$THREADS install && \
|
||||
rm -rf $(pwd)
|
||||
|
||||
RUN apt install -y libtool-bin && \
|
||||
git clone -b libXau-1.0.9 --depth 1 https://gitlab.freedesktop.org/xorg/lib/libxau && \
|
||||
RUN git clone -b libXau-1.0.9 --depth 1 https://gitlab.freedesktop.org/xorg/lib/libxau && \
|
||||
cd libxau && \
|
||||
git reset --hard d9443b2c57b512cfb250b35707378654d86c7dea && \
|
||||
./autogen.sh --disable-shared --enable-static && \
|
||||
./autogen.sh --enable-shared --disable-static && \
|
||||
make -j$THREADS && \
|
||||
make -j$THREADS install && \
|
||||
rm -rf $(pwd)
|
||||
|
||||
RUN apt install -y libpthread-stubs0-dev && \
|
||||
git clone -b 1.12 --depth 1 https://gitlab.freedesktop.org/xorg/lib/libxcb && \
|
||||
RUN git clone -b 1.12 --depth 1 https://gitlab.freedesktop.org/xorg/lib/libxcb && \
|
||||
cd libxcb && \
|
||||
git reset --hard d34785a34f28fa6a00f8ce00d87e3132ff0f6467 && \
|
||||
./autogen.sh --disable-shared --enable-static && \
|
||||
./autogen.sh --enable-shared --disable-static && \
|
||||
make -j$THREADS && \
|
||||
make -j$THREADS install && \
|
||||
make -j$THREADS clean && \
|
||||
rm /usr/local/lib/libxcb-xinerama.so && \
|
||||
./autogen.sh --disable-shared --enable-static && \
|
||||
make -j$THREADS && \
|
||||
cp src/.libs/libxcb-xinerama.a /usr/local/lib/ && \
|
||||
rm -rf $(pwd)
|
||||
|
||||
RUN git clone -b 0.4.0 --depth 1 https://gitlab.freedesktop.org/xorg/lib/libxcb-util && \
|
||||
@@ -50,7 +56,7 @@ RUN git clone -b 0.4.0 --depth 1 https://gitlab.freedesktop.org/xorg/lib/libxcb-
|
||||
git submodule init && \
|
||||
git clone --depth 1 https://gitlab.freedesktop.org/xorg/util/xcb-util-m4 m4 && \
|
||||
git -C m4 reset --hard f662e3a93ebdec3d1c9374382dcc070093a42fed && \
|
||||
./autogen.sh --disable-shared --enable-static && \
|
||||
./autogen.sh --enable-shared --disable-static && \
|
||||
make -j$THREADS && \
|
||||
make -j$THREADS install && \
|
||||
rm -rf $(pwd)
|
||||
@@ -61,7 +67,7 @@ RUN git clone -b 0.4.0 --depth 1 https://gitlab.freedesktop.org/xorg/lib/libxcb-
|
||||
git submodule init && \
|
||||
git clone --depth 1 https://gitlab.freedesktop.org/xorg/util/xcb-util-m4 m4 && \
|
||||
git -C m4 reset --hard f662e3a93ebdec3d1c9374382dcc070093a42fed && \
|
||||
./autogen.sh --disable-shared --enable-static && \
|
||||
./autogen.sh --enable-shared --disable-static && \
|
||||
make -j$THREADS && \
|
||||
make -j$THREADS install && \
|
||||
rm -rf $(pwd)
|
||||
@@ -72,7 +78,7 @@ RUN git clone -b 0.4.0 --depth 1 https://gitlab.freedesktop.org/xorg/lib/libxcb-
|
||||
git submodule init && \
|
||||
git clone --depth 1 https://gitlab.freedesktop.org/xorg/util/xcb-util-m4 m4 && \
|
||||
git -C m4 reset --hard f662e3a93ebdec3d1c9374382dcc070093a42fed && \
|
||||
./autogen.sh --disable-shared --enable-static && \
|
||||
./autogen.sh --enable-shared --disable-static && \
|
||||
make -j$THREADS && \
|
||||
make -j$THREADS install && \
|
||||
rm -rf $(pwd)
|
||||
@@ -83,7 +89,7 @@ RUN git clone -b 0.3.9 --depth 1 https://gitlab.freedesktop.org/xorg/lib/libxcb-
|
||||
git submodule init && \
|
||||
git clone --depth 1 https://gitlab.freedesktop.org/xorg/util/xcb-util-m4 m4 && \
|
||||
git -C m4 reset --hard f662e3a93ebdec3d1c9374382dcc070093a42fed && \
|
||||
./autogen.sh --disable-shared --enable-static && \
|
||||
./autogen.sh --enable-shared --disable-static && \
|
||||
make -j$THREADS && \
|
||||
make -j$THREADS install && \
|
||||
rm -rf $(pwd)
|
||||
@@ -94,16 +100,15 @@ RUN git clone -b 0.4.1 --depth 1 https://gitlab.freedesktop.org/xorg/lib/libxcb-
|
||||
git submodule init && \
|
||||
git clone --depth 1 https://gitlab.freedesktop.org/xorg/util/xcb-util-m4 m4 && \
|
||||
git -C m4 reset --hard f662e3a93ebdec3d1c9374382dcc070093a42fed && \
|
||||
./autogen.sh --disable-shared --enable-static && \
|
||||
./autogen.sh --enable-shared --disable-static && \
|
||||
make -j$THREADS && \
|
||||
make -j$THREADS install && \
|
||||
rm -rf $(pwd)
|
||||
|
||||
RUN apt install -y bison &&\
|
||||
git clone -b xkbcommon-0.5.0 --depth 1 https://github.com/xkbcommon/libxkbcommon && \
|
||||
RUN git clone -b xkbcommon-0.5.0 --depth 1 https://github.com/xkbcommon/libxkbcommon && \
|
||||
cd libxkbcommon && \
|
||||
git reset --hard c43c3c866eb9d52cd8f61e75cbef1c30d07f3a28 && \
|
||||
./autogen.sh --prefix=/usr --disable-shared --enable-static --enable-x11 --disable-docs && \
|
||||
./autogen.sh --prefix=/usr --enable-shared --disable-static --enable-x11 --disable-docs && \
|
||||
make -j$THREADS && \
|
||||
make -j$THREADS install && \
|
||||
rm -rf $(pwd)
|
||||
@@ -134,8 +139,7 @@ RUN git clone -b R_2_2_9 --depth 1 https://github.com/libexpat/libexpat && \
|
||||
make -j$THREADS install && \
|
||||
rm -rf $(pwd)
|
||||
|
||||
RUN apt install -y autopoint gettext gperf libpng12-dev && \
|
||||
git clone -b 2.13.92 --depth 1 https://gitlab.freedesktop.org/fontconfig/fontconfig && \
|
||||
RUN git clone -b 2.13.92 --depth 1 https://gitlab.freedesktop.org/fontconfig/fontconfig && \
|
||||
cd fontconfig && \
|
||||
git reset --hard b1df1101a643ae16cdfa1d83b939de2497b1bf27 && \
|
||||
./autogen.sh --disable-shared --enable-static --sysconfdir=/etc --localstatedir=/var && \
|
||||
@@ -151,8 +155,7 @@ RUN git clone -b release-64-2 --depth 1 https://github.com/unicode-org/icu && \
|
||||
make -j$THREADS install && \
|
||||
rm -rf $(pwd)
|
||||
|
||||
RUN apt install -y wget && \
|
||||
wget https://dl.bintray.com/boostorg/release/1.73.0/source/boost_1_73_0.tar.gz && \
|
||||
RUN wget https://downloads.sourceforge.net/project/boost/boost/1.73.0/boost_1_73_0.tar.gz && \
|
||||
echo "9995e192e68528793755692917f9eb6422f3052a53c5e13ba278a228af6c7acf boost_1_73_0.tar.gz" | sha256sum -c && \
|
||||
tar -xzf boost_1_73_0.tar.gz && \
|
||||
rm boost_1_73_0.tar.gz && \
|
||||
@@ -171,7 +174,9 @@ RUN wget https://www.openssl.org/source/openssl-1.1.1g.tar.gz && \
|
||||
make -j$THREADS install && \
|
||||
rm -rf $(pwd)
|
||||
|
||||
RUN apt install -y libgl1-mesa-dev libglib2.0-dev mesa-common-dev && \
|
||||
RUN rm /usr/lib/x86_64-linux-gnu/libX11.a && \
|
||||
rm /usr/lib/x86_64-linux-gnu/libXext.a && \
|
||||
rm /usr/lib/x86_64-linux-gnu/libX11-xcb.a && \
|
||||
git clone git://code.qt.io/qt/qt5.git -b ${QT_VERSION} --depth 1 && \
|
||||
cd qt5 && \
|
||||
git clone git://code.qt.io/qt/qtbase.git -b ${QT_VERSION} --depth 1 && \
|
||||
@@ -209,8 +214,7 @@ RUN apt install -y libgl1-mesa-dev libglib2.0-dev mesa-common-dev && \
|
||||
cd ../../../.. && \
|
||||
rm -rf $(pwd)
|
||||
|
||||
RUN apt install -y libudev-dev && \
|
||||
git clone -b v1.0.23 --depth 1 https://github.com/libusb/libusb && \
|
||||
RUN git clone -b v1.0.23 --depth 1 https://github.com/libusb/libusb && \
|
||||
cd libusb && \
|
||||
git reset --hard e782eeb2514266f6738e242cdcb18e3ae1ed06fa && \
|
||||
./autogen.sh --disable-shared --enable-static && \
|
||||
@@ -227,24 +231,7 @@ RUN git clone -b hidapi-0.9.0 --depth 1 https://github.com/libusb/hidapi && \
|
||||
make -j$THREADS install && \
|
||||
rm -rf $(pwd)
|
||||
|
||||
RUN git clone -b libX11-1.6.9 --depth 1 https://gitlab.freedesktop.org/xorg/lib/libx11 && \
|
||||
cd libx11 && \
|
||||
git reset --hard db7cca17ad7807e92a928da9d4c68a00f4836da2 && \
|
||||
./autogen.sh --disable-shared --enable-static && \
|
||||
make -j$THREADS && \
|
||||
make -j$THREADS install && \
|
||||
rm -rf $(pwd)
|
||||
|
||||
RUN git clone -b libXext-1.3.4 --depth 1 https://gitlab.freedesktop.org/xorg/lib/libxext && \
|
||||
cd libxext && \
|
||||
git reset --hard ebb167f34a3514783966775fb12573c4ed209625 && \
|
||||
./autogen.sh --disable-shared --enable-static && \
|
||||
make -j$THREADS && \
|
||||
make -j$THREADS install && \
|
||||
rm -rf $(pwd)
|
||||
|
||||
RUN apt install -y libsodium-dev && \
|
||||
git clone -b v4.3.2 --depth 1 https://github.com/zeromq/libzmq && \
|
||||
RUN git clone -b v4.3.2 --depth 1 https://github.com/zeromq/libzmq && \
|
||||
cd libzmq && \
|
||||
git reset --hard a84ffa12b2eb3569ced199660bac5ad128bff1f0 && \
|
||||
./autogen.sh && \
|
||||
@@ -287,5 +274,3 @@ RUN git clone -b v3.18.4 --depth 1 https://github.com/Kitware/CMake && \
|
||||
make -j$THREADS && \
|
||||
make -j$THREADS install && \
|
||||
rm -rf $(pwd)
|
||||
|
||||
RUN apt install -y libusb-1.0-0-dev
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
FROM ubuntu:20.04
|
||||
|
||||
ARG THREADS=1
|
||||
ARG QT_VERSION=5.15.2
|
||||
ENV SOURCE_DATE_EPOCH=1397818193
|
||||
|
||||
RUN apt update && \
|
||||
DEBIAN_FRONTEND=noninteractive apt install -y build-essential cmake g++-mingw-w64 gettext git libtool pkg-config \
|
||||
@@ -19,26 +21,35 @@ RUN git clone -b v0.17.0.0 --depth 1 https://github.com/monero-project/monero &&
|
||||
|
||||
RUN make -j$THREADS -C /depends HOST=x86_64-w64-mingw32 NO_QT=1
|
||||
|
||||
RUN curl -LO https://download.qt.io/archive/qt/5.9/5.9.9/single/qt-everywhere-opensource-src-5.9.9.tar.xz && \
|
||||
echo "5ce285209290a157d7f42ec8eb22bf3f1d76f2e03a95fc0b99b553391be01642 qt-everywhere-opensource-src-5.9.9.tar.xz" > hashsum.txt && \
|
||||
sha256sum -c hashsum.txt && \
|
||||
tar -xf qt-everywhere-opensource-src-5.9.9.tar.xz && \
|
||||
rm qt-everywhere-opensource-src-5.9.9.tar.xz && \
|
||||
cd qt-everywhere-opensource-src-5.9.9 && \
|
||||
RUN git clone git://code.qt.io/qt/qt5.git -b ${QT_VERSION} --depth 1 && \
|
||||
cd qt5 && \
|
||||
git clone git://code.qt.io/qt/qtbase.git -b ${QT_VERSION} --depth 1 && \
|
||||
git clone git://code.qt.io/qt/qtdeclarative.git -b ${QT_VERSION} --depth 1 && \
|
||||
git clone git://code.qt.io/qt/qtgraphicaleffects.git -b ${QT_VERSION} --depth 1 && \
|
||||
git clone git://code.qt.io/qt/qtimageformats.git -b ${QT_VERSION} --depth 1 && \
|
||||
git clone git://code.qt.io/qt/qtmultimedia.git -b ${QT_VERSION} --depth 1 && \
|
||||
git clone git://code.qt.io/qt/qtquickcontrols.git -b ${QT_VERSION} --depth 1 && \
|
||||
git clone git://code.qt.io/qt/qtquickcontrols2.git -b ${QT_VERSION} --depth 1 && \
|
||||
git clone git://code.qt.io/qt/qtsvg.git -b ${QT_VERSION} --depth 1 && \
|
||||
git clone git://code.qt.io/qt/qttools.git -b ${QT_VERSION} --depth 1 && \
|
||||
git clone git://code.qt.io/qt/qttranslations.git -b ${QT_VERSION} --depth 1 && \
|
||||
git clone git://code.qt.io/qt/qtxmlpatterns.git -b ${QT_VERSION} --depth 1 && \
|
||||
./configure --prefix=/depends/x86_64-w64-mingw32 -xplatform win32-g++ \
|
||||
-device-option CROSS_COMPILE=/usr/bin/x86_64-w64-mingw32- \
|
||||
-I $(pwd)/qtbase/src/3rdparty/angle/include \
|
||||
-opensource -confirm-license -release -static -static-runtime -opengl dynamic -no-angle \
|
||||
-no-avx -no-openssl -no-sql-sqlite \
|
||||
-no-feature-qml-worker-script -no-openssl -no-sql-sqlite \
|
||||
-qt-freetype -qt-harfbuzz -qt-libjpeg -qt-libpng -qt-pcre -qt-zlib \
|
||||
-skip gamepad -skip location -skip qt3d -skip qtactiveqt -skip qtandroidextras -skip qtcanvas3d -skip qtcharts \
|
||||
-skip qtconnectivity -skip qtdatavis3d -skip qtdoc -skip qtgamepad -skip qtlocation -skip qtmacextras \
|
||||
-skip qtmultimedia -skip qtnetworkauth -skip qtpurchasing -skip qtscript -skip qtscxml -skip qtsensors \
|
||||
-skip qtserialbus -skip qtserialport -skip qtspeech -skip qttools -skip qtvirtualkeyboard -skip qtwayland \
|
||||
-skip qtwebchannel -skip qtwebengine -skip qtwebsockets -skip qtwebview -skip qtwinextras -skip qtx11extras \
|
||||
-skip gamepad -skip location -skip qt3d -skip qtactiveqt -skip qtandroidextras \
|
||||
-skip qtcanvas3d -skip qtcharts -skip qtconnectivity -skip qtdatavis3d -skip qtdoc \
|
||||
-skip qtgamepad -skip qtlocation -skip qtmacextras -skip qtnetworkauth -skip qtpurchasing \
|
||||
-skip qtscript -skip qtscxml -skip qtsensors -skip qtserialbus -skip qtserialport \
|
||||
-skip qtspeech -skip qttools -skip qtvirtualkeyboard -skip qtwayland -skip qtwebchannel \
|
||||
-skip qtwebengine -skip qtwebsockets -skip qtwebview -skip qtwinextras -skip qtx11extras \
|
||||
-skip serialbus -skip webengine \
|
||||
-nomake examples -nomake tests -nomake tools && \
|
||||
make QMAKE="$(pwd)/qtbase/bin/qmake CONFIG-='debug debug_and_release'" -j$THREADS && \
|
||||
make -j$THREADS && \
|
||||
make -j$THREADS install && \
|
||||
cd qttools/src/linguist/lrelease && \
|
||||
../../../../qtbase/bin/qmake && \
|
||||
|
||||
102
LeftPanel.qml
102
LeftPanel.qml
@@ -58,12 +58,9 @@ Rectangle {
|
||||
signal historyClicked()
|
||||
signal transferClicked()
|
||||
signal receiveClicked()
|
||||
signal txkeyClicked()
|
||||
signal sharedringdbClicked()
|
||||
signal advancedClicked()
|
||||
signal settingsClicked()
|
||||
signal addressBookClicked()
|
||||
signal miningClicked()
|
||||
signal signClicked()
|
||||
signal accountClicked()
|
||||
|
||||
function selectItem(pos) {
|
||||
@@ -72,10 +69,6 @@ Rectangle {
|
||||
else if(pos === "Transfer") menuColumn.previousButton = transferButton
|
||||
else if(pos === "Receive") menuColumn.previousButton = receiveButton
|
||||
else if(pos === "AddressBook") menuColumn.previousButton = addressBookButton
|
||||
else if(pos === "Mining") menuColumn.previousButton = miningButton
|
||||
else if(pos === "TxKey") menuColumn.previousButton = txkeyButton
|
||||
else if(pos === "SharedRingDB") menuColumn.previousButton = sharedringdbButton
|
||||
else if(pos === "Sign") menuColumn.previousButton = signButton
|
||||
else if(pos === "Settings") menuColumn.previousButton = settingsButton
|
||||
else if(pos === "Advanced") menuColumn.previousButton = advancedButton
|
||||
else if(pos === "Account") menuColumn.previousButton = accountButton
|
||||
@@ -480,6 +473,7 @@ Rectangle {
|
||||
onClicked: {
|
||||
parent.previousButton.checked = false
|
||||
parent.previousButton = advancedButton
|
||||
panel.advancedClicked()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -490,98 +484,6 @@ Rectangle {
|
||||
anchors.leftMargin: 20
|
||||
}
|
||||
|
||||
// ------------- Mining tab ---------------
|
||||
MoneroComponents.MenuButton {
|
||||
id: miningButton
|
||||
visible: !isAndroid && !isIOS && appWindow.walletMode >= 2
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
text: qsTr("Mining") + translationManager.emptyString
|
||||
symbol: qsTr("M") + translationManager.emptyString
|
||||
under: advancedButton
|
||||
onClicked: {
|
||||
parent.previousButton.checked = false
|
||||
parent.previousButton = miningButton
|
||||
panel.miningClicked()
|
||||
}
|
||||
}
|
||||
|
||||
MoneroComponents.MenuButtonDivider {
|
||||
visible: miningButton.present && appWindow.walletMode >= 2
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.leftMargin: 20
|
||||
}
|
||||
|
||||
// ------------- TxKey tab ---------------
|
||||
MoneroComponents.MenuButton {
|
||||
id: txkeyButton
|
||||
visible: appWindow.walletMode >= 2
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
text: qsTr("Prove/check") + translationManager.emptyString
|
||||
symbol: qsTr("K") + translationManager.emptyString
|
||||
under: advancedButton
|
||||
onClicked: {
|
||||
parent.previousButton.checked = false
|
||||
parent.previousButton = txkeyButton
|
||||
panel.txkeyClicked()
|
||||
}
|
||||
}
|
||||
|
||||
MoneroComponents.MenuButtonDivider {
|
||||
visible: txkeyButton.present && appWindow.walletMode >= 2
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.leftMargin: 20
|
||||
}
|
||||
|
||||
// ------------- Shared RingDB tab ---------------
|
||||
MoneroComponents.MenuButton {
|
||||
id: sharedringdbButton
|
||||
visible: appWindow.walletMode >= 2
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
text: qsTr("Shared RingDB") + translationManager.emptyString
|
||||
symbol: qsTr("G") + translationManager.emptyString
|
||||
under: advancedButton
|
||||
onClicked: {
|
||||
parent.previousButton.checked = false
|
||||
parent.previousButton = sharedringdbButton
|
||||
panel.sharedringdbClicked()
|
||||
}
|
||||
}
|
||||
|
||||
MoneroComponents.MenuButtonDivider {
|
||||
visible: sharedringdbButton.present && appWindow.walletMode >= 2
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.leftMargin: 20
|
||||
}
|
||||
|
||||
// ------------- Sign/verify tab ---------------
|
||||
MoneroComponents.MenuButton {
|
||||
id: signButton
|
||||
visible: appWindow.walletMode >= 2
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
text: qsTr("Sign/verify") + translationManager.emptyString
|
||||
symbol: qsTr("I") + translationManager.emptyString
|
||||
under: advancedButton
|
||||
onClicked: {
|
||||
parent.previousButton.checked = false
|
||||
parent.previousButton = signButton
|
||||
panel.signClicked()
|
||||
}
|
||||
}
|
||||
|
||||
MoneroComponents.MenuButtonDivider {
|
||||
visible: signButton.present && appWindow.walletMode >= 2
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.leftMargin: 20
|
||||
}
|
||||
|
||||
// ------------- Settings tab ---------------
|
||||
MoneroComponents.MenuButton {
|
||||
id: settingsButton
|
||||
|
||||
31
Makefile
31
Makefile
@@ -2,25 +2,36 @@ ANDROID_STANDALONE_TOOLCHAIN_PATH ?= /usr/local/toolchain
|
||||
MANUAL_SUBMODULES ?= OFF
|
||||
|
||||
dotgit=$(shell ls -d .git/config)
|
||||
ifneq ($(dotgit), .git/config)
|
||||
USE_SINGLE_BUILDDIR=1
|
||||
ifeq ($(dotgit), .git/config)
|
||||
ifeq ($(shell git --version > /dev/null 2>&1 ; echo $$?), 0)
|
||||
git = yes
|
||||
else
|
||||
$(warning git command not found)
|
||||
endif
|
||||
endif
|
||||
|
||||
subbuilddir:=$(shell echo `uname | sed -e 's|[:/\\ \(\)]|_|g'`/`git branch | grep '\* ' | cut -f2- -d' '| sed -e 's|[:/\\ \(\)]|_|g'`)
|
||||
builddir := build
|
||||
topdir := ../..
|
||||
ifeq ($(USE_SINGLE_BUILDDIR), OFF)
|
||||
builddir := build/"$(subbuilddir)"
|
||||
topdir := ../../../..
|
||||
deldirs := $(builddir)
|
||||
os := $(shell echo `uname | sed -e 's|[:/\\ \(\)]|_|g'`)
|
||||
builddir := $(builddir)/$(os)
|
||||
topdir := $(topdir)/..
|
||||
|
||||
ifdef git
|
||||
branch := $(shell git branch | grep '\* ' | cut -f2- -d' '| sed -e 's|[:/\\ \(\)]|_|g')
|
||||
builddir := $(builddir)/$(branch)
|
||||
topdir := $(topdir)/..
|
||||
endif
|
||||
|
||||
deldirs := $(builddir)
|
||||
else
|
||||
builddir := build
|
||||
topdir := ../..
|
||||
deldirs := $(builddir)/debug $(builddir)/release $(builddir)/fuzz
|
||||
deldirs := $(builddir)/debug $(builddir)/release $(builddir)/fuzz
|
||||
endif
|
||||
|
||||
default:
|
||||
mkdir -p build && cd build && cmake -D ARCH="x86-64" -D DEV_MODE=$(or ${DEV_MODE},OFF) -DMANUAL_SUBMODULES=${MANUAL_SUBMODULES} -D BUILD_64=ON -D CMAKE_BUILD_TYPE=Release .. && $(MAKE)
|
||||
debug:
|
||||
mkdir -p build && cd build && cmake -D DEV_MODE=$(or ${DEV_MODE},ON) -DMANUAL_SUBMODULES=${MANUAL_SUBMODULES} .. && $(MAKE) VERBOSE=1
|
||||
mkdir -p build && cd build && cmake -D DEV_MODE=$(or ${DEV_MODE},ON) -DMANUAL_SUBMODULES=${MANUAL_SUBMODULES} -D CMAKE_BUILD_TYPE=Debug .. && $(MAKE) VERBOSE=1
|
||||
|
||||
depends:
|
||||
mkdir -p build/$(target)/release
|
||||
|
||||
@@ -51,22 +51,19 @@ Rectangle {
|
||||
property alias flickable: mainFlickable
|
||||
|
||||
property Transfer transferView: Transfer {
|
||||
onPaymentClicked: root.paymentClicked(address, paymentId, amount, mixinCount, priority, description)
|
||||
onPaymentClicked: root.paymentClicked(recipients, paymentId, mixinCount, priority, description)
|
||||
onSweepUnmixableClicked: root.sweepUnmixableClicked()
|
||||
}
|
||||
property Receive receiveView: Receive { }
|
||||
property Merchant merchantView: Merchant { }
|
||||
property TxKey txkeyView: TxKey { }
|
||||
property SharedRingDB sharedringdbView: SharedRingDB { }
|
||||
property History historyView: History { }
|
||||
property Sign signView: Sign { }
|
||||
property Advanced advancedView: Advanced { }
|
||||
property Settings settingsView: Settings { }
|
||||
property Mining miningView: Mining { }
|
||||
property AddressBook addressBookView: AddressBook { }
|
||||
property Keys keysView: Keys { }
|
||||
property Account accountView: Account { }
|
||||
|
||||
signal paymentClicked(string address, string paymentId, string amount, int mixinCount, int priority, string description)
|
||||
signal paymentClicked(var recipients, string paymentId, int mixinCount, int priority, string description)
|
||||
signal sweepUnmixableClicked()
|
||||
signal generatePaymentIdInvoked()
|
||||
signal getProofClicked(string txid, string address, string message);
|
||||
@@ -119,6 +116,12 @@ Rectangle {
|
||||
transferView.sendTo(address, paymentId, description);
|
||||
}
|
||||
|
||||
// open Transactions page with search term in search field
|
||||
function searchInHistory(searchTerm){
|
||||
root.state = "History";
|
||||
historyView.searchInHistory(searchTerm);
|
||||
}
|
||||
|
||||
states: [
|
||||
State {
|
||||
name: "History"
|
||||
@@ -136,30 +139,18 @@ Rectangle {
|
||||
name: "Merchant"
|
||||
PropertyChanges { target: root; currentView: merchantView }
|
||||
PropertyChanges { target: mainFlickable; contentHeight: merchantView.merchantHeight + 80 }
|
||||
}, State {
|
||||
name: "TxKey"
|
||||
PropertyChanges { target: root; currentView: txkeyView }
|
||||
PropertyChanges { target: mainFlickable; contentHeight: txkeyView.txkeyHeight + 80 }
|
||||
}, State {
|
||||
name: "SharedRingDB"
|
||||
PropertyChanges { target: root; currentView: sharedringdbView }
|
||||
PropertyChanges { target: mainFlickable; contentHeight: sharedringdbView.panelHeight + 80 }
|
||||
}, State {
|
||||
name: "AddressBook"
|
||||
PropertyChanges { target: root; currentView: addressBookView }
|
||||
PropertyChanges { target: mainFlickable; contentHeight: addressBookView.addressbookHeight + 80 }
|
||||
}, State {
|
||||
name: "Sign"
|
||||
PropertyChanges { target: root; currentView: signView }
|
||||
PropertyChanges { target: mainFlickable; contentHeight: signView.signHeight + 80 }
|
||||
name: "Advanced"
|
||||
PropertyChanges { target: root; currentView: advancedView }
|
||||
PropertyChanges { target: mainFlickable; contentHeight: advancedView.panelHeight }
|
||||
}, State {
|
||||
name: "Settings"
|
||||
PropertyChanges { target: root; currentView: settingsView }
|
||||
PropertyChanges { target: mainFlickable; contentHeight: settingsView.settingsHeight }
|
||||
}, State {
|
||||
name: "Mining"
|
||||
PropertyChanges { target: root; currentView: miningView }
|
||||
PropertyChanges { target: mainFlickable; contentHeight: miningView.miningHeight + 80 }
|
||||
}, State {
|
||||
name: "Keys"
|
||||
PropertyChanges { target: root; currentView: keysView }
|
||||
@@ -168,7 +159,7 @@ Rectangle {
|
||||
name: "Account"
|
||||
PropertyChanges { target: root; currentView: accountView }
|
||||
PropertyChanges { target: mainFlickable; contentHeight: accountView.accountHeight + 80 }
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
ColumnLayout {
|
||||
|
||||
56
README.md
56
README.md
@@ -2,12 +2,29 @@
|
||||
|
||||
Copyright (c) 2014-2019, The Monero Project
|
||||
|
||||
## Table of Contents
|
||||
* [Development resources](#development-resources)
|
||||
* [Vulnerability response](#vulnerability-response)
|
||||
* [Introduction](#introduction)
|
||||
* [About this project](#about-this-project)
|
||||
* [Supporting the project](#supporting-the-project)
|
||||
* [License](#license)
|
||||
* [Translations](#translations)
|
||||
* [Installing the Monero GUI from a package](#installing-the-monero-gui-from-a-package)
|
||||
* [Compiling the Monero GUI from source](#compiling-the-monero-gui-from-source)
|
||||
+ [Building Reproducible Windows static binaries with Docker (any OS)](#building-reproducible-windows-static-binaries-with-docker-any-os)
|
||||
+ [Building Reproducible Linux static binaries with Docker (any OS)](#building-reproducible-linux-static-binaries-with-docker-any-os)
|
||||
+ [Building Android APK with Docker (any OS) *Experimental*](#building-android-apk-with-docker-any-os-experimental)
|
||||
+ [Building on Linux](#building-on-linux)
|
||||
+ [Building on OS X](#building-on-os-x)
|
||||
+ [Building on Windows](#building-on-windows)
|
||||
|
||||
## Development resources
|
||||
|
||||
- Web: [getmonero.org](https://getmonero.org)
|
||||
- Mail: [dev@getmonero.org](mailto:dev@getmonero.org)
|
||||
- Github: [https://github.com/monero-project/monero-gui](https://github.com/monero-project/monero-gui)
|
||||
- IRC: [#monero-dev on Freenode](irc://chat.freenode.net/#monero-dev)
|
||||
- IRC: [#monero-gui on Libera](irc://irc.libera.chat/#monero-gui)
|
||||
- Translation platform (Weblate): [translate.getmonero.org](https://translate.getmonero.org)
|
||||
- UI Design: [Monero-GUI on Figma](https://www.figma.com/file/DplJ2DDQfIKiuRvolHX2hN/Monero-GUI)
|
||||
|
||||
@@ -72,7 +89,7 @@ Packages are available for
|
||||
* Debian: See the [whonix/monero-gui repository](https://gitlab.com/whonix/monero-gui#how-to-install-monero-using-apt-get)
|
||||
* Void Linux: `xbps-install -S monero-gui`
|
||||
* GuixSD: `guix package -i monero-gui`
|
||||
* macOS (homebrew): `brew cask install monero-wallet`
|
||||
* macOS (homebrew): `brew install --cask monero-wallet`
|
||||
|
||||
Packaging for your favorite distribution would be a welcome contribution!
|
||||
|
||||
@@ -80,13 +97,14 @@ Packaging for your favorite distribution would be a welcome contribution!
|
||||
|
||||
*Note*: Qt 5.9.7 is the minimum version required to build the GUI.
|
||||
|
||||
### Building Windows static binaries with Docker (any OS)
|
||||
### Building Reproducible Windows static binaries with Docker (any OS)
|
||||
|
||||
1. Install Docker [https://docs.docker.com/engine/install/](https://docs.docker.com/engine/install/)
|
||||
2. Clone the repository
|
||||
```
|
||||
git clone --recursive https://github.com/monero-project/monero-gui.git
|
||||
git clone --branch master --recursive https://github.com/monero-project/monero-gui.git
|
||||
```
|
||||
\* `master` - replace with the desired version tag (e.g. `v0.17.1.9`) to build the release binaries.
|
||||
3. Prepare build environment
|
||||
```
|
||||
cd monero-gui
|
||||
@@ -102,13 +120,14 @@ Packaging for your favorite distribution would be a welcome contribution!
|
||||
\* `4` - number of CPU threads to use
|
||||
5. Monero GUI Windows static binaries will be placed in `monero-gui/build/x86_64-w64-mingw32/release/bin` directory
|
||||
|
||||
### Building Linux static binaries with Docker (any OS)
|
||||
### Building Reproducible Linux static binaries with Docker (any OS)
|
||||
|
||||
1. Install Docker [https://docs.docker.com/engine/install/](https://docs.docker.com/engine/install/)
|
||||
2. Clone the repository
|
||||
```
|
||||
git clone --recursive https://github.com/monero-project/monero-gui.git
|
||||
git clone --branch master --recursive https://github.com/monero-project/monero-gui.git
|
||||
```
|
||||
\* `master` - replace with the desired version tag (e.g. `v0.17.1.9`) to build the release binaries.
|
||||
3. Prepare build environment
|
||||
```
|
||||
cd monero-gui
|
||||
@@ -123,6 +142,11 @@ Packaging for your favorite distribution would be a welcome contribution!
|
||||
\* `<MONERO_GUI_DIR_FULL_PATH>` - absolute path to `monero-gui` directory
|
||||
\* `4` - number of CPU threads to use
|
||||
5. Monero GUI Linux static binaries will be placed in `monero-gui/build/release/bin` directory
|
||||
6. (*Optional*) Compare `monero-wallet-gui` SHA-256 hash to the one obtained from a trusted source
|
||||
```
|
||||
docker run --rm -it -v <MONERO_GUI_DIR_FULL_PATH>:/monero-gui -w /monero-gui monero:build-env-linux sh -c 'shasum -a 256 /monero-gui/build/release/bin/monero-wallet-gui'
|
||||
```
|
||||
\* `<MONERO_GUI_DIR_FULL_PATH>` - absolute path to `monero-gui` directory
|
||||
|
||||
### Building Android APK with Docker (any OS) *Experimental*
|
||||
- Minimum Android 9 Pie (API 28)
|
||||
@@ -173,7 +197,7 @@ Packaging for your favorite distribution would be a welcome contribution!
|
||||
http://<your.local.ip>:8080/QtApp-debug.apk
|
||||
```
|
||||
|
||||
### On Linux:
|
||||
### Building on Linux
|
||||
|
||||
(Tested on Ubuntu 17.10 x64, Ubuntu 18.04 x64 and Gentoo x64)
|
||||
|
||||
@@ -201,7 +225,7 @@ The following instructions will fetch Qt from your distribution's repositories i
|
||||
|
||||
- For Ubuntu 17.10+
|
||||
|
||||
`sudo apt install qtbase5-dev qt5-default qtdeclarative5-dev qml-module-qtquick-controls qml-module-qtquick-controls2 qml-module-qtquick-dialogs qml-module-qtquick-xmllistmodel qml-module-qt-labs-settings qml-module-qt-labs-folderlistmodel qttools5-dev-tools qml-module-qtquick-templates2 libqt5svg5-dev`
|
||||
`sudo apt install qtbase5-dev qt5-default qtdeclarative5-dev qml-module-qtqml-models2 qml-module-qtquick-controls qml-module-qtquick-controls2 qml-module-qtquick-dialogs qml-module-qtquick-xmllistmodel qml-module-qt-labs-settings qml-module-qt-labs-platform qml-module-qt-labs-folderlistmodel qttools5-dev-tools qml-module-qtquick-templates2 libqt5svg5-dev`
|
||||
|
||||
- For Gentoo
|
||||
|
||||
@@ -211,13 +235,13 @@ The following instructions will fetch Qt from your distribution's repositories i
|
||||
|
||||
- For Ubuntu
|
||||
|
||||
`sudo apt install qtmultimedia5-dev qml-module-qtmultimedia libzbar-dev`
|
||||
`sudo apt install qtmultimedia5-dev qml-module-qtmultimedia`
|
||||
|
||||
- For Gentoo
|
||||
|
||||
The *qml* USE flag must be enabled.
|
||||
|
||||
`emerge dev-qt/qtmultimedia:5 media-gfx/zbar`
|
||||
`emerge dev-qt/qtmultimedia:5`
|
||||
|
||||
|
||||
3. Clone repository
|
||||
@@ -237,7 +261,7 @@ The following instructions will fetch Qt from your distribution's repositories i
|
||||
|
||||
The executable can be found in the build/release/bin folder.
|
||||
|
||||
### On OS X:
|
||||
### Building on OS X
|
||||
|
||||
1. Install Xcode from AppStore
|
||||
|
||||
@@ -245,7 +269,7 @@ The executable can be found in the build/release/bin folder.
|
||||
|
||||
3. Install [monero](https://github.com/monero-project/monero) dependencies:
|
||||
|
||||
`brew install boost hidapi zmq libpgm miniupnpc ldns expat libunwind-headers protobuf libgcrypt`
|
||||
`brew install boost hidapi zmq libpgm libsodium miniupnpc ldns expat libunwind-headers protobuf libgcrypt`
|
||||
|
||||
4. Install Qt:
|
||||
|
||||
@@ -270,7 +294,7 @@ The executable can be found in the `build/release/bin` folder.
|
||||
|
||||
For building an application bundle see `DEPLOY.md`.
|
||||
|
||||
### On Windows:
|
||||
### Building on Windows
|
||||
|
||||
The Monero GUI on Windows is 64 bits only; 32-bit Windows GUI builds are not officially supported anymore.
|
||||
|
||||
@@ -284,12 +308,6 @@ The Monero GUI on Windows is 64 bits only; 32-bit Windows GUI builds are not off
|
||||
pacman -S mingw-w64-x86_64-toolchain make mingw-w64-x86_64-cmake mingw-w64-x86_64-boost mingw-w64-x86_64-openssl mingw-w64-x86_64-zeromq mingw-w64-x86_64-libsodium mingw-w64-x86_64-hidapi mingw-w64-x86_64-protobuf-c mingw-w64-x86_64-libusb mingw-w64-x86_64-libgcrypt
|
||||
```
|
||||
|
||||
Optional : To build the flag `WITH_SCANNER`
|
||||
|
||||
```
|
||||
pacman -S mingw-w64-x86_64-zbar
|
||||
```
|
||||
|
||||
You find more details about those dependencies in the [Monero documentation](https://github.com/monero-project/monero). Note that that there is no more need to compile Boost from source; like everything else, you can install it now with a MSYS2 package.
|
||||
|
||||
4. Install Qt5
|
||||
|
||||
@@ -17,11 +17,7 @@ if(APPLE OR (WIN32 AND NOT STATIC))
|
||||
add_custom_command(TARGET deploy
|
||||
POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${_qt_svg_dylib} $<TARGET_FILE_DIR:monero-wallet-gui>/../PlugIns/imageformats/
|
||||
COMMAND ${CMAKE_INSTALL_NAME_TOOL} -change "${CMAKE_PREFIX_PATH}/lib/QtGui.framework/Versions/5/QtGui" "@executable_path/../Frameworks/QtGui.fr amework/Versions/5/QtGui" $<TARGET_FILE_DIR:monero-wallet-gui>/../PlugIns/imageformats/libqsvg.dylib
|
||||
COMMAND ${CMAKE_INSTALL_NAME_TOOL} -change "${CMAKE_PREFIX_PATH}/lib/QtWidgets.framework/Versions/5/QtWidgets" "@executable_path/../Frameworks/ QtGui.framework/Versions/5/QtGui" $<TARGET_FILE_DIR:monero-wallet-gui>/../PlugIns/imageformats/libqsvg.dylib
|
||||
COMMAND ${CMAKE_INSTALL_NAME_TOOL} -change "${CMAKE_PREFIX_PATH}/lib/QtSvg.framework/Versions/5/QtSvg" "@executable_path/../Frameworks/QtGui.fr amework/Versions/5/QtGui" $<TARGET_FILE_DIR:monero-wallet-gui>/../PlugIns/imageformats/libqsvg.dylib
|
||||
COMMAND ${CMAKE_INSTALL_NAME_TOOL} -change "${CMAKE_PREFIX_PATH}/lib/QtCore.framework/Versions/5/QtCore" "@executable_path/../Frameworks/QtGui. framework/Versions/5/QtGui" $<TARGET_FILE_DIR:monero-wallet-gui>/../PlugIns/imageformats/libqsvg.dylib
|
||||
COMMENT "Copying libqsvg.dylib, running install_name_tool"
|
||||
COMMENT "Copying libqsvg.dylib"
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -78,19 +74,19 @@ if(APPLE OR (WIN32 AND NOT STATIC))
|
||||
)
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
list(APPEND WIN_DEPLOY_DLLS
|
||||
libicudtd67.dll
|
||||
libicuind67.dll
|
||||
libicuiod67.dll
|
||||
libicutud67.dll
|
||||
libicuucd67.dll
|
||||
libicudtd68.dll
|
||||
libicuind68.dll
|
||||
libicuiod68.dll
|
||||
libicutud68.dll
|
||||
libicuucd68.dll
|
||||
)
|
||||
else() # assume release
|
||||
list(APPEND WIN_DEPLOY_DLLS
|
||||
libicudt67.dll
|
||||
libicuin67.dll
|
||||
libicuio67.dll
|
||||
libicutu67.dll
|
||||
libicuuc67.dll
|
||||
libicudt68.dll
|
||||
libicuin68.dll
|
||||
libicuio68.dll
|
||||
libicutu68.dll
|
||||
libicuuc68.dll
|
||||
)
|
||||
endif()
|
||||
list(TRANSFORM WIN_DEPLOY_DLLS PREPEND "$ENV{MSYSTEM_PREFIX}/bin/")
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
# - try to find HIDAPI library
|
||||
# from http://www.signal11.us/oss/hidapi/
|
||||
#
|
||||
# Cache Variables: (probably not for direct use in your scripts)
|
||||
# HIDAPI_INCLUDE_DIR
|
||||
# HIDAPI_LIBRARY
|
||||
#
|
||||
# Non-cache variables you might use in your CMakeLists.txt:
|
||||
# HIDAPI_FOUND
|
||||
# HIDAPI_INCLUDE_DIRS
|
||||
# HIDAPI_LIBRARIES
|
||||
#
|
||||
# Requires these CMake modules:
|
||||
# FindPackageHandleStandardArgs (known included with CMake >=2.6.2)
|
||||
#
|
||||
# Original Author:
|
||||
# 2009-2010 Ryan Pavlik <rpavlik@iastate.edu> <abiryan@ryand.net>
|
||||
# http://academic.cleardefinition.com
|
||||
# Iowa State University HCI Graduate Program/VRAC
|
||||
#
|
||||
# Copyright Iowa State University 2009-2010.
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE_1_0.txt or copy at
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
find_library(HIDAPI_LIBRARY
|
||||
NAMES hidapi hidapi-libusb)
|
||||
|
||||
find_path(HIDAPI_INCLUDE_DIR
|
||||
NAMES hidapi.h
|
||||
PATH_SUFFIXES
|
||||
hidapi)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(HIDAPI
|
||||
DEFAULT_MSG
|
||||
HIDAPI_LIBRARY
|
||||
HIDAPI_INCLUDE_DIR)
|
||||
|
||||
if(HIDAPI_FOUND)
|
||||
set(HIDAPI_LIBRARIES "${HIDAPI_LIBRARY}")
|
||||
if((STATIC AND UNIX AND NOT APPLE) OR (DEPENDS AND CMAKE_SYSTEM_NAME STREQUAL "Linux"))
|
||||
find_library(LIBUSB-1.0_LIBRARY usb-1.0)
|
||||
find_library(LIBUDEV_LIBRARY udev)
|
||||
if(LIBUSB-1.0_LIBRARY)
|
||||
set(HIDAPI_LIBRARIES "${HIDAPI_LIBRARIES};${LIBUSB-1.0_LIBRARY}")
|
||||
if(LIBUDEV_LIBRARY)
|
||||
set(HIDAPI_LIBRARIES "${HIDAPI_LIBRARIES};${LIBUDEV_LIBRARY}")
|
||||
else()
|
||||
message(WARNING "libudev library not found, binaries may fail to link.")
|
||||
endif()
|
||||
else()
|
||||
message(WARNING "libusb-1.0 library not found, binaries may fail to link.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(HIDAPI_INCLUDE_DIRS "${HIDAPI_INCLUDE_DIR}")
|
||||
endif()
|
||||
|
||||
mark_as_advanced(HIDAPI_INCLUDE_DIR HIDAPI_LIBRARY)
|
||||
@@ -1,149 +0,0 @@
|
||||
# - Find libusb for portable USB support
|
||||
# This module will find libusb as published by
|
||||
# http://libusb.sf.net and
|
||||
# http://libusb-win32.sf.net
|
||||
#
|
||||
# It will use PkgConfig if present and supported, else search
|
||||
# it on its own. If the LibUSB_ROOT_DIR environment variable
|
||||
# is defined, it will be used as base path.
|
||||
# The following standard variables get defined:
|
||||
# LibUSB_FOUND: true if LibUSB was found
|
||||
# LibUSB_HEADER_FILE: the location of the C header file
|
||||
# LibUSB_INCLUDE_DIRS: the directory that contains the include file
|
||||
# LibUSB_LIBRARIES: the library
|
||||
# source: https://github.com/IntelRealSense/librealsense
|
||||
|
||||
include ( CheckLibraryExists )
|
||||
include ( CheckIncludeFile )
|
||||
|
||||
find_package ( PkgConfig )
|
||||
if ( PKG_CONFIG_FOUND )
|
||||
pkg_check_modules ( PKGCONFIG_LIBUSB libusb-1.0 )
|
||||
if ( NOT PKGCONFIG_LIBUSB_FOUND )
|
||||
pkg_check_modules ( PKGCONFIG_LIBUSB libusb )
|
||||
endif ( NOT PKGCONFIG_LIBUSB_FOUND )
|
||||
endif ( PKG_CONFIG_FOUND )
|
||||
|
||||
if ( PKGCONFIG_LIBUSB_FOUND )
|
||||
set ( LibUSB_INCLUDE_DIRS ${PKGCONFIG_LIBUSB_INCLUDE_DIRS} )
|
||||
foreach ( i ${PKGCONFIG_LIBUSB_LIBRARIES} )
|
||||
string ( REGEX MATCH "[^-]*" ibase "${i}" )
|
||||
find_library ( ${ibase}_LIBRARY
|
||||
NAMES ${i}
|
||||
PATHS ${PKGCONFIG_LIBUSB_LIBRARY_DIRS}
|
||||
)
|
||||
if ( ${ibase}_LIBRARY )
|
||||
list ( APPEND LibUSB_LIBRARIES ${${ibase}_LIBRARY} )
|
||||
endif ( ${ibase}_LIBRARY )
|
||||
mark_as_advanced ( ${ibase}_LIBRARY )
|
||||
endforeach ( i )
|
||||
|
||||
else ( PKGCONFIG_LIBUSB_FOUND )
|
||||
find_file ( LibUSB_HEADER_FILE
|
||||
NAMES
|
||||
libusb.h usb.h
|
||||
PATHS
|
||||
$ENV{ProgramFiles}/LibUSB-Win32
|
||||
$ENV{LibUSB_ROOT_DIR}
|
||||
PATH_SUFFIXES
|
||||
include
|
||||
libusb-1.0
|
||||
include/libusb-1.0
|
||||
)
|
||||
mark_as_advanced ( LibUSB_HEADER_FILE )
|
||||
get_filename_component ( LibUSB_INCLUDE_DIRS "${LibUSB_HEADER_FILE}" PATH )
|
||||
|
||||
if ( ${CMAKE_SYSTEM_NAME} STREQUAL "Windows" )
|
||||
# LibUSB-Win32 binary distribution contains several libs.
|
||||
# Use the lib that got compiled with the same compiler.
|
||||
if ( MSVC )
|
||||
if ( WIN32 )
|
||||
set ( LibUSB_LIBRARY_PATH_SUFFIX lib/msvc )
|
||||
else ( WIN32 )
|
||||
set ( LibUSB_LIBRARY_PATH_SUFFIX lib/msvc_x64 )
|
||||
endif ( WIN32 )
|
||||
elseif ( BORLAND )
|
||||
set ( LibUSB_LIBRARY_PATH_SUFFIX lib/bcc )
|
||||
elseif ( CMAKE_COMPILER_IS_GNUCC )
|
||||
set ( LibUSB_LIBRARY_PATH_SUFFIX lib/gcc )
|
||||
endif ( MSVC )
|
||||
endif ( ${CMAKE_SYSTEM_NAME} STREQUAL "Windows" )
|
||||
|
||||
find_library ( usb_LIBRARY
|
||||
NAMES
|
||||
usb-1.0 libusb usb
|
||||
PATHS
|
||||
$ENV{ProgramFiles}/LibUSB-Win32
|
||||
$ENV{LibUSB_ROOT_DIR}
|
||||
PATH_SUFFIXES
|
||||
${LibUSB_LIBRARY_PATH_SUFFIX}
|
||||
)
|
||||
mark_as_advanced ( usb_LIBRARY )
|
||||
if ( usb_LIBRARY )
|
||||
set ( LibUSB_LIBRARIES ${usb_LIBRARY} )
|
||||
endif ( usb_LIBRARY )
|
||||
|
||||
endif ( PKGCONFIG_LIBUSB_FOUND )
|
||||
|
||||
if ( LibUSB_INCLUDE_DIRS AND LibUSB_LIBRARIES )
|
||||
set ( LibUSB_FOUND true )
|
||||
endif ( LibUSB_INCLUDE_DIRS AND LibUSB_LIBRARIES )
|
||||
|
||||
if ( LibUSB_FOUND )
|
||||
set ( CMAKE_REQUIRED_INCLUDES "${LibUSB_INCLUDE_DIRS}" )
|
||||
check_include_file ( "${LibUSB_HEADER_FILE}" LibUSB_FOUND )
|
||||
endif ( LibUSB_FOUND )
|
||||
|
||||
if ( LibUSB_FOUND )
|
||||
check_library_exists ( "${LibUSB_LIBRARIES}" usb_open "" LibUSB_FOUND )
|
||||
check_library_exists ( "${LibUSB_LIBRARIES}" libusb_get_device_list "" LibUSB_VERSION_1.0 )
|
||||
check_library_exists ( "${LibUSB_LIBRARIES}" libusb_get_port_numbers "" LibUSB_VERSION_1.0.16 )
|
||||
|
||||
if((STATIC AND UNIX AND NOT APPLE) OR (DEPENDS AND CMAKE_SYSTEM_NAME STREQUAL "Linux"))
|
||||
find_library(LIBUDEV_LIBRARY udev)
|
||||
if(LIBUDEV_LIBRARY)
|
||||
set(LibUSB_LIBRARIES "${LibUSB_LIBRARIES};${LIBUDEV_LIBRARY}")
|
||||
else()
|
||||
message(WARNING "libudev library not found, binaries may fail to link.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Library 1.0.16+ compilation test.
|
||||
# The check_library_exists does not work well on Apple with shared libs.
|
||||
if (APPLE OR LibUSB_VERSION_1.0.16 OR STATIC)
|
||||
if (APPLE)
|
||||
if(DEPENDS)
|
||||
list(APPEND TEST_COMPILE_EXTRA_LIBRARIES "-framework Foundation -framework IOKit")
|
||||
else()
|
||||
find_library(COREFOUNDATION CoreFoundation)
|
||||
find_library(IOKIT IOKit)
|
||||
list(APPEND TEST_COMPILE_EXTRA_LIBRARIES ${IOKIT})
|
||||
list(APPEND TEST_COMPILE_EXTRA_LIBRARIES ${COREFOUNDATION})
|
||||
endif()
|
||||
endif()
|
||||
if (WIN32)
|
||||
list(APPEND TEST_COMPILE_EXTRA_LIBRARIES setupapi)
|
||||
endif()
|
||||
list(APPEND TEST_COMPILE_EXTRA_LIBRARIES ${LibUSB_LIBRARIES})
|
||||
|
||||
try_compile(LibUSB_COMPILE_TEST_PASSED
|
||||
${CMAKE_BINARY_DIR}
|
||||
"${CMAKE_SOURCE_DIR}/cmake/test-libusb-version.c"
|
||||
CMAKE_FLAGS
|
||||
"-DINCLUDE_DIRECTORIES=${LibUSB_INCLUDE_DIRS}"
|
||||
"-DLINK_DIRECTORIES=${LibUSB_LIBRARIES}"
|
||||
LINK_LIBRARIES ${TEST_COMPILE_EXTRA_LIBRARIES}
|
||||
OUTPUT_VARIABLE OUTPUT)
|
||||
unset(TEST_COMPILE_EXTRA_LIBRARIES)
|
||||
message(STATUS "LibUSB Compilation test: ${LibUSB_COMPILE_TEST_PASSED}")
|
||||
endif()
|
||||
endif ( LibUSB_FOUND )
|
||||
|
||||
if ( NOT LibUSB_FOUND )
|
||||
if ( NOT LibUSB_FIND_QUIETLY )
|
||||
message ( STATUS "LibUSB not found, try setting LibUSB_ROOT_DIR environment variable." )
|
||||
endif ( NOT LibUSB_FIND_QUIETLY )
|
||||
if ( LibUSB_FIND_REQUIRED )
|
||||
message ( FATAL_ERROR "" )
|
||||
endif ( LibUSB_FIND_REQUIRED )
|
||||
endif ( NOT LibUSB_FOUND )
|
||||
@@ -1,38 +0,0 @@
|
||||
# from http://code.google.com/p/low-cost-vision-2012/source/browse/CMakeModules/FindZBar0.cmake?name=2-helium-1&r=d61f248bd5565b3c086bf4769a04bfd98f7079df
|
||||
# - Try to find ZBar
|
||||
# This will define
|
||||
#
|
||||
# ZBAR_FOUND -
|
||||
# ZBAR_LIBRARY_DIR -
|
||||
# ZBAR_INCLUDE_DIR -
|
||||
# ZBAR_LIBRARIES -
|
||||
#
|
||||
|
||||
find_package(PkgConfig)
|
||||
if(PkgConfig_FOUND)
|
||||
pkg_check_modules(PC_ZBAR QUIET zbar)
|
||||
if(PC_ZBAR_FOUND)
|
||||
set(ZBAR_DEFINITIONS ${PC_ZBAR_CFLAGS_OTHER})
|
||||
find_library(ZBAR_LIBRARIES NAMES zbar HINTS ${PC_ZBAR_LIBDIR} ${PC_ZBAR_LIBRARY_DIRS})
|
||||
find_path(ZBAR_INCLUDE_DIR Decoder.h HINTS ${PC_ZBAR_INCLUDEDIR} ${PC_ZBAR_INCLUDE_DIRS} PATH_SUFFIXES zbar)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT ZBAR_LIBRARIES AND ANDROID)
|
||||
find_library(ZBARJNI_LIBRARY NAMES zbarjni)
|
||||
find_library(ICONV_LIBRARY NAMES iconv)
|
||||
if(ZBARJNI_LIBRARY AND ICONV_LIBRARY)
|
||||
set(ZBAR_LIBRARIES ${ZBARJNI_LIBRARY} ${ICONV_LIBRARY})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT ZBAR_INCLUDE_DIR)
|
||||
find_path(ZBAR_H_PATH zbar.h)
|
||||
if(ZBAR_H_PATH)
|
||||
set(ZBAR_INCLUDE_DIR "${ZBAR_H_PATH}/zbar")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(ZBAR DEFAULT_MSG ZBAR_LIBRARIES ZBAR_INCLUDE_DIR)
|
||||
message(STATUS "Found zbar libraries ${ZBAR_LIBRARIES}")
|
||||
@@ -1,19 +1,17 @@
|
||||
import QtQuick 2.9
|
||||
import QtQuick.Layouts 1.1
|
||||
import FontAwesome 1.0
|
||||
|
||||
import "../components" as MoneroComponents
|
||||
|
||||
RowLayout {
|
||||
id: advancedOptionsItem
|
||||
|
||||
|
||||
property alias title: title.text
|
||||
property alias tooltip: title.tooltip
|
||||
property alias button1: button1
|
||||
property alias button2: button2
|
||||
property alias button3: button3
|
||||
property alias helpTextLarge: helpTextLarge
|
||||
property alias helpTextSmall: helpTextSmall
|
||||
|
||||
|
||||
RowLayout {
|
||||
id: titlecolumn
|
||||
Layout.alignment: Qt.AlignTop | Qt.AlignLeft
|
||||
@@ -24,24 +22,9 @@ RowLayout {
|
||||
MoneroComponents.Label {
|
||||
id: title
|
||||
fontSize: 14
|
||||
tooltipIconVisible: true
|
||||
}
|
||||
|
||||
MoneroComponents.Label {
|
||||
id: iconLabel
|
||||
fontSize: 12
|
||||
text: FontAwesome.questionCircle
|
||||
fontFamily: FontAwesome.fontFamily
|
||||
opacity: 0.3
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: helpText.visible = !helpText.visible
|
||||
onEntered: parent.opacity = 0.4
|
||||
onExited: parent.opacity = 0.3
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: separator
|
||||
Layout.fillWidth: true
|
||||
@@ -78,29 +61,5 @@ RowLayout {
|
||||
visible: button3.text
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: helpText
|
||||
visible: false
|
||||
Layout.alignment: Qt.AlignTop | Qt.AlignLeft
|
||||
|
||||
MoneroComponents.TextPlain {
|
||||
id: helpTextLarge
|
||||
visible: helpTextLarge.text
|
||||
font.family: MoneroComponents.Style.fontRegular.name
|
||||
font.pixelSize: 13
|
||||
color: MoneroComponents.Style.defaultFontColor
|
||||
}
|
||||
|
||||
MoneroComponents.TextPlain {
|
||||
id: helpTextSmall
|
||||
visible: helpTextSmall.text
|
||||
Layout.leftMargin: 5
|
||||
textFormat: Text.RichText
|
||||
font.family: MoneroComponents.Style.fontRegular.name
|
||||
font.pixelSize: 12
|
||||
color: MoneroComponents.Style.defaultFontColor
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,9 +48,17 @@ Item {
|
||||
property int fontSize: 14
|
||||
property alias fontColor: label.color
|
||||
property bool iconOnTheLeft: true
|
||||
property alias tooltipIconVisible: label.tooltipIconVisible
|
||||
property alias tooltip: label.tooltip
|
||||
signal clicked()
|
||||
|
||||
height: 25
|
||||
width: checkBoxLayout.width
|
||||
opacity: enabled ? 1 : 0.7
|
||||
|
||||
Keys.onEnterPressed: toggle()
|
||||
Keys.onReturnPressed: Keys.onEnterPressed(event)
|
||||
Keys.onSpacePressed: Keys.onEnterPressed(event)
|
||||
|
||||
function toggle(){
|
||||
if (checkBox.toggleOnClick) {
|
||||
@@ -76,7 +84,7 @@ Item {
|
||||
radius: 3
|
||||
color: checkBox.enabled ? "transparent" : MoneroComponents.Style.inputBoxBackgroundDisabled
|
||||
border.color:
|
||||
if(checkBox.checked){
|
||||
if (checkBox.activeFocus) {
|
||||
return MoneroComponents.Style.inputBorderColorActive;
|
||||
} else {
|
||||
return MoneroComponents.Style.inputBorderColorInActive;
|
||||
@@ -115,7 +123,10 @@ Item {
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onEntered: !label.tooltipIconVisible && label.tooltip ? label.tooltipPopup.open() : ""
|
||||
onExited: !label.tooltipIconVisible && label.tooltip ? label.tooltipPopup.close() : ""
|
||||
onClicked: {
|
||||
toggle()
|
||||
}
|
||||
|
||||
@@ -52,6 +52,7 @@ Window {
|
||||
// TODO: implement without hardcoding sizes
|
||||
width: 480
|
||||
height: 200
|
||||
color: MoneroComponents.Style.middlePanelBackgroundColor
|
||||
|
||||
// Make window draggable
|
||||
MouseArea {
|
||||
@@ -96,7 +97,7 @@ Window {
|
||||
Layout.fillWidth: true
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
themeTransition: false
|
||||
color: "black"
|
||||
color: MoneroComponents.Style.defaultFontColor
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ import QtQuick.Controls 2.2 as QtQuickControls2
|
||||
import QtQuick.Layouts 1.2
|
||||
import QtGraphicalEffects 1.0
|
||||
import QtQuick.Controls.Styles 1.2
|
||||
import FontAwesome 1.0
|
||||
|
||||
import "." as MoneroComponents
|
||||
import "effects/" as MoneroEffects
|
||||
@@ -91,8 +92,8 @@ Item {
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
height: parent.height - 1
|
||||
anchors.leftMargin: datePicker.expanded ? 1 : 0
|
||||
anchors.rightMargin: datePicker.expanded ? 1 : 0
|
||||
anchors.leftMargin: 0
|
||||
anchors.rightMargin: 0
|
||||
radius: 4
|
||||
y: 1
|
||||
color: datePicker.backgroundColor
|
||||
@@ -221,21 +222,18 @@ Item {
|
||||
Layout.fillWidth: true
|
||||
color: "transparent"
|
||||
|
||||
Image {
|
||||
MoneroEffects.ImageMask {
|
||||
id: button
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 10
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
source: "qrc:///images/whiteDropIndicator.png"
|
||||
visible: false
|
||||
}
|
||||
|
||||
ColorOverlay {
|
||||
source: button
|
||||
anchors.fill: button
|
||||
image: "qrc:///images/whiteDropIndicator.png"
|
||||
height: 8
|
||||
width: 12
|
||||
fontAwesomeFallbackIcon: FontAwesome.arrowDown
|
||||
fontAwesomeFallbackSize: 14
|
||||
color: MoneroComponents.Style.defaultFontColor
|
||||
rotation: datePicker.expanded ? 180 : 0
|
||||
opacity: 1
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
@@ -252,12 +250,16 @@ Item {
|
||||
id: popup
|
||||
padding: 0
|
||||
closePolicy: QtQuickControls2.Popup.CloseOnEscape | QtQuickControls2.Popup.CloseOnPressOutsideParent
|
||||
onOpened: {
|
||||
calendar.visibleMonth = currentDate.getMonth();
|
||||
calendar.visibleYear = currentDate.getFullYear();
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: calendarRect
|
||||
width: head.width
|
||||
x: head.x
|
||||
y: head.y + head.height + 10
|
||||
y: head.y + head.height - 2
|
||||
|
||||
color: MoneroComponents.Style.middlePanelBackgroundColor
|
||||
border.width: 1
|
||||
@@ -266,11 +268,16 @@ Item {
|
||||
clip: true
|
||||
|
||||
Behavior on height {
|
||||
NumberAnimation { duration: 100; easing.type: Easing.InQuad }
|
||||
NumberAnimation { duration: 150; easing.type: Easing.InQuad }
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
scrollGestureEnabled: false
|
||||
onWheel: {
|
||||
if (wheel.angleDelta.y > 0) return calendar.showPreviousMonth();
|
||||
if (wheel.angleDelta.y < 0) return calendar.showNextMonth();
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
@@ -305,11 +312,6 @@ Item {
|
||||
id: dayRect
|
||||
anchors.fill: parent
|
||||
radius: parent.implicitHeight / 2
|
||||
color: {
|
||||
if(dayArea.pressed && styleData.visibleMonth)
|
||||
return MoneroComponents.Style.blackTheme ? "#20FFFFFF" : "#10000000"
|
||||
return "transparent";
|
||||
}
|
||||
}
|
||||
|
||||
MoneroComponents.TextPlain {
|
||||
@@ -327,19 +329,32 @@ Item {
|
||||
text: styleData.date.getDate()
|
||||
themeTransition: false
|
||||
color: {
|
||||
if(!styleData.visibleMonth) return MoneroComponents.Style.lightGreyFontColor
|
||||
if(dayArea.pressed) return MoneroComponents.Style.defaultFontColor
|
||||
if(styleData.today) return MoneroComponents.Style.orange
|
||||
return MoneroComponents.Style.defaultFontColor
|
||||
if (currentDate.toDateString() === styleData.date.toDateString()) {
|
||||
if (dayArea.containsMouse) {
|
||||
dayRect.color = MoneroComponents.Style.buttonBackgroundColorHover;
|
||||
} else {
|
||||
dayRect.color = MoneroComponents.Style.buttonBackgroundColor;
|
||||
}
|
||||
} else {
|
||||
if (dayArea.containsMouse) {
|
||||
dayRect.color = MoneroComponents.Style.blackTheme ? "#20FFFFFF" : "#10000000"
|
||||
} else {
|
||||
dayRect.color = "transparent";
|
||||
}
|
||||
}
|
||||
if(!styleData.valid) return "transparent"
|
||||
if(styleData.date.toDateString() === (new Date()).toDateString()) return "#FFFF00"
|
||||
if(!styleData.visibleMonth) return MoneroComponents.Style.lightGreyFontColor
|
||||
if(dayArea.pressed) return MoneroComponents.Style.defaultFontColor
|
||||
return MoneroComponents.Style.defaultFontColor
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: dayArea
|
||||
anchors.fill: parent
|
||||
visible: styleData.valid
|
||||
hoverEnabled: true
|
||||
onEntered: dayRect.color = MoneroComponents.Style.blackTheme ? "#20FFFFFF" : "#10000000"
|
||||
onExited: dayRect.color = "transparent"
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
if(styleData.visibleMonth) {
|
||||
@@ -397,18 +412,15 @@ Item {
|
||||
anchors.bottom: parent.bottom
|
||||
width: height
|
||||
|
||||
Image {
|
||||
MoneroEffects.ImageMask {
|
||||
id: prevMonthIcon
|
||||
anchors.centerIn: parent
|
||||
source: "qrc:///images/prevMonth.png"
|
||||
visible: false
|
||||
}
|
||||
|
||||
ColorOverlay {
|
||||
source: prevMonthIcon
|
||||
anchors.fill: prevMonthIcon
|
||||
image: "qrc:///images/prevMonth.png"
|
||||
height: 8
|
||||
width: 12
|
||||
fontAwesomeFallbackIcon: FontAwesome.arrowLeft
|
||||
fontAwesomeFallbackSize: 14
|
||||
color: MoneroComponents.Style.defaultFontColor
|
||||
opacity: 0.5
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
@@ -426,19 +438,16 @@ Item {
|
||||
anchors.bottom: parent.bottom
|
||||
width: height
|
||||
|
||||
Image {
|
||||
MoneroEffects.ImageMask {
|
||||
id: nextMonthIcon
|
||||
anchors.centerIn: parent
|
||||
source: "qrc:///images/prevMonth.png"
|
||||
visible: false
|
||||
}
|
||||
|
||||
ColorOverlay {
|
||||
source: nextMonthIcon
|
||||
anchors.fill: nextMonthIcon
|
||||
color: MoneroComponents.Style.defaultFontColor
|
||||
opacity: 0.5
|
||||
image: "qrc:///images/prevMonth.png"
|
||||
height: 8
|
||||
width: 12
|
||||
rotation: 180
|
||||
fontAwesomeFallbackIcon: FontAwesome.arrowLeft
|
||||
fontAwesomeFallbackSize: 14
|
||||
color: MoneroComponents.Style.defaultFontColor
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
|
||||
66
components/Dialog.qml
Normal file
66
components/Dialog.qml
Normal file
@@ -0,0 +1,66 @@
|
||||
// Copyright (c) 2021, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import QtQuick 2.9
|
||||
import QtQuick.Controls 2.2
|
||||
import QtQuick.Layouts 1.1
|
||||
|
||||
import "." as MoneroComponents
|
||||
|
||||
Popup {
|
||||
id: dialog
|
||||
|
||||
default property alias content: mainLayout.children
|
||||
property alias title: header.text
|
||||
|
||||
background: Rectangle {
|
||||
border.color: MoneroComponents.Style.blackTheme ? Qt.rgba(255, 255, 255, 0.25) : Qt.rgba(0, 0, 0, 0.25)
|
||||
border.width: 1
|
||||
color: MoneroComponents.Style.blackTheme ? "black" : "white"
|
||||
radius: 10
|
||||
}
|
||||
closePolicy: Popup.CloseOnEscape
|
||||
focus: true
|
||||
padding: 20
|
||||
x: (appWindow.width - width) / 2
|
||||
y: (appWindow.height - height) / 2
|
||||
|
||||
ColumnLayout {
|
||||
id: mainLayout
|
||||
spacing: dialog.padding
|
||||
|
||||
Text {
|
||||
id: header
|
||||
color: MoneroComponents.Style.defaultFontColor
|
||||
font.bold: true
|
||||
font.family: MoneroComponents.Style.fontRegular.name
|
||||
font.pixelSize: 18
|
||||
visible: text != ""
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -36,19 +36,28 @@ MoneroEffects.ImageMask {
|
||||
color: MoneroComponents.Style.defaultFontColor
|
||||
image: ""
|
||||
|
||||
property alias tooltip: tooltip.text
|
||||
signal clicked(var mouse)
|
||||
|
||||
MoneroComponents.Tooltip {
|
||||
id: tooltip
|
||||
anchors.fill: parent
|
||||
tooltipLeft: true
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
|
||||
onEntered: {
|
||||
tooltip.text ? tooltip.tooltipPopup.open() : ""
|
||||
button.width = button.width + 2
|
||||
button.height = button.height + 2
|
||||
}
|
||||
|
||||
onExited: {
|
||||
tooltip.text ? tooltip.tooltipPopup.close() : ""
|
||||
button.width = button.width - 2
|
||||
button.height = button.height - 2
|
||||
}
|
||||
|
||||
@@ -30,30 +30,29 @@ import QtQuick 2.9
|
||||
import QtQuick.Layouts 1.1
|
||||
import QtGraphicalEffects 1.0
|
||||
|
||||
import FontAwesome 1.0
|
||||
|
||||
import "." as MoneroComponents
|
||||
import "./effects/" as MoneroEffects
|
||||
|
||||
Item {
|
||||
id: inlineButton
|
||||
height: parent.height
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
|
||||
property bool small: false
|
||||
property string shadowPressedColor: "#B32D00"
|
||||
property string shadowReleasedColor: "#FF4304"
|
||||
property string pressedColor: "#FF4304"
|
||||
property string releasedColor: "#FF6C3C"
|
||||
property string icon: ""
|
||||
property string textColor: MoneroComponents.Style.inlineButtonTextColor
|
||||
property int fontSize: small ? 14 : 16
|
||||
property int rectHeight: small ? 24 : 24
|
||||
property int rectHMargin: small ? 16 : 22
|
||||
property alias text: inlineText.text
|
||||
property alias fontPixelSize: inlineText.font.pixelSize
|
||||
property alias fontFamily: inlineText.font.family
|
||||
property alias fontStyleName: inlineText.font.styleName
|
||||
property bool isFontAwesomeIcon: fontFamily == FontAwesome.fontFamily || fontFamily == FontAwesome.fontFamilySolid
|
||||
property alias buttonColor: rect.color
|
||||
property alias buttonHeight: rect.height
|
||||
property alias tooltip: tooltip.text
|
||||
property alias tooltipLeft: tooltip.tooltipLeft
|
||||
property alias tooltipBottom: tooltip.tooltipBottom
|
||||
|
||||
height: isFontAwesomeIcon ? 30 : 24
|
||||
width: isFontAwesomeIcon ? height : inlineText.width + 16
|
||||
|
||||
signal clicked()
|
||||
|
||||
function doClick() {
|
||||
@@ -64,20 +63,16 @@ Item {
|
||||
|
||||
Rectangle{
|
||||
id: rect
|
||||
anchors.fill: parent
|
||||
color: MoneroComponents.Style.buttonInlineBackgroundColor
|
||||
height: 24
|
||||
width: inlineText.text ? (inlineText.width + 16) : inlineButton.icon ? (inlineImage.width + 16) : rect.height
|
||||
radius: 4
|
||||
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 4
|
||||
|
||||
MoneroComponents.TextPlain {
|
||||
id: inlineText
|
||||
font.family: MoneroComponents.Style.fontBold.name
|
||||
font.bold: true
|
||||
font.pixelSize: inlineButton.fontSize
|
||||
font.pixelSize: inlineButton.isFontAwesomeIcon ? 22 : inlineButton.small ? 14 : 16
|
||||
color: inlineButton.textColor
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
@@ -90,11 +85,9 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
Image {
|
||||
id: inlineImage
|
||||
visible: inlineButton.icon !== ""
|
||||
anchors.centerIn: parent
|
||||
source: inlineButton.icon
|
||||
MoneroComponents.Tooltip {
|
||||
id: tooltip
|
||||
anchors.fill: parent
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
@@ -102,12 +95,17 @@ Item {
|
||||
cursorShape: rect.enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||
hoverEnabled: true
|
||||
anchors.fill: parent
|
||||
onClicked: doClick()
|
||||
onClicked: {
|
||||
tooltip.text ? tooltip.tooltipPopup.close() : ""
|
||||
doClick()
|
||||
}
|
||||
onEntered: {
|
||||
tooltip.text ? tooltip.tooltipPopup.open() : ""
|
||||
rect.color = buttonColor ? buttonColor : "#707070";
|
||||
rect.opacity = 0.8;
|
||||
}
|
||||
onExited: {
|
||||
tooltip.text ? tooltip.tooltipPopup.close() : ""
|
||||
rect.opacity = 1.0;
|
||||
rect.color = buttonColor ? buttonColor : "#808080";
|
||||
}
|
||||
|
||||
@@ -129,6 +129,7 @@ Item {
|
||||
|
||||
MoneroComponents.StandardButton {
|
||||
id: cancelButton
|
||||
primary: false
|
||||
small: true
|
||||
width: 120
|
||||
fontSize: 14
|
||||
|
||||
@@ -34,7 +34,10 @@ import "../components" as MoneroComponents
|
||||
Item {
|
||||
id: item
|
||||
property alias text: label.text
|
||||
property alias tooltip: label.tooltip
|
||||
property alias tooltipIconVisible: label.tooltipIconVisible
|
||||
property alias color: label.color
|
||||
property alias labelMouseArea: labelMouseArea
|
||||
property int textFormat: Text.PlainText
|
||||
property string tipText: ""
|
||||
property int fontSize: 16
|
||||
@@ -70,9 +73,13 @@ Item {
|
||||
onLinkActivated: item.linkActivated()
|
||||
textFormat: parent.textFormat
|
||||
MouseArea {
|
||||
id: labelMouseArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
acceptedButtons: Qt.NoButton
|
||||
cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||
cursorShape: parent.hoveredLink || (tooltip && !tooltipIconVisible) ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||
onEntered: tooltip && !tooltipIconVisible ? parent.tooltipPopup.open() : undefined
|
||||
onExited: tooltip && !tooltipIconVisible ? parent.tooltipPopup.close() : undefined
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,17 +37,6 @@ import QtQuick.Controls 2.0
|
||||
Drawer {
|
||||
id: sideBar
|
||||
|
||||
// @TODO: Qt 5.10 introduces `opened` built-in for Drawer
|
||||
property bool isOpened: false
|
||||
|
||||
onClosed: {
|
||||
isOpened = false;
|
||||
}
|
||||
|
||||
onOpened: {
|
||||
isOpened = true;
|
||||
}
|
||||
|
||||
width: 240
|
||||
height: parent.height - (persistentSettings.customDecorations ? 50 : 0)
|
||||
y: titleBar.height
|
||||
@@ -64,26 +53,64 @@ Drawer {
|
||||
color: "red"
|
||||
|
||||
ListView {
|
||||
id: languagesListView
|
||||
clip: true
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
boundsBehavior: Flickable.StopAtBounds
|
||||
width: sideBar.width
|
||||
height: sideBar.height
|
||||
focus: true
|
||||
|
||||
model: langModel
|
||||
|
||||
Keys.onUpPressed: currentIndex !== 0 ? currentIndex = currentIndex - 1 : ""
|
||||
Keys.onBacktabPressed: currentIndex !== 0 ? currentIndex = currentIndex - 1 : ""
|
||||
Keys.onDownPressed: currentIndex + 1 !== count ? currentIndex = currentIndex + 1 : ""
|
||||
Keys.onTabPressed: currentIndex + 1 !== count ? currentIndex = currentIndex + 1 : ""
|
||||
|
||||
delegate: Rectangle {
|
||||
id: item
|
||||
color: "transparent"
|
||||
color: index == languagesListView.currentIndex ? MoneroComponents.Style.titleBarButtonHoverColor : "transparent"
|
||||
width: sideBar.width
|
||||
height: 32
|
||||
|
||||
Accessible.role: Accessible.ListItem
|
||||
Accessible.name: display_name
|
||||
Keys.onEnterPressed: setSelectedItemAsLanguage();
|
||||
Keys.onReturnPressed: setSelectedItemAsLanguage();
|
||||
Keys.onSpacePressed: setSelectedItemAsLanguage();
|
||||
|
||||
function setSelectedItemAsLanguage() {
|
||||
var locale_spl = locale.split("_");
|
||||
|
||||
// reload active translations
|
||||
console.log(locale_spl[0]);
|
||||
translationManager.setLanguage(locale_spl[0]);
|
||||
|
||||
// set wizard language settings
|
||||
persistentSettings.locale = locale;
|
||||
persistentSettings.language = display_name;
|
||||
persistentSettings.language_wallet = wallet_language;
|
||||
|
||||
appWindow.showStatusMessage(qsTr("Language changed."), 3);
|
||||
appWindow.toggleLanguageView();
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: selectedIndicator
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 0
|
||||
height: parent.height
|
||||
width: 2
|
||||
color: index == languagesListView.currentIndex ? MoneroComponents.Style.buttonBackgroundColor : "transparent"
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: flagRect
|
||||
height: 24
|
||||
width: 24
|
||||
anchors.left: parent.left
|
||||
anchors.left: selectedIndicator.right
|
||||
anchors.leftMargin: 4
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
color: "transparent"
|
||||
@@ -96,8 +123,8 @@ Drawer {
|
||||
|
||||
MoneroComponents.TextPlain {
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 30
|
||||
font.bold: true
|
||||
anchors.leftMargin: 32
|
||||
font.bold: languagesListView.currentIndex == index ? true : false
|
||||
font.pixelSize: 14
|
||||
color: MoneroComponents.Style.defaultFontColor
|
||||
text: display_name
|
||||
@@ -123,21 +150,7 @@ Drawer {
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
var locale_spl = locale.split("_");
|
||||
|
||||
// reload active translations
|
||||
console.log(locale_spl[0]);
|
||||
translationManager.setLanguage(locale_spl[0]);
|
||||
|
||||
// set wizard language settings
|
||||
wizard.language_locale = locale;
|
||||
wizard.language_wallet = wallet_language;
|
||||
wizard.language_language = display_name;
|
||||
|
||||
appWindow.showStatusMessage(qsTr("Language changed."), 3);
|
||||
appWindow.toggleLanguageView();
|
||||
}
|
||||
onClicked: setSelectedItemAsLanguage();
|
||||
hoverEnabled: true
|
||||
onEntered: {
|
||||
// item.color = "#26FFFFFF"
|
||||
@@ -177,4 +190,12 @@ Drawer {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function selectCurrentLanguage() {
|
||||
for (var i = 0; i < langModel.count; ++i) {
|
||||
if (langModel.get(i).display_name === persistentSettings.language) {
|
||||
languagesListView.currentIndex = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,14 +29,25 @@
|
||||
import FontAwesome 1.0
|
||||
import QtQuick 2.9
|
||||
import QtGraphicalEffects 1.0
|
||||
import QtQuick.Layouts 1.1
|
||||
|
||||
import "../components" as MoneroComponents
|
||||
|
||||
Item {
|
||||
ColumnLayout {
|
||||
id: item
|
||||
Layout.fillWidth: true
|
||||
|
||||
default property alias content: inlineButtons.children
|
||||
|
||||
property alias input: input
|
||||
property alias text: input.text
|
||||
|
||||
property int inputPaddingLeft: 10
|
||||
property int inputPaddingRight: 10
|
||||
property int inputPaddingTop: 10
|
||||
property int inputPaddingBottom: 10
|
||||
property int inputRadius: 4
|
||||
|
||||
property bool password: false
|
||||
property bool passwordHidden: true
|
||||
property var passwordLinked: null
|
||||
@@ -48,33 +59,40 @@ Item {
|
||||
property int placeholderFontSize: 18
|
||||
property string placeholderColor: MoneroComponents.Style.defaultFontColor
|
||||
property real placeholderOpacity: 0.35
|
||||
property real placeholderLeftMargin: {
|
||||
if (placeholderCenter) {
|
||||
return undefined;
|
||||
} else {
|
||||
return inputPaddingLeft;
|
||||
}
|
||||
}
|
||||
|
||||
property alias acceptableInput: input.acceptableInput
|
||||
property alias validator: input.validator
|
||||
property alias readOnly : input.readOnly
|
||||
property alias cursorPosition: input.cursorPosition
|
||||
property alias inlineButton: inlineButtonId
|
||||
property alias inlineButtonText: inlineButtonId.text
|
||||
property alias inlineIcon: inlineIcon.visible
|
||||
property bool copyButton: false
|
||||
property bool pasteButton: false
|
||||
property alias copyButtonText: copyButtonId.text
|
||||
property alias copyButtonEnabled: copyButtonId.enabled
|
||||
|
||||
property bool borderDisabled: false
|
||||
property string borderColor: {
|
||||
if(error && input.text !== ""){
|
||||
if ((error && input.text !== "") || (errorWhenEmpty && input.text == "")) {
|
||||
return MoneroComponents.Style.inputBorderColorInvalid;
|
||||
} else if(input.activeFocus){
|
||||
} else if (input.activeFocus) {
|
||||
return MoneroComponents.Style.inputBorderColorActive;
|
||||
} else {
|
||||
return MoneroComponents.Style.inputBorderColorInActive;
|
||||
}
|
||||
}
|
||||
|
||||
property string fontFamily: MoneroComponents.Style.fontRegular.name
|
||||
property int fontSize: 18
|
||||
property bool fontBold: false
|
||||
property alias fontColor: input.color
|
||||
property bool error: false
|
||||
property bool errorWhenEmpty: false
|
||||
property alias labelText: inputLabel.text
|
||||
property alias labelColor: inputLabel.color
|
||||
property alias labelTextFormat: inputLabel.textFormat
|
||||
@@ -85,15 +103,14 @@ Item {
|
||||
property alias labelWrapMode: inputLabel.wrapMode
|
||||
property alias labelHorizontalAlignment: inputLabel.horizontalAlignment
|
||||
property bool showingHeader: inputLabel.text !== "" || copyButton
|
||||
property int inputHeight: 42
|
||||
property int inputHeight: 39
|
||||
|
||||
signal labelLinkActivated(); // input label, rich text <a> signal
|
||||
signal editingFinished();
|
||||
signal accepted();
|
||||
signal textUpdated();
|
||||
|
||||
height: showingHeader ? (inputLabel.height + inputItem.height + 2) : 42
|
||||
|
||||
onActiveFocusChanged: activeFocus && input.forceActiveFocus()
|
||||
onTextUpdated: {
|
||||
// check to remove placeholder text when there is content
|
||||
if(item.isEmpty()){
|
||||
@@ -138,45 +155,100 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
MoneroComponents.TextPlain {
|
||||
id: inputLabel
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
font.family: MoneroComponents.Style.fontRegular.name
|
||||
font.pixelSize: labelFontSize
|
||||
font.bold: labelFontBold
|
||||
textFormat: Text.RichText
|
||||
color: MoneroComponents.Style.defaultFontColor
|
||||
onLinkActivated: item.labelLinkActivated()
|
||||
spacing: 0
|
||||
Rectangle {
|
||||
id: inputLabelRect
|
||||
color: "transparent"
|
||||
Layout.fillWidth: true
|
||||
height: (inputLabel.height + 10)
|
||||
visible: showingHeader ? true : false
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
acceptedButtons: Qt.NoButton
|
||||
cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||
}
|
||||
}
|
||||
MoneroComponents.TextPlain {
|
||||
id: inputLabel
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
font.family: MoneroComponents.Style.fontRegular.name
|
||||
font.pixelSize: labelFontSize
|
||||
font.bold: labelFontBold
|
||||
textFormat: Text.RichText
|
||||
color: MoneroComponents.Style.defaultFontColor
|
||||
onLinkActivated: item.labelLinkActivated()
|
||||
|
||||
MoneroComponents.LabelButton {
|
||||
id: copyButtonId
|
||||
text: qsTr("Copy") + translationManager.emptyString
|
||||
anchors.right: parent.right
|
||||
onClicked: {
|
||||
if (input.text.length > 0) {
|
||||
console.log("Copied to clipboard");
|
||||
clipboard.setText(input.text);
|
||||
appWindow.showStatusMessage(qsTr("Copied to clipboard"), 3);
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
acceptedButtons: Qt.NoButton
|
||||
cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
anchors.right: parent.right
|
||||
spacing: 16
|
||||
|
||||
MoneroComponents.LabelButton {
|
||||
id: copyButtonId
|
||||
text: qsTr("Copy") + translationManager.emptyString
|
||||
onClicked: {
|
||||
if (input.text.length > 0) {
|
||||
console.log("Copied to clipboard");
|
||||
clipboard.setText(input.text);
|
||||
appWindow.showStatusMessage(qsTr("Copied to clipboard"), 3);
|
||||
}
|
||||
}
|
||||
visible: copyButton && input.text !== ""
|
||||
}
|
||||
|
||||
MoneroComponents.LabelButton {
|
||||
id: pasteButtonId
|
||||
onClicked: {
|
||||
input.clear();
|
||||
input.paste();
|
||||
}
|
||||
text: qsTr("Paste") + translationManager.emptyString
|
||||
visible: pasteButton
|
||||
}
|
||||
}
|
||||
visible: copyButton && input.text !== ""
|
||||
}
|
||||
|
||||
Item{
|
||||
id: inputItem
|
||||
height: inputHeight
|
||||
anchors.top: showingHeader ? inputLabel.bottom : parent.top
|
||||
anchors.topMargin: showingHeader ? 12 : 2
|
||||
width: parent.width
|
||||
clip: true
|
||||
MoneroComponents.Input {
|
||||
id: input
|
||||
KeyNavigation.backtab: item.KeyNavigation.backtab
|
||||
KeyNavigation.tab: item.KeyNavigation.tab
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: inputHeight
|
||||
|
||||
leftPadding: item.inputPaddingLeft
|
||||
rightPadding: (inlineButtons.width > 0 ? inlineButtons.width + inlineButtons.spacing : 0) + inputPaddingRight
|
||||
topPadding: item.inputPaddingTop
|
||||
bottomPadding: item.inputPaddingBottom
|
||||
|
||||
font.family: item.fontFamily
|
||||
font.pixelSize: item.fontSize
|
||||
font.bold: item.fontBold
|
||||
onEditingFinished: item.editingFinished()
|
||||
onAccepted: item.accepted();
|
||||
onTextChanged: item.textUpdated()
|
||||
echoMode: isPasswordHidden() ? TextInput.Password : TextInput.Normal
|
||||
|
||||
MoneroComponents.Label {
|
||||
visible: password || passwordLinked
|
||||
fontSize: 20
|
||||
text: isPasswordHidden() ? FontAwesome.eye : FontAwesome.eyeSlash
|
||||
opacity: eyeMouseArea.containsMouse ? 0.9 : 0.7
|
||||
fontFamily: FontAwesome.fontFamily
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 15
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.verticalCenterOffset: 1
|
||||
|
||||
MouseArea {
|
||||
id: eyeMouseArea
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
hoverEnabled: true
|
||||
onClicked: passwordToggle()
|
||||
}
|
||||
}
|
||||
|
||||
MoneroComponents.TextPlain {
|
||||
id: placeholderLabel
|
||||
@@ -184,13 +256,7 @@ Item {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.horizontalCenter: placeholderCenter ? parent.horizontalCenter : undefined
|
||||
anchors.left: placeholderCenter ? undefined : parent.left
|
||||
anchors.leftMargin: {
|
||||
if(placeholderCenter){
|
||||
return undefined;
|
||||
}
|
||||
else if(inlineIcon.visible){ return 50; }
|
||||
else { return 10; }
|
||||
}
|
||||
anchors.leftMargin: placeholderLeftMargin
|
||||
|
||||
opacity: item.placeholderOpacity
|
||||
color: item.placeholderColor
|
||||
@@ -213,60 +279,15 @@ Item {
|
||||
anchors.fill: parent
|
||||
border.width: borderDisabled ? 0 : 1
|
||||
border.color: borderColor
|
||||
radius: 4
|
||||
radius: item.inputRadius
|
||||
}
|
||||
|
||||
Image {
|
||||
id: inlineIcon
|
||||
width: 26
|
||||
height: 26
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 8
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 12
|
||||
source: "qrc:///images/moneroIcon-28x28.png"
|
||||
visible: false
|
||||
}
|
||||
|
||||
MoneroComponents.Input {
|
||||
id: input
|
||||
anchors.fill: parent
|
||||
anchors.leftMargin: inlineIcon.visible ? 44 : 0
|
||||
font.pixelSize: item.fontSize
|
||||
font.bold: item.fontBold
|
||||
onEditingFinished: item.editingFinished()
|
||||
onAccepted: item.accepted();
|
||||
onTextChanged: item.textUpdated()
|
||||
topPadding: 10
|
||||
bottomPadding: 10
|
||||
echoMode: isPasswordHidden() ? TextInput.Password : TextInput.Normal
|
||||
|
||||
MoneroComponents.Label {
|
||||
visible: password || passwordLinked
|
||||
fontSize: 20
|
||||
text: isPasswordHidden() ? FontAwesome.eye : FontAwesome.eyeSlash
|
||||
opacity: eyeMouseArea.containsMouse ? 0.9 : 0.7
|
||||
fontFamily: FontAwesome.fontFamily
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 15
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.verticalCenterOffset: 1
|
||||
|
||||
MouseArea {
|
||||
id: eyeMouseArea
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
hoverEnabled: true
|
||||
onClicked: passwordToggle()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MoneroComponents.InlineButton {
|
||||
id: inlineButtonId
|
||||
visible: item.inlineButtonText ? true : false
|
||||
RowLayout {
|
||||
id: inlineButtons
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 8
|
||||
anchors.rightMargin: inputPaddingRight
|
||||
spacing: 4
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,8 @@ ColumnLayout {
|
||||
|
||||
Layout.fillWidth: true
|
||||
|
||||
default property alias content: inlineButtons.children
|
||||
|
||||
property alias text: input.text
|
||||
property alias labelText: inputLabel.text
|
||||
property alias labelButtonText: labelButton.text
|
||||
@@ -65,7 +67,8 @@ ColumnLayout {
|
||||
}
|
||||
}
|
||||
|
||||
property bool error: false
|
||||
property alias error: input.error
|
||||
property alias cursorPosition: input.cursorPosition
|
||||
|
||||
property string labelFontColor: MoneroComponents.Style.defaultFontColor
|
||||
property bool labelFontBold: false
|
||||
@@ -73,6 +76,7 @@ ColumnLayout {
|
||||
property bool labelButtonVisible: false
|
||||
|
||||
property string fontColor: MoneroComponents.Style.defaultFontColor
|
||||
property string fontFamily: MoneroComponents.Style.fontRegular.name
|
||||
property bool fontBold: false
|
||||
property int fontSize: 16
|
||||
|
||||
@@ -85,14 +89,13 @@ ColumnLayout {
|
||||
property alias addressValidation: input.addressValidation
|
||||
property string backgroundColor: "" // mock
|
||||
|
||||
property alias inlineButton: inlineButtonId
|
||||
property bool inlineButtonVisible: false
|
||||
property alias inlineButton2: inlineButton2Id
|
||||
property bool inlineButton2Visible: false
|
||||
|
||||
signal labelButtonClicked();
|
||||
signal inputLabelLinkActivated();
|
||||
signal editingFinished();
|
||||
signal returnPressed();
|
||||
signal enterPressed();
|
||||
|
||||
onActiveFocusChanged: activeFocus && input.forceActiveFocus()
|
||||
|
||||
spacing: 0
|
||||
Rectangle {
|
||||
@@ -159,20 +162,25 @@ ColumnLayout {
|
||||
id: input
|
||||
readOnly: false
|
||||
addressValidation: false
|
||||
KeyNavigation.backtab: item.KeyNavigation.backtab
|
||||
KeyNavigation.priority: KeyNavigation.BeforeItem
|
||||
KeyNavigation.tab: item.KeyNavigation.tab
|
||||
Layout.fillWidth: true
|
||||
|
||||
|
||||
leftPadding: item.inputPaddingLeft
|
||||
rightPadding: item.inputPaddingRight
|
||||
rightPadding: (inlineButtons.width > 0 ? inlineButtons.width + inlineButtons.spacing : 0) + inputPaddingRight
|
||||
topPadding: item.inputPaddingTop
|
||||
bottomPadding: item.inputPaddingBottom
|
||||
|
||||
wrapMode: item.wrapMode
|
||||
font.family: item.fontFamily
|
||||
fontSize: item.fontSize
|
||||
fontBold: item.fontBold
|
||||
fontColor: item.fontColor
|
||||
mouseSelection: item.mouseSelection
|
||||
onEditingFinished: item.editingFinished()
|
||||
error: item.error
|
||||
Keys.onReturnPressed: item.returnPressed()
|
||||
Keys.onEnterPressed: item.enterPressed()
|
||||
|
||||
MoneroComponents.TextPlain {
|
||||
id: placeholderLabel
|
||||
@@ -198,18 +206,12 @@ ColumnLayout {
|
||||
visible: !item.borderDisabled
|
||||
}
|
||||
|
||||
MoneroComponents.InlineButton {
|
||||
id: inlineButtonId
|
||||
visible: (inlineButtonId.text || inlineButtonId.icon) && inlineButtonVisible ? true : false
|
||||
RowLayout {
|
||||
id: inlineButtons
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 8
|
||||
}
|
||||
|
||||
MoneroComponents.InlineButton {
|
||||
id: inlineButton2Id
|
||||
visible: (inlineButton2Id.text || inlineButton2Id.icon) && inlineButton2Visible ? true : false
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: inlineButtonVisible ? 48 : 8
|
||||
anchors.rightMargin: inputPaddingRight
|
||||
spacing: 4
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
55
components/MenuBar.qml
Normal file
55
components/MenuBar.qml
Normal file
@@ -0,0 +1,55 @@
|
||||
// Copyright (c) 2014-2019, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import Qt.labs.platform 1.0 as PlatformLabs
|
||||
import "." as MoneroComponents
|
||||
|
||||
PlatformLabs.MenuBar {
|
||||
PlatformLabs.Menu {
|
||||
title: qsTr("File")
|
||||
PlatformLabs.MenuItem {
|
||||
enabled: appWindow.viewState === "normal"
|
||||
text: qsTr("Close Wallet")
|
||||
onTriggered: appWindow.showWizard()
|
||||
}
|
||||
}
|
||||
PlatformLabs.Menu {
|
||||
title: qsTr("View")
|
||||
PlatformLabs.MenuItem {
|
||||
text: MoneroComponents.Style.blackTheme ? qsTr("Light Theme") : qsTr("Dark Theme")
|
||||
onTriggered: {
|
||||
MoneroComponents.Style.blackTheme = !MoneroComponents.Style.blackTheme;
|
||||
}
|
||||
}
|
||||
PlatformLabs.MenuItem {
|
||||
text: qsTr("Change Language")
|
||||
onTriggered: appWindow.toggleLanguageView();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
208
components/Navbar.qml
Normal file
208
components/Navbar.qml
Normal file
@@ -0,0 +1,208 @@
|
||||
// Copyright (c) 2014-2021, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import QtQuick 2.9
|
||||
import QtQuick.Layouts 1.1
|
||||
import "." as MoneroComponents
|
||||
|
||||
Rectangle {
|
||||
default property list<MoneroComponents.NavbarItem> items
|
||||
|
||||
color: "transparent"
|
||||
height: grid.height
|
||||
width: grid.width
|
||||
|
||||
GridLayout {
|
||||
id: grid
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
columnSpacing: 0
|
||||
property string fontColorActive: MoneroComponents.Style.blackTheme ? "white" : "white"
|
||||
property string fontColorInActive: MoneroComponents.Style.blackTheme ? "white" : MoneroComponents.Style.dimmedFontColor
|
||||
property int fontSize: 15
|
||||
property bool fontBold: true
|
||||
property var fontFamily: MoneroComponents.Style.fontRegular.name
|
||||
property string borderColor: MoneroComponents.Style.blackTheme ? "#808080" : "#B9B9B9"
|
||||
property int textMargin: {
|
||||
// left-right margins for a given cell
|
||||
if(appWindow.width < 890){
|
||||
return 32;
|
||||
} else {
|
||||
return 64;
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
// navbar left side border
|
||||
id: navBarLeft
|
||||
Layout.preferredWidth: 2
|
||||
Layout.preferredHeight: 32
|
||||
color: "transparent"
|
||||
|
||||
Rectangle {
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: 1
|
||||
height: parent.height - 2
|
||||
color: grid.borderColor
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.right: parent.right
|
||||
width: 1
|
||||
spacing: 0
|
||||
|
||||
Rectangle {
|
||||
Layout.preferredHeight: 1
|
||||
Layout.preferredWidth: 1
|
||||
color: grid.borderColor
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
Layout.fillHeight: true
|
||||
width: 1
|
||||
color: items.length > 0 && items[0].active ? grid.borderColor : "transparent";
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
color: grid.borderColor
|
||||
Layout.preferredHeight: 1
|
||||
Layout.preferredWidth: 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Repeater {
|
||||
model: items.length
|
||||
|
||||
RowLayout {
|
||||
spacing: 0
|
||||
|
||||
Rectangle {
|
||||
Layout.preferredWidth: 1
|
||||
Layout.preferredHeight: 32
|
||||
color: grid.borderColor
|
||||
visible: index > 0 && items[index - 1].visible
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
Layout.minimumWidth: 72
|
||||
Layout.preferredHeight: 32
|
||||
Layout.fillWidth: true
|
||||
spacing: 0
|
||||
visible: items[index].visible
|
||||
|
||||
Rectangle {
|
||||
color: grid.borderColor
|
||||
Layout.preferredHeight: 1
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
Layout.minimumHeight: 30
|
||||
Layout.fillWidth: true
|
||||
color: items[index].active ? grid.borderColor : "transparent"
|
||||
implicitHeight: children[0].implicitHeight
|
||||
implicitWidth: children[0].implicitWidth
|
||||
|
||||
MoneroComponents.TextPlain {
|
||||
anchors.centerIn: parent
|
||||
font.family: grid.fontFamily
|
||||
font.pixelSize: grid.fontSize
|
||||
font.bold: grid.fontBold
|
||||
leftPadding: grid.textMargin / 2
|
||||
rightPadding: grid.textMargin / 2
|
||||
text: items[index].text
|
||||
color: items[index].active ? grid.fontColorActive : grid.fontColorInActive
|
||||
themeTransition: false
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
|
||||
onClicked: items[index].selected()
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
color: grid.borderColor
|
||||
Layout.preferredHeight: 1
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
// navbar right side border
|
||||
id: navBarRight
|
||||
Layout.preferredWidth: 2
|
||||
Layout.preferredHeight: 32
|
||||
color: "transparent"
|
||||
rotation: 180
|
||||
|
||||
Rectangle {
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: 1
|
||||
height: parent.height - 2
|
||||
color: grid.borderColor
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.right: parent.right
|
||||
width: 1
|
||||
spacing: 0
|
||||
|
||||
Rectangle {
|
||||
Layout.preferredHeight: 1
|
||||
Layout.preferredWidth: 1
|
||||
color: grid.borderColor
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
Layout.fillHeight: true
|
||||
width: 1
|
||||
color: items.length > 0 && items[items.length - 1].active ? grid.borderColor : "transparent"
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
color: grid.borderColor
|
||||
Layout.preferredHeight: 1
|
||||
Layout.preferredWidth: 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
37
components/NavbarItem.qml
Normal file
37
components/NavbarItem.qml
Normal file
@@ -0,0 +1,37 @@
|
||||
// Copyright (c) 2021, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import QtQuick 2.9
|
||||
|
||||
QtObject {
|
||||
property bool active: false
|
||||
property string text
|
||||
property bool visible: true
|
||||
|
||||
signal selected()
|
||||
}
|
||||
@@ -80,7 +80,7 @@ Rectangle {
|
||||
if(item.connected == Wallet.ConnectionStatus_Connected){
|
||||
return 1
|
||||
} else {
|
||||
return 0.5
|
||||
MoneroComponents.Style.blackTheme ? 0.5 : 0.3
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ Rectangle {
|
||||
source: {
|
||||
if(appWindow.isMining) {
|
||||
return "qrc:///images/miningxmr.png"
|
||||
} else if(item.connected == Wallet.ConnectionStatus_Connected) {
|
||||
} else if(item.connected == Wallet.ConnectionStatus_Connected || !MoneroComponents.Style.blackTheme) {
|
||||
return "qrc:///images/lightning.png"
|
||||
} else {
|
||||
return "qrc:///images/lightning-white.png"
|
||||
@@ -126,8 +126,8 @@ Rectangle {
|
||||
font.family: MoneroComponents.Style.fontMedium.name
|
||||
font.bold: true
|
||||
font.pixelSize: 13
|
||||
color: MoneroComponents.Style.dimmedFontColor
|
||||
opacity: MoneroComponents.Style.blackTheme ? 0.65 : 0.5
|
||||
color: MoneroComponents.Style.blackTheme ? MoneroComponents.Style.dimmedFontColor : MoneroComponents.Style.defaultFontColor
|
||||
opacity: MoneroComponents.Style.blackTheme ? 0.65 : 0.75
|
||||
text: qsTr("Network status") + translationManager.emptyString
|
||||
themeTransition: false
|
||||
}
|
||||
@@ -159,16 +159,18 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
MoneroComponents.TextPlain {
|
||||
anchors.left: statusTextVal.right
|
||||
anchors.leftMargin: 16
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
color: refreshMouseArea.containsMouse ? MoneroComponents.Style.dimmedFontColor : MoneroComponents.Style.defaultFontColor
|
||||
color: refreshMouseArea.containsMouse ? MoneroComponents.Style.defaultFontColor : MoneroComponents.Style.dimmedFontColor
|
||||
font.family: FontAwesome.fontFamilySolid
|
||||
font.pixelSize: 24
|
||||
font.styleName: "Solid"
|
||||
opacity: iconItem.opacity * (refreshMouseArea.visible ? 1 : 0.5)
|
||||
opacity: 0.85
|
||||
text: FontAwesome.random
|
||||
themeTransition: false
|
||||
tooltip: qsTr("Switch to another public remote node") + translationManager.emptyString;
|
||||
visible: (
|
||||
!appWindow.disconnected &&
|
||||
!persistentSettings.useRemoteNode &&
|
||||
@@ -181,6 +183,8 @@ Rectangle {
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
visible: true
|
||||
onEntered: parent.tooltipPopup.open()
|
||||
onExited: parent.tooltipPopup.close()
|
||||
onClicked: {
|
||||
const callback = function(result) {
|
||||
refreshMouseArea.visible = true;
|
||||
|
||||
@@ -90,6 +90,9 @@ Rectangle {
|
||||
if (!parsed.error) {
|
||||
root.qrcode_decoded(parsed.address, parsed.payment_id, parsed.amount, parsed.tx_description, parsed.recipient_name, parsed.extra_parameters);
|
||||
root.state = "Stopped";
|
||||
} else if (walletManager.addressValid(data, appWindow.persistentSettings.nettype)) {
|
||||
root.qrcode_decoded(data, "", "", "", "", null);
|
||||
root.state = "Stopped";
|
||||
} else {
|
||||
onNotifyError(parsed.error);
|
||||
}
|
||||
|
||||
153
components/RemoteNodeDialog.qml
Normal file
153
components/RemoteNodeDialog.qml
Normal file
@@ -0,0 +1,153 @@
|
||||
// Copyright (c) 2021, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import QtQuick 2.9
|
||||
import QtQuick.Controls 2.2
|
||||
import QtQuick.Layouts 1.1
|
||||
|
||||
import "." as MoneroComponents
|
||||
|
||||
MoneroComponents.Dialog {
|
||||
id: root
|
||||
title: (editMode ? qsTr("Edit remote node") : qsTr("Add remote node")) + translationManager.emptyString
|
||||
|
||||
property var callbackOnSuccess: null
|
||||
property bool editMode: false
|
||||
property bool success: false
|
||||
|
||||
onActiveFocusChanged: activeFocus && remoteNodeAddress.forceActiveFocus()
|
||||
|
||||
function add(callbackOnSuccess) {
|
||||
root.editMode = false;
|
||||
root.callbackOnSuccess = callbackOnSuccess;
|
||||
|
||||
open();
|
||||
}
|
||||
|
||||
function edit(remoteNode, callbackOnSuccess) {
|
||||
const hostPort = remoteNode.address.match(/^(.*?)(?:\:?(\d*))$/);
|
||||
if (hostPort) {
|
||||
remoteNodeAddress.daemonAddrText = hostPort[1];
|
||||
remoteNodeAddress.daemonPortText = hostPort[2];
|
||||
}
|
||||
daemonUsername.text = remoteNode.username;
|
||||
daemonPassword.text = remoteNode.password;
|
||||
setTrustedDaemonCheckBox.checked = remoteNode.trusted;
|
||||
root.callbackOnSuccess = callbackOnSuccess;
|
||||
root.editMode = true;
|
||||
|
||||
open();
|
||||
}
|
||||
|
||||
onClosed: {
|
||||
if (root.success && callbackOnSuccess) {
|
||||
callbackOnSuccess({
|
||||
address: remoteNodeAddress.getAddress(),
|
||||
username: daemonUsername.text,
|
||||
password: daemonPassword.text,
|
||||
trusted: setTrustedDaemonCheckBox.checked,
|
||||
});
|
||||
}
|
||||
|
||||
remoteNodeAddress.daemonAddrText = "";
|
||||
remoteNodeAddress.daemonPortText = "";
|
||||
daemonUsername.text = "";
|
||||
daemonPassword.text = "";
|
||||
setTrustedDaemonCheckBox.checked = false;
|
||||
root.success = false;
|
||||
}
|
||||
|
||||
MoneroComponents.RemoteNodeEdit {
|
||||
id: remoteNodeAddress
|
||||
Layout.fillWidth: true
|
||||
placeholderFontSize: 15
|
||||
|
||||
daemonAddrLabelText: qsTr("Address") + translationManager.emptyString
|
||||
daemonPortLabelText: qsTr("Port") + translationManager.emptyString
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
spacing: 32
|
||||
|
||||
MoneroComponents.LineEdit {
|
||||
id: daemonUsername
|
||||
Layout.fillWidth: true
|
||||
Layout.minimumWidth: 220
|
||||
labelText: qsTr("Daemon username") + translationManager.emptyString
|
||||
placeholderText: qsTr("(optional)") + translationManager.emptyString
|
||||
placeholderFontSize: 15
|
||||
labelFontSize: 14
|
||||
fontSize: 15
|
||||
}
|
||||
|
||||
MoneroComponents.LineEdit {
|
||||
id: daemonPassword
|
||||
Layout.fillWidth: true
|
||||
Layout.minimumWidth: 220
|
||||
labelText: qsTr("Daemon password") + translationManager.emptyString
|
||||
placeholderText: qsTr("Password") + translationManager.emptyString
|
||||
password: true
|
||||
placeholderFontSize: 15
|
||||
labelFontSize: 14
|
||||
fontSize: 15
|
||||
}
|
||||
}
|
||||
|
||||
MoneroComponents.CheckBox {
|
||||
id: setTrustedDaemonCheckBox
|
||||
activeFocusOnTab: true
|
||||
text: qsTr("Mark as Trusted Daemon") + translationManager.emptyString
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Layout.alignment: Qt.AlignRight
|
||||
spacing: parent.spacing
|
||||
|
||||
MoneroComponents.StandardButton {
|
||||
activeFocusOnTab: true
|
||||
fontBold: false
|
||||
primary: false
|
||||
text: qsTr("Cancel") + translationManager.emptyString
|
||||
|
||||
onClicked: root.close()
|
||||
}
|
||||
|
||||
MoneroComponents.StandardButton {
|
||||
activeFocusOnTab: true
|
||||
fontBold: false
|
||||
enabled: remoteNodeAddress.getAddress() != ""
|
||||
text: qsTr("Ok") + translationManager.emptyString
|
||||
|
||||
onClicked: {
|
||||
root.success = true;
|
||||
root.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -56,7 +56,6 @@ GridLayout {
|
||||
property int labelFontSize: 14
|
||||
|
||||
property string lineEditBackgroundColor: "transparent"
|
||||
property string lineEditBorderColor: MoneroComponents.Style.inputBorderColorInActive
|
||||
property string lineEditFontColor: MoneroComponents.Style.defaultFontColor
|
||||
property bool lineEditFontBold: false
|
||||
property int lineEditFontSize: 15
|
||||
@@ -67,24 +66,25 @@ GridLayout {
|
||||
signal editingFinished()
|
||||
signal textChanged()
|
||||
|
||||
onActiveFocusChanged: activeFocus && daemonAddr.forceActiveFocus()
|
||||
|
||||
function isValid() {
|
||||
return daemonAddr.text.trim().length > 0 && daemonPort.acceptableInput
|
||||
}
|
||||
|
||||
function getAddress() {
|
||||
if (!isValid()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
var addr = daemonAddr.text.trim();
|
||||
var port = daemonPort.text.trim();
|
||||
|
||||
// validation
|
||||
if(addr === "" || addr.length < 2) return "";
|
||||
if(!Utils.isNumeric(port)) return "";
|
||||
|
||||
return addr + ":" + port;
|
||||
}
|
||||
|
||||
LineEdit {
|
||||
MoneroComponents.LineEdit {
|
||||
id: daemonAddr
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredWidth: root.width/3
|
||||
placeholderText: qsTr("Remote Node Hostname / IP") + translationManager.emptyString
|
||||
placeholderFontFamily: root.placeholderFontFamily
|
||||
placeholderFontBold: root.placeholderFontBold
|
||||
@@ -92,7 +92,6 @@ GridLayout {
|
||||
placeholderColor: root.placeholderColor
|
||||
placeholderOpacity: root.placeholderOpacity
|
||||
labelFontSize: root.labelFontSize
|
||||
borderColor: lineEditBorderColor
|
||||
backgroundColor: lineEditBackgroundColor
|
||||
fontColor: lineEditFontColor
|
||||
fontBold: lineEditFontBold
|
||||
@@ -105,9 +104,9 @@ GridLayout {
|
||||
text: initialHostPort[1]
|
||||
}
|
||||
|
||||
LineEdit {
|
||||
MoneroComponents.LineEdit {
|
||||
id: daemonPort
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredWidth: root.width/3
|
||||
placeholderText: qsTr("Port") + translationManager.emptyString
|
||||
placeholderFontFamily: root.placeholderFontFamily
|
||||
placeholderFontBold: root.placeholderFontBold
|
||||
@@ -115,7 +114,6 @@ GridLayout {
|
||||
placeholderColor: root.placeholderColor
|
||||
placeholderOpacity: root.placeholderOpacity
|
||||
labelFontSize: root.labelFontSize
|
||||
borderColor: lineEditBorderColor
|
||||
backgroundColor: lineEditBackgroundColor
|
||||
fontColor: lineEditFontColor
|
||||
fontBold: lineEditFontBold
|
||||
|
||||
163
components/RemoteNodeList.qml
Normal file
163
components/RemoteNodeList.qml
Normal file
@@ -0,0 +1,163 @@
|
||||
// Copyright (c) 2021, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import QtQuick 2.9
|
||||
import QtQuick.Layouts 1.1
|
||||
|
||||
import FontAwesome 1.0
|
||||
|
||||
import "." as MoneroComponents
|
||||
import "effects/" as MoneroEffects
|
||||
|
||||
ColumnLayout {
|
||||
id: remoteNodeList
|
||||
spacing: 20
|
||||
|
||||
MoneroComponents.CheckBox {
|
||||
border: false
|
||||
checkedIcon: FontAwesome.minusCircle
|
||||
uncheckedIcon: FontAwesome.plusCircle
|
||||
fontAwesomeIcons: true
|
||||
fontSize: 16
|
||||
iconOnTheLeft: true
|
||||
text: qsTr("Add remote node") + translationManager.emptyString
|
||||
toggleOnClick: false
|
||||
onClicked: remoteNodeDialog.add(remoteNodesModel.append)
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
spacing: 0
|
||||
|
||||
Repeater {
|
||||
model: remoteNodesModel
|
||||
|
||||
Rectangle {
|
||||
height: 30
|
||||
Layout.fillWidth: true
|
||||
color: itemMouseArea.containsMouse || trustedDaemonCheckMark.labelMouseArea.containsMouse || index === remoteNodesModel.selected ? MoneroComponents.Style.titleBarButtonHoverColor : "transparent"
|
||||
|
||||
Rectangle {
|
||||
visible: index === remoteNodesModel.selected
|
||||
Layout.fillHeight: true
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
color: "darkgrey"
|
||||
width: 2
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
color: MoneroComponents.Style.appWindowBorderColor
|
||||
anchors.right: parent.right
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.top
|
||||
height: 1
|
||||
visible: index > 0
|
||||
|
||||
MoneroEffects.ColorTransition {
|
||||
targetObj: parent
|
||||
blackColor: MoneroComponents.Style._b_appWindowBorderColor
|
||||
whiteColor: MoneroComponents.Style._w_appWindowBorderColor
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
anchors.rightMargin: 80
|
||||
color: "transparent"
|
||||
property var trusted: remoteNodesModel.get(index).trusted
|
||||
|
||||
MoneroComponents.TextPlain {
|
||||
id: addressText
|
||||
width: parent.width - trustedDaemonCheckMark.width
|
||||
color: index === remoteNodesModel.selected ? MoneroComponents.Style.defaultFontColor : MoneroComponents.Style.dimmedFontColor
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 6
|
||||
font.pixelSize: 16
|
||||
text: address
|
||||
themeTransition: false
|
||||
elide: Text.ElideMiddle
|
||||
}
|
||||
|
||||
MoneroComponents.Label {
|
||||
id: trustedDaemonCheckMark
|
||||
anchors.left: addressText.right
|
||||
anchors.leftMargin: 6
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
z: itemMouseArea.z + 1
|
||||
fontSize: 16
|
||||
fontFamily: FontAwesome.fontFamilySolid
|
||||
fontColor: index === remoteNodesModel.selected ? MoneroComponents.Style.defaultFontColor : MoneroComponents.Style.dimmedFontColor
|
||||
styleName: "Solid"
|
||||
visible: trusted
|
||||
text: FontAwesome.shieldAlt
|
||||
tooltip: qsTr("Trusted daemon") + translationManager.emptyString
|
||||
themeTransition: false
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: itemMouseArea
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
onClicked: remoteNodesModel.applyRemoteNode(index)
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.right: parent.right
|
||||
height: 30
|
||||
spacing: 2
|
||||
|
||||
MoneroComponents.InlineButton {
|
||||
buttonColor: "transparent"
|
||||
fontFamily: FontAwesome.fontFamily
|
||||
fontPixelSize: 18
|
||||
text: FontAwesome.edit
|
||||
tooltip: qsTr("Edit remote node") + translationManager.emptyString
|
||||
tooltipLeft: true
|
||||
onClicked: remoteNodeDialog.edit(remoteNodesModel.get(index), function (remoteNode) {
|
||||
remoteNodesModel.set(index, remoteNode)
|
||||
})
|
||||
}
|
||||
|
||||
MoneroComponents.InlineButton {
|
||||
buttonColor: "transparent"
|
||||
fontFamily: FontAwesome.fontFamily
|
||||
text: FontAwesome.times
|
||||
visible: remoteNodesModel.count > 1
|
||||
tooltip: qsTr("Remove remote node") + translationManager.emptyString
|
||||
tooltipLeft: true
|
||||
onClicked: remoteNodesModel.removeSelectNextIfNeeded(index)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,11 +16,11 @@ ColumnLayout {
|
||||
|
||||
spacing: 0
|
||||
|
||||
Text {
|
||||
MoneroComponents.TextPlain {
|
||||
id: label
|
||||
color: MoneroComponents.Style.defaultFontColor
|
||||
font.pixelSize: 14
|
||||
Layout.fillWidth: true
|
||||
font.family: MoneroComponents.Style.fontRegular.name
|
||||
}
|
||||
|
||||
QtQuickControls.Slider {
|
||||
|
||||
@@ -52,6 +52,9 @@ Item {
|
||||
else return 16;
|
||||
}
|
||||
property alias label: label
|
||||
property alias tooltip: tooltip.text
|
||||
property alias tooltipLeft: tooltip.tooltipLeft
|
||||
property alias tooltipPopup: tooltip.tooltipPopup
|
||||
signal clicked()
|
||||
|
||||
height: small ? 30 : 36
|
||||
@@ -68,7 +71,7 @@ Item {
|
||||
id: buttonRect
|
||||
anchors.fill: parent
|
||||
radius: 3
|
||||
border.width: parent.focus ? 1 : 0
|
||||
border.width: parent.focus && parent.enabled ? 1 : 0
|
||||
|
||||
state: button.enabled ? "active" : "disabled"
|
||||
Component.onCompleted: state = state
|
||||
@@ -76,7 +79,7 @@ Item {
|
||||
states: [
|
||||
State {
|
||||
name: "hover"
|
||||
when: buttonArea.containsMouse || button.focus
|
||||
when: button.enabled && (buttonArea.containsMouse || button.focus)
|
||||
PropertyChanges {
|
||||
target: buttonRect
|
||||
color: primary
|
||||
@@ -143,6 +146,7 @@ Item {
|
||||
width: button.small ? 16 : 20
|
||||
height: button.small ? 16 : 20
|
||||
source: {
|
||||
if (fontAwesomeIcon) return "";
|
||||
if(button.rightIconInactive !== "" && !button.enabled) {
|
||||
return button.rightIconInactive;
|
||||
}
|
||||
@@ -161,11 +165,18 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
MoneroComponents.Tooltip {
|
||||
id: tooltip
|
||||
anchors.fill: parent
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: buttonArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
onClicked: doClick()
|
||||
onEntered: tooltip.text ? tooltip.tooltipPopup.open() : ""
|
||||
onExited: tooltip.text ? tooltip.tooltipPopup.close() : ""
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
}
|
||||
|
||||
|
||||
@@ -171,6 +171,7 @@ Rectangle {
|
||||
|
||||
MoneroComponents.StandardButton {
|
||||
id: cancelButton
|
||||
primary: false
|
||||
text: qsTr("Cancel") + translationManager.emptyString
|
||||
onClicked: {
|
||||
root.close()
|
||||
|
||||
@@ -29,12 +29,16 @@
|
||||
import QtQuick 2.9
|
||||
import QtQuick.Controls 2.2
|
||||
import QtGraphicalEffects 1.0
|
||||
import FontAwesome 1.0
|
||||
import QtQuick.Layouts 1.1
|
||||
|
||||
import "../components" as MoneroComponents
|
||||
import "../components/effects/" as MoneroEffects
|
||||
|
||||
Item {
|
||||
ColumnLayout {
|
||||
id: dropdown
|
||||
Layout.fillWidth: true
|
||||
|
||||
property int itemTopMargin: 0
|
||||
property alias dataModel: repeater.model
|
||||
property string shadowPressedColor
|
||||
@@ -44,46 +48,66 @@ Item {
|
||||
property string textColor: MoneroComponents.Style.defaultFontColor
|
||||
property alias currentIndex: columnid.currentIndex
|
||||
readonly property alias expanded: popup.visible
|
||||
property int dropdownHeight: 42
|
||||
property int fontHeaderSize: 16
|
||||
property alias labelText: dropdownLabel.text
|
||||
property alias labelColor: dropdownLabel.color
|
||||
property alias labelTextFormat: dropdownLabel.textFormat
|
||||
property alias labelWrapMode: dropdownLabel.wrapMode
|
||||
property alias labelHorizontalAlignment: dropdownLabel.horizontalAlignment
|
||||
property bool showingHeader: dropdownLabel.text !== ""
|
||||
property int labelFontSize: 14
|
||||
property bool labelFontBold: false
|
||||
property int dropdownHeight: 39
|
||||
property int fontSize: 14
|
||||
property int fontItemSize: 14
|
||||
property string colorBorder: MoneroComponents.Style.inputBorderColorInActive
|
||||
property string colorHeaderBackground: "transparent"
|
||||
property bool headerBorder: true
|
||||
property bool headerFontBold: false
|
||||
|
||||
height: dropdownHeight
|
||||
|
||||
signal changed();
|
||||
|
||||
onExpandedChanged: if(expanded) appWindow.currentItem = dropdown
|
||||
|
||||
Item {
|
||||
id: head
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: parent.itemTopMargin
|
||||
height: dropdown.dropdownHeight
|
||||
spacing: 0
|
||||
Rectangle {
|
||||
id: dropdownLabelRect
|
||||
color: "transparent"
|
||||
Layout.fillWidth: true
|
||||
height: (dropdownLabel.height + 10)
|
||||
visible: showingHeader ? true : false
|
||||
|
||||
Rectangle {
|
||||
color: "transparent"
|
||||
border.width: dropdown.headerBorder ? 1 : 0
|
||||
border.color: dropdown.colorBorder
|
||||
radius: 4
|
||||
anchors.fill: parent
|
||||
MoneroComponents.TextPlain {
|
||||
id: dropdownLabel
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
font.family: MoneroComponents.Style.fontRegular.name
|
||||
font.pixelSize: labelFontSize
|
||||
font.bold: labelFontBold
|
||||
textFormat: Text.RichText
|
||||
color: MoneroComponents.Style.defaultFontColor
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: head
|
||||
color: dropArea.containsMouse ? MoneroComponents.Style.titleBarButtonHoverColor : "transparent"
|
||||
border.width: dropdown.headerBorder ? 1 : 0
|
||||
border.color: dropdown.colorBorder
|
||||
radius: 4
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: dropdownHeight
|
||||
|
||||
MoneroComponents.TextPlain {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 12
|
||||
anchors.leftMargin: 10
|
||||
anchors.right: dropIndicator.left
|
||||
anchors.rightMargin: 12
|
||||
width: droplist.width
|
||||
elide: Text.ElideRight
|
||||
font.family: MoneroComponents.Style.fontRegular.name
|
||||
font.bold: dropdown.headerFontBold
|
||||
font.pixelSize: dropdown.fontHeaderSize
|
||||
font.pixelSize: dropdown.fontSize
|
||||
color: dropdown.textColor
|
||||
text: columnid.currentIndex < repeater.model.count ? qsTr(repeater.model.get(columnid.currentIndex).column1) + translationManager.emptyString : ""
|
||||
}
|
||||
@@ -96,19 +120,15 @@ Item {
|
||||
anchors.rightMargin: 12
|
||||
width: dropdownIcon.width
|
||||
|
||||
Image {
|
||||
MoneroEffects.ImageMask {
|
||||
id: dropdownIcon
|
||||
anchors.centerIn: parent
|
||||
source: "qrc:///images/whiteDropIndicator.png"
|
||||
visible: false
|
||||
}
|
||||
|
||||
ColorOverlay {
|
||||
source: dropdownIcon
|
||||
anchors.fill: dropdownIcon
|
||||
image: "qrc:///images/whiteDropIndicator.png"
|
||||
height: 8
|
||||
width: 12
|
||||
fontAwesomeFallbackIcon: FontAwesome.arrowDown
|
||||
fontAwesomeFallbackSize: 14
|
||||
color: MoneroComponents.Style.defaultFontColor
|
||||
rotation: dropdown.expanded ? 180 : 0
|
||||
opacity: 1
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,7 +137,7 @@ Item {
|
||||
anchors.fill: parent
|
||||
onClicked: dropdown.expanded ? popup.close() : popup.open()
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
cursorShape: Qt.ArrowCursor
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,7 +148,7 @@ Item {
|
||||
|
||||
Rectangle {
|
||||
id: droplist
|
||||
x: dropdown.x
|
||||
anchors.left: parent.left
|
||||
width: dropdown.width
|
||||
y: head.y + head.height
|
||||
clip: true
|
||||
@@ -188,25 +208,11 @@ Item {
|
||||
text: ""
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.top
|
||||
width: 3; height: 3
|
||||
color: parent.color
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
width: 3; height: 3
|
||||
color: parent.color
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: itemArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
cursorShape: Qt.ArrowCursor
|
||||
|
||||
onClicked: {
|
||||
popup.close()
|
||||
|
||||
@@ -45,20 +45,11 @@ Rectangle {
|
||||
radius: 10
|
||||
border.color: MoneroComponents.Style.blackTheme ? Qt.rgba(255, 255, 255, 0.25) : Qt.rgba(0, 0, 0, 0.25)
|
||||
border.width: 1
|
||||
focus: true
|
||||
Keys.enabled: true
|
||||
Keys.onEscapePressed: {
|
||||
root.close()
|
||||
root.rejected()
|
||||
}
|
||||
Keys.onEnterPressed: {
|
||||
root.close()
|
||||
root.accepted()
|
||||
}
|
||||
Keys.onReturnPressed: {
|
||||
root.close()
|
||||
root.accepted()
|
||||
}
|
||||
KeyNavigation.tab: doneButton
|
||||
|
||||
Clipboard { id: clipboard }
|
||||
@@ -72,7 +63,6 @@ Rectangle {
|
||||
function open(txid) {
|
||||
root.transactionID = txid;
|
||||
root.visible = true;
|
||||
root.forceActiveFocus();
|
||||
}
|
||||
|
||||
function close() {
|
||||
@@ -142,7 +132,7 @@ Rectangle {
|
||||
fontSize: 16
|
||||
}
|
||||
|
||||
// open folder / done buttons
|
||||
// view progress / open folder / done buttons
|
||||
RowLayout {
|
||||
id: buttons
|
||||
spacing: 70
|
||||
@@ -150,19 +140,26 @@ Rectangle {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 50
|
||||
|
||||
MoneroComponents.StandardButton {
|
||||
id: viewProgressButton
|
||||
visible: !appWindow.viewOnly
|
||||
text: qsTr("View progress") + translationManager.emptyString;
|
||||
width: 200
|
||||
primary: false
|
||||
KeyNavigation.tab: doneButton
|
||||
onClicked: {
|
||||
doSearchInHistory(root.transactionID);
|
||||
root.close()
|
||||
root.rejected()
|
||||
}
|
||||
}
|
||||
|
||||
MoneroComponents.StandardButton {
|
||||
id: openFolderButton
|
||||
visible: appWindow.viewOnly
|
||||
text: qsTr("Open folder") + translationManager.emptyString;
|
||||
width: 200
|
||||
KeyNavigation.tab: doneButton
|
||||
Keys.enabled: openFolderButton.visible
|
||||
Keys.onReturnPressed: openFolderButton.onClicked
|
||||
Keys.onEnterPressed: openFolderButton.onClicked
|
||||
Keys.onEscapePressed: {
|
||||
root.close()
|
||||
root.rejected()
|
||||
}
|
||||
onClicked: {
|
||||
oshelper.openContainingFolder(walletManager.urlToLocalPath(saveTxDialog.fileUrl))
|
||||
}
|
||||
@@ -172,15 +169,8 @@ Rectangle {
|
||||
id: doneButton
|
||||
text: qsTr("Done") + translationManager.emptyString;
|
||||
width: 200
|
||||
focus: true
|
||||
KeyNavigation.tab: openFolderButton
|
||||
Keys.enabled: doneButton.visible
|
||||
Keys.onReturnPressed: doneButton.onClicked
|
||||
Keys.onEnterPressed: doneButton.onClicked
|
||||
Keys.onEscapePressed: {
|
||||
root.close()
|
||||
root.rejected()
|
||||
}
|
||||
focus: root.visible
|
||||
KeyNavigation.tab: appWindow.viewOnly ? openFolderButton : viewProgressButton
|
||||
onClicked: {
|
||||
root.close()
|
||||
root.accepted()
|
||||
|
||||
@@ -12,6 +12,10 @@ Text {
|
||||
property bool themeTransition: true
|
||||
property string themeTransitionBlackColor: ""
|
||||
property string themeTransitionWhiteColor: ""
|
||||
property alias tooltip: tooltip.text
|
||||
property alias tooltipLeft: tooltip.tooltipLeft
|
||||
property alias tooltipIconVisible: tooltip.tooltipIconVisible
|
||||
property alias tooltipPopup: tooltip.tooltipPopup
|
||||
font.family: MoneroComponents.Style.fontMedium.name
|
||||
font.bold: false
|
||||
font.pixelSize: 14
|
||||
@@ -25,4 +29,10 @@ Text {
|
||||
blackColor: root.themeTransitionBlackColor !== "" ? root.themeTransitionBlackColor : MoneroComponents.Style._b_defaultFontColor
|
||||
whiteColor: root.themeTransitionWhiteColor !== "" ? root.themeTransitionWhiteColor : MoneroComponents.Style._w_defaultFontColor
|
||||
}
|
||||
|
||||
MoneroComponents.Tooltip {
|
||||
id: tooltip
|
||||
anchors.top: parent.top
|
||||
anchors.left: tooltipIconVisible ? parent.right : parent.left
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,12 +110,24 @@ Rectangle {
|
||||
opacity: 0.75
|
||||
}
|
||||
|
||||
MoneroComponents.Tooltip {
|
||||
id: btnCloseWalletTooltip
|
||||
anchors.fill: parent
|
||||
text: qsTr("Close this wallet and return to main menu") + translationManager.emptyString
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onEntered: parent.color = MoneroComponents.Style.titleBarButtonHoverColor
|
||||
onExited: parent.color = "transparent"
|
||||
onEntered: {
|
||||
parent.color = MoneroComponents.Style.titleBarButtonHoverColor
|
||||
btnCloseWalletTooltip.tooltipPopup.open()
|
||||
}
|
||||
onExited: {
|
||||
parent.color = "transparent"
|
||||
btnCloseWalletTooltip.tooltipPopup.close()
|
||||
}
|
||||
onClicked: root.closeWalletClicked(leftPanel.visible)
|
||||
}
|
||||
}
|
||||
@@ -138,12 +150,24 @@ Rectangle {
|
||||
opacity: 0.75
|
||||
}
|
||||
|
||||
MoneroComponents.Tooltip {
|
||||
id: btnLanguageToggleTooltip
|
||||
anchors.fill: parent
|
||||
text: qsTr("Change language") + translationManager.emptyString
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onEntered: parent.color = MoneroComponents.Style.titleBarButtonHoverColor
|
||||
onExited: parent.color = "transparent"
|
||||
onEntered: {
|
||||
parent.color = MoneroComponents.Style.titleBarButtonHoverColor
|
||||
btnLanguageToggleTooltip.tooltipPopup.open()
|
||||
}
|
||||
onExited: {
|
||||
parent.color = "transparent"
|
||||
btnLanguageToggleTooltip.tooltipPopup.close()
|
||||
}
|
||||
onClicked: root.languageClicked()
|
||||
}
|
||||
}
|
||||
@@ -165,15 +189,26 @@ Rectangle {
|
||||
opacity: 0.75
|
||||
}
|
||||
|
||||
MoneroComponents.Tooltip {
|
||||
id: btnSwitchThemeTooltip
|
||||
anchors.fill: parent
|
||||
text: MoneroComponents.Style.blackTheme ? qsTr("Switch to light theme") : qsTr("Switch to dark theme") + translationManager.emptyString
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onEntered: parent.color = MoneroComponents.Style.titleBarButtonHoverColor
|
||||
onExited: parent.color = "transparent"
|
||||
onEntered: {
|
||||
parent.color = MoneroComponents.Style.titleBarButtonHoverColor
|
||||
btnSwitchThemeTooltip.tooltipPopup.open()
|
||||
}
|
||||
onExited: {
|
||||
parent.color = "transparent"
|
||||
btnSwitchThemeTooltip.tooltipPopup.close()
|
||||
}
|
||||
onClicked: {
|
||||
MoneroComponents.Style.blackTheme = !MoneroComponents.Style.blackTheme;
|
||||
persistentSettings.blackTheme = MoneroComponents.Style.blackTheme;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -347,6 +382,7 @@ Rectangle {
|
||||
anchors.fill: parent
|
||||
propagateComposedEvents: true
|
||||
onPressed: previousPosition = globalCursor.getPosition()
|
||||
onDoubleClicked: root.maximizeClicked()
|
||||
onPositionChanged: {
|
||||
if (pressedButtons == Qt.LeftButton) {
|
||||
var pos = globalCursor.getPosition()
|
||||
|
||||
111
components/Tooltip.qml
Normal file
111
components/Tooltip.qml
Normal file
@@ -0,0 +1,111 @@
|
||||
// Copyright (c) 2021, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import QtQuick 2.9
|
||||
import QtQuick.Controls 2.2
|
||||
import QtQuick.Layouts 1.1
|
||||
|
||||
import FontAwesome 1.0
|
||||
import "." as MoneroComponents
|
||||
|
||||
Rectangle {
|
||||
property alias text: tooltip.text
|
||||
property alias tooltipPopup: popup
|
||||
property bool tooltipIconVisible: false
|
||||
property bool tooltipLeft: false
|
||||
property bool tooltipBottom: tooltipIconVisible ? false : true
|
||||
|
||||
color: "transparent"
|
||||
height: tooltipIconVisible ? icon.height : parent.height
|
||||
width: tooltipIconVisible ? icon.width : parent.width
|
||||
visible: text != ""
|
||||
|
||||
Text {
|
||||
id: icon
|
||||
visible: tooltipIconVisible
|
||||
color: MoneroComponents.Style.orange
|
||||
font.family: FontAwesome.fontFamily
|
||||
font.pixelSize: 10
|
||||
font.styleName: "Regular"
|
||||
leftPadding: 5
|
||||
rightPadding: 5
|
||||
text: FontAwesome.questionCircle
|
||||
opacity: mouseArea.containsMouse ? 0.7 : 1
|
||||
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.WhatsThisCursor
|
||||
onEntered: popup.open()
|
||||
onExited: popup.close()
|
||||
}
|
||||
}
|
||||
|
||||
ToolTip {
|
||||
id: popup
|
||||
height: tooltip.height + 20
|
||||
|
||||
background: Rectangle {
|
||||
border.color: MoneroComponents.Style.buttonInlineBackgroundColor
|
||||
border.width: 1
|
||||
color: MoneroComponents.Style.titleBarBackgroundGradientStart
|
||||
radius: 4
|
||||
}
|
||||
closePolicy: Popup.NoAutoClose
|
||||
padding: 10
|
||||
x: tooltipLeft
|
||||
? (tooltipIconVisible ? icon.x - icon.width : parent.x - tooltip.width - 20 + parent.width/2)
|
||||
: (tooltipIconVisible ? icon.x + icon.width : parent.x + parent.width/2)
|
||||
y: tooltipBottom
|
||||
? (tooltipIconVisible ? icon.y + height : parent.y + parent.height + 2)
|
||||
: (tooltipIconVisible ? icon.y - height : parent.y - tooltip.height - 20)
|
||||
enter: Transition {
|
||||
NumberAnimation { property: "opacity"; from: 0.0; to: 1.0; duration: 150 }
|
||||
}
|
||||
|
||||
exit: Transition {
|
||||
NumberAnimation { property: "opacity"; from: 1.0; to: 0.0; duration: 150 }
|
||||
}
|
||||
delay: 200
|
||||
|
||||
RowLayout {
|
||||
Layout.maximumWidth: 350
|
||||
|
||||
Text {
|
||||
id: tooltip
|
||||
width: contentWidth
|
||||
color: MoneroComponents.Style.defaultFontColor
|
||||
font.family: MoneroComponents.Style.fontRegular.name
|
||||
font.pixelSize: 12
|
||||
textFormat: Text.RichText
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -27,7 +27,8 @@
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import QtQuick 2.9
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Controls 1.4 as QtQuickControls1
|
||||
import QtQuick.Controls 2.2
|
||||
import QtQuick.Layouts 1.1
|
||||
|
||||
import "../components" as MoneroComponents
|
||||
@@ -35,47 +36,29 @@ import FontAwesome 1.0
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
|
||||
property int margins: 25
|
||||
|
||||
x: parent.width/2 - root.width/2
|
||||
y: parent.height/2 - root.height/2
|
||||
// TODO: implement without hardcoding sizes
|
||||
width: 580
|
||||
height: 400
|
||||
width: 590
|
||||
height: layout.height + layout.anchors.margins * 2
|
||||
color: MoneroComponents.Style.blackTheme ? "black" : "white"
|
||||
visible: false
|
||||
radius: 10
|
||||
border.color: MoneroComponents.Style.blackTheme ? Qt.rgba(255, 255, 255, 0.25) : Qt.rgba(0, 0, 0, 0.25)
|
||||
border.width: 1
|
||||
focus: true
|
||||
Keys.enabled: true
|
||||
Keys.onEscapePressed: {
|
||||
root.close()
|
||||
root.clearFields()
|
||||
root.rejected()
|
||||
}
|
||||
Keys.onEnterPressed: {
|
||||
if (root.state == "default") {
|
||||
root.close()
|
||||
root.accepted()
|
||||
} else if (root.state == "error") {
|
||||
root.close()
|
||||
root.clearFields()
|
||||
root.rejected()
|
||||
}
|
||||
}
|
||||
Keys.onReturnPressed: {
|
||||
if (root.state == "default") {
|
||||
root.close()
|
||||
root.accepted()
|
||||
} else if (root.state == "error") {
|
||||
root.close()
|
||||
root.clearFields()
|
||||
root.rejected()
|
||||
}
|
||||
}
|
||||
KeyNavigation.tab: confirmButton
|
||||
|
||||
property var recipients: []
|
||||
property var transactionAmount: ""
|
||||
property var transactionAddress: ""
|
||||
property var transactionDescription: ""
|
||||
property var transactionFee: ""
|
||||
property var transactionPriority: ""
|
||||
@@ -101,7 +84,7 @@ Rectangle {
|
||||
PropertyChanges { target: bottomMessage; visible: false }
|
||||
PropertyChanges { target: buttons; visible: true }
|
||||
PropertyChanges { target: backButton; visible: true; primary: false }
|
||||
PropertyChanges { target: confirmButton; visible: true }
|
||||
PropertyChanges { target: confirmButton; visible: true; focus: true }
|
||||
}, State {
|
||||
// error message being displayed, show only back button
|
||||
name: "error";
|
||||
@@ -115,7 +98,7 @@ Rectangle {
|
||||
PropertyChanges { target: bottom; visible: true }
|
||||
PropertyChanges { target: bottomMessage; visible: false }
|
||||
PropertyChanges { target: buttons; visible: true }
|
||||
PropertyChanges { target: backButton; visible: true; primary: true }
|
||||
PropertyChanges { target: backButton; visible: true; primary: true; focus: true }
|
||||
PropertyChanges { target: confirmButton; visible: false }
|
||||
}, State {
|
||||
// creating or sending transaction, show tx details and don't show any button
|
||||
@@ -141,7 +124,6 @@ Rectangle {
|
||||
|
||||
//clean previous error message
|
||||
errorText.text = "";
|
||||
root.forceActiveFocus()
|
||||
}
|
||||
|
||||
function close() {
|
||||
@@ -149,8 +131,8 @@ Rectangle {
|
||||
}
|
||||
|
||||
function clearFields() {
|
||||
root.recipients = [];
|
||||
root.transactionAmount = "";
|
||||
root.transactionAddress = "";
|
||||
root.transactionDescription = "";
|
||||
root.transactionFee = "";
|
||||
root.transactionPriority = "";
|
||||
@@ -159,13 +141,16 @@ Rectangle {
|
||||
|
||||
function showFiatConversion(valueXMR) {
|
||||
const fiatFee = fiatApiConvertToFiat(valueXMR);
|
||||
return "%1 %2".arg(fiatFee < 0.01 ? "<0.01" : "~" + fiatFee).arg(fiatApiCurrencySymbol());
|
||||
return "%1 %2".arg(fiatFee < 0.01 ? "<0.01" : "~" + fiatFee).arg(fiatApiCurrencySymbol());
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: layout
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.margins: parent.margins
|
||||
spacing: 10
|
||||
anchors.fill: parent
|
||||
anchors.margins: 25
|
||||
|
||||
RowLayout {
|
||||
Layout.topMargin: 10
|
||||
@@ -203,11 +188,11 @@ Rectangle {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 71
|
||||
|
||||
BusyIndicator {
|
||||
id: txAmountBusyIndicator
|
||||
Layout.fillWidth: true
|
||||
Layout.alignment : Qt.AlignTop | Qt.AlignLeft
|
||||
running: root.transactionAmount == "(all)"
|
||||
QtQuickControls1.BusyIndicator {
|
||||
id: txAmountBusyIndicator
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
running: root.transactionAmount == "(all)"
|
||||
}
|
||||
|
||||
Text {
|
||||
@@ -242,16 +227,10 @@ Rectangle {
|
||||
columnSpacing: 15
|
||||
rowSpacing: 16
|
||||
|
||||
ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.alignment : Qt.AlignTop | Qt.AlignLeft
|
||||
|
||||
Text {
|
||||
Layout.fillWidth: true
|
||||
color: MoneroComponents.Style.dimmedFontColor
|
||||
text: qsTr("From") + ":" + translationManager.emptyString
|
||||
font.pixelSize: 15
|
||||
}
|
||||
Text {
|
||||
color: MoneroComponents.Style.dimmedFontColor
|
||||
text: qsTr("From") + ":" + translationManager.emptyString
|
||||
font.pixelSize: 15
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
@@ -288,57 +267,70 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.alignment : Qt.AlignTop | Qt.AlignLeft
|
||||
|
||||
Text {
|
||||
Layout.fillWidth: true
|
||||
font.pixelSize: 15
|
||||
color: MoneroComponents.Style.dimmedFontColor
|
||||
text: qsTr("To") + ":" + translationManager.emptyString
|
||||
}
|
||||
Text {
|
||||
font.pixelSize: 15
|
||||
color: MoneroComponents.Style.dimmedFontColor
|
||||
text: qsTr("To") + ":" + translationManager.emptyString
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
Flickable {
|
||||
id: flickable
|
||||
property int linesInMultipleRecipientsMode: 7
|
||||
Layout.fillWidth: true
|
||||
spacing: 16
|
||||
Layout.preferredHeight: recipients.length > 1
|
||||
? linesInMultipleRecipientsMode * (recipientsArea.contentHeight / recipientsArea.lineCount)
|
||||
: recipientsArea.contentHeight
|
||||
boundsBehavior: isMac ? Flickable.DragAndOvershootBounds : Flickable.StopAtBounds
|
||||
clip: true
|
||||
|
||||
Text {
|
||||
Layout.fillWidth: true
|
||||
font.pixelSize: 15
|
||||
font.family: MoneroComponents.Style.fontRegular.name
|
||||
textFormat: Text.RichText
|
||||
wrapMode: Text.Wrap
|
||||
TextArea.flickable: TextArea {
|
||||
id : recipientsArea
|
||||
color: MoneroComponents.Style.defaultFontColor
|
||||
font.family: MoneroComponents.Style.fontMonoRegular.name
|
||||
font.pixelSize: 14
|
||||
topPadding: 0
|
||||
bottomPadding: 0
|
||||
leftPadding: 0
|
||||
textMargin: 0
|
||||
readOnly: true
|
||||
selectByKeyboard: true
|
||||
selectByMouse: true
|
||||
selectionColor: MoneroComponents.Style.textSelectionColor
|
||||
textFormat: TextEdit.RichText
|
||||
wrapMode: TextEdit.Wrap
|
||||
text: {
|
||||
if (root.transactionAddress) {
|
||||
const addressBookName = currentWallet ? currentWallet.addressBook.getDescription(root.transactionAddress) : null;
|
||||
var fulladdress = root.transactionAddress;
|
||||
var spacedaddress = fulladdress.match(/.{1,4}/g);
|
||||
var spacedaddress = spacedaddress.join(' ');
|
||||
if (!addressBookName) {
|
||||
return qsTr("Monero address") + "<br>" + spacedaddress + translationManager.emptyString;
|
||||
} else {
|
||||
return FontAwesome.addressBook + " " + addressBookName + "<br>" + spacedaddress;
|
||||
return recipients.map(function (recipient, index) {
|
||||
var addressBookName = null;
|
||||
if (currentWallet) {
|
||||
addressBookName = currentWallet.addressBook.getDescription(recipient.address);
|
||||
}
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
var title;
|
||||
if (addressBookName) {
|
||||
title = FontAwesome.addressBook + " " + addressBookName;
|
||||
} else {
|
||||
title = qsTr("Monero address") + translationManager.emptyString;
|
||||
}
|
||||
if (recipients.length > 1) {
|
||||
title = "%1. %2 - %3 XMR".arg(index + 1).arg(title).arg(recipient.amount);
|
||||
if (persistentSettings.fiatPriceEnabled) {
|
||||
title += " (%1)".arg(showFiatConversion(recipient.amount));
|
||||
}
|
||||
}
|
||||
const spacedaddress = recipient.address.match(/.{1,4}/g).join(' ');
|
||||
return title + "<br>" + spacedaddress;
|
||||
}).join("<br><br>");
|
||||
}
|
||||
}
|
||||
|
||||
ScrollBar.vertical: ScrollBar {
|
||||
policy: recipientsArea.contentHeight > flickable.height ? ScrollBar.AlwaysOn : ScrollBar.AlwaysOff
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.alignment : Qt.AlignTop | Qt.AlignLeft
|
||||
|
||||
Text {
|
||||
Layout.fillWidth: true
|
||||
color: MoneroComponents.Style.dimmedFontColor
|
||||
text: qsTr("Fee") + ":" + translationManager.emptyString
|
||||
font.pixelSize: 15
|
||||
}
|
||||
Text {
|
||||
color: MoneroComponents.Style.dimmedFontColor
|
||||
text: qsTr("Fee") + ":" + translationManager.emptyString
|
||||
font.pixelSize: 15
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
@@ -386,7 +378,7 @@ Rectangle {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 50
|
||||
|
||||
BusyIndicator {
|
||||
QtQuickControls1.BusyIndicator {
|
||||
visible: !bottomTextAnimation.running
|
||||
running: !bottomTextAnimation.running
|
||||
scale: .5
|
||||
@@ -422,17 +414,8 @@ Rectangle {
|
||||
id: backButton
|
||||
text: qsTr("Back") + translationManager.emptyString;
|
||||
width: 200
|
||||
focus: false
|
||||
primary: false
|
||||
KeyNavigation.tab: confirmButton
|
||||
Keys.enabled: backButton.visible
|
||||
Keys.onReturnPressed: backButton.onClicked
|
||||
Keys.onEnterPressed: backButton.onClicked
|
||||
Keys.onEscapePressed: {
|
||||
root.close()
|
||||
root.clearFields()
|
||||
root.rejected()
|
||||
}
|
||||
onClicked: {
|
||||
root.close()
|
||||
root.clearFields()
|
||||
@@ -445,16 +428,7 @@ Rectangle {
|
||||
text: qsTr("Confirm") + translationManager.emptyString;
|
||||
rightIcon: "qrc:///images/rightArrow.png"
|
||||
width: 200
|
||||
focus: false
|
||||
KeyNavigation.tab: backButton
|
||||
Keys.enabled: confirmButton.visible
|
||||
Keys.onReturnPressed: confirmButton.onClicked
|
||||
Keys.onEnterPressed: confirmButton.onClicked
|
||||
Keys.onEscapePressed: {
|
||||
root.close()
|
||||
root.clearFields()
|
||||
root.rejected()
|
||||
}
|
||||
onClicked: {
|
||||
root.close()
|
||||
root.accepted()
|
||||
|
||||
8
external/CMakeLists.txt
vendored
Normal file
8
external/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
add_library(quirc STATIC
|
||||
quirc/lib/decode.c
|
||||
quirc/lib/identify.c
|
||||
quirc/lib/quirc.c
|
||||
quirc/lib/version_db.c
|
||||
)
|
||||
set_target_properties(quirc PROPERTIES POSITION_INDEPENDENT_CODE ON)
|
||||
target_include_directories(quirc PUBLIC quirc/lib)
|
||||
1
external/quirc
vendored
Submodule
1
external/quirc
vendored
Submodule
Submodule external/quirc added at 7e7ab596e4
@@ -3,811 +3,71 @@ import QtQuick 2.9
|
||||
|
||||
Object {
|
||||
|
||||
//Font Awesome version 5.15.3
|
||||
FontLoader {
|
||||
id: regular
|
||||
source: "./fa-regular-400.ttf"
|
||||
source: "./fa-regular-400.otf"
|
||||
}
|
||||
|
||||
FontLoader {
|
||||
id: brands
|
||||
source: "./fa-brands-400.ttf"
|
||||
source: "./fa-brands-400.otf"
|
||||
}
|
||||
|
||||
FontLoader {
|
||||
id: solid
|
||||
source: "./fa-solid-900.ttf"
|
||||
source: "./fa-solid-900.otf"
|
||||
}
|
||||
|
||||
property string fontFamily: regular.name
|
||||
property string fontFamilyBrands: brands.name
|
||||
property string fontFamilySolid: solid.name
|
||||
|
||||
// Icons
|
||||
// Icons used in Monero GUI (Font Awesome version 5.15.3)
|
||||
// To add new icons, check unicodes in Font Awesome Free's Cheatsheet:
|
||||
// https://fontawesome.com/v5/cheatsheet/free/solid
|
||||
// https://fontawesome.com/v5/cheatsheet/free/regular
|
||||
// https://fontawesome.com/v5/cheatsheet/free/brands
|
||||
|
||||
property string addressBook : "\uf2b9"
|
||||
property string addressBookO : "\uf2ba"
|
||||
property string addressCard : "\uf2bb"
|
||||
property string addressCardO : "\uf2bc"
|
||||
property string adjust : "\uf042"
|
||||
property string adn : "\uf170"
|
||||
property string alignCenter : "\uf037"
|
||||
property string alignJustify : "\uf039"
|
||||
property string alignLeft : "\uf036"
|
||||
property string alignRight : "\uf038"
|
||||
property string amazon : "\uf270"
|
||||
property string ambulance : "\uf0f9"
|
||||
property string americanSignLanguageInterpreting : "\uf2a3"
|
||||
property string anchor : "\uf13d"
|
||||
property string android : "\uf17b"
|
||||
property string angellist : "\uf209"
|
||||
property string angleDoubleDown : "\uf103"
|
||||
property string angleDoubleLeft : "\uf100"
|
||||
property string angleDoubleRight : "\uf101"
|
||||
property string angleDoubleUp : "\uf102"
|
||||
property string angleDown : "\uf107"
|
||||
property string angleLeft : "\uf104"
|
||||
property string angleRight : "\uf105"
|
||||
property string angleUp : "\uf106"
|
||||
property string apple : "\uf179"
|
||||
property string archive : "\uf187"
|
||||
property string areaChart : "\uf1fe"
|
||||
property string arrowCircleDown : "\uf0ab"
|
||||
property string arrowCircleLeft : "\uf0a8"
|
||||
property string arrowCircleODown : "\uf01a"
|
||||
property string arrowCircleOLeft : "\uf190"
|
||||
property string arrowCircleORight : "\uf18e"
|
||||
property string arrowCircleOUp : "\uf01b"
|
||||
property string arrowCircleRight : "\uf0a9"
|
||||
property string arrowCircleUp : "\uf0aa"
|
||||
property string arrowDown : "\uf063"
|
||||
property string arrowLeft : "\uf060"
|
||||
property string arrowRight : "\uf061"
|
||||
property string arrowUp : "\uf062"
|
||||
property string arrows : "\uf047"
|
||||
property string arrowsAlt : "\uf0b2"
|
||||
property string arrowsH : "\uf07e"
|
||||
property string arrowsV : "\uf07d"
|
||||
property string aslInterpreting : "\uf2a3"
|
||||
property string assistiveListeningSystems : "\uf2a2"
|
||||
property string asterisk : "\uf069"
|
||||
property string at : "\uf1fa"
|
||||
property string audioDescription : "\uf29e"
|
||||
property string automobile : "\uf1b9"
|
||||
property string backward : "\uf04a"
|
||||
property string balanceScale : "\uf24e"
|
||||
property string ban : "\uf05e"
|
||||
property string bandcamp : "\uf2d5"
|
||||
property string bank : "\uf19c"
|
||||
property string barChart : "\uf080"
|
||||
property string barChartO : "\uf080"
|
||||
property string barcode : "\uf02a"
|
||||
property string bars : "\uf0c9"
|
||||
property string bath : "\uf2cd"
|
||||
property string bathtub : "\uf2cd"
|
||||
property string battery : "\uf240"
|
||||
property string battery0 : "\uf244"
|
||||
property string battery1 : "\uf243"
|
||||
property string battery2 : "\uf242"
|
||||
property string battery3 : "\uf241"
|
||||
property string battery4 : "\uf240"
|
||||
property string batteryEmpty : "\uf244"
|
||||
property string batteryFull : "\uf240"
|
||||
property string batteryHalf : "\uf242"
|
||||
property string batteryQuarter : "\uf243"
|
||||
property string batteryThreeQuarters : "\uf241"
|
||||
property string bed : "\uf236"
|
||||
property string beer : "\uf0fc"
|
||||
property string behance : "\uf1b4"
|
||||
property string behanceSquare : "\uf1b5"
|
||||
property string bell : "\uf0f3"
|
||||
property string bellO : "\uf0a2"
|
||||
property string bellSlash : "\uf1f6"
|
||||
property string bellSlashO : "\uf1f7"
|
||||
property string bicycle : "\uf206"
|
||||
property string binoculars : "\uf1e5"
|
||||
property string birthdayCake : "\uf1fd"
|
||||
property string bitbucket : "\uf171"
|
||||
property string bitbucketSquare : "\uf172"
|
||||
property string bitcoin : "\uf15a"
|
||||
property string blackTie : "\uf27e"
|
||||
property string blind : "\uf29d"
|
||||
property string bluetooth : "\uf293"
|
||||
property string bluetoothB : "\uf294"
|
||||
property string bold : "\uf032"
|
||||
property string bolt : "\uf0e7"
|
||||
property string bomb : "\uf1e2"
|
||||
property string book : "\uf02d"
|
||||
property string bookmark : "\uf02e"
|
||||
property string bookmarkO : "\uf097"
|
||||
property string braille : "\uf2a1"
|
||||
property string briefcase : "\uf0b1"
|
||||
property string btc : "\uf15a"
|
||||
property string bug : "\uf188"
|
||||
property string building : "\uf1ad"
|
||||
property string buildingO : "\uf0f7"
|
||||
property string bullhorn : "\uf0a1"
|
||||
property string bullseye : "\uf140"
|
||||
property string bus : "\uf207"
|
||||
property string buysellads : "\uf20d"
|
||||
property string cab : "\uf1ba"
|
||||
property string calculator : "\uf1ec"
|
||||
property string calendar : "\uf073"
|
||||
property string calendarCheckO : "\uf274"
|
||||
property string calendarMinusO : "\uf272"
|
||||
property string calendarO : "\uf133"
|
||||
property string calendarPlusO : "\uf271"
|
||||
property string calendarTimesO : "\uf273"
|
||||
property string camera : "\uf030"
|
||||
property string cameraRetro : "\uf083"
|
||||
property string car : "\uf1b9"
|
||||
property string caretDown : "\uf0d7"
|
||||
property string caretLeft : "\uf0d9"
|
||||
property string caretRight : "\uf0da"
|
||||
property string caretSquareODown : "\uf150"
|
||||
property string caretSquareOLeft : "\uf191"
|
||||
property string caretSquareORight : "\uf152"
|
||||
property string caretSquareOUp : "\uf151"
|
||||
property string caretUp : "\uf0d8"
|
||||
property string cartArrowDown : "\uf218"
|
||||
property string cartPlus : "\uf217"
|
||||
property string cashRegister: "\uf788"
|
||||
property string cc : "\uf20a"
|
||||
property string ccAmex : "\uf1f3"
|
||||
property string ccDinersClub : "\uf24c"
|
||||
property string ccDiscover : "\uf1f2"
|
||||
property string ccJcb : "\uf24b"
|
||||
property string ccMastercard : "\uf1f1"
|
||||
property string ccPaypal : "\uf1f4"
|
||||
property string ccStripe : "\uf1f5"
|
||||
property string ccVisa : "\uf1f0"
|
||||
property string certificate : "\uf0a3"
|
||||
property string chain : "\uf0c1"
|
||||
property string chainBroken : "\uf127"
|
||||
property string check : "\uf00c"
|
||||
property string checkCircle : "\uf058"
|
||||
property string checkCircleO : "\uf05d"
|
||||
property string checkSquare : "\uf14a"
|
||||
property string checkSquareO : "\uf046"
|
||||
property string chevronCircleDown : "\uf13a"
|
||||
property string chevronCircleLeft : "\uf137"
|
||||
property string chevronCircleRight : "\uf138"
|
||||
property string chevronCircleUp : "\uf139"
|
||||
property string chevronDown : "\uf078"
|
||||
property string chevronLeft : "\uf053"
|
||||
property string chevronRight : "\uf054"
|
||||
property string chevronUp : "\uf077"
|
||||
property string child : "\uf1ae"
|
||||
property string chrome : "\uf268"
|
||||
property string circle : "\uf111"
|
||||
property string circleO : "\uf10c"
|
||||
property string circleONotch : "\uf1ce"
|
||||
property string circleThin : "\uf1db"
|
||||
property string clipboard : "\uf0ea"
|
||||
property string clockO : "\uf017"
|
||||
property string clone : "\uf24d"
|
||||
property string close : "\uf00d"
|
||||
property string cloud : "\uf0c2"
|
||||
property string cloudDownload : "\uf0ed"
|
||||
property string cloudUpload : "\uf0ee"
|
||||
property string cny : "\uf157"
|
||||
property string code : "\uf121"
|
||||
property string codeFork : "\uf126"
|
||||
property string codepen : "\uf1cb"
|
||||
property string codiepie : "\uf284"
|
||||
property string coffee : "\uf0f4"
|
||||
property string cog : "\uf013"
|
||||
property string cogs : "\uf085"
|
||||
property string columns : "\uf0db"
|
||||
property string comment : "\uf075"
|
||||
property string commentO : "\uf0e5"
|
||||
property string commenting : "\uf27a"
|
||||
property string commentingO : "\uf27b"
|
||||
property string comments : "\uf086"
|
||||
property string commentsO : "\uf0e6"
|
||||
property string compass : "\uf14e"
|
||||
property string compress : "\uf066"
|
||||
property string connectdevelop : "\uf20e"
|
||||
property string contao : "\uf26d"
|
||||
property string copy : "\uf0c5"
|
||||
property string copyright : "\uf1f9"
|
||||
property string creativeCommons : "\uf25e"
|
||||
property string creditCard : "\uf09d"
|
||||
property string creditCardAlt : "\uf283"
|
||||
property string crop : "\uf125"
|
||||
property string crosshairs : "\uf05b"
|
||||
property string css3 : "\uf13c"
|
||||
property string cube : "\uf1b2"
|
||||
property string cubes : "\uf1b3"
|
||||
property string cut : "\uf0c4"
|
||||
property string cutlery : "\uf0f5"
|
||||
property string dashboard : "\uf0e4"
|
||||
property string dashcube : "\uf210"
|
||||
property string database : "\uf1c0"
|
||||
property string deaf : "\uf2a4"
|
||||
property string deafness : "\uf2a4"
|
||||
property string dedent : "\uf03b"
|
||||
property string delicious : "\uf1a5"
|
||||
property string desktop : "\uf108"
|
||||
property string deviantart : "\uf1bd"
|
||||
property string diamond : "\uf219"
|
||||
property string digg : "\uf1a6"
|
||||
property string dollar : "\uf155"
|
||||
property string dotCircleO : "\uf192"
|
||||
property string download : "\uf019"
|
||||
property string dribbble : "\uf17d"
|
||||
property string driversLicense : "\uf2c2"
|
||||
property string driversLicenseO : "\uf2c3"
|
||||
property string dropbox : "\uf16b"
|
||||
property string drupal : "\uf1a9"
|
||||
property string edge : "\uf282"
|
||||
property string edit : "\uf044"
|
||||
property string eercast : "\uf2da"
|
||||
property string eject : "\uf052"
|
||||
property string ellipsisH : "\uf141"
|
||||
property string ellipsisV : "\uf142"
|
||||
property string empire : "\uf1d1"
|
||||
property string envelope : "\uf0e0"
|
||||
property string envelopeO : "\uf003"
|
||||
property string envelopeOpen : "\uf2b6"
|
||||
property string envelopeOpenO : "\uf2b7"
|
||||
property string envelopeSquare : "\uf199"
|
||||
property string envira : "\uf299"
|
||||
property string eraser : "\uf12d"
|
||||
property string etsy : "\uf2d7"
|
||||
property string eur : "\uf153"
|
||||
property string euro : "\uf153"
|
||||
property string exchange : "\uf0ec"
|
||||
property string exclamation : "\uf12a"
|
||||
property string exclamationCircle : "\uf06a"
|
||||
property string exclamationTriangle : "\uf071"
|
||||
property string expand : "\uf065"
|
||||
property string expeditedssl : "\uf23e"
|
||||
property string externalLink : "\uf08e"
|
||||
property string externalLinkSquare : "\uf14c"
|
||||
property string eye : "\uf06e"
|
||||
property string eyeSlash : "\uf070"
|
||||
property string eyedropper : "\uf1fb"
|
||||
property string fa : "\uf2b4"
|
||||
property string facebook : "\uf09a"
|
||||
property string facebookF : "\uf09a"
|
||||
property string facebookOfficial : "\uf230"
|
||||
property string facebookSquare : "\uf082"
|
||||
property string fastBackward : "\uf049"
|
||||
property string fastForward : "\uf050"
|
||||
property string fax : "\uf1ac"
|
||||
property string feed : "\uf09e"
|
||||
property string female : "\uf182"
|
||||
property string fighterJet : "\uf0fb"
|
||||
property string file : "\uf15b"
|
||||
property string fileArchiveO : "\uf1c6"
|
||||
property string fileAudioO : "\uf1c7"
|
||||
property string fileCodeO : "\uf1c9"
|
||||
property string fileExcelO : "\uf1c3"
|
||||
property string fileImageO : "\uf1c5"
|
||||
property string fileMovieO : "\uf1c8"
|
||||
property string fileO : "\uf016"
|
||||
property string filePdfO : "\uf1c1"
|
||||
property string filePhotoO : "\uf1c5"
|
||||
property string filePictureO : "\uf1c5"
|
||||
property string filePowerpointO : "\uf1c4"
|
||||
property string fileSoundO : "\uf1c7"
|
||||
property string fileText : "\uf15c"
|
||||
property string fileTextO : "\uf0f6"
|
||||
property string fileVideoO : "\uf1c8"
|
||||
property string fileWordO : "\uf1c2"
|
||||
property string fileZipO : "\uf1c6"
|
||||
property string filesO : "\uf0c5"
|
||||
property string film : "\uf008"
|
||||
property string filter : "\uf0b0"
|
||||
property string fire : "\uf06d"
|
||||
property string fireExtinguisher : "\uf134"
|
||||
property string firefox : "\uf269"
|
||||
property string firstOrder : "\uf2b0"
|
||||
property string flag : "\uf024"
|
||||
property string flagCheckered : "\uf11e"
|
||||
property string flagO : "\uf11d"
|
||||
property string flash : "\uf0e7"
|
||||
property string flask : "\uf0c3"
|
||||
property string flickr : "\uf16e"
|
||||
property string floppyO : "\uf0c7"
|
||||
property string folder : "\uf07b"
|
||||
property string folderO : "\uf114"
|
||||
property string folderOpen : "\uf07c"
|
||||
property string folderOpenO : "\uf115"
|
||||
property string font : "\uf031"
|
||||
property string fontAwesome : "\uf2b4"
|
||||
property string fonticons : "\uf280"
|
||||
property string fortAwesome : "\uf286"
|
||||
property string forumbee : "\uf211"
|
||||
property string forward : "\uf04e"
|
||||
property string foursquare : "\uf180"
|
||||
property string freeCodeCamp : "\uf2c5"
|
||||
property string frownO : "\uf119"
|
||||
property string futbolO : "\uf1e3"
|
||||
property string gamepad : "\uf11b"
|
||||
property string gavel : "\uf0e3"
|
||||
property string gbp : "\uf154"
|
||||
property string ge : "\uf1d1"
|
||||
property string gear : "\uf013"
|
||||
property string gears : "\uf085"
|
||||
property string genderless : "\uf22d"
|
||||
property string getPocket : "\uf265"
|
||||
property string gg : "\uf260"
|
||||
property string ggCircle : "\uf261"
|
||||
property string gift : "\uf06b"
|
||||
property string git : "\uf1d3"
|
||||
property string gitSquare : "\uf1d2"
|
||||
property string github : "\uf09b"
|
||||
property string githubAlt : "\uf113"
|
||||
property string githubSquare : "\uf092"
|
||||
property string gitlab : "\uf296"
|
||||
property string gittip : "\uf184"
|
||||
property string glass : "\uf000"
|
||||
property string glide : "\uf2a5"
|
||||
property string glideG : "\uf2a6"
|
||||
property string globe : "\uf0ac"
|
||||
property string google : "\uf1a0"
|
||||
property string googlePlus : "\uf0d5"
|
||||
property string googlePlusCircle : "\uf2b3"
|
||||
property string googlePlusOfficial : "\uf2b3"
|
||||
property string googlePlusSquare : "\uf0d4"
|
||||
property string googleWallet : "\uf1ee"
|
||||
property string graduationCap : "\uf19d"
|
||||
property string gratipay : "\uf184"
|
||||
property string grav : "\uf2d6"
|
||||
property string group : "\uf0c0"
|
||||
property string hSquare : "\uf0fd"
|
||||
property string hackerNews : "\uf1d4"
|
||||
property string handGrabO : "\uf255"
|
||||
property string handLizardO : "\uf258"
|
||||
property string handODown : "\uf0a7"
|
||||
property string handOLeft : "\uf0a5"
|
||||
property string handORight : "\uf0a4"
|
||||
property string handOUp : "\uf0a6"
|
||||
property string handPaperO : "\uf256"
|
||||
property string handPeaceO : "\uf25b"
|
||||
property string handPointerO : "\uf25a"
|
||||
property string handRockO : "\uf255"
|
||||
property string handScissorsO : "\uf257"
|
||||
property string handSpockO : "\uf259"
|
||||
property string handStopO : "\uf256"
|
||||
property string handshakeO : "\uf2b5"
|
||||
property string hardOfHearing : "\uf2a4"
|
||||
property string hashtag : "\uf292"
|
||||
property string hddO : "\uf0a0"
|
||||
property string header : "\uf1dc"
|
||||
property string headphones : "\uf025"
|
||||
property string heart : "\uf004"
|
||||
property string heartO : "\uf08a"
|
||||
property string heartbeat : "\uf21e"
|
||||
property string history : "\uf1da"
|
||||
property string home : "\uf015"
|
||||
property string hospitalO : "\uf0f8"
|
||||
property string hotel : "\uf236"
|
||||
property string hourglass : "\uf254"
|
||||
property string hourglass1 : "\uf251"
|
||||
property string hourglass2 : "\uf252"
|
||||
property string hourglass3 : "\uf253"
|
||||
property string hourglassEnd : "\uf253"
|
||||
property string hourglassHalf : "\uf252"
|
||||
property string hourglassO : "\uf250"
|
||||
property string hourglassStart : "\uf251"
|
||||
property string houzz : "\uf27c"
|
||||
property string html5 : "\uf13b"
|
||||
property string iCursor : "\uf246"
|
||||
property string idBadge : "\uf2c1"
|
||||
property string idCard : "\uf2c2"
|
||||
property string idCardO : "\uf2c3"
|
||||
property string ils : "\uf20b"
|
||||
property string image : "\uf03e"
|
||||
property string imdb : "\uf2d8"
|
||||
property string inbox : "\uf01c"
|
||||
property string indent : "\uf03c"
|
||||
property string industry : "\uf275"
|
||||
property string houseUser : "\ue065"
|
||||
property string infinity : "\uf534"
|
||||
property string info : "\uf129"
|
||||
property string infoCircle : "\uf05a"
|
||||
property string inr : "\uf156"
|
||||
property string instagram : "\uf16d"
|
||||
property string institution : "\uf19c"
|
||||
property string internetExplorer : "\uf26b"
|
||||
property string intersex : "\uf224"
|
||||
property string ioxhost : "\uf208"
|
||||
property string italic : "\uf033"
|
||||
property string joomla : "\uf1aa"
|
||||
property string jpy : "\uf157"
|
||||
property string jsfiddle : "\uf1cc"
|
||||
property string key : "\uf084"
|
||||
property string keyboardO : "\uf11c"
|
||||
property string krw : "\uf159"
|
||||
property string language : "\uf1ab"
|
||||
property string laptop : "\uf109"
|
||||
property string lastfm : "\uf202"
|
||||
property string lastfmSquare : "\uf203"
|
||||
property string leaf : "\uf06c"
|
||||
property string leanpub : "\uf212"
|
||||
property string legal : "\uf0e3"
|
||||
property string lemonO : "\uf094"
|
||||
property string levelDown : "\uf149"
|
||||
property string levelUp : "\uf148"
|
||||
property string lifeBouy : "\uf1cd"
|
||||
property string lifeBuoy : "\uf1cd"
|
||||
property string lifeRing : "\uf1cd"
|
||||
property string lifeSaver : "\uf1cd"
|
||||
property string lightbulbO : "\uf0eb"
|
||||
property string lineChart : "\uf201"
|
||||
property string link : "\uf0c1"
|
||||
property string linkedin : "\uf0e1"
|
||||
property string linkedinSquare : "\uf08c"
|
||||
property string linode : "\uf2b8"
|
||||
property string linux : "\uf17c"
|
||||
property string list : "\uf03a"
|
||||
property string listAlt : "\uf022"
|
||||
property string listOl : "\uf0cb"
|
||||
property string listUl : "\uf0ca"
|
||||
property string locationArrow : "\uf124"
|
||||
property string lock : "\uf023"
|
||||
property string longArrowDown : "\uf175"
|
||||
property string longArrowLeft : "\uf177"
|
||||
property string longArrowRight : "\uf178"
|
||||
property string longArrowUp : "\uf176"
|
||||
property string lowVision : "\uf2a8"
|
||||
property string magic : "\uf0d0"
|
||||
property string magnet : "\uf076"
|
||||
property string mailForward : "\uf064"
|
||||
property string mailReply : "\uf112"
|
||||
property string mailReplyAll : "\uf122"
|
||||
property string male : "\uf183"
|
||||
property string map : "\uf279"
|
||||
property string mapMarker : "\uf041"
|
||||
property string mapO : "\uf278"
|
||||
property string mapPin : "\uf276"
|
||||
property string mapSigns : "\uf277"
|
||||
property string mars : "\uf222"
|
||||
property string marsDouble : "\uf227"
|
||||
property string marsStroke : "\uf229"
|
||||
property string marsStrokeH : "\uf22b"
|
||||
property string marsStrokeV : "\uf22a"
|
||||
property string maxcdn : "\uf136"
|
||||
property string meanpath : "\uf20c"
|
||||
property string medium : "\uf23a"
|
||||
property string medkit : "\uf0fa"
|
||||
property string meetup : "\uf2e0"
|
||||
property string mehO : "\uf11a"
|
||||
property string mercury : "\uf223"
|
||||
property string microchip : "\uf2db"
|
||||
property string microphone : "\uf130"
|
||||
property string microphoneSlash : "\uf131"
|
||||
property string minus : "\uf068"
|
||||
property string minusCircle : "\uf056"
|
||||
property string minusSquare : "\uf146"
|
||||
property string minusSquareO : "\uf147"
|
||||
property string mixcloud : "\uf289"
|
||||
property string mobile : "\uf10b"
|
||||
property string mobilePhone : "\uf10b"
|
||||
property string modx : "\uf285"
|
||||
property string money : "\uf0d6"
|
||||
property string moonO : "\uf186"
|
||||
property string mortarBoard : "\uf19d"
|
||||
property string motorcycle : "\uf21c"
|
||||
property string mousePointer : "\uf245"
|
||||
property string music : "\uf001"
|
||||
property string navicon : "\uf0c9"
|
||||
property string neuter : "\uf22c"
|
||||
property string newspaperO : "\uf1ea"
|
||||
property string objectGroup : "\uf247"
|
||||
property string objectUngroup : "\uf248"
|
||||
property string odnoklassniki : "\uf263"
|
||||
property string odnoklassnikiSquare : "\uf264"
|
||||
property string opencart : "\uf23d"
|
||||
property string openid : "\uf19b"
|
||||
property string opera : "\uf26a"
|
||||
property string optinMonster : "\uf23c"
|
||||
property string outdent : "\uf03b"
|
||||
property string pagelines : "\uf18c"
|
||||
property string paintBrush : "\uf1fc"
|
||||
property string paperPlane : "\uf1d8"
|
||||
property string paperPlaneO : "\uf1d9"
|
||||
property string paperclip : "\uf0c6"
|
||||
property string paragraph : "\uf1dd"
|
||||
property string monero : "\uf3d0"
|
||||
property string paste : "\uf0ea"
|
||||
property string pause : "\uf04c"
|
||||
property string pauseCircle : "\uf28b"
|
||||
property string pauseCircleO : "\uf28c"
|
||||
property string paw : "\uf1b0"
|
||||
property string paypal : "\uf1ed"
|
||||
property string pencil : "\uf040"
|
||||
property string pencilSquare : "\uf14b"
|
||||
property string pencilSquareO : "\uf044"
|
||||
property string percent : "\uf295"
|
||||
property string phone : "\uf095"
|
||||
property string phoneSquare : "\uf098"
|
||||
property string photo : "\uf03e"
|
||||
property string pictureO : "\uf03e"
|
||||
property string pieChart : "\uf200"
|
||||
property string piedPiper : "\uf2ae"
|
||||
property string piedPiperAlt : "\uf1a8"
|
||||
property string piedPiperPp : "\uf1a7"
|
||||
property string pinterest : "\uf0d2"
|
||||
property string pinterestP : "\uf231"
|
||||
property string pinterestSquare : "\uf0d3"
|
||||
property string plane : "\uf072"
|
||||
property string play : "\uf04b"
|
||||
property string playCircle : "\uf144"
|
||||
property string playCircleO : "\uf01d"
|
||||
property string plug : "\uf1e6"
|
||||
property string plus : "\uf067"
|
||||
property string plusCircle : "\uf055"
|
||||
property string plusSquare : "\uf0fe"
|
||||
property string plusSquareO : "\uf196"
|
||||
property string podcast : "\uf2ce"
|
||||
property string powerOff : "\uf011"
|
||||
property string printIcon : "\uf02f"
|
||||
property string productHunt : "\uf288"
|
||||
property string puzzlePiece : "\uf12e"
|
||||
property string qq : "\uf1d6"
|
||||
property string qrcode : "\uf029"
|
||||
property string question : "\uf128"
|
||||
property string questionCircle : "\uf059"
|
||||
property string questionCircleO : "\uf29c"
|
||||
property string quora : "\uf2c4"
|
||||
property string quoteLeft : "\uf10d"
|
||||
property string quoteRight : "\uf10e"
|
||||
property string ra : "\uf1d0"
|
||||
property string random : "\uf074"
|
||||
property string ravelry : "\uf2d9"
|
||||
property string rebel : "\uf1d0"
|
||||
property string recycle : "\uf1b8"
|
||||
property string reddit : "\uf1a1"
|
||||
property string redditAlien : "\uf281"
|
||||
property string redditSquare : "\uf1a2"
|
||||
property string refresh : "\uf021"
|
||||
property string registered : "\uf25d"
|
||||
property string remove : "\uf00d"
|
||||
property string renren : "\uf18b"
|
||||
property string reorder : "\uf0c9"
|
||||
property string repeat : "\uf01e"
|
||||
property string reply : "\uf112"
|
||||
property string replyAll : "\uf122"
|
||||
property string resistance : "\uf1d0"
|
||||
property string retweet : "\uf079"
|
||||
property string rmb : "\uf157"
|
||||
property string road : "\uf018"
|
||||
property string rocket : "\uf135"
|
||||
property string rotateLeft : "\uf0e2"
|
||||
property string rotateRight : "\uf01e"
|
||||
property string rouble : "\uf158"
|
||||
property string rss : "\uf09e"
|
||||
property string rssSquare : "\uf143"
|
||||
property string rub : "\uf158"
|
||||
property string ruble : "\uf158"
|
||||
property string rupee : "\uf156"
|
||||
property string s15 : "\uf2cd"
|
||||
property string safari : "\uf267"
|
||||
property string save : "\uf0c7"
|
||||
property string scissors : "\uf0c4"
|
||||
property string scribd : "\uf28a"
|
||||
property string search : "\uf002"
|
||||
property string searchMinus : "\uf010"
|
||||
property string searchPlus : "\uf00e"
|
||||
property string sellsy : "\uf213"
|
||||
property string send : "\uf1d8"
|
||||
property string sendO : "\uf1d9"
|
||||
property string server : "\uf233"
|
||||
property string share : "\uf064"
|
||||
property string shareAlt : "\uf1e0"
|
||||
property string shareAltSquare : "\uf1e1"
|
||||
property string shareSquare : "\uf14d"
|
||||
property string shareSquareO : "\uf045"
|
||||
property string shekel : "\uf20b"
|
||||
property string sheqel : "\uf20b"
|
||||
property string shield : "\uf132"
|
||||
property string ship : "\uf21a"
|
||||
property string shirtsinbulk : "\uf214"
|
||||
property string shoppingBag : "\uf290"
|
||||
property string shoppingBasket : "\uf291"
|
||||
property string shoppingCart : "\uf07a"
|
||||
property string shower : "\uf2cc"
|
||||
property string signIn : "\uf090"
|
||||
property string signLanguage : "\uf2a7"
|
||||
property string shieldAlt : "\uf3ed"
|
||||
property string signOutAlt : "\uf2f5"
|
||||
property string signOut : "\uf08b"
|
||||
property string signal : "\uf012"
|
||||
property string signing : "\uf2a7"
|
||||
property string simplybuilt : "\uf215"
|
||||
property string sitemap : "\uf0e8"
|
||||
property string skyatlas : "\uf216"
|
||||
property string skype : "\uf17e"
|
||||
property string slack : "\uf198"
|
||||
property string sliders : "\uf1de"
|
||||
property string slideshare : "\uf1e7"
|
||||
property string smileO : "\uf118"
|
||||
property string snapchat : "\uf2ab"
|
||||
property string snapchatGhost : "\uf2ac"
|
||||
property string snapchatSquare : "\uf2ad"
|
||||
property string snowflakeO : "\uf2dc"
|
||||
property string soccerBallO : "\uf1e3"
|
||||
property string sort : "\uf0dc"
|
||||
property string sortAlphaAsc : "\uf15d"
|
||||
property string sortAlphaDesc : "\uf15e"
|
||||
property string sortAmountAsc : "\uf160"
|
||||
property string sortAmountDesc : "\uf161"
|
||||
property string sortAsc : "\uf0de"
|
||||
property string sortDesc : "\uf0dd"
|
||||
property string sortDown : "\uf0dd"
|
||||
property string sortNumericAsc : "\uf162"
|
||||
property string sortNumericDesc : "\uf163"
|
||||
property string sortUp : "\uf0de"
|
||||
property string soundcloud : "\uf1be"
|
||||
property string spaceShuttle : "\uf197"
|
||||
property string spinner : "\uf110"
|
||||
property string spoon : "\uf1b1"
|
||||
property string spotify : "\uf1bc"
|
||||
property string square : "\uf0c8"
|
||||
property string squareO : "\uf096"
|
||||
property string stackExchange : "\uf18d"
|
||||
property string stackOverflow : "\uf16c"
|
||||
property string star : "\uf005"
|
||||
property string starHalf : "\uf089"
|
||||
property string starHalfEmpty : "\uf123"
|
||||
property string starHalfFull : "\uf123"
|
||||
property string starHalfO : "\uf123"
|
||||
property string starO : "\uf006"
|
||||
property string steam : "\uf1b6"
|
||||
property string steamSquare : "\uf1b7"
|
||||
property string stepBackward : "\uf048"
|
||||
property string stepForward : "\uf051"
|
||||
property string stethoscope : "\uf0f1"
|
||||
property string stickyNote : "\uf249"
|
||||
property string stickyNoteO : "\uf24a"
|
||||
property string stop : "\uf04d"
|
||||
property string stopCircle : "\uf28d"
|
||||
property string stopCircleO : "\uf28e"
|
||||
property string streetView : "\uf21d"
|
||||
property string strikethrough : "\uf0cc"
|
||||
property string stumbleupon : "\uf1a4"
|
||||
property string stumbleuponCircle : "\uf1a3"
|
||||
property string subscript : "\uf12c"
|
||||
property string subway : "\uf239"
|
||||
property string suitcase : "\uf0f2"
|
||||
property string sunO : "\uf185"
|
||||
property string superpowers : "\uf2dd"
|
||||
property string superscript : "\uf12b"
|
||||
property string support : "\uf1cd"
|
||||
property string table : "\uf0ce"
|
||||
property string tablet : "\uf10a"
|
||||
property string tachometer : "\uf0e4"
|
||||
property string tag : "\uf02b"
|
||||
property string tags : "\uf02c"
|
||||
property string tasks : "\uf0ae"
|
||||
property string taxi : "\uf1ba"
|
||||
property string telegram : "\uf2c6"
|
||||
property string television : "\uf26c"
|
||||
property string tencentWeibo : "\uf1d5"
|
||||
property string terminal : "\uf120"
|
||||
property string textHeight : "\uf034"
|
||||
property string textWidth : "\uf035"
|
||||
property string th : "\uf00a"
|
||||
property string thLarge : "\uf009"
|
||||
property string thList : "\uf00b"
|
||||
property string themeisle : "\uf2b2"
|
||||
property string thermometer : "\uf2c7"
|
||||
property string thermometer0 : "\uf2cb"
|
||||
property string thermometer1 : "\uf2ca"
|
||||
property string thermometer2 : "\uf2c9"
|
||||
property string thermometer3 : "\uf2c8"
|
||||
property string thermometer4 : "\uf2c7"
|
||||
property string thermometerEmpty : "\uf2cb"
|
||||
property string thermometerFull : "\uf2c7"
|
||||
property string thermometerHalf : "\uf2c9"
|
||||
property string thermometerQuarter : "\uf2ca"
|
||||
property string thermometerThreeQuarters : "\uf2c8"
|
||||
property string thumbTack : "\uf08d"
|
||||
property string thumbsDown : "\uf165"
|
||||
property string thumbsODown : "\uf088"
|
||||
property string thumbsOUp : "\uf087"
|
||||
property string thumbsUp : "\uf164"
|
||||
property string ticket : "\uf145"
|
||||
property string times : "\uf00d"
|
||||
property string timesCircle : "\uf057"
|
||||
property string timesCircleO : "\uf05c"
|
||||
property string timesRectangle : "\uf2d3"
|
||||
property string timesRectangleO : "\uf2d4"
|
||||
property string tint : "\uf043"
|
||||
property string toggleDown : "\uf150"
|
||||
property string toggleLeft : "\uf191"
|
||||
property string toggleOff : "\uf204"
|
||||
property string toggleOn : "\uf205"
|
||||
property string toggleRight : "\uf152"
|
||||
property string toggleUp : "\uf151"
|
||||
property string trademark : "\uf25c"
|
||||
property string train : "\uf238"
|
||||
property string transgender : "\uf224"
|
||||
property string transgenderAlt : "\uf225"
|
||||
property string trash : "\uf1f8"
|
||||
property string trashO : "\uf014"
|
||||
property string tree : "\uf1bb"
|
||||
property string trello : "\uf181"
|
||||
property string tripadvisor : "\uf262"
|
||||
property string trophy : "\uf091"
|
||||
property string truck : "\uf0d1"
|
||||
property string tryIcon : "\uf195"
|
||||
property string tty : "\uf1e4"
|
||||
property string tumblr : "\uf173"
|
||||
property string tumblrSquare : "\uf174"
|
||||
property string turkishLira : "\uf195"
|
||||
property string tv : "\uf26c"
|
||||
property string twitch : "\uf1e8"
|
||||
property string twitter : "\uf099"
|
||||
property string twitterSquare : "\uf081"
|
||||
property string umbrella : "\uf0e9"
|
||||
property string underline : "\uf0cd"
|
||||
property string undo : "\uf0e2"
|
||||
property string universalAccess : "\uf29a"
|
||||
property string university : "\uf19c"
|
||||
property string unlink : "\uf127"
|
||||
property string unlock : "\uf09c"
|
||||
property string unlockAlt : "\uf13e"
|
||||
property string unsorted : "\uf0dc"
|
||||
property string upload : "\uf093"
|
||||
property string usb : "\uf287"
|
||||
property string usd : "\uf155"
|
||||
property string user : "\uf007"
|
||||
property string userCircle : "\uf2bd"
|
||||
property string userCircleO : "\uf2be"
|
||||
property string userMd : "\uf0f0"
|
||||
property string userO : "\uf2c0"
|
||||
property string userPlus : "\uf234"
|
||||
property string userSecret : "\uf21b"
|
||||
property string userTimes : "\uf235"
|
||||
property string users : "\uf0c0"
|
||||
property string vcard : "\uf2bb"
|
||||
property string vcardO : "\uf2bc"
|
||||
property string venus : "\uf221"
|
||||
property string venusDouble : "\uf226"
|
||||
property string venusMars : "\uf228"
|
||||
property string viacoin : "\uf237"
|
||||
property string viadeo : "\uf2a9"
|
||||
property string viadeoSquare : "\uf2aa"
|
||||
property string videoCamera : "\uf03d"
|
||||
property string vimeo : "\uf27d"
|
||||
property string vimeoSquare : "\uf194"
|
||||
property string vine : "\uf1ca"
|
||||
property string vk : "\uf189"
|
||||
property string volumeControlPhone : "\uf2a0"
|
||||
property string volumeDown : "\uf027"
|
||||
property string volumeOff : "\uf026"
|
||||
property string volumeUp : "\uf028"
|
||||
property string warning : "\uf071"
|
||||
property string wechat : "\uf1d7"
|
||||
property string weibo : "\uf18a"
|
||||
property string weixin : "\uf1d7"
|
||||
property string whatsapp : "\uf232"
|
||||
property string wheelchair : "\uf193"
|
||||
property string wheelchairAlt : "\uf29b"
|
||||
property string wifi : "\uf1eb"
|
||||
property string wikipediaW : "\uf266"
|
||||
property string windowClose : "\uf2d3"
|
||||
property string windowCloseO : "\uf2d4"
|
||||
property string windowMaximize : "\uf2d0"
|
||||
property string windowMinimize : "\uf2d1"
|
||||
property string windowRestore : "\uf2d2"
|
||||
property string windows : "\uf17a"
|
||||
property string won : "\uf159"
|
||||
property string wordpress : "\uf19a"
|
||||
property string wpbeginner : "\uf297"
|
||||
property string wpexplorer : "\uf2de"
|
||||
property string wpforms : "\uf298"
|
||||
property string wrench : "\uf0ad"
|
||||
property string xing : "\uf168"
|
||||
property string xingSquare : "\uf169"
|
||||
property string yCombinator : "\uf23b"
|
||||
property string yCombinatorSquare : "\uf1d4"
|
||||
property string yahoo : "\uf19e"
|
||||
property string yc : "\uf23b"
|
||||
property string ycSquare : "\uf1d4"
|
||||
property string yelp : "\uf1e9"
|
||||
property string yen : "\uf157"
|
||||
property string yoast : "\uf2b1"
|
||||
property string youtube : "\uf167"
|
||||
property string youtubePlay : "\uf16a"
|
||||
property string youtubeSquare : "\uf166"
|
||||
}
|
||||
|
||||
BIN
fonts/FontAwesome/fa-brands-400.otf
Normal file
BIN
fonts/FontAwesome/fa-brands-400.otf
Normal file
Binary file not shown.
Binary file not shown.
BIN
fonts/FontAwesome/fa-regular-400.otf
Normal file
BIN
fonts/FontAwesome/fa-regular-400.otf
Normal file
Binary file not shown.
Binary file not shown.
BIN
fonts/FontAwesome/fa-solid-900.otf
Normal file
BIN
fonts/FontAwesome/fa-solid-900.otf
Normal file
Binary file not shown.
Binary file not shown.
BIN
images/ledgerNanoS.png
Normal file
BIN
images/ledgerNanoS.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
BIN
images/ledgerNanoX.png
Normal file
BIN
images/ledgerNanoX.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
BIN
images/trezor.png
Normal file
BIN
images/trezor.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 72 KiB |
BIN
images/trezor@2x.png
Normal file
BIN
images/trezor@2x.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 301 KiB |
@@ -105,9 +105,6 @@ Source: "bin\extras\monero-gen-ssl-cert.exe"; DestDir: "{app}"; Flags: ignorever
|
||||
; Qt Quick 2D Renderer fallback for systems / environments with "low-level graphics" i.e. without 3D support
|
||||
Source: "bin\start-low-graphics-mode.bat"; DestDir: "{app}"; Flags: ignoreversion
|
||||
|
||||
; Use a scale factor of 2 for Qt for high-DPI systems, as long as Qt does not handle some such systems adequately
|
||||
Source: "bin\start-high-dpi.bat"; DestDir: "{app}"; Flags: ignoreversion
|
||||
|
||||
; Mesa, open-source OpenGL implementation; part of "low-level graphics" support
|
||||
Source: "bin\opengl32sw.dll"; DestDir: "{app}"; Flags: ignoreversion
|
||||
|
||||
@@ -170,6 +167,7 @@ Type: files; Name: "{app}\libssp-0.dll"
|
||||
Type: files; Name: "{app}\libhidapi-0.dll"
|
||||
Type: files; Name: "{app}\libeay32.dll"
|
||||
Type: files; Name: "{app}\ssleay32.dll"
|
||||
Type: files; Name: "{app}\start-high-dpi.bat"
|
||||
Type: files; Name: "{group}\Utilities\x (Check Blockchain Folder).lnk"
|
||||
|
||||
|
||||
|
||||
@@ -105,8 +105,8 @@
|
||||
<p>The Monero software and especially the GUI wallet are "work in progress", and sometimes things go wrong.</p>
|
||||
|
||||
<p>Please note that despite any technical problems that you may encounter your Moneroj are almost always safe: You may
|
||||
not be able to move them or you even may not see how many you currently have, but you most probably won't loose any.
|
||||
But do remember that the seed needed to re-create the wallet <b>is</b> critical, however: <b>Never loose your
|
||||
not be able to move them or you even may not see how many you currently have, but you most probably won't lose any.
|
||||
But do remember that the seed needed to re-create the wallet <b>is</b> critical, however: <b>Never lose your
|
||||
seed!</b></p>
|
||||
|
||||
<p>In the <i>Utilities</i> sub-folder there are several more icons that may help you to solve problems.
|
||||
|
||||
@@ -74,13 +74,29 @@ function isValidOpenAliasAddress(address) {
|
||||
return true
|
||||
}
|
||||
|
||||
function makeQRCodeString(addr, amount) {
|
||||
function makeQRCodeString(addr, amount, txDescription, recipientName) {
|
||||
var XMR_URI_SCHEME = "monero:"
|
||||
var XMR_AMOUNT = "tx_amount"
|
||||
var XMR_RECIPIENT_NAME = "recipient_name"
|
||||
var XMR_TX_DESCRIPTION = "tx_description"
|
||||
var qrCodeString =""
|
||||
qrCodeString += (XMR_URI_SCHEME + addr)
|
||||
if (amount !== undefined && amount !== ""){
|
||||
qrCodeString += ("?" + XMR_AMOUNT + "=" + amount)
|
||||
}
|
||||
if (txDescription !== undefined && txDescription !== ""){
|
||||
if (amount == ""){
|
||||
qrCodeString += ("?" + XMR_TX_DESCRIPTION + "=" + encodeURI(txDescription))
|
||||
} else {
|
||||
qrCodeString += ("&" + XMR_TX_DESCRIPTION + "=" + encodeURI(txDescription))
|
||||
}
|
||||
}
|
||||
if (recipientName !== undefined && recipientName !== ""){
|
||||
if (amount == "" && txDescription == ""){
|
||||
qrCodeString += ("?" + XMR_RECIPIENT_NAME + "=" + encodeURI(recipientName))
|
||||
} else {
|
||||
qrCodeString += ("&" + XMR_RECIPIENT_NAME + "=" + encodeURI(recipientName))
|
||||
}
|
||||
}
|
||||
return qrCodeString
|
||||
}
|
||||
|
||||
17
js/Utils.js
17
js/Utils.js
@@ -113,5 +113,20 @@ function capitalize(s){
|
||||
}
|
||||
|
||||
function removeTrailingZeros(value) {
|
||||
return (value + '').replace(/(\.\d*[1-9])0+$/, '$1');
|
||||
return (value + '').replace(/(\.\d*?)0+$/, '$1').replace(/\.$/, '');
|
||||
}
|
||||
|
||||
function parseDateStringOrRestoreHeightAsInteger(value) {
|
||||
// Parse date string or restore height as integer
|
||||
var restoreHeight = 0;
|
||||
if (value.indexOf('-') === 4 && value.length === 10) {
|
||||
restoreHeight = Wizard.getApproximateBlockchainHeight(value, Utils.netTypeToString());
|
||||
} else if (parseInt(value.substring(0, 4)) >= 2014 && parseInt(value.substring(0, 4)) <= 2025 && value.length === 8) {
|
||||
// Correct date typed in a wrong format (20201225 instead of 2020-12-25)
|
||||
var restoreHeightHyphenated = value.substring(0, 4) + "-" + value.substring(4, 6) + "-" + value.substring(6, 8);
|
||||
restoreHeight = Wizard.getApproximateBlockchainHeight(restoreHeightHyphenated, Utils.netTypeToString());
|
||||
} else {
|
||||
restoreHeight = parseInt(value);
|
||||
}
|
||||
return restoreHeight;
|
||||
}
|
||||
|
||||
18
js/Wizard.js
18
js/Wizard.js
@@ -69,10 +69,7 @@ function walletPathExists(accountsDir, directory, filename, isIOS, walletManager
|
||||
if(!filename || filename === "") return false;
|
||||
if(!directory || directory === "") return false;
|
||||
|
||||
// make sure directory endswith path seperator
|
||||
// @TODO: use .endswith() after Qt 5.8
|
||||
var trailing_path_sep = directory[directory.length-1];
|
||||
if(trailing_path_sep !== "/" && trailing_path_sep !== "\\")
|
||||
if (!directory.endsWith("/") && !directory.endsWith("\\"))
|
||||
directory += "/"
|
||||
|
||||
if(isIOS)
|
||||
@@ -85,6 +82,17 @@ function walletPathExists(accountsDir, directory, filename, isIOS, walletManager
|
||||
return false;
|
||||
}
|
||||
|
||||
function unusedWalletName(directory, filename, walletManager) {
|
||||
for (var i = 0; i < 100; i++) {
|
||||
var walletName = filename + (i > 0 ? "_" + i : "");
|
||||
if (!walletManager.walletExists(directory + "/" + walletName + "/" + walletName)) {
|
||||
return walletName;
|
||||
}
|
||||
}
|
||||
|
||||
return filename;
|
||||
}
|
||||
|
||||
function isAscii(str){
|
||||
for (var i = 0; i < str.length; i++) {
|
||||
if (str.charCodeAt(i) > 127)
|
||||
@@ -158,7 +166,7 @@ function getApproximateBlockchainHeight(_date, _nettype){
|
||||
|
||||
if(_nettype == "Testnet"){
|
||||
// testnet got some huge rollbacks, so the estimation is way off
|
||||
var approximateTestnetRolledBackBlocks = 303967;
|
||||
var approximateTestnetRolledBackBlocks = 342100;
|
||||
if(approxBlockchainHeight > approximateTestnetRolledBackBlocks)
|
||||
approxBlockchainHeight -= approximateTestnetRolledBackBlocks
|
||||
}
|
||||
|
||||
400
main.qml
400
main.qml
@@ -26,6 +26,7 @@
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import QtQml.Models 2.2
|
||||
import QtQuick 2.9
|
||||
import QtQuick.Window 2.0
|
||||
import QtQuick.Controls 1.1
|
||||
@@ -53,11 +54,15 @@ import "version.js" as Version
|
||||
|
||||
ApplicationWindow {
|
||||
id: appWindow
|
||||
title: "Monero" + (walletName ? " - " + walletName : "")
|
||||
title: "Monero" +
|
||||
(persistentSettings.displayWalletNameInTitleBar && walletName
|
||||
? " - " + walletName
|
||||
: "")
|
||||
minimumWidth: 750
|
||||
minimumHeight: 450
|
||||
|
||||
property var currentItem
|
||||
property var previousActiveFocusItem
|
||||
property bool hideBalanceForced: false
|
||||
property bool ctrlPressed: false
|
||||
property alias persistentSettings : persistentSettings
|
||||
@@ -69,7 +74,7 @@ ApplicationWindow {
|
||||
property int restoreHeight:0
|
||||
property bool daemonSynced: false
|
||||
property bool walletSynced: false
|
||||
property int maxWindowHeight: (isAndroid || isIOS)? screenHeight : (screenHeight < 900)? 720 : 800;
|
||||
property int maxWindowHeight: (isAndroid || isIOS)? screenAvailableHeight : (screenAvailableHeight < 900)? 720 : 800;
|
||||
property bool daemonRunning: !persistentSettings.useRemoteNode && !disconnected
|
||||
property int daemonStartStopInProgress: 0
|
||||
property alias toolTip: toolTip
|
||||
@@ -88,16 +93,14 @@ ApplicationWindow {
|
||||
readonly property string localDaemonAddress : "localhost:" + getDefaultDaemonRpcPort(persistentSettings.nettype)
|
||||
property string currentDaemonAddress;
|
||||
property int disconnectedEpoch: 0
|
||||
property int estimatedBlockchainSize: 75 // GB
|
||||
property int estimatedBlockchainSize: persistentSettings.pruneBlockchain ? 40 : 105 // GB
|
||||
property alias viewState: rootItem.state
|
||||
property string prevSplashText;
|
||||
property bool splashDisplayedBeforeButtonRequest;
|
||||
property int appEpoch: Math.floor((new Date).getTime() / 1000)
|
||||
property bool themeTransition: false
|
||||
|
||||
// fiat price conversion
|
||||
property real fiatPriceXMRUSD: 0
|
||||
property real fiatPriceXMREUR: 0
|
||||
property real fiatPrice: 0
|
||||
property var fiatPriceAPIs: {
|
||||
return {
|
||||
"kraken": {
|
||||
@@ -123,8 +126,6 @@ ApplicationWindow {
|
||||
property var current_address_label: "Primary"
|
||||
property int current_subaddress_table_index: 0
|
||||
|
||||
function altKeyReleased() { ctrlPressed = false; }
|
||||
|
||||
function showPageRequest(page) {
|
||||
middlePanel.state = page
|
||||
leftPanel.selectItem(page)
|
||||
@@ -140,12 +141,8 @@ ApplicationWindow {
|
||||
|
||||
if(seq === "Ctrl+S") middlePanel.state = "Transfer"
|
||||
else if(seq === "Ctrl+R") middlePanel.state = "Receive"
|
||||
else if(seq === "Ctrl+K") middlePanel.state = "TxKey"
|
||||
else if(seq === "Ctrl+H") middlePanel.state = "History"
|
||||
else if(seq === "Ctrl+B") middlePanel.state = "AddressBook"
|
||||
else if(seq === "Ctrl+M") middlePanel.state = "Mining"
|
||||
else if(seq === "Ctrl+I") middlePanel.state = "Sign"
|
||||
else if(seq === "Ctrl+G") middlePanel.state = "SharedRingDB"
|
||||
else if(seq === "Ctrl+E") middlePanel.state = "Settings"
|
||||
else if(seq === "Ctrl+D") middlePanel.state = "Advanced"
|
||||
else if(seq === "Ctrl+T") middlePanel.state = "Account"
|
||||
@@ -165,11 +162,8 @@ ApplicationWindow {
|
||||
else if(middlePanel.state === "Transfer") middlePanel.state = "AddressBook"
|
||||
else if(middlePanel.state === "AddressBook") middlePanel.state = "Receive"
|
||||
else if(middlePanel.state === "Receive") middlePanel.state = "History"
|
||||
else if(middlePanel.state === "History") middlePanel.state = "Mining"
|
||||
else if(middlePanel.state === "Mining") middlePanel.state = "TxKey"
|
||||
else if(middlePanel.state === "TxKey") middlePanel.state = "SharedRingDB"
|
||||
else if(middlePanel.state === "SharedRingDB") middlePanel.state = "Sign"
|
||||
else if(middlePanel.state === "Sign") middlePanel.state = "Settings"
|
||||
else if(middlePanel.state === "History") middlePanel.state = "Advanced"
|
||||
else if(middlePanel.state === "Advanced") middlePanel.state = "Settings"
|
||||
} else if(seq === "Ctrl+Shift+Backtab" || seq === "Alt+Shift+Backtab") {
|
||||
/*
|
||||
if(middlePanel.state === "Settings") middlePanel.state = "Sign"
|
||||
@@ -181,11 +175,8 @@ ApplicationWindow {
|
||||
else if(middlePanel.state === "TxKey") middlePanel.state = "Receive"
|
||||
else if(middlePanel.state === "Receive") middlePanel.state = "Transfer"
|
||||
*/
|
||||
if(middlePanel.state === "Settings") middlePanel.state = "Sign"
|
||||
else if(middlePanel.state === "Sign") middlePanel.state = "SharedRingDB"
|
||||
else if(middlePanel.state === "SharedRingDB") middlePanel.state = "TxKey"
|
||||
else if(middlePanel.state === "TxKey") middlePanel.state = "Mining"
|
||||
else if(middlePanel.state === "Mining") middlePanel.state = "History"
|
||||
if(middlePanel.state === "Settings") middlePanel.state = "Advanced"
|
||||
else if(middlePanel.state === "Advanced") middlePanel.state = "History"
|
||||
else if(middlePanel.state === "History") middlePanel.state = "Receive"
|
||||
else if(middlePanel.state === "Receive") middlePanel.state = "AddressBook"
|
||||
else if(middlePanel.state === "AddressBook") middlePanel.state = "Transfer"
|
||||
@@ -220,6 +211,9 @@ ApplicationWindow {
|
||||
if (prevState) {
|
||||
appWindow.viewState = prevState;
|
||||
}
|
||||
if (wizard.wizardState == "wizardOpenWallet1") {
|
||||
wizard.wizardStateView.wizardOpenWallet1View.pageRoot.forceActiveFocus();
|
||||
}
|
||||
};
|
||||
passwordDialog.open(usefulName(persistentSettings.wallet_path));
|
||||
}
|
||||
@@ -233,12 +227,6 @@ ApplicationWindow {
|
||||
else
|
||||
walletManager.setLogLevel(persistentSettings.logLevel)
|
||||
|
||||
// setup language
|
||||
var locale = persistentSettings.locale
|
||||
if (locale !== "") {
|
||||
translationManager.setLanguage(locale.split("_")[0]);
|
||||
}
|
||||
|
||||
// Reload transfer page with translations enabled
|
||||
middlePanel.transferView.onPageCompleted();
|
||||
|
||||
@@ -373,17 +361,18 @@ ApplicationWindow {
|
||||
middlePanel.getProofClicked.connect(handleGetProof);
|
||||
middlePanel.checkProofClicked.connect(handleCheckProof);
|
||||
|
||||
persistentSettings.restore_height = currentWallet.walletCreationHeight;
|
||||
|
||||
console.log("Recovering from seed: ", persistentSettings.is_recovering)
|
||||
console.log("restore Height", persistentSettings.restore_height)
|
||||
|
||||
// Use saved daemon rpc login settings
|
||||
currentWallet.setDaemonLogin(persistentSettings.daemonUsername, persistentSettings.daemonPassword)
|
||||
|
||||
if(persistentSettings.useRemoteNode)
|
||||
currentDaemonAddress = persistentSettings.remoteNodeAddress
|
||||
else
|
||||
currentDaemonAddress = localDaemonAddress
|
||||
if (persistentSettings.useRemoteNode) {
|
||||
const remoteNode = remoteNodesModel.currentRemoteNode();
|
||||
currentDaemonAddress = remoteNode.address;
|
||||
currentWallet.setDaemonLogin(remoteNode.username, remoteNode.password);
|
||||
} else {
|
||||
currentDaemonAddress = localDaemonAddress;
|
||||
}
|
||||
|
||||
console.log("initializing with daemon address: ", currentDaemonAddress)
|
||||
currentWallet.initAsync(
|
||||
@@ -400,7 +389,7 @@ ApplicationWindow {
|
||||
}
|
||||
|
||||
function isTrustedDaemon() {
|
||||
return !persistentSettings.useRemoteNode || persistentSettings.is_trusted_daemon;
|
||||
return !persistentSettings.useRemoteNode || remoteNodesModel.currentRemoteNode().trusted;
|
||||
}
|
||||
|
||||
function usefulName(path) {
|
||||
@@ -436,8 +425,8 @@ ApplicationWindow {
|
||||
leftPanel.balanceString = balance
|
||||
leftPanel.balanceUnlockedString = balanceU
|
||||
if (middlePanel.state === "Account") {
|
||||
middlePanel.accountView.balanceAllText = walletManager.displayAmount(appWindow.currentWallet.balanceAll());
|
||||
middlePanel.accountView.unlockedBalanceAllText = walletManager.displayAmount(appWindow.currentWallet.unlockedBalanceAll());
|
||||
middlePanel.accountView.balanceAllText = walletManager.displayAmount(appWindow.currentWallet.balanceAll()) + " XMR";
|
||||
middlePanel.accountView.unlockedBalanceAllText = walletManager.displayAmount(appWindow.currentWallet.unlockedBalanceAll()) + " XMR";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -502,7 +491,7 @@ ApplicationWindow {
|
||||
walletInitialized = true
|
||||
|
||||
// check if daemon was already mining and add mining logo if true
|
||||
middlePanel.miningView.update();
|
||||
middlePanel.advancedView.miningView.update();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -546,12 +535,6 @@ ApplicationWindow {
|
||||
// try to resolve common wallet cache errors automatically
|
||||
switch (wallet.errorString) {
|
||||
case "basic_string::_M_replace_aux":
|
||||
walletManager.clearWalletCache(wallet.path);
|
||||
walletPassword = passwordDialog.password;
|
||||
appWindow.initialize();
|
||||
console.error("Repairing wallet cache with error: ", wallet.errorString);
|
||||
appWindow.showStatusMessage(qsTr("Repairing incompatible wallet cache. Resyncing wallet."),6);
|
||||
return;
|
||||
case "std::bad_alloc":
|
||||
walletManager.clearWalletCache(wallet.path);
|
||||
walletPassword = passwordDialog.password;
|
||||
@@ -629,7 +612,9 @@ ApplicationWindow {
|
||||
|
||||
const callback = function() {
|
||||
persistentSettings.useRemoteNode = true;
|
||||
currentDaemonAddress = persistentSettings.remoteNodeAddress;
|
||||
const remoteNode = remoteNodesModel.currentRemoteNode();
|
||||
currentDaemonAddress = remoteNode.address;
|
||||
currentWallet.setDaemonLogin(remoteNode.username, remoteNode.password);
|
||||
currentWallet.initAsync(
|
||||
currentDaemonAddress,
|
||||
isTrustedDaemon(),
|
||||
@@ -655,6 +640,7 @@ ApplicationWindow {
|
||||
console.log("disconnecting remote node");
|
||||
persistentSettings.useRemoteNode = false;
|
||||
currentDaemonAddress = localDaemonAddress
|
||||
currentWallet.setDaemonLogin("", "");
|
||||
currentWallet.initAsync(
|
||||
currentDaemonAddress,
|
||||
isTrustedDaemon(),
|
||||
@@ -727,7 +713,7 @@ ApplicationWindow {
|
||||
|
||||
const noSync = appWindow.walletMode === 0;
|
||||
const bootstrapNodeAddress = persistentSettings.walletMode < 2 ? "auto" : persistentSettings.bootstrapNodeAddress
|
||||
daemonManager.start(flags, persistentSettings.nettype, persistentSettings.blockchainDataDir, bootstrapNodeAddress, noSync);
|
||||
daemonManager.start(flags, persistentSettings.nettype, persistentSettings.blockchainDataDir, bootstrapNodeAddress, noSync, persistentSettings.pruneBlockchain);
|
||||
}
|
||||
|
||||
function stopDaemon(callback, splash){
|
||||
@@ -823,7 +809,7 @@ ApplicationWindow {
|
||||
return false;
|
||||
}
|
||||
|
||||
function onTransactionCreated(pendingTransaction,address,paymentId,mixinCount){
|
||||
function onTransactionCreated(pendingTransaction, addresses, paymentId, mixinCount) {
|
||||
console.log("Transaction created");
|
||||
txConfirmationPopup.bottomText.text = "";
|
||||
transaction = pendingTransaction;
|
||||
@@ -855,48 +841,49 @@ ApplicationWindow {
|
||||
}
|
||||
}
|
||||
|
||||
function getDisplayAmountTotal(recipients) {
|
||||
const amounts = recipients.map(function (recipient) {
|
||||
return recipient.amount;
|
||||
});
|
||||
const total = walletManager.amountsSumFromStrings(amounts);
|
||||
return Utils.removeTrailingZeros(walletManager.displayAmount(total));
|
||||
}
|
||||
|
||||
// called on "transfer"
|
||||
function handlePayment(address, paymentId, amount, mixinCount, priority, description, createFile) {
|
||||
function handlePayment(recipients, paymentId, mixinCount, priority, description, createFile) {
|
||||
console.log("Creating transaction: ")
|
||||
console.log("\taddress: ", address,
|
||||
console.log("\trecipients: ", recipients,
|
||||
", payment_id: ", paymentId,
|
||||
", amount: ", amount,
|
||||
", mixins: ", mixinCount,
|
||||
", priority: ", priority,
|
||||
", description: ", description);
|
||||
txConfirmationPopup.bottomTextAnimation.running = false
|
||||
txConfirmationPopup.bottomText.text = qsTr("Creating transaction...") + translationManager.emptyString;
|
||||
txConfirmationPopup.transactionAddress = address;
|
||||
txConfirmationPopup.transactionAmount = Utils.removeTrailingZeros(amount);
|
||||
txConfirmationPopup.transactionPriority = priority;
|
||||
txConfirmationPopup.transactionDescription = description;
|
||||
|
||||
// validate amount;
|
||||
if (amount !== "(all)") {
|
||||
var amountxmr = walletManager.amountFromString(amount);
|
||||
console.log("integer amount: ", amountxmr);
|
||||
console.log("integer unlocked", currentWallet.unlockedBalance())
|
||||
if (amountxmr <= 0) {
|
||||
txConfirmationPopup.errorText.text = qsTr("Amount is wrong: expected number from %1 to %2")
|
||||
.arg(walletManager.displayAmount(0))
|
||||
.arg(walletManager.displayAmount(currentWallet.unlockedBalance()))
|
||||
+ translationManager.emptyString;
|
||||
return;
|
||||
} else if (amountxmr > currentWallet.unlockedBalance()) {
|
||||
txConfirmationPopup.errorText.text = qsTr("Insufficient funds. Unlocked balance: %1")
|
||||
.arg(walletManager.displayAmount(currentWallet.unlockedBalance()))
|
||||
+ translationManager.emptyString;
|
||||
return;
|
||||
}
|
||||
const recipientAll = recipients.find(function (recipient) {
|
||||
return recipient.amount == "(all)";
|
||||
});
|
||||
if (recipientAll && recipients.length > 1) {
|
||||
throw "Sending all requires one destination address";
|
||||
}
|
||||
|
||||
txConfirmationPopup.bottomTextAnimation.running = false;
|
||||
txConfirmationPopup.bottomText.text = qsTr("Creating transaction...") + translationManager.emptyString;
|
||||
txConfirmationPopup.recipients = recipients;
|
||||
txConfirmationPopup.transactionAmount = recipientAll ? "(all)" : getDisplayAmountTotal(recipients);
|
||||
txConfirmationPopup.transactionPriority = priority;
|
||||
txConfirmationPopup.transactionDescription = description;
|
||||
txConfirmationPopup.open();
|
||||
|
||||
if (amount === "(all)")
|
||||
currentWallet.createTransactionAllAsync(address, paymentId, mixinCount, priority);
|
||||
else
|
||||
currentWallet.createTransactionAsync(address, paymentId, amountxmr, mixinCount, priority);
|
||||
if (recipientAll) {
|
||||
currentWallet.createTransactionAllAsync(recipientAll.address, paymentId, mixinCount, priority);
|
||||
} else {
|
||||
const addresses = recipients.map(function (recipient) {
|
||||
return recipient.address;
|
||||
});
|
||||
const amountsxmr = recipients.map(function (recipient) {
|
||||
return recipient.amount;
|
||||
});
|
||||
currentWallet.createTransactionAsync(addresses, paymentId, amountsxmr, mixinCount, priority);
|
||||
}
|
||||
}
|
||||
|
||||
//Choose where to save transaction
|
||||
@@ -946,7 +933,7 @@ ApplicationWindow {
|
||||
// called after user confirms transaction
|
||||
function handleTransactionConfirmed(fileName) {
|
||||
// View only wallet - we save the tx
|
||||
if(viewOnly && saveTxDialog.fileUrl){
|
||||
if(viewOnly){
|
||||
// No file specified - abort
|
||||
if(!saveTxDialog.fileUrl) {
|
||||
currentWallet.disposeTransaction(transaction)
|
||||
@@ -958,10 +945,12 @@ ApplicationWindow {
|
||||
// Store to file
|
||||
transaction.setFilename(path);
|
||||
}
|
||||
appWindow.showProcessingSplash(qsTr("Sending transaction ..."));
|
||||
currentWallet.commitTransactionAsync(transaction);
|
||||
}
|
||||
|
||||
function onTransactionCommitted(success, transaction, txid) {
|
||||
hideProcessingSplash();
|
||||
if (!success) {
|
||||
console.log("Error committing transaction: " + transaction.errorString);
|
||||
informationPopup.title = qsTr("Error") + translationManager.emptyString
|
||||
@@ -989,6 +978,11 @@ ApplicationWindow {
|
||||
});
|
||||
}
|
||||
|
||||
function doSearchInHistory(searchTerm) {
|
||||
middlePanel.searchInHistory(searchTerm);
|
||||
leftPanel.selectItem(middlePanel.state)
|
||||
}
|
||||
|
||||
// called on "getProof"
|
||||
function handleGetProof(txid, address, message) {
|
||||
console.log("Getting payment proof: ")
|
||||
@@ -1011,7 +1005,6 @@ ApplicationWindow {
|
||||
}
|
||||
|
||||
function txProofComputed(txid, result){
|
||||
informationPopup.title = qsTr("Payment proof") + translationManager.emptyString;
|
||||
if (result.indexOf("error|") === 0) {
|
||||
var errorString = result.split("|")[1];
|
||||
informationPopup.text = qsTr("Couldn't generate a proof because of the following reason: \n") + errorString + translationManager.emptyString;
|
||||
@@ -1020,8 +1013,6 @@ ApplicationWindow {
|
||||
informationPopup.text = result;
|
||||
informationPopup.icon = StandardIcon.Critical;
|
||||
}
|
||||
informationPopup.onCloseCallback = null
|
||||
informationPopup.open()
|
||||
}
|
||||
|
||||
// called on "checkProof"
|
||||
@@ -1076,12 +1067,6 @@ ApplicationWindow {
|
||||
informationPopup.open()
|
||||
}
|
||||
|
||||
// blocks UI if wallet can't be opened or no connection to the daemon
|
||||
function enableUI(enable) {
|
||||
middlePanel.enabled = enable;
|
||||
leftPanel.enabled = enable;
|
||||
}
|
||||
|
||||
function showProcessingSplash(message) {
|
||||
console.log("Displaying processing splash")
|
||||
if (typeof message != 'undefined') {
|
||||
@@ -1119,19 +1104,22 @@ ApplicationWindow {
|
||||
middlePanel.addressBookView.clearFields();
|
||||
middlePanel.transferView.clearFields();
|
||||
middlePanel.receiveView.clearFields();
|
||||
middlePanel.historyView.clearFields();
|
||||
// disable timers
|
||||
userInActivityTimer.running = false;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
objectName: "appWindow"
|
||||
visible: true
|
||||
width: screenWidth > 980 ? 980 : 800
|
||||
height: screenHeight > maxWindowHeight ? maxWindowHeight : 700
|
||||
width: screenAvailableWidth > 980
|
||||
? 980
|
||||
: Math.min(screenAvailableWidth, 800)
|
||||
height: screenAvailableHeight > maxWindowHeight
|
||||
? maxWindowHeight
|
||||
: Math.min(screenAvailableHeight, 700)
|
||||
color: MoneroComponents.Style.appWindowBackgroundColor
|
||||
flags: persistentSettings.customDecorations ? Windows.flagsCustomDecorations : Windows.flags
|
||||
onWidthChanged: x -= 0
|
||||
|
||||
Timer {
|
||||
id: fiatPriceTimer
|
||||
@@ -1154,7 +1142,7 @@ ApplicationWindow {
|
||||
}
|
||||
|
||||
var key = currency === "xmreur" ? "XXMRZEUR" : "XXMRZUSD";
|
||||
var ticker = resp.result[key]["o"];
|
||||
var ticker = resp.result[key]["c"][0];
|
||||
return ticker;
|
||||
} else if(url.startsWith("https://api.coingecko.com/api/v3/")){
|
||||
var key = currency === "xmreur" ? "eur" : "usd";
|
||||
@@ -1216,10 +1204,7 @@ ApplicationWindow {
|
||||
return;
|
||||
}
|
||||
|
||||
if(persistentSettings.fiatPriceCurrency === "xmrusd")
|
||||
appWindow.fiatPriceXMRUSD = ticker;
|
||||
else if(persistentSettings.fiatPriceCurrency === "xmreur")
|
||||
appWindow.fiatPriceXMREUR = ticker;
|
||||
appWindow.fiatPrice = ticker;
|
||||
|
||||
appWindow.updateBalance();
|
||||
}
|
||||
@@ -1258,7 +1243,7 @@ ApplicationWindow {
|
||||
}
|
||||
|
||||
function fiatApiConvertToFiat(amount) {
|
||||
var ticker = persistentSettings.fiatPriceCurrency === "xmrusd" ? appWindow.fiatPriceXMRUSD : appWindow.fiatPriceXMREUR;
|
||||
const ticker = appWindow.fiatPrice;
|
||||
if(ticker <= 0){
|
||||
fiatApiError("Invalid ticker value: " + ticker);
|
||||
return "?.??";
|
||||
@@ -1266,6 +1251,15 @@ ApplicationWindow {
|
||||
return (amount * ticker).toFixed(2);
|
||||
}
|
||||
|
||||
function fiatApiConvertToXMR(amount) {
|
||||
const ticker = appWindow.fiatPrice;
|
||||
if(ticker <= 0){
|
||||
fiatApiError("Invalid ticker value: " + ticker);
|
||||
return "?.??";
|
||||
}
|
||||
return (amount / ticker).toFixed(12);
|
||||
}
|
||||
|
||||
function fiatApiUpdateBalance(balance){
|
||||
// update balance card
|
||||
var bFiat = "?.??"
|
||||
@@ -1288,8 +1282,14 @@ ApplicationWindow {
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
x = (Screen.width - width) / 2
|
||||
y = (Screen.height - maxWindowHeight) / 2
|
||||
if (screenAvailableWidth > width) {
|
||||
x = (screenAvailableWidth - width) / 2;
|
||||
}
|
||||
if (screenAvailableHeight > height) {
|
||||
y = (screenAvailableHeight - height) / 2;
|
||||
}
|
||||
|
||||
translationManager.setLanguage(persistentSettings.locale.split("_")[0]);
|
||||
|
||||
applyWalletMode(persistentSettings.walletMode);
|
||||
|
||||
@@ -1336,6 +1336,27 @@ ApplicationWindow {
|
||||
appWindow.fiatApiRefresh();
|
||||
appWindow.fiatTimerStart();
|
||||
}
|
||||
|
||||
if (persistentSettings.askDesktopShortcut && !persistentSettings.portable) {
|
||||
persistentSettings.askDesktopShortcut = false;
|
||||
|
||||
if (isTails) {
|
||||
oshelper.createDesktopEntry();
|
||||
} else if (isLinux) {
|
||||
confirmationDialog.title = qsTr("Desktop entry") + translationManager.emptyString;
|
||||
confirmationDialog.text = qsTr("Would you like to register Monero GUI Desktop entry?") + translationManager.emptyString;
|
||||
confirmationDialog.icon = StandardIcon.Question;
|
||||
confirmationDialog.cancelText = qsTr("No") + translationManager.emptyString;
|
||||
confirmationDialog.okText = qsTr("Yes") + translationManager.emptyString;
|
||||
confirmationDialog.onAcceptedCallback = function() {
|
||||
oshelper.createDesktopEntry();
|
||||
};
|
||||
confirmationDialog.onRejectedCallback = null;
|
||||
confirmationDialog.open();
|
||||
}
|
||||
}
|
||||
|
||||
remoteNodesModel.initialize();
|
||||
}
|
||||
|
||||
MoneroSettings {
|
||||
@@ -1346,44 +1367,59 @@ ApplicationWindow {
|
||||
return "";
|
||||
}
|
||||
|
||||
property string language
|
||||
property string locale
|
||||
property bool askDesktopShortcut: isLinux
|
||||
property string language: 'English (US)'
|
||||
property string language_wallet: 'English'
|
||||
property string locale: 'en_US'
|
||||
property string account_name
|
||||
property string wallet_path
|
||||
property bool allow_background_mining : false
|
||||
property bool miningIgnoreBattery : true
|
||||
property var nettype: NetworkType.MAINNET
|
||||
property int restore_height : 0
|
||||
property bool is_trusted_daemon : false
|
||||
property bool is_trusted_daemon : false // TODO: drop after v0.17.2.0 release
|
||||
property bool is_recovering : false
|
||||
property bool is_recovering_from_device : false
|
||||
property bool customDecorations : true
|
||||
property string daemonFlags
|
||||
property int logLevel: 0
|
||||
property string logCategories: ""
|
||||
property string daemonUsername: ""
|
||||
property string daemonPassword: ""
|
||||
property string daemonUsername: "" // TODO: drop after v0.17.2.0 release
|
||||
property string daemonPassword: "" // TODO: drop after v0.17.2.0 release
|
||||
property bool transferShowAdvanced: false
|
||||
property bool receiveShowAdvanced: false
|
||||
property bool historyShowAdvanced: false
|
||||
property bool historyHumanDates: true
|
||||
property string blockchainDataDir: ""
|
||||
property bool useRemoteNode: false
|
||||
property string remoteNodeAddress: ""
|
||||
property string remoteNodeAddress: "" // TODO: drop after v0.17.2.0 release
|
||||
property string remoteNodesSerialized: JSON.stringify({
|
||||
selected: 0,
|
||||
nodes: remoteNodeAddress != ""
|
||||
? [{
|
||||
address: remoteNodeAddress,
|
||||
username: daemonUsername,
|
||||
password: daemonPassword,
|
||||
trusted: is_trusted_daemon,
|
||||
}]
|
||||
: [],
|
||||
})
|
||||
property string bootstrapNodeAddress: ""
|
||||
property bool segregatePreForkOutputs: true
|
||||
property bool keyReuseMitigation2: true
|
||||
property int segregationHeight: 0
|
||||
property int kdfRounds: 1
|
||||
property bool displayWalletNameInTitleBar: true
|
||||
property bool hideBalance: false
|
||||
property bool askPasswordBeforeSending: true
|
||||
property bool lockOnUserInActivity: true
|
||||
property int walletMode: 2
|
||||
property int lockOnUserInActivityInterval: 10 // minutes
|
||||
property bool blackTheme: true
|
||||
property bool blackTheme: MoneroComponents.Style.blackTheme
|
||||
property bool checkForUpdates: true
|
||||
property bool autosave: true
|
||||
property int autosaveMinutes: 10
|
||||
property bool pruneBlockchain: false
|
||||
|
||||
property bool fiatPriceEnabled: false
|
||||
property bool fiatPriceToggle: false
|
||||
@@ -1414,6 +1450,88 @@ ApplicationWindow {
|
||||
}
|
||||
}
|
||||
|
||||
ListModel {
|
||||
id: remoteNodesModel
|
||||
|
||||
property int selected: 0
|
||||
|
||||
signal store()
|
||||
|
||||
function initialize() {
|
||||
try {
|
||||
const remoteNodes = JSON.parse(persistentSettings.remoteNodesSerialized);
|
||||
for (var index = 0; index < remoteNodes.nodes.length; ++index) {
|
||||
const remoteNode = remoteNodes.nodes[index];
|
||||
remoteNodesModel.append(remoteNode);
|
||||
}
|
||||
selected = remoteNodes.selected % remoteNodesModel.count || 0;
|
||||
} catch (e) {
|
||||
console.error('failed to parse remoteNodesSerialized', e);
|
||||
}
|
||||
|
||||
store.connect(function() {
|
||||
var remoteNodes = [];
|
||||
for (var index = 0; index < remoteNodesModel.count; ++index) {
|
||||
remoteNodes.push(remoteNodesModel.get(index));
|
||||
}
|
||||
persistentSettings.remoteNodesSerialized = JSON.stringify({
|
||||
selected: selected,
|
||||
nodes: remoteNodes
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function appendIfNotExists(newRemoteNode) {
|
||||
for (var index = 0; index < remoteNodesModel.count; ++index) {
|
||||
const remoteNode = remoteNodesModel.get(index);
|
||||
if (remoteNode.address == newRemoteNode.address &&
|
||||
remoteNode.username == newRemoteNode.username &&
|
||||
remoteNode.password == newRemoteNode.password &&
|
||||
remoteNode.trusted == newRemoteNode.trusted) {
|
||||
return index;
|
||||
}
|
||||
}
|
||||
remoteNodesModel.append(newRemoteNode);
|
||||
return remoteNodesModel.count - 1;
|
||||
}
|
||||
|
||||
function applyRemoteNode(index) {
|
||||
selected = index;
|
||||
const remoteNode = currentRemoteNode();
|
||||
persistentSettings.useRemoteNode = true;
|
||||
if (currentWallet) {
|
||||
currentWallet.setDaemonLogin(remoteNode.username, remoteNode.password);
|
||||
currentWallet.setTrustedDaemon(remoteNode.trusted);
|
||||
appWindow.connectRemoteNode();
|
||||
}
|
||||
}
|
||||
|
||||
function currentRemoteNode() {
|
||||
if (selected < remoteNodesModel.count) {
|
||||
return remoteNodesModel.get(selected);
|
||||
}
|
||||
return {
|
||||
address: "",
|
||||
username: "",
|
||||
password: "",
|
||||
trusted: false,
|
||||
};
|
||||
}
|
||||
|
||||
function removeSelectNextIfNeeded(index) {
|
||||
remoteNodesModel.remove(index);
|
||||
if (selected == index) {
|
||||
applyRemoteNode(selected % remoteNodesModel.count || 0);
|
||||
} else if (selected > index) {
|
||||
selected = selected - 1;
|
||||
}
|
||||
}
|
||||
|
||||
onCountChanged: store()
|
||||
onDataChanged: store()
|
||||
onSelectedChanged: store()
|
||||
}
|
||||
|
||||
// Information dialog
|
||||
StandardDialog {
|
||||
// dynamically change onclose handler
|
||||
@@ -1494,6 +1612,10 @@ ApplicationWindow {
|
||||
y: (parent.height - height) / 2
|
||||
}
|
||||
|
||||
MoneroComponents.RemoteNodeDialog {
|
||||
id: remoteNodeDialog
|
||||
}
|
||||
|
||||
// Choose blockchain folder
|
||||
FileDialog {
|
||||
id: blockchainFileDialog
|
||||
@@ -1665,18 +1787,6 @@ ApplicationWindow {
|
||||
updateBalance();
|
||||
}
|
||||
|
||||
onTxkeyClicked: {
|
||||
middlePanel.state = "TxKey";
|
||||
middlePanel.flickable.contentY = 0;
|
||||
updateBalance();
|
||||
}
|
||||
|
||||
onSharedringdbClicked: {
|
||||
middlePanel.state = "SharedRingDB";
|
||||
middlePanel.flickable.contentY = 0;
|
||||
updateBalance();
|
||||
}
|
||||
|
||||
onHistoryClicked: {
|
||||
middlePanel.state = "History";
|
||||
middlePanel.flickable.contentY = 0;
|
||||
@@ -1689,14 +1799,8 @@ ApplicationWindow {
|
||||
updateBalance();
|
||||
}
|
||||
|
||||
onMiningClicked: {
|
||||
middlePanel.state = "Mining";
|
||||
middlePanel.flickable.contentY = 0;
|
||||
updateBalance();
|
||||
}
|
||||
|
||||
onSignClicked: {
|
||||
middlePanel.state = "Sign";
|
||||
onAdvancedClicked: {
|
||||
middlePanel.state = "Advanced";
|
||||
middlePanel.flickable.contentY = 0;
|
||||
updateBalance();
|
||||
}
|
||||
@@ -1739,7 +1843,9 @@ ApplicationWindow {
|
||||
anchors.fill: blurredArea
|
||||
source: blurredArea
|
||||
radius: 64
|
||||
visible: passwordDialog.visible || inputDialog.visible || splash.visible || updateDialog.visible || devicePassphraseDialog.visible || txConfirmationPopup.visible || successfulTxPopup.visible
|
||||
visible: passwordDialog.visible || inputDialog.visible || splash.visible || updateDialog.visible ||
|
||||
devicePassphraseDialog.visible || txConfirmationPopup.visible || successfulTxPopup.visible ||
|
||||
remoteNodeDialog.visible
|
||||
}
|
||||
|
||||
|
||||
@@ -1792,7 +1898,7 @@ ApplicationWindow {
|
||||
TitleBar {
|
||||
id: titleBar
|
||||
visible: persistentSettings.customDecorations && middlePanel.state !== "Merchant"
|
||||
walletName: appWindow.walletName
|
||||
walletName: persistentSettings.displayWalletNameInTitleBar ? appWindow.walletName : ""
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
onCloseClicked: appWindow.close();
|
||||
@@ -1843,13 +1949,9 @@ ApplicationWindow {
|
||||
}
|
||||
|
||||
function toggleLanguageView(){
|
||||
languageSidebar.isOpened ? languageSidebar.close() : languageSidebar.open();
|
||||
languageSidebar.visible ? languageSidebar.close() : languageSidebar.open();
|
||||
languageSidebar.selectCurrentLanguage()
|
||||
resetLanguageFields()
|
||||
// update after changing language from settings page
|
||||
if (persistentSettings.language != wizard.language_language) {
|
||||
persistentSettings.language = wizard.language_language
|
||||
persistentSettings.locale = wizard.language_locale
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
@@ -1924,12 +2026,13 @@ ApplicationWindow {
|
||||
return;
|
||||
}
|
||||
|
||||
const simpleModeFlags = "--enable-dns-blocklist --out-peers 16";
|
||||
if (appWindow.daemonRunning) {
|
||||
appWindow.stopDaemon(function() {
|
||||
appWindow.startDaemon("")
|
||||
appWindow.startDaemon(simpleModeFlags)
|
||||
});
|
||||
} else {
|
||||
appWindow.startDaemon("");
|
||||
appWindow.startDaemon(simpleModeFlags);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2107,8 +2210,7 @@ ApplicationWindow {
|
||||
|
||||
function userActivity() {
|
||||
// register user activity
|
||||
var epoch = Math.floor((new Date).getTime()/1000);
|
||||
appWindow.userLastActive = epoch;
|
||||
appWindow.userLastActive = Utils.epoch();
|
||||
}
|
||||
|
||||
function checkInUserActivity() {
|
||||
@@ -2116,23 +2218,32 @@ ApplicationWindow {
|
||||
if(!persistentSettings.lockOnUserInActivity) return;
|
||||
if(passwordDialog.visible) return;
|
||||
var inputDialogVisible = inputDialog && inputDialog.visible
|
||||
var successfulTxPopupVisible = successfulTxPopup && successfulTxPopup.visible
|
||||
var informationPopupVisible = informationPopup && informationPopup.visible
|
||||
|
||||
// prompt password after X seconds of inactivity
|
||||
var epoch = Math.floor((new Date).getTime() / 1000);
|
||||
var inactivity = epoch - appWindow.userLastActive;
|
||||
var inactivity = Utils.epoch() - appWindow.userLastActive;
|
||||
if(inactivity < (persistentSettings.lockOnUserInActivityInterval * 60)) return;
|
||||
|
||||
passwordDialog.onAcceptedCallback = function() {
|
||||
if(walletPassword === passwordDialog.password){
|
||||
passwordDialog.close();
|
||||
if (inputDialogVisible) inputDialog.open(inputDialog.inputText)
|
||||
if (successfulTxPopupVisible) successfulTxPopup.open(successfulTxPopup.transactionID)
|
||||
if (informationPopupVisible) informationPopup.open()
|
||||
} else {
|
||||
passwordDialog.showError(qsTr("Wrong password"));
|
||||
}
|
||||
if (inputDialogVisible) inputDialog.open(inputDialog.inputText)
|
||||
}
|
||||
|
||||
passwordDialog.onRejectedCallback = function() { appWindow.showWizard(); }
|
||||
if (inputDialogVisible) inputDialog.close()
|
||||
remoteNodeDialog.close();
|
||||
informationPopup.close()
|
||||
txConfirmationPopup.close()
|
||||
txConfirmationPopup.clearFields()
|
||||
txConfirmationPopup.rejected()
|
||||
successfulTxPopup.close();
|
||||
passwordDialog.open();
|
||||
}
|
||||
|
||||
@@ -2149,7 +2260,6 @@ ApplicationWindow {
|
||||
|
||||
function changeWalletMode(mode){
|
||||
appWindow.disconnectedEpoch = 0;
|
||||
appWindow.walletMode = mode;
|
||||
persistentSettings.walletMode = mode;
|
||||
applyWalletMode(mode);
|
||||
}
|
||||
@@ -2253,8 +2363,12 @@ ApplicationWindow {
|
||||
MoneroComponents.LanguageSidebar {
|
||||
id: languageSidebar
|
||||
dragMargin: 0
|
||||
onAboutToShow: previousActiveFocusItem = activeFocusItem;
|
||||
onClosed: { if (previousActiveFocusItem) previousActiveFocusItem.forceActiveFocus() }
|
||||
}
|
||||
|
||||
MoneroComponents.MenuBar { }
|
||||
|
||||
Network {
|
||||
id: network
|
||||
proxyAddress: persistentSettings.getProxyAddress()
|
||||
|
||||
2
monero
2
monero
Submodule monero updated: f690e4984d...2222bea92f
@@ -103,6 +103,7 @@ Rectangle {
|
||||
|
||||
MoneroComponents.TextPlain {
|
||||
id: balanceAll
|
||||
Layout.rightMargin: 87
|
||||
font.family: MoneroComponents.Style.fontMonoRegular.name;
|
||||
font.pixelSize: 16
|
||||
color: MoneroComponents.Style.defaultFontColor
|
||||
@@ -115,7 +116,8 @@ Rectangle {
|
||||
onExited: parent.color = MoneroComponents.Style.defaultFontColor
|
||||
onClicked: {
|
||||
console.log("Copied to clipboard");
|
||||
clipboard.setText(parent.text);
|
||||
var balanceAllNumberOnly = parent.text.slice(0, -4);
|
||||
clipboard.setText(balanceAllNumberOnly);
|
||||
appWindow.showStatusMessage(qsTr("Copied to clipboard"),3)
|
||||
}
|
||||
}
|
||||
@@ -136,6 +138,7 @@ Rectangle {
|
||||
|
||||
MoneroComponents.TextPlain {
|
||||
id: unlockedBalanceAll
|
||||
Layout.rightMargin: 87
|
||||
font.family: MoneroComponents.Style.fontMonoRegular.name;
|
||||
font.pixelSize: 16
|
||||
color: MoneroComponents.Style.defaultFontColor
|
||||
@@ -148,7 +151,8 @@ Rectangle {
|
||||
onExited: parent.color = MoneroComponents.Style.defaultFontColor
|
||||
onClicked: {
|
||||
console.log("Copied to clipboard");
|
||||
clipboard.setText(parent.text);
|
||||
var unlockedBalanceAllNumberOnly = parent.text.slice(0, -4);
|
||||
clipboard.setText(unlockedBalanceAllNumberOnly);
|
||||
appWindow.showStatusMessage(qsTr("Copied to clipboard"),3)
|
||||
}
|
||||
}
|
||||
@@ -190,7 +194,16 @@ Rectangle {
|
||||
height: subaddressAccountListRow.subaddressAccountListItemHeight
|
||||
width: parent ? parent.width : undefined
|
||||
Layout.fillWidth: true
|
||||
color: "transparent"
|
||||
color: itemMouseArea.containsMouse || index === currentAccountIndex ? MoneroComponents.Style.titleBarButtonHoverColor : "transparent"
|
||||
|
||||
Rectangle {
|
||||
visible: index === currentAccountIndex
|
||||
Layout.fillHeight: true
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
color: "darkgrey"
|
||||
width: 2
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
color: MoneroComponents.Style.appWindowBorderColor
|
||||
@@ -226,7 +239,7 @@ Rectangle {
|
||||
|
||||
MoneroComponents.Label {
|
||||
id: nameLabel
|
||||
color: MoneroComponents.Style.dimmedFontColor
|
||||
color: index === currentAccountIndex ? MoneroComponents.Style.defaultFontColor : MoneroComponents.Style.dimmedFontColor
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: idLabel.right
|
||||
anchors.leftMargin: 6
|
||||
@@ -241,7 +254,7 @@ Rectangle {
|
||||
id: addressLabel
|
||||
color: MoneroComponents.Style.defaultFontColor
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: mainLayout.width >= 590 ? balanceTextLabel.left : balanceNumberLabel.left
|
||||
anchors.left: balanceNumberLabel.left
|
||||
anchors.leftMargin: -addressLabel.width - 30
|
||||
fontSize: 16
|
||||
fontFamily: MoneroComponents.Style.fontMonoRegular.name;
|
||||
@@ -249,18 +262,6 @@ Rectangle {
|
||||
themeTransition: false
|
||||
}
|
||||
|
||||
MoneroComponents.Label {
|
||||
id: balanceTextLabel
|
||||
visible: mainLayout.width >= 590
|
||||
color: MoneroComponents.Style.defaultFontColor
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: balanceNumberLabel.left
|
||||
anchors.leftMargin: -balanceTextLabel.width - 5
|
||||
fontSize: 16
|
||||
text: qsTr("Balance: ") + translationManager.emptyString
|
||||
themeTransition: false
|
||||
}
|
||||
|
||||
MoneroComponents.Label {
|
||||
id: balanceNumberLabel
|
||||
color: MoneroComponents.Style.defaultFontColor
|
||||
@@ -269,18 +270,17 @@ Rectangle {
|
||||
anchors.leftMargin: -balanceNumberLabel.width
|
||||
fontSize: 16
|
||||
fontFamily: MoneroComponents.Style.fontMonoRegular.name;
|
||||
text: balance
|
||||
text: balance + " XMR"
|
||||
elide: Text.ElideRight
|
||||
textWidth: mainLayout.width < 660 ? 70 : 135
|
||||
textWidth: 180
|
||||
themeTransition: false
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: itemMouseArea
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
onEntered: tableItem2.color = MoneroComponents.Style.titleBarButtonHoverColor
|
||||
onExited: tableItem2.color = "transparent"
|
||||
onClicked: {
|
||||
appWindow.currentWallet.switchSubaddressAccount(index);
|
||||
if (selectAndSend)
|
||||
@@ -299,10 +299,14 @@ Rectangle {
|
||||
MoneroComponents.IconButton {
|
||||
id: renameButton
|
||||
image: "qrc:///images/edit.svg"
|
||||
fontAwesomeFallbackIcon: FontAwesome.edit
|
||||
fontAwesomeFallbackSize: 22
|
||||
color: MoneroComponents.Style.defaultFontColor
|
||||
opacity: 0.5
|
||||
opacity: isOpenGL ? 0.5 : 1
|
||||
fontAwesomeFallbackOpacity: 0.5
|
||||
Layout.preferredWidth: 23
|
||||
Layout.preferredHeight: 21
|
||||
tooltip: qsTr("Edit account label") + translationManager.emptyString
|
||||
|
||||
onClicked: pageAccount.renameSubaddressAccountLabel(index);
|
||||
}
|
||||
@@ -310,10 +314,14 @@ Rectangle {
|
||||
MoneroComponents.IconButton {
|
||||
id: copyButton
|
||||
image: "qrc:///images/copy.svg"
|
||||
fontAwesomeFallbackIcon: FontAwesome.clipboard
|
||||
fontAwesomeFallbackSize: 22
|
||||
color: MoneroComponents.Style.defaultFontColor
|
||||
opacity: 0.5
|
||||
opacity: isOpenGL ? 0.5 : 1
|
||||
fontAwesomeFallbackOpacity: 0.5
|
||||
Layout.preferredWidth: 16
|
||||
Layout.preferredHeight: 21
|
||||
tooltip: qsTr("Copy address to clipboard") + translationManager.emptyString
|
||||
|
||||
onClicked: {
|
||||
console.log("Address copied to clipboard");
|
||||
@@ -375,8 +383,8 @@ Rectangle {
|
||||
subaddressAccountListView.model = appWindow.currentWallet.subaddressAccountModel;
|
||||
appWindow.currentWallet.subaddress.refresh(appWindow.currentWallet.currentSubaddressAccount)
|
||||
|
||||
balanceAll.text = walletManager.displayAmount(appWindow.currentWallet.balanceAll())
|
||||
unlockedBalanceAll.text = walletManager.displayAmount(appWindow.currentWallet.unlockedBalanceAll())
|
||||
balanceAll.text = walletManager.displayAmount(appWindow.currentWallet.balanceAll()) + " XMR"
|
||||
unlockedBalanceAll.text = walletManager.displayAmount(appWindow.currentWallet.unlockedBalanceAll()) + " XMR"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -132,13 +132,13 @@ Rectangle {
|
||||
delegate: Rectangle {
|
||||
id: tableItem2
|
||||
height: addressBookListRow.addressBookListItemHeight
|
||||
width: parent.width
|
||||
width: parent ? parent.width : undefined
|
||||
Layout.fillWidth: true
|
||||
color: "transparent"
|
||||
color: itemMouseArea.containsMouse ? MoneroComponents.Style.titleBarButtonHoverColor : "transparent"
|
||||
|
||||
function doSend() {
|
||||
console.log("Sending to: ", address +" "+ paymentId);
|
||||
middlePanel.sendTo(address, paymentId, description);
|
||||
middlePanel.sendTo(address, paymentId);
|
||||
leftPanel.selectItem(middlePanel.state)
|
||||
}
|
||||
|
||||
@@ -159,7 +159,7 @@ Rectangle {
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
anchors.topMargin: 5
|
||||
anchors.rightMargin: 110
|
||||
anchors.rightMargin: 125
|
||||
color: "transparent"
|
||||
|
||||
MoneroComponents.Label {
|
||||
@@ -187,8 +187,10 @@ Rectangle {
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: itemMouseArea
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
hoverEnabled: true
|
||||
visible: root.selectAndSend
|
||||
onClicked: {
|
||||
doSend();
|
||||
@@ -207,21 +209,42 @@ Rectangle {
|
||||
id: sendToButton
|
||||
image: "qrc:///images/arrow-right-in-circle-outline-medium-white.svg"
|
||||
color: MoneroComponents.Style.defaultFontColor
|
||||
opacity: 0.5
|
||||
opacity: isOpenGL ? 0.5 : 1
|
||||
fontAwesomeFallbackIcon: FontAwesome.arrowRight
|
||||
fontAwesomeFallbackSize: 22
|
||||
fontAwesomeFallbackOpacity: 0.5
|
||||
Layout.preferredWidth: 20
|
||||
Layout.preferredHeight: 20
|
||||
tooltip: qsTr("Send to this address") + translationManager.emptyString
|
||||
|
||||
onClicked: {
|
||||
doSend();
|
||||
}
|
||||
}
|
||||
|
||||
MoneroComponents.IconButton {
|
||||
fontAwesomeFallbackIcon: FontAwesome.searchPlus
|
||||
fontAwesomeFallbackSize: 22
|
||||
color: MoneroComponents.Style.defaultFontColor
|
||||
fontAwesomeFallbackOpacity: 0.5
|
||||
Layout.preferredWidth: 23
|
||||
Layout.preferredHeight: 21
|
||||
tooltip: qsTr("See transactions") + translationManager.emptyString
|
||||
|
||||
onClicked: doSearchInHistory(address)
|
||||
}
|
||||
|
||||
MoneroComponents.IconButton {
|
||||
id: renameButton
|
||||
image: "qrc:///images/edit.svg"
|
||||
color: MoneroComponents.Style.defaultFontColor
|
||||
opacity: 0.5
|
||||
opacity: isOpenGL ? 0.5 : 1
|
||||
fontAwesomeFallbackIcon: FontAwesome.edit
|
||||
fontAwesomeFallbackSize: 22
|
||||
fontAwesomeFallbackOpacity: 0.5
|
||||
Layout.preferredWidth: 23
|
||||
Layout.preferredHeight: 21
|
||||
tooltip: qsTr("Edit address label") + translationManager.emptyString
|
||||
|
||||
onClicked: {
|
||||
addressBookListView.currentIndex = index;
|
||||
@@ -232,10 +255,14 @@ Rectangle {
|
||||
MoneroComponents.IconButton {
|
||||
id: copyButton
|
||||
image: "qrc:///images/copy.svg"
|
||||
color: MoneroComponents.Style.defaultFontColor
|
||||
opacity: isOpenGL ? 0.5 : 1
|
||||
fontAwesomeFallbackIcon: FontAwesome.clipboard
|
||||
fontAwesomeFallbackSize: 22
|
||||
fontAwesomeFallbackOpacity: 0.5
|
||||
Layout.preferredWidth: 16
|
||||
Layout.preferredHeight: 21
|
||||
color: MoneroComponents.Style.defaultFontColor
|
||||
opacity: 0.5
|
||||
tooltip: qsTr("Copy address to clipboard") + translationManager.emptyString
|
||||
|
||||
onClicked: {
|
||||
console.log("Address copied to clipboard");
|
||||
@@ -292,6 +319,8 @@ Rectangle {
|
||||
MoneroComponents.LineEditMulti {
|
||||
id: addressLine
|
||||
Layout.topMargin: 20
|
||||
KeyNavigation.backtab: deleteButton.visible ? deleteButton: cancelButton
|
||||
KeyNavigation.tab: resolveButton.visible ? resolveButton : descriptionLine
|
||||
labelText: "<style type='text/css'>a {text-decoration: none; color: #858585; font-size: 14px;}</style> %1"
|
||||
.arg(qsTr("Address")) + translationManager.emptyString
|
||||
placeholderText: {
|
||||
@@ -313,21 +342,48 @@ Rectangle {
|
||||
descriptionLine.text = parsed.tx_description;
|
||||
}
|
||||
}
|
||||
onEnterPressed: addButton.enabled ? addButton.clicked() : ""
|
||||
onReturnPressed: addButton.enabled ? addButton.clicked() : ""
|
||||
|
||||
inlineButton.text: FontAwesome.qrcode
|
||||
inlineButton.fontPixelSize: 22
|
||||
inlineButton.fontFamily: FontAwesome.fontFamily
|
||||
inlineButton.textColor: MoneroComponents.Style.defaultFontColor
|
||||
inlineButton.buttonColor: MoneroComponents.Style.orange
|
||||
inlineButton.onClicked: {
|
||||
cameraUi.state = "Capture"
|
||||
cameraUi.qrcode_decoded.connect(root.updateFromQrCode)
|
||||
MoneroComponents.InlineButton {
|
||||
fontFamily: FontAwesome.fontFamilySolid
|
||||
fontStyleName: "Solid"
|
||||
fontPixelSize: 18
|
||||
text: FontAwesome.desktop
|
||||
tooltip: qsTr("Grab QR code from screen") + translationManager.emptyString
|
||||
onClicked: {
|
||||
clearFields();
|
||||
const codes = oshelper.grabQrCodesFromScreen();
|
||||
for (var index = 0; index < codes.length; ++index) {
|
||||
const parsed = walletManager.parse_uri_to_object(codes[index]);
|
||||
if (!parsed.error) {
|
||||
addressLine.text = parsed.address
|
||||
descriptionLine.text = parsed.recipient_name
|
||||
break;
|
||||
} else if (walletManager.addressValid(codes[index], appWindow.persistentSettings.nettype)) {
|
||||
addressLine.text = codes[index];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MoneroComponents.InlineButton {
|
||||
buttonColor: MoneroComponents.Style.orange
|
||||
fontFamily: FontAwesome.fontFamily
|
||||
text: FontAwesome.qrcode
|
||||
visible : appWindow.qrScannerEnabled && !addressLine.text
|
||||
onClicked: {
|
||||
cameraUi.state = "Capture"
|
||||
cameraUi.qrcode_decoded.connect(root.updateFromQrCode)
|
||||
}
|
||||
}
|
||||
inlineButtonVisible : appWindow.qrScannerEnabled && !addressLine.text
|
||||
}
|
||||
|
||||
MoneroComponents.StandardButton {
|
||||
id: resolveButton
|
||||
KeyNavigation.backtab: addressLine
|
||||
KeyNavigation.tab: descriptionLine
|
||||
Layout.topMargin: 10
|
||||
text: qsTr("Resolve") + translationManager.emptyString
|
||||
visible: TxUtils.isValidOpenAliasAddress(addressLine.text)
|
||||
@@ -365,17 +421,25 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
|
||||
MoneroComponents.LineEditMulti {
|
||||
MoneroComponents.LineEdit {
|
||||
id: descriptionLine
|
||||
KeyNavigation.backtab: resolveButton.visible ? resolveButton : addressLine
|
||||
KeyNavigation.tab: addButton.enabled ? addButton : cancelButton
|
||||
Layout.topMargin: 20
|
||||
Layout.fillWidth: true
|
||||
fontSize: 16
|
||||
placeholderFontSize: 16
|
||||
labelText: "<style type='text/css'>a {text-decoration: none; color: #858585; font-size: 14px;}</style> %1"
|
||||
.arg(qsTr("Description")) + translationManager.emptyString
|
||||
placeholderText: qsTr("Add a name...") + translationManager.emptyString
|
||||
onAccepted: addButton.enabled ? addButton.clicked() : ""
|
||||
}
|
||||
RowLayout {
|
||||
Layout.topMargin: 20
|
||||
MoneroComponents.StandardButton {
|
||||
id: addButton
|
||||
KeyNavigation.backtab: descriptionLine
|
||||
KeyNavigation.tab: cancelButton
|
||||
text: (root.editEntry ? qsTr("Save") : qsTr("Add")) + translationManager.emptyString
|
||||
enabled: root.checkInformation(addressLine.text, appWindow.persistentSettings.nettype)
|
||||
onClicked: {
|
||||
@@ -401,39 +465,25 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
MoneroComponents.StandardButton {
|
||||
id: cancelButton
|
||||
Layout.leftMargin: 20
|
||||
font.pixelSize: 16
|
||||
font.bold: false
|
||||
color: MoneroComponents.Style.defaultFontColor
|
||||
KeyNavigation.backtab: addButton
|
||||
KeyNavigation.tab: deleteButton.visible ? deleteButton : addressLine
|
||||
text: qsTr("Cancel") + translationManager.emptyString
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: root.showAddressBook();
|
||||
}
|
||||
primary: false
|
||||
onClicked: root.showAddressBook();
|
||||
}
|
||||
|
||||
Text {
|
||||
MoneroComponents.StandardButton {
|
||||
id: deleteButton
|
||||
KeyNavigation.backtab: cancelButton
|
||||
KeyNavigation.tab: addressLine
|
||||
visible: root.editEntry
|
||||
Layout.leftMargin: 20
|
||||
font.pixelSize: 16
|
||||
font.bold: false
|
||||
color: MoneroComponents.Style.defaultFontColor
|
||||
text: qsTr("Delete") + translationManager.emptyString
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
currentWallet.addressBook.deleteRow(addressBookListView.currentIndex);
|
||||
root.showAddressBook();
|
||||
}
|
||||
primary: false
|
||||
onClicked: {
|
||||
currentWallet.addressBook.deleteRow(addressBookListView.currentIndex);
|
||||
root.showAddressBook();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -464,6 +514,7 @@ Rectangle {
|
||||
addressBookEmptyLayout.visible = false
|
||||
addressBookLayout.visible = false;
|
||||
addContactLayout.visible = true;
|
||||
addressLine.forceActiveFocus();
|
||||
}
|
||||
|
||||
function showEditAddress(address, description) {
|
||||
@@ -474,12 +525,14 @@ Rectangle {
|
||||
addContactLayout.visible = true;
|
||||
addressLine.text = address;
|
||||
descriptionLine.text = description;
|
||||
addressLine.forceActiveFocus();
|
||||
addressLine.cursorPosition = addressLine.text.length;
|
||||
}
|
||||
|
||||
function updateFromQrCode(address, payment_id, amount, tx_description, recipient_name) {
|
||||
console.log("updateFromQrCode")
|
||||
addressLine.text = address
|
||||
descriptionLine.text = recipient_name + " " + tx_description
|
||||
descriptionLine.text = recipient_name
|
||||
cameraUi.qrcode_decoded.disconnect(updateFromQrCode)
|
||||
}
|
||||
|
||||
|
||||
148
pages/Advanced.qml
Normal file
148
pages/Advanced.qml
Normal file
@@ -0,0 +1,148 @@
|
||||
// Copyright (c) 2021, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import QtQuick 2.9
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Controls.Styles 1.4
|
||||
import QtQuick.Layouts 1.1
|
||||
import "../components" as MoneroComponents
|
||||
import "."
|
||||
|
||||
ColumnLayout {
|
||||
id: root
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 900
|
||||
spacing: 0
|
||||
property int panelHeight: 900
|
||||
property alias miningView: stateView.miningView
|
||||
property alias state: stateView.state
|
||||
|
||||
MoneroComponents.Navbar {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.topMargin: height
|
||||
Layout.bottomMargin: height
|
||||
|
||||
MoneroComponents.NavbarItem {
|
||||
active: state == "Mining"
|
||||
text: qsTr("Mining") + translationManager.emptyString
|
||||
onSelected: state = "Mining"
|
||||
}
|
||||
MoneroComponents.NavbarItem {
|
||||
active: state == "Prove"
|
||||
text: qsTr("Prove/check") + translationManager.emptyString
|
||||
onSelected: state = "Prove"
|
||||
}
|
||||
MoneroComponents.NavbarItem {
|
||||
active: state == "SharedRingDB"
|
||||
text: qsTr("Shared RingDB") + translationManager.emptyString
|
||||
onSelected: state = "SharedRingDB"
|
||||
}
|
||||
MoneroComponents.NavbarItem {
|
||||
active: state == "Sign"
|
||||
text: qsTr("Sign/verify") + translationManager.emptyString
|
||||
onSelected: state = "Sign"
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle{
|
||||
id: stateView
|
||||
property Item currentView
|
||||
property Item previousView
|
||||
property Mining miningView: Mining { }
|
||||
property TxKey prooveView: TxKey { }
|
||||
property SharedRingDB sharedRingDBView: SharedRingDB { }
|
||||
property Sign signView: Sign { }
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: panelHeight
|
||||
color: "transparent"
|
||||
state: "Mining"
|
||||
|
||||
onCurrentViewChanged: {
|
||||
if (previousView) {
|
||||
if (typeof previousView.onPageClosed === "function") {
|
||||
previousView.onPageClosed();
|
||||
}
|
||||
}
|
||||
previousView = currentView
|
||||
if (currentView) {
|
||||
stackView.replace(currentView)
|
||||
if (typeof currentView.onPageCompleted === "function") {
|
||||
currentView.onPageCompleted();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
states: [
|
||||
State {
|
||||
name: "Mining"
|
||||
PropertyChanges { target: stateView; currentView: stateView.miningView }
|
||||
PropertyChanges { target: root; panelHeight: stateView.miningView.miningHeight + 140 }
|
||||
}, State {
|
||||
name: "Prove"
|
||||
PropertyChanges { target: stateView; currentView: stateView.prooveView }
|
||||
PropertyChanges { target: root; panelHeight: stateView.prooveView.txkeyHeight + 140 }
|
||||
}, State {
|
||||
name: "SharedRingDB"
|
||||
PropertyChanges { target: stateView; currentView: stateView.sharedRingDBView }
|
||||
PropertyChanges { target: root; panelHeight: stateView.sharedRingDBView.panelHeight + 140 }
|
||||
}, State {
|
||||
name: "Sign"
|
||||
PropertyChanges { target: stateView; currentView: stateView.signView }
|
||||
PropertyChanges { target: root; panelHeight: stateView.signView.signHeight + 140 }
|
||||
}
|
||||
]
|
||||
|
||||
StackView {
|
||||
id: stackView
|
||||
initialItem: stateView.miningView
|
||||
anchors.fill: parent
|
||||
clip: false // otherwise animation will affect left panel
|
||||
|
||||
delegate: StackViewDelegate {
|
||||
pushTransition: StackViewTransition {
|
||||
PropertyAnimation {
|
||||
target: enterItem
|
||||
property: "x"
|
||||
from: 0 - target.width
|
||||
to: 0
|
||||
duration: 300
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
PropertyAnimation {
|
||||
target: exitItem
|
||||
property: "x"
|
||||
from: 0
|
||||
to: target.width
|
||||
duration: 300
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -127,7 +127,7 @@ Rectangle {
|
||||
image: "qrc:///images/whiteDropIndicator.png"
|
||||
fontAwesomeFallbackIcon: FontAwesome.arrowDown
|
||||
fontAwesomeFallbackSize: 14
|
||||
rotation: sortAndFilter.collapsed ? 0 : 180
|
||||
rotation: sortAndFilter.collapsed ? 180 : 0
|
||||
color: MoneroComponents.Style.defaultFontColor
|
||||
|
||||
MouseArea {
|
||||
@@ -154,12 +154,15 @@ Rectangle {
|
||||
Layout.fillWidth: true
|
||||
input.topPadding: 6
|
||||
input.bottomPadding: 6
|
||||
fontSize: 16
|
||||
fontSize: 15
|
||||
labelFontSize: 14
|
||||
placeholderText: qsTr("Search by Transaction ID, Address, Description, Amount or Blockheight") + translationManager.emptyString
|
||||
placeholderFontSize: 16
|
||||
placeholderFontSize: 15
|
||||
inputHeight: 34
|
||||
onTextUpdated: {
|
||||
if (!sortAndFilter.collapsed) {
|
||||
sortAndFilter.collapsed = true;
|
||||
}
|
||||
if(searchInput.text != null && searchInput.text.length >= 3){
|
||||
root.sortSearchString = searchInput.text;
|
||||
root.reset();
|
||||
@@ -170,6 +173,27 @@ Rectangle {
|
||||
root.updateFilter();
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
color: "transparent"
|
||||
height: cleanButton.height
|
||||
width: cleanButton.width
|
||||
Layout.rightMargin: -8
|
||||
Layout.leftMargin: -2
|
||||
|
||||
MoneroComponents.InlineButton {
|
||||
id: cleanButton
|
||||
buttonColor: "transparent"
|
||||
fontFamily: FontAwesome.fontFamilySolid
|
||||
fontStyleName: "Solid"
|
||||
fontPixelSize: 18
|
||||
text: FontAwesome.times
|
||||
tooltip: qsTr("Clean") + translationManager.emptyString
|
||||
tooltipLeft: true
|
||||
visible: searchInput.text != ""
|
||||
onClicked: searchInput.text = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -588,6 +612,7 @@ Rectangle {
|
||||
color: "transparent"
|
||||
|
||||
Rectangle {
|
||||
visible: !isFailed && !isPending
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 24
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
@@ -596,6 +621,19 @@ Rectangle {
|
||||
radius: 8
|
||||
color: isout ? "#d85a00" : "#2eb358"
|
||||
}
|
||||
|
||||
MoneroComponents.TextPlain {
|
||||
visible: isFailed || isPending
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 24
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
font.family: FontAwesome.fontFamilySolid
|
||||
font.styleName: isFailed ? "Solid" : ""
|
||||
font.pixelSize: 15
|
||||
text: isFailed ? FontAwesome.times : FontAwesome.clockO
|
||||
color: isFailed ? "#FF0000" : MoneroComponents.Style.defaultFontColor
|
||||
themeTransition: false
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
@@ -633,7 +671,7 @@ Rectangle {
|
||||
MoneroComponents.TextPlain {
|
||||
font.family: MoneroComponents.Style.fontRegular.name
|
||||
font.pixelSize: 15
|
||||
text: (isout ? qsTr("Sent") : qsTr("Received")) + translationManager.emptyString
|
||||
text: (isout ? qsTr("Sent") : qsTr("Received")) + (isFailed ? " (" + qsTr("Failed") + ")" : (isPending ? " (" + qsTr("Pending") + ")" : "")) + translationManager.emptyString
|
||||
color: MoneroComponents.Style.historyHeaderTextColor
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
themeTransitionBlackColor: MoneroComponents.Style._b_historyHeaderTextColor
|
||||
@@ -764,14 +802,7 @@ Rectangle {
|
||||
font.pixelSize: 15
|
||||
text: {
|
||||
if (isout) {
|
||||
if (isFailed) {
|
||||
return qsTr("Failed") + translationManager.emptyString;
|
||||
}
|
||||
if (isPending) {
|
||||
return qsTr("Waiting confirmation...") + translationManager.emptyString;
|
||||
}
|
||||
if (address) {
|
||||
const addressBookName = currentWallet ? currentWallet.addressBook.getDescription(address) : null;
|
||||
return (addressBookName ? FontAwesome.addressBook + " " + addressBookName : TxUtils.addressTruncate(address, 8));
|
||||
}
|
||||
if (amount != 0) {
|
||||
@@ -780,8 +811,6 @@ Rectangle {
|
||||
return qsTr("My wallet") + translationManager.emptyString;
|
||||
}
|
||||
} else {
|
||||
const receivingAddress = currentWallet ? currentWallet.address(subaddrAccount, subaddrIndex) : null;
|
||||
const receivingAddressLabel = currentWallet ? appWindow.currentWallet.getSubaddressLabel(subaddrAccount, subaddrIndex) : null;
|
||||
if (receivingAddress) {
|
||||
if (subaddrIndex == 0) {
|
||||
return qsTr("Address") + " #0" + " (" + qsTr("Primary address") + ")" + translationManager.emptyString;
|
||||
@@ -953,6 +982,8 @@ Rectangle {
|
||||
label.font.family: FontAwesome.fontFamily
|
||||
fontSize: 18
|
||||
width: 34
|
||||
tooltip: qsTr("Transaction details") + translationManager.emptyString
|
||||
tooltipLeft: true
|
||||
|
||||
MouseArea {
|
||||
state: "details"
|
||||
@@ -960,8 +991,14 @@ Rectangle {
|
||||
hoverEnabled: true
|
||||
z: parent.z + 1
|
||||
|
||||
onEntered: parent.opacity = 0.8;
|
||||
onExited: parent.opacity = 1.0;
|
||||
onEntered: {
|
||||
parent.opacity = 0.8;
|
||||
parent.tooltipPopup.open()
|
||||
}
|
||||
onExited: {
|
||||
parent.opacity = 1.0;
|
||||
parent.tooltipPopup.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -983,6 +1020,8 @@ Rectangle {
|
||||
label.font.family: FontAwesome.fontFamilyBrands
|
||||
fontSize: 18
|
||||
width: 34
|
||||
tooltip: qsTr("Generate payment proof") + translationManager.emptyString
|
||||
tooltipLeft: true
|
||||
|
||||
MouseArea {
|
||||
state: "proof"
|
||||
@@ -990,8 +1029,14 @@ Rectangle {
|
||||
hoverEnabled: true
|
||||
z: parent.z + 1
|
||||
|
||||
onEntered: parent.opacity = 0.8;
|
||||
onExited: parent.opacity = 1.0;
|
||||
onEntered: {
|
||||
parent.opacity = 0.8;
|
||||
parent.tooltipPopup.open()
|
||||
}
|
||||
onExited: {
|
||||
parent.opacity = 1.0;
|
||||
parent.tooltipPopup.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1227,7 +1272,7 @@ Rectangle {
|
||||
if(res[i].state === 'copyable_address') (address ? root.toClipboard(address) : root.toClipboard(addressField.text));
|
||||
if(res[i].state === 'copyable_receiving_address') root.toClipboard(currentWallet.address(subaddrAccount, subaddrIndex));
|
||||
if(res[i].state === 'copyable_txkey') root.getTxKey(hash, res[i]);
|
||||
if(res[i].state === 'set_tx_note') root.editDescription(hash, tx_note);
|
||||
if(res[i].state === 'set_tx_note') root.editDescription(hash, tx_note, root.txPage);
|
||||
if(res[i].state === 'details') root.showTxDetails(hash, paymentId, destinations, subaddrAccount, subaddrIndex, dateTime, displayAmount, isout);
|
||||
if(res[i].state === 'proof') root.showTxProof(hash, paymentId, destinations, subaddrAccount, subaddrIndex);
|
||||
doCollapse = false;
|
||||
@@ -1266,6 +1311,8 @@ Rectangle {
|
||||
image: "qrc:///images/whiteDropIndicator.png"
|
||||
rotation: delegate.collapsed ? 180 : 0
|
||||
color: MoneroComponents.Style.defaultFontColor
|
||||
fontAwesomeFallbackIcon: FontAwesome.arrowDown
|
||||
fontAwesomeFallbackSize: 14
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1341,7 +1388,7 @@ Rectangle {
|
||||
checked: persistentSettings.historyHumanDates
|
||||
onClicked: {
|
||||
persistentSettings.historyHumanDates = !persistentSettings.historyHumanDates
|
||||
root.updateDisplay(root.txOffset, root.txMax, false);
|
||||
root.updateDisplay(root.txOffset, root.txMax);
|
||||
}
|
||||
text: qsTr("Human readable date format") + translationManager.emptyString
|
||||
}
|
||||
@@ -1388,7 +1435,7 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
|
||||
function updateFilter(){
|
||||
function updateFilter(currentPage){
|
||||
// applying filters
|
||||
root.txData = JSON.parse(JSON.stringify(root.txModelData)); // deepcopy
|
||||
|
||||
@@ -1417,6 +1464,12 @@ Rectangle {
|
||||
txs.push(item);
|
||||
} else if(item.address !== "" && item.address.toLowerCase().startsWith(root.sortSearchString.toLowerCase())){
|
||||
txs.push(item);
|
||||
} else if(item.receivingAddress !== "" && item.receivingAddress.toLowerCase().startsWith(root.sortSearchString.toLowerCase())){
|
||||
txs.push(item);
|
||||
} else if(item.receivingAddressLabel !== "" && item.receivingAddressLabel.toLowerCase().startsWith(root.sortSearchString.toLowerCase())){
|
||||
txs.push(item);
|
||||
} else if(item.addressBookName !== "" && item.addressBookName.toLowerCase().startsWith(root.sortSearchString.toLowerCase())){
|
||||
txs.push(item);
|
||||
} else if(typeof item.blockheight !== "undefined" && item.blockheight.toString().startsWith(root.sortSearchString)) {
|
||||
txs.push(item);
|
||||
} else if(item.tx_note.toLowerCase().indexOf(root.sortSearchString.toLowerCase()) !== -1) {
|
||||
@@ -1432,6 +1485,9 @@ Rectangle {
|
||||
|
||||
root.updateSort();
|
||||
root.updateDisplay(root.txOffset, root.txMax);
|
||||
if (currentPage) {
|
||||
root.paginationJump(parseInt(currentPage));
|
||||
}
|
||||
}
|
||||
|
||||
function updateSort(){
|
||||
@@ -1447,15 +1503,14 @@ Rectangle {
|
||||
root.updateDisplay(root.txOffset, root.txMax);
|
||||
}
|
||||
|
||||
function updateDisplay(tx_offset, tx_max, auto_collapse) {
|
||||
if(typeof auto_collapse === 'undefined') auto_collapse = false;
|
||||
function updateDisplay(tx_offset, tx_max) {
|
||||
txListViewModel.clear();
|
||||
|
||||
// limit results as per tx_max (root.txMax)
|
||||
var txs = root.txData.slice(tx_offset, tx_offset + tx_max);
|
||||
|
||||
// make first result on the first page collapsed by default
|
||||
if(auto_collapse && root.txPage === 1 && txs.length > 0 && (root.sortSearchString == null || root.sortSearchString === ""))
|
||||
// collapse tx if there is a single result
|
||||
if(root.txPage === 1 && txs.length === 1)
|
||||
root.txDataCollapsed.push(txs[0]['hash']);
|
||||
|
||||
// populate listview
|
||||
@@ -1522,8 +1577,16 @@ Rectangle {
|
||||
|
||||
var tx_note = currentWallet.getUserNote(hash);
|
||||
var address = "";
|
||||
if(isout) {
|
||||
var addressBookName = "";
|
||||
var receivingAddress = "";
|
||||
var receivingAddressLabel = "";
|
||||
|
||||
if (isout) {
|
||||
address = TxUtils.destinationsToAddress(destinations);
|
||||
addressBookName = currentWallet ? currentWallet.addressBook.getDescription(address) : null;
|
||||
} else {
|
||||
receivingAddress = currentWallet ? currentWallet.address(subaddrAccount, subaddrIndex) : null;
|
||||
receivingAddressLabel = currentWallet ? appWindow.currentWallet.getSubaddressLabel(subaddrAccount, subaddrIndex) : null;
|
||||
}
|
||||
|
||||
if (isout)
|
||||
@@ -1541,6 +1604,7 @@ Rectangle {
|
||||
"hash": hash,
|
||||
"paymentId": paymentId,
|
||||
"address": address,
|
||||
"addressBookName": addressBookName,
|
||||
"destinations": destinations,
|
||||
"tx_note": tx_note,
|
||||
"dateHuman": dateHuman,
|
||||
@@ -1551,6 +1615,8 @@ Rectangle {
|
||||
"fee": fee,
|
||||
"confirmations": confirmations,
|
||||
"confirmationsRequired": confirmationsRequired,
|
||||
"receivingAddress": receivingAddress,
|
||||
"receivingAddressLabel": receivingAddressLabel,
|
||||
"subaddrAccount": subaddrAccount,
|
||||
"subaddrIndex": subaddrIndex
|
||||
});
|
||||
@@ -1560,20 +1626,20 @@ Rectangle {
|
||||
root.txCount = root.txData.length;
|
||||
}
|
||||
|
||||
function update() {
|
||||
function update(currentPage) {
|
||||
// handle outside mutation of tx model; incoming/outgoing funds or new blocks. Update table.
|
||||
currentWallet.history.refresh(currentWallet.currentSubaddressAccount);
|
||||
|
||||
root.updateTransactionsFromModel();
|
||||
root.updateFilter();
|
||||
root.updateFilter(currentPage);
|
||||
}
|
||||
|
||||
function editDescription(_hash, _tx_note){
|
||||
function editDescription(_hash, _tx_note, currentPage){
|
||||
inputDialog.labelText = qsTr("Set description:") + translationManager.emptyString;
|
||||
inputDialog.onAcceptedCallback = function() {
|
||||
appWindow.currentWallet.setUserNote(_hash, inputDialog.inputText);
|
||||
appWindow.showStatusMessage(qsTr("Updated description."),3);
|
||||
root.update();
|
||||
root.update(currentPage);
|
||||
}
|
||||
inputDialog.onRejectedCallback = null;
|
||||
inputDialog.open(_tx_note);
|
||||
@@ -1654,6 +1720,10 @@ Rectangle {
|
||||
|
||||
console.log("getProof: Generate clicked: txid " + hash + ", address " + address);
|
||||
middlePanel.getProofClicked(hash, address, '');
|
||||
informationPopup.title = qsTr("Payment proof") + translationManager.emptyString;
|
||||
informationPopup.text = qsTr("Generating payment proof") + "..." + translationManager.emptyString;
|
||||
informationPopup.onCloseCallback = null
|
||||
informationPopup.open()
|
||||
}
|
||||
|
||||
function toClipboard(text){
|
||||
@@ -1682,16 +1752,6 @@ Rectangle {
|
||||
+ translationManager.emptyString;
|
||||
}
|
||||
|
||||
function lookupPaymentID(paymentId) {
|
||||
if (!addressBookModel)
|
||||
return ""
|
||||
var idx = addressBookModel.lookupPaymentID(paymentId)
|
||||
if (idx < 0)
|
||||
return ""
|
||||
idx = addressBookModel.index(idx, 0)
|
||||
return addressBookModel.data(idx, AddressBookModel.AddressBookDescriptionRole)
|
||||
}
|
||||
|
||||
FileDialog {
|
||||
id: writeCSVFileDialog
|
||||
title: qsTr("Please choose a folder") + translationManager.emptyString
|
||||
@@ -1735,16 +1795,38 @@ Rectangle {
|
||||
root.model = appWindow.currentWallet.historyModel;
|
||||
root.model.sortRole = TransactionHistoryModel.TransactionBlockHeightRole
|
||||
root.model.sort(0, Qt.DescendingOrder);
|
||||
fromDatePicker.currentDate = model.transactionHistory.firstDateTime
|
||||
var count = root.model.rowCount()
|
||||
if (count > 0) {
|
||||
//date of the first transaction
|
||||
fromDatePicker.currentDate = root.model.data(root.model.index((count - 1), 0), TransactionHistoryModel.TransactionDateRole);
|
||||
} else {
|
||||
//date of monero birth (2014-04-18)
|
||||
fromDatePicker.currentDate = model.transactionHistory.firstDateTime
|
||||
}
|
||||
}
|
||||
|
||||
root.reset();
|
||||
root.refresh();
|
||||
root.initialized = true;
|
||||
root.updateFilter();
|
||||
}
|
||||
|
||||
function onPageClosed(){
|
||||
root.initialized = false;
|
||||
root.reset(true);
|
||||
root.clearFields();
|
||||
}
|
||||
|
||||
function searchInHistory(searchTerm){
|
||||
searchInput.text = searchTerm;
|
||||
searchInput.forceActiveFocus();
|
||||
searchInput.cursorPosition = searchInput.text.length;
|
||||
sortAndFilter.collapsed = true;
|
||||
}
|
||||
|
||||
function clearFields() {
|
||||
sortAndFilter.collapsed = false;
|
||||
searchInput.text = "";
|
||||
root.txDataCollapsed = [];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ Rectangle {
|
||||
id: mainLayout
|
||||
Layout.fillWidth: true
|
||||
anchors.margins: 20
|
||||
anchors.topMargin: 40
|
||||
anchors.topMargin: 0
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.top
|
||||
anchors.right: parent.right
|
||||
|
||||
@@ -50,6 +50,7 @@ Rectangle {
|
||||
color: "transparent"
|
||||
property var model
|
||||
property alias receiveHeight: mainLayout.height
|
||||
property var state: "Address"
|
||||
|
||||
function renameSubaddressLabel(_index){
|
||||
inputDialog.labelText = qsTr("Set the label of the selected address:") + translationManager.emptyString;
|
||||
@@ -60,6 +61,17 @@ Rectangle {
|
||||
inputDialog.open(appWindow.currentWallet.getSubaddressLabel(appWindow.currentWallet.currentSubaddressAccount, _index))
|
||||
}
|
||||
|
||||
function generateQRCodeString() {
|
||||
if (pageReceive.state == "PaymentRequest") {
|
||||
return TxUtils.makeQRCodeString(appWindow.current_address,
|
||||
(amountToReceiveXMR.text != "" && parseFloat(amountToReceiveXMR.text) != 0 ? amountToReceiveXMR.text : ""),
|
||||
(txDescriptionInput.text != "" ? txDescriptionInput.text : ""),
|
||||
(receiverNameInput.text != "" ? receiverNameInput.text : ""));
|
||||
} else {
|
||||
return TxUtils.makeQRCodeString(appWindow.current_address);
|
||||
}
|
||||
}
|
||||
|
||||
Clipboard { id: clipboard }
|
||||
|
||||
/* main layout */
|
||||
@@ -72,17 +84,467 @@ Rectangle {
|
||||
anchors.top: parent.top
|
||||
anchors.right: parent.right
|
||||
|
||||
spacing: 20
|
||||
spacing: 15
|
||||
|
||||
ColumnLayout {
|
||||
id: selectedAddressDetailsColumn
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
spacing: 0
|
||||
property int qrSize: 220
|
||||
|
||||
MoneroComponents.Navbar {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.bottomMargin: 10
|
||||
|
||||
MoneroComponents.NavbarItem {
|
||||
active: state == "Address"
|
||||
text: qsTr("Address") + translationManager.emptyString
|
||||
onSelected: state = "Address"
|
||||
}
|
||||
|
||||
MoneroComponents.NavbarItem {
|
||||
active: state == "PaymentRequest"
|
||||
text: qsTr("Payment request") + translationManager.emptyString
|
||||
onSelected: {
|
||||
state = "PaymentRequest";
|
||||
qrCodeTextMouseArea.hoverEnabled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: qrContainer
|
||||
color: MoneroComponents.Style.blackTheme ? "white" : "transparent"
|
||||
Layout.fillWidth: true
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.maximumWidth: parent.qrSize
|
||||
Layout.preferredHeight: width
|
||||
radius: 4
|
||||
|
||||
Image {
|
||||
id: qrCode
|
||||
anchors.fill: parent
|
||||
anchors.margins: 1
|
||||
smooth: false
|
||||
fillMode: Image.PreserveAspectFit
|
||||
source: "image://qrcode/" + generateQRCodeString();
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||
onEntered: qrCodeTooltip.tooltipPopup.open()
|
||||
onExited: qrCodeTooltip.tooltipPopup.close()
|
||||
onClicked: {
|
||||
if (mouse.button == Qt.LeftButton){
|
||||
walletManager.saveQrCodeToClipboard(generateQRCodeString());
|
||||
appWindow.showStatusMessage(qsTr("QR code copied to clipboard") + translationManager.emptyString, 3);
|
||||
} else if (mouse.button == Qt.RightButton){
|
||||
qrMenu.x = this.mouseX;
|
||||
qrMenu.y = this.mouseY;
|
||||
qrMenu.open()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Menu {
|
||||
id: qrMenu
|
||||
title: "QrCode"
|
||||
|
||||
MenuItem {
|
||||
text: qsTr("Copy to clipboard") + translationManager.emptyString;
|
||||
onTriggered: walletManager.saveQrCodeToClipboard(generateQRCodeString())
|
||||
}
|
||||
|
||||
MenuItem {
|
||||
text: qsTr("Save as Image") + translationManager.emptyString;
|
||||
onTriggered: qrFileDialog.open()
|
||||
}
|
||||
}
|
||||
|
||||
MoneroComponents.Tooltip {
|
||||
id: qrCodeTooltip
|
||||
text: qsTr("Left click: copy QR code to clipboard") + "<br>" + qsTr("Right click: save QR code as image file") + translationManager.emptyString
|
||||
}
|
||||
}
|
||||
|
||||
MoneroComponents.TextPlain {
|
||||
id: qrCodeText
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.topMargin: 6
|
||||
Layout.maximumWidth: 285
|
||||
Layout.minimumHeight: 75
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
visible: paymentRequestGridLayout.visible
|
||||
font.pixelSize: 12
|
||||
color: qrCodeTextMouseArea.containsMouse ? MoneroComponents.Style.orange : MoneroComponents.Style.defaultFontColor
|
||||
text: generateQRCodeString();
|
||||
wrapMode: Text.WrapAnywhere
|
||||
tooltip: qsTr("Copy payment request to clipboard") + translationManager.emptyString
|
||||
themeTransition: false
|
||||
|
||||
MouseArea {
|
||||
id: qrCodeTextMouseArea
|
||||
hoverEnabled: false //true when Payment request navbar button is clicked (fix bug displaying tooltip when navbar button is clicked)
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onEntered: parent.tooltipPopup.open()
|
||||
onExited: parent.tooltipPopup.close()
|
||||
onClicked: {
|
||||
clipboard.setText(qrCodeText.text);
|
||||
appWindow.showStatusMessage(qsTr("Payment request copied to clipboard") + translationManager.emptyString, 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GridLayout {
|
||||
id: paymentRequestGridLayout
|
||||
columns: 3
|
||||
rows: 4
|
||||
visible: pageReceive.state == "PaymentRequest"
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.topMargin: 6
|
||||
Layout.preferredWidth: 285
|
||||
Layout.maximumWidth: 285
|
||||
|
||||
MoneroComponents.Label {
|
||||
id: amountTitleFiat
|
||||
Layout.bottomMargin: 3
|
||||
Layout.preferredWidth: 90
|
||||
visible: persistentSettings.fiatPriceEnabled
|
||||
fontSize: 14
|
||||
text: qsTr("Amount") + translationManager.emptyString
|
||||
}
|
||||
|
||||
MoneroComponents.Input {
|
||||
id: amountToReceiveFiat
|
||||
Layout.preferredWidth: 165
|
||||
Layout.maximumWidth: 165
|
||||
visible: persistentSettings.fiatPriceEnabled
|
||||
topPadding: 5
|
||||
leftPadding: 5
|
||||
font.family: MoneroComponents.Style.fontMonoRegular.name
|
||||
font.pixelSize: 14
|
||||
font.bold: false
|
||||
horizontalAlignment: TextInput.AlignLeft
|
||||
verticalAlignment: TextInput.AlignVCenter
|
||||
selectByMouse: true
|
||||
color: MoneroComponents.Style.defaultFontColor
|
||||
placeholderText: "0.00"
|
||||
|
||||
background: Rectangle {
|
||||
color: MoneroComponents.Style.blackTheme ? "transparent" : "white"
|
||||
radius: 3
|
||||
border.color: parent.activeFocus ? MoneroComponents.Style.inputBorderColorActive : MoneroComponents.Style.inputBorderColorInActive
|
||||
border.width: 1
|
||||
}
|
||||
onTextEdited: {
|
||||
text = text.trim().replace(",", ".");
|
||||
const match = text.match(/^0+(\d.*)/);
|
||||
if (match) {
|
||||
const cursorPosition = cursorPosition;
|
||||
text = match[1];
|
||||
cursorPosition = Math.max(cursorPosition, 1) - 1;
|
||||
} else if(text.indexOf('.') === 0){
|
||||
text = '0' + text;
|
||||
if (text.length > 2) {
|
||||
cursorPosition = 1;
|
||||
}
|
||||
}
|
||||
if (amountToReceiveFiat.text == "") {
|
||||
amountToReceiveXMR.text = "";
|
||||
} else {
|
||||
amountToReceiveXMR.text = fiatApiConvertToXMR(amountToReceiveFiat.text);
|
||||
}
|
||||
}
|
||||
validator: RegExpValidator {
|
||||
regExp: /^\s*(\d{1,8})?([\.,]\d{1,2})?\s*$/
|
||||
}
|
||||
}
|
||||
|
||||
MoneroComponents.Label {
|
||||
Layout.bottomMargin: 3
|
||||
visible: persistentSettings.fiatPriceEnabled
|
||||
fontSize: 14
|
||||
text: appWindow.fiatApiCurrencySymbol();
|
||||
}
|
||||
|
||||
MoneroComponents.Label {
|
||||
id: amountTitleXMR
|
||||
Layout.bottomMargin: 3
|
||||
Layout.preferredWidth: 90
|
||||
fontSize: 14
|
||||
text: persistentSettings.fiatPriceEnabled ? "" : qsTr("Amount") + translationManager.emptyString
|
||||
}
|
||||
|
||||
MoneroComponents.Input {
|
||||
id: amountToReceiveXMR
|
||||
Layout.preferredWidth: 165
|
||||
Layout.maximumWidth: 165
|
||||
topPadding: 5
|
||||
leftPadding: 5
|
||||
font.family: MoneroComponents.Style.fontMonoRegular.name
|
||||
font.pixelSize: 14
|
||||
font.bold: false
|
||||
horizontalAlignment: TextInput.AlignLeft
|
||||
verticalAlignment: TextInput.AlignVCenter
|
||||
selectByMouse: true
|
||||
color: MoneroComponents.Style.defaultFontColor
|
||||
placeholderText: "0.000000000000"
|
||||
|
||||
background: Rectangle {
|
||||
color: MoneroComponents.Style.blackTheme ? "transparent" : "white"
|
||||
radius: 3
|
||||
border.color: parent.activeFocus ? MoneroComponents.Style.inputBorderColorActive : MoneroComponents.Style.inputBorderColorInActive
|
||||
border.width: 1
|
||||
}
|
||||
onTextEdited: {
|
||||
text = text.trim().replace(",", ".");
|
||||
const match = text.match(/^0+(\d.*)/);
|
||||
if (match) {
|
||||
const cursorPosition = cursorPosition;
|
||||
text = match[1];
|
||||
cursorPosition = Math.max(cursorPosition, 1) - 1;
|
||||
} else if(text.indexOf('.') === 0){
|
||||
text = '0' + text;
|
||||
if (text.length > 2) {
|
||||
cursorPosition = 1;
|
||||
}
|
||||
}
|
||||
if (amountToReceiveXMR.text == "") {
|
||||
amountToReceiveFiat.text = "";
|
||||
} else {
|
||||
amountToReceiveFiat.text = fiatApiConvertToFiat(amountToReceiveXMR.text);
|
||||
}
|
||||
}
|
||||
validator: RegExpValidator {
|
||||
regExp: /^\s*(\d{1,8})?([\.,]\d{1,12})?\s*$/
|
||||
}
|
||||
}
|
||||
|
||||
MoneroComponents.Label {
|
||||
Layout.bottomMargin: 3
|
||||
fontSize: 14
|
||||
text: "XMR"
|
||||
}
|
||||
|
||||
MoneroComponents.Label {
|
||||
id: txDescription
|
||||
Layout.bottomMargin: 3
|
||||
Layout.preferredWidth: 90
|
||||
fontSize: 14
|
||||
text: qsTr("Description") + translationManager.emptyString
|
||||
tooltip: qsTr("What is being payed for (a product, service, donation) (optional)") + translationManager.emptyString
|
||||
tooltipIconVisible: true
|
||||
}
|
||||
|
||||
MoneroComponents.Input {
|
||||
id: txDescriptionInput
|
||||
Layout.preferredWidth: 165
|
||||
Layout.maximumWidth: 165
|
||||
topPadding: 7
|
||||
leftPadding: 7
|
||||
font.pixelSize: 14
|
||||
font.bold: false
|
||||
horizontalAlignment: TextInput.AlignLeft
|
||||
verticalAlignment: TextInput.AlignVCenter
|
||||
selectByMouse: true
|
||||
color: MoneroComponents.Style.defaultFontColor
|
||||
placeholderText: qsTr("Visible to the sender") + translationManager.emptyString
|
||||
|
||||
background: Rectangle {
|
||||
color: MoneroComponents.Style.blackTheme ? "transparent" : "white"
|
||||
radius: 3
|
||||
border.color: parent.activeFocus ? MoneroComponents.Style.inputBorderColorActive : MoneroComponents.Style.inputBorderColorInActive
|
||||
border.width: 1
|
||||
}
|
||||
}
|
||||
|
||||
MoneroComponents.Label {
|
||||
Layout.bottomMargin: 3
|
||||
fontSize: 14
|
||||
text: ""
|
||||
}
|
||||
|
||||
MoneroComponents.Label {
|
||||
id: receiverNameLabel
|
||||
Layout.bottomMargin: 3
|
||||
Layout.preferredWidth: 90
|
||||
fontSize: 14
|
||||
text: qsTr("Your name") + translationManager.emptyString
|
||||
tooltip: qsTr("Your name, company or website (optional)") + translationManager.emptyString
|
||||
tooltipIconVisible: true
|
||||
}
|
||||
|
||||
MoneroComponents.Input {
|
||||
id: receiverNameInput
|
||||
Layout.preferredWidth: 165
|
||||
Layout.maximumWidth: 165
|
||||
topPadding: 7
|
||||
leftPadding: 7
|
||||
font.pixelSize: 14
|
||||
font.bold: false
|
||||
horizontalAlignment: TextInput.AlignLeft
|
||||
verticalAlignment: TextInput.AlignVCenter
|
||||
selectByMouse: true
|
||||
color: MoneroComponents.Style.defaultFontColor
|
||||
placeholderText: qsTr("Visible to the sender") + translationManager.emptyString
|
||||
|
||||
background: Rectangle {
|
||||
color: MoneroComponents.Style.blackTheme ? "transparent" : "white"
|
||||
radius: 3
|
||||
border.color: parent.activeFocus ? MoneroComponents.Style.inputBorderColorActive : MoneroComponents.Style.inputBorderColorInActive
|
||||
border.width: 1
|
||||
}
|
||||
}
|
||||
|
||||
MoneroComponents.Label {
|
||||
Layout.bottomMargin: 3
|
||||
fontSize: 14
|
||||
text: ""
|
||||
}
|
||||
}
|
||||
|
||||
MoneroComponents.TextPlain {
|
||||
id: selectedaddressIndex
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.preferredWidth: 220
|
||||
Layout.maximumWidth: 220
|
||||
Layout.topMargin: 15
|
||||
visible: pageReceive.state == "Address"
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
text: qsTr("Address #") + subaddressListView.currentIndex + translationManager.emptyString
|
||||
wrapMode: Text.WordWrap
|
||||
font.family: MoneroComponents.Style.fontRegular.name
|
||||
font.pixelSize: 17
|
||||
textFormat: Text.RichText
|
||||
color: MoneroComponents.Style.defaultFontColor
|
||||
themeTransition: false
|
||||
}
|
||||
|
||||
MoneroComponents.TextPlain {
|
||||
id: selectedAddressDrescription
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.preferredWidth: 220
|
||||
Layout.maximumWidth: 220
|
||||
Layout.topMargin: 10
|
||||
visible: pageReceive.state == "Address"
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
text: "(" + qsTr("no label") + ")" + translationManager.emptyString
|
||||
wrapMode: Text.WordWrap
|
||||
font.family: MoneroComponents.Style.fontRegular.name
|
||||
font.pixelSize: 17
|
||||
textFormat: Text.RichText
|
||||
color: selectedAddressDrescriptionMouseArea.containsMouse ? MoneroComponents.Style.orange : MoneroComponents.Style.dimmedFontColor
|
||||
themeTransition: false
|
||||
tooltip: subaddressListView.currentIndex > 0 ? qsTr("Edit address label") : "" + translationManager.emptyString
|
||||
MouseArea {
|
||||
id: selectedAddressDrescriptionMouseArea
|
||||
visible: subaddressListView.currentIndex > 0
|
||||
hoverEnabled: true
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onEntered: parent.tooltip ? parent.tooltipPopup.open() : ""
|
||||
onExited: parent.tooltip ? parent.tooltipPopup.close() : ""
|
||||
onClicked: {
|
||||
renameSubaddressLabel(appWindow.current_subaddress_table_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MoneroComponents.TextPlain {
|
||||
id: selectedAddress
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.maximumWidth: 300
|
||||
Layout.topMargin: 11
|
||||
visible: pageReceive.state == "Address"
|
||||
text: appWindow.current_address ? appWindow.current_address : ""
|
||||
horizontalAlignment: TextInput.AlignHCenter
|
||||
wrapMode: Text.Wrap
|
||||
textFormat: Text.RichText
|
||||
color: selectedAddressMouseArea.containsMouse ? MoneroComponents.Style.orange : MoneroComponents.Style.defaultFontColor
|
||||
font.pixelSize: 15
|
||||
font.family: MoneroComponents.Style.fontRegular.name
|
||||
themeTransition: false
|
||||
tooltip: qsTr("Copy address to clipboard") + translationManager.emptyString
|
||||
MouseArea {
|
||||
id: selectedAddressMouseArea
|
||||
hoverEnabled: true
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onEntered: parent.tooltip ? parent.tooltipPopup.open() : ""
|
||||
onExited: parent.tooltip ? parent.tooltipPopup.close() : ""
|
||||
onClicked: {
|
||||
clipboard.setText(appWindow.current_address);
|
||||
appWindow.showStatusMessage(qsTr("Address copied to clipboard") + translationManager.emptyString, 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MoneroComponents.StandardButton {
|
||||
Layout.preferredWidth: 220
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.topMargin: 18
|
||||
small: true
|
||||
text: qsTr("Show on device") + translationManager.emptyString
|
||||
fontSize: 14
|
||||
visible: appWindow.currentWallet ? appWindow.currentWallet.isHwBacked() : false
|
||||
onClicked: {
|
||||
appWindow.currentWallet.deviceShowAddressAsync(
|
||||
appWindow.currentWallet.currentSubaddressAccount,
|
||||
appWindow.current_subaddress_table_index,
|
||||
'');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: addressRow
|
||||
spacing: 0
|
||||
|
||||
MoneroComponents.LabelSubheader {
|
||||
Layout.fillWidth: true
|
||||
fontSize: 24
|
||||
textFormat: Text.RichText
|
||||
text: qsTr("Addresses") + translationManager.emptyString
|
||||
RowLayout {
|
||||
spacing: 0
|
||||
|
||||
MoneroComponents.LabelSubheader {
|
||||
Layout.fillWidth: true
|
||||
fontSize: 24
|
||||
textFormat: Text.RichText
|
||||
text: qsTr("Addresses") + translationManager.emptyString
|
||||
}
|
||||
|
||||
MoneroComponents.StandardButton {
|
||||
id: createAddressButton
|
||||
small: true
|
||||
text: qsTr("Create new address") + translationManager.emptyString
|
||||
fontSize: 13
|
||||
onClicked: {
|
||||
inputDialog.labelText = qsTr("Set the label of the new address:") + translationManager.emptyString
|
||||
inputDialog.onAcceptedCallback = function() {
|
||||
appWindow.currentWallet.subaddress.addRow(appWindow.currentWallet.currentSubaddressAccount, inputDialog.inputText)
|
||||
current_subaddress_table_index = appWindow.currentWallet.numSubaddresses(appWindow.currentWallet.currentSubaddressAccount) - 1
|
||||
subaddressListView.currentIndex = current_subaddress_table_index
|
||||
}
|
||||
inputDialog.onRejectedCallback = null;
|
||||
inputDialog.open()
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors.top: createAddressButton.bottom
|
||||
anchors.topMargin: 8
|
||||
anchors.left: createAddressButton.left
|
||||
anchors.right: createAddressButton.right
|
||||
height: 2
|
||||
color: MoneroComponents.Style.appWindowBorderColor
|
||||
|
||||
MoneroEffects.ColorTransition {
|
||||
targetObj: parent
|
||||
blackColor: MoneroComponents.Style._b_appWindowBorderColor
|
||||
whiteColor: MoneroComponents.Style._w_appWindowBorderColor
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
@@ -107,7 +569,16 @@ Rectangle {
|
||||
height: subaddressListRow.subaddressListItemHeight
|
||||
width: parent ? parent.width : undefined
|
||||
Layout.fillWidth: true
|
||||
color: "transparent"
|
||||
color: itemMouseArea.containsMouse || index === appWindow.current_subaddress_table_index ? MoneroComponents.Style.titleBarButtonHoverColor : "transparent"
|
||||
|
||||
Rectangle {
|
||||
visible: index === appWindow.current_subaddress_table_index
|
||||
Layout.fillHeight: true
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
color: "darkgrey"
|
||||
width: 2
|
||||
}
|
||||
|
||||
Rectangle{
|
||||
anchors.right: parent.right
|
||||
@@ -127,7 +598,7 @@ Rectangle {
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
anchors.topMargin: 5
|
||||
anchors.rightMargin: 80
|
||||
anchors.rightMargin: 90
|
||||
color: "transparent"
|
||||
|
||||
MoneroComponents.Label {
|
||||
@@ -143,7 +614,7 @@ Rectangle {
|
||||
|
||||
MoneroComponents.Label {
|
||||
id: nameLabel
|
||||
color: MoneroComponents.Style.dimmedFontColor
|
||||
color: index === appWindow.current_subaddress_table_index ? MoneroComponents.Style.defaultFontColor : MoneroComponents.Style.dimmedFontColor
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: idLabel.right
|
||||
anchors.leftMargin: 6
|
||||
@@ -167,11 +638,10 @@ Rectangle {
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: itemMouseArea
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
onEntered: tableItem2.color = MoneroComponents.Style.titleBarButtonHoverColor
|
||||
onExited: tableItem2.color = "transparent"
|
||||
onClicked: subaddressListView.currentIndex = index;
|
||||
}
|
||||
}
|
||||
@@ -183,14 +653,30 @@ Rectangle {
|
||||
height: 21
|
||||
spacing: 10
|
||||
|
||||
MoneroComponents.IconButton {
|
||||
fontAwesomeFallbackIcon: FontAwesome.searchPlus
|
||||
fontAwesomeFallbackSize: 22
|
||||
color: MoneroComponents.Style.defaultFontColor
|
||||
fontAwesomeFallbackOpacity: 0.5
|
||||
Layout.preferredWidth: 23
|
||||
Layout.preferredHeight: 21
|
||||
tooltip: qsTr("See transactions") + translationManager.emptyString
|
||||
|
||||
onClicked: doSearchInHistory(address)
|
||||
}
|
||||
|
||||
MoneroComponents.IconButton {
|
||||
id: renameButton
|
||||
image: "qrc:///images/edit.svg"
|
||||
fontAwesomeFallbackIcon: FontAwesome.edit
|
||||
fontAwesomeFallbackSize: 22
|
||||
color: MoneroComponents.Style.defaultFontColor
|
||||
opacity: 0.5
|
||||
opacity: isOpenGL ? 0.5 : 1
|
||||
fontAwesomeFallbackOpacity: 0.5
|
||||
Layout.preferredWidth: 23
|
||||
Layout.preferredHeight: 21
|
||||
visible: index !== 0
|
||||
tooltip: qsTr("Edit address label") + translationManager.emptyString
|
||||
|
||||
onClicked: {
|
||||
renameSubaddressLabel(index);
|
||||
@@ -200,10 +686,14 @@ Rectangle {
|
||||
MoneroComponents.IconButton {
|
||||
id: copyButton
|
||||
image: "qrc:///images/copy.svg"
|
||||
fontAwesomeFallbackIcon: FontAwesome.clipboard
|
||||
fontAwesomeFallbackSize: 22
|
||||
color: MoneroComponents.Style.defaultFontColor
|
||||
opacity: 0.5
|
||||
opacity: isOpenGL ? 0.5 : 1
|
||||
fontAwesomeFallbackOpacity: 0.5
|
||||
Layout.preferredWidth: 16
|
||||
Layout.preferredHeight: 21
|
||||
tooltip: qsTr("Copy address to clipboard") + translationManager.emptyString
|
||||
|
||||
onClicked: {
|
||||
console.log("Address copied to clipboard");
|
||||
@@ -220,6 +710,16 @@ Rectangle {
|
||||
appWindow.currentWallet.currentSubaddressAccount,
|
||||
subaddressListView.currentIndex
|
||||
);
|
||||
if (subaddressListView.currentIndex == 0) {
|
||||
selectedAddressDrescription.text = qsTr("Primary address") + translationManager.emptyString;
|
||||
} else {
|
||||
var selectedAddressLabel = appWindow.currentWallet.getSubaddressLabel(appWindow.currentWallet.currentSubaddressAccount, appWindow.current_subaddress_table_index);
|
||||
if (selectedAddressLabel == "") {
|
||||
selectedAddressDrescription.text = "(" + qsTr("no label") + ")" + translationManager.emptyString
|
||||
} else {
|
||||
selectedAddressDrescription.text = selectedAddressLabel
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -235,96 +735,6 @@ Rectangle {
|
||||
whiteColor: MoneroComponents.Style._w_appWindowBorderColor
|
||||
}
|
||||
}
|
||||
|
||||
MoneroComponents.CheckBox {
|
||||
id: addNewAddressCheckbox
|
||||
border: false
|
||||
uncheckedIcon: FontAwesome.plusCircle
|
||||
toggleOnClick: false
|
||||
fontAwesomeIcons: true
|
||||
fontSize: 16
|
||||
iconOnTheLeft: true
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 10
|
||||
text: qsTr("Create new address") + translationManager.emptyString;
|
||||
onClicked: {
|
||||
inputDialog.labelText = qsTr("Set the label of the new address:") + translationManager.emptyString
|
||||
inputDialog.onAcceptedCallback = function() {
|
||||
appWindow.currentWallet.subaddress.addRow(appWindow.currentWallet.currentSubaddressAccount, inputDialog.inputText)
|
||||
current_subaddress_table_index = appWindow.currentWallet.numSubaddresses(appWindow.currentWallet.currentSubaddressAccount) - 1
|
||||
subaddressListView.currentIndex = current_subaddress_table_index
|
||||
}
|
||||
inputDialog.onRejectedCallback = null;
|
||||
inputDialog.open()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
spacing: 11
|
||||
property int qrSize: 220
|
||||
|
||||
Rectangle {
|
||||
id: qrContainer
|
||||
color: MoneroComponents.Style.blackTheme ? "white" : "transparent"
|
||||
Layout.fillWidth: true
|
||||
Layout.maximumWidth: parent.qrSize
|
||||
Layout.preferredHeight: width
|
||||
radius: 4
|
||||
|
||||
Image {
|
||||
id: qrCode
|
||||
anchors.fill: parent
|
||||
anchors.margins: 1
|
||||
|
||||
smooth: false
|
||||
fillMode: Image.PreserveAspectFit
|
||||
source: "image://qrcode/" + TxUtils.makeQRCodeString(appWindow.current_address)
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
acceptedButtons: Qt.RightButton
|
||||
onPressAndHold: qrFileDialog.open()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MoneroComponents.StandardButton {
|
||||
Layout.preferredWidth: 220
|
||||
small: true
|
||||
text: FontAwesome.save + " %1".arg(qsTr("Save as image")) + translationManager.emptyString
|
||||
label.font.family: FontAwesome.fontFamily
|
||||
fontSize: 13
|
||||
onClicked: qrFileDialog.open()
|
||||
}
|
||||
|
||||
MoneroComponents.StandardButton {
|
||||
Layout.preferredWidth: 220
|
||||
small: true
|
||||
text: FontAwesome.clipboard + " %1".arg(qsTr("Copy to clipboard")) + translationManager.emptyString
|
||||
label.font.family: FontAwesome.fontFamily
|
||||
fontSize: 13
|
||||
onClicked: {
|
||||
clipboard.setText(TxUtils.makeQRCodeString(appWindow.current_address));
|
||||
appWindow.showStatusMessage(qsTr("Copied to clipboard") + translationManager.emptyString, 3);
|
||||
}
|
||||
}
|
||||
|
||||
MoneroComponents.StandardButton {
|
||||
Layout.preferredWidth: 220
|
||||
small: true
|
||||
text: FontAwesome.eye + " %1".arg(qsTr("Show on device")) + translationManager.emptyString
|
||||
label.font.family: FontAwesome.fontFamily
|
||||
fontSize: 13
|
||||
visible: appWindow.currentWallet ? appWindow.currentWallet.isHwBacked() : false
|
||||
onClicked: {
|
||||
appWindow.currentWallet.deviceShowAddressAsync(
|
||||
appWindow.currentWallet.currentSubaddressAccount,
|
||||
appWindow.current_subaddress_table_index,
|
||||
'');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MessageDialog {
|
||||
@@ -339,12 +749,14 @@ Rectangle {
|
||||
selectExisting: false
|
||||
nameFilters: ["Image (*.png)"]
|
||||
onAccepted: {
|
||||
if(!walletManager.saveQrCode(TxUtils.makeQRCodeString(appWindow.current_address), walletManager.urlToLocalPath(fileUrl))) {
|
||||
if(!walletManager.saveQrCode(generateQRCodeString(), walletManager.urlToLocalPath(fileUrl))) {
|
||||
console.log("Failed to save QrCode to file " + walletManager.urlToLocalPath(fileUrl) )
|
||||
receivePageDialog.title = qsTr("Save QrCode") + translationManager.emptyString;
|
||||
receivePageDialog.text = qsTr("Failed to save QrCode to ") + walletManager.urlToLocalPath(fileUrl) + translationManager.emptyString;
|
||||
receivePageDialog.icon = StandardIcon.Error
|
||||
receivePageDialog.open()
|
||||
} else {
|
||||
appWindow.showStatusMessage(qsTr("QR code saved to ") + walletManager.urlToLocalPath(fileUrl) + translationManager.emptyString, 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -352,16 +764,23 @@ Rectangle {
|
||||
|
||||
function onPageCompleted() {
|
||||
console.log("Receive page loaded");
|
||||
pageReceive.clearFields();
|
||||
subaddressListView.model = appWindow.currentWallet.subaddressModel;
|
||||
|
||||
if (appWindow.currentWallet) {
|
||||
appWindow.current_address = appWindow.currentWallet.address(appWindow.currentWallet.currentSubaddressAccount, 0)
|
||||
appWindow.currentWallet.subaddress.refresh(appWindow.currentWallet.currentSubaddressAccount)
|
||||
if (subaddressListView.currentIndex == -1) {
|
||||
subaddressListView.currentIndex = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function clearFields() {
|
||||
// @TODO: add fields
|
||||
amountToReceiveFiat.text = "";
|
||||
amountToReceiveXMR.text = "";
|
||||
txDescriptionInput.text = "";
|
||||
receiverNameInput.text = "";
|
||||
}
|
||||
|
||||
function onPageClosed() {
|
||||
|
||||
@@ -81,8 +81,7 @@ Rectangle {
|
||||
id: mainLayout
|
||||
Layout.fillWidth: true
|
||||
anchors.margins: 20
|
||||
anchors.topMargin: 40
|
||||
|
||||
anchors.topMargin: 0
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.top
|
||||
anchors.right: parent.right
|
||||
|
||||
@@ -89,8 +89,7 @@ Rectangle {
|
||||
id: mainLayout
|
||||
Layout.fillWidth: true
|
||||
anchors.margins: 20
|
||||
anchors.topMargin: 40
|
||||
|
||||
anchors.topMargin: 0
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.top
|
||||
anchors.right: parent.right
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import QtQml.Models 2.2
|
||||
import QtQuick 2.9
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Layouts 1.1
|
||||
@@ -44,8 +45,7 @@ import "../js/Utils.js" as Utils
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
signal paymentClicked(string address, string paymentId, string amount, int mixinCount,
|
||||
int priority, string description)
|
||||
signal paymentClicked(var recipients, string paymentId, int mixinCount, int priority, string description)
|
||||
signal sweepUnmixableClicked()
|
||||
|
||||
color: "transparent"
|
||||
@@ -61,19 +61,18 @@ Rectangle {
|
||||
}
|
||||
|
||||
// There are sufficient unlocked funds available
|
||||
if (walletManager.amountFromString(amountLine.text) > appWindow.getUnlockedBalance()) {
|
||||
if (recipientModel.getAmountTotal() > appWindow.getUnlockedBalance()) {
|
||||
return qsTr("Amount is more than unlocked balance.") + translationManager.emptyString;
|
||||
}
|
||||
|
||||
if (addressLine.text)
|
||||
{
|
||||
if (!recipientModel.hasEmptyAddress()) {
|
||||
// Address is valid
|
||||
if (!TxUtils.checkAddress(addressLine.text, appWindow.persistentSettings.nettype)) {
|
||||
if (recipientModel.hasInvalidAddress()) {
|
||||
return qsTr("Address is invalid.") + translationManager.emptyString;
|
||||
}
|
||||
|
||||
// Amount is nonzero
|
||||
if (!amountLine.text || parseFloat(amountLine.text) <= 0) {
|
||||
if (recipientModel.hasEmptyAmount()) {
|
||||
return qsTr("Enter an amount.") + translationManager.emptyString;
|
||||
}
|
||||
}
|
||||
@@ -93,12 +92,22 @@ Rectangle {
|
||||
oaPopup.open()
|
||||
}
|
||||
|
||||
function fillPaymentDetails(address, payment_id, amount, tx_description, recipient_name) {
|
||||
if (recipientModel.count > 0) {
|
||||
const last = recipientModel.count - 1;
|
||||
if (recipientModel.get(recipientModel.count - 1).address == "") {
|
||||
recipientModel.remove(last);
|
||||
}
|
||||
}
|
||||
|
||||
recipientModel.newRecipient(address, Utils.removeTrailingZeros(amount || ""));
|
||||
setPaymentId(payment_id || "");
|
||||
setDescription((recipient_name ? recipient_name + (tx_description ? " (" + tx_description + ")" : "") : (tx_description || "")));
|
||||
}
|
||||
|
||||
function updateFromQrCode(address, payment_id, amount, tx_description, recipient_name) {
|
||||
console.log("updateFromQrCode")
|
||||
addressLine.text = address
|
||||
setPaymentId(payment_id);
|
||||
amountLine.text = amount
|
||||
setDescription(recipient_name + " " + tx_description);
|
||||
fillPaymentDetails(address, payment_id, amount, tx_description, recipient_name);
|
||||
cameraUi.qrcode_decoded.disconnect(updateFromQrCode)
|
||||
}
|
||||
|
||||
@@ -113,10 +122,8 @@ Rectangle {
|
||||
}
|
||||
|
||||
function clearFields() {
|
||||
addressLine.text = ""
|
||||
setPaymentId("");
|
||||
amountLine.text = ""
|
||||
setDescription("");
|
||||
recipientModel.clear();
|
||||
fillPaymentDetails("", "", "", "", "");
|
||||
priorityDropdown.currentIndex = 0
|
||||
}
|
||||
|
||||
@@ -163,166 +170,550 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
|
||||
// recipient address input
|
||||
RowLayout {
|
||||
id: addressLineRow
|
||||
Layout.fillWidth: true
|
||||
ListModel {
|
||||
id: recipientModel
|
||||
|
||||
LineEditMulti {
|
||||
id: addressLine
|
||||
spacing: 0
|
||||
inputPaddingRight: inlineButtonVisible && inlineButton2Visible ? 100 : 60
|
||||
fontBold: true
|
||||
labelText: qsTr("Address") + translationManager.emptyString
|
||||
labelButtonText: qsTr("Resolve") + translationManager.emptyString
|
||||
placeholderText: {
|
||||
if(persistentSettings.nettype == NetworkType.MAINNET){
|
||||
return "4.. / 8.. / OpenAlias";
|
||||
} else if (persistentSettings.nettype == NetworkType.STAGENET){
|
||||
return "5.. / 7..";
|
||||
} else if(persistentSettings.nettype == NetworkType.TESTNET){
|
||||
return "9.. / B..";
|
||||
}
|
||||
}
|
||||
wrapMode: Text.WrapAnywhere
|
||||
addressValidation: true
|
||||
onTextChanged: {
|
||||
const parsed = walletManager.parse_uri_to_object(text);
|
||||
if (!parsed.error) {
|
||||
addressLine.text = parsed.address;
|
||||
setPaymentId(parsed.payment_id);
|
||||
amountLine.text = parsed.amount;
|
||||
setDescription(parsed.tx_description);
|
||||
}
|
||||
}
|
||||
inlineButton.text: FontAwesome.addressBook
|
||||
inlineButton.buttonHeight: 30
|
||||
inlineButton.fontPixelSize: 22
|
||||
inlineButton.fontFamily: FontAwesome.fontFamily
|
||||
inlineButton.textColor: MoneroComponents.Style.defaultFontColor
|
||||
inlineButton.onClicked: {
|
||||
middlePanel.addressBookView.selectAndSend = true;
|
||||
appWindow.showPageRequest("AddressBook");
|
||||
}
|
||||
inlineButtonVisible: true
|
||||
|
||||
inlineButton2.text: FontAwesome.qrcode
|
||||
inlineButton2.buttonHeight: 30
|
||||
inlineButton2.fontPixelSize: 22
|
||||
inlineButton2.fontFamily: FontAwesome.fontFamily
|
||||
inlineButton2.textColor: MoneroComponents.Style.defaultFontColor
|
||||
inlineButton2.onClicked: {
|
||||
cameraUi.state = "Capture"
|
||||
cameraUi.qrcode_decoded.connect(updateFromQrCode)
|
||||
}
|
||||
inlineButton2Visible: appWindow.qrScannerEnabled
|
||||
}
|
||||
}
|
||||
readonly property int maxRecipients: 16
|
||||
|
||||
StandardButton {
|
||||
id: resolveButton
|
||||
width: 80
|
||||
text: qsTr("Resolve") + translationManager.emptyString
|
||||
visible: TxUtils.isValidOpenAliasAddress(addressLine.text)
|
||||
enabled : visible
|
||||
onClicked: {
|
||||
var result = walletManager.resolveOpenAlias(addressLine.text)
|
||||
if (result) {
|
||||
var parts = result.split("|")
|
||||
if (parts.length == 2) {
|
||||
var address_ok = walletManager.addressValid(parts[1], appWindow.persistentSettings.nettype)
|
||||
if (parts[0] === "true") {
|
||||
if (address_ok) {
|
||||
// prepend openalias to description
|
||||
descriptionLine.text = descriptionLine.text ? addressLine.text + " " + descriptionLine.text : addressLine.text
|
||||
descriptionCheckbox.checked = true
|
||||
addressLine.text = parts[1]
|
||||
}
|
||||
else
|
||||
oa_message(qsTr("No valid address found at this OpenAlias address"))
|
||||
}
|
||||
else if (parts[0] === "false") {
|
||||
if (address_ok) {
|
||||
addressLine.text = parts[1]
|
||||
oa_message(qsTr("Address found, but the DNSSEC signatures could not be verified, so this address may be spoofed"))
|
||||
}
|
||||
else
|
||||
{
|
||||
oa_message(qsTr("No valid address found at this OpenAlias address, but the DNSSEC signatures could not be verified, so this may be spoofed"))
|
||||
}
|
||||
}
|
||||
else {
|
||||
oa_message(qsTr("Internal error"))
|
||||
}
|
||||
}
|
||||
else {
|
||||
oa_message(qsTr("Internal error"))
|
||||
}
|
||||
}
|
||||
else {
|
||||
oa_message(qsTr("No address found"))
|
||||
}
|
||||
}
|
||||
}
|
||||
ListElement {
|
||||
address: ""
|
||||
amount: ""
|
||||
}
|
||||
|
||||
GridLayout {
|
||||
columns: appWindow.walletMode < 2 ? 1 : 2
|
||||
Layout.fillWidth: true
|
||||
columnSpacing: 32
|
||||
function newRecipient(address, amount) {
|
||||
if (recipientModel.count < maxRecipients) {
|
||||
recipientModel.append({address: address, amount: amount});
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.minimumWidth: 200
|
||||
function getRecipients() {
|
||||
var recipients = [];
|
||||
for (var index = 0; index < recipientModel.count; ++index) {
|
||||
const recipient = recipientModel.get(index);
|
||||
recipients.push({
|
||||
address: recipient.address,
|
||||
amount: recipient.amount,
|
||||
});
|
||||
}
|
||||
return recipients;
|
||||
}
|
||||
|
||||
// Amount input
|
||||
LineEdit {
|
||||
id: amountLine
|
||||
Layout.fillWidth: true
|
||||
inlineIcon: true
|
||||
labelText: "<style type='text/css'>a {text-decoration: none; color: #858585; font-size: 14px;}</style>\
|
||||
%1 <a href='#'>(%2)</a>".arg(qsTr("Amount")).arg(qsTr("Change account"))
|
||||
+ translationManager.emptyString
|
||||
copyButton: !isNaN(amountLine.text) && persistentSettings.fiatPriceEnabled
|
||||
copyButtonText: "~%1 %2".arg(fiatApiConvertToFiat(amountLine.text)).arg(fiatApiCurrencySymbol())
|
||||
copyButtonEnabled: false
|
||||
function getAmountTotal() {
|
||||
var sum = [];
|
||||
for (var index = 0; index < recipientModel.count; ++index) {
|
||||
const amount = recipientModel.get(index).amount;
|
||||
if (amount == "(all)") {
|
||||
return appWindow.getUnlockedBalance();
|
||||
}
|
||||
sum.push(amount || "0");
|
||||
}
|
||||
return walletManager.amountsSumFromStrings(sum);
|
||||
}
|
||||
|
||||
onLabelLinkActivated: {
|
||||
middlePanel.accountView.selectAndSend = true;
|
||||
appWindow.showPageRequest("Account")
|
||||
}
|
||||
placeholderText: "0.00"
|
||||
width: 100
|
||||
fontBold: true
|
||||
inlineButtonText: qsTr("All") + translationManager.emptyString
|
||||
inlineButton.onClicked: amountLine.text = "(all)"
|
||||
onTextChanged: {
|
||||
amountLine.text = amountLine.text.replace(",", ".");
|
||||
const match = amountLine.text.match(/^0+(\d.*)/);
|
||||
if (match) {
|
||||
const cursorPosition = amountLine.cursorPosition;
|
||||
amountLine.text = match[1];
|
||||
amountLine.cursorPosition = Math.max(cursorPosition, 1) - 1;
|
||||
} else if(amountLine.text.indexOf('.') === 0){
|
||||
amountLine.text = '0' + amountLine.text;
|
||||
if (amountLine.text.length > 2) {
|
||||
amountLine.cursorPosition = 1;
|
||||
function hasEmptyAmount() {
|
||||
for (var index = 0; index < recipientModel.count; ++index) {
|
||||
if (recipientModel.get(index).amount === "") {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function hasEmptyAddress() {
|
||||
for (var index = 0; index < recipientModel.count; ++index) {
|
||||
if (recipientModel.get(index).address === "") {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function hasInvalidAddress() {
|
||||
for (var index = 0; index < recipientModel.count; ++index) {
|
||||
if (!TxUtils.checkAddress(recipientModel.get(index).address, appWindow.persistentSettings.nettype)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
implicitHeight: recipientLayout.height
|
||||
|
||||
ColumnLayout {
|
||||
id: recipientLayout
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
spacing: 0
|
||||
|
||||
readonly property int colSpacing: 10
|
||||
readonly property int rowSpacing: 10
|
||||
readonly property int secondRowWidth: 125
|
||||
readonly property int thirdRowWidth: 50
|
||||
|
||||
RowLayout {
|
||||
Layout.bottomMargin: recipientLayout.rowSpacing / 2
|
||||
spacing: recipientLayout.colSpacing
|
||||
|
||||
RowLayout {
|
||||
id: addressLabel
|
||||
spacing: 6
|
||||
Layout.fillWidth: true
|
||||
|
||||
MoneroComponents.TextPlain {
|
||||
font.family: MoneroComponents.Style.fontRegular.name
|
||||
font.pixelSize: 16
|
||||
color: MoneroComponents.Style.defaultFontColor
|
||||
text: qsTr("Address") + translationManager.emptyString
|
||||
}
|
||||
|
||||
MoneroComponents.InlineButton {
|
||||
fontFamily: FontAwesome.fontFamilySolid
|
||||
fontStyleName: "Solid"
|
||||
fontPixelSize: 18
|
||||
text: FontAwesome.desktop
|
||||
tooltip: qsTr("Grab QR code from screen") + translationManager.emptyString
|
||||
onClicked: {
|
||||
clearFields();
|
||||
const codes = oshelper.grabQrCodesFromScreen();
|
||||
for (var index = 0; index < codes.length; ++index) {
|
||||
const parsed = walletManager.parse_uri_to_object(codes[index]);
|
||||
if (!parsed.error) {
|
||||
fillPaymentDetails(parsed.address, parsed.payment_id, parsed.amount, parsed.tx_description, parsed.recipient_name);
|
||||
break;
|
||||
} else if (walletManager.addressValid(codes[index], appWindow.persistentSettings.nettype)) {
|
||||
fillPaymentDetails(codes[index]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
amountLine.error = walletManager.amountFromString(amountLine.text) > appWindow.getUnlockedBalance()
|
||||
}
|
||||
|
||||
validator: RegExpValidator {
|
||||
regExp: /^(\d{1,8})?([\.,]\d{1,12})?$/
|
||||
}
|
||||
}
|
||||
MoneroComponents.InlineButton {
|
||||
fontFamily: FontAwesome.fontFamilySolid
|
||||
fontStyleName: "Solid"
|
||||
text: FontAwesome.qrcode
|
||||
visible: appWindow.qrScannerEnabled
|
||||
tooltip: qsTr("Scan QR code") + translationManager.emptyString
|
||||
onClicked: {
|
||||
cameraUi.state = "Capture"
|
||||
cameraUi.qrcode_decoded.connect(updateFromQrCode)
|
||||
}
|
||||
}
|
||||
|
||||
MoneroComponents.InlineButton {
|
||||
fontFamily: FontAwesome.fontFamily
|
||||
text: FontAwesome.addressBook
|
||||
tooltip: qsTr("Import from address book") + translationManager.emptyString
|
||||
onClicked: {
|
||||
middlePanel.addressBookView.selectAndSend = true;
|
||||
appWindow.showPageRequest("AddressBook");
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
id: amountLabel
|
||||
spacing: 6
|
||||
Layout.preferredWidth: 125
|
||||
Layout.maximumWidth: recipientLayout.secondRowWidth
|
||||
|
||||
MoneroComponents.TextPlain {
|
||||
font.family: MoneroComponents.Style.fontRegular.name
|
||||
font.pixelSize: 16
|
||||
color: MoneroComponents.Style.defaultFontColor
|
||||
text: qsTr("Amount") + translationManager.emptyString
|
||||
}
|
||||
|
||||
MoneroComponents.InlineButton {
|
||||
fontFamily: FontAwesome.fontFamilySolid
|
||||
fontStyleName: "Solid"
|
||||
fontPixelSize: 16
|
||||
text: FontAwesome.infinity
|
||||
visible: recipientModel.count == 1
|
||||
tooltip: qsTr("Send all unlocked balance of this account") + translationManager.emptyString
|
||||
onClicked: recipientRepeater.itemAt(0).children[1].children[2].text = "(all)";
|
||||
}
|
||||
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
Layout.preferredWidth: recipientLayout.thirdRowWidth
|
||||
}
|
||||
}
|
||||
|
||||
Repeater {
|
||||
id: recipientRepeater
|
||||
model: recipientModel
|
||||
|
||||
ColumnLayout {
|
||||
spacing: 0
|
||||
|
||||
Rectangle {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: -1
|
||||
Layout.leftMargin: 1
|
||||
Layout.rightMargin: recipientLayout.thirdRowWidth + 1
|
||||
color: MoneroComponents.Style.inputBorderColorInActive
|
||||
height: 1
|
||||
visible: index > 0
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
spacing: 0
|
||||
|
||||
MoneroComponents.LineEditMulti {
|
||||
KeyNavigation.backtab: index > 0 ? recipientRepeater.itemAt(index - 1).children[1].children[2] : sendButton
|
||||
KeyNavigation.tab: parent.children[2]
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
Layout.topMargin: index > 0 ? 0 : 1
|
||||
Layout.bottomMargin: 2
|
||||
Layout.fillWidth: true
|
||||
addressValidation: true
|
||||
borderDisabled: true
|
||||
fontColor: error && text != "" ? MoneroComponents.Style.errorColor : MoneroComponents.Style.defaultFontColor
|
||||
fontFamily: MoneroComponents.Style.fontMonoRegular.name
|
||||
fontSize: 14
|
||||
inputPaddingBottom: 0
|
||||
inputPaddingTop: 0
|
||||
inputPaddingRight: 0
|
||||
placeholderFontFamily: MoneroComponents.Style.fontMonoRegular.name
|
||||
placeholderFontSize: 14
|
||||
spacing: 0
|
||||
wrapMode: Text.WrapAnywhere
|
||||
placeholderText: {
|
||||
if(persistentSettings.nettype == NetworkType.MAINNET){
|
||||
return "4.. / 8.. / OpenAlias";
|
||||
} else if (persistentSettings.nettype == NetworkType.STAGENET){
|
||||
return "5.. / 7..";
|
||||
} else if(persistentSettings.nettype == NetworkType.TESTNET){
|
||||
return "9.. / B..";
|
||||
}
|
||||
}
|
||||
onTextChanged: {
|
||||
const parsed = walletManager.parse_uri_to_object(text);
|
||||
if (!parsed.error) {
|
||||
fillPaymentDetails(parsed.address, parsed.payment_id, parsed.amount, parsed.tx_description, parsed.recipient_name);
|
||||
}
|
||||
address = text;
|
||||
}
|
||||
text: address
|
||||
|
||||
MoneroComponents.InlineButton {
|
||||
small: true
|
||||
text: qsTr("Resolve") + translationManager.emptyString
|
||||
visible: TxUtils.isValidOpenAliasAddress(address)
|
||||
onClicked: {
|
||||
var result = walletManager.resolveOpenAlias(address)
|
||||
if (result) {
|
||||
var parts = result.split("|")
|
||||
if (parts.length == 2) {
|
||||
var address_ok = walletManager.addressValid(parts[1], appWindow.persistentSettings.nettype)
|
||||
if (parts[0] === "true") {
|
||||
if (address_ok) {
|
||||
// prepend openalias to description
|
||||
descriptionLine.text = descriptionLine.text ? address + " " + descriptionLine.text : address
|
||||
descriptionCheckbox.checked = true
|
||||
recipientRepeater.itemAt(index).children[1].children[0].text = parts[1];
|
||||
}
|
||||
else
|
||||
oa_message(qsTr("No valid address found at this OpenAlias address"))
|
||||
}
|
||||
else if (parts[0] === "false") {
|
||||
if (address_ok) {
|
||||
recipientRepeater.itemAt(index).children[1].children[0].text = parts[1];
|
||||
oa_message(qsTr("Address found, but the DNSSEC signatures could not be verified, so this address may be spoofed"))
|
||||
}
|
||||
else
|
||||
{
|
||||
oa_message(qsTr("No valid address found at this OpenAlias address, but the DNSSEC signatures could not be verified, so this may be spoofed"))
|
||||
}
|
||||
}
|
||||
else {
|
||||
oa_message(qsTr("Internal error"))
|
||||
}
|
||||
}
|
||||
else {
|
||||
oa_message(qsTr("Internal error"))
|
||||
}
|
||||
}
|
||||
else {
|
||||
oa_message(qsTr("No address found"))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
Layout.fillHeight: true
|
||||
Layout.topMargin: index > 0 ? 0 : 1
|
||||
Layout.bottomMargin: 1
|
||||
Layout.leftMargin: recipientLayout.colSpacing / 2 - width
|
||||
Layout.rightMargin: recipientLayout.colSpacing / 2
|
||||
color: MoneroComponents.Style.inputBorderColorInActive
|
||||
width: 1
|
||||
}
|
||||
|
||||
MoneroComponents.LineEdit {
|
||||
KeyNavigation.backtab: parent.children[0]
|
||||
KeyNavigation.tab: index + 1 < recipientRepeater.count ? recipientRepeater.itemAt(index + 1).children[1].children[0] : sendButton
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
Layout.topMargin: index > 0 ? 0 : 1
|
||||
Layout.bottomMargin: 2
|
||||
Layout.rightMargin: recipientLayout.colSpacing / 2
|
||||
Layout.preferredWidth: 125
|
||||
Layout.maximumWidth: 125
|
||||
borderDisabled: true
|
||||
fontFamily: MoneroComponents.Style.fontMonoRegular.name
|
||||
fontSize: 14
|
||||
inputPaddingLeft: 0
|
||||
inputPaddingRight: 0
|
||||
inputPaddingTop: 0
|
||||
inputPaddingBottom: 0
|
||||
placeholderFontFamily: MoneroComponents.Style.fontMonoRegular.name
|
||||
placeholderFontSize: 14
|
||||
placeholderLeftMargin: 0
|
||||
placeholderText: "0.00"
|
||||
text: amount
|
||||
onTextChanged: {
|
||||
text = text.trim().replace(",", ".");
|
||||
const match = text.match(/^0+(\d.*)/);
|
||||
if (match) {
|
||||
const cursorPosition = cursorPosition;
|
||||
text = match[1];
|
||||
cursorPosition = Math.max(cursorPosition, 1) - 1;
|
||||
} else if(text.indexOf('.') === 0){
|
||||
text = '0' + text;
|
||||
if (text.length > 2) {
|
||||
cursorPosition = 1;
|
||||
}
|
||||
}
|
||||
error = walletManager.amountFromString(text) > appWindow.getUnlockedBalance();
|
||||
|
||||
amount = text;
|
||||
}
|
||||
validator: RegExpValidator {
|
||||
regExp: /^\s*(\d{1,8})?([\.,]\d{1,12})?\s*$/
|
||||
}
|
||||
}
|
||||
|
||||
MoneroComponents.TextPlain {
|
||||
Layout.leftMargin: recipientLayout.colSpacing / 2
|
||||
Layout.preferredWidth: recipientLayout.thirdRowWidth
|
||||
font.family: FontAwesome.fontFamilySolid
|
||||
font.styleName: "Solid"
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
opacity: mouseArea.containsMouse ? 1 : 0.85
|
||||
text: FontAwesome.times
|
||||
tooltip: qsTr("Remove recipient") + translationManager.emptyString
|
||||
tooltipLeft: true
|
||||
visible: recipientModel.count > 1
|
||||
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
hoverEnabled: true
|
||||
onEntered: parent.tooltipPopup.open()
|
||||
onExited: parent.tooltipPopup.close()
|
||||
onClicked: recipientModel.remove(index);
|
||||
}
|
||||
}
|
||||
|
||||
MoneroComponents.TextPlain {
|
||||
Layout.leftMargin: recipientLayout.colSpacing / 2
|
||||
Layout.preferredWidth: recipientLayout.thirdRowWidth
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
font.family: MoneroComponents.Style.fontRegular.name
|
||||
text: "XMR"
|
||||
visible: recipientModel.count == 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GridLayout {
|
||||
id: totalLayout
|
||||
Layout.topMargin: recipientLayout.rowSpacing / 2
|
||||
Layout.fillWidth: true
|
||||
columns: 3
|
||||
columnSpacing: recipientLayout.colSpacing
|
||||
rowSpacing: 0
|
||||
|
||||
RowLayout {
|
||||
Layout.column: 0
|
||||
Layout.row: 0
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: recipientModel.count > 1 ? 0 : -1
|
||||
spacing: 0
|
||||
|
||||
CheckBox {
|
||||
border: false
|
||||
checked: false
|
||||
enabled: {
|
||||
if (recipientModel.count > 0 && recipientModel.get(0).amount == "(all)") {
|
||||
return false;
|
||||
}
|
||||
if (recipientModel.count >= recipientModel.maxRecipients) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
fontAwesomeIcons: true
|
||||
fontSize: descriptionLine.labelFontSize
|
||||
iconOnTheLeft: true
|
||||
text: qsTr("Add recipient") + translationManager.emptyString
|
||||
toggleOnClick: false
|
||||
uncheckedIcon: FontAwesome.plusCircle
|
||||
onClicked: {
|
||||
recipientModel.newRecipient("", "");
|
||||
}
|
||||
}
|
||||
|
||||
MoneroComponents.TextPlain {
|
||||
Layout.fillWidth: true
|
||||
horizontalAlignment: Text.AlignRight
|
||||
font.family: MoneroComponents.Style.fontRegular.name
|
||||
font.pixelSize: 16
|
||||
text: recipientModel.count > 1 ? qsTr("Total") + translationManager.emptyString : ""
|
||||
}
|
||||
}
|
||||
|
||||
MoneroComponents.LineEdit {
|
||||
id: totalValue
|
||||
Layout.column: 1
|
||||
Layout.row: 0
|
||||
Layout.preferredWidth: recipientLayout.secondRowWidth
|
||||
Layout.topMargin: recipientModel.count > 1 ? 0 : -1
|
||||
Layout.maximumWidth: recipientLayout.secondRowWidth
|
||||
borderDisabled: true
|
||||
fontFamily: MoneroComponents.Style.fontMonoRegular.name
|
||||
fontSize: 14
|
||||
inputHeight: 30
|
||||
inputPaddingLeft: 0
|
||||
inputPaddingRight: 0
|
||||
inputPaddingTop: 0
|
||||
inputPaddingBottom: 0
|
||||
readOnly: true
|
||||
text: Utils.removeTrailingZeros(walletManager.displayAmount(recipientModel.getAmountTotal()))
|
||||
visible: recipientModel.count > 1
|
||||
}
|
||||
|
||||
MoneroComponents.TextPlain {
|
||||
Layout.column: 2
|
||||
Layout.row: 0
|
||||
Layout.preferredWidth: recipientLayout.thirdRowWidth
|
||||
Layout.maximumWidth: recipientLayout.thirdRowWidth
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
font.family: MoneroComponents.Style.fontRegular.name
|
||||
text: "XMR"
|
||||
visible: recipientModel.count > 1
|
||||
}
|
||||
|
||||
MoneroComponents.LineEdit {
|
||||
Layout.column: 1
|
||||
Layout.row: recipientModel.count > 1 ? 1 : 0
|
||||
Layout.preferredWidth: recipientLayout.secondRowWidth
|
||||
Layout.topMargin: recipientModel.count > 1 ? 0 : -1
|
||||
Layout.maximumWidth: recipientLayout.secondRowWidth
|
||||
borderDisabled: true
|
||||
fontFamily: MoneroComponents.Style.fontMonoRegular.name
|
||||
fontSize: 14
|
||||
inputHeight: 30
|
||||
inputPaddingLeft: 0
|
||||
inputPaddingRight: 0
|
||||
inputPaddingTop: 0
|
||||
inputPaddingBottom: 0
|
||||
opacity: 0.7
|
||||
readOnly: true
|
||||
text: fiatApiConvertToFiat(walletManager.displayAmount(recipientModel.getAmountTotal()))
|
||||
visible: persistentSettings.fiatPriceEnabled
|
||||
}
|
||||
|
||||
MoneroComponents.TextPlain {
|
||||
Layout.column: 2
|
||||
Layout.row: recipientModel.count > 1 ? 1 : 0
|
||||
Layout.preferredWidth: recipientLayout.thirdRowWidth
|
||||
Layout.topMargin: recipientModel.count > 1 ? 0 : -1
|
||||
Layout.maximumWidth: recipientLayout.thirdRowWidth
|
||||
font.family: MoneroComponents.Style.fontRegular.name
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
opacity: 0.7
|
||||
text: fiatApiCurrencySymbol()
|
||||
visible: persistentSettings.fiatPriceEnabled
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors.top: recipientLayout.top
|
||||
anchors.topMargin: addressLabel.height + recipientLayout.rowSpacing / 2
|
||||
anchors.bottom: recipientLayout.bottom
|
||||
anchors.bottomMargin: totalLayout.height + recipientLayout.rowSpacing / 2
|
||||
anchors.left: recipientLayout.left
|
||||
anchors.right: recipientLayout.right
|
||||
anchors.rightMargin: recipientLayout.thirdRowWidth
|
||||
color: "transparent"
|
||||
border.color: MoneroComponents.Style.inputBorderColorInActive
|
||||
border.width: 1
|
||||
radius: 4
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
spacing: 0
|
||||
visible: appWindow.walletMode >= 2
|
||||
|
||||
// Note: workaround for translations in listElements
|
||||
// ListElement: cannot use script for property value, so
|
||||
// code like this wont work:
|
||||
// ListElement { column1: qsTr("LOW") + translationManager.emptyString ; column2: ""; priority: PendingTransaction.Priority_Low }
|
||||
// For translations to work, the strings need to be listed in
|
||||
// the file components/StandardDropdown.qml too.
|
||||
|
||||
// Priorites after v5
|
||||
ListModel {
|
||||
id: priorityModelV5
|
||||
|
||||
ListElement { column1: qsTr("Automatic") ; column2: ""; priority: 0}
|
||||
ListElement { column1: qsTr("Slow (x0.2 fee)") ; column2: ""; priority: 1}
|
||||
ListElement { column1: qsTr("Normal (x1 fee)") ; column2: ""; priority: 2 }
|
||||
ListElement { column1: qsTr("Fast (x5 fee)") ; column2: ""; priority: 3 }
|
||||
ListElement { column1: qsTr("Fastest (x200 fee)") ; column2: ""; priority: 4 }
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Layout.topMargin: 5
|
||||
spacing: 10
|
||||
|
||||
StandardDropdown {
|
||||
Layout.maximumWidth: 200
|
||||
id: priorityDropdown
|
||||
currentIndex: 0
|
||||
dataModel: priorityModelV5
|
||||
labelText: qsTr("Transaction priority") + translationManager.emptyString
|
||||
labelFontSize: 16
|
||||
}
|
||||
|
||||
MoneroComponents.TextPlain {
|
||||
id: feeLabel
|
||||
Layout.alignment: Qt.AlignRight
|
||||
Layout.topMargin: 12
|
||||
Layout.alignment: Qt.AlignBottom
|
||||
Layout.bottomMargin: 11
|
||||
font.family: MoneroComponents.Style.fontRegular.name
|
||||
font.pixelSize: 14
|
||||
color: MoneroComponents.Style.defaultFontColor
|
||||
opacity: 0.7
|
||||
property bool estimating: false
|
||||
property var estimatedFee: null
|
||||
property string estimatedFeeFiat: {
|
||||
@@ -338,12 +729,21 @@ Rectangle {
|
||||
if (!sendButton.enabled || !currentWallet) {
|
||||
return;
|
||||
}
|
||||
var addresses = [];
|
||||
var amounts = [];
|
||||
for (var index = 0; index < recipientModel.count; ++index) {
|
||||
const recipient = recipientModel.get(index);
|
||||
addresses.push(recipient.address);
|
||||
amounts.push(walletManager.amountFromString(recipient.amount));
|
||||
}
|
||||
currentWallet.estimateTransactionFeeAsync(
|
||||
addressLine.text,
|
||||
walletManager.amountFromString(amountLine.text),
|
||||
addresses,
|
||||
amounts,
|
||||
priorityModelV5.get(priorityDropdown.currentIndex).priority,
|
||||
function (amount) {
|
||||
estimatedFee = Utils.removeTrailingZeros(amount);
|
||||
if (amount) {
|
||||
estimatedFee = Utils.removeTrailingZeros(amount);
|
||||
}
|
||||
estimating = false;
|
||||
});
|
||||
}
|
||||
@@ -351,56 +751,20 @@ Rectangle {
|
||||
if (!sendButton.enabled || estimatedFee == null) {
|
||||
return ""
|
||||
}
|
||||
return "%1: ~%2 XMR".arg(qsTr("Fee")).arg(estimatedFee) +
|
||||
estimatedFeeFiat +
|
||||
translationManager.emptyString;
|
||||
return "~%1 XMR%2 %3".arg(estimatedFee)
|
||||
.arg(estimatedFeeFiat)
|
||||
.arg(qsTr("fee") + translationManager.emptyString);
|
||||
}
|
||||
|
||||
BusyIndicator {
|
||||
anchors.right: parent.right
|
||||
anchors.left: parent.left
|
||||
running: feeLabel.estimating
|
||||
height: parent.height
|
||||
width: height
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
visible: appWindow.walletMode >= 2
|
||||
Layout.alignment: Qt.AlignTop
|
||||
Label {
|
||||
id: transactionPriority
|
||||
Layout.topMargin: 0
|
||||
text: qsTr("Transaction priority") + translationManager.emptyString
|
||||
fontBold: false
|
||||
fontSize: 16
|
||||
}
|
||||
// Note: workaround for translations in listElements
|
||||
// ListElement: cannot use script for property value, so
|
||||
// code like this wont work:
|
||||
// ListElement { column1: qsTr("LOW") + translationManager.emptyString ; column2: ""; priority: PendingTransaction.Priority_Low }
|
||||
// For translations to work, the strings need to be listed in
|
||||
// the file components/StandardDropdown.qml too.
|
||||
|
||||
// Priorites after v5
|
||||
ListModel {
|
||||
id: priorityModelV5
|
||||
|
||||
ListElement { column1: qsTr("Automatic") ; column2: ""; priority: 0}
|
||||
ListElement { column1: qsTr("Slow (x0.2 fee)") ; column2: ""; priority: 1}
|
||||
ListElement { column1: qsTr("Normal (x1 fee)") ; column2: ""; priority: 2 }
|
||||
ListElement { column1: qsTr("Fast (x5 fee)") ; column2: ""; priority: 3 }
|
||||
ListElement { column1: qsTr("Fastest (x200 fee)") ; column2: ""; priority: 4 }
|
||||
}
|
||||
|
||||
StandardDropdown {
|
||||
Layout.preferredWidth: 200
|
||||
id: priorityDropdown
|
||||
Layout.topMargin: 5
|
||||
currentIndex: 0
|
||||
dataModel: priorityModelV5
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MoneroComponents.WarningBox {
|
||||
text: qsTr("Description field contents match long payment ID format. \
|
||||
@@ -429,9 +793,11 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
|
||||
LineEditMulti {
|
||||
LineEdit {
|
||||
id: descriptionLine
|
||||
placeholderText: qsTr("Saved to local wallet history") + translationManager.emptyString
|
||||
placeholderFontSize: 16
|
||||
fontSize: 16
|
||||
placeholderText: qsTr("Saved to local wallet history") + " (" + qsTr("only visible to you") + ")" + translationManager.emptyString
|
||||
Layout.fillWidth: true
|
||||
visible: descriptionCheckbox.checked
|
||||
}
|
||||
@@ -492,21 +858,21 @@ Rectangle {
|
||||
rightIconInactive: "qrc:///images/rightArrowInactive.png"
|
||||
Layout.topMargin: 4
|
||||
text: qsTr("Send") + translationManager.emptyString
|
||||
enabled: !sendButtonWarningBox.visible && !warningContent && addressLine.text && !paymentIdWarningBox.visible
|
||||
enabled: !sendButtonWarningBox.visible && !warningContent && !recipientModel.hasEmptyAddress() && !paymentIdWarningBox.visible
|
||||
onClicked: {
|
||||
console.log("Transfer: paymentClicked")
|
||||
var priority = priorityModelV5.get(priorityDropdown.currentIndex).priority
|
||||
console.log("priority: " + priority)
|
||||
console.log("amount: " + amountLine.text)
|
||||
addressLine.text = addressLine.text.trim()
|
||||
setPaymentId(paymentIdLine.text.trim());
|
||||
root.paymentClicked(addressLine.text, paymentIdLine.text, amountLine.text, root.mixin, priority, descriptionLine.text)
|
||||
root.paymentClicked(recipientModel.getRecipients(), paymentIdLine.text, root.mixin, priority, descriptionLine.text)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function checkInformation(amount, address, nettype) {
|
||||
return amount.length > 0 && walletManager.amountFromString(amountLine.text) <= appWindow.getUnlockedBalance() && TxUtils.checkAddress(address, nettype)
|
||||
function checkInformation() {
|
||||
return !recipientModel.hasEmptyAmount() &&
|
||||
recipientModel.getAmountTotal() <= appWindow.getUnlockedBalance() &&
|
||||
!recipientModel.hasInvalidAddress();
|
||||
}
|
||||
|
||||
} // pageRoot
|
||||
@@ -547,34 +913,32 @@ Rectangle {
|
||||
console.log("Transfer: import key images clicked")
|
||||
importKeyImagesDialog.open();
|
||||
}
|
||||
helpTextLarge.text: qsTr("Required for view-only wallets to display the real balance") + translationManager.emptyString
|
||||
helpTextSmall.text: {
|
||||
tooltip: {
|
||||
var errorMessage = "";
|
||||
if (appWindow.viewOnly && !appWindow.isTrustedDaemon()){
|
||||
errorMessage = "<p class='orange'>" + qsTr("* To import, you must connect to a local node or a trusted remote node") + "</p>";
|
||||
}
|
||||
return "<style type='text/css'>p{line-height:20px; margin-top:0px; margin-bottom:0px; color:" + MoneroComponents.Style.defaultFontColor +
|
||||
var header = qsTr("Required for view-only wallets to display the real balance") + translationManager.emptyString;
|
||||
return "<style type='text/css'>.header{ font-size: 13px; } p{line-height:20px; margin-top:0px; margin-bottom:0px; " +
|
||||
";} p.orange{color:#ff9323;}</style>" +
|
||||
"<div class='header'>" + header + "</div>" +
|
||||
"<p>" + qsTr("1. Using cold wallet, export the key images into a file") + "</p>" +
|
||||
"<p>" + qsTr("2. Using view-only wallet, import the key images file") + "</p>" +
|
||||
errorMessage + translationManager.emptyString
|
||||
}
|
||||
helpTextSmall.themeTransition: false
|
||||
}
|
||||
|
||||
|
||||
AdvancedOptionsItem {
|
||||
visible: persistentSettings.transferShowAdvanced && appWindow.walletMode >= 2
|
||||
title: qsTr("Offline transaction signing") + translationManager.emptyString
|
||||
button1.text: qsTr("Create") + translationManager.emptyString
|
||||
button1.enabled: appWindow.viewOnly && pageRoot.checkInformation(amountLine.text, addressLine.text, appWindow.persistentSettings.nettype)
|
||||
button1.enabled: appWindow.viewOnly && pageRoot.checkInformation()
|
||||
button1.onClicked: {
|
||||
console.log("Transfer: saveTx Clicked")
|
||||
var priority = priorityModelV5.get(priorityDropdown.currentIndex).priority
|
||||
console.log("priority: " + priority)
|
||||
console.log("amount: " + amountLine.text)
|
||||
addressLine.text = addressLine.text.trim()
|
||||
setPaymentId(paymentIdLine.text.trim());
|
||||
root.paymentClicked(addressLine.text, paymentIdLine.text, amountLine.text, root.mixin, priority, descriptionLine.text)
|
||||
root.paymentClicked(recipientModel.getRecipients(), paymentIdLine.text, root.mixin, priority, descriptionLine.text)
|
||||
}
|
||||
button2.text: qsTr("Sign (offline)") + translationManager.emptyString
|
||||
button2.enabled: !appWindow.viewOnly
|
||||
@@ -588,14 +952,15 @@ Rectangle {
|
||||
console.log("Transfer: submit tx clicked")
|
||||
submitTxDialog.open();
|
||||
}
|
||||
helpTextLarge.text: qsTr("Spend XMR from a cold (offline) wallet") + translationManager.emptyString
|
||||
helpTextSmall.text: {
|
||||
tooltip: {
|
||||
var errorMessage = "";
|
||||
if (appWindow.viewOnly && !pageRoot.checkInformation(amountLine.text, addressLine.text, appWindow.persistentSettings.nettype)){
|
||||
if (appWindow.viewOnly && !pageRoot.checkInformation()) {
|
||||
errorMessage = "<p class='orange'>" + qsTr("* To create a transaction file, please enter address and amount above") + "</p>";
|
||||
}
|
||||
return "<style type='text/css'>p{line-height:20px; margin-top:0px; margin-bottom:0px; color:" + MoneroComponents.Style.defaultFontColor +
|
||||
var header = qsTr("Spend XMR from a cold (offline) wallet") + translationManager.emptyString;
|
||||
return "<style type='text/css'>.header{ font-size: 13px; } p{line-height:20px; margin-top:0px; margin-bottom:0px; " +
|
||||
";} p.orange{color:#ff9323;}</style>" +
|
||||
"<div class='header'>" + header + "</div>" +
|
||||
"<p>" + qsTr("1. Using view-only wallet, export the outputs into a file") + "</p>" +
|
||||
"<p>" + qsTr("2. Using cold wallet, import the outputs file and export the key images") + "</p>" +
|
||||
"<p>" + qsTr("3. Using view-only wallet, import the key images file and create a transaction file") + "</p>" +
|
||||
@@ -603,7 +968,6 @@ Rectangle {
|
||||
"<p>" + qsTr("4. Using cold wallet, sign your transaction file") + "</p>" +
|
||||
"<p>" + qsTr("5. Using view-only wallet, submit your signed transaction") + "</p>" + translationManager.emptyString
|
||||
}
|
||||
helpTextSmall.themeTransition: false
|
||||
}
|
||||
|
||||
AdvancedOptionsItem {
|
||||
@@ -615,7 +979,7 @@ Rectangle {
|
||||
console.log("Transfer: sweepUnmixableClicked")
|
||||
root.sweepUnmixableClicked()
|
||||
}
|
||||
helpTextLarge.text: qsTr("Create a transaction that spends old unmovable outputs") + translationManager.emptyString
|
||||
tooltip: qsTr("Create a transaction that spends old unmovable outputs") + translationManager.emptyString
|
||||
}
|
||||
}
|
||||
|
||||
@@ -792,19 +1156,9 @@ Rectangle {
|
||||
}
|
||||
|
||||
// Popuplate fields from addressbook.
|
||||
function sendTo(address, paymentId, description, amount){
|
||||
function sendTo(address, paymentId, description, amount) {
|
||||
middlePanel.state = 'Transfer';
|
||||
|
||||
if(typeof address !== 'undefined')
|
||||
addressLine.text = address
|
||||
|
||||
if(typeof paymentId !== 'undefined')
|
||||
setPaymentId(paymentId);
|
||||
|
||||
if(typeof description !== 'undefined')
|
||||
setDescription(description);
|
||||
|
||||
if(typeof amount !== 'undefined')
|
||||
amountLine.text = amount;
|
||||
fillPaymentDetails(address, paymentId, amount, description);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ Rectangle {
|
||||
ColumnLayout {
|
||||
id: mainLayout
|
||||
anchors.margins: 20
|
||||
anchors.topMargin: 40
|
||||
anchors.topMargin: 0
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.top
|
||||
anchors.right: parent.right
|
||||
@@ -116,7 +116,7 @@ Rectangle {
|
||||
enabled: TxUtils.checkTxID(getProofTxIdLine.text) && (getProofAddressLine.text.length == 0 || TxUtils.checkAddress(getProofAddressLine.text, appWindow.persistentSettings.nettype))
|
||||
onClicked: {
|
||||
console.log("getProof: Generate clicked: txid " + getProofTxIdLine.text + ", address " + getProofAddressLine.text + ", message: " + getProofMessageLine.text);
|
||||
root.getProofClicked(getProofTxIdLine.text, getProofAddressLine.text, getProofMessageLine.text)
|
||||
middlePanel.getProofClicked(getProofTxIdLine.text, getProofAddressLine.text, getProofMessageLine.text)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -201,7 +201,7 @@ Rectangle {
|
||||
enabled: TxUtils.checkTxID(checkProofTxIdLine.text) && TxUtils.checkSignature(checkProofSignatureLine.text) && ((checkProofSignatureLine.text.indexOf("SpendProofV") === 0 && checkProofAddressLine.text.length == 0) || (checkProofSignatureLine.text.indexOf("SpendProofV") !== 0 && TxUtils.checkAddress(checkProofAddressLine.text, appWindow.persistentSettings.nettype)))
|
||||
onClicked: {
|
||||
console.log("checkProof: Check clicked: txid " + checkProofTxIdLine.text + ", address " + checkProofAddressLine.text + ", message " + checkProofMessageLine.text + ", signature " + checkProofSignatureLine.text);
|
||||
root.checkProofClicked(checkProofTxIdLine.text, checkProofAddressLine.text, checkProofMessageLine.text, checkProofSignatureLine.text)
|
||||
middlePanel.checkProofClicked(checkProofTxIdLine.text, checkProofAddressLine.text, checkProofMessageLine.text, checkProofSignatureLine.text)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ Item {
|
||||
|
||||
function onPageCompleted() {
|
||||
if (appWindow.currentWallet) {
|
||||
appWindow.current_address = appWindow.currentWallet.address(appWindow.currentWallet.currentSubaddressAccount, 0)
|
||||
appWindow.current_address = appWindow.currentWallet.address(appWindow.currentWallet.currentSubaddressAccount, appWindow.current_subaddress_table_index);
|
||||
}
|
||||
// prepare tracking
|
||||
trackingCheckbox.checked = root.enableTracking
|
||||
|
||||
@@ -1,423 +0,0 @@
|
||||
// Copyright (c) 2014-2018, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import QtQuick 2.9
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Controls.Styles 1.4
|
||||
import QtQuick.Layouts 1.1
|
||||
import QtQuick.Dialogs 1.2
|
||||
import "../../js/Windows.js" as Windows
|
||||
import "../../js/Utils.js" as Utils
|
||||
import "../../components" as MoneroComponents
|
||||
import "../../pages"
|
||||
import "."
|
||||
import moneroComponents.Clipboard 1.0
|
||||
|
||||
Rectangle {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 96
|
||||
color: "transparent"
|
||||
|
||||
ColumnLayout {
|
||||
spacing: 0
|
||||
Layout.preferredHeight: 32
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
GridLayout {
|
||||
id: grid
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
columnSpacing: 0
|
||||
property string fontColorActive: MoneroComponents.Style.blackTheme ? "white" : "white"
|
||||
property string fontColorInActive: MoneroComponents.Style.blackTheme ? "white" : MoneroComponents.Style.dimmedFontColor
|
||||
property int fontSize: 15
|
||||
property bool fontBold: true
|
||||
property var fontFamily: MoneroComponents.Style.fontRegular.name
|
||||
property string borderColor: MoneroComponents.Style.blackTheme ? "#808080" : "#B9B9B9"
|
||||
property int textMargin: {
|
||||
// left-right margins for a given cell
|
||||
if(appWindow.width < 890){
|
||||
return 32;
|
||||
} else {
|
||||
return 64;
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
// navbar left side border
|
||||
id: navBarLeft
|
||||
property bool isActive: settingsStateView.state === "Wallet"
|
||||
Layout.preferredWidth: 2
|
||||
Layout.preferredHeight: 32
|
||||
color: "transparent"
|
||||
|
||||
Rectangle {
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: 1
|
||||
height: parent.height - 2
|
||||
color: grid.borderColor
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.right: parent.right
|
||||
width: 1
|
||||
spacing: 0
|
||||
|
||||
Rectangle {
|
||||
Layout.preferredHeight: 1
|
||||
Layout.preferredWidth: 1
|
||||
color: grid.borderColor
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
Layout.fillHeight: true
|
||||
width: 1
|
||||
color: navBarLeft.isActive ? grid.borderColor : "transparent"
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
color: grid.borderColor
|
||||
Layout.preferredHeight: 1
|
||||
Layout.preferredWidth: 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
// WALLET
|
||||
id: navWallet
|
||||
property bool isActive: settingsStateView.state === "Wallet"
|
||||
Layout.preferredWidth: navWalletText.width + grid.textMargin
|
||||
Layout.minimumWidth: 72
|
||||
Layout.preferredHeight: 32
|
||||
spacing: 0
|
||||
|
||||
Rectangle {
|
||||
color: grid.borderColor
|
||||
Layout.preferredHeight: 1
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
color: parent.isActive ? grid.borderColor : "transparent"
|
||||
height: 30
|
||||
Layout.fillWidth: true
|
||||
|
||||
MoneroComponents.TextPlain {
|
||||
id: navWalletText
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
font.family: grid.fontFamily
|
||||
font.pixelSize: grid.fontSize
|
||||
font.bold: grid.fontBold
|
||||
text: qsTr("Wallet") + translationManager.emptyString
|
||||
color: navWallet.isActive ? grid.fontColorActive : grid.fontColorInActive
|
||||
themeTransition: false
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
|
||||
onClicked: { settingsStateView.state = "Wallet" }
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
color: grid.borderColor
|
||||
Layout.preferredHeight: 1
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
}
|
||||
Rectangle{
|
||||
Layout.preferredWidth: 1
|
||||
Layout.preferredHeight: 32
|
||||
color: grid.borderColor
|
||||
}
|
||||
ColumnLayout {
|
||||
// UI
|
||||
id: navUI
|
||||
property bool isActive: settingsStateView.state === "UI"
|
||||
Layout.preferredWidth: navUIText.width + grid.textMargin
|
||||
Layout.preferredHeight: 32
|
||||
Layout.minimumWidth: 72
|
||||
spacing: 0
|
||||
|
||||
Rectangle {
|
||||
color: grid.borderColor
|
||||
Layout.preferredHeight: 1
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
color: parent.isActive ? grid.borderColor : "transparent"
|
||||
height: 30
|
||||
Layout.fillWidth: true
|
||||
|
||||
MoneroComponents.TextPlain {
|
||||
id: navUIText
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
font.family: grid.fontFamily
|
||||
font.pixelSize: grid.fontSize
|
||||
font.bold: grid.fontBold
|
||||
text: qsTr("Interface") + translationManager.emptyString
|
||||
color: navUI.isActive ? grid.fontColorActive : grid.fontColorInActive
|
||||
themeTransition: false
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
|
||||
onClicked: { settingsStateView.state = "UI" }
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
color: grid.borderColor
|
||||
Layout.preferredHeight: 1
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
}
|
||||
Rectangle{
|
||||
Layout.preferredWidth: 1
|
||||
Layout.preferredHeight: 32
|
||||
color: grid.borderColor
|
||||
}
|
||||
ColumnLayout {
|
||||
// NODE
|
||||
id: navNode
|
||||
property bool isActive: settingsStateView.state === "Node"
|
||||
visible: appWindow.walletMode >= 2
|
||||
Layout.preferredWidth: navNodeText.width + grid.textMargin
|
||||
Layout.preferredHeight: 32
|
||||
Layout.minimumWidth: 72
|
||||
spacing: 0
|
||||
|
||||
Rectangle {
|
||||
color: grid.borderColor
|
||||
Layout.preferredHeight: 1
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
color: parent.isActive ? grid.borderColor : "transparent"
|
||||
height: 30
|
||||
Layout.fillWidth: true
|
||||
|
||||
MoneroComponents.TextPlain {
|
||||
id: navNodeText
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
font.family: grid.fontFamily
|
||||
font.pixelSize: grid.fontSize
|
||||
font.bold: grid.fontBold
|
||||
text: qsTr("Node") + translationManager.emptyString
|
||||
color: navNode.isActive ? grid.fontColorActive : grid.fontColorInActive
|
||||
themeTransition: false
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
|
||||
onClicked: { settingsStateView.state = "Node" }
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
color: grid.borderColor
|
||||
Layout.preferredHeight: 1
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
}
|
||||
Rectangle{
|
||||
visible: appWindow.walletMode >= 2
|
||||
Layout.preferredWidth: 1
|
||||
Layout.preferredHeight: 32
|
||||
color: grid.borderColor
|
||||
}
|
||||
ColumnLayout {
|
||||
// LOG
|
||||
id: navLog
|
||||
property bool isActive: settingsStateView.state === "Log"
|
||||
Layout.preferredWidth: navLogText.width + grid.textMargin
|
||||
Layout.preferredHeight: 32
|
||||
Layout.minimumWidth: 72
|
||||
spacing: 0
|
||||
|
||||
Rectangle {
|
||||
color: grid.borderColor
|
||||
Layout.preferredHeight: 1
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
color: parent.isActive ? grid.borderColor : "transparent"
|
||||
height: 30
|
||||
Layout.fillWidth: true
|
||||
|
||||
MoneroComponents.TextPlain {
|
||||
id: navLogText
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
font.family: grid.fontFamily
|
||||
font.pixelSize: grid.fontSize
|
||||
font.bold: grid.fontBold
|
||||
text: qsTr("Log") + translationManager.emptyString
|
||||
color: navLog.isActive ? grid.fontColorActive : grid.fontColorInActive
|
||||
themeTransition: false
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
|
||||
onClicked: { settingsStateView.state = "Log" }
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
color: grid.borderColor
|
||||
Layout.preferredHeight: 1
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
}
|
||||
Rectangle{
|
||||
visible: appWindow.walletMode >= 2
|
||||
Layout.preferredWidth: 1
|
||||
Layout.preferredHeight: 32
|
||||
color: grid.borderColor
|
||||
}
|
||||
ColumnLayout {
|
||||
// INFO
|
||||
id: navInfo
|
||||
property bool isActive: settingsStateView.state === "Info"
|
||||
Layout.preferredWidth: navInfoText.width + grid.textMargin
|
||||
Layout.preferredHeight: 32
|
||||
Layout.minimumWidth: 72
|
||||
spacing: 0
|
||||
|
||||
Rectangle {
|
||||
color: grid.borderColor
|
||||
Layout.preferredHeight: 1
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
color: parent.isActive ? grid.borderColor : "transparent"
|
||||
height: 30
|
||||
Layout.fillWidth: true
|
||||
|
||||
MoneroComponents.TextPlain {
|
||||
id: navInfoText
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
font.family: grid.fontFamily
|
||||
font.pixelSize: grid.fontSize
|
||||
font.bold: grid.fontBold
|
||||
text: qsTr("Info") + translationManager.emptyString
|
||||
color: navInfo.isActive ? grid.fontColorActive : grid.fontColorInActive
|
||||
themeTransition: false
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
|
||||
onClicked: { settingsStateView.state = "Info" }
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
color: grid.borderColor
|
||||
Layout.preferredHeight: 1
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
// navbar right side border
|
||||
id: navBarRight
|
||||
property bool isActive: settingsStateView.state === "Info"
|
||||
Layout.preferredWidth: 2
|
||||
Layout.preferredHeight: 32
|
||||
color: "transparent"
|
||||
rotation: 180
|
||||
|
||||
Rectangle {
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: 1
|
||||
height: parent.height - 2
|
||||
color: grid.borderColor
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.right: parent.right
|
||||
width: 1
|
||||
spacing: 0
|
||||
|
||||
Rectangle {
|
||||
Layout.preferredHeight: 1
|
||||
Layout.preferredWidth: 1
|
||||
color: grid.borderColor
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
Layout.fillHeight: true
|
||||
width: 1
|
||||
color: navBarRight.isActive ? grid.borderColor : "transparent"
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
color: grid.borderColor
|
||||
Layout.preferredHeight: 1
|
||||
Layout.preferredWidth: 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
color: "transparent"
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -48,7 +48,38 @@ ColumnLayout {
|
||||
property int settingsHeight: 900
|
||||
property alias settingsStateViewState: settingsStateView.state
|
||||
|
||||
Navbar{}
|
||||
MoneroComponents.Navbar {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.topMargin: height
|
||||
Layout.bottomMargin: height
|
||||
|
||||
MoneroComponents.NavbarItem {
|
||||
active: settingsStateView.state == "Wallet"
|
||||
text: qsTr("Wallet") + translationManager.emptyString
|
||||
onSelected: settingsStateView.state = "Wallet"
|
||||
}
|
||||
MoneroComponents.NavbarItem {
|
||||
active: settingsStateView.state == "UI"
|
||||
text: qsTr("Interface") + translationManager.emptyString
|
||||
onSelected: settingsStateView.state = "UI"
|
||||
}
|
||||
MoneroComponents.NavbarItem {
|
||||
active: settingsStateView.state == "Node"
|
||||
text: qsTr("Node") + translationManager.emptyString
|
||||
visible: appWindow.walletMode >= 2
|
||||
onSelected: settingsStateView.state = "Node"
|
||||
}
|
||||
MoneroComponents.NavbarItem {
|
||||
active: settingsStateView.state == "Log"
|
||||
text: qsTr("Log") + translationManager.emptyString
|
||||
onSelected: settingsStateView.state = "Log"
|
||||
}
|
||||
MoneroComponents.NavbarItem {
|
||||
active: settingsStateView.state == "Info"
|
||||
text: qsTr("Info") + translationManager.emptyString
|
||||
onSelected: settingsStateView.state = "Info"
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle{
|
||||
id: settingsStateView
|
||||
|
||||
@@ -42,13 +42,15 @@ Rectangle {
|
||||
Layout.fillWidth: true
|
||||
property alias infoHeight: infoLayout.height
|
||||
property string walletModeString: {
|
||||
var modeStr;
|
||||
if(appWindow.walletMode === 0){
|
||||
return qsTr("Simple mode") + translationManager.emptyString;
|
||||
modeStr = qsTr("Simple mode") + translationManager.emptyString;
|
||||
} else if(appWindow.walletMode === 1){
|
||||
return qsTr("Simple mode") + " (bootstrap)" + translationManager.emptyString;
|
||||
modeStr = qsTr("Simple mode") + " (bootstrap)" + translationManager.emptyString;
|
||||
} else if(appWindow.walletMode === 2){
|
||||
return "%1 (%2)".arg(qsTr("Advanced mode")).arg(persistentSettings.useRemoteNode ? qsTr("Remote node") : qsTr("Local node")) + translationManager.emptyString;
|
||||
modeStr = "%1 (%2)".arg(qsTr("Advanced mode")).arg(persistentSettings.useRemoteNode ? qsTr("Remote node") : qsTr("Local node")) + translationManager.emptyString;
|
||||
}
|
||||
return modeStr + (persistentSettings.portable ? ", %1".arg(qsTr("portable")) : "");
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
@@ -189,13 +191,7 @@ Rectangle {
|
||||
inputDialog.onAcceptedCallback = function() {
|
||||
var _restoreHeight;
|
||||
if (inputDialog.inputText) {
|
||||
var restoreHeightText = inputDialog.inputText;
|
||||
// Parse date string or restore height as integer
|
||||
if(restoreHeightText.indexOf('-') === 4 && restoreHeightText.length === 10) {
|
||||
_restoreHeight = Wizard.getApproximateBlockchainHeight(restoreHeightText, Utils.netTypeToString());
|
||||
} else {
|
||||
_restoreHeight = parseInt(restoreHeightText)
|
||||
}
|
||||
_restoreHeight = Utils.parseDateStringOrRestoreHeightAsInteger(inputDialog.inputText);
|
||||
}
|
||||
if (!isNaN(_restoreHeight)) {
|
||||
if(_restoreHeight >= 0) {
|
||||
@@ -399,9 +395,9 @@ Rectangle {
|
||||
|
||||
data += "\nWallet log path: " + logger.logFilePath;
|
||||
data += "\nWallet mode: " + walletModeString;
|
||||
data += "\nGraphics mode: " + isOpenGL ? "OpenGL" : "Low graphics mode";
|
||||
data += "\nGraphics mode: " + (isOpenGL ? "OpenGL" : "Low graphics mode");
|
||||
if (isTails)
|
||||
data += "\nTails: " + tailsUsePersistence ? "persistent" : "persistence disabled";
|
||||
data += "\nTails: " + (tailsUsePersistence ? "persistent" : "persistence disabled");
|
||||
|
||||
console.log("Copied to clipboard");
|
||||
clipboard.setText(data);
|
||||
|
||||
@@ -66,6 +66,12 @@ Rectangle {
|
||||
text: qsTr("Check for updates periodically") + translationManager.emptyString
|
||||
}
|
||||
|
||||
MoneroComponents.CheckBox {
|
||||
checked: persistentSettings.displayWalletNameInTitleBar
|
||||
onClicked: persistentSettings.displayWalletNameInTitleBar = !persistentSettings.displayWalletNameInTitleBar
|
||||
text: qsTr("Display wallet name in title bar") + translationManager.emptyString
|
||||
}
|
||||
|
||||
MoneroComponents.CheckBox {
|
||||
id: hideBalanceCheckBox
|
||||
checked: persistentSettings.hideBalance
|
||||
@@ -83,7 +89,6 @@ Rectangle {
|
||||
toggleOnClick: false
|
||||
onClicked: {
|
||||
MoneroComponents.Style.blackTheme = !MoneroComponents.Style.blackTheme;
|
||||
persistentSettings.blackTheme = MoneroComponents.Style.blackTheme;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -173,52 +178,34 @@ Rectangle {
|
||||
Layout.leftMargin: 36
|
||||
columnSpacing: 32
|
||||
|
||||
ColumnLayout {
|
||||
spacing: 10
|
||||
Layout.fillWidth: true
|
||||
MoneroComponents.StandardDropdown {
|
||||
id: fiatPriceProviderDropDown
|
||||
Layout.maximumWidth: 200
|
||||
labelText: qsTr("Price source") + translationManager.emptyString
|
||||
labelFontSize: 14
|
||||
dataModel: fiatPriceProvidersModel
|
||||
onChanged: {
|
||||
var obj = dataModel.get(currentIndex);
|
||||
persistentSettings.fiatPriceProvider = obj.data;
|
||||
|
||||
MoneroComponents.Label {
|
||||
Layout.fillWidth: true
|
||||
fontSize: 14
|
||||
text: qsTr("Price source") + translationManager.emptyString
|
||||
}
|
||||
|
||||
MoneroComponents.StandardDropdown {
|
||||
id: fiatPriceProviderDropDown
|
||||
Layout.fillWidth: true
|
||||
dataModel: fiatPriceProvidersModel
|
||||
onChanged: {
|
||||
var obj = dataModel.get(currentIndex);
|
||||
persistentSettings.fiatPriceProvider = obj.data;
|
||||
|
||||
if(persistentSettings.fiatPriceEnabled)
|
||||
appWindow.fiatApiRefresh();
|
||||
}
|
||||
if(persistentSettings.fiatPriceEnabled)
|
||||
appWindow.fiatApiRefresh();
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
spacing: 10
|
||||
Layout.fillWidth: true
|
||||
MoneroComponents.StandardDropdown {
|
||||
id: fiatPriceCurrencyDropdown
|
||||
Layout.maximumWidth: 100
|
||||
labelText: qsTr("Currency") + translationManager.emptyString
|
||||
labelFontSize: 14
|
||||
currentIndex: persistentSettings.fiatPriceCurrency === "xmrusd" ? 0 : 1
|
||||
dataModel: fiatPriceCurrencyModel
|
||||
onChanged: {
|
||||
var obj = dataModel.get(currentIndex);
|
||||
persistentSettings.fiatPriceCurrency = obj.data;
|
||||
|
||||
MoneroComponents.Label {
|
||||
Layout.fillWidth: true
|
||||
fontSize: 14
|
||||
text: qsTr("Currency") + translationManager.emptyString
|
||||
}
|
||||
|
||||
MoneroComponents.StandardDropdown {
|
||||
id: fiatPriceCurrencyDropdown
|
||||
Layout.fillWidth: true
|
||||
currentIndex: persistentSettings.fiatPriceCurrency === "xmrusd" ? 0 : 1
|
||||
dataModel: fiatPriceCurrencyModel
|
||||
onChanged: {
|
||||
var obj = dataModel.get(currentIndex);
|
||||
persistentSettings.fiatPriceCurrency = obj.data;
|
||||
|
||||
if(persistentSettings.fiatPriceEnabled)
|
||||
appWindow.fiatApiRefresh();
|
||||
}
|
||||
if(persistentSettings.fiatPriceEnabled)
|
||||
appWindow.fiatApiRefresh();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
|
||||
import QtQuick 2.9
|
||||
import QtQuick.Layouts 1.1
|
||||
import QtQuick.Controls 2.0
|
||||
import QtQuick.Controls 2.2
|
||||
|
||||
import "../../js/Utils.js" as Utils
|
||||
import "../../components" as MoneroComponents
|
||||
@@ -132,6 +132,18 @@ Rectangle {
|
||||
font.pixelSize: 18
|
||||
font.family: MoneroComponents.Style.fontRegular.name
|
||||
text: qsTr("Daemon log") + translationManager.emptyString
|
||||
themeTransition: false
|
||||
onColorChanged: {
|
||||
var flickableContentYBefore = flickable.contentY
|
||||
var daemonLogText = consoleArea.text
|
||||
consoleArea.clear();
|
||||
if (MoneroComponents.Style.blackTheme) {
|
||||
consoleArea.append(daemonLogText.replace(/#000000/g, '#ffffff').replace(/#008000/g, '#00ff00'));
|
||||
} else {
|
||||
consoleArea.append(daemonLogText.replace(/#ffffff/g, '#000000').replace(/#00ff00/g, '#008000'));
|
||||
}
|
||||
flickable.contentY = flickableContentYBefore
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
@@ -164,7 +176,7 @@ Rectangle {
|
||||
wrapMode: TextEdit.Wrap
|
||||
readOnly: true
|
||||
function logCommand(msg){
|
||||
msg = log_color(msg, "lime");
|
||||
msg = log_color(msg, MoneroComponents.Style.blackTheme ? "lime" : "green");
|
||||
consoleArea.append(msg);
|
||||
}
|
||||
function logMessage(msg){
|
||||
@@ -173,7 +185,7 @@ Rectangle {
|
||||
if(msg.toLowerCase().indexOf('error') >= 0){
|
||||
color = MoneroComponents.Style.errorColor;
|
||||
} else if (msg.toLowerCase().indexOf('warning') >= 0){
|
||||
color = MoneroComponents.Style.warningColor;
|
||||
color = "#fa6800"
|
||||
}
|
||||
|
||||
// format multi-lines
|
||||
@@ -206,6 +218,7 @@ Rectangle {
|
||||
|
||||
ScrollBar.vertical: ScrollBar {
|
||||
onActiveChanged: if (!active && !isMac) active = true
|
||||
policy: isMac ? ScrollBar.AsNeeded : ScrollBar.AlwaysOn
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -213,10 +226,14 @@ Rectangle {
|
||||
MoneroComponents.LineEdit {
|
||||
id: sendCommandText
|
||||
Layout.fillWidth: true
|
||||
inputPaddingTop: 0
|
||||
inputPaddingBottom: 0
|
||||
property var lastCommands: []
|
||||
property int currentCommandIndex
|
||||
enabled: !persistentSettings.useRemoteNode
|
||||
fontBold: false
|
||||
placeholderText: qsTr("command + enter (e.g 'help' or 'status')") + translationManager.emptyString
|
||||
fontSize: 16
|
||||
placeholderText: qsTr("Type a command (e.g '%1' or '%2') and press Enter").arg("help").arg("status") + translationManager.emptyString
|
||||
placeholderFontSize: 16
|
||||
Keys.onUpPressed: {
|
||||
if (currentCommandIndex != 0) {
|
||||
|
||||
@@ -72,7 +72,7 @@ Rectangle{
|
||||
Layout.fillHeight: true
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
color: MoneroComponents.Style.blackTheme ? "white" : "darkgrey"
|
||||
color: "darkgrey"
|
||||
width: 2
|
||||
}
|
||||
|
||||
@@ -130,7 +130,7 @@ Rectangle{
|
||||
topPadding: 0
|
||||
text: qsTr("The blockchain is downloaded to your computer. Provides higher security and requires more local storage.") + translationManager.emptyString
|
||||
width: parent.width - (localNodeIcon.width + localNodeIcon.anchors.leftMargin + anchors.leftMargin)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
@@ -165,7 +165,7 @@ Rectangle{
|
||||
Layout.fillHeight: true
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
color: MoneroComponents.Style.blackTheme ? "white" : "darkgrey"
|
||||
color: "darkgrey"
|
||||
width: 2
|
||||
}
|
||||
|
||||
@@ -248,96 +248,16 @@ Rectangle{
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: remoteNodeLayout
|
||||
anchors.margins: 0
|
||||
spacing: 20
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 20
|
||||
MoneroComponents.WarningBox {
|
||||
Layout.topMargin: 46
|
||||
text: qsTr("To find a remote node, type 'Monero remote node' into your favorite search engine. Please ensure the node is run by a trusted third-party.") + translationManager.emptyString
|
||||
visible: persistentSettings.useRemoteNode
|
||||
}
|
||||
|
||||
MoneroComponents.WarningBox {
|
||||
Layout.topMargin: 26
|
||||
Layout.bottomMargin: 6
|
||||
text: qsTr("To find a remote node, type 'Monero remote node' into your favorite search engine. Please ensure the node is run by a trusted third-party.") + translationManager.emptyString
|
||||
}
|
||||
|
||||
MoneroComponents.RemoteNodeEdit {
|
||||
id: remoteNodeEdit
|
||||
Layout.minimumWidth: 100
|
||||
placeholderFontSize: 15
|
||||
|
||||
daemonAddrLabelText: qsTr("Address") + translationManager.emptyString
|
||||
daemonPortLabelText: qsTr("Port") + translationManager.emptyString
|
||||
|
||||
initialAddress: persistentSettings.remoteNodeAddress
|
||||
onEditingFinished: {
|
||||
persistentSettings.remoteNodeAddress = remoteNodeEdit.getAddress();
|
||||
console.log("setting remote node to " + persistentSettings.remoteNodeAddress);
|
||||
if (persistentSettings.is_trusted_daemon) {
|
||||
persistentSettings.is_trusted_daemon = !persistentSettings.is_trusted_daemon
|
||||
currentWallet.setTrustedDaemon(persistentSettings.is_trusted_daemon)
|
||||
setTrustedDaemonCheckBox.checked = !setTrustedDaemonCheckBox.checked
|
||||
appWindow.showStatusMessage(qsTr("Remote node updated. Trusted daemon has been reset. Mark again, if desired."), 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GridLayout {
|
||||
columns: 2
|
||||
columnSpacing: 32
|
||||
|
||||
MoneroComponents.LineEdit {
|
||||
id: daemonUsername
|
||||
Layout.fillWidth: true
|
||||
labelText: qsTr("Daemon username") + translationManager.emptyString
|
||||
text: persistentSettings.daemonUsername
|
||||
placeholderText: qsTr("(optional)") + translationManager.emptyString
|
||||
placeholderFontSize: 15
|
||||
labelFontSize: 14
|
||||
fontSize: 15
|
||||
}
|
||||
|
||||
MoneroComponents.LineEdit {
|
||||
id: daemonPassword
|
||||
Layout.fillWidth: true
|
||||
labelText: qsTr("Daemon password") + translationManager.emptyString
|
||||
text: persistentSettings.daemonPassword
|
||||
placeholderText: qsTr("Password") + translationManager.emptyString
|
||||
password: true
|
||||
placeholderFontSize: 15
|
||||
labelFontSize: 14
|
||||
fontSize: 15
|
||||
}
|
||||
}
|
||||
|
||||
MoneroComponents.CheckBox {
|
||||
id: setTrustedDaemonCheckBox
|
||||
checked: persistentSettings.is_trusted_daemon
|
||||
onClicked: {
|
||||
persistentSettings.is_trusted_daemon = !persistentSettings.is_trusted_daemon
|
||||
currentWallet.setTrustedDaemon(persistentSettings.is_trusted_daemon)
|
||||
}
|
||||
text: qsTr("Mark as Trusted Daemon") + translationManager.emptyString
|
||||
}
|
||||
|
||||
MoneroComponents.StandardButton {
|
||||
id: btnConnectRemote
|
||||
enabled: remoteNodeEdit.isValid()
|
||||
small: true
|
||||
text: qsTr("Connect") + translationManager.emptyString
|
||||
onClicked: {
|
||||
// Update daemon login
|
||||
persistentSettings.remoteNodeAddress = remoteNodeEdit.getAddress();
|
||||
persistentSettings.daemonUsername = daemonUsername.text;
|
||||
persistentSettings.daemonPassword = daemonPassword.text;
|
||||
persistentSettings.useRemoteNode = true
|
||||
|
||||
currentWallet.setDaemonLogin(persistentSettings.daemonUsername, persistentSettings.daemonPassword);
|
||||
|
||||
appWindow.connectRemoteNode()
|
||||
}
|
||||
}
|
||||
MoneroComponents.RemoteNodeList {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 26
|
||||
visible: persistentSettings.useRemoteNode
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
@@ -398,7 +318,7 @@ Rectangle{
|
||||
placeholderFontSize: 15
|
||||
text: persistentSettings.daemonFlags
|
||||
addressValidation: false
|
||||
error: text.match(/(^|\s)--(data-dir|bootstrap-daemon-address)/)
|
||||
error: text.match(/(^|\s)--(data-dir|bootstrap-daemon-address|non-interactive)/)
|
||||
onEditingFinished: {
|
||||
if (!daemonFlags.error) {
|
||||
persistentSettings.daemonFlags = daemonFlags.text;
|
||||
@@ -431,7 +351,7 @@ Rectangle{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
19
qml.qrc
19
qml.qrc
@@ -3,10 +3,16 @@
|
||||
<file>main.qml</file>
|
||||
<file>LeftPanel.qml</file>
|
||||
<file>MiddlePanel.qml</file>
|
||||
<file>components/Dialog.qml</file>
|
||||
<file>components/Label.qml</file>
|
||||
<file>components/LanguageButton.qml</file>
|
||||
<file>components/Navbar.qml</file>
|
||||
<file>components/NavbarItem.qml</file>
|
||||
<file>components/RemoteNodeDialog.qml</file>
|
||||
<file>components/RemoteNodeList.qml</file>
|
||||
<file>components/SettingsListItem.qml</file>
|
||||
<file>components/Slider.qml</file>
|
||||
<file>components/Tooltip.qml</file>
|
||||
<file>components/UpdateDialog.qml</file>
|
||||
<file>images/whatIsIcon.png</file>
|
||||
<file>images/whatIsIcon@2x.png</file>
|
||||
@@ -15,6 +21,7 @@
|
||||
<file>monero/utils/gpg_keys/fluffypony.asc</file>
|
||||
<file>monero/utils/gpg_keys/luigi1111.asc</file>
|
||||
<file>pages/Account.qml</file>
|
||||
<file>pages/Advanced.qml</file>
|
||||
<file>pages/Transfer.qml</file>
|
||||
<file>pages/History.qml</file>
|
||||
<file>pages/AddressBook.qml</file>
|
||||
@@ -39,6 +46,7 @@
|
||||
<file>images/prevMonth.png</file>
|
||||
<file>images/prevMonth@2x.png</file>
|
||||
<file>components/TitleBar.qml</file>
|
||||
<file>components/MenuBar.qml</file>
|
||||
<file>images/resize.png</file>
|
||||
<file>images/resize@2x.png</file>
|
||||
<file>images/resizeHovered.png</file>
|
||||
@@ -162,7 +170,6 @@
|
||||
<file>pages/settings/SettingsLog.qml</file>
|
||||
<file>pages/settings/SettingsLayout.qml</file>
|
||||
<file>pages/settings/SettingsInfo.qml</file>
|
||||
<file>pages/settings/Navbar.qml</file>
|
||||
<file>components/WarningBox.qml</file>
|
||||
<file>images/miningxmr.png</file>
|
||||
<file>images/miningxmr@2x.png</file>
|
||||
@@ -172,9 +179,9 @@
|
||||
<file>images/merchant/arrow_right.png</file>
|
||||
<file>images/merchant/bg.png</file>
|
||||
<file>images/merchant/input_box.png</file>
|
||||
<file>fonts/FontAwesome/fa-brands-400.ttf</file>
|
||||
<file>fonts/FontAwesome/fa-regular-400.ttf</file>
|
||||
<file>fonts/FontAwesome/fa-solid-900.ttf</file>
|
||||
<file>fonts/FontAwesome/fa-brands-400.otf</file>
|
||||
<file>fonts/FontAwesome/fa-regular-400.otf</file>
|
||||
<file>fonts/FontAwesome/fa-solid-900.otf</file>
|
||||
<file>fonts/FontAwesome/FontAwesome.qml</file>
|
||||
<file>fonts/FontAwesome/Object.qml</file>
|
||||
<file>fonts/FontAwesome/qmldir</file>
|
||||
@@ -245,5 +252,9 @@
|
||||
<file>images/success@2x.png</file>
|
||||
<file>components/SuccessfulTxDialog.qml</file>
|
||||
<file>components/TxConfirmationDialog.qml</file>
|
||||
<file>images/ledgerNanoS.png</file>
|
||||
<file>images/ledgerNanoX.png</file>
|
||||
<file>images/trezor.png</file>
|
||||
<file>images/trezor@2x.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
add_subdirectory(QR-Code-scanner)
|
||||
add_subdirectory(daemon)
|
||||
add_subdirectory(libwalletqt)
|
||||
add_subdirectory(model)
|
||||
add_subdirectory(openpgp)
|
||||
add_subdirectory(zxcvbn-c)
|
||||
|
||||
@@ -20,7 +17,7 @@ file(GLOB SOURCE_FILES
|
||||
"libwalletqt/PendingTransaction.cpp"
|
||||
"libwalletqt/TransactionHistory.cpp"
|
||||
"libwalletqt/TransactionInfo.cpp"
|
||||
"libwalletqt/QRCodeImageProvider.cpp" QR
|
||||
"libwalletqt/QRCodeImageProvider.cpp"
|
||||
"libwalletqt/AddressBook.cpp"
|
||||
"libwalletqt/Subaddress.cpp"
|
||||
"libwalletqt/SubaddressAccount.cpp"
|
||||
@@ -48,20 +45,6 @@ if(APPLE)
|
||||
list(APPEND SOURCE_FILES "qt/macoshelper.mm")
|
||||
endif()
|
||||
|
||||
if(ENABLE_PASS_STRENGTH_METER)
|
||||
file(GLOB PASS_STRENGTH_FILES
|
||||
"zxcvbn-c/zxcvbn.h"
|
||||
"zxcvbn-c/zxcvbn.c"
|
||||
)
|
||||
endif()
|
||||
|
||||
if(WITH_SCANNER)
|
||||
file(GLOB QR_CODE_FILES
|
||||
"QR-Code-scanner/*.h"
|
||||
"QR-Code-scanner/*.cpp"
|
||||
)
|
||||
endif()
|
||||
|
||||
set(EXECUTABLE_FLAG)
|
||||
if(MINGW)
|
||||
set(EXECUTABLE_FLAG WIN32)
|
||||
@@ -83,8 +66,6 @@ endif()
|
||||
|
||||
set(monero_wallet_gui_sources
|
||||
${SOURCE_FILES}
|
||||
${PASS_STRENGTH_FILES}
|
||||
${QR_CODE_FILES}
|
||||
${RESOURCES}
|
||||
)
|
||||
|
||||
@@ -108,9 +89,6 @@ message(STATUS "OpenGL: libraries at ${OPENGL_LIBRARIES}")
|
||||
|
||||
target_include_directories(monero-wallet-gui PUBLIC ${Qt5Gui_PRIVATE_INCLUDE_DIRS})
|
||||
|
||||
file(GLOB_RECURSE SRC_SOURCES *.cpp)
|
||||
file(GLOB_RECURSE SRC_HEADERS *.h)
|
||||
|
||||
target_include_directories(monero-wallet-gui PUBLIC
|
||||
${CMAKE_SOURCE_DIR}/monero/include
|
||||
${CMAKE_SOURCE_DIR}/monero/src
|
||||
@@ -123,12 +101,9 @@ target_include_directories(monero-wallet-gui PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/model
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/QR-Code-scanner
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/zxcvbn-c
|
||||
${LibUSB_INCLUDE_DIRS}
|
||||
${HIDAPI_INCLUDE_DIRS}
|
||||
${X11_INCLUDE_DIR}
|
||||
${Boost_INCLUDE_DIRS}
|
||||
${OPENSSL_INCLUDE_DIR}
|
||||
${ZBAR_INCLUDE_DIR}
|
||||
)
|
||||
|
||||
target_compile_definitions(monero-wallet-gui
|
||||
@@ -137,50 +112,44 @@ target_compile_definitions(monero-wallet-gui
|
||||
${Qt5Qml_DEFINITIONS}
|
||||
)
|
||||
|
||||
if(APPLE)
|
||||
if(NOT ICU_ROOT)
|
||||
execute_process(COMMAND brew --prefix icu4c OUTPUT_VARIABLE ICU_ROOT OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
endif()
|
||||
find_package(ICU REQUIRED COMPONENTS data i18n uc)
|
||||
target_link_directories(monero-wallet-gui PRIVATE ${ICU_ROOT}/lib)
|
||||
endif()
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Widgets_EXECUTABLE_COMPILE_FLAGS}")
|
||||
|
||||
target_link_libraries(monero-wallet-gui
|
||||
wallet_merged
|
||||
${LMDB_LIBRARY}
|
||||
epee
|
||||
wallet_api
|
||||
qrcodegen
|
||||
${UNBOUND_LIBRARY}
|
||||
${SODIUM_LIBRARY}
|
||||
easylogging
|
||||
blockchain_db
|
||||
randomx
|
||||
hardforks
|
||||
${Boost_LIBRARIES}
|
||||
${OPENSSL_LIBRARIES}
|
||||
${CMAKE_DL_LIBS}
|
||||
${LibUSB_LIBRARIES}
|
||||
${HIDAPI_LIBRARIES}
|
||||
${QT5_LIBRARIES}
|
||||
${EXTRA_LIBRARIES}
|
||||
${ICU_LIBRARIES}
|
||||
openpgp
|
||||
qrdecoder
|
||||
translations
|
||||
zxcvbn
|
||||
)
|
||||
|
||||
if(DEVICE_TREZOR_READY)
|
||||
target_link_libraries(monero-wallet-gui ${TREZOR_DEP_LIBS})
|
||||
endif()
|
||||
|
||||
if(X11_FOUND)
|
||||
target_link_libraries(monero-wallet-gui ${X11_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if(WITH_SCANNER)
|
||||
if(NOT ANDROID)
|
||||
target_link_libraries(monero-wallet-gui qrscanner)
|
||||
if(LINUX AND NOT ANDROID)
|
||||
target_link_libraries(monero-wallet-gui
|
||||
${ZBAR_LIBRARIES}
|
||||
jpeg
|
||||
v4l2
|
||||
v4lconvert
|
||||
rt
|
||||
)
|
||||
else()
|
||||
target_link_libraries(monero-wallet-gui ${ZBAR_LIBRARIES})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
@@ -1,4 +1,21 @@
|
||||
file(GLOB_RECURSE SRC_SOURCES *.cpp)
|
||||
file(GLOB_RECURSE SRC_HEADERS *.h)
|
||||
|
||||
add_library(qrdecoder STATIC
|
||||
Decoder.cpp
|
||||
)
|
||||
target_link_libraries(qrdecoder
|
||||
PUBLIC
|
||||
Qt5::Gui
|
||||
PRIVATE
|
||||
quirc
|
||||
)
|
||||
|
||||
if(WITH_SCANNER)
|
||||
add_library(qrscanner
|
||||
QrCodeScanner.cpp
|
||||
QrScanThread.cpp
|
||||
)
|
||||
target_link_libraries(qrscanner
|
||||
PUBLIC
|
||||
Qt5::Multimedia
|
||||
qrdecoder
|
||||
)
|
||||
endif()
|
||||
|
||||
99
src/QR-Code-scanner/Decoder.cpp
Normal file
99
src/QR-Code-scanner/Decoder.cpp
Normal file
@@ -0,0 +1,99 @@
|
||||
// Copyright (c) 2020, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "Decoder.h"
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include "quirc.h"
|
||||
|
||||
QrDecoder::QrDecoder()
|
||||
: m_qr(quirc_new())
|
||||
{
|
||||
if (m_qr == nullptr)
|
||||
{
|
||||
throw std::runtime_error("QUIRC: failed to allocate memory");
|
||||
}
|
||||
}
|
||||
|
||||
QrDecoder::~QrDecoder()
|
||||
{
|
||||
quirc_destroy(m_qr);
|
||||
}
|
||||
|
||||
std::vector<std::string> QrDecoder::decode(const QImage &image)
|
||||
{
|
||||
if (image.format() == QImage::Format_Grayscale8)
|
||||
{
|
||||
return decodeGrayscale8(image);
|
||||
}
|
||||
return decodeGrayscale8(image.convertToFormat(QImage::Format_Grayscale8));
|
||||
}
|
||||
|
||||
std::vector<std::string> QrDecoder::decodeGrayscale8(const QImage &image)
|
||||
{
|
||||
if (quirc_resize(m_qr, image.width(), image.height()) < 0)
|
||||
{
|
||||
throw std::runtime_error("QUIRC: failed to allocate video memory");
|
||||
}
|
||||
|
||||
uint8_t *rawImage = quirc_begin(m_qr, nullptr, nullptr);
|
||||
if (rawImage == nullptr)
|
||||
{
|
||||
throw std::runtime_error("QUIRC: failed to get image buffer");
|
||||
}
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
|
||||
std::copy(image.constBits(), image.constBits() + image.sizeInBytes(), rawImage);
|
||||
#else
|
||||
std::copy(image.constBits(), image.constBits() + image.byteCount(), rawImage);
|
||||
#endif
|
||||
quirc_end(m_qr);
|
||||
|
||||
const int count = quirc_count(m_qr);
|
||||
if (count < 0)
|
||||
{
|
||||
throw std::runtime_error("QUIRC: failed to get the number of recognized QR-codes");
|
||||
}
|
||||
|
||||
std::vector<std::string> result;
|
||||
result.reserve(static_cast<size_t>(count));
|
||||
for (int index = 0; index < count; ++index)
|
||||
{
|
||||
quirc_code code;
|
||||
quirc_extract(m_qr, index, &code);
|
||||
|
||||
quirc_data data;
|
||||
const quirc_decode_error_t err = quirc_decode(&code, &data);
|
||||
if (err == QUIRC_SUCCESS)
|
||||
{
|
||||
result.emplace_back(&data.payload[0], &data.payload[data.payload_len]);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
49
src/QR-Code-scanner/Decoder.h
Normal file
49
src/QR-Code-scanner/Decoder.h
Normal file
@@ -0,0 +1,49 @@
|
||||
// Copyright (c) 2020, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <QImage>
|
||||
|
||||
struct quirc;
|
||||
|
||||
class QrDecoder
|
||||
{
|
||||
public:
|
||||
QrDecoder(const QrDecoder &) = delete;
|
||||
QrDecoder &operator=(const QrDecoder &) = delete;
|
||||
|
||||
QrDecoder();
|
||||
~QrDecoder();
|
||||
|
||||
std::vector<std::string> decode(const QImage &image);
|
||||
|
||||
private:
|
||||
std::vector<std::string> decodeGrayscale8(const QImage &image);
|
||||
|
||||
private:
|
||||
quirc *m_qr;
|
||||
};
|
||||
@@ -27,7 +27,6 @@
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "QrCodeScanner.h"
|
||||
#include <WalletManager.h>
|
||||
#include <QVideoProbe>
|
||||
#include <QCamera>
|
||||
|
||||
@@ -40,7 +39,7 @@ QrCodeScanner::QrCodeScanner(QObject *parent)
|
||||
m_probe = new QVideoProbe(this);
|
||||
m_thread = new QrScanThread(this);
|
||||
m_thread->start();
|
||||
QObject::connect(m_thread, SIGNAL(decoded(int, QString)), this, SIGNAL(decoded(int, QString)));
|
||||
QObject::connect(m_thread, SIGNAL(decoded(QString)), this, SIGNAL(decoded(QString)));
|
||||
QObject::connect(m_thread, SIGNAL(notifyError(const QString &, bool)), this, SIGNAL(notifyError(const QString &, bool)));
|
||||
connect(m_probe, SIGNAL(videoFrameProbed(QVideoFrame)), this, SLOT(processFrame(QVideoFrame)));
|
||||
}
|
||||
|
||||
@@ -56,8 +56,7 @@ public Q_SLOTS:
|
||||
Q_SIGNALS:
|
||||
void enabledChanged();
|
||||
|
||||
void decoded(int type, const QString &data);
|
||||
void decode(int type, const QString &data);
|
||||
void decoded(const QString &data);
|
||||
void notifyError(const QString &error, bool warning = false);
|
||||
|
||||
protected:
|
||||
|
||||
@@ -38,62 +38,15 @@ QrScanThread::QrScanThread(QObject *parent)
|
||||
: QThread(parent)
|
||||
,m_running(true)
|
||||
{
|
||||
m_scanner.set_handler(*this);
|
||||
}
|
||||
|
||||
void QrScanThread::image_callback(zbar::Image &image)
|
||||
{
|
||||
qDebug() << "image_callback : Found Code ! " ;
|
||||
for(zbar::Image::SymbolIterator sym = image.symbol_begin();
|
||||
sym != image.symbol_end();
|
||||
++sym)
|
||||
if(!sym->get_count()) {
|
||||
QString data = QString::fromStdString(sym->get_data());
|
||||
emit decoded(sym->get_type(), data);
|
||||
}
|
||||
}
|
||||
|
||||
void QrScanThread::processZImage(zbar::Image &image)
|
||||
{
|
||||
m_scanner.recycle_image(image);
|
||||
zbar::Image tmp = image.convert(*(long*)"Y800");
|
||||
m_scanner.scan(tmp);
|
||||
image.set_symbols(tmp.get_symbols());
|
||||
}
|
||||
|
||||
bool QrScanThread::zimageFromQImage(const QImage &qimg, zbar::Image &dst)
|
||||
{
|
||||
switch( qimg.format() ){
|
||||
case QImage::Format_RGB32 :
|
||||
case QImage::Format_ARGB32 :
|
||||
case QImage::Format_ARGB32_Premultiplied :
|
||||
break;
|
||||
default :
|
||||
emit notifyError(QString("Invalid QImage Format !"));
|
||||
return false;
|
||||
}
|
||||
unsigned int bpl( qimg.bytesPerLine() ), width( bpl / 4), height( qimg.height());
|
||||
dst.set_size(width, height);
|
||||
dst.set_format("BGR4");
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
|
||||
unsigned long datalen = qimg.sizeInBytes();
|
||||
#else
|
||||
unsigned long datalen = qimg.byteCount();
|
||||
#endif
|
||||
dst.set_data(qimg.bits(), datalen);
|
||||
if((width * 4 != bpl) || (width * height * 4 > datalen)){
|
||||
emit notifyError(QString("QImage to Zbar::Image failed !"));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
void QrScanThread::processQImage(const QImage &qimg)
|
||||
{
|
||||
try {
|
||||
m_image = QSharedPointer<zbar::Image>(new zbar::Image());
|
||||
if( ! zimageFromQImage(qimg, *m_image) )
|
||||
return;
|
||||
processZImage(*m_image);
|
||||
for (const std::string &code : m_decoder.decode(qimg))
|
||||
{
|
||||
emit decoded(QString::fromStdString(code));
|
||||
}
|
||||
}
|
||||
catch(std::exception &e) {
|
||||
qDebug() << "ERROR: " << e.what();
|
||||
|
||||
@@ -35,9 +35,10 @@
|
||||
#include <QEvent>
|
||||
#include <QVideoFrame>
|
||||
#include <QCamera>
|
||||
#include <zbar.h>
|
||||
|
||||
class QrScanThread : public QThread, public zbar::Image::Handler
|
||||
#include "Decoder.h"
|
||||
|
||||
class QrScanThread : public QThread
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
@@ -47,20 +48,16 @@ public:
|
||||
virtual void stop();
|
||||
|
||||
Q_SIGNALS:
|
||||
void decoded(int type, const QString &data);
|
||||
void decoded(const QString &data);
|
||||
void notifyError(const QString &error, bool warning = false);
|
||||
|
||||
protected:
|
||||
virtual void run();
|
||||
void processVideoFrame(const QVideoFrame &);
|
||||
void processQImage(const QImage &);
|
||||
void processZImage(zbar::Image &image);
|
||||
virtual void image_callback(zbar::Image &image);
|
||||
bool zimageFromQImage(const QImage&, zbar::Image &);
|
||||
|
||||
private:
|
||||
zbar::ImageScanner m_scanner;
|
||||
QSharedPointer<zbar::Image> m_image;
|
||||
QrDecoder m_decoder;
|
||||
bool m_running;
|
||||
QMutex m_mutex;
|
||||
QWaitCondition m_waitCondition;
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
file(GLOB_RECURSE SRC_SOURCES *.cpp)
|
||||
file(GLOB_RECURSE SRC_HEADERS *.h)
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "DaemonManager.h"
|
||||
#include "common/util.h"
|
||||
#include <QElapsedTimer>
|
||||
#include <QFile>
|
||||
#include <QMutexLocker>
|
||||
@@ -47,24 +48,7 @@ namespace {
|
||||
static const int DAEMON_START_TIMEOUT_SECONDS = 120;
|
||||
}
|
||||
|
||||
DaemonManager * DaemonManager::m_instance = nullptr;
|
||||
QStringList DaemonManager::m_clArgs;
|
||||
|
||||
DaemonManager *DaemonManager::instance(const QStringList *args/* = nullptr*/)
|
||||
{
|
||||
if (!m_instance) {
|
||||
m_instance = new DaemonManager;
|
||||
// store command line arguments for later use
|
||||
if (args != nullptr)
|
||||
{
|
||||
m_clArgs = *args;
|
||||
}
|
||||
}
|
||||
|
||||
return m_instance;
|
||||
}
|
||||
|
||||
bool DaemonManager::start(const QString &flags, NetworkType::Type nettype, const QString &dataDir, const QString &bootstrapNodeAddress, bool noSync /* = false*/)
|
||||
bool DaemonManager::start(const QString &flags, NetworkType::Type nettype, const QString &dataDir, const QString &bootstrapNodeAddress, bool noSync /* = false*/, bool pruneBlockchain /* = false*/)
|
||||
{
|
||||
if (!QFileInfo(m_monerod).isFile())
|
||||
{
|
||||
@@ -85,12 +69,6 @@ bool DaemonManager::start(const QString &flags, NetworkType::Type nettype, const
|
||||
else if (nettype == NetworkType::STAGENET)
|
||||
arguments << "--stagenet";
|
||||
|
||||
foreach (const QString &str, m_clArgs) {
|
||||
qDebug() << QString(" [%1] ").arg(str);
|
||||
if (!str.isEmpty())
|
||||
arguments << str;
|
||||
}
|
||||
|
||||
// Custom startup flags for daemon
|
||||
foreach (const QString &str, flags.split(" ")) {
|
||||
qDebug() << QString(" [%1] ").arg(str);
|
||||
@@ -108,15 +86,18 @@ bool DaemonManager::start(const QString &flags, NetworkType::Type nettype, const
|
||||
arguments << "--bootstrap-daemon-address" << bootstrapNodeAddress;
|
||||
}
|
||||
|
||||
if (pruneBlockchain) {
|
||||
if (!checkLmdbExists(dataDir)) { // check that DB has not already been created
|
||||
arguments << "--prune-blockchain";
|
||||
}
|
||||
}
|
||||
|
||||
if (noSync) {
|
||||
arguments << "--no-sync";
|
||||
}
|
||||
|
||||
if (!flags.contains("--out-peers", Qt::CaseSensitive) && bootstrapNodeAddress == "auto") {
|
||||
arguments << "--out-peers" << "16";
|
||||
}
|
||||
|
||||
arguments << "--check-updates" << "disabled";
|
||||
arguments << "--non-interactive";
|
||||
|
||||
// --max-concurrency based on threads available.
|
||||
int32_t concurrency = qMax(1, QThread::idealThreadCount() / 2);
|
||||
@@ -349,6 +330,13 @@ QVariantMap DaemonManager::validateDataDir(const QString &dataDir) const
|
||||
return result;
|
||||
}
|
||||
|
||||
bool DaemonManager::checkLmdbExists(QString datadir) {
|
||||
if (datadir.isEmpty() || datadir.isNull()) {
|
||||
datadir = QString::fromStdString(tools::get_default_data_dir());
|
||||
}
|
||||
return validateDataDir(datadir).value("lmdbExists").value<bool>();
|
||||
}
|
||||
|
||||
DaemonManager::DaemonManager(QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_scheduler(this)
|
||||
|
||||
@@ -44,10 +44,10 @@ class DaemonManager : public QObject
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit DaemonManager(QObject *parent = 0);
|
||||
~DaemonManager();
|
||||
|
||||
static DaemonManager * instance(const QStringList *args = nullptr);
|
||||
|
||||
Q_INVOKABLE bool start(const QString &flags, NetworkType::Type nettype, const QString &dataDir = "", const QString &bootstrapNodeAddress = "", bool noSync = false);
|
||||
Q_INVOKABLE bool start(const QString &flags, NetworkType::Type nettype, const QString &dataDir = "", const QString &bootstrapNodeAddress = "", bool noSync = false, bool pruneBlockchain = false);
|
||||
Q_INVOKABLE void stopAsync(NetworkType::Type nettype, const QJSValue& callback);
|
||||
|
||||
Q_INVOKABLE bool noSync() const noexcept;
|
||||
@@ -57,6 +57,7 @@ public:
|
||||
Q_INVOKABLE void sendCommandAsync(const QStringList &cmd, NetworkType::Type nettype, const QJSValue& callback) const;
|
||||
Q_INVOKABLE void exit();
|
||||
Q_INVOKABLE QVariantMap validateDataDir(const QString &dataDir) const;
|
||||
Q_INVOKABLE bool checkLmdbExists(QString datadir);
|
||||
|
||||
private:
|
||||
|
||||
@@ -76,11 +77,6 @@ public slots:
|
||||
void stateChanged(QProcess::ProcessState state);
|
||||
|
||||
private:
|
||||
explicit DaemonManager(QObject *parent = 0);
|
||||
~DaemonManager();
|
||||
|
||||
static DaemonManager * m_instance;
|
||||
static QStringList m_clArgs;
|
||||
std::unique_ptr<QProcess> m_daemon;
|
||||
QMutex m_daemonMutex;
|
||||
QString m_monerod;
|
||||
|
||||
@@ -121,13 +121,6 @@ quint64 AddressBook::count() const
|
||||
return m_rows.size();
|
||||
}
|
||||
|
||||
int AddressBook::lookupPaymentID(const QString &payment_id) const
|
||||
{
|
||||
QReadLocker locker(&m_lock);
|
||||
|
||||
return m_addressBookImpl->lookupPaymentID(payment_id.toStdString());
|
||||
}
|
||||
|
||||
QString AddressBook::getDescription(const QString &address) const
|
||||
{
|
||||
QReadLocker locker(&m_lock);
|
||||
|
||||
@@ -51,7 +51,6 @@ public:
|
||||
quint64 count() const;
|
||||
Q_INVOKABLE QString errorString() const;
|
||||
Q_INVOKABLE int errorCode() const;
|
||||
Q_INVOKABLE int lookupPaymentID(const QString &payment_id) const;
|
||||
Q_INVOKABLE QString getDescription(const QString &address) const;
|
||||
|
||||
enum ErrorCode {
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
file(GLOB_RECURSE SRC_SOURCES *.cpp)
|
||||
file(GLOB_RECURSE SRC_HEADERS *.h)
|
||||
|
||||
|
||||
@@ -78,7 +78,14 @@ void Subaddress::setLabel(quint32 accountIndex, quint32 addressIndex, const QStr
|
||||
|
||||
void Subaddress::refresh(quint32 accountIndex) const
|
||||
{
|
||||
m_subaddressImpl->refresh(accountIndex);
|
||||
try
|
||||
{
|
||||
m_subaddressImpl->refresh(accountIndex);
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
qCritical() << "Failed to refresh account" << accountIndex << "subaddresses:" << e.what();
|
||||
}
|
||||
getAll();
|
||||
}
|
||||
|
||||
|
||||
@@ -181,7 +181,6 @@ QString TransactionHistory::writeCSV(quint32 accountIndex, QString out)
|
||||
TransactionInfo info(tx, this);
|
||||
|
||||
// collect column data
|
||||
double amount = info.amount();
|
||||
quint64 atomicAmount = info.atomicAmount();
|
||||
quint32 subaddrAccount = info.subaddrAccount();
|
||||
QString fee = info.fee();
|
||||
@@ -212,7 +211,7 @@ QString TransactionHistory::writeCSV(quint32 accountIndex, QString out)
|
||||
// format and write
|
||||
QString line = QString("%1,%2,%3,%4,%5,%6,%7,%8,\"%9\",%10,%11\n")
|
||||
.arg(QString::number(blockHeight), QString::number(epoch), date)
|
||||
.arg(direction, QString::number(amount), QString::number(atomicAmount))
|
||||
.arg(direction, displayAmount, QString::number(atomicAmount))
|
||||
.arg(info.fee(), info.hash(), label, QString::number(subaddrAccount))
|
||||
.arg(paymentId);
|
||||
output << line;
|
||||
|
||||
@@ -104,10 +104,7 @@ void Wallet::updateConnectionStatusAsync()
|
||||
setConnectionStatus(ConnectionStatus_Connecting);
|
||||
}
|
||||
ConnectionStatus newStatus = static_cast<ConnectionStatus>(m_walletImpl->connected());
|
||||
if (newStatus != m_connectionStatus || !m_initialized) {
|
||||
m_initialized = true;
|
||||
setConnectionStatus(newStatus);
|
||||
}
|
||||
setConnectionStatus(newStatus);
|
||||
// Release lock
|
||||
m_connectionStatusRunning = false;
|
||||
});
|
||||
@@ -115,8 +112,13 @@ void Wallet::updateConnectionStatusAsync()
|
||||
|
||||
Wallet::ConnectionStatus Wallet::connected(bool forceCheck)
|
||||
{
|
||||
if (!m_initialized)
|
||||
{
|
||||
return ConnectionStatus_Connecting;
|
||||
}
|
||||
|
||||
// cache connection status
|
||||
if (forceCheck || !m_initialized || (m_connectionStatusTime.elapsed() / 1000 > m_connectionStatusTtl && !m_connectionStatusRunning) || m_connectionStatusTime.elapsed() > 30000) {
|
||||
if (forceCheck || (m_connectionStatusTime.elapsed() / 1000 > m_connectionStatusTtl && !m_connectionStatusRunning) || m_connectionStatusTime.elapsed() > 30000) {
|
||||
qDebug() << "Checking connection status";
|
||||
m_connectionStatusRunning = true;
|
||||
m_connectionStatusTime.restart();
|
||||
@@ -277,14 +279,25 @@ void Wallet::initAsync(
|
||||
{
|
||||
qDebug() << "initAsync: " + daemonAddress;
|
||||
const auto future = m_scheduler.run([this, daemonAddress, trustedDaemon, upperTransactionLimit, isRecovering, isRecoveringFromDevice, restoreHeight, proxyAddress] {
|
||||
bool success = init(daemonAddress, trustedDaemon, upperTransactionLimit, isRecovering, isRecoveringFromDevice, restoreHeight, proxyAddress);
|
||||
if (success)
|
||||
m_initialized = init(
|
||||
daemonAddress,
|
||||
trustedDaemon,
|
||||
upperTransactionLimit,
|
||||
isRecovering,
|
||||
isRecoveringFromDevice,
|
||||
restoreHeight,
|
||||
proxyAddress);
|
||||
if (m_initialized)
|
||||
{
|
||||
emit walletCreationHeightChanged();
|
||||
qDebug() << "init async finished - starting refresh";
|
||||
connected(true);
|
||||
startRefresh();
|
||||
}
|
||||
else
|
||||
{
|
||||
qCritical() << "Failed to initialize the wallet";
|
||||
}
|
||||
});
|
||||
if (future.first)
|
||||
{
|
||||
@@ -519,25 +532,44 @@ void Wallet::pauseRefresh()
|
||||
m_refreshEnabled = false;
|
||||
}
|
||||
|
||||
PendingTransaction *Wallet::createTransaction(const QString &dst_addr, const QString &payment_id,
|
||||
quint64 amount, quint32 mixin_count,
|
||||
PendingTransaction::Priority priority)
|
||||
PendingTransaction *Wallet::createTransaction(
|
||||
const QVector<QString> &destinationAddresses,
|
||||
const QString &payment_id,
|
||||
const QVector<QString> &destinationAmounts,
|
||||
quint32 mixin_count,
|
||||
PendingTransaction::Priority priority)
|
||||
{
|
||||
std::vector<std::string> destinations;
|
||||
for (const auto &address : destinationAddresses) {
|
||||
destinations.push_back(address.toStdString());
|
||||
}
|
||||
std::vector<uint64_t> amounts;
|
||||
for (const auto &amount : destinationAmounts) {
|
||||
amounts.push_back(Monero::Wallet::amountFromString(amount.toStdString()));
|
||||
}
|
||||
std::set<uint32_t> subaddr_indices;
|
||||
Monero::PendingTransaction * ptImpl = m_walletImpl->createTransaction(
|
||||
dst_addr.toStdString(), payment_id.toStdString(), amount, mixin_count,
|
||||
static_cast<Monero::PendingTransaction::Priority>(priority), currentSubaddressAccount(), subaddr_indices);
|
||||
PendingTransaction * result = new PendingTransaction(ptImpl,0);
|
||||
Monero::PendingTransaction *ptImpl = m_walletImpl->createTransactionMultDest(
|
||||
destinations,
|
||||
payment_id.toStdString(),
|
||||
amounts,
|
||||
mixin_count,
|
||||
static_cast<Monero::PendingTransaction::Priority>(priority),
|
||||
currentSubaddressAccount(),
|
||||
subaddr_indices);
|
||||
PendingTransaction *result = new PendingTransaction(ptImpl, 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
void Wallet::createTransactionAsync(const QString &dst_addr, const QString &payment_id,
|
||||
quint64 amount, quint32 mixin_count,
|
||||
PendingTransaction::Priority priority)
|
||||
void Wallet::createTransactionAsync(
|
||||
const QVector<QString> &destinationAddresses,
|
||||
const QString &payment_id,
|
||||
const QVector<QString> &destinationAmounts,
|
||||
quint32 mixin_count,
|
||||
PendingTransaction::Priority priority)
|
||||
{
|
||||
m_scheduler.run([this, dst_addr, payment_id, amount, mixin_count, priority] {
|
||||
PendingTransaction *tx = createTransaction(dst_addr, payment_id, amount, mixin_count, priority);
|
||||
emit transactionCreated(tx, dst_addr, payment_id, mixin_count);
|
||||
m_scheduler.run([this, destinationAddresses, payment_id, destinationAmounts, mixin_count, priority] {
|
||||
PendingTransaction *tx = createTransaction(destinationAddresses, payment_id, destinationAmounts, mixin_count, priority);
|
||||
emit transactionCreated(tx, destinationAddresses, payment_id, mixin_count);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -558,7 +590,7 @@ void Wallet::createTransactionAllAsync(const QString &dst_addr, const QString &p
|
||||
{
|
||||
m_scheduler.run([this, dst_addr, payment_id, mixin_count, priority] {
|
||||
PendingTransaction *tx = createTransactionAll(dst_addr, payment_id, mixin_count, priority);
|
||||
emit transactionCreated(tx, dst_addr, payment_id, mixin_count);
|
||||
emit transactionCreated(tx, {dst_addr}, payment_id, mixin_count);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -573,7 +605,7 @@ void Wallet::createSweepUnmixableTransactionAsync()
|
||||
{
|
||||
m_scheduler.run([this] {
|
||||
PendingTransaction *tx = createSweepUnmixableTransaction();
|
||||
emit transactionCreated(tx, "", "", 0);
|
||||
emit transactionCreated(tx, {""}, "", 0);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -613,17 +645,32 @@ void Wallet::disposeTransaction(UnsignedTransaction *t)
|
||||
delete t;
|
||||
}
|
||||
|
||||
void Wallet::estimateTransactionFeeAsync(const QString &destination,
|
||||
quint64 amount,
|
||||
PendingTransaction::Priority priority,
|
||||
const QJSValue &callback)
|
||||
void Wallet::estimateTransactionFeeAsync(
|
||||
const QVector<QString> &destinationAddresses,
|
||||
const QVector<quint64> &amounts,
|
||||
PendingTransaction::Priority priority,
|
||||
const QJSValue &callback)
|
||||
{
|
||||
m_scheduler.run([this, destination, amount, priority] {
|
||||
const uint64_t fee = m_walletImpl->estimateTransactionFee(
|
||||
{std::make_pair(destination.toStdString(), amount)},
|
||||
static_cast<Monero::PendingTransaction::Priority>(priority));
|
||||
return QJSValueList({QString::fromStdString(Monero::Wallet::displayAmount(fee))});
|
||||
}, callback);
|
||||
m_scheduler.run(
|
||||
[this, destinationAddresses, amounts, priority] {
|
||||
if (destinationAddresses.size() != amounts.size())
|
||||
{
|
||||
return QJSValueList({""});
|
||||
}
|
||||
|
||||
std::vector<std::pair<std::string, uint64_t>> destinations;
|
||||
destinations.reserve(destinationAddresses.size());
|
||||
for (size_t index = 0; index < destinationAddresses.size(); ++index)
|
||||
{
|
||||
destinations.emplace_back(std::make_pair(destinationAddresses[index].toStdString(), amounts[index]));
|
||||
}
|
||||
|
||||
const uint64_t fee = m_walletImpl->estimateTransactionFee(
|
||||
destinations,
|
||||
static_cast<Monero::PendingTransaction::Priority>(priority));
|
||||
return QJSValueList({QString::fromStdString(Monero::Wallet::displayAmount(fee))});
|
||||
},
|
||||
callback);
|
||||
}
|
||||
|
||||
TransactionHistory *Wallet::history() const
|
||||
@@ -699,16 +746,6 @@ QString Wallet::integratedAddress(const QString &paymentId) const
|
||||
return QString::fromStdString(m_walletImpl->integratedAddress(paymentId.toStdString()));
|
||||
}
|
||||
|
||||
QString Wallet::paymentId() const
|
||||
{
|
||||
return m_paymentId;
|
||||
}
|
||||
|
||||
void Wallet::setPaymentId(const QString &paymentId)
|
||||
{
|
||||
m_paymentId = paymentId;
|
||||
}
|
||||
|
||||
QString Wallet::getCacheAttribute(const QString &key) const {
|
||||
return QString::fromStdString(m_walletImpl->getCacheAttribute(key.toStdString()));
|
||||
}
|
||||
@@ -1043,9 +1080,9 @@ void Wallet::onPassphraseEntered(const QString &passphrase, bool enter_on_device
|
||||
Wallet::Wallet(Monero::Wallet *w, QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_walletImpl(w)
|
||||
, m_history(nullptr)
|
||||
, m_history(new TransactionHistory(m_walletImpl->history(), this))
|
||||
, m_historyModel(nullptr)
|
||||
, m_addressBook(nullptr)
|
||||
, m_addressBook(new AddressBook(m_walletImpl->addressBook(), this))
|
||||
, m_addressBookModel(nullptr)
|
||||
, m_daemonBlockChainHeight(0)
|
||||
, m_daemonBlockChainHeightTtl(DAEMON_BLOCKCHAIN_HEIGHT_CACHE_TTL_SECONDS)
|
||||
@@ -1054,19 +1091,16 @@ Wallet::Wallet(Monero::Wallet *w, QObject *parent)
|
||||
, m_connectionStatus(Wallet::ConnectionStatus_Disconnected)
|
||||
, m_connectionStatusTtl(WALLET_CONNECTION_STATUS_CACHE_TTL_SECONDS)
|
||||
, m_disconnected(true)
|
||||
, m_initialized(false)
|
||||
, m_currentSubaddressAccount(0)
|
||||
, m_subaddress(nullptr)
|
||||
, m_subaddress(new Subaddress(m_walletImpl->subaddress(), this))
|
||||
, m_subaddressModel(nullptr)
|
||||
, m_subaddressAccount(nullptr)
|
||||
, m_subaddressAccount(new SubaddressAccount(m_walletImpl->subaddressAccount(), this))
|
||||
, m_subaddressAccountModel(nullptr)
|
||||
, m_refreshEnabled(false)
|
||||
, m_refreshing(false)
|
||||
, m_scheduler(this)
|
||||
{
|
||||
m_history = new TransactionHistory(m_walletImpl->history(), this);
|
||||
m_addressBook = new AddressBook(m_walletImpl->addressBook(), this);
|
||||
m_subaddress = new Subaddress(m_walletImpl->subaddress(), this);
|
||||
m_subaddressAccount = new SubaddressAccount(m_walletImpl->subaddressAccount(), this);
|
||||
m_walletListener = new WalletListenerImpl(this);
|
||||
m_walletImpl->setListener(m_walletListener);
|
||||
m_currentSubaddressAccount = getCacheAttribute(ATTRIBUTE_SUBADDRESS_ACCOUNT).toUInt();
|
||||
@@ -1074,7 +1108,6 @@ Wallet::Wallet(Monero::Wallet *w, QObject *parent)
|
||||
m_connectionStatusTime.start();
|
||||
m_daemonBlockChainHeightTime.start();
|
||||
m_daemonBlockChainTargetHeightTime.start();
|
||||
m_initialized = false;
|
||||
m_connectionStatusRunning = false;
|
||||
m_daemonUsername = "";
|
||||
m_daemonPassword = "";
|
||||
@@ -1090,17 +1123,6 @@ Wallet::~Wallet()
|
||||
m_walletImpl->stop();
|
||||
m_scheduler.shutdownWaitForFinished();
|
||||
|
||||
delete m_addressBook;
|
||||
m_addressBook = NULL;
|
||||
|
||||
delete m_history;
|
||||
m_history = NULL;
|
||||
delete m_addressBook;
|
||||
m_addressBook = NULL;
|
||||
delete m_subaddress;
|
||||
m_subaddress = NULL;
|
||||
delete m_subaddressAccount;
|
||||
m_subaddressAccount = NULL;
|
||||
//Monero::WalletManagerFactory::getWalletManager()->closeWallet(m_walletImpl);
|
||||
if(status() == Status_Critical)
|
||||
qDebug("Not storing wallet cache");
|
||||
|
||||
@@ -29,6 +29,8 @@
|
||||
#ifndef WALLET_H
|
||||
#define WALLET_H
|
||||
|
||||
#include <atomic>
|
||||
|
||||
#include <QElapsedTimer>
|
||||
#include <QObject>
|
||||
#include <QMutex>
|
||||
@@ -73,7 +75,6 @@ class Wallet : public QObject, public PassprasePrompter
|
||||
Q_PROPERTY(bool synchronized READ synchronized)
|
||||
Q_PROPERTY(QString errorString READ errorString)
|
||||
Q_PROPERTY(TransactionHistory * history READ history)
|
||||
Q_PROPERTY(QString paymentId READ paymentId WRITE setPaymentId)
|
||||
Q_PROPERTY(TransactionHistorySortFilterModel * historyModel READ historyModel NOTIFY historyModelChanged)
|
||||
Q_PROPERTY(QString path READ path)
|
||||
Q_PROPERTY(AddressBookModel * addressBookModel READ addressBookModel)
|
||||
@@ -214,15 +215,13 @@ public:
|
||||
Q_INVOKABLE void startRefresh();
|
||||
Q_INVOKABLE void pauseRefresh();
|
||||
|
||||
//! creates transaction
|
||||
Q_INVOKABLE PendingTransaction * createTransaction(const QString &dst_addr, const QString &payment_id,
|
||||
quint64 amount, quint32 mixin_count,
|
||||
PendingTransaction::Priority priority);
|
||||
|
||||
//! creates async transaction
|
||||
Q_INVOKABLE void createTransactionAsync(const QString &dst_addr, const QString &payment_id,
|
||||
quint64 amount, quint32 mixin_count,
|
||||
PendingTransaction::Priority priority);
|
||||
Q_INVOKABLE void createTransactionAsync(
|
||||
const QVector<QString> &destinationAddresses,
|
||||
const QString &payment_id,
|
||||
const QVector<QString> &destinationAmounts,
|
||||
quint32 mixin_count,
|
||||
PendingTransaction::Priority priority);
|
||||
|
||||
//! creates transaction with all outputs
|
||||
Q_INVOKABLE PendingTransaction * createTransactionAll(const QString &dst_addr, const QString &payment_id,
|
||||
@@ -253,10 +252,11 @@ public:
|
||||
//! deletes unsigned transaction and frees memory
|
||||
Q_INVOKABLE void disposeTransaction(UnsignedTransaction * t);
|
||||
|
||||
Q_INVOKABLE void estimateTransactionFeeAsync(const QString &destination,
|
||||
quint64 amount,
|
||||
PendingTransaction::Priority priority,
|
||||
const QJSValue &callback);
|
||||
Q_INVOKABLE void estimateTransactionFeeAsync(
|
||||
const QVector<QString> &destinationAddresses,
|
||||
const QVector<quint64> &amounts,
|
||||
PendingTransaction::Priority priority,
|
||||
const QJSValue &callback);
|
||||
|
||||
//! returns transaction history
|
||||
TransactionHistory * history() const;
|
||||
@@ -297,11 +297,6 @@ public:
|
||||
//! Parse URI
|
||||
Q_INVOKABLE bool parse_uri(const QString &uri, QString &address, QString &payment_id, uint64_t &amount, QString &tx_description, QString &recipient_name, QVector<QString> &unknown_parameters, QString &error);
|
||||
|
||||
//! saved payment id
|
||||
QString paymentId() const;
|
||||
|
||||
void setPaymentId(const QString &paymentId);
|
||||
|
||||
//! Namespace your cacheAttribute keys to avoid collisions
|
||||
Q_INVOKABLE bool setCacheAttribute(const QString &key, const QString &val);
|
||||
Q_INVOKABLE QString getCacheAttribute(const QString &key) const;
|
||||
@@ -380,7 +375,11 @@ signals:
|
||||
void deviceShowAddressShowed();
|
||||
|
||||
// emitted when transaction is created async
|
||||
void transactionCreated(PendingTransaction * transaction, QString address, QString paymentId, quint32 mixinCount);
|
||||
void transactionCreated(
|
||||
PendingTransaction *transaction,
|
||||
const QVector<QString> &addresses,
|
||||
const QString &paymentId,
|
||||
quint32 mixinCount);
|
||||
|
||||
void connectionStatusChanged(int status) const;
|
||||
void currentSubaddressAccountChanged() const;
|
||||
@@ -413,6 +412,13 @@ private:
|
||||
quint64 restoreHeight,
|
||||
const QString& proxyAddress);
|
||||
|
||||
PendingTransaction *createTransaction(
|
||||
const QVector<QString> &destinationAddresses,
|
||||
const QString &payment_id,
|
||||
const QVector<QString> &destinationAmounts,
|
||||
quint32 mixin_count,
|
||||
PendingTransaction::Priority priority);
|
||||
|
||||
bool disconnected() const;
|
||||
bool refreshing() const;
|
||||
void refreshingSet(bool value);
|
||||
@@ -431,7 +437,6 @@ private:
|
||||
// Used for UI history view
|
||||
mutable TransactionHistoryModel * m_historyModel;
|
||||
mutable TransactionHistorySortFilterModel * m_historySortFilterModel;
|
||||
QString m_paymentId;
|
||||
AddressBook * m_addressBook;
|
||||
mutable AddressBookModel * m_addressBookModel;
|
||||
mutable QElapsedTimer m_daemonBlockChainHeightTime;
|
||||
@@ -444,7 +449,7 @@ private:
|
||||
int m_connectionStatusTtl;
|
||||
mutable QElapsedTimer m_connectionStatusTime;
|
||||
bool m_disconnected;
|
||||
mutable bool m_initialized;
|
||||
std::atomic<bool> m_initialized;
|
||||
uint32_t m_currentSubaddressAccount;
|
||||
Subaddress * m_subaddress;
|
||||
mutable SubaddressModel * m_subaddressModel;
|
||||
|
||||
@@ -31,6 +31,8 @@
|
||||
#include "wallet/api/wallet2_api.h"
|
||||
#include "zxcvbn-c/zxcvbn.h"
|
||||
#include "QRCodeImageProvider.h"
|
||||
#include <QClipboard>
|
||||
#include <QGuiApplication>
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
#include <QDir>
|
||||
@@ -169,7 +171,7 @@ Wallet *WalletManager::createWalletFromKeys(const QString &path, const QString &
|
||||
}
|
||||
|
||||
Wallet *WalletManager::createWalletFromDevice(const QString &path, const QString &password, NetworkType::Type nettype,
|
||||
const QString &deviceName, quint64 restoreHeight, const QString &subaddressLookahead)
|
||||
const QString &deviceName, quint64 restoreHeight, const QString &subaddressLookahead, quint64 kdfRounds)
|
||||
{
|
||||
QMutexLocker locker(&m_mutex);
|
||||
WalletPassphraseListenerImpl tmpListener(this);
|
||||
@@ -187,7 +189,7 @@ Wallet *WalletManager::createWalletFromDevice(const QString &path, const QString
|
||||
m_currentWallet = NULL;
|
||||
}
|
||||
Monero::Wallet * w = m_pimpl->createWalletFromDevice(path.toStdString(), password.toStdString(), static_cast<Monero::NetworkType>(nettype),
|
||||
deviceName.toStdString(), restoreHeight, subaddressLookahead.toStdString(), 1, &tmpListener);
|
||||
deviceName.toStdString(), restoreHeight, subaddressLookahead.toStdString(), kdfRounds, &tmpListener);
|
||||
w->setListener(nullptr);
|
||||
|
||||
m_currentWallet = new Wallet(w);
|
||||
@@ -202,10 +204,10 @@ Wallet *WalletManager::createWalletFromDevice(const QString &path, const QString
|
||||
|
||||
|
||||
void WalletManager::createWalletFromDeviceAsync(const QString &path, const QString &password, NetworkType::Type nettype,
|
||||
const QString &deviceName, quint64 restoreHeight, const QString &subaddressLookahead)
|
||||
const QString &deviceName, quint64 restoreHeight, const QString &subaddressLookahead, quint64 kdfRounds)
|
||||
{
|
||||
m_scheduler.run([this, path, password, nettype, deviceName, restoreHeight, subaddressLookahead] {
|
||||
Wallet *wallet = createWalletFromDevice(path, password, nettype, deviceName, restoreHeight, subaddressLookahead);
|
||||
m_scheduler.run([this, path, password, nettype, deviceName, restoreHeight, subaddressLookahead, kdfRounds] {
|
||||
Wallet *wallet = createWalletFromDevice(path, password, nettype, deviceName, restoreHeight, subaddressLookahead, kdfRounds);
|
||||
emit walletCreated(wallet);
|
||||
});
|
||||
}
|
||||
@@ -251,7 +253,7 @@ QString WalletManager::errorString() const
|
||||
return tr("Unknown error");
|
||||
}
|
||||
|
||||
quint64 WalletManager::maximumAllowedAmount() const
|
||||
quint64 WalletManager::maximumAllowedAmount()
|
||||
{
|
||||
return Monero::Wallet::maximumAllowedAmount();
|
||||
}
|
||||
@@ -266,7 +268,7 @@ QString WalletManager::displayAmount(quint64 amount)
|
||||
return QString::fromStdString(Monero::Wallet::displayAmount(amount));
|
||||
}
|
||||
|
||||
quint64 WalletManager::amountFromString(const QString &amount) const
|
||||
quint64 WalletManager::amountFromString(const QString &amount)
|
||||
{
|
||||
return Monero::Wallet::amountFromString(amount.toStdString());
|
||||
}
|
||||
@@ -276,6 +278,17 @@ quint64 WalletManager::amountFromDouble(double amount) const
|
||||
return Monero::Wallet::amountFromDouble(amount);
|
||||
}
|
||||
|
||||
QString WalletManager::amountsSumFromStrings(const QVector<QString> &amounts)
|
||||
{
|
||||
quint64 sum = 0;
|
||||
for (const auto &amountString : amounts)
|
||||
{
|
||||
const quint64 amount = amountFromString(amountString);
|
||||
sum = sum + std::min(maximumAllowedAmount() - sum, amount);
|
||||
}
|
||||
return QString::number(sum);
|
||||
}
|
||||
|
||||
bool WalletManager::paymentIdValid(const QString &payment_id) const
|
||||
{
|
||||
return Monero::Wallet::paymentIdValid(payment_id.toStdString());
|
||||
@@ -448,7 +461,6 @@ QUrl WalletManager::localPathToUrl(const QString &path) const
|
||||
return QUrl::fromLocalFile(path);
|
||||
}
|
||||
|
||||
#ifndef DISABLE_PASS_STRENGTH_METER
|
||||
double WalletManager::getPasswordStrength(const QString &password) const
|
||||
{
|
||||
static const char *local_dict[] = {
|
||||
@@ -463,7 +475,6 @@ double WalletManager::getPasswordStrength(const QString &password) const
|
||||
ZxcvbnUnInit();
|
||||
return e;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool WalletManager::saveQrCode(const QString &code, const QString &path) const
|
||||
{
|
||||
@@ -471,6 +482,14 @@ bool WalletManager::saveQrCode(const QString &code, const QString &path) const
|
||||
return QRCodeImageProvider::genQrImage(code, &size).scaled(size.expandedTo(QSize(240, 240)), Qt::KeepAspectRatio).save(path, "PNG", 100);
|
||||
}
|
||||
|
||||
void WalletManager::saveQrCodeToClipboard(const QString &code) const
|
||||
{
|
||||
QClipboard *clipboard = QGuiApplication::clipboard();
|
||||
QSize size;
|
||||
clipboard->setImage(QRCodeImageProvider::genQrImage(code, &size).scaled(size.expandedTo(QSize(240, 240)), Qt::KeepAspectRatio), QClipboard::Clipboard);
|
||||
clipboard->setImage(QRCodeImageProvider::genQrImage(code, &size).scaled(size.expandedTo(QSize(240, 240)), Qt::KeepAspectRatio), QClipboard::Selection);
|
||||
}
|
||||
|
||||
void WalletManager::checkUpdatesAsync(
|
||||
const QString &software,
|
||||
const QString &subdir,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user