mirror of https://github.com/borgbase/vorta
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:
parent
8571ef6cb8
commit
7535f92ac8
|
@ -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: |
|
||||
|
|
|
@ -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)
|
||||
|
|
10
setup.cfg
10
setup.cfg
|
@ -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]
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -1 +1 @@
|
|||
__version__ = '0.8.11'
|
||||
__version__ = '0.9.0'
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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__)
|
||||
|
||||
|
|
|
@ -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__)
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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__)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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)'))
|
||||
|
||||
|
|
|
@ -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,),
|
||||
)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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))
|
||||
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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):
|
||||
"""
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import sys
|
||||
import pytest
|
||||
from PyQt5 import QtDBus
|
||||
from PyQt6 import QtDBus
|
||||
import vorta.borg
|
||||
import vorta.notifications
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue