PyQt6 Upgrade (#1685)

This puts Vorta on PyQt6 and starts a new main branch 0.9.

---------

Co-authored-by: real-yfprojects <real-yfprojects@users.noreply.github.com>
Co-authored-by: Manu <3916435+m3nu@users.noreply.github.com>
Co-authored-by: yfprojects <62463991+real-yfprojects@users.noreply.github.com>
This commit is contained in:
i1sm3ky 2023-04-17 15:47:01 +05:30 committed by GitHub
parent 8571ef6cb8
commit 7535f92ac8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
47 changed files with 294 additions and 259 deletions

View File

@ -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: |

View File

@ -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)
@ -51,7 +51,7 @@ def fix_dll(dll: Path) -> None:
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)

View File

@ -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
@ -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]

View File

@ -14,7 +14,7 @@ from vorta.utils import parse_args
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",

View File

@ -1 +1 @@
__version__ = '0.8.11'
__version__ = '0.9.0'

View File

@ -3,8 +3,8 @@ import os
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
@ -179,10 +179,10 @@ class VortaApp(QtSingleApplication):
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):
@ -201,8 +201,8 @@ class VortaApp(QtSingleApplication):
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(
@ -212,7 +212,7 @@ class VortaApp(QtSingleApplication):
"System Preferences > Security & Privacy</a>."
)
)
msg.setStandardButtons(QMessageBox.Ok)
msg.setStandardButtons(QMessageBox.StandardButton.Ok)
msg.exec()
def react_to_log(self, mgs, context):
@ -225,9 +225,9 @@ class VortaApp(QtSingleApplication):
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(
@ -324,7 +324,7 @@ class VortaApp(QtSingleApplication):
# 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:

View File

@ -11,8 +11,8 @@ from collections import namedtuple
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

View File

@ -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

View File

@ -2,7 +2,7 @@ import logging
import queue
import threading
from abc import abstractmethod
from PyQt5.QtCore import QObject
from PyQt6.QtCore import QObject
logger = logging.getLogger(__name__)

View File

@ -3,7 +3,7 @@ internationalisation (i18n) support code
"""
import logging
import os
from PyQt5.QtCore import QLocale, QTranslator
from PyQt6.QtCore import QLocale, QTranslator
logger = logging.getLogger(__name__)

View File

@ -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__)
@ -47,9 +47,9 @@ class VortaKWallet5Keyring(VortaKeyring):
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
@ -60,7 +60,7 @@ class VortaKWallet5Keyring(VortaKeyring):
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)

View File

@ -16,7 +16,7 @@ logger = logging.getLogger()
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')

View File

@ -2,8 +2,8 @@ import logging
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__)

View File

@ -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__)
@ -77,13 +77,12 @@ class DBusNotifications(VortaNotifications):
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
@ -91,7 +90,9 @@ class DBusNotifications(VortaNotifications):
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,

View File

@ -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):
@ -52,7 +52,6 @@ class QtSingleApplication(QApplication):
if self._isRunning:
# Yes, there is.
self._outStream = QTextStream(self._outSocket)
self._outStream.setCodec('UTF-8')
else:
# No, there isn't.
self._outSocket = None
@ -84,7 +83,6 @@ class QtSingleApplication(QApplication):
if not self._inSocket:
return
self._inStream = QTextStream(self._inSocket)
self._inStream.setCodec('UTF-8')
self._inSocket.readyRead.connect(self._onReadyRead)
def _onReadyRead(self):

View File

@ -4,9 +4,9 @@ import threading
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

View File

@ -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
@ -31,8 +31,8 @@ class TrayMenu(QSystemTrayIcon):
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()

View File

@ -12,17 +12,14 @@ from datetime import datetime as dt
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
@ -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

View File

@ -2,18 +2,17 @@ import logging
import sys
from datetime import timedelta
from typing import Dict, Optional
from PyQt5 import QtCore, uic
from PyQt5.QtCore import QItemSelectionModel, QMimeData, QPoint, Qt, pyqtSlot
from PyQt5.QtGui import QDesktopServices, QKeySequence
from PyQt5.QtWidgets import (
QAction,
from PyQt6 import QtCore, uic
from PyQt6.QtCore import QItemSelectionModel, QMimeData, QPoint, Qt, pyqtSlot
from PyQt6.QtGui import QAction, QDesktopServices, QKeySequence, QShortcut
from PyQt6.QtWidgets import (
QAbstractItemView,
QApplication,
QHeaderView,
QInputDialog,
QLayout,
QMenu,
QMessageBox,
QShortcut,
QTableView,
QTableWidgetItem,
QWidget,
@ -77,20 +76,20 @@ class ArchiveTab(ArchiveTabBase, ArchiveTabUI, BackupProfileMixin):
header = self.archiveTable.horizontalHeader()
header.setVisible(True)
header.setSectionResizeMode(0, QHeaderView.ResizeToContents)
header.setSectionResizeMode(1, QHeaderView.ResizeToContents)
header.setSectionResizeMode(2, QHeaderView.ResizeToContents)
header.setSectionResizeMode(3, QHeaderView.Interactive)
header.setSectionResizeMode(4, QHeaderView.Stretch)
header.setSectionResizeMode(0, QHeaderView.ResizeMode.ResizeToContents)
header.setSectionResizeMode(1, QHeaderView.ResizeMode.ResizeToContents)
header.setSectionResizeMode(2, QHeaderView.ResizeMode.ResizeToContents)
header.setSectionResizeMode(3, QHeaderView.ResizeMode.Interactive)
header.setSectionResizeMode(4, QHeaderView.ResizeMode.Stretch)
header.setStretchLastSection(True)
if sys.platform != 'darwin':
self._set_status('') # Set platform-specific hints.
self.archiveTable.setSelectionBehavior(QTableView.SelectRows)
self.archiveTable.setEditTriggers(QTableView.NoEditTriggers)
self.archiveTable.setSelectionBehavior(QAbstractItemView.SelectionBehavior.SelectRows)
self.archiveTable.setEditTriggers(QAbstractItemView.EditTrigger.NoEditTriggers)
self.archiveTable.setWordWrap(False)
self.archiveTable.setTextElideMode(QtCore.Qt.ElideLeft)
self.archiveTable.setTextElideMode(QtCore.Qt.TextElideMode.ElideLeft)
self.archiveTable.setAlternatingRowColors(True)
self.archiveTable.cellDoubleClicked.connect(self.cell_double_clicked)
self.archiveTable.setSortingEnabled(True)
@ -757,7 +756,7 @@ class ArchiveTab(ArchiveTabBase, ArchiveTabUI, BackupProfileMixin):
window = ExtractDialog(archive, model)
self._toggle_all_buttons(True)
window.setParent(self, QtCore.Qt.Sheet)
window.setParent(self, QtCore.Qt.WindowType.Sheet)
self._window = window # for testing
window.show()
window.accepted.connect(process_result)
@ -778,19 +777,19 @@ class ArchiveTab(ArchiveTabBase, ArchiveTabUI, BackupProfileMixin):
QDesktopServices.openUrl(QtCore.QUrl(f'file:///{mount_point}'))
def row_of_archive(self, archive_name):
items = self.archiveTable.findItems(archive_name, QtCore.Qt.MatchExactly)
items = self.archiveTable.findItems(archive_name, QtCore.Qt.MatchFlag.MatchExactly)
rows = [item.row() for item in items if item.column() == 4]
return rows[0] if rows else None
def confirm_dialog(self, title, text):
msg = QMessageBox()
msg.setIcon(QMessageBox.Information)
msg.setIcon(QMessageBox.Icon.Information)
msg.setText(text)
msg.setWindowTitle(title)
msg.setStandardButtons(QMessageBox.Yes | QMessageBox.Cancel)
msg.button(msg.Yes).setText(self.tr("Yes"))
msg.button(msg.Cancel).setText(self.tr("Cancel"))
return msg.exec_() == QMessageBox.Yes
msg.setStandardButtons(QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.Cancel)
msg.button(QMessageBox.StandardButton.Yes).setText(self.tr("Yes"))
msg.button(QMessageBox.StandardButton.Cancel).setText(self.tr("Cancel"))
return msg.exec() == QMessageBox.StandardButton.Yes
def delete_action(self):
# Since this function modify the UI, we can't put the whole function in a JobQUeue.
@ -835,7 +834,7 @@ class ArchiveTab(ArchiveTabBase, ArchiveTabUI, BackupProfileMixin):
# remove rows from list and database
for archive in archives:
for entry in self.archiveTable.findItems(archive, QtCore.Qt.MatchExactly):
for entry in self.archiveTable.findItems(archive, QtCore.Qt.MatchFlag.MatchExactly):
self.archiveTable.removeRow(entry.row())
ArchiveModel.get(name=archive).delete_instance()

View File

@ -5,10 +5,10 @@ import re
from dataclasses import dataclass
from pathlib import PurePath
from typing import List, Optional, Tuple
from PyQt5 import uic
from PyQt5.QtCore import QDateTime, QLocale, QMimeData, QModelIndex, QPoint, Qt, QThread, QUrl
from PyQt5.QtGui import QColor, QKeySequence
from PyQt5.QtWidgets import QApplication, QHeaderView, QMenu, QShortcut, QTreeView
from PyQt6 import uic
from PyQt6.QtCore import QDateTime, QLocale, QMimeData, QModelIndex, QPoint, Qt, QThread, QUrl
from PyQt6.QtGui import QColor, QKeySequence, QShortcut
from PyQt6.QtWidgets import QApplication, QHeaderView, QMenu, QTreeView
from vorta.store.models import SettingsModel
from vorta.utils import get_asset, pretty_bytes, uses_dark_mode
from vorta.views.partials.treemodel import (
@ -89,9 +89,9 @@ class DiffResultDialog(DiffResultBase, DiffResultUI):
# header
header = self.treeView.header()
header.setStretchLastSection(False) # stretch only first section
header.setSectionResizeMode(0, QHeaderView.Stretch)
header.setSectionResizeMode(1, QHeaderView.ResizeToContents)
header.setSectionResizeMode(2, QHeaderView.ResizeToContents)
header.setSectionResizeMode(0, QHeaderView.ResizeMode.Stretch)
header.setSectionResizeMode(1, QHeaderView.ResizeMode.ResizeToContents)
header.setSectionResizeMode(2, QHeaderView.ResizeMode.ResizeToContents)
# signals
@ -824,11 +824,11 @@ class DiffTree(FileTreeModel[DiffData]):
if role == Qt.ItemDataRole.ForegroundRole:
# colour
if item.data.change_type == ChangeType.ADDED:
return QColor(Qt.green) if uses_dark_mode() else QColor(Qt.darkGreen)
return QColor(Qt.GlobalColor.green) if uses_dark_mode() else QColor(Qt.GlobalColor.darkGreen)
if item.data.change_type == ChangeType.MODIFIED:
return QColor(Qt.yellow) if uses_dark_mode() else QColor(Qt.darkYellow)
return QColor(Qt.GlobalColor.yellow) if uses_dark_mode() else QColor(Qt.GlobalColor.darkYellow)
if item.data.change_type == ChangeType.REMOVED:
return QColor(Qt.red) if uses_dark_mode() else QColor(Qt.darkRed)
return QColor(Qt.GlobalColor.red) if uses_dark_mode() else QColor(Qt.GlobalColor.darkRed)
return None # no change
if role == Qt.ItemDataRole.ToolTipRole:

View File

@ -1,8 +1,9 @@
import logging
import os
from pathlib import Path
from PyQt5 import uic
from PyQt5.QtWidgets import QFileDialog, QMessageBox
from PyQt6 import uic
from PyQt6.QtCore import Qt
from PyQt6.QtWidgets import QFileDialog, QMessageBox
from vorta.keyring.abc import VortaKeyring
from vorta.store.models import BackupProfileModel # noqa: F401
from vorta.utils import get_asset
@ -31,7 +32,7 @@ class ExportWindow(ExportWindowBase, ExportWindowUI):
self.keyring = VortaKeyring.get_keyring()
profile = self.profile
if profile.repo is None or self.keyring.get_password('vorta-repo', profile.repo.url) is None:
self.storePassword.setCheckState(False)
self.storePassword.setCheckState(Qt.CheckState(False))
self.storePassword.setDisabled(True)
self.storePassword.setToolTip(self.tr('Disclose your borg passphrase (No passphrase set)'))

View File

@ -4,11 +4,11 @@ import logging
from dataclasses import dataclass
from datetime import datetime
from pathlib import PurePath
from typing import Optional
from PyQt5 import uic
from PyQt5.QtCore import QDateTime, QLocale, QMimeData, QModelIndex, QPoint, Qt, QThread, QUrl
from PyQt5.QtGui import QColor, QKeySequence
from PyQt5.QtWidgets import QApplication, QDialogButtonBox, QHeaderView, QMenu, QPushButton, QShortcut
from typing import Optional, Union
from PyQt6 import uic
from PyQt6.QtCore import QDateTime, QLocale, QMimeData, QModelIndex, QPoint, Qt, QThread, QUrl
from PyQt6.QtGui import QColor, QKeySequence, QShortcut
from PyQt6.QtWidgets import QApplication, QDialogButtonBox, QHeaderView, QMenu, QPushButton
from vorta.store.models import SettingsModel
from vorta.utils import borg_compat, get_asset, pretty_bytes, uses_dark_mode
from vorta.views.utils import get_colored_icon
@ -72,10 +72,10 @@ class ExtractDialog(ExtractDialogBase, ExtractDialogUI):
# header
header = view.header()
header.setStretchLastSection(False)
header.setSectionResizeMode(1, QHeaderView.ResizeToContents)
header.setSectionResizeMode(2, QHeaderView.ResizeToContents)
header.setSectionResizeMode(3, QHeaderView.ResizeToContents)
header.setSectionResizeMode(0, QHeaderView.Stretch)
header.setSectionResizeMode(1, QHeaderView.ResizeMode.ResizeToContents)
header.setSectionResizeMode(2, QHeaderView.ResizeMode.ResizeToContents)
header.setSectionResizeMode(3, QHeaderView.ResizeMode.ResizeToContents)
header.setSectionResizeMode(0, QHeaderView.ResizeMode.Stretch)
# shortcuts
shortcut_copy = QShortcut(QKeySequence.StandardKey.Copy, self.treeView)
@ -281,7 +281,7 @@ class FileData:
last_modified: QDateTime
source_path: Optional[str] = None # only relevant for links
checkstate: int = 0 # whether to extract the file (0, 1 or 2)
checkstate: Qt.CheckState = Qt.CheckState.Unchecked # whether to extract the file (0, 1 or 2)
checked_children: int = 0 # number of children checked
@ -378,7 +378,7 @@ class ExtractTree(FileTreeModel[FileData]):
self,
section: int,
orientation: Qt.Orientation,
role: int = Qt.ItemDataRole.DisplayRole,
role: Union[int, Qt.ItemDataRole] = Qt.ItemDataRole.DisplayRole,
):
"""
Get the data for the given role and section in the given header.
@ -414,7 +414,7 @@ class ExtractTree(FileTreeModel[FileData]):
return None
def data(self, index: QModelIndex, role: int = Qt.ItemDataRole.DisplayRole):
def data(self, index: QModelIndex, role: Union[int, Qt.ItemDataRole] = Qt.ItemDataRole.DisplayRole):
"""
Get the data for the given role and index.
@ -467,9 +467,9 @@ class ExtractTree(FileTreeModel[FileData]):
if role == Qt.ItemDataRole.BackgroundRole and column == 3:
# health indicator
if item.data.health:
return QColor(Qt.green) if uses_dark_mode() else QColor(Qt.darkGreen)
return QColor(Qt.GlobalColor.green) if uses_dark_mode() else QColor(Qt.GlobalColor.darkGreen)
else:
return QColor(Qt.green) if uses_dark_mode() else QColor(Qt.darkGreen)
return QColor(Qt.GlobalColor.green) if uses_dark_mode() else QColor(Qt.GlobalColor.darkGreen)
if role == Qt.ItemDataRole.ToolTipRole:
if column == 0:
@ -532,7 +532,12 @@ class ExtractTree(FileTreeModel[FileData]):
if role == Qt.ItemDataRole.CheckStateRole and column == 0:
return item.data.checkstate
def setData(self, index: QModelIndex, value, role: int = Qt.ItemDataRole.DisplayRole) -> bool:
def setData(
self,
index: QModelIndex,
value: Union[int, Qt.CheckState],
role: Union[int, Qt.ItemDataRole] = Qt.ItemDataRole.CheckStateRole,
) -> bool:
"""
Sets the role data for the item at index to value.
@ -543,6 +548,13 @@ class ExtractTree(FileTreeModel[FileData]):
if role != Qt.ItemDataRole.CheckStateRole:
return False
# convert int to enum member
# PyQt6 will pass Ints where there were IntEnums in PyQt5
if isinstance(value, int):
value = Qt.CheckState(value)
if isinstance(role, int):
role = Qt.ItemDataRole(role)
item: ExtractFileItem = index.internalPointer()
if value == item.data.checkstate:
@ -616,7 +628,7 @@ class ExtractTree(FileTreeModel[FileData]):
item = index.internalPointer()
for i in range(number_children):
child = index.child(i, 0)
child = self.index(i, 0, index)
child_item: ExtractFileItem = child.internalPointer()
child_item.data.checkstate = value
@ -633,8 +645,8 @@ class ExtractTree(FileTreeModel[FileData]):
self.set_checkstate_recursively(child, value)
self.dataChanged.emit(
index.child(0, 0),
index.child(0, number_children - 1),
self.index(0, 0, index),
self.index(0, number_children - 1, index),
(Qt.ItemDataRole.CheckStateRole,),
)

View File

@ -1,5 +1,5 @@
from PyQt5 import QtCore
from PyQt5.QtWidgets import QMessageBox
from PyQt6 import QtCore
from PyQt6.QtWidgets import QMessageBox
from vorta.keyring.abc import VortaKeyring
from vorta.profile_export import VersionException
from vorta.store.connection import SCHEMA_VERSION

View File

@ -1,9 +1,9 @@
import logging
from pathlib import Path
from PyQt5 import QtCore, uic
from PyQt5.QtCore import QPoint
from PyQt5.QtGui import QFontMetrics, QKeySequence
from PyQt5.QtWidgets import QApplication, QCheckBox, QFileDialog, QMenu, QMessageBox, QShortcut, QToolTip
from PyQt6 import QtCore, uic
from PyQt6.QtCore import QPoint
from PyQt6.QtGui import QFontMetrics, QKeySequence, QShortcut
from PyQt6.QtWidgets import QApplication, QCheckBox, QFileDialog, QMenu, QMessageBox, QToolTip
from vorta.profile_export import ImportFailedException, ProfileExport
from vorta.store.models import BackupProfileModel, SettingsModel
from vorta.utils import borg_compat, get_asset, get_network_status_monitor, is_system_tray_available
@ -31,7 +31,7 @@ class MainWindow(MainWindowBase, MainWindowUI):
self.setWindowTitle('Vorta for Borg Backup')
self.app = parent
self.setWindowIcon(get_colored_icon("icon"))
self.setWindowFlags(QtCore.Qt.WindowCloseButtonHint | QtCore.Qt.WindowMinimizeButtonHint)
self.setWindowFlags(QtCore.Qt.WindowType.WindowCloseButtonHint | QtCore.Qt.WindowType.WindowMinimizeButtonHint)
self.createStartBtn = LoadingButton(self.tr("Start Backup"))
self.gridLayout.addWidget(self.createStartBtn, 0, 0, 1, 1)
self.createStartBtn.setGif(get_asset("icons/loading"))
@ -156,7 +156,7 @@ class MainWindow(MainWindowBase, MainWindowUI):
def profile_rename_action(self):
window = EditProfileWindow(rename_existing_id=self.profileSelector.currentData())
self.window = window # For tests
window.setParent(self, QtCore.Qt.Sheet)
window.setParent(self, QtCore.Qt.WindowType.Sheet)
window.open()
window.profile_changed.connect(self.profile_add_edit_result)
window.rejected.connect(lambda: self.profileSelector.setCurrentIndex(self.profileSelector.currentIndex()))
@ -171,11 +171,11 @@ class MainWindow(MainWindowBase, MainWindowUI):
self,
self.tr("Confirm deletion"),
msg,
QMessageBox.Yes | QMessageBox.No,
QMessageBox.No,
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
QMessageBox.StandardButton.No,
)
if reply == QMessageBox.Yes:
if reply == QMessageBox.StandardButton.Yes:
to_delete.delete_instance(recursive=True)
self.app.scheduler.remove_job(to_delete_id) # Remove pending jobs
self.profileSelector.removeItem(self.profileSelector.currentIndex())
@ -189,7 +189,7 @@ class MainWindow(MainWindowBase, MainWindowUI):
def profile_add_action(self):
window = AddProfileWindow()
self.window = window # For tests
window.setParent(self, QtCore.Qt.Sheet)
window.setParent(self, QtCore.Qt.WindowType.Sheet)
window.open()
window.profile_changed.connect(self.profile_add_edit_result)
window.rejected.connect(lambda: self.profileSelector.setCurrentIndex(self.profileSelector.currentIndex()))
@ -201,7 +201,7 @@ class MainWindow(MainWindowBase, MainWindowUI):
"""
window = ExportWindow(profile=self.current_profile.refresh())
self.window = window
window.setParent(self, QtCore.Qt.Sheet)
window.setParent(self, QtCore.Qt.WindowType.Sheet)
window.show()
def profile_import_action(self):
@ -236,7 +236,7 @@ class MainWindow(MainWindowBase, MainWindowUI):
return
window = ImportWindow(profile_export=profile_export)
self.window = window
window.setParent(self, QtCore.Qt.Sheet)
window.setParent(self, QtCore.Qt.WindowType.Sheet)
window.profile_imported.connect(profile_imported_event)
window.show()
@ -280,13 +280,13 @@ class MainWindow(MainWindowBase, MainWindowUI):
if not is_system_tray_available():
if SettingsModel.get(key="enable_background_question").value:
msg = QMessageBox()
msg.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
msg.setParent(self, QtCore.Qt.Sheet)
msg.setStandardButtons(QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No)
msg.setParent(self, QtCore.Qt.WindowType.Sheet)
msg.setText(self.tr("Should Vorta continue to run in the background?"))
msg.button(QMessageBox.Yes).clicked.connect(
msg.button(QMessageBox.StandardButton.Yes).clicked.connect(
lambda: self.miscTab.save_setting("disable_background_state", True)
)
msg.button(QMessageBox.No).clicked.connect(
msg.button(QMessageBox.StandardButton.No).clicked.connect(
lambda: (
self.miscTab.save_setting("disable_background_state", False),
self.app.quit(),

View File

@ -1,7 +1,7 @@
import logging
from PyQt5 import uic
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication, QCheckBox, QFormLayout, QHBoxLayout, QLabel, QSizePolicy, QSpacerItem
from PyQt6 import uic
from PyQt6.QtCore import Qt
from PyQt6.QtWidgets import QApplication, QCheckBox, QFormLayout, QHBoxLayout, QLabel, QSizePolicy, QSpacerItem
from vorta._version import __version__
from vorta.config import LOG_DIR
from vorta.i18n import translate
@ -87,7 +87,7 @@ class MiscTab(MiscTabBase, MiscTabUI, BackupProfileMixin):
# create widget
cb = QCheckBox(translate('settings', setting.label))
cb.setToolTip(setting.tooltip)
cb.setCheckState(setting.value)
cb.setCheckState(Qt.CheckState(setting.value))
cb.setTristate(False)
cb.stateChanged.connect(lambda v, key=setting.key: self.save_setting(key, v))

View File

@ -2,7 +2,7 @@
Adapted from https://stackoverflow.com/questions/53618971/how-to-make-a-qpushbutton-a-loading-button
"""
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt6 import QtCore, QtGui, QtWidgets
class LoadingButton(QtWidgets.QPushButton):

