diff --git a/Makefile b/Makefile index 71be91cb..bed56f31 100644 --- a/Makefile +++ b/Makefile @@ -60,8 +60,8 @@ ifndef NO_VENV @${PYTHON} -m venv -h > /dev/null || \ echo "Creation of our virtualenv failed. If you're on Ubuntu, you probably need python3-venv." endif - @${PYTHON} -c 'import PyQt5' >/dev/null 2>&1 || \ - { echo "PyQt 5.4+ required. Install it and try again. Aborting"; exit 1; } + @${PYTHON} -c 'import PyQt6' >/dev/null 2>&1 || \ + { echo "PyQt 6.3+ required. Install it and try again. Aborting"; exit 1; } env: | reqs ifndef NO_VENV diff --git a/README.md b/README.md index 60194318..7ea743d9 100644 --- a/README.md +++ b/README.md @@ -32,18 +32,15 @@ For macos instructions (qt version) see the [macOS Instructions](macos.md). ### Prerequisites * [Python 3.7+][python] -* PyQt5 +* PyQt6 ### System Setup When running in a linux based environment the following system packages or equivalents are needed to build: -* python3-pyqt5 -* pyqt5-dev-tools (on some systems, see note) +* python3-pyqt6 * python3-venv (only if using a virtual environment) * python3-dev * build-essential -Note: On some linux systems pyrcc5 is not put on the path when installing python3-pyqt5, this will cause some issues with the resource files (and icons). These systems should have a respective pyqt5-dev-tools package, which should also be installed. The presence of pyrcc5 can be checked with `which pyrcc5`. Debian based systems need the extra package, and Arch does not. - To create packages the following are also needed: * python3-setuptools * debhelper diff --git a/Windows.md b/Windows.md index 13f60ae1..461e5643 100644 --- a/Windows.md +++ b/Windows.md @@ -28,7 +28,7 @@ To build with a different python version 3.7 vs 3.8 or 32 bit vs 64 bit specify ### With makefile It is possible to build dupeGuru with the makefile on windows using a compatable POSIX environment. The following steps have been tested using [msys2][msys2]. Before running make: 1. Install msys2 or other POSIX environment -2. Install PyQt5 globally via pip +2. Install PyQt6 globally via pip 3. Use the respective console for msys2 it is `msys2 msys` Then the following execution of the makefile should work. Pass the correct value for PYTHON to the makefile if not on the path as python3. diff --git a/macos.md b/macos.md index ae0c8c74..355d97be 100644 --- a/macos.md +++ b/macos.md @@ -7,19 +7,19 @@ These instructions are for the Qt version of the UI on macOS. - [Python 3.7+][python] - [Xcode 12.3][xcode] or just Xcode command line tools (older versions can be used if not interested in arm macs) - [Homebrew][homebrew] -- [qt5](https://www.qt.io/) +- [qt6](https://www.qt.io/) #### Prerequisite setup 1. Install Xcode if desired 2. Install [Homebrew][homebrew], if not on the path after install (arm based Macs) create `~/.zshrc` with `export PATH="/opt/homebrew/bin:$PATH"`. Will need to reload terminal or source the file to take effect. -3. Install qt5 with `brew`. If you are using a version of macos without system python 3.7+ then you will +3. Install qt6 with `brew`. If you are using a version of macos without system python 3.7+ then you will also need to install that via brew or with pyenv. - $ brew install qt5 + $ brew install qt6 - NOTE: Using `brew` to install qt5 is to allow pyqt5 to build without a native wheel + NOTE: Using `brew` to install qt6 is to allow pyqt6 to build without a native wheel available. If you are using an intel based mac you can probably skip this step. 4. May need to launch a new terminal to have everything working. diff --git a/qt/util.py b/qt/util.py index ba6e0eb6..46c2894f 100644 --- a/qt/util.py +++ b/qt/util.py @@ -11,22 +11,18 @@ import io import os.path as op import os import logging +from typing import List, Union from core.util import executable_folder from hscommon.util import first from hscommon.plat import ISWINDOWS -from PyQt5.QtCore import QStandardPaths, QSettings -from PyQt5.QtGui import QPixmap, QIcon, QGuiApplication -from PyQt5.QtWidgets import ( - QSpacerItem, - QSizePolicy, - QAction, - QHBoxLayout, -) +from PyQt6.QtCore import QStandardPaths, QSettings +from PyQt6.QtGui import QPixmap, QIcon, QGuiApplication, QAction +from PyQt6.QtWidgets import QSpacerItem, QSizePolicy, QHBoxLayout, QWidget -def move_to_screen_center(widget): +def move_to_screen_center(widget: QWidget) -> None: frame = widget.frameGeometry() if QGuiApplication.screenAt(frame.center()) is None: # if center not on any screen use default screen @@ -43,21 +39,21 @@ def move_to_screen_center(widget): widget.move(frame.topLeft()) -def vertical_spacer(size=None): +def vertical_spacer(size: Union[int, None] = None) -> QSpacerItem: if size: - return QSpacerItem(1, size, QSizePolicy.Fixed, QSizePolicy.Fixed) + return QSpacerItem(1, size, QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed) else: - return QSpacerItem(1, 1, QSizePolicy.Fixed, QSizePolicy.MinimumExpanding) + return QSpacerItem(1, 1, QSizePolicy.Policy.Fixed, QSizePolicy.Policy.MinimumExpanding) -def horizontal_spacer(size=None): +def horizontal_spacer(size: Union[int, None] = None) -> QSpacerItem: if size: - return QSpacerItem(size, 1, QSizePolicy.Fixed, QSizePolicy.Fixed) + return QSpacerItem(size, 1, QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed) else: - return QSpacerItem(1, 1, QSizePolicy.MinimumExpanding, QSizePolicy.Fixed) + return QSpacerItem(1, 1, QSizePolicy.Policy.MinimumExpanding, QSizePolicy.Policy.Fixed) -def horizontal_wrap(widgets): +def horizontal_wrap(widgets: List[Union[QWidget, int, None]]) -> QHBoxLayout: """Wrap all widgets in `widgets` in a horizontal layout. If, instead of placing a widget in your list, you place an int or None, an horizontal spacer @@ -77,7 +73,7 @@ def create_actions(actions, target): for name, shortcut, icon, desc, func in actions: action = QAction(target) if icon: - action.setIcon(QIcon(QPixmap(":/" + icon))) + action.setIcon(QIcon(QPixmap(":/" + icon))) # TODO stop using qrc file path if shortcut: action.setShortcut(shortcut) action.setText(desc) @@ -100,11 +96,11 @@ def set_accel_keys(menu): action.setText(newtext) -def get_appdata(portable=False): +def get_appdata(portable: bool = False) -> str: if portable: return op.join(executable_folder(), "data") else: - return QStandardPaths.standardLocations(QStandardPaths.AppDataLocation)[0] + return QStandardPaths.standardLocations(QStandardPaths.StandardLocation.AppDataLocation)[0] class SysWrapper(io.IOBase): @@ -140,18 +136,18 @@ def escape_amp(s): return s.replace("&", "&&") -def create_qsettings(): +def create_qsettings() -> QSettings: # Create a QSettings instance with the correct arguments. config_location = op.join(executable_folder(), "settings.ini") if op.isfile(config_location): - settings = QSettings(config_location, QSettings.IniFormat) + settings = QSettings(config_location, QSettings.Format.IniFormat) settings.setValue("Portable", True) elif ISWINDOWS: # On windows use an ini file in the AppDataLocation instead of registry if possible as it # makes it easier for a user to clear it out when there are issues. - locations = QStandardPaths.standardLocations(QStandardPaths.AppDataLocation) + locations = QStandardPaths.standardLocations(QStandardPaths.StandardLocation.AppDataLocation) if locations: - settings = QSettings(op.join(locations[0], "settings.ini"), QSettings.IniFormat) + settings = QSettings(op.join(locations[0], "settings.ini"), QSettings.Format.IniFormat) else: settings = QSettings() settings.setValue("Portable", False) diff --git a/requirements-extra.txt b/requirements-extra.txt index 163d000b..3cca6c0f 100644 --- a/requirements-extra.txt +++ b/requirements-extra.txt @@ -1,4 +1,4 @@ -pytest>=6,<7 +pytest>=6,<7.2 flake8 black pyinstaller>=4.5,<5.0; sys_platform != 'linux' \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index e52757ba..98e4aed9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,9 +1,9 @@ -distro>=1.5.0 -mutagen>=1.44.0 -polib>=1.1.0 -PyQt5 >=5.14.1,<6.0; sys_platform != 'linux' +distro>=1.5.0, <2.0 +mutagen>=1.44.0, <2.0 +polib>=1.1.0, <2.0 +PyQt6 >=6.3,<7.0; sys_platform != 'linux' pywin32>=228; sys_platform == 'win32' semantic-version>=2.0.0,<3.0.0 Send2Trash>=1.3.0 -sphinx>=3.0.0 +sphinx>=5.0.0, <6.0 xxhash>=3.0.0,<4.0.0