Compare commits
156 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bea3032df9 | ||
|
|
ab8ac87023 | ||
|
|
588b8435b7 | ||
|
|
8983cae468 | ||
|
|
3612866f9f | ||
|
|
beb336cb93 | ||
|
|
90cbe37846 | ||
|
|
10984a0a37 | ||
|
|
f5cb2443d1 | ||
|
|
8f7de0e9fc | ||
|
|
b60a98ae6c | ||
|
|
7040e3b72f | ||
|
|
12a0966eb9 | ||
|
|
5ff03786c7 | ||
|
|
483b825a2f | ||
|
|
ca304fc63d | ||
|
|
5a1a349977 | ||
|
|
5683f76cd0 | ||
|
|
cc7d7da346 | ||
|
|
d10e4d1e50 | ||
|
|
d338e06abd | ||
|
|
145ea10d93 | ||
|
|
d42caf1fbc | ||
|
|
705cc6573f | ||
|
|
5c3544f211 | ||
|
|
f859664443 | ||
|
|
2d25364f42 | ||
|
|
8323fb02ca | ||
|
|
d442ca38dc | ||
|
|
57409a8c47 | ||
|
|
f002987edd | ||
|
|
866a7b3a78 | ||
|
|
f342d46541 | ||
|
|
f5e016930b | ||
|
|
ac9a305543 | ||
|
|
f824aebfaa | ||
|
|
7765b8b462 | ||
|
|
a65fbee213 | ||
|
|
17e3ed6c97 | ||
|
|
b6e336dbaf | ||
|
|
ddcc17b7b8 | ||
|
|
f6549f328b | ||
|
|
4cbfa5efb2 | ||
|
|
fa2241f1a5 | ||
|
|
6bd11f2270 | ||
|
|
6c4a8fb819 | ||
|
|
ad1b53fa63 | ||
|
|
a9e0affe59 | ||
|
|
371ff6105b | ||
|
|
cad8874724 | ||
|
|
5345dcc11b | ||
|
|
33310786db | ||
|
|
6ac8e7a464 | ||
|
|
434f548a87 | ||
|
|
90c4aa4ec6 | ||
|
|
7a4052f3af | ||
|
|
f650e96363 | ||
|
|
91e3d3ae04 | ||
|
|
9f33c77a47 | ||
|
|
7d9c1284f9 | ||
|
|
84899f4884 | ||
|
|
9c9ff13bd2 | ||
|
|
b117b9be61 | ||
|
|
f0ccf29f48 | ||
|
|
3e80d563df | ||
|
|
e4bdff0a0c | ||
|
|
6b82c01891 | ||
|
|
cd1eab45d0 | ||
|
|
511e2f467a | ||
|
|
4941b494cc | ||
|
|
5e949dbc15 | ||
|
|
bdf14a2520 | ||
|
|
710e3f6948 | ||
|
|
6ec9e24f2f | ||
|
|
cb9af349cd | ||
|
|
c8687a961c | ||
|
|
8a910ad4c7 | ||
|
|
e8020c86df | ||
|
|
a50491d0b2 | ||
|
|
bdd91b053d | ||
|
|
4b23148e68 | ||
|
|
e167bbce20 | ||
|
|
3338bc3741 | ||
|
|
af368c93ce | ||
|
|
5ced4ef547 | ||
|
|
198dfb338c | ||
|
|
587ea68a99 | ||
|
|
7d2f2cacbf | ||
|
|
757bc7d7b9 | ||
|
|
500dc573e4 | ||
|
|
56a91b2d1b | ||
|
|
c437dab90f | ||
|
|
b7ba9437d8 | ||
|
|
76fa06ceab | ||
|
|
4487471ada | ||
|
|
55a0bc46e4 | ||
|
|
3e17445a4d | ||
|
|
fc077fa54e | ||
|
|
70950619b8 | ||
|
|
a01dc06a54 | ||
|
|
a3b54a942c | ||
|
|
c8127f651d | ||
|
|
4cc6bcbd7d | ||
|
|
8b682fbd2b | ||
|
|
48393db2c7 | ||
|
|
faa4473b17 | ||
|
|
9924dfe8af | ||
|
|
47f336bf33 | ||
|
|
07b75fb692 | ||
|
|
6c39e82519 | ||
|
|
f8178f2e54 | ||
|
|
75290d2454 | ||
|
|
b180ac8cab | ||
|
|
58c7c9ab76 | ||
|
|
b8e6cb221b | ||
|
|
ef2e711e15 | ||
|
|
2ade733867 | ||
|
|
1735154b81 | ||
|
|
a9b52f6752 | ||
|
|
7faec48c0a | ||
|
|
9e2ae684ed | ||
|
|
6984bb8113 | ||
|
|
c0a739c9fa | ||
|
|
2d254542f3 | ||
|
|
2fa79c670e | ||
|
|
4743e443dc | ||
|
|
43cc666e77 | ||
|
|
1215a6e5d8 | ||
|
|
499c2a47fc | ||
|
|
c390afd258 | ||
|
|
3b0e66a3d0 | ||
|
|
4cd6652825 | ||
|
|
80ade41905 | ||
|
|
83921a4bc8 | ||
|
|
acf876f4b2 | ||
|
|
7954661100 | ||
|
|
22a1509316 | ||
|
|
499eeee59a | ||
|
|
8cf76cf7c2 | ||
|
|
6441d99279 | ||
|
|
aef4a982dc | ||
|
|
f93c67740c | ||
|
|
4b8e0f36ab | ||
|
|
c247b96c4a | ||
|
|
085f4af1dc | ||
|
|
49a6c8ba9c | ||
|
|
df9b35e947 | ||
|
|
96b6e5972f | ||
|
|
b801ef594b | ||
|
|
ff0c068cb8 | ||
|
|
1b119eb8f5 | ||
|
|
6a8a123da8 | ||
|
|
6f2aafdd6c | ||
|
|
64a6ca7fc7 | ||
|
|
8b356605b4 | ||
|
|
131154ba80 |
107
.github/verify_p2pool.py
vendored
Normal file
@@ -0,0 +1,107 @@
|
||||
import requests
|
||||
import subprocess
|
||||
from urllib.request import urlretrieve
|
||||
import difflib
|
||||
|
||||
sech_key = "https://p2pool.io/SChernykh.asc"
|
||||
sech_key_backup = "https://raw.githubusercontent.com/monero-project/gitian.sigs/master/gitian-pubkeys/SChernykh.asc"
|
||||
sech_key_fp = "1FCA AB4D 3DC3 310D 16CB D508 C47F 82B5 4DA8 7ADF"
|
||||
|
||||
p2pool_files = [{
|
||||
"os": "WIN",
|
||||
"filename": "windows-x64.zip",
|
||||
},
|
||||
{
|
||||
"os": "LINUX",
|
||||
"filename": "linux-x64.tar.gz"
|
||||
},
|
||||
{
|
||||
"os": "MACOS_AARCH64",
|
||||
"filename": "macos-aarch64.tar.gz",
|
||||
},
|
||||
{
|
||||
"os": "MACOS",
|
||||
"filename": "macos-x64.tar.gz",
|
||||
}]
|
||||
|
||||
def get_hash(fname):
|
||||
fhash = subprocess.check_output(["sha256sum", fname]).decode("utf-8")
|
||||
print(fhash.strip())
|
||||
return fhash.split()[0]
|
||||
|
||||
def main():
|
||||
global p2pool_files, sech_key, sech_key_backup, sech_key_fp
|
||||
p2pool_tag_api = "https://api.github.com/repos/SChernykh/p2pool/releases/latest"
|
||||
data = requests.get(p2pool_tag_api).json()
|
||||
tag = data["tag_name"]
|
||||
head = f"p2pool-{tag}-"
|
||||
url = f"https://github.com/SChernykh/p2pool/releases/download/{tag}/"
|
||||
|
||||
try:
|
||||
urlretrieve(sech_key,"SChernykh.asc")
|
||||
except:
|
||||
urlretrieve(sech_key_backup,"SChernykh.asc")
|
||||
|
||||
urlretrieve(f"{url}sha256sums.txt.asc","sha256sums.txt.asc")
|
||||
|
||||
subprocess.check_call(["gpg", "--import", "SChernykh.asc"])
|
||||
subprocess.check_call(["gpg", "--verify", "sha256sums.txt.asc"])
|
||||
fingerprint = subprocess.check_output(["gpg","--fingerprint", "SChernykh"]).decode("utf-8").splitlines()[1].strip()
|
||||
|
||||
assert fingerprint == sech_key_fp
|
||||
|
||||
with open("sha256sums.txt.asc","r") as f:
|
||||
lines = f.readlines()
|
||||
|
||||
signed_hashes = {}
|
||||
for line in lines:
|
||||
if "Name:" in line:
|
||||
signed_fname = line.split()[1]
|
||||
if "SHA256:" in line:
|
||||
signed_hashes[signed_fname] = line.split()[1].lower()
|
||||
|
||||
expected = ""
|
||||
for i in range(len(p2pool_files)):
|
||||
fname = p2pool_files[i]["filename"]
|
||||
str_os =p2pool_files[i]["os"]
|
||||
dl = f"{url}{head}{fname}"
|
||||
urlretrieve(dl,f"{head}{fname}")
|
||||
fhash = get_hash(f"{head}{fname}")
|
||||
assert signed_hashes[f"{head}{fname}"] == fhash
|
||||
if i == 0:
|
||||
expected += f" #ifdef Q_OS_{str_os}\n"
|
||||
else:
|
||||
expected += f" #elif defined(Q_OS_{str_os})\n"
|
||||
expected += f" url = \"https://github.com/SChernykh/p2pool/releases/download/{tag}/{head}{fname}\";\n"
|
||||
expected += f" fileName = m_p2poolPath + \"/{head}{fname}\";\n"
|
||||
expected += f" validHash = \"{fhash}\";\n"
|
||||
expected += " #endif\n"
|
||||
|
||||
print(f"Expected:\n{expected}")
|
||||
|
||||
with open("src/p2pool/P2PoolManager.cpp","r") as f:
|
||||
p2pool_lines = f.readlines()
|
||||
|
||||
unexpected = ""
|
||||
ignore = 1
|
||||
for line in p2pool_lines:
|
||||
if ignore == 0:
|
||||
unexpected += line
|
||||
if "QString validHash;" in line:
|
||||
ignore = 0
|
||||
if "#endif" in line and ignore == 0:
|
||||
break
|
||||
|
||||
d = difflib.Differ()
|
||||
diff = d.compare(str(unexpected).splitlines(True),str(expected).splitlines(True))
|
||||
|
||||
print("Unexpected:")
|
||||
for i in diff:
|
||||
if i.startswith("?"):
|
||||
continue
|
||||
print(i.replace("\n",""))
|
||||
|
||||
assert unexpected == expected
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
19
.github/workflows/build.yml
vendored
@@ -34,7 +34,7 @@ jobs:
|
||||
- name: install monero dependencies
|
||||
run: sudo apt -y install build-essential cmake libboost-all-dev miniupnpc libunbound-dev graphviz doxygen libunwind8-dev pkg-config libssl-dev libzmq3-dev libsodium-dev libhidapi-dev libnorm-dev libusb-1.0-0-dev libpgm-dev libprotobuf-dev protobuf-compiler
|
||||
- name: install monero gui dependencies
|
||||
run: sudo apt -y install qtbase5-dev qt5-default qtdeclarative5-dev qml-module-qtqml-models2 qml-module-qtquick-controls qml-module-qtquick-controls2 qml-module-qtquick-dialogs qml-module-qtquick-xmllistmodel qml-module-qt-labs-settings qml-module-qt-labs-platform qml-module-qt-labs-folderlistmodel qttools5-dev-tools qml-module-qtquick-templates2 libqt5svg5-dev libgcrypt20-dev xvfb
|
||||
run: sudo apt -y install qtbase5-dev qtdeclarative5-dev qml-module-qtqml-models2 qml-module-qtquick-controls qml-module-qtquick-controls2 qml-module-qtquick-dialogs qml-module-qtquick-xmllistmodel qml-module-qt-labs-settings qml-module-qt-labs-platform qml-module-qt-labs-folderlistmodel qttools5-dev-tools qml-module-qtquick-templates2 libqt5svg5-dev libgcrypt20-dev xvfb
|
||||
- name: build
|
||||
run: DEV_MODE=ON make release -j3
|
||||
- name: test qml
|
||||
@@ -52,7 +52,7 @@ jobs:
|
||||
- uses: eine/setup-msys2@v2
|
||||
with:
|
||||
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 mingw-w64-x86_64-unbound git mingw-w64-x86_64-qt5 mingw-w64-x86_64-libgcrypt
|
||||
install: mingw-w64-x86_64-toolchain make mingw-w64-x86_64-pcre 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-unbound git mingw-w64-x86_64-qt5 mingw-w64-x86_64-libgcrypt
|
||||
- name: build
|
||||
run: DEV_MODE=ON make release-win64 -j2
|
||||
- name: deploy
|
||||
@@ -75,19 +75,22 @@ jobs:
|
||||
run: python3 monero-gui/.github/qt_helper.py mac_x64 desktop 5.15.2 clang_64 c384008156fe63cc183bade0316828c598ff3e5074397c0c9ccc588d6cdc5aca
|
||||
working-directory: ../
|
||||
- name: build
|
||||
run: CMAKE_PREFIX_PATH=/Users/runner/work/monero-gui/5.15.2/clang_64 make release -j3
|
||||
run: |
|
||||
mkdir build && cd build
|
||||
cmake -D CMAKE_BUILD_TYPE=Release -D ARCH=default -D CMAKE_PREFIX_PATH=/Users/runner/work/monero-gui/5.15.2/clang_64 ..
|
||||
make
|
||||
- name: deploy
|
||||
run: make deploy
|
||||
working-directory: build/release
|
||||
working-directory: build
|
||||
- name: test qml
|
||||
run: build/release/bin/monero-wallet-gui.app/Contents/MacOS/monero-wallet-gui --test-qml
|
||||
run: build/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
|
||||
working-directory: build/bin
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: ${{ github.job }}
|
||||
path: build/release/bin/monero-wallet-gui.tar
|
||||
path: build/bin/monero-wallet-gui.tar
|
||||
|
||||
docker-linux-static:
|
||||
runs-on: ubuntu-20.04
|
||||
@@ -162,6 +165,8 @@ jobs:
|
||||
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
|
||||
- name: Remove obsolete docker layers
|
||||
run: docker images -a | grep none | awk '{ print $3; }' | xargs docker rmi || true
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: ${{ github.job }}
|
||||
|
||||
174
.github/workflows/flatpak.yml
vendored
Normal file
@@ -0,0 +1,174 @@
|
||||
name: Flatpak
|
||||
|
||||
on:
|
||||
release:
|
||||
types: released
|
||||
|
||||
jobs:
|
||||
part1:
|
||||
name: Part 1/3
|
||||
if: github.repository == 'monero-project/monero-gui'
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: bilelmoussaoui/flatpak-github-actions:kde-5.15-22.08
|
||||
options: --privileged
|
||||
strategy:
|
||||
matrix:
|
||||
arch: [x86_64, aarch64]
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Install deps
|
||||
run: dnf -y install docker
|
||||
|
||||
- name: Setup QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
with:
|
||||
platforms: arm64
|
||||
|
||||
- name: Build flatpak
|
||||
uses: flatpak/flatpak-github-actions/flatpak-builder@v6
|
||||
env:
|
||||
FLATPAK_BUILDER_N_JOBS: 3
|
||||
with:
|
||||
manifest-path: share/org.getmonero.Monero.yaml
|
||||
arch: ${{ matrix.arch }}
|
||||
cache: false
|
||||
stop-at-module: boost
|
||||
|
||||
- name: Tar flatpak-builder
|
||||
run: tar -cvf flatpak-builder.tar .flatpak-builder
|
||||
|
||||
- name: Save flatpak-builder
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: flatpak-builder-${{ matrix.arch }}
|
||||
path: flatpak-builder.tar
|
||||
|
||||
part2:
|
||||
name: Part 2/3
|
||||
if: github.repository == 'monero-project/monero-gui'
|
||||
needs: part1
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: bilelmoussaoui/flatpak-github-actions:kde-5.15-22.08
|
||||
options: --privileged
|
||||
strategy:
|
||||
matrix:
|
||||
arch: [x86_64, aarch64]
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Install deps
|
||||
run: dnf -y install docker
|
||||
|
||||
- name: Setup QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
with:
|
||||
platforms: arm64
|
||||
|
||||
- name: Restore flatpak-builder
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: flatpak-builder-${{ matrix.arch }}
|
||||
|
||||
- name: Untar flatpak-builder
|
||||
run: tar -xvf flatpak-builder.tar
|
||||
|
||||
- name: Build flatpak
|
||||
uses: flatpak/flatpak-github-actions/flatpak-builder@v6
|
||||
env:
|
||||
FLATPAK_BUILDER_N_JOBS: 3
|
||||
with:
|
||||
manifest-path: share/org.getmonero.Monero.yaml
|
||||
arch: ${{ matrix.arch }}
|
||||
cache: false
|
||||
stop-at-module: monero-gui
|
||||
|
||||
- name: Tar flatpak-builder
|
||||
run: tar -cvf flatpak-builder.tar .flatpak-builder
|
||||
|
||||
- name: Save flatpak-builder
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: flatpak-builder-${{ matrix.arch }}
|
||||
path: flatpak-builder.tar
|
||||
|
||||
part3:
|
||||
name: Part 3/3
|
||||
if: github.repository == 'monero-project/monero-gui'
|
||||
needs: [part1, part2]
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: bilelmoussaoui/flatpak-github-actions:kde-5.15-22.08
|
||||
options: --privileged
|
||||
strategy:
|
||||
matrix:
|
||||
arch: [x86_64, aarch64]
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Add version and date
|
||||
run: |
|
||||
sed -i 's/<version>/${{ github.event.release.tag_name }}/g' $GITHUB_WORKSPACE/share/org.getmonero.Monero.metainfo.xml
|
||||
sed -i 's/<date>/'"$(date '+%F')"'/g' $GITHUB_WORKSPACE/share/org.getmonero.Monero.metainfo.xml
|
||||
|
||||
- name: Install deps
|
||||
run: dnf -y install docker
|
||||
|
||||
- name: Setup QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
with:
|
||||
platforms: arm64
|
||||
|
||||
- name: Restore flatpak-builder
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: flatpak-builder-${{ matrix.arch }}
|
||||
|
||||
- name: Untar flatpak-builder
|
||||
run: tar -xvf flatpak-builder.tar
|
||||
|
||||
- name: Build flatpak
|
||||
uses: flatpak/flatpak-github-actions/flatpak-builder@v6
|
||||
env:
|
||||
FLATPAK_BUILDER_N_JOBS: 3
|
||||
with:
|
||||
manifest-path: share/org.getmonero.Monero.yaml
|
||||
arch: ${{ matrix.arch }}
|
||||
cache: false
|
||||
|
||||
- name: Validate AppData
|
||||
working-directory: flatpak_app/files/share/appdata
|
||||
run: appstream-util validate org.getmonero.Monero.appdata.xml
|
||||
|
||||
- name: Delete flatpak-builder
|
||||
uses: geekyeggo/delete-artifact@v2
|
||||
with:
|
||||
name: flatpak-builder-${{ matrix.arch }}
|
||||
|
||||
- name: Print hashes
|
||||
working-directory: flatpak_app/files/bin
|
||||
run: |
|
||||
echo "Hashes of the ${{ matrix.arch }} binaries:" >> $GITHUB_STEP_SUMMARY
|
||||
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
|
||||
for bin in monero-blockchain-ancestry monero-blockchain-depth monero-blockchain-export monero-blockchain-import monero-blockchain-mark-spent-outputs monero-blockchain-prune monero-blockchain-prune-known-spent-data monero-blockchain-stats monero-blockchain-usage monerod monero-gen-ssl-cert monero-gen-trusted-multisig monero-wallet-cli monero-wallet-gui monero-wallet-rpc p2pool; do sha256sum $bin; done >> $GITHUB_STEP_SUMMARY
|
||||
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
|
||||
echo "An example command to check hashes:" >> $GITHUB_STEP_SUMMARY
|
||||
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
|
||||
echo "$ flatpak run --command=sha256sum org.getmonero.Monero /app/bin/monero-wallet-gui" >> $GITHUB_STEP_SUMMARY
|
||||
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
- name: Publish to Flathub Beta
|
||||
uses: flatpak/flatpak-github-actions/flat-manager@v6
|
||||
with:
|
||||
flat-manager-url: https://hub.flathub.org
|
||||
repository: beta
|
||||
token: ${{ secrets.FLATHUB_ }}
|
||||
16
.github/workflows/verify_p2pool.yml
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
name: ci/gh-actions/verify
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- 'src/p2pool/P2PoolManager.cpp'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'src/p2pool/P2PoolManager.cpp'
|
||||
jobs:
|
||||
p2pool-hashes:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Verify Hashes
|
||||
run: |
|
||||
python3 .github/verify_p2pool.py
|
||||
@@ -4,7 +4,7 @@ project(monero-gui)
|
||||
message(STATUS "Initiating compile using CMake ${CMAKE_VERSION}")
|
||||
|
||||
set(VERSION_MAJOR "18")
|
||||
set(VERSION_MINOR "1")
|
||||
set(VERSION_MINOR "3")
|
||||
set(VERSION_REVISION "1")
|
||||
set(VERSION "0.${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_REVISION}")
|
||||
|
||||
|
||||
@@ -1,47 +1,50 @@
|
||||
FROM debian:stretch
|
||||
FROM debian:buster
|
||||
|
||||
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
|
||||
ARG ANDROID_NDK_REVISION=21e
|
||||
ARG ANDROID_NDK_HASH=c3ebc83c96a4d7f539bd72c241b2be9dcd29bda9
|
||||
ARG ANDROID_SDK_REVISION=7302050_latest
|
||||
ARG ANDROID_SDK_HASH=7a00faadc0864f78edd8f4908a629a46d622375cbe2e5814e82934aebecdb622
|
||||
ARG QT_VERSION=v5.15.7-lts-lgpl
|
||||
|
||||
WORKDIR /opt/android
|
||||
ENV WORKDIR=/opt/android
|
||||
|
||||
ENV ANDROID_NATIVE_API_LEVEL=28
|
||||
ENV ANDROID_NATIVE_API_LEVEL=30
|
||||
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 ANDROID_SDK_ROOT=${WORKDIR}/cmdline-tools
|
||||
ENV JAVA_HOME=/usr/lib/jvm/java-11-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 \
|
||||
libssl-dev libstdc++6 libtinfo5 libtool libz1 openjdk-11-jdk-headless openjdk-11-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 PACKAGE_NAME=commandlinetools-linux-${ANDROID_SDK_REVISION}.zip \
|
||||
&& wget -q https://dl.google.com/android/repository/${PACKAGE_NAME} \
|
||||
&& echo "${ANDROID_SDK_HASH} ${PACKAGE_NAME}" | sha256sum -c \
|
||||
&& unzip -q ${PACKAGE_NAME} \
|
||||
&& rm -f ${PACKAGE_NAME}
|
||||
|
||||
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 PACKAGE_NAME=android-ndk-r${ANDROID_NDK_REVISION}-linux-x86_64.zip \
|
||||
&& wget -q https://dl.google.com/android/repository/${PACKAGE_NAME} \
|
||||
&& echo "${ANDROID_NDK_HASH} ${PACKAGE_NAME}" | sha1sum -c \
|
||||
&& unzip -q ${PACKAGE_NAME} \
|
||||
&& rm -f ${PACKAGE_NAME}
|
||||
|
||||
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}
|
||||
RUN echo y | ${ANDROID_SDK_ROOT}/bin/sdkmanager --sdk_root=${ANDROID_SDK_ROOT} "build-tools;28.0.3" "platforms;${ANDROID_API}" "tools" > /dev/null
|
||||
|
||||
ENV HOST_PATH=${PATH}
|
||||
ENV PATH=${TOOLCHAIN_DIR}/aarch64-linux-android/bin:${TOOLCHAIN_DIR}/bin:${PATH}
|
||||
|
||||
ARG ZLIB_VERSION=1.2.12
|
||||
ARG ZLIB_HASH=91844808532e5ce316b3c010929493c0244f3d37593afd6de04f71821d5136d9
|
||||
ARG ZLIB_VERSION=1.3
|
||||
ARG ZLIB_HASH=ff0ba4c292013dbc27530b3a81e1f9a813cd39de01ca5e0f8bf355702efa593e
|
||||
RUN wget -q https://zlib.net/zlib-${ZLIB_VERSION}.tar.gz \
|
||||
&& echo "${ZLIB_HASH} zlib-${ZLIB_VERSION}.tar.gz" | sha256sum -c \
|
||||
&& tar -xzf zlib-${ZLIB_VERSION}.tar.gz \
|
||||
@@ -76,7 +79,6 @@ RUN git clone git://code.qt.io/qt/qt5.git -b ${QT_VERSION} --depth 1 \
|
||||
-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 \
|
||||
@@ -99,7 +101,7 @@ RUN wget -q http://ftp.gnu.org/pub/gnu/libiconv/libiconv-${ICONV_VERSION}.tar.gz
|
||||
ARG BOOST_VERSION=1_74_0
|
||||
ARG BOOST_VERSION_DOT=1.74.0
|
||||
ARG BOOST_HASH=83bfc1507731a0906e387fc28b7ef5417d591429e51e788417fe9ff025e116b1
|
||||
RUN wget -q https://downloads.sourceforge.net/project/boost/boost/${BOOST_VERSION_DOT}/boost_${BOOST_VERSION}.tar.bz2 \
|
||||
RUN wget -q https://boostorg.jfrog.io/artifactory/main/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 \
|
||||
@@ -115,8 +117,8 @@ RUN wget -q https://downloads.sourceforge.net/project/boost/boost/${BOOST_VERSIO
|
||||
install -j${THREADS} \
|
||||
&& rm -rf $(pwd)
|
||||
|
||||
ARG OPENSSL_VERSION=1.1.1q
|
||||
ARG OPENSSL_HASH=d7939ce614029cdff0b6c20f0e2e5703158a489a72b2507b8bd51bf8c8fd10ca
|
||||
ARG OPENSSL_VERSION=1.1.1u
|
||||
ARG OPENSSL_HASH=e2f8d84b523eecd06c7be7626830370300fbcc15386bf5142d72758f6963ebc6
|
||||
RUN wget -q https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz \
|
||||
&& echo "${OPENSSL_HASH} openssl-${OPENSSL_VERSION}.tar.gz" | sha256sum -c \
|
||||
&& tar -xzf openssl-${OPENSSL_VERSION}.tar.gz \
|
||||
@@ -143,8 +145,8 @@ RUN wget https://github.com/libexpat/libexpat/releases/download/R_2_4_1/expat-${
|
||||
make -j$THREADS install && \
|
||||
rm -rf $(pwd)
|
||||
|
||||
ARG UNBOUND_VERSION=1.13.2
|
||||
ARG UNBOUND_HASH=0a13b547f3b92a026b5ebd0423f54c991e5718037fd9f72445817f6a040e1a83
|
||||
ARG UNBOUND_VERSION=1.16.2
|
||||
ARG UNBOUND_HASH=2e32f283820c24c51ca1dd8afecfdb747c7385a137abe865c99db4b257403581
|
||||
RUN wget https://www.nlnetlabs.nl/downloads/unbound/unbound-${UNBOUND_VERSION}.tar.gz && \
|
||||
echo "${UNBOUND_HASH} unbound-${UNBOUND_VERSION}.tar.gz" | sha256sum -c && \
|
||||
tar -xzf unbound-${UNBOUND_VERSION}.tar.gz && \
|
||||
@@ -155,8 +157,8 @@ RUN wget https://www.nlnetlabs.nl/downloads/unbound/unbound-${UNBOUND_VERSION}.t
|
||||
make -j$THREADS install && \
|
||||
rm -rf $(pwd)
|
||||
|
||||
ARG ZMQ_VERSION=v4.3.3
|
||||
ARG ZMQ_HASH=04f5bbedee58c538934374dc45182d8fc5926fa3
|
||||
ARG ZMQ_VERSION=v4.3.4
|
||||
ARG ZMQ_HASH=4097855ddaaa65ed7b5e8cb86d143842a594eebd
|
||||
RUN git clone https://github.com/zeromq/libzmq.git -b ${ZMQ_VERSION} --depth 1 \
|
||||
&& cd libzmq \
|
||||
&& git checkout ${ZMQ_HASH} \
|
||||
@@ -178,38 +180,42 @@ RUN set -ex \
|
||||
&& make -j${THREADS} install \
|
||||
&& rm -rf $(pwd)
|
||||
|
||||
RUN git clone -b libgpg-error-1.38 --depth 1 git://git.gnupg.org/libgpg-error.git \
|
||||
RUN git clone -b libgpg-error-1.41 --depth 1 git://git.gnupg.org/libgpg-error.git \
|
||||
&& cd libgpg-error \
|
||||
&& git reset --hard 71d278824c5fe61865f7927a2ed1aa3115f9e439 \
|
||||
&& git reset --hard 98032624ae89a67ee6fe3b1db5d95032e681d163 \
|
||||
&& ./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 \
|
||||
RUN git clone -b libgcrypt-1.10.1 --depth 1 git://git.gnupg.org/libgcrypt.git \
|
||||
&& cd libgcrypt \
|
||||
&& git reset --hard 56606331bc2a80536db9fc11ad53695126007298 \
|
||||
&& git reset --hard ae0e567820c37f9640440b3cff77d7c185aa6742 \
|
||||
&& ./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 \
|
||||
RUN git clone -b v3.24.2 --depth 1 https://github.com/Kitware/CMake \
|
||||
&& cd CMake \
|
||||
&& git reset --hard 22612dd53a46c7f9b4c3f4b7dbe5c78f9afd9581 \
|
||||
&& git reset --hard 31f835410efeea50acd43512eb9e5646a26ea177 \
|
||||
&& PATH=${HOST_PATH} ./bootstrap \
|
||||
&& PATH=${HOST_PATH} make -j${THREADS} \
|
||||
&& PATH=${HOST_PATH} make -j${THREADS} install \
|
||||
&& rm -rf $(pwd)
|
||||
|
||||
RUN GRADLE_VERSION=5.6.4 \
|
||||
&& GRADLE_HASH=1f3067073041bc44554d0efe5d402a33bc3d3c93cc39ab684f308586d732a80d \
|
||||
&& wget -q https\://services.gradle.org/distributions/gradle-${GRADLE_VERSION}-bin.zip \
|
||||
&& echo "${GRADLE_HASH} gradle-${GRADLE_VERSION}-bin.zip" | sha256sum -c \
|
||||
&& GRADLE_LOCAL_PATH=gradle/wrapper/dists/gradle-${GRADLE_VERSION}-bin/bxirm19lnfz6nurbatndyydux \
|
||||
&& mkdir -p ${GRADLE_LOCAL_PATH} \
|
||||
&& mv gradle-${GRADLE_VERSION}-bin.zip ${GRADLE_LOCAL_PATH}
|
||||
|
||||
ENV GRADLE_USER_HOME=${WORKDIR}/gradle
|
||||
|
||||
CMD set -ex \
|
||||
&& cd /monero-gui \
|
||||
&& mkdir -p build/Android/release \
|
||||
@@ -226,7 +232,9 @@ CMD set -ex \
|
||||
-DBoost_USE_STATIC_RUNTIME=ON \
|
||||
-DLRELEASE_PATH="${PREFIX}/bin" \
|
||||
-DQT_ANDROID_APPLICATION_BINARY="monero-wallet-gui" \
|
||||
-DANDROID_SDK="${ANDROID_SDK_ROOT}" \
|
||||
-DWITH_SCANNER=ON \
|
||||
-DWITH_DESKTOP_ENTRY=OFF \
|
||||
../../.. \
|
||||
&& PATH=${HOST_PATH} make generate_translations_header \
|
||||
&& make -j${THREADS} -C src \
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
FROM ubuntu:16.04
|
||||
|
||||
ARG THREADS=1
|
||||
ARG QT_VERSION=v5.15.6-lts-lgpl
|
||||
ARG QT_VERSION=v5.15.10-lts-lgpl
|
||||
|
||||
ENV CFLAGS="-fPIC"
|
||||
ENV CPPFLAGS="-fPIC"
|
||||
@@ -113,9 +113,9 @@ RUN git clone -b xkbcommon-0.5.0 --depth 1 https://github.com/xkbcommon/libxkbco
|
||||
make -j$THREADS install && \
|
||||
rm -rf $(pwd)
|
||||
|
||||
RUN git clone -b v1.2.11 --depth 1 https://github.com/madler/zlib && \
|
||||
RUN git clone -b v1.3 --depth 1 https://github.com/madler/zlib && \
|
||||
cd zlib && \
|
||||
git reset --hard cacf7f1d4e3d44d871b605da3b647f07d718623f && \
|
||||
git reset --hard 09155eaa2f9270dc4ed1fa13e2b4b2613e6e4851 && \
|
||||
./configure --static && \
|
||||
make -j$THREADS && \
|
||||
make -j$THREADS install && \
|
||||
@@ -130,11 +130,12 @@ RUN git clone -b VER-2-10-2 --depth 1 https://git.savannah.gnu.org/git/freetype/
|
||||
make -j$THREADS install && \
|
||||
rm -rf $(pwd)
|
||||
|
||||
RUN git clone -b R_2_2_9 --depth 1 https://github.com/libexpat/libexpat && \
|
||||
cd libexpat/expat && \
|
||||
git reset --hard a7bc26b69768f7fb24f0c7976fae24b157b85b13 && \
|
||||
./buildconf.sh && \
|
||||
./configure --disable-shared --enable-static && \
|
||||
RUN wget https://github.com/libexpat/libexpat/releases/download/R_2_4_8/expat-2.4.8.tar.bz2 && \
|
||||
echo "a247a7f6bbb21cf2ca81ea4cbb916bfb9717ca523631675f99b3d4a5678dcd16 expat-2.4.8.tar.bz2" | sha256sum -c && \
|
||||
tar -xf expat-2.4.8.tar.bz2 && \
|
||||
rm expat-2.4.8.tar.bz2 && \
|
||||
cd expat-2.4.8 && \
|
||||
./configure --enable-static --disable-shared --prefix=/usr && \
|
||||
make -j$THREADS && \
|
||||
make -j$THREADS install && \
|
||||
rm -rf $(pwd)
|
||||
@@ -164,26 +165,16 @@ RUN wget https://boostorg.jfrog.io/artifactory/main/release/1.80.0/source/boost_
|
||||
./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)
|
||||
|
||||
RUN wget https://www.openssl.org/source/openssl-1.1.1q.tar.gz && \
|
||||
echo "d7939ce614029cdff0b6c20f0e2e5703158a489a72b2507b8bd51bf8c8fd10ca openssl-1.1.1q.tar.gz" | sha256sum -c && \
|
||||
tar -xzf openssl-1.1.1q.tar.gz && \
|
||||
rm openssl-1.1.1q.tar.gz && \
|
||||
cd openssl-1.1.1q && \
|
||||
RUN wget https://www.openssl.org/source/openssl-1.1.1u.tar.gz && \
|
||||
echo "e2f8d84b523eecd06c7be7626830370300fbcc15386bf5142d72758f6963ebc6 openssl-1.1.1u.tar.gz" | sha256sum -c && \
|
||||
tar -xzf openssl-1.1.1u.tar.gz && \
|
||||
rm openssl-1.1.1u.tar.gz && \
|
||||
cd openssl-1.1.1u && \
|
||||
./config no-asm no-shared no-zlib-dynamic --prefix=/usr --openssldir=/usr && \
|
||||
make -j$THREADS && \
|
||||
make -j$THREADS install && \
|
||||
rm -rf $(pwd)
|
||||
|
||||
RUN wget https://github.com/libexpat/libexpat/releases/download/R_2_4_8/expat-2.4.8.tar.bz2 && \
|
||||
echo "a247a7f6bbb21cf2ca81ea4cbb916bfb9717ca523631675f99b3d4a5678dcd16 expat-2.4.8.tar.bz2" | sha256sum -c && \
|
||||
tar -xf expat-2.4.8.tar.bz2 && \
|
||||
rm expat-2.4.8.tar.bz2 && \
|
||||
cd expat-2.4.8 && \
|
||||
./configure --enable-static --disable-shared --prefix=/usr && \
|
||||
make -j$THREADS && \
|
||||
make -j$THREADS install && \
|
||||
rm -rf $(pwd)
|
||||
|
||||
RUN wget https://www.nlnetlabs.nl/downloads/unbound/unbound-1.16.2.tar.gz && \
|
||||
echo "2e32f283820c24c51ca1dd8afecfdb747c7385a137abe865c99db4b257403581 unbound-1.16.2.tar.gz" | sha256sum -c && \
|
||||
tar -xzf unbound-1.16.2.tar.gz && \
|
||||
@@ -242,9 +233,9 @@ RUN git clone -b v1.0.26 --depth 1 https://github.com/libusb/libusb && \
|
||||
make -j$THREADS install && \
|
||||
rm -rf $(pwd)
|
||||
|
||||
RUN git clone -b hidapi-0.12.0 --depth 1 https://github.com/libusb/hidapi && \
|
||||
RUN git clone -b hidapi-0.13.1 --depth 1 https://github.com/libusb/hidapi && \
|
||||
cd hidapi && \
|
||||
git reset --hard 76108294092c023a4ece99eb3219559cea0d5066 && \
|
||||
git reset --hard 4ebce6b5059b086d05ca7e091ce04a5fd08ac3ac && \
|
||||
./bootstrap && \
|
||||
./configure --disable-shared --enable-static && \
|
||||
make -j$THREADS && \
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
FROM ubuntu:20.04
|
||||
|
||||
ARG THREADS=1
|
||||
ARG QT_VERSION=v5.15.6-lts-lgpl
|
||||
ARG QT_VERSION=v5.15.10-lts-lgpl
|
||||
ENV SOURCE_DATE_EPOCH=1397818193
|
||||
|
||||
RUN apt update && \
|
||||
@@ -12,9 +12,9 @@ RUN apt update && \
|
||||
RUN update-alternatives --set x86_64-w64-mingw32-g++ $(which x86_64-w64-mingw32-g++-posix) && \
|
||||
update-alternatives --set x86_64-w64-mingw32-gcc $(which x86_64-w64-mingw32-gcc-posix)
|
||||
|
||||
RUN git clone -b v0.18.1.0 --depth 1 https://github.com/monero-project/monero && \
|
||||
RUN git clone -b v0.18.2.0 --depth 1 https://github.com/monero-project/monero && \
|
||||
cd monero && \
|
||||
git reset --hard 727bc5b6878170332bf2d838f2c60d1c8dc685c8 && \
|
||||
git reset --hard 99be9a044f3854f339548e2d99c539c18d7b1b01 && \
|
||||
cp -a contrib/depends / && \
|
||||
cd .. && \
|
||||
rm -rf monero
|
||||
|
||||
@@ -120,7 +120,7 @@ Rectangle {
|
||||
width: 260
|
||||
height: 135
|
||||
fillMode: Image.PreserveAspectFit
|
||||
source: MoneroComponents.Style.blackTheme ? "qrc:///images/card-background-black.png" : "qrc:///images/card-background-white.png"
|
||||
source: MoneroComponents.Style.blackTheme ? "qrc:///images/card-background-black" + (currentAccountIndex % MoneroComponents.Style.accountColors.length) + ".png" : "qrc:///images/card-background-white.png"
|
||||
}
|
||||
|
||||
DropShadow {
|
||||
|
||||
25
README.md
@@ -86,8 +86,7 @@ Status of the translations:
|
||||
## Installing the Monero GUI from a package
|
||||
|
||||
Packages are available for
|
||||
* Arch Linux: [monero-gui](https://www.archlinux.org/packages/community/x86_64/monero-gui/)
|
||||
* Debian: See the [whonix/monero-gui repository](https://gitlab.com/whonix/monero-gui#how-to-install-monero-using-apt-get)
|
||||
* Arch Linux: [monero-gui](https://archlinux.org/packages/extra/x86_64/monero-gui/)
|
||||
* Void Linux: `xbps-install -S monero-gui`
|
||||
* Flatpak: [Monero GUI](https://flathub.org/apps/details/org.getmonero.Monero)
|
||||
* GuixSD: `guix package -i monero-gui`
|
||||
@@ -108,7 +107,7 @@ Packaging for your favorite distribution would be a welcome contribution!
|
||||
```
|
||||
git clone --branch master --recursive https://github.com/monero-project/monero-gui.git
|
||||
```
|
||||
\* `master` - replace with the desired version tag (e.g. `v0.18.1.1`) to build the release binaries.
|
||||
\* `master` - replace with the desired version tag (e.g. `v0.18.3.1`) to build the release binaries.
|
||||
3. Prepare build environment
|
||||
```
|
||||
cd monero-gui
|
||||
@@ -131,7 +130,7 @@ Packaging for your favorite distribution would be a welcome contribution!
|
||||
```
|
||||
git clone --branch master --recursive https://github.com/monero-project/monero-gui.git
|
||||
```
|
||||
\* `master` - replace with the desired version tag (e.g. `v0.18.1.1`) to build the release binaries.
|
||||
\* `master` - replace with the desired version tag (e.g. `v0.18.3.1`) to build the release binaries.
|
||||
3. Prepare build environment
|
||||
```
|
||||
cd monero-gui
|
||||
@@ -221,15 +220,15 @@ Packaging for your favorite distribution would be a welcome contribution!
|
||||
|
||||
2. Install Qt:
|
||||
|
||||
*Note*: The Qt 5.9.7 or newer requirement makes **some** distributions (mostly based on debian, like Ubuntu 16.x or Linux Mint 18.x) obsolete due to their repositories containing an older Qt version.
|
||||
*Note*: The Qt 5.9.7 or newer requirement makes **some** distributions (mostly based on Debian, like Ubuntu 16.x or Linux Mint 18.x) obsolete due to their repositories containing an older Qt version.
|
||||
|
||||
The recommended way is to install 5.9.7 from the [official Qt installer](https://www.qt.io/download-qt-installer) or [compiling it yourself](https://wiki.qt.io/Install_Qt_5_on_Ubuntu). This ensures you have the correct version. Higher versions *can* work but as it differs from our production build target, slight differences may occur.
|
||||
|
||||
The following instructions will fetch Qt from your distribution's repositories instead. Take note of what version it installs. Your mileage may vary.
|
||||
|
||||
- For Ubuntu 17.10+
|
||||
- For Debian distributions (Debian, Ubuntu, Mint, Tails...)
|
||||
|
||||
`sudo apt install qtbase5-dev qt5-default qtdeclarative5-dev qml-module-qtqml-models2 qml-module-qtquick-controls qml-module-qtquick-controls2 qml-module-qtquick-dialogs qml-module-qtquick-xmllistmodel qml-module-qt-labs-settings qml-module-qt-labs-platform qml-module-qt-labs-folderlistmodel qttools5-dev-tools qml-module-qtquick-templates2 libqt5svg5-dev`
|
||||
`sudo apt install qtbase5-dev qtdeclarative5-dev qml-module-qtqml-models2 qml-module-qtquick-controls qml-module-qtquick-controls2 qml-module-qtquick-dialogs qml-module-qtquick-xmllistmodel qml-module-qt-labs-settings qml-module-qt-labs-platform qml-module-qt-labs-folderlistmodel qttools5-dev-tools qml-module-qtquick-templates2 libqt5svg5-dev`
|
||||
|
||||
- For Gentoo
|
||||
|
||||
@@ -240,7 +239,7 @@ The following instructions will fetch Qt from your distribution's repositories i
|
||||
|
||||
- Optional : To build the flag `WITH_SCANNER`
|
||||
|
||||
- For Ubuntu
|
||||
- For Debian distributions (Debian, Ubuntu, Mint, Tails...)
|
||||
|
||||
`sudo apt install qtmultimedia5-dev qml-module-qtmultimedia`
|
||||
|
||||
@@ -258,18 +257,10 @@ The following instructions will fetch Qt from your distribution's repositories i
|
||||
|
||||
4. Build
|
||||
|
||||
If on x86-64:
|
||||
|
||||
```
|
||||
make release -j4
|
||||
```
|
||||
|
||||
If on ppc64le:
|
||||
|
||||
```
|
||||
make release-linux-ppc64le -j4
|
||||
```
|
||||
|
||||
\* `4` - number of CPU threads to use
|
||||
\* Add `CMAKE_PREFIX_PATH` environment variable to set a custom Qt install directory, e.g. `CMAKE_PREFIX_PATH=$HOME/Qt/5.9.7/gcc_64 make release -j4`
|
||||
|
||||
@@ -319,7 +310,7 @@ The Monero GUI on Windows is 64 bits only; 32-bit Windows GUI builds are not off
|
||||
3. Install MSYS2 packages for Monero dependencies; the needed 64-bit packages have `x86_64` in their names
|
||||
|
||||
```
|
||||
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 mingw-w64-x86_64-unbound mingw-w64-x86_64-pcre
|
||||
```
|
||||
|
||||
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.
|
||||
|
||||
@@ -17,7 +17,33 @@ if(APPLE OR (WIN32 AND NOT STATIC))
|
||||
add_custom_command(TARGET deploy
|
||||
POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${_qt_svg_dylib} $<TARGET_FILE_DIR:monero-wallet-gui>/../PlugIns/imageformats/
|
||||
COMMENT "Copying libqsvg.dylib"
|
||||
COMMAND ${CMAKE_INSTALL_NAME_TOOL} -change "${CMAKE_PREFIX_PATH}/lib/QtGui.framework/Versions/5/QtGui" "@executable_path/../Frameworks/QtGui.framework/Versions/5/QtGui" $<TARGET_FILE_DIR:monero-wallet-gui>/../PlugIns/imageformats/libqsvg.dylib
|
||||
COMMAND ${CMAKE_INSTALL_NAME_TOOL} -change "${CMAKE_PREFIX_PATH}/lib/QtWidgets.framework/Versions/5/QtWidgets" "@executable_path/../Frameworks/QtWidgets.framework/Versions/5/QtWidgets" $<TARGET_FILE_DIR:monero-wallet-gui>/../PlugIns/imageformats/libqsvg.dylib
|
||||
COMMAND ${CMAKE_INSTALL_NAME_TOOL} -change "${CMAKE_PREFIX_PATH}/lib/QtSvg.framework/Versions/5/QtSvg" "@executable_path/../Frameworks/QtSvg.framework/Versions/5/QtSvg" $<TARGET_FILE_DIR:monero-wallet-gui>/../PlugIns/imageformats/libqsvg.dylib
|
||||
COMMAND ${CMAKE_INSTALL_NAME_TOOL} -change "${CMAKE_PREFIX_PATH}/lib/QtCore.framework/Versions/5/QtCore" "@executable_path/../Frameworks/QtCore.framework/Versions/5/QtCore" $<TARGET_FILE_DIR:monero-wallet-gui>/../PlugIns/imageformats/libqsvg.dylib
|
||||
COMMENT "Copying libqsvg.dylib, running install_name_tool"
|
||||
|
||||
)
|
||||
endif()
|
||||
|
||||
# libbost_filesyste-mt.dylib has a dependency on libboost_atomic-mt.dylib, maydeployqt does not copy it by itself
|
||||
find_package(Boost COMPONENTS atomic)
|
||||
get_target_property(BOOST_ATOMIC_LIB_PATH Boost::atomic LOCATION)
|
||||
if(EXISTS ${BOOST_ATOMIC_LIB_PATH})
|
||||
add_custom_command(TARGET deploy
|
||||
POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy "${BOOST_ATOMIC_LIB_PATH}" "$<TARGET_FILE_DIR:monero-wallet-gui>/../Frameworks/"
|
||||
COMMENT "Copying libboost_atomic-mt.dylib"
|
||||
)
|
||||
endif()
|
||||
|
||||
# Apple Silicon requires all binaries to be codesigned
|
||||
find_program(CODESIGN_EXECUTABLE NAMES codesign)
|
||||
if(CODESIGN_EXECUTABLE)
|
||||
add_custom_command(TARGET deploy
|
||||
POST_BUILD
|
||||
COMMAND "${CODESIGN_EXECUTABLE}" --force --deep --sign - "$<TARGET_FILE_DIR:monero-wallet-gui>/../.."
|
||||
COMMENT "Running codesign..."
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -42,7 +68,7 @@ if(APPLE OR (WIN32 AND NOT STATIC))
|
||||
zlib1.dll
|
||||
libzstd.dll
|
||||
libwinpthread-1.dll
|
||||
libtiff-5.dll
|
||||
libtiff-6.dll
|
||||
libstdc++-6.dll
|
||||
libpng16-16.dll
|
||||
libpcre16-0.dll
|
||||
@@ -58,7 +84,6 @@ if(APPLE OR (WIN32 AND NOT STATIC))
|
||||
libglib-2.0-0.dll
|
||||
libfreetype-6.dll
|
||||
libbz2-1.dll
|
||||
libssp-0.dll
|
||||
libpcre2-16-0.dll
|
||||
libhidapi-0.dll
|
||||
libdouble-conversion.dll
|
||||
@@ -69,24 +94,24 @@ if(APPLE OR (WIN32 AND NOT STATIC))
|
||||
#platform files
|
||||
libgcc_s_seh-1.dll
|
||||
#openssl files
|
||||
libssl-1_1-x64.dll
|
||||
libcrypto-1_1-x64.dll
|
||||
libssl-3-x64.dll
|
||||
libcrypto-3-x64.dll
|
||||
)
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
list(APPEND WIN_DEPLOY_DLLS
|
||||
libicudtd71.dll
|
||||
libicuind71.dll
|
||||
libicuiod71.dll
|
||||
libicutud71.dll
|
||||
libicuucd71.dll
|
||||
libicudtd73.dll
|
||||
libicuind73.dll
|
||||
libicuiod73.dll
|
||||
libicutud73.dll
|
||||
libicuucd73.dll
|
||||
)
|
||||
else() # assume release
|
||||
list(APPEND WIN_DEPLOY_DLLS
|
||||
libicudt71.dll
|
||||
libicuin71.dll
|
||||
libicuio71.dll
|
||||
libicutu71.dll
|
||||
libicuuc71.dll
|
||||
libicudt73.dll
|
||||
libicuin73.dll
|
||||
libicuio73.dll
|
||||
libicutu73.dll
|
||||
libicuuc73.dll
|
||||
)
|
||||
endif()
|
||||
list(TRANSFORM WIN_DEPLOY_DLLS PREPEND "$ENV{MSYSTEM_PREFIX}/bin/")
|
||||
|
||||
@@ -66,7 +66,7 @@ Item {
|
||||
anchors.fill: parent
|
||||
color: buttonArea.containsMouse ? MoneroComponents.Style.buttonInlineBackgroundColorHover : MoneroComponents.Style.buttonInlineBackgroundColor
|
||||
radius: 4
|
||||
|
||||
border.width: parent.focus && parent.enabled ? 1 : 0
|
||||
|
||||
MoneroComponents.TextPlain {
|
||||
id: inlineText
|
||||
|
||||
@@ -40,6 +40,8 @@ ColumnLayout {
|
||||
default property alias content: inlineButtons.children
|
||||
|
||||
property alias input: input
|
||||
property bool inputHasFocus: input.activeFocus
|
||||
property bool tabNavigationEnabled: true
|
||||
property alias text: input.text
|
||||
|
||||
property int inputPaddingLeft: 10
|
||||
@@ -109,6 +111,8 @@ ColumnLayout {
|
||||
signal editingFinished();
|
||||
signal accepted();
|
||||
signal textUpdated();
|
||||
signal backtabPressed();
|
||||
signal tabPressed();
|
||||
|
||||
onActiveFocusChanged: activeFocus && input.forceActiveFocus()
|
||||
onTextUpdated: {
|
||||
@@ -212,8 +216,18 @@ ColumnLayout {
|
||||
|
||||
MoneroComponents.Input {
|
||||
id: input
|
||||
KeyNavigation.backtab: item.KeyNavigation.backtab
|
||||
KeyNavigation.tab: item.KeyNavigation.tab
|
||||
Keys.onBacktabPressed: {
|
||||
item.backtabPressed();
|
||||
if (item.KeyNavigation.backtab) {
|
||||
item.KeyNavigation.backtab.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
Keys.onTabPressed: {
|
||||
item.tabPressed();
|
||||
if (item.KeyNavigation.tab) {
|
||||
item.KeyNavigation.tab.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: inputHeight
|
||||
|
||||
|
||||
@@ -92,7 +92,7 @@ Rectangle {
|
||||
anchors.leftMargin: 20
|
||||
height: parent.height
|
||||
width: 2
|
||||
color: button.checked ? MoneroComponents.Style.buttonBackgroundColor : "transparent"
|
||||
color: button.checked ? MoneroComponents.Style.accountColors[currentAccountIndex % MoneroComponents.Style.accountColors.length] : "transparent"
|
||||
|
||||
// button text
|
||||
MoneroComponents.TextPlain {
|
||||
|
||||
@@ -201,6 +201,7 @@ Rectangle {
|
||||
daemonManager.sendCommandAsync(
|
||||
["set_bootstrap_daemon", "auto"],
|
||||
appWindow.currentWallet.nettype,
|
||||
persistentSettings.blockchainDataDir,
|
||||
callback);
|
||||
|
||||
refreshMouseArea.visible = false;
|
||||
|
||||
@@ -81,6 +81,7 @@ QtObject {
|
||||
property string leftPanelBackgroundGradientStart: blackTheme ? _b_leftPanelBackgroundGradientStart : _w_leftPanelBackgroundGradientStart
|
||||
property string leftPanelBackgroundGradientStop: blackTheme ? _b_leftPanelBackgroundGradientStop : _w_leftPanelBackgroundGradientStop
|
||||
property string historyHeaderTextColor: blackTheme ? _b_historyHeaderTextColor : _w_historyHeaderTextColor
|
||||
property var accountColors: blackTheme ? _b_accountColors : _w_accountColors
|
||||
|
||||
property string _b_defaultFontColor: "white"
|
||||
property string _b_dimmedFontColor: "#BBBBBB"
|
||||
@@ -142,6 +143,7 @@ QtObject {
|
||||
property string _b_leftPanelBackgroundGradientStart: "#222222"
|
||||
property string _b_leftPanelBackgroundGradientStop: "#1a1a1a"
|
||||
property string _b_historyHeaderTextColor: "#C0C0C0"
|
||||
property var _b_accountColors: ["#6E513C", "#842129", "#458421", "#742184", "#291DBE", "#846F21", "#217F84", "#696969"]
|
||||
|
||||
property string _w_defaultFontColor: "black"
|
||||
property string _w_dimmedFontColor: "#3f3f3f"
|
||||
@@ -203,4 +205,5 @@ QtObject {
|
||||
property string _w_leftPanelBackgroundGradientStart: "white"
|
||||
property string _w_leftPanelBackgroundGradientStop: "#f5f5f5"
|
||||
property string _w_historyHeaderTextColor: "#515151"
|
||||
property var _w_accountColors: ["#6E513C", "#6E513C", "#842129", "#458421", "#742184", "#291DBE", "#846F21", "#217F84", "#696969"]
|
||||
}
|
||||
|
||||
@@ -21,6 +21,14 @@ Text {
|
||||
font.pixelSize: 14
|
||||
textFormat: Text.PlainText
|
||||
|
||||
Rectangle {
|
||||
width: root.contentWidth
|
||||
height: root.height
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.top
|
||||
color: root.focus ? MoneroComponents.Style.titleBarButtonHoverColor : "transparent"
|
||||
}
|
||||
|
||||
MoneroEffects.ColorTransition {
|
||||
enabled: root.themeTransition
|
||||
themeTransition: root.themeTransition
|
||||
|
||||
0
images/card-background-black.png → images/card-background-black0.png
Executable file → Normal file
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
0
images/card-background-black@2x.png → images/card-background-black0@2x.png
Executable file → Normal file
|
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 68 KiB |
BIN
images/card-background-black1.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
images/card-background-black1@2x.png
Normal file
|
After Width: | Height: | Size: 52 KiB |
BIN
images/card-background-black2.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
images/card-background-black2@2x.png
Normal file
|
After Width: | Height: | Size: 52 KiB |
BIN
images/card-background-black3.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
images/card-background-black3@2x.png
Normal file
|
After Width: | Height: | Size: 53 KiB |
BIN
images/card-background-black4.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
images/card-background-black4@2x.png
Normal file
|
After Width: | Height: | Size: 52 KiB |
BIN
images/card-background-black5.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
images/card-background-black5@2x.png
Normal file
|
After Width: | Height: | Size: 52 KiB |
BIN
images/card-background-black6.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
images/card-background-black6@2x.png
Normal file
|
After Width: | Height: | Size: 53 KiB |
BIN
images/card-background-black7.png
Normal file
|
After Width: | Height: | Size: 7.0 KiB |
BIN
images/card-background-black7@2x.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
images/ledgerStax.png
Normal file
|
After Width: | Height: | Size: 41 KiB |
BIN
images/verify-white.png
Normal file
|
After Width: | Height: | Size: 956 B |
BIN
images/verify-white@2x.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
images/verify.png
Normal file
|
After Width: | Height: | Size: 854 B |
BIN
images/verify@2x.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
images/write-down-white.png
Normal file
|
After Width: | Height: | Size: 779 B |
BIN
images/write-down-white@2x.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
images/write-down.png
Normal file
|
After Width: | Height: | Size: 728 B |
BIN
images/write-down@2x.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
@@ -167,7 +167,6 @@ Type: files; Name: "{app}\libstdc++-6.dll"
|
||||
Type: files; Name: "{app}\libtiff-5.dll"
|
||||
Type: files; Name: "{app}\libwinpthread-1.dll"
|
||||
Type: files; Name: "{app}\zlib1.dll"
|
||||
Type: files; Name: "{app}\libssp-0.dll"
|
||||
Type: files; Name: "{app}\libhidapi-0.dll"
|
||||
Type: files; Name: "{app}\libeay32.dll"
|
||||
Type: files; Name: "{app}\ssleay32.dll"
|
||||
|
||||
@@ -56,11 +56,14 @@
|
||||
i.e. let it download the blockchain and store it locally on your computer, or you can configure your wallet to
|
||||
access a remote <i>open node</i> to get indirect access to the blockchain.</p>
|
||||
|
||||
<p>Working with your own copy of the blockchain is <b>preferred</b>: It strengthens the Monero network, and it
|
||||
<p>You can also <i>Prune</i> the blockchain in order to save 2/3 of storage space while keeping the full transaction history.
|
||||
More information regarding how pruning works can be found <a href="https://www.getmonero.org/resources/moneropedia/pruning.html">here</a>.</p>
|
||||
|
||||
<p>Working with your own copy of the blockchain, even pruned, is <b>preferred</b>: It strengthens the Monero network, and it
|
||||
provides the most security and privacy possible for you.</p>
|
||||
|
||||
<p>However if your Internet access makes it difficult to run a full node, or if you have simply no room to store
|
||||
the blockchain locally (about 90 GB in May 2020, and of course growing), you can compromise and try to connect
|
||||
the blockchain locally (about 160 GB in June 2023, and of course growing), you can compromise and try to connect
|
||||
to a remote node. One way of finding such a node is checking
|
||||
<a href="https://moneroworld.com/#nodes">this page</a>.
|
||||
</p>
|
||||
|
||||
@@ -76,3 +76,34 @@ function isValidOpenAliasAddress(address) {
|
||||
// make sure it is not some kind of floating number
|
||||
return address.length > 2 && isNaN(parseFloat(address)) && address.indexOf('.') >= 0
|
||||
}
|
||||
|
||||
function handleOpenAliasResolution(address, descriptionText) {
|
||||
const result = walletManager.resolveOpenAlias(address);
|
||||
if (!result) {
|
||||
return { message: qsTr("No address found") };
|
||||
}
|
||||
|
||||
const [isDnssecValid, resolvedAddress] = result.split("|");
|
||||
const isAddressValid = walletManager.addressValid(resolvedAddress, appWindow.persistentSettings.nettype);
|
||||
let updatedDescriptionText = descriptionText;
|
||||
|
||||
if (isDnssecValid === "true") {
|
||||
if (isAddressValid) {
|
||||
updatedDescriptionText = descriptionText ? `${address} ${descriptionText}` : address;
|
||||
return { address: resolvedAddress, description: updatedDescriptionText };
|
||||
} else {
|
||||
return { message: qsTr("No valid address found at this OpenAlias address") };
|
||||
}
|
||||
} else if (isDnssecValid === "false") {
|
||||
if (isAddressValid) {
|
||||
return {
|
||||
address: resolvedAddress,
|
||||
message: qsTr("Address found, but the DNSSEC signatures could not be verified, so this address may be spoofed"),
|
||||
};
|
||||
} else {
|
||||
return { message: qsTr("No valid address found at this OpenAlias address, but the DNSSEC signatures could not be verified, so this may be spoofed") };
|
||||
}
|
||||
} else {
|
||||
return { message: qsTr("Internal error") };
|
||||
}
|
||||
}
|
||||
|
||||
10
js/Utils.js
@@ -57,12 +57,12 @@ function ago(epoch) {
|
||||
|
||||
if(delta < 60)
|
||||
return qsTr("%n second(s) ago", "0", Math.floor(delta))
|
||||
else if (delta >= 60 && delta <= 3600)
|
||||
else if (delta < 3600)
|
||||
return qsTr("%n minute(s) ago", "0", Math.floor(delta / 60))
|
||||
else if (delta >= 3600 && delta <= 86400)
|
||||
return qsTr("%n hour(s) ago", "0", Math.floor(delta / 60 / 60))
|
||||
else if (delta >= 86400)
|
||||
return qsTr("%n day(s) ago", "0", Math.floor(delta / 24 / 60 / 60))
|
||||
else if (delta < 86400)
|
||||
return qsTr("%n hour(s) ago", "0", Math.floor(delta / 3600))
|
||||
else
|
||||
return qsTr("%n day(s) ago", "0", Math.floor(delta / 86400))
|
||||
}
|
||||
|
||||
function netTypeToString(){
|
||||
|
||||
40
main.qml
@@ -94,7 +94,7 @@ ApplicationWindow {
|
||||
readonly property string localDaemonAddress : "localhost:" + getDefaultDaemonRpcPort(persistentSettings.nettype)
|
||||
property string currentDaemonAddress;
|
||||
property int disconnectedEpoch: 0
|
||||
property int estimatedBlockchainSize: persistentSettings.pruneBlockchain ? 40 : 105 // GB
|
||||
property int estimatedBlockchainSize: persistentSettings.pruneBlockchain ? 55 : 150 // GB
|
||||
property alias viewState: rootItem.state
|
||||
property string prevSplashText;
|
||||
property bool splashDisplayedBeforeButtonRequest;
|
||||
@@ -379,7 +379,7 @@ ApplicationWindow {
|
||||
}
|
||||
|
||||
function isTrustedDaemon() {
|
||||
return !persistentSettings.useRemoteNode || remoteNodesModel.currentRemoteNode().trusted;
|
||||
return appWindow.walletMode >= 2 && (!persistentSettings.useRemoteNode || remoteNodesModel.currentRemoteNode().trusted);
|
||||
}
|
||||
|
||||
function usefulName(path) {
|
||||
@@ -469,7 +469,7 @@ ApplicationWindow {
|
||||
|
||||
// If wallet isnt connected, advanced wallet mode and no daemon is running - Ask
|
||||
if (appWindow.walletMode >= 2 && !persistentSettings.useRemoteNode && !walletInitialized && disconnected) {
|
||||
daemonManager.runningAsync(persistentSettings.nettype, function(running) {
|
||||
daemonManager.runningAsync(persistentSettings.nettype, persistentSettings.blockchainDataDir, function(running) {
|
||||
if (!running) {
|
||||
daemonManagerDialog.open();
|
||||
}
|
||||
@@ -602,6 +602,9 @@ ApplicationWindow {
|
||||
function connectRemoteNode() {
|
||||
console.log("connecting remote node");
|
||||
|
||||
p2poolManager.exit();
|
||||
p2poolManager.getStatus();
|
||||
|
||||
const callback = function() {
|
||||
persistentSettings.useRemoteNode = true;
|
||||
const remoteNode = remoteNodesModel.currentRemoteNode();
|
||||
@@ -630,6 +633,10 @@ ApplicationWindow {
|
||||
return;
|
||||
|
||||
console.log("disconnecting remote node");
|
||||
|
||||
p2poolManager.exit();
|
||||
p2poolManager.getStatus();
|
||||
|
||||
persistentSettings.useRemoteNode = false;
|
||||
currentDaemonAddress = localDaemonAddress
|
||||
currentWallet.setDaemonLogin("", "");
|
||||
@@ -694,7 +701,8 @@ ApplicationWindow {
|
||||
// Daemon connected
|
||||
leftPanel.networkStatus.connected = currentWallet ? currentWallet.connected() : Wallet.ConnectionStatus_Disconnected
|
||||
|
||||
currentWallet.refreshHeightAsync();
|
||||
if (currentWallet)
|
||||
currentWallet.refreshHeightAsync();
|
||||
}
|
||||
|
||||
function startDaemon(flags){
|
||||
@@ -714,7 +722,7 @@ ApplicationWindow {
|
||||
appWindow.showProcessingSplash(qsTr("Waiting for daemon to stop..."));
|
||||
}
|
||||
p2poolManager.exit()
|
||||
daemonManager.stopAsync(persistentSettings.nettype, function(result) {
|
||||
daemonManager.stopAsync(persistentSettings.nettype, persistentSettings.blockchainDataDir, function(result) {
|
||||
daemonStartStopInProgress = 0;
|
||||
if (splash) {
|
||||
hideProcessingSplash();
|
||||
@@ -747,6 +755,12 @@ ApplicationWindow {
|
||||
currentWallet.startRefresh();
|
||||
informationPopup.title = qsTr("Daemon failed to start") + translationManager.emptyString;
|
||||
informationPopup.text = error + ".\n\n" + qsTr("Please check your wallet and daemon log for errors. You can also try to start %1 manually.").arg((isWindows)? "monerod.exe" : "monerod")
|
||||
if (middlePanel.advancedView.miningView.stopMiningEnabled == true) {
|
||||
walletManager.stopMining()
|
||||
p2poolManager.exit()
|
||||
middlePanel.advancedView.miningView.update()
|
||||
informationPopup.text += qsTr("\n\nExiting p2pool. Please check that port 18083 is available.") + translationManager.emptyString;
|
||||
}
|
||||
informationPopup.icon = StandardIcon.Critical
|
||||
informationPopup.onCloseCallback = null
|
||||
informationPopup.open();
|
||||
@@ -1118,6 +1132,7 @@ ApplicationWindow {
|
||||
middlePanel.transferView.clearFields();
|
||||
middlePanel.receiveView.clearFields();
|
||||
middlePanel.historyView.clearFields();
|
||||
middlePanel.advancedView.clearFields();
|
||||
// disable timers
|
||||
userInActivityTimer.running = false;
|
||||
});
|
||||
@@ -1395,7 +1410,7 @@ ApplicationWindow {
|
||||
property bool historyShowAdvanced: false
|
||||
property bool historyHumanDates: true
|
||||
property string blockchainDataDir: ""
|
||||
property bool useRemoteNode: false
|
||||
property bool useRemoteNode: isAndroid
|
||||
property string remoteNodeAddress: "" // TODO: drop after v0.17.2.0 release
|
||||
property string remoteNodesSerialized: JSON.stringify({
|
||||
selected: 0,
|
||||
@@ -1445,8 +1460,15 @@ ApplicationWindow {
|
||||
function getWalletProxyAddress() {
|
||||
if (!useRemoteNode) {
|
||||
return "";
|
||||
} else {
|
||||
const remoteAddress = remoteNodesModel.currentRemoteNode().address;
|
||||
// skip proxy when using localhost remote node
|
||||
if (remoteAddress.startsWith("127.0.0.1:") || remoteAddress.startsWith("localhost:")) {
|
||||
return "";
|
||||
} else {
|
||||
return getProxyAddress();
|
||||
}
|
||||
}
|
||||
return getProxyAddress();
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
@@ -2141,7 +2163,7 @@ ApplicationWindow {
|
||||
if (currentWallet) {
|
||||
handler(!currentWallet.disconnected);
|
||||
} else {
|
||||
daemonManager.runningAsync(persistentSettings.nettype, handler);
|
||||
daemonManager.runningAsync(persistentSettings.nettype, persistentSettings.blockchainDataDir, handler);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2164,7 +2186,7 @@ ApplicationWindow {
|
||||
|
||||
function getBuildTag() {
|
||||
if (isMac) {
|
||||
return "mac-x64";
|
||||
return isARM ? "mac-armv8" : "mac-x64";
|
||||
}
|
||||
if (isWindows) {
|
||||
return oshelper.installed ? "install-win-x64" : "win-x64";
|
||||
|
||||
2
monero
@@ -238,7 +238,7 @@ Rectangle {
|
||||
Layout.fillHeight: true
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
color: "darkgrey"
|
||||
color: MoneroComponents.Style.accountColors[currentAccountIndex % MoneroComponents.Style.accountColors.length]
|
||||
width: 2
|
||||
}
|
||||
|
||||
|
||||
@@ -387,34 +387,17 @@ Rectangle {
|
||||
visible: TxUtils.isValidOpenAliasAddress(addressLine.text)
|
||||
enabled : visible
|
||||
onClicked: {
|
||||
var result = walletManager.resolveOpenAlias(addressLine.text)
|
||||
if (result) {
|
||||
var parts = result.split("|")
|
||||
if (parts.length === 2) {
|
||||
var address_ok = walletManager.addressValid(parts[1], appWindow.persistentSettings.nettype)
|
||||
if (parts[0] === "true") {
|
||||
if (address_ok) {
|
||||
// prepend openalias to description
|
||||
descriptionLine.text = descriptionLine.text ? addressLine.text + " " + descriptionLine.text : addressLine.text
|
||||
addressLine.text = parts[1]
|
||||
} else {
|
||||
root.oa_message(qsTr("No valid address found at this OpenAlias address"))
|
||||
}
|
||||
} else if (parts[0] === "false") {
|
||||
if (address_ok) {
|
||||
addressLine.text = parts[1]
|
||||
root.oa_message(qsTr("Address found, but the DNSSEC signatures could not be verified, so this address may be spoofed"))
|
||||
} else {
|
||||
root.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 {
|
||||
root.oa_message(qsTr("Internal error"))
|
||||
}
|
||||
} else {
|
||||
root.oa_message(qsTr("Internal error"))
|
||||
const response = TxUtils.handleOpenAliasResolution(addressLine.text, descriptionLine.text);
|
||||
if (response) {
|
||||
if (response.message) {
|
||||
oa_message(response.message);
|
||||
}
|
||||
if (response.address) {
|
||||
addressLine.text = response.address;
|
||||
}
|
||||
if (response.description) {
|
||||
descriptionLine.text = response.description;
|
||||
}
|
||||
} else {
|
||||
root.oa_message(qsTr("No address found"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,6 +40,8 @@ ColumnLayout {
|
||||
spacing: 0
|
||||
property int panelHeight: 900
|
||||
property alias miningView: stateView.miningView
|
||||
property alias signView: stateView.signView
|
||||
property alias prooveView: stateView.prooveView
|
||||
property alias state: stateView.state
|
||||
|
||||
MoneroComponents.Navbar {
|
||||
@@ -52,6 +54,7 @@ ColumnLayout {
|
||||
active: state == "Mining"
|
||||
text: qsTr("Mining") + translationManager.emptyString
|
||||
onSelected: state = "Mining"
|
||||
visible: !isAndroid
|
||||
}
|
||||
MoneroComponents.NavbarItem {
|
||||
active: state == "Prove"
|
||||
@@ -81,7 +84,7 @@ ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: panelHeight
|
||||
color: "transparent"
|
||||
state: "Mining"
|
||||
state: isAndroid ? "Prove" : "Mining"
|
||||
|
||||
onCurrentViewChanged: {
|
||||
if (previousView) {
|
||||
@@ -120,7 +123,7 @@ ColumnLayout {
|
||||
|
||||
StackView {
|
||||
id: stackView
|
||||
initialItem: stateView.miningView
|
||||
initialItem: isAndroid ? stateView.prooveView : stateView.miningView
|
||||
anchors.fill: parent
|
||||
clip: false // otherwise animation will affect left panel
|
||||
|
||||
@@ -146,4 +149,10 @@ ColumnLayout {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function clearFields() {
|
||||
signView.clearFields();
|
||||
prooveView.clearFields();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1765,18 +1765,25 @@ Rectangle {
|
||||
var written = currentWallet.history.writeCSV(currentWallet.currentSubaddressAccount, dataDir);
|
||||
|
||||
if(written !== ""){
|
||||
informationPopup.title = qsTr("Success") + translationManager.emptyString;
|
||||
confirmationDialog.title = qsTr("Success") + translationManager.emptyString;
|
||||
var text = qsTr("CSV file written to: %1").arg(written) + "\n\n"
|
||||
text += qsTr("Tip: Use your favorite spreadsheet software to sort on blockheight.") + "\n\n" + translationManager.emptyString;
|
||||
informationPopup.text = text;
|
||||
informationPopup.icon = StandardIcon.Information;
|
||||
confirmationDialog.text = text;
|
||||
confirmationDialog.icon = StandardIcon.Information;
|
||||
confirmationDialog.cancelText = qsTr("Open folder") + translationManager.emptyString;
|
||||
confirmationDialog.onAcceptedCallback = null;
|
||||
confirmationDialog.onRejectedCallback = function() {
|
||||
oshelper.openContainingFolder(written);
|
||||
}
|
||||
confirmationDialog.open();
|
||||
} else {
|
||||
informationPopup.title = qsTr("Error") + translationManager.emptyString;
|
||||
informationPopup.text = qsTr("Error exporting transaction data.") + "\n\n" + translationManager.emptyString;
|
||||
informationPopup.icon = StandardIcon.Critical;
|
||||
informationPopup.onCloseCallback = null;
|
||||
informationPopup.open();
|
||||
|
||||
}
|
||||
informationPopup.onCloseCallback = null;
|
||||
informationPopup.open();
|
||||
}
|
||||
Component.onCompleted: {
|
||||
var _folder = 'file://' + appWindow.accountsDir;
|
||||
|
||||
@@ -41,7 +41,8 @@ Rectangle {
|
||||
property alias miningHeight: mainLayout.height
|
||||
property double currentHashRate: 0
|
||||
property int threads: idealThreadCount / 2
|
||||
|
||||
property alias stopMiningEnabled: stopSoloMinerButton.enabled
|
||||
property string args: ""
|
||||
ColumnLayout {
|
||||
id: mainLayout
|
||||
Layout.fillWidth: true
|
||||
@@ -293,11 +294,12 @@ Rectangle {
|
||||
var success;
|
||||
if (persistentSettings.allow_p2pool_mining) {
|
||||
if (p2poolManager.isInstalled()) {
|
||||
if (persistentSettings.allowRemoteNodeMining) {
|
||||
args = daemonManager.getArgs(persistentSettings.blockchainDataDir) //updates arguments
|
||||
if (persistentSettings.allowRemoteNodeMining || (args.includes("--zmq-pub tcp://127.0.0.1:18083") || args.includes("--zmq-pub=tcp://127.0.0.1:18083")) && !args.includes("--no-zmq")) {
|
||||
startP2Pool()
|
||||
}
|
||||
else {
|
||||
daemonManager.stopAsync(persistentSettings.nettype, startP2PoolLocal)
|
||||
daemonManager.stopAsync(persistentSettings.nettype, persistentSettings.blockchainDataDir, startP2PoolLocal)
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -585,12 +587,35 @@ Rectangle {
|
||||
|
||||
function startP2PoolLocal() {
|
||||
var noSync = false;
|
||||
var customDaemonArgs = persistentSettings.daemonFlags.toLowerCase();
|
||||
var daemonArgs = "--zmq-pub " + "tcp://127.0.0.1:18083 " + "--disable-dns-checkpoints "
|
||||
if (!customDaemonArgs.includes("--zmq-pub") && !customDaemonArgs.includes("--disable-dns-checkpoints") && !customDaemonArgs.includes("--no-zmq")) {
|
||||
daemonArgs = daemonArgs + customDaemonArgs;
|
||||
//these args will be deleted because DaemonManager::start will re-add them later.
|
||||
//--no-zmq must be deleted. removing '--zmq-pub=tcp...' lets us blindly add '--zmq-pub tcp...' later without risking duplication.
|
||||
var defaultArgs = ["--detach","--data-dir","--bootstrap-daemon-address","--prune-blockchain","--no-sync","--check-updates","--non-interactive","--max-concurrency","--no-zmq","--zmq-pub=tcp://127.0.0.1:18083"]
|
||||
var customDaemonArgsArray = args.split(' ');
|
||||
var flag = "";
|
||||
var allArgs = [];
|
||||
var p2poolArgs = ["--zmq-pub tcp://127.0.0.1:18083"];
|
||||
//create an array (allArgs) of ['--arg value','--arg2','--arg3']
|
||||
for (let i = 0; i < customDaemonArgsArray.length; i++) {
|
||||
if(!customDaemonArgsArray[i].startsWith("--")) {
|
||||
flag += " " + customDaemonArgsArray[i]
|
||||
} else {
|
||||
if(flag){
|
||||
allArgs.push(flag)
|
||||
}
|
||||
flag = customDaemonArgsArray[i]
|
||||
}
|
||||
}
|
||||
var success = daemonManager.start(daemonArgs, persistentSettings.nettype, persistentSettings.blockchainDataDir, persistentSettings.bootstrapNodeAddress, noSync, persistentSettings.pruneBlockchain)
|
||||
allArgs.push(flag)
|
||||
//pop from allArgs if value is inside the deleteme array (defaultArgs)
|
||||
allArgs = allArgs.filter( ( el ) => !defaultArgs.includes( el.split(" ")[0] ) )
|
||||
//append required p2pool flags
|
||||
for (let i = 0; i < p2poolArgs.length; i++) {
|
||||
if(!allArgs.includes(p2poolArgs[i])) {
|
||||
allArgs.push(p2poolArgs[i])
|
||||
continue
|
||||
}
|
||||
}
|
||||
var success = daemonManager.start(allArgs.join(" "), persistentSettings.nettype, persistentSettings.blockchainDataDir, persistentSettings.bootstrapNodeAddress, noSync, persistentSettings.pruneBlockchain)
|
||||
if (success) {
|
||||
startP2Pool()
|
||||
}
|
||||
@@ -616,10 +641,25 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
|
||||
function p2poolDownloadFailed() {
|
||||
function p2poolDownloadFailed(errorCode) {
|
||||
statusMessage.visible = false
|
||||
errorPopup.title = qsTr("P2Pool Installation Failed") + translationManager.emptyString;
|
||||
errorPopup.text = qsTr("P2Pool installation failed.") + isWindows ? (" " + qsTr("Try starting the program with administrator privileges.")) : ""
|
||||
switch (errorCode) {
|
||||
case P2PoolManager.HashVerificationFailed:
|
||||
errorPopup.text = qsTr("Hash verification failed.") + translationManager.emptyString;
|
||||
break;
|
||||
case P2PoolManager.BinaryNotAvailable:
|
||||
errorPopup.text = qsTr("P2Pool download is not available.") + translationManager.emptyString;
|
||||
break;
|
||||
case P2PoolManager.ConnectionIssue:
|
||||
errorPopup.text = qsTr("P2Pool download failed due to a connection issue.") + translationManager.emptyString;
|
||||
break;
|
||||
case P2PoolManager.InstallationFailed:
|
||||
errorPopup.text = qsTr("P2Pool installation failed.") + (isWindows ? (" " + qsTr("Try starting the program with administrator privileges.")) : "")
|
||||
break;
|
||||
default:
|
||||
errorPopup.text = qsTr("Unknown error.") + translationManager.emptyString;
|
||||
}
|
||||
errorPopup.icon = StandardIcon.Critical
|
||||
errorPopup.open()
|
||||
update()
|
||||
|
||||
@@ -580,7 +580,8 @@ Rectangle {
|
||||
Layout.fillHeight: true
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
color: "darkgrey"
|
||||
property int currentAccountIndex: currentWallet ? currentWallet.currentSubaddressAccount : 0
|
||||
color: MoneroComponents.Style.accountColors[currentAccountIndex % MoneroComponents.Style.accountColors.length]
|
||||
width: 2
|
||||
}
|
||||
|
||||
|
||||
@@ -50,15 +50,6 @@ Rectangle {
|
||||
return true
|
||||
}
|
||||
|
||||
function validUnsigned(s) {
|
||||
if (s.length == 0)
|
||||
return false
|
||||
for (var i = 0; i < s.length; ++i)
|
||||
if ("0123456789".indexOf(s[i]) == -1)
|
||||
return false
|
||||
return true
|
||||
}
|
||||
|
||||
function validRing(str, relative) {
|
||||
var outs = str.split(" ");
|
||||
if (outs.length == 0)
|
||||
@@ -109,136 +100,6 @@ Rectangle {
|
||||
color: MoneroComponents.Style.defaultFontColor
|
||||
}
|
||||
|
||||
MoneroComponents.LabelSubheader {
|
||||
Layout.fillWidth: true
|
||||
textFormat: Text.RichText
|
||||
text: qsTr("Outputs marked as spent") + translationManager.emptyString
|
||||
tooltip: qsTr(
|
||||
"In order to obscure which inputs in a Monero transaction are being spent, a third party should not be able " +
|
||||
"to tell which inputs in a ring are already known to be spent. Being able to do so would weaken the protection " +
|
||||
"afforded by ring signatures. If all but one of the inputs are known to be already spent, then the input being " +
|
||||
"actually spent becomes apparent, thereby nullifying the effect of ring signatures, one of the three main layers " +
|
||||
"of privacy protection Monero uses.<br>" +
|
||||
"To help transactions avoid those inputs, a list of known spent ones can be used to avoid using them in new " +
|
||||
"transactions. Such a list is maintained by the Monero project and is available on the getmonero.org website, " +
|
||||
"and you can import this list here.<br>" +
|
||||
"Alternatively, you can scan the blockchain (and the blockchain of key-reusing Monero clones) yourself " +
|
||||
"using the monero-blockchain-mark-spent-outputs tool to create a list of known spent outputs.<br>"
|
||||
) + translationManager.emptyString
|
||||
}
|
||||
|
||||
MoneroComponents.TextPlain {
|
||||
textFormat: Text.RichText
|
||||
font.family: MoneroComponents.Style.fontRegular.name
|
||||
font.pixelSize: 14
|
||||
text: qsTr("This sets which outputs are known to be spent, and thus not to be used as privacy placeholders in ring signatures. ") +
|
||||
qsTr("You should only have to load a file when you want to refresh the list. Manual adding/removing is possible if needed.") + translationManager.emptyString
|
||||
wrapMode: Text.Wrap
|
||||
Layout.fillWidth: true;
|
||||
color: MoneroComponents.Style.defaultFontColor
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 12
|
||||
|
||||
FileDialog {
|
||||
id: loadBlackballFileDialog
|
||||
title: qsTr("Please choose a file from which to load outputs to mark as spent") + translationManager.emptyString;
|
||||
folder: "file://"
|
||||
nameFilters: ["*"]
|
||||
|
||||
onAccepted: {
|
||||
loadBlackballFileLine.text = walletManager.urlToLocalPath(loadBlackballFileDialog.fileUrl)
|
||||
}
|
||||
}
|
||||
|
||||
MoneroComponents.LineEdit {
|
||||
id: loadBlackballFileLine
|
||||
Layout.fillWidth: true
|
||||
fontSize: 16
|
||||
placeholderFontSize: 16
|
||||
placeholderText: qsTr("Path to file") + "..." + translationManager.emptyString
|
||||
labelFontSize: 14
|
||||
labelText: qsTr("Filename with outputs to mark as spent") + ":" + translationManager.emptyString
|
||||
copyButton: true
|
||||
readOnly: false
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 18
|
||||
|
||||
MoneroComponents.StandardButton {
|
||||
id: selectBlackballFileButton
|
||||
text: qsTr("Browse") + translationManager.emptyString
|
||||
enabled: true
|
||||
small: true
|
||||
onClicked: {
|
||||
loadBlackballFileDialog.open()
|
||||
}
|
||||
}
|
||||
|
||||
MoneroComponents.StandardButton {
|
||||
id: loadBlackballFileButton
|
||||
text: qsTr("Load") + translationManager.emptyString
|
||||
small: true
|
||||
enabled: !!appWindow.currentWallet && loadBlackballFileLine.text !== ""
|
||||
onClicked: appWindow.currentWallet.blackballOutputs(walletManager.urlToLocalPath(loadBlackballFileDialog.fileUrl), true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GridLayout {
|
||||
Layout.fillWidth: true
|
||||
columnSpacing: 20
|
||||
|
||||
MoneroComponents.LineEdit {
|
||||
id: blackballOutputAmountLine
|
||||
Layout.fillWidth: true
|
||||
fontSize: 16
|
||||
labelFontSize: 14
|
||||
labelText: qsTr("Or manually mark a single output as spent/unspent:") + translationManager.emptyString
|
||||
placeholderFontSize: 16
|
||||
placeholderText: qsTr("Paste output amount") + "..." + translationManager.emptyString
|
||||
readOnly: false
|
||||
validator: IntValidator { bottom: 0 }
|
||||
}
|
||||
|
||||
MoneroComponents.LineEdit {
|
||||
id: blackballOutputOffsetLine
|
||||
Layout.fillWidth: true
|
||||
fontSize: 16
|
||||
labelFontSize: 14
|
||||
labelText: " "
|
||||
placeholderFontSize: 16
|
||||
placeholderText: qsTr("Paste output offset") + "..." + translationManager.emptyString
|
||||
readOnly: false
|
||||
validator: IntValidator { bottom: 0 }
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 18
|
||||
|
||||
MoneroComponents.StandardButton {
|
||||
id: blackballButton
|
||||
text: qsTr("Mark as spent") + translationManager.emptyString
|
||||
small: true
|
||||
enabled: !!appWindow.currentWallet && validUnsigned(blackballOutputAmountLine.text) && validUnsigned(blackballOutputOffsetLine.text)
|
||||
onClicked: appWindow.currentWallet.blackballOutput(blackballOutputAmountLine.text, blackballOutputOffsetLine.text)
|
||||
}
|
||||
|
||||
MoneroComponents.StandardButton {
|
||||
id: unblackballButton
|
||||
text: qsTr("Mark as unspent") + translationManager.emptyString
|
||||
small: true
|
||||
enabled: !!appWindow.currentWallet && validUnsigned(blackballOutputAmountLine.text) && validUnsigned(blackballOutputOffsetLine.text)
|
||||
onClicked: appWindow.currentWallet.unblackballOutput(blackballOutputAmountLine.text, blackballOutputOffsetLine.text)
|
||||
}
|
||||
}
|
||||
|
||||
MoneroComponents.LabelSubheader {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 24
|
||||
|
||||
@@ -421,6 +421,16 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
|
||||
function clearFields() {
|
||||
verifyMessageLine.text = ""
|
||||
signMessageLine.text = ""
|
||||
signSignatureLine.text = ""
|
||||
verifyAddressLine.text = ""
|
||||
verifySignatureLine.text = ""
|
||||
signFileLine.text = ""
|
||||
verifyFileLine.text = ""
|
||||
}
|
||||
|
||||
function onPageCompleted() {
|
||||
console.log("Sign/verify page loaded");
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ Rectangle {
|
||||
color: "transparent"
|
||||
property alias transferHeight1: pageRoot.height
|
||||
property alias transferHeight2: advancedLayout.height
|
||||
property int mixin: 10 // (ring size 11)
|
||||
property int mixin: 15 // (ring size 16)
|
||||
property string warningContent: ""
|
||||
property string sendButtonWarning: {
|
||||
// Currently opened wallet is not view-only
|
||||
@@ -415,41 +415,18 @@ Rectangle {
|
||||
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"))
|
||||
}
|
||||
const response = TxUtils.handleOpenAliasResolution(address, descriptionLine.text);
|
||||
if (response) {
|
||||
if (response.message) {
|
||||
oa_message(response.message);
|
||||
}
|
||||
else {
|
||||
oa_message(qsTr("Internal error"))
|
||||
if (response.address) {
|
||||
recipientRepeater.itemAt(index).children[1].children[0].text = response.address;
|
||||
}
|
||||
if (response.description) {
|
||||
descriptionLine.text = response.description;
|
||||
descriptionCheckbox.checked = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
oa_message(qsTr("No address found"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -259,6 +259,17 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
|
||||
function clearFields() {
|
||||
checkProofAddressLine.text = ""
|
||||
checkProofMessageLine.text = ""
|
||||
checkProofSignatureLine.text = ""
|
||||
checkProofTxIdLine.text = ""
|
||||
getProofAddressLine.text = ""
|
||||
getProofMessageLine.text = ""
|
||||
getProofTxIdLine.text = ""
|
||||
getReserveProofAmtLine.text = ""
|
||||
}
|
||||
|
||||
function onPageCompleted() {
|
||||
console.log("TxKey page loaded");
|
||||
|
||||
|
||||
@@ -74,6 +74,7 @@ ColumnLayout {
|
||||
active: settingsStateView.state == "Log"
|
||||
text: qsTr("Log") + translationManager.emptyString
|
||||
onSelected: settingsStateView.state = "Log"
|
||||
visible: !isAndroid
|
||||
}
|
||||
MoneroComponents.NavbarItem {
|
||||
active: settingsStateView.state == "Info"
|
||||
|
||||
@@ -254,7 +254,7 @@ Rectangle {
|
||||
onAccepted: {
|
||||
if(text.length > 0) {
|
||||
consoleArea.logCommand(">>> " + text)
|
||||
daemonManager.sendCommandAsync(text.split(" "), currentWallet.nettype, function(result) {
|
||||
daemonManager.sendCommandAsync(text.split(" "), currentWallet.nettype, persistentSettings.blockchainDataDir, function(result) {
|
||||
if (!result) {
|
||||
appWindow.showStatusMessage(qsTr("Failed to send command"), 3);
|
||||
}
|
||||
|
||||
@@ -55,6 +55,7 @@ Rectangle{
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 90
|
||||
color: "transparent"
|
||||
visible: !isAndroid
|
||||
|
||||
Rectangle {
|
||||
id: localNodeDivider
|
||||
|
||||
@@ -138,9 +138,19 @@ Rectangle {
|
||||
inputDialog.onAcceptedCallback = function() {
|
||||
var txid = inputDialog.inputText.trim();
|
||||
if (currentWallet.scanTransactions([txid])) {
|
||||
updateBalance();
|
||||
appWindow.showStatusMessage(qsTr("Transaction successfully scanned"), 3);
|
||||
} else {
|
||||
appWindow.showStatusMessage(qsTr("Failed to scan transaction") + ": " + currentWallet.errorString, 5);
|
||||
console.error("Error: ", currentWallet.errorString);
|
||||
if (currentWallet.errorString == "The wallet has already seen 1 or more recent transactions than the scanned tx") {
|
||||
informationPopup.title = qsTr("Error") + translationManager.emptyString;
|
||||
informationPopup.text = qsTr("The wallet has already seen 1 or more recent transactions than the scanned transaction.\n\nIn order to rescan the transaction, you can re-sync your wallet by resetting the wallet restore height in the Settings > Info page. Make sure to use a restore height from before your wallet's earliest transaction.") + translationManager.emptyString;
|
||||
informationPopup.icon = StandardIcon.Critical
|
||||
informationPopup.onCloseCallback = null
|
||||
informationPopup.open();
|
||||
} else {
|
||||
appWindow.showStatusMessage(qsTr("Failed to scan transaction") + ": " + currentWallet.errorString, 5);
|
||||
}
|
||||
}
|
||||
}
|
||||
inputDialog.onRejectedCallback = null;
|
||||
|
||||
32
qml.qrc
@@ -119,8 +119,22 @@
|
||||
<file>components/RemoteNodeEdit.qml</file>
|
||||
<file>pages/Keys.qml</file>
|
||||
<file>images/appicon.ico</file>
|
||||
<file>images/card-background-black.png</file>
|
||||
<file>images/card-background-black@2x.png</file>
|
||||
<file>images/card-background-black0.png</file>
|
||||
<file>images/card-background-black1.png</file>
|
||||
<file>images/card-background-black2.png</file>
|
||||
<file>images/card-background-black3.png</file>
|
||||
<file>images/card-background-black4.png</file>
|
||||
<file>images/card-background-black5.png</file>
|
||||
<file>images/card-background-black6.png</file>
|
||||
<file>images/card-background-black7.png</file>
|
||||
<file>images/card-background-black0@2x.png</file>
|
||||
<file>images/card-background-black1@2x.png</file>
|
||||
<file>images/card-background-black2@2x.png</file>
|
||||
<file>images/card-background-black3@2x.png</file>
|
||||
<file>images/card-background-black4@2x.png</file>
|
||||
<file>images/card-background-black5@2x.png</file>
|
||||
<file>images/card-background-black6@2x.png</file>
|
||||
<file>images/card-background-black7@2x.png</file>
|
||||
<file>images/card-background-white.png</file>
|
||||
<file>images/card-background-white@2x.png</file>
|
||||
<file>images/moneroLogo_white.png</file>
|
||||
@@ -192,6 +206,7 @@
|
||||
<file>wizard/WizardCreateWallet2.qml</file>
|
||||
<file>wizard/WizardCreateWallet3.qml</file>
|
||||
<file>wizard/WizardCreateWallet4.qml</file>
|
||||
<file>wizard/WizardCreateWallet5.qml</file>
|
||||
<file>wizard/WizardCreateDevice1.qml</file>
|
||||
<file>wizard/WizardDaemonSettings.qml</file>
|
||||
<file>wizard/WizardHeader.qml</file>
|
||||
@@ -266,7 +281,20 @@
|
||||
<file>images/ledgerNanoS.png</file>
|
||||
<file>images/ledgerNanoSPlus.png</file>
|
||||
<file>images/ledgerNanoX.png</file>
|
||||
<file>images/ledgerStax.png</file>
|
||||
<file>images/trezor.png</file>
|
||||
<file>images/trezor@2x.png</file>
|
||||
<file>qtquickcontrols2.conf</file>
|
||||
<file>images/write-down.png</file>
|
||||
<file>images/write-down-white.png</file>
|
||||
<file>images/write-down@2x.png</file>
|
||||
<file>images/write-down-white@2x.png</file>
|
||||
<file>images/verify.png</file>
|
||||
<file>images/verify-white.png</file>
|
||||
<file>images/verify@2x.png</file>
|
||||
<file>images/verify-white@2x.png</file>
|
||||
<file>wizard/SeedListItem.qml</file>
|
||||
<file>wizard/SeedListGrid.qml</file>
|
||||
<file>wizard/template.pdf</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
2
qtquickcontrols2.conf
Normal file
@@ -0,0 +1,2 @@
|
||||
[Controls]
|
||||
Style=Desktop
|
||||
10
share/org.getmonero.Monero.desktop
Normal file
@@ -0,0 +1,10 @@
|
||||
[Desktop Entry]
|
||||
Name=Monero GUI
|
||||
GenericName=Monero-GUI
|
||||
Comment=Monero GUI
|
||||
Exec=monero-wallet-gui
|
||||
Type=Application
|
||||
Terminal=false
|
||||
Categories=Network;Qt;Finance;Office;
|
||||
Icon=org.getmonero.Monero
|
||||
StartupNotify=true
|
||||
65
share/org.getmonero.Monero.metainfo.xml
Normal file
@@ -0,0 +1,65 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<component type="desktop-application">
|
||||
<id>org.getmonero.Monero</id>
|
||||
<metadata_license>CC0-1.0</metadata_license>
|
||||
<project_license>BSD-3-Clause</project_license>
|
||||
<content_rating type="oars-1.1"/>
|
||||
<developer_name>The Monero Project</developer_name>
|
||||
<categories>
|
||||
<category>Network</category>
|
||||
<category>Qt</category>
|
||||
<category>Finance</category>
|
||||
<category>Office</category>
|
||||
</categories>
|
||||
<name>Monero GUI</name>
|
||||
<summary>Monero: the secure, private, untraceable cryptocurrency</summary>
|
||||
|
||||
<description>
|
||||
<p>Monero is a private, secure, untraceable, decentralised digital currency. You
|
||||
are your bank, you control your funds, and nobody can trace your transfers
|
||||
unless you allow them to do so.</p>
|
||||
|
||||
<p>Privacy: Monero uses a cryptographically sound system to allow you to send
|
||||
and receive funds without your transactions being easily revealed on the
|
||||
blockchain (the ledger of transactions that everyone has). This ensures that
|
||||
your purchases, receipts, and all transfers remain absolutely private by
|
||||
default.</p>
|
||||
|
||||
<p>Security: Using the power of a distributed peer-to-peer consensus network,
|
||||
every transaction on the network is cryptographically secured. Individual
|
||||
wallets have a 25 word mnemonic seed that is only displayed once, and can be
|
||||
written down to backup the wallet. Wallet files are encrypted with a passphrase
|
||||
to ensure they are useless if stolen.</p>
|
||||
|
||||
<p>Untraceability: By taking advantage of ring signatures, a special property of
|
||||
a certain type of cryptography, Monero is able to ensure that transactions are
|
||||
not only untraceable, but have an optional measure of ambiguity that ensures
|
||||
that transactions cannot easily be tied back to an individual user or computer.</p>
|
||||
</description>
|
||||
|
||||
<launchable type="desktop-id">org.getmonero.Monero.desktop</launchable>
|
||||
|
||||
<screenshots>
|
||||
<screenshot type="default">
|
||||
<caption>A screenshot of the Monero GUI wallet</caption>
|
||||
<image>https://raw.githubusercontent.com/monero-project/monero-site/master/img/downloads/gui.png</image>
|
||||
</screenshot>
|
||||
</screenshots>
|
||||
|
||||
<url type="homepage">https://getmonero.org</url>
|
||||
<url type="bugtracker">https://github.com/monero-project/monero-gui/issues</url>
|
||||
<url type="donation">https://getmonero.org/get-started/contributing</url>
|
||||
<url type="faq">https://getmonero.org/get-started/faq</url>
|
||||
<url type="help">https://getmonero.org/resources/user-guides</url>
|
||||
<url type="translate">https://translate.getmonero.org</url>
|
||||
<url type="contact">https://getmonero.org/community/hangouts</url>
|
||||
<url type="contribute">https://getmonero.org/get-started/contributing</url>
|
||||
|
||||
<releases>
|
||||
<release version="<version>" date="<date>"/>
|
||||
</releases>
|
||||
|
||||
<custom>
|
||||
<value key="flathub::manifest">https://github.com/monero-project/monero-gui/tree/master/share/org.getmonero.Monero.yaml</value>
|
||||
</custom>
|
||||
</component>
|
||||
133
share/org.getmonero.Monero.yaml
Normal file
@@ -0,0 +1,133 @@
|
||||
app-id: org.getmonero.Monero
|
||||
runtime: org.kde.Platform
|
||||
runtime-version: 5.15-22.08
|
||||
sdk: org.kde.Sdk
|
||||
finish-args:
|
||||
- --share=network
|
||||
- --share=ipc
|
||||
- --socket=x11
|
||||
- --socket=wayland
|
||||
- --device=all
|
||||
- --filesystem=~/Monero:create
|
||||
- --persist=.bitmonero
|
||||
|
||||
cleanup:
|
||||
- /include
|
||||
- /etc
|
||||
- /share/man
|
||||
- /lib/pkgconfig
|
||||
- /lib/cmake
|
||||
- '*.a'
|
||||
- '*.la'
|
||||
|
||||
command: monero-wallet-gui
|
||||
modules:
|
||||
- name: protobuf
|
||||
buildsystem: cmake-ninja
|
||||
config-opts:
|
||||
- -DCMAKE_BUILD_TYPE=Release
|
||||
sources:
|
||||
- type: git
|
||||
url: https://github.com/protocolbuffers/protobuf
|
||||
tag: v22.4
|
||||
commit: 40e1daca18708c21c7edf07c489a688355bd297b
|
||||
|
||||
- name: boost
|
||||
buildsystem: simple
|
||||
build-commands:
|
||||
- ./bootstrap.sh --prefix=$FLATPAK_DEST --with-libraries=chrono,date_time,filesystem,locale,program_options,regex,serialization,system,thread
|
||||
- ./b2 headers
|
||||
- ./b2 -j$FLATPAK_BUILDER_N_JOBS install variant=release --layout=system
|
||||
sources:
|
||||
- type: archive
|
||||
url: https://boostorg.jfrog.io/artifactory/main/release/1.82.0/source/boost_1_82_0.tar.gz
|
||||
sha256: 66a469b6e608a51f8347236f4912e27dc5c60c60d7d53ae9bfe4683316c6f04c
|
||||
|
||||
- name: libunbound
|
||||
config-opts:
|
||||
- --with-libunbound-only
|
||||
sources:
|
||||
- type: archive
|
||||
url: https://nlnetlabs.nl/downloads/unbound/unbound-1.17.1.tar.gz
|
||||
sha256: ee4085cecce12584e600f3d814a28fa822dfaacec1f94c84bfd67f8a5571a5f4
|
||||
|
||||
- name: libsodium
|
||||
sources:
|
||||
- type: archive
|
||||
url: https://github.com/jedisct1/libsodium/releases/download/1.0.18-RELEASE/libsodium-1.0.18.tar.gz
|
||||
sha256: 6f504490b342a4f8a4c4a02fc9b866cbef8622d5df4e5452b46be121e46636c1
|
||||
|
||||
- name: libusb
|
||||
sources:
|
||||
- type: archive
|
||||
url: https://github.com/libusb/libusb/releases/download/v1.0.26/libusb-1.0.26.tar.bz2
|
||||
sha256: 12ce7a61fc9854d1d2a1ffe095f7b5fac19ddba095c259e6067a46500381b5a5
|
||||
|
||||
- name: hidapi
|
||||
buildsystem: cmake-ninja
|
||||
config-opts:
|
||||
- -DCMAKE_BUILD_TYPE=Release
|
||||
sources:
|
||||
- type: archive
|
||||
url: https://github.com/libusb/hidapi/archive/hidapi-0.13.1.tar.gz
|
||||
sha256: 476a2c9a4dc7d1fc97dd223b84338dbea3809a84caea2dcd887d9778725490e3
|
||||
|
||||
- name: libzmq
|
||||
config-opts:
|
||||
- --with-libsodium
|
||||
- --disable-Werror
|
||||
sources:
|
||||
- type: archive
|
||||
url: https://github.com/zeromq/libzmq/releases/download/v4.3.4/zeromq-4.3.4.tar.gz
|
||||
sha256: c593001a89f5a85dd2ddf564805deb860e02471171b3f204944857336295c3e5
|
||||
|
||||
- name: libgss
|
||||
sources:
|
||||
- type: archive
|
||||
url: https://ftp.gnu.org/gnu/gss/gss-1.0.4.tar.gz
|
||||
sha256: ecceabdef4cae3fce7218b2ecb83eb4227dba44b53b61b8c2b2e88ae02419c73
|
||||
|
||||
- name: libuv
|
||||
buildsystem: cmake-ninja
|
||||
config-opts:
|
||||
- -DCMAKE_BUILD_TYPE=Release
|
||||
sources:
|
||||
- type: archive
|
||||
url: https://github.com/libuv/libuv/archive/v1.44.2.tar.gz
|
||||
sha256: e6e2ba8b4c349a4182a33370bb9be5e23c51b32efb9b9e209d0e8556b73a48da
|
||||
|
||||
- name: p2pool
|
||||
buildsystem: cmake-ninja
|
||||
config-opts:
|
||||
- -DCMAKE_BUILD_TYPE=Release
|
||||
- -DWITH_LTO=OFF
|
||||
sources:
|
||||
- type: git
|
||||
url: https://github.com/SChernykh/p2pool
|
||||
tag: v3.2
|
||||
commit: 92827035e07ff15da6b7645a332f3e59aa0ab1c4
|
||||
post-install:
|
||||
- install -Dm755 p2pool $FLATPAK_DEST/bin/p2pool
|
||||
|
||||
- name: monero-gui
|
||||
buildsystem: cmake-ninja
|
||||
config-opts:
|
||||
- -DCMAKE_BUILD_TYPE=Release
|
||||
- -DWITH_DESKTOP_ENTRY=OFF
|
||||
- -DWITH_UPDATER=OFF
|
||||
build-options:
|
||||
arch:
|
||||
aarch64:
|
||||
config-opts:
|
||||
- -DARCH=armv8-a
|
||||
- -DBUILD_TAG=linux-armv8
|
||||
x86_64:
|
||||
config-opts:
|
||||
- -DARCH=default
|
||||
sources:
|
||||
- type: dir
|
||||
path: ../
|
||||
post-install:
|
||||
- install -Dpm644 share/org.getmonero.Monero.desktop $FLATPAK_DEST/share/applications/$FLATPAK_ID.desktop
|
||||
- install -Dpm644 share/org.getmonero.Monero.metainfo.xml $FLATPAK_DEST/share/metainfo/$FLATPAK_ID.metainfo.xml
|
||||
- for x in 16 24 32 48 64 96 128 256; do install -Dpm644 images/appicons/${x}x${x}.png $FLATPAK_DEST/share/icons/hicolor/${x}x${x}/apps/$FLATPAK_ID.png; done
|
||||
@@ -117,8 +117,17 @@ bool DaemonManager::start(const QString &flags, NetworkType::Type nettype, const
|
||||
connect(m_daemon.get(), SIGNAL(readyReadStandardOutput()), this, SLOT(printOutput()));
|
||||
connect(m_daemon.get(), SIGNAL(readyReadStandardError()), this, SLOT(printError()));
|
||||
|
||||
// Start monerod
|
||||
bool started = m_daemon->startDetached(m_monerod, arguments);
|
||||
#if defined(Q_OS_MAC) && defined(__aarch64__)
|
||||
// RandomX crashes with JIT enabled when started as a detached process, disable it for now
|
||||
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
|
||||
env.insert("MONERO_RANDOMX_UMASK", "8");
|
||||
m_daemon->setProcessEnvironment(env);
|
||||
#endif
|
||||
|
||||
m_daemon->setProgram(m_monerod);
|
||||
m_daemon->setArguments(arguments);
|
||||
bool started = m_daemon->startDetached();
|
||||
|
||||
|
||||
// add state changed listener
|
||||
connect(m_daemon.get(), SIGNAL(stateChanged(QProcess::ProcessState)), this, SLOT(stateChanged(QProcess::ProcessState)));
|
||||
@@ -130,8 +139,8 @@ bool DaemonManager::start(const QString &flags, NetworkType::Type nettype, const
|
||||
}
|
||||
|
||||
// Start start watcher
|
||||
m_scheduler.run([this, nettype, noSync] {
|
||||
if (startWatcher(nettype)) {
|
||||
m_scheduler.run([this, nettype, dataDir, noSync] {
|
||||
if (startWatcher(nettype, dataDir)) {
|
||||
emit daemonStarted();
|
||||
m_noSync = noSync;
|
||||
} else {
|
||||
@@ -142,13 +151,13 @@ bool DaemonManager::start(const QString &flags, NetworkType::Type nettype, const
|
||||
return true;
|
||||
}
|
||||
|
||||
void DaemonManager::stopAsync(NetworkType::Type nettype, const QJSValue& callback)
|
||||
void DaemonManager::stopAsync(NetworkType::Type nettype, const QString &dataDir, const QJSValue& callback)
|
||||
{
|
||||
const auto feature = m_scheduler.run([this, nettype] {
|
||||
const auto feature = m_scheduler.run([this, nettype, dataDir] {
|
||||
QString message;
|
||||
sendCommand({"exit"}, nettype, message);
|
||||
sendCommand({"exit"}, nettype, dataDir, message);
|
||||
|
||||
return QJSValueList({stopWatcher(nettype)});
|
||||
return QJSValueList({stopWatcher(nettype, dataDir)});
|
||||
}, callback);
|
||||
|
||||
if (!feature.first)
|
||||
@@ -157,14 +166,14 @@ void DaemonManager::stopAsync(NetworkType::Type nettype, const QJSValue& callbac
|
||||
}
|
||||
}
|
||||
|
||||
bool DaemonManager::startWatcher(NetworkType::Type nettype) const
|
||||
bool DaemonManager::startWatcher(NetworkType::Type nettype, const QString &dataDir) const
|
||||
{
|
||||
// Check if daemon is started every 2 seconds
|
||||
QElapsedTimer timer;
|
||||
timer.start();
|
||||
while(true && !m_app_exit && timer.elapsed() / 1000 < DAEMON_START_TIMEOUT_SECONDS ) {
|
||||
QThread::sleep(2);
|
||||
if(!running(nettype)) {
|
||||
if(!running(nettype, dataDir)) {
|
||||
qDebug() << "daemon not running. checking again in 2 seconds.";
|
||||
} else {
|
||||
qDebug() << "daemon is started. Waiting 5 seconds to let daemon catch up";
|
||||
@@ -175,14 +184,14 @@ bool DaemonManager::startWatcher(NetworkType::Type nettype) const
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DaemonManager::stopWatcher(NetworkType::Type nettype) const
|
||||
bool DaemonManager::stopWatcher(NetworkType::Type nettype, const QString &dataDir) const
|
||||
{
|
||||
// Check if daemon is running every 2 seconds. Kill if still running after 10 seconds
|
||||
int counter = 0;
|
||||
while(true && !m_app_exit) {
|
||||
QThread::sleep(2);
|
||||
counter++;
|
||||
if(running(nettype)) {
|
||||
if(running(nettype, dataDir)) {
|
||||
qDebug() << "Daemon still running. " << counter;
|
||||
if(counter >= 5) {
|
||||
qDebug() << "Killing it! ";
|
||||
@@ -236,10 +245,10 @@ void DaemonManager::printError()
|
||||
}
|
||||
}
|
||||
|
||||
bool DaemonManager::running(NetworkType::Type nettype) const
|
||||
bool DaemonManager::running(NetworkType::Type nettype, const QString &dataDir) const
|
||||
{
|
||||
QString status;
|
||||
sendCommand({"sync_info"}, nettype, status);
|
||||
sendCommand({"sync_info"}, nettype, dataDir, status);
|
||||
qDebug() << status;
|
||||
return status.contains("Height:");
|
||||
}
|
||||
@@ -249,14 +258,14 @@ bool DaemonManager::noSync() const noexcept
|
||||
return m_noSync;
|
||||
}
|
||||
|
||||
void DaemonManager::runningAsync(NetworkType::Type nettype, const QJSValue& callback) const
|
||||
void DaemonManager::runningAsync(NetworkType::Type nettype, const QString &dataDir, const QJSValue& callback) const
|
||||
{
|
||||
m_scheduler.run([this, nettype] {
|
||||
return QJSValueList({running(nettype)});
|
||||
m_scheduler.run([this, nettype, dataDir] {
|
||||
return QJSValueList({running(nettype, dataDir)});
|
||||
}, callback);
|
||||
}
|
||||
|
||||
bool DaemonManager::sendCommand(const QStringList &cmd, NetworkType::Type nettype, QString &message) const
|
||||
bool DaemonManager::sendCommand(const QStringList &cmd, NetworkType::Type nettype, const QString &dataDir, QString &message) const
|
||||
{
|
||||
QProcess p;
|
||||
QStringList external_cmd(cmd);
|
||||
@@ -267,6 +276,11 @@ bool DaemonManager::sendCommand(const QStringList &cmd, NetworkType::Type nettyp
|
||||
else if (nettype == NetworkType::STAGENET)
|
||||
external_cmd << "--stagenet";
|
||||
|
||||
// Custom data-dir
|
||||
if (!dataDir.isEmpty()) {
|
||||
external_cmd << "--data-dir" << dataDir;
|
||||
}
|
||||
|
||||
qDebug() << "sending external cmd: " << external_cmd;
|
||||
|
||||
|
||||
@@ -278,11 +292,11 @@ bool DaemonManager::sendCommand(const QStringList &cmd, NetworkType::Type nettyp
|
||||
return started;
|
||||
}
|
||||
|
||||
void DaemonManager::sendCommandAsync(const QStringList &cmd, NetworkType::Type nettype, const QJSValue& callback) const
|
||||
void DaemonManager::sendCommandAsync(const QStringList &cmd, NetworkType::Type nettype, const QString &dataDir, const QJSValue& callback) const
|
||||
{
|
||||
m_scheduler.run([this, cmd, nettype] {
|
||||
m_scheduler.run([this, cmd, nettype, dataDir] {
|
||||
QString message;
|
||||
return QJSValueList({sendCommand(cmd, nettype, message)});
|
||||
return QJSValueList({sendCommand(cmd, nettype, dataDir, message)});
|
||||
}, callback);
|
||||
}
|
||||
|
||||
@@ -337,6 +351,57 @@ bool DaemonManager::checkLmdbExists(QString datadir) {
|
||||
return validateDataDir(datadir).value("lmdbExists").value<bool>();
|
||||
}
|
||||
|
||||
QString DaemonManager::getArgs(const QString &dataDir) {
|
||||
if (!running(NetworkType::MAINNET, dataDir)) {
|
||||
return args;
|
||||
}
|
||||
QProcess p;
|
||||
QStringList tempArgs;
|
||||
#ifdef Q_OS_WIN
|
||||
//powershell
|
||||
tempArgs << "Get-CimInstance Win32_Process -Filter \"name = 'monerod.exe'\" | select -ExpandProperty CommandLine ";
|
||||
p.setProgram("powershell");
|
||||
p.setArguments(tempArgs);
|
||||
p.start();
|
||||
p.waitForFinished();
|
||||
args = p.readAllStandardOutput().simplified().trimmed();
|
||||
|
||||
#elif defined(Q_OS_UNIX)
|
||||
//pgrep
|
||||
tempArgs << "monerod";
|
||||
p.setProgram("pgrep");
|
||||
p.setArguments(tempArgs);
|
||||
p.start();
|
||||
p.waitForFinished();
|
||||
QString pid = p.readAllStandardOutput().trimmed();
|
||||
if (pid.isEmpty()) {
|
||||
return args;
|
||||
}
|
||||
|
||||
tempArgs.clear();
|
||||
|
||||
//ps
|
||||
tempArgs << "-o";
|
||||
tempArgs << "args=";
|
||||
tempArgs << "-fp";
|
||||
tempArgs << pid;
|
||||
p.setProgram("ps");
|
||||
p.setArguments(tempArgs);
|
||||
p.start();
|
||||
p.waitForFinished();
|
||||
args = p.readAllStandardOutput().trimmed();
|
||||
|
||||
#endif
|
||||
if (args.contains("--")) {
|
||||
int index = args.indexOf("--");
|
||||
args.remove(0, index);
|
||||
}
|
||||
else {
|
||||
args = "";
|
||||
}
|
||||
return args;
|
||||
}
|
||||
|
||||
DaemonManager::DaemonManager(QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_scheduler(this)
|
||||
|
||||
@@ -48,23 +48,24 @@ public:
|
||||
~DaemonManager();
|
||||
|
||||
Q_INVOKABLE bool start(const QString &flags, NetworkType::Type nettype, const QString &dataDir = "", const QString &bootstrapNodeAddress = "", bool noSync = false, bool pruneBlockchain = false);
|
||||
Q_INVOKABLE void stopAsync(NetworkType::Type nettype, const QJSValue& callback);
|
||||
Q_INVOKABLE void stopAsync(NetworkType::Type nettype, const QString &dataDir, const QJSValue& callback);
|
||||
|
||||
Q_INVOKABLE bool noSync() const noexcept;
|
||||
// return true if daemon process is started
|
||||
Q_INVOKABLE void runningAsync(NetworkType::Type nettype, const QJSValue& callback) const;
|
||||
Q_INVOKABLE void runningAsync(NetworkType::Type nettype, const QString &dataDir, const QJSValue& callback) const;
|
||||
// Send daemon command from qml and prints output in console window.
|
||||
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 QString &dataDir, const QJSValue& callback) const;
|
||||
Q_INVOKABLE void exit();
|
||||
Q_INVOKABLE QVariantMap validateDataDir(const QString &dataDir) const;
|
||||
Q_INVOKABLE bool checkLmdbExists(QString datadir);
|
||||
Q_INVOKABLE QString getArgs(const QString &dataDir);
|
||||
|
||||
private:
|
||||
|
||||
bool running(NetworkType::Type nettype) const;
|
||||
bool sendCommand(const QStringList &cmd, NetworkType::Type nettype, QString &message) const;
|
||||
bool startWatcher(NetworkType::Type nettype) const;
|
||||
bool stopWatcher(NetworkType::Type nettype) const;
|
||||
bool running(NetworkType::Type nettype, const QString &dataDir) const;
|
||||
bool sendCommand(const QStringList &cmd, NetworkType::Type nettype, const QString &dataDir, QString &message) const;
|
||||
bool startWatcher(NetworkType::Type nettype, const QString &dataDir) const;
|
||||
bool stopWatcher(NetworkType::Type nettype, const QString &dataDir) const;
|
||||
signals:
|
||||
void daemonStarted() const;
|
||||
void daemonStopped() const;
|
||||
@@ -82,6 +83,7 @@ private:
|
||||
QString m_monerod;
|
||||
bool m_app_exit = false;
|
||||
bool m_noSync = false;
|
||||
QString args = "";
|
||||
|
||||
mutable FutureScheduler m_scheduler;
|
||||
};
|
||||
|
||||
@@ -101,20 +101,30 @@ NetworkType::Type Wallet::nettype() const
|
||||
void Wallet::updateConnectionStatusAsync()
|
||||
{
|
||||
m_scheduler.run([this] {
|
||||
qDebug() << "updateConnectionStatusAsync current status:" << m_connectionStatus;
|
||||
if (m_connectionStatus == Wallet::ConnectionStatus_Disconnected)
|
||||
{
|
||||
setConnectionStatus(ConnectionStatus_Connecting);
|
||||
}
|
||||
ConnectionStatus newStatus = static_cast<ConnectionStatus>(m_walletImpl->connected());
|
||||
setConnectionStatus(newStatus);
|
||||
qDebug() << "Newest wallet status:" << newStatus;
|
||||
if (m_connectionStatus != newStatus)
|
||||
{
|
||||
setConnectionStatus(newStatus);
|
||||
if (newStatus == ConnectionStatus_Connected)
|
||||
{
|
||||
startRefresh();
|
||||
}
|
||||
}
|
||||
// Release lock
|
||||
m_connectionStatusRunning = false;
|
||||
m_connectionStatusTime.restart();
|
||||
});
|
||||
}
|
||||
|
||||
Wallet::ConnectionStatus Wallet::connected(bool forceCheck)
|
||||
{
|
||||
if (!m_initialized)
|
||||
if (!m_initialized || m_initializing)
|
||||
{
|
||||
return ConnectionStatus_Connecting;
|
||||
}
|
||||
@@ -123,7 +133,6 @@ Wallet::ConnectionStatus Wallet::connected(bool forceCheck)
|
||||
if (forceCheck || (m_connectionStatusTime.elapsed() / 1000 > m_connectionStatusTtl && !m_connectionStatusRunning) || m_connectionStatusTime.elapsed() > 30000) {
|
||||
qDebug() << "Checking connection status";
|
||||
m_connectionStatusRunning = true;
|
||||
m_connectionStatusTime.restart();
|
||||
updateConnectionStatusAsync();
|
||||
}
|
||||
|
||||
@@ -156,10 +165,9 @@ void Wallet::setConnectionStatus(ConnectionStatus value)
|
||||
}
|
||||
|
||||
m_connectionStatus = value;
|
||||
emit connectionStatusChanged(m_connectionStatus);
|
||||
emit connectionStatusChanged(value);
|
||||
|
||||
bool disconnected = m_connectionStatus == Wallet::ConnectionStatus_Connecting ||
|
||||
m_connectionStatus == Wallet::ConnectionStatus_Disconnected;
|
||||
bool disconnected = value != Wallet::ConnectionStatus_Connected;
|
||||
|
||||
if (m_disconnected != disconnected)
|
||||
{
|
||||
@@ -280,6 +288,8 @@ void Wallet::initAsync(
|
||||
const QString &proxyAddress /* = "" */)
|
||||
{
|
||||
qDebug() << "initAsync: " + daemonAddress;
|
||||
m_initializing = true;
|
||||
pauseRefresh();
|
||||
const auto future = m_scheduler.run([this, daemonAddress, trustedDaemon, upperTransactionLimit, isRecovering, isRecoveringFromDevice, restoreHeight, proxyAddress] {
|
||||
m_initialized = init(
|
||||
daemonAddress,
|
||||
@@ -289,12 +299,12 @@ void Wallet::initAsync(
|
||||
isRecoveringFromDevice,
|
||||
restoreHeight,
|
||||
proxyAddress);
|
||||
m_initializing = false;
|
||||
if (m_initialized)
|
||||
{
|
||||
emit walletCreationHeightChanged();
|
||||
qDebug() << "init async finished - starting refresh";
|
||||
qDebug() << "init async finished: " + daemonAddress;
|
||||
connected(true);
|
||||
startRefresh();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -544,12 +554,14 @@ bool Wallet::refresh(bool historyAndSubaddresses /* = true */)
|
||||
|
||||
void Wallet::startRefresh()
|
||||
{
|
||||
qDebug() << "Starting refresh";
|
||||
m_refreshEnabled = true;
|
||||
m_refreshNow = true;
|
||||
}
|
||||
|
||||
void Wallet::pauseRefresh()
|
||||
{
|
||||
qDebug() << "Pausing refresh";
|
||||
m_refreshEnabled = false;
|
||||
}
|
||||
|
||||
@@ -1001,46 +1013,6 @@ QString Wallet::getDaemonLogPath() const
|
||||
return QString::fromStdString(m_walletImpl->getDefaultDataDir()) + "/bitmonero.log";
|
||||
}
|
||||
|
||||
bool Wallet::blackballOutput(const QString &amount, const QString &offset)
|
||||
{
|
||||
return m_walletImpl->blackballOutput(amount.toStdString(), offset.toStdString());
|
||||
}
|
||||
|
||||
bool Wallet::blackballOutputs(const QList<QString> &pubkeys, bool add)
|
||||
{
|
||||
std::vector<std::string> std_pubkeys;
|
||||
foreach (const QString &pubkey, pubkeys) {
|
||||
std_pubkeys.push_back(pubkey.toStdString());
|
||||
}
|
||||
return m_walletImpl->blackballOutputs(std_pubkeys, add);
|
||||
}
|
||||
|
||||
bool Wallet::blackballOutputs(const QString &filename, bool add)
|
||||
{
|
||||
QFile file(filename);
|
||||
|
||||
try {
|
||||
if (!file.open(QIODevice::ReadOnly))
|
||||
return false;
|
||||
QList<QString> outputs;
|
||||
QTextStream in(&file);
|
||||
while (!in.atEnd()) {
|
||||
outputs.push_back(in.readLine());
|
||||
}
|
||||
file.close();
|
||||
return blackballOutputs(outputs, add);
|
||||
}
|
||||
catch (const std::exception &e) {
|
||||
file.close();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool Wallet::unblackballOutput(const QString &amount, const QString &offset)
|
||||
{
|
||||
return m_walletImpl->unblackballOutput(amount.toStdString(), offset.toStdString());
|
||||
}
|
||||
|
||||
QString Wallet::getRing(const QString &key_image)
|
||||
{
|
||||
std::vector<uint64_t> cring;
|
||||
@@ -1138,6 +1110,7 @@ Wallet::Wallet(Monero::Wallet *w, QObject *parent)
|
||||
, m_connectionStatusTtl(WALLET_CONNECTION_STATUS_CACHE_TTL_SECONDS)
|
||||
, m_disconnected(true)
|
||||
, m_initialized(false)
|
||||
, m_initializing(false)
|
||||
, m_currentSubaddressAccount(0)
|
||||
, m_subaddress(new Subaddress(m_walletImpl->subaddress(), this))
|
||||
, m_subaddressModel(nullptr)
|
||||
|
||||
@@ -341,12 +341,6 @@ public:
|
||||
QString getDaemonLogPath() const;
|
||||
QString getWalletLogPath() const;
|
||||
|
||||
// Blackalled outputs
|
||||
Q_INVOKABLE bool blackballOutput(const QString &amount, const QString &offset);
|
||||
Q_INVOKABLE bool blackballOutputs(const QList<QString> &outputs, bool add);
|
||||
Q_INVOKABLE bool blackballOutputs(const QString &filename, bool add);
|
||||
Q_INVOKABLE bool unblackballOutput(const QString &amount, const QString &offset);
|
||||
|
||||
// Rings
|
||||
Q_INVOKABLE QString getRing(const QString &key_image);
|
||||
Q_INVOKABLE QString getRings(const QString &txid);
|
||||
@@ -461,6 +455,7 @@ private:
|
||||
mutable QElapsedTimer m_connectionStatusTime;
|
||||
bool m_disconnected;
|
||||
std::atomic<bool> m_initialized;
|
||||
std::atomic<bool> m_initializing;
|
||||
uint32_t m_currentSubaddressAccount;
|
||||
Subaddress * m_subaddress;
|
||||
mutable SubaddressModel * m_subaddressModel;
|
||||
|
||||
@@ -156,6 +156,7 @@ bool isLinux = false;
|
||||
bool isTails = false;
|
||||
bool isDesktop = false;
|
||||
bool isOpenGL = true;
|
||||
bool isARM = false;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
@@ -177,6 +178,9 @@ int main(int argc, char *argv[])
|
||||
#elif defined(Q_OS_MAC)
|
||||
bool isMac = true;
|
||||
#endif
|
||||
#if defined(__aarch64__)
|
||||
bool isARM = true;
|
||||
#endif
|
||||
|
||||
// detect low graphics mode (start-low-graphics-mode.bat)
|
||||
if(qgetenv("QMLSCENE_DEVICE") == "softwarecontext")
|
||||
@@ -483,6 +487,7 @@ Verify update binary using 'shasum'-compatible (SHA256 algo) output signed by tw
|
||||
engine.rootContext()->setContextProperty("isAndroid", isAndroid);
|
||||
engine.rootContext()->setContextProperty("isOpenGL", isOpenGL);
|
||||
engine.rootContext()->setContextProperty("isTails", isTails);
|
||||
engine.rootContext()->setContextProperty("isARM", isARM);
|
||||
|
||||
engine.rootContext()->setContextProperty("screenAvailableWidth", screenAvailableSize.width());
|
||||
engine.rootContext()->setContextProperty("screenAvailableHeight", screenAvailableSize.height());
|
||||
|
||||
@@ -63,6 +63,7 @@
|
||||
|
||||
#include "QR-Code-scanner/Decoder.h"
|
||||
#include "qt/ScopeGuard.h"
|
||||
#include "NetworkType.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
@@ -159,6 +160,18 @@ QList<QString> OSHelper::grabQrCodesFromScreen() const
|
||||
return codes;
|
||||
}
|
||||
|
||||
bool OSHelper::openFile(const QString &filePath) const
|
||||
{
|
||||
QString canonicalFilePath = QFileInfo(filePath).canonicalFilePath();
|
||||
QUrl url = QUrl::fromLocalFile(canonicalFilePath);
|
||||
if (!url.isValid())
|
||||
{
|
||||
qWarning() << "Malformed file path" << canonicalFilePath << url.errorString();
|
||||
return false;
|
||||
}
|
||||
return QDesktopServices::openUrl(url);
|
||||
}
|
||||
|
||||
bool OSHelper::openContainingFolder(const QString &filePath) const
|
||||
{
|
||||
QString canonicalFilePath = QFileInfo(filePath).canonicalFilePath();
|
||||
@@ -280,3 +293,41 @@ bool OSHelper::installed() const
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
std::pair<quint8, QString> OSHelper::getNetworkTypeAndAddressFromFile(const QString &wallet)
|
||||
{
|
||||
quint8 networkType = NetworkType::MAINNET;
|
||||
QString address = QString("");
|
||||
// attempt to retreive wallet address
|
||||
if(QFile::exists(wallet + ".address.txt")){
|
||||
QFile file(wallet + ".address.txt");
|
||||
file.open(QFile::ReadOnly | QFile::Text);
|
||||
QString _address = QString(file.readAll());
|
||||
if(!_address.isEmpty()){
|
||||
address = _address;
|
||||
if(address.startsWith("5") || address.startsWith("7")){
|
||||
networkType = NetworkType::STAGENET;
|
||||
} else if(address.startsWith("9") || address.startsWith("B")){
|
||||
networkType = NetworkType::TESTNET;
|
||||
}
|
||||
}
|
||||
|
||||
file.close();
|
||||
}
|
||||
return std::make_pair(networkType, address);
|
||||
}
|
||||
|
||||
quint8 OSHelper::getNetworkTypeFromFile(const QString &keysPath) const
|
||||
{
|
||||
QString walletPath = keysPath;
|
||||
if(keysPath.endsWith(".keys")){
|
||||
walletPath = keysPath.mid(0,keysPath.length()-5);
|
||||
}
|
||||
return getNetworkTypeAndAddressFromFile(walletPath).first;
|
||||
}
|
||||
|
||||
void OSHelper::openSeedTemplate() const
|
||||
{
|
||||
QFile::copy(":/wizard/template.pdf", QDir::tempPath() + "/seed_template.pdf");
|
||||
openFile(QDir::tempPath() + "/seed_template.pdf");
|
||||
}
|
||||
|
||||
@@ -46,13 +46,17 @@ public:
|
||||
Q_INVOKABLE void createDesktopEntry() const;
|
||||
Q_INVOKABLE QString downloadLocation() const;
|
||||
Q_INVOKABLE QList<QString> grabQrCodesFromScreen() const;
|
||||
Q_INVOKABLE bool openFile(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 temporaryFilename() const;
|
||||
Q_INVOKABLE QString temporaryPath() const;
|
||||
Q_INVOKABLE bool removeTemporaryWallet(const QString &walletName) const;
|
||||
Q_INVOKABLE bool isCapsLock() const;
|
||||
Q_INVOKABLE quint8 getNetworkTypeFromFile(const QString &keysPath) const;
|
||||
Q_INVOKABLE void openSeedTemplate() const;
|
||||
|
||||
static std::pair<quint8, QString> getNetworkTypeAndAddressFromFile(const QString &wallet);
|
||||
private:
|
||||
bool installed() const;
|
||||
|
||||
|
||||
@@ -43,23 +43,31 @@
|
||||
#include <QMap>
|
||||
#include <QCryptographicHash>
|
||||
|
||||
#if defined(Q_OS_MACOS) && defined(__aarch64__) && !defined(Q_OS_MACOS_AARCH64)
|
||||
#define Q_OS_MACOS_AARCH64
|
||||
#endif
|
||||
|
||||
void P2PoolManager::download() {
|
||||
m_scheduler.run([this] {
|
||||
QUrl url;
|
||||
QString fileName;
|
||||
QString validHash;
|
||||
#ifdef Q_OS_WIN
|
||||
url = "https://github.com/SChernykh/p2pool/releases/download/v2.2.1/p2pool-v2.2.1-windows-x64.zip";
|
||||
fileName = m_p2poolPath + "/p2pool-v2.2.1-windows-x64.zip";
|
||||
validHash = "06b6fe302600c959007bf94e7a5b445f45f823dc4e43ae6cf03b3b98a805167a";
|
||||
url = "https://github.com/SChernykh/p2pool/releases/download/v3.7/p2pool-v3.7-windows-x64.zip";
|
||||
fileName = m_p2poolPath + "/p2pool-v3.7-windows-x64.zip";
|
||||
validHash = "9888afb51a206f1d2c6efc414dd1f498f82de58c689fbb73aceecd88ecdf6c43";
|
||||
#elif defined(Q_OS_LINUX)
|
||||
url = "https://github.com/SChernykh/p2pool/releases/download/v2.2.1/p2pool-v2.2.1-linux-x64.tar.gz";
|
||||
fileName = m_p2poolPath + "/p2pool-v2.2.1-linux-x64.tar.gz";
|
||||
validHash = "02f1daea0f8f99076b7da3368a43cc3989b800f8b5afaf4dfc7e8f9bdc27d274";
|
||||
url = "https://github.com/SChernykh/p2pool/releases/download/v3.7/p2pool-v3.7-linux-x64.tar.gz";
|
||||
fileName = m_p2poolPath + "/p2pool-v3.7-linux-x64.tar.gz";
|
||||
validHash = "d5b932053f56f85b119450e64b1a7765c632f16c6226c8762b00e48f50e7e421";
|
||||
#elif defined(Q_OS_MACOS_AARCH64)
|
||||
url = "https://github.com/SChernykh/p2pool/releases/download/v3.7/p2pool-v3.7-macos-aarch64.tar.gz";
|
||||
fileName = m_p2poolPath + "/p2pool-v3.7-macos-aarch64.tar.gz";
|
||||
validHash = "d2b483a10c01f4a84faacbb8e2eedafef451ca4e6a4128e44800018556bb2c62";
|
||||
#elif defined(Q_OS_MACOS)
|
||||
url = "https://github.com/SChernykh/p2pool/releases/download/v2.2.1/p2pool-v2.2.1-macos-x64.tar.gz";
|
||||
fileName = m_p2poolPath + "/p2pool-v2.2.1-macos-x64.tar.gz";
|
||||
validHash = "d973a8dca922f209dfb6f203006f93664e19d870975621bec07e9d855e79d7d5";
|
||||
url = "https://github.com/SChernykh/p2pool/releases/download/v3.7/p2pool-v3.7-macos-x64.tar.gz";
|
||||
fileName = m_p2poolPath + "/p2pool-v3.7-macos-x64.tar.gz";
|
||||
validHash = "444ded858b18a9ecba7d08a2d333188d1758a3da358817887d28d0827dc4287b";
|
||||
#endif
|
||||
QFile file(fileName);
|
||||
epee::net_utils::http::http_simple_client http_client;
|
||||
@@ -68,7 +76,10 @@ void P2PoolManager::download() {
|
||||
std::chrono::milliseconds timeout = std::chrono::seconds(10);
|
||||
http_client.set_server(url.host().toStdString(), "443", {});
|
||||
bool success = http_client.invoke_get(url.path().toStdString(), timeout, {}, std::addressof(response), {{"User-Agent", userAgent}});
|
||||
if (response->m_response_code == 302) {
|
||||
if (success && response->m_response_code == 404) {
|
||||
emit p2poolDownloadFailure(BinaryNotAvailable);
|
||||
return;
|
||||
} else if (success && response->m_response_code == 302) {
|
||||
epee::net_utils::http::fields_list fields = response->m_header_info.m_etc_fields;
|
||||
for (std::pair<std::string, std::string> i : fields) {
|
||||
if (i.first == "Location") {
|
||||
@@ -82,7 +93,7 @@ void P2PoolManager::download() {
|
||||
}
|
||||
}
|
||||
if (!success) {
|
||||
emit p2poolDownloadFailure();
|
||||
emit p2poolDownloadFailure(ConnectionIssue);
|
||||
}
|
||||
else {
|
||||
std::string stringData = response->m_body;
|
||||
@@ -90,7 +101,7 @@ void P2PoolManager::download() {
|
||||
QByteArray hashData = QCryptographicHash::hash(data, QCryptographicHash::Sha256);
|
||||
QString hash = hashData.toHex();
|
||||
if (hash != validHash) {
|
||||
emit p2poolDownloadFailure();
|
||||
emit p2poolDownloadFailure(HashVerificationFailed);
|
||||
}
|
||||
else {
|
||||
file.open(QIODevice::WriteOnly);
|
||||
@@ -102,7 +113,7 @@ void P2PoolManager::download() {
|
||||
emit p2poolDownloadSuccess();
|
||||
}
|
||||
else {
|
||||
emit p2poolDownloadFailure();
|
||||
emit p2poolDownloadFailure(InstallationFailed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,13 +51,22 @@ public:
|
||||
Q_INVOKABLE bool isInstalled();
|
||||
Q_INVOKABLE void getStatus();
|
||||
Q_INVOKABLE void download();
|
||||
|
||||
enum DownloadError {
|
||||
BinaryNotAvailable,
|
||||
ConnectionIssue,
|
||||
HashVerificationFailed,
|
||||
InstallationFailed,
|
||||
};
|
||||
Q_ENUM(DownloadError)
|
||||
|
||||
private:
|
||||
|
||||
bool running(NetworkType::Type nettype) const;
|
||||
signals:
|
||||
void p2poolStartFailure() const;
|
||||
void p2poolStatus(bool isMining, int hashrate) const;
|
||||
void p2poolDownloadFailure() const;
|
||||
void p2poolDownloadFailure(int errorCode) const;
|
||||
void p2poolDownloadSuccess() const;
|
||||
|
||||
private:
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
#include "libwalletqt/WalletManager.h"
|
||||
#include "NetworkType.h"
|
||||
#include "qt/utils.h"
|
||||
#include "main/oshelper.h"
|
||||
|
||||
#include "KeysFiles.h"
|
||||
|
||||
@@ -121,26 +122,9 @@ void WalletKeysFilesModel::findWallets(const QString &moneroAccountsDir)
|
||||
}
|
||||
|
||||
QString wallet(keysFileinfo.path() + QDir::separator() + keysFileinfo.completeBaseName());
|
||||
quint8 networkType = NetworkType::MAINNET;
|
||||
QString address = QString("");
|
||||
|
||||
// attempt to retreive wallet address
|
||||
if(fileExists(wallet + ".address.txt")){
|
||||
QFile file(wallet + ".address.txt");
|
||||
file.open(QFile::ReadOnly | QFile::Text);
|
||||
QString _address = QString(file.readAll());
|
||||
|
||||
if(!_address.isEmpty()){
|
||||
address = _address;
|
||||
if(address.startsWith("5") || address.startsWith("7")){
|
||||
networkType = NetworkType::STAGENET;
|
||||
} else if(address.startsWith("9") || address.startsWith("B")){
|
||||
networkType = NetworkType::TESTNET;
|
||||
}
|
||||
}
|
||||
|
||||
file.close();
|
||||
}
|
||||
auto networkTypeAndAddress = OSHelper::getNetworkTypeAndAddressFromFile(wallet);
|
||||
quint8 networkType = networkTypeAndAddress.first;
|
||||
QString address = networkTypeAndAddress.second;
|
||||
|
||||
this->addWalletKeysFile(WalletKeysFiles(wallet, networkType, std::move(address)));
|
||||
}
|
||||
|
||||
26
wizard/SeedListGrid.qml
Normal file
@@ -0,0 +1,26 @@
|
||||
import QtQuick 2.9
|
||||
import QtQuick.Dialogs 1.2
|
||||
import QtQuick.Layouts 1.2
|
||||
import QtQuick.Controls 2.0
|
||||
|
||||
import "../js/Wizard.js" as Wizard
|
||||
import "../js/Utils.js" as Utils
|
||||
import "../components" as MoneroComponents
|
||||
|
||||
GridLayout {
|
||||
id: seedGrid
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
flow: GridLayout.TopToBottom
|
||||
columns: wizardController.layoutScale == 1 ? 5 : wizardController.layoutScale == 2 ? 4 : wizardController.layoutScale == 3 ? 3 : 2
|
||||
rows: wizardController.layoutScale == 1 ? 5 :wizardController.layoutScale == 2 ? 7 : wizardController.layoutScale == 3 ? 9 : 13
|
||||
columnSpacing: wizardController.layoutScale == 1 ? 25 : 18
|
||||
rowSpacing: 0
|
||||
|
||||
Component.onCompleted: {
|
||||
var seed = wizardController.walletOptionsSeed.split(" ");
|
||||
var component = Qt.createComponent("SeedListItem.qml");
|
||||
for(var i = 0; i < seed.length; i++) {
|
||||
component.createObject(seedGrid, {wordNumber: i, word: seed[i]});
|
||||
}
|
||||
}
|
||||
}
|
||||
153
wizard/SeedListItem.qml
Normal file
@@ -0,0 +1,153 @@
|
||||
import "../components" as MoneroComponents;
|
||||
import QtQuick 2.9
|
||||
import QtQuick.Layouts 1.2
|
||||
import FontAwesome 1.0
|
||||
|
||||
ColumnLayout {
|
||||
id: seedListItem
|
||||
property var wordNumber;
|
||||
property var word;
|
||||
property var wordSpelled: (word.split("")).join(". ")
|
||||
property var acessibleText: (wordNumber + 1) + word
|
||||
property alias wordText: wordText
|
||||
property alias lineEdit: lineEdit
|
||||
property alias icon: icon
|
||||
spacing: 0
|
||||
|
||||
Layout.preferredWidth: 136
|
||||
Layout.maximumWidth: 136
|
||||
Layout.minimumWidth: 136
|
||||
|
||||
Accessible.role: Accessible.StaticText
|
||||
Accessible.name: lineEdit.inputHasFocus && !lineEdit.readOnly ? qsTr("Please enter the word number") + " " + (wordNumber + 1) + "." +
|
||||
(icon.visible ? (icon.wordsMatch ? qsTr("Green check mark") + "."
|
||||
: qsTr("Red exclamation mark") + ".")
|
||||
: "")
|
||||
: (wordNumber + 1) + word + ". " +
|
||||
(lineEdit.inputHasFocus && lineEdit.readOnly ? qsTr("Green check mark")
|
||||
: qsTr("This word is spelled ") + " " + wordSpelled + ".") +
|
||||
translationManager.emptyString
|
||||
KeyNavigation.up: wordNumber == 0 ? (recoveryPhraseLabel.visible ? recoveryPhraseLabel : header) : parent.children[wordNumber - 1]
|
||||
KeyNavigation.backtab: wordNumber == 0 ? (recoveryPhraseLabel.visible ? recoveryPhraseLabel : header) : parent.children[wordNumber - 1]
|
||||
Keys.onUpPressed: focusOnPreviousField()
|
||||
Keys.onBacktabPressed: focusOnPreviousField()
|
||||
Keys.onDownPressed: focusOnNextField()
|
||||
Keys.onTabPressed: focusOnNextField()
|
||||
|
||||
function focusOnPreviousField() {
|
||||
if (wizardCreateWallet2.state == "verify") {
|
||||
if (wordNumber < 5) {
|
||||
if (recoveryPhraseLabel.visible) {
|
||||
return recoveryPhraseLabel.forceActiveFocus();
|
||||
} else {
|
||||
return header.forceActiveFocus();
|
||||
}
|
||||
} else if (wordNumber >= 5 && wordNumber < 25) {
|
||||
return parent.children[wizardCreateWallet2.hiddenWords[parseInt(wordNumber / 5) - 1]].lineEdit.forceActiveFocus()
|
||||
}
|
||||
} else {
|
||||
if (wordNumber == 0) {
|
||||
if (recoveryPhraseLabel.visible) {
|
||||
return recoveryPhraseLabel.forceActiveFocus();
|
||||
} else {
|
||||
return header.forceActiveFocus();
|
||||
}
|
||||
} else {
|
||||
return parent.children[wordNumber - 1].forceActiveFocus()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function focusOnNextField() {
|
||||
if (wizardCreateWallet2.state == "verify") {
|
||||
if (wordNumber < 20) {
|
||||
return parent.children[wizardCreateWallet2.hiddenWords[parseInt(wordNumber / 5) + 1]].lineEdit.forceActiveFocus()
|
||||
} else {
|
||||
return navigation.btnPrev.forceActiveFocus()
|
||||
}
|
||||
} else {
|
||||
if (wordNumber == 24) {
|
||||
if (createNewSeedButton.visible) {
|
||||
return createNewSeedButton.forceActiveFocus()
|
||||
} else {
|
||||
return printPDFTemplate.forceActiveFocus()
|
||||
}
|
||||
} else {
|
||||
return parent.children[wordNumber + 1].forceActiveFocus()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
id: wordRow
|
||||
spacing: 0
|
||||
|
||||
MoneroComponents.Label {
|
||||
color: lineEdit.inputHasFocus ? MoneroComponents.Style.defaultFontColor : MoneroComponents.Style.dimmedFontColor
|
||||
fontSize: 13
|
||||
text: (wordNumber + 1)
|
||||
themeTransition: false
|
||||
}
|
||||
|
||||
MoneroComponents.LineEdit {
|
||||
id: lineEdit
|
||||
property bool firstUserInput: true
|
||||
inputHeight: 29
|
||||
inputPaddingLeft: 10
|
||||
inputPaddingBottom: 2
|
||||
inputPaddingRight: 0
|
||||
borderDisabled: true
|
||||
visible: !wordText.visible
|
||||
fontSize: 16
|
||||
fontBold: true
|
||||
text: ""
|
||||
tabNavigationEnabled: false
|
||||
onTextChanged: {
|
||||
if (lineEdit.text.length == wordText.text.length) {
|
||||
firstUserInput = false;
|
||||
}
|
||||
}
|
||||
onBacktabPressed: focusOnPreviousField()
|
||||
onTabPressed: focusOnNextField()
|
||||
}
|
||||
|
||||
MoneroComponents.Label {
|
||||
id: wordText
|
||||
Layout.leftMargin: 10
|
||||
color: MoneroComponents.Style.defaultFontColor
|
||||
fontSize: seedListItem.focus ? 19 : 16
|
||||
fontBold: true
|
||||
text: word
|
||||
themeTransition: false
|
||||
}
|
||||
|
||||
MoneroComponents.TextPlain {
|
||||
id: icon
|
||||
Layout.leftMargin: wordsMatch ? 10 : 0
|
||||
property bool wordsMatch: lineEdit.text === wordText.text
|
||||
property bool partialWordMatches: lineEdit.text === wordText.text.substring(0, lineEdit.text.length)
|
||||
visible: lineEdit.text.length > 0 && !lineEdit.firstUserInput || lineEdit.firstUserInput && !partialWordMatches
|
||||
font.family: FontAwesome.fontFamilySolid
|
||||
font.styleName: "Solid"
|
||||
font.pixelSize: 15
|
||||
text: wordsMatch ? FontAwesome.checkCircle : FontAwesome.exclamationCircle
|
||||
color: wordsMatch ? (MoneroComponents.Style.blackTheme ? "#00FF00" : "#008000") : "#FF0000"
|
||||
themeTransition: false
|
||||
onTextChanged: {
|
||||
if (wizardCreateWallet2.seedListGrid && wordsMatch) {
|
||||
if (wordNumber < 20) {
|
||||
focusOnNextField();
|
||||
}
|
||||
lineEdit.readOnly = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: underLine
|
||||
color: lineEdit.inputHasFocus ? MoneroComponents.Style.defaultFontColor : MoneroComponents.Style.appWindowBorderColor
|
||||
Layout.fillWidth: true
|
||||
height: 1
|
||||
}
|
||||
}
|
||||
@@ -50,13 +50,14 @@ Rectangle {
|
||||
signal useMoneroClicked()
|
||||
signal walletCreatedFromDevice(bool success)
|
||||
|
||||
function restart() {
|
||||
function restart(generatingNewSeed) {
|
||||
// Clear up any state, including `m_wallet`, which
|
||||
// is the temp. wallet object whilst creating new wallets.
|
||||
// This function is called automatically by navigating to `wizardHome`.
|
||||
wizardStateView.state = "wizardHome"
|
||||
wizardController.walletOptionsName = defaultAccountName;
|
||||
wizardController.walletOptionsLocation = '';
|
||||
if(!generatingNewSeed) {
|
||||
wizardController.walletOptionsName = defaultAccountName;
|
||||
wizardController.walletOptionsLocation = '';
|
||||
}
|
||||
wizardController.walletOptionsPassword = '';
|
||||
wizardController.walletOptionsSeed = '';
|
||||
wizardController.walletOptionsSeedOffset = '';
|
||||
@@ -113,10 +114,18 @@ Rectangle {
|
||||
|
||||
|
||||
property int layoutScale: {
|
||||
if(appWindow.width < 800){
|
||||
return 1;
|
||||
} else {
|
||||
if (appWindow.width < 506) {
|
||||
//mobile (25 word mnemonic seed displayed in 2 columns)
|
||||
return 4;
|
||||
} else if (appWindow.width < 660) {
|
||||
//tablet (25 word mnemonic seed displayed in 3 columns)
|
||||
return 3;
|
||||
} else if (appWindow.width < 842) {
|
||||
//tablet (25 word mnemonic seed displayed in 4 columns)
|
||||
return 2;
|
||||
} else if (appWindow.width >= 842) {
|
||||
//desktop (25 word mnemonic seed displayed in 5 columns)
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,6 +140,7 @@ Rectangle {
|
||||
property WizardCreateWallet2 wizardCreateWallet2View: WizardCreateWallet2 { }
|
||||
property WizardCreateWallet3 wizardCreateWallet3View: WizardCreateWallet3 { }
|
||||
property WizardCreateWallet4 wizardCreateWallet4View: WizardCreateWallet4 { }
|
||||
property WizardCreateWallet5 wizardCreateWallet5View: WizardCreateWallet5 { }
|
||||
property WizardRestoreWallet1 wizardRestoreWallet1View: WizardRestoreWallet1 { }
|
||||
property WizardRestoreWallet2 wizardRestoreWallet2View: WizardRestoreWallet2 { }
|
||||
property WizardRestoreWallet3 wizardRestoreWallet3View: WizardRestoreWallet3 { }
|
||||
@@ -195,6 +205,10 @@ Rectangle {
|
||||
name: "wizardCreateWallet4"
|
||||
PropertyChanges { target: wizardStateView; currentView: wizardStateView.wizardCreateWallet4View }
|
||||
PropertyChanges { target: wizardFlickable; contentHeight: wizardStateView.wizardCreateWallet4View.pageHeight + 80 }
|
||||
}, State {
|
||||
name: "wizardCreateWallet5"
|
||||
PropertyChanges { target: wizardStateView; currentView: wizardStateView.wizardCreateWallet5View }
|
||||
PropertyChanges { target: wizardFlickable; contentHeight: wizardStateView.wizardCreateWallet5View.pageHeight + 80 }
|
||||
}, State {
|
||||
name: "wizardRestoreWallet1"
|
||||
PropertyChanges { target: wizardStateView; currentView: wizardStateView.wizardRestoreWallet1View }
|
||||
@@ -308,7 +322,9 @@ Rectangle {
|
||||
sidebarVisible: false
|
||||
|
||||
onAccepted: {
|
||||
wizardController.openWalletFile(fileDialog.fileUrl);
|
||||
var keysPath = walletManager.urlToLocalPath(fileDialog.fileUrl)
|
||||
persistentSettings.nettype = oshelper.getNetworkTypeFromFile(keysPath);
|
||||
wizardController.openWalletFile(keysPath);
|
||||
}
|
||||
onRejected: {
|
||||
console.log("Canceled")
|
||||
@@ -354,6 +370,10 @@ Rectangle {
|
||||
return;
|
||||
}
|
||||
|
||||
if (wizardStateView.wizardCreateWallet2View.seedListGrid) {
|
||||
wizardStateView.wizardCreateWallet2View.seedListGrid.destroy();
|
||||
}
|
||||
|
||||
// make sure temporary wallet files are deleted
|
||||
console.log("Removing temporary wallet: " + wizardController.tmpWalletFilename)
|
||||
oshelper.removeTemporaryWallet(wizardController.tmpWalletFilename)
|
||||
|
||||
@@ -54,6 +54,7 @@ Rectangle {
|
||||
ListElement { column1: "Ledger Nano S"; column2: "Ledger";}
|
||||
ListElement { column1: "Ledger Nano S Plus"; column2: "Ledger";}
|
||||
ListElement { column1: "Ledger Nano X"; column2: "Ledger";}
|
||||
ListElement { column1: "Ledger Stax"; column2: "Ledger";}
|
||||
ListElement { column1: "Trezor Model T"; column2: "Trezor";}
|
||||
}
|
||||
|
||||
@@ -170,6 +171,8 @@ Rectangle {
|
||||
return "qrc:///images/ledgerNanoSPlus.png";
|
||||
} else if (ledgerType == "Ledger Nano X") {
|
||||
return "qrc:///images/ledgerNanoX.png";
|
||||
} else if (ledgerType == "Ledger Stax") {
|
||||
return "qrc:///images/ledgerStax.png";
|
||||
}
|
||||
}
|
||||
return "";
|
||||
@@ -282,7 +285,7 @@ Rectangle {
|
||||
function onCreateWalletFromDeviceCompleted(written){
|
||||
hideProcessingSplash();
|
||||
if(written){
|
||||
wizardStateView.state = "wizardCreateWallet2";
|
||||
wizardStateView.state = "wizardCreateWallet3";
|
||||
} else {
|
||||
errorMsg.text = qsTr("Error writing wallet from hardware device. Check application logs.") + translationManager.emptyString;
|
||||
}
|
||||
|
||||
@@ -40,8 +40,8 @@ Rectangle {
|
||||
|
||||
color: "transparent"
|
||||
property alias pageHeight: pageRoot.height
|
||||
property alias pageRoot: pageRoot
|
||||
property string viewName: "wizardCreateWallet1"
|
||||
property alias seed: seed
|
||||
|
||||
ColumnLayout {
|
||||
id: pageRoot
|
||||
@@ -51,6 +51,8 @@ Rectangle {
|
||||
anchors.horizontalCenter: parent.horizontalCenter;
|
||||
|
||||
spacing: 0
|
||||
KeyNavigation.down: createWalletHeader
|
||||
KeyNavigation.tab: createWalletHeader
|
||||
|
||||
ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
@@ -60,6 +62,7 @@ Rectangle {
|
||||
spacing: 20
|
||||
|
||||
WizardHeader {
|
||||
id: createWalletHeader
|
||||
title: {
|
||||
var nettype = persistentSettings.nettype;
|
||||
return qsTr("Create a new wallet") + (nettype === 2 ? " (" + qsTr("stagenet") + ")"
|
||||
@@ -67,146 +70,42 @@ Rectangle {
|
||||
: "") + translationManager.emptyString
|
||||
}
|
||||
subtitle: qsTr("Creates a new wallet on this computer.") + translationManager.emptyString
|
||||
Accessible.role: Accessible.StaticText
|
||||
Accessible.name: title + subtitle
|
||||
Keys.onUpPressed: wizardNav.btnNext.enabled ? wizardNav.btnNext.forceActiveFocus() : wizardNav.wizardProgress.forceActiveFocus()
|
||||
Keys.onBacktabPressed: wizardNav.btnNext.enabled ? wizardNav.btnNext.forceActiveFocus() : wizardNav.wizardProgress.forceActiveFocus()
|
||||
Keys.onDownPressed: walletInput.walletName.forceActiveFocus();
|
||||
Keys.onTabPressed: walletInput.walletName.forceActiveFocus();
|
||||
}
|
||||
|
||||
WizardWalletInput{
|
||||
id: walletInput
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
spacing: 0
|
||||
|
||||
Layout.topMargin: -10
|
||||
Layout.fillWidth: true
|
||||
|
||||
MoneroComponents.LineEditMulti {
|
||||
id: seed
|
||||
|
||||
spacing: 0
|
||||
inputPaddingLeft: 16
|
||||
inputPaddingRight: 16
|
||||
inputPaddingTop: 20
|
||||
inputPaddingBottom: 20
|
||||
inputRadius: 0
|
||||
|
||||
fontSize: 18
|
||||
fontBold: true
|
||||
wrapMode: Text.WordWrap
|
||||
backgroundColor: "red"
|
||||
addressValidation: false
|
||||
labelText: qsTr("Mnemonic seed") + translationManager.emptyString
|
||||
labelFontSize: 14
|
||||
copyButton: false
|
||||
readOnly: true
|
||||
|
||||
placeholderText: "-"
|
||||
text: wizardController.walletOptionsSeed
|
||||
}
|
||||
|
||||
MoneroComponents.WarningBox {
|
||||
Rectangle {
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
width: 1
|
||||
color: MoneroComponents.Style.inputBorderColorInActive
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors.right: parent.right
|
||||
anchors.left: parent.left
|
||||
anchors.bottom: parent.bottom
|
||||
height: 1
|
||||
color: MoneroComponents.Style.inputBorderColorInActive
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
width: 1
|
||||
color: MoneroComponents.Style.inputBorderColorInActive
|
||||
}
|
||||
|
||||
radius: 0
|
||||
border.color: MoneroComponents.Style.inputBorderColorInActive
|
||||
border.width: 0
|
||||
|
||||
text: qsTr("This seed is <b>very</b> important to write down and keep secret. It is all you need to backup and restore your wallet.") + translationManager.emptyString
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
spacing: 0
|
||||
|
||||
Layout.topMargin: 10
|
||||
Layout.fillWidth: true
|
||||
|
||||
MoneroComponents.LineEditMulti {
|
||||
id: restoreHeight
|
||||
|
||||
spacing: 0
|
||||
inputPaddingLeft: 16
|
||||
inputPaddingRight: 16
|
||||
inputPaddingTop: 20
|
||||
inputPaddingBottom: 20
|
||||
inputRadius: 0
|
||||
fontSize: 18
|
||||
fontBold: true
|
||||
wrapMode: Text.WordWrap
|
||||
labelText: qsTr("Wallet restore height") + translationManager.emptyString
|
||||
labelFontSize: 14
|
||||
copyButton: false
|
||||
readOnly: true
|
||||
text: Utils.roundDownToNearestThousand(wizardController.m_wallet ? wizardController.m_wallet.walletCreationHeight : 0)
|
||||
}
|
||||
|
||||
MoneroComponents.WarningBox {
|
||||
Rectangle {
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
width: 1
|
||||
color: MoneroComponents.Style.inputBorderColorInActive
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors.right: parent.right
|
||||
anchors.left: parent.left
|
||||
anchors.bottom: parent.bottom
|
||||
height: 1
|
||||
color: MoneroComponents.Style.inputBorderColorInActive
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
width: 1
|
||||
color: MoneroComponents.Style.inputBorderColorInActive
|
||||
}
|
||||
|
||||
radius: 0
|
||||
border.color: MoneroComponents.Style.inputBorderColorInActive
|
||||
border.width: 0
|
||||
text: qsTr("Should you restore your wallet in the future, specifying this block number will recover your wallet quicker.") + translationManager.emptyString
|
||||
}
|
||||
rowLayout: false
|
||||
walletNameKeyNavigationBackTab: createWalletHeader
|
||||
browseButtonKeyNavigationTab: wizardNav.btnPrev
|
||||
}
|
||||
|
||||
WizardNav {
|
||||
progressSteps: appWindow.walletMode <= 1 ? 3 : 4
|
||||
id: wizardNav
|
||||
progressSteps: appWindow.walletMode <= 1 ? 4 : 5
|
||||
progress: 0
|
||||
btnNext.enabled: walletInput.verify();
|
||||
btnPrev.text: qsTr("Back to menu") + translationManager.emptyString
|
||||
btnPrev.text: appWindow.width <= 506 ? "<" : qsTr("Back to menu") + translationManager.emptyString
|
||||
onPrevClicked: {
|
||||
wizardController.wizardStateView.wizardCreateWallet2View.pwField = "";
|
||||
wizardController.wizardStateView.wizardCreateWallet2View.pwConfirmField = "";
|
||||
if (wizardStateView.wizardCreateWallet2View.seedListGrid) {
|
||||
wizardStateView.wizardCreateWallet2View.seedListGrid.destroy();
|
||||
}
|
||||
wizardController.wizardStateView.wizardCreateWallet3View.pwField = "";
|
||||
wizardController.wizardStateView.wizardCreateWallet3View.pwConfirmField = "";
|
||||
wizardStateView.state = "wizardHome";
|
||||
}
|
||||
btnPrevKeyNavigationBackTab: walletInput.errorMessageWalletLocation.text != "" ? walletInput.errorMessageWalletLocation : walletInput.browseButton
|
||||
btnNextKeyNavigationTab: createWalletHeader
|
||||
onNextClicked: {
|
||||
wizardController.walletOptionsName = walletInput.walletName.text;
|
||||
wizardController.walletOptionsLocation = walletInput.walletLocation.text;
|
||||
wizardController.walletOptionsLocation = appWindow.walletMode >= 2 ? walletInput.walletLocation.text : appWindow.accountsDir;
|
||||
wizardStateView.state = "wizardCreateWallet2";
|
||||
wizardStateView.wizardCreateWallet2View.pageRoot.forceActiveFocus();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,9 +27,13 @@
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import QtQuick 2.9
|
||||
import QtQuick.Dialogs 1.2
|
||||
import QtQuick.Layouts 1.2
|
||||
import QtQuick.Controls 2.0
|
||||
import moneroComponents.Clipboard 1.0
|
||||
|
||||
import "../js/Wizard.js" as Wizard
|
||||
import "../js/Utils.js" as Utils
|
||||
import "../components" as MoneroComponents
|
||||
|
||||
Rectangle {
|
||||
@@ -37,9 +41,56 @@ Rectangle {
|
||||
|
||||
color: "transparent"
|
||||
property alias pageHeight: pageRoot.height
|
||||
property alias pageRoot: pageRoot
|
||||
property string viewName: "wizardCreateWallet2"
|
||||
property alias pwField: passwordFields.password
|
||||
property alias pwConfirmField: passwordFields.passwordConfirm
|
||||
property var seedArray: wizardController.walletOptionsSeed.split(" ")
|
||||
property var seedListGrid: ""
|
||||
property var hiddenWords: [0, 5, 10, 15, 20]
|
||||
|
||||
Clipboard { id: clipboard }
|
||||
|
||||
state: "default"
|
||||
states: [
|
||||
State {
|
||||
name: "default";
|
||||
}, State {
|
||||
name: "verify";
|
||||
when: typeof currentWallet != "undefined" && wizardStateView.state == "wizardCreateWallet2"
|
||||
PropertyChanges { target: header; title: qsTr("Verify your recovery phrase") + translationManager.emptyString }
|
||||
PropertyChanges { target: header; imageIcon: wizardController.layoutScale != 4 ? (MoneroComponents.Style.blackTheme ? "qrc:///images/verify.png" : "qrc:///images/verify-white.png") : "" }
|
||||
PropertyChanges { target: header; subtitle: qsTr("Please confirm that you have written down your recover phrase by filling in the five blank fields with the correct words. If you have not written down your recovery phrase on a piece of paper, click on the Previous button and write it down right now!") + translationManager.emptyString}
|
||||
PropertyChanges { target: walletCreationDate; opacity: 0; enabled: false}
|
||||
PropertyChanges { target: walletCreationDateValue; opacity: 0; enabled: false}
|
||||
PropertyChanges { target: walletRestoreHeight; opacity: 0; enabled: false}
|
||||
PropertyChanges { target: walletRestoreHeightValue; opacity: 0; enabled: false}
|
||||
PropertyChanges { target: createNewSeedButton; opacity: 0; enabled: false}
|
||||
PropertyChanges { target: copyToClipboardButton; opacity: 0; enabled: false}
|
||||
PropertyChanges { target: printPDFTemplate; opacity: 0; enabled: false}
|
||||
|
||||
PropertyChanges { target: navigation; onPrevClicked: {
|
||||
seedListGridColumn.clearFields();
|
||||
wizardCreateWallet2.state = "default";
|
||||
pageRoot.forceActiveFocus();
|
||||
}}
|
||||
PropertyChanges { target: navigation; onNextClicked: {
|
||||
seedListGridColumn.clearFields();
|
||||
wizardStateView.state = "wizardCreateWallet3";
|
||||
wizardCreateWallet2.state = "default";
|
||||
}}
|
||||
}
|
||||
]
|
||||
|
||||
MoneroComponents.TextPlain {
|
||||
//PDF template text
|
||||
// the translation of these strings is used to create localized PDF templates
|
||||
visible: false
|
||||
text: qsTr("Print this paper, fill it out, and keep it in a safe location. Never share your recovery phrase with anybody, especially with strangers offering technical support.") +
|
||||
qsTr("Recovery phrase (mnemonic seed)") +
|
||||
qsTr("These words are are a backup of your wallet. They are the only thing needed to access your funds and restore your Monero wallet, so keep this paper in a safe place and do not disclose it to anybody! It is strongly not recommended to store your recovery phrase digitally (in an email, online service, screenshot, photo, or any other type of computer file).") +
|
||||
qsTr("Wallet creation date") +
|
||||
qsTr("Wallet restore height") +
|
||||
qsTr("For instructions on how to restore this wallet, visit www.getmonero.org and go to Resources > User Guides > \"How to restore a wallet from mnemonic seed\". Use only Monero wallets that are trusted and recommended by the Monero community (see a list of them in www.getmonero.org/downloads).") + translationManager.emptyString
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: pageRoot
|
||||
@@ -49,39 +100,350 @@ Rectangle {
|
||||
anchors.horizontalCenter: parent.horizontalCenter;
|
||||
|
||||
spacing: 0
|
||||
KeyNavigation.down: mobileDialog.visible ? mobileHeader : header
|
||||
KeyNavigation.tab: mobileDialog.visible ? mobileHeader : header
|
||||
|
||||
ColumnLayout {
|
||||
id: mobileDialog
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: wizardController.wizardSubViewTopMargin
|
||||
Layout.maximumWidth: wizardController.wizardSubViewWidth
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
spacing: 0
|
||||
visible: wizardController.layoutScale == 4
|
||||
spacing: 60
|
||||
|
||||
WizardAskPassword {
|
||||
id: passwordFields
|
||||
WizardHeader {
|
||||
id: mobileHeader
|
||||
title: qsTr("Write down your recovery phrase") + translationManager.emptyString
|
||||
Accessible.role: Accessible.StaticText
|
||||
Accessible.name: qsTr("Write down your recovery phrase") + translationManager.emptyString
|
||||
Keys.onUpPressed: displaySeedButton.forceActiveFocus()
|
||||
Keys.onBacktabPressed: displaySeedButton.forceActiveFocus()
|
||||
KeyNavigation.down: mobileImage
|
||||
KeyNavigation.tab: mobileImage
|
||||
}
|
||||
|
||||
Image {
|
||||
id: mobileImage
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
fillMode: Image.PreserveAspectCrop
|
||||
source: MoneroComponents.Style.blackTheme ? "qrc:///images/write-down@2x.png" : "qrc:///images/write-down-white@2x.png"
|
||||
width: 125
|
||||
height: 125
|
||||
sourceSize.width: 125
|
||||
sourceSize.height: 125
|
||||
Accessible.role: Accessible.Graphic
|
||||
Accessible.name: qsTr("A pencil writing on a piece of paper") + translationManager.emptyString
|
||||
KeyNavigation.up: mobileHeader
|
||||
KeyNavigation.backtab: mobileHeader
|
||||
KeyNavigation.down: mobileText
|
||||
KeyNavigation.tab: mobileText
|
||||
|
||||
Rectangle {
|
||||
width: mobileImage.width
|
||||
height: mobileImage.height
|
||||
color: mobileImage.focus ? MoneroComponents.Style.titleBarButtonHoverColor : "transparent"
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
id: mobileText
|
||||
Layout.fillWidth: true
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
color: MoneroComponents.Style.dimmedFontColor
|
||||
text: qsTr("The next page will display your recovery phrase, also known as mnemonic seed.") + " " + qsTr("These words are a backup of your wallet. Write these words down now on a piece of paper in the same order displayed. Keep this paper in a safe place and do not disclose it to anybody! Do not store these words digitally, always use a paper!") + translationManager.emptyString
|
||||
|
||||
font.family: MoneroComponents.Style.fontRegular.name
|
||||
font.pixelSize: 14
|
||||
wrapMode: Text.WordWrap
|
||||
leftPadding: 0
|
||||
topPadding: 0
|
||||
Accessible.role: Accessible.StaticText
|
||||
Accessible.name: qsTr("The next page will display your recovery phrase, also known as mnemonic seed.") + " " + qsTr("These words are a backup of your wallet. Write these words down now on a piece of paper in the same order displayed. Keep this paper in a safe place and do not disclose it to anybody! Do not store these words digitally, always use a paper!") + translationManager.emptyString
|
||||
KeyNavigation.up: mobileImage
|
||||
KeyNavigation.backtab: mobileImage
|
||||
KeyNavigation.down: displaySeedButton
|
||||
KeyNavigation.tab: displaySeedButton
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: parent.focus ? MoneroComponents.Style.titleBarButtonHoverColor : "transparent"
|
||||
}
|
||||
}
|
||||
|
||||
MoneroComponents.StandardButton {
|
||||
id: displaySeedButton
|
||||
Layout.alignment: Qt.AlignHCenter;
|
||||
text: qsTr("Display recovery phrase") + translationManager.emptyString
|
||||
onClicked: {
|
||||
mobileDialog.visible = false;
|
||||
}
|
||||
Accessible.role: Accessible.Button
|
||||
Accessible.name: qsTr("The next page will display your recovery phrase, also known as mnemonic seed. ") + qsTr("These words are a backup of your wallet. Write these words down now on a piece of paper in the same order displayed. Keep this paper in a safe place and do not disclose it to anybody! Do not store these words digitally, always use a paper!") + translationManager.emptyString
|
||||
KeyNavigation.up: mobileText
|
||||
KeyNavigation.backtab: mobileText
|
||||
KeyNavigation.down: mobileHeader
|
||||
KeyNavigation.tab: mobileHeader
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: mainPage
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: wizardController.wizardSubViewTopMargin
|
||||
Layout.maximumWidth: wizardController.wizardSubViewWidth
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
visible: !mobileDialog.visible
|
||||
spacing: 15
|
||||
|
||||
WizardHeader {
|
||||
id: header
|
||||
imageIcon: wizardController.layoutScale != 4 ? (MoneroComponents.Style.blackTheme ? "qrc:///images/write-down.png" : "qrc:///images/write-down-white.png") : ""
|
||||
title: qsTr("Write down your recovery phrase") + translationManager.emptyString
|
||||
subtitleVisible: wizardController.layoutScale != 4
|
||||
subtitle: qsTr("These words are a backup of your wallet. Write these words down now on a piece of paper in the same order displayed. Keep this paper in a safe place and do not disclose it to anybody! Do not store these words digitally, always use a paper!") + translationManager.emptyString
|
||||
|
||||
Accessible.role: Accessible.StaticText
|
||||
Accessible.name: title + ". " + subtitle
|
||||
Keys.onUpPressed: navigation.btnNext.enabled ? navigation.btnNext.forceActiveFocus() : navigation.wizardProgress.forceActiveFocus()
|
||||
Keys.onBacktabPressed: navigation.btnNext.enabled ? navigation.btnNext.forceActiveFocus() : navigation.wizardProgress.forceActiveFocus()
|
||||
Keys.onDownPressed: recoveryPhraseLabel.visible ? recoveryPhraseLabel.forceActiveFocus() : focusOnListGrid()
|
||||
Keys.onTabPressed: recoveryPhraseLabel.visible ? recoveryPhraseLabel.forceActiveFocus() : focusOnListGrid()
|
||||
|
||||
function focusOnListGrid() {
|
||||
if (wizardCreateWallet2.state == "verify") {
|
||||
if (seedListGridColumn.children[0].children[wizardCreateWallet2.hiddenWords[0]].lineEdit.visible) {
|
||||
return seedListGridColumn.children[0].children[wizardCreateWallet2.hiddenWords[0]].lineEdit.forceActiveFocus();
|
||||
} else {
|
||||
return seedListGridColumn.children[0].children[wizardCreateWallet2.hiddenWords[0]].forceActiveFocus();
|
||||
}
|
||||
} else {
|
||||
return seedListGridColumn.children[0].children[0].forceActiveFocus();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MoneroComponents.TextPlain {
|
||||
id: recoveryPhraseLabel
|
||||
visible: wizardController.layoutScale != 4
|
||||
font.family: MoneroComponents.Style.fontRegular.name
|
||||
font.pixelSize: 15
|
||||
font.bold: false
|
||||
textFormat: Text.RichText
|
||||
color: MoneroComponents.Style.dimmedFontColor
|
||||
text: qsTr("Recovery phrase (mnemonic seed)") + ":" + translationManager.emptyString
|
||||
themeTransition: false
|
||||
tooltip: qsTr("These words encode your private spend key in a human readable format.") + "<br>" + qsTr("It is expected that some words may be repeated.") + translationManager.emptyString
|
||||
tooltipIconVisible: true
|
||||
Accessible.role: Accessible.StaticText
|
||||
Accessible.name: qsTr("Recovery phrase (mnemonic seed)") + translationManager.emptyString;
|
||||
KeyNavigation.up: header
|
||||
KeyNavigation.backtab: header
|
||||
Keys.onDownPressed: header.focusOnListGrid()
|
||||
Keys.onTabPressed: header.focusOnListGrid()
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: seedListGridColumn
|
||||
|
||||
function clearFields() {
|
||||
for (var i = 0; i < wizardCreateWallet2.hiddenWords.length; i++) {
|
||||
seedListGridColumn.children[0].children[wizardCreateWallet2.hiddenWords[i]].wordText.visible = true;
|
||||
seedListGridColumn.children[0].children[wizardCreateWallet2.hiddenWords[i]].lineEdit.text = "";
|
||||
seedListGridColumn.children[0].children[wizardCreateWallet2.hiddenWords[i]].lineEdit.readOnly = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.alignment: Qt.AlignRight
|
||||
|
||||
Timer {
|
||||
id: checkSeedListGridDestruction
|
||||
interval: 100; running: false; repeat: true
|
||||
onTriggered: {
|
||||
if (!wizardCreateWallet2.seedListGrid) {
|
||||
var newSeedListGrid = Qt.createComponent("SeedListGrid.qml");
|
||||
wizardCreateWallet2.seedListGrid = newSeedListGrid.createObject(seedListGridColumn);
|
||||
appWindow.showStatusMessage(qsTr("New seed generated"),3);
|
||||
pageRoot.forceActiveFocus();
|
||||
checkSeedListGridDestruction.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MoneroComponents.StandardButton {
|
||||
id: createNewSeedButton
|
||||
visible: appWindow.walletMode >= 2
|
||||
small: true
|
||||
primary: false
|
||||
text: qsTr("Create new seed") + translationManager.emptyString
|
||||
onClicked: {
|
||||
wizardController.restart(true);
|
||||
wizardController.createWallet();
|
||||
wizardCreateWallet2.seedArray = wizardController.walletOptionsSeed.split(" ")
|
||||
wizardCreateWallet2.seedListGrid.destroy();
|
||||
checkSeedListGridDestruction.start();
|
||||
}
|
||||
Accessible.role: Accessible.Button
|
||||
Accessible.name: qsTr("Create new seed") + translationManager.emptyString
|
||||
KeyNavigation.up: (wizardCreateWallet2.seedListGrid && seedListGridColumn.children[0]) ? seedListGridColumn.children[0].children[24] : recoveryPhraseLabel
|
||||
KeyNavigation.backtab: (wizardCreateWallet2.seedListGrid && seedListGridColumn.children[0]) ? seedListGridColumn.children[0].children[24] : recoveryPhraseLabel
|
||||
KeyNavigation.down: copyToClipboardButton
|
||||
KeyNavigation.tab: copyToClipboardButton
|
||||
}
|
||||
|
||||
MoneroComponents.StandardButton {
|
||||
id: copyToClipboardButton
|
||||
visible: appWindow.walletMode >= 2
|
||||
small: true
|
||||
primary: false
|
||||
text: qsTr("Copy to clipboard") + translationManager.emptyString
|
||||
onClicked: {
|
||||
clipboard.setText(wizardController.walletOptionsSeed);
|
||||
appWindow.showStatusMessage(qsTr("Recovery phrase copied to clipboard"),3);
|
||||
}
|
||||
Accessible.role: Accessible.Button
|
||||
Accessible.name: qsTr("Copy to clipboard") + translationManager.emptyString
|
||||
KeyNavigation.up: createNewSeedButton
|
||||
KeyNavigation.backtab: createNewSeedButton
|
||||
KeyNavigation.down: printPDFTemplate.visible ? printPDFTemplate : walletCreationDate
|
||||
KeyNavigation.tab: printPDFTemplate.visible ? printPDFTemplate : walletCreationDate
|
||||
}
|
||||
|
||||
MoneroComponents.StandardButton {
|
||||
id: printPDFTemplate
|
||||
small: true
|
||||
primary: false
|
||||
text: qsTr("Print a template") + translationManager.emptyString
|
||||
tooltip: qsTr("Print a template to write down your seed") + translationManager.emptyString
|
||||
onClicked: {
|
||||
oshelper.openSeedTemplate();
|
||||
}
|
||||
Accessible.role: Accessible.Button
|
||||
Accessible.name: qsTr("Print a template to write down your seed") + translationManager.emptyString
|
||||
KeyNavigation.up: copyToClipboardButton.visible ? copyToClipboardButton : (wizardCreateWallet2.seedListGrid && seedListGridColumn.children[0]) ? seedListGridColumn.children[0].children[24] : recoveryPhraseLabel
|
||||
KeyNavigation.backtab: copyToClipboardButton.visible ? copyToClipboardButton : (wizardCreateWallet2.seedListGrid && seedListGridColumn.children[0]) ? seedListGridColumn.children[0].children[24] : recoveryPhraseLabel
|
||||
KeyNavigation.down: walletCreationDate
|
||||
KeyNavigation.tab: walletCreationDate
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Layout.topMargin: 0
|
||||
Layout.fillWidth: true
|
||||
Layout.maximumWidth: seedListGridColumn.width
|
||||
spacing: 10
|
||||
|
||||
ColumnLayout {
|
||||
spacing: 5
|
||||
Layout.fillWidth: true
|
||||
|
||||
MoneroComponents.TextPlain {
|
||||
id: walletCreationDate
|
||||
font.family: MoneroComponents.Style.fontRegular.name
|
||||
font.pixelSize: 15
|
||||
font.bold: false
|
||||
textFormat: Text.RichText
|
||||
color: MoneroComponents.Style.dimmedFontColor
|
||||
text: qsTr("Creation date") + ": " + translationManager.emptyString
|
||||
themeTransition: false
|
||||
Accessible.role: Accessible.StaticText
|
||||
Accessible.name: qsTr("Creation date") + " " + walletCreationDateValue.text + translationManager.emptyString
|
||||
KeyNavigation.up: printPDFTemplate.visible ? printPDFTemplate : copyToClipboardButton
|
||||
KeyNavigation.backtab: printPDFTemplate.visible ? printPDFTemplate : copyToClipboardButton
|
||||
KeyNavigation.down: walletRestoreHeight
|
||||
KeyNavigation.tab: walletRestoreHeight
|
||||
}
|
||||
|
||||
MoneroComponents.TextPlain {
|
||||
id: walletCreationDateValue
|
||||
property var locale: Qt.locale()
|
||||
property date currentDate: new Date()
|
||||
font.family: MoneroComponents.Style.fontRegular.name
|
||||
font.pixelSize: 16
|
||||
font.bold: true
|
||||
textFormat: Text.RichText
|
||||
color: MoneroComponents.Style.defaultFontColor
|
||||
text: currentDate.toLocaleDateString(locale, Locale.ShortFormat)
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
spacing: 5
|
||||
Layout.fillWidth: true
|
||||
|
||||
MoneroComponents.TextPlain {
|
||||
id: walletRestoreHeight
|
||||
font.family: MoneroComponents.Style.fontRegular.name
|
||||
font.pixelSize: 15
|
||||
font.bold: false
|
||||
textFormat: Text.RichText
|
||||
color: MoneroComponents.Style.dimmedFontColor
|
||||
text: qsTr("Restore height") + ":" + translationManager.emptyString
|
||||
tooltip: wizardController.layoutScale != 4 ? qsTr("Enter this number when restoring the wallet to make your initial wallet synchronization faster.") : "" + translationManager.emptyString
|
||||
tooltipIconVisible: true
|
||||
themeTransition: false
|
||||
Accessible.role: Accessible.StaticText
|
||||
Accessible.name: qsTr("Restore height") + " " + Utils.roundDownToNearestThousand(wizardController.m_wallet ? wizardController.m_wallet.walletCreationHeight : 0) + translationManager.emptyString
|
||||
KeyNavigation.up: walletCreationDate
|
||||
KeyNavigation.backtab: walletCreationDate
|
||||
Keys.onDownPressed: navigation.btnPrev.forceActiveFocus();
|
||||
Keys.onTabPressed: navigation.btnPrev.forceActiveFocus();
|
||||
}
|
||||
|
||||
MoneroComponents.TextPlain {
|
||||
id: walletRestoreHeightValue
|
||||
font.family: MoneroComponents.Style.fontRegular.name
|
||||
font.pixelSize: 16
|
||||
font.bold: true
|
||||
textFormat: Text.RichText
|
||||
color: MoneroComponents.Style.defaultFontColor
|
||||
text: Utils.roundDownToNearestThousand(wizardController.m_wallet ? wizardController.m_wallet.walletCreationHeight : 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WizardNav {
|
||||
progressSteps: appWindow.walletMode <= 1 ? 3 : 4
|
||||
id: navigation
|
||||
progressSteps: appWindow.walletMode <= 1 ? 4 : 5
|
||||
progress: 1
|
||||
btnNext.enabled: passwordFields.calcStrengthAndVerify();
|
||||
onPrevClicked: {
|
||||
if(wizardController.walletOptionsIsRecoveringFromDevice){
|
||||
wizardStateView.state = "wizardCreateDevice1";
|
||||
} else {
|
||||
wizardStateView.state = "wizardCreateWallet1";
|
||||
}
|
||||
wizardStateView.state = "wizardCreateWallet1";
|
||||
mobileDialog.visible = Qt.binding(function() { return wizardController.layoutScale == 4 })
|
||||
}
|
||||
btnPrevKeyNavigationBackTab: wizardCreateWallet2.state == "default" ? walletRestoreHeight
|
||||
: seedListGridColumn.children[0].children[wizardCreateWallet2.hiddenWords[4]].lineEdit.visible ? seedListGridColumn.children[0].children[wizardCreateWallet2.hiddenWords[4]].lineEdit
|
||||
: seedListGridColumn.children[0].children[24]
|
||||
btnNextKeyNavigationTab: mobileDialog.visible ? mobileHeader : header
|
||||
btnNext.enabled: walletCreationDate.opacity == 1 || appWindow.ctrlPressed ? true
|
||||
: seedListGridColumn.children[0].children[hiddenWords[0]].icon.wordsMatch &&
|
||||
seedListGridColumn.children[0].children[hiddenWords[1]].icon.wordsMatch &&
|
||||
seedListGridColumn.children[0].children[hiddenWords[2]].icon.wordsMatch &&
|
||||
seedListGridColumn.children[0].children[hiddenWords[3]].icon.wordsMatch &&
|
||||
seedListGridColumn.children[0].children[hiddenWords[4]].icon.wordsMatch
|
||||
onNextClicked: {
|
||||
wizardController.walletOptionsPassword = passwordFields.password;
|
||||
|
||||
if(appWindow.walletMode === 0 || appWindow.walletMode === 1){
|
||||
wizardStateView.state = "wizardCreateWallet4";
|
||||
} else {
|
||||
wizardStateView.state = "wizardCreateWallet3";
|
||||
//choose five random words to hide
|
||||
for (var i = 0; i < hiddenWords.length; i++) {
|
||||
wizardCreateWallet2.hiddenWords[i] = Math.floor(Math.random() * 5) + 5 * i
|
||||
}
|
||||
|
||||
wizardCreateWallet2.state = "verify";
|
||||
for (var i = 0; i < hiddenWords.length; i++) {
|
||||
seedListGridColumn.children[0].children[wizardCreateWallet2.hiddenWords[i]].wordText.visible = false;
|
||||
}
|
||||
seedListGridColumn.children[0].children[wizardCreateWallet2.hiddenWords[0]].lineEdit.forceActiveFocus();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function onPageCompleted(previousView){
|
||||
wizardCreateWallet2.seedArray = wizardController.walletOptionsSeed.split(" ")
|
||||
if (!wizardCreateWallet2.seedListGrid) {
|
||||
var component = Qt.createComponent("SeedListGrid.qml");
|
||||
wizardCreateWallet2.seedListGrid = component.createObject(seedListGridColumn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,6 +38,8 @@ Rectangle {
|
||||
color: "transparent"
|
||||
property alias pageHeight: pageRoot.height
|
||||
property string viewName: "wizardCreateWallet3"
|
||||
property alias pwField: passwordFields.password
|
||||
property alias pwConfirmField: passwordFields.passwordConfirm
|
||||
|
||||
ColumnLayout {
|
||||
id: pageRoot
|
||||
@@ -53,26 +55,32 @@ Rectangle {
|
||||
Layout.topMargin: wizardController.wizardSubViewTopMargin
|
||||
Layout.maximumWidth: wizardController.wizardSubViewWidth
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
spacing: 20
|
||||
spacing: 0
|
||||
|
||||
WizardHeader {
|
||||
title: qsTr("Daemon settings") + translationManager.emptyString
|
||||
subtitle: qsTr("To be able to communicate with the Monero network your wallet needs to be connected to a Monero node. For best privacy it's recommended to run your own node.") + translationManager.emptyString
|
||||
}
|
||||
|
||||
WizardDaemonSettings {
|
||||
id: daemonSettings
|
||||
WizardAskPassword {
|
||||
id: passwordFields
|
||||
}
|
||||
|
||||
WizardNav {
|
||||
progressSteps: 4
|
||||
progressSteps: appWindow.walletMode <= 1 ? 4 : 5
|
||||
progress: 2
|
||||
btnNext.enabled: passwordFields.calcStrengthAndVerify();
|
||||
onPrevClicked: {
|
||||
wizardStateView.state = "wizardCreateWallet2";
|
||||
if(wizardController.walletOptionsIsRecoveringFromDevice){
|
||||
wizardStateView.state = "wizardCreateDevice1";
|
||||
} else {
|
||||
wizardStateView.state = "wizardCreateWallet2";
|
||||
wizardStateView.wizardCreateWallet2View.pageRoot.forceActiveFocus();
|
||||
}
|
||||
}
|
||||
onNextClicked: {
|
||||
daemonSettings.save();
|
||||
wizardStateView.state = "wizardCreateWallet4";
|
||||
wizardController.walletOptionsPassword = passwordFields.password;
|
||||
|
||||
if (appWindow.walletMode < 2) {
|
||||
wizardStateView.state = "wizardCreateWallet5";
|
||||
} else {
|
||||
wizardStateView.state = "wizardCreateWallet4";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,6 @@ import QtQuick 2.9
|
||||
import QtQuick.Layouts 1.2
|
||||
import QtQuick.Controls 2.0
|
||||
|
||||
import "../js/Wizard.js" as Wizard
|
||||
import "../components" as MoneroComponents
|
||||
|
||||
Rectangle {
|
||||
@@ -38,7 +37,6 @@ Rectangle {
|
||||
|
||||
color: "transparent"
|
||||
property alias pageHeight: pageRoot.height
|
||||
property alias wizardNav: wizardNav
|
||||
property string viewName: "wizardCreateWallet4"
|
||||
|
||||
ColumnLayout {
|
||||
@@ -58,35 +56,23 @@ Rectangle {
|
||||
spacing: 20
|
||||
|
||||
WizardHeader {
|
||||
title: qsTr("You're all set up!") + translationManager.emptyString
|
||||
subtitle: qsTr("New wallet details:") + translationManager.emptyString
|
||||
title: qsTr("Daemon settings") + translationManager.emptyString
|
||||
subtitle: qsTr("To be able to communicate with the Monero network your wallet needs to be connected to a Monero node. For best privacy it's recommended to run your own node.") + translationManager.emptyString
|
||||
}
|
||||
|
||||
WizardSummary {}
|
||||
WizardDaemonSettings {
|
||||
id: daemonSettings
|
||||
}
|
||||
|
||||
WizardNav {
|
||||
id: wizardNav
|
||||
Layout.topMargin: 24
|
||||
btnNextText: qsTr("Create wallet") + translationManager.emptyString
|
||||
progressSteps: appWindow.walletMode <= 1 ? 3 : 4
|
||||
progress: appWindow.walletMode <= 1 ? 2 : 3
|
||||
|
||||
progressSteps: 5
|
||||
progress: 3
|
||||
onPrevClicked: {
|
||||
if (appWindow.walletMode <= 1){
|
||||
wizardStateView.state = "wizardCreateWallet1";
|
||||
} else {
|
||||
wizardStateView.state = "wizardCreateWallet3";
|
||||
}
|
||||
wizardStateView.state = "wizardCreateWallet3";
|
||||
}
|
||||
onNextClicked: {
|
||||
btnNext.enabled = false;
|
||||
wizardController.wizardStateView.wizardCreateWallet2View.pwField = "";
|
||||
wizardController.wizardStateView.wizardCreateWallet2View.pwConfirmField = "";
|
||||
wizardController.writeWallet(function() {
|
||||
wizardController.useMoneroClicked();
|
||||
wizardController.walletOptionsIsRecoveringFromDevice = false;
|
||||
btnNext.enabled = true;
|
||||
});
|
||||
daemonSettings.save();
|
||||
wizardStateView.state = "wizardCreateWallet5";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
94
wizard/WizardCreateWallet5.qml
Normal file
@@ -0,0 +1,94 @@
|
||||
// Copyright (c) 2014-2019, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import QtQuick 2.9
|
||||
import QtQuick.Layouts 1.2
|
||||
import QtQuick.Controls 2.0
|
||||
|
||||
import "../js/Wizard.js" as Wizard
|
||||
import "../components" as MoneroComponents
|
||||
|
||||
Rectangle {
|
||||
id: wizardCreateWallet5
|
||||
|
||||
color: "transparent"
|
||||
property alias pageHeight: pageRoot.height
|
||||
property alias wizardNav: wizardNav
|
||||
property string viewName: "wizardCreateWallet5"
|
||||
|
||||
ColumnLayout {
|
||||
id: pageRoot
|
||||
Layout.alignment: Qt.AlignHCenter;
|
||||
width: parent.width - 100
|
||||
Layout.fillWidth: true
|
||||
anchors.horizontalCenter: parent.horizontalCenter;
|
||||
|
||||
spacing: 0
|
||||
|
||||
ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: wizardController.wizardSubViewTopMargin
|
||||
Layout.maximumWidth: wizardController.wizardSubViewWidth
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
spacing: 20
|
||||
|
||||
WizardHeader {
|
||||
title: qsTr("You're all set up!") + translationManager.emptyString
|
||||
subtitle: qsTr("New wallet details:") + translationManager.emptyString
|
||||
}
|
||||
|
||||
WizardSummary {}
|
||||
|
||||
WizardNav {
|
||||
id: wizardNav
|
||||
Layout.topMargin: 24
|
||||
btnNextText: qsTr("Create wallet") + translationManager.emptyString
|
||||
progressSteps: appWindow.walletMode <= 1 ? 4 : 5
|
||||
progress: appWindow.walletMode <= 1 ? 3 : 4
|
||||
|
||||
onPrevClicked: {
|
||||
if (appWindow.walletMode <= 1){
|
||||
wizardStateView.state = "wizardCreateWallet1";
|
||||
} else {
|
||||
wizardStateView.state = "wizardCreateWallet4";
|
||||
}
|
||||
}
|
||||
onNextClicked: {
|
||||
btnNext.enabled = false;
|
||||
wizardController.wizardStateView.wizardCreateWallet3View.pwField = "";
|
||||
wizardController.wizardStateView.wizardCreateWallet3View.pwConfirmField = "";
|
||||
wizardController.writeWallet(function() {
|
||||
wizardController.useMoneroClicked();
|
||||
wizardController.walletOptionsIsRecoveringFromDevice = false;
|
||||
});
|
||||
btnNext.enabled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -38,44 +38,60 @@ import QtQuick.Controls 2.0
|
||||
ColumnLayout {
|
||||
property string title: ""
|
||||
property string subtitle: ""
|
||||
property alias imageIcon: icon.source
|
||||
property bool subtitleVisible: true
|
||||
spacing: 4
|
||||
Layout.maximumWidth: wizardController.wizardSubViewWidth
|
||||
|
||||
Text {
|
||||
text: title
|
||||
font.family: MoneroComponents.Style.fontRegular.name
|
||||
color: MoneroComponents.Style.defaultFontColor
|
||||
opacity: MoneroComponents.Style.blackTheme ? 1.0 : 0.8
|
||||
font.pixelSize: {
|
||||
if(wizardController.layoutScale === 2 ){
|
||||
return 34;
|
||||
} else {
|
||||
return 28;
|
||||
}
|
||||
RowLayout {
|
||||
spacing: 0
|
||||
|
||||
Image {
|
||||
id: icon
|
||||
visible: icon.source != ""
|
||||
source: ""
|
||||
width: wizardController.layoutScale == 4 ? 35 : 50
|
||||
height: wizardController.layoutScale == 4 ? 35 : 50
|
||||
}
|
||||
|
||||
wrapMode: Text.WordWrap
|
||||
leftPadding: 0
|
||||
topPadding: 0
|
||||
bottomPadding: 0
|
||||
Text {
|
||||
text: title
|
||||
font.family: MoneroComponents.Style.fontRegular.name
|
||||
color: MoneroComponents.Style.defaultFontColor
|
||||
opacity: MoneroComponents.Style.blackTheme ? 1.0 : 0.8
|
||||
font.pixelSize: {
|
||||
if (wizardController.layoutScale == 4) {
|
||||
return 16;
|
||||
} else if (wizardController.layoutScale == 3) {
|
||||
return 28;
|
||||
} else if (wizardController.layoutScale <= 2) {
|
||||
return 32;
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: parent.parent.focus ? MoneroComponents.Style.titleBarButtonHoverColor : "transparent"
|
||||
wrapMode: Text.WordWrap
|
||||
leftPadding: 0
|
||||
topPadding: 0
|
||||
bottomPadding: 0
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: parent.parent.parent.focus ? MoneroComponents.Style.titleBarButtonHoverColor : "transparent"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
Layout.fillWidth: true
|
||||
Layout.alignment: Qt.AlignLeft
|
||||
visible: parent.subtitle !== ""
|
||||
visible: parent.subtitle !== "" && subtitleVisible
|
||||
|
||||
color: MoneroComponents.Style.dimmedFontColor
|
||||
text: subtitle
|
||||
|
||||
font.family: MoneroComponents.Style.fontRegular.name
|
||||
font.pixelSize: {
|
||||
if(wizardController.layoutScale === 2 ){
|
||||
if (wizardController.layoutScale <= 2 ) {
|
||||
return 16;
|
||||
} else {
|
||||
return 14;
|
||||
|
||||
@@ -86,6 +86,7 @@ Rectangle {
|
||||
wizardController.restart();
|
||||
wizardController.createWallet();
|
||||
wizardStateView.state = "wizardCreateWallet1"
|
||||
wizardStateView.wizardCreateWallet1View.pageRoot.forceActiveFocus();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -102,10 +102,12 @@ RowLayout {
|
||||
font.bold: true
|
||||
font.family: MoneroComponents.Style.fontRegular.name
|
||||
font.pixelSize: {
|
||||
if(wizardController.layoutScale === 2 ){
|
||||
return 22;
|
||||
} else {
|
||||
if (wizardController.layoutScale == 4) {
|
||||
return 16;
|
||||
} else if (wizardController.layoutScale == 3) {
|
||||
return 20;
|
||||
} else if (wizardController.layoutScale <= 2) {
|
||||
return 22;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,7 +126,7 @@ RowLayout {
|
||||
color: MoneroComponents.Style.dimmedFontColor
|
||||
font.family: MoneroComponents.Style.fontRegular.name
|
||||
font.pixelSize: {
|
||||
if(wizardController.layoutScale === 2 ){
|
||||
if (wizardController.layoutScale <= 2 ){
|
||||
return 16;
|
||||
} else {
|
||||
return 14;
|
||||
|
||||
@@ -41,7 +41,7 @@ Rectangle {
|
||||
property alias pageHeight: pageRoot.height
|
||||
property string viewName: "wizardModeSelection1"
|
||||
property bool portable: persistentSettings.portable
|
||||
property bool simpleModeAvailable: !isTails && appWindow.persistentSettings.nettype == 0
|
||||
property bool simpleModeAvailable: !isTails && appWindow.persistentSettings.nettype == 0 && !isAndroid
|
||||
|
||||
function applyWalletMode(mode, wizardState) {
|
||||
if (!persistentSettings.setPortable(portable)) {
|
||||
|
||||
@@ -43,9 +43,10 @@ RowLayout {
|
||||
property bool autoTransition: true
|
||||
property alias btnPrev: btnPrev
|
||||
property alias btnNext: btnNext
|
||||
property alias wizardProgress: wizardProgress
|
||||
property string btnPrevText: qsTr("Previous") + translationManager.emptyString
|
||||
property string btnNextText: qsTr("Next") + translationManager.emptyString
|
||||
Layout.topMargin: 20
|
||||
Layout.topMargin: 0
|
||||
Layout.preferredHeight: 70
|
||||
Layout.preferredWidth: parent.width
|
||||
|
||||
@@ -70,9 +71,11 @@ RowLayout {
|
||||
|
||||
MoneroComponents.StandardButton {
|
||||
id: btnPrev
|
||||
width: appWindow.width <= 506 ? 45 : appWindow.width <= 660 ? 120 : 180
|
||||
small: true
|
||||
text: menuNav.btnPrevText
|
||||
|
||||
primary: false
|
||||
text: appWindow.width <= 506 ? "<" : menuNav.btnPrevText
|
||||
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
@@ -134,8 +137,9 @@ RowLayout {
|
||||
|
||||
MoneroComponents.StandardButton {
|
||||
id: btnNext
|
||||
width: appWindow.width <= 506 ? 45 : appWindow.width <= 660 ? 120 : 180
|
||||
small: true
|
||||
text: menuNav.btnNextText
|
||||
text: appWindow.width <= 506 ? ">" : menuNav.btnNextText
|
||||
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.right: parent.right
|
||||
|
||||
@@ -34,6 +34,7 @@ import QtGraphicalEffects 1.0
|
||||
import Qt.labs.folderlistmodel 2.1
|
||||
import moneroComponents.NetworkType 1.0
|
||||
import moneroComponents.WalletKeysFilesModel 1.0
|
||||
import FontAwesome 1.0
|
||||
|
||||
import "../js/Wizard.js" as Wizard
|
||||
import "../components"
|
||||
@@ -329,8 +330,9 @@ Rectangle {
|
||||
id: wizardNav
|
||||
Layout.topMargin: 0
|
||||
progressEnabled: false
|
||||
btnPrev.text: qsTr("Back to menu") + translationManager.emptyString
|
||||
btnNext.text: qsTr("Browse filesystem") + translationManager.emptyString
|
||||
btnPrev.text: appWindow.width <= 506 ? "<" : qsTr("Back to menu") + translationManager.emptyString
|
||||
btnNext.text: appWindow.width <= 506 ? qsTr("Browse") : qsTr("Browse filesystem") + translationManager.emptyString
|
||||
btnNext.width: appWindow.width <= 506 ? 80 : appWindow.width <= 660 ? 120 : 180
|
||||
btnNext.visible: true
|
||||
btnPrevKeyNavigationBackTab: recentList.itemAt(recentList.count - 1)
|
||||
btnNextKeyNavigationTab: openWalletFromFileHeader
|
||||
|
||||
@@ -54,7 +54,8 @@ ColumnLayout {
|
||||
WizardSummaryItem {
|
||||
Layout.fillWidth: true
|
||||
header: qsTr("Mnemonic seed language") + translationManager.emptyString
|
||||
value: persistentSettings.language
|
||||
value: persistentSettings.language_wallet
|
||||
visible: wizardStateView.state === "wizardCreateWallet5" && !wizardController.walletOptionsIsRecoveringFromDevice
|
||||
}
|
||||
|
||||
WizardSummaryItem {
|
||||
|
||||
@@ -41,9 +41,16 @@ GridLayout {
|
||||
Layout.fillWidth: true
|
||||
property alias walletName: walletName
|
||||
property alias walletLocation: walletLocation
|
||||
property alias browseButton: browseButton
|
||||
property alias errorMessageWalletName: errorMessageWalletName
|
||||
property alias errorMessageWalletLocation: errorMessageWalletLocation
|
||||
property bool rowLayout: true
|
||||
property var walletNameKeyNavigationBackTab: browseButton
|
||||
property var browseButtonKeyNavigationTab: walletName
|
||||
|
||||
columnSpacing: 20
|
||||
columns: 2
|
||||
columnSpacing: rowLayout ? 20 : 0
|
||||
rowSpacing: rowLayout ? 0 : 20
|
||||
columns: rowLayout ? 2 : 1
|
||||
|
||||
function verify() {
|
||||
if (walletName.text !== '' && walletLocation.text !== '') {
|
||||
@@ -61,79 +68,163 @@ GridLayout {
|
||||
walletName.text = Wizard.unusedWalletName(appWindow.accountsDir, defaultAccountName, walletManager);
|
||||
}
|
||||
|
||||
MoneroComponents.LineEdit {
|
||||
id: walletName
|
||||
Layout.preferredWidth: grid.width/5
|
||||
ColumnLayout {
|
||||
MoneroComponents.LineEdit {
|
||||
id: walletName
|
||||
Layout.preferredWidth: grid.width/5
|
||||
|
||||
function verify(){
|
||||
if (walletName.text === "") {
|
||||
errorMessageWalletName.text = qsTr("Wallet name is empty") + translationManager.emptyString;
|
||||
return false;
|
||||
}
|
||||
if (/[\\\/]/.test(walletName.text)) {
|
||||
errorMessageWalletName.text = qsTr("Wallet name is invalid") + translationManager.emptyString;
|
||||
return false;
|
||||
}
|
||||
if (walletLocation.text !== "") {
|
||||
var walletAlreadyExists = Wizard.walletPathExists(appWindow.accountsDir, walletLocation.text, walletName.text, isIOS, walletManager);
|
||||
if (walletAlreadyExists) {
|
||||
errorMessageWalletName.text = qsTr("Wallet already exists") + translationManager.emptyString;
|
||||
function verify(){
|
||||
if (walletName.text === "") {
|
||||
errorMessageWalletName.text = qsTr("Wallet name is empty") + translationManager.emptyString;
|
||||
return false;
|
||||
}
|
||||
if (/[\\\/]/.test(walletName.text)) {
|
||||
errorMessageWalletName.text = qsTr("Wallet name is invalid") + translationManager.emptyString;
|
||||
return false;
|
||||
}
|
||||
if (walletLocation.text !== "") {
|
||||
var walletAlreadyExists = Wizard.walletPathExists(appWindow.accountsDir, walletLocation.text, walletName.text, isIOS, walletManager);
|
||||
if (walletAlreadyExists) {
|
||||
errorMessageWalletName.text = qsTr("Wallet already exists") + translationManager.emptyString;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
errorMessageWalletName.text = "";
|
||||
return true;
|
||||
}
|
||||
errorMessageWalletName.text = "";
|
||||
return true;
|
||||
|
||||
labelText: qsTr("Wallet name") + translationManager.emptyString
|
||||
labelFontSize: 14
|
||||
fontSize: 16
|
||||
placeholderFontSize: 16
|
||||
placeholderText: ""
|
||||
errorWhenEmpty: true
|
||||
text: defaultAccountName
|
||||
|
||||
onTextChanged: walletName.error = !walletName.verify();
|
||||
Component.onCompleted: walletName.error = !walletName.verify();
|
||||
|
||||
Accessible.role: Accessible.EditableText
|
||||
Accessible.name: labelText + text
|
||||
KeyNavigation.up: walletNameKeyNavigationBackTab
|
||||
KeyNavigation.backtab: walletNameKeyNavigationBackTab
|
||||
KeyNavigation.down: errorMessageWalletName.text != "" ? errorMessageWalletName : appWindow.walletMode >= 2 ? walletLocation : wizardNav.btnPrev
|
||||
KeyNavigation.tab: errorMessageWalletName.text != "" ? errorMessageWalletName : appWindow.walletMode >= 2 ? walletLocation : wizardNav.btnPrev
|
||||
}
|
||||
|
||||
labelText: qsTr("Wallet name") + translationManager.emptyString
|
||||
labelFontSize: 14
|
||||
fontSize: 16
|
||||
placeholderFontSize: 16
|
||||
placeholderText: ""
|
||||
errorWhenEmpty: true
|
||||
text: defaultAccountName
|
||||
RowLayout {
|
||||
Layout.preferredWidth: grid.width/5
|
||||
|
||||
onTextChanged: walletName.error = !walletName.verify();
|
||||
Component.onCompleted: walletName.error = !walletName.verify();
|
||||
MoneroComponents.TextPlain {
|
||||
visible: errorMessageWalletName.text != ""
|
||||
font.family: FontAwesome.fontFamilySolid
|
||||
font.styleName: "Solid"
|
||||
font.pixelSize: 15
|
||||
text: FontAwesome.exclamationCircle
|
||||
color: "#FF0000"
|
||||
themeTransition: false
|
||||
}
|
||||
|
||||
MoneroComponents.TextPlain {
|
||||
id: errorMessageWalletName
|
||||
textFormat: Text.PlainText
|
||||
font.family: MoneroComponents.Style.fontRegular.name
|
||||
font.pixelSize: 14
|
||||
color: "#FF0000"
|
||||
themeTransition: false
|
||||
Accessible.role: Accessible.StaticText
|
||||
Accessible.name: text
|
||||
KeyNavigation.up: walletName
|
||||
KeyNavigation.backtab: walletName
|
||||
KeyNavigation.down: walletLocation
|
||||
KeyNavigation.tab: walletLocation
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MoneroComponents.LineEdit {
|
||||
id: walletLocation
|
||||
Layout.preferredWidth: grid.width/3
|
||||
ColumnLayout {
|
||||
visible: appWindow.walletMode >= 2
|
||||
|
||||
function verify() {
|
||||
if (walletLocation.text == "") {
|
||||
errorMessageWalletLocation.text = qsTr("Wallet location is empty") + translationManager.emptyString;
|
||||
return false;
|
||||
MoneroComponents.LineEdit {
|
||||
id: walletLocation
|
||||
Layout.preferredWidth: grid.width/3
|
||||
|
||||
function verify() {
|
||||
if (walletLocation.text == "") {
|
||||
errorMessageWalletLocation.text = qsTr("Wallet location is empty") + translationManager.emptyString;
|
||||
return false;
|
||||
}
|
||||
errorMessageWalletLocation.text = "";
|
||||
return true;
|
||||
}
|
||||
|
||||
labelText: qsTr("Wallet location") + translationManager.emptyString
|
||||
labelFontSize: 14
|
||||
fontSize: 16
|
||||
placeholderText: ""
|
||||
placeholderFontSize: 16
|
||||
errorWhenEmpty: true
|
||||
text: appWindow.accountsDir + "/"
|
||||
onTextChanged: {
|
||||
walletLocation.error = !walletLocation.verify();
|
||||
walletName.error = !walletName.verify();
|
||||
}
|
||||
Component.onCompleted: walletLocation.error = !walletLocation.verify();
|
||||
Accessible.role: Accessible.EditableText
|
||||
Accessible.name: labelText + text
|
||||
KeyNavigation.up: errorMessageWalletName.text != "" ? errorMessageWalletName : walletName
|
||||
KeyNavigation.backtab: errorMessageWalletName.text != "" ? errorMessageWalletName : walletName
|
||||
KeyNavigation.down: browseButton
|
||||
KeyNavigation.tab: browseButton
|
||||
|
||||
MoneroComponents.InlineButton {
|
||||
id: browseButton
|
||||
fontFamily: FontAwesome.fontFamilySolid
|
||||
fontStyleName: "Solid"
|
||||
fontPixelSize: 18
|
||||
text: FontAwesome.folderOpen
|
||||
tooltip: qsTr("Browse") + translationManager.emptyString
|
||||
tooltipLeft: true
|
||||
onClicked: {
|
||||
fileWalletDialog.folder = walletManager.localPathToUrl(walletLocation.text)
|
||||
fileWalletDialog.open()
|
||||
walletLocation.focus = true
|
||||
}
|
||||
Accessible.role: Accessible.Button
|
||||
Accessible.name: qsTr("Browse") + translationManager.emptyString
|
||||
KeyNavigation.up: walletLocation
|
||||
KeyNavigation.backtab: walletLocation
|
||||
KeyNavigation.down: errorMessageWalletLocation.text != "" ? errorMessageWalletLocation : browseButtonKeyNavigationTab
|
||||
KeyNavigation.tab: errorMessageWalletLocation.text != "" ? errorMessageWalletLocation : browseButtonKeyNavigationTab
|
||||
}
|
||||
errorMessageWalletLocation.text = "";
|
||||
return true;
|
||||
}
|
||||
|
||||
labelText: qsTr("Wallet location") + translationManager.emptyString
|
||||
labelFontSize: 14
|
||||
fontSize: 16
|
||||
placeholderText: ""
|
||||
placeholderFontSize: 16
|
||||
errorWhenEmpty: true
|
||||
text: appWindow.accountsDir + "/"
|
||||
onTextChanged: {
|
||||
walletLocation.error = !walletLocation.verify();
|
||||
walletName.error = !walletName.verify();
|
||||
}
|
||||
Component.onCompleted: walletLocation.error = !walletLocation.verify();
|
||||
RowLayout {
|
||||
Layout.preferredWidth: grid.width/3
|
||||
|
||||
MoneroComponents.InlineButton {
|
||||
fontFamily: FontAwesome.fontFamilySolid
|
||||
fontStyleName: "Solid"
|
||||
fontPixelSize: 18
|
||||
text: FontAwesome.folderOpen
|
||||
tooltip: qsTr("Browse") + translationManager.emptyString
|
||||
tooltipLeft: true
|
||||
onClicked: {
|
||||
fileWalletDialog.folder = walletManager.localPathToUrl(walletLocation.text)
|
||||
fileWalletDialog.open()
|
||||
walletLocation.focus = true
|
||||
MoneroComponents.TextPlain {
|
||||
visible: errorMessageWalletLocation.text != ""
|
||||
font.family: FontAwesome.fontFamilySolid
|
||||
font.styleName: "Solid"
|
||||
font.pixelSize: 15
|
||||
text: FontAwesome.exclamationCircle
|
||||
color: "#FF0000"
|
||||
themeTransition: false
|
||||
}
|
||||
|
||||
MoneroComponents.TextPlain {
|
||||
id: errorMessageWalletLocation
|
||||
textFormat: Text.PlainText
|
||||
font.family: MoneroComponents.Style.fontRegular.name
|
||||
font.pixelSize: 14
|
||||
color: "#FF0000"
|
||||
themeTransition: false
|
||||
Accessible.role: Accessible.StaticText
|
||||
Accessible.name: text
|
||||
KeyNavigation.up: browseButton
|
||||
KeyNavigation.backtab: browseButton
|
||||
KeyNavigation.down: browseButtonKeyNavigationTab
|
||||
KeyNavigation.tab: browseButtonKeyNavigationTab
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -152,50 +243,4 @@ GridLayout {
|
||||
fileWalletDialog.visible = false;
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Layout.preferredWidth: grid.width/5
|
||||
|
||||
MoneroComponents.TextPlain {
|
||||
visible: errorMessageWalletName.text != ""
|
||||
font.family: FontAwesome.fontFamilySolid
|
||||
font.styleName: "Solid"
|
||||
font.pixelSize: 15
|
||||
text: FontAwesome.exclamationCircle
|
||||
color: "#FF0000"
|
||||
themeTransition: false
|
||||
}
|
||||
|
||||
MoneroComponents.TextPlain {
|
||||
id: errorMessageWalletName
|
||||
textFormat: Text.PlainText
|
||||
font.family: MoneroComponents.Style.fontRegular.name
|
||||
font.pixelSize: 14
|
||||
color: "#FF0000"
|
||||
themeTransition: false
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Layout.preferredWidth: grid.width/3
|
||||
|
||||
MoneroComponents.TextPlain {
|
||||
visible: errorMessageWalletLocation.text != ""
|
||||
font.family: FontAwesome.fontFamilySolid
|
||||
font.styleName: "Solid"
|
||||
font.pixelSize: 15
|
||||
text: FontAwesome.exclamationCircle
|
||||
color: "#FF0000"
|
||||
themeTransition: false
|
||||
}
|
||||
|
||||
MoneroComponents.TextPlain {
|
||||
id: errorMessageWalletLocation
|
||||
textFormat: Text.PlainText
|
||||
font.family: MoneroComponents.Style.fontRegular.name
|
||||
font.pixelSize: 14
|
||||
color: "#FF0000"
|
||||
themeTransition: false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||