View File

@ -1,7 +1,7 @@
from typing import Optional
from PyQt5.QtCore import QCoreApplication, QEvent, QSize, Qt
from PyQt5.QtGui import QHelpEvent, QIcon, QMouseEvent, QPaintEvent
from PyQt5.QtWidgets import QSizePolicy, QStyle, QStylePainter, QToolTip, QWidget
from PyQt6.QtCore import QCoreApplication, QEvent, QSize, Qt
from PyQt6.QtGui import QHelpEvent, QIcon, QMouseEvent, QPaintEvent
from PyQt6.QtWidgets import QSizePolicy, QStyle, QStylePainter, QToolTip, QWidget
class ToolTipButton(QWidget):
@ -24,7 +24,7 @@ class ToolTipButton(QWidget):
"""
super().__init__(parent)
self.setCursor(Qt.CursorShape.WhatsThisCursor)
self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
self.setSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed)
self.setMouseTracking(True)
self._icon = icon or QIcon()
@ -98,8 +98,10 @@ class ToolTipButton(QWidget):
https://doc.qt.io/qt-5/qwidget.html#mouseMoveEvent
"""
super().mouseMoveEvent(event)
QToolTip.showText(event.globalPos(), self.toolTip(), self)
QCoreApplication.postEvent(self, QHelpEvent(QEvent.Type.ToolTip, event.pos(), event.globalPos()))
QToolTip.showText(event.globalPosition().toPoint(), self.toolTip(), self)
QCoreApplication.postEvent(
self, QHelpEvent(QEvent.Type.ToolTip, event.position().toPoint(), event.globalPosition().toPoint())
)
def setIcon(self, icon: QIcon):
"""

View File

@ -9,7 +9,7 @@ import os.path as osp
from functools import reduce
from pathlib import PurePath
from typing import Generic, List, Optional, Sequence, Tuple, TypeVar, Union, overload
from PyQt5.QtCore import QAbstractItemModel, QModelIndex, QObject, QSortFilterProxyModel, Qt, pyqtSignal
from PyQt6.QtCore import QAbstractItemModel, QModelIndex, QObject, QSortFilterProxyModel, Qt, pyqtSignal
#: A representation of a path
Path = Tuple[str, ...]
@ -837,7 +837,7 @@ class FileTreeModel(QAbstractItemModel, Generic[T]):
row, item = parent_item._parent.get(parent_item.subpath)
return self.createIndex(row, 0, parent_item)
def flags(self, index: QModelIndex) -> Qt.ItemFlags:
def flags(self, index: QModelIndex) -> Qt.ItemFlag:
"""
Returns the item flags for the given index.

