Compare commits
218 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2e2ae5c88f | ||
|
|
2021d61d91 | ||
|
|
46d0b6b0ff | ||
|
|
8ae8019f5a | ||
|
|
1a6ea3302c | ||
|
|
4de4e82ee6 | ||
|
|
5da0d5768a | ||
|
|
58586ce2dc | ||
|
|
1cc9e8af49 | ||
|
|
37a5bdc331 | ||
|
|
cc4815a3db | ||
|
|
46eba838f5 | ||
|
|
b31cc36de2 | ||
|
|
76dd4fee2f | ||
|
|
55a4b67880 | ||
|
|
97fb3d4982 | ||
|
|
28f0645d9e | ||
|
|
85dff323c8 | ||
|
|
0468e0e43a | ||
|
|
2cc3ebd315 | ||
|
|
377a1a9680 | ||
|
|
877f822de0 | ||
|
|
0feef2268d | ||
|
|
002fe8eefa | ||
|
|
1dba06a7ff | ||
|
|
838b0179e5 | ||
|
|
b12ad939ad | ||
|
|
74fbf77f62 | ||
|
|
211ef24d18 | ||
|
|
a2e0ea4faf | ||
|
|
6ab104ead7 | ||
|
|
62748b6121 | ||
|
|
8bbf2bfcbb | ||
|
|
de81af0e8d | ||
|
|
346913f3db | ||
|
|
fd8983a7ff | ||
|
|
4ef5ca5721 | ||
|
|
119deb4e82 | ||
|
|
ea92f3f272 | ||
|
|
9c383bcc24 | ||
|
|
4fba8e654d | ||
|
|
14383a1922 | ||
|
|
1610b93975 | ||
|
|
8ece450f18 | ||
|
|
ced654707d | ||
|
|
da63ab2e05 | ||
|
|
ddd95f73b4 | ||
|
|
08e386f63f | ||
|
|
bf324ec2d9 | ||
|
|
e9afaa9cc8 | ||
|
|
78e3b947d1 | ||
|
|
05b4a3dd6b | ||
|
|
c2f706a28a | ||
|
|
4df925e8a8 | ||
|
|
adf88c63ec | ||
|
|
c2545e226b | ||
|
|
5c7c4dde14 | ||
|
|
2bbb6adb4f | ||
|
|
493105b457 | ||
|
|
2bf0dd840f | ||
|
|
0f67580e8f | ||
|
|
599033815a | ||
|
|
de49ddcf5b | ||
|
|
d752117ed3 | ||
|
|
fa9285a108 | ||
|
|
9194522b56 | ||
|
|
11a16952c5 | ||
|
|
a959919b8a | ||
|
|
6f88ad0a13 | ||
|
|
cb169f11d4 | ||
|
|
98b81fa1ee | ||
|
|
a6fadd2140 | ||
|
|
09bf4a1e71 | ||
|
|
f44fcb4459 | ||
|
|
c5d598f401 | ||
|
|
9476a9880c | ||
|
|
487f2ceecb | ||
|
|
d0950499da | ||
|
|
56df20ba27 | ||
|
|
41b827b65d | ||
|
|
0b6ceab25b | ||
|
|
2566f445b2 | ||
|
|
9199f95af5 | ||
|
|
f2b4e1ea3e | ||
|
|
621c11925b | ||
|
|
a4cc91cca2 | ||
|
|
db4123ccb5 | ||
|
|
98f8f194cd | ||
|
|
f8a3a26e0d | ||
|
|
f7792b72bf | ||
|
|
d160828cda | ||
|
|
e85b51e1c2 | ||
|
|
6b926b3199 | ||
|
|
008a38aae2 | ||
|
|
70e3c2d3ad | ||
|
|
817b015335 | ||
|
|
bddb9b0050 | ||
|
|
78f7b05ecb | ||
|
|
999bc21d6b | ||
|
|
901b4b0f77 | ||
|
|
69dc0b3570 | ||
|
|
0bebf412fd | ||
|
|
ce1c5aebf7 | ||
|
|
7eef4f3364 | ||
|
|
ecadd44a16 | ||
|
|
4bd7d43588 | ||
|
|
50c8f30d0b | ||
|
|
e2203a871c | ||
|
|
3e159e0ed6 | ||
|
|
d922c91071 | ||
|
|
fa35410851 | ||
|
|
23b74a3412 | ||
|
|
6e24930026 | ||
|
|
b8b96ee719 | ||
|
|
22450cb68d | ||
|
|
a4b907a668 | ||
|
|
843536c7a1 | ||
|
|
31ae9b3947 | ||
|
|
c72729fa5d | ||
|
|
a07299f64d | ||
|
|
d55a001875 | ||
|
|
917d6d4243 | ||
|
|
05e629c0eb | ||
|
|
9c901b33f0 | ||
|
|
a0ff56fbef | ||
|
|
fc8c1114b2 | ||
|
|
93e5ef883c | ||
|
|
10a36f96f6 | ||
|
|
80cd2e08a4 | ||
|
|
97755e1b34 | ||
|
|
8a8a3847d7 | ||
|
|
00a95c11a0 | ||
|
|
8f12e97b79 | ||
|
|
9961305867 | ||
|
|
9e83942920 | ||
|
|
e390b43bdc | ||
|
|
cc8ddde01b | ||
|
|
98b2727857 | ||
|
|
4d2186fb75 | ||
|
|
419a1975eb | ||
|
|
9846bff226 | ||
|
|
a37c3756b7 | ||
|
|
c844e3d179 | ||
|
|
61d8b5efb6 | ||
|
|
ecf5c501d6 | ||
|
|
db639b96a3 | ||
|
|
e65956e910 | ||
|
|
09ce233f4b | ||
|
|
34893e169e | ||
|
|
dd171c8b49 | ||
|
|
985406e70f | ||
|
|
8bf457c864 | ||
|
|
96dab92f33 | ||
|
|
d348324f50 | ||
|
|
4f5903e7fd | ||
|
|
bdadd98622 | ||
|
|
bdad630d51 | ||
|
|
987bf920c7 | ||
|
|
f8e1b9bdb6 | ||
|
|
06fe68b56c | ||
|
|
b811d6a84f | ||
|
|
f91e1791fe | ||
|
|
49ade0d689 | ||
|
|
c970588c55 | ||
|
|
4aab43a127 | ||
|
|
c0aface962 | ||
|
|
bd7bd43504 | ||
|
|
b44d359f9e | ||
|
|
2f109d3333 | ||
|
|
7cc225039c | ||
|
|
cef9be3d02 | ||
|
|
1c31f2e481 | ||
|
|
1173dd2826 | ||
|
|
6239f949fe | ||
|
|
4ec78b35f8 | ||
|
|
87b1518023 | ||
|
|
02c55e3fd1 | ||
|
|
96762ebf09 | ||
|
|
702d3b8ec1 | ||
|
|
a3069e4a58 | ||
|
|
bd9a2d7bbb | ||
|
|
1ef9a5c2d7 | ||
|
|
3f48e3ef1c | ||
|
|
d9f7482ae8 | ||
|
|
facec65dfc | ||
|
|
dc331f0e64 | ||
|
|
67eb486e63 | ||
|
|
edb0358916 | ||
|
|
569ba16df8 | ||
|
|
d48438aeef | ||
|
|
92b3f5a2ee | ||
|
|
f430d49304 | ||
|
|
76c3b3cd1d | ||
|
|
35aee155d7 | ||
|
|
d93af5a469 | ||
|
|
051282931a | ||
|
|
d3780abe33 | ||
|
|
f327d20deb | ||
|
|
dcc16a44be | ||
|
|
36940f07c9 | ||
|
|
b99b333b71 | ||
|
|
5fa310c961 | ||
|
|
e36b166edd | ||
|
|
27525b37e0 | ||
|
|
d3d78416d7 | ||
|
|
f30570d54b | ||
|
|
20579049fa | ||
|
|
544cff7dc1 | ||
|
|
165817ec02 | ||
|
|
95c07e1a62 | ||
|
|
2f8f7c2054 | ||
|
|
99ad8ef1ba | ||
|
|
18a76299f2 | ||
|
|
57c205206c | ||
|
|
afb88ff511 | ||
|
|
75746a8153 | ||
|
|
66d29a4d40 | ||
|
|
6dd7445938 |
107
.github/qt_helper.py
vendored
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
import defusedxml.ElementTree
|
||||||
|
import hashlib
|
||||||
|
import mmap
|
||||||
|
import pathlib
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import urllib.parse
|
||||||
|
import urllib.request
|
||||||
|
import xml.etree.ElementTree as ET
|
||||||
|
|
||||||
|
MAX_TRIES = 32
|
||||||
|
|
||||||
|
def fetch_links_to_archives(os, target, major, minor, patch, toolchain):
|
||||||
|
MAX_XML_SIZE = 1024 * 1024 * 1024
|
||||||
|
MIRROR = 'download.qt.io'
|
||||||
|
base_url = f'https://{MIRROR}/online/qtsdkrepository/{os}/{target}/qt{major}_{major}{minor}{patch}'
|
||||||
|
url = f'{base_url}/Updates.xml'
|
||||||
|
for _ in range(MAX_TRIES):
|
||||||
|
try:
|
||||||
|
resp = urllib.request.urlopen(url).read(MAX_XML_SIZE)
|
||||||
|
update_xml = defusedxml.ElementTree.fromstring(resp)
|
||||||
|
break
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
raise
|
||||||
|
except BaseException as e:
|
||||||
|
print('error', e, flush=True)
|
||||||
|
else:
|
||||||
|
return
|
||||||
|
for pkg in update_xml.findall('./PackageUpdate'):
|
||||||
|
name = pkg.find('.//Name')
|
||||||
|
if name == None:
|
||||||
|
continue
|
||||||
|
if name.text != f'qt.qt{major}.{major}{minor}{patch}.{toolchain}':
|
||||||
|
continue
|
||||||
|
version = pkg.find('.//Version')
|
||||||
|
if version == None:
|
||||||
|
continue
|
||||||
|
archives = pkg.find('.//DownloadableArchives')
|
||||||
|
if archives == None or archives.text == None:
|
||||||
|
continue
|
||||||
|
for archive in archives.text.split(', '):
|
||||||
|
url = f'{base_url}/{name.text}/{version.text}{archive}'
|
||||||
|
file_name = pathlib.Path(urllib.parse.urlparse(url).path).name
|
||||||
|
yield {'name': file_name, 'url': url}
|
||||||
|
|
||||||
|
def download(links):
|
||||||
|
metalink = ET.Element('metalink', xmlns = "urn:ietf:params:xml:ns:metalink")
|
||||||
|
for link in links:
|
||||||
|
file = ET.SubElement(metalink, 'file', name = link['name'])
|
||||||
|
ET.SubElement(file, 'url').text = link['url']
|
||||||
|
data = ET.tostring(metalink, encoding='UTF-8', xml_declaration=True)
|
||||||
|
for _ in range(MAX_TRIES):
|
||||||
|
with subprocess.Popen([
|
||||||
|
'aria2c',
|
||||||
|
'--connect-timeout=8',
|
||||||
|
'--console-log-level=warn',
|
||||||
|
'--continue',
|
||||||
|
'--follow-metalink=mem',
|
||||||
|
'--max-concurrent-downloads=100',
|
||||||
|
'--max-connection-per-server=16',
|
||||||
|
'--max-file-not-found=100',
|
||||||
|
'--max-tries=100',
|
||||||
|
'--min-split-size=1MB',
|
||||||
|
'--retry-wait=1',
|
||||||
|
'--split=100',
|
||||||
|
'--summary-interval=0',
|
||||||
|
'--timeout=8',
|
||||||
|
'--user-agent=',
|
||||||
|
'--metalink-file=-',
|
||||||
|
], stdin=subprocess.PIPE) as aria:
|
||||||
|
aria.communicate(data)
|
||||||
|
if aria.wait() == 0:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def calc_hash_sum(files):
|
||||||
|
obj = hashlib.new('sha256')
|
||||||
|
for path in files:
|
||||||
|
with open(path, 'rb') as f:
|
||||||
|
with mmap.mmap(f.fileno(), 0, mmap.MAP_SHARED, mmap.PROT_READ) as m:
|
||||||
|
file_hash = hashlib.new('sha256', m).digest()
|
||||||
|
obj.update(file_hash)
|
||||||
|
return obj.digest().hex()
|
||||||
|
|
||||||
|
def extract_archives(files, out='.', targets=[]):
|
||||||
|
for path in files:
|
||||||
|
if subprocess.Popen(['7z', 'x', '-bd', '-y', '-aoa', f'-o{out}', path] + targets,
|
||||||
|
stdout=subprocess.DEVNULL,
|
||||||
|
).wait() != 0:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def main():
|
||||||
|
os, target, version, toolchain, expect = sys.argv[1:]
|
||||||
|
major, minor, patch = version.split('.')
|
||||||
|
links = [*fetch_links_to_archives(os, target, major, minor, patch, toolchain)]
|
||||||
|
print(*[l['url'].encode() for l in links], sep='\n', flush=True)
|
||||||
|
assert download(links)
|
||||||
|
result = calc_hash_sum([l['name'] for l in links])
|
||||||
|
print('result', result, 'expect', expect, flush=True)
|
||||||
|
assert result == expect
|
||||||
|
assert extract_archives([l['name'] for l in links], '.', ['{}.{}.{}'.format(major, minor, patch)])
|
||||||
|
[pathlib.Path(l['name']).unlink() for l in links]
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
22
.github/workflows/build.yml
vendored
@@ -10,7 +10,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
- name: install dependencies
|
- name: install dependencies
|
||||||
run: HOMEBREW_NO_AUTO_UPDATE=1 brew install boost hidapi zmq libpgm libsodium miniupnpc ldns expat libunwind-headers protobuf qt5 pkg-config
|
run: HOMEBREW_NO_AUTO_UPDATE=1 brew install boost hidapi openssl zmq libpgm libsodium miniupnpc ldns expat libunwind-headers protobuf qt5 pkg-config
|
||||||
- name: build
|
- name: build
|
||||||
run: DEV_MODE=ON make release -j3
|
run: DEV_MODE=ON make release -j3
|
||||||
- name: test qml
|
- name: test qml
|
||||||
@@ -52,9 +52,12 @@ jobs:
|
|||||||
- uses: eine/setup-msys2@v2
|
- uses: eine/setup-msys2@v2
|
||||||
with:
|
with:
|
||||||
update: true
|
update: true
|
||||||
install: mingw-w64-x86_64-toolchain make mingw-w64-x86_64-cmake mingw-w64-x86_64-boost mingw-w64-x86_64-openssl mingw-w64-x86_64-zeromq mingw-w64-x86_64-libsodium mingw-w64-x86_64-hidapi mingw-w64-x86_64-protobuf-c mingw-w64-x86_64-libusb git mingw-w64-x86_64-qt5 mingw-w64-x86_64-libgcrypt
|
install: mingw-w64-x86_64-toolchain make mingw-w64-x86_64-cmake mingw-w64-x86_64-boost mingw-w64-x86_64-openssl mingw-w64-x86_64-zeromq mingw-w64-x86_64-libsodium mingw-w64-x86_64-hidapi mingw-w64-x86_64-protobuf-c mingw-w64-x86_64-libusb mingw-w64-x86_64-unbound git mingw-w64-x86_64-qt5 mingw-w64-x86_64-libgcrypt
|
||||||
- name: build
|
- name: build
|
||||||
run: DEV_MODE=ON make release-win64 -j2
|
run: DEV_MODE=ON make release-win64 -j2
|
||||||
|
- name: deploy
|
||||||
|
run: make deploy
|
||||||
|
working-directory: build/release
|
||||||
- name: test qml
|
- name: test qml
|
||||||
run: build/release/bin/monero-wallet-gui --test-qml
|
run: build/release/bin/monero-wallet-gui --test-qml
|
||||||
|
|
||||||
@@ -65,14 +68,11 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
- name: install dependencies
|
- name: install dependencies
|
||||||
run: HOMEBREW_NO_AUTO_UPDATE=1 brew install boost hidapi zmq libpgm miniupnpc ldns expat libunwind-headers protobuf pkg-config python3 p7zip
|
run: HOMEBREW_NO_AUTO_UPDATE=1 brew install boost hidapi openssl zmq libpgm miniupnpc ldns expat libunwind-headers protobuf pkg-config python3 p7zip aria2
|
||||||
- name: install dependencies
|
- name: install dependencies
|
||||||
run: pip3 install requests semantic_version lxml py7zr
|
run: pip3 install defusedxml
|
||||||
- name: download qt
|
- name: download qt
|
||||||
run: |
|
run: python3 monero-gui/.github/qt_helper.py mac_x64 desktop 5.15.2 clang_64 c384008156fe63cc183bade0316828c598ff3e5074397c0c9ccc588d6cdc5aca
|
||||||
curl -O https://raw.githubusercontent.com/engnr/qt-downloader/master/qt-downloader
|
|
||||||
chmod +x qt-downloader
|
|
||||||
./qt-downloader macos desktop 5.15.2 clang_64
|
|
||||||
working-directory: ../
|
working-directory: ../
|
||||||
- name: build
|
- name: build
|
||||||
run: CMAKE_PREFIX_PATH=/Users/runner/work/monero-gui/5.15.2/clang_64 make release -j3
|
run: CMAKE_PREFIX_PATH=/Users/runner/work/monero-gui/5.15.2/clang_64 make release -j3
|
||||||
@@ -95,7 +95,8 @@ jobs:
|
|||||||
- uses: actions/checkout@v1
|
- uses: actions/checkout@v1
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
- uses: satackey/action-docker-layer-caching@v0.0.10
|
- uses: satackey/action-docker-layer-caching@v0.0.11
|
||||||
|
if: "!startsWith(github.ref, 'refs/tags/v')"
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
with:
|
with:
|
||||||
key: docker-linux-static-{hash}
|
key: docker-linux-static-{hash}
|
||||||
@@ -124,7 +125,8 @@ jobs:
|
|||||||
- uses: actions/checkout@v1
|
- uses: actions/checkout@v1
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
- uses: satackey/action-docker-layer-caching@v0.0.10
|
- uses: satackey/action-docker-layer-caching@v0.0.11
|
||||||
|
if: "!startsWith(github.ref, 'refs/tags/v')"
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
with:
|
with:
|
||||||
key: docker-windows-static-{hash}
|
key: docker-windows-static-{hash}
|
||||||
|
|||||||
@@ -4,28 +4,23 @@ project(monero-gui)
|
|||||||
message(STATUS "Initiating compile using CMake ${CMAKE_VERSION}")
|
message(STATUS "Initiating compile using CMake ${CMAKE_VERSION}")
|
||||||
|
|
||||||
set(VERSION_MAJOR "17")
|
set(VERSION_MAJOR "17")
|
||||||
set(VERSION_MINOR "2")
|
set(VERSION_MINOR "3")
|
||||||
set(VERSION_REVISION "3")
|
set(VERSION_REVISION "2")
|
||||||
set(VERSION "0.${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_REVISION}")
|
set(VERSION "0.${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_REVISION}")
|
||||||
|
|
||||||
option(STATIC "Link libraries statically, requires static Qt")
|
option(STATIC "Link libraries statically, requires static Qt")
|
||||||
|
|
||||||
option(USE_DEVICE_TREZOR "Trezor support compilation" ON)
|
option(USE_DEVICE_TREZOR "Trezor support compilation" ON)
|
||||||
option(WITH_SCANNER "Enable webcam QR scanner" OFF)
|
option(WITH_SCANNER "Enable webcam QR scanner" OFF)
|
||||||
|
option(WITH_DESKTOP_ENTRY "Ask to install desktop entry on first startup" ON)
|
||||||
option(DEV_MODE "Checkout latest monero master on build" OFF)
|
option(DEV_MODE "Checkout latest monero master on build" OFF)
|
||||||
|
|
||||||
list(INSERT CMAKE_MODULE_PATH 0 "${CMAKE_SOURCE_DIR}/cmake")
|
list(INSERT CMAKE_MODULE_PATH 0 "${CMAKE_SOURCE_DIR}/cmake")
|
||||||
include(CheckCCompilerFlag)
|
include(CheckCCompilerFlag)
|
||||||
include(CheckCXXCompilerFlag)
|
include(CheckCXXCompilerFlag)
|
||||||
include(CheckLinkerFlag)
|
include(CheckLinkerFlag)
|
||||||
include(FindCcache)
|
|
||||||
|
|
||||||
if(DEBUG)
|
|
||||||
set(CMAKE_VERBOSE_MAKEFILE ON)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(BUILD_GUI_DEPS ON)
|
set(BUILD_GUI_DEPS ON)
|
||||||
set(ARCH "x86-64" CACHE STRING "Target architecture")
|
|
||||||
set(BUILD_64 ON CACHE BOOL "Build 64-bit binaries")
|
set(BUILD_64 ON CACHE BOOL "Build 64-bit binaries")
|
||||||
|
|
||||||
if(NOT MANUAL_SUBMODULES)
|
if(NOT MANUAL_SUBMODULES)
|
||||||
@@ -71,85 +66,31 @@ endif()
|
|||||||
|
|
||||||
if(STATIC)
|
if(STATIC)
|
||||||
message(STATUS "Initiating static build")
|
message(STATUS "Initiating static build")
|
||||||
set(Boost_USE_STATIC_LIBS ON)
|
|
||||||
set(Boost_USE_STATIC_RUNTIME ON)
|
|
||||||
set(CMAKE_FIND_LIBRARY_SUFFIXES ".a" ${CMAKE_FIND_LIBRARY_SUFFIXES})
|
set(CMAKE_FIND_LIBRARY_SUFFIXES ".a" ${CMAKE_FIND_LIBRARY_SUFFIXES})
|
||||||
add_definitions(-DMONERO_GUI_STATIC)
|
add_definitions(-DMONERO_GUI_STATIC)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
include(CMakePackageConfigHelpers)
|
include(CMakePackageConfigHelpers)
|
||||||
|
|
||||||
# force version update
|
|
||||||
function (monero_gui_add_library_with_deps)
|
|
||||||
cmake_parse_arguments(MONERO_ADD_LIBRARY "" "NAME" "DEPENDS;SOURCES" ${ARGN})
|
|
||||||
source_group("${MONERO_ADD_LIBRARY_NAME}" FILES ${MONERO_ADD_LIBRARY_SOURCES})
|
|
||||||
|
|
||||||
# Define a ("virtual") object library and an actual library that links those
|
|
||||||
# objects together. The virtual libraries can be arbitrarily combined to link
|
|
||||||
# any subset of objects into one library archive. This is used for releasing
|
|
||||||
# libwallet, which combines multiple components.
|
|
||||||
set(objlib obj_${MONERO_ADD_LIBRARY_NAME})
|
|
||||||
add_library(${objlib} OBJECT ${MONERO_ADD_LIBRARY_SOURCES})
|
|
||||||
add_library("${MONERO_ADD_LIBRARY_NAME}" $<TARGET_OBJECTS:${objlib}>)
|
|
||||||
if (MONERO_ADD_LIBRARY_DEPENDS)
|
|
||||||
add_dependencies(${objlib} ${MONERO_ADD_LIBRARY_DEPENDS})
|
|
||||||
endif()
|
|
||||||
set_property(TARGET "${MONERO_ADD_LIBRARY_NAME}" PROPERTY FOLDER "libs")
|
|
||||||
target_compile_definitions(${objlib}
|
|
||||||
PRIVATE $<TARGET_PROPERTY:${MONERO_ADD_LIBRARY_NAME},INTERFACE_COMPILE_DEFINITIONS>)
|
|
||||||
endfunction ()
|
|
||||||
|
|
||||||
function (monero_gui_add_library name)
|
|
||||||
monero_gui_add_library_with_deps(NAME "${name}" SOURCES ${ARGN})
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
include_directories(${EASYLOGGING_INCLUDE})
|
include_directories(${EASYLOGGING_INCLUDE})
|
||||||
link_directories(${EASYLOGGING_LIBRARY_DIRS})
|
link_directories(${EASYLOGGING_LIBRARY_DIRS})
|
||||||
|
|
||||||
|
|
||||||
include(VersionGui)
|
include(VersionGui)
|
||||||
monero_gui_add_library(gui_version SOURCES version.js DEPENDS genversiongui)
|
|
||||||
|
|
||||||
message(STATUS "${CMAKE_MODULE_PATH}")
|
message(STATUS "${CMAKE_MODULE_PATH}")
|
||||||
|
|
||||||
# OpenSSL
|
|
||||||
if(APPLE AND NOT OPENSSL_ROOT_DIR)
|
|
||||||
execute_process(COMMAND brew --prefix openssl OUTPUT_VARIABLE OPENSSL_ROOT_DIR OUTPUT_STRIP_TRAILING_WHITESPACE)
|
|
||||||
endif()
|
|
||||||
find_package(OpenSSL REQUIRED)
|
|
||||||
message(STATUS "OpenSSL: Version ${OPENSSL_VERSION}")
|
|
||||||
message(STATUS "OpenSSL: include dir at ${OPENSSL_INCLUDE_DIR}")
|
|
||||||
message(STATUS "OpenSSL: libraries at ${OPENSSL_LIBRARIES} ${OPENSSL_SSL_LIBRARIES}")
|
|
||||||
|
|
||||||
if(WITH_SCANNER)
|
if(WITH_SCANNER)
|
||||||
add_definitions(-DWITH_SCANNER)
|
add_definitions(-DWITH_SCANNER)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(WITH_DESKTOP_ENTRY)
|
||||||
|
add_definitions(-DWITH_DESKTOP_ENTRY)
|
||||||
|
endif()
|
||||||
|
|
||||||
# Sodium
|
# Sodium
|
||||||
find_library(SODIUM_LIBRARY sodium)
|
find_library(SODIUM_LIBRARY sodium)
|
||||||
message(STATUS "libsodium: libraries at ${SODIUM_LIBRARY}")
|
message(STATUS "libsodium: libraries at ${SODIUM_LIBRARY}")
|
||||||
|
|
||||||
# Boost
|
|
||||||
if(DEBUG)
|
|
||||||
set(Boost_DEBUG ON)
|
|
||||||
endif()
|
|
||||||
if(APPLE AND NOT BOOST_ROOT)
|
|
||||||
execute_process(COMMAND brew --prefix boost OUTPUT_VARIABLE BOOST_ROOT OUTPUT_STRIP_TRAILING_WHITESPACE)
|
|
||||||
endif()
|
|
||||||
if(MINGW)
|
|
||||||
set(Boost_THREADAPI win32)
|
|
||||||
endif()
|
|
||||||
find_package(Boost 1.58 REQUIRED COMPONENTS
|
|
||||||
system
|
|
||||||
filesystem
|
|
||||||
thread
|
|
||||||
date_time
|
|
||||||
chrono
|
|
||||||
regex
|
|
||||||
serialization
|
|
||||||
program_options
|
|
||||||
locale)
|
|
||||||
|
|
||||||
if(UNIX AND NOT APPLE AND NOT ANDROID)
|
if(UNIX AND NOT APPLE AND NOT ANDROID)
|
||||||
set(CMAKE_SKIP_RPATH ON)
|
set(CMAKE_SKIP_RPATH ON)
|
||||||
set(CMAKE_FIND_LIBRARY_SUFFIXES_PREV ${CMAKE_FIND_LIBRARY_SUFFIXES})
|
set(CMAKE_FIND_LIBRARY_SUFFIXES_PREV ${CMAKE_FIND_LIBRARY_SUFFIXES})
|
||||||
@@ -167,19 +108,6 @@ if(UNIX AND NOT APPLE AND NOT ANDROID)
|
|||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(MINGW)
|
|
||||||
string(REGEX MATCH "^[^/]:/[^/]*" msys2_install_path "${CMAKE_C_COMPILER}")
|
|
||||||
message(STATUS "MSYS location: ${msys2_install_path}")
|
|
||||||
set(CMAKE_INCLUDE_PATH "${msys2_install_path}/mingw${ARCH_WIDTH}/include")
|
|
||||||
# This is necessary because otherwise CMake will make Boost libraries -lfoo
|
|
||||||
# rather than a full path. Unfortunately, this makes the shared libraries get
|
|
||||||
# linked due to a bug in CMake which misses putting -static flags around the
|
|
||||||
# -lfoo arguments.
|
|
||||||
set(DEFLIB ${msys2_install_path}/mingw${ARCH_WIDTH}/lib)
|
|
||||||
list(REMOVE_ITEM CMAKE_C_IMPLICIT_LINK_DIRECTORIES ${DEFLIB})
|
|
||||||
list(REMOVE_ITEM CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES ${DEFLIB})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(QT5_LIBRARIES
|
set(QT5_LIBRARIES
|
||||||
Qt5Core
|
Qt5Core
|
||||||
Qt5Quick
|
Qt5Quick
|
||||||
@@ -392,10 +320,6 @@ if(ANDROID)
|
|||||||
endforeach()
|
endforeach()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
message(STATUS "Using Boost include dir at ${Boost_INCLUDE_DIRS}")
|
|
||||||
message(STATUS "Using Boost libraries at ${Boost_LIBRARIES}")
|
|
||||||
|
|
||||||
include_directories(SYSTEM ${Boost_INCLUDE_DIRS})
|
|
||||||
if(MINGW)
|
if(MINGW)
|
||||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wa,-mbig-obj")
|
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wa,-mbig-obj")
|
||||||
set(EXTRA_LIBRARIES mswsock;ws2_32;iphlpapi;crypt32;bcrypt)
|
set(EXTRA_LIBRARIES mswsock;ws2_32;iphlpapi;crypt32;bcrypt)
|
||||||
@@ -423,14 +347,11 @@ endif()
|
|||||||
list(APPEND EXTRA_LIBRARIES ${CMAKE_DL_LIBS})
|
list(APPEND EXTRA_LIBRARIES ${CMAKE_DL_LIBS})
|
||||||
|
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
include_directories(SYSTEM /usr/include/malloc)
|
cmake_policy(SET CMP0042 NEW)
|
||||||
if(POLICY CMP0042)
|
|
||||||
cmake_policy(SET CMP0042 NEW)
|
|
||||||
endif()
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (APPLE AND NOT IOS)
|
if (APPLE AND NOT IOS)
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=x86-64 -fvisibility=default -std=c++11")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=default -std=c++11")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
@@ -438,8 +359,6 @@ if(APPLE)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
# warnings
|
# warnings
|
||||||
add_c_flag_if_supported(-Werror C_SECURITY_FLAGS)
|
|
||||||
add_cxx_flag_if_supported(-Werror CXX_SECURITY_FLAGS)
|
|
||||||
add_c_flag_if_supported(-Wformat C_SECURITY_FLAGS)
|
add_c_flag_if_supported(-Wformat C_SECURITY_FLAGS)
|
||||||
add_cxx_flag_if_supported(-Wformat CXX_SECURITY_FLAGS)
|
add_cxx_flag_if_supported(-Wformat CXX_SECURITY_FLAGS)
|
||||||
add_c_flag_if_supported(-Wformat-security C_SECURITY_FLAGS)
|
add_c_flag_if_supported(-Wformat-security C_SECURITY_FLAGS)
|
||||||
|
|||||||
11
DEPLOY.md
@@ -8,11 +8,16 @@ Use macOS 10.12 - 10.13 for better backwards compability.
|
|||||||
|
|
||||||
3. `git clone --recursive -b v0.X.Y.Z --depth 1 https://github.com/monero-project/monero-gui`
|
3. `git clone --recursive -b v0.X.Y.Z --depth 1 https://github.com/monero-project/monero-gui`
|
||||||
|
|
||||||
4. `CMAKE_PREFIX_PATH=~/Qt5.12.8/5.12.8/clang_64 make release`
|
4. Compile `monero-wallet-gui.app`
|
||||||
|
|
||||||
5. `cd build/release && make deploy`
|
```
|
||||||
|
mkdir build && cd build
|
||||||
|
cmake -D CMAKE_BUILD_TYPE=Release -D ARCH=default -D CMAKE_PREFIX_PATH=~/Qt5.12.8/5.12.8/clang_64 ..
|
||||||
|
make
|
||||||
|
make deploy
|
||||||
|
```
|
||||||
|
|
||||||
6. Replace the `monerod` binary inside `monero-wallet-gui.app/Contents/MacOS/` with one built using deterministic builds / gitian.
|
5. Replace the `monerod` binary inside `monero-wallet-gui.app/Contents/MacOS/` with one built using deterministic builds / gitian.
|
||||||
|
|
||||||
## Codesigning and notarizing
|
## Codesigning and notarizing
|
||||||
|
|
||||||
|
|||||||
@@ -40,9 +40,10 @@ RUN cp -r ${WORKDIR}/platforms ${WORKDIR}/platform-tools ${ANDROID_SDK_ROOT}
|
|||||||
ENV HOST_PATH=${PATH}
|
ENV HOST_PATH=${PATH}
|
||||||
ENV PATH=${TOOLCHAIN_DIR}/aarch64-linux-android/bin:${TOOLCHAIN_DIR}/bin:${PATH}
|
ENV PATH=${TOOLCHAIN_DIR}/aarch64-linux-android/bin:${TOOLCHAIN_DIR}/bin:${PATH}
|
||||||
|
|
||||||
ARG ZLIB_VERSION=1.2.11
|
ARG ZLIB_VERSION=1.2.12
|
||||||
ARG ZLIB_HASH=c3e5e9fdd5004dcb542feda5ee4f0ff0744628baf8ed2dd5d66f8ca1197cb1a1
|
ARG ZLIB_HASH=91844808532e5ce316b3c010929493c0244f3d37593afd6de04f71821d5136d9
|
||||||
RUN wget -q https://zlib.net/zlib-${ZLIB_VERSION}.tar.gz \
|
RUN wget -q https://zlib.net/zlib-${ZLIB_VERSION}.tar.gz \
|
||||||
|
&& echo "${ZLIB_HASH} zlib-${ZLIB_VERSION}.tar.gz" | sha256sum -c \
|
||||||
&& tar -xzf zlib-${ZLIB_VERSION}.tar.gz \
|
&& tar -xzf zlib-${ZLIB_VERSION}.tar.gz \
|
||||||
&& rm zlib-${ZLIB_VERSION}.tar.gz \
|
&& rm zlib-${ZLIB_VERSION}.tar.gz \
|
||||||
&& cd zlib-${ZLIB_VERSION} \
|
&& cd zlib-${ZLIB_VERSION} \
|
||||||
@@ -117,6 +118,7 @@ RUN wget -q https://downloads.sourceforge.net/project/boost/boost/${BOOST_VERSIO
|
|||||||
ARG OPENSSL_VERSION=1.1.1g
|
ARG OPENSSL_VERSION=1.1.1g
|
||||||
ARG OPENSSL_HASH=ddb04774f1e32f0c49751e21b67216ac87852ceb056b75209af2443400636d46
|
ARG OPENSSL_HASH=ddb04774f1e32f0c49751e21b67216ac87852ceb056b75209af2443400636d46
|
||||||
RUN wget -q https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz \
|
RUN wget -q https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz \
|
||||||
|
&& echo "${OPENSSL_HASH} openssl-${OPENSSL_VERSION}.tar.gz" | sha256sum -c \
|
||||||
&& tar -xzf openssl-${OPENSSL_VERSION}.tar.gz \
|
&& tar -xzf openssl-${OPENSSL_VERSION}.tar.gz \
|
||||||
&& rm openssl-${OPENSSL_VERSION}.tar.gz \
|
&& rm openssl-${OPENSSL_VERSION}.tar.gz \
|
||||||
&& cd openssl-${OPENSSL_VERSION} \
|
&& cd openssl-${OPENSSL_VERSION} \
|
||||||
@@ -129,6 +131,30 @@ RUN wget -q https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz \
|
|||||||
&& make -j${THREADS} install \
|
&& make -j${THREADS} install \
|
||||||
&& rm -rf $(pwd)
|
&& rm -rf $(pwd)
|
||||||
|
|
||||||
|
ARG EXPAT_VERSION=2.4.1
|
||||||
|
ARG EXPAT_HASH=2f9b6a580b94577b150a7d5617ad4643a4301a6616ff459307df3e225bcfbf40
|
||||||
|
RUN wget https://github.com/libexpat/libexpat/releases/download/R_2_4_1/expat-${EXPAT_VERSION}.tar.bz2 && \
|
||||||
|
echo "${EXPAT_HASH} expat-${EXPAT_VERSION}.tar.bz2" | sha256sum -c && \
|
||||||
|
tar -xf expat-${EXPAT_VERSION}.tar.bz2 && \
|
||||||
|
rm expat-${EXPAT_VERSION}.tar.bz2 && \
|
||||||
|
cd expat-${EXPAT_VERSION} && \
|
||||||
|
CC=${ANDROID_CLANG} CXX=${ANDROID_CLANGPP} ./configure --enable-static --disable-shared --prefix=${PREFIX} --host=aarch64-linux-android && \
|
||||||
|
make -j$THREADS && \
|
||||||
|
make -j$THREADS install && \
|
||||||
|
rm -rf $(pwd)
|
||||||
|
|
||||||
|
ARG UNBOUND_VERSION=1.13.2
|
||||||
|
ARG UNBOUND_HASH=0a13b547f3b92a026b5ebd0423f54c991e5718037fd9f72445817f6a040e1a83
|
||||||
|
RUN wget https://www.nlnetlabs.nl/downloads/unbound/unbound-${UNBOUND_VERSION}.tar.gz && \
|
||||||
|
echo "${UNBOUND_HASH} unbound-${UNBOUND_VERSION}.tar.gz" | sha256sum -c && \
|
||||||
|
tar -xzf unbound-${UNBOUND_VERSION}.tar.gz && \
|
||||||
|
rm unbound-${UNBOUND_VERSION}.tar.gz && \
|
||||||
|
cd unbound-${UNBOUND_VERSION} && \
|
||||||
|
CC=${ANDROID_CLANG} CXX=${ANDROID_CLANGPP} ./configure --disable-shared --enable-static --without-pyunbound --with-libexpat=${PREFIX} --with-ssl=${PREFIX} --with-libevent=no --without-pythonmodule --disable-flto --with-pthreads --with-libunbound-only --host=aarch64-linux-android --with-pic --prefix=${PREFIX} && \
|
||||||
|
make -j$THREADS && \
|
||||||
|
make -j$THREADS install && \
|
||||||
|
rm -rf $(pwd)
|
||||||
|
|
||||||
ARG ZMQ_VERSION=v4.3.3
|
ARG ZMQ_VERSION=v4.3.3
|
||||||
ARG ZMQ_HASH=04f5bbedee58c538934374dc45182d8fc5926fa3
|
ARG ZMQ_HASH=04f5bbedee58c538934374dc45182d8fc5926fa3
|
||||||
RUN git clone https://github.com/zeromq/libzmq.git -b ${ZMQ_VERSION} --depth 1 \
|
RUN git clone https://github.com/zeromq/libzmq.git -b ${ZMQ_VERSION} --depth 1 \
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
FROM ubuntu:16.04
|
FROM ubuntu:16.04
|
||||||
|
|
||||||
ARG THREADS=1
|
ARG THREADS=1
|
||||||
ARG QT_VERSION=5.15.2
|
ARG QT_VERSION=v5.15.3-lts-lgpl
|
||||||
|
|
||||||
ENV CFLAGS="-fPIC"
|
ENV CFLAGS="-fPIC"
|
||||||
ENV CPPFLAGS="-fPIC"
|
ENV CPPFLAGS="-fPIC"
|
||||||
@@ -169,7 +169,27 @@ RUN wget https://www.openssl.org/source/openssl-1.1.1g.tar.gz && \
|
|||||||
tar -xzf openssl-1.1.1g.tar.gz && \
|
tar -xzf openssl-1.1.1g.tar.gz && \
|
||||||
rm openssl-1.1.1g.tar.gz && \
|
rm openssl-1.1.1g.tar.gz && \
|
||||||
cd openssl-1.1.1g && \
|
cd openssl-1.1.1g && \
|
||||||
./config no-asm no-shared no-zlib-dynamic --openssldir=/usr && \
|
./config no-asm no-shared no-zlib-dynamic --prefix=/usr --openssldir=/usr && \
|
||||||
|
make -j$THREADS && \
|
||||||
|
make -j$THREADS install && \
|
||||||
|
rm -rf $(pwd)
|
||||||
|
|
||||||
|
RUN wget https://github.com/libexpat/libexpat/releases/download/R_2_4_1/expat-2.4.1.tar.bz2 && \
|
||||||
|
echo "2f9b6a580b94577b150a7d5617ad4643a4301a6616ff459307df3e225bcfbf40 expat-2.4.1.tar.bz2" | sha256sum -c && \
|
||||||
|
tar -xf expat-2.4.1.tar.bz2 && \
|
||||||
|
rm expat-2.4.1.tar.bz2 && \
|
||||||
|
cd expat-2.4.1 && \
|
||||||
|
./configure --enable-static --disable-shared --prefix=/usr && \
|
||||||
|
make -j$THREADS && \
|
||||||
|
make -j$THREADS install && \
|
||||||
|
rm -rf $(pwd)
|
||||||
|
|
||||||
|
RUN wget https://www.nlnetlabs.nl/downloads/unbound/unbound-1.13.2.tar.gz && \
|
||||||
|
echo "0a13b547f3b92a026b5ebd0423f54c991e5718037fd9f72445817f6a040e1a83 unbound-1.13.2.tar.gz" | sha256sum -c && \
|
||||||
|
tar -xzf unbound-1.13.2.tar.gz && \
|
||||||
|
rm unbound-1.13.2.tar.gz && \
|
||||||
|
cd unbound-1.13.2 && \
|
||||||
|
./configure --disable-shared --enable-static --without-pyunbound --with-libexpat=/usr --with-ssl=/usr --with-libevent=no --without-pythonmodule --disable-flto --with-pthreads --with-libunbound-only --with-pic && \
|
||||||
make -j$THREADS && \
|
make -j$THREADS && \
|
||||||
make -j$THREADS install && \
|
make -j$THREADS install && \
|
||||||
rm -rf $(pwd)
|
rm -rf $(pwd)
|
||||||
@@ -222,9 +242,9 @@ RUN git clone -b v1.0.23 --depth 1 https://github.com/libusb/libusb && \
|
|||||||
make -j$THREADS install && \
|
make -j$THREADS install && \
|
||||||
rm -rf $(pwd)
|
rm -rf $(pwd)
|
||||||
|
|
||||||
RUN git clone -b hidapi-0.9.0 --depth 1 https://github.com/libusb/hidapi && \
|
RUN git clone -b hidapi-0.11.0 --depth 1 https://github.com/libusb/hidapi && \
|
||||||
cd hidapi && \
|
cd hidapi && \
|
||||||
git reset --hard 7da5cc91fc0d2dbe4df4f08cd31f6ca1a262418f && \
|
git reset --hard 0ec60c03cbe87cdbfb9fb199c7536fdcbc0a94b8 && \
|
||||||
./bootstrap && \
|
./bootstrap && \
|
||||||
./configure --disable-shared --enable-static && \
|
./configure --disable-shared --enable-static && \
|
||||||
make -j$THREADS && \
|
make -j$THREADS && \
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
FROM ubuntu:20.04
|
FROM ubuntu:20.04
|
||||||
|
|
||||||
ARG THREADS=1
|
ARG THREADS=1
|
||||||
ARG QT_VERSION=5.15.2
|
ARG QT_VERSION=v5.15.3-lts-lgpl
|
||||||
ENV SOURCE_DATE_EPOCH=1397818193
|
ENV SOURCE_DATE_EPOCH=1397818193
|
||||||
|
|
||||||
RUN apt update && \
|
RUN apt update && \
|
||||||
@@ -12,9 +12,9 @@ RUN apt update && \
|
|||||||
RUN update-alternatives --set x86_64-w64-mingw32-g++ $(which x86_64-w64-mingw32-g++-posix) && \
|
RUN update-alternatives --set x86_64-w64-mingw32-g++ $(which x86_64-w64-mingw32-g++-posix) && \
|
||||||
update-alternatives --set x86_64-w64-mingw32-gcc $(which x86_64-w64-mingw32-gcc-posix)
|
update-alternatives --set x86_64-w64-mingw32-gcc $(which x86_64-w64-mingw32-gcc-posix)
|
||||||
|
|
||||||
RUN git clone -b v0.17.0.0 --depth 1 https://github.com/monero-project/monero && \
|
RUN git clone -b v0.17.3.0 --depth 1 https://github.com/monero-project/monero && \
|
||||||
cd monero && \
|
cd monero && \
|
||||||
git reset --hard d27d4526fe89b7cdeb4b296280c4a6cf7efe21f8 && \
|
git reset --hard ab18fea3500841fc312630d49ed6840b3aedb34d && \
|
||||||
cp -a contrib/depends / && \
|
cp -a contrib/depends / && \
|
||||||
cd .. && \
|
cd .. && \
|
||||||
rm -rf monero
|
rm -rf monero
|
||||||
|
|||||||
@@ -360,7 +360,8 @@ Rectangle {
|
|||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
text: qsTr("Account") + translationManager.emptyString
|
text: qsTr("Account") + translationManager.emptyString
|
||||||
symbol: qsTr("T") + translationManager.emptyString
|
symbol: (isMac ? "⌃" : qsTr("Ctrl+")) + "T" + translationManager.emptyString
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
parent.previousButton.checked = false
|
parent.previousButton.checked = false
|
||||||
parent.previousButton = accountButton
|
parent.previousButton = accountButton
|
||||||
@@ -381,7 +382,7 @@ Rectangle {
|
|||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
text: qsTr("Send") + translationManager.emptyString
|
text: qsTr("Send") + translationManager.emptyString
|
||||||
symbol: qsTr("S") + translationManager.emptyString
|
symbol: (isMac ? "⌃" : qsTr("Ctrl+")) + "S" + translationManager.emptyString
|
||||||
onClicked: {
|
onClicked: {
|
||||||
parent.previousButton.checked = false
|
parent.previousButton.checked = false
|
||||||
parent.previousButton = transferButton
|
parent.previousButton = transferButton
|
||||||
@@ -403,7 +404,7 @@ Rectangle {
|
|||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
text: qsTr("Address book") + translationManager.emptyString
|
text: qsTr("Address book") + translationManager.emptyString
|
||||||
symbol: qsTr("B") + translationManager.emptyString
|
symbol: (isMac ? "⌃" : qsTr("Ctrl+")) + "B" + translationManager.emptyString
|
||||||
under: transferButton
|
under: transferButton
|
||||||
onClicked: {
|
onClicked: {
|
||||||
parent.previousButton.checked = false
|
parent.previousButton.checked = false
|
||||||
@@ -425,7 +426,7 @@ Rectangle {
|
|||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
text: qsTr("Receive") + translationManager.emptyString
|
text: qsTr("Receive") + translationManager.emptyString
|
||||||
symbol: qsTr("R") + translationManager.emptyString
|
symbol: (isMac ? "⌃" : qsTr("Ctrl+")) + "R" + translationManager.emptyString
|
||||||
onClicked: {
|
onClicked: {
|
||||||
parent.previousButton.checked = false
|
parent.previousButton.checked = false
|
||||||
parent.previousButton = receiveButton
|
parent.previousButton = receiveButton
|
||||||
@@ -447,7 +448,7 @@ Rectangle {
|
|||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
text: qsTr("Transactions") + translationManager.emptyString
|
text: qsTr("Transactions") + translationManager.emptyString
|
||||||
symbol: qsTr("H") + translationManager.emptyString
|
symbol: (isMac ? "⌃" : qsTr("Ctrl+")) + "H" + translationManager.emptyString
|
||||||
onClicked: {
|
onClicked: {
|
||||||
parent.previousButton.checked = false
|
parent.previousButton.checked = false
|
||||||
parent.previousButton = historyButton
|
parent.previousButton = historyButton
|
||||||
@@ -469,7 +470,7 @@ Rectangle {
|
|||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
text: qsTr("Advanced") + translationManager.emptyString
|
text: qsTr("Advanced") + translationManager.emptyString
|
||||||
symbol: qsTr("D") + translationManager.emptyString
|
symbol: (isMac ? "⌃" : qsTr("Ctrl+")) + "D" + translationManager.emptyString
|
||||||
onClicked: {
|
onClicked: {
|
||||||
parent.previousButton.checked = false
|
parent.previousButton.checked = false
|
||||||
parent.previousButton = advancedButton
|
parent.previousButton = advancedButton
|
||||||
@@ -490,7 +491,7 @@ Rectangle {
|
|||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
text: qsTr("Settings") + translationManager.emptyString
|
text: qsTr("Settings") + translationManager.emptyString
|
||||||
symbol: qsTr("E") + translationManager.emptyString
|
symbol: (isMac ? "⌃" : qsTr("Ctrl+")) + "E" + translationManager.emptyString
|
||||||
onClicked: {
|
onClicked: {
|
||||||
parent.previousButton.checked = false
|
parent.previousButton.checked = false
|
||||||
parent.previousButton = settingsButton
|
parent.previousButton = settingsButton
|
||||||
|
|||||||
15
Makefile
@@ -29,7 +29,7 @@ else
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
default:
|
default:
|
||||||
mkdir -p build && cd build && cmake -D ARCH="x86-64" -D DEV_MODE=$(or ${DEV_MODE},OFF) -DMANUAL_SUBMODULES=${MANUAL_SUBMODULES} -D BUILD_64=ON -D CMAKE_BUILD_TYPE=Release .. && $(MAKE)
|
mkdir -p build && cd build && cmake -D DEV_MODE=$(or ${DEV_MODE},OFF) -DMANUAL_SUBMODULES=${MANUAL_SUBMODULES} -D BUILD_64=ON -D CMAKE_BUILD_TYPE=Release .. && $(MAKE)
|
||||||
debug:
|
debug:
|
||||||
mkdir -p build && cd build && cmake -D DEV_MODE=$(or ${DEV_MODE},ON) -DMANUAL_SUBMODULES=${MANUAL_SUBMODULES} -D CMAKE_BUILD_TYPE=Debug .. && $(MAKE) VERBOSE=1
|
mkdir -p build && cd build && cmake -D DEV_MODE=$(or ${DEV_MODE},ON) -DMANUAL_SUBMODULES=${MANUAL_SUBMODULES} -D CMAKE_BUILD_TYPE=Debug .. && $(MAKE) VERBOSE=1
|
||||||
|
|
||||||
@@ -38,19 +38,20 @@ depends:
|
|||||||
cd build/$(target)/release && cmake -D STATIC=ON -D DEV_MODE=$(or ${DEV_MODE},OFF) -DMANUAL_SUBMODULES=${MANUAL_SUBMODULES} -D BUILD_TAG=$(tag) -D CMAKE_BUILD_TYPE=Release -D CMAKE_TOOLCHAIN_FILE=$(root)/$(target)/share/toolchain.cmake ../../.. && $(MAKE)
|
cd build/$(target)/release && cmake -D STATIC=ON -D DEV_MODE=$(or ${DEV_MODE},OFF) -DMANUAL_SUBMODULES=${MANUAL_SUBMODULES} -D BUILD_TAG=$(tag) -D CMAKE_BUILD_TYPE=Release -D CMAKE_TOOLCHAIN_FILE=$(root)/$(target)/share/toolchain.cmake ../../.. && $(MAKE)
|
||||||
|
|
||||||
devmode:
|
devmode:
|
||||||
mkdir -p build && cd build && cmake -D ARCH="x86-64" -D DEV_MODE=$(or ${DEV_MODE},ON) -DMANUAL_SUBMODULES=${MANUAL_SUBMODULES} -D BUILD_64=ON -D CMAKE_BUILD_TYPE=Release .. && $(MAKE)
|
mkdir -p build && cd build && cmake -D DEV_MODE=$(or ${DEV_MODE},ON) -DMANUAL_SUBMODULES=${MANUAL_SUBMODULES} -D BUILD_64=ON -D CMAKE_BUILD_TYPE=Release .. && $(MAKE)
|
||||||
clean:
|
clean:
|
||||||
mkdir -p build && cd build && rm -rf *
|
mkdir -p build && cd build && rm -rf *
|
||||||
scanner:
|
scanner:
|
||||||
mkdir -p build && cd build && cmake -D ARCH="x86-64" -D DEV_MODE=$(or ${DEV_MODE},ON) -DMANUAL_SUBMODULES=${MANUAL_SUBMODULES} -D WITH_SCANNER=ON -D BUILD_64=ON -D CMAKE_BUILD_TYPE=Release .. && $(MAKE)
|
mkdir -p build && cd build && cmake -D DEV_MODE=$(or ${DEV_MODE},ON) -DMANUAL_SUBMODULES=${MANUAL_SUBMODULES} -D WITH_SCANNER=ON -D BUILD_64=ON -D CMAKE_BUILD_TYPE=Release .. && $(MAKE)
|
||||||
|
|
||||||
release:
|
release:
|
||||||
mkdir -p $(builddir)/release && cd $(builddir)/release && cmake -D DEV_MODE=$(or ${DEV_MODE},OFF) -DMANUAL_SUBMODULES=${MANUAL_SUBMODULES} -D ARCH="x86-64" -D CMAKE_BUILD_TYPE=Release $(topdir) && $(MAKE)
|
mkdir -p $(builddir)/release && cd $(builddir)/release && cmake -D DEV_MODE=$(or ${DEV_MODE},OFF) -DMANUAL_SUBMODULES=${MANUAL_SUBMODULES} -D CMAKE_BUILD_TYPE=Release $(topdir) && $(MAKE)
|
||||||
|
|
||||||
release-linux-armv8:
|
release-linux-armv8:
|
||||||
mkdir -p $(builddir)/release
|
mkdir -p $(builddir)/release && cd $(builddir)/release && cmake -D DEV_MODE=$(or ${DEV_MODE},OFF) -D ARCH="armv8-a" -D BUILD_64=ON -D CMAKE_BUILD_TYPE=Release -D BUILD_TAG="linux-armv8" $(topdir) && $(MAKE)
|
||||||
cd $(builddir)/release
|
|
||||||
cmake -D DEV_MODE=$(or ${DEV_MODE},OFF) -D ARCH="armv8-a" -D BUILD_64=ON -D CMAKE_BUILD_TYPE=Release -D BUILD_TAG="linux-armv8" $(topdir) && $(MAKE)
|
release-linux-ppc64le:
|
||||||
|
mkdir -p $(builddir)/release && cd $(builddir)/release && cmake -D DEV_MODE=$(or ${DEV_MODE},OFF) -DMANUAL_SUBMODULES=${MANUAL_SUBMODULES} -D ARCH="ppc64le" -D CMAKE_BUILD_TYPE=Release $(topdir) && $(MAKE)
|
||||||
|
|
||||||
release-static:
|
release-static:
|
||||||
mkdir -p $(builddir)/release && cd $(builddir)/release && cmake -D STATIC=ON -D DEV_MODE=$(or ${DEV_MODE},OFF) -DMANUAL_SUBMODULES=${MANUAL_SUBMODULES} -D ARCH="x86-64" -D BUILD_64=ON -D CMAKE_BUILD_TYPE=Release $(topdir) && $(MAKE)
|
mkdir -p $(builddir)/release && cd $(builddir)/release && cmake -D STATIC=ON -D DEV_MODE=$(or ${DEV_MODE},OFF) -DMANUAL_SUBMODULES=${MANUAL_SUBMODULES} -D ARCH="x86-64" -D BUILD_64=ON -D CMAKE_BUILD_TYPE=Release $(topdir) && $(MAKE)
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ Rectangle {
|
|||||||
signal paymentClicked(var recipients, string paymentId, int mixinCount, int priority, string description)
|
signal paymentClicked(var recipients, string paymentId, int mixinCount, int priority, string description)
|
||||||
signal sweepUnmixableClicked()
|
signal sweepUnmixableClicked()
|
||||||
signal generatePaymentIdInvoked()
|
signal generatePaymentIdInvoked()
|
||||||
signal getProofClicked(string txid, string address, string message);
|
signal getProofClicked(string txid, string address, string message, string amount);
|
||||||
signal checkProofClicked(string txid, string address, string message, string signature);
|
signal checkProofClicked(string txid, string address, string message, string signature);
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
|
|||||||
30
README.md
@@ -75,9 +75,10 @@ See [LICENSE](LICENSE).
|
|||||||
|
|
||||||
Do you speak a second language and would like to help translate the Monero GUI? Check out Weblate, our localization platform, at [translate.getmonero.org](https://translate.getmonero.org/). Choose the language and suggest a translation for a string or review an existing one. The Localization Workgroup made [a guide with step-by-step instructions](https://github.com/monero-ecosystem/monero-translations/blob/master/weblate.md) for Weblate.
|
Do you speak a second language and would like to help translate the Monero GUI? Check out Weblate, our localization platform, at [translate.getmonero.org](https://translate.getmonero.org/). Choose the language and suggest a translation for a string or review an existing one. The Localization Workgroup made [a guide with step-by-step instructions](https://github.com/monero-ecosystem/monero-translations/blob/master/weblate.md) for Weblate.
|
||||||
|
|
||||||
If you need help/support or any info you can contact the localization workgroup on the IRC channel #monero-translations (relayed on matrix/riot and MatterMost) or by email at translate[at]getmonero[dot]org. For more info about the Localization workgroup: [github.com/monero-ecosystem/monero-translations](https://github.com/monero-ecosystem/monero-translations)
|
If you need help/support or any info you can contact the localization workgroup on the IRC channel #monero-translations (relayed on [Matrix](https://matrix.to/#/!BKMbQLMDzHKzmtrBfg:matrix.org?via=monero.social&via=matrix.org&via=libera.chat)) or by email at translate[at]getmonero[dot]org. For more info about the Localization workgroup: [github.com/monero-ecosystem/monero-translations](https://github.com/monero-ecosystem/monero-translations)
|
||||||
|
|
||||||
Status of the translations:
|
Status of the translations:
|
||||||
|
|
||||||
<a href="https://translate.getmonero.org/engage/monero/?utm_source=widget">
|
<a href="https://translate.getmonero.org/engage/monero/?utm_source=widget">
|
||||||
<img src="https://translate.getmonero.org/widgets/monero/-/gui-wallet/horizontal-auto.svg" alt="Translation status" />
|
<img src="https://translate.getmonero.org/widgets/monero/-/gui-wallet/horizontal-auto.svg" alt="Translation status" />
|
||||||
</a>
|
</a>
|
||||||
@@ -88,6 +89,7 @@ Packages are available for
|
|||||||
* Arch Linux: [monero-gui](https://www.archlinux.org/packages/community/x86_64/monero-gui/)
|
* Arch Linux: [monero-gui](https://www.archlinux.org/packages/community/x86_64/monero-gui/)
|
||||||
* Debian: See the [whonix/monero-gui repository](https://gitlab.com/whonix/monero-gui#how-to-install-monero-using-apt-get)
|
* Debian: See the [whonix/monero-gui repository](https://gitlab.com/whonix/monero-gui#how-to-install-monero-using-apt-get)
|
||||||
* Void Linux: `xbps-install -S monero-gui`
|
* Void Linux: `xbps-install -S monero-gui`
|
||||||
|
* Flatpak: [Monero GUI](https://flathub.org/apps/details/org.getmonero.Monero)
|
||||||
* GuixSD: `guix package -i monero-gui`
|
* GuixSD: `guix package -i monero-gui`
|
||||||
* macOS (homebrew): `brew install --cask monero-wallet`
|
* macOS (homebrew): `brew install --cask monero-wallet`
|
||||||
|
|
||||||
@@ -97,6 +99,8 @@ Packaging for your favorite distribution would be a welcome contribution!
|
|||||||
|
|
||||||
*Note*: Qt 5.9.7 is the minimum version required to build the GUI.
|
*Note*: Qt 5.9.7 is the minimum version required to build the GUI.
|
||||||
|
|
||||||
|
*Note*: Official GUI releases use monero-wallet-gui from this process alongside the supporting binaries (monerod, etc) from the [CLI deterministic builds](https://github.com/monero-project/monero/blob/master/contrib/gitian/README.md).
|
||||||
|
|
||||||
### Building Reproducible Windows static binaries with Docker (any OS)
|
### Building Reproducible Windows static binaries with Docker (any OS)
|
||||||
|
|
||||||
1. Install Docker [https://docs.docker.com/engine/install/](https://docs.docker.com/engine/install/)
|
1. Install Docker [https://docs.docker.com/engine/install/](https://docs.docker.com/engine/install/)
|
||||||
@@ -205,7 +209,7 @@ Packaging for your favorite distribution would be a welcome contribution!
|
|||||||
|
|
||||||
- For Debian distributions (Debian, Ubuntu, Mint, Tails...)
|
- For Debian distributions (Debian, Ubuntu, Mint, Tails...)
|
||||||
|
|
||||||
`sudo apt install build-essential cmake libboost-all-dev miniupnpc libunbound-dev graphviz doxygen libunwind8-dev pkg-config libssl-dev libzmq3-dev libsodium-dev libhidapi-dev libnorm-dev libusb-1.0-0-dev libpgm-dev libprotobuf-dev protobuf-compiler libgcrypt20-dev`
|
`sudo apt install build-essential cmake miniupnpc libunbound-dev graphviz doxygen libunwind8-dev pkg-config libssl-dev libzmq3-dev libsodium-dev libhidapi-dev libnorm-dev libusb-1.0-0-dev libpgm-dev libprotobuf-dev protobuf-compiler libgcrypt20-dev libboost-chrono-dev libboost-date-time-dev libboost-filesystem-dev libboost-locale-dev libboost-program-options-dev libboost-regex-dev libboost-serialization-dev libboost-system-dev libboost-thread-dev`
|
||||||
|
|
||||||
- For Gentoo
|
- For Gentoo
|
||||||
|
|
||||||
@@ -228,6 +232,9 @@ The following instructions will fetch Qt from your distribution's repositories i
|
|||||||
`sudo apt install qtbase5-dev qt5-default qtdeclarative5-dev qml-module-qtqml-models2 qml-module-qtquick-controls qml-module-qtquick-controls2 qml-module-qtquick-dialogs qml-module-qtquick-xmllistmodel qml-module-qt-labs-settings qml-module-qt-labs-platform qml-module-qt-labs-folderlistmodel qttools5-dev-tools qml-module-qtquick-templates2 libqt5svg5-dev`
|
`sudo apt install qtbase5-dev qt5-default qtdeclarative5-dev qml-module-qtqml-models2 qml-module-qtquick-controls qml-module-qtquick-controls2 qml-module-qtquick-dialogs qml-module-qtquick-xmllistmodel qml-module-qt-labs-settings qml-module-qt-labs-platform qml-module-qt-labs-folderlistmodel qttools5-dev-tools qml-module-qtquick-templates2 libqt5svg5-dev`
|
||||||
|
|
||||||
- For Gentoo
|
- For Gentoo
|
||||||
|
|
||||||
|
|
||||||
|
The *qml* USE flag must be enabled.
|
||||||
|
|
||||||
`sudo emerge dev-qt/qtcore:5 dev-qt/qtdeclarative:5 dev-qt/qtquickcontrols:5 dev-qt/qtquickcontrols2:5 dev-qt/qtgraphicaleffects:5`
|
`sudo emerge dev-qt/qtcore:5 dev-qt/qtdeclarative:5 dev-qt/qtquickcontrols:5 dev-qt/qtquickcontrols2:5 dev-qt/qtgraphicaleffects:5`
|
||||||
|
|
||||||
@@ -237,9 +244,7 @@ The following instructions will fetch Qt from your distribution's repositories i
|
|||||||
|
|
||||||
`sudo apt install qtmultimedia5-dev qml-module-qtmultimedia`
|
`sudo apt install qtmultimedia5-dev qml-module-qtmultimedia`
|
||||||
|
|
||||||
- For Gentoo
|
- For Gentoo
|
||||||
|
|
||||||
The *qml* USE flag must be enabled.
|
|
||||||
|
|
||||||
`emerge dev-qt/qtmultimedia:5`
|
`emerge dev-qt/qtmultimedia:5`
|
||||||
|
|
||||||
@@ -253,11 +258,20 @@ The following instructions will fetch Qt from your distribution's repositories i
|
|||||||
|
|
||||||
4. Build
|
4. Build
|
||||||
|
|
||||||
|
If on x86-64:
|
||||||
|
|
||||||
```
|
```
|
||||||
make release -j4
|
make release -j4
|
||||||
```
|
```
|
||||||
|
|
||||||
|
If on ppc64le:
|
||||||
|
|
||||||
|
```
|
||||||
|
make release-linux-ppc64le -j4
|
||||||
|
```
|
||||||
|
|
||||||
\* `4` - number of CPU threads to use
|
\* `4` - number of CPU threads to use
|
||||||
\* Add `CMAKE_PREFIX_PATH` enviroment variable to set a custom Qt install directory, e.g. `CMAKE_PREFIX_PATH=$HOME/Qt/5.9.7/gcc_64 make release -j4`
|
\* Add `CMAKE_PREFIX_PATH` environment variable to set a custom Qt install directory, e.g. `CMAKE_PREFIX_PATH=$HOME/Qt/5.9.7/gcc_64 make release -j4`
|
||||||
|
|
||||||
The executable can be found in the build/release/bin folder.
|
The executable can be found in the build/release/bin folder.
|
||||||
|
|
||||||
@@ -269,7 +283,7 @@ The executable can be found in the build/release/bin folder.
|
|||||||
|
|
||||||
3. Install [monero](https://github.com/monero-project/monero) dependencies:
|
3. Install [monero](https://github.com/monero-project/monero) dependencies:
|
||||||
|
|
||||||
`brew install boost hidapi zmq libpgm libsodium miniupnpc ldns expat libunwind-headers protobuf libgcrypt`
|
`brew install cmake pkg-config openssl boost unbound hidapi zmq libpgm libsodium miniupnpc ldns expat libunwind-headers protobuf libgcrypt`
|
||||||
|
|
||||||
4. Install Qt:
|
4. Install Qt:
|
||||||
|
|
||||||
@@ -288,7 +302,7 @@ The executable can be found in the build/release/bin folder.
|
|||||||
make release -j4
|
make release -j4
|
||||||
```
|
```
|
||||||
\* `4` - number of CPU threads to use
|
\* `4` - number of CPU threads to use
|
||||||
\* Add `CMAKE_PREFIX_PATH` enviroment variable to set a custom Qt install directory, e.g. `CMAKE_PREFIX_PATH=$HOME/Qt/5.9.7/clang_64 make release -j4`
|
\* Add `CMAKE_PREFIX_PATH` environment variable to set a custom Qt install directory, e.g. `CMAKE_PREFIX_PATH=$HOME/Qt/5.9.7/clang_64 make release -j4`
|
||||||
|
|
||||||
The executable can be found in the `build/release/bin` folder.
|
The executable can be found in the `build/release/bin` folder.
|
||||||
|
|
||||||
|
|||||||
@@ -74,19 +74,19 @@ if(APPLE OR (WIN32 AND NOT STATIC))
|
|||||||
)
|
)
|
||||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||||
list(APPEND WIN_DEPLOY_DLLS
|
list(APPEND WIN_DEPLOY_DLLS
|
||||||
libicudtd68.dll
|
libicudtd69.dll
|
||||||
libicuind68.dll
|
libicuind69.dll
|
||||||
libicuiod68.dll
|
libicuiod69.dll
|
||||||
libicutud68.dll
|
libicutud69.dll
|
||||||
libicuucd68.dll
|
libicuucd69.dll
|
||||||
)
|
)
|
||||||
else() # assume release
|
else() # assume release
|
||||||
list(APPEND WIN_DEPLOY_DLLS
|
list(APPEND WIN_DEPLOY_DLLS
|
||||||
libicudt68.dll
|
libicudt69.dll
|
||||||
libicuin68.dll
|
libicuin69.dll
|
||||||
libicuio68.dll
|
libicuio69.dll
|
||||||
libicutu68.dll
|
libicutu69.dll
|
||||||
libicuuc68.dll
|
libicuuc69.dll
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
list(TRANSFORM WIN_DEPLOY_DLLS PREPEND "$ENV{MSYSTEM_PREFIX}/bin/")
|
list(TRANSFORM WIN_DEPLOY_DLLS PREPEND "$ENV{MSYSTEM_PREFIX}/bin/")
|
||||||
|
|||||||
@@ -1,56 +0,0 @@
|
|||||||
# Copyright (c) 2014-2020, The Monero Project
|
|
||||||
#
|
|
||||||
# All rights reserved.
|
|
||||||
#
|
|
||||||
# Redistribution and use in source and binary forms, with or without modification, are
|
|
||||||
# permitted provided that the following conditions are met:
|
|
||||||
#
|
|
||||||
# 1. Redistributions of source code must retain the above copyright notice, this list of
|
|
||||||
# conditions and the following disclaimer.
|
|
||||||
#
|
|
||||||
# 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
|
||||||
# of conditions and the following disclaimer in the documentation and/or other
|
|
||||||
# materials provided with the distribution.
|
|
||||||
#
|
|
||||||
# 3. Neither the name of the copyright holder nor the names of its contributors may be
|
|
||||||
# used to endorse or promote products derived from this software without specific
|
|
||||||
# prior written permission.
|
|
||||||
#
|
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
|
||||||
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
||||||
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
|
||||||
# THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
||||||
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
|
||||||
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
|
||||||
# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
# - Try to find readline include dirs and libraries
|
|
||||||
#
|
|
||||||
# Automatically finds ccache build accelerator, if it's found in PATH.
|
|
||||||
#
|
|
||||||
# Usage of this module as follows:
|
|
||||||
#
|
|
||||||
# project(monero)
|
|
||||||
# include(FindCcache) # Include AFTER the project() macro to be able to reach the CMAKE_CXX_COMPILER variable
|
|
||||||
#
|
|
||||||
# Properties modified by this module:
|
|
||||||
#
|
|
||||||
# GLOBAL PROPERTY RULE_LAUNCH_COMPILE set to ccache, when ccache found
|
|
||||||
# GLOBAL PROPERTY RULE_LAUNCH_LINK set to ccache, when ccache found
|
|
||||||
|
|
||||||
find_program(CCACHE_FOUND ccache)
|
|
||||||
if (CCACHE_FOUND)
|
|
||||||
set(TEMP_CPP_FILE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/test-program.cpp")
|
|
||||||
file(WRITE "${TEMP_CPP_FILE}" "int main() { return 0; }")
|
|
||||||
execute_process(COMMAND "${CCACHE_FOUND}" "${CMAKE_CXX_COMPILER}" "${TEMP_CPP_FILE}" RESULT_VARIABLE RET)
|
|
||||||
if (${RET} EQUAL 0)
|
|
||||||
message("found usable ccache: ${CCACHE_FOUND}")
|
|
||||||
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CCACHE_FOUND}")
|
|
||||||
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK "${CCACHE_FOUND}")
|
|
||||||
else()
|
|
||||||
message("found ccache ${CCACHE_FOUND}, but is UNUSABLE! Return code: ${RET}")
|
|
||||||
endif()
|
|
||||||
else()
|
|
||||||
message("ccache NOT found!")
|
|
||||||
endif()
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
# Copyright (c) 2014-2019, The Monero Project
|
|
||||||
#
|
|
||||||
# All rights reserved.
|
|
||||||
#
|
|
||||||
# Redistribution and use in source and binary forms, with or without modification, are
|
|
||||||
# permitted provided that the following conditions are met:
|
|
||||||
#
|
|
||||||
# 1. Redistributions of source code must retain the above copyright notice, this list of
|
|
||||||
# conditions and the following disclaimer.
|
|
||||||
#
|
|
||||||
# 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
|
||||||
# of conditions and the following disclaimer in the documentation and/or other
|
|
||||||
# materials provided with the distribution.
|
|
||||||
#
|
|
||||||
# 3. Neither the name of the copyright holder nor the names of its contributors may be
|
|
||||||
# used to endorse or promote products derived from this software without specific
|
|
||||||
# prior written permission.
|
|
||||||
#
|
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
|
||||||
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
||||||
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
|
||||||
# THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
||||||
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
|
||||||
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
|
||||||
# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
#
|
|
||||||
# Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
|
|
||||||
|
|
||||||
function (git_get_version_tag git directory result_var)
|
|
||||||
execute_process(COMMAND "${git}" rev-parse --short HEAD
|
|
||||||
WORKING_DIRECTORY ${directory}
|
|
||||||
OUTPUT_VARIABLE COMMIT
|
|
||||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
|
||||||
)
|
|
||||||
if(NOT COMMIT)
|
|
||||||
message(WARNING "${directory}: cannot determine current commit. Make sure that you are building from a Git working tree")
|
|
||||||
set(${result_var} "unknown" PARENT_SCOPE)
|
|
||||||
return()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
execute_process(COMMAND "${git}" describe --tags --exact-match
|
|
||||||
WORKING_DIRECTORY ${directory}
|
|
||||||
OUTPUT_VARIABLE TAG
|
|
||||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
|
||||||
)
|
|
||||||
if(TAG)
|
|
||||||
message(STATUS "${directory}: building tagged release ${TAG}-${COMMIT}")
|
|
||||||
set(${result_var} "${TAG}-${COMMIT}" PARENT_SCOPE)
|
|
||||||
return()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
execute_process(COMMAND "${git}" describe --tags --long
|
|
||||||
WORKING_DIRECTORY ${directory}
|
|
||||||
OUTPUT_VARIABLE MOST_RECENT_TAG
|
|
||||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
|
||||||
)
|
|
||||||
if(MOST_RECENT_TAG)
|
|
||||||
message(STATUS "${directory}: ahead of or behind a tagged release, building ${MOST_RECENT_TAG}")
|
|
||||||
set(${result_var} "${MOST_RECENT_TAG}" PARENT_SCOPE)
|
|
||||||
return()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
message(STATUS "${directory}: building ${COMMIT} commit")
|
|
||||||
set(${result_var} "${COMMIT}" PARENT_SCOPE)
|
|
||||||
endfunction()
|
|
||||||
@@ -26,7 +26,8 @@
|
|||||||
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||||
# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
function (write_static_version_header VERSION_TAG_GUI)
|
function (write_static_version_header tag)
|
||||||
|
set(VERSION_TAG_GUI "${tag}" CACHE STRING "The tag portion of the Monero GUI software version" FORCE)
|
||||||
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/version.js.in" "${CMAKE_CURRENT_SOURCE_DIR}/version.js")
|
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/version.js.in" "${CMAKE_CURRENT_SOURCE_DIR}/version.js")
|
||||||
endfunction ()
|
endfunction ()
|
||||||
|
|
||||||
@@ -36,11 +37,8 @@ if ("$Format:$" STREQUAL "")
|
|||||||
write_static_version_header("release")
|
write_static_version_header("release")
|
||||||
elseif (GIT_FOUND OR Git_FOUND)
|
elseif (GIT_FOUND OR Git_FOUND)
|
||||||
message(STATUS "Found Git: ${GIT_EXECUTABLE}")
|
message(STATUS "Found Git: ${GIT_EXECUTABLE}")
|
||||||
|
get_version_tag_from_git("${GIT_EXECUTABLE}")
|
||||||
include(GitGetVersionTag)
|
write_static_version_header(${VERSIONTAG})
|
||||||
git_get_version_tag(${GIT_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR} VERSION_TAG_GUI)
|
|
||||||
STRING(REGEX REPLACE "^v([0-9])" "\\1" VERSION_TAG_GUI ${VERSION_TAG_GUI})
|
|
||||||
write_static_version_header(${VERSION_TAG_GUI})
|
|
||||||
else()
|
else()
|
||||||
message(STATUS "WARNING: Git was not found!")
|
message(STATUS "WARNING: Git was not found!")
|
||||||
write_static_version_header("unknown")
|
write_static_version_header("unknown")
|
||||||
|
|||||||
@@ -37,27 +37,30 @@ RowLayout {
|
|||||||
Layout.fillWidth: false
|
Layout.fillWidth: false
|
||||||
Layout.alignment: Qt.AlignTop | Qt.AlignLeft
|
Layout.alignment: Qt.AlignTop | Qt.AlignLeft
|
||||||
spacing: 4
|
spacing: 4
|
||||||
|
|
||||||
RowLayout {
|
RowLayout {
|
||||||
Layout.fillWidth: false
|
Layout.fillWidth: false
|
||||||
spacing: 12
|
spacing: 12
|
||||||
Layout.alignment: Qt.AlignTop | Qt.AlignLeft
|
Layout.alignment: Qt.AlignTop | Qt.AlignLeft
|
||||||
|
|
||||||
StandardButton {
|
StandardButton {
|
||||||
id: button1
|
id: button1
|
||||||
small: true
|
small: true
|
||||||
|
primary: false
|
||||||
visible: button1.text
|
visible: button1.text
|
||||||
}
|
}
|
||||||
|
|
||||||
StandardButton {
|
StandardButton {
|
||||||
id: button2
|
id: button2
|
||||||
small: true
|
small: true
|
||||||
|
primary: false
|
||||||
visible: button2.text
|
visible: button2.text
|
||||||
}
|
}
|
||||||
|
|
||||||
StandardButton {
|
StandardButton {
|
||||||
id: button3
|
id: button3
|
||||||
small: true
|
small: true
|
||||||
|
primary: false
|
||||||
visible: button3.text
|
visible: button3.text
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,14 +5,21 @@ import FontAwesome 1.0
|
|||||||
import "../components" as MoneroComponents
|
import "../components" as MoneroComponents
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
|
signal cut()
|
||||||
|
signal copy()
|
||||||
signal paste()
|
signal paste()
|
||||||
|
signal remove()
|
||||||
|
signal selectAll()
|
||||||
|
|
||||||
id: root
|
id: root
|
||||||
acceptedButtons: Qt.RightButton
|
acceptedButtons: Qt.RightButton
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if (mouse.button === Qt.RightButton)
|
if (mouse.button === Qt.RightButton) {
|
||||||
|
root.parent.persistentSelection = true;
|
||||||
contextMenu.open()
|
contextMenu.open()
|
||||||
|
root.parent.cursorVisible = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Menu {
|
Menu {
|
||||||
@@ -22,19 +29,50 @@ MouseArea {
|
|||||||
border.color: MoneroComponents.Style.buttonBackgroundColorDisabledHover
|
border.color: MoneroComponents.Style.buttonBackgroundColorDisabledHover
|
||||||
border.width: 1
|
border.width: 1
|
||||||
radius: 2
|
radius: 2
|
||||||
color: MoneroComponents.Style.buttonBackgroundColorDisabled
|
color: MoneroComponents.Style.blackTheme ? MoneroComponents.Style.buttonBackgroundColorDisabled : "#E5E5E5"
|
||||||
}
|
}
|
||||||
|
|
||||||
padding: 1
|
padding: 1
|
||||||
width: 100
|
width: 110
|
||||||
x: root.mouseX
|
x: root.mouseX
|
||||||
y: root.mouseY
|
y: root.mouseY
|
||||||
|
|
||||||
|
onClosed: {
|
||||||
|
if (!root.parent.activeFocus) {
|
||||||
|
root.parent.cursorVisible = false;
|
||||||
|
}
|
||||||
|
root.parent.persistentSelection = false;
|
||||||
|
root.parent.forceActiveFocus()
|
||||||
|
}
|
||||||
|
|
||||||
|
MoneroComponents.ContextMenuItem {
|
||||||
|
enabled: root.parent.selectedText != "" && !root.parent.readOnly
|
||||||
|
onTriggered: root.cut()
|
||||||
|
text: qsTr("Cut") + translationManager.emptyString
|
||||||
|
}
|
||||||
|
|
||||||
|
MoneroComponents.ContextMenuItem {
|
||||||
|
enabled: root.parent.selectedText != ""
|
||||||
|
onTriggered: root.copy()
|
||||||
|
text: qsTr("Copy") + translationManager.emptyString
|
||||||
|
}
|
||||||
|
|
||||||
MoneroComponents.ContextMenuItem {
|
MoneroComponents.ContextMenuItem {
|
||||||
enabled: root.parent.canPaste === true
|
enabled: root.parent.canPaste === true
|
||||||
glyphIcon: FontAwesome.paste
|
|
||||||
onTriggered: root.paste()
|
onTriggered: root.paste()
|
||||||
text: qsTr("Paste") + translationManager.emptyString
|
text: qsTr("Paste") + translationManager.emptyString
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MoneroComponents.ContextMenuItem {
|
||||||
|
enabled: root.parent.selectedText != "" && !root.parent.readOnly
|
||||||
|
onTriggered: root.remove()
|
||||||
|
text: qsTr("Delete") + translationManager.emptyString
|
||||||
|
}
|
||||||
|
|
||||||
|
MoneroComponents.ContextMenuItem {
|
||||||
|
enabled: root.parent.text != ""
|
||||||
|
onTriggered: root.selectAll()
|
||||||
|
text: qsTr("Select All") + translationManager.emptyString
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,21 +13,31 @@ MenuItem {
|
|||||||
|
|
||||||
background: Rectangle {
|
background: Rectangle {
|
||||||
color: MoneroComponents.Style.buttonBackgroundColorDisabledHover
|
color: MoneroComponents.Style.buttonBackgroundColorDisabledHover
|
||||||
opacity: mouse.containsMouse ? 1 : 0
|
opacity: 0
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
id: mouse
|
id: mouse
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
onClicked: menuItem.triggered()
|
onEntered: {
|
||||||
visible: menuItem.enabled
|
parent.opacity = 1;
|
||||||
|
}
|
||||||
|
onExited: {
|
||||||
|
parent.opacity = 0;
|
||||||
|
}
|
||||||
|
onClicked: {
|
||||||
|
if (menuItem.enabled) {
|
||||||
|
menuItem.triggered();
|
||||||
|
parent.opacity = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
contentItem: RowLayout {
|
contentItem: RowLayout {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.leftMargin: 10
|
anchors.leftMargin: 20
|
||||||
anchors.rightMargin: 10
|
anchors.rightMargin: 10
|
||||||
opacity: menuItem.enabled ? 1 : 0.4
|
opacity: menuItem.enabled ? 1 : 0.4
|
||||||
spacing: 8
|
spacing: 8
|
||||||
@@ -42,7 +52,7 @@ MenuItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
color: MoneroComponents.Style.buttonTextColor
|
color: MoneroComponents.Style.blackTheme ? MoneroComponents.Style.buttonTextColor : MoneroComponents.Style.defaultFontColor
|
||||||
font.family: MoneroComponents.Style.fontRegular.name
|
font.family: MoneroComponents.Style.fontRegular.name
|
||||||
font.pixelSize: 14
|
font.pixelSize: 14
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ Item {
|
|||||||
Rectangle{
|
Rectangle{
|
||||||
id: rect
|
id: rect
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
color: MoneroComponents.Style.buttonInlineBackgroundColor
|
color: buttonArea.containsMouse ? MoneroComponents.Style.buttonInlineBackgroundColorHover : MoneroComponents.Style.buttonInlineBackgroundColor
|
||||||
radius: 4
|
radius: 4
|
||||||
|
|
||||||
|
|
||||||
@@ -101,13 +101,9 @@ Item {
|
|||||||
}
|
}
|
||||||
onEntered: {
|
onEntered: {
|
||||||
tooltip.text ? tooltip.tooltipPopup.open() : ""
|
tooltip.text ? tooltip.tooltipPopup.open() : ""
|
||||||
rect.color = buttonColor ? buttonColor : "#707070";
|
|
||||||
rect.opacity = 0.8;
|
|
||||||
}
|
}
|
||||||
onExited: {
|
onExited: {
|
||||||
tooltip.text ? tooltip.tooltipPopup.close() : ""
|
tooltip.text ? tooltip.tooltipPopup.close() : ""
|
||||||
rect.opacity = 1.0;
|
|
||||||
rect.color = buttonColor ? buttonColor : "#808080";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,9 +48,16 @@ TextField {
|
|||||||
|
|
||||||
MoneroComponents.ContextMenu {
|
MoneroComponents.ContextMenu {
|
||||||
cursorShape: Qt.IBeamCursor
|
cursorShape: Qt.IBeamCursor
|
||||||
|
onCut: textField.cut();
|
||||||
|
onCopy: textField.copy();
|
||||||
onPaste: {
|
onPaste: {
|
||||||
textField.clear();
|
var previoustextFieldLength = textField.length
|
||||||
|
var previousCursorPosition = textField.cursorPosition;
|
||||||
textField.paste();
|
textField.paste();
|
||||||
|
textField.forceActiveFocus()
|
||||||
|
textField.cursorPosition = previousCursorPosition + (textField.length - previoustextFieldLength);
|
||||||
}
|
}
|
||||||
|
onRemove: textField.remove(selectionStart, selectionEnd);
|
||||||
|
onSelectAll: textField.selectAll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,9 +71,16 @@ TextArea {
|
|||||||
|
|
||||||
MoneroComponents.ContextMenu {
|
MoneroComponents.ContextMenu {
|
||||||
cursorShape: Qt.IBeamCursor
|
cursorShape: Qt.IBeamCursor
|
||||||
|
onCut: textArea.cut();
|
||||||
|
onCopy: textArea.copy();
|
||||||
onPaste: {
|
onPaste: {
|
||||||
textArea.clear();
|
var previoustextFieldLength = textArea.length
|
||||||
|
var previousCursorPosition = textArea.cursorPosition;
|
||||||
textArea.paste();
|
textArea.paste();
|
||||||
|
textArea.forceActiveFocus()
|
||||||
|
textArea.cursorPosition = previousCursorPosition + (textArea.length - previoustextFieldLength);
|
||||||
}
|
}
|
||||||
|
onRemove: textArea.remove(selectionStart, selectionEnd);
|
||||||
|
onSelectAll: textArea.selectAll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import "../components/effects/" as MoneroEffects
|
|||||||
Label {
|
Label {
|
||||||
id: item
|
id: item
|
||||||
fontSize: 18
|
fontSize: 18
|
||||||
|
tooltipIconVisible: true
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
anchors.top: item.bottom
|
anchors.top: item.bottom
|
||||||
|
|||||||
@@ -218,7 +218,7 @@ ColumnLayout {
|
|||||||
Layout.preferredHeight: inputHeight
|
Layout.preferredHeight: inputHeight
|
||||||
|
|
||||||
leftPadding: item.inputPaddingLeft
|
leftPadding: item.inputPaddingLeft
|
||||||
rightPadding: (inlineButtons.width > 0 ? inlineButtons.width + inlineButtons.spacing : 0) + inputPaddingRight
|
rightPadding: (inlineButtons.width > 0 ? inlineButtons.width + inlineButtons.spacing : 0) + inputPaddingRight + (password || passwordLinked ? 45 : 0)
|
||||||
topPadding: item.inputPaddingTop
|
topPadding: item.inputPaddingTop
|
||||||
bottomPadding: item.inputPaddingBottom
|
bottomPadding: item.inputPaddingBottom
|
||||||
|
|
||||||
|
|||||||
@@ -32,6 +32,8 @@ import "." as MoneroComponents
|
|||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
default property list<MoneroComponents.NavbarItem> items
|
default property list<MoneroComponents.NavbarItem> items
|
||||||
|
property alias currentIndex: repeater.currentIndex
|
||||||
|
property alias previousIndex: repeater.previousIndex
|
||||||
|
|
||||||
color: "transparent"
|
color: "transparent"
|
||||||
height: grid.height
|
height: grid.height
|
||||||
@@ -100,7 +102,10 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Repeater {
|
Repeater {
|
||||||
|
id: repeater
|
||||||
model: items.length
|
model: items.length
|
||||||
|
property int currentIndex: 0
|
||||||
|
property int previousIndex: 0
|
||||||
|
|
||||||
RowLayout {
|
RowLayout {
|
||||||
spacing: 0
|
spacing: 0
|
||||||
@@ -149,7 +154,11 @@ Rectangle {
|
|||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
cursorShape: Qt.PointingHandCursor
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
|
||||||
onClicked: items[index].selected()
|
onClicked: {
|
||||||
|
repeater.previousIndex = repeater.currentIndex;
|
||||||
|
repeater.currentIndex = index;
|
||||||
|
items[index].selected()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -52,6 +52,8 @@ Rectangle {
|
|||||||
case Wallet.ConnectionStatus_Connected:
|
case Wallet.ConnectionStatus_Connected:
|
||||||
if (!appWindow.daemonSynced)
|
if (!appWindow.daemonSynced)
|
||||||
return qsTr("Synchronizing");
|
return qsTr("Synchronizing");
|
||||||
|
if (persistentSettings.useRemoteNode && persistentSettings.allowRemoteNodeMining && appWindow.isMining)
|
||||||
|
return qsTr("Remote node") + " + " + qsTr("Mining");
|
||||||
if (persistentSettings.useRemoteNode)
|
if (persistentSettings.useRemoteNode)
|
||||||
return qsTr("Remote node");
|
return qsTr("Remote node");
|
||||||
return appWindow.isMining ? qsTr("Connected") + " + " + qsTr("Mining"): qsTr("Connected");
|
return appWindow.isMining ? qsTr("Connected") + " + " + qsTr("Mining"): qsTr("Connected");
|
||||||
|
|||||||
@@ -108,7 +108,11 @@ Item {
|
|||||||
leftPanel.enabled = true
|
leftPanel.enabled = true
|
||||||
middlePanel.enabled = true
|
middlePanel.enabled = true
|
||||||
wizard.enabled = true
|
wizard.enabled = true
|
||||||
titleBar.state = "default"
|
if (rootItem.state == "wizard") {
|
||||||
|
titleBar.state = "essentials"
|
||||||
|
} else {
|
||||||
|
titleBar.state = "default"
|
||||||
|
}
|
||||||
|
|
||||||
root.visible = false;
|
root.visible = false;
|
||||||
appWindow.hideBalanceForced = false;
|
appWindow.hideBalanceForced = false;
|
||||||
|
|||||||
@@ -42,6 +42,13 @@ MoneroComponents.Dialog {
|
|||||||
|
|
||||||
onActiveFocusChanged: activeFocus && remoteNodeAddress.forceActiveFocus()
|
onActiveFocusChanged: activeFocus && remoteNodeAddress.forceActiveFocus()
|
||||||
|
|
||||||
|
function onOk() {
|
||||||
|
root.success = true;
|
||||||
|
root.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
function onCancel() { root.close(); }
|
||||||
|
|
||||||
function add(callbackOnSuccess) {
|
function add(callbackOnSuccess) {
|
||||||
root.editMode = false;
|
root.editMode = false;
|
||||||
root.callbackOnSuccess = callbackOnSuccess;
|
root.callbackOnSuccess = callbackOnSuccess;
|
||||||
@@ -89,6 +96,11 @@ MoneroComponents.Dialog {
|
|||||||
|
|
||||||
daemonAddrLabelText: qsTr("Address") + translationManager.emptyString
|
daemonAddrLabelText: qsTr("Address") + translationManager.emptyString
|
||||||
daemonPortLabelText: qsTr("Port") + translationManager.emptyString
|
daemonPortLabelText: qsTr("Port") + translationManager.emptyString
|
||||||
|
|
||||||
|
Keys.enabled: root.visible
|
||||||
|
Keys.onEnterPressed: root.onOk()
|
||||||
|
Keys.onReturnPressed: root.onOk()
|
||||||
|
Keys.onEscapePressed: root.onCancel()
|
||||||
}
|
}
|
||||||
|
|
||||||
RowLayout {
|
RowLayout {
|
||||||
@@ -116,6 +128,11 @@ MoneroComponents.Dialog {
|
|||||||
placeholderFontSize: 15
|
placeholderFontSize: 15
|
||||||
labelFontSize: 14
|
labelFontSize: 14
|
||||||
fontSize: 15
|
fontSize: 15
|
||||||
|
|
||||||
|
Keys.enabled: root.visible
|
||||||
|
Keys.onEnterPressed: root.onOk()
|
||||||
|
Keys.onReturnPressed: root.onOk()
|
||||||
|
Keys.onEscapePressed: root.onCancel()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ ColumnLayout {
|
|||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.rightMargin: 80
|
anchors.rightMargin: 80
|
||||||
color: "transparent"
|
color: "transparent"
|
||||||
property var trusted: remoteNodesModel.get(index).trusted
|
property var trusted: remoteNodesModel.get(index) ? remoteNodesModel.get(index).trusted : false
|
||||||
|
|
||||||
MoneroComponents.TextPlain {
|
MoneroComponents.TextPlain {
|
||||||
id: addressText
|
id: addressText
|
||||||
@@ -107,8 +107,9 @@ ColumnLayout {
|
|||||||
MoneroComponents.Label {
|
MoneroComponents.Label {
|
||||||
id: trustedDaemonCheckMark
|
id: trustedDaemonCheckMark
|
||||||
anchors.left: addressText.right
|
anchors.left: addressText.right
|
||||||
anchors.leftMargin: 6
|
anchors.leftMargin: 3
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
anchors.verticalCenterOffset: 2
|
||||||
z: itemMouseArea.z + 1
|
z: itemMouseArea.z + 1
|
||||||
fontSize: 16
|
fontSize: 16
|
||||||
fontFamily: FontAwesome.fontFamilySolid
|
fontFamily: FontAwesome.fontFamilySolid
|
||||||
@@ -144,6 +145,9 @@ ColumnLayout {
|
|||||||
tooltipLeft: true
|
tooltipLeft: true
|
||||||
onClicked: remoteNodeDialog.edit(remoteNodesModel.get(index), function (remoteNode) {
|
onClicked: remoteNodeDialog.edit(remoteNodesModel.get(index), function (remoteNode) {
|
||||||
remoteNodesModel.set(index, remoteNode)
|
remoteNodesModel.set(index, remoteNode)
|
||||||
|
if (index === remoteNodesModel.selected) {
|
||||||
|
remoteNodesModel.applyRemoteNode(index)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,9 +7,11 @@ import "../components" as MoneroComponents
|
|||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
id: settingsListItem
|
id: settingsListItem
|
||||||
property alias iconText: iconLabel.text
|
property alias iconText: iconLabel.text
|
||||||
|
property alias symbol: symbolText.text
|
||||||
property alias description: area.text
|
property alias description: area.text
|
||||||
property alias title: header.text
|
property alias title: header.text
|
||||||
property bool isLast: false
|
property bool isLast: false
|
||||||
|
property bool enabled: true
|
||||||
signal clicked()
|
signal clicked()
|
||||||
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
@@ -37,6 +39,7 @@ ColumnLayout {
|
|||||||
width: parent.width
|
width: parent.width
|
||||||
height: header.height + area.contentHeight
|
height: header.height + area.contentHeight
|
||||||
color: "transparent";
|
color: "transparent";
|
||||||
|
opacity: settingsListItem.enabled ? 1 : 0.25
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.bottomMargin: 4
|
anchors.bottomMargin: 4
|
||||||
anchors.topMargin: 4
|
anchors.topMargin: 4
|
||||||
@@ -102,6 +105,7 @@ ColumnLayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
|
visible: settingsListItem.enabled
|
||||||
cursorShape: Qt.PointingHandCursor
|
cursorShape: Qt.PointingHandCursor
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
@@ -111,5 +115,17 @@ ColumnLayout {
|
|||||||
settingsListItem.clicked()
|
settingsListItem.clicked()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MoneroComponents.TextPlain {
|
||||||
|
id: symbolText
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.rightMargin: 44
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
font.pixelSize: 12
|
||||||
|
font.bold: true
|
||||||
|
color: MoneroComponents.Style.menuButtonTextColor
|
||||||
|
visible: appWindow.ctrlPressed
|
||||||
|
themeTransition: false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,16 +39,12 @@ Item {
|
|||||||
property bool primary: true
|
property bool primary: true
|
||||||
property string rightIcon: ""
|
property string rightIcon: ""
|
||||||
property string rightIconInactive: ""
|
property string rightIconInactive: ""
|
||||||
property color textColor: !button.enabled
|
property color textColor: primary ? MoneroComponents.Style.buttonTextColor : MoneroComponents.Style.buttonSecondaryTextColor;
|
||||||
? MoneroComponents.Style.buttonTextColorDisabled
|
|
||||||
: primary
|
|
||||||
? MoneroComponents.Style.buttonTextColor
|
|
||||||
: MoneroComponents.Style.buttonSecondaryTextColor;
|
|
||||||
property bool small: false
|
property bool small: false
|
||||||
property alias text: label.text
|
property alias text: label.text
|
||||||
property alias fontBold: label.font.bold
|
property alias fontBold: label.font.bold
|
||||||
property int fontSize: {
|
property int fontSize: {
|
||||||
if(small) return 14;
|
if(small) return 13.5;
|
||||||
else return 16;
|
else return 16;
|
||||||
}
|
}
|
||||||
property alias label: label
|
property alias label: label
|
||||||
@@ -72,6 +68,7 @@ Item {
|
|||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
radius: 3
|
radius: 3
|
||||||
border.width: parent.focus && parent.enabled ? 1 : 0
|
border.width: parent.focus && parent.enabled ? 1 : 0
|
||||||
|
opacity: 1
|
||||||
|
|
||||||
state: button.enabled ? "active" : "disabled"
|
state: button.enabled ? "active" : "disabled"
|
||||||
Component.onCompleted: state = state
|
Component.onCompleted: state = state
|
||||||
@@ -102,7 +99,14 @@ Item {
|
|||||||
when: !button.enabled
|
when: !button.enabled
|
||||||
PropertyChanges {
|
PropertyChanges {
|
||||||
target: buttonRect
|
target: buttonRect
|
||||||
color: MoneroComponents.Style.buttonBackgroundColorDisabled
|
opacity: 0.5
|
||||||
|
color: primary
|
||||||
|
? MoneroComponents.Style.buttonBackgroundColor
|
||||||
|
: MoneroComponents.Style.buttonSecondaryBackgroundColor
|
||||||
|
}
|
||||||
|
PropertyChanges {
|
||||||
|
target: label
|
||||||
|
opacity: 0.5
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -122,7 +126,7 @@ Item {
|
|||||||
MoneroComponents.TextPlain {
|
MoneroComponents.TextPlain {
|
||||||
id: label
|
id: label
|
||||||
font.family: MoneroComponents.Style.fontBold.name
|
font.family: MoneroComponents.Style.fontBold.name
|
||||||
font.bold: true
|
font.bold: button.primary ? true : false
|
||||||
font.pixelSize: button.fontSize
|
font.pixelSize: button.fontSize
|
||||||
color: !buttonArea.pressed ? button.textColor : "transparent"
|
color: !buttonArea.pressed ? button.textColor : "transparent"
|
||||||
visible: text !== ""
|
visible: text !== ""
|
||||||
@@ -145,6 +149,7 @@ Item {
|
|||||||
Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
|
Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
|
||||||
width: button.small ? 16 : 20
|
width: button.small ? 16 : 20
|
||||||
height: button.small ? 16 : 20
|
height: button.small ? 16 : 20
|
||||||
|
opacity: buttonRect.opacity
|
||||||
source: {
|
source: {
|
||||||
if (fontAwesomeIcon) return "";
|
if (fontAwesomeIcon) return "";
|
||||||
if(button.rightIconInactive !== "" && !button.enabled) {
|
if(button.rightIconInactive !== "" && !button.enabled) {
|
||||||
|
|||||||
@@ -191,7 +191,7 @@ ColumnLayout {
|
|||||||
anchors.leftMargin: 12
|
anchors.leftMargin: 12
|
||||||
anchors.rightMargin: 0
|
anchors.rightMargin: 0
|
||||||
font.family: MoneroComponents.Style.fontRegular.name
|
font.family: MoneroComponents.Style.fontRegular.name
|
||||||
font.bold: true
|
font.bold: false
|
||||||
font.pixelSize: fontItemSize
|
font.pixelSize: fontItemSize
|
||||||
color: itemArea.containsMouse || index === columnid.currentIndex || itemArea.containsMouse ? "#FA6800" : "#FFFFFF"
|
color: itemArea.containsMouse || index === columnid.currentIndex || itemArea.containsMouse ? "#FA6800" : "#FFFFFF"
|
||||||
text: qsTr(column1) + translationManager.emptyString
|
text: qsTr(column1) + translationManager.emptyString
|
||||||
|
|||||||
@@ -42,11 +42,12 @@ QtObject {
|
|||||||
property string buttonBackgroundColorDisabled: blackTheme ? _b_buttonBackgroundColorDisabled : _w_buttonBackgroundColorDisabled
|
property string buttonBackgroundColorDisabled: blackTheme ? _b_buttonBackgroundColorDisabled : _w_buttonBackgroundColorDisabled
|
||||||
property string buttonBackgroundColorDisabledHover: blackTheme ? _b_buttonBackgroundColorDisabledHover : _w_buttonBackgroundColorDisabledHover
|
property string buttonBackgroundColorDisabledHover: blackTheme ? _b_buttonBackgroundColorDisabledHover : _w_buttonBackgroundColorDisabledHover
|
||||||
property string buttonInlineBackgroundColor: blackTheme ? _b_buttonInlineBackgroundColor : _w_buttonInlineBackgroundColor
|
property string buttonInlineBackgroundColor: blackTheme ? _b_buttonInlineBackgroundColor : _w_buttonInlineBackgroundColor
|
||||||
|
property string buttonInlineBackgroundColorHover: blackTheme ? _b_buttonInlineBackgroundColorHover : _w_buttonInlineBackgroundColorHover
|
||||||
property string buttonTextColor: blackTheme ? _b_buttonTextColor : _w_buttonTextColor
|
property string buttonTextColor: blackTheme ? _b_buttonTextColor : _w_buttonTextColor
|
||||||
property string buttonTextColorDisabled: blackTheme ? _b_buttonTextColorDisabled : _w_buttonTextColorDisabled
|
property string buttonTextColorDisabled: blackTheme ? _b_buttonTextColorDisabled : _w_buttonTextColorDisabled
|
||||||
property string buttonSecondaryBackgroundColor: "#d9d9d9"
|
property string buttonSecondaryBackgroundColor: blackTheme ? _b_buttonSecondaryBackgroundColor : _w_buttonSecondaryBackgroundColor
|
||||||
property string buttonSecondaryBackgroundColorHover: "#a6a6a6"
|
property string buttonSecondaryBackgroundColorHover: blackTheme ? _b_buttonSecondaryBackgroundColorHover : _w_buttonSecondaryBackgroundColorHover
|
||||||
property string buttonSecondaryTextColor: "#4d4d4d"
|
property string buttonSecondaryTextColor: blackTheme ? _b_buttonSecondaryTextColor : _w_buttonSecondaryTextColor
|
||||||
property string dividerColor: blackTheme ? _b_dividerColor : _w_dividerColor
|
property string dividerColor: blackTheme ? _b_dividerColor : _w_dividerColor
|
||||||
property real dividerOpacity: blackTheme ? _b_dividerOpacity : _w_dividerOpacity
|
property real dividerOpacity: blackTheme ? _b_dividerOpacity : _w_dividerOpacity
|
||||||
|
|
||||||
@@ -102,8 +103,12 @@ QtObject {
|
|||||||
property string _b_buttonBackgroundColorDisabled: "#707070"
|
property string _b_buttonBackgroundColorDisabled: "#707070"
|
||||||
property string _b_buttonBackgroundColorDisabledHover: "#808080"
|
property string _b_buttonBackgroundColorDisabledHover: "#808080"
|
||||||
property string _b_buttonInlineBackgroundColor: "#707070"
|
property string _b_buttonInlineBackgroundColor: "#707070"
|
||||||
|
property string _b_buttonInlineBackgroundColorHover: "#808080"
|
||||||
property string _b_buttonTextColor: "white"
|
property string _b_buttonTextColor: "white"
|
||||||
property string _b_buttonTextColorDisabled: "black"
|
property string _b_buttonTextColorDisabled: "black"
|
||||||
|
property string _b_buttonSecondaryBackgroundColor: "#707070"
|
||||||
|
property string _b_buttonSecondaryBackgroundColorHover: "#808080"
|
||||||
|
property string _b_buttonSecondaryTextColor: "white"
|
||||||
property string _b_dividerColor: "white"
|
property string _b_dividerColor: "white"
|
||||||
property real _b_dividerOpacity: 0.20
|
property real _b_dividerOpacity: 0.20
|
||||||
|
|
||||||
@@ -158,9 +163,13 @@ QtObject {
|
|||||||
property string _w_buttonBackgroundColorHover: "#E65E00"
|
property string _w_buttonBackgroundColorHover: "#E65E00"
|
||||||
property string _w_buttonBackgroundColorDisabled: "#bbbbbb"
|
property string _w_buttonBackgroundColorDisabled: "#bbbbbb"
|
||||||
property string _w_buttonBackgroundColorDisabledHover: "#D1D1D1"
|
property string _w_buttonBackgroundColorDisabledHover: "#D1D1D1"
|
||||||
property string _w_buttonInlineBackgroundColor: "#bbbbbb"
|
property string _w_buttonInlineBackgroundColor: "#d9d9d9"
|
||||||
|
property string _w_buttonInlineBackgroundColorHover: "#C8C8C8"
|
||||||
property string _w_buttonTextColor: "white"
|
property string _w_buttonTextColor: "white"
|
||||||
property string _w_buttonTextColorDisabled: "black"
|
property string _w_buttonTextColorDisabled: "black"
|
||||||
|
property string _w_buttonSecondaryBackgroundColor: "#d9d9d9"
|
||||||
|
property string _w_buttonSecondaryBackgroundColorHover: "#C8C8C8"
|
||||||
|
property string _w_buttonSecondaryTextColor: "#4d4d4d"
|
||||||
property string _w_dividerColor: "black"
|
property string _w_dividerColor: "black"
|
||||||
property real _w_dividerOpacity: 0.20
|
property real _w_dividerOpacity: 0.20
|
||||||
|
|
||||||
@@ -185,7 +194,7 @@ QtObject {
|
|||||||
property string _w_menuButtonImageRightColorActive: "#FA6800"
|
property string _w_menuButtonImageRightColorActive: "#FA6800"
|
||||||
property string _w_menuButtonImageRightColor: "#808080"
|
property string _w_menuButtonImageRightColor: "#808080"
|
||||||
property string _w_menuButtonImageDotArrowSource: "qrc:///images/arrow-right-medium-white.png"
|
property string _w_menuButtonImageDotArrowSource: "qrc:///images/arrow-right-medium-white.png"
|
||||||
property string _w_inlineButtonTextColor: "black"
|
property string _w_inlineButtonTextColor: "#4d4d4d"
|
||||||
property string _w_inlineButtonBorderColor: "transparent"
|
property string _w_inlineButtonBorderColor: "transparent"
|
||||||
property string _w_appWindowBackgroundColor: "black"
|
property string _w_appWindowBackgroundColor: "black"
|
||||||
property string _w_appWindowBorderColor: "#dedede"
|
property string _w_appWindowBorderColor: "#dedede"
|
||||||
|
|||||||
@@ -57,17 +57,20 @@ Rectangle {
|
|||||||
signal minimizeClicked
|
signal minimizeClicked
|
||||||
signal languageClicked
|
signal languageClicked
|
||||||
signal closeWalletClicked
|
signal closeWalletClicked
|
||||||
|
signal lockWalletClicked
|
||||||
|
|
||||||
state: "default"
|
state: "default"
|
||||||
states: [
|
states: [
|
||||||
State {
|
State {
|
||||||
name: "default";
|
name: "default";
|
||||||
PropertyChanges { target: btnCloseWallet; visible: true}
|
PropertyChanges { target: btnCloseWallet; visible: true}
|
||||||
|
PropertyChanges { target: btnLockWallet; visible: true}
|
||||||
PropertyChanges { target: btnLanguageToggle; visible: true}
|
PropertyChanges { target: btnLanguageToggle; visible: true}
|
||||||
}, State {
|
}, State {
|
||||||
// show only theme switcher and window controls
|
// show only theme switcher and window controls
|
||||||
name: "essentials";
|
name: "essentials";
|
||||||
PropertyChanges { target: btnCloseWallet; visible: false}
|
PropertyChanges { target: btnCloseWallet; visible: false}
|
||||||
|
PropertyChanges { target: btnLockWallet; visible: false}
|
||||||
PropertyChanges { target: btnLanguageToggle; visible: false}
|
PropertyChanges { target: btnLanguageToggle; visible: false}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -91,6 +94,46 @@ Rectangle {
|
|||||||
spacing: 0
|
spacing: 0
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|
||||||
|
// lock wallet
|
||||||
|
Rectangle {
|
||||||
|
id: btnLockWallet
|
||||||
|
color: "transparent"
|
||||||
|
Layout.preferredWidth: parent.height
|
||||||
|
Layout.preferredHeight: parent.height
|
||||||
|
|
||||||
|
Text {
|
||||||
|
text: FontAwesome.lock
|
||||||
|
font.family: FontAwesome.fontFamilySolid
|
||||||
|
font.pixelSize: 16
|
||||||
|
color: MoneroComponents.Style.defaultFontColor
|
||||||
|
font.styleName: "Solid"
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
opacity: 0.75
|
||||||
|
}
|
||||||
|
|
||||||
|
MoneroComponents.Tooltip {
|
||||||
|
id: btnLockWalletTooltip
|
||||||
|
anchors.fill: parent
|
||||||
|
text: qsTr("Lock this wallet") + translationManager.emptyString
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
onEntered: {
|
||||||
|
parent.color = MoneroComponents.Style.titleBarButtonHoverColor
|
||||||
|
btnLockWalletTooltip.tooltipPopup.open()
|
||||||
|
}
|
||||||
|
onExited: {
|
||||||
|
parent.color = "transparent"
|
||||||
|
btnLockWalletTooltip.tooltipPopup.close()
|
||||||
|
}
|
||||||
|
onClicked: root.lockWalletClicked(leftPanel.visible)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// collapse sidebar
|
// collapse sidebar
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: btnCloseWallet
|
id: btnCloseWallet
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ Rectangle {
|
|||||||
Text {
|
Text {
|
||||||
id: icon
|
id: icon
|
||||||
visible: tooltipIconVisible
|
visible: tooltipIconVisible
|
||||||
color: MoneroComponents.Style.orange
|
color: MoneroComponents.Style.defaultFontColor
|
||||||
font.family: FontAwesome.fontFamily
|
font.family: FontAwesome.fontFamily
|
||||||
font.pixelSize: 10
|
font.pixelSize: 10
|
||||||
font.styleName: "Regular"
|
font.styleName: "Regular"
|
||||||
@@ -95,11 +95,12 @@ Rectangle {
|
|||||||
delay: 200
|
delay: 200
|
||||||
|
|
||||||
RowLayout {
|
RowLayout {
|
||||||
Layout.maximumWidth: 350
|
Layout.maximumWidth: 370
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
id: tooltip
|
id: tooltip
|
||||||
width: contentWidth
|
width: contentWidth
|
||||||
|
Layout.maximumWidth: 370
|
||||||
color: MoneroComponents.Style.defaultFontColor
|
color: MoneroComponents.Style.defaultFontColor
|
||||||
font.family: MoneroComponents.Style.fontRegular.name
|
font.family: MoneroComponents.Style.fontRegular.name
|
||||||
font.pixelSize: 12
|
font.pixelSize: 12
|
||||||
|
|||||||
@@ -338,8 +338,9 @@ Rectangle {
|
|||||||
spacing: 16
|
spacing: 16
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
color: MoneroComponents.Style.defaultFontColor
|
property bool maliciousTxFee: parseFloat(root.transactionFee) > 0.01
|
||||||
font.pixelSize: 15
|
color: maliciousTxFee ? "red" : MoneroComponents.Style.defaultFontColor
|
||||||
|
font.pixelSize: maliciousTxFee ? 20 : 15
|
||||||
text: {
|
text: {
|
||||||
if (currentWallet) {
|
if (currentWallet) {
|
||||||
if (!root.transactionFee) {
|
if (!root.transactionFee) {
|
||||||
@@ -349,7 +350,7 @@ Rectangle {
|
|||||||
return qsTr("Calculating fee") + "..." + translationManager.emptyString;
|
return qsTr("Calculating fee") + "..." + translationManager.emptyString;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return root.transactionFee + " XMR"
|
return root.transactionFee + " XMR" + (maliciousTxFee ? " (HIGH FEE)" : "")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return "";
|
return "";
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ Object {
|
|||||||
property string arrowLeft : "\uf060"
|
property string arrowLeft : "\uf060"
|
||||||
property string arrowRight : "\uf061"
|
property string arrowRight : "\uf061"
|
||||||
property string cashRegister: "\uf788"
|
property string cashRegister: "\uf788"
|
||||||
|
property string checkCircle: "\uf058"
|
||||||
property string clipboard : "\uf0ea"
|
property string clipboard : "\uf0ea"
|
||||||
property string clockO : "\uf017"
|
property string clockO : "\uf017"
|
||||||
property string cloud : "\uf0c2"
|
property string cloud : "\uf0c2"
|
||||||
@@ -52,6 +53,7 @@ Object {
|
|||||||
property string info : "\uf129"
|
property string info : "\uf129"
|
||||||
property string key : "\uf084"
|
property string key : "\uf084"
|
||||||
property string language : "\uf1ab"
|
property string language : "\uf1ab"
|
||||||
|
property string lock : "\uf023"
|
||||||
property string minus : "\uf068"
|
property string minus : "\uf068"
|
||||||
property string minusCircle : "\uf056"
|
property string minusCircle : "\uf056"
|
||||||
property string moonO : "\uf186"
|
property string moonO : "\uf186"
|
||||||
|
|||||||
BIN
images/open-wallet-from-file-mainnet.png
Normal file
|
After Width: | Height: | Size: 640 B |
BIN
images/open-wallet-from-file-mainnet@2x.png
Normal file
|
After Width: | Height: | Size: 937 B |
BIN
images/open-wallet-from-file-stagenet.png
Normal file
|
After Width: | Height: | Size: 569 B |
BIN
images/open-wallet-from-file-stagenet@2x.png
Normal file
|
After Width: | Height: | Size: 717 B |
BIN
images/open-wallet-from-file-testnet.png
Normal file
|
After Width: | Height: | Size: 608 B |
BIN
images/open-wallet-from-file-testnet@2x.png
Normal file
|
After Width: | Height: | Size: 779 B |
BIN
images/open-wallet-from-file-trezor.png
Normal file
|
After Width: | Height: | Size: 969 B |
BIN
images/open-wallet-from-file-trezor@2x.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
images/open-wallet-from-file-view-only.png
Normal file
|
After Width: | Height: | Size: 958 B |
BIN
images/open-wallet-from-file-view-only@2x.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 742 B After Width: | Height: | Size: 424 B |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 678 B |
|
Before Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.6 KiB |
@@ -61,6 +61,10 @@ function checkSignature(signature) {
|
|||||||
if ((signature.length - 12) % 88 != 0)
|
if ((signature.length - 12) % 88 != 0)
|
||||||
return false;
|
return false;
|
||||||
return check256(signature, signature.length);
|
return check256(signature, signature.length);
|
||||||
|
} else if (signature.indexOf("ReserveProofV") === 0) {
|
||||||
|
if ((signature.length - 14) % 447 != 0)
|
||||||
|
return false;
|
||||||
|
return check256(signature, signature.length);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -73,30 +77,3 @@ function isValidOpenAliasAddress(address) {
|
|||||||
// we can get an awful lot of valid domains, including non ASCII chars... accept anything
|
// we can get an awful lot of valid domains, including non ASCII chars... accept anything
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
function makeQRCodeString(addr, amount, txDescription, recipientName) {
|
|
||||||
var XMR_URI_SCHEME = "monero:"
|
|
||||||
var XMR_AMOUNT = "tx_amount"
|
|
||||||
var XMR_RECIPIENT_NAME = "recipient_name"
|
|
||||||
var XMR_TX_DESCRIPTION = "tx_description"
|
|
||||||
var qrCodeString =""
|
|
||||||
qrCodeString += (XMR_URI_SCHEME + addr)
|
|
||||||
if (amount !== undefined && amount !== ""){
|
|
||||||
qrCodeString += ("?" + XMR_AMOUNT + "=" + amount)
|
|
||||||
}
|
|
||||||
if (txDescription !== undefined && txDescription !== ""){
|
|
||||||
if (amount == ""){
|
|
||||||
qrCodeString += ("?" + XMR_TX_DESCRIPTION + "=" + encodeURI(txDescription))
|
|
||||||
} else {
|
|
||||||
qrCodeString += ("&" + XMR_TX_DESCRIPTION + "=" + encodeURI(txDescription))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (recipientName !== undefined && recipientName !== ""){
|
|
||||||
if (amount == "" && txDescription == ""){
|
|
||||||
qrCodeString += ("?" + XMR_RECIPIENT_NAME + "=" + encodeURI(recipientName))
|
|
||||||
} else {
|
|
||||||
qrCodeString += ("&" + XMR_RECIPIENT_NAME + "=" + encodeURI(recipientName))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return qrCodeString
|
|
||||||
}
|
|
||||||
|
|||||||
BIN
lang/flags/el.png
Normal file
|
After Width: | Height: | Size: 8.8 KiB |
BIN
lang/flags/is.png
Normal file
|
After Width: | Height: | Size: 7.9 KiB |
BIN
lang/flags/vi.png
Normal file
|
After Width: | Height: | Size: 9.1 KiB |
@@ -61,4 +61,9 @@ Lojban
|
|||||||
<!-- <language display_name="کورمانجی" locale="kmr_KMR" wallet_language="English" flag="/lang/flags/ku.png" qs="none"/> -->
|
<!-- <language display_name="کورمانجی" locale="kmr_KMR" wallet_language="English" flag="/lang/flags/ku.png" qs="none"/> -->
|
||||||
<!-- <language display_name="বাংলা" locale="bn_BN" wallet_language="English" flag="/lang/flags/bd.png" qs="none"/> -->
|
<!-- <language display_name="বাংলা" locale="bn_BN" wallet_language="English" flag="/lang/flags/bd.png" qs="none"/> -->
|
||||||
<!-- <language display_name="Gaeilge" locale="ga_GA" wallet_language="English" flag="/lang/flags/irl.png" qs="none"/> -->
|
<!-- <language display_name="Gaeilge" locale="ga_GA" wallet_language="English" flag="/lang/flags/irl.png" qs="none"/> -->
|
||||||
|
<language display_name="Afrikaans" locale="af_AF" wallet_language="English" flag="/lang/flags/za.png" qs="none"/>
|
||||||
|
<language display_name="Ελληνικά" locale="el_GR" wallet_language="English" flag="/lang/flags/el.png" qs="none"/>
|
||||||
|
<language display_name="தமிழ்" locale="ta_IN" wallet_language="English" flag="/lang/flags/in.png" qs="none"/>
|
||||||
|
<language display_name="Tiếng Việt" locale="vi_VN" wallet_language="English" flag="/lang/flags/vi.png" qs="none"/>
|
||||||
|
<language display_name="Íslenska" locale="is_IS" wallet_language="English" flag="/lang/flags/is.png" qs="none"/>
|
||||||
</languages>
|
</languages>
|
||||||
|
|||||||
120
main.qml
@@ -42,6 +42,7 @@ import moneroComponents.WalletManager 1.0
|
|||||||
import moneroComponents.PendingTransaction 1.0
|
import moneroComponents.PendingTransaction 1.0
|
||||||
import moneroComponents.NetworkType 1.0
|
import moneroComponents.NetworkType 1.0
|
||||||
import moneroComponents.Settings 1.0
|
import moneroComponents.Settings 1.0
|
||||||
|
import moneroComponents.P2PoolManager 1.0
|
||||||
|
|
||||||
import "components"
|
import "components"
|
||||||
import "components" as MoneroComponents
|
import "components" as MoneroComponents
|
||||||
@@ -131,6 +132,17 @@ ApplicationWindow {
|
|||||||
leftPanel.selectItem(page)
|
leftPanel.selectItem(page)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function lock() {
|
||||||
|
passwordDialog.onRejectedCallback = function() { appWindow.showWizard(); }
|
||||||
|
passwordDialog.onAcceptedCallback = function() {
|
||||||
|
if(walletPassword === passwordDialog.password)
|
||||||
|
passwordDialog.close();
|
||||||
|
else
|
||||||
|
passwordDialog.showError(qsTr("Wrong password") + translationManager.emptyString);
|
||||||
|
}
|
||||||
|
passwordDialog.open(usefulName(persistentSettings.wallet_path));
|
||||||
|
}
|
||||||
|
|
||||||
function sequencePressed(obj, seq) {
|
function sequencePressed(obj, seq) {
|
||||||
if(seq === undefined || !leftPanel.enabled)
|
if(seq === undefined || !leftPanel.enabled)
|
||||||
return
|
return
|
||||||
@@ -139,6 +151,8 @@ ApplicationWindow {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// lock wallet on demand
|
||||||
|
if(seq === "Ctrl+L" && !passwordDialog.visible) lock()
|
||||||
if(seq === "Ctrl+S") middlePanel.state = "Transfer"
|
if(seq === "Ctrl+S") middlePanel.state = "Transfer"
|
||||||
else if(seq === "Ctrl+R") middlePanel.state = "Receive"
|
else if(seq === "Ctrl+R") middlePanel.state = "Receive"
|
||||||
else if(seq === "Ctrl+H") middlePanel.state = "History"
|
else if(seq === "Ctrl+H") middlePanel.state = "History"
|
||||||
@@ -259,9 +273,6 @@ ApplicationWindow {
|
|||||||
walletPassword,
|
walletPassword,
|
||||||
persistentSettings.nettype,
|
persistentSettings.nettype,
|
||||||
persistentSettings.kdfRounds);
|
persistentSettings.kdfRounds);
|
||||||
|
|
||||||
// Hide titlebar based on persistentSettings.customDecorations
|
|
||||||
titleBar.visible = persistentSettings.customDecorations;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function closeWallet(callback) {
|
function closeWallet(callback) {
|
||||||
@@ -721,6 +732,7 @@ ApplicationWindow {
|
|||||||
if (splash) {
|
if (splash) {
|
||||||
appWindow.showProcessingSplash(qsTr("Waiting for daemon to stop..."));
|
appWindow.showProcessingSplash(qsTr("Waiting for daemon to stop..."));
|
||||||
}
|
}
|
||||||
|
p2poolManager.exit()
|
||||||
daemonManager.stopAsync(persistentSettings.nettype, function(result) {
|
daemonManager.stopAsync(persistentSettings.nettype, function(result) {
|
||||||
daemonStartStopInProgress = 0;
|
daemonStartStopInProgress = 0;
|
||||||
if (splash) {
|
if (splash) {
|
||||||
@@ -733,14 +745,18 @@ ApplicationWindow {
|
|||||||
function onDaemonStarted(){
|
function onDaemonStarted(){
|
||||||
console.log("daemon started");
|
console.log("daemon started");
|
||||||
daemonStartStopInProgress = 0;
|
daemonStartStopInProgress = 0;
|
||||||
currentWallet.connected(true);
|
if (currentWallet) {
|
||||||
// resume refresh
|
currentWallet.connected(true);
|
||||||
currentWallet.startRefresh();
|
// resume refresh
|
||||||
|
currentWallet.startRefresh();
|
||||||
|
}
|
||||||
// resume simplemode connection timer
|
// resume simplemode connection timer
|
||||||
appWindow.disconnectedEpoch = Utils.epoch();
|
appWindow.disconnectedEpoch = Utils.epoch();
|
||||||
}
|
}
|
||||||
function onDaemonStopped(){
|
function onDaemonStopped(){
|
||||||
currentWallet.connected(true);
|
if (currentWallet) {
|
||||||
|
currentWallet.connected(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function onDaemonStartFailure(error) {
|
function onDaemonStartFailure(error) {
|
||||||
@@ -984,24 +1000,28 @@ ApplicationWindow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// called on "getProof"
|
// called on "getProof"
|
||||||
function handleGetProof(txid, address, message) {
|
function handleGetProof(txid, address, message, amount) {
|
||||||
console.log("Getting payment proof: ")
|
if (amount.length > 0) {
|
||||||
console.log("\ttxid: ", txid,
|
var result = currentWallet.getReserveProof(false, currentWallet.currentSubaddressAccount, walletManager.amountFromString(amount), message)
|
||||||
", address: ", address,
|
txProofComputed(null, result)
|
||||||
", message: ", message);
|
} else {
|
||||||
|
console.log("Getting payment proof: ")
|
||||||
function spendProofFallback(txid, result){
|
console.log("\ttxid: ", txid,
|
||||||
if (!result || result.indexOf("error|") === 0) {
|
", address: ", address,
|
||||||
currentWallet.getSpendProofAsync(txid, message, txProofComputed);
|
", message: ", message);
|
||||||
} else {
|
function spendProofFallback(txid, result){
|
||||||
txProofComputed(txid, result);
|
if (!result || result.indexOf("error|") === 0) {
|
||||||
|
currentWallet.getSpendProofAsync(txid, message, txProofComputed);
|
||||||
|
} else {
|
||||||
|
txProofComputed(txid, result);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if (address.length > 0)
|
||||||
|
currentWallet.getTxProofAsync(txid, address, message, spendProofFallback);
|
||||||
|
else
|
||||||
|
spendProofFallback(txid, null);
|
||||||
}
|
}
|
||||||
|
informationPopup.open()
|
||||||
if (address.length > 0)
|
|
||||||
currentWallet.getTxProofAsync(txid, address, message, spendProofFallback);
|
|
||||||
else
|
|
||||||
spendProofFallback(txid, null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function txProofComputed(txid, result){
|
function txProofComputed(txid, result){
|
||||||
@@ -1024,12 +1044,18 @@ ApplicationWindow {
|
|||||||
", signature: ", signature);
|
", signature: ", signature);
|
||||||
|
|
||||||
var result;
|
var result;
|
||||||
if (address.length > 0)
|
var isReserveProof = signature.indexOf("ReserveProofV") === 0;
|
||||||
|
if (address.length > 0 && !isReserveProof) {
|
||||||
result = currentWallet.checkTxProof(txid, address, message, signature);
|
result = currentWallet.checkTxProof(txid, address, message, signature);
|
||||||
else
|
}
|
||||||
|
else if (isReserveProof) {
|
||||||
|
result = currentWallet.checkReserveProof(address, message, signature);
|
||||||
|
}
|
||||||
|
else {
|
||||||
result = currentWallet.checkSpendProof(txid, message, signature);
|
result = currentWallet.checkSpendProof(txid, message, signature);
|
||||||
|
}
|
||||||
var results = result.split("|");
|
var results = result.split("|");
|
||||||
if (address.length > 0 && results.length == 5 && results[0] === "true") {
|
if (address.length > 0 && results.length == 5 && results[0] === "true" && !isReserveProof) {
|
||||||
var good = results[1] === "true";
|
var good = results[1] === "true";
|
||||||
var received = results[2];
|
var received = results[2];
|
||||||
var in_pool = results[3] === "true";
|
var in_pool = results[3] === "true";
|
||||||
@@ -1057,6 +1083,12 @@ ApplicationWindow {
|
|||||||
informationPopup.title = qsTr("Payment proof check") + translationManager.emptyString;
|
informationPopup.title = qsTr("Payment proof check") + translationManager.emptyString;
|
||||||
informationPopup.icon = good ? StandardIcon.Information : StandardIcon.Critical;
|
informationPopup.icon = good ? StandardIcon.Information : StandardIcon.Critical;
|
||||||
informationPopup.text = good ? qsTr("Good signature") : qsTr("Bad signature");
|
informationPopup.text = good ? qsTr("Good signature") : qsTr("Bad signature");
|
||||||
|
}
|
||||||
|
else if (isReserveProof && results[0] === "true") {
|
||||||
|
var good = results[1] === "true";
|
||||||
|
informationPopup.title = qsTr("Reserve proof check") + translationManager.emptyString;
|
||||||
|
informationPopup.icon = good ? StandardIcon.Information : StandardIcon.Critical;
|
||||||
|
informationPopup.text = good ? qsTr("Good signature on %1 total and %2 spent.").arg(results[2]).arg(results[3]) : qsTr("Bad signature");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
informationPopup.title = qsTr("Error") + translationManager.emptyString;
|
informationPopup.title = qsTr("Error") + translationManager.emptyString;
|
||||||
@@ -1124,13 +1156,10 @@ ApplicationWindow {
|
|||||||
Timer {
|
Timer {
|
||||||
id: fiatPriceTimer
|
id: fiatPriceTimer
|
||||||
interval: 1000 * 60;
|
interval: 1000 * 60;
|
||||||
running: persistentSettings.fiatPriceEnabled;
|
running: persistentSettings.fiatPriceEnabled && currentWallet !== undefined
|
||||||
repeat: true
|
repeat: true
|
||||||
onTriggered: {
|
onTriggered: appWindow.fiatApiRefresh()
|
||||||
if(persistentSettings.fiatPriceEnabled)
|
triggeredOnStart: true
|
||||||
appWindow.fiatApiRefresh();
|
|
||||||
}
|
|
||||||
triggeredOnStart: false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function fiatApiParseTicker(url, resp, currency){
|
function fiatApiParseTicker(url, resp, currency){
|
||||||
@@ -1269,14 +1298,6 @@ ApplicationWindow {
|
|||||||
leftPanel.balanceFiatString = bFiat;
|
leftPanel.balanceFiatString = bFiat;
|
||||||
}
|
}
|
||||||
|
|
||||||
function fiatTimerStart(){
|
|
||||||
fiatPriceTimer.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
function fiatTimerStop(){
|
|
||||||
fiatPriceTimer.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
function fiatApiError(msg){
|
function fiatApiError(msg){
|
||||||
console.log("fiatPriceError: " + msg);
|
console.log("fiatPriceError: " + msg);
|
||||||
}
|
}
|
||||||
@@ -1332,12 +1353,8 @@ ApplicationWindow {
|
|||||||
openWallet("wizard");
|
openWallet("wizard");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(persistentSettings.fiatPriceEnabled){
|
const desktopEntryEnabled = (typeof builtWithDesktopEntry != "undefined") && builtWithDesktopEntry;
|
||||||
appWindow.fiatApiRefresh();
|
if (persistentSettings.askDesktopShortcut && !persistentSettings.portable && desktopEntryEnabled) {
|
||||||
appWindow.fiatTimerStart();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (persistentSettings.askDesktopShortcut && !persistentSettings.portable) {
|
|
||||||
persistentSettings.askDesktopShortcut = false;
|
persistentSettings.askDesktopShortcut = false;
|
||||||
|
|
||||||
if (isTails) {
|
if (isTails) {
|
||||||
@@ -1374,6 +1391,8 @@ ApplicationWindow {
|
|||||||
property string account_name
|
property string account_name
|
||||||
property string wallet_path
|
property string wallet_path
|
||||||
property bool allow_background_mining : false
|
property bool allow_background_mining : false
|
||||||
|
property bool allow_p2pool_mining : false
|
||||||
|
property bool allowRemoteNodeMining : false
|
||||||
property bool miningIgnoreBattery : true
|
property bool miningIgnoreBattery : true
|
||||||
property var nettype: NetworkType.MAINNET
|
property var nettype: NetworkType.MAINNET
|
||||||
property int restore_height : 0
|
property int restore_height : 0
|
||||||
@@ -1382,6 +1401,7 @@ ApplicationWindow {
|
|||||||
property bool is_recovering_from_device : false
|
property bool is_recovering_from_device : false
|
||||||
property bool customDecorations : true
|
property bool customDecorations : true
|
||||||
property string daemonFlags
|
property string daemonFlags
|
||||||
|
property string p2poolFlags
|
||||||
property int logLevel: 0
|
property int logLevel: 0
|
||||||
property string logCategories: ""
|
property string logCategories: ""
|
||||||
property string daemonUsername: "" // TODO: drop after v0.17.2.0 release
|
property string daemonUsername: "" // TODO: drop after v0.17.2.0 release
|
||||||
@@ -1691,6 +1711,9 @@ ApplicationWindow {
|
|||||||
informationPopup.open();
|
informationPopup.open();
|
||||||
}
|
}
|
||||||
onRejectedNewPassword: {}
|
onRejectedNewPassword: {}
|
||||||
|
Keys.enabled: !passwordDialog.visible && informationPopup.visible
|
||||||
|
Keys.onEnterPressed: informationPopup.close()
|
||||||
|
Keys.onReturnPressed: informationPopup.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
DevicePassphraseDialog {
|
DevicePassphraseDialog {
|
||||||
@@ -1898,10 +1921,11 @@ ApplicationWindow {
|
|||||||
TitleBar {
|
TitleBar {
|
||||||
id: titleBar
|
id: titleBar
|
||||||
visible: persistentSettings.customDecorations && middlePanel.state !== "Merchant"
|
visible: persistentSettings.customDecorations && middlePanel.state !== "Merchant"
|
||||||
walletName: persistentSettings.displayWalletNameInTitleBar ? appWindow.walletName : ""
|
walletName: persistentSettings.displayWalletNameInTitleBar && rootItem.state != "wizard" ? appWindow.walletName : ""
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
onCloseClicked: appWindow.close();
|
onCloseClicked: appWindow.close();
|
||||||
|
onLockWalletClicked: appWindow.lock();
|
||||||
onLanguageClicked: appWindow.toggleLanguageView();
|
onLanguageClicked: appWindow.toggleLanguageView();
|
||||||
onCloseWalletClicked: appWindow.showWizard();
|
onCloseWalletClicked: appWindow.showWizard();
|
||||||
onMaximizeClicked: appWindow.visibility = appWindow.visibility !== Window.Maximized ? Window.Maximized : Window.Windowed
|
onMaximizeClicked: appWindow.visibility = appWindow.visibility !== Window.Maximized ? Window.Maximized : Window.Windowed
|
||||||
@@ -2142,7 +2166,7 @@ ApplicationWindow {
|
|||||||
console.log("close accepted");
|
console.log("close accepted");
|
||||||
// Close wallet non async on exit
|
// Close wallet non async on exit
|
||||||
daemonManager.exit();
|
daemonManager.exit();
|
||||||
|
p2poolManager.exit();
|
||||||
closeWallet(Qt.quit);
|
closeWallet(Qt.quit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
2
monero
@@ -164,11 +164,48 @@ Rectangle {
|
|||||||
id: addressRow
|
id: addressRow
|
||||||
spacing: 0
|
spacing: 0
|
||||||
|
|
||||||
MoneroComponents.LabelSubheader {
|
RowLayout {
|
||||||
Layout.fillWidth: true
|
spacing: 0
|
||||||
fontSize: 24
|
|
||||||
textFormat: Text.RichText
|
MoneroComponents.LabelSubheader {
|
||||||
text: qsTr("Accounts") + translationManager.emptyString
|
Layout.fillWidth: true
|
||||||
|
fontSize: 24
|
||||||
|
textFormat: Text.RichText
|
||||||
|
text: qsTr("Accounts") + translationManager.emptyString
|
||||||
|
}
|
||||||
|
|
||||||
|
MoneroComponents.StandardButton {
|
||||||
|
id: createNewAccountButton
|
||||||
|
visible: !selectAndSend
|
||||||
|
small: true
|
||||||
|
text: qsTr("Create new account") + translationManager.emptyString
|
||||||
|
fontSize: 13
|
||||||
|
onClicked: {
|
||||||
|
inputDialog.labelText = qsTr("Set the label of the new account:") + translationManager.emptyString
|
||||||
|
inputDialog.onAcceptedCallback = function() {
|
||||||
|
appWindow.currentWallet.subaddressAccount.addRow(inputDialog.inputText)
|
||||||
|
appWindow.currentWallet.switchSubaddressAccount(appWindow.currentWallet.numSubaddressAccounts() - 1)
|
||||||
|
appWindow.onWalletUpdate();
|
||||||
|
}
|
||||||
|
inputDialog.onRejectedCallback = null;
|
||||||
|
inputDialog.open()
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
anchors.top: createNewAccountButton.bottom
|
||||||
|
anchors.topMargin: 8
|
||||||
|
anchors.left: createNewAccountButton.left
|
||||||
|
anchors.right: createNewAccountButton.right
|
||||||
|
height: 2
|
||||||
|
color: MoneroComponents.Style.appWindowBorderColor
|
||||||
|
|
||||||
|
MoneroEffects.ColorTransition {
|
||||||
|
targetObj: parent
|
||||||
|
blackColor: MoneroComponents.Style._b_appWindowBorderColor
|
||||||
|
whiteColor: MoneroComponents.Style._w_appWindowBorderColor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
@@ -349,30 +386,6 @@ Rectangle {
|
|||||||
whiteColor: MoneroComponents.Style._w_appWindowBorderColor
|
whiteColor: MoneroComponents.Style._w_appWindowBorderColor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MoneroComponents.CheckBox {
|
|
||||||
id: addNewAccountCheckbox
|
|
||||||
visible: !selectAndSend
|
|
||||||
border: false
|
|
||||||
uncheckedIcon: FontAwesome.plusCircle
|
|
||||||
toggleOnClick: false
|
|
||||||
fontAwesomeIcons: true
|
|
||||||
fontSize: 16
|
|
||||||
iconOnTheLeft: true
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: 10
|
|
||||||
text: qsTr("Create new account") + translationManager.emptyString;
|
|
||||||
onClicked: {
|
|
||||||
inputDialog.labelText = qsTr("Set the label of the new account:") + translationManager.emptyString
|
|
||||||
inputDialog.onAcceptedCallback = function() {
|
|
||||||
appWindow.currentWallet.subaddressAccount.addRow(inputDialog.inputText)
|
|
||||||
appWindow.currentWallet.switchSubaddressAccount(appWindow.currentWallet.numSubaddressAccounts() - 1)
|
|
||||||
appWindow.onWalletUpdate();
|
|
||||||
}
|
|
||||||
inputDialog.onRejectedCallback = null;
|
|
||||||
inputDialog.open()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -97,6 +97,8 @@ Rectangle {
|
|||||||
MoneroComponents.StandardButton {
|
MoneroComponents.StandardButton {
|
||||||
id: addFirstEntryButton
|
id: addFirstEntryButton
|
||||||
Layout.topMargin: 20
|
Layout.topMargin: 20
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
small: true
|
||||||
text: qsTr("Add an address") + translationManager.emptyString
|
text: qsTr("Add an address") + translationManager.emptyString
|
||||||
onClicked: {
|
onClicked: {
|
||||||
root.showAddAddress();
|
root.showAddAddress();
|
||||||
@@ -115,6 +117,18 @@ Rectangle {
|
|||||||
text: qsTr("Address book") + translationManager.emptyString
|
text: qsTr("Address book") + translationManager.emptyString
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MoneroComponents.StandardButton {
|
||||||
|
id: addAddressButton
|
||||||
|
Layout.bottomMargin: 8
|
||||||
|
Layout.alignment: Qt.AlignRight
|
||||||
|
small: true
|
||||||
|
text: qsTr("Add address") + translationManager.emptyString
|
||||||
|
fontSize: 13
|
||||||
|
onClicked: {
|
||||||
|
root.showAddAddress();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
id: addressBookListRow
|
id: addressBookListRow
|
||||||
property int addressBookListItemHeight: 50
|
property int addressBookListItemHeight: 50
|
||||||
@@ -235,7 +249,7 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
MoneroComponents.IconButton {
|
MoneroComponents.IconButton {
|
||||||
id: renameButton
|
id: editEntryButton
|
||||||
image: "qrc:///images/edit.svg"
|
image: "qrc:///images/edit.svg"
|
||||||
color: MoneroComponents.Style.defaultFontColor
|
color: MoneroComponents.Style.defaultFontColor
|
||||||
opacity: isOpenGL ? 0.5 : 1
|
opacity: isOpenGL ? 0.5 : 1
|
||||||
@@ -244,7 +258,7 @@ Rectangle {
|
|||||||
fontAwesomeFallbackOpacity: 0.5
|
fontAwesomeFallbackOpacity: 0.5
|
||||||
Layout.preferredWidth: 23
|
Layout.preferredWidth: 23
|
||||||
Layout.preferredHeight: 21
|
Layout.preferredHeight: 21
|
||||||
tooltip: qsTr("Edit address label") + translationManager.emptyString
|
tooltip: qsTr("Edit entry") + translationManager.emptyString
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
addressBookListView.currentIndex = index;
|
addressBookListView.currentIndex = index;
|
||||||
@@ -287,23 +301,6 @@ Rectangle {
|
|||||||
whiteColor: MoneroComponents.Style._w_appWindowBorderColor
|
whiteColor: MoneroComponents.Style._w_appWindowBorderColor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MoneroComponents.CheckBox {
|
|
||||||
id: addNewEntryCheckbox
|
|
||||||
border: false
|
|
||||||
uncheckedIcon: FontAwesome.plusCircle
|
|
||||||
toggleOnClick: false
|
|
||||||
fontAwesomeIcons: true
|
|
||||||
fontSize: 16
|
|
||||||
iconOnTheLeft: true
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: 10
|
|
||||||
text: qsTr("Add address") + translationManager.emptyString;
|
|
||||||
onClicked: {
|
|
||||||
root.showAddAddress();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
id: addContactLayout
|
id: addContactLayout
|
||||||
@@ -313,11 +310,12 @@ Rectangle {
|
|||||||
MoneroComponents.Label {
|
MoneroComponents.Label {
|
||||||
fontSize: 32
|
fontSize: 32
|
||||||
wrapMode: Text.WordWrap
|
wrapMode: Text.WordWrap
|
||||||
text: (root.editEntry ? qsTr("Edit an address") : qsTr("Add an address")) + translationManager.emptyString
|
text: (root.editEntry ? qsTr("Edit entry") : qsTr("Add an address")) + translationManager.emptyString
|
||||||
}
|
}
|
||||||
|
|
||||||
MoneroComponents.LineEditMulti {
|
MoneroComponents.LineEditMulti {
|
||||||
id: addressLine
|
id: addressLine
|
||||||
|
visible: !root.editEntry
|
||||||
Layout.topMargin: 20
|
Layout.topMargin: 20
|
||||||
KeyNavigation.backtab: deleteButton.visible ? deleteButton: cancelButton
|
KeyNavigation.backtab: deleteButton.visible ? deleteButton: cancelButton
|
||||||
KeyNavigation.tab: resolveButton.visible ? resolveButton : descriptionLine
|
KeyNavigation.tab: resolveButton.visible ? resolveButton : descriptionLine
|
||||||
@@ -325,16 +323,16 @@ Rectangle {
|
|||||||
.arg(qsTr("Address")) + translationManager.emptyString
|
.arg(qsTr("Address")) + translationManager.emptyString
|
||||||
placeholderText: {
|
placeholderText: {
|
||||||
if(persistentSettings.nettype == NetworkType.MAINNET){
|
if(persistentSettings.nettype == NetworkType.MAINNET){
|
||||||
return "4.. / 8.. / OpenAlias";
|
return "4.. / 8.. / monero:.. / OpenAlias";
|
||||||
} else if (persistentSettings.nettype == NetworkType.STAGENET){
|
} else if (persistentSettings.nettype == NetworkType.STAGENET){
|
||||||
return "5.. / 7..";
|
return "5.. / 7.. / monero:..";
|
||||||
} else if(persistentSettings.nettype == NetworkType.TESTNET){
|
} else if(persistentSettings.nettype == NetworkType.TESTNET){
|
||||||
return "9.. / B..";
|
return "9.. / B.. / monero:..";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
wrapMode: Text.WrapAnywhere
|
wrapMode: Text.WrapAnywhere
|
||||||
addressValidation: true
|
addressValidation: true
|
||||||
pasteButton: true
|
pasteButton: false
|
||||||
onTextChanged: {
|
onTextChanged: {
|
||||||
const parsed = walletManager.parse_uri_to_object(addressLine.text);
|
const parsed = walletManager.parse_uri_to_object(addressLine.text);
|
||||||
if (!parsed.error) {
|
if (!parsed.error) {
|
||||||
@@ -436,39 +434,13 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
RowLayout {
|
RowLayout {
|
||||||
Layout.topMargin: 20
|
Layout.topMargin: 20
|
||||||
MoneroComponents.StandardButton {
|
Layout.alignment: Qt.AlignRight
|
||||||
id: addButton
|
|
||||||
KeyNavigation.backtab: descriptionLine
|
|
||||||
KeyNavigation.tab: cancelButton
|
|
||||||
text: (root.editEntry ? qsTr("Save") : qsTr("Add")) + translationManager.emptyString
|
|
||||||
enabled: root.checkInformation(addressLine.text, appWindow.persistentSettings.nettype)
|
|
||||||
onClicked: {
|
|
||||||
console.log("Add")
|
|
||||||
if (!currentWallet.addressBook.addRow(addressLine.text.trim(),"", descriptionLine.text)) {
|
|
||||||
informationPopup.title = qsTr("Error") + translationManager.emptyString;
|
|
||||||
// TODO: check currentWallet.addressBook.errorString() instead.
|
|
||||||
if(currentWallet.addressBook.errorCode() === AddressBook.Invalid_Address)
|
|
||||||
informationPopup.text = qsTr("Invalid address") + translationManager.emptyString
|
|
||||||
else if(currentWallet.addressBook.errorCode() === AddressBook.Invalid_Payment_Id)
|
|
||||||
informationPopup.text = currentWallet.addressBook.errorString()
|
|
||||||
else
|
|
||||||
informationPopup.text = qsTr("Can't create entry") + translationManager.emptyString
|
|
||||||
|
|
||||||
informationPopup.onCloseCallback = null
|
|
||||||
informationPopup.open();
|
|
||||||
} else {
|
|
||||||
if (root.editEntry) {
|
|
||||||
currentWallet.addressBook.deleteRow(addressBookListView.currentIndex);
|
|
||||||
}
|
|
||||||
root.showAddressBook();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MoneroComponents.StandardButton {
|
MoneroComponents.StandardButton {
|
||||||
id: cancelButton
|
id: cancelButton
|
||||||
KeyNavigation.backtab: addButton
|
KeyNavigation.backtab: addButton
|
||||||
KeyNavigation.tab: deleteButton.visible ? deleteButton : addressLine
|
KeyNavigation.tab: deleteButton.visible ? deleteButton : addressLine
|
||||||
|
small: true
|
||||||
text: qsTr("Cancel") + translationManager.emptyString
|
text: qsTr("Cancel") + translationManager.emptyString
|
||||||
primary: false
|
primary: false
|
||||||
onClicked: root.showAddressBook();
|
onClicked: root.showAddressBook();
|
||||||
@@ -478,6 +450,7 @@ Rectangle {
|
|||||||
id: deleteButton
|
id: deleteButton
|
||||||
KeyNavigation.backtab: cancelButton
|
KeyNavigation.backtab: cancelButton
|
||||||
KeyNavigation.tab: addressLine
|
KeyNavigation.tab: addressLine
|
||||||
|
small: true
|
||||||
visible: root.editEntry
|
visible: root.editEntry
|
||||||
text: qsTr("Delete") + translationManager.emptyString
|
text: qsTr("Delete") + translationManager.emptyString
|
||||||
primary: false
|
primary: false
|
||||||
@@ -486,6 +459,38 @@ Rectangle {
|
|||||||
root.showAddressBook();
|
root.showAddressBook();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MoneroComponents.StandardButton {
|
||||||
|
id: addButton
|
||||||
|
KeyNavigation.backtab: descriptionLine
|
||||||
|
KeyNavigation.tab: cancelButton
|
||||||
|
small: true
|
||||||
|
text: (root.editEntry ? qsTr("Save") : qsTr("Add")) + translationManager.emptyString
|
||||||
|
enabled: root.checkInformation(addressLine.text, appWindow.persistentSettings.nettype)
|
||||||
|
onClicked: {
|
||||||
|
if (!root.editEntry) {
|
||||||
|
if (currentWallet.addressBook.addRow(addressLine.text.trim(),"", descriptionLine.text)) {
|
||||||
|
console.log("Entry added")
|
||||||
|
} else {
|
||||||
|
informationPopup.title = qsTr("Error") + translationManager.emptyString;
|
||||||
|
// TODO: check currentWallet.addressBook.errorString() instead.
|
||||||
|
if (currentWallet.addressBook.errorCode() === AddressBook.Invalid_Address)
|
||||||
|
informationPopup.text = qsTr("Invalid address") + translationManager.emptyString
|
||||||
|
else if (currentWallet.addressBook.errorCode() === AddressBook.Invalid_Payment_Id)
|
||||||
|
informationPopup.text = currentWallet.addressBook.errorString()
|
||||||
|
else
|
||||||
|
informationPopup.text = qsTr("Can't create entry") + translationManager.emptyString
|
||||||
|
|
||||||
|
informationPopup.onCloseCallback = null
|
||||||
|
informationPopup.open();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
currentWallet.addressBook.setDescription(addressBookListView.currentIndex, descriptionLine.text);
|
||||||
|
console.log("Description edited")
|
||||||
|
}
|
||||||
|
root.showAddressBook()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ ColumnLayout {
|
|||||||
property alias state: stateView.state
|
property alias state: stateView.state
|
||||||
|
|
||||||
MoneroComponents.Navbar {
|
MoneroComponents.Navbar {
|
||||||
|
id: navbarId
|
||||||
Layout.alignment: Qt.AlignHCenter
|
Layout.alignment: Qt.AlignHCenter
|
||||||
Layout.topMargin: height
|
Layout.topMargin: height
|
||||||
Layout.bottomMargin: height
|
Layout.bottomMargin: height
|
||||||
@@ -128,7 +129,7 @@ ColumnLayout {
|
|||||||
PropertyAnimation {
|
PropertyAnimation {
|
||||||
target: enterItem
|
target: enterItem
|
||||||
property: "x"
|
property: "x"
|
||||||
from: 0 - target.width
|
from: (navbarId.currentIndex < navbarId.previousIndex ? 1 : -1) * - target.width
|
||||||
to: 0
|
to: 0
|
||||||
duration: 300
|
duration: 300
|
||||||
easing.type: Easing.OutCubic
|
easing.type: Easing.OutCubic
|
||||||
@@ -137,7 +138,7 @@ ColumnLayout {
|
|||||||
target: exitItem
|
target: exitItem
|
||||||
property: "x"
|
property: "x"
|
||||||
from: 0
|
from: 0
|
||||||
to: target.width
|
to: (navbarId.currentIndex < navbarId.previousIndex ? 1 : -1) * target.width
|
||||||
duration: 300
|
duration: 300
|
||||||
easing.type: Easing.OutCubic
|
easing.type: Easing.OutCubic
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1013,6 +1013,7 @@ Rectangle {
|
|||||||
|
|
||||||
MoneroComponents.StandardButton {
|
MoneroComponents.StandardButton {
|
||||||
visible: isout
|
visible: isout
|
||||||
|
enabled: currentWallet ? !currentWallet.isHwBacked() : false
|
||||||
anchors.left: btnDetails.right
|
anchors.left: btnDetails.right
|
||||||
anchors.leftMargin: 10
|
anchors.leftMargin: 10
|
||||||
text: FontAwesome.productHunt
|
text: FontAwesome.productHunt
|
||||||
|
|||||||
456
pages/Mining.qml
@@ -26,17 +26,21 @@
|
|||||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
import QtQml.Models 2.2
|
||||||
import QtQuick 2.9
|
import QtQuick 2.9
|
||||||
import QtQuick.Layouts 1.1
|
import QtQuick.Layouts 1.1
|
||||||
import QtQuick.Dialogs 1.2
|
import QtQuick.Dialogs 1.2
|
||||||
import "../components" as MoneroComponents
|
import "../components" as MoneroComponents
|
||||||
import moneroComponents.Wallet 1.0
|
import moneroComponents.Wallet 1.0
|
||||||
|
import moneroComponents.P2PoolManager 1.0
|
||||||
|
import moneroComponents.DaemonManager 1.0
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: root
|
id: root
|
||||||
color: "transparent"
|
color: "transparent"
|
||||||
property alias miningHeight: mainLayout.height
|
property alias miningHeight: mainLayout.height
|
||||||
property double currentHashRate: 0
|
property double currentHashRate: 0
|
||||||
|
property int threads: idealThreadCount / 2
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
id: mainLayout
|
id: mainLayout
|
||||||
@@ -51,13 +55,14 @@ Rectangle {
|
|||||||
MoneroComponents.Label {
|
MoneroComponents.Label {
|
||||||
id: soloTitleLabel
|
id: soloTitleLabel
|
||||||
fontSize: 24
|
fontSize: 24
|
||||||
text: qsTr("Solo mining") + translationManager.emptyString
|
text: qsTr("Mining") + translationManager.emptyString
|
||||||
}
|
}
|
||||||
|
|
||||||
MoneroComponents.WarningBox {
|
MoneroComponents.WarningBox {
|
||||||
Layout.bottomMargin: 8
|
Layout.bottomMargin: 8
|
||||||
|
id: localDaemonWarning
|
||||||
text: qsTr("Mining is only available on local daemons.") + translationManager.emptyString
|
text: qsTr("Mining is only available on local daemons.") + translationManager.emptyString
|
||||||
visible: persistentSettings.useRemoteNode
|
visible: persistentSettings.useRemoteNode && !persistentSettings.allowRemoteNodeMining
|
||||||
}
|
}
|
||||||
|
|
||||||
MoneroComponents.WarningBox {
|
MoneroComponents.WarningBox {
|
||||||
@@ -68,7 +73,7 @@ Rectangle {
|
|||||||
|
|
||||||
MoneroComponents.TextPlain {
|
MoneroComponents.TextPlain {
|
||||||
id: soloMainLabel
|
id: soloMainLabel
|
||||||
text: qsTr("Mining with your computer helps strengthen the Monero network. The more that people mine, the harder it is for the network to be attacked, and every little bit helps.\n\nMining also gives you a small chance to earn some Monero. Your computer will create hashes looking for block solutions. If you find a block, you will get the associated reward. Good luck!") + translationManager.emptyString
|
text: qsTr("Mining with your computer helps strengthen the Monero network. The more people mine, the harder it is for the network to be attacked, and every little bit helps.\n\nMining also gives you a small chance to earn some Monero. Your computer will create hashes looking for block solutions. If you find a block, you will get the associated reward. Good luck!") + "\n\n" + qsTr("P2Pool mining is a decentralized way to pool mine that pays out more frequently compared to solo mining, while also supporting the network.") + translationManager.emptyString
|
||||||
wrapMode: Text.Wrap
|
wrapMode: Text.Wrap
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
font.family: MoneroComponents.Style.fontRegular.name
|
font.family: MoneroComponents.Style.fontRegular.name
|
||||||
@@ -89,6 +94,43 @@ Rectangle {
|
|||||||
columnSpacing: 20
|
columnSpacing: 20
|
||||||
rowSpacing: 16
|
rowSpacing: 16
|
||||||
|
|
||||||
|
ListModel {
|
||||||
|
id: miningModeModel
|
||||||
|
|
||||||
|
ListElement { column1: qsTr("Solo") ; column2: ""; priority: 0}
|
||||||
|
ListElement { column1: "P2Pool" ; column2: ""; priority: 1}
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.alignment : Qt.AlignTop | Qt.AlignLeft
|
||||||
|
|
||||||
|
MoneroComponents.Label {
|
||||||
|
id: miningModeLabel
|
||||||
|
color: MoneroComponents.Style.defaultFontColor
|
||||||
|
text: qsTr("Mining mode") + translationManager.emptyString
|
||||||
|
fontSize: 16
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
Layout.topMargin: 5
|
||||||
|
spacing: 10
|
||||||
|
|
||||||
|
MoneroComponents.StandardDropdown {
|
||||||
|
Layout.maximumWidth: 200
|
||||||
|
id: miningModeDropdown
|
||||||
|
visible: true
|
||||||
|
currentIndex: 0
|
||||||
|
dataModel: miningModeModel
|
||||||
|
onChanged: {
|
||||||
|
persistentSettings.allow_p2pool_mining = miningModeDropdown.currentIndex === 1;
|
||||||
|
walletManager.stopMining();
|
||||||
|
p2poolManager.exit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.alignment : Qt.AlignTop | Qt.AlignLeft
|
Layout.alignment : Qt.AlignTop | Qt.AlignLeft
|
||||||
@@ -106,30 +148,56 @@ Rectangle {
|
|||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
spacing: 16
|
spacing: 16
|
||||||
|
|
||||||
MoneroComponents.LineEdit {
|
RowLayout {
|
||||||
id: soloMinerThreadsLine
|
MoneroComponents.StandardButton {
|
||||||
Layout.minimumWidth: 200
|
id: removeThreadButton
|
||||||
text: "1"
|
small: true
|
||||||
validator: IntValidator { bottom: 1; top: idealThreadCount }
|
primary: false
|
||||||
}
|
text: "−"
|
||||||
|
enabled: threads > 1
|
||||||
|
onClicked: threads--
|
||||||
|
}
|
||||||
|
|
||||||
MoneroComponents.TextPlain {
|
MoneroComponents.TextPlain {
|
||||||
id: numAvailableThreadsText
|
Layout.bottomMargin: 1
|
||||||
text: qsTr("Max # of CPU threads available for mining: ") + idealThreadCount + translationManager.emptyString
|
Layout.minimumWidth: 45
|
||||||
wrapMode: Text.WordWrap
|
color: MoneroComponents.Style.defaultFontColor
|
||||||
font.family: MoneroComponents.Style.fontRegular.name
|
text: threads
|
||||||
font.pixelSize: 14
|
horizontalAlignment: Text.AlignHCenter
|
||||||
color: MoneroComponents.Style.defaultFontColor
|
font.pixelSize: 16
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
scrollGestureEnabled: false
|
||||||
|
onWheel: {
|
||||||
|
if (wheel.angleDelta.y > 0 && threads < idealThreadCount) {
|
||||||
|
return threads++
|
||||||
|
} else if (wheel.angleDelta.y < 0 && threads > 1) {
|
||||||
|
return threads--
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MoneroComponents.StandardButton {
|
||||||
|
id: addThreadButton
|
||||||
|
small: true
|
||||||
|
primary: false
|
||||||
|
text: "+"
|
||||||
|
enabled: threads < idealThreadCount
|
||||||
|
onClicked: threads++
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RowLayout {
|
RowLayout {
|
||||||
MoneroComponents.StandardButton {
|
MoneroComponents.StandardButton {
|
||||||
id: autoRecommendedThreadsButton
|
id: autoRecommendedThreadsButton
|
||||||
small: true
|
small: true
|
||||||
text: qsTr("Use recommended # of threads") + translationManager.emptyString
|
primary: false
|
||||||
|
text: qsTr("Use half (recommended)") + translationManager.emptyString
|
||||||
enabled: startSoloMinerButton.enabled
|
enabled: startSoloMinerButton.enabled
|
||||||
onClicked: {
|
onClicked: {
|
||||||
soloMinerThreadsLine.text = Math.floor(idealThreadCount / 2);
|
threads = idealThreadCount / 2
|
||||||
appWindow.showStatusMessage(qsTr("Set to use recommended # of threads"),3)
|
appWindow.showStatusMessage(qsTr("Set to use recommended # of threads"),3)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -137,25 +205,16 @@ Rectangle {
|
|||||||
MoneroComponents.StandardButton {
|
MoneroComponents.StandardButton {
|
||||||
id: autoSetMaxThreadsButton
|
id: autoSetMaxThreadsButton
|
||||||
small: true
|
small: true
|
||||||
text: qsTr("Use all threads") + translationManager.emptyString
|
primary: false
|
||||||
|
text: qsTr("Use all threads") + " (" + idealThreadCount + ")" + translationManager.emptyString
|
||||||
enabled: startSoloMinerButton.enabled
|
enabled: startSoloMinerButton.enabled
|
||||||
onClicked: {
|
onClicked: {
|
||||||
soloMinerThreadsLine.text = idealThreadCount
|
threads = idealThreadCount
|
||||||
appWindow.showStatusMessage(qsTr("Set to use all threads") + translationManager.emptyString,3)
|
appWindow.showStatusMessage(qsTr("Set to use all threads") + translationManager.emptyString,3)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RowLayout {
|
|
||||||
MoneroComponents.CheckBox {
|
|
||||||
id: backgroundMining
|
|
||||||
enabled: startSoloMinerButton.enabled
|
|
||||||
checked: persistentSettings.allow_background_mining
|
|
||||||
onClicked: {persistentSettings.allow_background_mining = checked}
|
|
||||||
text: qsTr("Background mining (experimental)") + translationManager.emptyString
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RowLayout {
|
RowLayout {
|
||||||
// Disable this option until stable
|
// Disable this option until stable
|
||||||
visible: false
|
visible: false
|
||||||
@@ -169,6 +228,37 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
Layout.alignment: Qt.AlignTop | Qt.AlignLeft
|
||||||
|
Layout.minimumWidth: 140
|
||||||
|
|
||||||
|
MoneroComponents.Label {
|
||||||
|
id: optionsLabel
|
||||||
|
color: MoneroComponents.Style.defaultFontColor
|
||||||
|
visible: !persistentSettings.allow_p2pool_mining
|
||||||
|
text: qsTr("Options") + translationManager.emptyString
|
||||||
|
fontSize: 16
|
||||||
|
wrapMode: Text.Wrap
|
||||||
|
Layout.preferredWidth: manageSoloMinerLabel.textWidth
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
spacing: 16
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
MoneroComponents.CheckBox {
|
||||||
|
id: backgroundMining
|
||||||
|
visible: !persistentSettings.allow_p2pool_mining
|
||||||
|
enabled: startSoloMinerButton.enabled && !persistentSettings.allow_p2pool_mining
|
||||||
|
checked: persistentSettings.allow_background_mining
|
||||||
|
onClicked: persistentSettings.allow_background_mining = checked
|
||||||
|
text: qsTr("Background mining (experimental)") + translationManager.emptyString
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
Layout.alignment : Qt.AlignTop | Qt.AlignLeft
|
Layout.alignment : Qt.AlignTop | Qt.AlignLeft
|
||||||
|
|
||||||
@@ -191,18 +281,55 @@ Rectangle {
|
|||||||
visible: true
|
visible: true
|
||||||
id: startSoloMinerButton
|
id: startSoloMinerButton
|
||||||
small: true
|
small: true
|
||||||
|
primary: !stopSoloMinerButton.enabled
|
||||||
text: qsTr("Start mining") + translationManager.emptyString
|
text: qsTr("Start mining") + translationManager.emptyString
|
||||||
onClicked: {
|
onClicked: {
|
||||||
var success = walletManager.startMining(appWindow.currentWallet.address(0, 0), soloMinerThreadsLine.text, persistentSettings.allow_background_mining, persistentSettings.miningIgnoreBattery)
|
var daemonReady = appWindow.daemonSynced && appWindow.daemonRunning && !persistentSettings.useRemoteNode
|
||||||
if (success) {
|
if (persistentSettings.allowRemoteNodeMining) {
|
||||||
update()
|
daemonReady = persistentSettings.useRemoteNode && appWindow.daemonSynced
|
||||||
} else {
|
}
|
||||||
errorPopup.title = qsTr("Error starting mining") + translationManager.emptyString;
|
if (daemonReady) {
|
||||||
errorPopup.text = qsTr("Couldn't start mining.<br>") + translationManager.emptyString
|
var success;
|
||||||
if (persistentSettings.useRemoteNode)
|
if (persistentSettings.allow_p2pool_mining) {
|
||||||
errorPopup.text += qsTr("Mining is only available on local daemons. Run a local daemon to be able to mine.<br>") + translationManager.emptyString
|
if (p2poolManager.isInstalled()) {
|
||||||
errorPopup.icon = StandardIcon.Critical
|
if (persistentSettings.allowRemoteNodeMining) {
|
||||||
errorPopup.open()
|
startP2Pool()
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
daemonManager.stopAsync(persistentSettings.nettype, startP2PoolLocal)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
confirmationDialog.title = qsTr("P2Pool installation") + translationManager.emptyString;
|
||||||
|
confirmationDialog.text = qsTr("P2Pool will be installed at %1. Proceed?").arg(applicationDirectory) + translationManager.emptyString;
|
||||||
|
confirmationDialog.icon = StandardIcon.Question;
|
||||||
|
confirmationDialog.cancelText = qsTr("No") + translationManager.emptyString;
|
||||||
|
confirmationDialog.okText = qsTr("Yes") + translationManager.emptyString;
|
||||||
|
confirmationDialog.onAcceptedCallback = function() {
|
||||||
|
p2poolManager.download();
|
||||||
|
statusMessageText.text = "Downloading P2Pool...";
|
||||||
|
statusMessage.visible = true
|
||||||
|
startSoloMinerButton.enabled = false;
|
||||||
|
stopSoloMinerButton.enabled = false;
|
||||||
|
}
|
||||||
|
confirmationDialog.open();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
success = walletManager.startMining(appWindow.currentWallet.address(0, 0), threads, persistentSettings.allow_background_mining, persistentSettings.miningIgnoreBattery)
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
update()
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
miningError(qsTr("Couldn't start mining.<br>") + translationManager.emptyString)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
miningError(qsTr("Couldn't start mining.<br>") + translationManager.emptyString)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -211,9 +338,11 @@ Rectangle {
|
|||||||
visible: true
|
visible: true
|
||||||
id: stopSoloMinerButton
|
id: stopSoloMinerButton
|
||||||
small: true
|
small: true
|
||||||
|
primary: stopSoloMinerButton.enabled
|
||||||
text: qsTr("Stop mining") + translationManager.emptyString
|
text: qsTr("Stop mining") + translationManager.emptyString
|
||||||
onClicked: {
|
onClicked: {
|
||||||
walletManager.stopMining()
|
walletManager.stopMining()
|
||||||
|
p2poolManager.exit()
|
||||||
update()
|
update()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -246,23 +375,161 @@ Rectangle {
|
|||||||
inputPaddingLeft: 0
|
inputPaddingLeft: 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ListModel {
|
||||||
|
id: chainModel
|
||||||
|
|
||||||
|
ListElement { column1: qsTr("Mini") ; column2: ""; priority: 0}
|
||||||
|
ListElement { column1: qsTr("Main") ; column2: ""; priority: 1}
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.alignment : Qt.AlignTop | Qt.AlignLeft
|
||||||
|
|
||||||
|
MoneroComponents.Label {
|
||||||
|
id: chainLabel
|
||||||
|
color: MoneroComponents.Style.defaultFontColor
|
||||||
|
visible: persistentSettings.allow_p2pool_mining
|
||||||
|
text: qsTr("Chain") + translationManager.emptyString
|
||||||
|
fontSize: 16
|
||||||
|
}
|
||||||
|
|
||||||
|
MoneroComponents.Tooltip {
|
||||||
|
id: chainsHelpTooltip
|
||||||
|
text: qsTr("Use the mini chain if you have a low hashrate.") + translationManager.emptyString
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: chainsTooltipArea
|
||||||
|
width: parent.width
|
||||||
|
height: parent.height
|
||||||
|
enabled: persistentSettings.allow_p2pool_mining
|
||||||
|
hoverEnabled: true
|
||||||
|
onEntered: {
|
||||||
|
chainsHelpTooltip.tooltipPopup.open();
|
||||||
|
}
|
||||||
|
onExited: {
|
||||||
|
chainsHelpTooltip.tooltipPopup.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
Layout.topMargin: 5
|
||||||
|
spacing: 10
|
||||||
|
|
||||||
|
MoneroComponents.StandardDropdown {
|
||||||
|
Layout.maximumWidth: 200
|
||||||
|
id: chainDropdown
|
||||||
|
visible: persistentSettings.allow_p2pool_mining
|
||||||
|
currentIndex: 0
|
||||||
|
dataModel: chainModel
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.alignment : Qt.AlignTop | Qt.AlignLeft
|
||||||
|
|
||||||
|
MoneroComponents.Label {
|
||||||
|
id: flagsLabel
|
||||||
|
visible: persistentSettings.allow_p2pool_mining
|
||||||
|
color: MoneroComponents.Style.defaultFontColor
|
||||||
|
text: qsTr("Flags") + translationManager.emptyString
|
||||||
|
fontSize: 16
|
||||||
|
}
|
||||||
|
|
||||||
|
MoneroComponents.Tooltip {
|
||||||
|
id: flagsHelpTooltip
|
||||||
|
text: "
|
||||||
|
Usage:<br>
|
||||||
|
--wallet Wallet address to mine to. Subaddresses and integrated addresses are not supported!<br>
|
||||||
|
--host IP address of your Monero node, default is 127.0.0.1<br>
|
||||||
|
--rpc-port monerod RPC API port number, default is 18081<br>
|
||||||
|
--zmq-port monerod ZMQ pub port number, default is 18083 (same port as in monerod\'s \"--zmq-pub\" command line parameter)<br>
|
||||||
|
--stratum Comma-separated list of IP:port for stratum server to listen on<br>
|
||||||
|
--p2p Comma-separated list of IP:port for p2p server to listen on<br>
|
||||||
|
--addpeers Comma-separated list of IP:port of other p2pool nodes to connect to<br>
|
||||||
|
--light-mode Don't allocate RandomX dataset, saves 2GB of RAM<br>
|
||||||
|
--loglevel Verbosity of the log, integer number between 0 and 6<br>
|
||||||
|
--config Name of the p2pool config file<br>
|
||||||
|
--data-api Path to the p2pool JSON data (use it in tandem with an external web-server)<br>
|
||||||
|
--local-api Enable /local/ path in api path for Stratum Server and built-in miner statistics<br>
|
||||||
|
--stratum-api An alias for --local-api<br>
|
||||||
|
--no-cache Disable p2pool.cache<br>
|
||||||
|
--no-color Disable colors in console output<br>
|
||||||
|
--no-randomx Disable internal RandomX hasher: p2pool will use RPC calls to monerod to check PoW hashes<br>
|
||||||
|
--out-peers N Maximum number of outgoing connections for p2p server (any value between 10 and 1000)<br>
|
||||||
|
--in-peers N Maximum number of incoming connections for p2p server (any value between 10 and 1000)<br>
|
||||||
|
--start-mining N Start built-in miner using N threads (any value between 1 and 64)<br>
|
||||||
|
--help Show this help message
|
||||||
|
"
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: flagsTooltipArea
|
||||||
|
width: parent.width
|
||||||
|
height: parent.height
|
||||||
|
enabled: persistentSettings.allow_p2pool_mining
|
||||||
|
hoverEnabled: true
|
||||||
|
onEntered: {
|
||||||
|
flagsHelpTooltip.tooltipPopup.open();
|
||||||
|
}
|
||||||
|
onExited: {
|
||||||
|
flagsHelpTooltip.tooltipPopup.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
MoneroComponents.LineEditMulti {
|
||||||
|
id: p2poolFlags
|
||||||
|
Layout.minimumWidth: 100
|
||||||
|
Layout.bottomMargin: 20
|
||||||
|
labelFontSize: 14
|
||||||
|
fontSize: 15
|
||||||
|
visible: persistentSettings.allow_p2pool_mining
|
||||||
|
wrapMode: Text.WrapAnywhere
|
||||||
|
labelText: qsTr("P2Pool startup flags") + translationManager.emptyString
|
||||||
|
placeholderText: qsTr("(optional)") + translationManager.emptyString
|
||||||
|
placeholderFontSize: 15
|
||||||
|
text: persistentSettings.p2poolFlags
|
||||||
|
addressValidation: false
|
||||||
|
onEditingFinished: {
|
||||||
|
persistentSettings.allowRemoteNodeMining = p2poolFlags.text.includes("--host");
|
||||||
|
persistentSettings.p2poolFlags = p2poolFlags.text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateStatusText() {
|
function updateStatusText(p2poolHashrate) {
|
||||||
if (appWindow.isMining) {
|
if (appWindow.isMining) {
|
||||||
var userHashRate = walletManager.miningHashRate();
|
if (persistentSettings.allow_p2pool_mining) {
|
||||||
if (userHashRate === 0) {
|
if (p2poolHashrate === 0) {
|
||||||
statusText.text = qsTr("Mining temporarily suspended.") + translationManager.emptyString;
|
statusText.text = qsTr("Starting P2Pool") + translationManager.emptyString;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
statusText.text = qsTr("Mining with P2Pool, at %1 H/s").arg(p2poolHashrate) + translationManager.emptyString;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
var blockTime = 120;
|
var userHashRate = walletManager.miningHashRate();
|
||||||
var blocksPerDay = 86400 / blockTime;
|
if (userHashRate === 0) {
|
||||||
var globalHashRate = walletManager.networkDifficulty() / blockTime;
|
statusText.text = qsTr("Mining temporarily suspended.") + translationManager.emptyString;
|
||||||
var probabilityFindNextBlock = userHashRate / globalHashRate;
|
}
|
||||||
var probabilityFindBlockDay = 1 - Math.pow(1 - probabilityFindNextBlock, blocksPerDay);
|
else {
|
||||||
var chanceFindBlockDay = Math.round(1 / probabilityFindBlockDay);
|
var blockTime = 120;
|
||||||
statusText.text = qsTr("Mining at %1 H/s. It gives you a 1 in %2 daily chance of finding a block.").arg(userHashRate).arg(chanceFindBlockDay) + translationManager.emptyString;
|
var blocksPerDay = 86400 / blockTime;
|
||||||
|
var globalHashRate = walletManager.networkDifficulty() / blockTime;
|
||||||
|
var probabilityFindNextBlock = userHashRate / globalHashRate;
|
||||||
|
var probabilityFindBlockDay = 1 - Math.pow(1 - probabilityFindNextBlock, blocksPerDay);
|
||||||
|
var chanceFindBlockDay = Math.round(1 / probabilityFindBlockDay);
|
||||||
|
statusText.text = qsTr("Mining at %1 H/s. It gives you a 1 in %2 daily chance of finding a block.").arg(userHashRate).arg(chanceFindBlockDay) + translationManager.emptyString;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -270,16 +537,35 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function onMiningStatus(isMining) {
|
function onMiningStatus(isMining, hashrate) {
|
||||||
var daemonReady = !persistentSettings.useRemoteNode && appWindow.daemonSynced
|
var daemonReady = appWindow.daemonSynced
|
||||||
|
if (!persistentSettings.allowRemoteNodeMining) {
|
||||||
|
var daemonReady = !persistentSettings.useRemoteNode && daemonReady
|
||||||
|
}
|
||||||
appWindow.isMining = isMining;
|
appWindow.isMining = isMining;
|
||||||
updateStatusText()
|
updateStatusText(hashrate)
|
||||||
startSoloMinerButton.enabled = !appWindow.isMining && daemonReady
|
startSoloMinerButton.enabled = !appWindow.isMining && daemonReady
|
||||||
stopSoloMinerButton.enabled = !startSoloMinerButton.enabled && daemonReady
|
stopSoloMinerButton.enabled = !startSoloMinerButton.enabled && daemonReady
|
||||||
}
|
}
|
||||||
|
|
||||||
function update() {
|
function update() {
|
||||||
walletManager.miningStatusAsync();
|
persistentSettings.allow_p2pool_mining = miningModeDropdown.currentIndex === 1;
|
||||||
|
if (persistentSettings.allow_p2pool_mining) {
|
||||||
|
p2poolManager.getStatus();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
walletManager.miningStatusAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function miningError(message) {
|
||||||
|
p2poolManager.exit()
|
||||||
|
errorPopup.title = qsTr("Error starting mining") + translationManager.emptyString;
|
||||||
|
errorPopup.text = message
|
||||||
|
if (persistentSettings.useRemoteNode && !persistentSettings.allowRemoteNodeMining)
|
||||||
|
errorPopup.text += qsTr("Mining is only available on local daemons. Run a local daemon to be able to mine.<br>") + translationManager.emptyString
|
||||||
|
errorPopup.icon = StandardIcon.Critical
|
||||||
|
errorPopup.open()
|
||||||
}
|
}
|
||||||
|
|
||||||
MoneroComponents.StandardDialog {
|
MoneroComponents.StandardDialog {
|
||||||
@@ -289,21 +575,67 @@ Rectangle {
|
|||||||
|
|
||||||
Timer {
|
Timer {
|
||||||
id: timer
|
id: timer
|
||||||
interval: 2000; running: false; repeat: true
|
interval: 2000
|
||||||
|
running: middlePanel.advancedView.state === "Mining" && middlePanel.state === "Advanced" && currentWallet !== undefined && (!persistentSettings.useRemoteNode || persistentSettings.allowRemoteNodeMining)
|
||||||
|
repeat: true
|
||||||
onTriggered: update()
|
onTriggered: update()
|
||||||
}
|
}
|
||||||
|
|
||||||
function onPageCompleted() {
|
function startP2PoolLocal() {
|
||||||
console.log("Mining page loaded");
|
var noSync = false;
|
||||||
update()
|
var customDaemonArgs = persistentSettings.daemonFlags.toLowerCase();
|
||||||
timer.running = !persistentSettings.useRemoteNode
|
var daemonArgs = "--zmq-pub " + "tcp://127.0.0.1:18083 " + "--disable-dns-checkpoints "
|
||||||
|
if (!customDaemonArgs.includes("--zmq-pub") && !customDaemonArgs.includes("--disable-dns-checkpoints") && !customDaemonArgs.includes("--no-zmq")) {
|
||||||
|
daemonArgs = daemonArgs + customDaemonArgs;
|
||||||
|
}
|
||||||
|
var success = daemonManager.start(daemonArgs, persistentSettings.nettype, persistentSettings.blockchainDataDir, persistentSettings.bootstrapNodeAddress, noSync, persistentSettings.pruneBlockchain)
|
||||||
|
if (success) {
|
||||||
|
startP2Pool()
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
miningError(qsTr("Couldn't start mining.<br>") + translationManager.emptyString)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function onPageClosed() {
|
function startP2Pool() {
|
||||||
timer.running = false
|
var address = currentWallet.address(0, 0);
|
||||||
|
var chain = "mini"
|
||||||
|
if (chainDropdown.currentIndex === 1) {
|
||||||
|
chain = "main"
|
||||||
|
}
|
||||||
|
var p2poolArgs = persistentSettings.p2poolFlags;
|
||||||
|
var success = p2poolManager.start(p2poolArgs, address, chain, threads);
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
update()
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
miningError(qsTr("Couldn't start mining.<br>") + translationManager.emptyString)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function p2poolDownloadFailed() {
|
||||||
|
statusMessage.visible = false
|
||||||
|
errorPopup.title = qsTr("P2Pool Installation Failed") + translationManager.emptyString;
|
||||||
|
errorPopup.text = "P2Pool installation failed."
|
||||||
|
errorPopup.icon = StandardIcon.Critical
|
||||||
|
errorPopup.open()
|
||||||
|
update()
|
||||||
|
}
|
||||||
|
|
||||||
|
function p2poolDownloadSucceeded() {
|
||||||
|
statusMessage.visible = false
|
||||||
|
informationPopup.title = qsTr("P2Pool Installation Succeeded") + translationManager.emptyString;
|
||||||
|
informationPopup.text = qsTr("P2Pool has successfully installed.");
|
||||||
|
informationPopup.icon = StandardIcon.Critical
|
||||||
|
informationPopup.open()
|
||||||
|
update()
|
||||||
}
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
walletManager.miningStatus.connect(onMiningStatus);
|
walletManager.miningStatus.connect(onMiningStatus);
|
||||||
|
p2poolManager.p2poolStatus.connect(onMiningStatus);
|
||||||
|
p2poolManager.p2poolDownloadFailure.connect(p2poolDownloadFailed);
|
||||||
|
p2poolManager.p2poolDownloadSuccess.connect(p2poolDownloadSucceeded);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,12 +63,11 @@ Rectangle {
|
|||||||
|
|
||||||
function generateQRCodeString() {
|
function generateQRCodeString() {
|
||||||
if (pageReceive.state == "PaymentRequest") {
|
if (pageReceive.state == "PaymentRequest") {
|
||||||
return TxUtils.makeQRCodeString(appWindow.current_address,
|
return walletManager.make_uri(appWindow.current_address,
|
||||||
(amountToReceiveXMR.text != "" && parseFloat(amountToReceiveXMR.text) != 0 ? amountToReceiveXMR.text : ""),
|
walletManager.amountFromString(amountToReceiveXMR.text),
|
||||||
(txDescriptionInput.text != "" ? txDescriptionInput.text : ""),
|
txDescriptionInput.text, receiverNameInput.text);
|
||||||
(receiverNameInput.text != "" ? receiverNameInput.text : ""));
|
|
||||||
} else {
|
} else {
|
||||||
return TxUtils.makeQRCodeString(appWindow.current_address);
|
return walletManager.make_uri(appWindow.current_address);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,13 +151,16 @@ Rectangle {
|
|||||||
Menu {
|
Menu {
|
||||||
id: qrMenu
|
id: qrMenu
|
||||||
title: "QrCode"
|
title: "QrCode"
|
||||||
|
currentIndex: menuItem1.hovered ? 0 : menuItem2.hovered ? 1 : -1
|
||||||
|
|
||||||
MenuItem {
|
MenuItem {
|
||||||
|
id: menuItem1
|
||||||
text: qsTr("Copy to clipboard") + translationManager.emptyString;
|
text: qsTr("Copy to clipboard") + translationManager.emptyString;
|
||||||
onTriggered: walletManager.saveQrCodeToClipboard(generateQRCodeString())
|
onTriggered: walletManager.saveQrCodeToClipboard(generateQRCodeString())
|
||||||
}
|
}
|
||||||
|
|
||||||
MenuItem {
|
MenuItem {
|
||||||
|
id: menuItem2
|
||||||
text: qsTr("Save as Image") + translationManager.emptyString;
|
text: qsTr("Save as Image") + translationManager.emptyString;
|
||||||
onTriggered: qrFileDialog.open()
|
onTriggered: qrFileDialog.open()
|
||||||
}
|
}
|
||||||
@@ -344,6 +346,7 @@ Rectangle {
|
|||||||
id: txDescriptionInput
|
id: txDescriptionInput
|
||||||
Layout.preferredWidth: 165
|
Layout.preferredWidth: 165
|
||||||
Layout.maximumWidth: 165
|
Layout.maximumWidth: 165
|
||||||
|
maximumLength: 800
|
||||||
topPadding: 7
|
topPadding: 7
|
||||||
leftPadding: 7
|
leftPadding: 7
|
||||||
font.pixelSize: 14
|
font.pixelSize: 14
|
||||||
@@ -391,6 +394,7 @@ Rectangle {
|
|||||||
selectByMouse: true
|
selectByMouse: true
|
||||||
color: MoneroComponents.Style.defaultFontColor
|
color: MoneroComponents.Style.defaultFontColor
|
||||||
placeholderText: qsTr("Visible to the sender") + translationManager.emptyString
|
placeholderText: qsTr("Visible to the sender") + translationManager.emptyString
|
||||||
|
maximumLength: 100
|
||||||
|
|
||||||
background: Rectangle {
|
background: Rectangle {
|
||||||
color: MoneroComponents.Style.blackTheme ? "transparent" : "white"
|
color: MoneroComponents.Style.blackTheme ? "transparent" : "white"
|
||||||
|
|||||||
@@ -112,11 +112,8 @@ Rectangle {
|
|||||||
MoneroComponents.LabelSubheader {
|
MoneroComponents.LabelSubheader {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
textFormat: Text.RichText
|
textFormat: Text.RichText
|
||||||
text: "<style type='text/css'>a {text-decoration: none; color: #FF6C3C; font-size: 14px;}</style>" +
|
text: qsTr("Outputs marked as spent") + translationManager.emptyString
|
||||||
qsTr("Outputs marked as spent") + " <a href='#'>" + qsTr("Help") + "</a>" + translationManager.emptyString
|
tooltip: qsTr(
|
||||||
onLinkActivated: {
|
|
||||||
sharedRingDBDialog.title = qsTr("Outputs marked as spent") + translationManager.emptyString;
|
|
||||||
sharedRingDBDialog.text = qsTr(
|
|
||||||
"In order to obscure which inputs in a Monero transaction are being spent, a third party should not be able " +
|
"In order to obscure which inputs in a Monero transaction are being spent, a third party should not be able " +
|
||||||
"to tell which inputs in a ring are already known to be spent. Being able to do so would weaken the protection " +
|
"to tell which inputs in a ring are already known to be spent. Being able to do so would weaken the protection " +
|
||||||
"afforded by ring signatures. If all but one of the inputs are known to be already spent, then the input being " +
|
"afforded by ring signatures. If all but one of the inputs are known to be already spent, then the input being " +
|
||||||
@@ -128,9 +125,6 @@ Rectangle {
|
|||||||
"Alternatively, you can scan the blockchain (and the blockchain of key-reusing Monero clones) yourself " +
|
"Alternatively, you can scan the blockchain (and the blockchain of key-reusing Monero clones) yourself " +
|
||||||
"using the monero-blockchain-mark-spent-outputs tool to create a list of known spent outputs.<br>"
|
"using the monero-blockchain-mark-spent-outputs tool to create a list of known spent outputs.<br>"
|
||||||
) + translationManager.emptyString
|
) + translationManager.emptyString
|
||||||
sharedRingDBDialog.icon = StandardIcon.Information
|
|
||||||
sharedRingDBDialog.open()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MoneroComponents.TextPlain {
|
MoneroComponents.TextPlain {
|
||||||
@@ -249,11 +243,8 @@ Rectangle {
|
|||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.topMargin: 24
|
Layout.topMargin: 24
|
||||||
textFormat: Text.RichText
|
textFormat: Text.RichText
|
||||||
text: "<style type='text/css'>a {text-decoration: none; color: #FF6C3C; font-size: 14px;}</style>" +
|
text: qsTr("Rings") + translationManager.emptyString
|
||||||
qsTr("Rings") + " <a href='#'>" + qsTr("Help") + "</a>" + translationManager.emptyString
|
tooltip: qsTr(
|
||||||
onLinkActivated: {
|
|
||||||
sharedRingDBDialog.title = qsTr("Rings") + translationManager.emptyString;
|
|
||||||
sharedRingDBDialog.text = qsTr(
|
|
||||||
"In order to avoid nullifying the protection afforded by Monero's ring signatures, an output should not " +
|
"In order to avoid nullifying the protection afforded by Monero's ring signatures, an output should not " +
|
||||||
"be spent with different rings on different blockchains. While this is normally not a concern, it can become one " +
|
"be spent with different rings on different blockchains. While this is normally not a concern, it can become one " +
|
||||||
"when a key-reusing Monero clone allows you to spend existing outputs. In this case, you need to ensure this " +
|
"when a key-reusing Monero clone allows you to spend existing outputs. In this case, you need to ensure this " +
|
||||||
@@ -266,9 +257,6 @@ Rectangle {
|
|||||||
"If you do not use a key-reusing Monero clone without these safety features, then you do not need to do anything " +
|
"If you do not use a key-reusing Monero clone without these safety features, then you do not need to do anything " +
|
||||||
"as it is all automated.<br>"
|
"as it is all automated.<br>"
|
||||||
) + translationManager.emptyString
|
) + translationManager.emptyString
|
||||||
sharedRingDBDialog.icon = StandardIcon.Information
|
|
||||||
sharedRingDBDialog.open()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MoneroComponents.TextPlain {
|
MoneroComponents.TextPlain {
|
||||||
|
|||||||
@@ -394,11 +394,11 @@ Rectangle {
|
|||||||
wrapMode: Text.WrapAnywhere
|
wrapMode: Text.WrapAnywhere
|
||||||
placeholderText: {
|
placeholderText: {
|
||||||
if(persistentSettings.nettype == NetworkType.MAINNET){
|
if(persistentSettings.nettype == NetworkType.MAINNET){
|
||||||
return "4.. / 8.. / OpenAlias";
|
return "4.. / 8.. / monero:.. / OpenAlias";
|
||||||
} else if (persistentSettings.nettype == NetworkType.STAGENET){
|
} else if (persistentSettings.nettype == NetworkType.STAGENET){
|
||||||
return "5.. / 7..";
|
return "5.. / 7.. / monero:..";
|
||||||
} else if(persistentSettings.nettype == NetworkType.TESTNET){
|
} else if(persistentSettings.nettype == NetworkType.TESTNET){
|
||||||
return "9.. / B..";
|
return "9.. / B.. / monero:..";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onTextChanged: {
|
onTextChanged: {
|
||||||
@@ -855,7 +855,6 @@ Rectangle {
|
|||||||
StandardButton {
|
StandardButton {
|
||||||
id: sendButton
|
id: sendButton
|
||||||
rightIcon: "qrc:///images/rightArrow.png"
|
rightIcon: "qrc:///images/rightArrow.png"
|
||||||
rightIconInactive: "qrc:///images/rightArrowInactive.png"
|
|
||||||
Layout.topMargin: 4
|
Layout.topMargin: 4
|
||||||
text: qsTr("Send") + translationManager.emptyString
|
text: qsTr("Send") + translationManager.emptyString
|
||||||
enabled: !sendButtonWarningBox.visible && !warningContent && !recipientModel.hasEmptyAddress() && !paymentIdWarningBox.visible
|
enabled: !sendButtonWarningBox.visible && !warningContent && !recipientModel.hasEmptyAddress() && !paymentIdWarningBox.visible
|
||||||
@@ -898,6 +897,32 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AdvancedOptionsItem {
|
||||||
|
visible: persistentSettings.transferShowAdvanced && appWindow.walletMode >= 2
|
||||||
|
title: qsTr("Outputs") + translationManager.emptyString
|
||||||
|
button1.text: qsTr("Export") + translationManager.emptyString
|
||||||
|
button1.enabled: appWindow.viewOnly
|
||||||
|
button1.onClicked: {
|
||||||
|
console.log("Transfer: export outputs clicked")
|
||||||
|
exportOutputsDialog.open();
|
||||||
|
}
|
||||||
|
button2.text: qsTr("Import") + translationManager.emptyString
|
||||||
|
button2.enabled: !appWindow.viewOnly
|
||||||
|
button2.onClicked: {
|
||||||
|
console.log("Transfer: import outputs clicked")
|
||||||
|
importOutputsDialog.open();
|
||||||
|
}
|
||||||
|
tooltip: {
|
||||||
|
var header = qsTr("Required for cold wallets to sign their corresponding key images") + translationManager.emptyString;
|
||||||
|
return "<style type='text/css'>.header{ font-size: 13px; } p{line-height:20px; margin-top:0px; margin-bottom:0px; " +
|
||||||
|
";} p.orange{color:#ff9323;}</style>" +
|
||||||
|
"<div class='header'>" + header + "</div>" +
|
||||||
|
"<p>" + qsTr("1. Using view-only wallet, export the outputs into a file") + "</p>" +
|
||||||
|
"<p>" + qsTr("2. Using cold wallet, import the outputs file") + "</p>" +
|
||||||
|
translationManager.emptyString
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
AdvancedOptionsItem {
|
AdvancedOptionsItem {
|
||||||
visible: persistentSettings.transferShowAdvanced && appWindow.walletMode >= 2
|
visible: persistentSettings.transferShowAdvanced && appWindow.walletMode >= 2
|
||||||
title: qsTr("Key images") + translationManager.emptyString
|
title: qsTr("Key images") + translationManager.emptyString
|
||||||
@@ -1005,24 +1030,7 @@ Rectangle {
|
|||||||
// deleting transaction object, we don't want memleaks
|
// deleting transaction object, we don't want memleaks
|
||||||
transaction.destroy();
|
transaction.destroy();
|
||||||
} else {
|
} else {
|
||||||
confirmationDialog.text = qsTr("\nNumber of transactions: ") + transaction.txCount
|
confirmationDialog.text = qsTr("\nConfirmation message:\n ") + transaction.confirmationMessage
|
||||||
for (var i = 0; i < transaction.txCount; ++i) {
|
|
||||||
confirmationDialog.text += qsTr("\nTransaction #%1").arg(i+1)
|
|
||||||
+qsTr("\nRecipient: ") + transaction.recipientAddress[i]
|
|
||||||
+ (transaction.paymentId[i] == "" ? "" : qsTr("\n\payment ID: ") + transaction.paymentId[i])
|
|
||||||
+ qsTr("\nAmount: ") + walletManager.displayAmount(transaction.amount(i))
|
|
||||||
+ qsTr("\nFee: ") + walletManager.displayAmount(transaction.fee(i))
|
|
||||||
+ qsTr("\nRingsize: ") + (transaction.mixin(i)+1)
|
|
||||||
|
|
||||||
// TODO: add descriptions to unsigned_tx_set?
|
|
||||||
// + (transactionDescription === "" ? "" : (qsTr("\n\nDescription: ") + transactionDescription))
|
|
||||||
+ translationManager.emptyString
|
|
||||||
if (i > 0) {
|
|
||||||
confirmationDialog.text += "\n\n"
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(transaction.confirmationMessage);
|
console.log(transaction.confirmationMessage);
|
||||||
|
|
||||||
// Show confirmation dialog
|
// Show confirmation dialog
|
||||||
@@ -1072,6 +1080,41 @@ Rectangle {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FileDialog {
|
||||||
|
id: exportOutputsDialog
|
||||||
|
selectMultiple: false
|
||||||
|
selectExisting: false
|
||||||
|
onAccepted: {
|
||||||
|
console.log(walletManager.urlToLocalPath(exportOutputsDialog.fileUrl))
|
||||||
|
if (currentWallet.exportOutputs(walletManager.urlToLocalPath(exportOutputsDialog.fileUrl), true)) {
|
||||||
|
appWindow.showStatusMessage(qsTr("Outputs successfully exported to file") + translationManager.emptyString, 3);
|
||||||
|
} else {
|
||||||
|
appWindow.showStatusMessage(currentWallet.errorString, 5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onRejected: {
|
||||||
|
console.log("Canceled");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FileDialog {
|
||||||
|
id: importOutputsDialog
|
||||||
|
selectMultiple: false
|
||||||
|
selectExisting: true
|
||||||
|
title: qsTr("Please choose a file") + translationManager.emptyString
|
||||||
|
onAccepted: {
|
||||||
|
console.log(walletManager.urlToLocalPath(importOutputsDialog.fileUrl))
|
||||||
|
if (currentWallet.importOutputs(walletManager.urlToLocalPath(importOutputsDialog.fileUrl))) {
|
||||||
|
appWindow.showStatusMessage(qsTr("Outputs successfully imported to wallet") + translationManager.emptyString, 3);
|
||||||
|
} else {
|
||||||
|
appWindow.showStatusMessage(currentWallet.errorString, 5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onRejected: {
|
||||||
|
console.log("Canceled");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//ExportKeyImagesDialog
|
//ExportKeyImagesDialog
|
||||||
FileDialog {
|
FileDialog {
|
||||||
id: exportKeyImagesDialog
|
id: exportKeyImagesDialog
|
||||||
@@ -1079,7 +1122,11 @@ Rectangle {
|
|||||||
selectExisting: false
|
selectExisting: false
|
||||||
onAccepted: {
|
onAccepted: {
|
||||||
console.log(walletManager.urlToLocalPath(exportKeyImagesDialog.fileUrl))
|
console.log(walletManager.urlToLocalPath(exportKeyImagesDialog.fileUrl))
|
||||||
currentWallet.exportKeyImages(walletManager.urlToLocalPath(exportKeyImagesDialog.fileUrl));
|
if (currentWallet.exportKeyImages(walletManager.urlToLocalPath(exportKeyImagesDialog.fileUrl), true)) {
|
||||||
|
appWindow.showStatusMessage(qsTr("Key images successfully exported to file") + translationManager.emptyString, 3);
|
||||||
|
} else {
|
||||||
|
appWindow.showStatusMessage(currentWallet.errorString, 5);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
onRejected: {
|
onRejected: {
|
||||||
console.log("Canceled");
|
console.log("Canceled");
|
||||||
@@ -1094,7 +1141,11 @@ Rectangle {
|
|||||||
title: qsTr("Please choose a file") + translationManager.emptyString
|
title: qsTr("Please choose a file") + translationManager.emptyString
|
||||||
onAccepted: {
|
onAccepted: {
|
||||||
console.log(walletManager.urlToLocalPath(importKeyImagesDialog.fileUrl))
|
console.log(walletManager.urlToLocalPath(importKeyImagesDialog.fileUrl))
|
||||||
currentWallet.importKeyImages(walletManager.urlToLocalPath(importKeyImagesDialog.fileUrl));
|
if (currentWallet.importKeyImages(walletManager.urlToLocalPath(importKeyImagesDialog.fileUrl))) {
|
||||||
|
appWindow.showStatusMessage(qsTr("Key images successfully imported to wallet") + translationManager.emptyString, 3);
|
||||||
|
} else {
|
||||||
|
appWindow.showStatusMessage(currentWallet.errorString, 5);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
onRejected: {
|
onRejected: {
|
||||||
console.log("Canceled");
|
console.log("Canceled");
|
||||||
|
|||||||
@@ -60,13 +60,13 @@ Rectangle {
|
|||||||
MoneroComponents.Label {
|
MoneroComponents.Label {
|
||||||
id: soloTitleLabel
|
id: soloTitleLabel
|
||||||
fontSize: 24
|
fontSize: 24
|
||||||
text: qsTr("Prove Transaction") + translationManager.emptyString
|
text: qsTr("Prove Transaction") + " / " + qsTr("Reserve") + translationManager.emptyString
|
||||||
}
|
}
|
||||||
|
|
||||||
MoneroComponents.TextPlain {
|
MoneroComponents.TextPlain {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
text: qsTr("Generate a proof of your incoming/outgoing payment by supplying the transaction ID, the recipient address and an optional message. \n" +
|
text: qsTr("Generate a proof of your incoming/outgoing payment by supplying the transaction ID, the recipient address and an optional message. \n" +
|
||||||
"For the case of outgoing payments, you can get a 'Spend Proof' that proves the authorship of a transaction. In this case, you don't need to specify the recipient address.") + translationManager.emptyString
|
"For the case of outgoing payments, you can get a 'Spend Proof' that proves the authorship of a transaction. In this case, you don't need to specify the recipient address.") + qsTr("\nFor reserve proofs you don't need to specify tx id or address.") + translationManager.emptyString
|
||||||
wrapMode: Text.Wrap
|
wrapMode: Text.Wrap
|
||||||
font.family: MoneroComponents.Style.fontRegular.name
|
font.family: MoneroComponents.Style.fontRegular.name
|
||||||
font.pixelSize: 14
|
font.pixelSize: 14
|
||||||
@@ -83,6 +83,7 @@ Rectangle {
|
|||||||
placeholderText: qsTr("Paste tx ID") + translationManager.emptyString
|
placeholderText: qsTr("Paste tx ID") + translationManager.emptyString
|
||||||
readOnly: false
|
readOnly: false
|
||||||
copyButton: true
|
copyButton: true
|
||||||
|
enabled: getReserveProofAmtLine.text.length === 0
|
||||||
}
|
}
|
||||||
|
|
||||||
MoneroComponents.LineEdit {
|
MoneroComponents.LineEdit {
|
||||||
@@ -95,6 +96,38 @@ Rectangle {
|
|||||||
placeholderText: qsTr("Recipient's wallet address") + translationManager.emptyString;
|
placeholderText: qsTr("Recipient's wallet address") + translationManager.emptyString;
|
||||||
readOnly: false
|
readOnly: false
|
||||||
copyButton: true
|
copyButton: true
|
||||||
|
enabled: getReserveProofAmtLine.text.length === 0
|
||||||
|
}
|
||||||
|
|
||||||
|
MoneroComponents.LineEdit {
|
||||||
|
id: getReserveProofAmtLine
|
||||||
|
Layout.fillWidth: true
|
||||||
|
labelFontSize: 14
|
||||||
|
labelText: qsTr("Amount") + translationManager.emptyString
|
||||||
|
fontSize: 16
|
||||||
|
placeholderFontSize: 16
|
||||||
|
placeholderText: qsTr("Paste amount of XMR (reserve proof only)") + translationManager.emptyString
|
||||||
|
readOnly: false
|
||||||
|
copyButton: true
|
||||||
|
enabled: getProofAddressLine.text.length === 0 && getProofTxIdLine.text.length === 0
|
||||||
|
onTextChanged: {
|
||||||
|
text = text.trim().replace(",", ".");
|
||||||
|
const match = text.match(/^0+(\d.*)/);
|
||||||
|
if (match) {
|
||||||
|
const cursorPosition = cursorPosition;
|
||||||
|
text = match[1];
|
||||||
|
cursorPosition = Math.max(cursorPosition, 1) - 1;
|
||||||
|
} else if(text.indexOf('.') === 0) {
|
||||||
|
text = '0' + text;
|
||||||
|
if (text.length > 2) {
|
||||||
|
cursorPosition = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
error = walletManager.amountFromString(text) > appWindow.getUnlockedBalance();
|
||||||
|
}
|
||||||
|
validator: RegExpValidator {
|
||||||
|
regExp: /^\s*(\d{1,8})?([\.,]\d{1,12})?\s*$/
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MoneroComponents.LineEdit {
|
MoneroComponents.LineEdit {
|
||||||
@@ -113,10 +146,10 @@ Rectangle {
|
|||||||
Layout.topMargin: 16
|
Layout.topMargin: 16
|
||||||
small: true
|
small: true
|
||||||
text: qsTr("Generate") + translationManager.emptyString
|
text: qsTr("Generate") + translationManager.emptyString
|
||||||
enabled: TxUtils.checkTxID(getProofTxIdLine.text) && (getProofAddressLine.text.length == 0 || TxUtils.checkAddress(getProofAddressLine.text, appWindow.persistentSettings.nettype))
|
enabled: TxUtils.checkTxID(getProofTxIdLine.text) && (getProofAddressLine.text.length == 0 || TxUtils.checkAddress(getProofAddressLine.text, appWindow.persistentSettings.nettype)) || getReserveProofAmtLine.text.length != 0 && walletManager.amountFromString(getReserveProofAmtLine.text) < appWindow.getUnlockedBalance() && walletManager.amountFromString(getReserveProofAmtLine.text) > 0
|
||||||
onClicked: {
|
onClicked: {
|
||||||
console.log("getProof: Generate clicked: txid " + getProofTxIdLine.text + ", address " + getProofAddressLine.text + ", message: " + getProofMessageLine.text);
|
console.log("getProof: Generate clicked: txid " + getProofTxIdLine.text + ", address " + getProofAddressLine.text + ", message: " + getProofMessageLine.text);
|
||||||
middlePanel.getProofClicked(getProofTxIdLine.text, getProofAddressLine.text, getProofMessageLine.text)
|
middlePanel.getProofClicked(getProofTxIdLine.text, getProofAddressLine.text, getProofMessageLine.text, getReserveProofAmtLine.text)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,12 +166,12 @@ Rectangle {
|
|||||||
MoneroComponents.Label {
|
MoneroComponents.Label {
|
||||||
id: soloTitleLabel2
|
id: soloTitleLabel2
|
||||||
fontSize: 24
|
fontSize: 24
|
||||||
text: qsTr("Check Transaction") + translationManager.emptyString
|
text: qsTr("Check Transaction") + " / " + qsTr("Reserve") + translationManager.emptyString
|
||||||
}
|
}
|
||||||
|
|
||||||
MoneroComponents.TextPlain {
|
MoneroComponents.TextPlain {
|
||||||
text: qsTr("Verify that funds were paid to an address by supplying the transaction ID, the recipient address, the message used for signing and the signature.\n" +
|
text: qsTr("Verify that funds were paid to an address by supplying the transaction ID, the recipient address, the message used for signing and the signature.\n" +
|
||||||
"For the case with Spend Proof, you don't need to specify the recipient address.") + translationManager.emptyString
|
"For the case with Spend Proof, you don't need to specify the recipient address.") + "\n" + qsTr("Transaction is not needed for reserve proof.") + translationManager.emptyString
|
||||||
wrapMode: Text.Wrap
|
wrapMode: Text.Wrap
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
font.family: MoneroComponents.Style.fontRegular.name
|
font.family: MoneroComponents.Style.fontRegular.name
|
||||||
@@ -189,7 +222,7 @@ Rectangle {
|
|||||||
labelFontSize: 14
|
labelFontSize: 14
|
||||||
labelText: qsTr("Signature") + translationManager.emptyString
|
labelText: qsTr("Signature") + translationManager.emptyString
|
||||||
placeholderFontSize: 16
|
placeholderFontSize: 16
|
||||||
placeholderText: qsTr("Paste tx proof") + translationManager.emptyString;
|
placeholderText: qsTr("Paste tx proof") + " / " + qsTr("reserve proof") + translationManager.emptyString;
|
||||||
readOnly: false
|
readOnly: false
|
||||||
copyButton: true
|
copyButton: true
|
||||||
}
|
}
|
||||||
@@ -198,7 +231,7 @@ Rectangle {
|
|||||||
Layout.topMargin: 16
|
Layout.topMargin: 16
|
||||||
small: true
|
small: true
|
||||||
text: qsTr("Check") + translationManager.emptyString
|
text: qsTr("Check") + translationManager.emptyString
|
||||||
enabled: TxUtils.checkTxID(checkProofTxIdLine.text) && TxUtils.checkSignature(checkProofSignatureLine.text) && ((checkProofSignatureLine.text.indexOf("SpendProofV") === 0 && checkProofAddressLine.text.length == 0) || (checkProofSignatureLine.text.indexOf("SpendProofV") !== 0 && TxUtils.checkAddress(checkProofAddressLine.text, appWindow.persistentSettings.nettype)))
|
enabled: (TxUtils.checkTxID(checkProofTxIdLine.text) && TxUtils.checkSignature(checkProofSignatureLine.text) && ((checkProofSignatureLine.text.indexOf("SpendProofV") === 0 && checkProofAddressLine.text.length == 0) || (checkProofSignatureLine.text.indexOf("SpendProofV") !== 0 && TxUtils.checkAddress(checkProofAddressLine.text, appWindow.persistentSettings.nettype)))) || (TxUtils.checkSignature(checkProofSignatureLine.text) && checkProofSignatureLine.text.indexOf("ReserveProofV") === 0 && TxUtils.checkAddress(checkProofAddressLine.text, appWindow.persistentSettings.nettype))
|
||||||
onClicked: {
|
onClicked: {
|
||||||
console.log("checkProof: Check clicked: txid " + checkProofTxIdLine.text + ", address " + checkProofAddressLine.text + ", message " + checkProofMessageLine.text + ", signature " + checkProofSignatureLine.text);
|
console.log("checkProof: Check clicked: txid " + checkProofTxIdLine.text + ", address " + checkProofAddressLine.text + ", message " + checkProofMessageLine.text + ", signature " + checkProofSignatureLine.text);
|
||||||
middlePanel.checkProofClicked(checkProofTxIdLine.text, checkProofAddressLine.text, checkProofMessageLine.text, checkProofSignatureLine.text)
|
middlePanel.checkProofClicked(checkProofTxIdLine.text, checkProofAddressLine.text, checkProofMessageLine.text, checkProofSignatureLine.text)
|
||||||
|
|||||||
@@ -211,7 +211,7 @@ Item {
|
|||||||
|
|
||||||
smooth: false
|
smooth: false
|
||||||
fillMode: Image.PreserveAspectFit
|
fillMode: Image.PreserveAspectFit
|
||||||
source: "image://qrcode/" + TxUtils.makeQRCodeString(appWindow.current_address, amountToReceive.text)
|
source: "image://qrcode/" + walletManager.make_uri(appWindow.current_address, walletManager.amountFromString(amountToReceive.text))
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
@@ -400,7 +400,7 @@ Item {
|
|||||||
font.pixelSize: 12
|
font.pixelSize: 12
|
||||||
font.bold: true
|
font.bold: true
|
||||||
color: _color
|
color: _color
|
||||||
text: TxUtils.makeQRCodeString(appWindow.current_address, amountToReceive.text)
|
text: walletManager.make_uri(appWindow.current_address, walletManager.amountFromString(amountToReceive.text))
|
||||||
themeTransition: false
|
themeTransition: false
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
@@ -685,7 +685,7 @@ Item {
|
|||||||
selectExisting: false
|
selectExisting: false
|
||||||
nameFilters: ["Image (*.png)"]
|
nameFilters: ["Image (*.png)"]
|
||||||
onAccepted: {
|
onAccepted: {
|
||||||
if(!walletManager.saveQrCode(TxUtils.makeQRCodeString(appWindow.current_address, amountToReceive.text), walletManager.urlToLocalPath(fileUrl))) {
|
if (!walletManager.saveQrCode(walletManager.make_uri(appWindow.current_address, walletManager.amountFromString(amountToReceive.text)), walletManager.urlToLocalPath(fileUrl))) {
|
||||||
console.log("Failed to save QrCode to file " + walletManager.urlToLocalPath(fileUrl) )
|
console.log("Failed to save QrCode to file " + walletManager.urlToLocalPath(fileUrl) )
|
||||||
receivePageDialog.title = qsTr("Save QrCode") + translationManager.emptyString;
|
receivePageDialog.title = qsTr("Save QrCode") + translationManager.emptyString;
|
||||||
receivePageDialog.text = qsTr("Failed to save QrCode to ") + walletManager.urlToLocalPath(fileUrl) + translationManager.emptyString;
|
receivePageDialog.text = qsTr("Failed to save QrCode to ") + walletManager.urlToLocalPath(fileUrl) + translationManager.emptyString;
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ ColumnLayout {
|
|||||||
property alias settingsStateViewState: settingsStateView.state
|
property alias settingsStateViewState: settingsStateView.state
|
||||||
|
|
||||||
MoneroComponents.Navbar {
|
MoneroComponents.Navbar {
|
||||||
|
id: navbarId
|
||||||
Layout.alignment: Qt.AlignHCenter
|
Layout.alignment: Qt.AlignHCenter
|
||||||
Layout.topMargin: height
|
Layout.topMargin: height
|
||||||
Layout.bottomMargin: height
|
Layout.bottomMargin: height
|
||||||
@@ -145,7 +146,7 @@ ColumnLayout {
|
|||||||
PropertyAnimation {
|
PropertyAnimation {
|
||||||
target: enterItem
|
target: enterItem
|
||||||
property: "x"
|
property: "x"
|
||||||
from: 0 - target.width
|
from: (navbarId.currentIndex < navbarId.previousIndex ? 1 : -1) * - target.width
|
||||||
to: 0
|
to: 0
|
||||||
duration: 300
|
duration: 300
|
||||||
easing.type: Easing.OutCubic
|
easing.type: Easing.OutCubic
|
||||||
@@ -154,7 +155,7 @@ ColumnLayout {
|
|||||||
target: exitItem
|
target: exitItem
|
||||||
property: "x"
|
property: "x"
|
||||||
from: 0
|
from: 0
|
||||||
to: target.width
|
to: (navbarId.currentIndex < navbarId.previousIndex ? 1 : -1) * target.width
|
||||||
duration: 300
|
duration: 300
|
||||||
easing.type: Easing.OutCubic
|
easing.type: Easing.OutCubic
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -409,7 +409,7 @@ Rectangle {
|
|||||||
small: true
|
small: true
|
||||||
text: qsTr("Donate to Monero") + translationManager.emptyString
|
text: qsTr("Donate to Monero") + translationManager.emptyString
|
||||||
onClicked: {
|
onClicked: {
|
||||||
middlePanel.sendTo("888tNkZrPN6JsEgekjMnABU4TBzc2Dt29EPAvkRxbANsAnjyPbb3iQ1YBRk1UXcdRsiKc9dhwMVgN5S9cQUiyoogDavup3H", "", "Donation to Monero Core Team");
|
middlePanel.sendTo("888tNkZrPN6JsEgekjMnABU4TBzc2Dt29EPAvkRxbANsAnjyPbb3iQ1YBRk1UXcdRsiKc9dhwMVgN5S9cQUiyoogDavup3H", "", qsTr("Donation to Monero Core Team") + translationManager.emptyString);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -165,7 +165,6 @@ Rectangle {
|
|||||||
if (!checked) {
|
if (!checked) {
|
||||||
console.log("Disabled price conversion");
|
console.log("Disabled price conversion");
|
||||||
persistentSettings.fiatPriceEnabled = false;
|
persistentSettings.fiatPriceEnabled = false;
|
||||||
appWindow.fiatTimerStop();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -232,8 +231,6 @@ Rectangle {
|
|||||||
onClicked: {
|
onClicked: {
|
||||||
console.log("Enabled price conversion");
|
console.log("Enabled price conversion");
|
||||||
persistentSettings.fiatPriceEnabled = true;
|
persistentSettings.fiatPriceEnabled = true;
|
||||||
appWindow.fiatApiRefresh();
|
|
||||||
appWindow.fiatTimerStart();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,6 +50,14 @@ Rectangle {
|
|||||||
anchors.topMargin: 0
|
anchors.topMargin: 0
|
||||||
spacing: 0
|
spacing: 0
|
||||||
|
|
||||||
|
MoneroComponents.SettingsListItem {
|
||||||
|
iconText: FontAwesome.lock
|
||||||
|
description: qsTr("Locks the wallet on demand.") + translationManager.emptyString
|
||||||
|
title: qsTr("Lock this wallet") + translationManager.emptyString
|
||||||
|
symbol: (isMac ? "⌃" : qsTr("Ctrl+")) + "L" + translationManager.emptyString
|
||||||
|
onClicked: appWindow.lock();
|
||||||
|
}
|
||||||
|
|
||||||
MoneroComponents.SettingsListItem {
|
MoneroComponents.SettingsListItem {
|
||||||
iconText: FontAwesome.signOutAlt
|
iconText: FontAwesome.signOutAlt
|
||||||
description: qsTr("Logs out of this wallet.") + translationManager.emptyString
|
description: qsTr("Logs out of this wallet.") + translationManager.emptyString
|
||||||
@@ -91,6 +99,7 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
MoneroComponents.SettingsListItem {
|
MoneroComponents.SettingsListItem {
|
||||||
|
enabled: leftPanel.progressBar.fillLevel == 100
|
||||||
iconText: FontAwesome.repeat
|
iconText: FontAwesome.repeat
|
||||||
description: qsTr("Use this feature if you think the shown balance is not accurate.") + translationManager.emptyString
|
description: qsTr("Use this feature if you think the shown balance is not accurate.") + translationManager.emptyString
|
||||||
title: qsTr("Rescan wallet balance") + translationManager.emptyString
|
title: qsTr("Rescan wallet balance") + translationManager.emptyString
|
||||||
@@ -100,7 +109,11 @@ Rectangle {
|
|||||||
if (!currentWallet.rescanSpent()) {
|
if (!currentWallet.rescanSpent()) {
|
||||||
console.error("Error: ", currentWallet.errorString);
|
console.error("Error: ", currentWallet.errorString);
|
||||||
informationPopup.title = qsTr("Error") + translationManager.emptyString;
|
informationPopup.title = qsTr("Error") + translationManager.emptyString;
|
||||||
informationPopup.text = qsTr("Error: ") + currentWallet.errorString
|
if (currentWallet.errorString == "Rescan spent can only be used with a trusted daemon") {
|
||||||
|
informationPopup.text = qsTr("Error: ") + qsTr("Rescan spent can only be used with a trusted remote node. If you trust the current node you are connected to (%1), you can mark it as trusted in Settings > Node page.").arg(remoteNodesModel.currentRemoteNode().address) + translationManager.emptyString;
|
||||||
|
} else {
|
||||||
|
informationPopup.text = qsTr("Error: ") + currentWallet.errorString;
|
||||||
|
}
|
||||||
informationPopup.icon = StandardIcon.Critical
|
informationPopup.icon = StandardIcon.Critical
|
||||||
informationPopup.onCloseCallback = null
|
informationPopup.onCloseCallback = null
|
||||||
informationPopup.open();
|
informationPopup.open();
|
||||||
|
|||||||
15
qml.qrc
@@ -97,6 +97,9 @@
|
|||||||
<file>lang/flags/gb.png</file>
|
<file>lang/flags/gb.png</file>
|
||||||
<file>lang/flags/us.png</file>
|
<file>lang/flags/us.png</file>
|
||||||
<file>lang/flags/nb_NO.png</file>
|
<file>lang/flags/nb_NO.png</file>
|
||||||
|
<file>lang/flags/el.png</file>
|
||||||
|
<file>lang/flags/vi.png</file>
|
||||||
|
<file>lang/flags/is.png</file>
|
||||||
<file>pages/Receive.qml</file>
|
<file>pages/Receive.qml</file>
|
||||||
<file>pages/TxKey.qml</file>
|
<file>pages/TxKey.qml</file>
|
||||||
<file>pages/SharedRingDB.qml</file>
|
<file>pages/SharedRingDB.qml</file>
|
||||||
@@ -159,8 +162,6 @@
|
|||||||
<file>js/TxUtils.js</file>
|
<file>js/TxUtils.js</file>
|
||||||
<file>images/warning.png</file>
|
<file>images/warning.png</file>
|
||||||
<file>images/warning@2x.png</file>
|
<file>images/warning@2x.png</file>
|
||||||
<file>images/rightArrowInactive.png</file>
|
|
||||||
<file>images/rightArrowInactive@2x.png</file>
|
|
||||||
<file>js/Windows.js</file>
|
<file>js/Windows.js</file>
|
||||||
<file>js/Utils.js</file>
|
<file>js/Utils.js</file>
|
||||||
<file>components/RadioButton.qml</file>
|
<file>components/RadioButton.qml</file>
|
||||||
@@ -215,6 +216,16 @@
|
|||||||
<file>images/restore-wallet-from-hardware.png</file>
|
<file>images/restore-wallet-from-hardware.png</file>
|
||||||
<file>images/open-wallet-from-file@2x.png</file>
|
<file>images/open-wallet-from-file@2x.png</file>
|
||||||
<file>images/open-wallet-from-file.png</file>
|
<file>images/open-wallet-from-file.png</file>
|
||||||
|
<file>images/open-wallet-from-file-mainnet@2x.png</file>
|
||||||
|
<file>images/open-wallet-from-file-mainnet.png</file>
|
||||||
|
<file>images/open-wallet-from-file-stagenet@2x.png</file>
|
||||||
|
<file>images/open-wallet-from-file-stagenet.png</file>
|
||||||
|
<file>images/open-wallet-from-file-testnet@2x.png</file>
|
||||||
|
<file>images/open-wallet-from-file-testnet.png</file>
|
||||||
|
<file>images/open-wallet-from-file-view-only@2x.png</file>
|
||||||
|
<file>images/open-wallet-from-file-view-only.png</file>
|
||||||
|
<file>images/open-wallet-from-file-trezor@2x.png</file>
|
||||||
|
<file>images/open-wallet-from-file-trezor.png</file>
|
||||||
<file>images/restore-wallet@2x.png</file>
|
<file>images/restore-wallet@2x.png</file>
|
||||||
<file>images/restore-wallet.png</file>
|
<file>images/restore-wallet.png</file>
|
||||||
<file>images/create-wallet@2x.png</file>
|
<file>images/create-wallet@2x.png</file>
|
||||||
|
|||||||
@@ -36,6 +36,8 @@ file(GLOB SOURCE_FILES
|
|||||||
"libwalletqt/UnsignedTransaction.h"
|
"libwalletqt/UnsignedTransaction.h"
|
||||||
"daemon/*.h"
|
"daemon/*.h"
|
||||||
"daemon/*.cpp"
|
"daemon/*.cpp"
|
||||||
|
"p2pool/*.h"
|
||||||
|
"p2pool/*.cpp"
|
||||||
"model/*.h"
|
"model/*.h"
|
||||||
"model/*.cpp"
|
"model/*.cpp"
|
||||||
"qt/*.h"
|
"qt/*.h"
|
||||||
@@ -97,13 +99,12 @@ target_include_directories(monero-wallet-gui PUBLIC
|
|||||||
${CMAKE_SOURCE_DIR}/monero/external/qrcodegen
|
${CMAKE_SOURCE_DIR}/monero/external/qrcodegen
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}
|
${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/daemon
|
${CMAKE_CURRENT_SOURCE_DIR}/daemon
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/p2pool
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/libwalletqt
|
${CMAKE_CURRENT_SOURCE_DIR}/libwalletqt
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/model
|
${CMAKE_CURRENT_SOURCE_DIR}/model
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/QR-Code-scanner
|
${CMAKE_CURRENT_SOURCE_DIR}/QR-Code-scanner
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/zxcvbn-c
|
${CMAKE_CURRENT_SOURCE_DIR}/zxcvbn-c
|
||||||
${X11_INCLUDE_DIR}
|
${X11_INCLUDE_DIR}
|
||||||
${Boost_INCLUDE_DIRS}
|
|
||||||
${OPENSSL_INCLUDE_DIR}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
target_compile_definitions(monero-wallet-gui
|
target_compile_definitions(monero-wallet-gui
|
||||||
@@ -124,13 +125,13 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Widgets_EXECUTABLE_COMPILE_FLAGS}")
|
|||||||
|
|
||||||
target_link_libraries(monero-wallet-gui
|
target_link_libraries(monero-wallet-gui
|
||||||
epee
|
epee
|
||||||
|
common
|
||||||
|
net
|
||||||
wallet_api
|
wallet_api
|
||||||
qrcodegen
|
qrcodegen
|
||||||
easylogging
|
easylogging
|
||||||
${Boost_LIBRARIES}
|
|
||||||
${QT5_LIBRARIES}
|
${QT5_LIBRARIES}
|
||||||
${EXTRA_LIBRARIES}
|
${EXTRA_LIBRARIES}
|
||||||
${ICU_LIBRARIES}
|
|
||||||
openpgp
|
openpgp
|
||||||
qrdecoder
|
qrdecoder
|
||||||
translations
|
translations
|
||||||
|
|||||||
@@ -132,3 +132,19 @@ QString AddressBook::getDescription(const QString &address) const
|
|||||||
}
|
}
|
||||||
return QString::fromStdString(m_rows.value(*it)->getDescription());
|
return QString::fromStdString(m_rows.value(*it)->getDescription());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AddressBook::setDescription(int index, const QString &description)
|
||||||
|
{
|
||||||
|
bool result;
|
||||||
|
|
||||||
|
{
|
||||||
|
QWriteLocker locker(&m_lock);
|
||||||
|
|
||||||
|
result = m_addressBookImpl->setDescription(index, description.toStdString());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
getAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ public:
|
|||||||
Q_INVOKABLE QString errorString() const;
|
Q_INVOKABLE QString errorString() const;
|
||||||
Q_INVOKABLE int errorCode() const;
|
Q_INVOKABLE int errorCode() const;
|
||||||
Q_INVOKABLE QString getDescription(const QString &address) const;
|
Q_INVOKABLE QString getDescription(const QString &address) const;
|
||||||
|
Q_INVOKABLE void setDescription(int index, const QString &label);
|
||||||
|
|
||||||
enum ErrorCode {
|
enum ErrorCode {
|
||||||
Status_Ok,
|
Status_Ok,
|
||||||
|
|||||||
@@ -170,7 +170,7 @@ QString TransactionHistory::writeCSV(quint32 accountIndex, QString out)
|
|||||||
|
|
||||||
// write header
|
// write header
|
||||||
QTextStream output(&data);
|
QTextStream output(&data);
|
||||||
output << "blockHeight,epoch,date,direction,amount,atomicAmount,fee,txid,label,subaddrAccount,paymentId\n";
|
output << "blockHeight,epoch,date,direction,amount,atomicAmount,fee,txid,label,subaddrAccount,paymentId,description\n";
|
||||||
|
|
||||||
QReadLocker locker(&m_lock);
|
QReadLocker locker(&m_lock);
|
||||||
for (const auto &tx : m_pimpl->getAll()) {
|
for (const auto &tx : m_pimpl->getAll()) {
|
||||||
@@ -198,6 +198,8 @@ QString TransactionHistory::writeCSV(quint32 accountIndex, QString out)
|
|||||||
}
|
}
|
||||||
QString label = info.label();
|
QString label = info.label();
|
||||||
label.remove(QChar('"')); // reserved
|
label.remove(QChar('"')); // reserved
|
||||||
|
QString description = info.description();
|
||||||
|
description.remove(QChar('"')); // reserved
|
||||||
quint64 blockHeight = info.blockHeight();
|
quint64 blockHeight = info.blockHeight();
|
||||||
QDateTime timeStamp = info.timestamp();
|
QDateTime timeStamp = info.timestamp();
|
||||||
QString date = info.date() + " " + info.time();
|
QString date = info.date() + " " + info.time();
|
||||||
@@ -209,11 +211,11 @@ QString TransactionHistory::writeCSV(quint32 accountIndex, QString out)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// format and write
|
// format and write
|
||||||
QString line = QString("%1,%2,%3,%4,%5,%6,%7,%8,\"%9\",%10,%11\n")
|
QString line = QString("%1,%2,%3,%4,%5,%6,%7,%8,\"%9\",%10,%11,\"%12\"\n")
|
||||||
.arg(QString::number(blockHeight), QString::number(epoch), date)
|
.arg(QString::number(blockHeight), QString::number(epoch), date)
|
||||||
.arg(direction, displayAmount, QString::number(atomicAmount))
|
.arg(direction, displayAmount, QString::number(atomicAmount))
|
||||||
.arg(info.fee(), info.hash(), label, QString::number(subaddrAccount))
|
.arg(info.fee(), info.hash(), label, QString::number(subaddrAccount))
|
||||||
.arg(paymentId);
|
.arg(paymentId, description);
|
||||||
output << line;
|
output << line;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -47,6 +47,10 @@ bool TransactionInfo::isFailed() const
|
|||||||
return m_failed;
|
return m_failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool TransactionInfo::isCoinbase() const
|
||||||
|
{
|
||||||
|
return m_coinbase;
|
||||||
|
}
|
||||||
|
|
||||||
double TransactionInfo::amount() const
|
double TransactionInfo::amount() const
|
||||||
{
|
{
|
||||||
@@ -126,6 +130,11 @@ QString TransactionInfo::paymentId() const
|
|||||||
return m_paymentId;
|
return m_paymentId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString TransactionInfo::description() const
|
||||||
|
{
|
||||||
|
return m_description;
|
||||||
|
}
|
||||||
|
|
||||||
QString TransactionInfo::destinations_formatted() const
|
QString TransactionInfo::destinations_formatted() const
|
||||||
{
|
{
|
||||||
QString destinations;
|
QString destinations;
|
||||||
@@ -144,10 +153,12 @@ TransactionInfo::TransactionInfo(const Monero::TransactionInfo *pimpl, QObject *
|
|||||||
, m_confirmations(pimpl->confirmations())
|
, m_confirmations(pimpl->confirmations())
|
||||||
, m_direction(static_cast<Direction>(pimpl->direction()))
|
, m_direction(static_cast<Direction>(pimpl->direction()))
|
||||||
, m_failed(pimpl->isFailed())
|
, m_failed(pimpl->isFailed())
|
||||||
|
, m_coinbase(pimpl->isCoinbase())
|
||||||
, m_fee(pimpl->fee())
|
, m_fee(pimpl->fee())
|
||||||
, m_hash(QString::fromStdString(pimpl->hash()))
|
, m_hash(QString::fromStdString(pimpl->hash()))
|
||||||
, m_label(QString::fromStdString(pimpl->label()))
|
, m_label(QString::fromStdString(pimpl->label()))
|
||||||
, m_paymentId(QString::fromStdString(pimpl->paymentId()))
|
, m_paymentId(QString::fromStdString(pimpl->paymentId()))
|
||||||
|
, m_description(QString::fromStdString(pimpl->description()))
|
||||||
, m_pending(pimpl->isPending())
|
, m_pending(pimpl->isPending())
|
||||||
, m_subaddrAccount(pimpl->subaddrAccount())
|
, m_subaddrAccount(pimpl->subaddrAccount())
|
||||||
, m_timestamp(QDateTime::fromTime_t(pimpl->timestamp()))
|
, m_timestamp(QDateTime::fromTime_t(pimpl->timestamp()))
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ class TransactionInfo : public QObject
|
|||||||
Q_PROPERTY(Direction direction READ direction)
|
Q_PROPERTY(Direction direction READ direction)
|
||||||
Q_PROPERTY(bool isPending READ isPending)
|
Q_PROPERTY(bool isPending READ isPending)
|
||||||
Q_PROPERTY(bool isFailed READ isFailed)
|
Q_PROPERTY(bool isFailed READ isFailed)
|
||||||
|
Q_PROPERTY(bool isCoinbase READ isCoinbase)
|
||||||
Q_PROPERTY(double amount READ amount)
|
Q_PROPERTY(double amount READ amount)
|
||||||
Q_PROPERTY(quint64 atomicAmount READ atomicAmount)
|
Q_PROPERTY(quint64 atomicAmount READ atomicAmount)
|
||||||
Q_PROPERTY(QString displayAmount READ displayAmount)
|
Q_PROPERTY(QString displayAmount READ displayAmount)
|
||||||
@@ -57,6 +58,7 @@ class TransactionInfo : public QObject
|
|||||||
Q_PROPERTY(QString date READ date)
|
Q_PROPERTY(QString date READ date)
|
||||||
Q_PROPERTY(QString time READ time)
|
Q_PROPERTY(QString time READ time)
|
||||||
Q_PROPERTY(QString paymentId READ paymentId)
|
Q_PROPERTY(QString paymentId READ paymentId)
|
||||||
|
Q_PROPERTY(QString description READ description)
|
||||||
Q_PROPERTY(QString destinations_formatted READ destinations_formatted)
|
Q_PROPERTY(QString destinations_formatted READ destinations_formatted)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -71,6 +73,7 @@ public:
|
|||||||
Direction direction() const;
|
Direction direction() const;
|
||||||
bool isPending() const;
|
bool isPending() const;
|
||||||
bool isFailed() const;
|
bool isFailed() const;
|
||||||
|
bool isCoinbase() const;
|
||||||
double amount() const;
|
double amount() const;
|
||||||
quint64 atomicAmount() const;
|
quint64 atomicAmount() const;
|
||||||
QString displayAmount() const;
|
QString displayAmount() const;
|
||||||
@@ -87,6 +90,7 @@ public:
|
|||||||
QString date() const;
|
QString date() const;
|
||||||
QString time() const;
|
QString time() const;
|
||||||
QString paymentId() const;
|
QString paymentId() const;
|
||||||
|
QString description() const;
|
||||||
//! only applicable for output transactions
|
//! only applicable for output transactions
|
||||||
//! used in tx details popup
|
//! used in tx details popup
|
||||||
QString destinations_formatted() const;
|
QString destinations_formatted() const;
|
||||||
@@ -104,7 +108,9 @@ private:
|
|||||||
QString m_hash;
|
QString m_hash;
|
||||||
QString m_label;
|
QString m_label;
|
||||||
QString m_paymentId;
|
QString m_paymentId;
|
||||||
|
QString m_description;
|
||||||
bool m_pending;
|
bool m_pending;
|
||||||
|
bool m_coinbase;
|
||||||
quint32 m_subaddrAccount;
|
quint32 m_subaddrAccount;
|
||||||
QSet<quint32> m_subaddrIndex;
|
QSet<quint32> m_subaddrIndex;
|
||||||
QDateTime m_timestamp;
|
QDateTime m_timestamp;
|
||||||
|
|||||||
@@ -489,9 +489,9 @@ quint64 Wallet::daemonBlockChainTargetHeight() const
|
|||||||
return m_daemonBlockChainTargetHeight;
|
return m_daemonBlockChainTargetHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Wallet::exportKeyImages(const QString& path)
|
bool Wallet::exportKeyImages(const QString& path, bool all)
|
||||||
{
|
{
|
||||||
return m_walletImpl->exportKeyImages(path.toStdString());
|
return m_walletImpl->exportKeyImages(path.toStdString(), all);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Wallet::importKeyImages(const QString& path)
|
bool Wallet::importKeyImages(const QString& path)
|
||||||
@@ -499,6 +499,14 @@ 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) {
|
||||||
|
return m_walletImpl->exportOutputs(path.toStdString(), all);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Wallet::importOutputs(const QString& path) {
|
||||||
|
return m_walletImpl->importOutputs(path.toStdString());
|
||||||
|
}
|
||||||
|
|
||||||
bool Wallet::refresh(bool historyAndSubaddresses /* = true */)
|
bool Wallet::refresh(bool historyAndSubaddresses /* = true */)
|
||||||
{
|
{
|
||||||
refreshingSet(true);
|
refreshingSet(true);
|
||||||
@@ -836,6 +844,25 @@ Q_INVOKABLE QString Wallet::checkSpendProof(const QString &txid, const QString &
|
|||||||
return QString::fromStdString(result);
|
return QString::fromStdString(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Q_INVOKABLE QString Wallet::getReserveProof(bool all, quint32 account_index, quint64 amount, const QString &message) const
|
||||||
|
{
|
||||||
|
qDebug("Generating reserve proof");
|
||||||
|
std::string result = m_walletImpl->getReserveProof(all, account_index, amount, message.toStdString());
|
||||||
|
if (result.empty())
|
||||||
|
result = "error|" + m_walletImpl->errorString();
|
||||||
|
return QString::fromStdString(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_INVOKABLE QString Wallet::checkReserveProof(const QString &address, const QString &message, const QString &signature) const
|
||||||
|
{
|
||||||
|
bool good;
|
||||||
|
uint64_t total;
|
||||||
|
uint64_t spent;
|
||||||
|
bool success = m_walletImpl->checkReserveProof(address.toStdString(), message.toStdString(), signature.toStdString(), good, total, spent);
|
||||||
|
std::string result = std::string(success ? "true" : "false") + "|" + std::string(good ? "true" : "false") + "|" + QString::number(total).toStdString() + "|" + QString::number(spent).toStdString();
|
||||||
|
return QString::fromStdString(result);
|
||||||
|
}
|
||||||
|
|
||||||
QString Wallet::signMessage(const QString &message, bool filename) const
|
QString Wallet::signMessage(const QString &message, bool filename) const
|
||||||
{
|
{
|
||||||
if (filename) {
|
if (filename) {
|
||||||
@@ -925,6 +952,12 @@ bool Wallet::parse_uri(const QString &uri, QString &address, QString &payment_id
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString Wallet::make_uri(const QString &address, const quint64 &amount, const QString &tx_description, const QString &recipient_name) const
|
||||||
|
{
|
||||||
|
std::string error;
|
||||||
|
return QString::fromStdString(m_walletImpl->make_uri(address.toStdString(), "", amount, tx_description.toStdString(), recipient_name.toStdString(), error));
|
||||||
|
}
|
||||||
|
|
||||||
bool Wallet::rescanSpent()
|
bool Wallet::rescanSpent()
|
||||||
{
|
{
|
||||||
QMutexLocker locker(&m_asyncMutex);
|
QMutexLocker locker(&m_asyncMutex);
|
||||||
|
|||||||
@@ -205,9 +205,13 @@ public:
|
|||||||
Q_INVOKABLE void refreshHeightAsync();
|
Q_INVOKABLE void refreshHeightAsync();
|
||||||
|
|
||||||
//! export/import key images
|
//! export/import key images
|
||||||
Q_INVOKABLE bool exportKeyImages(const QString& path);
|
Q_INVOKABLE bool exportKeyImages(const QString& path, bool all = false);
|
||||||
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);
|
||||||
|
|
||||||
//! refreshes the wallet
|
//! refreshes the wallet
|
||||||
Q_INVOKABLE bool refresh(bool historyAndSubaddresses = true);
|
Q_INVOKABLE bool refresh(bool historyAndSubaddresses = true);
|
||||||
|
|
||||||
@@ -296,6 +300,8 @@ public:
|
|||||||
|
|
||||||
//! Parse URI
|
//! Parse URI
|
||||||
Q_INVOKABLE bool parse_uri(const QString &uri, QString &address, QString &payment_id, uint64_t &amount, QString &tx_description, QString &recipient_name, QVector<QString> &unknown_parameters, QString &error);
|
Q_INVOKABLE bool parse_uri(const QString &uri, QString &address, QString &payment_id, uint64_t &amount, QString &tx_description, QString &recipient_name, QVector<QString> &unknown_parameters, QString &error);
|
||||||
|
//! Make URI
|
||||||
|
Q_INVOKABLE QString make_uri(const QString &address, const quint64 &amount = 0, const QString &tx_description = "", const QString &recipient_name = "") const;
|
||||||
|
|
||||||
//! Namespace your cacheAttribute keys to avoid collisions
|
//! Namespace your cacheAttribute keys to avoid collisions
|
||||||
Q_INVOKABLE bool setCacheAttribute(const QString &key, const QString &val);
|
Q_INVOKABLE bool setCacheAttribute(const QString &key, const QString &val);
|
||||||
@@ -312,6 +318,8 @@ public:
|
|||||||
Q_INVOKABLE QString 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 QString checkSpendProof(const QString &txid, const QString &message, const QString &signature) const;
|
Q_INVOKABLE QString checkSpendProof(const QString &txid, const QString &message, const QString &signature) const;
|
||||||
|
Q_INVOKABLE QString getReserveProof(bool all, quint32 account_index, quint64 amount, const QString &message) const;
|
||||||
|
Q_INVOKABLE QString checkReserveProof(const QString &address, const QString &message, const QString &signature) const;
|
||||||
// Rescan spent outputs
|
// Rescan spent outputs
|
||||||
Q_INVOKABLE bool rescanSpent();
|
Q_INVOKABLE bool rescanSpent();
|
||||||
|
|
||||||
|
|||||||
@@ -441,6 +441,14 @@ QVariantMap WalletManager::parse_uri_to_object(const QString &uri) const
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString WalletManager::make_uri(const QString &address, const quint64 &amount, const QString &tx_description, const QString &recipient_name) const
|
||||||
|
{
|
||||||
|
QMutexLocker locker(&m_mutex);
|
||||||
|
if (m_currentWallet)
|
||||||
|
return m_currentWallet->make_uri(address, amount, tx_description, recipient_name);
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
void WalletManager::setLogLevel(int logLevel)
|
void WalletManager::setLogLevel(int logLevel)
|
||||||
{
|
{
|
||||||
Monero::WalletManagerFactory::setLogLevel(logLevel);
|
Monero::WalletManagerFactory::setLogLevel(logLevel);
|
||||||
|
|||||||
@@ -179,6 +179,7 @@ public:
|
|||||||
Q_INVOKABLE QString resolveOpenAlias(const QString &address) const;
|
Q_INVOKABLE QString resolveOpenAlias(const QString &address) const;
|
||||||
Q_INVOKABLE bool parse_uri(const QString &uri, QString &address, QString &payment_id, uint64_t &amount, QString &tx_description, QString &recipient_name, QVector<QString> &unknown_parameters, QString &error) const;
|
Q_INVOKABLE bool parse_uri(const QString &uri, QString &address, QString &payment_id, uint64_t &amount, QString &tx_description, QString &recipient_name, QVector<QString> &unknown_parameters, QString &error) const;
|
||||||
Q_INVOKABLE QVariantMap parse_uri_to_object(const QString &uri) const;
|
Q_INVOKABLE QVariantMap parse_uri_to_object(const QString &uri) const;
|
||||||
|
Q_INVOKABLE QString make_uri(const QString &address, const quint64 &amount = 0, const QString &tx_description = "", const QString &recipient_name = "") const;
|
||||||
Q_INVOKABLE bool saveQrCode(const QString &, const QString &) const;
|
Q_INVOKABLE bool saveQrCode(const QString &, const QString &) const;
|
||||||
Q_INVOKABLE void saveQrCodeToClipboard(const QString &) const;
|
Q_INVOKABLE void saveQrCodeToClipboard(const QString &) const;
|
||||||
Q_INVOKABLE void checkUpdatesAsync(
|
Q_INVOKABLE void checkUpdatesAsync(
|
||||||
|
|||||||
@@ -79,6 +79,7 @@
|
|||||||
// IOS exclusions
|
// IOS exclusions
|
||||||
#ifndef Q_OS_IOS
|
#ifndef Q_OS_IOS
|
||||||
#include "daemon/DaemonManager.h"
|
#include "daemon/DaemonManager.h"
|
||||||
|
#include "p2pool/P2PoolManager.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(Q_OS_WIN)
|
#if defined(Q_OS_WIN)
|
||||||
@@ -401,6 +402,8 @@ Verify update binary using 'shasum'-compatible (SHA256 algo) output signed by tw
|
|||||||
#ifndef Q_OS_IOS
|
#ifndef Q_OS_IOS
|
||||||
qmlRegisterUncreatableType<DaemonManager>("moneroComponents.DaemonManager", 1, 0, "DaemonManager",
|
qmlRegisterUncreatableType<DaemonManager>("moneroComponents.DaemonManager", 1, 0, "DaemonManager",
|
||||||
"DaemonManager can't be instantiated directly");
|
"DaemonManager can't be instantiated directly");
|
||||||
|
qmlRegisterUncreatableType<P2PoolManager>("moneroComponents.P2PoolManager", 1, 0, "P2PoolManager",
|
||||||
|
"P2PoolManager can't be instantiated directly");
|
||||||
#endif
|
#endif
|
||||||
qmlRegisterUncreatableType<AddressBookModel>("moneroComponents.AddressBookModel", 1, 0, "AddressBookModel",
|
qmlRegisterUncreatableType<AddressBookModel>("moneroComponents.AddressBookModel", 1, 0, "AddressBookModel",
|
||||||
"AddressBookModel can't be instantiated directly");
|
"AddressBookModel can't be instantiated directly");
|
||||||
@@ -462,7 +465,9 @@ Verify update binary using 'shasum'-compatible (SHA256 algo) output signed by tw
|
|||||||
// Exclude daemon manager from IOS
|
// Exclude daemon manager from IOS
|
||||||
#ifndef Q_OS_IOS
|
#ifndef Q_OS_IOS
|
||||||
DaemonManager daemonManager;
|
DaemonManager daemonManager;
|
||||||
|
P2PoolManager p2poolManager;
|
||||||
engine.rootContext()->setContextProperty("daemonManager", &daemonManager);
|
engine.rootContext()->setContextProperty("daemonManager", &daemonManager);
|
||||||
|
engine.rootContext()->setContextProperty("p2poolManager", &p2poolManager);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
engine.rootContext()->setContextProperty("isWindows", isWindows);
|
engine.rootContext()->setContextProperty("isWindows", isWindows);
|
||||||
@@ -503,6 +508,12 @@ Verify update binary using 'shasum'-compatible (SHA256 algo) output signed by tw
|
|||||||
#endif
|
#endif
|
||||||
engine.rootContext()->setContextProperty("builtWithScanner", builtWithScanner);
|
engine.rootContext()->setContextProperty("builtWithScanner", builtWithScanner);
|
||||||
|
|
||||||
|
bool builtWithDesktopEntry = false;
|
||||||
|
#ifdef WITH_DESKTOP_ENTRY
|
||||||
|
builtWithDesktopEntry = true;
|
||||||
|
#endif
|
||||||
|
engine.rootContext()->setContextProperty("builtWithDesktopEntry", builtWithDesktopEntry);
|
||||||
|
|
||||||
engine.rootContext()->setContextProperty("moneroVersion", MONERO_VERSION_FULL);
|
engine.rootContext()->setContextProperty("moneroVersion", MONERO_VERSION_FULL);
|
||||||
|
|
||||||
// Load main window (context properties needs to be defined obove this line)
|
// Load main window (context properties needs to be defined obove this line)
|
||||||
|
|||||||
238
src/p2pool/P2PoolManager.cpp
Normal file
@@ -0,0 +1,238 @@
|
|||||||
|
// Copyright (c) 2014-2022, The Monero Project
|
||||||
|
//
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
// permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
// conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
|
// of conditions and the following disclaimer in the documentation and/or other
|
||||||
|
// materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||||
|
// used to endorse or promote products derived from this software without specific
|
||||||
|
// prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||||
|
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||||
|
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||||
|
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
#include "P2PoolManager.h"
|
||||||
|
#include "net/http_client.h"
|
||||||
|
#include "common/util.h"
|
||||||
|
#include "qt/utils.h"
|
||||||
|
#include <QElapsedTimer>
|
||||||
|
#include <QFile>
|
||||||
|
#include <QMutexLocker>
|
||||||
|
#include <QFileInfo>
|
||||||
|
#include <QDir>
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QUrl>
|
||||||
|
#include <QtConcurrent/QtConcurrent>
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QProcess>
|
||||||
|
#include <QMap>
|
||||||
|
#include <QCryptographicHash>
|
||||||
|
|
||||||
|
void P2PoolManager::download() {
|
||||||
|
m_scheduler.run([this] {
|
||||||
|
QUrl url;
|
||||||
|
QString fileName;
|
||||||
|
QString validHash;
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
url = "https://github.com/SChernykh/p2pool/releases/download/v1.9/p2pool-v1.9-windows-x64.zip";
|
||||||
|
fileName = "p2pool-v1.9-windows-x64.zip";
|
||||||
|
validHash = "2587903dc04a4879dca2b6f5c5b584e869928e716274a7660e24b219c9f18839";
|
||||||
|
#elif defined(Q_OS_LINUX)
|
||||||
|
url = "https://github.com/SChernykh/p2pool/releases/download/v1.9/p2pool-v1.9-linux-x64.tar.gz";
|
||||||
|
fileName = "p2pool-v1.9-linux-x64.tar.gz";
|
||||||
|
validHash = "0cd85d933ac4a76708d326698d9db3155bb29d0be82984c735fabd9e9a351b8e";
|
||||||
|
#elif defined(Q_OS_MACOS)
|
||||||
|
url = "https://github.com/SChernykh/p2pool/releases/download/v1.9/p2pool-v1.9-macos-x64.tar.gz";
|
||||||
|
fileName = "p2pool-v1.9-macos-x64.tar.gz";
|
||||||
|
validHash = "47fbdd69d719da80597dd5487f109b61e30b540499cced7b93de1ee01344351e";
|
||||||
|
#endif
|
||||||
|
QFile file(fileName);
|
||||||
|
epee::net_utils::http::http_simple_client http_client;
|
||||||
|
const epee::net_utils::http::http_response_info* response = NULL;
|
||||||
|
std::string userAgent = randomUserAgent().toStdString();
|
||||||
|
std::chrono::milliseconds timeout = std::chrono::seconds(10);
|
||||||
|
http_client.set_server(url.host().toStdString(), "443", {});
|
||||||
|
bool success = http_client.invoke_get(url.path().toStdString(), timeout, {}, std::addressof(response), {{"User-Agent", userAgent}});
|
||||||
|
if (response->m_response_code == 302) {
|
||||||
|
epee::net_utils::http::fields_list fields = response->m_header_info.m_etc_fields;
|
||||||
|
for (std::pair<std::string, std::string> i : fields) {
|
||||||
|
if (i.first == "Location") {
|
||||||
|
url = QString::fromStdString(i.second);
|
||||||
|
http_client.set_server(url.host().toStdString(), "443", {});
|
||||||
|
std::string query = url.query(QUrl::FullyEncoded).toStdString();
|
||||||
|
std::string path = url.path().toStdString() + "?" + query;
|
||||||
|
http_client.wipe_response();
|
||||||
|
success = http_client.invoke_get(path, timeout, {}, std::addressof(response), {{"User-Agent", userAgent}});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!success) {
|
||||||
|
emit p2poolDownloadFailure();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
std::string stringData = response->m_body;
|
||||||
|
QByteArray data(stringData.c_str(), stringData.length());
|
||||||
|
QByteArray hashData = QCryptographicHash::hash(data, QCryptographicHash::Sha256);
|
||||||
|
QString hash = hashData.toHex();
|
||||||
|
if (hash != validHash) {
|
||||||
|
emit p2poolDownloadFailure();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
file.open(QIODevice::WriteOnly);
|
||||||
|
file.write(data);
|
||||||
|
file.close();
|
||||||
|
QProcess::execute("tar", {"-xzf", fileName, "--strip=1", "-C", QApplication::applicationDirPath()});
|
||||||
|
QFile::remove(fileName);
|
||||||
|
if (isInstalled()) {
|
||||||
|
emit p2poolDownloadSuccess();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
emit p2poolDownloadFailure();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool P2PoolManager::isInstalled() {
|
||||||
|
if (!QFileInfo(m_p2pool).isFile())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void P2PoolManager::getStatus() {
|
||||||
|
QString statsPath = QApplication::applicationDirPath() + "/stats/local/miner";
|
||||||
|
bool status = true;
|
||||||
|
if (!QFileInfo(statsPath).isFile() || !started)
|
||||||
|
{
|
||||||
|
status = started;
|
||||||
|
emit p2poolStatus(status, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QFile statsFile(statsPath);
|
||||||
|
statsFile.open(QIODevice::ReadOnly);
|
||||||
|
QTextStream statsOut(&statsFile);
|
||||||
|
QByteArray data;
|
||||||
|
statsOut >> data;
|
||||||
|
statsFile.close();
|
||||||
|
QJsonDocument json = QJsonDocument::fromJson(data);
|
||||||
|
QJsonObject jsonObj = json.object();
|
||||||
|
int hashrate = jsonObj.value("current_hashrate").toInt();
|
||||||
|
emit p2poolStatus(status, hashrate);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool P2PoolManager::start(const QString &flags, const QString &address, const QString &chain, const QString &threads)
|
||||||
|
{
|
||||||
|
// prepare command line arguments and pass to p2pool
|
||||||
|
QStringList arguments;
|
||||||
|
|
||||||
|
// Custom startup flags for p2pool
|
||||||
|
foreach (const QString &str, flags.split(" ")) {
|
||||||
|
qDebug() << QString(" [%1] ").arg(str);
|
||||||
|
if (!str.isEmpty())
|
||||||
|
arguments << str;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!arguments.contains("--local-api")) {
|
||||||
|
arguments << "--local-api";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!arguments.contains("--data-api")) {
|
||||||
|
QDir dir;
|
||||||
|
QString dirName = QApplication::applicationDirPath() + "/stats/";
|
||||||
|
QDir statsDir(dirName);
|
||||||
|
if (dir.exists(dirName)) {
|
||||||
|
statsDir.removeRecursively();
|
||||||
|
}
|
||||||
|
dir.mkdir(dirName);
|
||||||
|
arguments << "--data-api" << dirName;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!arguments.contains("--start-mining")) {
|
||||||
|
arguments << "--start-mining" << threads;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chain == "mini") {
|
||||||
|
arguments << "--mini";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!arguments.contains("--wallet")) {
|
||||||
|
arguments << "--wallet" << address;
|
||||||
|
}
|
||||||
|
|
||||||
|
qDebug() << "starting p2pool " + m_p2pool;
|
||||||
|
qDebug() << "With command line arguments " << arguments;
|
||||||
|
|
||||||
|
QMutexLocker locker(&m_p2poolMutex);
|
||||||
|
|
||||||
|
m_p2poold.reset(new QProcess());
|
||||||
|
|
||||||
|
// Set program parameters
|
||||||
|
m_p2poold->setProgram(m_p2pool);
|
||||||
|
m_p2poold->setArguments(arguments);
|
||||||
|
m_p2poold->setWorkingDirectory(QApplication::applicationDirPath());
|
||||||
|
|
||||||
|
// Start p2pool
|
||||||
|
started = m_p2poold->startDetached();
|
||||||
|
|
||||||
|
if (!started) {
|
||||||
|
qDebug() << "P2Pool start error: " + m_p2poold->errorString();
|
||||||
|
emit p2poolStartFailure();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void P2PoolManager::exit()
|
||||||
|
{
|
||||||
|
qDebug("P2PoolManager: exit()");
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
QProcess::execute("taskkill", {"/F", "/IM", "p2pool.exe"});
|
||||||
|
#else
|
||||||
|
QProcess::execute("pkill", {"p2pool"});
|
||||||
|
#endif
|
||||||
|
started = false;
|
||||||
|
QString dirName = QApplication::applicationDirPath() + "/stats/";
|
||||||
|
QDir dir(dirName);
|
||||||
|
dir.removeRecursively();
|
||||||
|
}
|
||||||
|
|
||||||
|
P2PoolManager::P2PoolManager(QObject *parent)
|
||||||
|
: QObject(parent)
|
||||||
|
, m_scheduler(this)
|
||||||
|
{
|
||||||
|
started = false;
|
||||||
|
// Platform dependent path to p2pool
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
m_p2pool = QApplication::applicationDirPath() + "/p2pool.exe";
|
||||||
|
#elif defined(Q_OS_UNIX)
|
||||||
|
m_p2pool = QApplication::applicationDirPath() + "/p2pool";
|
||||||
|
#endif
|
||||||
|
if (m_p2pool.length() == 0) {
|
||||||
|
qCritical() << "no p2pool binary defined for current platform";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
P2PoolManager::~P2PoolManager() {
|
||||||
|
m_scheduler.shutdownWaitForFinished();
|
||||||
|
}
|
||||||
@@ -1,21 +1,21 @@
|
|||||||
// Copyright (c) 2014-2019, The Monero Project
|
// Copyright (c) 2014-2022, The Monero Project
|
||||||
//
|
//
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
//
|
//
|
||||||
// Redistribution and use in source and binary forms, with or without modification, are
|
// Redistribution and use in source and binary forms, with or without modification, are
|
||||||
// permitted provided that the following conditions are met:
|
// permitted provided that the following conditions are met:
|
||||||
//
|
//
|
||||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
// conditions and the following disclaimer.
|
// conditions and the following disclaimer.
|
||||||
//
|
//
|
||||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
// of conditions and the following disclaimer in the documentation and/or other
|
// of conditions and the following disclaimer in the documentation and/or other
|
||||||
// materials provided with the distribution.
|
// materials provided with the distribution.
|
||||||
//
|
//
|
||||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||||
// used to endorse or promote products derived from this software without specific
|
// used to endorse or promote products derived from this software without specific
|
||||||
// prior written permission.
|
// prior written permission.
|
||||||
//
|
//
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||||
@@ -26,27 +26,47 @@
|
|||||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
#include <libusb.h>
|
#ifndef P2POOLMANAGER_H
|
||||||
|
#define P2POOLMANAGER_H
|
||||||
|
|
||||||
#define UNUSED(expr) (void)(expr)
|
#include <memory>
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
#include <QMutex>
|
||||||
libusb_device **devs;
|
#include <QObject>
|
||||||
libusb_context *ctx = NULL;
|
#include <QUrl>
|
||||||
|
#include <QProcess>
|
||||||
|
#include "NetworkType.h"
|
||||||
|
#include "qt/FutureScheduler.h"
|
||||||
|
|
||||||
int r = libusb_init(&ctx); UNUSED(r);
|
class P2PoolManager : public QObject
|
||||||
ssize_t cnt = libusb_get_device_list(ctx, &devs); UNUSED(cnt);
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
struct libusb_device_descriptor desc;
|
public:
|
||||||
r = libusb_get_device_descriptor(devs[0], &desc); UNUSED(r);
|
explicit P2PoolManager(QObject *parent = 0);
|
||||||
uint8_t bus_id = libusb_get_bus_number(devs[0]); UNUSED(bus_id);
|
~P2PoolManager();
|
||||||
uint8_t addr = libusb_get_device_address(devs[0]); UNUSED(addr);
|
|
||||||
|
|
||||||
uint8_t tmp_path[16];
|
Q_INVOKABLE bool start(const QString &flags, const QString &address, const QString &chain, const QString &threads);
|
||||||
r = libusb_get_port_numbers(devs[0], tmp_path, sizeof(tmp_path));
|
Q_INVOKABLE void exit();
|
||||||
UNUSED(r);
|
Q_INVOKABLE bool isInstalled();
|
||||||
UNUSED(tmp_path);
|
Q_INVOKABLE void getStatus();
|
||||||
|
Q_INVOKABLE void download();
|
||||||
|
private:
|
||||||
|
|
||||||
libusb_free_device_list(devs, 1);
|
bool running(NetworkType::Type nettype) const;
|
||||||
libusb_exit(ctx);
|
signals:
|
||||||
}
|
void p2poolStartFailure() const;
|
||||||
|
void p2poolStatus(bool isMining, int hashrate) const;
|
||||||
|
void p2poolDownloadFailure() const;
|
||||||
|
void p2poolDownloadSuccess() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<QProcess> m_p2poold;
|
||||||
|
QMutex m_p2poolMutex;
|
||||||
|
QString m_p2pool;
|
||||||
|
bool started = false;
|
||||||
|
|
||||||
|
mutable FutureScheduler m_scheduler;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // P2POOLMANAGER_H
|
||||||
@@ -53,9 +53,6 @@ private:
|
|||||||
return qMakePair(false, QFuture<T>());
|
return qMakePair(false, QFuture<T>());
|
||||||
}
|
}
|
||||||
|
|
||||||
QFutureWatcher<void> schedule(std::function<void()> function);
|
|
||||||
QFutureWatcher<QJSValueList> schedule(std::function<QJSValueList() noexcept> function, const QJSValue &callback);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
size_t Alive;
|
size_t Alive;
|
||||||
QWaitCondition Condition;
|
QWaitCondition Condition;
|
||||||
|
|||||||
@@ -26,6 +26,10 @@
|
|||||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
#if defined(_WIN32) && !defined(MONERO_GUI_STATIC)
|
||||||
|
#include <Winsock2.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "updater.h"
|
#include "updater.h"
|
||||||
|
|
||||||
#include <common/util.h>
|
#include <common/util.h>
|
||||||
|
|||||||
@@ -1 +1,3 @@
|
|||||||
var GUI_VERSION = "@VERSION_TAG_GUI@";
|
var GUI_VERSION_NUMBER = "@VERSION@"
|
||||||
|
var GUI_VERSION_TAG = "@VERSION_TAG_GUI@";
|
||||||
|
var GUI_VERSION = GUI_VERSION_NUMBER + "-" + GUI_VERSION_TAG
|
||||||
|
|||||||
@@ -516,7 +516,7 @@ typedef struct
|
|||||||
uint8_t LeetCnv[sizeof L33TCnv / LEET_NORM_MAP_SIZE + 1];
|
uint8_t LeetCnv[sizeof L33TCnv / LEET_NORM_MAP_SIZE + 1];
|
||||||
/* uint8_t LeetChr[3]; */
|
/* uint8_t LeetChr[3]; */
|
||||||
uint8_t First;
|
uint8_t First;
|
||||||
uint8_t PossChars[48];
|
uint8_t PossChars[49];
|
||||||
} DictWork_t;
|
} DictWork_t;
|
||||||
|
|
||||||
/**********************************************************************************
|
/**********************************************************************************
|
||||||
|
|||||||