Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PyQt6 Upgrade #1685

Merged
merged 24 commits into from
Apr 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ jobs:
sudo apt update && sudo apt install -y \
xvfb libssl-dev openssl libacl1-dev libacl1 build-essential borgbackup \
libxkbcommon-x11-0 dbus-x11 libxcb-icccm4 libxcb-image0 libxcb-keysyms1 \
libxcb-randr0 libxcb-render-util0 libxcb-xinerama0 libxcb-xfixes0 libxcb-shape0
libxcb-randr0 libxcb-render-util0 libxcb-xinerama0 libxcb-xfixes0 libxcb-shape0 \
libegl1 libxcb-cursor0
- name: Install system dependencies (macOS)
if: runner.os == 'macOS'
run: |
Expand Down
6 changes: 3 additions & 3 deletions package/fix_app_qt_folder_names_for_codesign.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ def create_symlink(folder: Path) -> None:
"""
sibbling = Path(str(folder).replace("MacOS", ""))

# PyQt5/Qt/qml/QtQml/Models.2
# PyQt6/Qt/qml/QtQml/Models.2
root = str(sibbling).partition("Contents")[2].lstrip("/")
# ../../../../
backward = "../" * (root.count("/") + 1)
# ../../../../Resources/PyQt5/Qt/qml/QtQml/Models.2
# ../../../../Resources/PyQt6/Qt/qml/QtQml/Models.2
good_path = f"{backward}Resources/{root}"

folder.symlink_to(good_path)
Expand All @@ -51,7 +51,7 @@ def match_func(pth: str) -> Optional[str]:
return None
return f"@loader_path{good_path}/{basename}"

# Resources/PyQt5/Qt/qml/QtQuick/Controls.2/Fusion
# Resources/PyQt6/Qt/qml/QtQuick/Controls.2/Fusion
root = str(dll.parent).partition("Contents")[2][1:]
# /../../../../../../..
backward = "/.." * (root.count("/") + 1)
Expand Down
10 changes: 5 additions & 5 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,14 @@ python_requires = >=3.7
install_requires =
platformdirs >=3.0.0, <4.0.0; sys_platform == 'darwin' # for macOS: breaking changes in 3.0.0,
platformdirs >=2.6.0, <4.0.0; sys_platform != 'darwin' # for others: 2.6+ works consistently.
pyqt5
pyqt6
peewee
psutil
setuptools
secretstorage; sys_platform != 'darwin'
pyobjc-core; sys_platform == 'darwin'
pyobjc-framework-Cocoa; sys_platform == 'darwin'
pyobjc-framework-LaunchServices; sys_platform == 'darwin'
pyobjc-core < 9.1; sys_platform == 'darwin'
pyobjc-framework-Cocoa < 9.1; sys_platform == 'darwin'
pyobjc-framework-LaunchServices < 9.1; sys_platform == 'darwin'
tests_require =
pytest
pytest-qt
Expand Down Expand Up @@ -100,7 +100,7 @@ commands=flake8 src tests
max_line_length = 120

[pylint.master]
extension-pkg-whitelist=PyQt5
extension-pkg-whitelist=PyQt6
load-plugins=

[pylint.messages control]
Expand Down
2 changes: 1 addition & 1 deletion src/vorta/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
def main():
def exception_handler(type, value, tb):
from traceback import format_exception
from PyQt5.QtWidgets import QMessageBox
from PyQt6.QtWidgets import QMessageBox

logger.critical(
"Uncaught exception, file a report at https://github.com/borgbase/vorta/issues/new/choose",
Expand Down
2 changes: 1 addition & 1 deletion src/vorta/_version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = '0.8.11'
__version__ = '0.9.0'
22 changes: 11 additions & 11 deletions src/vorta/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
import sys
from pathlib import Path
from typing import Any, Dict, List, Tuple
from PyQt5 import QtCore
from PyQt5.QtWidgets import QMessageBox
from PyQt6 import QtCore
from PyQt6.QtWidgets import QMessageBox
from vorta.borg.break_lock import BorgBreakJob
from vorta.borg.create import BorgCreateJob
from vorta.borg.jobs_manager import JobsManager
Expand Down Expand Up @@ -179,10 +179,10 @@ def set_borg_details_result(self, result):

def _alert_missing_borg(self):
msg = QMessageBox()
msg.setIcon(QMessageBox.Critical)
msg.setIcon(QMessageBox.Icon.Critical)
msg.setText(self.tr("No Borg Binary Found"))
msg.setInformativeText(self.tr("Vorta was unable to locate a usable Borg Backup binary."))
msg.setStandardButtons(QMessageBox.Ok)
msg.setStandardButtons(QMessageBox.StandardButton.Ok)
msg.exec()

def check_darwin_permissions(self):
Expand All @@ -201,8 +201,8 @@ def check_darwin_permissions(self):
test_path = Path('~/Library/Cookies').expanduser()
if test_path.exists() and not os.access(test_path, os.R_OK):
msg = QMessageBox()
msg.setIcon(QMessageBox.Warning)
msg.setTextInteractionFlags(QtCore.Qt.LinksAccessibleByMouse)
msg.setIcon(QMessageBox.Icon.Warning)
msg.setTextInteractionFlags(QtCore.Qt.TextInteractionFlag.LinksAccessibleByMouse)
msg.setText(self.tr("Vorta needs Full Disk Access for complete Backups"))
msg.setInformativeText(
self.tr(
Expand All @@ -212,7 +212,7 @@ def check_darwin_permissions(self):
"System Preferences > Security & Privacy</a>."
)
)
msg.setStandardButtons(QMessageBox.Ok)
msg.setStandardButtons(QMessageBox.StandardButton.Ok)
msg.exec()

def react_to_log(self, mgs, context):
Expand All @@ -225,9 +225,9 @@ def react_to_log(self, mgs, context):
repo_url = context.get('repo_url')
msg = QMessageBox()
msg.setWindowTitle(self.tr("Repository In Use"))
msg.setIcon(QMessageBox.Critical)
abortButton = msg.addButton(self.tr("Abort"), QMessageBox.RejectRole)
msg.addButton(self.tr("Continue"), QMessageBox.AcceptRole)
msg.setIcon(QMessageBox.Icon.Critical)
abortButton = msg.addButton(self.tr("Abort"), QMessageBox.ButtonRole.RejectRole)
msg.addButton(self.tr("Continue"), QMessageBox.ButtonRole.AcceptRole)
msg.setDefaultButton(abortButton)
msg.setText(self.tr(f"The repository at {repo_url} might be in use elsewhere."))
msg.setInformativeText(
Expand Down Expand Up @@ -324,7 +324,7 @@ def check_failed_response(self, result: Dict[str, Any]):
# Create QMessageBox
msg = QMessageBox()
msg.setIcon(QMessageBox.Icon.Critical) # changed for warning
msg.setStandardButtons(QMessageBox.Ok)
msg.setStandardButtons(QMessageBox.StandardButton.Ok)
msg.setWindowTitle(self.tr('Repo Check Failed'))

if returncode == 1:
Expand Down
4 changes: 2 additions & 2 deletions src/vorta/borg/borg_job.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
from datetime import datetime as dt
from subprocess import PIPE, Popen, TimeoutExpired
from threading import Lock
from PyQt5 import QtCore
from PyQt5.QtWidgets import QApplication
from PyQt6 import QtCore
from PyQt6.QtWidgets import QApplication
from vorta import application
from vorta.borg.jobs_manager import JobInterface
from vorta.i18n import trans_late, translate
Expand Down
2 changes: 1 addition & 1 deletion src/vorta/borg/extract.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import tempfile
from PyQt5.QtCore import QModelIndex, Qt
from PyQt6.QtCore import QModelIndex, Qt
from vorta.utils import borg_compat
from vorta.views.extract_dialog import ExtractTree, FileData
from vorta.views.partials.treemodel import FileSystemItem, path_to_str
Expand Down
2 changes: 1 addition & 1 deletion src/vorta/borg/jobs_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import queue
import threading
from abc import abstractmethod
from PyQt5.QtCore import QObject
from PyQt6.QtCore import QObject

logger = logging.getLogger(__name__)

Expand Down
2 changes: 1 addition & 1 deletion src/vorta/i18n/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"""
import logging
import os
from PyQt5.QtCore import QLocale, QTranslator
from PyQt6.QtCore import QLocale, QTranslator