View File

@ -1,5 +1,5 @@
from PyQt5 import QtCore, uic
from PyQt5.QtWidgets import QDialogButtonBox
from PyQt6 import QtCore, uic
from PyQt6.QtWidgets import QDialogButtonBox
from vorta.i18n import trans_late, translate
from vorta.store.models import BackupProfileModel
from vorta.utils import get_asset
@ -14,20 +14,20 @@ class AddProfileWindow(AddProfileBase, AddProfileUI):
def __init__(self, parent=None):
super().__init__(parent)
self.setupUi(self)
self.setAttribute(QtCore.Qt.WA_DeleteOnClose)
self.setAttribute(QtCore.Qt.WidgetAttribute.WA_DeleteOnClose)
self.edited_profile = None
self.buttonBox.rejected.connect(self.close)
self.buttonBox.accepted.connect(self.save)
self.profileNameField.textChanged.connect(self.button_validation)
self.buttonBox.button(QDialogButtonBox.Save).setText(self.tr("Save"))
self.buttonBox.button(QDialogButtonBox.Cancel).setText(self.tr("Cancel"))
self.buttonBox.button(QDialogButtonBox.StandardButton.Save).setText(self.tr("Save"))
self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel).setText(self.tr("Cancel"))
self.name_blank = trans_late('AddProfileWindow', 'Please enter a profile name.')
self.name_exists = trans_late('AddProfileWindow', 'A profile with this name already exists.')
# Call validate to set inital messages
self.buttonBox.button(QDialogButtonBox.Save).setEnabled(self.validate())
self.buttonBox.button(QDialogButtonBox.StandardButton.Save).setEnabled(self.validate())
def _set_status(self, text):
self.errorText.setText(text)
@ -40,7 +40,7 @@ class AddProfileWindow(AddProfileBase, AddProfileUI):
self.accept()
def button_validation(self):
self.buttonBox.button(QDialogButtonBox.Save).setEnabled(self.validate())
self.buttonBox.button(QDialogButtonBox.StandardButton.Save).setEnabled(self.validate())
def validate(self):
name = self.profileNameField.text()

