diff --git a/.cirrus.yml b/.cirrus.yml index c37ad7e0c1d4..7a5ee585f8d3 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -182,6 +182,7 @@ task: task: name: "build: Android (QML $APK_ARCH)" + timeout_in: 90m container: dockerfile: contrib/android/Dockerfile cpu: 8 diff --git a/.gitignore b/.gitignore index 8ac25d80a065..9ade38ca33f2 100644 --- a/.gitignore +++ b/.gitignore @@ -12,8 +12,7 @@ electrum/locale/ packages env/ .buildozer -.buildozer_kivy/ -.buildozer_qml/ +.buildozer_*/ bin/ /app.fil .idea diff --git a/contrib/android/Dockerfile b/contrib/android/Dockerfile index 08e887caf821..054b58cdf4e5 100644 --- a/contrib/android/Dockerfile +++ b/contrib/android/Dockerfile @@ -1,6 +1,6 @@ # based on https://github.com/kivy/python-for-android/blob/master/Dockerfile -FROM debian:bullseye@sha256:43ef0c6c3585d5b406caa7a0f232ff5a19c1402aeb415f68bcd1cf9d10180af8 +FROM debian:bookworm@sha256:d568e251e460295a8743e9d5ef7de673c5a8f9027db11f4e666e96fb5bed708e ENV DEBIAN_FRONTEND=noninteractive @@ -31,12 +31,12 @@ RUN apt -y update -qq \ ENV ANDROID_NDK_HOME="${ANDROID_HOME}/android-ndk" -ENV ANDROID_NDK_VERSION="22b" -ENV ANDROID_NDK_HASH="ac3a0421e76f71dd330d0cd55f9d99b9ac864c4c034fc67e0d671d022d4e806b" +ENV ANDROID_NDK_VERSION="23b" +ENV ANDROID_NDK_HASH="c6e97f9c8cfe5b7be0a9e6c15af8e7a179475b7ded23e2d1c1fa0945d6fb4382" 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 -ENV ANDROID_NDK_ARCHIVE="android-ndk-r${ANDROID_NDK_VERSION}-linux-x86_64.zip" +ENV ANDROID_NDK_ARCHIVE="android-ndk-r${ANDROID_NDK_VERSION}-linux.zip" ENV ANDROID_NDK_DL_URL="https://dl.google.com/android/repository/${ANDROID_NDK_ARCHIVE}" # download and install Android NDK @@ -53,9 +53,8 @@ RUN curl --location --progress-bar \ 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="8092744" -ENV ANDROID_SDK_BUILD_TOOLS_VERSION="30.0.3" -ENV ANDROID_SDK_HASH="d71f75333d79c9c6ef5c39d3456c6c58c613de30e6a751ea0dbd433e8f8b9cbf" +ENV ANDROID_SDK_TOOLS_VERSION="9477386" +ENV ANDROID_SDK_HASH="bd1aa17c7ef10066949c88dc6c9c8d536be27f992a1f3b5a584f9bd2ba5646a0" 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}" @@ -77,19 +76,22 @@ RUN mkdir --parents "${ANDROID_SDK_HOME}/.android/" \ # accept Android licenses (JDK necessary!) RUN apt -y update -qq \ && apt -y install -qq --no-install-recommends --allow-downgrades \ - openjdk-11-jdk-headless \ + openjdk-17-jdk-headless \ && apt -y autoremove RUN yes | ${ANDROID_SDK_MANAGER} --licenses > /dev/null + +ENV ANDROID_SDK_BUILD_TOOLS_VERSION="31.0.0" + # download platforms, API, build tools -RUN ${ANDROID_SDK_MANAGER} "platforms;android-30" > /dev/null && \ +RUN ${ANDROID_SDK_MANAGER} "platforms;android-31" > /dev/null && \ ${ANDROID_SDK_MANAGER} "build-tools;${ANDROID_SDK_BUILD_TOOLS_VERSION}" > /dev/null && \ ${ANDROID_SDK_MANAGER} "extras;android;m2repository" > /dev/null && \ chmod +x "${ANDROID_SDK_HOME}/cmdline-tools/bin/avdmanager" # download ANT -ENV APACHE_ANT_VERSION="1.9.4" -ENV APACHE_ANT_HASH="66d3edcbb0eba11387705cd89178ffb65e55cd53f13ca35c1bb983c0f9992540" +ENV APACHE_ANT_VERSION="1.10.13" +ENV APACHE_ANT_HASH="776be4a5704158f00ef3f23c0327546e38159389bc8f39abbfe114913f88bab1" ENV APACHE_ANT_ARCHIVE="apache-ant-${APACHE_ANT_VERSION}-bin.tar.gz" ENV APACHE_ANT_DL_URL="https://archive.apache.org/dist/ant/binaries/${APACHE_ANT_ARCHIVE}" ENV APACHE_ANT_HOME="${ANDROID_HOME}/apache-ant" @@ -139,6 +141,15 @@ RUN apt -y update -qq \ && apt -y autoremove \ && apt -y clean +# cross compile deps for Qt6 +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 + # create new user to avoid using root; but with sudo access and no password for convenience. ARG UID=1000 @@ -154,12 +165,16 @@ RUN chown --recursive ${USER} ${WORK_DIR} ${ANDROID_SDK_HOME} RUN chown ${USER} /opt USER ${USER} +# venv, VIRTUAL_ENV is used by buildozer to indicate a venv environemnt +ENV VIRTUAL_ENV=/opt/venv +RUN python3 -m venv ${VIRTUAL_ENV} +ENV PATH="${VIRTUAL_ENV}/bin:${PATH}" COPY contrib/deterministic-build/requirements-build-base.txt /opt/deterministic-build/ COPY contrib/deterministic-build/requirements-build-android.txt /opt/deterministic-build/ -RUN python3 -m pip install --no-build-isolation --no-dependencies --user \ +RUN /opt/venv/bin/python3 -m pip install --no-build-isolation --no-dependencies \ -r /opt/deterministic-build/requirements-build-base.txt -RUN python3 -m pip install --no-build-isolation --no-dependencies --no-binary :all: --user \ +RUN /opt/venv/bin/python3 -m pip install --no-build-isolation --no-dependencies --no-binary :all: \ -r /opt/deterministic-build/requirements-build-android.txt # install buildozer @@ -167,10 +182,11 @@ RUN cd /opt \ && git clone https://github.com/kivy/buildozer \ && cd buildozer \ && git remote add sombernight https://github.com/SomberNight/buildozer \ + && git remote add accumulator https://github.com/accumulator/buildozer \ && git fetch --all \ - # commit: from branch sombernight/electrum_20210421 (note: careful with force-pushing! see #8162) - && git checkout "6f03256e8312f8d1e5a6da3a2a1bf06e2738325e^{commit}" \ - && python3 -m pip install --no-build-isolation --no-dependencies --user -e . + # commit: from branch electrum-qt6 (note: careful with force-pushing! see #8162) \ + && git checkout "ce4f2257249fdf4ff1f4cb8983fd7ac44174a274^{commit}" \ + && /opt/venv/bin/python3 -m pip install --no-build-isolation --no-dependencies -e . # install python-for-android RUN cd /opt \ @@ -179,9 +195,10 @@ RUN cd /opt \ && git remote add sombernight https://github.com/SomberNight/python-for-android \ && git remote add accumulator https://github.com/accumulator/python-for-android \ && git fetch --all \ - # commit: from branch accumulator/electrum_20210421d (note: careful with force-pushing! see #8162) - && git checkout "052b9f7945bae557347fa4a4b418040d9da9eaff^{commit}" \ - && python3 -m pip install --no-build-isolation --no-dependencies --user -e . + # commit: from branch accumulator/qt6-wip (note: careful with force-pushing! see #8162) \ + # + && git checkout "eb4a3522373e0b4e2749b8a8bc965ff51355ea35^{commit}" \ + && /opt/venv/bin/python3 -m pip install --no-build-isolation --no-dependencies -e . # build env vars ENV USE_SDK_WRAPPER=1 diff --git a/contrib/android/apt.sources.list b/contrib/android/apt.sources.list index e8c300942e3c..7a9bb8a98757 100644 --- a/contrib/android/apt.sources.list +++ b/contrib/android/apt.sources.list @@ -1,2 +1,2 @@ -deb https://snapshot.debian.org/archive/debian/20230317T205011Z/ bullseye main -deb-src https://snapshot.debian.org/archive/debian/20230317T205011Z/ bullseye main \ No newline at end of file +deb https://snapshot.debian.org/archive/debian/20230629T090352Z/ bookworm main +deb-src https://snapshot.debian.org/archive/debian/20230629T090352Z/ bookworm main diff --git a/contrib/android/build.sh b/contrib/android/build.sh index 5dea8ede0c48..be1514ba701d 100755 --- a/contrib/android/build.sh +++ b/contrib/android/build.sh @@ -48,7 +48,6 @@ docker build \ --file "$CONTRIB_ANDROID/Dockerfile" \ "$PROJECT_ROOT" - # maybe do fresh clone if [ ! -z "$ELECBUILD_COMMIT" ] ; then info "ELECBUILD_COMMIT=$ELECBUILD_COMMIT. doing fresh clone and git checkout." diff --git a/contrib/android/buildozer_qml.spec b/contrib/android/buildozer_qml.spec index 655b9ae88e00..e8e854b6f5f5 100644 --- a/contrib/android/buildozer_qml.spec +++ b/contrib/android/buildozer_qml.spec @@ -24,6 +24,7 @@ source.exclude_dirs = bin, build, dist, contrib, env, electrum/www, electrum/gui/qt, electrum/gui/kivy, + electrum/plugins/payserver, packages/qdarkstyle, packages/qtpy, packages/bin, @@ -55,8 +56,8 @@ requirements = libffi, libsecp256k1, cryptography, - pyqt5sip, - pyqt5, + pyqt6sip, + pyqt6, pillow, libzbar @@ -84,22 +85,22 @@ android.permissions = INTERNET, CAMERA, WRITE_EXTERNAL_STORAGE # (int) Android API to use (compileSdkVersion) # note: when changing, Dockerfile also needs to be changed to install corresponding build tools -android.api = 30 +android.api = 31 # (int) Android targetSdkVersion -android.target_sdk_version = 31 +android.target_sdk_version = 33 # (int) Minimum API required. You will need to set the android.ndk_api to be as low as this value. android.minapi = 21 # (str) Android NDK version to use -android.ndk = 22b +android.ndk = 23b # (int) Android NDK API to use (optional). This is the minimum API your app will support. android.ndk_api = 21 # (bool) Use --private data storage (True) or --dir public storage (False) -android.private_storage = True +#android.private_storage = True # (str) Android NDK directory (if empty, it will be automatically downloaded.) android.ndk_path = /opt/android/android-ndk @@ -137,9 +138,25 @@ android.add_jars = .buildozer/android/platform/*/build/libs_collections/Electrum # (list) List of Java files to add to the android project (can be java or a # directory containing the files) -# android.add_src = ... -# android.add_activities = ... -android.gradle_dependencies = com.android.support:support-compat:28.0.0 +android.add_src = electrum/gui/qml/java_classes/ + +android.gradle_dependencies = + com.android.support:support-compat:28.0.0, + me.dm7.barcodescanner:zxing:1.9.8 + +android.add_activities = org.electrum.qr.SimpleScannerActivity + +# (list) Put these files or directories in the apk res directory. +# The option may be used in three ways, the value may contain one or zero ':' +# Some examples: +# 1) A file to add to resources, legal resource names contain ['a-z','0-9','_'] +# android.add_resources = my_icons/all-inclusive.png:drawable/all_inclusive.png +# 2) A directory, here 'legal_icons' must contain resources of one kind +# android.add_resources = legal_icons:drawable +# 3) A directory, here 'legal_resources' must contain one or more directories, +# each of a resource kind: drawable, xml, etc... +# android.add_resources = legal_resources +android.add_resources = electrum/gui/qml/android_res/layout:layout # (str) python-for-android branch to use, if not master, useful to try # not yet merged features. @@ -199,7 +216,7 @@ p4a.local_recipes = %(source.dir)s/contrib/android/p4a_recipes/ #p4a.hook = # (str) Bootstrap to use for android builds -p4a.bootstrap = qt5 +p4a.bootstrap = qt6 # (int) port number to specify an explicit --port= p4a argument (eg for bootstrap flask) #p4a.port = diff --git a/contrib/android/make_apk.sh b/contrib/android/make_apk.sh index 7f2a348900b0..977148bfb391 100755 --- a/contrib/android/make_apk.sh +++ b/contrib/android/make_apk.sh @@ -90,16 +90,16 @@ fi if [[ "$2" == "all" ]] ; then # build all apks # FIXME failures are not propagated out: we should fail the script if any arch build fails - export APP_ANDROID_ARCH=armeabi-v7a + export APP_ANDROID_ARCHS=armeabi-v7a make $TARGET - export APP_ANDROID_ARCH=arm64-v8a + export APP_ANDROID_ARCHS=arm64-v8a make $TARGET - #export APP_ANDROID_ARCH=x86 + #export APP_ANDROID_ARCHS=x86 #make $TARGET - export APP_ANDROID_ARCH=x86_64 + export APP_ANDROID_ARCHS=x86_64 make $TARGET else - export APP_ANDROID_ARCH=$2 + export APP_ANDROID_ARCHS=$2 make $TARGET fi diff --git a/contrib/android/p4a_recipes/Pillow/__init__.py b/contrib/android/p4a_recipes/Pillow/__init__.py index a08cd3b284d2..fd9a91ea7d19 100644 --- a/contrib/android/p4a_recipes/Pillow/__init__.py +++ b/contrib/android/p4a_recipes/Pillow/__init__.py @@ -6,13 +6,13 @@ util = load_source('util', os.path.join(os.path.dirname(os.path.dirname(__file__)), 'util.py')) -assert PillowRecipe._version == "7.0.0" +assert PillowRecipe._version == "8.4.0" assert PillowRecipe.depends == ['png', 'jpeg', 'freetype', 'setuptools', 'python3'] assert PillowRecipe.python_depends == [] class PillowRecipePinned(util.InheritedRecipeMixin, PillowRecipe): - sha512sum = "187173a525d4f3f01b4898633263b53a311f337aa7b159c64f79ba8c7006fd44798a058e7cc5d8f1116bad008e4142ff303456692329fe73b0e115ef5c225d73" + sha512sum = "d395f69ccb37c52a3b6f45836700ffbc3173afae31848cc61d7b47db88ca1594541023beb9a14fd9067aca664e182c7d6e3300ab3e3095c31afe8dcbc6e08233" recipe = PillowRecipePinned() diff --git a/contrib/android/p4a_recipes/libffi/__init__.py b/contrib/android/p4a_recipes/libffi/__init__.py index 4867cc0311ba..e2aad27cbc43 100644 --- a/contrib/android/p4a_recipes/libffi/__init__.py +++ b/contrib/android/p4a_recipes/libffi/__init__.py @@ -6,13 +6,13 @@ util = load_source('util', os.path.join(os.path.dirname(os.path.dirname(__file__)), 'util.py')) -assert LibffiRecipe._version == "v3.3" +assert LibffiRecipe._version == "v3.4.2" assert LibffiRecipe.depends == [] assert LibffiRecipe.python_depends == [] class LibffiRecipePinned(util.InheritedRecipeMixin, LibffiRecipe): - sha512sum = "62798fb31ba65fa2a0e1f71dd3daca30edcf745dc562c6f8e7126e54db92572cc63f5aa36d927dd08375bb6f38a2380ebe6c5735f35990681878fc78fc9dbc83" + sha512sum = "d399319efcca375fe901b05722e25eca31d11a4261c6a5d5079480bbc552d4e4b42de2026912689d3b2f886ebb3c8bebbea47102e38a2f6acbc526b8d5bba388" recipe = LibffiRecipePinned() diff --git a/contrib/android/p4a_recipes/libiconv/__init__.py b/contrib/android/p4a_recipes/libiconv/__init__.py index 4d0ba2f5926d..552f42f1c79b 100644 --- a/contrib/android/p4a_recipes/libiconv/__init__.py +++ b/contrib/android/p4a_recipes/libiconv/__init__.py @@ -6,13 +6,13 @@ util = load_source('util', os.path.join(os.path.dirname(os.path.dirname(__file__)), 'util.py')) -assert LibIconvRecipe._version == "1.15" +assert LibIconvRecipe._version == "1.16" assert LibIconvRecipe.depends == [] assert LibIconvRecipe.python_depends == [] class LibIconvRecipePinned(util.InheritedRecipeMixin, LibIconvRecipe): - sha512sum = "1233fe3ca09341b53354fd4bfe342a7589181145a1232c9919583a8c9979636855839049f3406f253a9d9829908816bb71fd6d34dd544ba290d6f04251376b1a" + sha512sum = "365dac0b34b4255a0066e8033a8b3db4bdb94b9b57a9dca17ebf2d779139fe935caf51a465d17fd8ae229ec4b926f3f7025264f37243432075e5583925bb77b7" recipe = LibIconvRecipePinned() diff --git a/contrib/android/p4a_recipes/pyjnius/__init__.py b/contrib/android/p4a_recipes/pyjnius/__init__.py index 536cbde49cb6..a8a415c826fd 100644 --- a/contrib/android/p4a_recipes/pyjnius/__init__.py +++ b/contrib/android/p4a_recipes/pyjnius/__init__.py @@ -6,13 +6,13 @@ util = load_source('util', os.path.join(os.path.dirname(os.path.dirname(__file__)), 'util.py')) -assert PyjniusRecipe._version == "1.3.0" -assert PyjniusRecipe.depends == [('genericndkbuild', 'sdl2', 'qt5'), 'six', 'python3'] +assert PyjniusRecipe._version == "1.5.0" +assert PyjniusRecipe.depends == [('genericndkbuild', 'sdl2', 'qt6'), 'six', 'python3'] assert PyjniusRecipe.python_depends == [] class PyjniusRecipePinned(util.InheritedRecipeMixin, PyjniusRecipe): - sha512sum = "5a3475afcda5afbef6e1a67bab508e3c24bd564efda5ac38ae7669d39b4bfdbfaaa83f435f26d39b3d849d3a167a9c136c9ac6b2bfcc0bda09ef1c00aa66cf25" + sha512sum = "e47ff08bdcda8fc9ef9617fc84515a85404d77cfce3ede3e190ae21221837a4275840e14976271f38eb5d514682d22eab5d83d8ca94dbf3a6b47d4effa109790" recipe = PyjniusRecipePinned() diff --git a/contrib/android/p4a_recipes/pyqt5/__init__.py b/contrib/android/p4a_recipes/pyqt5/__init__.py deleted file mode 100644 index c21caaa69326..000000000000 --- a/contrib/android/p4a_recipes/pyqt5/__init__.py +++ /dev/null @@ -1,18 +0,0 @@ -import os - -from pythonforandroid.recipes.pyqt5 import PyQt5Recipe -from pythonforandroid.util import load_source - -util = load_source('util', os.path.join(os.path.dirname(os.path.dirname(__file__)), 'util.py')) - - -assert PyQt5Recipe._version == "5.15.9" -assert PyQt5Recipe.depends == ['qt5', 'pyjnius', 'setuptools', 'pyqt5sip', 'hostpython3', 'pyqt_builder'] -assert PyQt5Recipe.python_depends == [] - - -class PyQt5RecipePinned(util.InheritedRecipeMixin, PyQt5Recipe): - sha512sum = "1c07d93aefe1c24e80851eb4631b80a99e7ba06e823181325456edb90285d3d22417a9f7d4c3ff9c6195bd801e7dc2bbabf0587af844a5e4b0a410c4611d119e" - - -recipe = PyQt5RecipePinned() diff --git a/contrib/android/p4a_recipes/pyqt5sip/__init__.py b/contrib/android/p4a_recipes/pyqt5sip/__init__.py deleted file mode 100644 index 8150bed4e56e..000000000000 --- a/contrib/android/p4a_recipes/pyqt5sip/__init__.py +++ /dev/null @@ -1,18 +0,0 @@ -import os - -from pythonforandroid.recipes.pyqt5sip import PyQt5SipRecipe -from pythonforandroid.util import load_source - -util = load_source('util', os.path.join(os.path.dirname(os.path.dirname(__file__)), 'util.py')) - - -assert PyQt5SipRecipe._version == "12.11.1" -assert PyQt5SipRecipe.depends == ['setuptools', 'python3'] -assert PyQt5SipRecipe.python_depends == [] - - -class PyQt5SipRecipePinned(util.InheritedRecipeMixin, PyQt5SipRecipe): - sha512sum = "9a24b6e8356fdb1070672ee37e5f4259d72a75bb60376ad0946274331ae29a6cceb98a6c5a278bf5e8015a3d493c925bacab8593ef02c310ff3773bd3ee46a5d" - - -recipe = PyQt5SipRecipePinned() diff --git a/contrib/android/p4a_recipes/pyqt6/__init__.py b/contrib/android/p4a_recipes/pyqt6/__init__.py new file mode 100644 index 000000000000..37b2a2119341 --- /dev/null +++ b/contrib/android/p4a_recipes/pyqt6/__init__.py @@ -0,0 +1,18 @@ +import os + +from pythonforandroid.recipes.pyqt6 import PyQt6Recipe +from pythonforandroid.util import load_source + +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.python_depends == [] + + +class PyQt6RecipePinned(util.InheritedRecipeMixin, PyQt6Recipe): + sha512sum = "51e5f0d028ee7984876da1653cb135d61e2c402f18b939a92477888cc7c86d3bc2889477403dee6b3d9f66519ee3236d344323493b4c2c2e658e1637b10e53bf" + + +recipe = PyQt6RecipePinned() diff --git a/contrib/android/p4a_recipes/pyqt6sip/__init__.py b/contrib/android/p4a_recipes/pyqt6sip/__init__.py new file mode 100644 index 000000000000..301c157627fb --- /dev/null +++ b/contrib/android/p4a_recipes/pyqt6sip/__init__.py @@ -0,0 +1,18 @@ +import os + +from pythonforandroid.recipes.pyqt6sip import PyQt6SipRecipe +from pythonforandroid.util import load_source + +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.python_depends == [] + + +class PyQt6SipRecipePinned(util.InheritedRecipeMixin, PyQt6SipRecipe): + sha512sum = "1e4170d167a326afe6df86e4a35e209299548054981cb2e5d56da234ef9db4d8594bcb05b6be363c3bc6252776ae9de63d589a3d9f33fba8250d39cdb5e9061a" + + +recipe = PyQt6SipRecipePinned() diff --git a/contrib/android/p4a_recipes/pyqt_builder/__init__.py b/contrib/android/p4a_recipes/pyqt_builder/__init__.py index b43a1208dd0c..6b6a674887a3 100644 --- a/contrib/android/p4a_recipes/pyqt_builder/__init__.py +++ b/contrib/android/p4a_recipes/pyqt_builder/__init__.py @@ -1,13 +1,13 @@ from pythonforandroid.recipes.pyqt_builder import PyQtBuilderRecipe -assert PyQtBuilderRecipe._version == "1.14.1" +assert PyQtBuilderRecipe._version == "1.15.1" assert PyQtBuilderRecipe.depends == ["sip", "packaging", "python3"] assert PyQtBuilderRecipe.python_depends == [] class PyQtBuilderRecipePinned(PyQtBuilderRecipe): - sha512sum = "4de9be2c42f38fbc22d46a31dd6da37c02620bb112a674ef846a4eb7f862715852e1d7328da1e0d0e33f78475166fe3c690e710e18bfeb48f840f137831a2182" + sha512sum = "61ee73b6bb922c04739da60025ab50d35d345d2e298943305fcbd3926cda31d732cc5e5b0dbfc39f5eb85c0f0b091b8c3f5fee00dcc240d7849c5c4191c1368a" recipe = PyQtBuilderRecipePinned() diff --git a/contrib/android/p4a_recipes/qt5/__init__.py b/contrib/android/p4a_recipes/qt5/__init__.py deleted file mode 100644 index 562b21832276..000000000000 --- a/contrib/android/p4a_recipes/qt5/__init__.py +++ /dev/null @@ -1,16 +0,0 @@ -import os - -from pythonforandroid.recipes.qt5 import Qt5Recipe - -from pythonforandroid.util import load_source - -util = load_source('util', os.path.join(os.path.dirname(os.path.dirname(__file__)), 'util.py')) - -assert Qt5Recipe._version == "95254e52c658729e80f741324045034c15ce9cb0" -assert Qt5Recipe.depends == ['python3'] -assert Qt5Recipe.python_depends == [] - -class Qt5RecipePinned(util.InheritedRecipeMixin, Qt5Recipe): - pass - -recipe = Qt5RecipePinned() diff --git a/contrib/android/p4a_recipes/qt6/__init__.py b/contrib/android/p4a_recipes/qt6/__init__.py new file mode 100644 index 000000000000..1a91e0bf3e3f --- /dev/null +++ b/contrib/android/p4a_recipes/qt6/__init__.py @@ -0,0 +1,19 @@ +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.depends == ['python3', 'hostqt6'] +assert Qt6Recipe.python_depends == [] + +class Qt6RecipePinned(util.InheritedRecipeMixin, Qt6Recipe): + sha512sum = "0bdbe8b9a43390c98cf19e851ec5394bc78438d227cf9d0d7a3748aee9a32a7f14fc46f52d4fa283819f21413567080aee7225c566af5278557f5e1992674da3" + # sha512sum = "ca8ea3b81c121886636988275f7fa8ae6d19f7be02669e63ab19b4285b611057a41279db9532c25ae87baa3904b010e1db68b899cd0eda17a5a8d3d87098b4d5" + + +recipe = Qt6RecipePinned() diff --git a/contrib/android/p4a_recipes/sip/__init__.py b/contrib/android/p4a_recipes/sip/__init__.py index ee4f4495650f..d1aea65e4110 100644 --- a/contrib/android/p4a_recipes/sip/__init__.py +++ b/contrib/android/p4a_recipes/sip/__init__.py @@ -1,13 +1,13 @@ from pythonforandroid.recipes.sip import SipRecipe -assert SipRecipe._version == "6.7.7" -assert SipRecipe.depends == ["setuptools", "packaging", "toml", "ply", "python3"], SipRecipe.depends +assert SipRecipe._version == "6.7.9" +assert SipRecipe.depends == ["setuptools", "packaging", "tomli", "ply", "python3"], SipRecipe.depends assert SipRecipe.python_depends == [] class SipRecipePinned(SipRecipe): - sha512sum = "b41a1e53e8bad1fca08eda2c89b8a7cabe6cb9e54d0ddeba0c718499b0288633fb6b90128d54f3df2420e20bb217d3df224750d30e865487d2b0a640fba82444" + sha512sum = "bb9d0d0d92002b6fd33f7e8ebe8cd62456dacc16b5734b73760b1ba14fb9b1f2b9b6640b40196c6cf5f345e1afde48bdef39675c4d3480041771325d4cf3c233" recipe = SipRecipePinned() diff --git a/contrib/android/p4a_recipes/sqlite3/__init__.py b/contrib/android/p4a_recipes/sqlite3/__init__.py index 70b6bd932377..d7e604f467a9 100644 --- a/contrib/android/p4a_recipes/sqlite3/__init__.py +++ b/contrib/android/p4a_recipes/sqlite3/__init__.py @@ -6,13 +6,13 @@ util = load_source('util', os.path.join(os.path.dirname(os.path.dirname(__file__)), 'util.py')) -assert Sqlite3Recipe._version == "3.34.1" +assert Sqlite3Recipe._version == "3.35.5" assert Sqlite3Recipe.depends == [] assert Sqlite3Recipe.python_depends == [] class Sqlite3RecipePinned(util.InheritedRecipeMixin, Sqlite3Recipe): - sha512sum = "8a936f1c34fc9036cadf5bd53f9ee594135c2efdef1d2c82bd4fdf3e0218afde710fc4c436cfc992687d008e6086a697da0487352ed88809d677e05d824940dd" + sha512sum = "9684fee89224f0c975c280cb6b2c64adb040334bc5517dfe0e354b0557459fa3ae642c4289a7a5265f65b3ad5b6747db8068a1e5172fbb8edec7f6d964ecbb20" recipe = Sqlite3RecipePinned() diff --git a/contrib/android/p4a_recipes/tomli/__init__.py b/contrib/android/p4a_recipes/tomli/__init__.py new file mode 100644 index 000000000000..2798afd5df50 --- /dev/null +++ b/contrib/android/p4a_recipes/tomli/__init__.py @@ -0,0 +1,13 @@ +from pythonforandroid.recipes.tomli import TomliRecipe + + +assert TomliRecipe._version == "2.0.1" +assert TomliRecipe.depends == ["setuptools", "python3"] +assert TomliRecipe.python_depends == [] + + +class TomliRecipePinned(TomliRecipe): + sha512sum = "fd410039e255e2b3359e999d69a5a2d38b9b89b77e8557f734f2621dfbd5e1207e13aecc11589197ec22594c022f07f41b4cfe486a3a719281a595c95fd19ecf" + + +recipe = TomliRecipePinned() diff --git a/contrib/freeze_containers_distro.sh b/contrib/freeze_containers_distro.sh index 5566ca4916e8..8095b2826dc6 100755 --- a/contrib/freeze_containers_distro.sh +++ b/contrib/freeze_containers_distro.sh @@ -7,7 +7,7 @@ set -e DEBIAN_SNAPSHOT_BASE="https://snapshot.debian.org/archive/debian/" DEBIAN_APPIMAGE_DISTRO="buster" # should match build-linux/appimage Dockerfile base DEBIAN_WINE_DISTRO="bullseye" # should match build-wine Dockerfile base -DEBIAN_ANDROID_DISTRO="bullseye" # should match android Dockerfile base +DEBIAN_ANDROID_DISTRO="bookworm" # should match android Dockerfile base contrib=$(dirname "$0") diff --git a/electrum/gui/common_qt/plugins.py b/electrum/gui/common_qt/plugins.py index ba2189dd25c1..0934477b483a 100644 --- a/electrum/gui/common_qt/plugins.py +++ b/electrum/gui/common_qt/plugins.py @@ -1,4 +1,9 @@ -from PyQt5.QtCore import pyqtSignal, pyqtProperty, QObject +import sys + +if getattr(sys, '_GUI_QT_VERSION') == 5: # FIXME: remove when both desktop and mobile are Qt6 + from PyQt5.QtCore import pyqtSignal, pyqtProperty, QObject +else: + from PyQt6.QtCore import pyqtSignal, pyqtProperty, QObject from electrum.logging import get_logger diff --git a/electrum/gui/default_lang.py b/electrum/gui/default_lang.py index e8a3e9b8eda0..aacf8112f05e 100644 --- a/electrum/gui/default_lang.py +++ b/electrum/gui/default_lang.py @@ -24,7 +24,7 @@ def get_default_language(*, gui_name: Optional[str] = None) -> str: name = QLocale.system().name() return name if name in languages else "en_UK" elif gui_name == "qml": - from PyQt5.QtCore import QLocale + from PyQt6.QtCore import QLocale # On Android QLocale does not return the system locale try: name = str(jLocale.getDefault().toString()) diff --git a/electrum/gui/qml/__init__.py b/electrum/gui/qml/__init__.py index 68c2ca40ca6d..35926cb707b5 100644 --- a/electrum/gui/qml/__init__.py +++ b/electrum/gui/qml/__init__.py @@ -5,17 +5,18 @@ from typing import TYPE_CHECKING try: - import PyQt5 + import PyQt6 except Exception: - sys.exit("Error: Could not import PyQt5 on Linux systems, you may try 'sudo apt-get install python3-pyqt5'") + sys.exit("Error: Could not import PyQt6. On Linux systems, you may try 'sudo apt-get install python3-pyqt6'") try: - import PyQt5.QtQml + import PyQt6.QtQml except Exception: - sys.exit("Error: Could not import PyQt5.QtQml on Linux systems, you may try 'sudo apt-get install python3-pyqt5.qtquick'") + sys.exit("Error: Could not import PyQt6.QtQml. On Linux systems, you may try 'sudo apt-get install python3-pyqt6.qtquick'") -from PyQt5.QtCore import (Qt, QCoreApplication, QLocale, QTranslator, QTimer, QT_VERSION_STR, PYQT_VERSION_STR) -from PyQt5.QtGui import QGuiApplication +from PyQt6.QtCore import (Qt, QCoreApplication, QLocale, QTranslator, QTimer, QT_VERSION_STR, PYQT_VERSION_STR) +from PyQt6.QtGui import QGuiApplication +sys._GUI_QT_VERSION = 6 # used by gui/common_qt from electrum.i18n import _ from electrum.plugin import run_hook @@ -40,7 +41,6 @@ def translate(self, context, source_text, disambiguation, n): class ElectrumGui(BaseElectrumGui, Logger): - @profiler def __init__(self, config: 'SimpleConfig', daemon: 'Daemon', plugins: 'Plugins'): BaseElectrumGui.__init__(self, config=config, daemon=daemon, plugins=plugins) @@ -63,13 +63,11 @@ def __init__(self, config: 'SimpleConfig', daemon: 'Daemon', plugins: 'Plugins') # GC-ed when windows are closed #network.add_jobs([DebugMem([Abstract_Wallet, SPV, Synchronizer, # ElectrumWindow], interval=5)]) - QCoreApplication.setAttribute(Qt.AA_X11InitThreads) + if hasattr(Qt, "AA_ShareOpenGLContexts"): QCoreApplication.setAttribute(Qt.AA_ShareOpenGLContexts) if hasattr(QGuiApplication, 'setDesktopFileName'): QGuiApplication.setDesktopFileName('electrum.desktop') - if hasattr(Qt, "AA_EnableHighDpiScaling"): - QCoreApplication.setAttribute(Qt.AA_EnableHighDpiScaling) if "QT_QUICK_CONTROLS_STYLE" not in os.environ: os.environ["QT_QUICK_CONTROLS_STYLE"] = "Material" @@ -100,10 +98,14 @@ def main(self): return self.timer.start() - signal.signal(signal.SIGINT, lambda *args: self.stop()) + signal.signal(signal.SIGINT, lambda *args: self._handle_sigint()) self.logger.info('Entering main loop') - self.app.exec_() + self.app.exec() + + def _handle_sigint(self): + self.app.appController.wantClose = True + self.stop() def stop(self): self.logger.info('closing GUI') diff --git a/electrum/gui/qml/android_res/layout/scanner_layout.xml b/electrum/gui/qml/android_res/layout/scanner_layout.xml new file mode 100644 index 000000000000..948e9e9cb663 --- /dev/null +++ b/electrum/gui/qml/android_res/layout/scanner_layout.xml @@ -0,0 +1,36 @@ + + + + + + + + +