diff --git a/Makefile b/Makefile
index 164a11e0..4cc1e0bd 100644
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,8 @@ VERSION := $(shell cat version)
PYTHON ?= python3
-LRELEASE_QT5 ?= $(if $(wildcard /etc/debian_version),lrelease,lrelease-qt5)
+LRELEASE_QT6 ?= $(if $(wildcard /etc/debian_version),lrelease,lrelease-qt6)
+RCC ?= /usr/lib64/qt6/libexec/rcc
SETUPTOOLS_OPTS =
SETUPTOOLS_OPTS += $(if $(wildcard /etc/debian_version),--install-layout=deb,)
@@ -11,17 +12,17 @@ export QT_HASH_SEED=0
export PYTHONHASHSEED=0
qubesmanager/ui_%.py: ui/%.ui
- pyuic5 --from-imports -o $@ $<
+ pyuic6 -o $@ $<
touch --reference=$< $@
ui: $(patsubst ui/%.ui,qubesmanager/ui_%.py,$(wildcard ui/*.ui))
res:
- pyrcc5 -o qubesmanager/resources_rc.py resources.qrc
+ $(RCC) -g python resources.qrc | sed '0,/PySide6/s//PyQt6/' > qubesmanager/resources_rc.py
touch --reference=resources.qrc qubesmanager/resources_rc.py
translations:
- $(LRELEASE_QT5) qubesmanager.pro
+ $(LRELEASE_QT6) qubesmanager.pro
python:
$(PYTHON) ./setup.py build
@@ -30,7 +31,7 @@ python_install:
$(PYTHON) ./setup.py install -O1 --skip-build --root $(DESTDIR) $(SETUPTOOLS_OPTS)
update_ts: res
- pylupdate5 qubesmanager.pro
+ pylupdate6 qubesmanager.pro
install:
mkdir -p $(DESTDIR)/usr/libexec/qubes-manager/
diff --git a/qubesmanager/about.py b/qubesmanager/about.py
index 1f8d9fd1..8dfde976 100644
--- a/qubesmanager/about.py
+++ b/qubesmanager/about.py
@@ -20,8 +20,8 @@
# with this program; if not, see .
#
#
-from PyQt5.QtWidgets import QDialog # pylint: disable=import-error
-from PyQt5.QtGui import QIcon # pylint: disable=import-error
+from PyQt6.QtWidgets import QDialog # pylint: disable=import-error
+from PyQt6.QtGui import QIcon # pylint: disable=import-error
from qubesmanager.releasenotes import ReleaseNotesDialog
from qubesmanager.informationnotes import InformationNotesDialog
@@ -60,8 +60,8 @@ def __init__(self, parent=None):
def on_release_notes_clicked(self):
release_notes_dialog = ReleaseNotesDialog(self)
- release_notes_dialog.exec_()
+ release_notes_dialog.exec()
def on_information_notes_clicked(self):
information_notes_dialog = InformationNotesDialog(self)
- information_notes_dialog.exec_()
+ information_notes_dialog.exec()
diff --git a/qubesmanager/appmenu_select.py b/qubesmanager/appmenu_select.py
index 74bf648c..1c1c5d9b 100755
--- a/qubesmanager/appmenu_select.py
+++ b/qubesmanager/appmenu_select.py
@@ -20,7 +20,7 @@
#
import subprocess
-from PyQt5 import QtWidgets, QtCore # pylint: disable=import-error
+from PyQt6 import QtWidgets, QtCore # pylint: disable=import-error
from qubesadmin import exc
# TODO description in tooltip
diff --git a/qubesmanager/backup.py b/qubesmanager/backup.py
index d35c24be..04b61ee7 100644
--- a/qubesmanager/backup.py
+++ b/qubesmanager/backup.py
@@ -24,12 +24,12 @@
from qubesadmin import exc
from qubesadmin import utils as admin_utils
-from PyQt5 import QtCore, QtWidgets, QtGui, Qt # pylint: disable=import-error
-from . import ui_backupdlg # pylint: disable=no-name-in-module
-from . import multiselectwidget
+from PyQt6 import QtCore, QtWidgets, QtGui # pylint: disable=import-error
+from qubesmanager import ui_backupdlg # pylint: disable=no-name-in-module
+from qubesmanager import multiselectwidget
-from . import backup_utils
-from . import utils
+from qubesmanager import backup_utils
+from qubesmanager import utils
import grp
import pwd
@@ -81,8 +81,8 @@ def __init__(self, qt_app, qubes_app, dispatcher, parent=None):
self.setupUi(self)
self.setWindowFlags(self.windowFlags() |
- Qt.Qt.WindowMaximizeButtonHint |
- Qt.Qt.WindowMinimizeButtonHint)
+ QtCore.Qt.WindowType.WindowMaximizeButtonHint |
+ QtCore.Qt.WindowType.WindowMinimizeButtonHint)
self.progress_status.text = self.tr("Backup in progress...")
self.dir_line_edit.setReadOnly(False)
@@ -146,10 +146,12 @@ def __init__(self, qt_app, qubes_app, dispatcher, parent=None):
def show_hide_password(self):
if self.show_passwd_button.isChecked():
- self.passphrase_line_edit.setEchoMode(QtWidgets.QLineEdit.Password)
+ self.passphrase_line_edit.setEchoMode(
+ QtWidgets.QLineEdit.EchoMode.Password)
self.show_passwd_button.setIcon(QtGui.QIcon(':/eye-off.svg'))
else:
- self.passphrase_line_edit.setEchoMode(QtWidgets.QLineEdit.Normal)
+ self.passphrase_line_edit.setEchoMode(
+ QtWidgets.QLineEdit.EchoMode.Normal)
self.show_passwd_button.setIcon(QtGui.QIcon(':/eye.svg'))
def save_profile_changed(self):
@@ -376,7 +378,7 @@ def current_page_changed(self, page_id): # pylint: disable=unused-argument
self.save_settings(use_temp=False,
save_passphrase=save_passphrase)
- self.button(self.FinishButton).setDisabled(True)
+ self.button(self.WizardButton.FinishButton).setDisabled(True)
self.showFileDialog.setEnabled(
self.appvm_combobox.currentIndex() != 0)
self.showFileDialog.setChecked(self.showFileDialog.isEnabled()
@@ -399,8 +401,8 @@ def backup_finished(self):
self, self.tr("Backup error"),
self.tr("ERROR: {}").format(
self.thread.msg))
- self.button(self.CancelButton).setEnabled(False)
- self.button(self.FinishButton).setEnabled(True)
+ self.button(self.WizardButton.CancelButton).setEnabled(False)
+ self.button(self.WizardButton.FinishButton).setEnabled(True)
self.cleanup_temporary_files()
else:
@@ -415,8 +417,8 @@ def backup_finished(self):
"the file selection dialog."))
backup_utils.select_path_button_clicked(self, False, True)
- self.button(self.CancelButton).setEnabled(False)
- self.button(self.FinishButton).setEnabled(True)
+ self.button(self.WizardButton.CancelButton).setEnabled(False)
+ self.button(self.WizardButton.FinishButton).setEnabled(True)
self.showFileDialog.setEnabled(False)
self.cleanup_temporary_files()
@@ -426,7 +428,7 @@ def backup_finished(self):
def reject(self):
if (self.currentPage() is self.commit_page) and \
- self.button(self.CancelButton).isEnabled():
+ self.button(self.WizardButton.CancelButton).isEnabled():
try:
self.qubes_app.qubesd_call(
'dom0', 'admin.backup.Cancel',
diff --git a/qubesmanager/backup_utils.py b/qubesmanager/backup_utils.py
index 1e41d1d7..e72ff013 100644
--- a/qubesmanager/backup_utils.py
+++ b/qubesmanager/backup_utils.py
@@ -21,7 +21,7 @@
import re
import socket
-from PyQt5 import QtWidgets # pylint: disable=import-error
+from PyQt6 import QtWidgets # pylint: disable=import-error
import subprocess
from . import utils
diff --git a/qubesmanager/bootfromdevice.py b/qubesmanager/bootfromdevice.py
index f0502f2b..474b609a 100644
--- a/qubesmanager/bootfromdevice.py
+++ b/qubesmanager/bootfromdevice.py
@@ -21,7 +21,7 @@
import subprocess
from . import utils
from . import ui_bootfromdevice # pylint: disable=no-name-in-module
-from PyQt5 import QtWidgets, QtGui, Qt # pylint: disable=import-error
+from PyQt6 import QtWidgets, QtGui, QtCore # pylint: disable=import-error
from qubesadmin import tools
from qubesadmin import exc
from qubesadmin.tools import qvm_start
@@ -42,8 +42,8 @@ def __init__(self, vm, qapp, qubesapp=None, parent=None, new_vm=False):
self.setWindowTitle(
self.tr("Boot {vm} from device").format(vm=self.vm))
self.setWindowFlags(self.windowFlags() |
- Qt.Qt.WindowMaximizeButtonHint |
- Qt.Qt.WindowMinimizeButtonHint)
+ QtCore.Qt.WindowType.WindowMaximizeButtonHint |
+ QtCore.Qt.WindowType.WindowMinimizeButtonHint)
self.buttonBox.accepted.connect(self.save_and_apply)
self.buttonBox.rejected.connect(self.reject)
diff --git a/qubesmanager/clipboard.py b/qubesmanager/clipboard.py
index 8bf8f1eb..8c81671e 100644
--- a/qubesmanager/clipboard.py
+++ b/qubesmanager/clipboard.py
@@ -26,8 +26,8 @@
from math import log
# pylint: disable=import-error
-from PyQt5.QtWidgets import QApplication, QMessageBox
-from PyQt5.QtCore import QCoreApplication
+from PyQt6.QtWidgets import QApplication, QMessageBox
+from PyQt6.QtCore import QCoreApplication
APPVIEWER_LOCK = "/var/run/qubes/appviewer.lock"
CLIPBOARD_CONTENTS = "/var/run/qubes/qubes-clipboard.bin"
diff --git a/qubesmanager/clone_vm.py b/qubesmanager/clone_vm.py
index 5b55b3e5..e0392743 100644
--- a/qubesmanager/clone_vm.py
+++ b/qubesmanager/clone_vm.py
@@ -24,7 +24,7 @@
import sys
import subprocess
-from PyQt5 import QtCore, QtWidgets, QtGui # pylint: disable=import-error
+from PyQt6 import QtCore, QtWidgets, QtGui # pylint: disable=import-error
import qubesadmin
import qubesadmin.tools
@@ -183,4 +183,4 @@ def main(args=None):
"appname", 'Clone qube'))
dialog = CloneVMDlg(qtapp, args.app, src_vm=src_vm)
- dialog.exec_()
+ dialog.exec()
diff --git a/qubesmanager/common_threads.py b/qubesmanager/common_threads.py
index d3a0ebcf..a95163cb 100644
--- a/qubesmanager/common_threads.py
+++ b/qubesmanager/common_threads.py
@@ -20,7 +20,7 @@
#
-from PyQt5 import QtCore, QtWidgets # pylint: disable=import-error
+from PyQt6 import QtCore, QtWidgets # pylint: disable=import-error
from contextlib import contextmanager
from qubesadmin import exc
@@ -29,7 +29,8 @@
@contextmanager
def busy_cursor():
try:
- QtWidgets.QApplication.setOverrideCursor(QtCore.Qt.BusyCursor)
+ QtWidgets.QApplication.setOverrideCursor(
+ QtCore.Qt.CursorShape.BusyCursor)
yield
finally:
QtWidgets.QApplication.restoreOverrideCursor()
diff --git a/qubesmanager/create_new_vm.py b/qubesmanager/create_new_vm.py
index e8038146..32e6c29e 100644
--- a/qubesmanager/create_new_vm.py
+++ b/qubesmanager/create_new_vm.py
@@ -25,7 +25,7 @@
import sys
import subprocess
-from PyQt5 import QtCore, QtWidgets, QtGui # pylint: disable=import-error
+from PyQt6 import QtCore, QtWidgets, QtGui # pylint: disable=import-error
import qubesadmin
import qubesadmin.tools
@@ -145,8 +145,11 @@ def __init__(self, qtapp, app, parent=None):
self.storage_pool.clear()
self.storage_pool.addItem("(default)", qubesadmin.DEFAULT)
- self.name.setValidator(QtGui.QRegExpValidator(
- QtCore.QRegExp("[a-zA-Z0-9_-]*", QtCore.Qt.CaseInsensitive), None))
+ self.name.setValidator(QtGui.QRegularExpressionValidator(
+ QtCore.QRegularExpression(
+ "[a-zA-Z0-9_-]*",
+ QtCore.QRegularExpression.PatternOption.CaseInsensitiveOption),
+ None))
self.name.selectAll()
self.name.setFocus()
@@ -182,7 +185,7 @@ def accept(self):
if self.install_system.isChecked():
self.boot_dialog = bootfromdevice.VMBootFromDeviceWindow(
name, self.qtapp, self.app, self, True)
- if not self.boot_dialog.exec_():
+ if not self.boot_dialog.exec():
return
if name in self.app.domains:
@@ -336,4 +339,4 @@ def main(args=None):
"appname", 'Create qube'))
dialog = NewVmDlg(qtapp, args.app)
- dialog.exec_()
+ dialog.exec()
diff --git a/qubesmanager/device_list.py b/qubesmanager/device_list.py
index c32fd249..aacc1013 100644
--- a/qubesmanager/device_list.py
+++ b/qubesmanager/device_list.py
@@ -18,7 +18,7 @@
#
from . import ui_devicelist # pylint: disable=no-name-in-module
-from PyQt5 import QtWidgets # pylint: disable=import-error
+from PyQt6 import QtWidgets # pylint: disable=import-error
class PCIDeviceListWindow(ui_devicelist.Ui_Dialog, QtWidgets.QDialog):
diff --git a/qubesmanager/firewall.py b/qubesmanager/firewall.py
index 4564504d..93193944 100644
--- a/qubesmanager/firewall.py
+++ b/qubesmanager/firewall.py
@@ -21,7 +21,7 @@
import datetime
import re
-from PyQt5 import QtCore, QtGui, QtWidgets # pylint: disable=import-error
+from PyQt6 import QtCore, QtGui, QtWidgets # pylint: disable=import-error
import qubesadmin.firewall
from . import ui_newfwruledlg # pylint: disable=no-name-in-module
@@ -39,13 +39,17 @@ def __init__(self, parent=None):
self.set_ok_state(False)
self.addressComboBox.editTextChanged.connect(
self.address_editing_finished)
- self.serviceComboBox.setValidator(QtGui.QRegExpValidator(
- QtCore.QRegExp("[a-z][a-z0-9-]+|[0-9]+(-[0-9]+)?",
- QtCore.Qt.CaseInsensitive), None))
+ self.serviceComboBox.setValidator(QtGui.QRegularExpressionValidator(
+ QtCore.QRegularExpression(
+ "[a-z][a-z0-9-]+|[0-9]+(-[0-9]+)?",
+ QtCore.QRegularExpression.PatternOption.CaseInsensitiveOption),
+ None))
self.serviceComboBox.setEnabled(False)
- self.serviceComboBox.setInsertPolicy(QtWidgets.QComboBox.InsertAtBottom)
+ self.serviceComboBox.setInsertPolicy(
+ QtWidgets.QComboBox.InsertPolicy.InsertAtBottom)
self.populate_combos()
- self.serviceComboBox.setInsertPolicy(QtWidgets.QComboBox.InsertAtTop)
+ self.serviceComboBox.setInsertPolicy(
+ QtWidgets.QComboBox.InsertPolicy.InsertAtTop)
self.model = None
@@ -142,7 +146,8 @@ def address_editing_finished(self):
self.set_ok_state(True)
def set_ok_state(self, ok_state):
- ok_button = self.buttonBox.button(QtWidgets.QDialogButtonBox.Ok)
+ ok_button = self.buttonBox.button(
+ QtWidgets.QDialogButtonBox.StandardButton.Ok)
if ok_button is not None:
ok_button.setEnabled(ok_state)
@@ -190,7 +195,7 @@ def __init__(self, parent=None):
self.__children = None # list of rules in the FW
def sort(self, idx, order):
- rev = order == QtCore.Qt.AscendingOrder
+ rev = order == QtCore.Qt.SortOrder.AscendingOrder
self.children.sort(key=lambda x: self.get_column_string(idx, x),
reverse=rev)
@@ -413,16 +418,17 @@ def hasChildren(self, index=QtCore.QModelIndex()):
parent_item = index.internalPointer()
return parent_item is None
- def data(self, index, role=QtCore.Qt.DisplayRole):
- if index.isValid() and role == QtCore.Qt.DisplayRole:
+ def data(self, index, role=QtCore.Qt.ItemDataRole.DisplayRole):
+ if index.isValid() and role == QtCore.Qt.ItemDataRole.DisplayRole:
return self.get_column_string(index.column(),
self.children[index.row()])
# pylint: disable=invalid-name
- def headerData(self, section, orientation, role=QtCore.Qt.DisplayRole):
+ def headerData(self, section, orientation,
+ role=QtCore.Qt.ItemDataRole.DisplayRole):
if section < len(self.__column_names) \
- and orientation == QtCore.Qt.Horizontal \
- and role == QtCore.Qt.DisplayRole:
+ and orientation == QtCore.Qt.Orientation.Horizontal \
+ and role == QtCore.Qt.ItemDataRole.DisplayRole:
return self.__column_names[section]
@property
diff --git a/qubesmanager/informationnotes.py b/qubesmanager/informationnotes.py
index 755be5b7..70e21abb 100644
--- a/qubesmanager/informationnotes.py
+++ b/qubesmanager/informationnotes.py
@@ -20,7 +20,7 @@
# with this program; if not, see .
#
#
-from PyQt5.QtWidgets import QDialog # pylint: disable=import-error
+from PyQt6.QtWidgets import QDialog # pylint: disable=import-error
from . import ui_informationnotes # pylint: disable=no-name-in-module
import subprocess
diff --git a/qubesmanager/log_dialog.py b/qubesmanager/log_dialog.py
index d5ac0031..d62bbe6a 100644
--- a/qubesmanager/log_dialog.py
+++ b/qubesmanager/log_dialog.py
@@ -22,7 +22,7 @@
import sys
import os
from functools import partial
-from PyQt5 import QtWidgets, Qt # pylint: disable=import-error
+from PyQt6 import QtWidgets, QtCore # pylint: disable=import-error
from qubesadmin import Qubes
from . import ui_logdlg # pylint: disable=no-name-in-module
from . import clipboard
@@ -43,8 +43,8 @@ def __init__(self, app, logfiles, parent=None):
self.setupUi(self)
self.setWindowFlags(self.windowFlags() |
- Qt.Qt.WindowMaximizeButtonHint |
- Qt.Qt.WindowMinimizeButtonHint)
+ QtCore.Qt.WindowType.WindowMaximizeButtonHint |
+ QtCore.Qt.WindowType.WindowMinimizeButtonHint)
self.copy_to_qubes_clipboard.clicked.connect(
self.copy_to_clipboard_triggered)
@@ -89,7 +89,7 @@ def main():
log_window = LogDialog(qubes_app, sys.argv[1:])
log_window.show()
- qt_app.exec_()
+ qt_app.exec()
qt_app.exit()
diff --git a/qubesmanager/multiselectwidget.py b/qubesmanager/multiselectwidget.py
index 534d8a9f..90ac7fff 100644
--- a/qubesmanager/multiselectwidget.py
+++ b/qubesmanager/multiselectwidget.py
@@ -1,4 +1,4 @@
-from PyQt5 import QtCore, QtWidgets # pylint: disable=import-error
+from PyQt6 import QtCore, QtWidgets # pylint: disable=import-error
from . import ui_multiselectwidget # pylint: disable=no-name-in-module
@@ -17,9 +17,9 @@ def __init__(self, parent=None):
self.remove_selected_button.clicked.connect(self.remove_selected)
self.remove_all_button.clicked.connect(self.remove_all)
self.available_list.setSelectionMode(
- QtWidgets.QAbstractItemView.ExtendedSelection)
+ QtWidgets.QAbstractItemView.SelectionMode.ExtendedSelection)
self.selected_list.setSelectionMode(
- QtWidgets.QAbstractItemView.ExtendedSelection)
+ QtWidgets.QAbstractItemView.SelectionMode.ExtendedSelection)
def switch_selected(self, src, dst):
selected = src.selectedItems()
diff --git a/qubesmanager/qube_manager.py b/qubesmanager/qube_manager.py
index 608ccad6..32da5f16 100644
--- a/qubesmanager/qube_manager.py
+++ b/qubesmanager/qube_manager.py
@@ -33,17 +33,18 @@
from qubesadmin.tools import qvm_start
# pylint: disable=import-error
-from PyQt5.QtCore import (Qt, QAbstractTableModel, QObject, pyqtSlot, QEvent,
- QSettings, QRegExp, QSortFilterProxyModel, QSize, QPoint, QTimer)
+from PyQt6.QtCore import (Qt, QAbstractTableModel, QObject, pyqtSlot, QEvent,
+ QSettings, QRegularExpression, QSortFilterProxyModel,
+ QSize, QPoint, QTimer)
# pylint: disable=import-error
-from PyQt5.QtWidgets import (QLineEdit, QStyledItemDelegate, QToolTip,
- QMenu, QInputDialog, QMainWindow, QProgressDialog, QStyleOptionViewItem,
- QMessageBox, QShortcut)
+from PyQt6.QtWidgets import (QLineEdit, QStyledItemDelegate, QToolTip,
+ QMenu, QInputDialog, QMainWindow, QProgressDialog,
+ QStyleOptionViewItem, QMessageBox)
# pylint: disable=import-error
-from PyQt5.QtGui import (QIcon, QPixmap, QRegExpValidator, QFont, QColor,
- QKeySequence)
+from PyQt6.QtGui import (QIcon, QPixmap, QRegularExpressionValidator, QFont,
+ QColor, QShortcut, QKeySequence)
from qubesmanager.about import AboutDialog
@@ -116,12 +117,12 @@ def __init__(self):
def sizeHint(self, option, index):
hint = super().sizeHint(option, index)
option = QStyleOptionViewItem(option)
- option.features |= option.HasDecoration
+ option.features |= option.ViewItemFeature.HasDecoration
widget = option.widget
style = widget.style()
- iconRect = style.subElementRect(style.SE_ItemViewItemDecoration,
- option, widget)
- width = iconRect.width() * 3 # Nº of possible icons
+ iconRect = style.subElementRect(
+ style.SubElement.SE_ItemViewItemDecoration, option, widget)
+ width = iconRect.width() * 3 # Nº of possible icons
hint.setWidth(width)
return hint
@@ -133,13 +134,14 @@ def paint(self, qp, option, index):
style = widget.style()
# paint the base item (borders, gradients, selection colors, etc)
- style.drawControl(style.CE_ItemViewItem, option, qp, widget)
+ style.drawControl(style.ControlElement.CE_ItemViewItem,
+ option, qp, widget)
# "lie" about the decoration, to get a valid icon rectangle (even if we
# don't have any "real" icon set for the item)
- option.features |= option.HasDecoration
- iconRect = style.subElementRect(style.SE_ItemViewItemDecoration,
- option, widget)
+ option.features |= option.ViewItemFeature.HasDecoration
+ iconRect = style.subElementRect(
+ style.SubElement.SE_ItemViewItemDecoration, option, widget)
iconSize = iconRect.size()
margin = iconRect.left() - option.rect.left()
@@ -162,16 +164,16 @@ def paint(self, qp, option, index):
qp.restore()
def helpEvent(self, event, view, option, index):
- if event.type() != QEvent.ToolTip:
+ if event.type() != QEvent.Type.ToolTip:
return super().helpEvent(event, view,
option, index)
option = QStyleOptionViewItem(option)
widget = option.widget
style = widget.style()
- option.features |= option.HasDecoration
+ option.features |= option.ViewItemFeature.HasDecoration
- iconRect = style.subElementRect(style.SE_ItemViewItemDecoration,
- option, widget)
+ iconRect = style.subElementRect(
+ style.SubElement.SE_ItemViewItemDecoration, option, widget)
iconRect.setTop(option.rect.y())
iconRect.setHeight(option.rect.height())
@@ -405,7 +407,7 @@ def data(self, index, role):
col_name = self.columns_indices[col]
vm = self.qubes_cache.get_vm(row)
- if role == Qt.DisplayRole:
+ if role == Qt.ItemDataRole.DisplayRole:
if col in [0, 1]:
return None
if col_name == "Name":
@@ -432,7 +434,7 @@ def data(self, index, role):
return "Yes" if vm.dvm_template else ""
if col_name == "Virt Mode":
return vm.virt_mode
- if role == Qt.DecorationRole:
+ if role == Qt.ItemDataRole.DecorationRole:
if col_name == "Type":
try:
return self.klass_pixmap[vm.klass]
@@ -453,24 +455,25 @@ def data(self, index, role):
icon = QIcon.fromTheme(vm.icon)
self.label_pixmap[vm.icon] = icon.pixmap(icon_size)
return self.label_pixmap[vm.icon]
- if role == Qt.CheckStateRole:
+ if role == Qt.ItemDataRole.CheckStateRole:
if col_name == "Backup":
- return Qt.Checked if vm.inc_backup else Qt.Unchecked
- if role == Qt.FontRole:
+ return Qt.CheckState.Checked if vm.inc_backup else (
+ Qt.CheckState.Unchecked)
+ if role == Qt.ItemDataRole.FontRole:
if col_name == "Template":
if vm.template is None:
font = QFont()
font.setItalic(True)
return font
- if role == Qt.ForegroundRole:
+ if role == Qt.ItemDataRole.ForegroundRole:
if col_name == "Template":
if vm.template is None:
return QColor("gray")
# Used for get VM Object
- if role == Qt.UserRole:
+ if role == Qt.ItemDataRole.UserRole:
return vm
# Used for sorting
- if role == Qt.UserRole + 1:
+ if role == Qt.ItemDataRole.UserRole + 1:
if vm.klass == 'AdminVM':
return ""
if col_name == "Type":
@@ -500,36 +503,37 @@ def data(self, index, role):
if col_name == "Backup":
# sort True before False, hence the not
return not vm.inc_backup
- return self.data(index, Qt.DisplayRole)
+ return self.data(index, Qt.ItemDataRole.DisplayRole)
# pylint: disable=invalid-name
def headerData(self, col, orientation, role):
if col < 2:
return None
- if orientation == Qt.Horizontal and role == Qt.DisplayRole:
+ if (orientation == Qt.Orientation.Horizontal and role ==
+ Qt.ItemDataRole.DisplayRole):
return self.columns_indices[col]
return None
- def setData(self, index, value, role=Qt.EditRole):
+ def setData(self, index, value, role=Qt.ItemDataRole.EditRole):
if not index.isValid():
return False
- if role == Qt.CheckStateRole:
+ if role == Qt.ItemDataRole.CheckStateRole:
col_name = self.columns_indices[index.column()]
if col_name == "Backup":
vm = self.qubes_cache.get_vm(index.row())
- vm.vm.include_in_backups = value == Qt.Checked
- vm.inc_backup = value == Qt.Checked
+ vm.vm.include_in_backups = value == Qt.CheckState.Checked
+ vm.inc_backup = value == Qt.CheckState.Checked
return True
return False
def flags(self, index):
if not index.isValid():
- return Qt.NoItemFlags
+ return Qt.ItemFlag.NoItemFlags
def_flags = QAbstractTableModel.flags(self, index)
if self.columns_indices[index.column()] == "Backup":
- return def_flags | Qt.ItemIsUserCheckable
+ return def_flags | Qt.ItemFlag.ItemIsUserCheckable
return def_flags
vm_restart_check_timeout = 1000 # in msec
@@ -573,27 +577,28 @@ def check_if_vm_has_shutdown(self):
if self.timeout_reached():
msgbox = QMessageBox(self.caller)
- msgbox.setIcon(QMessageBox.Question)
+ msgbox.setIcon(QMessageBox.Icon.Question)
msgbox.setWindowTitle(self.tr("Qube Shutdown"))
msgbox.setText(self.tr(
"The Qube '{0}' hasn't shutdown within the last "
"{1} seconds, do you want to kill it?
").format(
vm.name, self.shutdown_timeout))
kill_button = msgbox.addButton(
- self.tr("Kill it!"), QMessageBox.YesRole)
+ self.tr("Kill it!"), QMessageBox.ButtonRole.YesRole)
wait_button = msgbox.addButton(
self.tr("Wait another {0} seconds...").format(
self.shutdown_timeout),
- QMessageBox.NoRole)
- ignore_button = msgbox.addButton(self.tr("Don't ask again"),
- QMessageBox.RejectRole)
+ QMessageBox.ButtonRole.NoRole)
+ ignore_button = msgbox.addButton(
+ self.tr("Don't ask again"),
+ QMessageBox.ButtonRole.RejectRole)
msgbox.setDefaultButton(wait_button)
msgbox.setEscapeButton(ignore_button)
msgbox.setWindowFlags(
- msgbox.windowFlags() | Qt.CustomizeWindowHint)
+ msgbox.windowFlags() | Qt.WindowType.CustomizeWindowHint)
msgbox.setWindowFlags(
- msgbox.windowFlags() & ~Qt.WindowCloseButtonHint)
- msgbox.exec_()
+ msgbox.windowFlags() & ~Qt.WindowType.WindowCloseButtonHint)
+ msgbox.exec()
msgbox.deleteLater()
if msgbox.clickedButton() is kill_button:
@@ -666,15 +671,15 @@ def lessThan(self, left, right):
if left.data(self.sortRole()) != right.data(self.sortRole()):
return super().lessThan(left, right)
- left_vm = left.data(Qt.UserRole)
- right_vm = right.data(Qt.UserRole)
+ left_vm = left.data(Qt.ItemDataRole.UserRole)
+ right_vm = right.data(Qt.ItemDataRole.UserRole)
return left_vm.name.lower() < right_vm.name.lower()
# pylint: disable=too-many-return-statements
def filterAcceptsRow(self, sourceRow, sourceParent):
index = self.sourceModel().index(sourceRow, 0, sourceParent)
- vm = self.sourceModel().data(index, Qt.UserRole)
+ vm = self.sourceModel().data(index, Qt.ItemDataRole.UserRole)
# if hide internal is true, ignore all other filters
if not self.window.show_internal_action.isChecked() and vm.internal:
@@ -714,8 +719,11 @@ def __init__(self, qt_app, qubes_app, dispatcher, _parent=None):
self.qt_app = qt_app
self.searchbox = SearchBox()
- self.searchbox.setValidator(QRegExpValidator(
- QRegExp("[a-zA-Z0-9_-]*", Qt.CaseInsensitive), None))
+ self.searchbox.setValidator(QRegularExpressionValidator(
+ QRegularExpression(
+ "[a-zA-Z0-9_-]*",
+ QRegularExpression.PatternOption.CaseInsensitiveOption),
+ None))
self.searchbox.textChanged.connect(self.do_search)
self.searchContainer.insertWidget(1, self.searchbox)
@@ -782,10 +790,10 @@ def __init__(self, qt_app, qubes_app, dispatcher, _parent=None):
self.proxy = QubesProxyModel(self)
self.proxy.setSourceModel(self.qubes_model)
- self.proxy.setSortRole(Qt.UserRole + 1)
- self.proxy.setSortCaseSensitivity(Qt.CaseInsensitive)
+ self.proxy.setSortRole(Qt.ItemDataRole.UserRole + 1)
+ self.proxy.setSortCaseSensitivity(Qt.CaseSensitivity.CaseInsensitive)
self.proxy.setFilterKeyColumn(2)
- self.proxy.setFilterCaseSensitivity(Qt.CaseInsensitive)
+ self.proxy.setFilterCaseSensitivity(Qt.CaseSensitivity.CaseInsensitive)
self.proxy.layoutChanged.connect(self.save_sorting)
self.proxy.layoutChanged.connect(self.update_template_menu)
self.proxy.layoutChanged.connect(self.update_network_menu)
@@ -796,7 +804,7 @@ def __init__(self, qt_app, qubes_app, dispatcher, _parent=None):
selection_model = self.table.selectionModel()
selection_model.selectionChanged.connect(self.table_selection_changed)
- self.table.setContextMenuPolicy(Qt.CustomContextMenu)
+ self.table.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)
self.table.customContextMenuRequested.connect(self.open_context_menu)
try:
@@ -863,9 +871,9 @@ def change_template(self, template):
self.tr("Do you want to change '{0}'
"
"to Template '{1}'?").format(
', '.join(vm.name for vm in selected_vms), template),
- QMessageBox.Yes | QMessageBox.Cancel)
+ QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.Cancel)
- if reply == QMessageBox.Yes:
+ if reply == QMessageBox.StandardButton.Yes:
errors = []
for info in selected_vms:
try:
@@ -884,9 +892,9 @@ def change_network(self, netvm_name):
self.tr("Do you want to change '{0}'
"
"to Network '{1}'?").format(
', '.join(vm.name for vm in selected_vms), netvm_name),
- QMessageBox.Yes | QMessageBox.Cancel)
+ QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.Cancel)
- if reply != QMessageBox.Yes:
+ if reply != QMessageBox.StandardButton.Yes:
return
if netvm_name:
@@ -903,9 +911,10 @@ def change_network(self, netvm_name):
self.tr("
Can not change netvm to a halted Qube.
"
"Do you want to start the Qube '{0}'?").format(
netvm_name),
- QMessageBox.Yes | QMessageBox.Cancel)
+ QMessageBox.StandardButton.Yes |
+ QMessageBox.StandardButton.Cancel)
- if reply == QMessageBox.Yes:
+ if reply == QMessageBox.StandardButton.Yes:
self.start_vm(netvm, True)
else:
return
@@ -981,7 +990,7 @@ def fill_cache(self):
len(self.qubes_app.domains.keys()))
progress.setWindowTitle(self.tr("Qube Manager"))
progress.setMinimumDuration(1000)
- progress.setWindowModality(Qt.WindowModal)
+ progress.setWindowModality(Qt.WindowModality.WindowModal)
progress.setCancelButton(None)
row_no = 0
@@ -1024,7 +1033,7 @@ def setup_application(self):
self.qt_app.setWindowIcon(QIcon.fromTheme("qubes-manager"))
def keyPressEvent(self, event): # pylint: disable=invalid-name
- if event.key() == Qt.Key_Escape:
+ if event.key() == Qt.Key.Key_Escape:
self.searchbox.clear()
super().keyPressEvent(event)
@@ -1149,10 +1158,10 @@ def load_manager_settings(self):
sort_column = int(self.manager_settings.value("view/sort_column",
defaultValue=2))
order = Qt.SortOrder(self.manager_settings.value("view/sort_order",
- defaultValue=Qt.AscendingOrder))
+ defaultValue=Qt.SortOrder.AscendingOrder))
if not sort_column: # Default sort by name
- self.table.sortByColumn(2, Qt.AscendingOrder)
+ self.table.sortByColumn(2, Qt.SortOrder.AscendingOrder)
else:
self.table.sortByColumn(sort_column, order)
@@ -1204,7 +1213,7 @@ def get_selected_vms(self):
for index in indexes:
if index.column() != 0:
continue
- vms.append(index.data(Qt.UserRole))
+ vms.append(index.data(Qt.ItemDataRole.UserRole))
return vms
@@ -1323,7 +1332,7 @@ def action_createvm_triggered(self):
with common_threads.busy_cursor():
create_window = create_new_vm.NewVmDlg(
self.qt_app, self.qubes_app, self)
- create_window.exec_()
+ create_window.exec()
# noinspection PyArgumentList
@pyqtSlot(name='on_action_removevm_triggered')
@@ -1388,7 +1397,7 @@ def action_clonevm_triggered(self):
with common_threads.busy_cursor():
clone_window = clone_vm.CloneVMDlg(
self.qt_app, self.qubes_app, src_vm=vm)
- clone_window.exec_()
+ clone_window.exec()
# noinspection PyArgumentList
@pyqtSlot(name='on_action_resumevm_triggered')
@@ -1457,9 +1466,10 @@ def action_shutdownvm_triggered(self):
"?
This will shutdown all the running"
" applications within this Qube.").format(
vm.name),
- QMessageBox.Yes | QMessageBox.Cancel)
+ QMessageBox.StandardButton.Yes |
+ QMessageBox.StandardButton.Cancel)
- if reply == QMessageBox.Yes:
+ if reply == QMessageBox.StandardButton.Yes:
self.shutdown_vm(vm)
def get_connected_vms(self, vm, connected_vms):
@@ -1483,9 +1493,10 @@ def shutdown_vm(self, vm, force=False, check_time=vm_restart_check_timeout,
"
Do you want to shutdown: "
"'{1}'?").format(vm.name,
", ".join([x.name for x in connected_vms])),
- QMessageBox.Yes | QMessageBox.Cancel)
+ QMessageBox.StandardButton.Yes |
+ QMessageBox.StandardButton.Cancel)
- if reply != QMessageBox.Yes:
+ if reply != QMessageBox.StandardButton.Yes:
return False
force = True
@@ -1518,9 +1529,10 @@ def action_restartvm_triggered(self):
self.tr("Are you sure you want to restart the Qube '{0}'"
"?
This will shutdown all the running applica"
"tions within this Qube.").format(vm.name),
- QMessageBox.Yes | QMessageBox.Cancel)
+ QMessageBox.StandardButton.Yes |
+ QMessageBox.StandardButton.Cancel)
- if reply == QMessageBox.Yes:
+ if reply == QMessageBox.StandardButton.Yes:
# in case the user shut down the VM in the meantime
try:
if manager_utils.is_running(vm, False):
@@ -1558,10 +1570,11 @@ def action_killvm_triggered(self):
reply = QMessageBox.question(
self, self.tr("Qube Kill Confirmation"), info,
- QMessageBox.Yes | QMessageBox.Cancel,
- QMessageBox.Cancel)
+ QMessageBox.StandardButton.Yes |
+ QMessageBox.StandardButton.Cancel,
+ QMessageBox.StandardButton.Cancel)
- if reply == QMessageBox.Yes:
+ if reply == QMessageBox.StandardButton.Yes:
try:
vm.kill()
except exc.QubesException as ex:
@@ -1688,7 +1701,7 @@ def action_restore_triggered(self):
with common_threads.busy_cursor():
restore_window = restore.RestoreVMsWindow(self.qt_app,
self.qubes_app, self)
- restore_window.exec_()
+ restore_window.exec()
# noinspection PyArgumentList
@pyqtSlot(name='on_action_backup_triggered')
@@ -1705,9 +1718,11 @@ def action_exit_triggered(self):
def set_compactview(self, checked):
if checked:
- self.toolbar.setToolButtonStyle(Qt.ToolButtonIconOnly)
+ self.toolbar.setToolButtonStyle(
+ Qt.ToolButtonStyle.ToolButtonIconOnly)
else:
- self.toolbar.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)
+ self.toolbar.setToolButtonStyle(
+ Qt.ToolButtonStyle.ToolButtonTextUnderIcon)
if self.settings_loaded:
self.manager_settings.setValue('view/compactview', checked)
@@ -1738,7 +1753,7 @@ def showhide_column(self, col_num, show):
@pyqtSlot(name='on_action_about_qubes_triggered')
def action_about_qubes_triggered(self):
about = AboutDialog(self)
- about.exec_()
+ about.exec()
def createPopupMenu(self): # pylint: disable=invalid-name
menu = QMenu()
@@ -1747,11 +1762,11 @@ def createPopupMenu(self): # pylint: disable=invalid-name
return menu
def open_tools_context_menu(self, widget, point):
- self.tools_context_menu.exec_(widget.mapToGlobal(point))
+ self.tools_context_menu.exec(widget.mapToGlobal(point))
@pyqtSlot('const QPoint&')
def open_context_menu(self, point):
- self.context_menu.exec_(self.table.mapToGlobal(
+ self.context_menu.exec(self.table.mapToGlobal(
point + QPoint(10, 0)))
def show_log(self):
@@ -1775,7 +1790,7 @@ def show_log(self):
if len(logfiles) > 0:
log_dlg = log_dialog.LogDialog(self.qt_app, logfiles)
- log_dlg.exec_()
+ log_dlg.exec()
else:
QMessageBox.warning(
self,
diff --git a/qubesmanager/qvm_template_gui.py b/qubesmanager/qvm_template_gui.py
index 91f1636f..4da1fdd6 100644
--- a/qubesmanager/qvm_template_gui.py
+++ b/qubesmanager/qvm_template_gui.py
@@ -35,10 +35,10 @@
import typing
import shlex
-import PyQt5 # pylint: disable=import-error
-import PyQt5.QtWidgets # pylint: disable=import-error
-import PyQt5.QtCore # pylint: disable=import-error
-import PyQt5.QtGui # pylint: disable=import-error
+import PyQt6 # pylint: disable=import-error
+import PyQt6.QtWidgets # pylint: disable=import-error
+import PyQt6.QtCore # pylint: disable=import-error
+import PyQt6.QtGui # pylint: disable=import-error
from . import ui_templateinstallconfirmdlg # pylint: disable=no-name-in-module
from . import ui_templateinstallprogressdlg # pylint: disable=no-name-in-module
@@ -50,7 +50,7 @@
# singleton for "no date"
ZERO_DATE = datetime.fromtimestamp(0, UTC)
-tr = functools.partial(PyQt5.QtCore.QCoreApplication.translate, "Template GUI")
+tr = functools.partial(PyQt6.QtCore.QCoreApplication.translate, "Template GUI")
HELP_TEXT = tr("""
This tool can be used to manage templates on your system. \
@@ -247,21 +247,21 @@ def get_upgradable(self) -> bool:
def status(self, role):
# pylint: disable=too-many-return-statements
if self.obsolete():
- if role == PyQt5.QtCore.Qt.ToolTipRole:
+ if role == PyQt6.QtCore.Qt.ItemDataRole.ToolTipRole:
return tr("This template is obsolete and no longer receives "
"updates")
- if role == PyQt5.QtCore.Qt.DecorationRole:
+ if role == PyQt6.QtCore.Qt.ItemDataRole.DecorationRole:
return ":/obsolete.svg"
if self.template_status == 'extra':
- if role == PyQt5.QtCore.Qt.ToolTipRole:
+ if role == PyQt6.QtCore.Qt.ItemDataRole.ToolTipRole:
return tr("This template is a local template, not installed "
"from a repository")
- if role == PyQt5.QtCore.Qt.DecorationRole:
+ if role == PyQt6.QtCore.Qt.ItemDataRole.DecorationRole:
return ':/checkmark-with-plus.svg'
if self.template_status in ['installed', 'upgradable']:
- if role == PyQt5.QtCore.Qt.ToolTipRole:
+ if role == PyQt6.QtCore.Qt.ItemDataRole.ToolTipRole:
return tr("This template is installed")
- if role == PyQt5.QtCore.Qt.DecorationRole:
+ if role == PyQt6.QtCore.Qt.ItemDataRole.DecorationRole:
return ':/checkmark.svg'
return None
@@ -311,7 +311,7 @@ class DescriptiveItem(TreeItem):
def __init__(self, name):
self._name = name
self._children: typing.List[TreeItem] = []
- self._parent = PyQt5.QtCore.QModelIndex()
+ self._parent = PyQt6.QtCore.QModelIndex()
@property
def name(self) -> str:
@@ -330,22 +330,22 @@ def parent(self) -> TreeItem:
return self._parent
-class TemplateModel(PyQt5.QtCore.QAbstractItemModel):
+class TemplateModel(PyQt6.QtCore.QAbstractItemModel):
def __init__(self):
super().__init__()
self.children = []
- def index(self, row, column, parent=PyQt5.QtCore.QModelIndex()):
+ def index(self, row, column, parent=PyQt6.QtCore.QModelIndex()):
if not self.hasIndex(row, column, parent):
- return PyQt5.QtCore.QModelIndex()
+ return PyQt6.QtCore.QModelIndex()
if not parent.isValid():
child_item = self.children[row]
else:
child_item = parent.internalPointer().children[row]
return self.createIndex(row, column, child_item)
- def parent(self, child_index: PyQt5.QtCore.QModelIndex):
- node = PyQt5.QtCore.QModelIndex()
+ def parent(self, child_index: PyQt6.QtCore.QModelIndex):
+ node = PyQt6.QtCore.QModelIndex()
if child_index.isValid():
own_object = child_index.internalPointer()
if own_object is not None:
@@ -358,21 +358,21 @@ def parent(self, child_index: PyQt5.QtCore.QModelIndex):
node = self.createIndex(row, 0, parent)
return node
- def rowCount(self, parent=PyQt5.QtCore.QModelIndex()):
+ def rowCount(self, parent=PyQt6.QtCore.QModelIndex()):
if parent.internalPointer():
return len(parent.internalPointer().children)
return len(self.children)
- def columnCount(self, _parent=PyQt5.QtCore.QModelIndex()):
+ def columnCount(self, _parent=PyQt6.QtCore.QModelIndex()):
return len(Template.COL_NAMES)
- def data(self, index, role=PyQt5.QtCore.Qt.DisplayRole):
+ def data(self, index, role=PyQt6.QtCore.Qt.ItemDataRole.DisplayRole):
# pylint: disable=too-many-return-statements
if index.isValid():
data = index.internalPointer()
- if role == PyQt5.QtCore.Qt.ItemDataRole:
+ if role == PyQt6.QtCore.Qt.ItemDataRole:
return data.description
- if role == PyQt5.QtCore.Qt.DisplayRole:
+ if role == PyQt6.QtCore.Qt.ItemDataRole.DisplayRole:
if index.column() == 0:
return data.name
if index.column() == 1:
@@ -382,7 +382,7 @@ def data(self, index, role=PyQt5.QtCore.Qt.DisplayRole):
if index.column() == 3:
return data.repository()
return data.name
- if role == PyQt5.QtCore.Qt.ToolTipRole:
+ if role == PyQt6.QtCore.Qt.ItemDataRole.ToolTipRole:
if index.column() == 0:
return "Template name"
if index.column() == 1:
@@ -391,29 +391,29 @@ def data(self, index, role=PyQt5.QtCore.Qt.DisplayRole):
return "Template version"
if index.column() == 3:
return "Repository"
- if role == PyQt5.QtCore.Qt.TextAlignmentRole:
+ if role == PyQt6.QtCore.Qt.ItemDataRole.TextAlignmentRole:
if isinstance(data, int):
- return PyQt5.QtCore.Qt.AlignRight
- return PyQt5.QtCore.Qt.AlignLeft
- if role == PyQt5.QtCore.Qt.DecorationRole:
+ return PyQt6.QtCore.Qt.AlignmentFlag.AlignRight
+ return PyQt6.QtCore.Qt.AlignmentFlag.AlignLeft
+ if role == PyQt6.QtCore.Qt.ItemDataRole.DecorationRole:
if index.column() == 1:
icon_name = data.status(role)
if icon_name:
- return PyQt5.QtGui.QIcon(icon_name)
- if role == PyQt5.QtCore.Qt.UserRole:
+ return PyQt6.QtGui.QIcon(icon_name)
+ if role == PyQt6.QtCore.Qt.ItemDataRole.UserRole:
return data
return None
def headerData(self, section, orientation,
- role=PyQt5.QtCore.Qt.DisplayRole):
+ role=PyQt6.QtCore.Qt.ItemDataRole.DisplayRole):
if section < len(Template.COL_NAMES) \
- and orientation == PyQt5.QtCore.Qt.Horizontal \
- and role == PyQt5.QtCore.Qt.DisplayRole:
+ and orientation == PyQt6.QtCore.Qt.Orientation.Horizontal \
+ and role == PyQt6.QtCore.Qt.ItemDataRole.DisplayRole:
return Template.COL_NAMES[section]
return None
- def removeRows(self, row, count, _parent=PyQt5.QtCore.QModelIndex()):
- self.beginRemoveRows(PyQt5.QtCore.QModelIndex(), row, row + count)
+ def removeRows(self, row, count, _parent=PyQt6.QtCore.QModelIndex()):
+ self.beginRemoveRows(PyQt6.QtCore.QModelIndex(), row, row + count)
del self.children[row:row+count]
self.endRemoveRows()
self.dataChanged.emit(*self.row_index(row, row + count))
@@ -440,7 +440,7 @@ async def refresh(self, refresh=True):
return False, stderr
# remove old rows
rows_to_remove = len(self.children)
- self.beginRemoveRows(PyQt5.QtCore.QModelIndex(), 0,
+ self.beginRemoveRows(PyQt6.QtCore.QModelIndex(), 0,
rows_to_remove)
self.children = []
self.endRemoveRows()
@@ -494,7 +494,7 @@ async def refresh(self, refresh=True):
# Convert back to list
tpls = {k.title(): list(v.values()) for k, v in tpls.items()}
- self.beginInsertRows(PyQt5.QtCore.QModelIndex(), 0, len(tpls) - 1)
+ self.beginInsertRows(PyQt6.QtCore.QModelIndex(), 0, len(tpls) - 1)
for template_type, template_list in tpls.items():
if not template_list:
continue
@@ -511,10 +511,10 @@ async def refresh(self, refresh=True):
class TemplateInstallConfirmDialog(
ui_templateinstallconfirmdlg.Ui_TemplateInstallConfirmDlg,
- PyQt5.QtWidgets.QDialog):
+ PyQt6.QtWidgets.QDialog):
# pylint: disable=too-few-public-methods
def __init__(self, question: str, operation_name: str,
- palette: PyQt5.QtGui.QPalette, enable_warn: bool = False):
+ palette: PyQt6.QtGui.QPalette, enable_warn: bool = False):
super().__init__()
self.setupUi(self)
@@ -523,19 +523,19 @@ def __init__(self, question: str, operation_name: str,
ok_button = self.button_box.addButton(
operation_name,
- PyQt5.QtWidgets.QDialogButtonBox.ButtonRole.AcceptRole)
+ PyQt6.QtWidgets.QDialogButtonBox.ButtonRole.AcceptRole)
ok_button.setPalette(palette)
self.button_box.addButton(
"Cancel",
- PyQt5.QtWidgets.QDialogButtonBox.ButtonRole.RejectRole)
+ PyQt6.QtWidgets.QDialogButtonBox.ButtonRole.RejectRole)
class TemplateInstallProgressDialog(
ui_templateinstallprogressdlg.Ui_TemplateInstallProgressDlg,
- PyQt5.QtWidgets.QDialog):
+ PyQt6.QtWidgets.QDialog):
def __init__(self, command: typing.List[str],
- palette: PyQt5.QtGui.QPalette,
+ palette: PyQt6.QtGui.QPalette,
window_title: typing.Optional[str] = None):
"""
:param command: a list of strings containing the command to be used
@@ -549,13 +549,13 @@ def __init__(self, command: typing.List[str],
self.cancel_button = self.button_box.addButton(
"Abort",
- PyQt5.QtWidgets.QDialogButtonBox.ButtonRole.RejectRole)
+ PyQt6.QtWidgets.QDialogButtonBox.ButtonRole.RejectRole)
def add_ok_button(self):
self.button_box.removeButton(self.cancel_button)
- ok_button: PyQt5.QtWidgets.QPushButton = self.button_box.addButton(
+ ok_button: PyQt6.QtWidgets.QPushButton = self.button_box.addButton(
"OK",
- PyQt5.QtWidgets.QDialogButtonBox.ButtonRole.AcceptRole)
+ PyQt6.QtWidgets.QDialogButtonBox.ButtonRole.AcceptRole)
ok_button.setPalette(self.qubes_palette)
@staticmethod
@@ -606,16 +606,16 @@ async def coro():
class QvmTemplateWindow(
ui_templatemanger2.Ui_MainWindow,
- PyQt5.QtWidgets.QMainWindow):
+ PyQt6.QtWidgets.QMainWindow):
def __init__(self, qt_app, qubes_app, dispatcher, _parent=None):
super().__init__()
self.setupUi(self)
self.template_tree.header().setSectionResizeMode(
- PyQt5.QtWidgets.QHeaderView.ResizeToContents)
+ PyQt6.QtWidgets.QHeaderView.ResizeMode.ResizeToContents)
self.qubes_app = qubes_app
- self.qt_app: PyQt5.QtWidgets.QApplication = qt_app
- self.qt_app.setWindowIcon(PyQt5.QtGui.QIcon.fromTheme("qubes-manager"))
+ self.qt_app: PyQt6.QtWidgets.QApplication = qt_app
+ self.qt_app.setWindowIcon(PyQt6.QtGui.QIcon.fromTheme("qubes-manager"))
self.dispatcher = dispatcher
self.template_model = TemplateModel()
@@ -651,10 +651,10 @@ def initialize_styles(self):
qubes_style_buttons = [self.upgrade_button, self.install_button,
self.reinstall_button, self.uninstall_button]
palette = self.qt_app.palette()
- palette.setColor(PyQt5.QtGui.QPalette.Button, PyQt5.QtGui.QColor(
- "#4180c9"))
- palette.setColor(PyQt5.QtGui.QPalette.ButtonText, PyQt5.QtGui.QColor(
- "#ffffff"))
+ palette.setColor(PyQt6.QtGui.QPalette.ColorRole.Button,
+ PyQt6.QtGui.QColor("#4180c9"))
+ palette.setColor(PyQt6.QtGui.QPalette.ColorRole.ButtonText,
+ PyQt6.QtGui.QColor("#ffffff"))
for button in qubes_style_buttons:
button.setPalette(palette)
@@ -688,10 +688,10 @@ def _get_selected_item(self) -> typing.Optional[TreeItem]:
# and the selection model is single-row
selected_item = selected_indexes[0]
item = self.template_model.data(selected_item,
- PyQt5.QtCore.Qt.UserRole)
+ PyQt6.QtCore.Qt.ItemDataRole.UserRole)
return item
- def template_selected(self, _selected: PyQt5.QtCore.QItemSelection):
+ def template_selected(self, _selected: PyQt6.QtCore.QItemSelection):
item = self._get_selected_item()
if not item:
self._show_help()
@@ -716,12 +716,12 @@ def _do_action(self, command: typing.List[str], operation_name: str,
confirm = TemplateInstallConfirmDialog(question, operation_name,
self.qubes_palette,
enable_warn)
- if confirm.exec_():
+ if confirm.exec():
progress = TemplateInstallProgressDialog(command,
self.qubes_palette,
window_title)
progress.install()
- progress.exec_()
+ progress.exec()
self.refresh()
def do_uninstall(self):
@@ -769,7 +769,7 @@ def refresh(self, refresh=True):
async def coro():
ok, stderr = await self.template_model.refresh(refresh)
if not ok:
- PyQt5.QtWidgets.QMessageBox.warning(
+ PyQt6.QtWidgets.QMessageBox.warning(
self,
self.tr('Failed to fetch template list!'),
self.tr('Failed to fetch template list: \n') + stderr
diff --git a/qubesmanager/releasenotes.py b/qubesmanager/releasenotes.py
index 827926fe..c4d1d8e3 100644
--- a/qubesmanager/releasenotes.py
+++ b/qubesmanager/releasenotes.py
@@ -20,7 +20,7 @@
# with this program; if not, see .
#
#
-from PyQt5.QtWidgets import QDialog # pylint: disable=import-error
+from PyQt6.QtWidgets import QDialog # pylint: disable=import-error
from . import ui_releasenotes # pylint: disable=no-name-in-module
diff --git a/qubesmanager/restore.py b/qubesmanager/restore.py
index a3379897..03319e0a 100644
--- a/qubesmanager/restore.py
+++ b/qubesmanager/restore.py
@@ -20,7 +20,7 @@
#
#
-from PyQt5 import QtCore, QtWidgets, QtGui, Qt # pylint: disable=import-error
+from PyQt6 import QtCore, QtWidgets, QtGui # pylint: disable=import-error
import os
import os.path
import logging
@@ -75,8 +75,8 @@ def __init__(self, qt_app, qubes_app, parent=None):
self.qt_app = qt_app
self.qubes_app = qubes_app
self.setWindowFlags(self.windowFlags() |
- Qt.Qt.WindowMaximizeButtonHint |
- Qt.Qt.WindowMinimizeButtonHint)
+ QtCore.Qt.WindowType.WindowMaximizeButtonHint |
+ QtCore.Qt.WindowType.WindowMinimizeButtonHint)
self.vms_to_restore = None
self.func_output = []
@@ -117,10 +117,12 @@ def __init__(self, qt_app, qubes_app, parent=None):
def show_hide_password(self):
if self.passwd_show_button.isChecked():
- self.passphrase_line_edit.setEchoMode(QtWidgets.QLineEdit.Password)
+ self.passphrase_line_edit.setEchoMode(
+ QtWidgets.QLineEdit.EchoMode.Password)
self.passwd_show_button.setIcon(QtGui.QIcon(':/eye-off.svg'))
else:
- self.passphrase_line_edit.setEchoMode(QtWidgets.QLineEdit.Normal)
+ self.passphrase_line_edit.setEchoMode(
+ QtWidgets.QLineEdit.EchoMode.Normal)
self.passwd_show_button.setIcon(QtGui.QIcon(':/eye.svg'))
def setup_application(self):
@@ -212,7 +214,7 @@ def current_page_changed(self, page_id): # pylint: disable=unused-argument
self.confirm_page.completeChanged.emit()
elif self.currentPage() is self.commit_page:
- self.button(self.FinishButton).setDisabled(True)
+ self.button(self.WizardButton.FinishButton).setDisabled(True)
self.showFileDialog.setEnabled(True)
self.showFileDialog.setChecked(self.showFileDialog.isEnabled()
and str(self.dir_line_edit.text())
@@ -249,8 +251,8 @@ def thread_finished(self):
"the file selection dialog.")))
backup_utils.select_path_button_clicked(self, False, True)
- self.button(self.FinishButton).setEnabled(True)
- self.button(self.CancelButton).setEnabled(False)
+ self.button(self.WizardButton.FinishButton).setEnabled(True)
+ self.button(self.WizardButton.CancelButton).setEnabled(False)
self.showFileDialog.setEnabled(False)
def update_log(self):
@@ -280,7 +282,7 @@ def reject(self):
self.backup_restore.canceled = True
self.append_output('{0}'.format(
self.tr("Aborting the operation...")))
- self.button(self.CancelButton).setDisabled(True)
+ self.button(self.WizardButton.CancelButton).setDisabled(True)
else:
self.done(0)
diff --git a/qubesmanager/settings.py b/qubesmanager/settings.py
index 18207804..8aa0b532 100644
--- a/qubesmanager/settings.py
+++ b/qubesmanager/settings.py
@@ -43,7 +43,7 @@
from .appmenu_select import AppmenuSelectManager
from . import firewall
-from PyQt5 import QtCore, QtWidgets, QtGui, Qt # pylint: disable=import-error
+from PyQt6 import QtCore, QtWidgets, QtGui # pylint: disable=import-error
from . import ui_settingsdlg # pylint: disable=no-name-in-module
@@ -152,14 +152,15 @@ def __init__(self, vm, init_page="basic", qapp=None, qubesapp=None,
self.setupUi(self)
self.setWindowTitle(self.tr("Settings: {vm}").format(vm=self.vm.name))
self.setWindowFlags(self.windowFlags() |
- Qt.Qt.WindowMaximizeButtonHint |
- Qt.Qt.WindowMinimizeButtonHint)
+ QtCore.Qt.WindowType.WindowMaximizeButtonHint |
+ QtCore.Qt.WindowType.WindowMinimizeButtonHint)
if init_page in self.tabs_indices:
idx = self.tabs_indices[init_page]
assert idx in range(self.tabWidget.count())
self.tabWidget.setCurrentIndex(idx)
- self.buttonBox.button(QtWidgets.QDialogButtonBox.Apply).clicked.connect(
+ self.buttonBox.button(
+ QtWidgets.QDialogButtonBox.StandardButton.Apply).clicked.connect(
self.apply)
self.tabWidget.currentChanged.connect(self.current_tab_changed)
@@ -266,8 +267,8 @@ def clear_threads(self):
raise RuntimeError(self.tr('No finished thread found'))
def keyPressEvent(self, event): # pylint: disable=invalid-name
- if event.key() == QtCore.Qt.Key_Enter \
- or event.key() == QtCore.Qt.Key_Return:
+ if event.key() == QtCore.Qt.Key.Key_Enter \
+ or event.key() == QtCore.Qt.Key.Key_Return:
return
super().keyPressEvent(event)
@@ -381,9 +382,11 @@ def current_tab_changed(self, idx):
def __init_basic_tab__(self):
self.vmname.setText(self.vm.name)
self.vmname.setValidator(
- QtGui.QRegExpValidator(
- QtCore.QRegExp("[a-zA-Z0-9_-]*",
- QtCore.Qt.CaseInsensitive), None))
+ QtGui.QRegularExpressionValidator(
+ QtCore.QRegularExpression(
+ "[a-zA-Z0-9_-]*",
+ QtCore.QRegularExpression.
+ PatternOption.CaseInsensitiveOption), None))
self.vmname.setEnabled(False)
self.rename_vm_button.setEnabled(not self.vm.is_running())
self.delete_vm_button.setEnabled(not self.vm.is_running())
@@ -574,10 +577,10 @@ def __apply_basic_tab__(self):
"to a halted Qube.
"
"Do you want to start the Qube"
" '{0}'?").format(netvm.name),
- QtWidgets.QMessageBox.Yes |
- QtWidgets.QMessageBox.Cancel)
+ QtWidgets.QMessageBox.StandardButton.Yes |
+ QtWidgets.QMessageBox.StandardButton.Cancel)
- if reply == QtWidgets.QMessageBox.Yes:
+ if reply == QtWidgets.QMessageBox.StandardButton.Yes:
netvm.start()
self.vm.netvm = self.netVM.currentData()
else:
@@ -800,7 +803,7 @@ def clone_vm(self):
with common_threads.busy_cursor():
clone_window = clone_vm.CloneVMDlg(
self.qapp, self.qubesapp, src_vm=self.vm)
- clone_window.exec_()
+ clone_window.exec()
######### advanced tab
@@ -1059,7 +1062,7 @@ def __apply_advanced_tab__(self):
def include_in_balancing_changed(self, state):
if self.dev_list.selected_list.count() > 0:
- if state == ui_settingsdlg.QtCore.Qt.Checked:
+ if state == ui_settingsdlg.QtCore.Qt.CheckState.Checked:
self.dmm_warning_adv.show()
self.dmm_warning_dev.show()
else:
@@ -1072,7 +1075,7 @@ def include_in_balancing_changed(self, state):
def boot_from_cdrom_button_pressed(self):
boot_dialog = bootfromdevice.VMBootFromDeviceWindow(
self.vm.name, self.qapp, self.qubesapp, self)
- if boot_dialog.exec_():
+ if boot_dialog.exec():
self.save_and_apply()
qvm_start.main(
['--cdrom', boot_dialog.cdrom_location, self.vm.name])
@@ -1353,9 +1356,10 @@ def __init_services_tab__(self):
continue
service = feature[len(SERVICE_PREFIX):]
item = QtWidgets.QListWidgetItem(service)
- item.setCheckState(ui_settingsdlg.QtCore.Qt.Checked
- if self.vm.features[feature]
- else ui_settingsdlg.QtCore.Qt.Unchecked)
+ item.setCheckState(
+ ui_settingsdlg.QtCore.Qt.CheckState.Checked
+ if self.vm.features[feature]
+ else ui_settingsdlg.QtCore.Qt.CheckState.Unchecked)
self.services_list.addItem(item)
self.new_srv_dict[service] = self.vm.features[feature]
except qubesadmin.exc.QubesDaemonAccessError:
@@ -1407,7 +1411,7 @@ def __add_service__(self):
self.tr('Service already on the list!'))
return
item = QtWidgets.QListWidgetItem(srv)
- item.setCheckState(ui_settingsdlg.QtCore.Qt.Checked)
+ item.setCheckState(ui_settingsdlg.QtCore.Qt.CheckState.Checked)
self.services_list.addItem(item)
self.new_srv_dict[srv] = True
@@ -1431,7 +1435,8 @@ def __apply_services_tab__(self):
for i in range(self.services_list.count()):
item = self.services_list.item(i)
self.new_srv_dict[str(item.text())] = \
- item.checkState() == ui_settingsdlg.QtCore.Qt.Checked
+ (item.checkState() ==
+ ui_settingsdlg.QtCore.Qt.CheckState.Checked)
for service, v in self.new_srv_dict.items():
feature = SERVICE_PREFIX + service
@@ -1455,9 +1460,9 @@ def set_fw_model(self, model):
self.fw_model = model
self.rulesTreeView.setModel(model)
self.rulesTreeView.header().setSectionResizeMode(
- QtWidgets.QHeaderView.ResizeToContents)
+ QtWidgets.QHeaderView.ResizeMode.ResizeToContents)
self.rulesTreeView.header().setSectionResizeMode(
- 0, QtWidgets.QHeaderView.Stretch)
+ 0, QtWidgets.QHeaderView.ResizeMode.Stretch)
self.set_allow(model.allow)
if model.temp_full_access_expire_time:
self.temp_full_access.setChecked(True)
diff --git a/qubesmanager/template_manager.py b/qubesmanager/template_manager.py
index 2da1c4a2..34bace99 100644
--- a/qubesmanager/template_manager.py
+++ b/qubesmanager/template_manager.py
@@ -22,7 +22,7 @@
from qubesadmin import exc
-from PyQt5 import QtWidgets, QtGui, QtCore # pylint: disable=import-error
+from PyQt6 import QtWidgets, QtGui, QtCore # pylint: disable=import-error
from . import ui_templatemanager # pylint: disable=no-name-in-module
from . import utils
@@ -49,11 +49,14 @@ def __init__(self, qt_app, qubes_app, dispatcher, parent=None):
self.prepare_lists()
self.initialize_table_events()
- self.buttonBox.button(QtWidgets.QDialogButtonBox.Ok).clicked.connect(
+ self.buttonBox.button(
+ QtWidgets.QDialogButtonBox.StandardButton.Ok).clicked.connect(
self.apply)
self.buttonBox.button(
- QtWidgets.QDialogButtonBox.Cancel).clicked.connect(self.cancel)
- self.buttonBox.button(QtWidgets.QDialogButtonBox.Reset).clicked.connect(
+ QtWidgets.QDialogButtonBox.StandardButton.Cancel).clicked.connect(
+ self.cancel)
+ self.buttonBox.button(
+ QtWidgets.QDialogButtonBox.StandardButton.Reset).clicked.connect(
self.reset)
self.change_all_combobox.currentIndexChanged.connect(
@@ -161,7 +164,7 @@ def sorting_changed(self, index, _order):
if index == column_names.index('New template') or \
index == column_names.index('State'):
self.vm_list.horizontalHeader().setSortIndicator(
- -1, QtCore.Qt.AscendingOrder)
+ -1, QtCore.Qt.SortOrder.AscendingOrder)
def clear_selection(self):
for row in self.rows_in_table.values():
diff --git a/qubesmanager/tests/__init__.py b/qubesmanager/tests/__init__.py
index 5590f56c..059e7833 100644
--- a/qubesmanager/tests/__init__.py
+++ b/qubesmanager/tests/__init__.py
@@ -2,7 +2,7 @@
import sys
import qasync
-from PyQt5 import QtWidgets
+from PyQt6 import QtWidgets
qtapp = None
loop = None
diff --git a/qubesmanager/tests/test_backup.py b/qubesmanager/tests/test_backup.py
index e6475c29..5e554086 100644
--- a/qubesmanager/tests/test_backup.py
+++ b/qubesmanager/tests/test_backup.py
@@ -23,7 +23,7 @@
import unittest
import unittest.mock
-from PyQt5 import QtTest, QtCore, QtWidgets
+from PyQt6 import QtTest, QtCore, QtWidgets
from qubesadmin import Qubes, events, utils, exc
from qubesmanager import backup
from qubesmanager.tests import init_qtapp
@@ -394,7 +394,7 @@ def test_21_loading_settings_error(self, mock_load):
self.assertIn('incorrect_vm', self.dialog.warning_running_label.text())
@unittest.mock.patch('qubesmanager.backup_utils.load_backup_profile')
- @unittest.mock.patch('PyQt5.QtWidgets.QMessageBox.information')
+ @unittest.mock.patch('PyQt6.QtWidgets.QMessageBox.information')
def test_22_loading_settings_exc(self, mock_info, mock_load):
mock_load.side_effect = exc.QubesException('Error')
@@ -431,7 +431,7 @@ def test_23_cancel_confirm(self, *_args):
mock_remove.assert_called_once_with(
'/etc/qubes/backup/qubes-manager-backup-tmp.conf')
- @unittest.mock.patch('PyQt5.QtWidgets.QMessageBox.warning')
+ @unittest.mock.patch('PyQt6.QtWidgets.QMessageBox.warning')
@unittest.mock.patch('qubesmanager.backup_utils.write_backup_profile')
@unittest.mock.patch('qubesadmin.Qubes.qubesd_call',
return_value=b'backup output')
@@ -456,7 +456,7 @@ def test_24_cancel_in_progress(self, mock_call, *_args):
mock_remove.assert_called_once_with(
'/etc/qubes/backup/qubes-manager-backup-tmp.conf')
- @unittest.mock.patch('PyQt5.QtWidgets.QMessageBox.warning')
+ @unittest.mock.patch('PyQt6.QtWidgets.QMessageBox.warning')
@unittest.mock.patch('os.system')
@unittest.mock.patch('os.remove')
@unittest.mock.patch('qubesmanager.backup_utils.write_backup_profile')
@@ -496,7 +496,7 @@ def test_25_successful_backup(self, _a, _b, mock_remove,
self.assertEqual(mock_warning.call_count, 0,
"Backup succeeded but received warning")
- @unittest.mock.patch('PyQt5.QtWidgets.QMessageBox.warning')
+ @unittest.mock.patch('PyQt6.QtWidgets.QMessageBox.warning')
@unittest.mock.patch('os.system')
@unittest.mock.patch('os.remove')
@unittest.mock.patch('qubesmanager.backup_utils.write_backup_profile')
@@ -535,7 +535,7 @@ def test_26_success_backup_poweroff(
self.assertEqual(mock_warning.call_count, 0,
"Backup succeeded but received warning")
- @unittest.mock.patch('PyQt5.QtWidgets.QMessageBox.warning')
+ @unittest.mock.patch('PyQt6.QtWidgets.QMessageBox.warning')
@unittest.mock.patch('os.system')
@unittest.mock.patch('os.remove')
@unittest.mock.patch('qubesmanager.backup_utils.write_backup_profile')
@@ -573,7 +573,7 @@ def test_27_failed_backup(
"Attempted shutdown at failed backup")
self.assertEqual(mock_warn.call_count, 1)
- @unittest.mock.patch('PyQt5.QtWidgets.QMessageBox.warning')
+ @unittest.mock.patch('PyQt6.QtWidgets.QMessageBox.warning')
@unittest.mock.patch('os.system')
@unittest.mock.patch('os.remove')
@unittest.mock.patch('qubesmanager.backup_utils.write_backup_profile')
diff --git a/qubesmanager/tests/test_backup_utils.py b/qubesmanager/tests/test_backup_utils.py
index 615b9f41..cc9653e9 100644
--- a/qubesmanager/tests/test_backup_utils.py
+++ b/qubesmanager/tests/test_backup_utils.py
@@ -21,7 +21,7 @@
#
import logging.handlers
import unittest.mock
-from PyQt5 import QtWidgets
+from PyQt6 import QtWidgets
from qubesadmin import Qubes
from qubesmanager import backup_utils
diff --git a/qubesmanager/tests/test_clone_vm.py b/qubesmanager/tests/test_clone_vm.py
index 63ab668a..765f7cf1 100644
--- a/qubesmanager/tests/test_clone_vm.py
+++ b/qubesmanager/tests/test_clone_vm.py
@@ -23,7 +23,7 @@
import unittest
import unittest.mock
-from PyQt5 import QtTest, QtCore
+from PyQt6 import QtTest, QtCore
from qubesadmin import Qubes
from qubesmanager.tests import init_qtapp
from qubesmanager import clone_vm
@@ -46,13 +46,13 @@ def setUp(self):
# mock the progress dialog to speed testing up
self.patcher_progress = unittest.mock.patch(
- 'PyQt5.QtWidgets.QProgressDialog')
+ 'PyQt6.QtWidgets.QProgressDialog')
self.mock_progress = self.patcher_progress.start()
self.addCleanup(self.patcher_progress.stop)
# mock the progress dialog to speed testing up
self.patcher_warning = unittest.mock.patch(
- 'PyQt5.QtWidgets.QMessageBox.warning')
+ 'PyQt6.QtWidgets.QMessageBox.warning')
self.mock_warning = self.patcher_warning.start()
self.addCleanup(self.patcher_warning.stop)
@@ -225,13 +225,13 @@ def setUp(self):
# mock the progress dialog to speed testing up
self.patcher_progress = unittest.mock.patch(
- 'PyQt5.QtWidgets.QProgressDialog')
+ 'PyQt6.QtWidgets.QProgressDialog')
self.mock_progress = self.patcher_progress.start()
self.addCleanup(self.patcher_progress.stop)
# mock the progress dialog to speed testing up
self.patcher_warning = unittest.mock.patch(
- 'PyQt5.QtWidgets.QMessageBox.warning')
+ 'PyQt6.QtWidgets.QMessageBox.warning')
self.mock_warning = self.patcher_warning.start()
self.addCleanup(self.patcher_warning.stop)
diff --git a/qubesmanager/tests/test_create_new_vm.py b/qubesmanager/tests/test_create_new_vm.py
index 19456d2e..c3bf9e25 100644
--- a/qubesmanager/tests/test_create_new_vm.py
+++ b/qubesmanager/tests/test_create_new_vm.py
@@ -23,7 +23,7 @@
import unittest
import unittest.mock
-from PyQt5 import QtTest, QtCore
+from PyQt6 import QtTest, QtCore
from qubesadmin import Qubes
from qubesmanager.tests import init_qtapp
from qubesmanager import create_new_vm
@@ -44,7 +44,7 @@ def setUp(self):
# mock the progress dialog to speed testing up
self.patcher_progress = unittest.mock.patch(
- 'PyQt5.QtWidgets.QProgressDialog')
+ 'PyQt6.QtWidgets.QProgressDialog')
self.mock_progress = self.patcher_progress.start()
self.addCleanup(self.patcher_progress.stop)
diff --git a/qubesmanager/tests/test_qube_manager.py b/qubesmanager/tests/test_qube_manager.py
index ddf4bf6f..acc89713 100644
--- a/qubesmanager/tests/test_qube_manager.py
+++ b/qubesmanager/tests/test_qube_manager.py
@@ -30,9 +30,9 @@
import datetime
import time
-from PyQt5 import QtTest, QtCore, QtWidgets
-from PyQt5.QtCore import (Qt, QSize)
-from PyQt5.QtGui import (QIcon)
+from PyQt6 import QtTest, QtCore, QtWidgets
+from PyQt6.QtCore import (Qt, QSize)
+from PyQt6.QtGui import (QIcon)
from qubesadmin import Qubes, events, exc
import qubesmanager.qube_manager as qube_manager
@@ -78,7 +78,7 @@ def setUp(self):
self.qtapp, self.loop = init_qtapp()
self.mock_qprogress = unittest.mock.patch(
- 'PyQt5.QtWidgets.QProgressDialog')
+ 'PyQt6.QtWidgets.QProgressDialog')
self.mock_qprogress.start()
self.addCleanup(self.mock_qprogress.stop)
@@ -268,9 +268,9 @@ def test_013_incorrect_settings_file(self):
mock_settings.side_effect = (
lambda x, *args, **kwargs: settings_result_dict.get(x))
- with unittest.mock.patch('PyQt5.QtCore.QSettings.value',
+ with unittest.mock.patch('PyQt6.QtCore.QSettings.value',
mock_settings),\
- unittest.mock.patch('PyQt5.QtWidgets.QMessageBox.warning')\
+ unittest.mock.patch('PyQt6.QtWidgets.QMessageBox.warning')\
as mock_warning:
self.dialog = qube_manager.VmManagerWindow(
self.qtapp, self.qapp, self.dispatcher)
@@ -338,7 +338,7 @@ def test_203_vm_open_apps(self, mock_window):
mock_window.assert_called_once_with(
selected_vm, "applications", self.qtapp, self.qapp, self.dialog)
- @unittest.mock.patch('PyQt5.QtWidgets.QMessageBox.warning')
+ @unittest.mock.patch('PyQt6.QtWidgets.QMessageBox.warning')
def test_204_vm_keyboard(self, mock_message):
selected_vm = self._select_non_admin_vm(running=True)
self.assertIsNotNone(selected_vm, "No valid non-admin VM found")
@@ -353,7 +353,7 @@ def test_204_vm_keyboard(self, mock_message):
self.assertEqual(mock_message.call_count, 0,
"VM does not support new layout change")
- @unittest.mock.patch('PyQt5.QtWidgets.QMessageBox.warning')
+ @unittest.mock.patch('PyQt6.QtWidgets.QMessageBox.warning')
def test_205_vm_keyboard_not_running(self, mock_message):
selected_vm = self._select_non_admin_vm(running=False)
self.assertIsNotNone(selected_vm, "No valid non-admin VM found")
@@ -383,7 +383,7 @@ def test_208_update_vm_admin(self):
mock_update.assert_called_once_with([selected_vm.name])
mock_update().start.assert_called_once_with()
- @unittest.mock.patch("PyQt5.QtWidgets.QInputDialog.getText",
+ @unittest.mock.patch("PyQt6.QtWidgets.QInputDialog.getText",
return_value=("command to run", True))
def test_209_run_command_in_vm(self, _):
selected_vm = self._select_non_admin_vm()
@@ -404,7 +404,7 @@ def test_210_run_command_in_adminvm(self):
self.assertFalse(self.dialog.action_run_command_in_vm.isEnabled(),
"Should not be able to run commands for dom0")
- @unittest.mock.patch("PyQt5.QtWidgets.QMessageBox.warning")
+ @unittest.mock.patch("PyQt6.QtWidgets.QMessageBox.warning")
def test_211_pausevm(self, mock_warn):
selected_vm = self._select_non_admin_vm(running=True)
@@ -442,9 +442,9 @@ def test_213_resume_running_vm(self):
self._select_non_admin_vm(running=True)
self.assertFalse(self.dialog.action_resumevm.isEnabled())
- @unittest.mock.patch("PyQt5.QtWidgets.QMessageBox.question",
+ @unittest.mock.patch("PyQt6.QtWidgets.QMessageBox.question",
return_value=QtWidgets.QMessageBox.Yes)
- @unittest.mock.patch('PyQt5.QtCore.QTimer.singleShot')
+ @unittest.mock.patch('PyQt6.QtCore.QTimer.singleShot')
@unittest.mock.patch('qubesmanager.qube_manager.VmShutdownMonitor')
def test_214_shutdownvm(self, mock_monitor, mock_timer, _):
selected_vm = self._select_non_admin_vm(running=True)
@@ -492,8 +492,8 @@ def test_218_remove_vm_dependencies(self, mock_dependencies, mock_msgbox):
mock_msgbox().show.assert_called_with()
- @unittest.mock.patch('PyQt5.QtWidgets.QMessageBox.warning')
- @unittest.mock.patch("PyQt5.QtWidgets.QInputDialog.getText")
+ @unittest.mock.patch('PyQt6.QtWidgets.QMessageBox.warning')
+ @unittest.mock.patch("PyQt6.QtWidgets.QInputDialog.getText")
@unittest.mock.patch('qubesadmin.utils.vm_dependencies')
def test_219_remove_vm_no_depencies(
self, mock_dependencies, mock_input, mock_warning):
@@ -527,9 +527,9 @@ def test_220_restartvm_halted_vm(self):
self._select_non_admin_vm(running=False)
self.assertFalse(self.dialog.action_restartvm.isEnabled())
- @unittest.mock.patch('PyQt5.QtCore.QTimer.singleShot')
+ @unittest.mock.patch('PyQt6.QtCore.QTimer.singleShot')
@unittest.mock.patch('qubesmanager.qube_manager.VmShutdownMonitor')
- @unittest.mock.patch("PyQt5.QtWidgets.QMessageBox.question",
+ @unittest.mock.patch("PyQt6.QtWidgets.QMessageBox.question",
return_value=QtWidgets.QMessageBox.Yes)
def test_221_restartvm_running_vm(self, _msgbox, mock_monitor, _qtimer):
selected_vm = self._select_non_admin_vm(running=True)
@@ -545,7 +545,7 @@ def test_221_restartvm_running_vm(self, _msgbox, mock_monitor, _qtimer):
selected_vm, 1000, True, unittest.mock.ANY)
@unittest.mock.patch('qubesmanager.qube_manager.StartVMThread')
- @unittest.mock.patch("PyQt5.QtWidgets.QMessageBox.question",
+ @unittest.mock.patch("PyQt6.QtWidgets.QMessageBox.question",
return_value=QtWidgets.QMessageBox.Yes)
def test_222_restartvm_shutdown_meantime(self, _, mock_thread):
selected_vm = self._select_non_admin_vm(running=True)
@@ -572,7 +572,7 @@ def test_223_updatevm_running(self, mock_thread):
self.dialog.clear_threads)
mock_thread().start.assert_called_once_with()
- @unittest.mock.patch("PyQt5.QtWidgets.QMessageBox.question",
+ @unittest.mock.patch("PyQt6.QtWidgets.QMessageBox.question",
return_value=QtWidgets.QMessageBox.Yes)
def test_224_killvm(self, _):
selected_vm = self._select_non_admin_vm(running=True)
@@ -582,7 +582,7 @@ def test_224_killvm(self, _):
action.trigger()
mock_kill.assert_called_once_with()
- @unittest.mock.patch("PyQt5.QtWidgets.QMessageBox.question",
+ @unittest.mock.patch("PyQt6.QtWidgets.QMessageBox.question",
return_value=QtWidgets.QMessageBox.Cancel)
def test_225_killvm_cancel(self, _):
selected_vm = self._select_non_admin_vm(running=True)
@@ -686,7 +686,7 @@ def test_234_searchbox(self):
"Incorrect number of vms shown for cleared search box")
def test_235_hide_show_toolbars(self):
- with unittest.mock.patch('PyQt5.QtCore.QSettings.setValue')\
+ with unittest.mock.patch('PyQt6.QtCore.QSettings.setValue')\
as mock_setvalue:
self.dialog.action_menubar.trigger()
mock_setvalue.assert_called_with('view/menubar_visible', False)
@@ -714,7 +714,7 @@ def test_236_clear_searchbox(self):
self.assertEqual(expected_number, actual_number,
"Incorrect number of vms shown for cleared search box")
- @unittest.mock.patch('PyQt5.QtWidgets.QMessageBox.question')
+ @unittest.mock.patch('PyQt6.QtWidgets.QMessageBox.question')
@listen_for_events
def test_240_network_menu_single(self, mock_question):
mock_question.return_value = QtWidgets.QMessageBox.Yes
@@ -777,7 +777,7 @@ def test_240_network_menu_single(self, mock_question):
mock_question.assert_called()
self.assertTrue(selected_vm.property_is_default('netvm'))
- @unittest.mock.patch('PyQt5.QtWidgets.QMessageBox.question')
+ @unittest.mock.patch('PyQt6.QtWidgets.QMessageBox.question')
@listen_for_events
def test_241_network_menu_multiple(self, mock_question):
mock_question.return_value = QtWidgets.QMessageBox.Yes
@@ -828,7 +828,7 @@ def test_241_network_menu_multiple(self, mock_question):
self.assertEqual(str(vault.netvm), 'sys-net')
mock_question.reset_mock()
- @unittest.mock.patch('PyQt5.QtWidgets.QMessageBox.question')
+ @unittest.mock.patch('PyQt6.QtWidgets.QMessageBox.question')
@listen_for_events
@skip_if_running('work')
def test_250_template_menu_single(self, mock_question):
@@ -876,7 +876,7 @@ def test_250_template_menu_single(self, mock_question):
self.assertEqual(str(selected_vm.template), str(new_template))
mock_question.reset_mock()
- @unittest.mock.patch('PyQt5.QtWidgets.QMessageBox.question')
+ @unittest.mock.patch('PyQt6.QtWidgets.QMessageBox.question')
@listen_for_events
@skip_if_running('work', 'personal', 'untrusted')
def test_251_template_menu_multiple(self, mock_question):
@@ -946,8 +946,8 @@ def test_251_template_menu_multiple(self, mock_question):
self.assertEqual(str(untrusted.template), str(new_template))
- @unittest.mock.patch('PyQt5.QtWidgets.QMessageBox.information')
- @unittest.mock.patch('PyQt5.QtWidgets.QMessageBox.warning')
+ @unittest.mock.patch('PyQt6.QtWidgets.QMessageBox.information')
+ @unittest.mock.patch('PyQt6.QtWidgets.QMessageBox.warning')
def test_300_clear_threads(self, mock_warning, mock_info):
mock_thread_finished_ok = unittest.mock.Mock(
spec=['isFinished', 'msg', 'msg_is_success'],
@@ -1619,7 +1619,7 @@ def test_23_update_vm_thread_error(self, mock_call):
class VMShutdownMonitorTest(unittest.TestCase):
@unittest.mock.patch('qubesmanager.qube_manager.QMessageBox')
- @unittest.mock.patch('PyQt5.QtCore.QTimer')
+ @unittest.mock.patch('PyQt6.QtCore.QTimer')
def test_01_vm_shutdown_correct(self, mock_timer, mock_question):
mock_vm = unittest.mock.Mock()
mock_vm.is_running.return_value = False
@@ -1634,7 +1634,7 @@ def test_01_vm_shutdown_correct(self, mock_timer, mock_question):
monitor.restart_vm_if_needed.assert_called_once_with()
@unittest.mock.patch('qubesmanager.qube_manager.QMessageBox')
- @unittest.mock.patch('PyQt5.QtCore.QTimer.singleShot')
+ @unittest.mock.patch('PyQt6.QtCore.QTimer.singleShot')
def test_02_vm_not_shutdown_wait(self, mock_timer, mock_question):
mock_question().clickedButton.return_value = 1
mock_question().addButton.return_value = 0
@@ -1652,7 +1652,7 @@ def test_02_vm_not_shutdown_wait(self, mock_timer, mock_question):
self.assertEqual(mock_timer.call_count, 1)
@unittest.mock.patch('qubesmanager.qube_manager.QMessageBox')
- @unittest.mock.patch('PyQt5.QtCore.QTimer.singleShot')
+ @unittest.mock.patch('PyQt6.QtCore.QTimer.singleShot')
def test_03_vm_kill(self, mock_timer, mock_question):
mock_question().clickedButton.return_value = 1
mock_question().addButton.return_value = 1
@@ -1673,7 +1673,7 @@ def test_03_vm_kill(self, mock_timer, mock_question):
monitor.restart_vm_if_needed.assert_called_once_with()
@unittest.mock.patch('qubesmanager.qube_manager.QMessageBox')
- @unittest.mock.patch('PyQt5.QtCore.QTimer.singleShot')
+ @unittest.mock.patch('PyQt6.QtCore.QTimer.singleShot')
def test_04_check_later(self, mock_timer, mock_question):
mock_vm = unittest.mock.Mock()
mock_vm.is_running.return_value = True
diff --git a/qubesmanager/tests/test_vm_settings.py b/qubesmanager/tests/test_vm_settings.py
index 0af18d99..f04d8da1 100644
--- a/qubesmanager/tests/test_vm_settings.py
+++ b/qubesmanager/tests/test_vm_settings.py
@@ -23,7 +23,7 @@
import unittest
import unittest.mock
-from PyQt5 import QtTest, QtCore
+from PyQt6 import QtTest, QtCore
from qubesadmin import Qubes
import qubesmanager.settings as vm_settings
from qubesmanager.tests import init_qtapp
@@ -35,7 +35,7 @@ def setUp(self):
self.qtapp, self.loop = init_qtapp()
self.mock_qprogress = unittest.mock.patch(
- 'PyQt5.QtWidgets.QProgressDialog')
+ 'PyQt6.QtWidgets.QProgressDialog')
self.mock_qprogress.start()
self.addCleanup(self.mock_qprogress.stop)
@@ -295,8 +295,8 @@ def test_10_increase_private_storage(self):
# TODO are dependencies correctly processed
- @unittest.mock.patch('PyQt5.QtWidgets.QProgressDialog')
- @unittest.mock.patch('PyQt5.QtWidgets.QInputDialog.getText')
+ @unittest.mock.patch('PyQt6.QtWidgets.QProgressDialog')
+ @unittest.mock.patch('PyQt6.QtWidgets.QInputDialog.getText')
@unittest.mock.patch('qubesmanager.settings.RenameVMThread')
def test_11_rename_vm(self, mock_thread, mock_input, _):
self.vm = self.qapp.add_new_vm("AppVM", "test-vm", "blue")
@@ -325,9 +325,9 @@ def test_12_clone_vm(self, mock_clone):
src_vm=self.vm)
- @unittest.mock.patch('PyQt5.QtWidgets.QMessageBox.warning')
- @unittest.mock.patch('PyQt5.QtWidgets.QProgressDialog')
- @unittest.mock.patch('PyQt5.QtWidgets.QInputDialog.getText')
+ @unittest.mock.patch('PyQt6.QtWidgets.QMessageBox.warning')
+ @unittest.mock.patch('PyQt6.QtWidgets.QProgressDialog')
+ @unittest.mock.patch('PyQt6.QtWidgets.QInputDialog.getText')
@unittest.mock.patch('qubesmanager.common_threads.RemoveVMThread')
def test_13_remove_vm(self, mock_thread, mock_input, _, mock_warning):
self.vm = self.qapp.add_new_vm("AppVM", "test-vm", "blue")
diff --git a/qubesmanager/utils.py b/qubesmanager/utils.py
index 44551fb2..7350ef9f 100644
--- a/qubesmanager/utils.py
+++ b/qubesmanager/utils.py
@@ -33,7 +33,7 @@
from qubesadmin import events
from qubesadmin import exc
-from PyQt5 import QtWidgets, QtCore, QtGui # pylint: disable=import-error
+from PyQt6 import QtWidgets, QtCore, QtGui # pylint: disable=import-error
# important usage note: which initialize_widget should I use?
@@ -81,8 +81,8 @@ def __init__(self, *args, **kwargs):
self.pattern = r'(\d+\.?\d?) ?(GB|MB)'
self.regex = re.compile(self.pattern)
- self.validator = QtGui.QRegExpValidator(QtCore.QRegExp(
- self.pattern), self)
+ self.validator = QtGui.QRegularExpressionValidator(
+ QtCore.QRegularExpression(self.pattern), self)
def textFromValue(self, v: int) -> str:
if v > 1024:
@@ -484,7 +484,7 @@ def handle_exception(exc_type, exc_value, exc_traceback):
msg_box = QtWidgets.QMessageBox()
msg_box.setDetailedText(strace)
- msg_box.setIcon(QtWidgets.QMessageBox.Critical)
+ msg_box.setIcon(QtWidgets.QMessageBox.Icon.Critical)
msg_box.setWindowTitle(QtCore.QCoreApplication.translate(
"ManagerUtils", "Houston, we have a problem..."))
msg_box.setText(QtCore.QCoreApplication.translate(
@@ -493,7 +493,7 @@ def handle_exception(exc_type, exc_value, exc_traceback):
"{0}
at line {1}
of file "
"{2}.
").format(error, line, filename))
- msg_box.exec_()
+ msg_box.exec()
def run_asynchronous(window_class):
@@ -512,13 +512,16 @@ def run_asynchronous(window_class):
qt_app.setOrganizationDomain("http://qubes-os.org")
qt_app.lastWindowClosed.connect(loop_shutdown)
- qubes_app = qubesadmin.Qubes()
+ # qubes_app = qubesadmin.Qubes()
+ import qubesadmin.tests.mock_app as mock_app
+ qapp = mock_app.MockQubesComplete()
+ dispatcher = mock_app.MockDispatcher(qapp)
loop = qasync.QEventLoop(qt_app)
asyncio.set_event_loop(loop)
- dispatcher = events.EventsDispatcher(qubes_app)
+ # dispatcher = events.EventsDispatcher(qubes_app)
- window = window_class(qt_app, qubes_app, dispatcher)
+ window = window_class(qt_app, qapp, dispatcher)
if hasattr(window, "setup_application"):
window.setup_application()
@@ -562,7 +565,7 @@ def run_synchronous(window_class):
window.show()
- qt_app.exec_()
+ qt_app.exec()
qt_app.exit()
return window
diff --git a/rpm_spec/qmgr.spec.in b/rpm_spec/qmgr.spec.in
index b287af1f..0dffa055 100644
--- a/rpm_spec/qmgr.spec.in
+++ b/rpm_spec/qmgr.spec.in
@@ -8,11 +8,7 @@ Vendor: Invisible Things Lab
License: GPL
URL: https://www.qubes-os.org
Requires: python%{python3_pkgversion}
-%if 0%{?fedora} >= 34
-Requires: python%{python3_pkgversion}-qt5
-%else
-Requires: python%{python3_pkgversion}-PyQt5
-%endif
+Requires: python%{python3_pkgversion}-pyqt6
Requires: python%{python3_pkgversion}-inotify
Requires: python%{python3_pkgversion}-qubesadmin >= 4.1.18
Requires: python%{python3_pkgversion}-qasync
@@ -21,16 +17,16 @@ Requires: qubes-artwork
Requires: pmount
Requires: cryptsetup
Requires: wmctrl
-BuildRequires: python%{python3_pkgversion}-PyQt5-devel
+BuildRequires: python%{python3_pkgversion}-PyQt6-devel
BuildRequires: python%{python3_pkgversion}-devel
BuildRequires: python%{python3_pkgversion}-setuptools
BuildRequires: make
%if 0%{?fedora} >= 33 || 0%{?rhel} >= 7
-BuildRequires: qt5-qtbase-devel
+BuildRequires: qt6-qtbase-devel
%else
-BuildRequires: qt5-devel
+BuildRequires: qt6-devel
%endif
-BuildRequires: qt5-linguist
+BuildRequires: qt6-linguist
AutoReq: 0
Source0: %{name}-%{version}.tar.gz
diff --git a/ui/backupdlg.ui b/ui/backupdlg.ui
index d8d737fc..4b8402e8 100644
--- a/ui/backupdlg.ui
+++ b/ui/backupdlg.ui
@@ -378,11 +378,14 @@
-
-
-<html><head><meta name="qrichtext" content="1" /><style type="text/css">
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
+<html><head><meta name="qrichtext" content="1" /><meta charset="utf-8" /><style type="text/css">
p, li { white-space: pre-wrap; }
-</style></head><body style=" font-family:'Cantarell'; font-size:11pt; font-weight:400; font-style:normal;">
-<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p></body></html>
+hr { height: 1px; border-width: 0; }
+li.unchecked::marker { content: "\2610"; }
+li.checked::marker { content: "\2612"; }
+</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;">
+<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html>
diff --git a/ui/clonevmdlg.ui b/ui/clonevmdlg.ui
index 6a9d64b3..38266b4c 100644
--- a/ui/clonevmdlg.ui
+++ b/ui/clonevmdlg.ui
@@ -14,8 +14,7 @@
Clone qube
-
- ..
+
-
diff --git a/ui/newappvmdlg.ui b/ui/newappvmdlg.ui
index fc2c8b6f..6b2cd679 100644
--- a/ui/newappvmdlg.ui
+++ b/ui/newappvmdlg.ui
@@ -14,8 +14,7 @@
Create new qube
-
- ..
+
-
diff --git a/ui/qubemanager.ui b/ui/qubemanager.ui
index f91c8246..1da413e1 100644
--- a/ui/qubemanager.ui
+++ b/ui/qubemanager.ui
@@ -23,8 +23,7 @@
Qube Manager
-
- ..
+
@@ -388,7 +387,7 @@ template
Network
-
+
:/netvm.png:/netvm.png
@@ -801,8 +800,7 @@ template
-
- ..
+
&Qubes OS
@@ -986,7 +984,7 @@ template
-
+
:/log.png:/log.png
diff --git a/ui/qvmtemplate.ui b/ui/qvmtemplate.ui
index 79554482..cc48c59d 100644
--- a/ui/qvmtemplate.ui
+++ b/ui/qvmtemplate.ui
@@ -92,8 +92,7 @@
-
- ..
+
Refresh
@@ -101,8 +100,7 @@
-
- ..
+
Apply
diff --git a/ui/restoredlg.ui b/ui/restoredlg.ui
index bba923d7..03dcf3c6 100644
--- a/ui/restoredlg.ui
+++ b/ui/restoredlg.ui
@@ -225,11 +225,14 @@
-
-
-<html><head><meta name="qrichtext" content="1" /><style type="text/css">
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
+<html><head><meta name="qrichtext" content="1" /><meta charset="utf-8" /><style type="text/css">
p, li { white-space: pre-wrap; }
-</style></head><body style=" font-family:'Cantarell'; font-size:11pt; font-weight:400; font-style:normal;">
-<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p></body></html>
+hr { height: 1px; border-width: 0; }
+li.unchecked::marker { content: "\2610"; }
+li.checked::marker { content: "\2612"; }
+</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;">
+<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html>
diff --git a/ui/templatemanager.ui b/ui/templatemanager.ui
index 881bd21f..b50b18e8 100644
--- a/ui/templatemanager.ui
+++ b/ui/templatemanager.ui
@@ -46,12 +46,12 @@
false
-
- 20
-
4
+
+ 20
+
true
diff --git a/ui/templatemanger2.ui b/ui/templatemanger2.ui
index ecd98f35..1625857a 100644
--- a/ui/templatemanger2.ui
+++ b/ui/templatemanger2.ui
@@ -180,8 +180,7 @@
-
- ..
+
Repository settings
@@ -204,8 +203,7 @@
-
- ..
+
Help