View File

@ -1,6 +1,7 @@
import re
from PyQt5 import QtCore, uic
from PyQt5.QtWidgets import QAction, QApplication, QDialogButtonBox, QLineEdit
from PyQt6 import QtCore, uic
from PyQt6.QtGui import QAction
from PyQt6.QtWidgets import QApplication, QDialogButtonBox, QLineEdit
from vorta.borg.info_repo import BorgInfoRepoJob
from vorta.borg.init import BorgInitJob
from vorta.i18n import translate
@ -19,7 +20,7 @@ class AddRepoWindow(AddRepoBase, AddRepoUI):
def __init__(self, parent=None):
super().__init__(parent)
self.setupUi(self)
self.setAttribute(QtCore.Qt.WA_DeleteOnClose)
self.setAttribute(QtCore.Qt.WidgetAttribute.WA_DeleteOnClose)
self.result = None
self.is_remote_repo = True
@ -41,7 +42,7 @@ class AddRepoWindow(AddRepoBase, AddRepoUI):
self.showHideAction.setCheckable(True)
self.showHideAction.toggled.connect(self.set_visibility)
self.passwordLineEdit.addAction(self.showHideAction, QLineEdit.TrailingPosition)
self.passwordLineEdit.addAction(self.showHideAction, QLineEdit.ActionPosition.TrailingPosition)
self.tabWidget.setCurrentIndex(0)
@ -103,7 +104,7 @@ class AddRepoWindow(AddRepoBase, AddRepoUI):
self.confirmLineEdit.setText(password)
def set_visibility(self, visible):
visibility = QLineEdit.Normal if visible else QLineEdit.Password
visibility = QLineEdit.EchoMode.Normal if visible else QLineEdit.EchoMode.Password
self.passwordLineEdit.setEchoMode(visibility)
self.confirmLineEdit.setEchoMode(visibility)
@ -224,7 +225,7 @@ class ExistingRepoWindow(AddRepoWindow):
del self.confirmLabel
def set_visibility(self, visible):
visibility = QLineEdit.Normal if visible else QLineEdit.Password
visibility = QLineEdit.EchoMode.Normal if visible else QLineEdit.EchoMode.Password
self.passwordLineEdit.setEchoMode(visibility)
if visible:

View File