logger = logging.getLogger(__name__)

Expand Down
10 changes: 5 additions & 5 deletions src/vorta/keyring/kwallet.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import logging
import os
from PyQt5 import QtDBus
from PyQt5.QtCore import QVariant
from PyQt6 import QtDBus
from PyQt6.QtCore import QMetaType, QVariant
from vorta.keyring.abc import VortaKeyring

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -47,9 +47,9 @@ def get_password(self, service, repo_url):

def get_result(self, method, args=[]):
if args:
result = self.iface.callWithArgumentList(QtDBus.QDBus.AutoDetect, method, args)
result = self.iface.callWithArgumentList(QtDBus.QDBus.CallMode.AutoDetect, method, args)
else:
result = self.iface.call(QtDBus.QDBus.AutoDetect, method)
result = self.iface.call(QtDBus.QDBus.CallMode.AutoDetect, method)
return result.arguments()[0]

@property
Expand All @@ -60,7 +60,7 @@ def is_unlocked(self):
def try_unlock(self):
wallet_name = self.get_result("networkWallet")
wId = QVariant(0)
wId.convert(4)
wId.convert(QMetaType(QMetaType.Type.LongLong.value))
output = self.get_result("open", args=[wallet_name, wId, 'vorta-repo'])
try:
self.handle = int(output)
Expand Down
2 changes: 1 addition & 1 deletion src/vorta/log.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
def init_logger(background=False):
logger.setLevel(logging.DEBUG)
logging.getLogger('peewee').setLevel(logging.INFO)
logging.getLogger('PyQt5').setLevel(logging.INFO)
logging.getLogger('PyQt6').setLevel(logging.INFO)

