Qt6 Build Test
Some more compatibility for Qt5&6, and first try at build scripts.
This commit is contained in:
parent
d912b67f7c
commit
b1ab9931b5
|
@ -5,7 +5,7 @@ on:
|
|||
- 'v*'
|
||||
|
||||
jobs:
|
||||
build-macos:
|
||||
build-macos-Qt5:
|
||||
runs-on: macos-11
|
||||
steps:
|
||||
-
|
||||
|
@ -32,7 +32,7 @@ jobs:
|
|||
cd $GITHUB_WORKSPACE
|
||||
cp ${{ steps.setup_ffmpeg.outputs.ffmpeg-path }} bin/
|
||||
cp static/build_files/macos/pyoxidizer.bzl pyoxidizer.bzl
|
||||
cp static/build_files/macos/requirements.txt requirements.txt
|
||||
cp static/build_files/macos/requirementsQt5.txt requirements.txt
|
||||
basename $(rustc --print sysroot) | sed -e "s/^stable-//" > triple.txt
|
||||
pyoxidizer build --release
|
||||
cd build/$(head -n 1 triple.txt)/release
|
||||
|
@ -49,17 +49,71 @@ jobs:
|
|||
cd $GITHUB_WORKSPACE
|
||||
temp_dmg="$(mktemp).dmg"
|
||||
hdiutil create "$temp_dmg" -ov -volname "HydrusNetwork" -fs HFS+ -srcfolder "$GITHUB_WORKSPACE/build/$(head -n 1 triple.txt)/release"
|
||||
hdiutil convert "$temp_dmg" -format UDZO -o HydrusNetwork.dmg
|
||||
hdiutil convert "$temp_dmg" -format UDZO -o HydrusNetwork5.dmg
|
||||
-
|
||||
name: Upload a Build Artifact
|
||||
uses: actions/upload-artifact@v2.2.1
|
||||
with:
|
||||
name: MacOS-DMG
|
||||
path: HydrusNetwork.dmg
|
||||
path: HydrusNetwork5.dmg
|
||||
if-no-files-found: error
|
||||
retention-days: 2
|
||||
|
||||
build-ubuntu:
|
||||
build-macos-Qt6:
|
||||
runs-on: macos-11
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
-
|
||||
name: Setup FFMPEG
|
||||
uses: FedericoCarboni/setup-ffmpeg@v1
|
||||
id: setup_ffmpeg
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
-
|
||||
name: Install mkdocs-material
|
||||
run: python3 -m pip install mkdocs-material
|
||||
-
|
||||
name: Build docs to /help
|
||||
run: mkdocs build -d help
|
||||
-
|
||||
name: Install PyOxidizer
|
||||
run: python3 -m pip install pyoxidizer
|
||||
-
|
||||
name: Build Hydrus
|
||||
run: |
|
||||
cd $GITHUB_WORKSPACE
|
||||
cp ${{ steps.setup_ffmpeg.outputs.ffmpeg-path }} bin/
|
||||
cp static/build_files/macos/pyoxidizer.bzl pyoxidizer.bzl
|
||||
cp static/build_files/macos/requirementsQt6.txt requirements.txt
|
||||
basename $(rustc --print sysroot) | sed -e "s/^stable-//" > triple.txt
|
||||
pyoxidizer build --release
|
||||
cd build/$(head -n 1 triple.txt)/release
|
||||
mkdir -p "Hydrus Network.app/Contents/MacOS"
|
||||
mkdir -p "Hydrus Network.app/Contents/Resources"
|
||||
mkdir -p "Hydrus Network.app/Contents/Frameworks"
|
||||
mv install/static/icon.icns "Hydrus Network.app/Contents/Resources/icon.icns"
|
||||
cp install/static/build_files/macos/Info.plist "Hydrus Network.app/Contents/Info.plist"
|
||||
cp install/static/build_files/macos/ReadMeFirst.rtf ./ReadMeFirst.rtf
|
||||
cp install/static/build_files/macos/running_from_app "install/running_from_app"
|
||||
ln -s /Applications ./Applications
|
||||
mv install/* "Hydrus Network.app/Contents/MacOS/"
|
||||
rm -rf install
|
||||
cd $GITHUB_WORKSPACE
|
||||
temp_dmg="$(mktemp).dmg"
|
||||
hdiutil create "$temp_dmg" -ov -volname "HydrusNetwork" -fs HFS+ -srcfolder "$GITHUB_WORKSPACE/build/$(head -n 1 triple.txt)/release"
|
||||
hdiutil convert "$temp_dmg" -format UDZO -o HydrusNetwork6.dmg
|
||||
-
|
||||
name: Upload a Build Artifact
|
||||
uses: actions/upload-artifact@v2.2.1
|
||||
with:
|
||||
name: MacOS-DMG
|
||||
path: HydrusNetwork6.dmg
|
||||
if-no-files-found: error
|
||||
retention-days: 2
|
||||
|
||||
build-ubuntu-Qt5:
|
||||
runs-on: ubuntu-18.04
|
||||
steps:
|
||||
-
|
||||
|
@ -104,7 +158,7 @@ jobs:
|
|||
uses: BSFishy/pip-action@v1
|
||||
with:
|
||||
packages: pyinstaller
|
||||
requirements: hydrus/static/build_files/linux/requirements.txt
|
||||
requirements: hydrus/static/build_files/linux/requirementsQt5.txt
|
||||
-
|
||||
name: Build Hydrus
|
||||
run: |
|
||||
|
@ -127,17 +181,95 @@ jobs:
|
|||
name: Compress Client
|
||||
run: |
|
||||
mv dist/client "dist/Hydrus Network"
|
||||
tar -czvf Ubuntu-Extract.tar.gz -C dist "Hydrus Network"
|
||||
tar -czvf Ubuntu-Extract5.tar.gz -C dist "Hydrus Network"
|
||||
-
|
||||
name: Upload a Build Artifact
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: Ubuntu-Extract
|
||||
path: Ubuntu-Extract.tar.gz
|
||||
path: Ubuntu-Extract5.tar.gz
|
||||
if-no-files-found: error
|
||||
retention-days: 2
|
||||
|
||||
build-windows:
|
||||
build-ubuntu-Qt6:
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
path: hydrus
|
||||
-
|
||||
name: Setup Python
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: 3.8
|
||||
architecture: x64
|
||||
-
|
||||
name: Install mkdocs-material
|
||||
run: pip install mkdocs-material
|
||||
-
|
||||
name: Build docs to /help
|
||||
run: mkdocs build -d help
|
||||
working-directory: hydrus
|
||||
#- name: Cache Qt
|
||||
# id: cache-qt
|
||||
# uses: actions/cache@v1
|
||||
# with:
|
||||
# path: Qt
|
||||
# key: ${{ runner.os }}-QtCache
|
||||
#-
|
||||
# name: Install Qt
|
||||
# uses: jurplel/install-qt-action@v2
|
||||
# with:
|
||||
# install-deps: true
|
||||
# setup-python: 'false'
|
||||
# modules: qtcharts qtwidgets qtgui qtcore
|
||||
# cached: ${{ steps.cache-qt.outputs.cache-hit }}
|
||||
-
|
||||
name: APT Install
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y libmpv1
|
||||
-
|
||||
name: Pip Installer
|
||||
uses: BSFishy/pip-action@v1
|
||||
with:
|
||||
packages: pyinstaller
|
||||
requirements: hydrus/static/build_files/linux/requirementsQt6.txt
|
||||
-
|
||||
name: Build Hydrus
|
||||
run: |
|
||||
cp hydrus/static/build_files/linux/client.spec client.spec
|
||||
cp hydrus/static/build_files/linux/server.spec server.spec
|
||||
pyinstaller server.spec
|
||||
pyinstaller client.spec
|
||||
-
|
||||
name: Remove Chonk
|
||||
run: |
|
||||
find dist/client/ -type f -name "*.pyc" -delete
|
||||
while read line; do find dist/client/ -type f -name "${line}" -delete ; done < hydrus/static/build_files/linux/files_to_delete.txt
|
||||
-
|
||||
name: Set Permissions
|
||||
run: |
|
||||
sudo chown --recursive 1000:1000 dist/client
|
||||
sudo find dist/client -type d -exec chmod 0755 {} \;
|
||||
sudo chmod +x dist/client/client dist/client/server dist/client/bin/swfrender_linux
|
||||
-
|
||||
name: Compress Client
|
||||
run: |
|
||||
mv dist/client "dist/Hydrus Network"
|
||||
tar -czvf Ubuntu-Extract6.tar.gz -C dist "Hydrus Network"
|
||||
-
|
||||
name: Upload a Build Artifact
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: Ubuntu-Extract
|
||||
path: Ubuntu-Extract6.tar.gz
|
||||
if-no-files-found: error
|
||||
retention-days: 2
|
||||
|
||||
build-windows-Qt5:
|
||||
runs-on: windows-2019
|
||||
steps:
|
||||
-
|
||||
|
@ -184,7 +316,7 @@ jobs:
|
|||
uses: BSFishy/pip-action@v1
|
||||
with:
|
||||
packages: pyinstaller
|
||||
requirements: hydrus\static\build_files\windows\requirements.txt
|
||||
requirements: hydrus\static\build_files\windows\requirementsQt5.txt
|
||||
-
|
||||
name: Download mpv-dev
|
||||
uses: carlosperate/download-file-action@v1.0.3
|
||||
|
@ -220,7 +352,7 @@ jobs:
|
|||
name: Compress Client
|
||||
run: |
|
||||
cd .\dist
|
||||
7z.exe a -tzip -mm=Deflate -mx=5 ..\Windows-Extract.zip 'Hydrus Network'
|
||||
7z.exe a -tzip -mm=Deflate -mx=5 ..\Windows-Extract5.zip 'Hydrus Network'
|
||||
cd ..
|
||||
-
|
||||
name: Upload a Build Artifact
|
||||
|
@ -235,14 +367,101 @@ jobs:
|
|||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: Windows-Extract
|
||||
path: Windows-Extract.zip
|
||||
path: Windows-Extract5.zip
|
||||
if-no-files-found: error
|
||||
retention-days: 2
|
||||
|
||||
build-windows-Qt6:
|
||||
runs-on: windows-2019
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
path: hydrus
|
||||
-
|
||||
name: Setup FFMPEG
|
||||
uses: FedericoCarboni/setup-ffmpeg@v1
|
||||
id: setup_ffmpeg
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
-
|
||||
name: Setup Python
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: 3.8
|
||||
architecture: x64
|
||||
-
|
||||
name: Install mkdocs-material
|
||||
run: pip install mkdocs-material
|
||||
-
|
||||
name: Build docs to /help
|
||||
run: mkdocs build -d help
|
||||
working-directory: hydrus
|
||||
-
|
||||
name: Cache Qt
|
||||
id: cache_qt
|
||||
uses: actions/cache@v1
|
||||
with:
|
||||
path: ../Qt
|
||||
key: ${{ runner.os }}-QtCache
|
||||
-
|
||||
name: Install Qt
|
||||
uses: jurplel/install-qt-action@v2
|
||||
with:
|
||||
install-deps: true
|
||||
setup-python: 'false'
|
||||
modules: qtcharts qtwidgets qtgui qtcore
|
||||
cached: ${{ steps.cache_qt.outputs.cache-hit }}
|
||||
-
|
||||
name: PIP Install Packages
|
||||
uses: BSFishy/pip-action@v1
|
||||
with:
|
||||
packages: pyinstaller
|
||||
requirements: hydrus\static\build_files\windows\requirementsQt6.txt
|
||||
-
|
||||
name: Download mpv-dev
|
||||
uses: carlosperate/download-file-action@v1.0.3
|
||||
id: download_mpv
|
||||
with:
|
||||
file-url: 'https://sourceforge.net/projects/mpv-player-windows/files/libmpv/mpv-dev-x86_64-20210228-git-d1be8bb.7z'
|
||||
file-name: 'mpv-dev-x86_64.7z'
|
||||
location: '.'
|
||||
-
|
||||
name: Process mpv-dev
|
||||
run: |
|
||||
7z x ${{ steps.download_mpv.outputs.file-path }}
|
||||
move mpv-1.dll hydrus\
|
||||
-
|
||||
name: Build Hydrus
|
||||
run: |
|
||||
move ${{ steps.setup_ffmpeg.outputs.ffmpeg-path }} hydrus\bin\
|
||||
move hydrus\static\build_files\windows\sqlite3.dll hydrus\
|
||||
move hydrus\static\build_files\windows\sqlite3.exe hydrus\db
|
||||
move hydrus\static\build_files\windows\client-win.spec client-win.spec
|
||||
move hydrus\static\build_files\windows\server-win.spec server-win.spec
|
||||
pyinstaller server-win.spec
|
||||
pyinstaller client-win.spec
|
||||
dir -r
|
||||
-
|
||||
name: Compress Client
|
||||
run: |
|
||||
cd .\dist
|
||||
7z.exe a -tzip -mm=Deflate -mx=5 ..\Windows-Extract6.zip 'Hydrus Network'
|
||||
cd ..
|
||||
-
|
||||
name: Upload a Build Artifact
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: Windows-Extract
|
||||
path: Windows-Extract6.zip
|
||||
if-no-files-found: error
|
||||
retention-days: 2
|
||||
|
||||
create-release:
|
||||
name: Create Release Entry
|
||||
runs-on: ubuntu-20.04
|
||||
needs: [build-windows, build-ubuntu, build-macos]
|
||||
needs: [build-windows-Qt5, build-windows-Qt6, build-ubuntu-Qt5, build-ubuntu-Qt6, build-macos-Qt5, build-macos-Qt6]
|
||||
steps:
|
||||
-
|
||||
name: Checkout code
|
||||
|
@ -260,19 +479,25 @@ jobs:
|
|||
name: Rename Files
|
||||
run: |
|
||||
mkdir ubuntu windows
|
||||
mv MacOS-DMG/HydrusNetwork.dmg Hydrus.Network.${{ steps.meta.outputs.version_short }}.-.macOS.-.App.dmg
|
||||
mv Windows-Install/HydrusInstaller.exe Hydrus.Network.${{ steps.meta.outputs.version_short }}.-.Windows.-.Installer.exe
|
||||
mv Windows-Extract/Windows-Extract.zip Hydrus.Network.${{ steps.meta.outputs.version_short }}.-.Windows.-.Extract.only.zip
|
||||
mv Ubuntu-Extract/Ubuntu-Extract.tar.gz Hydrus.Network.${{ steps.meta.outputs.version_short }}.-.Linux.-.Executable.tar.gz
|
||||
mv MacOS-DMG/HydrusNetwork5.dmg Hydrus.Network.${{ steps.meta.outputs.version_short }}.-.macOS.Qt5.-.App.dmg
|
||||
mv MacOS-DMG/HydrusNetwork6.dmg Hydrus.Network.${{ steps.meta.outputs.version_short }}.-.macOS.Qt6.-.App.dmg
|
||||
mv Windows-Install/HydrusInstaller.exe Hydrus.Network.${{ steps.meta.outputs.version_short }}.-.Windows.Qt5.-.Installer.exe
|
||||
mv Windows-Extract/Windows-Extract5.zip Hydrus.Network.${{ steps.meta.outputs.version_short }}.-.Windows.Qt5.-.Extract.only.zip
|
||||
mv Windows-Extract/Windows-Extract6.zip Hydrus.Network.${{ steps.meta.outputs.version_short }}.-.Windows.Qt6.-.Extract.only.zip
|
||||
mv Ubuntu-Extract/Ubuntu-Extract5.tar.gz Hydrus.Network.${{ steps.meta.outputs.version_short }}.-.Linux.Qt5.-.Executable.tar.gz
|
||||
mv Ubuntu-Extract/Ubuntu-Extract6.tar.gz Hydrus.Network.${{ steps.meta.outputs.version_short }}.-.Linux.Qt6.-.Executable.tar.gz
|
||||
-
|
||||
name: Release new
|
||||
uses: softprops/action-gh-release@v1
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
with:
|
||||
files: |
|
||||
Hydrus.Network.${{ steps.meta.outputs.version_short }}.-.Windows.-.Installer.exe
|
||||
Hydrus.Network.${{ steps.meta.outputs.version_short }}.-.Windows.-.Extract.only.zip
|
||||
Hydrus.Network.${{ steps.meta.outputs.version_short }}.-.Linux.-.Executable.tar.gz
|
||||
Hydrus.Network.${{ steps.meta.outputs.version_short }}.-.macOS.-.App.dmg
|
||||
Hydrus.Network.${{ steps.meta.outputs.version_short }}.-.Windows.Qt5.-.Installer.exe
|
||||
Hydrus.Network.${{ steps.meta.outputs.version_short }}.-.Windows.Qt5.-.Extract.only.zip
|
||||
Hydrus.Network.${{ steps.meta.outputs.version_short }}.-.Windows.Qt6.-.Extract.only.zip
|
||||
Hydrus.Network.${{ steps.meta.outputs.version_short }}.-.Linux.Qt5.-.Executable.tar.gz
|
||||
Hydrus.Network.${{ steps.meta.outputs.version_short }}.-.Linux.Qt6.-.Executable.tar.gz
|
||||
Hydrus.Network.${{ steps.meta.outputs.version_short }}.-.macOS.Qt5.-.App.dmg
|
||||
Hydrus.Network.${{ steps.meta.outputs.version_short }}.-.macOS.Qt6.-.App.dmg
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
|
|
@ -64,14 +64,20 @@ pip3 install -r requirements_windows.txt
|
|||
|
||||
If you prefer to do things manually, inspect the document and install the modules yourself.
|
||||
|
||||
## PyQt5 support { id="pyqt5" }
|
||||
## Qt { id="qt" }
|
||||
|
||||
For Qt, either PySide2 (default) or PyQt5 are supported, through qtpy. For PyQt5, go:
|
||||
Qt is the UI library. You can run PySide2, PySide6, PyQt5, or PyQt6. A wrapper library called `qtpy` allows this. The default for now is PySide2, but it will soon be PySide6. For PyQt5 or PyQt6, go:
|
||||
|
||||
```
|
||||
pip3 install qtpy PyQtChart PyQt5
|
||||
-or-
|
||||
pip3 install qtpy PyQt6-Charts PyQt6
|
||||
```
|
||||
|
||||
If you have multiple Qts installed, then select which one you want to use by setting the `QT_API` environment variable to 'pyside2', 'pyside6', 'pyqt5', or 'pyqt6'. Check _help->about_ to make sure it loaded the right one.
|
||||
|
||||
If you run Windows 7, you cannot run Qt6. Please try PySide2 or PyQt5.
|
||||
|
||||
## FFMPEG { id="ffmpeg" }
|
||||
|
||||
If you don't have FFMPEG in your PATH and you want to import anything more fun than jpegs, you will need to put a static [FFMPEG](https://ffmpeg.org/) executable in your PATH or the `install_dir/bin` directory. If you can't find a static exe on Windows, you can copy the exe from one of my extractable releases.
|
||||
|
|
|
@ -42,6 +42,7 @@ from hydrus.client.gui import ClientGUIScrolledPanelsManagement
|
|||
from hydrus.client.gui import ClientGUISplash
|
||||
from hydrus.client.gui import ClientGUIStyle
|
||||
from hydrus.client.gui import ClientGUITopLevelWindowsPanels
|
||||
from hydrus.client.gui import QtInit
|
||||
from hydrus.client.gui import QtPorting as QP
|
||||
from hydrus.client.gui.lists import ClientGUIListManager
|
||||
from hydrus.client.importing import ClientImportSubscriptions
|
||||
|
@ -1588,7 +1589,7 @@ class Controller( HydrusController.HydrusController ):
|
|||
|
||||
def Run( self ):
|
||||
|
||||
QP.MonkeyPatchMissingMethods()
|
||||
QtInit.MonkeyPatchMissingMethods()
|
||||
|
||||
from hydrus.client.gui import ClientGUICore
|
||||
|
||||
|
|
|
@ -76,6 +76,7 @@ from hydrus.client.gui import ClientGUITopLevelWindows
|
|||
from hydrus.client.gui import ClientGUITopLevelWindowsPanels
|
||||
from hydrus.client.gui import QLocator
|
||||
from hydrus.client.gui import ClientGUILocatorSearchProviders
|
||||
from hydrus.client.gui import QtInit
|
||||
from hydrus.client.gui import QtPorting as QP
|
||||
from hydrus.client.gui.canvas import ClientGUIMPV
|
||||
from hydrus.client.gui.networking import ClientGUIHydrusNetwork
|
||||
|
@ -696,38 +697,45 @@ class FrameGUI( ClientGUITopLevelWindows.MainFrameThatResizes, CAC.ApplicationCo
|
|||
|
||||
library_versions.append( ( 'Qt', QC.__version__ ) )
|
||||
|
||||
if qtpy.PYSIDE2:
|
||||
if QtInit.WE_ARE_QT5:
|
||||
|
||||
import PySide2
|
||||
import shiboken2
|
||||
if QtInit.WE_ARE_PYSIDE:
|
||||
|
||||
import PySide2
|
||||
import shiboken2
|
||||
|
||||
library_versions.append( ( 'PySide2', PySide2.__version__ ) )
|
||||
library_versions.append( ( 'shiboken2', shiboken2.__version__ ) )
|
||||
|
||||
elif QtInit.WE_ARE_PYQT:
|
||||
|
||||
from PyQt5.Qt import PYQT_VERSION_STR # pylint: disable=E0401,E0611
|
||||
from PyQt5.sip import SIP_VERSION_STR # pylint: disable=E0401
|
||||
|
||||
library_versions.append( ( 'PyQt5', PYQT_VERSION_STR ) )
|
||||
library_versions.append( ( 'sip', SIP_VERSION_STR ) )
|
||||
|
||||
|
||||
library_versions.append( ( 'PySide2', PySide2.__version__ ) )
|
||||
library_versions.append( ( 'shiboken2', shiboken2.__version__ ) )
|
||||
elif QtInit.WE_ARE_QT6:
|
||||
|
||||
elif qtpy.PYQT5:
|
||||
|
||||
from PyQt5.Qt import PYQT_VERSION_STR # pylint: disable=E0401,E0611
|
||||
from PyQt5.sip import SIP_VERSION_STR # pylint: disable=E0401
|
||||
|
||||
library_versions.append( ( 'PyQt5', PYQT_VERSION_STR ) )
|
||||
library_versions.append( ( 'sip', SIP_VERSION_STR ) )
|
||||
if QtInit.WE_ARE_PYSIDE:
|
||||
|
||||
import PySide6
|
||||
import shiboken6
|
||||
|
||||
library_versions.append( ( 'PySide6', PySide6.__version__ ) )
|
||||
library_versions.append( ( 'shiboken6', shiboken6.__version__ ) )
|
||||
|
||||
elif QtInit.WE_ARE_PYQT:
|
||||
|
||||
from PyQt6.QtCore import PYQT_VERSION_STR # pylint: disable=E0401
|
||||
from PyQt6.sip import SIP_VERSION_STR # pylint: disable=E0401
|
||||
|
||||
library_versions.append( ( 'PyQt6', PYQT_VERSION_STR ) )
|
||||
library_versions.append( ( 'sip', SIP_VERSION_STR ) )
|
||||
|
||||
|
||||
elif QP.WE_ARE_PYSIDE and QP.WE_ARE_QT6:
|
||||
|
||||
import PySide6
|
||||
import shiboken6
|
||||
|
||||
library_versions.append( ( 'PySide6', PySide6.__version__ ) )
|
||||
library_versions.append( ( 'shiboken6', shiboken6.__version__ ) )
|
||||
|
||||
elif QP.WE_ARE_PYQT and QP.WE_ARE_QT6:
|
||||
|
||||
from PyQt6.QtCore import PYQT_VERSION_STR # pylint: disable=E0401
|
||||
from PyQt6.sip import SIP_VERSION_STR # pylint: disable=E0401
|
||||
|
||||
library_versions.append( ( 'PyQt6', PYQT_VERSION_STR ) )
|
||||
library_versions.append( ( 'sip', SIP_VERSION_STR ) )
|
||||
|
||||
|
||||
CBOR_AVAILABLE = False
|
||||
|
||||
try:
|
||||
|
|
|
@ -9,6 +9,7 @@ from hydrus.core import HydrusConstants as HC
|
|||
from hydrus.core import HydrusGlobals as HG
|
||||
from hydrus.core import HydrusText
|
||||
|
||||
from hydrus.client.gui import QtInit
|
||||
from hydrus.client.gui import QtPorting as QP
|
||||
|
||||
def ClientToScreen( win: QW.QWidget, pos: QC.QPoint ) -> QC.QPoint:
|
||||
|
@ -84,11 +85,11 @@ def ConvertQtImageToNumPy( qt_image: QG.QImage ):
|
|||
|
||||
data_bytearray = qt_image.bits()
|
||||
|
||||
if QP.WE_ARE_PYSIDE:
|
||||
if QtInit.WE_ARE_PYSIDE:
|
||||
|
||||
data_bytes = bytes( data_bytearray )
|
||||
|
||||
elif QP.WE_ARE_PYQT:
|
||||
elif QtInit.WE_ARE_PYQT:
|
||||
|
||||
data_bytes = data_bytearray.asstring( height * width * depth )
|
||||
|
||||
|
|
|
@ -348,9 +348,9 @@ class RatingNumerical( QW.QWidget ):
|
|||
|
||||
def _GetRatingStateAndRatingFromClickEvent( self, event ):
|
||||
|
||||
click_pos = event.pos()
|
||||
click_pos = event.position().toPoint()
|
||||
|
||||
x = event.pos().x()
|
||||
x = click_pos.x()
|
||||
|
||||
BORDER = 1
|
||||
|
||||
|
|
|
@ -1273,7 +1273,7 @@ class ShortcutsHandler( QC.QObject ):
|
|||
|
||||
if event.type() == QC.QEvent.MouseButtonPress:
|
||||
|
||||
self._last_click_down_position = event.globalPos()
|
||||
self._last_click_down_position = event.globalPosition().toPoint()
|
||||
|
||||
CUMULATIVE_MOUSEWARP_MANHATTAN_LENGTH = 0
|
||||
|
||||
|
@ -1290,7 +1290,7 @@ class ShortcutsHandler( QC.QObject ):
|
|||
|
||||
if event.type() == QC.QEvent.MouseButtonRelease:
|
||||
|
||||
release_press_pos = event.globalPos()
|
||||
release_press_pos = event.globalPosition().toPoint()
|
||||
|
||||
delta = release_press_pos - self._last_click_down_position
|
||||
|
||||
|
|
|
@ -0,0 +1,135 @@
|
|||
import os
|
||||
|
||||
# If not explicitly set, prefer PySide instead of PyQt5, which is the qtpy default
|
||||
# It is critical that this runs on startup *before* anything is imported from qtpy.
|
||||
|
||||
if 'QT_API' not in os.environ:
|
||||
|
||||
try:
|
||||
|
||||
import PySide2 # Qt5
|
||||
|
||||
os.environ[ 'QT_API' ] = 'pyside2'
|
||||
|
||||
except ImportError as e:
|
||||
|
||||
try:
|
||||
|
||||
import PySide6 # Qt6
|
||||
|
||||
os.environ[ 'QT_API' ] = 'pyside6'
|
||||
|
||||
except ImportError as e:
|
||||
|
||||
pass
|
||||
|
||||
|
||||
|
||||
|
||||
#
|
||||
|
||||
import qtpy
|
||||
|
||||
from qtpy import QtCore as QC
|
||||
from qtpy import QtWidgets as QW
|
||||
from qtpy import QtGui as QG
|
||||
|
||||
# 2022-07
|
||||
# an older version of qtpy, 1.9 or so, didn't actually have attribute qtpy.PYQT6, so we'll test and assign carefully
|
||||
|
||||
WE_ARE_QT5 = False
|
||||
WE_ARE_QT6 = False
|
||||
|
||||
WE_ARE_PYQT = False
|
||||
WE_ARE_PYSIDE = False
|
||||
|
||||
if qtpy.PYQT5:
|
||||
|
||||
WE_ARE_QT5 = True
|
||||
WE_ARE_PYQT = True
|
||||
|
||||
from PyQt5 import sip # pylint: disable=E0401
|
||||
|
||||
def isValid( obj ):
|
||||
|
||||
if isinstance( obj, sip.simplewrapper ):
|
||||
|
||||
return not sip.isdeleted( obj )
|
||||
|
||||
|
||||
return True
|
||||
|
||||
|
||||
elif hasattr( qtpy, 'PYQT6' ) and qtpy.PYQT6:
|
||||
|
||||
WE_ARE_QT6 = True
|
||||
WE_ARE_PYQT = True
|
||||
|
||||
from PyQt6 import sip # pylint: disable=E0401
|
||||
|
||||
def isValid( obj ):
|
||||
|
||||
if isinstance( obj, sip.simplewrapper ):
|
||||
|
||||
return not sip.isdeleted( obj )
|
||||
|
||||
|
||||
return True
|
||||
|
||||
elif qtpy.PYSIDE2:
|
||||
|
||||
WE_ARE_QT5 = True
|
||||
WE_ARE_PYSIDE = True
|
||||
|
||||
import shiboken2
|
||||
|
||||
isValid = shiboken2.isValid
|
||||
|
||||
elif qtpy.PYSIDE6:
|
||||
|
||||
WE_ARE_QT6 = True
|
||||
WE_ARE_PYSIDE = True
|
||||
|
||||
import shiboken6
|
||||
|
||||
isValid = shiboken6.isValid
|
||||
|
||||
else:
|
||||
|
||||
raise RuntimeError( 'You need one of PySide2, PySide6, PyQt5, or PyQt6' )
|
||||
|
||||
|
||||
def MonkeyPatchMissingMethods():
|
||||
|
||||
if WE_ARE_QT5:
|
||||
|
||||
QG.QMouseEvent.globalPosition = lambda self, *args, **kwargs: QC.QPointF( self.globalPos( *args, **kwargs ) )
|
||||
|
||||
QG.QMouseEvent.position = lambda self, *args, **kwargs: QC.QPointF( self.pos( *args, **kwargs ) )
|
||||
|
||||
QG.QDropEvent.position = lambda self, *args, **kwargs: QC.QPointF( self.pos( *args, **kwargs ) )
|
||||
|
||||
QG.QDropEvent.modifiers = lambda self, *args, **kwargs: self.keyboardModifiers( *args, **kwargs )
|
||||
|
||||
|
||||
if WE_ARE_PYQT:
|
||||
|
||||
def MonkeyPatchGetSaveFileName( original_function ):
|
||||
|
||||
def new_function( *args, **kwargs ):
|
||||
|
||||
if 'selectedFilter' in kwargs:
|
||||
|
||||
kwargs[ 'initialFilter' ] = kwargs[ 'selectedFilter' ]
|
||||
del kwargs[ 'selectedFilter' ]
|
||||
|
||||
return original_function( *args, **kwargs )
|
||||
|
||||
|
||||
|
||||
return new_function
|
||||
|
||||
|
||||
QW.QFileDialog.getSaveFileName = MonkeyPatchGetSaveFileName( QW.QFileDialog.getSaveFileName )
|
||||
|
||||
|
|
@ -2,32 +2,6 @@
|
|||
|
||||
import os
|
||||
|
||||
# If not explicitly set, prefer PySide2/PySide6 instead of the qtpy default which is PyQt5
|
||||
# It is important that this runs on startup *before* anything is imported from qtpy.
|
||||
# Since test.py, client.py and client.pyw all import this module first before any other Qt related ones, this requirement is satisfied.
|
||||
|
||||
if not 'QT_API' in os.environ:
|
||||
|
||||
try:
|
||||
|
||||
import PySide2 # Qt5
|
||||
|
||||
os.environ[ 'QT_API' ] = 'pyside2'
|
||||
|
||||
except ImportError as e:
|
||||
|
||||
try:
|
||||
|
||||
import PySide6 # Qt6
|
||||
|
||||
os.environ[ 'QT_API' ] = 'pyside6'
|
||||
|
||||
except ImportError as e:
|
||||
|
||||
pass
|
||||
|
||||
|
||||
#
|
||||
import qtpy
|
||||
from qtpy import QtCore as QC
|
||||
from qtpy import QtWidgets as QW
|
||||
|
@ -37,113 +11,26 @@ import math
|
|||
|
||||
from collections import defaultdict
|
||||
|
||||
# we can't test qtpy.PYQT6 unless it has it lmao, so we'll test and assign more carefully
|
||||
|
||||
WE_ARE_QT5 = False
|
||||
WE_ARE_QT6 = False
|
||||
|
||||
WE_ARE_PYQT = False
|
||||
WE_ARE_PYSIDE = False
|
||||
|
||||
if qtpy.PYQT5:
|
||||
|
||||
from PyQt5 import sip # pylint: disable=E0401
|
||||
|
||||
WE_ARE_QT5 = True
|
||||
WE_ARE_PYQT = True
|
||||
|
||||
def isValid( obj ):
|
||||
|
||||
if isinstance( obj, sip.simplewrapper ):
|
||||
|
||||
return not sip.isdeleted( obj )
|
||||
|
||||
|
||||
return True
|
||||
|
||||
|
||||
elif hasattr( qtpy, 'PYQT6' ) and qtpy.PYQT6:
|
||||
|
||||
from PyQt6 import sip # pylint: disable=E0401
|
||||
|
||||
WE_ARE_QT6 = True
|
||||
WE_ARE_PYQT = True
|
||||
|
||||
def isValid( obj ):
|
||||
|
||||
if isinstance( obj, sip.simplewrapper ):
|
||||
|
||||
return not sip.isdeleted( obj )
|
||||
|
||||
|
||||
return True
|
||||
|
||||
elif qtpy.PYSIDE2:
|
||||
|
||||
import shiboken2
|
||||
|
||||
WE_ARE_QT5 = True
|
||||
WE_ARE_PYSIDE = True
|
||||
|
||||
isValid = shiboken2.isValid
|
||||
|
||||
elif qtpy.PYSIDE6:
|
||||
|
||||
import shiboken6
|
||||
|
||||
WE_ARE_QT6 = True
|
||||
WE_ARE_PYSIDE = True
|
||||
|
||||
isValid = shiboken6.isValid
|
||||
|
||||
else:
|
||||
|
||||
raise RuntimeError( 'You need one of PySide2, PySide6, PyQt5 or PyQt6' )
|
||||
|
||||
|
||||
from hydrus.core import HydrusConstants as HC
|
||||
from hydrus.core import HydrusData
|
||||
from hydrus.core import HydrusGlobals as HG
|
||||
|
||||
from hydrus.client import ClientConstants as CC
|
||||
from hydrus.client.gui import QtInit
|
||||
|
||||
def MonkeyPatchMissingMethods():
|
||||
|
||||
if WE_ARE_QT5:
|
||||
|
||||
QG.QMouseEvent.globalPosition = lambda self, *args, **kwargs: self.globalPos( *args, **kwargs )
|
||||
QG.QDropEvent.position = lambda self, *args, **kwargs: self.posF( *args, **kwargs )
|
||||
|
||||
|
||||
if WE_ARE_PYQT:
|
||||
|
||||
def MonkeyPatchGetSaveFileName( original_function ):
|
||||
|
||||
def new_function( *args, **kwargs ):
|
||||
|
||||
if 'selectedFilter' in kwargs:
|
||||
|
||||
kwargs[ 'initialFilter' ] = kwargs[ 'selectedFilter' ]
|
||||
del kwargs[ 'selectedFilter' ]
|
||||
|
||||
return original_function( *args, **kwargs )
|
||||
|
||||
|
||||
|
||||
return new_function
|
||||
|
||||
|
||||
QW.QFileDialog.getSaveFileName = MonkeyPatchGetSaveFileName( QW.QFileDialog.getSaveFileName )
|
||||
|
||||
isValid = QtInit.isValid
|
||||
|
||||
def registerEventType():
|
||||
|
||||
if qtpy.PYSIDE2 or qtpy.PYSIDE6:
|
||||
if QtInit.WE_ARE_PYSIDE:
|
||||
|
||||
return QC.QEvent.Type( QC.QEvent.registerEventType() )
|
||||
|
||||
return QC.QEvent.registerEventType()
|
||||
|
||||
else:
|
||||
|
||||
return QC.QEvent.registerEventType()
|
||||
|
||||
|
||||
|
||||
class HBoxLayout( QW.QHBoxLayout ):
|
||||
|
||||
|
@ -159,6 +46,7 @@ class HBoxLayout( QW.QHBoxLayout ):
|
|||
|
||||
self.setContentsMargins( val, val, val, val )
|
||||
|
||||
|
||||
|
||||
class VBoxLayout( QW.QVBoxLayout ):
|
||||
|
||||
|
@ -465,13 +353,13 @@ class TabBar( QW.QTabBar ):
|
|||
|
||||
def mousePressEvent( self, event ):
|
||||
|
||||
index = self.tabAt( event.pos() )
|
||||
index = self.tabAt( event.position().toPoint() )
|
||||
|
||||
if event.button() == QC.Qt.LeftButton:
|
||||
|
||||
self._last_clicked_tab_index = index
|
||||
|
||||
self._last_clicked_global_pos = event.globalPosition()
|
||||
self._last_clicked_global_pos = event.globalPosition().toPoint()
|
||||
|
||||
|
||||
QW.QTabBar.mousePressEvent( self, event )
|
||||
|
@ -479,7 +367,7 @@ class TabBar( QW.QTabBar ):
|
|||
|
||||
def mouseReleaseEvent( self, event ):
|
||||
|
||||
index = self.tabAt( event.pos() )
|
||||
index = self.tabAt( event.position().toPoint() )
|
||||
|
||||
if event.button() == QC.Qt.MiddleButton:
|
||||
|
||||
|
@ -496,7 +384,7 @@ class TabBar( QW.QTabBar ):
|
|||
|
||||
def mouseDoubleClickEvent( self, event ):
|
||||
|
||||
index = self.tabAt( event.pos() )
|
||||
index = self.tabAt( event.position().toPoint() )
|
||||
|
||||
if event.button() == QC.Qt.LeftButton:
|
||||
|
||||
|
@ -649,7 +537,7 @@ class TabWidgetWithDnD( QW.QTabWidget ):
|
|||
|
||||
def mouseMoveEvent( self, e ):
|
||||
|
||||
if self.currentWidget() and self.currentWidget().rect().contains( self.currentWidget().mapFromGlobal( self.mapToGlobal( e.pos() ) ) ):
|
||||
if self.currentWidget() and self.currentWidget().rect().contains( self.currentWidget().mapFromGlobal( self.mapToGlobal( e.position().toPoint() ) ) ):
|
||||
|
||||
QW.QTabWidget.mouseMoveEvent( self, e )
|
||||
|
||||
|
@ -659,7 +547,7 @@ class TabWidgetWithDnD( QW.QTabWidget ):
|
|||
return
|
||||
|
||||
|
||||
my_mouse_pos = e.pos()
|
||||
my_mouse_pos = e.position().toPoint()
|
||||
global_mouse_pos = self.mapToGlobal( my_mouse_pos )
|
||||
tab_bar_mouse_pos = self._tab_bar.mapFromGlobal( global_mouse_pos )
|
||||
|
||||
|
@ -680,7 +568,7 @@ class TabWidgetWithDnD( QW.QTabWidget ):
|
|||
return
|
||||
|
||||
|
||||
if e.globalPosition() == clicked_global_pos:
|
||||
if e.globalPosition().toPoint() == clicked_global_pos:
|
||||
|
||||
# don't start a drag until movement
|
||||
|
||||
|
@ -714,7 +602,7 @@ class TabWidgetWithDnD( QW.QTabWidget ):
|
|||
drag.exec_( QC.Qt.MoveAction )
|
||||
|
||||
|
||||
def dragEnterEvent( self, e ):
|
||||
def dragEnterEvent( self, e: QG.QDragEnterEvent ):
|
||||
|
||||
if self.currentWidget() and self.currentWidget().rect().contains( self.currentWidget().mapFromGlobal( self.mapToGlobal( e.position().toPoint() ) ) ):
|
||||
|
||||
|
@ -731,11 +619,11 @@ class TabWidgetWithDnD( QW.QTabWidget ):
|
|||
|
||||
|
||||
|
||||
def dragMoveEvent( self, event ):
|
||||
def dragMoveEvent( self, event: QG.QDragMoveEvent ):
|
||||
|
||||
#if self.currentWidget() and self.currentWidget().rect().contains( self.currentWidget().mapFromGlobal( self.mapToGlobal( event.pos() ) ) ): return QW.QTabWidget.dragMoveEvent( self, event )
|
||||
#if self.currentWidget() and self.currentWidget().rect().contains( self.currentWidget().mapFromGlobal( self.mapToGlobal( event.position().toPoint() ) ) ): return QW.QTabWidget.dragMoveEvent( self, event )
|
||||
|
||||
screen_pos = self.mapToGlobal( event.pos() )
|
||||
screen_pos = self.mapToGlobal( event.position().toPoint() )
|
||||
|
||||
tab_pos = self._tab_bar.mapFromGlobal( screen_pos )
|
||||
|
||||
|
@ -743,7 +631,7 @@ class TabWidgetWithDnD( QW.QTabWidget ):
|
|||
|
||||
if tab_index != -1:
|
||||
|
||||
shift_down = event.keyboardModifiers() & QC.Qt.ShiftModifier
|
||||
shift_down = event.modifiers() & QC.Qt.ShiftModifier
|
||||
|
||||
self.setCurrentIndex( tab_index )
|
||||
|
||||
|
@ -756,9 +644,9 @@ class TabWidgetWithDnD( QW.QTabWidget ):
|
|||
#return QW.QTabWidget.dragMoveEvent( self, event )
|
||||
|
||||
|
||||
def dragLeaveEvent( self, e ):
|
||||
def dragLeaveEvent( self, e: QG.QDragLeaveEvent ):
|
||||
|
||||
#if self.currentWidget() and self.currentWidget().rect().contains( self.currentWidget().mapFromGlobal( self.mapToGlobal( e.pos() ) ) ): return QW.QTabWidget.dragLeaveEvent( self, e )
|
||||
#if self.currentWidget() and self.currentWidget().rect().contains( self.currentWidget().mapFromGlobal( self.mapToGlobal( e.position().toPoint() ) ) ): return QW.QTabWidget.dragLeaveEvent( self, e )
|
||||
|
||||
e.accept()
|
||||
|
||||
|
@ -783,13 +671,13 @@ class TabWidgetWithDnD( QW.QTabWidget ):
|
|||
QW.QTabWidget.insertTab( self, index, widget, *args, **kwargs )
|
||||
|
||||
|
||||
def dropEvent( self, e ):
|
||||
def dropEvent( self, e: QG.QDropEvent ):
|
||||
|
||||
if self.currentWidget() and self.currentWidget().rect().contains( self.currentWidget().mapFromGlobal( self.mapToGlobal( e.pos() ) ) ):
|
||||
if self.currentWidget() and self.currentWidget().rect().contains( self.currentWidget().mapFromGlobal( self.mapToGlobal( e.position().toPoint() ) ) ):
|
||||
|
||||
return QW.QTabWidget.dropEvent( self, e )
|
||||
|
||||
|
||||
|
||||
if 'application/hydrus-tab' not in e.mimeData().formats(): #Page dnd has no associated mime data
|
||||
|
||||
e.ignore()
|
||||
|
@ -832,7 +720,7 @@ class TabWidgetWithDnD( QW.QTabWidget ):
|
|||
|
||||
counter = self.count()
|
||||
|
||||
screen_pos = self.mapToGlobal( e.pos() )
|
||||
screen_pos = self.mapToGlobal( e.position().toPoint() )
|
||||
|
||||
tab_pos = self.tabBar().mapFromGlobal( screen_pos )
|
||||
|
||||
|
@ -857,8 +745,10 @@ class TabWidgetWithDnD( QW.QTabWidget ):
|
|||
left_edge_rect = QC.QRect( tab_rect.topLeft(), edge_size )
|
||||
right_edge_rect = QC.QRect( tab_rect.topRight() - QC.QPoint( EDGE_PADDING, 0 ), edge_size )
|
||||
|
||||
dropped_on_left_edge = left_edge_rect.contains( e.pos() )
|
||||
dropped_on_right_edge = right_edge_rect.contains( e.pos() )
|
||||
drop_pos = e.position().toPoint()
|
||||
|
||||
dropped_on_left_edge = left_edge_rect.contains( drop_pos )
|
||||
dropped_on_right_edge = right_edge_rect.contains( drop_pos )
|
||||
|
||||
|
||||
if counter == 0:
|
||||
|
@ -902,8 +792,8 @@ class TabWidgetWithDnD( QW.QTabWidget ):
|
|||
|
||||
self.insertTab( insert_index, source_page, source_name )
|
||||
|
||||
shift_down = e.keyboardModifiers() & QC.Qt.ShiftModifier
|
||||
|
||||
shift_down = e.modifiers() & QC.Qt.ShiftModifier
|
||||
|
||||
follow_dropped_page = not shift_down
|
||||
|
||||
new_options = HG.client_controller.new_options
|
||||
|
|
|
@ -1119,7 +1119,7 @@ class ListBox( QW.QScrollArea ):
|
|||
|
||||
def _GetLogicalIndexUnderMouse( self, mouse_event ):
|
||||
|
||||
y = mouse_event.pos().y()
|
||||
y = mouse_event.position().toPoint().y()
|
||||
|
||||
if mouse_event.type() == QC.QEvent.MouseMove:
|
||||
|
||||
|
|
|
@ -2916,8 +2916,10 @@ class MediaPanelThumbnails( MediaPanel ):
|
|||
|
||||
def _GetThumbnailUnderMouse( self, mouse_event ):
|
||||
|
||||
x = mouse_event.pos().x()
|
||||
y = mouse_event.pos().y()
|
||||
pos = mouse_event.position().toPoint()
|
||||
|
||||
x = pos.x()
|
||||
y = pos.y()
|
||||
|
||||
( t_span_x, t_span_y ) = self._GetThumbnailSpanDimensions()
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ try:
|
|||
HydrusBoot.AddBaseDirToEnvPath()
|
||||
|
||||
# initialise Qt here, important it is done early
|
||||
from hydrus.client.gui import QtPorting as QP
|
||||
from hydrus.client.gui import QtInit
|
||||
|
||||
from hydrus.core import HydrusConstants as HC
|
||||
from hydrus.core import HydrusData
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
from hydrus.client.gui import QtInit
|
||||
from hydrus.client.gui import QtPorting as QP
|
||||
from qtpy import QtWidgets as QW
|
||||
|
||||
|
@ -36,7 +37,7 @@ def boot():
|
|||
|
||||
threading.Thread( target = reactor.run, kwargs = { 'installSignalHandlers' : 0 } ).start()
|
||||
|
||||
QP.MonkeyPatchMissingMethods()
|
||||
QtInit.MonkeyPatchMissingMethods()
|
||||
app = QW.QApplication( sys.argv )
|
||||
|
||||
app.call_after_catcher = QP.CallAfterEventCatcher( app )
|
||||
|
|
|
@ -3,11 +3,10 @@ on:
|
|||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
workflow_dispatch: []
|
||||
|
||||
jobs:
|
||||
build-client:
|
||||
runs-on: [ubuntu-latest]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
|
@ -53,7 +52,7 @@ jobs:
|
|||
labels: ${{ steps.docker_meta.outputs.labels }}
|
||||
|
||||
build-server:
|
||||
runs-on: [ubuntu-latest]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
|
@ -99,4 +98,4 @@ jobs:
|
|||
file: ./static/build_files/docker/server/Dockerfile
|
||||
platforms: linux/amd64,linux/386,linux/arm/v6,linux/arm/v7,linux/arm64
|
||||
tags: ${{ steps.docker_meta.outputs.tags }}
|
||||
labels: ${{ steps.docker_meta.outputs.labels }}
|
||||
labels: ${{ steps.docker_meta.outputs.labels }}
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
beautifulsoup4>=4.0.0
|
||||
cbor2
|
||||
chardet>=3.0.4
|
||||
cloudscraper>=1.2.33
|
||||
html5lib>=1.0.1
|
||||
lxml>=4.5.0
|
||||
lz4>=3.0.0
|
||||
nose>=1.3.0
|
||||
numpy>=1.16.0
|
||||
opencv-python-headless>=4.0.0, <=4.5.3.56
|
||||
Pillow>=6.0.0
|
||||
psutil>=5.0.0
|
||||
pylzma>=0.5.0
|
||||
pyOpenSSL>=19.1.0
|
||||
PySide6>=6.0.0
|
||||
PySocks>=1.7.0
|
||||
python-mpv==0.4.5
|
||||
PyYAML>=5.0.0
|
||||
QtPy>=1.9.0
|
||||
requests==2.23.0
|
||||
Send2Trash>=1.5.0
|
||||
service-identity>=18.1.0
|
||||
six>=1.14.0
|
||||
Twisted>=20.3.0
|
|
@ -0,0 +1,24 @@
|
|||
beautifulsoup4>=4.0.0
|
||||
cbor2
|
||||
chardet>=3.0.4
|
||||
cloudscraper>=1.2.33
|
||||
html5lib>=1.0.1
|
||||
lxml>=4.5.0
|
||||
lz4>=3.0.0
|
||||
nose>=1.3.0
|
||||
numpy>=1.16.0
|
||||
opencv-python-headless>=4.0.0, <=4.5.3.56
|
||||
Pillow>=6.0.0
|
||||
psutil>=5.0.0
|
||||
pylzma>=0.5.0
|
||||
pyOpenSSL>=19.1.0
|
||||
PySide6>=6.0.0
|
||||
PySocks>=1.7.0
|
||||
python-mpv==0.4.5
|
||||
PyYAML>=5.0.0
|
||||
QtPy>=1.9.0
|
||||
requests==2.23.0
|
||||
Send2Trash>=1.5.0
|
||||
service-identity>=18.1.0
|
||||
six>=1.14.0
|
||||
Twisted>=20.3.0
|
|
@ -0,0 +1,28 @@
|
|||
beautifulsoup4>=4.0.0
|
||||
cbor2
|
||||
chardet>=3.0.4
|
||||
cloudscraper>=1.2.33
|
||||
html5lib>=1.0.1
|
||||
lxml>=4.5.0
|
||||
lz4>=3.0.0
|
||||
nose>=1.3.0
|
||||
numpy>=1.16.0
|
||||
opencv-python-headless>=4.0.0, <=4.5.3.56
|
||||
Pillow>=6.0.0
|
||||
psutil>=5.0.0
|
||||
pylzma>=0.5.0
|
||||
pyOpenSSL>=19.1.0
|
||||
PySide6>=6.0.0
|
||||
PySocks>=1.7.0
|
||||
python-mpv==0.5.2
|
||||
PyYAML>=5.0.0
|
||||
QtPy>=1.9.0
|
||||
requests==2.23.0
|
||||
Send2Trash>=1.5.0
|
||||
service-identity>=18.1.0
|
||||
six>=1.14.0
|
||||
Twisted>=20.3.0
|
||||
PyWin32
|
||||
pypiwin32
|
||||
pywin32-ctypes
|
||||
pefile
|
Loading…
Reference in New Issue