@ -1,8 +1,8 @@
import os
from pathlib import PurePath
from PyQt5 import QtCore, uic
from PyQt5.QtCore import QMimeData, QUrl
from PyQt5.QtWidgets import QApplication, QLayout, QMenu, QMessageBox
from PyQt6 import QtCore, uic
from PyQt6.QtCore import QMimeData, QUrl
from PyQt6.QtWidgets import QApplication, QLayout, QMenu, QMessageBox
from vorta.store.models import ArchiveModel, BackupProfileMixin, RepoModel
from vorta.utils import borg_compat, get_asset, get_private_keys, pretty_bytes
from .repo_add_dialog import AddRepoWindow, ExistingRepoWindow
@ -192,15 +192,15 @@ class RepoTab(RepoBase, RepoUI, BackupProfileMixin):
"""Open a dialog to create an ssh key."""
ssh_add_window = SSHAddWindow()
self._window = ssh_add_window # For tests
ssh_add_window.setParent(self, QtCore.Qt.Sheet)
ssh_add_window.setParent(self, QtCore.Qt.WindowType.Sheet)
ssh_add_window.accepted.connect(self.init_ssh)
# ssh_add_window.rejected.connect(lambda: self.sshComboBox.setCurrentIndex(0))
ssh_add_window.open()
def ssh_copy_to_clipboard_action(self):
msg = QMessageBox()
msg.setStandardButtons(QMessageBox.Ok)
msg.setParent(self, QtCore.Qt.Sheet)
msg.setStandardButtons(QMessageBox.StandardButton.Ok)
msg.setParent(self, QtCore.Qt.WindowType.Sheet)
index = self.sshComboBox.currentIndex()
if index > 0:
@ -234,7 +234,7 @@ class RepoTab(RepoBase, RepoUI, BackupProfileMixin):
"""Open a dialog to create a new repo and add it to vorta."""
window = AddRepoWindow()
self._window = window # For tests
window.setParent(self, QtCore.Qt.Sheet)
window.setParent(self, QtCore.Qt.WindowType.Sheet)
window.added_repo.connect(self.process_new_repo)
# window.rejected.connect(lambda: self.repoSelector.setCurrentIndex(0))
window.open()
@ -243,7 +243,7 @@ class RepoTab(RepoBase, RepoUI, BackupProfileMixin):
"""Open a dialog to add a existing repo to vorta."""
window = ExistingRepoWindow()
self._window = window # For tests
window.setParent(self, QtCore.Qt.Sheet)
window.setParent(self, QtCore.Qt.WindowType.Sheet)
window.added_repo.connect(self.process_new_repo)
# window.rejected.connect(lambda: self.repoSelector.setCurrentIndex(0))
window.open()
@ -271,8 +271,8 @@ class RepoTab(RepoBase, RepoUI, BackupProfileMixin):
self.init_repo_stats()
msg = QMessageBox()
msg.setStandardButtons(QMessageBox.Ok)
msg.setParent(self, QtCore.Qt.Sheet)
msg.setStandardButtons(QMessageBox.StandardButton.Ok)
msg.setParent(self, QtCore.Qt.WindowType.Sheet)
selected_repo_id = self.repoSelector.currentData()
selected_repo_index = self.repoSelector.currentIndex()

View File

@ -1,6 +1,6 @@
from PyQt5 import QtCore, uic
from PyQt5.QtCore import QDateTime, QLocale
from PyQt5.QtWidgets import QApplication, QHeaderView, QListWidgetItem, QTableView, QTableWidgetItem
from PyQt6 import QtCore, uic
from PyQt6.QtCore import QDateTime, QLocale
from PyQt6.QtWidgets import QAbstractItemView, QApplication, QHeaderView, QListWidgetItem, QTableWidgetItem
from vorta import application
from vorta.i18n import get_locale
from vorta.scheduler import ScheduleStatusType
@ -37,10 +37,10 @@ class ScheduleTab(ScheduleBase, ScheduleUI, BackupProfileMixin):
self.logTableWidget.setAlternatingRowColors(True)
header = self.logTableWidget.horizontalHeader()
header.setVisible(True)
[header.setSectionResizeMode(i, QHeaderView.ResizeToContents) for i in range(5)]
header.setSectionResizeMode(3, QHeaderView.Stretch)
self.logTableWidget.setSelectionBehavior(QTableView.SelectRows)
self.logTableWidget.setEditTriggers(QTableView.NoEditTriggers)
[header.setSectionResizeMode(i, QHeaderView.ResizeMode.ResizeToContents) for i in range(5)]
header.setSectionResizeMode(3, QHeaderView.ResizeMode.Stretch)
self.logTableWidget.setSelectionBehavior(QAbstractItemView.SelectionBehavior.SelectRows)
self.logTableWidget.setEditTriggers(QAbstractItemView.EditTrigger.NoEditTriggers)
# Scheduler intervals we know
self.scheduleIntervalUnit.addItem(self.tr('Minutes'), 'minutes')
@ -138,17 +138,19 @@ class ScheduleTab(ScheduleBase, ScheduleUI, BackupProfileMixin):
self.scheduleFixedTime.setTime(QtCore.QTime(profile.schedule_fixed_hour, profile.schedule_fixed_minute))
# Set borg-check options
self.validationCheckBox.setCheckState(QtCore.Qt.Checked if profile.validation_on else QtCore.Qt.Unchecked)
self.validationCheckBox.setCheckState(
QtCore.Qt.CheckState.Checked if profile.validation_on else QtCore.Qt.CheckState.Unchecked
)
self.validationWeeksCount.setValue(profile.validation_weeks)
# Other checkbox options
self.pruneCheckBox.setCheckState(QtCore.Qt.Checked if profile.prune_on else QtCore.Qt.Unchecked)
self.pruneCheckBox.setCheckState(
QtCore.Qt.CheckState.Checked if profile.prune_on else QtCore.Qt.CheckState.Unchecked
)
self.missedBackupsCheckBox.setCheckState(
QtCore.Qt.Checked if profile.schedule_make_up_missed else QtCore.Qt.Unchecked
)
self.meteredNetworksCheckBox.setChecked(
QtCore.Qt.Unchecked if profile.dont_run_on_metered_networks else QtCore.Qt.Checked
QtCore.Qt.CheckState.Checked if profile.schedule_make_up_missed else QtCore.Qt.CheckState.Unchecked
)
self.meteredNetworksCheckBox.setChecked(False if profile.dont_run_on_metered_networks else True)
self.preBackupCmdLineEdit.setText(profile.pre_backup_cmd)
self.postBackupCmdLineEdit.setText(profile.post_backup_cmd)
@ -183,11 +185,11 @@ class ScheduleTab(ScheduleBase, ScheduleUI, BackupProfileMixin):
for wifi in get_sorted_wifis(self.profile()):
item = QListWidgetItem()
item.setText(wifi.ssid)
item.setFlags(item.flags() | QtCore.Qt.ItemIsUserCheckable)
item.setFlags(item.flags() | QtCore.Qt.ItemFlag.ItemIsUserCheckable)
if wifi.allowed:
item.setCheckState(QtCore.Qt.Checked)
item.setCheckState(QtCore.Qt.CheckState.Checked)
else:
item.setCheckState(QtCore.Qt.Unchecked)
item.setCheckState(QtCore.Qt.CheckState.Unchecked)
self.wifiListWidget.addItem(item)
self.wifiListWidget.itemChanged.connect(self.save_wifi_item)

View File