# create logging format
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
Expand Down
4 changes: 2 additions & 2 deletions src/vorta/network_status/network_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
from datetime import datetime
from enum import Enum
from typing import Any, List, Mapping, NamedTuple, Optional
from PyQt5 import QtDBus
from PyQt5.QtCore import QObject, QVersionNumber
from PyQt6 import QtDBus
from PyQt6.QtCore import QObject, QVersionNumber
from vorta.network_status.abc import NetworkStatusMonitor, SystemWifiInfo

logger = logging.getLogger(__name__)
Expand Down
13 changes: 7 additions & 6 deletions src/vorta/notifications.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import logging
import sys
from PyQt5 import QtCore, QtDBus
from PyQt6 import QtCore, QtDBus
from vorta.store.models import SettingsModel

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -77,21 +77,22 @@ def _dbus_notify(self, header, msg, level='info'):
path = "/org/freedesktop/Notifications"
interface = "org.freedesktop.Notifications"
app_name = "vorta"
v = QtCore.QVariant(12321) # random int to identify all notifications
if v.convert(QtCore.QVariant.UInt):
id_replace = v
id_replace = QtCore.QVariant(12321)
id_replace.convert(QtCore.QMetaType(QtCore.QMetaType.Type.UInt.value))
icon = "com.borgbase.Vorta-symbolic"
title = header
text = msg
actions_list = QtDBus.QDBusArgument([], QtCore.QMetaType.QStringList)
actions_list = QtDBus.QDBusArgument([], QtCore.QMetaType.Type.QStringList.value)
hint = {'urgency': self.URGENCY[level]}
time = 5000 # milliseconds for display timeout

