mirror of
https://github.com/monero-project/monero-gui.git
synced 2026-04-10 13:07:26 -04:00
Compare commits
243 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
816eeb4647 | ||
|
|
d5b4f43f48 | ||
|
|
4597b4d94d | ||
|
|
691fdac7a4 | ||
|
|
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 | ||
|
|
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 | ||
|
|
158e0c3523 | ||
|
|
770a7a344b | ||
|
|
f3ddf525a4 | ||
|
|
cedfa5aabb | ||
|
|
df2b85e7ee | ||
|
|
e86fa3e4fb | ||
|
|
5702bdef39 | ||
|
|
c7213abb9a | ||
|
|
5ee363f9f3 | ||
|
|
3e01647744 | ||
|
|
f491b41100 | ||
|
|
a564abbe6b | ||
|
|
149732af3a | ||
|
|
2bb6da5f09 | ||
|
|
11370c50eb | ||
|
|
0ae4677a25 | ||
|
|
1c2879bda3 | ||
|
|
0997b38e1e | ||
|
|
be177d6205 | ||
|
|
919b2e4f3a | ||
|
|
8b9580d621 | ||
|
|
6f5bacabfd | ||
|
|
6fab741f2e | ||
|
|
c2977ac410 | ||
|
|
1adf58793f | ||
|
|
9fa597bb58 | ||
|
|
d79f8e8b17 | ||
|
|
a817bfba05 | ||
|
|
04429e85e6 | ||
|
|
e52d86d442 | ||
|
|
7f164e739a | ||
|
|
43214de7d0 | ||
|
|
0cf683a6cf | ||
|
|
c9fd9634ee | ||
|
|
ddcee95b88 | ||
|
|
299067a273 | ||
|
|
08635e3030 | ||
|
|
fdff5f68dd | ||
|
|
9b18344d23 | ||
|
|
153154f484 | ||
|
|
ee0137056d | ||
|
|
1b0f274aed | ||
|
|
cd054f6c26 | ||
|
|
d6cb9b6c85 | ||
|
|
852378accb | ||
|
|
fe73011422 | ||
|
|
9d2f083a97 | ||
|
|
33afd0bb83 | ||
|
|
a165a14519 | ||
|
|
33e1801c57 | ||
|
|
fac3fcb518 | ||
|
|
8457055f08 | ||
|
|
e01c847fde | ||
|
|
bedf04d08a | ||
|
|
83da709436 | ||
|
|
f51b0d7d0c | ||
|
|
1f9d60602a | ||
|
|
7a285b3613 | ||
|
|
6ee5effc15 | ||
|
|
954c972530 | ||
|
|
cd3a0f85a6 | ||
|
|
e5b0837c8e | ||
|
|
a73ae62526 | ||
|
|
44df1bccfc | ||
|
|
0a0dbf8853 | ||
|
|
1373e709d6 | ||
|
|
baa0ffa5f9 | ||
|
|
25ca081109 | ||
|
|
b932df85fd | ||
|
|
9da52f2387 | ||
|
|
79ee893499 | ||
|
|
1b2d940850 | ||
|
|
db4273ee82 | ||
|
|
05733c14b7 | ||
|
|
56722e4747 |
96
.github/workflows/build.yml
vendored
96
.github/workflows/build.yml
vendored
@@ -1,4 +1,4 @@
|
|||||||
name: continuous-integration/gh-actions/gui
|
name: ci/gh-actions/gui
|
||||||
|
|
||||||
on: [push, pull_request]
|
on: [push, pull_request]
|
||||||
|
|
||||||
@@ -10,7 +10,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
- name: install dependencies
|
- 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
|
- name: build
|
||||||
run: DEV_MODE=ON make release -j3
|
run: DEV_MODE=ON make release -j3
|
||||||
- name: test qml
|
- name: test qml
|
||||||
@@ -34,7 +34,7 @@ jobs:
|
|||||||
- name: install monero dependencies
|
- 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
|
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
|
- name: install monero gui dependencies
|
||||||
run: sudo apt -y install qtbase5-dev qt5-default qtdeclarative5-dev qml-module-qtquick-controls qml-module-qtquick-controls2 qml-module-qtquick-dialogs qml-module-qtquick-xmllistmodel qml-module-qt-labs-settings qml-module-qt-labs-folderlistmodel qttools5-dev-tools qml-module-qtquick-templates2 libqt5svg5-dev libgcrypt20-dev xvfb
|
run: sudo apt -y install qtbase5-dev qt5-default qtdeclarative5-dev qml-module-qtqml-models2 qml-module-qtquick-controls qml-module-qtquick-controls2 qml-module-qtquick-dialogs qml-module-qtquick-xmllistmodel qml-module-qt-labs-settings qml-module-qt-labs-folderlistmodel qttools5-dev-tools qml-module-qtquick-templates2 libqt5svg5-dev libgcrypt20-dev xvfb
|
||||||
- name: build
|
- name: build
|
||||||
run: DEV_MODE=ON make release -j3
|
run: DEV_MODE=ON make release -j3
|
||||||
- name: test qml
|
- name: test qml
|
||||||
@@ -49,7 +49,7 @@ jobs:
|
|||||||
- uses: actions/checkout@v1
|
- uses: actions/checkout@v1
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
- uses: eine/setup-msys2@v1
|
- uses: eine/setup-msys2@v2
|
||||||
with:
|
with:
|
||||||
update: true
|
update: true
|
||||||
install: mingw-w64-x86_64-toolchain make mingw-w64-x86_64-cmake mingw-w64-x86_64-boost mingw-w64-x86_64-openssl mingw-w64-x86_64-zeromq mingw-w64-x86_64-libsodium mingw-w64-x86_64-hidapi mingw-w64-x86_64-protobuf-c mingw-w64-x86_64-libusb git mingw-w64-x86_64-qt5 mingw-w64-x86_64-libgcrypt
|
install: mingw-w64-x86_64-toolchain make mingw-w64-x86_64-cmake mingw-w64-x86_64-boost mingw-w64-x86_64-openssl mingw-w64-x86_64-zeromq mingw-w64-x86_64-libsodium mingw-w64-x86_64-hidapi mingw-w64-x86_64-protobuf-c mingw-w64-x86_64-libusb git mingw-w64-x86_64-qt5 mingw-w64-x86_64-libgcrypt
|
||||||
@@ -58,22 +58,65 @@ jobs:
|
|||||||
- name: test qml
|
- name: test qml
|
||||||
run: build/release/bin/monero-wallet-gui --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:
|
docker-linux-static:
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v1
|
- uses: actions/checkout@v1
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
- uses: satackey/action-docker-layer-caching@v0.0.8
|
- uses: satackey/action-docker-layer-caching@v0.0.10
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
with:
|
with:
|
||||||
key: docker-linux-static-{hash}
|
key: docker-linux-static-{hash}
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
docker-linux-static-
|
docker-linux-static-
|
||||||
|
- name: install dependencies
|
||||||
|
run: sudo apt -y install xvfb libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-randr0 libxcb-render-util0 libxcb-xkb1 libxkbcommon-x11-0
|
||||||
- name: preprare build enviroment
|
- name: preprare build enviroment
|
||||||
run: docker build --tag monero:build-env-linux --build-arg THREADS=3 --file Dockerfile.linux .
|
run: docker build --tag monero:build-env-linux --build-arg THREADS=3 --file Dockerfile.linux .
|
||||||
- name: build
|
- 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'
|
run: docker run --rm -v /home/runner/work/monero-gui/monero-gui:/monero-gui -w /monero-gui monero:build-env-linux sh -c 'make release-static -j3'
|
||||||
|
- name: sha256sum
|
||||||
|
run: shasum -a256 /home/runner/work/monero-gui/monero-gui/build/release/bin/monero-wallet-gui
|
||||||
|
- name: test qml
|
||||||
|
run: xvfb-run -a /home/runner/work/monero-gui/monero-gui/build/release/bin/monero-wallet-gui --test-qml
|
||||||
|
- uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: ${{ github.job }}
|
||||||
|
path: |
|
||||||
|
/home/runner/work/monero-gui/monero-gui/build/release/bin/monero-wallet-gui
|
||||||
|
/home/runner/work/monero-gui/monero-gui/build/release/bin/monerod
|
||||||
|
|
||||||
docker-windows-static:
|
docker-windows-static:
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
@@ -81,7 +124,7 @@ jobs:
|
|||||||
- uses: actions/checkout@v1
|
- uses: actions/checkout@v1
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
- uses: satackey/action-docker-layer-caching@v0.0.8
|
- uses: satackey/action-docker-layer-caching@v0.0.10
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
with:
|
with:
|
||||||
key: docker-windows-static-{hash}
|
key: docker-windows-static-{hash}
|
||||||
@@ -91,3 +134,44 @@ jobs:
|
|||||||
run: docker build --tag monero:build-env-windows --build-arg THREADS=3 --file Dockerfile.windows .
|
run: docker build --tag monero:build-env-windows --build-arg THREADS=3 --file Dockerfile.windows .
|
||||||
- name: build
|
- 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'
|
run: docker run --rm -v /home/runner/work/monero-gui/monero-gui:/monero-gui -w /monero-gui monero:build-env-windows sh -c 'make depends root=/depends target=x86_64-w64-mingw32 tag=win-x64 -j3'
|
||||||
|
- name: sha256sum
|
||||||
|
run: shasum -a256 /home/runner/work/monero-gui/monero-gui/build/x86_64-w64-mingw32/release/bin/monero-wallet-gui.exe
|
||||||
|
- uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: ${{ github.job }}
|
||||||
|
path: |
|
||||||
|
/home/runner/work/monero-gui/monero-gui/build/x86_64-w64-mingw32/release/bin/monero-wallet-gui.exe
|
||||||
|
/home/runner/work/monero-gui/monero-gui/build/x86_64-w64-mingw32/release/bin/monerod.exe
|
||||||
|
|
||||||
|
docker-android:
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v1
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
- name: preprare build enviroment
|
||||||
|
run: docker build --tag monero:build-env-android --build-arg THREADS=3 --file Dockerfile.android .
|
||||||
|
- name: build
|
||||||
|
run: docker run --rm -v /home/runner/work/monero-gui/monero-gui:/monero-gui -e THREADS=3 monero:build-env-android
|
||||||
|
- uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: ${{ github.job }}
|
||||||
|
path: /home/runner/work/monero-gui/monero-gui/build/Android/release/android-build/monero-gui.apk
|
||||||
|
|
||||||
|
source-archive:
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v1
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
- name: archive
|
||||||
|
run: |
|
||||||
|
pip install git-archive-all
|
||||||
|
export VERSION="monero-gui-$(git describe)"
|
||||||
|
export OUTPUT="$VERSION.tar"
|
||||||
|
echo "OUTPUT=$OUTPUT" >> $GITHUB_ENV
|
||||||
|
/home/runner/.local/bin/git-archive-all --prefix "$VERSION/" --force-submodules "$OUTPUT"
|
||||||
|
- uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: ${{ env.OUTPUT }}
|
||||||
|
path: /home/runner/work/monero-gui/monero-gui/${{ env.OUTPUT }}
|
||||||
|
|||||||
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -2,3 +2,6 @@
|
|||||||
path = monero
|
path = monero
|
||||||
url = https://github.com/monero-project/monero
|
url = https://github.com/monero-project/monero
|
||||||
ignore = all
|
ignore = all
|
||||||
|
[submodule "external/quirc"]
|
||||||
|
path = external/quirc
|
||||||
|
url = https://github.com/dlbeer/quirc/
|
||||||
|
|||||||
103
CMakeLists.txt
103
CMakeLists.txt
@@ -1,10 +1,10 @@
|
|||||||
cmake_minimum_required(VERSION 3.5)
|
cmake_minimum_required(VERSION 3.12)
|
||||||
project(monero-gui)
|
project(monero-gui)
|
||||||
|
|
||||||
message(STATUS "Initiating compile using CMake ${CMAKE_VERSION}")
|
message(STATUS "Initiating compile using CMake ${CMAKE_VERSION}")
|
||||||
|
|
||||||
set(VERSION_MAJOR "17")
|
set(VERSION_MAJOR "17")
|
||||||
set(VERSION_MINOR "1")
|
set(VERSION_MINOR "2")
|
||||||
set(VERSION_REVISION "0")
|
set(VERSION_REVISION "0")
|
||||||
set(VERSION "0.${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_REVISION}")
|
set(VERSION "0.${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_REVISION}")
|
||||||
|
|
||||||
@@ -48,8 +48,9 @@ if(NOT MANUAL_SUBMODULES)
|
|||||||
else()
|
else()
|
||||||
execute_process(COMMAND ${GIT_EXECUTABLE} fetch WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/monero RESULT_VARIABLE GIT_FETCH_RESULT)
|
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} 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)
|
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")
|
message(FATAL_ERROR "Updating git submodule to master (-DDEV_MODE=ON) failed")
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
@@ -76,7 +77,7 @@ if(STATIC)
|
|||||||
message(STATUS "Initiating static build")
|
message(STATUS "Initiating static build")
|
||||||
set(Boost_USE_STATIC_LIBS ON)
|
set(Boost_USE_STATIC_LIBS ON)
|
||||||
set(Boost_USE_STATIC_RUNTIME ON)
|
set(Boost_USE_STATIC_RUNTIME ON)
|
||||||
set(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
|
set(CMAKE_FIND_LIBRARY_SUFFIXES ".a" ${CMAKE_FIND_LIBRARY_SUFFIXES})
|
||||||
add_definitions(-DMONERO_GUI_STATIC)
|
add_definitions(-DMONERO_GUI_STATIC)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@@ -131,12 +132,8 @@ message(STATUS "OpenSSL: Version ${OPENSSL_VERSION}")
|
|||||||
message(STATUS "OpenSSL: include dir at ${OPENSSL_INCLUDE_DIR}")
|
message(STATUS "OpenSSL: include dir at ${OPENSSL_INCLUDE_DIR}")
|
||||||
message(STATUS "OpenSSL: libraries at ${OPENSSL_LIBRARIES} ${OPENSSL_SSL_LIBRARIES}")
|
message(STATUS "OpenSSL: libraries at ${OPENSSL_LIBRARIES} ${OPENSSL_SSL_LIBRARIES}")
|
||||||
|
|
||||||
# Zbar (for QR scanner)
|
|
||||||
if(WITH_SCANNER)
|
if(WITH_SCANNER)
|
||||||
add_definitions(-DWITH_SCANNER)
|
add_definitions(-DWITH_SCANNER)
|
||||||
find_package(ZBar0)
|
|
||||||
message(STATUS "libzbar: include dir at ${ZBAR_INCLUDE_DIR}")
|
|
||||||
message(STATUS "libzbar: libraries at ${ZBAR_LIBRARIES}")
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Sodium
|
# Sodium
|
||||||
@@ -149,9 +146,11 @@ message(STATUS "libusb: include dir at ${LibUSB_INCLUDE_DIRS}")
|
|||||||
message(STATUS "libusb: libraries at ${LibUSB_LIBRARIES}")
|
message(STATUS "libusb: libraries at ${LibUSB_LIBRARIES}")
|
||||||
|
|
||||||
# HIDApi
|
# HIDApi
|
||||||
find_package(HIDAPI REQUIRED)
|
if(NOT ANDROID)
|
||||||
message(STATUS "libhidapi: include dir at ${HIDAPI_INCLUDE_DIRS}")
|
find_package(HIDAPI REQUIRED)
|
||||||
message(STATUS "libhidapi: libraries at ${HIDAPI_LIBRARIES}")
|
message(STATUS "libhidapi: include dir at ${HIDAPI_INCLUDE_DIRS}")
|
||||||
|
message(STATUS "libhidapi: libraries at ${HIDAPI_LIBRARIES}")
|
||||||
|
endif()
|
||||||
|
|
||||||
# Boost
|
# Boost
|
||||||
if(DEBUG)
|
if(DEBUG)
|
||||||
@@ -174,9 +173,12 @@ find_package(Boost 1.58 REQUIRED COMPONENTS
|
|||||||
program_options
|
program_options
|
||||||
locale)
|
locale)
|
||||||
|
|
||||||
if(UNIX AND NOT APPLE)
|
if(UNIX AND NOT APPLE AND NOT ANDROID)
|
||||||
set(CMAKE_SKIP_RPATH ON)
|
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)
|
find_package(X11 REQUIRED)
|
||||||
|
set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES_PREV})
|
||||||
message(STATUS "X11_FOUND = ${X11_FOUND}")
|
message(STATUS "X11_FOUND = ${X11_FOUND}")
|
||||||
message(STATUS "X11_INCLUDE_DIR = ${X11_INCLUDE_DIR}")
|
message(STATUS "X11_INCLUDE_DIR = ${X11_INCLUDE_DIR}")
|
||||||
message(STATUS "X11_LIBRARIES = ${X11_LIBRARIES}")
|
message(STATUS "X11_LIBRARIES = ${X11_LIBRARIES}")
|
||||||
@@ -204,9 +206,7 @@ endif()
|
|||||||
set(QT5_LIBRARIES
|
set(QT5_LIBRARIES
|
||||||
Qt5Core
|
Qt5Core
|
||||||
Qt5Quick
|
Qt5Quick
|
||||||
Qt5Widgets
|
|
||||||
Qt5Gui
|
Qt5Gui
|
||||||
Qt5Network
|
|
||||||
Qt5Qml
|
Qt5Qml
|
||||||
Qt5Svg
|
Qt5Svg
|
||||||
Qt5Xml
|
Qt5Xml
|
||||||
@@ -218,20 +218,17 @@ endif()
|
|||||||
|
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
list(APPEND QT5_LIBRARIES Qt5MacExtras)
|
list(APPEND QT5_LIBRARIES Qt5MacExtras)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(UNIX)
|
||||||
if(NOT CMAKE_PREFIX_PATH AND DEFINED ENV{CMAKE_PREFIX_PATH})
|
if(NOT CMAKE_PREFIX_PATH AND DEFINED ENV{CMAKE_PREFIX_PATH})
|
||||||
message(STATUS "Using CMAKE_PREFIX_PATH environment variable: '$ENV{CMAKE_PREFIX_PATH}'")
|
message(STATUS "Using CMAKE_PREFIX_PATH environment variable: '$ENV{CMAKE_PREFIX_PATH}'")
|
||||||
set(CMAKE_PREFIX_PATH $ENV{CMAKE_PREFIX_PATH})
|
set(CMAKE_PREFIX_PATH $ENV{CMAKE_PREFIX_PATH})
|
||||||
endif()
|
endif()
|
||||||
if(NOT CMAKE_PREFIX_PATH)
|
if(APPLE AND NOT CMAKE_PREFIX_PATH)
|
||||||
execute_process(COMMAND brew --prefix qt5 OUTPUT_VARIABLE QT5_DIR OUTPUT_STRIP_TRAILING_WHITESPACE)
|
execute_process(COMMAND brew --prefix qt5 OUTPUT_VARIABLE QT5_DIR OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||||
list(APPEND CMAKE_PREFIX_PATH ${QT5_DIR})
|
list(APPEND CMAKE_PREFIX_PATH ${QT5_DIR})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CMAKE_PREFIX_PATH)
|
|
||||||
include_directories(${CMAKE_PREFIX_PATH}/include)
|
|
||||||
set(CMAKE_BUILD_RPATH "${CMAKE_PREFIX_PATH}/lib")
|
|
||||||
endif()
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
find_package(PkgConfig REQUIRED)
|
find_package(PkgConfig REQUIRED)
|
||||||
@@ -253,7 +250,22 @@ foreach(QT5_MODULE ${QT5_LIBRARIES})
|
|||||||
include_directories(${${QT5_MODULE}_INCLUDE_DIRS})
|
include_directories(${${QT5_MODULE}_INCLUDE_DIRS})
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
pkg_check_modules(QT5_PKG_CONFIG REQUIRED ${QT5_LIBRARIES})
|
if(NOT (CMAKE_CROSSCOMPILING AND ANDROID))
|
||||||
|
pkg_check_modules(QT5_PKG_CONFIG REQUIRED ${QT5_LIBRARIES})
|
||||||
|
else()
|
||||||
|
set(QT5_LIBRARIES_ABI)
|
||||||
|
foreach(QT5_MODULE ${QT5_LIBRARIES})
|
||||||
|
list(APPEND QT5_LIBRARIES_ABI "${QT5_MODULE}_${CMAKE_ANDROID_ARCH_ABI}")
|
||||||
|
endforeach()
|
||||||
|
pkg_check_modules(QT5_PKG_CONFIG REQUIRED ${QT5_LIBRARIES_ABI})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
get_target_property(QMAKE_IMPORTED_LOCATION Qt5::qmake IMPORTED_LOCATION)
|
||||||
|
get_filename_component(QT_INSTALL_PREFIX "${QMAKE_IMPORTED_LOCATION}/../.." ABSOLUTE)
|
||||||
|
|
||||||
|
if(APPLE AND NOT STATIC)
|
||||||
|
set(CMAKE_BUILD_RPATH "${QT_INSTALL_PREFIX}/lib")
|
||||||
|
endif()
|
||||||
|
|
||||||
if(QT5_PKG_CONFIG_FOUND)
|
if(QT5_PKG_CONFIG_FOUND)
|
||||||
set(QT5_PKG_CONFIG "QT5_PKG_CONFIG")
|
set(QT5_PKG_CONFIG "QT5_PKG_CONFIG")
|
||||||
@@ -261,15 +273,15 @@ if(QT5_PKG_CONFIG_FOUND)
|
|||||||
set(QT5_PKG_CONFIG "${QT5_PKG_CONFIG}_STATIC")
|
set(QT5_PKG_CONFIG "${QT5_PKG_CONFIG}_STATIC")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(APPLE)
|
if(UNIX AND CMAKE_PREFIX_PATH)
|
||||||
list(JOIN ${QT5_PKG_CONFIG}_LDFLAGS_OTHER " " ${QT5_PKG_CONFIG}_LDFLAGS_OTHER)
|
if(APPLE)
|
||||||
list(JOIN ${QT5_PKG_CONFIG}_LIBRARIES " " ${QT5_PKG_CONFIG}_LIBRARIES)
|
list(JOIN ${QT5_PKG_CONFIG}_LDFLAGS_OTHER " " ${QT5_PKG_CONFIG}_LDFLAGS_OTHER)
|
||||||
list(JOIN ${QT5_PKG_CONFIG}_INCLUDE_DIRS " " ${QT5_PKG_CONFIG}_INCLUDE_DIRS)
|
endif()
|
||||||
|
|
||||||
# temporal workaround for https://bugreports.qt.io/browse/QTBUG-80922
|
# 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}" "${QT_INSTALL_PREFIX}" ${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}" "${QT_INSTALL_PREFIX}" ${QT5_PKG_CONFIG}_LIBRARIES "${${QT5_PKG_CONFIG}_LIBRARIES}")
|
||||||
STRING(REPLACE "${QT5_PKG_CONFIG_Qt5Core_PREFIX}" "${CMAKE_PREFIX_PATH}" ${QT5_PKG_CONFIG}_INCLUDE_DIRS "${${QT5_PKG_CONFIG}_INCLUDE_DIRS}")
|
STRING(REPLACE "${QT5_PKG_CONFIG_Qt5Core_PREFIX}" "${QT_INSTALL_PREFIX}" ${QT5_PKG_CONFIG}_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()
|
endif()
|
||||||
|
|
||||||
set(QT5_LIBRARIES ${${QT5_PKG_CONFIG}_LIBRARIES} ${${QT5_PKG_CONFIG}_LDFLAGS_OTHER})
|
set(QT5_LIBRARIES ${${QT5_PKG_CONFIG}_LIBRARIES} ${${QT5_PKG_CONFIG}_LDFLAGS_OTHER})
|
||||||
@@ -290,6 +302,8 @@ if(STATIC)
|
|||||||
list(APPEND QT5_EXTRA_PATHS ${QT5_PKG_CONFIG_Qt5Qml_PREFIX}/qml/QtGraphicalEffects)
|
list(APPEND QT5_EXTRA_PATHS ${QT5_PKG_CONFIG_Qt5Qml_PREFIX}/qml/QtGraphicalEffects)
|
||||||
list(APPEND QT5_EXTRA_PATHS ${QT5_PKG_CONFIG_Qt5Qml_PREFIX}/qml/QtGraphicalEffects/private)
|
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/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.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)
|
||||||
list(APPEND QT5_EXTRA_PATHS ${QT5_PKG_CONFIG_Qt5Qml_PREFIX}/qml/QtQuick/Controls.2)
|
list(APPEND QT5_EXTRA_PATHS ${QT5_PKG_CONFIG_Qt5Qml_PREFIX}/qml/QtQuick/Controls.2)
|
||||||
@@ -312,6 +326,7 @@ if(STATIC)
|
|||||||
qmlsettingsplugin
|
qmlsettingsplugin
|
||||||
qmlxmllistmodelplugin
|
qmlxmllistmodelplugin
|
||||||
qquicklayoutsplugin
|
qquicklayoutsplugin
|
||||||
|
modelsplugin
|
||||||
)
|
)
|
||||||
|
|
||||||
if(WITH_SCANNER)
|
if(WITH_SCANNER)
|
||||||
@@ -330,6 +345,10 @@ if(STATIC)
|
|||||||
windowplugin
|
windowplugin
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if(NOT ${Qt5Core_VERSION} VERSION_LESS 5.14)
|
||||||
|
list(APPEND QT5_EXTRA_LIBRARIES_LIST qmlplugin)
|
||||||
|
endif()
|
||||||
|
|
||||||
set(QT5_EXTRA_LIBRARIES)
|
set(QT5_EXTRA_LIBRARIES)
|
||||||
foreach(LIBRARY ${QT5_EXTRA_LIBRARIES_LIST})
|
foreach(LIBRARY ${QT5_EXTRA_LIBRARIES_LIST})
|
||||||
find_library(${LIBRARY}_LIBRARY ${LIBRARY} PATHS ${QT5_EXTRA_PATHS} REQUIRED)
|
find_library(${LIBRARY}_LIBRARY ${LIBRARY} PATHS ${QT5_EXTRA_PATHS} REQUIRED)
|
||||||
@@ -357,7 +376,6 @@ if(STATIC)
|
|||||||
if(UNIX AND NOT APPLE)
|
if(UNIX AND NOT APPLE)
|
||||||
list(APPEND QT5_INTEGRATION_LIBRARIES_LIST
|
list(APPEND QT5_INTEGRATION_LIBRARIES_LIST
|
||||||
Qt5XcbQpa
|
Qt5XcbQpa
|
||||||
xcb-static
|
|
||||||
Qt5ServiceSupport
|
Qt5ServiceSupport
|
||||||
Qt5GlxSupport
|
Qt5GlxSupport
|
||||||
)
|
)
|
||||||
@@ -371,11 +389,30 @@ if(STATIC)
|
|||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
if(UNIX AND NOT APPLE)
|
if(UNIX AND NOT APPLE)
|
||||||
pkg_check_modules(X11XCB_XCBGLX_FONTCONFIG REQUIRED x11-xcb xcb-glx fontconfig)
|
pkg_check_modules(X11XCB_XCBGLX REQUIRED x11-xcb xcb-glx)
|
||||||
list(APPEND QT5_LIBRARIES ${X11XCB_XCBGLX_FONTCONFIG_STATIC_LIBRARIES})
|
list(APPEND QT5_LIBRARIES ${X11XCB_XCBGLX_LIBRARIES})
|
||||||
|
pkg_check_modules(FONTCONFIG REQUIRED fontconfig)
|
||||||
|
list(APPEND QT5_LIBRARIES ${FONTCONFIG_STATIC_LIBRARIES})
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(ANDROID)
|
||||||
|
set(QT5_EXTRA_LIBRARIES_LIST
|
||||||
|
GLESv2
|
||||||
|
log
|
||||||
|
z
|
||||||
|
jnigraphics
|
||||||
|
android
|
||||||
|
EGL
|
||||||
|
Qt5VirtualKeyboard_${CMAKE_ANDROID_ARCH_ABI}
|
||||||
|
c++_shared
|
||||||
|
)
|
||||||
|
foreach(LIBRARY ${QT5_EXTRA_LIBRARIES_LIST})
|
||||||
|
find_library(${LIBRARY}_LIBRARY ${LIBRARY} PATHS "${ANDROID_TOOLCHAIN_ROOT}/sysroot/usr/lib/${CMAKE_LIBRARY_ARCHITECTURE}/${ANDROID_PLATFORM_LEVEL}" REQUIRED)
|
||||||
|
list(APPEND QT5_LIBRARIES ${${LIBRARY}_LIBRARY})
|
||||||
|
endforeach()
|
||||||
|
endif()
|
||||||
|
|
||||||
message(STATUS "Using Boost include dir at ${Boost_INCLUDE_DIRS}")
|
message(STATUS "Using Boost include dir at ${Boost_INCLUDE_DIRS}")
|
||||||
message(STATUS "Using Boost libraries at ${Boost_LIBRARIES}")
|
message(STATUS "Using Boost libraries at ${Boost_LIBRARIES}")
|
||||||
|
|
||||||
@@ -525,6 +562,6 @@ if (HIDAPI_FOUND OR LibUSB_COMPILE_TEST_PASSED)
|
|||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
add_subdirectory(external)
|
||||||
add_subdirectory(translations)
|
add_subdirectory(translations)
|
||||||
|
|
||||||
add_subdirectory(src)
|
add_subdirectory(src)
|
||||||
|
|||||||
14
DEPLOY.md
14
DEPLOY.md
@@ -2,19 +2,17 @@
|
|||||||
|
|
||||||
Use macOS 10.12 - 10.13 for better backwards compability.
|
Use macOS 10.12 - 10.13 for better backwards compability.
|
||||||
|
|
||||||
1. `HOMEBREW_OPTFLAGS="-march=core2" HOMEBREW_OPTIMIZATION_LEVEL="O0" brew install boost zmq libpgm miniupnpc libsodium expat libunwind-headers protobuf libgcrypt`
|
1. `HOMEBREW_OPTFLAGS="-march=core2" HOMEBREW_OPTIMIZATION_LEVEL="O0" brew install boost zmq libpgm miniupnpc libsodium expat libunwind-headers protobuf libgcrypt hidapi`
|
||||||
|
|
||||||
2. `HOMEBREW_OPTFLAGS="-march=core2" HOMEBREW_OPTIMIZATION_LEVEL="O0" brew install --HEAD hidapi`
|
2. Get the latest LTS from here: https://www.qt.io/offline-installers and install
|
||||||
|
|
||||||
3. Get the latest LTS from here: https://www.qt.io/offline-installers and install
|
3. `git clone --recursive -b v0.X.Y.Z --depth 1 https://github.com/monero-project/monero-gui`
|
||||||
|
|
||||||
4. `git clone --recursive -b v0.X.Y.Z --depth 1 https://github.com/monero-project/monero-gui`
|
4. `CMAKE_PREFIX_PATH=~/Qt5.12.8/5.12.8/clang_64 make release`
|
||||||
|
|
||||||
5. `CMAKE_PREFIX_PATH=~/Qt5.12.8/5.12.8/clang_64 make release`
|
5. `cd build/release && make deploy`
|
||||||
|
|
||||||
6. `cd build/release && make deploy`
|
6. Replace the `monerod` binary inside `monero-wallet-gui.app/Contents/MacOS/` with one built using deterministic builds / gitian.
|
||||||
|
|
||||||
7. Replace the `monerod` binary inside `monero-wallet-gui.app/Contents/MacOS/` with one built using deterministic builds / gitian.
|
|
||||||
|
|
||||||
## Codesigning and notarizing
|
## Codesigning and notarizing
|
||||||
|
|
||||||
|
|||||||
207
Dockerfile.android
Normal file
207
Dockerfile.android
Normal file
@@ -0,0 +1,207 @@
|
|||||||
|
FROM debian:stretch
|
||||||
|
|
||||||
|
ARG THREADS=1
|
||||||
|
ARG ANDROID_NDK_REVISION=21d
|
||||||
|
ARG ANDROID_NDK_HASH=bcf4023eb8cb6976a4c7cff0a8a8f145f162bf4d
|
||||||
|
ARG ANDROID_SDK_REVISION=4333796
|
||||||
|
ARG ANDROID_SDK_HASH=92ffee5a1d98d856634e8b71132e8a95d96c83a63fde1099be3d86df3106def9
|
||||||
|
ARG QT_VERSION=5.15.2
|
||||||
|
|
||||||
|
WORKDIR /opt/android
|
||||||
|
ENV WORKDIR=/opt/android
|
||||||
|
|
||||||
|
ENV ANDROID_NATIVE_API_LEVEL=28
|
||||||
|
ENV ANDROID_API=android-${ANDROID_NATIVE_API_LEVEL}
|
||||||
|
ENV ANDROID_CLANG=aarch64-linux-android${ANDROID_NATIVE_API_LEVEL}-clang
|
||||||
|
ENV ANDROID_CLANGPP=aarch64-linux-android${ANDROID_NATIVE_API_LEVEL}-clang++
|
||||||
|
ENV ANDROID_NDK_ROOT=${WORKDIR}/android-ndk-r${ANDROID_NDK_REVISION}
|
||||||
|
ENV ANDROID_SDK_ROOT=${WORKDIR}/tools
|
||||||
|
ENV JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
|
||||||
|
ENV PATH=${JAVA_HOME}/bin:${PATH}
|
||||||
|
ENV PREFIX=${WORKDIR}/prefix
|
||||||
|
ENV TOOLCHAIN_DIR=${ANDROID_NDK_ROOT}/toolchains/llvm/prebuilt/linux-x86_64
|
||||||
|
|
||||||
|
RUN apt-get update \
|
||||||
|
&& apt-get install -y ant automake build-essential ca-certificates-java file gettext git libc6 libncurses5 \
|
||||||
|
libssl-dev libstdc++6 libtinfo5 libtool libz1 openjdk-8-jdk-headless openjdk-8-jre-headless pkg-config python3 \
|
||||||
|
unzip wget
|
||||||
|
|
||||||
|
RUN wget -q https://dl.google.com/android/repository/sdk-tools-linux-${ANDROID_SDK_REVISION}.zip \
|
||||||
|
&& unzip -q sdk-tools-linux-${ANDROID_SDK_REVISION}.zip \
|
||||||
|
&& rm -f sdk-tools-linux-${ANDROID_SDK_REVISION}.zip
|
||||||
|
|
||||||
|
RUN wget -q https://dl.google.com/android/repository/android-ndk-r${ANDROID_NDK_REVISION}-linux-x86_64.zip \
|
||||||
|
&& unzip -q android-ndk-r${ANDROID_NDK_REVISION}-linux-x86_64.zip \
|
||||||
|
&& rm -f android-ndk-r${ANDROID_NDK_REVISION}-linux-x86_64.zip
|
||||||
|
|
||||||
|
RUN cd ${ANDROID_SDK_ROOT} && echo y | ./bin/sdkmanager "platform-tools" "platforms;${ANDROID_API}" "tools" > /dev/null
|
||||||
|
RUN cp -r ${WORKDIR}/platforms ${WORKDIR}/platform-tools ${ANDROID_SDK_ROOT}
|
||||||
|
|
||||||
|
ENV HOST_PATH=${PATH}
|
||||||
|
ENV PATH=${TOOLCHAIN_DIR}/aarch64-linux-android/bin:${TOOLCHAIN_DIR}/bin:${PATH}
|
||||||
|
|
||||||
|
ARG ZLIB_VERSION=1.2.11
|
||||||
|
ARG ZLIB_HASH=c3e5e9fdd5004dcb542feda5ee4f0ff0744628baf8ed2dd5d66f8ca1197cb1a1
|
||||||
|
RUN wget -q https://zlib.net/zlib-${ZLIB_VERSION}.tar.gz \
|
||||||
|
&& tar -xzf zlib-${ZLIB_VERSION}.tar.gz \
|
||||||
|
&& rm zlib-${ZLIB_VERSION}.tar.gz \
|
||||||
|
&& cd zlib-${ZLIB_VERSION} \
|
||||||
|
&& CC=${ANDROID_CLANG} CXX=${ANDROID_CLANGPP} ./configure --prefix=${PREFIX} --static \
|
||||||
|
&& make -j${THREADS} \
|
||||||
|
&& make -j${THREADS} install \
|
||||||
|
&& rm -rf $(pwd)
|
||||||
|
|
||||||
|
RUN git clone git://code.qt.io/qt/qt5.git -b ${QT_VERSION} --depth 1 \
|
||||||
|
&& cd qt5 \
|
||||||
|
&& perl init-repository --module-subset=default,-qtwebengine \
|
||||||
|
&& PATH=${HOST_PATH} ./configure -v -developer-build -release \
|
||||||
|
-xplatform android-clang \
|
||||||
|
-android-ndk-platform ${ANDROID_API} \
|
||||||
|
-android-ndk ${ANDROID_NDK_ROOT} \
|
||||||
|
-android-sdk ${ANDROID_SDK_ROOT} \
|
||||||
|
-android-ndk-host linux-x86_64 \
|
||||||
|
-no-dbus \
|
||||||
|
-opengl es2 \
|
||||||
|
-no-use-gold-linker \
|
||||||
|
-no-sql-mysql \
|
||||||
|
-opensource -confirm-license \
|
||||||
|
-android-arch arm64-v8a \
|
||||||
|
-prefix ${PREFIX} \
|
||||||
|
-nomake tools -nomake tests -nomake examples \
|
||||||
|
-skip qtwebengine \
|
||||||
|
-skip qtserialport \
|
||||||
|
-skip qtconnectivity \
|
||||||
|
-skip qttranslations \
|
||||||
|
-skip qtpurchasing \
|
||||||
|
-skip qtgamepad -skip qtscript -skip qtdoc \
|
||||||
|
-no-warnings-are-errors \
|
||||||
|
&& sed -i '213,215d' qtbase/src/3rdparty/pcre2/src/sljit/sljitConfigInternal.h \
|
||||||
|
&& PATH=${HOST_PATH} make -j${THREADS} \
|
||||||
|
&& PATH=${HOST_PATH} make -j${THREADS} install \
|
||||||
|
&& cd qttools/src/linguist/lrelease \
|
||||||
|
&& ../../../../qtbase/bin/qmake \
|
||||||
|
&& PATH=${HOST_PATH} make -j${THREADS} install \
|
||||||
|
&& cd ../../../.. \
|
||||||
|
&& rm -rf $(pwd)
|
||||||
|
|
||||||
|
ARG ICONV_VERSION=1.16
|
||||||
|
ARG ICONV_HASH=e6a1b1b589654277ee790cce3734f07876ac4ccfaecbee8afa0b649cf529cc04
|
||||||
|
RUN wget -q http://ftp.gnu.org/pub/gnu/libiconv/libiconv-${ICONV_VERSION}.tar.gz \
|
||||||
|
&& echo "${ICONV_HASH} libiconv-${ICONV_VERSION}.tar.gz" | sha256sum -c \
|
||||||
|
&& tar -xzf libiconv-${ICONV_VERSION}.tar.gz \
|
||||||
|
&& rm -f libiconv-${ICONV_VERSION}.tar.gz \
|
||||||
|
&& cd libiconv-${ICONV_VERSION} \
|
||||||
|
&& CC=${ANDROID_CLANG} CXX=${ANDROID_CLANGPP} ./configure --build=x86_64-linux-gnu --host=aarch64 --prefix=${PREFIX} --disable-rpath \
|
||||||
|
&& make -j${THREADS} \
|
||||||
|
&& make -j${THREADS} install
|
||||||
|
|
||||||
|
ARG BOOST_VERSION=1_74_0
|
||||||
|
ARG BOOST_VERSION_DOT=1.74.0
|
||||||
|
ARG BOOST_HASH=83bfc1507731a0906e387fc28b7ef5417d591429e51e788417fe9ff025e116b1
|
||||||
|
RUN wget -q https://dl.bintray.com/boostorg/release/${BOOST_VERSION_DOT}/source/boost_${BOOST_VERSION}.tar.bz2 \
|
||||||
|
&& echo "${BOOST_HASH} boost_${BOOST_VERSION}.tar.bz2" | sha256sum -c \
|
||||||
|
&& tar -xf boost_${BOOST_VERSION}.tar.bz2 \
|
||||||
|
&& rm -f boost_${BOOST_VERSION}.tar.bz2 \
|
||||||
|
&& cd boost_${BOOST_VERSION} \
|
||||||
|
&& PATH=${HOST_PATH} ./bootstrap.sh --prefix=${PREFIX} \
|
||||||
|
&& PATH=${TOOLCHAIN_DIR}/bin:${HOST_PATH} ./b2 --build-type=minimal link=static runtime-link=static \
|
||||||
|
--with-chrono --with-date_time --with-filesystem --with-program_options --with-regex --with-serialization \
|
||||||
|
--with-system --with-thread --with-locale --build-dir=android --stagedir=android toolset=clang threading=multi \
|
||||||
|
threadapi=pthread target-os=android -sICONV_PATH=${PREFIX} \
|
||||||
|
cflags='--target=aarch64-linux-android' \
|
||||||
|
cxxflags='--target=aarch64-linux-android' \
|
||||||
|
linkflags='--target=aarch64-linux-android --sysroot=${ANDROID_NDK_ROOT}/platforms/${ANDROID_API}/arch-arm64 ${ANDROID_NDK_ROOT}/sources/cxx-stl/llvm-libc++/libs/arm64-v8a/libc++_shared.so -nostdlib++' \
|
||||||
|
install -j${THREADS} \
|
||||||
|
&& rm -rf $(pwd)
|
||||||
|
|
||||||
|
ARG OPENSSL_VERSION=1.1.1g
|
||||||
|
ARG OPENSSL_HASH=ddb04774f1e32f0c49751e21b67216ac87852ceb056b75209af2443400636d46
|
||||||
|
RUN wget -q https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz \
|
||||||
|
&& tar -xzf openssl-${OPENSSL_VERSION}.tar.gz \
|
||||||
|
&& rm openssl-${OPENSSL_VERSION}.tar.gz \
|
||||||
|
&& cd openssl-${OPENSSL_VERSION} \
|
||||||
|
&& ANDROID_NDK_HOME=${ANDROID_NDK_ROOT} ./Configure CC=${ANDROID_CLANG} CXX=${ANDROID_CLANGPP} \
|
||||||
|
android-arm64 no-asm no-shared --static \
|
||||||
|
--with-zlib-include=${PREFIX}/include --with-zlib-lib=${PREFIX}/lib \
|
||||||
|
--prefix=${PREFIX} --openssldir=${PREFIX} \
|
||||||
|
&& sed -i 's/CNF_EX_LIBS=-ldl -pthread//g;s/BIN_CFLAGS=-pie $(CNF_CFLAGS) $(CFLAGS)//g' Makefile \
|
||||||
|
&& ANDROID_NDK_HOME=${ANDROID_NDK_ROOT} make -j${THREADS} \
|
||||||
|
&& make -j${THREADS} install \
|
||||||
|
&& rm -rf $(pwd)
|
||||||
|
|
||||||
|
ARG ZMQ_VERSION=v4.3.3
|
||||||
|
ARG ZMQ_HASH=04f5bbedee58c538934374dc45182d8fc5926fa3
|
||||||
|
RUN git clone https://github.com/zeromq/libzmq.git -b ${ZMQ_VERSION} --depth 1 \
|
||||||
|
&& cd libzmq \
|
||||||
|
&& git checkout ${ZMQ_HASH} \
|
||||||
|
&& ./autogen.sh \
|
||||||
|
&& CC=${ANDROID_CLANG} CXX=${ANDROID_CLANGPP} ./configure --prefix=${PREFIX} --host=aarch64-linux-android \
|
||||||
|
--enable-static --disable-shared \
|
||||||
|
&& make -j${THREADS} \
|
||||||
|
&& make -j${THREADS} install \
|
||||||
|
&& rm -rf $(pwd)
|
||||||
|
|
||||||
|
ARG SODIUM_VERSION=1.0.18
|
||||||
|
ARG SODIUM_HASH=4f5e89fa84ce1d178a6765b8b46f2b6f91216677
|
||||||
|
RUN set -ex \
|
||||||
|
&& git clone https://github.com/jedisct1/libsodium.git -b ${SODIUM_VERSION} --depth 1 \
|
||||||
|
&& cd libsodium \
|
||||||
|
&& test `git rev-parse HEAD` = ${SODIUM_HASH} || exit 1 \
|
||||||
|
&& ./autogen.sh \
|
||||||
|
&& CC=${ANDROID_CLANG} CXX=${ANDROID_CLANGPP} ./configure --prefix=${PREFIX} --host=aarch64-linux-android --enable-static --disable-shared \
|
||||||
|
&& make -j${THREADS} install \
|
||||||
|
&& rm -rf $(pwd)
|
||||||
|
|
||||||
|
RUN git clone -b libgpg-error-1.38 --depth 1 git://git.gnupg.org/libgpg-error.git \
|
||||||
|
&& cd libgpg-error \
|
||||||
|
&& git reset --hard 71d278824c5fe61865f7927a2ed1aa3115f9e439 \
|
||||||
|
&& ./autogen.sh \
|
||||||
|
&& CC=${ANDROID_CLANG} CXX=${ANDROID_CLANGPP} ./configure --host=aarch64-linux-android --prefix=${PREFIX} --disable-rpath --disable-shared --enable-static --disable-doc --disable-tests \
|
||||||
|
&& PATH=${TOOLCHAIN_DIR}/bin:${HOST_PATH} make -j${THREADS} \
|
||||||
|
&& make -j${THREADS} install \
|
||||||
|
&& rm -rf $(pwd)
|
||||||
|
|
||||||
|
RUN git clone -b libgcrypt-1.8.5 --depth 1 git://git.gnupg.org/libgcrypt.git \
|
||||||
|
&& cd libgcrypt \
|
||||||
|
&& git reset --hard 56606331bc2a80536db9fc11ad53695126007298 \
|
||||||
|
&& ./autogen.sh \
|
||||||
|
&& CC=${ANDROID_CLANG} CXX=${ANDROID_CLANGPP} ./configure --host=aarch64-linux-android --prefix=${PREFIX} --with-gpg-error-prefix=${PREFIX} --disable-shared --enable-static --disable-doc --disable-tests \
|
||||||
|
&& PATH=${TOOLCHAIN_DIR}/bin:${HOST_PATH} make -j${THREADS} \
|
||||||
|
&& make -j${THREADS} install \
|
||||||
|
&& rm -rf $(pwd)
|
||||||
|
|
||||||
|
RUN cd tools \
|
||||||
|
&& wget -q http://dl-ssl.google.com/android/repository/tools_r25.2.5-linux.zip \
|
||||||
|
&& unzip -q tools_r25.2.5-linux.zip \
|
||||||
|
&& rm -f tools_r25.2.5-linux.zip \
|
||||||
|
&& echo y | ${ANDROID_SDK_ROOT}/tools/android update sdk --no-ui --all --filter build-tools-28.0.3
|
||||||
|
|
||||||
|
RUN git clone -b v3.19.7 --depth 1 https://github.com/Kitware/CMake \
|
||||||
|
&& cd CMake \
|
||||||
|
&& git reset --hard 22612dd53a46c7f9b4c3f4b7dbe5c78f9afd9581 \
|
||||||
|
&& PATH=${HOST_PATH} ./bootstrap \
|
||||||
|
&& PATH=${HOST_PATH} make -j${THREADS} \
|
||||||
|
&& PATH=${HOST_PATH} make -j${THREADS} install \
|
||||||
|
&& rm -rf $(pwd)
|
||||||
|
|
||||||
|
CMD set -ex \
|
||||||
|
&& cd /monero-gui \
|
||||||
|
&& mkdir -p build/Android/release \
|
||||||
|
&& cd build/Android/release \
|
||||||
|
&& cmake \
|
||||||
|
-DCMAKE_TOOLCHAIN_FILE="${ANDROID_NDK_ROOT}/build/cmake/android.toolchain.cmake" \
|
||||||
|
-DCMAKE_PREFIX_PATH="${PREFIX}" \
|
||||||
|
-DCMAKE_FIND_ROOT_PATH="${PREFIX}" \
|
||||||
|
-DCMAKE_BUILD_TYPE=Release \
|
||||||
|
-DARCH="armv8-a" \
|
||||||
|
-DANDROID_NATIVE_API_LEVEL=${ANDROID_NATIVE_API_LEVEL} \
|
||||||
|
-DANDROID_ABI="arm64-v8a" \
|
||||||
|
-DANDROID_TOOLCHAIN=clang \
|
||||||
|
-DBoost_USE_STATIC_RUNTIME=ON \
|
||||||
|
-DLRELEASE_PATH="${PREFIX}/bin" \
|
||||||
|
-DQT_ANDROID_APPLICATION_BINARY="monero-wallet-gui" \
|
||||||
|
-DWITH_SCANNER=ON \
|
||||||
|
../../.. \
|
||||||
|
&& PATH=${HOST_PATH} make generate_translations_header \
|
||||||
|
&& make -j${THREADS} -C src \
|
||||||
|
&& make -j${THREADS} apk
|
||||||
171
Dockerfile.linux
171
Dockerfile.linux
@@ -1,6 +1,12 @@
|
|||||||
FROM ubuntu:16.04
|
FROM ubuntu:16.04
|
||||||
|
|
||||||
ARG THREADS=1
|
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
|
||||||
|
|
||||||
@@ -8,7 +14,7 @@ RUN apt install -y automake git pkg-config python xutils-dev && \
|
|||||||
git clone -b xorgproto-2020.1 --depth 1 https://gitlab.freedesktop.org/xorg/proto/xorgproto && \
|
git clone -b xorgproto-2020.1 --depth 1 https://gitlab.freedesktop.org/xorg/proto/xorgproto && \
|
||||||
cd xorgproto && \
|
cd xorgproto && \
|
||||||
git reset --hard c62e8203402cafafa5ba0357b6d1c019156c9f36 && \
|
git reset --hard c62e8203402cafafa5ba0357b6d1c019156c9f36 && \
|
||||||
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./autogen.sh --disable-shared --enable-static && \
|
./autogen.sh && \
|
||||||
make -j$THREADS && \
|
make -j$THREADS && \
|
||||||
make -j$THREADS install && \
|
make -j$THREADS install && \
|
||||||
rm -rf $(pwd)
|
rm -rf $(pwd)
|
||||||
@@ -16,7 +22,7 @@ RUN apt install -y automake git pkg-config python xutils-dev && \
|
|||||||
RUN git clone -b 1.12 --depth 1 https://gitlab.freedesktop.org/xorg/proto/xcbproto && \
|
RUN git clone -b 1.12 --depth 1 https://gitlab.freedesktop.org/xorg/proto/xcbproto && \
|
||||||
cd xcbproto && \
|
cd xcbproto && \
|
||||||
git reset --hard 6398e42131eedddde0d98759067dde933191f049 && \
|
git reset --hard 6398e42131eedddde0d98759067dde933191f049 && \
|
||||||
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./autogen.sh --disable-shared --enable-static && \
|
./autogen.sh && \
|
||||||
make -j$THREADS && \
|
make -j$THREADS && \
|
||||||
make -j$THREADS install && \
|
make -j$THREADS install && \
|
||||||
rm -rf $(pwd)
|
rm -rf $(pwd)
|
||||||
@@ -25,7 +31,7 @@ RUN apt install -y libtool-bin && \
|
|||||||
git clone -b libXau-1.0.9 --depth 1 https://gitlab.freedesktop.org/xorg/lib/libxau && \
|
git clone -b libXau-1.0.9 --depth 1 https://gitlab.freedesktop.org/xorg/lib/libxau && \
|
||||||
cd libxau && \
|
cd libxau && \
|
||||||
git reset --hard d9443b2c57b512cfb250b35707378654d86c7dea && \
|
git reset --hard d9443b2c57b512cfb250b35707378654d86c7dea && \
|
||||||
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./autogen.sh --disable-shared --enable-static && \
|
./autogen.sh --enable-shared --disable-static && \
|
||||||
make -j$THREADS && \
|
make -j$THREADS && \
|
||||||
make -j$THREADS install && \
|
make -j$THREADS install && \
|
||||||
rm -rf $(pwd)
|
rm -rf $(pwd)
|
||||||
@@ -34,7 +40,76 @@ RUN apt install -y libpthread-stubs0-dev && \
|
|||||||
git clone -b 1.12 --depth 1 https://gitlab.freedesktop.org/xorg/lib/libxcb && \
|
git clone -b 1.12 --depth 1 https://gitlab.freedesktop.org/xorg/lib/libxcb && \
|
||||||
cd libxcb && \
|
cd libxcb && \
|
||||||
git reset --hard d34785a34f28fa6a00f8ce00d87e3132ff0f6467 && \
|
git reset --hard d34785a34f28fa6a00f8ce00d87e3132ff0f6467 && \
|
||||||
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./autogen.sh --disable-shared --enable-static && \
|
./autogen.sh --enable-shared --disable-static && \
|
||||||
|
make -j$THREADS && \
|
||||||
|
make -j$THREADS install && \
|
||||||
|
make -j$THREADS clean && \
|
||||||
|
rm /usr/local/lib/libxcb-xinerama.so && \
|
||||||
|
./autogen.sh --disable-shared --enable-static && \
|
||||||
|
make -j$THREADS && \
|
||||||
|
cp src/.libs/libxcb-xinerama.a /usr/local/lib/ && \
|
||||||
|
rm -rf $(pwd)
|
||||||
|
|
||||||
|
RUN git clone -b 0.4.0 --depth 1 https://gitlab.freedesktop.org/xorg/lib/libxcb-util && \
|
||||||
|
cd libxcb-util && \
|
||||||
|
git reset --hard acf790d7752f36e450d476ad79807d4012ec863b && \
|
||||||
|
git submodule init && \
|
||||||
|
git clone --depth 1 https://gitlab.freedesktop.org/xorg/util/xcb-util-m4 m4 && \
|
||||||
|
git -C m4 reset --hard f662e3a93ebdec3d1c9374382dcc070093a42fed && \
|
||||||
|
./autogen.sh --enable-shared --disable-static && \
|
||||||
|
make -j$THREADS && \
|
||||||
|
make -j$THREADS install && \
|
||||||
|
rm -rf $(pwd)
|
||||||
|
|
||||||
|
RUN git clone -b 0.4.0 --depth 1 https://gitlab.freedesktop.org/xorg/lib/libxcb-image && \
|
||||||
|
cd libxcb-image && \
|
||||||
|
git reset --hard d882052fb2ce439c6483fce944ba8f16f7294639 && \
|
||||||
|
git submodule init && \
|
||||||
|
git clone --depth 1 https://gitlab.freedesktop.org/xorg/util/xcb-util-m4 m4 && \
|
||||||
|
git -C m4 reset --hard f662e3a93ebdec3d1c9374382dcc070093a42fed && \
|
||||||
|
./autogen.sh --enable-shared --disable-static && \
|
||||||
|
make -j$THREADS && \
|
||||||
|
make -j$THREADS install && \
|
||||||
|
rm -rf $(pwd)
|
||||||
|
|
||||||
|
RUN git clone -b 0.4.0 --depth 1 https://gitlab.freedesktop.org/xorg/lib/libxcb-keysyms && \
|
||||||
|
cd libxcb-keysyms && \
|
||||||
|
git reset --hard 0e51ee5570a6a80bdf98770b975dfe8a57f4eeb1 && \
|
||||||
|
git submodule init && \
|
||||||
|
git clone --depth 1 https://gitlab.freedesktop.org/xorg/util/xcb-util-m4 m4 && \
|
||||||
|
git -C m4 reset --hard f662e3a93ebdec3d1c9374382dcc070093a42fed && \
|
||||||
|
./autogen.sh --enable-shared --disable-static && \
|
||||||
|
make -j$THREADS && \
|
||||||
|
make -j$THREADS install && \
|
||||||
|
rm -rf $(pwd)
|
||||||
|
|
||||||
|
RUN git clone -b 0.3.9 --depth 1 https://gitlab.freedesktop.org/xorg/lib/libxcb-render-util && \
|
||||||
|
cd libxcb-render-util && \
|
||||||
|
git reset --hard 0317caf63de532fd7a0493ed6afa871a67253747 && \
|
||||||
|
git submodule init && \
|
||||||
|
git clone --depth 1 https://gitlab.freedesktop.org/xorg/util/xcb-util-m4 m4 && \
|
||||||
|
git -C m4 reset --hard f662e3a93ebdec3d1c9374382dcc070093a42fed && \
|
||||||
|
./autogen.sh --enable-shared --disable-static && \
|
||||||
|
make -j$THREADS && \
|
||||||
|
make -j$THREADS install && \
|
||||||
|
rm -rf $(pwd)
|
||||||
|
|
||||||
|
RUN git clone -b 0.4.1 --depth 1 https://gitlab.freedesktop.org/xorg/lib/libxcb-wm && \
|
||||||
|
cd libxcb-wm && \
|
||||||
|
git reset --hard 24eb17df2e1245885e72c9d4bbb0a0f69f0700f2 && \
|
||||||
|
git submodule init && \
|
||||||
|
git clone --depth 1 https://gitlab.freedesktop.org/xorg/util/xcb-util-m4 m4 && \
|
||||||
|
git -C m4 reset --hard f662e3a93ebdec3d1c9374382dcc070093a42fed && \
|
||||||
|
./autogen.sh --enable-shared --disable-static && \
|
||||||
|
make -j$THREADS && \
|
||||||
|
make -j$THREADS install && \
|
||||||
|
rm -rf $(pwd)
|
||||||
|
|
||||||
|
RUN apt install -y bison && \
|
||||||
|
git clone -b xkbcommon-0.5.0 --depth 1 https://github.com/xkbcommon/libxkbcommon && \
|
||||||
|
cd libxkbcommon && \
|
||||||
|
git reset --hard c43c3c866eb9d52cd8f61e75cbef1c30d07f3a28 && \
|
||||||
|
./autogen.sh --prefix=/usr --enable-shared --disable-static --enable-x11 --disable-docs && \
|
||||||
make -j$THREADS && \
|
make -j$THREADS && \
|
||||||
make -j$THREADS install && \
|
make -j$THREADS install && \
|
||||||
rm -rf $(pwd)
|
rm -rf $(pwd)
|
||||||
@@ -42,7 +117,7 @@ RUN apt install -y libpthread-stubs0-dev && \
|
|||||||
RUN git clone -b v1.2.11 --depth 1 https://github.com/madler/zlib && \
|
RUN git clone -b v1.2.11 --depth 1 https://github.com/madler/zlib && \
|
||||||
cd zlib && \
|
cd zlib && \
|
||||||
git reset --hard cacf7f1d4e3d44d871b605da3b647f07d718623f && \
|
git reset --hard cacf7f1d4e3d44d871b605da3b647f07d718623f && \
|
||||||
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./configure --static && \
|
./configure --static && \
|
||||||
make -j$THREADS && \
|
make -j$THREADS && \
|
||||||
make -j$THREADS install && \
|
make -j$THREADS install && \
|
||||||
rm -rf $(pwd)
|
rm -rf $(pwd)
|
||||||
@@ -51,7 +126,7 @@ RUN git clone -b VER-2-10-2 --depth 1 https://git.savannah.gnu.org/git/freetype/
|
|||||||
cd freetype2 && \
|
cd freetype2 && \
|
||||||
git reset --hard 132f19b779828b194b3fede187cee719785db4d8 && \
|
git reset --hard 132f19b779828b194b3fede187cee719785db4d8 && \
|
||||||
./autogen.sh && \
|
./autogen.sh && \
|
||||||
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./configure --disable-shared --enable-static --with-zlib=no && \
|
./configure --disable-shared --enable-static --with-zlib=no && \
|
||||||
make -j$THREADS && \
|
make -j$THREADS && \
|
||||||
make -j$THREADS install && \
|
make -j$THREADS install && \
|
||||||
rm -rf $(pwd)
|
rm -rf $(pwd)
|
||||||
@@ -60,7 +135,7 @@ RUN git clone -b R_2_2_9 --depth 1 https://github.com/libexpat/libexpat && \
|
|||||||
cd libexpat/expat && \
|
cd libexpat/expat && \
|
||||||
git reset --hard a7bc26b69768f7fb24f0c7976fae24b157b85b13 && \
|
git reset --hard a7bc26b69768f7fb24f0c7976fae24b157b85b13 && \
|
||||||
./buildconf.sh && \
|
./buildconf.sh && \
|
||||||
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./configure --disable-shared --enable-static && \
|
./configure --disable-shared --enable-static && \
|
||||||
make -j$THREADS && \
|
make -j$THREADS && \
|
||||||
make -j$THREADS install && \
|
make -j$THREADS install && \
|
||||||
rm -rf $(pwd)
|
rm -rf $(pwd)
|
||||||
@@ -69,7 +144,7 @@ RUN apt install -y autopoint gettext gperf libpng12-dev && \
|
|||||||
git clone -b 2.13.92 --depth 1 https://gitlab.freedesktop.org/fontconfig/fontconfig && \
|
git clone -b 2.13.92 --depth 1 https://gitlab.freedesktop.org/fontconfig/fontconfig && \
|
||||||
cd fontconfig && \
|
cd fontconfig && \
|
||||||
git reset --hard b1df1101a643ae16cdfa1d83b939de2497b1bf27 && \
|
git reset --hard b1df1101a643ae16cdfa1d83b939de2497b1bf27 && \
|
||||||
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./autogen.sh --disable-shared --enable-static --sysconfdir=/etc --localstatedir=/var && \
|
./autogen.sh --disable-shared --enable-static --sysconfdir=/etc --localstatedir=/var && \
|
||||||
make -j$THREADS && \
|
make -j$THREADS && \
|
||||||
make -j$THREADS install && \
|
make -j$THREADS install && \
|
||||||
rm -rf $(pwd)
|
rm -rf $(pwd)
|
||||||
@@ -77,46 +152,56 @@ RUN apt install -y autopoint gettext gperf libpng12-dev && \
|
|||||||
RUN git clone -b release-64-2 --depth 1 https://github.com/unicode-org/icu && \
|
RUN git clone -b release-64-2 --depth 1 https://github.com/unicode-org/icu && \
|
||||||
cd icu/icu4c/source && \
|
cd icu/icu4c/source && \
|
||||||
git reset --hard e2d85306162d3a0691b070b4f0a73e4012433444 && \
|
git reset --hard e2d85306162d3a0691b070b4f0a73e4012433444 && \
|
||||||
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./configure --disable-shared --enable-static --disable-tests --disable-samples && \
|
./configure --disable-shared --enable-static --disable-tests --disable-samples && \
|
||||||
make -j$THREADS && \
|
make -j$THREADS && \
|
||||||
make -j$THREADS install && \
|
make -j$THREADS install && \
|
||||||
rm -rf $(pwd)
|
rm -rf $(pwd)
|
||||||
|
|
||||||
RUN apt install -y wget && \
|
RUN apt install -y wget && \
|
||||||
wget https://dl.bintray.com/boostorg/release/1.73.0/source/boost_1_73_0.tar.gz && \
|
wget https://dl.bintray.com/boostorg/release/1.73.0/source/boost_1_73_0.tar.gz && \
|
||||||
echo "9995e192e68528793755692917f9eb6422f3052a53c5e13ba278a228af6c7acf boost_1_73_0.tar.gz" > hashsum.txt && \
|
echo "9995e192e68528793755692917f9eb6422f3052a53c5e13ba278a228af6c7acf boost_1_73_0.tar.gz" | sha256sum -c && \
|
||||||
sha256sum -c hashsum.txt && \
|
|
||||||
tar -xzf boost_1_73_0.tar.gz && \
|
tar -xzf boost_1_73_0.tar.gz && \
|
||||||
rm boost_1_73_0.tar.gz && \
|
rm boost_1_73_0.tar.gz && \
|
||||||
cd boost_1_73_0 && \
|
cd boost_1_73_0 && \
|
||||||
./bootstrap.sh && \
|
./bootstrap.sh && \
|
||||||
./b2 --with-atomic --with-system --with-filesystem --with-thread --with-date_time --with-chrono --with-regex --with-serialization --with-program_options --with-locale variant=release link=static runtime-link=static cflags='-fPIC' cxxflags='-fPIC' install -a --prefix=/usr && \
|
./b2 --with-atomic --with-system --with-filesystem --with-thread --with-date_time --with-chrono --with-regex --with-serialization --with-program_options --with-locale variant=release link=static runtime-link=static cflags="${CFLAGS}" cxxflags="${CXXFLAGS}" install -a --prefix=/usr && \
|
||||||
rm -rf $(pwd)
|
rm -rf $(pwd)
|
||||||
|
|
||||||
RUN wget https://www.openssl.org/source/openssl-1.1.1g.tar.gz && \
|
RUN wget https://www.openssl.org/source/openssl-1.1.1g.tar.gz && \
|
||||||
echo "ddb04774f1e32f0c49751e21b67216ac87852ceb056b75209af2443400636d46 openssl-1.1.1g.tar.gz" > hashsum.txt && \
|
echo "ddb04774f1e32f0c49751e21b67216ac87852ceb056b75209af2443400636d46 openssl-1.1.1g.tar.gz" | sha256sum -c && \
|
||||||
sha256sum -c hashsum.txt && \
|
|
||||||
tar -xzf openssl-1.1.1g.tar.gz && \
|
tar -xzf openssl-1.1.1g.tar.gz && \
|
||||||
rm openssl-1.1.1g.tar.gz && \
|
rm openssl-1.1.1g.tar.gz && \
|
||||||
cd openssl-1.1.1g && \
|
cd openssl-1.1.1g && \
|
||||||
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./config no-asm no-shared no-zlib-dynamic --openssldir=/usr && \
|
./config no-asm no-shared no-zlib-dynamic --openssldir=/usr && \
|
||||||
make -j$THREADS && \
|
make -j$THREADS && \
|
||||||
make -j$THREADS install && \
|
make -j$THREADS install && \
|
||||||
rm -rf $(pwd)
|
rm -rf $(pwd)
|
||||||
|
|
||||||
RUN apt install -y libgl1-mesa-dev libglib2.0-dev libxkbcommon-dev && \
|
RUN apt install -y libgl1-mesa-dev libglib2.0-dev mesa-common-dev && \
|
||||||
wget https://download.qt.io/archive/qt/5.9/5.9.9/single/qt-everywhere-opensource-src-5.9.9.tar.xz && \
|
rm /usr/lib/x86_64-linux-gnu/libX11.a && \
|
||||||
echo "5ce285209290a157d7f42ec8eb22bf3f1d76f2e03a95fc0b99b553391be01642 qt-everywhere-opensource-src-5.9.9.tar.xz" > hashsum.txt && \
|
rm /usr/lib/x86_64-linux-gnu/libXext.a && \
|
||||||
sha256sum -c hashsum.txt && \
|
rm /usr/lib/x86_64-linux-gnu/libX11-xcb.a && \
|
||||||
tar -xf qt-everywhere-opensource-src-5.9.9.tar.xz && \
|
git clone git://code.qt.io/qt/qt5.git -b ${QT_VERSION} --depth 1 && \
|
||||||
rm qt-everywhere-opensource-src-5.9.9.tar.xz && \
|
cd qt5 && \
|
||||||
cd qt-everywhere-opensource-src-5.9.9 && \
|
git clone git://code.qt.io/qt/qtbase.git -b ${QT_VERSION} --depth 1 && \
|
||||||
|
git clone git://code.qt.io/qt/qtdeclarative.git -b ${QT_VERSION} --depth 1 && \
|
||||||
|
git clone git://code.qt.io/qt/qtgraphicaleffects.git -b ${QT_VERSION} --depth 1 && \
|
||||||
|
git clone git://code.qt.io/qt/qtimageformats.git -b ${QT_VERSION} --depth 1 && \
|
||||||
|
git clone git://code.qt.io/qt/qtmultimedia.git -b ${QT_VERSION} --depth 1 && \
|
||||||
|
git clone git://code.qt.io/qt/qtquickcontrols.git -b ${QT_VERSION} --depth 1 && \
|
||||||
|
git clone git://code.qt.io/qt/qtquickcontrols2.git -b ${QT_VERSION} --depth 1 && \
|
||||||
|
git clone git://code.qt.io/qt/qtsvg.git -b ${QT_VERSION} --depth 1 && \
|
||||||
|
git clone git://code.qt.io/qt/qttools.git -b ${QT_VERSION} --depth 1 && \
|
||||||
|
git clone git://code.qt.io/qt/qttranslations.git -b ${QT_VERSION} --depth 1 && \
|
||||||
|
git clone git://code.qt.io/qt/qtx11extras.git -b ${QT_VERSION} --depth 1 && \
|
||||||
|
git clone git://code.qt.io/qt/qtxmlpatterns.git -b ${QT_VERSION} --depth 1 && \
|
||||||
sed -ri s/\(Libs:.*\)/\\1\ -lexpat/ /usr/local/lib/pkgconfig/fontconfig.pc && \
|
sed -ri s/\(Libs:.*\)/\\1\ -lexpat/ /usr/local/lib/pkgconfig/fontconfig.pc && \
|
||||||
sed -ri s/\(Libs:.*\)/\\1\ -lz/ /usr/local/lib/pkgconfig/freetype2.pc && \
|
sed -ri s/\(Libs:.*\)/\\1\ -lz/ /usr/local/lib/pkgconfig/freetype2.pc && \
|
||||||
sed -ri s/\(Libs:.*\)/\\1\ -lXau/ /usr/local/lib/pkgconfig/xcb.pc && \
|
sed -ri s/\(Libs:.*\)/\\1\ -lXau/ /usr/local/lib/pkgconfig/xcb.pc && \
|
||||||
|
sed -i s/\\/usr\\/X11R6\\/lib64/\\/usr\\/local\\/lib/ qtbase/mkspecs/linux-g++-64/qmake.conf && \
|
||||||
./configure --prefix=/usr -platform linux-g++-64 -opensource -confirm-license -release -static -no-avx \
|
./configure --prefix=/usr -platform linux-g++-64 -opensource -confirm-license -release -static -no-avx \
|
||||||
-opengl desktop -qpa xcb -system-freetype -fontconfig -glib \
|
-opengl desktop -qpa xcb -xcb -xcb-xlib -feature-xlib -system-freetype -fontconfig -glib \
|
||||||
-no-dbus -no-openssl -no-sql-sqlite -no-use-gold-linker \
|
-no-dbus -no-feature-qml-worker-script -no-linuxfb -no-openssl -no-sql-sqlite -no-kms -no-use-gold-linker \
|
||||||
-qt-harfbuzz -qt-libjpeg -qt-libpng -qt-pcre -qt-zlib \
|
-qt-harfbuzz -qt-libjpeg -qt-libpng -qt-pcre -qt-zlib \
|
||||||
-skip qt3d -skip qtandroidextras -skip qtcanvas3d -skip qtcharts -skip qtconnectivity -skip qtdatavis3d \
|
-skip qt3d -skip qtandroidextras -skip qtcanvas3d -skip qtcharts -skip qtconnectivity -skip qtdatavis3d \
|
||||||
-skip qtdoc -skip qtgamepad -skip qtlocation -skip qtmacextras -skip qtnetworkauth -skip qtpurchasing \
|
-skip qtdoc -skip qtgamepad -skip qtlocation -skip qtmacextras -skip qtnetworkauth -skip qtpurchasing \
|
||||||
@@ -137,7 +222,7 @@ RUN apt install -y libudev-dev && \
|
|||||||
git clone -b v1.0.23 --depth 1 https://github.com/libusb/libusb && \
|
git clone -b v1.0.23 --depth 1 https://github.com/libusb/libusb && \
|
||||||
cd libusb && \
|
cd libusb && \
|
||||||
git reset --hard e782eeb2514266f6738e242cdcb18e3ae1ed06fa && \
|
git reset --hard e782eeb2514266f6738e242cdcb18e3ae1ed06fa && \
|
||||||
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./autogen.sh --disable-shared --enable-static && \
|
./autogen.sh --disable-shared --enable-static && \
|
||||||
make -j$THREADS && \
|
make -j$THREADS && \
|
||||||
make -j$THREADS install && \
|
make -j$THREADS install && \
|
||||||
rm -rf $(pwd)
|
rm -rf $(pwd)
|
||||||
@@ -146,23 +231,7 @@ RUN git clone -b hidapi-0.9.0 --depth 1 https://github.com/libusb/hidapi && \
|
|||||||
cd hidapi && \
|
cd hidapi && \
|
||||||
git reset --hard 7da5cc91fc0d2dbe4df4f08cd31f6ca1a262418f && \
|
git reset --hard 7da5cc91fc0d2dbe4df4f08cd31f6ca1a262418f && \
|
||||||
./bootstrap && \
|
./bootstrap && \
|
||||||
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./configure --disable-shared --enable-static && \
|
./configure --disable-shared --enable-static && \
|
||||||
make -j$THREADS && \
|
|
||||||
make -j$THREADS install && \
|
|
||||||
rm -rf $(pwd)
|
|
||||||
|
|
||||||
RUN git clone -b libX11-1.6.9 --depth 1 https://gitlab.freedesktop.org/xorg/lib/libx11 && \
|
|
||||||
cd libx11 && \
|
|
||||||
git reset --hard db7cca17ad7807e92a928da9d4c68a00f4836da2 && \
|
|
||||||
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./autogen.sh --disable-shared --enable-static && \
|
|
||||||
make -j$THREADS && \
|
|
||||||
make -j$THREADS install && \
|
|
||||||
rm -rf $(pwd)
|
|
||||||
|
|
||||||
RUN git clone -b libXext-1.3.4 --depth 1 https://gitlab.freedesktop.org/xorg/lib/libxext && \
|
|
||||||
cd libxext && \
|
|
||||||
git reset --hard ebb167f34a3514783966775fb12573c4ed209625 && \
|
|
||||||
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./autogen.sh --disable-shared --enable-static && \
|
|
||||||
make -j$THREADS && \
|
make -j$THREADS && \
|
||||||
make -j$THREADS install && \
|
make -j$THREADS install && \
|
||||||
rm -rf $(pwd)
|
rm -rf $(pwd)
|
||||||
@@ -172,7 +241,7 @@ RUN apt install -y libsodium-dev && \
|
|||||||
cd libzmq && \
|
cd libzmq && \
|
||||||
git reset --hard a84ffa12b2eb3569ced199660bac5ad128bff1f0 && \
|
git reset --hard a84ffa12b2eb3569ced199660bac5ad128bff1f0 && \
|
||||||
./autogen.sh && \
|
./autogen.sh && \
|
||||||
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./configure --disable-shared --enable-static --disable-libunwind --with-libsodium && \
|
./configure --disable-shared --enable-static --disable-libunwind --with-libsodium && \
|
||||||
make -j$THREADS && \
|
make -j$THREADS && \
|
||||||
make -j$THREADS install && \
|
make -j$THREADS install && \
|
||||||
rm -rf $(pwd)
|
rm -rf $(pwd)
|
||||||
@@ -181,7 +250,7 @@ RUN git clone -b libgpg-error-1.38 --depth 1 git://git.gnupg.org/libgpg-error.gi
|
|||||||
cd libgpg-error && \
|
cd libgpg-error && \
|
||||||
git reset --hard 71d278824c5fe61865f7927a2ed1aa3115f9e439 && \
|
git reset --hard 71d278824c5fe61865f7927a2ed1aa3115f9e439 && \
|
||||||
./autogen.sh && \
|
./autogen.sh && \
|
||||||
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./configure --disable-shared --enable-static --disable-doc --disable-tests && \
|
./configure --disable-shared --enable-static --disable-doc --disable-tests && \
|
||||||
make -j$THREADS && \
|
make -j$THREADS && \
|
||||||
make -j$THREADS install && \
|
make -j$THREADS install && \
|
||||||
rm -rf $(pwd)
|
rm -rf $(pwd)
|
||||||
@@ -190,7 +259,7 @@ RUN git clone -b libgcrypt-1.8.5 --depth 1 git://git.gnupg.org/libgcrypt.git &&
|
|||||||
cd libgcrypt && \
|
cd libgcrypt && \
|
||||||
git reset --hard 56606331bc2a80536db9fc11ad53695126007298 && \
|
git reset --hard 56606331bc2a80536db9fc11ad53695126007298 && \
|
||||||
./autogen.sh && \
|
./autogen.sh && \
|
||||||
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./configure --disable-shared --enable-static --disable-doc && \
|
./configure --disable-shared --enable-static --disable-doc && \
|
||||||
make -j$THREADS && \
|
make -j$THREADS && \
|
||||||
make -j$THREADS install && \
|
make -j$THREADS install && \
|
||||||
rm -rf $(pwd)
|
rm -rf $(pwd)
|
||||||
@@ -199,9 +268,17 @@ RUN git clone -b v3.10.0 --depth 1 https://github.com/protocolbuffers/protobuf &
|
|||||||
cd protobuf && \
|
cd protobuf && \
|
||||||
git reset --hard 6d4e7fd7966c989e38024a8ea693db83758944f1 && \
|
git reset --hard 6d4e7fd7966c989e38024a8ea693db83758944f1 && \
|
||||||
./autogen.sh && \
|
./autogen.sh && \
|
||||||
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./configure --enable-static --disable-shared && \
|
./configure --enable-static --disable-shared && \
|
||||||
make -j$THREADS && \
|
make -j$THREADS && \
|
||||||
make -j$THREADS install && \
|
make -j$THREADS install && \
|
||||||
rm -rf $(pwd)
|
rm -rf $(pwd)
|
||||||
|
|
||||||
RUN apt install -y cmake libusb-1.0-0-dev
|
RUN git clone -b v3.18.4 --depth 1 https://github.com/Kitware/CMake && \
|
||||||
|
cd CMake && \
|
||||||
|
git reset --hard 3cc3d42aba879fff5e85b363ae8f21386a3f9f9b && \
|
||||||
|
./bootstrap && \
|
||||||
|
make -j$THREADS && \
|
||||||
|
make -j$THREADS install && \
|
||||||
|
rm -rf $(pwd)
|
||||||
|
|
||||||
|
RUN apt install -y libusb-1.0-0-dev
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
FROM ubuntu:20.04
|
FROM ubuntu:20.04
|
||||||
|
|
||||||
ARG THREADS=1
|
ARG THREADS=1
|
||||||
|
ARG QT_VERSION=5.15.2
|
||||||
|
ENV SOURCE_DATE_EPOCH=1397818193
|
||||||
|
|
||||||
RUN apt update && \
|
RUN apt update && \
|
||||||
DEBIAN_FRONTEND=noninteractive apt install -y build-essential cmake g++-mingw-w64 gettext git libtool pkg-config \
|
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 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 && \
|
RUN git clone git://code.qt.io/qt/qt5.git -b ${QT_VERSION} --depth 1 && \
|
||||||
echo "5ce285209290a157d7f42ec8eb22bf3f1d76f2e03a95fc0b99b553391be01642 qt-everywhere-opensource-src-5.9.9.tar.xz" > hashsum.txt && \
|
cd qt5 && \
|
||||||
sha256sum -c hashsum.txt && \
|
git clone git://code.qt.io/qt/qtbase.git -b ${QT_VERSION} --depth 1 && \
|
||||||
tar -xf qt-everywhere-opensource-src-5.9.9.tar.xz && \
|
git clone git://code.qt.io/qt/qtdeclarative.git -b ${QT_VERSION} --depth 1 && \
|
||||||
rm qt-everywhere-opensource-src-5.9.9.tar.xz && \
|
git clone git://code.qt.io/qt/qtgraphicaleffects.git -b ${QT_VERSION} --depth 1 && \
|
||||||
cd qt-everywhere-opensource-src-5.9.9 && \
|
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++ \
|
./configure --prefix=/depends/x86_64-w64-mingw32 -xplatform win32-g++ \
|
||||||
-device-option CROSS_COMPILE=/usr/bin/x86_64-w64-mingw32- \
|
-device-option CROSS_COMPILE=/usr/bin/x86_64-w64-mingw32- \
|
||||||
-I $(pwd)/qtbase/src/3rdparty/angle/include \
|
-I $(pwd)/qtbase/src/3rdparty/angle/include \
|
||||||
-opensource -confirm-license -release -static -static-runtime -opengl dynamic -no-angle \
|
-opensource -confirm-license -release -static -static-runtime -opengl dynamic -no-angle \
|
||||||
-no-avx -no-openssl -no-sql-sqlite \
|
-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 \
|
-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 gamepad -skip location -skip qt3d -skip qtactiveqt -skip qtandroidextras \
|
||||||
-skip qtconnectivity -skip qtdatavis3d -skip qtdoc -skip qtgamepad -skip qtlocation -skip qtmacextras \
|
-skip qtcanvas3d -skip qtcharts -skip qtconnectivity -skip qtdatavis3d -skip qtdoc \
|
||||||
-skip qtmultimedia -skip qtnetworkauth -skip qtpurchasing -skip qtscript -skip qtscxml -skip qtsensors \
|
-skip qtgamepad -skip qtlocation -skip qtmacextras -skip qtnetworkauth -skip qtpurchasing \
|
||||||
-skip qtserialbus -skip qtserialport -skip qtspeech -skip qttools -skip qtvirtualkeyboard -skip qtwayland \
|
-skip qtscript -skip qtscxml -skip qtsensors -skip qtserialbus -skip qtserialport \
|
||||||
-skip qtwebchannel -skip qtwebengine -skip qtwebsockets -skip qtwebview -skip qtwinextras -skip qtx11extras \
|
-skip qtspeech -skip qttools -skip qtvirtualkeyboard -skip qtwayland -skip qtwebchannel \
|
||||||
|
-skip qtwebengine -skip qtwebsockets -skip qtwebview -skip qtwinextras -skip qtx11extras \
|
||||||
-skip serialbus -skip webengine \
|
-skip serialbus -skip webengine \
|
||||||
-nomake examples -nomake tests -nomake tools && \
|
-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 && \
|
make -j$THREADS install && \
|
||||||
cd qttools/src/linguist/lrelease && \
|
cd qttools/src/linguist/lrelease && \
|
||||||
../../../../qtbase/bin/qmake && \
|
../../../../qtbase/bin/qmake && \
|
||||||
|
|||||||
102
LeftPanel.qml
102
LeftPanel.qml
@@ -58,12 +58,9 @@ Rectangle {
|
|||||||
signal historyClicked()
|
signal historyClicked()
|
||||||
signal transferClicked()
|
signal transferClicked()
|
||||||
signal receiveClicked()
|
signal receiveClicked()
|
||||||
signal txkeyClicked()
|
signal advancedClicked()
|
||||||
signal sharedringdbClicked()
|
|
||||||
signal settingsClicked()
|
signal settingsClicked()
|
||||||
signal addressBookClicked()
|
signal addressBookClicked()
|
||||||
signal miningClicked()
|
|
||||||
signal signClicked()
|
|
||||||
signal accountClicked()
|
signal accountClicked()
|
||||||
|
|
||||||
function selectItem(pos) {
|
function selectItem(pos) {
|
||||||
@@ -72,10 +69,6 @@ Rectangle {
|
|||||||
else if(pos === "Transfer") menuColumn.previousButton = transferButton
|
else if(pos === "Transfer") menuColumn.previousButton = transferButton
|
||||||
else if(pos === "Receive") menuColumn.previousButton = receiveButton
|
else if(pos === "Receive") menuColumn.previousButton = receiveButton
|
||||||
else if(pos === "AddressBook") menuColumn.previousButton = addressBookButton
|
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 === "Settings") menuColumn.previousButton = settingsButton
|
||||||
else if(pos === "Advanced") menuColumn.previousButton = advancedButton
|
else if(pos === "Advanced") menuColumn.previousButton = advancedButton
|
||||||
else if(pos === "Account") menuColumn.previousButton = accountButton
|
else if(pos === "Account") menuColumn.previousButton = accountButton
|
||||||
@@ -480,6 +473,7 @@ Rectangle {
|
|||||||
onClicked: {
|
onClicked: {
|
||||||
parent.previousButton.checked = false
|
parent.previousButton.checked = false
|
||||||
parent.previousButton = advancedButton
|
parent.previousButton = advancedButton
|
||||||
|
panel.advancedClicked()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -490,98 +484,6 @@ Rectangle {
|
|||||||
anchors.leftMargin: 20
|
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 ---------------
|
// ------------- Settings tab ---------------
|
||||||
MoneroComponents.MenuButton {
|
MoneroComponents.MenuButton {
|
||||||
id: settingsButton
|
id: settingsButton
|
||||||
|
|||||||
60
Makefile
60
Makefile
@@ -1,53 +1,69 @@
|
|||||||
ANDROID_STANDALONE_TOOLCHAIN_PATH ?= /usr/local/toolchain
|
ANDROID_STANDALONE_TOOLCHAIN_PATH ?= /usr/local/toolchain
|
||||||
|
MANUAL_SUBMODULES ?= OFF
|
||||||
|
|
||||||
dotgit=$(shell ls -d .git/config)
|
dotgit=$(shell ls -d .git/config)
|
||||||
ifneq ($(dotgit), .git/config)
|
ifeq ($(dotgit), .git/config)
|
||||||
USE_SINGLE_BUILDDIR=1
|
ifeq ($(shell git --version > /dev/null 2>&1 ; echo $$?), 0)
|
||||||
|
git = yes
|
||||||
|
else
|
||||||
|
$(warning git command not found)
|
||||||
|
endif
|
||||||
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)
|
ifeq ($(USE_SINGLE_BUILDDIR), OFF)
|
||||||
builddir := build/"$(subbuilddir)"
|
os := $(shell echo `uname | sed -e 's|[:/\\ \(\)]|_|g'`)
|
||||||
topdir := ../../../..
|
builddir := $(builddir)/$(os)
|
||||||
deldirs := $(builddir)
|
topdir := $(topdir)/..
|
||||||
else
|
|
||||||
builddir := build
|
|
||||||
topdir := ../..
|
|
||||||
deldirs := $(builddir)/debug $(builddir)/release $(builddir)/fuzz
|
|
||||||
endif
|
|
||||||
|
|
||||||
|
ifdef git
|
||||||
|
branch := $(shell git branch | grep '\* ' | cut -f2- -d' '| sed -e 's|[:/\\ \(\)]|_|g')
|
||||||
|
builddir := $(builddir)/$(branch)
|
||||||
|
topdir := $(topdir)/..
|
||||||
|
endif
|
||||||
|
|
||||||
|
deldirs := $(builddir)
|
||||||
|
else
|
||||||
|
deldirs := $(builddir)/debug $(builddir)/release $(builddir)/fuzz
|
||||||
|
endif
|
||||||
|
|
||||||
default:
|
default:
|
||||||
mkdir -p build && cd build && cmake -D ARCH="x86-64" -D DEV_MODE=$(or ${DEV_MODE},OFF) -D BUILD_64=ON -D CMAKE_BUILD_TYPE=Release .. && $(MAKE)
|
mkdir -p build && cd build && cmake -D ARCH="x86-64" -D DEV_MODE=$(or ${DEV_MODE},OFF) -DMANUAL_SUBMODULES=${MANUAL_SUBMODULES} -D BUILD_64=ON -D CMAKE_BUILD_TYPE=Release .. && $(MAKE)
|
||||||
debug:
|
debug:
|
||||||
mkdir -p build && cd build && cmake -D DEV_MODE=$(or ${DEV_MODE},ON) .. && $(MAKE) VERBOSE=1
|
mkdir -p build && cd build && cmake -D DEV_MODE=$(or ${DEV_MODE},ON) -DMANUAL_SUBMODULES=${MANUAL_SUBMODULES} .. && $(MAKE) VERBOSE=1
|
||||||
|
|
||||||
depends:
|
depends:
|
||||||
mkdir -p build/$(target)/release
|
mkdir -p build/$(target)/release
|
||||||
cd build/$(target)/release && cmake -D STATIC=ON -D DEV_MODE=$(or ${DEV_MODE},OFF) -D BUILD_TAG=$(tag) -D CMAKE_BUILD_TYPE=Release -D CMAKE_TOOLCHAIN_FILE=$(root)/$(target)/share/toolchain.cmake ../../.. && $(MAKE)
|
cd build/$(target)/release && cmake -D STATIC=ON -D DEV_MODE=$(or ${DEV_MODE},OFF) -DMANUAL_SUBMODULES=${MANUAL_SUBMODULES} -D BUILD_TAG=$(tag) -D CMAKE_BUILD_TYPE=Release -D CMAKE_TOOLCHAIN_FILE=$(root)/$(target)/share/toolchain.cmake ../../.. && $(MAKE)
|
||||||
|
|
||||||
devmode:
|
devmode:
|
||||||
mkdir -p build && cd build && cmake -D ARCH="x86-64" -D DEV_MODE=$(or ${DEV_MODE},ON) -D BUILD_64=ON -D CMAKE_BUILD_TYPE=Release .. && $(MAKE)
|
mkdir -p build && cd build && cmake -D ARCH="x86-64" -D DEV_MODE=$(or ${DEV_MODE},ON) -DMANUAL_SUBMODULES=${MANUAL_SUBMODULES} -D BUILD_64=ON -D CMAKE_BUILD_TYPE=Release .. && $(MAKE)
|
||||||
clean:
|
clean:
|
||||||
mkdir -p build && cd build && rm -rf *
|
mkdir -p build && cd build && rm -rf *
|
||||||
scanner:
|
scanner:
|
||||||
mkdir -p build && cd build && cmake -D ARCH="x86-64" -D DEV_MODE=$(or ${DEV_MODE},ON) -D WITH_SCANNER=ON -D BUILD_64=ON -D CMAKE_BUILD_TYPE=Release .. && $(MAKE)
|
mkdir -p build && cd build && cmake -D ARCH="x86-64" -D DEV_MODE=$(or ${DEV_MODE},ON) -DMANUAL_SUBMODULES=${MANUAL_SUBMODULES} -D WITH_SCANNER=ON -D BUILD_64=ON -D CMAKE_BUILD_TYPE=Release .. && $(MAKE)
|
||||||
|
|
||||||
release:
|
release:
|
||||||
mkdir -p $(builddir)/release && cd $(builddir)/release && cmake -D DEV_MODE=$(or ${DEV_MODE},OFF) -D ARCH="x86-64" -D CMAKE_BUILD_TYPE=Release $(topdir) && $(MAKE)
|
mkdir -p $(builddir)/release && cd $(builddir)/release && cmake -D DEV_MODE=$(or ${DEV_MODE},OFF) -DMANUAL_SUBMODULES=${MANUAL_SUBMODULES} -D ARCH="x86-64" -D CMAKE_BUILD_TYPE=Release $(topdir) && $(MAKE)
|
||||||
|
|
||||||
|
release-linux-armv8:
|
||||||
|
mkdir -p $(builddir)/release
|
||||||
|
cd $(builddir)/release
|
||||||
|
cmake -D DEV_MODE=$(or ${DEV_MODE},OFF) -D ARCH="armv8-a" -D BUILD_64=ON -D CMAKE_BUILD_TYPE=Release -D BUILD_TAG="linux-armv8" $(topdir) && $(MAKE)
|
||||||
|
|
||||||
release-static:
|
release-static:
|
||||||
mkdir -p $(builddir)/release && cd $(builddir)/release && cmake -D STATIC=ON -D DEV_MODE=$(or ${DEV_MODE},OFF) -D ARCH="x86-64" -D BUILD_64=ON -D CMAKE_BUILD_TYPE=Release $(topdir) && $(MAKE)
|
mkdir -p $(builddir)/release && cd $(builddir)/release && cmake -D STATIC=ON -D DEV_MODE=$(or ${DEV_MODE},OFF) -DMANUAL_SUBMODULES=${MANUAL_SUBMODULES} -D ARCH="x86-64" -D BUILD_64=ON -D CMAKE_BUILD_TYPE=Release $(topdir) && $(MAKE)
|
||||||
|
|
||||||
debug-static-win64:
|
debug-static-win64:
|
||||||
mkdir -p $(builddir)/debug && cd $(builddir)/debug && cmake -D STATIC=ON -G "MSYS Makefiles" -D DEV_MODE=$(or ${DEV_MODE},ON) -D ARCH="x86-64" -D BUILD_64=ON -D CMAKE_BUILD_TYPE=Debug -D BUILD_TAG="win-x64" -D CMAKE_TOOLCHAIN_FILE=$(topdir)/cmake/64-bit-toolchain.cmake -D MSYS2_FOLDER=$(shell cd ${MINGW_PREFIX}/.. && pwd -W) -D MINGW=ON $(topdir) && $(MAKE)
|
mkdir -p $(builddir)/debug && cd $(builddir)/debug && cmake -D STATIC=ON -G "MSYS Makefiles" -D DEV_MODE=$(or ${DEV_MODE},ON) -DMANUAL_SUBMODULES=${MANUAL_SUBMODULES} -D ARCH="x86-64" -D BUILD_64=ON -D CMAKE_BUILD_TYPE=Debug -D BUILD_TAG="win-x64" -D CMAKE_TOOLCHAIN_FILE=$(topdir)/cmake/64-bit-toolchain.cmake -D MSYS2_FOLDER=$(shell cd ${MINGW_PREFIX}/.. && pwd -W) -D MINGW=ON $(topdir) && $(MAKE)
|
||||||
|
|
||||||
debug-static-mac64:
|
debug-static-mac64:
|
||||||
mkdir -p $(builddir)/debug
|
mkdir -p $(builddir)/debug
|
||||||
cd $(builddir)/debug && cmake -D STATIC=ON -D DEV_MODE=$(or ${DEV_MODE},ON) -D ARCH="x86-64" -D BUILD_64=ON -D CMAKE_BUILD_TYPE=release -D BUILD_TAG="mac-x64" $(topdir) && $(MAKE)
|
cd $(builddir)/debug && cmake -D STATIC=ON -D DEV_MODE=$(or ${DEV_MODE},ON) -DMANUAL_SUBMODULES=${MANUAL_SUBMODULES} -D ARCH="x86-64" -D BUILD_64=ON -D CMAKE_BUILD_TYPE=release -D BUILD_TAG="mac-x64" $(topdir) && $(MAKE)
|
||||||
|
|
||||||
release-static-win64:
|
release-static-win64:
|
||||||
mkdir -p $(builddir)/release && cd $(builddir)/release && cmake -D STATIC=ON -G "MSYS Makefiles" -D DEV_MODE=$(or ${DEV_MODE},OFF) -D ARCH="x86-64" -D BUILD_64=ON -D CMAKE_BUILD_TYPE=Release -D BUILD_TAG="win-x64" -D CMAKE_TOOLCHAIN_FILE=$(topdir)/cmake/64-bit-toolchain.cmake -D MSYS2_FOLDER=$(shell cd ${MINGW_PREFIX}/.. && pwd -W) -D MINGW=ON $(topdir) && $(MAKE)
|
mkdir -p $(builddir)/release && cd $(builddir)/release && cmake -D STATIC=ON -G "MSYS Makefiles" -D DEV_MODE=$(or ${DEV_MODE},OFF) -DMANUAL_SUBMODULES=${MANUAL_SUBMODULES} -D ARCH="x86-64" -D BUILD_64=ON -D CMAKE_BUILD_TYPE=Release -D BUILD_TAG="win-x64" -D CMAKE_TOOLCHAIN_FILE=$(topdir)/cmake/64-bit-toolchain.cmake -D MSYS2_FOLDER=$(shell cd ${MINGW_PREFIX}/.. && pwd -W) -D MINGW=ON $(topdir) && $(MAKE)
|
||||||
|
|
||||||
release-win64:
|
release-win64:
|
||||||
mkdir -p $(builddir)/release && cd $(builddir)/release && cmake -D STATIC=OFF -G "MSYS Makefiles" -D DEV_MODE=$(or ${DEV_MODE},OFF) -D ARCH="x86-64" -D BUILD_64=ON -D CMAKE_BUILD_TYPE=Release -D BUILD_TAG="win-x64" -D CMAKE_TOOLCHAIN_FILE=$(topdir)/cmake/64-bit-toolchain.cmake -D MSYS2_FOLDER=$(shell cd ${MINGW_PREFIX}/.. && pwd -W) -D MINGW=ON $(topdir) && $(MAKE)
|
mkdir -p $(builddir)/release && cd $(builddir)/release && cmake -D STATIC=OFF -G "MSYS Makefiles" -D DEV_MODE=$(or ${DEV_MODE},OFF) -DMANUAL_SUBMODULES=${MANUAL_SUBMODULES} -D ARCH="x86-64" -D BUILD_64=ON -D CMAKE_BUILD_TYPE=Release -D BUILD_TAG="win-x64" -D CMAKE_TOOLCHAIN_FILE=$(topdir)/cmake/64-bit-toolchain.cmake -D MSYS2_FOLDER=$(shell cd ${MINGW_PREFIX}/.. && pwd -W) -D MINGW=ON $(topdir) && $(MAKE)
|
||||||
|
|||||||
@@ -51,22 +51,19 @@ Rectangle {
|
|||||||
property alias flickable: mainFlickable
|
property alias flickable: mainFlickable
|
||||||
|
|
||||||
property Transfer transferView: Transfer {
|
property Transfer transferView: Transfer {
|
||||||
onPaymentClicked: root.paymentClicked(address, paymentId, amount, mixinCount, priority, description)
|
onPaymentClicked: root.paymentClicked(recipients, paymentId, mixinCount, priority, description)
|
||||||
onSweepUnmixableClicked: root.sweepUnmixableClicked()
|
onSweepUnmixableClicked: root.sweepUnmixableClicked()
|
||||||
}
|
}
|
||||||
property Receive receiveView: Receive { }
|
property Receive receiveView: Receive { }
|
||||||
property Merchant merchantView: Merchant { }
|
property Merchant merchantView: Merchant { }
|
||||||
property TxKey txkeyView: TxKey { }
|
|
||||||
property SharedRingDB sharedringdbView: SharedRingDB { }
|
|
||||||
property History historyView: History { }
|
property History historyView: History { }
|
||||||
property Sign signView: Sign { }
|
property Advanced advancedView: Advanced { }
|
||||||
property Settings settingsView: Settings { }
|
property Settings settingsView: Settings { }
|
||||||
property Mining miningView: Mining { }
|
|
||||||
property AddressBook addressBookView: AddressBook { }
|
property AddressBook addressBookView: AddressBook { }
|
||||||
property Keys keysView: Keys { }
|
property Keys keysView: Keys { }
|
||||||
property Account accountView: Account { }
|
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 sweepUnmixableClicked()
|
||||||
signal generatePaymentIdInvoked()
|
signal generatePaymentIdInvoked()
|
||||||
signal getProofClicked(string txid, string address, string message);
|
signal getProofClicked(string txid, string address, string message);
|
||||||
@@ -136,30 +133,18 @@ Rectangle {
|
|||||||
name: "Merchant"
|
name: "Merchant"
|
||||||
PropertyChanges { target: root; currentView: merchantView }
|
PropertyChanges { target: root; currentView: merchantView }
|
||||||
PropertyChanges { target: mainFlickable; contentHeight: merchantView.merchantHeight + 80 }
|
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 {
|
}, State {
|
||||||
name: "AddressBook"
|
name: "AddressBook"
|
||||||
PropertyChanges { target: root; currentView: addressBookView }
|
PropertyChanges { target: root; currentView: addressBookView }
|
||||||
PropertyChanges { target: mainFlickable; contentHeight: addressBookView.addressbookHeight + 80 }
|
PropertyChanges { target: mainFlickable; contentHeight: addressBookView.addressbookHeight + 80 }
|
||||||
}, State {
|
}, State {
|
||||||
name: "Sign"
|
name: "Advanced"
|
||||||
PropertyChanges { target: root; currentView: signView }
|
PropertyChanges { target: root; currentView: advancedView }
|
||||||
PropertyChanges { target: mainFlickable; contentHeight: signView.signHeight + 80 }
|
PropertyChanges { target: mainFlickable; contentHeight: advancedView.panelHeight }
|
||||||
}, State {
|
}, State {
|
||||||
name: "Settings"
|
name: "Settings"
|
||||||
PropertyChanges { target: root; currentView: settingsView }
|
PropertyChanges { target: root; currentView: settingsView }
|
||||||
PropertyChanges { target: mainFlickable; contentHeight: settingsView.settingsHeight }
|
PropertyChanges { target: mainFlickable; contentHeight: settingsView.settingsHeight }
|
||||||
}, State {
|
|
||||||
name: "Mining"
|
|
||||||
PropertyChanges { target: root; currentView: miningView }
|
|
||||||
PropertyChanges { target: mainFlickable; contentHeight: miningView.miningHeight + 80 }
|
|
||||||
}, State {
|
}, State {
|
||||||
name: "Keys"
|
name: "Keys"
|
||||||
PropertyChanges { target: root; currentView: keysView }
|
PropertyChanges { target: root; currentView: keysView }
|
||||||
|
|||||||
80
README.md
80
README.md
@@ -72,7 +72,7 @@ Packages are available for
|
|||||||
* Debian: See the [whonix/monero-gui repository](https://gitlab.com/whonix/monero-gui#how-to-install-monero-using-apt-get)
|
* 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`
|
* Void Linux: `xbps-install -S monero-gui`
|
||||||
* GuixSD: `guix package -i 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!
|
Packaging for your favorite distribution would be a welcome contribution!
|
||||||
|
|
||||||
@@ -80,13 +80,14 @@ Packaging for your favorite distribution would be a welcome contribution!
|
|||||||
|
|
||||||
*Note*: Qt 5.9.7 is the minimum version required to build the GUI.
|
*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/)
|
1. Install Docker [https://docs.docker.com/engine/install/](https://docs.docker.com/engine/install/)
|
||||||
2. Clone the repository
|
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
|
3. Prepare build environment
|
||||||
```
|
```
|
||||||
cd monero-gui
|
cd monero-gui
|
||||||
@@ -102,13 +103,14 @@ Packaging for your favorite distribution would be a welcome contribution!
|
|||||||
\* `4` - number of CPU threads to use
|
\* `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
|
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/)
|
1. Install Docker [https://docs.docker.com/engine/install/](https://docs.docker.com/engine/install/)
|
||||||
2. Clone the repository
|
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
|
3. Prepare build environment
|
||||||
```
|
```
|
||||||
cd monero-gui
|
cd monero-gui
|
||||||
@@ -123,6 +125,60 @@ Packaging for your favorite distribution would be a welcome contribution!
|
|||||||
\* `<MONERO_GUI_DIR_FULL_PATH>` - absolute path to `monero-gui` directory
|
\* `<MONERO_GUI_DIR_FULL_PATH>` - absolute path to `monero-gui` directory
|
||||||
\* `4` - number of CPU threads to use
|
\* `4` - number of CPU threads to use
|
||||||
5. Monero GUI Linux static binaries will be placed in `monero-gui/build/release/bin` directory
|
5. Monero GUI Linux static binaries will be placed in `monero-gui/build/release/bin` directory
|
||||||
|
6. (*Optional*) Compare `monero-wallet-gui` SHA-256 hash to the one obtained from a trusted source
|
||||||
|
```
|
||||||
|
docker run --rm -it -v <MONERO_GUI_DIR_FULL_PATH>:/monero-gui -w /monero-gui monero:build-env-linux sh -c 'shasum -a 256 /monero-gui/build/release/bin/monero-wallet-gui'
|
||||||
|
```
|
||||||
|
\* `<MONERO_GUI_DIR_FULL_PATH>` - absolute path to `monero-gui` directory
|
||||||
|
|
||||||
|
### Building Android APK with Docker (any OS) *Experimental*
|
||||||
|
- Minimum Android 9 Pie (API 28)
|
||||||
|
- ARMv8-A 64-bit CPU
|
||||||
|
1. Install Docker [https://docs.docker.com/engine/install/](https://docs.docker.com/engine/install/)
|
||||||
|
2. Clone the repository
|
||||||
|
```
|
||||||
|
git clone --recursive https://github.com/monero-project/monero-gui.git
|
||||||
|
```
|
||||||
|
3. Prepare build environment
|
||||||
|
```
|
||||||
|
cd monero-gui
|
||||||
|
docker build --tag monero:build-env-android --build-arg THREADS=4 --file Dockerfile.android .
|
||||||
|
```
|
||||||
|
\* `4` - number of CPU threads to use
|
||||||
|
|
||||||
|
4. Build
|
||||||
|
```
|
||||||
|
docker run --rm -it -v <MONERO_GUI_DIR_FULL_PATH>:/monero-gui -e THREADS=4 monero:build-env-android
|
||||||
|
```
|
||||||
|
\* `<MONERO_GUI_DIR_FULL_PATH>` - absolute path to `monero-gui` directory
|
||||||
|
\* `4` - number of CPU threads to use
|
||||||
|
5. Monero GUI APK will be placed in `monero-gui/build/Android/release/android-build` directory
|
||||||
|
6. Deploy
|
||||||
|
* Using ADB (Android debugger bridge)
|
||||||
|
- [Enable adb debugging on your device](https://developer.android.com/studio/command-line/adb.html#Enabling)
|
||||||
|
* Connect your device with USB and install Monero GUI APK with adb:
|
||||||
|
```
|
||||||
|
adb install build/Android/release/android-build/monero-gui.apk
|
||||||
|
```
|
||||||
|
* Troubleshooting:
|
||||||
|
```
|
||||||
|
adb devices -l
|
||||||
|
adb logcat
|
||||||
|
```
|
||||||
|
* If using adb inside docker, make sure you did
|
||||||
|
```
|
||||||
|
docker run -v /dev/bus/usb:/dev/bus/usb --privileged
|
||||||
|
```
|
||||||
|
* Using a web server
|
||||||
|
```
|
||||||
|
mkdir /usr/tmp
|
||||||
|
cp build/Android/release/android-build/monero-gui.apk /usr/tmp
|
||||||
|
docker run -d -v /usr/tmp:/usr/share/nginx/html:ro -p 8080:80 nginx
|
||||||
|
```
|
||||||
|
Now it should be accessible through a web browser at
|
||||||
|
```
|
||||||
|
http://<your.local.ip>:8080/QtApp-debug.apk
|
||||||
|
```
|
||||||
|
|
||||||
### On Linux:
|
### On Linux:
|
||||||
|
|
||||||
@@ -152,7 +208,7 @@ The following instructions will fetch Qt from your distribution's repositories i
|
|||||||
|
|
||||||
- For Ubuntu 17.10+
|
- For Ubuntu 17.10+
|
||||||
|
|
||||||
`sudo apt install qtbase5-dev qt5-default qtdeclarative5-dev qml-module-qtquick-controls qml-module-qtquick-controls2 qml-module-qtquick-dialogs qml-module-qtquick-xmllistmodel qml-module-qt-labs-settings qml-module-qt-labs-folderlistmodel qttools5-dev-tools qml-module-qtquick-templates2 libqt5svg5-dev`
|
`sudo apt install qtbase5-dev qt5-default qtdeclarative5-dev qml-module-qtqml-models2 qml-module-qtquick-controls qml-module-qtquick-controls2 qml-module-qtquick-dialogs qml-module-qtquick-xmllistmodel qml-module-qt-labs-settings qml-module-qt-labs-folderlistmodel qttools5-dev-tools qml-module-qtquick-templates2 libqt5svg5-dev`
|
||||||
|
|
||||||
- For Gentoo
|
- For Gentoo
|
||||||
|
|
||||||
@@ -162,13 +218,13 @@ The following instructions will fetch Qt from your distribution's repositories i
|
|||||||
|
|
||||||
- For Ubuntu
|
- For Ubuntu
|
||||||
|
|
||||||
`sudo apt install qtmultimedia5-dev qml-module-qtmultimedia libzbar-dev`
|
`sudo apt install qtmultimedia5-dev qml-module-qtmultimedia`
|
||||||
|
|
||||||
- For Gentoo
|
- For Gentoo
|
||||||
|
|
||||||
The *qml* USE flag must be enabled.
|
The *qml* USE flag must be enabled.
|
||||||
|
|
||||||
`emerge dev-qt/qtmultimedia:5 media-gfx/zbar`
|
`emerge dev-qt/qtmultimedia:5`
|
||||||
|
|
||||||
|
|
||||||
3. Clone repository
|
3. Clone repository
|
||||||
@@ -196,7 +252,7 @@ The executable can be found in the build/release/bin folder.
|
|||||||
|
|
||||||
3. Install [monero](https://github.com/monero-project/monero) dependencies:
|
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:
|
4. Install Qt:
|
||||||
|
|
||||||
@@ -235,12 +291,6 @@ The Monero GUI on Windows is 64 bits only; 32-bit Windows GUI builds are not off
|
|||||||
pacman -S mingw-w64-x86_64-toolchain make mingw-w64-x86_64-cmake mingw-w64-x86_64-boost mingw-w64-x86_64-openssl mingw-w64-x86_64-zeromq mingw-w64-x86_64-libsodium mingw-w64-x86_64-hidapi mingw-w64-x86_64-protobuf-c mingw-w64-x86_64-libusb mingw-w64-x86_64-libgcrypt
|
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.
|
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
|
4. Install Qt5
|
||||||
|
|||||||
@@ -1,53 +0,0 @@
|
|||||||
Copyright (c) 2014-2018, The Monero Project
|
|
||||||
|
|
||||||
|
|
||||||
## Current status : ALPHA
|
|
||||||
|
|
||||||
- Minimum Android 5.0 (api level 21)
|
|
||||||
- Modal dialogs can appear in background giving the feeling that the application is frozen (Work around : turn screen off/on or switch to another app and back)
|
|
||||||
|
|
||||||
## Build using Docker
|
|
||||||
|
|
||||||
# Base environnement
|
|
||||||
|
|
||||||
cd monero/utils/build_scripts
|
|
||||||
docker build -f android32.Dockerfile -t monero-android .
|
|
||||||
cd ..
|
|
||||||
|
|
||||||
# Build GUI
|
|
||||||
|
|
||||||
cd android/docker
|
|
||||||
docker build -t monero-gui-android .
|
|
||||||
docker create -it --name monero-gui-android monero-gui-android bash
|
|
||||||
|
|
||||||
# Get the apk
|
|
||||||
|
|
||||||
docker cp monero-gui-android:/opt/android/monero-gui/build/release/bin/bin/QtApp-debug.apk .
|
|
||||||
|
|
||||||
## Deployment
|
|
||||||
|
|
||||||
- Using ADB (Android debugger bridge) :
|
|
||||||
|
|
||||||
First, see section [Enable adb debugging on your device](https://developer.android.com/studio/command-line/adb.html#Enabling)
|
|
||||||
The only place where we are allowed to play is `/data/local/tmp`. So :
|
|
||||||
|
|
||||||
adb push /opt/android/monero-gui/build/release/bin/bin/QtApp-debug.apk /data/local/tmp
|
|
||||||
adb shell pm install -r /data/local/tmp/QtApp-debug.apk
|
|
||||||
|
|
||||||
- Troubleshooting:
|
|
||||||
|
|
||||||
adb devices -l
|
|
||||||
adb logcat
|
|
||||||
|
|
||||||
if using adb inside docker, make sure you did "docker run -v /dev/bus/usb:/dev/bus/usb --privileged"
|
|
||||||
|
|
||||||
- Using a web server
|
|
||||||
|
|
||||||
mkdir /usr/tmp
|
|
||||||
cp QtApp-debug.apk /usr/tmp
|
|
||||||
docker run -d -v /usr/tmp:/usr/share/nginx/html:ro -p 8080:80 nginx
|
|
||||||
|
|
||||||
Now it should be accessible through a web browser at
|
|
||||||
|
|
||||||
http://<your.local.ip>:8080/QtApp-debug.apk
|
|
||||||
|
|
||||||
@@ -1,107 +0,0 @@
|
|||||||
FROM monero-android
|
|
||||||
|
|
||||||
#INSTALL JAVA
|
|
||||||
RUN echo "deb http://ftp.fr.debian.org/debian/ jessie-backports main contrib non-free" >> /etc/apt/sources.list
|
|
||||||
RUN dpkg --add-architecture i386 \
|
|
||||||
&& apt-get update \
|
|
||||||
&& apt-get install -y libc6:i386 libncurses5:i386 libstdc++6:i386 libz1:i386 \
|
|
||||||
&& apt-get install -y -t jessie-backports ca-certificates-java openjdk-8-jdk-headless openjdk-8-jre-headless ant
|
|
||||||
ENV JAVA_HOME /usr/lib/jvm/java-8-openjdk-amd64
|
|
||||||
ENV PATH $JAVA_HOME/bin:$PATH
|
|
||||||
|
|
||||||
#Get Qt
|
|
||||||
ENV QT_VERSION 5.8
|
|
||||||
|
|
||||||
RUN git clone git://code.qt.io/qt/qt5.git -b ${QT_VERSION} \
|
|
||||||
&& cd qt5 \
|
|
||||||
&& perl init-repository
|
|
||||||
|
|
||||||
## Note: Need to use libc++ but Qt does not provide mkspec for libc++.
|
|
||||||
## Their support of it is quite recent and they claim they don't use it by default
|
|
||||||
## [only because it produces bigger binary objects](https://bugreports.qt.io/browse/QTBUG-50724).
|
|
||||||
|
|
||||||
#Create new mkspec for clang + libc++
|
|
||||||
RUN cp -r qt5/qtbase/mkspecs/android-clang qt5/qtbase/mkspecs/android-clang-libc \
|
|
||||||
&& cd qt5/qtbase/mkspecs/android-clang-libc \
|
|
||||||
&& sed -i '16i ANDROID_SOURCES_CXX_STL_LIBDIR = $$NDK_ROOT/sources/cxx-stl/llvm-libc++/libs/$$ANDROID_TARGET_ARCH' qmake.conf \
|
|
||||||
&& sed -i '17i ANDROID_SOURCES_CXX_STL_INCDIR = $$NDK_ROOT/sources/cxx-stl/llvm-libc++/include' qmake.conf \
|
|
||||||
&& echo "QMAKE_LIBS_PRIVATE = -lc++_shared -llog -lz -lm -ldl -lc -lgcc " >> qmake.conf \
|
|
||||||
&& echo "QMAKE_CFLAGS -= -mfpu=vfp " >> qmake.conf \
|
|
||||||
&& echo "QMAKE_CXXFLAGS -= -mfpu=vfp " >> qmake.conf \
|
|
||||||
&& echo "QMAKE_CFLAGS += -mfpu=vfp4 " >> qmake.conf \
|
|
||||||
&& echo "QMAKE_CXXFLAGS += -mfpu=vfp4 " >> qmake.conf
|
|
||||||
|
|
||||||
ENV ANDROID_API android-21
|
|
||||||
|
|
||||||
#ANDROID SDK TOOLS
|
|
||||||
RUN echo y | $ANDROID_SDK_ROOT/tools/android update sdk --no-ui --all --filter platform-tools
|
|
||||||
RUN echo y | $ANDROID_SDK_ROOT/tools/android update sdk --no-ui --all --filter ${ANDROID_API}
|
|
||||||
RUN echo y | $ANDROID_SDK_ROOT/tools/android update sdk --no-ui --all --filter build-tools-25.0.1
|
|
||||||
|
|
||||||
ENV CLEAN_PATH $JAVA_HOME/bin:/usr/cmake-3.6.3-Linux-x86_64/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
|
||||||
|
|
||||||
#build Qt
|
|
||||||
RUN cd qt5 && PATH=${CLEAN_PATH} ./configure -developer-build -release \
|
|
||||||
-xplatform android-clang-libc \
|
|
||||||
-android-ndk-platform ${ANDROID_API} \
|
|
||||||
-android-ndk $ANDROID_NDK_ROOT \
|
|
||||||
-android-sdk $ANDROID_SDK_ROOT \
|
|
||||||
-opensource -confirm-license \
|
|
||||||
-prefix ${WORKDIR}/Qt-${QT_VERSION} \
|
|
||||||
-nomake tests -nomake examples \
|
|
||||||
-skip qtserialport \
|
|
||||||
-skip qtconnectivity \
|
|
||||||
-skip qttranslations \
|
|
||||||
-skip qtgamepad -skip qtscript -skip qtdoc
|
|
||||||
|
|
||||||
# build Qt tools : gnustl_shared.so is hard-coded in androiddeployqt
|
|
||||||
# replace it with libc++_shared.so
|
|
||||||
COPY androiddeployqt.patch qt5/qttools/androiddeployqt.patch
|
|
||||||
RUN cd qt5/qttools \
|
|
||||||
&& git apply androiddeployqt.patch \
|
|
||||||
&& cd .. \
|
|
||||||
&& PATH=${CLEAN_PATH} make -j4 \
|
|
||||||
&& PATH=${CLEAN_PATH} make install
|
|
||||||
|
|
||||||
# Get iconv and ZBar
|
|
||||||
ENV ICONV_VERSION 1.14
|
|
||||||
RUN git clone https://github.com/ZBar/ZBar.git \
|
|
||||||
&& curl -s -O http://ftp.gnu.org/pub/gnu/libiconv/libiconv-${ICONV_VERSION}.tar.gz \
|
|
||||||
&& tar -xzf libiconv-${ICONV_VERSION}.tar.gz \
|
|
||||||
&& cd libiconv-${ICONV_VERSION} \
|
|
||||||
&& CC=arm-linux-androideabi-clang CXX=arm-linux-androideabi-clang++ ./configure --build=x86_64-linux-gnu --host=arm-eabi --prefix=${WORKDIR}/libiconv --disable-rpath
|
|
||||||
|
|
||||||
ENV PATH $ANDROID_SDK_ROOT/tools:$ANDROID_SDK_ROOT/platform-tools:${WORKDIR}/Qt-${QT_VERSION}/bin:$PATH
|
|
||||||
|
|
||||||
#Build libiconv.a and libzbarjni.a
|
|
||||||
COPY android.mk.patch ZBar/android.mk.patch
|
|
||||||
RUN cd ZBar \
|
|
||||||
&& git apply android.mk.patch \
|
|
||||||
&& echo \
|
|
||||||
"APP_ABI := armeabi-v7a \n\
|
|
||||||
APP_STL := c++_shared \n\
|
|
||||||
TARGET_PLATFORM := ${ANDROID_API} \n\
|
|
||||||
TARGET_ARCH_ABI := armeabi-v7a \n\
|
|
||||||
APP_CFLAGS += -target armv7-none-linux-androideabi -fexceptions -fstack-protector-strong -fno-limit-debug-info -mfloat-abi=softfp -mfpu=vfp -fno-builtin-memmove -fno-omit-frame-pointer -fno-stack-protector\n"\
|
|
||||||
>> android/jni/Application.mk \
|
|
||||||
&& cd android \
|
|
||||||
&& android update project --path . -t "${ANDROID_API}" \
|
|
||||||
&& CC=arm-linux-androideabi-clang CXX=arm-linux-androideabi-clang++ ant -Dndk.dir=${ANDROID_NDK_ROOT} -Diconv.src=${WORKDIR}/libiconv-${ICONV_VERSION} zbar-clean zbar-ndk-build
|
|
||||||
|
|
||||||
RUN cp openssl/lib* ${ANDROID_NDK_ROOT}/platforms/${ANDROID_API}/arch-arm/usr/lib
|
|
||||||
RUN cp boost_${BOOST_VERSION}/android32/lib/lib* ${ANDROID_NDK_ROOT}/platforms/${ANDROID_API}/arch-arm/usr/lib
|
|
||||||
RUN cp ZBar/android/obj/local/armeabi-v7a/lib* ${ANDROID_NDK_ROOT}/platforms/${ANDROID_API}/arch-arm/usr/lib
|
|
||||||
|
|
||||||
RUN git clone https://github.com/monero-project/monero-gui.git \
|
|
||||||
&& cd monero-gui \
|
|
||||||
&& git submodule update \
|
|
||||||
&& CC=arm-linux-androideabi-clang CXX=arm-linux-androideabi-clang++ BOOST_ROOT=/opt/android/boost_1_62_0 \
|
|
||||||
BOOST_LIBRARYDIR=${WORKDIR}/boost_${BOOST_VERSION}/android32/lib/ \
|
|
||||||
OPENSSL_ROOT_DIR=${WORKDIR}/openssl/ \
|
|
||||||
CMAKE_INCLUDE_PATH=${WORKDIR}/cppzmq/ \
|
|
||||||
CMAKE_LIBRARY_PATH=${WORKDIR}/zeromq4-1/.libs \
|
|
||||||
CXXFLAGS="-I ${WORKDIR}/zeromq4-1/include/" \
|
|
||||||
./build.sh release-android \
|
|
||||||
&& cd build \
|
|
||||||
&& make deploy
|
|
||||||
|
|
||||||
@@ -1,61 +0,0 @@
|
|||||||
diff --git a/android/jni/Android.mk b/android/jni/Android.mk
|
|
||||||
index e442b07..158afd5 100644
|
|
||||||
--- a/android/jni/Android.mk
|
|
||||||
+++ b/android/jni/Android.mk
|
|
||||||
@@ -12,14 +12,18 @@ LOCAL_PATH := $(ICONV_SRC)
|
|
||||||
|
|
||||||
LOCAL_MODULE := libiconv
|
|
||||||
|
|
||||||
+LOCAL_ARM_MODE := arm
|
|
||||||
+LOCAL_CPP_FEATURES := exceptions rtti features
|
|
||||||
LOCAL_CFLAGS := \
|
|
||||||
-Wno-multichar \
|
|
||||||
-D_ANDROID \
|
|
||||||
- -DLIBDIR="c" \
|
|
||||||
+ -DLIBDIR="\".\"" \
|
|
||||||
-DBUILDING_LIBICONV \
|
|
||||||
-DBUILDING_LIBCHARSET \
|
|
||||||
-DIN_LIBRARY
|
|
||||||
|
|
||||||
+LOCAL_CFLAGS += -fno-stack-protector
|
|
||||||
+
|
|
||||||
LOCAL_SRC_FILES := \
|
|
||||||
lib/iconv.c \
|
|
||||||
libcharset/lib/localcharset.c \
|
|
||||||
@@ -30,13 +34,14 @@ LOCAL_C_INCLUDES := \
|
|
||||||
$(ICONV_SRC)/libcharset \
|
|
||||||
$(ICONV_SRC)/libcharset/include
|
|
||||||
|
|
||||||
-include $(BUILD_SHARED_LIBRARY)
|
|
||||||
+include $(BUILD_STATIC_LIBRARY)
|
|
||||||
|
|
||||||
LOCAL_LDLIBS := -llog -lcharset
|
|
||||||
|
|
||||||
# libzbarjni
|
|
||||||
include $(CLEAR_VARS)
|
|
||||||
|
|
||||||
+
|
|
||||||
LOCAL_PATH := $(MY_LOCAL_PATH)
|
|
||||||
LOCAL_MODULE := zbarjni
|
|
||||||
LOCAL_SRC_FILES := ../../java/zbarjni.c \
|
|
||||||
@@ -71,6 +76,17 @@ LOCAL_C_INCLUDES := ../include \
|
|
||||||
../zbar \
|
|
||||||
$(ICONV_SRC)/include
|
|
||||||
|
|
||||||
-LOCAL_SHARED_LIBRARIES := libiconv
|
|
||||||
+LOCAL_STATIC_LIBRARIES := libiconv
|
|
||||||
+LOCAL_ARM_MODE := arm
|
|
||||||
+LOCAL_CPP_FEATURES := exceptions rtti features
|
|
||||||
+
|
|
||||||
+LOCAL_CFLAGS := \
|
|
||||||
+ -Wno-multichar \
|
|
||||||
+ -D_ANDROID \
|
|
||||||
+ -DLIBDIR="\".\"" \
|
|
||||||
+ -DBUILDING_LIBICONV \
|
|
||||||
+ -DBUILDING_LIBCHARSET \
|
|
||||||
+ -DIN_LIBRARY
|
|
||||||
+
|
|
||||||
|
|
||||||
-include $(BUILD_SHARED_LIBRARY)
|
|
||||||
\ No newline at end of file
|
|
||||||
+include $(BUILD_STATIC_LIBRARY)
|
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
diff --git a/src/androiddeployqt/main.cpp b/src/androiddeployqt/main.cpp
|
|
||||||
index 8a8e591..71d693e 100644
|
|
||||||
--- a/src/androiddeployqt/main.cpp
|
|
||||||
+++ b/src/androiddeployqt/main.cpp
|
|
||||||
@@ -1122,7 +1122,7 @@ bool updateLibsXml(const Options &options)
|
|
||||||
|
|
||||||
QString libsPath = QLatin1String("libs/") + options.architecture + QLatin1Char('/');
|
|
||||||
|
|
||||||
- QString qtLibs = QLatin1String("<item>gnustl_shared</item>\n");
|
|
||||||
+ QString qtLibs = QLatin1String("<item>c++_shared</item>\n");
|
|
||||||
QString bundledInLibs;
|
|
||||||
QString bundledInAssets;
|
|
||||||
foreach (Options::BundledFile bundledFile, options.bundledFiles) {
|
|
||||||
@@ -2519,6 +2519,39 @@ bool installApk(const Options &options)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
+bool copyStl(Options *options)
|
|
||||||
+{
|
|
||||||
+ if (options->deploymentMechanism == Options::Debug && !options->installApk)
|
|
||||||
+ return true;
|
|
||||||
+
|
|
||||||
+ if (options->verbose)
|
|
||||||
+ fprintf(stdout, "Copying LIBC++ STL library\n");
|
|
||||||
+
|
|
||||||
+ QString filePath = options->ndkPath
|
|
||||||
+ + QLatin1String("/sources/cxx-stl/llvm-libc++")
|
|
||||||
+ + QLatin1String("/libs/")
|
|
||||||
+ + options->architecture
|
|
||||||
+ + QLatin1String("/libc++_shared.so");
|
|
||||||
+ if (!QFile::exists(filePath)) {
|
|
||||||
+ fprintf(stderr, "LIBC STL library does not exist at %s\n", qPrintable(filePath));
|
|
||||||
+ return false;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ QString destinationDirectory =
|
|
||||||
+ options->deploymentMechanism == Options::Debug
|
|
||||||
+ ? options->temporaryDirectoryName + QLatin1String("/lib")
|
|
||||||
+ : options->outputDirectory + QLatin1String("/libs/") + options->architecture;
|
|
||||||
+
|
|
||||||
+ if (!copyFileIfNewer(filePath, destinationDirectory
|
|
||||||
+ + QLatin1String("/libc++_shared.so"), options->verbose)) {
|
|
||||||
+ return false;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (options->deploymentMechanism == Options::Debug && !deployToLocalTmp(options, QLatin1String("/lib/libc++_shared.so")))
|
|
||||||
+ return false;
|
|
||||||
+
|
|
||||||
+ return true;
|
|
||||||
+}
|
|
||||||
bool copyGnuStl(Options *options)
|
|
||||||
{
|
|
||||||
if (options->deploymentMechanism == Options::Debug && !options->installApk)
|
|
||||||
@@ -2870,7 +2903,7 @@ int main(int argc, char *argv[])
|
|
||||||
if (Q_UNLIKELY(options.timing))
|
|
||||||
fprintf(stdout, "[TIMING] %d ms: Read dependencies\n", options.timer.elapsed());
|
|
||||||
|
|
||||||
- if (options.deploymentMechanism != Options::Ministro && !copyGnuStl(&options))
|
|
||||||
+ if (options.deploymentMechanism != Options::Ministro && !copyStl(&options))
|
|
||||||
return CannotCopyGnuStl;
|
|
||||||
|
|
||||||
if (Q_UNLIKELY(options.timing))
|
|
||||||
121
build.sh
121
build.sh
@@ -1,121 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
BUILD_TYPE=$1
|
|
||||||
BUILD_TREZOR=${BUILD_TREZOR-true}
|
|
||||||
source ./utils.sh
|
|
||||||
platform=$(get_platform)
|
|
||||||
# default build type
|
|
||||||
if [ -z $BUILD_TYPE ]; then
|
|
||||||
BUILD_TYPE=release
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Return 0 if the command exists, 1 if it does not.
|
|
||||||
exists() {
|
|
||||||
command -v "$1" &>/dev/null
|
|
||||||
}
|
|
||||||
|
|
||||||
# Return the first value in $@ that's a runnable command.
|
|
||||||
find_command() {
|
|
||||||
for arg in "$@"; do
|
|
||||||
if exists "$arg"; then
|
|
||||||
echo "$arg"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
if [ "$BUILD_TYPE" == "release" ]; then
|
|
||||||
echo "Building release"
|
|
||||||
CONFIG="CONFIG+=release";
|
|
||||||
BIN_PATH=release/bin
|
|
||||||
elif [ "$BUILD_TYPE" == "release-static" ]; then
|
|
||||||
echo "Building release-static"
|
|
||||||
if [ "$platform" != "darwin" ]; then
|
|
||||||
CONFIG="CONFIG+=release static";
|
|
||||||
else
|
|
||||||
# OS X: build static libwallet but dynamic Qt.
|
|
||||||
echo "OS X: Building Qt project without static flag"
|
|
||||||
CONFIG="CONFIG+=release";
|
|
||||||
fi
|
|
||||||
BIN_PATH=release/bin
|
|
||||||
elif [ "$BUILD_TYPE" == "release-android" ]; then
|
|
||||||
echo "Building release for ANDROID"
|
|
||||||
CONFIG="CONFIG+=release static WITH_SCANNER DISABLE_PASS_STRENGTH_METER";
|
|
||||||
ANDROID=true
|
|
||||||
BIN_PATH=release/bin
|
|
||||||
DISABLE_PASS_STRENGTH_METER=true
|
|
||||||
elif [ "$BUILD_TYPE" == "debug-android" ]; then
|
|
||||||
echo "Building debug for ANDROID : ultra INSECURE !!"
|
|
||||||
CONFIG="CONFIG+=debug qml_debug WITH_SCANNER DISABLE_PASS_STRENGTH_METER";
|
|
||||||
ANDROID=true
|
|
||||||
BIN_PATH=debug/bin
|
|
||||||
DISABLE_PASS_STRENGTH_METER=true
|
|
||||||
elif [ "$BUILD_TYPE" == "debug" ]; then
|
|
||||||
echo "Building debug"
|
|
||||||
CONFIG="CONFIG+=debug"
|
|
||||||
BIN_PATH=debug/bin
|
|
||||||
else
|
|
||||||
echo "Valid build types are release, release-static, release-android, debug-android and debug"
|
|
||||||
exit 1;
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
source ./utils.sh
|
|
||||||
pushd $(pwd)
|
|
||||||
ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|
||||||
MONERO_DIR=monero
|
|
||||||
MONEROD_EXEC=monerod
|
|
||||||
|
|
||||||
MAKE='make'
|
|
||||||
if [[ $platform == *bsd* ]]; then
|
|
||||||
MAKE='gmake'
|
|
||||||
fi
|
|
||||||
|
|
||||||
# build libwallet
|
|
||||||
export BUILD_TREZOR
|
|
||||||
./get_libwallet_api.sh $BUILD_TYPE
|
|
||||||
|
|
||||||
# build zxcvbn
|
|
||||||
if [ "$DISABLE_PASS_STRENGTH_METER" != true ]; then
|
|
||||||
$MAKE -C src/zxcvbn-c || exit
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ ! -d build ]; then mkdir build; fi
|
|
||||||
|
|
||||||
|
|
||||||
# Platform indepenent settings
|
|
||||||
if [ "$ANDROID" != true ] && ([ "$platform" == "linux32" ] || [ "$platform" == "linux64" ]); then
|
|
||||||
exists lsb_release && distro="$(lsb_release -is)"
|
|
||||||
if [ "$distro" = "Ubuntu" ] || [ "$distro" = "Fedora" ] || test -f /etc/fedora-release; then
|
|
||||||
CONFIG="$CONFIG libunwind_off"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$platform" == "darwin" ]; then
|
|
||||||
BIN_PATH=$BIN_PATH/monero-wallet-gui.app/Contents/MacOS/
|
|
||||||
elif [ "$platform" == "mingw64" ] || [ "$platform" == "mingw32" ]; then
|
|
||||||
MONEROD_EXEC=monerod.exe
|
|
||||||
fi
|
|
||||||
|
|
||||||
# force version update
|
|
||||||
get_tag
|
|
||||||
GUI_VERSION=$(echo "$TAGNAME" | sed 's/^v\([[:digit:]]\)/\1/')
|
|
||||||
echo "var GUI_VERSION = \"$GUI_VERSION\"" > version.js
|
|
||||||
|
|
||||||
cd build
|
|
||||||
if ! QMAKE=$(find_command qmake qmake-qt5); then
|
|
||||||
echo "Failed to find suitable qmake command."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
$QMAKE ../monero-wallet-gui.pro "$CONFIG" || exit
|
|
||||||
$MAKE || exit
|
|
||||||
|
|
||||||
# Copy monerod to bin folder
|
|
||||||
if [ "$platform" != "mingw32" ] && [ "$ANDROID" != true ]; then
|
|
||||||
cp ../$MONERO_DIR/bin/$MONEROD_EXEC $BIN_PATH
|
|
||||||
fi
|
|
||||||
|
|
||||||
# make deploy
|
|
||||||
popd
|
|
||||||
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
# from http://code.google.com/p/low-cost-vision-2012/source/browse/CMakeModules/FindZBar0.cmake?name=2-helium-1&r=d61f248bd5565b3c086bf4769a04bfd98f7079df
|
|
||||||
# - Try to find ZBar
|
|
||||||
# This will define
|
|
||||||
#
|
|
||||||
# ZBAR_FOUND -
|
|
||||||
# ZBAR_LIBRARY_DIR -
|
|
||||||
# ZBAR_INCLUDE_DIR -
|
|
||||||
# ZBAR_LIBRARIES -
|
|
||||||
#
|
|
||||||
|
|
||||||
find_package(PkgConfig)
|
|
||||||
pkg_check_modules(PC_ZBAR QUIET zbar)
|
|
||||||
set(ZBAR_DEFINITIONS ${PC_ZBAR_CFLAGS_OTHER})
|
|
||||||
find_library(ZBAR_LIBRARIES NAMES zbar
|
|
||||||
HINTS ${PC_ZBAR_LIBDIR} ${PC_ZBAR_LIBRARY_DIRS} )
|
|
||||||
find_path(ZBAR_INCLUDE_DIR Decoder.h
|
|
||||||
HINTS ${PC_ZBAR_INCLUDEDIR} ${PC_ZBAR_INCLUDE_DIRS}
|
|
||||||
PATH_SUFFIXES zbar )
|
|
||||||
include(FindPackageHandleStandardArgs)
|
|
||||||
find_package_handle_standard_args(ZBAR DEFAULT_MSG ZBAR_LIBRARIES ZBAR_INCLUDE_DIR)
|
|
||||||
message(STATUS "Found zbar libraries ${ZBAR_LIBRARIES}")
|
|
||||||
|
|
||||||
@@ -49,8 +49,14 @@ Item {
|
|||||||
property alias fontColor: label.color
|
property alias fontColor: label.color
|
||||||
property bool iconOnTheLeft: true
|
property bool iconOnTheLeft: true
|
||||||
signal clicked()
|
signal clicked()
|
||||||
|
|
||||||
height: 25
|
height: 25
|
||||||
width: checkBoxLayout.width
|
width: checkBoxLayout.width
|
||||||
|
opacity: enabled ? 1 : 0.7
|
||||||
|
|
||||||
|
Keys.onEnterPressed: toggle()
|
||||||
|
Keys.onReturnPressed: Keys.onEnterPressed(event)
|
||||||
|
Keys.onSpacePressed: Keys.onEnterPressed(event)
|
||||||
|
|
||||||
function toggle(){
|
function toggle(){
|
||||||
if (checkBox.toggleOnClick) {
|
if (checkBox.toggleOnClick) {
|
||||||
@@ -76,7 +82,7 @@ Item {
|
|||||||
radius: 3
|
radius: 3
|
||||||
color: checkBox.enabled ? "transparent" : MoneroComponents.Style.inputBoxBackgroundDisabled
|
color: checkBox.enabled ? "transparent" : MoneroComponents.Style.inputBoxBackgroundDisabled
|
||||||
border.color:
|
border.color:
|
||||||
if(checkBox.checked){
|
if (checkBox.activeFocus) {
|
||||||
return MoneroComponents.Style.inputBorderColorActive;
|
return MoneroComponents.Style.inputBorderColorActive;
|
||||||
} else {
|
} else {
|
||||||
return MoneroComponents.Style.inputBorderColorInActive;
|
return MoneroComponents.Style.inputBorderColorInActive;
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ Window {
|
|||||||
// TODO: implement without hardcoding sizes
|
// TODO: implement without hardcoding sizes
|
||||||
width: 480
|
width: 480
|
||||||
height: 200
|
height: 200
|
||||||
|
color: MoneroComponents.Style.middlePanelBackgroundColor
|
||||||
|
|
||||||
// Make window draggable
|
// Make window draggable
|
||||||
MouseArea {
|
MouseArea {
|
||||||
@@ -96,7 +97,7 @@ Window {
|
|||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
horizontalAlignment: Text.AlignHCenter
|
horizontalAlignment: Text.AlignHCenter
|
||||||
themeTransition: false
|
themeTransition: false
|
||||||
color: "black"
|
color: MoneroComponents.Style.defaultFontColor
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
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 != ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -30,30 +30,25 @@ import QtQuick 2.9
|
|||||||
import QtQuick.Layouts 1.1
|
import QtQuick.Layouts 1.1
|
||||||
import QtGraphicalEffects 1.0
|
import QtGraphicalEffects 1.0
|
||||||
|
|
||||||
|
import FontAwesome 1.0
|
||||||
|
|
||||||
import "." as MoneroComponents
|
import "." as MoneroComponents
|
||||||
import "./effects/" as MoneroEffects
|
import "./effects/" as MoneroEffects
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: inlineButton
|
id: inlineButton
|
||||||
height: parent.height
|
|
||||||
anchors.top: parent.top
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
|
|
||||||
property bool small: false
|
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 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 text: inlineText.text
|
||||||
property alias fontPixelSize: inlineText.font.pixelSize
|
property alias fontPixelSize: inlineText.font.pixelSize
|
||||||
property alias fontFamily: inlineText.font.family
|
property alias fontFamily: inlineText.font.family
|
||||||
|
property bool isFontAwesomeIcon: fontFamily == FontAwesome.fontFamily || fontFamily == FontAwesome.fontFamilySolid
|
||||||
property alias buttonColor: rect.color
|
property alias buttonColor: rect.color
|
||||||
property alias buttonHeight: rect.height
|
|
||||||
|
height: isFontAwesomeIcon ? 30 : 24
|
||||||
|
width: isFontAwesomeIcon ? height : inlineText.width + 16
|
||||||
|
|
||||||
signal clicked()
|
signal clicked()
|
||||||
|
|
||||||
function doClick() {
|
function doClick() {
|
||||||
@@ -64,20 +59,16 @@ Item {
|
|||||||
|
|
||||||
Rectangle{
|
Rectangle{
|
||||||
id: rect
|
id: rect
|
||||||
|
anchors.fill: parent
|
||||||
color: MoneroComponents.Style.buttonInlineBackgroundColor
|
color: MoneroComponents.Style.buttonInlineBackgroundColor
|
||||||
height: 24
|
|
||||||
width: inlineText.text ? (inlineText.width + 16) : inlineButton.icon ? (inlineImage.width + 16) : rect.height
|
|
||||||
radius: 4
|
radius: 4
|
||||||
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.rightMargin: 4
|
|
||||||
|
|
||||||
MoneroComponents.TextPlain {
|
MoneroComponents.TextPlain {
|
||||||
id: inlineText
|
id: inlineText
|
||||||
font.family: MoneroComponents.Style.fontBold.name
|
font.family: MoneroComponents.Style.fontBold.name
|
||||||
font.bold: true
|
font.bold: true
|
||||||
font.pixelSize: inlineButton.fontSize
|
font.pixelSize: inlineButton.isFontAwesomeIcon ? 22 : inlineButton.small ? 14 : 16
|
||||||
color: inlineButton.textColor
|
color: inlineButton.textColor
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
@@ -90,13 +81,6 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Image {
|
|
||||||
id: inlineImage
|
|
||||||
visible: inlineButton.icon !== ""
|
|
||||||
anchors.centerIn: parent
|
|
||||||
source: inlineButton.icon
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
id: buttonArea
|
id: buttonArea
|
||||||
cursorShape: rect.enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
|
cursorShape: rect.enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||||
|
|||||||
67
components/LanguageButton.qml
Normal file
67
components/LanguageButton.qml
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
// Copyright (c) 2020, The Monero Project
|
||||||
|
//
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
// permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
// conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
|
// of conditions and the following disclaimer in the documentation and/or other
|
||||||
|
// materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||||
|
// used to endorse or promote products derived from this software without specific
|
||||||
|
// prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||||
|
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||||
|
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||||
|
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
import QtQuick 2.9
|
||||||
|
import QtQuick.Layouts 1.3
|
||||||
|
|
||||||
|
import FontAwesome 1.0
|
||||||
|
|
||||||
|
import "../components" as MoneroComponents
|
||||||
|
|
||||||
|
Item {
|
||||||
|
implicitHeight: layout.height
|
||||||
|
implicitWidth: layout.width
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
id: layout
|
||||||
|
opacity: mouseArea.containsMouse ? 1 : 0.85
|
||||||
|
spacing: 10
|
||||||
|
|
||||||
|
MoneroComponents.Label {
|
||||||
|
Layout.bottomMargin: 5
|
||||||
|
fontColor: MoneroComponents.Style.defaultFontColor
|
||||||
|
fontFamily: FontAwesome.fontFamilySolid
|
||||||
|
fontSize: 26
|
||||||
|
styleName: "Solid"
|
||||||
|
text: FontAwesome.language
|
||||||
|
}
|
||||||
|
|
||||||
|
MoneroComponents.TextPlain {
|
||||||
|
font.pixelSize: 14
|
||||||
|
text: persistentSettings.language
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: mouseArea
|
||||||
|
anchors.fill: parent
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
hoverEnabled: true
|
||||||
|
onClicked: appWindow.toggleLanguageView()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -131,9 +131,9 @@ Drawer {
|
|||||||
translationManager.setLanguage(locale_spl[0]);
|
translationManager.setLanguage(locale_spl[0]);
|
||||||
|
|
||||||
// set wizard language settings
|
// set wizard language settings
|
||||||
wizard.language_locale = locale;
|
persistentSettings.locale = locale;
|
||||||
wizard.language_wallet = wallet_language;
|
persistentSettings.language = display_name;
|
||||||
wizard.language_language = display_name;
|
persistentSettings.language_wallet = wallet_language;
|
||||||
|
|
||||||
appWindow.showStatusMessage(qsTr("Language changed."), 3);
|
appWindow.showStatusMessage(qsTr("Language changed."), 3);
|
||||||
appWindow.toggleLanguageView();
|
appWindow.toggleLanguageView();
|
||||||
|
|||||||
@@ -29,11 +29,15 @@
|
|||||||
import FontAwesome 1.0
|
import FontAwesome 1.0
|
||||||
import QtQuick 2.9
|
import QtQuick 2.9
|
||||||
import QtGraphicalEffects 1.0
|
import QtGraphicalEffects 1.0
|
||||||
|
import QtQuick.Layouts 1.1
|
||||||
|
|
||||||
import "../components" as MoneroComponents
|
import "../components" as MoneroComponents
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: item
|
id: item
|
||||||
|
|
||||||
|
default property alias content: inlineButtons.children
|
||||||
|
|
||||||
property alias input: input
|
property alias input: input
|
||||||
property alias text: input.text
|
property alias text: input.text
|
||||||
|
|
||||||
@@ -48,13 +52,20 @@ Item {
|
|||||||
property int placeholderFontSize: 18
|
property int placeholderFontSize: 18
|
||||||
property string placeholderColor: MoneroComponents.Style.defaultFontColor
|
property string placeholderColor: MoneroComponents.Style.defaultFontColor
|
||||||
property real placeholderOpacity: 0.35
|
property real placeholderOpacity: 0.35
|
||||||
|
property real placeholderLeftMargin: {
|
||||||
|
if (placeholderCenter) {
|
||||||
|
return undefined;
|
||||||
|
} else if (inlineIcon.visible) {
|
||||||
|
return inlineIcon.width + inlineIcon.anchors.leftMargin + inputPadding;
|
||||||
|
} else {
|
||||||
|
return inputPadding;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
property alias acceptableInput: input.acceptableInput
|
property alias acceptableInput: input.acceptableInput
|
||||||
property alias validator: input.validator
|
property alias validator: input.validator
|
||||||
property alias readOnly : input.readOnly
|
property alias readOnly : input.readOnly
|
||||||
property alias cursorPosition: input.cursorPosition
|
property alias cursorPosition: input.cursorPosition
|
||||||
property alias inlineButton: inlineButtonId
|
|
||||||
property alias inlineButtonText: inlineButtonId.text
|
|
||||||
property alias inlineIcon: inlineIcon.visible
|
property alias inlineIcon: inlineIcon.visible
|
||||||
property bool copyButton: false
|
property bool copyButton: false
|
||||||
property alias copyButtonText: copyButtonId.text
|
property alias copyButtonText: copyButtonId.text
|
||||||
@@ -71,6 +82,7 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
property string fontFamily: MoneroComponents.Style.fontRegular.name
|
||||||
property int fontSize: 18
|
property int fontSize: 18
|
||||||
property bool fontBold: false
|
property bool fontBold: false
|
||||||
property alias fontColor: input.color
|
property alias fontColor: input.color
|
||||||
@@ -86,14 +98,16 @@ Item {
|
|||||||
property alias labelHorizontalAlignment: inputLabel.horizontalAlignment
|
property alias labelHorizontalAlignment: inputLabel.horizontalAlignment
|
||||||
property bool showingHeader: inputLabel.text !== "" || copyButton
|
property bool showingHeader: inputLabel.text !== "" || copyButton
|
||||||
property int inputHeight: 42
|
property int inputHeight: 42
|
||||||
|
property int inputPadding: 10
|
||||||
|
|
||||||
signal labelLinkActivated(); // input label, rich text <a> signal
|
signal labelLinkActivated(); // input label, rich text <a> signal
|
||||||
signal editingFinished();
|
signal editingFinished();
|
||||||
signal accepted();
|
signal accepted();
|
||||||
signal textUpdated();
|
signal textUpdated();
|
||||||
|
|
||||||
height: showingHeader ? (inputLabel.height + inputItem.height + 2) : 42
|
height: showingHeader ? (inputLabel.height + inputItem.height + 2) : inputHeight
|
||||||
|
|
||||||
|
onActiveFocusChanged: activeFocus && input.forceActiveFocus()
|
||||||
onTextUpdated: {
|
onTextUpdated: {
|
||||||
// check to remove placeholder text when there is content
|
// check to remove placeholder text when there is content
|
||||||
if(item.isEmpty()){
|
if(item.isEmpty()){
|
||||||
@@ -174,7 +188,7 @@ Item {
|
|||||||
id: inputItem
|
id: inputItem
|
||||||
height: inputHeight
|
height: inputHeight
|
||||||
anchors.top: showingHeader ? inputLabel.bottom : parent.top
|
anchors.top: showingHeader ? inputLabel.bottom : parent.top
|
||||||
anchors.topMargin: showingHeader ? 12 : 2
|
anchors.topMargin: showingHeader ? 12 : 0
|
||||||
width: parent.width
|
width: parent.width
|
||||||
clip: true
|
clip: true
|
||||||
|
|
||||||
@@ -184,13 +198,7 @@ Item {
|
|||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
anchors.horizontalCenter: placeholderCenter ? parent.horizontalCenter : undefined
|
anchors.horizontalCenter: placeholderCenter ? parent.horizontalCenter : undefined
|
||||||
anchors.left: placeholderCenter ? undefined : parent.left
|
anchors.left: placeholderCenter ? undefined : parent.left
|
||||||
anchors.leftMargin: {
|
anchors.leftMargin: placeholderLeftMargin
|
||||||
if(placeholderCenter){
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
else if(inlineIcon.visible){ return 50; }
|
|
||||||
else { return 10; }
|
|
||||||
}
|
|
||||||
|
|
||||||
opacity: item.placeholderOpacity
|
opacity: item.placeholderOpacity
|
||||||
color: item.placeholderColor
|
color: item.placeholderColor
|
||||||
@@ -232,13 +240,18 @@ Item {
|
|||||||
id: input
|
id: input
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.leftMargin: inlineIcon.visible ? 44 : 0
|
anchors.leftMargin: inlineIcon.visible ? 44 : 0
|
||||||
|
font.family: item.fontFamily
|
||||||
font.pixelSize: item.fontSize
|
font.pixelSize: item.fontSize
|
||||||
font.bold: item.fontBold
|
font.bold: item.fontBold
|
||||||
|
KeyNavigation.backtab: item.KeyNavigation.backtab
|
||||||
|
KeyNavigation.tab: item.KeyNavigation.tab
|
||||||
onEditingFinished: item.editingFinished()
|
onEditingFinished: item.editingFinished()
|
||||||
onAccepted: item.accepted();
|
onAccepted: item.accepted();
|
||||||
onTextChanged: item.textUpdated()
|
onTextChanged: item.textUpdated()
|
||||||
topPadding: 10
|
leftPadding: inputPadding
|
||||||
bottomPadding: 10
|
rightPadding: (inlineButtons.width > 0 ? inlineButtons.width + inlineButtons.spacing : 0) + inputPadding
|
||||||
|
topPadding: inputPadding
|
||||||
|
bottomPadding: inputPadding
|
||||||
echoMode: isPasswordHidden() ? TextInput.Password : TextInput.Normal
|
echoMode: isPasswordHidden() ? TextInput.Password : TextInput.Normal
|
||||||
|
|
||||||
MoneroComponents.Label {
|
MoneroComponents.Label {
|
||||||
@@ -260,13 +273,17 @@ Item {
|
|||||||
onClicked: passwordToggle()
|
onClicked: passwordToggle()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
MoneroComponents.InlineButton {
|
RowLayout {
|
||||||
id: inlineButtonId
|
id: inlineButtons
|
||||||
visible: item.inlineButtonText ? true : false
|
anchors.bottom: parent.bottom
|
||||||
anchors.right: parent.right
|
anchors.top: parent.top
|
||||||
anchors.rightMargin: 8
|
anchors.right: parent.right
|
||||||
|
anchors.topMargin: inputPadding
|
||||||
|
anchors.bottomMargin: inputPadding
|
||||||
|
anchors.rightMargin: inputPadding
|
||||||
|
spacing: 4
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,8 @@ ColumnLayout {
|
|||||||
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
default property alias content: inlineButtons.children
|
||||||
|
|
||||||
property alias text: input.text
|
property alias text: input.text
|
||||||
property alias labelText: inputLabel.text
|
property alias labelText: inputLabel.text
|
||||||
property alias labelButtonText: labelButton.text
|
property alias labelButtonText: labelButton.text
|
||||||
@@ -73,6 +75,7 @@ ColumnLayout {
|
|||||||
property bool labelButtonVisible: false
|
property bool labelButtonVisible: false
|
||||||
|
|
||||||
property string fontColor: MoneroComponents.Style.defaultFontColor
|
property string fontColor: MoneroComponents.Style.defaultFontColor
|
||||||
|
property string fontFamily: MoneroComponents.Style.fontRegular.name
|
||||||
property bool fontBold: false
|
property bool fontBold: false
|
||||||
property int fontSize: 16
|
property int fontSize: 16
|
||||||
|
|
||||||
@@ -85,15 +88,12 @@ ColumnLayout {
|
|||||||
property alias addressValidation: input.addressValidation
|
property alias addressValidation: input.addressValidation
|
||||||
property string backgroundColor: "" // mock
|
property string backgroundColor: "" // mock
|
||||||
|
|
||||||
property alias inlineButton: inlineButtonId
|
|
||||||
property bool inlineButtonVisible: false
|
|
||||||
property alias inlineButton2: inlineButton2Id
|
|
||||||
property bool inlineButton2Visible: false
|
|
||||||
|
|
||||||
signal labelButtonClicked();
|
signal labelButtonClicked();
|
||||||
signal inputLabelLinkActivated();
|
signal inputLabelLinkActivated();
|
||||||
signal editingFinished();
|
signal editingFinished();
|
||||||
|
|
||||||
|
onActiveFocusChanged: activeFocus && input.forceActiveFocus()
|
||||||
|
|
||||||
spacing: 0
|
spacing: 0
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: inputLabelRect
|
id: inputLabelRect
|
||||||
@@ -159,14 +159,18 @@ ColumnLayout {
|
|||||||
id: input
|
id: input
|
||||||
readOnly: false
|
readOnly: false
|
||||||
addressValidation: false
|
addressValidation: false
|
||||||
|
KeyNavigation.backtab: item.KeyNavigation.backtab
|
||||||
|
KeyNavigation.priority: KeyNavigation.BeforeItem
|
||||||
|
KeyNavigation.tab: item.KeyNavigation.tab
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
|
||||||
leftPadding: item.inputPaddingLeft
|
leftPadding: item.inputPaddingLeft
|
||||||
rightPadding: item.inputPaddingRight
|
rightPadding: (inlineButtons.width > 0 ? inlineButtons.width + inlineButtons.spacing : 0) + inputPaddingRight
|
||||||
topPadding: item.inputPaddingTop
|
topPadding: item.inputPaddingTop
|
||||||
bottomPadding: item.inputPaddingBottom
|
bottomPadding: item.inputPaddingBottom
|
||||||
|
|
||||||
wrapMode: item.wrapMode
|
wrapMode: item.wrapMode
|
||||||
|
font.family: item.fontFamily
|
||||||
fontSize: item.fontSize
|
fontSize: item.fontSize
|
||||||
fontBold: item.fontBold
|
fontBold: item.fontBold
|
||||||
fontColor: item.fontColor
|
fontColor: item.fontColor
|
||||||
@@ -198,18 +202,12 @@ ColumnLayout {
|
|||||||
visible: !item.borderDisabled
|
visible: !item.borderDisabled
|
||||||
}
|
}
|
||||||
|
|
||||||
MoneroComponents.InlineButton {
|
RowLayout {
|
||||||
id: inlineButtonId
|
id: inlineButtons
|
||||||
visible: (inlineButtonId.text || inlineButtonId.icon) && inlineButtonVisible ? true : false
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.rightMargin: 8
|
anchors.rightMargin: inputPaddingRight
|
||||||
}
|
spacing: 4
|
||||||
|
|
||||||
MoneroComponents.InlineButton {
|
|
||||||
id: inlineButton2Id
|
|
||||||
visible: (inlineButton2Id.text || inlineButton2Id.icon) && inlineButton2Visible ? true : false
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.rightMargin: inlineButtonVisible ? 48 : 8
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
207
components/Navbar.qml
Normal file
207
components/Navbar.qml
Normal file
@@ -0,0 +1,207 @@
|
|||||||
|
// Copyright (c) 2014-2021, The Monero Project
|
||||||
|
//
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
// permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
// conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
|
// of conditions and the following disclaimer in the documentation and/or other
|
||||||
|
// materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||||
|
// used to endorse or promote products derived from this software without specific
|
||||||
|
// prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||||
|
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||||
|
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||||
|
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
import QtQuick 2.9
|
||||||
|
import QtQuick.Layouts 1.1
|
||||||
|
import "." as MoneroComponents
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
default property list<MoneroComponents.NavbarItem> items
|
||||||
|
|
||||||
|
color: "transparent"
|
||||||
|
height: grid.height
|
||||||
|
width: grid.width
|
||||||
|
|
||||||
|
GridLayout {
|
||||||
|
id: grid
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
columnSpacing: 0
|
||||||
|
property string fontColorActive: MoneroComponents.Style.blackTheme ? "white" : "white"
|
||||||
|
property string fontColorInActive: MoneroComponents.Style.blackTheme ? "white" : MoneroComponents.Style.dimmedFontColor
|
||||||
|
property int fontSize: 15
|
||||||
|
property bool fontBold: true
|
||||||
|
property var fontFamily: MoneroComponents.Style.fontRegular.name
|
||||||
|
property string borderColor: MoneroComponents.Style.blackTheme ? "#808080" : "#B9B9B9"
|
||||||
|
property int textMargin: {
|
||||||
|
// left-right margins for a given cell
|
||||||
|
if(appWindow.width < 890){
|
||||||
|
return 32;
|
||||||
|
} else {
|
||||||
|
return 64;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
// navbar left side border
|
||||||
|
id: navBarLeft
|
||||||
|
Layout.preferredWidth: 2
|
||||||
|
Layout.preferredHeight: 32
|
||||||
|
color: "transparent"
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
width: 1
|
||||||
|
height: parent.height - 2
|
||||||
|
color: grid.borderColor
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.right: parent.right
|
||||||
|
width: 1
|
||||||
|
spacing: 0
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
Layout.preferredHeight: 1
|
||||||
|
Layout.preferredWidth: 1
|
||||||
|
color: grid.borderColor
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
Layout.fillHeight: true
|
||||||
|
width: 1
|
||||||
|
color: items.length > 0 && items[0].active ? grid.borderColor : "transparent";
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
color: grid.borderColor
|
||||||
|
Layout.preferredHeight: 1
|
||||||
|
Layout.preferredWidth: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
model: items.length
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
spacing: 0
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
Layout.preferredWidth: 1
|
||||||
|
Layout.preferredHeight: 32
|
||||||
|
color: grid.borderColor
|
||||||
|
visible: index > 0 && items[index - 1].visible
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
Layout.minimumWidth: 72
|
||||||
|
Layout.preferredHeight: 32
|
||||||
|
Layout.fillWidth: true
|
||||||
|
spacing: 0
|
||||||
|
visible: items[index].visible
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
color: grid.borderColor
|
||||||
|
Layout.preferredHeight: 1
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
Layout.minimumHeight: 30
|
||||||
|
color: items[index].active ? grid.borderColor : "transparent"
|
||||||
|
height: children[0].height
|
||||||
|
width: children[0].width
|
||||||
|
|
||||||
|
MoneroComponents.TextPlain {
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
font.family: grid.fontFamily
|
||||||
|
font.pixelSize: grid.fontSize
|
||||||
|
font.bold: grid.fontBold
|
||||||
|
leftPadding: grid.textMargin / 2
|
||||||
|
rightPadding: grid.textMargin / 2
|
||||||
|
text: items[index].text
|
||||||
|
color: items[index].active ? grid.fontColorActive : grid.fontColorInActive
|
||||||
|
themeTransition: false
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
|
||||||
|
onClicked: items[index].selected()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
color: grid.borderColor
|
||||||
|
Layout.preferredHeight: 1
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
// navbar right side border
|
||||||
|
id: navBarRight
|
||||||
|
Layout.preferredWidth: 2
|
||||||
|
Layout.preferredHeight: 32
|
||||||
|
color: "transparent"
|
||||||
|
rotation: 180
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
width: 1
|
||||||
|
height: parent.height - 2
|
||||||
|
color: grid.borderColor
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.right: parent.right
|
||||||
|
width: 1
|
||||||
|
spacing: 0
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
Layout.preferredHeight: 1
|
||||||
|
Layout.preferredWidth: 1
|
||||||
|
color: grid.borderColor
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
Layout.fillHeight: true
|
||||||
|
width: 1
|
||||||
|
color: items.length > 0 && items[items.length - 1].active ? grid.borderColor : "transparent"
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
color: grid.borderColor
|
||||||
|
Layout.preferredHeight: 1
|
||||||
|
Layout.preferredWidth: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
37
components/NavbarItem.qml
Normal file
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()
|
||||||
|
}
|
||||||
@@ -39,6 +39,15 @@ Rectangle {
|
|||||||
property var connected: Wallet.ConnectionStatus_Disconnected
|
property var connected: Wallet.ConnectionStatus_Disconnected
|
||||||
|
|
||||||
function getConnectionStatusString(status) {
|
function getConnectionStatusString(status) {
|
||||||
|
switch (appWindow.daemonStartStopInProgress)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
return qsTr("Starting the node");
|
||||||
|
case 2:
|
||||||
|
return qsTr("Stopping the node");
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case Wallet.ConnectionStatus_Connected:
|
case Wallet.ConnectionStatus_Connected:
|
||||||
if (!appWindow.daemonSynced)
|
if (!appWindow.daemonSynced)
|
||||||
|
|||||||
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 int labelFontSize: 14
|
||||||
|
|
||||||
property string lineEditBackgroundColor: "transparent"
|
property string lineEditBackgroundColor: "transparent"
|
||||||
property string lineEditBorderColor: MoneroComponents.Style.inputBorderColorInActive
|
|
||||||
property string lineEditFontColor: MoneroComponents.Style.defaultFontColor
|
property string lineEditFontColor: MoneroComponents.Style.defaultFontColor
|
||||||
property bool lineEditFontBold: false
|
property bool lineEditFontBold: false
|
||||||
property int lineEditFontSize: 15
|
property int lineEditFontSize: 15
|
||||||
@@ -67,6 +66,8 @@ GridLayout {
|
|||||||
signal editingFinished()
|
signal editingFinished()
|
||||||
signal textChanged()
|
signal textChanged()
|
||||||
|
|
||||||
|
onActiveFocusChanged: activeFocus && daemonAddr.forceActiveFocus()
|
||||||
|
|
||||||
function isValid() {
|
function isValid() {
|
||||||
return daemonAddr.text.trim().length > 0 && daemonPort.acceptableInput
|
return daemonAddr.text.trim().length > 0 && daemonPort.acceptableInput
|
||||||
}
|
}
|
||||||
@@ -92,7 +93,6 @@ GridLayout {
|
|||||||
placeholderColor: root.placeholderColor
|
placeholderColor: root.placeholderColor
|
||||||
placeholderOpacity: root.placeholderOpacity
|
placeholderOpacity: root.placeholderOpacity
|
||||||
labelFontSize: root.labelFontSize
|
labelFontSize: root.labelFontSize
|
||||||
borderColor: lineEditBorderColor
|
|
||||||
backgroundColor: lineEditBackgroundColor
|
backgroundColor: lineEditBackgroundColor
|
||||||
fontColor: lineEditFontColor
|
fontColor: lineEditFontColor
|
||||||
fontBold: lineEditFontBold
|
fontBold: lineEditFontBold
|
||||||
@@ -115,7 +115,6 @@ GridLayout {
|
|||||||
placeholderColor: root.placeholderColor
|
placeholderColor: root.placeholderColor
|
||||||
placeholderOpacity: root.placeholderOpacity
|
placeholderOpacity: root.placeholderOpacity
|
||||||
labelFontSize: root.labelFontSize
|
labelFontSize: root.labelFontSize
|
||||||
borderColor: lineEditBorderColor
|
|
||||||
backgroundColor: lineEditBackgroundColor
|
backgroundColor: lineEditBackgroundColor
|
||||||
fontColor: lineEditFontColor
|
fontColor: lineEditFontColor
|
||||||
fontBold: lineEditFontBold
|
fontBold: lineEditFontBold
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ Item {
|
|||||||
id: buttonRect
|
id: buttonRect
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
radius: 3
|
radius: 3
|
||||||
border.width: parent.focus ? 1 : 0
|
border.width: parent.focus && parent.enabled ? 1 : 0
|
||||||
|
|
||||||
state: button.enabled ? "active" : "disabled"
|
state: button.enabled ? "active" : "disabled"
|
||||||
Component.onCompleted: state = state
|
Component.onCompleted: state = state
|
||||||
@@ -76,7 +76,7 @@ Item {
|
|||||||
states: [
|
states: [
|
||||||
State {
|
State {
|
||||||
name: "hover"
|
name: "hover"
|
||||||
when: buttonArea.containsMouse || button.focus
|
when: button.enabled && (buttonArea.containsMouse || button.focus)
|
||||||
PropertyChanges {
|
PropertyChanges {
|
||||||
target: buttonRect
|
target: buttonRect
|
||||||
color: primary
|
color: primary
|
||||||
|
|||||||
@@ -45,20 +45,11 @@ Rectangle {
|
|||||||
radius: 10
|
radius: 10
|
||||||
border.color: MoneroComponents.Style.blackTheme ? Qt.rgba(255, 255, 255, 0.25) : Qt.rgba(0, 0, 0, 0.25)
|
border.color: MoneroComponents.Style.blackTheme ? Qt.rgba(255, 255, 255, 0.25) : Qt.rgba(0, 0, 0, 0.25)
|
||||||
border.width: 1
|
border.width: 1
|
||||||
focus: true
|
|
||||||
Keys.enabled: true
|
Keys.enabled: true
|
||||||
Keys.onEscapePressed: {
|
Keys.onEscapePressed: {
|
||||||
root.close()
|
root.close()
|
||||||
root.rejected()
|
root.rejected()
|
||||||
}
|
}
|
||||||
Keys.onEnterPressed: {
|
|
||||||
root.close()
|
|
||||||
root.accepted()
|
|
||||||
}
|
|
||||||
Keys.onReturnPressed: {
|
|
||||||
root.close()
|
|
||||||
root.accepted()
|
|
||||||
}
|
|
||||||
KeyNavigation.tab: doneButton
|
KeyNavigation.tab: doneButton
|
||||||
|
|
||||||
Clipboard { id: clipboard }
|
Clipboard { id: clipboard }
|
||||||
@@ -72,7 +63,6 @@ Rectangle {
|
|||||||
function open(txid) {
|
function open(txid) {
|
||||||
root.transactionID = txid;
|
root.transactionID = txid;
|
||||||
root.visible = true;
|
root.visible = true;
|
||||||
root.forceActiveFocus();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function close() {
|
function close() {
|
||||||
@@ -156,13 +146,6 @@ Rectangle {
|
|||||||
text: qsTr("Open folder") + translationManager.emptyString;
|
text: qsTr("Open folder") + translationManager.emptyString;
|
||||||
width: 200
|
width: 200
|
||||||
KeyNavigation.tab: doneButton
|
KeyNavigation.tab: doneButton
|
||||||
Keys.enabled: openFolderButton.visible
|
|
||||||
Keys.onReturnPressed: openFolderButton.onClicked
|
|
||||||
Keys.onEnterPressed: openFolderButton.onClicked
|
|
||||||
Keys.onEscapePressed: {
|
|
||||||
root.close()
|
|
||||||
root.rejected()
|
|
||||||
}
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
oshelper.openContainingFolder(walletManager.urlToLocalPath(saveTxDialog.fileUrl))
|
oshelper.openContainingFolder(walletManager.urlToLocalPath(saveTxDialog.fileUrl))
|
||||||
}
|
}
|
||||||
@@ -172,15 +155,8 @@ Rectangle {
|
|||||||
id: doneButton
|
id: doneButton
|
||||||
text: qsTr("Done") + translationManager.emptyString;
|
text: qsTr("Done") + translationManager.emptyString;
|
||||||
width: 200
|
width: 200
|
||||||
focus: true
|
focus: root.visible
|
||||||
KeyNavigation.tab: openFolderButton
|
KeyNavigation.tab: openFolderButton
|
||||||
Keys.enabled: doneButton.visible
|
|
||||||
Keys.onReturnPressed: doneButton.onClicked
|
|
||||||
Keys.onEnterPressed: doneButton.onClicked
|
|
||||||
Keys.onEscapePressed: {
|
|
||||||
root.close()
|
|
||||||
root.rejected()
|
|
||||||
}
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
root.close()
|
root.close()
|
||||||
root.accepted()
|
root.accepted()
|
||||||
|
|||||||
440
components/TxConfirmationDialog.qml
Normal file
440
components/TxConfirmationDialog.qml
Normal file
@@ -0,0 +1,440 @@
|
|||||||
|
// Copyright (c) 2014-2020, The Monero Project
|
||||||
|
//
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
// permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
// conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
|
// of conditions and the following disclaimer in the documentation and/or other
|
||||||
|
// materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||||
|
// used to endorse or promote products derived from this software without specific
|
||||||
|
// prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||||
|
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||||
|
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||||
|
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
import QtQuick 2.9
|
||||||
|
import QtQuick.Controls 1.4 as QtQuickControls1
|
||||||
|
import QtQuick.Controls 2.2
|
||||||
|
import QtQuick.Layouts 1.1
|
||||||
|
|
||||||
|
import "../components" as MoneroComponents
|
||||||
|
import FontAwesome 1.0
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property int margins: 25
|
||||||
|
|
||||||
|
x: parent.width/2 - root.width/2
|
||||||
|
y: parent.height/2 - root.height/2
|
||||||
|
// TODO: implement without hardcoding sizes
|
||||||
|
width: 590
|
||||||
|
height: layout.height + layout.anchors.margins * 2
|
||||||
|
color: MoneroComponents.Style.blackTheme ? "black" : "white"
|
||||||
|
visible: false
|
||||||
|
radius: 10
|
||||||
|
border.color: MoneroComponents.Style.blackTheme ? Qt.rgba(255, 255, 255, 0.25) : Qt.rgba(0, 0, 0, 0.25)
|
||||||
|
border.width: 1
|
||||||
|
Keys.enabled: true
|
||||||
|
Keys.onEscapePressed: {
|
||||||
|
root.close()
|
||||||
|
root.clearFields()
|
||||||
|
root.rejected()
|
||||||
|
}
|
||||||
|
KeyNavigation.tab: confirmButton
|
||||||
|
|
||||||
|
property var recipients: []
|
||||||
|
property var transactionAmount: ""
|
||||||
|
property var transactionDescription: ""
|
||||||
|
property var transactionFee: ""
|
||||||
|
property var transactionPriority: ""
|
||||||
|
property bool sweepUnmixable: false
|
||||||
|
property alias errorText: errorText
|
||||||
|
property alias confirmButton: confirmButton
|
||||||
|
property alias backButton: backButton
|
||||||
|
property alias bottomText: bottomText
|
||||||
|
property alias bottomTextAnimation: bottomTextAnimation
|
||||||
|
|
||||||
|
state: "default"
|
||||||
|
states: [
|
||||||
|
State {
|
||||||
|
// waiting for user action, show tx details + back and confirm buttons
|
||||||
|
name: "default";
|
||||||
|
when: errorText.text == "" && bottomText.text == ""
|
||||||
|
PropertyChanges { target: errorText; visible: false }
|
||||||
|
PropertyChanges { target: txAmountText; visible: root.transactionAmount !== "(all)" || (root.transactionAmount === "(all)" && currentWallet.isHwBacked() === true) }
|
||||||
|
PropertyChanges { target: txAmountBusyIndicator; visible: !txAmountText.visible }
|
||||||
|
PropertyChanges { target: txFiatAmountText; visible: txAmountText.visible && persistentSettings.fiatPriceEnabled && root.transactionAmount !== "(all)" }
|
||||||
|
PropertyChanges { target: txDetails; visible: true }
|
||||||
|
PropertyChanges { target: bottom; visible: true }
|
||||||
|
PropertyChanges { target: bottomMessage; visible: false }
|
||||||
|
PropertyChanges { target: buttons; visible: true }
|
||||||
|
PropertyChanges { target: backButton; visible: true; primary: false }
|
||||||
|
PropertyChanges { target: confirmButton; visible: true; focus: true }
|
||||||
|
}, State {
|
||||||
|
// error message being displayed, show only back button
|
||||||
|
name: "error";
|
||||||
|
when: errorText.text !== ""
|
||||||
|
PropertyChanges { target: dialogTitle; text: "Error" }
|
||||||
|
PropertyChanges { target: errorText; visible: true }
|
||||||
|
PropertyChanges { target: txAmountText; visible: false }
|
||||||
|
PropertyChanges { target: txAmountBusyIndicator; visible: false }
|
||||||
|
PropertyChanges { target: txFiatAmountText; visible: false }
|
||||||
|
PropertyChanges { target: txDetails; visible: false }
|
||||||
|
PropertyChanges { target: bottom; visible: true }
|
||||||
|
PropertyChanges { target: bottomMessage; visible: false }
|
||||||
|
PropertyChanges { target: buttons; visible: true }
|
||||||
|
PropertyChanges { target: backButton; visible: true; primary: true; focus: true }
|
||||||
|
PropertyChanges { target: confirmButton; visible: false }
|
||||||
|
}, State {
|
||||||
|
// creating or sending transaction, show tx details and don't show any button
|
||||||
|
name: "bottomText";
|
||||||
|
when: errorText.text == "" && bottomText.text !== ""
|
||||||
|
PropertyChanges { target: errorText; visible: false }
|
||||||
|
PropertyChanges { target: txAmountText; visible: root.transactionAmount !== "(all)" || (root.transactionAmount === "(all)" && currentWallet.isHwBacked() === true) }
|
||||||
|
PropertyChanges { target: txAmountBusyIndicator; visible: !txAmountText.visible }
|
||||||
|
PropertyChanges { target: txFiatAmountText; visible: txAmountText.visible && persistentSettings.fiatPriceEnabled && root.transactionAmount !== "(all)" }
|
||||||
|
PropertyChanges { target: txDetails; visible: true }
|
||||||
|
PropertyChanges { target: bottom; visible: true }
|
||||||
|
PropertyChanges { target: bottomMessage; visible: true }
|
||||||
|
PropertyChanges { target: buttons; visible: false }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
// same signals as Dialog has
|
||||||
|
signal accepted()
|
||||||
|
signal rejected()
|
||||||
|
|
||||||
|
function open() {
|
||||||
|
root.visible = true;
|
||||||
|
|
||||||
|
//clean previous error message
|
||||||
|
errorText.text = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
function close() {
|
||||||
|
root.visible = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearFields() {
|
||||||
|
root.recipients = [];
|
||||||
|
root.transactionAmount = "";
|
||||||
|
root.transactionDescription = "";
|
||||||
|
root.transactionFee = "";
|
||||||
|
root.transactionPriority = "";
|
||||||
|
root.sweepUnmixable = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function showFiatConversion(valueXMR) {
|
||||||
|
const fiatFee = fiatApiConvertToFiat(valueXMR);
|
||||||
|
return "%1 %2".arg(fiatFee < 0.01 ? "<0.01" : "~" + fiatFee).arg(fiatApiCurrencySymbol());
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
id: layout
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.margins: parent.margins
|
||||||
|
spacing: 10
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
Layout.topMargin: 10
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
MoneroComponents.Label {
|
||||||
|
id: dialogTitle
|
||||||
|
Layout.fillWidth: true
|
||||||
|
fontSize: 18
|
||||||
|
fontFamily: "Arial"
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
text: {
|
||||||
|
if (appWindow.viewOnly) {
|
||||||
|
return qsTr("Create transaction file") + translationManager.emptyString;
|
||||||
|
} else if (root.sweepUnmixable) {
|
||||||
|
return qsTr("Sweep unmixable outputs") + translationManager.emptyString;
|
||||||
|
} else {
|
||||||
|
return qsTr("Confirm send") + translationManager.emptyString;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
id: errorText
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.fillHeight: true
|
||||||
|
color: MoneroComponents.Style.defaultFontColor
|
||||||
|
wrapMode: Text.Wrap
|
||||||
|
font.pixelSize: 15
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
spacing: 0
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.preferredHeight: 71
|
||||||
|
|
||||||
|
QtQuickControls1.BusyIndicator {
|
||||||
|
id: txAmountBusyIndicator
|
||||||
|
Layout.fillHeight: true
|
||||||
|
Layout.fillWidth: true
|
||||||
|
running: root.transactionAmount == "(all)"
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
id: txAmountText
|
||||||
|
Layout.fillWidth: true
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
font.pixelSize: root.transactionAmount == "(all)" && currentWallet.isHwBacked() === true ? 32 : 42
|
||||||
|
color: MoneroComponents.Style.defaultFontColor
|
||||||
|
text: {
|
||||||
|
if (root.transactionAmount == "(all)" && currentWallet.isHwBacked() === true) {
|
||||||
|
return qsTr("All unlocked balance") + translationManager.emptyString;
|
||||||
|
} else {
|
||||||
|
return root.transactionAmount + " XMR " + translationManager.emptyString;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
id: txFiatAmountText
|
||||||
|
Layout.fillWidth: true
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
font.pixelSize: 20
|
||||||
|
color: MoneroComponents.Style.buttonSecondaryTextColor
|
||||||
|
text: showFiatConversion(transactionAmount) + translationManager.emptyString
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GridLayout {
|
||||||
|
columns: 2
|
||||||
|
id: txDetails
|
||||||
|
Layout.fillWidth: true
|
||||||
|
columnSpacing: 15
|
||||||
|
rowSpacing: 16
|
||||||
|
|
||||||
|
Text {
|
||||||
|
color: MoneroComponents.Style.dimmedFontColor
|
||||||
|
text: qsTr("From") + ":" + translationManager.emptyString
|
||||||
|
font.pixelSize: 15
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
spacing: 16
|
||||||
|
|
||||||
|
Text {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
font.pixelSize: 15
|
||||||
|
color: MoneroComponents.Style.defaultFontColor
|
||||||
|
text: {
|
||||||
|
if (currentWallet) {
|
||||||
|
var walletTitle = function() {
|
||||||
|
if (currentWallet.isLedger()) {
|
||||||
|
return "Ledger";
|
||||||
|
} else if (currentWallet.isTrezor()) {
|
||||||
|
return "Trezor";
|
||||||
|
} else {
|
||||||
|
return qsTr("My wallet");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var walletName = appWindow.walletName;
|
||||||
|
if (appWindow.currentWallet.numSubaddressAccounts() > 1) {
|
||||||
|
var currentSubaddressAccount = currentWallet.currentSubaddressAccount;
|
||||||
|
var currentAccountLabel = currentWallet.getSubaddressLabel(currentWallet.currentSubaddressAccount, 0);
|
||||||
|
return walletTitle() + " (" + walletName + ")" + "<br>" + qsTr("Account #") + currentSubaddressAccount + (currentAccountLabel !== "" ? " (" + currentAccountLabel + ")" : "") + translationManager.emptyString;
|
||||||
|
} else {
|
||||||
|
return walletTitle() + " (" + walletName + ")" + translationManager.emptyString;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
font.pixelSize: 15
|
||||||
|
color: MoneroComponents.Style.dimmedFontColor
|
||||||
|
text: qsTr("To") + ":" + translationManager.emptyString
|
||||||
|
}
|
||||||
|
|
||||||
|
Flickable {
|
||||||
|
id: flickable
|
||||||
|
property int linesInMultipleRecipientsMode: 7
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.preferredHeight: recipients.length > 1
|
||||||
|
? linesInMultipleRecipientsMode * (recipientsArea.contentHeight / recipientsArea.lineCount)
|
||||||
|
: recipientsArea.contentHeight
|
||||||
|
boundsBehavior: isMac ? Flickable.DragAndOvershootBounds : Flickable.StopAtBounds
|
||||||
|
clip: true
|
||||||
|
|
||||||
|
TextArea.flickable: TextArea {
|
||||||
|
id : recipientsArea
|
||||||
|
color: MoneroComponents.Style.defaultFontColor
|
||||||
|
font.family: MoneroComponents.Style.fontMonoRegular.name
|
||||||
|
font.pixelSize: 14
|
||||||
|
topPadding: 0
|
||||||
|
bottomPadding: 0
|
||||||
|
leftPadding: 0
|
||||||
|
textMargin: 0
|
||||||
|
readOnly: true
|
||||||
|
selectByKeyboard: true
|
||||||
|
selectByMouse: true
|
||||||
|
selectionColor: MoneroComponents.Style.textSelectionColor
|
||||||
|
textFormat: TextEdit.RichText
|
||||||
|
wrapMode: TextEdit.Wrap
|
||||||
|
text: {
|
||||||
|
return recipients.map(function (recipient, index) {
|
||||||
|
var addressBookName = null;
|
||||||
|
if (currentWallet) {
|
||||||
|
addressBookName = currentWallet.addressBook.getDescription(recipient.address);
|
||||||
|
}
|
||||||
|
var title;
|
||||||
|
if (addressBookName) {
|
||||||
|
title = FontAwesome.addressBook + " " + addressBookName;
|
||||||
|
} else {
|
||||||
|
title = qsTr("Monero address") + translationManager.emptyString;
|
||||||
|
}
|
||||||
|
if (recipients.length > 1) {
|
||||||
|
title = "%1. %2 - %3 XMR".arg(index + 1).arg(title).arg(recipient.amount);
|
||||||
|
if (persistentSettings.fiatPriceEnabled) {
|
||||||
|
title += " (%1)".arg(showFiatConversion(recipient.amount));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const spacedaddress = recipient.address.match(/.{1,4}/g).join(' ');
|
||||||
|
return title + "<br>" + spacedaddress;
|
||||||
|
}).join("<br><br>");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ScrollBar.vertical: ScrollBar {
|
||||||
|
policy: recipientsArea.contentHeight > flickable.height ? ScrollBar.AlwaysOn : ScrollBar.AlwaysOff
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
color: MoneroComponents.Style.dimmedFontColor
|
||||||
|
text: qsTr("Fee") + ":" + translationManager.emptyString
|
||||||
|
font.pixelSize: 15
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
spacing: 16
|
||||||
|
|
||||||
|
Text {
|
||||||
|
color: MoneroComponents.Style.defaultFontColor
|
||||||
|
font.pixelSize: 15
|
||||||
|
text: {
|
||||||
|
if (currentWallet) {
|
||||||
|
if (!root.transactionFee) {
|
||||||
|
if (currentWallet.isHwBacked() === true) {
|
||||||
|
return qsTr("See on device") + translationManager.emptyString;
|
||||||
|
} else {
|
||||||
|
return qsTr("Calculating fee") + "..." + translationManager.emptyString;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return root.transactionFee + " XMR"
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.leftMargin: 8
|
||||||
|
color: MoneroComponents.Style.buttonSecondaryTextColor
|
||||||
|
visible: persistentSettings.fiatPriceEnabled && root.transactionFee
|
||||||
|
font.pixelSize: 15
|
||||||
|
text: showFiatConversion(root.transactionFee)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
id: bottom
|
||||||
|
Layout.alignment: Qt.AlignBottom | Qt.AlignHCenter
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
id: bottomMessage
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.preferredHeight: 50
|
||||||
|
|
||||||
|
QtQuickControls1.BusyIndicator {
|
||||||
|
visible: !bottomTextAnimation.running
|
||||||
|
running: !bottomTextAnimation.running
|
||||||
|
scale: .5
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
id: bottomText
|
||||||
|
color: MoneroComponents.Style.defaultFontColor
|
||||||
|
text: ""
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
wrapMode: Text.Wrap
|
||||||
|
font.pixelSize: 17
|
||||||
|
opacity: 1
|
||||||
|
|
||||||
|
SequentialAnimation{
|
||||||
|
id:bottomTextAnimation
|
||||||
|
running: false
|
||||||
|
loops: Animation.Infinite
|
||||||
|
alwaysRunToEnd: true
|
||||||
|
NumberAnimation { target: bottomText; property: "opacity"; to: 0; duration: 500}
|
||||||
|
NumberAnimation { target: bottomText; property: "opacity"; to: 1; duration: 500}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
id: buttons
|
||||||
|
spacing: 70
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.preferredHeight: 50
|
||||||
|
|
||||||
|
MoneroComponents.StandardButton {
|
||||||
|
id: backButton
|
||||||
|
text: qsTr("Back") + translationManager.emptyString;
|
||||||
|
width: 200
|
||||||
|
primary: false
|
||||||
|
KeyNavigation.tab: confirmButton
|
||||||
|
onClicked: {
|
||||||
|
root.close()
|
||||||
|
root.clearFields()
|
||||||
|
root.rejected()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MoneroComponents.StandardButton {
|
||||||
|
id: confirmButton
|
||||||
|
text: qsTr("Confirm") + translationManager.emptyString;
|
||||||
|
rightIcon: "qrc:///images/rightArrow.png"
|
||||||
|
width: 200
|
||||||
|
KeyNavigation.tab: backButton
|
||||||
|
onClicked: {
|
||||||
|
root.close()
|
||||||
|
root.accepted()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
android-no-sdk {
|
|
||||||
target.path = /data/user/qt
|
|
||||||
export(target.path)
|
|
||||||
INSTALLS += target
|
|
||||||
} else:android {
|
|
||||||
x86 {
|
|
||||||
target.path = /libs/x86
|
|
||||||
} else: armeabi-v7a {
|
|
||||||
target.path = /libs/armeabi-v7a
|
|
||||||
} else {
|
|
||||||
target.path = /libs/armeabi
|
|
||||||
}
|
|
||||||
export(target.path)
|
|
||||||
INSTALLS += target
|
|
||||||
} else:unix {
|
|
||||||
isEmpty(target.path) {
|
|
||||||
qnx {
|
|
||||||
target.path = /tmp/$${TARGET}/bin
|
|
||||||
} else {
|
|
||||||
target.path = /opt/$${TARGET}/bin
|
|
||||||
}
|
|
||||||
export(target.path)
|
|
||||||
}
|
|
||||||
INSTALLS += target
|
|
||||||
}
|
|
||||||
|
|
||||||
export(INSTALLS)
|
|
||||||
7
external/CMakeLists.txt
vendored
Normal file
7
external/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
add_library(quirc STATIC
|
||||||
|
quirc/lib/decode.c
|
||||||
|
quirc/lib/identify.c
|
||||||
|
quirc/lib/quirc.c
|
||||||
|
quirc/lib/version_db.c
|
||||||
|
)
|
||||||
|
target_include_directories(quirc PUBLIC quirc/lib)
|
||||||
1
external/quirc
vendored
Submodule
1
external/quirc
vendored
Submodule
Submodule external/quirc added at 7e7ab596e4
@@ -403,6 +403,7 @@ Object {
|
|||||||
property string inbox : "\uf01c"
|
property string inbox : "\uf01c"
|
||||||
property string indent : "\uf03c"
|
property string indent : "\uf03c"
|
||||||
property string industry : "\uf275"
|
property string industry : "\uf275"
|
||||||
|
property string infinity : "\uf534"
|
||||||
property string info : "\uf129"
|
property string info : "\uf129"
|
||||||
property string infoCircle : "\uf05a"
|
property string infoCircle : "\uf05a"
|
||||||
property string inr : "\uf156"
|
property string inr : "\uf156"
|
||||||
|
|||||||
@@ -1,286 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
MONERO_URL=https://github.com/monero-project/monero.git
|
|
||||||
MONERO_BRANCH=master
|
|
||||||
|
|
||||||
pushd $(pwd)
|
|
||||||
ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|
||||||
|
|
||||||
source $ROOT_DIR/utils.sh
|
|
||||||
|
|
||||||
INSTALL_DIR=$ROOT_DIR/wallet
|
|
||||||
MONERO_DIR=$ROOT_DIR/monero
|
|
||||||
BUILD_LIBWALLET=false
|
|
||||||
|
|
||||||
# init and update monero submodule
|
|
||||||
if [ ! -d $MONERO_DIR/src ]; then
|
|
||||||
git submodule init monero
|
|
||||||
fi
|
|
||||||
git submodule update --remote
|
|
||||||
git -C $MONERO_DIR fetch
|
|
||||||
git -C $MONERO_DIR checkout v0.17.1.0
|
|
||||||
|
|
||||||
# get monero core tag
|
|
||||||
pushd $MONERO_DIR
|
|
||||||
get_tag
|
|
||||||
popd
|
|
||||||
# create local monero branch
|
|
||||||
git -C $MONERO_DIR checkout -B $VERSIONTAG
|
|
||||||
|
|
||||||
# Merge monero PR dependencies
|
|
||||||
|
|
||||||
# Workaround for git username requirements
|
|
||||||
# Save current user settings and revert back when we are done with merging PR's
|
|
||||||
OLD_GIT_USER=$(git -C $MONERO_DIR config --local user.name)
|
|
||||||
OLD_GIT_EMAIL=$(git -C $MONERO_DIR config --local user.email)
|
|
||||||
git -C $MONERO_DIR config user.name "Monero GUI"
|
|
||||||
git -C $MONERO_DIR config user.email "gui@monero.local"
|
|
||||||
# check for PR requirements in most recent commit message (i.e requires #xxxx)
|
|
||||||
for PR in $(git log --format=%B -n 1 | grep -io "requires #[0-9]*" | sed 's/[^0-9]*//g'); do
|
|
||||||
echo "Merging monero push request #$PR"
|
|
||||||
# fetch pull request and merge
|
|
||||||
git -C $MONERO_DIR fetch origin pull/$PR/head:PR-$PR
|
|
||||||
git -C $MONERO_DIR merge --quiet PR-$PR -m "Merge monero PR #$PR"
|
|
||||||
BUILD_LIBWALLET=true
|
|
||||||
done
|
|
||||||
|
|
||||||
# revert back to old git config
|
|
||||||
$(git -C $MONERO_DIR config user.name "$OLD_GIT_USER")
|
|
||||||
$(git -C $MONERO_DIR config user.email "$OLD_GIT_EMAIL")
|
|
||||||
|
|
||||||
git -C $MONERO_DIR submodule init
|
|
||||||
git -C $MONERO_DIR submodule update
|
|
||||||
|
|
||||||
# Build libwallet if it doesnt exist
|
|
||||||
if [ ! -f $MONERO_DIR/lib/libwallet_merged.a ]; then
|
|
||||||
echo "libwallet_merged.a not found - Building libwallet"
|
|
||||||
BUILD_LIBWALLET=true
|
|
||||||
# Build libwallet if no previous version file exists
|
|
||||||
elif [ ! -f $MONERO_DIR/version.sh ]; then
|
|
||||||
echo "monero/version.h not found - Building libwallet"
|
|
||||||
BUILD_LIBWALLET=true
|
|
||||||
## Compare previously built version with submodule + merged PR's version.
|
|
||||||
else
|
|
||||||
source $MONERO_DIR/version.sh
|
|
||||||
# compare submodule version with latest build
|
|
||||||
pushd "$MONERO_DIR"
|
|
||||||
get_tag
|
|
||||||
popd
|
|
||||||
echo "latest libwallet version: $GUI_MONERO_VERSION"
|
|
||||||
echo "Installed libwallet version: $VERSIONTAG"
|
|
||||||
# check if recent
|
|
||||||
if [ "$VERSIONTAG" != "$GUI_MONERO_VERSION" ]; then
|
|
||||||
echo "Building new libwallet version $GUI_MONERO_VERSION"
|
|
||||||
BUILD_LIBWALLET=true
|
|
||||||
else
|
|
||||||
echo "latest libwallet ($GUI_MONERO_VERSION) is already built. Remove monero/lib/libwallet_merged.a to force rebuild"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$BUILD_LIBWALLET" != true ]; then
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "GUI_MONERO_VERSION=\"$VERSIONTAG\"" > $MONERO_DIR/version.sh
|
|
||||||
|
|
||||||
## Continue building libwallet
|
|
||||||
|
|
||||||
# default build type
|
|
||||||
BUILD_TYPE=$1
|
|
||||||
if [ -z $BUILD_TYPE ]; then
|
|
||||||
BUILD_TYPE=release
|
|
||||||
fi
|
|
||||||
|
|
||||||
BUILD_TREZOR_FLAGS=" -DUSE_DEVICE_TREZOR=ON"
|
|
||||||
if [ "$BUILD_TREZOR" == false ]; then
|
|
||||||
BUILD_TREZOR_FLAGS=" -DUSE_DEVICE_TREZOR=OFF"
|
|
||||||
fi
|
|
||||||
BUILD_TREZOR_FLAGS=" -DUSE_DEVICE_TREZOR_UDP_RELEASE=ON ${BUILD_TREZOR_FLAGS}"
|
|
||||||
|
|
||||||
STATIC=false
|
|
||||||
ANDROID=false
|
|
||||||
if [ "$BUILD_TYPE" == "release" ]; then
|
|
||||||
echo "Building libwallet release"
|
|
||||||
CMAKE_BUILD_TYPE=Release
|
|
||||||
elif [ "$BUILD_TYPE" == "release-static" ]; then
|
|
||||||
echo "Building libwallet release-static"
|
|
||||||
CMAKE_BUILD_TYPE=Release
|
|
||||||
STATIC=true
|
|
||||||
elif [ "$BUILD_TYPE" == "release-android" ]; then
|
|
||||||
echo "Building libwallet release-static for ANDROID"
|
|
||||||
CMAKE_BUILD_TYPE=Release
|
|
||||||
STATIC=true
|
|
||||||
ANDROID=true
|
|
||||||
elif [ "$BUILD_TYPE" == "debug-android" ]; then
|
|
||||||
echo "Building libwallet debug-static for ANDROID"
|
|
||||||
CMAKE_BUILD_TYPE=Debug
|
|
||||||
STATIC=true
|
|
||||||
ANDROID=true
|
|
||||||
elif [ "$BUILD_TYPE" == "debug" ]; then
|
|
||||||
echo "Building libwallet debug"
|
|
||||||
CMAKE_BUILD_TYPE=Debug
|
|
||||||
STATIC=true
|
|
||||||
else
|
|
||||||
echo "Valid build types are release, release-static, release-android, debug-android and debug"
|
|
||||||
exit 1;
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
echo "cleaning up existing monero build dir, libs and includes"
|
|
||||||
rm -fr $MONERO_DIR/build
|
|
||||||
rm -fr $MONERO_DIR/lib
|
|
||||||
rm -fr $MONERO_DIR/include
|
|
||||||
rm -fr $MONERO_DIR/bin
|
|
||||||
|
|
||||||
|
|
||||||
mkdir -p $MONERO_DIR/build/$BUILD_TYPE
|
|
||||||
pushd $MONERO_DIR/build/$BUILD_TYPE
|
|
||||||
|
|
||||||
# reusing function from "utils.sh"
|
|
||||||
platform=$(get_platform)
|
|
||||||
# default make executable
|
|
||||||
make_exec="make"
|
|
||||||
|
|
||||||
if [ -z "$ARCH" ]; then
|
|
||||||
ARCH="native"
|
|
||||||
if [ "$platform" == "darwin" ]; then
|
|
||||||
if [ "$STATIC" == true ]; then
|
|
||||||
ARCH="x86-64"
|
|
||||||
fi
|
|
||||||
elif [ "$platform" == "linux64" ]; then
|
|
||||||
if [ "$ANDROID" == true ]; then
|
|
||||||
ARCH="armv7-a"
|
|
||||||
elif [ "$STATIC" == true ]; then
|
|
||||||
ARCH="x86-64"
|
|
||||||
fi
|
|
||||||
elif [ "$platform" == "linux32" ]; then
|
|
||||||
if [ "$STATIC" == true ]; then
|
|
||||||
ARCH="i686"
|
|
||||||
fi
|
|
||||||
elif [ "$platform" == "linuxarmv7" ]; then
|
|
||||||
ARCH="armv7-a"
|
|
||||||
elif [ "$platform" == "mingw32" ]; then
|
|
||||||
ARCH="i686"
|
|
||||||
elif [ "$platform" == "mingw64" ]; then
|
|
||||||
ARCH="x86-64"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Building for ARCH=$ARCH"
|
|
||||||
|
|
||||||
## OS X
|
|
||||||
if [ "$platform" == "darwin" ]; then
|
|
||||||
echo "Configuring build for MacOS.."
|
|
||||||
if [ "$STATIC" == true ]; then
|
|
||||||
cmake -D CMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE -D STATIC=ON -D ARCH="$ARCH" -D BUILD_64=ON -D BUILD_TAG="mac-x64" -D BUILD_GUI_DEPS=ON -D INSTALL_VENDORED_LIBUNBOUND=ON $BUILD_TREZOR_FLAGS -D CMAKE_INSTALL_PREFIX="$MONERO_DIR" ../..
|
|
||||||
else
|
|
||||||
cmake -D CMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE -D ARCH="$ARCH" -D BUILD_TAG="mac-x64" -D BUILD_GUI_DEPS=ON -D INSTALL_VENDORED_LIBUNBOUND=ON $BUILD_TREZOR_FLAGS -D CMAKE_INSTALL_PREFIX="$MONERO_DIR" ../..
|
|
||||||
fi
|
|
||||||
|
|
||||||
## LINUX 64
|
|
||||||
elif [ "$platform" == "linux64" ]; then
|
|
||||||
echo "Configuring build for Linux x64"
|
|
||||||
if [ "$ANDROID" == true ]; then
|
|
||||||
echo "Configuring build for Android on Linux host"
|
|
||||||
cmake -D CMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE -D STATIC=ON -D ARCH="$ARCH" -D ANDROID=true -D BUILD_GUI_DEPS=ON -D USE_LTO=OFF -D INSTALL_VENDORED_LIBUNBOUND=ON $BUILD_TREZOR_FLAGS -D CMAKE_INSTALL_PREFIX="$MONERO_DIR" ../..
|
|
||||||
elif [ "$STATIC" == true ]; then
|
|
||||||
cmake -D CMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE -D STATIC=ON -D ARCH="$ARCH" -D BUILD_64=ON -D BUILD_TAG="linux-x64" -D BUILD_GUI_DEPS=ON -D INSTALL_VENDORED_LIBUNBOUND=ON $BUILD_TREZOR_FLAGS -D CMAKE_INSTALL_PREFIX="$MONERO_DIR" ../..
|
|
||||||
else
|
|
||||||
cmake -D CMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE -D ARCH="$ARCH" -D BUILD_TAG="linux-x64" -D BUILD_GUI_DEPS=ON $BUILD_TREZOR_FLAGS -D CMAKE_INSTALL_PREFIX="$MONERO_DIR" ../..
|
|
||||||
fi
|
|
||||||
|
|
||||||
## LINUX 32
|
|
||||||
elif [ "$platform" == "linux32" ]; then
|
|
||||||
echo "Configuring build for Linux i686"
|
|
||||||
if [ "$STATIC" == true ]; then
|
|
||||||
cmake -D CMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE -D STATIC=ON -D ARCH="$ARCH" -D BUILD_64=OFF -D BUILD_GUI_DEPS=ON -D INSTALL_VENDORED_LIBUNBOUND=ON $BUILD_TREZOR_FLAGS -D CMAKE_INSTALL_PREFIX="$MONERO_DIR" ../..
|
|
||||||
else
|
|
||||||
cmake -D CMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE -D ARCH="$ARCH" -D BUILD_GUI_DEPS=ON $BUILD_TREZOR_FLAGS -D CMAKE_INSTALL_PREFIX="$MONERO_DIR" ../..
|
|
||||||
fi
|
|
||||||
|
|
||||||
## LINUX ARMv7
|
|
||||||
elif [ "$platform" == "linuxarmv7" ]; then
|
|
||||||
echo "Configuring build for Linux armv7"
|
|
||||||
if [ "$STATIC" == true ]; then
|
|
||||||
cmake -D BUILD_TESTS=OFF -D ARCH="$ARCH" -D STATIC=ON -D BUILD_64=OFF -D BUILD_GUI_DEPS=ON $BUILD_TREZOR_FLAGS -D CMAKE_INSTALL_PREFIX="$MONERO_DIR" ../..
|
|
||||||
else
|
|
||||||
cmake -D BUILD_TESTS=OFF -D ARCH="$ARCH" -D BUILD_64=OFF -D BUILD_GUI_DEPS=ON $BUILD_TREZOR_FLAGS -D CMAKE_INSTALL_PREFIX="$MONERO_DIR" ../..
|
|
||||||
fi
|
|
||||||
|
|
||||||
## LINUX other
|
|
||||||
elif [ "$platform" == "linux" ]; then
|
|
||||||
echo "Configuring build for Linux general"
|
|
||||||
if [ "$STATIC" == true ]; then
|
|
||||||
cmake -D CMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE -D STATIC=ON -D ARCH="$ARCH" -D BUILD_GUI_DEPS=ON -D INSTALL_VENDORED_LIBUNBOUND=ON $BUILD_TREZOR_FLAGS -D CMAKE_INSTALL_PREFIX="$MONERO_DIR" ../..
|
|
||||||
else
|
|
||||||
cmake -D CMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE -D ARCH="$ARCH" -D BUILD_GUI_DEPS=ON $BUILD_TREZOR_FLAGS -D CMAKE_INSTALL_PREFIX="$MONERO_DIR" ../..
|
|
||||||
fi
|
|
||||||
|
|
||||||
## Windows 64
|
|
||||||
## Windows is always static to work outside msys2
|
|
||||||
elif [ "$platform" == "mingw64" ]; then
|
|
||||||
# Do something under Windows NT platform
|
|
||||||
echo "Configuring build for MINGW64.."
|
|
||||||
BOOST_ROOT=/mingw64/boost
|
|
||||||
cmake -D CMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE -D STATIC=ON -D BOOST_ROOT="$BOOST_ROOT" -D ARCH="$ARCH" -D BUILD_TAG="win-x64" -D BUILD_GUI_DEPS=ON -D INSTALL_VENDORED_LIBUNBOUND=ON $BUILD_TREZOR_FLAGS -D CMAKE_INSTALL_PREFIX="$MONERO_DIR" -G "MSYS Makefiles" -D CMAKE_TOOLCHAIN_FILE=../../cmake/64-bit-toolchain.cmake -D MSYS2_FOLDER=$(cd $MINGW_PREFIX/.. && pwd -W) ../..
|
|
||||||
|
|
||||||
## Windows 32
|
|
||||||
elif [ "$platform" == "mingw32" ]; then
|
|
||||||
# Do something under Windows NT platform
|
|
||||||
echo "Configuring build for MINGW32.."
|
|
||||||
BOOST_ROOT=/mingw32/boost
|
|
||||||
cmake -D CMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE -D STATIC=ON -D Boost_DEBUG=ON -D BOOST_ROOT="$BOOST_ROOT" -D ARCH="$ARCH" -D BUILD_64=OFF -D BUILD_GUI_DEPS=ON -D INSTALL_VENDORED_LIBUNBOUND=ON $BUILD_TREZOR_FLAGS -D CMAKE_INSTALL_PREFIX="$MONERO_DIR" -G "MSYS Makefiles" -D CMAKE_TOOLCHAIN_FILE=../../cmake/32-bit-toolchain.cmake -D MSYS2_FOLDER=$(cd $MINGW_PREFIX/.. && pwd -W) ../..
|
|
||||||
make_exec="mingw32-make"
|
|
||||||
else
|
|
||||||
echo "Unknown platform, configuring general build"
|
|
||||||
if [ "$STATIC" == true ]; then
|
|
||||||
cmake -D CMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE -D STATIC=ON -D ARCH="$ARCH" -D BUILD_GUI_DEPS=ON $BUILD_TREZOR_FLAGS -D CMAKE_INSTALL_PREFIX="$MONERO_DIR" ../..
|
|
||||||
else
|
|
||||||
cmake -D CMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE -D ARCH="$ARCH" -D BUILD_GUI_DEPS=ON $BUILD_TREZOR_FLAGS -D CMAKE_INSTALL_PREFIX="$MONERO_DIR" ../..
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# set CPU core count
|
|
||||||
# thanks to SO: http://stackoverflow.com/a/20283965/4118915
|
|
||||||
if test -z "$CPU_CORE_COUNT"; then
|
|
||||||
CPU_CORE_COUNT=$(grep -c ^processor /proc/cpuinfo 2>/dev/null || sysctl -n hw.ncpu)
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Build libwallet_merged
|
|
||||||
pushd $MONERO_DIR/build/$BUILD_TYPE/src/wallet
|
|
||||||
eval $make_exec version -C ../..
|
|
||||||
eval $make_exec -j$CPU_CORE_COUNT
|
|
||||||
eval $make_exec install -j$CPU_CORE_COUNT
|
|
||||||
popd
|
|
||||||
|
|
||||||
# Build monerod
|
|
||||||
# win32 need to build daemon manually with msys2 toolchain
|
|
||||||
if [ "$platform" != "mingw32" ] && [ "$ANDROID" != true ]; then
|
|
||||||
pushd $MONERO_DIR/build/$BUILD_TYPE/src/daemon
|
|
||||||
eval make -j$CPU_CORE_COUNT
|
|
||||||
eval make install -j$CPU_CORE_COUNT
|
|
||||||
popd
|
|
||||||
fi
|
|
||||||
|
|
||||||
# build install epee
|
|
||||||
eval make -C $MONERO_DIR/build/$BUILD_TYPE/contrib/epee all install
|
|
||||||
|
|
||||||
# install easylogging
|
|
||||||
eval make -C $MONERO_DIR/build/$BUILD_TYPE/external/easylogging++ all install
|
|
||||||
|
|
||||||
# install lmdb
|
|
||||||
eval make -C $MONERO_DIR/build/$BUILD_TYPE/external/db_drivers/liblmdb all install
|
|
||||||
|
|
||||||
# Install libunbound
|
|
||||||
if [ -d $MONERO_DIR/build/$BUILD_TYPE/external/unbound ]; then
|
|
||||||
echo "Installing libunbound..."
|
|
||||||
pushd $MONERO_DIR/build/$BUILD_TYPE/external/unbound
|
|
||||||
# no need to make, it was already built as dependency for libwallet
|
|
||||||
# make -j$CPU_CORE_COUNT
|
|
||||||
$make_exec install -j$CPU_CORE_COUNT
|
|
||||||
popd
|
|
||||||
fi
|
|
||||||
|
|
||||||
# install randomx
|
|
||||||
eval make -C $MONERO_DIR/build/$BUILD_TYPE/external/randomx all install
|
|
||||||
|
|
||||||
popd
|
|
||||||
@@ -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
|
; 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
|
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
|
; Mesa, open-source OpenGL implementation; part of "low-level graphics" support
|
||||||
Source: "bin\opengl32sw.dll"; DestDir: "{app}"; Flags: ignoreversion
|
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}\libhidapi-0.dll"
|
||||||
Type: files; Name: "{app}\libeay32.dll"
|
Type: files; Name: "{app}\libeay32.dll"
|
||||||
Type: files; Name: "{app}\ssleay32.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"
|
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>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
|
<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.
|
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 loose your
|
But do remember that the seed needed to re-create the wallet <b>is</b> critical, however: <b>Never lose your
|
||||||
seed!</b></p>
|
seed!</b></p>
|
||||||
|
|
||||||
<p>In the <i>Utilities</i> sub-folder there are several more icons that may help you to solve problems.
|
<p>In the <i>Utilities</i> sub-folder there are several more icons that may help you to solve problems.
|
||||||
|
|||||||
@@ -1,49 +0,0 @@
|
|||||||
#!/bin/bash -e
|
|
||||||
|
|
||||||
# 3 header files required by monero are missing from the IOS SDK. I copied them from iphoneSimulator SDK
|
|
||||||
# cd /Applications/XCode.app
|
|
||||||
# sudo cp ./Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/include/sys/vmmeter.h ./Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include/sys/
|
|
||||||
# sudo cp ./Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/include/netinet/udp_var.h ./Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include/netinet/
|
|
||||||
# sudo cp ./Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/include/netinet/ip_var.h ./Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include/netinet/
|
|
||||||
|
|
||||||
|
|
||||||
if [ -z $BUILD_TYPE ]; then
|
|
||||||
BUILD_TYPE=release
|
|
||||||
fi
|
|
||||||
|
|
||||||
ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|
||||||
if [ -z $BOOST_LIBRARYDIR ]; then
|
|
||||||
BOOST_LIBRARYDIR=${ROOT_DIR}/../ofxiOSBoost/build/ios/prefix/lib
|
|
||||||
fi
|
|
||||||
if [ -z $BOOST_INCLUDEDIR ]; then
|
|
||||||
BOOST_INCLUDEDIR=${ROOT_DIR}/../ofxiOSBoost/build/ios/prefix/include
|
|
||||||
fi
|
|
||||||
if [ -z $OPENSSL_INCLUDE_DIR ]; then
|
|
||||||
OPENSSL_INCLUDE_DIR=${ROOT_DIR}/../openssl/1.0.2j/include
|
|
||||||
fi
|
|
||||||
if [ -z $OPENSSL_ROOT_DIR ]; then
|
|
||||||
OPENSSL_ROOT_DIR=${ROOT_DIR}/../openssl/1.0.2j
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Building IOS armv7"
|
|
||||||
rm -r monero/build > /dev/null
|
|
||||||
mkdir -p monero/build/release
|
|
||||||
pushd monero/build/release
|
|
||||||
cmake -D IOS=ON -D ARCH=armv7 -D BOOST_LIBRARYDIR=${BOOST_INCLUDEDIR} -D BOOST_INCLUDEDIR=${BOOST_INCLUDEDIR} -D OPENSSL_INCLUDE_DIR=${OPENSSL_INCLUDE_DIR} -D OPENSSL_ROOT_DIR=${OPENSSL_ROOT_DIR} -D CMAKE_BUILD_TYPE=debug -D STATIC=ON -D BUILD_GUI_DEPS=ON -D INSTALL_VENDORED_LIBUNBOUND=ON -D CMAKE_INSTALL_PREFIX="/Users/jacob/crypto/monero-core/monero" ../..
|
|
||||||
make -j4 && make install
|
|
||||||
popd
|
|
||||||
echo "Building IOS arm64"
|
|
||||||
rm -r monero/build > /dev/null
|
|
||||||
mkdir -p monero/build/release
|
|
||||||
pushd monero/build/release
|
|
||||||
cmake -D IOS=ON -D ARCH=armv8-a -D BOOST_LIBRARYDIR=${BOOST_INCLUDEDIR} -D BOOST_INCLUDEDIR=${BOOST_INCLUDEDIR} -D OPENSSL_INCLUDE_DIR=${OPENSSL_INCLUDE_DIR} -D OPENSSL_ROOT_DIR=${OPENSSL_ROOT_DIR} -D CMAKE_BUILD_TYPE=debug -D STATIC=ON -D BUILD_GUI_DEPS=ON -D INSTALL_VENDORED_LIBUNBOUND=ON -D CMAKE_INSTALL_PREFIX="/Users/jacob/crypto/monero-core/monero" ../..
|
|
||||||
make -j4 && make install
|
|
||||||
popd
|
|
||||||
|
|
||||||
echo "Creating fat library for armv7 and arm64"
|
|
||||||
pushd monero
|
|
||||||
mkdir -p lib-ios
|
|
||||||
lipo -create lib-armv7/libwallet_merged.a lib-arm64/libwallet_merged.a -output lib-ios/libwallet_merged.a
|
|
||||||
lipo -create lib-armv7/libunbound.a lib-arm64/libunbound.a -output lib-ios/libunbound.a
|
|
||||||
lipo -create lib-armv7/libepee.a lib-arm64/libepee.a -output lib-ios/libepee.a
|
|
||||||
popd
|
|
||||||
@@ -113,5 +113,5 @@ function capitalize(s){
|
|||||||
}
|
}
|
||||||
|
|
||||||
function removeTrailingZeros(value) {
|
function removeTrailingZeros(value) {
|
||||||
return (value + '').replace(/(\.\d*[1-9])0+$/, '$1');
|
return (value + '').replace(/(\.\d*?)0+$/, '$1').replace(/\.$/, '');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,62 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|
||||||
source $ROOT_DIR/utils.sh
|
|
||||||
|
|
||||||
TARGET=$1
|
|
||||||
|
|
||||||
GUI_EXEC=$2
|
|
||||||
|
|
||||||
platform=$(get_platform)
|
|
||||||
|
|
||||||
if [[ "$platform" == "linux64" ]]; then
|
|
||||||
PLAT_DIR="/usr/lib/x86_64-linux-gnu"
|
|
||||||
elif [[ "$platform" == "linux32" ]]; then
|
|
||||||
PLAT_DIR="/usr/lib/i386-linux-gnu"
|
|
||||||
elif [[ "$platform" == "linuxarmv7" ]]; then
|
|
||||||
PLAT_DIR="/usr/lib/arm-linux-gnueabihf"
|
|
||||||
elif [[ "$platform" == "linuxarmv8" ]]; then
|
|
||||||
PLAT_DIR="/usr/lib/aarch64-linux-gnu"
|
|
||||||
else
|
|
||||||
PLAT_DIR="/usr/lib"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "$QT_DIR" ]; then
|
|
||||||
QT_DIR=$PLAT_DIR/qt5
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "$QTXML_DIR" ]; then
|
|
||||||
QTXML_DIR=$PLAT_DIR
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Copy dependencies
|
|
||||||
EXCLUDE='libstdc++|libgcc_s.so|libc.so|libpthread'
|
|
||||||
INCLUDE='libunbound'
|
|
||||||
cp -rv $QT_DIR/qml $TARGET || exit
|
|
||||||
cp -rv $QT_DIR/plugins $TARGET || exit
|
|
||||||
mkdir -p $TARGET/libs || exit
|
|
||||||
#ldd $TARGET/$GUI_EXEC | grep "=> /" | awk '{print $3}' | grep $INCLUDE | xargs -I '{}' cp -v '{}' $TARGET/libs || exit
|
|
||||||
#ldd $TARGET/$GUI_EXEC | grep "=> /" | awk '{print $3}' | grep -Ev $EXCLUDE | xargs -I '{}' cp -v '{}' $TARGET/libs || exit
|
|
||||||
#ldd $TARGET/plugins/platforms/libqxcb.so| grep "=> /" | awk '{print $3}' | grep -Ev $EXCLUDE | xargs -I '{}' cp -v '{}' $TARGET/libs || exit
|
|
||||||
#cp -v $QTXML_DIR/libQt5XmlPatterns.so.5 $TARGET/libs || exit
|
|
||||||
|
|
||||||
# Create start script
|
|
||||||
cat > $TARGET/start-gui.sh <<EOL
|
|
||||||
#!/bin/bash
|
|
||||||
export LD_LIBRARY_PATH=\`pwd\`/libs
|
|
||||||
export QT_PLUGIN_PATH=\`pwd\`/plugins
|
|
||||||
export QML2_IMPORT_PATH=\`pwd\`/qml
|
|
||||||
# make it so that it can be called from anywhere and also through soft links
|
|
||||||
SCRIPT_DIR="\$(dirname "\$(test -L "\${BASH_SOURCE[0]}" && readlink "\${BASH_SOURCE[0]}" || echo "\${BASH_SOURCE[0]}")")"
|
|
||||||
"\$SCRIPT_DIR"/$GUI_EXEC "\$@"
|
|
||||||
EOL
|
|
||||||
|
|
||||||
# Create start script
|
|
||||||
cat > $TARGET/start-tails.AppImage <<EOL
|
|
||||||
#!/bin/bash
|
|
||||||
# Silly hack to provide a launcher that is double clickable
|
|
||||||
bash ./start-gui.sh
|
|
||||||
EOL
|
|
||||||
|
|
||||||
chmod +x $TARGET/start-gui.sh
|
|
||||||
chmod +x $TARGET/start-tails.AppImage
|
|
||||||
462
main.qml
462
main.qml
@@ -26,6 +26,7 @@
|
|||||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
// 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.
|
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
import QtQml.Models 2.12
|
||||||
import QtQuick 2.9
|
import QtQuick 2.9
|
||||||
import QtQuick.Window 2.0
|
import QtQuick.Window 2.0
|
||||||
import QtQuick.Controls 1.1
|
import QtQuick.Controls 1.1
|
||||||
@@ -53,7 +54,10 @@ import "version.js" as Version
|
|||||||
|
|
||||||
ApplicationWindow {
|
ApplicationWindow {
|
||||||
id: appWindow
|
id: appWindow
|
||||||
title: "Monero" + (walletName ? " - " + walletName : "")
|
title: "Monero" +
|
||||||
|
(persistentSettings.displayWalletNameInTitleBar && walletName
|
||||||
|
? " - " + walletName
|
||||||
|
: "")
|
||||||
minimumWidth: 750
|
minimumWidth: 750
|
||||||
minimumHeight: 450
|
minimumHeight: 450
|
||||||
|
|
||||||
@@ -65,14 +69,13 @@ ApplicationWindow {
|
|||||||
property var currentWallet;
|
property var currentWallet;
|
||||||
property bool disconnected: currentWallet ? currentWallet.disconnected : false
|
property bool disconnected: currentWallet ? currentWallet.disconnected : false
|
||||||
property var transaction;
|
property var transaction;
|
||||||
property var transactionDescription;
|
|
||||||
property var walletPassword
|
property var walletPassword
|
||||||
property int restoreHeight:0
|
property int restoreHeight:0
|
||||||
property bool daemonSynced: false
|
property bool daemonSynced: false
|
||||||
property bool walletSynced: false
|
property bool walletSynced: false
|
||||||
property int maxWindowHeight: (isAndroid || isIOS)? screenHeight : (screenHeight < 900)? 720 : 800;
|
property int maxWindowHeight: (isAndroid || isIOS)? screenHeight : (screenHeight < 900)? 720 : 800;
|
||||||
property bool daemonRunning: !persistentSettings.useRemoteNode && !disconnected
|
property bool daemonRunning: !persistentSettings.useRemoteNode && !disconnected
|
||||||
property bool daemonStartStopInProgress: false
|
property int daemonStartStopInProgress: 0
|
||||||
property alias toolTip: toolTip
|
property alias toolTip: toolTip
|
||||||
property string walletName
|
property string walletName
|
||||||
property bool viewOnly: false
|
property bool viewOnly: false
|
||||||
@@ -141,12 +144,8 @@ ApplicationWindow {
|
|||||||
|
|
||||||
if(seq === "Ctrl+S") middlePanel.state = "Transfer"
|
if(seq === "Ctrl+S") middlePanel.state = "Transfer"
|
||||||
else if(seq === "Ctrl+R") middlePanel.state = "Receive"
|
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+H") middlePanel.state = "History"
|
||||||
else if(seq === "Ctrl+B") middlePanel.state = "AddressBook"
|
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+E") middlePanel.state = "Settings"
|
||||||
else if(seq === "Ctrl+D") middlePanel.state = "Advanced"
|
else if(seq === "Ctrl+D") middlePanel.state = "Advanced"
|
||||||
else if(seq === "Ctrl+T") middlePanel.state = "Account"
|
else if(seq === "Ctrl+T") middlePanel.state = "Account"
|
||||||
@@ -166,11 +165,8 @@ ApplicationWindow {
|
|||||||
else if(middlePanel.state === "Transfer") middlePanel.state = "AddressBook"
|
else if(middlePanel.state === "Transfer") middlePanel.state = "AddressBook"
|
||||||
else if(middlePanel.state === "AddressBook") middlePanel.state = "Receive"
|
else if(middlePanel.state === "AddressBook") middlePanel.state = "Receive"
|
||||||
else if(middlePanel.state === "Receive") middlePanel.state = "History"
|
else if(middlePanel.state === "Receive") middlePanel.state = "History"
|
||||||
else if(middlePanel.state === "History") middlePanel.state = "Mining"
|
else if(middlePanel.state === "History") middlePanel.state = "Advanced"
|
||||||
else if(middlePanel.state === "Mining") middlePanel.state = "TxKey"
|
else if(middlePanel.state === "Advanced") middlePanel.state = "Settings"
|
||||||
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(seq === "Ctrl+Shift+Backtab" || seq === "Alt+Shift+Backtab") {
|
} else if(seq === "Ctrl+Shift+Backtab" || seq === "Alt+Shift+Backtab") {
|
||||||
/*
|
/*
|
||||||
if(middlePanel.state === "Settings") middlePanel.state = "Sign"
|
if(middlePanel.state === "Settings") middlePanel.state = "Sign"
|
||||||
@@ -182,11 +178,8 @@ ApplicationWindow {
|
|||||||
else if(middlePanel.state === "TxKey") middlePanel.state = "Receive"
|
else if(middlePanel.state === "TxKey") middlePanel.state = "Receive"
|
||||||
else if(middlePanel.state === "Receive") middlePanel.state = "Transfer"
|
else if(middlePanel.state === "Receive") middlePanel.state = "Transfer"
|
||||||
*/
|
*/
|
||||||
if(middlePanel.state === "Settings") middlePanel.state = "Sign"
|
if(middlePanel.state === "Settings") middlePanel.state = "Advanced"
|
||||||
else if(middlePanel.state === "Sign") middlePanel.state = "SharedRingDB"
|
else if(middlePanel.state === "Advanced") middlePanel.state = "History"
|
||||||
else if(middlePanel.state === "SharedRingDB") middlePanel.state = "TxKey"
|
|
||||||
else if(middlePanel.state === "TxKey") middlePanel.state = "Mining"
|
|
||||||
else if(middlePanel.state === "Mining") middlePanel.state = "History"
|
|
||||||
else if(middlePanel.state === "History") middlePanel.state = "Receive"
|
else if(middlePanel.state === "History") middlePanel.state = "Receive"
|
||||||
else if(middlePanel.state === "Receive") middlePanel.state = "AddressBook"
|
else if(middlePanel.state === "Receive") middlePanel.state = "AddressBook"
|
||||||
else if(middlePanel.state === "AddressBook") middlePanel.state = "Transfer"
|
else if(middlePanel.state === "AddressBook") middlePanel.state = "Transfer"
|
||||||
@@ -234,12 +227,6 @@ ApplicationWindow {
|
|||||||
else
|
else
|
||||||
walletManager.setLogLevel(persistentSettings.logLevel)
|
walletManager.setLogLevel(persistentSettings.logLevel)
|
||||||
|
|
||||||
// setup language
|
|
||||||
var locale = persistentSettings.locale
|
|
||||||
if (locale !== "") {
|
|
||||||
translationManager.setLanguage(locale.split("_")[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reload transfer page with translations enabled
|
// Reload transfer page with translations enabled
|
||||||
middlePanel.transferView.onPageCompleted();
|
middlePanel.transferView.onPageCompleted();
|
||||||
|
|
||||||
@@ -378,13 +365,13 @@ ApplicationWindow {
|
|||||||
console.log("Recovering from seed: ", persistentSettings.is_recovering)
|
console.log("Recovering from seed: ", persistentSettings.is_recovering)
|
||||||
console.log("restore Height", persistentSettings.restore_height)
|
console.log("restore Height", persistentSettings.restore_height)
|
||||||
|
|
||||||
// Use saved daemon rpc login settings
|
if (persistentSettings.useRemoteNode) {
|
||||||
currentWallet.setDaemonLogin(persistentSettings.daemonUsername, persistentSettings.daemonPassword)
|
const remoteNode = remoteNodesModel.currentRemoteNode();
|
||||||
|
currentDaemonAddress = remoteNode.address;
|
||||||
if(persistentSettings.useRemoteNode)
|
currentWallet.setDaemonLogin(remoteNode.username, remoteNode.password);
|
||||||
currentDaemonAddress = persistentSettings.remoteNodeAddress
|
} else {
|
||||||
else
|
currentDaemonAddress = localDaemonAddress;
|
||||||
currentDaemonAddress = localDaemonAddress
|
}
|
||||||
|
|
||||||
console.log("initializing with daemon address: ", currentDaemonAddress)
|
console.log("initializing with daemon address: ", currentDaemonAddress)
|
||||||
currentWallet.initAsync(
|
currentWallet.initAsync(
|
||||||
@@ -401,7 +388,7 @@ ApplicationWindow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function isTrustedDaemon() {
|
function isTrustedDaemon() {
|
||||||
return !persistentSettings.useRemoteNode || persistentSettings.is_trusted_daemon;
|
return !persistentSettings.useRemoteNode || remoteNodesModel.currentRemoteNode().trusted;
|
||||||
}
|
}
|
||||||
|
|
||||||
function usefulName(path) {
|
function usefulName(path) {
|
||||||
@@ -503,21 +490,35 @@ ApplicationWindow {
|
|||||||
walletInitialized = true
|
walletInitialized = true
|
||||||
|
|
||||||
// check if daemon was already mining and add mining logo if true
|
// check if daemon was already mining and add mining logo if true
|
||||||
middlePanel.miningView.update();
|
middlePanel.advancedView.miningView.update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function onDeviceButtonRequest(code){
|
function onDeviceButtonRequest(code){
|
||||||
prevSplashText = splash.messageText;
|
if (txConfirmationPopup.visible) {
|
||||||
splashDisplayedBeforeButtonRequest = splash.visible;
|
txConfirmationPopup.bottomTextAnimation.running = true
|
||||||
appWindow.showProcessingSplash(qsTr("Please proceed to the device..."));
|
if (!txConfirmationPopup.errorText.visible) {
|
||||||
|
txConfirmationPopup.bottomText.text = qsTr("Please confirm transaction on the device...") + translationManager.emptyString;
|
||||||
|
} else {
|
||||||
|
txConfirmationPopup.bottomText.text = qsTr("Please proceed to the device...") + translationManager.emptyString;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
prevSplashText = splash.messageText;
|
||||||
|
splashDisplayedBeforeButtonRequest = splash.visible;
|
||||||
|
appWindow.showProcessingSplash(qsTr("Please proceed to the device..."));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function onDeviceButtonPressed(){
|
function onDeviceButtonPressed(){
|
||||||
if (splashDisplayedBeforeButtonRequest){
|
if (txConfirmationPopup.visible) {
|
||||||
appWindow.showProcessingSplash(prevSplashText);
|
txConfirmationPopup.bottomTextAnimation.running = false;
|
||||||
|
txConfirmationPopup.bottomText.text = qsTr("Signing transaction in the device...") + translationManager.emptyString;
|
||||||
} else {
|
} else {
|
||||||
hideProcessingSplash();
|
if (splashDisplayedBeforeButtonRequest){
|
||||||
|
appWindow.showProcessingSplash(prevSplashText);
|
||||||
|
} else {
|
||||||
|
hideProcessingSplash();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -616,7 +617,9 @@ ApplicationWindow {
|
|||||||
|
|
||||||
const callback = function() {
|
const callback = function() {
|
||||||
persistentSettings.useRemoteNode = true;
|
persistentSettings.useRemoteNode = true;
|
||||||
currentDaemonAddress = persistentSettings.remoteNodeAddress;
|
const remoteNode = remoteNodesModel.currentRemoteNode();
|
||||||
|
currentDaemonAddress = remoteNode.address;
|
||||||
|
currentWallet.setDaemonLogin(remoteNode.username, remoteNode.password);
|
||||||
currentWallet.initAsync(
|
currentWallet.initAsync(
|
||||||
currentDaemonAddress,
|
currentDaemonAddress,
|
||||||
isTrustedDaemon(),
|
isTrustedDaemon(),
|
||||||
@@ -642,6 +645,7 @@ ApplicationWindow {
|
|||||||
console.log("disconnecting remote node");
|
console.log("disconnecting remote node");
|
||||||
persistentSettings.useRemoteNode = false;
|
persistentSettings.useRemoteNode = false;
|
||||||
currentDaemonAddress = localDaemonAddress
|
currentDaemonAddress = localDaemonAddress
|
||||||
|
currentWallet.setDaemonLogin("", "");
|
||||||
currentWallet.initAsync(
|
currentWallet.initAsync(
|
||||||
currentDaemonAddress,
|
currentDaemonAddress,
|
||||||
isTrustedDaemon(),
|
isTrustedDaemon(),
|
||||||
@@ -707,31 +711,33 @@ ApplicationWindow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function startDaemon(flags){
|
function startDaemon(flags){
|
||||||
daemonStartStopInProgress = true;
|
daemonStartStopInProgress = 1;
|
||||||
|
|
||||||
// Pause refresh while starting daemon
|
// Pause refresh while starting daemon
|
||||||
currentWallet.pauseRefresh();
|
currentWallet.pauseRefresh();
|
||||||
|
|
||||||
appWindow.showProcessingSplash(qsTr("Waiting for daemon to start..."))
|
|
||||||
const noSync = appWindow.walletMode === 0;
|
const noSync = appWindow.walletMode === 0;
|
||||||
const bootstrapNodeAddress = persistentSettings.walletMode < 2 ? "auto" : persistentSettings.bootstrapNodeAddress
|
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){
|
function stopDaemon(callback, splash){
|
||||||
daemonStartStopInProgress = true;
|
daemonStartStopInProgress = 2;
|
||||||
appWindow.showProcessingSplash(qsTr("Waiting for daemon to stop..."))
|
if (splash) {
|
||||||
|
appWindow.showProcessingSplash(qsTr("Waiting for daemon to stop..."));
|
||||||
|
}
|
||||||
daemonManager.stopAsync(persistentSettings.nettype, function(result) {
|
daemonManager.stopAsync(persistentSettings.nettype, function(result) {
|
||||||
daemonStartStopInProgress = false;
|
daemonStartStopInProgress = 0;
|
||||||
hideProcessingSplash();
|
if (splash) {
|
||||||
|
hideProcessingSplash();
|
||||||
|
}
|
||||||
callback(result);
|
callback(result);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function onDaemonStarted(){
|
function onDaemonStarted(){
|
||||||
console.log("daemon started");
|
console.log("daemon started");
|
||||||
daemonStartStopInProgress = false;
|
daemonStartStopInProgress = 0;
|
||||||
hideProcessingSplash();
|
|
||||||
currentWallet.connected(true);
|
currentWallet.connected(true);
|
||||||
// resume refresh
|
// resume refresh
|
||||||
currentWallet.startRefresh();
|
currentWallet.startRefresh();
|
||||||
@@ -744,8 +750,7 @@ ApplicationWindow {
|
|||||||
|
|
||||||
function onDaemonStartFailure(error) {
|
function onDaemonStartFailure(error) {
|
||||||
console.log("daemon start failed");
|
console.log("daemon start failed");
|
||||||
daemonStartStopInProgress = false;
|
daemonStartStopInProgress = 0;
|
||||||
hideProcessingSplash();
|
|
||||||
// resume refresh
|
// resume refresh
|
||||||
currentWallet.startRefresh();
|
currentWallet.startRefresh();
|
||||||
informationPopup.title = qsTr("Daemon failed to start") + translationManager.emptyString;
|
informationPopup.title = qsTr("Daemon failed to start") + translationManager.emptyString;
|
||||||
@@ -809,108 +814,81 @@ ApplicationWindow {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function onTransactionCreated(pendingTransaction,address,paymentId,mixinCount){
|
function onTransactionCreated(pendingTransaction, addresses, paymentId, mixinCount) {
|
||||||
console.log("Transaction created");
|
console.log("Transaction created");
|
||||||
hideProcessingSplash();
|
txConfirmationPopup.bottomText.text = "";
|
||||||
transaction = pendingTransaction;
|
transaction = pendingTransaction;
|
||||||
// validate address;
|
// validate address;
|
||||||
if (transaction.status !== PendingTransaction.Status_Ok) {
|
if (transaction.status !== PendingTransaction.Status_Ok) {
|
||||||
console.error("Can't create transaction: ", transaction.errorString);
|
console.error("Can't create transaction: ", transaction.errorString);
|
||||||
informationPopup.title = qsTr("Error") + translationManager.emptyString;
|
if (currentWallet.connected() == Wallet.ConnectionStatus_WrongVersion) {
|
||||||
if (currentWallet.connected() == Wallet.ConnectionStatus_WrongVersion)
|
txConfirmationPopup.errorText.text = qsTr("Can't create transaction: Wrong daemon version: ") + transaction.errorString
|
||||||
informationPopup.text = qsTr("Can't create transaction: Wrong daemon version: ") + transaction.errorString
|
} else {
|
||||||
else
|
txConfirmationPopup.errorText.text = qsTr("Can't create transaction: ") + transaction.errorString
|
||||||
informationPopup.text = qsTr("Can't create transaction: ") + transaction.errorString
|
}
|
||||||
informationPopup.icon = StandardIcon.Critical
|
|
||||||
informationPopup.onCloseCallback = null
|
|
||||||
informationPopup.open();
|
|
||||||
// deleting transaction object, we don't want memleaks
|
// deleting transaction object, we don't want memleaks
|
||||||
currentWallet.disposeTransaction(transaction);
|
currentWallet.disposeTransaction(transaction);
|
||||||
|
|
||||||
} else if (transaction.txCount == 0) {
|
} else if (transaction.txCount == 0) {
|
||||||
informationPopup.title = qsTr("Error") + translationManager.emptyString
|
console.error("Can't create transaction: ", transaction.errorString);
|
||||||
informationPopup.text = qsTr("No unmixable outputs to sweep") + translationManager.emptyString
|
txConfirmationPopup.errorText.text = qsTr("No unmixable outputs to sweep") + translationManager.emptyString
|
||||||
informationPopup.icon = StandardIcon.Information
|
|
||||||
informationPopup.onCloseCallback = null
|
|
||||||
informationPopup.open()
|
|
||||||
// deleting transaction object, we don't want memleaks
|
// deleting transaction object, we don't want memleaks
|
||||||
currentWallet.disposeTransaction(transaction);
|
currentWallet.disposeTransaction(transaction);
|
||||||
} else {
|
} else {
|
||||||
console.log("Transaction created, amount: " + walletManager.displayAmount(transaction.amount)
|
console.log("Transaction created, amount: " + walletManager.displayAmount(transaction.amount)
|
||||||
+ ", fee: " + walletManager.displayAmount(transaction.fee));
|
+ ", fee: " + walletManager.displayAmount(transaction.fee));
|
||||||
|
|
||||||
// here we show confirmation popup;
|
// here we update txConfirmationPopup
|
||||||
transactionConfirmationPopup.title = qsTr("Please confirm transaction:\n") + translationManager.emptyString;
|
txConfirmationPopup.transactionAmount = Utils.removeTrailingZeros(walletManager.displayAmount(transaction.amount));
|
||||||
transactionConfirmationPopup.text = "";
|
txConfirmationPopup.transactionFee = Utils.removeTrailingZeros(walletManager.displayAmount(transaction.fee));
|
||||||
transactionConfirmationPopup.text += (address === "" ? "" : (qsTr("Address: ") + address));
|
txConfirmationPopup.confirmButton.text = viewOnly ? qsTr("Save as file") : qsTr("Confirm") + translationManager.emptyString;
|
||||||
transactionConfirmationPopup.text += (paymentId === "" ? "" : (qsTr("\nPayment ID: ") + paymentId));
|
txConfirmationPopup.confirmButton.rightIcon = viewOnly ? "" : "qrc:///images/rightArrow.png"
|
||||||
transactionConfirmationPopup.text += qsTr("\n\nAmount: ") + walletManager.displayAmount(transaction.amount);
|
|
||||||
transactionConfirmationPopup.text += qsTr("\nFee: ") + walletManager.displayAmount(transaction.fee);
|
|
||||||
transactionConfirmationPopup.text += qsTr("\nRingsize: ") + (mixinCount + 1);
|
|
||||||
transactionConfirmationPopup.text += qsTr("\n\nNumber of transactions: ") + transaction.txCount
|
|
||||||
transactionConfirmationPopup.text += (transactionDescription === "" ? "" : (qsTr("\nDescription: ") + transactionDescription))
|
|
||||||
for (var i = 0; i < transaction.subaddrIndices.length; ++i){
|
|
||||||
transactionConfirmationPopup.text += qsTr("\nSpending address index: ") + transaction.subaddrIndices[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
transactionConfirmationPopup.text += translationManager.emptyString;
|
|
||||||
transactionConfirmationPopup.icon = StandardIcon.Question
|
|
||||||
transactionConfirmationPopup.open()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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"
|
// 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("Creating transaction: ")
|
||||||
console.log("\taddress: ", address,
|
console.log("\trecipients: ", recipients,
|
||||||
", payment_id: ", paymentId,
|
", payment_id: ", paymentId,
|
||||||
", amount: ", amount,
|
|
||||||
", mixins: ", mixinCount,
|
", mixins: ", mixinCount,
|
||||||
", priority: ", priority,
|
", priority: ", priority,
|
||||||
", description: ", description);
|
", description: ", description);
|
||||||
|
|
||||||
var splashMsg = qsTr("Creating transaction...");
|
const recipientAll = recipients.find(function (recipient) {
|
||||||
splashMsg += appWindow.currentWallet.isLedger() ? qsTr("\n\nPlease check your hardware wallet –\nyour input may be required.") : "";
|
return recipient.amount == "(all)";
|
||||||
showProcessingSplash(splashMsg);
|
});
|
||||||
|
if (recipientAll && recipients.length > 1) {
|
||||||
transactionDescription = description;
|
throw "Sending all requires one destination address";
|
||||||
|
|
||||||
// validate amount;
|
|
||||||
if (amount !== "(all)") {
|
|
||||||
var amountxmr = walletManager.amountFromString(amount);
|
|
||||||
console.log("integer amount: ", amountxmr);
|
|
||||||
console.log("integer unlocked", currentWallet.unlockedBalance())
|
|
||||||
if (amountxmr <= 0) {
|
|
||||||
hideProcessingSplash()
|
|
||||||
informationPopup.title = qsTr("Error") + translationManager.emptyString;
|
|
||||||
informationPopup.text = qsTr("Amount is wrong: expected number from %1 to %2")
|
|
||||||
.arg(walletManager.displayAmount(0))
|
|
||||||
.arg(walletManager.displayAmount(currentWallet.unlockedBalance()))
|
|
||||||
+ translationManager.emptyString
|
|
||||||
|
|
||||||
informationPopup.icon = StandardIcon.Critical
|
|
||||||
informationPopup.onCloseCallback = null
|
|
||||||
informationPopup.open()
|
|
||||||
return;
|
|
||||||
} else if (amountxmr > currentWallet.unlockedBalance()) {
|
|
||||||
hideProcessingSplash()
|
|
||||||
informationPopup.title = qsTr("Error") + translationManager.emptyString;
|
|
||||||
informationPopup.text = qsTr("Insufficient funds. Unlocked balance: %1")
|
|
||||||
.arg(walletManager.displayAmount(currentWallet.unlockedBalance()))
|
|
||||||
+ translationManager.emptyString
|
|
||||||
|
|
||||||
informationPopup.icon = StandardIcon.Critical
|
|
||||||
informationPopup.onCloseCallback = null
|
|
||||||
informationPopup.open()
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (amount === "(all)")
|
txConfirmationPopup.bottomTextAnimation.running = false;
|
||||||
currentWallet.createTransactionAllAsync(address, paymentId, mixinCount, priority);
|
txConfirmationPopup.bottomText.text = qsTr("Creating transaction...") + translationManager.emptyString;
|
||||||
else
|
txConfirmationPopup.recipients = recipients;
|
||||||
currentWallet.createTransactionAsync(address, paymentId, amountxmr, mixinCount, priority);
|
txConfirmationPopup.transactionAmount = recipientAll ? "(all)" : getDisplayAmountTotal(recipients);
|
||||||
|
txConfirmationPopup.transactionPriority = priority;
|
||||||
|
txConfirmationPopup.transactionDescription = description;
|
||||||
|
txConfirmationPopup.open();
|
||||||
|
|
||||||
|
if (recipientAll) {
|
||||||
|
currentWallet.createTransactionAllAsync(recipientAll.address, paymentId, mixinCount, priority);
|
||||||
|
} else {
|
||||||
|
const addresses = recipients.map(function (recipient) {
|
||||||
|
return recipient.address;
|
||||||
|
});
|
||||||
|
const amountsxmr = recipients.map(function (recipient) {
|
||||||
|
return walletManager.amountFromString(recipient.amount);
|
||||||
|
});
|
||||||
|
currentWallet.createTransactionAsync(addresses, paymentId, amountsxmr, mixinCount, priority);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Choose where to save transaction
|
//Choose where to save transaction
|
||||||
@@ -934,40 +912,27 @@ ApplicationWindow {
|
|||||||
function handleSweepUnmixable() {
|
function handleSweepUnmixable() {
|
||||||
console.log("Creating transaction: ")
|
console.log("Creating transaction: ")
|
||||||
|
|
||||||
|
txConfirmationPopup.sweepUnmixable = true;
|
||||||
transaction = currentWallet.createSweepUnmixableTransaction();
|
transaction = currentWallet.createSweepUnmixableTransaction();
|
||||||
if (transaction.status !== PendingTransaction.Status_Ok) {
|
if (transaction.status !== PendingTransaction.Status_Ok) {
|
||||||
console.error("Can't create transaction: ", transaction.errorString);
|
console.error("Can't create transaction: ", transaction.errorString);
|
||||||
informationPopup.title = qsTr("Error") + translationManager.emptyString;
|
txConfirmationPopup.errorText.text = qsTr("Can't create transaction: ") + transaction.errorString + translationManager.emptyString
|
||||||
informationPopup.text = qsTr("Can't create transaction: ") + transaction.errorString
|
|
||||||
informationPopup.icon = StandardIcon.Critical
|
|
||||||
informationPopup.onCloseCallback = null
|
|
||||||
informationPopup.open();
|
|
||||||
// deleting transaction object, we don't want memleaks
|
// deleting transaction object, we don't want memleaks
|
||||||
currentWallet.disposeTransaction(transaction);
|
currentWallet.disposeTransaction(transaction);
|
||||||
|
|
||||||
} else if (transaction.txCount == 0) {
|
} else if (transaction.txCount == 0) {
|
||||||
informationPopup.title = qsTr("Error") + translationManager.emptyString
|
console.error("No unmixable outputs to sweep");
|
||||||
informationPopup.text = qsTr("No unmixable outputs to sweep") + translationManager.emptyString
|
txConfirmationPopup.errorText.text = qsTr("No unmixable outputs to sweep") + translationManager.emptyString
|
||||||
informationPopup.icon = StandardIcon.Information
|
|
||||||
informationPopup.onCloseCallback = null
|
|
||||||
informationPopup.open()
|
|
||||||
// deleting transaction object, we don't want memleaks
|
// deleting transaction object, we don't want memleaks
|
||||||
currentWallet.disposeTransaction(transaction);
|
currentWallet.disposeTransaction(transaction);
|
||||||
} else {
|
} else {
|
||||||
console.log("Transaction created, amount: " + walletManager.displayAmount(transaction.amount)
|
console.log("Transaction created, amount: " + walletManager.displayAmount(transaction.amount)
|
||||||
+ ", fee: " + walletManager.displayAmount(transaction.fee));
|
+ ", fee: " + walletManager.displayAmount(transaction.fee));
|
||||||
|
txConfirmationPopup.transactionAmount = Utils.removeTrailingZeros(walletManager.displayAmount(transaction.amount));
|
||||||
// here we show confirmation popup;
|
txConfirmationPopup.transactionFee = Utils.removeTrailingZeros(walletManager.displayAmount(transaction.fee));
|
||||||
|
|
||||||
transactionConfirmationPopup.title = qsTr("Confirmation") + translationManager.emptyString
|
|
||||||
transactionConfirmationPopup.text = qsTr("Please confirm transaction:\n")
|
|
||||||
+ qsTr("\n\nAmount: ") + walletManager.displayAmount(transaction.amount)
|
|
||||||
+ qsTr("\nFee: ") + walletManager.displayAmount(transaction.fee)
|
|
||||||
+ translationManager.emptyString
|
|
||||||
transactionConfirmationPopup.icon = StandardIcon.Question
|
|
||||||
transactionConfirmationPopup.open()
|
|
||||||
// committing transaction
|
// committing transaction
|
||||||
}
|
}
|
||||||
|
txConfirmationPopup.open();
|
||||||
}
|
}
|
||||||
|
|
||||||
// called after user confirms transaction
|
// called after user confirms transaction
|
||||||
@@ -985,7 +950,6 @@ ApplicationWindow {
|
|||||||
// Store to file
|
// Store to file
|
||||||
transaction.setFilename(path);
|
transaction.setFilename(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
appWindow.showProcessingSplash(qsTr("Sending transaction ..."));
|
appWindow.showProcessingSplash(qsTr("Sending transaction ..."));
|
||||||
currentWallet.commitTransactionAsync(transaction);
|
currentWallet.commitTransactionAsync(transaction);
|
||||||
}
|
}
|
||||||
@@ -1000,13 +964,14 @@ ApplicationWindow {
|
|||||||
informationPopup.onCloseCallback = null;
|
informationPopup.onCloseCallback = null;
|
||||||
informationPopup.open();
|
informationPopup.open();
|
||||||
} else {
|
} else {
|
||||||
if (transactionDescription.length > 0) {
|
if (txConfirmationPopup.transactionDescription.length > 0) {
|
||||||
for (var i = 0; i < txid.length; ++i)
|
for (var i = 0; i < txid.length; ++i)
|
||||||
currentWallet.setUserNote(txid[i], transactionDescription);
|
currentWallet.setUserNote(txid[i], txConfirmationPopup.transactionDescription);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear tx fields
|
// Clear tx fields
|
||||||
middlePanel.transferView.clearFields()
|
middlePanel.transferView.clearFields()
|
||||||
|
txConfirmationPopup.clearFields()
|
||||||
successfulTxPopup.open(txid)
|
successfulTxPopup.open(txid)
|
||||||
}
|
}
|
||||||
currentWallet.refresh()
|
currentWallet.refresh()
|
||||||
@@ -1156,11 +1121,14 @@ ApplicationWindow {
|
|||||||
|
|
||||||
objectName: "appWindow"
|
objectName: "appWindow"
|
||||||
visible: true
|
visible: true
|
||||||
width: screenWidth > 980 ? 980 : 800
|
width: Screen.desktopAvailableWidth > 980
|
||||||
height: screenHeight > maxWindowHeight ? maxWindowHeight : 700
|
? 980
|
||||||
|
: Math.min(Screen.desktopAvailableWidth, 800)
|
||||||
|
height: Screen.desktopAvailableHeight > maxWindowHeight
|
||||||
|
? maxWindowHeight
|
||||||
|
: Math.min(Screen.desktopAvailableHeight, 700)
|
||||||
color: MoneroComponents.Style.appWindowBackgroundColor
|
color: MoneroComponents.Style.appWindowBackgroundColor
|
||||||
flags: persistentSettings.customDecorations ? Windows.flagsCustomDecorations : Windows.flags
|
flags: persistentSettings.customDecorations ? Windows.flagsCustomDecorations : Windows.flags
|
||||||
onWidthChanged: x -= 0
|
|
||||||
|
|
||||||
Timer {
|
Timer {
|
||||||
id: fiatPriceTimer
|
id: fiatPriceTimer
|
||||||
@@ -1183,7 +1151,7 @@ ApplicationWindow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var key = currency === "xmreur" ? "XXMRZEUR" : "XXMRZUSD";
|
var key = currency === "xmreur" ? "XXMRZEUR" : "XXMRZUSD";
|
||||||
var ticker = resp.result[key]["o"];
|
var ticker = resp.result[key]["c"][0];
|
||||||
return ticker;
|
return ticker;
|
||||||
} else if(url.startsWith("https://api.coingecko.com/api/v3/")){
|
} else if(url.startsWith("https://api.coingecko.com/api/v3/")){
|
||||||
var key = currency === "xmreur" ? "eur" : "usd";
|
var key = currency === "xmreur" ? "eur" : "usd";
|
||||||
@@ -1317,8 +1285,10 @@ ApplicationWindow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
x = (Screen.width - width) / 2
|
x = (Screen.desktopAvailableWidth - width) / 2;
|
||||||
y = (Screen.height - maxWindowHeight) / 2
|
y = (Screen.desktopAvailableHeight - height) / 2;
|
||||||
|
|
||||||
|
translationManager.setLanguage(persistentSettings.locale.split("_")[0]);
|
||||||
|
|
||||||
applyWalletMode(persistentSettings.walletMode);
|
applyWalletMode(persistentSettings.walletMode);
|
||||||
|
|
||||||
@@ -1365,6 +1335,27 @@ ApplicationWindow {
|
|||||||
appWindow.fiatApiRefresh();
|
appWindow.fiatApiRefresh();
|
||||||
appWindow.fiatTimerStart();
|
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 {
|
MoneroSettings {
|
||||||
@@ -1375,35 +1366,49 @@ ApplicationWindow {
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
property string language
|
property bool askDesktopShortcut: isLinux
|
||||||
property string locale
|
property string language: 'English (US)'
|
||||||
|
property string language_wallet: 'English'
|
||||||
|
property string locale: 'en_US'
|
||||||
property string account_name
|
property string account_name
|
||||||
property string wallet_path
|
property string wallet_path
|
||||||
property bool allow_background_mining : false
|
property bool allow_background_mining : false
|
||||||
property bool miningIgnoreBattery : true
|
property bool miningIgnoreBattery : true
|
||||||
property var nettype: NetworkType.MAINNET
|
property var nettype: NetworkType.MAINNET
|
||||||
property int restore_height : 0
|
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 : false
|
||||||
property bool is_recovering_from_device : false
|
property bool is_recovering_from_device : false
|
||||||
property bool customDecorations : true
|
property bool customDecorations : true
|
||||||
property string daemonFlags
|
property string daemonFlags
|
||||||
property int logLevel: 0
|
property int logLevel: 0
|
||||||
property string logCategories: ""
|
property string logCategories: ""
|
||||||
property string daemonUsername: ""
|
property string daemonUsername: "" // TODO: drop after v0.17.2.0 release
|
||||||
property string daemonPassword: ""
|
property string daemonPassword: "" // TODO: drop after v0.17.2.0 release
|
||||||
property bool transferShowAdvanced: false
|
property bool transferShowAdvanced: false
|
||||||
property bool receiveShowAdvanced: false
|
property bool receiveShowAdvanced: false
|
||||||
property bool historyShowAdvanced: false
|
property bool historyShowAdvanced: false
|
||||||
property bool historyHumanDates: true
|
property bool historyHumanDates: true
|
||||||
property string blockchainDataDir: ""
|
property string blockchainDataDir: ""
|
||||||
property bool useRemoteNode: false
|
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 string bootstrapNodeAddress: ""
|
||||||
property bool segregatePreForkOutputs: true
|
property bool segregatePreForkOutputs: true
|
||||||
property bool keyReuseMitigation2: true
|
property bool keyReuseMitigation2: true
|
||||||
property int segregationHeight: 0
|
property int segregationHeight: 0
|
||||||
property int kdfRounds: 1
|
property int kdfRounds: 1
|
||||||
|
property bool displayWalletNameInTitleBar: true
|
||||||
property bool hideBalance: false
|
property bool hideBalance: false
|
||||||
property bool askPasswordBeforeSending: true
|
property bool askPasswordBeforeSending: true
|
||||||
property bool lockOnUserInActivity: true
|
property bool lockOnUserInActivity: true
|
||||||
@@ -1413,6 +1418,7 @@ ApplicationWindow {
|
|||||||
property bool checkForUpdates: true
|
property bool checkForUpdates: true
|
||||||
property bool autosave: true
|
property bool autosave: true
|
||||||
property int autosaveMinutes: 10
|
property int autosaveMinutes: 10
|
||||||
|
property bool pruneBlockchain: false
|
||||||
|
|
||||||
property bool fiatPriceEnabled: false
|
property bool fiatPriceEnabled: false
|
||||||
property bool fiatPriceToggle: false
|
property bool fiatPriceToggle: false
|
||||||
@@ -1443,6 +1449,88 @@ ApplicationWindow {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ListModel {
|
||||||
|
id: remoteNodesModel
|
||||||
|
|
||||||
|
property int selected: 0
|
||||||
|
|
||||||
|
signal store()
|
||||||
|
|
||||||
|
function initialize() {
|
||||||
|
try {
|
||||||
|
const remoteNodes = JSON.parse(persistentSettings.remoteNodesSerialized);
|
||||||
|
for (var index = 0; index < remoteNodes.nodes.length; ++index) {
|
||||||
|
const remoteNode = remoteNodes.nodes[index];
|
||||||
|
remoteNodesModel.append(remoteNode);
|
||||||
|
}
|
||||||
|
selected = remoteNodes.selected % remoteNodesModel.count || 0;
|
||||||
|
} catch (e) {
|
||||||
|
console.error('failed to parse remoteNodesSerialized', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
store.connect(function() {
|
||||||
|
var remoteNodes = [];
|
||||||
|
for (var index = 0; index < remoteNodesModel.count; ++index) {
|
||||||
|
remoteNodes.push(remoteNodesModel.get(index));
|
||||||
|
}
|
||||||
|
persistentSettings.remoteNodesSerialized = JSON.stringify({
|
||||||
|
selected: selected,
|
||||||
|
nodes: remoteNodes
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function appendIfNotExists(newRemoteNode) {
|
||||||
|
for (var index = 0; index < remoteNodesModel.count; ++index) {
|
||||||
|
const remoteNode = remoteNodesModel.get(index);
|
||||||
|
if (remoteNode.address == newRemoteNode.address &&
|
||||||
|
remoteNode.username == newRemoteNode.username &&
|
||||||
|
remoteNode.password == newRemoteNode.password &&
|
||||||
|
remoteNode.trusted == newRemoteNode.trusted) {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
remoteNodesModel.append(newRemoteNode);
|
||||||
|
return remoteNodesModel.count - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
function applyRemoteNode(index) {
|
||||||
|
selected = index;
|
||||||
|
const remoteNode = currentRemoteNode();
|
||||||
|
persistentSettings.useRemoteNode = true;
|
||||||
|
if (currentWallet) {
|
||||||
|
currentWallet.setDaemonLogin(remoteNode.username, remoteNode.password);
|
||||||
|
currentWallet.setTrustedDaemon(remoteNode.trusted);
|
||||||
|
appWindow.connectRemoteNode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function currentRemoteNode() {
|
||||||
|
if (selected < remoteNodesModel.count) {
|
||||||
|
return remoteNodesModel.get(selected);
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
address: "",
|
||||||
|
username: "",
|
||||||
|
password: "",
|
||||||
|
trusted: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeSelectNextIfNeeded(index) {
|
||||||
|
remoteNodesModel.remove(index);
|
||||||
|
if (selected == index) {
|
||||||
|
applyRemoteNode(selected % remoteNodesModel.count || 0);
|
||||||
|
} else if (selected > index) {
|
||||||
|
selected = selected - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onCountChanged: store()
|
||||||
|
onDataChanged: store()
|
||||||
|
onSelectedChanged: store()
|
||||||
|
}
|
||||||
|
|
||||||
// Information dialog
|
// Information dialog
|
||||||
StandardDialog {
|
StandardDialog {
|
||||||
// dynamically change onclose handler
|
// dynamically change onclose handler
|
||||||
@@ -1458,10 +1546,11 @@ ApplicationWindow {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Confrirmation aka question dialog
|
// Transaction confirmation popup
|
||||||
StandardDialog {
|
TxConfirmationDialog {
|
||||||
|
// dynamically change onclose handler
|
||||||
|
id: txConfirmationPopup
|
||||||
z: parent.z + 1
|
z: parent.z + 1
|
||||||
id: transactionConfirmationPopup
|
|
||||||
onAccepted: {
|
onAccepted: {
|
||||||
var handleAccepted = function() {
|
var handleAccepted = function() {
|
||||||
// Save transaction to file if view only wallet
|
// Save transaction to file if view only wallet
|
||||||
@@ -1522,6 +1611,10 @@ ApplicationWindow {
|
|||||||
y: (parent.height - height) / 2
|
y: (parent.height - height) / 2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MoneroComponents.RemoteNodeDialog {
|
||||||
|
id: remoteNodeDialog
|
||||||
|
}
|
||||||
|
|
||||||
// Choose blockchain folder
|
// Choose blockchain folder
|
||||||
FileDialog {
|
FileDialog {
|
||||||
id: blockchainFileDialog
|
id: blockchainFileDialog
|
||||||
@@ -1693,18 +1786,6 @@ ApplicationWindow {
|
|||||||
updateBalance();
|
updateBalance();
|
||||||
}
|
}
|
||||||
|
|
||||||
onTxkeyClicked: {
|
|
||||||
middlePanel.state = "TxKey";
|
|
||||||
middlePanel.flickable.contentY = 0;
|
|
||||||
updateBalance();
|
|
||||||
}
|
|
||||||
|
|
||||||
onSharedringdbClicked: {
|
|
||||||
middlePanel.state = "SharedRingDB";
|
|
||||||
middlePanel.flickable.contentY = 0;
|
|
||||||
updateBalance();
|
|
||||||
}
|
|
||||||
|
|
||||||
onHistoryClicked: {
|
onHistoryClicked: {
|
||||||
middlePanel.state = "History";
|
middlePanel.state = "History";
|
||||||
middlePanel.flickable.contentY = 0;
|
middlePanel.flickable.contentY = 0;
|
||||||
@@ -1717,14 +1798,8 @@ ApplicationWindow {
|
|||||||
updateBalance();
|
updateBalance();
|
||||||
}
|
}
|
||||||
|
|
||||||
onMiningClicked: {
|
onAdvancedClicked: {
|
||||||
middlePanel.state = "Mining";
|
middlePanel.state = "Advanced";
|
||||||
middlePanel.flickable.contentY = 0;
|
|
||||||
updateBalance();
|
|
||||||
}
|
|
||||||
|
|
||||||
onSignClicked: {
|
|
||||||
middlePanel.state = "Sign";
|
|
||||||
middlePanel.flickable.contentY = 0;
|
middlePanel.flickable.contentY = 0;
|
||||||
updateBalance();
|
updateBalance();
|
||||||
}
|
}
|
||||||
@@ -1767,7 +1842,9 @@ ApplicationWindow {
|
|||||||
anchors.fill: blurredArea
|
anchors.fill: blurredArea
|
||||||
source: blurredArea
|
source: blurredArea
|
||||||
radius: 64
|
radius: 64
|
||||||
visible: passwordDialog.visible || inputDialog.visible || splash.visible || updateDialog.visible || devicePassphraseDialog.visible || successfulTxPopup.visible
|
visible: passwordDialog.visible || inputDialog.visible || splash.visible || updateDialog.visible ||
|
||||||
|
devicePassphraseDialog.visible || txConfirmationPopup.visible || successfulTxPopup.visible ||
|
||||||
|
remoteNodeDialog.visible
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1820,7 +1897,7 @@ ApplicationWindow {
|
|||||||
TitleBar {
|
TitleBar {
|
||||||
id: titleBar
|
id: titleBar
|
||||||
visible: persistentSettings.customDecorations && middlePanel.state !== "Merchant"
|
visible: persistentSettings.customDecorations && middlePanel.state !== "Merchant"
|
||||||
walletName: appWindow.walletName
|
walletName: persistentSettings.displayWalletNameInTitleBar ? appWindow.walletName : ""
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
onCloseClicked: appWindow.close();
|
onCloseClicked: appWindow.close();
|
||||||
@@ -1873,11 +1950,6 @@ ApplicationWindow {
|
|||||||
function toggleLanguageView(){
|
function toggleLanguageView(){
|
||||||
languageSidebar.isOpened ? languageSidebar.close() : languageSidebar.open();
|
languageSidebar.isOpened ? languageSidebar.close() : languageSidebar.open();
|
||||||
resetLanguageFields()
|
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 {
|
Timer {
|
||||||
@@ -1952,12 +2024,13 @@ ApplicationWindow {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const simpleModeFlags = "--enable-dns-blocklist --out-peers 16";
|
||||||
if (appWindow.daemonRunning) {
|
if (appWindow.daemonRunning) {
|
||||||
appWindow.stopDaemon(function() {
|
appWindow.stopDaemon(function() {
|
||||||
appWindow.startDaemon("")
|
appWindow.startDaemon(simpleModeFlags)
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
appWindow.startDaemon("");
|
appWindow.startDaemon(simpleModeFlags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1965,7 +2038,7 @@ ApplicationWindow {
|
|||||||
// Simple mode connection check timer
|
// Simple mode connection check timer
|
||||||
id: simpleModeConnectionTimer
|
id: simpleModeConnectionTimer
|
||||||
interval: 2000
|
interval: 2000
|
||||||
running: appWindow.walletMode < 2 && currentWallet != undefined && !daemonStartStopInProgress
|
running: appWindow.walletMode < 2 && currentWallet != undefined && daemonStartStopInProgress == 0
|
||||||
repeat: true
|
repeat: true
|
||||||
onTriggered: appWindow.checkSimpleModeConnection()
|
onTriggered: appWindow.checkSimpleModeConnection()
|
||||||
}
|
}
|
||||||
@@ -2043,7 +2116,7 @@ ApplicationWindow {
|
|||||||
if(daemonManager == undefined || persistentSettings.useRemoteNode) {
|
if(daemonManager == undefined || persistentSettings.useRemoteNode) {
|
||||||
closeAccepted();
|
closeAccepted();
|
||||||
} else if (appWindow.walletMode == 0) {
|
} else if (appWindow.walletMode == 0) {
|
||||||
stopDaemon(closeAccepted);
|
stopDaemon(closeAccepted, true);
|
||||||
} else {
|
} else {
|
||||||
showProcessingSplash(qsTr("Checking local node status..."));
|
showProcessingSplash(qsTr("Checking local node status..."));
|
||||||
const handler = function(running) {
|
const handler = function(running) {
|
||||||
@@ -2161,6 +2234,7 @@ ApplicationWindow {
|
|||||||
|
|
||||||
passwordDialog.onRejectedCallback = function() { appWindow.showWizard(); }
|
passwordDialog.onRejectedCallback = function() { appWindow.showWizard(); }
|
||||||
if (inputDialogVisible) inputDialog.close()
|
if (inputDialogVisible) inputDialog.close()
|
||||||
|
remoteNodeDialog.close();
|
||||||
passwordDialog.open();
|
passwordDialog.open();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
2
monero
2
monero
Submodule monero updated: 4d855fcca7...f6e63ef260
@@ -1,581 +0,0 @@
|
|||||||
# qml components require at least QT 5.9.7
|
|
||||||
lessThan (QT_MAJOR_VERSION, 5) | lessThan (QT_MINOR_VERSION, 9) {
|
|
||||||
error("Can't build with Qt $${QT_VERSION}. Use at least Qt 5.9.7")
|
|
||||||
}
|
|
||||||
|
|
||||||
TEMPLATE = app
|
|
||||||
|
|
||||||
QT += svg qml gui-private quick widgets
|
|
||||||
|
|
||||||
WALLET_ROOT=$$PWD/monero
|
|
||||||
|
|
||||||
CONFIG += c++11 link_pkgconfig
|
|
||||||
packagesExist(libusb-1.0) {
|
|
||||||
PKGCONFIG += libusb-1.0
|
|
||||||
}
|
|
||||||
packagesExist(hidapi-libusb) {
|
|
||||||
PKGCONFIG += hidapi-libusb
|
|
||||||
}
|
|
||||||
|
|
||||||
GCC_VERSION = $$system("g++ -dumpversion")
|
|
||||||
GCC_VERSION = $$split(GCC_VERSION, .)
|
|
||||||
GCC_VERSION_MAJOR = $$member(GCC_VERSION, 0)
|
|
||||||
GCC_VERSION_MINOR = $$member(GCC_VERSION, 1)
|
|
||||||
greaterThan(GCC_VERSION_MAJOR, 9) | if(equals(GCC_VERSION_MAJOR, 9) : greaterThan(GCC_VERSION_MINOR, 0)) {
|
|
||||||
GCC_9_1_OR_GREATER = TRUE
|
|
||||||
}
|
|
||||||
|
|
||||||
!win32 | !isEmpty(GCC_9_1_OR_GREATER) {
|
|
||||||
QMAKE_CXXFLAGS += -fPIC -fstack-protector -fstack-protector-strong
|
|
||||||
QMAKE_LFLAGS += -fstack-protector -fstack-protector-strong
|
|
||||||
}
|
|
||||||
|
|
||||||
!win32 {
|
|
||||||
packagesExist(protobuf) {
|
|
||||||
PKGCONFIG += protobuf
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# cleaning "auto-generated" bitmonero directory on "make distclean"
|
|
||||||
QMAKE_DISTCLEAN += -r $$WALLET_ROOT
|
|
||||||
|
|
||||||
INCLUDEPATH += $$WALLET_ROOT/include \
|
|
||||||
$$PWD/src/libwalletqt \
|
|
||||||
$$PWD/src/QR-Code-generator \
|
|
||||||
$$PWD/src \
|
|
||||||
$$WALLET_ROOT/src \
|
|
||||||
$$WALLET_ROOT/external/easylogging++ \
|
|
||||||
$$WALLET_ROOT/contrib/epee/include
|
|
||||||
|
|
||||||
HEADERS += \
|
|
||||||
src/main/filter.h \
|
|
||||||
src/main/clipboardAdapter.h \
|
|
||||||
src/main/oscursor.h \
|
|
||||||
src/libwalletqt/WalletManager.h \
|
|
||||||
src/libwalletqt/Wallet.h \
|
|
||||||
src/libwalletqt/PassphraseHelper.h \
|
|
||||||
src/libwalletqt/PendingTransaction.h \
|
|
||||||
src/libwalletqt/TransactionHistory.h \
|
|
||||||
src/libwalletqt/TransactionInfo.h \
|
|
||||||
src/libwalletqt/QRCodeImageProvider.h \
|
|
||||||
src/libwalletqt/Transfer.h \
|
|
||||||
src/NetworkType.h \
|
|
||||||
src/main/oshelper.h \
|
|
||||||
src/TranslationManager.h \
|
|
||||||
src/model/TransactionHistoryModel.h \
|
|
||||||
src/model/TransactionHistorySortFilterModel.h \
|
|
||||||
src/QR-Code-generator/BitBuffer.hpp \
|
|
||||||
src/QR-Code-generator/QrCode.hpp \
|
|
||||||
src/QR-Code-generator/QrSegment.hpp \
|
|
||||||
src/model/AddressBookModel.h \
|
|
||||||
src/libwalletqt/AddressBook.h \
|
|
||||||
src/model/SubaddressModel.h \
|
|
||||||
src/libwalletqt/Subaddress.h \
|
|
||||||
src/model/SubaddressAccountModel.h \
|
|
||||||
src/libwalletqt/SubaddressAccount.h \
|
|
||||||
src/zxcvbn-c/zxcvbn.h \
|
|
||||||
src/libwalletqt/UnsignedTransaction.h \
|
|
||||||
src/main/Logger.h \
|
|
||||||
src/main/MainApp.h \
|
|
||||||
src/qt/downloader.h \
|
|
||||||
src/qt/FutureScheduler.h \
|
|
||||||
src/qt/ipc.h \
|
|
||||||
src/qt/KeysFiles.h \
|
|
||||||
src/qt/network.h \
|
|
||||||
src/qt/utils.h \
|
|
||||||
src/qt/macoshelper.h \
|
|
||||||
src/qt/MoneroSettings.h \
|
|
||||||
src/qt/TailsOS.h
|
|
||||||
|
|
||||||
SOURCES += src/main/main.cpp \
|
|
||||||
src/main/filter.cpp \
|
|
||||||
src/main/clipboardAdapter.cpp \
|
|
||||||
src/main/oscursor.cpp \
|
|
||||||
src/libwalletqt/WalletManager.cpp \
|
|
||||||
src/libwalletqt/WalletListenerImpl.cpp \
|
|
||||||
src/libwalletqt/Wallet.cpp \
|
|
||||||
src/libwalletqt/PassphraseHelper.cpp \
|
|
||||||
src/libwalletqt/PendingTransaction.cpp \
|
|
||||||
src/libwalletqt/TransactionHistory.cpp \
|
|
||||||
src/libwalletqt/TransactionInfo.cpp \
|
|
||||||
src/libwalletqt/QRCodeImageProvider.cpp \
|
|
||||||
src/main/oshelper.cpp \
|
|
||||||
src/openpgp/openpgp.cpp \
|
|
||||||
src/TranslationManager.cpp \
|
|
||||||
src/model/TransactionHistoryModel.cpp \
|
|
||||||
src/model/TransactionHistorySortFilterModel.cpp \
|
|
||||||
src/QR-Code-generator/BitBuffer.cpp \
|
|
||||||
src/QR-Code-generator/QrCode.cpp \
|
|
||||||
src/QR-Code-generator/QrSegment.cpp \
|
|
||||||
src/model/AddressBookModel.cpp \
|
|
||||||
src/libwalletqt/AddressBook.cpp \
|
|
||||||
src/model/SubaddressModel.cpp \
|
|
||||||
src/libwalletqt/Subaddress.cpp \
|
|
||||||
src/model/SubaddressAccountModel.cpp \
|
|
||||||
src/libwalletqt/SubaddressAccount.cpp \
|
|
||||||
src/zxcvbn-c/zxcvbn.c \
|
|
||||||
src/libwalletqt/UnsignedTransaction.cpp \
|
|
||||||
src/main/Logger.cpp \
|
|
||||||
src/main/MainApp.cpp \
|
|
||||||
src/qt/downloader.cpp \
|
|
||||||
src/qt/FutureScheduler.cpp \
|
|
||||||
src/qt/ipc.cpp \
|
|
||||||
src/qt/KeysFiles.cpp \
|
|
||||||
src/qt/network.cpp \
|
|
||||||
src/qt/updater.cpp \
|
|
||||||
src/qt/utils.cpp \
|
|
||||||
src/qt/MoneroSettings.cpp \
|
|
||||||
src/qt/TailsOS.cpp
|
|
||||||
|
|
||||||
CONFIG(DISABLE_PASS_STRENGTH_METER) {
|
|
||||||
HEADERS -= src/zxcvbn-c/zxcvbn.h
|
|
||||||
SOURCES -= src/zxcvbn-c/zxcvbn.c
|
|
||||||
DEFINES += "DISABLE_PASS_STRENGTH_METER"
|
|
||||||
}
|
|
||||||
|
|
||||||
!ios {
|
|
||||||
HEADERS += src/daemon/DaemonManager.h
|
|
||||||
SOURCES += src/daemon/DaemonManager.cpp
|
|
||||||
}
|
|
||||||
|
|
||||||
lupdate_only {
|
|
||||||
SOURCES = *.qml \
|
|
||||||
components/*.qml \
|
|
||||||
components/effects/*.qml \
|
|
||||||
pages/*.qml \
|
|
||||||
pages/settings/*.qml \
|
|
||||||
pages/merchant/*.qml \
|
|
||||||
wizard/*.qml \
|
|
||||||
wizard/*js
|
|
||||||
}
|
|
||||||
|
|
||||||
# Linker flags required by Trezor
|
|
||||||
TREZOR_LINKER = $$cat($$WALLET_ROOT/lib/trezor_link_flags.txt)
|
|
||||||
|
|
||||||
ios:armv7 {
|
|
||||||
message("target is armv7")
|
|
||||||
LIBS += \
|
|
||||||
-L$$PWD/../ofxiOSBoost/build/libs/boost/lib/armv7 \
|
|
||||||
}
|
|
||||||
ios:arm64 {
|
|
||||||
message("target is arm64")
|
|
||||||
LIBS += \
|
|
||||||
-L$$PWD/../ofxiOSBoost/build/libs/boost/lib/arm64 \
|
|
||||||
}
|
|
||||||
|
|
||||||
LIBS_COMMON = \
|
|
||||||
-lgcrypt \
|
|
||||||
-lgpg-error \
|
|
||||||
-lwallet_merged \
|
|
||||||
-llmdb \
|
|
||||||
-lepee \
|
|
||||||
-lunbound \
|
|
||||||
-lsodium \
|
|
||||||
-leasylogging \
|
|
||||||
-lrandomx
|
|
||||||
|
|
||||||
!ios:!android {
|
|
||||||
LIBS += -L$$WALLET_ROOT/lib \
|
|
||||||
$$LIBS_COMMON
|
|
||||||
}
|
|
||||||
|
|
||||||
android {
|
|
||||||
message("Host is Android")
|
|
||||||
LIBS += -L$$WALLET_ROOT/lib \
|
|
||||||
$$LIBS_COMMON
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
QMAKE_CXXFLAGS += -Werror -Wformat -Wformat-security
|
|
||||||
QMAKE_CFLAGS += -Werror -Wformat -Wformat-security
|
|
||||||
QMAKE_CXXFLAGS_RELEASE += -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1 -O2
|
|
||||||
QMAKE_CFLAGS_RELEASE += -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1 -O2
|
|
||||||
|
|
||||||
ios {
|
|
||||||
message("Host is IOS")
|
|
||||||
|
|
||||||
QMAKE_LFLAGS += -v
|
|
||||||
QMAKE_IOS_DEVICE_ARCHS = arm64
|
|
||||||
CONFIG += arm64
|
|
||||||
LIBS += -L$$WALLET_ROOT/lib-ios \
|
|
||||||
$$LIBS_COMMON
|
|
||||||
|
|
||||||
LIBS+= \
|
|
||||||
-L$$PWD/../OpenSSL-for-iPhone/lib \
|
|
||||||
-L$$PWD/../ofxiOSBoost/build/libs/boost/lib/arm64 \
|
|
||||||
-lboost_serialization \
|
|
||||||
-lboost_thread \
|
|
||||||
-lboost_system \
|
|
||||||
-lboost_date_time \
|
|
||||||
-lboost_filesystem \
|
|
||||||
-lboost_regex \
|
|
||||||
-lboost_chrono \
|
|
||||||
-lboost_program_options \
|
|
||||||
-lssl \
|
|
||||||
-lcrypto \
|
|
||||||
-ldl
|
|
||||||
}
|
|
||||||
|
|
||||||
CONFIG(WITH_SCANNER) {
|
|
||||||
if( greaterThan(QT_MINOR_VERSION, 5) ) {
|
|
||||||
message("using camera scanner")
|
|
||||||
QT += multimedia
|
|
||||||
DEFINES += "WITH_SCANNER"
|
|
||||||
INCLUDEPATH += $$PWD/src/QR-Code-scanner
|
|
||||||
HEADERS += \
|
|
||||||
src/QR-Code-scanner/QrScanThread.h \
|
|
||||||
src/QR-Code-scanner/QrCodeScanner.h
|
|
||||||
SOURCES += \
|
|
||||||
src/QR-Code-scanner/QrScanThread.cpp \
|
|
||||||
src/QR-Code-scanner/QrCodeScanner.cpp
|
|
||||||
android {
|
|
||||||
INCLUDEPATH += $$PWD/../ZBar/include
|
|
||||||
LIBS += -lzbarjni -liconv
|
|
||||||
} else {
|
|
||||||
LIBS += -lzbar
|
|
||||||
macx {
|
|
||||||
ZBAR_DIR = $$system(brew --prefix zbar, lines, EXIT_CODE)
|
|
||||||
equals(EXIT_CODE, 0) {
|
|
||||||
INCLUDEPATH += $$ZBAR_DIR/include
|
|
||||||
} else {
|
|
||||||
INCLUDEPATH += /usr/local/include
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
message("Skipping camera scanner because of Incompatible Qt Version !")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
# currently we only support x86 build as qt.io only provides prebuilt qt for x86 mingw
|
|
||||||
|
|
||||||
win32 {
|
|
||||||
|
|
||||||
# QMAKE_HOST.arch is unreliable, will allways report 32bit if mingw32 shell is run.
|
|
||||||
# Obtaining arch through uname should be reliable. This also fixes building the project in Qt creator without changes.
|
|
||||||
MSYS_HOST_ARCH = $$system(uname -a | grep -o "x86_64")
|
|
||||||
|
|
||||||
# WIN64 Host settings
|
|
||||||
contains(MSYS_HOST_ARCH, x86_64) {
|
|
||||||
message("Host is 64bit")
|
|
||||||
MSYS_ROOT_PATH=c:/msys64
|
|
||||||
|
|
||||||
# WIN32 Host settings
|
|
||||||
} else {
|
|
||||||
message("Host is 32bit")
|
|
||||||
MSYS_ROOT_PATH=c:/msys32
|
|
||||||
}
|
|
||||||
|
|
||||||
# WIN64 Target settings
|
|
||||||
contains(QMAKE_HOST.arch, x86_64) {
|
|
||||||
MSYS_MINGW_PATH=/mingw64
|
|
||||||
|
|
||||||
# WIN32 Target settings
|
|
||||||
} else {
|
|
||||||
MSYS_MINGW_PATH=/mingw32
|
|
||||||
}
|
|
||||||
|
|
||||||
MSYS_PATH=$$MSYS_ROOT_PATH$$MSYS_MINGW_PATH
|
|
||||||
|
|
||||||
# boost root path
|
|
||||||
BOOST_PATH=$$MSYS_PATH/boost
|
|
||||||
BOOST_MINGW_PATH=$$MSYS_MINGW_PATH/boost
|
|
||||||
|
|
||||||
LIBS+=-L$$MSYS_PATH/lib
|
|
||||||
LIBS+=-L$$MSYS_MINGW_PATH/lib
|
|
||||||
LIBS+=-L$$BOOST_PATH/lib
|
|
||||||
LIBS+=-L$$BOOST_MINGW_PATH/lib
|
|
||||||
|
|
||||||
QMAKE_LFLAGS += -static-libgcc -static-libstdc++
|
|
||||||
|
|
||||||
LIBS+= \
|
|
||||||
-Wl,-Bdynamic \
|
|
||||||
-lwinscard \
|
|
||||||
-lwsock32 \
|
|
||||||
-lIphlpapi \
|
|
||||||
-lcrypt32 \
|
|
||||||
-lhidapi \
|
|
||||||
-lgdi32 $$TREZOR_LINKER \
|
|
||||||
-Wl,-Bstatic \
|
|
||||||
-lboost_serialization-mt \
|
|
||||||
-lboost_thread-mt \
|
|
||||||
-lboost_system-mt \
|
|
||||||
-lboost_date_time-mt \
|
|
||||||
-lboost_filesystem-mt \
|
|
||||||
-lboost_regex-mt \
|
|
||||||
-lboost_chrono-mt \
|
|
||||||
-lboost_program_options-mt \
|
|
||||||
-lboost_locale-mt \
|
|
||||||
-licuio \
|
|
||||||
-licuin \
|
|
||||||
-licuuc \
|
|
||||||
-licudt \
|
|
||||||
-licutu \
|
|
||||||
-liconv \
|
|
||||||
-lstdc++ \
|
|
||||||
-lpthread \
|
|
||||||
-lsetupapi \
|
|
||||||
-lssl \
|
|
||||||
-lsodium \
|
|
||||||
-lcrypto \
|
|
||||||
-lws2_32 \
|
|
||||||
-lole32
|
|
||||||
|
|
||||||
!contains(QMAKE_TARGET.arch, x86_64) {
|
|
||||||
message("Target is 32bit")
|
|
||||||
## Windows x86 (32bit) specific build here
|
|
||||||
## there's 2Mb stack in libwallet allocated internally, so we set stack=4Mb
|
|
||||||
## this fixes app crash for x86 Windows build
|
|
||||||
QMAKE_LFLAGS += -Wl,--stack,4194304
|
|
||||||
} else {
|
|
||||||
message("Target is 64bit")
|
|
||||||
}
|
|
||||||
|
|
||||||
QMAKE_LFLAGS += -Wl,--dynamicbase -Wl,--nxcompat
|
|
||||||
}
|
|
||||||
|
|
||||||
linux {
|
|
||||||
CONFIG(static) {
|
|
||||||
message("using static libraries")
|
|
||||||
LIBS+= -Wl,-Bstatic
|
|
||||||
QMAKE_LFLAGS += -static-libgcc -static-libstdc++
|
|
||||||
QMAKE_LIBDIR += /usr/local/ssl/lib
|
|
||||||
# contains(QT_ARCH, x86_64) {
|
|
||||||
LIBS+= -lunbound \
|
|
||||||
-lusb-1.0 \
|
|
||||||
-lhidapi-hidraw \
|
|
||||||
-ludev
|
|
||||||
# }
|
|
||||||
} else {
|
|
||||||
# On some distro's we need to add dynload
|
|
||||||
LIBS+= -ldl
|
|
||||||
}
|
|
||||||
|
|
||||||
LIBS+= \
|
|
||||||
-lboost_serialization \
|
|
||||||
-lboost_thread \
|
|
||||||
-lboost_system \
|
|
||||||
-lboost_date_time \
|
|
||||||
-lboost_filesystem \
|
|
||||||
-lboost_regex \
|
|
||||||
-lboost_chrono \
|
|
||||||
-lboost_program_options \
|
|
||||||
-lssl \
|
|
||||||
-llmdb \
|
|
||||||
-lsodium \
|
|
||||||
-lhidapi-libusb \
|
|
||||||
-lcrypto $$TREZOR_LINKER
|
|
||||||
|
|
||||||
if(!android) {
|
|
||||||
LIBS+= \
|
|
||||||
-Wl,-Bdynamic \
|
|
||||||
-lGL \
|
|
||||||
-lX11
|
|
||||||
}
|
|
||||||
# currently monero has an issue with "static" build and linunwind-dev,
|
|
||||||
# so we link libunwind-dev only for non-Ubuntu distros
|
|
||||||
CONFIG(libunwind_off) {
|
|
||||||
message(Building without libunwind)
|
|
||||||
} else {
|
|
||||||
message(Building with libunwind)
|
|
||||||
LIBS += -Wl,-Bdynamic -lunwind
|
|
||||||
}
|
|
||||||
|
|
||||||
QMAKE_LFLAGS += -pie -Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack
|
|
||||||
}
|
|
||||||
|
|
||||||
macx {
|
|
||||||
# mixing static and shared libs are not supported on mac
|
|
||||||
# CONFIG(static) {
|
|
||||||
# message("using static libraries")
|
|
||||||
# LIBS+= -Wl,-Bstatic
|
|
||||||
# }
|
|
||||||
|
|
||||||
OPENSSL_DIR = $$system(brew --prefix openssl, lines, EXIT_CODE)
|
|
||||||
!equals(EXIT_CODE, 0) {
|
|
||||||
OPENSSL_DIR = /usr/local/ssl
|
|
||||||
}
|
|
||||||
OPENSSL_LIBRARY_DIR = $$OPENSSL_DIR/lib
|
|
||||||
INCLUDEPATH += $$OPENSSL_DIR/include
|
|
||||||
|
|
||||||
BOOST_DIR = $$system(brew --prefix boost, lines, EXIT_CODE)
|
|
||||||
equals(EXIT_CODE, 0) {
|
|
||||||
INCLUDEPATH += $$BOOST_DIR/include
|
|
||||||
} else {
|
|
||||||
INCLUDEPATH += /usr/local/include
|
|
||||||
}
|
|
||||||
|
|
||||||
GCRYPT_DIR = $$system(brew --prefix libgcrypt, lines, EXIT_CODE)
|
|
||||||
equals(EXIT_CODE, 0) {
|
|
||||||
INCLUDEPATH += $$GCRYPT_DIR/include
|
|
||||||
} else {
|
|
||||||
INCLUDEPATH += /usr/local/include
|
|
||||||
}
|
|
||||||
|
|
||||||
GPGP_ERROR_DIR = $$system(brew --prefix libgpg-error, lines, EXIT_CODE)
|
|
||||||
equals(EXIT_CODE, 0) {
|
|
||||||
INCLUDEPATH += $$GPGP_ERROR_DIR/include
|
|
||||||
} else {
|
|
||||||
INCLUDEPATH += /usr/local/include
|
|
||||||
}
|
|
||||||
|
|
||||||
SODIUM_DIR = $$system(brew --prefix libsodium, lines, EXIT_CODE)
|
|
||||||
equals(EXIT_CODE, 0) {
|
|
||||||
INCLUDEPATH += $$SODIUM_DIR/include
|
|
||||||
} else {
|
|
||||||
INCLUDEPATH += /usr/local/include
|
|
||||||
}
|
|
||||||
|
|
||||||
QT += macextras
|
|
||||||
OBJECTIVE_SOURCES += src/qt/macoshelper.mm
|
|
||||||
LIBS+= -Wl,-dead_strip
|
|
||||||
LIBS+= -Wl,-dead_strip_dylibs
|
|
||||||
LIBS+= -Wl,-bind_at_load
|
|
||||||
LIBS+= \
|
|
||||||
-L/usr/local/lib \
|
|
||||||
-L$$OPENSSL_LIBRARY_DIR \
|
|
||||||
-L/usr/local/opt/boost/lib \
|
|
||||||
-lboost_serialization \
|
|
||||||
-lboost_thread-mt \
|
|
||||||
-lboost_system \
|
|
||||||
-lboost_date_time \
|
|
||||||
-lboost_filesystem \
|
|
||||||
-lboost_regex \
|
|
||||||
-lboost_chrono \
|
|
||||||
-lboost_program_options \
|
|
||||||
-framework CoreFoundation \
|
|
||||||
-framework AppKit \
|
|
||||||
-lhidapi \
|
|
||||||
-lssl \
|
|
||||||
-lsodium \
|
|
||||||
-lcrypto \
|
|
||||||
-ldl $$TREZOR_LINKER
|
|
||||||
|
|
||||||
QMAKE_LFLAGS += -pie
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
# translation stuff
|
|
||||||
TRANSLATIONS = $$files($$PWD/translations/monero-core_*.ts)
|
|
||||||
|
|
||||||
CONFIG(release, debug|release) {
|
|
||||||
DESTDIR = release/bin
|
|
||||||
LANGUPD_OPTIONS = -locations none -no-ui-lines -no-obsolete
|
|
||||||
LANGREL_OPTIONS = -compress -nounfinished -removeidentical
|
|
||||||
|
|
||||||
} else {
|
|
||||||
DESTDIR = debug/bin
|
|
||||||
LANGUPD_OPTIONS =
|
|
||||||
# LANGREL_OPTIONS = -markuntranslated "MISS_TR "
|
|
||||||
}
|
|
||||||
|
|
||||||
TRANSLATION_TARGET_DIR = $$OUT_PWD/translations
|
|
||||||
|
|
||||||
!ios {
|
|
||||||
isEmpty(QMAKE_LUPDATE) {
|
|
||||||
win32:LANGUPD = $$[QT_INSTALL_BINS]\lupdate.exe
|
|
||||||
else:LANGUPD = $$[QT_INSTALL_BINS]/lupdate
|
|
||||||
}
|
|
||||||
|
|
||||||
isEmpty(QMAKE_LRELEASE) {
|
|
||||||
win32:LANGREL = $$[QT_INSTALL_BINS]\lrelease.exe
|
|
||||||
else:LANGREL = $$[QT_INSTALL_BINS]/lrelease
|
|
||||||
}
|
|
||||||
|
|
||||||
langupd.command = \
|
|
||||||
$$LANGUPD $$LANGUPD_OPTIONS $$shell_path($$_PRO_FILE) -ts $$_PRO_FILE_PWD/$$TRANSLATIONS
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
langrel.depends = langupd
|
|
||||||
langrel.input = TRANSLATIONS
|
|
||||||
langrel.output = $$TRANSLATION_TARGET_DIR/${QMAKE_FILE_BASE}.qm
|
|
||||||
langrel.commands = \
|
|
||||||
$$LANGREL $$LANGREL_OPTIONS ${QMAKE_FILE_IN} -qm $$TRANSLATION_TARGET_DIR/${QMAKE_FILE_BASE}.qm
|
|
||||||
langrel.CONFIG += no_link
|
|
||||||
|
|
||||||
QMAKE_EXTRA_TARGETS += langupd deploy deploy_win
|
|
||||||
QMAKE_EXTRA_COMPILERS += langrel
|
|
||||||
|
|
||||||
# Compile an initial version of translation files when running qmake
|
|
||||||
# the first time and generate the resource file for translations.
|
|
||||||
!exists($$TRANSLATION_TARGET_DIR) {
|
|
||||||
mkpath($$TRANSLATION_TARGET_DIR)
|
|
||||||
}
|
|
||||||
qrc_entry = "<RCC>"
|
|
||||||
qrc_entry += ' <qresource prefix="/">'
|
|
||||||
write_file($$TRANSLATION_TARGET_DIR/translations.qrc, qrc_entry)
|
|
||||||
for(tsfile, TRANSLATIONS) {
|
|
||||||
qmfile = $$TRANSLATION_TARGET_DIR/$$basename(tsfile)
|
|
||||||
qmfile ~= s/.ts$/.qm/
|
|
||||||
system($$LANGREL $$LANGREL_OPTIONS $$tsfile -qm $$qmfile)
|
|
||||||
qrc_entry = " <file>$$basename(qmfile)</file>"
|
|
||||||
write_file($$TRANSLATION_TARGET_DIR/translations.qrc, qrc_entry, append)
|
|
||||||
}
|
|
||||||
qrc_entry = " </qresource>"
|
|
||||||
qrc_entry += "</RCC>"
|
|
||||||
write_file($$TRANSLATION_TARGET_DIR/translations.qrc, qrc_entry, append)
|
|
||||||
RESOURCES += $$TRANSLATION_TARGET_DIR/translations.qrc
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
# Update: no issues with the "slow link process" anymore,
|
|
||||||
# for development, just build debug version of libwallet_merged lib
|
|
||||||
# by invoking 'get_libwallet_api.sh Debug'
|
|
||||||
# so we update translations everytime even for debug build
|
|
||||||
|
|
||||||
PRE_TARGETDEPS += langupd compiler_langrel_make_all
|
|
||||||
|
|
||||||
RESOURCES += qml.qrc
|
|
||||||
CONFIG += qtquickcompiler
|
|
||||||
|
|
||||||
# Additional import path used to resolve QML modules in Qt Creator's code model
|
|
||||||
QML_IMPORT_PATH = fonts
|
|
||||||
|
|
||||||
# Default rules for deployment.
|
|
||||||
include(deployment.pri)
|
|
||||||
macx {
|
|
||||||
deploy.commands += macdeployqt $$sprintf("%1/%2/%3.app", $$OUT_PWD, $$DESTDIR, $$TARGET) -qmldir=$$PWD
|
|
||||||
}
|
|
||||||
|
|
||||||
win32 {
|
|
||||||
deploy.commands += windeployqt $$sprintf("%1/%2/%3.exe", $$OUT_PWD, $$DESTDIR, $$TARGET) -no-translations -qmldir=$$PWD
|
|
||||||
# Win64 msys2 deploy settings
|
|
||||||
contains(QMAKE_HOST.arch, x86_64) {
|
|
||||||
deploy.commands += $$escape_expand(\n\t) $$PWD/windeploy_helper.sh $$DESTDIR
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
linux:!android {
|
|
||||||
deploy.commands += $$escape_expand(\n\t) $$PWD/linuxdeploy_helper.sh $$DESTDIR $$TARGET
|
|
||||||
}
|
|
||||||
|
|
||||||
android{
|
|
||||||
deploy.commands += make install INSTALL_ROOT=$$DESTDIR && androiddeployqt --input android-libmonero-wallet-gui.so-deployment-settings.json --output $$DESTDIR --deployment bundled --android-platform android-21 --jdk /usr/lib/jvm/java-8-openjdk-amd64 -qmldir=$$PWD
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
OTHER_FILES += \
|
|
||||||
.gitignore \
|
|
||||||
$$TRANSLATIONS
|
|
||||||
|
|
||||||
DISTFILES += \
|
|
||||||
notes.txt \
|
|
||||||
monero/src/wallet/CMakeLists.txt
|
|
||||||
|
|
||||||
VERSION = $$cat('version.js', lines)
|
|
||||||
VERSION = $$find(VERSION, 'GUI_VERSION')
|
|
||||||
VERSION_LONG = $$replace(VERSION, '.*\"(.*)\"', '\1')
|
|
||||||
VERSION = $$replace(VERSION, '.*(\d+\.\d+\.\d+\.\d+).*', '\1')
|
|
||||||
|
|
||||||
# windows application icon
|
|
||||||
RC_ICONS = images/appicon.ico
|
|
||||||
|
|
||||||
# mac Info.plist & application icon
|
|
||||||
QMAKE_INFO_PLIST = $$PWD/share/Info.plist
|
|
||||||
macx {
|
|
||||||
QMAKE_POST_LINK += sed -i "''" -e "s/@VERSION@/$$VERSION/g" -e "s/@VERSION_LONG@/$$VERSION_LONG/g" "$$sprintf("%1/%2/%3.app", $$OUT_PWD, $$DESTDIR, $$TARGET)/Contents/Info.plist";
|
|
||||||
}
|
|
||||||
ICON = $$PWD/images/appicon.icns
|
|
||||||
@@ -190,7 +190,7 @@ Rectangle {
|
|||||||
height: subaddressAccountListRow.subaddressAccountListItemHeight
|
height: subaddressAccountListRow.subaddressAccountListItemHeight
|
||||||
width: parent ? parent.width : undefined
|
width: parent ? parent.width : undefined
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
color: "transparent"
|
color: itemMouseArea.containsMouse || index === currentAccountIndex ? MoneroComponents.Style.titleBarButtonHoverColor : "transparent"
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
color: MoneroComponents.Style.appWindowBorderColor
|
color: MoneroComponents.Style.appWindowBorderColor
|
||||||
@@ -226,7 +226,7 @@ Rectangle {
|
|||||||
|
|
||||||
MoneroComponents.Label {
|
MoneroComponents.Label {
|
||||||
id: nameLabel
|
id: nameLabel
|
||||||
color: MoneroComponents.Style.dimmedFontColor
|
color: index === currentAccountIndex ? MoneroComponents.Style.defaultFontColor : MoneroComponents.Style.dimmedFontColor
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
anchors.left: idLabel.right
|
anchors.left: idLabel.right
|
||||||
anchors.leftMargin: 6
|
anchors.leftMargin: 6
|
||||||
@@ -276,11 +276,10 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
|
id: itemMouseArea
|
||||||
cursorShape: Qt.PointingHandCursor
|
cursorShape: Qt.PointingHandCursor
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
onEntered: tableItem2.color = MoneroComponents.Style.titleBarButtonHoverColor
|
|
||||||
onExited: tableItem2.color = "transparent"
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
appWindow.currentWallet.switchSubaddressAccount(index);
|
appWindow.currentWallet.switchSubaddressAccount(index);
|
||||||
if (selectAndSend)
|
if (selectAndSend)
|
||||||
|
|||||||
@@ -132,13 +132,13 @@ Rectangle {
|
|||||||
delegate: Rectangle {
|
delegate: Rectangle {
|
||||||
id: tableItem2
|
id: tableItem2
|
||||||
height: addressBookListRow.addressBookListItemHeight
|
height: addressBookListRow.addressBookListItemHeight
|
||||||
width: parent.width
|
width: parent ? parent.width : undefined
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
color: "transparent"
|
color: "transparent"
|
||||||
|
|
||||||
function doSend() {
|
function doSend() {
|
||||||
console.log("Sending to: ", address +" "+ paymentId);
|
console.log("Sending to: ", address +" "+ paymentId);
|
||||||
middlePanel.sendTo(address, paymentId, description);
|
middlePanel.sendTo(address, paymentId);
|
||||||
leftPanel.selectItem(middlePanel.state)
|
leftPanel.selectItem(middlePanel.state)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -314,16 +314,16 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inlineButton.text: FontAwesome.qrcode
|
MoneroComponents.InlineButton {
|
||||||
inlineButton.fontPixelSize: 22
|
buttonColor: MoneroComponents.Style.orange
|
||||||
inlineButton.fontFamily: FontAwesome.fontFamily
|
fontFamily: FontAwesome.fontFamily
|
||||||
inlineButton.textColor: MoneroComponents.Style.defaultFontColor
|
text: FontAwesome.qrcode
|
||||||
inlineButton.buttonColor: MoneroComponents.Style.orange
|
visible : appWindow.qrScannerEnabled && !addressLine.text
|
||||||
inlineButton.onClicked: {
|
onClicked: {
|
||||||
cameraUi.state = "Capture"
|
cameraUi.state = "Capture"
|
||||||
cameraUi.qrcode_decoded.connect(root.updateFromQrCode)
|
cameraUi.qrcode_decoded.connect(root.updateFromQrCode)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
inlineButtonVisible : appWindow.qrScannerEnabled && !addressLine.text
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MoneroComponents.StandardButton {
|
MoneroComponents.StandardButton {
|
||||||
|
|||||||
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"
|
image: "qrc:///images/whiteDropIndicator.png"
|
||||||
fontAwesomeFallbackIcon: FontAwesome.arrowDown
|
fontAwesomeFallbackIcon: FontAwesome.arrowDown
|
||||||
fontAwesomeFallbackSize: 14
|
fontAwesomeFallbackSize: 14
|
||||||
rotation: sortAndFilter.collapsed ? 0 : 180
|
rotation: sortAndFilter.collapsed ? 180 : 0
|
||||||
color: MoneroComponents.Style.defaultFontColor
|
color: MoneroComponents.Style.defaultFontColor
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
@@ -764,18 +764,21 @@ Rectangle {
|
|||||||
font.pixelSize: 15
|
font.pixelSize: 15
|
||||||
text: {
|
text: {
|
||||||
if (isout) {
|
if (isout) {
|
||||||
|
if (isFailed) {
|
||||||
|
return qsTr("Failed") + translationManager.emptyString;
|
||||||
|
}
|
||||||
|
if (isPending) {
|
||||||
|
return qsTr("Waiting confirmation...") + translationManager.emptyString;
|
||||||
|
}
|
||||||
if (address) {
|
if (address) {
|
||||||
const addressBookName = currentWallet ? currentWallet.addressBook.getDescription(address) : null;
|
|
||||||
return (addressBookName ? FontAwesome.addressBook + " " + addressBookName : TxUtils.addressTruncate(address, 8));
|
return (addressBookName ? FontAwesome.addressBook + " " + addressBookName : TxUtils.addressTruncate(address, 8));
|
||||||
}
|
}
|
||||||
if (amount != 0) {
|
if (amount != 0) {
|
||||||
return (blockheight ? qsTr("Unknown recipient") : qsTr("Waiting confirmation...")) + translationManager.emptyString;
|
return qsTr("Unknown recipient") + translationManager.emptyString;
|
||||||
} else {
|
} else {
|
||||||
return qsTr("My wallet") + translationManager.emptyString;
|
return qsTr("My wallet") + translationManager.emptyString;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const receivingAddress = currentWallet ? currentWallet.address(subaddrAccount, subaddrIndex) : null;
|
|
||||||
const receivingAddressLabel = currentWallet ? appWindow.currentWallet.getSubaddressLabel(subaddrAccount, subaddrIndex) : null;
|
|
||||||
if (receivingAddress) {
|
if (receivingAddress) {
|
||||||
if (subaddrIndex == 0) {
|
if (subaddrIndex == 0) {
|
||||||
return qsTr("Address") + " #0" + " (" + qsTr("Primary address") + ")" + translationManager.emptyString;
|
return qsTr("Address") + " #0" + " (" + qsTr("Primary address") + ")" + translationManager.emptyString;
|
||||||
@@ -1411,6 +1414,12 @@ Rectangle {
|
|||||||
txs.push(item);
|
txs.push(item);
|
||||||
} else if(item.address !== "" && item.address.toLowerCase().startsWith(root.sortSearchString.toLowerCase())){
|
} else if(item.address !== "" && item.address.toLowerCase().startsWith(root.sortSearchString.toLowerCase())){
|
||||||
txs.push(item);
|
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)) {
|
} else if(typeof item.blockheight !== "undefined" && item.blockheight.toString().startsWith(root.sortSearchString)) {
|
||||||
txs.push(item);
|
txs.push(item);
|
||||||
} else if(item.tx_note.toLowerCase().indexOf(root.sortSearchString.toLowerCase()) !== -1) {
|
} else if(item.tx_note.toLowerCase().indexOf(root.sortSearchString.toLowerCase()) !== -1) {
|
||||||
@@ -1489,6 +1498,8 @@ Rectangle {
|
|||||||
|
|
||||||
for (var i = 0; i < count; ++i) {
|
for (var i = 0; i < count; ++i) {
|
||||||
var idx = _model.index(i, 0);
|
var idx = _model.index(i, 0);
|
||||||
|
var isPending = model.data(idx, TransactionHistoryModel.TransactionPendingRole);
|
||||||
|
var isFailed = model.data(idx, TransactionHistoryModel.TransactionFailedRole);
|
||||||
var isout = _model.data(idx, TransactionHistoryModel.TransactionIsOutRole);
|
var isout = _model.data(idx, TransactionHistoryModel.TransactionIsOutRole);
|
||||||
var amount = _model.data(idx, TransactionHistoryModel.TransactionAmountRole);
|
var amount = _model.data(idx, TransactionHistoryModel.TransactionAmountRole);
|
||||||
var hash = _model.data(idx, TransactionHistoryModel.TransactionHashRole);
|
var hash = _model.data(idx, TransactionHistoryModel.TransactionHashRole);
|
||||||
@@ -1514,8 +1525,16 @@ Rectangle {
|
|||||||
|
|
||||||
var tx_note = currentWallet.getUserNote(hash);
|
var tx_note = currentWallet.getUserNote(hash);
|
||||||
var address = "";
|
var address = "";
|
||||||
if(isout) {
|
var addressBookName = "";
|
||||||
|
var receivingAddress = "";
|
||||||
|
var receivingAddressLabel = "";
|
||||||
|
|
||||||
|
if (isout) {
|
||||||
address = TxUtils.destinationsToAddress(destinations);
|
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)
|
if (isout)
|
||||||
@@ -1525,12 +1544,15 @@ Rectangle {
|
|||||||
|
|
||||||
root.txModelData.push({
|
root.txModelData.push({
|
||||||
"i": i,
|
"i": i,
|
||||||
|
"isPending": isPending,
|
||||||
|
"isFailed": isFailed,
|
||||||
"isout": isout,
|
"isout": isout,
|
||||||
"amount": amount,
|
"amount": amount,
|
||||||
"displayAmount": displayAmount,
|
"displayAmount": displayAmount,
|
||||||
"hash": hash,
|
"hash": hash,
|
||||||
"paymentId": paymentId,
|
"paymentId": paymentId,
|
||||||
"address": address,
|
"address": address,
|
||||||
|
"addressBookName": addressBookName,
|
||||||
"destinations": destinations,
|
"destinations": destinations,
|
||||||
"tx_note": tx_note,
|
"tx_note": tx_note,
|
||||||
"dateHuman": dateHuman,
|
"dateHuman": dateHuman,
|
||||||
@@ -1541,6 +1563,8 @@ Rectangle {
|
|||||||
"fee": fee,
|
"fee": fee,
|
||||||
"confirmations": confirmations,
|
"confirmations": confirmations,
|
||||||
"confirmationsRequired": confirmationsRequired,
|
"confirmationsRequired": confirmationsRequired,
|
||||||
|
"receivingAddress": receivingAddress,
|
||||||
|
"receivingAddressLabel": receivingAddressLabel,
|
||||||
"subaddrAccount": subaddrAccount,
|
"subaddrAccount": subaddrAccount,
|
||||||
"subaddrIndex": subaddrIndex
|
"subaddrIndex": subaddrIndex
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ Rectangle {
|
|||||||
id: mainLayout
|
id: mainLayout
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
anchors.margins: 20
|
anchors.margins: 20
|
||||||
anchors.topMargin: 40
|
anchors.topMargin: 0
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ Rectangle {
|
|||||||
height: subaddressListRow.subaddressListItemHeight
|
height: subaddressListRow.subaddressListItemHeight
|
||||||
width: parent ? parent.width : undefined
|
width: parent ? parent.width : undefined
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
color: "transparent"
|
color: itemMouseArea.containsMouse || index === appWindow.current_subaddress_table_index ? MoneroComponents.Style.titleBarButtonHoverColor : "transparent"
|
||||||
|
|
||||||
Rectangle{
|
Rectangle{
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
@@ -143,7 +143,7 @@ Rectangle {
|
|||||||
|
|
||||||
MoneroComponents.Label {
|
MoneroComponents.Label {
|
||||||
id: nameLabel
|
id: nameLabel
|
||||||
color: MoneroComponents.Style.dimmedFontColor
|
color: index === appWindow.current_subaddress_table_index ? MoneroComponents.Style.defaultFontColor : MoneroComponents.Style.dimmedFontColor
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
anchors.left: idLabel.right
|
anchors.left: idLabel.right
|
||||||
anchors.leftMargin: 6
|
anchors.leftMargin: 6
|
||||||
@@ -167,11 +167,10 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
|
id: itemMouseArea
|
||||||
cursorShape: Qt.PointingHandCursor
|
cursorShape: Qt.PointingHandCursor
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
onEntered: tableItem2.color = MoneroComponents.Style.titleBarButtonHoverColor
|
|
||||||
onExited: tableItem2.color = "transparent"
|
|
||||||
onClicked: subaddressListView.currentIndex = index;
|
onClicked: subaddressListView.currentIndex = index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -299,18 +298,6 @@ Rectangle {
|
|||||||
onClicked: qrFileDialog.open()
|
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 {
|
MoneroComponents.StandardButton {
|
||||||
Layout.preferredWidth: 220
|
Layout.preferredWidth: 220
|
||||||
small: true
|
small: true
|
||||||
|
|||||||
@@ -81,8 +81,7 @@ Rectangle {
|
|||||||
id: mainLayout
|
id: mainLayout
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
anchors.margins: 20
|
anchors.margins: 20
|
||||||
anchors.topMargin: 40
|
anchors.topMargin: 0
|
||||||
|
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
|
|||||||
@@ -89,8 +89,7 @@ Rectangle {
|
|||||||
id: mainLayout
|
id: mainLayout
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
anchors.margins: 20
|
anchors.margins: 20
|
||||||
anchors.topMargin: 40
|
anchors.topMargin: 0
|
||||||
|
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
// 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.
|
// 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 2.9
|
||||||
import QtQuick.Controls 1.4
|
import QtQuick.Controls 1.4
|
||||||
import QtQuick.Layouts 1.1
|
import QtQuick.Layouts 1.1
|
||||||
@@ -44,8 +45,7 @@ import "../js/Utils.js" as Utils
|
|||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: root
|
id: root
|
||||||
signal paymentClicked(string address, string paymentId, string amount, int mixinCount,
|
signal paymentClicked(var recipients, string paymentId, int mixinCount, int priority, string description)
|
||||||
int priority, string description)
|
|
||||||
signal sweepUnmixableClicked()
|
signal sweepUnmixableClicked()
|
||||||
|
|
||||||
color: "transparent"
|
color: "transparent"
|
||||||
@@ -61,19 +61,18 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// There are sufficient unlocked funds available
|
// 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;
|
return qsTr("Amount is more than unlocked balance.") + translationManager.emptyString;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (addressLine.text)
|
if (!recipientModel.hasEmptyAddress()) {
|
||||||
{
|
|
||||||
// Address is valid
|
// Address is valid
|
||||||
if (!TxUtils.checkAddress(addressLine.text, appWindow.persistentSettings.nettype)) {
|
if (recipientModel.hasInvalidAddress()) {
|
||||||
return qsTr("Address is invalid.") + translationManager.emptyString;
|
return qsTr("Address is invalid.") + translationManager.emptyString;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Amount is nonzero
|
// Amount is nonzero
|
||||||
if (!amountLine.text || parseFloat(amountLine.text) <= 0) {
|
if (recipientModel.hasEmptyAmount()) {
|
||||||
return qsTr("Enter an amount.") + translationManager.emptyString;
|
return qsTr("Enter an amount.") + translationManager.emptyString;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -93,12 +92,22 @@ Rectangle {
|
|||||||
oaPopup.open()
|
oaPopup.open()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function fillPaymentDetails(address, payment_id, amount, tx_description, recipient_name) {
|
||||||
|
if (recipientModel.count > 0) {
|
||||||
|
const last = recipientModel.count - 1;
|
||||||
|
if (recipientModel.get(recipientModel.count - 1).address == "") {
|
||||||
|
recipientModel.remove(last);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
recipientModel.newRecipient(address, Utils.removeTrailingZeros(amount || ""));
|
||||||
|
setPaymentId(payment_id || "");
|
||||||
|
setDescription((recipient_name ? recipient_name + " " : "") + (tx_description || ""));
|
||||||
|
}
|
||||||
|
|
||||||
function updateFromQrCode(address, payment_id, amount, tx_description, recipient_name) {
|
function updateFromQrCode(address, payment_id, amount, tx_description, recipient_name) {
|
||||||
console.log("updateFromQrCode")
|
console.log("updateFromQrCode")
|
||||||
addressLine.text = address
|
fillPaymentDetails(address, payment_id, amount, tx_description, recipient_name);
|
||||||
setPaymentId(payment_id);
|
|
||||||
amountLine.text = amount
|
|
||||||
setDescription(recipient_name + " " + tx_description);
|
|
||||||
cameraUi.qrcode_decoded.disconnect(updateFromQrCode)
|
cameraUi.qrcode_decoded.disconnect(updateFromQrCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,10 +122,8 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function clearFields() {
|
function clearFields() {
|
||||||
addressLine.text = ""
|
recipientModel.clear();
|
||||||
setPaymentId("");
|
fillPaymentDetails("", "", "", "", "");
|
||||||
amountLine.text = ""
|
|
||||||
setDescription("");
|
|
||||||
priorityDropdown.currentIndex = 0
|
priorityDropdown.currentIndex = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,166 +170,496 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// recipient address input
|
ListModel {
|
||||||
RowLayout {
|
id: recipientModel
|
||||||
id: addressLineRow
|
|
||||||
Layout.fillWidth: true
|
|
||||||
|
|
||||||
LineEditMulti {
|
readonly property int maxRecipients: 16
|
||||||
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
|
ListElement {
|
||||||
inlineButton2.buttonHeight: 30
|
address: ""
|
||||||
inlineButton2.fontPixelSize: 22
|
amount: ""
|
||||||
inlineButton2.fontFamily: FontAwesome.fontFamily
|
}
|
||||||
inlineButton2.textColor: MoneroComponents.Style.defaultFontColor
|
|
||||||
inlineButton2.onClicked: {
|
|
||||||
cameraUi.state = "Capture"
|
|
||||||
cameraUi.qrcode_decoded.connect(updateFromQrCode)
|
|
||||||
}
|
|
||||||
inlineButton2Visible: appWindow.qrScannerEnabled
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
StandardButton {
|
function newRecipient(address, amount) {
|
||||||
id: resolveButton
|
if (recipientModel.count < maxRecipients) {
|
||||||
width: 80
|
recipientModel.append({address: address, amount: amount});
|
||||||
text: qsTr("Resolve") + translationManager.emptyString
|
return true;
|
||||||
visible: TxUtils.isValidOpenAliasAddress(addressLine.text)
|
}
|
||||||
enabled : visible
|
return false;
|
||||||
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"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GridLayout {
|
function getRecipients() {
|
||||||
columns: appWindow.walletMode < 2 ? 1 : 2
|
var recipients = [];
|
||||||
Layout.fillWidth: true
|
for (var index = 0; index < recipientModel.count; ++index) {
|
||||||
columnSpacing: 32
|
const recipient = recipientModel.get(index);
|
||||||
|
recipients.push({
|
||||||
|
address: recipient.address,
|
||||||
|
amount: recipient.amount,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return recipients;
|
||||||
|
}
|
||||||
|
|
||||||
ColumnLayout {
|
function getAmountTotal() {
|
||||||
Layout.fillWidth: true
|
var sum = [];
|
||||||
Layout.minimumWidth: 200
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
// Amount input
|
function hasEmptyAmount() {
|
||||||
LineEdit {
|
for (var index = 0; index < recipientModel.count; ++index) {
|
||||||
id: amountLine
|
if (recipientModel.get(index).amount === "") {
|
||||||
Layout.fillWidth: true
|
return 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"))
|
return false;
|
||||||
+ translationManager.emptyString
|
}
|
||||||
copyButton: !isNaN(amountLine.text) && persistentSettings.fiatPriceEnabled
|
|
||||||
copyButtonText: "~%1 %2".arg(fiatApiConvertToFiat(amountLine.text)).arg(fiatApiCurrencySymbol())
|
|
||||||
copyButtonEnabled: false
|
|
||||||
|
|
||||||
onLabelLinkActivated: {
|
function hasEmptyAddress() {
|
||||||
middlePanel.accountView.selectAndSend = true;
|
for (var index = 0; index < recipientModel.count; ++index) {
|
||||||
appWindow.showPageRequest("Account")
|
if (recipientModel.get(index).address === "") {
|
||||||
}
|
return true;
|
||||||
placeholderText: "0.00"
|
}
|
||||||
width: 100
|
}
|
||||||
fontBold: true
|
return false;
|
||||||
inlineButtonText: qsTr("All") + translationManager.emptyString
|
}
|
||||||
inlineButton.onClicked: amountLine.text = "(all)"
|
|
||||||
onTextChanged: {
|
function hasInvalidAddress() {
|
||||||
amountLine.text = amountLine.text.replace(",", ".");
|
for (var index = 0; index < recipientModel.count; ++index) {
|
||||||
const match = amountLine.text.match(/^0+(\d.*)/);
|
if (!TxUtils.checkAddress(recipientModel.get(index).address, appWindow.persistentSettings.nettype)) {
|
||||||
if (match) {
|
return true;
|
||||||
const cursorPosition = amountLine.cursorPosition;
|
}
|
||||||
amountLine.text = match[1];
|
}
|
||||||
amountLine.cursorPosition = Math.max(cursorPosition, 1) - 1;
|
return false;
|
||||||
} else if(amountLine.text.indexOf('.') === 0){
|
}
|
||||||
amountLine.text = '0' + amountLine.text;
|
}
|
||||||
if (amountLine.text.length > 2) {
|
|
||||||
amountLine.cursorPosition = 1;
|
Item {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
implicitHeight: recipientLayout.height
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
id: recipientLayout
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
spacing: 0
|
||||||
|
|
||||||
|
readonly property int colSpacing: 10
|
||||||
|
readonly property int rowSpacing: 10
|
||||||
|
readonly property int secondRowWidth: 125
|
||||||
|
readonly property int thirdRowWidth: 50
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
Layout.bottomMargin: recipientLayout.rowSpacing / 2
|
||||||
|
spacing: recipientLayout.colSpacing
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
id: addressLabel
|
||||||
|
spacing: 6
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
MoneroComponents.TextPlain {
|
||||||
|
Layout.leftMargin: 10
|
||||||
|
font.family: MoneroComponents.Style.fontRegular.name
|
||||||
|
font.pixelSize: 16
|
||||||
|
color: MoneroComponents.Style.defaultFontColor
|
||||||
|
text: qsTr("Address") + translationManager.emptyString
|
||||||
|
}
|
||||||
|
|
||||||
|
MoneroComponents.InlineButton {
|
||||||
|
fontFamily: FontAwesome.fontFamily
|
||||||
|
fontPixelSize: 18
|
||||||
|
text: FontAwesome.desktop
|
||||||
|
onClicked: {
|
||||||
|
clearFields();
|
||||||
|
const codes = oshelper.grabQrCodesFromScreen();
|
||||||
|
for (var index = 0; index < codes.length; ++index) {
|
||||||
|
const parsed = walletManager.parse_uri_to_object(codes[index]);
|
||||||
|
if (!parsed.error) {
|
||||||
|
fillPaymentDetails(parsed.address, parsed.payment_id, parsed.amount, parsed.tx_description, parsed.recipient_name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
amountLine.error = walletManager.amountFromString(amountLine.text) > appWindow.getUnlockedBalance()
|
|
||||||
}
|
|
||||||
|
|
||||||
validator: RegExpValidator {
|
MoneroComponents.InlineButton {
|
||||||
regExp: /^(\d{1,8})?([\.,]\d{1,12})?$/
|
fontFamily: FontAwesome.fontFamily
|
||||||
}
|
text: FontAwesome.qrcode
|
||||||
}
|
visible: appWindow.qrScannerEnabled
|
||||||
|
onClicked: {
|
||||||
|
cameraUi.state = "Capture"
|
||||||
|
cameraUi.qrcode_decoded.connect(updateFromQrCode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MoneroComponents.InlineButton {
|
||||||
|
fontFamily: FontAwesome.fontFamily
|
||||||
|
text: FontAwesome.addressBook
|
||||||
|
onClicked: {
|
||||||
|
middlePanel.addressBookView.selectAndSend = true;
|
||||||
|
appWindow.showPageRequest("AddressBook");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MoneroComponents.TextPlain {
|
||||||
|
Layout.preferredWidth: recipientLayout.secondRowWidth
|
||||||
|
font.family: MoneroComponents.Style.fontRegular.name
|
||||||
|
font.pixelSize: 16
|
||||||
|
color: MoneroComponents.Style.defaultFontColor
|
||||||
|
text: qsTr("Amount") + translationManager.emptyString
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
Layout.preferredWidth: recipientLayout.thirdRowWidth
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
id: recipientRepeater
|
||||||
|
model: recipientModel
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
spacing: 0
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.rightMargin: recipientLayout.thirdRowWidth
|
||||||
|
color: MoneroComponents.Style.inputBorderColorInActive
|
||||||
|
height: 1
|
||||||
|
visible: index > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
spacing: 0
|
||||||
|
|
||||||
|
MoneroComponents.LineEditMulti {
|
||||||
|
KeyNavigation.backtab: index > 0 ? recipientRepeater.itemAt(index - 1).children[1].children[2] : sendButton
|
||||||
|
KeyNavigation.tab: parent.children[2]
|
||||||
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
Layout.topMargin: index > 0 ? recipientLayout.rowSpacing / 2 : 0
|
||||||
|
Layout.bottomMargin: recipientLayout.rowSpacing / 2
|
||||||
|
Layout.fillWidth: true
|
||||||
|
addressValidation: true
|
||||||
|
borderDisabled: true
|
||||||
|
fontFamily: MoneroComponents.Style.fontMonoRegular.name
|
||||||
|
fontSize: 14
|
||||||
|
inputPaddingBottom: 0
|
||||||
|
inputPaddingTop: 0
|
||||||
|
inputPaddingRight: 0
|
||||||
|
placeholderFontFamily: MoneroComponents.Style.fontMonoRegular.name
|
||||||
|
placeholderFontSize: 14
|
||||||
|
spacing: 0
|
||||||
|
wrapMode: Text.WrapAnywhere
|
||||||
|
placeholderText: {
|
||||||
|
if(persistentSettings.nettype == NetworkType.MAINNET){
|
||||||
|
return "4.. / 8.. / OpenAlias";
|
||||||
|
} else if (persistentSettings.nettype == NetworkType.STAGENET){
|
||||||
|
return "5.. / 7..";
|
||||||
|
} else if(persistentSettings.nettype == NetworkType.TESTNET){
|
||||||
|
return "9.. / B..";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onTextChanged: {
|
||||||
|
const parsed = walletManager.parse_uri_to_object(text);
|
||||||
|
if (!parsed.error) {
|
||||||
|
fillPaymentDetails(parsed.address, parsed.payment_id, parsed.amount, parsed.tx_description);
|
||||||
|
}
|
||||||
|
address = text;
|
||||||
|
}
|
||||||
|
text: address
|
||||||
|
|
||||||
|
MoneroComponents.InlineButton {
|
||||||
|
small: true
|
||||||
|
text: qsTr("Resolve") + translationManager.emptyString
|
||||||
|
visible: TxUtils.isValidOpenAliasAddress(address)
|
||||||
|
onClicked: {
|
||||||
|
var result = walletManager.resolveOpenAlias(address)
|
||||||
|
if (result) {
|
||||||
|
var parts = result.split("|")
|
||||||
|
if (parts.length == 2) {
|
||||||
|
var address_ok = walletManager.addressValid(parts[1], appWindow.persistentSettings.nettype)
|
||||||
|
if (parts[0] === "true") {
|
||||||
|
if (address_ok) {
|
||||||
|
// prepend openalias to description
|
||||||
|
descriptionLine.text = descriptionLine.text ? address + " " + descriptionLine.text : address
|
||||||
|
descriptionCheckbox.checked = true
|
||||||
|
recipientRepeater.itemAt(index).children[1].children[0].text = parts[1];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
oa_message(qsTr("No valid address found at this OpenAlias address"))
|
||||||
|
}
|
||||||
|
else if (parts[0] === "false") {
|
||||||
|
if (address_ok) {
|
||||||
|
recipientRepeater.itemAt(index).children[1].children[0].text = parts[1];
|
||||||
|
oa_message(qsTr("Address found, but the DNSSEC signatures could not be verified, so this address may be spoofed"))
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
oa_message(qsTr("No valid address found at this OpenAlias address, but the DNSSEC signatures could not be verified, so this may be spoofed"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
oa_message(qsTr("Internal error"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
oa_message(qsTr("Internal error"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
oa_message(qsTr("No address found"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
Layout.fillHeight: true
|
||||||
|
Layout.leftMargin: recipientLayout.colSpacing / 2 - width
|
||||||
|
Layout.rightMargin: recipientLayout.colSpacing / 2
|
||||||
|
color: MoneroComponents.Style.inputBorderColorInActive
|
||||||
|
width: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
MoneroComponents.LineEdit {
|
||||||
|
KeyNavigation.backtab: parent.children[0]
|
||||||
|
KeyNavigation.tab: index + 1 < recipientRepeater.count ? recipientRepeater.itemAt(index + 1).children[1].children[0] : sendButton
|
||||||
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
Layout.topMargin: recipientLayout.rowSpacing / 2
|
||||||
|
Layout.bottomMargin: recipientLayout.rowSpacing / 2
|
||||||
|
Layout.rightMargin: recipientLayout.colSpacing / 2
|
||||||
|
Layout.preferredWidth: 125
|
||||||
|
borderDisabled: true
|
||||||
|
fontFamily: MoneroComponents.Style.fontMonoRegular.name
|
||||||
|
fontSize: 14
|
||||||
|
inputPadding: 0
|
||||||
|
placeholderFontFamily: MoneroComponents.Style.fontMonoRegular.name
|
||||||
|
placeholderFontSize: 14
|
||||||
|
placeholderLeftMargin: 0
|
||||||
|
placeholderText: "0.00"
|
||||||
|
text: amount
|
||||||
|
onTextChanged: {
|
||||||
|
text = text.trim().replace(",", ".");
|
||||||
|
const match = text.match(/^0+(\d.*)/);
|
||||||
|
if (match) {
|
||||||
|
const cursorPosition = cursorPosition;
|
||||||
|
text = match[1];
|
||||||
|
cursorPosition = Math.max(cursorPosition, 1) - 1;
|
||||||
|
} else if(text.indexOf('.') === 0){
|
||||||
|
text = '0' + text;
|
||||||
|
if (text.length > 2) {
|
||||||
|
cursorPosition = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
error = walletManager.amountFromString(text) > appWindow.getUnlockedBalance();
|
||||||
|
|
||||||
|
amount = text;
|
||||||
|
}
|
||||||
|
validator: RegExpValidator {
|
||||||
|
regExp: /^\s*(\d{1,8})?([\.,]\d{1,12})?\s*$/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MoneroComponents.TextPlain {
|
||||||
|
Layout.leftMargin: recipientLayout.colSpacing / 2
|
||||||
|
Layout.preferredWidth: recipientLayout.thirdRowWidth
|
||||||
|
font.family: FontAwesome.fontFamilySolid
|
||||||
|
font.styleName: "Solid"
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
opacity: mouseArea.containsMouse ? 1 : 0.85
|
||||||
|
text: recipientModel.count == 1 ? FontAwesome.infinity : FontAwesome.times
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: mouseArea
|
||||||
|
anchors.fill: parent
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
hoverEnabled: true
|
||||||
|
onClicked: {
|
||||||
|
if (recipientModel.count == 1) {
|
||||||
|
parent.parent.children[2].text = "(all)";
|
||||||
|
} else {
|
||||||
|
recipientModel.remove(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GridLayout {
|
||||||
|
id: totalLayout
|
||||||
|
Layout.topMargin: recipientLayout.rowSpacing / 2
|
||||||
|
Layout.fillWidth: true
|
||||||
|
columns: 3
|
||||||
|
columnSpacing: recipientLayout.colSpacing
|
||||||
|
rowSpacing: 0
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
Layout.column: 0
|
||||||
|
Layout.row: 0
|
||||||
|
Layout.fillWidth: true
|
||||||
|
spacing: 0
|
||||||
|
|
||||||
|
CheckBox {
|
||||||
|
border: false
|
||||||
|
checked: false
|
||||||
|
enabled: {
|
||||||
|
if (recipientModel.count > 0 && recipientModel.get(0).amount == "(all)") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (recipientModel.count >= recipientModel.maxRecipients) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
fontAwesomeIcons: true
|
||||||
|
fontSize: descriptionLine.labelFontSize
|
||||||
|
iconOnTheLeft: true
|
||||||
|
text: qsTr("Add recipient") + translationManager.emptyString
|
||||||
|
toggleOnClick: false
|
||||||
|
uncheckedIcon: FontAwesome.plusCircle
|
||||||
|
onClicked: {
|
||||||
|
recipientModel.newRecipient("", "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MoneroComponents.TextPlain {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
horizontalAlignment: Text.AlignRight
|
||||||
|
font.family: MoneroComponents.Style.fontRegular.name
|
||||||
|
font.pixelSize: 16
|
||||||
|
text: recipientModel.count > 1 ? qsTr("Total") + translationManager.emptyString : ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MoneroComponents.LineEdit {
|
||||||
|
id: totalValue
|
||||||
|
Layout.column: 1
|
||||||
|
Layout.row: 0
|
||||||
|
Layout.preferredWidth: recipientLayout.secondRowWidth
|
||||||
|
borderDisabled: true
|
||||||
|
fontFamily: MoneroComponents.Style.fontMonoRegular.name
|
||||||
|
fontSize: 14
|
||||||
|
inputHeight: 30
|
||||||
|
inputPadding: 0
|
||||||
|
readOnly: true
|
||||||
|
text: Utils.removeTrailingZeros(walletManager.displayAmount(recipientModel.getAmountTotal()))
|
||||||
|
visible: recipientModel.count > 1
|
||||||
|
}
|
||||||
|
|
||||||
|
MoneroComponents.TextPlain {
|
||||||
|
Layout.column: 2
|
||||||
|
Layout.row: 0
|
||||||
|
Layout.preferredWidth: recipientLayout.thirdRowWidth
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
font.family: MoneroComponents.Style.fontRegular.name
|
||||||
|
text: "XMR"
|
||||||
|
visible: recipientModel.count > 1
|
||||||
|
}
|
||||||
|
|
||||||
|
MoneroComponents.LineEdit {
|
||||||
|
Layout.column: 1
|
||||||
|
Layout.row: recipientModel.count > 1 ? 1 : 0
|
||||||
|
Layout.preferredWidth: recipientLayout.secondRowWidth
|
||||||
|
borderDisabled: true
|
||||||
|
fontFamily: MoneroComponents.Style.fontMonoRegular.name
|
||||||
|
fontSize: 14
|
||||||
|
inputHeight: 30
|
||||||
|
inputPadding: 0
|
||||||
|
opacity: 0.7
|
||||||
|
readOnly: true
|
||||||
|
text: fiatApiConvertToFiat(walletManager.displayAmount(recipientModel.getAmountTotal()))
|
||||||
|
visible: persistentSettings.fiatPriceEnabled
|
||||||
|
}
|
||||||
|
|
||||||
|
MoneroComponents.TextPlain {
|
||||||
|
Layout.column: 2
|
||||||
|
Layout.row: recipientModel.count > 1 ? 1 : 0
|
||||||
|
Layout.preferredWidth: recipientLayout.thirdRowWidth
|
||||||
|
font.family: MoneroComponents.Style.fontRegular.name
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
opacity: 0.7
|
||||||
|
text: fiatApiCurrencySymbol()
|
||||||
|
visible: persistentSettings.fiatPriceEnabled
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
anchors.top: recipientLayout.top
|
||||||
|
anchors.topMargin: addressLabel.height + recipientLayout.rowSpacing / 2
|
||||||
|
anchors.bottom: recipientLayout.bottom
|
||||||
|
anchors.bottomMargin: totalLayout.height + recipientLayout.rowSpacing / 2
|
||||||
|
anchors.left: recipientLayout.left
|
||||||
|
anchors.right: recipientLayout.right
|
||||||
|
anchors.rightMargin: recipientLayout.thirdRowWidth
|
||||||
|
color: "transparent"
|
||||||
|
border.color: MoneroComponents.Style.inputBorderColorInActive
|
||||||
|
border.width: 1
|
||||||
|
radius: 4
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
spacing: 0
|
||||||
|
visible: appWindow.walletMode >= 2
|
||||||
|
|
||||||
|
Label {
|
||||||
|
id: transactionPriority
|
||||||
|
Layout.topMargin: 0
|
||||||
|
text: qsTr("Transaction priority") + translationManager.emptyString
|
||||||
|
fontBold: false
|
||||||
|
fontSize: 16
|
||||||
|
}
|
||||||
|
// Note: workaround for translations in listElements
|
||||||
|
// ListElement: cannot use script for property value, so
|
||||||
|
// code like this wont work:
|
||||||
|
// ListElement { column1: qsTr("LOW") + translationManager.emptyString ; column2: ""; priority: PendingTransaction.Priority_Low }
|
||||||
|
// For translations to work, the strings need to be listed in
|
||||||
|
// the file components/StandardDropdown.qml too.
|
||||||
|
|
||||||
|
// Priorites after v5
|
||||||
|
ListModel {
|
||||||
|
id: priorityModelV5
|
||||||
|
|
||||||
|
ListElement { column1: qsTr("Automatic") ; column2: ""; priority: 0}
|
||||||
|
ListElement { column1: qsTr("Slow (x0.2 fee)") ; column2: ""; priority: 1}
|
||||||
|
ListElement { column1: qsTr("Normal (x1 fee)") ; column2: ""; priority: 2 }
|
||||||
|
ListElement { column1: qsTr("Fast (x5 fee)") ; column2: ""; priority: 3 }
|
||||||
|
ListElement { column1: qsTr("Fastest (x200 fee)") ; column2: ""; priority: 4 }
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
Layout.topMargin: 5
|
||||||
|
spacing: 10
|
||||||
|
|
||||||
|
StandardDropdown {
|
||||||
|
Layout.preferredWidth: 200
|
||||||
|
id: priorityDropdown
|
||||||
|
currentIndex: 0
|
||||||
|
dataModel: priorityModelV5
|
||||||
|
}
|
||||||
|
|
||||||
MoneroComponents.TextPlain {
|
MoneroComponents.TextPlain {
|
||||||
id: feeLabel
|
id: feeLabel
|
||||||
Layout.alignment: Qt.AlignRight
|
Layout.alignment: Qt.AlignVCenter
|
||||||
Layout.topMargin: 12
|
|
||||||
font.family: MoneroComponents.Style.fontRegular.name
|
font.family: MoneroComponents.Style.fontRegular.name
|
||||||
font.pixelSize: 14
|
font.pixelSize: 14
|
||||||
color: MoneroComponents.Style.defaultFontColor
|
color: MoneroComponents.Style.defaultFontColor
|
||||||
|
opacity: 0.7
|
||||||
property bool estimating: false
|
property bool estimating: false
|
||||||
property var estimatedFee: null
|
property var estimatedFee: null
|
||||||
property string estimatedFeeFiat: {
|
property string estimatedFeeFiat: {
|
||||||
@@ -338,12 +675,21 @@ Rectangle {
|
|||||||
if (!sendButton.enabled || !currentWallet) {
|
if (!sendButton.enabled || !currentWallet) {
|
||||||
return;
|
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(
|
currentWallet.estimateTransactionFeeAsync(
|
||||||
addressLine.text,
|
addresses,
|
||||||
walletManager.amountFromString(amountLine.text),
|
amounts,
|
||||||
priorityModelV5.get(priorityDropdown.currentIndex).priority,
|
priorityModelV5.get(priorityDropdown.currentIndex).priority,
|
||||||
function (amount) {
|
function (amount) {
|
||||||
estimatedFee = Utils.removeTrailingZeros(amount);
|
if (amount) {
|
||||||
|
estimatedFee = Utils.removeTrailingZeros(amount);
|
||||||
|
}
|
||||||
estimating = false;
|
estimating = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -351,56 +697,20 @@ Rectangle {
|
|||||||
if (!sendButton.enabled || estimatedFee == null) {
|
if (!sendButton.enabled || estimatedFee == null) {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
return "%1: ~%2 XMR".arg(qsTr("Fee")).arg(estimatedFee) +
|
return "~%1 XMR%2 %3".arg(estimatedFee)
|
||||||
estimatedFeeFiat +
|
.arg(estimatedFeeFiat)
|
||||||
translationManager.emptyString;
|
.arg(qsTr("fee") + translationManager.emptyString);
|
||||||
}
|
}
|
||||||
|
|
||||||
BusyIndicator {
|
BusyIndicator {
|
||||||
anchors.right: parent.right
|
anchors.left: parent.left
|
||||||
running: feeLabel.estimating
|
running: feeLabel.estimating
|
||||||
height: parent.height
|
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 {
|
MoneroComponents.WarningBox {
|
||||||
text: qsTr("Description field contents match long payment ID format. \
|
text: qsTr("Description field contents match long payment ID format. \
|
||||||
@@ -492,21 +802,21 @@ Rectangle {
|
|||||||
rightIconInactive: "qrc:///images/rightArrowInactive.png"
|
rightIconInactive: "qrc:///images/rightArrowInactive.png"
|
||||||
Layout.topMargin: 4
|
Layout.topMargin: 4
|
||||||
text: qsTr("Send") + translationManager.emptyString
|
text: qsTr("Send") + translationManager.emptyString
|
||||||
enabled: !sendButtonWarningBox.visible && !warningContent && addressLine.text && !paymentIdWarningBox.visible
|
enabled: !sendButtonWarningBox.visible && !warningContent && !recipientModel.hasEmptyAddress() && !paymentIdWarningBox.visible
|
||||||
onClicked: {
|
onClicked: {
|
||||||
console.log("Transfer: paymentClicked")
|
console.log("Transfer: paymentClicked")
|
||||||
var priority = priorityModelV5.get(priorityDropdown.currentIndex).priority
|
var priority = priorityModelV5.get(priorityDropdown.currentIndex).priority
|
||||||
console.log("priority: " + priority)
|
console.log("priority: " + priority)
|
||||||
console.log("amount: " + amountLine.text)
|
|
||||||
addressLine.text = addressLine.text.trim()
|
|
||||||
setPaymentId(paymentIdLine.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) {
|
function checkInformation() {
|
||||||
return amount.length > 0 && walletManager.amountFromString(amountLine.text) <= appWindow.getUnlockedBalance() && TxUtils.checkAddress(address, nettype)
|
return !recipientModel.hasEmptyAmount() &&
|
||||||
|
recipientModel.getAmountTotal() <= appWindow.getUnlockedBalance() &&
|
||||||
|
!recipientModel.hasInvalidAddress();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // pageRoot
|
} // pageRoot
|
||||||
@@ -553,7 +863,8 @@ Rectangle {
|
|||||||
if (appWindow.viewOnly && !appWindow.isTrustedDaemon()){
|
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>";
|
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:#ffffff;} p.orange{color:#ff9323;}</style>" +
|
return "<style type='text/css'>p{line-height:20px; margin-top:0px; margin-bottom:0px; color:" + MoneroComponents.Style.defaultFontColor +
|
||||||
|
";} p.orange{color:#ff9323;}</style>" +
|
||||||
"<p>" + qsTr("1. Using cold wallet, export the key images into a file") + "</p>" +
|
"<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>" +
|
"<p>" + qsTr("2. Using view-only wallet, import the key images file") + "</p>" +
|
||||||
errorMessage + translationManager.emptyString
|
errorMessage + translationManager.emptyString
|
||||||
@@ -565,15 +876,13 @@ Rectangle {
|
|||||||
visible: persistentSettings.transferShowAdvanced && appWindow.walletMode >= 2
|
visible: persistentSettings.transferShowAdvanced && appWindow.walletMode >= 2
|
||||||
title: qsTr("Offline transaction signing") + translationManager.emptyString
|
title: qsTr("Offline transaction signing") + translationManager.emptyString
|
||||||
button1.text: qsTr("Create") + 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: {
|
button1.onClicked: {
|
||||||
console.log("Transfer: saveTx Clicked")
|
console.log("Transfer: saveTx Clicked")
|
||||||
var priority = priorityModelV5.get(priorityDropdown.currentIndex).priority
|
var priority = priorityModelV5.get(priorityDropdown.currentIndex).priority
|
||||||
console.log("priority: " + priority)
|
console.log("priority: " + priority)
|
||||||
console.log("amount: " + amountLine.text)
|
|
||||||
addressLine.text = addressLine.text.trim()
|
|
||||||
setPaymentId(paymentIdLine.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.text: qsTr("Sign (offline)") + translationManager.emptyString
|
||||||
button2.enabled: !appWindow.viewOnly
|
button2.enabled: !appWindow.viewOnly
|
||||||
@@ -590,10 +899,11 @@ Rectangle {
|
|||||||
helpTextLarge.text: qsTr("Spend XMR from a cold (offline) wallet") + translationManager.emptyString
|
helpTextLarge.text: qsTr("Spend XMR from a cold (offline) wallet") + translationManager.emptyString
|
||||||
helpTextSmall.text: {
|
helpTextSmall.text: {
|
||||||
var errorMessage = "";
|
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>";
|
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:#ffffff;} p.orange{color:#ff9323;}</style>" +
|
return "<style type='text/css'>p{line-height:20px; margin-top:0px; margin-bottom:0px; color:" + MoneroComponents.Style.defaultFontColor +
|
||||||
|
";} p.orange{color:#ff9323;}</style>" +
|
||||||
"<p>" + qsTr("1. Using view-only wallet, export the outputs into a file") + "</p>" +
|
"<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("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>" +
|
"<p>" + qsTr("3. Using view-only wallet, import the key images file and create a transaction file") + "</p>" +
|
||||||
@@ -790,19 +1100,9 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Popuplate fields from addressbook.
|
// Popuplate fields from addressbook.
|
||||||
function sendTo(address, paymentId, description, amount){
|
function sendTo(address, paymentId, description, amount) {
|
||||||
middlePanel.state = 'Transfer';
|
middlePanel.state = 'Transfer';
|
||||||
|
|
||||||
if(typeof address !== 'undefined')
|
fillPaymentDetails(address, paymentId, amount, description);
|
||||||
addressLine.text = address
|
|
||||||
|
|
||||||
if(typeof paymentId !== 'undefined')
|
|
||||||
setPaymentId(paymentId);
|
|
||||||
|
|
||||||
if(typeof description !== 'undefined')
|
|
||||||
setDescription(description);
|
|
||||||
|
|
||||||
if(typeof amount !== 'undefined')
|
|
||||||
amountLine.text = amount;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ Rectangle {
|
|||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
id: mainLayout
|
id: mainLayout
|
||||||
anchors.margins: 20
|
anchors.margins: 20
|
||||||
anchors.topMargin: 40
|
anchors.topMargin: 0
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
|
|||||||
@@ -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 int settingsHeight: 900
|
||||||
property alias settingsStateViewState: settingsStateView.state
|
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{
|
Rectangle{
|
||||||
id: settingsStateView
|
id: settingsStateView
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ Rectangle {
|
|||||||
} else if(appWindow.walletMode === 1){
|
} else if(appWindow.walletMode === 1){
|
||||||
return qsTr("Simple mode") + " (bootstrap)" + translationManager.emptyString;
|
return qsTr("Simple mode") + " (bootstrap)" + translationManager.emptyString;
|
||||||
} else if(appWindow.walletMode === 2){
|
} else if(appWindow.walletMode === 2){
|
||||||
return qsTr("Advanced mode") + translationManager.emptyString;
|
return "%1 (%2)".arg(qsTr("Advanced mode")).arg(persistentSettings.useRemoteNode ? qsTr("Remote node") : qsTr("Local node")) + translationManager.emptyString;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -66,6 +66,12 @@ Rectangle {
|
|||||||
text: qsTr("Check for updates periodically") + translationManager.emptyString
|
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 {
|
MoneroComponents.CheckBox {
|
||||||
id: hideBalanceCheckBox
|
id: hideBalanceCheckBox
|
||||||
checked: persistentSettings.hideBalance
|
checked: persistentSettings.hideBalance
|
||||||
|
|||||||
@@ -215,6 +215,7 @@ Rectangle {
|
|||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
property var lastCommands: []
|
property var lastCommands: []
|
||||||
property int currentCommandIndex
|
property int currentCommandIndex
|
||||||
|
enabled: !persistentSettings.useRemoteNode
|
||||||
fontBold: false
|
fontBold: false
|
||||||
placeholderText: qsTr("command + enter (e.g 'help' or 'status')") + translationManager.emptyString
|
placeholderText: qsTr("command + enter (e.g 'help' or 'status')") + translationManager.emptyString
|
||||||
placeholderFontSize: 16
|
placeholderFontSize: 16
|
||||||
|
|||||||
@@ -136,6 +136,7 @@ Rectangle{
|
|||||||
MouseArea {
|
MouseArea {
|
||||||
cursorShape: Qt.PointingHandCursor
|
cursorShape: Qt.PointingHandCursor
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
enabled: persistentSettings.useRemoteNode
|
||||||
onClicked: {
|
onClicked: {
|
||||||
persistentSettings.useRemoteNode = false;
|
persistentSettings.useRemoteNode = false;
|
||||||
appWindow.disconnectRemoteNode();
|
appWindow.disconnectRemoteNode();
|
||||||
@@ -227,6 +228,7 @@ Rectangle{
|
|||||||
MouseArea {
|
MouseArea {
|
||||||
cursorShape: Qt.PointingHandCursor
|
cursorShape: Qt.PointingHandCursor
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
enabled: !persistentSettings.useRemoteNode
|
||||||
onClicked: {
|
onClicked: {
|
||||||
appWindow.connectRemoteNode();
|
appWindow.connectRemoteNode();
|
||||||
}
|
}
|
||||||
@@ -260,80 +262,94 @@ Rectangle{
|
|||||||
text: qsTr("To find a remote node, type 'Monero remote node' into your favorite search engine. Please ensure the node is run by a trusted third-party.") + translationManager.emptyString
|
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 {
|
MoneroComponents.CheckBox {
|
||||||
id: setTrustedDaemonCheckBox
|
border: false
|
||||||
checked: persistentSettings.is_trusted_daemon
|
checkedIcon: FontAwesome.minusCircle
|
||||||
onClicked: {
|
uncheckedIcon: FontAwesome.plusCircle
|
||||||
persistentSettings.is_trusted_daemon = !persistentSettings.is_trusted_daemon
|
fontAwesomeIcons: true
|
||||||
currentWallet.setTrustedDaemon(persistentSettings.is_trusted_daemon)
|
fontSize: 16
|
||||||
}
|
iconOnTheLeft: true
|
||||||
text: qsTr("Mark as Trusted Daemon") + translationManager.emptyString
|
text: qsTr("Add remote node") + translationManager.emptyString
|
||||||
|
toggleOnClick: false
|
||||||
|
onClicked: remoteNodeDialog.add(remoteNodesModel.append)
|
||||||
}
|
}
|
||||||
|
|
||||||
MoneroComponents.StandardButton {
|
ColumnLayout {
|
||||||
id: btnConnectRemote
|
spacing: 0
|
||||||
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);
|
Repeater {
|
||||||
|
model: remoteNodesModel
|
||||||
|
|
||||||
appWindow.connectRemoteNode()
|
Rectangle {
|
||||||
|
height: 30
|
||||||
|
Layout.fillWidth: true
|
||||||
|
color: itemMouseArea.containsMouse || index === remoteNodesModel.selected ? MoneroComponents.Style.titleBarButtonHoverColor : "transparent"
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
color: MoneroComponents.Style.appWindowBorderColor
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.top: parent.top
|
||||||
|
height: 1
|
||||||
|
visible: index > 0
|
||||||
|
|
||||||
|
MoneroEffects.ColorTransition {
|
||||||
|
targetObj: parent
|
||||||
|
blackColor: MoneroComponents.Style._b_appWindowBorderColor
|
||||||
|
whiteColor: MoneroComponents.Style._w_appWindowBorderColor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.rightMargin: 80
|
||||||
|
color: "transparent"
|
||||||
|
|
||||||
|
MoneroComponents.TextPlain {
|
||||||
|
color: index === remoteNodesModel.selected ? MoneroComponents.Style.defaultFontColor : MoneroComponents.Style.dimmedFontColor
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: 6
|
||||||
|
font.pixelSize: 16
|
||||||
|
text: address
|
||||||
|
themeTransition: false
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: itemMouseArea
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
onClicked: remoteNodesModel.applyRemoteNode(index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.rightMargin: 6
|
||||||
|
height: 30
|
||||||
|
spacing: 10
|
||||||
|
|
||||||
|
MoneroComponents.InlineButton {
|
||||||
|
buttonColor: "transparent"
|
||||||
|
fontFamily: FontAwesome.fontFamily
|
||||||
|
fontPixelSize: 18
|
||||||
|
text: FontAwesome.edit
|
||||||
|
onClicked: remoteNodeDialog.edit(remoteNodesModel.get(index), function (remoteNode) {
|
||||||
|
remoteNodesModel.set(index, remoteNode)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
MoneroComponents.InlineButton {
|
||||||
|
buttonColor: "transparent"
|
||||||
|
fontFamily: FontAwesome.fontFamily
|
||||||
|
text: FontAwesome.times
|
||||||
|
visible: remoteNodesModel.count > 1
|
||||||
|
onClicked: remoteNodesModel.removeSelectNextIfNeeded(index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -396,7 +412,7 @@ Rectangle{
|
|||||||
placeholderFontSize: 15
|
placeholderFontSize: 15
|
||||||
text: persistentSettings.daemonFlags
|
text: persistentSettings.daemonFlags
|
||||||
addressValidation: false
|
addressValidation: false
|
||||||
error: text.match(/(^|\s)--(data-dir|bootstrap-daemon-address)/)
|
error: text.match(/(^|\s)--(data-dir|bootstrap-daemon-address|non-interactive)/)
|
||||||
onEditingFinished: {
|
onEditingFinished: {
|
||||||
if (!daemonFlags.error) {
|
if (!daemonFlags.error) {
|
||||||
persistentSettings.daemonFlags = daemonFlags.text;
|
persistentSettings.daemonFlags = daemonFlags.text;
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ Rectangle {
|
|||||||
iconText: FontAwesome.eye
|
iconText: FontAwesome.eye
|
||||||
description: qsTr("Creates a new wallet that can only view and initiate transactions, but requires a spendable wallet to sign transactions before sending.") + translationManager.emptyString
|
description: qsTr("Creates a new wallet that can only view and initiate transactions, but requires a spendable wallet to sign transactions before sending.") + translationManager.emptyString
|
||||||
title: qsTr("Create a view-only wallet") + translationManager.emptyString
|
title: qsTr("Create a view-only wallet") + translationManager.emptyString
|
||||||
visible: !appWindow.viewOnly
|
visible: !appWindow.viewOnly && (currentWallet ? !currentWallet.isLedger() : true)
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
var newPath = currentWallet.path + "_viewonly";
|
var newPath = currentWallet.path + "_viewonly";
|
||||||
|
|||||||
8
qml.qrc
8
qml.qrc
@@ -3,7 +3,12 @@
|
|||||||
<file>main.qml</file>
|
<file>main.qml</file>
|
||||||
<file>LeftPanel.qml</file>
|
<file>LeftPanel.qml</file>
|
||||||
<file>MiddlePanel.qml</file>
|
<file>MiddlePanel.qml</file>
|
||||||
|
<file>components/Dialog.qml</file>
|
||||||
<file>components/Label.qml</file>
|
<file>components/Label.qml</file>
|
||||||
|
<file>components/LanguageButton.qml</file>
|
||||||
|
<file>components/Navbar.qml</file>
|
||||||
|
<file>components/NavbarItem.qml</file>
|
||||||
|
<file>components/RemoteNodeDialog.qml</file>
|
||||||
<file>components/SettingsListItem.qml</file>
|
<file>components/SettingsListItem.qml</file>
|
||||||
<file>components/Slider.qml</file>
|
<file>components/Slider.qml</file>
|
||||||
<file>components/UpdateDialog.qml</file>
|
<file>components/UpdateDialog.qml</file>
|
||||||
@@ -14,6 +19,7 @@
|
|||||||
<file>monero/utils/gpg_keys/fluffypony.asc</file>
|
<file>monero/utils/gpg_keys/fluffypony.asc</file>
|
||||||
<file>monero/utils/gpg_keys/luigi1111.asc</file>
|
<file>monero/utils/gpg_keys/luigi1111.asc</file>
|
||||||
<file>pages/Account.qml</file>
|
<file>pages/Account.qml</file>
|
||||||
|
<file>pages/Advanced.qml</file>
|
||||||
<file>pages/Transfer.qml</file>
|
<file>pages/Transfer.qml</file>
|
||||||
<file>pages/History.qml</file>
|
<file>pages/History.qml</file>
|
||||||
<file>pages/AddressBook.qml</file>
|
<file>pages/AddressBook.qml</file>
|
||||||
@@ -161,7 +167,6 @@
|
|||||||
<file>pages/settings/SettingsLog.qml</file>
|
<file>pages/settings/SettingsLog.qml</file>
|
||||||
<file>pages/settings/SettingsLayout.qml</file>
|
<file>pages/settings/SettingsLayout.qml</file>
|
||||||
<file>pages/settings/SettingsInfo.qml</file>
|
<file>pages/settings/SettingsInfo.qml</file>
|
||||||
<file>pages/settings/Navbar.qml</file>
|
|
||||||
<file>components/WarningBox.qml</file>
|
<file>components/WarningBox.qml</file>
|
||||||
<file>images/miningxmr.png</file>
|
<file>images/miningxmr.png</file>
|
||||||
<file>images/miningxmr@2x.png</file>
|
<file>images/miningxmr@2x.png</file>
|
||||||
@@ -243,5 +248,6 @@
|
|||||||
<file>images/success.png</file>
|
<file>images/success.png</file>
|
||||||
<file>images/success@2x.png</file>
|
<file>images/success@2x.png</file>
|
||||||
<file>components/SuccessfulTxDialog.qml</file>
|
<file>components/SuccessfulTxDialog.qml</file>
|
||||||
|
<file>components/TxConfirmationDialog.qml</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
|||||||
@@ -55,13 +55,6 @@ if(ENABLE_PASS_STRENGTH_METER)
|
|||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(WITH_SCANNER)
|
|
||||||
file(GLOB QR_CODE_FILES
|
|
||||||
"QR-Code-scanner/*.h"
|
|
||||||
"QR-Code-scanner/*.cpp"
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(EXECUTABLE_FLAG)
|
set(EXECUTABLE_FLAG)
|
||||||
if(MINGW)
|
if(MINGW)
|
||||||
set(EXECUTABLE_FLAG WIN32)
|
set(EXECUTABLE_FLAG WIN32)
|
||||||
@@ -81,13 +74,19 @@ if(APPLE)
|
|||||||
list(APPEND RESOURCES ${ICON})
|
list(APPEND RESOURCES ${ICON})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_executable(monero-wallet-gui ${EXECUTABLE_FLAG} main/main.cpp
|
set(monero_wallet_gui_sources
|
||||||
${SOURCE_FILES}
|
${SOURCE_FILES}
|
||||||
${PASS_STRENGTH_FILES}
|
${PASS_STRENGTH_FILES}
|
||||||
${QR_CODE_FILES}
|
|
||||||
${RESOURCES}
|
${RESOURCES}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if(NOT ANDROID)
|
||||||
|
add_executable(monero-wallet-gui ${EXECUTABLE_FLAG} ${monero_wallet_gui_sources})
|
||||||
|
else()
|
||||||
|
add_library(monero-wallet-gui SHARED ${monero_wallet_gui_sources})
|
||||||
|
set_target_properties(monero-wallet-gui PROPERTIES COMPILE_DEFINITIONS "ANDROID")
|
||||||
|
endif()
|
||||||
|
|
||||||
set_target_properties(monero-wallet-gui PROPERTIES
|
set_target_properties(monero-wallet-gui PROPERTIES
|
||||||
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin"
|
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin"
|
||||||
MACOSX_BUNDLE TRUE
|
MACOSX_BUNDLE TRUE
|
||||||
@@ -121,7 +120,6 @@ target_include_directories(monero-wallet-gui PUBLIC
|
|||||||
${X11_INCLUDE_DIR}
|
${X11_INCLUDE_DIR}
|
||||||
${Boost_INCLUDE_DIRS}
|
${Boost_INCLUDE_DIRS}
|
||||||
${OPENSSL_INCLUDE_DIR}
|
${OPENSSL_INCLUDE_DIR}
|
||||||
${ZBAR_INCLUDE_DIR}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
target_compile_definitions(monero-wallet-gui
|
target_compile_definitions(monero-wallet-gui
|
||||||
@@ -130,6 +128,14 @@ target_compile_definitions(monero-wallet-gui
|
|||||||
${Qt5Qml_DEFINITIONS}
|
${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}")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Widgets_EXECUTABLE_COMPILE_FLAGS}")
|
||||||
|
|
||||||
target_link_libraries(monero-wallet-gui
|
target_link_libraries(monero-wallet-gui
|
||||||
@@ -152,6 +158,7 @@ target_link_libraries(monero-wallet-gui
|
|||||||
${EXTRA_LIBRARIES}
|
${EXTRA_LIBRARIES}
|
||||||
${ICU_LIBRARIES}
|
${ICU_LIBRARIES}
|
||||||
openpgp
|
openpgp
|
||||||
|
qrdecoder
|
||||||
translations
|
translations
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -164,13 +171,15 @@ if(X11_FOUND)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(WITH_SCANNER)
|
if(WITH_SCANNER)
|
||||||
target_link_libraries(monero-wallet-gui
|
target_link_libraries(monero-wallet-gui qrscanner)
|
||||||
${ZBAR_LIBRARIES}
|
if(LINUX AND NOT ANDROID)
|
||||||
jpeg
|
target_link_libraries(monero-wallet-gui
|
||||||
v4l2
|
jpeg
|
||||||
v4lconvert
|
v4l2
|
||||||
rt
|
v4lconvert
|
||||||
)
|
rt
|
||||||
|
)
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_custom_command(TARGET monero-wallet-gui POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:daemon> $<TARGET_FILE_DIR:monero-wallet-gui>)
|
add_custom_command(TARGET monero-wallet-gui POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:daemon> $<TARGET_FILE_DIR:monero-wallet-gui>)
|
||||||
@@ -178,5 +187,5 @@ add_custom_command(TARGET monero-wallet-gui POST_BUILD COMMAND ${CMAKE_COMMAND}
|
|||||||
include(Deploy)
|
include(Deploy)
|
||||||
|
|
||||||
install(TARGETS monero-wallet-gui
|
install(TARGETS monero-wallet-gui
|
||||||
DESTINATION ${CMAKE_INSTALL_PREFIX}
|
DESTINATION bin
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,4 +1,21 @@
|
|||||||
file(GLOB_RECURSE SRC_SOURCES *.cpp)
|
add_library(qrdecoder STATIC
|
||||||
file(GLOB_RECURSE SRC_HEADERS *.h)
|
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.
|
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
#include "QrCodeScanner.h"
|
#include "QrCodeScanner.h"
|
||||||
#include <WalletManager.h>
|
|
||||||
#include <QVideoProbe>
|
#include <QVideoProbe>
|
||||||
#include <QCamera>
|
#include <QCamera>
|
||||||
|
|
||||||
@@ -40,7 +39,7 @@ QrCodeScanner::QrCodeScanner(QObject *parent)
|
|||||||
m_probe = new QVideoProbe(this);
|
m_probe = new QVideoProbe(this);
|
||||||
m_thread = new QrScanThread(this);
|
m_thread = new QrScanThread(this);
|
||||||
m_thread->start();
|
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)));
|
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)));
|
connect(m_probe, SIGNAL(videoFrameProbed(QVideoFrame)), this, SLOT(processFrame(QVideoFrame)));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,8 +56,7 @@ public Q_SLOTS:
|
|||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void enabledChanged();
|
void enabledChanged();
|
||||||
|
|
||||||
void decoded(int type, const QString &data);
|
void decoded(const QString &data);
|
||||||
void decode(int type, const QString &data);
|
|
||||||
void notifyError(const QString &error, bool warning = false);
|
void notifyError(const QString &error, bool warning = false);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|||||||
@@ -38,62 +38,15 @@ QrScanThread::QrScanThread(QObject *parent)
|
|||||||
: QThread(parent)
|
: QThread(parent)
|
||||||
,m_running(true)
|
,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)
|
void QrScanThread::processQImage(const QImage &qimg)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
m_image = QSharedPointer<zbar::Image>(new zbar::Image());
|
for (const std::string &code : m_decoder.decode(qimg))
|
||||||
if( ! zimageFromQImage(qimg, *m_image) )
|
{
|
||||||
return;
|
emit decoded(QString::fromStdString(code));
|
||||||
processZImage(*m_image);
|
}
|
||||||
}
|
}
|
||||||
catch(std::exception &e) {
|
catch(std::exception &e) {
|
||||||
qDebug() << "ERROR: " << e.what();
|
qDebug() << "ERROR: " << e.what();
|
||||||
|
|||||||
@@ -35,9 +35,10 @@
|
|||||||
#include <QEvent>
|
#include <QEvent>
|
||||||
#include <QVideoFrame>
|
#include <QVideoFrame>
|
||||||
#include <QCamera>
|
#include <QCamera>
|
||||||
#include <zbar.h>
|
|
||||||
|
|
||||||
class QrScanThread : public QThread, public zbar::Image::Handler
|
#include "Decoder.h"
|
||||||
|
|
||||||
|
class QrScanThread : public QThread
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
@@ -47,20 +48,16 @@ public:
|
|||||||
virtual void stop();
|
virtual void stop();
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void decoded(int type, const QString &data);
|
void decoded(const QString &data);
|
||||||
void notifyError(const QString &error, bool warning = false);
|
void notifyError(const QString &error, bool warning = false);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void run();
|
virtual void run();
|
||||||
void processVideoFrame(const QVideoFrame &);
|
void processVideoFrame(const QVideoFrame &);
|
||||||
void processQImage(const QImage &);
|
void processQImage(const QImage &);
|
||||||
void processZImage(zbar::Image &image);
|
|
||||||
virtual void image_callback(zbar::Image &image);
|
|
||||||
bool zimageFromQImage(const QImage&, zbar::Image &);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
zbar::ImageScanner m_scanner;
|
QrDecoder m_decoder;
|
||||||
QSharedPointer<zbar::Image> m_image;
|
|
||||||
bool m_running;
|
bool m_running;
|
||||||
QMutex m_mutex;
|
QMutex m_mutex;
|
||||||
QWaitCondition m_waitCondition;
|
QWaitCondition m_waitCondition;
|
||||||
|
|||||||
@@ -27,6 +27,7 @@
|
|||||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
#include "DaemonManager.h"
|
#include "DaemonManager.h"
|
||||||
|
#include "common/util.h"
|
||||||
#include <QElapsedTimer>
|
#include <QElapsedTimer>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QMutexLocker>
|
#include <QMutexLocker>
|
||||||
@@ -47,24 +48,7 @@ namespace {
|
|||||||
static const int DAEMON_START_TIMEOUT_SECONDS = 120;
|
static const int DAEMON_START_TIMEOUT_SECONDS = 120;
|
||||||
}
|
}
|
||||||
|
|
||||||
DaemonManager * DaemonManager::m_instance = nullptr;
|
bool DaemonManager::start(const QString &flags, NetworkType::Type nettype, const QString &dataDir, const QString &bootstrapNodeAddress, bool noSync /* = false*/, bool pruneBlockchain /* = false*/)
|
||||||
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*/)
|
|
||||||
{
|
{
|
||||||
if (!QFileInfo(m_monerod).isFile())
|
if (!QFileInfo(m_monerod).isFile())
|
||||||
{
|
{
|
||||||
@@ -85,12 +69,6 @@ bool DaemonManager::start(const QString &flags, NetworkType::Type nettype, const
|
|||||||
else if (nettype == NetworkType::STAGENET)
|
else if (nettype == NetworkType::STAGENET)
|
||||||
arguments << "--stagenet";
|
arguments << "--stagenet";
|
||||||
|
|
||||||
foreach (const QString &str, m_clArgs) {
|
|
||||||
qDebug() << QString(" [%1] ").arg(str);
|
|
||||||
if (!str.isEmpty())
|
|
||||||
arguments << str;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Custom startup flags for daemon
|
// Custom startup flags for daemon
|
||||||
foreach (const QString &str, flags.split(" ")) {
|
foreach (const QString &str, flags.split(" ")) {
|
||||||
qDebug() << QString(" [%1] ").arg(str);
|
qDebug() << QString(" [%1] ").arg(str);
|
||||||
@@ -108,11 +86,18 @@ bool DaemonManager::start(const QString &flags, NetworkType::Type nettype, const
|
|||||||
arguments << "--bootstrap-daemon-address" << bootstrapNodeAddress;
|
arguments << "--bootstrap-daemon-address" << bootstrapNodeAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pruneBlockchain) {
|
||||||
|
if (!checkLmdbExists(dataDir)) { // check that DB has not already been created
|
||||||
|
arguments << "--prune-blockchain";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (noSync) {
|
if (noSync) {
|
||||||
arguments << "--no-sync";
|
arguments << "--no-sync";
|
||||||
}
|
}
|
||||||
|
|
||||||
arguments << "--check-updates" << "disabled";
|
arguments << "--check-updates" << "disabled";
|
||||||
|
arguments << "--non-interactive";
|
||||||
|
|
||||||
// --max-concurrency based on threads available.
|
// --max-concurrency based on threads available.
|
||||||
int32_t concurrency = qMax(1, QThread::idealThreadCount() / 2);
|
int32_t concurrency = qMax(1, QThread::idealThreadCount() / 2);
|
||||||
@@ -345,6 +330,13 @@ QVariantMap DaemonManager::validateDataDir(const QString &dataDir) const
|
|||||||
return result;
|
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)
|
DaemonManager::DaemonManager(QObject *parent)
|
||||||
: QObject(parent)
|
: QObject(parent)
|
||||||
, m_scheduler(this)
|
, m_scheduler(this)
|
||||||
|
|||||||
@@ -44,10 +44,10 @@ class DaemonManager : public QObject
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
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, bool pruneBlockchain = false);
|
||||||
|
|
||||||
Q_INVOKABLE bool start(const QString &flags, NetworkType::Type nettype, const QString &dataDir = "", const QString &bootstrapNodeAddress = "", bool noSync = false);
|
|
||||||
Q_INVOKABLE void stopAsync(NetworkType::Type nettype, const QJSValue& callback);
|
Q_INVOKABLE void stopAsync(NetworkType::Type nettype, const QJSValue& callback);
|
||||||
|
|
||||||
Q_INVOKABLE bool noSync() const noexcept;
|
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 sendCommandAsync(const QStringList &cmd, NetworkType::Type nettype, const QJSValue& callback) const;
|
||||||
Q_INVOKABLE void exit();
|
Q_INVOKABLE void exit();
|
||||||
Q_INVOKABLE QVariantMap validateDataDir(const QString &dataDir) const;
|
Q_INVOKABLE QVariantMap validateDataDir(const QString &dataDir) const;
|
||||||
|
Q_INVOKABLE bool checkLmdbExists(QString datadir);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@@ -76,11 +77,6 @@ public slots:
|
|||||||
void stateChanged(QProcess::ProcessState state);
|
void stateChanged(QProcess::ProcessState state);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit DaemonManager(QObject *parent = 0);
|
|
||||||
~DaemonManager();
|
|
||||||
|
|
||||||
static DaemonManager * m_instance;
|
|
||||||
static QStringList m_clArgs;
|
|
||||||
std::unique_ptr<QProcess> m_daemon;
|
std::unique_ptr<QProcess> m_daemon;
|
||||||
QMutex m_daemonMutex;
|
QMutex m_daemonMutex;
|
||||||
QString m_monerod;
|
QString m_monerod;
|
||||||
|
|||||||
@@ -78,7 +78,14 @@ void Subaddress::setLabel(quint32 accountIndex, quint32 addressIndex, const QStr
|
|||||||
|
|
||||||
void Subaddress::refresh(quint32 accountIndex) const
|
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();
|
getAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -104,10 +104,7 @@ void Wallet::updateConnectionStatusAsync()
|
|||||||
setConnectionStatus(ConnectionStatus_Connecting);
|
setConnectionStatus(ConnectionStatus_Connecting);
|
||||||
}
|
}
|
||||||
ConnectionStatus newStatus = static_cast<ConnectionStatus>(m_walletImpl->connected());
|
ConnectionStatus newStatus = static_cast<ConnectionStatus>(m_walletImpl->connected());
|
||||||
if (newStatus != m_connectionStatus || !m_initialized) {
|
setConnectionStatus(newStatus);
|
||||||
m_initialized = true;
|
|
||||||
setConnectionStatus(newStatus);
|
|
||||||
}
|
|
||||||
// Release lock
|
// Release lock
|
||||||
m_connectionStatusRunning = false;
|
m_connectionStatusRunning = false;
|
||||||
});
|
});
|
||||||
@@ -115,8 +112,13 @@ void Wallet::updateConnectionStatusAsync()
|
|||||||
|
|
||||||
Wallet::ConnectionStatus Wallet::connected(bool forceCheck)
|
Wallet::ConnectionStatus Wallet::connected(bool forceCheck)
|
||||||
{
|
{
|
||||||
|
if (!m_initialized)
|
||||||
|
{
|
||||||
|
return ConnectionStatus_Connecting;
|
||||||
|
}
|
||||||
|
|
||||||
// cache connection status
|
// 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";
|
qDebug() << "Checking connection status";
|
||||||
m_connectionStatusRunning = true;
|
m_connectionStatusRunning = true;
|
||||||
m_connectionStatusTime.restart();
|
m_connectionStatusTime.restart();
|
||||||
@@ -277,14 +279,25 @@ void Wallet::initAsync(
|
|||||||
{
|
{
|
||||||
qDebug() << "initAsync: " + daemonAddress;
|
qDebug() << "initAsync: " + daemonAddress;
|
||||||
const auto future = m_scheduler.run([this, daemonAddress, trustedDaemon, upperTransactionLimit, isRecovering, isRecoveringFromDevice, restoreHeight, proxyAddress] {
|
const auto future = m_scheduler.run([this, daemonAddress, trustedDaemon, upperTransactionLimit, isRecovering, isRecoveringFromDevice, restoreHeight, proxyAddress] {
|
||||||
bool success = init(daemonAddress, trustedDaemon, upperTransactionLimit, isRecovering, isRecoveringFromDevice, restoreHeight, proxyAddress);
|
m_initialized = init(
|
||||||
if (success)
|
daemonAddress,
|
||||||
|
trustedDaemon,
|
||||||
|
upperTransactionLimit,
|
||||||
|
isRecovering,
|
||||||
|
isRecoveringFromDevice,
|
||||||
|
restoreHeight,
|
||||||
|
proxyAddress);
|
||||||
|
if (m_initialized)
|
||||||
{
|
{
|
||||||
emit walletCreationHeightChanged();
|
emit walletCreationHeightChanged();
|
||||||
qDebug() << "init async finished - starting refresh";
|
qDebug() << "init async finished - starting refresh";
|
||||||
connected(true);
|
connected(true);
|
||||||
startRefresh();
|
startRefresh();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
qCritical() << "Failed to initialize the wallet";
|
||||||
|
}
|
||||||
});
|
});
|
||||||
if (future.first)
|
if (future.first)
|
||||||
{
|
{
|
||||||
@@ -519,25 +532,40 @@ void Wallet::pauseRefresh()
|
|||||||
m_refreshEnabled = false;
|
m_refreshEnabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
PendingTransaction *Wallet::createTransaction(const QString &dst_addr, const QString &payment_id,
|
PendingTransaction *Wallet::createTransaction(
|
||||||
quint64 amount, quint32 mixin_count,
|
const QVector<QString> &destinationAddresses,
|
||||||
PendingTransaction::Priority priority)
|
const QString &payment_id,
|
||||||
|
const QVector<quint64> &amounts,
|
||||||
|
quint32 mixin_count,
|
||||||
|
PendingTransaction::Priority priority)
|
||||||
{
|
{
|
||||||
|
std::vector<std::string> destinations;
|
||||||
|
for (const auto &address : destinationAddresses) {
|
||||||
|
destinations.push_back(address.toStdString());
|
||||||
|
}
|
||||||
std::set<uint32_t> subaddr_indices;
|
std::set<uint32_t> subaddr_indices;
|
||||||
Monero::PendingTransaction * ptImpl = m_walletImpl->createTransaction(
|
Monero::PendingTransaction *ptImpl = m_walletImpl->createTransactionMultDest(
|
||||||
dst_addr.toStdString(), payment_id.toStdString(), amount, mixin_count,
|
destinations,
|
||||||
static_cast<Monero::PendingTransaction::Priority>(priority), currentSubaddressAccount(), subaddr_indices);
|
payment_id.toStdString(),
|
||||||
PendingTransaction * result = new PendingTransaction(ptImpl,0);
|
std::vector<uint64_t>(amounts.begin(), amounts.end()),
|
||||||
|
mixin_count,
|
||||||
|
static_cast<Monero::PendingTransaction::Priority>(priority),
|
||||||
|
currentSubaddressAccount(),
|
||||||
|
subaddr_indices);
|
||||||
|
PendingTransaction *result = new PendingTransaction(ptImpl, 0);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Wallet::createTransactionAsync(const QString &dst_addr, const QString &payment_id,
|
void Wallet::createTransactionAsync(
|
||||||
quint64 amount, quint32 mixin_count,
|
const QVector<QString> &destinationAddresses,
|
||||||
PendingTransaction::Priority priority)
|
const QString &payment_id,
|
||||||
|
const QVector<quint64> &amounts,
|
||||||
|
quint32 mixin_count,
|
||||||
|
PendingTransaction::Priority priority)
|
||||||
{
|
{
|
||||||
m_scheduler.run([this, dst_addr, payment_id, amount, mixin_count, priority] {
|
m_scheduler.run([this, destinationAddresses, payment_id, amounts, mixin_count, priority] {
|
||||||
PendingTransaction *tx = createTransaction(dst_addr, payment_id, amount, mixin_count, priority);
|
PendingTransaction *tx = createTransaction(destinationAddresses, payment_id, amounts, mixin_count, priority);
|
||||||
emit transactionCreated(tx, dst_addr, payment_id, mixin_count);
|
emit transactionCreated(tx, destinationAddresses, payment_id, mixin_count);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -558,7 +586,7 @@ void Wallet::createTransactionAllAsync(const QString &dst_addr, const QString &p
|
|||||||
{
|
{
|
||||||
m_scheduler.run([this, dst_addr, payment_id, mixin_count, priority] {
|
m_scheduler.run([this, dst_addr, payment_id, mixin_count, priority] {
|
||||||
PendingTransaction *tx = createTransactionAll(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 +601,7 @@ void Wallet::createSweepUnmixableTransactionAsync()
|
|||||||
{
|
{
|
||||||
m_scheduler.run([this] {
|
m_scheduler.run([this] {
|
||||||
PendingTransaction *tx = createSweepUnmixableTransaction();
|
PendingTransaction *tx = createSweepUnmixableTransaction();
|
||||||
emit transactionCreated(tx, "", "", 0);
|
emit transactionCreated(tx, {""}, "", 0);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -613,17 +641,32 @@ void Wallet::disposeTransaction(UnsignedTransaction *t)
|
|||||||
delete t;
|
delete t;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Wallet::estimateTransactionFeeAsync(const QString &destination,
|
void Wallet::estimateTransactionFeeAsync(
|
||||||
quint64 amount,
|
const QVector<QString> &destinationAddresses,
|
||||||
PendingTransaction::Priority priority,
|
const QVector<quint64> &amounts,
|
||||||
const QJSValue &callback)
|
PendingTransaction::Priority priority,
|
||||||
|
const QJSValue &callback)
|
||||||
{
|
{
|
||||||
m_scheduler.run([this, destination, amount, priority] {
|
m_scheduler.run(
|
||||||
const uint64_t fee = m_walletImpl->estimateTransactionFee(
|
[this, destinationAddresses, amounts, priority] {
|
||||||
{std::make_pair(destination.toStdString(), amount)},
|
if (destinationAddresses.size() != amounts.size())
|
||||||
static_cast<Monero::PendingTransaction::Priority>(priority));
|
{
|
||||||
return QJSValueList({QString::fromStdString(Monero::Wallet::displayAmount(fee))});
|
return QJSValueList({""});
|
||||||
}, callback);
|
}
|
||||||
|
|
||||||
|
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
|
TransactionHistory *Wallet::history() const
|
||||||
@@ -1054,6 +1097,7 @@ Wallet::Wallet(Monero::Wallet *w, QObject *parent)
|
|||||||
, m_connectionStatus(Wallet::ConnectionStatus_Disconnected)
|
, m_connectionStatus(Wallet::ConnectionStatus_Disconnected)
|
||||||
, m_connectionStatusTtl(WALLET_CONNECTION_STATUS_CACHE_TTL_SECONDS)
|
, m_connectionStatusTtl(WALLET_CONNECTION_STATUS_CACHE_TTL_SECONDS)
|
||||||
, m_disconnected(true)
|
, m_disconnected(true)
|
||||||
|
, m_initialized(false)
|
||||||
, m_currentSubaddressAccount(0)
|
, m_currentSubaddressAccount(0)
|
||||||
, m_subaddress(nullptr)
|
, m_subaddress(nullptr)
|
||||||
, m_subaddressModel(nullptr)
|
, m_subaddressModel(nullptr)
|
||||||
@@ -1074,7 +1118,6 @@ Wallet::Wallet(Monero::Wallet *w, QObject *parent)
|
|||||||
m_connectionStatusTime.start();
|
m_connectionStatusTime.start();
|
||||||
m_daemonBlockChainHeightTime.start();
|
m_daemonBlockChainHeightTime.start();
|
||||||
m_daemonBlockChainTargetHeightTime.start();
|
m_daemonBlockChainTargetHeightTime.start();
|
||||||
m_initialized = false;
|
|
||||||
m_connectionStatusRunning = false;
|
m_connectionStatusRunning = false;
|
||||||
m_daemonUsername = "";
|
m_daemonUsername = "";
|
||||||
m_daemonPassword = "";
|
m_daemonPassword = "";
|
||||||
@@ -1086,6 +1129,8 @@ Wallet::~Wallet()
|
|||||||
{
|
{
|
||||||
qDebug("~Wallet: Closing wallet");
|
qDebug("~Wallet: Closing wallet");
|
||||||
|
|
||||||
|
pauseRefresh();
|
||||||
|
m_walletImpl->stop();
|
||||||
m_scheduler.shutdownWaitForFinished();
|
m_scheduler.shutdownWaitForFinished();
|
||||||
|
|
||||||
delete m_addressBook;
|
delete m_addressBook;
|
||||||
@@ -1116,8 +1161,8 @@ Wallet::~Wallet()
|
|||||||
void Wallet::startRefreshThread()
|
void Wallet::startRefreshThread()
|
||||||
{
|
{
|
||||||
const auto future = m_scheduler.run([this] {
|
const auto future = m_scheduler.run([this] {
|
||||||
static constexpr const size_t refreshIntervalSec = 10;
|
constexpr const std::chrono::seconds refreshInterval{10};
|
||||||
static constexpr const size_t intervalResolutionMs = 100;
|
constexpr const std::chrono::milliseconds intervalResolution{100};
|
||||||
|
|
||||||
auto last = std::chrono::steady_clock::now();
|
auto last = std::chrono::steady_clock::now();
|
||||||
while (!m_scheduler.stopping())
|
while (!m_scheduler.stopping())
|
||||||
@@ -1125,15 +1170,15 @@ void Wallet::startRefreshThread()
|
|||||||
if (m_refreshEnabled)
|
if (m_refreshEnabled)
|
||||||
{
|
{
|
||||||
const auto now = std::chrono::steady_clock::now();
|
const auto now = std::chrono::steady_clock::now();
|
||||||
const auto elapsed = std::chrono::duration_cast<std::chrono::seconds>(now - last).count();
|
const auto elapsed = now - last;
|
||||||
if (elapsed >= refreshIntervalSec)
|
if (elapsed >= refreshInterval)
|
||||||
{
|
{
|
||||||
refresh(false);
|
refresh(false);
|
||||||
last = std::chrono::steady_clock::now();
|
last = std::chrono::steady_clock::now();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(intervalResolutionMs));
|
std::this_thread::sleep_for(intervalResolution);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (!future.first)
|
if (!future.first)
|
||||||
|
|||||||
@@ -29,6 +29,8 @@
|
|||||||
#ifndef WALLET_H
|
#ifndef WALLET_H
|
||||||
#define WALLET_H
|
#define WALLET_H
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
#include <QElapsedTimer>
|
#include <QElapsedTimer>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QMutex>
|
#include <QMutex>
|
||||||
@@ -214,15 +216,13 @@ public:
|
|||||||
Q_INVOKABLE void startRefresh();
|
Q_INVOKABLE void startRefresh();
|
||||||
Q_INVOKABLE void pauseRefresh();
|
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
|
//! creates async transaction
|
||||||
Q_INVOKABLE void createTransactionAsync(const QString &dst_addr, const QString &payment_id,
|
Q_INVOKABLE void createTransactionAsync(
|
||||||
quint64 amount, quint32 mixin_count,
|
const QVector<QString> &destinationAddresses,
|
||||||
PendingTransaction::Priority priority);
|
const QString &payment_id,
|
||||||
|
const QVector<quint64> &amounts,
|
||||||
|
quint32 mixin_count,
|
||||||
|
PendingTransaction::Priority priority);
|
||||||
|
|
||||||
//! creates transaction with all outputs
|
//! creates transaction with all outputs
|
||||||
Q_INVOKABLE PendingTransaction * createTransactionAll(const QString &dst_addr, const QString &payment_id,
|
Q_INVOKABLE PendingTransaction * createTransactionAll(const QString &dst_addr, const QString &payment_id,
|
||||||
@@ -253,10 +253,11 @@ public:
|
|||||||
//! deletes unsigned transaction and frees memory
|
//! deletes unsigned transaction and frees memory
|
||||||
Q_INVOKABLE void disposeTransaction(UnsignedTransaction * t);
|
Q_INVOKABLE void disposeTransaction(UnsignedTransaction * t);
|
||||||
|
|
||||||
Q_INVOKABLE void estimateTransactionFeeAsync(const QString &destination,
|
Q_INVOKABLE void estimateTransactionFeeAsync(
|
||||||
quint64 amount,
|
const QVector<QString> &destinationAddresses,
|
||||||
PendingTransaction::Priority priority,
|
const QVector<quint64> &amounts,
|
||||||
const QJSValue &callback);
|
PendingTransaction::Priority priority,
|
||||||
|
const QJSValue &callback);
|
||||||
|
|
||||||
//! returns transaction history
|
//! returns transaction history
|
||||||
TransactionHistory * history() const;
|
TransactionHistory * history() const;
|
||||||
@@ -380,7 +381,11 @@ signals:
|
|||||||
void deviceShowAddressShowed();
|
void deviceShowAddressShowed();
|
||||||
|
|
||||||
// emitted when transaction is created async
|
// 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 connectionStatusChanged(int status) const;
|
||||||
void currentSubaddressAccountChanged() const;
|
void currentSubaddressAccountChanged() const;
|
||||||
@@ -413,6 +418,13 @@ private:
|
|||||||
quint64 restoreHeight,
|
quint64 restoreHeight,
|
||||||
const QString& proxyAddress);
|
const QString& proxyAddress);
|
||||||
|
|
||||||
|
PendingTransaction *createTransaction(
|
||||||
|
const QVector<QString> &destinationAddresses,
|
||||||
|
const QString &payment_id,
|
||||||
|
const QVector<quint64> &amounts,
|
||||||
|
quint32 mixin_count,
|
||||||
|
PendingTransaction::Priority priority);
|
||||||
|
|
||||||
bool disconnected() const;
|
bool disconnected() const;
|
||||||
bool refreshing() const;
|
bool refreshing() const;
|
||||||
void refreshingSet(bool value);
|
void refreshingSet(bool value);
|
||||||
@@ -444,7 +456,7 @@ private:
|
|||||||
int m_connectionStatusTtl;
|
int m_connectionStatusTtl;
|
||||||
mutable QElapsedTimer m_connectionStatusTime;
|
mutable QElapsedTimer m_connectionStatusTime;
|
||||||
bool m_disconnected;
|
bool m_disconnected;
|
||||||
mutable bool m_initialized;
|
std::atomic<bool> m_initialized;
|
||||||
uint32_t m_currentSubaddressAccount;
|
uint32_t m_currentSubaddressAccount;
|
||||||
Subaddress * m_subaddress;
|
Subaddress * m_subaddress;
|
||||||
mutable SubaddressModel * m_subaddressModel;
|
mutable SubaddressModel * m_subaddressModel;
|
||||||
|
|||||||
@@ -251,7 +251,7 @@ QString WalletManager::errorString() const
|
|||||||
return tr("Unknown error");
|
return tr("Unknown error");
|
||||||
}
|
}
|
||||||
|
|
||||||
quint64 WalletManager::maximumAllowedAmount() const
|
quint64 WalletManager::maximumAllowedAmount()
|
||||||
{
|
{
|
||||||
return Monero::Wallet::maximumAllowedAmount();
|
return Monero::Wallet::maximumAllowedAmount();
|
||||||
}
|
}
|
||||||
@@ -266,7 +266,7 @@ QString WalletManager::displayAmount(quint64 amount)
|
|||||||
return QString::fromStdString(Monero::Wallet::displayAmount(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());
|
return Monero::Wallet::amountFromString(amount.toStdString());
|
||||||
}
|
}
|
||||||
@@ -276,6 +276,17 @@ quint64 WalletManager::amountFromDouble(double amount) const
|
|||||||
return Monero::Wallet::amountFromDouble(amount);
|
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
|
bool WalletManager::paymentIdValid(const QString &payment_id) const
|
||||||
{
|
{
|
||||||
return Monero::Wallet::paymentIdValid(payment_id.toStdString());
|
return Monero::Wallet::paymentIdValid(payment_id.toStdString());
|
||||||
|
|||||||
@@ -133,9 +133,10 @@ public:
|
|||||||
|
|
||||||
//! since we can't call static method from QML, move it to this class
|
//! since we can't call static method from QML, move it to this class
|
||||||
Q_INVOKABLE static QString displayAmount(quint64 amount);
|
Q_INVOKABLE static QString displayAmount(quint64 amount);
|
||||||
Q_INVOKABLE quint64 amountFromString(const QString &amount) const;
|
Q_INVOKABLE static quint64 amountFromString(const QString &amount);
|
||||||
Q_INVOKABLE quint64 amountFromDouble(double amount) const;
|
Q_INVOKABLE quint64 amountFromDouble(double amount) const;
|
||||||
Q_INVOKABLE quint64 maximumAllowedAmount() const;
|
Q_INVOKABLE static QString amountsSumFromStrings(const QVector<QString> &amounts);
|
||||||
|
Q_INVOKABLE static quint64 maximumAllowedAmount();
|
||||||
|
|
||||||
// QML JS engine doesn't support unsigned integers
|
// QML JS engine doesn't support unsigned integers
|
||||||
Q_INVOKABLE QString maximumAllowedAmountAsString() const;
|
Q_INVOKABLE QString maximumAllowedAmountAsString() const;
|
||||||
|
|||||||
@@ -117,13 +117,14 @@ Logger::Logger(QCoreApplication &parent, QString userDefinedLogFilePath)
|
|||||||
c.setGlobally(el::ConfigurationType::ToFile, "false");
|
c.setGlobally(el::ConfigurationType::ToFile, "false");
|
||||||
c.setGlobally(el::ConfigurationType::ToStandardOutput, "true");
|
c.setGlobally(el::ConfigurationType::ToStandardOutput, "true");
|
||||||
el::Loggers::setDefaultConfigurations(c, true);
|
el::Loggers::setDefaultConfigurations(c, true);
|
||||||
|
qInstallMessageHandler(messageHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Logger::resetLogFilePath(bool portable)
|
void Logger::resetLogFilePath(bool portable)
|
||||||
{
|
{
|
||||||
m_logFilePath = QDir::toNativeSeparators(getLogPath(m_userDefinedLogFilePath, portable));
|
m_logFilePath = QDir::toNativeSeparators(getLogPath(m_userDefinedLogFilePath, portable));
|
||||||
Monero::Wallet::init(m_applicationFilePath.c_str(), "monero-wallet-gui", m_logFilePath.toStdString(), true);
|
Monero::Wallet::init(m_applicationFilePath.c_str(), "monero-wallet-gui", m_logFilePath.toStdString(), true);
|
||||||
qInstallMessageHandler(messageHandler);
|
qWarning() << "Logging to" << m_logFilePath;
|
||||||
emit logFilePathChanged();
|
emit logFilePathChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -120,6 +120,10 @@ Q_IMPORT_PLUGIN(QQmlDebugServerFactory)
|
|||||||
Q_IMPORT_PLUGIN(QTcpServerConnectionFactory)
|
Q_IMPORT_PLUGIN(QTcpServerConnectionFactory)
|
||||||
Q_IMPORT_PLUGIN(QGenericEnginePlugin)
|
Q_IMPORT_PLUGIN(QGenericEnginePlugin)
|
||||||
|
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
|
||||||
|
Q_IMPORT_PLUGIN(QtQmlPlugin)
|
||||||
|
#endif
|
||||||
|
Q_IMPORT_PLUGIN(QtQmlModelsPlugin)
|
||||||
Q_IMPORT_PLUGIN(QtQuick2Plugin)
|
Q_IMPORT_PLUGIN(QtQuick2Plugin)
|
||||||
Q_IMPORT_PLUGIN(QtQuickLayoutsPlugin)
|
Q_IMPORT_PLUGIN(QtQuickLayoutsPlugin)
|
||||||
Q_IMPORT_PLUGIN(QtGraphicalEffectsPlugin)
|
Q_IMPORT_PLUGIN(QtGraphicalEffectsPlugin)
|
||||||
@@ -156,8 +160,6 @@ int main(int argc, char *argv[])
|
|||||||
// platform dependant settings
|
// platform dependant settings
|
||||||
#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS)
|
#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS)
|
||||||
bool isDesktop = true;
|
bool isDesktop = true;
|
||||||
#elif defined(Q_OS_LINUX)
|
|
||||||
bool isLinux = true;
|
|
||||||
#elif defined(Q_OS_ANDROID)
|
#elif defined(Q_OS_ANDROID)
|
||||||
bool isAndroid = true;
|
bool isAndroid = true;
|
||||||
#elif defined(Q_OS_IOS)
|
#elif defined(Q_OS_IOS)
|
||||||
@@ -179,8 +181,8 @@ int main(int argc, char *argv[])
|
|||||||
// disable "QApplication: invalid style override passed" warning
|
// disable "QApplication: invalid style override passed" warning
|
||||||
if (isDesktop) qputenv("QT_STYLE_OVERRIDE", "fusion");
|
if (isDesktop) qputenv("QT_STYLE_OVERRIDE", "fusion");
|
||||||
#ifdef Q_OS_LINUX
|
#ifdef Q_OS_LINUX
|
||||||
// force platform xcb
|
// platform xcb by default
|
||||||
if (isDesktop) qputenv("QT_QPA_PLATFORM", "xcb");
|
if (isDesktop && qEnvironmentVariableIsEmpty("QT_QPA_PLATFORM")) qputenv("QT_QPA_PLATFORM", "xcb");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// enable High DPI scaling
|
// enable High DPI scaling
|
||||||
@@ -189,6 +191,12 @@ int main(int argc, char *argv[])
|
|||||||
// Turn off colors in monerod log output.
|
// Turn off colors in monerod log output.
|
||||||
qputenv("TERM", "goaway");
|
qputenv("TERM", "goaway");
|
||||||
|
|
||||||
|
#if defined(Q_OS_MACOS)
|
||||||
|
QDir::setCurrent(QDir(MacOSHelper::bundlePath() + QDir::separator() + "..").canonicalPath());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
qputenv("QML_DISABLE_DISK_CACHE", "1");
|
||||||
|
|
||||||
MainApp app(argc, argv);
|
MainApp app(argc, argv);
|
||||||
|
|
||||||
#if defined(Q_OS_WIN)
|
#if defined(Q_OS_WIN)
|
||||||
@@ -277,7 +285,6 @@ Verify update binary using 'shasum'-compatible (SHA256 algo) output signed by tw
|
|||||||
if (logLevelOk && logLevel >= 0 && logLevel <= Monero::WalletManagerFactory::LogLevel_Max){
|
if (logLevelOk && logLevel >= 0 && logLevel <= Monero::WalletManagerFactory::LogLevel_Max){
|
||||||
Monero::WalletManagerFactory::setLogLevel(logLevel);
|
Monero::WalletManagerFactory::setLogLevel(logLevel);
|
||||||
}
|
}
|
||||||
qWarning().noquote() << "app startd" << "(log: " + logger.logFilePath() + ")";
|
|
||||||
|
|
||||||
if (parser.isSet(verifyUpdateOption))
|
if (parser.isSet(verifyUpdateOption))
|
||||||
{
|
{
|
||||||
@@ -305,11 +312,6 @@ Verify update binary using 'shasum'-compatible (SHA256 algo) output signed by tw
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Desktop entry
|
|
||||||
#ifdef Q_OS_LINUX
|
|
||||||
registerXdgMime(app);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
IPC *ipc = new IPC(&app);
|
IPC *ipc = new IPC(&app);
|
||||||
QStringList posArgs = parser.positionalArguments();
|
QStringList posArgs = parser.positionalArguments();
|
||||||
|
|
||||||
@@ -326,10 +328,6 @@ Verify update binary using 'shasum'-compatible (SHA256 algo) output signed by tw
|
|||||||
// start listening
|
// start listening
|
||||||
QTimer::singleShot(0, ipc, SLOT(bind()));
|
QTimer::singleShot(0, ipc, SLOT(bind()));
|
||||||
|
|
||||||
#if defined(Q_OS_MACOS)
|
|
||||||
QDir::setCurrent(QDir(MacOSHelper::bundlePath() + QDir::separator() + "..").canonicalPath());
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// screen settings
|
// screen settings
|
||||||
// Mobile is designed on 128dpi
|
// Mobile is designed on 128dpi
|
||||||
qreal ref_dpi = 128;
|
qreal ref_dpi = 128;
|
||||||
@@ -454,8 +452,8 @@ Verify update binary using 'shasum'-compatible (SHA256 algo) output signed by tw
|
|||||||
|
|
||||||
// Exclude daemon manager from IOS
|
// Exclude daemon manager from IOS
|
||||||
#ifndef Q_OS_IOS
|
#ifndef Q_OS_IOS
|
||||||
DaemonManager * daemonManager = DaemonManager::instance();
|
DaemonManager daemonManager;
|
||||||
engine.rootContext()->setContextProperty("daemonManager", daemonManager);
|
engine.rootContext()->setContextProperty("daemonManager", &daemonManager);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
engine.rootContext()->setContextProperty("isWindows", isWindows);
|
engine.rootContext()->setContextProperty("isWindows", isWindows);
|
||||||
|
|||||||
@@ -27,10 +27,16 @@
|
|||||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
#include "oshelper.h"
|
#include "oshelper.h"
|
||||||
|
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
|
#include <QGuiApplication>
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
|
#include <QScreen>
|
||||||
#include <QStandardPaths>
|
#include <QStandardPaths>
|
||||||
#include <QTemporaryFile>
|
#include <QTemporaryFile>
|
||||||
|
#include <QWindow>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QDesktopServices>
|
#include <QDesktopServices>
|
||||||
@@ -46,13 +52,49 @@
|
|||||||
#endif
|
#endif
|
||||||
#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)
|
#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)
|
||||||
#include <X11/XKBlib.h>
|
#include <X11/XKBlib.h>
|
||||||
|
#undef Bool
|
||||||
#undef KeyPress
|
#undef KeyPress
|
||||||
#undef KeyRelease
|
#undef KeyRelease
|
||||||
#undef FocusIn
|
#undef FocusIn
|
||||||
#undef FocusOut
|
#undef FocusOut
|
||||||
// #undef those Xlib #defines that conflict with QEvent::Type enum
|
// #undef those Xlib #defines that conflict with QEvent::Type enum
|
||||||
|
#include "qt/utils.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "QR-Code-scanner/Decoder.h"
|
||||||
|
#include "qt/ScopeGuard.h"
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
|
QPixmap screenshot()
|
||||||
|
{
|
||||||
|
#ifdef Q_OS_MAC
|
||||||
|
return MacOSHelper::screenshot();
|
||||||
|
#else
|
||||||
|
std::unordered_set<QWindow *> hidden;
|
||||||
|
const QWindowList windows = QGuiApplication::allWindows();
|
||||||
|
for (QWindow *window : windows)
|
||||||
|
{
|
||||||
|
if (window->isVisible())
|
||||||
|
{
|
||||||
|
hidden.emplace(window);
|
||||||
|
window->hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const auto unhide = sg::make_scope_guard([&hidden]() {
|
||||||
|
for (QWindow *window : hidden)
|
||||||
|
{
|
||||||
|
window->show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return QGuiApplication::primaryScreen()->grabWindow(0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
#if defined(Q_OS_WIN)
|
#if defined(Q_OS_WIN)
|
||||||
bool openFolderAndSelectItem(const QString &filePath)
|
bool openFolderAndSelectItem(const QString &filePath)
|
||||||
{
|
{
|
||||||
@@ -85,11 +127,38 @@ OSHelper::OSHelper(QObject *parent) : QObject(parent)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OSHelper::createDesktopEntry() const
|
||||||
|
{
|
||||||
|
#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)
|
||||||
|
registerXdgMime();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
QString OSHelper::downloadLocation() const
|
QString OSHelper::downloadLocation() const
|
||||||
{
|
{
|
||||||
return QStandardPaths::writableLocation(QStandardPaths::DownloadLocation);
|
return QStandardPaths::writableLocation(QStandardPaths::DownloadLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QList<QString> OSHelper::grabQrCodesFromScreen() const
|
||||||
|
{
|
||||||
|
QList<QString> codes;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
const QImage image = screenshot().toImage();
|
||||||
|
const std::vector<std::string> decoded = QrDecoder().decode(image);
|
||||||
|
std::for_each(decoded.begin(), decoded.end(), [&codes](const std::string &code) {
|
||||||
|
codes.push_back(QString::fromStdString(code));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (const std::exception &e)
|
||||||
|
{
|
||||||
|
qWarning() << e.what();
|
||||||
|
}
|
||||||
|
|
||||||
|
return codes;
|
||||||
|
}
|
||||||
|
|
||||||
bool OSHelper::openContainingFolder(const QString &filePath) const
|
bool OSHelper::openContainingFolder(const QString &filePath) const
|
||||||
{
|
{
|
||||||
QString canonicalFilePath = QFileInfo(filePath).canonicalFilePath();
|
QString canonicalFilePath = QFileInfo(filePath).canonicalFilePath();
|
||||||
@@ -154,6 +223,7 @@ bool OSHelper::isCapsLock() const
|
|||||||
unsigned n;
|
unsigned n;
|
||||||
XkbGetIndicatorState(d, XkbUseCoreKbd, &n);
|
XkbGetIndicatorState(d, XkbUseCoreKbd, &n);
|
||||||
caps_state = (n & 0x01) == 1;
|
caps_state = (n & 0x01) == 1;
|
||||||
|
XCloseDisplay(d);
|
||||||
}
|
}
|
||||||
return caps_state;
|
return caps_state;
|
||||||
#elif defined(Q_OS_MAC)
|
#elif defined(Q_OS_MAC)
|
||||||
|
|||||||
@@ -29,7 +29,9 @@
|
|||||||
#ifndef OSHELPER_H
|
#ifndef OSHELPER_H
|
||||||
#define OSHELPER_H
|
#define OSHELPER_H
|
||||||
|
|
||||||
|
#include <QList>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
#include <QString>
|
||||||
/**
|
/**
|
||||||
* @brief The OSHelper class - exports to QML some OS-related functions
|
* @brief The OSHelper class - exports to QML some OS-related functions
|
||||||
*/
|
*/
|
||||||
@@ -41,7 +43,9 @@ class OSHelper : public QObject
|
|||||||
public:
|
public:
|
||||||
explicit OSHelper(QObject *parent = 0);
|
explicit OSHelper(QObject *parent = 0);
|
||||||
|
|
||||||
|
Q_INVOKABLE void createDesktopEntry() const;
|
||||||
Q_INVOKABLE QString downloadLocation() const;
|
Q_INVOKABLE QString downloadLocation() const;
|
||||||
|
Q_INVOKABLE QList<QString> grabQrCodesFromScreen() const;
|
||||||
Q_INVOKABLE bool openContainingFolder(const QString &filePath) const;
|
Q_INVOKABLE bool openContainingFolder(const QString &filePath) const;
|
||||||
Q_INVOKABLE QString openSaveFileDialog(const QString &title, const QString &folder, const QString &filename) const;
|
Q_INVOKABLE QString openSaveFileDialog(const QString &title, const QString &folder, const QString &filename) const;
|
||||||
Q_INVOKABLE QString temporaryFilename() const;
|
Q_INVOKABLE QString temporaryFilename() const;
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
file(GLOB_RECURSE SOURCES *.cpp)
|
file(GLOB_RECURSE SOURCES *.cpp)
|
||||||
file(GLOB_RECURSE HEADERS *.h)
|
file(GLOB_RECURSE HEADERS *.h)
|
||||||
|
|
||||||
find_library(GCRYPT_LIBRARY gcrypt)
|
find_library(GCRYPT_LIBRARY gcrypt REQUIRED)
|
||||||
find_library(GPG_ERROR_LIBRARY gpg-error)
|
find_path(GCRYPT_INCLUDE_DIR gcrypt.h REQUIRED)
|
||||||
|
|
||||||
|
find_library(GPG_ERROR_LIBRARY gpg-error REQUIRED)
|
||||||
|
|
||||||
add_library(openpgp
|
add_library(openpgp
|
||||||
${SOURCES}
|
${SOURCES}
|
||||||
@@ -10,7 +12,8 @@ add_library(openpgp
|
|||||||
|
|
||||||
target_include_directories(openpgp
|
target_include_directories(openpgp
|
||||||
PUBLIC
|
PUBLIC
|
||||||
${CMAKE_SOURCE_DIR}/monero/contrib/epee/include)
|
${CMAKE_SOURCE_DIR}/monero/contrib/epee/include
|
||||||
|
${GCRYPT_INCLUDE_DIR})
|
||||||
|
|
||||||
target_link_libraries(openpgp
|
target_link_libraries(openpgp
|
||||||
PUBLIC
|
PUBLIC
|
||||||
|
|||||||
@@ -1,8 +1,16 @@
|
|||||||
#include "FutureScheduler.h"
|
#include "FutureScheduler.h"
|
||||||
|
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
#include <QThreadPool>
|
||||||
|
|
||||||
FutureScheduler::FutureScheduler(QObject *parent)
|
FutureScheduler::FutureScheduler(QObject *parent)
|
||||||
: QObject(parent), Alive(0), Stopping(false)
|
: QObject(parent), Alive(0), Stopping(false)
|
||||||
{
|
{
|
||||||
|
static std::once_flag once;
|
||||||
|
std::call_once(once, []() {
|
||||||
|
QThreadPool::globalInstance()->setMaxThreadCount(4);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
FutureScheduler::~FutureScheduler()
|
FutureScheduler::~FutureScheduler()
|
||||||
|
|||||||
@@ -179,13 +179,13 @@ bool MoneroSettings::portable() const
|
|||||||
return this->m_settings && this->m_settings->fileName() == portableFilePath();
|
return this->m_settings && this->m_settings->fileName() == portableFilePath();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MoneroSettings::portableConfigExists() const
|
bool MoneroSettings::portableConfigExists()
|
||||||
{
|
{
|
||||||
QFileInfo info(portableFilePath());
|
QFileInfo info(portableFilePath());
|
||||||
return info.exists() && info.isFile();
|
return info.exists() && info.isFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString MoneroSettings::portableFilePath() const
|
QString MoneroSettings::portableFilePath()
|
||||||
{
|
{
|
||||||
static QString filename(QDir(portableFolderName()).absoluteFilePath("settings.ini"));
|
static QString filename(QDir(portableFolderName()).absoluteFilePath("settings.ini"));
|
||||||
return filename;
|
return filename;
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ public:
|
|||||||
Q_INVOKABLE void setWritable(bool enabled);
|
Q_INVOKABLE void setWritable(bool enabled);
|
||||||
|
|
||||||
static QString portableFolderName();
|
static QString portableFolderName();
|
||||||
|
static bool portableConfigExists();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void _q_propertyChanged();
|
void _q_propertyChanged();
|
||||||
@@ -84,8 +85,7 @@ private:
|
|||||||
void store();
|
void store();
|
||||||
|
|
||||||
bool portable() const;
|
bool portable() const;
|
||||||
bool portableConfigExists() const;
|
static QString portableFilePath();
|
||||||
QString portableFilePath() const;
|
|
||||||
std::unique_ptr<QSettings> portableSettings() const;
|
std::unique_ptr<QSettings> portableSettings() const;
|
||||||
std::unique_ptr<QSettings> unportableSettings() const;
|
std::unique_ptr<QSettings> unportableSettings() const;
|
||||||
void swap(std::unique_ptr<QSettings> newSettings);
|
void swap(std::unique_ptr<QSettings> newSettings);
|
||||||
|
|||||||
@@ -29,6 +29,8 @@
|
|||||||
#ifndef MACOSHELPER_H
|
#ifndef MACOSHELPER_H
|
||||||
#define MACOSHELPER_H
|
#define MACOSHELPER_H
|
||||||
|
|
||||||
|
#include <QPixmap>
|
||||||
|
|
||||||
class MacOSHelper
|
class MacOSHelper
|
||||||
{
|
{
|
||||||
MacOSHelper() {}
|
MacOSHelper() {}
|
||||||
@@ -36,6 +38,7 @@ class MacOSHelper
|
|||||||
public:
|
public:
|
||||||
static bool isCapsLock();
|
static bool isCapsLock();
|
||||||
static bool openFolderAndSelectItem(const QUrl &path);
|
static bool openFolderAndSelectItem(const QUrl &path);
|
||||||
|
static QPixmap screenshot();
|
||||||
static QString bundlePath();
|
static QString bundlePath();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,8 @@
|
|||||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
// 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.
|
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
#include <QtCore>
|
#include <QtCore>
|
||||||
#include <QtGui>
|
#include <QtGui>
|
||||||
#include <QtMac>
|
#include <QtMac>
|
||||||
@@ -37,6 +39,8 @@
|
|||||||
#include <ApplicationServices/ApplicationServices.h>
|
#include <ApplicationServices/ApplicationServices.h>
|
||||||
#include <Availability.h>
|
#include <Availability.h>
|
||||||
|
|
||||||
|
#include "ScopeGuard.h"
|
||||||
|
|
||||||
bool MacOSHelper::isCapsLock()
|
bool MacOSHelper::isCapsLock()
|
||||||
{
|
{
|
||||||
#ifdef __MAC_10_12
|
#ifdef __MAC_10_12
|
||||||
@@ -56,6 +60,41 @@ bool MacOSHelper::openFolderAndSelectItem(const QUrl &path)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QPixmap MacOSHelper::screenshot()
|
||||||
|
{
|
||||||
|
std::unordered_set<uintptr_t> appWindowIds;
|
||||||
|
for (NSWindow *window in [NSApp windows])
|
||||||
|
{
|
||||||
|
appWindowIds.insert((uintptr_t)[window windowNumber]);
|
||||||
|
}
|
||||||
|
|
||||||
|
CFArrayRef onScreenWindows = CGWindowListCreate(kCGWindowListOptionOnScreenOnly, kCGNullWindowID);
|
||||||
|
const auto onScreenWindowsClenaup = sg::make_scope_guard([&onScreenWindows]() {
|
||||||
|
CFRelease(onScreenWindows);
|
||||||
|
});
|
||||||
|
|
||||||
|
CFMutableArrayRef foreignWindows = CFArrayCreateMutable(NULL, CFArrayGetCount(onScreenWindows), NULL);
|
||||||
|
const auto foreignWindowsClenaup = sg::make_scope_guard([&foreignWindows]() {
|
||||||
|
CFRelease(foreignWindows);
|
||||||
|
});
|
||||||
|
|
||||||
|
for (CFIndex index = 0, count = CFArrayGetCount(onScreenWindows); index < count; ++index)
|
||||||
|
{
|
||||||
|
const uintptr_t windowId = reinterpret_cast<const uintptr_t>(CFArrayGetValueAtIndex(onScreenWindows, index));
|
||||||
|
if (appWindowIds.find(windowId) == appWindowIds.end())
|
||||||
|
{
|
||||||
|
CFArrayAppendValue(foreignWindows, reinterpret_cast<const void *>(windowId));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CGImageRef image = CGWindowListCreateImageFromArray(CGRectInfinite, foreignWindows, kCGWindowListOptionAll);
|
||||||
|
const auto imageClenaup = sg::make_scope_guard([&image]() {
|
||||||
|
CFRelease(image);
|
||||||
|
});
|
||||||
|
|
||||||
|
return QtMac::fromCGImageRef(image);
|
||||||
|
}
|
||||||
|
|
||||||
QString MacOSHelper::bundlePath()
|
QString MacOSHelper::bundlePath()
|
||||||
{
|
{
|
||||||
NSBundle *main = [NSBundle mainBundle];
|
NSBundle *main = [NSBundle mainBundle];
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
#include <QtCore>
|
#include <QtCore>
|
||||||
#include <QApplication>
|
#include <QCoreApplication>
|
||||||
#include <QtGlobal>
|
#include <QtGlobal>
|
||||||
|
|
||||||
#include "TailsOS.h"
|
#include "TailsOS.h"
|
||||||
@@ -88,7 +88,7 @@ QString getAccountName(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef Q_OS_LINUX
|
#ifdef Q_OS_LINUX
|
||||||
QString xdgMime(QApplication &app){
|
QString xdgMime(){
|
||||||
return QString(
|
return QString(
|
||||||
"[Desktop Entry]\n"
|
"[Desktop Entry]\n"
|
||||||
"Name=Monero GUI\n"
|
"Name=Monero GUI\n"
|
||||||
@@ -105,32 +105,31 @@ QString xdgMime(QApplication &app){
|
|||||||
"StartupNotify=true\n"
|
"StartupNotify=true\n"
|
||||||
"X-GNOME-Bugzilla-Bugzilla=GNOME\n"
|
"X-GNOME-Bugzilla-Bugzilla=GNOME\n"
|
||||||
"X-GNOME-UsesNotifications=true\n"
|
"X-GNOME-UsesNotifications=true\n"
|
||||||
).arg(app.applicationFilePath());
|
).arg(QCoreApplication::applicationFilePath());
|
||||||
}
|
}
|
||||||
|
|
||||||
void registerXdgMime(QApplication &app){
|
void registerXdgMime(){
|
||||||
// Register desktop entry
|
// Register desktop entry
|
||||||
// - MacOS handled via Info.plist
|
// - MacOS handled via Info.plist
|
||||||
// - Windows handled in the installer by rbrunner7
|
// - Windows handled in the installer by rbrunner7
|
||||||
// - Linux written to `QStandardPaths::ApplicationsLocation`
|
// - Linux written to `QStandardPaths::ApplicationsLocation`
|
||||||
// - Tails written to persistent dotfiles
|
// - Tails written to persistent dotfiles
|
||||||
QString mime = xdgMime(app);
|
QString mime = xdgMime();
|
||||||
QString appPath = QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation);
|
QString appPath = QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation);
|
||||||
QString filePath = QString("%1/monero-gui.desktop").arg(appPath);
|
QString filePath = QString("%1/monero-gui.desktop").arg(appPath);
|
||||||
|
|
||||||
if (TailsOS::detect() && TailsOS::detectDotPersistence() && TailsOS::usePersistence) {
|
if (TailsOS::detect())
|
||||||
TailsOS::persistXdgMime(filePath, mime);
|
{
|
||||||
return;
|
if (TailsOS::detectDotPersistence() && TailsOS::usePersistence)
|
||||||
|
{
|
||||||
|
TailsOS::persistXdgMime(filePath, mime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
QDir().mkpath(QFileInfo(filePath).path());
|
||||||
|
fileWrite(filePath, mime);
|
||||||
}
|
}
|
||||||
|
|
||||||
QFileInfo file(filePath);
|
|
||||||
QDir().mkpath(file.path()); // ensure directory exists
|
|
||||||
|
|
||||||
#ifdef QT_DEBUG
|
|
||||||
qDebug() << "Writing xdg mime: " << filePath;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
fileWrite(filePath, mime);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -39,8 +39,8 @@ QByteArray fileOpen(QString path);
|
|||||||
bool fileWrite(QString path, QString data);
|
bool fileWrite(QString path, QString data);
|
||||||
QString getAccountName();
|
QString getAccountName();
|
||||||
#ifdef Q_OS_LINUX
|
#ifdef Q_OS_LINUX
|
||||||
QString xdgMime(QApplication &app);
|
QString xdgMime();
|
||||||
void registerXdgMime(QApplication &app);
|
void registerXdgMime();
|
||||||
#endif
|
#endif
|
||||||
const static QRegExp reURI = QRegExp("^\\w+:\\/\\/([\\w+\\-?\\-_\\-=\\-&]+)");
|
const static QRegExp reURI = QRegExp("^\\w+:\\/\\/([\\w+\\-?\\-_\\-=\\-&]+)");
|
||||||
QString randomUserAgent();
|
QString randomUserAgent();
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
3907
translations/monero-core_az.ts
Normal file
3907
translations/monero-core_az.ts
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user