@ -1,9 +1,10 @@
import logging
import os
from pathlib import PurePath
from PyQt5 import QtCore, QtGui, uic
from PyQt5.QtCore import QFileInfo, QMimeData, QPoint, Qt, QUrl, pyqtSlot
from PyQt5.QtWidgets import QApplication, QHeaderView, QMenu, QMessageBox, QShortcut, QTableWidgetItem
from PyQt6 import QtCore, QtGui, uic
from PyQt6.QtCore import QFileInfo, QMimeData, QPoint, Qt, QUrl, pyqtSlot
from PyQt6.QtGui import QShortcut
from PyQt6.QtWidgets import QApplication, QHeaderView, QMenu, QMessageBox, QTableWidgetItem
from vorta.store.models import BackupProfileMixin, SettingsModel, SourceFileModel
from vorta.utils import FilePathInfoAsync, choose_file_dialog, get_asset, pretty_bytes, sort_sizes
from vorta.views.utils import get_colored_icon
@ -23,7 +24,7 @@ class SourceColumn:
class SizeItem(QTableWidgetItem):
def __init__(self, s):
super().__init__(s)
self.setTextAlignment(Qt.AlignVCenter + Qt.AlignRight)
self.setTextAlignment(Qt.AlignmentFlag.AlignVCenter + Qt.AlignmentFlag.AlignRight)
def __lt__(self, other):
if other.text() == '':
@ -63,9 +64,9 @@ class SourceTab(SourceBase, SourceUI, BackupProfileMixin):
header.setVisible(True)
header.setSortIndicatorShown(1)
header.setSectionResizeMode(SourceColumn.Path, QHeaderView.Stretch)
header.setSectionResizeMode(SourceColumn.Size, QHeaderView.ResizeToContents)
header.setSectionResizeMode(SourceColumn.FilesCount, QHeaderView.ResizeToContents)
header.setSectionResizeMode(SourceColumn.Path, QHeaderView.ResizeMode.Stretch)
header.setSectionResizeMode(SourceColumn.Size, QHeaderView.ResizeMode.ResizeToContents)
header.setSectionResizeMode(SourceColumn.FilesCount, QHeaderView.ResizeMode.ResizeToContents)
self.sourceFilesWidget.setSortingEnabled(True)
self.sourceFilesWidget.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)
@ -139,7 +140,7 @@ class SourceTab(SourceBase, SourceUI, BackupProfileMixin):
sorting = self.sourceFilesWidget.isSortingEnabled()
self.sourceFilesWidget.setSortingEnabled(False)
items = self.sourceFilesWidget.findItems(path, QtCore.Qt.MatchExactly)
items = self.sourceFilesWidget.findItems(path, QtCore.Qt.MatchFlag.MatchExactly)
# Conversion int->str->int needed because QT limits int to 32-bit
data_size = int(data_size)
files_count = int(files_count)
@ -250,7 +251,7 @@ class SourceTab(SourceBase, SourceUI, BackupProfileMixin):
sourcetab_sort_order = int(SettingsModel.get(key='sourcetab_sort_order').str_value)
# Sort items as per settings
self.sourceFilesWidget.sortItems(sourcetab_sort_column, sourcetab_sort_order)
self.sourceFilesWidget.sortItems(sourcetab_sort_column, Qt.SortOrder(sourcetab_sort_order))
self.excludePatternsField.appendPlainText(profile.exclude_patterns)
self.excludeIfPresentField.appendPlainText(profile.exclude_if_present)
@ -262,7 +263,7 @@ class SourceTab(SourceBase, SourceUI, BackupProfileMixin):
SettingsModel.update({SettingsModel.str_value: str(column)}).where(
SettingsModel.key == 'sourcetab_sort_column'
).execute()
SettingsModel.update({SettingsModel.str_value: str(order)}).where(
SettingsModel.update({SettingsModel.str_value: str(order.value)}).where(
SettingsModel.key == 'sourcetab_sort_order'
).execute()

View File

@ -1,7 +1,7 @@
import os
from PyQt5 import uic
from PyQt5.QtCore import QProcess, Qt
from PyQt5.QtWidgets import QApplication, QDialogButtonBox
from PyQt6 import uic
from PyQt6.QtCore import QProcess, Qt
from PyQt6.QtWidgets import QApplication, QDialogButtonBox
from ..utils import get_asset
uifile = get_asset('UI/sshadd.ui')
@ -12,7 +12,7 @@ class SSHAddWindow(SSHAddBase, SSHAddUI):
def __init__(self):
super().__init__()
self.setupUi(self)
self.setAttribute(Qt.WA_DeleteOnClose)
self.setAttribute(Qt.WidgetAttribute.WA_DeleteOnClose)
# dialogButtonBox
self.generateButton = self.buttonBox.button(QDialogButtonBox.StandardButton.Ok)

View File

@ -1,4 +1,4 @@
from PyQt5.QtGui import QIcon, QImage, QPixmap
from PyQt6.QtGui import QIcon, QImage, QPixmap
from vorta.utils import get_asset, uses_dark_mode

View File

@ -46,6 +46,12 @@ def qapp(tmpdir_factory):
mock_db = SqliteDatabase(str(tmp_db))
vorta.store.connection.init_db(mock_db)
# Needs to be disabled before calling VortaApp()
if sys.platform == 'darwin':
cfg = vorta.store.models.SettingsModel.get(key='check_full_disk_access')
cfg.value = False
cfg.save()
from vorta.application import VortaApp
VortaApp.set_borg_details_action = MagicMock() # Can't use pytest-mock in session scope

View File

@ -1,7 +1,7 @@
from collections import namedtuple
import psutil
import pytest
from PyQt5 import QtCore
from PyQt6 import QtCore
import vorta.borg
import vorta.utils
import vorta.views.archive_tab
@ -58,7 +58,7 @@ def test_repo_prune(qapp, qtbot, mocker, borg_json_output):
popen_result = mocker.MagicMock(stdout=stdout, stderr=stderr, returncode=0)
mocker.patch.object(vorta.borg.borg_job, 'Popen', return_value=popen_result)
qtbot.mouseClick(tab.bPrune, QtCore.Qt.LeftButton)
qtbot.mouseClick(tab.bPrune, QtCore.Qt.MouseButton.LeftButton)
qtbot.waitUntil(lambda: 'Refreshing archives done.' in main.progressText.text(), **pytest._wait_defaults)
@ -73,7 +73,7 @@ def test_repo_compact(qapp, qtbot, mocker, borg_json_output):
popen_result = mocker.MagicMock(stdout=stdout, stderr=stderr, returncode=0)
mocker.patch.object(vorta.borg.borg_job, 'Popen', return_value=popen_result)
qtbot.mouseClick(tab.compactButton, QtCore.Qt.LeftButton)
qtbot.mouseClick(tab.compactButton, QtCore.Qt.MouseButton.LeftButton)
qtbot.waitUntil(
lambda: 'compaction freed about 56.00 kB repository space' in main.logText.text(), **pytest._wait_defaults
@ -91,7 +91,7 @@ def test_check(qapp, mocker, borg_json_output, qtbot):
popen_result = mocker.MagicMock(stdout=stdout, stderr=stderr, returncode=0)
mocker.patch.object(vorta.borg.borg_job, 'Popen', return_value=popen_result)
qtbot.mouseClick(tab.bCheck, QtCore.Qt.LeftButton)
qtbot.mouseClick(tab.bCheck, QtCore.Qt.MouseButton.LeftButton)
success_text = 'INFO: Archive consistency check complete'
qtbot.waitUntil(lambda: success_text in main.logText.text(), **pytest._wait_defaults)

View File

@ -1,6 +1,6 @@
from pathlib import PurePath
import pytest
from PyQt5.QtCore import QDateTime, QItemSelectionModel, Qt
from PyQt6.QtCore import QDateTime, QItemSelectionModel, Qt
import vorta.borg
import vorta.utils
import vorta.views.archive_tab

View File

@ -1,4 +1,4 @@
from PyQt5.QtCore import QModelIndex, Qt
from PyQt6.QtCore import QModelIndex, Qt
import vorta.borg
from vorta.views.extract_dialog import ExtractTree, FileData, FileType, parse_json_lines
from vorta.views.partials.treemodel import FileSystemItem
@ -92,12 +92,12 @@ def test_selection():
c: FileSystemItem[FileData] = ic.internalPointer()
select(model, ic)
assert c.data.checkstate == 2
assert c.data.checkstate == Qt.CheckState(2)
assert c.data.checked_children == 0
# Test deselect
deselect(model, ic)
assert c.data.checkstate == 0
assert c.data.checkstate == Qt.CheckState(0)
assert c.data.checked_children == 0
# Test select parent as well as children
@ -121,19 +121,19 @@ def test_selection():
iab = model.indexPath(("a", "b"))
deselect(model, iab)
assert a.data.checkstate == 1
assert aa.data.checkstate == 2
assert ab.data.checkstate == 0
assert abc.data.checkstate == 0
assert a.data.checkstate == Qt.CheckState(1)
assert aa.data.checkstate == Qt.CheckState(2)
assert ab.data.checkstate == Qt.CheckState(0)
assert abc.data.checkstate == Qt.CheckState(0)
assert a.data.checked_children == 1
assert ab.data.checked_children == 0
# Test deselect item and children
deselect(model, ia)
assert a.data.checkstate == 0
assert aa.data.checkstate == 0
assert ab.data.checkstate == 0
assert a.data.checkstate == Qt.CheckState(0)
assert aa.data.checkstate == Qt.CheckState(0)
assert ab.data.checkstate == Qt.CheckState(0)
assert a.data.checked_children == 0
assert aa.data.checked_children == 0
@ -146,9 +146,9 @@ def test_selection():
select(model, iab)
select(model, iaac)
assert a.data.checkstate == 1
assert aa.data.checkstate == 1
assert ab.data.checkstate == 2
assert a.data.checkstate == Qt.CheckState(1)
assert aa.data.checkstate == Qt.CheckState(1)
assert ab.data.checkstate == Qt.CheckState(2)
assert a.data.checked_children == 2
assert ab.data.checked_children == 2
@ -159,21 +159,21 @@ def test_selection():
deselect(model, iaa)
deselect(model, iab)
assert a.data.checkstate == 0
assert a.data.checkstate == Qt.CheckState(0)
assert a.data.checked_children == 0
# Test select child with deselected parent
select(model, iaac)
assert a.data.checkstate == 1
assert ab.data.checkstate == 0
assert aa.data.checkstate == 1
assert a.data.checkstate == Qt.CheckState(1)
assert ab.data.checkstate == Qt.CheckState(0)
assert aa.data.checkstate == Qt.CheckState(1)
assert a.data.checked_children == 1
assert ab.data.checked_children == 0
assert aa.data.checked_children == 1
select(model, iaa)
assert a.data.checkstate == 1
assert a.data.checkstate == Qt.CheckState(1)
select(model, iab)
assert a.data.checkstate == 1
assert a.data.checkstate == Qt.CheckState(1)

View File

@ -1,8 +1,8 @@
import os
from pathlib import Path
import pytest
from PyQt5 import QtCore
from PyQt5.QtWidgets import QDialogButtonBox, QFileDialog, QMessageBox
from PyQt6 import QtCore
from PyQt6.QtWidgets import QDialogButtonBox, QFileDialog, QMessageBox
from vorta.store.models import BackupProfileModel, SourceFileModel
from vorta.views.import_window import ImportWindow
@ -18,7 +18,9 @@ def test_import_success(qapp, qtbot, rootdir, monkeypatch):
import_dialog: ImportWindow = main.window
import_dialog.overwriteExistingSettings.setChecked(True)
qtbot.mouseClick(import_dialog.buttonBox.button(QDialogButtonBox.Ok), QtCore.Qt.LeftButton)
qtbot.mouseClick(
import_dialog.buttonBox.button(QDialogButtonBox.StandardButton.Ok), QtCore.Qt.MouseButton.LeftButton
)
qtbot.waitSignal(import_dialog.profile_imported, **pytest._wait_defaults)
restored_profile = BackupProfileModel.get_or_none(name="Test Profile Restoration")
@ -81,7 +83,9 @@ def test_export_success(qapp, qtbot, tmpdir, monkeypatch):
main.profile_export_action()
export_dialog = main.window
qtbot.mouseClick(export_dialog.buttonBox.button(QDialogButtonBox.Save), QtCore.Qt.LeftButton)
qtbot.mouseClick(
export_dialog.buttonBox.button(QDialogButtonBox.StandardButton.Save), QtCore.Qt.MouseButton.LeftButton
)
qtbot.waitUntil(lambda: os.path.isfile(FILE_PATH))
assert os.path.isfile(FILE_PATH)
@ -107,7 +111,9 @@ def test_export_fail_unwritable(qapp, qtbot, tmpdir, monkeypatch):
main.profile_export_action()
export_dialog = main.window
qtbot.mouseClick(export_dialog.buttonBox.button(QDialogButtonBox.Save), QtCore.Qt.LeftButton)
qtbot.mouseClick(
export_dialog.buttonBox.button(QDialogButtonBox.StandardButton.Save), QtCore.Qt.MouseButton.LeftButton
)
assert 'could not be created' in alert_message
assert not os.path.isfile(FILE_PATH)

View File

@ -1,5 +1,5 @@
import pytest
from PyQt5 import QtCore
from PyQt6 import QtCore
import vorta.application
import vorta.borg.borg_job
@ -12,7 +12,7 @@ def test_create_perm_error(qapp, borg_json_output, mocker, qtbot):
popen_result = mocker.MagicMock(stdout=stdout, stderr=stderr, returncode=0)
mocker.patch.object(vorta.borg.borg_job, 'Popen', return_value=popen_result)
qtbot.mouseClick(main.createStartBtn, QtCore.Qt.LeftButton)
qtbot.mouseClick(main.createStartBtn, QtCore.Qt.MouseButton.LeftButton)
qtbot.waitUntil(lambda: hasattr(qapp, '_msg'), **pytest._wait_defaults)
assert qapp._msg.text().startswith("You do not have permission")
@ -28,7 +28,7 @@ def test_create_lock(qapp, borg_json_output, mocker, qtbot):
popen_result = mocker.MagicMock(stdout=stdout, stderr=stderr, returncode=0)
mocker.patch.object(vorta.borg.borg_job, 'Popen', return_value=popen_result)
qtbot.mouseClick(main.createStartBtn, QtCore.Qt.LeftButton)
qtbot.mouseClick(main.createStartBtn, QtCore.Qt.MouseButton.LeftButton)
qtbot.waitUntil(lambda: hasattr(qapp, '_msg'), **pytest._wait_defaults)
assert "The repository at" in qapp._msg.text()

View File

@ -3,8 +3,8 @@ import sys
from pathlib import Path
from unittest.mock import Mock
import pytest
from PyQt5 import QtCore
from PyQt5.QtWidgets import QCheckBox, QFormLayout
from PyQt6 import QtCore
from PyQt6.QtWidgets import QCheckBox, QFormLayout
import vorta.store.models
@ -79,5 +79,7 @@ def _click_toggle_setting(setting, qapp, qtbot):
if checkbox.text() == setting:
# Have to use pos to click checkbox correctly
# https://stackoverflow.com/questions/19418125/pysides-qtest-not-checking-box/24070484#24070484
qtbot.mouseClick(checkbox, QtCore.Qt.LeftButton, pos=QtCore.QPoint(2, int(checkbox.height() / 2)))
qtbot.mouseClick(
checkbox, QtCore.Qt.MouseButton.LeftButton, pos=QtCore.QPoint(2, int(checkbox.height() / 2))
)
break

View File

@ -1,6 +1,6 @@
import sys
import pytest
from PyQt5 import QtDBus
from PyQt6 import QtDBus
import vorta.borg
import vorta.notifications

View File

@ -1,17 +1,19 @@
from PyQt5 import QtCore
from PyQt5.QtWidgets import QDialogButtonBox
from PyQt6 import QtCore
from PyQt6.QtWidgets import QDialogButtonBox
from vorta.store.models import BackupProfileModel
def test_profile_add(qapp, qtbot):
main = qapp.main_window
qtbot.mouseClick(main.profileAddButton, QtCore.Qt.LeftButton)
qtbot.mouseClick(main.profileAddButton, QtCore.Qt.MouseButton.LeftButton)
add_profile_window = main.window
qtbot.addWidget(add_profile_window)
# qtbot.addWidget(add_profile_window)
qtbot.keyClicks(add_profile_window.profileNameField, 'Test Profile')
qtbot.mouseClick(add_profile_window.buttonBox.button(QDialogButtonBox.Save), QtCore.Qt.LeftButton)
qtbot.mouseClick(
add_profile_window.buttonBox.button(QDialogButtonBox.StandardButton.Save), QtCore.Qt.MouseButton.LeftButton
)
assert BackupProfileModel.get_or_none(name='Test Profile') is not None
assert main.profileSelector.currentText() == 'Test Profile'
@ -19,14 +21,16 @@ def test_profile_add(qapp, qtbot):
def test_profile_edit(qapp, qtbot):
main = qapp.main_window
qtbot.mouseClick(main.profileRenameButton, QtCore.Qt.LeftButton)
qtbot.mouseClick(main.profileRenameButton, QtCore.Qt.MouseButton.LeftButton)
edit_profile_window = main.window
qtbot.addWidget(edit_profile_window)
# qtbot.addWidget(edit_profile_window)
edit_profile_window.profileNameField.setText("")
qtbot.keyClicks(edit_profile_window.profileNameField, 'Test Profile')
qtbot.mouseClick(edit_profile_window.buttonBox.button(QDialogButtonBox.Save), QtCore.Qt.LeftButton)
qtbot.mouseClick(
edit_profile_window.buttonBox.button(QDialogButtonBox.StandardButton.Save), QtCore.Qt.MouseButton.LeftButton
)
assert BackupProfileModel.get_or_none(name='Default') is None
assert BackupProfileModel.get_or_none(name='Test Profile') is not None

View File

@ -1,7 +1,8 @@
import os
import uuid
import pytest
from PyQt5 import QtCore
from PyQt6 import QtCore
from PyQt6.QtWidgets import QMessageBox
import vorta.borg.borg_job
from vorta.keyring.abc import VortaKeyring
from vorta.store.models import ArchiveModel, EventLogModel, RepoModel
@ -20,7 +21,7 @@ def test_repo_add_failures(qapp, qtbot, mocker, borg_json_output):
qtbot.keyClicks(add_repo_window.passwordLineEdit, LONG_PASSWORD)
qtbot.keyClicks(add_repo_window.confirmLineEdit, LONG_PASSWORD)
qtbot.keyClicks(add_repo_window.repoURL, 'aaa')
qtbot.mouseClick(add_repo_window.saveButton, QtCore.Qt.LeftButton)
qtbot.mouseClick(add_repo_window.saveButton, QtCore.Qt.MouseButton.LeftButton)
assert add_repo_window.errorText.text().startswith('Please enter a valid')
add_repo_window.passwordLineEdit.clear()
@ -28,34 +29,35 @@ def test_repo_add_failures(qapp, qtbot, mocker, borg_json_output):
qtbot.keyClicks(add_repo_window.passwordLineEdit, SHORT_PASSWORD)
qtbot.keyClicks(add_repo_window.confirmLineEdit, SHORT_PASSWORD)
qtbot.keyClicks(add_repo_window.repoURL, 'bbb.com:repo')
qtbot.mouseClick(add_repo_window.saveButton, QtCore.Qt.LeftButton)
qtbot.mouseClick(add_repo_window.saveButton, QtCore.Qt.MouseButton.LeftButton)
assert add_repo_window.passwordLabel.text() == 'Passwords must be greater than 8 characters long.'
add_repo_window.passwordLineEdit.clear()
add_repo_window.confirmLineEdit.clear()
qtbot.keyClicks(add_repo_window.passwordLineEdit, SHORT_PASSWORD + "1")
qtbot.keyClicks(add_repo_window.confirmLineEdit, SHORT_PASSWORD)
qtbot.mouseClick(add_repo_window.saveButton, QtCore.Qt.LeftButton)
qtbot.mouseClick(add_repo_window.saveButton, QtCore.Qt.MouseButton.LeftButton)
assert add_repo_window.passwordLabel.text() == 'Passwords must be identical and greater than 8 characters long.'
add_repo_window.passwordLineEdit.clear()
add_repo_window.confirmLineEdit.clear()
qtbot.keyClicks(add_repo_window.passwordLineEdit, LONG_PASSWORD)
qtbot.keyClicks(add_repo_window.confirmLineEdit, SHORT_PASSWORD)
qtbot.mouseClick(add_repo_window.saveButton, QtCore.Qt.LeftButton)
qtbot.mouseClick(add_repo_window.saveButton, QtCore.Qt.MouseButton.LeftButton)
assert add_repo_window.passwordLabel.text() == 'Passwords must be identical.'
def test_repo_unlink(qapp, qtbot):
def test_repo_unlink(qapp, qtbot, monkeypatch):
main = qapp.main_window
tab = main.repoTab
monkeypatch.setattr(QMessageBox, "show", lambda *args: True)
main.tabWidget.setCurrentIndex(0)
qtbot.mouseClick(tab.repoRemoveToolbutton, QtCore.Qt.LeftButton)
qtbot.mouseClick(tab.repoRemoveToolbutton, QtCore.Qt.MouseButton.LeftButton)
qtbot.waitUntil(lambda: tab.repoSelector.count() == 1, **pytest._wait_defaults)
assert RepoModel.select().count() == 0
qtbot.mouseClick(main.createStartBtn, QtCore.Qt.LeftButton)
qtbot.mouseClick(main.createStartBtn, QtCore.Qt.MouseButton.LeftButton)
# -1 is the repo id in this test
qtbot.waitUntil(lambda: 'Select a backup repository first.' in main.progressText.text(), **pytest._wait_defaults)
assert 'Select a backup repository first.' in main.progressText.text()
@ -105,7 +107,7 @@ def test_repo_add_success(qapp, qtbot, mocker, borg_json_output):
def test_ssh_dialog(qapp, qtbot, tmpdir):
main = qapp.main_window
qtbot.mouseClick(main.repoTab.bAddSSHKey, QtCore.Qt.LeftButton)
qtbot.mouseClick(main.repoTab.bAddSSHKey, QtCore.Qt.MouseButton.LeftButton)
ssh_dialog = main.repoTab._window
ssh_dir = tmpdir
@ -135,7 +137,7 @@ def test_create(qapp, borg_json_output, mocker, qtbot):
popen_result = mocker.MagicMock(stdout=stdout, stderr=stderr, returncode=0)
mocker.patch.object(vorta.borg.borg_job, 'Popen', return_value=popen_result)
qtbot.mouseClick(main.createStartBtn, QtCore.Qt.LeftButton)
qtbot.mouseClick(main.createStartBtn, QtCore.Qt.MouseButton.LeftButton)
qtbot.waitUntil(lambda: 'Backup finished.' in main.progressText.text(), **pytest._wait_defaults)
qtbot.waitUntil(lambda: main.createStartBtn.isEnabled(), **pytest._wait_defaults)
assert EventLogModel.select().count() == 1

View File

@ -2,7 +2,7 @@ from datetime import datetime as dt
from datetime import timedelta
from unittest.mock import MagicMock
import pytest
from PyQt5 import QtCore
from PyQt6 import QtCore
import vorta.scheduler
from vorta.application import VortaApp
from vorta.store.models import BackupProfileModel, EventLogModel
@ -31,17 +31,17 @@ def test_schedule_tab(qapp: VortaApp, qtbot, clockmock):
qapp.scheduler.schedule_changed.connect(lambda *args: tab.draw_next_scheduled_backup())
# Test
qtbot.mouseClick(tab.scheduleOffRadio, QtCore.Qt.LeftButton)
qtbot.mouseClick(tab.scheduleOffRadio, QtCore.Qt.MouseButton.LeftButton)
assert tab.nextBackupDateTimeLabel.text() == 'None scheduled'
tab.scheduleIntervalCount.setValue(5)
qtbot.mouseClick(tab.scheduleIntervalRadio, QtCore.Qt.LeftButton)
qtbot.mouseClick(tab.scheduleIntervalRadio, QtCore.Qt.MouseButton.LeftButton)
assert "None" not in tab.nextBackupDateTimeLabel.text()
tab.scheduleFixedTime.setTime(QtCore.QTime(23, 59))
# Clicking currently broken for this button on github.com only
# qtbot.mouseClick(tab.scheduleFixedRadio, QtCore.Qt.LeftButton)
# qtbot.mouseClick(tab.scheduleFixedRadio, QtCore.Qt.MouseButton.LeftButton)
# Workaround for github
tab.scheduleFixedRadio.setChecked(True)

View File

@ -1,6 +1,6 @@
from pathlib import PurePath
import pytest
from PyQt5.QtCore import QModelIndex
from PyQt6.QtCore import QModelIndex
from vorta.views.partials.treemodel import FileSystemItem, FileTreeModel