bus = QtDBus.QDBusConnection.sessionBus()
notify = QtDBus.QDBusInterface(item, path, interface, bus)
if notify.isValid():
x = notify.call(
QtDBus.QDBus.AutoDetect,
# Call arguments for Notify interface need to match exactly:
# https://specifications.freedesktop.org/notification-spec/notification-spec-latest.html#command-notify
QtDBus.QDBus.CallMode.AutoDetect,
"Notify",
app_name,
id_replace,
Expand Down
8 changes: 3 additions & 5 deletions src/vorta/qt_single_application.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from PyQt5.QtCore import QTextStream, pyqtSignal
from PyQt5.QtNetwork import QLocalServer, QLocalSocket
from PyQt5.QtWidgets import QApplication
from PyQt6.QtCore import QTextStream, pyqtSignal
from PyQt6.QtNetwork import QLocalServer, QLocalSocket
from PyQt6.QtWidgets import QApplication


class QtSingleApplication(QApplication):
Expand Down Expand Up @@ -52,7 +52,6 @@ def __init__(self, id, *argv):
if self._isRunning:
# Yes, there is.
self._outStream = QTextStream(self._outSocket)
self._outStream.setCodec('UTF-8')
else:
# No, there isn't.
self._outSocket = None
Expand Down Expand Up @@ -84,7 +83,6 @@ def _onNewConnection(self):
if not self._inSocket:
return
self._inStream = QTextStream(self._inSocket)
self._inStream.setCodec('UTF-8')
self._inSocket.readyRead.connect(self._onReadyRead)

def _onReadyRead(self):
Expand Down
6 changes: 3 additions & 3 deletions src/vorta/scheduler.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
from datetime import datetime as dt
from datetime import timedelta
from typing import Dict, NamedTuple, Optional, Tuple, Union
from PyQt5 import QtCore, QtDBus
from PyQt5.QtCore import QTimer
from PyQt5.QtWidgets import QApplication
from PyQt6 import QtCore, QtDBus
from PyQt6.QtCore import QTimer
from PyQt6.QtWidgets import QApplication
from vorta import application
from vorta.borg.check import BorgCheckJob
from vorta.borg.create import BorgCreateJob
Expand Down
8 changes: 4 additions & 4 deletions src/vorta/tray_menu.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import os
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QApplication, QMenu, QSystemTrayIcon
from PyQt6.QtGui import QIcon
from PyQt6.QtWidgets import QApplication, QMenu, QSystemTrayIcon
from vorta.store.models import BackupProfileModel
from vorta.utils import get_asset

Expand Down Expand Up @@ -31,8 +31,8 @@ def on_activation(self, reason):
If XDG_CURRENT_DESKTOP isn't set, always open the tray menu (macOS)
"""
if reason in [
QSystemTrayIcon.Trigger,
QSystemTrayIcon.DoubleClick,
QSystemTrayIcon.ActivationReason.Trigger,
QSystemTrayIcon.ActivationReason.DoubleClick,
] and os.environ.get('XDG_CURRENT_DESKTOP'):
self.app.toggle_main_window_visibility()

Expand Down
15 changes: 6 additions & 9 deletions src/vorta/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,14 @@
from functools import reduce
from typing import Any, Callable, Iterable, List, Optional, Tuple, TypeVar
import psutil
from PyQt5 import QtCore
from PyQt5.QtCore import QFileInfo, QThread, pyqtSignal
from PyQt5.QtWidgets import QApplication, QFileDialog, QSystemTrayIcon
from PyQt6 import QtCore
from PyQt6.QtCore import QFileInfo, QThread, pyqtSignal
from PyQt6.QtWidgets import QApplication, QFileDialog, QSystemTrayIcon
from vorta.borg._compatibility import BorgCompatibility
from vorta.i18n import trans_late
from vorta.log import logger
from vorta.network_status.abc import NetworkStatusMonitor

QApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling, True) # enable highdpi scaling
QApplication.setAttribute(QtCore.Qt.AA_UseHighDpiPixmaps, True) # use highdpi icons

borg_compat = BorgCompatibility()
_network_status_monitor = None

Expand Down Expand Up @@ -168,10 +165,10 @@ def get_dict_from_list(dataDict, mapList):

def choose_file_dialog(parent, title, want_folder=True):
dialog = QFileDialog(parent, title, os.path.expanduser('~'))
dialog.setFileMode(QFileDialog.Directory if want_folder else QFileDialog.ExistingFiles)
dialog.setParent(parent, QtCore.Qt.Sheet)
dialog.setFileMode(QFileDialog.FileMode.Directory if want_folder else QFileDialog.FileMode.ExistingFiles)
dialog.setParent(parent, QtCore.Qt.WindowType.Sheet)
if want_folder:
dialog.setOption(QFileDialog.ShowDirsOnly)
dialog.setOption(QFileDialog.Option.ShowDirsOnly)
return dialog


Expand Down