Compare commits
80 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
c390afd258 | ||
|
|
80ade41905 | ||
|
|
83921a4bc8 | ||
|
|
acf876f4b2 | ||
|
|
7954661100 | ||
|
|
22a1509316 | ||
|
|
499eeee59a | ||
|
|
8cf76cf7c2 | ||
|
|
6441d99279 | ||
|
|
aef4a982dc | ||
|
|
f93c67740c | ||
|
|
4b8e0f36ab | ||
|
|
c247b96c4a | ||
|
|
085f4af1dc | ||
|
|
49a6c8ba9c | ||
|
|
df9b35e947 | ||
|
|
96b6e5972f | ||
|
|
b801ef594b | ||
|
|
ff0c068cb8 | ||
|
|
1b119eb8f5 | ||
|
|
6a8a123da8 | ||
|
|
6f2aafdd6c | ||
|
|
64a6ca7fc7 | ||
|
|
8b356605b4 | ||
|
|
131154ba80 |
103
.github/verify_p2pool.py
vendored
Normal file
@@ -0,0 +1,103 @@
|
||||
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",
|
||||
"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()
|
||||
6
.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
|
||||
@@ -162,6 +162,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 }}
|
||||
|
||||
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,8 +4,8 @@ project(monero-gui)
|
||||
message(STATUS "Initiating compile using CMake ${CMAKE_VERSION}")
|
||||
|
||||
set(VERSION_MAJOR "18")
|
||||
set(VERSION_MINOR "1")
|
||||
set(VERSION_REVISION "1")
|
||||
set(VERSION_MINOR "2")
|
||||
set(VERSION_REVISION "0")
|
||||
set(VERSION "0.${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_REVISION}")
|
||||
|
||||
option(STATIC "Link libraries statically, requires static Qt")
|
||||
|
||||
@@ -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.2.13
|
||||
ARG ZLIB_HASH=b3a24de97a8fdbc835b9833169501030b8977031bcb54b3b3ac13740f846ab30
|
||||
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 \
|
||||
@@ -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.8-lts-lgpl
|
||||
|
||||
ENV CFLAGS="-fPIC"
|
||||
ENV CPPFLAGS="-fPIC"
|
||||
@@ -242,9 +242,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.8-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 {
|
||||
|
||||
14
README.md
@@ -108,7 +108,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.2.0`) to build the release binaries.
|
||||
3. Prepare build environment
|
||||
```
|
||||
cd monero-gui
|
||||
@@ -131,7 +131,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.2.0`) to build the release binaries.
|
||||
3. Prepare build environment
|
||||
```
|
||||
cd monero-gui
|
||||
@@ -221,15 +221,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 +240,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`
|
||||
|
||||
@@ -319,7 +319,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
|
||||
```
|
||||
|
||||
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.
|
||||
|
||||
@@ -42,7 +42,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
|
||||
@@ -69,24 +69,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
|
||||
libicudtd72.dll
|
||||
libicuind72.dll
|
||||
libicuiod72.dll
|
||||
libicutud72.dll
|
||||
libicuucd72.dll
|
||||
)
|
||||
else() # assume release
|
||||
list(APPEND WIN_DEPLOY_DLLS
|
||||
libicudt71.dll
|
||||
libicuin71.dll
|
||||
libicuio71.dll
|
||||
libicutu71.dll
|
||||
libicuuc71.dll
|
||||
libicudt72.dll
|
||||
libicuin72.dll
|
||||
libicuio72.dll
|
||||
libicutu72.dll
|
||||
libicuuc72.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/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 |
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(){
|
||||
|
||||
36
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;
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ ColumnLayout {
|
||||
spacing: 0
|
||||
property int panelHeight: 900
|
||||
property alias miningView: stateView.miningView
|
||||
property alias signView: stateView.signView
|
||||
property alias state: stateView.state
|
||||
|
||||
MoneroComponents.Navbar {
|
||||
@@ -52,6 +53,7 @@ ColumnLayout {
|
||||
active: state == "Mining"
|
||||
text: qsTr("Mining") + translationManager.emptyString
|
||||
onSelected: state = "Mining"
|
||||
visible: !isAndroid
|
||||
}
|
||||
MoneroComponents.NavbarItem {
|
||||
active: state == "Prove"
|
||||
@@ -81,7 +83,7 @@ ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: panelHeight
|
||||
color: "transparent"
|
||||
state: "Mining"
|
||||
state: isAndroid ? "Prove" : "Mining"
|
||||
|
||||
onCurrentViewChanged: {
|
||||
if (previousView) {
|
||||
@@ -120,7 +122,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 +148,9 @@ ColumnLayout {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function clearFields() {
|
||||
signView.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()
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
31
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>
|
||||
@@ -268,5 +283,17 @@
|
||||
<file>images/ledgerNanoX.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
|
||||
@@ -130,8 +130,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 +142,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 +157,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 +175,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 +236,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 +249,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 +267,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 +283,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 +342,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;
|
||||
}
|
||||
|
||||
@@ -1138,6 +1150,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)
|
||||
|
||||
@@ -461,6 +461,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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -49,17 +49,17 @@ void P2PoolManager::download() {
|
||||
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.0/p2pool-v3.0-windows-x64.zip";
|
||||
fileName = m_p2poolPath + "/p2pool-v3.0-windows-x64.zip";
|
||||
validHash = "102390ca812ede79f26f6a9b7c0ff7cf57b1c37523bee223e8ee10d6bc890e1b";
|
||||
#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.0/p2pool-v3.0-linux-x64.tar.gz";
|
||||
fileName = m_p2poolPath + "/p2pool-v3.0-linux-x64.tar.gz";
|
||||
validHash = "a7a0fdd19a0c413cbb2beb7f767cc3f706e26cd0cf3a08c104e312fd7ebd882e";
|
||||
#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.0/p2pool-v3.0-macos-x64.tar.gz";
|
||||
fileName = m_p2poolPath + "/p2pool-v3.0-macos-x64.tar.gz";
|
||||
validHash = "b648fef621891c16713bf42504677c1def205c4e63c7c51d91f850e57f4a97d6";
|
||||
#endif
|
||||
QFile file(fileName);
|
||||
epee::net_utils::http::http_simple_client http_client;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -282,7 +282,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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||