Merge pull request #10485 from accumulator/ndk28_qt610_rebase_p4a
p4a rebase, use ndk28 and qt6.10
@@ -33,12 +33,8 @@ RUN apt -y update -qq \
|
||||
|
||||
|
||||
ENV ANDROID_NDK_HOME="${ANDROID_HOME}/android-ndk"
|
||||
#ENV ANDROID_NDK_VERSION="23b"
|
||||
#ENV ANDROID_NDK_HASH="c6e97f9c8cfe5b7be0a9e6c15af8e7a179475b7ded23e2d1c1fa0945d6fb4382"
|
||||
#ENV ANDROID_NDK_VERSION="27d"
|
||||
#ENV ANDROID_NDK_HASH="601246087a682d1944e1e16dd85bc6e49560fe8b6d61255be2829178c8ed15d9"
|
||||
ENV ANDROID_NDK_VERSION="23d-canary"
|
||||
ENV ANDROID_NDK_HASH="6944ffc20ab018ff4ef6a403048d0a99d50a0630c3eae690c8f803c452f46f3e"
|
||||
ENV ANDROID_NDK_VERSION="28c"
|
||||
ENV ANDROID_NDK_HASH="dfb20d396df28ca02a8c708314b814a4d961dc9074f9a161932746f815aa552f"
|
||||
ENV ANDROID_NDK_HOME_V="${ANDROID_NDK_HOME}-r${ANDROID_NDK_VERSION}"
|
||||
|
||||
# get the latest version from https://developer.android.com/ndk/downloads/index.html
|
||||
@@ -48,31 +44,21 @@ ENV ANDROID_NDK_DL_URL="https://dl.google.com/android/repository/${ANDROID_NDK_A
|
||||
# below disabled in favor of CI build download
|
||||
|
||||
# download and install Android NDK
|
||||
#RUN curl --location --progress-bar \
|
||||
# "${ANDROID_NDK_DL_URL}" \
|
||||
# --output "${ANDROID_NDK_ARCHIVE}" \
|
||||
# && echo "${ANDROID_NDK_HASH} ${ANDROID_NDK_ARCHIVE}" | sha256sum -c - \
|
||||
# && mkdir --parents "${ANDROID_NDK_HOME_V}" \
|
||||
# && unzip -q "${ANDROID_NDK_ARCHIVE}" -d "${ANDROID_HOME}" \
|
||||
# && ln -sfn "${ANDROID_NDK_HOME_V}" "${ANDROID_NDK_HOME}" \
|
||||
# && rm -rf "${ANDROID_NDK_ARCHIVE}"
|
||||
|
||||
# temporary build using NDK from CI
|
||||
ENV CI_REV="12186248"
|
||||
ENV CI_NDK_FILE="android-ndk-${CI_REV}-linux-x86_64.zip"
|
||||
COPY contrib/android/dl-ndk-ci.sh /tmp/
|
||||
RUN /tmp/dl-ndk-ci.sh https://ci.android.com/builds/submitted/${CI_REV}/linux/latest/${CI_NDK_FILE} \
|
||||
&& echo "${ANDROID_NDK_HASH} android-ndk-ci-linux-x86_64.zip" | sha256sum -c - \
|
||||
RUN curl --location --progress-bar \
|
||||
"${ANDROID_NDK_DL_URL}" \
|
||||
--output "${ANDROID_NDK_ARCHIVE}" \
|
||||
&& echo "${ANDROID_NDK_HASH} ${ANDROID_NDK_ARCHIVE}" | sha256sum -c - \
|
||||
&& mkdir --parents "${ANDROID_NDK_HOME_V}" \
|
||||
&& unzip -q "android-ndk-ci-linux-x86_64.zip" -d "${ANDROID_HOME}" \
|
||||
&& unzip -q "${ANDROID_NDK_ARCHIVE}" -d "${ANDROID_HOME}" \
|
||||
&& ln -sfn "${ANDROID_NDK_HOME_V}" "${ANDROID_NDK_HOME}" \
|
||||
&& rm -rf "android-ndk-ci-linux-x86_64.zip"
|
||||
&& rm -rf "${ANDROID_NDK_ARCHIVE}"
|
||||
|
||||
ENV ANDROID_SDK_HOME="${ANDROID_HOME}/android-sdk"
|
||||
|
||||
# get the latest version from https://developer.android.com/studio/index.html
|
||||
ENV ANDROID_SDK_TOOLS_VERSION="9477386"
|
||||
ENV ANDROID_SDK_HASH="bd1aa17c7ef10066949c88dc6c9c8d536be27f992a1f3b5a584f9bd2ba5646a0"
|
||||
ENV ANDROID_SDK_TOOLS_VERSION="14742923"
|
||||
ENV ANDROID_SDK_HASH="04453066b540409d975c676d781da1477479dde3761310f1a7eb92a1dfb15af7"
|
||||
|
||||
ENV ANDROID_SDK_TOOLS_ARCHIVE="commandlinetools-linux-${ANDROID_SDK_TOOLS_VERSION}_latest.zip"
|
||||
ENV ANDROID_SDK_TOOLS_DL_URL="https://dl.google.com/android/repository/${ANDROID_SDK_TOOLS_ARCHIVE}"
|
||||
ENV ANDROID_SDK_MANAGER="${ANDROID_SDK_HOME}/cmdline-tools/bin/sdkmanager --sdk_root=${ANDROID_SDK_HOME}"
|
||||
@@ -130,8 +116,8 @@ RUN apt -y update -qq \
|
||||
RUN yes | ${ANDROID_SDK_MANAGER} --licenses > /dev/null
|
||||
|
||||
|
||||
ENV ANDROID_SDK_BUILD_TOOLS_MAJOR_V="31"
|
||||
ENV ANDROID_SDK_BUILD_TOOLS_VERSION="31.0.0"
|
||||
ENV ANDROID_SDK_BUILD_TOOLS_MAJOR_V="35"
|
||||
ENV ANDROID_SDK_BUILD_TOOLS_VERSION="35.0.0"
|
||||
|
||||
# download platforms, API, build tools
|
||||
RUN ${ANDROID_SDK_MANAGER} "platforms;android-${ANDROID_SDK_BUILD_TOOLS_MAJOR_V}" > /dev/null && \
|
||||
@@ -190,7 +176,6 @@ RUN apt -y update -qq \
|
||||
&& apt -y install -qq --no-install-recommends --allow-downgrades \
|
||||
libopengl-dev \
|
||||
libegl-dev \
|
||||
dos2unix \
|
||||
&& apt -y autoremove \
|
||||
&& apt -y clean
|
||||
|
||||
@@ -250,8 +235,8 @@ RUN cd /opt \
|
||||
&& /opt/venv/bin/python3 -m pip install --no-build-isolation --no-dependencies -e .
|
||||
|
||||
# install python-for-android
|
||||
ENV P4A_CHECKOUT_COMMIT="a01269f7799587ad74ee40e0b642d917b8db7d4e"
|
||||
# ^ from branch electrum_20251211 (note: careful with force-pushing! see #8162)
|
||||
ENV P4A_CHECKOUT_COMMIT="1098be6964cfc2156959e435e81c2c50f8398586"
|
||||
# ^ from branch electrum_202602 (note: careful with force-pushing! see #8162)
|
||||
RUN cd /opt \
|
||||
&& git clone https://github.com/spesmilo/python-for-android \
|
||||
&& cd python-for-android \
|
||||
|
||||
@@ -108,8 +108,6 @@ Run electrum with the `-g` switch: `electrum -g qml`
|
||||
|
||||
Notes:
|
||||
|
||||
- pyqt ~6.4 would work best, as the gui has not yet been adapted to styling changes in 6.5
|
||||
- However, pyqt6 as distributed on PyPI does not include a required module (PyQt6.QtQml) until 6.5
|
||||
- Installing these deps from your OS package manager should also work,
|
||||
except many don't distribute pyqt6 yet.
|
||||
For pyqt5 on debian-based distros, this used to look like this:
|
||||
|
||||
@@ -105,19 +105,19 @@ android.permissions = INTERNET, CAMERA, WRITE_EXTERNAL_STORAGE, POST_NOTIFICATIO
|
||||
|
||||
# (int) Android API to use (compileSdkVersion)
|
||||
# note: when changing, Dockerfile also needs to be changed to install corresponding build tools
|
||||
android.api = 31
|
||||
android.api = 35
|
||||
|
||||
# (int) Android targetSdkVersion
|
||||
android.target_sdk_version = 35
|
||||
|
||||
# (int) Minimum API required. You will need to set the android.ndk_api to be as low as this value.
|
||||
android.minapi = 23
|
||||
android.minapi = 26
|
||||
|
||||
# (str) Android NDK version to use
|
||||
android.ndk = 23b
|
||||
android.ndk = 28c
|
||||
|
||||
# (int) Android NDK API to use (optional). This is the minimum API your app will support.
|
||||
android.ndk_api = 23
|
||||
android.ndk_api = 26
|
||||
|
||||
# (bool) Use --private data storage (True) or --dir public storage (False)
|
||||
#android.private_storage = True
|
||||
@@ -168,7 +168,7 @@ android.add_src = electrum/gui/qml/java_classes/
|
||||
|
||||
# kotlin-stdlib is required for zxing-cpp (BarcodeScannerView)
|
||||
android.gradle_dependencies =
|
||||
com.android.support:support-compat:28.0.0,
|
||||
androidx.core:core:1.16.0,
|
||||
org.jetbrains.kotlin:kotlin-stdlib:1.8.22
|
||||
|
||||
android.add_activities = org.electrum.qr.SimpleScannerActivity, org.electrum.biometry.BiometricActivity
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
#!/bin/sh
|
||||
if [ -z "$1" ]; then
|
||||
echo "missing url"
|
||||
exit 1
|
||||
fi
|
||||
echo $1
|
||||
|
||||
curl $1 | grep "var JSVariables" | python3 -c "import sys; line=sys.stdin.read(); line=line[line.find('{'):-2]; import json; j=json.loads(line); print(j['artifactUrl'])" | wget -i - -O android-ndk-ci-linux-x86_64.zip
|
||||
@@ -0,0 +1,20 @@
|
||||
import os
|
||||
|
||||
from pythonforandroid.recipes.android import AndroidRecipe
|
||||
from pythonforandroid.util import load_source, HashPinnedDependency
|
||||
|
||||
util = load_source('util', os.path.join(os.path.dirname(os.path.dirname(__file__)), 'util.py'))
|
||||
|
||||
|
||||
assert AndroidRecipe.depends == [('sdl3', 'sdl2', 'genericndkbuild', 'qt6'), 'pyjnius', 'python3'], AndroidRecipe.depends
|
||||
assert AndroidRecipe.python_depends == []
|
||||
|
||||
|
||||
class AndroidRecipePinned(util.InheritedRecipeMixin, AndroidRecipe):
|
||||
hostpython_prerequisites = [
|
||||
HashPinnedDependency(package="Cython==3.1.8",
|
||||
hashes=['sha256:282b3c8e6abc3fea421919e862e898ffdd86fc0796009bdb5ffdf8211413219f'])
|
||||
]
|
||||
|
||||
|
||||
recipe = AndroidRecipePinned()
|
||||
@@ -6,14 +6,13 @@ from pythonforandroid.util import load_source
|
||||
util = load_source('util', os.path.join(os.path.dirname(os.path.dirname(__file__)), 'util.py'))
|
||||
|
||||
|
||||
assert CffiRecipe._version == "1.15.1"
|
||||
assert CffiRecipe.depends == ['setuptools', 'pycparser', 'libffi', 'python3']
|
||||
assert CffiRecipe._version == "2.0.0"
|
||||
assert CffiRecipe.depends == ['pycparser', 'libffi', 'python3'], CffiRecipe.depends
|
||||
assert CffiRecipe.python_depends == []
|
||||
|
||||
|
||||
class CffiRecipePinned(util.InheritedRecipeMixin, CffiRecipe):
|
||||
version = "1.17.1"
|
||||
sha512sum = "907129891d56351ca5cb885aae62334ad432321826d6eddfaa32195b4c7b7689a80333e6d14d0aab479a646aba148b9852c0815b80344dfffa4f183a5e74372c"
|
||||
sha512sum = "a71b74e642e11eb50e9bb4ae0e7116bdb3c4a7c9622a3766d84506fa7994c02e09644b41b439b95ca99b0303e91891897cff38018d498eb087e0961f0ad4fb8b"
|
||||
|
||||
|
||||
recipe = CffiRecipePinned()
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import os
|
||||
|
||||
from pythonforandroid.recipes.hostpython3 import HostPython3Recipe
|
||||
from pythonforandroid.util import load_source
|
||||
from pythonforandroid.util import load_source, HashPinnedDependency
|
||||
|
||||
util = load_source('util', os.path.join(os.path.dirname(os.path.dirname(__file__)), 'util.py'))
|
||||
|
||||
@@ -13,7 +13,23 @@ assert HostPython3Recipe.python_depends == []
|
||||
class HostPython3RecipePinned(util.InheritedRecipeMixin, HostPython3Recipe):
|
||||
# PYTHON_VERSION= # < line here so that I can grep the codebase and teleport here
|
||||
version = "3.11.14"
|
||||
sha512sum = "41fb3ae22ce4ac0e8bb6b9ae8db88a810af1001d944e3f1abc9e86824ae4be31347e3e3a70425ab12271c6b7eeef552f00164ef23cfffa2551c3c9d1fe5ab91f"
|
||||
sha512sum = "4642f6d59c76c6e5dbd827fdb28694376a9cc76e513146d092b49afb41513b3c9dff2339cfcebfb5b260f5cdc49a59a69906e284e5d478b2189d3374e9e24fd5"
|
||||
|
||||
# this property overrides the default hostpython dependencies for PyProjectRecipe recipies
|
||||
pyproject_base_dependencies = [
|
||||
HashPinnedDependency(package="build==1.4.0",
|
||||
hashes=['sha256:6a07c1b8eb6f2b311b96fcbdbce5dab5fe637ffda0fd83c9cac622e927501596']),
|
||||
HashPinnedDependency(package="pip==24.0",
|
||||
hashes=['sha256:ba0d021a166865d2265246961bec0152ff124de910c5cc39f1156ce3fa7c69dc']),
|
||||
HashPinnedDependency(package="setuptools==80.9.0",
|
||||
hashes=['sha256:062d34222ad13e0cc312a4c02d73f059e86a4acbfbdea8f8f76b28c99f306922']),
|
||||
|
||||
# pin deptree build==1.4.0
|
||||
HashPinnedDependency(package="packaging==26.0",
|
||||
hashes=['sha256:b36f1fef9334a5588b4166f8bcd26a14e521f2b55e6b9de3aaa80d3ff7a37529']),
|
||||
HashPinnedDependency(package="pyproject_hooks==1.2.0",
|
||||
hashes=['sha256:9e5c6bfa8dcc30091c74b0cf803c81fdd29d94f01992a7707bc97babb1141913']),
|
||||
]
|
||||
|
||||
|
||||
recipe = HostPython3RecipePinned()
|
||||
|
||||
@@ -6,7 +6,7 @@ from pythonforandroid.util import load_source
|
||||
util = load_source('util', os.path.join(os.path.dirname(os.path.dirname(__file__)), 'util.py'))
|
||||
|
||||
|
||||
assert OpenSSLRecipe._version == "3.0.18"
|
||||
# assert OpenSSLRecipe._version == "3.3.1"
|
||||
assert OpenSSLRecipe.depends == []
|
||||
assert OpenSSLRecipe.python_depends == []
|
||||
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
from pythonforandroid.recipes.packaging import PackagingRecipe
|
||||
|
||||
|
||||
assert PackagingRecipe._version == "21.3"
|
||||
assert PackagingRecipe._version == "26.0"
|
||||
assert PackagingRecipe.depends == ["setuptools", "pyparsing", "python3"]
|
||||
assert PackagingRecipe.python_depends == []
|
||||
|
||||
|
||||
class PackagingRecipePinned(PackagingRecipe):
|
||||
#version = "21.3"
|
||||
# note: 21.3 is the last version to use setup.py, so newer versions don't work. see comment for PyparsingRecipePinned
|
||||
sha512sum = "2e3aa276a4229ac7dc0654d586799473ced9761a83aa4159660d37ae1a2a8f30e987248dd0e260e2834106b589f259a57ce9936eef0dcc3c430a99ac6b663e05"
|
||||
sha512sum = "27a066a7d65ba76189212973b6a0d162f3d361848b1b0c34a82865cf180b3284a837cc34206c297f002a73feae414e25a26c5960bb884a74ea337f582585f1d2"
|
||||
|
||||
|
||||
recipe = PackagingRecipePinned()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
from pythonforandroid.recipe import PythonRecipe
|
||||
|
||||
from pythonforandroid.util import HashPinnedDependency
|
||||
|
||||
assert PythonRecipe.depends == ['python3']
|
||||
assert PythonRecipe.python_depends == []
|
||||
@@ -9,7 +9,11 @@ class PycryptodomexRecipe(PythonRecipe):
|
||||
version = "3.23.0"
|
||||
sha512sum = "951cebaad2e19b9f9d04fe85c73ab1ff8b515069c1e0e8e3cd6845ec9ccd5ef3e5737259e0934ed4a6536e289dee6aabac58e1c822a5a6393e86b482c60afc89"
|
||||
url = "https://github.com/Legrandin/pycryptodome/archive/v{version}x.tar.gz"
|
||||
depends = ["setuptools", "cffi"]
|
||||
depends = ["cffi"]
|
||||
hostpython_prerequisites = [
|
||||
HashPinnedDependency(package="setuptools==80.9.0",
|
||||
hashes=['sha256:062d34222ad13e0cc312a4c02d73f059e86a4acbfbdea8f8f76b28c99f306922']),
|
||||
]
|
||||
|
||||
|
||||
recipe = PycryptodomexRecipe()
|
||||
|
||||
@@ -1,19 +1,23 @@
|
||||
import os
|
||||
|
||||
from pythonforandroid.recipes.pyjnius import PyjniusRecipe
|
||||
from pythonforandroid.util import load_source
|
||||
from pythonforandroid.util import load_source, HashPinnedDependency
|
||||
|
||||
util = load_source('util', os.path.join(os.path.dirname(os.path.dirname(__file__)), 'util.py'))
|
||||
|
||||
|
||||
assert PyjniusRecipe._version == "1.5.0"
|
||||
assert PyjniusRecipe.depends == [('genericndkbuild', 'sdl2', 'qt6'), 'six', 'python3']
|
||||
assert PyjniusRecipe._version == "1.7.0"
|
||||
assert PyjniusRecipe.depends == [('genericndkbuild', 'sdl2', 'sdl3', 'qt6'), 'six', 'python3'], PyjniusRecipe.depends
|
||||
assert PyjniusRecipe.python_depends == []
|
||||
|
||||
|
||||
class PyjniusRecipePinned(util.InheritedRecipeMixin, PyjniusRecipe):
|
||||
version = "1.6.1"
|
||||
sha512sum = "deb5ac566479111c6f4c6adb895821b263d72bf88414fb093bdfd5ad5d0b7aea56b53d5ef0967e28db360f4fb6fb1c2264123f15c747884799df55848191c424"
|
||||
hostpython_prerequisites = [
|
||||
HashPinnedDependency(package="Cython==3.1.8",
|
||||
hashes=['sha256:282b3c8e6abc3fea421919e862e898ffdd86fc0796009bdb5ffdf8211413219f'])
|
||||
]
|
||||
|
||||
sha512sum = "a192c30ef87ca9601455976feb49f03dfdb8e1bf2545744a7b771a6d0930a56b334c7a2a39d30fb8855c070f16e4673dc5ff6920b04a6155ab5f9247b271df76"
|
||||
|
||||
|
||||
recipe = PyjniusRecipePinned()
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
from pythonforandroid.recipes.pyparsing import PyparsingRecipe
|
||||
from pythonforandroid.util import HashPinnedDependency
|
||||
|
||||
|
||||
assert PyparsingRecipe._version == "3.0.7"
|
||||
@@ -15,5 +16,12 @@ class PyparsingRecipePinned(PyparsingRecipe):
|
||||
# see "PyProjectRecipe" from https://github.com/kivy/python-for-android/pull/3007
|
||||
sha512sum = "1e692f4cdaa6b6e8ca2729d0a3e2ba16d978f1957c538b6de3a4220ec7d996bdbe87c41c43abab851fffa3b0498a05841373e435602917b8c095042e273badb5"
|
||||
|
||||
hostpython_prerequisites = [
|
||||
HashPinnedDependency(package="setuptools==80.9.0",
|
||||
hashes=['sha256:062d34222ad13e0cc312a4c02d73f059e86a4acbfbdea8f8f76b28c99f306922']),
|
||||
HashPinnedDependency(package="pip==24.0",
|
||||
hashes=['sha256:ba0d021a166865d2265246961bec0152ff124de910c5cc39f1156ce3fa7c69dc']),
|
||||
]
|
||||
|
||||
|
||||
recipe = PyparsingRecipePinned()
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
import os
|
||||
|
||||
from pythonforandroid.recipes.pyqt6 import PyQt6Recipe
|
||||
from pythonforandroid.util import load_source
|
||||
from pythonforandroid.util import load_source, HashPinnedDependency
|
||||
|
||||
util = load_source('util', os.path.join(os.path.dirname(os.path.dirname(__file__)), 'util.py'))
|
||||
|
||||
|
||||
assert PyQt6Recipe._version == "6.4.2"
|
||||
assert PyQt6Recipe.depends == ['qt6', 'pyjnius', 'setuptools', 'pyqt6sip', 'hostpython3', 'pyqt_builder']
|
||||
assert PyQt6Recipe._version == "6.10.2"
|
||||
assert PyQt6Recipe.depends == ['qt6', 'pyjnius', 'setuptools', 'pyqt6sip', 'hostpython3', 'pyqt_builder', 'python3'], PyQt6Recipe.depends
|
||||
assert PyQt6Recipe.python_depends == []
|
||||
|
||||
|
||||
class PyQt6RecipePinned(util.InheritedRecipeMixin, PyQt6Recipe):
|
||||
sha512sum = "51e5f0d028ee7984876da1653cb135d61e2c402f18b939a92477888cc7c86d3bc2889477403dee6b3d9f66519ee3236d344323493b4c2c2e658e1637b10e53bf"
|
||||
sha512sum = "d58515d181530fdd71edc3edfa0b647a3aeeb56cbc33f4d7fd0d40a7a99d52298ac5bb4438b5dadea5439759e52cc459e601f1fab5d9afdd61f2a492d0bae1ef"
|
||||
|
||||
|
||||
recipe = PyQt6RecipePinned()
|
||||
|
||||
@@ -1,18 +1,25 @@
|
||||
import os
|
||||
|
||||
from pythonforandroid.recipes.pyqt6sip import PyQt6SipRecipe
|
||||
from pythonforandroid.util import load_source
|
||||
from pythonforandroid.util import load_source, HashPinnedDependency
|
||||
|
||||
util = load_source('util', os.path.join(os.path.dirname(os.path.dirname(__file__)), 'util.py'))
|
||||
|
||||
|
||||
assert PyQt6SipRecipe._version == "13.5.1"
|
||||
assert PyQt6SipRecipe.depends == ['setuptools', 'python3']
|
||||
assert PyQt6SipRecipe._version == "13.10.3"
|
||||
assert PyQt6SipRecipe.depends == ['python3']
|
||||
assert PyQt6SipRecipe.python_depends == []
|
||||
|
||||
|
||||
class PyQt6SipRecipePinned(util.InheritedRecipeMixin, PyQt6SipRecipe):
|
||||
sha512sum = "1e4170d167a326afe6df86e4a35e209299548054981cb2e5d56da234ef9db4d8594bcb05b6be363c3bc6252776ae9de63d589a3d9f33fba8250d39cdb5e9061a"
|
||||
sha512sum = "555b061eec3db6a66388fae07de21f58d756f6f12b13e4ede729c3348d2c8997ac5a59d3006ee45c3a09b5cde673f579265fa254bc583a4ba721748cf8f3a617"
|
||||
|
||||
hostpython_prerequisites = [
|
||||
HashPinnedDependency(package="setuptools==80.9.0",
|
||||
hashes=['sha256:062d34222ad13e0cc312a4c02d73f059e86a4acbfbdea8f8f76b28c99f306922']),
|
||||
HashPinnedDependency(package="packaging==26.0",
|
||||
hashes=['sha256:b36f1fef9334a5588b4166f8bcd26a14e521f2b55e6b9de3aaa80d3ff7a37529']),
|
||||
]
|
||||
|
||||
|
||||
recipe = PyQt6SipRecipePinned()
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
from pythonforandroid.recipes.pyqt_builder import PyQtBuilderRecipe
|
||||
from pythonforandroid.util import HashPinnedDependency
|
||||
|
||||
|
||||
assert PyQtBuilderRecipe._version == "1.15.1"
|
||||
assert PyQtBuilderRecipe.depends == ["sip", "packaging", "python3"]
|
||||
assert PyQtBuilderRecipe._version == "1.19.1"
|
||||
assert PyQtBuilderRecipe.depends == ["sip", "python3"], PyQtBuilderRecipe.depends
|
||||
assert PyQtBuilderRecipe.python_depends == []
|
||||
|
||||
|
||||
class PyQtBuilderRecipePinned(PyQtBuilderRecipe):
|
||||
sha512sum = "61ee73b6bb922c04739da60025ab50d35d345d2e298943305fcbd3926cda31d732cc5e5b0dbfc39f5eb85c0f0b091b8c3f5fee00dcc240d7849c5c4191c1368a"
|
||||
sha512sum = "2308c51f93c37b1d13f312e4f2475d26b22d374ef284925fead9eab4aa89b994770431aca45170ac2154b4813fff151798f113f56d4cbf6c6e544fb463104a6d"
|
||||
|
||||
|
||||
recipe = PyQtBuilderRecipePinned()
|
||||
|
||||
@@ -13,7 +13,7 @@ assert Python3Recipe.python_depends == []
|
||||
class Python3RecipePinned(util.InheritedRecipeMixin, Python3Recipe):
|
||||
# PYTHON_VERSION= # < line here so that I can grep the codebase and teleport here
|
||||
version = "3.11.14"
|
||||
sha512sum = "41fb3ae22ce4ac0e8bb6b9ae8db88a810af1001d944e3f1abc9e86824ae4be31347e3e3a70425ab12271c6b7eeef552f00164ef23cfffa2551c3c9d1fe5ab91f"
|
||||
sha512sum = "4642f6d59c76c6e5dbd827fdb28694376a9cc76e513146d092b49afb41513b3c9dff2339cfcebfb5b260f5cdc49a59a69906e284e5d478b2189d3374e9e24fd5"
|
||||
|
||||
|
||||
recipe = Python3RecipePinned()
|
||||
|
||||
@@ -1,19 +1,17 @@
|
||||
import os
|
||||
|
||||
from pythonforandroid.recipes.qt6 import Qt6Recipe
|
||||
|
||||
from pythonforandroid.util import load_source
|
||||
|
||||
util = load_source('util', os.path.join(os.path.dirname(os.path.dirname(__file__)), 'util.py'))
|
||||
|
||||
assert Qt6Recipe._version == "6.4.3"
|
||||
# assert Qt6Recipe._version == "6.5.3"
|
||||
assert Qt6Recipe._version == "6.10.2"
|
||||
assert Qt6Recipe.depends == ['python3', 'hostqt6']
|
||||
assert Qt6Recipe.python_depends == []
|
||||
|
||||
|
||||
class Qt6RecipePinned(util.InheritedRecipeMixin, Qt6Recipe):
|
||||
sha512sum = "0bdbe8b9a43390c98cf19e851ec5394bc78438d227cf9d0d7a3748aee9a32a7f14fc46f52d4fa283819f21413567080aee7225c566af5278557f5e1992674da3"
|
||||
# sha512sum = "ca8ea3b81c121886636988275f7fa8ae6d19f7be02669e63ab19b4285b611057a41279db9532c25ae87baa3904b010e1db68b899cd0eda17a5a8d3d87098b4d5"
|
||||
sha512sum = "bf1a1d42d57b4d2e77f7227f4cbe01e847fd65035461b89481063b32f25a57be6e5a07889acc4af65ca9ff9d27b7fe63bd2fe60b8aa7fa19d554394d799fbaa1"
|
||||
|
||||
|
||||
recipe = Qt6RecipePinned()
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
from pythonforandroid.recipes.setuptools import SetuptoolsRecipe
|
||||
|
||||
|
||||
assert SetuptoolsRecipe._version == "51.3.3"
|
||||
assert SetuptoolsRecipe.depends == ['python3']
|
||||
assert SetuptoolsRecipe.python_depends == []
|
||||
|
||||
|
||||
class SetuptoolsRecipePinned(SetuptoolsRecipe):
|
||||
sha512sum = "5a3572466a68c6f650111448ce3343f64c62044650bb8635edbff97e2bc7b216b8bbe3b4e3bccf34e6887f3bedc911b27ca5f9a515201cae49cf44fbacf03345"
|
||||
|
||||
|
||||
recipe = SetuptoolsRecipePinned()
|
||||
@@ -1,13 +1,18 @@
|
||||
from pythonforandroid.recipes.sip import SipRecipe
|
||||
from pythonforandroid.util import HashPinnedDependency
|
||||
|
||||
|
||||
assert SipRecipe._version == "6.7.9"
|
||||
assert SipRecipe.depends == ["setuptools", "packaging", "tomli", "ply", "python3"], SipRecipe.depends
|
||||
assert SipRecipe._version == "6.15.1"
|
||||
assert SipRecipe.depends == ["python3"], SipRecipe.depends
|
||||
assert SipRecipe.python_depends == []
|
||||
|
||||
|
||||
class SipRecipePinned(SipRecipe):
|
||||
sha512sum = "bb9d0d0d92002b6fd33f7e8ebe8cd62456dacc16b5734b73760b1ba14fb9b1f2b9b6640b40196c6cf5f345e1afde48bdef39675c4d3480041771325d4cf3c233"
|
||||
sha512sum = "30a312419ba82c0221c0cf03c3fb3ad7d45bb8fe633d1d7477025a7986b0a7f7b7b781a8d9cd6bcdb78f3b872231fd1eed123a761b497861822f2e35093f574d"
|
||||
|
||||
hostpython_prerequisites = [
|
||||
HashPinnedDependency(package="setuptools==80.9.0",
|
||||
hashes=['sha256:062d34222ad13e0cc312a4c02d73f059e86a4acbfbdea8f8f76b28c99f306922']),
|
||||
]
|
||||
|
||||
|
||||
recipe = SipRecipePinned()
|
||||
|
||||
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 691 B |
|
Before Width: | Height: | Size: 880 B After Width: | Height: | Size: 833 B |
|
Before Width: | Height: | Size: 314 B After Width: | Height: | Size: 394 B |
|
Before Width: | Height: | Size: 380 B After Width: | Height: | Size: 412 B |
@@ -329,6 +329,7 @@ Pane {
|
||||
}
|
||||
}
|
||||
}
|
||||
property color navigationBarBackgroundColor: constants.highlightBackground
|
||||
|
||||
AddressDetails {
|
||||
id: addressdetails
|
||||
|
||||
@@ -107,9 +107,9 @@ Pane {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
|
||||
verticalPadding: 0
|
||||
verticalPadding: bg.lineWidth
|
||||
horizontalPadding: 0
|
||||
background: PaneInsetBackground {}
|
||||
background: PaneInsetBackground { id: bg; vertical: false }
|
||||
|
||||
ElListView {
|
||||
id: listview
|
||||
@@ -249,6 +249,7 @@ Pane {
|
||||
|
||||
ButtonContainer {
|
||||
Layout.fillWidth: true
|
||||
|
||||
FlatButton {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredWidth: 1
|
||||
@@ -275,6 +276,7 @@ Pane {
|
||||
}
|
||||
|
||||
}
|
||||
property color navigationBarBackgroundColor: constants.highlightBackground
|
||||
|
||||
Component {
|
||||
id: sectionDelegate
|
||||
|
||||
@@ -37,6 +37,7 @@ ElDialog {
|
||||
InfoTextArea {
|
||||
Layout.fillWidth: true
|
||||
Layout.margins: constants.paddingMedium
|
||||
backgroundColor: constants.darkerDialogBackground
|
||||
|
||||
text: bip39RecoveryListModel.state == Bip39RecoveryListModel.Scanning
|
||||
? qsTr('Scanning for accounts...')
|
||||
@@ -65,7 +66,9 @@ ElDialog {
|
||||
|
||||
verticalPadding: 0
|
||||
horizontalPadding: 0
|
||||
background: PaneInsetBackground {}
|
||||
background: PaneInsetBackground {
|
||||
baseColor: constants.darkerDialogBackground
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
spacing: 0
|
||||
|
||||
@@ -233,8 +233,8 @@ Pane {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
property color navigationBarBackgroundColor: constants.highlightBackground
|
||||
|
||||
Component {
|
||||
id: openChannelDialog
|
||||
|
||||
@@ -145,14 +145,10 @@ Pane {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 1
|
||||
}
|
||||
Pane {
|
||||
background: Rectangle { color: Material.dialogColor }
|
||||
padding: 0
|
||||
FlatButton {
|
||||
Layout.minimumWidth: implicitWidth
|
||||
text: channeldetails.frozenForSending ? qsTr('Unfreeze') : qsTr('Freeze')
|
||||
onClicked: channeldetails.freezeForSending()
|
||||
}
|
||||
Button {
|
||||
Layout.minimumWidth: implicitWidth
|
||||
text: channeldetails.frozenForSending ? qsTr('Unfreeze') : qsTr('Freeze')
|
||||
onClicked: channeldetails.freezeForSending()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -182,14 +178,10 @@ Pane {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 1
|
||||
}
|
||||
Pane {
|
||||
background: Rectangle { color: Material.dialogColor }
|
||||
padding: 0
|
||||
FlatButton {
|
||||
Layout.minimumWidth: implicitWidth
|
||||
text: channeldetails.frozenForReceiving ? qsTr('Unfreeze') : qsTr('Freeze')
|
||||
onClicked: channeldetails.freezeForReceiving()
|
||||
}
|
||||
Button {
|
||||
Layout.minimumWidth: implicitWidth
|
||||
text: channeldetails.frozenForReceiving ? qsTr('Unfreeze') : qsTr('Freeze')
|
||||
onClicked: channeldetails.freezeForReceiving()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -466,8 +458,8 @@ Pane {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
property color navigationBarBackgroundColor: constants.highlightBackground
|
||||
|
||||
ChannelDetails {
|
||||
id: channeldetails
|
||||
|
||||
@@ -23,7 +23,7 @@ ElDialog {
|
||||
|
||||
property string channelBackup
|
||||
|
||||
function reset() {
|
||||
function resetDialog() {
|
||||
state = ''
|
||||
errorText.text = ''
|
||||
peerText.text = ''
|
||||
@@ -81,7 +81,7 @@ ElDialog {
|
||||
}
|
||||
}
|
||||
|
||||
TextHighlightPane {
|
||||
DialogHighlightPane {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.preferredWidth: dialog.width * 3/4
|
||||
Label {
|
||||
@@ -100,6 +100,7 @@ ElDialog {
|
||||
visible: false
|
||||
iconStyle: InfoTextArea.IconStyle.Error
|
||||
textFormat: TextEdit.PlainText
|
||||
backgroundColor: constants.darkerDialogBackground
|
||||
}
|
||||
|
||||
InfoTextArea {
|
||||
@@ -108,6 +109,7 @@ ElDialog {
|
||||
Layout.preferredWidth: dialog.width * 2/3
|
||||
visible: false
|
||||
textFormat: TextEdit.PlainText
|
||||
backgroundColor: constants.darkerDialogBackground
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -63,13 +63,10 @@ Pane {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
Layout.topMargin: constants.paddingLarge
|
||||
Layout.bottomMargin: constants.paddingLarge
|
||||
Layout.leftMargin: constants.paddingMedium
|
||||
Layout.rightMargin: constants.paddingMedium
|
||||
|
||||
verticalPadding: 0
|
||||
verticalPadding: bg.lineWidth
|
||||
horizontalPadding: 0
|
||||
background: PaneInsetBackground {}
|
||||
background: PaneInsetBackground { id: bg; vertical: false }
|
||||
|
||||
ColumnLayout {
|
||||
spacing: 0
|
||||
@@ -121,6 +118,7 @@ Pane {
|
||||
|
||||
ButtonContainer {
|
||||
Layout.fillWidth: true
|
||||
|
||||
FlatButton {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredWidth: 1
|
||||
@@ -157,8 +155,8 @@ Pane {
|
||||
icon.source: '../../icons/lightning.png'
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
property color navigationBarBackgroundColor: constants.highlightBackground
|
||||
|
||||
Component {
|
||||
id: openChannelDialog
|
||||
|
||||
@@ -70,7 +70,7 @@ ElDialog {
|
||||
color: Material.accentColor
|
||||
}
|
||||
|
||||
TextHighlightPane {
|
||||
DialogHighlightPane {
|
||||
Layout.columnSpan: 2
|
||||
Layout.fillWidth: true
|
||||
|
||||
@@ -91,6 +91,7 @@ ElDialog {
|
||||
Layout.fillWidth: true
|
||||
Layout.bottomMargin: constants.paddingLarge
|
||||
text: channeldetails.messageForceClose
|
||||
backgroundColor: constants.darkerDialogBackground
|
||||
}
|
||||
|
||||
Label {
|
||||
@@ -140,6 +141,7 @@ ElDialog {
|
||||
Layout.maximumWidth: parent.width
|
||||
visible: !channeldetails.isClosing && errorText.text
|
||||
iconStyle: InfoTextArea.IconStyle.Error
|
||||
backgroundColor: constants.darkerDialogBackground
|
||||
}
|
||||
Label {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
@@ -154,17 +156,21 @@ ElDialog {
|
||||
}
|
||||
}
|
||||
|
||||
FlatButton {
|
||||
DialogButtonContainer {
|
||||
Layout.columnSpan: 2
|
||||
Layout.fillWidth: true
|
||||
text: qsTr('Close channel')
|
||||
icon.source: '../../icons/closebutton.png'
|
||||
enabled: !channeldetails.isClosing
|
||||
onClicked: {
|
||||
if (closetypegroup.checkedButton.closetype == 'local_force') {
|
||||
showBackupThenClose()
|
||||
} else {
|
||||
doCloseChannel()
|
||||
|
||||
FlatButton {
|
||||
Layout.fillWidth: true
|
||||
text: qsTr('Close channel')
|
||||
icon.source: '../../icons/closebutton.png'
|
||||
enabled: !channeldetails.isClosing
|
||||
onClicked: {
|
||||
if (closetypegroup.checkedButton.closetype == 'local_force') {
|
||||
showBackupThenClose()
|
||||
} else {
|
||||
doCloseChannel()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ ElDialog {
|
||||
id: dialog
|
||||
|
||||
required property QtObject finalizer
|
||||
required property Amount satoshis
|
||||
required property var satoshis // type: Amount
|
||||
property string address
|
||||
property string message
|
||||
property bool showOptions: true
|
||||
@@ -71,7 +71,7 @@ ElDialog {
|
||||
color: Material.accentColor
|
||||
}
|
||||
|
||||
TextHighlightPane {
|
||||
DialogHighlightPane {
|
||||
Layout.columnSpan: 2
|
||||
Layout.fillWidth: true
|
||||
GridLayout {
|
||||
@@ -122,7 +122,7 @@ ElDialog {
|
||||
color: Material.accentColor
|
||||
}
|
||||
|
||||
TextHighlightPane {
|
||||
DialogHighlightPane {
|
||||
Layout.columnSpan: 2
|
||||
Layout.fillWidth: true
|
||||
height: feepicker.height
|
||||
@@ -153,7 +153,7 @@ ElDialog {
|
||||
visible: showOptions
|
||||
}
|
||||
|
||||
TextHighlightPane {
|
||||
DialogHighlightPane {
|
||||
Layout.columnSpan: 2
|
||||
Layout.fillWidth: true
|
||||
visible: optionstoggle.visible && !optionstoggle.collapsed
|
||||
@@ -214,6 +214,7 @@ ElDialog {
|
||||
visible: finalizer.warning != ''
|
||||
text: finalizer.warning
|
||||
iconStyle: InfoTextArea.IconStyle.Warn
|
||||
backgroundColor: constants.darkerDialogBackground
|
||||
}
|
||||
|
||||
ToggleLabel {
|
||||
@@ -234,6 +235,7 @@ ElDialog {
|
||||
Layout.columnSpan: 2
|
||||
Layout.fillWidth: true
|
||||
visible: finalizer.valid
|
||||
backgroundColor: constants.darkerDialogBackground
|
||||
|
||||
idx: index
|
||||
model: modelData
|
||||
@@ -258,6 +260,7 @@ ElDialog {
|
||||
Layout.columnSpan: 2
|
||||
Layout.fillWidth: true
|
||||
visible: finalizer.valid
|
||||
backgroundColor: constants.darkerDialogBackground
|
||||
|
||||
allowShare: false
|
||||
allowClickAddress: false
|
||||
@@ -270,15 +273,19 @@ ElDialog {
|
||||
}
|
||||
}
|
||||
|
||||
FlatButton {
|
||||
id: sendButton
|
||||
DialogButtonContainer {
|
||||
Layout.fillWidth: true
|
||||
text: (Daemon.currentWallet.isWatchOnly || !Daemon.currentWallet.canSignWithoutCosigner)
|
||||
? qsTr('Finalize...')
|
||||
: qsTr('Pay...')
|
||||
icon.source: '../../icons/confirmed.png'
|
||||
enabled: finalizer.valid
|
||||
onClicked: doAccept()
|
||||
|
||||
FlatButton {
|
||||
id: sendButton
|
||||
Layout.fillWidth: true
|
||||
text: (Daemon.currentWallet.isWatchOnly || !Daemon.currentWallet.canSignWithoutCosigner)
|
||||
? qsTr('Finalize...')
|
||||
: qsTr('Pay...')
|
||||
icon.source: '../../icons/confirmed.png'
|
||||
enabled: finalizer.valid
|
||||
onClicked: doAccept()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,8 +29,10 @@ Item {
|
||||
|
||||
property color mutedForeground: 'gray' //Qt.lighter(Material.background, 2)
|
||||
property color darkerBackground: Qt.darker(Material.background, 1.20)
|
||||
property color lighterBackground: Qt.lighter(Material.background, 1.10)
|
||||
property color darkerDialogBackground: Qt.darker(Material.dialogColor, 1.20)
|
||||
property color highlightBackground: Qt.lighter(Material.background, 1.30)
|
||||
property color dialogColor: Material.dialogColor
|
||||
property color seedTextAreaBackground: Qt.darker(darkerDialogBackground, 1.20)
|
||||
property color notificationBackground: Qt.lighter(Material.background, 1.5)
|
||||
|
||||
property color colorCredit: "#ff80ff80"
|
||||
|
||||
@@ -59,7 +59,7 @@ ElDialog {
|
||||
color: Material.accentColor
|
||||
}
|
||||
|
||||
TextHighlightPane {
|
||||
DialogHighlightPane {
|
||||
Layout.columnSpan: 2
|
||||
Layout.fillWidth: true
|
||||
height: feepicker_childinfo.height
|
||||
@@ -82,7 +82,7 @@ ElDialog {
|
||||
color: Material.accentColor
|
||||
}
|
||||
|
||||
TextHighlightPane {
|
||||
DialogHighlightPane {
|
||||
Layout.columnSpan: 2
|
||||
Layout.fillWidth: true
|
||||
|
||||
@@ -159,6 +159,7 @@ ElDialog {
|
||||
visible: cpfpfeebumper.warning != ''
|
||||
text: cpfpfeebumper.warning
|
||||
iconStyle: InfoTextArea.IconStyle.Warn
|
||||
backgroundColor: constants.darkerDialogBackground
|
||||
}
|
||||
|
||||
ToggleLabel {
|
||||
@@ -213,13 +214,16 @@ ElDialog {
|
||||
}
|
||||
}
|
||||
|
||||
FlatButton {
|
||||
id: sendButton
|
||||
DialogButtonContainer {
|
||||
Layout.fillWidth: true
|
||||
text: qsTr('Ok')
|
||||
icon.source: '../../icons/confirmed.png'
|
||||
enabled: cpfpfeebumper.valid
|
||||
onClicked: doAccept()
|
||||
FlatButton {
|
||||
id: sendButton
|
||||
Layout.fillWidth: true
|
||||
text: qsTr('Ok')
|
||||
icon.source: '../../icons/confirmed.png'
|
||||
enabled: cpfpfeebumper.valid
|
||||
onClicked: doAccept()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ ElDialog {
|
||||
width: parent.width
|
||||
spacing: constants.paddingMedium
|
||||
|
||||
TextHighlightPane {
|
||||
DialogHighlightPane {
|
||||
Layout.fillWidth: true
|
||||
Layout.leftMargin: constants.paddingMedium
|
||||
Layout.rightMargin: constants.paddingMedium
|
||||
@@ -61,6 +61,7 @@ ElDialog {
|
||||
Layout.margins: constants.paddingLarge
|
||||
visible: dialog.text_help
|
||||
text: dialog.text_help
|
||||
backgroundColor: constants.darkerDialogBackground
|
||||
}
|
||||
|
||||
InfoTextArea {
|
||||
@@ -72,11 +73,12 @@ ElDialog {
|
||||
visible: dialog.text_warn
|
||||
text: dialog.text_warn
|
||||
iconStyle: InfoTextArea.IconStyle.Warn
|
||||
backgroundColor: constants.darkerDialogBackground
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ButtonContainer {
|
||||
DialogButtonContainer {
|
||||
id: buttons
|
||||
Layout.fillWidth: true
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ ElDialog {
|
||||
width: parent.width
|
||||
spacing: constants.paddingMedium
|
||||
|
||||
TextHighlightPane {
|
||||
DialogHighlightPane {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.fillWidth: true
|
||||
Layout.leftMargin: constants.paddingMedium
|
||||
@@ -60,7 +60,7 @@ ElDialog {
|
||||
Layout.bottomMargin: constants.paddingMedium
|
||||
}
|
||||
|
||||
TextHighlightPane {
|
||||
DialogHighlightPane {
|
||||
Layout.fillWidth: true
|
||||
visible: dialog.text
|
||||
|
||||
@@ -84,11 +84,12 @@ ElDialog {
|
||||
visible: dialog.text_help
|
||||
text: dialog.text_help
|
||||
Layout.fillWidth: true
|
||||
backgroundColor: constants.darkerDialogBackground
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ButtonContainer {
|
||||
DialogButtonContainer {
|
||||
Layout.fillWidth: true
|
||||
|
||||
FlatButton {
|
||||
|
||||
@@ -14,8 +14,8 @@ Pane {
|
||||
padding: 0
|
||||
clip: true
|
||||
|
||||
background: Rectangle {
|
||||
color: constants.darkerBackground
|
||||
background: PaneInsetBackground {
|
||||
vertical: false
|
||||
}
|
||||
|
||||
ElListView {
|
||||
|
||||
@@ -84,7 +84,6 @@ ElDialog {
|
||||
icon.source: '../../icons/qrcode.png'
|
||||
icon.height: constants.iconSizeMedium
|
||||
icon.width: constants.iconSizeMedium
|
||||
scale: 1.2
|
||||
onClicked: {
|
||||
var dialog = app.scanDialog.createObject(app, {
|
||||
hint: Daemon.currentWallet.isWatchOnly
|
||||
|
||||
@@ -1,98 +0,0 @@
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import QtQuick.Controls
|
||||
|
||||
import org.electrum 1.0
|
||||
|
||||
import "controls"
|
||||
|
||||
ElDialog {
|
||||
id: root
|
||||
|
||||
property bool valid: false
|
||||
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
|
||||
padding: 0
|
||||
|
||||
title: qsTr('Import channel backup')
|
||||
iconSource: Qt.resolvedUrl('../../icons/file.png')
|
||||
|
||||
function verifyChannelBackup(text) {
|
||||
return valid = Daemon.currentWallet.isValidChannelBackup(text)
|
||||
}
|
||||
|
||||
onAccepted: {
|
||||
Daemon.currentWallet.importChannelBackup(channelbackup_ta.text)
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
spacing: 0
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.leftMargin: constants.paddingLarge
|
||||
|
||||
TextArea {
|
||||
id: channelbackup_ta
|
||||
Layout.fillWidth: true
|
||||
Layout.minimumHeight: 80
|
||||
font.family: FixedFont
|
||||
focus: true
|
||||
wrapMode: TextEdit.WrapAnywhere
|
||||
onTextChanged: verifyChannelBackup(text)
|
||||
}
|
||||
ColumnLayout {
|
||||
ToolButton {
|
||||
icon.source: '../../icons/paste.png'
|
||||
icon.height: constants.iconSizeMedium
|
||||
icon.width: constants.iconSizeMedium
|
||||
onClicked: {
|
||||
channelbackup_ta.text = AppController.clipboardToText()
|
||||
}
|
||||
}
|
||||
ToolButton {
|
||||
icon.source: '../../icons/qrcode.png'
|
||||
icon.height: constants.iconSizeMedium
|
||||
icon.width: constants.iconSizeMedium
|
||||
scale: 1.2
|
||||
onClicked: {
|
||||
var dialog = app.scanDialog.createObject(app, {
|
||||
hint: qsTr('Scan a channel backup')
|
||||
})
|
||||
dialog.onFoundText.connect(function(data) {
|
||||
channelbackup_ta.text = data
|
||||
dialog.close()
|
||||
})
|
||||
dialog.open()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TextArea {
|
||||
id: validationtext
|
||||
visible: text
|
||||
Layout.fillWidth: true
|
||||
Layout.leftMargin: constants.paddingLarge
|
||||
|
||||
readOnly: true
|
||||
wrapMode: TextInput.WordWrap
|
||||
background: Rectangle {
|
||||
color: 'transparent'
|
||||
}
|
||||
}
|
||||
|
||||
Item { Layout.preferredWidth: 1; Layout.fillHeight: true }
|
||||
|
||||
FlatButton {
|
||||
Layout.fillWidth: true
|
||||
enabled: valid
|
||||
text: qsTr('Import')
|
||||
onClicked: doAccept()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -10,7 +10,7 @@ import "controls"
|
||||
ElDialog {
|
||||
id: dialog
|
||||
|
||||
property Invoice invoice
|
||||
property var invoice // type Invoice
|
||||
property bool payImmediately: false
|
||||
property string broadcastTxid
|
||||
|
||||
@@ -24,7 +24,7 @@ ElDialog {
|
||||
|
||||
property bool _canMax: invoice.invoiceType == Invoice.OnchainInvoice
|
||||
|
||||
property Amount _invoice_amount: invoice.amount
|
||||
property var _invoice_amount: invoice.amount // type: Amount
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
@@ -67,6 +67,7 @@ ElDialog {
|
||||
? InfoTextArea.IconStyle.Pending
|
||||
: InfoTextArea.IconStyle.Error
|
||||
: InfoTextArea.IconStyle.Info
|
||||
backgroundColor: constants.darkerDialogBackground
|
||||
}
|
||||
|
||||
Label {
|
||||
@@ -77,7 +78,7 @@ ElDialog {
|
||||
color: Material.accentColor
|
||||
}
|
||||
|
||||
TextHighlightPane {
|
||||
DialogHighlightPane {
|
||||
Layout.columnSpan: 2
|
||||
Layout.fillWidth: true
|
||||
visible: invoice.invoiceType == Invoice.OnchainInvoice
|
||||
@@ -114,7 +115,7 @@ ElDialog {
|
||||
color: Material.accentColor
|
||||
}
|
||||
|
||||
TextHighlightPane {
|
||||
DialogHighlightPane {
|
||||
Layout.columnSpan: 2
|
||||
Layout.fillWidth: true
|
||||
|
||||
@@ -137,7 +138,7 @@ ElDialog {
|
||||
color: Material.accentColor
|
||||
}
|
||||
|
||||
TextHighlightPane {
|
||||
DialogHighlightPane {
|
||||
id: amountContainer
|
||||
|
||||
Layout.columnSpan: 2
|
||||
@@ -294,6 +295,8 @@ ElDialog {
|
||||
id: maxAmountMessage
|
||||
visible: amountMax.checked && text
|
||||
compact: true
|
||||
backgroundColor: constants.darkerDialogBackground
|
||||
|
||||
Connections {
|
||||
target: invoice
|
||||
function onMaxAmountMessage(message) {
|
||||
@@ -320,7 +323,7 @@ ElDialog {
|
||||
color: Material.accentColor
|
||||
}
|
||||
|
||||
TextHighlightPane {
|
||||
DialogHighlightPane {
|
||||
Layout.columnSpan: 2
|
||||
Layout.fillWidth: true
|
||||
|
||||
@@ -358,7 +361,7 @@ ElDialog {
|
||||
color: Material.accentColor
|
||||
}
|
||||
|
||||
TextHighlightPane {
|
||||
DialogHighlightPane {
|
||||
Layout.columnSpan: 2
|
||||
Layout.fillWidth: true
|
||||
|
||||
@@ -401,7 +404,7 @@ ElDialog {
|
||||
visible: 'r' in invoice.lnprops && invoice.lnprops.r.length
|
||||
model: invoice.lnprops.r
|
||||
|
||||
TextHighlightPane {
|
||||
DialogHighlightPane {
|
||||
Layout.columnSpan: 2
|
||||
Layout.fillWidth: true
|
||||
|
||||
@@ -428,7 +431,7 @@ ElDialog {
|
||||
color: Material.accentColor
|
||||
}
|
||||
|
||||
TextHighlightPane {
|
||||
DialogHighlightPane {
|
||||
Layout.columnSpan: 2
|
||||
Layout.fillWidth: true
|
||||
visible: invoice.invoiceType == Invoice.LightningInvoice && invoice.address
|
||||
@@ -458,7 +461,7 @@ ElDialog {
|
||||
}
|
||||
}
|
||||
|
||||
ButtonContainer {
|
||||
DialogButtonContainer {
|
||||
Layout.fillWidth: true
|
||||
|
||||
FlatButton {
|
||||
|
||||
@@ -18,7 +18,6 @@ Pane {
|
||||
|
||||
ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.margins: constants.paddingLarge
|
||||
|
||||
InfoTextArea {
|
||||
Layout.fillWidth: true
|
||||
@@ -32,9 +31,9 @@ Pane {
|
||||
}
|
||||
|
||||
Frame {
|
||||
background: PaneInsetBackground {}
|
||||
background: PaneInsetBackground {id: bg; vertical: false}
|
||||
|
||||
verticalPadding: 0
|
||||
verticalPadding: bg.lineWidth
|
||||
horizontalPadding: 0
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
@@ -87,6 +86,7 @@ Pane {
|
||||
|
||||
ButtonContainer {
|
||||
Layout.fillWidth: true
|
||||
|
||||
FlatButton {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredWidth: 1
|
||||
@@ -112,4 +112,6 @@ Pane {
|
||||
}
|
||||
}
|
||||
}
|
||||
property color navigationBarBackgroundColor: constants.highlightBackground
|
||||
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ ElDialog {
|
||||
title: qsTr('LNURL Payment request')
|
||||
iconSource: '../../../icons/link.png'
|
||||
|
||||
property InvoiceParser invoiceParser
|
||||
property var invoiceParser // type: InvoiceParser
|
||||
|
||||
padding: 0
|
||||
needsSystemBarPadding: false
|
||||
@@ -43,6 +43,7 @@ ElDialog {
|
||||
compact: true
|
||||
visible: invoiceParser.lnurlData['min_sendable_sat'] != invoiceParser.lnurlData['max_sendable_sat']
|
||||
text: qsTr('Amount must be between %1 and %2 %3').arg(Config.formatSats(invoiceParser.lnurlData['min_sendable_sat'])).arg(Config.formatSats(invoiceParser.lnurlData['max_sendable_sat'])).arg(Config.baseUnit)
|
||||
backgroundColor: constants.darkerDialogBackground
|
||||
}
|
||||
|
||||
Label {
|
||||
@@ -129,15 +130,18 @@ ElDialog {
|
||||
}
|
||||
}
|
||||
|
||||
FlatButton {
|
||||
DialogButtonContainer {
|
||||
Layout.topMargin: constants.paddingLarge
|
||||
Layout.fillWidth: true
|
||||
text: qsTr('Pay...')
|
||||
icon.source: '../../icons/confirmed.png'
|
||||
enabled: valid
|
||||
onClicked: {
|
||||
invoiceParser.lnurlGetInvoice(comment.text)
|
||||
dialog.close()
|
||||
FlatButton {
|
||||
Layout.fillWidth: true
|
||||
text: qsTr('Pay...')
|
||||
icon.source: '../../icons/confirmed.png'
|
||||
enabled: valid
|
||||
onClicked: {
|
||||
invoiceParser.lnurlGetInvoice(comment.text)
|
||||
dialog.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,8 +13,8 @@ ElDialog {
|
||||
title: qsTr('LNURL Withdraw request')
|
||||
iconSource: '../../../icons/link.png'
|
||||
|
||||
property Wallet wallet: Daemon.currentWallet
|
||||
property RequestDetails requestDetails
|
||||
property var wallet: Daemon.currentWallet // type: Wallet
|
||||
property var requestDetails // type: RequestDetails
|
||||
|
||||
padding: 0
|
||||
needsSystemBarPadding: false
|
||||
@@ -50,6 +50,7 @@ ElDialog {
|
||||
|
||||
ColumnLayout {
|
||||
width: parent.width
|
||||
spacing: 0
|
||||
|
||||
GridLayout {
|
||||
id: rootLayout
|
||||
@@ -75,6 +76,7 @@ ElDialog {
|
||||
+ '\n\n'
|
||||
+ qsTr('Do a submarine swap in the \'Channels\' tab to get more incoming liquidity.')
|
||||
iconStyle: InfoTextArea.IconStyle.Error
|
||||
backgroundColor: constants.darkerDialogBackground
|
||||
}
|
||||
|
||||
InfoTextArea {
|
||||
@@ -83,9 +85,10 @@ ElDialog {
|
||||
compact: true
|
||||
visible: !dialog.insufficientLiquidity && dialog.providerMinWithdrawable != dialog.providerMaxWithdrawable
|
||||
text: qsTr('Amount must be between %1 and %2 %3')
|
||||
.arg(Config.formatSats(dialog.effectiveMinWithdrawable))
|
||||
.arg(Config.formatSats(dialog.effectiveMaxWithdrawable))
|
||||
.arg(Config.baseUnit)
|
||||
.arg(Config.formatSats(dialog.effectiveMinWithdrawable))
|
||||
.arg(Config.formatSats(dialog.effectiveMaxWithdrawable))
|
||||
.arg(Config.baseUnit)
|
||||
backgroundColor: constants.darkerDialogBackground
|
||||
}
|
||||
|
||||
InfoTextArea {
|
||||
@@ -99,6 +102,7 @@ ElDialog {
|
||||
+ ' '
|
||||
+ qsTr('You may need to do a submarine swap to increase your incoming liquidity.')
|
||||
iconStyle: InfoTextArea.IconStyle.Warn
|
||||
backgroundColor: constants.darkerDialogBackground
|
||||
}
|
||||
|
||||
Label {
|
||||
@@ -160,16 +164,19 @@ ElDialog {
|
||||
}
|
||||
}
|
||||
|
||||
FlatButton {
|
||||
DialogButtonContainer {
|
||||
Layout.topMargin: constants.paddingLarge
|
||||
Layout.fillWidth: true
|
||||
text: qsTr('Withdraw...')
|
||||
icon.source: '../../icons/confirmed.png'
|
||||
enabled: valid && !requestDetails.busy
|
||||
onClicked: {
|
||||
var satsAmount = amountBtc.textAsSats.satsInt;
|
||||
requestDetails.lnurlRequestWithdrawal(satsAmount);
|
||||
dialog.close();
|
||||
FlatButton {
|
||||
Layout.fillWidth: true
|
||||
text: qsTr('Withdraw...')
|
||||
icon.source: '../../icons/confirmed.png'
|
||||
enabled: valid && !requestDetails.busy
|
||||
onClicked: {
|
||||
var satsAmount = amountBtc.textAsSats.satsInt;
|
||||
requestDetails.lnurlRequestWithdrawal(satsAmount);
|
||||
dialog.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,8 +46,13 @@ ElDialog {
|
||||
}
|
||||
}
|
||||
|
||||
ButtonContainer {
|
||||
DialogButtonContainer {
|
||||
Layout.fillWidth: true
|
||||
function beforeLayout() {
|
||||
if (!dialog.text) {
|
||||
headerComponent = null
|
||||
}
|
||||
}
|
||||
|
||||
FlatButton {
|
||||
Layout.fillWidth: true
|
||||
|
||||
@@ -314,6 +314,7 @@ Pane {
|
||||
}
|
||||
}
|
||||
}
|
||||
property color navigationBarBackgroundColor: constants.highlightBackground
|
||||
|
||||
Component {
|
||||
id: serverConfig
|
||||
|
||||
@@ -50,21 +50,25 @@ ElDialog {
|
||||
Layout.fillHeight: true
|
||||
Layout.leftMargin: constants.paddingLarge
|
||||
Layout.rightMargin: constants.paddingLarge
|
||||
Layout.bottomMargin: constants.paddingLarge
|
||||
|
||||
TextHighlightPane {
|
||||
InfoTextArea {
|
||||
Layout.fillWidth: true
|
||||
Label {
|
||||
text: qsTr('Enter the list of Nostr relays') + '<br/><br/>' +
|
||||
qsTr('Nostr relays are used to send and receive submarine swap offers.') +
|
||||
' ' + qsTr('For multisig wallets, nostr is also used to relay transactions to your co-signers.') +
|
||||
' ' + qsTr('Connections to nostr are only made when required, and ephemerally.')
|
||||
width: parent.width
|
||||
wrapMode: Text.Wrap
|
||||
}
|
||||
Layout.bottomMargin: constants.paddingLarge
|
||||
compact: true
|
||||
text: qsTr('Nostr relays are used to send and receive submarine swap offers.') +
|
||||
' ' + qsTr('For multisig wallets, nostr is also used to relay transactions to your co-signers.') +
|
||||
' ' + qsTr('Connections to nostr are only made when required, and ephemerally.')
|
||||
backgroundColor: constants.darkerDialogBackground
|
||||
}
|
||||
|
||||
Label {
|
||||
text: qsTr('Enter the list of Nostr relays')
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: constants.paddingLarge
|
||||
ElTextArea {
|
||||
id: relays_ta
|
||||
Layout.fillWidth: true
|
||||
@@ -96,14 +100,18 @@ ElDialog {
|
||||
}
|
||||
}
|
||||
|
||||
FlatButton {
|
||||
DialogButtonContainer {
|
||||
Layout.fillWidth: true
|
||||
text: qsTr('Ok')
|
||||
enabled: valid
|
||||
icon.source: '../../icons/confirmed.png'
|
||||
onClicked: {
|
||||
Config.nostrRelays = clean_array(relays_ta.text).join(",")
|
||||
rootItem.close()
|
||||
|
||||
FlatButton {
|
||||
Layout.fillWidth: true
|
||||
text: qsTr('Ok')
|
||||
enabled: valid
|
||||
icon.source: '../../icons/confirmed.png'
|
||||
onClicked: {
|
||||
Config.nostrRelays = clean_array(relays_ta.text).join(",")
|
||||
rootItem.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,6 +55,7 @@ ElDialog {
|
||||
'\n\n',
|
||||
qsTr('If you want to have recoverable channels, you must create a new wallet with an Electrum seed')
|
||||
].join('')
|
||||
backgroundColor: constants.darkerDialogBackground
|
||||
}
|
||||
|
||||
InfoTextArea {
|
||||
@@ -65,80 +66,79 @@ ElDialog {
|
||||
text: [ qsTr('You currently have recoverable channels setting disabled.'),
|
||||
qsTr('This means your channels cannot be recovered from seed.')
|
||||
].join(' ')
|
||||
}
|
||||
|
||||
Label {
|
||||
text: qsTr('Node')
|
||||
Layout.columnSpan: 3
|
||||
color: Material.accentColor
|
||||
backgroundColor: constants.darkerDialogBackground
|
||||
}
|
||||
|
||||
// gossip
|
||||
TextArea {
|
||||
id: node
|
||||
visible: Config.useGossip
|
||||
Layout.columnSpan: 2
|
||||
Layout.fillWidth: true
|
||||
font.family: FixedFont
|
||||
wrapMode: Text.Wrap
|
||||
placeholderText: qsTr('Paste or scan node uri/pubkey')
|
||||
inputMethodHints: Qt.ImhSensitiveData | Qt.ImhNoPredictiveText | Qt.ImhNoAutoUppercase
|
||||
onTextChanged: {
|
||||
if (activeFocus)
|
||||
channelopener.connectStr = text
|
||||
}
|
||||
onActiveFocusChanged: {
|
||||
if (!activeFocus)
|
||||
channelopener.connectStr = text
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Layout.columnSpan: 3
|
||||
visible: Config.useGossip
|
||||
spacing: 0
|
||||
ToolButton {
|
||||
icon.source: '../../icons/paste.png'
|
||||
icon.height: constants.iconSizeMedium
|
||||
icon.width: constants.iconSizeMedium
|
||||
onClicked: {
|
||||
var cliptext = AppController.clipboardToText()
|
||||
if (!cliptext)
|
||||
return
|
||||
if (channelopener.validateConnectString(cliptext)) {
|
||||
channelopener.connectStr = cliptext
|
||||
node.text = channelopener.connectStr
|
||||
} else {
|
||||
var dialog = app.messageDialog.createObject(app, {
|
||||
text: qsTr('Invalid node-id or connect string')
|
||||
|
||||
TextArea {
|
||||
id: nodeUri
|
||||
visible: Config.useGossip
|
||||
Layout.fillWidth: true
|
||||
Layout.minimumHeight: nodeUriFontMetrics.lineSpacing * 4 + topPadding + bottomPadding
|
||||
Layout.topMargin: constants.paddingSmall
|
||||
font.family: FixedFont
|
||||
wrapMode: Text.Wrap
|
||||
placeholderText: qsTr('Paste or scan node uri/pubkey')
|
||||
inputMethodHints: Qt.ImhSensitiveData | Qt.ImhNoPredictiveText | Qt.ImhNoAutoUppercase
|
||||
onTextChanged: {
|
||||
if (activeFocus)
|
||||
channelopener.connectStr = text
|
||||
}
|
||||
onActiveFocusChanged: {
|
||||
if (!activeFocus)
|
||||
channelopener.connectStr = text
|
||||
}
|
||||
}
|
||||
ColumnLayout {
|
||||
spacing: 0
|
||||
ToolButton {
|
||||
icon.source: '../../icons/paste.png'
|
||||
icon.height: constants.iconSizeMedium
|
||||
icon.width: constants.iconSizeMedium
|
||||
onClicked: {
|
||||
var cliptext = AppController.clipboardToText()
|
||||
if (!cliptext)
|
||||
return
|
||||
if (channelopener.validateConnectString(cliptext)) {
|
||||
channelopener.connectStr = cliptext
|
||||
nodeUri.text = channelopener.connectStr
|
||||
} else {
|
||||
var dialog = app.messageDialog.createObject(app, {
|
||||
text: qsTr('Invalid node-id or connect string')
|
||||
})
|
||||
dialog.open()
|
||||
}
|
||||
}
|
||||
}
|
||||
ToolButton {
|
||||
icon.source: '../../icons/qrcode.png'
|
||||
icon.height: constants.iconSizeMedium
|
||||
icon.width: constants.iconSizeMedium
|
||||
onClicked: {
|
||||
var dialog = app.scanDialog.createObject(app, {
|
||||
hint: qsTr('Scan a node-id or a connect string')
|
||||
})
|
||||
dialog.onFoundText.connect(function(data) {
|
||||
if (channelopener.validateConnectString(data)) {
|
||||
channelopener.connectStr = data
|
||||
nodeUri.text = channelopener.connectStr
|
||||
} else {
|
||||
var errdialog = app.messageDialog.createObject(app, {
|
||||
text: qsTr('Invalid node-id or connect string')
|
||||
})
|
||||
errdialog.open()
|
||||
}
|
||||
dialog.close()
|
||||
})
|
||||
dialog.open()
|
||||
}
|
||||
}
|
||||
}
|
||||
ToolButton {
|
||||
icon.source: '../../icons/qrcode.png'
|
||||
icon.height: constants.iconSizeMedium
|
||||
icon.width: constants.iconSizeMedium
|
||||
scale: 1.2
|
||||
onClicked: {
|
||||
var dialog = app.scanDialog.createObject(app, {
|
||||
hint: qsTr('Scan a node-id or a connect string')
|
||||
})
|
||||
dialog.onFoundText.connect(function(data) {
|
||||
if (channelopener.validateConnectString(data)) {
|
||||
channelopener.connectStr = data
|
||||
node.text = channelopener.connectStr
|
||||
} else {
|
||||
var errdialog = app.messageDialog.createObject(app, {
|
||||
text: qsTr('Invalid node-id or connect string')
|
||||
})
|
||||
errdialog.open()
|
||||
}
|
||||
dialog.close()
|
||||
})
|
||||
dialog.open()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// trampoline
|
||||
@@ -160,11 +160,7 @@ ElDialog {
|
||||
}
|
||||
}
|
||||
|
||||
Label {
|
||||
text: qsTr('Amount')
|
||||
Layout.columnSpan: 3
|
||||
color: Material.accentColor
|
||||
}
|
||||
Item { Layout.columnSpan: 3; width: 1; height: constants.paddingLarge }
|
||||
|
||||
BtcField {
|
||||
id: amountBtc
|
||||
@@ -238,17 +234,21 @@ ElDialog {
|
||||
text: channelopener.warning
|
||||
visible: text
|
||||
compact: true
|
||||
backgroundColor: constants.darkerDialogBackground
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
FlatButton {
|
||||
DialogButtonContainer {
|
||||
Layout.fillWidth: true
|
||||
text: qsTr('Open Channel...')
|
||||
icon.source: '../../icons/confirmed.png'
|
||||
enabled: channelopener.valid
|
||||
onClicked: channelopener.openChannel()
|
||||
FlatButton {
|
||||
Layout.fillWidth: true
|
||||
text: qsTr('Open Channel...')
|
||||
icon.source: '../../icons/confirmed.png'
|
||||
enabled: channelopener.valid
|
||||
onClicked: channelopener.openChannel()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -298,7 +298,7 @@ ElDialog {
|
||||
}
|
||||
onChannelOpening: (peer) => {
|
||||
console.log('Channel is opening')
|
||||
app.channelOpenProgressDialog.reset()
|
||||
app.channelOpenProgressDialog.resetDialog()
|
||||
app.channelOpenProgressDialog.peer = peer
|
||||
app.channelOpenProgressDialog.open()
|
||||
}
|
||||
@@ -327,4 +327,8 @@ ElDialog {
|
||||
id: amountFontMetrics
|
||||
font: amountBtc.font
|
||||
}
|
||||
FontMetrics {
|
||||
id: nodeUriFontMetrics
|
||||
font: nodeUri.font
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,23 +41,20 @@ ElDialog {
|
||||
|
||||
InfoTextArea {
|
||||
id: notice
|
||||
Layout.fillWidth: true
|
||||
Layout.bottomMargin: constants.paddingSmall
|
||||
text: Daemon.singlePasswordEnabled || isStartup
|
||||
? qsTr('Please enter password')
|
||||
: qsTr('Wallet <b>%1</b> requires password to unlock').arg(name)
|
||||
iconStyle: InfoTextArea.IconStyle.Warn
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
Label {
|
||||
text: qsTr('Password')
|
||||
Layout.fillWidth: true
|
||||
color: Material.accentColor
|
||||
compact: true
|
||||
iconStyle: InfoTextArea.IconStyle.Info
|
||||
backgroundColor: constants.darkerDialogBackground
|
||||
}
|
||||
|
||||
PasswordField {
|
||||
id: password
|
||||
Layout.fillWidth: true
|
||||
Layout.leftMargin: constants.paddingXLarge
|
||||
placeholderText: qsTr('Password')
|
||||
|
||||
onTextChanged: {
|
||||
unlockButton.enabled = true
|
||||
@@ -77,16 +74,19 @@ ElDialog {
|
||||
}
|
||||
}
|
||||
|
||||
FlatButton {
|
||||
id: unlockButton
|
||||
DialogButtonContainer {
|
||||
Layout.fillWidth: true
|
||||
icon.source: '../../icons/unlock.png'
|
||||
text: qsTr("Unlock")
|
||||
onClicked: {
|
||||
unlock()
|
||||
|
||||
FlatButton {
|
||||
id: unlockButton
|
||||
Layout.fillWidth: true
|
||||
icon.source: '../../icons/unlock.png'
|
||||
text: qsTr("Unlock")
|
||||
onClicked: {
|
||||
unlock()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function unlock() {
|
||||
|
||||
@@ -39,32 +39,23 @@ ElDialog {
|
||||
text: infotext
|
||||
Layout.bottomMargin: constants.paddingMedium
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
Label {
|
||||
Layout.fillWidth: true
|
||||
text: qsTr('Password')
|
||||
color: Material.accentColor
|
||||
backgroundColor: constants.darkerDialogBackground
|
||||
compact: true
|
||||
}
|
||||
|
||||
PasswordField {
|
||||
id: pw_1
|
||||
Layout.leftMargin: constants.paddingXLarge
|
||||
}
|
||||
|
||||
Label {
|
||||
Layout.fillWidth: true
|
||||
text: qsTr('Password (again)')
|
||||
visible: confirmPassword
|
||||
color: Material.accentColor
|
||||
Layout.bottomMargin: constants.paddingSmall
|
||||
placeholderText: qsTr('Password')
|
||||
}
|
||||
|
||||
PasswordField {
|
||||
id: pw_2
|
||||
Layout.leftMargin: constants.paddingXLarge
|
||||
Layout.bottomMargin: constants.paddingSmall
|
||||
visible: confirmPassword
|
||||
showReveal: false
|
||||
echoMode: pw_1.echoMode
|
||||
placeholderText: qsTr('Password (again)')
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
@@ -82,7 +73,7 @@ ElDialog {
|
||||
}
|
||||
|
||||
PasswordStrengthIndicator {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredWidth: passworddialog.width / 2
|
||||
password: pw_1.text
|
||||
}
|
||||
}
|
||||
@@ -98,13 +89,17 @@ ElDialog {
|
||||
}
|
||||
}
|
||||
|
||||
FlatButton {
|
||||
DialogButtonContainer {
|
||||
Layout.fillWidth: true
|
||||
text: qsTr("Ok")
|
||||
icon.source: '../../icons/confirmed.png'
|
||||
enabled: confirmPassword ? pw_1.text.length >= 6 && pw_1.text == pw_2.text : true
|
||||
onClicked: {
|
||||
passwordEntered(pw_1.text)
|
||||
|
||||
FlatButton {
|
||||
Layout.fillWidth: true
|
||||
text: qsTr("Ok")
|
||||
icon.source: '../../icons/confirmed.png'
|
||||
enabled: confirmPassword ? pw_1.text.length >= 6 && pw_1.text == pw_2.text : true
|
||||
onClicked: {
|
||||
passwordEntered(pw_1.text)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,13 +32,17 @@ ElDialog {
|
||||
|
||||
Item { Layout.fillHeight: true; Layout.preferredWidth: 1 }
|
||||
|
||||
FlatButton {
|
||||
DialogButtonContainer {
|
||||
Layout.fillWidth: true
|
||||
text: qsTr('Ok')
|
||||
icon.source: '../../icons/confirmed.png'
|
||||
onClicked: {
|
||||
Network.proxy = proxyconfig.toProxyDict()
|
||||
rootItem.close()
|
||||
|
||||
FlatButton {
|
||||
Layout.fillWidth: true
|
||||
text: qsTr('Ok')
|
||||
icon.source: '../../icons/confirmed.png'
|
||||
onClicked: {
|
||||
Network.proxy = proxyconfig.toProxyDict()
|
||||
rootItem.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,6 +46,7 @@ ElDialog {
|
||||
Layout.fillWidth: true
|
||||
Layout.bottomMargin: constants.paddingLarge
|
||||
text: qsTr('Move the slider to increase your transaction\'s fee. This will improve its position in the mempool')
|
||||
backgroundColor: constants.darkerDialogBackground
|
||||
}
|
||||
|
||||
Label {
|
||||
@@ -107,7 +108,7 @@ ElDialog {
|
||||
color: Material.accentColor
|
||||
}
|
||||
|
||||
TextHighlightPane {
|
||||
DialogHighlightPane {
|
||||
Layout.columnSpan: 2
|
||||
Layout.fillWidth: true
|
||||
height: feepicker.height
|
||||
@@ -127,7 +128,7 @@ ElDialog {
|
||||
color: Material.accentColor
|
||||
}
|
||||
|
||||
TextHighlightPane {
|
||||
DialogHighlightPane {
|
||||
Layout.columnSpan: 2
|
||||
Layout.fillWidth: true
|
||||
visible: !optionstoggle.collapsed
|
||||
@@ -167,6 +168,7 @@ ElDialog {
|
||||
iconStyle: InfoTextArea.IconStyle.Warn
|
||||
visible: rbffeebumper.warning != ''
|
||||
text: rbffeebumper.warning
|
||||
backgroundColor: constants.darkerDialogBackground
|
||||
}
|
||||
|
||||
ToggleLabel {
|
||||
@@ -221,13 +223,17 @@ ElDialog {
|
||||
}
|
||||
}
|
||||
|
||||
FlatButton {
|
||||
id: sendButton
|
||||
DialogButtonContainer {
|
||||
Layout.fillWidth: true
|
||||
text: qsTr('Ok')
|
||||
icon.source: '../../icons/confirmed.png'
|
||||
enabled: rbffeebumper.valid
|
||||
onClicked: doAccept()
|
||||
|
||||
FlatButton {
|
||||
id: sendButton
|
||||
Layout.fillWidth: true
|
||||
text: qsTr('Ok')
|
||||
icon.source: '../../icons/confirmed.png'
|
||||
enabled: rbffeebumper.valid
|
||||
onClicked: doAccept()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@ ElDialog {
|
||||
Layout.fillWidth: true
|
||||
Layout.bottomMargin: constants.paddingLarge
|
||||
text: qsTr('Cancel an unconfirmed transaction by double-spending its inputs back to your wallet with a higher fee.')
|
||||
backgroundColor: constants.darkerDialogBackground
|
||||
}
|
||||
|
||||
Label {
|
||||
@@ -79,7 +80,7 @@ ElDialog {
|
||||
color: Material.accentColor
|
||||
}
|
||||
|
||||
TextHighlightPane {
|
||||
DialogHighlightPane {
|
||||
Layout.columnSpan: 2
|
||||
Layout.fillWidth: true
|
||||
height: feepicker.height
|
||||
@@ -99,6 +100,7 @@ ElDialog {
|
||||
iconStyle: InfoTextArea.IconStyle.Warn
|
||||
visible: txcanceller.warning != ''
|
||||
text: txcanceller.warning
|
||||
backgroundColor: constants.darkerDialogBackground
|
||||
}
|
||||
|
||||
ToggleLabel {
|
||||
@@ -153,13 +155,17 @@ ElDialog {
|
||||
}
|
||||
}
|
||||
|
||||
FlatButton {
|
||||
id: confirmButton
|
||||
DialogButtonContainer {
|
||||
Layout.fillWidth: true
|
||||
text: qsTr('Ok')
|
||||
icon.source: '../../icons/confirmed.png'
|
||||
enabled: txcanceller.valid
|
||||
onClicked: doAccept()
|
||||
|
||||
FlatButton {
|
||||
id: confirmButton
|
||||
Layout.fillWidth: true
|
||||
text: qsTr('Ok')
|
||||
icon.source: '../../icons/confirmed.png'
|
||||
enabled: txcanceller.valid
|
||||
onClicked: doAccept()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,7 +95,7 @@ ElDialog {
|
||||
}
|
||||
}
|
||||
|
||||
ButtonContainer {
|
||||
DialogButtonContainer {
|
||||
Layout.fillWidth: true
|
||||
|
||||
FlatButton {
|
||||
|
||||
@@ -50,7 +50,7 @@ ElDialog {
|
||||
width: parent.width
|
||||
spacing: constants.paddingMedium
|
||||
|
||||
TextHighlightPane {
|
||||
DialogHighlightPane {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.fillWidth: true
|
||||
|
||||
@@ -143,7 +143,7 @@ ElDialog {
|
||||
|
||||
}
|
||||
|
||||
ButtonContainer {
|
||||
DialogButtonContainer {
|
||||
id: buttons
|
||||
Layout.fillWidth: true
|
||||
|
||||
|
||||
@@ -21,7 +21,6 @@ Pane {
|
||||
|
||||
ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.margins: constants.paddingLarge
|
||||
|
||||
InfoTextArea {
|
||||
Layout.fillWidth: true
|
||||
@@ -31,13 +30,13 @@ Pane {
|
||||
}
|
||||
|
||||
Heading {
|
||||
text: qsTr('Pending requests')
|
||||
text: qsTr('Pending payment requests')
|
||||
}
|
||||
|
||||
Frame {
|
||||
background: PaneInsetBackground {}
|
||||
background: PaneInsetBackground {id: bg; vertical: false}
|
||||
|
||||
verticalPadding: 0
|
||||
verticalPadding: bg.lineWidth
|
||||
horizontalPadding: 0
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
@@ -108,4 +107,5 @@ Pane {
|
||||
}
|
||||
}
|
||||
}
|
||||
property color navigationBarBackgroundColor: constants.highlightBackground
|
||||
}
|
||||
|
||||
@@ -6,7 +6,8 @@ import org.electrum
|
||||
|
||||
import "controls"
|
||||
|
||||
// currently not used on android, kept for future use when qt6 camera stops crashing
|
||||
// currently not used on android, kept for testing on desktop, and future use
|
||||
// on android when qt6 camera support becomes usable (i.e. stops crashing)
|
||||
ElDialog {
|
||||
id: scanDialog
|
||||
|
||||
@@ -50,4 +51,6 @@ ElDialog {
|
||||
onClicked: doReject()
|
||||
}
|
||||
}
|
||||
|
||||
onClosed: destroy()
|
||||
}
|
||||
|
||||
@@ -11,8 +11,8 @@ import "controls"
|
||||
ElDialog {
|
||||
id: dialog
|
||||
|
||||
property InvoiceParser invoiceParser
|
||||
property PIResolver piResolver
|
||||
property var invoiceParser // type: InvoiceParser
|
||||
property var piResolver // type: PIResolver
|
||||
|
||||
signal txFound(data: string)
|
||||
signal channelBackupFound(data: string)
|
||||
@@ -66,7 +66,7 @@ ElDialog {
|
||||
}
|
||||
}
|
||||
|
||||
ButtonContainer {
|
||||
DialogButtonContainer {
|
||||
Layout.fillWidth: true
|
||||
|
||||
FlatButton {
|
||||
|
||||
@@ -26,27 +26,31 @@ ElDialog {
|
||||
ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
Layout.leftMargin: constants.paddingLarge
|
||||
Layout.rightMargin: constants.paddingLarge
|
||||
|
||||
ServerConfig {
|
||||
id: serverconfig
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
Layout.leftMargin: constants.paddingLarge
|
||||
Layout.rightMargin: constants.paddingLarge
|
||||
}
|
||||
}
|
||||
|
||||
FlatButton {
|
||||
DialogButtonContainer {
|
||||
Layout.fillWidth: true
|
||||
text: qsTr('Ok')
|
||||
enabled: serverconfig.addressValid
|
||||
icon.source: '../../icons/confirmed.png'
|
||||
onClicked: {
|
||||
let auto_connect = serverconfig.serverConnectMode == ServerConnectModeComboBox.Mode.Autoconnect
|
||||
let server = serverconfig.address
|
||||
let one_server = serverconfig.serverConnectMode == ServerConnectModeComboBox.Mode.Single
|
||||
Network.setServerParameters(server, auto_connect, one_server)
|
||||
rootItem.close()
|
||||
|
||||
FlatButton {
|
||||
Layout.fillWidth: true
|
||||
text: qsTr('Ok')
|
||||
enabled: serverconfig.addressValid
|
||||
icon.source: '../../icons/confirmed.png'
|
||||
onClicked: {
|
||||
let auto_connect = serverconfig.serverConnectMode == ServerConnectModeComboBox.Mode.Autoconnect
|
||||
let server = serverconfig.address
|
||||
let one_server = serverconfig.serverConnectMode == ServerConnectModeComboBox.Mode.Single
|
||||
Network.setServerParameters(server, auto_connect, one_server)
|
||||
rootItem.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,8 +179,9 @@ ElDialog {
|
||||
}
|
||||
}
|
||||
|
||||
ButtonContainer {
|
||||
DialogButtonContainer {
|
||||
Layout.fillWidth: true
|
||||
|
||||
FlatButton {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredWidth: 1
|
||||
|
||||
@@ -42,6 +42,7 @@ ElDialog {
|
||||
: swaphelper.state == SwapHelper.NoService
|
||||
? InfoTextArea.IconStyle.Warn
|
||||
: InfoTextArea.IconStyle.Info
|
||||
backgroundColor: constants.darkerDialogBackground
|
||||
}
|
||||
|
||||
GridLayout {
|
||||
@@ -252,37 +253,32 @@ ElDialog {
|
||||
}
|
||||
|
||||
|
||||
Pane {
|
||||
Button {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
visible: _swaphelper.isNostr()
|
||||
background: Rectangle { color: constants.darkerDialogBackground }
|
||||
padding: 0
|
||||
|
||||
FlatButton {
|
||||
text: qsTr('Choose swap provider')
|
||||
enabled: _swaphelper.state != SwapHelper.Initializing
|
||||
&& _swaphelper.state != SwapHelper.Started
|
||||
&& _swaphelper.state != SwapHelper.Success
|
||||
&& _swaphelper.availableSwapServers.count
|
||||
onClicked: {
|
||||
var dialog = app.nostrSwapServersDialog.createObject(app, {
|
||||
swaphelper: _swaphelper,
|
||||
selectedPubkey: Config.swapServerNPub
|
||||
})
|
||||
dialog.accepted.connect(function() {
|
||||
if (Config.swapServerNPub != dialog.selectedPubkey) {
|
||||
Config.swapServerNPub = dialog.selectedPubkey
|
||||
_swaphelper.setReadyState()
|
||||
}
|
||||
})
|
||||
dialog.open()
|
||||
}
|
||||
text: qsTr('Choose swap provider')
|
||||
enabled: _swaphelper.state != SwapHelper.Initializing
|
||||
&& _swaphelper.state != SwapHelper.Started
|
||||
&& _swaphelper.state != SwapHelper.Success
|
||||
&& _swaphelper.availableSwapServers.count
|
||||
onClicked: {
|
||||
var dialog = app.nostrSwapServersDialog.createObject(app, {
|
||||
swaphelper: _swaphelper,
|
||||
selectedPubkey: Config.swapServerNPub
|
||||
})
|
||||
dialog.accepted.connect(function() {
|
||||
if (Config.swapServerNPub != dialog.selectedPubkey) {
|
||||
Config.swapServerNPub = dialog.selectedPubkey
|
||||
_swaphelper.setReadyState()
|
||||
}
|
||||
})
|
||||
dialog.open()
|
||||
}
|
||||
}
|
||||
|
||||
Item { Layout.fillHeight: true; Layout.preferredWidth: 1 }
|
||||
|
||||
ButtonContainer {
|
||||
DialogButtonContainer {
|
||||
Layout.columnSpan: 2
|
||||
Layout.fillWidth: true
|
||||
FlatButton {
|
||||
|
||||
@@ -58,8 +58,10 @@ ElDialog {
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
TextHighlightPane {
|
||||
|
||||
DialogHighlightPane {
|
||||
Layout.fillWidth: true
|
||||
|
||||
Label {
|
||||
text: qsTr('Enter the list of private keys to sweep into this wallet')
|
||||
width: parent.width
|
||||
@@ -112,7 +114,6 @@ ElDialog {
|
||||
icon.source: '../../icons/qrcode.png'
|
||||
icon.height: constants.iconSizeMedium
|
||||
icon.width: constants.iconSizeMedium
|
||||
scale: 1.2
|
||||
onClicked: {
|
||||
var dialog = app.scanDialog.createObject(app, {
|
||||
hint: qsTr('Scan a private key')
|
||||
@@ -133,24 +134,29 @@ ElDialog {
|
||||
iconStyle: InfoTextArea.IconStyle.Warn
|
||||
Layout.fillWidth: true
|
||||
Layout.margins: constants.paddingMedium
|
||||
backgroundColor: constants.darkerDialogBackground
|
||||
visible: text
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FlatButton {
|
||||
DialogButtonContainer {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredWidth: 1
|
||||
enabled: valid
|
||||
icon.source: '../../icons/tab_send.png'
|
||||
text: qsTr('Sweep...')
|
||||
onClicked: {
|
||||
console.log('sweeping')
|
||||
root.privateKeys = sweepkeys.text
|
||||
root.accept()
|
||||
headerComponent: null
|
||||
|
||||
FlatButton {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredWidth: 1
|
||||
enabled: valid
|
||||
icon.source: '../../icons/tab_send.png'
|
||||
text: qsTr('Sweep...')
|
||||
onClicked: {
|
||||
console.log('sweeping')
|
||||
root.privateKeys = sweepkeys.text
|
||||
root.accept()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Bitcoin {
|
||||
|
||||
@@ -480,6 +480,7 @@ Pane {
|
||||
}
|
||||
|
||||
}
|
||||
property color navigationBarBackgroundColor: constants.highlightBackground
|
||||
|
||||
TxDetails {
|
||||
id: txdetails
|
||||
|
||||
@@ -517,6 +517,7 @@ Pane {
|
||||
}
|
||||
}
|
||||
}
|
||||
property color navigationBarBackgroundColor: constants.highlightBackground
|
||||
|
||||
Connections {
|
||||
target: Daemon
|
||||
|
||||
@@ -2,6 +2,7 @@ import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import QtQuick.Controls.Material
|
||||
import QtQuick.Controls.Material.impl
|
||||
import QtQml
|
||||
|
||||
import org.electrum 1.0
|
||||
@@ -302,6 +303,7 @@ Item {
|
||||
var dialog = receiveDetailsDialog.createObject(mainView)
|
||||
dialog.open()
|
||||
}
|
||||
pressAndHoldIndicator: true
|
||||
onPressAndHold: {
|
||||
Config.userKnowsPressAndHold = true
|
||||
Daemon.currentWallet.deleteExpiredRequests()
|
||||
@@ -316,6 +318,7 @@ Item {
|
||||
text: qsTr('Send')
|
||||
enabled: !invoiceParser.busy && !piResolver.busy && !requestDetails.busy
|
||||
onClicked: openSendDialog()
|
||||
pressAndHoldIndicator: true
|
||||
onPressAndHold: {
|
||||
Config.userKnowsPressAndHold = true
|
||||
app.stack.push(Qt.resolvedUrl('Invoices.qml'))
|
||||
@@ -324,6 +327,7 @@ Item {
|
||||
}
|
||||
}
|
||||
}
|
||||
property color navigationBarBackgroundColor: constants.highlightBackground
|
||||
|
||||
PIResolver {
|
||||
id: piResolver
|
||||
|
||||
@@ -1,128 +0,0 @@
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Controls.Material
|
||||
|
||||
import org.electrum 1.0
|
||||
|
||||
import "controls"
|
||||
|
||||
Item {
|
||||
id: root
|
||||
clip: true
|
||||
implicitHeight: 0
|
||||
|
||||
function open() {
|
||||
state = 'opened'
|
||||
}
|
||||
function close() {
|
||||
state = ''
|
||||
}
|
||||
function toggle() {
|
||||
if (state == 'opened')
|
||||
state = ''
|
||||
else
|
||||
state = 'opened'
|
||||
}
|
||||
|
||||
states: [
|
||||
State {
|
||||
name: 'opened'
|
||||
PropertyChanges { target: root; implicitHeight: detailsPane.height }
|
||||
}
|
||||
]
|
||||
|
||||
transitions: [
|
||||
Transition {
|
||||
from: ''
|
||||
to: 'opened'
|
||||
NumberAnimation { target: root; properties: 'implicitHeight'; duration: 200 }
|
||||
},
|
||||
Transition {
|
||||
from: 'opened'
|
||||
to: ''
|
||||
NumberAnimation { target: root; properties: 'implicitHeight'; duration: 100 }
|
||||
}
|
||||
]
|
||||
|
||||
Pane {
|
||||
id: detailsPane
|
||||
width: parent.width
|
||||
anchors.bottom: parent.bottom
|
||||
padding: 0
|
||||
background: Rectangle {
|
||||
color: Material.dialogColor
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: rootLayout
|
||||
width: parent.width
|
||||
spacing: constants.paddingXLarge
|
||||
|
||||
Item { Layout.preferredWidth: 1; Layout.preferredHeight: 1 }
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
FlatButton {
|
||||
text: qsTr('More details')
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredWidth: 1
|
||||
enabled: app.stack.currentItem.objectName != 'WalletDetails'
|
||||
onClicked: {
|
||||
root.close()
|
||||
app.stack.pushOnRoot(Qt.resolvedUrl('WalletDetails.qml'))
|
||||
}
|
||||
}
|
||||
FlatButton {
|
||||
text: qsTr('Switch wallet')
|
||||
Layout.fillWidth: true
|
||||
icon.source: '../../icons/file.png'
|
||||
Layout.preferredWidth: 1
|
||||
enabled: app.stack.currentItem.objectName != 'Wallets'
|
||||
onClicked: {
|
||||
root.close()
|
||||
app.stack.pushOnRoot(Qt.resolvedUrl('Wallets.qml'))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
property string formattedTotalBalance
|
||||
property string formattedTotalBalanceFiat
|
||||
|
||||
function setBalances() {
|
||||
root.formattedTotalBalance = Config.formatSats(Daemon.currentWallet.totalBalance)
|
||||
if (Daemon.fx.enabled) {
|
||||
root.formattedTotalBalanceFiat = Daemon.fx.fiatValue(Daemon.currentWallet.totalBalance, false)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// instead of all these explicit connections, we should expose
|
||||
// formatted balances directly as a property
|
||||
Connections {
|
||||
target: Config
|
||||
function onBaseUnitChanged() { setBalances() }
|
||||
function onThousandsSeparatorChanged() { setBalances() }
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: Daemon
|
||||
function onWalletLoaded() { setBalances() }
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: Daemon.fx
|
||||
function onEnabledUpdated() { setBalances() }
|
||||
function onQuotesUpdated() { setBalances() }
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: Daemon.currentWallet
|
||||
function onBalanceChanged() {
|
||||
setBalances()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -32,7 +32,6 @@ Pane {
|
||||
|
||||
ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.margins: constants.paddingLarge
|
||||
|
||||
Heading {
|
||||
text: qsTr('Wallets')
|
||||
@@ -42,9 +41,9 @@ Pane {
|
||||
id: detailsFrame
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
verticalPadding: 0
|
||||
verticalPadding: bg.lineWidth
|
||||
horizontalPadding: 0
|
||||
background: PaneInsetBackground {}
|
||||
background: PaneInsetBackground { id: bg; vertical: false }
|
||||
|
||||
ElListView {
|
||||
id: listview
|
||||
@@ -117,27 +116,31 @@ Pane {
|
||||
|
||||
}
|
||||
|
||||
FlatButton {
|
||||
ButtonContainer {
|
||||
Layout.fillWidth: true
|
||||
text: qsTr('Create Wallet')
|
||||
icon.source: '../../icons/add.png'
|
||||
onClicked: {
|
||||
if (Daemon.availableWallets.rowCount() > 0 && Config.walletShouldUseSinglePassword
|
||||
&& (!Daemon.singlePassword || Daemon.numWalletsWithPassword(Daemon.singlePassword) < 1)) {
|
||||
// if the user has wallets but hasn't unlocked any wallet yet force them to do so.
|
||||
// this ensures they know at least one wallets password and can complete the wizard
|
||||
// where they will need to enter the password of an existing wallet.
|
||||
var dialog = app.messageDialog.createObject(app, {
|
||||
title: qsTr('Wallet unlock required'),
|
||||
text: qsTr("You have to unlock any existing wallet first before creating a new wallet."),
|
||||
})
|
||||
dialog.open()
|
||||
} else {
|
||||
rootItem.createWallet()
|
||||
FlatButton {
|
||||
Layout.fillWidth: true
|
||||
text: qsTr('Create Wallet')
|
||||
icon.source: '../../icons/add.png'
|
||||
onClicked: {
|
||||
if (Daemon.availableWallets.rowCount() > 0 && Config.walletShouldUseSinglePassword
|
||||
&& (!Daemon.singlePassword || Daemon.numWalletsWithPassword(Daemon.singlePassword) < 1)) {
|
||||
// if the user has wallets but hasn't unlocked any wallet yet force them to do so.
|
||||
// this ensures they know at least one wallets password and can complete the wizard
|
||||
// where they will need to enter the password of an existing wallet.
|
||||
var dialog = app.messageDialog.createObject(app, {
|
||||
title: qsTr('Wallet unlock required'),
|
||||
text: qsTr("You have to unlock any existing wallet first before creating a new wallet."),
|
||||
})
|
||||
dialog.open()
|
||||
} else {
|
||||
rootItem.createWallet()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
property color navigationBarBackgroundColor: constants.highlightBackground
|
||||
|
||||
Connections {
|
||||
target: Daemon
|
||||
|
||||
@@ -16,7 +16,7 @@ TextField {
|
||||
regularExpression: msatPrecision ? Config.btcAmountRegexMsat : Config.btcAmountRegex
|
||||
}
|
||||
|
||||
property Amount textAsSats
|
||||
property var textAsSats
|
||||
onTextChanged: {
|
||||
textAsSats = Config.unitsToSats(amount.text)
|
||||
if (fiatfield.activeFocus)
|
||||
|
||||
@@ -7,11 +7,22 @@ Container {
|
||||
id: root
|
||||
|
||||
property bool showSeparator: true
|
||||
property color separatorColor: constants.darkerBackground
|
||||
property Component headerComponent: null
|
||||
|
||||
property var _contentRootItem
|
||||
property var _headerItem
|
||||
property Item _layout
|
||||
|
||||
background: Rectangle {
|
||||
color: constants.highlightBackground
|
||||
}
|
||||
|
||||
function fillContentItem() {
|
||||
var contentRoot = containerLayout.createObject(root)
|
||||
var outerLayout = rootLayout.createObject(root)
|
||||
if (headerComponent != null)
|
||||
_headerItem = headerComponent.createObject(outerLayout)
|
||||
var contentRoot = containerLayout.createObject(outerLayout)
|
||||
|
||||
contentRoot.children.length = 0 // empty array
|
||||
let total = contentChildren.length
|
||||
@@ -32,7 +43,8 @@ Container {
|
||||
contentRoot.children.push(button)
|
||||
}
|
||||
|
||||
contentItem = contentRoot
|
||||
contentItem = outerLayout //contentRoot
|
||||
_contentRootItem = contentRoot
|
||||
}
|
||||
|
||||
// override this function to dynamically add buttons.
|
||||
@@ -43,6 +55,13 @@ Container {
|
||||
fillContentItem()
|
||||
}
|
||||
|
||||
Component {
|
||||
id: rootLayout
|
||||
ColumnLayout {
|
||||
spacing: 0
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: containerLayout
|
||||
RowLayout {
|
||||
@@ -59,7 +78,7 @@ Container {
|
||||
Layout.preferredWidth: showSeparator ? 2 : 0
|
||||
Layout.preferredHeight: pheight
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
color: constants.darkerBackground
|
||||
color: root.separatorColor
|
||||
Component.onCompleted: {
|
||||
// create binding here, we need to be able to have stable ref master_idx
|
||||
visible = Qt.binding(function() {
|
||||
@@ -74,3 +93,4 @@ Container {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -6,11 +6,11 @@ import QtQuick.Controls.Material
|
||||
import org.electrum 1.0
|
||||
|
||||
Item {
|
||||
property Amount capacity
|
||||
property Amount localCapacity
|
||||
property Amount remoteCapacity
|
||||
property Amount canSend
|
||||
property Amount canReceive
|
||||
property var capacity // type: Amount
|
||||
property var localCapacity // type: Amount
|
||||
property var remoteCapacity // type: Amount
|
||||
property var canSend // type: Amount
|
||||
property var canReceive // type: Amount
|
||||
property bool frozenForSending: false
|
||||
property bool frozenForReceiving: false
|
||||
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
|
||||
ButtonContainer {
|
||||
id: root
|
||||
separatorColor: constants.darkerDialogBackground
|
||||
background: Rectangle {
|
||||
color: "transparent"
|
||||
}
|
||||
headerComponent: Component {
|
||||
Rectangle {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 2
|
||||
Layout.leftMargin: constants.paddingSmall
|
||||
Layout.rightMargin: constants.paddingSmall
|
||||
color: root.separatorColor
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import QtQuick
|
||||
|
||||
TextHighlightPane {
|
||||
backgroundColor: constants.darkerDialogBackground
|
||||
}
|
||||
@@ -17,7 +17,7 @@ Dialog {
|
||||
property bool _wasOpened: false
|
||||
|
||||
// Add bottom padding for Android navigation bar if needed
|
||||
bottomPadding: needsSystemBarPadding ? app.navigationBarHeight : 0
|
||||
bottomPadding: needsSystemBarPadding && app.keyboardFreeZone.state != 'visible' ? app.navigationBarHeight : 0
|
||||
|
||||
// called to finally close dialog after checks by onClosing handler in main.qml
|
||||
function doClose() {
|
||||
@@ -106,10 +106,10 @@ Dialog {
|
||||
|
||||
Rectangle {
|
||||
Layout.fillWidth: true
|
||||
Layout.leftMargin: constants.paddingXXSmall
|
||||
Layout.rightMargin: constants.paddingXXSmall
|
||||
height: 1
|
||||
color: Qt.rgba(0,0,0,0.5)
|
||||
Layout.leftMargin: constants.paddingSmall
|
||||
Layout.rightMargin: constants.paddingSmall
|
||||
Layout.preferredHeight: 2
|
||||
color: constants.darkerDialogBackground
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ TabButton {
|
||||
checkable: false
|
||||
|
||||
property bool textUnderIcon: true
|
||||
property bool pressAndHoldIndicator: false
|
||||
|
||||
font.pixelSize: constants.fontSizeSmall
|
||||
icon.width: constants.iconSizeMedium
|
||||
@@ -25,4 +26,45 @@ TabButton {
|
||||
font: control.font
|
||||
color: !control.enabled ? control.Material.hintTextColor : control.down || control.checked ? control.Material.accentColor : control.Material.foreground
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: indicator
|
||||
anchors.top: control.top
|
||||
anchors.horizontalCenter: control.horizontalCenter
|
||||
width: 0
|
||||
opacity: 0
|
||||
height: 3
|
||||
color: control.Material.accentColor
|
||||
|
||||
states: State {
|
||||
name: 'pressing'
|
||||
when: pressAndHoldIndicator && control.pressed
|
||||
PropertyChanges {
|
||||
target: indicator
|
||||
width: control.width
|
||||
opacity: 1
|
||||
}
|
||||
}
|
||||
|
||||
transitions: Transition {
|
||||
to: 'pressing'
|
||||
SequentialAnimation {
|
||||
PauseAnimation {
|
||||
duration: 200
|
||||
}
|
||||
ParallelAnimation {
|
||||
NumberAnimation {
|
||||
target: indicator
|
||||
property: "width"
|
||||
duration: 600
|
||||
}
|
||||
NumberAnimation {
|
||||
target: indicator
|
||||
property: "opacity"
|
||||
duration: 600
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import QtQuick.Controls.Material
|
||||
import org.electrum 1.0
|
||||
|
||||
GridLayout {
|
||||
required property Amount amount
|
||||
required property var amount // type: Amount
|
||||
property bool showAlt: true
|
||||
property bool singleLine: true
|
||||
property bool valid: true
|
||||
|
||||
@@ -35,7 +35,7 @@ ElDialog {
|
||||
implicitHeight: rootLayout.height + topPadding + bottomPadding
|
||||
padding: constants.paddingLarge
|
||||
background: Rectangle {
|
||||
color: constants.lighterBackground
|
||||
color: constants.highlightBackground
|
||||
}
|
||||
ColumnLayout {
|
||||
id: rootLayout
|
||||
|
||||
@@ -3,25 +3,33 @@ import QtQuick.Controls.Material
|
||||
|
||||
Rectangle {
|
||||
property color baseColor: Material.background
|
||||
property bool vertical: true
|
||||
property bool horizontal: true
|
||||
property int lineWidth: 2
|
||||
|
||||
Rectangle {
|
||||
anchors { left: parent.left; top: parent.top; right: parent.right }
|
||||
height: 1
|
||||
height: lineWidth
|
||||
color: Qt.darker(baseColor, 1.50)
|
||||
visible: horizontal
|
||||
}
|
||||
Rectangle {
|
||||
anchors { left: parent.left; top: parent.top; bottom: parent.bottom }
|
||||
width: 1
|
||||
width: lineWidth
|
||||
color: Qt.darker(baseColor, 1.50)
|
||||
visible: vertical
|
||||
}
|
||||
Rectangle {
|
||||
anchors { left: parent.left; bottom: parent.bottom; right: parent.right }
|
||||
height: 1
|
||||
height: lineWidth
|
||||
color: Qt.lighter(baseColor, 1.50)
|
||||
visible: horizontal
|
||||
}
|
||||
Rectangle {
|
||||
anchors { right: parent.right; top: parent.top; bottom: parent.bottom }
|
||||
width: 1
|
||||
width: lineWidth
|
||||
color: Qt.lighter(baseColor, 1.50)
|
||||
visible: vertical
|
||||
}
|
||||
color: Qt.darker(baseColor, 1.15)
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ RowLayout {
|
||||
property alias text: password_tf.text
|
||||
property alias tf: password_tf
|
||||
property alias echoMode: password_tf.echoMode
|
||||
property alias placeholderText: password_tf.placeholderText
|
||||
property bool showReveal: true
|
||||
|
||||
signal accepted
|
||||
|
||||
@@ -53,68 +53,62 @@ Item {
|
||||
model: proxy_type_map
|
||||
}
|
||||
|
||||
GridLayout {
|
||||
columns: 2
|
||||
ColumnLayout {
|
||||
// columns: 2
|
||||
Layout.fillWidth: true
|
||||
spacing: constants.paddingSmall
|
||||
|
||||
Label {
|
||||
text: qsTr("Address")
|
||||
enabled: address.enabled
|
||||
}
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.rightMargin: constants.paddingLarge
|
||||
|
||||
TextField {
|
||||
id: address
|
||||
enabled: proxy_enabled_cb.checked
|
||||
inputMethodHints: Qt.ImhNoPredictiveText
|
||||
TextField {
|
||||
id: address
|
||||
Layout.fillWidth: true
|
||||
enabled: proxy_enabled_cb.checked
|
||||
inputMethodHints: Qt.ImhNoPredictiveText
|
||||
placeholderText: qsTr("Address")
|
||||
}
|
||||
|
||||
TextField {
|
||||
id: port
|
||||
Layout.fillWidth: true
|
||||
enabled: proxy_enabled_cb.checked
|
||||
inputMethodHints: Qt.ImhDigitsOnly
|
||||
placeholderText: qsTr("Port")
|
||||
}
|
||||
}
|
||||
|
||||
Label {
|
||||
text: qsTr("Port")
|
||||
enabled: port.enabled
|
||||
}
|
||||
|
||||
TextField {
|
||||
id: port
|
||||
enabled: proxy_enabled_cb.checked
|
||||
inputMethodHints: Qt.ImhDigitsOnly
|
||||
}
|
||||
|
||||
Label {
|
||||
text: qsTr("Username")
|
||||
Layout.topMargin: constants.paddingLarge
|
||||
text: qsTr("Authentication")
|
||||
enabled: username_tf.enabled
|
||||
}
|
||||
|
||||
TextField {
|
||||
id: username_tf
|
||||
Layout.fillWidth: true
|
||||
Layout.rightMargin: constants.paddingLarge
|
||||
enabled: proxy_enabled_cb.checked
|
||||
inputMethodHints: Qt.ImhNoPredictiveText
|
||||
}
|
||||
|
||||
Label {
|
||||
text: qsTr("Password")
|
||||
enabled: password_tf.enabled
|
||||
placeholderText: qsTr("Username")
|
||||
}
|
||||
|
||||
PasswordField {
|
||||
id: password_tf
|
||||
enabled: proxy_enabled_cb.checked
|
||||
placeholderText: qsTr("Password")
|
||||
}
|
||||
}
|
||||
|
||||
Pane {
|
||||
Button {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.topMargin: constants.paddingLarge
|
||||
padding: 0
|
||||
background: Rectangle {
|
||||
color: constants.darkerDialogBackground
|
||||
}
|
||||
FlatButton {
|
||||
enabled: proxy_enabled_cb.checked && !_probing
|
||||
text: qsTr('Detect Tor proxy')
|
||||
onClicked: {
|
||||
_probing = true
|
||||
Network.probeTor()
|
||||
}
|
||||
enabled: proxy_enabled_cb.checked && !_probing
|
||||
text: qsTr('Detect Tor proxy')
|
||||
onClicked: {
|
||||
_probing = true
|
||||
Network.probeTor()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,10 @@ Pane {
|
||||
kbd.keyEvent(keycode, key)
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
color: constants.darkerDialogBackground
|
||||
}
|
||||
|
||||
FlatButton {
|
||||
anchors.fill: parent
|
||||
|
||||
|
||||
@@ -35,10 +35,11 @@ Pane {
|
||||
TextArea {
|
||||
id: seedtextarea
|
||||
Layout.fillWidth: true
|
||||
Layout.minimumHeight: fontMetrics.height * 3 + topPadding + bottomPadding
|
||||
Layout.minimumHeight: fontMetrics.lineSpacing * 3 + topPadding + bottomPadding
|
||||
|
||||
rightPadding: constants.paddingLarge
|
||||
leftPadding: constants.paddingLarge
|
||||
bottomPadding: constants.paddingXLarge
|
||||
|
||||
wrapMode: TextInput.WordWrap
|
||||
font.bold: true
|
||||
@@ -47,8 +48,9 @@ Pane {
|
||||
inputMethodHints: Qt.ImhSensitiveData | Qt.ImhLowercaseOnly | Qt.ImhNoPredictiveText
|
||||
readOnly: AppController.isAndroid()
|
||||
|
||||
background: Rectangle {
|
||||
color: constants.darkerBackground
|
||||
Component.onCompleted: {
|
||||
background.filled = true
|
||||
background.fillColor = constants.seedTextAreaBackground
|
||||
}
|
||||
|
||||
onTextChanged: {
|
||||
@@ -66,16 +68,19 @@ Pane {
|
||||
Rectangle {
|
||||
anchors.fill: contentText
|
||||
color: root.indicatorValid ? 'green' : 'red'
|
||||
border.color: Material.accentColor
|
||||
radius: 2
|
||||
radius: 3
|
||||
}
|
||||
Label {
|
||||
id: contentText
|
||||
text: root.indicatorText
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
leftPadding: root.indicatorText != '' ? constants.paddingLarge : 0
|
||||
rightPadding: root.indicatorText != '' ? constants.paddingLarge : 0
|
||||
anchors.rightMargin: constants.paddingXXSmall
|
||||
anchors.bottomMargin: constants.paddingXXSmall
|
||||
leftPadding: root.indicatorText != '' ? constants.paddingMedium : 0
|
||||
rightPadding: root.indicatorText != '' ? constants.paddingMedium : 0
|
||||
topPadding: root.indicatorText != '' ? constants.paddingXXSmall/2 : 0
|
||||
bottomPadding: root.indicatorText != '' ? constants.paddingXXSmall/2 : 0
|
||||
font.bold: false
|
||||
font.pixelSize: constants.fontSizeSmall
|
||||
}
|
||||
@@ -99,7 +104,7 @@ Pane {
|
||||
Layout.margins: constants.paddingXXSmall
|
||||
width: suggestionLabel.width
|
||||
height: suggestionLabel.height
|
||||
color: constants.lighterBackground
|
||||
color: constants.darkerDialogBackground
|
||||
radius: constants.paddingXXSmall
|
||||
Label {
|
||||
id: suggestionLabel
|
||||
@@ -127,7 +132,7 @@ Pane {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: kbd.width / 1.75
|
||||
visible: !root.readOnly
|
||||
onKeyEvent: {
|
||||
onKeyEvent: (keycode, text) => {
|
||||
if (keycode == Qt.Key_Backspace) {
|
||||
if (seedtextarea.text.length > 0)
|
||||
seedtextarea.text = seedtextarea.text.substring(0, seedtextarea.text.length-1)
|
||||
|
||||
@@ -43,7 +43,7 @@ Item {
|
||||
|
||||
HelpButton {
|
||||
Layout.alignment: Qt.AlignRight
|
||||
heading: qsTr('Connection mode')+':'
|
||||
heading: qsTr('Connection mode') + ':'
|
||||
helptext: Config.getTranslatedMessage('MSG_CONNECTMODE_SERVER_HELP') + '<br/><br/>' +
|
||||
Config.getTranslatedMessage('MSG_CONNECTMODE_NODES_HELP') + '<ul>' +
|
||||
'<li><b>' + Config.getTranslatedMessage('MSG_CONNECTMODE_AUTOCONNECT') +
|
||||
@@ -56,39 +56,32 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
Label {
|
||||
text: qsTr("Server")
|
||||
enabled: address_tf.enabled
|
||||
}
|
||||
|
||||
TextHighlightPane {
|
||||
TextField {
|
||||
id: address_tf
|
||||
Layout.fillWidth: true
|
||||
|
||||
TextField {
|
||||
id: address_tf
|
||||
enabled: server_connect_mode_cb.currentValue != ServerConnectModeComboBox.Mode.Autoconnect
|
||||
width: parent.width
|
||||
inputMethodHints: Qt.ImhNoPredictiveText
|
||||
enabled: server_connect_mode_cb.currentValue != ServerConnectModeComboBox.Mode.Autoconnect
|
||||
inputMethodHints: Qt.ImhNoPredictiveText
|
||||
placeholderText: qsTr('Server')
|
||||
|
||||
property bool valid: true
|
||||
property bool valid: true
|
||||
|
||||
function validate() {
|
||||
if (!enabled) {
|
||||
valid = true
|
||||
return
|
||||
}
|
||||
valid = Network.isValidServerAddress(address_tf.text)
|
||||
function validate() {
|
||||
if (!enabled) {
|
||||
valid = true
|
||||
return
|
||||
}
|
||||
valid = Network.isValidServerAddress(address_tf.text)
|
||||
}
|
||||
|
||||
onTextChanged: validate()
|
||||
onEnabledChanged: validate()
|
||||
onTextChanged: validate()
|
||||
onEnabledChanged: validate()
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: "red"
|
||||
opacity: 0.2
|
||||
visible: !parent.valid
|
||||
}
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: "red"
|
||||
opacity: 0.2
|
||||
visible: !parent.valid
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import QtQuick.Controls.Material
|
||||
Pane {
|
||||
padding: constants.paddingSmall
|
||||
|
||||
property color backgroundColor: Qt.lighter(Material.background, 1.15)
|
||||
property color backgroundColor: constants.highlightBackground
|
||||
property color borderColor: 'transparent'
|
||||
|
||||
background: Rectangle {
|
||||
|
||||
@@ -7,7 +7,6 @@ import QtQuick.Controls.Material.impl
|
||||
import QtQuick.Window
|
||||
|
||||
import QtQml
|
||||
import QtMultimedia
|
||||
|
||||
import org.electrum 1.0
|
||||
|
||||
@@ -37,6 +36,7 @@ ApplicationWindow
|
||||
property alias stack: mainStackView
|
||||
property alias keyboardFreeZone: _keyboardFreeZone
|
||||
property alias infobanner: _infobanner
|
||||
property color _navigationBarBackgroundColor: 'transparent'
|
||||
|
||||
property string pendingIntent: ""
|
||||
|
||||
@@ -128,7 +128,7 @@ ApplicationWindow
|
||||
|
||||
background: Rectangle {
|
||||
implicitHeight: 48
|
||||
color: Material.dialogColor
|
||||
color: constants.dialogColor
|
||||
|
||||
layer.enabled: true
|
||||
layer.effect: ElevationEffect {
|
||||
@@ -288,13 +288,21 @@ ApplicationWindow
|
||||
mainStackView.clear()
|
||||
mainStackView.push(Qt.resolvedUrl(item_url))
|
||||
}
|
||||
function updateStylingFromItem(item) {
|
||||
_navigationBarBackgroundColor = item && 'navigationBarBackgroundColor' in item
|
||||
? item.navigationBarBackgroundColor
|
||||
: 'transparent'
|
||||
}
|
||||
onCurrentItemChanged: updateStylingFromItem(currentItem)
|
||||
}
|
||||
|
||||
// Add bottom padding for navigation bar on Android when UI is edge-to-edge
|
||||
Item {
|
||||
visible: app.navigationBarHeight > 0
|
||||
visible: app.navigationBarHeight > 0 && _keyboardFreeZone.state != 'visible'
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: app.navigationBarHeight
|
||||
|
||||
Rectangle { anchors.fill: parent; color: _navigationBarBackgroundColor }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -450,12 +458,6 @@ ApplicationWindow
|
||||
onFinished: destroy()
|
||||
}
|
||||
}
|
||||
Component {
|
||||
id: _qtScanDialog
|
||||
ScanDialog {
|
||||
onClosed: destroy()
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: crashDialog
|
||||
@@ -533,7 +535,8 @@ ApplicationWindow
|
||||
if (AppController.isAndroid()) {
|
||||
app.scanDialog = _scanDialog
|
||||
} else {
|
||||
app.scanDialog = _qtScanDialog
|
||||
// for running on Desktop. uses QtMultimedia.
|
||||
app.scanDialog = Qt.createComponent('ScanDialog.qml')
|
||||
}
|
||||
|
||||
function continueWithServerConnection() {
|
||||
|
||||
@@ -30,6 +30,7 @@ WizardComponent {
|
||||
InfoTextArea {
|
||||
Layout.fillWidth: true
|
||||
Layout.bottomMargin: constants.paddingLarge
|
||||
backgroundColor: constants.darkerDialogBackground
|
||||
text: qsTr('Your seed is important!') + ' ' +
|
||||
qsTr('If you lose your seed, your money will be permanently lost.') + ' ' +
|
||||
qsTr('To make sure that you have properly saved your seed, please retype it here.')
|
||||
@@ -42,6 +43,7 @@ WizardComponent {
|
||||
SeedTextArea {
|
||||
id: confirm
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: constants.paddingSmall
|
||||
placeholderText: qsTr('Enter your seed')
|
||||
onTextChanged: checkValid()
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ WizardComponent {
|
||||
wrapMode: Text.Wrap
|
||||
}
|
||||
|
||||
TextHighlightPane {
|
||||
DialogHighlightPane {
|
||||
Layout.fillWidth: true
|
||||
|
||||
visible: cosigner
|
||||
|
||||
@@ -47,6 +47,7 @@ WizardComponent {
|
||||
InfoTextArea {
|
||||
id: warningtext
|
||||
Layout.fillWidth: true
|
||||
backgroundColor: constants.darkerDialogBackground
|
||||
iconStyle: InfoTextArea.IconStyle.Warn
|
||||
}
|
||||
|
||||
|
||||
@@ -61,6 +61,7 @@ WizardComponent {
|
||||
id: validationtext
|
||||
Layout.fillWidth: true
|
||||
Layout.columnSpan: 2
|
||||
backgroundColor: constants.darkerDialogBackground
|
||||
visible: text
|
||||
iconStyle: InfoTextArea.IconStyle.Error
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ WizardComponent {
|
||||
wrapMode: Text.Wrap
|
||||
}
|
||||
|
||||
TextHighlightPane {
|
||||
DialogHighlightPane {
|
||||
Layout.fillWidth: true
|
||||
|
||||
visible: cosigner
|
||||
@@ -159,7 +159,6 @@ WizardComponent {
|
||||
icon.source: '../../../icons/qrcode.png'
|
||||
icon.height: constants.iconSizeMedium
|
||||
icon.width: constants.iconSizeMedium
|
||||
scale: 1.2
|
||||
onClicked: {
|
||||
var dialog = app.scanDialog.createObject(app, {
|
||||
hint: cosigner
|
||||
|
||||
@@ -117,7 +117,7 @@ WizardComponent {
|
||||
wrapMode: Text.Wrap
|
||||
}
|
||||
|
||||
TextHighlightPane {
|
||||
DialogHighlightPane {
|
||||
Layout.columnSpan: 2
|
||||
Layout.fillWidth: true
|
||||
|
||||
@@ -169,6 +169,7 @@ WizardComponent {
|
||||
|
||||
ComboBox {
|
||||
id: seed_variant_cb
|
||||
|
||||
visible: !is2fa
|
||||
|
||||
textRole: 'text'
|
||||
@@ -188,13 +189,16 @@ WizardComponent {
|
||||
id: infotext
|
||||
Layout.fillWidth: true
|
||||
Layout.columnSpan: 2
|
||||
Layout.bottomMargin: constants.paddingLarge
|
||||
Layout.topMargin: constants.paddingLarge
|
||||
compact: true
|
||||
backgroundColor: constants.darkerDialogBackground
|
||||
}
|
||||
|
||||
SeedTextArea {
|
||||
id: seedtext
|
||||
Layout.fillWidth: true
|
||||
Layout.columnSpan: 2
|
||||
Layout.topMargin: constants.paddingLarge
|
||||
|
||||
placeholderText: cosigner ? qsTr('Enter cosigner seed') : qsTr('Enter your seed')
|
||||
|
||||
|
||||
@@ -27,8 +27,10 @@ WizardComponent {
|
||||
ColumnLayout {
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
|
||||
InfoTextArea {
|
||||
Layout.preferredWidth: parent.width
|
||||
backgroundColor: constants.darkerDialogBackground
|
||||
text: qsTr('Enter a list of Bitcoin addresses (this will create a watching-only wallet), or a list of private keys.')
|
||||
}
|
||||
|
||||
@@ -67,7 +69,6 @@ WizardComponent {
|
||||
icon.source: '../../../icons/qrcode.png'
|
||||
icon.height: constants.iconSizeMedium
|
||||
icon.width: constants.iconSizeMedium
|
||||
scale: 1.2
|
||||
onClicked: {
|
||||
var dialog = app.scanDialog.createObject(app, {
|
||||
hint: bitcoin.isAddressList(import_ta.text)
|
||||
|
||||
@@ -41,6 +41,7 @@ WizardComponent {
|
||||
|
||||
InfoTextArea {
|
||||
Layout.preferredWidth: parent.width
|
||||
backgroundColor: constants.darkerDialogBackground
|
||||
text: qsTr('Choose the number of participants, and the number of signatures needed to unlock funds in your wallet.')
|
||||
}
|
||||
|
||||
|
||||
@@ -161,19 +161,19 @@ WizardComponent {
|
||||
|
||||
InfoTextArea {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: constants.paddingMedium
|
||||
Layout.bottomMargin: constants.paddingMedium
|
||||
compact: true
|
||||
backgroundColor: constants.darkerDialogBackground
|
||||
text: qsTr('You can override the suggested derivation path.') + ' ' +
|
||||
qsTr('If you are not sure what this is, leave this field unchanged.')
|
||||
}
|
||||
|
||||
Label {
|
||||
text: qsTr('Derivation path')
|
||||
}
|
||||
|
||||
TextField {
|
||||
id: derivationpathtext
|
||||
Layout.fillWidth: true
|
||||
Layout.leftMargin: constants.paddingMedium
|
||||
inputMethodHints: Qt.ImhNoPredictiveText
|
||||
placeholderText: qsTr('Derivation path')
|
||||
|
||||
onTextChanged: validate()
|
||||
}
|
||||
@@ -181,43 +181,36 @@ WizardComponent {
|
||||
InfoTextArea {
|
||||
id: validationtext
|
||||
Layout.fillWidth: true
|
||||
backgroundColor: constants.darkerDialogBackground
|
||||
visible: text
|
||||
iconStyle: InfoTextArea.IconStyle.Error
|
||||
}
|
||||
|
||||
Pane {
|
||||
Button {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.topMargin: constants.paddingLarge
|
||||
padding: 0
|
||||
visible: !isMultisig
|
||||
background: Rectangle {
|
||||
color: Qt.lighter(Material.dialogColor, 1.5)
|
||||
}
|
||||
|
||||
FlatButton {
|
||||
text: qsTr('Detect Existing Accounts')
|
||||
onClicked: {
|
||||
var dialog = bip39recoveryDialog.createObject(mainLayout, {
|
||||
walletType: wizard_data['wallet_type'],
|
||||
seed: wizard_data['seed'],
|
||||
seedExtraWords: wizard_data['seed_extra_words']
|
||||
})
|
||||
dialog.accepted.connect(function () {
|
||||
// select matching script type button and set derivation path
|
||||
for (var i = 0; i < scripttypegroup.buttons.length; i++) {
|
||||
var btn = scripttypegroup.buttons[i]
|
||||
if (btn.visible && btn.scripttype == dialog.scriptType) {
|
||||
btn.checked = true
|
||||
derivationpathtext.text = dialog.derivationPath
|
||||
return
|
||||
}
|
||||
text: qsTr('Detect Existing Accounts')
|
||||
onClicked: {
|
||||
var dialog = bip39recoveryDialog.createObject(mainLayout, {
|
||||
walletType: wizard_data['wallet_type'],
|
||||
seed: wizard_data['seed'],
|
||||
seedExtraWords: wizard_data['seed_extra_words']
|
||||
})
|
||||
dialog.accepted.connect(function () {
|
||||
// select matching script type button and set derivation path
|
||||
for (var i = 0; i < scripttypegroup.buttons.length; i++) {
|
||||
var btn = scripttypegroup.buttons[i]
|
||||
if (btn.visible && btn.scripttype == dialog.scriptType) {
|
||||
btn.checked = true
|
||||
derivationpathtext.text = dialog.derivationPath
|
||||
return
|
||||
}
|
||||
})
|
||||
dialog.open()
|
||||
}
|
||||
}
|
||||
})
|
||||
dialog.open()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import QtQuick.Controls
|
||||
|
||||
import org.electrum 1.0
|
||||
|
||||
import "../controls"
|
||||
|
||||
WizardComponent {
|
||||
valid: true
|
||||
|
||||
property string masterPubkey: wizard_data['multisig_master_pubkey']
|
||||
|
||||
ColumnLayout {
|
||||
width: parent.width
|
||||
|
||||
Label {
|
||||
text: qsTr('Here is your master public key. Please share it with your cosigners')
|
||||
Layout.fillWidth: true
|
||||
wrapMode: Text.Wrap
|
||||
}
|
||||
|
||||
TextHighlightPane {
|
||||
Layout.fillWidth: true
|
||||
|
||||
RowLayout {
|
||||
width: parent.width
|
||||
Label {
|
||||
Layout.fillWidth: true
|
||||
text: masterPubkey
|
||||
font.pixelSize: constants.fontSizeMedium
|
||||
font.family: FixedFont
|
||||
wrapMode: Text.Wrap
|
||||
}
|
||||
ToolButton {
|
||||
icon.source: '../../../icons/share.png'
|
||||
icon.color: 'transparent'
|
||||
onClicked: {
|
||||
var dialog = app.genericShareDialog.createObject(app,
|
||||
{ title: qsTr('Master public key'), text: masterPubkey }
|
||||
)
|
||||
dialog.open()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -45,12 +45,14 @@ WizardComponent {
|
||||
|
||||
Label {
|
||||
Layout.fillWidth: true
|
||||
text: !enforceExistingPassword ? qsTr('Enter password') : qsTr('Enter existing password')
|
||||
Layout.bottomMargin: constants.paddingSmall
|
||||
text: !enforceExistingPassword ? qsTr('Enter a password to secure access to your wallet') : qsTr('Enter your existing wallet password')
|
||||
wrapMode: Text.Wrap
|
||||
}
|
||||
|
||||
PasswordField {
|
||||
id: password1
|
||||
placeholderText: qsTr('Enter password')
|
||||
onTextChanged: {
|
||||
if (enforceExistingPassword) {
|
||||
root.passwordMatchesAnyExisting = false
|
||||
@@ -59,16 +61,12 @@ WizardComponent {
|
||||
}
|
||||
}
|
||||
|
||||
Label {
|
||||
text: qsTr('Enter password (again)')
|
||||
visible: !enforceExistingPassword
|
||||
}
|
||||
|
||||
PasswordField {
|
||||
id: password2
|
||||
showReveal: false
|
||||
echoMode: password1.echoMode
|
||||
visible: !enforceExistingPassword
|
||||
placeholderText: qsTr('Enter password (again)')
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
@@ -100,12 +98,14 @@ WizardComponent {
|
||||
text: qsTr('Passwords don\'t match')
|
||||
visible: (password1.text != password2.text) && !enforceExistingPassword
|
||||
iconStyle: InfoTextArea.IconStyle.Warn
|
||||
backgroundColor: constants.darkerDialogBackground
|
||||
}
|
||||
InfoTextArea {
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
text: qsTr('Password too short')
|
||||
visible: (password1.text == password2.text) && !valid && !enforceExistingPassword
|
||||
visible: (password1.text == password2.text) && password1.text != '' && !valid && !enforceExistingPassword
|
||||
iconStyle: InfoTextArea.IconStyle.Warn
|
||||
backgroundColor: constants.darkerDialogBackground
|
||||
}
|
||||
InfoTextArea {
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
@@ -116,6 +116,7 @@ WizardComponent {
|
||||
qsTr("Creating new wallets with different passwords is not supported.")
|
||||
].join("\n")
|
||||
iconStyle: InfoTextArea.IconStyle.Info
|
||||
backgroundColor: constants.darkerDialogBackground
|
||||
}
|
||||
InfoTextArea {
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
@@ -123,6 +124,13 @@ WizardComponent {
|
||||
visible: password1.text != "" && !valid && enforceExistingPassword
|
||||
text: qsTr('Password does not match any existing wallets password.')
|
||||
iconStyle: InfoTextArea.IconStyle.Warn
|
||||
backgroundColor: constants.darkerDialogBackground
|
||||
}
|
||||
|
||||
Item {
|
||||
Layout.preferredWidth: 1
|
||||
Layout.fillHeight: true
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,7 +107,7 @@ ElDialog {
|
||||
spacing: 0
|
||||
|
||||
// root Item in Wizard, capture back button here and delegate to main
|
||||
Keys.onReleased: {
|
||||
Keys.onReleased: (event) => {
|
||||
if (event.key == Qt.Key_Back) {
|
||||
console.log("Back button within wizard")
|
||||
app.close() // this handles unwind of dialogs/stack
|
||||
@@ -159,12 +159,13 @@ ElDialog {
|
||||
}
|
||||
}
|
||||
|
||||
ButtonContainer {
|
||||
DialogButtonContainer {
|
||||
Layout.fillWidth: true
|
||||
|
||||
FlatButton {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredWidth: 1
|
||||
Layout.preferredHeight: constants.fingerWidth
|
||||
visible: pages.currentIndex == 0
|
||||
text: qsTr("Cancel")
|
||||
onClicked: wizard.doReject()
|
||||
@@ -172,6 +173,7 @@ ElDialog {
|
||||
FlatButton {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredWidth: 1
|
||||
Layout.preferredHeight: constants.fingerWidth
|
||||
visible: pages.currentIndex > 0
|
||||
text: qsTr('Back')
|
||||
onClicked: pages.prev()
|
||||
@@ -179,6 +181,7 @@ ElDialog {
|
||||
FlatButton {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredWidth: 1
|
||||
Layout.preferredHeight: constants.fingerWidth
|
||||
text: qsTr("Next")
|
||||
visible: !pages.lastpage
|
||||
enabled: pages.pagevalid
|
||||
@@ -188,6 +191,7 @@ ElDialog {
|
||||
id: finishButton
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredWidth: 1
|
||||
Layout.preferredHeight: constants.fingerWidth
|
||||
text: qsTr("Finish")
|
||||
visible: pages.lastpage
|
||||
enabled: pages.pagevalid
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from PyQt6.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject
|
||||
from PyQt6.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject, QVariant
|
||||
|
||||
from electrum.logging import get_logger
|
||||
from electrum.util import UserFacingException
|
||||
@@ -35,12 +35,13 @@ class QEAddressDetails(AuthMixin, QObject):
|
||||
self._historyModel = None
|
||||
|
||||
walletChanged = pyqtSignal()
|
||||
@pyqtProperty(QEWallet, notify=walletChanged)
|
||||
def wallet(self):
|
||||
@pyqtProperty(QVariant, notify=walletChanged)
|
||||
def wallet(self) -> QEWallet:
|
||||
return self._wallet
|
||||
|
||||
@wallet.setter
|
||||
def wallet(self, wallet: QEWallet):
|
||||
assert isinstance(wallet, QEWallet)
|
||||
if self._wallet != wallet:
|
||||
self._wallet = wallet
|
||||
self.walletChanged.emit()
|
||||
|
||||
@@ -2,7 +2,7 @@ import threading
|
||||
from enum import IntEnum
|
||||
from typing import Optional, TYPE_CHECKING
|
||||
|
||||
from PyQt6.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject, pyqtEnum
|
||||
from PyQt6.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject, pyqtEnum, QVariant
|
||||
|
||||
from electrum.i18n import _
|
||||
from electrum.gui import messages
|
||||
@@ -61,12 +61,13 @@ class QEChannelDetails(AuthMixin, QObject, QtEventListener):
|
||||
self.unregister_callbacks()
|
||||
|
||||
walletChanged = pyqtSignal()
|
||||
@pyqtProperty(QEWallet, notify=walletChanged)
|
||||
@pyqtProperty(QVariant, notify=walletChanged)
|
||||
def wallet(self) -> QEWallet:
|
||||
return self._wallet
|
||||
|
||||
@wallet.setter
|
||||
def wallet(self, wallet: QEWallet):
|
||||
assert wallet is None or isinstance(wallet, QEWallet)
|
||||
if self._wallet != wallet:
|
||||
self._wallet = wallet
|
||||
self.walletChanged.emit()
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from PyQt6.QtCore import Qt, QAbstractListModel, QModelIndex
|
||||
from PyQt6.QtCore import pyqtProperty, pyqtSignal, pyqtSlot
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from PyQt6.QtCore import Qt, QAbstractListModel, QModelIndex, pyqtProperty, pyqtSignal, pyqtSlot
|
||||
|
||||
from electrum.lnchannel import ChannelState
|
||||
from electrum.lnutil import LOCAL, REMOTE
|
||||
@@ -12,6 +13,9 @@ from electrum.gui.common_qt.util import qt_event_listener, QtEventListener
|
||||
from .qetypes import QEAmount
|
||||
from .qemodelfilter import QEFilterProxyModel
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from electrum.wallet import Abstract_Wallet
|
||||
|
||||
|
||||
class QEChannelListModel(QAbstractListModel, QtEventListener):
|
||||
_logger = get_logger(__name__)
|
||||
@@ -27,7 +31,7 @@ class QEChannelListModel(QAbstractListModel, QtEventListener):
|
||||
|
||||
_network_signal = pyqtSignal(str, object)
|
||||
|
||||
def __init__(self, wallet, parent=None):
|
||||
def __init__(self, wallet: 'Abstract_Wallet', parent=None):
|
||||
super().__init__(parent)
|
||||
self.wallet = wallet
|
||||
self._channels = []
|
||||
|
||||
@@ -4,7 +4,7 @@ from asyncio.exceptions import TimeoutError
|
||||
from typing import Optional
|
||||
import electrum_ecc as ecc
|
||||
|
||||
from PyQt6.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject
|
||||
from PyQt6.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject, QVariant
|
||||
|
||||
from electrum.i18n import _
|
||||
from electrum.gui import messages
|
||||
@@ -14,7 +14,6 @@ from electrum.lntransport import extract_nodeid, ConnStringFormatError
|
||||
from electrum.bitcoin import DummyAddress
|
||||
from electrum.lnworker import hardcoded_trampoline_nodes
|
||||
from electrum.logging import get_logger
|
||||
from electrum.fee_policy import FeePolicy
|
||||
from electrum.transaction import PartialTransaction
|
||||
|
||||
from .auth import AuthMixin, auth_protect
|
||||
@@ -55,12 +54,13 @@ class QEChannelOpener(QObject, AuthMixin):
|
||||
self._updating_max = False
|
||||
|
||||
walletChanged = pyqtSignal()
|
||||
@pyqtProperty(QEWallet, notify=walletChanged)
|
||||
def wallet(self):
|
||||
@pyqtProperty(QVariant, notify=walletChanged)
|
||||
def wallet(self) -> QEWallet:
|
||||
return self._wallet
|
||||
|
||||
@wallet.setter
|
||||
def wallet(self, wallet: QEWallet):
|
||||
assert wallet is None or isinstance(wallet, QEWallet)
|
||||
if self._wallet != wallet:
|
||||
self._wallet = wallet
|
||||
self.walletChanged.emit()
|
||||
@@ -79,12 +79,13 @@ class QEChannelOpener(QObject, AuthMixin):
|
||||
self.validate()
|
||||
|
||||
amountChanged = pyqtSignal()
|
||||
@pyqtProperty(QEAmount, notify=amountChanged)
|
||||
def amount(self):
|
||||
@pyqtProperty(QVariant, notify=amountChanged)
|
||||
def amount(self) -> QEAmount:
|
||||
return self._amount
|
||||
|
||||
@amount.setter
|
||||
def amount(self, amount: QEAmount):
|
||||
assert amount is None or isinstance(amount, QEAmount)
|
||||
if self._amount != amount:
|
||||
self._amount.copyFrom(amount)
|
||||
self.amountChanged.emit()
|
||||
|
||||
@@ -4,7 +4,7 @@ from enum import IntEnum
|
||||
from typing import Optional, Dict, Any, Tuple
|
||||
from urllib.parse import urlparse
|
||||
|
||||
from PyQt6.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject, pyqtEnum, QTimer
|
||||
from PyQt6.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject, pyqtEnum, QTimer, QVariant
|
||||
|
||||
from electrum.i18n import _
|
||||
from electrum.logging import get_logger
|
||||
@@ -111,12 +111,13 @@ class QEInvoice(QObject, QtEventListener):
|
||||
self.determine_can_pay()
|
||||
|
||||
walletChanged = pyqtSignal()
|
||||
@pyqtProperty(QEWallet, notify=walletChanged)
|
||||
def wallet(self):
|
||||
@pyqtProperty(QVariant, notify=walletChanged)
|
||||
def wallet(self) -> QEWallet:
|
||||
return self._wallet
|
||||
|
||||
@wallet.setter
|
||||
def wallet(self, wallet: QEWallet):
|
||||
assert wallet is None or isinstance(wallet, QEWallet)
|
||||
if self._wallet != wallet:
|
||||
self._wallet = wallet
|
||||
self.walletChanged.emit()
|
||||
@@ -153,12 +154,13 @@ class QEInvoice(QObject, QtEventListener):
|
||||
self._amount.copyFrom(QEAmount(from_invoice=self._effectiveInvoice))
|
||||
return self._amount
|
||||
|
||||
@pyqtProperty(QEAmount, notify=amountOverrideChanged)
|
||||
def amountOverride(self):
|
||||
@pyqtProperty(QVariant, notify=amountOverrideChanged)
|
||||
def amountOverride(self) -> QEAmount:
|
||||
return self._amountOverride
|
||||
|
||||
@amountOverride.setter
|
||||
def amountOverride(self, new_amount: QEAmount):
|
||||
assert new_amount is None or isinstance(new_amount, QEAmount)
|
||||
self._logger.debug(f'set new override amount {repr(new_amount)}')
|
||||
self._amountOverride.copyFrom(new_amount)
|
||||
self.amountOverrideChanged.emit()
|
||||
|
||||