Compare commits

..
Author SHA1 Message Date
dsc 6745f49e8f Commit cd1cd5cb75
introduced an issue for CMAKE_BUILD_TYPE=Debug:

  libringct.so => not found
  libcryptonote_basic.so => not found
  libcheckpoints.so => not found
  libdevice.so => not found
  libringct_basic.so => not found
  libcommon.so => not found
  libwallet-crypto.so => not found
  libcncrypto.so => not found
  libeasylogging.so => not found
  librandomx.so => not found
  libversion.so => not found

We'll only set `CMAKE_SKIP_RPATH` when in release.
2020-10-12 17:39:26 +02:00
163 changed files with 1146 additions and 6607 deletions
+15 -11
View File
@@ -14,9 +14,11 @@ steps:
commands: commands:
- git config --global url."http://gitea:3000/tor/".insteadOf https://git.torproject.org/ - git config --global url."http://gitea:3000/tor/".insteadOf https://git.torproject.org/
- git config --global url."http://gitea:3000/".insteadOf https://github.com/ - git config --global url."http://gitea:3000/".insteadOf https://github.com/
- git submodule update --init --depth 50 contrib/tor
- git submodule update --init --depth 50 contrib/torsocks
- git submodule update --init --depth 120 monero - git submodule update --init --depth 120 monero
- git submodule update --init --depth 120 --recursive monero - git submodule update --init --depth 120 --recursive monero
- TOR="/usr/local/tor/bin/tor" XMRIG="/xmrig/xmrig" make -j6 release-static - make -j8 release-static
environment: environment:
OPENSSL_ROOT_DIR: /usr/local/openssl/ OPENSSL_ROOT_DIR: /usr/local/openssl/
CMAKEFLAGS_EXTRA: -DFETCH_DEPS=Off CMAKEFLAGS_EXTRA: -DFETCH_DEPS=Off
@@ -28,7 +30,7 @@ steps:
- name: files_linux_release - name: files_linux_release
path: /files path: /files
commands: commands:
- export FN="feather-`echo $DRONE_COMMIT_AFTER | cut -c 1-7`.zip" - export FN="feather-`git rev-parse --short HEAD`.zip"
- export TARGET_DIR="/files/$DRONE_SOURCE_BRANCH" - export TARGET_DIR="/files/$DRONE_SOURCE_BRANCH"
- mkdir -p "$TARGET_DIR" - mkdir -p "$TARGET_DIR"
- echo "writing to $TARGET_DIR/$FN" - echo "writing to $TARGET_DIR/$FN"
@@ -42,7 +44,7 @@ volumes:
path: /var/drone/ccache_linux_release/ path: /var/drone/ccache_linux_release/
- name: files_linux_release - name: files_linux_release
host: host:
path: /build/feather_files/files/linux-release/ path: /mnt/storage1/feather_files/files/linux-release/
--- ---
@@ -54,7 +56,7 @@ steps:
- name: build - name: build
image: feather:appimage image: feather:appimage
commands: commands:
- export FN="feather-`echo $DRONE_COMMIT_AFTER | cut -c 1-7`.zip" - export FN="feather-`git rev-parse --short HEAD`.zip"
- export BRANCH="$DRONE_SOURCE_BRANCH" - export BRANCH="$DRONE_SOURCE_BRANCH"
- bash ./contrib/build-appimage.sh - bash ./contrib/build-appimage.sh
- name: deploy - name: deploy
@@ -73,7 +75,7 @@ steps:
volumes: volumes:
- name: files_linux_appimage - name: files_linux_appimage
host: host:
path: /build/feather_files/files/linux-release-appimage/ path: /mnt/storage1/feather_files/files/linux-release-appimage/
--- ---
@@ -92,9 +94,11 @@ steps:
commands: commands:
- git config --global url."http://gitea:3000/tor/".insteadOf https://git.torproject.org/ - git config --global url."http://gitea:3000/tor/".insteadOf https://git.torproject.org/
- git config --global url."http://gitea:3000/".insteadOf https://github.com/ - git config --global url."http://gitea:3000/".insteadOf https://github.com/
- git submodule update --init --depth 50 contrib/tor
- git submodule update --init --depth 50 contrib/torsocks
- git submodule update --init --depth 120 monero - git submodule update --init --depth 120 monero
- git submodule update --init --depth 120 --recursive monero - git submodule update --init --depth 120 --recursive monero
- PATH="/mxe/usr/bin/:$PATH" TOR="/mxe/usr/x86_64-w64-mingw32.static/bin/tor.exe" XMRIG="/xmrig/xmrig.exe" make -j6 windows-mxe-release - PATH=/mxe/usr/bin/:$PATH make -j8 windows-mxe-release
environment: environment:
CMAKEFLAGS_EXTRA: -DFETCH_DEPS=Off CMAKEFLAGS_EXTRA: -DFETCH_DEPS=Off
- name: deploy - name: deploy
@@ -105,7 +109,7 @@ steps:
- name: files_win_release - name: files_win_release
path: /files path: /files
commands: commands:
- export FN="feather-`echo $DRONE_COMMIT_AFTER | cut -c 1-7`.zip" - export FN="feather-`git rev-parse --short HEAD`.zip"
- export TARGET_DIR="/files/$DRONE_SOURCE_BRANCH" - export TARGET_DIR="/files/$DRONE_SOURCE_BRANCH"
- mkdir -p "$TARGET_DIR" - mkdir -p "$TARGET_DIR"
- echo "writing to $TARGET_DIR/$FN" - echo "writing to $TARGET_DIR/$FN"
@@ -118,7 +122,7 @@ volumes:
path: /var/drone/ccache_win_release/ path: /var/drone/ccache_win_release/
- name: files_win_release - name: files_win_release
host: host:
path: /build/feather_files/files/windows-mxe-release/ path: /mnt/storage1/feather_files/files/windows-mxe-release/
--- ---
@@ -143,7 +147,7 @@ steps:
- name: files_mac_release - name: files_mac_release
path: /files path: /files
commands: commands:
- export FN="feather-`echo $DRONE_COMMIT_AFTER | cut -c 1-7`.zip" - export FN="feather-`git rev-parse --short HEAD`.zip"
- export TARGET_DIR="/files/$DRONE_SOURCE_BRANCH" - export TARGET_DIR="/files/$DRONE_SOURCE_BRANCH"
- mkdir -p "$TARGET_DIR" - mkdir -p "$TARGET_DIR"
- echo "writing to $TARGET_DIR/$FN" - echo "writing to $TARGET_DIR/$FN"
@@ -153,9 +157,9 @@ steps:
volumes: volumes:
- name: files_mac_release - name: files_mac_release
host: host:
path: /build/feather_files/files/mac-release/ path: /mnt/storage1/feather_files/files/mac-release/
--- ---
kind: signature kind: signature
hmac: 527d334190a8a824b3b781a05ae4c7d87f4fa2bc37ebc53a96db91f925fa4a52 hmac: 91e773a27d27f29ea62f5df500664b733df641b7c31202c8e5558174fd046fba
... ...
-3
View File
@@ -7,6 +7,3 @@
[submodule "contrib/tor"] [submodule "contrib/tor"]
path = contrib/tor path = contrib/tor
url = https://git.torproject.org/tor.git url = https://git.torproject.org/tor.git
[submodule "contrib/KDMacTouchBar"]
path = contrib/KDMacTouchBar
url = https://github.com/KDAB/KDMacTouchBar.git
+3 -3
View File
@@ -35,7 +35,7 @@ Note: You only need to build the base image once.
#### 3. Build #### 3. Build
```bash ```bash
docker run --rm -it -v /tmp/ccache:/root/.ccache -v /root/feather:/feather -w /feather feather:win /bin/bash -c 'PATH="/mxe/usr/bin/:$PATH" TOR="/mxe/usr/x86_64-w64-mingw32.static/bin/tor.exe" XMRIG="/xmrig/xmrig.exe" make windows-mxe-release -j8' docker run --rm -it -v /tmp/ccache:/root/.ccache -v /root/feather:/feather -w /feather feather:win /bin/bash -c 'PATH=/mxe/usr/bin/:$PATH make windows-mxe-release -j8'
``` ```
Replace `PATH_TO_FEATHER` with the absolute path to Feather locally. Replace `PATH_TO_FEATHER` with the absolute path to Feather locally.
@@ -68,7 +68,7 @@ Note: You only need to build the base image once.
#### 3. Build #### 3. Build
```bash ```bash
docker run --env OPENSSL_ROOT_DIR=/usr/local/openssl/ --rm -it -v /tmp/ccache:/root/.ccache -v PATH_TO_FEATHER:/feather -w /feather feather:linux sh -c 'TOR="/usr/local/tor/bin/tor" XMRIG="/xmrig/xmrig" make release-static -j8' docker run --env OPENSSL_ROOT_DIR=/usr/local/openssl/ --rm -it -v /tmp/ccache:/root/.ccache -v PATH_TO_FEATHER:/feather -w /feather feather:linux sh -c 'make release-static -j8'
``` ```
Replace `PATH_TO_FEATHER` with the absolute path to Feather locally. Replace `PATH_TO_FEATHER` with the absolute path to Feather locally.
@@ -98,4 +98,4 @@ Build Feather.
CMAKE_PREFIX_PATH=~/Qt5.15.1/5.15.1/clang_64 make mac-release CMAKE_PREFIX_PATH=~/Qt5.15.1/5.15.1/clang_64 make mac-release
``` ```
The resulting Mac OS application can be found `build/bin/feather.app` and will **not** have Tor embedded. The resulting Mac OS application can be found `build/bin/feather.app`.
+39 -48
View File
@@ -11,10 +11,7 @@ set(VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_REVISION}")
option(FETCH_DEPS "Download dependencies if they are not found" ON) option(FETCH_DEPS "Download dependencies if they are not found" ON)
option(XMRTO "Include Xmr.To module" ON) option(XMRTO "Include Xmr.To module" ON)
option(MORPHTOKEN "Include MorphToken module" ON) option(BUILD_TOR "Build Tor" OFF)
option(XMRIG "Path to XMRig binary to embed inside Feather" OFF)
option(TOR "Path to Tor binary to embed inside Feather" OFF)
option(TOR_VERSION "Optional git hash or tag of embedded Tor version" "tor-0.4.3.5")
option(STATIC "Link libraries statically, requires static Qt") option(STATIC "Link libraries statically, requires static Qt")
option(USE_DEVICE_TREZOR "Trezor support compilation" OFF) option(USE_DEVICE_TREZOR "Trezor support compilation" OFF)
option(DONATE_BEG "Prompt donation window every once in a while" ON) option(DONATE_BEG "Prompt donation window every once in a while" ON)
@@ -31,7 +28,7 @@ if(DEBUG)
set(CMAKE_VERBOSE_MAKEFILE ON) set(CMAKE_VERBOSE_MAKEFILE ON)
endif() endif()
set(MONERO_HEAD "2c41634c13994a8a112a1e3a61e5e0b456791a97") set(MONERO_HEAD "a1404e92cb439ba0f120e7c4a579ed0b9a0372a4")
set(BUILD_GUI_DEPS ON) set(BUILD_GUI_DEPS ON)
set(ARCH "x86-64") set(ARCH "x86-64")
set(BUILD_64 ON) set(BUILD_64 ON)
@@ -161,7 +158,6 @@ find_package(Boost 1.58 REQUIRED COMPONENTS
if(UNIX AND NOT APPLE) if(UNIX AND NOT APPLE)
if (NOT CMAKE_BUILD_TYPE STREQUAL "Debug") if (NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
# https://github.com/monero-project/monero-gui/issues/3142#issuecomment-705940446
set(CMAKE_SKIP_RPATH ON) set(CMAKE_SKIP_RPATH ON)
endif() endif()
@@ -177,48 +173,47 @@ if(UNIX AND NOT APPLE)
endif() endif()
endif() endif()
if("$ENV{DRONE}" STREQUAL "true") # Tor/torsocks
set(TOR_TAG "tor-0.4.3.5")
set(TOR_DIR "${CMAKE_SOURCE_DIR}/contrib/tor")
if(BUILD_TOR AND APPLE)
execute_process(COMMAND bash -c "touch ${CMAKE_SOURCE_DIR}/src/tor/libevent-2.1.7.dylib")
ENDIF()
if(UNIX AND NOT APPLE)
set(TOR_LIB "libtorsocks.so")
elseif(APPLE)
set(TOR_LIB "libtorsocks.dylib")
endif()
if("$ENV{DRONE}" STREQUAL "true" AND APPLE)
message(STATUS "We are inside a static compile with Drone CI") message(STATUS "We are inside a static compile with Drone CI")
endif() # @TODO: taken from Tor Browser official release for now
execute_process(COMMAND bash -c "cp ~/tor/libevent-2.1.7.dylib ${CMAKE_SOURCE_DIR}/src/tor/libevent-2.1.7.dylib")
# To build Feather with embedded (and static) Tor, pass CMake -DTOR=/path/to/tor execute_process(COMMAND bash -c "cp ~/tor/tor ${CMAKE_SOURCE_DIR}/src/tor/tor")
if(TOR) elseif("$ENV{DRONE}" STREQUAL "true" AND BUILD_TOR)
if(APPLE) message(STATUS "We are inside a static compile with Drone CI")
execute_process(COMMAND bash -c "touch ${CMAKE_CURRENT_SOURCE_DIR}/src/tor/libevent-2.1.7.dylib") if(MINGW)
execute_process(COMMAND bash -c "cp /mxe/usr/x86_64-w64-mingw32.static/bin/tor.exe ${CMAKE_SOURCE_DIR}/src/tor/tor.exe")
elseif(UNIX AND NOT APPLE)
execute_process(COMMAND bash -c "cp /usr/local/tor/bin/tor ${CMAKE_SOURCE_DIR}/src/tor/tor")
execute_process(COMMAND bash -c "cp /usr/local/torsocks/lib/torsocks/* ${CMAKE_SOURCE_DIR}/src/tor/")
endif() endif()
# on the buildbot Tor is baked into the image
# - linux: See `Dockerfile`
# - windows: https://github.com/mxe/mxe/blob/1024dc7d2db5eb7d5d3c64a2c12b5f592572f1ce/plugins/apps/tor.mk
# - macos: taken from Tor Browser official release
set(TOR_COPY_CMD "cp ${TOR} ${CMAKE_CURRENT_SOURCE_DIR}/src/assets/exec/tor")
message(STATUS "${TOR_COPY_CMD}")
execute_process(COMMAND bash -c "${TOR_COPY_CMD}" RESULT_VARIABLE ret)
if(ret EQUAL "1")
message(FATAL_ERROR "Tor copy failure: ${TOR_COPY_CMD}")
endif()
message(STATUS "Embedding Tor binary at ${TOR}")
else() else()
message(STATUS "Skipping Tor inclusion because -DTOR=Off") if(BUILD_TOR)
endif() if(UNIX OR APPLE)
execute_process(COMMAND bash -c "ls -al src/tor/${TOR_LIB} 2>/dev/null" WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} OUTPUT_VARIABLE TOR_FOUND OUTPUT_STRIP_TRAILING_WHITESPACE)
# To build Feather with embedded (and static) XMRig, pass CMake -DXMRIG=/path/to/xmrig if(TOR_FOUND)
if(XMRIG) message(STATUS "${TOR_LIB} found, skipping Tor build")
# on the buildbot XMRig is baked into the image else()
# - linux: See `Dockerfile` message(STATUS "${TOR_LIB} not found, building Tor")
# - windows: See `Dockerfile_windows` execute_process(COMMAND bash -c "bash build_tor.sh ${TOR_TAG} ${CMAKE_SOURCE_DIR} 'ON'" WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/contrib)
# - macos: manually downloaded an official release endif()
set(XMRIG_COPY_CMD "cp ${XMRIG} ${CMAKE_CURRENT_SOURCE_DIR}/src/assets/exec/xmrig") endif()
message(STATUS "${XMRIG_COPY_CMD}") else()
execute_process(COMMAND bash -c "${XMRIG_COPY_CMD}" RESULT_VARIABLE ret) message(STATUS "Skipping Tor build because -DBUILD_TOR=OFF")
if(ret EQUAL "1")
message(FATAL_ERROR "XMRig copy failure: ${XMRIG_COPY_CMD}")
endif() endif()
message(STATUS "Embedding XMRig binary at ${XMRIG}")
else()
message(STATUS "Skipping XMRig inclusion because -DXMRIG=Off")
endif() endif()
if(MINGW) if(MINGW)
@@ -366,8 +361,4 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11 ${C_SECURITY_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 ${CXX_SECURITY_FLAGS}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 ${CXX_SECURITY_FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LD_SECURITY_FLAGS} ${STATIC_FLAGS}") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LD_SECURITY_FLAGS} ${STATIC_FLAGS}")
if(APPLE)
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/contrib/KDMacTouchBar")
endif()
add_subdirectory(src) add_subdirectory(src)
+1 -7
View File
@@ -191,7 +191,7 @@ RUN cd /qt-everywhere-src-5.15.0 && \
-skip qtscript -skip qtscxml -skip qtsensors -skip qtserialbus -skip qtserialport -skip qtspeech -skip qttools \ -skip qtscript -skip qtscxml -skip qtsensors -skip qtserialbus -skip qtserialport -skip qtspeech -skip qttools \
-skip qtvirtualkeyboard -skip qtwayland -skip qtwebchannel -skip qtwebengine -skip qtwebview \ -skip qtvirtualkeyboard -skip qtwayland -skip qtwebchannel -skip qtwebengine -skip qtwebview \
-skip qtwinextras -skip qtx11extras -skip gamepad -skip serialbus -skip location -skip webengine \ -skip qtwinextras -skip qtx11extras -skip gamepad -skip serialbus -skip location -skip webengine \
-skip qtdeclarative \ -skip qtdeclarative -skip qtmultimedia \
-no-feature-cups -no-feature-ftp -no-feature-pdf -no-feature-animation \ -no-feature-cups -no-feature-ftp -no-feature-pdf -no-feature-animation \
-nomake examples -nomake tests -nomake tools -nomake examples -nomake tests -nomake tools
@@ -305,9 +305,3 @@ RUN git clone https://git.wownero.com/feather/monero-seed.git && \
cmake -DCMAKE_BUILD_TYPE=Release -Bbuild && \ cmake -DCMAKE_BUILD_TYPE=Release -Bbuild && \
make -Cbuild -j$THREADS && \ make -Cbuild -j$THREADS && \
make -Cbuild install make -Cbuild install
RUN apt install -y curl && \
curl -LO "https://github.com/xmrig/xmrig/releases/download/v6.3.5/xmrig-6.3.5-linux-static-x64.tar.gz" && \
echo "24d4f07cf5850f00ab513b228f95769a5a5ed68d35808d98f9959b58d97985a0 xmrig-6.3.5-linux-static-x64.tar.gz" > hashsum.txt && \
sha256sum -c hashsum.txt && \
tar xvf xmrig-6.3.5-linux-static-x64.tar.gz --one-top-level=/xmrig --strip 1
+1 -8
View File
@@ -50,7 +50,7 @@ RUN apt install -y \
RUN git clone -b feather-patch --depth 1 https://git.wownero.com/feather/mxe.git && \ RUN git clone -b feather-patch --depth 1 https://git.wownero.com/feather/mxe.git && \
cd mxe && \ cd mxe && \
make -j$THREADS MXE_TARGETS='x86_64-w64-mingw32.static' gcc libqrencode pkgconf libgpg_error libgcrypt cmake libsodium lzma readline libzmq boost qtbase qtsvg qtwebsockets qtimageformats qtmultimedia make -j$THREADS MXE_TARGETS='x86_64-w64-mingw32.static' gcc libqrencode pkgconf libgpg_error libgcrypt cmake libsodium lzma readline libzmq boost qtbase qtsvg qtwebsockets qtimageformats
# plugins # plugins
RUN cd mxe && make -j$THREADS MXE_PLUGIN_DIRS='/mxe/plugins/apps/' MXE_TARGETS='x86_64-w64-mingw32.static' tor RUN cd mxe && make -j$THREADS MXE_PLUGIN_DIRS='/mxe/plugins/apps/' MXE_TARGETS='x86_64-w64-mingw32.static' tor
@@ -72,10 +72,3 @@ RUN git clone https://git.wownero.com/feather/monero-seed.git && \
cmake -DCMAKE_BUILD_TYPE=Release -Bbuild && \ cmake -DCMAKE_BUILD_TYPE=Release -Bbuild && \
make -Cbuild -j$THREADS && \ make -Cbuild -j$THREADS && \
make -Cbuild install make -Cbuild install
RUN apt install -y curl && \
curl -LO "https://github.com/xmrig/xmrig/releases/download/v6.3.5/xmrig-6.3.5-gcc-win64.zip" && \
echo "e45915ada7e6e30f6ab40abf33831056449d5914307d7706bb0ad439b6d64c12 xmrig-6.3.5-gcc-win64.zip" > hashsum.txt && \
sha256sum -c hashsum.txt && \
unzip -q xmrig-6.3.5-gcc-win64.zip -d /xmrig && \
mv /xmrig/xmrig-6.3.5/* /xmrig/
+1 -3
View File
@@ -42,9 +42,7 @@ via the `CMAKE_PREFIX_PATH` definition. For me this is:
There are some Monero/Feather related options/definitions that you may pass: There are some Monero/Feather related options/definitions that you may pass:
- `-DXMRTO=OFF` - disable Xmr.To feature - `-DXMRTO=OFF` - disable Xmr.To feature
- `-DMORPHTOKEN=OFF` - diable MorphToken feature - `-DBUILD_TOR=OFF` - disable embedded Tor
- `-DTOR=/path/to/tor` - Embed a Tor executable inside Feather
- `-DXMRIG=/path/to/xmrig` - Embed a XMRig executable inside Feather
- `-DDONATE_BEG=OFF` - disable the dreaded donate requests - `-DDONATE_BEG=OFF` - disable the dreaded donate requests
And: And:
+4 -11
View File
@@ -31,9 +31,6 @@ CMAKEFLAGS = \
-DBUILD_64=On \ -DBUILD_64=On \
-DBUILD_TESTS=Off \ -DBUILD_TESTS=Off \
-DXMRTO=ON \ -DXMRTO=ON \
-DMORPHTOKEN=ON \
-DXMRIG=Off \
-DTOR=Off \
-DCMAKE_CXX_STANDARD=11 \ -DCMAKE_CXX_STANDARD=11 \
-DCMAKE_VERBOSE_MAKEFILE=On \ -DCMAKE_VERBOSE_MAKEFILE=On \
-DINSTALL_VENDORED_LIBUNBOUND=Off \ -DINSTALL_VENDORED_LIBUNBOUND=Off \
@@ -43,33 +40,29 @@ CMAKEFLAGS = \
$(CMAKEFLAGS_EXTRA) $(CMAKEFLAGS_EXTRA)
release-static: CMAKEFLAGS += -DBUILD_TAG="linux-x64" release-static: CMAKEFLAGS += -DBUILD_TAG="linux-x64"
release-static: CMAKEFLAGS += -DTOR=$(or ${TOR},OFF) release-static: CMAKEFLAGS += -DBUILD_TOR=On
release-static: CMAKEFLAGS += -DXMRIG=$(or ${XMRIG},OFF)
release-static: CMAKEFLAGS += -DCMAKE_BUILD_TYPE=Release release-static: CMAKEFLAGS += -DCMAKE_BUILD_TYPE=Release
release-static: release-static:
cmake -Bbuild $(CMAKEFLAGS) cmake -Bbuild $(CMAKEFLAGS)
$(MAKE) -Cbuild $(MAKE) -Cbuild
windows-mxe-release: CMAKEFLAGS += -DBUILD_TAG="win-x64" windows-mxe-release: CMAKEFLAGS += -DBUILD_TAG="win-x64"
windows-mxe-release: CMAKEFLAGS += -DTOR=$(or ${TOR},OFF) windows-mxe-release: CMAKEFLAGS += -DBUILD_TOR=On
windows-mxe-release: CMAKEFLAGS += -DXMRIG=$(or ${XMRIG},OFF)
windows-mxe-release: CMAKEFLAGS += -DCMAKE_BUILD_TYPE=Release windows-mxe-release: CMAKEFLAGS += -DCMAKE_BUILD_TYPE=Release
windows-mxe-release: windows-mxe-release:
cmake -Bbuild $(CMAKEFLAGS) cmake -Bbuild $(CMAKEFLAGS)
$(MAKE) -Cbuild $(MAKE) -Cbuild
windows-mxe-debug: CMAKEFLAGS += -DBUILD_TAG="win-x64" windows-mxe-debug: CMAKEFLAGS += -DBUILD_TAG="win-x64"
windows-mxe-debug: CMAKEFLAGS += -DTOR=$(or ${TOR},OFF) windows-mxe-debug: CMAKEFLAGS += -DBUILD_TOR=Off
windows-mxe-debug: CMAKEFLAGS += -DXMRIG=$(or ${XMRIG},OFF)
windows-mxe-debug: CMAKEFLAGS += -DCMAKE_BUILD_TYPE=Debug windows-mxe-debug: CMAKEFLAGS += -DCMAKE_BUILD_TYPE=Debug
windows-mxe-debug: windows-mxe-debug:
cmake -Bbuild $(CMAKEFLAGS) cmake -Bbuild $(CMAKEFLAGS)
$(MAKE) -Cbuild $(MAKE) -Cbuild
mac-release: CMAKEFLAGS += -DSTATIC=Off mac-release: CMAKEFLAGS += -DSTATIC=Off
mac-release: CMAKEFLAGS += -DTOR=$(or ${TOR},OFF)
mac-release: CMAKEFLAGS += -DXMRIG=$(or ${XMRIG},OFF)
mac-release: CMAKEFLAGS += -DBUILD_TAG="mac-x64" mac-release: CMAKEFLAGS += -DBUILD_TAG="mac-x64"
mac-release: CMAKEFLAGS += -DBUILD_TOR=Off
mac-release: CMAKEFLAGS += -DCMAKE_BUILD_TYPE=Release mac-release: CMAKEFLAGS += -DCMAKE_BUILD_TYPE=Release
mac-release: mac-release:
cmake -Bbuild $(CMAKEFLAGS) cmake -Bbuild $(CMAKEFLAGS)
+11 -12
View File
@@ -1,35 +1,34 @@
# Maintainer: wowario <wowario[at]protonmail[dot]com> # Maintainer: wowario <wowario[at]protonmail[dot]com>
# Contributor: wowario <wowario[at]protonmail[dot]com> # Contributor: wowario <wowario[at]protonmail[dot]com>
pkgname='monero-feather-git' pkgbase=('monero-feather-git')
pkgver=0.1.0.925ef5683 pkgname=('monero-feather-git')
pkgver=v0.1.0.0.cd1cd5cb75
pkgrel=1 pkgrel=1
pkgdesc='a free Monero desktop wallet' pkgdesc="a free Monero desktop wallet"
license=('BSD') license=('BSD')
arch=('x86_64') arch=('x86_64')
url="https://featherwallet.org" url="https://featherwallet.org"
depends=('boost-libs' 'libunwind' 'openssl' 'readline' 'pcsclite' 'hidapi' 'protobuf' 'miniupnpc' 'libgcrypt' 'qrencode' 'libsodium' 'libpgm' 'expat' 'qt5-base' 'qt5-websockets' 'tor') depends=('boost-libs' 'libunwind' 'openssl' 'readline' 'zeromq' 'pcsclite' 'hidapi' 'protobuf' 'miniupnpc'
'libgcrypt' 'qrencode' 'ccache' 'libsodium' 'libpgm' 'expat' 'base-devel' 'qt5-base')
makedepends=('git' 'cmake' 'boost') makedepends=('git' 'cmake' 'boost')
provides=('monero-feather-git')
source=("${pkgname}"::"git+https://git.wownero.com/feather/feather") source=("${pkgname}"::"git+https://git.wownero.com/feather/feather")
sha256sums=('SKIP') sha256sums=('SKIP')
pkgver() { pkgver() {
cd "${srcdir}/${pkgname}" cd "$srcdir/$pkgname"
printf "%s.%s" "$(git describe --tags --abbrev=0)" "$(git rev-parse --short=9 HEAD)" git describe --long --tags | sed 's/\([^-]*-\)g/r\1/;s/-/./g'
} }
build() { build() {
cd "${srcdir}/${pkgname}" cd "${srcdir}/${pkgname}"
git submodule update --init --recursive mkdir build && cd build && cmake .. && make release-static -j2
mkdir -p build
cd build
cmake ..
make
} }
package_monero-feather-git() { package_feather-git() {
install -Dm644 "${srcdir}/${pkgname}/LICENSE" "${pkgdir}/usr/share/licenses/${pkgname}/LICENSE" install -Dm644 "${srcdir}/${pkgname}/LICENSE" "${pkgdir}/usr/share/licenses/${pkgname}/LICENSE"
install -Dm755 "${srcdir}/${pkgname}/build/bin/feather" "${pkgdir}/usr/bin/feather" install -Dm755 "${srcdir}/${pkgname}/build/bin/feather" "${pkgdir}/usr/bin/feather"
} }
+1 -1
View File
@@ -2,7 +2,7 @@
[![Build Status](https://build.featherwallet.org/api/badges/feather/feather/status.svg)](https://build.featherwallet.org/feather/feather) [![Build Status](https://build.featherwallet.org/api/badges/feather/feather/status.svg)](https://build.featherwallet.org/feather/feather)
Feather is a free, open-source Monero client Linux with ports for Mac OS and Windows written in C++ with the Qt framework. It is created and maintained by [dsc](dsc@xmr.pm) and [tobtoht](thotbot@protonmail.com). Feather is a free, open-source Monero client Linux with ports for Mac OS and Windows written in C++ with the Qt framework. It is created and maintained by [dsc](dsc@xmr.pm) and [tobtoht](thotbot@protonmail.com).
## Development resources ## Development resources
* Web: [featherwallet.org](https://featherwallet.org) * Web: [featherwallet.org](https://featherwallet.org)
+1 -1
Submodule monero updated: 2c41634c13...a1404e92cb
+13 -32
View File
@@ -42,16 +42,14 @@ file(GLOB SOURCE_FILES
"dialog/*.cpp" "dialog/*.cpp"
) )
if(TOR) if((APPLE AND BUILD_TOR) OR (APPLE AND "$ENV{DRONE}" STREQUAL "true"))
if(APPLE) set(ASSETS_OS "assets_macos_tor.qrc")
set(ASSETS_TOR "assets_tor_macos.qrc") elseif(UNIX AND NOT APPLE AND BUILD_TOR)
else() set(ASSETS_OS "assets_linux_tor.qrc")
set(ASSETS_TOR "assets_tor.qrc") elseif(MINGW AND BUILD_TOR)
endif() set(ASSETS_OS "assets_windows_tor.qrc")
endif() else()
message(STATUS "Building without embedded Tor")
if(XMRIG)
set(ASSETS_XMRIG "assets_mining.qrc")
endif() endif()
set(EXECUTABLE_FLAG) set(EXECUTABLE_FLAG)
@@ -76,8 +74,7 @@ endif()
add_executable(feather ${EXECUTABLE_FLAG} main.cpp add_executable(feather ${EXECUTABLE_FLAG} main.cpp
${SOURCE_FILES} ${SOURCE_FILES}
${RESOURCES} ${RESOURCES}
${ASSETS_TOR} ${ASSETS_OS}
${ASSETS_XMRIG}
) )
# mac os bundle # mac os bundle
@@ -125,22 +122,14 @@ if(DONATE_BEG)
target_compile_definitions(feather PRIVATE DONATE_BEG=1) target_compile_definitions(feather PRIVATE DONATE_BEG=1)
endif() endif()
if(BUILD_TOR)
target_compile_definitions(feather PRIVATE BUILD_TOR=1)
endif()
if(XMRTO) if(XMRTO)
target_compile_definitions(feather PRIVATE XMRTO=1) target_compile_definitions(feather PRIVATE XMRTO=1)
endif() endif()
if(MORPHTOKEN)
target_compile_definitions(feather PRIVATE HAS_MORPHTOKEN=1)
endif()
if(TOR)
target_compile_definitions(feather PRIVATE HAS_TOR=1)
endif()
if(XMRIG)
target_compile_definitions(feather PRIVATE HAS_XMRIG=1)
endif()
if(HAVE_SYS_PRCTL_H) if(HAVE_SYS_PRCTL_H)
target_compile_definitions(feather PRIVATE HAVE_SYS_PRCTL_H=1) target_compile_definitions(feather PRIVATE HAVE_SYS_PRCTL_H=1)
endif() endif()
@@ -205,14 +194,6 @@ target_link_libraries(feather
${QRENCODE_LIBRARY} ${QRENCODE_LIBRARY}
) )
if(APPLE)
target_link_libraries(feather
KDMacTouchBar
)
target_include_directories(feather
PUBLIC ../contrib/KDMacTouchBar)
endif()
if(NOT APPLE) if(NOT APPLE)
target_link_libraries(feather target_link_libraries(feather
Qt5::QSvgIconPlugin Qt5::QSvgIconPlugin
-226
View File
@@ -1,226 +0,0 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2020, The Monero Project.
#include "MorphTokenWidget.h"
#include "ui_MorphTokenWidget.h"
#include "mainwindow.h"
#include "qrcode/QrCode.h"
#include "dialog/qrcodedialog.h"
#include <QMessageBox>
MorphTokenWidget::MorphTokenWidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::MorphTokenWidget)
{
ui->setupUi(this);
m_ctx = MainWindow::getContext();
m_network = new UtilsNetworking(this->m_ctx->network);
m_api = new MorphTokenApi(this, m_network);
connect(ui->btnCreateTrade, &QPushButton::clicked, this, &MorphTokenWidget::createTrade);
connect(ui->btn_lookupTrade, &QPushButton::clicked, this, &MorphTokenWidget::lookupTrade);
connect(ui->btn_getRates, &QPushButton::clicked, this, &MorphTokenWidget::getRates);
connect(m_api, &MorphTokenApi::ApiResponse, this, &MorphTokenWidget::onApiResponse);
connect(ui->combo_From, QOverload<int>::of(&QComboBox::currentIndexChanged), [this](int index){
this->displayRate();
ui->label_refundAddress->setText(QString("Refund address (%1):").arg(ui->combo_From->currentText()));
});
connect(ui->combo_To, QOverload<int>::of(&QComboBox::currentIndexChanged), [this](int index){
this->displayRate();
ui->label_destinationAddress->setText(QString("Destination address (%1):").arg(ui->combo_To->currentText()));
});
connect(ui->check_autorefresh, &QCheckBox::toggled, [this](bool toggled){
m_countdown = 30;
toggled ? m_countdownTimer.start(1000) : m_countdownTimer.stop();
ui->check_autorefresh->setText("Autorefresh");
});
connect(&m_countdownTimer, &QTimer::timeout, this, &MorphTokenWidget::onCountdown);
connect(ui->line_Id, &QLineEdit::textChanged, [this](const QString &text){
ui->btn_lookupTrade->setEnabled(!text.isEmpty());
ui->check_autorefresh->setEnabled(!text.isEmpty());
});
// Default to BTC -> XMR
ui->combo_From->setCurrentIndex(1);
ui->combo_To->setCurrentIndex(0);
ui->label_rate->setVisible(false);
m_ratesTimer.setSingleShot(true);
connect(&m_ratesTimer, &QTimer::timeout, [this]{
ui->label_rate->setVisible(false);
});
ui->qrCode->setVisible(false);
ui->label_depositAddress->setVisible(false);
connect(ui->qrCode, &ClickableLabel::clicked, this, &MorphTokenWidget::showQrCodeDialog);
ui->tabWidget->setTabVisible(2, false);
}
void MorphTokenWidget::createTrade() {
QString inputAsset = ui->combo_From->currentText();
QString outputAsset = ui->combo_To->currentText();
QString refundAddress = ui->line_refundAddress->text();
QString destinationAddress = ui->line_destinationAddress->text();
m_api->createTrade(inputAsset, outputAsset, refundAddress, destinationAddress);
}
void MorphTokenWidget::lookupTrade() {
QString morphId = ui->line_Id->text();
if (!morphId.isEmpty())
m_api->getTrade(morphId);
}
void MorphTokenWidget::getRates() {
m_api->getRates();
}
void MorphTokenWidget::onApiResponse(const MorphTokenApi::MorphTokenResponse &resp) {
if (!resp.ok) {
ui->check_autorefresh->setChecked(false);
QMessageBox::warning(this, "MorphToken error", QString("Request failed:\n\n%1").arg(resp.message));
return;
}
ui->debugInfo->setPlainText(QJsonDocument(resp.obj).toJson(QJsonDocument::Indented));
bool shouldShowQr = (resp.endpoint == MorphTokenApi::Endpoint::CREATE_TRADE || resp.endpoint == MorphTokenApi::Endpoint::GET_TRADE);
ui->qrCode->setVisible(shouldShowQr);
ui->label_depositAddress->setVisible(shouldShowQr);
if (resp.endpoint == MorphTokenApi::Endpoint::CREATE_TRADE || resp.endpoint == MorphTokenApi::Endpoint::GET_TRADE) {
ui->tabWidget->setCurrentIndex(1);
ui->line_Id->setText(resp.obj.value("id").toString());
auto obj = resp.obj;
auto input = obj["input"].toObject();
auto output = obj["output"].toArray()[0].toObject();
QString state = obj.value("state").toString();
QString statusText;
ui->trade->setTitle(QString("Trade (%1)").arg(state));
statusText += QString("Morph ID: %1\n\n").arg(obj["id"].toString());
if (state == "PENDING") {
statusText += QString("Waiting for a deposit, send %1 to %2\n").arg(input["asset"].toString(),
input["deposit_address"].toString());
statusText += QString("Rate: 1 %1 -> %2 %3\n\n").arg(input["asset"].toString(),
output["seen_rate"].toString(),
output["asset"].toString());
statusText += "Limits:\n";
statusText += QString(" Minimum amount accepted: %1 %2\n").arg(formatAmount(input["asset"].toString(), input["limits"].toObject()["min"].toDouble()),
input["asset"].toString());
statusText += QString(" Maximum amount accepted: %1 %2\n").arg(formatAmount(input["asset"].toString(), input["limits"].toObject()["max"].toDouble()),
input["asset"].toString());
statusText += QString("\nSend a single deposit. If the amount is outside the limits, a refund will happen.");
m_depositAddress = input["deposit_address"].toString();
const QrCode qrc(m_depositAddress, QrCode::Version::AUTO, QrCode::ErrorCorrectionLevel::MEDIUM);
int width = ui->qrCode->width();
if (qrc.isValid()) {
ui->qrCode->setPixmap(qrc.toPixmap(1).scaled(width, width, Qt::KeepAspectRatio));
}
} else if (state == "PROCESSING" || state == "TRADING" || state == "CONFIRMING") {
if (state == "CONFIRMING") {
statusText += QString("Waiting for confirmations\n");
} else if (state == "TRADING") {
statusText += QString("Your transaction has been received and is confirmed. MorphToken is now executing your trade.\n"
"Usually this step takes no longer than a minute, "
"but in rare cases it can take a couple hours.\n"
"Wait a bit before contacting support.\n");
}
statusText += QString("Converting %1 to %2\n").arg(input["asset"].toString(), output["asset"].toString());
statusText += QString("Sending to %1\n").arg(output["address"].toString());
statusText += QString("Stuck? Contact support at contact@morphtoken.com");
} else if (state == "COMPLETE") {
if (output["txid"].toString().isEmpty()) {
statusText += QString("MorphToken is sending your transaction.\n");
statusText += QString("MorphToken will send %1 %2 to %2").arg(this->formatAmount(output["asset"].toString(), output["converted_amount"].toDouble() - output["network_fee"].toObject()["fee"].toDouble()),
output["asset"].toString(),
output["address"].toString());
} else {
statusText += QString("Sent %1 %2 to %3\ntxid: {}").arg(this->formatAmount(output["asset"].toString(), output["converted_amount"].toDouble() - output["network_fee"].toObject()["fee"].toDouble()),
output["asset"].toString(),
output["address"].toString(),
output["txid"].toString());
}
} else if (state == "PROCESSING_REFUND" || state == "COMPLETE_WITH_REFUND") {
statusText += QString("MorphToken will refund %1 %2\nReason: %3\n").arg(obj["final_amount"].toString(),
obj["asset"].toString(),
obj["reason"].toString());
if (obj.contains("txid")) {
statusText += QString("txid: %1").arg(obj["txid"].toString());
}
} else if (state == "COMPLETE_WITHOUT_REFUND") {
statusText += "Deposit amount below network fee, too small to refund.";
}
ui->label_status->setText(statusText);
} else if (resp.endpoint == MorphTokenApi::Endpoint::GET_RATES) {
m_rates = resp.obj.value("data").toObject();
this->displayRate();
ui->label_rate->setVisible(true);
m_ratesTimer.start(120 * 1000);
}
if (resp.endpoint == MorphTokenApi::Endpoint::CREATE_TRADE) {
QMessageBox::information(this, "MorphToken", "Trade created!\n\nMake sure to save your Morph ID. You may need it in case something goes wrong.");
}
}
void MorphTokenWidget::onCountdown() {
if (m_countdown > 0) {
m_countdown -= 1;
} else {
this->lookupTrade();
m_countdown = 30;
}
ui->check_autorefresh->setText(QString("Autorefresh (%1)").arg(m_countdown));
}
void MorphTokenWidget::displayRate() {
QString inputAsset = ui->combo_From->currentText();
QString outputAsset = ui->combo_To->currentText();
QString outputRate = m_rates.value(inputAsset).toObject().value(outputAsset).toString("1");
QString rateStr = QString("1 %1 -> %2 %3").arg(inputAsset, outputRate, outputAsset);
ui->label_rate->setText(rateStr);
}
void MorphTokenWidget::showQrCodeDialog() {
QrCode qr(m_depositAddress, QrCode::Version::AUTO, QrCode::ErrorCorrectionLevel::HIGH);
auto *dialog = new QrCodeDialog(this, qr, "Deposit address");
dialog->exec();
dialog->deleteLater();
}
QString MorphTokenWidget::formatAmount(const QString &asset, double amount) {
double displayAmount;
double div;
if (asset == "ETH")
div = 1e18;
else if (asset == "XMR")
div = 1e12;
else
div = 1e8;
displayAmount = amount / div;
return QString::number(displayAmount, 'f', 8);
}
MorphTokenWidget::~MorphTokenWidget() {
delete ui;
}
-47
View File
@@ -1,47 +0,0 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2020, The Monero Project.
#ifndef FEATHER_MORPHTOKENWIDGET_H
#define FEATHER_MORPHTOKENWIDGET_H
#include <QWidget>
#include "appcontext.h"
#include "utils/MorphTokenApi.h"
namespace Ui {
class MorphTokenWidget;
}
class MorphTokenWidget : public QWidget
{
Q_OBJECT
public:
explicit MorphTokenWidget(QWidget *parent = nullptr);
~MorphTokenWidget() override;
private:
void createTrade();
void lookupTrade();
void getRates();
void onApiResponse(const MorphTokenApi::MorphTokenResponse &resp);
void onCountdown();
void displayRate();
void showQrCodeDialog();
QString formatAmount(const QString &asset, double amount);
Ui::MorphTokenWidget *ui;
AppContext *m_ctx;
MorphTokenApi *m_api;
UtilsNetworking *m_network;
QTimer m_countdownTimer;
int m_countdown = 30;
QJsonObject m_rates;
QTimer m_ratesTimer;
QString m_depositAddress;
};
#endif //FEATHER_MORPHTOKENWIDGET_H
-423
View File
@@ -1,423 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MorphTokenWidget</class>
<widget class="QWidget" name="MorphTokenWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1036</width>
<height>614</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>1</number>
</property>
<widget class="QWidget" name="tabCreateTrade">
<attribute name="title">
<string>Create trade</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>From:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="combo_From">
<item>
<property name="text">
<string>XMR</string>
</property>
</item>
<item>
<property name="text">
<string>BTC</string>
</property>
</item>
<item>
<property name="text">
<string>ETH</string>
</property>
</item>
<item>
<property name="text">
<string>BCH</string>
</property>
</item>
<item>
<property name="text">
<string>LTC</string>
</property>
</item>
<item>
<property name="text">
<string>DASH</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="QLabel" name="label_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>To:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="combo_To">
<item>
<property name="text">
<string>XMR</string>
</property>
</item>
<item>
<property name="text">
<string>BTC</string>
</property>
</item>
<item>
<property name="text">
<string>ETH</string>
</property>
</item>
<item>
<property name="text">
<string>BCH</string>
</property>
</item>
<item>
<property name="text">
<string>LTC</string>
</property>
</item>
<item>
<property name="text">
<string>DASH</string>
</property>
</item>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label_rate">
<property name="text">
<string>rate</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="label_refundAddress">
<property name="text">
<string>Refund address (XMR):</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="line_refundAddress"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_destinationAddress">
<property name="text">
<string>Destination address (XMR):</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="line_destinationAddress"/>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="label_4">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Powered by MorphToken.com</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="btn_getRates">
<property name="text">
<string>Get Rates</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnCreateTrade">
<property name="text">
<string>Create Trade</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QWidget" name="tabLookupTrade">
<attribute name="title">
<string>Lookup trade</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>Morph ID or MorphToken deposit address:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="line_Id"/>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QCheckBox" name="check_autorefresh">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Autorefresh</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="btn_lookupTrade">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Lookup trade</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="Line" name="line_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QGroupBox" name="trade">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Trade</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QLabel" name="label_status">
<property name="text">
<string>No trade loaded.</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="ClickableLabel" name="qrCode">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>qrcode</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_depositAddress">
<property name="text">
<string>Deposit address</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tabDebug">
<attribute name="title">
<string>Debug</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_6">
<item>
<widget class="QPlainTextEdit" name="debugInfo">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>ClickableLabel</class>
<extends>QLabel</extends>
<header>components.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
+49 -105
View File
@@ -9,14 +9,12 @@
#include <QDesktopWidget> #include <QDesktopWidget>
#include "appcontext.h" #include "appcontext.h"
#include "globals.h"
#include "utils/tails.h" #include "utils/tails.h"
#include "utils/whonix.h" #include "utils/whonix.h"
#include "utils/utils.h" #include "utils/utils.h"
#include "utils/prices.h" #include "utils/prices.h"
#include "utils/networktype.h" #include "utils/networktype.h"
#include "utils/wsclient.h" #include "utils/wsclient.h"
#include "utils/config.h"
// libwalletqt // libwalletqt
#include "libwalletqt/WalletManager.h" #include "libwalletqt/WalletManager.h"
@@ -30,6 +28,7 @@
#include "model/SubaddressModel.h" #include "model/SubaddressModel.h"
#include "utils/keysfiles.h" #include "utils/keysfiles.h"
#include "utils/networktype.h" #include "utils/networktype.h"
#include "utils/config.h"
Prices *AppContext::prices = nullptr; Prices *AppContext::prices = nullptr;
@@ -113,6 +112,7 @@ AppContext::AppContext(QCommandLineParser *cmdargs) {
this->nodes = new Nodes(this, this->networkClearnet); this->nodes = new Nodes(this, this->networkClearnet);
connect(this, &AppContext::nodeSourceChanged, this->nodes, &Nodes::onNodeSourceChanged); connect(this, &AppContext::nodeSourceChanged, this->nodes, &Nodes::onNodeSourceChanged);
connect(this, &AppContext::setCustomNodes, this->nodes, &Nodes::setCustomNodes); connect(this, &AppContext::setCustomNodes, this->nodes, &Nodes::setCustomNodes);
connect(this, &AppContext::walletClosing, this->nodes, &Nodes::onWalletClosing);
// Tor & socks proxy // Tor & socks proxy
this->ws = new WSClient(this, m_wsUrl); this->ws = new WSClient(this, m_wsUrl);
@@ -147,16 +147,10 @@ AppContext::AppContext(QCommandLineParser *cmdargs) {
AppContext::prices = new Prices(); AppContext::prices = new Prices();
// xmr.to // xmr.to
#ifdef XMRTO #if defined(XMRTO)
this->XMRTo = new XmrTo(this); this->XMRTo = new XmrTo(this);
#endif #endif
// XMRig
#ifdef HAS_XMRIG
this->XMRig = new XmRig(this->configDirectory, this);
this->XMRig->prepare();
#endif
this->walletManager = WalletManager::instance(); this->walletManager = WalletManager::instance();
QString logPath = QString("%1/daemon.log").arg(configDirectory); QString logPath = QString("%1/daemon.log").arg(configDirectory);
Monero::Utils::onStartup(); Monero::Utils::onStartup();
@@ -179,7 +173,7 @@ void AppContext::initTor() {
this->tor = new Tor(this, this); this->tor = new Tor(this, this);
this->tor->start(); this->tor->start();
if (!(isWhonix)) { if (!(isTails || isWhonix)) {
auto networkProxy = new QNetworkProxy(QNetworkProxy::Socks5Proxy, Tor::torHost, Tor::torPort); auto networkProxy = new QNetworkProxy(QNetworkProxy::Socks5Proxy, Tor::torHost, Tor::torPort);
this->network->setProxy(*networkProxy); this->network->setProxy(*networkProxy);
if (m_wsUrl.host().endsWith(".onion")) if (m_wsUrl.host().endsWith(".onion"))
@@ -194,7 +188,7 @@ void AppContext::initWS() {
void AppContext::onCancelTransaction(PendingTransaction *tx, const QString &address) { void AppContext::onCancelTransaction(PendingTransaction *tx, const QString &address) {
// tx cancelled by user // tx cancelled by user
double amount = tx->amount() / globals::cdiv; double amount = tx->amount() / AppContext::cdiv;
emit createTransactionCancelled(address, amount); emit createTransactionCancelled(address, amount);
this->currentWallet->disposeTransaction(tx); this->currentWallet->disposeTransaction(tx);
} }
@@ -233,8 +227,8 @@ void AppContext::onCreateTransaction(const QString &address, const double amount
return; return;
} }
auto balance = this->currentWallet->balance() / globals::cdiv; auto balance = this->currentWallet->balance() / AppContext::cdiv;
auto unlocked_balance = this->currentWallet->unlockedBalance() / globals::cdiv; auto unlocked_balance = this->currentWallet->unlockedBalance() / AppContext::cdiv;
if(!all && amount > unlocked_balance) { if(!all && amount > unlocked_balance) {
emit createTransactionError("Not enough money to spend"); emit createTransactionError("Not enough money to spend");
return; return;
@@ -243,7 +237,7 @@ void AppContext::onCreateTransaction(const QString &address, const double amount
return; return;
} }
auto amount_num = static_cast<quint64>(amount * globals::cdiv); auto amount_num = static_cast<quint64>(amount * AppContext::cdiv);
qDebug() << "creating tx"; qDebug() << "creating tx";
if(all || amount == balance) if(all || amount == balance)
this->currentWallet->createTransactionAllAsync(address, "", this->tx_mixin, this->tx_priority); this->currentWallet->createTransactionAllAsync(address, "", this->tx_mixin, this->tx_priority);
@@ -259,6 +253,7 @@ void AppContext::onCreateTransactionError(const QString &msg) {
} }
void AppContext::walletClose(bool emitClosedSignal) { void AppContext::walletClose(bool emitClosedSignal) {
this->nodes->stopTimer();
if(this->currentWallet == nullptr) return; if(this->currentWallet == nullptr) return;
emit walletClosing(); emit walletClosing();
//ctx->currentWallet->store(); @TODO: uncomment to store on wallet close //ctx->currentWallet->store(); @TODO: uncomment to store on wallet close
@@ -281,10 +276,6 @@ void AppContext::onOpenWallet(const QString &path, const QString &password){
return; return;
} }
if (password.isEmpty()) {
this->walletPassword = "";
}
config()->set(Config::firstRun, false); config()->set(Config::firstRun, false);
this->walletPath = path; this->walletPath = path;
@@ -319,14 +310,13 @@ void AppContext::onWalletOpened(Wallet *wallet) {
emit walletOpenedError(errMsg); emit walletOpenedError(errMsg);
} else { } else {
this->walletClose(false); this->walletClose(false);
emit walletOpenPasswordNeeded(!this->walletPassword.isEmpty(), wallet->path()); emit walletOpenPasswordNeeded(this->walletPassword.isEmpty());
} }
return; return;
} }
this->currentWallet = wallet; this->currentWallet = wallet;
this->walletPath = this->currentWallet->path() + ".keys"; this->walletPath = this->currentWallet->path() + ".keys";
this->walletViewOnly = this->currentWallet->viewOnly();
config()->set(Config::walletPath, this->walletPath); config()->set(Config::walletPath, this->walletPath);
connect(this->currentWallet, &Wallet::moneySpent, this, &AppContext::onMoneySpent); connect(this->currentWallet, &Wallet::moneySpent, this, &AppContext::onMoneySpent);
@@ -340,12 +330,9 @@ void AppContext::onWalletOpened(Wallet *wallet) {
connect(this->currentWallet, &Wallet::transactionCreated, this, &AppContext::onTransactionCreated); connect(this->currentWallet, &Wallet::transactionCreated, this, &AppContext::onTransactionCreated);
connect(this->currentWallet, &Wallet::connectionStatusChanged, this, &AppContext::onConnectionStatusChanged); connect(this->currentWallet, &Wallet::connectionStatusChanged, this, &AppContext::onConnectionStatusChanged);
emit walletOpened();
connect(this->currentWallet, &Wallet::connectionStatusChanged, [this]{
this->nodes->autoConnect();
});
this->nodes->connectToNode(); this->nodes->connectToNode();
emit walletOpened();
this->updateBalance(); this->updateBalance();
#ifdef DONATE_BEG #ifdef DONATE_BEG
@@ -354,18 +341,6 @@ void AppContext::onWalletOpened(Wallet *wallet) {
// force trigger preferredFiat signal for history model // force trigger preferredFiat signal for history model
this->onPreferredFiatCurrencyChanged(config()->get(Config::preferredFiatCurrency).toString()); this->onPreferredFiatCurrencyChanged(config()->get(Config::preferredFiatCurrency).toString());
this->setWindowTitle();
}
void AppContext::setWindowTitle(bool mining) {
QFileInfo fileInfo(this->walletPath);
auto title = QString("Feather - [%1]").arg(fileInfo.fileName());
if(this->walletViewOnly)
title += " [view-only]";
if(mining)
title += " [mining]";
emit setTitle(title);
} }
void AppContext::onWSMessage(const QJsonObject &msg) { void AppContext::onWSMessage(const QJsonObject &msg) {
@@ -405,11 +380,7 @@ void AppContext::onWSMessage(const QJsonObject &msg) {
else if(cmd == "nodes") { else if(cmd == "nodes") {
this->onWSNodes(msg.value("data").toArray()); this->onWSNodes(msg.value("data").toArray());
} }
#if defined(HAS_XMRIG)
else if(cmd == "xmrig") {
this->XMRigDownloads(msg.value("data").toObject());
}
#endif
else if(cmd == "crypto_rates") { else if(cmd == "crypto_rates") {
QJsonArray crypto_rates = msg.value("data").toArray(); QJsonArray crypto_rates = msg.value("data").toArray();
AppContext::prices->cryptoPricesReceived(crypto_rates); AppContext::prices->cryptoPricesReceived(crypto_rates);
@@ -463,8 +434,7 @@ void AppContext::onWSNodes(const QJsonArray &nodes) {
auto node = new FeatherNode( auto node = new FeatherNode(
obj.value("address").toString(), obj.value("address").toString(),
obj.value("height").toInt(), (unsigned int)obj.value("height").toInt(),
obj.value("target_height").toInt(),
obj.value("online").toBool()); obj.value("online").toBool());
QSharedPointer<FeatherNode> r = QSharedPointer<FeatherNode>(node); QSharedPointer<FeatherNode> r = QSharedPointer<FeatherNode>(node);
l.append(r); l.append(r);
@@ -524,17 +494,31 @@ void AppContext::onWSCCS(const QJsonArray &ccs_data) {
} }
void AppContext::createConfigDirectory(const QString &dir) { void AppContext::createConfigDirectory(const QString &dir) {
QString config_dir_tor = QString("%1%2").arg(dir).arg("tor"); if(!Utils::dirExists(dir)) {
QString config_dir_tordata = QString("%1%2").arg(dir).arg("tor/data"); qDebug() << QString("Creating directory: %1").arg(dir);
QString config_dir_xmrig = QString("%1%2").arg(dir).arg("xmrig"); if(!QDir().mkpath(dir))
throw std::runtime_error("Could not create directory " + dir.toStdString());
}
QStringList createDirs({dir, config_dir_tor, config_dir_tordata, config_dir_xmrig}); QString config_dir_tor = QString("%1%2").arg(dir).arg("tor");
for(const auto &d: createDirs) { if(!Utils::dirExists(config_dir_tor)) {
if(!Utils::dirExists(d)) { qDebug() << QString("Creating directory: %1").arg(config_dir_tor);
qDebug() << QString("Creating directory: %1").arg(d); if (!QDir().mkpath(config_dir_tor))
if (!QDir().mkpath(d)) throw std::runtime_error("Could not create directory " + config_dir_tor.toStdString());
throw std::runtime_error("Could not create directory " + d.toStdString()); }
}
QString config_dir_tordata = QString("%1%2").arg(dir).arg("tor/data");
if(!Utils::dirExists(config_dir_tordata)) {
qDebug() << QString("Creating directory: %1").arg(config_dir_tordata);
if (!QDir().mkpath(config_dir_tordata))
throw std::runtime_error("Could not create directory " + config_dir_tordata.toStdString());
}
QString config_dir_torsocks = QString("%1%2").arg(dir).arg("torsocks");
if(!Utils::dirExists(config_dir_torsocks)) {
qDebug() << QString("Creating directory: %1").arg(config_dir_torsocks);
if (!QDir().mkpath(config_dir_torsocks))
throw std::runtime_error("Could not create directory " + config_dir_torsocks.toStdString());
} }
} }
@@ -557,43 +541,6 @@ void AppContext::createWallet(FeatherSeed seed, const QString &path, const QStri
return; return;
} }
this->createWalletFinish(password);
}
void AppContext::createWalletViewOnly(const QString &path, const QString &password, const QString &address, const QString &viewkey, const QString &spendkey, quint64 restoreHeight) {
if(Utils::fileExists(path)) {
auto err = QString("Failed to write wallet to path: \"%1\"; file already exists.").arg(path);
qCritical() << err;
emit walletCreatedError(err);
return;
}
if(!this->walletManager->addressValid(address, this->networkType)) {
auto err = QString("Failed to create wallet. Invalid address provided.").arg(path);
qCritical() << err;
emit walletCreatedError(err);
return;
}
if(!this->walletManager->keyValid(viewkey, address, true, this->networkType)) {
auto err = QString("Failed to create wallet. Invalid viewkey provided.").arg(path);
qCritical() << err;
emit walletCreatedError(err);
return;
}
if(!spendkey.isEmpty() && !this->walletManager->keyValid(spendkey, address, false, this->networkType)) {
auto err = QString("Failed to create wallet. Invalid spendkey provided.").arg(path);
qCritical() << err;
emit walletCreatedError(err);
return;
}
this->currentWallet = this->walletManager->createWalletFromKeys(path, this->seedLanguage, this->networkType, address, viewkey, spendkey, restoreHeight);
this->createWalletFinish(password);
}
void AppContext::createWalletFinish(const QString &password) {
this->currentWallet->setPassword(password); this->currentWallet->setPassword(password);
this->currentWallet->store(); this->currentWallet->store();
this->walletPassword = password; this->walletPassword = password;
@@ -615,7 +562,7 @@ void AppContext::onSetRestoreHeight(unsigned int height){
} }
this->currentWallet->setWalletCreationHeight(height); this->currentWallet->setWalletCreationHeight(height);
this->currentWallet->setPassword(this->currentWallet->getPassword()); // trigger .keys write this->currentWallet->setPassword(this->walletPassword); // trigger .keys write
// nuke wallet cache // nuke wallet cache
const auto fn = this->currentWallet->path(); const auto fn = this->currentWallet->path();
@@ -667,9 +614,8 @@ void AppContext::onOpenAliasResolve(const QString &openAlias) {
} }
void AppContext::donateBeg() { void AppContext::donateBeg() {
if(this->currentWallet == nullptr) return; if(this->networkType != NetworkType::Type::MAINNET)
if(this->networkType != NetworkType::Type::MAINNET) return; return;
if(this->currentWallet->viewOnly()) return;
auto donationCounter = config()->get(Config::donateBeg).toInt(); auto donationCounter = config()->get(Config::donateBeg).toInt();
if(donationCounter == -1) if(donationCounter == -1)
@@ -697,19 +643,19 @@ AppContext::~AppContext() {
// ############################################## LIBWALLET QT ######################################################### // ############################################## LIBWALLET QT #########################################################
void AppContext::onMoneySpent(const QString &txId, quint64 amount) { void AppContext::onMoneySpent(const QString &txId, quint64 amount) {
auto amount_num = amount / globals::cdiv; auto amount_num = amount / AppContext::cdiv;
qDebug() << Q_FUNC_INFO << txId << " " << QString::number(amount_num); qDebug() << Q_FUNC_INFO << txId << " " << QString::number(amount_num);
} }
void AppContext::onMoneyReceived(const QString &txId, quint64 amount) { void AppContext::onMoneyReceived(const QString &txId, quint64 amount) {
// Incoming tx included in a block. // Incoming tx included in a block.
auto amount_num = amount / globals::cdiv; auto amount_num = amount / AppContext::cdiv;
qDebug() << Q_FUNC_INFO << txId << " " << QString::number(amount_num); qDebug() << Q_FUNC_INFO << txId << " " << QString::number(amount_num);
} }
void AppContext::onUnconfirmedMoneyReceived(const QString &txId, quint64 amount) { void AppContext::onUnconfirmedMoneyReceived(const QString &txId, quint64 amount) {
// Incoming transaction in pool // Incoming transaction in pool
auto amount_num = amount / globals::cdiv; auto amount_num = amount / AppContext::cdiv;
qDebug() << Q_FUNC_INFO << txId << " " << QString::number(amount_num); qDebug() << Q_FUNC_INFO << txId << " " << QString::number(amount_num);
if(this->currentWallet->synchronized()) { if(this->currentWallet->synchronized()) {
@@ -727,15 +673,13 @@ void AppContext::onWalletUpdate() {
this->storeWallet(); this->storeWallet();
} }
void AppContext::onWalletRefreshed(bool success) { void AppContext::onWalletRefreshed() {
if (!this->refreshed) { if (!this->refreshed) {
refreshModels(); refreshModels();
this->refreshed = true; this->refreshed = true;
this->storeWallet(); this->storeWallet();
} }
qDebug() << "Wallet refresh status: " << success;
this->currentWallet->refreshHeightAsync(); this->currentWallet->refreshHeightAsync();
} }
@@ -752,7 +696,7 @@ void AppContext::onWalletNewBlock(quint64 blockheight, quint64 targetHeight) {
void AppContext::onHeightRefreshed(quint64 walletHeight, quint64 daemonHeight, quint64 targetHeight) { void AppContext::onHeightRefreshed(quint64 walletHeight, quint64 daemonHeight, quint64 targetHeight) {
qDebug() << Q_FUNC_INFO << walletHeight << daemonHeight << targetHeight; qDebug() << Q_FUNC_INFO << walletHeight << daemonHeight << targetHeight;
if (this->currentWallet->connectionStatus() == Wallet::ConnectionStatus_Disconnected) if (!this->currentWallet->connected())
return; return;
if (daemonHeight < targetHeight) { if (daemonHeight < targetHeight) {
@@ -798,12 +742,12 @@ void AppContext::storeWallet() {
void AppContext::updateBalance() { void AppContext::updateBalance() {
if(!this->currentWallet) if(!this->currentWallet)
return; throw std::runtime_error("this should not happen, ever");
AppContext::balance = this->currentWallet->balance() / globals::cdiv; AppContext::balance = this->currentWallet->balance() / AppContext::cdiv;
auto balance_str = QString::number(balance, 'f'); auto balance_str = QString::number(balance, 'f');
double unlocked = this->currentWallet->unlockedBalance() / globals::cdiv; double unlocked = this->currentWallet->unlockedBalance() / AppContext::cdiv;
auto unlocked_str = QString::number(unlocked, 'f'); auto unlocked_str = QString::number(unlocked, 'f');
emit balanceUpdated(balance, unlocked, balance_str, unlocked_str); emit balanceUpdated(balance, unlocked, balance_str, unlocked_str);
+4 -12
View File
@@ -14,7 +14,6 @@
#include "utils/networking.h" #include "utils/networking.h"
#include "utils/tor.h" #include "utils/tor.h"
#include "utils/xmrto.h" #include "utils/xmrto.h"
#include "utils/xmrig.h"
#include "utils/wsclient.h" #include "utils/wsclient.h"
#include "utils/txfiathistory.h" #include "utils/txfiathistory.h"
#include "widgets/RedditPost.h" #include "widgets/RedditPost.h"
@@ -57,7 +56,6 @@ public:
QString walletPath; QString walletPath;
QString walletPassword = ""; QString walletPassword = "";
bool walletViewOnly = false;
NetworkType::Type networkType; NetworkType::Type networkType;
QString applicationPath; QString applicationPath;
@@ -69,7 +67,7 @@ public:
const unsigned int kdfRounds = 1; const unsigned int kdfRounds = 1;
PendingTransaction::Priority tx_priority = PendingTransaction::Priority::Priority_Low; PendingTransaction::Priority tx_priority = PendingTransaction::Priority::Priority_Low;
quint32 tx_mixin = static_cast<const quint32 &>(10); quint32 tx_mixin = static_cast<const quint32 &>(10);
QString seedLanguage = "English"; // 14 word `monero-seed` only has English static constexpr const double cdiv = 1e12;
QNetworkAccessManager *network; QNetworkAccessManager *network;
QNetworkAccessManager *networkClearnet; QNetworkAccessManager *networkClearnet;
@@ -78,7 +76,6 @@ public:
Tor *tor; Tor *tor;
WSClient *ws; WSClient *ws;
XmrTo *XMRTo; XmrTo *XMRTo;
XmRig *XMRig;
Nodes *nodes; Nodes *nodes;
static Prices *prices; static Prices *prices;
static WalletKeysFilesModel *wallets; static WalletKeysFilesModel *wallets;
@@ -92,8 +89,6 @@ public:
WalletManager *walletManager; WalletManager *walletManager;
Wallet *currentWallet = nullptr; Wallet *currentWallet = nullptr;
void createWallet(FeatherSeed seed, const QString &path, const QString &password); void createWallet(FeatherSeed seed, const QString &path, const QString &password);
void createWalletViewOnly(const QString &path, const QString &password, const QString &address, const QString &viewkey, const QString &spendkey, quint64 restoreHeight);
void createWalletFinish(const QString &password);
void syncStatusUpdated(quint64 height, quint64 target); void syncStatusUpdated(quint64 height, quint64 target);
void updateBalance(); void updateBalance();
void initTor(); void initTor();
@@ -103,7 +98,6 @@ public:
void walletClose(bool emitClosedSignal = true); void walletClose(bool emitClosedSignal = true);
void storeWallet(); void storeWallet();
void refreshModels(); void refreshModels();
void setWindowTitle(bool mining = false);
public slots: public slots:
void onOpenWallet(const QString& path, const QString &password); void onOpenWallet(const QString& path, const QString &password);
@@ -126,7 +120,7 @@ private slots:
void onMoneyReceived(const QString &txId, quint64 amount); void onMoneyReceived(const QString &txId, quint64 amount);
void onUnconfirmedMoneyReceived(const QString &txId, quint64 amount); void onUnconfirmedMoneyReceived(const QString &txId, quint64 amount);
void onWalletUpdate(); void onWalletUpdate();
void onWalletRefreshed(bool success); void onWalletRefreshed();
void onWalletOpened(Wallet *wallet); void onWalletOpened(Wallet *wallet);
void onWalletNewBlock(quint64 blockheight, quint64 targetHeight); void onWalletNewBlock(quint64 blockheight, quint64 targetHeight);
void onHeightRefreshed(quint64 walletHeight, quint64 daemonHeight, quint64 targetHeight); void onHeightRefreshed(quint64 walletHeight, quint64 daemonHeight, quint64 targetHeight);
@@ -146,7 +140,7 @@ signals:
void walletCreatedError(const QString &msg); void walletCreatedError(const QString &msg);
void walletCreated(Wallet *wallet); void walletCreated(Wallet *wallet);
void walletOpenedError(QString msg); void walletOpenedError(QString msg);
void walletOpenPasswordNeeded(bool invalidPassword, QString path); void walletOpenPasswordNeeded(bool invalidPassword);
void transactionCommitted(bool status, PendingTransaction *tx, const QStringList& txid); void transactionCommitted(bool status, PendingTransaction *tx, const QStringList& txid);
void createTransactionError(QString message); void createTransactionError(QString message);
void createTransactionCancelled(QString address, double amount); void createTransactionCancelled(QString address, double amount);
@@ -155,7 +149,6 @@ signals:
void nodesUpdated(QList<QSharedPointer<FeatherNode>> &nodes); void nodesUpdated(QList<QSharedPointer<FeatherNode>> &nodes);
void ccsUpdated(QList<QSharedPointer<CCSEntry>> &entries); void ccsUpdated(QList<QSharedPointer<CCSEntry>> &entries);
void nodeSourceChanged(NodeSource nodeSource); void nodeSourceChanged(NodeSource nodeSource);
void XMRigDownloads(const QJsonObject &data);
void setCustomNodes(QList<FeatherNode> nodes); void setCustomNodes(QList<FeatherNode> nodes);
void ccsEmpty(); void ccsEmpty();
void openAliasResolveError(const QString &msg); void openAliasResolveError(const QString &msg);
@@ -167,14 +160,13 @@ signals:
void initiateTransaction(); void initiateTransaction();
void endTransaction(); void endTransaction();
void walletClosing(); void walletClosing();
void setTitle(const QString &title); // set window title
private: private:
void sorry(); void sorry();
const unsigned int m_donationBoundary = 15; const unsigned int m_donationBoundary = 15;
UtilsNetworking *m_utilsNetworkingNodes; UtilsNetworking *m_utilsNetworkingNodes;
QTimer *m_storeTimer = new QTimer(this); QTimer *m_storeTimer = new QTimer(this);
QUrl m_wsUrl = QUrl(QStringLiteral("ws://7e6egbawekbkxzkv4244pqeqgoo4axko2imgjbedwnn6s5yb6b7oliqd.onion/ws")); QUrl m_wsUrl = QUrl(QStringLiteral("ws://dtg2clrd6iand4mwp2x6nhbqd3nqbxlbiw65f6vkwmmutxy2sijsnjyd.onion/ws"));
}; };
#endif //FEATHER_APPCONTEXT_H #endif //FEATHER_APPCONTEXT_H
-8
View File
@@ -23,7 +23,6 @@
<file>assets/images/coldcard.png</file> <file>assets/images/coldcard.png</file>
<file>assets/images/coldcard_unpaired.png</file> <file>assets/images/coldcard_unpaired.png</file>
<file>assets/images/confirmed.png</file> <file>assets/images/confirmed.png</file>
<file>assets/images/confirmed_icon.png</file>
<file>assets/images/confirmed.svg</file> <file>assets/images/confirmed.svg</file>
<file>assets/images/connect.svg</file> <file>assets/images/connect.svg</file>
<file>assets/images/copy.png</file> <file>assets/images/copy.png</file>
@@ -31,13 +30,10 @@
<file>assets/images/edit.png</file> <file>assets/images/edit.png</file>
<file>assets/images/exchange.png</file> <file>assets/images/exchange.png</file>
<file>assets/images/expired.png</file> <file>assets/images/expired.png</file>
<file>assets/images/expired_icon.png</file>
<file>assets/images/eye1.png</file> <file>assets/images/eye1.png</file>
<file>assets/images/eye_blind.png</file>
<file>assets/images/feather.png</file> <file>assets/images/feather.png</file>
<file>assets/images/file.png</file> <file>assets/images/file.png</file>
<file>assets/images/ghost.png</file> <file>assets/images/ghost.png</file>
<file>assets/images/ghost_icon.png</file>
<file>assets/images/history.png</file> <file>assets/images/history.png</file>
<file>assets/images/info.png</file> <file>assets/images/info.png</file>
<file>assets/images/key.png</file> <file>assets/images/key.png</file>
@@ -45,10 +41,8 @@
<file>assets/images/ledger_unpaired.png</file> <file>assets/images/ledger_unpaired.png</file>
<file>assets/images/lightning.png</file> <file>assets/images/lightning.png</file>
<file>assets/images/lock.png</file> <file>assets/images/lock.png</file>
<file>assets/images/lock_icon.png</file>
<file>assets/images/lock.svg</file> <file>assets/images/lock.svg</file>
<file>assets/images/microphone.png</file> <file>assets/images/microphone.png</file>
<file>assets/images/morphtoken.png</file>
<file>assets/images/network.png</file> <file>assets/images/network.png</file>
<file>assets/images/offline_tx.png</file> <file>assets/images/offline_tx.png</file>
<file>assets/images/person.svg</file> <file>assets/images/person.svg</file>
@@ -97,8 +91,6 @@
<file>assets/images/warning.png</file> <file>assets/images/warning.png</file>
<file>assets/images/xmrto_big.png</file> <file>assets/images/xmrto_big.png</file>
<file>assets/images/xmrto.png</file> <file>assets/images/xmrto.png</file>
<file>assets/images/xmrig.ico</file>
<file>assets/images/xmrig.svg</file>
<file>assets/images/zoom.png</file> <file>assets/images/zoom.png</file>
<file>assets/mnemonic_25_english.txt</file> <file>assets/mnemonic_25_english.txt</file>
<file>assets/restore_heights_monero_mainnet.txt</file> <file>assets/restore_heights_monero_mainnet.txt</file>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

-1
View File
@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 496.06 496.06"><title>XMRig</title><defs><style>.a{fill:none;}.b{clip-path:url(#a);}.c{fill:#ec671a;}.d{fill:#575756;}.e{fill:#fff;}</style><clipPath id="a" transform="translate(-106.3 -106.3)"><circle class="a" cx="354.33" cy="354.33" r="248.03"/></clipPath></defs><title>Xr_icon</title><g class="b"><rect class="c" width="496.06" height="496.06"/><polygon class="d" points="496.06 496.06 0 496.06 0 387.21 124.02 387.55 189.12 291.44 254.23 387.55 496.06 387.55 496.06 496.06"/><path class="e" d="M481.44,441.14c0-13.18,0-27,0-37.32,0-54.11,22.15-77.57,55.82-52.71-0.39.07,27.9-43.41,27.9-43.41-35.68-24.09-67.09-10.17-86.81,19.45V295.42H428.74V441.14H391.12l-61-91.46,89.91-134.87H351.85L296,298.52l-55.81-83.71H172l89.91,134.87-61,91.46H106.3v52.37l59.65,0.16-0.12.18H234l62-93,62,93H602.36V441.14H481.44Z" transform="translate(-106.3 -106.3)"/></g></svg>

Before

Width:  |  Height:  |  Size: 955 B

@@ -1,5 +1,5 @@
<!DOCTYPE RCC><RCC version="1.0"> <!DOCTYPE RCC><RCC version="1.0">
<qresource prefix="/"> <qresource prefix="/">
<file>assets/exec/tor</file> <file>tor/tor</file>
</qresource> </qresource>
</RCC> </RCC>
+6
View File
@@ -0,0 +1,6 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource prefix="/">
<file>tor/tor</file>
<file>tor/libevent-2.1.7.dylib</file>
</qresource>
</RCC>
-6
View File
@@ -1,6 +0,0 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource prefix="/">
<file>assets/exec/tor</file>
<file>assets/exec/libevent-2.1.7.dylib</file>
</qresource>
</RCC>
@@ -1,5 +1,5 @@
<!DOCTYPE RCC><RCC version="1.0"> <!DOCTYPE RCC><RCC version="1.0">
<qresource prefix="/"> <qresource prefix="/">
<file>assets/exec/xmrig</file> <file>tor/tor.exe</file>
</qresource> </qresource>
</RCC> </RCC>
+1 -1
View File
@@ -58,7 +58,7 @@ void CLI::onWalletOpenedError(const QString &err) {
return this->finishedError(err); return this->finishedError(err);
} }
void CLI::onWalletOpenPasswordRequired(bool invalidPassword, const QString &path) { void CLI::onWalletOpenPasswordRequired(bool invalidPassword) {
if(mode == CLIMode::CLIModeExportContacts || if(mode == CLIMode::CLIModeExportContacts ||
mode == CLIMode::CLIModeExportTxHistory) mode == CLIMode::CLIModeExportTxHistory)
return this->finishedError("invalid password"); return this->finishedError("invalid password");
+1 -1
View File
@@ -26,7 +26,7 @@ public slots:
//libwalletqt //libwalletqt
void onWalletOpened(); void onWalletOpened();
void onWalletOpenedError(const QString& err); void onWalletOpenedError(const QString& err);
void onWalletOpenPasswordRequired(bool invalidPassword, const QString &path); void onWalletOpenPasswordRequired(bool invalidPassword);
private: private:
AppContext *ctx; AppContext *ctx;
+10 -24
View File
@@ -7,7 +7,6 @@
#include "utils/utils.h" #include "utils/utils.h"
#include "dialog/outputinfodialog.h" #include "dialog/outputinfodialog.h"
#include "dialog/outputsweepdialog.h" #include "dialog/outputsweepdialog.h"
#include "mainwindow.h"
#include <QClipboard> #include <QClipboard>
#include <QDebug> #include <QDebug>
@@ -22,7 +21,6 @@ CoinsWidget::CoinsWidget(QWidget *parent)
, m_copyMenu(new QMenu("Copy",this)) , m_copyMenu(new QMenu("Copy",this))
{ {
ui->setupUi(this); ui->setupUi(this);
m_ctx = MainWindow::getContext();
// header context menu // header context menu
ui->coins->header()->setContextMenuPolicy(Qt::CustomContextMenu); ui->coins->header()->setContextMenuPolicy(Qt::CustomContextMenu);
@@ -42,14 +40,14 @@ CoinsWidget::CoinsWidget(QWidget *parent)
// context menu // context menu
ui->coins->setContextMenuPolicy(Qt::CustomContextMenu); ui->coins->setContextMenuPolicy(Qt::CustomContextMenu);
m_thawOutputAction = new QAction("Thaw output", this); m_thawOutputAction = new QAction("Thaw output");
m_freezeOutputAction = new QAction("Freeze output", this); m_freezeOutputAction = new QAction("Freeze output");
m_freezeAllSelectedAction = new QAction("Freeze selected", this); m_freezeAllSelectedAction = new QAction("Freeze selected");
m_thawAllSelectedAction = new QAction("Thaw selected", this); m_thawAllSelectedAction = new QAction("Thaw selected");
m_viewOutputAction = new QAction(QIcon(":/assets/images/info.png"), "Details", this); m_viewOutputAction = new QAction(QIcon(":/assets/images/info.png"), "Details");
m_sweepOutputAction = new QAction("Sweep output", this); m_sweepOutputAction = new QAction("Sweep output");
connect(m_freezeOutputAction, &QAction::triggered, this, &CoinsWidget::freezeOutput); connect(m_freezeOutputAction, &QAction::triggered, this, &CoinsWidget::freezeOutput);
connect(m_thawOutputAction, &QAction::triggered, this, &CoinsWidget::thawOutput); connect(m_thawOutputAction, &QAction::triggered, this, &CoinsWidget::thawOutput);
connect(m_viewOutputAction, &QAction::triggered, this, &CoinsWidget::viewOutput); connect(m_viewOutputAction, &QAction::triggered, this, &CoinsWidget::viewOutput);
@@ -65,19 +63,13 @@ CoinsWidget::CoinsWidget(QWidget *parent)
void CoinsWidget::setModel(CoinsModel * model, Coins * coins) { void CoinsWidget::setModel(CoinsModel * model, Coins * coins) {
m_coins = coins; m_coins = coins;
m_model = model; m_model = model;
m_proxyModel = new CoinsProxyModel(this); m_proxyModel = new CoinsProxyModel;
m_proxyModel->setSourceModel(m_model); m_proxyModel->setSourceModel(m_model);
ui->coins->setModel(m_proxyModel); ui->coins->setModel(m_proxyModel);
ui->coins->setColumnHidden(CoinsModel::Spent, true); ui->coins->setColumnHidden(CoinsModel::Spent, true);
ui->coins->setColumnHidden(CoinsModel::SpentHeight, true); ui->coins->setColumnHidden(CoinsModel::SpentHeight, true);
ui->coins->setColumnHidden(CoinsModel::Frozen, true); ui->coins->setColumnHidden(CoinsModel::Frozen, true);
if (!m_ctx->currentWallet->viewOnly()) {
ui->coins->setColumnHidden(CoinsModel::KeyImageKnown, true);
} else {
ui->coins->setColumnHidden(CoinsModel::KeyImageKnown, false);
}
ui->coins->header()->setSectionResizeMode(QHeaderView::ResizeToContents); ui->coins->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
ui->coins->header()->setSectionResizeMode(CoinsModel::AddressLabel, QHeaderView::Stretch); ui->coins->header()->setSectionResizeMode(CoinsModel::AddressLabel, QHeaderView::Stretch);
ui->coins->header()->setSortIndicator(CoinsModel::BlockHeight, Qt::DescendingOrder); ui->coins->header()->setSortIndicator(CoinsModel::BlockHeight, Qt::DescendingOrder);
@@ -111,15 +103,10 @@ void CoinsWidget::showContextMenu(const QPoint &point) {
if (!isSpent) { if (!isSpent) {
isFrozen ? menu->addAction(m_thawOutputAction) : menu->addAction(m_freezeOutputAction); isFrozen ? menu->addAction(m_thawOutputAction) : menu->addAction(m_freezeOutputAction);
menu->addAction(m_sweepOutputAction);
if (isFrozen || !isUnlocked) {
m_sweepOutputAction->setDisabled(true);
} else {
m_sweepOutputAction->setEnabled(true);
}
} }
if (!isFrozen && isUnlocked) {
menu->addAction(m_sweepOutputAction);
}
menu->addAction(m_viewOutputAction); menu->addAction(m_viewOutputAction);
} }
@@ -207,7 +194,6 @@ void CoinsWidget::onSweepOutput() {
qCritical() << "key image: " << keyImage; qCritical() << "key image: " << keyImage;
emit sweepOutput(keyImage, dialog->address(), dialog->churn(), dialog->outputs()); emit sweepOutput(keyImage, dialog->address(), dialog->churn(), dialog->outputs());
dialog->deleteLater();
} }
void CoinsWidget::copy(copyField field) { void CoinsWidget::copy(copyField field) {
-1
View File
@@ -67,7 +67,6 @@ private:
Coins *m_coins; Coins *m_coins;
CoinsModel * m_model; CoinsModel * m_model;
CoinsProxyModel * m_proxyModel; CoinsProxyModel * m_proxyModel;
AppContext *m_ctx;
void showContextMenu(const QPoint & point); void showContextMenu(const QPoint & point);
void copy(copyField field); void copy(copyField field);
+3 -1
View File
@@ -68,7 +68,9 @@ HelpLabel::HelpLabel(QWidget *parent) : QLabel(parent)
void HelpLabel::mouseReleaseEvent(QMouseEvent *event) void HelpLabel::mouseReleaseEvent(QMouseEvent *event)
{ {
Q_UNUSED(event) Q_UNUSED(event)
QMessageBox::information(this, "Help", this->help_text); QMessageBox msgBox(QApplication::activeWindow());
msgBox.setText(this->help_text);
msgBox.exec();
} }
void HelpLabel::enterEvent(QEvent *event) void HelpLabel::enterEvent(QEvent *event)
+1 -1
View File
@@ -53,7 +53,7 @@
<item> <item>
<widget class="QPlainTextEdit" name="copyrightText"> <widget class="QPlainTextEdit" name="copyrightText">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding"> <sizepolicy hsizetype="Expanding" vsizetype="Minimum">
<horstretch>0</horstretch> <horstretch>0</horstretch>
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
-62
View File
@@ -1,62 +0,0 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2020, The Monero Project.
#include "broadcasttxdialog.h"
#include "ui_broadcasttxdialog.h"
#include <QMessageBox>
BroadcastTxDialog::BroadcastTxDialog(QWidget *parent, AppContext *ctx)
: QDialog(parent)
, m_ctx(ctx)
, ui(new Ui::BroadcastTxDialog)
{
ui->setupUi(this);
m_network = new UtilsNetworking(m_ctx->network, this);
auto node = ctx->nodes->connection();
m_rpc = new DaemonRpc(this, m_network, node.full);
connect(ui->btn_Broadcast, &QPushButton::clicked, this, &BroadcastTxDialog::broadcastTx);
connect(ui->btn_Close, &QPushButton::clicked, this, &BroadcastTxDialog::reject);
connect(m_rpc, &DaemonRpc::ApiResponse, this, &BroadcastTxDialog::onApiResponse);
this->adjustSize();
}
void BroadcastTxDialog::broadcastTx() {
QString tx = ui->transaction->toPlainText();
QString node = [this]{
QString node;
if (ui->radio_useCustom->isChecked())
node = ui->customNode->text();
else
node = m_ctx->nodes->connection().full;
if (!node.startsWith("http://"))
node = QString("http://%1").arg(node);
return node;
}();
m_rpc->setDaemonAddress(node);
m_rpc->sendRawTransaction(tx);
}
void BroadcastTxDialog::onApiResponse(const DaemonRpc::DaemonResponse &resp) {
if (!resp.ok) {
QMessageBox::warning(this, "Transaction broadcast", resp.status);
return;
}
if (resp.endpoint == DaemonRpc::Endpoint::SEND_RAW_TRANSACTION) {
QMessageBox::information(this, "Transaction broadcast", "Transaction submitted successfully.\n\n"
"If the transaction belongs to this wallet it may take several minutes before it shows up in the history tab.");
}
}
BroadcastTxDialog::~BroadcastTxDialog() {
delete ui;
}
-35
View File
@@ -1,35 +0,0 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2020, The Monero Project.
#ifndef FEATHER_BROADCASTTXDIALOG_H
#define FEATHER_BROADCASTTXDIALOG_H
#include <QDialog>
#include "appcontext.h"
#include "utils/daemonrpc.h"
namespace Ui {
class BroadcastTxDialog;
}
class BroadcastTxDialog : public QDialog
{
Q_OBJECT
public:
explicit BroadcastTxDialog(QWidget *parent, AppContext *ctx);
~BroadcastTxDialog() override;
private slots:
void broadcastTx();
void onApiResponse(const DaemonRpc::DaemonResponse &resp);
private:
Ui::BroadcastTxDialog *ui;
UtilsNetworking *m_network;
AppContext *m_ctx;
DaemonRpc *m_rpc;
};
#endif //FEATHER_BROADCASTTXDIALOG_H
-111
View File
@@ -1,111 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>BroadcastTxDialog</class>
<widget class="QDialog" name="BroadcastTxDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>797</width>
<height>575</height>
</rect>
</property>
<property name="windowTitle">
<string>Broadcast transaction</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Transaction:</string>
</property>
</widget>
</item>
<item>
<widget class="QPlainTextEdit" name="transaction">
<property name="minimumSize">
<size>
<width>500</width>
<height>0</height>
</size>
</property>
<property name="placeholderText">
<string>Paste hex encoded signed tx string here</string>
</property>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Node</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QRadioButton" name="radio_useDefault">
<property name="text">
<string>Use currently connected node</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="radio_useCustom">
<property name="text">
<string>Use custom node</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="customNode"/>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QLabel" name="label_2">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>All transactions are broadcast over Tor</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="btn_Broadcast">
<property name="text">
<string>Broadcast</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btn_Close">
<property name="text">
<string>Close</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
+33 -47
View File
@@ -12,26 +12,15 @@
DebugInfoDialog::DebugInfoDialog(AppContext *ctx, QWidget *parent) DebugInfoDialog::DebugInfoDialog(AppContext *ctx, QWidget *parent)
: QDialog(parent) : QDialog(parent)
, ui(new Ui::DebugInfoDialog) , ui(new Ui::DebugInfoDialog)
, m_ctx(ctx)
{ {
ui->setupUi(this); ui->setupUi(this);
connect(ui->btn_Copy, &QPushButton::clicked, this, &DebugInfoDialog::copyToClipboad);
m_updateTimer.start(5000);
connect(&m_updateTimer, &QTimer::timeout, this, &DebugInfoDialog::updateInfo);
this->updateInfo();
this->adjustSize();
}
void DebugInfoDialog::updateInfo() {
QString torStatus; QString torStatus;
if(m_ctx->isTorSocks) if(ctx->isTorSocks)
torStatus = "Torsocks"; torStatus = "Torsocks";
else if(m_ctx->tor->localTor) else if(ctx->tor->localTor)
torStatus = "Local (assumed to be running)"; torStatus = "Local (assumed to be running)";
else if(m_ctx->tor->torConnected) else if(ctx->tor->torConnected)
torStatus = "Running"; torStatus = "Running";
else else
torStatus = "Unknown"; torStatus = "Unknown";
@@ -39,28 +28,27 @@ void DebugInfoDialog::updateInfo() {
ui->label_featherVersion->setText(QString("%1-%2").arg(FEATHER_VERSION, FEATHER_BRANCH)); ui->label_featherVersion->setText(QString("%1-%2").arg(FEATHER_VERSION, FEATHER_BRANCH));
ui->label_moneroVersion->setText(QString("%1-%2").arg(MONERO_VERSION, MONERO_BRANCH)); ui->label_moneroVersion->setText(QString("%1-%2").arg(MONERO_VERSION, MONERO_BRANCH));
ui->label_walletHeight->setText(QString::number(m_ctx->currentWallet->blockChainHeight())); ui->label_walletHeight->setText(QString::number(ctx->currentWallet->blockChainHeight()));
ui->label_daemonHeight->setText(QString::number(m_ctx->currentWallet->daemonBlockChainHeight())); ui->label_daemonHeight->setText(QString::number(ctx->currentWallet->daemonBlockChainHeight()));
ui->label_targetHeight->setText(QString::number(m_ctx->currentWallet->daemonBlockChainTargetHeight())); ui->label_restoreHeight->setText(QString::number(ctx->currentWallet->getWalletCreationHeight()));
ui->label_restoreHeight->setText(QString::number(m_ctx->currentWallet->getWalletCreationHeight())); ui->label_synchronized->setText(ctx->currentWallet->synchronized() ? "True" : "False");
ui->label_synchronized->setText(m_ctx->currentWallet->synchronized() ? "True" : "False");
auto node = m_ctx->nodes->connection(); auto node = ctx->nodes->connection();
ui->label_remoteNode->setText(node.full); ui->label_remoteNode->setText(node.full);
ui->label_walletStatus->setText(this->statusToString(m_ctx->currentWallet->connectionStatus())); ui->label_walletStatus->setText(this->statusToString(ctx->currentWallet->connected()));
ui->label_torStatus->setText(torStatus); ui->label_torStatus->setText(torStatus);
ui->label_websocketStatus->setText(Utils::QtEnumToString(m_ctx->ws->webSocket.state())); ui->label_websocketStatus->setText(Utils::QtEnumToString(ctx->ws->webSocket.state()));
ui->label_netType->setText(Utils::QtEnumToString(m_ctx->currentWallet->nettype())); ui->label_netType->setText(Utils::QtEnumToString(ctx->currentWallet->nettype()));
ui->label_seedType->setText(m_ctx->currentWallet->getCacheAttribute("feather.seed").isEmpty() ? "25 word" : "14 word"); ui->label_seedType->setText(ctx->currentWallet->getCacheAttribute("feather.seed").isEmpty() ? "25 word" : "14 word");
ui->label_viewOnly->setText(m_ctx->currentWallet->viewOnly() ? "True" : "False"); ui->label_viewOnly->setText(ctx->currentWallet->viewOnly() ? "True" : "False");
QString os = QSysInfo::prettyProductName(); ui->label_OS->setText(QSysInfo::prettyProductName());
if (m_ctx->isTails) {
os = QString("Tails %1").arg(TailsOS::version());
}
ui->label_OS->setText(os);
ui->label_timestamp->setText(QString::number(QDateTime::currentSecsSinceEpoch())); ui->label_timestamp->setText(QString::number(QDateTime::currentSecsSinceEpoch()));
connect(ui->btn_Copy, &QPushButton::clicked, this, &DebugInfoDialog::copyToClipboad);
this->adjustSize();
} }
QString DebugInfoDialog::statusToString(Wallet::ConnectionStatus status) { QString DebugInfoDialog::statusToString(Wallet::ConnectionStatus status) {
@@ -79,28 +67,26 @@ QString DebugInfoDialog::statusToString(Wallet::ConnectionStatus status) {
} }
void DebugInfoDialog::copyToClipboad() { void DebugInfoDialog::copyToClipboad() {
// Two spaces at the end of each line are for newlines in Markdown
QString text = ""; QString text = "";
text += QString("Feather version: %1 \n").arg(ui->label_featherVersion->text()); text += QString("Feather version: %1\n").arg(ui->label_featherVersion->text());
text += QString("Monero version: %1 \n").arg(ui->label_moneroVersion->text()); text += QString("Monero version: %1\n").arg(ui->label_moneroVersion->text());
text += QString("Wallet height: %1 \n").arg(ui->label_walletHeight->text()); text += QString("Wallet height: %1\n").arg(ui->label_walletHeight->text());
text += QString("Daemon height: %1 \n").arg(ui->label_daemonHeight->text()); text += QString("Daemon height: %1\n").arg(ui->label_daemonHeight->text());
text += QString("Target height: %1 \n").arg(ui->label_targetHeight->text()); text += QString("Restore height: %1\n").arg(ui->label_restoreHeight->text());
text += QString("Restore height: %1 \n").arg(ui->label_restoreHeight->text()); text += QString("Synchronized: %1\n").arg(ui->label_synchronized->text());
text += QString("Synchronized: %1 \n").arg(ui->label_synchronized->text());
text += QString("Remote node: %1 \n").arg(ui->label_remoteNode->text()); text += QString("Remote node: %1\n").arg(ui->label_remoteNode->text());
text += QString("Wallet status: %1 \n").arg(ui->label_walletStatus->text()); text += QString("Wallet status: %1\n").arg(ui->label_walletStatus->text());
text += QString("Tor status: %1 \n").arg(ui->label_torStatus->text()); text += QString("Tor status: %1\n").arg(ui->label_torStatus->text());
text += QString("Websocket status: %1 \n").arg(ui->label_websocketStatus->text()); text += QString("Websocket status: %1\n").arg(ui->label_websocketStatus->text());
text += QString("Network type: %1 \n").arg(ui->label_netType->text()); text += QString("Network type: %1\n").arg(ui->label_netType->text());
text += QString("Seed type: %1 \n").arg(ui->label_seedType->text()); text += QString("Seed type: %1\n").arg(ui->label_seedType->text());
text += QString("View only: %1 \n").arg(ui->label_viewOnly->text()); text += QString("View only: %1\n").arg(ui->label_viewOnly->text());
text += QString("Operating system: %1 \n").arg(ui->label_OS->text()); text += QString("Operating system: %1\n").arg(ui->label_OS->text());
text += QString("Timestamp: %1 \n").arg(ui->label_timestamp->text()); text += QString("Timestamp: %1\n").arg(ui->label_timestamp->text());
Utils::copyToClipboard(text); Utils::copyToClipboard(text);
} }
-4
View File
@@ -23,10 +23,6 @@ public:
private: private:
QString statusToString(Wallet::ConnectionStatus status); QString statusToString(Wallet::ConnectionStatus status);
void copyToClipboad(); void copyToClipboad();
void updateInfo();
QTimer m_updateTimer;
AppContext *m_ctx;
Ui::DebugInfoDialog *ui; Ui::DebugInfoDialog *ui;
}; };
+26 -46
View File
@@ -7,7 +7,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>693</width> <width>693</width>
<height>612</height> <height>580</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@@ -91,14 +91,14 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="6" column="0"> <item row="5" column="0">
<widget class="QLabel" name="label_10"> <widget class="QLabel" name="label_10">
<property name="text"> <property name="text">
<string>Restore height:</string> <string>Restore height:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="6" column="1"> <item row="5" column="1">
<widget class="QLabel" name="label_restoreHeight"> <widget class="QLabel" name="label_restoreHeight">
<property name="text"> <property name="text">
<string>TextLabel</string> <string>TextLabel</string>
@@ -108,14 +108,14 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="7" column="0"> <item row="6" column="0">
<widget class="QLabel" name="label_9"> <widget class="QLabel" name="label_9">
<property name="text"> <property name="text">
<string>Synchronized:</string> <string>Synchronized:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="7" column="1"> <item row="6" column="1">
<widget class="QLabel" name="label_synchronized"> <widget class="QLabel" name="label_synchronized">
<property name="text"> <property name="text">
<string>TextLabel</string> <string>TextLabel</string>
@@ -125,21 +125,21 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="8" column="1"> <item row="7" column="1">
<widget class="Line" name="line_2"> <widget class="Line" name="line_2">
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
</widget> </widget>
</item> </item>
<item row="9" column="0"> <item row="8" column="0">
<widget class="QLabel" name="label_27"> <widget class="QLabel" name="label_27">
<property name="text"> <property name="text">
<string>Remote node:</string> <string>Remote node:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="9" column="1"> <item row="8" column="1">
<widget class="QLabel" name="label_remoteNode"> <widget class="QLabel" name="label_remoteNode">
<property name="text"> <property name="text">
<string>TextLabel</string> <string>TextLabel</string>
@@ -149,14 +149,14 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="10" column="0"> <item row="9" column="0">
<widget class="QLabel" name="label_17"> <widget class="QLabel" name="label_17">
<property name="text"> <property name="text">
<string>Wallet status:</string> <string>Wallet status:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="10" column="1"> <item row="9" column="1">
<widget class="QLabel" name="label_walletStatus"> <widget class="QLabel" name="label_walletStatus">
<property name="text"> <property name="text">
<string>TextLabel</string> <string>TextLabel</string>
@@ -166,14 +166,14 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="11" column="0"> <item row="10" column="0">
<widget class="QLabel" name="label_18"> <widget class="QLabel" name="label_18">
<property name="text"> <property name="text">
<string>Tor status:</string> <string>Tor status:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="11" column="1"> <item row="10" column="1">
<widget class="QLabel" name="label_torStatus"> <widget class="QLabel" name="label_torStatus">
<property name="text"> <property name="text">
<string>TextLabel</string> <string>TextLabel</string>
@@ -183,14 +183,14 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="12" column="0"> <item row="11" column="0">
<widget class="QLabel" name="label_19"> <widget class="QLabel" name="label_19">
<property name="text"> <property name="text">
<string>Websocket status:</string> <string>Websocket status:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="12" column="1"> <item row="11" column="1">
<widget class="QLabel" name="label_websocketStatus"> <widget class="QLabel" name="label_websocketStatus">
<property name="text"> <property name="text">
<string>TextLabel</string> <string>TextLabel</string>
@@ -200,21 +200,21 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="13" column="1"> <item row="12" column="1">
<widget class="Line" name="line_3"> <widget class="Line" name="line_3">
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
</widget> </widget>
</item> </item>
<item row="14" column="0"> <item row="13" column="0">
<widget class="QLabel" name="label_2"> <widget class="QLabel" name="label_2">
<property name="text"> <property name="text">
<string>Network type:</string> <string>Network type:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="14" column="1"> <item row="13" column="1">
<widget class="QLabel" name="label_netType"> <widget class="QLabel" name="label_netType">
<property name="text"> <property name="text">
<string>TextLabel</string> <string>TextLabel</string>
@@ -224,14 +224,14 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="15" column="0"> <item row="14" column="0">
<widget class="QLabel" name="label_23"> <widget class="QLabel" name="label_23">
<property name="text"> <property name="text">
<string>Seed type:</string> <string>Seed type:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="15" column="1"> <item row="14" column="1">
<widget class="QLabel" name="label_seedType"> <widget class="QLabel" name="label_seedType">
<property name="text"> <property name="text">
<string>TextLabel</string> <string>TextLabel</string>
@@ -241,14 +241,14 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="16" column="0"> <item row="15" column="0">
<widget class="QLabel" name="label_7"> <widget class="QLabel" name="label_7">
<property name="text"> <property name="text">
<string>View only:</string> <string>View only:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="16" column="1"> <item row="15" column="1">
<widget class="QLabel" name="label_viewOnly"> <widget class="QLabel" name="label_viewOnly">
<property name="text"> <property name="text">
<string>TextLabel</string> <string>TextLabel</string>
@@ -258,14 +258,14 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="19" column="0"> <item row="18" column="0">
<widget class="QLabel" name="label_24"> <widget class="QLabel" name="label_24">
<property name="text"> <property name="text">
<string>Timestamp:</string> <string>Timestamp:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="19" column="1"> <item row="18" column="1">
<widget class="QLabel" name="label_timestamp"> <widget class="QLabel" name="label_timestamp">
<property name="text"> <property name="text">
<string>TextLabel</string> <string>TextLabel</string>
@@ -275,47 +275,27 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="18" column="0"> <item row="17" column="0">
<widget class="QLabel" name="label_3"> <widget class="QLabel" name="label_3">
<property name="text"> <property name="text">
<string>Operating system:</string> <string>Operating system:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="18" column="1"> <item row="17" column="1">
<widget class="QLabel" name="label_OS"> <widget class="QLabel" name="label_OS">
<property name="text"> <property name="text">
<string>TextLabel</string> <string>TextLabel</string>
</property> </property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget> </widget>
</item> </item>
<item row="17" column="1"> <item row="16" column="1">
<widget class="Line" name="line_4"> <widget class="Line" name="line_4">
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
</widget> </widget>
</item> </item>
<item row="5" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Target height:</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QLabel" name="label_targetHeight">
<property name="text">
<string>TextLabel</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
</layout> </layout>
</item> </item>
<item> <item>
+10 -45
View File
@@ -5,39 +5,17 @@
#include "ui_passwordchangedialog.h" #include "ui_passwordchangedialog.h"
#include <QPushButton> #include <QPushButton>
#include <QMessageBox>
PasswordChangeDialog::PasswordChangeDialog(QWidget *parent, Wallet *wallet) PasswordChangeDialog::PasswordChangeDialog(QWidget *parent)
: QDialog(parent) : QDialog(parent)
, ui(new Ui::PasswordChangeDialog) , ui(new Ui::PasswordChangeDialog)
, m_wallet(wallet)
{ {
ui->setupUi(this); ui->setupUi(this);
ui->icon->setPixmap(QPixmap(":/assets/images/lock.png").scaledToWidth(32, Qt::SmoothTransformation));
bool noPassword = wallet->getPassword().isEmpty();
QString warning_str = noPassword ? "Your wallet is not password protected. Use this dialog to add a password to your wallet." :
"Your wallet is password protected and encrypted. Use this dialog to change your password.";
ui->label_warning->setText(warning_str);
QPixmap pixmap = noPassword ? QPixmap(":/assets/images/unlock.png") : QPixmap(":/assets/images/lock.png");
ui->icon->setPixmap(pixmap.scaledToWidth(32, Qt::SmoothTransformation));
if (noPassword) {
ui->label_currentPassword->hide();
ui->lineEdit_currentPassword->hide();
}
connect(ui->lineEdit_newPassword, &QLineEdit::textChanged, this, &PasswordChangeDialog::passwordsMatch); connect(ui->lineEdit_newPassword, &QLineEdit::textChanged, this, &PasswordChangeDialog::passwordsMatch);
connect(ui->lineEdit_confirmPassword, &QLineEdit::textChanged, this, &PasswordChangeDialog::passwordsMatch); connect(ui->lineEdit_confirmPassword, &QLineEdit::textChanged, this, &PasswordChangeDialog::passwordsMatch);
connect(ui->btn_Cancel, &QPushButton::clicked, [this]{
this->reject();
});
connect(ui->btn_OK, &QPushButton::clicked, this, &PasswordChangeDialog::setPassword);
ui->label_match->setVisible(false);
this->adjustSize(); this->adjustSize();
} }
@@ -46,28 +24,15 @@ PasswordChangeDialog::~PasswordChangeDialog()
delete ui; delete ui;
} }
void PasswordChangeDialog::passwordsMatch() { QString PasswordChangeDialog::getCurrentPassword() {
bool match = ui->lineEdit_newPassword->text() == ui->lineEdit_confirmPassword->text(); return ui->lineEdit_currentPassword->text();
ui->btn_OK->setEnabled(match);
ui->label_match->setHidden(match);
} }
void PasswordChangeDialog::setPassword() { QString PasswordChangeDialog::getNewPassword() {
QString currentPassword = ui->lineEdit_currentPassword->text(); return ui->lineEdit_newPassword->text();
QString newPassword = ui->lineEdit_newPassword->text(); }
if (currentPassword != m_wallet->getPassword()) { void PasswordChangeDialog::passwordsMatch() {
QMessageBox::warning(this, "Error", "Incorrect password"); bool match = ui->lineEdit_newPassword->text() == ui->lineEdit_confirmPassword->text();
ui->lineEdit_currentPassword->setText(""); ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(match);
ui->lineEdit_currentPassword->setFocus();
return;
}
if (m_wallet->setPassword(newPassword)) {
QMessageBox::information(this, "Information", "Password changed successfully");
this->accept();
}
else {
QMessageBox::warning(this, "Error", QString("Error: %1").arg(m_wallet->errorString()));
}
} }
+4 -4
View File
@@ -5,7 +5,6 @@
#define FEATHER_PASSWORDCHANGEDIALOG_H #define FEATHER_PASSWORDCHANGEDIALOG_H
#include <QDialog> #include <QDialog>
#include "libwalletqt/Wallet.h"
namespace Ui { namespace Ui {
class PasswordChangeDialog; class PasswordChangeDialog;
@@ -16,15 +15,16 @@ class PasswordChangeDialog : public QDialog
Q_OBJECT Q_OBJECT
public: public:
explicit PasswordChangeDialog(QWidget *parent, Wallet *wallet); explicit PasswordChangeDialog(QWidget *parent = nullptr);
~PasswordChangeDialog() override; ~PasswordChangeDialog() override;
QString getCurrentPassword();
QString getNewPassword();
private: private:
Ui::PasswordChangeDialog *ui; Ui::PasswordChangeDialog *ui;
Wallet *m_wallet;
void passwordsMatch(); void passwordsMatch();
void setPassword();
}; };
#endif //FEATHER_PASSWORDCHANGEDIALOG_H #endif //FEATHER_PASSWORDCHANGEDIALOG_H
+46 -60
View File
@@ -6,8 +6,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>556</width> <width>500</width>
<height>309</height> <height>237</height>
</rect> </rect>
</property> </property>
<property name="sizePolicy"> <property name="sizePolicy">
@@ -30,7 +30,7 @@
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QLabel" name="label_warning"> <widget class="QLabel" name="label_2">
<property name="text"> <property name="text">
<string>Your wallet is password protected and encrypted. Use this dialog to change your password.</string> <string>Your wallet is password protected and encrypted. Use this dialog to change your password.</string>
</property> </property>
@@ -41,22 +41,6 @@
</item> </item>
</layout> </layout>
</item> </item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>10</height>
</size>
</property>
</spacer>
</item>
<item> <item>
<layout class="QGridLayout" name="gridLayout"> <layout class="QGridLayout" name="gridLayout">
<item row="1" column="0"> <item row="1" column="0">
@@ -81,7 +65,7 @@
</widget> </widget>
</item> </item>
<item row="0" column="0"> <item row="0" column="0">
<widget class="QLabel" name="label_currentPassword"> <widget class="QLabel" name="label">
<property name="text"> <property name="text">
<string>Current Password:</string> <string>Current Password:</string>
</property> </property>
@@ -104,45 +88,14 @@
</layout> </layout>
</item> </item>
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout_2"> <widget class="QDialogButtonBox" name="buttonBox">
<item> <property name="orientation">
<widget class="QLabel" name="label_match"> <enum>Qt::Horizontal</enum>
<property name="enabled"> </property>
<bool>false</bool> <property name="standardButtons">
</property> <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
<property name="text"> </property>
<string>Passwords do not match</string> </widget>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="btn_Cancel">
<property name="text">
<string>Cancel</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btn_OK">
<property name="text">
<string>OK</string>
</property>
</widget>
</item>
</layout>
</item> </item>
</layout> </layout>
</widget> </widget>
@@ -152,5 +105,38 @@
<tabstop>lineEdit_confirmPassword</tabstop> <tabstop>lineEdit_confirmPassword</tabstop>
</tabstops> </tabstops>
<resources/> <resources/>
<connections/> <connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>PasswordChangeDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>PasswordChangeDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui> </ui>
-26
View File
@@ -1,26 +0,0 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2020, The Monero Project.
#include "passworddialog.h"
#include "ui_passworddialog.h"
PasswordDialog::PasswordDialog(QWidget *parent, const QString &walletName, bool incorrectPassword)
: QDialog(parent)
, ui(new Ui::PasswordDialog)
{
ui->setupUi(this);
ui->label_wallet->setText(QString("Please enter password for wallet: %1").arg(walletName));
ui->label_incorrectPassword->setVisible(incorrectPassword);
connect(ui->buttonBox, &QDialogButtonBox::accepted, [this]{
password = ui->line_password->text();
});
this->adjustSize();
}
PasswordDialog::~PasswordDialog()
{
delete ui;
}
-27
View File
@@ -1,27 +0,0 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2020, The Monero Project.
#ifndef FEATHER_PASSWORDDIALOG_H
#define FEATHER_PASSWORDDIALOG_H
#include <QDialog>
namespace Ui {
class PasswordDialog;
}
class PasswordDialog : public QDialog
{
Q_OBJECT
public:
explicit PasswordDialog(QWidget *parent, const QString &walletName, bool incorrectPassword);
~PasswordDialog() override;
QString password = "";
private:
Ui::PasswordDialog *ui;
};
#endif //FEATHER_PASSWORDDIALOG_H
-85
View File
@@ -1,85 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>PasswordDialog</class>
<widget class="QDialog" name="PasswordDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>832</width>
<height>158</height>
</rect>
</property>
<property name="windowTitle">
<string>Password required</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label_wallet">
<property name="text">
<string>Please enter password for wallet: </string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_incorrectPassword">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; color:#a40000;&quot;&gt;Incorrect password, try again.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="line_password">
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>PasswordDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>PasswordDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>
+4 -7
View File
@@ -9,14 +9,15 @@
#include <QFileDialog> #include <QFileDialog>
#include <QMessageBox> #include <QMessageBox>
QrCodeDialog::QrCodeDialog(QWidget *parent, const QrCode &qrCode, const QString &title) QrCodeDialog::QrCodeDialog(QWidget *parent, const QString &text, const QString &title)
: QDialog(parent) : QDialog(parent)
, ui(new Ui::QrCodeDialog) , ui(new Ui::QrCodeDialog)
{ {
ui->setupUi(this); ui->setupUi(this);
this->setWindowTitle(title); this->setWindowTitle(title);
m_pixmap = qrCode.toPixmap(1).scaled(500, 500, Qt::KeepAspectRatio); m_qrc = new QrCode(text, QrCode::Version::AUTO, QrCode::ErrorCorrectionLevel::HIGH);
m_pixmap = m_qrc->toPixmap(1).scaled(500, 500, Qt::KeepAspectRatio);
ui->QrCode->setPixmap(m_pixmap); ui->QrCode->setPixmap(m_pixmap);
connect(ui->btn_CopyImage, &QPushButton::clicked, this, &QrCodeDialog::copyImage); connect(ui->btn_CopyImage, &QPushButton::clicked, this, &QrCodeDialog::copyImage);
@@ -31,11 +32,7 @@ QrCodeDialog::QrCodeDialog(QWidget *parent, const QrCode &qrCode, const QString
QrCodeDialog::~QrCodeDialog() QrCodeDialog::~QrCodeDialog()
{ {
delete ui; delete ui;
} delete m_qrc;
void QrCodeDialog::setQrCode(const QrCode &qrCode) {
m_pixmap = qrCode.toPixmap(1).scaled(500, 500, Qt::KeepAspectRatio);
ui->QrCode->setPixmap(m_pixmap);
} }
void QrCodeDialog::copyImage() { void QrCodeDialog::copyImage() {
+2 -2
View File
@@ -16,15 +16,15 @@ class QrCodeDialog : public QDialog
Q_OBJECT Q_OBJECT
public: public:
explicit QrCodeDialog(QWidget *parent, const QrCode &qrCode, const QString &title = "Qr Code"); explicit QrCodeDialog(QWidget *parent, const QString &text, const QString &title = "Qr Code");
~QrCodeDialog() override; ~QrCodeDialog() override;
void setQrCode(const QrCode &qrCode);
private: private:
void copyImage(); void copyImage();
void saveImage(); void saveImage();
Ui::QrCodeDialog *ui; Ui::QrCodeDialog *ui;
QrCode *m_qrc;
QPixmap m_pixmap; QPixmap m_pixmap;
}; };
+12 -36
View File
@@ -4,51 +4,27 @@
#include "ui_seeddialog.h" #include "ui_seeddialog.h"
#include "seeddialog.h" #include "seeddialog.h"
SeedDialog::SeedDialog(Wallet *wallet, QWidget *parent) SeedDialog::SeedDialog(const QString &seed, QWidget *parent)
: QDialog(parent) : QDialog(parent)
, ui(new Ui::SeedDialog) , ui(new Ui::SeedDialog)
{ {
ui->setupUi(this); ui->setupUi(this);
ui->label_seedIcon->setPixmap(QPixmap(":/assets/images/seed.png").scaledToWidth(64, Qt::SmoothTransformation)); ui->label_seedIcon->setPixmap(QPixmap(":/assets/images/seed.png").scaledToWidth(64, Qt::SmoothTransformation));
ui->label_restoreHeight->setText(QString::number(wallet->getWalletCreationHeight()));
QString seed_14_words = wallet->getCacheAttribute("feather.seed");
QString seed_25_words = wallet->getSeed();
if (seed_14_words.isEmpty()) {
ui->check_toggleSeedType->hide();
this->setSeed(seed_25_words);
} else {
this->setSeed(seed_14_words);
ui->widgetRestoreHeight->setVisible(false);
}
connect(ui->check_toggleSeedType, &QCheckBox::toggled, [this, seed_25_words, seed_14_words](bool toggled){
this->setSeed(toggled ? seed_25_words : seed_14_words);
ui->widgetRestoreHeight->setVisible(toggled);
});
ui->label_restoreHeightHelp->setHelpText("Should you restore your wallet in the future, "
"specifying this block number will recover your wallet quicker.");
this->adjustSize();
}
void SeedDialog::setSeed(const QString &seed) {
ui->seed->setPlainText(seed); ui->seed->setPlainText(seed);
int words = seed.split(" ").size(); int words = seed.split(" ").size();
ui->label_warning->setText(QString("<p>Please save these %1 words on paper (order is important). " ui->label_warning->setText(QString("<p>Please save these %1 words on paper (order is important). "
"This seed will allow you to recover your wallet in case " "This seed will allow you to recover your wallet in case "
"of computer failure." "of computer failure."
"</p>" "</p>"
"<b>WARNING:</b>" "<b>WARNING:</b>"
"<ul>" "<ul>"
"<li>Never disclose your seed.</li>" "<li>Never disclose your seed.</li>"
"<li>Never type it on a website</li>" "<li>Never type it on a website</li>"
"<li>Do not store it electronically</li>" "<li>Do not store it electronically</li>"
"</ul>").arg(words)); "</ul>").arg(words));
this->adjustSize();
} }
SeedDialog::~SeedDialog() SeedDialog::~SeedDialog()
+1 -4
View File
@@ -5,7 +5,6 @@
#define FEATHER_SEEDDIALOG_H #define FEATHER_SEEDDIALOG_H
#include <QDialog> #include <QDialog>
#include "libwalletqt/Wallet.h"
namespace Ui { namespace Ui {
class SeedDialog; class SeedDialog;
@@ -16,12 +15,10 @@ class SeedDialog : public QDialog
Q_OBJECT Q_OBJECT
public: public:
explicit SeedDialog(Wallet *wallet, QWidget *parent = nullptr); explicit SeedDialog(const QString& seed, QWidget *parent = nullptr);
~SeedDialog() override; ~SeedDialog() override;
private: private:
void setSeed(const QString &seed);
Ui::SeedDialog *ui; Ui::SeedDialog *ui;
}; };
+22 -94
View File
@@ -6,8 +6,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>590</width> <width>542</width>
<height>346</height> <height>244</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@@ -34,94 +34,29 @@
</widget> </widget>
</item> </item>
<item> <item>
<layout class="QVBoxLayout" name="verticalLayout_2"> <widget class="QPlainTextEdit" name="seed">
<item> <property name="enabled">
<widget class="QPlainTextEdit" name="seed"> <bool>true</bool>
<property name="enabled"> </property>
<bool>true</bool> <property name="sizePolicy">
</property> <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<property name="sizePolicy"> <horstretch>0</horstretch>
<sizepolicy hsizetype="Expanding" vsizetype="Preferred"> <verstretch>0</verstretch>
<horstretch>0</horstretch> </sizepolicy>
<verstretch>0</verstretch> </property>
</sizepolicy> <property name="maximumSize">
</property> <size>
<property name="minimumSize"> <width>16777215</width>
<size> <height>125</height>
<width>0</width> </size>
<height>125</height> </property>
</size> <property name="readOnly">
</property> <bool>true</bool>
<property name="maximumSize"> </property>
<size> </widget>
<width>16777215</width>
<height>300</height>
</size>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QWidget" name="widgetRestoreHeight" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_4">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="HelpLabel" name="label_restoreHeightHelp">
<property name="text">
<string>Restore height:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_restoreHeight">
<property name="text">
<string>TextLabel</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
</layout>
</item> </item>
</layout> </layout>
</item> </item>
<item>
<widget class="QCheckBox" name="check_toggleSeedType">
<property name="text">
<string>Show 25 word seed</string>
</property>
</widget>
</item>
<item> <item>
<widget class="QLabel" name="label_warning"> <widget class="QLabel" name="label_warning">
<property name="text"> <property name="text">
@@ -144,13 +79,6 @@
</item> </item>
</layout> </layout>
</widget> </widget>
<customwidgets>
<customwidget>
<class>HelpLabel</class>
<extends>QLabel</extends>
<header>components.h</header>
</customwidget>
</customwidgets>
<resources/> <resources/>
<connections> <connections>
<connection> <connection>
+6 -19
View File
@@ -6,29 +6,18 @@
#include "libwalletqt/CoinsInfo.h" #include "libwalletqt/CoinsInfo.h"
#include "libwalletqt/WalletManager.h" #include "libwalletqt/WalletManager.h"
#include "utils.h" #include <QDebug>
#include <QMessageBox> TransactionInfoDialog::TransactionInfoDialog(Coins *coins, TransactionInfo *txInfo, QWidget *parent)
TransactionInfoDialog::TransactionInfoDialog(Wallet *wallet, TransactionInfo *txInfo, QWidget *parent)
: QDialog(parent) : QDialog(parent)
, ui(new Ui::TransactionInfoDialog) , ui(new Ui::TransactionInfoDialog)
, m_wallet(wallet) , m_coins(coins)
, m_txInfo(txInfo) , m_txInfo(txInfo)
{ {
ui->setupUi(this); ui->setupUi(this);
m_txProofWidget = new TxProofWidget(this, wallet, txInfo); ui->txid->setText(QString(txInfo->hash()));
ui->txid->setCursorPosition(0);
ui->label_txid->setText(QString(txInfo->hash()));
if (txInfo->direction() == TransactionInfo::Direction_In) {
ui->txKey->hide();
} else {
QString txKey = m_wallet->getTxKey(txInfo->hash());
txKey = txKey.isEmpty() ? "unknown" : txKey;
ui->label_txKey->setText(txKey);
}
ui->label_status->setText(QString("Status: %1 confirmations").arg(txInfo->confirmations())); ui->label_status->setText(QString("Status: %1 confirmations").arg(txInfo->confirmations()));
ui->label_date->setText(QString("Date: %1").arg(txInfo->timestamp().toString("yyyy-MM-dd HH:mm"))); ui->label_date->setText(QString("Date: %1").arg(txInfo->timestamp().toString("yyyy-MM-dd HH:mm")));
@@ -41,7 +30,7 @@ TransactionInfoDialog::TransactionInfoDialog(Wallet *wallet, TransactionInfo *tx
ui->label_fee->setText(QString("Fee: %1").arg(txInfo->isCoinbase() ? WalletManager::displayAmount(0) : fee)); ui->label_fee->setText(QString("Fee: %1").arg(txInfo->isCoinbase() ? WalletManager::displayAmount(0) : fee));
ui->label_unlockTime->setText(QString("Unlock time: %1 (height)").arg(txInfo->unlockTime())); ui->label_unlockTime->setText(QString("Unlock time: %1 (height)").arg(txInfo->unlockTime()));
qDebug() << m_wallet->coins()->coins_from_txid(txInfo->hash()); qDebug() << m_coins->coins_from_txid(txInfo->hash());
QString destinations = txInfo->destinations_formatted(); QString destinations = txInfo->destinations_formatted();
if (destinations.isEmpty()) { if (destinations.isEmpty()) {
@@ -52,8 +41,6 @@ TransactionInfoDialog::TransactionInfoDialog(Wallet *wallet, TransactionInfo *tx
ui->destinations->setText(destinations); ui->destinations->setText(destinations);
} }
ui->txProofWidget->addWidget(m_txProofWidget);
this->adjustSize(); this->adjustSize();
} }
+2 -5
View File
@@ -8,8 +8,6 @@
#include <QtSvg/QSvgWidget> #include <QtSvg/QSvgWidget>
#include "libwalletqt/Coins.h" #include "libwalletqt/Coins.h"
#include "libwalletqt/TransactionInfo.h" #include "libwalletqt/TransactionInfo.h"
#include "libwalletqt/Wallet.h"
#include "widgets/txproofwidget.h"
namespace Ui { namespace Ui {
class TransactionInfoDialog; class TransactionInfoDialog;
@@ -20,15 +18,14 @@ class TransactionInfoDialog : public QDialog
Q_OBJECT Q_OBJECT
public: public:
explicit TransactionInfoDialog(Wallet *wallet, TransactionInfo *txInfo, QWidget *parent = nullptr); explicit TransactionInfoDialog(Coins *coins, TransactionInfo *txInfo, QWidget *parent = nullptr);
~TransactionInfoDialog() override; ~TransactionInfoDialog() override;
private: private:
Ui::TransactionInfoDialog *ui; Ui::TransactionInfoDialog *ui;
TransactionInfo *m_txInfo; TransactionInfo *m_txInfo;
Wallet *m_wallet; Coins *m_coins;
TxProofWidget *m_txProofWidget;
}; };
#endif //FEATHER_TRANSACTIONINFODIALOG_H #endif //FEATHER_TRANSACTIONINFODIALOG_H
+22 -41
View File
@@ -6,8 +6,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>829</width> <width>547</width>
<height>570</height> <height>332</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@@ -15,41 +15,32 @@
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_4"> <layout class="QVBoxLayout" name="verticalLayout_4">
<item> <item>
<widget class="QGroupBox" name="groupBox"> <widget class="QLabel" name="label">
<property name="title"> <property name="text">
<string>Transaction ID:</string> <string>Transaction ID:</string>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label_txid">
<property name="text">
<string>txid</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
</layout>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QGroupBox" name="txKey"> <widget class="QLineEdit" name="txid">
<property name="title"> <property name="sizePolicy">
<string>Transaction key:</string> <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>525</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>txid</string>
</property>
<property name="readOnly">
<bool>true</bool>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<widget class="QLabel" name="label_txKey">
<property name="text">
<string>txKey</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
</layout>
</widget> </widget>
</item> </item>
<item> <item>
@@ -158,16 +149,6 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="Line" name="line_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="txProofWidget"/>
</item>
<item> <item>
<spacer name="verticalSpacer"> <spacer name="verticalSpacer">
<property name="orientation"> <property name="orientation">
-186
View File
@@ -1,186 +0,0 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2020, The Monero Project.
#include "txconfadvdialog.h"
#include "ui_txconfadvdialog.h"
#include "libwalletqt/WalletManager.h"
#include "qrcode/QrCode.h"
#include "dialog/qrcodedialog.h"
#include "utils/utils.h"
#include "libwalletqt/PendingTransactionInfo.h"
#include "libwalletqt/Transfer.h"
#include "libwalletqt/Input.h"
#include "model/ModelUtils.h"
#include <QFileDialog>
#include <QMessageBox>
TxConfAdvDialog::TxConfAdvDialog(AppContext *ctx, const QString &description, QWidget *parent)
: QDialog(parent)
, ui(new Ui::TxConfAdvDialog)
, m_ctx(ctx)
, m_exportUnsignedMenu(new QMenu(this))
, m_exportSignedMenu(new QMenu(this))
{
ui->setupUi(this);
m_exportUnsignedMenu->addAction("Copy to clipboard", this, &TxConfAdvDialog::unsignedCopy);
m_exportUnsignedMenu->addAction("Show as QR code", this, &TxConfAdvDialog::unsignedQrCode);
m_exportUnsignedMenu->addAction("Save to file", this, &TxConfAdvDialog::unsignedSaveFile);
ui->btn_exportUnsigned->setMenu(m_exportUnsignedMenu);
m_exportSignedMenu->addAction("Copy to clipboard", this, &TxConfAdvDialog::signedCopy);
m_exportSignedMenu->addAction("Save to file", this, &TxConfAdvDialog::signedSaveFile);
ui->btn_exportSigned->setMenu(m_exportSignedMenu);
if (m_ctx->currentWallet->viewOnly()) {
ui->btn_exportSigned->hide();
ui->btn_send->hide();
}
ui->label_description->setText(QString("Description: %1").arg(description));
connect(ui->btn_sign, &QPushButton::clicked, this, &TxConfAdvDialog::signTransaction);
connect(ui->btn_send, &QPushButton::clicked, this, &TxConfAdvDialog::broadcastTransaction);
connect(ui->btn_close, &QPushButton::clicked, this, &TxConfAdvDialog::closeDialog);
ui->inputs->setFont(ModelUtils::getMonospaceFont());
ui->outputs->setFont(ModelUtils::getMonospaceFont());
this->adjustSize();
}
void TxConfAdvDialog::setTransaction(PendingTransaction *tx) {
ui->btn_sign->hide();
m_tx = tx;
m_tx->refresh();
PendingTransactionInfo *ptx = m_tx->transaction(0);
ui->txid->setText(tx->txid().first());
ui->amount->setText(WalletManager::displayAmount(tx->amount()));
ui->fee->setText(WalletManager::displayAmount(ptx->fee()));
ui->total->setText(WalletManager::displayAmount(tx->amount() + ptx->fee()));
auto size_str = [this]{
if (m_ctx->currentWallet->viewOnly()) {
return QString("Size: %1 bytes (unsigned)").arg(QString::number(m_tx->unsignedTxToBin().size()));
} else {
auto size = m_tx->signedTxToHex(0).size() / 2;
return QString("Size: %1 bytes (%2 bytes unsigned)").arg(QString::number(size), QString::number(m_tx->unsignedTxToBin().size()));
}
}();
ui->label_size->setText(size_str);
this->setupConstructionData(ptx);
}
void TxConfAdvDialog::setUnsignedTransaction(UnsignedTransaction *utx) {
m_utx = utx;
m_utx->refresh();
ui->btn_exportUnsigned->hide();
ui->btn_exportSigned->hide();
ui->btn_sign->show();
ui->btn_send->hide();
ui->txid->setText("n/a");
ui->label_size->setText("Size: n/a");
ui->amount->setText(WalletManager::displayAmount(utx->amount(0)));
ui->fee->setText(WalletManager::displayAmount(utx->fee(0)));
ui->total->setText(WalletManager::displayAmount(utx->amount(0) + utx->fee(0)));
ConstructionInfo *ci = m_utx->constructionInfo(0);
this->setupConstructionData(ci);
}
void TxConfAdvDialog::setupConstructionData(ConstructionInfo *ci) {
QString inputs_str;
auto inputs = ci->inputs();
for (const auto& i: inputs) {
inputs_str += QString("%1 %2\n").arg(i->pubKey(), WalletManager::displayAmount(i->amount()));
}
ui->inputs->setText(inputs_str);
ui->label_inputs->setText(QString("Inputs (%1)").arg(QString::number(inputs.size())));
QString outputs_str;
auto outputs = ci->outputs();
for (const auto& o: outputs) {
outputs_str += QString("%1 %2\n").arg(o->address(), WalletManager::displayAmount(o->amount()));
}
ui->outputs->setText(outputs_str);
ui->label_outputs->setText(QString("Outputs (%1)").arg(QString::number(outputs.size())));
ui->label_ringSize->setText(QString("Ring size: %1").arg(QString::number(ci->minMixinCount() + 1)));
ui->label_unlockTime->setText(QString("Unlock time: %1 (height)").arg(QString::number(ci->unlockTime())));
}
void TxConfAdvDialog::signTransaction() {
QString defaultName = QString("%1_signed_monero_tx").arg(QString::number(QDateTime::currentSecsSinceEpoch()));
QString fn = QFileDialog::getSaveFileName(this, "Save signed transaction to file", QDir::home().filePath(defaultName), "Transaction (*signed_monero_tx)");
if(fn.isEmpty()) return;
m_utx->sign(fn) ? QMessageBox::information(this, "Sign transaction", "Transaction saved successfully")
: QMessageBox::warning(this, "Sign transaction", "Failes to save transaction to file.");
}
void TxConfAdvDialog::unsignedSaveFile() {
QString defaultName = QString("%1_unsigned_monero_tx").arg(QString::number(QDateTime::currentSecsSinceEpoch()));
QString fn = QFileDialog::getSaveFileName(this, "Save transaction to file", QDir::home().filePath(defaultName), "Transaction (*unsigned_monero_tx)");
if(fn.isEmpty()) return;
m_tx->saveToFile(fn) ? QMessageBox::information(this, "Transaction saved to file", "Transaction saved successfully")
: QMessageBox::warning(this, "Save transaction", "Failed to save transaction to file.");
}
void TxConfAdvDialog::signedSaveFile() {
QString defaultName = QString("%1_signed_monero_tx").arg(QString::number(QDateTime::currentSecsSinceEpoch()));
QString fn = QFileDialog::getSaveFileName(this, "Save transaction to file", QDir::home().filePath(defaultName), "Transaction (*signed_monero_tx)");
if(fn.isEmpty()) return;
m_tx->saveToFile(fn) ? QMessageBox::information(this, "Transaction saved to file", "Transaction saved successfully")
: QMessageBox::warning(this, "Save transaction", "Failed to save transaction to file.");
}
void TxConfAdvDialog::unsignedQrCode() {
if (m_tx->unsignedTxToBin().size() > 2953) {
QMessageBox::warning(this, "Unable to show QR code", "Transaction size exceeds the maximum size for QR codes (2953 bytes).");
return;
}
QrCode qr(m_tx->unsignedTxToBin(), QrCode::Version::AUTO, QrCode::ErrorCorrectionLevel::LOW);
auto *dialog = new QrCodeDialog(this, qr, "Unsigned Transaction");
dialog->exec();
dialog->deleteLater();
}
void TxConfAdvDialog::unsignedCopy() {
Utils::copyToClipboard(m_tx->unsignedTxToBase64());
}
void TxConfAdvDialog::signedCopy() {
Utils::copyToClipboard(m_tx->signedTxToHex(0));
}
void TxConfAdvDialog::signedQrCode() {
}
void TxConfAdvDialog::broadcastTransaction() {
if (m_tx == nullptr) return;
m_ctx->currentWallet->commitTransactionAsync(m_tx);
QDialog::accept();
}
void TxConfAdvDialog::closeDialog() {
if (m_tx != nullptr)
m_ctx->currentWallet->disposeTransaction(m_tx);
if (m_utx != nullptr)
m_ctx->currentWallet->disposeTransaction(m_utx);
QDialog::reject();
}
TxConfAdvDialog::~TxConfAdvDialog() {
delete ui;
}
-54
View File
@@ -1,54 +0,0 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2020, The Monero Project.
#ifndef FEATHER_TXCONFADVDIALOG_H
#define FEATHER_TXCONFADVDIALOG_H
#include <QDialog>
#include <QStandardItemModel>
#include <QAbstractButton>
#include <QMenu>
#include "libwalletqt/PendingTransaction.h"
#include "appcontext.h"
namespace Ui {
class TxConfAdvDialog;
}
class TxConfAdvDialog : public QDialog
{
Q_OBJECT
public:
explicit TxConfAdvDialog(AppContext *ctx, const QString &description, QWidget *parent = nullptr);
~TxConfAdvDialog() override;
void setTransaction(PendingTransaction *tx);
void setUnsignedTransaction(UnsignedTransaction *utx);
private:
void setupConstructionData(ConstructionInfo *ci);
void signTransaction();
void broadcastTransaction();
void closeDialog();
void unsignedCopy();
void unsignedQrCode();
void unsignedSaveFile();
void signedCopy();
void signedQrCode();
void signedSaveFile();
Ui::TxConfAdvDialog *ui;
AppContext *m_ctx;
PendingTransaction *m_tx = nullptr;
UnsignedTransaction *m_utx = nullptr;
QMenu *m_exportUnsignedMenu;
QMenu *m_exportSignedMenu;
};
#endif //FEATHER_TXCONFADVDIALOG_H
-279
View File
@@ -1,279 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>TxConfAdvDialog</class>
<widget class="QDialog" name="TxConfAdvDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>542</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>800</width>
<height>0</height>
</size>
</property>
<property name="windowTitle">
<string>Transaction</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Transaction ID:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="txid">
<property name="text">
<string>txid</string>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="label_amount">
<property name="text">
<string>Amount: </string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="amount">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_fee">
<property name="text">
<string>Fee: </string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="fee">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="Line" name="line_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Total:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="total">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QLabel" name="label_description">
<property name="text">
<string>Description:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_size">
<property name="text">
<string>Size: </string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_unlockTime">
<property name="text">
<string>Unlock time: </string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_ringSize">
<property name="text">
<string>Ringsize:</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Minimum</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>10</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label_inputs">
<property name="text">
<string>Inputs</string>
</property>
</widget>
</item>
<item>
<widget class="QTextEdit" name="inputs">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>100</height>
</size>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_outputs">
<property name="text">
<string>Outputs</string>
</property>
</widget>
</item>
<item>
<widget class="QTextEdit" name="outputs">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>100</height>
</size>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QToolButton" name="btn_exportUnsigned">
<property name="text">
<string>Export unsigned</string>
</property>
<property name="popupMode">
<enum>QToolButton::InstantPopup</enum>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="btn_exportSigned">
<property name="text">
<string>Export signed</string>
</property>
<property name="popupMode">
<enum>QToolButton::InstantPopup</enum>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="btn_sign">
<property name="text">
<string>Sign</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btn_send">
<property name="text">
<string>Send</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btn_close">
<property name="text">
<string>Close</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
+23 -14
View File
@@ -6,16 +6,12 @@
#include "appcontext.h" #include "appcontext.h"
#include "utils/config.h" #include "utils/config.h"
#include "model/ModelUtils.h" #include "model/ModelUtils.h"
#include "libwalletqt/WalletManager.h"
#include "txconfadvdialog.h"
#include "globals.h"
#include <QMessageBox> #include <QMessageBox>
TxConfDialog::TxConfDialog(AppContext *ctx, PendingTransaction *tx, const QString &address, const QString &description, int mixin, QWidget *parent) TxConfDialog::TxConfDialog(PendingTransaction *tx, const QString &address, const QString &description, int mixin, QWidget *parent)
: QDialog(parent) : QDialog(parent)
, ui(new Ui::TxConfDialog) , ui(new Ui::TxConfDialog)
, m_ctx(ctx)
, m_tx(tx) , m_tx(tx)
, m_address(address) , m_address(address)
, m_description(description) , m_description(description)
@@ -32,31 +28,44 @@ TxConfDialog::TxConfDialog(AppContext *ctx, PendingTransaction *tx, const QStrin
}; };
QString amount = WalletManager::displayAmount(tx->amount()); QString amount = WalletManager::displayAmount(tx->amount());
QString amount_fiat = convert(tx->amount() / globals::cdiv); QString amount_fiat = convert(tx->amount() / AppContext::cdiv);
ui->label_amount->setText(QString("%1 (%2 %3)").arg(amount, amount_fiat, preferredCur)); ui->label_amount->setText(QString("%1 (%2 %3)").arg(amount, amount_fiat, preferredCur));
QString fee = WalletManager::displayAmount(tx->fee()); QString fee = WalletManager::displayAmount(tx->fee());
QString fee_fiat = convert(tx->fee() / globals::cdiv); QString fee_fiat = convert(tx->fee() / AppContext::cdiv);
ui->label_fee->setText(QString("%1 (%2 %3)").arg(fee, fee_fiat, preferredCur)); ui->label_fee->setText(QString("%1 (%2 %3)").arg(fee, fee_fiat, preferredCur));
QString total = WalletManager::displayAmount(tx->amount() + tx->fee()); QString total = WalletManager::displayAmount(tx->amount() + tx->fee());
QString total_fiat = convert((tx->amount() + tx->fee()) / globals::cdiv); QString total_fiat = convert((tx->amount() + tx->fee()) / AppContext::cdiv);
ui->label_total->setText(QString("%1 (%2 %3)").arg(total, total_fiat, preferredCur)); ui->label_total->setText(QString("%1 (%2 %3)").arg(total, total_fiat, preferredCur));
ui->label_address->setText(ModelUtils::displayAddress(address, 2)); ui->label_address->setText(ModelUtils::displayAddress(address, 2));
ui->label_address->setFont(ModelUtils::getMonospaceFont()); ui->label_address->setFont(ModelUtils::getMonospaceFont());
ui->label_address->setToolTip(address); ui->label_address->setToolTip(address);
ui->buttonBox->button(QDialogButtonBox::Ok)->setText("Send"); connect(ui->btn_Advanced, &QPushButton::clicked, this, &TxConfDialog::showAdvanced);
connect(ui->btn_Advanced, &QPushButton::clicked, this, &TxConfDialog::setShowAdvanced);
this->adjustSize(); this->adjustSize();
} }
void TxConfDialog::setShowAdvanced() { void TxConfDialog::showAdvanced() {
this->showAdvanced = true; const auto amount = m_tx->amount() / AppContext::cdiv;
QDialog::reject(); const auto fee = m_tx->fee() / AppContext::cdiv;
QString body = QString("Address: %2\n").arg(m_address.left(60));
body += m_address.mid(60) + "\n";
if(!m_description.isEmpty())
body = QString("%1Description: %2\n").arg(body, m_description);
body = QString("%1Amount: %2 XMR\n").arg(body, QString::number(amount));
body = QString("%1Fee: %2 XMR\n").arg(body, QString::number(fee));
body = QString("%1Ringsize: %2").arg(body, QString::number(m_mixin + 1));
auto subaddrIndices = m_tx->subaddrIndices();
for (int i = 0; i < subaddrIndices.count(); ++i){
body = QString("%1\nSpending address index: %2").arg(body, QString::number(subaddrIndices.at(i).toInt()));
}
QMessageBox::information(this, "Transaction information", body);
} }
TxConfDialog::~TxConfDialog() { TxConfDialog::~TxConfDialog() {
+2 -8
View File
@@ -7,7 +7,6 @@
#include <QDialog> #include <QDialog>
#include "libwalletqt/PendingTransaction.h" #include "libwalletqt/PendingTransaction.h"
#include "libwalletqt/WalletManager.h" #include "libwalletqt/WalletManager.h"
#include "appcontext.h"
namespace Ui { namespace Ui {
class TxConfDialog; class TxConfDialog;
@@ -18,18 +17,13 @@ class TxConfDialog : public QDialog
Q_OBJECT Q_OBJECT
public: public:
explicit TxConfDialog(AppContext *ctx, PendingTransaction *tx, const QString &address, const QString &description, int mixin, QWidget *parent = nullptr); explicit TxConfDialog(PendingTransaction *tx, const QString &address, const QString &description, int mixin, QWidget *parent = nullptr);
~TxConfDialog() override; ~TxConfDialog() override;
bool showAdvanced = false;
private: private:
void setShowAdvanced(); void showAdvanced();
void saveToFile();
void copyToClipboard();
Ui::TxConfDialog *ui; Ui::TxConfDialog *ui;
AppContext *m_ctx;
PendingTransaction *m_tx; PendingTransaction *m_tx;
QString m_address; QString m_address;
QString m_description; QString m_description;
+1 -1
View File
@@ -6,7 +6,7 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>844</width> <width>655</width>
<height>248</height> <height>248</height>
</rect> </rect>
</property> </property>
-102
View File
@@ -1,102 +0,0 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2020, The Monero Project.
#include "tximportdialog.h"
#include "ui_tximportdialog.h"
#include <QMessageBox>
TxImportDialog::TxImportDialog(QWidget *parent, AppContext *ctx)
: QDialog(parent)
, m_ctx(ctx)
, m_loadTimer(new QTimer(this))
, ui(new Ui::TxImportDialog)
{
ui->setupUi(this);
ui->resp->hide();
ui->label_loading->hide();
m_network = new UtilsNetworking(m_ctx->network, this);
auto node = ctx->nodes->connection();
m_rpc = new DaemonRpc(this, m_network, node.full);
connect(ui->btn_load, &QPushButton::clicked, this, &TxImportDialog::loadTx);
connect(ui->btn_import, &QPushButton::clicked, this, &TxImportDialog::onImport);
connect(m_rpc, &DaemonRpc::ApiResponse, this, &TxImportDialog::onApiResponse);
connect(m_loadTimer, &QTimer::timeout, [this]{
ui->label_loading->setText(ui->label_loading->text() + ".");
});
this->adjustSize();
}
void TxImportDialog::loadTx() {
QString txid = ui->line_txid->text();
QString node = m_ctx->nodes->connection().full;
if (!node.startsWith("http://"))
node = QString("http://%1").arg(node);
m_rpc->setDaemonAddress(node);
m_rpc->getTransactions(QStringList() << txid, false, true);
ui->label_loading->setText("Loading transaction");
ui->label_loading->setHidden(false);
m_loadTimer->start(1000);
}
void TxImportDialog::onApiResponse(const DaemonRpc::DaemonResponse &resp) {
m_loadTimer->stop();
ui->label_loading->setHidden(true);
if (!resp.ok) {
QMessageBox::warning(this, "Import transaction", resp.status);
return;
}
if (resp.endpoint == DaemonRpc::Endpoint::GET_TRANSACTIONS) {
ui->resp->setVisible(true);
ui->resp->setPlainText(QJsonDocument(resp.obj).toJson(QJsonDocument::Indented));
this->adjustSize();
if (resp.obj.contains("missed_tx")) {
ui->btn_import->setEnabled(false);
QMessageBox::warning(this, "Load transaction", "Transaction could not be found. Make sure the txid is correct, or try connecting to a different node.");
return;
}
QMessageBox::information(this, "Load transaction", "Transaction loaded successfully.\n\nAfter closing this message box click the Import button to import the transaction into your wallet.");
m_transaction = resp.obj;
ui->btn_import->setEnabled(true);
}
}
void TxImportDialog::onImport() {
QJsonObject tx = m_transaction.value("txs").toArray().first().toObject();
QString txid = tx.value("tx_hash").toString();
QVector<quint64> output_indices;
for (const auto &o: tx.value("output_indices").toArray()) {
output_indices.push_back(o.toInt());
}
quint64 height = tx.value("block_height").toInt();
quint64 timestamp = tx.value("block_timestamp").toInt();
bool pool = tx.value("in_pool").toBool();
bool double_spend_seen = tx.value("double_spend_seen").toBool();
if (m_ctx->currentWallet->importTransaction(tx.value("tx_hash").toString(), output_indices, height, timestamp, false, pool, double_spend_seen)) {
QMessageBox::information(this, "Import transaction", "Transaction imported successfully.");
} else {
QMessageBox::warning(this, "Import transaction", "Transaction import failed.");
}
m_ctx->refreshModels();
}
TxImportDialog::~TxImportDialog() {
delete ui;
}
-39
View File
@@ -1,39 +0,0 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2020, The Monero Project.
#ifndef FEATHER_TXIMPORTDIALOG_H
#define FEATHER_TXIMPORTDIALOG_H
#include <QDialog>
#include "appcontext.h"
#include "utils/daemonrpc.h"
namespace Ui {
class TxImportDialog;
}
class TxImportDialog : public QDialog
{
Q_OBJECT
public:
explicit TxImportDialog(QWidget *parent, AppContext *ctx);
~TxImportDialog() override;
private slots:
void loadTx();
void onImport();
void onApiResponse(const DaemonRpc::DaemonResponse &resp);
private:
Ui::TxImportDialog *ui;
UtilsNetworking *m_network;
AppContext *m_ctx;
DaemonRpc *m_rpc;
QTimer *m_loadTimer;
QJsonObject m_transaction;
};
#endif //FEATHER_TXIMPORTDIALOG_H
-115
View File
@@ -1,115 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>TxImportDialog</class>
<widget class="QDialog" name="TxImportDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>700</width>
<height>442</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>700</width>
<height>0</height>
</size>
</property>
<property name="windowTitle">
<string>Import Transaction</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLineEdit" name="line_txid">
<property name="placeholderText">
<string>Transaction ID</string>
</property>
</widget>
</item>
<item>
<widget class="QPlainTextEdit" name="resp">
<property name="readOnly">
<bool>true</bool>
</property>
<property name="placeholderText">
<string>Debug info..</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QPushButton" name="btn_load">
<property name="text">
<string>Load</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btn_import">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Import</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_loading">
<property name="text">
<string>Loading transaction</string>
</property>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Close</set>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>TxImportDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>TxImportDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>
+19 -35
View File
@@ -16,28 +16,26 @@ VerifyProofDialog::VerifyProofDialog(Wallet *wallet, QWidget *parent)
{ {
ui->setupUi(this); ui->setupUi(this);
connect(ui->btn_verify, &QPushButton::clicked, this, &VerifyProofDialog::checkProof); connect(ui->btn_verifySpendProof, &QPushButton::clicked, this, &VerifyProofDialog::checkSpendProof);
connect(ui->btn_verifyOutProof, &QPushButton::clicked, this, &VerifyProofDialog::checkOutProof);
connect(ui->btn_verifyInProof, &QPushButton::clicked, this, &VerifyProofDialog::checkInProof);
connect(ui->btn_clear, &QPushButton::clicked, [this]{ connect(ui->btn_spendClear, &QPushButton::clicked, [this](){
switch (ui->tabWidget->currentIndex()) { ui->lineEdit_spendTxID->clear();
case 0: ui->lineEdit_spendMessage->clear();
ui->lineEdit_spendTxID->clear(); ui->input_SpendProof->clear();
ui->lineEdit_spendMessage->clear(); });
ui->input_SpendProof->clear(); connect(ui->btn_outClear, &QPushButton::clicked, [this](){
break; ui->lineEdit_outTxID->clear();
case 1: ui->lineEdit_outAddress->clear();
ui->lineEdit_outTxID->clear(); ui->lineEdit_outMessage->clear();
ui->lineEdit_outAddress->clear(); ui->input_OutProof->clear();
ui->lineEdit_outMessage->clear(); });
ui->input_OutProof->clear(); connect(ui->btn_inClear, &QPushButton::clicked, [this](){
break; ui->lineEdit_inTxID->clear();
case 2: ui->lineEdit_inAddress->clear();
ui->lineEdit_inTxID->clear(); ui->lineEdit_inMessage->clear();
ui->lineEdit_inAddress->clear(); ui->input_InProof->clear();
ui->lineEdit_inMessage->clear();
ui->input_InProof->clear();
break;
}
}); });
} }
@@ -46,20 +44,6 @@ VerifyProofDialog::~VerifyProofDialog()
delete ui; delete ui;
} }
void VerifyProofDialog::checkProof() {
switch (ui->tabWidget->currentIndex()) {
case 0:
this->checkSpendProof();
break;
case 1:
this->checkOutProof();
break;
case 2:
this->checkInProof();
break;
}
}
void VerifyProofDialog::checkSpendProof() { void VerifyProofDialog::checkSpendProof() {
auto r = m_wallet->checkSpendProof(ui->lineEdit_spendTxID->text(), ui->lineEdit_spendMessage->text(), ui->input_SpendProof->toPlainText()); auto r = m_wallet->checkSpendProof(ui->lineEdit_spendTxID->text(), ui->lineEdit_spendMessage->text(), ui->input_SpendProof->toPlainText());
+3 -4
View File
@@ -20,14 +20,13 @@ public:
~VerifyProofDialog() override; ~VerifyProofDialog() override;
private slots: private slots:
void checkProof();
private:
void checkTxProof(const QString &txId, const QString &address, const QString &message, const QString &signature);
void checkSpendProof(); void checkSpendProof();
void checkOutProof(); void checkOutProof();
void checkInProof(); void checkInProof();
private:
void checkTxProof(const QString &txId, const QString &address, const QString &message, const QString &signature);
Ui::VerifyProofDialog *ui; Ui::VerifyProofDialog *ui;
Wallet *m_wallet; Wallet *m_wallet;
}; };
+108 -49
View File
@@ -39,17 +39,7 @@
</widget> </widget>
</item> </item>
<item> <item>
<layout class="QGridLayout" name="gridLayout_3"> <layout class="QFormLayout" name="formLayout">
<item row="1" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Message:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="lineEdit_spendTxID"/>
</item>
<item row="0" column="0"> <item row="0" column="0">
<widget class="QLabel" name="label_3"> <widget class="QLabel" name="label_3">
<property name="text"> <property name="text">
@@ -57,10 +47,13 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="1"> <item row="0" column="1">
<widget class="QLineEdit" name="lineEdit_spendMessage"> <widget class="QLineEdit" name="lineEdit_spendTxID"/>
<property name="placeholderText"> </item>
<string>Optional message against which the signature is signed</string> <item row="1" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Message:</string>
</property> </property>
</widget> </widget>
</item> </item>
@@ -71,6 +64,13 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="1">
<widget class="QLineEdit" name="lineEdit_spendMessage">
<property name="placeholderText">
<string>Optional message against which the signature is signed</string>
</property>
</widget>
</item>
<item row="2" column="1"> <item row="2" column="1">
<widget class="QPlainTextEdit" name="input_SpendProof"> <widget class="QPlainTextEdit" name="input_SpendProof">
<property name="overwriteMode"> <property name="overwriteMode">
@@ -96,6 +96,37 @@
</property> </property>
</spacer> </spacer>
</item> </item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="btn_spendClear">
<property name="text">
<string>Clear</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btn_verifySpendProof">
<property name="text">
<string>Verify</string>
</property>
</widget>
</item>
</layout>
</item>
</layout> </layout>
</widget> </widget>
<widget class="QWidget" name="OutProof"> <widget class="QWidget" name="OutProof">
@@ -182,6 +213,37 @@
</property> </property>
</spacer> </spacer>
</item> </item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="btn_outClear">
<property name="text">
<string>Clear</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btn_verifyOutProof">
<property name="text">
<string>Verify</string>
</property>
</widget>
</item>
</layout>
</item>
</layout> </layout>
</widget> </widget>
<widget class="QWidget" name="InProof"> <widget class="QWidget" name="InProof">
@@ -269,44 +331,41 @@
</property> </property>
</spacer> </spacer>
</item> </item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="btn_inClear">
<property name="text">
<string>Clear</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btn_verifyInProof">
<property name="text">
<string>Verify</string>
</property>
</widget>
</item>
</layout>
</item>
</layout> </layout>
</widget> </widget>
</widget> </widget>
</item> </item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="btn_clear">
<property name="text">
<string>Clear</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btn_verify">
<property name="text">
<string>Verify</string>
</property>
<property name="default">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
</layout> </layout>
</widget> </widget>
<resources/> <resources/>
-59
View File
@@ -1,59 +0,0 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2020, The Monero Project.
#include <QFileDialog>
#include <QInputDialog>
#include <QMessageBox>
#include "viewonlydialog.h"
#include "ui_viewonlydialog.h"
ViewOnlyDialog::ViewOnlyDialog(AppContext *ctx, QWidget *parent)
: QDialog(parent)
, ui(new Ui::ViewOnlyDialog), m_ctx(ctx)
{
ui->setupUi(this);
ui->label_restoreHeight->setText(QString::number(ctx->currentWallet->getWalletCreationHeight()));
ui->label_primaryAddress->setText(ctx->currentWallet->address(0, 0));
ui->label_secretViewKey->setText(ctx->currentWallet->getSecretViewKey());
connect(ui->btn_Copy, &QPushButton::clicked, this, &ViewOnlyDialog::copyToClipboad);
connect(ui->btn_Save, &QPushButton::clicked, this, &ViewOnlyDialog::onWriteViewOnlyWallet);
ui->btn_Save->setEnabled(!m_ctx->currentWallet->viewOnly());
this->adjustSize();
}
void ViewOnlyDialog::onWriteViewOnlyWallet(){
QString fn = QFileDialog::getSaveFileName(this, "Save .keys wallet file", QDir::homePath(), "Monero wallet (*.keys)");
if(fn.isEmpty()) return;
if(!fn.endsWith(".keys")) fn += ".keys";
QString passwd;
QInputDialog passwordDialog(this);
passwordDialog.setInputMode(QInputDialog::TextInput);
passwordDialog.setTextEchoMode(QLineEdit::Password);
passwordDialog.setWindowTitle("View-Only wallet password");
passwordDialog.setLabelText("Protect this view-only wallet with a password?");
passwordDialog.resize(300, 100);
if((bool)passwordDialog.exec())
passwd = passwordDialog.textValue();
m_ctx->currentWallet->createViewOnly(fn, passwd);
QMessageBox::information(this, "Information", "View-only wallet successfully written to disk.");
}
void ViewOnlyDialog::copyToClipboad() {
QString text = "";
text += QString("Address: %1\n").arg(ui->label_primaryAddress->text());
text += QString("Secret view key: %1\n").arg(ui->label_secretViewKey->text());
text += QString("Restore height: %1\n").arg(ui->label_restoreHeight->text());
Utils::copyToClipboard(text);
}
ViewOnlyDialog::~ViewOnlyDialog()
{
delete ui;
}
-32
View File
@@ -1,32 +0,0 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2020, The Monero Project.
#ifndef FEATHER_VIEWONLYDIALOG_H
#define FEATHER_VIEWONLYDIALOG_H
#include <QDialog>
#include "appcontext.h"
namespace Ui {
class ViewOnlyDialog;
}
class ViewOnlyDialog : public QDialog
{
Q_OBJECT
public:
explicit ViewOnlyDialog(AppContext *ctx, QWidget *parent = nullptr);
~ViewOnlyDialog() override;
private slots:
void onWriteViewOnlyWallet();
private:
Ui::ViewOnlyDialog *ui;
AppContext *m_ctx = nullptr;
void copyToClipboad();
};
#endif //FEATHER_KEYSDIALOG_H
-139
View File
@@ -1,139 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ViewOnlyDialog</class>
<widget class="QDialog" name="ViewOnlyDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>659</width>
<height>254</height>
</rect>
</property>
<property name="windowTitle">
<string>View-Only</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QGroupBox" name="groupBox_6">
<property name="title">
<string>Restore height</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_6">
<item>
<widget class="QLabel" name="label_restoreHeight">
<property name="text">
<string>TextLabel</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Primary address</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label_primaryAddress">
<property name="text">
<string>TextLabel</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>Secret view key</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLabel" name="label_secretViewKey">
<property name="text">
<string>TextLabel</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QPushButton" name="btn_Copy">
<property name="text">
<string>Copy</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btn_Save">
<property name="text">
<string>Create view-only wallet</string>
</property>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>ViewOnlyDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>ViewOnlyDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>
+1 -1
View File
@@ -31,7 +31,7 @@ WalletInfoDialog::WalletInfoDialog(AppContext *ctx, QWidget *parent)
void WalletInfoDialog::openWalletDir() { void WalletInfoDialog::openWalletDir() {
QFileInfo file(m_ctx->walletPath); QFileInfo file(m_ctx->walletPath);
QDesktopServices::openUrl(QUrl(QString("file://%1").arg(file.absolutePath()), QUrl::TolerantMode)); QDesktopServices::openUrl(file.absolutePath());
} }
WalletInfoDialog::~WalletInfoDialog() { WalletInfoDialog::~WalletInfoDialog() {
-14
View File
@@ -1,14 +0,0 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2020, The Monero Project.
#ifndef FEATHER_GLOBALS_H
#define FEATHER_GLOBALS_H
#include <QtGlobal>
namespace globals
{
const qreal cdiv = 1e12;
}
#endif //FEATHER_GLOBALS_H
+5 -10
View File
@@ -25,17 +25,12 @@ HistoryWidget::HistoryWidget(QWidget *parent)
m_copyMenu->addAction("Transaction ID", this, [this]{copy(copyField::TxID);}); m_copyMenu->addAction("Transaction ID", this, [this]{copy(copyField::TxID);});
m_copyMenu->addAction("Date", this, [this]{copy(copyField::Date);}); m_copyMenu->addAction("Date", this, [this]{copy(copyField::Date);});
m_copyMenu->addAction("Amount", this, [this]{copy(copyField::Amount);}); m_copyMenu->addAction("Amount", this, [this]{copy(copyField::Amount);});
auto spendProof = m_copyMenu->addAction("Spend proof", this, &HistoryWidget::getSpendProof); m_copyMenu->addAction("Spend proof", this, &HistoryWidget::getSpendProof);
ui->history->setContextMenuPolicy(Qt::CustomContextMenu); ui->history->setContextMenuPolicy(Qt::CustomContextMenu);
connect(ui->history, &QTreeView::customContextMenuRequested, [=](const QPoint & point){ connect(ui->history, &QTreeView::customContextMenuRequested, [=](const QPoint & point){
QModelIndex index = ui->history->indexAt(point); QModelIndex index = ui->history->indexAt(point);
if (index.isValid()) { if (index.isValid()) {
TransactionInfo::Direction direction;
m_txHistory->transaction(m_model->mapToSource(index).row(), [&direction](TransactionInfo &tInfo) {
direction = tInfo.direction();
});
spendProof->setVisible(direction == TransactionInfo::Direction_Out);
m_contextMenu->exec(ui->history->viewport()->mapToGlobal(point)); m_contextMenu->exec(ui->history->viewport()->mapToGlobal(point));
} }
}); });
@@ -50,11 +45,11 @@ HistoryWidget::HistoryWidget(QWidget *parent)
} }
void HistoryWidget::setModel(TransactionHistoryProxyModel *model, Wallet *wallet) void HistoryWidget::setModel(Coins *coins, TransactionHistoryProxyModel *model, TransactionHistory *txHistory)
{ {
m_coins = coins;
m_model = model; m_model = model;
m_wallet = wallet; m_txHistory = txHistory;
m_txHistory = m_wallet->history();
ui->history->setModel(m_model); ui->history->setModel(m_model);
ui->history->header()->setSectionResizeMode(QHeaderView::ResizeToContents); ui->history->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
@@ -71,7 +66,7 @@ void HistoryWidget::showTxDetails() {
}); });
if (i != nullptr) { if (i != nullptr) {
auto * dialog = new TransactionInfoDialog(m_wallet, i, this); auto * dialog = new TransactionInfoDialog(m_coins, i, this);
dialog->exec(); dialog->exec();
} }
} }
+2 -3
View File
@@ -7,7 +7,6 @@
#include "model/TransactionHistoryModel.h" #include "model/TransactionHistoryModel.h"
#include "model/TransactionHistoryProxyModel.h" #include "model/TransactionHistoryProxyModel.h"
#include "libwalletqt/Coins.h" #include "libwalletqt/Coins.h"
#include "libwalletqt/Wallet.h"
#include <QWidget> #include <QWidget>
#include <QMenu> #include <QMenu>
@@ -22,7 +21,7 @@ Q_OBJECT
public: public:
explicit HistoryWidget(QWidget *parent = nullptr); explicit HistoryWidget(QWidget *parent = nullptr);
void setModel(TransactionHistoryProxyModel *model, Wallet *wallet); void setModel(Coins * coins, TransactionHistoryProxyModel * model, TransactionHistory * txHistory);
~HistoryWidget() override; ~HistoryWidget() override;
public slots: public slots:
@@ -52,7 +51,7 @@ private:
QMenu *m_copyMenu; QMenu *m_copyMenu;
TransactionHistory *m_txHistory; TransactionHistory *m_txHistory;
TransactionHistoryProxyModel *m_model; TransactionHistoryProxyModel *m_model;
Wallet *m_wallet = nullptr; Coins *m_coins;
}; };
#endif //FEATHER_HISTORYWIDGET_H #endif //FEATHER_HISTORYWIDGET_H
-53
View File
@@ -1,53 +0,0 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2014-2020, The Monero Project.
#include "ConstructionInfo.h"
#include "Input.h"
#include "Transfer.h"
quint64 ConstructionInfo::unlockTime() const {
return m_unlockTime;
}
QSet<quint32> ConstructionInfo::subaddressIndices() const {
return m_subaddressIndices;
}
QVector<QString> ConstructionInfo::subaddresses() const {
return m_subaddresses;
}
quint64 ConstructionInfo::minMixinCount() const {
return m_minMixinCount;
}
QList<Input *> ConstructionInfo::inputs() const {
return m_inputs;
}
QList<Transfer *> ConstructionInfo::outputs() const {
return m_outputs;
}
ConstructionInfo::ConstructionInfo(const Monero::TransactionConstructionInfo *pimpl, QObject *parent)
: QObject(parent)
, m_unlockTime(pimpl->unlockTime())
, m_minMixinCount(pimpl->minMixinCount())
{
for (auto const &i : pimpl->inputs())
{
Input *input = new Input(i.amount, QString::fromStdString(i.pubkey), this);
m_inputs.append(input);
}
for (auto const &o : pimpl->outputs())
{
Transfer *output = new Transfer(o.amount, QString::fromStdString(o.address), this);
m_outputs.append(output);
}
for (uint32_t i : pimpl->subaddressIndices())
{
m_subaddressIndices.insert(i);
}
}
-46
View File
@@ -1,46 +0,0 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2014-2020, The Monero Project.
#ifndef FEATHER_CONSTRUCTIONINFO_H
#define FEATHER_CONSTRUCTIONINFO_H
#include <wallet/api/wallet2_api.h>
#include <QObject>
#include <QSet>
class Input;
class Transfer;
class ConstructionInfo : public QObject
{
Q_OBJECT
Q_PROPERTY(quint64 unlockTime READ unlockTime)
Q_PROPERTY(QSet<quint32> subaddressIndices READ subaddressIndices)
Q_PROPERTY(QVector<QString> subaddresses READ subaddresses)
Q_PROPERTY(quint64 minMixinCount READ minMixinCount)
Q_PROPERTY(QList<Input*> inputs READ inputs)
Q_PROPERTY(QList<Transfer*> outputs READ outputs)
public:
quint64 unlockTime() const;
QSet<quint32> subaddressIndices() const;
QVector<QString> subaddresses() const;
quint64 minMixinCount() const;
QList<Input*> inputs() const;
QList<Transfer*> outputs() const;
private:
explicit ConstructionInfo(const Monero::TransactionConstructionInfo *pimpl, QObject *parent = nullptr);
friend class PendingTransactionInfo;
friend class UnsignedTransaction;
quint64 m_unlockTime;
QSet<quint32> m_subaddressIndices;
QVector<QString> m_subaddresses;
quint64 m_minMixinCount;
mutable QList<Input*> m_inputs;
mutable QList<Transfer*> m_outputs;
};
#endif //FEATHER_CONSTRUCTIONINFO_H
-29
View File
@@ -1,29 +0,0 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2014-2020, The Monero Project.
#ifndef FEATHER_INPUT_H
#define FEATHER_INPUT_H
#include <wallet/api/wallet2_api.h>
#include <QObject>
#include <utility>
class Input : public QObject
{
Q_OBJECT
Q_PROPERTY(quint64 amount READ amount)
Q_PROPERTY(QString pubKey READ pubKey)
private:
explicit Input(uint64_t _amount, QString _address, QObject *parent = nullptr): QObject(parent), m_amount(_amount), m_pubkey(std::move(_address)) {};
friend class ConstructionInfo;
quint64 m_amount;
QString m_pubkey;
public:
quint64 amount() const { return m_amount; }
QString pubKey() const { return m_pubkey; }
};
#endif //FEATHER_INPUT_H
+7 -32
View File
@@ -16,12 +16,10 @@ QString PendingTransaction::errorString() const
bool PendingTransaction::commit() bool PendingTransaction::commit()
{ {
return m_pimpl->commit(); // Save transaction to file if fileName is set.
} if(!m_fileName.isEmpty())
return m_pimpl->commit(m_fileName.toStdString());
bool PendingTransaction::saveToFile(const QString &fileName) return m_pimpl->commit(m_fileName.toStdString());
{
return m_pimpl->commit(fileName.toStdString());
} }
quint64 PendingTransaction::amount() const quint64 PendingTransaction::amount() const
@@ -39,6 +37,7 @@ quint64 PendingTransaction::fee() const
return m_pimpl->fee(); return m_pimpl->fee();
} }
QStringList PendingTransaction::txid() const QStringList PendingTransaction::txid() const
{ {
QStringList list; QStringList list;
@@ -64,33 +63,9 @@ QList<QVariant> PendingTransaction::subaddrIndices() const
return result; return result;
} }
QByteArray PendingTransaction::unsignedTxToBin() const { void PendingTransaction::setFilename(const QString &fileName)
return QByteArray::fromStdString(m_pimpl->unsignedTxToBin());
}
QString PendingTransaction::unsignedTxToBase64() const
{ {
return QString::fromStdString(m_pimpl->unsignedTxToBase64()); m_fileName = fileName;
}
QString PendingTransaction::signedTxToHex(int index) const
{
return QString::fromStdString(m_pimpl->signedTxToHex(index));
}
PendingTransactionInfo * PendingTransaction::transaction(int index) const {
return m_pending_tx_info[index];
}
void PendingTransaction::refresh()
{
qDeleteAll(m_pending_tx_info);
m_pending_tx_info.clear();
m_pimpl->refresh();
for (const auto i : m_pimpl->getAll()) {
m_pending_tx_info.append(new PendingTransactionInfo(i, this));
}
} }
PendingTransaction::PendingTransaction(Monero::PendingTransaction *pt, QObject *parent) PendingTransaction::PendingTransaction(Monero::PendingTransaction *pt, QObject *parent)
+4 -12
View File
@@ -9,8 +9,6 @@
#include <QVariant> #include <QVariant>
#include <wallet/api/wallet2_api.h> #include <wallet/api/wallet2_api.h>
#include "PendingTransactionInfo.h"
//namespace Monero { //namespace Monero {
//class PendingTransaction; //class PendingTransaction;
@@ -32,7 +30,7 @@ public:
enum Status { enum Status {
Status_Ok = Monero::PendingTransaction::Status_Ok, Status_Ok = Monero::PendingTransaction::Status_Ok,
Status_Error = Monero::PendingTransaction::Status_Error, Status_Error = Monero::PendingTransaction::Status_Error,
Status_Critical = Monero::PendingTransaction::Status_Critical Status_Critical = Monero::PendingTransaction::Status_Critical
}; };
Q_ENUM(Status) Q_ENUM(Status)
@@ -47,27 +45,21 @@ public:
Status status() const; Status status() const;
QString errorString() const; QString errorString() const;
Q_INVOKABLE bool commit(); Q_INVOKABLE bool commit();
bool saveToFile(const QString &fileName);
quint64 amount() const; quint64 amount() const;
quint64 dust() const; quint64 dust() const;
quint64 fee() const; quint64 fee() const;
QStringList txid() const; QStringList txid() const;
quint64 txCount() const; quint64 txCount() const;
QList<QVariant> subaddrIndices() const; QList<QVariant> subaddrIndices() const;
QByteArray unsignedTxToBin() const; Q_INVOKABLE void setFilename(const QString &fileName);
QString unsignedTxToBase64() const;
QString signedTxToHex(int index) const;
void refresh();
PendingTransactionInfo * transaction(int index) const;
private: private:
explicit PendingTransaction(Monero::PendingTransaction * pt, QObject *parent = nullptr); explicit PendingTransaction(Monero::PendingTransaction * pt, QObject *parent = 0);
private: private:
friend class Wallet; friend class Wallet;
Monero::PendingTransaction * m_pimpl; Monero::PendingTransaction * m_pimpl;
mutable QList<PendingTransactionInfo*> m_pending_tx_info; QString m_fileName;
}; };
#endif // PENDINGTRANSACTION_H #endif // PENDINGTRANSACTION_H
@@ -1,32 +0,0 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2014-2020, The Monero Project.
#include "PendingTransactionInfo.h"
#include "Input.h"
#include "Transfer.h"
quint64 PendingTransactionInfo::fee() const {
return m_fee;
}
quint64 PendingTransactionInfo::dust() const {
return m_dust;
}
bool PendingTransactionInfo::dustAddedToFee() const {
return m_dustAddedToFee;
}
QString PendingTransactionInfo::txKey() const {
return m_txKey;
}
PendingTransactionInfo::PendingTransactionInfo(const Monero::PendingTransactionInfo *pimpl, QObject *parent)
: ConstructionInfo(pimpl->constructionData(), parent)
, m_fee(pimpl->fee())
, m_dust(pimpl->dust())
, m_dustAddedToFee(pimpl->dustAddedToFee())
, m_txKey(QString::fromStdString(pimpl->txKey()))
{
}
-46
View File
@@ -1,46 +0,0 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2014-2020, The Monero Project.
#ifndef FEATHER_PENDINGTRANSACTIONINFO_H
#define FEATHER_PENDINGTRANSACTIONINFO_H
#include <wallet/api/wallet2_api.h>
#include "ConstructionInfo.h"
#include <QObject>
#include <QSet>
class Input;
class Transfer;
class PendingTransactionInfo : public ConstructionInfo
{
Q_OBJECT
Q_PROPERTY(quint64 fee READ fee)
Q_PROPERTY(quint64 dust READ dust)
Q_PROPERTY(bool dustAddedToFee READ dustAddedToFee)
Q_PROPERTY(QString txKey READ txKey)
Q_PROPERTY(quint64 unlockTime READ unlockTime)
Q_PROPERTY(QSet<quint32> subaddressIndices READ subaddressIndices)
Q_PROPERTY(QVector<QString> subaddresses READ subaddresses)
Q_PROPERTY(quint64 minMixinCount READ minMixinCount)
Q_PROPERTY(QList<Input*> inputs READ inputs)
Q_PROPERTY(QList<Transfer*> outputs READ outputs)
public:
quint64 fee() const;
quint64 dust() const;
bool dustAddedToFee() const;
QString txKey() const;
private:
explicit PendingTransactionInfo(const Monero::PendingTransactionInfo *pimpl, QObject *parent = nullptr);
friend class PendingTransaction;
quint64 m_fee;
quint64 m_dust;
bool m_dustAddedToFee;
QString m_txKey;
};
#endif //FEATHER_PENDINGTRANSACTIONINFO_H
-19
View File
@@ -28,11 +28,6 @@ bool TransactionInfo::isCoinbase() const
return m_coinbase; return m_coinbase;
} }
quint64 TransactionInfo::balanceDelta() const
{
return m_amount + m_fee;
}
double TransactionInfo::amount() const double TransactionInfo::amount() const
{ {
// there's no unsigned uint64 for JS, so better use double // there's no unsigned uint64 for JS, so better use double
@@ -49,11 +44,6 @@ QString TransactionInfo::displayAmount() const
return WalletManager::displayAmount(m_amount); return WalletManager::displayAmount(m_amount);
} }
quint64 TransactionInfo::atomicFee() const
{
return m_fee;
}
QString TransactionInfo::fee() const QString TransactionInfo::fee() const
{ {
if(m_fee == 0) if(m_fee == 0)
@@ -137,15 +127,6 @@ QString TransactionInfo::destinations_formatted() const
return destinations; return destinations;
} }
QList<QString> TransactionInfo::destinations() const
{
QList<QString> dests;
for (auto const& t: m_transfers) {
dests.append(t->address());
}
return dests;
}
QString TransactionInfo::rings_formatted() const QString TransactionInfo::rings_formatted() const
{ {
QString rings; QString rings;
-3
View File
@@ -52,12 +52,10 @@ public:
bool isPending() const; bool isPending() const;
bool isFailed() const; bool isFailed() const;
bool isCoinbase() const; bool isCoinbase() const;
quint64 balanceDelta() const;
double amount() const; double amount() const;
quint64 atomicAmount() const; quint64 atomicAmount() const;
QString displayAmount() const; QString displayAmount() const;
QString fee() const; QString fee() const;
quint64 atomicFee() const;
quint64 blockHeight() const; quint64 blockHeight() const;
QString description() const; QString description() const;
QSet<quint32> subaddrIndex() const; QSet<quint32> subaddrIndex() const;
@@ -74,7 +72,6 @@ public:
QString paymentId() const; QString paymentId() const;
//! only applicable for output transactions //! only applicable for output transactions
//! used in tx details popup //! used in tx details popup
QList<QString> destinations() const;
QString destinations_formatted() const; QString destinations_formatted() const;
QString rings_formatted() const; QString rings_formatted() const;
-1
View File
@@ -17,7 +17,6 @@ private:
explicit Transfer(uint64_t _amount, QString _address, QObject *parent = 0): QObject(parent), m_amount(_amount), m_address(std::move(_address)) {}; explicit Transfer(uint64_t _amount, QString _address, QObject *parent = 0): QObject(parent), m_amount(_amount), m_address(std::move(_address)) {};
private: private:
friend class TransactionInfo; friend class TransactionInfo;
friend class ConstructionInfo;
quint64 m_amount; quint64 m_amount;
QString m_address; QString m_address;
public: public:
-15
View File
@@ -83,21 +83,6 @@ void UnsignedTransaction::setFilename(const QString &fileName)
m_fileName = fileName; m_fileName = fileName;
} }
ConstructionInfo * UnsignedTransaction::constructionInfo(int index) const {
return m_construction_info[index];
}
void UnsignedTransaction::refresh()
{
qDeleteAll(m_construction_info);
m_construction_info.clear();
m_pimpl->refresh();
for (const auto i : m_pimpl->getAll()) {
m_construction_info.append(new ConstructionInfo(i, this));
}
}
UnsignedTransaction::UnsignedTransaction(Monero::UnsignedTransaction *pt, Monero::Wallet *walletImpl, QObject *parent) UnsignedTransaction::UnsignedTransaction(Monero::UnsignedTransaction *pt, Monero::Wallet *walletImpl, QObject *parent)
: QObject(parent), m_pimpl(pt), m_walletImpl(walletImpl) : QObject(parent), m_pimpl(pt), m_walletImpl(walletImpl)
{ {
+3 -6
View File
@@ -7,13 +7,14 @@
#include <QObject> #include <QObject>
#include <wallet/api/wallet2_api.h> #include <wallet/api/wallet2_api.h>
#include "libwalletqt/PendingTransactionInfo.h"
class UnsignedTransaction : public QObject class UnsignedTransaction : public QObject
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY(Status status READ status) Q_PROPERTY(Status status READ status)
Q_PROPERTY(QString errorString READ errorString) Q_PROPERTY(QString errorString READ errorString)
// Q_PROPERTY(QList<qulonglong> amount READ amount)
// Q_PROPERTY(QList<qulonglong> fee READ fee)
Q_PROPERTY(quint64 txCount READ txCount) Q_PROPERTY(quint64 txCount READ txCount)
Q_PROPERTY(QString confirmationMessage READ confirmationMessage) Q_PROPERTY(QString confirmationMessage READ confirmationMessage)
Q_PROPERTY(QStringList recipientAddress READ recipientAddress) Q_PROPERTY(QStringList recipientAddress READ recipientAddress)
@@ -40,19 +41,15 @@ public:
quint64 minMixinCount() const; quint64 minMixinCount() const;
Q_INVOKABLE bool sign(const QString &fileName) const; Q_INVOKABLE bool sign(const QString &fileName) const;
Q_INVOKABLE void setFilename(const QString &fileName); Q_INVOKABLE void setFilename(const QString &fileName);
void refresh();
ConstructionInfo * constructionInfo(int index) const;
private: private:
explicit UnsignedTransaction(Monero::UnsignedTransaction * pt, Monero::Wallet *walletImpl, QObject *parent = nullptr); explicit UnsignedTransaction(Monero::UnsignedTransaction * pt, Monero::Wallet *walletImpl, QObject *parent = 0);
~UnsignedTransaction(); ~UnsignedTransaction();
private: private:
friend class Wallet; friend class Wallet;
Monero::UnsignedTransaction * m_pimpl; Monero::UnsignedTransaction * m_pimpl;
QString m_fileName; QString m_fileName;
Monero::Wallet * m_walletImpl; Monero::Wallet * m_walletImpl;
mutable QList<ConstructionInfo*> m_construction_info;
}; };
#endif // UNSIGNEDTRANSACTION_H #endif // UNSIGNEDTRANSACTION_H
+141 -282
View File
@@ -2,11 +2,6 @@
// Copyright (c) 2014-2020, The Monero Project. // Copyright (c) 2014-2020, The Monero Project.
#include "Wallet.h" #include "Wallet.h"
#include <chrono>
#include <stdexcept>
#include <thread>
#include "PendingTransaction.h" #include "PendingTransaction.h"
#include "UnsignedTransaction.h" #include "UnsignedTransaction.h"
#include "TransactionHistory.h" #include "TransactionHistory.h"
@@ -32,8 +27,6 @@
#include <QVector> #include <QVector>
#include <QMutexLocker> #include <QMutexLocker>
#include "utils/ScopeGuard.h"
namespace { namespace {
static const int DAEMON_BLOCKCHAIN_HEIGHT_CACHE_TTL_SECONDS = 5; static const int DAEMON_BLOCKCHAIN_HEIGHT_CACHE_TTL_SECONDS = 5;
static const int DAEMON_BLOCKCHAIN_TARGET_HEIGHT_CACHE_TTL_SECONDS = 30; static const int DAEMON_BLOCKCHAIN_TARGET_HEIGHT_CACHE_TTL_SECONDS = 30;
@@ -43,15 +36,10 @@ namespace {
} }
Wallet::Wallet(QObject * parent) Wallet::Wallet(QObject * parent)
: Wallet(nullptr, parent) : Wallet(nullptr, parent)
{ {
} }
Wallet::ConnectionStatus Wallet::connectionStatus() const
{
return m_connectionStatus;
}
QString Wallet::getSeed() const QString Wallet::getSeed() const
{ {
return QString::fromStdString(m_walletImpl->seed()); return QString::fromStdString(m_walletImpl->seed());
@@ -77,28 +65,41 @@ NetworkType::Type Wallet::nettype() const
return static_cast<NetworkType::Type>(m_walletImpl->nettype()); return static_cast<NetworkType::Type>(m_walletImpl->nettype());
} }
void Wallet::updateConnectionStatusAsync()
{
m_scheduler.run([this] {
if (m_connectionStatus == Wallet::ConnectionStatus_Disconnected)
{
setConnectionStatus(ConnectionStatus_Connecting);
}
ConnectionStatus newStatus = static_cast<ConnectionStatus>(m_walletImpl->connected());
if (newStatus != m_connectionStatus || !m_initialized) {
m_initialized = true;
setConnectionStatus(newStatus);
}
// Release lock
m_connectionStatusRunning = false;
});
}
Wallet::ConnectionStatus Wallet::connected(bool forceCheck)
{
// cache connection status
if (forceCheck || !m_initialized || (m_connectionStatusTime.elapsed() / 1000 > m_connectionStatusTtl && !m_connectionStatusRunning) || m_connectionStatusTime.elapsed() > 30000) {
m_connectionStatusRunning = true;
m_connectionStatusTime.restart();
updateConnectionStatusAsync();
}
return m_connectionStatus;
}
bool Wallet::disconnected() const bool Wallet::disconnected() const
{ {
return m_disconnected; return m_disconnected;
} }
bool Wallet::refreshing() const
{
return m_refreshing;
}
void Wallet::refreshingSet(bool value)
{
if (m_refreshing.exchange(value) != value)
{
emit refreshingChanged();
}
}
void Wallet::setConnectionTimeout(int timeout) {
m_connectionTimeout = timeout;
}
void Wallet::setConnectionStatus(ConnectionStatus value) void Wallet::setConnectionStatus(ConnectionStatus value)
{ {
if (m_connectionStatus == value) if (m_connectionStatus == value)
@@ -110,7 +111,7 @@ void Wallet::setConnectionStatus(ConnectionStatus value)
emit connectionStatusChanged(m_connectionStatus); emit connectionStatusChanged(m_connectionStatus);
bool disconnected = m_connectionStatus == Wallet::ConnectionStatus_Connecting || bool disconnected = m_connectionStatus == Wallet::ConnectionStatus_Connecting ||
m_connectionStatus == Wallet::ConnectionStatus_Disconnected; m_connectionStatus == Wallet::ConnectionStatus_Disconnected;
if (m_disconnected != disconnected) if (m_disconnected != disconnected)
{ {
@@ -119,29 +120,6 @@ void Wallet::setConnectionStatus(ConnectionStatus value)
} }
} }
QString Wallet::getProxyAddress() const
{
QMutexLocker locker(&m_proxyMutex);
return m_proxyAddress;
}
void Wallet::setProxyAddress(QString address)
{
m_scheduler.run([this, address] {
{
QMutexLocker locker(&m_proxyMutex);
if (!m_walletImpl->setProxy(address.toStdString()))
{
qCritical() << "failed to set proxy" << address;
}
m_proxyAddress = address;
}
emit proxyAddressChanged();
});
}
bool Wallet::synchronized() const bool Wallet::synchronized() const
{ {
return m_walletImpl->synchronized(); return m_walletImpl->synchronized();
@@ -157,11 +135,6 @@ bool Wallet::setPassword(const QString &password)
return m_walletImpl->setPassword(password.toStdString()); return m_walletImpl->setPassword(password.toStdString());
} }
QString Wallet::getPassword()
{
return QString::fromStdString(m_walletImpl->getPassword());
}
QString Wallet::address(quint32 accountIndex, quint32 addressIndex) const QString Wallet::address(quint32 accountIndex, quint32 addressIndex) const
{ {
return QString::fromStdString(m_walletImpl->address(accountIndex, addressIndex)); return QString::fromStdString(m_walletImpl->address(accountIndex, addressIndex));
@@ -172,18 +145,20 @@ QString Wallet::path() const
return QDir::toNativeSeparators(QString::fromStdString(m_walletImpl->path())); return QDir::toNativeSeparators(QString::fromStdString(m_walletImpl->path()));
} }
//void Wallet::storeAsync(const QJSValue &callback, const QString &path /* = "" */)
//void Wallet::storeAsync(const QVariant &callback, const QString &path /* = "" */)
//{ //{
// const auto future = m_scheduler.run( // const auto future = m_scheduler.run(
// [this, path] { // [this, path] {
// QMutexLocker locker(&m_asyncMutex); // QMutexLocker locker(&m_storeMutex);
//
// return QJSValueList({m_walletImpl->store(path.toStdString())}); // return QVariantList({m_walletImpl->store(path.toStdString())});
// }, // },
// callback); // callback);
// if (!future.first) // if (!future.first)
// { // {
// QJSValue(callback).call(QJSValueList({false})); // QVariant(callback).call(QVariantList({false}));
// } // }
//} //}
@@ -192,7 +167,7 @@ void Wallet::store(const QString &path)
m_walletImpl->store(path.toStdString()); m_walletImpl->store(path.toStdString());
} }
bool Wallet::init(const QString &daemonAddress, bool trustedDaemon, quint64 upperTransactionLimit, bool isRecovering, bool isRecoveringFromDevice, quint64 restoreHeight, const QString& proxyAddress) bool Wallet::init(const QString &daemonAddress, bool trustedDaemon, quint64 upperTransactionLimit, bool isRecovering, bool isRecoveringFromDevice, quint64 restoreHeight)
{ {
qDebug() << "init non async"; qDebug() << "init non async";
if (isRecovering){ if (isRecovering){
@@ -206,20 +181,7 @@ bool Wallet::init(const QString &daemonAddress, bool trustedDaemon, quint64 uppe
if (isRecovering || isRecoveringFromDevice) { if (isRecovering || isRecoveringFromDevice) {
m_walletImpl->setRefreshFromBlockHeight(restoreHeight); m_walletImpl->setRefreshFromBlockHeight(restoreHeight);
} }
m_walletImpl->init(daemonAddress.toStdString(), upperTransactionLimit, m_daemonUsername.toStdString(), m_daemonPassword.toStdString());
{
QMutexLocker locker(&m_proxyMutex);
if (!m_walletImpl->init(daemonAddress.toStdString(), upperTransactionLimit, m_daemonUsername.toStdString(), m_daemonPassword.toStdString(), m_useSSL, false, proxyAddress.toStdString()))
{
return false;
}
m_proxyAddress = proxyAddress;
}
emit proxyAddressChanged();
setTrustedDaemon(trustedDaemon);
setTrustedDaemon(trustedDaemon); setTrustedDaemon(trustedDaemon);
return true; return true;
} }
@@ -231,24 +193,17 @@ void Wallet::setDaemonLogin(const QString &daemonUsername, const QString &daemon
m_daemonPassword = daemonPassword; m_daemonPassword = daemonPassword;
} }
void Wallet::initAsync( void Wallet::initAsync(const QString &daemonAddress, bool trustedDaemon, quint64 upperTransactionLimit, bool isRecovering, bool isRecoveringFromDevice, quint64 restoreHeight)
const QString &daemonAddress,
bool trustedDaemon /* = false */,
quint64 upperTransactionLimit /* = 0 */,
bool isRecovering /* = false */,
bool isRecoveringFromDevice /* = false */,
quint64 restoreHeight /* = 0 */,
const QString &proxyAddress /* = "" */)
{ {
qDebug() << "initAsync: " + daemonAddress; qDebug() << "initAsync: " + daemonAddress;
const auto future = m_scheduler.run([this, daemonAddress, trustedDaemon, upperTransactionLimit, isRecovering, isRecoveringFromDevice, restoreHeight, proxyAddress] { const auto future = m_scheduler.run([this, daemonAddress, trustedDaemon, upperTransactionLimit, isRecovering, isRecoveringFromDevice, restoreHeight] {
bool success = init(daemonAddress, trustedDaemon, upperTransactionLimit, isRecovering, isRecoveringFromDevice, restoreHeight, proxyAddress); bool success = init(daemonAddress, trustedDaemon, upperTransactionLimit, isRecovering, isRecoveringFromDevice, restoreHeight);
if (success) if (success)
{ {
emit walletCreationHeightChanged(); emit walletCreationHeightChanged();
qDebug() << "init async finished - starting refresh"; qDebug() << "init async finished - starting refresh";
refreshHeightAsync(); connected(true);
startRefresh(); m_walletImpl->startRefresh();
} }
}); });
if (future.first) if (future.first)
@@ -291,11 +246,6 @@ void Wallet::setTrustedDaemon(bool arg)
m_walletImpl->setTrustedDaemon(arg); m_walletImpl->setTrustedDaemon(arg);
} }
void Wallet::setUseSSL(bool ssl)
{
m_useSSL = ssl;
}
bool Wallet::viewOnly() const bool Wallet::viewOnly() const
{ {
return m_walletImpl->watchOnly(); return m_walletImpl->watchOnly();
@@ -408,8 +358,6 @@ void Wallet::refreshHeightAsync()
daemonHeightFuture.second.waitForFinished(); daemonHeightFuture.second.waitForFinished();
targetHeightFuture.second.waitForFinished(); targetHeightFuture.second.waitForFinished();
setConnectionStatus(ConnectionStatus_Connected);
emit heightRefreshed(walletHeight, daemonHeight, targetHeight); emit heightRefreshed(walletHeight, daemonHeight, targetHeight);
}); });
} }
@@ -424,8 +372,7 @@ quint64 Wallet::daemonBlockChainHeight() const
// cache daemon blockchain height for some time (60 seconds by default) // cache daemon blockchain height for some time (60 seconds by default)
if (m_daemonBlockChainHeight == 0 if (m_daemonBlockChainHeight == 0
|| m_daemonBlockChainHeightTime.elapsed() / 1000 > m_daemonBlockChainHeightTtl) || m_daemonBlockChainHeightTime.elapsed() / 1000 > m_daemonBlockChainHeightTtl) {
{
m_daemonBlockChainHeight = m_walletImpl->daemonBlockChainHeight(); m_daemonBlockChainHeight = m_walletImpl->daemonBlockChainHeight();
m_daemonBlockChainHeightTime.restart(); m_daemonBlockChainHeightTime.restart();
} }
@@ -435,8 +382,7 @@ quint64 Wallet::daemonBlockChainHeight() const
quint64 Wallet::daemonBlockChainTargetHeight() const quint64 Wallet::daemonBlockChainTargetHeight() const
{ {
if (m_daemonBlockChainTargetHeight <= 1 if (m_daemonBlockChainTargetHeight <= 1
|| m_daemonBlockChainTargetHeightTime.elapsed() / 1000 > m_daemonBlockChainTargetHeightTtl) || m_daemonBlockChainTargetHeightTime.elapsed() / 1000 > m_daemonBlockChainTargetHeightTtl) {
{
m_daemonBlockChainTargetHeight = m_walletImpl->daemonBlockChainTargetHeight(); m_daemonBlockChainTargetHeight = m_walletImpl->daemonBlockChainTargetHeight();
// Target height is set to 0 if daemon is synced. // Target height is set to 0 if daemon is synced.
@@ -450,9 +396,9 @@ quint64 Wallet::daemonBlockChainTargetHeight() const
return m_daemonBlockChainTargetHeight; return m_daemonBlockChainTargetHeight;
} }
bool Wallet::exportKeyImages(const QString& path, bool all) bool Wallet::exportKeyImages(const QString& path)
{ {
return m_walletImpl->exportKeyImages(path.toStdString(), all); return m_walletImpl->exportKeyImages(path.toStdString());
} }
bool Wallet::importKeyImages(const QString& path) bool Wallet::importKeyImages(const QString& path)
@@ -460,40 +406,42 @@ bool Wallet::importKeyImages(const QString& path)
return m_walletImpl->importKeyImages(path.toStdString()); return m_walletImpl->importKeyImages(path.toStdString());
} }
bool Wallet::exportOutputs(const QString& path, bool all) { bool Wallet::refresh()
return m_walletImpl->exportOutputs(path.toStdString(), all);
}
bool Wallet::importOutputs(const QString& path) {
return m_walletImpl->importOutputs(path.toStdString());
}
bool Wallet::importTransaction(const QString& txid, const QVector<quint64>& output_indeces, quint64 height, quint64 timestamp, bool miner_tx, bool pool, bool double_spend_seen) {
std::vector<uint64_t> o_indeces;
for (const auto &o : output_indeces) {
o_indeces.push_back(o);
}
return m_walletImpl->importTransaction(
txid.toStdString(),
o_indeces,
height,
17, // todo: get actual block_version
timestamp,
miner_tx,
pool,
double_spend_seen);
}
void Wallet::startRefresh()
{ {
m_refreshEnabled = true; bool result = m_walletImpl->refresh();
m_refreshNow = true; m_history->refresh(currentSubaddressAccount());
m_subaddress->refresh(currentSubaddressAccount());
m_coins->refresh(currentSubaddressAccount());
m_subaddressAccount->getAll();
if (result)
emit updated();
return result;
} }
void Wallet::pauseRefresh() void Wallet::refreshAsync()
{ {
m_refreshEnabled = false; qDebug() << "refresh async";
m_walletImpl->refreshAsync();
}
void Wallet::setAutoRefreshInterval(int seconds)
{
m_walletImpl->setAutoRefreshInterval(seconds);
}
int Wallet::autoRefreshInterval() const
{
return m_walletImpl->autoRefreshInterval();
}
void Wallet::startRefresh() const
{
m_walletImpl->startRefresh();
}
void Wallet::pauseRefresh() const
{
m_walletImpl->pauseRefresh();
} }
PendingTransaction *Wallet::createTransaction(const QString &dst_addr, const QString &payment_id, PendingTransaction *Wallet::createTransaction(const QString &dst_addr, const QString &payment_id,
@@ -502,15 +450,15 @@ PendingTransaction *Wallet::createTransaction(const QString &dst_addr, const QSt
{ {
std::set<uint32_t> subaddr_indices; std::set<uint32_t> subaddr_indices;
Monero::PendingTransaction * ptImpl = m_walletImpl->createTransaction( Monero::PendingTransaction * ptImpl = m_walletImpl->createTransaction(
dst_addr.toStdString(), payment_id.toStdString(), amount, mixin_count, dst_addr.toStdString(), payment_id.toStdString(), amount, mixin_count,
static_cast<Monero::PendingTransaction::Priority>(priority), currentSubaddressAccount(), subaddr_indices); static_cast<Monero::PendingTransaction::Priority>(priority), currentSubaddressAccount(), subaddr_indices);
PendingTransaction * result = new PendingTransaction(ptImpl,0); PendingTransaction * result = new PendingTransaction(ptImpl,0);
return result; return result;
} }
void Wallet::createTransactionAsync(const QString &dst_addr, const QString &payment_id, void Wallet::createTransactionAsync(const QString &dst_addr, const QString &payment_id,
quint64 amount, quint32 mixin_count, quint64 amount, quint32 mixin_count,
PendingTransaction::Priority priority) PendingTransaction::Priority priority)
{ {
m_scheduler.run([this, dst_addr, payment_id, amount, mixin_count, priority] { m_scheduler.run([this, dst_addr, payment_id, amount, mixin_count, priority] {
PendingTransaction *tx = createTransaction(dst_addr, payment_id, amount, mixin_count, priority); PendingTransaction *tx = createTransaction(dst_addr, payment_id, amount, mixin_count, priority);
@@ -523,15 +471,15 @@ PendingTransaction *Wallet::createTransactionAll(const QString &dst_addr, const
{ {
std::set<uint32_t> subaddr_indices; std::set<uint32_t> subaddr_indices;
Monero::PendingTransaction * ptImpl = m_walletImpl->createTransaction( Monero::PendingTransaction * ptImpl = m_walletImpl->createTransaction(
dst_addr.toStdString(), payment_id.toStdString(), Monero::optional<uint64_t>(), mixin_count, dst_addr.toStdString(), payment_id.toStdString(), Monero::optional<uint64_t>(), mixin_count,
static_cast<Monero::PendingTransaction::Priority>(priority), currentSubaddressAccount(), subaddr_indices); static_cast<Monero::PendingTransaction::Priority>(priority), currentSubaddressAccount(), subaddr_indices);
PendingTransaction * result = new PendingTransaction(ptImpl, this); PendingTransaction * result = new PendingTransaction(ptImpl, this);
return result; return result;
} }
void Wallet::createTransactionAllAsync(const QString &dst_addr, const QString &payment_id, void Wallet::createTransactionAllAsync(const QString &dst_addr, const QString &payment_id,
quint32 mixin_count, quint32 mixin_count,
PendingTransaction::Priority priority) PendingTransaction::Priority priority)
{ {
m_scheduler.run([this, dst_addr, payment_id, mixin_count, priority] { m_scheduler.run([this, dst_addr, payment_id, mixin_count, priority] {
PendingTransaction *tx = createTransactionAll(dst_addr, payment_id, mixin_count, priority); PendingTransaction *tx = createTransactionAll(dst_addr, payment_id, mixin_count, priority);
@@ -553,7 +501,7 @@ void Wallet::createTransactionSingleAsync(const QString &key_image, const QStrin
{ {
m_scheduler.run([this, key_image, dst_addr, outputs, priority] { m_scheduler.run([this, key_image, dst_addr, outputs, priority] {
PendingTransaction *tx = createTransactionSingle(key_image, dst_addr, outputs, priority); PendingTransaction *tx = createTransactionSingle(key_image, dst_addr, outputs, priority);
emit transactionCreated(tx, dst_addr, "", 10); // todo: return true mixincount emit transactionCreated(tx, dst_addr, "", 0); // todo: return true mixincount
}); });
} }
@@ -580,21 +528,6 @@ UnsignedTransaction * Wallet::loadTxFile(const QString &fileName)
return result; return result;
} }
UnsignedTransaction * Wallet::loadTxFromBase64Str(const QString &unsigned_tx)
{
Monero::UnsignedTransaction * ptImpl = m_walletImpl->loadUnsignedTxFromBase64Str(unsigned_tx.toStdString());
UnsignedTransaction * result = new UnsignedTransaction(ptImpl, m_walletImpl, this);
return result;
}
PendingTransaction * Wallet::loadSignedTxFile(const QString &fileName)
{
qDebug() << "Tying to load " << fileName;
Monero::PendingTransaction * ptImpl = m_walletImpl->loadSignedTx(fileName.toStdString());
PendingTransaction * result = new PendingTransaction(ptImpl, this);
return result;
}
bool Wallet::submitTxFile(const QString &fileName) const bool Wallet::submitTxFile(const QString &fileName) const
{ {
qDebug() << "Trying to submit " << fileName; qDebug() << "Trying to submit " << fileName;
@@ -604,28 +537,6 @@ bool Wallet::submitTxFile(const QString &fileName) const
return m_walletImpl->importKeyImages(fileName.toStdString() + "_keyImages"); return m_walletImpl->importKeyImages(fileName.toStdString() + "_keyImages");
} }
bool Wallet::refresh(bool historyAndSubaddresses /* = true */)
{
refreshingSet(true);
const auto cleanup = sg::make_scope_guard([this]() noexcept {
refreshingSet(false);
});
{
QMutexLocker locker(&m_asyncMutex);
bool result = m_walletImpl->refresh();
if (historyAndSubaddresses)
{
m_history->refresh(currentSubaddressAccount());
m_subaddress->refresh(currentSubaddressAccount());
m_subaddressAccount->getAll();
}
return result;
}
}
void Wallet::commitTransactionAsync(PendingTransaction *t) void Wallet::commitTransactionAsync(PendingTransaction *t)
{ {
m_scheduler.run([this, t] { m_scheduler.run([this, t] {
@@ -645,6 +556,7 @@ void Wallet::disposeTransaction(UnsignedTransaction *t)
delete t; delete t;
} }
// @ TODO: QJSValue could probably be QVARIANT
//void Wallet::estimateTransactionFeeAsync(const QString &destination, //void Wallet::estimateTransactionFeeAsync(const QString &destination,
// quint64 amount, // quint64 amount,
// PendingTransaction::Priority priority, // PendingTransaction::Priority priority,
@@ -652,8 +564,8 @@ void Wallet::disposeTransaction(UnsignedTransaction *t)
//{ //{
// m_scheduler.run([this, destination, amount, priority] { // m_scheduler.run([this, destination, amount, priority] {
// const uint64_t fee = m_walletImpl->estimateTransactionFee( // const uint64_t fee = m_walletImpl->estimateTransactionFee(
// {std::make_pair(destination.toStdString(), amount)}, // {std::make_pair(destination.toStdString(), amount)},
// static_cast<Monero::PendingTransaction::Priority>(priority)); // static_cast<Monero::PendingTransaction::Priority>(priority));
// return QJSValueList({QString::fromStdString(Monero::Wallet::displayAmount(fee))}); // return QJSValueList({QString::fromStdString(Monero::Wallet::displayAmount(fee))});
// }, callback); // }, callback);
//} //}
@@ -771,17 +683,17 @@ bool Wallet::setCacheAttribute(const QString &key, const QString &val)
bool Wallet::setUserNote(const QString &txid, const QString &note) bool Wallet::setUserNote(const QString &txid, const QString &note)
{ {
return m_walletImpl->setUserNote(txid.toStdString(), note.toStdString()); return m_walletImpl->setUserNote(txid.toStdString(), note.toStdString());
} }
QString Wallet::getUserNote(const QString &txid) const QString Wallet::getUserNote(const QString &txid) const
{ {
return QString::fromStdString(m_walletImpl->getUserNote(txid.toStdString())); return QString::fromStdString(m_walletImpl->getUserNote(txid.toStdString()));
} }
QString Wallet::getTxKey(const QString &txid) const QString Wallet::getTxKey(const QString &txid) const
{ {
return QString::fromStdString(m_walletImpl->getTxKey(txid.toStdString())); return QString::fromStdString(m_walletImpl->getTxKey(txid.toStdString()));
} }
//void Wallet::getTxKeyAsync(const QString &txid, const QJSValue &callback) //void Wallet::getTxKeyAsync(const QString &txid, const QJSValue &callback)
@@ -801,10 +713,12 @@ QString Wallet::checkTxKey(const QString &txid, const QString &tx_key, const QSt
return QString::fromStdString(result); return QString::fromStdString(result);
} }
TxProof Wallet::getTxProof(const QString &txid, const QString &address, const QString &message) const QString Wallet::getTxProof(const QString &txid, const QString &address, const QString &message) const
{ {
std::string result = m_walletImpl->getTxProof(txid.toStdString(), address.toStdString(), message.toStdString()); std::string result = m_walletImpl->getTxProof(txid.toStdString(), address.toStdString(), message.toStdString());
return TxProof(QString::fromStdString(result), QString::fromStdString(m_walletImpl->errorString())); if (result.empty())
result = "error|" + m_walletImpl->errorString();
return QString::fromStdString(result);
} }
//void Wallet::getTxProofAsync(const QString &txid, const QString &address, const QString &message, const QJSValue &callback) //void Wallet::getTxProofAsync(const QString &txid, const QString &address, const QString &message, const QJSValue &callback)
@@ -824,10 +738,12 @@ TxProofResult Wallet::checkTxProof(const QString &txid, const QString &address,
return {success, good, received, in_pool, confirmations}; return {success, good, received, in_pool, confirmations};
} }
Q_INVOKABLE TxProof Wallet::getSpendProof(const QString &txid, const QString &message) const Q_INVOKABLE QString Wallet::getSpendProof(const QString &txid, const QString &message) const
{ {
std::string result = m_walletImpl->getSpendProof(txid.toStdString(), message.toStdString()); std::string result = m_walletImpl->getSpendProof(txid.toStdString(), message.toStdString());
return TxProof(QString::fromStdString(result), QString::fromStdString(m_walletImpl->errorString())); if (result.empty())
result = "error|" + m_walletImpl->errorString();
return QString::fromStdString(result);
} }
//void Wallet::getSpendProofAsync(const QString &txid, const QString &message, const QJSValue &callback) //void Wallet::getSpendProofAsync(const QString &txid, const QString &message, const QJSValue &callback)
@@ -915,6 +831,7 @@ bool Wallet::verifySignedMessage(const QString &message, const QString &address,
return m_walletImpl->verifySignedMessage(message.toStdString(), address.toStdString(), signature.toStdString()); return m_walletImpl->verifySignedMessage(message.toStdString(), address.toStdString(), signature.toStdString());
} }
} }
bool Wallet::parse_uri(const QString &uri, QString &address, QString &payment_id, uint64_t &amount, QString &tx_description, QString &recipient_name, QVector<QString> &unknown_parameters, QString &error) bool Wallet::parse_uri(const QString &uri, QString &address, QString &payment_id, uint64_t &amount, QString &tx_description, QString &recipient_name, QVector<QString> &unknown_parameters, QString &error)
{ {
std::string s_address, s_payment_id, s_tx_description, s_recipient_name, s_error; std::string s_address, s_payment_id, s_tx_description, s_recipient_name, s_error;
@@ -935,8 +852,6 @@ bool Wallet::parse_uri(const QString &uri, QString &address, QString &payment_id
bool Wallet::rescanSpent() bool Wallet::rescanSpent()
{ {
QMutexLocker locker(&m_asyncMutex);
return m_walletImpl->rescanSpent(); return m_walletImpl->rescanSpent();
} }
@@ -1013,8 +928,8 @@ QString Wallet::getRing(const QString &key_image)
{ {
if (!ring.isEmpty()) if (!ring.isEmpty())
ring = ring + " "; ring = ring + " ";
QString s; QString s;
s.setNum(out); s.setNum(out);
ring = ring + s; ring = ring + s;
} }
return ring; return ring;
@@ -1034,8 +949,8 @@ QString Wallet::getRings(const QString &txid)
for (uint64_t out: cring.second) for (uint64_t out: cring.second)
{ {
ring = ring + " "; ring = ring + " ";
QString s; QString s;
s.setNum(out); s.setNum(out);
ring = ring + s; ring = ring + s;
} }
} }
@@ -1049,9 +964,9 @@ bool Wallet::setRing(const QString &key_image, const QString &ring, bool relativ
foreach(QString str, strOuts) foreach(QString str, strOuts)
{ {
uint64_t out; uint64_t out;
bool ok; bool ok;
out = str.toULong(&ok); out = str.toULong(&ok);
if (ok) if (ok)
cring.push_back(out); cring.push_back(out);
} }
return m_walletImpl->setRing(key_image.toStdString(), cring, relative); return m_walletImpl->setRing(key_image.toStdString(), cring, relative);
@@ -1077,14 +992,6 @@ void Wallet::onWalletPassphraseNeeded(bool on_device)
emit this->walletPassphraseNeeded(on_device); emit this->walletPassphraseNeeded(on_device);
} }
quint64 Wallet::getBytesReceived() const {
return m_walletImpl->getBytesReceived();
}
quint64 Wallet::getBytesSent() const {
return m_walletImpl->getBytesSent();
}
void Wallet::onPassphraseEntered(const QString &passphrase, bool enter_on_device, bool entry_abort) void Wallet::onPassphraseEntered(const QString &passphrase, bool enter_on_device, bool entry_abort)
{ {
if (m_walletListener != nullptr) if (m_walletListener != nullptr)
@@ -1094,30 +1001,26 @@ void Wallet::onPassphraseEntered(const QString &passphrase, bool enter_on_device
} }
Wallet::Wallet(Monero::Wallet *w, QObject *parent) Wallet::Wallet(Monero::Wallet *w, QObject *parent)
: QObject(parent) : QObject(parent)
, m_walletImpl(w) , m_walletImpl(w)
, m_history(nullptr) , m_history(nullptr)
, m_historyModel(nullptr) , m_historyModel(nullptr)
, m_addressBook(nullptr) , m_addressBook(nullptr)
, m_addressBookModel(nullptr) , m_addressBookModel(nullptr)
, m_daemonBlockChainHeight(0) , m_daemonBlockChainHeight(0)
, m_daemonBlockChainHeightTtl(DAEMON_BLOCKCHAIN_HEIGHT_CACHE_TTL_SECONDS) , m_daemonBlockChainHeightTtl(DAEMON_BLOCKCHAIN_HEIGHT_CACHE_TTL_SECONDS)
, m_daemonBlockChainTargetHeight(0) , m_daemonBlockChainTargetHeight(0)
, m_daemonBlockChainTargetHeightTtl(DAEMON_BLOCKCHAIN_TARGET_HEIGHT_CACHE_TTL_SECONDS) , m_daemonBlockChainTargetHeightTtl(DAEMON_BLOCKCHAIN_TARGET_HEIGHT_CACHE_TTL_SECONDS)
, m_connectionStatus(Wallet::ConnectionStatus_Disconnected) , m_connectionStatus(Wallet::ConnectionStatus_Disconnected)
, m_connectionStatusTtl(WALLET_CONNECTION_STATUS_CACHE_TTL_SECONDS) , m_connectionStatusTtl(WALLET_CONNECTION_STATUS_CACHE_TTL_SECONDS)
, m_disconnected(true) , m_disconnected(true)
, m_currentSubaddressAccount(0) , m_currentSubaddressAccount(0)
, m_subaddress(nullptr) , m_subaddress(nullptr)
, m_subaddressModel(nullptr) , m_subaddressModel(nullptr)
, m_subaddressAccount(nullptr) , m_subaddressAccount(nullptr)
, m_subaddressAccountModel(nullptr) , m_subaddressAccountModel(nullptr)
, m_coinsModel(nullptr) , m_coinsModel(nullptr)
, m_refreshNow(false) , m_scheduler(this)
, m_refreshEnabled(false)
, m_refreshing(false)
, m_scheduler(this)
, m_useSSL(true)
{ {
m_history = new TransactionHistory(m_walletImpl->history(), this); m_history = new TransactionHistory(m_walletImpl->history(), this);
m_addressBook = new AddressBook(m_walletImpl->addressBook(), this); m_addressBook = new AddressBook(m_walletImpl->addressBook(), this);
@@ -1135,16 +1038,11 @@ Wallet::Wallet(Monero::Wallet *w, QObject *parent)
m_connectionStatusRunning = false; m_connectionStatusRunning = false;
m_daemonUsername = ""; m_daemonUsername = "";
m_daemonPassword = ""; m_daemonPassword = "";
startRefreshThread();
} }
Wallet::~Wallet() Wallet::~Wallet()
{ {
qDebug("~Wallet: Closing wallet"); qDebug() << "~Wallet: Closing wallet";
pauseRefresh();
m_walletImpl->stop();
m_scheduler.shutdownWaitForFinished(); m_scheduler.shutdownWaitForFinished();
@@ -1164,52 +1062,13 @@ Wallet::~Wallet()
//Monero::WalletManagerFactory::getWalletManager()->closeWallet(m_walletImpl); //Monero::WalletManagerFactory::getWalletManager()->closeWallet(m_walletImpl);
if(status() == Status_Critical) if(status() == Status_Critical)
qDebug("Not storing wallet cache"); qDebug("Not storing wallet cache");
// Don't store on wallet close for now else if( m_walletImpl->store(""))
// else if( m_walletImpl->store("")) qDebug("Wallet cache stored successfully");
// qDebug("Wallet cache stored successfully"); else
// else qDebug("Error storing wallet cache");
// qDebug("Error storing wallet cache");
delete m_walletImpl; delete m_walletImpl;
m_walletImpl = NULL; m_walletImpl = NULL;
delete m_walletListener; delete m_walletListener;
m_walletListener = NULL; m_walletListener = NULL;
qDebug("m_walletImpl deleted"); qDebug("m_walletImpl deleted");
} }
void Wallet::startRefreshThread()
{
const auto future = m_scheduler.run([this] {
constexpr const std::chrono::seconds refreshInterval{10};
constexpr const std::chrono::milliseconds intervalResolution{100};
auto last = std::chrono::steady_clock::now();
while (!m_scheduler.stopping())
{
if (m_refreshEnabled)
{
const auto now = std::chrono::steady_clock::now();
const auto elapsed = now - last;
if (elapsed >= refreshInterval || m_refreshNow)
{
m_refreshNow = false;
refresh(false);
last = std::chrono::steady_clock::now();
}
}
std::this_thread::sleep_for(intervalResolution);
}
});
if (!future.first)
{
throw std::runtime_error("failed to start auto refresh thread");
}
}
void Wallet::onRefreshed(bool success) {
if (success) {
setConnectionStatus(ConnectionStatus_Connected);
} else {
setConnectionStatus(ConnectionStatus_Disconnected);
}
}
+30 -83
View File
@@ -8,6 +8,7 @@
#include <QObject> #include <QObject>
#include <QMutex> #include <QMutex>
#include <QList> #include <QList>
//#include <QJSValue>
#include <QtConcurrent/QtConcurrent> #include <QtConcurrent/QtConcurrent>
#include "wallet/api/wallet2_api.h" // we need to have an access to the Monero::Wallet::Status enum here; #include "wallet/api/wallet2_api.h" // we need to have an access to the Monero::Wallet::Status enum here;
@@ -19,20 +20,14 @@
#include "WalletListenerImpl.h" #include "WalletListenerImpl.h"
namespace Monero { namespace Monero {
struct Wallet; // forward declaration struct Wallet; // forward declaration
} }
struct TxProof {
TxProof(QString proof, QString error = "")
: proof(std::move(proof)), error(std::move(error)){}
QString proof;
QString error;
};
class TransactionHistory; class TransactionHistory;
class TransactionHistoryModel; class TransactionHistoryModel;
class TransactionHistoryProxyModel; class TransactionHistoryProxyModel;
class TransactionHistorySortFilterModel;
class AddressBook; class AddressBook;
class AddressBookModel; class AddressBookModel;
class Subaddress; class Subaddress;
@@ -55,14 +50,13 @@ struct TxProofResult {
class Wallet : public QObject, public PassprasePrompter class Wallet : public QObject, public PassprasePrompter
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY(bool disconnected READ disconnected NOTIFY disconnectedChanged) Q_PROPERTY(bool disconnected READ disconnected NOTIFY disconnectedChanged)
Q_PROPERTY(bool refreshing READ refreshing NOTIFY refreshingChanged)
Q_PROPERTY(QString seed READ getSeed) Q_PROPERTY(QString seed READ getSeed)
Q_PROPERTY(QString seedLanguage READ getSeedLanguage) Q_PROPERTY(QString seedLanguage READ getSeedLanguage)
Q_PROPERTY(Status status READ status) Q_PROPERTY(Status status READ status)
Q_PROPERTY(NetworkType::Type nettype READ nettype) Q_PROPERTY(NetworkType::Type nettype READ nettype)
Q_PROPERTY(ConnectionStatus connectionStatus READ connectionStatus) Q_PROPERTY(ConnectionStatus connected READ connected)
Q_PROPERTY(quint32 currentSubaddressAccount READ currentSubaddressAccount NOTIFY currentSubaddressAccountChanged) Q_PROPERTY(quint32 currentSubaddressAccount READ currentSubaddressAccount NOTIFY currentSubaddressAccountChanged)
Q_PROPERTY(bool synchronized READ synchronized) Q_PROPERTY(bool synchronized READ synchronized)
Q_PROPERTY(QString errorString READ errorString) Q_PROPERTY(QString errorString READ errorString)
@@ -82,7 +76,6 @@ Q_OBJECT
Q_PROPERTY(QString secretSpendKey READ getSecretSpendKey) Q_PROPERTY(QString secretSpendKey READ getSecretSpendKey)
Q_PROPERTY(QString publicSpendKey READ getPublicSpendKey) Q_PROPERTY(QString publicSpendKey READ getPublicSpendKey)
Q_PROPERTY(QString daemonLogPath READ getDaemonLogPath CONSTANT) Q_PROPERTY(QString daemonLogPath READ getDaemonLogPath CONSTANT)
Q_PROPERTY(QString proxyAddress READ getProxyAddress WRITE setProxyAddress NOTIFY proxyAddressChanged)
Q_PROPERTY(quint64 walletCreationHeight READ getWalletCreationHeight WRITE setWalletCreationHeight NOTIFY walletCreationHeightChanged) Q_PROPERTY(quint64 walletCreationHeight READ getWalletCreationHeight WRITE setWalletCreationHeight NOTIFY walletCreationHeightChanged)
public: public:
@@ -105,9 +98,6 @@ public:
Q_ENUM(ConnectionStatus) Q_ENUM(ConnectionStatus)
//! return connection status
ConnectionStatus connectionStatus() const;
//! returns mnemonic seed //! returns mnemonic seed
QString getSeed() const; QString getSeed() const;
@@ -123,19 +113,19 @@ public:
//! returns network type of the wallet. //! returns network type of the wallet.
NetworkType::Type nettype() const; NetworkType::Type nettype() const;
//! returns whether the wallet is connected, and version status
Q_INVOKABLE ConnectionStatus connected(bool forceCheck = false);
void updateConnectionStatusAsync();
//! returns true if wallet was ever synchronized //! returns true if wallet was ever synchronized
bool synchronized() const; bool synchronized() const;
//! returns last operation's error message //! returns last operation's error message
QString errorString() const; QString errorString() const;
//! changes the password using existing parameters (path, seed, seed lang) //! changes the password using existing parameters (path, seed, seed lang)
Q_INVOKABLE bool setPassword(const QString &password); Q_INVOKABLE bool setPassword(const QString &password);
//! get current wallet password
Q_INVOKABLE QString getPassword();
//! returns wallet's public address //! returns wallet's public address
Q_INVOKABLE QString address(quint32 accountIndex, quint32 addressIndex) const; Q_INVOKABLE QString address(quint32 accountIndex, quint32 addressIndex) const;
@@ -148,14 +138,7 @@ public:
// Q_INVOKABLE void storeAsync(const QJSValue &callback, const QString &path = ""); // Q_INVOKABLE void storeAsync(const QJSValue &callback, const QString &path = "");
//! initializes wallet asynchronously //! initializes wallet asynchronously
Q_INVOKABLE void initAsync( Q_INVOKABLE void initAsync(const QString &daemonAddress, bool trustedDaemon = false, quint64 upperTransactionLimit = 0, bool isRecovering = false, bool isRecoveringFromDevice = false, quint64 restoreHeight = 0);
const QString &daemonAddress,
bool trustedDaemon = false,
quint64 upperTransactionLimit = 0,
bool isRecovering = false,
bool isRecoveringFromDevice = false,
quint64 restoreHeight = 0,
const QString &proxyAddress = "");
// Set daemon rpc user/pass // Set daemon rpc user/pass
Q_INVOKABLE void setDaemonLogin(const QString &daemonUsername = "", const QString &daemonPassword = ""); Q_INVOKABLE void setDaemonLogin(const QString &daemonUsername = "", const QString &daemonPassword = "");
@@ -166,15 +149,9 @@ public:
//! connects to daemon //! connects to daemon
Q_INVOKABLE bool connectToDaemon(); Q_INVOKABLE bool connectToDaemon();
//! set connect to daemon timeout //! indicates id daemon is trusted
Q_INVOKABLE void setConnectionTimeout(int timeout);
//! indicates if daemon is trusted
Q_INVOKABLE void setTrustedDaemon(bool arg); Q_INVOKABLE void setTrustedDaemon(bool arg);
//! indicates if ssl should be used to connect to daemon
Q_INVOKABLE void setUseSSL(bool ssl);
//! returns balance //! returns balance
Q_INVOKABLE quint64 balance() const; Q_INVOKABLE quint64 balance() const;
Q_INVOKABLE quint64 balance(quint32 accountIndex) const; Q_INVOKABLE quint64 balance(quint32 accountIndex) const;
@@ -207,22 +184,24 @@ public:
Q_INVOKABLE void refreshHeightAsync(); Q_INVOKABLE void refreshHeightAsync();
//! export/import key images //! export/import key images
Q_INVOKABLE bool exportKeyImages(const QString& path, bool all = false); Q_INVOKABLE bool exportKeyImages(const QString& path);
Q_INVOKABLE bool importKeyImages(const QString& path); Q_INVOKABLE bool importKeyImages(const QString& path);
//! export/import outputs
Q_INVOKABLE bool exportOutputs(const QString& path, bool all = false);
Q_INVOKABLE bool importOutputs(const QString& path);
//! import a transaction
Q_INVOKABLE bool importTransaction(const QString& txid, const QVector<quint64>& output_indeces, quint64 height, quint64 timestamp, bool miner_tx, bool pool, bool double_spend_seen);
//! refreshes the wallet //! refreshes the wallet
Q_INVOKABLE bool refresh(bool historyAndSubaddresses = false); Q_INVOKABLE bool refresh();
//! refreshes the wallet asynchronously
Q_INVOKABLE void refreshAsync();
//! setup auto-refresh interval in seconds
Q_INVOKABLE void setAutoRefreshInterval(int seconds);
//! return auto-refresh interval in seconds
Q_INVOKABLE int autoRefreshInterval() const;
// pause/resume refresh // pause/resume refresh
Q_INVOKABLE void startRefresh(); Q_INVOKABLE void startRefresh() const;
Q_INVOKABLE void pauseRefresh(); Q_INVOKABLE void pauseRefresh() const;
//! returns current wallet's block height //! returns current wallet's block height
//! (can be less than daemon's blockchain height when wallet sync in progress) //! (can be less than daemon's blockchain height when wallet sync in progress)
@@ -246,7 +225,7 @@ public:
//! creates transaction with all outputs //! creates transaction with all outputs
Q_INVOKABLE PendingTransaction * createTransactionAll(const QString &dst_addr, const QString &payment_id, Q_INVOKABLE PendingTransaction * createTransactionAll(const QString &dst_addr, const QString &payment_id,
quint32 mixin_count, PendingTransaction::Priority priority); quint32 mixin_count, PendingTransaction::Priority priority);
//! creates async transaction with all outputs //! creates async transaction with all outputs
Q_INVOKABLE void createTransactionAllAsync(const QString &dst_addr, const QString &payment_id, Q_INVOKABLE void createTransactionAllAsync(const QString &dst_addr, const QString &payment_id,
@@ -269,12 +248,6 @@ public:
//! Sign a transfer from file //! Sign a transfer from file
Q_INVOKABLE UnsignedTransaction * loadTxFile(const QString &fileName); Q_INVOKABLE UnsignedTransaction * loadTxFile(const QString &fileName);
//! Load an unsigned transaction from a base64 encoded string
Q_INVOKABLE UnsignedTransaction * loadTxFromBase64Str(const QString &unsigned_tx);
//! Load a signed transaction from file
Q_INVOKABLE PendingTransaction * loadSignedTxFile(const QString &fileName);
//! Submit a transfer from file //! Submit a transfer from file
Q_INVOKABLE bool submitTxFile(const QString &fileName) const; Q_INVOKABLE bool submitTxFile(const QString &fileName) const;
@@ -354,11 +327,11 @@ public:
Q_INVOKABLE QString getTxKey(const QString &txid) const; Q_INVOKABLE QString getTxKey(const QString &txid) const;
//Q_INVOKABLE void getTxKeyAsync(const QString &txid, const QJSValue &callback); //Q_INVOKABLE void getTxKeyAsync(const QString &txid, const QJSValue &callback);
Q_INVOKABLE QString checkTxKey(const QString &txid, const QString &tx_key, const QString &address); Q_INVOKABLE QString checkTxKey(const QString &txid, const QString &tx_key, const QString &address);
Q_INVOKABLE TxProof getTxProof(const QString &txid, const QString &address, const QString &message) const; Q_INVOKABLE QString getTxProof(const QString &txid, const QString &address, const QString &message) const;
// Q_INVOKABLE void getTxProofAsync(const QString &txid, const QString &address, const QString &message, const QJSValue &callback); // Q_INVOKABLE void getTxProofAsync(const QString &txid, const QString &address, const QString &message, const QJSValue &callback);
//Q_INVOKABLE QString checkTxProof(const QString &txid, const QString &address, const QString &message, const QString &signature); //Q_INVOKABLE QString checkTxProof(const QString &txid, const QString &address, const QString &message, const QString &signature);
Q_INVOKABLE TxProofResult checkTxProof(const QString &txid, const QString &address, const QString &message, const QString &signature); Q_INVOKABLE TxProofResult checkTxProof(const QString &txid, const QString &address, const QString &message, const QString &signature);
Q_INVOKABLE TxProof getSpendProof(const QString &txid, const QString &message) const; Q_INVOKABLE QString getSpendProof(const QString &txid, const QString &message) const;
// Q_INVOKABLE void getSpendProofAsync(const QString &txid, const QString &message, const QJSValue &callback); // Q_INVOKABLE void getSpendProofAsync(const QString &txid, const QString &message, const QJSValue &callback);
Q_INVOKABLE QPair<bool, bool> checkSpendProof(const QString &txid, const QString &message, const QString &signature) const; Q_INVOKABLE QPair<bool, bool> checkSpendProof(const QString &txid, const QString &message, const QString &signature) const;
// Rescan spent outputs // Rescan spent outputs
@@ -399,9 +372,6 @@ public:
Q_INVOKABLE void onPassphraseEntered(const QString &passphrase, bool enter_on_device, bool entry_abort=false); Q_INVOKABLE void onPassphraseEntered(const QString &passphrase, bool enter_on_device, bool entry_abort=false);
virtual void onWalletPassphraseNeeded(bool on_device) override; virtual void onWalletPassphraseNeeded(bool on_device) override;
Q_INVOKABLE quint64 getBytesReceived() const;
Q_INVOKABLE quint64 getBytesSent() const;
// TODO: setListenter() when it implemented in API // TODO: setListenter() when it implemented in API
signals: signals:
// emitted on every event happened with wallet // emitted on every event happened with wallet
@@ -410,7 +380,7 @@ signals:
// emitted when refresh process finished (could take a long time) // emitted when refresh process finished (could take a long time)
// signalling only after we // signalling only after we
void refreshed(bool success); void refreshed();
void moneySpent(const QString &txId, quint64 amount); void moneySpent(const QString &txId, quint64 amount);
void moneyReceived(const QString &txId, quint64 amount); void moneyReceived(const QString &txId, quint64 amount);
@@ -432,8 +402,6 @@ signals:
void connectionStatusChanged(int status) const; void connectionStatusChanged(int status) const;
void currentSubaddressAccountChanged() const; void currentSubaddressAccountChanged() const;
void disconnectedChanged() const; void disconnectedChanged() const;
void proxyAddressChanged() const;
void refreshingChanged() const;
private: private:
Wallet(QObject * parent = nullptr); Wallet(QObject * parent = nullptr);
@@ -441,24 +409,10 @@ private:
~Wallet(); ~Wallet();
//! initializes wallet //! initializes wallet
bool init( bool init(const QString &daemonAddress, bool trustedDaemon, quint64 upperTransactionLimit, bool isRecovering, bool isRecoveringFromDevice, quint64 restoreHeight);
const QString &daemonAddress,
bool trustedDaemon,
quint64 upperTransactionLimit,
bool isRecovering,
bool isRecoveringFromDevice,
quint64 restoreHeight,
const QString& proxyAddress);
bool disconnected() const; bool disconnected() const;
bool refreshing() const;
void refreshingSet(bool value);
void onRefreshed(bool success);
void setConnectionStatus(ConnectionStatus value); void setConnectionStatus(ConnectionStatus value);
QString getProxyAddress() const;
void setProxyAddress(QString address);
void startRefreshThread();
private: private:
friend class WalletManager; friend class WalletManager;
@@ -491,20 +445,13 @@ private:
mutable SubaddressAccountModel * m_subaddressAccountModel; mutable SubaddressAccountModel * m_subaddressAccountModel;
Coins * m_coins; Coins * m_coins;
mutable CoinsModel * m_coinsModel; mutable CoinsModel * m_coinsModel;
QMutex m_asyncMutex;
QMutex m_connectionStatusMutex; QMutex m_connectionStatusMutex;
bool m_connectionStatusRunning; bool m_connectionStatusRunning;
QString m_daemonUsername; QString m_daemonUsername;
QString m_daemonPassword; QString m_daemonPassword;
QString m_proxyAddress;
mutable QMutex m_proxyMutex;
std::atomic<bool> m_refreshNow;
std::atomic<bool> m_refreshEnabled;
std::atomic<bool> m_refreshing;
WalletListenerImpl *m_walletListener; WalletListenerImpl *m_walletListener;
FutureScheduler m_scheduler; FutureScheduler m_scheduler;
int m_connectionTimeout = 30; QMutex m_storeMutex;
bool m_useSSL;
}; };
+2 -3
View File
@@ -41,11 +41,10 @@ void WalletListenerImpl::updated()
} }
// called when wallet refreshed by background thread or explicitly // called when wallet refreshed by background thread or explicitly
void WalletListenerImpl::refreshed(bool success) void WalletListenerImpl::refreshed()
{ {
qDebug() << __FUNCTION__; qDebug() << __FUNCTION__;
m_wallet->onRefreshed(success); emit m_wallet->refreshed();
emit m_wallet->refreshed(success);
} }
void WalletListenerImpl::onDeviceButtonRequest(uint64_t code) void WalletListenerImpl::onDeviceButtonRequest(uint64_t code)
+1 -1
View File
@@ -25,7 +25,7 @@ public:
virtual void updated() override; virtual void updated() override;
// called when wallet refreshed by background thread or explicitly // called when wallet refreshed by background thread or explicitly
virtual void refreshed(bool success) override; virtual void refreshed() override;
virtual void onDeviceButtonRequest(uint64_t code) override; virtual void onDeviceButtonRequest(uint64_t code) override;
+2 -2
View File
@@ -26,7 +26,7 @@ public:
virtual void unconfirmedMoneyReceived(const std::string &txId, uint64_t amount) override { (void)txId; (void)amount; }; virtual void unconfirmedMoneyReceived(const std::string &txId, uint64_t amount) override { (void)txId; (void)amount; };
virtual void newBlock(uint64_t height) override { (void) height; }; virtual void newBlock(uint64_t height) override { (void) height; };
virtual void updated() override {}; virtual void updated() override {};
virtual void refreshed(bool success) override {}; virtual void refreshed() override {};
virtual void onPassphraseEntered(const QString &passphrase, bool enter_on_device, bool entry_abort) override virtual void onPassphraseEntered(const QString &passphrase, bool enter_on_device, bool entry_abort) override
{ {
@@ -335,7 +335,7 @@ bool WalletManager::isMining() const
{ {
{ {
QMutexLocker locker(&m_mutex); QMutexLocker locker(&m_mutex);
if (m_currentWallet == nullptr || !m_currentWallet->connectionStatus()) if (m_currentWallet == nullptr || !m_currentWallet->connected())
{ {
return false; return false;
} }
+6 -8
View File
@@ -22,14 +22,12 @@ int main(int argc, char *argv[])
{ {
Q_INIT_RESOURCE(assets); Q_INIT_RESOURCE(assets);
#if defined(Q_OS_MAC) && defined(HAS_TOR) #if defined(Q_OS_MAC) && defined(BUILD_TOR)
Q_INIT_RESOURCE(assets_tor_macos); Q_INIT_RESOURCE(assets_macos_tor);
#elif defined(HAS_TOR) #elif defined(Q_OS_LINUX) && defined(BUILD_TOR)
Q_INIT_RESOURCE(assets_tor); Q_INIT_RESOURCE(assets_linux_tor);
#endif #elif defined(Q_OS_WIN) && defined(BUILD_TOR)
Q_INIT_RESOURCE(assets_windows_tor);
#if defined(HAS_XMRIG)
Q_INIT_RESOURCE(assets_mining);
#endif #endif
QStringList argv_; QStringList argv_;
+72 -355
View File
@@ -13,17 +13,11 @@
#include "widgets/ccswidget.h" #include "widgets/ccswidget.h"
#include "widgets/redditwidget.h" #include "widgets/redditwidget.h"
#include "dialog/txconfdialog.h" #include "dialog/txconfdialog.h"
#include "dialog/txconfadvdialog.h"
#include "dialog/debuginfodialog.h" #include "dialog/debuginfodialog.h"
#include "dialog/walletinfodialog.h" #include "dialog/walletinfodialog.h"
#include "dialog/torinfodialog.h" #include "dialog/torinfodialog.h"
#include "dialog/viewonlydialog.h"
#include "dialog/broadcasttxdialog.h"
#include "dialog/tximportdialog.h"
#include "dialog/passworddialog.h"
#include "utils/utils.h" #include "utils/utils.h"
#include "utils/config.h" #include "utils/config.h"
#include "utils/daemonrpc.h"
#include "components.h" #include "components.h"
#include "calcwindow.h" #include "calcwindow.h"
#include "ui_mainwindow.h" #include "ui_mainwindow.h"
@@ -105,6 +99,8 @@ MainWindow::MainWindow(AppContext *ctx, QWidget *parent) :
}); });
connect(ui->actionShow_debug_info, &QAction::triggered, this, &MainWindow::showDebugInfo); connect(ui->actionShow_debug_info, &QAction::triggered, this, &MainWindow::showDebugInfo);
connect(ui->actionOfficialWebsite, &QAction::triggered, [=] { Utils::externalLinkWarning("https://featherwallet.org"); }); connect(ui->actionOfficialWebsite, &QAction::triggered, [=] { Utils::externalLinkWarning("https://featherwallet.org"); });
connect(ui->actionAbout_Qt, &QAction::triggered, [=] { QApplication::aboutQt(); });
#if defined(XMRTO) #if defined(XMRTO)
// xmr.to connects/widget // xmr.to connects/widget
@@ -118,12 +114,9 @@ MainWindow::MainWindow(AppContext *ctx, QWidget *parent) :
connect(m_ctx->XMRTo, &XmrTo::openURL, this, [=](const QString &url){ Utils::externalLinkWarning(url); }); connect(m_ctx->XMRTo, &XmrTo::openURL, this, [=](const QString &url){ Utils::externalLinkWarning(url); });
ui->xmrToWidget->setHistoryModel(m_ctx->XMRTo->tableModel); ui->xmrToWidget->setHistoryModel(m_ctx->XMRTo->tableModel);
#else #else
ui->tabWidget->setTabVisible(Tabs::XMR_TO, false); ui->tabWidget->setTabVisible(5, false);
#endif #endif
#ifndef HAS_MORPHTOKEN
ui->tabWidget->setTabVisible(Tabs::MORPHTOKEN, false);
#endif
#if defined(Q_OS_LINUX) #if defined(Q_OS_LINUX)
// system tray // system tray
@@ -172,24 +165,6 @@ MainWindow::MainWindow(AppContext *ctx, QWidget *parent) :
connect(m_ctx->nodes, &Nodes::nodeExhausted, this, &MainWindow::showNodeExhaustedMessage); connect(m_ctx->nodes, &Nodes::nodeExhausted, this, &MainWindow::showNodeExhaustedMessage);
connect(m_ctx->nodes, &Nodes::WSNodeExhausted, this, &MainWindow::showWSNodeExhaustedMessage); connect(m_ctx->nodes, &Nodes::WSNodeExhausted, this, &MainWindow::showWSNodeExhaustedMessage);
// XMRig
#ifdef HAS_XMRIG
m_xmrig = new XMRigWidget(m_ctx, this);
ui->xmrRigLayout->addWidget(m_xmrig);
connect(m_ctx->XMRig, &XmRig::output, m_xmrig, &XMRigWidget::onProcessOutput);
connect(m_ctx->XMRig, &XmRig::error, m_xmrig, &XMRigWidget::onProcessError);
connect(m_ctx->XMRig, &XmRig::hashrate, m_xmrig, &XMRigWidget::onHashrate);
connect(m_ctx, &AppContext::walletClosed, m_xmrig, &XMRigWidget::onWalletClosed);
connect(m_ctx, &AppContext::walletOpened, m_xmrig, &XMRigWidget::onWalletOpened);
connect(m_ctx, &AppContext::XMRigDownloads, m_xmrig, &XMRigWidget::onDownloads);
connect(m_xmrig, &XMRigWidget::miningStarted, [=]{ m_ctx->setWindowTitle(true); });
connect(m_xmrig, &XMRigWidget::miningEnded, [=]{ m_ctx->setWindowTitle(false); });
#else
ui->tabWidget->setTabVisible(Tabs::XMRIG, false);
#endif
// CCS/Reddit widget // CCS/Reddit widget
m_ccsWidget = new CCSWidget(this); m_ccsWidget = new CCSWidget(this);
m_redditWidget = new RedditWidget(this); m_redditWidget = new RedditWidget(this);
@@ -280,7 +255,6 @@ MainWindow::MainWindow(AppContext *ctx, QWidget *parent) :
connect(m_windowSettings, &Settings::preferredFiatCurrencyChanged, tickerWidget, &TickerWidget::init); connect(m_windowSettings, &Settings::preferredFiatCurrencyChanged, tickerWidget, &TickerWidget::init);
connect(m_windowSettings, &Settings::preferredFiatCurrencyChanged, m_balanceWidget, &TickerWidget::init); connect(m_windowSettings, &Settings::preferredFiatCurrencyChanged, m_balanceWidget, &TickerWidget::init);
connect(m_windowSettings, &Settings::preferredFiatCurrencyChanged, m_ctx, &AppContext::onPreferredFiatCurrencyChanged); connect(m_windowSettings, &Settings::preferredFiatCurrencyChanged, m_ctx, &AppContext::onPreferredFiatCurrencyChanged);
connect(m_windowSettings, &Settings::preferredFiatCurrencyChanged, ui->sendWidget, QOverload<>::of(&SendWidget::onPreferredFiatCurrencyChanged));
// CCS/Reddit widget // CCS/Reddit widget
connect(m_windowSettings, &Settings::homeWidgetChanged, this, &MainWindow::homeWidgetChanged); connect(m_windowSettings, &Settings::homeWidgetChanged, this, &MainWindow::homeWidgetChanged);
@@ -301,13 +275,13 @@ MainWindow::MainWindow(AppContext *ctx, QWidget *parent) :
}); });
connect(ui->receiveWidget, &ReceiveWidget::showTransactions, [this](const QString &text) { connect(ui->receiveWidget, &ReceiveWidget::showTransactions, [this](const QString &text) {
ui->historyWidget->setSearchText(text); ui->historyWidget->setSearchText(text);
ui->tabWidget->setCurrentIndex(Tabs::HISTORY); ui->tabWidget->setCurrentIndex(1); //history
}); });
// History // History
connect(ui->historyWidget, &HistoryWidget::spendProof, [&](const QString &txid){ connect(ui->historyWidget, &HistoryWidget::spendProof, [&](const QString &txid){
TxProof txproof = m_ctx->currentWallet->getSpendProof(txid, ""); QString spendProof = m_ctx->currentWallet->getSpendProof(txid, "");
Utils::copyToClipboard(txproof.proof); Utils::copyToClipboard(spendProof);
}); });
connect(ui->historyWidget, &HistoryWidget::viewOnBlockExplorer, this, &MainWindow::onViewOnBlockExplorer); connect(ui->historyWidget, &HistoryWidget::viewOnBlockExplorer, this, &MainWindow::onViewOnBlockExplorer);
@@ -349,26 +323,12 @@ MainWindow::MainWindow(AppContext *ctx, QWidget *parent) :
connect(ui->coinsWidget, &CoinsWidget::sweepOutput, m_ctx, &AppContext::onSweepOutput); connect(ui->coinsWidget, &CoinsWidget::sweepOutput, m_ctx, &AppContext::onSweepOutput);
connect(m_ctx, &AppContext::walletClosing, [=]{ connect(m_ctx, &AppContext::walletClosing, [=]{
ui->tabWidget->setCurrentIndex(Tabs::HOME); ui->tabWidget->setCurrentIndex(0);
}); });
// window title
connect(m_ctx, &AppContext::setTitle, this, &QMainWindow::setWindowTitle);
// init touchbar
#ifdef Q_OS_MAC
m_touchbar = new KDMacTouchBar(this);
m_touchbarActionWelcome = new QAction(QIcon(":/assets/images/feather.png"), "Welcome to Feather!");
m_touchbarWalletItems = {ui->actionSettings, ui->actionCalculator, ui->actionKeys, ui->actionDonate_to_Feather};
m_touchbarWizardItems = {m_touchbarActionWelcome};
#endif
// setup some UI // setup some UI
this->initMain(); this->initMain();
this->initWidgets(); this->initWidgets();
this->initMenu(); this->initMenu();
connect(&m_updateBytes, &QTimer::timeout, this, &MainWindow::updateNetStats);
} }
void MainWindow::initMain() { void MainWindow::initMain() {
@@ -396,51 +356,25 @@ void MainWindow::initMain() {
this->show(); this->show();
m_wizard = this->createWizard(WalletWizard::Page_Menu); m_wizard = this->createWizard(WalletWizard::Page_Menu);
m_wizard->show(); m_wizard->show();
this->touchbarShowWizard();
} }
void MainWindow::initMenu() { void MainWindow::initMenu() {
// setup shortcuts
ui->actionStore_wallet->setShortcut(QKeySequence("Ctrl+S"));
ui->actionRefresh_tabs->setShortcut(QKeySequence("Ctrl+R"));
ui->actionClose->setShortcut(QKeySequence("Ctrl+W"));
ui->actionShow_debug_info->setShortcut(QKeySequence("Ctrl+D"));
ui->actionSettings->setShortcut(QKeySequence("Ctrl+Alt+S"));
// hide/show tabs // hide/show tabs
m_tabShowHideSignalMapper = new QSignalMapper(this); m_tabShowHideSignalMapper = new QSignalMapper(this);
connect(ui->actionShow_Coins, &QAction::triggered, m_tabShowHideSignalMapper, QOverload<>::of(&QSignalMapper::map)); connect(ui->actionShow_Coins, &QAction::triggered, m_tabShowHideSignalMapper, QOverload<>::of(&QSignalMapper::map));
m_tabShowHideMapper["Coins"] = new ToggleTab(ui->tabCoins, "Coins", "Coins", ui->actionShow_Coins, Config::showTabCoins); m_tabShowHideMapper["Coins"] = new ToggleTab(ui->tabCoins, "Coins", "Coins", ui->actionShow_Coins, Config::showTabCoins);
m_tabShowHideSignalMapper->setMapping(ui->actionShow_Coins, "Coins"); m_tabShowHideSignalMapper->setMapping(ui->actionShow_Coins, "Coins");
connect(ui->actionShow_calc, &QAction::triggered, m_tabShowHideSignalMapper, QOverload<>::of(&QSignalMapper::map));
m_tabShowHideMapper["Calc"] = new ToggleTab(ui->tabCalc, "Calc", "Calc", ui->actionShow_calc, Config::showTabCalc);
m_tabShowHideSignalMapper->setMapping(ui->actionShow_calc, "Calc");
#if defined(HAS_MORPHTOKEN)
connect(ui->actionShow_MorphToken, &QAction::triggered, m_tabShowHideSignalMapper, QOverload<>::of(&QSignalMapper::map));
m_tabShowHideMapper["MorphToken"] = new ToggleTab(ui->tabMorphToken, "MorphToken", "MorphToken", ui->actionShow_MorphToken, Config::showTabMorphToken);
m_tabShowHideSignalMapper->setMapping(ui->actionShow_MorphToken, "MorphToken");
#else
ui->actionShow_MorphToken->setVisible(false);
#endif
#if defined(XMRTO) #if defined(XMRTO)
connect(ui->actionShow_xmr_to, &QAction::triggered, m_tabShowHideSignalMapper, QOverload<>::of(&QSignalMapper::map)); connect(ui->actionShow_xmr_to, &QAction::triggered, m_tabShowHideSignalMapper, QOverload<>::of(&QSignalMapper::map));
m_tabShowHideMapper["XMRto"] = new ToggleTab(ui->tabXmrTo, "XMRto", "XMR.to", ui->actionShow_xmr_to, Config::showTabXMRto); m_tabShowHideMapper["XMRto"] = new ToggleTab(ui->tabXmrTo, "XMRto", "xmr.to", ui->actionShow_xmr_to, Config::showTabXMRto);
m_tabShowHideSignalMapper->setMapping(ui->actionShow_xmr_to, "XMRto"); m_tabShowHideSignalMapper->setMapping(ui->actionShow_xmr_to, "XMRto");
#else #else
ui->actionShow_xmr_to->setVisible(false); ui->actionShow_xmr_to->setVisible(false);
#endif #endif
connect(ui->actionShow_calc, &QAction::triggered, m_tabShowHideSignalMapper, QOverload<>::of(&QSignalMapper::map));
#if defined(HAS_XMRIG) m_tabShowHideMapper["Calc"] = new ToggleTab(ui->tabCalc, "Calc", "Calc", ui->actionShow_calc, Config::showTabCalc);
connect(ui->actionShow_XMRig, &QAction::triggered, m_tabShowHideSignalMapper, QOverload<>::of(&QSignalMapper::map)); m_tabShowHideSignalMapper->setMapping(ui->actionShow_calc, "Calc");
m_tabShowHideMapper["XMRig"] = new ToggleTab(ui->tabXmrRig, "XMRig", "XMRig", ui->actionShow_XMRig, Config::showTabXMRig);
m_tabShowHideSignalMapper->setMapping(ui->actionShow_XMRig, "XMRig");
#else
ui->actionShow_XMRig->setVisible(false);
#endif
for (const auto &key: m_tabShowHideMapper.keys()) { for (const auto &key: m_tabShowHideMapper.keys()) {
const auto toggleTab = m_tabShowHideMapper.value(key); const auto toggleTab = m_tabShowHideMapper.value(key);
@@ -455,7 +389,6 @@ void MainWindow::initMenu() {
connect(ui->actionSeed, &QAction::triggered, this, &MainWindow::showSeedDialog); connect(ui->actionSeed, &QAction::triggered, this, &MainWindow::showSeedDialog);
connect(ui->actionPassword, &QAction::triggered, this, &MainWindow::showPasswordDialog); connect(ui->actionPassword, &QAction::triggered, this, &MainWindow::showPasswordDialog);
connect(ui->actionKeys, &QAction::triggered, this, &MainWindow::showKeysDialog); connect(ui->actionKeys, &QAction::triggered, this, &MainWindow::showKeysDialog);
connect(ui->actionViewOnly, &QAction::triggered, this, &MainWindow::showViewOnlyDialog);
connect(ui->actionStore_wallet, &QAction::triggered, [&]{ connect(ui->actionStore_wallet, &QAction::triggered, [&]{
m_ctx->currentWallet->store(); m_ctx->currentWallet->store();
}); });
@@ -465,10 +398,6 @@ void MainWindow::initMenu() {
connect(ui->actionUpdate_balance, &QAction::triggered, [&]{ connect(ui->actionUpdate_balance, &QAction::triggered, [&]{
m_ctx->updateBalance(); m_ctx->updateBalance();
}); });
connect(ui->actionExportKeyImages, &QAction::triggered, this, &MainWindow::exportKeyImages);
connect(ui->actionImportKeyImages, &QAction::triggered, this, &MainWindow::importKeyImages);
connect(ui->actionExportOutputs, &QAction::triggered, this, &MainWindow::exportOutputs);
connect(ui->actionImportOutputs, &QAction::triggered, this, &MainWindow::importOutputs);
// set restore height // set restore height
connect(ui->actionChange_restore_height, &QAction::triggered, this, &MainWindow::showRestoreHeightDialog); connect(ui->actionChange_restore_height, &QAction::triggered, this, &MainWindow::showRestoreHeightDialog);
@@ -483,8 +412,7 @@ void MainWindow::initMenu() {
connect(ui->actionExport_CSV, &QAction::triggered, [=]{ connect(ui->actionExport_CSV, &QAction::triggered, [=]{
if(m_ctx->currentWallet == nullptr) return; if(m_ctx->currentWallet == nullptr) return;
QString fn = QFileDialog::getSaveFileName(this, "Save CSV file", QDir::homePath(), "CSV (*.csv)"); QString fn = QFileDialog::getSaveFileName(this, "Save CSV file", QDir::homePath(), "CSV (*.csv)");
if(fn.isEmpty()) return; if(!fn.startsWith(".csv")) fn += ".csv";
if(!fn.endsWith(".csv")) fn += ".csv";
m_ctx->currentWallet->history()->writeCSV(fn); m_ctx->currentWallet->history()->writeCSV(fn);
Utils::showMessageBox("CSV export", QString("Transaction history exported to %1").arg(fn), false); Utils::showMessageBox("CSV export", QString("Transaction history exported to %1").arg(fn), false);
}); });
@@ -507,16 +435,9 @@ void MainWindow::initMenu() {
Utils::showMessageBox("Address book exported", QString("Address book exported to %1").arg(fn), false); Utils::showMessageBox("Address book exported", QString("Address book exported to %1").arg(fn), false);
}); });
connect(ui->actionImportContactsCSV, &QAction::triggered, this, &MainWindow::importContacts);
// Tools // Tools
connect(ui->actionSignVerify, &QAction::triggered, this, &MainWindow::menuSignVerifyClicked); connect(ui->actionSignVerify, &QAction::triggered, this, &MainWindow::menuSignVerifyClicked);
connect(ui->actionVerifyTxProof, &QAction::triggered, this, &MainWindow::menuVerifyTxProof); connect(ui->actionVerifyTxProof, &QAction::triggered, this, &MainWindow::menuVerifyTxProof);
connect(ui->actionLoadUnsignedTxFromFile, &QAction::triggered, this, &MainWindow::loadUnsignedTx);
connect(ui->actionLoadUnsignedTxFromClipboard, &QAction::triggered, this, &MainWindow::loadUnsignedTxFromClipboard);
connect(ui->actionLoadSignedTxFromFile, &QAction::triggered, this, &MainWindow::loadSignedTx);
connect(ui->actionLoadSignedTxFromText, &QAction::triggered, this, &MainWindow::loadSignedTxFromText);
connect(ui->actionImport_transaction, &QAction::triggered, this, &MainWindow::importTransaction);
// About screen // About screen
connect(ui->actionAbout, &QAction::triggered, this, &MainWindow::menuAboutClicked); connect(ui->actionAbout, &QAction::triggered, this, &MainWindow::menuAboutClicked);
@@ -556,11 +477,7 @@ WalletWizard *MainWindow::createWizard(WalletWizard::Page startPage){
void MainWindow::showWizard(WalletWizard::Page startPage) { void MainWindow::showWizard(WalletWizard::Page startPage) {
this->setEnabled(false); this->setEnabled(false);
if (m_wizard == nullptr) m_wizard = this->createWizard(startPage);
m_wizard = this->createWizard(startPage);
m_wizard->setStartId(startPage);
m_wizard->restart();
m_wizard->setEnabled(true);
m_wizard->show(); m_wizard->show();
} }
@@ -576,41 +493,24 @@ void MainWindow::onWalletClosed(WalletWizard::Page page) {
this->showWizard(page); this->showWizard(page);
} }
void MainWindow::touchbarShowWizard() {
#ifdef Q_OS_MAC
m_touchbar->clear();
for(auto* action: m_touchbarWizardItems) m_touchbar->addAction(action);
#endif
}
void MainWindow::touchbarShowWallet() {
#ifdef Q_OS_MAC
m_touchbar->clear();
for(auto* action: m_touchbarWalletItems) m_touchbar->addAction(action);
#endif
}
void MainWindow::onWalletCreatedError(const QString &err) { void MainWindow::onWalletCreatedError(const QString &err) {
Utils::showMessageBox("Wallet creation error", err, true); Utils::showMessageBox("Wallet creation error", err, true);
this->showWizard(WalletWizard::Page_CreateWallet); this->showWizard(WalletWizard::Page_CreateWallet);
} }
void MainWindow::onWalletOpenPasswordRequired(bool invalidPassword, const QString &path) { void MainWindow::onWalletOpenPasswordRequired(bool invalidPassword) {
QFileInfo fileInfo(path); QInputDialog passwordDialog(this);
passwordDialog.setInputMode(QInputDialog::TextInput);
passwordDialog.setTextEchoMode(QLineEdit::Password);
passwordDialog.setWindowTitle("Password required");
passwordDialog.setLabelText("Please enter wallet password.");
passwordDialog.resize(300, 100);
if(!(bool)passwordDialog.exec())
return this->showWizard(WalletWizard::Page_OpenWallet);
auto dialog = new PasswordDialog(this, fileInfo.fileName(), invalidPassword); const auto passwd = passwordDialog.textValue();
switch (dialog->exec()) { m_ctx->walletPassword = passwd;
case QDialog::Rejected:
{
this->showWizard(WalletWizard::Page_OpenWallet);
return;
}
}
m_ctx->walletPassword = dialog->password;
m_ctx->onOpenWallet(m_ctx->walletPath, m_ctx->walletPassword); m_ctx->onOpenWallet(m_ctx->walletPath, m_ctx->walletPassword);
dialog->deleteLater();
} }
void MainWindow::onWalletOpenedError(const QString &err) { void MainWindow::onWalletOpenedError(const QString &err) {
@@ -618,7 +518,6 @@ void MainWindow::onWalletOpenedError(const QString &err) {
QMessageBox::warning(this, "Wallet open error", err); QMessageBox::warning(this, "Wallet open error", err);
this->setWindowTitle("Feather"); this->setWindowTitle("Feather");
this->showWizard(WalletWizard::Page_OpenWallet); this->showWizard(WalletWizard::Page_OpenWallet);
this->touchbarShowWizard();
} }
void MainWindow::onWalletCreated(Wallet *wallet) { void MainWindow::onWalletCreated(Wallet *wallet) {
@@ -631,6 +530,8 @@ void MainWindow::onWalletOpened() {
qDebug() << Q_FUNC_INFO; qDebug() << Q_FUNC_INFO;
if(m_wizard != nullptr) { if(m_wizard != nullptr) {
m_wizard->hide(); m_wizard->hide();
m_wizard->disconnect();
m_wizard->deleteLater();
} }
this->raise(); this->raise();
@@ -642,6 +543,10 @@ void MainWindow::onWalletOpened() {
else else
m_statusLabelStatus->setText("Wallet opened - Searching for node"); m_statusLabelStatus->setText("Wallet opened - Searching for node");
// window title as wallet name
QFileInfo fileInfo(m_ctx->walletPath);
this->setWindowTitle(QString("Feather - [%1]").arg(fileInfo.fileName()));
connect(m_ctx->currentWallet, &Wallet::connectionStatusChanged, this, &MainWindow::onConnectionStatusChanged); connect(m_ctx->currentWallet, &Wallet::connectionStatusChanged, this, &MainWindow::onConnectionStatusChanged);
// receive page // receive page
@@ -658,7 +563,7 @@ void MainWindow::onWalletOpened() {
// history page // history page
m_ctx->currentWallet->history()->refresh(m_ctx->currentWallet->currentSubaddressAccount()); m_ctx->currentWallet->history()->refresh(m_ctx->currentWallet->currentSubaddressAccount());
ui->historyWidget->setModel(m_ctx->currentWallet->historyModel(), m_ctx->currentWallet); ui->historyWidget->setModel(m_ctx->currentWallet->coins(), m_ctx->currentWallet->historyModel(), m_ctx->currentWallet->history());
connect(m_ctx->currentWallet->history(), &TransactionHistory::txNoteChanged, [this]{ connect(m_ctx->currentWallet->history(), &TransactionHistory::txNoteChanged, [this]{
m_ctx->storeWallet(); m_ctx->storeWallet();
}); });
@@ -678,31 +583,17 @@ void MainWindow::onWalletOpened() {
connect(m_ctx->currentWallet->coins(), &Coins::coinThawed, [this]{ connect(m_ctx->currentWallet->coins(), &Coins::coinThawed, [this]{
m_ctx->storeWallet(); m_ctx->storeWallet();
}); });
this->touchbarShowWallet();
this->updatePasswordIcon();
m_updateBytes.start(1000);
} }
void MainWindow::onBalanceUpdated(double balance, double unlocked, const QString &balance_str, const QString &unlocked_str) { void MainWindow::onBalanceUpdated(double balance, double unlocked, const QString &balance_str, const QString &unlocked_str) {
qDebug() << Q_FUNC_INFO; qDebug() << Q_FUNC_INFO;
bool hide = config()->get(Config::hideBalance).toBool();
auto label_str = QString("Balance: %1 XMR").arg(unlocked_str); auto label_str = QString("Balance: %1 XMR").arg(unlocked_str);
if(balance > unlocked) if(balance > unlocked)
label_str += QString(" (+%1 XMR unconfirmed)").arg(QString::number(balance - unlocked, 'f')); label_str += QString(" (+%1 XMR unconfirmed)").arg(QString::number(balance - unlocked, 'f'));
if (hide) {
label_str = "Balance: HIDDEN";
}
m_statusLabelBalance->setText(label_str); m_statusLabelBalance->setText(label_str);
m_balanceWidget->setHidden(hide);
} }
void MainWindow::onSynchronized() { void MainWindow::onSynchronized() {
this->updateNetStats();
m_statusLabelStatus->setText("Synchronized"); m_statusLabelStatus->setText("Synchronized");
this->onConnectionStatusChanged(Wallet::ConnectionStatus_Connected); this->onConnectionStatusChanged(Wallet::ConnectionStatus_Connected);
} }
@@ -715,12 +606,11 @@ void MainWindow::onBlockchainSync(int height, int target) {
void MainWindow::onRefreshSync(int height, int target) { void MainWindow::onRefreshSync(int height, int target) {
QString heightText = QString("Wallet refresh: %1/%2").arg(height).arg(target); QString heightText = QString("Wallet refresh: %1/%2").arg(height).arg(target);
m_statusLabelStatus->setText(heightText); m_statusLabelStatus->setText(heightText);
this->updateNetStats();
} }
void MainWindow::onConnectionStatusChanged(int status) void MainWindow::onConnectionStatusChanged(int status)
{ {
qDebug() << "Wallet connection status changed " << Utils::QtEnumToString(static_cast<Wallet::ConnectionStatus>(status)); qDebug() << "Wallet connection status changed " << status;
// Update connection info in status bar. // Update connection info in status bar.
@@ -762,7 +652,7 @@ void MainWindow::onCreateTransactionSuccess(PendingTransaction *tx, const QStrin
auto tx_err = tx->errorString(); auto tx_err = tx->errorString();
qCritical() << tx_err; qCritical() << tx_err;
if (m_ctx->currentWallet->connectionStatus() == Wallet::ConnectionStatus_WrongVersion) if(m_ctx->currentWallet->connected() == Wallet::ConnectionStatus_WrongVersion)
err = QString("%1 Wrong daemon version: %2").arg(err).arg(tx_err); err = QString("%1 Wrong daemon version: %2").arg(err).arg(tx_err);
else else
err = QString("%1 %2").arg(err).arg(tx_err); err = QString("%1 %2").arg(err).arg(tx_err);
@@ -778,26 +668,15 @@ void MainWindow::onCreateTransactionSuccess(PendingTransaction *tx, const QStrin
} else { } else {
const auto &description = m_ctx->tmpTxDescription; const auto &description = m_ctx->tmpTxDescription;
auto *dialog = new TxConfDialog(m_ctx, tx, address, description, mixin, this); auto *dialog = new TxConfDialog(tx, address, description, mixin, this);
switch (dialog->exec()) { switch (dialog->exec()) {
case QDialog::Rejected: case QDialog::Rejected:
{ m_ctx->onCancelTransaction(tx, address);
if (!dialog->showAdvanced)
m_ctx->onCancelTransaction(tx, address);
break; break;
}
case QDialog::Accepted: case QDialog::Accepted:
m_ctx->currentWallet->commitTransactionAsync(tx); m_ctx->currentWallet->commitTransactionAsync(tx);
break; break;
} }
if (dialog->showAdvanced) {
auto *dialog_adv = new TxConfAdvDialog(m_ctx, description, this);
dialog_adv->setTransaction(tx);
dialog_adv->exec();
dialog_adv->deleteLater();
}
dialog->deleteLater();
} }
} }
@@ -842,10 +721,6 @@ void MainWindow::create_status_bar() {
m_statusLabelStatus->setTextInteractionFlags(Qt::TextSelectableByMouse); m_statusLabelStatus->setTextInteractionFlags(Qt::TextSelectableByMouse);
this->statusBar()->addWidget(m_statusLabelStatus); this->statusBar()->addWidget(m_statusLabelStatus);
m_statusLabelNetStats = new QLabel("", this);
m_statusLabelNetStats->setTextInteractionFlags(Qt::TextSelectableByMouse);
this->statusBar()->addWidget(m_statusLabelNetStats);
m_statusLabelBalance = new QLabel("Balance: 0.00 XMR", this); m_statusLabelBalance = new QLabel("Balance: 0.00 XMR", this);
m_statusLabelBalance->setTextInteractionFlags(Qt::TextSelectableByMouse); m_statusLabelBalance->setTextInteractionFlags(Qt::TextSelectableByMouse);
this->statusBar()->addPermanentWidget(m_statusLabelBalance); this->statusBar()->addPermanentWidget(m_statusLabelBalance);
@@ -878,13 +753,18 @@ void MainWindow::showWalletInfoDialog() {
} }
void MainWindow::showSeedDialog() { void MainWindow::showSeedDialog() {
auto *dialog = new SeedDialog(m_ctx->currentWallet, this); QString seed = m_ctx->currentWallet->getCacheAttribute("feather.seed");
if (seed.isEmpty()) {
seed = m_ctx->currentWallet->getSeed();
}
auto *dialog = new SeedDialog(seed, this);
dialog->exec(); dialog->exec();
dialog->deleteLater(); dialog->deleteLater();
} }
void MainWindow::showConnectionStatusDialog() { void MainWindow::showConnectionStatusDialog() {
auto status = m_ctx->currentWallet->connectionStatus(); auto status = m_ctx->currentWallet->connected(true);
bool synchronized = m_ctx->currentWallet->synchronized(); bool synchronized = m_ctx->currentWallet->synchronized();
QString statusMsg; QString statusMsg;
@@ -911,22 +791,32 @@ void MainWindow::showConnectionStatusDialog() {
statusMsg = "Unknown connection status (this should never happen)."; statusMsg = "Unknown connection status (this should never happen).";
} }
statusMsg += QString("\n\nTx: %1, Rx: %2").arg(Utils::formatBytes(m_ctx->currentWallet->getBytesSent()),
Utils::formatBytes(m_ctx->currentWallet->getBytesReceived()));
QMessageBox::information(this, "Connection Status", statusMsg); QMessageBox::information(this, "Connection Status", statusMsg);
} }
void MainWindow::showPasswordDialog() { void MainWindow::showPasswordDialog() {
auto *pdialog = new PasswordChangeDialog(this, m_ctx->currentWallet); auto *pdialog = new PasswordChangeDialog(this);
pdialog->exec(); int ret = pdialog->exec();
pdialog->deleteLater(); if (!ret) return;
this->updatePasswordIcon();
}
void MainWindow::updatePasswordIcon() { QApplication::setActiveWindow(this);
QIcon icon = m_ctx->currentWallet->getPassword().isEmpty() ? QIcon(":/assets/images/unlock.svg") : QIcon(":/assets/images/lock.svg");
m_statusBtnPassword->setIcon(icon); QString currentPassword = pdialog->getCurrentPassword();
QString newPassword = pdialog->getNewPassword();
if (currentPassword != m_ctx->walletPassword) {
QMessageBox::warning(this, "Error", "Incorrect password");
return;
}
if (m_ctx->currentWallet->setPassword(newPassword)) {
QMessageBox::information(this, "Information", "Password changed successfully");
}
else {
QMessageBox::warning(this, "Error", QString("Error: %1").arg(m_ctx->currentWallet->errorString()));
}
pdialog->deleteLater();
} }
void MainWindow::showRestoreHeightDialog() { void MainWindow::showRestoreHeightDialog() {
@@ -960,12 +850,6 @@ void MainWindow::showKeysDialog() {
dialog->deleteLater(); dialog->deleteLater();
} }
void MainWindow::showViewOnlyDialog() {
auto *dialog = new ViewOnlyDialog(m_ctx, this);
dialog->exec();
dialog->deleteLater();
}
void MainWindow::menuTorClicked() { void MainWindow::menuTorClicked() {
auto *dialog = new TorInfoDialog(m_ctx, this); auto *dialog = new TorInfoDialog(m_ctx, this);
@@ -980,8 +864,6 @@ void MainWindow::menuNewRestoreClicked() {
} }
void MainWindow::menuQuitClicked() { void MainWindow::menuQuitClicked() {
cleanupBeforeClose();
QCoreApplication::quit(); QCoreApplication::quit();
} }
@@ -1018,9 +900,7 @@ void MainWindow::menuAboutClicked() {
} }
void MainWindow::menuSettingsClicked() { void MainWindow::menuSettingsClicked() {
m_windowSettings->raise();
m_windowSettings->show(); m_windowSettings->show();
m_windowSettings->activateWindow();
} }
void MainWindow::menuSignVerifyClicked() { void MainWindow::menuSignVerifyClicked() {
@@ -1057,7 +937,11 @@ void MainWindow::homeWidgetChanged(const QString &widgetName) {
} }
void MainWindow::closeEvent(QCloseEvent *event) { void MainWindow::closeEvent(QCloseEvent *event) {
cleanupBeforeClose(); m_ctx->tor->stop();
this->saveGeo();
if(m_wizard != nullptr)
m_wizard->close();
QWidget::closeEvent(event); QWidget::closeEvent(event);
} }
@@ -1068,17 +952,17 @@ void MainWindow::donateButtonClicked() {
donation = 1.337; donation = 1.337;
ui->sendWidget->fill(m_ctx->featherDonationAddress, "Donation to the Feather development team", donation); ui->sendWidget->fill(m_ctx->featherDonationAddress, "Donation to the Feather development team", donation);
ui->tabWidget->setCurrentIndex(Tabs::SEND); ui->tabWidget->setCurrentIndex(2);
} }
void MainWindow::showHistoryTab() { void MainWindow::showHistoryTab() {
this->raise(); this->raise();
ui->tabWidget->setCurrentIndex(Tabs::HISTORY); ui->tabWidget->setCurrentIndex(1);
} }
void MainWindow::showSendTab() { void MainWindow::showSendTab() {
this->raise(); this->raise();
ui->tabWidget->setCurrentIndex(Tabs::SEND); ui->tabWidget->setCurrentIndex(2);
} }
void MainWindow::showCalcWindow() { void MainWindow::showCalcWindow() {
@@ -1087,7 +971,7 @@ void MainWindow::showCalcWindow() {
void MainWindow::showSendScreen(const CCSEntry &entry) { void MainWindow::showSendScreen(const CCSEntry &entry) {
ui->sendWidget->fill(entry); ui->sendWidget->fill(entry);
ui->tabWidget->setCurrentIndex(Tabs::SEND); ui->tabWidget->setCurrentIndex(2);
} }
void MainWindow::onViewOnBlockExplorer(const QString &txid) { void MainWindow::onViewOnBlockExplorer(const QString &txid) {
@@ -1105,29 +989,6 @@ void MainWindow::onAddContact(const QString &address, const QString &name) {
} }
} }
void MainWindow::importContacts() {
const QString targetFile = QFileDialog::getOpenFileName(this, "Import CSV file", QDir::homePath(), "CSV Files (*.csv)");
if(targetFile.isEmpty()) return;
auto *model = m_ctx->currentWallet->addressBookModel();
QMapIterator<QString, QString> i(model->readCSV(targetFile));
int inserts = 0;
while (i.hasNext()) {
i.next();
bool addressValid = WalletManager::addressValid(i.value(), m_ctx->currentWallet->nettype());
if(addressValid) {
m_ctx->currentWallet->addressBook()->addRow(i.value(), "", i.key());
inserts++;
}
}
if(inserts > 0) {
m_ctx->storeWallet();
}
QMessageBox::information(this, "Contacts imported", QString("Total contacts imported: %1").arg(inserts));
}
MainWindow *MainWindow::getInstance() { MainWindow *MainWindow::getInstance() {
return pMainWindow; return pMainWindow;
} }
@@ -1199,150 +1060,6 @@ void MainWindow::showWSNodeExhaustedMessage() {
QMessageBox::warning(this, "Could not connect to a node", msg); QMessageBox::warning(this, "Could not connect to a node", msg);
} }
void MainWindow::exportKeyImages() {
QString fn = QFileDialog::getSaveFileName(this, "Save key images to file", QDir::homePath(), "Key Images (*_keyImages)");
if (fn.isEmpty()) return;
if (!fn.endsWith("_keyImages")) fn += "_keyImages";
m_ctx->currentWallet->exportKeyImages(fn, true);
auto err = m_ctx->currentWallet->errorString();
if (!err.isEmpty()) {
QMessageBox::warning(this, "Key image export", QString("Failed to export key images.\nReason: %1").arg(err));
} else {
QMessageBox::information(this, "Key image export", "Successfully exported key images.");
}
}
void MainWindow::importKeyImages() {
QString fn = QFileDialog::getOpenFileName(this, "Import key image file", QDir::homePath(), "Key Images (*_keyImages)");
if (fn.isEmpty()) return;
m_ctx->currentWallet->importKeyImages(fn);
auto err = m_ctx->currentWallet->errorString();
if (!err.isEmpty()) {
QMessageBox::warning(this, "Key image import", QString("Failed to import key images.\n\n%1").arg(err));
} else {
QMessageBox::information(this, "Key image import", "Successfully imported key images");
m_ctx->refreshModels();
}
}
void MainWindow::exportOutputs() {
QString fn = QFileDialog::getSaveFileName(this, "Save outputs to file", QDir::homePath(), "Outputs (*_outputs)");
if (fn.isEmpty()) return;
if (!fn.endsWith("_outputs")) fn += "_outputs";
m_ctx->currentWallet->exportOutputs(fn, true);
auto err = m_ctx->currentWallet->errorString();
if (!err.isEmpty()) {
QMessageBox::warning(this, "Outputs export", QString("Failed to export outputs.\nReason: %1").arg(err));
} else {
QMessageBox::information(this, "Outputs export", "Successfully exported outputs.");
}
}
void MainWindow::importOutputs() {
QString fn = QFileDialog::getOpenFileName(this, "Import outputs file", QDir::homePath(), "Outputs (*_outputs)");
if (fn.isEmpty()) return;
m_ctx->currentWallet->importOutputs(fn);
auto err = m_ctx->currentWallet->errorString();
if (!err.isEmpty()) {
QMessageBox::warning(this, "Outputs import", QString("Failed to import outputs.\n\n%1").arg(err));
} else {
QMessageBox::information(this, "Outputs import", "Successfully imported outputs");
m_ctx->refreshModels();
}
}
void MainWindow::cleanupBeforeClose() {
m_ctx->walletManager->closeWallet();
m_ctx->tor->stop();
this->saveGeo();
}
void MainWindow::loadUnsignedTx() {
QString fn = QFileDialog::getOpenFileName(this, "Select transaction to load", QDir::homePath(), "Transaction (*unsigned_monero_tx)");
if (fn.isEmpty()) return;
UnsignedTransaction *tx = m_ctx->currentWallet->loadTxFile(fn);
auto err = m_ctx->currentWallet->errorString();
if (!err.isEmpty()) {
QMessageBox::warning(this, "Load transaction from file", QString("Failed to load transaction.\n\n%1").arg(err));
return;
}
this->createUnsignedTxDialog(tx);
}
void MainWindow::loadUnsignedTxFromClipboard() {
QString unsigned_tx = Utils::copyFromClipboard();
if (unsigned_tx.isEmpty()) {
QMessageBox::warning(this, "Load unsigned transaction from clipboard", "Clipboard is empty");
return;
}
UnsignedTransaction *tx = m_ctx->currentWallet->loadTxFromBase64Str(unsigned_tx);
auto err = m_ctx->currentWallet->errorString();
if (!err.isEmpty()) {
QMessageBox::warning(this, "Load unsigned transaction from clipboard", QString("Failed to load transaction.\n\n%1").arg(err));
return;
}
this->createUnsignedTxDialog(tx);
}
void MainWindow::loadSignedTx() {
QString fn = QFileDialog::getOpenFileName(this, "Select transaction to load", QDir::homePath(), "Transaction (*signed_monero_tx)");
if (fn.isEmpty()) return;
PendingTransaction *tx = m_ctx->currentWallet->loadSignedTxFile(fn);
auto err = m_ctx->currentWallet->errorString();
if (!err.isEmpty()) {
QMessageBox::warning(this, "Load signed transaction from file", err);
return;
}
auto *dialog = new TxConfAdvDialog(m_ctx, "", this);
dialog->setTransaction(tx);
dialog->exec();
dialog->deleteLater();
}
void MainWindow::loadSignedTxFromText() {
auto dialog = new BroadcastTxDialog(this, m_ctx);
dialog->exec();
dialog->deleteLater();
}
void MainWindow::createUnsignedTxDialog(UnsignedTransaction *tx) {
auto *dialog = new TxConfAdvDialog(m_ctx, "", this);
dialog->setUnsignedTransaction(tx);
dialog->exec();
dialog->deleteLater();
}
void MainWindow::importTransaction() {
auto result = QMessageBox::warning(this, "Warning", "Using this feature may allow a remote node to associate the transaction with your IP address.\n"
"\n"
"Connect to a trusted node or run Feather over Tor if network level metadata leakage is included in your threat model.",
QMessageBox::Ok | QMessageBox::Cancel);
if (result == QMessageBox::Ok) {
auto *dialog = new TxImportDialog(this, m_ctx);
dialog->exec();
dialog->deleteLater();
}
}
void MainWindow::updateNetStats() {
if (!m_ctx->currentWallet) {
m_statusLabelNetStats->setText("");
return;
}
if (m_ctx->currentWallet->connectionStatus() == Wallet::ConnectionStatus_Connected && m_ctx->currentWallet->synchronized()) {
m_statusLabelNetStats->setText("");
return;
}
m_statusLabelNetStats->setText(QString("(D: %1)").arg(Utils::formatBytes(m_ctx->currentWallet->getBytesReceived())));
}
MainWindow::~MainWindow() { MainWindow::~MainWindow() {
delete ui; delete ui;
} }
+2 -47
View File
@@ -4,10 +4,6 @@
#ifndef MAINWINDOW_H #ifndef MAINWINDOW_H
#define MAINWINDOW_H #define MAINWINDOW_H
#ifdef Q_OS_MAC
#include "src/kdmactouchbar.h"
#endif
#include <QMainWindow> #include <QMainWindow>
#include <QSystemTrayIcon> #include <QSystemTrayIcon>
#include <QScreen> #include <QScreen>
@@ -23,7 +19,6 @@
#include "widgets/ccswidget.h" #include "widgets/ccswidget.h"
#include "widgets/redditwidget.h" #include "widgets/redditwidget.h"
#include "widgets/tickerwidget.h" #include "widgets/tickerwidget.h"
#include "widgets/xmrigwidget.h"
#include "utils/networking.h" #include "utils/networking.h"
#include "appcontext.h" #include "appcontext.h"
#include "utils/config.h" #include "utils/config.h"
@@ -69,18 +64,6 @@ public:
qreal screenDpiPhysical; qreal screenDpiPhysical;
qreal screenRatio; qreal screenRatio;
enum Tabs {
HOME = 0,
HISTORY,
SEND,
RECEIVE,
COINS,
CALC,
MORPHTOKEN,
XMR_TO,
XMRIG
};
public slots: public slots:
void initWidgets(); void initWidgets();
void initMenu(); void initMenu();
@@ -96,7 +79,6 @@ public slots:
void showConnectionStatusDialog(); void showConnectionStatusDialog();
void showPasswordDialog(); void showPasswordDialog();
void showKeysDialog(); void showKeysDialog();
void showViewOnlyDialog();
void donateButtonClicked(); void donateButtonClicked();
void showCalcWindow(); void showCalcWindow();
void showSendTab(); void showSendTab();
@@ -112,22 +94,10 @@ public slots:
void onWalletCreated(Wallet *wallet); void onWalletCreated(Wallet *wallet);
void menuWalletCloseClicked(); void menuWalletCloseClicked();
void menuWalletOpenClicked(); void menuWalletOpenClicked();
void onWalletOpenPasswordRequired(bool invalidPassword, const QString &path); void onWalletOpenPasswordRequired(bool invalidPassword);
void onViewOnBlockExplorer(const QString &txid); void onViewOnBlockExplorer(const QString &txid);
void onAddContact(const QString &address, const QString &name); void onAddContact(const QString &address, const QString &name);
void importContacts();
void showRestoreHeightDialog(); void showRestoreHeightDialog();
void importTransaction();
// offline tx signing
void exportKeyImages();
void importKeyImages();
void exportOutputs();
void importOutputs();
void loadUnsignedTx();
void loadUnsignedTxFromClipboard();
void loadSignedTx();
void loadSignedTxFromText();
// libwalletqt // libwalletqt
void onBalanceUpdated(double balance, double unlocked, const QString &balance_str, const QString &unlocked_str); void onBalanceUpdated(double balance, double unlocked, const QString &balance_str, const QString &unlocked_str);
@@ -149,7 +119,6 @@ private:
static MainWindow * pMainWindow; static MainWindow * pMainWindow;
void closeEvent(QCloseEvent *event) override; void closeEvent(QCloseEvent *event) override;
void cleanupBeforeClose();
void create_status_bar(); void create_status_bar();
void initMain(); void initMain();
void loadSkins(); void loadSkins();
@@ -159,11 +128,6 @@ private:
void showDebugInfo(); void showDebugInfo();
void showNodeExhaustedMessage(); void showNodeExhaustedMessage();
void showWSNodeExhaustedMessage(); void showWSNodeExhaustedMessage();
void createUnsignedTxDialog(UnsignedTransaction *tx);
void touchbarShowWizard();
void touchbarShowWallet();
void updatePasswordIcon();
void updateNetStats();
WalletWizard *createWizard(WalletWizard::Page startPage); WalletWizard *createWizard(WalletWizard::Page startPage);
@@ -173,7 +137,6 @@ private:
SignVerifyDialog *m_windowSignVerify = nullptr; SignVerifyDialog *m_windowSignVerify = nullptr;
RestoreDialog *m_restoreDialog = nullptr; RestoreDialog *m_restoreDialog = nullptr;
AboutDialog *m_aboutDialog = nullptr; AboutDialog *m_aboutDialog = nullptr;
XMRigWidget *m_xmrig = nullptr;
bool m_windowSpawned = false; bool m_windowSpawned = false;
@@ -193,7 +156,6 @@ private:
// lower status bar // lower status bar
QLabel *m_statusLabelBalance; QLabel *m_statusLabelBalance;
QLabel *m_statusLabelStatus; QLabel *m_statusLabelStatus;
QLabel *m_statusLabelNetStats;
StatusBarButton *m_statusBtnConnectionStatusIndicator; StatusBarButton *m_statusBtnConnectionStatusIndicator;
StatusBarButton *m_statusBtnPassword; StatusBarButton *m_statusBtnPassword;
StatusBarButton *m_statusBtnPreferences; StatusBarButton *m_statusBtnPreferences;
@@ -203,20 +165,13 @@ private:
SubaddressProxyModel *subaddressProxyModel; SubaddressProxyModel *subaddressProxyModel;
TransactionHistoryModel *txHistModel; TransactionHistoryModel *txHistModel;
CoinsModel *coinsModel; CoinsModel *coinsModel;
#ifdef Q_OS_MAC
QAction *m_touchbarActionWelcome;
KDMacTouchBar *m_touchbar;
QList<QAction *> m_touchbarWalletItems;
QList<QAction *> m_touchbarWizardItems;
#endif
QSignalMapper *m_tabShowHideSignalMapper; QSignalMapper *m_tabShowHideSignalMapper;
QMap<QString, ToggleTab*> m_tabShowHideMapper; QMap<QString, ToggleTab*> m_tabShowHideMapper;
WalletWizard *m_wizard = nullptr; WalletWizard *m_wizard = nullptr;
QMap<QString, QString> m_skins; QMap<QString, QString> m_skins;
QTimer m_updateBytes;
private slots: private slots:
void menuToggleTabVisible(const QString &key); void menuToggleTabVisible(const QString &key);
}; };
+16 -188
View File
@@ -6,7 +6,7 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>1156</width> <width>894</width>
<height>496</height> <height>496</height>
</rect> </rect>
</property> </property>
@@ -224,41 +224,13 @@
</item> </item>
</layout> </layout>
</widget> </widget>
<widget class="QWidget" name="tabCalc">
<attribute name="icon">
<iconset resource="assets.qrc">
<normaloff>:/assets/images/coldcard.png</normaloff>:/assets/images/coldcard.png</iconset>
</attribute>
<attribute name="title">
<string>Calc</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_4">
<item row="0" column="0">
<widget class="CalcWidget" name="conversionWidget" native="true"/>
</item>
</layout>
</widget>
<widget class="QWidget" name="tabMorphToken">
<attribute name="icon">
<iconset resource="assets.qrc">
<normaloff>:/assets/images/morphtoken.png</normaloff>:/assets/images/morphtoken.png</iconset>
</attribute>
<attribute name="title">
<string>MorphToken</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<widget class="MorphTokenWidget" name="morphtokenWidget" native="true"/>
</item>
</layout>
</widget>
<widget class="QWidget" name="tabXmrTo"> <widget class="QWidget" name="tabXmrTo">
<attribute name="icon"> <attribute name="icon">
<iconset resource="assets.qrc"> <iconset resource="assets.qrc">
<normaloff>:/assets/images/xmrto.png</normaloff>:/assets/images/xmrto.png</iconset> <normaloff>:/assets/images/xmrto.png</normaloff>:/assets/images/xmrto.png</iconset>
</attribute> </attribute>
<attribute name="title"> <attribute name="title">
<string>XMR.to</string> <string>xmr.to</string>
</attribute> </attribute>
<layout class="QVBoxLayout" name="verticalLayout_4"> <layout class="QVBoxLayout" name="verticalLayout_4">
<property name="leftMargin"> <property name="leftMargin">
@@ -294,17 +266,17 @@
</item> </item>
</layout> </layout>
</widget> </widget>
<widget class="QWidget" name="tabXmrRig"> <widget class="QWidget" name="tabCalc">
<attribute name="icon"> <attribute name="icon">
<iconset resource="assets.qrc"> <iconset resource="assets.qrc">
<normaloff>:/assets/images/xmrig.ico</normaloff>:/assets/images/xmrig.ico</iconset> <normaloff>:/assets/images/coldcard.png</normaloff>:/assets/images/coldcard.png</iconset>
</attribute> </attribute>
<attribute name="title"> <attribute name="title">
<string>XMRig</string> <string>Calc</string>
</attribute> </attribute>
<layout class="QGridLayout" name="gridLayout_2"> <layout class="QGridLayout" name="gridLayout_4">
<item row="0" column="0"> <item row="0" column="0">
<layout class="QGridLayout" name="xmrRigLayout"/> <widget class="CalcWidget" name="conversionWidget" native="true"/>
</item> </item>
</layout> </layout>
</widget> </widget>
@@ -318,7 +290,7 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>1156</width> <width>894</width>
<height>30</height> <height>30</height>
</rect> </rect>
</property> </property>
@@ -347,33 +319,15 @@
<string>Contacts</string> <string>Contacts</string>
</property> </property>
<addaction name="actionExportContactsCSV"/> <addaction name="actionExportContactsCSV"/>
<addaction name="actionImportContactsCSV"/>
</widget> </widget>
<widget class="QMenu" name="menuAdvanced"> <widget class="QMenu" name="menuAdvanced">
<property name="title"> <property name="title">
<string>Advanced</string> <string>Advanced</string>
</property> </property>
<widget class="QMenu" name="menuExport">
<property name="title">
<string>Export</string>
</property>
<addaction name="actionExportOutputs"/>
<addaction name="actionExportKeyImages"/>
</widget>
<widget class="QMenu" name="menuImport">
<property name="title">
<string>Import</string>
</property>
<addaction name="actionImportOutputs"/>
<addaction name="actionImportKeyImages"/>
</widget>
<addaction name="actionStore_wallet"/> <addaction name="actionStore_wallet"/>
<addaction name="actionUpdate_balance"/> <addaction name="actionUpdate_balance"/>
<addaction name="actionRefresh_tabs"/> <addaction name="actionRefresh_tabs"/>
<addaction name="separator"/>
<addaction name="actionChange_restore_height"/> <addaction name="actionChange_restore_height"/>
<addaction name="menuExport"/>
<addaction name="menuImport"/>
</widget> </widget>
<addaction name="actionInformation"/> <addaction name="actionInformation"/>
<addaction name="menuAdvanced"/> <addaction name="menuAdvanced"/>
@@ -381,7 +335,6 @@
<addaction name="actionPassword"/> <addaction name="actionPassword"/>
<addaction name="actionSeed"/> <addaction name="actionSeed"/>
<addaction name="actionKeys"/> <addaction name="actionKeys"/>
<addaction name="actionViewOnly"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="menuHistory"/> <addaction name="menuHistory"/>
<addaction name="menuContacts"/> <addaction name="menuContacts"/>
@@ -390,27 +343,9 @@
<property name="title"> <property name="title">
<string>Tools</string> <string>Tools</string>
</property> </property>
<widget class="QMenu" name="menuLoad_transaction">
<property name="title">
<string>Load unsigned transaction</string>
</property>
<addaction name="actionLoadUnsignedTxFromFile"/>
<addaction name="actionLoadUnsignedTxFromClipboard"/>
</widget>
<widget class="QMenu" name="menuLoad_signed_transaction">
<property name="title">
<string>Broadcast transaction</string>
</property>
<addaction name="actionLoadSignedTxFromFile"/>
<addaction name="actionLoadSignedTxFromText"/>
</widget>
<addaction name="actionSignVerify"/> <addaction name="actionSignVerify"/>
<addaction name="actionVerifyTxProof"/> <addaction name="actionVerifyTxProof"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="menuLoad_transaction"/>
<addaction name="menuLoad_signed_transaction"/>
<addaction name="actionImport_transaction"/>
<addaction name="separator"/>
<addaction name="actionCalculator"/> <addaction name="actionCalculator"/>
<addaction name="actionCreateDesktopEntry"/> <addaction name="actionCreateDesktopEntry"/>
</widget> </widget>
@@ -419,6 +354,7 @@
<string>Help</string> <string>Help</string>
</property> </property>
<addaction name="actionAbout"/> <addaction name="actionAbout"/>
<addaction name="actionAbout_Qt"/>
<addaction name="actionOfficialWebsite"/> <addaction name="actionOfficialWebsite"/>
<addaction name="actionDonate_to_Feather"/> <addaction name="actionDonate_to_Feather"/>
<addaction name="separator"/> <addaction name="separator"/>
@@ -430,10 +366,8 @@
<string>View</string> <string>View</string>
</property> </property>
<addaction name="actionShow_Coins"/> <addaction name="actionShow_Coins"/>
<addaction name="actionShow_calc"/>
<addaction name="actionShow_MorphToken"/>
<addaction name="actionShow_xmr_to"/> <addaction name="actionShow_xmr_to"/>
<addaction name="actionShow_XMRig"/> <addaction name="actionShow_calc"/>
</widget> </widget>
<addaction name="menuFile"/> <addaction name="menuFile"/>
<addaction name="menuWallet"/> <addaction name="menuWallet"/>
@@ -521,7 +455,7 @@
</action> </action>
<action name="actionShow_xmr_to"> <action name="actionShow_xmr_to">
<property name="text"> <property name="text">
<string>Show XMR.to</string> <string>Show Xmr.To</string>
</property> </property>
</action> </action>
<action name="actionShow_calc"> <action name="actionShow_calc">
@@ -554,11 +488,6 @@
<string>Refresh models</string> <string>Refresh models</string>
</property> </property>
</action> </action>
<action name="actionImportContactsCSV">
<property name="text">
<string>Import CSV</string>
</property>
</action>
<action name="actionExportContactsCSV"> <action name="actionExportContactsCSV">
<property name="text"> <property name="text">
<string>Export CSV</string> <string>Export CSV</string>
@@ -574,6 +503,11 @@
<string>Keys</string> <string>Keys</string>
</property> </property>
</action> </action>
<action name="actionAbout_Qt">
<property name="text">
<string>About Qt</string>
</property>
</action>
<action name="actionCreateDesktopEntry"> <action name="actionCreateDesktopEntry">
<property name="text"> <property name="text">
<string>Create desktop entry</string> <string>Create desktop entry</string>
@@ -584,106 +518,6 @@
<string>Debug info</string> <string>Debug info</string>
</property> </property>
</action> </action>
<action name="actionCreate_view_only_details">
<property name="text">
<string>Details</string>
</property>
</action>
<action name="actionCreate_view_only_wallet_file">
<property name="text">
<string>Export wallet file</string>
</property>
</action>
<action name="actionViewOnly">
<property name="text">
<string>View-Only</string>
</property>
</action>
<action name="actionExport_key_images">
<property name="text">
<string>Export key images</string>
</property>
</action>
<action name="actionImport_key_images">
<property name="text">
<string>Import key images</string>
</property>
</action>
<action name="actionExport_outputs">
<property name="text">
<string>Export outputs</string>
</property>
</action>
<action name="actionImport_outputs">
<property name="text">
<string>Import outputs</string>
</property>
</action>
<action name="actionExportKeyImages">
<property name="text">
<string>Key Images</string>
</property>
</action>
<action name="actionExportOutputs">
<property name="text">
<string>Outputs</string>
</property>
</action>
<action name="actionImportKeyImages">
<property name="text">
<string>Key images</string>
</property>
</action>
<action name="actionImportOutputs">
<property name="text">
<string>Outputs</string>
</property>
</action>
<action name="actionShow_XMRig">
<property name="text">
<string>Show XMRig</string>
</property>
</action>
<action name="actionImportTransaction">
<property name="text">
<string>Transaction</string>
</property>
</action>
<action name="actionSubmitTransaction">
<property name="text">
<string>Submit transaction file</string>
</property>
</action>
<action name="actionLoadUnsignedTxFromFile">
<property name="text">
<string>From file</string>
</property>
</action>
<action name="actionLoadSignedTxFromFile">
<property name="text">
<string>From file</string>
</property>
</action>
<action name="actionLoadUnsignedTxFromClipboard">
<property name="text">
<string>From clipboard</string>
</property>
</action>
<action name="actionLoadSignedTxFromText">
<property name="text">
<string>From text</string>
</property>
</action>
<action name="actionImport_transaction">
<property name="text">
<string>Import transaction</string>
</property>
</action>
<action name="actionShow_MorphToken">
<property name="text">
<string>Show MorphToken</string>
</property>
</action>
</widget> </widget>
<layoutdefault spacing="6" margin="11"/> <layoutdefault spacing="6" margin="11"/>
<customwidgets> <customwidgets>
@@ -728,12 +562,6 @@
<header>calcwidget.h</header> <header>calcwidget.h</header>
<container>1</container> <container>1</container>
</customwidget> </customwidget>
<customwidget>
<class>MorphTokenWidget</class>
<extends>QWidget</extends>
<header>MorphTokenWidget.h</header>
<container>1</container>
</customwidget>
</customwidgets> </customwidgets>
<resources> <resources>
<include location="assets.qrc"/> <include location="assets.qrc"/>
-23
View File
@@ -174,26 +174,3 @@ bool AddressBookModel::writeCSV(const QString &path) {
csv = QString("address,description\n%1").arg(csv); csv = QString("address,description\n%1").arg(csv);
return Utils::fileWrite(path, csv); return Utils::fileWrite(path, csv);
} }
QMap<QString, QString> AddressBookModel::readCSV(const QString &path) {
if(!Utils::fileExists(path)) {
return QMap<QString, QString>();
}
QString csv = Utils::barrayToString(Utils::fileOpen(path));
QTextStream stream(&csv);
QMap<QString, QString> map;
while(!stream.atEnd()) {
QStringList line = stream.readLine().split(",");
if(line.length() != 2) {
continue;
}
QString address = line.at(0);
QString description = line.at(1);
description = description.replace("\"", "");
if(!description.isEmpty() && !address.isEmpty()) {
map[description] = address;
}
}
return map;
}
-1
View File
@@ -36,7 +36,6 @@ public:
bool isShowFullAddresses() const; bool isShowFullAddresses() const;
void setShowFullAddresses(bool show); void setShowFullAddresses(bool show);
bool writeCSV(const QString &path); bool writeCSV(const QString &path);
QMap<QString, QString> readCSV(const QString &path);
public slots: public slots:
void startReset(); void startReset();
+3 -36
View File
@@ -6,7 +6,6 @@
#include "Coins.h" #include "Coins.h"
#include <wallet/api/wallet2_api.h> #include <wallet/api/wallet2_api.h>
#include "ModelUtils.h" #include "ModelUtils.h"
#include "globals.h"
#include <QDebug> #include <QDebug>
#include <QHash> #include <QHash>
@@ -20,9 +19,6 @@ CoinsModel::CoinsModel(QObject *parent, Coins *coins)
{ {
connect(m_coins, &Coins::refreshStarted, this, &CoinsModel::startReset); connect(m_coins, &Coins::refreshStarted, this, &CoinsModel::startReset);
connect(m_coins, &Coins::refreshFinished, this, &CoinsModel::endReset); connect(m_coins, &Coins::refreshFinished, this, &CoinsModel::endReset);
m_eye = QIcon(":/assets/images/eye1.png");
m_eyeBlind = QIcon(":/assets/images/eye_blind.png");
} }
void CoinsModel::startReset(){ void CoinsModel::startReset(){
@@ -77,7 +73,7 @@ QVariant CoinsModel::data(const QModelIndex &index, int role) const
result = QBrush(QColor(173, 216, 230)); result = QBrush(QColor(173, 216, 230));
} }
else if (!cInfo.unlocked()) { else if (!cInfo.unlocked()) {
result = QBrush(QColor("#60993E")); result = QBrush(QColor("#BFFF00"));
} }
} }
else if (role == Qt::TextAlignmentRole) { else if (role == Qt::TextAlignmentRole) {
@@ -86,19 +82,6 @@ QVariant CoinsModel::data(const QModelIndex &index, int role) const
result = Qt::AlignRight; result = Qt::AlignRight;
} }
} }
else if (role == Qt::DecorationRole) {
switch (index.column()) {
case KeyImageKnown:
{
if (cInfo.keyImageKnown()) {
result = QVariant(m_eye);
}
else {
result = QVariant(m_eyeBlind);
}
}
}
}
else if (role == Qt::FontRole) { else if (role == Qt::FontRole) {
switch(index.column()) { switch(index.column()) {
case PubKey: case PubKey:
@@ -108,16 +91,6 @@ QVariant CoinsModel::data(const QModelIndex &index, int role) const
} }
} }
else if (role == Qt::ToolTipRole) { else if (role == Qt::ToolTipRole) {
switch(index.column()) {
case KeyImageKnown:
{
if (cInfo.keyImageKnown()) {
result = "Key image known";
} else {
result = "Key image unknown. Outgoing transactions that include this output will not be detected.";
}
}
}
if (cInfo.frozen()) { if (cInfo.frozen()) {
result = "Output is frozen."; result = "Output is frozen.";
} }
@@ -169,8 +142,6 @@ QVariant CoinsModel::parseTransactionInfo(const CoinsInfo &cInfo, int column, in
{ {
switch (column) switch (column)
{ {
case KeyImageKnown:
return "";
case PubKey: case PubKey:
return cInfo.pubKey().mid(0,8); return cInfo.pubKey().mid(0,8);
case OutputPoint: case OutputPoint:
@@ -191,14 +162,10 @@ QVariant CoinsModel::parseTransactionInfo(const CoinsInfo &cInfo, int column, in
case SpentHeight: case SpentHeight:
return cInfo.spentHeight(); return cInfo.spentHeight();
case Amount: case Amount:
{ return QString::number(cInfo.amount() / 1e12, 'f', 12);
if (role == Qt::UserRole) {
return cInfo.amount() / globals::cdiv;
}
return QString::number(cInfo.amount() / globals::cdiv, 'f', 12);
}
case Frozen: case Frozen:
return cInfo.frozen(); return cInfo.frozen();
default: default:
{ {
qCritical() << "Unimplemented role"; qCritical() << "Unimplemented role";

Some files were not shown because too many files have changed in this diff Show More